逐步替换代码

This commit is contained in:
2026-04-01 00:06:36 +08:00
parent ae786d5157
commit 1314e18142
15 changed files with 1964 additions and 40 deletions
+335
View File
@@ -0,0 +1,335 @@
package controllers
import (
"encoding/json"
"io"
"server/models"
"strconv"
"strings"
beego "github.com/beego/beego/v2/server/web"
)
// AdminMenuController 后台菜单控制器
type AdminMenuController struct {
beego.Controller
}
type menuPayload struct {
Pid *int64 `json:"pid"`
Title *string `json:"title"`
Path *string `json:"path"`
ComponentPath *string `json:"component_path"`
Icon *string `json:"icon"`
Sort *int64 `json:"sort"`
Status *int8 `json:"status"`
IsVisible *int8 `json:"is_visible"`
IsPlatform *int8 `json:"is_platform"`
Type *int8 `json:"type"`
Permission *string `json:"permission"`
}
// GetMenu 获取指定用户可见的菜单列表(简化版:当前先忽略用户权限,返回全部启用且平台端菜单)
// 路由示例:GET /platform/menu/1
func (c *AdminMenuController) GetMenu() {
// 从路由参数中解析用户 ID,占位保留,方便后续按用户权限过滤
_ = c.Ctx.Input.Param(":id")
// 查询所有启用且标记为平台端的菜单
var menus []models.SystemMenu
qs := models.Orm.
QueryTable(new(models.SystemMenu)).
Filter("status", 1).
Filter("is_platform", 1)
_, err := qs.All(&menus)
if err != nil {
c.Data["json"] = map[string]interface{}{
"code": 500,
"msg": "获取菜单失败: " + err.Error(),
"data": nil,
}
_ = c.ServeJSON()
return
}
// 将平铺的菜单列表构建为树形结构
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() {
var menus []models.SystemMenu
cid, _ := c.GetInt("cid")
qs := models.Orm.QueryTable(new(models.SystemMenu))
// 菜单管理默认返回全量菜单;仅在明确传 cid 时按分类筛选
// cid: 1平台角色 -> 平台菜单;2租户角色 -> 租户菜单
if cid == 1 {
qs = qs.Filter("is_platform", 1)
} else if cid == 2 {
qs = qs.Filter("is_platform", 0)
}
_, err := qs.All(&menus)
if err != nil {
c.Data["json"] = map[string]interface{}{
"code": 500,
"msg": "获取菜单失败: " + err.Error(),
"data": nil,
}
_ = c.ServeJSON()
return
}
tree := buildMenuTree(menus, 0)
c.Data["json"] = map[string]interface{}{
"code": 200,
"msg": "success",
"data": tree,
}
_ = c.ServeJSON()
}
// menuNode 用于 JSON 返回的菜单结构
type menuNode struct {
ID uint64 `json:"id"`
Pid int64 `json:"pid"`
Title string `json:"title"`
Path string `json:"path,omitempty"`
ComponentPath string `json:"component_path,omitempty"`
Icon string `json:"icon,omitempty"`
Sort int64 `json:"sort"`
Status int8 `json:"status"`
IsVisible *int8 `json:"is_visible,omitempty"`
IsPlatform *int8 `json:"is_platform,omitempty"`
Type int8 `json:"type"`
Permission string `json:"permission,omitempty"`
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,
IsPlatform: m.IsPlatform,
Type: m.Type,
}
if m.Path != nil {
node.Path = *m.Path
}
if m.ComponentPath != nil {
node.ComponentPath = *m.ComponentPath
}
if m.Icon != nil {
node.Icon = *m.Icon
}
if m.Permission != nil {
node.Permission = *m.Permission
}
// 递归查找子菜单
children := buildMenuTree(menus, int64(m.ID))
if len(children) > 0 {
node.Children = children
}
tree = append(tree, node)
}
}
return tree
}
// UpdateMenuStatus 更新菜单状态
// 路由:PATCH /platform/menu/status/:id
func (c *AdminMenuController) 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"}
_ = c.ServeJSON()
return
}
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 {
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 {
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() {
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)),
IsPlatform: ptrInt8(valueInt8(payload.IsPlatform, 1)),
Type: valueInt8(payload.Type, 1),
}
menu.Path = ptrString(valueString(payload.Path, ""))
menu.ComponentPath = ptrString(valueString(payload.ComponentPath, ""))
menu.Icon = ptrString(valueString(payload.Icon, ""))
menu.Permission = ptrString(valueString(payload.Permission, ""))
id, err := models.Orm.Insert(&menu)
if 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": "创建成功",
"data": map[string]interface{}{"id": id},
}
_ = c.ServeJSON()
}
// UpdateMenu 更新菜单
// 路由:PUT /platform/updatemenu/:id
func (c *AdminMenuController) 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"}
_ = c.ServeJSON()
return
}
payload, ok := c.parseMenuPayload(false)
if !ok {
return
}
update := map[string]interface{}{
"pid": valueInt64(payload.Pid, 0),
"title": strings.TrimSpace(valueString(payload.Title, "")),
"path": valueString(payload.Path, ""),
"component_path": valueString(payload.ComponentPath, ""),
"icon": valueString(payload.Icon, ""),
"sort": valueInt64(payload.Sort, 0),
"status": valueInt8(payload.Status, 1),
"is_visible": valueInt8(payload.IsVisible, 1),
"is_platform": valueInt8(payload.IsPlatform, 1),
"type": valueInt8(payload.Type, 1),
"permission": valueString(payload.Permission, ""),
}
_, err = models.Orm.QueryTable(new(models.SystemMenu)).
Filter("id", id).
Update(update)
if 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() {
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.ServeJSON()
return
}
_, err = models.Orm.QueryTable(new(models.SystemMenu)).Filter("id", id).Delete()
if 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)
var payload menuPayload
if err := json.Unmarshal(rawBody, &payload); err != nil {
c.Data["json"] = map[string]interface{}{"code": 400, "msg": "参数错误"}
_ = c.ServeJSON()
return nil, false
}
if needTitle && strings.TrimSpace(valueString(payload.Title, "")) == "" {
c.Data["json"] = map[string]interface{}{"code": 400, "msg": "菜单名称不能为空"}
_ = c.ServeJSON()
return nil, false
}
return &payload, true
}
func valueString(v *string, def string) string {
if v == nil {
return def
}
return *v
}
func valueInt8(v *int8, def int8) int8 {
if v == nil {
return def
}
return *v
}
func valueInt64(v *int64, def int64) int64 {
if v == nil {
return def
}
return *v
}
func ptrString(v string) *string {
return &v
}
func ptrInt8(v int8) *int8 {
return &v
}
+303
View File
@@ -0,0 +1,303 @@
package controllers
import (
"encoding/json"
"io"
"strconv"
"strings"
"server/models"
beego "github.com/beego/beego/v2/server/web"
)
// PlatformAdminUserController 平台管理员用户管理(yz_admin_user
type PlatformAdminUserController struct {
beego.Controller
}
type adminUserDTO struct {
ID uint64 `json:"id"`
Account string `json:"account"`
Name *string `json:"name"`
Phone *string `json:"phone"`
Email *string `json:"email"`
Qq *string `json:"qq"`
Sex uint8 `json:"sex"`
Avatar *string `json:"avatar"`
GroupID uint64 `json:"group_id"`
LoginCount uint64 `json:"login_count"`
LastLoginIP *string `json:"last_login_ip"`
Status uint8 `json:"status"`
CreateTime string `json:"create_time"`
UpdateTime *string `json:"update_time"`
}
func toAdminUserDTO(u models.AdminUser) adminUserDTO {
var updateTime *string
if u.UpdateTime != nil {
s := u.UpdateTime.Format("2006-01-02 15:04:05")
updateTime = &s
}
return adminUserDTO{
ID: u.ID,
Account: u.Account,
Name: u.Name,
Phone: u.Phone,
Email: u.Email,
Qq: u.Qq,
Sex: u.Sex,
Avatar: u.Avatar,
GroupID: u.RoleID,
LoginCount: u.LoginCount,
LastLoginIP: u.LastLoginIP,
Status: u.Status,
CreateTime: u.CreateTime.Format("2006-01-02 15:04:05"),
UpdateTime: updateTime,
}
}
// GetAllUsers 获取全部平台管理员用户
// GET /platform/getAllUsers
func (c *PlatformAdminUserController) GetAllUsers() {
rows, total, err := models.ListAdminUsers()
if err != nil {
c.Data["json"] = map[string]interface{}{"code": 500, "msg": "查询失败"}
_ = c.ServeJSON()
return
}
list := make([]adminUserDTO, 0, len(rows))
for _, u := range rows {
list = append(list, toAdminUserDTO(u))
}
c.Data["json"] = map[string]interface{}{
"code": 200,
"msg": "success",
"data": map[string]interface{}{"list": list, "total": total},
}
_ = c.ServeJSON()
}
// GetUserInfo 获取用户详情
// GET /platform/getUserInfo/:id
func (c *PlatformAdminUserController) GetUserInfo() {
idStr := c.Ctx.Input.Param(":id")
id, _ := strconv.ParseUint(idStr, 10, 64)
if id == 0 {
c.Data["json"] = map[string]interface{}{"code": 400, "msg": "id 不能为空"}
_ = c.ServeJSON()
return
}
u, err := models.GetAdminUserByID(id)
if err != nil {
c.Data["json"] = map[string]interface{}{"code": 404, "msg": "用户不存在"}
_ = c.ServeJSON()
return
}
c.Data["json"] = map[string]interface{}{
"code": 200,
"msg": "success",
"data": toAdminUserDTO(*u),
}
_ = c.ServeJSON()
}
type adminAddUserPayload struct {
Account string `json:"account"`
Password string `json:"password"`
Name *string `json:"name"`
Phone *string `json:"phone"`
Email *string `json:"email"`
Qq *string `json:"qq"`
Sex *uint8 `json:"sex"`
Avatar *string `json:"avatar"`
GroupID *uint64 `json:"group_id"`
Status *uint8 `json:"status"`
}
// AddUser 添加平台管理员用户(仅写 yz_admin_user,不处理 tid
// POST /platform/addUser
func (c *PlatformAdminUserController) AddUser() {
var p adminAddUserPayload
raw, _ := io.ReadAll(c.Ctx.Request.Body)
if err := json.Unmarshal(raw, &p); err != nil {
c.Data["json"] = map[string]interface{}{"code": 400, "msg": "参数错误"}
_ = c.ServeJSON()
return
}
p.Account = strings.TrimSpace(p.Account)
p.Password = strings.TrimSpace(p.Password)
if p.Account == "" {
c.Data["json"] = map[string]interface{}{"code": 400, "msg": "account 不能为空"}
_ = c.ServeJSON()
return
}
if p.Password == "" {
c.Data["json"] = map[string]interface{}{"code": 400, "msg": "password 不能为空"}
_ = c.ServeJSON()
return
}
status := uint8(1)
if p.Status != nil {
status = *p.Status
}
sex := uint8(0)
if p.Sex != nil {
sex = *p.Sex
}
groupID := uint64(1)
if p.GroupID != nil && *p.GroupID != 0 {
groupID = *p.GroupID
}
id, err := models.CreateAdminUser(p.Account, p.Password, p.Name, p.Phone, p.Email, p.Qq, p.Avatar, sex, groupID, status)
if err != nil {
c.Data["json"] = map[string]interface{}{"code": 500, "msg": "添加失败"}
_ = c.ServeJSON()
return
}
c.Data["json"] = map[string]interface{}{
"code": 200,
"msg": "success",
"data": map[string]interface{}{"id": id},
}
_ = c.ServeJSON()
}
type editUserPayload struct {
Account *string `json:"account"`
Password *string `json:"password"`
Name *string `json:"name"`
Phone *string `json:"phone"`
Email *string `json:"email"`
Qq *string `json:"qq"`
Sex *uint8 `json:"sex"`
Avatar *string `json:"avatar"`
GroupID *uint64 `json:"group_id"`
Status *uint8 `json:"status"`
}
// EditUser 编辑用户信息(password 可选,存在则修改)
// POST /platform/editUser/:id
func (c *PlatformAdminUserController) EditUser() {
idStr := c.Ctx.Input.Param(":id")
id, _ := strconv.ParseUint(idStr, 10, 64)
if id == 0 {
c.Data["json"] = map[string]interface{}{"code": 400, "msg": "id 不能为空"}
_ = c.ServeJSON()
return
}
var p editUserPayload
raw, _ := io.ReadAll(c.Ctx.Request.Body)
if err := json.Unmarshal(raw, &p); err != nil {
c.Data["json"] = map[string]interface{}{"code": 400, "msg": "参数错误"}
_ = c.ServeJSON()
return
}
fields := map[string]interface{}{}
if p.Account != nil {
acc := strings.TrimSpace(*p.Account)
if acc != "" {
fields["account"] = acc
}
}
if p.Name != nil {
fields["name"] = *p.Name
}
if p.Phone != nil {
fields["phone"] = *p.Phone
}
if p.Email != nil {
fields["email"] = *p.Email
}
if p.Qq != nil {
fields["qq"] = *p.Qq
}
if p.Sex != nil {
fields["sex"] = *p.Sex
}
if p.Avatar != nil {
fields["avatar"] = *p.Avatar
}
if p.GroupID != nil && *p.GroupID != 0 {
fields["role_id"] = *p.GroupID
}
if p.Status != nil {
fields["status"] = *p.Status
}
if len(fields) > 0 {
if err := models.UpdateAdminUser(id, fields); err != nil {
c.Data["json"] = map[string]interface{}{"code": 500, "msg": "编辑失败"}
_ = c.ServeJSON()
return
}
}
if p.Password != nil && strings.TrimSpace(*p.Password) != "" {
if err := models.ChangeAdminUserPassword(id, *p.Password); err != nil {
c.Data["json"] = map[string]interface{}{"code": 500, "msg": "密码修改失败"}
_ = c.ServeJSON()
return
}
}
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "success"}
_ = c.ServeJSON()
}
// DeleteUser 删除用户
// DELETE /platform/deleteUser/:id
func (c *PlatformAdminUserController) DeleteUser() {
idStr := c.Ctx.Input.Param(":id")
id, _ := strconv.ParseUint(idStr, 10, 64)
if id == 0 {
c.Data["json"] = map[string]interface{}{"code": 400, "msg": "id 不能为空"}
_ = c.ServeJSON()
return
}
if err := models.DeleteAdminUser(id); err != nil {
c.Data["json"] = map[string]interface{}{"code": 500, "msg": "删除失败"}
_ = c.ServeJSON()
return
}
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "success"}
_ = c.ServeJSON()
}
type changePasswordPayload struct {
ID uint64 `json:"id"`
Password string `json:"password"`
}
// ChangePassword 修改密码
// POST /platform/changePassword
func (c *PlatformAdminUserController) ChangePassword() {
var p changePasswordPayload
raw, _ := io.ReadAll(c.Ctx.Request.Body)
if err := json.Unmarshal(raw, &p); err != nil {
c.Data["json"] = map[string]interface{}{"code": 400, "msg": "参数错误"}
_ = c.ServeJSON()
return
}
if p.ID == 0 {
c.Data["json"] = map[string]interface{}{"code": 400, "msg": "id 不能为空"}
_ = c.ServeJSON()
return
}
if strings.TrimSpace(p.Password) == "" {
c.Data["json"] = map[string]interface{}{"code": 400, "msg": "password 不能为空"}
_ = c.ServeJSON()
return
}
if err := models.ChangeAdminUserPassword(p.ID, p.Password); err != nil {
c.Data["json"] = map[string]interface{}{"code": 500, "msg": "修改失败"}
_ = c.ServeJSON()
return
}
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "修改成功"}
_ = c.ServeJSON()
}
+6 -8
View File
@@ -53,7 +53,7 @@ func (c *PlatformAuthController) Login() {
}
// 控制器只做 HTTP 解析与响应编排,业务逻辑放 services 层
token, err := services.PlatformLogin(req.Account, req.Password)
token, loginUser, err := services.PlatformLogin(req.Account, req.Password)
if err != nil {
c.Data["json"] = map[string]interface{}{
"code": 401,
@@ -68,14 +68,12 @@ func (c *PlatformAuthController) Login() {
"msg": "登录成功",
"data": map[string]interface{}{
"token": token,
// user 结构用于前端 authStore 兼容旧格式
"user": map[string]interface{}{
"id": 1,
"account": req.Account,
"name": "平台管理员",
"group_id": "",
"tid": "",
"avatar": "",
"id": loginUser.ID,
"account": loginUser.Account,
"name": loginUser.Name,
"rid": loginUser.Rid,
"avatar": loginUser.Avatar,
},
},
}
+202
View File
@@ -0,0 +1,202 @@
package controllers
import (
"encoding/json"
"io"
"strconv"
"strings"
"server/models"
beego "github.com/beego/beego/v2/server/web"
)
// PlatformRoleController 平台角色管理(yz_admin_role
type PlatformRoleController struct {
beego.Controller
}
type rolePayload struct {
Cid *uint8 `json:"cid"`
Name string `json:"name"`
Status *uint8 `json:"status"`
Rights interface{} `json:"rights"`
}
func normalizeRights(v interface{}) *string {
if v == nil {
return nil
}
switch t := v.(type) {
case string:
s := strings.TrimSpace(t)
if s == "" {
return nil
}
return &s
default:
b, err := json.Marshal(v)
if err != nil {
return nil
}
s := string(b)
return &s
}
}
// GetAllRoles 获取角色列表
// GET /platform/allRoles
func (c *PlatformRoleController) GetAllRoles() {
var rows []models.AdminRole
_, err := models.Orm.QueryTable(new(models.AdminRole)).
OrderBy("-id").
All(&rows)
if err != nil {
c.Data["json"] = map[string]interface{}{"code": 500, "msg": "查询失败"}
_ = c.ServeJSON()
return
}
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "success", "data": rows}
_ = c.ServeJSON()
}
// GetRoleByID 获取角色详情
// GET /platform/roles/:id
func (c *PlatformRoleController) GetRoleByID() {
idStr := c.Ctx.Input.Param(":id")
id, _ := strconv.ParseUint(idStr, 10, 64)
if id == 0 {
c.Data["json"] = map[string]interface{}{"code": 400, "msg": "id 不能为空"}
_ = c.ServeJSON()
return
}
role := models.AdminRole{ID: id}
if err := models.Orm.Read(&role); err != nil {
c.Data["json"] = map[string]interface{}{"code": 404, "msg": "角色不存在"}
_ = c.ServeJSON()
return
}
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "success", "data": role}
_ = c.ServeJSON()
}
// CreateRole 创建角色
// POST /platform/roles
func (c *PlatformRoleController) CreateRole() {
var p rolePayload
raw, _ := io.ReadAll(c.Ctx.Request.Body)
if err := json.Unmarshal(raw, &p); err != nil {
c.Data["json"] = map[string]interface{}{"code": 400, "msg": "参数错误"}
_ = c.ServeJSON()
return
}
p.Name = strings.TrimSpace(p.Name)
if p.Name == "" {
c.Data["json"] = map[string]interface{}{"code": 400, "msg": "name 不能为空"}
_ = c.ServeJSON()
return
}
status := uint8(1)
if p.Status != nil {
status = *p.Status
}
cid := uint8(1)
if p.Cid != nil {
cid = *p.Cid
}
if cid != 1 && cid != 2 {
c.Data["json"] = map[string]interface{}{"code": 400, "msg": "cid 仅支持 1/2"}
_ = c.ServeJSON()
return
}
rights := normalizeRights(p.Rights)
role := &models.AdminRole{
Cid: cid,
Name: p.Name,
Status: status,
Rights: rights,
}
id, err := models.Orm.Insert(role)
if err != nil {
c.Data["json"] = map[string]interface{}{"code": 500, "msg": "创建失败"}
_ = c.ServeJSON()
return
}
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "success", "data": map[string]interface{}{"id": id}}
_ = c.ServeJSON()
}
// UpdateRole 更新角色
// PUT /platform/roles/:id
func (c *PlatformRoleController) UpdateRole() {
idStr := c.Ctx.Input.Param(":id")
id, _ := strconv.ParseUint(idStr, 10, 64)
if id == 0 {
c.Data["json"] = map[string]interface{}{"code": 400, "msg": "id 不能为空"}
_ = c.ServeJSON()
return
}
var p rolePayload
raw, _ := io.ReadAll(c.Ctx.Request.Body)
if err := json.Unmarshal(raw, &p); err != nil {
c.Data["json"] = map[string]interface{}{"code": 400, "msg": "参数错误"}
_ = c.ServeJSON()
return
}
update := map[string]interface{}{}
if strings.TrimSpace(p.Name) != "" {
update["name"] = strings.TrimSpace(p.Name)
}
if p.Status != nil {
update["status"] = *p.Status
}
if p.Cid != nil {
if *p.Cid != 1 && *p.Cid != 2 {
c.Data["json"] = map[string]interface{}{"code": 400, "msg": "cid 仅支持 1/2"}
_ = c.ServeJSON()
return
}
update["cid"] = *p.Cid
}
if p.Rights != nil {
update["rights"] = normalizeRights(p.Rights)
}
if len(update) == 0 {
c.Data["json"] = map[string]interface{}{"code": 400, "msg": "无更新字段"}
_ = c.ServeJSON()
return
}
_, err := models.Orm.QueryTable(new(models.AdminRole)).Filter("id", id).Update(update)
if err != nil {
c.Data["json"] = map[string]interface{}{"code": 500, "msg": "更新失败"}
_ = c.ServeJSON()
return
}
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "success"}
_ = c.ServeJSON()
}
// DeleteRole 删除角色
// DELETE /platform/roles/:id
func (c *PlatformRoleController) DeleteRole() {
idStr := c.Ctx.Input.Param(":id")
id, _ := strconv.ParseUint(idStr, 10, 64)
if id == 0 {
c.Data["json"] = map[string]interface{}{"code": 400, "msg": "id 不能为空"}
_ = c.ServeJSON()
return
}
_, err := models.Orm.QueryTable(new(models.AdminRole)).Filter("id", id).Delete()
if err != nil {
c.Data["json"] = map[string]interface{}{"code": 500, "msg": "删除失败"}
_ = c.ServeJSON()
return
}
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "success"}
_ = c.ServeJSON()
}
+333
View File
@@ -0,0 +1,333 @@
package controllers
import (
"encoding/json"
"io"
"strconv"
"strings"
"time"
"server/models"
beego "github.com/beego/beego/v2/server/web"
)
// PlatformTenantController 平台端租户管理
type PlatformTenantController struct {
beego.Controller
}
type tenantDTO struct {
ID uint64 `json:"id"`
TenantCode string `json:"tenant_code"`
TenantName string `json:"tenant_name"`
ContactPerson string `json:"contact_person"`
ContactPhone string `json:"contact_phone"`
ContactEmail string `json:"contact_email"`
Address string `json:"address"`
Worktime string `json:"worktime"`
Status int8 `json:"status"`
Remark string `json:"remark"`
CreateTime *time.Time `json:"create_time,omitempty"`
UpdateTime *time.Time `json:"update_time,omitempty"`
DeleteTime *time.Time `json:"delete_time,omitempty"`
}
func toTenantDTO(t models.Tenant) 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,
Status: t.Status,
Remark: t.Remark,
CreateTime: &ct,
UpdateTime: &ut,
DeleteTime: t.DeleteTime,
}
}
// 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)
pageSize, _ := c.GetInt("pageSize", 10)
if page < 1 {
page = 1
}
if pageSize < 1 {
pageSize = 10
}
tenantName := strings.TrimSpace(c.GetString("tenant_name"))
tenantCode := strings.TrimSpace(c.GetString("tenant_code"))
contactPerson := strings.TrimSpace(c.GetString("contact_person"))
contactPhone := strings.TrimSpace(c.GetString("contact_phone"))
qs := models.Orm.QueryTable(new(models.Tenant))
if tenantName != "" {
qs = qs.Filter("tenant_name__icontains", tenantName)
}
if tenantCode != "" {
qs = qs.Filter("tenant_code__icontains", tenantCode)
}
if contactPerson != "" {
qs = qs.Filter("contact_person__icontains", contactPerson)
}
if contactPhone != "" {
qs = qs.Filter("contact_phone__icontains", contactPhone)
}
total, err := qs.Count()
if err != nil {
c.Data["json"] = map[string]interface{}{"code": 500, "msg": "获取租户失败: " + err.Error()}
_ = c.ServeJSON()
return
}
var rows []models.Tenant
_, 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.ServeJSON()
return
}
list := make([]tenantDTO, 0, len(rows))
for _, t := range rows {
list = append(list, toTenantDTO(t))
}
c.Data["json"] = map[string]interface{}{
"code": 200,
"msg": "success",
"data": map[string]interface{}{
"list": list,
"total": total,
},
}
_ = c.ServeJSON()
}
// 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.ServeJSON()
return
}
var t models.Tenant
err = models.Orm.QueryTable(new(models.Tenant)).Filter("id", id).One(&t)
if err != nil {
c.Data["json"] = map[string]interface{}{"code": 404, "msg": "租户不存在"}
_ = c.ServeJSON()
return
}
c.Data["json"] = map[string]interface{}{
"code": 200,
"msg": "success",
"data": toTenantDTO(t),
}
_ = c.ServeJSON()
}
type tenantPayload struct {
TenantCode string `json:"tenant_code"`
TenantName string `json:"tenant_name"`
ContactPerson string `json:"contact_person"`
ContactPhone string `json:"contact_phone"`
ContactEmail string `json:"contact_email"`
Address string `json:"address"`
Worktime string `json:"worktime"`
Status *int8 `json:"status"`
Remark string `json:"remark"`
}
func (c *PlatformTenantController) parseTenantPayload() (tenantPayload, error) {
// 优先从表单读取(createTenant 使用 multipart/form-data
p := tenantPayload{
TenantCode: strings.TrimSpace(c.GetString("tenant_code")),
TenantName: strings.TrimSpace(c.GetString("tenant_name")),
ContactPerson: strings.TrimSpace(c.GetString("contact_person")),
ContactPhone: strings.TrimSpace(c.GetString("contact_phone")),
ContactEmail: strings.TrimSpace(c.GetString("contact_email")),
Address: strings.TrimSpace(c.GetString("address")),
Worktime: strings.TrimSpace(c.GetString("worktime")),
Remark: strings.TrimSpace(c.GetString("remark")),
}
if s := strings.TrimSpace(c.GetString("status")); s != "" {
if v, err := strconv.ParseInt(s, 10, 8); err == nil {
tmp := int8(v)
p.Status = &tmp
}
}
// 如果关键字段为空,尝试从 JSON body 解析(editTenant 默认 JSON
if p.TenantName == "" && p.TenantCode == "" {
raw, _ := io.ReadAll(c.Ctx.Request.Body)
if len(raw) > 0 {
_ = json.Unmarshal(raw, &p)
}
}
return p, nil
}
// 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.ServeJSON()
return
}
if strings.TrimSpace(p.TenantCode) == "" {
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()
if err != nil {
c.Data["json"] = map[string]interface{}{"code": 500, "msg": "创建失败: " + err.Error()}
_ = c.ServeJSON()
return
}
if cnt > 0 {
c.Data["json"] = map[string]interface{}{"code": 400, "msg": "租户编码已存在"}
_ = c.ServeJSON()
return
}
status := int8(1)
if p.Status != nil {
status = *p.Status
}
t := models.Tenant{
TenantCode: p.TenantCode,
TenantName: p.TenantName,
ContactPerson: p.ContactPerson,
ContactPhone: p.ContactPhone,
ContactEmail: p.ContactEmail,
Address: p.Address,
Worktime: p.Worktime,
Status: status,
Remark: p.Remark,
}
id, err := models.Orm.Insert(&t)
if 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",
"data": map[string]interface{}{"id": id},
}
_ = c.ServeJSON()
}
// 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.ServeJSON()
return
}
p, _ := c.parseTenantPayload()
if strings.TrimSpace(p.TenantName) == "" {
c.Data["json"] = map[string]interface{}{"code": 400, "msg": "租户名称不能为空"}
_ = c.ServeJSON()
return
}
update := map[string]interface{}{
"tenant_name": p.TenantName,
"contact_person": p.ContactPerson,
"contact_phone": p.ContactPhone,
"contact_email": p.ContactEmail,
"address": p.Address,
"worktime": p.Worktime,
"remark": p.Remark,
}
if p.Status != nil {
update["status"] = *p.Status
}
_, err = models.Orm.QueryTable(new(models.Tenant)).Filter("id", id).Update(update)
if 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"}
_ = c.ServeJSON()
}
// 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.ServeJSON()
return
}
_, err = models.Orm.QueryTable(new(models.Tenant)).Filter("id", id).Delete()
if 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"}
_ = c.ServeJSON()
}
// FindTenantCode 校验租户编码是否重复
// GET /platform/tenant/findTenantCode?tenant_code=xxxxxx
// 返回 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.ServeJSON()
return
}
cnt, err := models.Orm.QueryTable(new(models.Tenant)).Filter("tenant_code", code).Count()
if err != nil {
c.Data["json"] = map[string]interface{}{"code": 500, "msg": "校验失败: " + err.Error()}
_ = c.ServeJSON()
return
}
if cnt > 0 {
c.Data["json"] = map[string]interface{}{"code": 409, "msg": "租户编码已存在"}
_ = c.ServeJSON()
return
}
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "ok"}
_ = c.ServeJSON()
}
+289
View File
@@ -0,0 +1,289 @@
package controllers
import (
"encoding/json"
"errors"
"io"
"math/rand"
"strconv"
"strings"
"time"
"server/models"
beego "github.com/beego/beego/v2/server/web"
)
// PlatformTenantUserController 平台端租户-用户绑定管理
type PlatformTenantUserController struct {
beego.Controller
}
type tenantUserPayload struct {
Tid uint64 `json:"tid"`
Uid uint64 `json:"uid"`
Account *string `json:"account"`
Name *string `json:"name"`
Phone *string `json:"phone"`
Email *string `json:"email"`
Password *string `json:"password"`
IsDefault *int8 `json:"is_default"`
Status *int8 `json:"status"`
Remark *string `json:"remark"`
}
// GetTenantUserList 获取绑定列表(支持按 tid / uid 过滤)
// GET /platform/tenantUser/list?tid=1&uid=2
func (c *PlatformTenantUserController) GetTenantUserList() {
tid, _ := c.GetUint64("tid")
uid, _ := c.GetUint64("uid")
qs := models.Orm.QueryTable(new(models.TenantUser))
if tid > 0 {
qs = qs.Filter("tid", tid)
}
if uid > 0 {
qs = qs.Filter("uid", uid)
}
var rows []models.TenantUser
_, err := qs.OrderBy("-is_default", "-id").All(&rows)
if 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",
"data": map[string]interface{}{
"list": rows,
"total": len(rows),
},
}
_ = c.ServeJSON()
}
// GetTenantUsersByTid 兼容路径参数方式获取租户用户列表
// GET /platform/getTenantUsers/:tid
func (c *PlatformTenantUserController) GetTenantUsersByTid() {
tidStr := c.Ctx.Input.Param(":tid")
tid, _ := strconv.ParseUint(tidStr, 10, 64)
if tid == 0 {
c.Data["json"] = map[string]interface{}{"code": 400, "msg": "tid 不能为空"}
_ = c.ServeJSON()
return
}
var rows []models.TenantUser
_, err := models.Orm.QueryTable(new(models.TenantUser)).
Filter("tid", tid).
OrderBy("-is_default", "-id").
All(&rows)
if 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",
"data": map[string]interface{}{"list": rows, "total": len(rows)},
}
_ = c.ServeJSON()
}
// GetTenantUserDetail 获取绑定详情
// GET /platform/tenantUser/detail/:id
func (c *PlatformTenantUserController) GetTenantUserDetail() {
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.ServeJSON()
return
}
var row models.TenantUser
err = models.Orm.QueryTable(new(models.TenantUser)).Filter("id", id).One(&row)
if err != nil {
c.Data["json"] = map[string]interface{}{"code": 404, "msg": "记录不存在"}
_ = c.ServeJSON()
return
}
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "success", "data": row}
_ = c.ServeJSON()
}
// CreateTenantUser 创建绑定
// POST /platform/tenantUser/create
func (c *PlatformTenantUserController) CreateTenantUser() {
p, ok := c.parsePayload()
if !ok {
return
}
if p.Tid == 0 {
c.Data["json"] = map[string]interface{}{"code": 400, "msg": "tid 不能为空"}
_ = c.ServeJSON()
return
}
if p.Account == nil || strings.TrimSpace(*p.Account) == "" {
c.Data["json"] = map[string]interface{}{"code": 400, "msg": "account 不能为空"}
_ = c.ServeJSON()
return
}
if p.Password == nil || strings.TrimSpace(*p.Password) == "" {
c.Data["json"] = map[string]interface{}{"code": 400, "msg": "password 不能为空"}
_ = c.ServeJSON()
return
}
if p.Uid == 0 {
uid, err := generateTenantUID(p.Tid)
if err != nil {
c.Data["json"] = map[string]interface{}{"code": 500, "msg": "生成租户用户ID失败"}
_ = c.ServeJSON()
return
}
p.Uid = uid
}
isDefault := int8(0)
status := int8(1)
if p.IsDefault != nil {
isDefault = *p.IsDefault
}
if p.Status != nil {
status = *p.Status
}
id, err := models.BindTenantUser(p.Tid, p.Uid, p.Account, p.Name, p.Phone, p.Email, p.Password, isDefault, status, p.Remark)
if err != nil {
c.Data["json"] = map[string]interface{}{"code": 500, "msg": "创建失败: " + err.Error()}
_ = c.ServeJSON()
return
}
if isDefault == 1 {
_ = models.SetDefaultTenant(p.Uid, p.Tid)
}
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "success", "data": map[string]interface{}{"id": id}}
_ = c.ServeJSON()
}
// EditTenantUser 编辑绑定
// POST /platform/tenantUser/edit/:id
func (c *PlatformTenantUserController) EditTenantUser() {
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.ServeJSON()
return
}
p, ok := c.parsePayload()
if !ok {
return
}
update := map[string]interface{}{}
if p.Tid > 0 {
update["tid"] = p.Tid
}
if p.Uid > 0 {
update["uid"] = p.Uid
}
if p.Account != nil {
update["account"] = p.Account
}
if p.Name != nil {
update["name"] = p.Name
}
if p.Phone != nil {
update["phone"] = p.Phone
}
if p.Email != nil {
update["email"] = p.Email
}
if p.Password != nil {
update["password"] = p.Password
}
if p.IsDefault != nil {
update["is_default"] = *p.IsDefault
}
if p.Status != nil {
update["status"] = *p.Status
}
if p.Remark != nil {
update["remark"] = p.Remark
}
if len(update) == 0 {
c.Data["json"] = map[string]interface{}{"code": 400, "msg": "无更新字段"}
_ = c.ServeJSON()
return
}
_, err = models.Orm.QueryTable(new(models.TenantUser)).Filter("id", id).Update(update)
if err != nil {
c.Data["json"] = map[string]interface{}{"code": 500, "msg": "更新失败: " + err.Error()}
_ = c.ServeJSON()
return
}
if p.IsDefault != nil && *p.IsDefault == 1 && p.Uid > 0 && p.Tid > 0 {
_ = models.SetDefaultTenant(p.Uid, p.Tid)
}
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "success"}
_ = c.ServeJSON()
}
// DeleteTenantUser 删除绑定
// DELETE /platform/tenantUser/delete/:id
func (c *PlatformTenantUserController) DeleteTenantUser() {
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.ServeJSON()
return
}
if err := models.UnbindTenantUser(id); 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"}
_ = c.ServeJSON()
}
func (c *PlatformTenantUserController) parsePayload() (tenantUserPayload, bool) {
var p tenantUserPayload
raw, _ := io.ReadAll(c.Ctx.Request.Body)
if err := json.Unmarshal(raw, &p); err != nil {
c.Data["json"] = map[string]interface{}{"code": 400, "msg": "参数错误"}
_ = c.ServeJSON()
return tenantUserPayload{}, false
}
return p, true
}
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)).
Filter("tid", tid).
Filter("uid", uid).
Count()
if err != nil {
return 0, err
}
if cnt == 0 {
return uid, nil
}
}
return 0, errors.New("uid collision")
}
+100
View File
@@ -0,0 +1,100 @@
package controllers
import (
"encoding/json"
"io"
"math/rand"
"strings"
"time"
"server/models"
beego "github.com/beego/beego/v2/server/web"
)
// PlatformUserController 平台端用户相关(简化:当前用户信息落在 yz_tenant_user
type PlatformUserController struct {
beego.Controller
}
type addUserPayload struct {
Tid uint64 `json:"tid"`
Account string `json:"account"`
Password string `json:"password"`
Name string `json:"name"`
Phone string `json:"phone"`
Email string `json:"email"`
Status *int8 `json:"status"`
Remark *string `json:"remark"`
}
// AddUser 添加用户(绑定到租户)
// POST /platform/addUser
func (c *PlatformUserController) AddUser() {
var p addUserPayload
// 兼容 JSON body
raw, _ := io.ReadAll(c.Ctx.Request.Body)
if err := json.Unmarshal(raw, &p); err != nil {
c.Data["json"] = map[string]interface{}{"code": 400, "msg": "参数错误"}
_ = c.ServeJSON()
return
}
p.Account = strings.TrimSpace(p.Account)
p.Password = strings.TrimSpace(p.Password)
p.Name = strings.TrimSpace(p.Name)
p.Phone = strings.TrimSpace(p.Phone)
p.Email = strings.TrimSpace(p.Email)
if p.Tid == 0 {
c.Data["json"] = map[string]interface{}{"code": 400, "msg": "tid 不能为空"}
_ = c.ServeJSON()
return
}
if p.Account == "" {
c.Data["json"] = map[string]interface{}{"code": 400, "msg": "account 不能为空"}
_ = c.ServeJSON()
return
}
if p.Password == "" {
c.Data["json"] = map[string]interface{}{"code": 400, "msg": "password 不能为空"}
_ = c.ServeJSON()
return
}
status := int8(1)
if p.Status != nil {
status = *p.Status
}
// 生成 uid8位数字即可(10000000~99999999
rand.Seed(time.Now().UnixNano())
var uid uint64
for i := 0; i < 5; i++ {
uid = uint64(10000000 + rand.Intn(90000000))
// 尝试写入(若冲突由唯一索引兜底,外层再重试)
account := &p.Account
name := &p.Name
phone := &p.Phone
email := &p.Email
password := &p.Password
_, err := models.BindTenantUser(p.Tid, uid, account, name, phone, email, password, 0, status, p.Remark)
if err == nil {
c.Data["json"] = map[string]interface{}{
"code": 200,
"msg": "success",
"data": map[string]interface{}{"tid": p.Tid, "uid": uid},
}
_ = c.ServeJSON()
return
}
// 轻量重试
time.Sleep(5 * time.Millisecond)
}
c.Data["json"] = map[string]interface{}{"code": 500, "msg": "添加失败,请重试"}
_ = c.ServeJSON()
}