diff --git a/api/core/types/task.go b/api/core/types/task.go index 36142736..cd4b516e 100644 --- a/api/core/types/task.go +++ b/api/core/types/task.go @@ -25,6 +25,7 @@ type MjTask struct { Type TaskType `json:"type"` UserId int `json:"user_id"` Prompt string `json:"prompt,omitempty"` + NegPrompt string `json:"neg_prompt,omitempty"` Params string `json:"full_prompt"` Index int `json:"index,omitempty"` MessageId string `json:"message_id,omitempty"` @@ -42,19 +43,19 @@ type SdTask struct { } type SdTaskParams struct { - TaskId string `json:"task_id"` - Prompt string `json:"prompt"` // 提示词 - NegativePrompt string `json:"negative_prompt"` // 反向提示词 - Steps int `json:"steps"` // 迭代步数,默认20 - Sampler string `json:"sampler"` // 采样器 - FaceFix bool `json:"face_fix"` // 面部修复 - CfgScale float32 `json:"cfg_scale"` //引导系数,默认 7 - Seed int64 `json:"seed"` // 随机数种子 - Height int `json:"height"` - Width int `json:"width"` - HdFix bool `json:"hd_fix"` // 启用高清修复 - HdRedrawRate float32 `json:"hd_redraw_rate"` // 高清修复重绘幅度 - HdScale int `json:"hd_scale"` // 放大倍数 - HdScaleAlg string `json:"hd_scale_alg"` // 放大算法 - HdSteps int `json:"hd_steps"` // 高清修复迭代步数 + TaskId string `json:"task_id"` + Prompt string `json:"prompt"` // 提示词 + NegPrompt string `json:"neg_prompt"` // 反向提示词 + Steps int `json:"steps"` // 迭代步数,默认20 + Sampler string `json:"sampler"` // 采样器 + FaceFix bool `json:"face_fix"` // 面部修复 + CfgScale float32 `json:"cfg_scale"` //引导系数,默认 7 + Seed int64 `json:"seed"` // 随机数种子 + Height int `json:"height"` + Width int `json:"width"` + HdFix bool `json:"hd_fix"` // 启用高清修复 + HdRedrawRate float32 `json:"hd_redraw_rate"` // 高清修复重绘幅度 + HdScale int `json:"hd_scale"` // 放大倍数 + HdScaleAlg string `json:"hd_scale_alg"` // 放大算法 + HdSteps int `json:"hd_steps"` // 高清修复迭代步数 } diff --git a/api/handler/mj_handler.go b/api/handler/mj_handler.go index 5ca0bcb5..7988a380 100644 --- a/api/handler/mj_handler.go +++ b/api/handler/mj_handler.go @@ -133,9 +133,6 @@ func (h *MidJourneyHandler) Image(c *gin.Context) { if data.Quality > 0 { params += fmt.Sprintf(" --q %.2f", data.Quality) } - if data.NegPrompt != "" { - params += fmt.Sprintf(" --no %s", data.NegPrompt) - } if data.Tile { params += " --tile " } @@ -204,6 +201,7 @@ func (h *MidJourneyHandler) Image(c *gin.Context) { SessionId: data.SessionId, Type: types.TaskType(data.TaskType), Prompt: data.Prompt, + NegPrompt: data.NegPrompt, Params: params, UserId: userId, ImgArr: data.ImgArr, diff --git a/api/handler/payment_handler.go b/api/handler/payment_handler.go index 3f888c83..2b8f5dce 100644 --- a/api/handler/payment_handler.go +++ b/api/handler/payment_handler.go @@ -424,27 +424,21 @@ func (h *PaymentHandler) notify(orderNo string, tradeNo string) error { var opt string var power int - if user.Vip { // 已经是 VIP 用户 - if remark.Days > 0 { // 只延期 VIP,不增加调用次数 + if remark.Days > 0 { // VIP 充值 + if user.ExpiredTime >= time.Now().Unix() { user.ExpiredTime = time.Unix(user.ExpiredTime, 0).AddDate(0, 0, remark.Days).Unix() - } else { // 充值点卡,直接增加次数即可 - user.Power += remark.Power - opt = "点卡充值" - power = remark.Power - } - - } else { // 非 VIP 用户 - if remark.Days > 0 { // vip 套餐:days > 0, power == 0 + opt = "VIP充值,VIP 没到期,只延期不增加算力" + } else { user.ExpiredTime = time.Now().AddDate(0, 0, remark.Days).Unix() user.Power += h.App.SysConfig.VipMonthPower - user.Vip = true - opt = "VIP充值" power = h.App.SysConfig.VipMonthPower - } else { //点卡:days == 0, calls > 0 - user.Power += remark.Power - opt = "点卡充值" - power = remark.Power + opt = "VIP充值" } + user.Vip = true + } else { // 充值点卡,直接增加次数即可 + user.Power += remark.Power + opt = "点卡充值" + power = remark.Power } // 更新用户信息 diff --git a/api/handler/sd_handler.go b/api/handler/sd_handler.go index ca1e9650..b9c3625e 100644 --- a/api/handler/sd_handler.go +++ b/api/handler/sd_handler.go @@ -127,21 +127,21 @@ func (h *SdJobHandler) Image(c *gin.Context) { return } params := types.SdTaskParams{ - TaskId: taskId, - Prompt: data.Prompt, - NegativePrompt: data.NegativePrompt, - Steps: data.Steps, - Sampler: data.Sampler, - FaceFix: data.FaceFix, - CfgScale: data.CfgScale, - Seed: data.Seed, - Height: data.Height, - Width: data.Width, - HdFix: data.HdFix, - HdRedrawRate: data.HdRedrawRate, - HdScale: data.HdScale, - HdScaleAlg: data.HdScaleAlg, - HdSteps: data.HdSteps, + TaskId: taskId, + Prompt: data.Prompt, + NegPrompt: data.NegPrompt, + Steps: data.Steps, + Sampler: data.Sampler, + FaceFix: data.FaceFix, + CfgScale: data.CfgScale, + Seed: data.Seed, + Height: data.Height, + Width: data.Width, + HdFix: data.HdFix, + HdRedrawRate: data.HdRedrawRate, + HdScale: data.HdScale, + HdScaleAlg: data.HdScaleAlg, + HdSteps: data.HdSteps, } job := model.SdJob{ diff --git a/api/service/mj/plus_client.go b/api/service/mj/plus_client.go index 31029a22..89bca627 100644 --- a/api/service/mj/plus_client.go +++ b/api/service/mj/plus_client.go @@ -8,6 +8,7 @@ import ( "fmt" "github.com/imroc/req/v3" "io" + "time" "github.com/gin-gonic/gin" ) @@ -16,17 +17,26 @@ import ( type PlusClient struct { Config types.MjPlusConfig apiURL string + client *req.Client } func NewPlusClient(config types.MjPlusConfig) *PlusClient { - return &PlusClient{Config: config, apiURL: config.ApiURL} + return &PlusClient{ + Config: config, + apiURL: config.ApiURL, + client: req.C().SetTimeout(time.Minute).SetUserAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36"), + } } func (c *PlusClient) Imagine(task types.MjTask) (ImageRes, error) { apiURL := fmt.Sprintf("%s/mj-%s/mj/submit/imagine", c.apiURL, c.Config.Mode) + prompt := fmt.Sprintf("%s %s", task.Prompt, task.Params) + if task.NegPrompt != "" { + prompt += fmt.Sprintf(" --no %s", task.NegPrompt) + } body := ImageReq{ BotType: "MID_JOURNEY", - Prompt: fmt.Sprintf("%s %s", task.Prompt, task.Params), + Prompt: prompt, Base64Array: make([]string, 0), } // 生成图片 Base64 编码 @@ -42,7 +52,7 @@ func (c *PlusClient) Imagine(task types.MjTask) (ImageRes, error) { logger.Info("API URL: ", apiURL) var res ImageRes var errRes ErrRes - r, err := req.C().R(). + r, err := c.client.R(). SetHeader("Authorization", "Bearer "+c.Config.ApiKey). SetBody(body). SetSuccessResult(&res). @@ -81,7 +91,7 @@ func (c *PlusClient) Blend(task types.MjTask) (ImageRes, error) { } var res ImageRes var errRes ErrRes - r, err := req.C().R(). + r, err := c.client.R(). SetHeader("Authorization", "Bearer "+c.Config.ApiKey). SetBody(body). SetSuccessResult(&res). @@ -130,7 +140,7 @@ func (c *PlusClient) SwapFace(task types.MjTask) (ImageRes, error) { } var res ImageRes var errRes ErrRes - r, err := req.C().R(). + r, err := c.client.SetTimeout(time.Minute).R(). SetHeader("Authorization", "Bearer "+c.Config.ApiKey). SetBody(body). SetSuccessResult(&res). @@ -156,7 +166,7 @@ func (c *PlusClient) Upscale(task types.MjTask) (ImageRes, error) { apiURL := fmt.Sprintf("%s/mj/submit/action", c.apiURL) var res ImageRes var errRes ErrRes - r, err := req.C().R(). + r, err := c.client.R(). SetHeader("Authorization", "Bearer "+c.Config.ApiKey). SetBody(body). SetSuccessResult(&res). @@ -202,7 +212,7 @@ func (c *PlusClient) Variation(task types.MjTask) (ImageRes, error) { func (c *PlusClient) QueryTask(taskId string) (QueryRes, error) { apiURL := fmt.Sprintf("%s/mj/task/%s/fetch", c.apiURL, taskId) var res QueryRes - r, err := req.C().R().SetHeader("Authorization", "Bearer "+c.Config.ApiKey). + r, err := c.client.R().SetHeader("Authorization", "Bearer "+c.Config.ApiKey). SetSuccessResult(&res). Get(apiURL) diff --git a/api/service/mj/proxy_client.go b/api/service/mj/proxy_client.go index 41bb31d1..b8df3211 100644 --- a/api/service/mj/proxy_client.go +++ b/api/service/mj/proxy_client.go @@ -22,8 +22,12 @@ func NewProxyClient(config types.MjProxyConfig) *ProxyClient { func (c *ProxyClient) Imagine(task types.MjTask) (ImageRes, error) { apiURL := fmt.Sprintf("%s/mj/submit/imagine", c.apiURL) + prompt := fmt.Sprintf("%s %s", task.Prompt, task.Params) + if task.NegPrompt != "" { + prompt += fmt.Sprintf(" --no %s", task.NegPrompt) + } body := ImageReq{ - Prompt: fmt.Sprintf("%s %s", task.Prompt, task.Params), + Prompt: prompt, Base64Array: make([]string, 0), } // 生成图片 Base64 编码 diff --git a/api/service/mj/service.go b/api/service/mj/service.go index 17ffe454..3c870a17 100644 --- a/api/service/mj/service.go +++ b/api/service/mj/service.go @@ -67,7 +67,7 @@ func (s *Service) Run() { continue } - // 如果是 mj-proxy 则自动翻译提示词 + // translate prompt if utils.HasChinese(task.Prompt) { content, err := utils.OpenAIRequest(s.db, fmt.Sprintf(service.TranslatePromptTemplate, task.Prompt)) if err == nil { @@ -76,6 +76,15 @@ func (s *Service) Run() { logger.Warnf("error with translate prompt: %v", err) } } + // translate negative prompt + if task.NegPrompt != "" && utils.HasChinese(task.NegPrompt) { + content, err := utils.OpenAIRequest(s.db, fmt.Sprintf(service.TranslatePromptTemplate, task.NegPrompt)) + if err == nil { + task.NegPrompt = content + } else { + logger.Warnf("error with translate prompt: %v", err) + } + } var job model.MidJourneyJob tx := s.db.Where("id = ?", task.Id).First(&job) diff --git a/api/service/sd/service.go b/api/service/sd/service.go index b2baccca..4f68f3e0 100644 --- a/api/service/sd/service.go +++ b/api/service/sd/service.go @@ -49,11 +49,24 @@ func (s *Service) Run() { logger.Errorf("taking task with error: %v", err) continue } - // 翻译提示词 + + // translate prompt if utils.HasChinese(task.Params.Prompt) { content, err := utils.OpenAIRequest(s.db, fmt.Sprintf(service.RewritePromptTemplate, task.Params.Prompt)) if err == nil { task.Params.Prompt = content + } else { + logger.Warnf("error with translate prompt: %v", err) + } + } + + // translate negative prompt + if task.Params.NegPrompt != "" && utils.HasChinese(task.Params.NegPrompt) { + content, err := utils.OpenAIRequest(s.db, fmt.Sprintf(service.TranslatePromptTemplate, task.Params.NegPrompt)) + if err == nil { + task.Params.NegPrompt = content + } else { + logger.Warnf("error with translate prompt: %v", err) } } @@ -110,7 +123,7 @@ type TaskProgressResp struct { func (s *Service) Txt2Img(task types.SdTask) error { body := Txt2ImgReq{ Prompt: task.Params.Prompt, - NegativePrompt: task.Params.NegativePrompt, + NegativePrompt: task.Params.NegPrompt, Steps: task.Params.Steps, CfgScale: task.Params.CfgScale, Width: task.Params.Width, diff --git a/web/src/assets/css/mobile/image-mj.css b/web/src/assets/css/mobile/image-mj.css index 839ba770..15db23df 100644 --- a/web/src/assets/css/mobile/image-mj.css +++ b/web/src/assets/css/mobile/image-mj.css @@ -1,8 +1,8 @@ -.mobile-mj .content .text-line { +.mobile-mj .text-line { padding: 6px; font-size: 14px; } -.mobile-mj .content .text-line .van-row .van-col .rate { +.mobile-mj .text-line .van-row .van-col .rate { display: flex; justify-content: center; background-color: #f5f5f5; @@ -11,17 +11,17 @@ border-radius: 5px; flex-flow: column; } -.mobile-mj .content .text-line .van-row .van-col .rate .icon { +.mobile-mj .text-line .van-row .van-col .rate .icon { text-align: center; } -.mobile-mj .content .text-line .van-row .van-col .rate .icon .van-image { +.mobile-mj .text-line .van-row .van-col .rate .icon .van-image { max-width: 20px; } -.mobile-mj .content .text-line .van-row .van-col .rate .text { +.mobile-mj .text-line .van-row .van-col .rate .text { text-align: center; color: #555; } -.mobile-mj .content .text-line .van-row .van-col .model { +.mobile-mj .text-line .van-row .van-col .model { display: flex; justify-content: center; background-color: #f5f5f5; @@ -30,45 +30,45 @@ border-radius: 5px; flex-flow: column; } -.mobile-mj .content .text-line .van-row .van-col .model .icon { +.mobile-mj .text-line .van-row .van-col .model .icon { text-align: center; } -.mobile-mj .content .text-line .van-row .van-col .model .icon .van-image { +.mobile-mj .text-line .van-row .van-col .model .icon .van-image { width: 100%; height: 50px; } -.mobile-mj .content .text-line .van-row .van-col .model .text { +.mobile-mj .text-line .van-row .van-col .model .text { text-align: center; color: #555; } -.mobile-mj .content .text-line .van-row .van-col .active { +.mobile-mj .text-line .van-row .van-col .active { background-color: #e5e5e5; } -.mobile-mj .content .text-line .van-button { +.mobile-mj .text-line .van-button { position: relative; } -.mobile-mj .content .text-line .van-button .van-tag { +.mobile-mj .text-line .van-button .van-tag { position: absolute; right: 20px; } -.mobile-mj .content .text-line .align-right { +.mobile-mj .text-line .align-right { display: flex; justify-content: right; } -.mobile-mj .content .tip-text { +.mobile-mj .tip-text { padding: 10px; line-height: 1.5; color: #c1c1c1; } -.mobile-mj .content .running-job-list .van-grid .van-grid-item .van-grid-item__content { +.mobile-mj .running-job-list .van-grid .van-grid-item .van-grid-item__content { padding: 0; position: relative; } -.mobile-mj .content .running-job-list .van-grid .van-grid-item .van-grid-item__content .van-image, -.mobile-mj .content .running-job-list .van-grid .van-grid-item .van-grid-item__content .task-in-queue { +.mobile-mj .running-job-list .van-grid .van-grid-item .van-grid-item__content .van-image, +.mobile-mj .running-job-list .van-grid .van-grid-item .van-grid-item__content .task-in-queue { min-height: 100px; } -.mobile-mj .content .running-job-list .van-grid .van-grid-item .van-grid-item__content .progress { +.mobile-mj .running-job-list .van-grid .van-grid-item .van-grid-item__content .progress { display: flex; justify-content: center; align-items: center; @@ -79,36 +79,36 @@ left: 0; top: 0; } -.mobile-mj .content .running-job-list .van-grid .van-grid-item .van-grid-item__content .progress .van-circle__text { +.mobile-mj .running-job-list .van-grid .van-grid-item .van-grid-item__content .progress .van-circle__text { color: #fff; } -.mobile-mj .content .running-job-list .van-grid .van-grid-item .van-grid-item__content .task-in-queue { +.mobile-mj .running-job-list .van-grid .van-grid-item .van-grid-item__content .task-in-queue { display: flex; flex-flow: column; justify-content: center; color: #c1c1c1; } -.mobile-mj .content .running-job-list .van-grid .van-grid-item .van-grid-item__content .task-in-queue .icon { +.mobile-mj .running-job-list .van-grid .van-grid-item .van-grid-item__content .task-in-queue .icon { text-align: center; } -.mobile-mj .content .running-job-list .van-grid .van-grid-item .van-grid-item__content .task-in-queue .icon .iconfont { +.mobile-mj .running-job-list .van-grid .van-grid-item .van-grid-item__content .task-in-queue .icon .iconfont { font-size: 24px; } -.mobile-mj .content .running-job-list .van-grid .van-grid-item .van-grid-item__content .task-in-queue .text { +.mobile-mj .running-job-list .van-grid .van-grid-item .van-grid-item__content .task-in-queue .text { font-size: 14px; margin-top: 5px; } -.mobile-mj .content .finish-job-list .van-grid .van-grid-item .van-grid-item__content { +.mobile-mj .finish-job-list .van-grid .van-grid-item .van-grid-item__content { padding: 0; } -.mobile-mj .content .finish-job-list .van-grid .van-grid-item .van-grid-item__content .job-item { +.mobile-mj .finish-job-list .van-grid .van-grid-item .van-grid-item__content .job-item { overflow: hidden; border-radius: 6px; position: relative; height: 100%; width: 100%; } -.mobile-mj .content .finish-job-list .van-grid .van-grid-item .van-grid-item__content .job-item .opt .opt-btn { +.mobile-mj .finish-job-list .van-grid .van-grid-item .van-grid-item__content .job-item .opt .opt-btn { padding: 2px 0; text-align: center; border-radius: 5px; @@ -120,20 +120,20 @@ font-size: 14px; width: 100%; } -.mobile-mj .content .finish-job-list .van-grid .van-grid-item .van-grid-item__content .job-item .van-image { +.mobile-mj .finish-job-list .van-grid .van-grid-item .van-grid-item__content .job-item .van-image { width: 100%; height: 200px; } -.mobile-mj .content .finish-job-list .van-grid .van-grid-item .van-grid-item__content .job-item .upscale { +.mobile-mj .finish-job-list .van-grid .van-grid-item .van-grid-item__content .job-item .upscale { height: 260px; width: 100%; } -.mobile-mj .content .finish-job-list .van-grid .van-grid-item .van-grid-item__content .job-item .remove { +.mobile-mj .finish-job-list .van-grid .van-grid-item .van-grid-item__content .job-item .remove { position: absolute; right: 5px; top: 5px; } -.mobile-mj .content .finish-job-list .van-grid .van-grid-item .van-grid-item__content .job-item .remove .el-button { +.mobile-mj .finish-job-list .van-grid .van-grid-item .van-grid-item__content .job-item .remove .el-button { margin-left: 5px; height: auto; padding: 5px; diff --git a/web/src/assets/css/mobile/image-mj.styl b/web/src/assets/css/mobile/image-mj.styl index acdbd38f..76022f0f 100644 --- a/web/src/assets/css/mobile/image-mj.styl +++ b/web/src/assets/css/mobile/image-mj.styl @@ -1,194 +1,192 @@ .mobile-mj { - .content { - .text-line { - padding 6px - font-size 14px + .text-line { + padding 6px + font-size 14px - .van-row { - .van-col { - .rate { - display: flex; + .van-row { + .van-col { + .rate { + display: flex; + justify-content center + background-color #f5f5f5 + padding 5px 10px + margin 5px 0 + border-radius 5px + flex-flow column + + .icon { + text-align center + + .van-image { + max-width 20px + } + } + + .text { + text-align center + color #555555 + } + } + + .model { + display: flex; + justify-content center + background-color #f5f5f5 + padding 6px + margin 5px 0 + border-radius 5px + flex-flow column + + .icon { + text-align center + + .van-image { + width 100% + height 50px + } + } + + .text { + text-align center + color #555555 + } + } + + .active { + background-color #e5e5e5 + } + } + } + + .van-button { + position relative + + .van-tag { + position absolute + right 20px + } + } + + .align-right { + display flex + justify-content right + } + } + + + .tip-text { + padding 10px + line-height 1.5 + color #c1c1c1 + } + + .running-job-list { + .van-grid { + .van-grid-item { + .van-grid-item__content { + padding 0 + position relative + + .van-image, .task-in-queue { + min-height 100px + } + + .progress { + display flex justify-content center - background-color #f5f5f5 - padding 5px 10px - margin 5px 0 - border-radius 5px + align-items center + width 100% + height 100% + background rgba(50, 50, 50, 0.5) + position absolute + left 0 + top 0 + + .van-circle__text { + color #ffffff + } + } + + // end progress + + .task-in-queue { + display flex flex-flow column + justify-content center + color #c1c1c1 .icon { text-align center - .van-image { - max-width 20px + .iconfont { + font-size 24px } } .text { - text-align center - color #555555 + font-size 14px + margin-top 5px } } - - .model { - display: flex; - justify-content center - background-color #f5f5f5 - padding 6px - margin 5px 0 - border-radius 5px - flex-flow column - - .icon { - text-align center - - .van-image { - width 100% - height 50px - } - } - - .text { - text-align center - color #555555 - } - } - - .active { - background-color #e5e5e5 - } - } - } - - .van-button { - position relative - - .van-tag { - position absolute - right 20px - } - } - - .align-right { - display flex - justify-content right - } - } - - - .tip-text { - padding 10px - line-height 1.5 - color #c1c1c1 - } - - .running-job-list { - .van-grid { - .van-grid-item { - .van-grid-item__content { - padding 0 - position relative - - .van-image, .task-in-queue { - min-height 100px - } - - .progress { - display flex - justify-content center - align-items center - width 100% - height 100% - background rgba(50, 50, 50, 0.5) - position absolute - left 0 - top 0 - - .van-circle__text { - color #ffffff - } - } - - // end progress - - .task-in-queue { - display flex - flex-flow column - justify-content center - color #c1c1c1 - - .icon { - text-align center - - .iconfont { - font-size 24px - } - } - - .text { - font-size 14px - margin-top 5px - } - } - } - } - } - } - - //end running jobs - - .finish-job-list { - .van-grid { - .van-grid-item { - .van-grid-item__content { - padding 0 - - .job-item { - overflow hidden - border-radius 6px - position relative - height 100% - width 100% - - .opt { - .opt-btn { - padding 2px 0 - text-align center - border-radius 5px - margin 3px 0 - display block - cursor pointer - background-color #4E5058 - color #ffffff - font-size 14px - width 100% - } - } - - .van-image { - width 100% - height 200px - } - - .upscale { - height 260px - width 100% - } - - .remove { - position absolute - right 5px - top 5px - - .el-button { - margin-left 5px - height auto - padding 5px - } - } - } - - - } + } + } + } + } + + //end running jobs + + .finish-job-list { + .van-grid { + .van-grid-item { + .van-grid-item__content { + padding 0 + + .job-item { + overflow hidden + border-radius 6px + position relative + height 100% + width 100% + + .opt { + .opt-btn { + padding 2px 0 + text-align center + border-radius 5px + margin 3px 0 + display block + cursor pointer + background-color #4E5058 + color #ffffff + font-size 14px + width 100% + } + } + + .van-image { + width 100% + height 200px + } + + .upscale { + height 260px + width 100% + } + + .remove { + position absolute + right 5px + top 5px + + .el-button { + margin-left 5px + height auto + padding 5px + } + } + } + + } } } diff --git a/web/src/assets/css/mobile/image-sd.css b/web/src/assets/css/mobile/image-sd.css new file mode 100644 index 00000000..0189f1ac --- /dev/null +++ b/web/src/assets/css/mobile/image-sd.css @@ -0,0 +1,133 @@ +.mobile-sd .text-line { + padding: 0 6px; + font-size: 14px; +} +.mobile-sd .text-line .van-row { + width: 100%; +} +.mobile-sd .text-line .van-row .van-col .rate { + display: flex; + justify-content: center; + background-color: #f5f5f5; + padding: 5px 10px; + margin: 5px 0; + border-radius: 5px; + flex-flow: column; +} +.mobile-sd .text-line .van-row .van-col .rate .icon { + text-align: center; +} +.mobile-sd .text-line .van-row .van-col .rate .icon .van-image { + max-width: 20px; +} +.mobile-sd .text-line .van-row .van-col .rate .text { + text-align: center; + color: #555; +} +.mobile-sd .text-line .van-row .van-col .el-input__inner { + text-align: center; +} +.mobile-sd .text-line .van-row .van-col .model { + display: flex; + justify-content: center; + background-color: #f5f5f5; + padding: 6px; + margin: 5px 0; + border-radius: 5px; + flex-flow: column; +} +.mobile-sd .text-line .van-row .van-col .model .icon { + text-align: center; +} +.mobile-sd .text-line .van-row .van-col .model .icon .van-image { + width: 100%; + height: 50px; +} +.mobile-sd .text-line .van-row .van-col .model .text { + text-align: center; + color: #555; +} +.mobile-sd .text-line .van-row .van-col .active { + background-color: #e5e5e5; +} +.mobile-sd .text-line .van-button { + position: relative; +} +.mobile-sd .text-line .van-button .van-tag { + position: absolute; + right: 20px; +} +.mobile-sd .text-line .align-right { + display: flex; + justify-content: right; +} +.mobile-sd .pt-6 { + padding: 10px; +} +.mobile-sd .tip-text { + padding: 10px; + line-height: 1.5; + color: #c1c1c1; +} +.mobile-sd .running-job-list .van-grid .van-grid-item .van-grid-item__content { + padding: 0; + position: relative; +} +.mobile-sd .running-job-list .van-grid .van-grid-item .van-grid-item__content .van-image, +.mobile-sd .running-job-list .van-grid .van-grid-item .van-grid-item__content .task-in-queue { + min-height: 100px; +} +.mobile-sd .running-job-list .van-grid .van-grid-item .van-grid-item__content .progress { + display: flex; + justify-content: center; + align-items: center; + width: 100%; + height: 100%; + background: rgba(50,50,50,0.5); + position: absolute; + left: 0; + top: 0; +} +.mobile-sd .running-job-list .van-grid .van-grid-item .van-grid-item__content .progress .van-circle__text { + color: #fff; +} +.mobile-sd .running-job-list .van-grid .van-grid-item .van-grid-item__content .task-in-queue { + display: flex; + flex-flow: column; + justify-content: center; + color: #c1c1c1; +} +.mobile-sd .running-job-list .van-grid .van-grid-item .van-grid-item__content .task-in-queue .icon { + text-align: center; +} +.mobile-sd .running-job-list .van-grid .van-grid-item .van-grid-item__content .task-in-queue .icon .iconfont { + font-size: 24px; +} +.mobile-sd .running-job-list .van-grid .van-grid-item .van-grid-item__content .task-in-queue .text { + font-size: 14px; + margin-top: 5px; +} +.mobile-sd .finish-job-list .van-grid .van-grid-item .van-grid-item__content { + padding: 0; +} +.mobile-sd .finish-job-list .van-grid .van-grid-item .van-grid-item__content .job-item { + overflow: hidden; + border-radius: 6px; + position: relative; + height: 100%; + width: 100%; +} +.mobile-sd .finish-job-list .van-grid .van-grid-item .van-grid-item__content .job-item .van-image { + width: 100%; + height: 200px; +} +.mobile-sd .finish-job-list .van-grid .van-grid-item .van-grid-item__content .job-item .remove { + position: absolute; + right: 5px; + top: 5px; +} +.mobile-sd .finish-job-list .van-grid .van-grid-item .van-grid-item__content .job-item .remove .el-button { + margin-left: 5px; + height: auto; + padding: 5px; +} diff --git a/web/src/assets/css/mobile/image-sd.styl b/web/src/assets/css/mobile/image-sd.styl new file mode 100644 index 00000000..d5c1a1b8 --- /dev/null +++ b/web/src/assets/css/mobile/image-sd.styl @@ -0,0 +1,184 @@ +.mobile-sd { + .text-line { + padding 0 6px + font-size 14px + + .van-row { + width 100% + + .van-col { + .rate { + display: flex; + justify-content center + background-color #f5f5f5 + padding 5px 10px + margin 5px 0 + border-radius 5px + flex-flow column + + .icon { + text-align center + + .van-image { + max-width 20px + } + } + + .text { + text-align center + color #555555 + } + } + + .el-input__inner { + text-align center + } + + .model { + display: flex; + justify-content center + background-color #f5f5f5 + padding 6px + margin 5px 0 + border-radius 5px + flex-flow column + + .icon { + text-align center + + .van-image { + width 100% + height 50px + } + } + + .text { + text-align center + color #555555 + } + } + + .active { + background-color #e5e5e5 + } + } + } + + .van-button { + position relative + + .van-tag { + position absolute + right 20px + } + } + + .align-right { + display flex + justify-content right + } + } + + + .pt-6 { + padding 10px + } + + .tip-text { + padding 10px + line-height 1.5 + color #c1c1c1 + } + + .running-job-list { + .van-grid { + .van-grid-item { + .van-grid-item__content { + padding 0 + position relative + + .van-image, .task-in-queue { + min-height 100px + } + + .progress { + display flex + justify-content center + align-items center + width 100% + height 100% + background rgba(50, 50, 50, 0.5) + position absolute + left 0 + top 0 + + .van-circle__text { + color #ffffff + } + } + + // end progress + + .task-in-queue { + display flex + flex-flow column + justify-content center + color #c1c1c1 + + .icon { + text-align center + + .iconfont { + font-size 24px + } + } + + .text { + font-size 14px + margin-top 5px + } + } + } + } + } + } + + //end running jobs + + .finish-job-list { + .van-grid { + .van-grid-item { + .van-grid-item__content { + padding 0 + + .job-item { + overflow hidden + border-radius 6px + position relative + height 100% + width 100% + + .van-image { + width 100% + height 200px + } + + .remove { + position absolute + right 5px + top 5px + + .el-button { + margin-left 5px + height auto + padding 5px + } + } + } + + + } + } + } + } +} \ No newline at end of file diff --git a/web/src/router.js b/web/src/router.js index 968b0690..b17f6c51 100644 --- a/web/src/router.js +++ b/web/src/router.js @@ -181,7 +181,7 @@ const routes = [ { name: 'mobile', path: '/mobile', - meta: {title: 'ChatPlus-智能助手V3'}, + meta: {title: 'Geek-AI v4.0'}, component: () => import('@/views/mobile/Home.vue'), redirect: '/mobile/chat', children: [ @@ -191,9 +191,9 @@ const routes = [ component: () => import('@/views/mobile/ChatList.vue'), }, { - path: '/mobile/mj', - name: 'mobile-mj', - component: () => import('@/views/mobile/ImageMj.vue'), + path: '/mobile/image', + name: 'mobile-image', + component: () => import('@/views/mobile/Image.vue'), }, { path: '/mobile/profile', diff --git a/web/src/views/ImageMj.vue b/web/src/views/ImageMj.vue index 868268bb..a34d729d 100644 --- a/web/src/views/ImageMj.vue +++ b/web/src/views/ImageMj.vue @@ -309,7 +309,7 @@ -
请上传两张有脸部的图片,用右边图片的脸替换左边图片的脸
+
请上传两张有脸部的图片,用左边图片的脸替换右边图片的脸
@@ -334,7 +334,7 @@ -
注意:只有于 niji6 和 v6 模型支持一致性功能,如果选择其他模型此功能将不起作用。
+
注意:只有于 niji6 和 v6 模型支持一致性功能,如果选择其他模型此功能将会生成失败。
-
+
- {{ item.params.negative_prompt }} - + {{ item.params.neg_prompt }} +
@@ -496,7 +496,6 @@ const mjBoxHeight = ref(window.innerHeight - 150) const fullImgHeight = ref(window.innerHeight - 60) const showTaskDialog = ref(false) const item = ref({}) -const translating = ref(false) const showLoginDialog = ref(false) const isLogin = ref(false) @@ -519,7 +518,7 @@ const params = ref({ hd_scale_alg: scaleAlg[0], hd_steps: 0, prompt: "", - negative_prompt: "nsfw, paintings,low quality,easynegative,ng_deepnegative ,lowres,bad anatomy,bad hands,bad feet", + neg_prompt: "nsfw, paintings,low quality,easynegative,ng_deepnegative ,lowres,bad anatomy,bad hands,bad feet", }) const runningJobs = ref([]) @@ -559,7 +558,7 @@ const connect = () => { }); } - const _socket = new WebSocket(host + `/api/sd/client`); + const _socket = new WebSocket(host + `/api/sd/client?user_id=${userId.value}`); _socket.addEventListener('open', () => { socket.value = _socket; diff --git a/web/src/views/mobile/Home.vue b/web/src/views/mobile/Home.vue index b056fb7b..f500a301 100644 --- a/web/src/views/mobile/Home.vue +++ b/web/src/views/mobile/Home.vue @@ -5,7 +5,7 @@ 对话 - 绘图 + 绘图 广场 我的 @@ -64,6 +64,11 @@ const onChange = (index) => { color #f56c6c } +.van-toast--success { + background #D6FBCC + color #07C160 +} + .van-nav-bar { position fixed width 100% diff --git a/web/src/views/mobile/Image.vue b/web/src/views/mobile/Image.vue new file mode 100644 index 00000000..08ac7d6f --- /dev/null +++ b/web/src/views/mobile/Image.vue @@ -0,0 +1,33 @@ + + + + + \ No newline at end of file diff --git a/web/src/views/mobile/ImageMj.vue b/web/src/views/mobile/ImageMj.vue index 33a02f8b..bd08e494 100644 --- a/web/src/views/mobile/ImageMj.vue +++ b/web/src/views/mobile/ImageMj.vue @@ -1,278 +1,275 @@ @@ -289,13 +286,11 @@ import { } from "vant"; import {httpGet, httpPost} from "@/utils/http"; import Compressor from "compressorjs"; -import {ElMessage} from "element-plus"; import {getSessionId} from "@/store/session"; import {checkSession} from "@/action/session"; import {useRouter} from "vue-router"; import {Delete} from "@element-plus/icons-vue"; -const title = ref('MidJourney 绘画') const activeColspan = ref([""]) const rates = [ @@ -309,10 +304,10 @@ const rates = [ 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: "Niji5 原始", value: " --niji 5", img: "/images/mj/mj-niji.png"}, + {text: "Niji5", value: " --niji 5", img: "/images/mj/mj-niji.png"}, {text: "Niji5 可爱", value: " --niji 5 --style cute", img: "/images/mj/nj1.jpg"}, {text: "Niji5 风景", value: " --niji 5 --style scenic", img: "/images/mj/nj2.jpg"}, - {text: "Niji5 表现力", value: " --niji 5 --style expressive", img: "/images/mj/nj3.jpg"}, + {text: "Niji6", value: " --niji 6", img: "/images/mj/nj3.jpg"}, ] const imgList = ref([]) const params = ref({ @@ -365,7 +360,7 @@ httpGet("/api/config/get?key=system").then(res => { mjPower.value = res.data["mj_power"] mjActionPower.value = res.data["mj_action_power"] }).catch(e => { - ElMessage.error("获取系统配置失败:" + e.message) + showNotify({type: "danger", message: "获取系统配置失败:" + e.message}) }) const heartbeatHandle = ref(null) @@ -436,7 +431,7 @@ const fetchRunningJobs = (userId) => { } runningJobs.value = _jobs }).catch(e => { - ElMessage.error("获取任务失败:" + e.message) + showNotify({type: "danger", message: "获取任务失败:" + e.message}) }) } @@ -451,6 +446,19 @@ const fetchFinishJobs = (page) => { httpGet(`/api/mj/jobs?status=1&page=${page}&page_size=${pageSize.value}`).then(res => { const jobs = res.data for (let i = 0; i < jobs.length; i++) { + if (jobs[i].progress === -1) { + showNotify({ + message: `任务ID:${jobs[i]['task_id']} 原因:${jobs[i]['err_msg']}`, + type: 'danger', + }) + if (jobs[i].type === 'image') { + power.value += mjPower.value + } else { + power.value += mjActionPower.value + } + continue + } + if (jobs[i]['use_proxy']) { jobs[i]['thumb_url'] = jobs[i]['img_url'] + '?x-oss-process=image/quality,q_60&format=webp' } else { @@ -538,10 +546,10 @@ const send = (url, index, item) => { session_id: getSessionId(), prompt: item.prompt, }).then(() => { - ElMessage.success("任务推送成功,请耐心等待任务执行...") + showSuccessToast("任务推送成功,请耐心等待任务执行...") power.value -= mjActionPower.value }).catch(e => { - ElMessage.error("任务推送失败:" + e.message) + showFailToast("任务推送失败:" + e.message) }) } @@ -579,9 +587,9 @@ const removeImage = (item) => { '此操作将会删除任务和图片,继续操作码?', }).then(() => { httpPost("/api/mj/remove", {id: item.id, img_url: item.img_url, user_id: userId.value}).then(() => { - ElMessage.success("任务删除成功") + showSuccessToast("任务删除成功") }).catch(e => { - ElMessage.error("任务删除失败:" + e.message) + showFailToast("任务删除失败:" + e.message) }) }).catch(() => { showToast("您取消了操作") diff --git a/web/src/views/mobile/ImageSd.vue b/web/src/views/mobile/ImageSd.vue new file mode 100644 index 00000000..b310a0a1 --- /dev/null +++ b/web/src/views/mobile/ImageSd.vue @@ -0,0 +1,523 @@ + + + + + \ No newline at end of file