mirror of
				https://github.com/yangjian102621/geekai.git
				synced 2025-11-04 16:23:42 +08:00 
			
		
		
		
	feat: add blend and swapface task implements for midjourney
This commit is contained in:
		@@ -9,6 +9,8 @@ func (t TaskType) String() string {
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	TaskImage     = TaskType("image")
 | 
			
		||||
	TaskBlend     = TaskType("blend")
 | 
			
		||||
	TaskSwapFace  = TaskType("swapFace")
 | 
			
		||||
	TaskUpscale   = TaskType("upscale")
 | 
			
		||||
	TaskVariation = TaskType("variation")
 | 
			
		||||
)
 | 
			
		||||
@@ -16,6 +18,8 @@ const (
 | 
			
		||||
// MjTask MidJourney 任务
 | 
			
		||||
type MjTask struct {
 | 
			
		||||
	Id          int      `json:"id"`
 | 
			
		||||
	TaskId      string   `json:"task_id"`
 | 
			
		||||
	ImgArr      []string `json:"img_arr"`
 | 
			
		||||
	ChannelId   string   `json:"channel_id"`
 | 
			
		||||
	SessionId   string   `json:"session_id"`
 | 
			
		||||
	Type        TaskType `json:"type"`
 | 
			
		||||
 
 | 
			
		||||
@@ -86,19 +86,20 @@ func (h *MidJourneyHandler) Client(c *gin.Context) {
 | 
			
		||||
// Image 创建一个绘画任务
 | 
			
		||||
func (h *MidJourneyHandler) Image(c *gin.Context) {
 | 
			
		||||
	var data struct {
 | 
			
		||||
		SessionId string  `json:"session_id"`
 | 
			
		||||
		Prompt    string  `json:"prompt"`
 | 
			
		||||
		NegPrompt string  `json:"neg_prompt"`
 | 
			
		||||
		Rate      string  `json:"rate"`
 | 
			
		||||
		Model     string  `json:"model"`
 | 
			
		||||
		Chaos     int     `json:"chaos"`
 | 
			
		||||
		Raw       bool    `json:"raw"`
 | 
			
		||||
		Seed      int64   `json:"seed"`
 | 
			
		||||
		Stylize   int     `json:"stylize"`
 | 
			
		||||
		Img       string  `json:"img"`
 | 
			
		||||
		Tile      bool    `json:"tile"`
 | 
			
		||||
		Quality   float32 `json:"quality"`
 | 
			
		||||
		Weight    float32 `json:"weight"`
 | 
			
		||||
		SessionId string   `json:"session_id"`
 | 
			
		||||
		TaskType  string   `json:"task_type"`
 | 
			
		||||
		Prompt    string   `json:"prompt"`
 | 
			
		||||
		NegPrompt string   `json:"neg_prompt"`
 | 
			
		||||
		Rate      string   `json:"rate"`
 | 
			
		||||
		Model     string   `json:"model"`
 | 
			
		||||
		Chaos     int      `json:"chaos"`
 | 
			
		||||
		Raw       bool     `json:"raw"`
 | 
			
		||||
		Seed      int64    `json:"seed"`
 | 
			
		||||
		Stylize   int      `json:"stylize"`
 | 
			
		||||
		ImgArr    []string `json:"img_arr"`
 | 
			
		||||
		Tile      bool     `json:"tile"`
 | 
			
		||||
		Quality   float32  `json:"quality"`
 | 
			
		||||
		Weight    float32  `json:"weight"`
 | 
			
		||||
	}
 | 
			
		||||
	if err := c.ShouldBindJSON(&data); err != nil {
 | 
			
		||||
		resp.ERROR(c, types.InvalidArgs)
 | 
			
		||||
@@ -121,11 +122,8 @@ func (h *MidJourneyHandler) Image(c *gin.Context) {
 | 
			
		||||
	if data.Chaos > 0 && !strings.Contains(prompt, "--c") && !strings.Contains(prompt, "--chaos") {
 | 
			
		||||
		prompt += fmt.Sprintf(" --c %d", data.Chaos)
 | 
			
		||||
	}
 | 
			
		||||
	if data.Img != "" {
 | 
			
		||||
		prompt = fmt.Sprintf("%s %s", data.Img, prompt)
 | 
			
		||||
		if data.Weight > 0 {
 | 
			
		||||
			prompt += fmt.Sprintf(" --iw %f", data.Weight)
 | 
			
		||||
		}
 | 
			
		||||
	if data.Weight > 0 {
 | 
			
		||||
		prompt += fmt.Sprintf(" --iw %f", data.Weight)
 | 
			
		||||
	}
 | 
			
		||||
	if data.Raw {
 | 
			
		||||
		prompt += " --style raw"
 | 
			
		||||
@@ -152,7 +150,7 @@ func (h *MidJourneyHandler) Image(c *gin.Context) {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	job := model.MidJourneyJob{
 | 
			
		||||
		Type:      types.TaskImage.String(),
 | 
			
		||||
		Type:      data.TaskType,
 | 
			
		||||
		UserId:    userId,
 | 
			
		||||
		TaskId:    taskId,
 | 
			
		||||
		Progress:  0,
 | 
			
		||||
@@ -166,10 +164,12 @@ func (h *MidJourneyHandler) Image(c *gin.Context) {
 | 
			
		||||
 | 
			
		||||
	h.pool.PushTask(types.MjTask{
 | 
			
		||||
		Id:        int(job.Id),
 | 
			
		||||
		TaskId:    taskId,
 | 
			
		||||
		SessionId: data.SessionId,
 | 
			
		||||
		Type:      types.TaskImage,
 | 
			
		||||
		Prompt:    fmt.Sprintf("%s %s", taskId, prompt),
 | 
			
		||||
		Prompt:    prompt,
 | 
			
		||||
		UserId:    userId,
 | 
			
		||||
		ImgArr:    data.ImgArr,
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	client := h.pool.Clients.Get(uint(job.UserId))
 | 
			
		||||
 
 | 
			
		||||
@@ -2,6 +2,7 @@ package mj
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"chatplus/core/types"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
@@ -33,7 +34,7 @@ func NewClient(config types.MidJourneyConfig, proxy string, imgCdnURL string) *C
 | 
			
		||||
	return &Client{client: client, Config: config, apiURL: apiURL, imgCdnURL: imgCdnURL}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Client) Imagine(prompt string) error {
 | 
			
		||||
func (c *Client) Imagine(task types.MjTask) error {
 | 
			
		||||
	interactionsReq := &InteractionsRequest{
 | 
			
		||||
		Type:          2,
 | 
			
		||||
		ApplicationID: ApplicationID,
 | 
			
		||||
@@ -49,7 +50,7 @@ func (c *Client) Imagine(prompt string) error {
 | 
			
		||||
				{
 | 
			
		||||
					"type":  3,
 | 
			
		||||
					"name":  "prompt",
 | 
			
		||||
					"value": prompt,
 | 
			
		||||
					"value": fmt.Sprintf("%s %s", task.TaskId, task.Prompt),
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			"application_command": map[string]any{
 | 
			
		||||
@@ -88,20 +89,28 @@ func (c *Client) Imagine(prompt string) error {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Client) Blend(task types.MjTask) error {
 | 
			
		||||
	return errors.New("function not implemented")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Client) SwapFace(task types.MjTask) error {
 | 
			
		||||
	return errors.New("function not implemented")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Upscale 放大指定的图片
 | 
			
		||||
func (c *Client) Upscale(index int, messageId string, hash string) error {
 | 
			
		||||
func (c *Client) Upscale(task types.MjTask) error {
 | 
			
		||||
	flags := 0
 | 
			
		||||
	interactionsReq := &InteractionsRequest{
 | 
			
		||||
		Type:          3,
 | 
			
		||||
		ApplicationID: ApplicationID,
 | 
			
		||||
		GuildID:       c.Config.GuildId,
 | 
			
		||||
		ChannelID:     c.Config.ChanelId,
 | 
			
		||||
		MessageFlags:  &flags,
 | 
			
		||||
		MessageID:     &messageId,
 | 
			
		||||
		MessageFlags:  flags,
 | 
			
		||||
		MessageID:     task.MessageId,
 | 
			
		||||
		SessionID:     SessionID,
 | 
			
		||||
		Data: map[string]any{
 | 
			
		||||
			"component_type": 2,
 | 
			
		||||
			"custom_id":      fmt.Sprintf("MJ::JOB::upsample::%d::%s", index, hash),
 | 
			
		||||
			"custom_id":      fmt.Sprintf("MJ::JOB::upsample::%d::%s", task.Index, task.MessageHash),
 | 
			
		||||
		},
 | 
			
		||||
		Nonce: fmt.Sprintf("%d", time.Now().UnixNano()),
 | 
			
		||||
	}
 | 
			
		||||
@@ -120,19 +129,19 @@ func (c *Client) Upscale(index int, messageId string, hash string) error {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Variation  以指定的图片的视角进行变换再创作,注意需要在对应的频道中关闭 Remix 变换,否则 Variation 指令将不会生效
 | 
			
		||||
func (c *Client) Variation(index int, messageId string, hash string) error {
 | 
			
		||||
func (c *Client) Variation(task types.MjTask) error {
 | 
			
		||||
	flags := 0
 | 
			
		||||
	interactionsReq := &InteractionsRequest{
 | 
			
		||||
		Type:          3,
 | 
			
		||||
		ApplicationID: ApplicationID,
 | 
			
		||||
		GuildID:       c.Config.GuildId,
 | 
			
		||||
		ChannelID:     c.Config.ChanelId,
 | 
			
		||||
		MessageFlags:  &flags,
 | 
			
		||||
		MessageID:     &messageId,
 | 
			
		||||
		MessageFlags:  flags,
 | 
			
		||||
		MessageID:     task.MessageId,
 | 
			
		||||
		SessionID:     SessionID,
 | 
			
		||||
		Data: map[string]any{
 | 
			
		||||
			"component_type": 2,
 | 
			
		||||
			"custom_id":      fmt.Sprintf("MJ::JOB::variation::%d::%s", index, hash),
 | 
			
		||||
			"custom_id":      fmt.Sprintf("MJ::JOB::variation::%d::%s", task.Index, task.MessageHash),
 | 
			
		||||
		},
 | 
			
		||||
		Nonce: fmt.Sprintf("%d", time.Now().UnixNano()),
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,8 +3,11 @@ package plus
 | 
			
		||||
import (
 | 
			
		||||
	"chatplus/core/types"
 | 
			
		||||
	logger2 "chatplus/logger"
 | 
			
		||||
	"chatplus/utils"
 | 
			
		||||
	"encoding/base64"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"github.com/gin-gonic/gin"
 | 
			
		||||
	"io"
 | 
			
		||||
 | 
			
		||||
	"github.com/imroc/req/v3"
 | 
			
		||||
@@ -22,9 +25,10 @@ func NewClient(config types.MidJourneyPlusConfig) *Client {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type ImageReq struct {
 | 
			
		||||
	BotType       string        `json:"botType"`
 | 
			
		||||
	Prompt        string        `json:"prompt"`
 | 
			
		||||
	Base64Array   []interface{} `json:"base64Array,omitempty"`
 | 
			
		||||
	BotType       string   `json:"botType"`
 | 
			
		||||
	Prompt        string   `json:"prompt,omitempty"`
 | 
			
		||||
	Dimensions    string   `json:"dimensions,omitempty"`
 | 
			
		||||
	Base64Array   []string `json:"base64Array,omitempty"`
 | 
			
		||||
	AccountFilter struct {
 | 
			
		||||
		InstanceId          string        `json:"instanceId"`
 | 
			
		||||
		Modes               []interface{} `json:"modes"`
 | 
			
		||||
@@ -49,12 +53,114 @@ type ErrRes struct {
 | 
			
		||||
	} `json:"error"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Client) Imagine(prompt string) (ImageRes, error) {
 | 
			
		||||
func (c *Client) Imagine(task types.MjTask) (ImageRes, error) {
 | 
			
		||||
	apiURL := fmt.Sprintf("%s/mj-fast/mj/submit/imagine", c.Config.ApiURL)
 | 
			
		||||
	body := ImageReq{
 | 
			
		||||
		BotType:    "MID_JOURNEY",
 | 
			
		||||
		Prompt:     prompt,
 | 
			
		||||
		NotifyHook: c.Config.NotifyURL,
 | 
			
		||||
		BotType:     "MID_JOURNEY",
 | 
			
		||||
		Prompt:      task.Prompt,
 | 
			
		||||
		NotifyHook:  c.Config.NotifyURL,
 | 
			
		||||
		Base64Array: make([]string, 1),
 | 
			
		||||
	}
 | 
			
		||||
	// 生成图片 Base64 编码
 | 
			
		||||
	if len(task.ImgArr) > 0 {
 | 
			
		||||
		imageData, err := utils.DownloadImage(task.ImgArr[0], "")
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			logger.Error("error with download image: ", err)
 | 
			
		||||
		} else {
 | 
			
		||||
			body.Base64Array[0] = "data:image/png;base64," + base64.StdEncoding.EncodeToString(imageData)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
	var res ImageRes
 | 
			
		||||
	var errRes ErrRes
 | 
			
		||||
	r, err := req.C().R().
 | 
			
		||||
		SetHeader("Authorization", "Bearer "+c.Config.ApiKey).
 | 
			
		||||
		SetBody(body).
 | 
			
		||||
		SetSuccessResult(&res).
 | 
			
		||||
		SetErrorResult(&errRes).
 | 
			
		||||
		Post(apiURL)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		errStr, _ := io.ReadAll(r.Body)
 | 
			
		||||
		return ImageRes{}, fmt.Errorf("请求 API 出错:%v,%v", err, string(errStr))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if r.IsErrorState() {
 | 
			
		||||
		return ImageRes{}, fmt.Errorf("API 返回错误:%s", errRes.Error.Message)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return res, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Blend 融图
 | 
			
		||||
func (c *Client) Blend(task types.MjTask) (ImageRes, error) {
 | 
			
		||||
	apiURL := fmt.Sprintf("%s/mj-fast/mj/submit/blend", c.Config.ApiURL)
 | 
			
		||||
	body := ImageReq{
 | 
			
		||||
		BotType:     "MID_JOURNEY",
 | 
			
		||||
		Dimensions:  "SQUARE",
 | 
			
		||||
		NotifyHook:  c.Config.NotifyURL,
 | 
			
		||||
		Base64Array: make([]string, 1),
 | 
			
		||||
	}
 | 
			
		||||
	// 生成图片 Base64 编码
 | 
			
		||||
	if len(task.ImgArr) > 0 {
 | 
			
		||||
		for _, imgURL := range task.ImgArr {
 | 
			
		||||
			imageData, err := utils.DownloadImage(imgURL, "")
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				logger.Error("error with download image: ", err)
 | 
			
		||||
			} else {
 | 
			
		||||
				body.Base64Array[0] = "data:image/png;base64," + base64.StdEncoding.EncodeToString(imageData)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	var res ImageRes
 | 
			
		||||
	var errRes ErrRes
 | 
			
		||||
	r, err := req.C().R().
 | 
			
		||||
		SetHeader("Authorization", "Bearer "+c.Config.ApiKey).
 | 
			
		||||
		SetBody(body).
 | 
			
		||||
		SetSuccessResult(&res).
 | 
			
		||||
		SetErrorResult(&errRes).
 | 
			
		||||
		Post(apiURL)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		errStr, _ := io.ReadAll(r.Body)
 | 
			
		||||
		return ImageRes{}, fmt.Errorf("请求 API 出错:%v,%v", err, string(errStr))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if r.IsErrorState() {
 | 
			
		||||
		return ImageRes{}, fmt.Errorf("API 返回错误:%s", errRes.Error.Message)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return res, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SwapFace 换脸
 | 
			
		||||
func (c *Client) SwapFace(task types.MjTask) (ImageRes, error) {
 | 
			
		||||
	apiURL := fmt.Sprintf("%s/mj-fast/mj/insight-face/swap", c.Config.ApiURL)
 | 
			
		||||
	// 生成图片 Base64 编码
 | 
			
		||||
	if len(task.ImgArr) != 2 {
 | 
			
		||||
		return ImageRes{}, errors.New("参数错误,必须上传2张图片")
 | 
			
		||||
	}
 | 
			
		||||
	var sourceBase64 string
 | 
			
		||||
	var targetBase64 string
 | 
			
		||||
	imageData, err := utils.DownloadImage(task.ImgArr[0], "")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		logger.Error("error with download image: ", err)
 | 
			
		||||
	} else {
 | 
			
		||||
		sourceBase64 = "data:image/png;base64," + base64.StdEncoding.EncodeToString(imageData)
 | 
			
		||||
	}
 | 
			
		||||
	imageData, err = utils.DownloadImage(task.ImgArr[1], "")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		logger.Error("error with download image: ", err)
 | 
			
		||||
	} else {
 | 
			
		||||
		targetBase64 = "data:image/png;base64," + base64.StdEncoding.EncodeToString(imageData)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	body := gin.H{
 | 
			
		||||
		"sourceBase64": sourceBase64,
 | 
			
		||||
		"targetBase64": targetBase64,
 | 
			
		||||
		"accountFilter": gin.H{
 | 
			
		||||
			"instanceId": "",
 | 
			
		||||
		},
 | 
			
		||||
		"notifyHook": c.Config.NotifyURL,
 | 
			
		||||
		"state":      "",
 | 
			
		||||
	}
 | 
			
		||||
	var res ImageRes
 | 
			
		||||
	var errRes ErrRes
 | 
			
		||||
@@ -77,10 +183,10 @@ func (c *Client) Imagine(prompt string) (ImageRes, error) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Upscale 放大指定的图片
 | 
			
		||||
func (c *Client) Upscale(index int, messageId string, hash string) (ImageRes, error) {
 | 
			
		||||
func (c *Client) Upscale(task types.MjTask) (ImageRes, error) {
 | 
			
		||||
	body := map[string]string{
 | 
			
		||||
		"customId":   fmt.Sprintf("MJ::JOB::upsample::%d::%s", index, hash),
 | 
			
		||||
		"taskId":     messageId,
 | 
			
		||||
		"customId":   fmt.Sprintf("MJ::JOB::upsample::%d::%s", task.Index, task.MessageHash),
 | 
			
		||||
		"taskId":     task.MessageId,
 | 
			
		||||
		"notifyHook": c.Config.NotifyURL,
 | 
			
		||||
	}
 | 
			
		||||
	apiURL := fmt.Sprintf("%s/mj/submit/action", c.Config.ApiURL)
 | 
			
		||||
@@ -104,10 +210,10 @@ func (c *Client) Upscale(index int, messageId string, hash string) (ImageRes, er
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Variation  以指定的图片的视角进行变换再创作,注意需要在对应的频道中关闭 Remix 变换,否则 Variation 指令将不会生效
 | 
			
		||||
func (c *Client) Variation(index int, messageId string, hash string) (ImageRes, error) {
 | 
			
		||||
func (c *Client) Variation(task types.MjTask) (ImageRes, error) {
 | 
			
		||||
	body := map[string]string{
 | 
			
		||||
		"customId":   fmt.Sprintf("MJ::JOB::variation::%d::%s", index, hash),
 | 
			
		||||
		"taskId":     messageId,
 | 
			
		||||
		"customId":   fmt.Sprintf("MJ::JOB::variation::%d::%s", task.Index, task.MessageHash),
 | 
			
		||||
		"taskId":     task.MessageId,
 | 
			
		||||
		"notifyHook": c.Config.NotifyURL,
 | 
			
		||||
	}
 | 
			
		||||
	apiURL := fmt.Sprintf("%s/mj/submit/action", c.Config.ApiURL)
 | 
			
		||||
 
 | 
			
		||||
@@ -69,18 +69,24 @@ func (s *Service) Run() {
 | 
			
		||||
		var res ImageRes
 | 
			
		||||
		switch task.Type {
 | 
			
		||||
		case types.TaskImage:
 | 
			
		||||
			index := strings.Index(task.Prompt, " ")
 | 
			
		||||
			res, err = s.Client.Imagine(task.Prompt[index+1:])
 | 
			
		||||
			res, err = s.Client.Imagine(task)
 | 
			
		||||
			break
 | 
			
		||||
		case types.TaskUpscale:
 | 
			
		||||
			res, err = s.Client.Upscale(task.Index, task.MessageId, task.MessageHash)
 | 
			
		||||
			res, err = s.Client.Upscale(task)
 | 
			
		||||
			break
 | 
			
		||||
		case types.TaskVariation:
 | 
			
		||||
			res, err = s.Client.Variation(task.Index, task.MessageId, task.MessageHash)
 | 
			
		||||
			res, err = s.Client.Variation(task)
 | 
			
		||||
			break
 | 
			
		||||
		case types.TaskBlend:
 | 
			
		||||
			res, err = s.Client.Blend(task)
 | 
			
		||||
			break
 | 
			
		||||
		case types.TaskSwapFace:
 | 
			
		||||
			res, err = s.Client.SwapFace(task)
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if err != nil || (res.Code != 1 && res.Code != 22) {
 | 
			
		||||
			logger.Error("绘画任务执行失败:", err)
 | 
			
		||||
			logger.Error("绘画任务执行失败:", err, res.Description)
 | 
			
		||||
			// update the task progress
 | 
			
		||||
			s.db.Model(&model.MidJourneyJob{Id: uint(task.Id)}).UpdateColumn("progress", -1)
 | 
			
		||||
			// 任务失败,通知前端
 | 
			
		||||
 
 | 
			
		||||
@@ -65,14 +65,20 @@ func (s *Service) Run() {
 | 
			
		||||
		logger.Infof("%s handle a new MidJourney task: %+v", s.name, task)
 | 
			
		||||
		switch task.Type {
 | 
			
		||||
		case types.TaskImage:
 | 
			
		||||
			err = s.client.Imagine(task.Prompt)
 | 
			
		||||
			err = s.client.Imagine(task)
 | 
			
		||||
			break
 | 
			
		||||
		case types.TaskUpscale:
 | 
			
		||||
			err = s.client.Upscale(task.Index, task.MessageId, task.MessageHash)
 | 
			
		||||
 | 
			
		||||
			err = s.client.Upscale(task)
 | 
			
		||||
			break
 | 
			
		||||
		case types.TaskVariation:
 | 
			
		||||
			err = s.client.Variation(task.Index, task.MessageId, task.MessageHash)
 | 
			
		||||
			err = s.client.Variation(task)
 | 
			
		||||
			break
 | 
			
		||||
		case types.TaskBlend:
 | 
			
		||||
			err = s.client.Blend(task)
 | 
			
		||||
			break
 | 
			
		||||
		case types.TaskSwapFace:
 | 
			
		||||
			err = s.client.SwapFace(task)
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if err != nil {
 | 
			
		||||
 
 | 
			
		||||
@@ -8,8 +8,8 @@ const (
 | 
			
		||||
type InteractionsRequest struct {
 | 
			
		||||
	Type          int            `json:"type"`
 | 
			
		||||
	ApplicationID string         `json:"application_id"`
 | 
			
		||||
	MessageFlags  *int           `json:"message_flags,omitempty"`
 | 
			
		||||
	MessageID     *string        `json:"message_id,omitempty"`
 | 
			
		||||
	MessageFlags  int            `json:"message_flags,omitempty"`
 | 
			
		||||
	MessageID     string         `json:"message_id,omitempty"`
 | 
			
		||||
	GuildID       string         `json:"guild_id"`
 | 
			
		||||
	ChannelID     string         `json:"channel_id"`
 | 
			
		||||
	SessionID     string         `json:"session_id"`
 | 
			
		||||
 
 | 
			
		||||
@@ -48,12 +48,12 @@ func DownloadImage(imageURL string, proxy string) ([]byte, error) {
 | 
			
		||||
			},
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	req, err := http.NewRequest("GET", imageURL, nil)
 | 
			
		||||
	request, err := http.NewRequest("GET", imageURL, nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	resp, err := client.Do(req)
 | 
			
		||||
	resp, err := client.Do(request)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -201,9 +201,6 @@
 | 
			
		||||
.page-mj .inner .task-list-box .task-list-inner .title-tabs .el-tabs__active-bar {
 | 
			
		||||
  background-color: #47fff1;
 | 
			
		||||
}
 | 
			
		||||
.page-mj .inner .task-list-box .task-list-inner .title-tabs .el-tabs__content {
 | 
			
		||||
  padding: 10px 0;
 | 
			
		||||
}
 | 
			
		||||
.page-mj .inner .task-list-box .task-list-inner .el-textarea {
 | 
			
		||||
  --el-input-focus-border-color: #47fff1;
 | 
			
		||||
}
 | 
			
		||||
@@ -254,6 +251,12 @@
 | 
			
		||||
  height: 120px;
 | 
			
		||||
  text-align: center;
 | 
			
		||||
}
 | 
			
		||||
.page-mj .inner .task-list-box .task-list-inner .img-inline {
 | 
			
		||||
  display: flex;
 | 
			
		||||
}
 | 
			
		||||
.page-mj .inner .task-list-box .task-list-inner .img-inline .img-uploader {
 | 
			
		||||
  margin-right: 10px;
 | 
			
		||||
}
 | 
			
		||||
.page-mj .inner .task-list-box .task-list-inner .submit-btn {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  margin: 20px 0;
 | 
			
		||||
 
 | 
			
		||||
@@ -86,9 +86,6 @@
 | 
			
		||||
.page-sd .inner .task-list-box .task-list-inner .title-tabs .el-tabs__active-bar {
 | 
			
		||||
  background-color: #47fff1;
 | 
			
		||||
}
 | 
			
		||||
.page-sd .inner .task-list-box .task-list-inner .title-tabs .el-tabs__content {
 | 
			
		||||
  padding: 10px 0;
 | 
			
		||||
}
 | 
			
		||||
.page-sd .inner .task-list-box .task-list-inner .el-textarea {
 | 
			
		||||
  --el-input-focus-border-color: #47fff1;
 | 
			
		||||
}
 | 
			
		||||
@@ -139,6 +136,12 @@
 | 
			
		||||
  height: 120px;
 | 
			
		||||
  text-align: center;
 | 
			
		||||
}
 | 
			
		||||
.page-sd .inner .task-list-box .task-list-inner .img-inline {
 | 
			
		||||
  display: flex;
 | 
			
		||||
}
 | 
			
		||||
.page-sd .inner .task-list-box .task-list-inner .img-inline .img-uploader {
 | 
			
		||||
  margin-right: 10px;
 | 
			
		||||
}
 | 
			
		||||
.page-sd .inner .task-list-box .task-list-inner .submit-btn {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  margin: 20px 0;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								web/src/assets/css/mobile/image-mj.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								web/src/assets/css/mobile/image-mj.css
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
			
		||||
.mobile-mj .content .van-field__label {
 | 
			
		||||
  width: 100px;
 | 
			
		||||
  text-align: right;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										8
									
								
								web/src/assets/css/mobile/image-mj.styl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								web/src/assets/css/mobile/image-mj.styl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
.mobile-mj {
 | 
			
		||||
  .content {
 | 
			
		||||
    .van-field__label {
 | 
			
		||||
      width 100px
 | 
			
		||||
      text-align right
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -23,10 +23,6 @@
 | 
			
		||||
      background-color: #47FFF1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .title-tabs .el-tabs__content {
 | 
			
		||||
      padding: 10px 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .el-textarea {
 | 
			
		||||
      --el-input-focus-border-color: #47FFF1;
 | 
			
		||||
    }
 | 
			
		||||
@@ -90,6 +86,14 @@
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .img-inline {
 | 
			
		||||
      display flex
 | 
			
		||||
 | 
			
		||||
      .img-uploader {
 | 
			
		||||
        margin-right 10px
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .submit-btn {
 | 
			
		||||
      display flex
 | 
			
		||||
      margin: 20px 0
 | 
			
		||||
@@ -192,7 +196,7 @@
 | 
			
		||||
        top 10px
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      &:hover{
 | 
			
		||||
      &:hover {
 | 
			
		||||
        .remove {
 | 
			
		||||
          display block
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -167,8 +167,8 @@
 | 
			
		||||
        <div class="task-list-inner" :style="{ height: listBoxHeight + 'px' }">
 | 
			
		||||
          <h2>AI绘画</h2>
 | 
			
		||||
          <el-form>
 | 
			
		||||
            <el-tabs v-model="activeName" class="title-tabs">
 | 
			
		||||
              <el-tab-pane label="图生图(可选)" name="图生图">
 | 
			
		||||
            <el-tabs v-model="activeName" class="title-tabs" @tabChange="tabChange">
 | 
			
		||||
              <el-tab-pane label="文生图(可选)" name="image">
 | 
			
		||||
                <div class="text">图生图:以某张图片为底稿参考来创作绘画,生成类似风格或类型图像,支持 PNG 和 JPG 格式图片;
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="param-line pt">
 | 
			
		||||
@@ -194,7 +194,7 @@
 | 
			
		||||
 | 
			
		||||
                <div class="param-line">
 | 
			
		||||
                  <el-upload class="img-uploader" :auto-upload="true" :show-file-list="false"
 | 
			
		||||
                             :http-request="afterRead" style="--el-color-primary:#47fff1">
 | 
			
		||||
                             :http-request="uploadImg" style="--el-color-primary:#47fff1">
 | 
			
		||||
                    <el-image v-if="params.img !== ''" :src="params.img" fit="cover"/>
 | 
			
		||||
                    <el-icon v-else class="uploader-icon">
 | 
			
		||||
                      <Plus/>
 | 
			
		||||
@@ -219,88 +219,119 @@
 | 
			
		||||
                    </template>
 | 
			
		||||
                  </el-form-item>
 | 
			
		||||
                </div>
 | 
			
		||||
              </el-tab-pane>
 | 
			
		||||
 | 
			
		||||
              <el-tab-pane label="图生文(可选)" name="图生文">
 | 
			
		||||
                <div class="text">图生文功能正在紧锣密鼓开发中,敬请期待...</div>
 | 
			
		||||
                <!--              <div class="param-line pt">-->
 | 
			
		||||
                <!--                <el-empty image-size="100px" description="功能建设中"/>-->
 | 
			
		||||
                <!--              </div>-->
 | 
			
		||||
              </el-tab-pane>
 | 
			
		||||
                <div class="prompt-box">
 | 
			
		||||
                  <div class="param-line pt">
 | 
			
		||||
                    <div class="flex-row justify-between items-center">
 | 
			
		||||
                      <div class="flex-row justify-start items-center">
 | 
			
		||||
                        <span>提示词:</span>
 | 
			
		||||
                        <el-tooltip effect="light" content="输入你想要的内容,用逗号分割" placement="right">
 | 
			
		||||
                          <el-icon>
 | 
			
		||||
                            <InfoFilled/>
 | 
			
		||||
                          </el-icon>
 | 
			
		||||
                        </el-tooltip>
 | 
			
		||||
                      </div>
 | 
			
		||||
                      <div>
 | 
			
		||||
                        <el-button type="primary" @click="translatePrompt(false)" :disabled="loading">
 | 
			
		||||
                          <el-icon style="margin-right: 6px;font-size: 18px;">
 | 
			
		||||
                            <Refresh/>
 | 
			
		||||
                          </el-icon>
 | 
			
		||||
                          翻译
 | 
			
		||||
                        </el-button>
 | 
			
		||||
 | 
			
		||||
              <el-tab-pane label="融图(可选)" name="融图">
 | 
			
		||||
                <div class="text">融图功能正在紧锣密鼓开发中,敬请期待...</div>
 | 
			
		||||
              </el-tab-pane>
 | 
			
		||||
            </el-tabs>
 | 
			
		||||
 | 
			
		||||
            <div v-loading="loading" element-loading-background="rgba(122, 122, 122, 0.8)">
 | 
			
		||||
              <div class="param-line pt">
 | 
			
		||||
                <div class="flex-row justify-between items-center">
 | 
			
		||||
                  <div class="flex-row justify-start items-center">
 | 
			
		||||
                    <span>提示词:</span>
 | 
			
		||||
                    <el-tooltip effect="light" content="输入你想要的内容,用逗号分割" placement="right">
 | 
			
		||||
                      <el-icon>
 | 
			
		||||
                        <InfoFilled/>
 | 
			
		||||
                      </el-icon>
 | 
			
		||||
                    </el-tooltip>
 | 
			
		||||
                        <el-tooltip
 | 
			
		||||
                            class="box-item"
 | 
			
		||||
                            effect="light"
 | 
			
		||||
                            raw-content
 | 
			
		||||
                            content="使用 AI 翻译并重写提示词,<br/>增加更多细节,风格等描述"
 | 
			
		||||
                            placement="top-end"
 | 
			
		||||
                        >
 | 
			
		||||
                          <el-button type="success" @click="rewritePrompt" :disabled="loading">
 | 
			
		||||
                            <el-icon style="margin-right: 6px;font-size: 18px;">
 | 
			
		||||
                              <Refresh/>
 | 
			
		||||
                            </el-icon>
 | 
			
		||||
                            翻译并重写
 | 
			
		||||
                          </el-button>
 | 
			
		||||
                        </el-tooltip>
 | 
			
		||||
                      </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                  </div>
 | 
			
		||||
                  <div>
 | 
			
		||||
                    <el-button type="primary" @click="translatePrompt">
 | 
			
		||||
                      <el-icon style="margin-right: 6px;font-size: 18px;">
 | 
			
		||||
                        <Refresh/>
 | 
			
		||||
                      </el-icon>
 | 
			
		||||
                      翻译
 | 
			
		||||
                    </el-button>
 | 
			
		||||
 | 
			
		||||
                    <el-tooltip
 | 
			
		||||
                        class="box-item"
 | 
			
		||||
                        effect="light"
 | 
			
		||||
                        raw-content
 | 
			
		||||
                        content="使用 AI 翻译并重写提示词,<br/>增加更多细节,风格等描述"
 | 
			
		||||
                        placement="top-end"
 | 
			
		||||
                    >
 | 
			
		||||
                      <el-button type="success" @click="rewritePrompt">
 | 
			
		||||
                  <div class="param-line pt">
 | 
			
		||||
                    <el-input v-model="params.prompt" :autosize="{ minRows: 4, maxRows: 6 }" type="textarea"
 | 
			
		||||
                              ref="promptRef"
 | 
			
		||||
                              placeholder="这里输入你的英文咒语,例如:A chinese girl walking in the middle of a cobblestone street"/>
 | 
			
		||||
                  </div>
 | 
			
		||||
 | 
			
		||||
                  <div class="param-line pt">
 | 
			
		||||
                    <div class="flex-row justify-between items-center">
 | 
			
		||||
                      <div class="flex-row justify-start items-center">
 | 
			
		||||
                        <span>不希望出现的内容:(可选)</span>
 | 
			
		||||
                        <el-tooltip effect="light" content="不想出现在图片上的元素(例如:树,建筑)" placement="right">
 | 
			
		||||
                          <el-icon>
 | 
			
		||||
                            <InfoFilled/>
 | 
			
		||||
                          </el-icon>
 | 
			
		||||
                        </el-tooltip>
 | 
			
		||||
                      </div>
 | 
			
		||||
                      <el-button type="primary" @click="translatePrompt(true)" :disabled="loading">
 | 
			
		||||
                        <el-icon style="margin-right: 6px;font-size: 18px;">
 | 
			
		||||
                          <Refresh/>
 | 
			
		||||
                        </el-icon>
 | 
			
		||||
                        翻译并重写
 | 
			
		||||
                        翻译
 | 
			
		||||
                      </el-button>
 | 
			
		||||
                    </el-tooltip>
 | 
			
		||||
                    </div>
 | 
			
		||||
                  </div>
 | 
			
		||||
 | 
			
		||||
                  <div class="param-line pt">
 | 
			
		||||
                    <el-input v-model="params.neg_prompt" :autosize="{ minRows: 4, maxRows: 6 }" type="textarea"
 | 
			
		||||
                              ref="promptRef"
 | 
			
		||||
                              placeholder="这里输入你不希望出现在图片上的内容,元素"/>
 | 
			
		||||
                  </div>
 | 
			
		||||
                </div>
 | 
			
		||||
              </div>
 | 
			
		||||
              </el-tab-pane>
 | 
			
		||||
 | 
			
		||||
              <div class="param-line pt">
 | 
			
		||||
                <el-input v-model="params.prompt" :autosize="{ minRows: 4, maxRows: 6 }" type="textarea"
 | 
			
		||||
                          ref="promptRef"
 | 
			
		||||
                          placeholder="这里输入你的英文咒语,例如:A chinese girl walking in the middle of a cobblestone street"/>
 | 
			
		||||
              </div>
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            <div class="param-line pt">
 | 
			
		||||
              <div class="flex-row justify-between items-center">
 | 
			
		||||
                <div class="flex-row justify-start items-center">
 | 
			
		||||
                  <span>不希望出现的内容:(可选)</span>
 | 
			
		||||
                  <el-tooltip effect="light" content="不想出现在图片上的元素(例如:树,建筑)" placement="right">
 | 
			
		||||
                    <el-icon>
 | 
			
		||||
                      <InfoFilled/>
 | 
			
		||||
              <el-tab-pane label="融图(可选)" name="blend">
 | 
			
		||||
                <div class="text">请上传两张以上的图片</div>
 | 
			
		||||
                <div class="img-inline">
 | 
			
		||||
                  <el-upload class="img-uploader" :auto-upload="true" :show-file-list="false"
 | 
			
		||||
                             :http-request="uploadImg" style="--el-color-primary:#47fff1">
 | 
			
		||||
                    <el-image v-if="params.img !== ''" :src="params.img" fit="cover"/>
 | 
			
		||||
                    <el-icon v-else class="uploader-icon">
 | 
			
		||||
                      <Plus/>
 | 
			
		||||
                    </el-icon>
 | 
			
		||||
                  </el-tooltip>
 | 
			
		||||
                </div>
 | 
			
		||||
                <!--                <el-button type="success">-->
 | 
			
		||||
                <!--                  <el-icon style="margin-right: 6px;font-size: 18px;">-->
 | 
			
		||||
                <!--                    <Refresh/>-->
 | 
			
		||||
                <!--                  </el-icon>-->
 | 
			
		||||
                <!--                  翻译-->
 | 
			
		||||
                <!--                </el-button>-->
 | 
			
		||||
              </div>
 | 
			
		||||
            </div>
 | 
			
		||||
                  </el-upload>
 | 
			
		||||
 | 
			
		||||
            <div class="param-line pt">
 | 
			
		||||
              <el-input v-model="params.neg_prompt" :autosize="{ minRows: 4, maxRows: 6 }" type="textarea"
 | 
			
		||||
                        ref="promptRef"
 | 
			
		||||
                        placeholder="这里输入你不希望出现在图片上的内容,元素"/>
 | 
			
		||||
            </div>
 | 
			
		||||
                  <el-upload class="img-uploader" :auto-upload="true" :show-file-list="false"
 | 
			
		||||
                             :http-request="uploadImg2" style="--el-color-primary:#47fff1">
 | 
			
		||||
                    <el-image v-if="params.img2 !== ''" :src="params.img2" fit="cover"/>
 | 
			
		||||
                    <el-icon v-else class="uploader-icon">
 | 
			
		||||
                      <Plus/>
 | 
			
		||||
                    </el-icon>
 | 
			
		||||
                  </el-upload>
 | 
			
		||||
                </div>
 | 
			
		||||
              </el-tab-pane>
 | 
			
		||||
 | 
			
		||||
              <el-tab-pane label="换脸(可选)" name="swapFace">
 | 
			
		||||
                <div class="text">请上传两张有脸部的图片,用右边图片的脸替换左边图片的脸</div>
 | 
			
		||||
                <div class="img-inline">
 | 
			
		||||
                  <el-upload class="img-uploader" :auto-upload="true" :show-file-list="false"
 | 
			
		||||
                             :http-request="uploadImg" style="--el-color-primary:#47fff1">
 | 
			
		||||
                    <el-image v-if="params.img !== ''" :src="params.img" fit="cover"/>
 | 
			
		||||
                    <el-icon v-else class="uploader-icon">
 | 
			
		||||
                      <Plus/>
 | 
			
		||||
                    </el-icon>
 | 
			
		||||
                  </el-upload>
 | 
			
		||||
 | 
			
		||||
                  <el-upload class="img-uploader" :auto-upload="true" :show-file-list="false"
 | 
			
		||||
                             :http-request="uploadImg2" style="--el-color-primary:#47fff1">
 | 
			
		||||
                    <el-image v-if="params.img2 !== ''" :src="params.img2" fit="cover"/>
 | 
			
		||||
                    <el-icon v-else class="uploader-icon">
 | 
			
		||||
                      <Plus/>
 | 
			
		||||
                    </el-icon>
 | 
			
		||||
                  </el-upload>
 | 
			
		||||
                </div>
 | 
			
		||||
              </el-tab-pane>
 | 
			
		||||
            </el-tabs>
 | 
			
		||||
 | 
			
		||||
            <div class="submit-btn">
 | 
			
		||||
              <el-button color="#47fff1" :dark="false" @click="generate" round>立即生成</el-button>
 | 
			
		||||
@@ -516,6 +547,7 @@ const options = [
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
const params = ref({
 | 
			
		||||
  task_type: "image",
 | 
			
		||||
  rate: rates[0].value,
 | 
			
		||||
  model: models[0].value,
 | 
			
		||||
  chaos: 0,
 | 
			
		||||
@@ -523,6 +555,8 @@ const params = ref({
 | 
			
		||||
  seed: 0,
 | 
			
		||||
  raw: false,
 | 
			
		||||
  img: "",
 | 
			
		||||
  img2: "",
 | 
			
		||||
  img_arr: [],
 | 
			
		||||
  weight: 0.25,
 | 
			
		||||
  prompt: "",
 | 
			
		||||
  neg_prompt: "",
 | 
			
		||||
@@ -530,7 +564,7 @@ const params = ref({
 | 
			
		||||
  quality: 0
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
const activeName = ref('图生图')
 | 
			
		||||
const activeName = ref('image')
 | 
			
		||||
 | 
			
		||||
const runningJobs = ref([])
 | 
			
		||||
const finishedJobs = ref([])
 | 
			
		||||
@@ -552,10 +586,18 @@ const rewritePrompt = () => {
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const translatePrompt = () => {
 | 
			
		||||
const translatePrompt = (negative) => {
 | 
			
		||||
  loading.value = true
 | 
			
		||||
  httpPost("/api/prompt/translate", {"prompt": params.value.prompt}).then(res => {
 | 
			
		||||
    params.value.prompt = res.data
 | 
			
		||||
  let prompt = params.value.prompt
 | 
			
		||||
  if (negative) {
 | 
			
		||||
    prompt = params.value.neg_prompt
 | 
			
		||||
  }
 | 
			
		||||
  httpPost("/api/prompt/translate", {"prompt": prompt}).then(res => {
 | 
			
		||||
    if (negative) {
 | 
			
		||||
      params.value.neg_prompt = res.data
 | 
			
		||||
    } else {
 | 
			
		||||
      params.value.prompt = res.data
 | 
			
		||||
    }
 | 
			
		||||
    loading.value = false
 | 
			
		||||
  }).catch(e => {
 | 
			
		||||
    loading.value = false
 | 
			
		||||
@@ -684,7 +726,7 @@ const changeModel = (item) => {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 图片上传
 | 
			
		||||
const afterRead = (file) => {
 | 
			
		||||
const uploadImg = (file) => {
 | 
			
		||||
  // 压缩图片并上传
 | 
			
		||||
  new Compressor(file.file, {
 | 
			
		||||
    quality: 0.6,
 | 
			
		||||
@@ -704,10 +746,30 @@ const afterRead = (file) => {
 | 
			
		||||
    },
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
const uploadImg2 = (file) => {
 | 
			
		||||
  // 压缩图片并上传
 | 
			
		||||
  new Compressor(file.file, {
 | 
			
		||||
    quality: 0.6,
 | 
			
		||||
    success(result) {
 | 
			
		||||
      const formData = new FormData();
 | 
			
		||||
      formData.append('file', result, result.name);
 | 
			
		||||
      // 执行上传操作
 | 
			
		||||
      httpPost('/api/upload', formData).then((res) => {
 | 
			
		||||
        params.value.img2 = res.data.url
 | 
			
		||||
        ElMessage.success('上传成功')
 | 
			
		||||
      }).catch((e) => {
 | 
			
		||||
        ElMessage.error('上传失败:' + e.message)
 | 
			
		||||
      })
 | 
			
		||||
    },
 | 
			
		||||
    error(err) {
 | 
			
		||||
      console.log(err.message);
 | 
			
		||||
    },
 | 
			
		||||
  });
 | 
			
		||||
};
 | 
			
		||||
// 创建绘图任务
 | 
			
		||||
const promptRef = ref(null)
 | 
			
		||||
const generate = () => {
 | 
			
		||||
  if (params.value.prompt === '') {
 | 
			
		||||
  if (params.value.prompt === '' && params.value.task_type === "image") {
 | 
			
		||||
    promptRef.value.focus()
 | 
			
		||||
    return ElMessage.error("请输入绘画提示词!")
 | 
			
		||||
  }
 | 
			
		||||
@@ -715,6 +777,12 @@ const generate = () => {
 | 
			
		||||
    return ElMessage.error("动漫模型不允许启用原始模式")
 | 
			
		||||
  }
 | 
			
		||||
  params.value.session_id = getSessionId()
 | 
			
		||||
  if (params.value.img !== "") {
 | 
			
		||||
    params.value.img_arr.push(params.value.img)
 | 
			
		||||
  }
 | 
			
		||||
  if (params.value.img2 !== "") {
 | 
			
		||||
    params.value.img_arr.push(params.value.img2)
 | 
			
		||||
  }
 | 
			
		||||
  httpPost("/api/mj/image", params.value).then(() => {
 | 
			
		||||
    ElMessage.success("绘画任务推送成功,请耐心等待任务执行...")
 | 
			
		||||
    imgCalls.value -= 1
 | 
			
		||||
@@ -725,7 +793,6 @@ const generate = () => {
 | 
			
		||||
 | 
			
		||||
// 图片放大任务
 | 
			
		||||
const upscale = (index, item) => {
 | 
			
		||||
  console.log(item)
 | 
			
		||||
  send('/api/mj/upscale', index, item)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -783,6 +850,11 @@ const publishImage = (item, action) => {
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 切换菜单
 | 
			
		||||
const tabChange = (tab) => {
 | 
			
		||||
  params.value.task_type = tab
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang="stylus">
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="mobile-user-profile container">
 | 
			
		||||
  <div class="mobile-mj container">
 | 
			
		||||
    <van-nav-bar :title="title"/>
 | 
			
		||||
 | 
			
		||||
    <div class="content">
 | 
			
		||||
@@ -56,7 +56,7 @@ import {showFailToast, showNotify, showSuccessToast} from "vant";
 | 
			
		||||
import {httpGet, httpPost} from "@/utils/http";
 | 
			
		||||
import Compressor from 'compressorjs';
 | 
			
		||||
 | 
			
		||||
const title = ref('用户设置')
 | 
			
		||||
const title = ref('MidJourney 绘画')
 | 
			
		||||
const form = ref({
 | 
			
		||||
  username: '',
 | 
			
		||||
  nickname: '',
 | 
			
		||||
@@ -116,13 +116,6 @@ const save = () => {
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang="stylus">
 | 
			
		||||
.mobile-user-profile {
 | 
			
		||||
  .content {
 | 
			
		||||
    .van-field__label {
 | 
			
		||||
      width 100px
 | 
			
		||||
      text-align right
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
<style lang="stylus" scoped>
 | 
			
		||||
@import "@/assets/css/mobile/image-mj.styl"
 | 
			
		||||
</style>
 | 
			
		||||
		Reference in New Issue
	
	Block a user