mirror of
https://github.com/yangjian102621/geekai.git
synced 2026-04-29 06:24:24 +08:00
整理即梦生视频的API 代码
This commit is contained in:
@@ -98,6 +98,7 @@ func (s *AppServer) Run(db *gorm.DB) error {
|
|||||||
&model.MidJourneyJob{},
|
&model.MidJourneyJob{},
|
||||||
&model.UserLoginLog{},
|
&model.UserLoginLog{},
|
||||||
&model.DallJob{},
|
&model.DallJob{},
|
||||||
|
&model.JimengJob{},
|
||||||
)
|
)
|
||||||
// 手动删除字段
|
// 手动删除字段
|
||||||
if db.Migrator().HasColumn(&model.Order{}, "deleted_at") {
|
if db.Migrator().HasColumn(&model.Order{}, "deleted_at") {
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ require (
|
|||||||
github.com/go-pay/util v0.0.2 // indirect
|
github.com/go-pay/util v0.0.2 // indirect
|
||||||
github.com/go-pay/xlog v0.0.2 // indirect
|
github.com/go-pay/xlog v0.0.2 // indirect
|
||||||
github.com/go-pay/xtime v0.0.2 // indirect
|
github.com/go-pay/xtime v0.0.2 // indirect
|
||||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db // indirect
|
github.com/golang/snappy v0.0.4 // indirect
|
||||||
github.com/gorilla/css v1.0.0 // indirect
|
github.com/gorilla/css v1.0.0 // indirect
|
||||||
github.com/tklauser/go-sysconf v0.3.13 // indirect
|
github.com/tklauser/go-sysconf v0.3.13 // indirect
|
||||||
github.com/tklauser/numcpus v0.7.0 // indirect
|
github.com/tklauser/numcpus v0.7.0 // indirect
|
||||||
@@ -78,7 +78,7 @@ require (
|
|||||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||||
github.com/jinzhu/now v1.1.5 // indirect
|
github.com/jinzhu/now v1.1.5 // indirect
|
||||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af // indirect
|
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||||
github.com/klauspost/compress v1.16.7 // indirect
|
github.com/klauspost/compress v1.16.7 // indirect
|
||||||
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
|
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
|
||||||
github.com/minio/md5-simd v1.1.2 // indirect
|
github.com/minio/md5-simd v1.1.2 // indirect
|
||||||
@@ -120,7 +120,7 @@ require (
|
|||||||
github.com/ugorji/go/codec v1.2.11 // indirect
|
github.com/ugorji/go/codec v1.2.11 // indirect
|
||||||
go.uber.org/atomic v1.9.0 // indirect
|
go.uber.org/atomic v1.9.0 // indirect
|
||||||
go.uber.org/fx v1.19.3
|
go.uber.org/fx v1.19.3
|
||||||
go.uber.org/multierr v1.6.0 // indirect
|
go.uber.org/multierr v1.7.0 // indirect
|
||||||
golang.org/x/crypto v0.23.0
|
golang.org/x/crypto v0.23.0
|
||||||
golang.org/x/sys v0.20.0 // indirect
|
golang.org/x/sys v0.20.0 // indirect
|
||||||
gorm.io/gorm v1.25.1
|
gorm.io/gorm v1.25.1
|
||||||
|
|||||||
15
api/go.sum
15
api/go.sum
@@ -87,8 +87,9 @@ github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVI
|
|||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w=
|
|
||||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
|
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
||||||
|
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/go-tika v0.3.1 h1:l+jr10hDhZjcgxFRfcQChRLo1bPXQeLFluMyvDhXTTA=
|
github.com/google/go-tika v0.3.1 h1:l+jr10hDhZjcgxFRfcQChRLo1bPXQeLFluMyvDhXTTA=
|
||||||
@@ -115,8 +116,11 @@ github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkr
|
|||||||
github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||||
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
|
|
||||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||||
|
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
|
||||||
|
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
||||||
|
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
|
||||||
|
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
|
||||||
github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||||
@@ -260,8 +264,8 @@ go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
|
|||||||
go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
|
go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
|
||||||
go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
|
go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
|
||||||
go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
|
go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
|
||||||
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
|
go.uber.org/multierr v1.7.0 h1:zaiO/rmgFjbmCXdSYJWQcdvOCsthmdaHfr3Gm2Kx4Ec=
|
||||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak=
|
||||||
go.uber.org/zap v1.23.0 h1:OjGQ5KQDEUawVHxNwQgPpiypGHOxo2mNZsOqTak4fFY=
|
go.uber.org/zap v1.23.0 h1:OjGQ5KQDEUawVHxNwQgPpiypGHOxo2mNZsOqTak4fFY=
|
||||||
go.uber.org/zap v1.23.0/go.mod h1:D+nX8jyLsMHMYrln8A0rJjFt/T/9/bGgIhAqxv5URuY=
|
go.uber.org/zap v1.23.0/go.mod h1:D+nX8jyLsMHMYrln8A0rJjFt/T/9/bGgIhAqxv5URuY=
|
||||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||||
@@ -360,6 +364,9 @@ gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYs
|
|||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||||
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package handler
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"geekai/core"
|
"geekai/core"
|
||||||
@@ -83,10 +82,10 @@ func (h *JimengHandler) TextToImage(c *gin.Context) {
|
|||||||
|
|
||||||
// 创建任务
|
// 创建任务
|
||||||
taskReq := &jimeng.CreateTaskRequest{
|
taskReq := &jimeng.CreateTaskRequest{
|
||||||
Type: model.JimengJobTypeTextToImage,
|
Type: model.JMTaskTypeTextToImage,
|
||||||
Prompt: req.Prompt,
|
Prompt: req.Prompt,
|
||||||
Params: params,
|
Params: params,
|
||||||
ReqKey: model.ReqKeyTextToImage,
|
ReqKey: jimeng.ReqKeyTextToImage,
|
||||||
Power: 20,
|
Power: 20,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,10 +179,10 @@ func (h *JimengHandler) ImageToImagePortrait(c *gin.Context) {
|
|||||||
|
|
||||||
// 创建任务
|
// 创建任务
|
||||||
taskReq := &jimeng.CreateTaskRequest{
|
taskReq := &jimeng.CreateTaskRequest{
|
||||||
Type: model.JimengJobTypeImageToImagePortrait,
|
Type: model.JMTaskTypeImageToImage,
|
||||||
Prompt: req.Prompt,
|
Prompt: req.Prompt,
|
||||||
Params: params,
|
Params: params,
|
||||||
ReqKey: model.ReqKeyImageToImagePortrait,
|
ReqKey: jimeng.ReqKeyImageToImagePortrait,
|
||||||
Power: 30,
|
Power: 30,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -259,10 +258,10 @@ func (h *JimengHandler) ImageEdit(c *gin.Context) {
|
|||||||
|
|
||||||
// 创建任务
|
// 创建任务
|
||||||
taskReq := &jimeng.CreateTaskRequest{
|
taskReq := &jimeng.CreateTaskRequest{
|
||||||
Type: model.JimengJobTypeImageEdit,
|
Type: model.JMTaskTypeImageEdit,
|
||||||
Prompt: req.Prompt,
|
Prompt: req.Prompt,
|
||||||
Params: params,
|
Params: params,
|
||||||
ReqKey: model.ReqKeyImageEdit,
|
ReqKey: jimeng.ReqKeyImageEdit,
|
||||||
Power: 25,
|
Power: 25,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -328,10 +327,10 @@ func (h *JimengHandler) ImageEffects(c *gin.Context) {
|
|||||||
|
|
||||||
// 创建任务
|
// 创建任务
|
||||||
taskReq := &jimeng.CreateTaskRequest{
|
taskReq := &jimeng.CreateTaskRequest{
|
||||||
Type: model.JimengJobTypeImageEffects,
|
Type: model.JMTaskTypeImageEffects,
|
||||||
Prompt: "",
|
Prompt: "",
|
||||||
Params: params,
|
Params: params,
|
||||||
ReqKey: model.ReqKeyImageEffects,
|
ReqKey: jimeng.ReqKeyImageEffects,
|
||||||
Power: 15,
|
Power: 15,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -394,10 +393,10 @@ func (h *JimengHandler) TextToVideo(c *gin.Context) {
|
|||||||
|
|
||||||
// 创建任务
|
// 创建任务
|
||||||
taskReq := &jimeng.CreateTaskRequest{
|
taskReq := &jimeng.CreateTaskRequest{
|
||||||
Type: model.JimengJobTypeTextToVideo,
|
Type: model.JMTaskTypeTextToVideo,
|
||||||
Prompt: req.Prompt,
|
Prompt: req.Prompt,
|
||||||
Params: params,
|
Params: params,
|
||||||
ReqKey: model.ReqKeyTextToVideo,
|
ReqKey: jimeng.ReqKeyTextToVideo,
|
||||||
Power: 100,
|
Power: 100,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -470,10 +469,10 @@ func (h *JimengHandler) ImageToVideo(c *gin.Context) {
|
|||||||
|
|
||||||
// 创建任务
|
// 创建任务
|
||||||
taskReq := &jimeng.CreateTaskRequest{
|
taskReq := &jimeng.CreateTaskRequest{
|
||||||
Type: model.JimengJobTypeImageToVideo,
|
Type: model.JMTaskTypeImageToVideo,
|
||||||
Prompt: req.Prompt,
|
Prompt: req.Prompt,
|
||||||
Params: params,
|
Params: params,
|
||||||
ReqKey: model.ReqKeyImageToVideo,
|
ReqKey: jimeng.ReqKeyImageToVideo,
|
||||||
Power: 120,
|
Power: 120,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -569,9 +568,8 @@ func (h *JimengHandler) Retry(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
jobIdStr := c.Param("id")
|
jobId := h.GetInt(c, "id", 0)
|
||||||
jobId, err := strconv.ParseUint(jobIdStr, 10, 32)
|
if jobId == 0 {
|
||||||
if err != nil {
|
|
||||||
resp.ERROR(c, "参数错误")
|
resp.ERROR(c, "参数错误")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -589,13 +587,13 @@ func (h *JimengHandler) Retry(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 只有失败的任务才能重试
|
// 只有失败的任务才能重试
|
||||||
if job.Status != model.JimengJobStatusFailed {
|
if job.Status != model.JMTaskStatusFailed {
|
||||||
resp.ERROR(c, "只有失败的任务才能重试")
|
resp.ERROR(c, "只有失败的任务才能重试")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 重置任务状态
|
// 重置任务状态
|
||||||
if err := h.jimengService.UpdateJobStatus(uint(jobId), model.JimengJobStatusPending, ""); err != nil {
|
if err := h.jimengService.UpdateJobStatus(uint(jobId), model.JMTaskStatusInQueue, ""); err != nil {
|
||||||
logger.Errorf("reset job status failed: %v", err)
|
logger.Errorf("reset job status failed: %v", err)
|
||||||
resp.ERROR(c, "重置任务状态失败")
|
resp.ERROR(c, "重置任务状态失败")
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -525,7 +525,7 @@ func main() {
|
|||||||
group.GET("jobs", h.Jobs)
|
group.GET("jobs", h.Jobs)
|
||||||
group.GET("pending-count", h.PendingCount)
|
group.GET("pending-count", h.PendingCount)
|
||||||
group.GET("remove", h.Remove)
|
group.GET("remove", h.Remove)
|
||||||
group.POST("retry/:id", h.Retry)
|
group.GET("retry", h.Retry)
|
||||||
}),
|
}),
|
||||||
fx.Invoke(func(s *core.AppServer, h *admin.AdminJimengHandler) {
|
fx.Invoke(func(s *core.AppServer, h *admin.AdminJimengHandler) {
|
||||||
group := s.Engine.Group("/api/admin/jimeng")
|
group := s.Engine.Group("/api/admin/jimeng")
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ func (c *Consumer) processTask() {
|
|||||||
jimengLogger.Errorf("process jimeng task failed: job_id=%d, error=%v", jobId, err)
|
jimengLogger.Errorf("process jimeng task failed: job_id=%d, error=%v", jobId, err)
|
||||||
|
|
||||||
// 任务失败,直接标记为失败状态,不进行重试
|
// 任务失败,直接标记为失败状态,不进行重试
|
||||||
c.service.UpdateJobStatus(jobId, model.JimengJobStatusFailed, err.Error())
|
c.service.UpdateJobStatus(jobId, model.JMTaskStatusFailed, err.Error())
|
||||||
} else {
|
} else {
|
||||||
jimengLogger.Infof("Jimeng task processed successfully: job_id=%d", jobId)
|
jimengLogger.Infof("Jimeng task processed successfully: job_id=%d", jobId)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ func (s *Service) CreateTask(userId uint, req *CreateTaskRequest) (*model.Jimeng
|
|||||||
ReqKey: req.ReqKey,
|
ReqKey: req.ReqKey,
|
||||||
Prompt: req.Prompt,
|
Prompt: req.Prompt,
|
||||||
TaskParams: string(paramsJson),
|
TaskParams: string(paramsJson),
|
||||||
Status: model.JimengJobStatusPending,
|
Status: model.JMTaskStatusInQueue,
|
||||||
Power: req.Power,
|
Power: req.Power,
|
||||||
CreatedAt: time.Now(),
|
CreatedAt: time.Now(),
|
||||||
UpdatedAt: time.Now(),
|
UpdatedAt: time.Now(),
|
||||||
@@ -88,23 +88,23 @@ func (s *Service) ProcessTask(jobId uint) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 更新任务状态为处理中
|
// 更新任务状态为处理中
|
||||||
if err := s.UpdateJobStatus(job.Id, model.JimengJobStatusProcessing, ""); err != nil {
|
if err := s.UpdateJobStatus(job.Id, model.JMTaskStatusGenerating, ""); err != nil {
|
||||||
return fmt.Errorf("update job status failed: %w", err)
|
return fmt.Errorf("update job status failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 根据任务类型处理
|
// 根据任务类型处理
|
||||||
switch job.Type {
|
switch job.Type {
|
||||||
case model.JimengJobTypeTextToImage:
|
case model.JMTaskTypeTextToImage:
|
||||||
return s.processTextToImage(&job)
|
return s.processTextToImage(&job)
|
||||||
case model.JimengJobTypeImageToImagePortrait:
|
case model.JMTaskTypeImageToImage:
|
||||||
return s.processImageToImagePortrait(&job)
|
return s.processImageToImagePortrait(&job)
|
||||||
case model.JimengJobTypeImageEdit:
|
case model.JMTaskTypeImageEdit:
|
||||||
return s.processImageEdit(&job)
|
return s.processImageEdit(&job)
|
||||||
case model.JimengJobTypeImageEffects:
|
case model.JMTaskTypeImageEffects:
|
||||||
return s.processImageEffects(&job)
|
return s.processImageEffects(&job)
|
||||||
case model.JimengJobTypeTextToVideo:
|
case model.JMTaskTypeTextToVideo:
|
||||||
return s.processTextToVideo(&job)
|
return s.processTextToVideo(&job)
|
||||||
case model.JimengJobTypeImageToVideo:
|
case model.JMTaskTypeImageToVideo:
|
||||||
return s.processImageToVideo(&job)
|
return s.processImageToVideo(&job)
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unsupported task type: %s", job.Type)
|
return fmt.Errorf("unsupported task type: %s", job.Type)
|
||||||
@@ -517,10 +517,15 @@ func (s *Service) pollTaskStatus(jobId uint, taskId, reqKey string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch resp.Data.Status {
|
switch resp.Data.Status {
|
||||||
case TaskStatusDone:
|
case model.JMTaskStatusDone:
|
||||||
|
// 判断任务是否成功
|
||||||
|
if resp.Message != "Success" {
|
||||||
|
return s.handleTaskError(jobId, fmt.Sprintf("task failed: %s", resp.Data.AlgorithmBaseResp.StatusMessage))
|
||||||
|
}
|
||||||
|
|
||||||
// 任务完成,更新结果
|
// 任务完成,更新结果
|
||||||
updates := map[string]any{
|
updates := map[string]any{
|
||||||
"status": model.JimengJobStatusCompleted,
|
"status": model.JMTaskStatusSuccess,
|
||||||
"progress": 100,
|
"progress": 100,
|
||||||
"updated_at": time.Now(),
|
"updated_at": time.Now(),
|
||||||
}
|
}
|
||||||
@@ -535,15 +540,15 @@ func (s *Service) pollTaskStatus(jobId uint, taskId, reqKey string) error {
|
|||||||
|
|
||||||
return s.db.Model(&model.JimengJob{}).Where("id = ?", jobId).Updates(updates).Error
|
return s.db.Model(&model.JimengJob{}).Where("id = ?", jobId).Updates(updates).Error
|
||||||
|
|
||||||
case TaskStatusInQueue:
|
case model.JMTaskStatusInQueue:
|
||||||
// 任务在队列中
|
// 任务在队列中
|
||||||
s.UpdateJobProgress(jobId, 10)
|
s.UpdateJobProgress(jobId, 10)
|
||||||
|
|
||||||
case TaskStatusGenerating:
|
case model.JMTaskStatusGenerating:
|
||||||
// 任务处理中
|
// 任务处理中
|
||||||
s.UpdateJobProgress(jobId, 50)
|
s.UpdateJobProgress(jobId, 50)
|
||||||
|
|
||||||
case TaskStatusNotFound, TaskStatusExpired:
|
case model.JMTaskStatusNotFound:
|
||||||
// 任务未找到或已过期
|
// 任务未找到或已过期
|
||||||
return s.handleTaskError(jobId, fmt.Sprintf("task not found or expired: %s", resp.Data.Status))
|
return s.handleTaskError(jobId, fmt.Sprintf("task not found or expired: %s", resp.Data.Status))
|
||||||
|
|
||||||
@@ -559,7 +564,7 @@ func (s *Service) pollTaskStatus(jobId uint, taskId, reqKey string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UpdateJobStatus 更新任务状态
|
// UpdateJobStatus 更新任务状态
|
||||||
func (s *Service) UpdateJobStatus(jobId uint, status, errMsg string) error {
|
func (s *Service) UpdateJobStatus(jobId uint, status model.JMTaskStatus, errMsg string) error {
|
||||||
updates := map[string]any{
|
updates := map[string]any{
|
||||||
"status": status,
|
"status": status,
|
||||||
"updated_at": time.Now(),
|
"updated_at": time.Now(),
|
||||||
@@ -581,7 +586,7 @@ func (s *Service) UpdateJobProgress(jobId uint, progress int) error {
|
|||||||
// handleTaskError 处理任务错误
|
// handleTaskError 处理任务错误
|
||||||
func (s *Service) handleTaskError(jobId uint, errMsg string) error {
|
func (s *Service) handleTaskError(jobId uint, errMsg string) error {
|
||||||
serviceLogger.Errorf("Jimeng task error (job_id: %d): %s", jobId, errMsg)
|
serviceLogger.Errorf("Jimeng task error (job_id: %d): %s", jobId, errMsg)
|
||||||
return s.UpdateJobStatus(jobId, model.JimengJobStatusFailed, errMsg)
|
return s.UpdateJobStatus(jobId, model.JMTaskStatusFailed, errMsg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetJob 获取任务
|
// GetJob 获取任务
|
||||||
@@ -618,7 +623,7 @@ func (s *Service) GetUserJobs(userId uint, page, pageSize int) ([]*model.JimengJ
|
|||||||
func (s *Service) GetPendingTaskCount(userId uint) (int64, error) {
|
func (s *Service) GetPendingTaskCount(userId uint) (int64, error) {
|
||||||
var count int64
|
var count int64
|
||||||
err := s.db.Model(&model.JimengJob{}).Where("user_id = ? AND status IN (?)", userId,
|
err := s.db.Model(&model.JimengJob{}).Where("user_id = ? AND status IN (?)", userId,
|
||||||
[]string{model.JimengJobStatusPending, model.JimengJobStatusProcessing}).Count(&count).Error
|
[]model.JMTaskStatus{model.JMTaskStatusInQueue, model.JMTaskStatusGenerating}).Count(&count).Error
|
||||||
return count, err
|
return count, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,25 +1,35 @@
|
|||||||
package jimeng
|
package jimeng
|
||||||
|
|
||||||
import "time"
|
import "geekai/store/model"
|
||||||
|
|
||||||
|
// ReqKey 常量定义
|
||||||
|
const (
|
||||||
|
ReqKeyTextToImage = "high_aes_general_v30l_zt2i" // 文生图
|
||||||
|
ReqKeyImageToImagePortrait = "i2i_portrait_photo" // 图生图人像写真
|
||||||
|
ReqKeyImageEdit = "seededit_v3.0" // 图像编辑
|
||||||
|
ReqKeyImageEffects = "i2i_multi_style_zx2x" // 图像特效
|
||||||
|
ReqKeyTextToVideo = "jimeng_vgfm_t2v_l20" // 文生视频
|
||||||
|
ReqKeyImageToVideo = "jimeng_vgfm_i2v_l20" // 图生视频
|
||||||
|
)
|
||||||
|
|
||||||
// SubmitTaskRequest 提交任务请求
|
// SubmitTaskRequest 提交任务请求
|
||||||
type SubmitTaskRequest struct {
|
type SubmitTaskRequest struct {
|
||||||
ReqKey string `json:"req_key"`
|
ReqKey string `json:"req_key"`
|
||||||
// 文生图参数
|
// 文生图参数
|
||||||
Prompt string `json:"prompt,omitempty"`
|
Prompt string `json:"prompt,omitempty"`
|
||||||
Seed int64 `json:"seed,omitempty"`
|
Seed int64 `json:"seed,omitempty"`
|
||||||
Scale float64 `json:"scale,omitempty"`
|
Scale float64 `json:"scale,omitempty"`
|
||||||
Width int `json:"width,omitempty"`
|
Width int `json:"width,omitempty"`
|
||||||
Height int `json:"height,omitempty"`
|
Height int `json:"height,omitempty"`
|
||||||
UsePreLLM bool `json:"use_pre_llm,omitempty"`
|
UsePreLLM bool `json:"use_pre_llm,omitempty"`
|
||||||
// 图生图参数
|
// 图生图参数
|
||||||
ImageInput string `json:"image_input,omitempty"`
|
ImageInput string `json:"image_input,omitempty"`
|
||||||
ImageUrls []string `json:"image_urls,omitempty"`
|
ImageUrls []string `json:"image_urls,omitempty"`
|
||||||
BinaryDataBase64 []string `json:"binary_data_base64,omitempty"`
|
BinaryDataBase64 []string `json:"binary_data_base64,omitempty"`
|
||||||
Gpen float64 `json:"gpen,omitempty"`
|
Gpen float64 `json:"gpen,omitempty"`
|
||||||
Skin float64 `json:"skin,omitempty"`
|
Skin float64 `json:"skin,omitempty"`
|
||||||
SkinUnifi float64 `json:"skin_unifi,omitempty"`
|
SkinUnifi float64 `json:"skin_unifi,omitempty"`
|
||||||
GenMode string `json:"gen_mode,omitempty"`
|
GenMode string `json:"gen_mode,omitempty"`
|
||||||
// 图像编辑参数
|
// 图像编辑参数
|
||||||
// 图像特效参数
|
// 图像特效参数
|
||||||
ImageInput1 string `json:"image_input1,omitempty"`
|
ImageInput1 string `json:"image_input1,omitempty"`
|
||||||
@@ -59,56 +69,28 @@ type QueryTaskResponse struct {
|
|||||||
StatusCode int `json:"status_code"`
|
StatusCode int `json:"status_code"`
|
||||||
StatusMessage string `json:"status_message"`
|
StatusMessage string `json:"status_message"`
|
||||||
} `json:"algorithm_base_resp"`
|
} `json:"algorithm_base_resp"`
|
||||||
BinaryDataBase64 []string `json:"binary_data_base64"`
|
BinaryDataBase64 []string `json:"binary_data_base64"`
|
||||||
ImageUrls []string `json:"image_urls"`
|
ImageUrls []string `json:"image_urls"`
|
||||||
VideoUrl string `json:"video_url"`
|
VideoUrl string `json:"video_url"`
|
||||||
RespData string `json:"resp_data"`
|
RespData string `json:"resp_data"`
|
||||||
Status string `json:"status"`
|
Status model.JMTaskStatus `json:"status"`
|
||||||
LlmResult string `json:"llm_result"`
|
LlmResult string `json:"llm_result"`
|
||||||
PeResult string `json:"pe_result"`
|
PeResult string `json:"pe_result"`
|
||||||
PredictTagsResult string `json:"predict_tags_result"`
|
PredictTagsResult string `json:"predict_tags_result"`
|
||||||
RephraserResult string `json:"rephraser_result"`
|
RephraserResult string `json:"rephraser_result"`
|
||||||
VlmResult string `json:"vlm_result"`
|
VlmResult string `json:"vlm_result"`
|
||||||
InferCtx interface{} `json:"infer_ctx"`
|
InferCtx any `json:"infer_ctx"`
|
||||||
} `json:"data"`
|
} `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// TaskStatus 任务状态
|
|
||||||
const (
|
|
||||||
TaskStatusInQueue = "in_queue" // 任务已提交
|
|
||||||
TaskStatusGenerating = "generating" // 任务处理中
|
|
||||||
TaskStatusDone = "done" // 处理完成
|
|
||||||
TaskStatusNotFound = "not_found" // 任务未找到
|
|
||||||
TaskStatusExpired = "expired" // 任务已过期
|
|
||||||
)
|
|
||||||
|
|
||||||
// CreateTaskRequest 创建任务请求
|
// CreateTaskRequest 创建任务请求
|
||||||
type CreateTaskRequest struct {
|
type CreateTaskRequest struct {
|
||||||
Type string `json:"type"`
|
Type model.JMTaskType `json:"type"`
|
||||||
Prompt string `json:"prompt"`
|
Prompt string `json:"prompt"`
|
||||||
Params map[string]interface{} `json:"params"`
|
Params map[string]any `json:"params"`
|
||||||
ReqKey string `json:"req_key"`
|
ReqKey string `json:"req_key"`
|
||||||
ImageUrls []string `json:"image_urls,omitempty"`
|
ImageUrls []string `json:"image_urls,omitempty"`
|
||||||
Power int `json:"power,omitempty"`
|
Power int `json:"power,omitempty"`
|
||||||
}
|
|
||||||
|
|
||||||
// TaskInfo 任务信息
|
|
||||||
type TaskInfo struct {
|
|
||||||
Id uint `json:"id"`
|
|
||||||
UserId uint `json:"user_id"`
|
|
||||||
TaskId string `json:"task_id"`
|
|
||||||
Type string `json:"type"`
|
|
||||||
ReqKey string `json:"req_key"`
|
|
||||||
Prompt string `json:"prompt"`
|
|
||||||
TaskParams string `json:"task_params"`
|
|
||||||
ImgURL string `json:"img_url"`
|
|
||||||
VideoURL string `json:"video_url"`
|
|
||||||
Progress int `json:"progress"`
|
|
||||||
Status string `json:"status"`
|
|
||||||
ErrMsg string `json:"err_msg"`
|
|
||||||
Power int `json:"power"`
|
|
||||||
CreatedAt time.Time `json:"created_at"`
|
|
||||||
UpdatedAt time.Time `json:"updated_at"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// LogoInfo 水印信息
|
// LogoInfo 水印信息
|
||||||
@@ -128,36 +110,36 @@ type ReqJsonConfig struct {
|
|||||||
|
|
||||||
// ImageEffectTemplate 图像特效模板
|
// ImageEffectTemplate 图像特效模板
|
||||||
const (
|
const (
|
||||||
TemplateIdFelt3DPolaroid = "felt_3d_polaroid" // 毛毡3d拍立得风格
|
TemplateIdFelt3DPolaroid = "felt_3d_polaroid" // 毛毡3d拍立得风格
|
||||||
TemplateIdMyWorld = "my_world" // 像素世界风
|
TemplateIdMyWorld = "my_world" // 像素世界风
|
||||||
TemplateIdMyWorldUniversal = "my_world_universal" // 像素世界-万物通用版
|
TemplateIdMyWorldUniversal = "my_world_universal" // 像素世界-万物通用版
|
||||||
TemplateIdPlasticBubbleFigure = "plastic_bubble_figure" // 盲盒玩偶风
|
TemplateIdPlasticBubbleFigure = "plastic_bubble_figure" // 盲盒玩偶风
|
||||||
TemplateIdPlasticBubbleFigureCartoon = "plastic_bubble_figure_cartoon_text" // 塑料泡罩人偶-文字卡头版
|
TemplateIdPlasticBubbleFigureCartoon = "plastic_bubble_figure_cartoon_text" // 塑料泡罩人偶-文字卡头版
|
||||||
TemplateIdFurryDreamDoll = "furry_dream_doll" // 毛绒玩偶风
|
TemplateIdFurryDreamDoll = "furry_dream_doll" // 毛绒玩偶风
|
||||||
TemplateIdMicroLandscapeMiniWorld = "micro_landscape_mini_world" // 迷你世界玩偶风
|
TemplateIdMicroLandscapeMiniWorld = "micro_landscape_mini_world" // 迷你世界玩偶风
|
||||||
TemplateIdMicroLandscapeProfessional = "micro_landscape_mini_world_professional" // 微型景观小世界-职业版
|
TemplateIdMicroLandscapeProfessional = "micro_landscape_mini_world_professional" // 微型景观小世界-职业版
|
||||||
TemplateIdAcrylicOrnaments = "acrylic_ornaments" // 亚克力挂饰
|
TemplateIdAcrylicOrnaments = "acrylic_ornaments" // 亚克力挂饰
|
||||||
TemplateIdFeltKeychain = "felt_keychain" // 毛毡钥匙扣
|
TemplateIdFeltKeychain = "felt_keychain" // 毛毡钥匙扣
|
||||||
TemplateIdLofiPixelCharacter = "lofi_pixel_character_mini_card" // Lofi像素人物小卡
|
TemplateIdLofiPixelCharacter = "lofi_pixel_character_mini_card" // Lofi像素人物小卡
|
||||||
TemplateIdAngelFigurine = "angel_figurine" // 天使形象手办
|
TemplateIdAngelFigurine = "angel_figurine" // 天使形象手办
|
||||||
TemplateIdLyingInFluffyBelly = "lying_in_fluffy_belly" // 躺在毛茸茸肚皮里
|
TemplateIdLyingInFluffyBelly = "lying_in_fluffy_belly" // 躺在毛茸茸肚皮里
|
||||||
TemplateIdGlassBall = "glass_ball" // 玻璃球
|
TemplateIdGlassBall = "glass_ball" // 玻璃球
|
||||||
)
|
)
|
||||||
|
|
||||||
// AspectRatio 视频宽高比
|
// AspectRatio 视频宽高比
|
||||||
const (
|
const (
|
||||||
AspectRatio16_9 = "16:9" // 1280×720
|
AspectRatio16_9 = "16:9" // 1280×720
|
||||||
AspectRatio9_16 = "9:16" // 720×1280
|
AspectRatio9_16 = "9:16" // 720×1280
|
||||||
AspectRatio1_1 = "1:1" // 960×960
|
AspectRatio1_1 = "1:1" // 960×960
|
||||||
AspectRatio4_3 = "4:3" // 960×720
|
AspectRatio4_3 = "4:3" // 960×720
|
||||||
AspectRatio3_4 = "3:4" // 720×960
|
AspectRatio3_4 = "3:4" // 720×960
|
||||||
AspectRatio21_9 = "21:9" // 1680×720
|
AspectRatio21_9 = "21:9" // 1680×720
|
||||||
AspectRatio9_21 = "9:21" // 720×1680
|
AspectRatio9_21 = "9:21" // 720×1680
|
||||||
)
|
)
|
||||||
|
|
||||||
// GenMode 生成模式
|
// GenMode 生成模式
|
||||||
const (
|
const (
|
||||||
GenModeCreative = "creative" // 提示词模式
|
GenModeCreative = "creative" // 提示词模式
|
||||||
GenModeReference = "reference" // 全参考模式
|
GenModeReference = "reference" // 全参考模式
|
||||||
GenModeReferenceChar = "reference_char" // 人物参考模式
|
GenModeReferenceChar = "reference_char" // 人物参考模式
|
||||||
)
|
)
|
||||||
@@ -6,50 +6,46 @@ import (
|
|||||||
|
|
||||||
// JimengJob 即梦AI任务模型
|
// JimengJob 即梦AI任务模型
|
||||||
type JimengJob struct {
|
type JimengJob struct {
|
||||||
Id uint `gorm:"column:id;primaryKey;autoIncrement" json:"id"`
|
Id uint `gorm:"column:id;primaryKey;autoIncrement" json:"id"`
|
||||||
UserId uint `gorm:"column:user_id;type:int;not null;index;comment:用户ID" json:"user_id"`
|
UserId uint `gorm:"column:user_id;type:int;not null;index;comment:用户ID" json:"user_id"`
|
||||||
TaskId string `gorm:"column:task_id;type:varchar(100);not null;index;comment:任务ID" json:"task_id"`
|
TaskId string `gorm:"column:task_id;type:varchar(100);not null;index;comment:任务ID" json:"task_id"`
|
||||||
Type string `gorm:"column:type;type:varchar(50);not null;comment:任务类型" json:"type"`
|
Type JMTaskType `gorm:"column:type;type:varchar(50);not null;comment:任务类型" json:"type"`
|
||||||
ReqKey string `gorm:"column:req_key;type:varchar(100);comment:请求Key" json:"req_key"`
|
ReqKey string `gorm:"column:req_key;type:varchar(100);comment:请求Key" json:"req_key"`
|
||||||
Prompt string `gorm:"column:prompt;type:text;comment:提示词" json:"prompt"`
|
Prompt string `gorm:"column:prompt;type:text;comment:提示词" json:"prompt"`
|
||||||
TaskParams string `gorm:"column:task_params;type:text;comment:任务参数JSON" json:"task_params"`
|
TaskParams string `gorm:"column:task_params;type:text;comment:任务参数JSON" json:"task_params"`
|
||||||
ImgURL string `gorm:"column:img_url;type:varchar(1024);comment:图片或封面URL" json:"img_url"`
|
ImgURL string `gorm:"column:img_url;type:varchar(1024);comment:图片或封面URL" json:"img_url"`
|
||||||
VideoURL string `gorm:"column:video_url;type:varchar(1024);comment:视频URL" json:"video_url"`
|
VideoURL string `gorm:"column:video_url;type:varchar(1024);comment:视频URL" json:"video_url"`
|
||||||
RawData string `gorm:"column:raw_data;type:text;comment:原始API响应" json:"raw_data"`
|
RawData string `gorm:"column:raw_data;type:text;comment:原始API响应" json:"raw_data"`
|
||||||
Progress int `gorm:"column:progress;type:int;default:0;comment:进度百分比" json:"progress"`
|
Progress int `gorm:"column:progress;type:int;default:0;comment:进度百分比" json:"progress"`
|
||||||
Status string `gorm:"column:status;type:varchar(20);default:'pending';comment:任务状态" json:"status"`
|
Status JMTaskStatus `gorm:"column:status;type:varchar(20);default:'pending';comment:任务状态" json:"status"`
|
||||||
ErrMsg string `gorm:"column:err_msg;type:varchar(1024);comment:错误信息" json:"err_msg"`
|
ErrMsg string `gorm:"column:err_msg;type:varchar(1024);comment:错误信息" json:"err_msg"`
|
||||||
Power int `gorm:"column:power;type:int;default:0;comment:消耗算力" json:"power"`
|
Power int `gorm:"column:power;type:int(11);default:0;comment:消耗算力" json:"power"`
|
||||||
CreatedAt time.Time `gorm:"column:created_at;type:datetime;not null;comment:创建时间" json:"created_at"`
|
CreatedAt time.Time `gorm:"column:created_at;type:datetime;not null;comment:创建时间" json:"created_at"`
|
||||||
UpdatedAt time.Time `gorm:"column:updated_at;type:datetime;not null;comment:更新时间" json:"updated_at"`
|
UpdatedAt time.Time `gorm:"column:updated_at;type:datetime;not null;comment:更新时间" json:"updated_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// JimengJobStatus 即梦任务状态常量
|
// JMTaskStatus 任务状态
|
||||||
|
type JMTaskStatus string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
JimengJobStatusPending = "pending"
|
JMTaskStatusInQueue = JMTaskStatus("in_queue") // 任务已提交
|
||||||
JimengJobStatusProcessing = "processing"
|
JMTaskStatusGenerating = JMTaskStatus("generating") // 任务处理中
|
||||||
JimengJobStatusCompleted = "completed"
|
JMTaskStatusDone = JMTaskStatus("done") // 处理完成
|
||||||
JimengJobStatusFailed = "failed"
|
JMTaskStatusNotFound = JMTaskStatus("not_found") // 任务未找到
|
||||||
|
JMTaskStatusSuccess = JMTaskStatus("success") // 任务成功
|
||||||
|
JMTaskStatusFailed = JMTaskStatus("failed") // 任务失败
|
||||||
)
|
)
|
||||||
|
|
||||||
// JimengJobType 即梦任务类型常量
|
// JMTaskType 任务类型
|
||||||
const (
|
type JMTaskType string
|
||||||
JimengJobTypeTextToImage = "text_to_image" // 文生图
|
|
||||||
JimengJobTypeImageToImagePortrait = "image_to_image_portrait" // 图生图人像写真
|
|
||||||
JimengJobTypeImageEdit = "image_edit" // 图像编辑
|
|
||||||
JimengJobTypeImageEffects = "image_effects" // 图像特效
|
|
||||||
JimengJobTypeTextToVideo = "text_to_video" // 文生视频
|
|
||||||
JimengJobTypeImageToVideo = "image_to_video" // 图生视频
|
|
||||||
)
|
|
||||||
|
|
||||||
// ReqKey 常量定义
|
|
||||||
const (
|
const (
|
||||||
ReqKeyTextToImage = "high_aes_general_v30l_zt2i" // 文生图
|
JMTaskTypeTextToImage = JMTaskType("text_to_image") // 文生图
|
||||||
ReqKeyImageToImagePortrait = "i2i_portrait_photo" // 图生图人像写真
|
JMTaskTypeImageToImage = JMTaskType("image_to_image") // 图生图
|
||||||
ReqKeyImageEdit = "seededit_v3.0" // 图像编辑
|
JMTaskTypeImageEdit = JMTaskType("image_edit") // 图像编辑
|
||||||
ReqKeyImageEffects = "i2i_multi_style_zx2x" // 图像特效
|
JMTaskTypeImageEffects = JMTaskType("image_effects") // 图像特效
|
||||||
ReqKeyTextToVideo = "jimeng_vgfm_t2v_l20" // 文生视频
|
JMTaskTypeTextToVideo = JMTaskType("text_to_video") // 文生视频
|
||||||
ReqKeyImageToVideo = "jimeng_vgfm_i2v_l20" // 图生视频
|
JMTaskTypeImageToVideo = JMTaskType("image_to_video") // 图生视频
|
||||||
)
|
)
|
||||||
|
|
||||||
// TableName 返回数据表名称
|
// TableName 返回数据表名称
|
||||||
|
|||||||
311
web/src/assets/css/jimeng.styl
Normal file
311
web/src/assets/css/jimeng.styl
Normal file
@@ -0,0 +1,311 @@
|
|||||||
|
.page-jimeng {
|
||||||
|
display: flex;
|
||||||
|
min-height: 100vh;
|
||||||
|
background: var(--chat-bg);
|
||||||
|
|
||||||
|
// 左侧参数面板
|
||||||
|
.params-panel {
|
||||||
|
min-width: 380px;
|
||||||
|
max-width: 380px;
|
||||||
|
margin: 10px;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 12px;
|
||||||
|
background: #ffffff;
|
||||||
|
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
|
||||||
|
color: #333;
|
||||||
|
font-size: 14px;
|
||||||
|
overflow: auto;
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 20px;
|
||||||
|
text-align: center;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 功能分类按钮组
|
||||||
|
.category-buttons {
|
||||||
|
margin-bottom: 25px;
|
||||||
|
|
||||||
|
.category-label {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333;
|
||||||
|
|
||||||
|
.el-icon {
|
||||||
|
margin-right: 8px;
|
||||||
|
color: #5865f2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.category-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
gap: 10px;
|
||||||
|
|
||||||
|
.category-btn {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
padding: 15px 10px;
|
||||||
|
border: 2px solid #f0f0f0;
|
||||||
|
border-radius: 12px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
background: #fafafa;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: #5865f2;
|
||||||
|
background: #f8f9ff;
|
||||||
|
transform: translateY(-2px);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
border-color: #5865f2;
|
||||||
|
background: linear-gradient(135deg, #5865f2 0%, #7289da 100%);
|
||||||
|
color: white;
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 4px 12px rgba(88, 101, 242, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.category-icon {
|
||||||
|
font-size: 20px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.category-name {
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 功能开关
|
||||||
|
.function-switch {
|
||||||
|
margin-bottom: 25px;
|
||||||
|
|
||||||
|
.switch-label {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333;
|
||||||
|
|
||||||
|
.el-icon {
|
||||||
|
margin-right: 8px;
|
||||||
|
color: #5865f2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.switch-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 15px;
|
||||||
|
border: 1px solid #e0e0e0;
|
||||||
|
border-radius: 10px;
|
||||||
|
background: #f9f9f9;
|
||||||
|
|
||||||
|
.switch-info {
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
.switch-title {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.switch-desc {
|
||||||
|
font-size: 12px;
|
||||||
|
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: #333;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-group {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
|
||||||
|
.label {
|
||||||
|
margin-right: 15px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #333;
|
||||||
|
min-width: 80px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-info {
|
||||||
|
margin: 20px 0;
|
||||||
|
padding: 15px;
|
||||||
|
background: #f0f8ff;
|
||||||
|
border-radius: 8px;
|
||||||
|
border-left: 4px solid #5865f2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit-btn {
|
||||||
|
margin-top: 30px;
|
||||||
|
|
||||||
|
.el-button {
|
||||||
|
width: 100%;
|
||||||
|
height: 50px;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 右侧主要内容区域
|
||||||
|
.main-content {
|
||||||
|
flex: 1;
|
||||||
|
padding: 20px;
|
||||||
|
background: var(--chat-bg);
|
||||||
|
color: var(--text-theme-color);
|
||||||
|
|
||||||
|
.works-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
|
||||||
|
.h-title {
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--text-theme-color);
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.task-list {
|
||||||
|
.list-box {
|
||||||
|
.task-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 20px;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
background: var(--card-bg);
|
||||||
|
border-radius: 12px;
|
||||||
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
|
||||||
|
.task-left {
|
||||||
|
margin-right: 20px;
|
||||||
|
|
||||||
|
.task-preview {
|
||||||
|
width: 120px;
|
||||||
|
height: 90px;
|
||||||
|
border-radius: 8px;
|
||||||
|
overflow: hidden;
|
||||||
|
background: #f0f0f0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
.preview-image, .preview-video {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-placeholder {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
color: #999;
|
||||||
|
font-size: 12px;
|
||||||
|
|
||||||
|
.el-icon {
|
||||||
|
font-size: 24px;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.task-center {
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
.task-info {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.task-prompt {
|
||||||
|
font-size: 14px;
|
||||||
|
color: var(--text-theme-color);
|
||||||
|
margin-bottom: 8px;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.task-meta {
|
||||||
|
display: flex;
|
||||||
|
gap: 15px;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.task-right {
|
||||||
|
.task-actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination {
|
||||||
|
margin-top: 30px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 响应式设计
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.page-jimeng {
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.params-panel {
|
||||||
|
min-width: 100%;
|
||||||
|
max-width: 100%;
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-content {
|
||||||
|
padding: 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
.member {
|
.member {
|
||||||
// background-color: #282c34;
|
|
||||||
height 100%
|
height 100%
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
@@ -13,36 +12,79 @@
|
|||||||
|
|
||||||
.inner {
|
.inner {
|
||||||
color var(--text-theme-color)
|
color var(--text-theme-color)
|
||||||
padding 15px 0 15px 15px;
|
padding 15px 0 15px 15px
|
||||||
overflow-x hidden
|
overflow-x hidden
|
||||||
overflow-y visible
|
overflow-y visible
|
||||||
display flex
|
display flex
|
||||||
flex-flow row
|
flex-flow row
|
||||||
|
|
||||||
.user-profile {
|
.profile-card {
|
||||||
padding 10px 20px 20px 20px
|
max-width 300px
|
||||||
width 300px
|
border-radius 18px
|
||||||
background-color var(--chat-bg)
|
box-shadow 0 4px 8px rgba(0,0,0,0.08)
|
||||||
color var(--text-theme-color)
|
padding 24px 16px
|
||||||
border-radius 10px
|
background var(--panel-bg)
|
||||||
//height 100vh
|
position relative
|
||||||
|
z-index 1
|
||||||
.el-form-item__label {
|
margin-bottom 24px
|
||||||
color var(--text-theme-color)
|
}
|
||||||
justify-content start
|
.profile-title {
|
||||||
|
font-size 18px
|
||||||
|
font-weight bold
|
||||||
|
margin-bottom 18px
|
||||||
|
color #2d8cf0
|
||||||
|
letter-spacing 2px
|
||||||
|
text-align center
|
||||||
|
}
|
||||||
|
.profile-btn {
|
||||||
|
width 100%
|
||||||
|
margin-bottom 12px
|
||||||
|
font-size 16px
|
||||||
|
font-weight 500
|
||||||
|
display flex
|
||||||
|
align-items center
|
||||||
|
justify-content center
|
||||||
|
border none
|
||||||
|
border-radius 8px
|
||||||
|
background linear-gradient(90deg, #6dd5ed 0%, #2193b0 100%)
|
||||||
|
color #fff
|
||||||
|
transition all 0.3s
|
||||||
|
i {
|
||||||
|
margin-right 8px
|
||||||
|
font-size 20px
|
||||||
}
|
}
|
||||||
|
&:hover {
|
||||||
.user-opt {
|
box-shadow 0 2px 12px #2193b0aa
|
||||||
.el-col {
|
transform translateY(-2px) scale(1.03)
|
||||||
padding 10px
|
background linear-gradient(90deg, #2193b0 0%, #6dd5ed 100%)
|
||||||
|
|
||||||
.el-button {
|
|
||||||
width 100%
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.profile-btn.email {
|
||||||
|
background linear-gradient(90deg, #f7971e 0%, #ffd200 100%)
|
||||||
|
}
|
||||||
|
.profile-btn.mobile {
|
||||||
|
background linear-gradient(90deg, #43cea2 0%, #185a9d 100%)
|
||||||
|
}
|
||||||
|
.profile-btn.third {
|
||||||
|
background linear-gradient(90deg, #ff512f 0%, #dd2476 100%)
|
||||||
|
}
|
||||||
|
.profile-btn.password {
|
||||||
|
background linear-gradient(90deg, #1d4350 0%, #a43931 100%)
|
||||||
|
}
|
||||||
|
.profile-btn.redeem {
|
||||||
|
background linear-gradient(90deg, #00c6ff 0%, #0072ff 100%)
|
||||||
|
}
|
||||||
|
.profile-bg {
|
||||||
|
position absolute
|
||||||
|
left 0
|
||||||
|
top 0
|
||||||
|
width 100%
|
||||||
|
height 100%
|
||||||
|
z-index 0
|
||||||
|
background url('data:image/svg+xml;utf8,<svg width="100%25" height="100%25" viewBox="0 0 400 200" fill="none" xmlns="http://www.w3.org/2000/svg"><circle cx="100" cy="100" r="80" fill="%23e0eaff"/><circle cx="300" cy="60" r="40" fill="%23f0f7ff"/><circle cx="320" cy="180" r="30" fill="%23e0eaff"/></svg>') no-repeat center/cover
|
||||||
|
opacity 0.08
|
||||||
|
pointer-events none
|
||||||
|
}
|
||||||
|
|
||||||
.product-box {
|
.product-box {
|
||||||
padding 0 20px
|
padding 0 20px
|
||||||
|
|||||||
@@ -96,4 +96,7 @@
|
|||||||
|
|
||||||
// el-dialog 阴影
|
// el-dialog 阴影
|
||||||
--el-box-shadow: 0 0 15px rgba(107, 80, 225, 0.8);
|
--el-box-shadow: 0 0 15px rgba(107, 80, 225, 0.8);
|
||||||
|
|
||||||
|
// 面板背景
|
||||||
|
--panel-bg: linear-gradient(135deg, #252d58 0%, #1f243f 100%);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,6 +57,8 @@
|
|||||||
// 引用快样式
|
// 引用快样式
|
||||||
--quote-bg-color: #e0dfff;
|
--quote-bg-color: #e0dfff;
|
||||||
--quote-text-color: #333;
|
--quote-text-color: #333;
|
||||||
|
// 面板背景
|
||||||
|
--panel-bg: linear-gradient(135deg, #f5eafe 0%, #e9e6fc 100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,14 +2,8 @@
|
|||||||
<div class="page-jimeng">
|
<div class="page-jimeng">
|
||||||
<!-- 左侧参数设置面板 -->
|
<!-- 左侧参数设置面板 -->
|
||||||
<div class="params-panel">
|
<div class="params-panel">
|
||||||
<h2>即梦AI</h2>
|
|
||||||
|
|
||||||
<!-- 功能分类按钮组 -->
|
<!-- 功能分类按钮组 -->
|
||||||
<div class="category-buttons">
|
<div class="category-buttons">
|
||||||
<div class="category-label">
|
|
||||||
<el-icon><Star /></el-icon>
|
|
||||||
功能分类
|
|
||||||
</div>
|
|
||||||
<div class="category-grid">
|
<div class="category-grid">
|
||||||
<div
|
<div
|
||||||
v-for="category in store.categories"
|
v-for="category in store.categories"
|
||||||
@@ -26,7 +20,12 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 功能开关 -->
|
<!-- 功能开关 -->
|
||||||
<div class="function-switch" v-if="store.activeCategory === 'image_generation' || store.activeCategory === 'video_generation'">
|
<div
|
||||||
|
class="function-switch"
|
||||||
|
v-if="
|
||||||
|
store.activeCategory === 'image_generation' || store.activeCategory === 'video_generation'
|
||||||
|
"
|
||||||
|
>
|
||||||
<div class="switch-label">
|
<div class="switch-label">
|
||||||
<el-icon><Switch /></el-icon>
|
<el-icon><Switch /></el-icon>
|
||||||
生成模式
|
生成模式
|
||||||
@@ -34,17 +33,21 @@
|
|||||||
<div class="switch-container">
|
<div class="switch-container">
|
||||||
<div class="switch-info">
|
<div class="switch-info">
|
||||||
<div class="switch-title">
|
<div class="switch-title">
|
||||||
{{ store.useImageInput ? (store.activeCategory === 'image_generation' ? '图生图' : '图生视频') : (store.activeCategory === 'image_generation' ? '文生图' : '文生视频') }}
|
{{
|
||||||
|
store.useImageInput
|
||||||
|
? store.activeCategory === 'image_generation'
|
||||||
|
? '图生图'
|
||||||
|
: '图生视频'
|
||||||
|
: store.activeCategory === 'image_generation'
|
||||||
|
? '文生图'
|
||||||
|
: '文生视频'
|
||||||
|
}}
|
||||||
</div>
|
</div>
|
||||||
<div class="switch-desc">
|
<div class="switch-desc">
|
||||||
{{ store.useImageInput ? '使用图片作为输入' : '使用文字作为输入' }}
|
{{ store.useImageInput ? '使用图片作为输入' : '使用文字作为输入' }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<el-switch
|
<el-switch v-model="store.useImageInput" @change="store.switchInputMode" size="large" />
|
||||||
v-model="store.useImageInput"
|
|
||||||
@change="store.switchInputMode"
|
|
||||||
size="large"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -88,7 +91,12 @@
|
|||||||
|
|
||||||
<div class="item-group">
|
<div class="item-group">
|
||||||
<span class="label">种子值:</span>
|
<span class="label">种子值:</span>
|
||||||
<el-input-number v-model="store.textToImageParams.seed" :min="-1" :max="999999" size="small" />
|
<el-input-number
|
||||||
|
v-model="store.textToImageParams.seed"
|
||||||
|
:min="-1"
|
||||||
|
:max="999999"
|
||||||
|
size="small"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="item-group flex justify-between">
|
<div class="item-group flex justify-between">
|
||||||
@@ -144,7 +152,12 @@
|
|||||||
|
|
||||||
<div class="item-group">
|
<div class="item-group">
|
||||||
<span class="label">种子值:</span>
|
<span class="label">种子值:</span>
|
||||||
<el-input-number v-model="store.imageToImageParams.seed" :min="-1" :max="999999" size="small" />
|
<el-input-number
|
||||||
|
v-model="store.imageToImageParams.seed"
|
||||||
|
:min="-1"
|
||||||
|
:max="999999"
|
||||||
|
size="small"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -178,7 +191,12 @@
|
|||||||
|
|
||||||
<div class="item-group">
|
<div class="item-group">
|
||||||
<span class="label">种子值:</span>
|
<span class="label">种子值:</span>
|
||||||
<el-input-number v-model="store.imageEditParams.seed" :min="-1" :max="999999" size="small" />
|
<el-input-number
|
||||||
|
v-model="store.imageEditParams.seed"
|
||||||
|
:min="-1"
|
||||||
|
:max="999999"
|
||||||
|
size="small"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -244,7 +262,12 @@
|
|||||||
|
|
||||||
<div class="item-group">
|
<div class="item-group">
|
||||||
<span class="label">种子值:</span>
|
<span class="label">种子值:</span>
|
||||||
<el-input-number v-model="store.textToVideoParams.seed" :min="-1" :max="999999" size="small" />
|
<el-input-number
|
||||||
|
v-model="store.textToVideoParams.seed"
|
||||||
|
:min="-1"
|
||||||
|
:max="999999"
|
||||||
|
size="small"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -284,7 +307,12 @@
|
|||||||
|
|
||||||
<div class="item-group">
|
<div class="item-group">
|
||||||
<span class="label">种子值:</span>
|
<span class="label">种子值:</span>
|
||||||
<el-input-number v-model="store.imageToVideoParams.seed" :min="-1" :max="999999" size="small" />
|
<el-input-number
|
||||||
|
v-model="store.imageToVideoParams.seed"
|
||||||
|
:min="-1"
|
||||||
|
:max="999999"
|
||||||
|
size="small"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -406,11 +434,7 @@
|
|||||||
>
|
>
|
||||||
播放
|
播放
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button
|
<el-button type="danger" size="small" @click="store.removeJob(item)">
|
||||||
type="danger"
|
|
||||||
size="small"
|
|
||||||
@click="store.removeJob(item)"
|
|
||||||
>
|
|
||||||
删除
|
删除
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
@@ -418,11 +442,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-empty
|
<el-empty v-else :image="store.nodata" description="暂无任务,快去创建吧!" />
|
||||||
v-else
|
|
||||||
:image="store.nodata"
|
|
||||||
description="暂无任务,快去创建吧!"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div class="pagination" v-if="store.total > store.pageSize">
|
<div class="pagination" v-if="store.total > store.pageSize">
|
||||||
<el-pagination
|
<el-pagination
|
||||||
@@ -438,17 +458,8 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 视频预览对话框 -->
|
<!-- 视频预览对话框 -->
|
||||||
<el-dialog
|
<el-dialog v-model="store.showDialog" title="视频预览" width="70%" center>
|
||||||
v-model="store.showDialog"
|
<video :src="store.currentVideoUrl" controls style="width: 100%; max-height: 60vh">
|
||||||
title="视频预览"
|
|
||||||
width="70%"
|
|
||||||
center
|
|
||||||
>
|
|
||||||
<video
|
|
||||||
:src="store.currentVideoUrl"
|
|
||||||
controls
|
|
||||||
style="width: 100%; max-height: 60vh;"
|
|
||||||
>
|
|
||||||
您的浏览器不支持视频播放
|
您的浏览器不支持视频播放
|
||||||
</video>
|
</video>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
@@ -456,21 +467,22 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { onMounted, onUnmounted } from 'vue'
|
import '@/assets/css/jimeng.styl'
|
||||||
|
import ImageUpload from '@/components/ImageUpload.vue'
|
||||||
import { useJimengStore } from '@/store/jimeng'
|
import { useJimengStore } from '@/store/jimeng'
|
||||||
import { dateFormat } from '@/utils/libs'
|
import { dateFormat } from '@/utils/libs'
|
||||||
import ImageUpload from '@/components/ImageUpload.vue'
|
import { InfoFilled, Picture, Switch } from '@element-plus/icons-vue'
|
||||||
import { InfoFilled, Star, Switch, Picture } from '@element-plus/icons-vue'
|
import { onMounted, onUnmounted } from 'vue'
|
||||||
|
|
||||||
const store = useJimengStore()
|
const store = useJimengStore()
|
||||||
|
|
||||||
// 获取分类图标
|
// 获取分类图标
|
||||||
const getCategoryIcon = (category) => {
|
const getCategoryIcon = (category) => {
|
||||||
const iconMap = {
|
const iconMap = {
|
||||||
'image_generation': 'iconfont icon-image',
|
image_generation: 'iconfont icon-image',
|
||||||
'image_editing': 'iconfont icon-edit',
|
image_editing: 'iconfont icon-edit',
|
||||||
'image_effects': 'iconfont icon-magic',
|
image_effects: 'iconfont icon-chuangzuo',
|
||||||
'video_generation': 'iconfont icon-video'
|
video_generation: 'iconfont icon-video',
|
||||||
}
|
}
|
||||||
return iconMap[category] || 'iconfont icon-image'
|
return iconMap[category] || 'iconfont icon-image'
|
||||||
}
|
}
|
||||||
@@ -483,317 +495,3 @@ onUnmounted(() => {
|
|||||||
store.cleanup()
|
store.cleanup()
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="stylus" scoped>
|
|
||||||
.page-jimeng {
|
|
||||||
display: flex;
|
|
||||||
min-height: 100vh;
|
|
||||||
background: var(--chat-bg);
|
|
||||||
|
|
||||||
// 左侧参数面板
|
|
||||||
.params-panel {
|
|
||||||
min-width: 380px;
|
|
||||||
max-width: 380px;
|
|
||||||
margin: 10px;
|
|
||||||
padding: 20px;
|
|
||||||
border-radius: 12px;
|
|
||||||
background: #ffffff;
|
|
||||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
|
|
||||||
color: #333;
|
|
||||||
font-size: 14px;
|
|
||||||
overflow: auto;
|
|
||||||
|
|
||||||
h2 {
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 20px;
|
|
||||||
text-align: center;
|
|
||||||
color: #333;
|
|
||||||
margin-bottom: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 功能分类按钮组
|
|
||||||
.category-buttons {
|
|
||||||
margin-bottom: 25px;
|
|
||||||
|
|
||||||
.category-label {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
margin-bottom: 15px;
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: #333;
|
|
||||||
|
|
||||||
.el-icon {
|
|
||||||
margin-right: 8px;
|
|
||||||
color: #5865f2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.category-grid {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(2, 1fr);
|
|
||||||
gap: 10px;
|
|
||||||
|
|
||||||
.category-btn {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
padding: 15px 10px;
|
|
||||||
border: 2px solid #f0f0f0;
|
|
||||||
border-radius: 12px;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
background: #fafafa;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
border-color: #5865f2;
|
|
||||||
background: #f8f9ff;
|
|
||||||
transform: translateY(-2px);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.active {
|
|
||||||
border-color: #5865f2;
|
|
||||||
background: linear-gradient(135deg, #5865f2 0%, #7289da 100%);
|
|
||||||
color: white;
|
|
||||||
transform: translateY(-2px);
|
|
||||||
box-shadow: 0 4px 12px rgba(88, 101, 242, 0.3);
|
|
||||||
}
|
|
||||||
|
|
||||||
.category-icon {
|
|
||||||
font-size: 20px;
|
|
||||||
margin-bottom: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.category-name {
|
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 功能开关
|
|
||||||
.function-switch {
|
|
||||||
margin-bottom: 25px;
|
|
||||||
|
|
||||||
.switch-label {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
margin-bottom: 15px;
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: #333;
|
|
||||||
|
|
||||||
.el-icon {
|
|
||||||
margin-right: 8px;
|
|
||||||
color: #5865f2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.switch-container {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
padding: 15px;
|
|
||||||
border: 1px solid #e0e0e0;
|
|
||||||
border-radius: 10px;
|
|
||||||
background: #f9f9f9;
|
|
||||||
|
|
||||||
.switch-info {
|
|
||||||
flex: 1;
|
|
||||||
|
|
||||||
.switch-title {
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: #333;
|
|
||||||
margin-bottom: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.switch-desc {
|
|
||||||
font-size: 12px;
|
|
||||||
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: #333;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.item-group {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
margin-bottom: 15px;
|
|
||||||
|
|
||||||
.label {
|
|
||||||
margin-right: 15px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: #333;
|
|
||||||
min-width: 80px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-info {
|
|
||||||
margin: 20px 0;
|
|
||||||
padding: 15px;
|
|
||||||
background: #f0f8ff;
|
|
||||||
border-radius: 8px;
|
|
||||||
border-left: 4px solid #5865f2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.submit-btn {
|
|
||||||
margin-top: 30px;
|
|
||||||
|
|
||||||
.el-button {
|
|
||||||
width: 100%;
|
|
||||||
height: 50px;
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 右侧主要内容区域
|
|
||||||
.main-content {
|
|
||||||
flex: 1;
|
|
||||||
padding: 20px;
|
|
||||||
background: var(--chat-bg);
|
|
||||||
color: var(--text-theme-color);
|
|
||||||
|
|
||||||
.works-header {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
|
|
||||||
.h-title {
|
|
||||||
font-size: 24px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: var(--text-theme-color);
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.task-list {
|
|
||||||
.list-box {
|
|
||||||
.task-item {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding: 20px;
|
|
||||||
margin-bottom: 15px;
|
|
||||||
background: var(--card-bg);
|
|
||||||
border-radius: 12px;
|
|
||||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
||||||
|
|
||||||
.task-left {
|
|
||||||
margin-right: 20px;
|
|
||||||
|
|
||||||
.task-preview {
|
|
||||||
width: 120px;
|
|
||||||
height: 90px;
|
|
||||||
border-radius: 8px;
|
|
||||||
overflow: hidden;
|
|
||||||
background: #f0f0f0;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
.preview-image, .preview-video {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
object-fit: cover;
|
|
||||||
}
|
|
||||||
|
|
||||||
.preview-placeholder {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
color: #999;
|
|
||||||
font-size: 12px;
|
|
||||||
|
|
||||||
.el-icon {
|
|
||||||
font-size: 24px;
|
|
||||||
margin-bottom: 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.task-center {
|
|
||||||
flex: 1;
|
|
||||||
|
|
||||||
.task-info {
|
|
||||||
display: flex;
|
|
||||||
gap: 8px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.task-prompt {
|
|
||||||
font-size: 14px;
|
|
||||||
color: var(--text-theme-color);
|
|
||||||
margin-bottom: 8px;
|
|
||||||
line-height: 1.4;
|
|
||||||
}
|
|
||||||
|
|
||||||
.task-meta {
|
|
||||||
display: flex;
|
|
||||||
gap: 15px;
|
|
||||||
font-size: 12px;
|
|
||||||
color: #999;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.task-right {
|
|
||||||
.task-actions {
|
|
||||||
display: flex;
|
|
||||||
gap: 8px;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.pagination {
|
|
||||||
margin-top: 30px;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 响应式设计
|
|
||||||
@media (max-width: 768px) {
|
|
||||||
.page-jimeng {
|
|
||||||
flex-direction: column;
|
|
||||||
|
|
||||||
.params-panel {
|
|
||||||
min-width: 100%;
|
|
||||||
max-width: 100%;
|
|
||||||
margin: 10px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.main-content {
|
|
||||||
padding: 15px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -7,27 +7,37 @@
|
|||||||
:element-loading-text="loadingText"
|
:element-loading-text="loadingText"
|
||||||
>
|
>
|
||||||
<div class="inner">
|
<div class="inner">
|
||||||
<div class="user-profile">
|
<el-card class="profile-card">
|
||||||
<user-profile :key="profileKey" />
|
<el-row class="user-opt" :gutter="16">
|
||||||
|
<el-col :span="24">
|
||||||
<el-row class="user-opt" :gutter="20">
|
<el-button class="profile-btn email" @click="showBindEmailDialog = true">
|
||||||
<el-col :span="12">
|
<i class="iconfont icon-email"></i> 绑定邮箱
|
||||||
<el-button type="primary" @click="showBindEmailDialog = true">绑定邮箱</el-button>
|
</el-button>
|
||||||
</el-col>
|
|
||||||
<el-col :span="12">
|
|
||||||
<el-button type="primary" @click="showBindMobileDialog = true">绑定手机</el-button>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="12">
|
|
||||||
<el-button type="primary" @click="showThirdLoginDialog = true">第三方登录</el-button>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="12">
|
|
||||||
<el-button type="primary" @click="showPasswordDialog = true">修改密码</el-button>
|
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="24">
|
<el-col :span="24">
|
||||||
<el-button type="primary" @click="showRedeemVerifyDialog = true">卡密兑换 </el-button>
|
<el-button class="profile-btn mobile" @click="showBindMobileDialog = true">
|
||||||
|
<i class="iconfont icon-mobile"></i> 绑定手机
|
||||||
|
</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-button class="profile-btn third" @click="showThirdLoginDialog = true">
|
||||||
|
<i class="iconfont icon-login"></i> 第三方登录
|
||||||
|
</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-button class="profile-btn password" @click="showPasswordDialog = true">
|
||||||
|
<i class="iconfont icon-password"></i> 修改密码
|
||||||
|
</el-button>
|
||||||
|
</el-col>
|
||||||
|
<el-divider />
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-button class="profile-btn redeem" @click="showRedeemVerifyDialog = true">
|
||||||
|
<i class="iconfont icon-redeem"></i> 卡密兑换
|
||||||
|
</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
</div>
|
</el-card>
|
||||||
|
<div class="profile-bg"></div>
|
||||||
|
|
||||||
<div class="product-box">
|
<div class="product-box">
|
||||||
<div class="info" v-if="orderPayInfoText !== ''">
|
<div class="info" v-if="orderPayInfoText !== ''">
|
||||||
@@ -158,7 +168,6 @@ import PasswordDialog from '@/components/PasswordDialog.vue'
|
|||||||
import RedeemVerify from '@/components/RedeemVerify.vue'
|
import RedeemVerify from '@/components/RedeemVerify.vue'
|
||||||
import ThirdLogin from '@/components/ThirdLogin.vue'
|
import ThirdLogin from '@/components/ThirdLogin.vue'
|
||||||
import UserOrder from '@/components/UserOrder.vue'
|
import UserOrder from '@/components/UserOrder.vue'
|
||||||
import UserProfile from '@/components/UserProfile.vue'
|
|
||||||
import { checkSession, getSystemInfo } from '@/store/cache'
|
import { checkSession, getSystemInfo } from '@/store/cache'
|
||||||
import { useSharedStore } from '@/store/sharedata'
|
import { useSharedStore } from '@/store/sharedata'
|
||||||
import { httpGet, httpPost } from '@/utils/http'
|
import { httpGet, httpPost } from '@/utils/http'
|
||||||
@@ -185,7 +194,6 @@ const orderPayInfoText = ref('')
|
|||||||
const payWays = ref([])
|
const payWays = ref([])
|
||||||
const vipInfoText = ref('')
|
const vipInfoText = ref('')
|
||||||
const store = useSharedStore()
|
const store = useSharedStore()
|
||||||
const profileKey = ref(0)
|
|
||||||
const userOrderKey = ref(0)
|
const userOrderKey = ref(0)
|
||||||
const showDialog = ref(false)
|
const showDialog = ref(false)
|
||||||
const qrImg = ref('')
|
const qrImg = ref('')
|
||||||
@@ -276,17 +284,13 @@ const pay = (product, payWay) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const redeemCallback = (success) => {
|
const redeemCallback = () => {
|
||||||
showRedeemVerifyDialog.value = false
|
showRedeemVerifyDialog.value = false
|
||||||
if (success) {
|
|
||||||
profileKey.value += 1
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const payCallback = (success) => {
|
const payCallback = (success) => {
|
||||||
showDialog.value = false
|
showDialog.value = false
|
||||||
if (success) {
|
if (success) {
|
||||||
profileKey.value += 1
|
|
||||||
userOrderKey.value += 1
|
userOrderKey.value += 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user