diff --git a/controllers/backend_admin_user.go b/controllers/backend_admin_user.go new file mode 100644 index 0000000..ab9afc5 --- /dev/null +++ b/controllers/backend_admin_user.go @@ -0,0 +1,96 @@ +package controllers + +import ( + "strconv" + + "server/models" + "server/services" + + beego "github.com/beego/beego/v2/server/web" +) + +type BackendAdminUserController struct { + beego.Controller +} + +type backendUserInfoDTO struct { + ID uint64 `json:"id"` + Tid uint64 `json:"tid"` + Uid uint64 `json:"uid"` + Account *string `json:"account"` + Name *string `json:"name"` + Phone *string `json:"phone"` + Email *string `json:"email"` + Status int8 `json:"status"` + CreateTime string `json:"create_time"` + TenantName string `json:"tenant_name"` + TenantCode string `json:"tenant_code"` +} + +// GetUserInfo 获取当前登录租户用户的详情 +// GET /backend/getUserInfo +func (c *BackendAdminUserController) GetUserInfo() { + var uid uint64 + var tid uint64 + + data := c.Ctx.Input.Data() + if jwtUid := data["uid"]; jwtUid != nil { + uid = jwtUid.(uint64) + } + if jwtTid := data["tid"]; jwtTid != nil { + tid = jwtTid.(uint64) + } + + if uid == 0 { + idStr := c.Ctx.Input.Param(":id") + uid, _ = strconv.ParseUint(idStr, 10, 64) + } + + if uid == 0 { + c.Data["json"] = map[string]interface{}{"code": 401, "msg": "未登录或非法请求"} + _ = c.ServeJSON() + return + } + + var u *models.SystemTenantUser + var err error + + if tid > 0 { + u, err = services.GetTenantUserByUidAndTid(uid, tid) + } else { + u, err = services.GetTenantUserByUid(uid) + } + + if err != nil || u == nil { + c.Data["json"] = map[string]interface{}{"code": 404, "msg": "后台用户信息不存在"} + _ = c.ServeJSON() + return + } + + tenant, err := services.GetTenantByID(u.Tid) + tenantName := "未知租户" + tenantCode := "" + if err == nil && tenant != nil { + tenantName = tenant.TenantName + tenantCode = tenant.TenantCode + } + + c.Data["json"] = map[string]interface{}{ + "code": 200, + "msg": "success", + "data": backendUserInfoDTO{ + ID: u.ID, + Tid: u.Tid, + Uid: u.Uid, + Account: u.Account, + Name: u.Name, + Phone: u.Phone, + Email: u.Email, + Status: u.Status, + CreateTime: u.CreateTime.Format("2006-01-02 15:04:05"), + TenantName: tenantName, + TenantCode: tenantCode, + }, + } + _ = c.ServeJSON() +} diff --git a/controllers/backend_menu.go b/controllers/backend_menu.go index 1abd550..21cca8f 100644 --- a/controllers/backend_menu.go +++ b/controllers/backend_menu.go @@ -2,7 +2,6 @@ package controllers import ( "encoding/json" - "io" "server/models" "strconv" "strings" @@ -10,11 +9,12 @@ import ( beego "github.com/beego/beego/v2/server/web" ) -// AdminMenuController 后台菜单控制器 -type AdminMenuController struct { +type BackendMenuController struct { beego.Controller } +type AdminMenuController = BackendMenuController + type menuPayload struct { Pid *int64 `json:"pid"` Title *string `json:"title"` @@ -30,15 +30,11 @@ type menuPayload struct { } func parseViews(raw *string) []int { - if raw == nil { - return nil - } - s := strings.TrimSpace(*raw) - if s == "" { + if raw == nil || strings.TrimSpace(*raw) == "" { return nil } var arr []int - if err := json.Unmarshal([]byte(s), &arr); err != nil { + if err := json.Unmarshal([]byte(*raw), &arr); err != nil { return nil } return arr @@ -53,21 +49,10 @@ func hasView(arr []int, v int) bool { return false } -func viewsJSON(views []int) string { - // 默认:平台端显示 - if len(views) == 0 { - views = []int{1} - } - b, _ := json.Marshal(views) - return string(b) -} - func filterMenusByView(menus []models.SystemMenu, v int) []models.SystemMenu { out := make([]models.SystemMenu, 0, len(menus)) for _, m := range menus { views := parseViews(m.Views) - // 兼容旧数据:views 为空时,平台端菜单默认可见(保持旧 is_platform=1 的常见默认体验) - // 租户端不做默认放行,避免把未迁移数据误暴露到租户端。 if v == 1 && len(views) == 0 { out = append(out, m) continue @@ -79,87 +64,63 @@ func filterMenusByView(menus []models.SystemMenu, v int) []models.SystemMenu { return out } -// GetMenu 获取指定用户可见的菜单列表(简化版:当前先忽略用户权限,返回全部启用且平台端菜单) -// 路由示例:GET /platform/menu/1 -func (c *AdminMenuController) GetMenu() { - // 从路由参数中解析用户 ID,占位保留,方便后续按用户权限过滤 - _ = c.Ctx.Input.Param(":id") - - // 查询所有启用菜单,再按 views 过滤平台端可见 +func (c *BackendMenuController) GetMenu() { var menus []models.SystemMenu - qs := models.Orm. - QueryTable(new(models.SystemMenu)). - Filter("status", 1) - _, err := qs.All(&menus) + _, err := models.Orm.QueryTable(new(models.SystemMenu)).Filter("status", 1).All(&menus) if err != nil { - c.Data["json"] = map[string]interface{}{ - "code": 500, - "msg": "获取菜单失败: " + err.Error(), - "data": nil, - } + c.Data["json"] = map[string]interface{}{"code": 500, "msg": "获取菜单失败: " + err.Error(), "data": nil} _ = c.ServeJSON() return } - menus = filterMenusByView(menus, 1) + c.Data["json"] = map[string]interface{}{"code": 200, "msg": "success", "data": buildMenuTree(filterMenusByView(menus, 1), 0)} + _ = c.ServeJSON() +} - // 将平铺的菜单列表构建为树形结构 - menuTree := buildMenuTree(menus, 0) +func (c *BackendMenuController) GetBackendMenu() { + var menus []models.SystemMenu + _, err := models.Orm.QueryTable(new(models.SystemMenu)).Filter("status", 1).All(&menus) + if err != nil { + c.Data["json"] = map[string]interface{}{"code": 500, "msg": "获取菜单失败: " + err.Error(), "data": nil} + _ = c.ServeJSON() + return + } + c.Data["json"] = map[string]interface{}{"code": 200, "msg": "success", "data": buildMenuTree(filterMenusByView(menus, 2), 0)} + _ = c.ServeJSON() +} +func (c *BackendMenuController) GetTenantList() { + var tid uint64 + if jwtTid := c.Ctx.Input.GetData("tid"); jwtTid != nil { + tid = jwtTid.(uint64) + } + if tid == 0 { + c.Data["json"] = map[string]interface{}{"code": 401, "msg": "未登录或非法请求"} + _ = c.ServeJSON() + return + } + + var menus []models.SystemMenu + if _, err := models.Orm.QueryTable(new(models.SystemMenu)).Filter("status", 1).All(&menus); err != nil { + c.Data["json"] = map[string]interface{}{"code": 500, "msg": "获取失败:" + err.Error()} + _ = c.ServeJSON() + return + } + + tree := buildMenuTree(filterMenusByView(menus, 2), 0) c.Data["json"] = map[string]interface{}{ "code": 200, - "msg": "success", - "data": menuTree, + "msg": "获取成功", + "data": map[string]interface{}{"list": tree, "total": len(tree)}, } _ = c.ServeJSON() } -// GetBackendMenu 获取租户端用户可见的菜单列表(简化版:当前先忽略用户权限,返回全部启用且租户端菜单) -// 路由示例:GET /backend/menu/1 -func (c *AdminMenuController) GetBackendMenu() { - // 从路由参数中解析用户 ID,占位保留,方便后续按用户权限过滤 - _ = c.Ctx.Input.Param(":id") - - var menus []models.SystemMenu - qs := models.Orm. - QueryTable(new(models.SystemMenu)). - Filter("status", 1) - _, err := qs.All(&menus) - if err != nil { - c.Data["json"] = map[string]interface{}{ - "code": 500, - "msg": "获取菜单失败: " + err.Error(), - "data": nil, - } - _ = c.ServeJSON() - return - } - menus = filterMenusByView(menus, 2) - - menuTree := buildMenuTree(menus, 0) - c.Data["json"] = map[string]interface{}{ - "code": 200, - "msg": "success", - "data": menuTree, - } - _ = c.ServeJSON() -} - -// GetAllMenus 获取平台端全部菜单(用于菜单管理界面) -// 路由:GET /platform/allmenu -func (c *AdminMenuController) GetAllMenus() { +func (c *BackendMenuController) GetAllMenus() { var menus []models.SystemMenu cid, _ := c.GetInt("cid") - qs := models.Orm.QueryTable(new(models.SystemMenu)) - // 菜单管理默认返回全量菜单;仅在明确传 cid 时按分类筛选 - // cid: 1平台角色 -> 平台菜单;2租户角色 -> 租户菜单 - _, err := qs.All(&menus) - if err != nil { - c.Data["json"] = map[string]interface{}{ - "code": 500, - "msg": "获取菜单失败: " + err.Error(), - "data": nil, - } + if _, err := models.Orm.QueryTable(new(models.SystemMenu)).All(&menus); err != nil { + c.Data["json"] = map[string]interface{}{"code": 500, "msg": "获取菜单失败: " + err.Error(), "data": nil} _ = c.ServeJSON() return } @@ -169,42 +130,21 @@ func (c *AdminMenuController) GetAllMenus() { menus = filterMenusByView(menus, 2) } - tree := buildMenuTree(menus, 0) - - c.Data["json"] = map[string]interface{}{ - "code": 200, - "msg": "success", - "data": tree, - } + c.Data["json"] = map[string]interface{}{"code": 200, "msg": "success", "data": buildMenuTree(menus, 0)} _ = c.ServeJSON() } -// GetAllBackendMenus 获取租户端全部菜单(用于菜单管理界面) -// 路由:GET /backend/allmenu -func (c *AdminMenuController) GetAllBackendMenus() { +func (c *BackendMenuController) GetAllBackendMenus() { var menus []models.SystemMenu - _, err := models.Orm.QueryTable(new(models.SystemMenu)). - All(&menus) - if err != nil { - c.Data["json"] = map[string]interface{}{ - "code": 500, - "msg": "获取菜单失败: " + err.Error(), - "data": nil, - } + if _, err := models.Orm.QueryTable(new(models.SystemMenu)).All(&menus); err != nil { + c.Data["json"] = map[string]interface{}{"code": 500, "msg": "获取菜单失败: " + err.Error(), "data": nil} _ = c.ServeJSON() return } - menus = filterMenusByView(menus, 2) - tree := buildMenuTree(menus, 0) - c.Data["json"] = map[string]interface{}{ - "code": 200, - "msg": "success", - "data": tree, - } + c.Data["json"] = map[string]interface{}{"code": 200, "msg": "success", "data": buildMenuTree(filterMenusByView(menus, 2), 0)} _ = c.ServeJSON() } -// menuNode 用于 JSON 返回的菜单结构 type menuNode struct { ID uint64 `json:"id"` Pid int64 `json:"pid"` @@ -221,20 +161,19 @@ type menuNode struct { Children []*menuNode `json:"children,omitempty"` } -// buildMenuTree 将菜单列表构建成树结构 func buildMenuTree(menus []models.SystemMenu, pid int64) []*menuNode { var tree []*menuNode for _, m := range menus { if m.Pid == pid { node := &menuNode{ - ID: m.ID, - Pid: m.Pid, - Title: m.Title, - Sort: m.Sort, - Status: m.Status, - IsVisible: m.IsVisible, - Views: parseViews(m.Views), - Type: m.Type, + ID: m.ID, + Pid: m.Pid, + Title: m.Title, + Sort: m.Sort, + Status: m.Status, + IsVisible: m.IsVisible, + Views: parseViews(m.Views), + Type: m.Type, } if m.Path != nil { node.Path = *m.Path @@ -248,10 +187,7 @@ func buildMenuTree(menus []models.SystemMenu, pid int64) []*menuNode { if m.Permission != nil { node.Permission = *m.Permission } - - // 递归查找子菜单 - children := buildMenuTree(menus, int64(m.ID)) - if len(children) > 0 { + if children := buildMenuTree(menus, int64(m.ID)); len(children) > 0 { node.Children = children } tree = append(tree, node) @@ -260,9 +196,7 @@ func buildMenuTree(menus []models.SystemMenu, pid int64) []*menuNode { return tree } -// UpdateMenuStatus 更新菜单状态 -// 路由:PATCH /platform/menu/status/:id -func (c *AdminMenuController) UpdateMenuStatus() { +func (c *BackendMenuController) UpdateMenuStatus() { id, err := strconv.ParseUint(c.Ctx.Input.Param(":id"), 10, 64) if err != nil || id == 0 { c.Data["json"] = map[string]interface{}{"code": 400, "msg": "无效菜单ID"} @@ -273,48 +207,49 @@ func (c *AdminMenuController) UpdateMenuStatus() { var body struct { Status *int8 `json:"status"` } - rawBody, _ := io.ReadAll(c.Ctx.Request.Body) - if err := json.Unmarshal(rawBody, &body); err != nil || body.Status == nil { + if err := json.Unmarshal(c.Ctx.Input.RequestBody, &body); err != nil || body.Status == nil { c.Data["json"] = map[string]interface{}{"code": 400, "msg": "参数错误"} _ = c.ServeJSON() return } - _, err = models.Orm.QueryTable(new(models.SystemMenu)). - Filter("id", id). - Update(map[string]interface{}{"status": *body.Status}) - if err != nil { + if _, err = models.Orm.QueryTable(new(models.SystemMenu)).Filter("id", id).Update(map[string]interface{}{"status": *body.Status}); err != nil { c.Data["json"] = map[string]interface{}{"code": 500, "msg": "更新失败: " + err.Error()} _ = c.ServeJSON() return } - c.Data["json"] = map[string]interface{}{"code": 200, "msg": "success", "success": true} _ = c.ServeJSON() } -// CreateMenu 创建菜单 -// 路由:POST /platform/createmenu -func (c *AdminMenuController) CreateMenu() { +func (c *BackendMenuController) CreateMenu() { payload, ok := c.parseMenuPayload(true) if !ok { return } - menu := models.SystemMenu{ - Pid: valueInt64(payload.Pid, 0), - Title: strings.TrimSpace(valueString(payload.Title, "")), - Sort: valueInt64(payload.Sort, 0), - Status: valueInt8(payload.Status, 1), - IsVisible: ptrInt8(valueInt8(payload.IsVisible, 1)), - Views: ptrString(viewsJSON(payload.Views)), - Type: valueInt8(payload.Type, 1), + var viewsStr string + views := payload.Views + if len(views) == 0 { + views = []int{1} + } + if b, err := json.Marshal(views); err == nil { + viewsStr = string(b) } - menu.Path = ptrString(valueString(payload.Path, "")) - menu.ComponentPath = ptrString(valueString(payload.ComponentPath, "")) - menu.Icon = ptrString(valueString(payload.Icon, "")) - menu.Permission = ptrString(valueString(payload.Permission, "")) + menu := models.SystemMenu{ + Pid: valueInt64(payload.Pid, 0), + Title: strings.TrimSpace(valueString(payload.Title, "")), + Sort: valueInt64(payload.Sort, 0), + Status: valueInt8(payload.Status, 1), + IsVisible: ptrInt8(valueInt8(payload.IsVisible, 1)), + Views: &viewsStr, + Type: valueInt8(payload.Type, 1), + Path: ptrString(valueString(payload.Path, "")), + ComponentPath: ptrString(valueString(payload.ComponentPath, "")), + Icon: ptrString(valueString(payload.Icon, "")), + Permission: ptrString(valueString(payload.Permission, "")), + } id, err := models.Orm.Insert(&menu) if err != nil { @@ -322,18 +257,11 @@ func (c *AdminMenuController) CreateMenu() { _ = c.ServeJSON() return } - - c.Data["json"] = map[string]interface{}{ - "code": 200, - "msg": "创建成功", - "data": map[string]interface{}{"id": id}, - } + c.Data["json"] = map[string]interface{}{"code": 200, "msg": "创建成功", "data": map[string]interface{}{"id": id}} _ = c.ServeJSON() } -// UpdateMenu 更新菜单 -// 路由:PUT /platform/updatemenu/:id -func (c *AdminMenuController) UpdateMenu() { +func (c *BackendMenuController) UpdateMenu() { id, err := strconv.ParseUint(c.Ctx.Input.Param(":id"), 10, 64) if err != nil || id == 0 { c.Data["json"] = map[string]interface{}{"code": 400, "msg": "无效菜单ID"} @@ -346,6 +274,12 @@ func (c *AdminMenuController) UpdateMenu() { return } + views := payload.Views + if len(views) == 0 { + views = []int{1} + } + viewsBytes, _ := json.Marshal(views) + update := map[string]interface{}{ "pid": valueInt64(payload.Pid, 0), "title": strings.TrimSpace(valueString(payload.Title, "")), @@ -355,27 +289,21 @@ func (c *AdminMenuController) UpdateMenu() { "sort": valueInt64(payload.Sort, 0), "status": valueInt8(payload.Status, 1), "is_visible": valueInt8(payload.IsVisible, 1), - "views": viewsJSON(payload.Views), + "views": string(viewsBytes), "type": valueInt8(payload.Type, 1), "permission": valueString(payload.Permission, ""), } - _, err = models.Orm.QueryTable(new(models.SystemMenu)). - Filter("id", id). - Update(update) - if err != nil { + if _, err = models.Orm.QueryTable(new(models.SystemMenu)).Filter("id", id).Update(update); err != nil { c.Data["json"] = map[string]interface{}{"code": 500, "msg": "更新失败: " + err.Error()} _ = c.ServeJSON() return } - c.Data["json"] = map[string]interface{}{"code": 200, "msg": "更新成功"} _ = c.ServeJSON() } -// DeleteMenu 删除菜单 -// 路由:DELETE /platform/deletemenu/:id -func (c *AdminMenuController) DeleteMenu() { +func (c *BackendMenuController) DeleteMenu() { id, err := strconv.ParseUint(c.Ctx.Input.Param(":id"), 10, 64) if err != nil || id == 0 { c.Data["json"] = map[string]interface{}{"code": 400, "msg": "无效菜单ID"} @@ -383,21 +311,18 @@ func (c *AdminMenuController) DeleteMenu() { return } - _, err = models.Orm.QueryTable(new(models.SystemMenu)).Filter("id", id).Delete() - if err != nil { + if _, err = models.Orm.QueryTable(new(models.SystemMenu)).Filter("id", id).Delete(); err != nil { c.Data["json"] = map[string]interface{}{"code": 500, "msg": "删除失败: " + err.Error()} _ = c.ServeJSON() return } - c.Data["json"] = map[string]interface{}{"code": 200, "msg": "删除成功", "success": true} _ = c.ServeJSON() } -func (c *AdminMenuController) parseMenuPayload(needTitle bool) (*menuPayload, bool) { - rawBody, _ := io.ReadAll(c.Ctx.Request.Body) +func (c *BackendMenuController) parseMenuPayload(needTitle bool) (*menuPayload, bool) { var payload menuPayload - if err := json.Unmarshal(rawBody, &payload); err != nil { + if err := json.Unmarshal(c.Ctx.Input.RequestBody, &payload); err != nil { c.Data["json"] = map[string]interface{}{"code": 400, "msg": "参数错误"} _ = c.ServeJSON() return nil, false @@ -431,11 +356,5 @@ func valueInt64(v *int64, def int64) int64 { return *v } -func ptrString(v string) *string { - return &v -} - -func ptrInt8(v int8) *int8 { - return &v -} - +func ptrString(v string) *string { return &v } +func ptrInt8(v int8) *int8 { return &v } diff --git a/controllers/platform_tenant.go b/controllers/platform_tenant.go index ef57026..e0958c0 100644 --- a/controllers/platform_tenant.go +++ b/controllers/platform_tenant.go @@ -12,7 +12,7 @@ import ( beego "github.com/beego/beego/v2/server/web" ) -// PlatformTenantController 平台端租户管理 +// PlatformTenantController 平台端租户管ç? type PlatformTenantController struct { beego.Controller } @@ -33,27 +33,38 @@ type tenantDTO struct { DeleteTime *time.Time `json:"delete_time,omitempty"` } -func toTenantDTO(t models.Tenant) tenantDTO { +func stringValue(s *string) string { + if s == nil { + return "" + } + return *s +} + +func stringPtr(s string) *string { + return &s +} + +func toTenantDTO(t models.SystemTenant) tenantDTO { ct := t.CreateTime ut := t.UpdateTime return tenantDTO{ ID: t.ID, TenantCode: t.TenantCode, TenantName: t.TenantName, - ContactPerson: t.ContactPerson, - ContactPhone: t.ContactPhone, - ContactEmail: t.ContactEmail, - Address: t.Address, - Worktime: t.Worktime, + ContactPerson: stringValue(t.ContactPerson), + ContactPhone: stringValue(t.ContactPhone), + ContactEmail: stringValue(t.ContactEmail), + Address: stringValue(t.Address), + Worktime: stringValue(t.Worktime), Status: t.Status, - Remark: t.Remark, + Remark: stringValue(t.Remark), CreateTime: &ct, UpdateTime: &ut, DeleteTime: t.DeleteTime, } } -// GetTenant 获取租户列表 +// GetTenant 获取租户列表 // GET /platform/tenant/getTenant?page=1&pageSize=10&tenant_name=...&tenant_code=...&contact_person=...&contact_phone=... func (c *PlatformTenantController) GetTenant() { page, _ := c.GetInt("page", 1) @@ -70,7 +81,7 @@ func (c *PlatformTenantController) GetTenant() { contactPerson := strings.TrimSpace(c.GetString("contact_person")) contactPhone := strings.TrimSpace(c.GetString("contact_phone")) - qs := models.Orm.QueryTable(new(models.Tenant)) + qs := models.Orm.QueryTable(new(models.SystemTenant)) if tenantName != "" { qs = qs.Filter("tenant_name__icontains", tenantName) } @@ -86,15 +97,15 @@ func (c *PlatformTenantController) GetTenant() { total, err := qs.Count() if err != nil { - c.Data["json"] = map[string]interface{}{"code": 500, "msg": "获取租户失败: " + err.Error()} + c.Data["json"] = map[string]interface{}{"code": 500, "msg": "获取租户失败: " + err.Error()} _ = c.ServeJSON() return } - var rows []models.Tenant + var rows []models.SystemTenant _, err = qs.OrderBy("-id").Limit(pageSize, (page-1)*pageSize).All(&rows) if err != nil { - c.Data["json"] = map[string]interface{}{"code": 500, "msg": "获取租户失败: " + err.Error()} + c.Data["json"] = map[string]interface{}{"code": 500, "msg": "获取租户失败: " + err.Error()} _ = c.ServeJSON() return } @@ -115,18 +126,18 @@ func (c *PlatformTenantController) GetTenant() { _ = c.ServeJSON() } -// GetTenantDetail 获取租户详情 +// GetTenantDetail čŽˇĺ–ç§ŸćˆˇčŻŚćƒ // GET /platform/tenant/getTenantDetail/:id func (c *PlatformTenantController) GetTenantDetail() { id, err := strconv.ParseUint(c.Ctx.Input.Param(":id"), 10, 64) if err != nil || id == 0 { - c.Data["json"] = map[string]interface{}{"code": 400, "msg": "无效ID"} + c.Data["json"] = map[string]interface{}{"code": 400, "msg": "无效ID"} _ = c.ServeJSON() return } - var t models.Tenant - err = models.Orm.QueryTable(new(models.Tenant)).Filter("id", id).One(&t) + var t models.SystemTenant + err = models.Orm.QueryTable(new(models.SystemTenant)).Filter("id", id).One(&t) if err != nil { c.Data["json"] = map[string]interface{}{"code": 404, "msg": "租户不存在"} _ = c.ServeJSON() @@ -154,7 +165,7 @@ type tenantPayload struct { } func (c *PlatformTenantController) parseTenantPayload() (tenantPayload, error) { - // 优先从表单读取(createTenant 使用 multipart/form-data) + // 优先从表单读取(createTenant 使用 multipart/form-dataďź? p := tenantPayload{ TenantCode: strings.TrimSpace(c.GetString("tenant_code")), TenantName: strings.TrimSpace(c.GetString("tenant_name")), @@ -172,7 +183,7 @@ func (c *PlatformTenantController) parseTenantPayload() (tenantPayload, error) { } } - // 如果关键字段为空,尝试从 JSON body 解析(editTenant 默认 JSON) + // 如果关键字段为空,尝试从 JSON body 解析(editTenant 靘莤 JSONďź? if p.TenantName == "" && p.TenantCode == "" { raw, _ := io.ReadAll(c.Ctx.Request.Body) if len(raw) > 0 { @@ -182,25 +193,25 @@ func (c *PlatformTenantController) parseTenantPayload() (tenantPayload, error) { return p, nil } -// CreateTenant 创建租户 +// CreateTenant 创建租户 // POST /platform/tenant/createTenant func (c *PlatformTenantController) CreateTenant() { p, _ := c.parseTenantPayload() if strings.TrimSpace(p.TenantName) == "" { - c.Data["json"] = map[string]interface{}{"code": 400, "msg": "租户名称不能为空"} + c.Data["json"] = map[string]interface{}{"code": 400, "msg": "租户名称不能为空"} _ = c.ServeJSON() return } if strings.TrimSpace(p.TenantCode) == "" { - c.Data["json"] = map[string]interface{}{"code": 400, "msg": "租户编码不能为空"} + c.Data["json"] = map[string]interface{}{"code": 400, "msg": "租户编码不能为空"} _ = c.ServeJSON() return } - // 校验编码唯一 - cnt, err := models.Orm.QueryTable(new(models.Tenant)).Filter("tenant_code", p.TenantCode).Count() + // 校验编码唯一 + cnt, err := models.Orm.QueryTable(new(models.SystemTenant)).Filter("tenant_code", p.TenantCode).Count() if err != nil { - c.Data["json"] = map[string]interface{}{"code": 500, "msg": "创建失败: " + err.Error()} + c.Data["json"] = map[string]interface{}{"code": 500, "msg": "创建失败: " + err.Error()} _ = c.ServeJSON() return } @@ -215,21 +226,21 @@ func (c *PlatformTenantController) CreateTenant() { status = *p.Status } - t := models.Tenant{ + t := models.SystemTenant{ TenantCode: p.TenantCode, TenantName: p.TenantName, - ContactPerson: p.ContactPerson, - ContactPhone: p.ContactPhone, - ContactEmail: p.ContactEmail, - Address: p.Address, - Worktime: p.Worktime, + ContactPerson: stringPtr(p.ContactPerson), + ContactPhone: stringPtr(p.ContactPhone), + ContactEmail: stringPtr(p.ContactEmail), + Address: stringPtr(p.Address), + Worktime: stringPtr(p.Worktime), Status: status, - Remark: p.Remark, + Remark: stringPtr(p.Remark), } id, err := models.Orm.Insert(&t) if err != nil { - c.Data["json"] = map[string]interface{}{"code": 500, "msg": "创建失败: " + err.Error()} + c.Data["json"] = map[string]interface{}{"code": 500, "msg": "创建失败: " + err.Error()} _ = c.ServeJSON() return } @@ -242,19 +253,19 @@ func (c *PlatformTenantController) CreateTenant() { _ = c.ServeJSON() } -// EditTenant 编辑租户 +// EditTenant 编辑租户 // POST /platform/tenant/editTenant/:id func (c *PlatformTenantController) EditTenant() { id, err := strconv.ParseUint(c.Ctx.Input.Param(":id"), 10, 64) if err != nil || id == 0 { - c.Data["json"] = map[string]interface{}{"code": 400, "msg": "无效ID"} + c.Data["json"] = map[string]interface{}{"code": 400, "msg": "无效ID"} _ = c.ServeJSON() return } p, _ := c.parseTenantPayload() if strings.TrimSpace(p.TenantName) == "" { - c.Data["json"] = map[string]interface{}{"code": 400, "msg": "租户名称不能为空"} + c.Data["json"] = map[string]interface{}{"code": 400, "msg": "租户名称不能为空"} _ = c.ServeJSON() return } @@ -272,9 +283,9 @@ func (c *PlatformTenantController) EditTenant() { update["status"] = *p.Status } - _, err = models.Orm.QueryTable(new(models.Tenant)).Filter("id", id).Update(update) + _, err = models.Orm.QueryTable(new(models.SystemTenant)).Filter("id", id).Update(update) if err != nil { - c.Data["json"] = map[string]interface{}{"code": 500, "msg": "更新失败: " + err.Error()} + c.Data["json"] = map[string]interface{}{"code": 500, "msg": "更新失败: " + err.Error()} _ = c.ServeJSON() return } @@ -283,19 +294,19 @@ func (c *PlatformTenantController) EditTenant() { _ = c.ServeJSON() } -// DeleteTenant 删除租户 +// DeleteTenant 删除租户 // DELETE /platform/tenant/deleteTenant/:id func (c *PlatformTenantController) DeleteTenant() { id, err := strconv.ParseUint(c.Ctx.Input.Param(":id"), 10, 64) if err != nil || id == 0 { - c.Data["json"] = map[string]interface{}{"code": 400, "msg": "无效ID"} + c.Data["json"] = map[string]interface{}{"code": 400, "msg": "无效ID"} _ = c.ServeJSON() return } - _, err = models.Orm.QueryTable(new(models.Tenant)).Filter("id", id).Delete() + _, err = models.Orm.QueryTable(new(models.SystemTenant)).Filter("id", id).Delete() if err != nil { - c.Data["json"] = map[string]interface{}{"code": 500, "msg": "删除失败: " + err.Error()} + c.Data["json"] = map[string]interface{}{"code": 500, "msg": "删除失败: " + err.Error()} _ = c.ServeJSON() return } @@ -304,20 +315,20 @@ func (c *PlatformTenantController) DeleteTenant() { _ = c.ServeJSON() } -// FindTenantCode 校验租户编码是否重复 +// FindTenantCode 校验租户编码是否重复 // GET /platform/tenant/findTenantCode?tenant_code=xxxxxx -// 返回 code=200 表示可用;非200表示重复/不可用(前端会自动重新生成) +// 返回 code=200 表示可用;非200表示重复/不可用(前端会自动重新生成) func (c *PlatformTenantController) FindTenantCode() { code := strings.TrimSpace(c.GetString("tenant_code")) if code == "" { - c.Data["json"] = map[string]interface{}{"code": 400, "msg": "tenant_code 不能为空"} + c.Data["json"] = map[string]interface{}{"code": 400, "msg": "tenant_code 不能为空"} _ = c.ServeJSON() return } - cnt, err := models.Orm.QueryTable(new(models.Tenant)).Filter("tenant_code", code).Count() + cnt, err := models.Orm.QueryTable(new(models.SystemTenant)).Filter("tenant_code", code).Count() if err != nil { - c.Data["json"] = map[string]interface{}{"code": 500, "msg": "校验失败: " + err.Error()} + c.Data["json"] = map[string]interface{}{"code": 500, "msg": "校验失败: " + err.Error()} _ = c.ServeJSON() return } @@ -330,4 +341,3 @@ func (c *PlatformTenantController) FindTenantCode() { c.Data["json"] = map[string]interface{}{"code": 200, "msg": "ok"} _ = c.ServeJSON() } - diff --git a/controllers/platform_tenant_user.go b/controllers/platform_tenant_user.go index e56e2b2..9dca893 100644 --- a/controllers/platform_tenant_user.go +++ b/controllers/platform_tenant_user.go @@ -17,7 +17,7 @@ import ( beego "github.com/beego/beego/v2/server/web" ) -// PlatformTenantUserController 平台端租户-用户绑定管理 +// PlatformTenantUserController 平台租户用户绑定管理 type PlatformTenantUserController struct { beego.Controller } @@ -35,14 +35,14 @@ type tenantUserPayload struct { Remark *string `json:"remark"` } -// GetTenantUserList 获取绑定列表(支持按 tid / uid 过滤;keyword 对姓名/手机/邮箱/账号模糊 OR 匹配) -// GET /platform/tenantUser/list?tid=1&uid=2&keyword=张 +// GetTenantUserList 获取绑定列表(支持按 tid / uid 过滤,keyword 对姓名/手机/邮箱/账号模糊匹配) +// GET /platform/tenantUser/list?tid=1&uid=2&keyword=xxx func (c *PlatformTenantUserController) GetTenantUserList() { tid, _ := c.GetUint64("tid") uid, _ := c.GetUint64("uid") keyword := strings.TrimSpace(c.GetString("keyword")) - qs := models.Orm.QueryTable(new(models.TenantUser)) + qs := models.Orm.QueryTable(new(models.SystemTenantUser)) var cond *orm.Condition needCond := false @@ -77,7 +77,7 @@ func (c *PlatformTenantUserController) GetTenantUserList() { qs = qs.SetCond(cond) } - var rows []models.TenantUser + var rows []models.SystemTenantUser _, err := qs.OrderBy("-is_default", "-id").All(&rows) if err != nil { c.Data["json"] = map[string]interface{}{"code": 500, "msg": "查询失败: " + err.Error()} @@ -96,7 +96,7 @@ func (c *PlatformTenantUserController) GetTenantUserList() { _ = c.ServeJSON() } -// GetTenantUsersByTid 兼容路径参数方式获取租户用户列表 +// GetTenantUsersByTid 兼容旧路由,根据租户 ID 获取租户用户列表 // GET /platform/getTenantUsers/:tid func (c *PlatformTenantUserController) GetTenantUsersByTid() { tidStr := c.Ctx.Input.Param(":tid") @@ -106,8 +106,8 @@ func (c *PlatformTenantUserController) GetTenantUsersByTid() { _ = c.ServeJSON() return } - var rows []models.TenantUser - _, err := models.Orm.QueryTable(new(models.TenantUser)). + var rows []models.SystemTenantUser + _, err := models.Orm.QueryTable(new(models.SystemTenantUser)). Filter("tid", tid). OrderBy("-is_default", "-id"). All(&rows) @@ -134,8 +134,8 @@ func (c *PlatformTenantUserController) GetTenantUserDetail() { return } - var row models.TenantUser - err = models.Orm.QueryTable(new(models.TenantUser)).Filter("id", id).One(&row) + var row models.SystemTenantUser + err = models.Orm.QueryTable(new(models.SystemTenantUser)).Filter("id", id).One(&row) if err != nil { c.Data["json"] = map[string]interface{}{"code": 404, "msg": "记录不存在"} _ = c.ServeJSON() @@ -146,7 +146,7 @@ func (c *PlatformTenantUserController) GetTenantUserDetail() { _ = c.ServeJSON() } -// CreateTenantUser 创建租户用户绑定(写入表 yz_system_tenant_user;uid 为空时由 generateTenantUID 生成) +// CreateTenantUser 创建租户用户绑定(写入 yz_system_tenant_user;uid 为空时自动生成) // POST /platform/tenantUser/create func (c *PlatformTenantUserController) CreateTenantUser() { p, ok := c.parsePayload() @@ -267,7 +267,7 @@ func (c *PlatformTenantUserController) EditTenantUser() { return } - _, err = models.Orm.QueryTable(new(models.TenantUser)).Filter("id", id).Update(update) + _, err = models.Orm.QueryTable(new(models.SystemTenantUser)).Filter("id", id).Update(update) if err != nil { c.Data["json"] = map[string]interface{}{"code": 500, "msg": "更新失败: " + err.Error()} _ = c.ServeJSON() @@ -317,7 +317,7 @@ func generateTenantUID(tid uint64) (uint64, error) { rand.Seed(time.Now().UnixNano()) for i := 0; i < 8; i++ { uid := uint64(10000000 + rand.Intn(90000000)) - cnt, err := models.Orm.QueryTable(new(models.TenantUser)). + cnt, err := models.Orm.QueryTable(new(models.SystemTenantUser)). Filter("tid", tid). Filter("uid", uid). Count() diff --git a/models/init.go b/models/init.go index 0f78f16..45bb3a8 100644 --- a/models/init.go +++ b/models/init.go @@ -33,8 +33,8 @@ func Init(_ string) { // 注册模型 orm.RegisterModel( - new(Tenant), - new(TenantUser), + new(SystemTenant), + new(SystemTenantUser), new(BackendErpOrganization), new(BackendErpEmployee), new(BackendErpPosition), diff --git a/models/system_tenant.go b/models/system_tenant.go new file mode 100644 index 0000000..8a22f94 --- /dev/null +++ b/models/system_tenant.go @@ -0,0 +1,23 @@ +package models + +import "time" + +type SystemTenant struct { + ID uint64 `orm:"column(id);pk;auto" json:"id"` + TenantCode string `orm:"column(tenant_code);size(32)" json:"tenant_code"` + TenantName string `orm:"column(tenant_name);size(128)" json:"tenant_name"` + ContactPerson *string `orm:"column(contact_person);size(64);null" json:"contact_person"` + ContactPhone *string `orm:"column(contact_phone);size(20);null" json:"contact_phone"` + ContactEmail *string `orm:"column(contact_email);size(128);null" json:"contact_email"` + Address *string `orm:"column(address);size(255);null" json:"address"` + Worktime *string `orm:"column(worktime);size(255);null" json:"worktime"` + Status int8 `orm:"column(status);default(1)" json:"status"` + Remark *string `orm:"column(remark);size(512);null" json:"remark"` + CreateTime time.Time `orm:"column(create_time);auto_now_add;type(datetime)" json:"create_time"` + UpdateTime time.Time `orm:"column(update_time);auto_now;type(datetime)" json:"update_time"` + DeleteTime *time.Time `orm:"column(delete_time);type(datetime);null" json:"delete_time"` +} + +func (m *SystemTenant) TableName() string { + return "yz_system_tenant" +} diff --git a/models/tenant_user.go b/models/system_tenant_user.go similarity index 59% rename from models/tenant_user.go rename to models/system_tenant_user.go index d0f1a8b..b382628 100644 --- a/models/tenant_user.go +++ b/models/system_tenant_user.go @@ -2,25 +2,23 @@ package models import "time" -// TenantUser 租户用户绑定关系表 yz_system_tenant_user -type TenantUser struct { +type SystemTenantUser struct { ID uint64 `orm:"column(id);pk;auto" json:"id"` - Tid uint64 `orm:"column(tid)" json:"tid"` // 租户ID - Uid uint64 `orm:"column(uid)" json:"uid"` // 用户ID - Account *string `orm:"column(account);size(64);null" json:"account"` // 用户账号(冗余) - Name *string `orm:"column(name);size(64);null" json:"name"` // 用户名称(冗余) - Phone *string `orm:"column(phone);size(20);null" json:"phone"` // 手机号(冗余) - Email *string `orm:"column(email);size(128);null" json:"email"` // 邮箱(冗余) - Password *string `orm:"column(password);size(255);null" json:"password"` // 密码(冗余/可选) - IsDefault int8 `orm:"column(is_default);default(0)" json:"is_default"` // 是否默认租户 - Status int8 `orm:"column(status);default(1)" json:"status"` // 状态:1启用,0禁用 + Tid uint64 `orm:"column(tid)" json:"tid"` + Uid uint64 `orm:"column(uid)" json:"uid"` + Account *string `orm:"column(account);size(64);null" json:"account"` + Name *string `orm:"column(name);size(64);null" json:"name"` + Phone *string `orm:"column(phone);size(20);null" json:"phone"` + Email *string `orm:"column(email);size(128);null" json:"email"` + Password *string `orm:"column(password);size(255);null" json:"password"` + IsDefault int8 `orm:"column(is_default);default(0)" json:"is_default"` + Status int8 `orm:"column(status);default(1)" json:"status"` Remark *string `orm:"column(remark);size(255);null" json:"remark"` CreateTime time.Time `orm:"column(create_time);auto_now_add;type(datetime)" json:"create_time"` UpdateTime *time.Time `orm:"column(update_time);auto_now;type(datetime);null" json:"update_time"` DeleteTime *time.Time `orm:"column(delete_time);type(datetime);null" json:"delete_time"` } -// TableName 自定义表名 -func (m *TenantUser) TableName() string { +func (m *SystemTenantUser) TableName() string { return "yz_system_tenant_user" } diff --git a/models/tenant.go b/models/tenant.go deleted file mode 100644 index a78289f..0000000 --- a/models/tenant.go +++ /dev/null @@ -1,25 +0,0 @@ -package models - -import "time" - -// Tenant 租户表 yz_system_tenant -type Tenant struct { - ID uint64 `orm:"column(id);pk;auto" json:"id"` // 租户唯一标识(主键) - TenantCode string `orm:"column(tenant_code);size(32);unique" json:"tenantCode"` // 租户编码 - TenantName string `orm:"column(tenant_name);size(128)" json:"tenantName"` // 租户名称 - ContactPerson string `orm:"column(contact_person);size(64);null" json:"contactPerson"` // 联系人 - ContactPhone string `orm:"column(contact_phone);size(20);null" json:"contactPhone"` // 联系电话 - ContactEmail string `orm:"column(contact_email);size(128);null" json:"contactEmail"` // 联系邮箱 - Address string `orm:"column(address);size(255);null" json:"address"` // 租户地址 - Worktime string `orm:"column(worktime);size(255);null" json:"worktime"` // 工作时间 - Status int8 `orm:"column(status);default(1)" json:"status"` // 租户状态:1-正常,2-停用,0-删除 - Remark string `orm:"column(remark);size(512);null" json:"remark"` // 备注信息 - CreateTime time.Time `orm:"column(create_time);auto_now_add;type(datetime)" json:"createTime"` // 创建时间 - UpdateTime time.Time `orm:"column(update_time);auto_now;type(datetime);null" json:"updateTime"` // 更新时间 - DeleteTime *time.Time `orm:"column(delete_time);type(datetime);null" json:"deleteTime"` // 删除时间 -} - -// TableName 自定义表名 -func (t *Tenant) TableName() string { - return "yz_system_tenant" -} diff --git a/routers/backend/backend.go b/routers/backend/backend.go index 74fa60c..c2740c0 100644 --- a/routers/backend/backend.go +++ b/routers/backend/backend.go @@ -25,58 +25,56 @@ func RegisterAuthRoutes() { beego.Router("/backend/login/getGeetest4Infos", &controllers.PlatformAuthController{}, "get:GetGeetest4Infos") beego.Router("/backend/login/getOpenVerify", &controllers.PlatformAuthController{}, "get:GetOpenVerify") + // 登录相关接口 + beego.Router("/backend/login/getGeetest3Infos", &controllers.PlatformAuthController{}, "get:GetGeetest3Infos") + beego.Router("/backend/login/getGeetest4Infos", &controllers.PlatformAuthController{}, "get:GetGeetest4Infos") + beego.Router("/backend/login/getOpenVerify", &controllers.PlatformAuthController{}, "get:GetOpenVerify") + // 注册与找回密码 beego.Router("/backend/register", &controllers.PlatformAuthController{}, "post:Register") beego.Router("/backend/sendRegisterCode", &controllers.PlatformAuthController{}, "post:SendRegisterCode") beego.Router("/backend/resetPassword", &controllers.PlatformAuthController{}, "post:ResetPassword") beego.Router("/backend/sendResetCode", &controllers.PlatformAuthController{}, "post:SendResetCode") - // backend 菜单相关(租户端菜单) - beego.Router("/backend/menu/:id", &controllers.AdminMenuController{}, "get:GetBackendMenu") - beego.Router("/backend/allmenu", &controllers.AdminMenuController{}, "get:GetAllBackendMenus") - beego.Router("/backend/menu/status/:id", &controllers.AdminMenuController{}, "patch:UpdateMenuStatus") - beego.Router("/backend/createmenu", &controllers.AdminMenuController{}, "post:CreateMenu") - beego.Router("/backend/updatemenu/:id", &controllers.AdminMenuController{}, "put:UpdateMenu") - beego.Router("/backend/deletemenu/:id", &controllers.AdminMenuController{}, "delete:DeleteMenu") - - // 模块管理(yz_system_modules)——语义更正:租户端走 /backend/modules/* - beego.Router("/backend/modules/list", &controllers.PlatformModulesController{}, "get:GetList") - beego.Router("/backend/modules/getTenantList", &controllers.PlatformModulesController{}, "get:GetTenantList") - beego.Router("/backend/modules/select/list", &controllers.PlatformModulesController{}, "get:GetSelectList") - beego.Router("/backend/modules/status", &controllers.PlatformModulesController{}, "post:ChangeStatus") - beego.Router("/backend/modules/batchDelete", &controllers.PlatformModulesController{}, "post:BatchDelete") - beego.Router("/backend/modules", &controllers.PlatformModulesController{}, "post:Add") - beego.Router("/backend/modules/:id", &controllers.PlatformModulesController{}, "get:GetDetail;put:Edit;delete:Delete") - - // 租户站点设置(yz_tenant_site_setting) + // 租户站点设置 beego.Router("/backend/normalInfos", &controllers.SiteSettingsController{}, "get:GetNormalInfos") beego.Router("/backend/saveNormalInfos", &controllers.SiteSettingsController{}, "post:SaveNormalInfos") - // 兼容旧 backend 前端 /admin/* 用户接口 - beego.Router("/admin/getTenantUsers/:tid", &controllers.PlatformTenantUserController{}, "get:GetTenantUsersByTid") - beego.Router("/admin/getAllUsers", &controllers.PlatformAdminUserController{}, "get:GetAllUsers") - beego.Router("/admin/getUserInfo/:id", &controllers.PlatformAdminUserController{}, "get:GetUserInfo") - beego.Router("/admin/addUser", &controllers.PlatformAdminUserController{}, "post:AddUser") - beego.Router("/admin/editUser/:id", &controllers.PlatformAdminUserController{}, "post:EditUser") - beego.Router("/admin/deleteUser/:id", &controllers.PlatformAdminUserController{}, "delete:DeleteUser") - beego.Router("/admin/changePassword", &controllers.PlatformAdminUserController{}, "post:ChangePassword") + // 菜单接口 + beego.Router("/backend/menu/:id", &controllers.BackendMenuController{}, "get:GetBackendMenu") + beego.Router("/backend/allmenu", &controllers.BackendMenuController{}, "get:GetAllBackendMenus") + + // 模块接口 + beego.Router("/backend/modules/getTenantList", &controllers.PlatformModulesController{}, "get:GetTenantList") + + //用户接口 + beego.Router("/backend/getTenantUsers/:tid", &controllers.PlatformTenantUserController{}, "get:GetTenantUsersByTid") + beego.Router("/backend/getAllUsers", &controllers.PlatformAdminUserController{}, "get:GetAllUsers") + beego.Router("/backend/getUserInfo/:id", &controllers.BackendAdminUserController{}, "get:GetUserInfo") + beego.Router("/backend/addUser", &controllers.PlatformAdminUserController{}, "post:AddUser") + beego.Router("/backend/editUser/:id", &controllers.PlatformAdminUserController{}, "post:EditUser") + beego.Router("/backend/deleteUser/:id", &controllers.PlatformAdminUserController{}, "delete:DeleteUser") + beego.Router("/backend/changePassword", &controllers.PlatformAdminUserController{}, "post:ChangePassword") + + // ERP 接口 + beego.Router("/backend/erp/getOrganization", &controllers.BackendErpController{}, "get:GetOrganization") + beego.Router("/backend/erp/getOrganizationDetail/:id", &controllers.BackendErpController{}, "get:GetOrganizationDetail") + beego.Router("/backend/erp/createOrganization", &controllers.BackendErpController{}, "post:CreateOrganization") + beego.Router("/backend/erp/editOrganization/:id", &controllers.BackendErpController{}, "post:EditOrganization") + beego.Router("/backend/erp/deleteOrganization/:id", &controllers.BackendErpController{}, "delete:DeleteOrganization") + beego.Router("/backend/erp/getCompanys", &controllers.BackendErpController{}, "get:GetCompanys") + beego.Router("/backend/erp/getDepartments", &controllers.BackendErpController{}, "get:GetDepartments") + beego.Router("/backend/erp/getEmployee", &controllers.BackendErpController{}, "get:GetEmployee") + beego.Router("/backend/erp/getEmployeeDetail/:id", &controllers.BackendErpController{}, "get:GetEmployeeDetail") + beego.Router("/backend/erp/createEmployee", &controllers.BackendErpController{}, "post:CreateEmployee") + beego.Router("/backend/erp/editEmployee/:id", &controllers.BackendErpController{}, "post:EditEmployee") + beego.Router("/backend/erp/deleteEmployee/:id", &controllers.BackendErpController{}, "delete:DeleteEmployee") + beego.Router("/backend/erp/getPosition", &controllers.BackendErpController{}, "get:GetPosition") + beego.Router("/backend/erp/getPositionDetail/:id", &controllers.BackendErpController{}, "get:GetPositionDetail") + beego.Router("/backend/erp/createPosition", &controllers.BackendErpController{}, "post:CreatePosition") + beego.Router("/backend/erp/editPosition/:id", &controllers.BackendErpController{}, "post:EditPosition") + beego.Router("/backend/erp/deletePosition/:id", &controllers.BackendErpController{}, "delete:DeletePosition") + + // 文章管理相关接口 - // 兼容旧 backend 前端 /admin/erp/* ERP 接口 - beego.Router("/admin/erp/getOrganization", &controllers.BackendErpController{}, "get:GetOrganization") - beego.Router("/admin/erp/getOrganizationDetail/:id", &controllers.BackendErpController{}, "get:GetOrganizationDetail") - beego.Router("/admin/erp/createOrganization", &controllers.BackendErpController{}, "post:CreateOrganization") - beego.Router("/admin/erp/editOrganization/:id", &controllers.BackendErpController{}, "post:EditOrganization") - beego.Router("/admin/erp/deleteOrganization/:id", &controllers.BackendErpController{}, "delete:DeleteOrganization") - beego.Router("/admin/erp/getCompanys", &controllers.BackendErpController{}, "get:GetCompanys") - beego.Router("/admin/erp/getDepartments", &controllers.BackendErpController{}, "get:GetDepartments") - beego.Router("/admin/erp/getEmployee", &controllers.BackendErpController{}, "get:GetEmployee") - beego.Router("/admin/erp/getEmployeeDetail/:id", &controllers.BackendErpController{}, "get:GetEmployeeDetail") - beego.Router("/admin/erp/createEmployee", &controllers.BackendErpController{}, "post:CreateEmployee") - beego.Router("/admin/erp/editEmployee/:id", &controllers.BackendErpController{}, "post:EditEmployee") - beego.Router("/admin/erp/deleteEmployee/:id", &controllers.BackendErpController{}, "delete:DeleteEmployee") - beego.Router("/admin/erp/getPosition", &controllers.BackendErpController{}, "get:GetPosition") - beego.Router("/admin/erp/getPositionDetail/:id", &controllers.BackendErpController{}, "get:GetPositionDetail") - beego.Router("/admin/erp/createPosition", &controllers.BackendErpController{}, "post:CreatePosition") - beego.Router("/admin/erp/editPosition/:id", &controllers.BackendErpController{}, "post:EditPosition") - beego.Router("/admin/erp/deletePosition/:id", &controllers.BackendErpController{}, "delete:DeletePosition") } diff --git a/services/login_verify_code.go b/services/login_verify_code.go index d365bde..bef2db4 100644 --- a/services/login_verify_code.go +++ b/services/login_verify_code.go @@ -58,7 +58,6 @@ func SendPlatformLoginCode(account, channel string) error { Channel: channel, ExpiredAt: time.Now().Add(5 * time.Minute), }) - // TODO: 接入短信/邮箱发送通道。当前阶段只做服务端验证码校验链路。 return nil } @@ -98,19 +97,20 @@ func SendBackendLoginCode(tenantName, account, channel string) error { if channel != "sms" && channel != "email" { return errors.New("仅支持短信或邮箱验证码") } - var tenant models.Tenant - if err := models.Orm.QueryTable(new(models.Tenant)).Filter("tenant_name", tenantName).One(&tenant); err != nil { + + var tenant models.SystemTenant + if err := models.Orm.QueryTable(new(models.SystemTenant)).Filter("tenant_name", tenantName).One(&tenant); err != nil { return errors.New("租户不存在") } + rand.Seed(time.Now().UnixNano()) code := fmt.Sprintf("%06d", rand.Intn(1000000)) - // 规则:先校验租户,再校验“输入的手机号/邮箱”是否为该租户已绑定的记录 switch channel { case "sms": phone := account - var user models.TenantUser - if err := models.Orm.QueryTable(new(models.TenantUser)). + var user models.SystemTenantUser + if err := models.Orm.QueryTable(new(models.SystemTenantUser)). Filter("tid", tenant.ID). Filter("phone", phone). One(&user); err != nil { @@ -129,8 +129,8 @@ func SendBackendLoginCode(tenantName, account, channel string) error { } case "email": email := account - var user models.TenantUser - if err := models.Orm.QueryTable(new(models.TenantUser)). + var user models.SystemTenantUser + if err := models.Orm.QueryTable(new(models.SystemTenantUser)). Filter("tid", tenant.ID). Filter("email", email). One(&user); err != nil { @@ -165,7 +165,6 @@ func getDefaultSystemSMSConfig() (backendURL string, apiKey string, err error) { Limit(1). One(&row) if err != nil { - // fallback:自定义网关 err2 := models.Orm.QueryTable(new(models.SystemSMS)). Filter("config_code", "custom"). OrderBy("-id"). @@ -219,7 +218,6 @@ func enqueueSMSTaskForLogin(tid uint64, phone, content, code string) error { return fmt.Errorf("gateway http status: %d, body: %s", resp.StatusCode, bodyStr) } - // 2xx:认为已成功提交 now := time.Now() tidCopy := tid contentPtr := content @@ -241,10 +239,8 @@ func enqueueSMSTaskForLogin(tid uint64, phone, content, code string) error { } _, insertErr := models.Orm.Insert(task) - // 入队成功但写任务表失败:不影响用户侧体验 if insertErr != nil { return nil } return nil } - diff --git a/services/platform_auth.go b/services/platform_auth.go index e06c689..770a9b8 100644 --- a/services/platform_auth.go +++ b/services/platform_auth.go @@ -51,7 +51,7 @@ func toPlatformLoginUser(user *models.AdminUser) *PlatformLoginUser { } } -// PlatformAdminLogin 平台端登录:仅校验 yz_system_admin_user(不需要租户) +// PlatformAdminLogin 平台端登录:仅校验 yz_system_admin_user,不需要租户。 func PlatformAdminLogin(account, password string) (string, *PlatformLoginUser, error) { account = strings.TrimSpace(account) password = strings.TrimSpace(password) @@ -84,7 +84,7 @@ func PlatformAdminLogin(account, password string) (string, *PlatformLoginUser, e return token, loginUser, nil } -// BackendLogin backend 登录:先校验租户,再校验租户下用户 +// BackendLogin backend 登录:先校验租户,再校验租户下用户账号和密码。 func BackendLogin(tenantName, account, password string) (string, *PlatformLoginUser, error) { tenantName = strings.TrimSpace(tenantName) account = strings.TrimSpace(account) @@ -93,9 +93,8 @@ func BackendLogin(tenantName, account, password string) (string, *PlatformLoginU return "", nil, errors.New("租户名称、用户名或密码不能为空") } - // 1) 校验租户名称 - var tenant models.Tenant - err := models.Orm.QueryTable(new(models.Tenant)). + var tenant models.SystemTenant + err := models.Orm.QueryTable(new(models.SystemTenant)). Filter("tenant_name", tenantName). One(&tenant) if err != nil { @@ -105,9 +104,8 @@ func BackendLogin(tenantName, account, password string) (string, *PlatformLoginU return "", nil, errors.New("租户已停用") } - // 2) 在 tid 下校验租户用户账号和密码 - var tenantUser models.TenantUser - err = models.Orm.QueryTable(new(models.TenantUser)). + var tenantUser models.SystemTenantUser + err = models.Orm.QueryTable(new(models.SystemTenantUser)). Filter("tid", tenant.ID). Filter("account", account). One(&tenantUser) @@ -143,10 +141,11 @@ func BackendLogin(tenantName, account, password string) (string, *PlatformLoginU if tenantUser.Name != nil { loginUser.Name = strings.TrimSpace(*tenantUser.Name) } + return token, loginUser, nil } -// PlatformGetCurrentUser 根据平台管理员用户 ID 返回登录用户信息(含角色名称) +// PlatformGetCurrentUser 根据平台管理员用户 ID 返回登录用户信息(含角色名称)。 func PlatformGetCurrentUser(uid uint64) (*PlatformLoginUser, error) { u, err := GetAdminUserByID(uid) if err != nil { diff --git a/services/tenant_user.go b/services/tenant_user.go index 3e6a568..c3db9cb 100644 --- a/services/tenant_user.go +++ b/services/tenant_user.go @@ -4,8 +4,8 @@ import "server/models" // BindTenantUser 绑定用户到租户(若已存在则更新状态/默认值) func BindTenantUser(tid, uid uint64, account, name, phone, email, password *string, isDefault, status int8, remark *string) (uint64, error) { - var existed models.TenantUser - err := models.Orm.QueryTable(new(models.TenantUser)). + var existed models.SystemTenantUser + err := models.Orm.QueryTable(new(models.SystemTenantUser)). Filter("tid", tid). Filter("uid", uid). One(&existed) @@ -20,11 +20,11 @@ func BindTenantUser(tid, uid uint64, account, name, phone, email, password *stri "is_default": isDefault, "remark": remark, } - _, uErr := models.Orm.QueryTable(new(models.TenantUser)).Filter("id", existed.ID).Update(update) + _, uErr := models.Orm.QueryTable(new(models.SystemTenantUser)).Filter("id", existed.ID).Update(update) return existed.ID, uErr } - m := &models.TenantUser{ + m := &models.SystemTenantUser{ Tid: tid, Uid: uid, Account: account, @@ -42,14 +42,14 @@ func BindTenantUser(tid, uid uint64, account, name, phone, email, password *stri // UnbindTenantUser 删除绑定关系 func UnbindTenantUser(id uint64) error { - _, err := models.Orm.QueryTable(new(models.TenantUser)).Filter("id", id).Delete() + _, err := models.Orm.QueryTable(new(models.SystemTenantUser)).Filter("id", id).Delete() return err } // ListTenantUsersByTid 根据租户ID查询绑定关系 -func ListTenantUsersByTid(tid uint64) ([]models.TenantUser, error) { - var rows []models.TenantUser - _, err := models.Orm.QueryTable(new(models.TenantUser)). +func ListTenantUsersByTid(tid uint64) ([]models.SystemTenantUser, error) { + var rows []models.SystemTenantUser + _, err := models.Orm.QueryTable(new(models.SystemTenantUser)). Filter("tid", tid). OrderBy("-is_default", "-id"). All(&rows) @@ -57,27 +57,64 @@ func ListTenantUsersByTid(tid uint64) ([]models.TenantUser, error) { } // ListTenantBindingsByUid 根据用户ID查询绑定关系 -func ListTenantBindingsByUid(uid uint64) ([]models.TenantUser, error) { - var rows []models.TenantUser - _, err := models.Orm.QueryTable(new(models.TenantUser)). +func ListTenantBindingsByUid(uid uint64) ([]models.SystemTenantUser, error) { + var rows []models.SystemTenantUser + _, err := models.Orm.QueryTable(new(models.SystemTenantUser)). Filter("uid", uid). OrderBy("-is_default", "-id"). All(&rows) return rows, err } +// GetTenantUserByUidAndTid 根据用户ID和租户ID查询租户用户绑定关系 +func GetTenantUserByUidAndTid(uid, tid uint64) (*models.SystemTenantUser, error) { + var row models.SystemTenantUser + err := models.Orm.QueryTable(new(models.SystemTenantUser)). + Filter("uid", uid). + Filter("tid", tid). + One(&row) + if err != nil { + return nil, err + } + return &row, nil +} + +// GetTenantUserByUid 根据用户ID查询默认/最新租户用户绑定关系 +func GetTenantUserByUid(uid uint64) (*models.SystemTenantUser, error) { + var row models.SystemTenantUser + err := models.Orm.QueryTable(new(models.SystemTenantUser)). + Filter("uid", uid). + OrderBy("-is_default", "-id"). + One(&row) + if err != nil { + return nil, err + } + return &row, nil +} + +// GetTenantByID 根据租户ID查询租户信息 +func GetTenantByID(id uint64) (*models.SystemTenant, error) { + var row models.SystemTenant + err := models.Orm.QueryTable(new(models.SystemTenant)). + Filter("id", id). + One(&row) + if err != nil { + return nil, err + } + return &row, nil +} + // SetDefaultTenant 设置用户默认租户(同一用户仅一个默认) func SetDefaultTenant(uid, tid uint64) error { - _, err := models.Orm.QueryTable(new(models.TenantUser)).Filter("uid", uid).Update(map[string]interface{}{ + _, err := models.Orm.QueryTable(new(models.SystemTenantUser)).Filter("uid", uid).Update(map[string]interface{}{ "is_default": 0, }) if err != nil { return err } - _, err = models.Orm.QueryTable(new(models.TenantUser)). + _, err = models.Orm.QueryTable(new(models.SystemTenantUser)). Filter("uid", uid). Filter("tid", tid). Update(map[string]interface{}{"is_default": 1}) return err } -