Compare commits

..

No commits in common. "e3e2a0c064cb9767ae87f173bb50c417f0d6afe7" and "60b76e5377c0231511fb584adb6d7b7d7079ba80" have entirely different histories.

14 changed files with 47 additions and 177 deletions

View File

@ -1,33 +0,0 @@
# 第一阶段使用最新Go版本构建
FROM docker.1ms.run/golang:1.24 AS builder
WORKDIR /app
ENV GOPROXY=https://goproxy.cn,direct
# 复制go.mod和go.sum以缓存依赖
COPY go.mod go.sum ./
RUN go mod download
# 复制源代码并构建
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags="-s -w" -o StuAcaWorksAI .
# 第二阶段:生产环境(最小化镜像)
FROM scratch
# 复制配置文件
COPY --from=builder /app/saw-ai.conf /home/saw/saw-ai.conf
# 复制二进制文件
COPY --from=builder /app/StuAcaWorksAI /home/saw/StuAcaWorksAI
# 设置工作目录
WORKDIR /home/saw
# 暴露端口
EXPOSE 8084
# 运行应用
CMD ["./StuAcaWorksAI"]

View File

@ -1,11 +0,0 @@
version: '3.8'
services:
app:
image: saw-img:latest
container_name: saw-container
ports:
- "8088:8083"
volumes:
- /etc/saw-app:/etc/saw-app
- /data/file:/data/file

View File

@ -21,7 +21,6 @@ func SetUpFileGroup(router *gin.Engine) {
fileGroup.POST("/file_delete", DeleteUserFile)
fileGroup.POST("/file_update", UpdateUserFile)
fileGroup.POST("/find_file_content", FindFileContent)
fileGroup.POST("/update_file_content", UpdateFileContent)
fileGroup.POST("/create_file_content", CreateFileContent)
fileGroup.POST("/get_file_will_convert_content", GetFileWillConvertContent) //需要将文件转为文件内容的文件列表接口
fileGroup.POST("/convert_msg_to_file", ConvertMsgToFile) //将消息转为文件
@ -278,7 +277,7 @@ func UploadFileV2(c *gin.Context) {
//查看用户上传的所有文件大小是否超过限制
userFileSpace := dao.GetUserFileSpace(id1)
user := service.GetUserByIDFromUserCenter(id1)
user := service.GetUserByIDWithCache(id1)
if userFileSpace.TotalSize > proto.UserMaxUploadSize && user.Role != "admin" {
c.JSON(http.StatusOK, gin.H{"error": "user file space is full", "code": proto.NoUploadPermissions, "message": "failed"})
return
@ -376,29 +375,7 @@ func CreateFileContent(c *gin.Context) {
fileContentID, err2 := service.CreateFileContent(userId, req.FileID, req.FileContent)
if err2 != nil {
resp.Code = proto.ParameterError
resp.Message = "create file content failed:" + err2.Error()
} else {
resp.Code = proto.SuccessCode
resp.Message = "success"
resp.Data = fileContentID
}
} else {
resp.Code = proto.ParameterError
resp.Message = "upload form parameter decode error:" + err.Error()
}
c.JSON(http.StatusOK, resp)
}
func UpdateFileContent(c *gin.Context) {
id, _ := c.Get("id")
userId := int(id.(float64))
var req proto.FileContentReq
var resp proto.FileContentResp
if err := c.ShouldBind(&req); err == nil {
fileContentID, err2 := service.UpdateFileContent(userId, req.FileID, req.FileContent)
if err2 != nil {
resp.Code = proto.ParameterError
resp.Message = "update file content failed:" + err2.Error()
resp.Message = "find file content failed:" + err2.Error()
} else {
resp.Code = proto.SuccessCode
resp.Message = "success"

View File

@ -438,7 +438,7 @@ func checkAndSetModelTemperatureParam(modelParam *proto.ModelParam, data *proto.
func SendMessageForeignAI(c *gin.Context) {
id, _ := c.Get("user_id")
userID := id.(int)
user := service.GetUserByIDFromUserCenter(userID)
user := service.GetUserByIDWithCache(userID)
var resp proto.GenerateResp
var req proto.SendMessageForeignAIRRequest
if user.Role == "admin" {
@ -471,7 +471,7 @@ func SendMessageForeignAI(c *gin.Context) {
func ReceiveMessageForeignAI(c *gin.Context) {
id, _ := c.Get("user_id")
userID := id.(int)
user := service.GetUserByIDFromUserCenter(userID)
user := service.GetUserByIDWithCache(userID)
var resp proto.GenerateResp
var req proto.ReceiveMessageForeignAIRRequest
if user.Role == "admin" {

View File

@ -58,16 +58,14 @@ func SetUpToolGroup(router *gin.Engine) {
toolGroup.POST("/file_del", DelFile)
//服务器、设备状态接口
toolGroup.POST("/monitor", SetDeviceStatusV2)
//第三方登录所有不进行,统一认证中心
//toolGroup.POST("/qq_callback", handleQQCallback)
//toolGroup.GET("/qq_auth", GetQQAuthUrl)
//toolGroup.GET("/github_auth", GetGithubAuthUrl)
//toolGroup.GET("/get_auth_url", GetThirdPartyAuthUrl)
//toolGroup.GET("/github_callback", handleGithubCallback)
//toolGroup.GET("/gitee_callback", handleGiteeCallback)
//toolGroup.GET("/third_party_callback", handleThirdPartyCallback) //统一处理第三方登录回调
toolGroup.POST("/qq_callback", handleQQCallback)
toolGroup.GET("/qq_auth", GetQQAuthUrl)
toolGroup.GET("/github_auth", GetGithubAuthUrl)
toolGroup.GET("/get_auth_url", GetThirdPartyAuthUrl)
toolGroup.GET("/github_callback", handleGithubCallback)
toolGroup.GET("/gitee_callback", handleGiteeCallback)
toolGroup.GET("/third_party_callback", handleThirdPartyCallback) //统一处理第三方登录回调
toolGroup.POST("/loginRedirect", LoginRedirect)
toolGroup.POST("/statistic", GetUserStatistic)
//发送邮件
toolGroup.POST("/send_mail", SendMailTool)
toolGroup.POST("/dashboard", DashBoardStatistics)
@ -80,9 +78,6 @@ func SetUpToolGroup(router *gin.Engine) {
//文本转为文档接口
toolGroup.POST("/text_to_docx", HandleMessageTextToDocx)
toolGroup.GET("/get_text_docx_set", GetTextDocxSet)
//前端用户ui配置
toolGroup.GET("/get_user_ui_config", GetUserUIConfig) //获取用户ui配置
toolGroup.POST("/set_user_ui_config", SetUserUIConfig) //设置用户ui配置
}
func SetDeviceStatusV2(c *gin.Context) {
@ -975,7 +970,7 @@ func GetTextDocxSet(c *gin.Context) {
var resp proto.GenerateResp
userID, _ := c.Get("user_id")
//查看用户是否是管理员
user := service.GetUserByIDFromUserCenter(int(userID.(float64)))
user := service.GetUserByIDWithCache(int(userID.(float64)))
if user.Role != "admin" {
resp.Code = proto.PermissionDenied
resp.Message = "没有权限"

10
main.go
View File

@ -37,7 +37,7 @@ func main() {
}
r.Use(handler.CrosHandler())
r.Use(JWTAuthMiddleware()) // 使用 JWT 认证中间件
//handler.SetUpUserGroup(r) // User不进行用户信息后面统一走认证中心
handler.SetUpUserGroup(r) // User
handler.SetUpToolGroup(r) // Tool
handler.SetUpFileGroup(r) // File
handler.SetUpKnowledgeBaseGroup(r) // KnowledgeBase
@ -68,12 +68,12 @@ func init() {
//系统是linux、macos还是windows
var configPath string
if os.Getenv("OS") == "Windows_NT" {
configPath = "C:/saw/saw-ai.conf"
configPath = "E:/Code/saw-ai/saw-ai.conf"
} else if os.Getenv("OS") == "linux" {
//文件地址/home/saw-ai/saw-ai.conf
configPath = "/etc/saw-app/saw-ai.conf"
configPath = "/home/saw/saw-ai-go/saw-ai.conf"
} else {
configPath = "/etc/saw-app/saw-ai.conf"
configPath = "/home/saw/saw-ai-go/saw-ai.conf"
}
//读取配置文件
err := proto.ReadConfig(configPath)
@ -360,7 +360,7 @@ func RunGeneralCron() {
// 用户功能拦截,返回true表示拦截false表示不拦截
func UserFuncIntercept(id int, url string) bool {
//先查看是否有权限
user := service.GetUserByIDFromUserCenter(id)
user := service.GetUserByIDWithCache(id)
//如果用户有权限,则不拦截
for k, v := range proto.Per_menu_map {
if strings.Contains(url, k) {

View File

@ -138,6 +138,4 @@ type UserUIConfigInfo struct {
type UserUIFunctionConfigInfo struct {
ModelID int `json:"model_id" form:"model_id" bson:"model_id"` // 模型ID,选择的模型
SessionID int `json:"session_id" form:"session_id" bson:"session_id"` // 会话ID,上一次的会话
Temperature float32 `json:"temperature" form:"temperature" bson:"temperature"` // 温度
TopP float32 `json:"top_p" form:"top_p" bson:"top_p"` // 采样温度
}

View File

@ -81,7 +81,7 @@ func CheckUploadRequestParameters(req *proto.FileUploadReq) error {
func CreateConfigFile(req *proto.AddConfigFileReq, userId int) error {
var err error
user := GetUserByIDFromUserCenter(userId)
user := GetUserByIDWithCache(userId)
if user.ID == 0 || user.Role != "admin" {
err = fmt.Errorf("user not found or no permission")
return err
@ -126,7 +126,7 @@ func CreateConfigFile(req *proto.AddConfigFileReq, userId int) error {
func DeleteConfigFile(req *proto.ConfigFileReq, userId int) error {
var err error
user := GetUserByIDFromUserCenter(userId)
user := GetUserByIDWithCache(userId)
if user.ID == 0 || user.Role != "admin" {
err = fmt.Errorf("user not found or no permission")
return err
@ -154,7 +154,7 @@ type ConfigFileService struct {
func (c *ConfigFileService) UpdateConfigFile(req *proto.ConfigFileReq, userId int) error {
var err error
user := GetUserByIDFromUserCenter(userId)
user := GetUserByIDWithCache(userId)
if user.ID == 0 || user.Role != "admin" {
err = fmt.Errorf("user not found or no permission")
return err
@ -196,7 +196,7 @@ func (c *ConfigFileService) UpdateConfigFile(req *proto.ConfigFileReq, userId in
}
func (c *ConfigFileService) SearchOneConfigFile(req *proto.ConfigFileReq, userId int) ([]proto.SearchOneConfigFileResp, error) {
user := GetUserByIDFromUserCenter(userId)
user := GetUserByIDWithCache(userId)
if user.ID == 0 || user.Role != "admin" {
return []proto.SearchOneConfigFileResp{}, fmt.Errorf("user not found or no permission")
}
@ -214,7 +214,7 @@ func (c *ConfigFileService) SearchOneConfigFile(req *proto.ConfigFileReq, userId
}
func (c *ConfigFileService) SearchAllConfigFile(userId int) ([]dao.ConfigFile, error) {
user := GetUserByIDFromUserCenter(userId)
user := GetUserByIDWithCache(userId)
if user.ID == 0 || user.Role != "admin" {
return []dao.ConfigFile{}, fmt.Errorf("user not found or no permission")
}
@ -331,7 +331,7 @@ func FindFileContent(userID int, userReq *proto.FileContentReq) ([]dao.FileConte
}
func CreateFileContent(userID, fileID int, fileContent string) (uint, error) {
user := GetUserByIDFromUserCenter(userID)
user := GetUserByIDWithCache(userID)
if user.Role != "admin" {
return 0, errors.New("no permission")
}
@ -347,30 +347,8 @@ func CreateFileContent(userID, fileID int, fileContent string) (uint, error) {
return dao.CreateFileContent(fileID, fileContent)
}
func UpdateFileContent(userID, fileID int, fileContent string) (uint, error) {
fileAuth := dao.FindFileAuthByID(fileID)
user := GetUserByIDFromUserCenter(userID)
if fileAuth.ID == 0 {
return 0, errors.New("file auth not found")
}
if fileAuth.AuthID != userID && user.Role != "admin" {
return 0, errors.New("no permission")
}
//查找文件内容是否存在
fileContentC, err := dao.FindFileContentByFileIDAndContentID(fileID)
if err != nil {
return 0, err
}
if fileContentC.ID == 0 {
return 0, errors.New("file content not found")
}
id, err := dao.UpdateFileContentByID(fileContentC.ID, fileContent)
return id, err
}
func GetFileWillConvertContentFileList(userID int) ([]dao.File, error) {
user := GetUserByIDFromUserCenter(userID)
user := GetUserByIDWithCache(userID)
if user.Role != "admin" {
return nil, errors.New("no permission")
}

View File

@ -364,8 +364,7 @@ func SendOpenAIForeignAI(modelParam proto.ModelParam, imCtx *proto.IMParamContex
var resp proto.GenerateResp
err = json.Unmarshal(respBytes, &resp)
if err != nil {
log.Println("send openai foreign ai request:", string(reqBytes))
log.Println("send openai foreign ai response error:", string(respBytes))
log.Println("send openai foreign ai response error:", err)
return
}
if resp.Code != proto.SuccessCode {

View File

@ -310,7 +310,7 @@ func ReceiveSparkSession(userID, sessionID int, channel string, msg proto.WSMess
func CheckUserCreatePPTSessionPermission(userID int) error {
sessionCount := dao.FindUserSessionCount(userID, proto.SessionTypeUserCreatePPT)
var err error
user := GetUserByIDFromUserCenter(userID)
user := GetUserByIDWithCache(userID)
if user.Role == "admin" {
return nil
}

View File

@ -11,7 +11,7 @@ import (
// 创建模型信息
func CreateModel(userID uint, modelType, url, parameter, description string) (error, uint) {
//查看用户是否有权限创建模型
user := GetUserByIDFromUserCenter(int(userID))
user := GetUserByIDWithCache(int(userID))
if user.ID == 0 {
return errors.New("user not exist"), 0
}
@ -60,7 +60,7 @@ func FindModelByUserID(userID int) []dao.ModelResponse {
// 根据id删除模型
func DeleteModelByID(id, userID int) error {
//查看用户是否有权限删除模型
user := GetUserByIDFromUserCenter(userID)
user := GetUserByIDWithCache(userID)
model := dao.FindModelByID(id, userID)
if user.ID == 0 {
return errors.New("user not exist")
@ -79,7 +79,7 @@ func UpdateModelByID(id int, userID uint, modelType, url, parameter, description
func CreateFuncModel(userID, modelID int, name, info, function, modelIDs string) (error, uint) {
//查看用户是否有权限创建模型
user := GetUserByIDFromUserCenter(userID)
user := GetUserByIDWithCache(userID)
if user.ID == 0 {
return errors.New("user not exist"), 0
}
@ -90,7 +90,7 @@ func CreateFuncModel(userID, modelID int, name, info, function, modelIDs string)
}
func FindFuncModelByID(id, userID int) ([]dao.FunctionModel, error) {
user := GetUserByIDFromUserCenter(userID)
user := GetUserByIDWithCache(userID)
if user.ID == 0 {
return nil, errors.New("user not exist")
}
@ -102,7 +102,7 @@ func FindFuncModelByID(id, userID int) ([]dao.FunctionModel, error) {
// 根据userID查找功能模型
func FindFuncModelByUserID(userID int) ([]dao.FunctionModel, error) {
user := GetUserByIDFromUserCenter(userID)
user := GetUserByIDWithCache(userID)
if user.ID == 0 {
return nil, errors.New("user not exist")
}
@ -118,7 +118,7 @@ func FindFuncModelByUserID(userID int) ([]dao.FunctionModel, error) {
func DeleteFuncModelByID(id, userID int) error {
//查看用户是否有权限删除模型
user := GetUserByIDFromUserCenter(userID)
user := GetUserByIDWithCache(userID)
model := dao.FindFunctionModelByID(id, userID)
if user.ID == 0 {
return errors.New("user not exist")
@ -130,7 +130,7 @@ func DeleteFuncModelByID(id, userID int) error {
}
func UpdateFuncModelByID(id int, userID, modelID uint, name, info, function, modelIDs string) error {
user := GetUserByIDFromUserCenter(int(userID))
user := GetUserByIDWithCache(int(userID))
if user.ID == 0 {
return errors.New("user not exist")
}

View File

@ -61,10 +61,10 @@ func Tongyi(modelParam proto.ModelParam, imCtx *proto.IMParamContext) {
log.Println("tongyi stream err:", stream.Err())
}
//将消息存入数据库
DoSaveMessageAndToken(imCtx, answer, "tongyi", tokens, PromptTokens)
DOSaveMessageAndToken(imCtx, answer, "tongyi", tokens, PromptTokens)
}
func DoSaveMessageAndToken(imCtx *proto.IMParamContext, answer, platform string, tokens, PromptTokens int64) {
func DOSaveMessageAndToken(imCtx *proto.IMParamContext, answer, platform string, tokens, PromptTokens int64) {
msg := dao.Message{SessionID: imCtx.SessionID, FromID: imCtx.UserID, ToID: imCtx.ModelID, Msg: answer, Type: proto.ModelToUserMsgType, FunctionID: imCtx.FunctionID, Token: int(tokens), Status: proto.UserToModelMsgType}
err2, msgID := dao.CreateMessageV2(msg)
if err2 != nil {
@ -132,7 +132,7 @@ func TongyiToGeneralMassageAndSendMsgQueue(data *openai.ChatCompletionChunk, cha
var apiMsg api.GenerateResponse
apiMsg.Model = proto.ModelTypeSpark
apiMsg.Response = data.Choices[0].Delta.Content
if data.Created < 0 || data.Choices[0].FinishReason != "" { //这里由于没有返回结束标志,所以用该字段来判断
if data.Created < 0 { //这里由于没有返回结束标志,所以用该字段来判断
apiMsg.Done = true
} else {
apiMsg.Done = false

View File

@ -343,7 +343,7 @@ func HandleThirdPartyLoginStatus(state *proto.ThirdPartyLoginState, thirdPartyLo
} else {
thirdPartyUserInfo := thirdPartyUserInfoList[0]
//获取用户信息
user := GetUserByIDFromUserCenter(thirdPartyUserInfo.UserID)
user := GetUserByIDWithCache(thirdPartyUserInfo.UserID)
if user.ID == 0 {
thirdPartyLoginStatus.Status = proto.ThirdPartyUserNotBinded
log.Println("get user by id error")
@ -370,7 +370,7 @@ func HandleThirdPartyLoginStatus(state *proto.ThirdPartyLoginState, thirdPartyLo
//字符串转int
userID, _ := strconv.Atoi(userIDStr)
//根据用户ID获取用户信息
user := GetUserByIDFromUserCenter(userID)
user := GetUserByIDWithCache(userID)
if user.ID == 0 {
thirdPartyLoginStatus.Status = 4 //添加用户信息错误
log.Println("get user by id error")
@ -412,7 +412,7 @@ func HandleThirdPartyLoginStatusV2(state *proto.ThirdPartyLoginState, thirdParty
} else {
thirdPartyUserInfo := thirdPartyUserInfoList[0]
//获取用户信息
user := GetUserByIDFromUserCenter(thirdPartyUserInfo.UserID)
user := GetUserByIDWithCache(thirdPartyUserInfo.UserID)
if user.ID == 0 {
thirdPartyLoginStatus.Status = proto.ThirdPartyUserNotBinded
log.Println("get user by id error")
@ -439,7 +439,7 @@ func HandleThirdPartyLoginStatusV2(state *proto.ThirdPartyLoginState, thirdParty
//字符串转int
userID, _ := strconv.Atoi(userIDStr)
//根据用户ID获取用户信息
user := GetUserByIDFromUserCenter(userID)
user := GetUserByIDWithCache(userID)
if user.ID == 0 {
thirdPartyLoginStatus.Status = 4 //添加用户信息错误
log.Println("get user by id error")

View File

@ -59,7 +59,7 @@ func GetUserByID(id int) []dao.User {
}
// 获取用户信息有redis缓存
func GetUserByIDFromUserCenter(id int) dao.User {
func GetUserByIDWithCache(id int) dao.User {
if id <= 0 {
return dao.User{}
}
@ -74,14 +74,14 @@ func GetUserByIDFromUserCenter(id int) dao.User {
return dao.User{}
}
} else {
user = GetUserInfoByIDFromUserCenterHttp(id)
user = dao.FindUserByID2(id)
if user.ID != 0 {
userJson, err := json.Marshal(user)
if err != nil {
fmt.Println("get user info , json marshal error:", err)
return dao.User{}
}
success := worker.SetRedisWithExpire(key, string(userJson), time.Second*10)
success := worker.SetRedis(key, string(userJson))
if !success {
fmt.Println("set redis error,user json:", string(userJson))
}
@ -90,39 +90,6 @@ func GetUserByIDFromUserCenter(id int) dao.User {
return user
}
type UserInfoResponse struct {
Code int `json:"code"`
Message string `json:"message"`
Data dao.User `json:"data"`
}
func GetUserInfoByIDFromUserCenterHttp(id int) dao.User {
var resp UserInfoResponse
url := "https://uc.ljsea.top/user/info?super_id=1"
tokens := worker.GetRedisSetMembers("super_permission_tokens")
if len(tokens) == 0 {
return resp.Data
}
token := tokens[0]
//请求参数
req := map[string]int{
"id": id,
}
headers := map[string]string{
"token": token,
}
reqByte, _ := json.Marshal(req)
err, respBytes := worker.DoPostRequestJSON(url, reqByte, headers)
if err != nil {
log.Println("GetUserInfoByIDFromUserCenterHttp error:", err)
return resp.Data
}
if err2 := json.Unmarshal(respBytes, &resp); err2 != nil {
log.Println("GetUserInfoByIDFromUserCenterHttp json unmarshal error:", err2)
}
return resp.Data
}
func GetUserByNameLike(name string) []dao.User {
users := dao.FindUserByNameLike(name)
for i, _ := range users {
@ -485,7 +452,7 @@ func GetUserInfoByToken(token string) (dao.User, error) {
return user, errors.New("token is invalid")
}
id := int(claims["id"].(float64))
user = GetUserByIDFromUserCenter(id)
user = GetUserByIDWithCache(id)
if user.ID == 0 {
return user, errors.New("user not found")
}