fixe page styles

This commit is contained in:
RockYang 2024-06-05 18:08:23 +08:00
parent d52dfbfef4
commit 2207830db9
17 changed files with 95 additions and 78 deletions

View File

@ -1,4 +1,7 @@
# 更新日志 # 更新日志
## v4.0.9
* Bug修复修复前端页面菜单把页面撑开底部留白问题
* 功能优化:聊天页面自动根据内容调整输入框的高度
## v4.0.8 ## v4.0.8
* 功能优化:升级 mathjax 公式解析插件,修复公式因为图片访问限制而无法显示的问题 * 功能优化:升级 mathjax 公式解析插件,修复公式因为图片访问限制而无法显示的问题
* 功能优化:当数据库更新失败的时候记录错误日志 * 功能优化:当数据库更新失败的时候记录错误日志

View File

@ -28,7 +28,6 @@ type MjTask struct {
TaskId string `json:"task_id"` TaskId string `json:"task_id"`
ImgArr []string `json:"img_arr"` ImgArr []string `json:"img_arr"`
ChannelId string `json:"channel_id"` ChannelId string `json:"channel_id"`
SessionId string `json:"session_id"`
Type TaskType `json:"type"` Type TaskType `json:"type"`
UserId int `json:"user_id"` UserId int `json:"user_id"`
Prompt string `json:"prompt,omitempty"` Prompt string `json:"prompt,omitempty"`
@ -42,7 +41,6 @@ type MjTask struct {
type SdTask struct { type SdTask struct {
Id int `json:"id"` // job 数据库ID Id int `json:"id"` // job 数据库ID
SessionId string `json:"session_id"`
Type TaskType `json:"type"` Type TaskType `json:"type"`
UserId int `json:"user_id"` UserId int `json:"user_id"`
Params SdTaskParams `json:"params"` Params SdTaskParams `json:"params"`

View File

@ -205,7 +205,6 @@ func (h *MidJourneyHandler) Image(c *gin.Context) {
h.pool.PushTask(types.MjTask{ h.pool.PushTask(types.MjTask{
Id: job.Id, Id: job.Id,
TaskId: taskId, TaskId: taskId,
SessionId: data.SessionId,
Type: types.TaskType(data.TaskType), Type: types.TaskType(data.TaskType),
Prompt: data.Prompt, Prompt: data.Prompt,
NegPrompt: data.NegPrompt, NegPrompt: data.NegPrompt,
@ -283,7 +282,6 @@ func (h *MidJourneyHandler) Upscale(c *gin.Context) {
h.pool.PushTask(types.MjTask{ h.pool.PushTask(types.MjTask{
Id: job.Id, Id: job.Id,
SessionId: data.SessionId,
Type: types.TaskUpscale, Type: types.TaskUpscale,
Prompt: data.Prompt, Prompt: data.Prompt,
UserId: userId, UserId: userId,
@ -350,7 +348,6 @@ func (h *MidJourneyHandler) Variation(c *gin.Context) {
h.pool.PushTask(types.MjTask{ h.pool.PushTask(types.MjTask{
Id: job.Id, Id: job.Id,
SessionId: data.SessionId,
Type: types.TaskVariation, Type: types.TaskVariation,
Prompt: data.Prompt, Prompt: data.Prompt,
UserId: userId, UserId: userId,

View File

@ -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)) 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{ h.DB.Create(&model.PowerLog{
UserId: user.Id, UserId: user.Id,
Username: user.Username, Username: user.Username,

View File

@ -168,11 +168,10 @@ func (h *SdJobHandler) Image(c *gin.Context) {
} }
h.pool.PushTask(types.SdTask{ h.pool.PushTask(types.SdTask{
Id: int(job.Id), Id: int(job.Id),
SessionId: data.SessionId, Type: types.TaskImage,
Type: types.TaskImage, Params: params,
Params: params, UserId: userId,
UserId: userId,
}) })
client := h.pool.Clients.Get(uint(job.UserId)) client := h.pool.Clients.Get(uint(job.UserId))

View File

@ -109,8 +109,8 @@ func (s *Service) Image(task types.DallTask, sync bool) (string, error) {
logger.Debugf("绘画参数:%+v", task) logger.Debugf("绘画参数:%+v", task)
prompt := task.Prompt prompt := task.Prompt
// translate prompt // translate prompt
if utils.HasChinese(task.Prompt) { if utils.HasChinese(prompt) {
content, err := utils.OpenAIRequest(s.db, fmt.Sprintf(service.RewritePromptTemplate, task.Prompt)) content, err := utils.OpenAIRequest(s.db, fmt.Sprintf(service.RewritePromptTemplate, prompt))
if err == nil { if err == nil {
prompt = content prompt = content
logger.Debugf("重写后提示词:%s", prompt) 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") 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 // get image generation API KEY
var apiKey model.ApiKey var apiKey model.ApiKey
tx := s.db.Where("type", "img"). tx = s.db.Where("type", "img").
Where("enabled", true). Where("enabled", true).
Order("last_used_at ASC").First(&apiKey) Order("last_used_at ASC").First(&apiKey)
if tx.Error != nil { 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![](%s)\n", prompt, imgURL) content = fmt.Sprintf("```\n%s\n```\n下面是我为你创作的图片\n\n![](%s)\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 return content, nil
} }

View File

@ -179,14 +179,14 @@ func (p *ServicePool) HasAvailableService() bool {
// SyncTaskProgress 异步拉取任务 // SyncTaskProgress 异步拉取任务
func (p *ServicePool) SyncTaskProgress() { func (p *ServicePool) SyncTaskProgress() {
go func() { go func() {
var items []model.MidJourneyJob var jobs []model.MidJourneyJob
for { for {
res := p.db.Where("progress < ?", 100).Find(&items) res := p.db.Where("progress < ?", 100).Find(&jobs)
if res.Error != nil { if res.Error != nil {
continue continue
} }
for _, job := range items { for _, job := range jobs {
// 失败或者 30 分钟还没完成的任务删除并退回算力 // 失败或者 30 分钟还没完成的任务删除并退回算力
if time.Now().Sub(job.CreatedAt) > time.Minute*30 || job.Progress == -1 { if time.Now().Sub(job.CreatedAt) > time.Minute*30 || job.Progress == -1 {
p.db.Delete(&job) p.db.Delete(&job)

View File

@ -132,7 +132,7 @@ func (p *ServicePool) CheckTaskStatus() {
continue continue
} }
} }
time.Sleep(time.Second * 10) time.Sleep(time.Second * 5)
} }
}() }()
} }

View File

@ -192,7 +192,7 @@ func (s *Service) Txt2Img(task types.SdTask) error {
return return
} }
task.Params.Seed = int64(utils.IntValue(utils.InterfaceToString(info["seed"]), -1)) 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 errChan <- nil
}() }()

View File

@ -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) e.db.Model(&model.User{}).Where("id", u.Id).UpdateColumn("vip", false)
continue continue
} }
// update user if u.Power < config.VipMonthPower {
tx := e.db.Model(&model.User{}).Where("id", u.Id).UpdateColumn("power", gorm.Expr("power + ?", config.VipMonthPower)) power := config.VipMonthPower - u.Power
// 记录算力变动日志 // update user
if tx.Error == nil { tx := e.db.Model(&model.User{}).Where("id", u.Id).UpdateColumn("power", gorm.Expr("power + ?", power))
var user model.User // 记录算力变动日志
e.db.Where("id", u.Id).First(&user) if tx.Error == nil {
e.db.Create(&model.PowerLog{ var user model.User
UserId: u.Id, e.db.Where("id", u.Id).First(&user)
Username: u.Username, e.db.Create(&model.PowerLog{
Type: types.PowerRecharge, UserId: u.Id,
Amount: config.VipMonthPower, Username: u.Username,
Mark: types.PowerAdd, Type: types.PowerRecharge,
Balance: user.Power, Amount: power,
Model: "系统盘点", Mark: types.PowerAdd,
Remark: fmt.Sprintf("VIP会员每月算力派发%d", config.VipMonthPower), Balance: user.Power,
CreatedAt: time.Now(), Model: "系统盘点",
}) Remark: fmt.Sprintf("VIP会员每月算力派发%d", config.VipMonthPower),
CreatedAt: time.Now(),
})
}
} }
} }
logger.Info("月底盘点完成!") logger.Info("月底盘点完成!")

View File

@ -54,7 +54,7 @@ type apiErrRes struct {
func OpenAIRequest(db *gorm.DB, prompt string) (string, error) { func OpenAIRequest(db *gorm.DB, prompt string) (string, error) {
var apiKey model.ApiKey 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 { if res.Error != nil {
return "", fmt.Errorf("error with fetch OpenAI API KEY%v", res.Error) 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"). r, err := client.R().SetHeader("Content-Type", "application/json").
SetHeader("Authorization", "Bearer "+apiKey.Value). SetHeader("Authorization", "Bearer "+apiKey.Value).
SetBody(types.ApiRequest{ SetBody(types.ApiRequest{
Model: "gpt-3.5-turbo-0125", Model: "gpt-3.5-turbo",
Temperature: 0.9, Temperature: 0.9,
MaxTokens: 1024, MaxTokens: 1024,
Stream: false, Stream: false,

View File

@ -222,10 +222,24 @@ export function processContent(content) {
return texts.join("\n") return texts.join("\n")
} }
export function escapeHTML(html) { export function processPrompt(prompt) {
return html.replace(/&/g, "&amp;") prompt = prompt.replace(/&/g, "&amp;")
.replace(/</g, "&lt;") .replace(/</g, "&lt;")
.replace(/>/g, "&gt;"); .replace(/>/g, "&gt;");
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![](" + link + ")\n")
}
}
}
}
return prompt
} }
// 判断是否为 iphone 设备 // 判断是否为 iphone 设备

View File

@ -191,7 +191,15 @@ import ChatPrompt from "@/components/ChatPrompt.vue";
import ChatReply from "@/components/ChatReply.vue"; import ChatReply from "@/components/ChatReply.vue";
import {Delete, Edit, More, Plus, Promotion, Search, Share, VideoPause} from '@element-plus/icons-vue' import {Delete, Edit, More, Plus, Promotion, Search, Share, VideoPause} from '@element-plus/icons-vue'
import 'highlight.js/styles/a11y-dark.css' 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 {ElMessage, ElMessageBox} from "element-plus";
import hl from "highlight.js"; import hl from "highlight.js";
import {getSessionId, getUserToken, removeUserToken} from "@/store/session"; import {getSessionId, getUserToken, removeUserToken} from "@/store/session";
@ -697,8 +705,10 @@ const onInput = (e) => {
inputRef.value.scrollTo(0, inputRef.value.scrollHeight) inputRef.value.scrollTo(0, inputRef.value.scrollHeight)
if (prompt.value.length < 10) { if (prompt.value.length < 10) {
row.value = 1 row.value = 1
} else if (row.value <= 7) { } else if (lines <= 7){
row.value = lines row.value = lines
} else {
row.value = 7
} }
// //
@ -738,7 +748,7 @@ const sendMessage = function () {
type: "prompt", type: "prompt",
id: randString(32), id: randString(32),
icon: loginUser.value.avatar, icon: loginUser.value.avatar,
content: md.render(escapeHTML(processContent(prompt.value))), content: md.render(processPrompt(prompt.value)),
created_at: new Date().getTime() / 1000, created_at: new Date().getTime() / 1000,
}); });

View File

@ -167,11 +167,6 @@
<i class="iconfont icon-loading"></i> <i class="iconfont icon-loading"></i>
<span>正在下载图片</span> <span>正在下载图片</span>
</div> </div>
<div class="image-slot">
<el-icon>
<Picture/>
</el-icon>
</div>
</template> </template>
</el-image> </el-image>

View File

@ -187,7 +187,7 @@ onMounted(() => {
httpGet("/api/menu/list").then(res => { httpGet("/api/menu/list").then(res => {
mainNavs.value = res.data mainNavs.value = res.data
// //
const rows = Math.floor((window.innerHeight - 90) / 60) const rows = Math.floor((window.innerHeight - 100) / 90)
if (res.data.length > rows) { if (res.data.length > rows) {
mainNavs.value = res.data.slice(0, rows) mainNavs.value = res.data.slice(0, rows)
moreNavs.value = res.data.slice(rows) moreNavs.value = res.data.slice(rows)

View File

@ -515,6 +515,13 @@
正在加载图片 正在加载图片
</div> </div>
</template> </template>
<template #error>
<div class="image-slot">
<el-icon>
<Picture/>
</el-icon>
</div>
</template>
</el-image> </el-image>
<el-image v-else> <el-image v-else>
<template #error> <template #error>
@ -522,11 +529,6 @@
<i class="iconfont icon-loading"></i> <i class="iconfont icon-loading"></i>
<span>正在下载图片</span> <span>正在下载图片</span>
</div> </div>
<div class="image-slot">
<el-icon>
<Picture/>
</el-icon>
</div>
</template> </template>
</el-image> </el-image>

View File

@ -308,11 +308,7 @@
</template> </template>
<template #error> <template #error>
<div class="image-slot"> <div class="image-slot"></div>
<el-icon>
<Picture/>
</el-icon>
</div>
</template> </template>
</el-image> </el-image>