mirror of
https://github.com/yangjian102621/geekai.git
synced 2026-04-22 19:14:29 +08:00
acomplish replacing Vue-cli with Vite
This commit is contained in:
@@ -391,7 +391,7 @@ const remove = function (row) {
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
@import "@/assets/css/admin/form.styl";
|
||||
@import "../../assets/css/admin/form.styl";
|
||||
.model-list {
|
||||
|
||||
.handle-box {
|
||||
|
||||
@@ -4,10 +4,7 @@
|
||||
<div class="content-box" :class="{ 'content-collapse': sidebar.collapse }">
|
||||
<admin-header />
|
||||
<admin-tags />
|
||||
<div
|
||||
:class="'content ' + theme"
|
||||
:style="{ height: contentHeight + 'px' }"
|
||||
>
|
||||
<div :class="'content ' + theme" :style="{ height: contentHeight + 'px' }">
|
||||
<router-view v-slot="{ Component }">
|
||||
<transition name="move" mode="out-in">
|
||||
<keep-alive :include="tags.nameList">
|
||||
@@ -20,41 +17,41 @@
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import {useSidebarStore} from "@/store/sidebar";
|
||||
import {useTagsStore} from "@/store/tags";
|
||||
import AdminHeader from "@/components/admin/AdminHeader.vue";
|
||||
import AdminSidebar from "@/components/admin/AdminSidebar.vue";
|
||||
import AdminTags from "@/components/admin/AdminTags.vue";
|
||||
import {useRouter} from "vue-router";
|
||||
import {checkAdminSession} from "@/store/cache";
|
||||
import {ref, watch} from "vue";
|
||||
import {useSharedStore} from "@/store/sharedata";
|
||||
import AdminHeader from '@/components/admin/AdminHeader.vue'
|
||||
import AdminSidebar from '@/components/admin/AdminSidebar.vue'
|
||||
import AdminTags from '@/components/admin/AdminTags.vue'
|
||||
import { checkAdminSession } from '@/store/cache'
|
||||
import { useSharedStore } from '@/store/sharedata'
|
||||
import { useSidebarStore } from '@/store/sidebar'
|
||||
import { useTagsStore } from '@/store/tags'
|
||||
import { ref, watch } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
const sidebar = useSidebarStore();
|
||||
const tags = useTagsStore();
|
||||
const isLogin = ref(false);
|
||||
const contentHeight = window.innerHeight - 80;
|
||||
const store = useSharedStore();
|
||||
const theme = ref(store.theme);
|
||||
const sidebar = useSidebarStore()
|
||||
const tags = useTagsStore()
|
||||
const isLogin = ref(false)
|
||||
const contentHeight = window.innerHeight - 80
|
||||
const store = useSharedStore()
|
||||
const theme = ref(store.theme)
|
||||
|
||||
// 获取会话信息
|
||||
const router = useRouter();
|
||||
const router = useRouter()
|
||||
checkAdminSession()
|
||||
.then(() => {
|
||||
isLogin.value = true;
|
||||
isLogin.value = true
|
||||
})
|
||||
.catch(() => {
|
||||
router.replace("/admin/login");
|
||||
});
|
||||
router.replace('/admin/login')
|
||||
})
|
||||
|
||||
watch(
|
||||
() => store.theme,
|
||||
() => store.theme,
|
||||
(val) => {
|
||||
theme.value = val;
|
||||
theme.value = val
|
||||
}
|
||||
);
|
||||
)
|
||||
</script>
|
||||
|
||||
<style scoped lang="stylus">
|
||||
@import '@/assets/css/main.styl';
|
||||
<style lang="stylus" scoped>
|
||||
@import "../../assets/css/main.styl";
|
||||
</style>
|
||||
|
||||
@@ -133,7 +133,7 @@ const doLogin = function (verifyData) {
|
||||
background #8d4bbb
|
||||
// background-image url("~@/assets/img/transparent-bg.png")
|
||||
// background-repeat:repeat;
|
||||
background-image url("~@/assets/img/admin-login-bg.jpg")
|
||||
background-image url("@/assets/img/admin-login-bg.jpg")
|
||||
background-size cover
|
||||
background-position center
|
||||
background-repeat no-repeat
|
||||
|
||||
@@ -5,7 +5,13 @@
|
||||
</div>
|
||||
|
||||
<el-row>
|
||||
<el-table :data="items" :row-key="(row) => row.id" table-layout="auto" border style="width: 100%">
|
||||
<el-table
|
||||
:data="items"
|
||||
:row-key="(row) => row.id"
|
||||
table-layout="auto"
|
||||
border
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-table-column prop="name" label="菜单名称">
|
||||
<template #default="scope">
|
||||
<span class="sort" :data-id="scope.row.id">
|
||||
@@ -51,7 +57,12 @@
|
||||
<template #label>
|
||||
<div class="label-title">
|
||||
开放注册
|
||||
<el-tooltip effect="dark" content="可以填写 iconfont 图标名称也可以自己上传图片" raw-content placement="right">
|
||||
<el-tooltip
|
||||
effect="dark"
|
||||
content="可以填写 iconfont 图标名称也可以自己上传图片"
|
||||
raw-content
|
||||
placement="right"
|
||||
>
|
||||
<el-icon>
|
||||
<InfoFilled />
|
||||
</el-icon>
|
||||
@@ -89,49 +100,49 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { onMounted, reactive, ref } from "vue";
|
||||
import { httpGet, httpPost } from "@/utils/http";
|
||||
import { ElMessage } from "element-plus";
|
||||
import { dateFormat, removeArrayItem } from "@/utils/libs";
|
||||
import { InfoFilled, Plus, UploadFilled } from "@element-plus/icons-vue";
|
||||
import { Sortable } from "sortablejs";
|
||||
import Compressor from "compressorjs";
|
||||
import { httpGet, httpPost } from '@/utils/http'
|
||||
import { dateFormat, removeArrayItem } from '@/utils/libs'
|
||||
import { InfoFilled, Plus, UploadFilled } from '@element-plus/icons-vue'
|
||||
import Compressor from 'compressorjs'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { Sortable } from 'sortablejs'
|
||||
import { onMounted, reactive, ref } from 'vue'
|
||||
|
||||
// 变量定义
|
||||
const items = ref([]);
|
||||
const item = ref({});
|
||||
const showDialog = ref(false);
|
||||
const title = ref("");
|
||||
const items = ref([])
|
||||
const item = ref({})
|
||||
const showDialog = ref(false)
|
||||
const title = ref('')
|
||||
const rules = reactive({
|
||||
name: [{ required: true, message: "请输入菜单名称", trigger: "change" }],
|
||||
icon: [{ required: true, message: "请上传菜单图标", trigger: "change" }],
|
||||
url: [{ required: true, message: "请输入菜单地址", trigger: "change" }],
|
||||
});
|
||||
const loading = ref(true);
|
||||
const formRef = ref(null);
|
||||
name: [{ required: true, message: '请输入菜单名称', trigger: 'change' }],
|
||||
icon: [{ required: true, message: '请上传菜单图标', trigger: 'change' }],
|
||||
url: [{ required: true, message: '请输入菜单地址', trigger: 'change' }],
|
||||
})
|
||||
const loading = ref(true)
|
||||
const formRef = ref(null)
|
||||
|
||||
const fetchData = () => {
|
||||
// 获取数据
|
||||
httpGet("/api/admin/menu/list")
|
||||
httpGet('/api/admin/menu/list')
|
||||
.then((res) => {
|
||||
if (res.data) {
|
||||
// 初始化数据
|
||||
const arr = res.data;
|
||||
const arr = res.data
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
arr[i].last_used_at = dateFormat(arr[i].last_used_at);
|
||||
arr[i].last_used_at = dateFormat(arr[i].last_used_at)
|
||||
}
|
||||
items.value = arr;
|
||||
items.value = arr
|
||||
}
|
||||
loading.value = false;
|
||||
loading.value = false
|
||||
})
|
||||
.catch(() => {
|
||||
ElMessage.error("获取数据失败");
|
||||
});
|
||||
};
|
||||
ElMessage.error('获取数据失败')
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
const drawBodyWrapper = document.querySelector(".el-table__body tbody");
|
||||
fetchData();
|
||||
const drawBodyWrapper = document.querySelector('.el-table__body tbody')
|
||||
fetchData()
|
||||
|
||||
// 初始化拖动排序插件
|
||||
Sortable.create(drawBodyWrapper, {
|
||||
@@ -139,80 +150,82 @@ onMounted(() => {
|
||||
animation: 500,
|
||||
onEnd({ newIndex, oldIndex, from }) {
|
||||
if (oldIndex === newIndex) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
|
||||
const sortedData = Array.from(from.children).map((row) => row.querySelector(".sort").getAttribute("data-id"));
|
||||
const ids = [];
|
||||
const sorts = [];
|
||||
const sortedData = Array.from(from.children).map((row) =>
|
||||
row.querySelector('.sort').getAttribute('data-id')
|
||||
)
|
||||
const ids = []
|
||||
const sorts = []
|
||||
sortedData.forEach((id, index) => {
|
||||
ids.push(parseInt(id));
|
||||
sorts.push(index + 1);
|
||||
items.value[index].sort_num = index + 1;
|
||||
});
|
||||
ids.push(parseInt(id))
|
||||
sorts.push(index + 1)
|
||||
items.value[index].sort_num = index + 1
|
||||
})
|
||||
|
||||
httpPost("/api/admin/menu/sort", { ids: ids, sorts: sorts }).catch((e) => {
|
||||
ElMessage.error("排序失败:" + e.message);
|
||||
});
|
||||
httpPost('/api/admin/menu/sort', { ids: ids, sorts: sorts }).catch((e) => {
|
||||
ElMessage.error('排序失败:' + e.message)
|
||||
})
|
||||
},
|
||||
});
|
||||
});
|
||||
})
|
||||
})
|
||||
|
||||
const add = function () {
|
||||
title.value = "新增菜单";
|
||||
showDialog.value = true;
|
||||
item.value = {};
|
||||
};
|
||||
title.value = '新增菜单'
|
||||
showDialog.value = true
|
||||
item.value = {}
|
||||
}
|
||||
|
||||
const edit = function (row) {
|
||||
title.value = "修改菜单";
|
||||
showDialog.value = true;
|
||||
item.value = row;
|
||||
};
|
||||
title.value = '修改菜单'
|
||||
showDialog.value = true
|
||||
item.value = row
|
||||
}
|
||||
|
||||
const save = function () {
|
||||
formRef.value.validate((valid) => {
|
||||
if (valid) {
|
||||
showDialog.value = false;
|
||||
showDialog.value = false
|
||||
if (!item.value.id) {
|
||||
item.value.sort_num = items.value.length + 1;
|
||||
item.value.sort_num = items.value.length + 1
|
||||
}
|
||||
httpPost("/api/admin/menu/save", item.value)
|
||||
httpPost('/api/admin/menu/save', item.value)
|
||||
.then(() => {
|
||||
ElMessage.success("操作成功!");
|
||||
fetchData();
|
||||
ElMessage.success('操作成功!')
|
||||
fetchData()
|
||||
})
|
||||
.catch((e) => {
|
||||
ElMessage.error("操作失败," + e.message);
|
||||
});
|
||||
ElMessage.error('操作失败,' + e.message)
|
||||
})
|
||||
} else {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
});
|
||||
};
|
||||
})
|
||||
}
|
||||
|
||||
const enable = (row) => {
|
||||
httpPost("/api/admin/menu/enable", { id: row.id, enabled: row.enabled })
|
||||
httpPost('/api/admin/menu/enable', { id: row.id, enabled: row.enabled })
|
||||
.then(() => {
|
||||
ElMessage.success("操作成功!");
|
||||
ElMessage.success('操作成功!')
|
||||
})
|
||||
.catch((e) => {
|
||||
ElMessage.error("操作失败:" + e.message);
|
||||
});
|
||||
};
|
||||
ElMessage.error('操作失败:' + e.message)
|
||||
})
|
||||
}
|
||||
|
||||
const remove = function (row) {
|
||||
httpGet("/api/admin/menu/remove?id=" + row.id)
|
||||
httpGet('/api/admin/menu/remove?id=' + row.id)
|
||||
.then(() => {
|
||||
ElMessage.success("删除成功!");
|
||||
ElMessage.success('删除成功!')
|
||||
items.value = removeArrayItem(items.value, row, (v1, v2) => {
|
||||
return v1.id === v2.id;
|
||||
});
|
||||
return v1.id === v2.id
|
||||
})
|
||||
})
|
||||
.catch((e) => {
|
||||
ElMessage.error("删除失败:" + e.message);
|
||||
});
|
||||
};
|
||||
ElMessage.error('删除失败:' + e.message)
|
||||
})
|
||||
}
|
||||
|
||||
// 图片上传
|
||||
const uploadImg = (file) => {
|
||||
@@ -220,28 +233,28 @@ const uploadImg = (file) => {
|
||||
new Compressor(file.file, {
|
||||
quality: 0.6,
|
||||
success(result) {
|
||||
const formData = new FormData();
|
||||
formData.append("file", result, result.name);
|
||||
const formData = new FormData()
|
||||
formData.append('file', result, result.name)
|
||||
// 执行上传操作
|
||||
httpPost("/api/admin/upload", formData)
|
||||
httpPost('/api/admin/upload', formData)
|
||||
.then((res) => {
|
||||
item.value.icon = res.data.url;
|
||||
ElMessage.success("上传成功");
|
||||
item.value.icon = res.data.url
|
||||
ElMessage.success('上传成功')
|
||||
})
|
||||
.catch((e) => {
|
||||
ElMessage.error("上传失败:" + e.message);
|
||||
});
|
||||
ElMessage.error('上传失败:' + e.message)
|
||||
})
|
||||
},
|
||||
error(e) {
|
||||
ElMessage.error("上传失败:" + e.message);
|
||||
ElMessage.error('上传失败:' + e.message)
|
||||
},
|
||||
});
|
||||
};
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="stylus">
|
||||
@import "@/assets/css/admin/form.styl"
|
||||
@import "@/assets/css/main.styl"
|
||||
<style lang="stylus" scoped>
|
||||
@import "../../assets/css/admin/form.styl"
|
||||
@import "../../assets/css/main.styl"
|
||||
.menu {
|
||||
|
||||
.handle-box {
|
||||
|
||||
@@ -567,38 +567,34 @@
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
|
||||
<el-tab-pane label="修复数据" name="fixData">
|
||||
<!-- <el-tab-pane label="修复数据" name="fixData">
|
||||
<div class="container">
|
||||
<p class="text">
|
||||
有些版本升级的时候更新了数据库的结构,比如字段名字改了,需要把之前的字段的值转移到其他字段,这些无法通过简单的
|
||||
SQL 语句可以实现的,需要手动写程序修正数据。
|
||||
</p>
|
||||
|
||||
<!-- <p class="text">当前版本 v4.1.4 需要修正用户数据,增加了 mobile 和 email 字段,需要把之前用手机号或者邮箱注册的用户的 username 字段数据初始化到 mobile 或者 email 字段。另外,需要把订单的支付渠道从名字称修正为 key。</p>-->
|
||||
|
||||
<!-- <el-text type="danger">请注意:在修复数据前,请先备份好数据库,以免数据丢失!</el-text>-->
|
||||
|
||||
<div class="mt-3">
|
||||
<el-button type="primary" @click="fixData">立即修复</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tab-pane> -->
|
||||
</el-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { onMounted, reactive, ref } from 'vue'
|
||||
import { httpGet, httpPost } from '@/utils/http'
|
||||
import Compressor from 'compressorjs'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { CloseBold, InfoFilled, Select, UploadFilled } from '@element-plus/icons-vue'
|
||||
import MdEditor from 'md-editor-v3'
|
||||
import 'md-editor-v3/lib/style.css'
|
||||
import Menu from '@/views/admin/Menu.vue'
|
||||
import { copyObj, dateFormat } from '@/utils/libs'
|
||||
import ItemsInput from '@/components/ui/ItemsInput.vue'
|
||||
import { useSharedStore } from '@/store/sharedata'
|
||||
import { httpGet, httpPost } from '@/utils/http'
|
||||
import { copyObj, dateFormat } from '@/utils/libs'
|
||||
import Menu from '@/views/admin/Menu.vue'
|
||||
import { CloseBold, InfoFilled, Select, UploadFilled } from '@element-plus/icons-vue'
|
||||
import Compressor from 'compressorjs'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import MdEditor from 'md-editor-v3'
|
||||
import 'md-editor-v3/lib/style.css'
|
||||
import { onMounted, reactive, ref } from 'vue'
|
||||
|
||||
const activeName = ref('basic')
|
||||
const system = ref({ models: [] })
|
||||
@@ -826,29 +822,29 @@ const onUploadImg = (files, callback) => {
|
||||
})
|
||||
}
|
||||
|
||||
const fixData = () => {
|
||||
ElMessageBox.confirm('在修复数据前,请先备份好数据库,以免数据丢失!是否继续操作?', '警告', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
}).then(() => {
|
||||
loading.value = true
|
||||
httpGet('/api/admin/config/fixData')
|
||||
.then(() => {
|
||||
ElMessage.success('数据修复成功')
|
||||
loading.value = false
|
||||
})
|
||||
.catch((e) => {
|
||||
loading.value = false
|
||||
ElMessage.error('数据修复失败:' + e.message)
|
||||
})
|
||||
})
|
||||
}
|
||||
// const fixData = () => {
|
||||
// ElMessageBox.confirm('在修复数据前,请先备份好数据库,以免数据丢失!是否继续操作?', '警告', {
|
||||
// confirmButtonText: '确定',
|
||||
// cancelButtonText: '取消',
|
||||
// type: 'warning',
|
||||
// }).then(() => {
|
||||
// loading.value = true
|
||||
// httpGet('/api/admin/config/fixData')
|
||||
// .then(() => {
|
||||
// ElMessage.success('数据修复成功')
|
||||
// loading.value = false
|
||||
// })
|
||||
// .catch((e) => {
|
||||
// loading.value = false
|
||||
// ElMessage.error('数据修复失败:' + e.message)
|
||||
// })
|
||||
// })
|
||||
// }
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
@import "@/assets/css/admin/form.styl"
|
||||
@import "@/assets/css/main.styl"
|
||||
@import '../../assets/css/admin/form.styl'
|
||||
@import '../../assets/css/main.styl'
|
||||
.system-config {
|
||||
display flex
|
||||
justify-content center
|
||||
|
||||
@@ -186,7 +186,7 @@
|
||||
class="chat-dialog"
|
||||
style="--el-dialog-width: 60%"
|
||||
>
|
||||
<div class="chat-box chat-page">
|
||||
<div class="chat-box chat-page p-2">
|
||||
<div v-for="item in messages" :key="item.id">
|
||||
<chat-prompt v-if="item.type === 'prompt'" :data="item" />
|
||||
<chat-reply v-else-if="item.type === 'reply'" :read-only="true" :data="item" />
|
||||
@@ -206,6 +206,8 @@ import { Search } from '@element-plus/icons-vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import hl from 'highlight.js'
|
||||
import 'highlight.js/styles/a11y-dark.css'
|
||||
import MarkdownIt from 'markdown-it'
|
||||
import mathjaxPlugin from 'markdown-it-mathjax3'
|
||||
import { onMounted, ref } from 'vue'
|
||||
|
||||
// 变量定义
|
||||
@@ -316,8 +318,7 @@ const removeMessage = function (row) {
|
||||
})
|
||||
}
|
||||
|
||||
const mathjaxPlugin = require('markdown-it-mathjax3')
|
||||
const md = require('markdown-it')({
|
||||
const md = MarkdownIt({
|
||||
breaks: true,
|
||||
html: true,
|
||||
linkify: true,
|
||||
|
||||
@@ -1,10 +1,28 @@
|
||||
<template>
|
||||
<div class="container media-page">
|
||||
<el-tabs v-model="activeName" @tab-change="handleChange">
|
||||
<el-tab-pane v-for="media in mediaTypes" :key="media.name" :label="media.label" :name="media.name" v-loading="data[media.name].loading">
|
||||
<el-tab-pane
|
||||
v-for="media in mediaTypes"
|
||||
:key="media.name"
|
||||
:label="media.label"
|
||||
:name="media.name"
|
||||
v-loading="data[media.name].loading"
|
||||
>
|
||||
<div class="handle-box">
|
||||
<el-input v-model="data[media.name].query.username" 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-input
|
||||
v-model="data[media.name].query.username"
|
||||
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
|
||||
v-model="data[media.name].query.created_at"
|
||||
type="daterange"
|
||||
@@ -28,7 +46,10 @@
|
||||
<div class="duration">
|
||||
{{ formatTime(scope.row.duration) }}
|
||||
</div>
|
||||
<button class="play" @click="playMusic(scope.row)">
|
||||
<button
|
||||
class="play flex justify-center items-center"
|
||||
@click="playMusic(scope.row)"
|
||||
>
|
||||
<img src="/images/play.svg" alt="" />
|
||||
</button>
|
||||
</div>
|
||||
@@ -37,12 +58,27 @@
|
||||
<template #default="scope" v-if="media.previewComponent === 'VideoPreview'">
|
||||
<div class="container">
|
||||
<div v-if="scope.row.progress === 100">
|
||||
<video class="video" :src="replaceImg(scope.row.video_url)" preload="auto" loop="loop" muted="muted">您的浏览器不支持视频播放</video>
|
||||
<button class="play" @click="playVideo(scope.row)">
|
||||
<video
|
||||
class="video"
|
||||
:src="replaceImg(scope.row.video_url)"
|
||||
preload="auto"
|
||||
loop="loop"
|
||||
muted="muted"
|
||||
>
|
||||
您的浏览器不支持视频播放
|
||||
</video>
|
||||
<button
|
||||
class="play flex justify-center items-center"
|
||||
@click="playVideo(scope.row)"
|
||||
>
|
||||
<img src="/images/play.svg" alt="" />
|
||||
</button>
|
||||
</div>
|
||||
<el-image :src="scope.row.cover_url" fit="cover" v-else-if="scope.row.progress > 100" />
|
||||
<el-image
|
||||
:src="scope.row.cover_url"
|
||||
fit="cover"
|
||||
v-else-if="scope.row.progress > 100"
|
||||
/>
|
||||
<generating message="正在生成视频" v-else />
|
||||
</div>
|
||||
</template>
|
||||
@@ -59,13 +95,21 @@
|
||||
<el-table-column prop="play_times" label="播放次数" />
|
||||
<el-table-column label="歌词">
|
||||
<template #default="scope">
|
||||
<el-button size="small" type="primary" plain @click="showLyric(scope.row)">查看歌词</el-button>
|
||||
<el-button size="small" type="primary" plain @click="showLyric(scope.row)"
|
||||
>查看歌词</el-button
|
||||
>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</template>
|
||||
<el-table-column label="提示词" v-if="media.previewComponent === 'VideoPreview'">
|
||||
<template #default="scope">
|
||||
<el-popover placement="top-start" title="提示词" :width="300" trigger="hover" :content="scope.row.prompt">
|
||||
<el-popover
|
||||
placement="top-start"
|
||||
title="提示词"
|
||||
:width="300"
|
||||
trigger="hover"
|
||||
:content="scope.row.prompt"
|
||||
>
|
||||
<template #reference>
|
||||
<span>{{ substr(scope.row.prompt, 20) }}</span>
|
||||
</template>
|
||||
@@ -74,7 +118,7 @@
|
||||
</el-table-column>
|
||||
<el-table-column label="创建时间">
|
||||
<template #default="scope">
|
||||
<span>{{ dateFormat(scope.row["created_at"]) }}</span>
|
||||
<span>{{ dateFormat(scope.row['created_at']) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="失败原因">
|
||||
@@ -96,7 +140,10 @@
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="180">
|
||||
<template #default="scope">
|
||||
<el-popconfirm title="确定要删除当前记录吗?" @confirm="remove(scope.row, media.name)">
|
||||
<el-popconfirm
|
||||
title="确定要删除当前记录吗?"
|
||||
@confirm="remove(scope.row, media.name)"
|
||||
>
|
||||
<template #reference>
|
||||
<el-button size="small" type="danger">删除</el-button>
|
||||
</template>
|
||||
@@ -123,13 +170,25 @@
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
<el-dialog v-model="showVideoDialog" title="视频预览">
|
||||
<video style="width: 100%; max-height: 90vh" :src="currentVideoUrl" preload="auto" :autoplay="true" loop="loop" muted="muted">
|
||||
<video
|
||||
style="width: 100%; max-height: 90vh"
|
||||
:src="currentVideoUrl"
|
||||
preload="auto"
|
||||
:autoplay="true"
|
||||
loop="loop"
|
||||
muted="muted"
|
||||
>
|
||||
您的浏览器不支持视频播放
|
||||
</video>
|
||||
</el-dialog>
|
||||
|
||||
<div class="music-player" v-if="showPlayer">
|
||||
<music-player :songs="playList" ref="playerRef" :show-close="true" @close="showPlayer = false" />
|
||||
<music-player
|
||||
:songs="playList"
|
||||
ref="playerRef"
|
||||
:show-close="true"
|
||||
@close="showPlayer = false"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<el-dialog v-model="showLyricDialog" title="歌词">
|
||||
@@ -139,18 +198,19 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { nextTick, onMounted, ref } from "vue";
|
||||
import { httpGet, httpPost } from "@/utils/http";
|
||||
import { ElMessage } from "element-plus";
|
||||
import { dateFormat, formatTime, replaceImg, substr } from "@/utils/libs";
|
||||
import { Search } from "@element-plus/icons-vue";
|
||||
import MusicPlayer from "@/components/MusicPlayer.vue";
|
||||
import Generating from "@/components/ui/Generating.vue";
|
||||
import MusicPlayer from '@/components/MusicPlayer.vue'
|
||||
import Generating from '@/components/ui/Generating.vue'
|
||||
import { httpGet, httpPost } from '@/utils/http'
|
||||
import { dateFormat, formatTime, replaceImg, substr } from '@/utils/libs'
|
||||
import { Search } from '@element-plus/icons-vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import MarkdownIt from 'markdown-it'
|
||||
import { nextTick, onMounted, ref } from 'vue'
|
||||
|
||||
const data = ref({
|
||||
suno: {
|
||||
items: [],
|
||||
query: { prompt: "", username: "", created_at: [], page: 1, page_size: 15 },
|
||||
query: { prompt: '', username: '', created_at: [], page: 1, page_size: 15 },
|
||||
total: 0,
|
||||
page: 1,
|
||||
pageSize: 10,
|
||||
@@ -158,7 +218,7 @@ const data = ref({
|
||||
},
|
||||
luma: {
|
||||
items: [],
|
||||
query: { prompt: "", username: "", created_at: [], page: 1, page_size: 15 },
|
||||
query: { prompt: '', username: '', created_at: [], page: 1, page_size: 15 },
|
||||
total: 0,
|
||||
page: 1,
|
||||
pageSize: 10,
|
||||
@@ -166,169 +226,169 @@ const data = ref({
|
||||
},
|
||||
keling: {
|
||||
items: [],
|
||||
query: { prompt: "", username: "", created_at: [], page: 1, page_size: 15 },
|
||||
query: { prompt: '', username: '', created_at: [], page: 1, page_size: 15 },
|
||||
total: 0,
|
||||
page: 1,
|
||||
pageSize: 10,
|
||||
loading: true,
|
||||
},
|
||||
});
|
||||
})
|
||||
|
||||
const mediaTypes = [
|
||||
{
|
||||
name: "suno",
|
||||
label: "Suno音乐",
|
||||
name: 'suno',
|
||||
label: 'Suno音乐',
|
||||
fetchData: () => fetchSunoData(),
|
||||
previewComponent: "MusicPreview",
|
||||
previewComponent: 'MusicPreview',
|
||||
},
|
||||
{
|
||||
name: "luma",
|
||||
label: "Luma视频",
|
||||
name: 'luma',
|
||||
label: 'Luma视频',
|
||||
fetchData: () => fetchLumaData(),
|
||||
previewComponent: "VideoPreview",
|
||||
previewComponent: 'VideoPreview',
|
||||
},
|
||||
{
|
||||
name: "keling",
|
||||
label: "可灵视频",
|
||||
name: 'keling',
|
||||
label: '可灵视频',
|
||||
fetchData: () => fetchKelingData(),
|
||||
previewComponent: "VideoPreview",
|
||||
previewComponent: 'VideoPreview',
|
||||
},
|
||||
];
|
||||
const activeName = ref("suno");
|
||||
const playList = ref([]);
|
||||
const playerRef = ref(null);
|
||||
const showPlayer = ref(false);
|
||||
const showLyricDialog = ref(false);
|
||||
const lyrics = ref("");
|
||||
const showVideoDialog = ref(false);
|
||||
const currentVideoUrl = ref("");
|
||||
]
|
||||
const activeName = ref('suno')
|
||||
const playList = ref([])
|
||||
const playerRef = ref(null)
|
||||
const showPlayer = ref(false)
|
||||
const showLyricDialog = ref(false)
|
||||
const lyrics = ref('')
|
||||
const showVideoDialog = ref(false)
|
||||
const currentVideoUrl = ref('')
|
||||
|
||||
onMounted(() => {
|
||||
fetchSunoData();
|
||||
});
|
||||
fetchSunoData()
|
||||
})
|
||||
|
||||
const handleChange = (tab) => {
|
||||
switch (tab) {
|
||||
case "suno":
|
||||
fetchSunoData();
|
||||
break;
|
||||
case "luma":
|
||||
fetchLumaData();
|
||||
break;
|
||||
case "keling":
|
||||
fetchKelingData();
|
||||
break;
|
||||
case 'suno':
|
||||
fetchSunoData()
|
||||
break
|
||||
case 'luma':
|
||||
fetchLumaData()
|
||||
break
|
||||
case 'keling':
|
||||
fetchKelingData()
|
||||
break
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// 搜索对话
|
||||
const search = (evt, tab) => {
|
||||
if (evt.keyCode === 13) {
|
||||
handleChange(tab);
|
||||
handleChange(tab)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// 获取数据
|
||||
const fetchSunoData = () => {
|
||||
const d = data.value.suno;
|
||||
d.query.page = d.page;
|
||||
d.query.page_size = d.pageSize;
|
||||
httpPost("/api/admin/media/suno", d.query)
|
||||
const d = data.value.suno
|
||||
d.query.page = d.page
|
||||
d.query.page_size = d.pageSize
|
||||
httpPost('/api/admin/media/suno', 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.items = res.data.items
|
||||
d.total = res.data.total
|
||||
d.page = res.data.page
|
||||
d.pageSize = res.data.page_size
|
||||
}
|
||||
d.loading = false;
|
||||
d.loading = false
|
||||
})
|
||||
.catch((e) => {
|
||||
ElMessage.error("获取数据失败:" + e.message);
|
||||
});
|
||||
};
|
||||
ElMessage.error('获取数据失败:' + e.message)
|
||||
})
|
||||
}
|
||||
|
||||
const fetchLumaData = () => {
|
||||
const d = data.value.luma;
|
||||
d.query.page = d.page;
|
||||
d.query.page_size = d.pageSize;
|
||||
d.query.type = "luma";
|
||||
httpPost("/api/admin/media/videos", d.query)
|
||||
const d = data.value.luma
|
||||
d.query.page = d.page
|
||||
d.query.page_size = d.pageSize
|
||||
d.query.type = 'luma'
|
||||
httpPost('/api/admin/media/videos', 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.items = res.data.items
|
||||
d.total = res.data.total
|
||||
d.page = res.data.page
|
||||
d.pageSize = res.data.page_size
|
||||
}
|
||||
d.loading = false;
|
||||
d.loading = false
|
||||
})
|
||||
.catch((e) => {
|
||||
ElMessage.error("获取数据失败:" + e.message);
|
||||
});
|
||||
};
|
||||
ElMessage.error('获取数据失败:' + e.message)
|
||||
})
|
||||
}
|
||||
const fetchKelingData = () => {
|
||||
const d = data.value.keling;
|
||||
d.query.page = d.page;
|
||||
d.query.page_size = d.pageSize;
|
||||
d.query.type = "keling";
|
||||
httpPost("/api/admin/media/videos", d.query)
|
||||
const d = data.value.keling
|
||||
d.query.page = d.page
|
||||
d.query.page_size = d.pageSize
|
||||
d.query.type = 'keling'
|
||||
httpPost('/api/admin/media/videos', 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.items = res.data.items
|
||||
d.total = res.data.total
|
||||
d.page = res.data.page
|
||||
d.pageSize = res.data.page_size
|
||||
}
|
||||
d.loading = false;
|
||||
d.loading = false
|
||||
})
|
||||
.catch((e) => {
|
||||
ElMessage.error("获取数据失败:" + e.message);
|
||||
});
|
||||
};
|
||||
ElMessage.error('获取数据失败:' + e.message)
|
||||
})
|
||||
}
|
||||
|
||||
const remove = function (row, tab) {
|
||||
httpGet(`/api/admin/media/remove?id=${row.id}&tab=${tab}`)
|
||||
.then(() => {
|
||||
ElMessage.success("删除成功!");
|
||||
handleChange(tab);
|
||||
ElMessage.success('删除成功!')
|
||||
handleChange(tab)
|
||||
})
|
||||
.catch((e) => {
|
||||
ElMessage.error("删除失败:" + e.message);
|
||||
ElMessage.error('删除失败:' + e.message)
|
||||
})
|
||||
.finally(() => {
|
||||
nextTick(() => {
|
||||
// data.value[tab].page = 1;
|
||||
// data.value[tab].pageSize = 10;
|
||||
const mediaType = mediaTypes.find((type) => type.name === tab);
|
||||
const mediaType = mediaTypes.find((type) => type.name === tab)
|
||||
if (mediaType && mediaType.fetchData) {
|
||||
mediaType.fetchData();
|
||||
mediaType.fetchData()
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const playMusic = (item) => {
|
||||
playList.value = [item];
|
||||
showPlayer.value = true;
|
||||
nextTick(() => playerRef.value.play());
|
||||
};
|
||||
playList.value = [item]
|
||||
showPlayer.value = true
|
||||
nextTick(() => playerRef.value.play())
|
||||
}
|
||||
|
||||
const playVideo = (item) => {
|
||||
currentVideoUrl.value = replaceImg(item.video_url);
|
||||
showVideoDialog.value = true;
|
||||
};
|
||||
currentVideoUrl.value = replaceImg(item.video_url)
|
||||
showVideoDialog.value = true
|
||||
}
|
||||
|
||||
const md = require("markdown-it")({
|
||||
const md = MarkdownIt({
|
||||
breaks: true,
|
||||
html: true,
|
||||
linkify: true,
|
||||
});
|
||||
})
|
||||
|
||||
const showLyric = (item) => {
|
||||
showLyricDialog.value = true;
|
||||
lyrics.value = md.render(item.prompt);
|
||||
};
|
||||
showLyricDialog.value = true
|
||||
lyrics.value = md.render(item.prompt)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
|
||||
Reference in New Issue
Block a user