chore: initial commit of ai site platform

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
whm
2026-07-31 10:31:17 +08:00
commit 4ca82fb58a
203 changed files with 45745 additions and 0 deletions

View File

@@ -0,0 +1,319 @@
package handler
import (
"encoding/json"
"net/http"
"strconv"
"aijianzhan/platform/internal/authx"
"aijianzhan/platform/internal/logic/applogic"
"aijianzhan/platform/internal/svc"
"github.com/zeromicro/go-zero/rest/httpx"
"github.com/zeromicro/go-zero/rest/pathvar"
)
func platformListTenantsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
l := applogic.NewPlatformLogic(applogic.NewAuthLogic(r.Context(), svcCtx))
list, err := l.ListTenants()
if err != nil {
authx.WriteError(w, http.StatusForbidden, err.Error())
return
}
httpx.OkJson(w, map[string]any{"items": list})
}
}
func platformCreateTenantHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var body struct {
Name string `json:"name"`
Slug string `json:"slug"`
AdminPhone string `json:"admin_phone"`
WithAdminInvite *bool `json:"with_admin_invite"`
}
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
authx.WriteError(w, http.StatusBadRequest, err.Error())
return
}
withInvite := false
if body.WithAdminInvite != nil {
withInvite = *body.WithAdminInvite
}
l := applogic.NewPlatformLogic(applogic.NewAuthLogic(r.Context(), svcCtx))
res, err := l.CreateTenant(body.Name, body.Slug, withInvite, body.AdminPhone)
if err != nil {
authx.WriteError(w, http.StatusBadRequest, err.Error())
return
}
httpx.OkJson(w, res)
}
}
func platformUpdateTenantHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
id, _ := strconv.ParseInt(pathvar.Vars(r)["id"], 10, 64)
var body struct {
Name string `json:"name"`
Slug string `json:"slug"`
}
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
authx.WriteError(w, http.StatusBadRequest, err.Error())
return
}
l := applogic.NewPlatformLogic(applogic.NewAuthLogic(r.Context(), svcCtx))
t, err := l.UpdateTenant(id, body.Name, body.Slug)
if err != nil {
authx.WriteError(w, http.StatusBadRequest, err.Error())
return
}
httpx.OkJson(w, t)
}
}
func platformAdminInviteHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
id, _ := strconv.ParseInt(pathvar.Vars(r)["id"], 10, 64)
l := applogic.NewPlatformLogic(applogic.NewAuthLogic(r.Context(), svcCtx))
inv, err := l.IssueAdminInvite(id)
if err != nil {
authx.WriteError(w, http.StatusBadRequest, err.Error())
return
}
httpx.OkJson(w, inv)
}
}
func platformAdminAccountHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
id, _ := strconv.ParseInt(pathvar.Vars(r)["id"], 10, 64)
var body struct {
Phone string `json:"phone"`
}
_ = json.NewDecoder(r.Body).Decode(&body)
l := applogic.NewPlatformLogic(applogic.NewAuthLogic(r.Context(), svcCtx))
acc, err := l.IssueAdminAccount(id, body.Phone)
if err != nil {
authx.WriteError(w, http.StatusBadRequest, err.Error())
return
}
_ = svcCtx.Audit.Log(r.Context(), id, authx.UserID(r.Context()), "platform.admin_account", acc.Username)
httpx.OkJson(w, map[string]any{"admin_account": acc})
}
}
func platformListAdminsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
id, _ := strconv.ParseInt(pathvar.Vars(r)["id"], 10, 64)
l := applogic.NewPlatformLogic(applogic.NewAuthLogic(r.Context(), svcCtx))
items, err := l.ListCompanyAdmins(id)
if err != nil {
authx.WriteError(w, http.StatusBadRequest, err.Error())
return
}
httpx.OkJson(w, map[string]any{"items": items})
}
}
func platformUpdateAdminHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
tid, _ := strconv.ParseInt(pathvar.Vars(r)["id"], 10, 64)
uid, _ := strconv.ParseInt(pathvar.Vars(r)["uid"], 10, 64)
var body struct {
ResetPassword *bool `json:"reset_password"`
Password string `json:"password"`
Phone *string `json:"phone"`
DisableUsernameLogin *bool `json:"disable_username_login"`
}
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
authx.WriteError(w, http.StatusBadRequest, err.Error())
return
}
reset := body.ResetPassword != nil && *body.ResetPassword
if !reset && body.Phone == nil && body.DisableUsernameLogin == nil {
authx.WriteError(w, http.StatusBadRequest, "请指定重置密码、更新手机号或禁用用户名登录")
return
}
l := applogic.NewPlatformLogic(applogic.NewAuthLogic(r.Context(), svcCtx))
acc, err := l.UpdateCompanyAdmin(tid, uid, reset, body.Password, body.Phone, body.DisableUsernameLogin)
if err != nil {
authx.WriteError(w, http.StatusBadRequest, err.Error())
return
}
_ = svcCtx.Audit.Log(r.Context(), tid, authx.UserID(r.Context()), "platform.update_admin", acc.Username)
httpx.OkJson(w, map[string]any{"admin_account": acc})
}
}
func platformEnterTenantHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
id, _ := strconv.ParseInt(pathvar.Vars(r)["id"], 10, 64)
l := applogic.NewPlatformLogic(applogic.NewAuthLogic(r.Context(), svcCtx))
resp, err := l.EnterTenant(id)
if err != nil {
authx.WriteError(w, http.StatusBadRequest, err.Error())
return
}
_ = svcCtx.Audit.Log(r.Context(), id, resp.UserID, "platform.enter_tenant", resp.Message)
httpx.OkJson(w, resp)
}
}
func platformExitTenantHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
l := applogic.NewPlatformLogic(applogic.NewAuthLogic(r.Context(), svcCtx))
resp, err := l.ExitTenant()
if err != nil {
authx.WriteError(w, http.StatusBadRequest, err.Error())
return
}
_ = svcCtx.Audit.Log(r.Context(), 0, resp.UserID, "platform.exit_tenant", resp.Message)
httpx.OkJson(w, resp)
}
}
func platformPermModulesHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if !authx.IsPlatformAdmin(authx.Role(r.Context())) {
authx.WriteError(w, http.StatusForbidden, "需要超级管理员")
return
}
httpx.OkJson(w, map[string]any{
"modules": authx.PermModules(),
"catalog": authx.CompanyPermCatalog(),
"platform": []string{authx.Perm管理租户},
})
}
}
func platformGetTenantPermsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
id, _ := strconv.ParseInt(pathvar.Vars(r)["id"], 10, 64)
l := applogic.NewPlatformLogic(applogic.NewAuthLogic(r.Context(), svcCtx))
perms, err := l.GetTenantPerms(id)
if err != nil {
authx.WriteError(w, http.StatusBadRequest, err.Error())
return
}
httpx.OkJson(w, map[string]any{"tenant_id": id, "permissions": perms, "total": len(authx.CompanyPermCatalog())})
}
}
func platformSetTenantPermsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
id, _ := strconv.ParseInt(pathvar.Vars(r)["id"], 10, 64)
var body struct {
Permissions []string `json:"permissions"`
}
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
authx.WriteError(w, http.StatusBadRequest, err.Error())
return
}
l := applogic.NewPlatformLogic(applogic.NewAuthLogic(r.Context(), svcCtx))
perms, err := l.SetTenantPerms(id, body.Permissions)
if err != nil {
authx.WriteError(w, http.StatusBadRequest, err.Error())
return
}
httpx.OkJson(w, map[string]any{"tenant_id": id, "permissions": perms, "total": len(authx.CompanyPermCatalog())})
}
}
func companyEntitlementsHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
l := applogic.NewAuthLogic(r.Context(), svcCtx)
perms, modules, err := l.CompanyEntitlements()
if err != nil {
authx.WriteError(w, http.StatusForbidden, err.Error())
return
}
httpx.OkJson(w, map[string]any{"permissions": perms, "modules": modules})
}
}
func memberListHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
l := applogic.NewMemberLogic(applogic.NewAuthLogic(r.Context(), svcCtx))
list, err := l.List()
if err != nil {
authx.WriteError(w, http.StatusBadRequest, err.Error())
return
}
items := make([]map[string]any, 0, len(list))
for _, u := range list {
items = append(items, map[string]any{
"user_id": u.UserID,
"username": u.Username,
"phone": u.Phone,
"display_name": u.DisplayName,
"role": u.Role,
"org_unit_id": u.OrgUnitID,
"status": u.Status,
"created_at": u.CreatedAt,
})
}
httpx.OkJson(w, map[string]any{"items": items})
}
}
func memberCreateHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var body struct {
Password string `json:"password"`
DisplayName string `json:"display_name"`
Role string `json:"role"`
OrgUnitID int64 `json:"org_unit_id"`
}
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
authx.WriteError(w, http.StatusBadRequest, err.Error())
return
}
l := applogic.NewMemberLogic(applogic.NewAuthLogic(r.Context(), svcCtx))
u, plain, err := l.Create(body.Password, body.DisplayName, body.Role, body.OrgUnitID)
if err != nil {
authx.WriteError(w, http.StatusBadRequest, err.Error())
return
}
_ = svcCtx.Audit.Log(r.Context(), authx.TenantID(r.Context()), authx.UserID(r.Context()),
"member.create", "创建成员 "+u.Username)
httpx.OkJson(w, map[string]any{
"user_id": u.UserID,
"username": u.Username,
"display_name": u.DisplayName,
"role": u.Role,
"org_unit_id": u.OrgUnitID,
"status": u.Status,
"password": plain,
})
}
}
func memberUpdateHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
id, _ := strconv.ParseInt(pathvar.Vars(r)["id"], 10, 64)
var body struct {
Role string `json:"role"`
OrgUnitID int64 `json:"org_unit_id"`
Status string `json:"status"`
}
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
authx.WriteError(w, http.StatusBadRequest, err.Error())
return
}
l := applogic.NewMemberLogic(applogic.NewAuthLogic(r.Context(), svcCtx))
u, err := l.Update(id, body.Role, body.OrgUnitID, body.Status)
if err != nil {
authx.WriteError(w, http.StatusBadRequest, err.Error())
return
}
httpx.OkJson(w, map[string]any{
"user_id": u.UserID,
"username": u.Username,
"display_name": u.DisplayName,
"role": u.Role,
"org_unit_id": u.OrgUnitID,
"status": u.Status,
})
}
}