@@ -6,5 +6,7 @@ NODE_ENV='development' | |||
VITE_APP_TITLE = 'Metavatar-PC' | |||
VITE_APP_PORT = 3000 | |||
## VITE_APP_BASE_API = 'https://photo.metavatar.cc/C' | |||
VITE_APP_BASE_API = 'https://test.metavatar.cc/C' | |||
# VITE_APP_BASE_API = 'https://test.metavatar.cc/C' | |||
# VITE_APP_BASE_API = 'https://phototest.metavatar.cc/C' | |||
VITE_APP_BASE_API = 'https://m.metavatar.cc/C' | |||
@@ -6,4 +6,4 @@ NODE_ENV='test' | |||
VITE_APP_TITLE = 'Metavatar-PC' | |||
VITE_APP_PORT = 3000 | |||
# VITE_APP_BASE_API = 'https://photo.metavatar.cc/C' | |||
VITE_APP_BASE_API = 'https://test.metavatar.cc/C' | |||
VITE_APP_BASE_API = 'https://mtest.metavatar.cc/C' |
@@ -5,7 +5,7 @@ | |||
<meta charset="UTF-8" /> | |||
<link rel="icon" href="/favicon.ico" /> | |||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |||
<title>Metavatar-慧影</title> | |||
<title>Metavatar</title> | |||
</head> | |||
<body> | |||
@@ -34,6 +34,7 @@ | |||
"vue": "^3.2.45", | |||
"vue-cropper": "^1.0.9", | |||
"vue-i18n": "9", | |||
"vue-qr": "^4.0.9", | |||
"vue-router": "^4.0.13" | |||
}, | |||
"devDependencies": { | |||
@@ -0,0 +1,39 @@ | |||
import request from "@/utils/request.js"; | |||
/** | |||
* @description 服务端api签名指南 | |||
* @params | |||
* @returns | |||
*/ | |||
export function getAvailableApiGuideApi() { | |||
return request({ | |||
url: `/api/apiGuide/getAvailableApiGuide`, | |||
method: 'get' | |||
}) | |||
} | |||
/** | |||
* @description 开放接口列表 | |||
* @params | |||
* @returns | |||
*/ | |||
export function apiMenuApi() { | |||
return request({ | |||
url: `/api/apiMenu/list`, | |||
method: 'get' | |||
}) | |||
} | |||
/** | |||
* @description 获取接口详情 | |||
* @params | |||
* @returns | |||
*/ | |||
export function getContentApi(id) { | |||
return request({ | |||
url: `/api/apiMenu/get?id=${id}`, | |||
method: 'get' | |||
}) | |||
} |
@@ -7,8 +7,9 @@ import request from "@/utils/request.js"; | |||
* @returns data | |||
*/ | |||
export function modeListApi(sex, pageNum, pageSize, videoType) { | |||
let api = localStorage.getItem("AccessToken") ? '/api/personPatch/loginList' : '/api/personPatch/list' | |||
return request({ | |||
url: `/api/personPatch/list?sex=${sex}&pageNum=${pageNum}&pageSize=${pageSize}&videoType=${videoType}`, | |||
url: `${api}?sex=${sex}&pageNum=${pageNum}&pageSize=${pageSize}&videoType=${videoType}`, | |||
method: 'get' | |||
}) | |||
} | |||
@@ -19,8 +20,9 @@ export function modeListApi(sex, pageNum, pageSize, videoType) { | |||
* @returns data | |||
*/ | |||
export function voiceTotalApi() { | |||
let api = localStorage.getItem("AccessToken") ? '/api/voiceMould/loginVoiceTotal' : '/api/voiceMould/voiceTotal' | |||
return request({ | |||
url: `api/voiceMould/voiceTotal`, | |||
url: api, | |||
method: 'GET', | |||
}) | |||
} | |||
@@ -88,12 +90,32 @@ export function personSCIListApi(pageNum, pageSize) { | |||
* @returns data | |||
*/ | |||
export function previewAudioApi(gen_txt, voice_id, voice_style) { | |||
let api = localStorage.getItem("AccessToken") ? '/api/voiceMould/loginPreview' : '/api/voiceMould/hypreview' | |||
return request({ | |||
url: `api/voiceMould/preview`, | |||
url: api, | |||
method: 'POST', | |||
data: { gen_txt, voice_id, voice_style } | |||
}) | |||
} | |||
/** | |||
* @description 图片检测接口 | |||
* @params id | |||
* @returns data | |||
*/ | |||
export function checkPhotoApi(data) { | |||
const timestamp = Date.now(); | |||
const formData = new FormData(); | |||
formData.append('file', data, timestamp + ".png"); | |||
return request({ | |||
url: '/api/baidu/checkPhoto', | |||
method: 'post', | |||
data: formData, | |||
headers: { | |||
'Content-Type': 'application/form-data', | |||
"Access-Control-Allow-Credentials": true, | |||
} | |||
}); | |||
} | |||
/** | |||
* @description 上传阿里云--裁剪后的个人背景图 | |||
@@ -173,7 +195,10 @@ export function createVideoApi(id) { | |||
return request({ | |||
url: `/api/userVideo/createVideo`, | |||
method: 'post', | |||
data: { id } | |||
data: { | |||
id, | |||
projectType: '2' | |||
} | |||
}) | |||
} | |||
@@ -188,3 +213,39 @@ export function getModelDetailByIdApi(id) { | |||
method: 'get' | |||
}) | |||
} | |||
/** | |||
* @description:文字判断语种 | |||
* @param {number} id | |||
* @return data | |||
*/ | |||
export function getLanguageApi(data) { | |||
return request({ | |||
url: `/api/VoiceLanguage/getLanguage`, | |||
method: 'POST', | |||
data | |||
}) | |||
} | |||
/** | |||
* @description:视频校验 | |||
* @param {number} id | |||
* @return data | |||
*/ | |||
export function checkVideoApi(id) { | |||
return request({ | |||
url: `/api/userVideo/checkVideo?id=${id}`, | |||
method: 'get' | |||
}) | |||
} | |||
/** | |||
* @description:扣币 | |||
* @return data | |||
*/ | |||
export function reduceUserPoinsApi() { | |||
return request({ | |||
url: `/api/user/reduceUserPoins`, | |||
method: 'get' | |||
}) | |||
} |
@@ -0,0 +1,81 @@ | |||
/* | |||
* @Autor: Chutingting | |||
* @Date: 2023-11-13 14:29:58 | |||
* @LastEditors: Chutingting | |||
* @LastEditTime: 2023-11-14 10:48:23 | |||
* @Description: | |||
*/ | |||
import request from "@/utils/request.js"; | |||
/** | |||
* @description 充值订单 | |||
* @params | |||
* @returns | |||
*/ | |||
export function rechargeListApi(data) { | |||
return request({ | |||
url: `/api/productOrder/myPaiedOrders?projectType=${data.projectType}&pageNum=${data.pageNum}&pageSize=${data.pageSize}`, | |||
method: 'get' | |||
}) | |||
} | |||
/** | |||
* @description 获取详情 | |||
* @params | |||
* @returns | |||
*/ | |||
export function getDetailApi(id) { | |||
return request({ | |||
url: `/api/userVideo/findById?id=${id}`, | |||
method: 'get' | |||
}) | |||
} | |||
/** | |||
* @description 扣币详情 | |||
* @params | |||
* @returns | |||
*/ | |||
export function coindedApi(data) { | |||
return request({ | |||
url: `/api/userVideo/list?videoStatus=5&pageNum=${data.pageNum}&pageSize=${data.pageSize}`, | |||
method: 'get' | |||
}) | |||
} | |||
/** | |||
* @description 当前币值 | |||
* @params | |||
* @returns | |||
*/ | |||
export function getUserPoinsApi() { | |||
return request({ | |||
url: `/api/user/getUserPoins`, | |||
method: 'get' | |||
}) | |||
} | |||
/** | |||
* @description 充值订单详情 | |||
* @params | |||
* @returns | |||
*/ | |||
export function findByNumberApi(orderNumber) { | |||
return request({ | |||
url: `/api/productOrder/findByNumber?orderNumber=${orderNumber}`, | |||
method: 'get' | |||
}) | |||
} | |||
/** | |||
* @description 扣币订单详情 | |||
* @params | |||
* @returns | |||
*/ | |||
export function findByIdApi(id) { | |||
return request({ | |||
url: `/api/userVideo/findById?id=${id}`, | |||
method: 'get' | |||
}) | |||
} |
@@ -1,3 +1,4 @@ | |||
import request from "@/utils/request.js"; | |||
@@ -52,7 +53,7 @@ export function videoHyApi(id) { | |||
*/ | |||
export function checkVideoStatusApi(list) { | |||
return request({ | |||
url: `/api/userPhotoVideo/checkVideoStatus?list=${list}`, | |||
url: `/api/userVideo/checkVideoStatus?list=${list}`, | |||
method: 'get' | |||
}) | |||
} |
@@ -8,9 +8,48 @@ import request from "@/utils/request.js"; | |||
*/ | |||
export function packageInfoApi() { | |||
return request({ | |||
url: `/api/user/getPackageInfo`, | |||
url: `/api/product/list_v1?type=2&projectType=2`, // /api/user/getPackageInfo | |||
method: 'get' | |||
}) | |||
} | |||
/** | |||
* @description 订单详情 | |||
* @params | |||
* @returns | |||
*/ | |||
export function orderDetailApi(id) { | |||
return request({ | |||
url: `/api/productOrder/findByNumber?orderNumber=${id}`, | |||
method: 'get' | |||
}) | |||
} | |||
/** | |||
* @description 创建支付 | |||
* @params | |||
* @returns | |||
*/ | |||
export function createPayApi(data) { | |||
return request({ | |||
url: `/api/productOrder/createPay`, | |||
method: 'post', | |||
data | |||
}) | |||
} | |||
/** | |||
* @description 创建支付 | |||
* @params | |||
* @returns | |||
*/ | |||
export function findStatusApi(data) { | |||
return request({ | |||
url: `/api/productOrder/findStatus?orderNumber=${data.orderNumber}&payVendor=${data.payVendor}`, | |||
method: 'get' | |||
}) | |||
} | |||
@@ -0,0 +1,39 @@ | |||
import request from "@/utils/request.js"; | |||
/** | |||
* @description:购买金币下单 | |||
* @param productId | |||
* @return: data | |||
*/ | |||
export function createOrderApi(data) { | |||
return request({ | |||
url: `api/productOrder/createOrder`, | |||
method: 'post', | |||
data | |||
}) | |||
} | |||
/** | |||
* @description:获取订单数据 | |||
* @param data | |||
* @return: data | |||
*/ | |||
export function createPayApi(data) { | |||
return request({ | |||
url: `api/productOrder/createPay`, | |||
method: 'post', | |||
data | |||
}) | |||
} | |||
/** | |||
* @description:获取订单支付状态 | |||
* @param orderNumber | |||
* @return: data payStatus 查询支付状态 0:待支付,2:支付中,3:已支付 | |||
*/ | |||
export function getOrderStatusApi(orderNumber, payVendor) { | |||
return request({ | |||
url: `api/productOrder/findStatus?orderNumber=${orderNumber}&payVendor=${payVendor}`, | |||
method: 'get' | |||
}) | |||
} |
@@ -51,7 +51,7 @@ | |||
v-for="(item, index) in materialList.scList" | |||
:key="item.id" | |||
class="scListItem" | |||
:class="showBorderActive == item.id ? 'border' : ''" | |||
:class="scBorderActive == index ? 'border' : ''" | |||
@mousedown.stop="handleDragSc(item, index, $event)" | |||
:style="{ | |||
top: item.y / props.proportion + 'px', | |||
@@ -64,7 +64,7 @@ | |||
<img id="scListItemImg" draggable="false" :src="item.material" alt="" /> | |||
<div ref="box1" class="stretchBox box1"></div> | |||
<div | |||
v-show="showBorderActive == item.id" | |||
v-show="scBorderActive == index" | |||
class="stretchBox box2" | |||
@click="delScListItem(index)" | |||
> | |||
@@ -77,7 +77,7 @@ | |||
</div> | |||
<div class="stretchBox box3"></div> | |||
<div | |||
v-show="showBorderActive == item.id" | |||
v-show="scBorderActive == index" | |||
ref="box4" | |||
@mousedown.stop="changeScaleSc(index, $event)" | |||
class="stretchBox box4" | |||
@@ -161,6 +161,7 @@ const virtualStyle = computed(() => { | |||
}); | |||
// 拖动盒子 | |||
const showBorderActive = ref(-1); //判断显示边框 | |||
const scBorderActive = ref('') | |||
watch( | |||
() => props.materialList.virtual.id, | |||
(newValue, oldValue) => { | |||
@@ -223,14 +224,14 @@ function changeScale(event) { | |||
let deltaY = touchStart.pageY - y; | |||
let boxDistance2 = Math.sqrt(deltaX ** 2 + deltaY ** 2); | |||
if (deltaX < 0) { | |||
if (props.materialList.virtual.w < 0.4) { | |||
props.materialList.virtual.w = 0.4; | |||
if (props.materialList.virtual.w < 0.2) { | |||
props.materialList.virtual.w = 0.2; | |||
return; | |||
} | |||
props.materialList.virtual.w = (baseLineScale + boxDistance2) / baseLine; | |||
} else { | |||
if (props.materialList.virtual.w > 1.3) { | |||
props.materialList.virtual.w = 1.3; | |||
if (props.materialList.virtual.w > 2.0) { | |||
props.materialList.virtual.w = 2.0; | |||
return; | |||
} | |||
props.materialList.virtual.w = (baseLineScale - boxDistance2) / baseLine; | |||
@@ -253,8 +254,12 @@ function changeScale(event) { | |||
//#region 素材图逻辑 | |||
const handleDragSc = (item, index, event) => { | |||
realImgUrl.value = item.material; | |||
scBorderActive.value= index | |||
showBorderActive.value = item.id; | |||
props.materialList.scList.forEach(res => { | |||
res.activeIndex ='' | |||
}) | |||
item.activeIndex = item.id | |||
event.preventDefault(); | |||
const imageElement = fatherBox.value; | |||
const startX = event.clientX; //保存初始值,避免闪烁 | |||
@@ -293,15 +298,15 @@ function changeScaleSc(index, event) { | |||
let deltaY = touchStart.pageY - y; | |||
let boxDistance2 = Math.sqrt(deltaX ** 2 + deltaY ** 2); | |||
if (deltaX < 0) { | |||
if (props.materialList.scList[index].w < 0.4) { | |||
props.materialList.scList[index].w = 0.4; | |||
if (props.materialList.scList[index].w < 0.2) { | |||
props.materialList.scList[index].w = 0.2; | |||
return; | |||
} | |||
props.materialList.scList[index].w = | |||
(baseLineScale + boxDistance2) / baseLine; | |||
} else { | |||
if (props.materialList.scList[index].w > 1.3) { | |||
props.materialList.scList[index].w = 1.3; | |||
if (props.materialList.scList[index].w > 2.0) { | |||
props.materialList.scList[index].w = 2.0; | |||
return; | |||
} | |||
props.materialList.scList[index].w = | |||
@@ -63,7 +63,7 @@ | |||
// import { VueCropper } from "vue-cropper"; | |||
import { ElMessage } from "element-plus/es"; | |||
import { ref, reactive, watch } from "vue"; | |||
import { awsImgUpload, saveImgApi } from "../apis/createVideo"; | |||
import { awsImgUpload, saveImgApi, checkPhotoApi } from "../apis/createVideo"; | |||
import { useI18n } from "vue-i18n"; | |||
const { locale } = useI18n(); | |||
@@ -92,30 +92,58 @@ function myUpload(params) {} | |||
const cropper = ref(null); | |||
const option = reactive({ | |||
img: "", | |||
canMove: true, | |||
outputSize: 0.5, //图片质量 | |||
info: false, // 裁剪框的大小信息 | |||
// outputType: 'jpeg', // 裁剪生成图片的格式 | |||
outputType: "png", // 裁剪生成图片的格式 | |||
outputType: "png", | |||
canScale: true, // 图片是否允许滚轮缩放 | |||
autoCrop: true, // 是否默认生成截图框 | |||
fixedBox: false, | |||
original: false, | |||
canMoveBox: true, | |||
autoCrop: true, | |||
// 只有自动截图开启 宽度高度才生效 | |||
autoCropWidth: window.innerWidth - 100 + "px", // 默认生成截图框宽度 | |||
autoCropHeight: window.innerWidth - 100 + "px", // 默认生成截图框高度 | |||
high: true, // 是否按照设备的dpr 输出等比例图片 | |||
fixedBox: false, // 固定截图框大小 不允许改变 | |||
fixed: false, // 是否开启截图框宽高固定比例 | |||
// fixedNumber: [1, 1], // 截图框的宽高比例 | |||
full: true, // 是否输出原图比例的截图 | |||
canMoveBox: true, // 截图框能否拖动 | |||
original: false, // 上传图片按照原始比例渲染 | |||
centerBox: true, // 截图框是否被限制在图片里面 | |||
centerBox: true, | |||
high: true, | |||
cropData: {}, | |||
enlarge: 1, | |||
mode: 'contain', | |||
maxImgSize: 3000, | |||
// limitMinSize: [50, 50], | |||
fixed: false, | |||
// fixedNumber: [2, 1], | |||
fillColor: '', | |||
full: true, | |||
infoTrue: false, // true 为展示真实输出图片宽高 false 展示看到的截图框宽高 | |||
mode: "100% auto", // 图片默认渲染方式 | |||
// outputSize: 0.5, //图片质量 | |||
// info: false, // 裁剪框的大小信息 | |||
// // outputType: 'jpeg', // 裁剪生成图片的格式 | |||
// outputType: "png", // 裁剪生成图片的格式 | |||
// canScale: true, // 图片是否允许滚轮缩放 | |||
// autoCrop: true, // 是否默认生成截图框 | |||
// autoCropWidth: window.innerWidth - 100 + "px", // 默认生成截图框宽度 | |||
// autoCropHeight: window.innerWidth - 100 + "px", // 默认生成截图框高度 | |||
// high: true, // 是否按照设备的dpr 输出等比例图片 | |||
// fixedBox: false, // 固定截图框大小 不允许改变 | |||
// fixed: false, // 是否开启截图框宽高固定比例 | |||
// // fixedNumber: [1, 1], // 截图框的宽高比例 | |||
// full: true, // 是否输出原图比例的截图 | |||
// canMoveBox: true, // 截图框能否拖动 | |||
// original: false, // 上传图片按照原始比例渲染 | |||
// centerBox: true, // 截图框是否被限制在图片里面 | |||
// infoTrue: false, // true 为展示真实输出图片宽高 false 展示看到的截图框宽高 | |||
// mode: "100% auto", // 图片默认渲染方式 | |||
}); | |||
//#region 裁剪图片 | |||
const cropperOverData = ref(null); | |||
function sendImgData() { | |||
cropper.value.getCropBlob(async (data) => { | |||
try { | |||
const checkPhotoRes = await checkPhotoApi(data) | |||
if (checkPhotoRes.code !== 200) { | |||
ElMessage.error(checkPhotoRes.message); | |||
return | |||
} | |||
const res = await awsImgUpload(data); | |||
const res2 = await saveImgApi({ | |||
type: props.type, | |||
@@ -0,0 +1,51 @@ | |||
<template> | |||
<div class="loadingIcon"> | |||
<div> | |||
<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> | |||
</div> | |||
</div> | |||
</template> | |||
<script setup> | |||
import { useI18n } from "vue-i18n"; | |||
const { locale } = useI18n(); | |||
const lanChange = ref(locale); | |||
const props = defineProps({ | |||
isLoading: { | |||
required: false, //是否必传 | |||
}, | |||
}); | |||
</script> | |||
<style lang="scss" scoped> | |||
.loadingIcon { | |||
position: relative; | |||
width: 100%; | |||
height: 60px; | |||
line-height: 60px; | |||
text-align: center; | |||
transform: scale(2); | |||
> div { | |||
position: absolute; | |||
top: 0; | |||
left: 50%; | |||
transform: translateX(-50%); | |||
} | |||
.loadingText { | |||
position: relative; | |||
top: -2px; | |||
left: 4px; | |||
} | |||
} | |||
</style> |
@@ -51,6 +51,7 @@ export default { | |||
logout: "Logout", | |||
goLogin: "Go and log in", | |||
LanguageChange: "Language switching", | |||
currencyValue: 'Current currency value' | |||
}, | |||
// 创作视频 | |||
@@ -85,6 +86,7 @@ export default { | |||
comingSoon: "COMING SOON", | |||
material: "Material", | |||
subtitles: "Subtitles", | |||
AItext:"AI Script", | |||
sex: "Sex", | |||
videoRatio: "Video Ratio", | |||
all: "All", | |||
@@ -104,6 +106,11 @@ export default { | |||
tooltip2: "Add Pause", | |||
SubtitlesTip: "Subtitles will be shown here", | |||
subtitlesSwitch: "Subtitles Switch", | |||
inputRequirement:'Please enter your requirements, for example: Please generate a beverage advertisement of 500 words or less', | |||
GeneratedText:'Generated Text', | |||
SmartText:'Smart Text', | |||
copy:'Copy to text', | |||
custom: 'VIP' | |||
}, | |||
// 我的视频 | |||
@@ -202,6 +209,18 @@ export default { | |||
title: "API Access", | |||
comingSoon: "Coming Soon", | |||
}, | |||
cooperate: { | |||
title: 'Partner Access', | |||
api: { | |||
title: 'API Access' | |||
}, | |||
privatization: { | |||
title: 'Privatization deployment' | |||
} | |||
}, | |||
my: { | |||
title: 'My', | |||
}, | |||
signSucceed: { | |||
title: "Confirm your email", | |||
@@ -215,4 +234,44 @@ export default { | |||
goLogin: "Login now", | |||
reSend: "Resend", | |||
}, | |||
recharge: { | |||
title: 'Recharge order', | |||
currencyValue: 'Current currency value', | |||
productTitle: 'name', | |||
orderNumber: 'Order No', | |||
payment: 'amount of money', | |||
createTime: 'Creation time', | |||
operate: 'operate', | |||
view: 'view', | |||
detailTitle: 'Recharge Details', | |||
payVendor: 'Payment method', | |||
weChat: 'WeChat', | |||
alipay: 'Alipay', | |||
paymentStr: 'Payment amount', | |||
orderStatus: 'Payment status', | |||
paymentTime: 'Pay time', | |||
close: 'close' | |||
}, | |||
coindeduc: { | |||
title: 'Creation Record', | |||
currencyValue: 'Current currency value', | |||
titleList: 'name', | |||
videoPlayUrl: 'Video address', | |||
videoTime: 'Video duration(S)', | |||
costPoints: 'Deduction quantity', | |||
createTime: 'Creation time', | |||
operate: 'operate', | |||
view: 'view', | |||
detailTitle: 'Deduction Details', | |||
second: 'S' | |||
}, | |||
store: { | |||
priceRmb: 'original price', | |||
glod: 'currency value', | |||
createOrder: 'BUY NOW', | |||
payType:'Choose payment method', | |||
cancel: 'Cancel', | |||
confirm: 'Confirm', | |||
pay: 'Payment in progress...', | |||
} | |||
}; |
@@ -52,6 +52,7 @@ export default { | |||
logout: "注销", | |||
goLogin: "登录", | |||
LanguageChange: "语言切换", | |||
currencyValue: '当前币值' | |||
}, | |||
// 创作视频 | |||
@@ -86,6 +87,7 @@ export default { | |||
BackgroundImage: "背景", | |||
material: "素材", | |||
subtitles: "字幕", | |||
AItext:"AI生成文本", | |||
sex: "性别", | |||
videoRatio: "视频比例", | |||
all: "全部", | |||
@@ -105,6 +107,11 @@ export default { | |||
tooltip2: "添加停顿", | |||
SubtitlesTip: "字幕将在此处展示", | |||
subtitlesSwitch: "字幕开关", | |||
inputRequirement:'请输入您的需求,例如:请生成一个500字以内的饮料广告', | |||
GeneratedText:'生成文本', | |||
SmartText:'智能文本', | |||
copy:'复制到文案', | |||
custom: '私人订制' | |||
}, | |||
// 我的视频 | |||
@@ -202,6 +209,18 @@ export default { | |||
title: "API 接口", | |||
comingSoon: "敬请期待", | |||
}, | |||
cooperate: { | |||
title: '合作商接入', | |||
api: { | |||
title: 'API 接口' | |||
}, | |||
privatization: { | |||
title: '私有化部署' | |||
} | |||
}, | |||
my: { | |||
title: '我的', | |||
}, | |||
signSucceed: { | |||
title: "确认邮箱", | |||
@@ -214,4 +233,44 @@ export default { | |||
goLogin: "即将登录", | |||
reSend: "重新发送", | |||
}, | |||
recharge: { | |||
title: '充值订单', | |||
currencyValue: '当前币值', | |||
productTitle: '名称', | |||
orderNumber: '订单号', | |||
payment: '金额', | |||
createTime: '创建时间', | |||
operate: '操作', | |||
view: '查看', | |||
detailTitle: '充值详情', | |||
payVendor: '支付方式', | |||
weChat: '微信', | |||
alipay: '支付宝', | |||
paymentStr: '支付金额', | |||
orderStatus: '支付状态', | |||
paymentTime: '支付时间', | |||
close: '关闭' | |||
}, | |||
coindeduc: { | |||
title: '创作记录', | |||
currencyValue: '当前币值', | |||
titleList: '名称', | |||
videoPlayUrl: '视频地址', | |||
videoTime: '视频时长(秒)', | |||
costPoints: '扣币数量', | |||
createTime: '创建时间', | |||
operate: '操作', | |||
view: '查看', | |||
detailTitle: '扣币详情', | |||
second: '秒' | |||
}, | |||
store: { | |||
priceRmb: '原价', | |||
glod: '币值', | |||
createOrder: '立即购买', | |||
payType:'选择支付方式', | |||
cancel: '取消', | |||
confirm: '确定', | |||
pay: '支付中...', | |||
} | |||
}; |
@@ -23,39 +23,58 @@ | |||
</div> | |||
{{ $t("myCreating.title") }} | |||
</div> | |||
<div class="myRouter-item" @click="showTalkUsDialog = true"> | |||
<div class="myRouter-item" @click="router.push('/separation')"> | |||
<div class="icon"> | |||
<el-icon><i-ep-user /></el-icon> | |||
</div> | |||
{{ $t("userModel.title") }} | |||
</div> | |||
<div class="myRouter-item" @click="showTalkUsDialog = true"> | |||
<div class="myRouter-item" @click="router.push('/voiceprint')"> | |||
<div class="icon"> | |||
<el-icon><i-ep-phone /></el-icon> | |||
</div> | |||
{{ $t("voiceModel.title") }} | |||
</div> | |||
<div class="bottomBtx"> | |||
<!-- <div class="bottomBtx"> --> | |||
<div class="myRouter-item" @click="router.push('/myStore')"> | |||
<div class="icon"> | |||
<el-icon><i-ep-Goods /></el-icon> | |||
</div> | |||
{{ $t("shop.title") }} | |||
</div> | |||
<div class="myRouter-item" @click="router.push('/myAPI')"> | |||
<!-- <div class="myRouter-item" @click="router.push('/myAPI')"> | |||
<div class="icon"> | |||
<el-icon><i-ep-DocumentAdd /></el-icon> | |||
</div> | |||
{{ $t("API.title") }} | |||
</div> | |||
</div> | |||
</div> --> | |||
<el-menu | |||
default-active="" | |||
class="el-menu-vertical-demo" | |||
active-text-color="#ffd04b" | |||
background-color="#000" | |||
text-color="#fff" | |||
> | |||
<el-sub-menu index="1"> | |||
<template #title> | |||
<el-icon><location /></el-icon> | |||
<span>{{ $t("my.title") }}</span> | |||
</template> | |||
<el-menu-item-group> | |||
<el-menu-item index="2-1" @click="router.push('/myRecharge')">{{ $t("recharge.title") }} </el-menu-item> | |||
<el-menu-item index="2-2" @click="router.push('/coindeduc')">{{ $t("coindeduc.title") }} </el-menu-item> | |||
</el-menu-item-group> | |||
</el-sub-menu> | |||
</el-menu> | |||
<!-- </div> --> | |||
</div> | |||
</div> | |||
<!-- 右边显示部分 --> | |||
<div class="rightBox"> | |||
<!-- nav栏 --> | |||
<div class="nav"> | |||
<div class="navItem">{{ $t("navbar.currencyValue") }}:{{ currentValue }}</div> | |||
<!-- 语言 --> | |||
<el-tooltip | |||
style="cursor: pointer; z-index: 999" | |||
@@ -66,6 +85,7 @@ | |||
> | |||
<lang-select class="navItem" /> | |||
</el-tooltip> | |||
<div class="navItem" v-if="currentPhone">{{ currentPhone }}</div> | |||
<!-- 登录 --> | |||
<div class="navItem" v-if="!AccessToken" @click="router.push('login')"> | |||
{{ $t("navbar.goLogin") }} | |||
@@ -103,6 +123,14 @@ import { useRoute, useRouter } from "vue-router"; | |||
import { useI18n } from "vue-i18n"; | |||
import { userInfoModules } from "@/store/modules/userInfo"; | |||
import { getUserPoinsApi } from '@/apis/my.js' | |||
import { | |||
Document, | |||
Menu as IconMenu, | |||
Location, | |||
Setting, | |||
} from '@element-plus/icons-vue' | |||
const userInfoPinia = userInfoModules(); | |||
const route = useRoute(); | |||
@@ -162,20 +190,41 @@ function handleOutsideClick() { | |||
appStore.closeSideBar(false); | |||
} | |||
onMounted(() => {}); | |||
// 当前币值 | |||
const currentValue = ref('') | |||
const currentPhone = localStorage.getItem('phone') | |||
function currentValFn() { | |||
getUserPoinsApi().then(res => { | |||
currentValue.value = res.data | |||
localStorage.setItem('userPoinsVal', res.data) | |||
}) | |||
} | |||
onMounted(() => { | |||
currentValFn() | |||
}); | |||
//#region 联系我们弹窗 | |||
const showTalkUsDialog = ref(false); | |||
const updateShowTalkUsDialog = (newValue: any) => { | |||
showTalkUsDialog.value = newValue; | |||
}; | |||
//#endregion ----------------------------------- | |||
//#region 页面跳转 | |||
function toUserModel() { | |||
// router.push("/userModel"); | |||
window.location.href = '/priMakeHtml/dingzhifenshen/index.shtml' | |||
showTalkUsDialog.value = true; | |||
} | |||
//#endregion ------------------------------------ | |||
</script> | |||
<!-- 新样式 --> | |||
<style lang="scss" scoped> | |||
.app-wrapper { | |||
width: 1920px; | |||
width: 100%; | |||
display: flex; | |||
overflow: hidden; | |||
} | |||
.Sidebar { | |||
width: 230px; | |||
@@ -194,9 +243,12 @@ const updateShowTalkUsDialog = (newValue: any) => { | |||
.myRouter { | |||
position: relative; | |||
height: calc(100% - 80px); | |||
padding: 130px 20px 0; | |||
padding: 40px 20px 0; | |||
color: #fff; | |||
user-select: none; | |||
// color: #868593; | |||
overflow: auto; | |||
overflow-x: hidden; | |||
.bottomBtx { | |||
position: absolute; | |||
@@ -207,8 +259,7 @@ const updateShowTalkUsDialog = (newValue: any) => { | |||
width: 100%; | |||
height: 50px; | |||
padding-left: 10px; | |||
font-size: 20px; | |||
font-weight: 500; | |||
font-size: 18px; | |||
line-height: 50px; | |||
text-align: center; | |||
cursor: pointer; | |||
@@ -234,7 +285,6 @@ const updateShowTalkUsDialog = (newValue: any) => { | |||
vertical-align: sub; | |||
} | |||
} | |||
&:hover { | |||
// background: rgba(255, 255, 255, 0.2); | |||
color: #000; | |||
@@ -261,7 +311,7 @@ const updateShowTalkUsDialog = (newValue: any) => { | |||
} | |||
} | |||
.rightBox { | |||
width: 1690px; | |||
width: calc(100% - 230px); | |||
// background-color: #000; | |||
.nav { | |||
display: flex; | |||
@@ -280,4 +330,11 @@ const updateShowTalkUsDialog = (newValue: any) => { | |||
} | |||
} | |||
} | |||
.el-menu{ | |||
border: none; | |||
:deep .el-sub-menu__title, :deep .el-menu-item{ | |||
font-size: 18px; | |||
} | |||
} | |||
</style> |
@@ -1,4 +1,4 @@ | |||
import { createRouter, createWebHashHistory, RouteRecordRaw } from "vue-router"; | |||
import { createRouter, createWebHashHistory, RouteRecordRaw, useRoute } from "vue-router"; | |||
import { getCurrentInstance } from "vue"; | |||
export const Layout = () => import("@/layout/index.vue"); | |||
@@ -55,6 +55,42 @@ export const constantRoutes: RouteRecordRaw[] = [ | |||
}, | |||
}, | |||
], | |||
}, // 定制分身 | |||
{ | |||
path: "/", | |||
component: Layout, | |||
redirect: "/userModel", | |||
children: [ | |||
{ | |||
path: "userModel", | |||
component: () => import("@/views/userModel/index.vue"), | |||
name: "userModel", | |||
meta: { | |||
title: "userModel", | |||
icon: "homepage", | |||
affix: true, | |||
name: "userModel.title", | |||
}, | |||
}, | |||
], | |||
}, // 定制声纹 | |||
{ | |||
path: "/", | |||
component: Layout, | |||
redirect: "/voiceModel", | |||
children: [ | |||
{ | |||
path: "voiceModel", | |||
component: () => import("@/views/voiceModel/index.vue"), | |||
name: "voiceModel", | |||
meta: { | |||
title: "voiceModel", | |||
icon: "homepage", | |||
affix: true, | |||
name: "voiceModel.title", | |||
}, | |||
}, | |||
], | |||
}, { | |||
path: "/", | |||
component: Layout, | |||
@@ -75,17 +111,28 @@ export const constantRoutes: RouteRecordRaw[] = [ | |||
}, { | |||
path: "/", | |||
component: Layout, | |||
redirect: "/myAPI", | |||
redirect: "/myRecharge", | |||
children: [ | |||
{ | |||
path: "myAPI", | |||
component: () => import("@/views/myAPI/index.vue"), | |||
name: "myAPI", | |||
path: "/myRecharge", | |||
component: () => import("@/views/my/recharge.vue"), | |||
name: "myRecharge", | |||
meta: { | |||
title: "myAPI", | |||
title: "myRecharge", | |||
icon: "homepage", | |||
affix: true, | |||
name: "API.title", | |||
name: "my.title", | |||
}, | |||
}, | |||
{ | |||
path: "/coindeduc", | |||
component: () => import("@/views/my/coindeduc.vue"), | |||
name: "coindeduc", | |||
meta: { | |||
title: "coindeduc", | |||
icon: "homepage", | |||
affix: true, | |||
name: "my.title", | |||
}, | |||
}, | |||
], | |||
@@ -108,6 +155,57 @@ export const constantRoutes: RouteRecordRaw[] = [ | |||
}, | |||
], | |||
}, | |||
{ | |||
path: "/", | |||
component: Layout, | |||
redirect: "/separation", | |||
children: [ | |||
{ | |||
path: "/separation", | |||
component: () => import("@/views/separation/index.vue"), | |||
name: "separation", | |||
meta: { | |||
title: "separation", | |||
icon: "homepage", | |||
affix: true, | |||
name: "separation.title", | |||
}, | |||
}, | |||
{ | |||
path: "/voiceprint", | |||
component: () => import("@/views/voiceprint/index.vue"), | |||
name: "voiceprint", | |||
meta: { | |||
title: "voiceprint", | |||
icon: "homepage", | |||
affix: true, | |||
name: "separation.title", | |||
}, | |||
}, | |||
{ | |||
path: "/privatization", | |||
component: () => import("@/views/privatization/index.vue"), | |||
name: "privatization", | |||
meta: { | |||
title: "privatization", | |||
icon: "homepage", | |||
affix: true, | |||
name: "separation.title", | |||
}, | |||
}, | |||
{ | |||
path: "/api", | |||
component: () => import("@/views/api/index.vue"), | |||
name: "api", | |||
meta: { | |||
title: "api", | |||
icon: "homepage", | |||
affix: true, | |||
name: "separation.title", | |||
}, | |||
}, | |||
], | |||
}, | |||
]; | |||
@@ -121,7 +219,9 @@ const router = createRouter({ | |||
// 2023-5-23 添加平滑滚动 YWQ | |||
scrollBehavior: () => ({ behavior: "smooth", left: 0, top: 0 }), | |||
}); | |||
router.beforeEach((to, from) => { | |||
document.title = '元气智驾-' + (to.query.p || from.query.p || localStorage.getItem("title") || '悟空') | |||
}) | |||
/** | |||
* 重置路由 | |||
*/ | |||
@@ -13,6 +13,7 @@ export const userInfoModules = defineStore("userInfo", () => { | |||
async function getUserInfo() { | |||
const res = await getUserInfoApi() | |||
userInfo.value = res.data | |||
localStorage.setItem('phone', res.data.phone) | |||
} | |||
// 退出清除用户信息 | |||
function loginOut(params) { | |||
@@ -2,6 +2,8 @@ | |||
export {} | |||
declare global { | |||
const EffectScope: typeof import('vue')['EffectScope'] | |||
const ElMessage: typeof import('element-plus/es')['ElMessage'] | |||
const ElMessageBox: typeof import('element-plus/es')['ElMessageBox'] | |||
const asyncComputed: typeof import('@vueuse/core')['asyncComputed'] | |||
const autoResetRef: typeof import('@vueuse/core')['autoResetRef'] | |||
const computed: typeof import('vue')['computed'] | |||
@@ -268,6 +270,8 @@ import { UnwrapRef } from 'vue' | |||
declare module 'vue' { | |||
interface ComponentCustomProperties { | |||
readonly EffectScope: UnwrapRef<typeof import('vue')['EffectScope']> | |||
readonly ElMessage: UnwrapRef<typeof import('element-plus/es')['ElMessage']> | |||
readonly ElMessageBox: UnwrapRef<typeof import('element-plus/es')['ElMessageBox']> | |||
readonly asyncComputed: UnwrapRef<typeof import('@vueuse/core')['asyncComputed']> | |||
readonly autoResetRef: UnwrapRef<typeof import('@vueuse/core')['autoResetRef']> | |||
readonly computed: UnwrapRef<typeof import('vue')['computed']> | |||
@@ -13,6 +13,7 @@ declare module '@vue/runtime-core' { | |||
CutImg1: typeof import('./../components/cutImg1.vue')['default'] | |||
EditPosition: typeof import('./../components/EditPosition.vue')['default'] | |||
'EditPosition copy': typeof import('./../components/EditPosition copy.vue')['default'] | |||
ElAlert: typeof import('element-plus/es')['ElAlert'] | |||
ElButton: typeof import('element-plus/es')['ElButton'] | |||
ElDialog: typeof import('element-plus/es')['ElDialog'] | |||
ElDropdown: typeof import('element-plus/es')['ElDropdown'] | |||
@@ -23,10 +24,19 @@ declare module '@vue/runtime-core' { | |||
ElIcon: typeof import('element-plus/es')['ElIcon'] | |||
ElInput: typeof import('element-plus/es')['ElInput'] | |||
ElInputNumber: typeof import('element-plus/es')['ElInputNumber'] | |||
ElMenu: typeof import('element-plus/es')['ElMenu'] | |||
ElMenuItem: typeof import('element-plus/es')['ElMenuItem'] | |||
ElMenuItemGroup: typeof import('element-plus/es')['ElMenuItemGroup'] | |||
ElOption: typeof import('element-plus/es')['ElOption'] | |||
ElPagination: typeof import('element-plus/es')['ElPagination'] | |||
ElRadio: typeof import('element-plus/es')['ElRadio'] | |||
ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup'] | |||
ElScrollbar: typeof import('element-plus/es')['ElScrollbar'] | |||
ElSelect: typeof import('element-plus/es')['ElSelect'] | |||
ElSubMenu: typeof import('element-plus/es')['ElSubMenu'] | |||
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'] | |||
ElUpload: typeof import('element-plus/es')['ElUpload'] | |||
GithubCorner: typeof import('./../components/GithubCorner/index.vue')['default'] | |||
@@ -49,6 +59,7 @@ declare module '@vue/runtime-core' { | |||
MultiUpload: typeof import('./../components/Upload/MultiUpload.vue')['default'] | |||
MyLoading: typeof import('./../components/myLoading.vue')['default'] | |||
MyLoadingIcon: typeof import('./../components/myLoadingIcon.vue')['default'] | |||
MyLoadingIcon2: typeof import('./../components/myLoadingIcon2.vue')['default'] | |||
Pagination: typeof import('./../components/Pagination/index.vue')['default'] | |||
RouterLink: typeof import('vue-router')['RouterLink'] | |||
RouterView: typeof import('vue-router')['RouterView'] | |||
@@ -69,12 +69,12 @@ request.interceptors.response.use( | |||
); | |||
return | |||
// 弹出错误 | |||
} else if (code != 200) { | |||
} else if (code != 200 && code !== 64001) { | |||
if (code == 500) { | |||
// ElMessage.error("系统异常,请稍后再试"); | |||
// ElMessage.error($t('tips.systemException')); | |||
ElMessage.error( | |||
appStore.language == "zh-cn" ? `服务器繁忙,请重试!` : `The server is busy, please try again` | |||
appStore.language == "zh-cn" ? (response.data.languageMessage && response.data.languageMessage['zh-cn']) || `服务器繁忙,请重试!` : (response.data.languageMessage && response.data.languageMessage[appStore.language]) || `The server is busy, please try again` | |||
); | |||
// 其他错误 | |||
} else { | |||
@@ -0,0 +1,141 @@ | |||
<!DOCTYPE html> | |||
<html lang="en"> | |||
<head> | |||
<meta charset="UTF-8"> | |||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |||
<title>Document</title> | |||
<style> | |||
* { | |||
padding: 0; | |||
margin: 0; | |||
} | |||
.page { | |||
padding: 50px | |||
} | |||
h1 { | |||
font-size: 20px; | |||
font-weight: 600; | |||
margin-bottom: 0.8em; | |||
} | |||
p { | |||
margin-bottom: 0.5em; | |||
font-size: 14px; | |||
line-height: 1.6; | |||
} | |||
.table { | |||
margin-top: 50px; | |||
} | |||
.table .table-wrp { | |||
margin: 1em 0 3em; | |||
overflow-x: auto; | |||
max-width: 100%; | |||
} | |||
.table table { | |||
display: table; | |||
width: 100%; | |||
border-collapse: collapse; | |||
border-spacing: 0; | |||
overflow: auto; | |||
font-size: 14px; | |||
} | |||
.table table th { | |||
font-weight: 600; | |||
text-align: left; | |||
border-bottom: 1px solid #888; | |||
padding: 10px 20px; | |||
white-space: nowrap; | |||
color: #888; | |||
} | |||
.table table td { | |||
color: #353535; | |||
text-align: left; | |||
border-bottom: 1px solid #e5e5e5; | |||
padding: 20px 20px; | |||
height: 62px; | |||
box-sizing: border-box; | |||
word-break: normal; | |||
} | |||
.style .code{ | |||
background-color: #f9f9fa; | |||
margin: 1em 0; | |||
border-radius: 4px | |||
} | |||
</style> | |||
</head> | |||
<body> | |||
<div class="page"> | |||
<!-- 文字 --> | |||
<div class="text"> | |||
<h1>概述</h1> | |||
<p>在小程序管理后台开启api加密后,开发者需要对原APl的请求内容 加密 与签名,同时AP的回包内容需要开发者验签 与 解密 。支持的api可参考接口调用。</p> | |||
<p>目前支持以下几种算法,可在MP管理页配置。</p> | |||
</div> | |||
<!-- 表格 --> | |||
<div class="table"> | |||
<h1>API请求处理</h1> | |||
<div class="table-wrp"> | |||
<table> | |||
<thead> | |||
<tr> | |||
<th>参数</th> | |||
<th>类型</th> | |||
<th>默认值</th> | |||
<th>必填</th> | |||
<th>备注</th> | |||
</tr> | |||
</thead> | |||
<tbody> | |||
<tr> | |||
<td>iv</td> | |||
<td>string</td> | |||
<td></td> | |||
<td>是</td> | |||
<td>初始向量,为16字节base64字符串(解码后为12字节随机字符串)</td> | |||
</tr> | |||
<tr> | |||
<td>data</td> | |||
<td>string</td> | |||
<td></td> | |||
<td>是</td> | |||
<td>加密后的密文,使用base64编码</td> | |||
</tr> | |||
<tr> | |||
<td>authtag</td> | |||
<td>string</td> | |||
<td></td> | |||
<td>是</td> | |||
<td>GCM模式输出的认证信息,使用base64编码</td> | |||
</tr> | |||
</tbody> | |||
</table> | |||
</div> | |||
</div> | |||
<!-- 样式 --> | |||
<div class="style"> | |||
<h1>样式</h1> | |||
<div class="code"> | |||
<pre class="language-json"> | |||
<code> | |||
<span>{</span> | |||
<span>"Sn"</span><span>:</span> <span>"fa05fe1e5bcc79b81ad5ad4b58acf787"</span><span>,</span> | |||
<span>"Key"</span><span>:</span> <span>"otUpngOjU+nVQaWJIC3D/yMLV17RKaP6t4Ot9tbnzLY="</span> | |||
<span>}</span> | |||
</code> | |||
</pre> | |||
</div> | |||
</div> | |||
</div> | |||
</body> | |||
</html> |
@@ -0,0 +1,125 @@ | |||
<template> | |||
<div class="page"> | |||
<div class=""> | |||
<el-menu | |||
default-active="1-1" | |||
class="sidebar" | |||
@open="handleOpen" | |||
@close="handleClose" | |||
> | |||
<el-sub-menu index="1"> | |||
<template #title> | |||
<span>开发前必读</span> | |||
</template> | |||
<el-menu-item index="1-1" @click="guide">服务端API签名指南</el-menu-item> | |||
</el-sub-menu> | |||
<el-sub-menu index="2"> | |||
<template #title> | |||
<span>开发接口</span> | |||
</template> | |||
<el-menu-item v-for="item in apiMenuList" :key="item.id" :index="item.id" @click="getContent(item.id)">{{ item.name }}</el-menu-item> | |||
</el-sub-menu> | |||
</el-menu> | |||
</div> | |||
<div class="content"> | |||
<div v-html="content"></div> | |||
</div> | |||
</div> | |||
</template> | |||
<script setup> | |||
import { getAvailableApiGuideApi, apiMenuApi, getContentApi } from '@/apis/api.js' | |||
const handleOpen = (key, keyPath) => { | |||
console.log(key, keyPath) | |||
if (key === '2') { | |||
getMenu() | |||
} | |||
} | |||
const handleClose = (key, keyPath) => { | |||
console.log(key, keyPath) | |||
} | |||
const content = ref(''); | |||
// 签名指南 | |||
const guide = () => { | |||
getAvailableApiGuideApi().then(res => { | |||
if(res.code === 200) { | |||
content.value = res.data.content | |||
} | |||
}) | |||
} | |||
// 开发接口 | |||
const apiMenuList = ref([]) | |||
const getMenu = () => { | |||
apiMenuApi().then(res => { | |||
if (res.code === 200) { | |||
apiMenuList.value = res.data | |||
} | |||
}) | |||
} | |||
// 详情 | |||
const getContent = (id) => { | |||
getContentApi(id).then(res => { | |||
if (res.code === 200) { | |||
content.value = res.data.content || '' | |||
} | |||
}) | |||
} | |||
onMounted(() => { | |||
guide() | |||
}); | |||
</script> | |||
<style> | |||
.sidebar.el-menu--vertical .el-sub-menu__title:hover { | |||
background-color: #fff !important; | |||
} | |||
.sidebar.el-menu--vertical .el-menu-item:hover { | |||
background-color: #fff !important; | |||
} | |||
</style> | |||
<style lang="scss" scoped> | |||
.page { | |||
display: flex; | |||
width: 100%; | |||
overflow: hidden; | |||
overflow-y: scroll; | |||
background-color: #f5f5f5; | |||
border-radius: 25px 0 0 0; | |||
min-height: calc(100vh - 80px); | |||
// text-align: center; | |||
.title { | |||
font-size: 50px; | |||
} | |||
.sidebar { | |||
position: absolute; | |||
width: 340px; | |||
top: 0; | |||
bottom: 0; | |||
overflow: auto; | |||
padding: 40px 30px; | |||
box-sizing: border-box; | |||
z-index: 1; | |||
} | |||
.content{ | |||
position: absolute; | |||
left: 340px; | |||
right: 0; | |||
top: 0; | |||
bottom:0; | |||
background: #fff; | |||
padding: 40px 30px; | |||
overflow: auto; | |||
} | |||
} | |||
:deep(.el-submenu .el-menu:hover) { | |||
background: transparent; | |||
color: #d75b5f; | |||
} | |||
</style> |
@@ -19,7 +19,7 @@ | |||
> | |||
<div class="flex text-white items-center"> | |||
<span class="flex-1 text-center">{{ | |||
$t("login.title") + " " + $t("login.login") | |||
title + " " + $t("login.login") | |||
}}</span> | |||
<el-tooltip | |||
class="box-item" | |||
@@ -136,7 +136,7 @@ | |||
> | |||
<div class="flex text-white items-center"> | |||
<span class="flex-1 text-center">{{ | |||
$t("login.title") + " " + $t("login.register") | |||
title + " " + $t("login.register") | |||
}}</span> | |||
<el-tooltip | |||
class="box-item" | |||
@@ -250,7 +250,7 @@ | |||
> | |||
<div class="flex text-white items-center"> | |||
<span class="flex-1 text-center">{{ | |||
$t("login.title") + " " + $t("login.register") | |||
title + " " + $t("login.register") | |||
}}</span> | |||
<el-tooltip | |||
class="box-item" | |||
@@ -318,7 +318,7 @@ | |||
> | |||
<div class="flex text-white items-center"> | |||
<span class="flex-1 text-center">{{ | |||
$t("login.title") + " " + $t("login.forgetPwdTitle") | |||
title + " " + $t("login.forgetPwdTitle") | |||
}}</span> | |||
<el-tooltip | |||
class="box-item" | |||
@@ -403,7 +403,7 @@ | |||
> | |||
<div class="flex text-white items-center"> | |||
<span class="flex-1 text-center">{{ | |||
$t("login.title") + " " + $t("login.resetPassword") | |||
title + " " + $t("login.resetPassword") | |||
}}</span> | |||
<el-tooltip | |||
class="box-item" | |||
@@ -524,7 +524,7 @@ | |||
> | |||
<div class="flex text-white items-center"> | |||
<span class="flex-1 text-center">{{ | |||
$t("login.title") + " " + $t("login.setNewPwd") | |||
title + " " + $t("login.setNewPwd") | |||
}}</span> | |||
<el-tooltip | |||
class="box-item" | |||
@@ -619,7 +619,7 @@ | |||
> | |||
<div class="flex text-white items-center"> | |||
<span class="flex-1 text-center">{{ | |||
$t("login.title") + " " + $t("login.login") | |||
title + " " + $t("login.login") | |||
}}</span> | |||
<el-tooltip | |||
class="box-item" | |||
@@ -716,7 +716,7 @@ | |||
> | |||
<div class="flex text-white items-center"> | |||
<span class="flex-1 text-center">{{ | |||
$t("login.title") + " " + $t("login.setInvitatioCode") | |||
title + " " + $t("login.setInvitatioCode") | |||
}}</span> | |||
<el-tooltip | |||
class="box-item" | |||
@@ -818,6 +818,15 @@ const currentLan = ref(locale); | |||
const userInfoPinia = userInfoModules(); | |||
const route = useRoute(); | |||
const router = useRouter(); | |||
/** | |||
* 获取页面标题 | |||
*/ | |||
const title = ref(<string>route.query.p || '慧影') | |||
if (title) { | |||
localStorage.setItem("title", title.value) | |||
document.title = 'Metavatar-' + title.value | |||
} | |||
/** | |||
* 按钮loading | |||
*/ | |||
@@ -0,0 +1,207 @@ | |||
<template> | |||
<div class="page justify-around"> | |||
<el-alert :title="`${$t('coindeduc.currencyValue')}:${currentValue}`" type="success" :closable="false" /> | |||
<el-table :data="tableData" style="width: 100%; height: 90%" size="large" align="center" border> | |||
<el-table-column | |||
prop="title" | |||
:label="$t('coindeduc.titleList')" | |||
align="center" | |||
/> | |||
<el-table-column | |||
prop="videoPlayUrl" | |||
:label="$t('coindeduc.videoPlayUrl')" | |||
align="center" | |||
/> | |||
<el-table-column | |||
prop="videoTime" | |||
:label="$t('coindeduc.videoTime')" | |||
align="center" | |||
/> | |||
<el-table-column | |||
prop="costPoints" | |||
:label="$t('coindeduc.costPoints')" | |||
align="center" | |||
/> | |||
<el-table-column | |||
prop="createTime" | |||
:label="$t('coindeduc.createTime')" | |||
align="center" | |||
> | |||
<template #default="scope"> | |||
{{ getDate(scope.row.createDate) }} | |||
</template> | |||
</el-table-column> | |||
<el-table-column | |||
fixed="right" | |||
:label="$t('coindeduc.operate')" | |||
align="center" | |||
> | |||
<template #default="scope"> | |||
<el-button link type="primary" size="small" @click="detailView(scope.row)">{{ $t('coindeduc.view') }}</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> | |||
<el-dialog v-model="dialogVisible" :title="`${$t('coindeduc.detailTitle')}:`" width="40%" :before-close="handleClose" > | |||
<el-form :model="form" label-width="120px"> | |||
<el-form-item label="名称"> | |||
<el-input v-model="form.title" /> | |||
</el-form-item> | |||
<el-form-item label="视频类型"> | |||
<el-radio-group v-model="form.videoType"> | |||
<el-radio :label="1">竖版</el-radio> | |||
<el-radio :label="2">横版</el-radio> | |||
</el-radio-group> | |||
</el-form-item> | |||
<el-form-item label="文案"> | |||
<el-input v-model="form.paperwork" type="textarea" /> | |||
</el-form-item> | |||
<el-form-item label="封面图"> | |||
<img :src="form.coverImg" alt="" :style="{ width: form.videoType === 1 ? '50%' : '100%'}"> | |||
</el-form-item> | |||
<el-form-item label="视频地址"> | |||
<el-input v-model="form.videoPlayUrl" /> | |||
<!-- <video :src="form.videoPlayUrl" style="width:100%;max-height: 300px;"></video> --> | |||
</el-form-item> | |||
<el-form-item label="视频时长"> | |||
<el-input v-model="form.videoTime" /> | |||
</el-form-item> | |||
<el-form-item label="创建时间"> | |||
<el-input v-model="form.createDate" /> | |||
</el-form-item> | |||
<el-form-item label="消耗金币"> | |||
<el-input v-model="form.costPoints" /> | |||
</el-form-item> | |||
<el-form-item label="消耗金币明细"> | |||
<el-input v-model="form.costPointsDetail" /> | |||
</el-form-item> | |||
<el-form-item> | |||
<el-button @click="dialogVisible = false">关闭</el-button> | |||
</el-form-item> | |||
</el-form> | |||
</el-dialog> | |||
</div> | |||
</template> | |||
<!-- videoType==1为竖,==2为横 --> | |||
<script setup> | |||
//#region 导入 | |||
import { coindedApi, getDetailApi, getUserPoinsApi, findByIdApi } from '@/apis/my.js' | |||
import dayjs from "dayjs"; | |||
import { useI18n } from "vue-i18n"; | |||
const { locale } = useI18n(); | |||
const lanChange = ref(locale); | |||
const tableData = ref([]); | |||
const pageNum = ref(1); | |||
const pageSize = ref(10); | |||
const total = ref(0); | |||
const getDate = (val) => { | |||
return dayjs(val).format("YYYY-MM-DD HH:mm:ss"); | |||
}; | |||
const handleSizeChange = (val) => { | |||
pageSize.value = val; | |||
getListData(pageNum.value, pageSize.value); | |||
}; | |||
const handleCurrentChange = (val) => { | |||
pageNum.value = val; | |||
getListData(pageNum.value, pageSize.value); | |||
}; | |||
const getListData = async (PageNum, PageSize) => { | |||
try { | |||
let data = { | |||
projectType: 2, | |||
pageNum: 1, | |||
pageSize: 10 | |||
} | |||
const res = await coindedApi(data); | |||
tableData.value = res.data.list; | |||
total.value = res.data.total * 1; | |||
} catch (error) { | |||
console.log(error, "err"); | |||
} | |||
}; | |||
// 当前币值 | |||
const currentValue = ref('') | |||
function currentValFn() { | |||
getUserPoinsApi().then(res => { | |||
currentValue.value = res.data | |||
}) | |||
} | |||
// 查看详情 | |||
const dialogVisible = ref(false) | |||
const form = ref({ | |||
title: '', | |||
videoPlayUrl: '' | |||
}) | |||
function detailView(item) { | |||
findByIdApi(item.id).then(res => { | |||
res.data.createDate = getDate(res.data.createDate) | |||
res.data.videoTime = res.data.videoTime + (lanChange.value == "zh-cn" ? '(秒)' : '(S)') | |||
form.value = res.data | |||
dialogVisible.value = true | |||
}) | |||
} | |||
onMounted(() => { | |||
getListData(1, 10); | |||
currentValFn() | |||
}); | |||
</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; | |||
.addbtn { | |||
margin-bottom: 2vh; | |||
} | |||
.formData { | |||
padding: 5vh 3vh; | |||
} | |||
.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> |
@@ -0,0 +1,193 @@ | |||
<template> | |||
<div class="page justify-around"> | |||
<el-alert :title="`${$t('recharge.currencyValue')}:${currentValue}`" type="success" :closable="false" /> | |||
<el-table :data="tableData" style="width: 100%; height: 90%" size="large" align="center" border> | |||
<el-table-column | |||
prop="productTitle" | |||
:label="$t('recharge.productTitle')" | |||
align="center" | |||
/> | |||
<el-table-column | |||
prop="orderNumber" | |||
:label="$t('recharge.orderNumber')" | |||
align="center" | |||
/> | |||
<el-table-column | |||
prop="paymentStr" | |||
:label="$t('recharge.payment')" | |||
align="center" | |||
/> | |||
<el-table-column | |||
prop="createTime" | |||
:label="$t('recharge.createTime')" | |||
align="center" | |||
> | |||
<template #default="scope"> | |||
{{ getDate(scope.row.createTime) }} | |||
</template> | |||
</el-table-column> | |||
<el-table-column | |||
fixed="right" | |||
:label="$t('recharge.operate')" | |||
align="center" | |||
> | |||
<template #default="scope"> | |||
<el-button link type="primary" size="small" @click="detailView(scope.row)">{{ $t('recharge.view') }}</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> | |||
<el-dialog v-model="dialogVisible" :title="`${ $t('recharge.detailTitle')}:`" width="40%" > | |||
<el-form :model="form" label-width="120px"> | |||
<el-form-item :label="$t('recharge.productTitle')"> | |||
<el-input v-model="form.productTitle" /> | |||
</el-form-item> | |||
<el-form-item :label="$t('recharge.orderNumber')"> | |||
<el-input v-model="form.orderNumber" /> | |||
</el-form-item> | |||
<el-form-item :label="$t('recharge.payVendor')"> | |||
<el-radio-group v-model="form.payVendor"> | |||
<el-radio :label="2">{{ $t('recharge.weChat') }}</el-radio> | |||
<el-radio :label="4">{{$t('recharge.alipay')}}</el-radio> | |||
</el-radio-group> | |||
</el-form-item> | |||
<el-form-item :label="$t('recharge.paymentStr')"> | |||
<el-input v-model="form.paymentStr" /> | |||
</el-form-item> | |||
<el-form-item :label="$t('recharge.orderStatus')"> | |||
<el-input v-model="form.orderStatus" /> | |||
</el-form-item> | |||
<el-form-item :label="$t('recharge.paymentTime')"> | |||
<el-input v-model="form.paymentTime" /> | |||
</el-form-item> | |||
<el-form-item> | |||
<el-button @click="dialogVisible = false">{{ $t('recharge.close') }}</el-button> | |||
</el-form-item> | |||
</el-form> | |||
</el-dialog> | |||
</div> | |||
</template> | |||
<!-- videoType==1为竖,==2为横 --> | |||
<script setup> | |||
//#region 导入 | |||
import { rechargeListApi, getDetailApi, getUserPoinsApi, findByNumberApi } from '@/apis/my.js' | |||
import dayjs from "dayjs"; | |||
import { useI18n } from "vue-i18n"; | |||
const { locale } = useI18n(); | |||
const lanChange = ref(locale); | |||
const tableData = ref([]); | |||
const pageNum = ref(1); | |||
const pageSize = ref(10); | |||
const total = ref(0); | |||
const getDate = (val) => { | |||
return dayjs(val).format("YYYY-MM-DD HH:mm:ss"); | |||
}; | |||
const handleSizeChange = (val) => { | |||
pageSize.value = val; | |||
getListData(pageNum.value, pageSize.value); | |||
}; | |||
const handleCurrentChange = (val) => { | |||
pageNum.value = val; | |||
getListData(pageNum.value, pageSize.value); | |||
}; | |||
const getListData = async (PageNum, PageSize) => { | |||
try { | |||
let data = { | |||
projectType: 2, | |||
pageNum: 1, | |||
pageSize: 10 | |||
} | |||
const res = await rechargeListApi(data); | |||
tableData.value = res.data.list; | |||
total.value = res.data.total * 1; | |||
} catch (error) { | |||
console.log(error, "err"); | |||
} | |||
}; | |||
// 当前币值 | |||
const currentValue = ref('') | |||
function currentValFn() { | |||
getUserPoinsApi().then(res => { | |||
currentValue.value = res.data | |||
}) | |||
} | |||
// 查看详情 | |||
const dialogVisible = ref(false) | |||
const form = ref({ | |||
productTitle: '', | |||
orderStatus:'', | |||
paymentTime: '', | |||
}) | |||
function detailView(item) { | |||
findByNumberApi(item.id).then(res => { | |||
res.data.paymentTime = getDate(res.data.paymentTime) | |||
res.data.orderStatus = res.data.orderStatus === 3 ? lanChange.value == "zh-cn" ? '支付成功' : 'Payment successful': lanChange.value == "zh-cn" ? '支付失败' : 'Payment failed' | |||
form.value = res.data | |||
dialogVisible.value = true | |||
}) | |||
} | |||
onMounted(() => { | |||
getListData(1, 10); | |||
currentValFn() | |||
}); | |||
</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; | |||
.addbtn { | |||
margin-bottom: 2vh; | |||
} | |||
.formData { | |||
padding: 5vh 3vh; | |||
} | |||
.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,22 +0,0 @@ | |||
<template> | |||
<div class="page"> | |||
<div class="title">{{ $t("API.comingSoon") }}</div> | |||
</div> | |||
</template> | |||
<script setup> | |||
// import { ref } from 'vue' | |||
</script> | |||
<style lang="scss" scoped> | |||
.page { | |||
padding: 30px; | |||
width: 100%; | |||
overflow: hidden; | |||
overflow-y: scroll; | |||
background-color: #fff; | |||
min-height: calc(100vh - 80px); | |||
text-align: center; | |||
.title { | |||
font-size: 50px; | |||
} | |||
} | |||
</style> |
@@ -481,6 +481,7 @@ const checkVideoStatus = async () => { | |||
// 如果列表中没有生成中的视频,不发送请求 | |||
const intervalId = setInterval(async () => { | |||
// && notGenerateList2.value.length == 0; | |||
console.log(""); | |||
if (notGenerateList.value.length == 0) { | |||
return; | |||
} | |||
@@ -509,7 +510,7 @@ onMounted(() => { | |||
isLoading.value = true; | |||
getPhotoVideoList(pageNum.value, pageSize.value, title.value); | |||
// checkVideoStatus(); | |||
checkVideoStatus(); | |||
}); | |||
//#endregion --------------------------- | |||
</script> | |||
@@ -1,141 +1,48 @@ | |||
<template> | |||
<div class="page"> | |||
<div class="commoditylIst" ref="scrollContainerRef" @wheel="handleWheel"> | |||
<div class="item" v-for="item in packageList" :key="item.typeDesc"> | |||
<!-- 遮罩层 --> | |||
<div class="mask" v-if="item.type != 1"> | |||
<el-icon><i-ep-Lock /></el-icon> | |||
</div> | |||
<div @click="clickPayDialog(item)" v-if="item.typeDesc"> | |||
<div class="line" :style="`background-color:${item.color} ;`"></div> | |||
<div class="info"> | |||
<!-- 商品信息 --> | |||
<div class="content"> | |||
<div class="titleBox"> | |||
<div class="title"> | |||
{{ lanChange == "zh-cn" ? item.typeDesc : item.englishName }} | |||
<div class="commoditylIst"> | |||
<el-scrollbar :always="true"> | |||
<div class="scrollbar-flex-content"> | |||
<div class="item" v-for="item in packageList" :key="item.typeDesc" :class="item.sellPriceRmb <= 0 ? 'dashed' : ''"> | |||
<!-- @click="clickPayDialog(item)" --> | |||
<div> | |||
<div class="line" :style="`background-color:${ item.sellPriceRmb > 0 ? item.color : '#eee'} ;`"></div> | |||
<div class="info"> | |||
<!-- 商品信息 --> | |||
<div class="content"> | |||
<div class="titleBox"> | |||
<!-- <p class="iconText" v-if="item.sellPriceRmb <= 0" >会员权益</p> --> | |||
<div class="title"> | |||
{{ item.title }} | |||
</div> | |||
</div> | |||
<template v-if="item.sellPriceRmb > 0"> | |||
<div class="money"> | |||
<span class="price">{{ | |||
item.sellPriceRmb / 100 | |||
}} ¥</span | |||
>/ <span style="text-decoration:line-through;"> {{ $t("store.priceRmb") }}{{ item.priceRmb / 100 }}</span> | |||
</div> | |||
<div class="time"> | |||
{{ $t("store.glod") }}<span> {{ item.glod }}</span | |||
> | |||
</div> | |||
<div v-if="item.sellPriceRmb > 0" class="button" @click="clickPayDialog(item)" :style="`background-color: #f3af00 ;`"> | |||
{{ $t("store.createOrder") }} | |||
</div> | |||
</template> | |||
</div> | |||
<div class="money"> | |||
<span class="price">{{ | |||
lanChange == "zh-cn" ? item.rmb + "¥" : item.dollar + "$" | |||
}}</span | |||
>/{{ item.validityDuration }}{{ $t("shop.day") }} | |||
</div> | |||
<div class="time"> | |||
<span>{{ item.credit }}</span | |||
>{{ $t("shop.score") }} | |||
</div> | |||
<div | |||
v-if="item.type != 1" | |||
class="button" | |||
:style="`background-color:${item.color} ;`" | |||
> | |||
{{ $t("createVideo.comingSoon") }} | |||
</div> | |||
<div | |||
v-else | |||
class="button" | |||
:style="`background-color:${item.color} ;`" | |||
> | |||
{{ $t("shop.selectPlan") }} | |||
</div> | |||
</div> | |||
<!-- 商品权益 --> | |||
<div class="authority"> | |||
<div class="authority-item"> | |||
{{ $t("shop.InviteGetscore") }}: | |||
<span> | |||
<i>{{ item.inviteUserCredit }}</i | |||
>{{ $t("shop.score") }}</span | |||
> | |||
</div> | |||
<div class="authority-item"> | |||
{{ $t("shop.createVideoPrice") }}:<span | |||
><i>{{ item.videoPrice }}</i | |||
>{{ $t("shop.score") }}</span | |||
> | |||
</div> | |||
<div class="authority-item"> | |||
{{ $t("shop.AIGeneratesPhotoPrices") }}:<span | |||
><i>{{ item.photoPrice }}</i | |||
>{{ $t("shop.score") }}</span | |||
> | |||
</div> | |||
<div class="authority-item"> | |||
{{ $t("shop.UnitChargeDuration") }}:<span | |||
><i>{{ item.chargeTime }}</i | |||
>{{ $t("shop.second") }}</span | |||
> | |||
</div> | |||
<div class="authority-item"> | |||
{{ $t("shop.Language") }}:<span | |||
><i>{{ item.userPackageDetails[0].languageDesc }}</i></span | |||
> | |||
</div> | |||
<div class="authority-item"> | |||
{{ $t("shop.sound") }}:<span | |||
><i>{{ item.userPackageDetails[0].soundDesc }}</i></span | |||
> | |||
</div> | |||
<div class="authority-item"> | |||
{{ $t("shop.IndividualVideoDuration") }}:<span | |||
><i>{{ item.userPackageDetails[0].videoTime }}</i | |||
>{{ $t("shop.second") }}</span | |||
> | |||
</div> | |||
<div class="authority-item"> | |||
{{ $t("shop.Watermark") }}:<span>{{ | |||
item.userPackageDetails[0].aiPortrait == 0 | |||
? $t("shop.yes") | |||
: $t("shop.no") | |||
}}</span> | |||
</div> | |||
<div class="authority-item"> | |||
{{ $t("shop.AIGeneratedPortrait") }}:<span>{{ | |||
item.userPackageDetails[0].aiPortrait == 0 | |||
? $t("shop.no") | |||
: $t("shop.yes") | |||
}}</span> | |||
</div> | |||
<div class="authority-item"> | |||
{{ $t("shop.PhotoSinging") }}:<span>{{ | |||
item.userPackageDetails[0].photoSing == 0 | |||
? $t("shop.no") | |||
: $t("shop.yes") | |||
}}</span> | |||
</div> | |||
<div class="authority-item"> | |||
{{ $t("shop.AIGeneratedText") }}:<span | |||
><i>{{ item.userPackageDetails[0].aiCreateTime }}</i></span | |||
> | |||
</div> | |||
<div class="authority-item"> | |||
{{ $t("shop.VideoResolution") }}:<span>{{ | |||
item.userPackageDetails[0].resolutionRatioDesc | |||
}}</span> | |||
<!-- 商品权益 --> | |||
<div class="authority"> | |||
<div v-html="item.detail"></div> | |||
</div> | |||
<!-- <div class="authority-item"> | |||
{{ $t("shop.DigitalPersonTemplate") }}:{{ | |||
item.userPackageDetails[0].humanTemplateDesc | |||
}} | |||
</div> --> | |||
<!-- <div | |||
class="authority-item" | |||
v-for="items in item.authority" | |||
:key="items" | |||
> | |||
<span>✔</span>{{ items }} | |||
</div> --> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</el-scrollbar> | |||
<!-- 企业版 --> | |||
<div class="item" @click="showTalkUsDialog = true"> | |||
<!-- 遮罩层 --> | |||
<!-- <div class="item" @click="showTalkUsDialog = true"> | |||
<div class="mask" v-if="false"> | |||
<el-icon><i-ep-Lock /></el-icon> | |||
</div> | |||
@@ -147,7 +54,6 @@ | |||
{{ $t("shop.Ent") }} | |||
</div> | |||
</div> | |||
<!-- 描述 --> | |||
<div class="description"> | |||
<div> | |||
{{ lanChange == "zh-cn" ? "所有权限" : "All Pro Benefits" }} | |||
@@ -178,64 +84,68 @@ | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</div> --> | |||
</div> | |||
<!-- 对话框 --> | |||
<el-dialog v-if="false" v-model="showPayDialog" width="60%" center> | |||
<!-- 对话框 v-if="false"--> | |||
<el-dialog v-model="showPayDialog" v-if="showPayDialog" | |||
:title="$t('store.payType')" width="300px"> | |||
<div class="payDialog"> | |||
<div class="left"> | |||
<div class="title">{{ $t(presentItme.value.title) }}</div> | |||
<div class="price"> | |||
<span>{{ presentItme.value.price }}</span> | |||
元/{{ presentItme.value.priceTime }} | |||
</div> | |||
<div | |||
class="authority" | |||
v-for="item in presentItme.value.authority" | |||
:key="item" | |||
> | |||
{{ item }} | |||
</div> | |||
</div> | |||
<div class="right"> | |||
<div | |||
style="background-color: #07c160; cursor: pointer" | |||
@click="showOrderCode(1)" | |||
> | |||
{{ $t("shop.WeChatPay") }} | |||
</div> | |||
<div | |||
style="background-color: #1378fe; cursor: pointer" | |||
@click="showOrderCode(2)" | |||
> | |||
{{ $t("shop.Alipay") }} | |||
</div> | |||
<div | |||
style="background-color: #0070ba; cursor: pointer" | |||
@click="showOrderCode(3)" | |||
> | |||
Paypal | |||
</div> | |||
</div> | |||
<el-radio-group v-model="payVendor"> | |||
<el-radio label="4" border> | |||
<img src="../../assets/img/alipay.png" alt="" />{{ $t("recharge.alipay") }} | |||
</el-radio> | |||
<el-radio label="2" border> | |||
<img src="../../assets/img/weChat.png" alt="" />{{ $t("recharge.weChat") }} | |||
</el-radio> | |||
</el-radio-group> | |||
</div> | |||
<!-- 二维码弹出框 --> | |||
<el-dialog | |||
v-model="orderCodeDialogShow" | |||
width="30%" | |||
width="500px" | |||
append-to-body | |||
destroy-on-close | |||
@closed="clearCode" | |||
:close-on-click-modal="false" | |||
> | |||
<div class="orderCodeDialog"> | |||
<div class="orderCodeDialog" v-loading="loading" | |||
:element-loading-text="`${$t('store.pay')}`"> | |||
<div class="codeImg"> | |||
<my-Loading-Icon v-if="!orderCodeUrl"></my-Loading-Icon> | |||
<img v-if="orderCodeUrl" src="../../assets/img/false1.png" alt="" /> | |||
<my-Loading-Icon2 | |||
v-if="!payCodeUrl && !iframeBody" | |||
></my-Loading-Icon2> | |||
<!-- :callback="qrcode" --> | |||
<vue-qr v-if="payCodeUrl" :text="payCodeUrl" :size="280"></vue-qr> | |||
<iframe | |||
v-show="iframeBody" | |||
id="myIframe" | |||
width="210PX" | |||
height="205PX" | |||
frameborder="0" | |||
></iframe> | |||
</div> | |||
<div class="tips">扫描二维码进行付款</div> | |||
<div class="btnBox"> | |||
<div>刷新二维码</div> | |||
<div class="tips"> | |||
{{ | |||
lanChange == "zh-cn" | |||
? `扫描二维码进行付款` | |||
: `Scan the QR code for payment` | |||
}} | |||
</div> | |||
<!-- <div class="btnBox"> | |||
<div @click="RefreshQR"> | |||
{{ lanChange == "zh-cn" ? `刷新二维码` : `Refresh QR code` }} | |||
</div> | |||
</div> --> | |||
</div> | |||
</el-dialog> | |||
<template #footer> | |||
<span class="dialog-footer"> | |||
<el-button size="small" @click="showPayDialog = false">{{ $t("store.cancel") }}</el-button> | |||
<el-button size="small" type="primary" @click="payConfirm"> | |||
{{$t("store.confirm")}} | |||
</el-button> | |||
</span> | |||
</template> | |||
</el-dialog> | |||
<!-- 联系我们对话框 --> | |||
@@ -249,10 +159,14 @@ | |||
<script setup> | |||
//#region 导入 | |||
import { getCurrentInstance, ref, onMounted } from "vue"; | |||
// import { packageInfoApi } from "@/apis/myStore"; | |||
import { packageInfoApi } from "@/apis/myStore"; | |||
import { useI18n } from "vue-i18n"; | |||
import talkUs from "@/components/talkUs.vue"; | |||
import { useRoute, useRouter } from "vue-router"; | |||
import { createOrderApi, createPayApi, getOrderStatusApi } from "@/apis/pay"; | |||
import { orderDetailApi, findStatusApi } from '@/apis/myStore.js' | |||
import vueQr from 'vue-qr/src/packages/vue-qr.vue'; | |||
const route = useRoute(); | |||
const router = useRouter(); | |||
const { locale } = useI18n(); | |||
@@ -261,236 +175,33 @@ const lanChange = ref(locale); | |||
const AccessToken = localStorage.getItem("AccessToken"); // 判断有没有登录 | |||
//#endregion ------------------------------------ | |||
//#region 各个套餐的逻辑 | |||
const packageList = ref([ | |||
{ | |||
id: 1, | |||
type: 1, | |||
typeDesc: "基础版", | |||
englishName: "Trial", | |||
dollar: "0.00", | |||
rmb: "0.00", | |||
credit: 100, | |||
validityDuration: 30, | |||
inviteUserCredit: 10, | |||
videoPrice: 10, | |||
photoPrice: 10, | |||
talkPrice: 20, | |||
chargeTime: 60, | |||
createDate: 1686814258000, | |||
updateDate: 1686814258000, | |||
isDel: 0, | |||
color: "#f3af00", | |||
userPackageDetails: [ | |||
{ | |||
id: 1, | |||
detailType: 1, | |||
detailTypeDesc: "照片说话", | |||
packageId: 1, | |||
watermark: 1, | |||
watermarkDesc: "是", | |||
language: 1, | |||
languageDesc: "50+", | |||
sound: 1, | |||
soundDesc: "400+", | |||
videoTime: 60, | |||
aiPortrait: 0, | |||
aiPortraitDesc: "否", | |||
photoSing: 0, | |||
photoSingDesc: "否", | |||
aiCreateTime: 0, | |||
resolutionRatio: 1, | |||
resolutionRatioDesc: "720p", | |||
createDate: 1686882177000, | |||
updateDate: 1686882177000, | |||
isDel: 0, | |||
}, | |||
{ | |||
id: 4, | |||
detailType: 2, | |||
detailTypeDesc: "口播", | |||
packageId: 1, | |||
watermark: 1, | |||
watermarkDesc: "是", | |||
language: 1, | |||
languageDesc: "50+", | |||
sound: 1, | |||
soundDesc: "400+", | |||
videoTime: 60, | |||
aiCreateTime: 0, | |||
resolutionRatio: 1, | |||
resolutionRatioDesc: "720p", | |||
humanTemplate: 1, | |||
humanTemplateDesc: "免费", | |||
createDate: 1686882177000, | |||
updateDate: 1686882177000, | |||
isDel: 0, | |||
}, | |||
], | |||
}, | |||
{ | |||
id: 2, | |||
type: 2, | |||
typeDesc: "专业版", | |||
englishName: "Pro", | |||
dollar: "7.99", | |||
rmb: "49.99", | |||
credit: 200, | |||
validityDuration: 30, | |||
inviteUserCredit: 10, | |||
videoPrice: 6, | |||
photoPrice: 6, | |||
talkPrice: 16, | |||
chargeTime: 60, | |||
createDate: 1686814258000, | |||
updateDate: 1686814258000, | |||
isDel: 0, | |||
color: "#c971ff", | |||
userPackageDetails: [ | |||
{ | |||
id: 2, | |||
detailType: 1, | |||
detailTypeDesc: "照片说话", | |||
packageId: 2, | |||
watermark: 0, | |||
watermarkDesc: "否", | |||
language: 1, | |||
languageDesc: "50+", | |||
sound: 1, | |||
soundDesc: "400+", | |||
videoTime: 300, | |||
aiPortrait: 1, | |||
aiPortraitDesc: "是", | |||
photoSing: 1, | |||
photoSingDesc: "是", | |||
aiCreateTime: 30, | |||
resolutionRatio: 2, | |||
resolutionRatioDesc: "1080p", | |||
createDate: 1686882177000, | |||
updateDate: 1686882177000, | |||
isDel: 0, | |||
}, | |||
{ | |||
id: 5, | |||
detailType: 2, | |||
detailTypeDesc: "口播", | |||
packageId: 2, | |||
watermark: 0, | |||
watermarkDesc: "否", | |||
language: 1, | |||
languageDesc: "50+", | |||
sound: 1, | |||
soundDesc: "400+", | |||
videoTime: 300, | |||
aiCreateTime: 100, | |||
resolutionRatio: 2, | |||
resolutionRatioDesc: "1080p", | |||
humanTemplate: 2, | |||
humanTemplateDesc: "VIP", | |||
createDate: 1686882177000, | |||
updateDate: 1686882177000, | |||
isDel: 0, | |||
}, | |||
], | |||
}, | |||
{ | |||
id: 3, | |||
type: 3, | |||
typeDesc: "加强版", | |||
englishName: "Advanced", | |||
dollar: "39.99", | |||
rmb: "279.99", | |||
credit: 1200, | |||
validityDuration: 30, | |||
inviteUserCredit: 10, | |||
videoPrice: 5, | |||
photoPrice: 5, | |||
talkPrice: 15, | |||
chargeTime: 60, | |||
createDate: 1686814258000, | |||
updateDate: 1686814258000, | |||
isDel: 0, | |||
color: "#7b61ff", | |||
userPackageDetails: [ | |||
{ | |||
id: 3, | |||
detailType: 1, | |||
detailTypeDesc: "照片说话", | |||
packageId: 3, | |||
watermark: 0, | |||
watermarkDesc: "否", | |||
language: 1, | |||
languageDesc: "50+", | |||
sound: 1, | |||
soundDesc: "400+", | |||
videoTime: 300, | |||
aiPortrait: 1, | |||
aiPortraitDesc: "是", | |||
photoSing: 1, | |||
photoSingDesc: "是", | |||
aiCreateTime: 200, | |||
resolutionRatio: 2, | |||
resolutionRatioDesc: "1080p", | |||
createDate: 1686882177000, | |||
updateDate: 1686882177000, | |||
isDel: 0, | |||
}, | |||
{ | |||
id: 6, | |||
detailType: 2, | |||
detailTypeDesc: "口播", | |||
packageId: 3, | |||
watermark: 0, | |||
watermarkDesc: "否", | |||
language: 1, | |||
languageDesc: "50+", | |||
sound: 1, | |||
soundDesc: "400+", | |||
videoTime: 300, | |||
aiCreateTime: 200, | |||
resolutionRatio: 2, | |||
resolutionRatioDesc: "1080p", | |||
humanTemplate: 2, | |||
humanTemplateDesc: "VIP", | |||
createDate: 1686882177000, | |||
updateDate: 1686882177000, | |||
isDel: 0, | |||
}, | |||
], | |||
}, | |||
]); | |||
const packageList = ref([]); | |||
async function getPackageList() { | |||
const res = await packageInfoApi(); | |||
packageList.value = res.data; | |||
} | |||
const showPayDialog = ref(false); //套餐信息dialog显示隐藏 | |||
const presentItme = reactive({}); //点击的套餐项 | |||
// const presentItme = ref({}); //点击的套餐项 | |||
function clickPayDialog(item) { | |||
presentItme.value = item; | |||
createOrder(item) | |||
showPayDialog.value = true; | |||
} | |||
function showOrderCode(type) { | |||
orderCodeDialogShow.value = true; | |||
} | |||
//#endregion ------------------------------------ | |||
//#region 点击套餐内的支付 | |||
function showOrderCode(type) { | |||
orderCodeDialogShow.value = true; | |||
myPayVendor.value = type; | |||
createOrderFunc(); | |||
} | |||
const orderCodeDialogShow = ref(false); | |||
const orderCodeUrl = ref(null); | |||
//#endregion ------------------------------------ | |||
//#region $t在script中的使用 | |||
// const { | |||
// appContext: { | |||
// config: { globalProperties }, | |||
// }, | |||
// } = getCurrentInstance(); | |||
// const string = "createVideo.typeScript"; | |||
// const t = globalProperties.$t(string); | |||
//#endregion ------------------------------------ | |||
//#region 页面滚动 | |||
const scrollContainerRef = ref(null); | |||
function handleWheel(event) { | |||
@@ -517,20 +228,191 @@ const updateShowTalkUsDialog = (newValue) => { | |||
//#region 页面初始化 | |||
onMounted(async () => { | |||
// getPackageList(); | |||
getPackageList(); | |||
// createOrderFunc(); | |||
}); | |||
//#endregion ------------------------------------ | |||
//#region | |||
//#region 支付 | |||
const myPayVendor = ref(null); // 2微信 4支付宝 | |||
const payCodeUrl = ref(null); //付款二维码地址 | |||
const payCodeImg = ref(null); //付款二维码图片 | |||
// 支付失败处理 | |||
function payErrorHandle() { | |||
orderCodeDialogShow.value = false; | |||
ElMessage.error( | |||
lanChange.value == "zh-cn" | |||
? `获取订单失败,请重试` | |||
: `Failed to get the order, please try again` | |||
); | |||
} | |||
// 获取订单 | |||
const myOrderNumber = ref(null); //订单号 | |||
async function createOrderFunc() { | |||
const data = { | |||
productId: 30, | |||
}; | |||
try { | |||
const res = await createOrderApi(data); | |||
if (res.code == 200) { | |||
myOrderNumber.value = res.data; | |||
createPayFunc(res.data); | |||
} else { | |||
payErrorHandle(); | |||
} | |||
} catch (error) { | |||
payErrorHandle(); | |||
} | |||
} | |||
// 获取订单详情 | |||
let iframeBody = ref(null); | |||
const iframeDom = ref(null); | |||
const loading = ref(false) | |||
async function createPayFunc(orderNumber) { | |||
const data = { | |||
orderNumber, | |||
payVendor: payVendor.value, | |||
}; | |||
try { | |||
const res = await createPayApi(data); | |||
if (res.code == 200) { | |||
// 支付宝获取iframe内容 | |||
if (res.data.body) { | |||
orderCodeDialogShow.value = true; | |||
setTimeout(() => { | |||
iframeBody.value = res.data.body; | |||
iframeDom.value = document.getElementById("myIframe"); | |||
iframeDom.value.srcdoc = iframeBody.value; | |||
}, 1000) | |||
} | |||
// 直接获取二维码 | |||
if (res.data.codeUrl) { | |||
payCodeUrl.value = res.data.codeUrl; | |||
// showOrderCode(payVendor.value) | |||
orderCodeDialogShow.value = true; | |||
} | |||
// findStatus() | |||
await getStatusOfOrderFunc(orderNumber); | |||
} else { | |||
payErrorHandle(); | |||
} | |||
} catch (error) { | |||
payErrorHandle(); | |||
} | |||
} | |||
// 获取订单支付状态 payStatus 查询支付状态 0:待支付,2:支付中,3:已支付 | |||
async function getStatusOfOrderFunc(orderNumber) { | |||
// if ( | |||
// route.path != "/myStore" || | |||
// orderCodeDialogShow.value == false || | |||
// orderNumber != payVendor.value | |||
// ) { | |||
// return; | |||
// } | |||
try { | |||
// let payVendor = payVendor.value; | |||
let data = { | |||
orderNumber, | |||
payVendor: payVendor.value | |||
} | |||
const res = await findStatusApi(data); | |||
if (res.code == 200) { | |||
if (res.data.orderStatus == 1) { // 页面就不动,继续定时请求 | |||
setTimeout(() => { | |||
getStatusOfOrderFunc(orderNumber); | |||
}, 3000); | |||
} else if (res.data.orderStatus == 2) { // 页面就不动, loading....的效果盖在二维码之前,继续定时请求 | |||
loading.value = true | |||
setTimeout(() => { | |||
getStatusOfOrderFunc(orderNumber); | |||
}, 3000); | |||
} else if (res.data.orderStatus == 3) { // 提示支付成功,关闭当前页 | |||
orderCodeDialogShow.value = false; | |||
showPayDialog.value = false | |||
ElMessage.success( | |||
lanChange.value == "zh-cn" ? `支付成功!` : `Payment is successful!` | |||
); | |||
} else { // 提示支付失败,关闭当前页 | |||
ElMessage.success('支付失败'); | |||
} | |||
} else { | |||
setTimeout(() => { | |||
getStatusOfOrderFunc(orderNumber); | |||
}, 3000); | |||
} | |||
} catch (error) { | |||
console.log(error, "error"); | |||
ElMessage.error( | |||
lanChange.value == "zh-cn" | |||
? `获取订单失败,请重试` | |||
: `Failed to get the order, please try again` | |||
); | |||
} | |||
} | |||
// 生成二维码 | |||
// function qrcode() { | |||
// return; | |||
// } | |||
// 关闭二维码弹窗 | |||
function clearCode() { | |||
myPayVendor.value = null; // 2微信 4支付宝 | |||
payCodeUrl.value = null; | |||
iframeBody.value = null; | |||
showPayDialog.value = false; | |||
} | |||
// 刷新二维码 | |||
function RefreshQR() { | |||
payCodeUrl.value = null; | |||
iframeBody.value = null; | |||
// createOrderFunc(); | |||
createPayFunc(myOrderNumber.value); | |||
} | |||
//#endregion ------------------------------------ | |||
//#region | |||
//#endregion ------------------------------------ | |||
</script> | |||
const payVendor = ref('4') | |||
const orderNumber = ref('') | |||
// 创建订单 | |||
function createOrder(item) { | |||
createOrderApi({productId: item.id}).then(res => { | |||
orderNumber.value = res.data | |||
}) | |||
} | |||
// 创建支付 | |||
function payConfirm() { | |||
createPayFunc(orderNumber.value); | |||
} | |||
// 获取订单详情 | |||
function getOrderDetail(item) { | |||
orderDetailApi(item.id).then(res => { | |||
}) | |||
} | |||
//每隔一分钟运行一次保存方法 | |||
// const timer = setInterval(()=>{ | |||
// findStatus() | |||
// },1000) | |||
function findStatus() { | |||
let data = { | |||
orderNumber: '', | |||
payVendor: '' | |||
} | |||
findStatusApi(data).then(res => { | |||
if (res.data !== 2) { // 如果是2就不停的调,直到返回1、3、4 | |||
clearInterval(timer); | |||
} | |||
}) | |||
} | |||
</script> | |||
<style> | |||
.el-dialog { | |||
border-radius: 5px !important; | |||
}</style> | |||
<style lang="scss" scoped> | |||
.page { | |||
// min-width: calc(100vw - 210px); | |||
height: calc(100vh - 80px); | |||
@@ -552,18 +434,14 @@ onMounted(async () => { | |||
overflow-x: scroll; | |||
padding: 30px 20px 20px 10px; | |||
max-width: 100%; | |||
// height: 75%; | |||
// overflow: hidden; | |||
// overflow-x: scroll; | |||
// scrollbar-width: none; /* 隐藏滚动条(Chrome、Firefox) */ | |||
// -ms-overflow-style: none; /* 隐藏滚动条(IE、Edge) */ | |||
// &::-webkit-scrollbar { | |||
// display: none; /* 隐藏滚动条(Safari、Chrome) */ | |||
// } | |||
.scrollbar-flex-content{ | |||
display: flex; | |||
padding-bottom: 30px; | |||
} | |||
.item { | |||
position: relative; | |||
width: 480px; | |||
width: 450px; | |||
// height: 680px; | |||
margin-left: 45px; | |||
background-color: #fffefd; | |||
@@ -573,6 +451,9 @@ onMounted(async () => { | |||
overflow: hidden; | |||
transition: all 0.2s; | |||
cursor: pointer; | |||
&.dashed { | |||
border: 1px dashed #c0bfbd; | |||
} | |||
&:hover { | |||
.mask { | |||
display: block; | |||
@@ -606,10 +487,21 @@ onMounted(async () => { | |||
padding: 20px; | |||
border-bottom: 1px solid #c0bfbd; | |||
cursor: pointer; | |||
position: relative; | |||
.titleBox { | |||
display: flex; | |||
justify-content: space-between; | |||
} | |||
.iconText{ | |||
font-size: 14px; | |||
position: absolute; | |||
left:-20px; | |||
top:0; | |||
transform: rotate(-45deg); | |||
background: rgb(243, 175, 0); | |||
padding: 3px 10px; | |||
color: #fff; | |||
} | |||
.title { | |||
font-size: 30px; | |||
font-weight: 700; | |||
@@ -636,7 +528,6 @@ onMounted(async () => { | |||
text-align: end; | |||
.price { | |||
font-size: 30px; | |||
font-weight: 700; | |||
color: #242625; | |||
cursor: pointer; | |||
} | |||
@@ -649,10 +540,10 @@ onMounted(async () => { | |||
cursor: pointer; | |||
margin-bottom: 20px; | |||
span { | |||
font-weight: 700; | |||
color: #242625; | |||
cursor: pointer; | |||
margin-right: 5px; | |||
padding-left: 10px; | |||
} | |||
} | |||
@@ -729,62 +620,29 @@ onMounted(async () => { | |||
} | |||
} | |||
// 支付弹窗 | |||
.payDialog { | |||
display: flex; | |||
position: relative; | |||
min-height: 500px; | |||
.left { | |||
width: 35%; | |||
border-right: 1px solid #7c7c7a; | |||
.title { | |||
color: #242625; | |||
font-weight: 700; | |||
font-size: 30px; | |||
text-align: center; | |||
} | |||
.price { | |||
span { | |||
font-size: 30px; | |||
font-weight: 700; | |||
color: #242625; | |||
} | |||
} | |||
.authority { | |||
padding: 10px 20px; | |||
} | |||
} | |||
.right { | |||
width: 65%; | |||
position: absolute; | |||
top: 20%; | |||
right: 0%; | |||
padding-left: 20%; | |||
> div { | |||
width: 200px; | |||
height: 40px; | |||
// border: 1px solid #242625; | |||
border-radius: 10px; | |||
text-align: center; | |||
line-height: 40px; | |||
margin: 30px; | |||
color: #fff; | |||
} | |||
.el-radio{ | |||
width: 100px; | |||
img { | |||
vertical-align: middle; | |||
margin-right: 5px; | |||
width: 16px; | |||
} | |||
} | |||
// 二维码弹窗 | |||
.orderCodeDialog { | |||
width: 100%; | |||
.codeImg { | |||
display: flex; | |||
margin: auto; | |||
justify-content: space-evenly; | |||
// justify-content: space-evenly; | |||
align-items: center; | |||
width: 300px; | |||
height: 300px; | |||
width: 220PX; | |||
height: 220PX; | |||
border: 1px solid #ccc; | |||
border-radius: 15px; | |||
overflow: hidden; | |||
padding: 10px; | |||
padding: 13px; | |||
img { | |||
width: 100%; | |||
height: 100%; | |||
@@ -0,0 +1,7 @@ | |||
<!-- | |||
* @Description: 定制分身 | |||
--> | |||
<template> | |||
<iframe src="/priMakeHtml/siyouhuabushu/index.shtml" style="width: 100%;height:86vh"></iframe> | |||
</template> |
@@ -0,0 +1,6 @@ | |||
<!-- | |||
* @Description: 定制声纹 | |||
--> | |||
<template> | |||
<iframe src="/priMakeHtml/dingzhifenshen/index.shtml" style="width: 100%;height:86vh"></iframe> | |||
</template> |
@@ -0,0 +1,944 @@ | |||
<template> | |||
<div class="page"> | |||
<!-- 搜索框 --> | |||
<div class="top"> | |||
<div class="search"> | |||
<el-input | |||
style="width: 300px" | |||
v-model="title" | |||
:placeholder="$t('myCreating.search')" | |||
@keyup.enter="searchVideoList" | |||
/> | |||
<el-icon class="icon-edit" @click="searchVideoList" | |||
><i-ep-search | |||
/></el-icon> | |||
<!-- 重置按钮 --> | |||
<div v-show="title" class="resetSearch" @click="resetSearch"> | |||
{{ $t("myCreating.reset") }} | |||
</div> | |||
</div> | |||
<!-- 更新视频提示 --> | |||
<div class="hasNewVideoTips" :class="hasNewCreate ? '' : 'hasNew'"> | |||
{{ $t("myCreating.hasNewVideo") }} | |||
</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, 7, 8, 9, 10, 11, 12].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, item.title)" | |||
> | |||
<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"> | |||
<!-- 免费用户1分钟 [5].includes(presentItem.videoStatus)--> | |||
<div | |||
v-if="presentItem.videoPlayUrl && presentItem.videoTime > 300" | |||
class="overtimeTips" | |||
> | |||
<img src="../../assets/img/tips.png" alt="" /> | |||
{{ $t("myCreating.freeUserTip") }} | |||
</div> | |||
<video | |||
v-if="presentItem.videoPlayUrl" | |||
controls="true" | |||
class="" | |||
:src="presentItem.videoPlayUrl" | |||
></video> | |||
<div v-else class="insteadVideo"> | |||
{{ $t("myCreating." + presentItem.statusName + "Text") }} | |||
<p v-if="lanChange == 'zh-cn' && presentItem.videoStatus == 3"> | |||
错误原因: {{ presentItem.videoMsg }} | |||
</p> | |||
<p v-if="lanChange == 'en' && presentItem.videoStatus == 3"> | |||
Error cause: {{ presentItem.videoMsg }} | |||
</p> | |||
<!-- <span v-if="presentItem.videoStatus == 3">{{ | |||
presentItem.videoMsg | |||
}}</span> --> | |||
</div> | |||
<!-- 有视频路径的页脚 --> | |||
<div class="footer" v-if="presentItem.videoPlayUrl"> | |||
<span class="dialog-footer"> | |||
<!-- dialog下载按钮 upGrades--> | |||
<button | |||
class="elBtn" | |||
type="primary" | |||
@click.stop=" | |||
handleDownload(presentItem.videoPlayUrl, presentItem.title) | |||
" | |||
> | |||
<!-- <el-icon class="icon-delete"><i-ep-download /></el-icon> --> | |||
{{ $t("myCreating.download") }} | |||
</button> | |||
<!-- 提升画质 v-if="presentItem.isHy == 0"--> | |||
<el-tooltip | |||
style="cursor: pointer" | |||
v-if="false" | |||
class="box-item" | |||
effect="light" | |||
:content="$t('myCreating.upSharpnessTips')" | |||
placement="top" | |||
> | |||
<button | |||
style="cursor: pointer" | |||
v-if="presentItem.isHy == 0" | |||
class="elBtn upSharpness" | |||
@click.stop="upGrades(presentItem.id)" | |||
> | |||
<div v-if="!upGradesLoading" style="cursor: pointer"> | |||
<img src="../../assets/img/Upgrades.png" alt="" /> | |||
{{ $t("myCreating.upSharpness") }} | |||
</div> | |||
<div v-if="upGradesLoading"> | |||
<!-- <my-Loading-Icon | |||
class="previewAudioLoadingBox" | |||
v-if="!upGradesLoading" | |||
></my-Loading-Icon> --> | |||
<el-icon class="is-loading" style="font-size: 16px" | |||
><i-ep-Loading | |||
/></el-icon> | |||
</div> | |||
</button> | |||
</el-tooltip> | |||
<!-- 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="[12, 24, 36]" | |||
: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> | |||
//#region 导入 | |||
import { | |||
userPhotoVideoListApi, | |||
delUserPhotoVideoByIDApi, | |||
videoHyApi, | |||
checkVideoStatusApi, | |||
} 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"; | |||
//#endregion ---------------------- | |||
const router = useRouter(); | |||
// 当前语言状态与国际化组件 | |||
const { locale } = useI18n(); | |||
const lanChange = ref(locale); | |||
//#region 老页面逻辑 | |||
const title = ref(""); | |||
const pageNum = ref(1); | |||
const pageSize = ref(12); | |||
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, name) { | |||
if (itemVideoPlayUrl) { | |||
console.log(1); | |||
let a = document.createElement("a"); | |||
a.download = `${name}.mp4`; | |||
a.href = itemVideoPlayUrl; | |||
// 设置下载文件名 | |||
a.style.display = "none"; | |||
document.body.appendChild(a); | |||
a.click(); | |||
a.remove(); | |||
ElMessage.success( | |||
lanChange.value == "zh-cn" ? `下载成功` : `Download Successfully` | |||
); | |||
} else { | |||
ElMessage.error( | |||
lanChange.value == "zh-cn" ? `无法下载` : `Unable to download` | |||
); | |||
} | |||
} | |||
function goCreate() { | |||
router.push("/createVideo"); | |||
} | |||
function resetSearch(params) { | |||
title.value = ""; | |||
searchVideoList(); | |||
} | |||
// 搜索 | |||
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); | |||
}); | |||
} | |||
// 升级画质 | |||
const upGradesLoading = ref(false); | |||
function upGrades(id) { | |||
if (upGradesLoading.value == true) { | |||
ElMessage.error( | |||
lanChange.value == "zh-cn" | |||
? `正在升级,请稍后~` | |||
: `Upgrading, please wait ~` | |||
); | |||
return; | |||
} | |||
const msg = | |||
lanChange.value == "zh-cn" | |||
? `确定要升级该作品吗?` | |||
: `Are you sure you want to upgrade this work?`; | |||
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(async () => { | |||
upGradesLoading.value = true; | |||
try { | |||
const res = await videoHyApi(id); | |||
ElMessage.success( | |||
lanChange.value == "zh-cn" | |||
? `升级中!请稍等~` | |||
: `Upgrading! Please wait a moment` | |||
); | |||
showDialog.value = false; | |||
upGradesLoading.value = false; | |||
getPhotoVideoList(pageNum.value, pageSize.value, title.value); | |||
} catch (error) { | |||
ElMessage.error( | |||
lanChange.value == "zh-cn" | |||
? `升级失败,请稍后重试` | |||
: `Upgrade failed, please try again later` | |||
); | |||
upGradesLoading.value = false; | |||
} | |||
}); | |||
} | |||
/** | |||
* @description:获取我的视频作品 | |||
* @return: data | |||
*/ | |||
function getPhotoVideoList(pageNum, pageSize, title, searchFlag) { | |||
userPhotoVideoListApi(pageNum, pageSize, title) | |||
.then((res) => { | |||
console.log(res, "res"); | |||
notGenerateList.value = []; | |||
// 找到数组中未生成的,放入列表,为了刷新 | |||
res.data.list.forEach((item) => { | |||
if ([1, 2, 4, 6, 7, 8, 10, 12].includes(item.videoStatus)) { | |||
notGenerateList.value.push(item.id); | |||
} | |||
}); | |||
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) { | |||
delUserPhotoVideoByIDApi(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); | |||
}); | |||
} | |||
//#endregion ---------------------- | |||
//#region 定时刷新 | |||
const hasNewCreate = ref(false); //提示框显示隐藏 | |||
const notGenerateList = ref([]); //页面上未生成的视频的id 普通视频 | |||
const notGenerateList2 = ref([]); //页面上未生成的视频的id 升级视频 | |||
const checkVideoStatus = async () => { | |||
// 如果列表中没有生成中的视频,不发送请求 | |||
const intervalId = setInterval(async () => { | |||
// && notGenerateList2.value.length == 0; | |||
console.log(""); | |||
if (notGenerateList.value.length == 0) { | |||
return; | |||
} | |||
try { | |||
const res = await checkVideoStatusApi(notGenerateList.value); | |||
// 如果有新的,则提示且更新列表 | |||
if (res.code != 2115) { | |||
hasNewCreate.value = true; | |||
const changeHasNewCreate = setTimeout(() => { | |||
hasNewCreate.value = false; | |||
}, 5000); | |||
notGenerateList.value = []; | |||
// notGenerateList2.value = []; | |||
getPhotoVideoList(pageNum.value, pageSize.value, title.value); | |||
} | |||
} catch (error) {} | |||
}, 3000); | |||
onUnmounted(() => { | |||
clearInterval(intervalId); | |||
}); | |||
}; | |||
//#endregion --------------------------- | |||
//#region 页面初始化 | |||
onMounted(() => { | |||
isLoading.value = true; | |||
getPhotoVideoList(pageNum.value, pageSize.value, title.value); | |||
// checkVideoStatus(); | |||
}); | |||
//#endregion --------------------------- | |||
</script> | |||
<style lang="scss" scoped> | |||
.page { | |||
position: relative; | |||
height: calc(100vh - 80px); | |||
padding: 15px 130px; | |||
background-color: #fff; | |||
border-radius: 25px 0 0; | |||
width: 100%; | |||
overflow: hidden; | |||
overflow-y: auto; | |||
.top { | |||
position: relative; | |||
margin-bottom: 35px; | |||
.search { | |||
display: flex; | |||
justify-content: flex-start; | |||
.resetSearch { | |||
margin-left: 10px; | |||
padding: 0 10px; | |||
height: 30px; | |||
width: 100px; | |||
text-align: center; | |||
line-height: 30px; | |||
background-color: #000; | |||
border: 1px solid #000; | |||
border-radius: 15px; | |||
cursor: pointer; | |||
transition: all 0.3s; | |||
color: #fff; | |||
&:hover { | |||
background-color: #fff; | |||
color: #000; | |||
} | |||
} | |||
} | |||
.hasNewVideoTips { | |||
position: absolute; | |||
top: 0; | |||
left: 50%; | |||
transform: translateX(-50%); | |||
width: 400px; | |||
padding: 5px 30px; | |||
color: #fff; | |||
background-color: #000; | |||
text-align: center; | |||
font-size: 20px; | |||
transition: all 0.5s; | |||
opacity: 1; | |||
border-radius: 15px; | |||
} | |||
.hasNew { | |||
opacity: 0; | |||
transition: all 0.5s; | |||
} | |||
} | |||
.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; | |||
.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; | |||
font-size: 13px; | |||
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%); | |||
} | |||
&.videoUping { | |||
/* 升级中 */ | |||
background: linear-gradient(120deg, #4512c7 0%, #4fd334 100%); | |||
} | |||
&.videoUpFailed { | |||
/* HD */ | |||
background: linear-gradient(120deg, #ff0019 0%, #ff00c3 100%); | |||
} | |||
&.videoUpSucceed { | |||
/* HD */ | |||
background: linear-gradient(120deg, #fdeb71 0%, #d37e1a 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; | |||
.overtimeTips { | |||
// width: 60%; | |||
// display: inline-block; | |||
padding: 5px; | |||
margin-bottom: 10px; | |||
background-color: #ccc; | |||
border-radius: 5px; | |||
line-height: 20px; | |||
color: #000; | |||
text-align: center; | |||
img { | |||
width: 20px; | |||
height: 20px; | |||
vertical-align: middle; | |||
margin-right: 5px; | |||
} | |||
} | |||
video { | |||
width: 100%; | |||
max-height: 600px; | |||
margin: auto; | |||
} | |||
.insteadVideo { | |||
font-size: 20px; | |||
font-weight: 400; | |||
margin: 20px auto; | |||
text-align: center; | |||
} | |||
p { | |||
font-weight: 700; | |||
} | |||
} | |||
.dialog-footer { | |||
display: flex; | |||
justify-content: space-between; | |||
.elBtn { | |||
color: #fff; | |||
border-radius: 10px; | |||
padding: 10px 15px; | |||
cursor: pointer; | |||
background-color: #000; | |||
transition: all 0.3s; | |||
&:hover { | |||
background-color: #15d1b8; | |||
} | |||
} | |||
.upSharpness { | |||
img { | |||
width: 14px; | |||
height: 14px; | |||
} | |||
} | |||
: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> |
@@ -0,0 +1,16 @@ | |||
/** | |||
* @description:根据状态返回状态名 | |||
* @param {number} status | |||
* @return: statusName | |||
*/ | |||
export const getStatus = status => { | |||
if (status == 0) { | |||
return "manuscript" | |||
} else if (status == 1 || status == 2 || status == 4 || status == 6) { | |||
return "generating" | |||
} else if (status == 3) { | |||
return "generationFailed" | |||
} else if (status == 5) { | |||
return "generationSucceed" | |||
} | |||
} |
@@ -0,0 +1,7 @@ | |||
<template> | |||
<div></div> | |||
</template> | |||
<script setup> | |||
// import { ref } from 'vue' | |||
</script> | |||
<style lang="scss" scoped></style> |
@@ -0,0 +1,6 @@ | |||
<!-- | |||
* @Description: 定制分身 | |||
--> | |||
<template> | |||
<iframe src="/priMakeHtml/dingzhishengwen/index.shtml" style="width: 100%;height:86vh"></iframe> | |||
</template> |