save task origin info for AI generating jobs

This commit is contained in:
RockYang 2024-11-11 17:22:08 +08:00
parent 135755d21d
commit ce8a2d0222
31 changed files with 358 additions and 136 deletions

View File

@ -74,7 +74,7 @@ type SdTaskParams struct {
// DallTask DALL-E task
type DallTask struct {
ClientId string `json:"client_id"`
JobId uint `json:"job_id"`
Id uint `json:"id"`
UserId uint `json:"user_id"`
Prompt string `json:"prompt"`
N int `json:"n"`

View File

@ -72,10 +72,21 @@ func (h *DallJobHandler) Image(c *gin.Context) {
idValue, _ := c.Get(types.LoginUserID)
userId := utils.IntValue(utils.InterfaceToString(idValue), 0)
task := types.DallTask{
ClientId: data.ClientId,
UserId: uint(userId),
Prompt: data.Prompt,
Quality: data.Quality,
Size: data.Size,
Style: data.Style,
Power: h.App.SysConfig.DallPower,
TranslateModelId: h.App.SysConfig.TranslateModelId,
}
job := model.DallJob{
UserId: uint(userId),
Prompt: data.Prompt,
Power: h.App.SysConfig.DallPower,
UserId: uint(userId),
Prompt: data.Prompt,
Power: task.Power,
TaskInfo: utils.JsonEncode(task),
}
res := h.DB.Create(&job)
if res.Error != nil {
@ -83,17 +94,8 @@ func (h *DallJobHandler) Image(c *gin.Context) {
return
}
h.dallService.PushTask(types.DallTask{
ClientId: data.ClientId,
JobId: job.Id,
UserId: uint(userId),
Prompt: data.Prompt,
Quality: data.Quality,
Size: data.Size,
Style: data.Style,
Power: job.Power,
TranslateModelId: h.App.SysConfig.TranslateModelId,
})
task.Id = job.Id
h.dallService.PushTask(task)
resp.SUCCESS(c)
}

View File

@ -212,7 +212,7 @@ func (h *FunctionHandler) Dall3(c *gin.Context) {
}
content, err := h.dallService.Image(types.DallTask{
JobId: job.Id,
Id: job.Id,
UserId: user.Id,
Prompt: job.Prompt,
N: 1,

View File

@ -152,10 +152,23 @@ func (h *MidJourneyHandler) Image(c *gin.Context) {
resp.ERROR(c, "error with generate task id: "+err.Error())
return
}
task := types.MjTask{
ClientId: data.ClientId,
TaskId: taskId,
Type: types.TaskType(data.TaskType),
Prompt: data.Prompt,
NegPrompt: data.NegPrompt,
Params: params,
UserId: userId,
ImgArr: data.ImgArr,
Mode: h.App.SysConfig.MjMode,
TranslateModelId: h.App.SysConfig.TranslateModelId,
}
job := model.MidJourneyJob{
Type: data.TaskType,
UserId: userId,
TaskId: taskId,
TaskInfo: utils.JsonEncode(task),
Progress: 0,
Prompt: fmt.Sprintf("%s %s", data.Prompt, params),
Power: h.App.SysConfig.MjPower,
@ -175,19 +188,8 @@ func (h *MidJourneyHandler) Image(c *gin.Context) {
return
}
h.mjService.PushTask(types.MjTask{
Id: job.Id,
ClientId: data.ClientId,
TaskId: taskId,
Type: types.TaskType(data.TaskType),
Prompt: data.Prompt,
NegPrompt: data.NegPrompt,
Params: params,
UserId: userId,
ImgArr: data.ImgArr,
Mode: h.App.SysConfig.MjMode,
TranslateModelId: h.App.SysConfig.TranslateModelId,
})
task.Id = job.Id
h.mjService.PushTask(task)
// update user's power
err = h.userService.DecreasePower(job.UserId, job.Power, model.PowerLog{
@ -226,10 +228,21 @@ func (h *MidJourneyHandler) Upscale(c *gin.Context) {
idValue, _ := c.Get(types.LoginUserID)
userId := utils.IntValue(utils.InterfaceToString(idValue), 0)
taskId, _ := h.snowflake.Next(true)
task := types.MjTask{
ClientId: data.ClientId,
Type: types.TaskUpscale,
UserId: userId,
ChannelId: data.ChannelId,
Index: data.Index,
MessageId: data.MessageId,
MessageHash: data.MessageHash,
Mode: h.App.SysConfig.MjMode,
}
job := model.MidJourneyJob{
Type: types.TaskUpscale.String(),
UserId: userId,
TaskId: taskId,
TaskInfo: utils.JsonEncode(task),
Progress: 0,
Power: h.App.SysConfig.MjActionPower,
CreatedAt: time.Now(),
@ -239,17 +252,8 @@ func (h *MidJourneyHandler) Upscale(c *gin.Context) {
return
}
h.mjService.PushTask(types.MjTask{
Id: job.Id,
ClientId: data.ClientId,
Type: types.TaskUpscale,
UserId: userId,
ChannelId: data.ChannelId,
Index: data.Index,
MessageId: data.MessageId,
MessageHash: data.MessageHash,
Mode: h.App.SysConfig.MjMode,
})
task.Id = job.Id
h.mjService.PushTask(task)
// update user's power
err := h.userService.DecreasePower(job.UserId, job.Power, model.PowerLog{
@ -280,11 +284,22 @@ func (h *MidJourneyHandler) Variation(c *gin.Context) {
idValue, _ := c.Get(types.LoginUserID)
userId := utils.IntValue(utils.InterfaceToString(idValue), 0)
taskId, _ := h.snowflake.Next(true)
task := types.MjTask{
Type: types.TaskVariation,
ClientId: data.ClientId,
UserId: userId,
Index: data.Index,
ChannelId: data.ChannelId,
MessageId: data.MessageId,
MessageHash: data.MessageHash,
Mode: h.App.SysConfig.MjMode,
}
job := model.MidJourneyJob{
Type: types.TaskVariation.String(),
ChannelId: data.ChannelId,
UserId: userId,
TaskId: taskId,
TaskInfo: utils.JsonEncode(task),
Progress: 0,
Power: h.App.SysConfig.MjActionPower,
CreatedAt: time.Now(),
@ -294,17 +309,8 @@ func (h *MidJourneyHandler) Variation(c *gin.Context) {
return
}
h.mjService.PushTask(types.MjTask{
Id: job.Id,
Type: types.TaskVariation,
ClientId: data.ClientId,
UserId: userId,
Index: data.Index,
ChannelId: data.ChannelId,
MessageId: data.MessageId,
MessageHash: data.MessageHash,
Mode: h.App.SysConfig.MjMode,
})
task.Id = job.Id
h.mjService.PushTask(task)
err := h.userService.DecreasePower(job.UserId, job.Power, model.PowerLog{
Type: types.PowerConsume,

View File

@ -18,6 +18,7 @@ import (
"geekai/utils/resp"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
"strings"
)
// 提示词生成 handler
@ -57,3 +58,39 @@ func (h *PromptHandler) Lyric(c *gin.Context) {
resp.SUCCESS(c, content)
}
// Image 生成 AI 绘画提示词
func (h *PromptHandler) Image(c *gin.Context) {
var data struct {
Prompt string `json:"prompt"`
}
if err := c.ShouldBindJSON(&data); err != nil {
resp.ERROR(c, types.InvalidArgs)
return
}
content, err := utils.OpenAIRequest(h.DB, fmt.Sprintf(service.ImagePromptOptimizeTemplate, data.Prompt), h.App.SysConfig.TranslateModelId)
if err != nil {
resp.ERROR(c, err.Error())
return
}
resp.SUCCESS(c, strings.Trim(content, `"`))
}
// Video 生成视频提示词
func (h *PromptHandler) Video(c *gin.Context) {
var data struct {
Prompt string `json:"prompt"`
}
if err := c.ShouldBindJSON(&data); err != nil {
resp.ERROR(c, types.InvalidArgs)
return
}
content, err := utils.OpenAIRequest(h.DB, fmt.Sprintf(service.VideoPromptTemplate, data.Prompt), h.App.SysConfig.TranslateModelId)
if err != nil {
resp.ERROR(c, err.Error())
return
}
resp.SUCCESS(c, strings.Trim(content, `"`))
}

View File

@ -89,13 +89,29 @@ func (h *SunoHandler) Create(c *gin.Context) {
data.Prompt = fmt.Sprintf("%s\n%s", song.Prompt, refSong.Prompt)
}
}
task := types.SunoTask{
ClientId: data.ClientId,
UserId: int(h.GetLoginUserId(c)),
Type: data.Type,
Title: data.Title,
RefTaskId: data.RefTaskId,
RefSongId: data.RefSongId,
ExtendSecs: data.ExtendSecs,
Prompt: data.Prompt,
Tags: data.Tags,
Model: data.Model,
Instrumental: data.Instrumental,
SongId: data.SongId,
AudioURL: data.AudioURL,
}
// 插入数据库
job := model.SunoJob{
UserId: int(h.GetLoginUserId(c)),
UserId: task.UserId,
Prompt: data.Prompt,
Instrumental: data.Instrumental,
ModelName: data.Model,
TaskInfo: utils.JsonEncode(task),
Tags: data.Tags,
Title: data.Title,
Type: data.Type,
@ -115,26 +131,13 @@ func (h *SunoHandler) Create(c *gin.Context) {
}
// 创建任务
h.sunoService.PushTask(types.SunoTask{
ClientId: data.ClientId,
Id: job.Id,
UserId: job.UserId,
Type: job.Type,
Title: job.Title,
RefTaskId: data.RefTaskId,
RefSongId: data.RefSongId,
ExtendSecs: data.ExtendSecs,
Prompt: job.Prompt,
Tags: data.Tags,
Model: data.Model,
Instrumental: data.Instrumental,
SongId: data.SongId,
AudioURL: data.AudioURL,
})
task.Id = job.Id
h.sunoService.PushTask(task)
// update user's power
err = h.userService.DecreasePower(job.UserId, job.Power, model.PowerLog{
Type: types.PowerConsume,
Model: job.ModelName,
Remark: fmt.Sprintf("Suno 文生歌曲,%s", job.ModelName),
CreatedAt: time.Now(),
})

View File

@ -80,13 +80,21 @@ func (h *VideoHandler) LumaCreate(c *gin.Context) {
StartImgURL: data.FirstFrameImg,
EndImgURL: data.EndFrameImg,
}
task := types.VideoTask{
ClientId: data.ClientId,
UserId: userId,
Type: types.VideoLuma,
Prompt: data.Prompt,
Params: params,
TranslateModelId: h.App.SysConfig.TranslateModelId,
}
// 插入数据库
job := model.VideoJob{
UserId: userId,
Type: types.VideoLuma,
Prompt: data.Prompt,
Power: h.App.SysConfig.LumaPower,
Params: utils.JsonEncode(params),
UserId: userId,
Type: types.VideoLuma,
Prompt: data.Prompt,
Power: h.App.SysConfig.LumaPower,
TaskInfo: utils.JsonEncode(task),
}
tx := h.DB.Create(&job)
if tx.Error != nil {
@ -95,15 +103,8 @@ func (h *VideoHandler) LumaCreate(c *gin.Context) {
}
// 创建任务
h.videoService.PushTask(types.VideoTask{
ClientId: data.ClientId,
Id: job.Id,
UserId: userId,
Type: types.VideoLuma,
Prompt: data.Prompt,
Params: params,
TranslateModelId: h.App.SysConfig.TranslateModelId,
})
task.Id = job.Id
h.videoService.PushTask(task)
// update user's power
err = h.userService.DecreasePower(job.UserId, job.Power, model.PowerLog{

View File

@ -521,6 +521,8 @@ func main() {
fx.Invoke(func(s *core.AppServer, h *handler.PromptHandler) {
group := s.Engine.Group("/api/prompt")
group.POST("/lyric", h.Lyric)
group.POST("/image", h.Image)
group.POST("/video", h.Video)
}),
fx.Invoke(func(s *core.AppServer, db *gorm.DB) {
go func() {

View File

@ -59,6 +59,20 @@ func (s *Service) PushTask(task types.DallTask) {
}
func (s *Service) Run() {
// 将数据库中未提交的人物加载到队列
var jobs []model.DallJob
s.db.Where("progress", 0).Find(&jobs)
for _, v := range jobs {
var task types.DallTask
err := utils.JsonDecode(v.TaskInfo, &task)
if err != nil {
logger.Errorf("decode task info with error: %v", err)
continue
}
task.Id = v.Id
s.PushTask(task)
}
logger.Info("Starting DALL-E job consumer...")
go func() {
for {
@ -69,15 +83,15 @@ func (s *Service) Run() {
continue
}
logger.Infof("handle a new DALL-E task: %+v", task)
s.clientIds[task.JobId] = task.ClientId
s.clientIds[task.Id] = task.ClientId
_, err = s.Image(task, false)
if err != nil {
logger.Errorf("error with image task: %v", err)
s.db.Model(&model.DallJob{Id: task.JobId}).UpdateColumns(map[string]interface{}{
s.db.Model(&model.DallJob{Id: task.Id}).UpdateColumns(map[string]interface{}{
"progress": service.FailTaskProgress,
"err_msg": err.Error(),
})
s.notifyQueue.RPush(service.NotifyMessage{ClientId: task.ClientId, UserId: int(task.UserId), JobId: int(task.JobId), Message: service.TaskStatusFailed})
s.notifyQueue.RPush(service.NotifyMessage{ClientId: task.ClientId, UserId: int(task.UserId), JobId: int(task.Id), Message: service.TaskStatusFailed})
}
}
}()
@ -177,7 +191,7 @@ func (s *Service) Image(task types.DallTask, sync bool) (string, error) {
// update the api key last use time
s.db.Model(&apiKey).UpdateColumn("last_used_at", time.Now().Unix())
// update task progress
err = s.db.Model(&model.DallJob{Id: task.JobId}).UpdateColumns(map[string]interface{}{
err = s.db.Model(&model.DallJob{Id: task.Id}).UpdateColumns(map[string]interface{}{
"progress": 100,
"org_url": res.Data[0].Url,
"prompt": prompt,
@ -186,10 +200,10 @@ func (s *Service) Image(task types.DallTask, sync bool) (string, error) {
return "", fmt.Errorf("err with update database: %v", err)
}
s.notifyQueue.RPush(service.NotifyMessage{ClientId: task.ClientId, UserId: int(task.UserId), JobId: int(task.JobId), Message: service.TaskStatusFailed})
s.notifyQueue.RPush(service.NotifyMessage{ClientId: task.ClientId, UserId: int(task.UserId), JobId: int(task.Id), Message: service.TaskStatusFailed})
var content string
if sync {
imgURL, err := s.downloadImage(task.JobId, int(task.UserId), res.Data[0].Url)
imgURL, err := s.downloadImage(task.Id, int(task.UserId), res.Data[0].Url)
if err != nil {
return "", fmt.Errorf("error with download image: %v", err)
}

View File

@ -46,6 +46,21 @@ func NewService(redisCli *redis.Client, db *gorm.DB, client *Client, manager *os
}
func (s *Service) Run() {
// 将数据库中未提交的人物加载到队列
var jobs []model.MidJourneyJob
s.db.Where("task_id", "").Where("progress", 0).Find(&jobs)
for _, v := range jobs {
var task types.MjTask
err := utils.JsonDecode(v.TaskInfo, &task)
if err != nil {
logger.Errorf("decode task info with error: %v", err)
continue
}
task.Id = v.Id
s.clientIds[task.Id] = task.ClientId
s.PushTask(task)
}
logger.Info("Starting MidJourney job consumer for service")
go func() {
for {

View File

@ -58,22 +58,17 @@ func (s *Service) PushTask(task types.SunoTask) {
func (s *Service) Run() {
// 将数据库中未提交的人物加载到队列
var jobs []model.SunoJob
s.db.Where("task_id", "").Find(&jobs)
s.db.Where("task_id", "").Where("progress", 0).Find(&jobs)
for _, v := range jobs {
s.PushTask(types.SunoTask{
Id: v.Id,
Channel: v.Channel,
UserId: v.UserId,
Type: v.Type,
Title: v.Title,
RefTaskId: v.RefTaskId,
RefSongId: v.RefSongId,
Prompt: v.Prompt,
Tags: v.Tags,
Model: v.ModelName,
Instrumental: v.Instrumental,
ExtendSecs: v.ExtendSecs,
})
var task types.SunoTask
err := utils.JsonDecode(v.TaskInfo, &task)
if err != nil {
logger.Errorf("decode task info with error: %v", err)
continue
}
task.Id = v.Id
s.PushTask(task)
s.clientIds[v.TaskId] = task.ClientId
}
logger.Info("Starting Suno job consumer...")
go func() {

View File

@ -90,3 +90,29 @@ const LyricPromptTemplate = `
尾声
{{歌词内容}}
`
const VideoPromptTemplate = `
As an expert in video generation prompts, please create a detailed descriptive prompt for the following video concept. The description should include the setting, character appearance, actions, overall atmosphere, and camera angles. Please make it as detailed and vivid as possible to help ensure that every aspect of the video is accurately captured.
Please remember that regardless of the users input, the final output must be in English.
# Details to Include
- Describe the overall visual style of the video (e.g., animated, realistic, retro tone, etc.)
- Identify key characters or objects in the video and describe their appearance, attire, and expressions
- Describe the environment of the scene, including weather, lighting, colors, and important details
- Explain the behavior and interactions of the characters
- Include any unique camera angles, movements, or special effects
# Output Format
Provide the prompt in paragraph form, ensuring that the description is detailed enough for a video generation system to recreate the envisioned scene. Include the beginning, middle, and end of the scene to convey a complete storyline.
# Example
**User Input:**
A small cat basking in the sun on a balcony.
**Generated Prompt:**
On a bright spring afternoon, an orange-striped kitten lies lazily on a balcony, basking in the warm sunlight. The iron railings around the balcony cast soft shadows that dance gently with the light. The cats eyes are half-closed, exuding a sense of contentment and tranquility in its surroundings. In the distance, a few fluffy white clouds drift slowly across the blue sky. The camera initially focuses on the cats face, capturing the delicate details of its fur, and then gradually zooms out to reveal the full balcony scene, immersing viewers in a moment of calm and relaxation.
The theme of the creation is:%s
`

View File

@ -60,20 +60,15 @@ func (s *Service) Run() {
var jobs []model.VideoJob
s.db.Where("task_id", "").Where("progress", 0).Find(&jobs)
for _, v := range jobs {
var params types.VideoParams
if err := utils.JsonDecode(v.Params, &params); err != nil {
logger.Errorf("unmarshal params failed: %v", err)
var task types.VideoTask
err := utils.JsonDecode(v.TaskInfo, &task)
if err != nil {
logger.Errorf("decode task info with error: %v", err)
continue
}
s.PushTask(types.VideoTask{
Id: v.Id,
Channel: v.Channel,
UserId: v.UserId,
Type: v.Type,
TaskId: v.TaskId,
Prompt: v.Prompt,
Params: params,
})
task.Id = v.Id
s.PushTask(task)
s.clientIds[v.Id] = task.ClientId
}
logger.Info("Starting Video job consumer...")
go func() {

View File

@ -6,6 +6,7 @@ type DallJob struct {
Id uint `gorm:"primarykey;column:id"`
UserId uint
Prompt string
TaskInfo string // 原始任务信息
ImgURL string
OrgURL string
Publish bool

View File

@ -7,6 +7,7 @@ type MidJourneyJob struct {
Type string
UserId int
TaskId string
TaskInfo string // 原始任务信息
ChannelId string
MessageId string
ReferenceId string

View File

@ -9,6 +9,7 @@ type SunoJob struct {
Title string
Type int
TaskId string
TaskInfo string // 原始任务信息
RefTaskId string // 续写的任务id
Tags string // 歌曲风格和标签
Instrumental bool // 是否生成纯音乐

View File

@ -8,6 +8,7 @@ type VideoJob struct {
Channel string // 频道
Type string // luma,runway,cog
TaskId string
TaskInfo string // 原始任务信息
Prompt string // 提示词
PromptExt string // 优化后提示词
CoverURL string // 封面图 URL
@ -18,7 +19,6 @@ type VideoJob struct {
ErrMsg string // 错误信息
RawData string // 原始数据 json
Power int // 消耗算力
Params string // 任务参数
CreatedAt time.Time
}

View File

@ -1,7 +1,5 @@
package vo
import "geekai/core/types"
type VideoJob struct {
Id uint `json:"id"`
UserId int `json:"user_id"`
@ -18,6 +16,5 @@ type VideoJob struct {
ErrMsg string `json:"err_msg"` // 错误信息
RawData map[string]interface{} `json:"raw_data"` // 原始数据 json
Power int `json:"power"` // 消耗算力
Params types.VideoParams `json:"params"` // 任务参数
CreatedAt int64 `json:"created_at"`
}

View File

@ -1 +1,5 @@
ALTER TABLE `chatgpt_sd_jobs` ADD `task_info` TEXT NOT NULL COMMENT '任务详情' AFTER `task_id`;
ALTER TABLE `chatgpt_sd_jobs` ADD `task_info` TEXT NOT NULL COMMENT '任务详情' AFTER `task_id`;
ALTER TABLE `chatgpt_mj_jobs` ADD `task_info` TEXT NOT NULL COMMENT '任务详情' AFTER `task_id`;
ALTER TABLE `chatgpt_dall_jobs` ADD `task_info` TEXT NOT NULL COMMENT '任务详情' AFTER `prompt`;
ALTER TABLE `chatgpt_suno_jobs` ADD `task_info` TEXT NOT NULL COMMENT '任务详情' AFTER `task_id`;
ALTER TABLE `chatgpt_video_jobs` CHANGE `params` `task_info` TEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '原始任务信息' AFTER `task_id`;

View File

@ -473,8 +473,13 @@
padding 30px
}
}
}
.generate-btn {
.iconfont {
margin-right 5px
}
}
}
}
.mj-list-item-prompt {

View File

@ -1,8 +1,8 @@
@font-face {
font-family: "iconfont"; /* Project id 4125778 */
src: url('iconfont.woff2?t=1728891448746') format('woff2'),
url('iconfont.woff?t=1728891448746') format('woff'),
url('iconfont.ttf?t=1728891448746') format('truetype');
src: url('iconfont.woff2?t=1731289567907') format('woff2'),
url('iconfont.woff?t=1731289567907') format('woff'),
url('iconfont.ttf?t=1731289567907') format('truetype');
}
.iconfont {
@ -13,6 +13,14 @@
-moz-osx-font-smoothing: grayscale;
}
.icon-linggan:before {
content: "\e641";
}
.icon-chuangzuo:before {
content: "\e6cc";
}
.icon-call:before {
content: "\e769";
}

File diff suppressed because one or more lines are too long

View File

@ -5,6 +5,20 @@
"css_prefix_text": "icon-",
"description": "",
"glyphs": [
{
"icon_id": "15330210",
"name": "创意灵感",
"font_class": "linggan",
"unicode": "e641",
"unicode_decimal": 58945
},
{
"icon_id": "39170417",
"name": "创作",
"font_class": "chuangzuo",
"unicode": "e6cc",
"unicode_decimal": 59084
},
{
"icon_id": "11231556",
"name": "打电话",

Binary file not shown.

View File

@ -59,10 +59,17 @@
:autosize="{ minRows: 4, maxRows: 6 }"
type="textarea"
ref="promptRef"
placeholder="请在此输入绘画提示词,系统会自动翻译中文提示词,高手请直接输入英文提示词"
placeholder="请在此输入绘画提示词,您也可以点击下面的提示词助手生成绘画提示词"
/>
</div>
<el-row class="text-info">
<el-button class="generate-btn" size="small" @click="generatePrompt" color="#5865f2" :disabled="isGenerating">
<i class="iconfont icon-chuangzuo" style="margin-right: 5px"></i>
<span>生成专业绘画指令</span>
</el-button>
</el-row>
<div class="text-info">
<el-row :gutter="10">
<el-col :span="12">
@ -212,6 +219,7 @@ import {checkSession, getClientId, getSystemInfo} from "@/store/cache";
import {useSharedStore} from "@/store/sharedata";
import TaskList from "@/components/TaskList.vue";
import BackTop from "@/components/BackTop.vue";
import {showMessageError} from "@/utils/dialog";
const listBoxHeight = ref(0)
// const paramBoxHeight = ref(0)
@ -410,6 +418,21 @@ const publishImage = (item, action) => {
})
}
const isGenerating = ref(false)
const generatePrompt = () => {
if (params.value.prompt === "") {
return showMessageError("请输入原始提示词")
}
isGenerating.value = true
httpPost("/api/prompt/image", {prompt: params.value.prompt}).then(res => {
params.value.prompt = res.data
isGenerating.value = false
}).catch(e => {
showMessageError("生成提示词失败:"+e.message)
isGenerating.value = false
})
}
</script>
<style lang="stylus">

View File

@ -21,7 +21,6 @@
<div class="flex-col items-center"
:class="item.value === params.rate ? 'grid-content active' : 'grid-content'"
@click="changeRate(item)">
<!-- <div :class="'shape ' + item.css"></div>-->
<el-image class="icon" :src="item.img" fit="cover"></el-image>
<div class="text">{{ item.text }}</div>
</div>
@ -183,12 +182,19 @@
</div>
</div>
<div class="param-line pt">
<div class="param-line pt" style="position: relative">
<el-input v-model="params.prompt" :autosize="{ minRows: 4, maxRows: 6 }" type="textarea"
ref="promptRef"
placeholder="请在此输入绘画提示词,系统会自动翻译中文提示词,高手请直接输入英文提示词"/>
placeholder="请在此输入绘画提示词,您也可以点击下面的提示词助手生成绘画提示词"/>
</div>
<el-row class="text-info">
<el-button class="generate-btn" size="small" @click="generatePrompt" color="#5865f2" :disabled="isGenerating">
<i class="iconfont icon-chuangzuo"></i>
<span>生成专业绘画指令</span>
</el-button>
</el-row>
<div class="param-line pt">
<div class="flex-row justify-between items-center">
<div class="flex-row justify-start items-center">
@ -268,6 +274,13 @@
placeholder="请在此输入绘画提示词,系统会自动翻译中文提示词,高手请直接输入英文提示词"/>
</div>
<el-row class="text-info">
<el-button class="generate-btn" size="small" @click="generatePrompt" color="#5865f2" :disabled="isGenerating">
<i class="iconfont icon-chuangzuo"></i>
<span>生成专业绘画指令</span>
</el-button>
</el-row>
<div class="param-line pt">
<div class="flex-row justify-between items-center">
<div class="flex-row justify-start items-center">
@ -615,6 +628,7 @@ import {copyObj, removeArrayItem} from "@/utils/libs";
import {useSharedStore} from "@/store/sharedata";
import TaskList from "@/components/TaskList.vue";
import BackTop from "@/components/BackTop.vue";
import {showMessageError} from "@/utils/dialog";
const listBoxHeight = ref(0)
const paramBoxHeight = ref(0)
@ -644,10 +658,10 @@ const rates = [
{css: "size9-16", value: "9:16", text: "9:16", img: "/images/mj/rate_9_16.png"},
]
const models = [
{text: "写实模式MJ-6.0", value: " --v 6", img: "/images/mj/mj-v6.png"},
{text: "优质模式MJ-5.2", value: " --v 5.2", img: "/images/mj/mj-v5.2.png"},
{text: "优质模式MJ-5.1", value: " --v 5.1", img: "/images/mj/mj-v5.1.jpg"},
{text: "虚幻模式MJ-5", value: " --v 5", img: "/images/mj/mj-v5.jpg"},
{text: "写实模式MJ-6.1", value: " --v 6.1", img: "/images/mj/mj-v6.png"},
{text: "优质模式MJ-6.0", value: " --v 6", img: "/images/mj/mj-v5.2.png"},
{text: "优质模式MJ-5.2", value: " --v 5.2", img: "/images/mj/mj-v5.1.jpg"},
{text: "虚幻模式MJ-5.1", value: " --v 5.1", img: "/images/mj/mj-v5.jpg"},
{text: "真实模式MJ-4", value: " --v 4", img: "/images/mj/mj-v4.jpg"},
{text: "动漫风-niji4", value: " --niji 4", img: "/images/mj/nj4.jpg"},
{text: "动漫风-niji5", value: " --niji 5", img: "/images/mj/mj-niji.png"},
@ -820,7 +834,7 @@ const fetchFinishJobs = () => {
jobs[i]['thumb_url'] = '/images/img-placeholder.jpg'
}
if ((jobs[i].type === 'image' || jobs[i].type === 'variation') && jobs[i].progress === 100) {
if (jobs[i].type !== 'upscale' && jobs[i].progress === 100){
jobs[i]['can_opt'] = true
}
}
@ -999,6 +1013,21 @@ const removeUploadImage = (url) => {
imgList.value = removeArrayItem(imgList.value, url)
}
const isGenerating = ref(false)
const generatePrompt = () => {
if (params.value.prompt === "") {
return showMessageError("请输入原始提示词")
}
isGenerating.value = true
httpPost("/api/prompt/image", {prompt: params.value.prompt}).then(res => {
params.value.prompt = res.data
isGenerating.value = false
}).catch(e => {
showMessageError("生成提示词失败:"+e.message)
isGenerating.value = false
})
}
</script>
<style lang="stylus">

View File

@ -250,10 +250,17 @@
:autosize="{ minRows: 4, maxRows: 6 }"
type="textarea"
ref="promptRef"
placeholder="请在此输入绘画提示词,系统会自动翻译中文提示词,高手请直接输入英文提示词"
placeholder="请在此输入绘画提示词,您也可以点击下面的提示词助手生成绘画提示词"
/>
</div>
<el-row class="text-info">
<el-button class="generate-btn" size="small" @click="generatePrompt" color="#5865f2" :disabled="isGenerating">
<i class="iconfont icon-chuangzuo" style="margin-right: 5px"></i>
<span>生成专业绘画指令</span>
</el-button>
</el-row>
<div class="param-line pt">
<span>反向提示词</span>
<el-tooltip
@ -497,6 +504,7 @@ import {getSessionId} from "@/store/session";
import {useSharedStore} from "@/store/sharedata";
import TaskList from "@/components/TaskList.vue";
import BackTop from "@/components/BackTop.vue";
import {showMessageError} from "@/utils/dialog";
const listBoxHeight = ref(0)
// const paramBoxHeight = ref(0)
@ -722,6 +730,21 @@ const publishImage = (item, action) => {
})
}
const isGenerating = ref(false)
const generatePrompt = () => {
if (params.value.prompt === "") {
return showMessageError("请输入原始提示词")
}
isGenerating.value = true
httpPost("/api/prompt/image", {prompt: params.value.prompt}).then(res => {
params.value.prompt = res.data
isGenerating.value = false
}).catch(e => {
showMessageError("生成提示词失败:"+e.message)
isGenerating.value = false
})
}
</script>
<style lang="stylus">

View File

@ -38,6 +38,12 @@
</div>
<div class="params">
<div class="item-group">
<el-button class="generate-btn" size="small" @click="generatePrompt" color="#5865f2" :disabled="isGenerating">
<i class="iconfont icon-chuangzuo" style="margin-right: 5px"></i>
<span>生成AI视频提示词</span>
</el-button>
</div>
<div class="item-group">
<span class="label">循环参考图</span>
<el-switch v-model="formData.loop" size="small" style="--el-switch-on-color:#BF78BF;" />
@ -294,6 +300,20 @@ const create = () => {
})
}
const isGenerating = ref(false)
const generatePrompt = () => {
if (formData.prompt === "") {
return showMessageError("请输入原始提示词")
}
isGenerating.value = true
httpPost("/api/prompt/image", {prompt: formData.prompt}).then(res => {
formData.prompt = res.data
isGenerating.value = false
}).catch(e => {
showMessageError("生成提示词失败:"+e.message)
isGenerating.value = false
})
}
</script>

View File

@ -434,7 +434,7 @@ const fetchFinishJobs = (page) => {
jobs[i]['thumb_url'] = jobs[i]['img_url'] + '?imageView2/1/w/480/h/480/q/75'
}
if ((jobs[i].type === 'image' || jobs[i].type === 'variation') && jobs[i].progress === 100){
if (jobs[i].type !== 'upscale' && jobs[i].progress === 100){
jobs[i]['can_opt'] = true
}
}