mirror of
https://github.com/yangjian102621/geekai.git
synced 2025-11-30 13:26:08 +08:00
fixed bug for redis pool connection timeout
This commit is contained in:
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
- 功能新增:新增支持可灵生成视频。
|
- 功能新增:新增支持可灵生成视频。
|
||||||
- 功能优化:优化聊天页面代码块样式,优化公式的解析。
|
- 功能优化:优化聊天页面代码块样式,优化公式的解析。
|
||||||
|
- Bug 修复:优化 Redis 连接池配置,增加连接池超时时间,单核服务器报错 `redis: connection pool timeout`。
|
||||||
|
|
||||||
## v4.2.0
|
## v4.2.0
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import (
|
|||||||
"geekai/store/vo"
|
"geekai/store/vo"
|
||||||
"geekai/utils"
|
"geekai/utils"
|
||||||
"geekai/utils/resp"
|
"geekai/utils/resp"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
@@ -33,6 +34,7 @@ func NewMediaHandler(app *core.AppServer, db *gorm.DB, userService *service.User
|
|||||||
}
|
}
|
||||||
|
|
||||||
type mediaQuery struct {
|
type mediaQuery struct {
|
||||||
|
Type string `json:"type"` // 任务类型 luma, keling
|
||||||
Prompt string `json:"prompt"`
|
Prompt string `json:"prompt"`
|
||||||
Username string `json:"username"`
|
Username string `json:"username"`
|
||||||
CreatedAt []string `json:"created_at"`
|
CreatedAt []string `json:"created_at"`
|
||||||
@@ -84,15 +86,15 @@ func (h *MediaHandler) SunoList(c *gin.Context) {
|
|||||||
resp.SUCCESS(c, vo.NewPage(total, data.Page, data.PageSize, items))
|
resp.SUCCESS(c, vo.NewPage(total, data.Page, data.PageSize, items))
|
||||||
}
|
}
|
||||||
|
|
||||||
// LumaList Luma 视频任务列表
|
// Videos 视频任务列表
|
||||||
func (h *MediaHandler) LumaList(c *gin.Context) {
|
func (h *MediaHandler) Videos(c *gin.Context) {
|
||||||
var data mediaQuery
|
var data mediaQuery
|
||||||
if err := c.ShouldBindJSON(&data); err != nil {
|
if err := c.ShouldBindJSON(&data); err != nil {
|
||||||
resp.ERROR(c, types.InvalidArgs)
|
resp.ERROR(c, types.InvalidArgs)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
session := h.DB.Session(&gorm.Session{})
|
session := h.DB.Session(&gorm.Session{}).Where("type", data.Type)
|
||||||
if data.Username != "" {
|
if data.Username != "" {
|
||||||
var user model.User
|
var user model.User
|
||||||
err := h.DB.Where("username", data.Username).First(&user).Error
|
err := h.DB.Where("username", data.Username).First(&user).Error
|
||||||
@@ -154,6 +156,7 @@ func (h *MediaHandler) Remove(c *gin.Context) {
|
|||||||
fileURL = job.AudioURL
|
fileURL = job.AudioURL
|
||||||
break
|
break
|
||||||
case "luma":
|
case "luma":
|
||||||
|
case "keling":
|
||||||
var job model.VideoJob
|
var job model.VideoJob
|
||||||
if res := h.DB.Where("id", id).First(&job); res.Error != nil {
|
if res := h.DB.Where("id", id).First(&job); res.Error != nil {
|
||||||
resp.ERROR(c, "记录不存在")
|
resp.ERROR(c, "记录不存在")
|
||||||
|
|||||||
@@ -561,8 +561,8 @@ func main() {
|
|||||||
fx.Provide(admin.NewMediaHandler),
|
fx.Provide(admin.NewMediaHandler),
|
||||||
fx.Invoke(func(s *core.AppServer, h *admin.MediaHandler) {
|
fx.Invoke(func(s *core.AppServer, h *admin.MediaHandler) {
|
||||||
group := s.Engine.Group("/api/admin/media")
|
group := s.Engine.Group("/api/admin/media")
|
||||||
group.POST("/list/suno", h.SunoList)
|
group.POST("/suno", h.SunoList)
|
||||||
group.POST("/list/luma", h.LumaList)
|
group.POST("/videos", h.Videos)
|
||||||
group.GET("/remove", h.Remove)
|
group.GET("/remove", h.Remove)
|
||||||
}),
|
}),
|
||||||
fx.Provide(handler.NewRealtimeHandler),
|
fx.Provide(handler.NewRealtimeHandler),
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ func (s *Service) PushTask(task types.VideoTask) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Service) Run() {
|
func (s *Service) Run() {
|
||||||
// 将数据库中未提交的人物加载到队列
|
// 将数据库中未提交的任务加载到队列
|
||||||
var jobs []model.VideoJob
|
var jobs []model.VideoJob
|
||||||
s.db.Where("task_id", "").Where("progress", 0).Find(&jobs)
|
s.db.Where("task_id", "").Where("progress", 0).Find(&jobs)
|
||||||
for _, v := range jobs {
|
for _, v := range jobs {
|
||||||
|
|||||||
@@ -10,14 +10,18 @@ package store
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"geekai/core/types"
|
"geekai/core/types"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/go-redis/redis/v8"
|
"github.com/go-redis/redis/v8"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewRedisClient(config *types.AppConfig) (*redis.Client, error) {
|
func NewRedisClient(config *types.AppConfig) (*redis.Client, error) {
|
||||||
client := redis.NewClient(&redis.Options{
|
client := redis.NewClient(&redis.Options{
|
||||||
Addr: config.Redis.Url(),
|
Addr: config.Redis.Url(),
|
||||||
Password: config.Redis.Password,
|
Password: config.Redis.Password,
|
||||||
DB: config.Redis.DB,
|
DB: config.Redis.DB,
|
||||||
|
PoolSize: 20,
|
||||||
|
PoolTimeout: 5 * time.Second,
|
||||||
})
|
})
|
||||||
_, err := client.Ping(context.Background()).Result()
|
_, err := client.Ping(context.Background()).Result()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -5,11 +5,11 @@ arch=${2:-amd64}
|
|||||||
|
|
||||||
# build go api program
|
# build go api program
|
||||||
cd ../api
|
cd ../api
|
||||||
make clean $arch
|
#make clean $arch
|
||||||
|
|
||||||
# build web app
|
# build web app
|
||||||
cd ../web
|
cd ../web
|
||||||
npm run build
|
#npm run build
|
||||||
|
|
||||||
cd ../build
|
cd ../build
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ ProxyURL = ""
|
|||||||
MysqlDns = "root:mhSCk0NheGhmtsha@tcp(geekai-mysql:3306)/geekai_plus?charset=utf8mb4&collation=utf8mb4_unicode_ci&parseTime=True&loc=Local"
|
MysqlDns = "root:mhSCk0NheGhmtsha@tcp(geekai-mysql:3306)/geekai_plus?charset=utf8mb4&collation=utf8mb4_unicode_ci&parseTime=True&loc=Local"
|
||||||
StaticDir = "./static"
|
StaticDir = "./static"
|
||||||
StaticUrl = "/static"
|
StaticUrl = "/static"
|
||||||
TikaHost = "http://tika-geekai:9998"
|
TikaHost = "http://geekai-tika:9998"
|
||||||
|
|
||||||
[Session]
|
[Session]
|
||||||
SecretKey = "azyehq3ivunjhbntz78isj00i4hz2mt9xtddysfucxakadq4qbfrt0b7q3lnvg80"
|
SecretKey = "azyehq3ivunjhbntz78isj00i4hz2mt9xtddysfucxakadq4qbfrt0b7q3lnvg80"
|
||||||
@@ -68,14 +68,6 @@ TikaHost = "http://tika-geekai:9998"
|
|||||||
SubDir = ""
|
SubDir = ""
|
||||||
Domain = ""
|
Domain = ""
|
||||||
|
|
||||||
[XXLConfig] # xxl-job 配置,需要你部署 XXL-JOB 定时任务工具,用来定期清理未支付订单和清理过期 VIP,如果你没有启用支付服务,则该服务也无需启动
|
|
||||||
Enabled = false # 是否启用 XXL JOB 服务
|
|
||||||
ServerAddr = "http://geekai-xxl-job-admin:8080/xxl-job-admin" # xxl-job-admin 管理地址
|
|
||||||
ExecutorIp = "geekai-api" # 执行器 IP 地址
|
|
||||||
ExecutorPort = "9999" # 执行器服务端口
|
|
||||||
AccessToken = "GeekMaster" # 执行器 API 通信 token
|
|
||||||
RegistryKey = "chatgpt-plus" # 任务注册 key,需要与 xxl-job 管理后台配置一致,请不要随意改动
|
|
||||||
|
|
||||||
# 支付宝商户支付
|
# 支付宝商户支付
|
||||||
[AlipayConfig]
|
[AlipayConfig]
|
||||||
Enabled = false # 启用支付宝支付通道
|
Enabled = false # 启用支付宝支付通道
|
||||||
|
|||||||
@@ -37,34 +37,13 @@ services:
|
|||||||
timeout: 10s
|
timeout: 10s
|
||||||
retries: 5
|
retries: 5
|
||||||
|
|
||||||
# xxl-job-admin:
|
geekai-tika:
|
||||||
# container_name: geekai-xxl-job-admin
|
|
||||||
# image: registry.cn-shenzhen.aliyuncs.com/geekmaster/xxl-job-admin:2.4.0
|
|
||||||
# restart: always
|
|
||||||
# ports:
|
|
||||||
# - "8081:8080"
|
|
||||||
# environment:
|
|
||||||
# - PARAMS=--spring.config.location=/application.properties
|
|
||||||
# volumes:
|
|
||||||
# - ./logs/xxl-job:/data/applogs
|
|
||||||
# - ./conf/xxl-job/application.properties:/application.properties
|
|
||||||
|
|
||||||
tika:
|
|
||||||
image: registry.cn-shenzhen.aliyuncs.com/geekmaster/tika:latest
|
image: registry.cn-shenzhen.aliyuncs.com/geekmaster/tika:latest
|
||||||
container_name: geekai-tika
|
container_name: geekai-tika
|
||||||
restart: always
|
restart: always
|
||||||
ports:
|
ports:
|
||||||
- "9999:9998"
|
- "9999:9998"
|
||||||
|
|
||||||
# midjourney-proxy:
|
|
||||||
# image: registry.cn-shenzhen.aliyuncs.com/geekmaster/midjourney-proxy:2.6.2
|
|
||||||
# container_name: geekai-midjourney-proxy
|
|
||||||
# restart: always
|
|
||||||
# ports:
|
|
||||||
# - "8082:8080"
|
|
||||||
# volumes:
|
|
||||||
# - ./conf/mj-proxy:/home/spring/config
|
|
||||||
|
|
||||||
# 后端 API 程序
|
# 后端 API 程序
|
||||||
geekai-api:
|
geekai-api:
|
||||||
image: registry.cn-shenzhen.aliyuncs.com/geekmaster/geekai-plus-api:v4.2.0-amd64
|
image: registry.cn-shenzhen.aliyuncs.com/geekmaster/geekai-plus-api:v4.2.0-amd64
|
||||||
|
|||||||
25
web/package-lock.json
generated
25
web/package-lock.json
generated
@@ -23,7 +23,6 @@
|
|||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"markdown-it": "^13.0.1",
|
"markdown-it": "^13.0.1",
|
||||||
"markdown-it-emoji": "^2.0.0",
|
"markdown-it-emoji": "^2.0.0",
|
||||||
"markdown-it-katex": "^2.0.3",
|
|
||||||
"markdown-it-mathjax3": "^4.3.2",
|
"markdown-it-mathjax3": "^4.3.2",
|
||||||
"markmap-common": "^0.16.0",
|
"markmap-common": "^0.16.0",
|
||||||
"markmap-lib": "^0.16.1",
|
"markmap-lib": "^0.16.1",
|
||||||
@@ -8655,25 +8654,6 @@
|
|||||||
"resolved": "https://registry.npmmirror.com/markdown-it-emoji/-/markdown-it-emoji-2.0.2.tgz",
|
"resolved": "https://registry.npmmirror.com/markdown-it-emoji/-/markdown-it-emoji-2.0.2.tgz",
|
||||||
"integrity": "sha512-zLftSaNrKuYl0kR5zm4gxXjHaOI3FAOEaloKmRA5hijmJZvSjmxcokOLlzycb/HXlUFWzXqpIEoyEMCE4i9MvQ=="
|
"integrity": "sha512-zLftSaNrKuYl0kR5zm4gxXjHaOI3FAOEaloKmRA5hijmJZvSjmxcokOLlzycb/HXlUFWzXqpIEoyEMCE4i9MvQ=="
|
||||||
},
|
},
|
||||||
"node_modules/markdown-it-katex": {
|
|
||||||
"version": "2.0.3",
|
|
||||||
"resolved": "https://registry.npmmirror.com/markdown-it-katex/-/markdown-it-katex-2.0.3.tgz",
|
|
||||||
"integrity": "sha512-nUkkMtRWeg7OpdflamflE/Ho/pWl64Lk9wNBKOmaj33XkQdumhXAIYhI0WO03GeiycPCsxbmX536V5NEXpC3Ng==",
|
|
||||||
"dependencies": {
|
|
||||||
"katex": "^0.6.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/markdown-it-katex/node_modules/katex": {
|
|
||||||
"version": "0.6.0",
|
|
||||||
"resolved": "https://registry.npmmirror.com/katex/-/katex-0.6.0.tgz",
|
|
||||||
"integrity": "sha512-rS4mY3SvHYg5LtQV6RBcK0if7ur6plyEukAOV+jGGPqFImuzu8fHL6M752iBmRGoUyF0bhZbAPoezehn7xYksA==",
|
|
||||||
"dependencies": {
|
|
||||||
"match-at": "^0.1.0"
|
|
||||||
},
|
|
||||||
"bin": {
|
|
||||||
"katex": "cli.js"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/markdown-it-mathjax3": {
|
"node_modules/markdown-it-mathjax3": {
|
||||||
"version": "4.3.2",
|
"version": "4.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/markdown-it-mathjax3/-/markdown-it-mathjax3-4.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/markdown-it-mathjax3/-/markdown-it-mathjax3-4.3.2.tgz",
|
||||||
@@ -8915,11 +8895,6 @@
|
|||||||
"markmap-common": "*"
|
"markmap-common": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/match-at": {
|
|
||||||
"version": "0.1.1",
|
|
||||||
"resolved": "https://registry.npmmirror.com/match-at/-/match-at-0.1.1.tgz",
|
|
||||||
"integrity": "sha512-h4Yd392z9mST+dzc+yjuybOGFNOZjmXIPKWjxBd1Bb23r4SmDOsk2NYCU2BMUBGbSpZqwVsZYNq26QS3xfaT3Q=="
|
|
||||||
},
|
|
||||||
"node_modules/mathjax-full": {
|
"node_modules/mathjax-full": {
|
||||||
"version": "3.2.2",
|
"version": "3.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/mathjax-full/-/mathjax-full-3.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/mathjax-full/-/mathjax-full-3.2.2.tgz",
|
||||||
|
|||||||
@@ -1,28 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="container media-page">
|
<div class="container media-page">
|
||||||
<el-tabs v-model="activeName" @tab-change="handleChange">
|
<el-tabs v-model="activeName" @tab-change="handleChange">
|
||||||
<el-tab-pane
|
<el-tab-pane v-for="media in mediaTypes" :key="media.name" :label="media.label" :name="media.name" v-loading="data[media.name].loading">
|
||||||
v-for="media in mediaTypes"
|
|
||||||
:key="media.name"
|
|
||||||
:label="media.label"
|
|
||||||
:name="media.name"
|
|
||||||
v-loading="data[media.name].loading"
|
|
||||||
>
|
|
||||||
<div class="handle-box">
|
<div class="handle-box">
|
||||||
<el-input
|
<el-input v-model="data[media.name].query.username" placeholder="用户名" class="handle-input mr10" @keyup="search($event, media.name)" clearable />
|
||||||
v-model="data[media.name].query.username"
|
<el-input v-model="data[media.name].query.prompt" placeholder="提示词" class="handle-input mr10" @keyup="search($event, media.name)" clearable />
|
||||||
placeholder="用户名"
|
|
||||||
class="handle-input mr10"
|
|
||||||
@keyup="search($event, media.name)"
|
|
||||||
clearable
|
|
||||||
/>
|
|
||||||
<el-input
|
|
||||||
v-model="data[media.name].query.prompt"
|
|
||||||
placeholder="提示词"
|
|
||||||
class="handle-input mr10"
|
|
||||||
@keyup="search($event, media.name)"
|
|
||||||
clearable
|
|
||||||
/>
|
|
||||||
<el-date-picker
|
<el-date-picker
|
||||||
v-model="data[media.name].query.created_at"
|
v-model="data[media.name].query.created_at"
|
||||||
type="daterange"
|
type="daterange"
|
||||||
@@ -30,31 +12,17 @@
|
|||||||
end-placeholder="结束日期"
|
end-placeholder="结束日期"
|
||||||
format="YYYY-MM-DD"
|
format="YYYY-MM-DD"
|
||||||
value-format="YYYY-MM-DD"
|
value-format="YYYY-MM-DD"
|
||||||
style="
|
style="margin-right: 10px; width: 200px; position: relative; top: 3px"
|
||||||
margin-right: 10px;
|
|
||||||
width: 200px;
|
|
||||||
position: relative;
|
|
||||||
top: 3px;
|
|
||||||
"
|
|
||||||
/>
|
/>
|
||||||
<el-button type="primary" :icon="Search" @click="media.fetchData"
|
<el-button type="primary" :icon="Search" @click="media.fetchData">搜索</el-button>
|
||||||
>搜索</el-button
|
|
||||||
>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="data[media.name].items.length > 0">
|
<div v-if="data[media.name].items.length > 0">
|
||||||
<el-row>
|
<el-row>
|
||||||
<el-table
|
<el-table :data="data[media.name].items" :row-key="(row) => row.id" table-layout="auto">
|
||||||
:data="data[media.name].items"
|
|
||||||
:row-key="(row) => row.id"
|
|
||||||
table-layout="auto"
|
|
||||||
>
|
|
||||||
<el-table-column prop="user_id" label="用户ID" />
|
<el-table-column prop="user_id" label="用户ID" />
|
||||||
<el-table-column label="预览">
|
<el-table-column label="预览">
|
||||||
<template
|
<template #default="scope" v-if="media.previewComponent === 'MusicPreview'">
|
||||||
#default="scope"
|
|
||||||
v-if="media.previewComponent === 'MusicPreview'"
|
|
||||||
>
|
|
||||||
<div class="container" v-if="scope.row.cover_url">
|
<div class="container" v-if="scope.row.cover_url">
|
||||||
<el-image :src="scope.row.cover_url" fit="cover" />
|
<el-image :src="scope.row.cover_url" fit="cover" />
|
||||||
<div class="duration">
|
<div class="duration">
|
||||||
@@ -64,46 +32,24 @@
|
|||||||
<img src="/images/play.svg" alt="" />
|
<img src="/images/play.svg" alt="" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<el-image
|
<el-image v-else src="/images/failed.jpg" style="height: 90px" fit="cover" />
|
||||||
v-else
|
|
||||||
src="/images/failed.jpg"
|
|
||||||
style="height: 90px"
|
|
||||||
fit="cover"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
<template
|
<template #default="scope" v-if="media.previewComponent === 'VideoPreview'">
|
||||||
#default="scope"
|
|
||||||
v-if="media.previewComponent === 'VideoPreview'"
|
|
||||||
>
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div v-if="scope.row.progress === 100">
|
<div v-if="scope.row.progress === 100">
|
||||||
<video
|
<video class="video" :src="replaceImg(scope.row.video_url)" preload="auto" loop="loop" muted="muted">您的浏览器不支持视频播放</video>
|
||||||
class="video"
|
|
||||||
:src="replaceImg(scope.row.video_url)"
|
|
||||||
preload="auto"
|
|
||||||
loop="loop"
|
|
||||||
muted="muted"
|
|
||||||
>
|
|
||||||
您的浏览器不支持视频播放
|
|
||||||
</video>
|
|
||||||
<button class="play" @click="playVideo(scope.row)">
|
<button class="play" @click="playVideo(scope.row)">
|
||||||
<img src="/images/play.svg" alt="" />
|
<img src="/images/play.svg" alt="" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<el-image
|
<el-image :src="scope.row.cover_url" fit="cover" v-else-if="scope.row.progress > 100" />
|
||||||
:src="scope.row.cover_url"
|
|
||||||
fit="cover"
|
|
||||||
v-else-if="scope.row.progress > 100"
|
|
||||||
/>
|
|
||||||
<generating message="正在生成视频" v-else />
|
<generating message="正在生成视频" v-else />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="progress" label="任务进度">
|
<el-table-column prop="progress" label="任务进度">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span v-if="scope.row.progress <= 100"
|
<span v-if="scope.row.progress <= 100">{{ scope.row.progress }}%</span>
|
||||||
>{{ scope.row.progress }}%</span
|
|
||||||
>
|
|
||||||
<el-tag v-else type="danger">已失败</el-tag>
|
<el-tag v-else type="danger">已失败</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
@@ -113,28 +59,13 @@
|
|||||||
<el-table-column prop="play_times" label="播放次数" />
|
<el-table-column prop="play_times" label="播放次数" />
|
||||||
<el-table-column label="歌词">
|
<el-table-column label="歌词">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button
|
<el-button size="small" type="primary" plain @click="showLyric(scope.row)">查看歌词</el-button>
|
||||||
size="small"
|
|
||||||
type="primary"
|
|
||||||
plain
|
|
||||||
@click="showLyric(scope.row)"
|
|
||||||
>查看歌词</el-button
|
|
||||||
>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</template>
|
</template>
|
||||||
<el-table-column
|
<el-table-column label="提示词" v-if="media.previewComponent === 'VideoPreview'">
|
||||||
label="提示词"
|
|
||||||
v-if="media.previewComponent === 'VideoPreview'"
|
|
||||||
>
|
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-popover
|
<el-popover placement="top-start" title="提示词" :width="300" trigger="hover" :content="scope.row.prompt">
|
||||||
placement="top-start"
|
|
||||||
title="提示词"
|
|
||||||
:width="300"
|
|
||||||
trigger="hover"
|
|
||||||
:content="scope.row.prompt"
|
|
||||||
>
|
|
||||||
<template #reference>
|
<template #reference>
|
||||||
<span>{{ substr(scope.row.prompt, 20) }}</span>
|
<span>{{ substr(scope.row.prompt, 20) }}</span>
|
||||||
</template>
|
</template>
|
||||||
@@ -157,9 +88,7 @@
|
|||||||
:content="scope.row.err_msg"
|
:content="scope.row.err_msg"
|
||||||
>
|
>
|
||||||
<template #reference>
|
<template #reference>
|
||||||
<el-text type="danger">{{
|
<el-text type="danger">{{ substr(scope.row.err_msg, 20) }}</el-text>
|
||||||
substr(scope.row.err_msg, 20)
|
|
||||||
}}</el-text>
|
|
||||||
</template>
|
</template>
|
||||||
</el-popover>
|
</el-popover>
|
||||||
<span v-else>无</span>
|
<span v-else>无</span>
|
||||||
@@ -167,10 +96,7 @@
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="操作" width="180">
|
<el-table-column label="操作" width="180">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-popconfirm
|
<el-popconfirm title="确定要删除当前记录吗?" @confirm="remove(scope.row, media.name)">
|
||||||
title="确定要删除当前记录吗?"
|
|
||||||
@confirm="remove(scope.row, media.name)"
|
|
||||||
>
|
|
||||||
<template #reference>
|
<template #reference>
|
||||||
<el-button size="small" type="danger">删除</el-button>
|
<el-button size="small" type="danger">删除</el-button>
|
||||||
</template>
|
</template>
|
||||||
@@ -197,25 +123,13 @@
|
|||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
<el-dialog v-model="showVideoDialog" title="视频预览">
|
<el-dialog v-model="showVideoDialog" title="视频预览">
|
||||||
<video
|
<video style="width: 100%; max-height: 90vh" :src="currentVideoUrl" preload="auto" :autoplay="true" loop="loop" muted="muted">
|
||||||
style="width: 100%; max-height: 90vh"
|
|
||||||
:src="currentVideoUrl"
|
|
||||||
preload="auto"
|
|
||||||
:autoplay="true"
|
|
||||||
loop="loop"
|
|
||||||
muted="muted"
|
|
||||||
>
|
|
||||||
您的浏览器不支持视频播放
|
您的浏览器不支持视频播放
|
||||||
</video>
|
</video>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
<div class="music-player" v-if="showPlayer">
|
<div class="music-player" v-if="showPlayer">
|
||||||
<music-player
|
<music-player :songs="playList" ref="playerRef" :show-close="true" @close="showPlayer = false" />
|
||||||
:songs="playList"
|
|
||||||
ref="playerRef"
|
|
||||||
:show-close="true"
|
|
||||||
@close="showPlayer = false"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-dialog v-model="showLyricDialog" title="歌词">
|
<el-dialog v-model="showLyricDialog" title="歌词">
|
||||||
@@ -240,7 +154,7 @@ const data = ref({
|
|||||||
total: 0,
|
total: 0,
|
||||||
page: 1,
|
page: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
loading: true
|
loading: true,
|
||||||
},
|
},
|
||||||
luma: {
|
luma: {
|
||||||
items: [],
|
items: [],
|
||||||
@@ -248,7 +162,7 @@ const data = ref({
|
|||||||
total: 0,
|
total: 0,
|
||||||
page: 1,
|
page: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
loading: true
|
loading: true,
|
||||||
},
|
},
|
||||||
keling: {
|
keling: {
|
||||||
items: [],
|
items: [],
|
||||||
@@ -256,8 +170,8 @@ const data = ref({
|
|||||||
total: 0,
|
total: 0,
|
||||||
page: 1,
|
page: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
loading: true
|
loading: true,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const mediaTypes = [
|
const mediaTypes = [
|
||||||
@@ -265,20 +179,20 @@ const mediaTypes = [
|
|||||||
name: "suno",
|
name: "suno",
|
||||||
label: "Suno音乐",
|
label: "Suno音乐",
|
||||||
fetchData: () => fetchSunoData(),
|
fetchData: () => fetchSunoData(),
|
||||||
previewComponent: "MusicPreview"
|
previewComponent: "MusicPreview",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "luma",
|
name: "luma",
|
||||||
label: "Luma视频",
|
label: "Luma视频",
|
||||||
fetchData: () => fetchLumaData(),
|
fetchData: () => fetchLumaData(),
|
||||||
previewComponent: "VideoPreview"
|
previewComponent: "VideoPreview",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "keling",
|
name: "keling",
|
||||||
label: "可灵视频",
|
label: "可灵视频",
|
||||||
fetchData: () => fetchKelingData(),
|
fetchData: () => fetchKelingData(),
|
||||||
previewComponent: "VideoPreview"
|
previewComponent: "VideoPreview",
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
const activeName = ref("suno");
|
const activeName = ref("suno");
|
||||||
const playList = ref([]);
|
const playList = ref([]);
|
||||||
@@ -319,7 +233,7 @@ const fetchSunoData = () => {
|
|||||||
const d = data.value.suno;
|
const d = data.value.suno;
|
||||||
d.query.page = d.page;
|
d.query.page = d.page;
|
||||||
d.query.page_size = d.pageSize;
|
d.query.page_size = d.pageSize;
|
||||||
httpPost("/api/admin/media/list/suno", d.query)
|
httpPost("/api/admin/media/suno", d.query)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (res.data) {
|
if (res.data) {
|
||||||
d.items = res.data.items;
|
d.items = res.data.items;
|
||||||
@@ -338,7 +252,8 @@ const fetchLumaData = () => {
|
|||||||
const d = data.value.luma;
|
const d = data.value.luma;
|
||||||
d.query.page = d.page;
|
d.query.page = d.page;
|
||||||
d.query.page_size = d.pageSize;
|
d.query.page_size = d.pageSize;
|
||||||
httpPost("/api/admin/media/list/luma", d.query)
|
d.query.type = "luma";
|
||||||
|
httpPost("/api/admin/media/videos", d.query)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (res.data) {
|
if (res.data) {
|
||||||
d.items = res.data.items;
|
d.items = res.data.items;
|
||||||
@@ -356,7 +271,8 @@ const fetchKelingData = () => {
|
|||||||
const d = data.value.keling;
|
const d = data.value.keling;
|
||||||
d.query.page = d.page;
|
d.query.page = d.page;
|
||||||
d.query.page_size = d.pageSize;
|
d.query.page_size = d.pageSize;
|
||||||
httpPost("/api/admin/media/list/luma", d.query)
|
d.query.type = "keling";
|
||||||
|
httpPost("/api/admin/media/videos", d.query)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (res.data) {
|
if (res.data) {
|
||||||
d.items = res.data.items;
|
d.items = res.data.items;
|
||||||
@@ -406,7 +322,7 @@ const playVideo = (item) => {
|
|||||||
const md = require("markdown-it")({
|
const md = require("markdown-it")({
|
||||||
breaks: true,
|
breaks: true,
|
||||||
html: true,
|
html: true,
|
||||||
linkify: true
|
linkify: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
const showLyric = (item) => {
|
const showLyric = (item) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user