diff --git a/CHANGELOG.md b/CHANGELOG.md index 8be1a044..fffe36ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,7 @@ # 更新日志 +## v4.0.9 +* Bug修复:修复前端页面菜单把页面撑开,底部留白问题 +* 功能优化:聊天页面自动根据内容调整输入框的高度 ## v4.0.8 * 功能优化:升级 mathjax 公式解析插件,修复公式因为图片访问限制而无法显示的问题 * 功能优化:当数据库更新失败的时候记录错误日志 diff --git a/api/core/types/task.go b/api/core/types/task.go index 6b6a364c..6224a383 100644 --- a/api/core/types/task.go +++ b/api/core/types/task.go @@ -28,7 +28,6 @@ type MjTask struct { TaskId string `json:"task_id"` ImgArr []string `json:"img_arr"` ChannelId string `json:"channel_id"` - SessionId string `json:"session_id"` Type TaskType `json:"type"` UserId int `json:"user_id"` Prompt string `json:"prompt,omitempty"` @@ -42,7 +41,6 @@ type MjTask struct { type SdTask struct { Id int `json:"id"` // job 数据库ID - SessionId string `json:"session_id"` Type TaskType `json:"type"` UserId int `json:"user_id"` Params SdTaskParams `json:"params"` diff --git a/api/handler/mj_handler.go b/api/handler/mj_handler.go index 822df42a..7b8d7ca0 100644 --- a/api/handler/mj_handler.go +++ b/api/handler/mj_handler.go @@ -205,7 +205,6 @@ func (h *MidJourneyHandler) Image(c *gin.Context) { h.pool.PushTask(types.MjTask{ Id: job.Id, TaskId: taskId, - SessionId: data.SessionId, Type: types.TaskType(data.TaskType), Prompt: data.Prompt, NegPrompt: data.NegPrompt, @@ -283,7 +282,6 @@ func (h *MidJourneyHandler) Upscale(c *gin.Context) { h.pool.PushTask(types.MjTask{ Id: job.Id, - SessionId: data.SessionId, Type: types.TaskUpscale, Prompt: data.Prompt, UserId: userId, @@ -350,7 +348,6 @@ func (h *MidJourneyHandler) Variation(c *gin.Context) { h.pool.PushTask(types.MjTask{ Id: job.Id, - SessionId: data.SessionId, Type: types.TaskVariation, Prompt: data.Prompt, UserId: userId, diff --git a/api/handler/payment_handler.go b/api/handler/payment_handler.go index 9c186517..6b4d062b 100644 --- a/api/handler/payment_handler.go +++ b/api/handler/payment_handler.go @@ -493,7 +493,7 @@ func (h *PaymentHandler) notify(orderNo string, tradeNo string) error { h.DB.Model(&model.Product{}).Where("id = ?", order.ProductId).UpdateColumn("sales", gorm.Expr("sales + ?", 1)) // 记录算力充值日志 - if opt != "" { + if power > 0 { h.DB.Create(&model.PowerLog{ UserId: user.Id, Username: user.Username, diff --git a/api/handler/sd_handler.go b/api/handler/sd_handler.go index e30e837d..5ed3c009 100644 --- a/api/handler/sd_handler.go +++ b/api/handler/sd_handler.go @@ -168,11 +168,10 @@ func (h *SdJobHandler) Image(c *gin.Context) { } h.pool.PushTask(types.SdTask{ - Id: int(job.Id), - SessionId: data.SessionId, - Type: types.TaskImage, - Params: params, - UserId: userId, + Id: int(job.Id), + Type: types.TaskImage, + Params: params, + UserId: userId, }) client := h.pool.Clients.Get(uint(job.UserId)) diff --git a/api/service/dalle/service.go b/api/service/dalle/service.go index dc66927b..9a915da5 100644 --- a/api/service/dalle/service.go +++ b/api/service/dalle/service.go @@ -109,8 +109,8 @@ func (s *Service) Image(task types.DallTask, sync bool) (string, error) { logger.Debugf("绘画参数:%+v", task) prompt := task.Prompt // translate prompt - if utils.HasChinese(task.Prompt) { - content, err := utils.OpenAIRequest(s.db, fmt.Sprintf(service.RewritePromptTemplate, task.Prompt)) + if utils.HasChinese(prompt) { + content, err := utils.OpenAIRequest(s.db, fmt.Sprintf(service.RewritePromptTemplate, prompt)) if err == nil { prompt = content logger.Debugf("重写后提示词:%s", prompt) @@ -124,9 +124,28 @@ func (s *Service) Image(task types.DallTask, sync bool) (string, error) { return "", errors.New("insufficient of power") } + // 更新用户算力 + tx := s.db.Model(&model.User{}).Where("id", user.Id).UpdateColumn("power", gorm.Expr("power - ?", task.Power)) + // 记录算力变化日志 + if tx.Error == nil && tx.RowsAffected > 0 { + var u model.User + s.db.Where("id", user.Id).First(&u) + s.db.Create(&model.PowerLog{ + UserId: user.Id, + Username: user.Username, + Type: types.PowerConsume, + Amount: task.Power, + Balance: u.Power, + Mark: types.PowerSub, + Model: "dall-e-3", + Remark: fmt.Sprintf("绘画提示词:%s", utils.CutWords(task.Prompt, 10)), + CreatedAt: time.Now(), + }) + } + // get image generation API KEY var apiKey model.ApiKey - tx := s.db.Where("type", "img"). + tx = s.db.Where("type", "img"). Where("enabled", true). Order("last_used_at ASC").First(&apiKey) if tx.Error != nil { @@ -183,25 +202,6 @@ func (s *Service) Image(task types.DallTask, sync bool) (string, error) { content = fmt.Sprintf("```\n%s\n```\n下面是我为你创作的图片:\n\n\n", prompt, imgURL) } - // 更新用户算力 - tx = s.db.Model(&model.User{}).Where("id", user.Id).UpdateColumn("power", gorm.Expr("power - ?", task.Power)) - // 记录算力变化日志 - if tx.Error == nil && tx.RowsAffected > 0 { - var u model.User - s.db.Where("id", user.Id).First(&u) - s.db.Create(&model.PowerLog{ - UserId: user.Id, - Username: user.Username, - Type: types.PowerConsume, - Amount: task.Power, - Balance: u.Power, - Mark: types.PowerSub, - Model: "dall-e-3", - Remark: fmt.Sprintf("绘画提示词:%s", utils.CutWords(task.Prompt, 10)), - CreatedAt: time.Now(), - }) - } - return content, nil } diff --git a/api/service/mj/pool.go b/api/service/mj/pool.go index ddddd280..3eacfd78 100644 --- a/api/service/mj/pool.go +++ b/api/service/mj/pool.go @@ -179,14 +179,14 @@ func (p *ServicePool) HasAvailableService() bool { // SyncTaskProgress 异步拉取任务 func (p *ServicePool) SyncTaskProgress() { go func() { - var items []model.MidJourneyJob + var jobs []model.MidJourneyJob for { - res := p.db.Where("progress < ?", 100).Find(&items) + res := p.db.Where("progress < ?", 100).Find(&jobs) if res.Error != nil { continue } - for _, job := range items { + for _, job := range jobs { // 失败或者 30 分钟还没完成的任务删除并退回算力 if time.Now().Sub(job.CreatedAt) > time.Minute*30 || job.Progress == -1 { p.db.Delete(&job) diff --git a/api/service/sd/pool.go b/api/service/sd/pool.go index 55329e46..548875ec 100644 --- a/api/service/sd/pool.go +++ b/api/service/sd/pool.go @@ -132,7 +132,7 @@ func (p *ServicePool) CheckTaskStatus() { continue } } - time.Sleep(time.Second * 10) + time.Sleep(time.Second * 5) } }() } diff --git a/api/service/sd/service.go b/api/service/sd/service.go index 736f4180..468e8b3e 100644 --- a/api/service/sd/service.go +++ b/api/service/sd/service.go @@ -192,7 +192,7 @@ func (s *Service) Txt2Img(task types.SdTask) error { return } task.Params.Seed = int64(utils.IntValue(utils.InterfaceToString(info["seed"]), -1)) - s.db.Model(&model.SdJob{Id: uint(task.Id)}).UpdateColumns(model.SdJob{ImgURL: imgURL, Params: utils.JsonEncode(task.Params)}) + s.db.Model(&model.SdJob{Id: uint(task.Id)}).UpdateColumns(model.SdJob{ImgURL: imgURL, Params: utils.JsonEncode(task.Params), Prompt: task.Params.Prompt}) errChan <- nil }() diff --git a/api/service/xxl_job_service.go b/api/service/xxl_job_service.go index 14fec1db..2adecf1b 100644 --- a/api/service/xxl_job_service.go +++ b/api/service/xxl_job_service.go @@ -106,23 +106,26 @@ func (e *XXLJobExecutor) ResetVipPower(cxt context.Context, param *xxl.RunReq) ( e.db.Model(&model.User{}).Where("id", u.Id).UpdateColumn("vip", false) continue } - // update user - tx := e.db.Model(&model.User{}).Where("id", u.Id).UpdateColumn("power", gorm.Expr("power + ?", config.VipMonthPower)) - // 记录算力变动日志 - if tx.Error == nil { - var user model.User - e.db.Where("id", u.Id).First(&user) - e.db.Create(&model.PowerLog{ - UserId: u.Id, - Username: u.Username, - Type: types.PowerRecharge, - Amount: config.VipMonthPower, - Mark: types.PowerAdd, - Balance: user.Power, - Model: "系统盘点", - Remark: fmt.Sprintf("VIP会员每月算力派发,:%d", config.VipMonthPower), - CreatedAt: time.Now(), - }) + if u.Power < config.VipMonthPower { + power := config.VipMonthPower - u.Power + // update user + tx := e.db.Model(&model.User{}).Where("id", u.Id).UpdateColumn("power", gorm.Expr("power + ?", power)) + // 记录算力变动日志 + if tx.Error == nil { + var user model.User + e.db.Where("id", u.Id).First(&user) + e.db.Create(&model.PowerLog{ + UserId: u.Id, + Username: u.Username, + Type: types.PowerRecharge, + Amount: power, + Mark: types.PowerAdd, + Balance: user.Power, + Model: "系统盘点", + Remark: fmt.Sprintf("VIP会员每月算力派发,:%d", config.VipMonthPower), + CreatedAt: time.Now(), + }) + } } } logger.Info("月底盘点完成!") diff --git a/api/utils/openai.go b/api/utils/openai.go index 9f012c2f..9ee01a35 100644 --- a/api/utils/openai.go +++ b/api/utils/openai.go @@ -54,7 +54,7 @@ type apiErrRes struct { func OpenAIRequest(db *gorm.DB, prompt string) (string, error) { var apiKey model.ApiKey - res := db.Where("platform IN ?", []string{types.OpenAI.Value, types.Azure.Value}).Where("type", "chat").Where("enabled = ?", true).First(&apiKey) + res := db.Where("platform", types.OpenAI.Value).Where("type", "chat").Where("enabled", true).First(&apiKey) if res.Error != nil { return "", fmt.Errorf("error with fetch OpenAI API KEY:%v", res.Error) } @@ -74,7 +74,7 @@ func OpenAIRequest(db *gorm.DB, prompt string) (string, error) { r, err := client.R().SetHeader("Content-Type", "application/json"). SetHeader("Authorization", "Bearer "+apiKey.Value). SetBody(types.ApiRequest{ - Model: "gpt-3.5-turbo-0125", + Model: "gpt-3.5-turbo", Temperature: 0.9, MaxTokens: 1024, Stream: false, diff --git a/web/src/utils/libs.js b/web/src/utils/libs.js index 2a2879bb..1ba88730 100644 --- a/web/src/utils/libs.js +++ b/web/src/utils/libs.js @@ -222,10 +222,24 @@ export function processContent(content) { return texts.join("\n") } -export function escapeHTML(html) { - return html.replace(/&/g, "&") +export function processPrompt(prompt) { + prompt = prompt.replace(/&/g, "&") .replace(//g, ">"); + + const linkRegex = /(https?:\/\/\S+)/g; + const links = prompt.match(linkRegex); + if (links) { + for (let link of links) { + if (isImage(link)) { + const index = prompt.indexOf(link) + if (prompt.substring(index - 1, 2) !== "]") { + prompt = prompt.replace(link, "\n\n") + } + } + } + } + return prompt } // 判断是否为 iphone 设备 diff --git a/web/src/views/ChatPlus.vue b/web/src/views/ChatPlus.vue index 887ddf77..3c495fa5 100644 --- a/web/src/views/ChatPlus.vue +++ b/web/src/views/ChatPlus.vue @@ -191,7 +191,15 @@ import ChatPrompt from "@/components/ChatPrompt.vue"; import ChatReply from "@/components/ChatReply.vue"; import {Delete, Edit, More, Plus, Promotion, Search, Share, VideoPause} from '@element-plus/icons-vue' import 'highlight.js/styles/a11y-dark.css' -import {dateFormat, escapeHTML, isMobile, processContent, randString, removeArrayItem, UUID} from "@/utils/libs"; +import { + dateFormat, + isMobile, + processContent, + processPrompt, + randString, + removeArrayItem, + UUID +} from "@/utils/libs"; import {ElMessage, ElMessageBox} from "element-plus"; import hl from "highlight.js"; import {getSessionId, getUserToken, removeUserToken} from "@/store/session"; @@ -697,8 +705,10 @@ const onInput = (e) => { inputRef.value.scrollTo(0, inputRef.value.scrollHeight) if (prompt.value.length < 10) { row.value = 1 - } else if (row.value <= 7) { + } else if (lines <= 7){ row.value = lines + } else { + row.value = 7 } // 输入回车自动提交 @@ -738,7 +748,7 @@ const sendMessage = function () { type: "prompt", id: randString(32), icon: loginUser.value.avatar, - content: md.render(escapeHTML(processContent(prompt.value))), + content: md.render(processPrompt(prompt.value)), created_at: new Date().getTime() / 1000, }); diff --git a/web/src/views/Dalle.vue b/web/src/views/Dalle.vue index 7d01f067..1e151b7d 100644 --- a/web/src/views/Dalle.vue +++ b/web/src/views/Dalle.vue @@ -167,11 +167,6 @@ 正在下载图片 -