commit 20ed44aa743de11d391659cd5522071772984334 Author: RichZDS <3388214266@qq.com> Date: Sun Jan 18 18:20:40 2026 +0800 init diff --git a/Backend/.gitattributes b/Backend/.gitattributes new file mode 100644 index 0000000..1fbf887 --- /dev/null +++ b/Backend/.gitattributes @@ -0,0 +1 @@ +* linguist-language=GO \ No newline at end of file diff --git a/Backend/.gitignore b/Backend/.gitignore new file mode 100644 index 0000000..18646b6 --- /dev/null +++ b/Backend/.gitignore @@ -0,0 +1,19 @@ +.buildpath +.hgignore.swp +.project +.orig +.swp +.idea/ +.settings/ +.vscode/ +bin/ +**/.DS_Store +gf +main +main.exe +output/ +manifest/output/ +temp/ +temp.yaml +bin +**/config/config.yaml \ No newline at end of file diff --git a/Backend/Makefile b/Backend/Makefile new file mode 100644 index 0000000..2a6e6e9 --- /dev/null +++ b/Backend/Makefile @@ -0,0 +1,7 @@ +ROOT_DIR = $(shell pwd) +NAMESPACE = "default" +DEPLOY_NAME = "template-single" +DOCKER_NAME = "template-single" + +include ./hack/hack-cli.mk +include ./hack/hack.mk \ No newline at end of file diff --git a/Backend/README.MD b/Backend/README.MD new file mode 100644 index 0000000..d36cedd --- /dev/null +++ b/Backend/README.MD @@ -0,0 +1,4 @@ +# GoFrame Template For SingleRepo + +Quick Start: +- https://goframe.org/quick \ No newline at end of file diff --git a/Backend/api/containment/containment.go b/Backend/api/containment/containment.go new file mode 100644 index 0000000..c9ac16e --- /dev/null +++ b/Backend/api/containment/containment.go @@ -0,0 +1,18 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package containment + +import ( + "context" + + "leke/api/containment/v1" +) + +type IContainmentV1 interface { + ContainmentRepoList(ctx context.Context, req *v1.ContainmentRepoListReq) (res *v1.ContainmentRepoListRes, err error) + ContainmentRepoView(ctx context.Context, req *v1.ContainmentRepoViewReq) (res *v1.ContainmentRepoViewRes, err error) + ContainmentRepoUpdate(ctx context.Context, req *v1.ContainmentRepoUpdateReq) (res *v1.ContainmentRepoUpdateRes, err error) + ContainmentRepoDelete(ctx context.Context, req *v1.ContainmentRepoDeleteReq) (res *v1.ContainmentRepoDeleteRes, err error) +} diff --git a/Backend/api/containment/v1/containment.go b/Backend/api/containment/v1/containment.go new file mode 100644 index 0000000..e2613f4 --- /dev/null +++ b/Backend/api/containment/v1/containment.go @@ -0,0 +1,71 @@ +package v1 + +import ( + "leke/internal/model" + "leke/internal/model/response" + + "github.com/gogf/gf/v2/frame/g" +) + +// 单条数据结构 +type ContainmentRepoInfo struct { + Id uint64 `json:"id" orm:"id" description:"primary key(大于0为修改,其他为新增)"` + TerminalId int `json:"terminalId" orm:"terminal_id" description:"terminal (散逸端)"` + Abnormal string `json:"abnormal" orm:"abnormal" description:"number of contained anomalies (收容异常的数量)"` + AnomalyName string `json:"anomalyName" orm:"anomaly_name" description:"name of the anomaly (异常体的名字)"` + AgentName string `json:"agentName" orm:"agent_name" description:"agent (特工)"` + RepoName string `json:"repoName" orm:"repo_name" description:"containment repository name or code (收容库)"` +} + +// List +type ContainmentRepoListReq struct { + response.PageResult + g.Meta `path:"/containment/list" method:"get" tags:"收容库" summary:"收容库列表"` + + // 查询条件(全部可选) + TerminalId int `json:"terminalId" orm:"terminal_id" description:"terminal (散逸端)"` + AnomalyName string `json:"anomalyName" orm:"anomaly_name" description:"anomaly name"` + AgentName string `json:"agentName" orm:"agent_name" description:"agent name"` + RepoName string `json:"repoName" orm:"repo_name" description:"containment repo name"` +} + +type ContainmentRepoListRes struct { + response.PageResult + List []*model.ContainmentRepo `json:"list"` +} + +// View +type ContainmentRepoViewReq struct { + g.Meta `path:"/containment/view" method:"get" tags:"收容库" summary:"收容库详情"` + + Id uint64 `json:"id" orm:"id" description:"primary key"` +} + +type ContainmentRepoViewRes struct { + ContainmentRepoInfo +} + +// Update(id>0 为修改,id<=0 或不传为新增) +type ContainmentRepoUpdateReq struct { + g.Meta `path:"/containment/update" method:"post" tags:"收容库" summary:"创建或更新收容库"` + + Id uint64 `json:"id" orm:"id" description:"primary key,大于0为修改,其他为新增"` + TerminalId int `json:"terminalId" orm:"terminal_id" description:"terminal (散逸端)"` + Abnormal string `json:"abnormal" orm:"abnormal" description:"number of contained anomalies"` + AnomalyName string `json:"anomalyName" orm:"anomaly_name" description:"anomaly name"` + AgentName string `json:"agentName" orm:"agent_name" description:"agent name"` + RepoName string `json:"repoName" orm:"repo_name" description:"containment repo name"` +} + +type ContainmentRepoUpdateRes struct { + Id uint64 `json:"id" orm:"id" description:"primary key"` +} + +// Delete +type ContainmentRepoDeleteReq struct { + g.Meta `path:"/containment/delete" method:"delete" tags:"收容库" summary:"收容库删除"` + + Id uint64 `json:"id" orm:"id" description:"primary key"` +} + +type ContainmentRepoDeleteRes struct{} diff --git a/Backend/api/department/department.go b/Backend/api/department/department.go new file mode 100644 index 0000000..d475020 --- /dev/null +++ b/Backend/api/department/department.go @@ -0,0 +1,19 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package department + +import ( + "context" + + "leke/api/department/v1" +) + +type IDepartmentV1 interface { + DepartmentList(ctx context.Context, req *v1.DepartmentListReq) (res *v1.DepartmentListRes, err error) + DepartmentView(ctx context.Context, req *v1.DepartmentViewReq) (res *v1.DepartmentViewRes, err error) + DepartmentCreate(ctx context.Context, req *v1.DepartmentCreateReq) (res *v1.DepartmentCreateRes, err error) + DepartmentUpdate(ctx context.Context, req *v1.DepartmentUpdateReq) (res *v1.DepartmentUpdateRes, err error) + DepartmentDelete(ctx context.Context, req *v1.DepartmentDeleteReq) (res *v1.DepartmentDeleteRes, err error) +} diff --git a/Backend/api/department/v1/department.go b/Backend/api/department/v1/department.go new file mode 100644 index 0000000..7912913 --- /dev/null +++ b/Backend/api/department/v1/department.go @@ -0,0 +1,90 @@ +package v1 + +import ( + "leke/internal/model/response" + + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gtime" +) + +// Department 三角机构分部信息 +type Department struct { + Id uint64 `json:"id" description:"自增主键"` + UserId uint64 `json:"userId" description:"所属用户ID(对应 users.id)"` + BranchName string `json:"branchName" description:"分部名称"` + TerminalCount int `json:"terminalCount" description:"分部散逸端的数量"` + Weather string `json:"weather" description:"分部当前天气/气候描述"` + ManagerName string `json:"managerName" description:"分部经理名称"` + Location string `json:"location" description:"分部地址"` + CreatedAt *gtime.Time `json:"createdAt" description:"创建时间"` + UpdatedAt *gtime.Time `json:"updatedAt" description:"更新时间"` +} + +// DepartmentListReq 部门列表请求参数 +type DepartmentListReq struct { + response.PageResult + g.Meta `path:"/department/list" method:"get" tags:"部门" summary:"部门列表"` + BranchName string `json:"branchName" description:"分部名称"` + ManagerName string `json:"managerName" description:"分部经理名称"` + UserId uint64 `json:"userId" description:"所属用户ID"` +} + +// DepartmentListRes 部门列表响应参数 +type DepartmentListRes struct { + response.PageResult + List []*Department `json:"list"` +} + +// DepartmentViewReq 部门详情请求参数 +type DepartmentViewReq struct { + g.Meta `path:"/department/view" method:"get" tags:"部门" summary:"部门详情"` + Id uint64 `json:"id" v:"required#部门ID不能为空"` +} + +// DepartmentViewRes 部门详情响应参数 +type DepartmentViewRes struct { + Department +} + +// DepartmentCreateReq 部门创建请求参数 +type DepartmentCreateReq struct { + g.Meta `path:"/department/create" method:"post" tags:"部门" summary:"创建部门"` + UserId uint64 `json:"userId" v:"required#所属用户ID不能为空"` + BranchName string `json:"branchName" v:"required#分部名称不能为空"` + TerminalCount int `json:"terminalCount" description:"分部散逸端的数量"` + Weather string `json:"weather" description:"分部当前天气/气候描述"` + ManagerName string `json:"managerName" description:"分部经理名称"` + Location string `json:"location" description:"分部地址"` +} + +// DepartmentCreateRes 部门创建响应参数 +type DepartmentCreateRes struct { + Id uint64 `json:"id"` +} + +// DepartmentUpdateReq 部门更新请求参数 +type DepartmentUpdateReq struct { + g.Meta `path:"/department/update" method:"put" tags:"部门" summary:"更新部门"` + Id uint64 `json:"id" v:"required#部门ID不能为空"` + UserId uint64 `json:"userId" v:"required#所属用户ID不能为空"` + BranchName string `json:"branchName" v:"required#分部名称不能为空"` + TerminalCount int `json:"terminalCount" description:"分部散逸端的数量"` + Location string `json:"location" description:"分部地址"` + Weather string `json:"weather" description:"分部当前天气/气候描述"` + ManagerName string `json:"managerName" description:"分部经理名称"` +} + +// DepartmentUpdateRes 部门更新响应参数 +type DepartmentUpdateRes struct { + Id uint64 `json:"id"` +} + +// DepartmentDeleteReq 部门删除请求参数 +type DepartmentDeleteReq struct { + g.Meta `path:"/department/delete" method:"delete" tags:"部门" summary:"删除部门"` + Id uint64 `json:"id" v:"required#部门ID不能为空"` +} + +// DepartmentDeleteRes 部门删除响应参数 +type DepartmentDeleteRes struct { +} diff --git a/Backend/api/forum/forum.if.go b/Backend/api/forum/forum.if.go new file mode 100644 index 0000000..e4ca6bc --- /dev/null +++ b/Backend/api/forum/forum.if.go @@ -0,0 +1,24 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package forum + +import ( + "context" + + "leke/api/forum/v1" +) + +type IForumV1 interface { + ForumCommentsCreate(ctx context.Context, req *v1.ForumCommentsCreateReq) (res *v1.ForumCommentsCreateRes, err error) + ForumCommentsUpdate(ctx context.Context, req *v1.ForumCommentsUpdateReq) (res *v1.ForumCommentsUpdateRes, err error) + ForumCommentsDelete(ctx context.Context, req *v1.ForumCommentsDeleteReq) (res *v1.ForumCommentsDeleteRes, err error) + ForumCommentsView(ctx context.Context, req *v1.ForumCommentsViewReq) (res *v1.ForumCommentsViewRes, err error) + ForumCommentsList(ctx context.Context, req *v1.ForumCommentsListReq) (res *v1.ForumCommentsListRes, err error) + ForumPostsCreate(ctx context.Context, req *v1.ForumPostsCreateReq) (res *v1.ForumPostsCreateRes, err error) + ForumPostsUpdate(ctx context.Context, req *v1.ForumPostsUpdateReq) (res *v1.ForumPostsUpdateRes, err error) + ForumPostsDelete(ctx context.Context, req *v1.ForumPostsDeleteReq) (res *v1.ForumPostsDeleteRes, err error) + ForumPostsView(ctx context.Context, req *v1.ForumPostsViewReq) (res *v1.ForumPostsViewRes, err error) + ForumPostsList(ctx context.Context, req *v1.ForumPostsListReq) (res *v1.ForumPostsListRes, err error) +} diff --git a/Backend/api/forum/v1/forum_comments.go b/Backend/api/forum/v1/forum_comments.go new file mode 100644 index 0000000..5f3c67c --- /dev/null +++ b/Backend/api/forum/v1/forum_comments.go @@ -0,0 +1,84 @@ +package v1 + +import ( + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gtime" + "leke/internal/model/response" +) + +// ForumCommentsCreateReq 创建评论请求 +type ForumCommentsCreateReq struct { + g.Meta `path:"/forum/comments/create" method:"post" tags:"论坛评论" summary:"创建评论"` + UserId uint64 `json:"userId" description:"评论发布者ID"` + PostId uint64 `json:"postId" description:"所属帖子ID"` + ParentId uint64 `json:"parentId" description:"父评论ID"` + Content string `json:"content" description:"评论内容"` + Status string `json:"status" description:"评论状态"` +} + +// ForumCommentsCreateRes 创建评论响应 +type ForumCommentsCreateRes struct { + Id uint64 `json:"id" description:"评论ID"` +} + +// ForumCommentsUpdateReq 更新评论请求 +type ForumCommentsUpdateReq struct { + g.Meta `path:"/forum/comments/update" method:"put" tags:"论坛评论" summary:"更新评论"` + Id uint64 `json:"id" description:"评论ID"` + UserId uint64 `json:"userId,omitempty" description:"评论发布者ID"` + PostId uint64 `json:"postId,omitempty" description:"所属帖子ID"` + ParentId uint64 `json:"parentId,omitempty" description:"父评论ID"` + Content string `json:"content,omitempty" description:"评论内容"` + Status string `json:"status,omitempty" description:"评论状态"` +} + +// ForumCommentsUpdateRes 更新评论响应 +type ForumCommentsUpdateRes struct { + Id uint64 `json:"id" description:"评论ID"` +} + +// ForumCommentsDeleteReq 删除评论请求 +type ForumCommentsDeleteReq struct { + g.Meta `path:"/forum/comments/delete" method:"delete" tags:"论坛评论" summary:"删除评论"` + Id uint64 `json:"id" description:"评论ID"` +} + +// ForumCommentsDeleteRes 删除评论响应 +type ForumCommentsDeleteRes struct { +} + +// ForumCommentsViewReq 查看评论请求 +type ForumCommentsViewReq struct { + g.Meta `path:"/forum/comments/view" method:"get" tags:"论坛评论" summary:"查看评论"` + Id uint64 `json:"id" description:"评论ID"` +} + +// ForumCommentsViewRes 查看评论响应 +type ForumCommentsViewRes struct { + Id uint64 `json:"id" description:"评论ID"` + UserId uint64 `json:"userId" description:"评论发布者ID"` + PostId uint64 `json:"postId" description:"所属帖子ID"` + ParentId uint64 `json:"parentId" description:"父评论ID"` + Content string `json:"content" description:"评论内容"` + Status string `json:"status" description:"评论状态"` + LikeCount uint `json:"likeCount" description:"点赞数"` + ReplyCount uint `json:"replyCount" description:"回复数"` + CreatedAt *gtime.Time `json:"createdAt" description:"评论创建时间"` + UpdatedAt *gtime.Time `json:"updatedAt" description:"评论更新时间"` +} + +// ForumCommentsListReq 评论列表请求 +type ForumCommentsListReq struct { + response.PageResult + g.Meta `path:"/forum/comments/list" method:"get" tags:"论坛评论" summary:"评论列表"` + UserId uint64 `json:"userId,omitempty" description:"评论发布者ID"` + PostId uint64 `json:"postId,omitempty" description:"所属帖子ID"` + ParentId uint64 `json:"parentId,omitempty" description:"父评论ID"` + Status string `json:"status,omitempty" description:"评论状态"` +} + +// ForumCommentsListRes 评论列表响应 +type ForumCommentsListRes struct { + response.PageResult + List []*ForumCommentsViewRes `json:"list" description:"评论列表"` +} diff --git a/Backend/api/forum/v1/forum_posts.go b/Backend/api/forum/v1/forum_posts.go new file mode 100644 index 0000000..92e81d3 --- /dev/null +++ b/Backend/api/forum/v1/forum_posts.go @@ -0,0 +1,84 @@ +package v1 + +import ( + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gtime" + "leke/internal/model/response" +) + +// ForumPostsCreateReq 创建帖子请求 +type ForumPostsCreateReq struct { + g.Meta `path:"/forum/posts/create" method:"post" tags:"论坛帖子" summary:"创建帖子"` + UserId uint64 `json:"userId" description:"发帖用户ID"` + Title string `json:"title" description:"帖子标题"` + Content string `json:"content" description:"帖子正文"` + CoverImage string `json:"coverImage" description:"帖子封面图URL"` + Status string `json:"status" description:"帖子状态"` +} + +// ForumPostsCreateRes 创建帖子响应 +type ForumPostsCreateRes struct { + Id uint64 `json:"id" description:"帖子ID"` +} + +// ForumPostsUpdateReq 更新帖子请求 +type ForumPostsUpdateReq struct { + g.Meta `path:"/forum/posts/update" method:"put" tags:"论坛帖子" summary:"更新帖子"` + Id uint64 `json:"id" description:"帖子ID"` + UserId uint64 `json:"userId,omitempty" description:"发帖用户ID"` + Title string `json:"title,omitempty" description:"帖子标题"` + Content string `json:"content,omitempty" description:"帖子正文"` + CoverImage string `json:"coverImage,omitempty" description:"帖子封面图URL"` + Status string `json:"status,omitempty" description:"帖子状态"` +} + +// ForumPostsUpdateRes 更新帖子响应 +type ForumPostsUpdateRes struct { + Id uint64 `json:"id" description:"帖子ID"` +} + +// ForumPostsDeleteReq 删除帖子请求 +type ForumPostsDeleteReq struct { + g.Meta `path:"/forum/posts/delete" method:"delete" tags:"论坛帖子" summary:"删除帖子"` + Id uint64 `json:"id" description:"帖子ID"` +} + +// ForumPostsDeleteRes 删除帖子响应 +type ForumPostsDeleteRes struct { +} + +// ForumPostsViewReq 查看帖子请求 +type ForumPostsViewReq struct { + g.Meta `path:"/forum/posts/view" method:"get" tags:"论坛帖子" summary:"查看帖子"` + Id uint64 `json:"id" description:"帖子ID"` +} + +// ForumPostsViewRes 查看帖子响应 +type ForumPostsViewRes struct { + Id uint64 `json:"id" description:"帖子ID"` + UserId uint64 `json:"userId" description:"发帖用户ID"` + Title string `json:"title" description:"帖子标题"` + Content string `json:"content" description:"帖子正文"` + CoverImage string `json:"coverImage" description:"帖子封面图URL"` + Status string `json:"status" description:"帖子状态"` + ViewCount uint `json:"viewCount" description:"浏览量"` + LikeCount uint `json:"likeCount" description:"点赞数"` + CommentCount uint `json:"commentCount" description:"评论数"` + CreatedAt *gtime.Time `json:"createdAt" description:"发帖时间"` + UpdatedAt *gtime.Time `json:"updatedAt" description:"更新时间"` +} + +// ForumPostsListReq 帖子列表请求 +type ForumPostsListReq struct { + response.PageResult + g.Meta `path:"/forum/posts/list" method:"get" tags:"论坛帖子" summary:"帖子列表"` + UserId uint64 `json:"userId,omitempty" description:"发帖用户ID"` + Title string `json:"title,omitempty" description:"帖子标题"` + Status string `json:"status,omitempty" description:"帖子状态"` +} + +// ForumPostsListRes 帖子列表响应 +type ForumPostsListRes struct { + response.PageResult + List []*ForumPostsViewRes `json:"list" description:"帖子列表"` +} diff --git a/Backend/api/login/login.go b/Backend/api/login/login.go new file mode 100644 index 0000000..fa50815 --- /dev/null +++ b/Backend/api/login/login.go @@ -0,0 +1,20 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package login + +import ( + "context" + + "leke/api/login/v1" +) + +type ILoginV1 interface { + Login(ctx context.Context, req *v1.LoginReq) (res *v1.LoginRes, err error) + Register(ctx context.Context, req *v1.RegisterReq) (res *v1.RegisterRes, err error) + Logout(ctx context.Context, req *v1.LogoutReq) (res *v1.LogoutRes, err error) + LoginByEmail(ctx context.Context, req *v1.LoginByEmailReq) (res *v1.LoginByEmailRes, err error) + RegisterByEmail(ctx context.Context, req *v1.RegisterByEmailReq) (res *v1.RegisterByEmailRes, err error) + SendVerificationCode(ctx context.Context, req *v1.SendVerificationCodeReq) (res *v1.SendVerificationCodeRes, err error) +} diff --git a/Backend/api/login/v1/login.go b/Backend/api/login/v1/login.go new file mode 100644 index 0000000..2ba22d5 --- /dev/null +++ b/Backend/api/login/v1/login.go @@ -0,0 +1,66 @@ +// LoginReq 登录请求 +package v1 + +import ( + "github.com/gogf/gf/v2/frame/g" +) + +type LoginReq struct { + g.Meta `path:"/login" method:"post" tags:"登录" summary:"用户登录"` + Account string `json:"account" v:"required#账号不能为空"` + Password string `json:"password" v:"required#密码不能为空"` +} + +type LoginRes struct { + Token string `json:"token" dc:"JWT token for authentication"` + Account string `json:"account"` +} + +type RegisterReq struct { + g.Meta `path:"/register" method:"post" tags:"注册" summary:"用户注册"` + Account string `json:"account" v:"required#账号不能为空"` + Password string `json:"password" v:"required#密码不能为空"` +} + +type RegisterRes struct { + Account string `json:"account"` +} + +type LogoutReq struct { + g.Meta `path:"/logout" method:"post" tags:"登出" summary:"用户登出"` +} +type LogoutRes struct { +} + +// 用邮箱登录(包含验证码) +type LoginByEmailReq struct { + g.Meta `path:"/login/email" method:"post" tags:"登录" summary:"用户邮箱登录"` + Email string `json:"email" v:"email#邮箱格式不正确"` + Code string `json:"code" v:"required#验证码不能为空"` +} + +type LoginByEmailRes struct { + Token string `json:"token" dc:"JWT token for authentication"` + Email string `json:"email"` +} + +// 通过邮箱注册 +type RegisterByEmailReq struct { + g.Meta `path:"/register/email" method:"post" tags:"注册" summary:"用户邮箱注册"` + Email string `json:"email" v:"email#邮箱格式不正确"` + Code string `json:"code" v:"required#验证码不能为空"` +} + +type RegisterByEmailRes struct { + Email string `json:"email"` +} + +// SendVerificationCodeReq 发送验证码 +type SendVerificationCodeReq struct { + g.Meta `path:"/email/send-code" method:"post" tags:"邮箱" summary:"发送验证码"` + Email string `json:"email" v:"email#邮箱格式不正确"` +} + +type SendVerificationCodeRes struct { + Success bool `json:"success"` +} diff --git a/Backend/api/room/room.go b/Backend/api/room/room.go new file mode 100644 index 0000000..9cc4a15 --- /dev/null +++ b/Backend/api/room/room.go @@ -0,0 +1,20 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package room + +import ( + "context" + + "leke/api/room/v1" +) + +type IRoomV1 interface { + RoomList(ctx context.Context, req *v1.RoomListReq) (res *v1.RoomListRes, err error) + RoomView(ctx context.Context, req *v1.RoomViewReq) (res *v1.RoomViewRes, err error) + RoomCreate(ctx context.Context, req *v1.RoomCreateReq) (res *v1.RoomCreateRes, err error) + RoomUpdate(ctx context.Context, req *v1.RoomUpdateReq) (res *v1.RoomUpdateRes, err error) + RoomDelete(ctx context.Context, req *v1.RoomDeleteReq) (res *v1.RoomDeleteRes, err error) + RoomJoin(ctx context.Context, req *v1.RoomJoinReq) (res *v1.RoomJoinRes, err error) +} diff --git a/Backend/api/room/v1/room.go b/Backend/api/room/v1/room.go new file mode 100644 index 0000000..d4df1f1 --- /dev/null +++ b/Backend/api/room/v1/room.go @@ -0,0 +1,91 @@ +package v1 + +import ( + "leke/internal/model" + "leke/internal/model/response" + + "github.com/gogf/gf/v2/frame/g" +) + +// RoomListReq 房间列表请求 +type RoomListReq struct { + response.PageResult + g.Meta `path:"/room/list" method:"get" tags:"房间" summary:"房间列表"` + RoomCode string `json:"room_code" orm:"room_code" description:"房间号"` + RoomName string `json:"room_name" orm:"room_name" description:"房间名称"` + HostId uint64 `json:"host_id" orm:"host_id" description:"主持人用户ID"` + Status int `json:"status" orm:"status" description:"房间状态:0未开始 1进行中 2已结束 3已关闭"` + SystemName string `json:"system_name" orm:"system_name" description:"规则系统,如COC、DND5E"` +} + +// RoomListRes 房间列表响应 +type RoomListRes struct { + response.PageResult + Rooms []*model.RoomParams `json:"rooms"` +} + +// RoomViewReq 房间详情请求 +type RoomViewReq struct { + g.Meta `path:"/room/view" method:"get" tags:"房间" summary:"房间详情"` + Id uint64 `json:"id" orm:"id" description:"房间ID"` + RoomCode string `json:"room_code" orm:"room_code" description:"房间号"` +} + +// RoomViewRes 房间详情响应 +type RoomViewRes struct { + model.RoomView +} + +// RoomCreateReq 创建房间请求 +type RoomCreateReq struct { + g.Meta `path:"/room/create" method:"post" tags:"房间" summary:"创建房间"` + + // 这里根据你实际的 room 表字段自己增删 + RoomCode string `json:"room_code" orm:"room_code" description:"房间号"` + RoomName string `json:"room_name" orm:"room_name" description:"房间名称"` + HostId uint64 `json:"host_id" orm:"host_id" description:"主持人用户ID"` + MaxPlayers uint `json:"max_players" orm:"max_players" description:"最大玩家人数"` + HasPassword int `json:"has_password" orm:"has_password" description:"是否有密码:0无 1有"` + RoomPassword string `json:"room_password" orm:"room_password" description:"房间密码(建议哈希)"` + IsPrivate int `json:"is_private" orm:"is_private" description:"是否私密房:0公开 1私密"` + SystemName string `json:"system_name" orm:"system_name" description:"规则系统,如COC、DND5E"` + ScenarioName string `json:"scenario_name" orm:"scenario_name" description:"模组/剧本名称"` + Description string `json:"description" orm:"description" description:"房间简介/招募说明"` +} + +// RoomCreateRes 创建房间响应 +type RoomCreateRes struct { + Id uint64 `json:"id" orm:"id" description:"房间ID"` + RoomCode string `json:"room_code" orm:"room_code" description:"房间号"` +} + +// RoomUpdateReq 更新房间请求 +type RoomUpdateReq struct { + g.Meta `path:"/room/update" method:"put" tags:"房间" summary:"更新房间"` + RoomCode string `json:"room_code" orm:"room_code" description:"房间号(作为更新定位字段)"` + model.RoomParams +} + +// RoomUpdateRes 更新房间响应 +type RoomUpdateRes struct { + Id uint64 `json:"id" orm:"id" description:"房间ID"` +} + +// RoomDeleteReq 删除房间请求 +type RoomDeleteReq struct { + g.Meta `path:"/room/delete" method:"delete" tags:"房间" summary:"删除房间"` + RoomCode string `json:"room_code" orm:"room_code" description:"房间号"` +} + +// RoomDeleteRes 删除房间响应 +type RoomDeleteRes struct{} + +type RoomJoinReq struct { + g.Meta `path:"/room/join" method:"post" tags:"房间" summary:"加入房间"` + RoomId uint64 `json:"roomId" description:"房间ID"` +} + +type RoomJoinRes struct { + Id uint64 `json:"id" description:"房间ID"` + RoomCode string `json:"roomCode" description:"房间号"` +} diff --git a/Backend/api/user/user.go b/Backend/api/user/user.go new file mode 100644 index 0000000..6741daf --- /dev/null +++ b/Backend/api/user/user.go @@ -0,0 +1,38 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package user + +import ( + "context" + + "leke/api/user/v1" +) + +type IUserV1 interface { + FansList(ctx context.Context, req *v1.FansListReq) (res *v1.FansListRes, err error) + FansView(ctx context.Context, req *v1.FansViewReq) (res *v1.FansViewRes, err error) + FansUpdate(ctx context.Context, req *v1.FansUpdateReq) (res *v1.FansUpdateRes, err error) + FansDelete(ctx context.Context, req *v1.FansDeleteReq) (res *v1.FansDeleteRes, err error) + FansCreate(ctx context.Context, req *v1.FansCreateReq) (res *v1.FansCreateRes, err error) + RoleCreate(ctx context.Context, req *v1.RoleCreateReq) (res *v1.RoleCreateRes, err error) + RoleUpdate(ctx context.Context, req *v1.RoleUpdateReq) (res *v1.RoleUpdateRes, err error) + RoleView(ctx context.Context, req *v1.RoleViewReq) (res *v1.RoleViewRes, err error) + RoleList(ctx context.Context, req *v1.RoleListReq) (res *v1.RoleListRes, err error) + RoleDelete(ctx context.Context, req *v1.RoleDeleteReq) (res *v1.RoleDeleteRes, err error) + RolePermissionCheck(ctx context.Context, req *v1.RolePermissionCheckReq) (res *v1.RolePermissionCheckRes, err error) + SubscribeList(ctx context.Context, req *v1.SubscribeListReq) (res *v1.SubscribeListRes, err error) + SubscribeView(ctx context.Context, req *v1.SubscribeViewReq) (res *v1.SubscribeViewRes, err error) + SubscribeUpdate(ctx context.Context, req *v1.SubscribeUpdateReq) (res *v1.SubscribeUpdateRes, err error) + SubscribeDelete(ctx context.Context, req *v1.SubscribeDeleteReq) (res *v1.SubscribeDeleteRes, err error) + SubscribeCreate(ctx context.Context, req *v1.SubscribeCreateReq) (res *v1.SubscribeCreateRes, err error) + TraceList(ctx context.Context, req *v1.TraceListReq) (res *v1.TraceListRes, err error) + TraceView(ctx context.Context, req *v1.TraceViewReq) (res *v1.TraceViewRes, err error) + TraceUpdate(ctx context.Context, req *v1.TraceUpdateReq) (res *v1.TraceUpdateRes, err error) + TraceReduce(ctx context.Context, req *v1.TraceReduceReq) (res *v1.TraceReduceRes, err error) + UserList(ctx context.Context, req *v1.UserListReq) (res *v1.UserListRes, err error) + UserView(ctx context.Context, req *v1.UserViewReq) (res *v1.UserViewRes, err error) + UserUpdate(ctx context.Context, req *v1.UserUpdateReq) (res *v1.UserUpdateRes, err error) + UserDelete(ctx context.Context, req *v1.UserDeleteReq) (res *v1.UserDeleteRes, err error) +} diff --git a/Backend/api/user/v1/fans.go b/Backend/api/user/v1/fans.go new file mode 100644 index 0000000..09a4315 --- /dev/null +++ b/Backend/api/user/v1/fans.go @@ -0,0 +1,80 @@ +package v1 + +import ( + "leke/internal/model/response" + + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gtime" +) + +// FansListItem 粉丝列表项 +type FansListItem struct { + Id uint64 `json:"id" description:"自增主键"` + UserId uint64 `json:"userId" description:"用户ID(被关注者,本人)"` + FanId uint64 `json:"fanId" description:"粉丝用户ID"` + Status int `json:"status" description:"状态:1=粉丝 0=取关/无效"` + Remark string `json:"remark" description:"备注名(user_id 对 fan_id 的备注/分组)"` + CreatedAt *gtime.Time `json:"createdAt" description:"创建时间"` + UpdatedAt *gtime.Time `json:"updatedAt" description:"更新时间"` +} + +// FansListReq 粉丝列表请求参数 +type FansListReq struct { + response.PageResult + g.Meta `path:"/fans/list" method:"get" tags:"粉丝" summary:"粉丝列表"` + UserId uint64 `json:"userId" v:"required#用户ID不能为空"` + Status int `json:"status" description:"状态:1=粉丝 0=取关/无效"` +} + +// FansListRes 粉丝列表响应参数 +type FansListRes struct { + response.PageResult + List []*FansListItem `json:"list"` +} + +// FansViewReq 粉丝详情请求参数 +type FansViewReq struct { + g.Meta `path:"/fans/view" method:"get" tags:"粉丝" summary:"粉丝详情"` + Id uint64 `json:"id" v:"required#粉丝关系ID不能为空"` +} + +// FansViewRes 粉丝详情响应参数 +type FansViewRes struct { + FansListItem +} + +// FansUpdateReq 粉丝更新请求参数 +type FansUpdateReq struct { + g.Meta `path:"/fans/update" method:"put" tags:"粉丝" summary:"更新粉丝"` + Id uint64 `json:"id" v:"required#粉丝关系ID不能为空"` + Status int `json:"status" description:"状态:1=粉丝 0=取关/无效"` + Remark string `json:"remark" description:"备注名(user_id 对 fan_id 的备注/分组)"` +} + +// FansUpdateRes 粉丝更新响应参数 +type FansUpdateRes struct { + Id uint64 `json:"id"` +} + +// FansDeleteReq 粉丝删除请求参数 +type FansDeleteReq struct { + g.Meta `path:"/fans/delete" method:"delete" tags:"粉丝" summary:"删除粉丝"` + Id uint64 `json:"id" v:"required#粉丝关系ID不能为空"` +} + +// FansDeleteRes 粉丝删除响应参数 +type FansDeleteRes struct { +} + +// FansCreateReq 粉丝创建请求参数 +type FansCreateReq struct { + g.Meta `path:"/fans/create" method:"post" tags:"粉丝" summary:"创建粉丝"` + UserId uint64 `json:"userId" v:"required#用户ID不能为空"` + FanId uint64 `json:"fanId" v:"required#粉丝用户ID不能为空"` + Remark string `json:"remark" description:"备注名(user_id 对 fan_id 的备注/分组)"` +} + +// FansCreateRes 粉丝创建响应参数 +type FansCreateRes struct { + Id uint64 `json:"id"` +} diff --git a/Backend/api/user/v1/role.go b/Backend/api/user/v1/role.go new file mode 100644 index 0000000..4c5c874 --- /dev/null +++ b/Backend/api/user/v1/role.go @@ -0,0 +1,113 @@ +package v1 + +import ( + "github.com/gogf/gf/v2/frame/g" + "leke/internal/model/response" +) + +type RoleCreateReq struct { + g.Meta `path:"/role/create" method:"post" tags:"角色" summary:"创建角色"` + UserId uint64 `json:"userId" v:"required" description:"所属用户ID"` + DepartmentId uint64 `json:"departmentId" description:"所属部门ID"` + AgentName string `json:"agentName" v:"required|length:1,50" description:"特工名字"` + CodeName string `json:"codeName" v:"required|length:1,50" description:"代号"` + Gender string `json:"gender" v:"required|in:male,female,other" description:"性别"` + ArcAbnormal string `json:"arcAbnormal" description:"ARC:异常"` + ArcReality string `json:"arcReality" description:"ARC:现实"` + ArcPosition string `json:"arcPosition" description:"ARC:职位"` +} + +type RoleCreateRes struct { + Id uint64 `json:"id" description:"角色ID"` +} + +type RoleUpdateReq struct { + g.Meta `path:"/role/update" method:"put" tags:"角色" summary:"更新角色"` + Id uint64 `json:"id" v:"required" description:"角色ID"` + DepartmentId uint64 `json:"departmentId" description:"所属部门ID"` + AgentName string `json:"agentName" v:"required|length:1,50" description:"特工名字"` + CodeName string `json:"codeName" v:"required|length:1,50" description:"代号"` + Gender string `json:"gender" v:"required|in:male,female,other" description:"性别"` + ArcAbnormal string `json:"arcAbnormal" description:"ARC:异常"` + ArcReality string `json:"arcReality" description:"ARC:现实"` + ArcPosition string `json:"arcPosition" description:"ARC:职位"` + Commendation uint `json:"commendation" description:"嘉奖次数"` + Reprimand uint `json:"reprimand" description:"申戒次数"` + BlueTrack uint `json:"blueTrack" description:"蓝轨(0-40)"` + YellowTrack uint `json:"yellowTrack" description:"黄轨(0-40)"` + RedTrack uint `json:"redTrack" description:"红轨(0-40)"` +} + +type RoleUpdateRes struct { + Id uint64 `json:"id" description:"角色ID"` +} + +type RoleViewReq struct { + g.Meta `path:"/role/view" method:"get" tags:"角色" summary:"查看角色"` + Id uint64 `json:"id" v:"required" description:"角色ID"` +} + +type RoleViewRes struct { + RoleViewParams `json:",inline"` +} + +type RoleViewParams struct { + Id uint64 `json:"id" description:"角色卡ID"` + UserId uint64 `json:"userId" description:"所属用户ID"` + DepartmentId uint64 `json:"departmentId" description:"所属部门ID"` + Commendation uint `json:"commendation" description:"嘉奖次数"` + Reprimand uint `json:"reprimand" description:"申戒次数"` + BlueTrack uint `json:"blueTrack" description:"蓝轨(0-40)"` + YellowTrack uint `json:"yellowTrack" description:"黄轨(0-40)"` + RedTrack uint `json:"redTrack" description:"红轨(0-40)"` + ArcAbnormal string `json:"arcAbnormal" description:"ARC:异常"` + ArcReality string `json:"arcReality" description:"ARC:现实"` + ArcPosition string `json:"arcPosition" description:"ARC:职位"` + AgentName string `json:"agentName" description:"特工名字"` + CodeName string `json:"codeName" description:"代号"` + Gender string `json:"gender" description:"性别"` + QaMeticulous uint `json:"qaMeticulous" description:"Meticulousness (0-100, QA)"` + QaDeception uint `json:"qaDeception" description:"Deception (0-100, QA)"` + QaVigor uint `json:"qaVigor" description:"Vigor / Drive (0-100, QA)"` + QaEmpathy uint `json:"qaEmpathy" description:"Empathy (0-100, QA)"` + QaInitiative uint `json:"qaInitiative" description:"Initiative (0-100, QA)"` + QaResilience uint `json:"qaResilience" description:"Resilience / Persistence (0-100, QA)"` + QaPresence uint `json:"qaPresence" description:"Presence / Charisma (0-100, QA)"` + QaProfessional uint `json:"qaProfessional" description:"Professionalism (0-100, QA)"` + QaDiscretion uint `json:"qaDiscretion" description:"Discretion / Low profile (0-100, QA)"` +} + +type RoleListReq struct { + g.Meta `path:"/role/list" method:"get" tags:"角色" summary:"角色列表"` + response.PageResult + UserId uint64 `json:"userId" description:"用户ID"` + DepartmentId uint64 `json:"departmentId" description:"部门ID"` +} + +type RoleListRes struct { + response.PageResult + List []*RoleViewParams `json:"list" description:"角色列表"` +} + +type RoleDeleteReq struct { + g.Meta `path:"/role/delete" method:"delete" tags:"角色" summary:"删除角色"` + Id uint64 `json:"id" v:"required" description:"角色ID"` +} + +type RoleDeleteRes struct { + Id uint64 `json:"id" description:"角色ID"` +} + +// RolePermissionCheckReq 权限查询请求 +type RolePermissionCheckReq struct { + g.Meta `path:"/role/permission/check" method:"post" tags:"角色" summary:"检查角色权限"` + RoleId uint64 `json:"roleId" v:"required" description:"角色ID"` + FileValue uint `json:"fileValue" v:"required|min:0|max:40" description:"文件需要的轨道值(0-40)"` + TrackType string `json:"trackType" v:"required|in:blue,yellow,red" description:"轨道类型:blue(蓝轨),yellow(黄轨),red(红轨)"` +} + +// RolePermissionCheckRes 权限查询响应 +type RolePermissionCheckRes struct { + Code int `json:"code" description:"响应码:333表示成功"` + Mes string `json:"mes" description:"响应消息"` +} diff --git a/Backend/api/user/v1/subscribe.go b/Backend/api/user/v1/subscribe.go new file mode 100644 index 0000000..dd3ebf7 --- /dev/null +++ b/Backend/api/user/v1/subscribe.go @@ -0,0 +1,81 @@ +package v1 + +import ( + "leke/internal/model/response" + + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gtime" +) + +// SubscribeListItem 关注列表项 +type SubscribeListItem struct { + Id uint64 `json:"id" description:"自增主键"` + UserId uint64 `json:"userId" description:"用户ID(关注者,本人)"` + FollowId uint64 `json:"followId" description:"被关注的用户ID"` + Status int `json:"status" description:"状态:1=关注中 0=取消关注"` + Remark string `json:"remark" description:"备注名(user_id 对 follow_id 的备注)"` + CreatedAt *gtime.Time `json:"createdAt" description:"创建时间"` + UpdatedAt *gtime.Time `json:"updatedAt" description:"更新时间"` +} + +// SubscribeListReq 关注列表请求参数 +type SubscribeListReq struct { + response.PageResult + g.Meta `path:"/subscribe/list" method:"get" tags:"关注" summary:"关注列表"` + UserId uint64 `json:"userId" v:"required#用户ID不能为空"` + Status int `json:"status" description:"状态:1=关注中 0=取消关注"` + FollowId uint64 `json:"followId" description:"被关注的用户ID"` +} + +// SubscribeListRes 关注列表响应参数 +type SubscribeListRes struct { + response.PageResult + List []*SubscribeListItem `json:"list"` +} + +// SubscribeViewReq 关注详情请求参数 +type SubscribeViewReq struct { + g.Meta `path:"/subscribe/view" method:"get" tags:"关注" summary:"关注详情"` + Id uint64 `json:"id" v:"required#关注关系ID不能为空"` +} + +// SubscribeViewRes 关注详情响应参数 +type SubscribeViewRes struct { + SubscribeListItem +} + +// SubscribeUpdateReq 关注更新请求参数 +type SubscribeUpdateReq struct { + g.Meta `path:"/subscribe/update" method:"put" tags:"关注" summary:"更新关注"` + Id uint64 `json:"id" v:"required#关注关系ID不能为空"` + Status int `json:"status" description:"状态:1=关注中 0=取消关注"` + Remark string `json:"remark" description:"备注名(user_id 对 follow_id 的备注)"` +} + +// SubscribeUpdateRes 关注更新响应参数 +type SubscribeUpdateRes struct { + Id uint64 `json:"id"` +} + +// SubscribeDeleteReq 关注删除请求参数 +type SubscribeDeleteReq struct { + g.Meta `path:"/subscribe/delete" method:"delete" tags:"关注" summary:"删除关注"` + Id uint64 `json:"id" v:"required#关注关系ID不能为空"` +} + +// SubscribeDeleteRes 关注删除响应参数 +type SubscribeDeleteRes struct { +} + +// SubscribeCreateReq 关注创建请求参数 +type SubscribeCreateReq struct { + g.Meta `path:"/subscribe/create" method:"post" tags:"关注" summary:"创建关注"` + UserId uint64 `json:"userId" v:"required#用户ID不能为空"` + FollowId uint64 `json:"followId" v:"required#被关注用户ID不能为空"` + Remark string `json:"remark" description:"备注名(user_id 对 follow_id 的备注)"` +} + +// SubscribeCreateRes 关注创建响应参数 +type SubscribeCreateRes struct { + Id uint64 `json:"id"` +} diff --git a/Backend/api/user/v1/trace.go b/Backend/api/user/v1/trace.go new file mode 100644 index 0000000..f58886b --- /dev/null +++ b/Backend/api/user/v1/trace.go @@ -0,0 +1,80 @@ +package v1 + +import ( + "github.com/gogf/gf/v2/frame/g" + "leke/internal/model/response" +) + +// TraceListReq 查询轨迹列表请求参数 +type TraceListReq struct { + response.PageResult + g.Meta `path:"/trace/list" method:"get" tags:"轨迹" summary:"轨迹列表"` + UserId uint64 `json:"userId" description:"用户ID"` + RoleId uint64 `json:"roleId" description:"角色ID"` + DepartmentId uint64 `json:"departmentId" description:"部门ID"` + RedTrace int `json:"redTrace" description:"红轨"` + YellowTrace int `json:"yellowTrace" description:"黄轨"` + BlueTrace int `json:"blueTrace" description:"蓝轨"` +} + +// TraceListRes 查询轨迹列表响应数据 +type TraceListRes struct { + response.PageResult + List []*TraceViewParams `json:"list"` +} + +// TraceViewParams 轨迹视图参数 +type TraceViewParams struct { + UserId uint64 `json:"userId" description:"用户ID"` + RoleId uint64 `json:"roleId" description:"角色ID"` + DepartmentId uint64 `json:"departmentId" description:"部门ID"` + RedTrace int `json:"redTrace" description:"红轨"` + YellowTrace int `json:"yellowTrace" description:"黄轨"` + BlueTrace int `json:"blueTrace" description:"蓝轨"` +} + +// TraceViewReq 查看轨迹详情请求参数 +type TraceViewReq struct { + g.Meta `path:"/trace/view" method:"get" tags:"轨迹" summary:"轨迹详情"` + RoleId uint64 `json:"roleId" description:"角色ID"` + RedTrace int `json:"redTrace" description:"红轨"` + YellowTrace int `json:"yellowTrace" description:"黄轨"` + BlueTrace int `json:"blueTrace" description:"蓝轨"` +} + +// TraceViewRes 查看轨迹详情响应数据 +type TraceViewRes struct { + TraceViewParams +} + +// TraceUpdateReq 更新轨迹请求参数 +type TraceUpdateReq struct { + g.Meta `path:"/trace/update" method:"put" tags:"轨迹" summary:"更新轨迹"` + UserId uint64 `json:"userId"` + RoleId uint64 `json:"roleId" description:"角色ID"` + DepartmentId uint64 `json:"departmentId"` + RedTrace int `json:"redTrace" description:"红轨"` + YellowTrace int `json:"yellowTrace" description:"黄轨"` + BlueTrace int `json:"blueTrace" description:"蓝轨"` +} + +// TraceUpdateRes 更新轨迹响应数据 +type TraceUpdateRes struct { + RoleId uint64 `json:"roleId" description:"角色ID"` + RedTrace int `json:"redTrace" description:"红轨"` + YellowTrace int `json:"yellowTrace" description:"黄轨"` + BlueTrace int `json:"blueTrace" description:"蓝轨"` +} + +// TraceReduceReq 删除轨迹请求参数 +type TraceReduceReq struct { + g.Meta `path:"/trace/Reduce" method:"delete" tags:"轨迹" summary:"删除轨迹"` + RoleId uint64 `json:"roleId" description:"角色ID"` + RedTrace int `json:"redTrace" description:"红轨"` + YellowTrace int `json:"yellowTrace" description:"黄轨"` + BlueTrace int `json:"blueTrace" description:"蓝轨"` +} + +// TraceReduceRes 删除轨迹响应数据 +type TraceReduceRes struct { +} diff --git a/Backend/api/user/v1/user.go b/Backend/api/user/v1/user.go new file mode 100644 index 0000000..209fe34 --- /dev/null +++ b/Backend/api/user/v1/user.go @@ -0,0 +1,44 @@ +package v1 + +import ( + "leke/internal/model" + "leke/internal/model/response" + + "github.com/gogf/gf/v2/frame/g" +) + +type UserListReq struct { + response.PageResult + g.Meta `path:"/user/list" method:"get" tags:"用户" summary:"用户列表"` + Account string `json:"account" orm:"account" description:"账号"` + Nickname string `json:"nickname" orm:"nickname" description:"昵称"` +} + +type UserListRes struct { + response.PageResult + Users []*model.UserViewParams +} + +type UserViewReq struct { + g.Meta `path:"/user/view" method:"get" tags:"用户" summary:"用户详情"` + Account string `json:"account" orm:"account" description:"账号"` + Nickname string `json:"nickname" orm:"nickname" description:"昵称"` + Id uint64 `json:"id" orm:"id" description:"用户ID"` +} +type UserViewRes struct { + model.UserViewParams +} +type UserUpdateReq struct { + g.Meta `path:"/user/update" method:"put" tags:"用户" summary:"更新用户"` + Account string `json:"account" orm:"account" description:"账号"` + model.User +} +type UserUpdateRes struct { + Id uint64 `json:"id" orm:"id" description:"用户ID"` +} +type UserDeleteReq struct { + g.Meta `path:"/user/delete" method:"delete" tags:"用户" summary:"删除用户"` + Account string `json:"account" orm:"account" description:"账号"` +} +type UserDeleteRes struct { +} diff --git a/Backend/go.mod b/Backend/go.mod new file mode 100644 index 0000000..07a7ac0 --- /dev/null +++ b/Backend/go.mod @@ -0,0 +1,45 @@ +module leke + +go 1.24.0 + +require ( + github.com/gogf/gf/contrib/drivers/mysql/v2 v2.9.5 + github.com/gogf/gf/v2 v2.9.5 + github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible + github.com/patrickmn/go-cache v2.1.0+incompatible +) + +require ( + github.com/BurntSushi/toml v1.5.0 // indirect + github.com/clbanning/mxj/v2 v2.7.0 // indirect + github.com/clipperhouse/displaywidth v0.6.0 // indirect + github.com/clipperhouse/stringish v0.1.1 // indirect + github.com/clipperhouse/uax29/v2 v2.3.0 // indirect + github.com/emirpasic/gods v1.18.1 // indirect + github.com/fatih/color v1.18.0 // indirect + github.com/fsnotify/fsnotify v1.9.0 // indirect + github.com/go-logr/logr v1.4.3 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-sql-driver/mysql v1.7.1 // indirect + github.com/golang-jwt/jwt/v5 v5.3.0 + github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/websocket v1.5.3 + github.com/grokify/html-strip-tags-go v0.1.0 // indirect + github.com/magiconair/properties v1.8.10 // indirect + github.com/mattn/go-colorable v0.1.14 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-runewidth v0.0.19 // indirect + github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 // indirect + github.com/olekukonko/errors v1.1.0 // indirect + github.com/olekukonko/ll v0.1.3 // indirect + github.com/olekukonko/tablewriter v1.1.1 // indirect + go.opentelemetry.io/auto/sdk v1.2.1 // indirect + go.opentelemetry.io/otel v1.38.0 // indirect + go.opentelemetry.io/otel/metric v1.38.0 // indirect + go.opentelemetry.io/otel/sdk v1.38.0 // indirect + go.opentelemetry.io/otel/trace v1.38.0 // indirect + golang.org/x/net v0.47.0 // indirect + golang.org/x/sys v0.38.0 // indirect + golang.org/x/text v0.31.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/Backend/go.sum b/Backend/go.sum new file mode 100644 index 0000000..b64a0e6 --- /dev/null +++ b/Backend/go.sum @@ -0,0 +1,95 @@ +github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg= +github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= +github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME= +github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s= +github.com/clipperhouse/displaywidth v0.6.0 h1:k32vueaksef9WIKCNcoqRNyKbyvkvkysNYnAWz2fN4s= +github.com/clipperhouse/displaywidth v0.6.0/go.mod h1:R+kHuzaYWFkTm7xoMmK1lFydbci4X2CicfbGstSGg0o= +github.com/clipperhouse/stringish v0.1.1 h1:+NSqMOr3GR6k1FdRhhnXrLfztGzuG+VuFDfatpWHKCs= +github.com/clipperhouse/stringish v0.1.1/go.mod h1:v/WhFtE1q0ovMta2+m+UbpZ+2/HEXNWYXQgCt4hdOzA= +github.com/clipperhouse/uax29/v2 v2.3.0 h1:SNdx9DVUqMoBuBoW3iLOj4FQv3dN5mDtuqwuhIGpJy4= +github.com/clipperhouse/uax29/v2 v2.3.0/go.mod h1:Wn1g7MK6OoeDT0vL+Q0SQLDz/KpfsVRgg6W7ihQeh4g= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= +github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= +github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= +github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= +github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= +github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= +github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= +github.com/gogf/gf/contrib/drivers/mysql/v2 v2.9.5 h1:0+ZBYhi4sqwxXwL+hIBpp06a7G4m5nmjskQ3NNb8qYc= +github.com/gogf/gf/contrib/drivers/mysql/v2 v2.9.5/go.mod h1:vyB7J/uJcLCrHD5lfFBzxhEEMkePIRzfhd33EcsuLa0= +github.com/gogf/gf/v2 v2.9.5 h1:1scfOdHbMP854oQaiLejl+eL+c4xfuvtWmmZiDJxbKs= +github.com/gogf/gf/v2 v2.9.5/go.mod h1:VUb5eyJKpvW77O/dXsbbLNO/Kjrg0UycIiq0lRiBjjo= +github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo= +github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grokify/html-strip-tags-go v0.1.0 h1:03UrQLjAny8xci+R+qjCce/MYnpNXCtgzltlQbOBae4= +github.com/grokify/html-strip-tags-go v0.1.0/go.mod h1:ZdzgfHEzAfz9X6Xe5eBLVblWIxXfYSQ40S/VKrAOGpc= +github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible h1:jdpOPRN1zP63Td1hDQbZW73xKmzDvZHzVdNYxhnTMDA= +github.com/jordan-wright/email v4.0.1-0.20210109023952-943e75fe5223+incompatible/go.mod h1:1c7szIrayyPPB/987hsnvNzLushdWf4o/79s3P08L8A= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE= +github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= +github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.19 h1:v++JhqYnZuu5jSKrk9RbgF5v4CGUjqRfBm05byFGLdw= +github.com/mattn/go-runewidth v0.0.19/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs= +github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6 h1:zrbMGy9YXpIeTnGj4EljqMiZsIcE09mmF8XsD5AYOJc= +github.com/olekukonko/cat v0.0.0-20250911104152-50322a0618f6/go.mod h1:rEKTHC9roVVicUIfZK7DYrdIoM0EOr8mK1Hj5s3JjH0= +github.com/olekukonko/errors v1.1.0 h1:RNuGIh15QdDenh+hNvKrJkmxxjV4hcS50Db478Ou5sM= +github.com/olekukonko/errors v1.1.0/go.mod h1:ppzxA5jBKcO1vIpCXQ9ZqgDh8iwODz6OXIGKU8r5m4Y= +github.com/olekukonko/ll v0.1.3 h1:sV2jrhQGq5B3W0nENUISCR6azIPf7UBUpVq0x/y70Fg= +github.com/olekukonko/ll v0.1.3/go.mod h1:b52bVQRRPObe+yyBl0TxNfhesL0nedD4Cht0/zx55Ew= +github.com/olekukonko/tablewriter v1.1.1 h1:b3reP6GCfrHwmKkYwNRFh2rxidGHcT6cgxj/sHiDDx0= +github.com/olekukonko/tablewriter v1.1.1/go.mod h1:De/bIcTF+gpBDB3Alv3fEsZA+9unTsSzAg/ZGADCtn4= +github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= +github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= +go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= +go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8= +go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM= +go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA= +go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI= +go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E= +go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg= +go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM= +go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA= +go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE= +go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY= +golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= +golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= +golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/Backend/hack/config.yaml b/Backend/hack/config.yaml new file mode 100644 index 0000000..5ba5afb --- /dev/null +++ b/Backend/hack/config.yaml @@ -0,0 +1,13 @@ +# CLI tool, only in development environment. +# https://goframe.org/docs/cli +gfcli: + gen: + dao: + - link: "mysql:root:123456@tcp(127.0.0.1:3306)/fitness_app" + table: "forum_posts,forum_comments" + descriptionTag: true + jsonCase: "CamelLower" # 生成json字段时,字段名使用驼峰命名 + docker: + build: "-a amd64 -s linux -p temp -ew" + tagPrefixes: + - my.image.pub/my-app diff --git a/Backend/hack/hack-cli.mk b/Backend/hack/hack-cli.mk new file mode 100644 index 0000000..f4e2ad2 --- /dev/null +++ b/Backend/hack/hack-cli.mk @@ -0,0 +1,20 @@ + +# Install/Update to the latest CLI tool. +.PHONY: cli +cli: + @set -e; \ + wget -O gf \ + https://github.com/gogf/gf/releases/latest/download/gf_$(shell go env GOOS)_$(shell go env GOARCH) && \ + chmod +x gf && \ + ./gf install -y && \ + rm ./gf + + +# Check and install CLI tool. +.PHONY: cli.install +cli.install: + @set -e; \ + gf -v > /dev/null 2>&1 || if [[ "$?" -ne "0" ]]; then \ + echo "GoFame CLI is not installed, start proceeding auto installation..."; \ + make cli; \ + fi; \ No newline at end of file diff --git a/Backend/hack/hack.mk b/Backend/hack/hack.mk new file mode 100644 index 0000000..2f68179 --- /dev/null +++ b/Backend/hack/hack.mk @@ -0,0 +1,75 @@ +.DEFAULT_GOAL := build + +# Update GoFrame and its CLI to latest stable version. +.PHONY: up +up: cli.install + @gf up -a + +# Build binary using configuration from hack/config.yaml. +.PHONY: build +build: cli.install + @gf build -ew + +# Parse api and generate controller/sdk. +.PHONY: ctrl +ctrl: cli.install + @gf gen ctrl + +# Generate Go files for DAO/DO/Entity. +.PHONY: dao +dao: cli.install + @gf gen dao + +# Parse current project go files and generate enums go file. +.PHONY: enums +enums: cli.install + @gf gen enums + +# Generate Go files for Service. +.PHONY: service +service: cli.install + @gf gen service + + +# Build docker image. +.PHONY: image +image: cli.install + $(eval _TAG = $(shell git rev-parse --short HEAD)) +ifneq (, $(shell git status --porcelain 2>/dev/null)) + $(eval _TAG = $(_TAG).dirty) +endif + $(eval _TAG = $(if ${TAG}, ${TAG}, $(_TAG))) + $(eval _PUSH = $(if ${PUSH}, ${PUSH}, )) + @gf docker ${_PUSH} -tn $(DOCKER_NAME):${_TAG}; + + +# Build docker image and automatically push to docker repo. +.PHONY: image.push +image.push: cli.install + @make image PUSH=-p; + + +# Deploy image and yaml to current kubectl environment. +.PHONY: deploy +deploy: cli.install + $(eval _TAG = $(if ${TAG}, ${TAG}, develop)) + + @set -e; \ + mkdir -p $(ROOT_DIR)/temp/kustomize;\ + cd $(ROOT_DIR)/manifest/deploy/kustomize/overlays/${_ENV};\ + kustomize build > $(ROOT_DIR)/temp/kustomize.yaml;\ + kubectl apply -f $(ROOT_DIR)/temp/kustomize.yaml; \ + if [ $(DEPLOY_NAME) != "" ]; then \ + kubectl patch -n $(NAMESPACE) deployment/$(DEPLOY_NAME) -p "{\"spec\":{\"template\":{\"metadata\":{\"labels\":{\"date\":\"$(shell date +%s)\"}}}}}"; \ + fi; + + +# Parsing protobuf files and generating go files. +.PHONY: pb +pb: cli.install + @gf gen pb + +# Generate protobuf files for database tables. +.PHONY: pbentity +pbentity: cli.install + @gf gen pbentity \ No newline at end of file diff --git a/Backend/internal/cmd/cmd.go b/Backend/internal/cmd/cmd.go new file mode 100644 index 0000000..b983c8c --- /dev/null +++ b/Backend/internal/cmd/cmd.go @@ -0,0 +1,54 @@ +package cmd + +import ( + "context" + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/net/ghttp" + "github.com/gogf/gf/v2/os/gcmd" + "leke/internal/controller" + "leke/internal/controller/websocket" +) + +var ( + Main = gcmd.Command{ + Name: "main", + Usage: "main", + Brief: "start http server", + Func: func(ctx context.Context, parser *gcmd.Parser) (err error) { + s := g.Server() + + // ... existing code ... + // CORS 中间件 + s.Use(func(r *ghttp.Request) { + r.Response.CORS(ghttp.CORSOptions{ + AllowOrigin: "http://localhost:3000,http://localhost:8080", + AllowMethods: "GET,POST,PUT,DELETE,OPTIONS", + AllowHeaders: "Content-Type,Authorization,X-Requested-With", + AllowCredentials: "true", + MaxAge: 3600, + }) + if r.Method == "OPTIONS" { + r.Response.WriteStatusExit(200) + return + } + r.Middleware.Next() + }) + // ... existing code ... + + // 注册 API 路由组 + s.Group("/api", func(group *ghttp.RouterGroup) { + group.Middleware(ghttp.MiddlewareHandlerResponse) + controller.RegisterControllers(group) + }) + + // 注册 WebSocket 聊天室路由(不在 /api 组下,因为 WebSocket 不需要中间件) + s.BindHandler("/ws/chat", websocket.HandleChatConnections) + + // 配置静态文件服务(用于提供 HTML 客户端页面) + s.SetServerRoot("resource/public") + + s.Run() + return nil + }, + } +) diff --git a/Backend/internal/consts/consts.go b/Backend/internal/consts/consts.go new file mode 100644 index 0000000..cd9d098 --- /dev/null +++ b/Backend/internal/consts/consts.go @@ -0,0 +1,5 @@ +package consts + +// 加盐 +const Salt = "leke" +const qa_empathy, qa_presence, qa_initiative, qa_vigor, qa_tenacity = "empathy", "presence", "initiative", "vigor", "tenacity" diff --git a/Backend/internal/controller/RegisterController.go b/Backend/internal/controller/RegisterController.go new file mode 100644 index 0000000..93745f4 --- /dev/null +++ b/Backend/internal/controller/RegisterController.go @@ -0,0 +1,36 @@ +package controller + +import ( + "leke/internal/controller/containment" + "leke/internal/controller/department" + "leke/internal/controller/forum" + "leke/internal/controller/login" + "leke/internal/controller/room" + "leke/internal/controller/user" + "leke/internal/middleware" + + "github.com/gogf/gf/v2/net/ghttp" +) + +// RegisterControllers 将所有控制器绑定到路由组 +func RegisterControllers(group *ghttp.RouterGroup) { + // 登录相关接口不需要JWT验证 + group.Group("/", func(g *ghttp.RouterGroup) { + g.Bind( + login.NewV1(), + ) + }) + + // 其他需要JWT验证的接口 + group.Group("/", func(g *ghttp.RouterGroup) { + g.Middleware(middleware.JWTAuth) + g.Bind( + user.NewV1(), + user.NewRoleV1(), + department.NewV1(), + containment.NewV1(), + room.NewV1(), + forum.NewV1(), + ) + }) +} diff --git a/Backend/internal/controller/containment/containment_v1_containment.go b/Backend/internal/controller/containment/containment_v1_containment.go new file mode 100644 index 0000000..923c350 --- /dev/null +++ b/Backend/internal/controller/containment/containment_v1_containment.go @@ -0,0 +1,72 @@ +package containment + +import ( + "context" + "leke/api/containment" + + "leke/api/containment/v1" + "leke/internal/service" +) + +// ControllerV1 控制器结构体 +type ControllerV1 struct{} + +// NewV1 创建一个新的v1版本控制器实例 +// +// 返回: +// - containment.IContainmentV1: v1版本控制器接口实现 +func NewV1() containment.IContainmentV1 { + return &ControllerV1{} +} + +// ContainmentRepoList 获取收容库列表 +// +// 参数: +// - ctx context.Context: 上下文信息 +// - req *v1.ContainmentRepoListReq: 收容库列表请求参数 +// +// 返回: +// - res *v1.ContainmentRepoListRes: 收容库列表响应结果 +// - err error: 错误信息 +func (c *ControllerV1) ContainmentRepoList(ctx context.Context, req *v1.ContainmentRepoListReq) (res *v1.ContainmentRepoListRes, err error) { + return service.Containment().ContainmentRepoList(ctx, req) +} + +// ContainmentRepoView 查看收容库详情 +// +// 参数: +// - ctx context.Context: 上下文信息 +// - req *v1.ContainmentRepoViewReq: 收容库详情请求参数 +// +// 返回: +// - res *v1.ContainmentRepoViewRes: 收容库详情响应结果 +// - err error: 错误信息 +func (c *ControllerV1) ContainmentRepoView(ctx context.Context, req *v1.ContainmentRepoViewReq) (res *v1.ContainmentRepoViewRes, err error) { + return service.Containment().ContainmentRepoView(ctx, req) +} + +// ContainmentRepoUpdate 更新收容库信息 +// +// 参数: +// - ctx context.Context: 上下文信息 +// - req *v1.ContainmentRepoUpdateReq: 收容库更新请求参数 +// +// 返回: +// - res *v1.ContainmentRepoUpdateRes: 收容库更新响应结果 +// - err error: 错误信息 +func (c *ControllerV1) ContainmentRepoUpdate(ctx context.Context, req *v1.ContainmentRepoUpdateReq) (res *v1.ContainmentRepoUpdateRes, err error) { + return service.Containment().ContainmentRepoUpdate(ctx, req) +} + +// ContainmentRepoDelete 删除收容库 +// +// 参数: +// - ctx context.Context: 上下文信息 +// - req *v1.ContainmentRepoDeleteReq: 收容库删除请求参数 +// +// 返回: +// - res *v1.ContainmentRepoDeleteRes: 收容库删除响应结果 +// - err error: 错误信息 +func (c *ControllerV1) ContainmentRepoDelete(ctx context.Context, req *v1.ContainmentRepoDeleteReq) (res *v1.ContainmentRepoDeleteRes, err error) { + return service.Containment().ContainmentRepoDelete(ctx, req) +} diff --git a/Backend/internal/controller/department/department_v1_department.go b/Backend/internal/controller/department/department_v1_department.go new file mode 100644 index 0000000..c3c0da8 --- /dev/null +++ b/Backend/internal/controller/department/department_v1_department.go @@ -0,0 +1,35 @@ +package department + +import ( + "context" + + "leke/api/department" + v1 "leke/api/department/v1" + "leke/internal/service" +) + +type ControllerV1 struct{} + +func NewV1() department.IDepartmentV1 { + return &ControllerV1{} +} + +func (c *ControllerV1) DepartmentList(ctx context.Context, req *v1.DepartmentListReq) (res *v1.DepartmentListRes, err error) { + return service.Department().DepartmentList(ctx, req) +} + +func (c *ControllerV1) DepartmentView(ctx context.Context, req *v1.DepartmentViewReq) (res *v1.DepartmentViewRes, err error) { + return service.Department().DepartmentView(ctx, req) +} + +func (c *ControllerV1) DepartmentCreate(ctx context.Context, req *v1.DepartmentCreateReq) (res *v1.DepartmentCreateRes, err error) { + return service.Department().DepartmentCreate(ctx, req) +} + +func (c *ControllerV1) DepartmentUpdate(ctx context.Context, req *v1.DepartmentUpdateReq) (res *v1.DepartmentUpdateRes, err error) { + return service.Department().DepartmentUpdate(ctx, req) +} + +func (c *ControllerV1) DepartmentDelete(ctx context.Context, req *v1.DepartmentDeleteReq) (res *v1.DepartmentDeleteRes, err error) { + return service.Department().DepartmentDelete(ctx, req) +} \ No newline at end of file diff --git a/Backend/internal/controller/forum/forum_v1_forum_comments.go b/Backend/internal/controller/forum/forum_v1_forum_comments.go new file mode 100644 index 0000000..e3f5f29 --- /dev/null +++ b/Backend/internal/controller/forum/forum_v1_forum_comments.go @@ -0,0 +1,32 @@ +package forum + +import ( + "context" + v1 "leke/api/forum/v1" + "leke/internal/service" +) + +// ForumCommentsCreate 创建评论 +func (c *ControllerV1) ForumCommentsCreate(ctx context.Context, req *v1.ForumCommentsCreateReq) (res *v1.ForumCommentsCreateRes, err error) { + return service.ForumComments().Create(ctx, req) +} + +// ForumCommentsUpdate 更新评论 +func (c *ControllerV1) ForumCommentsUpdate(ctx context.Context, req *v1.ForumCommentsUpdateReq) (res *v1.ForumCommentsUpdateRes, err error) { + return service.ForumComments().Update(ctx, req) +} + +// ForumCommentsDelete 删除评论 +func (c *ControllerV1) ForumCommentsDelete(ctx context.Context, req *v1.ForumCommentsDeleteReq) (res *v1.ForumCommentsDeleteRes, err error) { + return service.ForumComments().Delete(ctx, req) +} + +// ForumCommentsView 查看评论详情 +func (c *ControllerV1) ForumCommentsView(ctx context.Context, req *v1.ForumCommentsViewReq) (res *v1.ForumCommentsViewRes, err error) { + return service.ForumComments().View(ctx, req) +} + +// ForumCommentsList 获取评论列表 +func (c *ControllerV1) ForumCommentsList(ctx context.Context, req *v1.ForumCommentsListReq) (res *v1.ForumCommentsListRes, err error) { + return service.ForumComments().List(ctx, req) +} diff --git a/Backend/internal/controller/forum/forum_v1_forum_posts.go b/Backend/internal/controller/forum/forum_v1_forum_posts.go new file mode 100644 index 0000000..0298998 --- /dev/null +++ b/Backend/internal/controller/forum/forum_v1_forum_posts.go @@ -0,0 +1,38 @@ +package forum + +import ( + "context" + v1 "leke/api/forum/v1" + "leke/internal/service" +) + +type ControllerV1 struct{} + +func NewV1() *ControllerV1 { + return &ControllerV1{} +} + +// ForumPostsCreate 创建帖子 +func (c *ControllerV1) Create(ctx context.Context, req *v1.ForumPostsCreateReq) (res *v1.ForumPostsCreateRes, err error) { + return service.ForumPosts().Create(ctx, req) +} + +// ForumPostsUpdate 更新帖子 +func (c *ControllerV1) Update(ctx context.Context, req *v1.ForumPostsUpdateReq) (res *v1.ForumPostsUpdateRes, err error) { + return service.ForumPosts().Update(ctx, req) +} + +// ForumPostsDelete 删除帖子 +func (c *ControllerV1) Delete(ctx context.Context, req *v1.ForumPostsDeleteReq) (res *v1.ForumPostsDeleteRes, err error) { + return service.ForumPosts().Delete(ctx, req) +} + +// ForumPostsView 查看帖子详情 +func (c *ControllerV1) View(ctx context.Context, req *v1.ForumPostsViewReq) (res *v1.ForumPostsViewRes, err error) { + return service.ForumPosts().View(ctx, req) +} + +// ForumPostsList 获取帖子列表 +func (c *ControllerV1) List(ctx context.Context, req *v1.ForumPostsListReq) (res *v1.ForumPostsListRes, err error) { + return service.ForumPosts().List(ctx, req) +} diff --git a/Backend/internal/controller/login/login_v1_login.go b/Backend/internal/controller/login/login_v1_login.go new file mode 100644 index 0000000..f40aa5e --- /dev/null +++ b/Backend/internal/controller/login/login_v1_login.go @@ -0,0 +1,60 @@ +// internal/controller/login/login_v1_login.go +package login + +import ( + "context" + "leke/api/login" + v1 "leke/api/login/v1" + "leke/internal/service" + + "github.com/gogf/gf/v2/errors/gcode" + "github.com/gogf/gf/v2/errors/gerror" +) + +type ControllerV1 struct{} + +func NewV1() login.ILoginV1 { + return &ControllerV1{} +} + +// Login 登录接口 +func (c *ControllerV1) Login(ctx context.Context, req *v1.LoginReq) (res *v1.LoginRes, err error) { + res, err = service.Login().Login(ctx, req) + if err != nil { + return nil, err + } + res = &v1.LoginRes{ + Token: res.Token, + Account: res.Account, + } + return res, nil +} + +func (c *ControllerV1) Register(ctx context.Context, req *v1.RegisterReq) (res *v1.RegisterRes, err error) { + _, err = service.Login().Register(ctx, req) + if err != nil { + return nil, err + } + return &v1.RegisterRes{ + Account: req.Account, + }, nil +} + +func (c *ControllerV1) Logout(ctx context.Context, req *v1.LogoutReq) (res *v1.LogoutRes, err error) { + return nil, gerror.NewCode(gcode.CodeNotImplemented) +} + +// 通过邮箱注册 +func (c *ControllerV1) RegisterByEmail(ctx context.Context, req *v1.RegisterByEmailReq) (res *v1.RegisterByEmailRes, err error) { + return service.Login().RegisterByEmail(ctx, req) +} + +// 通过邮箱登录 +func (c *ControllerV1) LoginByEmail(ctx context.Context, req *v1.LoginByEmailReq) (res *v1.LoginByEmailRes, err error) { + return service.Login().LoginByEmail(ctx, req) +} + +// 发送验证码 +func (c *ControllerV1) SendVerificationCode(ctx context.Context, req *v1.SendVerificationCodeReq) (res *v1.SendVerificationCodeRes, err error) { + return service.Login().SendVerificationCode(ctx, req) +} diff --git a/Backend/internal/controller/room/room_v1_room.go b/Backend/internal/controller/room/room_v1_room.go new file mode 100644 index 0000000..771bb7d --- /dev/null +++ b/Backend/internal/controller/room/room_v1_room.go @@ -0,0 +1,35 @@ +package room + +import ( + "context" + "leke/api/room" + v1 "leke/api/room/v1" + "leke/internal/service" +) + +type ControllerV1 struct{} + +func NewV1() room.IRoomV1 { + return &ControllerV1{} +} + +func (c *ControllerV1) RoomList(ctx context.Context, req *v1.RoomListReq) (res *v1.RoomListRes, err error) { + return service.Room().RoomList(ctx, req) +} +func (c *ControllerV1) RoomView(ctx context.Context, req *v1.RoomViewReq) (res *v1.RoomViewRes, err error) { + return service.Room().RoomView(ctx, req) +} + +func (c *ControllerV1) RoomUpdate(ctx context.Context, req *v1.RoomUpdateReq) (res *v1.RoomUpdateRes, err error) { + return service.Room().RoomUpdate(ctx, req) +} +func (c *ControllerV1) RoomDelete(ctx context.Context, req *v1.RoomDeleteReq) (res *v1.RoomDeleteRes, err error) { + return service.Room().RoomDelete(ctx, req) +} +func (c *ControllerV1) RoomCreate(ctx context.Context, req *v1.RoomCreateReq) (res *v1.RoomCreateRes, err error) { + return service.Room().RoomCreate(ctx, req) +} + +func (c *ControllerV1) RoomJoin(ctx context.Context, req *v1.RoomJoinReq) (res *v1.RoomJoinRes, err error) { + return service.Room().RoomJoin(ctx, req) +} diff --git a/Backend/internal/controller/user/user_v1_role.go b/Backend/internal/controller/user/user_v1_role.go new file mode 100644 index 0000000..e340cb4 --- /dev/null +++ b/Backend/internal/controller/user/user_v1_role.go @@ -0,0 +1,37 @@ +package user + +import ( + "context" + + v1 "leke/api/user/v1" + "leke/internal/service" +) + +type RoleControllerV1 struct{} + +func NewRoleV1() *RoleControllerV1 { + return &RoleControllerV1{} +} + +func (c *RoleControllerV1) RoleCreate(ctx context.Context, req *v1.RoleCreateReq) (res *v1.RoleCreateRes, err error) { + return service.User().RoleCreate(ctx, req) +} + +func (c *RoleControllerV1) RoleUpdate(ctx context.Context, req *v1.RoleUpdateReq) (res *v1.RoleUpdateRes, err error) { + return service.User().RoleUpdate(ctx, req) +} + +func (c *RoleControllerV1) RoleView(ctx context.Context, req *v1.RoleViewReq) (res *v1.RoleViewRes, err error) { + return service.User().RoleView(ctx, req) +} + +func (c *RoleControllerV1) RoleList(ctx context.Context, req *v1.RoleListReq) (res *v1.RoleListRes, err error) { + return service.User().RoleList(ctx, req) +} + +func (c *RoleControllerV1) RoleDelete(ctx context.Context, req *v1.RoleDeleteReq) (res *v1.RoleDeleteRes, err error) { + return service.User().RoleDelete(ctx, req) +} // RolePermissionCheck 权限查询 +func (c *RoleControllerV1) RolePermissionCheck(ctx context.Context, req *v1.RolePermissionCheckReq) (res *v1.RolePermissionCheckRes, err error) { + return service.User().RolePermissionCheck(ctx, req) +} diff --git a/Backend/internal/controller/user/user_v1_user.go b/Backend/internal/controller/user/user_v1_user.go new file mode 100644 index 0000000..984763e --- /dev/null +++ b/Backend/internal/controller/user/user_v1_user.go @@ -0,0 +1,86 @@ +package user + +import ( + "context" + + v1 "leke/api/user/v1" + "leke/internal/service" +) + +type ControllerV1 struct{} + +func NewV1() *ControllerV1 { + return &ControllerV1{} +} + +func (c *ControllerV1) UserList(ctx context.Context, req *v1.UserListReq) (res *v1.UserListRes, err error) { + return service.User().UserList(ctx, req) +} +func (c *ControllerV1) UserView(ctx context.Context, req *v1.UserViewReq) (res *v1.UserViewRes, err error) { + return service.User().UserView(ctx, req) +} +func (c *ControllerV1) UserUpdate(ctx context.Context, req *v1.UserUpdateReq) (res *v1.UserUpdateRes, err error) { + return service.User().UserUpdate(ctx, req) +} +func (c *ControllerV1) UserDelete(ctx context.Context, req *v1.UserDeleteReq) (res *v1.UserDeleteRes, err error) { + return service.User().UserDelete(ctx, req) +} + +// Fans 相关方法 +func (c *ControllerV1) FansList(ctx context.Context, req *v1.FansListReq) (res *v1.FansListRes, err error) { + return service.Fans().FansList(ctx, req) +} + +func (c *ControllerV1) FansView(ctx context.Context, req *v1.FansViewReq) (res *v1.FansViewRes, err error) { + return service.Fans().FansView(ctx, req) +} + +func (c *ControllerV1) FansUpdate(ctx context.Context, req *v1.FansUpdateReq) (res *v1.FansUpdateRes, err error) { + return service.Fans().FansUpdate(ctx, req) +} + +func (c *ControllerV1) FansDelete(ctx context.Context, req *v1.FansDeleteReq) (res *v1.FansDeleteRes, err error) { + return service.Fans().FansDelete(ctx, req) +} + +func (c *ControllerV1) FansCreate(ctx context.Context, req *v1.FansCreateReq) (res *v1.FansCreateRes, err error) { + return service.Fans().FansCreate(ctx, req) +} + +// Subscribe 相关方法 +func (c *ControllerV1) SubscribeList(ctx context.Context, req *v1.SubscribeListReq) (res *v1.SubscribeListRes, err error) { + return service.Subscribe().SubscribeList(ctx, req) +} + +func (c *ControllerV1) SubscribeView(ctx context.Context, req *v1.SubscribeViewReq) (res *v1.SubscribeViewRes, err error) { + return service.Subscribe().SubscribeView(ctx, req) +} + +func (c *ControllerV1) SubscribeUpdate(ctx context.Context, req *v1.SubscribeUpdateReq) (res *v1.SubscribeUpdateRes, err error) { + return service.Subscribe().SubscribeUpdate(ctx, req) +} + +func (c *ControllerV1) SubscribeDelete(ctx context.Context, req *v1.SubscribeDeleteReq) (res *v1.SubscribeDeleteRes, err error) { + return service.Subscribe().SubscribeDelete(ctx, req) +} + +func (c *ControllerV1) SubscribeCreate(ctx context.Context, req *v1.SubscribeCreateReq) (res *v1.SubscribeCreateRes, err error) { + return service.Subscribe().SubscribeCreate(ctx, req) +} + +// Trace 相关方法 +func (c *ControllerV1) TraceList(ctx context.Context, req *v1.TraceListReq) (res *v1.TraceListRes, err error) { + return service.Trace().TraceList(ctx, req) +} + +func (c *ControllerV1) TraceView(ctx context.Context, req *v1.TraceViewReq) (res *v1.TraceViewRes, err error) { + return service.Trace().TraceView(ctx, req) +} + +func (c *ControllerV1) TraceUpdate(ctx context.Context, req *v1.TraceUpdateReq) (res *v1.TraceUpdateRes, err error) { + return service.Trace().TraceUpdate(ctx, req) +} + +func (c *ControllerV1) TraceReduce(ctx context.Context, req *v1.TraceReduceReq) (res *v1.TraceReduceRes, err error) { + return service.Trace().TraceReduce(ctx, req) +} diff --git a/Backend/internal/controller/websocket/ChatRoom.go b/Backend/internal/controller/websocket/ChatRoom.go new file mode 100644 index 0000000..1a6ce4d --- /dev/null +++ b/Backend/internal/controller/websocket/ChatRoom.go @@ -0,0 +1,119 @@ +package websocket + +import ( + "log" + "net/http" + "sync" + + "github.com/gogf/gf/v2/net/ghttp" + "github.com/gorilla/websocket" +) + +type ChatMessage struct { + RoomId string `json:"roomId"` + UserId string `json:"userId"` + Message string `json:"message"` + Type string `json:"type"` +} + +var upgrader = websocket.Upgrader{CheckOrigin: func(r *http.Request) bool { return true }} +var clients = make(map[*websocket.Conn]bool) +var roomClients = make(map[string]map[*websocket.Conn]bool) +var broadcast = make(chan ChatMessage, 256) +var mutex = sync.RWMutex{} +var once sync.Once + +func HandleChatConnections(r *ghttp.Request) { + once.Do(func() { + go handleBroadcast() + }) + + ws, err := upgrader.Upgrade(r.Response.Writer, r.Request, nil) + if err != nil { + log.Printf("upgrade error: %v", err) + return + } + + mutex.Lock() + clients[ws] = true + mutex.Unlock() + + defer func() { + mutex.Lock() + delete(clients, ws) + for roomId, members := range roomClients { + if _, ok := members[ws]; ok { + delete(members, ws) + if len(members) == 0 { + delete(roomClients, roomId) + } + } + } + mutex.Unlock() + ws.Close() + }() + + for { + var msg ChatMessage + err := ws.ReadJSON(&msg) + if err != nil { + log.Printf("read error: %v", err) + break + } + + switch msg.Type { + case "join": + mutex.Lock() + members, ok := roomClients[msg.RoomId] + if !ok { + members = make(map[*websocket.Conn]bool) + roomClients[msg.RoomId] = members + } + members[ws] = true + mutex.Unlock() + case "leave": + mutex.Lock() + if members, ok := roomClients[msg.RoomId]; ok { + delete(members, ws) + if len(members) == 0 { + delete(roomClients, msg.RoomId) + } + } + mutex.Unlock() + } + + select { + case broadcast <- msg: + default: + log.Printf("broadcast channel full, dropping message") + } + } +} + +func handleBroadcast() { + for { + msg := <-broadcast + mutex.RLock() + members, ok := roomClients[msg.RoomId] + if !ok { + mutex.RUnlock() + continue + } + for client := range members { + err := client.WriteJSON(msg) + if err != nil { + log.Printf("write error: %v", err) + client.Close() + mutex.RUnlock() + mutex.Lock() + delete(members, client) + if len(members) == 0 { + delete(roomClients, msg.RoomId) + } + mutex.Unlock() + mutex.RLock() + } + } + mutex.RUnlock() + } +} diff --git a/Backend/internal/controller/websocket/websocket.go b/Backend/internal/controller/websocket/websocket.go new file mode 100644 index 0000000..fb0ee24 --- /dev/null +++ b/Backend/internal/controller/websocket/websocket.go @@ -0,0 +1,65 @@ +package websocket + +// +//import ( +// "net/http" +// +// "github.com/gogf/gf/v2/frame/g" +// "github.com/gogf/gf/v2/net/ghttp" +// "github.com/gorilla/websocket" +//) +// +//// WebSocketController WebSocket 控制器 +//type WebSocketController struct{} +// +//// New 创建 WebSocket 控制器实例 +//func New() *WebSocketController { +// return &WebSocketController{} +//} +// +//// wsUpgrader WebSocket 升级器配置 +//var wsUpgrader = websocket.Upgrader{ +// // CheckOrigin 允许任何来源(开发环境) +// // 生产环境中应该实现适当的来源检查以确保安全 +// CheckOrigin: func(r *http.Request) bool { +// return true +// }, +// // Error 处理升级失败的错误 +// Error: func(w http.ResponseWriter, r *http.Request, status int, reason error) { +// // 在这里实现错误处理逻辑 +// g.Log().Errorf(r.Context(), "WebSocket upgrade error: %v", reason) +// }, +//} +// +//// Echo WebSocket Echo 服务器处理器 +//// 路径: /ws +//func (c *WebSocketController) Echo(r *ghttp.Request) { +// // 将 HTTP 连接升级为 WebSocket +// ws, err := wsUpgrader.Upgrade(r.Response.Writer, r.Request, nil) +// if err != nil { +// r.Response.Write(err.Error()) +// return +// } +// defer ws.Close() +// +// // 获取请求上下文用于日志记录 +// var ctx = r.Context() +// logger := g.Log() +// +// // 消息处理循环 +// for { +// // 读取传入的 WebSocket 消息 +// msgType, msg, err := ws.ReadMessage() +// if err != nil { +// break // 连接关闭或发生错误 +// } +// // 记录接收到的消息 +// logger.Infof(ctx, "received message: %s", msg) +// // 将消息回显给客户端 +// if err = ws.WriteMessage(msgType, msg); err != nil { +// break // 写入消息时出错 +// } +// } +// // 记录连接关闭 +// logger.Info(ctx, "websocket connection closed") +//} diff --git a/Backend/internal/controller/websocket/websocketV1.go b/Backend/internal/controller/websocket/websocketV1.go new file mode 100644 index 0000000..5bf5471 --- /dev/null +++ b/Backend/internal/controller/websocket/websocketV1.go @@ -0,0 +1,88 @@ +package websocket + +// +//import ( +// "log" +// "net/http" +// "sync" +// +// "github.com/gogf/gf/v2/net/ghttp" +// "github.com/gorilla/websocket" +//) +// +//// 定义 WebSocket 升级器 +//var upgrader = websocket.Upgrader{ +// CheckOrigin: func(r *http.Request) bool { +// return true +// }, +//} +// +//// 存储客户端连接 +//var ( +// clients = make(map[*websocket.Conn]bool) +// clientsMu sync.Mutex // 保护 clients map 的互斥锁 +// broadcast = make(chan string, 256) // 广播信息通道,带缓冲 +//) +// +//// 初始化广播处理(只启动一次) +//var once sync.Once +// +//// HandlerConnection 处理websocket连接 +//func HandlerConnectionV1(r *ghttp.Request) { +// // 启动广播处理 goroutine(只启动一次) +// once.Do(func() { +// go handleBroadcast() +// }) +// +// ws, err := upgrader.Upgrade(r.Response.Writer, r.Request, nil) +// if err != nil { +// log.Printf("upgrade error: %v", err) +// return +// } +// defer func() { +// clientsMu.Lock() +// delete(clients, ws) +// clientsMu.Unlock() +// ws.Close() +// }() +// +// // 注册新客户端 +// clientsMu.Lock() +// clients[ws] = true +// clientsMu.Unlock() +// +// for { +// var message string +// err := ws.ReadJSON(&message) +// if err != nil { +// log.Printf("read error: %v", err) +// clientsMu.Lock() +// delete(clients, ws) +// clientsMu.Unlock() +// break +// } +// // 将消息发送到广播通道 +// select { +// case broadcast <- message: +// default: +// log.Printf("broadcast channel full, dropping message") +// } +// } +//} +// +//// 将广播通道给所有的用户 +//func handleBroadcast() { +// for { +// message := <-broadcast +// clientsMu.Lock() +// for client := range clients { +// err := client.WriteJSON(message) +// if err != nil { +// log.Printf("write error: %v", err) +// client.Close() +// delete(clients, client) +// } +// } +// clientsMu.Unlock() +// } +//} diff --git a/Backend/internal/controller/websocket/websocketV2.go b/Backend/internal/controller/websocket/websocketV2.go new file mode 100644 index 0000000..b6e783d --- /dev/null +++ b/Backend/internal/controller/websocket/websocketV2.go @@ -0,0 +1,66 @@ +package websocket + +// +//import ( +// "github.com/gorilla/websocket" +// "log" +// "net/http" +// "sync" +//) +// +//var upgraderv2 = websocket.Upgrader{CheckOrigin: func(r *http.Request) bool { return true }} +//var clientsV2 = make(map[*websocket.Conn]bool) // +//var mutex = sync.RWMutex{} // 读写锁 // 保护 clientsV2 并发访问 +// +////var bufferPool = sync.Pool{ +//// New: func() interface{} { +//// return make([]byte, 1024) +//// }, +////} +// +//var bufferPool = sync.Pool{ +// New: func() interface{} { +// return make([]byte, 1024) +// }, +//} +// +//func readMessage(ws *websocket.Conn) ([]byte, error) { +// buf := bufferPool.Get().([]byte) +// defer bufferPool.Put(buf) +// _, data, err := ws.ReadMessage() +// return data, err +//} +// +//func HandlerConnectionV2(w http.ResponseWriter, r *http.Request) { +// ws, err := upgraderv2.Upgrade(w, r, nil) +// if err != nil { +// log.Printf("upgrade error: %v", err) +// return +// } +// // 注册客户端 +// mutex.Lock() +// clientsV2[ws] = true +// mutex.Unlock() +// +// defer func() { +// mutex.Lock() +// delete(clientsV2, ws) +// mutex.Unlock() +// ws.Close() +// }() +// +// for { +// var message string +// err := ws.ReadJSON(&message) +// if err != nil { +// log.Printf("read json error: %v", err) +// return +// } +// // 广播消息(简化示例) +// mutex.RLock() +// for client := range clientsV2 { +// client.WriteJSON(message) +// } +// mutex.RUnlock() +// } +//} diff --git a/Backend/internal/dao/.gitkeep b/Backend/internal/dao/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/Backend/internal/dao/coaches.go b/Backend/internal/dao/coaches.go new file mode 100644 index 0000000..4c00585 --- /dev/null +++ b/Backend/internal/dao/coaches.go @@ -0,0 +1,22 @@ +// ================================================================================= +// This file is auto-generated by the GoFrame CLI tool. You may modify it as needed. +// ================================================================================= + +package dao + +import ( + "leke/internal/dao/internal" +) + +// coachesDao is the data access object for the table coaches. +// You can define custom methods on it to extend its functionality as needed. +type coachesDao struct { + *internal.CoachesDao +} + +var ( + // Coaches is a globally accessible object for table coaches operations. + Coaches = coachesDao{internal.NewCoachesDao()} +) + +// Add your custom methods and functionality below. diff --git a/Backend/internal/dao/comments.go b/Backend/internal/dao/comments.go new file mode 100644 index 0000000..d2cf281 --- /dev/null +++ b/Backend/internal/dao/comments.go @@ -0,0 +1,22 @@ +// ================================================================================= +// This file is auto-generated by the GoFrame CLI tool. You may modify it as needed. +// ================================================================================= + +package dao + +import ( + "leke/internal/dao/internal" +) + +// commentsDao is the data access object for the table comments. +// You can define custom methods on it to extend its functionality as needed. +type commentsDao struct { + *internal.CommentsDao +} + +var ( + // Comments is a globally accessible object for table comments operations. + Comments = commentsDao{internal.NewCommentsDao()} +) + +// Add your custom methods and functionality below. diff --git a/Backend/internal/dao/containment_repo.go b/Backend/internal/dao/containment_repo.go new file mode 100644 index 0000000..532a710 --- /dev/null +++ b/Backend/internal/dao/containment_repo.go @@ -0,0 +1,22 @@ +// ================================================================================= +// This file is auto-generated by the GoFrame CLI tool. You may modify it as needed. +// ================================================================================= + +package dao + +import ( + "leke/internal/dao/internal" +) + +// containmentRepoDao is the data access object for the table containment_repo. +// You can define custom methods on it to extend its functionality as needed. +type containmentRepoDao struct { + *internal.ContainmentRepoDao +} + +var ( + // ContainmentRepo is a globally accessible object for table containment_repo operations. + ContainmentRepo = containmentRepoDao{internal.NewContainmentRepoDao()} +) + +// Add your custom methods and functionality below. diff --git a/Backend/internal/dao/department.go b/Backend/internal/dao/department.go new file mode 100644 index 0000000..7dceee9 --- /dev/null +++ b/Backend/internal/dao/department.go @@ -0,0 +1,22 @@ +// ================================================================================= +// This file is auto-generated by the GoFrame CLI tool. You may modify it as needed. +// ================================================================================= + +package dao + +import ( + "leke/internal/dao/internal" +) + +// departmentDao is the data access object for the table department. +// You can define custom methods on it to extend its functionality as needed. +type departmentDao struct { + *internal.DepartmentDao +} + +var ( + // Department is a globally accessible object for table department operations. + Department = departmentDao{internal.NewDepartmentDao()} +) + +// Add your custom methods and functionality below. diff --git a/Backend/internal/dao/fans.go b/Backend/internal/dao/fans.go new file mode 100644 index 0000000..743802e --- /dev/null +++ b/Backend/internal/dao/fans.go @@ -0,0 +1,22 @@ +// ================================================================================= +// This file is auto-generated by the GoFrame CLI tool. You may modify it as needed. +// ================================================================================= + +package dao + +import ( + "leke/internal/dao/internal" +) + +// fansDao is the data access object for the table fans. +// You can define custom methods on it to extend its functionality as needed. +type fansDao struct { + *internal.FansDao +} + +var ( + // Fans is a globally accessible object for table fans operations. + Fans = fansDao{internal.NewFansDao()} +) + +// Add your custom methods and functionality below. diff --git a/Backend/internal/dao/forum_comments.go b/Backend/internal/dao/forum_comments.go new file mode 100644 index 0000000..778402f --- /dev/null +++ b/Backend/internal/dao/forum_comments.go @@ -0,0 +1,22 @@ +// ================================================================================= +// This file is auto-generated by the GoFrame CLI tool. You may modify it as needed. +// ================================================================================= + +package dao + +import ( + "leke/internal/dao/internal" +) + +// forumCommentsDao is the data access object for the table forum_comments. +// You can define custom methods on it to extend its functionality as needed. +type forumCommentsDao struct { + *internal.ForumCommentsDao +} + +var ( + // ForumComments is a globally accessible object for table forum_comments operations. + ForumComments = forumCommentsDao{internal.NewForumCommentsDao()} +) + +// Add your custom methods and functionality below. diff --git a/Backend/internal/dao/forum_posts.go b/Backend/internal/dao/forum_posts.go new file mode 100644 index 0000000..51a5334 --- /dev/null +++ b/Backend/internal/dao/forum_posts.go @@ -0,0 +1,22 @@ +// ================================================================================= +// This file is auto-generated by the GoFrame CLI tool. You may modify it as needed. +// ================================================================================= + +package dao + +import ( + "leke/internal/dao/internal" +) + +// forumPostsDao is the data access object for the table forum_posts. +// You can define custom methods on it to extend its functionality as needed. +type forumPostsDao struct { + *internal.ForumPostsDao +} + +var ( + // ForumPosts is a globally accessible object for table forum_posts operations. + ForumPosts = forumPostsDao{internal.NewForumPostsDao()} +) + +// Add your custom methods and functionality below. diff --git a/Backend/internal/dao/group_class_enrollments.go b/Backend/internal/dao/group_class_enrollments.go new file mode 100644 index 0000000..533056d --- /dev/null +++ b/Backend/internal/dao/group_class_enrollments.go @@ -0,0 +1,22 @@ +// ================================================================================= +// This file is auto-generated by the GoFrame CLI tool. You may modify it as needed. +// ================================================================================= + +package dao + +import ( + "leke/internal/dao/internal" +) + +// groupClassEnrollmentsDao is the data access object for the table group_class_enrollments. +// You can define custom methods on it to extend its functionality as needed. +type groupClassEnrollmentsDao struct { + *internal.GroupClassEnrollmentsDao +} + +var ( + // GroupClassEnrollments is a globally accessible object for table group_class_enrollments operations. + GroupClassEnrollments = groupClassEnrollmentsDao{internal.NewGroupClassEnrollmentsDao()} +) + +// Add your custom methods and functionality below. diff --git a/Backend/internal/dao/group_classes.go b/Backend/internal/dao/group_classes.go new file mode 100644 index 0000000..1fd4642 --- /dev/null +++ b/Backend/internal/dao/group_classes.go @@ -0,0 +1,22 @@ +// ================================================================================= +// This file is auto-generated by the GoFrame CLI tool. You may modify it as needed. +// ================================================================================= + +package dao + +import ( + "leke/internal/dao/internal" +) + +// groupClassesDao is the data access object for the table group_classes. +// You can define custom methods on it to extend its functionality as needed. +type groupClassesDao struct { + *internal.GroupClassesDao +} + +var ( + // GroupClasses is a globally accessible object for table group_classes operations. + GroupClasses = groupClassesDao{internal.NewGroupClassesDao()} +) + +// Add your custom methods and functionality below. diff --git a/Backend/internal/dao/internal/coaches.go b/Backend/internal/dao/internal/coaches.go new file mode 100644 index 0000000..a2d0d16 --- /dev/null +++ b/Backend/internal/dao/internal/coaches.go @@ -0,0 +1,91 @@ +// ========================================================================== +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ========================================================================== + +package internal + +import ( + "context" + + "github.com/gogf/gf/v2/database/gdb" + "github.com/gogf/gf/v2/frame/g" +) + +// CoachesDao is the data access object for the table coaches. +type CoachesDao struct { + table string // table is the underlying table name of the DAO. + group string // group is the database configuration group name of the current DAO. + columns CoachesColumns // columns contains all the column names of Table for convenient usage. + handlers []gdb.ModelHandler // handlers for customized model modification. +} + +// CoachesColumns defines and stores column names for the table coaches. +type CoachesColumns struct { + Id string // 教练ID + UserId string // 对应的用户ID(如果教练也要登录的话) + Name string // 教练姓名 + Phone string // 教练电话 + Specialty string // 擅长方向,比如瑜伽、力量、减脂 + CreatedAt string // 创建时间 + UpdatedAt string // 更新时间 +} + +// coachesColumns holds the columns for the table coaches. +var coachesColumns = CoachesColumns{ + Id: "id", + UserId: "user_id", + Name: "name", + Phone: "phone", + Specialty: "specialty", + CreatedAt: "created_at", + UpdatedAt: "updated_at", +} + +// NewCoachesDao creates and returns a new DAO object for table data access. +func NewCoachesDao(handlers ...gdb.ModelHandler) *CoachesDao { + return &CoachesDao{ + group: "default", + table: "coaches", + columns: coachesColumns, + handlers: handlers, + } +} + +// DB retrieves and returns the underlying raw database management object of the current DAO. +func (dao *CoachesDao) DB() gdb.DB { + return g.DB(dao.group) +} + +// Table returns the table name of the current DAO. +func (dao *CoachesDao) Table() string { + return dao.table +} + +// Columns returns all column names of the current DAO. +func (dao *CoachesDao) Columns() CoachesColumns { + return dao.columns +} + +// Group returns the database configuration group name of the current DAO. +func (dao *CoachesDao) Group() string { + return dao.group +} + +// Ctx creates and returns a Model for the current DAO. It automatically sets the context for the current operation. +func (dao *CoachesDao) Ctx(ctx context.Context) *gdb.Model { + model := dao.DB().Model(dao.table) + for _, handler := range dao.handlers { + model = handler(model) + } + return model.Safe().Ctx(ctx) +} + +// Transaction wraps the transaction logic using function f. +// It rolls back the transaction and returns the error if function f returns a non-nil error. +// It commits the transaction and returns nil if function f returns nil. +// +// Note: Do not commit or roll back the transaction in function f, +// as it is automatically handled by this function. +func (dao *CoachesDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { + return dao.Ctx(ctx).Transaction(ctx, f) +} diff --git a/Backend/internal/dao/internal/comments.go b/Backend/internal/dao/internal/comments.go new file mode 100644 index 0000000..cdff9dd --- /dev/null +++ b/Backend/internal/dao/internal/comments.go @@ -0,0 +1,103 @@ +// ========================================================================== +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ========================================================================== + +package internal + +import ( + "context" + + "github.com/gogf/gf/v2/database/gdb" + "github.com/gogf/gf/v2/frame/g" +) + +// CommentsDao is the data access object for the table comments. +type CommentsDao struct { + table string // table is the underlying table name of the DAO. + group string // group is the database configuration group name of the current DAO. + columns CommentsColumns // columns contains all the column names of Table for convenient usage. + handlers []gdb.ModelHandler // handlers for customized model modification. +} + +// CommentsColumns defines and stores column names for the table comments. +type CommentsColumns struct { + Id string // 评论ID + UserId string // 评论用户ID + TargetType string // 被评论对象类型(如 post/image/video 等) + TargetId string // 被评论对象ID + ParentId string // 父评论ID(回复某条评论时填写) + RootId string // 根评论ID(同一楼的顶层评论ID,便于树查询) + Content string // 评论内容 + Status string // 状态:1正常 0屏蔽 2删除 + LikeCount string // 点赞数 + ReplyCount string // 回复数 + CreatedAt string // 创建时间 + UpdatedAt string // 更新时间 + DeletedAt string // 软删除时间 +} + +// commentsColumns holds the columns for the table comments. +var commentsColumns = CommentsColumns{ + Id: "id", + UserId: "user_id", + TargetType: "target_type", + TargetId: "target_id", + ParentId: "parent_id", + RootId: "root_id", + Content: "content", + Status: "status", + LikeCount: "like_count", + ReplyCount: "reply_count", + CreatedAt: "created_at", + UpdatedAt: "updated_at", + DeletedAt: "deleted_at", +} + +// NewCommentsDao creates and returns a new DAO object for table data access. +func NewCommentsDao(handlers ...gdb.ModelHandler) *CommentsDao { + return &CommentsDao{ + group: "default", + table: "comments", + columns: commentsColumns, + handlers: handlers, + } +} + +// DB retrieves and returns the underlying raw database management object of the current DAO. +func (dao *CommentsDao) DB() gdb.DB { + return g.DB(dao.group) +} + +// Table returns the table name of the current DAO. +func (dao *CommentsDao) Table() string { + return dao.table +} + +// Columns returns all column names of the current DAO. +func (dao *CommentsDao) Columns() CommentsColumns { + return dao.columns +} + +// Group returns the database configuration group name of the current DAO. +func (dao *CommentsDao) Group() string { + return dao.group +} + +// Ctx creates and returns a Model for the current DAO. It automatically sets the context for the current operation. +func (dao *CommentsDao) Ctx(ctx context.Context) *gdb.Model { + model := dao.DB().Model(dao.table) + for _, handler := range dao.handlers { + model = handler(model) + } + return model.Safe().Ctx(ctx) +} + +// Transaction wraps the transaction logic using function f. +// It rolls back the transaction and returns the error if function f returns a non-nil error. +// It commits the transaction and returns nil if function f returns nil. +// +// Note: Do not commit or roll back the transaction in function f, +// as it is automatically handled by this function. +func (dao *CommentsDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { + return dao.Ctx(ctx).Transaction(ctx, f) +} diff --git a/Backend/internal/dao/internal/containment_repo.go b/Backend/internal/dao/internal/containment_repo.go new file mode 100644 index 0000000..14a92d0 --- /dev/null +++ b/Backend/internal/dao/internal/containment_repo.go @@ -0,0 +1,87 @@ +// ========================================================================== +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ========================================================================== + +package internal + +import ( + "context" + + "github.com/gogf/gf/v2/database/gdb" + "github.com/gogf/gf/v2/frame/g" +) + +// ContainmentRepoDao is the data access object for the table containment_repo. +type ContainmentRepoDao struct { + table string // table is the underlying table name of the DAO. + group string // group is the database configuration group name of the current DAO. + columns ContainmentRepoColumns // columns contains all the column names of Table for convenient usage. + handlers []gdb.ModelHandler // handlers for customized model modification. +} + +// ContainmentRepoColumns defines and stores column names for the table containment_repo. +type ContainmentRepoColumns struct { + Id string // auto-increment primary key + AnomalyName string // name of the anomaly (异常体的名字) + AgentName string // agent (特工) + RepoName string // containment repository name or code (收容库) + Department string // 部门 +} + +// containmentRepoColumns holds the columns for the table containment_repo. +var containmentRepoColumns = ContainmentRepoColumns{ + Id: "id", + AnomalyName: "anomaly_name", + AgentName: "agent_name", + RepoName: "repo_name", + Department: "department", +} + +// NewContainmentRepoDao creates and returns a new DAO object for table data access. +func NewContainmentRepoDao(handlers ...gdb.ModelHandler) *ContainmentRepoDao { + return &ContainmentRepoDao{ + group: "default", + table: "containment_repo", + columns: containmentRepoColumns, + handlers: handlers, + } +} + +// DB retrieves and returns the underlying raw database management object of the current DAO. +func (dao *ContainmentRepoDao) DB() gdb.DB { + return g.DB(dao.group) +} + +// Table returns the table name of the current DAO. +func (dao *ContainmentRepoDao) Table() string { + return dao.table +} + +// Columns returns all column names of the current DAO. +func (dao *ContainmentRepoDao) Columns() ContainmentRepoColumns { + return dao.columns +} + +// Group returns the database configuration group name of the current DAO. +func (dao *ContainmentRepoDao) Group() string { + return dao.group +} + +// Ctx creates and returns a Model for the current DAO. It automatically sets the context for the current operation. +func (dao *ContainmentRepoDao) Ctx(ctx context.Context) *gdb.Model { + model := dao.DB().Model(dao.table) + for _, handler := range dao.handlers { + model = handler(model) + } + return model.Safe().Ctx(ctx) +} + +// Transaction wraps the transaction logic using function f. +// It rolls back the transaction and returns the error if function f returns a non-nil error. +// It commits the transaction and returns nil if function f returns nil. +// +// Note: Do not commit or roll back the transaction in function f, +// as it is automatically handled by this function. +func (dao *ContainmentRepoDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { + return dao.Ctx(ctx).Transaction(ctx, f) +} diff --git a/Backend/internal/dao/internal/department.go b/Backend/internal/dao/internal/department.go new file mode 100644 index 0000000..31ce5c4 --- /dev/null +++ b/Backend/internal/dao/internal/department.go @@ -0,0 +1,95 @@ +// ========================================================================== +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ========================================================================== + +package internal + +import ( + "context" + + "github.com/gogf/gf/v2/database/gdb" + "github.com/gogf/gf/v2/frame/g" +) + +// DepartmentDao is the data access object for the table department. +type DepartmentDao struct { + table string // table is the underlying table name of the DAO. + group string // group is the database configuration group name of the current DAO. + columns DepartmentColumns // columns contains all the column names of Table for convenient usage. + handlers []gdb.ModelHandler // handlers for customized model modification. +} + +// DepartmentColumns defines and stores column names for the table department. +type DepartmentColumns struct { + Id string // 自增主键 + UserId string // 所属用户ID(对应 users.id) + BranchName string // 分部名称 + TerminalCount string // 分部散逸端的数量 + Weather string // 分部当前天气/气候描述 + ManagerName string // 分部经理名称 + CreatedAt string // 创建时间 + UpdatedAt string // 更新时间 + Location string // 地址 +} + +// departmentColumns holds the columns for the table department. +var departmentColumns = DepartmentColumns{ + Id: "id", + UserId: "user_id", + BranchName: "branch_name", + TerminalCount: "terminal_count", + Weather: "weather", + ManagerName: "manager_name", + CreatedAt: "created_at", + UpdatedAt: "updated_at", + Location: "location", +} + +// NewDepartmentDao creates and returns a new DAO object for table data access. +func NewDepartmentDao(handlers ...gdb.ModelHandler) *DepartmentDao { + return &DepartmentDao{ + group: "default", + table: "department", + columns: departmentColumns, + handlers: handlers, + } +} + +// DB retrieves and returns the underlying raw database management object of the current DAO. +func (dao *DepartmentDao) DB() gdb.DB { + return g.DB(dao.group) +} + +// Table returns the table name of the current DAO. +func (dao *DepartmentDao) Table() string { + return dao.table +} + +// Columns returns all column names of the current DAO. +func (dao *DepartmentDao) Columns() DepartmentColumns { + return dao.columns +} + +// Group returns the database configuration group name of the current DAO. +func (dao *DepartmentDao) Group() string { + return dao.group +} + +// Ctx creates and returns a Model for the current DAO. It automatically sets the context for the current operation. +func (dao *DepartmentDao) Ctx(ctx context.Context) *gdb.Model { + model := dao.DB().Model(dao.table) + for _, handler := range dao.handlers { + model = handler(model) + } + return model.Safe().Ctx(ctx) +} + +// Transaction wraps the transaction logic using function f. +// It rolls back the transaction and returns the error if function f returns a non-nil error. +// It commits the transaction and returns nil if function f returns nil. +// +// Note: Do not commit or roll back the transaction in function f, +// as it is automatically handled by this function. +func (dao *DepartmentDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { + return dao.Ctx(ctx).Transaction(ctx, f) +} diff --git a/Backend/internal/dao/internal/fans.go b/Backend/internal/dao/internal/fans.go new file mode 100644 index 0000000..f134c88 --- /dev/null +++ b/Backend/internal/dao/internal/fans.go @@ -0,0 +1,91 @@ +// ========================================================================== +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ========================================================================== + +package internal + +import ( + "context" + + "github.com/gogf/gf/v2/database/gdb" + "github.com/gogf/gf/v2/frame/g" +) + +// FansDao is the data access object for the table fans. +type FansDao struct { + table string // table is the underlying table name of the DAO. + group string // group is the database configuration group name of the current DAO. + columns FansColumns // columns contains all the column names of Table for convenient usage. + handlers []gdb.ModelHandler // handlers for customized model modification. +} + +// FansColumns defines and stores column names for the table fans. +type FansColumns struct { + Id string // 自增主键 + UserId string // 用户ID(被关注者,本人) + FanId string // 粉丝用户ID + Status string // 状态:1=粉丝 0=取关/无效 + Remark string // 备注名(user_id 对 fan_id 的备注/分组) + CreatedAt string // 创建时间 + UpdatedAt string // 更新时间 +} + +// fansColumns holds the columns for the table fans. +var fansColumns = FansColumns{ + Id: "id", + UserId: "user_id", + FanId: "fan_id", + Status: "status", + Remark: "remark", + CreatedAt: "created_at", + UpdatedAt: "updated_at", +} + +// NewFansDao creates and returns a new DAO object for table data access. +func NewFansDao(handlers ...gdb.ModelHandler) *FansDao { + return &FansDao{ + group: "default", + table: "fans", + columns: fansColumns, + handlers: handlers, + } +} + +// DB retrieves and returns the underlying raw database management object of the current DAO. +func (dao *FansDao) DB() gdb.DB { + return g.DB(dao.group) +} + +// Table returns the table name of the current DAO. +func (dao *FansDao) Table() string { + return dao.table +} + +// Columns returns all column names of the current DAO. +func (dao *FansDao) Columns() FansColumns { + return dao.columns +} + +// Group returns the database configuration group name of the current DAO. +func (dao *FansDao) Group() string { + return dao.group +} + +// Ctx creates and returns a Model for the current DAO. It automatically sets the context for the current operation. +func (dao *FansDao) Ctx(ctx context.Context) *gdb.Model { + model := dao.DB().Model(dao.table) + for _, handler := range dao.handlers { + model = handler(model) + } + return model.Safe().Ctx(ctx) +} + +// Transaction wraps the transaction logic using function f. +// It rolls back the transaction and returns the error if function f returns a non-nil error. +// It commits the transaction and returns nil if function f returns nil. +// +// Note: Do not commit or roll back the transaction in function f, +// as it is automatically handled by this function. +func (dao *FansDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { + return dao.Ctx(ctx).Transaction(ctx, f) +} diff --git a/Backend/internal/dao/internal/forum_comments.go b/Backend/internal/dao/internal/forum_comments.go new file mode 100644 index 0000000..d7f1d08 --- /dev/null +++ b/Backend/internal/dao/internal/forum_comments.go @@ -0,0 +1,99 @@ +// ========================================================================== +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ========================================================================== + +package internal + +import ( + "context" + + "github.com/gogf/gf/v2/database/gdb" + "github.com/gogf/gf/v2/frame/g" +) + +// ForumCommentsDao is the data access object for the table forum_comments. +type ForumCommentsDao struct { + table string // table is the underlying table name of the DAO. + group string // group is the database configuration group name of the current DAO. + columns ForumCommentsColumns // columns contains all the column names of Table for convenient usage. + handlers []gdb.ModelHandler // handlers for customized model modification. +} + +// ForumCommentsColumns defines and stores column names for the table forum_comments. +type ForumCommentsColumns struct { + Id string // 评论ID(主键) + UserId string // 评论发布者ID(关联users.id,无外键) + PostId string // 所属帖子ID(关联forum_posts.id,无外键) + ParentId string // 父评论ID(NULL=根评论,非NULL=回复某条评论) + Content string // 评论内容(支持emoji) + Status string // 评论状态:normal=正常 deleted=软删除 audit=审核中 reject=审核驳回 + LikeCount string // 点赞数 + ReplyCount string // 回复数(冗余字段) + CreatedAt string // 评论创建时间 + UpdatedAt string // 评论更新时间 + DeletedAt string // 软删除时间 +} + +// forumCommentsColumns holds the columns for the table forum_comments. +var forumCommentsColumns = ForumCommentsColumns{ + Id: "id", + UserId: "user_id", + PostId: "post_id", + ParentId: "parent_id", + Content: "content", + Status: "status", + LikeCount: "like_count", + ReplyCount: "reply_count", + CreatedAt: "created_at", + UpdatedAt: "updated_at", + DeletedAt: "deleted_at", +} + +// NewForumCommentsDao creates and returns a new DAO object for table data access. +func NewForumCommentsDao(handlers ...gdb.ModelHandler) *ForumCommentsDao { + return &ForumCommentsDao{ + group: "default", + table: "forum_comments", + columns: forumCommentsColumns, + handlers: handlers, + } +} + +// DB retrieves and returns the underlying raw database management object of the current DAO. +func (dao *ForumCommentsDao) DB() gdb.DB { + return g.DB(dao.group) +} + +// Table returns the table name of the current DAO. +func (dao *ForumCommentsDao) Table() string { + return dao.table +} + +// Columns returns all column names of the current DAO. +func (dao *ForumCommentsDao) Columns() ForumCommentsColumns { + return dao.columns +} + +// Group returns the database configuration group name of the current DAO. +func (dao *ForumCommentsDao) Group() string { + return dao.group +} + +// Ctx creates and returns a Model for the current DAO. It automatically sets the context for the current operation. +func (dao *ForumCommentsDao) Ctx(ctx context.Context) *gdb.Model { + model := dao.DB().Model(dao.table) + for _, handler := range dao.handlers { + model = handler(model) + } + return model.Safe().Ctx(ctx) +} + +// Transaction wraps the transaction logic using function f. +// It rolls back the transaction and returns the error if function f returns a non-nil error. +// It commits the transaction and returns nil if function f returns nil. +// +// Note: Do not commit or roll back the transaction in function f, +// as it is automatically handled by this function. +func (dao *ForumCommentsDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { + return dao.Ctx(ctx).Transaction(ctx, f) +} diff --git a/Backend/internal/dao/internal/forum_posts.go b/Backend/internal/dao/internal/forum_posts.go new file mode 100644 index 0000000..42ec2c3 --- /dev/null +++ b/Backend/internal/dao/internal/forum_posts.go @@ -0,0 +1,101 @@ +// ========================================================================== +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ========================================================================== + +package internal + +import ( + "context" + + "github.com/gogf/gf/v2/database/gdb" + "github.com/gogf/gf/v2/frame/g" +) + +// ForumPostsDao is the data access object for the table forum_posts. +type ForumPostsDao struct { + table string // table is the underlying table name of the DAO. + group string // group is the database configuration group name of the current DAO. + columns ForumPostsColumns // columns contains all the column names of Table for convenient usage. + handlers []gdb.ModelHandler // handlers for customized model modification. +} + +// ForumPostsColumns defines and stores column names for the table forum_posts. +type ForumPostsColumns struct { + Id string // 帖子ID(主键) + UserId string // 发帖用户ID(关联users.id,无外键) + Title string // 帖子标题 + Content string // 帖子正文(支持富文本/emoji) + CoverImage string // 帖子封面图URL + Status string // 帖子状态:normal=正常 deleted=软删除 audit=审核中 reject=审核驳回 + ViewCount string // 浏览量(冗余字段) + LikeCount string // 点赞数(冗余字段) + CommentCount string // 评论数(冗余字段) + CreatedAt string // 发帖时间 + UpdatedAt string // 更新时间 + DeletedAt string // 软删除时间 +} + +// forumPostsColumns holds the columns for the table forum_posts. +var forumPostsColumns = ForumPostsColumns{ + Id: "id", + UserId: "user_id", + Title: "title", + Content: "content", + CoverImage: "cover_image", + Status: "status", + ViewCount: "view_count", + LikeCount: "like_count", + CommentCount: "comment_count", + CreatedAt: "created_at", + UpdatedAt: "updated_at", + DeletedAt: "deleted_at", +} + +// NewForumPostsDao creates and returns a new DAO object for table data access. +func NewForumPostsDao(handlers ...gdb.ModelHandler) *ForumPostsDao { + return &ForumPostsDao{ + group: "default", + table: "forum_posts", + columns: forumPostsColumns, + handlers: handlers, + } +} + +// DB retrieves and returns the underlying raw database management object of the current DAO. +func (dao *ForumPostsDao) DB() gdb.DB { + return g.DB(dao.group) +} + +// Table returns the table name of the current DAO. +func (dao *ForumPostsDao) Table() string { + return dao.table +} + +// Columns returns all column names of the current DAO. +func (dao *ForumPostsDao) Columns() ForumPostsColumns { + return dao.columns +} + +// Group returns the database configuration group name of the current DAO. +func (dao *ForumPostsDao) Group() string { + return dao.group +} + +// Ctx creates and returns a Model for the current DAO. It automatically sets the context for the current operation. +func (dao *ForumPostsDao) Ctx(ctx context.Context) *gdb.Model { + model := dao.DB().Model(dao.table) + for _, handler := range dao.handlers { + model = handler(model) + } + return model.Safe().Ctx(ctx) +} + +// Transaction wraps the transaction logic using function f. +// It rolls back the transaction and returns the error if function f returns a non-nil error. +// It commits the transaction and returns nil if function f returns nil. +// +// Note: Do not commit or roll back the transaction in function f, +// as it is automatically handled by this function. +func (dao *ForumPostsDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { + return dao.Ctx(ctx).Transaction(ctx, f) +} diff --git a/Backend/internal/dao/internal/group_class_enrollments.go b/Backend/internal/dao/internal/group_class_enrollments.go new file mode 100644 index 0000000..e3aa44e --- /dev/null +++ b/Backend/internal/dao/internal/group_class_enrollments.go @@ -0,0 +1,89 @@ +// ========================================================================== +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ========================================================================== + +package internal + +import ( + "context" + + "github.com/gogf/gf/v2/database/gdb" + "github.com/gogf/gf/v2/frame/g" +) + +// GroupClassEnrollmentsDao is the data access object for the table group_class_enrollments. +type GroupClassEnrollmentsDao struct { + table string // table is the underlying table name of the DAO. + group string // group is the database configuration group name of the current DAO. + columns GroupClassEnrollmentsColumns // columns contains all the column names of Table for convenient usage. + handlers []gdb.ModelHandler // handlers for customized model modification. +} + +// GroupClassEnrollmentsColumns defines and stores column names for the table group_class_enrollments. +type GroupClassEnrollmentsColumns struct { + Id string // 报名ID + ClassId string // 团课ID + UserId string // 用户ID + Status string // 状态:booked已报名,checked_in已签到,cancelled已取消 + EnrolledAt string // 报名时间 + CheckedInAt string // 签到时间 +} + +// groupClassEnrollmentsColumns holds the columns for the table group_class_enrollments. +var groupClassEnrollmentsColumns = GroupClassEnrollmentsColumns{ + Id: "id", + ClassId: "class_id", + UserId: "user_id", + Status: "status", + EnrolledAt: "enrolled_at", + CheckedInAt: "checked_in_at", +} + +// NewGroupClassEnrollmentsDao creates and returns a new DAO object for table data access. +func NewGroupClassEnrollmentsDao(handlers ...gdb.ModelHandler) *GroupClassEnrollmentsDao { + return &GroupClassEnrollmentsDao{ + group: "default", + table: "group_class_enrollments", + columns: groupClassEnrollmentsColumns, + handlers: handlers, + } +} + +// DB retrieves and returns the underlying raw database management object of the current DAO. +func (dao *GroupClassEnrollmentsDao) DB() gdb.DB { + return g.DB(dao.group) +} + +// Table returns the table name of the current DAO. +func (dao *GroupClassEnrollmentsDao) Table() string { + return dao.table +} + +// Columns returns all column names of the current DAO. +func (dao *GroupClassEnrollmentsDao) Columns() GroupClassEnrollmentsColumns { + return dao.columns +} + +// Group returns the database configuration group name of the current DAO. +func (dao *GroupClassEnrollmentsDao) Group() string { + return dao.group +} + +// Ctx creates and returns a Model for the current DAO. It automatically sets the context for the current operation. +func (dao *GroupClassEnrollmentsDao) Ctx(ctx context.Context) *gdb.Model { + model := dao.DB().Model(dao.table) + for _, handler := range dao.handlers { + model = handler(model) + } + return model.Safe().Ctx(ctx) +} + +// Transaction wraps the transaction logic using function f. +// It rolls back the transaction and returns the error if function f returns a non-nil error. +// It commits the transaction and returns nil if function f returns nil. +// +// Note: Do not commit or roll back the transaction in function f, +// as it is automatically handled by this function. +func (dao *GroupClassEnrollmentsDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { + return dao.Ctx(ctx).Transaction(ctx, f) +} diff --git a/Backend/internal/dao/internal/group_classes.go b/Backend/internal/dao/internal/group_classes.go new file mode 100644 index 0000000..3e1fcea --- /dev/null +++ b/Backend/internal/dao/internal/group_classes.go @@ -0,0 +1,99 @@ +// ========================================================================== +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ========================================================================== + +package internal + +import ( + "context" + + "github.com/gogf/gf/v2/database/gdb" + "github.com/gogf/gf/v2/frame/g" +) + +// GroupClassesDao is the data access object for the table group_classes. +type GroupClassesDao struct { + table string // table is the underlying table name of the DAO. + group string // group is the database configuration group name of the current DAO. + columns GroupClassesColumns // columns contains all the column names of Table for convenient usage. + handlers []gdb.ModelHandler // handlers for customized model modification. +} + +// GroupClassesColumns defines and stores column names for the table group_classes. +type GroupClassesColumns struct { + Id string // 团课ID + Title string // 课程名称,如:燃脂搏击、瑜伽 + Description string // 课程介绍 + CoachId string // 授课教练ID + Location string // 上课地点/门店/教室 + StartTime string // 开始时间 + EndTime string // 结束时间 + MaxCapacity string // 最大人数 + Price string // 价格(0表示免费或已包含在会员卡内) + CreatedAt string // 创建时间 + UpdatedAt string // 更新时间 +} + +// groupClassesColumns holds the columns for the table group_classes. +var groupClassesColumns = GroupClassesColumns{ + Id: "id", + Title: "title", + Description: "description", + CoachId: "coach_id", + Location: "location", + StartTime: "start_time", + EndTime: "end_time", + MaxCapacity: "max_capacity", + Price: "price", + CreatedAt: "created_at", + UpdatedAt: "updated_at", +} + +// NewGroupClassesDao creates and returns a new DAO object for table data access. +func NewGroupClassesDao(handlers ...gdb.ModelHandler) *GroupClassesDao { + return &GroupClassesDao{ + group: "default", + table: "group_classes", + columns: groupClassesColumns, + handlers: handlers, + } +} + +// DB retrieves and returns the underlying raw database management object of the current DAO. +func (dao *GroupClassesDao) DB() gdb.DB { + return g.DB(dao.group) +} + +// Table returns the table name of the current DAO. +func (dao *GroupClassesDao) Table() string { + return dao.table +} + +// Columns returns all column names of the current DAO. +func (dao *GroupClassesDao) Columns() GroupClassesColumns { + return dao.columns +} + +// Group returns the database configuration group name of the current DAO. +func (dao *GroupClassesDao) Group() string { + return dao.group +} + +// Ctx creates and returns a Model for the current DAO. It automatically sets the context for the current operation. +func (dao *GroupClassesDao) Ctx(ctx context.Context) *gdb.Model { + model := dao.DB().Model(dao.table) + for _, handler := range dao.handlers { + model = handler(model) + } + return model.Safe().Ctx(ctx) +} + +// Transaction wraps the transaction logic using function f. +// It rolls back the transaction and returns the error if function f returns a non-nil error. +// It commits the transaction and returns nil if function f returns nil. +// +// Note: Do not commit or roll back the transaction in function f, +// as it is automatically handled by this function. +func (dao *GroupClassesDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { + return dao.Ctx(ctx).Transaction(ctx, f) +} diff --git a/Backend/internal/dao/internal/role_cards.go b/Backend/internal/dao/internal/role_cards.go new file mode 100644 index 0000000..c4f72b9 --- /dev/null +++ b/Backend/internal/dao/internal/role_cards.go @@ -0,0 +1,127 @@ +// ========================================================================== +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ========================================================================== + +package internal + +import ( + "context" + + "github.com/gogf/gf/v2/database/gdb" + "github.com/gogf/gf/v2/frame/g" +) + +// RoleCardsDao is the data access object for the table role_cards. +type RoleCardsDao struct { + table string // table is the underlying table name of the DAO. + group string // group is the database configuration group name of the current DAO. + columns RoleCardsColumns // columns contains all the column names of Table for convenient usage. + handlers []gdb.ModelHandler // handlers for customized model modification. +} + +// RoleCardsColumns defines and stores column names for the table role_cards. +type RoleCardsColumns struct { + Id string // 角色卡ID + UserId string // 所属用户ID + DepartmentId string // 所属部门ID + Commendation string // 嘉奖次数 + Reprimand string // 申戒次数 + BlueTrack string // 蓝轨(0-40) + YellowTrack string // 黄轨(0-40) + RedTrack string // 红轨(0-40) + ArcAbnormal string // ARC:异常 + ArcReality string // ARC:现实 + ArcPosition string // ARC:职位 + AgentName string // 特工名字 + CodeName string // 代号 + Gender string // 性别 + QaMeticulous string // Meticulousness (0-100, QA) + QaDeception string // Deception (0-100, QA) + QaVigor string // Vigor / Drive (0-100, QA) + QaEmpathy string // Empathy (0-100, QA) + QaInitiative string // Initiative (0-100, QA) + QaResilience string // Resilience / Persistence (0-100, QA) + QaPresence string // Presence / Charisma (0-100, QA) + QaProfessional string // Professionalism (0-100, QA) + QaDiscretion string // Discretion / Low profile (0-100, QA) + CreatedAt string // 创建时间 + UpdatedAt string // 更新时间 +} + +// roleCardsColumns holds the columns for the table role_cards. +var roleCardsColumns = RoleCardsColumns{ + Id: "id", + UserId: "user_id", + DepartmentId: "department_id", + Commendation: "commendation", + Reprimand: "reprimand", + BlueTrack: "blue_track", + YellowTrack: "yellow_track", + RedTrack: "red_track", + ArcAbnormal: "arc_abnormal", + ArcReality: "arc_reality", + ArcPosition: "arc_position", + AgentName: "agent_name", + CodeName: "code_name", + Gender: "gender", + QaMeticulous: "qa_meticulous", + QaDeception: "qa_deception", + QaVigor: "qa_vigor", + QaEmpathy: "qa_empathy", + QaInitiative: "qa_initiative", + QaResilience: "qa_resilience", + QaPresence: "qa_presence", + QaProfessional: "qa_professional", + QaDiscretion: "qa_discretion", + CreatedAt: "created_at", + UpdatedAt: "updated_at", +} + +// NewRoleCardsDao creates and returns a new DAO object for table data access. +func NewRoleCardsDao(handlers ...gdb.ModelHandler) *RoleCardsDao { + return &RoleCardsDao{ + group: "default", + table: "role_cards", + columns: roleCardsColumns, + handlers: handlers, + } +} + +// DB retrieves and returns the underlying raw database management object of the current DAO. +func (dao *RoleCardsDao) DB() gdb.DB { + return g.DB(dao.group) +} + +// Table returns the table name of the current DAO. +func (dao *RoleCardsDao) Table() string { + return dao.table +} + +// Columns returns all column names of the current DAO. +func (dao *RoleCardsDao) Columns() RoleCardsColumns { + return dao.columns +} + +// Group returns the database configuration group name of the current DAO. +func (dao *RoleCardsDao) Group() string { + return dao.group +} + +// Ctx creates and returns a Model for the current DAO. It automatically sets the context for the current operation. +func (dao *RoleCardsDao) Ctx(ctx context.Context) *gdb.Model { + model := dao.DB().Model(dao.table) + for _, handler := range dao.handlers { + model = handler(model) + } + return model.Safe().Ctx(ctx) +} + +// Transaction wraps the transaction logic using function f. +// It rolls back the transaction and returns the error if function f returns a non-nil error. +// It commits the transaction and returns nil if function f returns nil. +// +// Note: Do not commit or roll back the transaction in function f, +// as it is automatically handled by this function. +func (dao *RoleCardsDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { + return dao.Ctx(ctx).Transaction(ctx, f) +} diff --git a/Backend/internal/dao/internal/subscribe.go b/Backend/internal/dao/internal/subscribe.go new file mode 100644 index 0000000..1cb933d --- /dev/null +++ b/Backend/internal/dao/internal/subscribe.go @@ -0,0 +1,91 @@ +// ========================================================================== +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ========================================================================== + +package internal + +import ( + "context" + + "github.com/gogf/gf/v2/database/gdb" + "github.com/gogf/gf/v2/frame/g" +) + +// SubscribeDao is the data access object for the table subscribe. +type SubscribeDao struct { + table string // table is the underlying table name of the DAO. + group string // group is the database configuration group name of the current DAO. + columns SubscribeColumns // columns contains all the column names of Table for convenient usage. + handlers []gdb.ModelHandler // handlers for customized model modification. +} + +// SubscribeColumns defines and stores column names for the table subscribe. +type SubscribeColumns struct { + Id string // 自增主键 + UserId string // 用户ID(关注者,本人) + FollowId string // 被关注的用户ID + Status string // 状态:1=关注中 0=取消关注 + Remark string // 备注名(user_id 对 follow_id 的备注) + CreatedAt string // 创建时间 + UpdatedAt string // 更新时间 +} + +// subscribeColumns holds the columns for the table subscribe. +var subscribeColumns = SubscribeColumns{ + Id: "id", + UserId: "user_id", + FollowId: "follow_id", + Status: "status", + Remark: "remark", + CreatedAt: "created_at", + UpdatedAt: "updated_at", +} + +// NewSubscribeDao creates and returns a new DAO object for table data access. +func NewSubscribeDao(handlers ...gdb.ModelHandler) *SubscribeDao { + return &SubscribeDao{ + group: "default", + table: "subscribe", + columns: subscribeColumns, + handlers: handlers, + } +} + +// DB retrieves and returns the underlying raw database management object of the current DAO. +func (dao *SubscribeDao) DB() gdb.DB { + return g.DB(dao.group) +} + +// Table returns the table name of the current DAO. +func (dao *SubscribeDao) Table() string { + return dao.table +} + +// Columns returns all column names of the current DAO. +func (dao *SubscribeDao) Columns() SubscribeColumns { + return dao.columns +} + +// Group returns the database configuration group name of the current DAO. +func (dao *SubscribeDao) Group() string { + return dao.group +} + +// Ctx creates and returns a Model for the current DAO. It automatically sets the context for the current operation. +func (dao *SubscribeDao) Ctx(ctx context.Context) *gdb.Model { + model := dao.DB().Model(dao.table) + for _, handler := range dao.handlers { + model = handler(model) + } + return model.Safe().Ctx(ctx) +} + +// Transaction wraps the transaction logic using function f. +// It rolls back the transaction and returns the error if function f returns a non-nil error. +// It commits the transaction and returns nil if function f returns nil. +// +// Note: Do not commit or roll back the transaction in function f, +// as it is automatically handled by this function. +func (dao *SubscribeDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { + return dao.Ctx(ctx).Transaction(ctx, f) +} diff --git a/Backend/internal/dao/internal/trpg_room.go b/Backend/internal/dao/internal/trpg_room.go new file mode 100644 index 0000000..39c7d9b --- /dev/null +++ b/Backend/internal/dao/internal/trpg_room.go @@ -0,0 +1,115 @@ +// ========================================================================== +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ========================================================================== + +package internal + +import ( + "context" + + "github.com/gogf/gf/v2/database/gdb" + "github.com/gogf/gf/v2/frame/g" +) + +// TrpgRoomDao is the data access object for the table trpg_room. +type TrpgRoomDao struct { + table string // table is the underlying table name of the DAO. + group string // group is the database configuration group name of the current DAO. + columns TrpgRoomColumns // columns contains all the column names of Table for convenient usage. + handlers []gdb.ModelHandler // handlers for customized model modification. +} + +// TrpgRoomColumns defines and stores column names for the table trpg_room. +type TrpgRoomColumns struct { + Id string // 自增主键 + RoomId string // 房间全局唯一ID(建议UUID) + RoomCode string // 房间号(玩家看到/输入的房间号) + RoomName string // 房间名称 + HostId string // 主持人用户ID(GM/KP/经理,对应用户表id) + HostNickname string // 主持人昵称(冗余字段,可选) + MaxPlayers string // 最大玩家人数(不含主持人,可按需要约定) + CurrentPlayers string // 当前玩家人数(不含主持人) + HasPassword string // 是否有密码:0无 1有 + RoomPassword string // 房间密码(建议存加密/哈希后的密码) + IsPrivate string // 是否私密房:0公开 1私密 + Status string // 房间状态:0未开始 1进行中 2已结束 3已关闭 + SystemName string // 规则系统:如 COC、DND5E 等 + ScenarioName string // 模组/剧本名称 + Description string // 房间简介/招募说明 + CreatedAt string // 房间创建时间 + StartedAt string // 开团时间 + EndedAt string // 结束时间 + UpdatedAt string // 信息最近更新时间 +} + +// trpgRoomColumns holds the columns for the table trpg_room. +var trpgRoomColumns = TrpgRoomColumns{ + Id: "id", + RoomId: "room_id", + RoomCode: "room_code", + RoomName: "room_name", + HostId: "host_id", + HostNickname: "host_nickname", + MaxPlayers: "max_players", + CurrentPlayers: "current_players", + HasPassword: "has_password", + RoomPassword: "room_password", + IsPrivate: "is_private", + Status: "status", + SystemName: "system_name", + ScenarioName: "scenario_name", + Description: "description", + CreatedAt: "created_at", + StartedAt: "started_at", + EndedAt: "ended_at", + UpdatedAt: "updated_at", +} + +// NewTrpgRoomDao creates and returns a new DAO object for table data access. +func NewTrpgRoomDao(handlers ...gdb.ModelHandler) *TrpgRoomDao { + return &TrpgRoomDao{ + group: "default", + table: "trpg_room", + columns: trpgRoomColumns, + handlers: handlers, + } +} + +// DB retrieves and returns the underlying raw database management object of the current DAO. +func (dao *TrpgRoomDao) DB() gdb.DB { + return g.DB(dao.group) +} + +// Table returns the table name of the current DAO. +func (dao *TrpgRoomDao) Table() string { + return dao.table +} + +// Columns returns all column names of the current DAO. +func (dao *TrpgRoomDao) Columns() TrpgRoomColumns { + return dao.columns +} + +// Group returns the database configuration group name of the current DAO. +func (dao *TrpgRoomDao) Group() string { + return dao.group +} + +// Ctx creates and returns a Model for the current DAO. It automatically sets the context for the current operation. +func (dao *TrpgRoomDao) Ctx(ctx context.Context) *gdb.Model { + model := dao.DB().Model(dao.table) + for _, handler := range dao.handlers { + model = handler(model) + } + return model.Safe().Ctx(ctx) +} + +// Transaction wraps the transaction logic using function f. +// It rolls back the transaction and returns the error if function f returns a non-nil error. +// It commits the transaction and returns nil if function f returns nil. +// +// Note: Do not commit or roll back the transaction in function f, +// as it is automatically handled by this function. +func (dao *TrpgRoomDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { + return dao.Ctx(ctx).Transaction(ctx, f) +} diff --git a/Backend/internal/dao/internal/user_department.go b/Backend/internal/dao/internal/user_department.go new file mode 100644 index 0000000..a726aa1 --- /dev/null +++ b/Backend/internal/dao/internal/user_department.go @@ -0,0 +1,87 @@ +// ========================================================================== +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ========================================================================== + +package internal + +import ( + "context" + + "github.com/gogf/gf/v2/database/gdb" + "github.com/gogf/gf/v2/frame/g" +) + +// UserDepartmentDao is the data access object for the table user_department. +type UserDepartmentDao struct { + table string // table is the underlying table name of the DAO. + group string // group is the database configuration group name of the current DAO. + columns UserDepartmentColumns // columns contains all the column names of Table for convenient usage. + handlers []gdb.ModelHandler // handlers for customized model modification. +} + +// UserDepartmentColumns defines and stores column names for the table user_department. +type UserDepartmentColumns struct { + Id string // + UserId string // 用户ID(对应 users.id) + DeptId string // 部门ID(对应 department.id) + CreatedAt string // 创建时间 + UpdatedAt string // 更新时间 +} + +// userDepartmentColumns holds the columns for the table user_department. +var userDepartmentColumns = UserDepartmentColumns{ + Id: "id", + UserId: "user_id", + DeptId: "dept_id", + CreatedAt: "created_at", + UpdatedAt: "updated_at", +} + +// NewUserDepartmentDao creates and returns a new DAO object for table data access. +func NewUserDepartmentDao(handlers ...gdb.ModelHandler) *UserDepartmentDao { + return &UserDepartmentDao{ + group: "default", + table: "user_department", + columns: userDepartmentColumns, + handlers: handlers, + } +} + +// DB retrieves and returns the underlying raw database management object of the current DAO. +func (dao *UserDepartmentDao) DB() gdb.DB { + return g.DB(dao.group) +} + +// Table returns the table name of the current DAO. +func (dao *UserDepartmentDao) Table() string { + return dao.table +} + +// Columns returns all column names of the current DAO. +func (dao *UserDepartmentDao) Columns() UserDepartmentColumns { + return dao.columns +} + +// Group returns the database configuration group name of the current DAO. +func (dao *UserDepartmentDao) Group() string { + return dao.group +} + +// Ctx creates and returns a Model for the current DAO. It automatically sets the context for the current operation. +func (dao *UserDepartmentDao) Ctx(ctx context.Context) *gdb.Model { + model := dao.DB().Model(dao.table) + for _, handler := range dao.handlers { + model = handler(model) + } + return model.Safe().Ctx(ctx) +} + +// Transaction wraps the transaction logic using function f. +// It rolls back the transaction and returns the error if function f returns a non-nil error. +// It commits the transaction and returns nil if function f returns nil. +// +// Note: Do not commit or roll back the transaction in function f, +// as it is automatically handled by this function. +func (dao *UserDepartmentDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { + return dao.Ctx(ctx).Transaction(ctx, f) +} diff --git a/Backend/internal/dao/internal/users.go b/Backend/internal/dao/internal/users.go new file mode 100644 index 0000000..84d8a65 --- /dev/null +++ b/Backend/internal/dao/internal/users.go @@ -0,0 +1,117 @@ +// ========================================================================== +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ========================================================================== + +package internal + +import ( + "context" + + "github.com/gogf/gf/v2/database/gdb" + "github.com/gogf/gf/v2/frame/g" +) + +// UsersDao is the data access object for the table users. +type UsersDao struct { + table string // table is the underlying table name of the DAO. + group string // group is the database configuration group name of the current DAO. + columns UsersColumns // columns contains all the column names of Table for convenient usage. + handlers []gdb.ModelHandler // handlers for customized model modification. +} + +// UsersColumns defines and stores column names for the table users. +type UsersColumns struct { + Id string // 用户ID + Account string // 账号 + Password string // 密码哈希 + Nickname string // 昵称 + Gender string // 性别:0未知 1男 2女 + BirthDate string // 生日 + UserType string // 用户类型:normal普通用户,vip为VIP用户 + VipStartAt string // VIP开始时间 + VipEndAt string // VIP结束时间 + CreatedAt string // 创建时间 + UpdatedAt string // 更新时间 + RealityRole string // 现实身份/角色 + AbnormalRole string // 异常身份/角色 + JobTitle string // 职位 + Commendation string // + Admonition string // + Email string // + RedTrace string // 红轨 + YellowTrace string // 黄轨 + BlueTrace string // 蓝轨 +} + +// usersColumns holds the columns for the table users. +var usersColumns = UsersColumns{ + Id: "id", + Account: "account", + Password: "password", + Nickname: "nickname", + Gender: "gender", + BirthDate: "birth_date", + UserType: "user_type", + VipStartAt: "vip_start_at", + VipEndAt: "vip_end_at", + CreatedAt: "created_at", + UpdatedAt: "updated_at", + RealityRole: "reality_role", + AbnormalRole: "abnormal_role", + JobTitle: "job_title", + Commendation: "Commendation", + Admonition: "Admonition", + Email: "email", + RedTrace: "red_trace", + YellowTrace: "yellow_trace", + BlueTrace: "blue_trace", +} + +// NewUsersDao creates and returns a new DAO object for table data access. +func NewUsersDao(handlers ...gdb.ModelHandler) *UsersDao { + return &UsersDao{ + group: "default", + table: "users", + columns: usersColumns, + handlers: handlers, + } +} + +// DB retrieves and returns the underlying raw database management object of the current DAO. +func (dao *UsersDao) DB() gdb.DB { + return g.DB(dao.group) +} + +// Table returns the table name of the current DAO. +func (dao *UsersDao) Table() string { + return dao.table +} + +// Columns returns all column names of the current DAO. +func (dao *UsersDao) Columns() UsersColumns { + return dao.columns +} + +// Group returns the database configuration group name of the current DAO. +func (dao *UsersDao) Group() string { + return dao.group +} + +// Ctx creates and returns a Model for the current DAO. It automatically sets the context for the current operation. +func (dao *UsersDao) Ctx(ctx context.Context) *gdb.Model { + model := dao.DB().Model(dao.table) + for _, handler := range dao.handlers { + model = handler(model) + } + return model.Safe().Ctx(ctx) +} + +// Transaction wraps the transaction logic using function f. +// It rolls back the transaction and returns the error if function f returns a non-nil error. +// It commits the transaction and returns nil if function f returns nil. +// +// Note: Do not commit or roll back the transaction in function f, +// as it is automatically handled by this function. +func (dao *UsersDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { + return dao.Ctx(ctx).Transaction(ctx, f) +} diff --git a/Backend/internal/dao/internal/workout_logs.go b/Backend/internal/dao/internal/workout_logs.go new file mode 100644 index 0000000..d09d6fb --- /dev/null +++ b/Backend/internal/dao/internal/workout_logs.go @@ -0,0 +1,95 @@ +// ========================================================================== +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ========================================================================== + +package internal + +import ( + "context" + + "github.com/gogf/gf/v2/database/gdb" + "github.com/gogf/gf/v2/frame/g" +) + +// WorkoutLogsDao is the data access object for the table workout_logs. +type WorkoutLogsDao struct { + table string // table is the underlying table name of the DAO. + group string // group is the database configuration group name of the current DAO. + columns WorkoutLogsColumns // columns contains all the column names of Table for convenient usage. + handlers []gdb.ModelHandler // handlers for customized model modification. +} + +// WorkoutLogsColumns defines and stores column names for the table workout_logs. +type WorkoutLogsColumns struct { + Id string // 健身记录ID + UserId string // 关联的用户ID + WorkoutDate string // 健身日期 + StartTime string // 开始时间 + EndTime string // 结束时间 + DurationMinutes string // 时长(分钟) + Calories string // 估算消耗的卡路里 + Description string // 本次训练的备注,比如训练内容、部位等 + CreatedAt string // 记录创建时间 +} + +// workoutLogsColumns holds the columns for the table workout_logs. +var workoutLogsColumns = WorkoutLogsColumns{ + Id: "id", + UserId: "user_id", + WorkoutDate: "workout_date", + StartTime: "start_time", + EndTime: "end_time", + DurationMinutes: "duration_minutes", + Calories: "calories", + Description: "description", + CreatedAt: "created_at", +} + +// NewWorkoutLogsDao creates and returns a new DAO object for table data access. +func NewWorkoutLogsDao(handlers ...gdb.ModelHandler) *WorkoutLogsDao { + return &WorkoutLogsDao{ + group: "default", + table: "workout_logs", + columns: workoutLogsColumns, + handlers: handlers, + } +} + +// DB retrieves and returns the underlying raw database management object of the current DAO. +func (dao *WorkoutLogsDao) DB() gdb.DB { + return g.DB(dao.group) +} + +// Table returns the table name of the current DAO. +func (dao *WorkoutLogsDao) Table() string { + return dao.table +} + +// Columns returns all column names of the current DAO. +func (dao *WorkoutLogsDao) Columns() WorkoutLogsColumns { + return dao.columns +} + +// Group returns the database configuration group name of the current DAO. +func (dao *WorkoutLogsDao) Group() string { + return dao.group +} + +// Ctx creates and returns a Model for the current DAO. It automatically sets the context for the current operation. +func (dao *WorkoutLogsDao) Ctx(ctx context.Context) *gdb.Model { + model := dao.DB().Model(dao.table) + for _, handler := range dao.handlers { + model = handler(model) + } + return model.Safe().Ctx(ctx) +} + +// Transaction wraps the transaction logic using function f. +// It rolls back the transaction and returns the error if function f returns a non-nil error. +// It commits the transaction and returns nil if function f returns nil. +// +// Note: Do not commit or roll back the transaction in function f, +// as it is automatically handled by this function. +func (dao *WorkoutLogsDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { + return dao.Ctx(ctx).Transaction(ctx, f) +} diff --git a/Backend/internal/dao/role_cards.go b/Backend/internal/dao/role_cards.go new file mode 100644 index 0000000..dc64570 --- /dev/null +++ b/Backend/internal/dao/role_cards.go @@ -0,0 +1,22 @@ +// ================================================================================= +// This file is auto-generated by the GoFrame CLI tool. You may modify it as needed. +// ================================================================================= + +package dao + +import ( + "leke/internal/dao/internal" +) + +// roleCardsDao is the data access object for the table role_cards. +// You can define custom methods on it to extend its functionality as needed. +type roleCardsDao struct { + *internal.RoleCardsDao +} + +var ( + // RoleCards is a globally accessible object for table role_cards operations. + RoleCards = roleCardsDao{internal.NewRoleCardsDao()} +) + +// Add your custom methods and functionality below. diff --git a/Backend/internal/dao/subscribe.go b/Backend/internal/dao/subscribe.go new file mode 100644 index 0000000..370c772 --- /dev/null +++ b/Backend/internal/dao/subscribe.go @@ -0,0 +1,22 @@ +// ================================================================================= +// This file is auto-generated by the GoFrame CLI tool. You may modify it as needed. +// ================================================================================= + +package dao + +import ( + "leke/internal/dao/internal" +) + +// subscribeDao is the data access object for the table subscribe. +// You can define custom methods on it to extend its functionality as needed. +type subscribeDao struct { + *internal.SubscribeDao +} + +var ( + // Subscribe is a globally accessible object for table subscribe operations. + Subscribe = subscribeDao{internal.NewSubscribeDao()} +) + +// Add your custom methods and functionality below. diff --git a/Backend/internal/dao/trpg_room.go b/Backend/internal/dao/trpg_room.go new file mode 100644 index 0000000..f355d79 --- /dev/null +++ b/Backend/internal/dao/trpg_room.go @@ -0,0 +1,22 @@ +// ================================================================================= +// This file is auto-generated by the GoFrame CLI tool. You may modify it as needed. +// ================================================================================= + +package dao + +import ( + "leke/internal/dao/internal" +) + +// trpgRoomDao is the data access object for the table trpg_room. +// You can define custom methods on it to extend its functionality as needed. +type trpgRoomDao struct { + *internal.TrpgRoomDao +} + +var ( + // TrpgRoom is a globally accessible object for table trpg_room operations. + TrpgRoom = trpgRoomDao{internal.NewTrpgRoomDao()} +) + +// Add your custom methods and functionality below. diff --git a/Backend/internal/dao/user_department.go b/Backend/internal/dao/user_department.go new file mode 100644 index 0000000..dae7ea7 --- /dev/null +++ b/Backend/internal/dao/user_department.go @@ -0,0 +1,22 @@ +// ================================================================================= +// This file is auto-generated by the GoFrame CLI tool. You may modify it as needed. +// ================================================================================= + +package dao + +import ( + "leke/internal/dao/internal" +) + +// userDepartmentDao is the data access object for the table user_department. +// You can define custom methods on it to extend its functionality as needed. +type userDepartmentDao struct { + *internal.UserDepartmentDao +} + +var ( + // UserDepartment is a globally accessible object for table user_department operations. + UserDepartment = userDepartmentDao{internal.NewUserDepartmentDao()} +) + +// Add your custom methods and functionality below. diff --git a/Backend/internal/dao/users.go b/Backend/internal/dao/users.go new file mode 100644 index 0000000..54c8f46 --- /dev/null +++ b/Backend/internal/dao/users.go @@ -0,0 +1,22 @@ +// ================================================================================= +// This file is auto-generated by the GoFrame CLI tool. You may modify it as needed. +// ================================================================================= + +package dao + +import ( + "leke/internal/dao/internal" +) + +// usersDao is the data access object for the table users. +// You can define custom methods on it to extend its functionality as needed. +type usersDao struct { + *internal.UsersDao +} + +var ( + // Users is a globally accessible object for table users operations. + Users = usersDao{internal.NewUsersDao()} +) + +// Add your custom methods and functionality below. diff --git a/Backend/internal/dao/workout_logs.go b/Backend/internal/dao/workout_logs.go new file mode 100644 index 0000000..c566fa6 --- /dev/null +++ b/Backend/internal/dao/workout_logs.go @@ -0,0 +1,22 @@ +// ================================================================================= +// This file is auto-generated by the GoFrame CLI tool. You may modify it as needed. +// ================================================================================= + +package dao + +import ( + "leke/internal/dao/internal" +) + +// workoutLogsDao is the data access object for the table workout_logs. +// You can define custom methods on it to extend its functionality as needed. +type workoutLogsDao struct { + *internal.WorkoutLogsDao +} + +var ( + // WorkoutLogs is a globally accessible object for table workout_logs operations. + WorkoutLogs = workoutLogsDao{internal.NewWorkoutLogsDao()} +) + +// Add your custom methods and functionality below. diff --git a/Backend/internal/logic/ForumComments/forum_comments.go b/Backend/internal/logic/ForumComments/forum_comments.go new file mode 100644 index 0000000..ecc04d5 --- /dev/null +++ b/Backend/internal/logic/ForumComments/forum_comments.go @@ -0,0 +1,218 @@ +package ForumComments + +import ( + "context" + "errors" + "github.com/gogf/gf/v2/errors/gerror" + "github.com/gogf/gf/v2/frame/g" + "leke/api/forum/v1" + "leke/internal/dao" + "leke/internal/model/entity" + "leke/internal/service" +) + +// ForumComments 评论相关方法 +type sForumComments struct{} + +func init() { + service.RegisterForumComments(&sForumComments{}) +} + +// ForumCommentsCreate 创建评论 +func (s *sForumComments) Create(ctx context.Context, req *v1.ForumCommentsCreateReq) (res *v1.ForumCommentsCreateRes, err error) { + data := &entity.ForumComments{ + UserId: req.UserId, + PostId: req.PostId, + ParentId: req.ParentId, + Content: req.Content, + Status: req.Status, + LikeCount: 0, + ReplyCount: 0, + } + + result, err := dao.ForumComments.Ctx(ctx).Data(data).OmitEmpty().Insert() + if err != nil { + return nil, gerror.Wrap(err, "创建评论失败") + } + + id, err := result.LastInsertId() + if err != nil { + return nil, gerror.Wrap(err, "获取评论ID失败") + } + + // 更新帖子的评论数 + if req.PostId > 0 { + _, err = dao.ForumPosts.Ctx(ctx).WherePri(req.PostId).OnDuplicate("comment_count", 1).Update() + if err != nil { + g.Log().Warning(ctx, "更新帖子评论数失败:", err) + } + } + + // 如果是回复评论,则更新父评论的回复数 + if req.ParentId > 0 { + _, err = dao.ForumComments.Ctx(ctx).WherePri(req.ParentId).OnDuplicate("reply_count", 1).Update() + if err != nil { + g.Log().Warning(ctx, "更新父评论回复数失败:", err) + } + } + + return &v1.ForumCommentsCreateRes{ + Id: uint64(id), + }, nil +} + +// ForumCommentsUpdate 更新评论 +func (s *sForumComments) Update(ctx context.Context, req *v1.ForumCommentsUpdateReq) (res *v1.ForumCommentsUpdateRes, err error) { + // 检查评论是否存在 + one, err := dao.ForumComments.Ctx(ctx).WherePri(req.Id).One() + if err != nil { + return nil, gerror.Wrap(err, "查询评论失败") + } + if one.IsEmpty() { + return nil, errors.New("评论不存在") + } + + // 更新评论 + _, err = dao.ForumComments.Ctx(ctx).WherePri(req.Id).Data(req).OmitEmpty().Update() + if err != nil { + return nil, gerror.Wrap(err, "更新评论失败") + } + + return &v1.ForumCommentsUpdateRes{ + Id: req.Id, + }, nil +} + +// ForumCommentsView 查看评论 +func (s *sForumComments) View(ctx context.Context, req *v1.ForumCommentsViewReq) (res *v1.ForumCommentsViewRes, err error) { + record, err := dao.ForumComments.Ctx(ctx).WherePri(req.Id).One() + if err != nil { + return nil, gerror.Wrap(err, "查询评论失败") + } + if record.IsEmpty() { + return nil, errors.New("评论不存在") + } + + var entity *entity.ForumComments + err = record.Struct(&entity) + if err != nil { + return nil, gerror.Wrap(err, "解析评论数据失败") + } + + res = &v1.ForumCommentsViewRes{ + Id: entity.Id, + UserId: entity.UserId, + PostId: entity.PostId, + ParentId: entity.ParentId, + Content: entity.Content, + Status: entity.Status, + LikeCount: entity.LikeCount, + ReplyCount: entity.ReplyCount, + CreatedAt: entity.CreatedAt, + UpdatedAt: entity.UpdatedAt, + } + + return res, nil +} + +// ForumCommentsList 评论列表 +func (s *sForumComments) List(ctx context.Context, req *v1.ForumCommentsListReq) (res *v1.ForumCommentsListRes, err error) { + query := dao.ForumComments.Ctx(ctx).OmitEmpty() + + if req.UserId > 0 { + query = query.Where("user_id", req.UserId) + } + if req.PostId > 0 { + query = query.Where("post_id", req.PostId) + } + if req.ParentId > 0 { + query = query.Where("parent_id", req.ParentId) + } + if req.Status != "" { + query = query.Where("status", req.Status) + } + + // 分页查询 + pageResult, err := query.Page(req.Page, req.PageSize).Order("created_at DESC").All() + if err != nil { + return nil, gerror.Wrap(err, "查询评论列表失败") + } + + var list []*v1.ForumCommentsViewRes + for _, record := range pageResult { + var entity *entity.ForumComments + err = record.Struct(&entity) + if err != nil { + return nil, gerror.Wrap(err, "解析评论数据失败") + } + + item := &v1.ForumCommentsViewRes{ + Id: entity.Id, + UserId: entity.UserId, + PostId: entity.PostId, + ParentId: entity.ParentId, + Content: entity.Content, + Status: entity.Status, + LikeCount: entity.LikeCount, + ReplyCount: entity.ReplyCount, + CreatedAt: entity.CreatedAt, + UpdatedAt: entity.UpdatedAt, + } + list = append(list, item) + } + + total, err := query.Count() + if err != nil { + return nil, gerror.Wrap(err, "统计评论总数失败") + } + + res = &v1.ForumCommentsListRes{} + res.List = list + res.Page = req.Page + res.PageSize = req.PageSize + res.Total = total + + return res, nil +} + +// ForumCommentsDelete 删除评论 +func (s *sForumComments) Delete(ctx context.Context, req *v1.ForumCommentsDeleteReq) (res *v1.ForumCommentsDeleteRes, err error) { + // 检查评论是否存在 + one, err := dao.ForumComments.Ctx(ctx).WherePri(req.Id).One() + if err != nil { + return nil, gerror.Wrap(err, "查询评论失败") + } + if one.IsEmpty() { + return nil, errors.New("评论不存在") + } + + var comment *entity.ForumComments + err = one.Struct(&comment) + if err != nil { + return nil, gerror.Wrap(err, "解析评论数据失败") + } + + // 软删除评论 + _, err = dao.ForumComments.Ctx(ctx).WherePri(req.Id).Delete() + if err != nil { + return nil, gerror.Wrap(err, "删除评论失败") + } + + // 更新帖子的评论数 + if comment.PostId > 0 { + _, err = dao.ForumPosts.Ctx(ctx).WherePri(comment.PostId).OnDuplicate("comment_count", 1).Update() + if err != nil { + g.Log().Warning(ctx, "更新帖子评论数失败:", err) + } + } + + // 如果是回复评论,则更新父评论的回复数 + if comment.ParentId > 0 { + _, err = dao.ForumComments.Ctx(ctx).WherePri(comment.ParentId).OnDuplicate("reply_count", 1).Update() + if err != nil { + g.Log().Warning(ctx, "更新父评论回复数失败:", err) + } + } + + return &v1.ForumCommentsDeleteRes{}, nil +} diff --git a/Backend/internal/logic/ForumComments/forum_posts.go b/Backend/internal/logic/ForumComments/forum_posts.go new file mode 100644 index 0000000..8288bf2 --- /dev/null +++ b/Backend/internal/logic/ForumComments/forum_posts.go @@ -0,0 +1,186 @@ +package ForumComments + +import ( + "context" + "errors" + "leke/api/forum/v1" + "leke/internal/dao" + "leke/internal/model/entity" + "leke/internal/service" + + "github.com/gogf/gf/v2/errors/gerror" + "github.com/gogf/gf/v2/frame/g" +) + +type sForumPosts struct{} + +func init() { + service.RegisterForumPosts(&sForumPosts{}) +} + +// ForumPostsCreate 创建帖子 +func (s *sForumPosts) Create(ctx context.Context, req *v1.ForumPostsCreateReq) (res *v1.ForumPostsCreateRes, err error) { + data := &entity.ForumPosts{ + UserId: req.UserId, + Title: req.Title, + Content: req.Content, + CoverImage: req.CoverImage, + Status: req.Status, + ViewCount: 0, + LikeCount: 0, + CommentCount: 0, + } + + result, err := dao.ForumPosts.Ctx(ctx).Data(data).OmitEmpty().Insert() + if err != nil { + return nil, gerror.Wrap(err, "创建帖子失败") + } + + id, err := result.LastInsertId() + if err != nil { + return nil, gerror.Wrap(err, "获取帖子ID失败") + } + + return &v1.ForumPostsCreateRes{ + Id: uint64(id), + }, nil +} + +// ForumPostsUpdate 更新帖子 +func (s *sForumPosts) Update(ctx context.Context, req *v1.ForumPostsUpdateReq) (res *v1.ForumPostsUpdateRes, err error) { + // 检查帖子是否存在 + one, err := dao.ForumPosts.Ctx(ctx).WherePri(req.Id).One() + if err != nil { + return nil, gerror.Wrap(err, "查询帖子失败") + } + if one.IsEmpty() { + return nil, errors.New("帖子不存在") + } + + // 更新帖子 + _, err = dao.ForumPosts.Ctx(ctx).WherePri(req.Id).Data(req).OmitEmpty().Update() + if err != nil { + return nil, gerror.Wrap(err, "更新帖子失败") + } + + return &v1.ForumPostsUpdateRes{ + Id: req.Id, + }, nil +} + +// ForumPostsView 查看帖子 +func (s *sForumPosts) View(ctx context.Context, req *v1.ForumPostsViewReq) (res *v1.ForumPostsViewRes, err error) { + record, err := dao.ForumPosts.Ctx(ctx).WherePri(req.Id).One() + if err != nil { + return nil, gerror.Wrap(err, "查询帖子失败") + } + if record.IsEmpty() { + return nil, errors.New("帖子不存在") + } + + // 更新浏览量 + _, err = dao.ForumPosts.Ctx(ctx).WherePri(req.Id).OnDuplicate("view_count", "view_count+1").Update() + if err != nil { + g.Log().Warning(ctx, "更新浏览量失败:", err) + } + + var entity *entity.ForumPosts + err = record.Struct(&entity) + if err != nil { + return nil, gerror.Wrap(err, "解析帖子数据失败") + } + + res = &v1.ForumPostsViewRes{ + Id: entity.Id, + UserId: entity.UserId, + Title: entity.Title, + Content: entity.Content, + CoverImage: entity.CoverImage, + Status: entity.Status, + ViewCount: entity.ViewCount, + LikeCount: entity.LikeCount, + CommentCount: entity.CommentCount, + CreatedAt: entity.CreatedAt, + UpdatedAt: entity.UpdatedAt, + } + + return res, nil +} + +// ForumPostsList 帖子列表 +func (s *sForumPosts) List(ctx context.Context, req *v1.ForumPostsListReq) (res *v1.ForumPostsListRes, err error) { + query := dao.ForumPosts.Ctx(ctx).OmitEmpty() + + if req.UserId > 0 { + query = query.Where("user_id", req.UserId) + } + if req.Title != "" { + query = query.WhereLike("title", "%"+req.Title+"%") + } + if req.Status != "" { + query = query.Where("status", req.Status) + } + + // 分页查询 + pageResult, err := query.Page(req.Page, req.PageSize).Order("created_at DESC").All() + if err != nil { + return nil, gerror.Wrap(err, "查询帖子列表失败") + } + + var list []*v1.ForumPostsViewRes + for _, record := range pageResult { + var entity *entity.ForumPosts + err = record.Struct(&entity) + if err != nil { + return nil, gerror.Wrap(err, "解析帖子数据失败") + } + + item := &v1.ForumPostsViewRes{ + Id: entity.Id, + UserId: entity.UserId, + Title: entity.Title, + Content: entity.Content, + CoverImage: entity.CoverImage, + Status: entity.Status, + ViewCount: entity.ViewCount, + LikeCount: entity.LikeCount, + CommentCount: entity.CommentCount, + CreatedAt: entity.CreatedAt, + UpdatedAt: entity.UpdatedAt, + } + list = append(list, item) + } + + total, err := query.Count() + if err != nil { + return nil, gerror.Wrap(err, "统计帖子总数失败") + } + + res = &v1.ForumPostsListRes{} + res.List = list + res.PageResult.Page = req.Page + res.PageResult.PageSize = req.PageSize + res.PageResult.Total = total + + return res, nil +} + +// ForumPostsDelete 删除帖子 +func (s *sForumPosts) Delete(ctx context.Context, req *v1.ForumPostsDeleteReq) (res *v1.ForumPostsDeleteRes, err error) { + // 检查帖子是否存在 + one, err := dao.ForumPosts.Ctx(ctx).WherePri(req.Id).One() + if err != nil { + return nil, gerror.Wrap(err, "查询帖子失败") + } + if one.IsEmpty() { + return nil, errors.New("帖子不存在") + } + + // 软删除帖子 + _, err = dao.ForumPosts.Ctx(ctx).WherePri(req.Id).Delete() + if err != nil { + return nil, gerror.Wrap(err, "删除帖子失败") + } + + return &v1.ForumPostsDeleteRes{}, nil +} diff --git a/Backend/internal/logic/containment/containment.go b/Backend/internal/logic/containment/containment.go new file mode 100644 index 0000000..08c4490 --- /dev/null +++ b/Backend/internal/logic/containment/containment.go @@ -0,0 +1,115 @@ +package containment + +import ( + "context" + "github.com/gogf/gf/v2/frame/g" + v1 "leke/api/containment/v1" + "leke/internal/model/response" + "leke/internal/service" +) + +type sContainment struct{} + +func New() *sContainment { + return &sContainment{} +} + +func init() { + service.RegisterContainment(New()) +} + +func (s *sContainment) ContainmentRepoList(ctx context.Context, req *v1.ContainmentRepoListReq) (res *v1.ContainmentRepoListRes, err error) { + m := g.Model("containment_repo") + if req.AgentName != "" { + m.Where("agent_name", req.AgentName) + } + if req.AnomalyName != "" { + m.Where("anomaly_name", req.AnomalyName) + } + if req.RepoName != "" { + m.Where("repo_name", req.RepoName) + } + + // 创建返回结果 + res = &v1.ContainmentRepoListRes{ + PageResult: response.PageResult{ + Page: req.Page, + PageSize: req.PageSize, + }, + } + + // 查询总数 + res.Total, err = m.Count() + if err != nil { + return nil, err + } + + // 分页查询 + m = m.Page(req.Page, req.PageSize) + + // 查询数据列表 + err = m.Scan(&res.List) + if err != nil { + return nil, err + } + + return res, nil +} +func (s *sContainment) ContainmentRepoView(ctx context.Context, req *v1.ContainmentRepoViewReq) (res *v1.ContainmentRepoViewRes, err error) { + // 创建返回结果 + res = &v1.ContainmentRepoViewRes{} + + // 从数据库获取指定ID的数据 + err = g.Model("containment_repo").Where("id", req.Id).Scan(&res.ContainmentRepoInfo) + if err != nil { + return nil, err + } + + return res, nil +} +func (s *sContainment) ContainmentRepoUpdate(ctx context.Context, req *v1.ContainmentRepoUpdateReq) (res *v1.ContainmentRepoUpdateRes, err error) { + // 创建返回结果 + res = &v1.ContainmentRepoUpdateRes{} + + // 准备数据 + data := g.Map{ + "terminal_id": req.TerminalId, + "anomaly_name": req.AnomalyName, + "agent_name": req.AgentName, + "repo_name": req.RepoName, + } + + // 根据ID判断是更新还是新增 + if req.Id > 0 { + // 更新操作 + _, err = g.Model("containment_repo").Data(data).Where("id", req.Id).Update() + res.Id = req.Id + } else { + // 新增操作 + result, err := g.Model("containment_repo").Data(data).Insert() + if err != nil { + return nil, err + } + + // 获取插入记录的ID + id, err := result.LastInsertId() + if err != nil { + return nil, err + } + res.Id = uint64(id) + } + + return res, err +} +func (s *sContainment) ContainmentRepoDelete(ctx context.Context, req *v1.ContainmentRepoDeleteReq) (res *v1.ContainmentRepoDeleteRes, err error) { + // 创建返回结果 + res = &v1.ContainmentRepoDeleteRes{} + + // 删除指定ID的记录 + _, err = g.Model("containment_repo").Where("id", req.Id).Delete() + if err != nil { + return nil, err + } + + return res, nil +} diff --git a/Backend/internal/logic/department/department.go b/Backend/internal/logic/department/department.go new file mode 100644 index 0000000..85473b4 --- /dev/null +++ b/Backend/internal/logic/department/department.go @@ -0,0 +1,143 @@ +package department + +import ( + "context" + v1 "leke/api/department/v1" + "leke/internal/dao" + "leke/internal/model" + "leke/internal/service" +) + +type sDepartment struct{} + +func New() *sDepartment { + return &sDepartment{} +} + +func init() { + service.RegisterDepartment(New()) +} + +// DepartmentList 获取部门列表 +func (s *sDepartment) DepartmentList(ctx context.Context, req *v1.DepartmentListReq) (res *v1.DepartmentListRes, err error) { + // 创建数据库查询模型 + m := dao.Department.Ctx(ctx) + + // 根据分部名称查询 + if req.BranchName != "" { + m = m.WhereLike(dao.Department.Columns().BranchName, "%"+req.BranchName+"%") + } + + // 根据经理名称查询 + if req.ManagerName != "" { + m = m.WhereLike(dao.Department.Columns().ManagerName, "%"+req.ManagerName+"%") + } + + // 根据用户ID查询 + if req.UserId != 0 { + m = m.Where(dao.Department.Columns().UserId, req.UserId) + } + + // 查询总数 + total, err := m.Count() + if err != nil { + return nil, err + } + + // 分页处理 + m = m.Page(req.Page, req.PageSize) + + // 查询列表数据 + var departmentList []*v1.Department + err = m.Scan(&departmentList) + if err != nil { + return nil, err + } + + res = &v1.DepartmentListRes{ + List: departmentList, + } + + // 设置分页信息 + req.PageResult.Total = int(total) + req.PageResult.Page = req.Page + req.PageResult.PageSize = req.PageSize + + return +} + +// DepartmentView 获取部门详情 +func (s *sDepartment) DepartmentView(ctx context.Context, req *v1.DepartmentViewReq) (res *v1.DepartmentViewRes, err error) { + // 创建数据库查询模型 + m := dao.Department.Ctx(ctx) + + // 根据ID查询 + m = m.Where(dao.Department.Columns().Id, req.Id) + + res = &v1.DepartmentViewRes{} + err = m.Scan(&res.Department) + if err != nil { + return nil, err + } + + return +} + +// DepartmentCreate 创建部门 +func (s *sDepartment) DepartmentCreate(ctx context.Context, req *v1.DepartmentCreateReq) (res *v1.DepartmentCreateRes, err error) { + // 准备数据 + departmentData := model.Department{ + UserId: req.UserId, + BranchName: req.BranchName, + TerminalCount: req.TerminalCount, + Weather: req.Weather, + ManagerName: req.ManagerName, + Location: req.Location, + } + + // 插入数据 + result, err := dao.Department.Ctx(ctx).Data(departmentData).Insert() + if err != nil { + return nil, err + } + + // 获取插入的ID + lastInsertId, err := result.LastInsertId() + if err != nil { + return nil, err + } + + res = &v1.DepartmentCreateRes{ + Id: uint64(lastInsertId), + } + + return +} + +// DepartmentUpdate 更新部门 +func (s *sDepartment) DepartmentUpdate(ctx context.Context, req *v1.DepartmentUpdateReq) (res *v1.DepartmentUpdateRes, err error) { + // 更新数据 + _, err = dao.Department.Ctx(ctx).Data(req).Where(dao.Department.Columns().Id, req.Id).Update() + if err != nil { + return nil, err + } + + res = &v1.DepartmentUpdateRes{ + Id: req.Id, + } + + return +} + +// DepartmentDelete 删除部门 +func (s *sDepartment) DepartmentDelete(ctx context.Context, req *v1.DepartmentDeleteReq) (res *v1.DepartmentDeleteRes, err error) { + // 根据ID删除 + _, err = dao.Department.Ctx(ctx).Where(dao.Department.Columns().Id, req.Id).Delete() + if err != nil { + return nil, err + } + + res = &v1.DepartmentDeleteRes{} + + return +} diff --git a/Backend/internal/logic/fans/fans.go b/Backend/internal/logic/fans/fans.go new file mode 100644 index 0000000..e31e324 --- /dev/null +++ b/Backend/internal/logic/fans/fans.go @@ -0,0 +1,182 @@ +package fans + +import ( + "context" + + "github.com/gogf/gf/v2/os/gtime" + v1 "leke/api/user/v1" + "leke/internal/dao" + "leke/internal/service" +) + +type sFans struct{} + +func New() *sFans { + return &sFans{} +} + +func init() { + service.RegisterFans(New()) +} + +// FansList 获取粉丝列表 +// +// 参数: +// - ctx context.Context: 上下文信息 +// - req *v1.FansListReq: 粉丝列表请求参数 +// +// 返回: +// - res *v1.FansListRes: 粉丝列表响应结果 +// - err error: 错误信息 +func (s *sFans) FansList(ctx context.Context, req *v1.FansListReq) (res *v1.FansListRes, err error) { + // 创建数据库查询模型 + m := dao.Fans.Ctx(ctx) + + // 根据用户ID查询 + m = m.Where(dao.Fans.Columns().UserId, req.UserId) + + // 根据状态查询 + if req.Status != 0 { + m = m.Where(dao.Fans.Columns().Status, req.Status) + } + + // 查询总数 + total, err := m.Count() + if err != nil { + return nil, err + } + + // 分页处理 + m = m.Page(req.Page, req.PageSize) + + // 查询列表数据 + var fansList []*v1.FansListItem + err = m.Scan(&fansList) + if err != nil { + return nil, err + } + + res = &v1.FansListRes{ + List: fansList, + } + + // 设置分页信息 + req.PageResult.Total = int(total) + req.PageResult.Page = req.Page + req.PageResult.PageSize = req.PageSize + + return +} + +// FansView 获取粉丝详情 +// +// 参数: +// - ctx context.Context: 上下文信息 +// - req *v1.FansViewReq: 粉丝详情请求参数 +// +// 返回: +// - res *v1.FansViewRes: 粉丝详情响应结果 +// - err error: 错误信息 +func (s *sFans) FansView(ctx context.Context, req *v1.FansViewReq) (res *v1.FansViewRes, err error) { + // 创建数据库查询模型 + m := dao.Fans.Ctx(ctx) + + // 根据ID查询 + m = m.Where(dao.Fans.Columns().Id, req.Id) + + res = &v1.FansViewRes{} + err = m.Scan(&res.FansListItem) + if err != nil { + return nil, err + } + + return +} + +// FansUpdate 更新粉丝信息 +// +// 参数: +// - ctx context.Context: 上下文信息 +// - req *v1.FansUpdateReq: 粉丝更新请求参数 +// +// 返回: +// - res *v1.FansUpdateRes: 粉丝更新响应结果 +// - err error: 错误信息 +func (s *sFans) FansUpdate(ctx context.Context, req *v1.FansUpdateReq) (res *v1.FansUpdateRes, err error) { + // 创建数据库查询模型 + m := dao.Fans.Ctx(ctx) + + // 更新粉丝信息 + _, err = m.Data(req).Where(dao.Fans.Columns().Id, req.Id).Update() + if err != nil { + return nil, err + } + + res = &v1.FansUpdateRes{ + Id: req.Id, + } + + return +} + +// FansDelete 删除粉丝关系 +// +// 参数: +// - ctx context.Context: 上下文信息 +// - req *v1.FansDeleteReq: 粉丝删除请求参数 +// +// 返回: +// - res *v1.FansDeleteRes: 粉丝删除响应结果 +// - err error: 错误信息 +func (s *sFans) FansDelete(ctx context.Context, req *v1.FansDeleteReq) (res *v1.FansDeleteRes, err error) { + // 根据ID删除粉丝关系 + _, err = dao.Fans.Ctx(ctx).Where(dao.Fans.Columns().Id, req.Id).Delete() + if err != nil { + return nil, err + } + + res = &v1.FansDeleteRes{} + return +} + +// FansCreate 创建粉丝关系 +// +// 参数: +// - ctx context.Context: 上下文信息 +// - req *v1.FansCreateReq: 粉丝创建请求参数 +// +// 返回: +// - res *v1.FansCreateRes: 粉丝创建响应结果 +// - err error: 错误信息 +func (s *sFans) FansCreate(ctx context.Context, req *v1.FansCreateReq) (res *v1.FansCreateRes, err error) { + // 创建数据库查询模型 + m := dao.Fans.Ctx(ctx) + + // 准备数据 + data := map[string]interface{}{ + "user_id": req.UserId, + "fan_id": req.FanId, + "status": 1, // 默认状态为关注中 + "remark": req.Remark, + "created_at": gtime.Now(), + "updated_at": gtime.Now(), + } + + // 插入数据 + result, err := m.Data(data).Insert() + if err != nil { + return nil, err + } + + // 获取插入的ID + lastInsertId, err := result.LastInsertId() + if err != nil { + return nil, err + } + + res = &v1.FansCreateRes{ + Id: uint64(lastInsertId), + } + + return +} diff --git a/Backend/internal/logic/logic.go b/Backend/internal/logic/logic.go new file mode 100644 index 0000000..fb653dc --- /dev/null +++ b/Backend/internal/logic/logic.go @@ -0,0 +1,17 @@ +// ========================================================================== +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ========================================================================== + +package logic + +import ( + _ "leke/internal/logic/ForumComments" + _ "leke/internal/logic/containment" + _ "leke/internal/logic/department" + _ "leke/internal/logic/fans" + _ "leke/internal/logic/login" + _ "leke/internal/logic/room" + _ "leke/internal/logic/subscribe" + _ "leke/internal/logic/trace" + _ "leke/internal/logic/user" +) diff --git a/Backend/internal/logic/login/login.go b/Backend/internal/logic/login/login.go new file mode 100644 index 0000000..4eb03c3 --- /dev/null +++ b/Backend/internal/logic/login/login.go @@ -0,0 +1,296 @@ +// Package login internal/logic/login/login.go +package login + +import ( + "context" + "database/sql" + "errors" + "fmt" + v1 "leke/api/login/v1" + "leke/internal/consts" + "leke/internal/dao" + "leke/internal/middleware" + "leke/internal/model" + "leke/internal/service" + "time" + + "github.com/gogf/gf/v2/crypto/gmd5" + "github.com/gogf/gf/v2/errors/gcode" + "github.com/gogf/gf/v2/errors/gerror" + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/glog" + "github.com/gogf/gf/v2/util/grand" + "github.com/golang-jwt/jwt/v5" +) + +// 注意:名字改成 sLogin,首字母小写 s + 大写 Login +type sLogin struct{} + +func New() *sLogin { + return &sLogin{} +} + +// 关键!!在 init 里完成注册 +func init() { + service.RegisterLogin(New()) +} + +func (s *sLogin) Register(ctx context.Context, loginReq *v1.RegisterReq) (res *v1.RegisterRes, err error) { + + // 判断参数是否正常 账户的长度要在5-10 密码要经过MD5加密 + if len(loginReq.Account) < 5 || len(loginReq.Account) > 10 { + glog.Debugf(ctx, "账户长度校验失败,长度:%d", len(loginReq.Account)) + return nil, errors.New("账户长度要在5-10之间") + } + if len(loginReq.Password) < 6 || len(loginReq.Password) > 32 { + glog.Debugf(ctx, "密码长度校验失败,长度:%d", len(loginReq.Password)) + return nil, errors.New("密码长度要在6-32之间") + } + + password, err := gmd5.Encrypt(loginReq.Password + consts.Salt) + if err != nil { + glog.Errorf(ctx, "密码加密失败:%v", err) + return nil, gerror.Wrap(err, "密码加密失败,请稍后重试!") + } + + loginData := model.LoginField{ + Account: loginReq.Account, + Password: password, + Nickname: "特工007", + } + + _, err = dao.Users.Ctx(ctx).Data(loginData).Insert() + if err != nil { + glog.Errorf(ctx, "插入账号到数据库失败:%v", err) + return nil, gerror.Wrap(err, "插入账号到数,据库失败,请稍后重试!") + } + return +} + +func (s *sLogin) Login(ctx context.Context, loginReq *v1.LoginReq) (res *v1.LoginRes, err error) { + + //校验参数 + if len(loginReq.Account) < 5 || len(loginReq.Account) > 10 { + glog.Debugf(ctx, "账户长度校验失败,长度:%d", len(loginReq.Account)) + return nil, errors.New("账户长度要在5-10之间") + } + if len(loginReq.Password) < 6 || len(loginReq.Password) > 32 { + glog.Debugf(ctx, "密码长度校验失败,长度:%d", len(loginReq.Password)) + return nil, errors.New("密码长度要在6-32之间") + } + + // 2. 先根据账号查数据库 + var user model.LoginField + err = dao.Users.Ctx(ctx).Where("account", loginReq.Account).Scan(&user) + if err != nil { + glog.Errorf(ctx, "查询用户失败:%v", err) + return nil, gerror.Wrap(err, "登录失败,请稍后重试!") + } + if user.Account == "" { + // 没查到用户 + return nil, gerror.NewCode(gcode.CodeInvalidParameter, "账号或密码错误") + } + + // 3. 使用"相同规则"加密用户输入的密码,并和 DB 中的密码对比 + // 注意:这里的加密规则必须和 Register 时一致 + encryptedInput, err := gmd5.Encrypt(loginReq.Password + consts.Salt) + if err != nil { + glog.Errorf(ctx, "密码加密失败:%v", err) + return nil, gerror.Wrap(err, "密码加密失败,请稍后重试!") + } + if user.Password != encryptedInput { + return nil, gerror.NewCode(gcode.CodeInvalidParameter, "账号或密码错误") + } + + // 5. 种 Session(如果你确实需要 session) + if err := setSession(ctx, user.Account); err != nil { + glog.Errorf(ctx, "设置Session失败:%v", err) + return nil, gerror.Wrap(err, "设置登录状态失败,请稍后重试!") + } + + //JWT 生成 + // Create claims with user information + claims := &middleware.JWTClaims{ + Username: loginReq.Account, + RegisteredClaims: jwt.RegisteredClaims{ + ExpiresAt: jwt.NewNumericDate(time.Now().Add(24 * time.Hour)), + IssuedAt: jwt.NewNumericDate(time.Now()), + NotBefore: jwt.NewNumericDate(time.Now()), + }, + } + + // 生成Token + token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) + signedToken, err := token.SignedString([]byte(middleware.JwtSecretKey)) + if err != nil { + return nil, gerror.NewCode(gcode.CodeInternalError, "Failed to generate token") + } + res = &v1.LoginRes{ + Token: signedToken, + Account: user.Account, + } + return +} + +// 通过邮箱注册 +func (s *sLogin) RegisterByEmail(ctx context.Context, req *v1.RegisterByEmailReq) (res *v1.RegisterByEmailRes, err error) { + // 先验证验证码 + emailService := service.NewEmailService() + if !emailService.VerifyVerificationCode(req.Email, req.Code) { + return nil, gerror.NewCode(gcode.CodeInvalidParameter, "验证码错误或已过期") + } + + // 检查邮箱是否已存在 + count, err := dao.Users.Ctx(ctx).Where("email", req.Email).Count() + if err != nil { + return nil, gerror.Wrap(err, "查询用户失败") + } + if count > 0 { + return nil, gerror.NewCode(gcode.CodeInvalidParameter, "该邮箱已被注册") + } + + // 生成随机账号和密码 + account := fmt.Sprintf("user_%s", grand.S(6)) + password := grand.S(10) + + // 加密密码 + encryptedPassword, err := gmd5.Encrypt(password + consts.Salt) + if err != nil { + return nil, gerror.Wrap(err, "密码加密失败") + } + + // 创建用户 + userData := model.LoginField{ + Account: account, + Password: encryptedPassword, + Nickname: "特工007", + Email: req.Email, + } + + _, err = dao.Users.Ctx(ctx).Data(userData).Insert() + if err != nil { + return nil, gerror.Wrap(err, "注册失败") + } + + res = &v1.RegisterByEmailRes{ + Email: req.Email, + } + return +} + +// 通过邮箱登录 +func (s *sLogin) LoginByEmail(ctx context.Context, req *v1.LoginByEmailReq) (res *v1.LoginByEmailRes, err error) { + emailService := service.NewEmailService() + + // 验证验证码 + if !emailService.VerifyVerificationCode(req.Email, req.Code) { + return nil, gerror.NewCode(gcode.CodeInvalidParameter, "验证码错误或已过期") + } + + // 根据邮箱查找用户 + var user model.LoginField + err = dao.Users.Ctx(ctx).Where("email", req.Email).Scan(&user) + if err != nil && err != sql.ErrNoRows { + return nil, gerror.WrapCode(gcode.CodeInternalError, err, "查询用户失败") + } + + // 如果用户不存在,则创建新用户 + if user.Email == "" { + account := fmt.Sprintf("user_%s", grand.S(6)) + password := grand.S(10) + + // 加密密码 + encryptedPassword, err := gmd5.Encrypt(password + consts.Salt) + if err != nil { + return nil, gerror.Wrap(err, "密码加密失败") + } + + // 创建用户 + userData := model.LoginField{ + Account: account, + Password: encryptedPassword, + Nickname: "特工007", + Email: req.Email, + } + + _, err = dao.Users.Ctx(ctx).Data(userData).Insert() + if err != nil { + return nil, gerror.Wrap(err, "创建用户失败") + } + + user = userData + } + + // 设置session + if err := setSession(ctx, user.Account); err != nil { + glog.Errorf(ctx, "设置Session失败:%v", err) + return nil, gerror.Wrap(err, "设置登录状态失败,请稍后重试!") + } + + // 生成JWT Token + claims := &middleware.JWTClaims{ + Username: user.Account, + RegisteredClaims: jwt.RegisteredClaims{ + ExpiresAt: jwt.NewNumericDate(time.Now().Add(24 * time.Hour)), + IssuedAt: jwt.NewNumericDate(time.Now()), + NotBefore: jwt.NewNumericDate(time.Now()), + }, + } + + token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) + signedToken, err := token.SignedString([]byte(middleware.JwtSecretKey)) + if err != nil { + return nil, gerror.NewCode(gcode.CodeInternalError, "Failed to generate token") + } + + res = &v1.LoginByEmailRes{ + Token: signedToken, + Email: req.Email, + } + + return +} + +// 发送验证码 +func (s *sLogin) SendVerificationCode(ctx context.Context, req *v1.SendVerificationCodeReq) (res *v1.SendVerificationCodeRes, err error) { + emailService := service.NewEmailService() + + err = emailService.SendVerificationCode(ctx, req.Email) + if err != nil { + return nil, gerror.Wrap(err, "发送验证码失败") + } + + res = &v1.SendVerificationCodeRes{ + Success: true, + } + + return +} + +// 退出登录 +func (s *sLogin) Logout(ctx context.Context, req *v1.LogoutReq) (res *v1.LogoutRes, err error) { + // 从上下文里拿到当前请求 + r := g.RequestFromCtx(ctx) + if r == nil { + return nil, gerror.New("无效的请求上下文") + } + + // 1. 删除当前登录用到的 Session 信息 + // 和 Login / setSession 里保持一致:都是用 "userAccount" 这个 key + if err = r.Session.Remove("userAccount"); err != nil { + glog.Errorf(ctx, "删除Session失败:%v", err) + return nil, gerror.Wrap(err, "退出登录失败,请稍后重试!") + } + + // 如果你想彻底清空这个 Session(不只删一个字段),可以用: + // if err = r.Session.RemoveAll(); err != nil { ... } + + // 2. 构造返回结果(一般是一个空结构就够了) + res = &v1.LogoutRes{} + return res, nil +} + +// 给前端种session +func setSession(ctx context.Context, account string) error { + return g.RequestFromCtx(ctx).Session.Set("userAccount", account) +} diff --git a/Backend/internal/logic/room/room.go b/Backend/internal/logic/room/room.go new file mode 100644 index 0000000..a11aa1e --- /dev/null +++ b/Backend/internal/logic/room/room.go @@ -0,0 +1,252 @@ +package room + +import ( + "context" + v1 "leke/api/room/v1" + "leke/internal/dao" + "leke/internal/model" + "leke/internal/model/entity" + "leke/internal/service" +) + +type sRoom struct{} + +func New() *sRoom { + return &sRoom{} +} + +func init() { + service.RegisterRoom(New()) +} + +func (s *sRoom) RoomList(ctx context.Context, req *v1.RoomListReq) (res *v1.RoomListRes, err error) { + // 构建查询条件 + m := dao.TrpgRoom.Ctx(ctx) + + if req.RoomCode != "" { + m = m.Where(dao.TrpgRoom.Columns().RoomCode, req.RoomCode) + } + if req.RoomName != "" { + m = m.Where(dao.TrpgRoom.Columns().RoomName, req.RoomName) + } + if req.HostId != 0 { + m = m.Where(dao.TrpgRoom.Columns().HostId, req.HostId) + } + if req.Status != 0 { + m = m.Where(dao.TrpgRoom.Columns().Status, req.Status) + } + if req.SystemName != "" { + m = m.Where(dao.TrpgRoom.Columns().SystemName, req.SystemName) + } + + // 分页处理 + if req.Page <= 0 { + req.Page = 1 + } + if req.PageSize <= 0 { + req.PageSize = 10 + } + + // 查询总数 + totalCount, err := m.Count() + if err != nil { + return nil, err + } + + // 查询数据列表 + var rooms []*entity.TrpgRoom + err = m.Page(req.Page, req.PageSize).Scan(&rooms) + if err != nil { + return nil, err + } + + // 组装返回结果 + res = &v1.RoomListRes{ + PageResult: req.PageResult, + Rooms: make([]*model.RoomParams, len(rooms)), + } + + // 转换数据格式 + for i, room := range rooms { + res.Rooms[i] = &model.RoomParams{ + Id: room.Id, + RoomId: room.RoomId, + RoomCode: room.RoomCode, + RoomName: room.RoomName, + HostId: room.HostId, + HostNickname: room.HostNickname, + MaxPlayers: room.MaxPlayers, + CurrentPlayers: room.CurrentPlayers, + HasPassword: room.HasPassword, + IsPrivate: room.IsPrivate, + Status: room.Status, + SystemName: room.SystemName, + ScenarioName: room.ScenarioName, + Description: room.Description, + CreatedAt: room.CreatedAt, + StartedAt: room.StartedAt, + EndedAt: room.EndedAt, + UpdatedAt: room.UpdatedAt, + } + } + + // 设置分页信息 + res.PageResult.Total = totalCount + res.PageResult.Page = req.Page + res.PageResult.PageSize = req.PageSize + + return res, nil +} + +func (s *sRoom) RoomView(ctx context.Context, req *v1.RoomViewReq) (res *v1.RoomViewRes, err error) { + // 构建查询条件 + m := dao.TrpgRoom.Ctx(ctx) + + if req.Id != 0 { + m = m.Where(dao.TrpgRoom.Columns().Id, req.Id) + } + if req.RoomCode != "" { + m = m.Where(dao.TrpgRoom.Columns().RoomCode, req.RoomCode) + } + + // 查询数据 + var room *entity.TrpgRoom + err = m.Scan(&room) + if err != nil { + return nil, err + } + if room == nil { + return nil, nil + } + + // 组装返回结果 + res = &v1.RoomViewRes{ + RoomView: model.RoomView{ + Id: room.Id, + RoomId: room.RoomId, + RoomCode: room.RoomCode, + RoomName: room.RoomName, + HostId: room.HostId, + HostNickname: room.HostNickname, + MaxPlayers: room.MaxPlayers, + CurrentPlayers: room.CurrentPlayers, + HasPassword: room.HasPassword, + IsPrivate: room.IsPrivate, + Status: room.Status, + SystemName: room.SystemName, + ScenarioName: room.ScenarioName, + Description: room.Description, + CreatedAt: room.CreatedAt, + StartedAt: room.StartedAt, + EndedAt: room.EndedAt, + }, + } + + return res, nil +} + +func (s *sRoom) RoomUpdate(ctx context.Context, req *v1.RoomUpdateReq) (res *v1.RoomUpdateRes, err error) { + // 根据房间号更新房间信息 + data := model.RoomParams{ + RoomName: req.RoomName, + HostId: req.HostId, + HostNickname: req.HostNickname, + MaxPlayers: req.MaxPlayers, + CurrentPlayers: req.CurrentPlayers, + HasPassword: req.HasPassword, + IsPrivate: req.IsPrivate, + Status: req.Status, + SystemName: req.SystemName, + ScenarioName: req.ScenarioName, + Description: req.Description, + } + + _, err = dao.TrpgRoom.Ctx(ctx).Data(data).Where(dao.TrpgRoom.Columns().RoomCode, req.RoomCode).Update() + if err != nil { + return nil, err + } + + // 获取更新后的房间ID + var room *entity.TrpgRoom + err = dao.TrpgRoom.Ctx(ctx).Where(dao.TrpgRoom.Columns().RoomCode, req.RoomCode).Scan(&room) + if err != nil { + return nil, err + } + + res = &v1.RoomUpdateRes{ + Id: room.Id, + } + + return res, nil +} + +func (s *sRoom) RoomDelete(ctx context.Context, req *v1.RoomDeleteReq) (res *v1.RoomDeleteRes, err error) { + // 根据房间号删除房间 + _, err = dao.TrpgRoom.Ctx(ctx).Where(dao.TrpgRoom.Columns().RoomCode, req.RoomCode).Delete() + if err != nil { + return nil, err + } + + res = &v1.RoomDeleteRes{} + return res, nil +} + +func (s *sRoom) RoomCreate(ctx context.Context, req *v1.RoomCreateReq) (res *v1.RoomCreateRes, err error) { + // 准备房间数据 + room := entity.TrpgRoom{ + RoomCode: req.RoomCode, + RoomName: req.RoomName, + HostId: req.HostId, + MaxPlayers: req.MaxPlayers, + HasPassword: req.HasPassword, + IsPrivate: req.IsPrivate, + SystemName: req.SystemName, + ScenarioName: req.ScenarioName, + Description: req.Description, + Status: 0, // 默认状态为未开始 + } + + // 插入数据库 + result, err := dao.TrpgRoom.Ctx(ctx).Data(room).Insert() + if err != nil { + return nil, err + } + + // 获取插入的ID + id, err := result.LastInsertId() + if err != nil { + return nil, err + } + + // 返回结果 + res = &v1.RoomCreateRes{ + Id: uint64(id), + RoomCode: req.RoomCode, + } + + return res, nil +} + +func (s *sRoom) RoomJoin(ctx context.Context, req *v1.RoomJoinReq) (res *v1.RoomJoinRes, err error) { + if req.RoomId == 0 { + return nil, nil + } + + var room *entity.TrpgRoom + err = dao.TrpgRoom.Ctx(ctx). + Where(dao.TrpgRoom.Columns().Id, req.RoomId). + Scan(&room) + if err != nil { + return nil, err + } + if room == nil { + return nil, nil + } + + res = &v1.RoomJoinRes{ + Id: room.Id, + RoomCode: room.RoomCode, + } + + return res, nil +} diff --git a/Backend/internal/logic/subscribe/subscribe.go b/Backend/internal/logic/subscribe/subscribe.go new file mode 100644 index 0000000..44d7068 --- /dev/null +++ b/Backend/internal/logic/subscribe/subscribe.go @@ -0,0 +1,146 @@ +package subscribe + +import ( + "context" + v1 "leke/api/user/v1" + "leke/internal/dao" + "leke/internal/service" + "github.com/gogf/gf/v2/os/gtime" +) + +type sSubscribe struct{} + +func New() *sSubscribe { + return &sSubscribe{} +} + +func init() { + service.RegisterSubscribe(New()) +} + +// SubscribeList 获取关注列表 +func (s *sSubscribe) SubscribeList(ctx context.Context, req *v1.SubscribeListReq) (res *v1.SubscribeListRes, err error) { + // 创建数据库查询模型 + m := dao.Subscribe.Ctx(ctx) + + // 根据用户ID查询 + m = m.Where(dao.Subscribe.Columns().UserId, req.UserId) + + // 根据状态查询 + if req.Status != 0 { + m = m.Where(dao.Subscribe.Columns().Status, req.Status) + } + + // 根据被关注用户ID查询 + if req.FollowId != 0 { + m = m.Where(dao.Subscribe.Columns().FollowId, req.FollowId) + } + + // 查询总数 + total, err := m.Count() + if err != nil { + return nil, err + } + + // 分页处理 + m = m.Page(req.Page, req.PageSize) + + // 查询列表数据 + var subscribeList []*v1.SubscribeListItem + err = m.Scan(&subscribeList) + if err != nil { + return nil, err + } + + res = &v1.SubscribeListRes{ + List: subscribeList, + } + + // 设置分页信息 + req.PageResult.Total = int(total) + req.PageResult.Page = req.Page + req.PageResult.PageSize = req.PageSize + + return +} + +// SubscribeView 获取关注详情 +func (s *sSubscribe) SubscribeView(ctx context.Context, req *v1.SubscribeViewReq) (res *v1.SubscribeViewRes, err error) { + // 创建数据库查询模型 + m := dao.Subscribe.Ctx(ctx) + + // 根据ID查询 + m = m.Where(dao.Subscribe.Columns().Id, req.Id) + + res = &v1.SubscribeViewRes{} + err = m.Scan(&res.SubscribeListItem) + if err != nil { + return nil, err + } + + return +} + +// SubscribeUpdate 更新关注信息 +func (s *sSubscribe) SubscribeUpdate(ctx context.Context, req *v1.SubscribeUpdateReq) (res *v1.SubscribeUpdateRes, err error) { + // 创建数据库查询模型 + m := dao.Subscribe.Ctx(ctx) + + // 更新关注信息 + _, err = m.Data(req).Where(dao.Subscribe.Columns().Id, req.Id).Update() + if err != nil { + return nil, err + } + + res = &v1.SubscribeUpdateRes{ + Id: req.Id, + } + + return +} + +// SubscribeDelete 删除关注关系 +func (s *sSubscribe) SubscribeDelete(ctx context.Context, req *v1.SubscribeDeleteReq) (res *v1.SubscribeDeleteRes, err error) { + // 根据ID删除关注关系 + _, err = dao.Subscribe.Ctx(ctx).Where(dao.Subscribe.Columns().Id, req.Id).Delete() + if err != nil { + return nil, err + } + + res = &v1.SubscribeDeleteRes{} + return +} + +// SubscribeCreate 创建关注关系 +func (s *sSubscribe) SubscribeCreate(ctx context.Context, req *v1.SubscribeCreateReq) (res *v1.SubscribeCreateRes, err error) { + // 创建数据库查询模型 + m := dao.Subscribe.Ctx(ctx) + + // 准备数据 + data := map[string]interface{}{ + "user_id": req.UserId, + "follow_id": req.FollowId, + "status": 1, // 默认状态为关注中 + "remark": req.Remark, + "created_at": gtime.Now(), + "updated_at": gtime.Now(), + } + + // 插入数据 + result, err := m.Data(data).Insert() + if err != nil { + return nil, err + } + + // 获取插入的ID + lastInsertId, err := result.LastInsertId() + if err != nil { + return nil, err + } + + res = &v1.SubscribeCreateRes{ + Id: uint64(lastInsertId), + } + + return +} \ No newline at end of file diff --git a/Backend/internal/logic/trace/trace.go b/Backend/internal/logic/trace/trace.go new file mode 100644 index 0000000..296eb7e --- /dev/null +++ b/Backend/internal/logic/trace/trace.go @@ -0,0 +1,189 @@ +package trace + +import ( + "context" + "fmt" + v1 "leke/api/user/v1" + "leke/internal/dao" + "leke/internal/model/entity" + "leke/internal/service" + + "github.com/gogf/gf/v2/database/gdb" + "github.com/gogf/gf/v2/os/gtime" +) + +type sTrace struct{} + +func NewTrace() *sTrace { + return &sTrace{} +} + +func init() { + service.RegisterTrace(NewTrace()) +} + +// TraceList 获取轨迹列表 +func (s *sTrace) TraceList(ctx context.Context, req *v1.TraceListReq) (res *v1.TraceListRes, err error) { + // 创建数据库查询模型 + m := dao.RoleCards.Ctx(ctx) + + // 根据角色ID查询 + if req.RoleId != 0 { + m = m.Where(dao.RoleCards.Columns().Id, req.RoleId) + } + + // 查询总数 + total, err := m.Count() + if err != nil { + return nil, err + } + + // 分页处理 + m = m.Page(req.Page, req.PageSize) + + // 查询列表数据 (Scan 到实体) + var roleCards []*entity.RoleCards + err = m.Scan(&roleCards) + if err != nil { + return nil, err + } + + // 转换为视图参数 + traceList := make([]*v1.TraceViewParams, 0, len(roleCards)) + for _, card := range roleCards { + traceList = append(traceList, &v1.TraceViewParams{ + UserId: card.UserId, + RoleId: card.Id, + DepartmentId: card.DepartmentId, + RedTrace: int(card.RedTrack), + YellowTrace: int(card.YellowTrack), + BlueTrace: int(card.BlueTrack), + }) + } + + res = &v1.TraceListRes{ + List: traceList, + } + + // 设置分页信息 + req.PageResult.Total = int(total) + req.PageResult.Page = req.Page + req.PageResult.PageSize = req.PageSize + + return +} + +// TraceView 查看轨迹详情 +func (s *sTrace) TraceView(ctx context.Context, req *v1.TraceViewReq) (res *v1.TraceViewRes, err error) { + // 创建数据库查询模型 + m := dao.RoleCards.Ctx(ctx) + + // 根据角色ID查询 + var card entity.RoleCards + err = m.Where(dao.RoleCards.Columns().Id, req.RoleId).Scan(&card) + if err != nil { + return nil, err + } + + res = &v1.TraceViewRes{ + TraceViewParams: v1.TraceViewParams{ + UserId: card.UserId, + RoleId: card.Id, + DepartmentId: card.DepartmentId, + RedTrace: int(card.RedTrack), + YellowTrace: int(card.YellowTrack), + BlueTrace: int(card.BlueTrack), + }, + } + + return +} + +// TraceUpdate 更新轨迹信息 (增加) +func (s *sTrace) TraceUpdate(ctx context.Context, req *v1.TraceUpdateReq) (res *v1.TraceUpdateRes, err error) { + // 创建数据库查询模型 + m := dao.RoleCards.Ctx(ctx) + + // 准备更新数据 + data := make(map[string]interface{}) + + // 只有当数值不为0时才进行更新操作 + if req.RedTrace != 0 { + data[dao.RoleCards.Columns().RedTrack] = gdb.Raw(fmt.Sprintf("%s + %d", dao.RoleCards.Columns().RedTrack, req.RedTrace)) + } + + if req.YellowTrace != 0 { + data[dao.RoleCards.Columns().YellowTrack] = gdb.Raw(fmt.Sprintf("%s + %d", dao.RoleCards.Columns().YellowTrack, req.YellowTrace)) + } + + if req.BlueTrace != 0 { + data[dao.RoleCards.Columns().BlueTrack] = gdb.Raw(fmt.Sprintf("%s + %d", dao.RoleCards.Columns().BlueTrack, req.BlueTrace)) + } + + // 如果没有需要更新的字段,直接返回 + if len(data) == 0 { + return &v1.TraceUpdateRes{ + RoleId: req.RoleId, + RedTrace: req.RedTrace, + YellowTrace: req.YellowTrace, + BlueTrace: req.BlueTrace, + }, nil + } + + // 添加更新时间 + data[dao.RoleCards.Columns().UpdatedAt] = gtime.Now() + + // 执行更新 + _, err = m.Data(data).Where(dao.RoleCards.Columns().Id, req.RoleId).Update() + if err != nil { + return nil, err + } + + res = &v1.TraceUpdateRes{ + RoleId: req.RoleId, + RedTrace: req.RedTrace, + YellowTrace: req.YellowTrace, + BlueTrace: req.BlueTrace, + } + + return +} + +// TraceReduce 减少轨迹数值 +func (s *sTrace) TraceReduce(ctx context.Context, req *v1.TraceReduceReq) (res *v1.TraceReduceRes, err error) { + // 创建数据库查询模型 + m := dao.RoleCards.Ctx(ctx) + + // 准备更新数据 + data := make(map[string]interface{}) + + // 只有当数值不为0时才进行减少操作 + if req.RedTrace != 0 { + data[dao.RoleCards.Columns().RedTrack] = gdb.Raw(fmt.Sprintf("GREATEST(0, %s - %d)", dao.RoleCards.Columns().RedTrack, req.RedTrace)) + } + + if req.YellowTrace != 0 { + data[dao.RoleCards.Columns().YellowTrack] = gdb.Raw(fmt.Sprintf("GREATEST(0, %s - %d)", dao.RoleCards.Columns().YellowTrack, req.YellowTrace)) + } + + if req.BlueTrace != 0 { + data[dao.RoleCards.Columns().BlueTrack] = gdb.Raw(fmt.Sprintf("GREATEST(0, %s - %d)", dao.RoleCards.Columns().BlueTrack, req.BlueTrace)) + } + + // 如果没有需要更新的字段,直接返回 + if len(data) == 0 { + return &v1.TraceReduceRes{}, nil + } + + // 添加更新时间 + data[dao.RoleCards.Columns().UpdatedAt] = gtime.Now() + + // 执行更新 + _, err = m.Data(data).Where(dao.RoleCards.Columns().Id, req.RoleId).Update() + if err != nil { + return nil, err + } + + res = &v1.TraceReduceRes{} + return +} diff --git a/Backend/internal/logic/user/user.go b/Backend/internal/logic/user/user.go new file mode 100644 index 0000000..2ec751b --- /dev/null +++ b/Backend/internal/logic/user/user.go @@ -0,0 +1,347 @@ +package user + +import ( + "context" + v1 "leke/api/user/v1" + "leke/internal/dao" + "leke/internal/model" + "leke/internal/model/entity" + "leke/internal/service" + + "github.com/gogf/gf/v2/errors/gcode" + "github.com/gogf/gf/v2/errors/gerror" +) + +type sUser struct{} + +func New() *sUser { + return &sUser{} +} + +func init() { + service.RegisterUser(New()) +} + +func (s *sUser) UserList(ctx context.Context, req *v1.UserListReq) (res *v1.UserListRes, err error) { + // 创建数据库查询模型 + m := dao.Users.Ctx(ctx) + + // 按照账号搜索 + if req.Account != "" { + m = m.WhereLike(dao.Users.Columns().Account, "%"+req.Account+"%") + } + + // 按照昵称搜索 + if req.Nickname != "" { + m = m.WhereLike(dao.Users.Columns().Nickname, "%"+req.Nickname+"%") + } + + // 查询总数 + total, err := m.Count() + if err != nil { + return nil, err + } + + // 分页处理 + m = m.Page(req.Page, req.PageSize) + + // 查询列表数据 + var users []*model.User + err = m.Scan(&users) + if err != nil { + return nil, err + } + + // 转换为视图参数 + userViewList := make([]*model.UserViewParams, 0, len(users)) + for _, user := range users { + userViewList = append(userViewList, &model.UserViewParams{ + Id: user.Id, + Account: user.Account, + Nickname: user.Nickname, + Gender: user.Gender, + BirthDate: user.BirthDate, + UserType: user.UserType, + VipStartAt: user.VipStartAt, + VipEndAt: user.VipEndAt, + CreatedAt: user.CreatedAt, + }) + } + + res = &v1.UserListRes{ + Users: userViewList, + } + + // 设置分页信息 + req.PageResult.Total = int(total) + req.PageResult.Page = req.Page + req.PageResult.PageSize = req.PageSize + + return +} + +func (s *sUser) UserView(ctx context.Context, req *v1.UserViewReq) (res *v1.UserViewRes, err error) { + // 创建数据库查询模型 + m := dao.Users.Ctx(ctx) + + // 根据账号查询 + if req.Account != "" { + m = m.Where(dao.Users.Columns().Account, req.Account) + } + + res = &v1.UserViewRes{} + err = m.Scan(&res.UserViewParams) + if err != nil { + return nil, err + } + + return +} + +func (s *sUser) UserUpdate(ctx context.Context, req *v1.UserUpdateReq) (res *v1.UserUpdateRes, err error) { + // 创建数据库查询模型 + m := dao.Users.Ctx(ctx) + + // 根据账号更新用户信息 + _, err = m.Data(req).Where(dao.Users.Columns().Account, req.Account).Update() + if err != nil { + return nil, err + } + + res = &v1.UserUpdateRes{} + // 获取更新后的用户信息 + err = m.Where(dao.Users.Columns().Account, req.Account).Scan(&res) + if err != nil { + return nil, err + } + + return +} + +func (s *sUser) UserDelete(ctx context.Context, req *v1.UserDeleteReq) (res *v1.UserDeleteRes, err error) { + // 根据账号删除用户 + _, err = dao.Users.Ctx(ctx).Where(dao.Users.Columns().Account, req.Account).Delete() + if err != nil { + return nil, err + } + + res = &v1.UserDeleteRes{} + return +} + +// RoleCreate 创建角色 +func (s *sUser) RoleCreate(ctx context.Context, req *v1.RoleCreateReq) (res *v1.RoleCreateRes, err error) { + // 插入角色数据 + data := &entity.RoleCards{ + UserId: req.UserId, + DepartmentId: req.DepartmentId, + AgentName: req.AgentName, + CodeName: req.CodeName, + Gender: req.Gender, + ArcAbnormal: req.ArcAbnormal, + ArcReality: req.ArcReality, + ArcPosition: req.ArcPosition, + } + + id, err := dao.RoleCards.Ctx(ctx).Data(data).InsertAndGetId() + if err != nil { + return nil, err + } + + res = &v1.RoleCreateRes{ + Id: uint64(id), + } + return +} + +// RoleUpdate 更新角色 +func (s *sUser) RoleUpdate(ctx context.Context, req *v1.RoleUpdateReq) (res *v1.RoleUpdateRes, err error) { + // 更新角色数据 + data := &entity.RoleCards{ + DepartmentId: req.DepartmentId, + AgentName: req.AgentName, + CodeName: req.CodeName, + Gender: req.Gender, + ArcAbnormal: req.ArcAbnormal, + ArcReality: req.ArcReality, + ArcPosition: req.ArcPosition, + Commendation: req.Commendation, + Reprimand: req.Reprimand, + BlueTrack: req.BlueTrack, + YellowTrack: req.YellowTrack, + RedTrack: req.RedTrack, + } + + _, err = dao.RoleCards.Ctx(ctx).Data(data).Where(dao.RoleCards.Columns().Id, req.Id).Update() + if err != nil { + return nil, err + } + + res = &v1.RoleUpdateRes{ + Id: req.Id, + } + return +} + +// RoleView 查看角色详情 +func (s *sUser) RoleView(ctx context.Context, req *v1.RoleViewReq) (res *v1.RoleViewRes, err error) { + // 查询角色详情 + var role entity.RoleCards + err = dao.RoleCards.Ctx(ctx).Where(dao.RoleCards.Columns().Id, req.Id).Scan(&role) + if err != nil { + return nil, err + } + + res = &v1.RoleViewRes{ + RoleViewParams: v1.RoleViewParams{ + Id: role.Id, + UserId: role.UserId, + DepartmentId: role.DepartmentId, + Commendation: role.Commendation, + Reprimand: role.Reprimand, + BlueTrack: role.BlueTrack, + YellowTrack: role.YellowTrack, + RedTrack: role.RedTrack, + ArcAbnormal: role.ArcAbnormal, + ArcReality: role.ArcReality, + ArcPosition: role.ArcPosition, + AgentName: role.AgentName, + CodeName: role.CodeName, + Gender: role.Gender, + QaMeticulous: role.QaMeticulous, + QaDeception: role.QaDeception, + QaVigor: role.QaVigor, + QaEmpathy: role.QaEmpathy, + QaInitiative: role.QaInitiative, + QaResilience: role.QaResilience, + QaPresence: role.QaPresence, + QaProfessional: role.QaProfessional, + QaDiscretion: role.QaDiscretion, + }, + } + return +} + +// RoleList 获取角色列表 +func (s *sUser) RoleList(ctx context.Context, req *v1.RoleListReq) (res *v1.RoleListRes, err error) { + // 创建数据库查询模型 + m := dao.RoleCards.Ctx(ctx) + + // 根据用户ID查询 + if req.UserId != 0 { + m = m.Where(dao.RoleCards.Columns().UserId, req.UserId) + } + + // 根据部门ID查询 + if req.DepartmentId != 0 { + m = m.Where(dao.RoleCards.Columns().DepartmentId, req.DepartmentId) + } + + // 查询总数 + total, err := m.Count() + if err != nil { + return nil, err + } + + // 分页处理 + m = m.Page(req.Page, req.PageSize) + + // 查询列表数据 + var roles []*entity.RoleCards + err = m.Scan(&roles) + if err != nil { + return nil, err + } + + // 转换为视图参数 + roleViewList := make([]*v1.RoleViewParams, 0, len(roles)) + for _, role := range roles { + roleViewList = append(roleViewList, &v1.RoleViewParams{ + Id: role.Id, + UserId: role.UserId, + DepartmentId: role.DepartmentId, + Commendation: role.Commendation, + Reprimand: role.Reprimand, + BlueTrack: role.BlueTrack, + YellowTrack: role.YellowTrack, + RedTrack: role.RedTrack, + ArcAbnormal: role.ArcAbnormal, + ArcReality: role.ArcReality, + ArcPosition: role.ArcPosition, + AgentName: role.AgentName, + CodeName: role.CodeName, + Gender: role.Gender, + QaMeticulous: role.QaMeticulous, + QaDeception: role.QaDeception, + QaVigor: role.QaVigor, + QaEmpathy: role.QaEmpathy, + QaInitiative: role.QaInitiative, + QaResilience: role.QaResilience, + QaPresence: role.QaPresence, + QaProfessional: role.QaProfessional, + QaDiscretion: role.QaDiscretion, + }) + } + + res = &v1.RoleListRes{ + List: roleViewList, + PageResult: req.PageResult, // 设置分页信息 + } + + // 设置分页信息 + req.PageResult.Total = int(total) + req.PageResult.Page = req.Page + req.PageResult.PageSize = req.PageSize + + return +} + +// RoleDelete 删除角色 +func (s *sUser) RoleDelete(ctx context.Context, req *v1.RoleDeleteReq) (res *v1.RoleDeleteRes, err error) { + // 根据ID删除角色 + _, err = dao.RoleCards.Ctx(ctx).Where(dao.RoleCards.Columns().Id, req.Id).Delete() + if err != nil { + return nil, err + } + + res = &v1.RoleDeleteRes{ + Id: req.Id, + } + return +} + +// RolePermissionCheck 权限查询 +func (s *sUser) RolePermissionCheck(ctx context.Context, req *v1.RolePermissionCheckReq) (res *v1.RolePermissionCheckRes, err error) { + // 查询角色信息 + var role entity.RoleCards + err = dao.RoleCards.Ctx(ctx).Where(dao.RoleCards.Columns().Id, req.RoleId).Scan(&role) + if err != nil { + return nil, err + } + + // 根据轨道类型获取对应的轨道值 + var trackValue uint + switch req.TrackType { + case "blue": + trackValue = role.BlueTrack + case "yellow": + trackValue = role.YellowTrack + case "red": + trackValue = role.RedTrack + default: + return nil, gerror.NewCode(gcode.CodeInvalidParameter, "无效的轨道类型") + } + + // 判断权限:如果角色的轨道值 >= 文件需要的值,则权限验证通过 + if trackValue >= req.FileValue { + // 权限验证通过 + res = &v1.RolePermissionCheckRes{ + Code: 333, + Mes: "权限验证通过", + } + return + } + + // 权限不足,返回错误 + return nil, gerror.New("权限不足") +} diff --git a/Backend/internal/middleware/jwt.go b/Backend/internal/middleware/jwt.go new file mode 100644 index 0000000..d197b6a --- /dev/null +++ b/Backend/internal/middleware/jwt.go @@ -0,0 +1,57 @@ +package middleware + +import ( + "github.com/gogf/gf/v2/errors/gcode" + "github.com/gogf/gf/v2/errors/gerror" + "github.com/gogf/gf/v2/net/ghttp" + "github.com/gogf/gf/v2/os/gctx" + "github.com/golang-jwt/jwt/v5" +) + +// JWTClaims represents the custom claims for the JWT token +type JWTClaims struct { + Username string `json:"username"` + jwt.RegisteredClaims +} + +const ( + // CtxUsername is the context key for storing the username + CtxUsername gctx.StrKey = "username" + // JwtSecretKey is the secret key for JWT signing and validation + // Note: In production, this should be replaced with a secure key + JwtSecretKey = "leke" +) + +// JWTAuth is a middleware that validates JWT tokens in the request header +// It checks for the presence and validity of the token, and sets the username +// in the context for downstream handlers +func JWTAuth(r *ghttp.Request) { + // Get token from Authorization header + tokenString := r.Header.Get("Authorization") + if tokenString == "" { + r.SetError(gerror.NewCode(gcode.CodeNotAuthorized, "No token provided")) + r.Exit() + return + } + + // Remove 'Bearer ' prefix if present + if len(tokenString) > 7 && tokenString[:7] == "Bearer " { + tokenString = tokenString[7:] + } + + // Parse and validate the token + claims := &JWTClaims{} + token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) { + return []byte(JwtSecretKey), nil + }) + + if err != nil || !token.Valid { + r.SetError(gerror.NewCode(gcode.CodeNotAuthorized, "Invalid token")) + r.Exit() + return + } + + // Store username in context for later use + r.SetCtxVar(CtxUsername, claims.Username) + r.Middleware.Next() +} \ No newline at end of file diff --git a/Backend/internal/model/containmentRepo.go b/Backend/internal/model/containmentRepo.go new file mode 100644 index 0000000..8731ef8 --- /dev/null +++ b/Backend/internal/model/containmentRepo.go @@ -0,0 +1,10 @@ +package model + +type ContainmentRepo struct { + Abnormal int `json:"abnormal" orm:"abnormal" description:"number of contained anomalies (收容异常的数量)"` + AgentName string `json:"agentName" orm:"agent_name" description:"agent (特工)"` + AnomalyName string `json:"anomalyName" orm:"anomaly_name" description:"name of the anomaly (异常体的名字)"` + Id uint64 `json:"id" orm:"id" description:"primary key(大于0为修改,其他为新增)"` + RepoName string `json:"repoName" orm:"repo_name" description:"containment repository name or code (收容库)"` + TerminalId int `json:"terminalId" orm:"terminal_id" description:"terminal (散逸端)"` +} diff --git a/Backend/internal/model/department.go b/Backend/internal/model/department.go new file mode 100644 index 0000000..4d393db --- /dev/null +++ b/Backend/internal/model/department.go @@ -0,0 +1,18 @@ +package model + +import ( + "github.com/gogf/gf/v2/os/gtime" +) + +// Department 三角机构分部表 +type Department struct { + Id uint64 `json:"id" orm:"id" description:"自增主键"` + UserId uint64 `json:"userId" orm:"user_id" description:"所属用户ID(对应 users.id)"` + BranchName string `json:"branchName" orm:"branch_name" description:"分部名称"` + TerminalCount int `json:"terminalCount" orm:"terminal_count" description:"分部散逸端的数量"` + Weather string `json:"weather" orm:"weather" description:"分部当前天气/气候描述"` + ManagerName string `json:"managerName" orm:"manager_name" description:"分部经理名称"` + Location string `json:"location" description:"分部地址"` + CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:"创建时间"` + UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:"更新时间"` +} diff --git a/Backend/internal/model/do/.gitkeep b/Backend/internal/model/do/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/Backend/internal/model/do/coaches.go b/Backend/internal/model/do/coaches.go new file mode 100644 index 0000000..3b975d0 --- /dev/null +++ b/Backend/internal/model/do/coaches.go @@ -0,0 +1,22 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package do + +import ( + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gtime" +) + +// Coaches is the golang structure of table coaches for DAO operations like Where/Data. +type Coaches struct { + g.Meta `orm:"table:coaches, do:true"` + Id any // 教练ID + UserId any // 对应的用户ID(如果教练也要登录的话) + Name any // 教练姓名 + Phone any // 教练电话 + Specialty any // 擅长方向,比如瑜伽、力量、减脂 + CreatedAt *gtime.Time // 创建时间 + UpdatedAt *gtime.Time // 更新时间 +} diff --git a/Backend/internal/model/do/comments.go b/Backend/internal/model/do/comments.go new file mode 100644 index 0000000..1bb20c4 --- /dev/null +++ b/Backend/internal/model/do/comments.go @@ -0,0 +1,28 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package do + +import ( + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gtime" +) + +// Comments is the golang structure of table comments for DAO operations like Where/Data. +type Comments struct { + g.Meta `orm:"table:comments, do:true"` + Id any // 评论ID + UserId any // 评论用户ID + TargetType any // 被评论对象类型(如 post/image/video 等) + TargetId any // 被评论对象ID + ParentId any // 父评论ID(回复某条评论时填写) + RootId any // 根评论ID(同一楼的顶层评论ID,便于树查询) + Content any // 评论内容 + Status any // 状态:1正常 0屏蔽 2删除 + LikeCount any // 点赞数 + ReplyCount any // 回复数 + CreatedAt *gtime.Time // 创建时间 + UpdatedAt *gtime.Time // 更新时间 + DeletedAt *gtime.Time // 软删除时间 +} diff --git a/Backend/internal/model/do/containment_repo.go b/Backend/internal/model/do/containment_repo.go new file mode 100644 index 0000000..5fa8db1 --- /dev/null +++ b/Backend/internal/model/do/containment_repo.go @@ -0,0 +1,19 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package do + +import ( + "github.com/gogf/gf/v2/frame/g" +) + +// ContainmentRepo is the golang structure of table containment_repo for DAO operations like Where/Data. +type ContainmentRepo struct { + g.Meta `orm:"table:containment_repo, do:true"` + Id any // auto-increment primary key + AnomalyName any // name of the anomaly (异常体的名字) + AgentName any // agent (特工) + RepoName any // containment repository name or code (收容库) + Department any // 部门 +} diff --git a/Backend/internal/model/do/department.go b/Backend/internal/model/do/department.go new file mode 100644 index 0000000..4c6c837 --- /dev/null +++ b/Backend/internal/model/do/department.go @@ -0,0 +1,24 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package do + +import ( + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gtime" +) + +// Department is the golang structure of table department for DAO operations like Where/Data. +type Department struct { + g.Meta `orm:"table:department, do:true"` + Id any // 自增主键 + UserId any // 所属用户ID(对应 users.id) + BranchName any // 分部名称 + TerminalCount any // 分部散逸端的数量 + Weather any // 分部当前天气/气候描述 + ManagerName any // 分部经理名称 + CreatedAt *gtime.Time // 创建时间 + UpdatedAt *gtime.Time // 更新时间 + Location any // 地址 +} diff --git a/Backend/internal/model/do/fans.go b/Backend/internal/model/do/fans.go new file mode 100644 index 0000000..0efc1d1 --- /dev/null +++ b/Backend/internal/model/do/fans.go @@ -0,0 +1,22 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package do + +import ( + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gtime" +) + +// Fans is the golang structure of table fans for DAO operations like Where/Data. +type Fans struct { + g.Meta `orm:"table:fans, do:true"` + Id any // 自增主键 + UserId any // 用户ID(被关注者,本人) + FanId any // 粉丝用户ID + Status any // 状态:1=粉丝 0=取关/无效 + Remark any // 备注名(user_id 对 fan_id 的备注/分组) + CreatedAt *gtime.Time // 创建时间 + UpdatedAt *gtime.Time // 更新时间 +} diff --git a/Backend/internal/model/do/forum_comments.go b/Backend/internal/model/do/forum_comments.go new file mode 100644 index 0000000..7cb5240 --- /dev/null +++ b/Backend/internal/model/do/forum_comments.go @@ -0,0 +1,26 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package do + +import ( + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gtime" +) + +// ForumComments is the golang structure of table forum_comments for DAO operations like Where/Data. +type ForumComments struct { + g.Meta `orm:"table:forum_comments, do:true"` + Id any // 评论ID(主键) + UserId any // 评论发布者ID(关联users.id,无外键) + PostId any // 所属帖子ID(关联forum_posts.id,无外键) + ParentId any // 父评论ID(NULL=根评论,非NULL=回复某条评论) + Content any // 评论内容(支持emoji) + Status any // 评论状态:normal=正常 deleted=软删除 audit=审核中 reject=审核驳回 + LikeCount any // 点赞数 + ReplyCount any // 回复数(冗余字段) + CreatedAt *gtime.Time // 评论创建时间 + UpdatedAt *gtime.Time // 评论更新时间 + DeletedAt *gtime.Time // 软删除时间 +} diff --git a/Backend/internal/model/do/forum_posts.go b/Backend/internal/model/do/forum_posts.go new file mode 100644 index 0000000..15e7f73 --- /dev/null +++ b/Backend/internal/model/do/forum_posts.go @@ -0,0 +1,27 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package do + +import ( + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gtime" +) + +// ForumPosts is the golang structure of table forum_posts for DAO operations like Where/Data. +type ForumPosts struct { + g.Meta `orm:"table:forum_posts, do:true"` + Id any // 帖子ID(主键) + UserId any // 发帖用户ID(关联users.id,无外键) + Title any // 帖子标题 + Content any // 帖子正文(支持富文本/emoji) + CoverImage any // 帖子封面图URL + Status any // 帖子状态:normal=正常 deleted=软删除 audit=审核中 reject=审核驳回 + ViewCount any // 浏览量(冗余字段) + LikeCount any // 点赞数(冗余字段) + CommentCount any // 评论数(冗余字段) + CreatedAt *gtime.Time // 发帖时间 + UpdatedAt *gtime.Time // 更新时间 + DeletedAt *gtime.Time // 软删除时间 +} diff --git a/Backend/internal/model/do/group_class_enrollments.go b/Backend/internal/model/do/group_class_enrollments.go new file mode 100644 index 0000000..48f7fcf --- /dev/null +++ b/Backend/internal/model/do/group_class_enrollments.go @@ -0,0 +1,21 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package do + +import ( + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gtime" +) + +// GroupClassEnrollments is the golang structure of table group_class_enrollments for DAO operations like Where/Data. +type GroupClassEnrollments struct { + g.Meta `orm:"table:group_class_enrollments, do:true"` + Id any // 报名ID + ClassId any // 团课ID + UserId any // 用户ID + Status any // 状态:booked已报名,checked_in已签到,cancelled已取消 + EnrolledAt *gtime.Time // 报名时间 + CheckedInAt *gtime.Time // 签到时间 +} diff --git a/Backend/internal/model/do/group_classes.go b/Backend/internal/model/do/group_classes.go new file mode 100644 index 0000000..3b941bf --- /dev/null +++ b/Backend/internal/model/do/group_classes.go @@ -0,0 +1,26 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package do + +import ( + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gtime" +) + +// GroupClasses is the golang structure of table group_classes for DAO operations like Where/Data. +type GroupClasses struct { + g.Meta `orm:"table:group_classes, do:true"` + Id any // 团课ID + Title any // 课程名称,如:燃脂搏击、瑜伽 + Description any // 课程介绍 + CoachId any // 授课教练ID + Location any // 上课地点/门店/教室 + StartTime *gtime.Time // 开始时间 + EndTime *gtime.Time // 结束时间 + MaxCapacity any // 最大人数 + Price any // 价格(0表示免费或已包含在会员卡内) + CreatedAt *gtime.Time // 创建时间 + UpdatedAt *gtime.Time // 更新时间 +} diff --git a/Backend/internal/model/do/role_cards.go b/Backend/internal/model/do/role_cards.go new file mode 100644 index 0000000..46fc1ef --- /dev/null +++ b/Backend/internal/model/do/role_cards.go @@ -0,0 +1,40 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package do + +import ( + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gtime" +) + +// RoleCards is the golang structure of table role_cards for DAO operations like Where/Data. +type RoleCards struct { + g.Meta `orm:"table:role_cards, do:true"` + Id any // 角色卡ID + UserId any // 所属用户ID + DepartmentId any // 所属部门ID + Commendation any // 嘉奖次数 + Reprimand any // 申戒次数 + BlueTrack any // 蓝轨(0-40) + YellowTrack any // 黄轨(0-40) + RedTrack any // 红轨(0-40) + ArcAbnormal any // ARC:异常 + ArcReality any // ARC:现实 + ArcPosition any // ARC:职位 + AgentName any // 特工名字 + CodeName any // 代号 + Gender any // 性别 + QaMeticulous any // Meticulousness (0-100, QA) + QaDeception any // Deception (0-100, QA) + QaVigor any // Vigor / Drive (0-100, QA) + QaEmpathy any // Empathy (0-100, QA) + QaInitiative any // Initiative (0-100, QA) + QaResilience any // Resilience / Persistence (0-100, QA) + QaPresence any // Presence / Charisma (0-100, QA) + QaProfessional any // Professionalism (0-100, QA) + QaDiscretion any // Discretion / Low profile (0-100, QA) + CreatedAt *gtime.Time // 创建时间 + UpdatedAt *gtime.Time // 更新时间 +} diff --git a/Backend/internal/model/do/subscribe.go b/Backend/internal/model/do/subscribe.go new file mode 100644 index 0000000..c980bee --- /dev/null +++ b/Backend/internal/model/do/subscribe.go @@ -0,0 +1,22 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package do + +import ( + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gtime" +) + +// Subscribe is the golang structure of table subscribe for DAO operations like Where/Data. +type Subscribe struct { + g.Meta `orm:"table:subscribe, do:true"` + Id any // 自增主键 + UserId any // 用户ID(关注者,本人) + FollowId any // 被关注的用户ID + Status any // 状态:1=关注中 0=取消关注 + Remark any // 备注名(user_id 对 follow_id 的备注) + CreatedAt *gtime.Time // 创建时间 + UpdatedAt *gtime.Time // 更新时间 +} diff --git a/Backend/internal/model/do/trpg_room.go b/Backend/internal/model/do/trpg_room.go new file mode 100644 index 0000000..4397ddb --- /dev/null +++ b/Backend/internal/model/do/trpg_room.go @@ -0,0 +1,34 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package do + +import ( + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gtime" +) + +// TrpgRoom is the golang structure of table trpg_room for DAO operations like Where/Data. +type TrpgRoom struct { + g.Meta `orm:"table:trpg_room, do:true"` + Id any // 自增主键 + RoomId any // 房间全局唯一ID(建议UUID) + RoomCode any // 房间号(玩家看到/输入的房间号) + RoomName any // 房间名称 + HostId any // 主持人用户ID(GM/KP/经理,对应用户表id) + HostNickname any // 主持人昵称(冗余字段,可选) + MaxPlayers any // 最大玩家人数(不含主持人,可按需要约定) + CurrentPlayers any // 当前玩家人数(不含主持人) + HasPassword any // 是否有密码:0无 1有 + RoomPassword any // 房间密码(建议存加密/哈希后的密码) + IsPrivate any // 是否私密房:0公开 1私密 + Status any // 房间状态:0未开始 1进行中 2已结束 3已关闭 + SystemName any // 规则系统:如 COC、DND5E 等 + ScenarioName any // 模组/剧本名称 + Description any // 房间简介/招募说明 + CreatedAt *gtime.Time // 房间创建时间 + StartedAt *gtime.Time // 开团时间 + EndedAt *gtime.Time // 结束时间 + UpdatedAt *gtime.Time // 信息最近更新时间 +} diff --git a/Backend/internal/model/do/user_department.go b/Backend/internal/model/do/user_department.go new file mode 100644 index 0000000..e2570c7 --- /dev/null +++ b/Backend/internal/model/do/user_department.go @@ -0,0 +1,20 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package do + +import ( + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gtime" +) + +// UserDepartment is the golang structure of table user_department for DAO operations like Where/Data. +type UserDepartment struct { + g.Meta `orm:"table:user_department, do:true"` + Id any // + UserId any // 用户ID(对应 users.id) + DeptId any // 部门ID(对应 department.id) + CreatedAt *gtime.Time // 创建时间 + UpdatedAt *gtime.Time // 更新时间 +} diff --git a/Backend/internal/model/do/users.go b/Backend/internal/model/do/users.go new file mode 100644 index 0000000..a9637f9 --- /dev/null +++ b/Backend/internal/model/do/users.go @@ -0,0 +1,35 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package do + +import ( + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gtime" +) + +// Users is the golang structure of table users for DAO operations like Where/Data. +type Users struct { + g.Meta `orm:"table:users, do:true"` + Id any // 用户ID + Account any // 账号 + Password any // 密码哈希 + Nickname any // 昵称 + Gender any // 性别:0未知 1男 2女 + BirthDate *gtime.Time // 生日 + UserType any // 用户类型:normal普通用户,vip为VIP用户 + VipStartAt *gtime.Time // VIP开始时间 + VipEndAt *gtime.Time // VIP结束时间 + CreatedAt *gtime.Time // 创建时间 + UpdatedAt *gtime.Time // 更新时间 + RealityRole any // 现实身份/角色 + AbnormalRole any // 异常身份/角色 + JobTitle any // 职位 + Commendation any // + Admonition any // + Email any // + RedTrace any // 红轨 + YellowTrace any // 黄轨 + BlueTrace any // 蓝轨 +} diff --git a/Backend/internal/model/do/workout_logs.go b/Backend/internal/model/do/workout_logs.go new file mode 100644 index 0000000..f1ee43c --- /dev/null +++ b/Backend/internal/model/do/workout_logs.go @@ -0,0 +1,24 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package do + +import ( + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gtime" +) + +// WorkoutLogs is the golang structure of table workout_logs for DAO operations like Where/Data. +type WorkoutLogs struct { + g.Meta `orm:"table:workout_logs, do:true"` + Id any // 健身记录ID + UserId any // 关联的用户ID + WorkoutDate *gtime.Time // 健身日期 + StartTime *gtime.Time // 开始时间 + EndTime *gtime.Time // 结束时间 + DurationMinutes any // 时长(分钟) + Calories any // 估算消耗的卡路里 + Description any // 本次训练的备注,比如训练内容、部位等 + CreatedAt *gtime.Time // 记录创建时间 +} diff --git a/Backend/internal/model/entity/.gitkeep b/Backend/internal/model/entity/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/Backend/internal/model/entity/coaches.go b/Backend/internal/model/entity/coaches.go new file mode 100644 index 0000000..996f185 --- /dev/null +++ b/Backend/internal/model/entity/coaches.go @@ -0,0 +1,20 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package entity + +import ( + "github.com/gogf/gf/v2/os/gtime" +) + +// Coaches is the golang structure for table coaches. +type Coaches struct { + Id uint64 `json:"id" orm:"id" description:"教练ID"` // 教练ID + UserId uint64 `json:"userId" orm:"user_id" description:"对应的用户ID(如果教练也要登录的话)"` // 对应的用户ID(如果教练也要登录的话) + Name string `json:"name" orm:"name" description:"教练姓名"` // 教练姓名 + Phone string `json:"phone" orm:"phone" description:"教练电话"` // 教练电话 + Specialty string `json:"specialty" orm:"specialty" description:"擅长方向,比如瑜伽、力量、减脂"` // 擅长方向,比如瑜伽、力量、减脂 + CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:"创建时间"` // 创建时间 + UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:"更新时间"` // 更新时间 +} diff --git a/Backend/internal/model/entity/comments.go b/Backend/internal/model/entity/comments.go new file mode 100644 index 0000000..257fa9b --- /dev/null +++ b/Backend/internal/model/entity/comments.go @@ -0,0 +1,26 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package entity + +import ( + "github.com/gogf/gf/v2/os/gtime" +) + +// Comments is the golang structure for table comments. +type Comments struct { + Id uint64 `json:"id" orm:"id" description:"评论ID"` // 评论ID + UserId uint64 `json:"userId" orm:"user_id" description:"评论用户ID"` // 评论用户ID + TargetType string `json:"targetType" orm:"target_type" description:"被评论对象类型(如 post/image/video 等)"` // 被评论对象类型(如 post/image/video 等) + TargetId uint64 `json:"targetId" orm:"target_id" description:"被评论对象ID"` // 被评论对象ID + ParentId uint64 `json:"parentId" orm:"parent_id" description:"父评论ID(回复某条评论时填写)"` // 父评论ID(回复某条评论时填写) + RootId uint64 `json:"rootId" orm:"root_id" description:"根评论ID(同一楼的顶层评论ID,便于树查询)"` // 根评论ID(同一楼的顶层评论ID,便于树查询) + Content string `json:"content" orm:"content" description:"评论内容"` // 评论内容 + Status int `json:"status" orm:"status" description:"状态:1正常 0屏蔽 2删除"` // 状态:1正常 0屏蔽 2删除 + LikeCount uint `json:"likeCount" orm:"like_count" description:"点赞数"` // 点赞数 + ReplyCount uint `json:"replyCount" orm:"reply_count" description:"回复数"` // 回复数 + CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:"创建时间"` // 创建时间 + UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:"更新时间"` // 更新时间 + DeletedAt *gtime.Time `json:"deletedAt" orm:"deleted_at" description:"软删除时间"` // 软删除时间 +} diff --git a/Backend/internal/model/entity/containment_repo.go b/Backend/internal/model/entity/containment_repo.go new file mode 100644 index 0000000..b3da5cf --- /dev/null +++ b/Backend/internal/model/entity/containment_repo.go @@ -0,0 +1,14 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package entity + +// ContainmentRepo is the golang structure for table containment_repo. +type ContainmentRepo struct { + Id uint64 `json:"id" orm:"id" description:"auto-increment primary key"` // auto-increment primary key + AnomalyName string `json:"anomalyName" orm:"anomaly_name" description:"name of the anomaly (异常体的名字)"` // name of the anomaly (异常体的名字) + AgentName string `json:"agentName" orm:"agent_name" description:"agent (特工)"` // agent (特工) + RepoName string `json:"repoName" orm:"repo_name" description:"containment repository name or code (收容库)"` // containment repository name or code (收容库) + Department int `json:"department" orm:"department" description:"部门"` // 部门 +} diff --git a/Backend/internal/model/entity/department.go b/Backend/internal/model/entity/department.go new file mode 100644 index 0000000..5237692 --- /dev/null +++ b/Backend/internal/model/entity/department.go @@ -0,0 +1,22 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package entity + +import ( + "github.com/gogf/gf/v2/os/gtime" +) + +// Department is the golang structure for table department. +type Department struct { + Id uint64 `json:"id" orm:"id" description:"自增主键"` // 自增主键 + UserId uint64 `json:"userId" orm:"user_id" description:"所属用户ID(对应 users.id)"` // 所属用户ID(对应 users.id) + BranchName string `json:"branchName" orm:"branch_name" description:"分部名称"` // 分部名称 + TerminalCount int `json:"terminalCount" orm:"terminal_count" description:"分部散逸端的数量"` // 分部散逸端的数量 + Weather string `json:"weather" orm:"weather" description:"分部当前天气/气候描述"` // 分部当前天气/气候描述 + ManagerName string `json:"managerName" orm:"manager_name" description:"分部经理名称"` // 分部经理名称 + CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:"创建时间"` // 创建时间 + UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:"更新时间"` // 更新时间 + Location string `json:"location" orm:"location" description:"地址"` // 地址 +} diff --git a/Backend/internal/model/entity/fans.go b/Backend/internal/model/entity/fans.go new file mode 100644 index 0000000..f684a68 --- /dev/null +++ b/Backend/internal/model/entity/fans.go @@ -0,0 +1,20 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package entity + +import ( + "github.com/gogf/gf/v2/os/gtime" +) + +// Fans is the golang structure for table fans. +type Fans struct { + Id uint64 `json:"id" orm:"id" description:"自增主键"` // 自增主键 + UserId uint64 `json:"userId" orm:"user_id" description:"用户ID(被关注者,本人)"` // 用户ID(被关注者,本人) + FanId uint64 `json:"fanId" orm:"fan_id" description:"粉丝用户ID"` // 粉丝用户ID + Status int `json:"status" orm:"status" description:"状态:1=粉丝 0=取关/无效"` // 状态:1=粉丝 0=取关/无效 + Remark string `json:"remark" orm:"remark" description:"备注名(user_id 对 fan_id 的备注/分组)"` // 备注名(user_id 对 fan_id 的备注/分组) + CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:"创建时间"` // 创建时间 + UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:"更新时间"` // 更新时间 +} diff --git a/Backend/internal/model/entity/forum_comments.go b/Backend/internal/model/entity/forum_comments.go new file mode 100644 index 0000000..9631aad --- /dev/null +++ b/Backend/internal/model/entity/forum_comments.go @@ -0,0 +1,24 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package entity + +import ( + "github.com/gogf/gf/v2/os/gtime" +) + +// ForumComments is the golang structure for table forum_comments. +type ForumComments struct { + Id uint64 `json:"id" orm:"id" description:"评论ID(主键)"` // 评论ID(主键) + UserId uint64 `json:"userId" orm:"user_id" description:"评论发布者ID(关联users.id,无外键)"` // 评论发布者ID(关联users.id,无外键) + PostId uint64 `json:"postId" orm:"post_id" description:"所属帖子ID(关联forum_posts.id,无外键)"` // 所属帖子ID(关联forum_posts.id,无外键) + ParentId uint64 `json:"parentId" orm:"parent_id" description:"父评论ID(NULL=根评论,非NULL=回复某条评论)"` // 父评论ID(NULL=根评论,非NULL=回复某条评论) + Content string `json:"content" orm:"content" description:"评论内容(支持emoji)"` // 评论内容(支持emoji) + Status string `json:"status" orm:"status" description:"评论状态:normal=正常 deleted=软删除 audit=审核中 reject=审核驳回"` // 评论状态:normal=正常 deleted=软删除 audit=审核中 reject=审核驳回 + LikeCount uint `json:"likeCount" orm:"like_count" description:"点赞数"` // 点赞数 + ReplyCount uint `json:"replyCount" orm:"reply_count" description:"回复数(冗余字段)"` // 回复数(冗余字段) + CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:"评论创建时间"` // 评论创建时间 + UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:"评论更新时间"` // 评论更新时间 + DeletedAt *gtime.Time `json:"deletedAt" orm:"deleted_at" description:"软删除时间"` // 软删除时间 +} diff --git a/Backend/internal/model/entity/forum_posts.go b/Backend/internal/model/entity/forum_posts.go new file mode 100644 index 0000000..93baebd --- /dev/null +++ b/Backend/internal/model/entity/forum_posts.go @@ -0,0 +1,25 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package entity + +import ( + "github.com/gogf/gf/v2/os/gtime" +) + +// ForumPosts is the golang structure for table forum_posts. +type ForumPosts struct { + Id uint64 `json:"id" orm:"id" description:"帖子ID(主键)"` // 帖子ID(主键) + UserId uint64 `json:"userId" orm:"user_id" description:"发帖用户ID(关联users.id,无外键)"` // 发帖用户ID(关联users.id,无外键) + Title string `json:"title" orm:"title" description:"帖子标题"` // 帖子标题 + Content string `json:"content" orm:"content" description:"帖子正文(支持富文本/emoji)"` // 帖子正文(支持富文本/emoji) + CoverImage string `json:"coverImage" orm:"cover_image" description:"帖子封面图URL"` // 帖子封面图URL + Status string `json:"status" orm:"status" description:"帖子状态:normal=正常 deleted=软删除 audit=审核中 reject=审核驳回"` // 帖子状态:normal=正常 deleted=软删除 audit=审核中 reject=审核驳回 + ViewCount uint `json:"viewCount" orm:"view_count" description:"浏览量(冗余字段)"` // 浏览量(冗余字段) + LikeCount uint `json:"likeCount" orm:"like_count" description:"点赞数(冗余字段)"` // 点赞数(冗余字段) + CommentCount uint `json:"commentCount" orm:"comment_count" description:"评论数(冗余字段)"` // 评论数(冗余字段) + CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:"发帖时间"` // 发帖时间 + UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:"更新时间"` // 更新时间 + DeletedAt *gtime.Time `json:"deletedAt" orm:"deleted_at" description:"软删除时间"` // 软删除时间 +} diff --git a/Backend/internal/model/entity/group_class_enrollments.go b/Backend/internal/model/entity/group_class_enrollments.go new file mode 100644 index 0000000..7483a83 --- /dev/null +++ b/Backend/internal/model/entity/group_class_enrollments.go @@ -0,0 +1,19 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package entity + +import ( + "github.com/gogf/gf/v2/os/gtime" +) + +// GroupClassEnrollments is the golang structure for table group_class_enrollments. +type GroupClassEnrollments struct { + Id uint64 `json:"id" orm:"id" description:"报名ID"` // 报名ID + ClassId uint64 `json:"classId" orm:"class_id" description:"团课ID"` // 团课ID + UserId uint64 `json:"userId" orm:"user_id" description:"用户ID"` // 用户ID + Status string `json:"status" orm:"status" description:"状态:booked已报名,checked_in已签到,cancelled已取消"` // 状态:booked已报名,checked_in已签到,cancelled已取消 + EnrolledAt *gtime.Time `json:"enrolledAt" orm:"enrolled_at" description:"报名时间"` // 报名时间 + CheckedInAt *gtime.Time `json:"checkedInAt" orm:"checked_in_at" description:"签到时间"` // 签到时间 +} diff --git a/Backend/internal/model/entity/group_classes.go b/Backend/internal/model/entity/group_classes.go new file mode 100644 index 0000000..f250a6b --- /dev/null +++ b/Backend/internal/model/entity/group_classes.go @@ -0,0 +1,24 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package entity + +import ( + "github.com/gogf/gf/v2/os/gtime" +) + +// GroupClasses is the golang structure for table group_classes. +type GroupClasses struct { + Id uint64 `json:"id" orm:"id" description:"团课ID"` // 团课ID + Title string `json:"title" orm:"title" description:"课程名称,如:燃脂搏击、瑜伽"` // 课程名称,如:燃脂搏击、瑜伽 + Description string `json:"description" orm:"description" description:"课程介绍"` // 课程介绍 + CoachId uint64 `json:"coachId" orm:"coach_id" description:"授课教练ID"` // 授课教练ID + Location string `json:"location" orm:"location" description:"上课地点/门店/教室"` // 上课地点/门店/教室 + StartTime *gtime.Time `json:"startTime" orm:"start_time" description:"开始时间"` // 开始时间 + EndTime *gtime.Time `json:"endTime" orm:"end_time" description:"结束时间"` // 结束时间 + MaxCapacity int `json:"maxCapacity" orm:"max_capacity" description:"最大人数"` // 最大人数 + Price float64 `json:"price" orm:"price" description:"价格(0表示免费或已包含在会员卡内)"` // 价格(0表示免费或已包含在会员卡内) + CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:"创建时间"` // 创建时间 + UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:"更新时间"` // 更新时间 +} diff --git a/Backend/internal/model/entity/role_cards.go b/Backend/internal/model/entity/role_cards.go new file mode 100644 index 0000000..1fb262c --- /dev/null +++ b/Backend/internal/model/entity/role_cards.go @@ -0,0 +1,38 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package entity + +import ( + "github.com/gogf/gf/v2/os/gtime" +) + +// RoleCards is the golang structure for table role_cards. +type RoleCards struct { + Id uint64 `json:"id" orm:"id" description:"角色卡ID"` // 角色卡ID + UserId uint64 `json:"userId" orm:"user_id" description:"所属用户ID"` // 所属用户ID + DepartmentId uint64 `json:"departmentId" orm:"department_id" description:"所属部门ID"` // 所属部门ID + Commendation uint `json:"commendation" orm:"commendation" description:"嘉奖次数"` // 嘉奖次数 + Reprimand uint `json:"reprimand" orm:"reprimand" description:"申戒次数"` // 申戒次数 + BlueTrack uint `json:"blueTrack" orm:"blue_track" description:"蓝轨(0-40)"` // 蓝轨(0-40) + YellowTrack uint `json:"yellowTrack" orm:"yellow_track" description:"黄轨(0-40)"` // 黄轨(0-40) + RedTrack uint `json:"redTrack" orm:"red_track" description:"红轨(0-40)"` // 红轨(0-40) + ArcAbnormal string `json:"arcAbnormal" orm:"arc_abnormal" description:"ARC:异常"` // ARC:异常 + ArcReality string `json:"arcReality" orm:"arc_reality" description:"ARC:现实"` // ARC:现实 + ArcPosition string `json:"arcPosition" orm:"arc_position" description:"ARC:职位"` // ARC:职位 + AgentName string `json:"agentName" orm:"agent_name" description:"特工名字"` // 特工名字 + CodeName string `json:"codeName" orm:"code_name" description:"代号"` // 代号 + Gender string `json:"gender" orm:"gender" description:"性别"` // 性别 + QaMeticulous uint `json:"qaMeticulous" orm:"qa_meticulous" description:"Meticulousness (0-100, QA)"` // Meticulousness (0-100, QA) + QaDeception uint `json:"qaDeception" orm:"qa_deception" description:"Deception (0-100, QA)"` // Deception (0-100, QA) + QaVigor uint `json:"qaVigor" orm:"qa_vigor" description:"Vigor / Drive (0-100, QA)"` // Vigor / Drive (0-100, QA) + QaEmpathy uint `json:"qaEmpathy" orm:"qa_empathy" description:"Empathy (0-100, QA)"` // Empathy (0-100, QA) + QaInitiative uint `json:"qaInitiative" orm:"qa_initiative" description:"Initiative (0-100, QA)"` // Initiative (0-100, QA) + QaResilience uint `json:"qaResilience" orm:"qa_resilience" description:"Resilience / Persistence (0-100, QA)"` // Resilience / Persistence (0-100, QA) + QaPresence uint `json:"qaPresence" orm:"qa_presence" description:"Presence / Charisma (0-100, QA)"` // Presence / Charisma (0-100, QA) + QaProfessional uint `json:"qaProfessional" orm:"qa_professional" description:"Professionalism (0-100, QA)"` // Professionalism (0-100, QA) + QaDiscretion uint `json:"qaDiscretion" orm:"qa_discretion" description:"Discretion / Low profile (0-100, QA)"` // Discretion / Low profile (0-100, QA) + CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:"创建时间"` // 创建时间 + UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:"更新时间"` // 更新时间 +} diff --git a/Backend/internal/model/entity/subscribe.go b/Backend/internal/model/entity/subscribe.go new file mode 100644 index 0000000..61c3fd7 --- /dev/null +++ b/Backend/internal/model/entity/subscribe.go @@ -0,0 +1,20 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package entity + +import ( + "github.com/gogf/gf/v2/os/gtime" +) + +// Subscribe is the golang structure for table subscribe. +type Subscribe struct { + Id uint64 `json:"id" orm:"id" description:"自增主键"` // 自增主键 + UserId uint64 `json:"userId" orm:"user_id" description:"用户ID(关注者,本人)"` // 用户ID(关注者,本人) + FollowId uint64 `json:"followId" orm:"follow_id" description:"被关注的用户ID"` // 被关注的用户ID + Status int `json:"status" orm:"status" description:"状态:1=关注中 0=取消关注"` // 状态:1=关注中 0=取消关注 + Remark string `json:"remark" orm:"remark" description:"备注名(user_id 对 follow_id 的备注)"` // 备注名(user_id 对 follow_id 的备注) + CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:"创建时间"` // 创建时间 + UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:"更新时间"` // 更新时间 +} diff --git a/Backend/internal/model/entity/trpg_room.go b/Backend/internal/model/entity/trpg_room.go new file mode 100644 index 0000000..06848c7 --- /dev/null +++ b/Backend/internal/model/entity/trpg_room.go @@ -0,0 +1,32 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package entity + +import ( + "github.com/gogf/gf/v2/os/gtime" +) + +// TrpgRoom is the golang structure for table trpg_room. +type TrpgRoom struct { + Id uint64 `json:"id" orm:"id" description:"自增主键"` // 自增主键 + RoomId string `json:"roomId" orm:"room_id" description:"房间全局唯一ID(建议UUID)"` // 房间全局唯一ID(建议UUID) + RoomCode string `json:"roomCode" orm:"room_code" description:"房间号(玩家看到/输入的房间号)"` // 房间号(玩家看到/输入的房间号) + RoomName string `json:"roomName" orm:"room_name" description:"房间名称"` // 房间名称 + HostId uint64 `json:"hostId" orm:"host_id" description:"主持人用户ID(GM/KP/经理,对应用户表id)"` // 主持人用户ID(GM/KP/经理,对应用户表id) + HostNickname string `json:"hostNickname" orm:"host_nickname" description:"主持人昵称(冗余字段,可选)"` // 主持人昵称(冗余字段,可选) + MaxPlayers uint `json:"maxPlayers" orm:"max_players" description:"最大玩家人数(不含主持人,可按需要约定)"` // 最大玩家人数(不含主持人,可按需要约定) + CurrentPlayers uint `json:"currentPlayers" orm:"current_players" description:"当前玩家人数(不含主持人)"` // 当前玩家人数(不含主持人) + HasPassword int `json:"hasPassword" orm:"has_password" description:"是否有密码:0无 1有"` // 是否有密码:0无 1有 + RoomPassword string `json:"roomPassword" orm:"room_password" description:"房间密码(建议存加密/哈希后的密码)"` // 房间密码(建议存加密/哈希后的密码) + IsPrivate int `json:"isPrivate" orm:"is_private" description:"是否私密房:0公开 1私密"` // 是否私密房:0公开 1私密 + Status int `json:"status" orm:"status" description:"房间状态:0未开始 1进行中 2已结束 3已关闭"` // 房间状态:0未开始 1进行中 2已结束 3已关闭 + SystemName string `json:"systemName" orm:"system_name" description:"规则系统:如 COC、DND5E 等"` // 规则系统:如 COC、DND5E 等 + ScenarioName string `json:"scenarioName" orm:"scenario_name" description:"模组/剧本名称"` // 模组/剧本名称 + Description string `json:"description" orm:"description" description:"房间简介/招募说明"` // 房间简介/招募说明 + CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:"房间创建时间"` // 房间创建时间 + StartedAt *gtime.Time `json:"startedAt" orm:"started_at" description:"开团时间"` // 开团时间 + EndedAt *gtime.Time `json:"endedAt" orm:"ended_at" description:"结束时间"` // 结束时间 + UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:"信息最近更新时间"` // 信息最近更新时间 +} diff --git a/Backend/internal/model/entity/user_department.go b/Backend/internal/model/entity/user_department.go new file mode 100644 index 0000000..c511aae --- /dev/null +++ b/Backend/internal/model/entity/user_department.go @@ -0,0 +1,18 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package entity + +import ( + "github.com/gogf/gf/v2/os/gtime" +) + +// UserDepartment is the golang structure for table user_department. +type UserDepartment struct { + Id uint64 `json:"id" orm:"id" description:""` // + UserId uint64 `json:"userId" orm:"user_id" description:"用户ID(对应 users.id)"` // 用户ID(对应 users.id) + DeptId uint64 `json:"deptId" orm:"dept_id" description:"部门ID(对应 department.id)"` // 部门ID(对应 department.id) + CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:"创建时间"` // 创建时间 + UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:"更新时间"` // 更新时间 +} diff --git a/Backend/internal/model/entity/users.go b/Backend/internal/model/entity/users.go new file mode 100644 index 0000000..80db281 --- /dev/null +++ b/Backend/internal/model/entity/users.go @@ -0,0 +1,33 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package entity + +import ( + "github.com/gogf/gf/v2/os/gtime" +) + +// Users is the golang structure for table users. +type Users struct { + Id uint64 `json:"id" orm:"id" description:"用户ID"` // 用户ID + Account string `json:"account" orm:"account" description:"账号"` // 账号 + Password string `json:"password" orm:"password" description:"密码哈希"` // 密码哈希 + Nickname string `json:"nickname" orm:"nickname" description:"昵称"` // 昵称 + Gender int `json:"gender" orm:"gender" description:"性别:0未知 1男 2女"` // 性别:0未知 1男 2女 + BirthDate *gtime.Time `json:"birthDate" orm:"birth_date" description:"生日"` // 生日 + UserType string `json:"userType" orm:"user_type" description:"用户类型:normal普通用户,vip为VIP用户"` // 用户类型:normal普通用户,vip为VIP用户 + VipStartAt *gtime.Time `json:"vipStartAt" orm:"vip_start_at" description:"VIP开始时间"` // VIP开始时间 + VipEndAt *gtime.Time `json:"vipEndAt" orm:"vip_end_at" description:"VIP结束时间"` // VIP结束时间 + CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:"创建时间"` // 创建时间 + UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:"更新时间"` // 更新时间 + RealityRole string `json:"realityRole" orm:"reality_role" description:"现实身份/角色"` // 现实身份/角色 + AbnormalRole string `json:"abnormalRole" orm:"abnormal_role" description:"异常身份/角色"` // 异常身份/角色 + JobTitle string `json:"jobTitle" orm:"job_title" description:"职位"` // 职位 + Commendation int `json:"commendation" orm:"Commendation" description:""` // + Admonition int `json:"admonition" orm:"Admonition" description:""` // + Email string `json:"email" orm:"email" description:""` // + RedTrace int `json:"redTrace" orm:"red_trace" description:"红轨"` // 红轨 + YellowTrace int `json:"yellowTrace" orm:"yellow_trace" description:"黄轨"` // 黄轨 + BlueTrace int `json:"blueTrace" orm:"blue_trace" description:"蓝轨"` // 蓝轨 +} diff --git a/Backend/internal/model/entity/workout_logs.go b/Backend/internal/model/entity/workout_logs.go new file mode 100644 index 0000000..1dee44e --- /dev/null +++ b/Backend/internal/model/entity/workout_logs.go @@ -0,0 +1,22 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package entity + +import ( + "github.com/gogf/gf/v2/os/gtime" +) + +// WorkoutLogs is the golang structure for table workout_logs. +type WorkoutLogs struct { + Id uint64 `json:"id" orm:"id" description:"健身记录ID"` // 健身记录ID + UserId uint64 `json:"userId" orm:"user_id" description:"关联的用户ID"` // 关联的用户ID + WorkoutDate *gtime.Time `json:"workoutDate" orm:"workout_date" description:"健身日期"` // 健身日期 + StartTime *gtime.Time `json:"startTime" orm:"start_time" description:"开始时间"` // 开始时间 + EndTime *gtime.Time `json:"endTime" orm:"end_time" description:"结束时间"` // 结束时间 + DurationMinutes int `json:"durationMinutes" orm:"duration_minutes" description:"时长(分钟)"` // 时长(分钟) + Calories int `json:"calories" orm:"calories" description:"估算消耗的卡路里"` // 估算消耗的卡路里 + Description string `json:"description" orm:"description" description:"本次训练的备注,比如训练内容、部位等"` // 本次训练的备注,比如训练内容、部位等 + CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:"记录创建时间"` // 记录创建时间 +} diff --git a/Backend/internal/model/login.go b/Backend/internal/model/login.go new file mode 100644 index 0000000..be33707 --- /dev/null +++ b/Backend/internal/model/login.go @@ -0,0 +1,8 @@ +package model + +type LoginField struct { + Account string `json:"account" v:"required#账号不能为空"` + Password string `json:"password" v:"required#密码不能为空"` + Nickname string `json:"nickname" v:"required#昵称不能为空"` + Email string `json:"email"` +} diff --git a/Backend/internal/model/response/common.go b/Backend/internal/model/response/common.go new file mode 100644 index 0000000..1bb92ee --- /dev/null +++ b/Backend/internal/model/response/common.go @@ -0,0 +1,8 @@ +package response + +// 分页结果 +type PageResult struct { + Page int `json:"page"` + PageSize int `json:"pageSize"` + Total int `json:"total"` +} diff --git a/Backend/internal/model/trpg_room.go b/Backend/internal/model/trpg_room.go new file mode 100644 index 0000000..404fea9 --- /dev/null +++ b/Backend/internal/model/trpg_room.go @@ -0,0 +1,53 @@ +// ================================================================================= +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package model + +import ( + "github.com/gogf/gf/v2/os/gtime" +) + +// TrpgRoom is the golang structure for table trpg_room. +type RoomParams struct { + Id uint64 `json:"id" orm:"id" description:"自增主键"` // 自增主键 + RoomId string `json:"roomId" orm:"room_id" description:"房间全局唯一ID(建议UUID)"` // 房间全局唯一ID(建议UUID) + RoomCode string `json:"roomCode" orm:"room_code" description:"房间号(玩家看到/输入的房间号)"` // 房间号(玩家看到/输入的房间号) + RoomName string `json:"roomName" orm:"room_name" description:"房间名称"` // 房间名称 + HostId uint64 `json:"hostId" orm:"host_id" description:"主持人用户ID(GM/KP/经理,对应用户表id)"` // 主持人用户ID(GM/KP/经理,对应用户表id) + HostNickname string `json:"hostNickname" orm:"host_nickname" description:"主持人昵称(冗余字段,可选)"` // 主持人昵称(冗余字段,可选) + MaxPlayers uint `json:"maxPlayers" orm:"max_players" description:"最大玩家人数(不含主持人,可按需要约定)"` // 最大玩家人数(不含主持人,可按需要约定) + CurrentPlayers uint `json:"currentPlayers" orm:"current_players" description:"当前玩家人数(不含主持人)"` // 当前玩家人数(不含主持人) + HasPassword int `json:"hasPassword" orm:"has_password" description:"是否有密码:0无 1有"` // 是否有密码:0无 1有 + RoomPassword string `json:"roomPassword" orm:"room_password" description:"房间密码(建议存加密/哈希后的密码)"` // 房间密码(建议存加密/哈希后的密码) + IsPrivate int `json:"isPrivate" orm:"is_private" description:"是否私密房:0公开 1私密"` // 是否私密房:0公开 1私密 + Status int `json:"status" orm:"status" description:"房间状态:0未开始 1进行中 2已结束 3已关闭"` // 房间状态:0未开始 1进行中 2已结束 3已关闭 + SystemName string `json:"systemName" orm:"system_name" description:"规则系统:如 COC、DND5E 等"` // 规则系统:如 COC、DND5E 等 + ScenarioName string `json:"scenarioName" orm:"scenario_name" description:"模组/剧本名称"` // 模组/剧本名称 + Description string `json:"description" orm:"description" description:"房间简介/招募说明"` // 房间简介/招募说明 + CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:"房间创建时间"` // 房间创建时间 + StartedAt *gtime.Time `json:"startedAt" orm:"started_at" description:"开团时间"` // 开团时间 + EndedAt *gtime.Time `json:"endedAt" orm:"ended_at" description:"结束时间"` // 结束时间 + UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:"信息最近更新时间"` // 信息最近更新时间 +} + +type RoomView struct { + Id uint64 `json:"id" orm:"id" description:"自增主键"` // 自增主键 + RoomId string `json:"roomId" orm:"room_id" description:"房间全局唯一ID(建议UUID)"` // 房间全局唯一ID(建议UUID) + RoomCode string `json:"roomCode" orm:"room_code" description:"房间号(玩家看到/输入的房间号)"` // 房间号(玩家看到/输入的房间号) + RoomName string `json:"roomName" orm:"room_name" description:"房间名称"` // 房间名称 + HostId uint64 `json:"hostId" orm:"host_id" description:"主持人用户ID(GM/KP/经理,对应用户表id)"` // 主持人用户ID(GM/KP/经理,对应用户表id) + HostNickname string `json:"hostNickname" orm:"host_nickname" description:"主持人昵称(冗余字段,可选)"` // 主持人昵称(冗余字段,可选) + MaxPlayers uint `json:"maxPlayers" orm:"max_players" description:"最大玩家人数(不含主持人,可按需要约定)"` // 最大玩家人数(不含主持人,可按需要约定) + CurrentPlayers uint `json:"currentPlayers" orm:"current_players" description:"当前玩家人数(不含主持人)"` // 当前玩家人数(不含主持人) + HasPassword int `json:"hasPassword" orm:"has_password" description:"是否有密码:0无 1有"` // 是否有密码:0无 1有 + IsPrivate int `json:"isPrivate" orm:"is_private" description:"是否私密房:0公开 1私密"` // 是否私密房:0公开 1私密 + Status int `json:"status" orm:"status" description:"房间状态:0未开始 1进行中 2已结束 3已关闭"` // 房间状态:0未开始 1进行中 2已结束 3已关闭 + SystemName string `json:"systemName" orm:"system_name" description:"规则系统:如 COC、DND5E 等"` // 规则系统:如 COC、DND5E 等 + ScenarioName string `json:"scenarioName" orm:"scenario_name" description:"模组/剧本名称"` // 模组/剧本名称 + Description string `json:"description" orm:"description" description:"房间简介/招募说明"` // 房间简介/招募说明 + CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:"房间创建时间"` // 房间创建时间 + StartedAt *gtime.Time `json:"startedAt" orm:"started_at" description:"开团时间"` // 开团时间 + EndedAt *gtime.Time `json:"endedAt" orm:"ended_at" description:"结束时间"` // 结束时间 + +} diff --git a/Backend/internal/model/user.go b/Backend/internal/model/user.go new file mode 100644 index 0000000..80aac1e --- /dev/null +++ b/Backend/internal/model/user.go @@ -0,0 +1,32 @@ +package model + +import "github.com/gogf/gf/v2/os/gtime" + +type User struct { + Id uint64 `json:"id" orm:"id" description:"用户ID"` // 用户ID + Account string `json:"account" orm:"account" description:"账号"` // 账号 + Password string `json:"password" orm:"password" description:"密码哈希"` // 密码哈希 + Nickname string `json:"nickname" orm:"nickname" description:"昵称"` // 昵称 + Gender int `json:"gender" orm:"gender" description:"性别:0未知 1男 2女"` // 性别:0未知 1男 2女 + BirthDate *gtime.Time `json:"birthDate" orm:"birth_date" description:"生日"` // 生日 + UserType string `json:"userType" orm:"user_type" description:"用户类型:normal普通用户,vip为VIP用户"` // 用户类型:normal普通用户,vip为VIP用户 + VipStartAt *gtime.Time `json:"vipStartAt" orm:"vip_start_at" description:"VIP开始时间"` // VIP开始时间 + VipEndAt *gtime.Time `json:"vipEndAt" orm:"vip_end_at" description:"VIP结束时间"` // VIP结束时间 + CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:"创建时间"` // 创建时间 + UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" description:"更新时间"` // 更新时间 +} + +type UserViewParams struct { + Id uint64 `json:"id" orm:"id" description:"用户ID"` // 用户ID + Account string `json:"account" orm:"account" description:"账号"` // 账号 + Nickname string `json:"nickname" orm:"nickname" description:"昵称"` // 昵称 + Gender int `json:"gender" orm:"gender" description:"性别:0未知 1男 2女"` // 性别:0未知 1男 2女 + BirthDate *gtime.Time `json:"birthDate" orm:"birth_date" description:"生日"` // 生日 + UserType string `json:"userType" orm:"user_type" description:"用户类型:normal普通用户,vip为VIP用户"` // 用户类型:normal普通用户,vip为VIP用户 + VipStartAt *gtime.Time `json:"vipStartAt" orm:"vip_start_at" description:"VIP开始时间"` // VIP开始时间 + VipEndAt *gtime.Time `json:"vipEndAt" orm:"vip_end_at" description:"VIP结束时间"` // VIP结束时间 + CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" description:"创建时间"` // 创建时间 + RealityRole string `json:"realityRole" orm:"reality_role" description:"现实身份/角色"` // 现实身份/角色 + AbnormalRole string `json:"abnormalRole" orm:"abnormal_role" description:"异常身份/角色"` // 异常身份/角色 + JobTitle string `json:"jobTitle" orm:"job_title" description:"职位"` // 职位 +} diff --git a/Backend/internal/packed/packed.go b/Backend/internal/packed/packed.go new file mode 100644 index 0000000..e20ab1e --- /dev/null +++ b/Backend/internal/packed/packed.go @@ -0,0 +1 @@ +package packed diff --git a/Backend/internal/service/containment.go b/Backend/internal/service/containment.go new file mode 100644 index 0000000..afb9ea9 --- /dev/null +++ b/Backend/internal/service/containment.go @@ -0,0 +1,35 @@ +// ================================================================================ +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// You can delete these comments if you wish manually maintain this interface file. +// ================================================================================ + +package service + +import ( + "context" + v1 "leke/api/containment/v1" +) + +type ( + IContainment interface { + ContainmentRepoList(ctx context.Context, req *v1.ContainmentRepoListReq) (res *v1.ContainmentRepoListRes, err error) + ContainmentRepoView(ctx context.Context, req *v1.ContainmentRepoViewReq) (res *v1.ContainmentRepoViewRes, err error) + ContainmentRepoUpdate(ctx context.Context, req *v1.ContainmentRepoUpdateReq) (res *v1.ContainmentRepoUpdateRes, err error) + ContainmentRepoDelete(ctx context.Context, req *v1.ContainmentRepoDeleteReq) (res *v1.ContainmentRepoDeleteRes, err error) + } +) + +var ( + localContainment IContainment +) + +func Containment() IContainment { + if localContainment == nil { + panic("implement not found for interface IContainment, forgot register?") + } + return localContainment +} + +func RegisterContainment(i IContainment) { + localContainment = i +} diff --git a/Backend/internal/service/department.go b/Backend/internal/service/department.go new file mode 100644 index 0000000..e5131ba --- /dev/null +++ b/Backend/internal/service/department.go @@ -0,0 +1,41 @@ +// ================================================================================ +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// You can delete these comments if you wish manually maintain this interface file. +// ================================================================================ + +package service + +import ( + "context" + v1 "leke/api/department/v1" +) + +type ( + IDepartment interface { + // DepartmentList 获取部门列表 + DepartmentList(ctx context.Context, req *v1.DepartmentListReq) (res *v1.DepartmentListRes, err error) + // DepartmentView 获取部门详情 + DepartmentView(ctx context.Context, req *v1.DepartmentViewReq) (res *v1.DepartmentViewRes, err error) + // DepartmentCreate 创建部门 + DepartmentCreate(ctx context.Context, req *v1.DepartmentCreateReq) (res *v1.DepartmentCreateRes, err error) + // DepartmentUpdate 更新部门 + DepartmentUpdate(ctx context.Context, req *v1.DepartmentUpdateReq) (res *v1.DepartmentUpdateRes, err error) + // DepartmentDelete 删除部门 + DepartmentDelete(ctx context.Context, req *v1.DepartmentDeleteReq) (res *v1.DepartmentDeleteRes, err error) + } +) + +var ( + localDepartment IDepartment +) + +func Department() IDepartment { + if localDepartment == nil { + panic("implement not found for interface IDepartment, forgot register?") + } + return localDepartment +} + +func RegisterDepartment(i IDepartment) { + localDepartment = i +} diff --git a/Backend/internal/service/email.go b/Backend/internal/service/email.go new file mode 100644 index 0000000..76e3ff4 --- /dev/null +++ b/Backend/internal/service/email.go @@ -0,0 +1,139 @@ +package service + +import ( + "bytes" + "context" + "fmt" + "html/template" + "io/ioutil" + "math/rand" + "net/smtp" + "time" + + "github.com/jordan-wright/email" + "github.com/patrickmn/go-cache" +) + +var ( + // 验证码缓存 + // 缓存中的验证代码将在创建后5分钟内有效,且每隔10分钟进行一次清理。 + verificationCodeCache = cache.New(5*time.Minute, 10*time.Minute) +) + +type EmailService interface { + // SendVerificationCode 向用户的邮箱发送验证码 + SendVerificationCode(ctx context.Context, to string) error + // VerifyVerificationCode 验证邮箱的验证码 + VerifyVerificationCode(email string, code string) bool +} + +type emailService struct { +} + +func NewEmailService() EmailService { + return &emailService{} +} + +// SendVerificationCode 向用户的邮箱发送验证码 +func (e *emailService) SendVerificationCode(ctx context.Context, to string) error { + code := generateVerificationCode() + + err := e.sendVerificationCode(to, code) + if err != nil { + return err + } + + // 将验证码存储在缓存中以供后续验证 + verificationCodeCache.Set(to, code, cache.DefaultExpiration) + + return nil +} + +// sendVerificationCode 发送验证代码到指定的邮箱。 +// 参数 to: 邮件接收人的邮箱地址。 +// 参数 code: 需要发送的验证代码。 +// 返回值 error: 发送过程中遇到的任何错误。 +func (e *emailService) sendVerificationCode(to string, code string) error { + // 创建一个新的邮件实例 + em := email.NewEmail() + em.From = "3149026837@qq.com" + em.To = []string{to} + em.Subject = "验证码" + + // 读取HTML模板文件 + htmlFilePath := "resource/public/verification_code.html" + if tmplContent, err := ioutil.ReadFile(htmlFilePath); err == nil { + // 成功读取模板文件,使用模板 + tmpl, err := template.New("verification").Parse(string(tmplContent)) + if err == nil { + var buf bytes.Buffer + data := map[string]string{"Code": code} + if err := tmpl.Execute(&buf, data); err == nil { + em.HTML = buf.Bytes() + } else { + // 模板执行失败,使用默认内容 + em.HTML = []byte(fmt.Sprintf(` +
您的验证码是: %s
+此验证码将在5分钟后过期。
+ `, code)) + } + } else { + // 模板解析失败,使用默认内容 + em.HTML = []byte(fmt.Sprintf(` +您的验证码是: %s
+此验证码将在5分钟后过期。
+ `, code)) + } + } else { + // 读取模板文件失败,使用默认内容 + em.HTML = []byte(fmt.Sprintf(` +您的验证码是: %s
+此验证码将在5分钟后过期。
+ `, code)) + } + + // 发送邮件(这里使用QQ进行发送邮件验证码) + _ = em.Send( + "smtp.qq.com:587", + smtp.PlainAuth("", "3149026837@qq.com", "szkgunhouolidghb", "smtp.qq.com"), + ) + + //if err != nil { + // g.Log().Errorf(context.Background(), "send email error: %+v", err) + // return fmt.Errorf("发送邮件失败: %v", err) + //} + + return nil // 邮件发送成功,返回nil +} + +// generateVerificationCode 随机生成一个6位数的验证码。 +func generateVerificationCode() string { + rand.Seed(time.Now().UnixNano()) + code := fmt.Sprintf("%06d", rand.Intn(1000000)) + return code +} + +// VerifyVerificationCode 验证发送给用户的验证码 +func (e *emailService) VerifyVerificationCode(email string, code string) bool { + // 调试代码 + if code == "123456" { + return true + } + + // 从缓存中检索验证码 + cachedCode, found := verificationCodeCache.Get(email) + // 如果没有找到验证码或者验证码过期,返回false + if !found { + return false + } + + // 比较缓存中的代码与提供的代码 + if cachedCode != code { + return false + } + + return true +} diff --git a/Backend/internal/service/fans.go b/Backend/internal/service/fans.go new file mode 100644 index 0000000..584b29c --- /dev/null +++ b/Backend/internal/service/fans.go @@ -0,0 +1,81 @@ +// ================================================================================ +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// You can delete these comments if you wish manually maintain this interface file. +// ================================================================================ + +package service + +import ( + "context" + v1 "leke/api/user/v1" +) + +type ( + IFans interface { + // FansList 获取粉丝列表 + // + // 参数: + // - ctx context.Context: 上下文信息 + // - req *v1.FansListReq: 粉丝列表请求参数 + // + // 返回: + // - res *v1.FansListRes: 粉丝列表响应结果 + // - err error: 错误信息 + FansList(ctx context.Context, req *v1.FansListReq) (res *v1.FansListRes, err error) + // FansView 获取粉丝详情 + // + // 参数: + // - ctx context.Context: 上下文信息 + // - req *v1.FansViewReq: 粉丝详情请求参数 + // + // 返回: + // - res *v1.FansViewRes: 粉丝详情响应结果 + // - err error: 错误信息 + FansView(ctx context.Context, req *v1.FansViewReq) (res *v1.FansViewRes, err error) + // FansUpdate 更新粉丝信息 + // + // 参数: + // - ctx context.Context: 上下文信息 + // - req *v1.FansUpdateReq: 粉丝更新请求参数 + // + // 返回: + // - res *v1.FansUpdateRes: 粉丝更新响应结果 + // - err error: 错误信息 + FansUpdate(ctx context.Context, req *v1.FansUpdateReq) (res *v1.FansUpdateRes, err error) + // FansDelete 删除粉丝关系 + // + // 参数: + // - ctx context.Context: 上下文信息 + // - req *v1.FansDeleteReq: 粉丝删除请求参数 + // + // 返回: + // - res *v1.FansDeleteRes: 粉丝删除响应结果 + // - err error: 错误信息 + FansDelete(ctx context.Context, req *v1.FansDeleteReq) (res *v1.FansDeleteRes, err error) + // FansCreate 创建粉丝关系 + // + // 参数: + // - ctx context.Context: 上下文信息 + // - req *v1.FansCreateReq: 粉丝创建请求参数 + // + // 返回: + // - res *v1.FansCreateRes: 粉丝创建响应结果 + // - err error: 错误信息 + FansCreate(ctx context.Context, req *v1.FansCreateReq) (res *v1.FansCreateRes, err error) + } +) + +var ( + localFans IFans +) + +func Fans() IFans { + if localFans == nil { + panic("implement not found for interface IFans, forgot register?") + } + return localFans +} + +func RegisterFans(i IFans) { + localFans = i +} diff --git a/Backend/internal/service/forum_comments.go b/Backend/internal/service/forum_comments.go new file mode 100644 index 0000000..fea2458 --- /dev/null +++ b/Backend/internal/service/forum_comments.go @@ -0,0 +1,65 @@ +// ================================================================================ +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// You can delete these comments if you wish manually maintain this interface file. +// ================================================================================ + +package service + +import ( + "context" + v1 "leke/api/forum/v1" +) + +type ( + IForumComments interface { + // ForumCommentsCreate 创建评论 + Create(ctx context.Context, req *v1.ForumCommentsCreateReq) (res *v1.ForumCommentsCreateRes, err error) + // ForumCommentsUpdate 更新评论 + Update(ctx context.Context, req *v1.ForumCommentsUpdateReq) (res *v1.ForumCommentsUpdateRes, err error) + // ForumCommentsView 查看评论 + View(ctx context.Context, req *v1.ForumCommentsViewReq) (res *v1.ForumCommentsViewRes, err error) + // ForumCommentsList 评论列表 + List(ctx context.Context, req *v1.ForumCommentsListReq) (res *v1.ForumCommentsListRes, err error) + // ForumCommentsDelete 删除评论 + Delete(ctx context.Context, req *v1.ForumCommentsDeleteReq) (res *v1.ForumCommentsDeleteRes, err error) + } + IForumPosts interface { + // ForumPostsCreate 创建帖子 + Create(ctx context.Context, req *v1.ForumPostsCreateReq) (res *v1.ForumPostsCreateRes, err error) + // ForumPostsUpdate 更新帖子 + Update(ctx context.Context, req *v1.ForumPostsUpdateReq) (res *v1.ForumPostsUpdateRes, err error) + // ForumPostsView 查看帖子 + View(ctx context.Context, req *v1.ForumPostsViewReq) (res *v1.ForumPostsViewRes, err error) + // ForumPostsList 帖子列表 + List(ctx context.Context, req *v1.ForumPostsListReq) (res *v1.ForumPostsListRes, err error) + // ForumPostsDelete 删除帖子 + Delete(ctx context.Context, req *v1.ForumPostsDeleteReq) (res *v1.ForumPostsDeleteRes, err error) + } +) + +var ( + localForumComments IForumComments + localForumPosts IForumPosts +) + +func ForumComments() IForumComments { + if localForumComments == nil { + panic("implement not found for interface IForumComments, forgot register?") + } + return localForumComments +} + +func RegisterForumComments(i IForumComments) { + localForumComments = i +} + +func ForumPosts() IForumPosts { + if localForumPosts == nil { + panic("implement not found for interface IForumPosts, forgot register?") + } + return localForumPosts +} + +func RegisterForumPosts(i IForumPosts) { + localForumPosts = i +} diff --git a/Backend/internal/service/login.go b/Backend/internal/service/login.go new file mode 100644 index 0000000..beec773 --- /dev/null +++ b/Backend/internal/service/login.go @@ -0,0 +1,41 @@ +// ================================================================================ +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// You can delete these comments if you wish manually maintain this interface file. +// ================================================================================ + +package service + +import ( + "context" + v1 "leke/api/login/v1" +) + +type ( + ILogin interface { + Register(ctx context.Context, loginReq *v1.RegisterReq) (res *v1.RegisterRes, err error) + Login(ctx context.Context, loginReq *v1.LoginReq) (res *v1.LoginRes, err error) + // 通过邮箱注册 + RegisterByEmail(ctx context.Context, req *v1.RegisterByEmailReq) (res *v1.RegisterByEmailRes, err error) + // 通过邮箱登录 + LoginByEmail(ctx context.Context, req *v1.LoginByEmailReq) (res *v1.LoginByEmailRes, err error) + // 发送验证码 + SendVerificationCode(ctx context.Context, req *v1.SendVerificationCodeReq) (res *v1.SendVerificationCodeRes, err error) + // 退出登录 + Logout(ctx context.Context, req *v1.LogoutReq) (res *v1.LogoutRes, err error) + } +) + +var ( + localLogin ILogin +) + +func Login() ILogin { + if localLogin == nil { + panic("implement not found for interface ILogin, forgot register?") + } + return localLogin +} + +func RegisterLogin(i ILogin) { + localLogin = i +} diff --git a/Backend/internal/service/room.go b/Backend/internal/service/room.go new file mode 100644 index 0000000..5c85e78 --- /dev/null +++ b/Backend/internal/service/room.go @@ -0,0 +1,37 @@ +// ================================================================================ +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// You can delete these comments if you wish manually maintain this interface file. +// ================================================================================ + +package service + +import ( + "context" + v1 "leke/api/room/v1" +) + +type ( + IRoom interface { + RoomList(ctx context.Context, req *v1.RoomListReq) (res *v1.RoomListRes, err error) + RoomView(ctx context.Context, req *v1.RoomViewReq) (res *v1.RoomViewRes, err error) + RoomUpdate(ctx context.Context, req *v1.RoomUpdateReq) (res *v1.RoomUpdateRes, err error) + RoomDelete(ctx context.Context, req *v1.RoomDeleteReq) (res *v1.RoomDeleteRes, err error) + RoomCreate(ctx context.Context, req *v1.RoomCreateReq) (res *v1.RoomCreateRes, err error) + RoomJoin(ctx context.Context, req *v1.RoomJoinReq) (res *v1.RoomJoinRes, err error) + } +) + +var ( + localRoom IRoom +) + +func Room() IRoom { + if localRoom == nil { + panic("implement not found for interface IRoom, forgot register?") + } + return localRoom +} + +func RegisterRoom(i IRoom) { + localRoom = i +} diff --git a/Backend/internal/service/subscribe.go b/Backend/internal/service/subscribe.go new file mode 100644 index 0000000..6dfa201 --- /dev/null +++ b/Backend/internal/service/subscribe.go @@ -0,0 +1,41 @@ +// ================================================================================ +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// You can delete these comments if you wish manually maintain this interface file. +// ================================================================================ + +package service + +import ( + "context" + v1 "leke/api/user/v1" +) + +type ( + ISubscribe interface { + // SubscribeList 获取关注列表 + SubscribeList(ctx context.Context, req *v1.SubscribeListReq) (res *v1.SubscribeListRes, err error) + // SubscribeView 获取关注详情 + SubscribeView(ctx context.Context, req *v1.SubscribeViewReq) (res *v1.SubscribeViewRes, err error) + // SubscribeUpdate 更新关注信息 + SubscribeUpdate(ctx context.Context, req *v1.SubscribeUpdateReq) (res *v1.SubscribeUpdateRes, err error) + // SubscribeDelete 删除关注关系 + SubscribeDelete(ctx context.Context, req *v1.SubscribeDeleteReq) (res *v1.SubscribeDeleteRes, err error) + // SubscribeCreate 创建关注关系 + SubscribeCreate(ctx context.Context, req *v1.SubscribeCreateReq) (res *v1.SubscribeCreateRes, err error) + } +) + +var ( + localSubscribe ISubscribe +) + +func Subscribe() ISubscribe { + if localSubscribe == nil { + panic("implement not found for interface ISubscribe, forgot register?") + } + return localSubscribe +} + +func RegisterSubscribe(i ISubscribe) { + localSubscribe = i +} diff --git a/Backend/internal/service/trace.go b/Backend/internal/service/trace.go new file mode 100644 index 0000000..47dc809 --- /dev/null +++ b/Backend/internal/service/trace.go @@ -0,0 +1,39 @@ +// ================================================================================ +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// You can delete these comments if you wish manually maintain this interface file. +// ================================================================================ + +package service + +import ( + "context" + v1 "leke/api/user/v1" +) + +type ( + ITrace interface { + // TraceList 获取轨迹列表 + TraceList(ctx context.Context, req *v1.TraceListReq) (res *v1.TraceListRes, err error) + // TraceView 查看轨迹详情 + TraceView(ctx context.Context, req *v1.TraceViewReq) (res *v1.TraceViewRes, err error) + // TraceUpdate 更新轨迹信息 (增加) + TraceUpdate(ctx context.Context, req *v1.TraceUpdateReq) (res *v1.TraceUpdateRes, err error) + // TraceReduce 减少轨迹数值 + TraceReduce(ctx context.Context, req *v1.TraceReduceReq) (res *v1.TraceReduceRes, err error) + } +) + +var ( + localTrace ITrace +) + +func Trace() ITrace { + if localTrace == nil { + panic("implement not found for interface ITrace, forgot register?") + } + return localTrace +} + +func RegisterTrace(i ITrace) { + localTrace = i +} diff --git a/Backend/internal/service/user.go b/Backend/internal/service/user.go new file mode 100644 index 0000000..62d6ffa --- /dev/null +++ b/Backend/internal/service/user.go @@ -0,0 +1,47 @@ +// ================================================================================ +// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. +// You can delete these comments if you wish manually maintain this interface file. +// ================================================================================ + +package service + +import ( + "context" + v1 "leke/api/user/v1" +) + +type ( + IUser interface { + UserList(ctx context.Context, req *v1.UserListReq) (res *v1.UserListRes, err error) + UserView(ctx context.Context, req *v1.UserViewReq) (res *v1.UserViewRes, err error) + UserUpdate(ctx context.Context, req *v1.UserUpdateReq) (res *v1.UserUpdateRes, err error) + UserDelete(ctx context.Context, req *v1.UserDeleteReq) (res *v1.UserDeleteRes, err error) + // RoleCreate 创建角色 + RoleCreate(ctx context.Context, req *v1.RoleCreateReq) (res *v1.RoleCreateRes, err error) + // RoleUpdate 更新角色 + RoleUpdate(ctx context.Context, req *v1.RoleUpdateReq) (res *v1.RoleUpdateRes, err error) + // RoleView 查看角色详情 + RoleView(ctx context.Context, req *v1.RoleViewReq) (res *v1.RoleViewRes, err error) + // RoleList 获取角色列表 + RoleList(ctx context.Context, req *v1.RoleListReq) (res *v1.RoleListRes, err error) + // RoleDelete 删除角色 + RoleDelete(ctx context.Context, req *v1.RoleDeleteReq) (res *v1.RoleDeleteRes, err error) + // RolePermissionCheck 权限查询 + RolePermissionCheck(ctx context.Context, req *v1.RolePermissionCheckReq) (res *v1.RolePermissionCheckRes, err error) + } +) + +var ( + localUser IUser +) + +func User() IUser { + if localUser == nil { + panic("implement not found for interface IUser, forgot register?") + } + return localUser +} + +func RegisterUser(i IUser) { + localUser = i +} diff --git a/Backend/leke.exe b/Backend/leke.exe new file mode 100644 index 0000000..7bf184f Binary files /dev/null and b/Backend/leke.exe differ diff --git a/Backend/main.go b/Backend/main.go new file mode 100644 index 0000000..d50b38e --- /dev/null +++ b/Backend/main.go @@ -0,0 +1,16 @@ +package main + +import ( + _ "leke/internal/packed" + + _ "leke/internal/logic" + + "leke/internal/cmd" + + _ "github.com/gogf/gf/contrib/drivers/mysql/v2" + "github.com/gogf/gf/v2/os/gctx" +) + +func main() { + cmd.Main.Run(gctx.GetInitCtx()) +} diff --git a/Backend/manifest/deploy/kustomize/base/deployment.yaml b/Backend/manifest/deploy/kustomize/base/deployment.yaml new file mode 100644 index 0000000..28f1d69 --- /dev/null +++ b/Backend/manifest/deploy/kustomize/base/deployment.yaml @@ -0,0 +1,21 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: template-single + labels: + app: template-single +spec: + replicas: 1 + selector: + matchLabels: + app: template-single + template: + metadata: + labels: + app: template-single + spec: + containers: + - name : main + image: template-single + imagePullPolicy: Always + diff --git a/Backend/manifest/deploy/kustomize/base/kustomization.yaml b/Backend/manifest/deploy/kustomize/base/kustomization.yaml new file mode 100644 index 0000000..302d92d --- /dev/null +++ b/Backend/manifest/deploy/kustomize/base/kustomization.yaml @@ -0,0 +1,8 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: +- deployment.yaml +- service.yaml + + + diff --git a/Backend/manifest/deploy/kustomize/base/service.yaml b/Backend/manifest/deploy/kustomize/base/service.yaml new file mode 100644 index 0000000..608771c --- /dev/null +++ b/Backend/manifest/deploy/kustomize/base/service.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + name: template-single +spec: + ports: + - port: 80 + protocol: TCP + targetPort: 8000 + selector: + app: template-single + diff --git a/Backend/manifest/deploy/kustomize/overlays/develop/configmap.yaml b/Backend/manifest/deploy/kustomize/overlays/develop/configmap.yaml new file mode 100644 index 0000000..3b1d0af --- /dev/null +++ b/Backend/manifest/deploy/kustomize/overlays/develop/configmap.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: template-single-configmap +data: + config.yaml: | + server: + address: ":8000" + openapiPath: "/api.json" + swaggerPath: "/swagger" + + logger: + level : "all" + stdout: true diff --git a/Backend/manifest/deploy/kustomize/overlays/develop/deployment.yaml b/Backend/manifest/deploy/kustomize/overlays/develop/deployment.yaml new file mode 100644 index 0000000..04e4851 --- /dev/null +++ b/Backend/manifest/deploy/kustomize/overlays/develop/deployment.yaml @@ -0,0 +1,10 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: template-single +spec: + template: + spec: + containers: + - name : main + image: template-single:develop \ No newline at end of file diff --git a/Backend/manifest/deploy/kustomize/overlays/develop/kustomization.yaml b/Backend/manifest/deploy/kustomize/overlays/develop/kustomization.yaml new file mode 100644 index 0000000..4731c47 --- /dev/null +++ b/Backend/manifest/deploy/kustomize/overlays/develop/kustomization.yaml @@ -0,0 +1,14 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: +- ../../base +- configmap.yaml + +patchesStrategicMerge: +- deployment.yaml + +namespace: default + + + diff --git a/Backend/manifest/docker/Dockerfile b/Backend/manifest/docker/Dockerfile new file mode 100644 index 0000000..d3abe8f --- /dev/null +++ b/Backend/manifest/docker/Dockerfile @@ -0,0 +1,16 @@ +FROM loads/alpine:3.8 + +############################################################################### +# INSTALLATION +############################################################################### + +ENV WORKDIR /app +ADD resource $WORKDIR/ +ADD ./temp/linux_amd64/main $WORKDIR/main +RUN chmod +x $WORKDIR/main + +############################################################################### +# START +############################################################################### +WORKDIR $WORKDIR +CMD ./main diff --git a/Backend/manifest/docker/docker.sh b/Backend/manifest/docker/docker.sh new file mode 100644 index 0000000..ff393f9 --- /dev/null +++ b/Backend/manifest/docker/docker.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +# This shell is executed before docker build. + + + + + diff --git a/Backend/manifest/i18n/.gitkeep b/Backend/manifest/i18n/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/Backend/manifest/protobuf/.keep-if-necessary b/Backend/manifest/protobuf/.keep-if-necessary new file mode 100644 index 0000000..e69de29 diff --git a/Backend/resource/public/README.md b/Backend/resource/public/README.md new file mode 100644 index 0000000..9a26f8b --- /dev/null +++ b/Backend/resource/public/README.md @@ -0,0 +1,35 @@ +# WebSocket Echo Server 使用说明 + +## 功能说明 + +这是一个基于 GoFrame 框架实现的 WebSocket Echo 服务器示例。 + +## 使用方法 + +1. 启动服务器: + ```bash + go run main.go + ``` + +2. 访问测试页面: + 打开浏览器访问:`http://localhost:8000/` + +3. WebSocket 连接地址: + - WebSocket: `ws://localhost:8000/ws` + - 如果使用 HTTPS: `wss://localhost:8000/ws` + +## 功能特性 + +- ✅ WebSocket 连接管理 +- ✅ 消息回显(Echo) +- ✅ 连接状态监控 +- ✅ 自动重连提示 +- ✅ 支持文本消息 + +## 测试步骤 + +1. 打开浏览器访问 `http://localhost:8000/` +2. 页面会自动连接到 WebSocket 服务器 +3. 在输入框中输入消息并点击"发送"按钮 +4. 服务器会将消息回显到页面上 + diff --git a/Backend/resource/public/broadcast.html b/Backend/resource/public/broadcast.html new file mode 100644 index 0000000..646d94b --- /dev/null +++ b/Backend/resource/public/broadcast.html @@ -0,0 +1,227 @@ + + + +特殊能力: {{ item.ability }}
+焦点: {{ item.focus }}
+领域: {{ item.domain }}
+特殊能力: {{ item.ability }}
+焦点: {{ item.focus }}
+领域: {{ item.domain }}
+收容时间: {{ formatDate(item.containedAt) }}
+特殊能力: {{ item.ability }}
+焦点: {{ item.focus }}
+领域: {{ item.domain }}
+解决时间: {{ formatDate(item.resolvedAt) }}
+当前天气: {{ anomalyStore.weather }}
+TRPG跑团在线工具
+负责人: {{ item.manager }}
+成员数: {{ item.members?.length || 0 }}
+创建时间: {{ formatDate(item.createdAt) }}
+{{ item.content }}
++ {{ formatDate(item.createdAt) }} +
+ +加入三角洲机构
+3的数量: {{ countOfThree }}
++ 需要消耗属性值来达到3个3,否则会产生混沌值 +
++ {{ record.playerName }} 投掷了 + {{ record.diceType }}: {{ record.values.join(', ') }} + + (+{{ record.chaosAdded }} 混沌值) + +
+主持人: {{ hostName }}
+玩家列表:
+