| @@ -0,0 +1,39 @@ | |||||
| import request from "@/utils/request.js"; | |||||
| /** | |||||
| * @description 获取密钥列表 | |||||
| * @param {*} (pageNum,pageSize) | |||||
| * @returns data | |||||
| */ | |||||
| export function keyListApi(pageNum, pageSize) { | |||||
| return request({ | |||||
| url: `/thirdPartyApi/page?pageNum=${pageNum}&pageSize=${pageSize}`, | |||||
| method: 'get' | |||||
| }) | |||||
| } | |||||
| /** | |||||
| * @description 根据id获取密钥详情 | |||||
| * @param {*} (id) | |||||
| * @returns data | |||||
| */ | |||||
| export function getKeyByIdApi(id) { | |||||
| return request({ | |||||
| url: `/thirdPartyApi/get?id=${id}`, | |||||
| method: 'get' | |||||
| }) | |||||
| } | |||||
| /** | |||||
| * @description 更改密钥状态 | |||||
| * @param {*} (id,status) | |||||
| * @returns data | |||||
| */ | |||||
| export function updateKeyStatusApi(id, status) { | |||||
| return request({ | |||||
| url: `/thirdPartyApi/updateStatus`, | |||||
| method: 'post', | |||||
| data: { id, status } | |||||
| }) | |||||
| } | |||||
| @@ -226,6 +226,11 @@ export default { | |||||
| keyMangage: { | keyMangage: { | ||||
| title: "Key", | title: "Key", | ||||
| list: "Key List", | |||||
| name: "Owner", | |||||
| status: "Status", | |||||
| operations: "Operations", | |||||
| check: "Check", | |||||
| }, | }, | ||||
| priceMangage: { | priceMangage: { | ||||
| @@ -225,6 +225,11 @@ export default { | |||||
| keyMangage: { | keyMangage: { | ||||
| title: "密钥管理", | title: "密钥管理", | ||||
| list: "密钥列表", | |||||
| name: "所属人", | |||||
| status: "密钥状态", | |||||
| operations: "操作", | |||||
| check: "查看", | |||||
| }, | }, | ||||
| priceMangage: { | priceMangage: { | ||||
| @@ -25,7 +25,7 @@ | |||||
| {{ $t("businessMangage.title") }} | {{ $t("businessMangage.title") }} | ||||
| </div> | </div> | ||||
| <div class="myRouter-item" @click="router.push('/keyCheck')"> | |||||
| <div class="myRouter-item" @click="router.push('/keyList')"> | |||||
| <div class="icon"> | <div class="icon"> | ||||
| <el-icon><i-ep-edit /></el-icon> | <el-icon><i-ep-edit /></el-icon> | ||||
| </div> | </div> | ||||
| @@ -37,6 +37,24 @@ export const constantRoutes: RouteRecordRaw[] = [ | |||||
| }, | }, | ||||
| ], | ], | ||||
| }, | }, | ||||
| { | |||||
| path: "/", | |||||
| component: Layout, | |||||
| redirect: "/keyList", | |||||
| children: [ | |||||
| { | |||||
| path: "keyList", | |||||
| component: () => import("@/views/mangage/keyList.vue"), | |||||
| name: "keyList", | |||||
| meta: { | |||||
| title: "keyList", | |||||
| icon: "homepage", | |||||
| affix: true, | |||||
| name: "keyMangage.list", | |||||
| }, | |||||
| }, | |||||
| ], | |||||
| }, | |||||
| { | { | ||||
| path: "/", | path: "/", | ||||
| component: Layout, | component: Layout, | ||||
| @@ -2,7 +2,6 @@ | |||||
| export {} | export {} | ||||
| declare global { | declare global { | ||||
| const EffectScope: typeof import('vue')['EffectScope'] | const EffectScope: typeof import('vue')['EffectScope'] | ||||
| const ElForm: typeof import('element-plus/es')['ElForm'] | |||||
| const ElMessage: typeof import('element-plus/es')['ElMessage'] | const ElMessage: typeof import('element-plus/es')['ElMessage'] | ||||
| const ElMessageBox: typeof import('element-plus/es')['ElMessageBox'] | const ElMessageBox: typeof import('element-plus/es')['ElMessageBox'] | ||||
| const asyncComputed: typeof import('@vueuse/core')['asyncComputed'] | const asyncComputed: typeof import('@vueuse/core')['asyncComputed'] | ||||
| @@ -271,7 +270,6 @@ import { UnwrapRef } from 'vue' | |||||
| declare module 'vue' { | declare module 'vue' { | ||||
| interface ComponentCustomProperties { | interface ComponentCustomProperties { | ||||
| readonly EffectScope: UnwrapRef<typeof import('vue')['EffectScope']> | readonly EffectScope: UnwrapRef<typeof import('vue')['EffectScope']> | ||||
| readonly ElForm: UnwrapRef<typeof import('element-plus/es')['ElForm']> | |||||
| readonly ElMessage: UnwrapRef<typeof import('element-plus/es')['ElMessage']> | readonly ElMessage: UnwrapRef<typeof import('element-plus/es')['ElMessage']> | ||||
| readonly ElMessageBox: UnwrapRef<typeof import('element-plus/es')['ElMessageBox']> | readonly ElMessageBox: UnwrapRef<typeof import('element-plus/es')['ElMessageBox']> | ||||
| readonly asyncComputed: UnwrapRef<typeof import('@vueuse/core')['asyncComputed']> | readonly asyncComputed: UnwrapRef<typeof import('@vueuse/core')['asyncComputed']> | ||||
| @@ -24,8 +24,11 @@ declare module '@vue/runtime-core' { | |||||
| ElInput: typeof import('element-plus/es')['ElInput'] | ElInput: typeof import('element-plus/es')['ElInput'] | ||||
| ElInputNumber: typeof import('element-plus/es')['ElInputNumber'] | ElInputNumber: typeof import('element-plus/es')['ElInputNumber'] | ||||
| ElOption: typeof import('element-plus/es')['ElOption'] | ElOption: typeof import('element-plus/es')['ElOption'] | ||||
| ElPagination: typeof import('element-plus/es')['ElPagination'] | |||||
| ElSelect: typeof import('element-plus/es')['ElSelect'] | ElSelect: typeof import('element-plus/es')['ElSelect'] | ||||
| ElSwitch: typeof import('element-plus/es')['ElSwitch'] | ElSwitch: typeof import('element-plus/es')['ElSwitch'] | ||||
| ElTable: typeof import('element-plus/es')['ElTable'] | |||||
| ElTableColumn: typeof import('element-plus/es')['ElTableColumn'] | |||||
| ElTooltip: typeof import('element-plus/es')['ElTooltip'] | ElTooltip: typeof import('element-plus/es')['ElTooltip'] | ||||
| ElUpload: typeof import('element-plus/es')['ElUpload'] | ElUpload: typeof import('element-plus/es')['ElUpload'] | ||||
| GithubCorner: typeof import('./../components/GithubCorner/index.vue')['default'] | GithubCorner: typeof import('./../components/GithubCorner/index.vue')['default'] | ||||
| @@ -1,24 +1,47 @@ | |||||
| <template> | <template> | ||||
| <div class="page flex justify-around"> | <div class="page flex justify-around"> | ||||
| <div class="card"> | <div class="card"> | ||||
| <div class="title">密钥管理</div> | |||||
| <div class="title">密钥详情</div> | |||||
| <div class="key"> | <div class="key"> | ||||
| <span class="text">密钥:{{ showCode }}</span> | |||||
| <span class="text">{{ $t("keyMangage.name") }}:{{ name }}</span> | |||||
| </div> | |||||
| <!-- appId --> | |||||
| <div class="key"> | |||||
| <span class="text">appId:{{ showCode }}</span> | |||||
| <span class="showOrHide" @click="showHideCode">{{ showText }}</span> | <span class="showOrHide" @click="showHideCode">{{ showText }}</span> | ||||
| <span v-if="showText == '隐藏'" class="copy" @click="copyKey" | |||||
| <span v-if="showText == '隐藏'" class="copy" @click="copyKey(showCode)" | |||||
| >复制</span | |||||
| > | |||||
| </div> | |||||
| <!-- appKey --> | |||||
| <div class="key"> | |||||
| <span class="text">appKey:{{ showCodeII }}</span> | |||||
| <span class="showOrHide" @click="showHideCodeII">{{ showTextII }}</span> | |||||
| <span | |||||
| v-if="showTextII == '隐藏'" | |||||
| class="copy" | |||||
| @click="copyKey(showCodeII)" | |||||
| >复制</span | |||||
| > | |||||
| </div> | |||||
| <!-- signKey --> | |||||
| <div class="key"> | |||||
| <span class="text">signKey:{{ showCodeIII }}</span> | |||||
| <span class="showOrHide" @click="showHideCodeIII(showCodeIII)">{{ | |||||
| showTextIII | |||||
| }}</span> | |||||
| <span v-if="showTextIII == '隐藏'" class="copy" @click="copyKey" | |||||
| >复制</span | >复制</span | ||||
| > | > | ||||
| </div> | </div> | ||||
| <div class="keyStatus"> | <div class="keyStatus"> | ||||
| <span class="text" | <span class="text" | ||||
| >密钥状态: | >密钥状态: | ||||
| <span v-if="keyStatus == 1" style="color: #ff0000">作废</span> | |||||
| <span v-else style="color: #36db43">正常</span> | |||||
| <span v-if="!keyStatus" style="color: #36db43">正常</span> | |||||
| <span v-else style="color: #ff0000">失效</span> | |||||
| </span> | </span> | ||||
| <span v-if="keyStatus == 1" class="fail" @click="changeStatus(2)" | |||||
| >恢复</span | |||||
| > | |||||
| <span v-if="keyStatus == 2" class="success" @click="changeStatus(1)" | |||||
| <span v-if="keyStatus" class="fail" @click="changeStatus(0)">恢复</span> | |||||
| <span v-if="!keyStatus" class="success" @click="changeStatus(1)" | |||||
| >作废</span | >作废</span | ||||
| > | > | ||||
| </div> | </div> | ||||
| @@ -36,40 +59,107 @@ import { useI18n } from "vue-i18n"; | |||||
| import { useRoute, useRouter } from "vue-router"; | import { useRoute, useRouter } from "vue-router"; | ||||
| import { getKeyByIdApi, updateKeyStatusApi } from "@/api_mangage/key"; | |||||
| const route = useRoute(); | const route = useRoute(); | ||||
| const router = useRouter(); | const router = useRouter(); | ||||
| const { locale } = useI18n(); | const { locale } = useI18n(); | ||||
| const lanChange = ref(locale); | const lanChange = ref(locale); | ||||
| const AccessToken = localStorage.getItem("AccessToken"); // 判断有没有登录 | const AccessToken = localStorage.getItem("AccessToken"); // 判断有没有登录 | ||||
| const key = ref("AE0DVHDWMDOURSBCAP"); | |||||
| const keyId = ref(""); | |||||
| const name = ref(""); | |||||
| const appId = ref(""); | |||||
| const hideCode = ref(""); | const hideCode = ref(""); | ||||
| const showCode = ref(""); | const showCode = ref(""); | ||||
| const showText = ref("查看"); | const showText = ref("查看"); | ||||
| const getKey = () => { | |||||
| const len = key.value.length; | |||||
| let code = ""; | |||||
| for (let index = 0; index < len; index++) { | |||||
| code += "*"; | |||||
| } | |||||
| hideCode.value = code; | |||||
| showCode.value = code; | |||||
| }; | |||||
| const showHideCode = () => { | const showHideCode = () => { | ||||
| if (showText.value == "查看") { | if (showText.value == "查看") { | ||||
| showText.value = "隐藏"; | showText.value = "隐藏"; | ||||
| showCode.value = key.value; | |||||
| showCode.value = appId.value; | |||||
| } else { | } else { | ||||
| showText.value = "查看"; | showText.value = "查看"; | ||||
| showCode.value = hideCode.value; | showCode.value = hideCode.value; | ||||
| } | } | ||||
| }; | }; | ||||
| const copyKey = () => { | |||||
| const appKey = ref(""); | |||||
| const hideCodeII = ref(""); | |||||
| const showCodeII = ref(""); | |||||
| const showTextII = ref("查看"); | |||||
| const showHideCodeII = () => { | |||||
| if (showTextII.value == "查看") { | |||||
| showTextII.value = "隐藏"; | |||||
| showCodeII.value = appKey.value; | |||||
| } else { | |||||
| showTextII.value = "查看"; | |||||
| showCodeII.value = hideCodeII.value; | |||||
| } | |||||
| }; | |||||
| const signKey = ref(""); | |||||
| const hideCodeIII = ref(""); | |||||
| const showCodeIII = ref(""); | |||||
| const showTextIII = ref("查看"); | |||||
| const showHideCodeIII = () => { | |||||
| if (showTextIII.value == "查看") { | |||||
| showTextIII.value = "隐藏"; | |||||
| showCodeIII.value = signKey.value; | |||||
| } else { | |||||
| showTextIII.value = "查看"; | |||||
| showCodeIII.value = hideCodeIII.value; | |||||
| } | |||||
| }; | |||||
| const getKeyFunc = async () => { | |||||
| const id = keyId.value; | |||||
| try { | |||||
| const res = await getKeyByIdApi(id); | |||||
| console.log(res, "res"); | |||||
| appId.value = res.data.appId; | |||||
| appKey.value = res.data.appKey; | |||||
| signKey.value = res.data.signKey; | |||||
| keyStatus.value = res.data.status; | |||||
| name.value = res.data.name; | |||||
| const len = signKey.value.length; | |||||
| const lenII = signKey.value.length; | |||||
| const lenIII = signKey.value.length; | |||||
| let code = ""; | |||||
| let codeII = ""; | |||||
| let codeIII = ""; | |||||
| for (let index = 0; index < len; index++) { | |||||
| code += "*"; | |||||
| } | |||||
| for (let index = 0; index < lenII; index++) { | |||||
| codeII += "*"; | |||||
| } | |||||
| for (let index = 0; index < lenIII; index++) { | |||||
| codeIII += "*"; | |||||
| } | |||||
| hideCode.value = code; | |||||
| showCode.value = code; | |||||
| hideCodeII.value = codeII; | |||||
| showCodeII.value = codeII; | |||||
| hideCodeIII.value = codeIII; | |||||
| showCodeIII.value = codeIII; | |||||
| } catch (error) { | |||||
| console.log(error, "err"); | |||||
| } | |||||
| }; | |||||
| const copyKey = (text) => { | |||||
| navigator.clipboard | navigator.clipboard | ||||
| .writeText(key.value) | |||||
| .writeText(text) | |||||
| .then(() => { | .then(() => { | ||||
| ElMessage.success("复制成功!"); | ElMessage.success("复制成功!"); | ||||
| }) | }) | ||||
| @@ -80,19 +170,48 @@ const copyKey = () => { | |||||
| const keyStatus = ref(""); | const keyStatus = ref(""); | ||||
| const getStatus = () => { | |||||
| // 1:正常;2:作废 | |||||
| const status = 1; | |||||
| keyStatus.value = status; | |||||
| }; | |||||
| const changeStatus = (num) => { | |||||
| keyStatus.value = num; | |||||
| const changeStatus = async (status) => { | |||||
| const id = keyId.value; | |||||
| if (status) { | |||||
| ElMessageBox.confirm("此操作将作废密钥,确定?", "Warning", { | |||||
| confirmButtonText: "确定", | |||||
| cancelButtonText: "取消", | |||||
| type: "warning", | |||||
| }) | |||||
| .then(async () => { | |||||
| try { | |||||
| const res = await updateKeyStatusApi(id, status); | |||||
| if (res.code == 200) { | |||||
| ElMessage({ | |||||
| type: "success", | |||||
| message: "作废成功!", | |||||
| }); | |||||
| getKeyFunc(); | |||||
| } | |||||
| } catch (error) { | |||||
| console.log(error, "err"); | |||||
| } | |||||
| }) | |||||
| .catch(() => {}); | |||||
| } else { | |||||
| try { | |||||
| const res = await updateKeyStatusApi(id, status); | |||||
| if (res.code == 200) { | |||||
| ElMessage({ | |||||
| type: "success", | |||||
| message: "恢复成功!", | |||||
| }); | |||||
| getKeyFunc(); | |||||
| } | |||||
| } catch (error) { | |||||
| console.log(error, "err"); | |||||
| } | |||||
| } | |||||
| }; | }; | ||||
| onMounted(() => { | onMounted(() => { | ||||
| getKey(); | |||||
| getStatus(); | |||||
| keyId.value = route.query.id; | |||||
| getKeyFunc(); | |||||
| }); | }); | ||||
| </script> | </script> | ||||
| @@ -104,9 +223,9 @@ onMounted(() => { | |||||
| border-radius: 30px 0 0 0; | border-radius: 30px 0 0 0; | ||||
| overflow: hidden; | overflow: hidden; | ||||
| .card { | .card { | ||||
| width: 60%; | |||||
| height: 55%; | |||||
| background-color: #f8f8f8; | |||||
| width: 80%; | |||||
| height: 70%; | |||||
| background-color: #fafafa; | |||||
| margin-top: 10vh; | margin-top: 10vh; | ||||
| border-radius: 5vh; | border-radius: 5vh; | ||||
| box-shadow: #0000002e 1px 1px 1px 1px; | box-shadow: #0000002e 1px 1px 1px 1px; | ||||
| @@ -119,8 +238,10 @@ onMounted(() => { | |||||
| .key { | .key { | ||||
| text-align: center; | text-align: center; | ||||
| font-size: 3vh; | |||||
| padding: 4vh; | |||||
| font-size: 2.5vh; | |||||
| padding: 5vh; | |||||
| padding-bottom: 0.5vh; | |||||
| text-align: left; | |||||
| .copy { | .copy { | ||||
| color: #ffffff; | color: #ffffff; | ||||
| @@ -146,8 +267,9 @@ onMounted(() => { | |||||
| } | } | ||||
| .keyStatus { | .keyStatus { | ||||
| text-align: center; | text-align: center; | ||||
| font-size: 3vh; | |||||
| font-size: 2.9vh; | |||||
| padding: 4vh; | padding: 4vh; | ||||
| margin-top: 1vh; | |||||
| .success { | .success { | ||||
| color: #ffffff; | color: #ffffff; | ||||
| @@ -0,0 +1,148 @@ | |||||
| <template> | |||||
| <div class="page flex justify-around"> | |||||
| <el-table | |||||
| :data="tableData" | |||||
| style="width: 100%; height: 90%" | |||||
| size="large" | |||||
| align="center" | |||||
| > | |||||
| <el-table-column | |||||
| prop="name" | |||||
| :label="$t('keyMangage.name')" | |||||
| width="220" | |||||
| align="center" | |||||
| /> | |||||
| <el-table-column | |||||
| prop="status" | |||||
| :label="$t('keyMangage.status')" | |||||
| width="220" | |||||
| align="center" | |||||
| > | |||||
| <template #default="scope"> | |||||
| <span | |||||
| :style="1 * scope.row.status ? 'color: #ff0000' : 'color: #36db43'" | |||||
| >{{ getStatus(scope.row.status) }}</span | |||||
| > | |||||
| </template> | |||||
| </el-table-column> | |||||
| <el-table-column | |||||
| fixed="right" | |||||
| :label="$t('keyMangage.operations')" | |||||
| width="220" | |||||
| align="center" | |||||
| > | |||||
| <template #default="scope"> | |||||
| <el-button | |||||
| link | |||||
| type="primary" | |||||
| size="small" | |||||
| @click="showDetail(scope.row.id)" | |||||
| >{{ $t("keyMangage.check") }}</el-button | |||||
| > | |||||
| </template> | |||||
| </el-table-column> | |||||
| </el-table> | |||||
| <div class="pagination"> | |||||
| <el-pagination | |||||
| v-model:current-page="pageNum" | |||||
| v-model:page-size="pageSize" | |||||
| :page-sizes="[10, 50, 100]" | |||||
| :small="false" | |||||
| :disabled="false" | |||||
| :background="true" | |||||
| layout="total, sizes, prev, pager, next, jumper" | |||||
| :total="total" | |||||
| @size-change="handleSizeChange" | |||||
| @current-change="handleCurrentChange" | |||||
| /> | |||||
| </div> | |||||
| </div> | |||||
| </template> | |||||
| <!-- videoType==1为竖,==2为横 --> | |||||
| <script setup> | |||||
| //#region 导入 | |||||
| import { linkEmits } from "element-plus"; | |||||
| import { getCurrentInstance } from "vue"; | |||||
| import { keyListApi } from "@/api_mangage/key"; | |||||
| import { useI18n } from "vue-i18n"; | |||||
| import { useRoute, useRouter } from "vue-router"; | |||||
| const route = useRoute(); | |||||
| const router = useRouter(); | |||||
| const { locale } = useI18n(); | |||||
| const lanChange = ref(locale); | |||||
| const tableData = ref([]); | |||||
| const showDetail = (id) => { | |||||
| router.push({ | |||||
| path: "/keyCheck", | |||||
| query: { | |||||
| id, | |||||
| }, | |||||
| }); | |||||
| }; | |||||
| const pageNum = ref(1); | |||||
| const pageSize = ref(10); | |||||
| const total = ref(0); | |||||
| const getStatus = (val) => { | |||||
| return val * 1 ? "失效" : "正常"; | |||||
| }; | |||||
| const handleSizeChange = (val) => { | |||||
| pageSize.value = val; | |||||
| getKeyListFunc(pageNum.value, pageSize.value); | |||||
| }; | |||||
| const handleCurrentChange = (val) => { | |||||
| pageNum.value = val; | |||||
| getKeyListFunc(pageNum.value, pageSize.value); | |||||
| }; | |||||
| const getKeyListFunc = async (PageNum, PageSize) => { | |||||
| try { | |||||
| const res = await keyListApi(PageNum, PageSize); | |||||
| console.log(res, "res"); | |||||
| tableData.value = res.data.list; | |||||
| } catch (error) { | |||||
| console.log(error, "err"); | |||||
| } | |||||
| }; | |||||
| onMounted(() => { | |||||
| getKeyListFunc(1, 10); | |||||
| }); | |||||
| </script> | |||||
| <style lang="scss" scoped> | |||||
| .page { | |||||
| height: calc(100vh - 80px); | |||||
| // height: calc(100vh - 80px); | |||||
| background-color: #ffffff; | |||||
| border-radius: 30px 0 0 0; | |||||
| overflow: hidden; | |||||
| padding: 10vh; | |||||
| .pagination { | |||||
| position: fixed; | |||||
| left: 55%; | |||||
| bottom: 8vh; | |||||
| transform: translateX(-50%); | |||||
| border-radius: 5px; | |||||
| padding: 10px 20px; | |||||
| z-index: 99; | |||||
| transition: all 0.3s; | |||||
| cursor: pointer; | |||||
| &:hover { | |||||
| background-color: #b8b8b873; | |||||
| } | |||||
| } | |||||
| } | |||||
| </style> | |||||
| @@ -1,698 +0,0 @@ | |||||
| <template> | |||||
| <div class="page"> | |||||
| <!-- 搜索框 --> | |||||
| <div class="top"> | |||||
| <div class="flex justify-between" style="width: 300px"> | |||||
| <el-input | |||||
| v-model="title" | |||||
| :placeholder="$t('myCreating.search')" | |||||
| @keyup.enter="searchVideoList" | |||||
| /> | |||||
| <el-icon class="icon-edit" @click="searchVideoList" | |||||
| ><i-ep-search | |||||
| /></el-icon> | |||||
| </div> | |||||
| </div> | |||||
| <!-- 作品列表 --> | |||||
| <div v-if="!isLoading"> | |||||
| <div v-if="videoList.length > 0" class="workList flex"> | |||||
| <div class="workItem" v-for="item in videoList" :key="item.id"> | |||||
| <div class="workImg"> | |||||
| <img | |||||
| v-if="item.coverImg" | |||||
| class="coverImg inmiddle" | |||||
| :src="item.coverImg" | |||||
| alt="" | |||||
| /> | |||||
| <img | |||||
| v-else | |||||
| class="takePlace inmiddle" | |||||
| src="@/assets/img/left-top-logo.png" | |||||
| alt="" | |||||
| /> | |||||
| </div> | |||||
| <div :class="'statusName ' + item.statusName"> | |||||
| {{ $t("myCreating." + item.statusName) }} | |||||
| </div> | |||||
| <div class="workInfo flex"> | |||||
| <span>{{ item.title }}</span> | |||||
| <span>{{ dayjs(item.createDate).format("YYYY-MM-DD") }}</span> | |||||
| </div> | |||||
| <!-- 更多遮罩层 --> | |||||
| <div | |||||
| class="more" | |||||
| @mouseleave="mouseleave" | |||||
| @click="clickVideoItem(item)" | |||||
| > | |||||
| <el-icon | |||||
| v-if="[0].includes(item.videoStatus)" | |||||
| class="icon-videoPlay" | |||||
| ><i-ep-edit | |||||
| /></el-icon> | |||||
| <el-icon | |||||
| v-if="[1, 2, 4, 6].includes(item.videoStatus)" | |||||
| class="icon-videoPlay" | |||||
| ><i-ep-loading | |||||
| /></el-icon> | |||||
| <el-icon | |||||
| v-if="[3].includes(item.videoStatus)" | |||||
| class="icon-videoPlay" | |||||
| ><i-ep-closeBold | |||||
| /></el-icon> | |||||
| <el-icon | |||||
| v-if="[5].includes(item.videoStatus)" | |||||
| class="icon-videoPlay" | |||||
| ><i-ep-videoPlay | |||||
| /></el-icon> | |||||
| <div class="showBtn" @click.stop="mouseenter(item)">...</div> | |||||
| <div class="btns" v-show="showPopup"> | |||||
| <!-- 下载按钮 --> | |||||
| <div | |||||
| class="btns-item" | |||||
| @click.stop="handleDownload(item.videoPlayUrl)" | |||||
| > | |||||
| <div class="btns-item-icon"> | |||||
| <el-icon class="icon-delete"><i-ep-download /></el-icon> | |||||
| </div> | |||||
| <div class="text">{{ $t("myCreating.download") }}</div> | |||||
| </div> | |||||
| <!-- 删除按钮 --> | |||||
| <div | |||||
| class="btns-item" | |||||
| @click.stop="handelDelete(item.id, item.title)" | |||||
| > | |||||
| <div class="btns-item-icon"> | |||||
| <el-icon class="icon-delete"><i-ep-delete /></el-icon> | |||||
| </div> | |||||
| <div class="text">{{ $t("myCreating.delete") }}</div> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| <div v-if="videoList.length == 0" class="noList"> | |||||
| <div class="title"> | |||||
| {{ $t("myCreating.noList") }} | |||||
| </div> | |||||
| <div class="goCreate" @click="goCreate"> | |||||
| {{ $t("myCreating.goCreate") }} | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| <div v-if="isLoading" class="loadingIcon"> | |||||
| <el-icon class="is-loading"> | |||||
| <svg | |||||
| viewBox="0 0 1024 1024" | |||||
| xmlns="http://www.w3.org/2000/svg" | |||||
| data-v-ea893728="" | |||||
| > | |||||
| <path | |||||
| fill="currentColor" | |||||
| d="M512 64a32 32 0 0 1 32 32v192a32 32 0 0 1-64 0V96a32 32 0 0 1 32-32zm0 640a32 32 0 0 1 32 32v192a32 32 0 1 1-64 0V736a32 32 0 0 1 32-32zm448-192a32 32 0 0 1-32 32H736a32 32 0 1 1 0-64h192a32 32 0 0 1 32 32zm-640 0a32 32 0 0 1-32 32H96a32 32 0 0 1 0-64h192a32 32 0 0 1 32 32zM195.2 195.2a32 32 0 0 1 45.248 0L376.32 331.008a32 32 0 0 1-45.248 45.248L195.2 240.448a32 32 0 0 1 0-45.248zm452.544 452.544a32 32 0 0 1 45.248 0L828.8 783.552a32 32 0 0 1-45.248 45.248L647.744 692.992a32 32 0 0 1 0-45.248zM828.8 195.264a32 32 0 0 1 0 45.184L692.992 376.32a32 32 0 0 1-45.248-45.248l135.808-135.808a32 32 0 0 1 45.248 0zm-452.544 452.48a32 32 0 0 1 0 45.248L240.448 828.8a32 32 0 0 1-45.248-45.248l135.808-135.808a32 32 0 0 1 45.248 0z" | |||||
| ></path> | |||||
| </svg> | |||||
| </el-icon> | |||||
| <span class="loadingText">{{ $t("myCreating.loading") }}</span> | |||||
| </div> | |||||
| <!-- 弹出框预览作品 --> | |||||
| <el-dialog | |||||
| destroy-on-close | |||||
| class="elDialog" | |||||
| v-model="showDialog" | |||||
| :title="presentItem.title" | |||||
| width="40%" | |||||
| center | |||||
| > | |||||
| <div class="videoBox"> | |||||
| <video | |||||
| v-if="presentItem.videoPlayUrl" | |||||
| controls="true" | |||||
| class="" | |||||
| :src="presentItem.videoPlayUrl" | |||||
| ></video> | |||||
| <div v-else class="insteadVideo"> | |||||
| {{ $t("myCreating." + presentItem.statusName + "Text") }} | |||||
| <span v-if="presentItem.videoStatus == 3">{{ | |||||
| presentItem.videoMsg | |||||
| }}</span> | |||||
| </div> | |||||
| <!-- 有视频路径的页脚 --> | |||||
| <div class="footer" v-if="presentItem.videoPlayUrl"> | |||||
| <span class="dialog-footer"> | |||||
| <!-- dialog下载按钮 --> | |||||
| <button | |||||
| class="elBtn" | |||||
| type="primary" | |||||
| @click.stop="handleDownload(presentItem.videoPlayUrl)" | |||||
| > | |||||
| <el-icon class="icon-delete"><i-ep-download /></el-icon | |||||
| >{{ $t("myCreating.download") }} | |||||
| </button> | |||||
| <!-- dialog删除按钮 --> | |||||
| <button | |||||
| class="elBtn" | |||||
| @click.stop="handelDelete(presentItem.id, presentItem.title)" | |||||
| > | |||||
| <el-icon class="icon-delete"><i-ep-delete /></el-icon | |||||
| >{{ $t("myCreating.delete") }} | |||||
| </button> | |||||
| </span> | |||||
| </div> | |||||
| <!-- 无视频路径的页脚 --> | |||||
| <div class="footer" v-if="!presentItem.videoPlayUrl"> | |||||
| <span class="dialog-footer"> | |||||
| <!-- dialog编辑按钮 --> | |||||
| <button | |||||
| class="elBtn" | |||||
| type="primary" | |||||
| @click.stop=" | |||||
| router.push({ | |||||
| path: '/createVideo', | |||||
| query: { id: presentItem.id }, | |||||
| }) | |||||
| " | |||||
| v-if="[0, 3].includes(presentItem.videoStatus)" | |||||
| > | |||||
| {{ $t("myCreating.edit") }} | |||||
| </button> | |||||
| </span> | |||||
| </div> | |||||
| </div> | |||||
| </el-dialog> | |||||
| <!-- 分页 --> | |||||
| <div v-if="!isLoading" class="pagination"> | |||||
| <el-pagination | |||||
| v-model:current-page="pageNum" | |||||
| v-model:page-size="pageSize" | |||||
| :page-sizes="[10, 20, 50, 100, 200]" | |||||
| :small="false" | |||||
| :disabled="false" | |||||
| :background="true" | |||||
| layout="total, sizes, prev, pager, next, jumper" | |||||
| :total="total" | |||||
| @size-change="handleSizeChange" | |||||
| @current-change="handleCurrentChange" | |||||
| /> | |||||
| </div> | |||||
| </div> | |||||
| </template> | |||||
| <script setup> | |||||
| import { | |||||
| userPhotoVideoListApi, | |||||
| delUserPhotoVideoByIDApi, | |||||
| } from "@/apis/myCreating"; | |||||
| import { timestampToTime } from "@/utils/tools"; | |||||
| import { useI18n } from "vue-i18n"; | |||||
| import { getStatus } from "./videoStatus"; | |||||
| import { useRouter } from "vue-router"; | |||||
| import dayjs from "dayjs"; | |||||
| const router = useRouter(); | |||||
| // 当前语言状态与国际化组件 | |||||
| const { locale } = useI18n(); | |||||
| const lanChange = ref(locale); | |||||
| const title = ref(""); | |||||
| const pageNum = ref(1); | |||||
| const pageSize = ref(10); | |||||
| const total = ref(0); | |||||
| // 弹窗显示隐藏 | |||||
| const showDialog = ref(false); | |||||
| const isLoading = ref(true); | |||||
| // 当前作品 | |||||
| const presentItem = ref(""); | |||||
| // 作品列表 | |||||
| const videoList = ref([]); | |||||
| const handleSizeChange = (val) => { | |||||
| pageSize.value = val; | |||||
| getPhotoVideoList(pageNum.value, pageSize.value, title.value); | |||||
| }; | |||||
| const handleCurrentChange = (val) => { | |||||
| pageNum.value = val; | |||||
| getPhotoVideoList(pageNum.value, pageSize.value, title.value); | |||||
| }; | |||||
| // 点击作品 | |||||
| function clickVideoItem(item) { | |||||
| showDialog.value = true; | |||||
| presentItem.value = item; | |||||
| } | |||||
| // 删除框是否显示 | |||||
| let showPopup = ref(false); | |||||
| function mouseleave() { | |||||
| showPopup.value = false; | |||||
| } | |||||
| function mouseenter(item) { | |||||
| presentItem.value = item; | |||||
| showPopup.value = !showPopup.value; | |||||
| } | |||||
| // 下载 | |||||
| function handleDownload(itemVideoPlayUrl) { | |||||
| if (itemVideoPlayUrl) { | |||||
| const link = document.createElement("a"); | |||||
| link.href = itemVideoPlayUrl; | |||||
| document.body.appendChild(link); | |||||
| link.click(); | |||||
| document.body.removeChild(link); | |||||
| } else { | |||||
| ElMessage.error( | |||||
| lanChange.value == "zh-cn" ? `无法下载` : `Unable to download` | |||||
| ); | |||||
| } | |||||
| } | |||||
| function goCreate() { | |||||
| router.push("/createVideo"); | |||||
| } | |||||
| function searchVideoList() { | |||||
| getPhotoVideoList(pageNum.value, pageSize.value, title.value, true); | |||||
| } | |||||
| function handelDelete(id, title) { | |||||
| const msg = | |||||
| lanChange.value == "zh-cn" | |||||
| ? `确定要删除这个作品吗? 作品标题:${title}` | |||||
| : `Are you sure to delete this video ? Title:${title};`; | |||||
| const notice = lanChange.value == "zh-cn" ? "提示" : "Notice"; | |||||
| const confirm = lanChange.value == "zh-cn" ? "确定" : "Confirm"; | |||||
| const cancel = lanChange.value == "zh-cn" ? "取消" : "Cancel"; | |||||
| ElMessageBox.confirm(msg, notice, { | |||||
| confirmButtonText: confirm, | |||||
| cancelButtonText: cancel, | |||||
| }).then(() => { | |||||
| delPhotoVideo(id); | |||||
| }); | |||||
| } | |||||
| /** | |||||
| * @description:获取我的视频作品 | |||||
| * @return: data | |||||
| */ | |||||
| function getPhotoVideoList(pageNum, pageSize, title, searchFlag) { | |||||
| userPhotoVideoList(pageNum, pageSize, title) | |||||
| .then((res) => { | |||||
| console.log(res, "res"); | |||||
| res.data.list.forEach((item) => { | |||||
| // item.createDate = timestampToTime(item.createDate) || ""; | |||||
| // item.updateDate = timestampToTime(item.updateDate) || ""; | |||||
| // item.createVideoDate = timestampToTime(item.createVideoDate) || ""; | |||||
| item.statusName = getStatus(item.videoStatus); | |||||
| }); | |||||
| videoList.value = res.data.list; | |||||
| total.value = res.data.total * 1; | |||||
| if (searchFlag) { | |||||
| const total = res.data.total; | |||||
| const msg1 = | |||||
| lanChange.value == "zh-cn" | |||||
| ? `查询成功!找到${total}条符合条件的视频` | |||||
| : `Found! Match ${total} videos`; | |||||
| const msg2 = | |||||
| lanChange.value == "zh-cn" | |||||
| ? `查询成功!没有符合条件的视频` | |||||
| : `Found! No match videos`; | |||||
| const msg3 = | |||||
| lanChange.value == "zh-cn" | |||||
| ? `查询成功!已加载全部视频` | |||||
| : `Found! Present all videos`; | |||||
| return title | |||||
| ? ElMessage.success(total > 0 ? msg1 : msg2) | |||||
| : ElMessage.success(msg3); | |||||
| } | |||||
| isLoading.value = false; | |||||
| }) | |||||
| .catch((err) => { | |||||
| console.log(err, "err"); | |||||
| }); | |||||
| } | |||||
| /** | |||||
| * @description:删除视频作品 | |||||
| * @param: videoID | |||||
| * @return: data | |||||
| */ | |||||
| function delPhotoVideo(videoID) { | |||||
| delUserPhotoVideoByID(videoID) | |||||
| .then((res) => { | |||||
| console.log(res, "res"); | |||||
| const msg = lanChange.value == "zh-cn" ? `删除成功!` : `Success !`; | |||||
| ElMessage.success(msg); | |||||
| showDialog.value = false; | |||||
| getPhotoVideoList(pageNum.value, pageSize.value, title.value); | |||||
| }) | |||||
| .catch((err) => { | |||||
| console.log(err, "err"); | |||||
| ElMessage.error(err.message); | |||||
| }); | |||||
| } | |||||
| onMounted(() => { | |||||
| isLoading.value = true; | |||||
| getPhotoVideoList(pageNum.value, pageSize.value, title.value); | |||||
| }); | |||||
| </script> | |||||
| <style lang="scss" scoped> | |||||
| .page { | |||||
| min-height: calc(100vh - 80px); | |||||
| padding: 15px 130px; | |||||
| background-color: #fff; | |||||
| border-radius: 25px 0 0; | |||||
| .top { | |||||
| margin-bottom: 35px; | |||||
| } | |||||
| .loadingIcon { | |||||
| height: 100px; | |||||
| line-height: 100px; | |||||
| text-align: center; | |||||
| transform: scale(2); | |||||
| .loadingText { | |||||
| position: relative; | |||||
| top: -2px; | |||||
| left: 4px; | |||||
| } | |||||
| } | |||||
| .workList { | |||||
| flex-wrap: wrap; | |||||
| justify-content: flex-start; | |||||
| width: 100%; | |||||
| // height: 200px; | |||||
| margin-top: 5px; | |||||
| padding-bottom: 50px; | |||||
| cursor: pointer; | |||||
| .workItem { | |||||
| position: relative; | |||||
| width: 300px; | |||||
| // height: 200px; | |||||
| margin: 0 20px 20px 0; | |||||
| border: 2px solid #c2c2c2; | |||||
| border-radius: 15px; | |||||
| cursor: pointer; | |||||
| overflow: hidden; | |||||
| .workImg { | |||||
| position: relative; | |||||
| width: 100%; | |||||
| height: 170px; | |||||
| cursor: pointer; | |||||
| padding: 10px; | |||||
| overflow: hidden; | |||||
| .coverImg { | |||||
| max-width: 90%; | |||||
| max-height: 170px; | |||||
| cursor: pointer; | |||||
| } | |||||
| .takePlace { | |||||
| position: absolute; | |||||
| top: 40%; | |||||
| width: 80%; | |||||
| } | |||||
| } | |||||
| .more { | |||||
| position: absolute; | |||||
| top: 0; | |||||
| left: 0; | |||||
| width: 100%; | |||||
| height: 170px; | |||||
| background-color: rgb(0 0 0 / 30%); | |||||
| cursor: pointer; | |||||
| opacity: 0; | |||||
| transition: all 0.2s; | |||||
| .icon-videoPlay { | |||||
| position: absolute; | |||||
| top: 50%; | |||||
| left: 50%; | |||||
| width: 50px; | |||||
| height: 50px; | |||||
| font-size: 50px; | |||||
| color: #fff; | |||||
| text-align: center; | |||||
| transform: translate(-50%, -50%); | |||||
| cursor: pointer; | |||||
| } | |||||
| .showBtn { | |||||
| position: absolute; | |||||
| top: 10px; | |||||
| right: 10px; | |||||
| width: 20px; | |||||
| height: 20px; | |||||
| font-size: 20px; | |||||
| line-height: 10px; | |||||
| color: #fff; | |||||
| text-align: center; | |||||
| transition: all 0.3s; | |||||
| cursor: pointer; | |||||
| border-radius: 2px; | |||||
| &:hover { | |||||
| background-color: #00000056; | |||||
| } | |||||
| } | |||||
| .btns { | |||||
| position: absolute; | |||||
| top: 45px; | |||||
| right: 10px; | |||||
| // width: 70px; | |||||
| // height: 60px; | |||||
| overflow: hidden; | |||||
| border-radius: 10px; | |||||
| cursor: pointer; | |||||
| &-item { | |||||
| // width: 70px; | |||||
| // height: 30px; | |||||
| text-align: center; | |||||
| background-color: #fff; | |||||
| padding: 0 10px; | |||||
| transition: all 0.3s; | |||||
| cursor: pointer; | |||||
| &-icon { | |||||
| position: relative; | |||||
| display: inline-block; | |||||
| width: 20px; | |||||
| height: 20px; | |||||
| cursor: pointer; | |||||
| .icon-delete { | |||||
| position: absolute; | |||||
| top: 4px; | |||||
| left: 0; | |||||
| width: 20px; | |||||
| height: 20px; | |||||
| font-size: 16px; | |||||
| color: #000; | |||||
| text-align: center; | |||||
| cursor: pointer; | |||||
| } | |||||
| } | |||||
| .text { | |||||
| display: inline-block; | |||||
| height: 30px; | |||||
| padding-left: 5px; | |||||
| margin-top: -5px; | |||||
| line-height: 20px; | |||||
| cursor: pointer; | |||||
| } | |||||
| &:hover { | |||||
| color: #ffffff; | |||||
| background-color: #0000001a; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| .workInfo { | |||||
| justify-content: space-between; | |||||
| height: 40px; | |||||
| padding: 0 10px; | |||||
| line-height: 40px; | |||||
| border-top: 1px solid #afafaf; | |||||
| white-space: nowrap; | |||||
| overflow: hidden; | |||||
| text-overflow: ellipsis; | |||||
| font-size: 13px; | |||||
| } | |||||
| .statusName { | |||||
| position: absolute; | |||||
| top: 10%; | |||||
| left: -10%; | |||||
| width: 120px; | |||||
| text-align: center; | |||||
| color: #ffffff; | |||||
| font-size: 14px; | |||||
| transform: rotate(-45deg); | |||||
| &.manuscript { | |||||
| /* 草稿 */ | |||||
| background: linear-gradient(to right, #d7d2cc 0%, #304352 100%); | |||||
| } | |||||
| &.generating { | |||||
| /* 生成中 */ | |||||
| background: linear-gradient(270deg, #4b61dc, #15d1b8); | |||||
| } | |||||
| &.generationFailed { | |||||
| /* 生成失败 */ | |||||
| background: linear-gradient(120deg, #f093fb 0%, #f5576c 100%); | |||||
| } | |||||
| &.generationSucceed { | |||||
| /* 生成成功 */ | |||||
| background: linear-gradient(120deg, #84fab0 0%, #8fd3f4 100%); | |||||
| } | |||||
| } | |||||
| &:hover { | |||||
| .more { | |||||
| opacity: 1; | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| .noList { | |||||
| .title { | |||||
| font-size: 30px; | |||||
| text-align: center; | |||||
| margin-top: 100px; | |||||
| background-image: -webkit-linear-gradient( | |||||
| left, | |||||
| #4b61dc, | |||||
| #15d1b8 25%, | |||||
| #4b61dc 50%, | |||||
| #15d1b8 75%, | |||||
| #4b61dc | |||||
| ) !important; | |||||
| -webkit-text-fill-color: transparent !important; | |||||
| -webkit-background-clip: text !important; | |||||
| background-clip: text !important; | |||||
| -webkit-background-size: 200% 100% !important; | |||||
| background-size: 200% 100% !important; | |||||
| } | |||||
| .goCreate { | |||||
| width: 200px; | |||||
| height: 40px; | |||||
| line-height: 40px; | |||||
| text-align: center; | |||||
| color: #ffffff; | |||||
| border-radius: 6px; | |||||
| background: linear-gradient(270deg, #4b61dc, #15d1b8); | |||||
| margin: 30px auto; | |||||
| cursor: pointer; | |||||
| transition: all 0.3s; | |||||
| &:hover { | |||||
| transform: scale(1.1); | |||||
| } | |||||
| } | |||||
| } | |||||
| .pagination { | |||||
| position: fixed; | |||||
| bottom: 20px; | |||||
| left: 50%; | |||||
| transform: translateX(-50%); | |||||
| background-color: #ffffff; | |||||
| padding: 10px 20px; | |||||
| border-radius: 8px; | |||||
| transition: all 0.3s; | |||||
| cursor: pointer; | |||||
| &:hover { | |||||
| background-color: #b8b8b873; | |||||
| } | |||||
| } | |||||
| } | |||||
| :deep(.el-input__wrapper) { | |||||
| border: none; | |||||
| border-bottom: 2px solid #000; | |||||
| border-radius: 0; | |||||
| box-shadow: none; | |||||
| } | |||||
| .el-icon.icon-edit { | |||||
| width: 30px; | |||||
| height: 30px; | |||||
| font-size: 30px; | |||||
| color: #8c939d; | |||||
| text-align: center; | |||||
| cursor: pointer; | |||||
| transition: all 0.3s; | |||||
| &:hover { | |||||
| color: #292929; | |||||
| } | |||||
| } | |||||
| .elDialog { | |||||
| .videoBox { | |||||
| // display: flex; | |||||
| // justify-content: space-between; | |||||
| width: 100%; | |||||
| padding: 20px; | |||||
| video { | |||||
| width: 100%; | |||||
| max-height: 600px; | |||||
| margin: auto; | |||||
| } | |||||
| .insteadVideo { | |||||
| font-size: 20px; | |||||
| font-weight: 600; | |||||
| margin: 20px auto; | |||||
| text-align: center; | |||||
| } | |||||
| } | |||||
| .dialog-footer { | |||||
| display: flex; | |||||
| justify-content: space-between; | |||||
| .elBtn { | |||||
| color: #fff; | |||||
| border-radius: 10px; | |||||
| padding: 5px 10px; | |||||
| cursor: pointer; | |||||
| background-color: #000; | |||||
| transition: all 0.3s; | |||||
| &:hover { | |||||
| background-color: #15d1b8; | |||||
| } | |||||
| } | |||||
| :deep(.el-icon) { | |||||
| margin-right: 5px; | |||||
| font-weight: 700; | |||||
| } | |||||
| } | |||||
| } | |||||
| :deep(.el-dialog) { | |||||
| overflow: hidden; | |||||
| border-radius: 25px; | |||||
| } | |||||
| // :deep(.el-dialog__header) { | |||||
| // } | |||||
| :deep(.el-dialog__title) { | |||||
| background-image: -webkit-linear-gradient( | |||||
| left, | |||||
| #4b61dc, | |||||
| #15d1b8 25%, | |||||
| #4b61dc 50%, | |||||
| #15d1b8 75%, | |||||
| #4b61dc | |||||
| ) !important; | |||||
| -webkit-text-fill-color: transparent !important; | |||||
| -webkit-background-clip: text !important; | |||||
| background-clip: text !important; | |||||
| -webkit-background-size: 200% 100% !important; | |||||
| background-size: 200% 100% !important; | |||||
| } | |||||
| :deep(.el-dialog__body) { | |||||
| padding: 0; | |||||
| } | |||||
| :deep(.dialog__footer) { | |||||
| padding: 0; | |||||
| } | |||||
| </style> | |||||