diff --git a/hxywd666/README.md b/hxywd666/README.md new file mode 100644 index 0000000..b4534dc --- /dev/null +++ b/hxywd666/README.md @@ -0,0 +1,26 @@ +# 说明 + +杭电助手后端部的大佬你好,我是计算机学院软件工程专业的`23050724黄效瑜`同学 + +这个代码按照后端任务做了基本的问答功能和登录鉴权功能 + +代码文件也是进行了模块化管理,因为我本身是有少量工程化开发经验的 + +问答功能就是类似于知乎那样的发帖的模式,一个人发布帖子,其它用户可以在下面评论 + +除了最基本的问答功能,我还增加了一些用户账户管理功能,比如修改用户个人信息 + +还有接入了星火大模型,但只有最基本的聊天功能,勉强……算是接入了一个AI助手 + +具体功能不在这里细说了,请看代码 + +在这里先自我检讨一下: + +时间有限,我没有给代码写注释,但是代码量又比较多…… + +而且有些功能开发得比较粗糙,在一些细节处理上做的不是很好,比如没有弄配置文件,没有做事务一致性处理…… + +还请见谅 + + + diff --git a/hxywd666/controller/bot.go b/hxywd666/controller/bot.go new file mode 100644 index 0000000..874b803 --- /dev/null +++ b/hxywd666/controller/bot.go @@ -0,0 +1,96 @@ +package controller + +import ( + "QASystem/dao" + "QASystem/models" + "QASystem/utils" + "encoding/base64" + "github.com/gin-gonic/gin" + "github.com/google/uuid" + "strconv" + "strings" +) + +type BotController struct{} + +type GetBotProfileRequest struct { + Name string `json:"name"` + Avatar string `json:"avatar"` +} + +type UpdateBotProfileRequest struct { + Name string `json:"name"` + Avatar string `json:"avatar"` + UserId string `json:"userId"` +} + +func (b BotController) GetBotProfile(c *gin.Context) { + paramId := c.Param("id") + botId, err := strconv.ParseInt(paramId, 10, 64) + if err != nil { + ReturnError(c, 0, "服务端异常") + } + bot, err := dao.GetBotByID(botId) + if err != nil { + ReturnError(c, 0, "获取大模型信息失败") + return + } + if bot == nil { + ReturnError(c, 0, "获取大模型信息失败") + return + } + res := &GetBotProfileRequest{ + Name: bot.Name, + Avatar: bot.Avatar, + } + ReturnSuccess(c, 1, "获取大模型信息成功", res) +} + +func (b BotController) UpdateBotProfile(c *gin.Context) { + var req UpdateBotProfileRequest + err := c.ShouldBindJSON(&req) + if err != nil { + ReturnError(c, 0, "参数错误") + } + + avatar := req.Avatar + if !utils.ValidatorURL(avatar) { + fileExtension := utils.GetImageExtensionFromBase64(avatar) + if fileExtension == "" { + ReturnError(c, 0, "头像格式错误") + return + } + fileName, err := uuid.NewRandom() + if err != nil { + ReturnError(c, 0, "图片上传失败") + return + } + file := fileName.String() + fileExtension + base64Avatar := avatar[strings.Index(avatar, ",")+1:] + imgBytes, err := base64.StdEncoding.DecodeString(base64Avatar) + if err != nil { + ReturnError(c, 0, "图片上传失败") + return + } + url := utils.UploadFile(imgBytes, file) + if url == "" { + ReturnError(c, 0, "图片上传失败") + return + } + userId, err := strconv.ParseInt(req.UserId, 10, 64) + if err != nil { + ReturnError(c, 0, "服务端异常") + } + bot := &models.Bot{ + Name: req.Name, + Avatar: url, + UserId: userId, + } + isUpdate := dao.UpdateBotProfile(bot) + if isUpdate != nil { + ReturnError(c, 0, "更新大模型信息失败") + return + } + ReturnSuccess(c, 1, "更新大模型信息成功", nil) + } +} diff --git a/hxywd666/controller/chat.go b/hxywd666/controller/chat.go new file mode 100644 index 0000000..b8b5d42 --- /dev/null +++ b/hxywd666/controller/chat.go @@ -0,0 +1,28 @@ +package controller + +import ( + "QASystem/utils" + "github.com/gin-gonic/gin" +) + +type ChatController struct{} + +type ChatRequest struct { + Message string `json:"message"` + Model string `json:"model"` +} + +func (chat ChatController) ChatWithSpark(c *gin.Context) { + var chatRequest ChatRequest + err := c.ShouldBindJSON(&chatRequest) + if err != nil { + ReturnError(c, 0, "参数错误") + } + res, err := utils.SendRequest(chatRequest.Message, chatRequest.Model) + if err != nil { + ReturnError(c, 0, "请求失败") + panic(err) + return + } + ReturnSuccess(c, 1, "请求成功", res) +} diff --git a/hxywd666/controller/comment.go b/hxywd666/controller/comment.go new file mode 100644 index 0000000..185e48b --- /dev/null +++ b/hxywd666/controller/comment.go @@ -0,0 +1,97 @@ +package controller + +import ( + "QASystem/dao" + "QASystem/models" + "github.com/gin-gonic/gin" + "strconv" + "time" +) + +type CommentController struct{} + +type CreateCommentRequest struct { + Content string `json:"content"` + PostID int64 `json:"post_id"` +} + +type GetCommentRequest struct { + Page int `json:"page"` + PageSize int `json:"pageSize"` + PostID int64 `json:"post_id"` + OrderBy int `json:"order_by"` +} + +type GetCommentResponse struct { + Content string `json:"content"` + CreatTime string `json:"create_time"` + Avatar string `json:"avatar"` + Name string `json:"name"` + Likes int64 `json:"likes"` +} + +func (cc CommentController) CreateComment(c *gin.Context) { + var req CreateCommentRequest + err := c.ShouldBind(&req) + if err != nil { + ReturnError(c, 0, "参数错误") + return + } + comment := &models.Comment{ + Content: req.Content, + PostID: req.PostID, + UserID: c.GetInt64("user_id"), + Likes: 0, + CreateTime: time.Now(), + } + err = dao.CreateComment(comment) + if err != nil { + ReturnError(c, 0, "评论失败") + return + } + ReturnSuccess(c, 1, "评论成功", nil) +} + +func (cc CommentController) DeleteComment(c *gin.Context) { + commentID, err := strconv.ParseInt(c.Param("id"), 10, 64) + if err != nil { + ReturnError(c, 0, "参数错误") + return + } + err = dao.DeleteComment(commentID) + if err != nil { + ReturnError(c, 0, "删除失败") + return + } + ReturnSuccess(c, 1, "删除成功", nil) +} + +func (cc CommentController) GetComment(c *gin.Context) { + var req GetCommentRequest + err := c.ShouldBind(&req) + if err != nil { + ReturnError(c, 0, "参数错误") + return + } + comments, err := dao.GetComment(req.PostID, req.Page, req.PageSize, req.OrderBy) + if err != nil { + ReturnError(c, 0, "获取失败") + return + } + var res []GetCommentResponse + for _, comment := range comments { + user, err := dao.GetUserByID(comment.UserID) + if err != nil { + ReturnError(c, 0, "获取失败") + return + } + res = append(res, GetCommentResponse{ + Content: comment.Content, + CreatTime: comment.CreateTime.Format("2006-01-02 15:04:05"), + Avatar: user.Avatar, + Name: user.Name, + Likes: comment.Likes, + }) + } + ReturnSuccess(c, 1, "获取成功", res) +} diff --git a/hxywd666/controller/common.go b/hxywd666/controller/common.go new file mode 100644 index 0000000..924015d --- /dev/null +++ b/hxywd666/controller/common.go @@ -0,0 +1,33 @@ +package controller + +import ( + "github.com/gin-gonic/gin" +) + +type JsonStruct struct { + Code int `json:"code"` + Msg interface{} `json:"msg"` + Data interface{} `json:"data"` +} + +type JsonErrorStruct struct { + Code int `json:"code"` + Msg interface{} `json:"msg"` +} + +func ReturnSuccess(c *gin.Context, code int, msg interface{}, data interface{}) { + json := &JsonStruct{ + Code: code, + Msg: msg, + Data: data, + } + c.JSON(200, json) +} + +func ReturnError(c *gin.Context, code int, msg interface{}) { + json := &JsonErrorStruct{ + Code: code, + Msg: msg, + } + c.JSON(200, json) +} diff --git a/hxywd666/controller/dialog.go b/hxywd666/controller/dialog.go new file mode 100644 index 0000000..0f55f3f --- /dev/null +++ b/hxywd666/controller/dialog.go @@ -0,0 +1,183 @@ +package controller + +import ( + "QASystem/dao" + "QASystem/models" + "github.com/gin-gonic/gin" + "strconv" + "time" +) + +type DialogController struct{} + +type CreateDialogResponse struct { + Name string `json:"name"` + ID int64 `json:"id"` + CreateTime string `json:"createTime"` +} + +type EditDialogNameRequest struct { + Name string `json:"newName"` + ID int64 `json:"dialogId"` +} + +type GetDialogListResponse struct { + ID int64 `json:"id"` + Name string `json:"name"` + CreateTime string `json:"createTime"` +} + +type GetDialogDetailResponse struct { + Content string `json:"content"` + CreateTime string `json:"createTime"` + Type int `json:"type"` + ID int64 `json:"id"` +} + +type SaveDialogRequest struct { + Content string `json:"content"` + CreateTime string `json:"createTime"` + Type int `json:"type"` + DialogID int64 `json:"dialogId"` +} + +func (d DialogController) CreateDialog(c *gin.Context) { + now := time.Now() + dialog := &models.Dialog{ + UserID: c.GetInt64("user_id"), + CreateTime: now, + Name: "New Chat", + } + + err := dao.CreateDialog(dialog) + if err != nil { + ReturnError(c, 0, "创建对话失败") + return + } + + res := &CreateDialogResponse{ + Name: dialog.Name, + ID: dialog.ID, + CreateTime: now.Format("2006-01-02 15:04:05"), + } + ReturnSuccess(c, 1, "创建对话成功", res) +} + +func (d DialogController) DeleteDialog(c *gin.Context) { + dialogID, _ := strconv.ParseInt(c.Param("id"), 10, 64) + err := dao.DeleteDialog(dialogID) + if err != nil { + ReturnError(c, 0, "删除对话失败") + return + } + err1 := dao.DeleteDialogDetail(dialogID) + if err1 != nil { + ReturnError(c, 0, "删除对话记录失败") + return + } + ReturnSuccess(c, 1, "删除对话成功", nil) +} + +func (d DialogController) DeleteOneDialogDetail(c *gin.Context) { + dialogDetailID, _ := strconv.ParseInt(c.Param("id"), 10, 64) + err := dao.DeleteOneDialogDetail(dialogDetailID) + if err != nil { + ReturnError(c, 0, "删除对话记录失败") + return + } + ReturnSuccess(c, 1, "删除对话记录成功", nil) +} + +func (d DialogController) EditDialogName(c *gin.Context) { + var req EditDialogNameRequest + err := c.ShouldBindJSON(&req) + if err != nil { + ReturnError(c, 0, "参数错误") + return + } + dialogID := req.ID + newName := req.Name + err = dao.EditDialogName(dialogID, newName) + if err != nil { + ReturnError(c, 0, "修改对话名称失败") + return + } + ReturnSuccess(c, 1, "修改对话名称成功", nil) +} + +func (d DialogController) GetDialogList(c *gin.Context) { + userID := c.GetInt64("user_id") + dialogList, err := dao.GetDialogList(userID) + if err != nil { + ReturnError(c, 0, "获取对话列表失败") + return + } + var res []GetDialogListResponse + for _, dialog := range dialogList { + item := GetDialogListResponse{ + ID: dialog.ID, + Name: dialog.Name, + CreateTime: dialog.CreateTime.Format("2006-01-02 15:04:05"), + } + res = append(res, item) + } + ReturnSuccess(c, 1, "获取对话列表成功", res) +} + +func (d DialogController) GetOneDialog(c *gin.Context) { + dialogID, _ := strconv.ParseInt(c.Param("id"), 10, 64) + oneDialog, err := dao.GetOneDialog(dialogID) + if err != nil { + ReturnError(c, 0, "获取对话失败") + return + } + res := &GetDialogListResponse{ + ID: oneDialog.ID, + Name: oneDialog.Name, + CreateTime: oneDialog.CreateTime.Format("2006-01-02 15:04:05"), + } + ReturnSuccess(c, 1, "获取对话成功", res) +} + +func (d DialogController) GetDialogDetails(c *gin.Context) { + dialogID, _ := strconv.ParseInt(c.Param("id"), 10, 64) + dialogDetails, err := dao.GetDialogDetails(dialogID) + if err != nil { + ReturnError(c, 0, "获取对话内容失败") + return + } + var res []GetDialogDetailResponse + for _, detail := range dialogDetails { + item := GetDialogDetailResponse{ + Content: detail.Content, + CreateTime: detail.CreateTime.Format("2006-01-02 15:04:05"), + Type: detail.Type, + ID: detail.ID, + } + res = append(res, item) + } + ReturnSuccess(c, 1, "获取对话内容成功", res) +} + +func (d DialogController) SaveDialogDetails(c *gin.Context) { + var req SaveDialogRequest + err := c.ShouldBindJSON(&req) + if err != nil { + ReturnError(c, 0, "参数错误") + return + } + createTime, _ := time.Parse("2006-01-02 15:04:05", req.CreateTime) + dialogDetail := &models.DialogDetail{ + UserID: c.GetInt64("user_id"), + Type: req.Type, + Content: req.Content, + CreateTime: createTime, + DialogID: req.DialogID, + } + err = dao.SaveDialogDetails(dialogDetail) + if err != nil { + ReturnError(c, 0, "保存对话内容失败") + return + } + ReturnSuccess(c, 1, "保存对话内容成功", nil) +} diff --git a/hxywd666/controller/post.go b/hxywd666/controller/post.go new file mode 100644 index 0000000..d24708b --- /dev/null +++ b/hxywd666/controller/post.go @@ -0,0 +1,184 @@ +package controller + +import ( + "QASystem/dao" + "QASystem/models" + "github.com/gin-gonic/gin" + "strconv" + "time" +) + +type PostController struct{} + +type CreatePostRequest struct { + Title string `json:"title"` + Content string `json:"content"` +} + +type GetPostResponse struct { + Title string `json:"title"` + Content string `json:"content"` + CreateTime string `json:"createTime"` + UpdateTime string `json:"updateTime"` + Likes int64 `json:"likes"` + Comments int64 `json:"comments"` + Avatar string `json:"avatar"` + Name string `json:"name"` +} + +type UpdatePostRequest struct { + Title string `json:"title"` + Content string `json:"content"` + PostId int64 `json:"id"` +} + +type LikePostRequest struct { + PostId int64 `json:"id"` + IsLiked bool `json:"isLike"` +} + +type PagePostRequest struct { + Page int `json:"page"` + PageSize int `json:"pageSize"` +} + +func (p PostController) CreatePost(c *gin.Context) { + var req CreatePostRequest + err := c.ShouldBindJSON(&req) + if err != nil { + ReturnError(c, 0, "参数错误") + return + } + post := &models.Post{ + Title: req.Title, + Content: req.Content, + UserID: c.GetInt64("user_id"), + CreateTime: time.Now(), + UpdateTime: time.Now(), + Views: 0, + Likes: 0, + } + err = dao.CreatePost(post) + if err != nil { + ReturnError(c, 0, "发布失败") + return + } + ReturnSuccess(c, 1, "发布成功", nil) +} + +func (p PostController) DeletePost(c *gin.Context) { + postId, err := strconv.ParseInt(c.Param("id"), 10, 64) + if err != nil { + ReturnError(c, 0, "参数错误") + return + } + err = dao.DeletePost(postId) + if err != nil { + ReturnError(c, 0, "删除失败") + return + } + ReturnSuccess(c, 1, "删除成功", nil) +} + +func (p PostController) GetPost(c *gin.Context) { + postId, err := strconv.ParseInt(c.Param("id"), 10, 64) + if err != nil { + ReturnError(c, 0, "参数错误") + return + } + post, err := dao.GetPostByID(postId) + if err != nil { + ReturnError(c, 0, "获取帖子失败") + return + } + if post == nil { + ReturnError(c, 0, "获取帖子失败") + return + } + postUser, err := dao.GetUserByID(post.UserID) + if postUser == nil { + ReturnError(c, 0, "获取用户信息失败") + return + } + comments, err := dao.CountCommentsByPostID(postId) + if err != nil { + ReturnError(c, 0, "获取评论数量失败") + return + } + res := &GetPostResponse{ + Title: post.Title, + Content: post.Content, + CreateTime: post.CreateTime.Format("2006-01-02 15:04:05"), + UpdateTime: post.UpdateTime.Format("2006-01-02 15:04:05"), + Likes: post.Likes, + Avatar: postUser.Avatar, + Name: postUser.Name, + Comments: comments, + } + ReturnSuccess(c, 1, "获取帖子成功", res) +} + +func (p PostController) UpdatePost(c *gin.Context) { + var req UpdatePostRequest + err := c.ShouldBindJSON(&req) + if err != nil { + ReturnError(c, 0, "参数错误") + return + } + post := &models.Post{ + Title: req.Title, + Content: req.Content, + UpdateTime: time.Now(), + ID: req.PostId, + } + err = dao.UpdatePost(post) + if err != nil { + ReturnError(c, 0, "更新失败") + return + } + ReturnSuccess(c, 1, "更新成功", nil) +} + +func (p PostController) ViewPost(c *gin.Context) { + postId, err := strconv.ParseInt(c.Param("id"), 10, 64) + if err != nil { + ReturnError(c, 0, "参数错误") + return + } + err = dao.ViewPost(postId) + if err != nil { + ReturnError(c, 0, "浏览失败") + return + } + ReturnSuccess(c, 1, "浏览成功", nil) +} + +func (p PostController) LikePost(c *gin.Context) { + var req LikePostRequest + err := c.ShouldBindJSON(&req) + if err != nil { + ReturnError(c, 0, "参数错误") + return + } + err = dao.LikePost(req.PostId, req.IsLiked) + if err != nil { + ReturnError(c, 0, "服务端异常") + return + } + ReturnSuccess(c, 1, "服务端异常", nil) +} + +func (p PostController) PagePost(c *gin.Context) { + var req PagePostRequest + err := c.ShouldBindJSON(&req) + if err != nil { + ReturnError(c, 0, "参数错误") + return + } + posts, err := dao.PagePost(req.Page, req.PageSize) + if err != nil { + ReturnError(c, 0, "获取帖子失败") + return + } + ReturnSuccess(c, 1, "获取帖子成功", posts) +} diff --git a/hxywd666/controller/user.go b/hxywd666/controller/user.go new file mode 100644 index 0000000..afb01cb --- /dev/null +++ b/hxywd666/controller/user.go @@ -0,0 +1,244 @@ +package controller + +import ( + "QASystem/dao" + "QASystem/models" + "QASystem/utils" + "encoding/base64" + "fmt" + "github.com/gin-gonic/gin" + "github.com/google/uuid" + "strconv" + "strings" + "time" +) + +type LoginRequest struct { + Username string `json:"username"` + Password string `json:"password"` +} + +type LoginResponse struct { + Token string `json:"token"` + ID int64 `json:"id"` + Username string `json:"username"` + Name string `json:"name"` +} + +type RegisterRequest struct { + Username string `json:"username"` + Password string `json:"password"` +} + +type ResetPasswordRequest struct { + Username string `json:"username"` + NewPassword string `json:"newPassword"` +} + +type UserProfileResponse struct { + Name string + Phone string + Email string + Avatar string + RegisterTime time.Time +} + +type UpdateUserProfileRequest struct { + Avatar string + Name string + Phone string + Email string + ID int64 +} + +type UserController struct{} + +func (u UserController) Login(c *gin.Context) { + var req LoginRequest + err := c.ShouldBindJSON(&req) + if err != nil { + ReturnError(c, 0, "参数错误") + return + } + user, isGetUsername := dao.GetUserByUsername(req.Username) + fmt.Println(user) + if isGetUsername != nil { + ReturnError(c, 0, "服务端错误") + return + } + if user == nil { + ReturnError(c, 0, "用户不存在") + return + } + if user.Password != req.Password { + ReturnError(c, 0, "密码错误") + return + } + claims := map[string]interface{}{ + "user_id": user.ID, + } + token, isTokenCreated := utils.CreateJWT("QASystem", 60*time.Minute, claims) + if isTokenCreated != nil { + ReturnError(c, 0, "登录失败") + return + } + loginResponse := LoginResponse{ + Token: token, + ID: user.ID, + Username: user.Username, + Name: user.Name, + } + ReturnSuccess(c, 0, "登录成功", loginResponse) +} + +func (u UserController) Register(c *gin.Context) { + var req RegisterRequest + err := c.ShouldBindJSON(&req) + if err != nil { + ReturnError(c, 0, "参数错误") + return + } + user, isGetUsername := dao.GetUserByUsername(req.Username) + if isGetUsername != nil { + ReturnError(c, 0, "服务端错误") + return + } + if user != nil { + ReturnError(c, 0, "用户已存在") + return + } + user = &models.User{ + Username: req.Username, + Password: req.Password, + Name: req.Username, + Avatar: "https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png", + Role: 0, + } + isCreated := dao.CreateNewUser(user) + if isCreated != nil { + ReturnError(c, 0, "注册失败,请稍后再试") + return + } + bot := &models.Bot{ + Name: "星火大模型", + Avatar: "https://my-bilibili-project.oss-cn-hangzhou.aliyuncs.com/spark_logo.png", + UserId: c.GetInt64("user_id"), + } + isBotCreated := dao.CreateNewBot(bot) + if isBotCreated != nil { + ReturnError(c, 0, "注册失败,请稍后再试") + return + } + ReturnSuccess(c, 1, "注册成功", nil) +} + +func (u UserController) ResetPassword(c *gin.Context) { + var req ResetPasswordRequest + err := c.ShouldBindJSON(&req) + if err != nil { + ReturnError(c, 0, "参数错误") + return + } + user, isGetUser := dao.GetUserByUsername(req.Username) + if isGetUser != nil { + ReturnError(c, 0, "服务端错误") + return + } + if user == nil { + ReturnError(c, 0, "用户不存在") + return + } + user.Password = req.NewPassword + isUpdated := dao.UpdateUser(user) + if isUpdated != nil { + ReturnError(c, 0, "重置密码失败") + return + } + ReturnSuccess(c, 1, "重置密码成功", nil) +} + +func (u UserController) GetUserProfile(c *gin.Context) { + userID, err := strconv.ParseInt(c.Param("id"), 10, 64) + if err != nil { + ReturnError(c, 0, "参数错误") + return + } + user, isGetUser := dao.GetUserByID(userID) + if isGetUser != nil { + ReturnError(c, 0, "获取用户信息失败") + return + } + if user == nil { + ReturnError(c, 0, "获取用户信息失败") + return + } + userProfile := UserProfileResponse{ + Name: user.Username, + Phone: user.Phone, + Email: user.Email, + Avatar: user.Avatar, + RegisterTime: user.RegisterTime, + } + ReturnSuccess(c, 1, "获取用户信息成功", userProfile) +} + +func (u UserController) UpdateUserProfile(c *gin.Context) { + var req UpdateUserProfileRequest + err := c.ShouldBindJSON(&req) + if err != nil { + ReturnError(c, 0, "服务端异常") + return + } + avatar := req.Avatar + if !utils.ValidatorURL(avatar) { + fileExtension := utils.GetImageExtensionFromBase64(avatar) + if fileExtension == "" { + ReturnError(c, 0, "头像格式错误") + return + } + fileName, err := uuid.NewRandom() + if err != nil { + ReturnError(c, 0, "图片上传失败") + return + } + file := fileName.String() + fileExtension + base64Avatar := avatar[strings.Index(avatar, ",")+1:] + imgBytes, err := base64.StdEncoding.DecodeString(base64Avatar) + if err != nil { + ReturnError(c, 0, "图片上传失败") + return + } + url := utils.UploadFile(imgBytes, file) + if url == "" { + ReturnError(c, 0, "图片上传失败") + return + } + user := &models.User{ + ID: req.ID, + Avatar: url, + Name: req.Name, + Phone: req.Phone, + Email: req.Email, + } + isUpdate := dao.UpdateUser(user) + if isUpdate != nil { + ReturnError(c, 0, "更新用户信息失败") + return + } + ReturnSuccess(c, 1, "更新用户信息成功", nil) + } + user := &models.User{ + ID: req.ID, + Avatar: avatar, + Name: req.Name, + Phone: req.Phone, + Email: req.Email, + } + isUpdate := dao.UpdateUser(user) + fmt.Println(isUpdate) + if isUpdate != nil { + ReturnError(c, 0, "更新用户信息失败") + return + } + ReturnSuccess(c, 1, "更新用户信息成功", nil) +} diff --git a/hxywd666/dao/bot.go b/hxywd666/dao/bot.go new file mode 100644 index 0000000..bcf241d --- /dev/null +++ b/hxywd666/dao/bot.go @@ -0,0 +1,16 @@ +package dao + +import "QASystem/models" + +func CreateNewBot(bot *models.Bot) error { + return DB.Create(bot).Error +} + +func GetBotByID(id int64) (*models.Bot, error) { + bot := &models.Bot{} + return bot, DB.Where("id = ?", id).First(bot).Error +} + +func UpdateBotProfile(bot *models.Bot) error { + return DB.Where("user_id", bot.UserId).Save(bot).Error +} diff --git a/hxywd666/dao/comment.go b/hxywd666/dao/comment.go new file mode 100644 index 0000000..d2a02f4 --- /dev/null +++ b/hxywd666/dao/comment.go @@ -0,0 +1,25 @@ +package dao + +import "QASystem/models" + +func CountCommentsByPostID(postID int64) (int64, error) { + var count int64 + return count, DB.Where("post_id=?", postID).Find(&models.Comment{}).Count(&count).Error +} + +func CreateComment(comment *models.Comment) error { + return DB.Create(&comment).Error +} + +func DeleteComment(commentID int64) error { + return DB.Where("id = ?", commentID).Delete(&models.Comment{}).Error +} + +func GetComment(postID int64, page int, pageSize int, orderBy int) ([]*models.Comment, error) { + var comments []*models.Comment + if orderBy == 1 { + return comments, DB.Where("post_id = ?", postID).Offset((page - 1) * pageSize).Limit(pageSize).Order("create_time desc").Find(&comments).Error + } else { + return comments, DB.Where("post_id = ?", postID).Offset((page - 1) * pageSize).Limit(pageSize).Order("likes desc").Find(&comments).Error + } +} diff --git a/hxywd666/dao/database.go b/hxywd666/dao/database.go new file mode 100644 index 0000000..631c51a --- /dev/null +++ b/hxywd666/dao/database.go @@ -0,0 +1,18 @@ +package dao + +import ( + "gorm.io/driver/mysql" + "gorm.io/gorm" +) + +var DB *gorm.DB + +func InitDB() error { + dsn := "root:1234@tcp(localhost:3306)/sparkchat?charset=utf8mb4&parseTime=True&loc=Local" + db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{}) + if err != nil { + return err + } + DB = db + return nil +} diff --git a/hxywd666/dao/dialog.go b/hxywd666/dao/dialog.go new file mode 100644 index 0000000..3050971 --- /dev/null +++ b/hxywd666/dao/dialog.go @@ -0,0 +1,45 @@ +package dao + +import "QASystem/models" + +func CreateDialog(dialog *models.Dialog) error { + return DB.Create(dialog).Error +} + +func DeleteDialog(dialogID int64) error { + return DB.Delete(&models.Dialog{}, dialogID).Error +} + +func DeleteDialogDetail(dialogID int64) error { + return DB.Delete(&models.DialogDetail{}, "dialog_id = ?", dialogID).Error +} + +func DeleteOneDialogDetail(dialogDetailID int64) error { + return DB.Delete(&models.DialogDetail{}, "id = ?", dialogDetailID).Error +} + +func EditDialogName(dialogID int64, newName string) error { + return DB.Model(&models.Dialog{}).Where("id = ?", dialogID).Update("name", newName).Error +} + +func GetDialogList(userId int64) ([]models.Dialog, error) { + var dialogs []models.Dialog + err := DB.Where("user_id = ?", userId).Find(&dialogs).Error + return dialogs, err +} + +func GetOneDialog(dialogID int64) (*models.Dialog, error) { + var dialog models.Dialog + err := DB.Where("id = ?", dialogID).First(&dialog).Error + return &dialog, err +} + +func GetDialogDetails(dialogID int64) ([]models.DialogDetail, error) { + var dialogDetails []models.DialogDetail + err := DB.Where("dialog_id = ?", dialogID).Find(&dialogDetails).Error + return dialogDetails, err +} + +func SaveDialogDetails(dialogDetail *models.DialogDetail) error { + return DB.Save(&dialogDetail).Error +} diff --git a/hxywd666/dao/post.go b/hxywd666/dao/post.go new file mode 100644 index 0000000..d534e42 --- /dev/null +++ b/hxywd666/dao/post.go @@ -0,0 +1,40 @@ +package dao + +import ( + "QASystem/models" + "gorm.io/gorm" +) + +func CreatePost(post *models.Post) error { + return DB.Create(post).Error +} + +func DeletePost(postId int64) error { + return DB.Where("id = ?", postId).Delete(&models.Post{}).Error +} + +func GetPostByID(postId int64) (*models.Post, error) { + post := &models.Post{} + return post, DB.Where("id = ?", postId).First(post).Error +} + +func UpdatePost(post *models.Post) error { + return DB.Model(&models.Post{}).Where("id = ?", post.ID).Updates(post).Error +} + +func ViewPost(postId int64) error { + return DB.Model(&models.Post{}).Where("id = ?", postId).UpdateColumn("views", gorm.Expr("views + ?", 1)).Error +} + +func LikePost(postId int64, isLiked bool) error { + if isLiked { + return DB.Model(&models.Post{}).Where("id = ?", postId).UpdateColumn("likes", gorm.Expr("likes - ?", 1)).Error + } else { + return DB.Model(&models.Post{}).Where("id = ?", postId).UpdateColumn("likes", gorm.Expr("likes + ?", 1)).Error + } +} + +func PagePost(pageNum int, pageSize int) ([]*models.Post, error) { + var posts []*models.Post + return posts, DB.Limit(pageSize).Offset((pageNum - 1) * pageSize).Find(&posts).Error +} diff --git a/hxywd666/dao/user.go b/hxywd666/dao/user.go new file mode 100644 index 0000000..29d7604 --- /dev/null +++ b/hxywd666/dao/user.go @@ -0,0 +1,35 @@ +package dao + +import ( + "QASystem/models" + "fmt" +) + +func GetUserByUsername(username string) (*models.User, error) { + var user models.User + err := DB.Where("username = ?", username).First(&user).Error + if err != nil { + return nil, err + } + return &user, nil +} + +func GetUserByID(id int64) (*models.User, error) { + var user models.User + err := DB.Where("id = ?", id).First(&user).Error + if err != nil { + return nil, err + } + return &user, nil +} + +func CreateNewUser(user *models.User) error { + err := DB.Create(user).Error + return err +} + +func UpdateUser(user *models.User) error { + fmt.Println(user) + err := DB.Model(&models.User{}).Where("id = ?", user.ID).UpdateColumns(user).Error + return err +} diff --git a/hxywd666/go.mod b/hxywd666/go.mod new file mode 100644 index 0000000..db781a9 --- /dev/null +++ b/hxywd666/go.mod @@ -0,0 +1,43 @@ +module QASystem + +go 1.22 + +require ( + filippo.io/edwards25519 v1.1.0 // indirect + github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible // indirect + github.com/bytedance/sonic v1.12.3 // indirect + github.com/bytedance/sonic/loader v0.2.0 // indirect + github.com/cloudwego/base64x v0.1.4 // indirect + github.com/cloudwego/iasm v0.2.0 // indirect + github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect + github.com/gabriel-vasile/mimetype v1.4.5 // indirect + github.com/gin-contrib/sse v0.1.0 // indirect + github.com/gin-gonic/gin v1.10.0 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/go-playground/validator/v10 v10.22.1 // indirect + github.com/go-sql-driver/mysql v1.8.1 // indirect + github.com/goccy/go-json v0.10.3 // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/jinzhu/inflection v1.0.0 // indirect + github.com/jinzhu/now v1.1.5 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/cpuid/v2 v2.2.8 // indirect + github.com/leodido/go-urn v1.4.0 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/pelletier/go-toml/v2 v2.2.3 // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/ugorji/go/codec v1.2.12 // indirect + golang.org/x/arch v0.10.0 // indirect + golang.org/x/crypto v0.27.0 // indirect + golang.org/x/net v0.29.0 // indirect + golang.org/x/sys v0.25.0 // indirect + golang.org/x/text v0.18.0 // indirect + golang.org/x/time v0.6.0 // indirect + google.golang.org/protobuf v1.34.2 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + gorm.io/driver/mysql v1.5.7 // indirect + gorm.io/gorm v1.25.12 // indirect +) diff --git a/hxywd666/go.sum b/hxywd666/go.sum new file mode 100644 index 0000000..ee1c237 --- /dev/null +++ b/hxywd666/go.sum @@ -0,0 +1,99 @@ +filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= +filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible h1:8psS8a+wKfiLt1iVDX79F7Y6wUM49Lcha2FMXt4UM8g= +github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= +github.com/bytedance/sonic v1.12.3 h1:W2MGa7RCU1QTeYRTPE3+88mVC0yXmsRQRChiyVocVjU= +github.com/bytedance/sonic v1.12.3/go.mod h1:B8Gt/XvtZ3Fqj+iSKMypzymZxw/FVwgIGKzMzT9r/rk= +github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= +github.com/bytedance/sonic/loader v0.2.0 h1:zNprn+lsIP06C/IqCHs3gPQIvnvpKbbxyXQP1iU4kWM= +github.com/bytedance/sonic/loader v0.2.0/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= +github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y= +github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= +github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= +github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/gabriel-vasile/mimetype v1.4.5 h1:J7wGKdGu33ocBOhGy0z653k/lFKLFDPJMG8Gql0kxn4= +github.com/gabriel-vasile/mimetype v1.4.5/go.mod h1:ibHel+/kbxn9x2407k1izTA1S81ku1z/DlgOW2QE0M4= +github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= +github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= +github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.22.1 h1:40JcKH+bBNGFczGuoBYgX4I6m/i27HYW8P9FDk5PbgA= +github.com/go-playground/validator/v10 v10.22.1/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= +github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= +github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= +github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= +github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA= +github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +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/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= +github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= +github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= +github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM= +github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= +github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= +github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= +github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= +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/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= +github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= +github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= +github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= +github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +golang.org/x/arch v0.10.0 h1:S3huipmSclq3PJMNe76NGwkBR504WFkQ5dhzWzP8ZW8= +golang.org/x/arch v0.10.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= +golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= +golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= +golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= +golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= +golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= +golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gorm.io/driver/mysql v1.5.7 h1:MndhOPYOfEp2rHKgkZIhJ16eVUIRf2HmzgoPmh7FCWo= +gorm.io/driver/mysql v1.5.7/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM= +gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= +gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8= +gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ= +nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/hxywd666/main/main.go b/hxywd666/main/main.go new file mode 100644 index 0000000..761dec4 --- /dev/null +++ b/hxywd666/main/main.go @@ -0,0 +1,20 @@ +package main + +import ( + "QASystem/dao" + "QASystem/router" + "fmt" +) + +func main() { + isConnect := dao.InitDB() + if isConnect != nil { + fmt.Println("数据库连接失败") + } + + r := router.Router() + err := r.Run(":8080") + if err != nil { + panic(err) + } +} diff --git a/hxywd666/middleware/jwt_middleware.go b/hxywd666/middleware/jwt_middleware.go new file mode 100644 index 0000000..c98acaf --- /dev/null +++ b/hxywd666/middleware/jwt_middleware.go @@ -0,0 +1,25 @@ +package middleware + +import ( + "QASystem/utils" + "github.com/gin-gonic/gin" + "net/http" +) + +func JwtTokenUserInterceptor() gin.HandlerFunc { + return func(c *gin.Context) { + if c.Request.URL.Path == "/user/login" || c.Request.URL.Path == "/user/reset" || c.Request.URL.Path == "/user/register" { + c.Next() + return + } + token := c.Request.Header.Get("Authorization") + claims, err := utils.ParseJWT("QASystem", token) + if err != nil { + c.JSON(http.StatusUnauthorized, gin.H{"msg": "未登录"}) + c.Abort() + } + userId := claims["user_id"] + c.Set("user_id", int64(userId.(float64))) + c.Next() + } +} diff --git a/hxywd666/models/bot.go b/hxywd666/models/bot.go new file mode 100644 index 0000000..40d2f9c --- /dev/null +++ b/hxywd666/models/bot.go @@ -0,0 +1,8 @@ +package models + +type Bot struct { + ID int64 `gorm:"primary_key"` + Name string + UserId int64 + Avatar string +} diff --git a/hxywd666/models/comment.go b/hxywd666/models/comment.go new file mode 100644 index 0000000..85aff42 --- /dev/null +++ b/hxywd666/models/comment.go @@ -0,0 +1,12 @@ +package models + +import "time" + +type Comment struct { + ID int64 `gorm:"id"` + Content string `gorm:"content"` + UserID int64 `gorm:"user_id"` + CreateTime time.Time `gorm:"create_time"` + PostID int64 `gorm:"post_id"` + Likes int64 `gorm:"likes"` +} diff --git a/hxywd666/models/dialog.go b/hxywd666/models/dialog.go new file mode 100644 index 0000000..5041e92 --- /dev/null +++ b/hxywd666/models/dialog.go @@ -0,0 +1,12 @@ +package models + +import ( + "time" +) + +type Dialog struct { + ID int64 + Name string + UserID int64 + CreateTime time.Time +} diff --git a/hxywd666/models/dialog_detail.go b/hxywd666/models/dialog_detail.go new file mode 100644 index 0000000..f2a435a --- /dev/null +++ b/hxywd666/models/dialog_detail.go @@ -0,0 +1,14 @@ +package models + +import ( + "time" +) + +type DialogDetail struct { + ID int64 + UserID int64 + Type int + Content string + CreateTime time.Time + DialogID int64 +} diff --git a/hxywd666/models/post.go b/hxywd666/models/post.go new file mode 100644 index 0000000..e5c936c --- /dev/null +++ b/hxywd666/models/post.go @@ -0,0 +1,14 @@ +package models + +import "time" + +type Post struct { + ID int64 `gorm:"id"` + Title string `gorm:"title"` + Content string `gorm:"content"` + UserID int64 `gorm:"user_id"` + CreateTime time.Time `gorm:"create_time"` + UpdateTime time.Time `gorm:"update_time"` + Views int64 `gorm:"views"` + Likes int64 `gorm:"likes"` +} diff --git a/hxywd666/models/user.go b/hxywd666/models/user.go new file mode 100644 index 0000000..b6c87de --- /dev/null +++ b/hxywd666/models/user.go @@ -0,0 +1,17 @@ +package models + +import ( + "time" +) + +type User struct { + ID int64 `gorm:"primary_key"` + Username string + Password string + Name string + Role int + Phone string + Email string + RegisterTime time.Time + Avatar string +} diff --git a/hxywd666/router/route.go b/hxywd666/router/route.go new file mode 100644 index 0000000..114bbb8 --- /dev/null +++ b/hxywd666/router/route.go @@ -0,0 +1,65 @@ +package router + +import ( + "QASystem/controller" + "QASystem/middleware" + "github.com/gin-gonic/gin" +) + +func Router() *gin.Engine { + r := gin.Default() + + r.Use(middleware.JwtTokenUserInterceptor()) + + user := r.Group("user") + { + user.POST("/login", controller.UserController{}.Login) + user.POST("/register", controller.UserController{}.Register) + user.POST("/reset", controller.UserController{}.ResetPassword) + user.GET("/profile/:id", controller.UserController{}.GetUserProfile) + user.POST("/profile", controller.UserController{}.UpdateUserProfile) + } + + bot := r.Group("bot") + { + bot.GET("/profile/:id", controller.BotController{}.GetBotProfile) + bot.POST("/profile", controller.BotController{}.UpdateBotProfile) + } + + dialog := r.Group("dialog") + { + dialog.POST("/add", controller.DialogController{}.CreateDialog) + dialog.DELETE("/delete/:id", controller.DialogController{}.DeleteDialog) + dialog.DELETE("/deleteone/:id", controller.DialogController{}.DeleteOneDialogDetail) + dialog.POST("/edit", controller.DialogController{}.EditDialogName) + dialog.GET("/list", controller.DialogController{}.GetDialogList) + dialog.GET("/one/:id", controller.DialogController{}.GetOneDialog) + dialog.GET("/details/:id", controller.DialogController{}.GetDialogDetails) + dialog.POST("/details", controller.DialogController{}.SaveDialogDetails) + } + + chat := r.Group("chat") + { + chat.POST("/", controller.ChatController{}.ChatWithSpark) + } + + post := r.Group("post") + { + post.PUT("/", controller.PostController{}.CreatePost) + post.DELETE("/:id", controller.PostController{}.DeletePost) + post.GET("/:id", controller.PostController{}.GetPost) + post.POST("/update", controller.PostController{}.UpdatePost) + post.POST("/view/:id", controller.PostController{}.ViewPost) + post.POST("/like", controller.PostController{}.LikePost) + post.GET("/list", controller.PostController{}.PagePost) + } + + comment := r.Group("comment") + { + comment.PUT("/", controller.CommentController{}.CreateComment) + comment.DELETE("/:id", controller.CommentController{}.DeleteComment) + comment.GET("/", controller.CommentController{}.GetComment) + } + + return r +} diff --git a/hxywd666/utils/alioss.go b/hxywd666/utils/alioss.go new file mode 100644 index 0000000..044102e --- /dev/null +++ b/hxywd666/utils/alioss.go @@ -0,0 +1,26 @@ +package utils + +import ( + "bytes" + "github.com/aliyun/aliyun-oss-go-sdk/oss" + "log" +) + +func UploadFile(fileBytes []byte, objectName string) string { + client, err := oss.New("", "", "") + if err != nil { + log.Printf("创建 OSS 客户端失败: %v", err) + return "" + } + bucket, err := client.Bucket("my-bilibili-project") + if err != nil { + log.Printf("获取存储空间失败: %v", err) + return "" + } + err = bucket.PutObject(objectName, bytes.NewReader(fileBytes)) + if err != nil { + log.Printf("上传文件失败: %v", err) + return "" + } + return "https://my-bilibili-project.oss-cn-hangzhou.aliyuncs.com/" + objectName +} diff --git a/hxywd666/utils/jwt.go b/hxywd666/utils/jwt.go new file mode 100644 index 0000000..03c3ef6 --- /dev/null +++ b/hxywd666/utils/jwt.go @@ -0,0 +1,37 @@ +package utils + +import ( + "time" + + "github.com/dgrijalva/jwt-go" +) + +type Claims struct { + jwt.StandardClaims + CustomClaims map[string]interface{} +} + +func CreateJWT(secretKey string, ttl time.Duration, claims map[string]interface{}) (string, error) { + expirationTime := time.Now().Add(ttl) + jwtClaims := jwt.MapClaims{ + "exp": expirationTime.Unix(), + } + for key, value := range claims { + jwtClaims[key] = value + } + token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwtClaims) + return token.SignedString([]byte(secretKey)) +} + +func ParseJWT(secretKey, tokenString string) (jwt.MapClaims, error) { + token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) { + return []byte(secretKey), nil + }) + if err != nil { + return nil, err + } + if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid { + return claims, nil + } + return nil, err +} diff --git a/hxywd666/utils/spark.go b/hxywd666/utils/spark.go new file mode 100644 index 0000000..022840f --- /dev/null +++ b/hxywd666/utils/spark.go @@ -0,0 +1,91 @@ +package utils + +import ( + "bytes" + "encoding/json" + "io" + "net/http" +) + +type SparkRequest struct { + Model string `json:"model"` + Messages []struct { + Role string `json:"role"` + Content string `json:"content"` + } `json:"messages"` + Stream bool `json:"stream,omitempty"` +} + +type SparkResponse struct { + Choices []struct { + Message struct { + Content string `json:"content"` + } `json:"message"` + Delta struct { + Content string `json:"content"` + } `json:"delta"` + } `json:"choices"` +} + +func SendRequest(content, model string) (string, error) { + apiPassword := "" + apiUrl := "https://spark-api-open.xf-yun.com/v1" + + requestBody := SparkRequest{ + Model: model, + Messages: []struct { + Role string `json:"role"` + Content string `json:"content"` + }{ + { + Role: "user", + Content: content, + }, + }, + } + + jsonData, err := json.Marshal(requestBody) + if err != nil { + return "", err + } + + req, err := http.NewRequest("POST", apiUrl+"/chat/completions", bytes.NewBuffer(jsonData)) + if err != nil { + return "", err + } + + req.Header.Set("Authorization", "Bearer "+apiPassword) + req.Header.Set("Content-Type", "application/json") + + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + return "", err + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return "", err + } + + if resp.StatusCode != http.StatusOK { + return "", err + } + + var response SparkResponse + err = json.Unmarshal(body, &response) + if err != nil { + return "", err + } + + if len(response.Choices) > 0 { + if response.Choices[0].Message.Content != "" { + return response.Choices[0].Message.Content, nil + } else { + return response.Choices[0].Delta.Content, nil + } + } else { + return "", err + } +} diff --git a/hxywd666/utils/verify.go b/hxywd666/utils/verify.go new file mode 100644 index 0000000..27dc61e --- /dev/null +++ b/hxywd666/utils/verify.go @@ -0,0 +1,41 @@ +package utils + +import ( + "net/url" + "strings" +) + +func ValidatorURL(str string) bool { + str = strings.TrimSpace(str) + if str == "" { + return false + } + u, err := url.Parse(str) + if err != nil { + return false + } + if u.Scheme == "" || u.Host == "" { + return false + } + return true +} + +func GetImageExtensionFromBase64(base64Str string) string { + // 提取 Base64 编码中的数据部分 + dataPart := base64Str[strings.IndexByte(base64Str, ',')+1:] + + // 常见的图片 Base64 数据开头 + imagePrefixes := map[string]string{ + "data:image/jpeg;base64": "jpg", + "data:image/png;base64": "png", + "data:image/gif;base64": "gif", + } + + for prefix, ext := range imagePrefixes { + if strings.HasPrefix(dataPart, prefix) { + return ext + } + } + + return "" +}