mirror of
https://github.com/yangjian102621/geekai.git
synced 2025-09-18 01:06:39 +08:00
refactor: use waterflow component in mj, sd and dall image drawing page
This commit is contained in:
parent
5fb9f84182
commit
43b6665370
@ -8,6 +8,8 @@
|
|||||||
* Bug修复:修复管理后台角色删除失败的Bug
|
* Bug修复:修复管理后台角色删除失败的Bug
|
||||||
* Bug修复:兼容最新版秋叶SD懒人包的 SD API,新增 scheduler 参数
|
* Bug修复:兼容最新版秋叶SD懒人包的 SD API,新增 scheduler 参数
|
||||||
* 功能优化:支持在管理后台配置 AI 绘图相关配置,包括 SD, MJ-PLUS, MJ-PROXY
|
* 功能优化:支持在管理后台配置 AI 绘图相关配置,包括 SD, MJ-PLUS, MJ-PROXY
|
||||||
|
* Bug修复:修复注册用户提示注册人数达到上限的 Bug
|
||||||
|
* 功能优化:将MJ,SD,Dall绘画页面的任务列表全改成瀑布流组件
|
||||||
|
|
||||||
## v4.0.5
|
## v4.0.5
|
||||||
|
|
||||||
|
@ -8,6 +8,8 @@ package dalle
|
|||||||
// * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
// * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
"geekai/core/types"
|
"geekai/core/types"
|
||||||
logger2 "geekai/logger"
|
logger2 "geekai/logger"
|
||||||
"geekai/service"
|
"geekai/service"
|
||||||
@ -16,8 +18,6 @@ import (
|
|||||||
"geekai/store"
|
"geekai/store"
|
||||||
"geekai/store/model"
|
"geekai/store/model"
|
||||||
"geekai/utils"
|
"geekai/utils"
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"github.com/go-redis/redis/v8"
|
"github.com/go-redis/redis/v8"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -261,7 +261,7 @@ func (s *Service) downloadImage(jobId uint, userId int, orgURL string) (string,
|
|||||||
if res.Error != nil {
|
if res.Error != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
s.notifyQueue.RPush(sd.NotifyMessage{UserId: userId, JobId: int(jobId), Message: sd.Failed})
|
s.notifyQueue.RPush(sd.NotifyMessage{UserId: userId, JobId: int(jobId), Message: sd.Finished})
|
||||||
return imgURL, nil
|
return imgURL, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -294,7 +294,7 @@ func (s *Service) CheckTaskStatus() {
|
|||||||
Balance: user.Power + job.Power,
|
Balance: user.Power + job.Power,
|
||||||
Mark: types.PowerAdd,
|
Mark: types.PowerAdd,
|
||||||
Model: "dall-e-3",
|
Model: "dall-e-3",
|
||||||
Remark: fmt.Sprintf("任务失败,退回算力。任务ID:%d", job.Id),
|
Remark: fmt.Sprintf("任务失败,退回算力。任务ID:%d", job.Id),
|
||||||
CreatedAt: time.Now(),
|
CreatedAt: time.Now(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ type ServicePool struct {
|
|||||||
db *gorm.DB
|
db *gorm.DB
|
||||||
uploaderManager *oss.UploaderManager
|
uploaderManager *oss.UploaderManager
|
||||||
Clients *types.LMap[uint, *types.WsClient] // UserId => Client
|
Clients *types.LMap[uint, *types.WsClient] // UserId => Client
|
||||||
licenseService *service.LicenseService
|
licenseService *service.LicenseService
|
||||||
}
|
}
|
||||||
|
|
||||||
var logger = logger2.GetLogger()
|
var logger = logger2.GetLogger()
|
||||||
@ -56,6 +56,7 @@ func (p *ServicePool) InitServices(plusConfigs []types.MjPlusConfig, proxyConfig
|
|||||||
for _, s := range p.services {
|
for _, s := range p.services {
|
||||||
s.Stop()
|
s.Stop()
|
||||||
}
|
}
|
||||||
|
p.services = make([]*Service, 0)
|
||||||
|
|
||||||
for k, config := range plusConfigs {
|
for k, config := range plusConfigs {
|
||||||
if config.Enabled == false {
|
if config.Enabled == false {
|
||||||
|
@ -28,7 +28,7 @@ type Service struct {
|
|||||||
taskQueue *store.RedisQueue
|
taskQueue *store.RedisQueue
|
||||||
notifyQueue *store.RedisQueue
|
notifyQueue *store.RedisQueue
|
||||||
db *gorm.DB
|
db *gorm.DB
|
||||||
running bool
|
running bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewService(name string, taskQueue *store.RedisQueue, notifyQueue *store.RedisQueue, db *gorm.DB, cli Client) *Service {
|
func NewService(name string, taskQueue *store.RedisQueue, notifyQueue *store.RedisQueue, db *gorm.DB, cli Client) *Service {
|
||||||
@ -38,7 +38,7 @@ func NewService(name string, taskQueue *store.RedisQueue, notifyQueue *store.Red
|
|||||||
taskQueue: taskQueue,
|
taskQueue: taskQueue,
|
||||||
notifyQueue: notifyQueue,
|
notifyQueue: notifyQueue,
|
||||||
Client: cli,
|
Client: cli,
|
||||||
running: true,
|
running: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,7 +129,6 @@ func (s *Service) Run() {
|
|||||||
|
|
||||||
func (s *Service) Stop() {
|
func (s *Service) Stop() {
|
||||||
s.running = false
|
s.running = false
|
||||||
s.Client = nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type CBReq struct {
|
type CBReq struct {
|
||||||
|
@ -25,8 +25,8 @@ type ServicePool struct {
|
|||||||
notifyQueue *store.RedisQueue
|
notifyQueue *store.RedisQueue
|
||||||
db *gorm.DB
|
db *gorm.DB
|
||||||
Clients *types.LMap[uint, *types.WsClient] // UserId => Client
|
Clients *types.LMap[uint, *types.WsClient] // UserId => Client
|
||||||
uploader *oss.UploaderManager
|
uploader *oss.UploaderManager
|
||||||
levelDB *store.LevelDB
|
levelDB *store.LevelDB
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewServicePool(db *gorm.DB, redisCli *redis.Client, manager *oss.UploaderManager, levelDB *store.LevelDB) *ServicePool {
|
func NewServicePool(db *gorm.DB, redisCli *redis.Client, manager *oss.UploaderManager, levelDB *store.LevelDB) *ServicePool {
|
||||||
@ -40,8 +40,8 @@ func NewServicePool(db *gorm.DB, redisCli *redis.Client, manager *oss.UploaderMa
|
|||||||
services: services,
|
services: services,
|
||||||
db: db,
|
db: db,
|
||||||
Clients: types.NewLMap[uint, *types.WsClient](),
|
Clients: types.NewLMap[uint, *types.WsClient](),
|
||||||
uploader: manager,
|
uploader: manager,
|
||||||
levelDB: levelDB,
|
levelDB: levelDB,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,6 +50,7 @@ func (p *ServicePool) InitServices(configs []types.StableDiffusionConfig) {
|
|||||||
for _, s := range p.services {
|
for _, s := range p.services {
|
||||||
s.Stop()
|
s.Stop()
|
||||||
}
|
}
|
||||||
|
p.services = make([]*Service, 0)
|
||||||
|
|
||||||
for k, config := range configs {
|
for k, config := range configs {
|
||||||
if config.Enabled == false {
|
if config.Enabled == false {
|
||||||
|
@ -60,7 +60,7 @@ func (s *Service) Run() {
|
|||||||
logger.Errorf("taking task with error: %v", err)
|
logger.Errorf("taking task with error: %v", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
logger.Infof("%s handle a new Stable-Diffusion task: %+v", s.name, task)
|
|
||||||
// translate prompt
|
// translate prompt
|
||||||
if utils.HasChinese(task.Params.Prompt) {
|
if utils.HasChinese(task.Params.Prompt) {
|
||||||
content, err := utils.OpenAIRequest(s.db, fmt.Sprintf(service.RewritePromptTemplate, task.Params.Prompt))
|
content, err := utils.OpenAIRequest(s.db, fmt.Sprintf(service.RewritePromptTemplate, task.Params.Prompt))
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
"qs": "^6.11.1",
|
"qs": "^6.11.1",
|
||||||
"sortablejs": "^1.15.0",
|
"sortablejs": "^1.15.0",
|
||||||
"three": "^0.128.0",
|
"three": "^0.128.0",
|
||||||
"v3-waterfall": "^1.2.1",
|
"v3-waterfall": "^1.3.3",
|
||||||
"vant": "^4.5.0",
|
"vant": "^4.5.0",
|
||||||
"vue": "^3.2.13",
|
"vue": "^3.2.13",
|
||||||
"vue-router": "^4.0.15"
|
"vue-router": "^4.0.15"
|
||||||
|
BIN
web/public/images/img-placeholder.jpg
Normal file
BIN
web/public/images/img-placeholder.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.2 KiB |
@ -81,7 +81,281 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@import "task-list.styl"
|
.task-list-box {
|
||||||
|
width 100%
|
||||||
|
padding 10px
|
||||||
|
color #ffffff
|
||||||
|
overflow-x hidden
|
||||||
|
|
||||||
|
.task-list-inner {
|
||||||
|
.el-tabs {
|
||||||
|
--el-tabs-header-height: 55px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-tabs__item {
|
||||||
|
color: #fff;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-tabs .el-tabs__item.is-active {
|
||||||
|
color: #47FFF1;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-tabs .el-tabs__active-bar {
|
||||||
|
background-color: #47FFF1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-textarea {
|
||||||
|
--el-input-focus-border-color: #47FFF1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-textarea__inner {
|
||||||
|
background: transparent;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-input__wrapper {
|
||||||
|
background: transparent;
|
||||||
|
padding 5px
|
||||||
|
}
|
||||||
|
|
||||||
|
.text {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
color: #6b778c;
|
||||||
|
font-size: 15px
|
||||||
|
}
|
||||||
|
|
||||||
|
.param-line.pt {
|
||||||
|
padding-top 5px
|
||||||
|
padding-bottom 5px
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-item-inner {
|
||||||
|
display flex
|
||||||
|
align-items: center
|
||||||
|
|
||||||
|
.el-icon {
|
||||||
|
margin-left 10px
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-form-item__label {
|
||||||
|
color #ffffff
|
||||||
|
}
|
||||||
|
|
||||||
|
// 图片上传样式
|
||||||
|
|
||||||
|
.img-inline {
|
||||||
|
display flex
|
||||||
|
|
||||||
|
.img-uploader {
|
||||||
|
.el-upload {
|
||||||
|
border: 1px dashed var(--el-border-color);
|
||||||
|
border-radius: 6px;
|
||||||
|
cursor: pointer;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
width 120px;
|
||||||
|
transition: var(--el-transition-duration-fast);
|
||||||
|
margin-bottom: 20px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: var(--el-color-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-icon.uploader-icon {
|
||||||
|
font-size: 28px
|
||||||
|
color: #8c939d
|
||||||
|
width 100%
|
||||||
|
height: 120px
|
||||||
|
text-align: center
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.img-list-box {
|
||||||
|
display flex
|
||||||
|
|
||||||
|
.img-item {
|
||||||
|
width 120px
|
||||||
|
position relative
|
||||||
|
margin-right 10px
|
||||||
|
|
||||||
|
.el-image {
|
||||||
|
width 120px
|
||||||
|
height 120px
|
||||||
|
border-radius 5px
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-button {
|
||||||
|
position absolute
|
||||||
|
right 5px
|
||||||
|
top 5px
|
||||||
|
width 20px
|
||||||
|
height 20px
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-row.text-info {
|
||||||
|
width 100%
|
||||||
|
padding 10px 0
|
||||||
|
|
||||||
|
.el-tag {
|
||||||
|
margin-right 10px
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提交按钮
|
||||||
|
|
||||||
|
.submit-btn {
|
||||||
|
display flex
|
||||||
|
margin: 20px 0
|
||||||
|
|
||||||
|
.el-button {
|
||||||
|
width 200px
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 任务列表
|
||||||
|
|
||||||
|
.job-list-box {
|
||||||
|
|
||||||
|
@import "running-job-list.styl"
|
||||||
|
|
||||||
|
.finish-job-list {
|
||||||
|
#waterfall {
|
||||||
|
display flex
|
||||||
|
justify-content center
|
||||||
|
padding-top 20px
|
||||||
|
flex-flow column
|
||||||
|
|
||||||
|
|
||||||
|
.job-item {
|
||||||
|
width 100%
|
||||||
|
height 100%
|
||||||
|
border 1px solid #666666
|
||||||
|
padding 6px
|
||||||
|
overflow hidden
|
||||||
|
border-radius 6px
|
||||||
|
transition: all 0.3s ease; /* 添加过渡效果 */
|
||||||
|
position relative
|
||||||
|
|
||||||
|
.opt {
|
||||||
|
.opt-line {
|
||||||
|
margin 6px 0
|
||||||
|
|
||||||
|
ul {
|
||||||
|
display flex
|
||||||
|
flex-flow row
|
||||||
|
|
||||||
|
li {
|
||||||
|
margin-right 6px
|
||||||
|
|
||||||
|
a {
|
||||||
|
padding 3px 0
|
||||||
|
width 40px
|
||||||
|
text-align center
|
||||||
|
border-radius 5px
|
||||||
|
display block
|
||||||
|
cursor pointer
|
||||||
|
background-color #4E5058
|
||||||
|
color #ffffff
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color #6D6F78
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.show-prompt {
|
||||||
|
font-size 20px
|
||||||
|
cursor pointer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.remove {
|
||||||
|
display none
|
||||||
|
position absolute
|
||||||
|
right 10px
|
||||||
|
top 10px
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
.remove {
|
||||||
|
display block
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.animate {
|
||||||
|
&:hover {
|
||||||
|
box-shadow: 0 0 10px rgba(71, 255, 241, 0.6); /* 添加阴影效果 */
|
||||||
|
transform: translateY(-10px); /* 向上移动10像素 */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.el-image {
|
||||||
|
width 100%
|
||||||
|
height 100%
|
||||||
|
overflow visible
|
||||||
|
|
||||||
|
.el-image-viewer__wrapper {
|
||||||
|
img {
|
||||||
|
width auto
|
||||||
|
height auto
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-slot {
|
||||||
|
display flex
|
||||||
|
flex-flow column
|
||||||
|
justify-content center
|
||||||
|
align-items center
|
||||||
|
min-height 200px
|
||||||
|
color #ffffff
|
||||||
|
|
||||||
|
.iconfont {
|
||||||
|
font-size 50px
|
||||||
|
margin-bottom 10px
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-image.upscale {
|
||||||
|
img {
|
||||||
|
height 310px
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-slot {
|
||||||
|
height 310px
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-image-viewer__wrapper {
|
||||||
|
img {
|
||||||
|
width auto
|
||||||
|
height auto
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-more-data {
|
||||||
|
text-align center
|
||||||
|
padding 30px
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -233,7 +233,280 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@import "task-list.styl"
|
.task-list-box {
|
||||||
|
width 100%
|
||||||
|
padding 10px
|
||||||
|
color #ffffff
|
||||||
|
overflow-x hidden
|
||||||
|
|
||||||
|
.task-list-inner {
|
||||||
|
.el-tabs {
|
||||||
|
--el-tabs-header-height: 55px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-tabs__item {
|
||||||
|
color: #fff;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-tabs .el-tabs__item.is-active {
|
||||||
|
color: #47FFF1;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-tabs .el-tabs__active-bar {
|
||||||
|
background-color: #47FFF1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-textarea {
|
||||||
|
--el-input-focus-border-color: #47FFF1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-textarea__inner {
|
||||||
|
background: transparent;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-input__wrapper {
|
||||||
|
background: transparent;
|
||||||
|
padding 5px
|
||||||
|
}
|
||||||
|
|
||||||
|
.text {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
color: #6b778c;
|
||||||
|
font-size: 15px
|
||||||
|
}
|
||||||
|
|
||||||
|
.param-line.pt {
|
||||||
|
padding-top 5px
|
||||||
|
padding-bottom 5px
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-item-inner {
|
||||||
|
display flex
|
||||||
|
align-items: center
|
||||||
|
|
||||||
|
.el-icon {
|
||||||
|
margin-left 10px
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-form-item__label {
|
||||||
|
color #ffffff
|
||||||
|
}
|
||||||
|
|
||||||
|
// 图片上传样式
|
||||||
|
|
||||||
|
.img-inline {
|
||||||
|
display flex
|
||||||
|
|
||||||
|
.img-uploader {
|
||||||
|
.el-upload {
|
||||||
|
border: 1px dashed var(--el-border-color);
|
||||||
|
border-radius: 6px;
|
||||||
|
cursor: pointer;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
width 120px;
|
||||||
|
transition: var(--el-transition-duration-fast);
|
||||||
|
margin-bottom: 20px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: var(--el-color-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-icon.uploader-icon {
|
||||||
|
font-size: 28px
|
||||||
|
color: #8c939d
|
||||||
|
width 100%
|
||||||
|
height: 120px
|
||||||
|
text-align: center
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.img-list-box {
|
||||||
|
display flex
|
||||||
|
|
||||||
|
.img-item {
|
||||||
|
width 120px
|
||||||
|
position relative
|
||||||
|
margin-right 10px
|
||||||
|
|
||||||
|
.el-image {
|
||||||
|
width 120px
|
||||||
|
height 120px
|
||||||
|
border-radius 5px
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-button {
|
||||||
|
position absolute
|
||||||
|
right 5px
|
||||||
|
top 5px
|
||||||
|
width 20px
|
||||||
|
height 20px
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-row.text-info {
|
||||||
|
width 100%
|
||||||
|
padding 10px 0
|
||||||
|
|
||||||
|
.el-tag {
|
||||||
|
margin-right 10px
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提交按钮
|
||||||
|
|
||||||
|
.submit-btn {
|
||||||
|
display flex
|
||||||
|
margin: 20px 0
|
||||||
|
|
||||||
|
.el-button {
|
||||||
|
width 200px
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.job-list-box {
|
||||||
|
// 任务列表
|
||||||
|
@import "running-job-list.styl"
|
||||||
|
|
||||||
|
.finish-job-list {
|
||||||
|
#waterfall {
|
||||||
|
display flex
|
||||||
|
justify-content center
|
||||||
|
padding-top 20px
|
||||||
|
flex-flow column
|
||||||
|
|
||||||
|
.waterfall-item {
|
||||||
|
overflow visible
|
||||||
|
|
||||||
|
.job-item {
|
||||||
|
width 100%
|
||||||
|
height 100%
|
||||||
|
border 1px solid #666666
|
||||||
|
padding 6px
|
||||||
|
border-radius 6px
|
||||||
|
//position relative
|
||||||
|
|
||||||
|
.el-image {
|
||||||
|
overflow auto
|
||||||
|
}
|
||||||
|
|
||||||
|
.opt {
|
||||||
|
padding-top 5px
|
||||||
|
|
||||||
|
.opt-line {
|
||||||
|
margin 6px 0
|
||||||
|
|
||||||
|
ul {
|
||||||
|
display flex
|
||||||
|
flex-flow row
|
||||||
|
|
||||||
|
li {
|
||||||
|
margin-right 6px
|
||||||
|
|
||||||
|
a {
|
||||||
|
padding 3px 0
|
||||||
|
width 40px
|
||||||
|
text-align center
|
||||||
|
border-radius 5px
|
||||||
|
display block
|
||||||
|
cursor pointer
|
||||||
|
background-color #4E5058
|
||||||
|
color #ffffff
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color #6D6F78
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.show-prompt {
|
||||||
|
font-size 20px
|
||||||
|
cursor pointer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.remove {
|
||||||
|
display none
|
||||||
|
position absolute
|
||||||
|
right 10px
|
||||||
|
top 10px
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
.remove {
|
||||||
|
display block
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.el-image {
|
||||||
|
width 100%
|
||||||
|
height 100%
|
||||||
|
overflow visible
|
||||||
|
|
||||||
|
.el-image-viewer__wrapper {
|
||||||
|
img {
|
||||||
|
width auto
|
||||||
|
height auto
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-slot {
|
||||||
|
display flex
|
||||||
|
flex-flow column
|
||||||
|
justify-content center
|
||||||
|
align-items center
|
||||||
|
min-height 200px
|
||||||
|
color #ffffff
|
||||||
|
|
||||||
|
.iconfont {
|
||||||
|
font-size 50px
|
||||||
|
margin-bottom 10px
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-image.upscale {
|
||||||
|
img {
|
||||||
|
//height 310px
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-slot {
|
||||||
|
min-height 310px
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-image-viewer__wrapper {
|
||||||
|
img {
|
||||||
|
width auto
|
||||||
|
height auto
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-more-data {
|
||||||
|
text-align center
|
||||||
|
padding 30px
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -81,7 +81,281 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@import "task-list.styl"
|
.task-list-box {
|
||||||
|
width 100%
|
||||||
|
padding 10px
|
||||||
|
color #ffffff
|
||||||
|
overflow-x hidden
|
||||||
|
|
||||||
|
.task-list-inner {
|
||||||
|
.el-tabs {
|
||||||
|
--el-tabs-header-height: 55px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-tabs__item {
|
||||||
|
color: #fff;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-tabs .el-tabs__item.is-active {
|
||||||
|
color: #47FFF1;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-tabs .el-tabs__active-bar {
|
||||||
|
background-color: #47FFF1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-textarea {
|
||||||
|
--el-input-focus-border-color: #47FFF1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-textarea__inner {
|
||||||
|
background: transparent;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-input__wrapper {
|
||||||
|
background: transparent;
|
||||||
|
padding 5px
|
||||||
|
}
|
||||||
|
|
||||||
|
.text {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
color: #6b778c;
|
||||||
|
font-size: 15px
|
||||||
|
}
|
||||||
|
|
||||||
|
.param-line.pt {
|
||||||
|
padding-top 5px
|
||||||
|
padding-bottom 5px
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-item-inner {
|
||||||
|
display flex
|
||||||
|
align-items: center
|
||||||
|
|
||||||
|
.el-icon {
|
||||||
|
margin-left 10px
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-form-item__label {
|
||||||
|
color #ffffff
|
||||||
|
}
|
||||||
|
|
||||||
|
// 图片上传样式
|
||||||
|
|
||||||
|
.img-inline {
|
||||||
|
display flex
|
||||||
|
|
||||||
|
.img-uploader {
|
||||||
|
.el-upload {
|
||||||
|
border: 1px dashed var(--el-border-color);
|
||||||
|
border-radius: 6px;
|
||||||
|
cursor: pointer;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
width 120px;
|
||||||
|
transition: var(--el-transition-duration-fast);
|
||||||
|
margin-bottom: 20px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: var(--el-color-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-icon.uploader-icon {
|
||||||
|
font-size: 28px
|
||||||
|
color: #8c939d
|
||||||
|
width 100%
|
||||||
|
height: 120px
|
||||||
|
text-align: center
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.img-list-box {
|
||||||
|
display flex
|
||||||
|
|
||||||
|
.img-item {
|
||||||
|
width 120px
|
||||||
|
position relative
|
||||||
|
margin-right 10px
|
||||||
|
|
||||||
|
.el-image {
|
||||||
|
width 120px
|
||||||
|
height 120px
|
||||||
|
border-radius 5px
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-button {
|
||||||
|
position absolute
|
||||||
|
right 5px
|
||||||
|
top 5px
|
||||||
|
width 20px
|
||||||
|
height 20px
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-row.text-info {
|
||||||
|
width 100%
|
||||||
|
padding 10px 0
|
||||||
|
|
||||||
|
.el-tag {
|
||||||
|
margin-right 10px
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提交按钮
|
||||||
|
|
||||||
|
.submit-btn {
|
||||||
|
display flex
|
||||||
|
margin: 20px 0
|
||||||
|
|
||||||
|
.el-button {
|
||||||
|
width 200px
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 任务列表
|
||||||
|
|
||||||
|
.job-list-box {
|
||||||
|
|
||||||
|
@import "running-job-list.styl"
|
||||||
|
|
||||||
|
.finish-job-list {
|
||||||
|
#waterfall {
|
||||||
|
display flex
|
||||||
|
justify-content center
|
||||||
|
padding-top 20px
|
||||||
|
flex-flow column
|
||||||
|
|
||||||
|
|
||||||
|
.job-item {
|
||||||
|
width 100%
|
||||||
|
height 100%
|
||||||
|
border 1px solid #666666
|
||||||
|
padding 6px
|
||||||
|
overflow hidden
|
||||||
|
border-radius 6px
|
||||||
|
transition: all 0.3s ease; /* 添加过渡效果 */
|
||||||
|
position relative
|
||||||
|
|
||||||
|
.opt {
|
||||||
|
.opt-line {
|
||||||
|
margin 6px 0
|
||||||
|
|
||||||
|
ul {
|
||||||
|
display flex
|
||||||
|
flex-flow row
|
||||||
|
|
||||||
|
li {
|
||||||
|
margin-right 6px
|
||||||
|
|
||||||
|
a {
|
||||||
|
padding 3px 0
|
||||||
|
width 40px
|
||||||
|
text-align center
|
||||||
|
border-radius 5px
|
||||||
|
display block
|
||||||
|
cursor pointer
|
||||||
|
background-color #4E5058
|
||||||
|
color #ffffff
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color #6D6F78
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.show-prompt {
|
||||||
|
font-size 20px
|
||||||
|
cursor pointer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.remove {
|
||||||
|
display none
|
||||||
|
position absolute
|
||||||
|
right 10px
|
||||||
|
top 10px
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
.remove {
|
||||||
|
display block
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.animate {
|
||||||
|
&:hover {
|
||||||
|
box-shadow: 0 0 10px rgba(71, 255, 241, 0.6); /* 添加阴影效果 */
|
||||||
|
transform: translateY(-10px); /* 向上移动10像素 */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.el-image {
|
||||||
|
width 100%
|
||||||
|
height 100%
|
||||||
|
overflow visible
|
||||||
|
|
||||||
|
.el-image-viewer__wrapper {
|
||||||
|
img {
|
||||||
|
width auto
|
||||||
|
height auto
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-slot {
|
||||||
|
display flex
|
||||||
|
flex-flow column
|
||||||
|
justify-content center
|
||||||
|
align-items center
|
||||||
|
min-height 200px
|
||||||
|
color #ffffff
|
||||||
|
|
||||||
|
.iconfont {
|
||||||
|
font-size 50px
|
||||||
|
margin-bottom 10px
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-image.upscale {
|
||||||
|
img {
|
||||||
|
height 310px
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-slot {
|
||||||
|
height 310px
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-image-viewer__wrapper {
|
||||||
|
img {
|
||||||
|
width auto
|
||||||
|
height auto
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-more-data {
|
||||||
|
text-align center
|
||||||
|
padding 30px
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@import "sd-task-dialog.styl"
|
@import "sd-task-dialog.styl"
|
||||||
|
@ -46,6 +46,10 @@
|
|||||||
overflow-y auto
|
overflow-y auto
|
||||||
overflow-x hidden
|
overflow-x hidden
|
||||||
|
|
||||||
|
.waterfall-over-message {
|
||||||
|
display none
|
||||||
|
}
|
||||||
|
|
||||||
.list-item {
|
.list-item {
|
||||||
|
|
||||||
.image {
|
.image {
|
||||||
|
39
web/src/assets/css/running-job-list.styl
Normal file
39
web/src/assets/css/running-job-list.styl
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
.running-job-list {
|
||||||
|
|
||||||
|
.running-job-box {
|
||||||
|
width 100%
|
||||||
|
display flex
|
||||||
|
flex-flow row
|
||||||
|
}
|
||||||
|
|
||||||
|
.job-item {
|
||||||
|
margin-right 10px
|
||||||
|
width 200px
|
||||||
|
height 200px
|
||||||
|
overflow hidden
|
||||||
|
padding 2px
|
||||||
|
background-color #555555
|
||||||
|
|
||||||
|
.job-item-inner {
|
||||||
|
position relative
|
||||||
|
height 100%
|
||||||
|
overflow hidden
|
||||||
|
|
||||||
|
.progress {
|
||||||
|
position absolute
|
||||||
|
width 100%
|
||||||
|
height 100%
|
||||||
|
top 0
|
||||||
|
left 0
|
||||||
|
display flex
|
||||||
|
justify-content center
|
||||||
|
align-items center
|
||||||
|
|
||||||
|
span {
|
||||||
|
font-size 20px
|
||||||
|
color #ffffff
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,215 +0,0 @@
|
|||||||
.task-list-box {
|
|
||||||
width: 100%;
|
|
||||||
padding: 10px;
|
|
||||||
color: #fff;
|
|
||||||
overflow-x: hidden;
|
|
||||||
}
|
|
||||||
.task-list-box .task-list-inner .el-tabs {
|
|
||||||
--el-tabs-header-height: 55px;
|
|
||||||
}
|
|
||||||
.task-list-box .task-list-inner .el-tabs__item {
|
|
||||||
color: #fff;
|
|
||||||
font-size: 18px;
|
|
||||||
}
|
|
||||||
.task-list-box .task-list-inner .title-tabs .el-tabs__item.is-active {
|
|
||||||
color: #47fff1;
|
|
||||||
font-size: 18px;
|
|
||||||
}
|
|
||||||
.task-list-box .task-list-inner .title-tabs .el-tabs__active-bar {
|
|
||||||
background-color: #47fff1;
|
|
||||||
}
|
|
||||||
.task-list-box .task-list-inner .el-textarea {
|
|
||||||
--el-input-focus-border-color: #47fff1;
|
|
||||||
}
|
|
||||||
.task-list-box .task-list-inner .el-textarea__inner {
|
|
||||||
background: transparent;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
.task-list-box .task-list-inner .el-input__wrapper {
|
|
||||||
background: transparent;
|
|
||||||
padding: 5px;
|
|
||||||
}
|
|
||||||
.task-list-box .task-list-inner .text {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
color: #6b778c;
|
|
||||||
font-size: 15px;
|
|
||||||
}
|
|
||||||
.task-list-box .task-list-inner .param-line.pt {
|
|
||||||
padding-top: 5px;
|
|
||||||
padding-bottom: 5px;
|
|
||||||
}
|
|
||||||
.task-list-box .task-list-inner .form-item-inner {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
.task-list-box .task-list-inner .form-item-inner .el-icon {
|
|
||||||
margin-left: 10px;
|
|
||||||
}
|
|
||||||
.task-list-box .task-list-inner .el-form-item__label {
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
.task-list-box .task-list-inner .img-inline {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
.task-list-box .task-list-inner .img-inline .img-uploader .el-upload {
|
|
||||||
border: 1px dashed var(--el-border-color);
|
|
||||||
border-radius: 6px;
|
|
||||||
cursor: pointer;
|
|
||||||
position: relative;
|
|
||||||
overflow: hidden;
|
|
||||||
width: 120px;
|
|
||||||
transition: var(--el-transition-duration-fast);
|
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
|
||||||
.task-list-box .task-list-inner .img-inline .img-uploader .el-upload:hover {
|
|
||||||
border-color: var(--el-color-primary);
|
|
||||||
}
|
|
||||||
.task-list-box .task-list-inner .img-inline .img-uploader .el-upload .el-icon.uploader-icon {
|
|
||||||
font-size: 28px;
|
|
||||||
color: #8c939d;
|
|
||||||
width: 100%;
|
|
||||||
height: 120px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
.task-list-box .task-list-inner .img-inline .img-list-box {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
.task-list-box .task-list-inner .img-inline .img-list-box .img-item {
|
|
||||||
width: 120px;
|
|
||||||
position: relative;
|
|
||||||
margin-right: 10px;
|
|
||||||
}
|
|
||||||
.task-list-box .task-list-inner .img-inline .img-list-box .img-item .el-image {
|
|
||||||
width: 120px;
|
|
||||||
height: 120px;
|
|
||||||
border-radius: 5px;
|
|
||||||
}
|
|
||||||
.task-list-box .task-list-inner .img-inline .img-list-box .img-item .el-button {
|
|
||||||
position: absolute;
|
|
||||||
right: 5px;
|
|
||||||
top: 5px;
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
}
|
|
||||||
.task-list-box .task-list-inner .submit-btn {
|
|
||||||
display: flex;
|
|
||||||
margin: 20px 0;
|
|
||||||
}
|
|
||||||
.task-list-box .task-list-inner .submit-btn .el-button {
|
|
||||||
width: 200px;
|
|
||||||
}
|
|
||||||
.task-list-box .task-list-inner .submit-btn .text-info {
|
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
|
||||||
justify-content: right;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
.task-list-box .task-list-inner .job-list-box .running-job-list .job-item {
|
|
||||||
width: 100%;
|
|
||||||
padding: 2px;
|
|
||||||
background-color: #555;
|
|
||||||
}
|
|
||||||
.task-list-box .task-list-inner .job-list-box .running-job-list .job-item .job-item-inner {
|
|
||||||
position: relative;
|
|
||||||
height: 100%;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
.task-list-box .task-list-inner .job-list-box .running-job-list .job-item .job-item-inner .progress {
|
|
||||||
position: absolute;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
.task-list-box .task-list-inner .job-list-box .running-job-list .job-item .job-item-inner .progress span {
|
|
||||||
font-size: 20px;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
.task-list-box .task-list-inner .job-list-box .finish-job-list .job-item {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
border: 1px solid #666;
|
|
||||||
padding: 6px;
|
|
||||||
overflow: hidden;
|
|
||||||
border-radius: 6px;
|
|
||||||
transition: all 0.3s ease; /* 添加过渡效果 */
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
.task-list-box .task-list-inner .job-list-box .finish-job-list .job-item .opt .opt-line {
|
|
||||||
margin: 6px 0;
|
|
||||||
}
|
|
||||||
.task-list-box .task-list-inner .job-list-box .finish-job-list .job-item .opt .opt-line ul {
|
|
||||||
display: flex;
|
|
||||||
flex-flow: row;
|
|
||||||
}
|
|
||||||
.task-list-box .task-list-inner .job-list-box .finish-job-list .job-item .opt .opt-line ul li {
|
|
||||||
margin-right: 6px;
|
|
||||||
}
|
|
||||||
.task-list-box .task-list-inner .job-list-box .finish-job-list .job-item .opt .opt-line ul li a {
|
|
||||||
padding: 3px 0;
|
|
||||||
width: 40px;
|
|
||||||
text-align: center;
|
|
||||||
border-radius: 5px;
|
|
||||||
display: block;
|
|
||||||
cursor: pointer;
|
|
||||||
background-color: #4e5058;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
.task-list-box .task-list-inner .job-list-box .finish-job-list .job-item .opt .opt-line ul li a:hover {
|
|
||||||
background-color: #6d6f78;
|
|
||||||
}
|
|
||||||
.task-list-box .task-list-inner .job-list-box .finish-job-list .job-item .opt .opt-line ul .show-prompt {
|
|
||||||
font-size: 20px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
.task-list-box .task-list-inner .job-list-box .finish-job-list .job-item .remove {
|
|
||||||
display: none;
|
|
||||||
position: absolute;
|
|
||||||
right: 10px;
|
|
||||||
top: 10px;
|
|
||||||
}
|
|
||||||
.task-list-box .task-list-inner .job-list-box .finish-job-list .job-item:hover .remove {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
.task-list-box .task-list-inner .job-list-box .finish-job-list .animate:hover {
|
|
||||||
box-shadow: 0 0 10px rgba(71,255,241,0.6); /* 添加阴影效果 */
|
|
||||||
transform: translateY(-10px); /* 向上移动10像素 */
|
|
||||||
}
|
|
||||||
.task-list-box .task-list-inner .job-list-box .el-image {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
overflow: visible;
|
|
||||||
}
|
|
||||||
.task-list-box .task-list-inner .job-list-box .el-image img {
|
|
||||||
height: 240px;
|
|
||||||
}
|
|
||||||
.task-list-box .task-list-inner .job-list-box .el-image .el-image-viewer__wrapper img {
|
|
||||||
width: auto;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
.task-list-box .task-list-inner .job-list-box .el-image .image-slot {
|
|
||||||
display: flex;
|
|
||||||
flex-flow: column;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
min-height: 200px;
|
|
||||||
color: #fff;
|
|
||||||
height: 240px;
|
|
||||||
}
|
|
||||||
.task-list-box .task-list-inner .job-list-box .el-image .image-slot .iconfont {
|
|
||||||
font-size: 50px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
.task-list-box .task-list-inner .job-list-box .el-image.upscale {
|
|
||||||
max-height: 310px;
|
|
||||||
}
|
|
||||||
.task-list-box .task-list-inner .job-list-box .el-image.upscale img {
|
|
||||||
height: 310px;
|
|
||||||
}
|
|
||||||
.task-list-box .task-list-inner .job-list-box .el-image.upscale .el-image-viewer__wrapper img {
|
|
||||||
width: auto;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
@ -1,302 +0,0 @@
|
|||||||
.task-list-box {
|
|
||||||
width 100%
|
|
||||||
padding 10px
|
|
||||||
color #ffffff
|
|
||||||
overflow-x hidden
|
|
||||||
|
|
||||||
.task-list-inner {
|
|
||||||
.el-tabs {
|
|
||||||
--el-tabs-header-height: 55px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-tabs__item {
|
|
||||||
color: #fff;
|
|
||||||
font-size: 18px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title-tabs .el-tabs__item.is-active {
|
|
||||||
color: #47FFF1;
|
|
||||||
font-size: 18px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title-tabs .el-tabs__active-bar {
|
|
||||||
background-color: #47FFF1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-textarea {
|
|
||||||
--el-input-focus-border-color: #47FFF1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-textarea__inner {
|
|
||||||
background: transparent;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-input__wrapper {
|
|
||||||
background: transparent;
|
|
||||||
padding 5px
|
|
||||||
}
|
|
||||||
|
|
||||||
.text {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
color: #6b778c;
|
|
||||||
font-size: 15px
|
|
||||||
}
|
|
||||||
|
|
||||||
.param-line.pt {
|
|
||||||
padding-top 5px
|
|
||||||
padding-bottom 5px
|
|
||||||
}
|
|
||||||
|
|
||||||
.form-item-inner {
|
|
||||||
display flex
|
|
||||||
align-items: center
|
|
||||||
|
|
||||||
.el-icon {
|
|
||||||
margin-left 10px
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-form-item__label {
|
|
||||||
color #ffffff
|
|
||||||
}
|
|
||||||
|
|
||||||
// 图片上传样式
|
|
||||||
|
|
||||||
.img-inline {
|
|
||||||
display flex
|
|
||||||
|
|
||||||
.img-uploader {
|
|
||||||
.el-upload {
|
|
||||||
border: 1px dashed var(--el-border-color);
|
|
||||||
border-radius: 6px;
|
|
||||||
cursor: pointer;
|
|
||||||
position: relative;
|
|
||||||
overflow: hidden;
|
|
||||||
width 120px;
|
|
||||||
transition: var(--el-transition-duration-fast);
|
|
||||||
margin-bottom: 20px;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
border-color: var(--el-color-primary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-icon.uploader-icon {
|
|
||||||
font-size: 28px
|
|
||||||
color: #8c939d
|
|
||||||
width 100%
|
|
||||||
height: 120px
|
|
||||||
text-align: center
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.img-list-box {
|
|
||||||
display flex
|
|
||||||
|
|
||||||
.img-item {
|
|
||||||
width 120px
|
|
||||||
position relative
|
|
||||||
margin-right 10px
|
|
||||||
|
|
||||||
.el-image {
|
|
||||||
width 120px
|
|
||||||
height 120px
|
|
||||||
border-radius 5px
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-button {
|
|
||||||
position absolute
|
|
||||||
right 5px
|
|
||||||
top 5px
|
|
||||||
width 20px
|
|
||||||
height 20px
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-row.text-info {
|
|
||||||
width 100%
|
|
||||||
padding 10px 0
|
|
||||||
|
|
||||||
.el-tag {
|
|
||||||
margin-right 10px
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 提交按钮
|
|
||||||
|
|
||||||
.submit-btn {
|
|
||||||
display flex
|
|
||||||
margin: 20px 0
|
|
||||||
|
|
||||||
.el-button {
|
|
||||||
width 200px
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// 任务列表
|
|
||||||
|
|
||||||
.job-list-box {
|
|
||||||
.running-job-list {
|
|
||||||
.job-item {
|
|
||||||
//border: 1px solid #454545;
|
|
||||||
width: 100%;
|
|
||||||
padding 2px
|
|
||||||
background-color #555555
|
|
||||||
|
|
||||||
.job-item-inner {
|
|
||||||
position relative
|
|
||||||
height 100%
|
|
||||||
overflow hidden
|
|
||||||
|
|
||||||
.progress {
|
|
||||||
position absolute
|
|
||||||
width 100%
|
|
||||||
height 100%
|
|
||||||
top 0
|
|
||||||
left 0
|
|
||||||
display flex
|
|
||||||
justify-content center
|
|
||||||
align-items center
|
|
||||||
|
|
||||||
span {
|
|
||||||
font-size 20px
|
|
||||||
color #ffffff
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.finish-job-list {
|
|
||||||
.job-item {
|
|
||||||
width 100%
|
|
||||||
height 100%
|
|
||||||
border 1px solid #666666
|
|
||||||
padding 6px
|
|
||||||
overflow hidden
|
|
||||||
border-radius 6px
|
|
||||||
transition: all 0.3s ease; /* 添加过渡效果 */
|
|
||||||
position relative
|
|
||||||
|
|
||||||
.opt {
|
|
||||||
.opt-line {
|
|
||||||
margin 6px 0
|
|
||||||
|
|
||||||
ul {
|
|
||||||
display flex
|
|
||||||
flex-flow row
|
|
||||||
|
|
||||||
li {
|
|
||||||
margin-right 6px
|
|
||||||
|
|
||||||
a {
|
|
||||||
padding 3px 0
|
|
||||||
width 40px
|
|
||||||
text-align center
|
|
||||||
border-radius 5px
|
|
||||||
display block
|
|
||||||
cursor pointer
|
|
||||||
background-color #4E5058
|
|
||||||
color #ffffff
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color #6D6F78
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.show-prompt {
|
|
||||||
font-size 20px
|
|
||||||
cursor pointer
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.remove {
|
|
||||||
display none
|
|
||||||
position absolute
|
|
||||||
right 10px
|
|
||||||
top 10px
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
.remove {
|
|
||||||
display block
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.animate {
|
|
||||||
&:hover {
|
|
||||||
box-shadow: 0 0 10px rgba(71, 255, 241, 0.6); /* 添加阴影效果 */
|
|
||||||
transform: translateY(-10px); /* 向上移动10像素 */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.el-image {
|
|
||||||
width 100%
|
|
||||||
height 100%
|
|
||||||
overflow visible
|
|
||||||
|
|
||||||
img {
|
|
||||||
height 240px
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-image-viewer__wrapper {
|
|
||||||
img {
|
|
||||||
width auto
|
|
||||||
height auto
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.image-slot {
|
|
||||||
display flex
|
|
||||||
flex-flow column
|
|
||||||
justify-content center
|
|
||||||
align-items center
|
|
||||||
min-height 200px
|
|
||||||
color #ffffff
|
|
||||||
height 240px
|
|
||||||
|
|
||||||
.iconfont {
|
|
||||||
font-size 50px
|
|
||||||
margin-bottom 10px
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-image.upscale {
|
|
||||||
img {
|
|
||||||
height 310px
|
|
||||||
}
|
|
||||||
|
|
||||||
.image-slot {
|
|
||||||
height 310px
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-image-viewer__wrapper {
|
|
||||||
img {
|
|
||||||
width auto
|
|
||||||
height auto
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.no-more-data {
|
|
||||||
text-align center
|
|
||||||
padding 20px
|
|
||||||
}
|
|
||||||
}
|
|
@ -82,39 +82,70 @@
|
|||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="task-list-box" @scrollend="handleScrollEnd">
|
<div class="task-list-box">
|
||||||
<div class="task-list-inner" :style="{ height: listBoxHeight + 'px' }">
|
<div class="task-list-inner" :style="{ height: listBoxHeight + 'px' }">
|
||||||
<div class="job-list-box">
|
<div class="job-list-box">
|
||||||
<h2>任务列表</h2>
|
<h2>任务列表</h2>
|
||||||
<div class="running-job-list">
|
<div class="running-job-list">
|
||||||
<ItemList :items="runningJobs" v-if="runningJobs.length > 0" :width="240">
|
<div class="running-job-box" v-if="runningJobs.length > 0">
|
||||||
<template #default>
|
<div class="job-item" v-for="item in runningJobs">
|
||||||
<div class="job-item">
|
<div v-if="item.progress > 0" class="job-item-inner">
|
||||||
<el-image fit="cover">
|
<el-image :src="item['img_url']" fit="cover" loading="lazy">
|
||||||
|
<template #placeholder>
|
||||||
|
<div class="image-slot">
|
||||||
|
正在加载图片
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
<template #error>
|
<template #error>
|
||||||
<div class="image-slot">
|
<div class="image-slot">
|
||||||
<i class="iconfont icon-quick-start"></i>
|
<el-icon>
|
||||||
<span>任务正在排队中</span>
|
<Picture/>
|
||||||
|
</el-icon>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-image>
|
</el-image>
|
||||||
|
|
||||||
|
<div class="progress">
|
||||||
|
<el-progress type="circle" :percentage="item.progress" :width="100"
|
||||||
|
color="#47fff1"/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
<el-image fit="cover" v-else>
|
||||||
</ItemList>
|
<template #error>
|
||||||
|
<div class="image-slot">
|
||||||
|
<i class="iconfont icon-quick-start"></i>
|
||||||
|
<span>任务正在排队中</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-image>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<el-empty :image-size="100" v-else/>
|
<el-empty :image-size="100" v-else/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h2>创作记录</h2>
|
<h2>创作记录</h2>
|
||||||
<div class="finish-job-list">
|
<div class="finish-job-list">
|
||||||
<div v-if="finishedJobs.length > 0">
|
<div v-if="finishedJobs.length > 0">
|
||||||
<ItemList :items="finishedJobs" :width="240" :gap="16">
|
<v3-waterfall
|
||||||
<template #default="scope">
|
id="waterfall"
|
||||||
|
:list="finishedJobs"
|
||||||
|
srcKey="img_thumb"
|
||||||
|
:gap="20"
|
||||||
|
:bottomGap="-10"
|
||||||
|
:colWidth="colWidth"
|
||||||
|
:distanceToScroll="100"
|
||||||
|
:isLoading="loading"
|
||||||
|
:isOver="isOver"
|
||||||
|
@scrollReachBottom="fetchFinishJobs()">
|
||||||
|
<template #default="slotProp">
|
||||||
<div class="job-item">
|
<div class="job-item">
|
||||||
<el-image v-if="scope.item['img_url']"
|
<el-image
|
||||||
:src="scope.item['img_url']+'?imageView2/1/w/240/h/240/q/75'"
|
v-if="slotProp.item.img_url !== ''"
|
||||||
fit="cover"
|
@click="previewImg(slotProp.item)"
|
||||||
:preview-src-list="[scope.item['img_url']]"
|
:src="slotProp.item['img_thumb']"
|
||||||
loading="lazy">
|
fit="cover"
|
||||||
|
loading="lazy">
|
||||||
<template #placeholder>
|
<template #placeholder>
|
||||||
<div class="image-slot">
|
<div class="image-slot">
|
||||||
正在加载图片
|
正在加载图片
|
||||||
@ -130,18 +161,12 @@
|
|||||||
</template>
|
</template>
|
||||||
</el-image>
|
</el-image>
|
||||||
|
|
||||||
<el-image v-else
|
<el-image v-else>
|
||||||
:src="scope.item['org_url']"
|
|
||||||
fit="cover"
|
|
||||||
:preview-src-list="[scope.item['org_url']]"
|
|
||||||
loading="lazy">
|
|
||||||
<template #placeholder>
|
|
||||||
<div class="image-slot">
|
|
||||||
正在加载图片
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template #error>
|
<template #error>
|
||||||
|
<div class="image-slot">
|
||||||
|
<i class="iconfont icon-loading"></i>
|
||||||
|
<span>正在下载图片</span>
|
||||||
|
</div>
|
||||||
<div class="image-slot">
|
<div class="image-slot">
|
||||||
<el-icon>
|
<el-icon>
|
||||||
<Picture/>
|
<Picture/>
|
||||||
@ -152,35 +177,39 @@
|
|||||||
|
|
||||||
<div class="remove">
|
<div class="remove">
|
||||||
<el-tooltip content="删除" placement="top" effect="light">
|
<el-tooltip content="删除" placement="top" effect="light">
|
||||||
<el-button type="danger" :icon="Delete" @click="removeImage($event,scope.item)" circle/>
|
<el-button type="danger" :icon="Delete" @click="removeImage($event,slotProp.item)" circle/>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
<el-tooltip content="分享" placement="top" effect="light" v-if="scope.item.publish">
|
<el-tooltip content="分享" placement="top" effect="light" v-if="slotProp.item.publish">
|
||||||
<el-button type="warning"
|
<el-button type="warning"
|
||||||
@click="publishImage($event,scope.item, false)"
|
@click="publishImage($event,slotProp.item, false)"
|
||||||
circle>
|
circle>
|
||||||
<i class="iconfont icon-cancel-share"></i>
|
<i class="iconfont icon-cancel-share"></i>
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
<el-tooltip content="取消分享" placement="top" effect="light" v-else>
|
<el-tooltip content="取消分享" placement="top" effect="light" v-else>
|
||||||
<el-button type="success" @click="publishImage($event,scope.item, true)" circle>
|
<el-button type="success" @click="publishImage($event,slotProp.item, true)" circle>
|
||||||
<i class="iconfont icon-share-bold"></i>
|
<i class="iconfont icon-share-bold"></i>
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
|
|
||||||
<el-tooltip content="复制提示词" placement="top" effect="light">
|
<el-tooltip content="复制提示词" placement="top" effect="light">
|
||||||
<el-button type="info" circle class="copy-prompt" :data-clipboard-text="scope.item.prompt">
|
<el-button type="info" circle class="copy-prompt"
|
||||||
|
:data-clipboard-text="slotProp.item.prompt">
|
||||||
<i class="iconfont icon-file"></i>
|
<i class="iconfont icon-file"></i>
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</ItemList>
|
|
||||||
|
|
||||||
<div class="no-more-data" v-if="isOver">
|
<template #footer>
|
||||||
<span>没有更多数据了</span>
|
<div class="no-more-data">
|
||||||
<i class="iconfont icon-face"></i>
|
<span>没有更多数据了</span>
|
||||||
</div>
|
<i class="iconfont icon-face"></i>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</v3-waterfall>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<el-empty :image-size="100" v-else/>
|
<el-empty :image-size="100" v-else/>
|
||||||
</div> <!-- end finish job list-->
|
</div> <!-- end finish job list-->
|
||||||
@ -193,15 +222,15 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<login-dialog :show="showLoginDialog" @hide="showLoginDialog = false" @success="initData"/>
|
<login-dialog :show="showLoginDialog" @hide="showLoginDialog = false" @success="initData"/>
|
||||||
|
<el-image-viewer @close="() => { previewURL = '' }" v-if="previewURL !== ''" :url-list="[previewURL]"/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import {onMounted, onUnmounted, ref} from "vue"
|
import {onMounted, onUnmounted, ref} from "vue"
|
||||||
import {Delete, InfoFilled, Picture} from "@element-plus/icons-vue";
|
import {Delete, InfoFilled} from "@element-plus/icons-vue";
|
||||||
import {httpGet, httpPost} from "@/utils/http";
|
import {httpGet, httpPost} from "@/utils/http";
|
||||||
import {ElMessage, ElMessageBox, ElNotification} from "element-plus";
|
import {ElMessage, ElMessageBox, ElNotification} from "element-plus";
|
||||||
import ItemList from "@/components/ItemList.vue";
|
|
||||||
import Clipboard from "clipboard";
|
import Clipboard from "clipboard";
|
||||||
import {checkSession} from "@/action/session";
|
import {checkSession} from "@/action/session";
|
||||||
import LoginDialog from "@/components/LoginDialog.vue";
|
import LoginDialog from "@/components/LoginDialog.vue";
|
||||||
@ -210,6 +239,10 @@ const listBoxHeight = ref(window.innerHeight - 40)
|
|||||||
const paramBoxHeight = ref(window.innerHeight - 150)
|
const paramBoxHeight = ref(window.innerHeight - 150)
|
||||||
const showLoginDialog = ref(false)
|
const showLoginDialog = ref(false)
|
||||||
const isLogin = ref(false)
|
const isLogin = ref(false)
|
||||||
|
const loading = ref(true)
|
||||||
|
const colWidth = ref(240)
|
||||||
|
const isOver = ref(false)
|
||||||
|
const previewURL = ref("")
|
||||||
|
|
||||||
window.onresize = () => {
|
window.onresize = () => {
|
||||||
listBoxHeight.value = window.innerHeight - 40
|
listBoxHeight.value = window.innerHeight - 40
|
||||||
@ -268,21 +301,15 @@ const initData = () => {
|
|||||||
power.value = user['power']
|
power.value = user['power']
|
||||||
userId.value = user.id
|
userId.value = user.id
|
||||||
isLogin.value = true
|
isLogin.value = true
|
||||||
|
|
||||||
|
page.value = 0
|
||||||
fetchRunningJobs()
|
fetchRunningJobs()
|
||||||
fetchFinishJobs(1)
|
fetchFinishJobs()
|
||||||
connect()
|
connect()
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleScrollEnd = () => {
|
|
||||||
if (isOver.value === true) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
page.value += 1
|
|
||||||
fetchFinishJobs(page.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
const socket = ref(null)
|
const socket = ref(null)
|
||||||
const heartbeatHandle = ref(null)
|
const heartbeatHandle = ref(null)
|
||||||
const connect = () => {
|
const connect = () => {
|
||||||
@ -323,7 +350,7 @@ const connect = () => {
|
|||||||
reader.onload = () => {
|
reader.onload = () => {
|
||||||
const message = String(reader.result)
|
const message = String(reader.result)
|
||||||
if (message === "FINISH") {
|
if (message === "FINISH") {
|
||||||
page.value = 1
|
page.value = 0
|
||||||
fetchFinishJobs(page.value)
|
fetchFinishJobs(page.value)
|
||||||
isOver.value = false
|
isOver.value = false
|
||||||
}
|
}
|
||||||
@ -368,21 +395,30 @@ const fetchRunningJobs = () => {
|
|||||||
|
|
||||||
const page = ref(1)
|
const page = ref(1)
|
||||||
const pageSize = ref(15)
|
const pageSize = ref(15)
|
||||||
const isOver = ref(false)
|
|
||||||
// 获取已完成的任务
|
// 获取已完成的任务
|
||||||
const fetchFinishJobs = (page) => {
|
const fetchFinishJobs = () => {
|
||||||
if (!isLogin.value) {
|
if (!isLogin.value) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
httpGet(`/api/dall/jobs?status=1&page=${page}&page_size=${pageSize.value}`).then(res => {
|
|
||||||
|
loading.value = true
|
||||||
|
page.value = page.value + 1
|
||||||
|
|
||||||
|
httpGet(`/api/dall/jobs?status=1&page=${page.value}&page_size=${pageSize.value}`).then(res => {
|
||||||
if (res.data.length < pageSize.value) {
|
if (res.data.length < pageSize.value) {
|
||||||
isOver.value = true
|
isOver.value = true
|
||||||
}
|
}
|
||||||
if (page === 1) {
|
const imageList = res.data
|
||||||
finishedJobs.value = res.data
|
for (let i = 0; i < imageList.length; i++) {
|
||||||
} else {
|
imageList[i]["img_thumb"] = imageList[i]["img_url"] + "?imageView2/4/w/300/h/0/q/75"
|
||||||
finishedJobs.value = finishedJobs.value.concat(res.data)
|
|
||||||
}
|
}
|
||||||
|
if (page.value === 1) {
|
||||||
|
finishedJobs.value = imageList
|
||||||
|
} else {
|
||||||
|
finishedJobs.value = finishedJobs.value.concat(imageList)
|
||||||
|
}
|
||||||
|
|
||||||
|
loading.value = false
|
||||||
}).catch(e => {
|
}).catch(e => {
|
||||||
ElMessage.error("获取任务失败:" + e.message)
|
ElMessage.error("获取任务失败:" + e.message)
|
||||||
})
|
})
|
||||||
@ -430,6 +466,10 @@ const removeImage = (event, item) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const previewImg = (item) => {
|
||||||
|
previewURL.value = item.img_url
|
||||||
|
}
|
||||||
|
|
||||||
// 发布图片到作品墙
|
// 发布图片到作品墙
|
||||||
const publishImage = (event, item, action) => {
|
const publishImage = (event, item, action) => {
|
||||||
event.stopPropagation()
|
event.stopPropagation()
|
||||||
|
@ -451,70 +451,78 @@
|
|||||||
<div class="job-list-box">
|
<div class="job-list-box">
|
||||||
<h2>任务列表</h2>
|
<h2>任务列表</h2>
|
||||||
<div class="running-job-list">
|
<div class="running-job-list">
|
||||||
<ItemList :items="runningJobs" v-if="runningJobs.length > 0">
|
<div class="running-job-box" v-if="runningJobs.length > 0">
|
||||||
<template #default="scope">
|
<div class="job-item" v-for="item in runningJobs">
|
||||||
<div class="job-item">
|
<div v-if="item.progress > 0" class="job-item-inner">
|
||||||
<div v-if="scope.item.progress > 0" class="job-item-inner">
|
<el-image :src="item['img_url']" fit="cover" loading="lazy">
|
||||||
<el-image :src="scope.item['img_url']" :zoom-rate="1.2"
|
<template #placeholder>
|
||||||
:preview-src-list="[scope.item['img_url']]" fit="cover" :initial-index="0"
|
<div class="image-slot">
|
||||||
loading="lazy">
|
正在加载图片
|
||||||
<template #placeholder>
|
</div>
|
||||||
<div class="image-slot">
|
</template>
|
||||||
正在加载图片
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template #error>
|
|
||||||
<div class="image-slot">
|
|
||||||
<el-icon>
|
|
||||||
<Picture/>
|
|
||||||
</el-icon>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</el-image>
|
|
||||||
|
|
||||||
<div class="progress">
|
|
||||||
<el-progress type="circle" :percentage="scope.item.progress" :width="100"
|
|
||||||
color="#47fff1"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<el-image fit="cover" v-else>
|
|
||||||
<template #error>
|
<template #error>
|
||||||
<div class="image-slot">
|
<div class="image-slot">
|
||||||
<i class="iconfont icon-quick-start"></i>
|
<el-icon>
|
||||||
<span>任务正在排队中</span>
|
<Picture/>
|
||||||
|
</el-icon>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-image>
|
</el-image>
|
||||||
|
|
||||||
|
<div class="progress">
|
||||||
|
<el-progress type="circle" :percentage="item.progress" :width="100"
|
||||||
|
color="#47fff1"/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
<el-image fit="cover" v-else>
|
||||||
</ItemList>
|
<template #error>
|
||||||
|
<div class="image-slot">
|
||||||
|
<i class="iconfont icon-quick-start"></i>
|
||||||
|
<span>任务正在排队中</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-image>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<el-empty :image-size="100" v-else/>
|
<el-empty :image-size="100" v-else/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h2>创作记录</h2>
|
<h2>创作记录</h2>
|
||||||
<div class="finish-job-list">
|
<div class="finish-job-list">
|
||||||
<div v-if="finishedJobs.length > 0">
|
<div v-if="finishedJobs.length > 0">
|
||||||
<ItemList :items="finishedJobs" :width="240" :gap="16">
|
<v3-waterfall
|
||||||
<template #default="scope">
|
id="waterfall"
|
||||||
|
:list="finishedJobs"
|
||||||
|
srcKey="thumb_url"
|
||||||
|
:gap="20"
|
||||||
|
:bottomGap="-8"
|
||||||
|
:colWidth="colWidth"
|
||||||
|
:distanceToScroll="100"
|
||||||
|
:isLoading="loading"
|
||||||
|
:isOver="isOver"
|
||||||
|
@scrollReachBottom="fetchFinishJobs()">
|
||||||
|
<template #default="slotProp">
|
||||||
<div class="job-item">
|
<div class="job-item">
|
||||||
<el-image
|
<el-image
|
||||||
:src="scope.item['thumb_url']"
|
v-if="slotProp.item.img_url !== ''"
|
||||||
:class="scope.item['can_opt'] ? '' : 'upscale'" :zoom-rate="1.2"
|
:src="slotProp.item['thumb_url']"
|
||||||
:preview-src-list="[scope.item['img_url']]" fit="cover" :initial-index="scope.index"
|
:class="slotProp.item['can_opt'] ? '' : 'upscale'" @click="previewImg(slotProp.item)"
|
||||||
loading="lazy" v-if="scope.item.progress > 0">
|
fit="cover" :initial-index="slotProp.index"
|
||||||
|
loading="lazy">
|
||||||
<template #placeholder>
|
<template #placeholder>
|
||||||
<div class="image-slot">
|
<div class="image-slot">
|
||||||
正在加载图片
|
正在加载图片
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
</el-image>
|
||||||
|
<el-image v-else>
|
||||||
<template #error>
|
<template #error>
|
||||||
<div class="image-slot" v-if="scope.item['img_url'] === ''">
|
<div class="image-slot">
|
||||||
<i class="iconfont icon-loading"></i>
|
<i class="iconfont icon-loading"></i>
|
||||||
<span>正在下载图片</span>
|
<span>正在下载图片</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="image-slot" v-else>
|
<div class="image-slot">
|
||||||
<el-icon>
|
<el-icon>
|
||||||
<Picture/>
|
<Picture/>
|
||||||
</el-icon>
|
</el-icon>
|
||||||
@ -522,13 +530,13 @@
|
|||||||
</template>
|
</template>
|
||||||
</el-image>
|
</el-image>
|
||||||
|
|
||||||
<div class="opt" v-if="scope.item['can_opt']">
|
<div class="opt" v-if="slotProp.item['can_opt']">
|
||||||
<div class="opt-line">
|
<div class="opt-line">
|
||||||
<ul>
|
<ul>
|
||||||
<li><a @click="upscale(1, scope.item)">U1</a></li>
|
<li><a @click="upscale(1, slotProp.item)">U1</a></li>
|
||||||
<li><a @click="upscale(2, scope.item)">U2</a></li>
|
<li><a @click="upscale(2, slotProp.item)">U2</a></li>
|
||||||
<li><a @click="upscale(3, scope.item)">U3</a></li>
|
<li><a @click="upscale(3, slotProp.item)">U3</a></li>
|
||||||
<li><a @click="upscale(4, scope.item)">U4</a></li>
|
<li><a @click="upscale(4, slotProp.item)">U4</a></li>
|
||||||
<li class="show-prompt">
|
<li class="show-prompt">
|
||||||
|
|
||||||
<el-popover placement="left" title="提示词" :width="240" trigger="hover">
|
<el-popover placement="left" title="提示词" :width="240" trigger="hover">
|
||||||
@ -540,9 +548,9 @@
|
|||||||
|
|
||||||
<template #default>
|
<template #default>
|
||||||
<div class="mj-list-item-prompt">
|
<div class="mj-list-item-prompt">
|
||||||
<span>{{ scope.item.prompt }}</span>
|
<span>{{ slotProp.item.prompt }}</span>
|
||||||
<el-icon class="copy-prompt-mj"
|
<el-icon class="copy-prompt-mj"
|
||||||
:data-clipboard-text="scope.item.prompt">
|
:data-clipboard-text="slotProp.item.prompt">
|
||||||
<DocumentCopy/>
|
<DocumentCopy/>
|
||||||
</el-icon>
|
</el-icon>
|
||||||
</div>
|
</div>
|
||||||
@ -554,40 +562,45 @@
|
|||||||
|
|
||||||
<div class="opt-line">
|
<div class="opt-line">
|
||||||
<ul>
|
<ul>
|
||||||
<li><a @click="variation(1, scope.item)">V1</a></li>
|
<li><a @click="variation(1, slotProp.item)">V1</a></li>
|
||||||
<li><a @click="variation(2, scope.item)">V2</a></li>
|
<li><a @click="variation(2, slotProp.item)">V2</a></li>
|
||||||
<li><a @click="variation(3, scope.item)">V3</a></li>
|
<li><a @click="variation(3, slotProp.item)">V3</a></li>
|
||||||
<li><a @click="variation(4, scope.item)">V4</a></li>
|
<li><a @click="variation(4, slotProp.item)">V4</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="remove">
|
<div class="remove">
|
||||||
<el-button type="danger" :icon="Delete" @click="removeImage(scope.item)" circle/>
|
<el-button type="danger" :icon="Delete" @click="removeImage(slotProp.item)" circle/>
|
||||||
<el-button type="warning" v-if="scope.item.publish" @click="publishImage(scope.item, false)"
|
<el-button type="warning" v-if="slotProp.item.publish"
|
||||||
|
@click="publishImage(slotProp.item, false)"
|
||||||
circle>
|
circle>
|
||||||
<i class="iconfont icon-cancel-share"></i>
|
<i class="iconfont icon-cancel-share"></i>
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button type="success" v-else @click="publishImage(scope.item, true)" circle>
|
<el-button type="success" v-else @click="publishImage(slotProp.item, true)" circle>
|
||||||
<i class="iconfont icon-share-bold"></i>
|
<i class="iconfont icon-share-bold"></i>
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</ItemList>
|
|
||||||
<div class="no-more-data" v-if="isOver">
|
<template #footer>
|
||||||
<span>没有更多数据了</span>
|
<div class="no-more-data">
|
||||||
<i class="iconfont icon-face"></i>
|
<span>没有更多数据了</span>
|
||||||
</div>
|
<i class="iconfont icon-face"></i>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</v3-waterfall>
|
||||||
</div>
|
</div>
|
||||||
<el-empty :image-size="100" v-else/>
|
<el-empty :image-size="100" v-else/>
|
||||||
</div> <!-- end finish job list-->
|
</div> <!-- end finish job list-->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div><!-- end task list box -->
|
</div><!-- end task list box -->
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<el-image-viewer @close="() => { previewURL = '' }" v-if="previewURL !== ''" :url-list="[previewURL]"/>
|
||||||
|
|
||||||
<login-dialog :show="showLoginDialog" @hide="showLoginDialog = false" @success="initData"/>
|
<login-dialog :show="showLoginDialog" @hide="showLoginDialog = false" @success="initData"/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -598,7 +611,6 @@ import {ChromeFilled, Delete, DocumentCopy, InfoFilled, Picture, Plus, UploadFil
|
|||||||
import Compressor from "compressorjs";
|
import Compressor from "compressorjs";
|
||||||
import {httpGet, httpPost} from "@/utils/http";
|
import {httpGet, httpPost} from "@/utils/http";
|
||||||
import {ElMessage, ElMessageBox, ElNotification} from "element-plus";
|
import {ElMessage, ElMessageBox, ElNotification} from "element-plus";
|
||||||
import ItemList from "@/components/ItemList.vue";
|
|
||||||
import Clipboard from "clipboard";
|
import Clipboard from "clipboard";
|
||||||
import {checkSession} from "@/action/session";
|
import {checkSession} from "@/action/session";
|
||||||
import {useRouter} from "vue-router";
|
import {useRouter} from "vue-router";
|
||||||
@ -609,6 +621,9 @@ import LoginDialog from "@/components/LoginDialog.vue";
|
|||||||
const listBoxHeight = ref(window.innerHeight - 40)
|
const listBoxHeight = ref(window.innerHeight - 40)
|
||||||
const paramBoxHeight = ref(window.innerHeight - 150)
|
const paramBoxHeight = ref(window.innerHeight - 150)
|
||||||
const showLoginDialog = ref(false)
|
const showLoginDialog = ref(false)
|
||||||
|
const loading = ref(true)
|
||||||
|
const colWidth = ref(240)
|
||||||
|
const previewURL = ref("")
|
||||||
|
|
||||||
window.onresize = () => {
|
window.onresize = () => {
|
||||||
listBoxHeight.value = window.innerHeight - 40
|
listBoxHeight.value = window.innerHeight - 40
|
||||||
@ -730,7 +745,7 @@ const connect = () => {
|
|||||||
reader.onload = () => {
|
reader.onload = () => {
|
||||||
const message = String(reader.result)
|
const message = String(reader.result)
|
||||||
if (message === "FINISH") {
|
if (message === "FINISH") {
|
||||||
page.value = 1
|
page.value = 0
|
||||||
fetchFinishJobs(page.value)
|
fetchFinishJobs(page.value)
|
||||||
isOver.value = false
|
isOver.value = false
|
||||||
}
|
}
|
||||||
@ -773,9 +788,9 @@ const initData = () => {
|
|||||||
power.value = user['power']
|
power.value = user['power']
|
||||||
userId.value = user.id
|
userId.value = user.id
|
||||||
isLogin.value = true
|
isLogin.value = true
|
||||||
|
page.value = 0
|
||||||
fetchRunningJobs()
|
fetchRunningJobs()
|
||||||
fetchFinishJobs(1)
|
fetchFinishJobs()
|
||||||
connect()
|
connect()
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
|
|
||||||
@ -824,35 +839,28 @@ const fetchRunningJobs = () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const page = ref(0)
|
||||||
const handleScrollEnd = () => {
|
|
||||||
if (isOver.value === true) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
page.value += 1
|
|
||||||
fetchFinishJobs(page.value)
|
|
||||||
};
|
|
||||||
|
|
||||||
const page = ref(1)
|
|
||||||
const pageSize = ref(15)
|
const pageSize = ref(15)
|
||||||
const isOver = ref(false)
|
const isOver = ref(false)
|
||||||
const fetchFinishJobs = (page) => {
|
const fetchFinishJobs = () => {
|
||||||
if (!isLogin.value) {
|
if (!isLogin.value || isOver.value) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loading.value = true
|
||||||
|
page.value = page.value + 1
|
||||||
// 获取已完成的任务
|
// 获取已完成的任务
|
||||||
httpGet(`/api/mj/jobs?status=1&page=${page}&page_size=${pageSize.value}`).then(res => {
|
httpGet(`/api/mj/jobs?status=1&page=${page.value}&page_size=${pageSize.value}`).then(res => {
|
||||||
const jobs = res.data
|
const jobs = res.data
|
||||||
for (let i = 0; i < jobs.length; i++) {
|
for (let i = 0; i < jobs.length; i++) {
|
||||||
if (jobs[i]['use_proxy']) {
|
if (jobs[i]['img_url'] !== "") {
|
||||||
jobs[i]['thumb_url'] = jobs[i]['img_url'] + '?x-oss-process=image/quality,q_60&format=webp'
|
|
||||||
} else {
|
|
||||||
if (jobs[i].type === 'upscale' || jobs[i].type === 'swapFace') {
|
if (jobs[i].type === 'upscale' || jobs[i].type === 'swapFace') {
|
||||||
jobs[i]['thumb_url'] = jobs[i]['img_url'] + '?imageView2/1/w/480/h/600/q/75'
|
jobs[i]['thumb_url'] = jobs[i]['img_url'] + '?imageView2/1/w/480/h/600/q/75'
|
||||||
} else {
|
} else {
|
||||||
jobs[i]['thumb_url'] = jobs[i]['img_url'] + '?imageView2/1/w/480/h/480/q/75'
|
jobs[i]['thumb_url'] = jobs[i]['img_url'] + '?imageView2/1/w/480/h/480/q/75'
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
jobs[i]['thumb_url'] = '/images/img-placeholder.jpg'
|
||||||
}
|
}
|
||||||
|
|
||||||
if (jobs[i].type === 'image' || jobs[i].type === 'variation') {
|
if (jobs[i].type === 'image' || jobs[i].type === 'variation') {
|
||||||
@ -862,11 +870,12 @@ const fetchFinishJobs = (page) => {
|
|||||||
if (jobs.length < pageSize.value) {
|
if (jobs.length < pageSize.value) {
|
||||||
isOver.value = true
|
isOver.value = true
|
||||||
}
|
}
|
||||||
if (page === 1) {
|
if (page.value === 1) {
|
||||||
finishedJobs.value = jobs
|
finishedJobs.value = jobs
|
||||||
} else {
|
} else {
|
||||||
finishedJobs.value = finishedJobs.value.concat(jobs)
|
finishedJobs.value = finishedJobs.value.concat(jobs)
|
||||||
}
|
}
|
||||||
|
loading.value = false
|
||||||
}).catch(e => {
|
}).catch(e => {
|
||||||
ElMessage.error("获取任务失败:" + e.message)
|
ElMessage.error("获取任务失败:" + e.message)
|
||||||
})
|
})
|
||||||
@ -1005,6 +1014,11 @@ const publishImage = (item, action) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const previewImg = (item) => {
|
||||||
|
previewURL.value = item.img_url
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// 切换菜单
|
// 切换菜单
|
||||||
const tabChange = (tab) => {
|
const tabChange = (tab) => {
|
||||||
if (tab === "txt2img" || tab === "img2img" || tab === "cref") {
|
if (tab === "txt2img" || tab === "img2img" || tab === "cref") {
|
||||||
|
@ -297,43 +297,40 @@
|
|||||||
<div class="job-list-box">
|
<div class="job-list-box">
|
||||||
<h2>任务列表</h2>
|
<h2>任务列表</h2>
|
||||||
<div class="running-job-list">
|
<div class="running-job-list">
|
||||||
<ItemList :items="runningJobs" v-if="runningJobs.length > 0" :width="240">
|
<div class="running-job-box" v-if="runningJobs.length > 0">
|
||||||
<template #default="scope">
|
<div class="job-item" v-for="item in runningJobs">
|
||||||
<div class="job-item">
|
<div v-if="item.progress > 0" class="job-item-inner">
|
||||||
<div v-if="scope.item.progress > 0" class="job-item-inner">
|
<el-image :src="item['img_url']" fit="cover" loading="lazy">
|
||||||
<el-image :src="scope.item['img_url']"
|
<template #placeholder>
|
||||||
fit="cover"
|
<div class="image-slot">
|
||||||
loading="lazy">
|
正在加载图片
|
||||||
<template #placeholder>
|
</div>
|
||||||
<div class="image-slot">
|
</template>
|
||||||
正在加载图片
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template #error>
|
|
||||||
<div class="image-slot">
|
|
||||||
<el-icon v-if="scope.item['img_url'] !== ''">
|
|
||||||
<Picture/>
|
|
||||||
</el-icon>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</el-image>
|
|
||||||
|
|
||||||
<div class="progress">
|
|
||||||
<el-progress type="circle" :percentage="scope.item.progress" :width="100" color="#47fff1"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<el-image fit="cover" v-else>
|
|
||||||
<template #error>
|
<template #error>
|
||||||
<div class="image-slot">
|
<div class="image-slot">
|
||||||
<i class="iconfont icon-quick-start"></i>
|
<el-icon>
|
||||||
<span>任务正在排队中</span>
|
<Picture/>
|
||||||
|
</el-icon>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-image>
|
</el-image>
|
||||||
|
|
||||||
|
<div class="progress">
|
||||||
|
<el-progress type="circle" :percentage="item.progress" :width="100"
|
||||||
|
color="#47fff1"/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
<el-image fit="cover" v-else>
|
||||||
</ItemList>
|
<template #error>
|
||||||
|
<div class="image-slot">
|
||||||
|
<i class="iconfont icon-quick-start"></i>
|
||||||
|
<span>任务正在排队中</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-image>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<el-empty :image-size="100" v-else/>
|
<el-empty :image-size="100" v-else/>
|
||||||
</div>
|
</div>
|
||||||
<h2>创作记录</h2>
|
<h2>创作记录</h2>
|
||||||
@ -344,7 +341,7 @@
|
|||||||
:list="finishedJobs"
|
:list="finishedJobs"
|
||||||
srcKey="img_thumb"
|
srcKey="img_thumb"
|
||||||
:gap="20"
|
:gap="20"
|
||||||
:bottomGap="10"
|
:bottomGap="-10"
|
||||||
:colWidth="colWidth"
|
:colWidth="colWidth"
|
||||||
:distanceToScroll="100"
|
:distanceToScroll="100"
|
||||||
:isLoading="loading"
|
:isLoading="loading"
|
||||||
@ -369,49 +366,15 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<div class="no-more-data">
|
||||||
|
<span>没有更多数据了</span>
|
||||||
|
<i class="iconfont icon-face"></i>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
</v3-waterfall>
|
</v3-waterfall>
|
||||||
|
|
||||||
<!-- <ItemList :items="finishedJobs" :width="240" :gap="16">-->
|
|
||||||
<!-- <template #default="scope">-->
|
|
||||||
<!-- <div class="job-item animate" @click="showTask(scope.item)">-->
|
|
||||||
<!-- <el-image-->
|
|
||||||
<!-- :src="scope.item['img_url']+'?imageView2/1/w/240/h/240/q/75'"-->
|
|
||||||
<!-- fit="cover"-->
|
|
||||||
<!-- loading="lazy">-->
|
|
||||||
<!-- <template #placeholder>-->
|
|
||||||
<!-- <div class="image-slot">-->
|
|
||||||
<!-- 正在加载图片-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- </template>-->
|
|
||||||
|
|
||||||
<!-- <template #error>-->
|
|
||||||
<!-- <div class="image-slot">-->
|
|
||||||
<!-- <el-icon>-->
|
|
||||||
<!-- <Picture/>-->
|
|
||||||
<!-- </el-icon>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- </template>-->
|
|
||||||
<!-- </el-image>-->
|
|
||||||
|
|
||||||
<!-- <div class="remove">-->
|
|
||||||
<!-- <el-button type="danger" :icon="Delete" @click="removeImage($event,scope.item)" circle/>-->
|
|
||||||
<!-- <el-button type="warning" v-if="scope.item.publish"-->
|
|
||||||
<!-- @click="publishImage($event,scope.item, false)"-->
|
|
||||||
<!-- circle>-->
|
|
||||||
<!-- <i class="iconfont icon-cancel-share"></i>-->
|
|
||||||
<!-- </el-button>-->
|
|
||||||
<!-- <el-button type="success" v-else @click="publishImage($event,scope.item, true)" circle>-->
|
|
||||||
<!-- <i class="iconfont icon-share-bold"></i>-->
|
|
||||||
<!-- </el-button>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- </template>-->
|
|
||||||
<!-- </ItemList>-->
|
|
||||||
|
|
||||||
<!-- <div class="no-more-data" v-if="isOver">-->
|
|
||||||
<!-- <span>没有更多数据了</span>-->
|
|
||||||
<!-- <i class="iconfont icon-face"></i>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
</div>
|
</div>
|
||||||
<el-empty :image-size="100" v-else/>
|
<el-empty :image-size="100" v-else/>
|
||||||
</div> <!-- end finish job list-->
|
</div> <!-- end finish job list-->
|
||||||
@ -541,10 +504,9 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import {onMounted, onUnmounted, ref} from "vue"
|
import {onMounted, onUnmounted, ref} from "vue"
|
||||||
import {DocumentCopy, InfoFilled, Orange, Picture} from "@element-plus/icons-vue";
|
import {Delete, DocumentCopy, InfoFilled, Orange, Picture} from "@element-plus/icons-vue";
|
||||||
import {httpGet, httpPost} from "@/utils/http";
|
import {httpGet, httpPost} from "@/utils/http";
|
||||||
import {ElMessage, ElMessageBox, ElNotification} from "element-plus";
|
import {ElMessage, ElMessageBox, ElNotification} from "element-plus";
|
||||||
import ItemList from "@/components/ItemList.vue";
|
|
||||||
import Clipboard from "clipboard";
|
import Clipboard from "clipboard";
|
||||||
import {checkSession} from "@/action/session";
|
import {checkSession} from "@/action/session";
|
||||||
import {useRouter} from "vue-router";
|
import {useRouter} from "vue-router";
|
||||||
@ -560,16 +522,8 @@ const showLoginDialog = ref(false)
|
|||||||
const isLogin = ref(false)
|
const isLogin = ref(false)
|
||||||
const loading = ref(true)
|
const loading = ref(true)
|
||||||
const colWidth = ref(240)
|
const colWidth = ref(240)
|
||||||
// 计算瀑布流列宽度
|
|
||||||
const calcColWidth = () => {
|
|
||||||
const listBoxWidth = window.innerWidth - 400
|
|
||||||
const rows = Math.floor(listBoxWidth / colWidth.value)
|
|
||||||
colWidth.value = Math.floor((listBoxWidth - (rows - 1) * 12) / rows)
|
|
||||||
}
|
|
||||||
calcColWidth()
|
|
||||||
|
|
||||||
window.onresize = () => {
|
window.onresize = () => {
|
||||||
calcColWidth()
|
|
||||||
listBoxHeight.value = window.innerHeight - 40
|
listBoxHeight.value = window.innerHeight - 40
|
||||||
paramBoxHeight.value = window.innerHeight - 150
|
paramBoxHeight.value = window.innerHeight - 150
|
||||||
}
|
}
|
||||||
@ -645,7 +599,7 @@ const connect = () => {
|
|||||||
reader.onload = () => {
|
reader.onload = () => {
|
||||||
const message = String(reader.result)
|
const message = String(reader.result)
|
||||||
if (message === "FINISH") {
|
if (message === "FINISH") {
|
||||||
page.value = 1
|
page.value = 0
|
||||||
fetchFinishJobs()
|
fetchFinishJobs()
|
||||||
isOver.value = false
|
isOver.value = false
|
||||||
}
|
}
|
||||||
@ -695,6 +649,7 @@ const initData = () => {
|
|||||||
power.value = user['power']
|
power.value = user['power']
|
||||||
userId.value = user.id
|
userId.value = user.id
|
||||||
isLogin.value = true
|
isLogin.value = true
|
||||||
|
page.value = 0
|
||||||
fetchRunningJobs()
|
fetchRunningJobs()
|
||||||
fetchFinishJobs()
|
fetchFinishJobs()
|
||||||
connect()
|
connect()
|
||||||
@ -735,7 +690,7 @@ const pageSize = ref(20)
|
|||||||
const isOver = ref(false)
|
const isOver = ref(false)
|
||||||
// 获取已完成的任务
|
// 获取已完成的任务
|
||||||
const fetchFinishJobs = () => {
|
const fetchFinishJobs = () => {
|
||||||
if (!isLogin.value) {
|
if (!isLogin.value || isOver.value === true) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
loading.value = true
|
loading.value = true
|
||||||
@ -749,7 +704,7 @@ const fetchFinishJobs = () => {
|
|||||||
for (let i = 0; i < imageList.length; i++) {
|
for (let i = 0; i < imageList.length; i++) {
|
||||||
imageList[i]["img_thumb"] = imageList[i]["img_url"] + "?imageView2/4/w/300/h/0/q/75"
|
imageList[i]["img_thumb"] = imageList[i]["img_url"] + "?imageView2/4/w/300/h/0/q/75"
|
||||||
}
|
}
|
||||||
if (page === 1) {
|
if (page.value === 1) {
|
||||||
finishedJobs.value = imageList
|
finishedJobs.value = imageList
|
||||||
} else {
|
} else {
|
||||||
finishedJobs.value = finishedJobs.value.concat(imageList)
|
finishedJobs.value = finishedJobs.value.concat(imageList)
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
:colWidth="colWidth"
|
:colWidth="colWidth"
|
||||||
:distanceToScroll="100"
|
:distanceToScroll="100"
|
||||||
:isLoading="loading"
|
:isLoading="loading"
|
||||||
:isOver="false"
|
:isOver="isOver"
|
||||||
@scrollReachBottom="getNext">
|
@scrollReachBottom="getNext">
|
||||||
<template #default="slotProp">
|
<template #default="slotProp">
|
||||||
<div class="list-item">
|
<div class="list-item">
|
||||||
@ -81,7 +81,7 @@
|
|||||||
:colWidth="colWidth"
|
:colWidth="colWidth"
|
||||||
:distanceToScroll="100"
|
:distanceToScroll="100"
|
||||||
:isLoading="loading"
|
:isLoading="loading"
|
||||||
:isOver="false"
|
:isOver="isOver"
|
||||||
@scrollReachBottom="getNext">
|
@scrollReachBottom="getNext">
|
||||||
<template #default="slotProp">
|
<template #default="slotProp">
|
||||||
<div class="list-item">
|
<div class="list-item">
|
||||||
@ -132,7 +132,7 @@
|
|||||||
:colWidth="colWidth"
|
:colWidth="colWidth"
|
||||||
:distanceToScroll="100"
|
:distanceToScroll="100"
|
||||||
:isLoading="loading"
|
:isLoading="loading"
|
||||||
:isOver="false"
|
:isOver="isOver"
|
||||||
@scrollReachBottom="getNext">
|
@scrollReachBottom="getNext">
|
||||||
<template #default="slotProp">
|
<template #default="slotProp">
|
||||||
<div class="list-item">
|
<div class="list-item">
|
||||||
|
Loading…
Reference in New Issue
Block a user