mirror of
https://github.com/yangjian102621/geekai.git
synced 2025-09-18 17:26:38 +08:00
image task list page for admin console is ready
This commit is contained in:
parent
52e40daf23
commit
ba20717a09
@ -1,4 +1,8 @@
|
||||
# 更新日志
|
||||
## v4.1.6
|
||||
* 功能优化:优化MysQL容器配置文档,解决MysQL容器资源占用过高问题
|
||||
* 功能新增:管理后台增加AI绘图任务管理,可在管理后台浏览和删除用户的绘图任务
|
||||
|
||||
## v4.1.5
|
||||
* 功能优化:重构 websocket 组件,减少 websocket 连接数,全站共享一个 websocket 连接
|
||||
* Bug修复:兼容手机端原生微信支付和支付宝支付渠道
|
||||
|
174
api/handler/admin/image_handler.go
Normal file
174
api/handler/admin/image_handler.go
Normal file
@ -0,0 +1,174 @@
|
||||
package admin
|
||||
|
||||
// * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
// * Copyright 2023 The Geek-AI Authors. All rights reserved.
|
||||
// * Use of this source code is governed by a Apache-2.0 license
|
||||
// * that can be found in the LICENSE file.
|
||||
// * @Author yangjian102621@163.com
|
||||
// * +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
import (
|
||||
"geekai/core"
|
||||
"geekai/core/types"
|
||||
"geekai/handler"
|
||||
"geekai/store/model"
|
||||
"geekai/store/vo"
|
||||
"geekai/utils"
|
||||
"geekai/utils/resp"
|
||||
"github.com/gin-gonic/gin"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type ImageHandler struct {
|
||||
handler.BaseHandler
|
||||
}
|
||||
|
||||
func NewImageHandler(app *core.AppServer, db *gorm.DB) *ImageHandler {
|
||||
return &ImageHandler{BaseHandler: handler.BaseHandler{App: app, DB: db}}
|
||||
}
|
||||
|
||||
type query struct {
|
||||
Prompt string `json:"prompt"`
|
||||
Username string `json:"username"`
|
||||
CreatedAt []string `json:"created_time"`
|
||||
Page int `json:"page"`
|
||||
PageSize int `json:"page_size"`
|
||||
}
|
||||
|
||||
// MjList Midjourney 任务列表
|
||||
func (h *ImageHandler) MjList(c *gin.Context) {
|
||||
var data query
|
||||
if err := c.ShouldBindJSON(&data); err != nil {
|
||||
resp.ERROR(c, types.InvalidArgs)
|
||||
return
|
||||
}
|
||||
|
||||
session := h.DB.Session(&gorm.Session{})
|
||||
if data.Username != "" {
|
||||
var user model.User
|
||||
err := h.DB.Where("username", data.Username).First(&user).Error
|
||||
if err == nil {
|
||||
session = session.Where("user_id", user.Id)
|
||||
}
|
||||
}
|
||||
if data.Prompt != "" {
|
||||
session = session.Where("prompt LIKE ?", "%"+data.Prompt+"%")
|
||||
}
|
||||
if len(data.CreatedAt) == 2 {
|
||||
start := utils.Str2stamp(data.CreatedAt[0] + " 00:00:00")
|
||||
end := utils.Str2stamp(data.CreatedAt[1] + " 00:00:00")
|
||||
session = session.Where("created_at >= ? AND created_at <= ?", start, end)
|
||||
}
|
||||
var total int64
|
||||
session.Model(&model.MidJourneyJob{}).Count(&total)
|
||||
var list []model.MidJourneyJob
|
||||
var items = make([]vo.MidJourneyJob, 0)
|
||||
offset := (data.Page - 1) * data.PageSize
|
||||
err := session.Order("id DESC").Offset(offset).Limit(data.PageSize).Find(&list).Error
|
||||
if err == nil {
|
||||
// 填充数据
|
||||
for _, item := range list {
|
||||
var job vo.MidJourneyJob
|
||||
err = utils.CopyObject(item, &job)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
job.CreatedAt = item.CreatedAt.Unix()
|
||||
items = append(items, job)
|
||||
}
|
||||
}
|
||||
|
||||
resp.SUCCESS(c, vo.NewPage(total, data.Page, data.PageSize, items))
|
||||
}
|
||||
|
||||
// SdList Stable Diffusion 任务列表
|
||||
func (h *ImageHandler) SdList(c *gin.Context) {
|
||||
var data query
|
||||
if err := c.ShouldBindJSON(&data); err != nil {
|
||||
resp.ERROR(c, types.InvalidArgs)
|
||||
return
|
||||
}
|
||||
|
||||
session := h.DB.Session(&gorm.Session{})
|
||||
if data.Username != "" {
|
||||
var user model.User
|
||||
err := h.DB.Where("username", data.Username).First(&user).Error
|
||||
if err == nil {
|
||||
session = session.Where("user_id", user.Id)
|
||||
}
|
||||
}
|
||||
if data.Prompt != "" {
|
||||
session = session.Where("prompt LIKE ?", "%"+data.Prompt+"%")
|
||||
}
|
||||
if len(data.CreatedAt) == 2 {
|
||||
start := utils.Str2stamp(data.CreatedAt[0] + " 00:00:00")
|
||||
end := utils.Str2stamp(data.CreatedAt[1] + " 00:00:00")
|
||||
session = session.Where("created_at >= ? AND created_at <= ?", start, end)
|
||||
}
|
||||
var total int64
|
||||
session.Model(&model.SdJob{}).Count(&total)
|
||||
var list []model.SdJob
|
||||
var items = make([]vo.SdJob, 0)
|
||||
offset := (data.Page - 1) * data.PageSize
|
||||
err := session.Order("id DESC").Offset(offset).Limit(data.PageSize).Find(&list).Error
|
||||
if err == nil {
|
||||
// 填充数据
|
||||
for _, item := range list {
|
||||
var job vo.SdJob
|
||||
err = utils.CopyObject(item, &job)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
job.CreatedAt = item.CreatedAt.Unix()
|
||||
items = append(items, job)
|
||||
}
|
||||
}
|
||||
|
||||
resp.SUCCESS(c, vo.NewPage(total, data.Page, data.PageSize, items))
|
||||
}
|
||||
|
||||
// DallList DALL-E 任务列表
|
||||
func (h *ImageHandler) DallList(c *gin.Context) {
|
||||
var data query
|
||||
if err := c.ShouldBindJSON(&data); err != nil {
|
||||
resp.ERROR(c, types.InvalidArgs)
|
||||
return
|
||||
}
|
||||
|
||||
session := h.DB.Session(&gorm.Session{})
|
||||
if data.Username != "" {
|
||||
var user model.User
|
||||
err := h.DB.Where("username", data.Username).First(&user).Error
|
||||
if err == nil {
|
||||
session = session.Where("user_id", user.Id)
|
||||
}
|
||||
}
|
||||
if data.Prompt != "" {
|
||||
session = session.Where("prompt LIKE ?", "%"+data.Prompt+"%")
|
||||
}
|
||||
if len(data.CreatedAt) == 2 {
|
||||
start := utils.Str2stamp(data.CreatedAt[0] + " 00:00:00")
|
||||
end := utils.Str2stamp(data.CreatedAt[1] + " 00:00:00")
|
||||
session = session.Where("created_at >= ? AND created_at <= ?", start, end)
|
||||
}
|
||||
var total int64
|
||||
session.Model(&model.DallJob{}).Count(&total)
|
||||
var list []model.DallJob
|
||||
var items = make([]vo.DallJob, 0)
|
||||
offset := (data.Page - 1) * data.PageSize
|
||||
err := session.Order("id DESC").Offset(offset).Limit(data.PageSize).Find(&list).Error
|
||||
if err == nil {
|
||||
// 填充数据
|
||||
for _, item := range list {
|
||||
var job vo.DallJob
|
||||
err = utils.CopyObject(item, &job)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
job.CreatedAt = item.CreatedAt.Unix()
|
||||
items = append(items, job)
|
||||
}
|
||||
}
|
||||
|
||||
resp.SUCCESS(c, vo.NewPage(total, data.Page, data.PageSize, items))
|
||||
}
|
@ -539,6 +539,13 @@ func main() {
|
||||
},
|
||||
})
|
||||
}),
|
||||
fx.Provide(admin.NewImageHandler),
|
||||
fx.Invoke(func(s *core.AppServer, h *admin.ImageHandler) {
|
||||
group := s.Engine.Group("/api/admin/image")
|
||||
group.POST("/list/mj", h.MjList)
|
||||
group.POST("/list/sd", h.SdList)
|
||||
group.POST("/list/dall", h.DallList)
|
||||
}),
|
||||
)
|
||||
// 启动应用程序
|
||||
go func() {
|
||||
|
@ -1,23 +1,21 @@
|
||||
package vo
|
||||
|
||||
import "time"
|
||||
|
||||
type MidJourneyJob struct {
|
||||
Id uint `json:"id"`
|
||||
Type string `json:"type"`
|
||||
UserId int `json:"user_id"`
|
||||
ChannelId string `json:"channel_id"`
|
||||
TaskId string `json:"task_id"`
|
||||
MessageId string `json:"message_id"`
|
||||
ReferenceId string `json:"reference_id"`
|
||||
ImgURL string `json:"img_url"`
|
||||
OrgURL string `json:"org_url"`
|
||||
Hash string `json:"hash"`
|
||||
Progress int `json:"progress"`
|
||||
Prompt string `json:"prompt"`
|
||||
UseProxy bool `json:"use_proxy"`
|
||||
Publish bool `json:"publish"`
|
||||
ErrMsg string `json:"err_msg"`
|
||||
Power int `json:"power"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
Id uint `json:"id"`
|
||||
Type string `json:"type"`
|
||||
UserId int `json:"user_id"`
|
||||
ChannelId string `json:"channel_id"`
|
||||
TaskId string `json:"task_id"`
|
||||
MessageId string `json:"message_id"`
|
||||
ReferenceId string `json:"reference_id"`
|
||||
ImgURL string `json:"img_url"`
|
||||
OrgURL string `json:"org_url"`
|
||||
Hash string `json:"hash"`
|
||||
Progress int `json:"progress"`
|
||||
Prompt string `json:"prompt"`
|
||||
UseProxy bool `json:"use_proxy"`
|
||||
Publish bool `json:"publish"`
|
||||
ErrMsg string `json:"err_msg"`
|
||||
Power int `json:"power"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ package vo
|
||||
|
||||
import (
|
||||
"geekai/core/types"
|
||||
"time"
|
||||
)
|
||||
|
||||
type SdJob struct {
|
||||
@ -17,5 +16,5 @@ type SdJob struct {
|
||||
Publish bool `json:"publish"`
|
||||
ErrMsg string `json:"err_msg"`
|
||||
Power int `json:"power"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
CreatedAt int64 `json:"created_at"`
|
||||
}
|
||||
|
@ -33,7 +33,7 @@
|
||||
{{ threeItem.title }}
|
||||
</el-menu-item>
|
||||
</el-sub-menu>
|
||||
<el-menu-item v-else :index="subItem.index">
|
||||
<el-menu-item v-else :index="subItem.index" :key="subItem.index">
|
||||
<i v-if="subItem.icon" :class="'iconfont icon-'+subItem.icon"></i>
|
||||
{{ subItem.title }}
|
||||
</el-menu-item>
|
||||
@ -64,8 +64,8 @@ const logo = ref('')
|
||||
|
||||
// 加载系统配置
|
||||
httpGet('/api/admin/config/get?key=system').then(res => {
|
||||
title.value = res.data['admin_title']
|
||||
logo.value = res.data['logo']
|
||||
title.value = res.data.admin_title
|
||||
logo.value = res.data.logo
|
||||
}).catch(e => {
|
||||
ElMessage.error("加载系统配置失败: " + e.message)
|
||||
})
|
||||
@ -101,7 +101,7 @@ const items = [
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
icon: 'api-key',
|
||||
index: '/admin/apikey',
|
||||
@ -137,6 +137,11 @@ const items = [
|
||||
index: '/admin/chats',
|
||||
title: '对话管理',
|
||||
},
|
||||
{
|
||||
icon: 'image',
|
||||
index: '/admin/images',
|
||||
title: '绘图管理',
|
||||
},
|
||||
{
|
||||
icon: 'role',
|
||||
index: '/admin/manger',
|
||||
|
@ -233,6 +233,12 @@ const routes = [
|
||||
meta: {title: '对话管理'},
|
||||
component: () => import('@/views/admin/ChatList.vue'),
|
||||
},
|
||||
{
|
||||
path: '/admin/images',
|
||||
name: 'admin-images',
|
||||
meta: {title: '绘图管理'},
|
||||
component: () => import('@/views/admin/ImageList.vue'),
|
||||
},
|
||||
{
|
||||
path: '/admin/powerLog',
|
||||
name: 'admin-power-log',
|
||||
|
510
web/src/views/admin/ImageList.vue
Normal file
510
web/src/views/admin/ImageList.vue
Normal file
@ -0,0 +1,510 @@
|
||||
<template>
|
||||
<div class="container chat-list">
|
||||
<el-tabs v-model="activeName" @tab-change="handleChange">
|
||||
<el-tab-pane label="Midjourney" name="mj" v-loading="data.mj.loading">
|
||||
<div class="handle-box">
|
||||
<el-input v-model.number="data.mj.query.username" placeholder="用户名" class="handle-input mr10"
|
||||
@keyup="search($event,'mj')"></el-input>
|
||||
<el-input v-model="data.mj.query.prompt" placeholder="提示词" class="handle-input mr10"
|
||||
@keyup="search($event,'mj')"></el-input>
|
||||
<el-date-picker
|
||||
v-model="data.mj.query.created_at"
|
||||
type="daterange"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
format="YYYY-MM-DD"
|
||||
value-format="YYYY-MM-DD"
|
||||
style="margin-right: 10px;width: 200px; position: relative;top:3px;"
|
||||
/>
|
||||
<el-button type="primary" :icon="Search" @click="fetchMjData">搜索</el-button>
|
||||
</div>
|
||||
|
||||
<div v-if="data.mj.items.length > 0">
|
||||
<el-row>
|
||||
<el-table :data="data.mj.items" :row-key="row => row.id" table-layout="auto">
|
||||
<el-table-column prop="user_id" label="用户ID"/>
|
||||
<el-table-column label="任务类型">
|
||||
<template #default="scope">
|
||||
<el-button :color="taskTypeTheme[scope.row.type].color" size="small" plain>{{taskTypeTheme[scope.row.type].text}}</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="progress" label="任务进度">
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.progress <= 100">{{scope.row.progress}}%</span>
|
||||
<el-tag v-else type="danger">已失败</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="power" label="消耗算力"/>
|
||||
<el-table-column label="结果图片">
|
||||
<template #default="scope">
|
||||
<el-button size="small" type="success" @click="showImage(scope.row.img_url)" v-if="scope.row.img_url !== ''" plain>预览图片</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="提示词">
|
||||
<template #default="scope">
|
||||
<el-popover
|
||||
placement="top-start"
|
||||
title="绘画提示词"
|
||||
:width="300"
|
||||
trigger="hover"
|
||||
:content="scope.row.prompt"
|
||||
>
|
||||
<template #reference>
|
||||
<span>{{ substr(scope.row.prompt, 20) }}</span>
|
||||
</template>
|
||||
</el-popover>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建时间">
|
||||
<template #default="scope">
|
||||
<span>{{ dateFormat(scope.row['created_at']) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="失败原因">
|
||||
<template #default="scope">
|
||||
<el-popover
|
||||
placement="top-start"
|
||||
title="失败原因"
|
||||
:width="300"
|
||||
trigger="hover"
|
||||
:content="scope.row.err_msg"
|
||||
v-if="scope.row.progress === 101"
|
||||
>
|
||||
<template #reference>
|
||||
<el-text type="danger">{{ substr(scope.row.err_msg, 20) }}</el-text>
|
||||
</template>
|
||||
</el-popover>
|
||||
<span v-else>无</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="180">
|
||||
<template #default="scope">
|
||||
<el-popconfirm title="确定要删除当前记录吗?" @confirm="remove(scope.row, 'mj')">
|
||||
<template #reference>
|
||||
<el-button size="small" type="danger">删除</el-button>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-row>
|
||||
|
||||
<div class="pagination">
|
||||
<el-pagination v-if="data.mj.total > 0" background
|
||||
layout="total,prev, pager, next"
|
||||
:hide-on-single-page="true"
|
||||
v-model:current-page="data.mj.page"
|
||||
v-model:page-size="data.mj.pageSize"
|
||||
@current-change="fetchMjData()"
|
||||
:total="data.mj.total"/>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<el-empty v-else />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="Stable-Diffusion" name="sd" v-loading="data.sd.loading">
|
||||
<div class="handle-box">
|
||||
<el-input v-model.number="data.sd.query.username" placeholder="用户名" class="handle-input mr10"
|
||||
@keyup="search($event, 'sd')"></el-input>
|
||||
<el-input v-model="data.sd.query.prompt" placeholder="提示词" class="handle-input mr10"
|
||||
@keyup="search($event, 'sd')"></el-input>
|
||||
<el-date-picker
|
||||
v-model="data.sd.query.created_at"
|
||||
type="daterange"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
format="YYYY-MM-DD"
|
||||
value-format="YYYY-MM-DD"
|
||||
style="margin-right: 10px;width: 200px; position: relative;top:3px;"
|
||||
/>
|
||||
<el-button type="primary" :icon="Search" @click="fetchSdData">搜索</el-button>
|
||||
</div>
|
||||
|
||||
<div v-if="data.sd.items.length > 0">
|
||||
<el-row>
|
||||
<el-table :data="data.sd.items" :row-key="row => row.id" table-layout="auto">
|
||||
<el-table-column prop="user_id" label="用户ID"/>
|
||||
<el-table-column prop="progress" label="任务进度">
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.progress <= 100">{{scope.row.progress}}%</span>
|
||||
<el-tag v-else type="danger">已失败</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="power" label="消耗算力"/>
|
||||
<el-table-column label="结果图片">
|
||||
<template #default="scope">
|
||||
<el-button size="small" type="success" @click="showImage(scope.row.img_url)" v-if="scope.row.img_url !== ''" plain>预览图片</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="提示词">
|
||||
<template #default="scope">
|
||||
<el-popover
|
||||
placement="top-start"
|
||||
title="绘画提示词"
|
||||
:width="300"
|
||||
trigger="hover"
|
||||
:content="scope.row.prompt"
|
||||
>
|
||||
<template #reference>
|
||||
<span>{{ substr(scope.row.prompt, 20) }}</span>
|
||||
</template>
|
||||
</el-popover>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建时间">
|
||||
<template #default="scope">
|
||||
<span>{{ dateFormat(scope.row['created_at']) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="失败原因">
|
||||
<template #default="scope">
|
||||
<el-popover
|
||||
placement="top-start"
|
||||
title="失败原因"
|
||||
:width="300"
|
||||
trigger="hover"
|
||||
:content="scope.row.err_msg"
|
||||
v-if="scope.row.progress === 101"
|
||||
>
|
||||
<template #reference>
|
||||
<el-text type="danger">{{ substr(scope.row.err_msg, 20) }}</el-text>
|
||||
</template>
|
||||
</el-popover>
|
||||
<span v-else>无</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="180">
|
||||
<template #default="scope">
|
||||
<el-popconfirm title="确定要删除当前记录吗?" @confirm="remove(scope.row, 'sd')">
|
||||
<template #reference>
|
||||
<el-button size="small" type="danger">删除</el-button>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-row>
|
||||
|
||||
<div class="pagination">
|
||||
<el-pagination v-if="data.sd.total > 0" background
|
||||
layout="total,prev, pager, next"
|
||||
:hide-on-single-page="true"
|
||||
v-model:current-page="data.sd.page"
|
||||
v-model:page-size="data.sd.pageSize"
|
||||
@current-change="fetchSdData()"
|
||||
:total="data.sd.total"/>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<el-empty v-else />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="DALL-E" name="dall">
|
||||
<div class="handle-box">
|
||||
<el-input v-model.number="data.dall.query.username" placeholder="用户名" class="handle-input mr10"
|
||||
@keyup="search($event,'dall')"></el-input>
|
||||
<el-input v-model="data.dall.query.prompt" placeholder="提示词" class="handle-input mr10"
|
||||
@keyup="search($event, 'dall')"></el-input>
|
||||
<el-date-picker
|
||||
v-model="data.dall.query.created_at"
|
||||
type="daterange"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
format="YYYY-MM-DD"
|
||||
value-format="YYYY-MM-DD"
|
||||
style="margin-right: 10px;width: 200px; position: relative;top:3px;"
|
||||
/>
|
||||
<el-button type="primary" :icon="Search" @click="fetchDallData">搜索</el-button>
|
||||
</div>
|
||||
|
||||
<div v-if="data.dall.items.length > 0">
|
||||
<el-row>
|
||||
<el-table :data="data.dall.items" :row-key="row => row.id" table-layout="auto">
|
||||
<el-table-column prop="user_id" label="用户ID"/>
|
||||
<el-table-column prop="progress" label="任务进度">
|
||||
<template #default="scope">
|
||||
<span v-if="scope.row.progress <= 100">{{scope.row.progress}}%</span>
|
||||
<el-tag v-else type="danger">已失败</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="power" label="消耗算力"/>
|
||||
<el-table-column label="结果图片">
|
||||
<template #default="scope">
|
||||
<el-button size="small" type="success" @click="showImage(scope.row.img_url)" v-if="scope.row.img_url !== ''" plain>预览图片</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="提示词">
|
||||
<template #default="scope">
|
||||
<el-popover
|
||||
placement="top-start"
|
||||
title="绘画提示词"
|
||||
:width="300"
|
||||
trigger="hover"
|
||||
:content="scope.row.prompt"
|
||||
>
|
||||
<template #reference>
|
||||
<span>{{ substr(scope.row.prompt, 20) }}</span>
|
||||
</template>
|
||||
</el-popover>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="创建时间">
|
||||
<template #default="scope">
|
||||
<span>{{ dateFormat(scope.row['created_at']) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="失败原因">
|
||||
<template #default="scope">
|
||||
<el-popover
|
||||
placement="top-start"
|
||||
title="失败原因"
|
||||
:width="300"
|
||||
trigger="hover"
|
||||
:content="scope.row.err_msg"
|
||||
v-if="scope.row.progress === 101"
|
||||
>
|
||||
<template #reference>
|
||||
<el-text type="danger">{{ substr(scope.row.err_msg, 20) }}</el-text>
|
||||
</template>
|
||||
</el-popover>
|
||||
<span v-else>无</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="180">
|
||||
<template #default="scope">
|
||||
<el-popconfirm title="确定要删除当前记录吗?" @confirm="remove(scope.row, 'dall')">
|
||||
<template #reference>
|
||||
<el-button size="small" type="danger">删除</el-button>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-row>
|
||||
|
||||
<div class="pagination">
|
||||
<el-pagination v-if="data.dall.total > 0" background
|
||||
layout="total,prev, pager, next"
|
||||
:hide-on-single-page="true"
|
||||
v-model:current-page="data.dall.page"
|
||||
v-model:page-size="data.dall.pageSize"
|
||||
@current-change="fetchDallData()"
|
||||
:total="data.dall.total"/>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<el-empty v-else />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
|
||||
|
||||
<el-dialog
|
||||
v-model="showImageDialog"
|
||||
title="图片预览"
|
||||
>
|
||||
<el-image
|
||||
:src="imgURL"
|
||||
:zoom-rate="1.2"
|
||||
:max-scale="7"
|
||||
:min-scale="0.2"
|
||||
:preview-src-list="[imgURL]"
|
||||
:initial-index="0"
|
||||
fit="cover"
|
||||
/>
|
||||
</el-dialog>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {onMounted, ref} from "vue";
|
||||
import {httpGet, httpPost} from "@/utils/http";
|
||||
import {ElMessage} from "element-plus";
|
||||
import {dateFormat, substr} from "@/utils/libs";
|
||||
import {Search} from "@element-plus/icons-vue";
|
||||
|
||||
// 变量定义
|
||||
const data = ref({
|
||||
"mj": {
|
||||
items: [],
|
||||
query: {prompt: "", username: "", created_at: [], page: 1, page_size: 15},
|
||||
total: 0,
|
||||
page: 1,
|
||||
pageSize: 15,
|
||||
loading: true
|
||||
},
|
||||
"sd": {
|
||||
items: [],
|
||||
query: {prompt: "", username: "", created_at: [], page: 1, page_size: 15},
|
||||
total: 0,
|
||||
page: 1,
|
||||
pageSize: 15,
|
||||
loading: true
|
||||
},
|
||||
"dall": {
|
||||
items: [],
|
||||
query: {prompt: "", username: "", created_at: [], page: 1, page_size: 15},
|
||||
total: 0,
|
||||
page: 1,
|
||||
pageSize: 15,
|
||||
loading: true
|
||||
}
|
||||
})
|
||||
const activeName = ref("mj")
|
||||
const taskTypeTheme = {
|
||||
image: {text: "绘图", color: "#2185d0"},
|
||||
upscale: {text: "放大", color: "#f2711c" },
|
||||
variation: {text: "变换", color: "#00b5ad"},
|
||||
blend: {text: "融图", color: "#21ba45"},
|
||||
swapFace: {text: "换脸", color: "#a333c8"}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
fetchMjData()
|
||||
})
|
||||
|
||||
const handleChange = (tab) => {
|
||||
switch (tab) {
|
||||
case "mj":
|
||||
fetchMjData()
|
||||
break
|
||||
case "sd":
|
||||
fetchSdData()
|
||||
break
|
||||
case "dall":
|
||||
fetchDallData()
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// 搜索对话
|
||||
const search = (evt,tab) => {
|
||||
if (evt.keyCode === 13) {
|
||||
handleChange(tab)
|
||||
}
|
||||
}
|
||||
|
||||
// 获取数据
|
||||
const fetchMjData = () => {
|
||||
const d = data.value.mj
|
||||
d.query.page = d.page
|
||||
d.query.page_size = d.pageSize
|
||||
httpPost('/api/admin/image/list/mj', d.query).then((res) => {
|
||||
if (res.data) {
|
||||
d.items = res.data.items
|
||||
d.total = res.data.total
|
||||
d.page = res.data.page
|
||||
d.pageSize = res.data.page_size
|
||||
}
|
||||
d.loading = false
|
||||
}).catch(e => {
|
||||
ElMessage.error("获取数据失败:" + e.message);
|
||||
})
|
||||
}
|
||||
|
||||
const fetchSdData = () => {
|
||||
const d = data.value.sd
|
||||
d.query.page = d.page
|
||||
d.query.page_size = d.pageSize
|
||||
httpPost('/api/admin/image/list/sd', d.query).then((res) => {
|
||||
if (res.data) {
|
||||
d.items = res.data.items
|
||||
d.total = res.data.total
|
||||
d.page = res.data.page
|
||||
d.pageSize = res.data.page_size
|
||||
}
|
||||
d.loading = false
|
||||
}).catch(e => {
|
||||
ElMessage.error("获取数据失败:" + e.message);
|
||||
})
|
||||
}
|
||||
|
||||
const fetchDallData = () => {
|
||||
const d = data.value.dall
|
||||
d.query.page = d.page
|
||||
d.query.page_size = d.pageSize
|
||||
httpPost('/api/admin/image/list/dall', d.query).then((res) => {
|
||||
if (res.data) {
|
||||
d.items = res.data.items
|
||||
d.total = res.data.total
|
||||
d.page = res.data.page
|
||||
d.pageSize = res.data.page_size
|
||||
}
|
||||
d.loading = false
|
||||
}).catch(e => {
|
||||
ElMessage.error("获取数据失败:" + e.message);
|
||||
})
|
||||
}
|
||||
|
||||
const remove = function (row,tab) {
|
||||
httpGet('/api/admin/chat/remove?chat_id=' + row.chat_id).then(() => {
|
||||
ElMessage.success("删除成功!")
|
||||
}).catch((e) => {
|
||||
ElMessage.error("删除失败:" + e.message)
|
||||
})
|
||||
}
|
||||
|
||||
const showImageDialog = ref(false)
|
||||
const imgURL = ref('')
|
||||
const showImage = (url) => {
|
||||
showImageDialog.value = true
|
||||
imgURL.value = url
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
.chat-list {
|
||||
.handle-box {
|
||||
margin-bottom 20px
|
||||
.handle-input {
|
||||
max-width 150px;
|
||||
margin-right 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.opt-box {
|
||||
padding-bottom: 10px;
|
||||
display flex;
|
||||
justify-content flex-end
|
||||
|
||||
.el-icon {
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.el-select {
|
||||
width: 100%
|
||||
}
|
||||
|
||||
.pagination {
|
||||
padding 20px 0
|
||||
display flex
|
||||
justify-content right
|
||||
}
|
||||
|
||||
.chat-box {
|
||||
overflow hidden
|
||||
|
||||
// 变量定义
|
||||
--content-font-size: 16px;
|
||||
--content-color: #c1c1c1;
|
||||
|
||||
font-family: 'Microsoft YaHei', '微软雅黑', Arial, sans-serif;
|
||||
|
||||
.chat-line {
|
||||
// 隐藏滚动条
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 0;
|
||||
height: 0;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
font-size: 14px;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
Loading…
Reference in New Issue
Block a user