refactor parameters for JimengCreate page
@@ -9,10 +9,8 @@ type JimengConfig struct {
|
|||||||
|
|
||||||
// JimengPower 即梦AI算力配置
|
// JimengPower 即梦AI算力配置
|
||||||
type JimengPower struct {
|
type JimengPower struct {
|
||||||
TextToImage int `json:"text_to_image"`
|
Image int `json:"image"` // 图片生成算力,单位:积分/张
|
||||||
ImageToImage int `json:"image_to_image"`
|
Video int `json:"video"` // 视频生成算力,单位:积分/秒
|
||||||
ImageEdit int `json:"image_edit"`
|
VirtualHuman int `json:"virtual_human"` // 数字人视频生成算力,单位:积分/秒
|
||||||
ImageEffects int `json:"image_effects"`
|
ActionTransfer int `json:"action_transfer"` // 视频动作迁移算力,单位:积分/秒
|
||||||
TextToVideo int `json:"text_to_video"`
|
|
||||||
ImageToVideo int `json:"image_to_video"`
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -231,28 +231,20 @@ func (h *AdminJimengHandler) UpdateConfig(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 验证算力配置
|
// 验证算力配置
|
||||||
if req.Power.TextToImage <= 0 {
|
if req.Power.Image <= 0 {
|
||||||
resp.ERROR(c, "文生图算力必须大于0")
|
resp.ERROR(c, "图片生成算力必须大于0")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if req.Power.ImageToImage <= 0 {
|
if req.Power.Video <= 0 {
|
||||||
resp.ERROR(c, "图生图算力必须大于0")
|
resp.ERROR(c, "视频生成算力必须大于0")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if req.Power.ImageEdit <= 0 {
|
if req.Power.VirtualHuman <= 0 {
|
||||||
resp.ERROR(c, "图片编辑算力必须大于0")
|
resp.ERROR(c, "数字人生成算力必须大于0")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if req.Power.ImageEffects <= 0 {
|
if req.Power.ActionTransfer <= 0 {
|
||||||
resp.ERROR(c, "图片特效算力必须大于0")
|
resp.ERROR(c, "视频动作迁移算力必须大于0")
|
||||||
return
|
|
||||||
}
|
|
||||||
if req.Power.TextToVideo <= 0 {
|
|
||||||
resp.ERROR(c, "文生视频算力必须大于0")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if req.Power.ImageToVideo <= 0 {
|
|
||||||
resp.ERROR(c, "图生视频算力必须大于0")
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -132,8 +132,8 @@ func (h *JimengHandler) CreateTask(c *gin.Context) {
|
|||||||
|
|
||||||
switch req.TaskType {
|
switch req.TaskType {
|
||||||
case "text_to_image":
|
case "text_to_image":
|
||||||
powerCost = h.getPowerFromConfig(model.JMTaskTypeTextToImage)
|
powerCost = h.getPowerFromConfig(model.JMTaskTypeImage)
|
||||||
taskType = model.JMTaskTypeTextToImage
|
taskType = model.JMTaskTypeImage
|
||||||
reqKey = jimeng.ReqKeyTextToImage
|
reqKey = jimeng.ReqKeyTextToImage
|
||||||
modelName = "即梦文生图"
|
modelName = "即梦文生图"
|
||||||
if req.Scale == 0 {
|
if req.Scale == 0 {
|
||||||
@@ -147,8 +147,8 @@ func (h *JimengHandler) CreateTask(c *gin.Context) {
|
|||||||
"use_pre_llm": req.UsePreLLM,
|
"use_pre_llm": req.UsePreLLM,
|
||||||
}
|
}
|
||||||
case "image_to_image":
|
case "image_to_image":
|
||||||
powerCost = h.getPowerFromConfig(model.JMTaskTypeImageToImage)
|
powerCost = h.getPowerFromConfig(model.JMTaskTypeVideo)
|
||||||
taskType = model.JMTaskTypeImageToImage
|
taskType = model.JMTaskTypeVideo
|
||||||
reqKey = jimeng.ReqKeyImageToImagePortrait
|
reqKey = jimeng.ReqKeyImageToImagePortrait
|
||||||
modelName = "即梦图生图"
|
modelName = "即梦图生图"
|
||||||
if req.Gpen == 0 {
|
if req.Gpen == 0 {
|
||||||
@@ -175,8 +175,8 @@ func (h *JimengHandler) CreateTask(c *gin.Context) {
|
|||||||
"seed": req.Seed,
|
"seed": req.Seed,
|
||||||
}
|
}
|
||||||
case "image_edit":
|
case "image_edit":
|
||||||
powerCost = h.getPowerFromConfig(model.JMTaskTypeImageEdit)
|
powerCost = h.getPowerFromConfig(model.JMTaskTypeVirtualHuman)
|
||||||
taskType = model.JMTaskTypeImageEdit
|
taskType = model.JMTaskTypeVirtualHuman
|
||||||
reqKey = jimeng.ReqKeyImageEdit
|
reqKey = jimeng.ReqKeyImageEdit
|
||||||
modelName = "即梦图像编辑"
|
modelName = "即梦图像编辑"
|
||||||
if req.Scale == 0 {
|
if req.Scale == 0 {
|
||||||
@@ -188,8 +188,8 @@ func (h *JimengHandler) CreateTask(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
params["image_urls"] = []string{req.ImageInput}
|
params["image_urls"] = []string{req.ImageInput}
|
||||||
case "image_effects":
|
case "image_effects":
|
||||||
powerCost = h.getPowerFromConfig(model.JMTaskTypeImageEffects)
|
powerCost = h.getPowerFromConfig(model.JMTaskTypeActionTransfer)
|
||||||
taskType = model.JMTaskTypeImageEffects
|
taskType = model.JMTaskTypeActionTransfer
|
||||||
reqKey = jimeng.ReqKeyImageEffects
|
reqKey = jimeng.ReqKeyImageEffects
|
||||||
modelName = "即梦图像特效"
|
modelName = "即梦图像特效"
|
||||||
if req.Width == 0 {
|
if req.Width == 0 {
|
||||||
@@ -205,8 +205,8 @@ func (h *JimengHandler) CreateTask(c *gin.Context) {
|
|||||||
"height": req.Height,
|
"height": req.Height,
|
||||||
}
|
}
|
||||||
case "text_to_video":
|
case "text_to_video":
|
||||||
powerCost = h.getPowerFromConfig(model.JMTaskTypeTextToVideo)
|
powerCost = h.getPowerFromConfig(model.JMTaskTypeVideo)
|
||||||
taskType = model.JMTaskTypeTextToVideo
|
taskType = model.JMTaskTypeVideo
|
||||||
reqKey = jimeng.ReqKeyTextToVideo
|
reqKey = jimeng.ReqKeyTextToVideo
|
||||||
modelName = "即梦文生视频"
|
modelName = "即梦文生视频"
|
||||||
if req.AspectRatio == "" {
|
if req.AspectRatio == "" {
|
||||||
@@ -217,8 +217,8 @@ func (h *JimengHandler) CreateTask(c *gin.Context) {
|
|||||||
"aspect_ratio": req.AspectRatio,
|
"aspect_ratio": req.AspectRatio,
|
||||||
}
|
}
|
||||||
case "image_to_video":
|
case "image_to_video":
|
||||||
powerCost = h.getPowerFromConfig(model.JMTaskTypeImageToVideo)
|
powerCost = h.getPowerFromConfig(model.JMTaskTypeVideo)
|
||||||
taskType = model.JMTaskTypeImageToVideo
|
taskType = model.JMTaskTypeVideo
|
||||||
reqKey = jimeng.ReqKeyImageToVideo
|
reqKey = jimeng.ReqKeyImageToVideo
|
||||||
modelName = "即梦图生视频"
|
modelName = "即梦图生视频"
|
||||||
params = map[string]any{
|
params = map[string]any{
|
||||||
@@ -287,17 +287,9 @@ func (h *JimengHandler) Jobs(c *gin.Context) {
|
|||||||
|
|
||||||
switch req.Filter {
|
switch req.Filter {
|
||||||
case "image":
|
case "image":
|
||||||
query = query.Where("type IN (?)", []model.JMTaskType{
|
query = query.Where("type = ?", model.JMTaskTypeImage)
|
||||||
model.JMTaskTypeTextToImage,
|
|
||||||
model.JMTaskTypeImageToImage,
|
|
||||||
model.JMTaskTypeImageEdit,
|
|
||||||
model.JMTaskTypeImageEffects,
|
|
||||||
})
|
|
||||||
case "video":
|
case "video":
|
||||||
query = query.Where("type IN (?)", []model.JMTaskType{
|
query = query.Where("type = ?", model.JMTaskTypeVideo)
|
||||||
model.JMTaskTypeTextToVideo,
|
|
||||||
model.JMTaskTypeImageToVideo,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(req.Ids) > 0 {
|
if len(req.Ids) > 0 {
|
||||||
@@ -438,18 +430,14 @@ func (h *JimengHandler) getPowerFromConfig(taskType model.JMTaskType) int {
|
|||||||
config := h.App.SysConfig.Jimeng
|
config := h.App.SysConfig.Jimeng
|
||||||
|
|
||||||
switch taskType {
|
switch taskType {
|
||||||
case model.JMTaskTypeTextToImage:
|
case model.JMTaskTypeImage:
|
||||||
return config.Power.TextToImage
|
return config.Power.Image
|
||||||
case model.JMTaskTypeImageToImage:
|
case model.JMTaskTypeVideo:
|
||||||
return config.Power.ImageToImage
|
return config.Power.Video
|
||||||
case model.JMTaskTypeImageEdit:
|
case model.JMTaskTypeVirtualHuman:
|
||||||
return config.Power.ImageEdit
|
return config.Power.VirtualHuman
|
||||||
case model.JMTaskTypeImageEffects:
|
case model.JMTaskTypeActionTransfer:
|
||||||
return config.Power.ImageEffects
|
return config.Power.ActionTransfer
|
||||||
case model.JMTaskTypeTextToVideo:
|
|
||||||
return config.Power.TextToVideo
|
|
||||||
case model.JMTaskTypeImageToVideo:
|
|
||||||
return config.Power.ImageToVideo
|
|
||||||
default:
|
default:
|
||||||
return 10
|
return 10
|
||||||
}
|
}
|
||||||
@@ -459,11 +447,9 @@ func (h *JimengHandler) getPowerFromConfig(taskType model.JMTaskType) int {
|
|||||||
func (h *JimengHandler) GetPowerConfig(c *gin.Context) {
|
func (h *JimengHandler) GetPowerConfig(c *gin.Context) {
|
||||||
config := h.App.SysConfig.Jimeng
|
config := h.App.SysConfig.Jimeng
|
||||||
resp.SUCCESS(c, gin.H{
|
resp.SUCCESS(c, gin.H{
|
||||||
"text_to_image": config.Power.TextToImage,
|
"image": config.Power.Image,
|
||||||
"image_to_image": config.Power.ImageToImage,
|
"video": config.Power.Video,
|
||||||
"image_edit": config.Power.ImageEdit,
|
"image_edit": config.Power.VirtualHuman,
|
||||||
"image_effects": config.Power.ImageEffects,
|
"image_effects": config.Power.ActionTransfer,
|
||||||
"text_to_video": config.Power.TextToVideo,
|
|
||||||
"image_to_video": config.Power.ImageToVideo,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -199,18 +199,14 @@ func (s *Service) buildTaskRequest(job *model.JimengJob) (*SubmitTaskRequest, er
|
|||||||
|
|
||||||
// 根据任务类型设置特定参数
|
// 根据任务类型设置特定参数
|
||||||
switch job.Type {
|
switch job.Type {
|
||||||
case model.JMTaskTypeTextToImage:
|
case model.JMTaskTypeImage:
|
||||||
s.setTextToImageParams(req, params)
|
s.setTextToImageParams(req, params)
|
||||||
case model.JMTaskTypeImageToImage:
|
case model.JMTaskTypeVideo:
|
||||||
s.setImageToImageParams(req, params)
|
s.setImageToImageParams(req, params)
|
||||||
case model.JMTaskTypeImageEdit:
|
case model.JMTaskTypeVirtualHuman:
|
||||||
s.setImageEditParams(req, params)
|
s.setImageEditParams(req, params)
|
||||||
case model.JMTaskTypeImageEffects:
|
case model.JMTaskTypeActionTransfer:
|
||||||
s.setImageEffectsParams(req, params)
|
s.setImageEffectsParams(req, params)
|
||||||
case model.JMTaskTypeTextToVideo:
|
|
||||||
s.setTextToVideoParams(req, params)
|
|
||||||
case model.JMTaskTypeImageToVideo:
|
|
||||||
s.setImageToVideoParams(req, params)
|
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("unsupported task type: %s", job.Type)
|
return nil, fmt.Errorf("unsupported task type: %s", job.Type)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,12 +41,10 @@ const (
|
|||||||
type JMTaskType string
|
type JMTaskType string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
JMTaskTypeTextToImage = JMTaskType("text_to_image") // 文生图
|
JMTaskTypeImage = JMTaskType("image") // 文生图
|
||||||
JMTaskTypeImageToImage = JMTaskType("image_to_image") // 图生图
|
JMTaskTypeVideo = JMTaskType("video") // 图生图
|
||||||
JMTaskTypeImageEdit = JMTaskType("image_edit") // 图像编辑
|
JMTaskTypeVirtualHuman = JMTaskType("virtual_human") // 图像编辑
|
||||||
JMTaskTypeImageEffects = JMTaskType("image_effects") // 图像特效
|
JMTaskTypeActionTransfer = JMTaskType("action_transfer") // 图像特效
|
||||||
JMTaskTypeTextToVideo = JMTaskType("text_to_video") // 文生视频
|
|
||||||
JMTaskTypeImageToVideo = JMTaskType("image_to_video") // 图生视频
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// TableName 返回数据表名称
|
// TableName 返回数据表名称
|
||||||
|
|||||||
@@ -49,16 +49,17 @@
|
|||||||
|
|
||||||
.category-btn {
|
.category-btn {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 15px 10px;
|
padding: 10px 15px;
|
||||||
border: 2px solid var(--border-color, #f0f0f0);
|
border: 2px solid var(--border-color, #f0f0f0);
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
background: var(--card-bg-secondary, #fafafa);
|
background: var(--card-bg-secondary, #fafafa);
|
||||||
/* 暗色主题支持 */
|
/* 暗色主题支持 */
|
||||||
[data-theme="dark"] & {
|
[data-theme='dark'] & {
|
||||||
background: var(--card-bg-secondary-dark, #23242a);
|
background: var(--card-bg-secondary-dark, #23242a);
|
||||||
border-color: var(--border-color-dark, #33343a);
|
border-color: var(--border-color-dark, #33343a);
|
||||||
}
|
}
|
||||||
@@ -66,7 +67,7 @@
|
|||||||
&:hover {
|
&:hover {
|
||||||
border-color: var(--primary-color, #5865f2);
|
border-color: var(--primary-color, #5865f2);
|
||||||
background: var(--card-bg-hover, #f8f9ff);
|
background: var(--card-bg-hover, #f8f9ff);
|
||||||
[data-theme="dark"] & {
|
[data-theme='dark'] & {
|
||||||
background: var(--card-bg-hover-dark, #2a2b31);
|
background: var(--card-bg-hover-dark, #2a2b31);
|
||||||
}
|
}
|
||||||
transform: translateY(-2px);
|
transform: translateY(-2px);
|
||||||
@@ -76,8 +77,11 @@
|
|||||||
border-color: var(--primary-color, #5865f2);
|
border-color: var(--primary-color, #5865f2);
|
||||||
background: var(--primary-gradient, linear-gradient(135deg, #5865f2 0%, #7289da 100%));
|
background: var(--primary-gradient, linear-gradient(135deg, #5865f2 0%, #7289da 100%));
|
||||||
color: var(--primary-text-on-primary, #fff);
|
color: var(--primary-text-on-primary, #fff);
|
||||||
[data-theme="dark"] & {
|
[data-theme='dark'] & {
|
||||||
background: var(--primary-gradient-dark, linear-gradient(135deg, #23242a 0%, #2a2b31 100%));
|
background: var(
|
||||||
|
--primary-gradient-dark,
|
||||||
|
linear-gradient(135deg, #23242a 0%, #2a2b31 100%)
|
||||||
|
);
|
||||||
color: var(--primary-text-on-primary-dark, #fff);
|
color: var(--primary-text-on-primary-dark, #fff);
|
||||||
}
|
}
|
||||||
transform: translateY(-2px);
|
transform: translateY(-2px);
|
||||||
@@ -96,108 +100,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 功能开关
|
|
||||||
.function-switch {
|
|
||||||
margin-bottom: 25px;
|
|
||||||
|
|
||||||
.switch-label {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
margin-bottom: 15px;
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: var(--text-theme-color);
|
|
||||||
|
|
||||||
.el-icon {
|
|
||||||
margin-right: 8px;
|
|
||||||
color: var(--primary-color, #5865f2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.switch-container {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
padding: 5px 15px;
|
|
||||||
border: 1px solid var(--border-color, #e0e0e0);
|
|
||||||
border-radius: 10px;
|
|
||||||
background: var(--card-bg-secondary, #f9f9f9);
|
|
||||||
[data-theme="dark"] & {
|
|
||||||
background: var(--card-bg-secondary-dark, #23242a);
|
|
||||||
border-color: var(--border-color-dark, #33343a);
|
|
||||||
}
|
|
||||||
|
|
||||||
.switch-info {
|
|
||||||
flex: 1;
|
|
||||||
|
|
||||||
.switch-title {
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: var(--text-theme-color);
|
|
||||||
margin-bottom: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.switch-desc {
|
|
||||||
font-size: 12px;
|
|
||||||
color: var(--text-sub-color, #666);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 参数容器
|
|
||||||
.params-container {
|
|
||||||
.function-panel {
|
|
||||||
.param-line {
|
|
||||||
margin-bottom: 15px;
|
|
||||||
|
|
||||||
&.pt {
|
|
||||||
margin-top: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.label {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
margin-bottom: 8px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: var(--text-theme-color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.item-group {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
margin-bottom: 15px;
|
|
||||||
|
|
||||||
.label {
|
|
||||||
margin-right: 15px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: var(--text-theme-color);
|
|
||||||
min-width: 80px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-info {
|
|
||||||
margin: 20px 0;
|
|
||||||
padding: 15px;
|
|
||||||
background: var(--info-bg, #f0f8ff);
|
|
||||||
border-radius: 8px;
|
|
||||||
border-left: 4px solid var(--primary-color, #5865f2);
|
|
||||||
}
|
|
||||||
|
|
||||||
.submit-btn {
|
|
||||||
margin-top: 30px;
|
|
||||||
|
|
||||||
.el-button {
|
|
||||||
width: 100%;
|
|
||||||
height: 50px;
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 右侧主要内容区域
|
// 右侧主要内容区域
|
||||||
@@ -239,6 +141,23 @@
|
|||||||
&:hover {
|
&:hover {
|
||||||
box-shadow: 0 4px 24px rgba(88, 101, 242, 0.12);
|
box-shadow: 0 4px 24px rgba(88, 101, 242, 0.12);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 增强任务项悬停动画
|
||||||
|
transition: box-shadow 3s cubic-bezier(0.4, 0, 0.2, 1),
|
||||||
|
transform 0.5s cubic-bezier(0.4, 0, 0.2, 1), border-color 0.5s;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
|
||||||
|
border: 1.5px solid transparent;
|
||||||
|
border-radius: 12px;
|
||||||
|
background: #fff;
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.18), 0 1.5px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
border-color: #a259ff;
|
||||||
|
transform: scale(1.025) translateY(-2px);
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
.task-left {
|
.task-left {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
flex: none;
|
flex: none;
|
||||||
@@ -253,18 +172,69 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
.preview-image, .preview-video {
|
.preview-image,
|
||||||
|
.preview-video {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 视频预览包装器
|
||||||
|
.preview-video-wrapper {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
.video-mask {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: rgba(0, 0, 0, 0.25);
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.2s;
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover .video-mask {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.play-btn {
|
||||||
|
width: 64px;
|
||||||
|
height: 64px;
|
||||||
|
background: rgba(255, 255, 255, 0.3);
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
||||||
|
cursor: pointer;
|
||||||
|
z-index: 3;
|
||||||
|
transition: background 0.2s;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: rgba(255, 255, 255, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 36px;
|
||||||
|
height: 36px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
.preview-placeholder {
|
.preview-placeholder {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
color: var(--text-disabled-color, #999);
|
color: var(--text-disabled-color, #999);
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
.el-icon, .iconfont {
|
.el-icon,
|
||||||
|
.iconfont {
|
||||||
font-size: 32px;
|
font-size: 32px;
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
}
|
}
|
||||||
@@ -347,3 +317,69 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 错误信息样式
|
||||||
|
.err-msg-clip {
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-line-clamp: 2;
|
||||||
|
line-clamp: 2;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
word-break: break-all;
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 模板选择器样式
|
||||||
|
.jimeng-template-select {
|
||||||
|
.el-select-dropdown__item {
|
||||||
|
height: 60px;
|
||||||
|
line-height: 60px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提示词指南样式
|
||||||
|
.prompt-guide {
|
||||||
|
margin: 12px 0 16px;
|
||||||
|
|
||||||
|
.guide-title {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.guide-content {
|
||||||
|
max-height: 220px;
|
||||||
|
overflow: auto;
|
||||||
|
line-height: 1.6;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #555;
|
||||||
|
padding-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.guide-section {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.guide-subtitle {
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
list-style: disc;
|
||||||
|
padding-left: 18px;
|
||||||
|
margin: 4px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quote {
|
||||||
|
margin: 8px 0;
|
||||||
|
padding: 8px 10px;
|
||||||
|
border-left: 3px solid #a3a3a3;
|
||||||
|
background: #f8f8f8;
|
||||||
|
border-radius: 4px;
|
||||||
|
color: #444;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
@font-face {
|
@font-face {
|
||||||
font-family: "iconfont"; /* Project id 4125778 */
|
font-family: "iconfont"; /* Project id 4125778 */
|
||||||
src: url('iconfont.woff2?t=1757465848673') format('woff2'),
|
src: url('iconfont.woff2?t=1757571432313') format('woff2'),
|
||||||
url('iconfont.woff?t=1757465848673') format('woff'),
|
url('iconfont.woff?t=1757571432313') format('woff'),
|
||||||
url('iconfont.ttf?t=1757465848673') format('truetype');
|
url('iconfont.ttf?t=1757571432313') format('truetype');
|
||||||
}
|
}
|
||||||
|
|
||||||
.iconfont {
|
.iconfont {
|
||||||
@@ -13,6 +13,26 @@
|
|||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.icon-resize:before {
|
||||||
|
content: "\e718";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-template:before {
|
||||||
|
content: "\e8a6";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-error-line:before {
|
||||||
|
content: "\e868";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-success-line:before {
|
||||||
|
content: "\e88c";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-yunjing:before {
|
||||||
|
content: "\e69b";
|
||||||
|
}
|
||||||
|
|
||||||
.icon-action:before {
|
.icon-action:before {
|
||||||
content: "\e658";
|
content: "\e658";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,41 @@
|
|||||||
"css_prefix_text": "icon-",
|
"css_prefix_text": "icon-",
|
||||||
"description": "",
|
"description": "",
|
||||||
"glyphs": [
|
"glyphs": [
|
||||||
|
{
|
||||||
|
"icon_id": "10564356",
|
||||||
|
"name": "resize",
|
||||||
|
"font_class": "resize",
|
||||||
|
"unicode": "e718",
|
||||||
|
"unicode_decimal": 59160
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "1727381",
|
||||||
|
"name": "34模板、框架",
|
||||||
|
"font_class": "template",
|
||||||
|
"unicode": "e8a6",
|
||||||
|
"unicode_decimal": 59558
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "9626841",
|
||||||
|
"name": "错误",
|
||||||
|
"font_class": "error-line",
|
||||||
|
"unicode": "e868",
|
||||||
|
"unicode_decimal": 59496
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "9626990",
|
||||||
|
"name": "正确",
|
||||||
|
"font_class": "success-line",
|
||||||
|
"unicode": "e88c",
|
||||||
|
"unicode_decimal": 59532
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "40613765",
|
||||||
|
"name": "运镜控制",
|
||||||
|
"font_class": "yunjing",
|
||||||
|
"unicode": "e69b",
|
||||||
|
"unicode_decimal": 59035
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"icon_id": "5215282",
|
"icon_id": "5215282",
|
||||||
"name": "动作",
|
"name": "动作",
|
||||||
|
|||||||
BIN
web/src/assets/img/jimeng/texiao/Christmas_green_background.jpeg
Normal file
|
After Width: | Height: | Size: 111 KiB |
BIN
web/src/assets/img/jimeng/texiao/Christmas_tree.jpeg
Normal file
|
After Width: | Height: | Size: 118 KiB |
|
After Width: | Height: | Size: 143 KiB |
|
After Width: | Height: | Size: 95 KiB |
|
After Width: | Height: | Size: 1.2 MiB |
BIN
web/src/assets/img/jimeng/texiao/acrylic_ornaments.png
Normal file
|
After Width: | Height: | Size: 1.5 MiB |
BIN
web/src/assets/img/jimeng/texiao/angel_figurine.png
Normal file
|
After Width: | Height: | Size: 933 KiB |
BIN
web/src/assets/img/jimeng/texiao/birthday_photo_gorgeous.jpeg
Normal file
|
After Width: | Height: | Size: 137 KiB |
BIN
web/src/assets/img/jimeng/texiao/birthday_photo_party.jpeg
Normal file
|
After Width: | Height: | Size: 98 KiB |
BIN
web/src/assets/img/jimeng/texiao/birthday_photo_red.jpeg
Normal file
|
After Width: | Height: | Size: 96 KiB |
BIN
web/src/assets/img/jimeng/texiao/car_miniature_ornaments.jpeg
Normal file
|
After Width: | Height: | Size: 78 KiB |
BIN
web/src/assets/img/jimeng/texiao/claw_machine_style.jpeg
Normal file
|
After Width: | Height: | Size: 47 KiB |
BIN
web/src/assets/img/jimeng/texiao/earphone_case_style.jpeg
Normal file
|
After Width: | Height: | Size: 42 KiB |
BIN
web/src/assets/img/jimeng/texiao/electronic_pet_egg_style.jpeg
Normal file
|
After Width: | Height: | Size: 67 KiB |
BIN
web/src/assets/img/jimeng/texiao/felt_3d_polaroid.png
Normal file
|
After Width: | Height: | Size: 1.5 MiB |
BIN
web/src/assets/img/jimeng/texiao/felt_keychain.png
Normal file
|
After Width: | Height: | Size: 1.6 MiB |
BIN
web/src/assets/img/jimeng/texiao/furry_dream_doll.png
Normal file
|
After Width: | Height: | Size: 1.6 MiB |
BIN
web/src/assets/img/jimeng/texiao/glass_ball.png
Normal file
|
After Width: | Height: | Size: 1.4 MiB |
BIN
web/src/assets/img/jimeng/texiao/graduation_photo.png
Normal file
|
After Width: | Height: | Size: 1.3 MiB |
|
After Width: | Height: | Size: 1.7 MiB |
BIN
web/src/assets/img/jimeng/texiao/lying_in_fluffy_belly.png
Normal file
|
After Width: | Height: | Size: 1.8 MiB |
BIN
web/src/assets/img/jimeng/texiao/micro_landscape_mini_world.png
Normal file
|
After Width: | Height: | Size: 1.3 MiB |
|
After Width: | Height: | Size: 982 KiB |
BIN
web/src/assets/img/jimeng/texiao/my_world.png
Normal file
|
After Width: | Height: | Size: 1.9 MiB |
BIN
web/src/assets/img/jimeng/texiao/my_world_universal.png
Normal file
|
After Width: | Height: | Size: 1.5 MiB |
BIN
web/src/assets/img/jimeng/texiao/patchwork_collage_style.jpeg
Normal file
|
After Width: | Height: | Size: 115 KiB |
BIN
web/src/assets/img/jimeng/texiao/plastic_bubble_figure.png
Normal file
|
After Width: | Height: | Size: 1.5 MiB |
|
After Width: | Height: | Size: 1.3 MiB |
|
Before Width: | Height: | Size: 1022 KiB After Width: | Height: | Size: 1022 KiB |
|
Before Width: | Height: | Size: 1016 KiB After Width: | Height: | Size: 1016 KiB |
|
Before Width: | Height: | Size: 1002 KiB After Width: | Height: | Size: 1002 KiB |
|
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 856 KiB After Width: | Height: | Size: 856 KiB |
|
Before Width: | Height: | Size: 877 KiB After Width: | Height: | Size: 877 KiB |
|
Before Width: | Height: | Size: 698 KiB After Width: | Height: | Size: 698 KiB |
|
Before Width: | Height: | Size: 948 KiB After Width: | Height: | Size: 948 KiB |
|
Before Width: | Height: | Size: 1021 KiB After Width: | Height: | Size: 1021 KiB |
|
Before Width: | Height: | Size: 874 KiB After Width: | Height: | Size: 874 KiB |
|
Before Width: | Height: | Size: 809 KiB After Width: | Height: | Size: 809 KiB |
@@ -2,10 +2,10 @@
|
|||||||
<div class="foot-container">
|
<div class="foot-container">
|
||||||
<div class="footer text-base">
|
<div class="footer text-base">
|
||||||
<div>
|
<div>
|
||||||
<a :href="gitURL" target="_blank">
|
<span>
|
||||||
{{ title }} -
|
{{ title }} -
|
||||||
{{ version }}
|
{{ version }}
|
||||||
</a>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex justify-center text-sm">
|
<div class="flex justify-center text-sm">
|
||||||
<span class="mr-2">{{ copyRight }}</span>
|
<span class="mr-2">{{ copyRight }}</span>
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
<span class="label text-sm">{{ item.name }}</span>
|
<span class="label text-sm">{{ item.name }}</span>
|
||||||
<div class="whitespace-pre-line">
|
<div class="whitespace-pre-line">
|
||||||
<span
|
<span
|
||||||
class="text-xs text-gray-500 break-words whitespace-pre-line line-clamp-1"
|
class="text-xs text-gray-500 break-words line-clamp-1 max-w-[200px]"
|
||||||
:title="item.label"
|
:title="item.label"
|
||||||
>{{ item.label }}</span
|
>{{ item.label }}</span
|
||||||
>
|
>
|
||||||
@@ -90,7 +90,11 @@
|
|||||||
v-model="modelValue[param.name]"
|
v-model="modelValue[param.name]"
|
||||||
:placeholder="param.placeholder"
|
:placeholder="param.placeholder"
|
||||||
:popper-class="param.popperClass"
|
:popper-class="param.popperClass"
|
||||||
|
filterable
|
||||||
>
|
>
|
||||||
|
<template #prefix v-if="param.prefix">
|
||||||
|
<i class="iconfont !text-lg" :class="param.prefix"></i>
|
||||||
|
</template>
|
||||||
<el-option
|
<el-option
|
||||||
v-for="option in param.options"
|
v-for="option in param.options"
|
||||||
:key="option.value"
|
:key="option.value"
|
||||||
@@ -99,11 +103,18 @@
|
|||||||
>
|
>
|
||||||
<div class="flex justify-start" v-if="option.image">
|
<div class="flex justify-start" v-if="option.image">
|
||||||
<span class="flex py-3 mr-2">
|
<span class="flex py-3 mr-2">
|
||||||
<img :src="option.image" class="w-[54px] h-[54px] rounded-lg"
|
<img
|
||||||
|
:src="option.image"
|
||||||
|
class="rounded-lg"
|
||||||
|
:style="{ width: param.imgSize, height: param.imgSize }"
|
||||||
/></span>
|
/></span>
|
||||||
<div class="flex !items-start flex-col py-2 space-y-1">
|
<div class="flex !items-start flex-col py-2 space-y-1">
|
||||||
<span class="label text-sm">{{ option.label }}</span>
|
<span class="label text-sm">{{ option.label }}</span>
|
||||||
<span class="text-xs text-gray-500">{{ option.value }}</span>
|
<span
|
||||||
|
class="text-xs text-gray-500 break-words line-clamp-1 max-w-[200px]"
|
||||||
|
:title="option.value"
|
||||||
|
>{{ option.value }}</span
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex justify-start items-center h-full" v-else>
|
<div class="flex justify-start items-center h-full" v-else>
|
||||||
@@ -148,6 +159,11 @@ const props = defineProps({
|
|||||||
type: Object,
|
type: Object,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
|
requiredKeys: {
|
||||||
|
type: Object,
|
||||||
|
default: {},
|
||||||
|
required: false,
|
||||||
|
},
|
||||||
items: {
|
items: {
|
||||||
type: Array,
|
type: Array,
|
||||||
required: true,
|
required: true,
|
||||||
@@ -159,15 +175,20 @@ const props = defineProps({
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const selectedModel = ref({ label: '请选择模型' })
|
const selectedModel = ref(props.items[0])
|
||||||
|
const requiredKeys = ref(props.requiredKeys)
|
||||||
|
|
||||||
const emit = defineEmits(['update:modelValue'])
|
const emit = defineEmits(['update:modelValue'])
|
||||||
|
|
||||||
// 初始化 modelValue 默认值
|
// 初始化 modelValue 默认值
|
||||||
const initModelValue = (model) => {
|
const initModelValue = (model) => {
|
||||||
const defaultValues = {}
|
const defaultValues = {}
|
||||||
|
requiredKeys.value = {}
|
||||||
if (model && model.params) {
|
if (model && model.params) {
|
||||||
model.params.forEach((param) => {
|
model.params.forEach((param) => {
|
||||||
|
if (param.required) {
|
||||||
|
requiredKeys.value[param.name] = { required: true, label: param.label }
|
||||||
|
}
|
||||||
// 根据参数类型设置默认值
|
// 根据参数类型设置默认值
|
||||||
switch (param.type) {
|
switch (param.type) {
|
||||||
case 'text':
|
case 'text':
|
||||||
@@ -201,6 +222,7 @@ const initModelValue = (model) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
defaultValues.model = selectedModel.value.key
|
||||||
return defaultValues
|
return defaultValues
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,6 +238,22 @@ watch(
|
|||||||
{ deep: true }
|
{ deep: true }
|
||||||
)
|
)
|
||||||
|
|
||||||
|
watch(
|
||||||
|
requiredKeys,
|
||||||
|
(newValue) => {
|
||||||
|
emit('update:requiredKeys', newValue)
|
||||||
|
},
|
||||||
|
{ deep: true }
|
||||||
|
)
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.items,
|
||||||
|
(newValue) => {
|
||||||
|
selectedModel.value = newValue[0]
|
||||||
|
},
|
||||||
|
{ deep: true }
|
||||||
|
)
|
||||||
|
|
||||||
// 组件挂载时初始化
|
// 组件挂载时初始化
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// 确保初始值被正确设置
|
// 确保初始值被正确设置
|
||||||
|
|||||||
@@ -1,17 +1,107 @@
|
|||||||
import central_orbit from '@/assets/img/jimeng/central_orbit.webp'
|
import central_orbit from '@/assets/img/jimeng/yunjing/central_orbit.webp'
|
||||||
import clockwise_swivel from '@/assets/img/jimeng/clockwise_swivel.webp'
|
import clockwise_swivel from '@/assets/img/jimeng/yunjing/clockwise_swivel.webp'
|
||||||
import counterclockwise_swivel from '@/assets/img/jimeng/counterclockwise_swivel.webp'
|
import counterclockwise_swivel from '@/assets/img/jimeng/yunjing/counterclockwise_swivel.webp'
|
||||||
import crane_push from '@/assets/img/jimeng/crane_push.webp'
|
import crane_push from '@/assets/img/jimeng/yunjing/crane_push.webp'
|
||||||
import dynamic_orbit from '@/assets/img/jimeng/dynamic_orbit.webp'
|
import dynamic_orbit from '@/assets/img/jimeng/yunjing/dynamic_orbit.webp'
|
||||||
import handheld from '@/assets/img/jimeng/handheld.webp'
|
import handheld from '@/assets/img/jimeng/yunjing/handheld.webp'
|
||||||
import hitchcock_dolly_in from '@/assets/img/jimeng/hitchcock_dolly_in.webp'
|
import hitchcock_dolly_in from '@/assets/img/jimeng/yunjing/hitchcock_dolly_in.webp'
|
||||||
import hitchcock_dolly_out from '@/assets/img/jimeng/hitchcock_dolly_out.webp'
|
import hitchcock_dolly_out from '@/assets/img/jimeng/yunjing/hitchcock_dolly_out.webp'
|
||||||
import quick_pull_back from '@/assets/img/jimeng/quick_pull_back.webp'
|
import quick_pull_back from '@/assets/img/jimeng/yunjing/quick_pull_back.webp'
|
||||||
import rapid_push_pull from '@/assets/img/jimeng/rapid_push_pull.webp'
|
import rapid_push_pull from '@/assets/img/jimeng/yunjing/rapid_push_pull.webp'
|
||||||
import robo_arm from '@/assets/img/jimeng/robo_arm.webp'
|
import robo_arm from '@/assets/img/jimeng/yunjing/robo_arm.webp'
|
||||||
|
|
||||||
|
import acrylic_ornaments from '@/assets/img/jimeng/texiao/acrylic_ornaments.png'
|
||||||
|
import angel_figurine from '@/assets/img/jimeng/texiao/angel_figurine.png'
|
||||||
|
import birthday_photo_gorgeous from '@/assets/img/jimeng/texiao/birthday_photo_gorgeous.jpeg'
|
||||||
|
import birthday_photo_party from '@/assets/img/jimeng/texiao/birthday_photo_party.jpeg'
|
||||||
|
import birthday_photo_red from '@/assets/img/jimeng/texiao/birthday_photo_red.jpeg'
|
||||||
|
import car_miniature_ornaments from '@/assets/img/jimeng/texiao/car_miniature_ornaments.jpeg'
|
||||||
|
import Christmas_green_background from '@/assets/img/jimeng/texiao/Christmas_green_background.jpeg'
|
||||||
|
import Christmas_tree from '@/assets/img/jimeng/texiao/Christmas_tree.jpeg'
|
||||||
|
import claw_machine_style from '@/assets/img/jimeng/texiao/claw_machine_style.jpeg'
|
||||||
|
import earphone_case_style from '@/assets/img/jimeng/texiao/earphone_case_style.jpeg'
|
||||||
|
import electronic_pet_egg_style from '@/assets/img/jimeng/texiao/electronic_pet_egg_style.jpeg'
|
||||||
|
import felt_3d_polaroid from '@/assets/img/jimeng/texiao/felt_3d_polaroid.png'
|
||||||
|
import felt_keychain from '@/assets/img/jimeng/texiao/felt_keychain.png'
|
||||||
|
import furry_dream_doll from '@/assets/img/jimeng/texiao/furry_dream_doll.png'
|
||||||
|
import glass_ball from '@/assets/img/jimeng/texiao/glass_ball.png'
|
||||||
|
import graduation_photo from '@/assets/img/jimeng/texiao/graduation_photo.png'
|
||||||
|
import lofi_pixel_character_mini_card from '@/assets/img/jimeng/texiao/lofi_pixel_character_mini_card.png'
|
||||||
|
import lying_in_fluffy_belly from '@/assets/img/jimeng/texiao/lying_in_fluffy_belly.png'
|
||||||
|
import micro_landscape_mini_world from '@/assets/img/jimeng/texiao/micro_landscape_mini_world.png'
|
||||||
|
import micro_landscape_mini_world_professional from '@/assets/img/jimeng/texiao/micro_landscape_mini_world_professional.png'
|
||||||
|
import Mid_Autumn_Festival_individual from '@/assets/img/jimeng/texiao/Mid-Autumn_Festival_individual.jpeg'
|
||||||
|
import Mid_Autumn_Festival_new_chinese_style from '@/assets/img/jimeng/texiao/Mid-Autumn_Festival_new_chinese_style.jpeg'
|
||||||
|
import my_world from '@/assets/img/jimeng/texiao/my_world.png'
|
||||||
|
import my_world_universal from '@/assets/img/jimeng/texiao/my_world_universal.png'
|
||||||
|
import patchwork_collage_style from '@/assets/img/jimeng/texiao/patchwork_collage_style.jpeg'
|
||||||
|
import plastic_bubble_figure from '@/assets/img/jimeng/texiao/plastic_bubble_figure.png'
|
||||||
|
import plastic_bubble_figure_cartoon_text from '@/assets/img/jimeng/texiao/plastic_bubble_figure_cartoon_text.png'
|
||||||
|
import Spring_Festival_traditional_Chinese_architecture from '@/assets/img/jimeng/texiao/Spring_Festival_traditional_Chinese_architecture.png'
|
||||||
|
|
||||||
export const JimengParams = {
|
export const JimengParams = {
|
||||||
image: [
|
image: [
|
||||||
|
{
|
||||||
|
name: '图片 4.0 文/图生图',
|
||||||
|
version: '4.0',
|
||||||
|
label: '支持文本、单图和多图输入,实现基于主体一致性的多图融合创作、图像编辑等多样玩法',
|
||||||
|
key: 'doubao-seedream-4-0-250828',
|
||||||
|
params: [
|
||||||
|
{
|
||||||
|
name: 'prompt',
|
||||||
|
label: '提示词',
|
||||||
|
type: 'textarea',
|
||||||
|
required: true,
|
||||||
|
showWordLimit: true,
|
||||||
|
maxlength: 800,
|
||||||
|
autosize: { minRows: 3, maxRows: 5 },
|
||||||
|
placeholder: '请输入用于编辑图像的提示词,如:把xxx改成xxx,删除xxx,添加xxx等',
|
||||||
|
info: '建议不超过300个汉字或600个英文单词。字数过多信息容易分散,模型可能因此忽略细节。',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'image_urls',
|
||||||
|
label: '参考图片',
|
||||||
|
type: 'image',
|
||||||
|
required: false,
|
||||||
|
placeholder: '请上传图片',
|
||||||
|
maxSize: 5,
|
||||||
|
multiple: true,
|
||||||
|
maxCount: 10,
|
||||||
|
accept: '.png,.jpg,.jpeg',
|
||||||
|
info: '支持编辑单张图片,或者一次融合多张图片',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'size',
|
||||||
|
type: 'select',
|
||||||
|
required: true,
|
||||||
|
placeholder: '请选择尺寸',
|
||||||
|
label: '图片尺寸',
|
||||||
|
prefix: 'icon-resize',
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
label: '1:1 (1328 * 1328)',
|
||||||
|
value: '1328x1328',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '4:3 (1472 * 1104)',
|
||||||
|
value: '1472x1104',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '3:2 (1584 * 1056)',
|
||||||
|
value: '1584x1056',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '16:9 (1664 * 936)',
|
||||||
|
value: '1664x936',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '21:9 (2016 * 864)',
|
||||||
|
value: '2016x864',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: '图片 2.1 文生图',
|
name: '图片 2.1 文生图',
|
||||||
version: '2.1',
|
version: '2.1',
|
||||||
@@ -36,6 +126,7 @@ export const JimengParams = {
|
|||||||
required: true,
|
required: true,
|
||||||
placeholder: '请选择尺寸',
|
placeholder: '请选择尺寸',
|
||||||
label: '图片尺寸',
|
label: '图片尺寸',
|
||||||
|
prefix: 'icon-resize',
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: '21:9 (1195 * 512)',
|
label: '21:9 (1195 * 512)',
|
||||||
@@ -104,7 +195,7 @@ export const JimengParams = {
|
|||||||
required: true,
|
required: true,
|
||||||
placeholder: '请选择尺寸',
|
placeholder: '请选择尺寸',
|
||||||
label: '图片尺寸',
|
label: '图片尺寸',
|
||||||
|
prefix: 'icon-resize',
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: '1:1 (1328 * 1328)',
|
label: '1:1 (1328 * 1328)',
|
||||||
@@ -181,7 +272,7 @@ export const JimengParams = {
|
|||||||
required: true,
|
required: true,
|
||||||
placeholder: '请选择尺寸',
|
placeholder: '请选择尺寸',
|
||||||
label: '图片尺寸',
|
label: '图片尺寸',
|
||||||
|
prefix: 'icon-resize',
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: '1:1 (1328 * 1328)',
|
label: '1:1 (1328 * 1328)',
|
||||||
@@ -263,54 +354,56 @@ export const JimengParams = {
|
|||||||
accept: '.png,.jpg,.jpeg',
|
accept: '.png,.jpg,.jpeg',
|
||||||
info: '长边与短边比例在3以内,超出此比例或比例相对极端,会导致报错。',
|
info: '长边与短边比例在3以内,超出此比例或比例相对极端,会导致报错。',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: 'scale',
|
|
||||||
label: '文本描述影响的程度',
|
|
||||||
type: 'slider',
|
|
||||||
min: 0,
|
|
||||||
max: 1,
|
|
||||||
step: 0.1,
|
|
||||||
value: 0.5,
|
|
||||||
info: '该值越大代表文本描述影响程度越大,且输入图片影响程度越小',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: 'size',
|
name: 'size',
|
||||||
type: 'select',
|
type: 'select',
|
||||||
required: true,
|
required: true,
|
||||||
placeholder: '请选择尺寸',
|
placeholder: '请选择尺寸',
|
||||||
label: '图片尺寸',
|
label: '图片尺寸',
|
||||||
|
prefix: 'icon-resize',
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: '1:1 (1328 * 1328)',
|
label: '1:1 (2048 * 2048)',
|
||||||
value: '1328x1328',
|
value: '2048x2048',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '4:3 (1472 * 1104)',
|
label: '4:3 (2304 * 1728)',
|
||||||
value: '1472x1104',
|
value: '2304x1728',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '3:2 (1584 * 1056)',
|
label: '3:4 (1728 * 2304)',
|
||||||
value: '1584x1056',
|
value: '1728x2304',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '16:9 (1664 * 936)',
|
label: '16:9 (2560 * 1440)',
|
||||||
value: '1664x936',
|
value: '2560x1440',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '21:9 (2016 * 864)',
|
label: '9:16 (1440 * 2560)',
|
||||||
value: '2016x864',
|
value: '1440x2560',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '3:2 (2496 * 1664)',
|
||||||
|
value: '2496x1664',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '2:3 (1664 * 2496)',
|
||||||
|
value: '1664x2496',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '21:9 (3024 * 1296)',
|
||||||
|
value: '3024x1296',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
name: '图片 4.0 文/图生图',
|
name: '图片 3.0 图像特效',
|
||||||
version: '4.0',
|
version: '3.0',
|
||||||
label:
|
label: '将输入的单人写真图片,进行有创意的特效化处理。',
|
||||||
'支持文本、单图和多图输入,实现基于主体一致性的多图融合创作、图像编辑、组图生成等多样玩法',
|
key: 'i2i_multi_style_zx2x',
|
||||||
key: 'jimeng_i2i_v30',
|
|
||||||
params: [
|
params: [
|
||||||
{
|
{
|
||||||
name: 'prompt',
|
name: 'prompt',
|
||||||
@@ -331,17 +424,159 @@ export const JimengParams = {
|
|||||||
placeholder: '请上传图片',
|
placeholder: '请上传图片',
|
||||||
maxSize: 5,
|
maxSize: 5,
|
||||||
accept: '.png,.jpg,.jpeg',
|
accept: '.png,.jpg,.jpeg',
|
||||||
info: '长边与短边比例在3以内,超出此比例或比例相对极端,会导致报错。',
|
info: '支持输入人像写真图片。',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'scale',
|
name: 'template_id',
|
||||||
label: '文本描述影响的程度',
|
label: '特效模板ID',
|
||||||
type: 'slider',
|
type: 'select',
|
||||||
min: 0,
|
required: true,
|
||||||
max: 1,
|
placeholder: '请选择特效模板ID',
|
||||||
step: 0.1,
|
imgSize: '40px',
|
||||||
value: 0.5,
|
popperClass: 'model-select',
|
||||||
info: '该值越大代表文本描述影响程度越大,且输入图片影响程度越小',
|
prefix: 'icon-sd',
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
label: '毛毡3D拍立得风格',
|
||||||
|
value: 'felt_3d_polaroid',
|
||||||
|
image: felt_3d_polaroid,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '像素世界风',
|
||||||
|
value: 'my_world',
|
||||||
|
image: my_world,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '像素世界-万物通用版',
|
||||||
|
value: 'my_world_universal',
|
||||||
|
image: my_world_universal,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '盲盒玩偶风',
|
||||||
|
value: 'plastic_bubble_figure',
|
||||||
|
image: plastic_bubble_figure,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '塑料泡罩人偶-文字卡头版',
|
||||||
|
value: 'plastic_bubble_figure_cartoon_text',
|
||||||
|
image: plastic_bubble_figure_cartoon_text,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '毛绒玩偶风',
|
||||||
|
value: 'furry_dream_doll',
|
||||||
|
image: furry_dream_doll,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '迷你世界玩偶风',
|
||||||
|
value: 'micro_landscape_mini_world',
|
||||||
|
image: micro_landscape_mini_world,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '微型景观小世界-职业版',
|
||||||
|
value: 'micro_landscape_mini_world_professional',
|
||||||
|
image: micro_landscape_mini_world_professional,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '亚克力挂饰',
|
||||||
|
value: 'acrylic_ornaments',
|
||||||
|
image: acrylic_ornaments,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '毛毡钥匙扣',
|
||||||
|
value: 'felt_keychain',
|
||||||
|
image: felt_keychain,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Lofi 像素人物小卡',
|
||||||
|
value: 'lofi_pixel_character_mini_card',
|
||||||
|
image: lofi_pixel_character_mini_card,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '天使形象手办',
|
||||||
|
value: 'angel_figurine',
|
||||||
|
image: angel_figurine,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '躺在毛茸茸肚皮里',
|
||||||
|
value: 'lying_in_fluffy_belly',
|
||||||
|
image: lying_in_fluffy_belly,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '玻璃球',
|
||||||
|
value: 'glass_ball',
|
||||||
|
image: glass_ball,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '耳机盒',
|
||||||
|
value: 'earphone_case_style',
|
||||||
|
image: earphone_case_style,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '电子宠物蛋',
|
||||||
|
value: 'electronic_pet_egg_style',
|
||||||
|
image: electronic_pet_egg_style,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '拼贴缝布',
|
||||||
|
value: 'patchwork_collage_style',
|
||||||
|
image: patchwork_collage_style,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '抓娃娃机',
|
||||||
|
value: 'claw_machine_style',
|
||||||
|
image: claw_machine_style,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '车内微缩摆件',
|
||||||
|
value: 'car_miniature_ornaments',
|
||||||
|
image: car_miniature_ornaments,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '中秋节-新中式',
|
||||||
|
value: 'Mid-Autumn_Festival_new_chinese_style',
|
||||||
|
image: Mid_Autumn_Festival_new_chinese_style,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '中秋单人',
|
||||||
|
value: 'Mid-Autumn_Festival_individual',
|
||||||
|
image: Mid_Autumn_Festival_individual,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '圣诞节绿背景',
|
||||||
|
value: 'Christmas_green_background',
|
||||||
|
image: Christmas_green_background,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '圣诞节圣诞树',
|
||||||
|
value: 'Christmas_tree',
|
||||||
|
image: Christmas_tree,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '春节红墙',
|
||||||
|
value: 'Spring_Festival_traditional_Chinese_architecture',
|
||||||
|
image: Spring_Festival_traditional_Chinese_architecture,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '生日照华丽',
|
||||||
|
value: 'birthday_photo_gorgeous',
|
||||||
|
image: birthday_photo_gorgeous,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '生日照红色',
|
||||||
|
value: 'birthday_photo_red',
|
||||||
|
image: birthday_photo_red,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '生日照派对',
|
||||||
|
value: 'birthday_photo_party',
|
||||||
|
image: birthday_photo_party,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '毕业照',
|
||||||
|
value: 'graduation_photo',
|
||||||
|
image: graduation_photo,
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'size',
|
name: 'size',
|
||||||
@@ -349,26 +584,26 @@ export const JimengParams = {
|
|||||||
required: true,
|
required: true,
|
||||||
placeholder: '请选择尺寸',
|
placeholder: '请选择尺寸',
|
||||||
label: '图片尺寸',
|
label: '图片尺寸',
|
||||||
|
prefix: 'icon-resize',
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: '1:1 (1328 * 1328)',
|
label: '1:1 (1328 * 1328)',
|
||||||
value: '1328x1328',
|
value: '1328x1328',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '4:3 (1472 * 1104)',
|
label: '4:3 (1472 * 1104)',
|
||||||
value: '1472x1104',
|
value: '1472x1104',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '3:2 (1584 * 1056)',
|
label: '3:2 (1584 * 1056)',
|
||||||
value: '1584x1056',
|
value: '1584x1056',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '16:9 (1664 * 936)',
|
label: '16:9 (1664 * 936)',
|
||||||
value: '1664x936',
|
value: '1664x936',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '21:9 (2016 * 864)',
|
label: '21:9 (2016 * 864)',
|
||||||
value: '2016x864',
|
value: '2016x864',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -377,6 +612,7 @@ export const JimengParams = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
video: [
|
video: [
|
||||||
|
// 视频 3.0 720P-文生视频
|
||||||
{
|
{
|
||||||
name: '视频 3.0 720P-文生视频',
|
name: '视频 3.0 720P-文生视频',
|
||||||
version: '3.0',
|
version: '3.0',
|
||||||
@@ -398,8 +634,9 @@ export const JimengParams = {
|
|||||||
name: 'aspect_ratio',
|
name: 'aspect_ratio',
|
||||||
label: '视频比例',
|
label: '视频比例',
|
||||||
type: 'select',
|
type: 'select',
|
||||||
required: false,
|
required: true,
|
||||||
placeholder: '请选择视频比例',
|
placeholder: '请选择视频比例',
|
||||||
|
prefix: 'icon-resize',
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: '16:9 (横版)',
|
label: '16:9 (横版)',
|
||||||
@@ -431,6 +668,7 @@ export const JimengParams = {
|
|||||||
name: 'duration',
|
name: 'duration',
|
||||||
type: 'select',
|
type: 'select',
|
||||||
label: '视频时长',
|
label: '视频时长',
|
||||||
|
prefix: 'icon-clock',
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: '5秒',
|
label: '5秒',
|
||||||
@@ -444,7 +682,7 @@ export const JimengParams = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
// 视频 3.0 图生视频-首帧
|
||||||
{
|
{
|
||||||
name: '视频 3.0 720P-图生视频-首帧',
|
name: '视频 3.0 720P-图生视频-首帧',
|
||||||
version: '3.0',
|
version: '3.0',
|
||||||
@@ -466,7 +704,7 @@ export const JimengParams = {
|
|||||||
name: 'image_urls',
|
name: 'image_urls',
|
||||||
label: '首帧图片',
|
label: '首帧图片',
|
||||||
type: 'image',
|
type: 'image',
|
||||||
required: false,
|
required: true,
|
||||||
multiple: false,
|
multiple: false,
|
||||||
maxCount: 1,
|
maxCount: 1,
|
||||||
maxSize: 5,
|
maxSize: 5,
|
||||||
@@ -476,6 +714,7 @@ export const JimengParams = {
|
|||||||
name: 'duration',
|
name: 'duration',
|
||||||
type: 'select',
|
type: 'select',
|
||||||
label: '视频时长',
|
label: '视频时长',
|
||||||
|
prefix: 'icon-clock',
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: '5秒',
|
label: '5秒',
|
||||||
@@ -489,7 +728,7 @@ export const JimengParams = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
// 视频 3.0 图生视频-首尾帧
|
||||||
{
|
{
|
||||||
name: '视频 3.0 720P-图生视频-首尾帧',
|
name: '视频 3.0 720P-图生视频-首尾帧',
|
||||||
version: '3.0',
|
version: '3.0',
|
||||||
@@ -511,7 +750,7 @@ export const JimengParams = {
|
|||||||
name: 'image_urls',
|
name: 'image_urls',
|
||||||
label: '首尾帧图片',
|
label: '首尾帧图片',
|
||||||
type: 'image',
|
type: 'image',
|
||||||
required: false,
|
required: true,
|
||||||
multiple: true,
|
multiple: true,
|
||||||
maxCount: 2,
|
maxCount: 2,
|
||||||
maxSize: 5,
|
maxSize: 5,
|
||||||
@@ -522,6 +761,7 @@ export const JimengParams = {
|
|||||||
name: 'duration',
|
name: 'duration',
|
||||||
type: 'select',
|
type: 'select',
|
||||||
label: '视频时长',
|
label: '视频时长',
|
||||||
|
prefix: 'icon-clock',
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: '5秒',
|
label: '5秒',
|
||||||
@@ -535,7 +775,7 @@ export const JimengParams = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
// 视频 3.0 图生视频-运镜
|
||||||
{
|
{
|
||||||
name: '视频 3.0 720P-图生视频-运镜',
|
name: '视频 3.0 720P-图生视频-运镜',
|
||||||
version: '3.0',
|
version: '3.0',
|
||||||
@@ -557,7 +797,7 @@ export const JimengParams = {
|
|||||||
name: 'image_urls',
|
name: 'image_urls',
|
||||||
label: '运镜图片',
|
label: '运镜图片',
|
||||||
type: 'image',
|
type: 'image',
|
||||||
required: false,
|
required: true,
|
||||||
placeholder: '请上传图片',
|
placeholder: '请上传图片',
|
||||||
maxSize: 5,
|
maxSize: 5,
|
||||||
multiple: true,
|
multiple: true,
|
||||||
@@ -571,6 +811,8 @@ export const JimengParams = {
|
|||||||
required: true,
|
required: true,
|
||||||
placeholder: '请选择运镜控制',
|
placeholder: '请选择运镜控制',
|
||||||
popperClass: 'model-select',
|
popperClass: 'model-select',
|
||||||
|
prefix: 'icon-yunjing',
|
||||||
|
imgSize: '54px',
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: '希区柯克推进',
|
label: '希区柯克推进',
|
||||||
@@ -656,6 +898,7 @@ export const JimengParams = {
|
|||||||
name: 'duration',
|
name: 'duration',
|
||||||
type: 'select',
|
type: 'select',
|
||||||
label: '视频时长',
|
label: '视频时长',
|
||||||
|
prefix: 'icon-clock',
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: '5秒',
|
label: '5秒',
|
||||||
@@ -670,7 +913,7 @@ export const JimengParams = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
// 视频 3.0 1080P-文生视频
|
||||||
{
|
{
|
||||||
name: '视频 3.0 1080P-文生视频',
|
name: '视频 3.0 1080P-文生视频',
|
||||||
version: '3.0',
|
version: '3.0',
|
||||||
@@ -694,6 +937,7 @@ export const JimengParams = {
|
|||||||
type: 'select',
|
type: 'select',
|
||||||
required: false,
|
required: false,
|
||||||
placeholder: '请选择视频比例',
|
placeholder: '请选择视频比例',
|
||||||
|
prefix: 'icon-resize',
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: '16:9 (横版)',
|
label: '16:9 (横版)',
|
||||||
@@ -725,6 +969,7 @@ export const JimengParams = {
|
|||||||
name: 'duration',
|
name: 'duration',
|
||||||
type: 'select',
|
type: 'select',
|
||||||
label: '视频时长',
|
label: '视频时长',
|
||||||
|
prefix: 'icon-clock',
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: '5秒',
|
label: '5秒',
|
||||||
@@ -738,7 +983,7 @@ export const JimengParams = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
// 视频 3.0 1080P-图生视频-首帧
|
||||||
{
|
{
|
||||||
name: '视频 3.0 1080P-图生视频-首帧',
|
name: '视频 3.0 1080P-图生视频-首帧',
|
||||||
version: '3.0',
|
version: '3.0',
|
||||||
@@ -760,7 +1005,7 @@ export const JimengParams = {
|
|||||||
name: 'image_urls',
|
name: 'image_urls',
|
||||||
label: '首帧图片',
|
label: '首帧图片',
|
||||||
type: 'image',
|
type: 'image',
|
||||||
required: false,
|
required: true,
|
||||||
multiple: false,
|
multiple: false,
|
||||||
maxCount: 1,
|
maxCount: 1,
|
||||||
maxSize: 5,
|
maxSize: 5,
|
||||||
@@ -770,6 +1015,7 @@ export const JimengParams = {
|
|||||||
name: 'duration',
|
name: 'duration',
|
||||||
type: 'select',
|
type: 'select',
|
||||||
label: '视频时长',
|
label: '视频时长',
|
||||||
|
prefix: 'icon-clock',
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: '5秒',
|
label: '5秒',
|
||||||
@@ -783,7 +1029,7 @@ export const JimengParams = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
// 视频 3.0 1080P-图生视频-首尾帧
|
||||||
{
|
{
|
||||||
name: '视频 3.0 1080P-图生视频-首尾帧',
|
name: '视频 3.0 1080P-图生视频-首尾帧',
|
||||||
version: '3.0',
|
version: '3.0',
|
||||||
@@ -805,7 +1051,7 @@ export const JimengParams = {
|
|||||||
name: 'image_urls',
|
name: 'image_urls',
|
||||||
label: '首尾帧图片',
|
label: '首尾帧图片',
|
||||||
type: 'image',
|
type: 'image',
|
||||||
required: false,
|
required: true,
|
||||||
multiple: true,
|
multiple: true,
|
||||||
maxCount: 2,
|
maxCount: 2,
|
||||||
maxSize: 5,
|
maxSize: 5,
|
||||||
@@ -816,6 +1062,7 @@ export const JimengParams = {
|
|||||||
name: 'duration',
|
name: 'duration',
|
||||||
type: 'select',
|
type: 'select',
|
||||||
label: '视频时长',
|
label: '视频时长',
|
||||||
|
prefix: 'icon-clock',
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: '5秒',
|
label: '5秒',
|
||||||
@@ -829,7 +1076,7 @@ export const JimengParams = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
// 视频 3.0Pro 1080P-图生视频
|
||||||
{
|
{
|
||||||
name: '视频 3.0Pro 1080P-图生视频',
|
name: '视频 3.0Pro 1080P-图生视频',
|
||||||
version: '3.0',
|
version: '3.0',
|
||||||
@@ -866,6 +1113,7 @@ export const JimengParams = {
|
|||||||
required: false,
|
required: false,
|
||||||
placeholder: '请选择视频比例',
|
placeholder: '请选择视频比例',
|
||||||
info: '只在文生视频场景下生效,图生视频场景会根据输入图的长宽比自动适配',
|
info: '只在文生视频场景下生效,图生视频场景会根据输入图的长宽比自动适配',
|
||||||
|
prefix: 'icon-resize',
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: '21:9 (2176 * 928)',
|
label: '21:9 (2176 * 928)',
|
||||||
@@ -897,6 +1145,8 @@ export const JimengParams = {
|
|||||||
name: 'duration',
|
name: 'duration',
|
||||||
type: 'select',
|
type: 'select',
|
||||||
label: '视频时长',
|
label: '视频时长',
|
||||||
|
prefix: 'icon-clock',
|
||||||
|
placeholder: '请选择视频时长',
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
label: '5秒',
|
label: '5秒',
|
||||||
@@ -919,7 +1169,7 @@ export const JimengParams = {
|
|||||||
export const JimengFunctions = [
|
export const JimengFunctions = [
|
||||||
{
|
{
|
||||||
key: 'image',
|
key: 'image',
|
||||||
icon: 'iconfont icon-image',
|
icon: 'icon-image',
|
||||||
name: '图片生成',
|
name: '图片生成',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -6,24 +6,16 @@
|
|||||||
// * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
import { checkSession } from '@/store/cache'
|
import { checkSession } from '@/store/cache'
|
||||||
import { JimengParams } from '@/store/data'
|
import { JimengFunctions, JimengParams } from '@/store/data/jimeng_data'
|
||||||
import { useSharedStore } from '@/store/sharedata'
|
import { useSharedStore } from '@/store/sharedata'
|
||||||
import { showMessageError, showMessageOK } from '@/utils/dialog'
|
import { showMessageError, showMessageOK } from '@/utils/dialog'
|
||||||
import { httpDownload, httpGet, httpPost } from '@/utils/http'
|
import { httpDownload, httpGet, httpPost } from '@/utils/http'
|
||||||
import { replaceImg, substr } from '@/utils/libs'
|
import { replaceImg, substr } from '@/utils/libs'
|
||||||
import { ElMessageBox } from 'element-plus'
|
import { ElMessageBox } from 'element-plus'
|
||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
import { computed, reactive, ref } from 'vue'
|
import { reactive, ref } from 'vue'
|
||||||
|
|
||||||
export const useJimengStore = defineStore('jimeng', () => {
|
export const useJimengStore = defineStore('jimeng', () => {
|
||||||
// 当前激活的功能分类和具体功能
|
|
||||||
const activeCategory = ref('image_generation')
|
|
||||||
const activeFunction = ref('text_to_image')
|
|
||||||
const useImageInput = ref(false)
|
|
||||||
|
|
||||||
// 新增:全局提示词
|
|
||||||
const currentPrompt = ref('')
|
|
||||||
|
|
||||||
// 共同状态
|
// 共同状态
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const submitting = ref(false)
|
const submitting = ref(false)
|
||||||
@@ -45,73 +37,8 @@ export const useJimengStore = defineStore('jimeng', () => {
|
|||||||
// 登录弹窗
|
// 登录弹窗
|
||||||
const shareStore = useSharedStore()
|
const shareStore = useSharedStore()
|
||||||
|
|
||||||
const paramsMap = JimengParams
|
|
||||||
|
|
||||||
// 功能分类配置
|
|
||||||
const categories = [
|
|
||||||
{ key: 'image_generation', name: '图片生成' },
|
|
||||||
{ key: 'image_editing', name: 'AI修图' },
|
|
||||||
{ key: 'image_effects', name: '图像特效' },
|
|
||||||
{ key: 'video_generation', name: '视频生成' },
|
|
||||||
]
|
|
||||||
|
|
||||||
// 新增:动态获取算力消耗配置
|
// 新增:动态获取算力消耗配置
|
||||||
const powerConfig = reactive({})
|
const powerConfig = reactive({})
|
||||||
|
|
||||||
// 功能配置
|
|
||||||
const functions = reactive([
|
|
||||||
{
|
|
||||||
key: 'text_to_image',
|
|
||||||
name: '文生图',
|
|
||||||
category: 'image_generation',
|
|
||||||
needsPrompt: true,
|
|
||||||
needsImage: false,
|
|
||||||
power: 20,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'image_to_image',
|
|
||||||
name: '图生图',
|
|
||||||
category: 'image_generation',
|
|
||||||
needsPrompt: true,
|
|
||||||
needsImage: true,
|
|
||||||
power: 30,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'image_edit',
|
|
||||||
name: '图像编辑',
|
|
||||||
category: 'image_editing',
|
|
||||||
needsPrompt: true,
|
|
||||||
needsImage: true,
|
|
||||||
multiple: true,
|
|
||||||
power: 25,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'image_effects',
|
|
||||||
name: '图像特效',
|
|
||||||
category: 'image_effects',
|
|
||||||
needsPrompt: false,
|
|
||||||
needsImage: true,
|
|
||||||
power: 15,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'text_to_video',
|
|
||||||
name: '文生视频',
|
|
||||||
category: 'video_generation',
|
|
||||||
needsPrompt: true,
|
|
||||||
needsImage: false,
|
|
||||||
power: 100,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: 'image_to_video',
|
|
||||||
name: '图生视频',
|
|
||||||
category: 'video_generation',
|
|
||||||
needsPrompt: true,
|
|
||||||
needsImage: true,
|
|
||||||
multiple: true,
|
|
||||||
power: 120,
|
|
||||||
},
|
|
||||||
])
|
|
||||||
|
|
||||||
// 动态设置算力消耗
|
// 动态设置算力消耗
|
||||||
const setFunctionPowers = (config) => {
|
const setFunctionPowers = (config) => {
|
||||||
functions.forEach((f) => {
|
functions.forEach((f) => {
|
||||||
@@ -121,114 +48,32 @@ export const useJimengStore = defineStore('jimeng', () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 各功能的参数
|
// 功能配置
|
||||||
const textToImageParams = reactive({
|
const functions = JimengFunctions
|
||||||
size: '1328x1328',
|
// 当前激活的功能
|
||||||
scale: 2.5,
|
const activeFunction = ref('image')
|
||||||
seed: -1,
|
// 参数配置
|
||||||
use_pre_llm: true,
|
const functionParams = JimengParams
|
||||||
|
// 表单数据
|
||||||
|
const formData = ref({})
|
||||||
|
// 必填参数
|
||||||
|
const requiredKeys = ref({})
|
||||||
|
// 进度
|
||||||
|
const progress = ref({
|
||||||
|
image: 100,
|
||||||
|
video: 100,
|
||||||
|
virtualHuman: 38,
|
||||||
|
actionTransfer: 65,
|
||||||
})
|
})
|
||||||
|
|
||||||
const imageToImageParams = reactive({
|
|
||||||
image_input: '',
|
|
||||||
size: '1328x1328',
|
|
||||||
gpen: 0.4,
|
|
||||||
skin: 0.3,
|
|
||||||
skin_unifi: 0,
|
|
||||||
gen_mode: 'creative',
|
|
||||||
seed: -1,
|
|
||||||
})
|
|
||||||
|
|
||||||
const imageEditParams = reactive({
|
|
||||||
image_input: '',
|
|
||||||
scale: 0.5,
|
|
||||||
seed: -1,
|
|
||||||
})
|
|
||||||
|
|
||||||
const imageEffectsParams = reactive({
|
|
||||||
image_input: '',
|
|
||||||
template_id: '',
|
|
||||||
size: '1328x1328',
|
|
||||||
})
|
|
||||||
|
|
||||||
const textToVideoParams = reactive({
|
|
||||||
aspect_ratio: '16:9',
|
|
||||||
seed: -1,
|
|
||||||
})
|
|
||||||
|
|
||||||
const imageToVideoParams = reactive({
|
|
||||||
image_input: [],
|
|
||||||
aspect_ratio: '16:9',
|
|
||||||
seed: -1,
|
|
||||||
})
|
|
||||||
|
|
||||||
// 计算属性
|
|
||||||
const currentFunction = computed(() => {
|
|
||||||
return functions.find((f) => f.key === activeFunction.value) || functions[0]
|
|
||||||
})
|
|
||||||
|
|
||||||
const currentFunctions = computed(() => {
|
|
||||||
return functions.filter((f) => f.category === activeCategory.value)
|
|
||||||
})
|
|
||||||
|
|
||||||
const needsPrompt = computed(() => currentFunction.value.needsPrompt)
|
|
||||||
const needsImage = computed(() => currentFunction.value.needsImage)
|
|
||||||
const needsMultipleImages = computed(() => currentFunction.value.multiple)
|
|
||||||
const currentPowerCost = computed(() => currentFunction.value.power)
|
|
||||||
|
|
||||||
// 初始化方法
|
|
||||||
const init = async () => {
|
|
||||||
try {
|
|
||||||
// 获取算力消耗配置
|
|
||||||
const powerRes = await httpGet('/api/jimeng/power-config')
|
|
||||||
if (powerRes.data) {
|
|
||||||
Object.assign(powerConfig, powerRes.data)
|
|
||||||
setFunctionPowers(powerRes.data)
|
|
||||||
}
|
|
||||||
const user = await checkSession()
|
|
||||||
isLogin.value = true
|
|
||||||
userPower.value = user.power
|
|
||||||
// 获取任务列表
|
|
||||||
await fetchData(1)
|
|
||||||
// 开始轮询
|
|
||||||
startPolling()
|
|
||||||
} catch (error) {
|
|
||||||
console.error('初始化失败:', error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 切换功能分类
|
|
||||||
const switchCategory = (category) => {
|
|
||||||
activeCategory.value = category
|
|
||||||
const categoryFunctions = functions.filter((f) => f.category === category)
|
|
||||||
if (categoryFunctions.length > 0) {
|
|
||||||
if (category === 'image_generation') {
|
|
||||||
activeFunction.value = useImageInput.value ? 'image_to_image' : 'text_to_image'
|
|
||||||
} else if (category === 'video_generation') {
|
|
||||||
activeFunction.value = useImageInput.value ? 'image_to_video' : 'text_to_video'
|
|
||||||
} else {
|
|
||||||
activeFunction.value = categoryFunctions[0].key
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 切换输入模式
|
|
||||||
const switchInputMode = () => {
|
|
||||||
if (activeCategory.value === 'image_generation') {
|
|
||||||
activeFunction.value = useImageInput.value ? 'image_to_image' : 'text_to_image'
|
|
||||||
} else if (activeCategory.value === 'video_generation') {
|
|
||||||
activeFunction.value = useImageInput.value ? 'image_to_video' : 'text_to_video'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 切换功能
|
// 切换功能
|
||||||
const switchFunction = (functionKey) => {
|
const switchFunction = (f) => {
|
||||||
activeFunction.value = functionKey
|
activeFunction.value = f.key
|
||||||
|
formData.value = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取当前算力消耗
|
// 获取当前算力消耗
|
||||||
const getCurrentPowerCost = () => {
|
const getCurrentPowerCost = () => {
|
||||||
return currentFunction.value.power
|
return activeFunction.value.power
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取功能名称
|
// 获取功能名称
|
||||||
@@ -353,71 +198,21 @@ export const useJimengStore = defineStore('jimeng', () => {
|
|||||||
shareStore.setShowLoginDialog(true)
|
shareStore.setShowLoginDialog(true)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (userPower.value < currentPowerCost.value) {
|
// if (userPower.value < currentPowerCost.value) {
|
||||||
showMessageError('算力不足')
|
// showMessageError('算力不足')
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
// 新增:除图像特效外,其他任务类型必须有提示词
|
for (const key in requiredKeys.value) {
|
||||||
if (activeFunction.value !== 'image_effects' && !currentPrompt.value) {
|
if (!formData.value[key].required) {
|
||||||
showMessageError('提示词不能为空')
|
showMessageError('缺少参数:' + requiredKeys.value[key].label)
|
||||||
return
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
submitting.value = true
|
submitting.value = true
|
||||||
let requestData = { task_type: activeFunction.value, prompt: currentPrompt.value }
|
|
||||||
switch (activeFunction.value) {
|
const response = await httpPost('/api/jimeng/task', formData.value)
|
||||||
case 'text_to_image':
|
|
||||||
Object.assign(requestData, {
|
|
||||||
width: parseInt(textToImageParams.size.split('x')[0]),
|
|
||||||
height: parseInt(textToImageParams.size.split('x')[1]),
|
|
||||||
scale: textToImageParams.scale,
|
|
||||||
seed: textToImageParams.seed,
|
|
||||||
use_pre_llm: textToImageParams.use_pre_llm,
|
|
||||||
})
|
|
||||||
break
|
|
||||||
case 'image_to_image':
|
|
||||||
Object.assign(requestData, {
|
|
||||||
image_input: imageToImageParams.image_input[0],
|
|
||||||
width: parseInt(imageToImageParams.size.split('x')[0]),
|
|
||||||
height: parseInt(imageToImageParams.size.split('x')[1]),
|
|
||||||
gpen: imageToImageParams.gpen,
|
|
||||||
skin: imageToImageParams.skin,
|
|
||||||
skin_unifi: imageToImageParams.skin_unifi,
|
|
||||||
gen_mode: imageToImageParams.gen_mode,
|
|
||||||
seed: imageToImageParams.seed,
|
|
||||||
})
|
|
||||||
break
|
|
||||||
case 'image_edit':
|
|
||||||
Object.assign(requestData, {
|
|
||||||
image_input: imageEditParams.image_input[0],
|
|
||||||
scale: imageEditParams.scale,
|
|
||||||
seed: imageEditParams.seed,
|
|
||||||
})
|
|
||||||
break
|
|
||||||
case 'image_effects':
|
|
||||||
Object.assign(requestData, {
|
|
||||||
image_input: imageEffectsParams.image_input[0],
|
|
||||||
template_id: imageEffectsParams.template_id,
|
|
||||||
width: parseInt(imageEffectsParams.size.split('x')[0]),
|
|
||||||
height: parseInt(imageEffectsParams.size.split('x')[1]),
|
|
||||||
prompt: imageEffectsParams.prompt,
|
|
||||||
})
|
|
||||||
break
|
|
||||||
case 'text_to_video':
|
|
||||||
Object.assign(requestData, {
|
|
||||||
aspect_ratio: textToVideoParams.aspect_ratio,
|
|
||||||
seed: textToVideoParams.seed,
|
|
||||||
})
|
|
||||||
break
|
|
||||||
case 'image_to_video':
|
|
||||||
Object.assign(requestData, {
|
|
||||||
image_urls: imageToVideoParams.image_input,
|
|
||||||
aspect_ratio: imageToVideoParams.aspect_ratio,
|
|
||||||
seed: imageToVideoParams.seed,
|
|
||||||
})
|
|
||||||
break
|
|
||||||
}
|
|
||||||
const response = await httpPost('/api/jimeng/task', requestData)
|
|
||||||
if (response.data) {
|
if (response.data) {
|
||||||
showMessageOK('任务提交成功')
|
showMessageOK('任务提交成功')
|
||||||
isOver.value = false
|
isOver.value = false
|
||||||
@@ -501,6 +296,27 @@ export const useJimengStore = defineStore('jimeng', () => {
|
|||||||
showDialog.value = true
|
showDialog.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 初始化方法
|
||||||
|
const init = async () => {
|
||||||
|
try {
|
||||||
|
// 获取算力消耗配置
|
||||||
|
const powerRes = await httpGet('/api/jimeng/power-config')
|
||||||
|
if (powerRes.data) {
|
||||||
|
Object.assign(powerConfig, powerRes.data)
|
||||||
|
setFunctionPowers(powerRes.data)
|
||||||
|
}
|
||||||
|
const user = await checkSession()
|
||||||
|
isLogin.value = true
|
||||||
|
userPower.value = user.power
|
||||||
|
// 获取任务列表
|
||||||
|
await fetchData(1)
|
||||||
|
// 开始轮询
|
||||||
|
startPolling()
|
||||||
|
} catch (error) {
|
||||||
|
console.error('初始化失败:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 页面卸载时清理轮询
|
// 页面卸载时清理轮询
|
||||||
const cleanup = () => {
|
const cleanup = () => {
|
||||||
stopPolling()
|
stopPolling()
|
||||||
@@ -509,9 +325,7 @@ export const useJimengStore = defineStore('jimeng', () => {
|
|||||||
// 返回所有状态和方法
|
// 返回所有状态和方法
|
||||||
return {
|
return {
|
||||||
// 状态
|
// 状态
|
||||||
activeCategory,
|
|
||||||
activeFunction,
|
activeFunction,
|
||||||
useImageInput,
|
|
||||||
loading,
|
loading,
|
||||||
submitting,
|
submitting,
|
||||||
page,
|
page,
|
||||||
@@ -526,31 +340,16 @@ export const useJimengStore = defineStore('jimeng', () => {
|
|||||||
currentVideoUrl,
|
currentVideoUrl,
|
||||||
|
|
||||||
// 配置
|
// 配置
|
||||||
categories,
|
|
||||||
functions,
|
functions,
|
||||||
currentFunctions,
|
activeFunction,
|
||||||
|
functionParams,
|
||||||
// 参数
|
formData,
|
||||||
currentPrompt,
|
requiredKeys,
|
||||||
textToImageParams,
|
progress,
|
||||||
imageToImageParams,
|
|
||||||
imageEditParams,
|
|
||||||
imageEffectsParams,
|
|
||||||
textToVideoParams,
|
|
||||||
imageToVideoParams,
|
|
||||||
|
|
||||||
// 计算属性
|
|
||||||
currentFunction,
|
|
||||||
needsPrompt,
|
|
||||||
needsImage,
|
|
||||||
needsMultipleImages,
|
|
||||||
currentPowerCost,
|
|
||||||
|
|
||||||
// 方法
|
// 方法
|
||||||
init,
|
init,
|
||||||
switchCategory,
|
|
||||||
switchFunction,
|
switchFunction,
|
||||||
switchInputMode,
|
|
||||||
getCurrentPowerCost,
|
getCurrentPowerCost,
|
||||||
getFunctionName,
|
getFunctionName,
|
||||||
getTaskStatusText,
|
getTaskStatusText,
|
||||||
@@ -569,85 +368,3 @@ export const useJimengStore = defineStore('jimeng', () => {
|
|||||||
replaceImg,
|
replaceImg,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
export const imageSizeOptions = [
|
|
||||||
{ label: '1:1 (1328x1328)', value: '1328x1328' },
|
|
||||||
{ label: '3:2 (1584x1056)', value: '1584x1056' },
|
|
||||||
{ label: '2:3 (1056x1584)', value: '1056x1584' },
|
|
||||||
{ label: '4:3 (1472x1104)', value: '1472x1104' },
|
|
||||||
{ label: '3:4 (1104x1472)', value: '1104x1472' },
|
|
||||||
{ label: '16:9 (1664x936)', value: '1664x936' },
|
|
||||||
{ label: '9:16 (936x1664)', value: '936x1664' },
|
|
||||||
{ label: '21:9 (2016x864)', value: '2016x864' },
|
|
||||||
{ label: '9:21 (864x2016)', value: '864x2016' },
|
|
||||||
]
|
|
||||||
|
|
||||||
export const videoAspectRatioOptions = [
|
|
||||||
{ label: '1:1 (正方形)', value: '1:1' },
|
|
||||||
{ label: '16:9 (横版)', value: '16:9' },
|
|
||||||
{ label: '9:16 (竖版)', value: '9:16' },
|
|
||||||
]
|
|
||||||
|
|
||||||
export const imageEffectsTemplateOptions = [
|
|
||||||
{
|
|
||||||
label: '毛毡3D拍立得风格',
|
|
||||||
value: 'felt_3d_polaroid',
|
|
||||||
preview: '/images/jimeng/templates/felt_3d_polaroid.png',
|
|
||||||
},
|
|
||||||
{ label: '像素世界风', value: 'my_world', preview: '/images/jimeng/templates/my_world.png' },
|
|
||||||
{
|
|
||||||
label: '像素世界-万物通用版',
|
|
||||||
value: 'my_world_universal',
|
|
||||||
preview: '/images/jimeng/templates/my_world_universal.png',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '盲盒玩偶风',
|
|
||||||
value: 'plastic_bubble_figure',
|
|
||||||
preview: '/images/jimeng/templates/plastic_bubble_figure.png',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '塑料泡罩人偶-文字卡头版',
|
|
||||||
value: 'plastic_bubble_figure_cartoon_text',
|
|
||||||
preview: '/images/jimeng/templates/plastic_bubble_figure_cartoon_text.png',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '毛绒玩偶风',
|
|
||||||
value: 'furry_dream_doll',
|
|
||||||
preview: '/images/jimeng/templates/furry_dream_doll.png',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '迷你世界玩偶风',
|
|
||||||
value: 'micro_landscape_mini_world',
|
|
||||||
preview: '/images/jimeng/templates/micro_landscape_mini_world.png',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '微型景观小世界-职业版',
|
|
||||||
value: 'micro_landscape_mini_world_professional',
|
|
||||||
preview: '/images/jimeng/templates/micro_landscape_mini_world_professional.png',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '亚克力挂饰',
|
|
||||||
value: 'acrylic_ornaments',
|
|
||||||
preview: '/images/jimeng/templates/acrylic_ornaments.png',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '毛毡钥匙扣',
|
|
||||||
value: 'felt_keychain',
|
|
||||||
preview: '/images/jimeng/templates/felt_keychain.png',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Lofi 像素人物小卡',
|
|
||||||
value: 'lofi_pixel_character_mini_card',
|
|
||||||
preview: '/images/jimeng/templates/lofi_pixel_character_mini_card.png',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '天使形象手办',
|
|
||||||
value: 'angel_figurine',
|
|
||||||
preview: '/images/jimeng/templates/angel_figurine.png',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '躺在毛茸茸肚皮里',
|
|
||||||
value: 'lying_in_fluffy_belly',
|
|
||||||
preview: '/images/jimeng/templates/lying_in_fluffy_belly.png',
|
|
||||||
},
|
|
||||||
{ label: '玻璃球', value: 'glass_ball', preview: '/images/jimeng/templates/glass_ball.png' },
|
|
||||||
]
|
|
||||||
|
|||||||
@@ -5,17 +5,16 @@
|
|||||||
<!-- 功能分类按钮组 -->
|
<!-- 功能分类按钮组 -->
|
||||||
<div class="category-buttons">
|
<div class="category-buttons">
|
||||||
<div class="category-grid">
|
<div class="category-grid">
|
||||||
<div
|
<button
|
||||||
v-for="category in store.categories"
|
v-for="f in store.functions"
|
||||||
:key="category.key"
|
:key="f.key"
|
||||||
:class="['category-btn', { active: store.activeCategory === category.key }]"
|
class="category-btn text-base"
|
||||||
@click="store.switchCategory(category.key)"
|
:class="{ active: store.activeFunction === f.key }"
|
||||||
|
@click="store.switchFunction(f)"
|
||||||
>
|
>
|
||||||
<div class="category-icon">
|
<i class="iconfont mr-2 !text-xl" :class="f.icon"></i>
|
||||||
<i :class="getCategoryIcon(category.key)"></i>
|
{{ f.name }}
|
||||||
</div>
|
</button>
|
||||||
<div class="category-name">{{ category.name }}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -139,290 +138,17 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 功能开关 -->
|
<!-- 功能开关 -->
|
||||||
<div
|
<div class="function-params">
|
||||||
class="function-switch"
|
<div class="mb-3">
|
||||||
v-if="
|
<div class="mb-2">
|
||||||
store.activeCategory === 'image_generation' || store.activeCategory === 'video_generation'
|
<label class="label text-left font-bold">模型选择</label>
|
||||||
"
|
|
||||||
>
|
|
||||||
<div class="switch-label">
|
|
||||||
<el-icon><Switch /></el-icon>
|
|
||||||
生成模式
|
|
||||||
</div>
|
|
||||||
<div class="switch-container">
|
|
||||||
<div class="switch-info">
|
|
||||||
<div class="switch-title">
|
|
||||||
{{ store.activeCategory === 'image_generation' ? '图生图人像写真' : '图生视频' }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<el-switch v-model="store.useImageInput" @change="store.switchInputMode" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 参数容器 -->
|
|
||||||
<div class="params-container">
|
|
||||||
<!-- 文生图 -->
|
|
||||||
<div v-if="store.activeFunction === 'text_to_image'" class="function-panel">
|
|
||||||
<div class="param-line pt">
|
|
||||||
<span class="label">提示词:</span>
|
|
||||||
</div>
|
|
||||||
<div class="param-line">
|
|
||||||
<el-input
|
|
||||||
v-model="store.currentPrompt"
|
|
||||||
type="textarea"
|
|
||||||
:autosize="{ minRows: 3, maxRows: 5 }"
|
|
||||||
placeholder="请输入图片描述,越详细越好"
|
|
||||||
maxlength="2000"
|
|
||||||
show-word-limit
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="param-line pt">
|
|
||||||
<span class="label">图片尺寸:</span>
|
|
||||||
</div>
|
|
||||||
<div class="param-line">
|
|
||||||
<el-select v-model="store.textToImageParams.size" placeholder="选择尺寸">
|
|
||||||
<el-option
|
|
||||||
v-for="opt in imageSizeOptions"
|
|
||||||
:key="opt.value"
|
|
||||||
:label="opt.label"
|
|
||||||
:value="opt.value"
|
|
||||||
/>
|
|
||||||
</el-select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="param-line">
|
|
||||||
<span class="label"
|
|
||||||
>创意度
|
|
||||||
<el-tooltip content="创意度越高,影响文本描述的程度越高" placement="top">
|
|
||||||
<i class="iconfont icon-info cursor-pointer ml-1"></i> </el-tooltip
|
|
||||||
></span>
|
|
||||||
</div>
|
|
||||||
<div class="item-group">
|
|
||||||
<el-slider v-model="store.textToImageParams.scale" :min="1" :max="10" :step="0.5" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="item-group flex justify-between">
|
|
||||||
<span class="label">智能优化提示词</span>
|
|
||||||
<el-switch v-model="store.textToImageParams.use_pre_llm" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 图生图 -->
|
|
||||||
<div v-if="store.activeFunction === 'image_to_image'" class="function-panel">
|
|
||||||
<div class="param-line pt">
|
|
||||||
<span class="label">上传图片:</span>
|
|
||||||
</div>
|
|
||||||
<div class="param-line">
|
|
||||||
<ImageUpload
|
|
||||||
v-model="store.imageToImageParams.image_input"
|
|
||||||
:max-count="1"
|
|
||||||
:multiple="false"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="param-line pt">
|
|
||||||
<span class="label">提示词:</span>
|
|
||||||
</div>
|
|
||||||
<div class="param-line">
|
|
||||||
<el-input
|
|
||||||
v-model="store.currentPrompt"
|
|
||||||
type="textarea"
|
|
||||||
:autosize="{ minRows: 3, maxRows: 5 }"
|
|
||||||
placeholder="描述你想要的图片效果"
|
|
||||||
maxlength="2000"
|
|
||||||
show-word-limit
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="param-line pt">
|
|
||||||
<span class="label">图片尺寸:</span>
|
|
||||||
</div>
|
|
||||||
<div class="param-line">
|
|
||||||
<el-select v-model="store.imageToImageParams.size" placeholder="选择尺寸">
|
|
||||||
<el-option
|
|
||||||
v-for="opt in imageSizeOptions"
|
|
||||||
:key="opt.value"
|
|
||||||
:label="opt.label"
|
|
||||||
:value="opt.value"
|
|
||||||
/>
|
|
||||||
</el-select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 图像编辑 -->
|
|
||||||
<div v-if="store.activeFunction === 'image_edit'" class="function-panel">
|
|
||||||
<div class="param-line pt">
|
|
||||||
<span class="label">上传图片:</span>
|
|
||||||
</div>
|
|
||||||
<div class="param-line">
|
|
||||||
<ImageUpload
|
|
||||||
v-model="store.imageEditParams.image_input"
|
|
||||||
:max-count="1"
|
|
||||||
:multiple="false"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="param-line pt">
|
|
||||||
<span class="label">编辑提示词:</span>
|
|
||||||
</div>
|
|
||||||
<div class="param-line">
|
|
||||||
<el-input
|
|
||||||
v-model="store.currentPrompt"
|
|
||||||
type="textarea"
|
|
||||||
:autosize="{ minRows: 3, maxRows: 5 }"
|
|
||||||
placeholder="描述你想要的编辑效果"
|
|
||||||
maxlength="2000"
|
|
||||||
show-word-limit
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="item-group">
|
|
||||||
<span class="label">编辑强度:</span>
|
|
||||||
<el-slider v-model="store.imageEditParams.scale" :min="0" :max="1" :step="0.1" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 图像特效 -->
|
|
||||||
<div v-if="store.activeFunction === 'image_effects'" class="function-panel">
|
|
||||||
<div class="param-line pt">
|
|
||||||
<span class="label">上传图片:</span>
|
|
||||||
</div>
|
|
||||||
<div class="param-line">
|
|
||||||
<ImageUpload
|
|
||||||
v-model="store.imageEffectsParams.image_input"
|
|
||||||
:max-count="1"
|
|
||||||
:multiple="false"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="param-line pt">
|
|
||||||
<span class="label">特效模板:</span>
|
|
||||||
</div>
|
|
||||||
<div class="param-line">
|
|
||||||
<el-select
|
|
||||||
v-model="store.imageEffectsParams.template_id"
|
|
||||||
placeholder="选择特效模板"
|
|
||||||
popper-class="jimeng-template-select"
|
|
||||||
@change="handleTemplateChange($event)"
|
|
||||||
>
|
|
||||||
<template #prefix>
|
|
||||||
<div class="flex items-center py-1">
|
|
||||||
<el-image
|
|
||||||
v-if="templatePreview"
|
|
||||||
:src="templatePreview"
|
|
||||||
class="w-[50px] h-[50px] object-cover rounded-md"
|
|
||||||
:preview-src-list="[templatePreview]"
|
|
||||||
:preview-teleported="true"
|
|
||||||
@click.stop
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<el-option
|
|
||||||
v-for="opt in imageEffectsTemplateOptions"
|
|
||||||
:key="opt.value"
|
|
||||||
:label="opt.label"
|
|
||||||
:value="opt.value"
|
|
||||||
>
|
|
||||||
<div class="flex flex-row justify-between">
|
|
||||||
<span class="template-label">{{ opt.label }}</span>
|
|
||||||
<img
|
|
||||||
v-if="opt.preview"
|
|
||||||
:src="opt.preview"
|
|
||||||
:alt="opt.label"
|
|
||||||
class="w-[50px] h-[50px] object-cover rounded-md"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</el-option>
|
|
||||||
</el-select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="param-line pt">
|
|
||||||
<span class="label">输出尺寸:</span>
|
|
||||||
</div>
|
|
||||||
<div class="param-line">
|
|
||||||
<el-select v-model="store.imageEffectsParams.size" placeholder="选择尺寸">
|
|
||||||
<el-option
|
|
||||||
v-for="opt in imageSizeOptions"
|
|
||||||
:key="opt.value"
|
|
||||||
:label="opt.label"
|
|
||||||
:value="opt.value"
|
|
||||||
/>
|
|
||||||
</el-select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 文生视频 -->
|
|
||||||
<div v-if="store.activeFunction === 'text_to_video'" class="function-panel">
|
|
||||||
<div class="param-line pt">
|
|
||||||
<span class="label">提示词:</span>
|
|
||||||
</div>
|
|
||||||
<div class="param-line">
|
|
||||||
<el-input
|
|
||||||
v-model="store.currentPrompt"
|
|
||||||
type="textarea"
|
|
||||||
:autosize="{ minRows: 3, maxRows: 5 }"
|
|
||||||
placeholder="描述你想要的视频内容"
|
|
||||||
maxlength="2000"
|
|
||||||
show-word-limit
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="param-line pt">
|
|
||||||
<span class="label">视频比例:</span>
|
|
||||||
</div>
|
|
||||||
<div class="param-line">
|
|
||||||
<el-select v-model="store.textToVideoParams.aspect_ratio" placeholder="选择比例">
|
|
||||||
<el-option
|
|
||||||
v-for="opt in videoAspectRatioOptions"
|
|
||||||
:key="opt.value"
|
|
||||||
:label="opt.label"
|
|
||||||
:value="opt.value"
|
|
||||||
/>
|
|
||||||
</el-select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 图生视频 -->
|
|
||||||
<div v-if="store.activeFunction === 'image_to_video'" class="function-panel">
|
|
||||||
<div class="param-line pt">
|
|
||||||
<span class="label">上传图片:</span>
|
|
||||||
</div>
|
|
||||||
<div class="param-line">
|
|
||||||
<ImageUpload
|
|
||||||
v-model="store.imageToVideoParams.image_input"
|
|
||||||
:max-count="2"
|
|
||||||
:multiple="true"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="param-line pt">
|
|
||||||
<span class="label">提示词:</span>
|
|
||||||
</div>
|
|
||||||
<div class="param-line">
|
|
||||||
<el-input
|
|
||||||
v-model="store.currentPrompt"
|
|
||||||
type="textarea"
|
|
||||||
:autosize="{ minRows: 3, maxRows: 5 }"
|
|
||||||
placeholder="描述你想要的视频效果"
|
|
||||||
maxlength="2000"
|
|
||||||
show-word-limit
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="param-line pt">
|
|
||||||
<span class="label">视频比例:</span>
|
|
||||||
</div>
|
|
||||||
<div class="param-line">
|
|
||||||
<el-select v-model="store.imageToVideoParams.aspect_ratio" placeholder="选择比例">
|
|
||||||
<el-option
|
|
||||||
v-for="opt in videoAspectRatioOptions"
|
|
||||||
:key="opt.value"
|
|
||||||
:label="opt.label"
|
|
||||||
:value="opt.value"
|
|
||||||
/>
|
|
||||||
</el-select>
|
|
||||||
</div>
|
</div>
|
||||||
|
<param-builder
|
||||||
|
v-model="store.formData"
|
||||||
|
v-model:required-keys="store.requiredKeys"
|
||||||
|
:items="store.functionParams[store.activeFunction]"
|
||||||
|
:progress="store.progress[store.activeFunction]"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 提交按钮 -->
|
<!-- 提交按钮 -->
|
||||||
@@ -660,20 +386,13 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import '@/assets/css/jimeng.scss'
|
|
||||||
import loadingIcon from '@/assets/img/loading.gif'
|
import loadingIcon from '@/assets/img/loading.gif'
|
||||||
import ImageUpload from '@/components/ImageUpload.vue'
|
|
||||||
|
|
||||||
|
import ParamBuilder from '@/components/ParamBuilder.vue'
|
||||||
import Generating from '@/components/ui/Generating.vue'
|
import Generating from '@/components/ui/Generating.vue'
|
||||||
import {
|
import { useJimengStore } from '@/store/jimeng'
|
||||||
imageEffectsTemplateOptions,
|
|
||||||
imageSizeOptions,
|
|
||||||
useJimengStore,
|
|
||||||
videoAspectRatioOptions,
|
|
||||||
} from '@/store/jimeng'
|
|
||||||
import { useSharedStore } from '@/store/sharedata'
|
import { useSharedStore } from '@/store/sharedata'
|
||||||
import { dateFormat } from '@/utils/libs'
|
import { dateFormat } from '@/utils/libs'
|
||||||
import { Switch } from '@element-plus/icons-vue'
|
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
import { onMounted, onUnmounted, ref, watch } from 'vue'
|
import { onMounted, onUnmounted, ref, watch } from 'vue'
|
||||||
import { Waterfall } from 'vue-waterfall-plugin-next'
|
import { Waterfall } from 'vue-waterfall-plugin-next'
|
||||||
@@ -682,17 +401,6 @@ import 'vue-waterfall-plugin-next/dist/style.css'
|
|||||||
const sharedStore = useSharedStore()
|
const sharedStore = useSharedStore()
|
||||||
const waterfallOptions = sharedStore.waterfallOptions
|
const waterfallOptions = sharedStore.waterfallOptions
|
||||||
|
|
||||||
// 获取分类图标
|
|
||||||
const getCategoryIcon = (category) => {
|
|
||||||
const iconMap = {
|
|
||||||
image_generation: 'iconfont icon-image',
|
|
||||||
image_editing: 'iconfont icon-edit',
|
|
||||||
image_effects: 'iconfont icon-chuangzuo',
|
|
||||||
video_generation: 'iconfont icon-video',
|
|
||||||
}
|
|
||||||
return iconMap[category] || 'iconfont icon-image'
|
|
||||||
}
|
|
||||||
|
|
||||||
const store = useJimengStore()
|
const store = useJimengStore()
|
||||||
|
|
||||||
// 新增:瀑布流渲染完成状态
|
// 新增:瀑布流渲染完成状态
|
||||||
@@ -730,13 +438,6 @@ watch(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
function handleTemplateChange(value) {
|
|
||||||
templatePreview.value = imageEffectsTemplateOptions.find((opt) => opt.value === value)?.preview
|
|
||||||
store.imageEffectsParams.prompt = imageEffectsTemplateOptions.find(
|
|
||||||
(opt) => opt.value === value
|
|
||||||
)?.label
|
|
||||||
}
|
|
||||||
|
|
||||||
function onWaterfallAfterRender() {
|
function onWaterfallAfterRender() {
|
||||||
waterfallRendered.value = true
|
waterfallRendered.value = true
|
||||||
if (!store.loading && !store.isOver) {
|
if (!store.loading && !store.isOver) {
|
||||||
@@ -768,150 +469,5 @@ function copyErrorMsg(msg) {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.task-list {
|
@use '@/assets/css/jimeng.scss' as *;
|
||||||
.task-grid {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
|
|
||||||
gap: 20px;
|
|
||||||
padding: 10px 0;
|
|
||||||
}
|
|
||||||
// 新增:增强任务项悬停动画
|
|
||||||
.task-item {
|
|
||||||
transition: box-shadow 3s cubic-bezier(0.4, 0, 0.2, 1),
|
|
||||||
transform 0.5s cubic-bezier(0.4, 0, 0.2, 1), border-color 0.5s;
|
|
||||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
|
|
||||||
border: 1.5px solid transparent;
|
|
||||||
border-radius: 12px;
|
|
||||||
background: #fff;
|
|
||||||
position: relative;
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
.task-item:hover {
|
|
||||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.18), 0 1.5px 8px rgba(0, 0, 0, 0.1);
|
|
||||||
border-color: #a259ff;
|
|
||||||
transform: scale(1.025) translateY(-2px);
|
|
||||||
z-index: 10;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@media (max-width: 1200px) {
|
|
||||||
.task-list .task-grid {
|
|
||||||
grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@media (max-width: 768px) {
|
|
||||||
.task-list .task-grid {
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.preview-video-wrapper {
|
|
||||||
position: relative;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
|
|
||||||
.video-mask {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background: rgba(0, 0, 0, 0.25);
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
opacity: 0;
|
|
||||||
transition: opacity 0.2s;
|
|
||||||
z-index: 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover .video-mask {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.play-btn {
|
|
||||||
width: 64px;
|
|
||||||
height: 64px;
|
|
||||||
background: rgba(255, 255, 255, 0.3);
|
|
||||||
border-radius: 50%;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
|
||||||
cursor: pointer;
|
|
||||||
z-index: 3;
|
|
||||||
transition: background 0.2s;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: rgba(255, 255, 255, 0.4);
|
|
||||||
}
|
|
||||||
|
|
||||||
img {
|
|
||||||
width: 36px;
|
|
||||||
height: 36px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.err-msg-clip {
|
|
||||||
display: -webkit-box;
|
|
||||||
-webkit-line-clamp: 2;
|
|
||||||
line-clamp: 2;
|
|
||||||
-webkit-box-orient: vertical;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
word-break: break-all;
|
|
||||||
white-space: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
.jimeng-template-select {
|
|
||||||
.el-select-dropdown__item {
|
|
||||||
height: 60px;
|
|
||||||
line-height: 60px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 新增:提示词指南样式
|
|
||||||
.prompt-guide {
|
|
||||||
margin: 12px 0 16px;
|
|
||||||
|
|
||||||
.guide-title {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
font-weight: 600;
|
|
||||||
color: #666;
|
|
||||||
}
|
|
||||||
|
|
||||||
.guide-content {
|
|
||||||
max-height: 220px;
|
|
||||||
overflow: auto;
|
|
||||||
line-height: 1.6;
|
|
||||||
font-size: 12px;
|
|
||||||
color: #555;
|
|
||||||
padding-right: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.guide-section {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.guide-subtitle {
|
|
||||||
font-weight: 600;
|
|
||||||
margin-bottom: 6px;
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
ul {
|
|
||||||
list-style: disc;
|
|
||||||
padding-left: 18px;
|
|
||||||
margin: 4px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.quote {
|
|
||||||
margin: 8px 0;
|
|
||||||
padding: 8px 10px;
|
|
||||||
border-left: 3px solid #a3a3a3;
|
|
||||||
background: #f8f8f8;
|
|
||||||
border-radius: 4px;
|
|
||||||
color: #444;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -56,134 +56,55 @@
|
|||||||
<h3 class="heading-3 mb-3">算力配置</h3>
|
<h3 class="heading-3 mb-3">算力配置</h3>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<template #label>
|
<template #label>
|
||||||
<div class="label-title">
|
<div class="text-gray-500 text-sm">
|
||||||
文生图算力
|
生成图片消耗的积分,包括:文生图、图生图、图片编辑、图片特效,<span
|
||||||
<el-tooltip
|
class="text-red-500"
|
||||||
effect="dark"
|
>单位:积分/张</span
|
||||||
content="用户使用文生图功能时消耗的算力"
|
|
||||||
raw-content
|
|
||||||
placement="right"
|
|
||||||
>
|
>
|
||||||
<el-icon>
|
|
||||||
<InfoFilled />
|
|
||||||
</el-icon>
|
|
||||||
</el-tooltip>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<el-input-number
|
<el-input-number
|
||||||
v-model="jimengConfig.power.text_to_image"
|
v-model="jimengConfig.power.image"
|
||||||
:min="1"
|
:min="1"
|
||||||
placeholder="请输入文生图算力消耗"
|
placeholder="请输入图片生成算力消耗"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<template #label>
|
<template #label>
|
||||||
<div class="label-title">
|
<div class="text-gray-500 text-sm">
|
||||||
图生图算力
|
生成视频消耗的积分,包括:文生视频、图生视频,<span class="text-red-500"
|
||||||
<el-tooltip
|
>单位:积分/秒</span
|
||||||
effect="dark"
|
|
||||||
content="用户使用图生图功能时消耗的算力"
|
|
||||||
raw-content
|
|
||||||
placement="right"
|
|
||||||
>
|
>
|
||||||
<el-icon>
|
|
||||||
<InfoFilled />
|
|
||||||
</el-icon>
|
|
||||||
</el-tooltip>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<el-input-number
|
<el-input-number
|
||||||
v-model="jimengConfig.power.image_to_image"
|
v-model="jimengConfig.power.video"
|
||||||
:min="1"
|
:min="1"
|
||||||
placeholder="请输入图生图算力消耗"
|
placeholder="请输入视频生成算力消耗"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<template #label>
|
<template #label>
|
||||||
<div class="label-title">
|
<div class="text-gray-500 text-sm">
|
||||||
图片编辑算力
|
生成数字人视频消耗的积分,<span class="text-red-500">单位:积分/秒</span>
|
||||||
<el-tooltip
|
|
||||||
effect="dark"
|
|
||||||
content="用户使用图片编辑功能时消耗的算力"
|
|
||||||
raw-content
|
|
||||||
placement="right"
|
|
||||||
>
|
|
||||||
<el-icon>
|
|
||||||
<InfoFilled />
|
|
||||||
</el-icon>
|
|
||||||
</el-tooltip>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<el-input-number
|
<el-input-number
|
||||||
v-model="jimengConfig.power.image_edit"
|
v-model="jimengConfig.power.virtual_human"
|
||||||
:min="1"
|
:min="1"
|
||||||
placeholder="请输入图片编辑算力消耗"
|
placeholder="请输入数字人视频生成算力消耗"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<template #label>
|
<template #label>
|
||||||
<div class="label-title">
|
<div class="text-gray-500 text-sm">
|
||||||
图片特效算力
|
生成视频动作迁移消耗的积分,<span class="text-red-500">单位:积分/秒</span>
|
||||||
<el-tooltip
|
|
||||||
effect="dark"
|
|
||||||
content="用户使用图片特效功能时消耗的算力"
|
|
||||||
raw-content
|
|
||||||
placement="right"
|
|
||||||
>
|
|
||||||
<el-icon>
|
|
||||||
<InfoFilled />
|
|
||||||
</el-icon>
|
|
||||||
</el-tooltip>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<el-input-number
|
<el-input-number
|
||||||
v-model="jimengConfig.power.image_effects"
|
v-model="jimengConfig.power.action_transfer"
|
||||||
:min="1"
|
:min="1"
|
||||||
placeholder="请输入图片特效算力消耗"
|
placeholder="请输入视频动作迁移算力消耗"
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
|
||||||
<template #label>
|
|
||||||
<div class="label-title">
|
|
||||||
文生视频算力
|
|
||||||
<el-tooltip
|
|
||||||
effect="dark"
|
|
||||||
content="用户使用文生视频功能时消耗的算力"
|
|
||||||
raw-content
|
|
||||||
placement="right"
|
|
||||||
>
|
|
||||||
<el-icon>
|
|
||||||
<InfoFilled />
|
|
||||||
</el-icon>
|
|
||||||
</el-tooltip>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<el-input-number
|
|
||||||
v-model="jimengConfig.power.text_to_video"
|
|
||||||
:min="1"
|
|
||||||
placeholder="请输入文生视频算力消耗"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
|
||||||
<template #label>
|
|
||||||
<div class="label-title">
|
|
||||||
图生视频算力
|
|
||||||
<el-tooltip
|
|
||||||
effect="dark"
|
|
||||||
content="用户使用图生视频功能时消耗的算力"
|
|
||||||
raw-content
|
|
||||||
placement="right"
|
|
||||||
>
|
|
||||||
<el-icon>
|
|
||||||
<InfoFilled />
|
|
||||||
</el-icon>
|
|
||||||
</el-tooltip>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<el-input-number
|
|
||||||
v-model="jimengConfig.power.image_to_video"
|
|
||||||
:min="1"
|
|
||||||
placeholder="请输入图生视频算力消耗"
|
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</div>
|
</div>
|
||||||
@@ -201,7 +122,6 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import Alert from '@/components/ui/Alert.vue'
|
import Alert from '@/components/ui/Alert.vue'
|
||||||
import { httpGet, httpPost } from '@/utils/http'
|
import { httpGet, httpPost } from '@/utils/http'
|
||||||
import { InfoFilled } from '@element-plus/icons-vue'
|
|
||||||
import { ElMessage } from 'element-plus'
|
import { ElMessage } from 'element-plus'
|
||||||
import { onMounted, ref } from 'vue'
|
import { onMounted, ref } from 'vue'
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,7 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import ParamBuilder from '@/components/ParamBuilder.vue'
|
import ParamBuilder from '@/components/ParamBuilder.vue'
|
||||||
import { JimengFunctions, JimengParams } from '@/store/data'
|
import { JimengFunctions, JimengParams } from '@/store/data/jimeng_data'
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
|
|
||||||
const functions = JimengFunctions
|
const functions = JimengFunctions
|
||||||
|
|||||||