Compare commits

...

11 Commits

Author SHA1 Message Date
  congzc bf1dbdeef7 1 1 year ago
  congzc af8a52f71a 1 1 year ago
  congzc 3c02f7889b 1 1 year ago
  congzc e010b8687d 1 1 year ago
  congzc 3ea71a8495 1 1 year ago
  congzc ae78019597 1 1 year ago
  congzc 6f62765b56 1 1 year ago
  congzc 837db768cd 1 1 year ago
  congzc 63b20451f0 AI文案 1 year ago
  congzc b2d3b0ad3e Merge branch 'dev' of https://git.malls.iformall.com/suimang/Home_wap_pc into dev 1 year ago
  congzc a75a03d1b0 1 1 year ago
20 changed files with 2372 additions and 385 deletions
Split View
  1. +3
    -1
      .env.development
  2. +1
    -1
      .env.test
  3. BIN
      dist.zip
  4. +1
    -0
      package.json
  5. +13
    -0
      src/apis/createVideo.js
  6. +39
    -0
      src/apis/pay.js
  7. +51
    -0
      src/components/myLoadingIcon2.vue
  8. +5
    -0
      src/lang/package/en.ts
  9. +5
    -0
      src/lang/package/zh-cn.ts
  10. +9
    -1
      src/layout/index.vue
  11. +36
    -0
      src/router/index.ts
  12. +1
    -0
      src/types/components.d.ts
  13. +631
    -150
      src/views/createVideo/index.vue
  14. +49
    -4
      src/views/myAPI/index.vue
  15. +2
    -1
      src/views/myCreating/index.vue
  16. +487
    -226
      src/views/myStore/index.vue
  17. +944
    -0
      src/views/userModel/index.vue
  18. +16
    -0
      src/views/userModel/videoStatus.js
  19. +7
    -0
      src/views/voiceModel/index.vue
  20. +72
    -1
      yarn.lock

+ 3
- 1
.env.development View File

@@ -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://mtest.metavatar.cc/C'


+ 1
- 1
.env.test View File

@@ -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'

BIN
dist.zip View File


+ 1
- 0
package.json View File

@@ -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": {


+ 13
- 0
src/apis/createVideo.js View File

@@ -188,3 +188,16 @@ 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
})
}

+ 39
- 0
src/apis/pay.js View File

@@ -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
- 0
src/components/myLoadingIcon2.vue View File

@@ -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>

+ 5
- 0
src/lang/package/en.ts View File

@@ -85,6 +85,7 @@ export default {
comingSoon: "COMING SOON",
material: "Material",
subtitles: "Subtitles",
AItext:"AI Script",
sex: "Sex",
videoRatio: "Video Ratio",
all: "All",
@@ -104,6 +105,10 @@ 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',
},

// 我的视频


+ 5
- 0
src/lang/package/zh-cn.ts View File

@@ -86,6 +86,7 @@ export default {
BackgroundImage: "背景",
material: "素材",
subtitles: "字幕",
AItext:"AI生成文本",
sex: "性别",
videoRatio: "视频比例",
all: "全部",
@@ -105,6 +106,10 @@ export default {
tooltip2: "添加停顿",
SubtitlesTip: "字幕将在此处展示",
subtitlesSwitch: "字幕开关",
inputRequirement:'请输入您的需求,例如:请生成一个500字以内的饮料广告',
GeneratedText:'生成文本',
SmartText:'智能文本',
copy:'复制到文案',
},

// 我的视频


+ 9
- 1
src/layout/index.vue View File

@@ -23,7 +23,7 @@
</div>
{{ $t("myCreating.title") }}
</div>
<div class="myRouter-item" @click="showTalkUsDialog = true">
<div class="myRouter-item" @click="toUserModel">
<div class="icon">
<el-icon><i-ep-user /></el-icon>
</div>
@@ -169,6 +169,13 @@ const updateShowTalkUsDialog = (newValue: any) => {
showTalkUsDialog.value = newValue;
};
//#endregion ------------------------------------

//#region 页面跳转
function toUserModel() {
router.push("/userModel");
showTalkUsDialog.value = true;
}
//#endregion ------------------------------------
</script>

<!-- 新样式 -->
@@ -196,6 +203,7 @@ const updateShowTalkUsDialog = (newValue: any) => {
height: calc(100% - 80px);
padding: 130px 20px 0;
color: #fff;
user-select: none;
// color: #868593;

.bottomBtx {


+ 36
- 0
src/router/index.ts View File

@@ -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,


+ 1
- 0
src/types/components.d.ts View File

@@ -49,6 +49,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']


+ 631
- 150
src/views/createVideo/index.vue View File

@@ -4,6 +4,203 @@
<div class="mask" v-show="showChooseModel"></div>
<!-- 左侧栏 -->
<div class="left">
<!-- 字幕框 -->
<div v-show="videoType == 2" class="subtitlesBoxTop">
<!-- 开关 -->
<div class="tab4Item">
<div v-if="materialList.BGI.material" class="SubtitlesSwitch">
<p>{{ $t("createVideo.subtitlesSwitch") }}</p>
<el-switch
v-model="Subtitles.SubtitlesSwitch"
style="--el-switch-on-color: #000"
/>
</div>
</div>
<!-- 字体系列 -->
<div class="tab4Item">
<div v-if="materialList.BGI.material" class="SubtitlesSwitch">
<p>
{{ lanChange == "zh-cn" ? `字体` : `Font Family` }}
</p>
<el-select
v-model="Subtitles.SubtitlesFontFamily"
style="width: 100px"
placeholder=" "
size="default"
>
<el-option
v-for="item in Subtitles.fontFamilyList"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</div>
</div>
<!-- y轴 -->
<div class="tab4Item">
<div v-if="materialList.BGI.material" class="SubtitlesSwitch">
<p>
{{ lanChange == "zh-cn" ? `纵坐标` : `Y-axis` }}
</p>
<el-input-number
:precision="0"
v-model="Subtitles.SubtitlesTop"
size="large"
controls-position="right"
/>
</div>
</div>
<!-- 字号大小 -->
<div class="tab4Item">
<div v-if="materialList.BGI.material" class="SubtitlesSwitch">
<p>
{{ lanChange == "zh-cn" ? `字号大小` : `Font Size` }}
</p>
<el-select
v-model="Subtitles.SubtitlesSize"
style="width: 100px"
placeholder=" "
size="default"
>
<el-option
v-for="item in Subtitles.fontSizeList"
:key="item"
:label="item"
:value="item"
:style="{
height: item + 'px',
lineHeight: item + 'px',
}"
>
<span :style="{ fontSize: item + 'px', padding: '5px' }">{{
item
}}</span>
</el-option>
</el-select>
</div>
</div>
<!-- 字色 -->
<div class="tab4Item">
<div v-if="materialList.BGI.material" class="SubtitlesSwitch">
<p>
{{ lanChange == "zh-cn" ? `字体颜色` : `Font Color` }}
</p>
<div
@click="handleSubtitlesColorShow"
class="myColorBox"
:style="{ backgroundColor: Subtitles.SubtitlesColor }"
>
<div v-show="SubtitlesColorShow" class="selectColor">
<div
v-for="item in Subtitles.colorList"
:style="{ backgroundColor: item }"
class="selectColor-item"
@click="Subtitles.SubtitlesColor = item"
></div>
</div>
</div>
</div>
</div>
</div>
<div v-show="videoType == 1" class="subtitlesBoxLeft">
<!-- 开关 -->
<div class="tab4Item">
<div v-if="materialList.BGI.material" class="SubtitlesSwitch">
<p>{{ $t("createVideo.subtitlesSwitch") }}</p>
<el-switch
v-model="Subtitles.SubtitlesSwitch"
style="--el-switch-on-color: #000"
/>
</div>
</div>
<!-- 字体系列 -->
<div class="tab4Item">
<div v-if="materialList.BGI.material" class="SubtitlesSwitch">
<p>
{{ lanChange == "zh-cn" ? `字体` : `Font Family` }}
</p>
<el-select
v-model="Subtitles.SubtitlesFontFamily"
style="width: 100px"
placeholder=" "
size="default"
>
<el-option
v-for="item in Subtitles.fontFamilyList"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</div>
</div>
<!-- y轴 -->
<div class="tab4Item">
<div v-if="materialList.BGI.material" class="SubtitlesSwitch">
<p>
{{ lanChange == "zh-cn" ? `纵坐标` : `Y-axis` }}
</p>
<el-input-number
:precision="0"
v-model="Subtitles.SubtitlesTop"
size="large"
controls-position="right"
/>
</div>
</div>
<!-- 字号大小 -->
<div class="tab4Item">
<div v-if="materialList.BGI.material" class="SubtitlesSwitch">
<p>
{{ lanChange == "zh-cn" ? `字号大小` : `Font Size` }}
</p>
<el-select
v-model="Subtitles.SubtitlesSize"
style="width: 100px"
placeholder=" "
size="default"
>
<el-option
v-for="item in Subtitles.fontSizeList"
:key="item"
:label="item"
:value="item"
:style="{
height: item + 'px',
lineHeight: item + 'px',
}"
>
<span :style="{ fontSize: item + 'px', padding: '5px' }">{{
item
}}</span>
</el-option>
</el-select>
</div>
</div>
<!-- 字色 -->
<div class="tab4Item">
<div v-if="materialList.BGI.material" class="SubtitlesSwitch">
<p>
{{ lanChange == "zh-cn" ? `字体颜色` : `Font Color` }}
</p>
<div
@click="handleSubtitlesColorShow"
class="myColorBox"
:style="{ backgroundColor: Subtitles.SubtitlesColor }"
>
<div v-show="SubtitlesColorShow" class="selectColor">
<div
v-for="item in Subtitles.colorList"
:style="{ backgroundColor: item }"
class="selectColor-item"
@click="Subtitles.SubtitlesColor = item"
></div>
</div>
</div>
</div>
</div>
</div>
<!-- 选择模版弹出框 -->
<div class="chooseModelBox" :class="showChooseModel ? '' : 'noModel'">
<!-- 伸缩按钮 -->
@@ -21,7 +218,7 @@
>
&lt;
</div>
<!-- tab栏 -->
<!-- tab栏 性别-->
<p>{{ $t("createVideo.sex") }}</p>
<div class="tab" v-show="showChooseModel">
<div
@@ -46,6 +243,7 @@
{{ $t("createVideo.female") }}
</div>
</div>
<!-- 横屏竖屏 -->
<p>{{ $t("createVideo.videoRatio") }}</p>
<div class="tab" v-show="showChooseModel">
<div
@@ -70,6 +268,17 @@
{{ $t("createVideo.portrait") }}
</div>
</div>
<!-- 风格模版 -->
<!-- <p>{{ $t("createVideo.videoRatio") }}</p>
<div class="tab" v-show="showChooseModel">
<div
class="tabItem"
:class="modelTabItemActive3 == -1 ? 'tabItemActive' : ''"
@click="changeModelStyle(-1)"
>
{{ $t("createVideo.all") }}
</div>
</div> -->
<!-- 模版列表 -->
<div
class="modeListBox"
@@ -177,6 +386,7 @@
<!-- tab栏 -->
<div class="tab">
<div
id="tab-0"
class="tabItem"
:class="tabItemActive == 1 ? 'tabItemActive' : ''"
@click="tabItemActive = 1"
@@ -202,8 +412,15 @@
:class="tabItemActive == 4 ? 'tabItemActive' : ''"
@click="tabItemActive = 4"
>
{{ $t("createVideo.subtitles") }}
{{ $t("createVideo.aiScript") }}
</div>
<!-- <div
class="tabItem"
:class="tabItemActive == 5 ? 'tabItemActive' : ''"
@click="tabItemActive = 5"
>
{{ $t("createVideo.AItext") }}
</div> -->
</div>
<!-- 文案 只能使用v-if,不能使用v-show-->
<div v-if="tabItemActive == 1" class="tabContent tab1">
@@ -255,6 +472,7 @@
v-model="language"
:placeholder="$t('createVideo.select')"
style="width: 100%"
filterable
>
<el-option
v-for="item in languageOptions"
@@ -443,149 +661,77 @@
/>
<cutImg
@reGetpersonSCIList="reGetpersonSCIList"
:type="5"
:videoType="videoType"
style="width: 100%; height: 100%"
></cutImg>
</div>
<div
class="bjSystemBoxItem"
v-for="item in personSCIList"
:key="item.id"
:class="scImgActive == item.id ? 'ImgBorderActive' : ''"
@click="selectScImg(item)"
>
<div
v-show="scImgActive == item.id"
class="delIcon"
@click="delImg(item.id)"
>
<img src="../../assets/img/delete.png" alt="" />
</div>
<img class="boxCentreImg" :src="item.material" alt="" />
</div>
</div>
</div>
<!-- 字幕 -->
<div v-if="tabItemActive == 4" class="tabContent tab4">
<!-- 开关 -->
<div class="tab4Item">
<div v-if="materialList.BGI.material" class="SubtitlesSwitch">
<p>{{ $t("createVideo.subtitlesSwitch") }}</p>
<el-switch
v-model="Subtitles.SubtitlesSwitch"
style="--el-switch-on-color: #000"
/>
</div>
</div>
<!-- 字体系列 -->
<div class="tab4Item">
<div v-if="materialList.BGI.material" class="SubtitlesSwitch">
<p>
{{ lanChange == "zh-cn" ? `字体` : `Font Family` }}
</p>
<el-select
v-model="Subtitles.SubtitlesFontFamily"
style="width: 100px"
placeholder=" "
size="default"
>
<el-option
v-for="item in Subtitles.fontFamilyList"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</div>
</div>
<!-- y轴 -->
<div class="tab4Item">
<div v-if="materialList.BGI.material" class="SubtitlesSwitch">
<p>
{{ lanChange == "zh-cn" ? `纵坐标` : `Y-axis` }}
</p>
<el-input-number
:precision="0"
v-model="Subtitles.SubtitlesTop"
size="large"
controls-position="right"
/>
</div>
</div>
<!-- 字号大小 -->
<div class="tab4Item">
<div v-if="materialList.BGI.material" class="SubtitlesSwitch">
<p>
{{ lanChange == "zh-cn" ? `字号大小` : `Font Size` }}
</p>
<el-select
v-model="Subtitles.SubtitlesSize"
style="width: 100px"
placeholder=" "
size="default"
>
<el-option
v-for="item in Subtitles.fontSizeList"
:key="item"
:label="item"
:value="item"
:style="{
height: item + 'px',
lineHeight: item + 'px',
}"
>
<span :style="{ fontSize: item + 'px', padding: '5px' }">{{
item
}}</span>
</el-option>
</el-select>
</div>
</div>
<!-- 字色 -->
<div class="tab4Item">
<div v-if="materialList.BGI.material" class="SubtitlesSwitch">
<p>
{{ lanChange == "zh-cn" ? `字体颜色` : `Font Color` }}
</p>
:type="5"
:videoType="videoType"
style="width: 100%; height: 100%"
></cutImg>
</div>
<div
class="bjSystemBoxItem"
v-for="item in personSCIList"
:key="item.id"
:class="scImgActive == item.id ? 'ImgBorderActive' : ''"
@click="selectScImg(item)"
>
<div
@click="handleSubtitlesColorShow"
class="myColorBox"
:style="{ backgroundColor: Subtitles.SubtitlesColor }"
v-show="scImgActive == item.id"
class="delIcon"
@click="delImg(item.id)"
>
<div v-show="SubtitlesColorShow" class="selectColor">
<div
v-for="item in Subtitles.colorList"
:style="{ backgroundColor: item }"
class="selectColor-item"
@click="Subtitles.SubtitlesColor = item"
></div>
</div>
<img src="../../assets/img/delete.png" alt="" />
</div>
<img class="boxCentreImg" :src="item.material" alt="" />
</div>
</div>
<!-- 字粗 -->
<!-- <div class="tab4Item">
<div v-if="materialList.BGI.material" class="SubtitlesSwitch">
<p>
{{ lanChange == "zh-cn" ? `字号大小` : `Font Size` }}
</p>
<el-select
v-model="Subtitles.SubtitlesWeight"
style="width: 100px"
placeholder=" "
size="default"
</div>
<!-- 智能文案 -->
<div v-if="tabItemActive == 4" class="tabContent tab4">
<div class="card4">
<!-- 语言 -->
<div class="text">
<!-- 文本域 -->
<el-input
maxlength="200"
id="textInputId"
v-model="problemContent"
:rows="5"
type="textarea"
:placeholder="$t('createVideo.inputRequirement')"
/>
</div>
<el-button
type="primary"
:disabled="sendLoading"
@click="sendRequirement"
color="#000"
>
<my-Loading-Icon2 v-if="sendLoading"></my-Loading-Icon2>
<span v-if="!sendLoading">
{{ $t("createVideo.GeneratedText") }}
</span>
</el-button>

<p>{{ $t("createVideo.SmartText") }}</p>
<!-- 语言 -->
<div class="text" style="cursor: text">
<!-- 文本域 -->
<el-input
maxlength="500"
id="textInputId"
v-model="answerContent"
:rows="15"
type="textarea"
disabled=""
/>
<i
>{{ $t("createVideo.entered") }} {{ answerContent.length }} /
500</i
>
<el-option
v-for="item in Subtitles.fontWeightList"
:key="item"
:label="item"
:value="item"
>
</el-option>
</el-select>
</div>
</div> -->
<el-button color="#000" @click="copyAnswerContent">
{{ $t("createVideo.copy") }}
</el-button>
</div>
</div>
</div>
<!-- 试听的mp3 -->
@@ -613,6 +759,7 @@ import {
saveOrUpdateApi,
createVideoApi,
getModelDetailByIdApi,
getLanguageApi,
} from "@/apis/createVideo";
import { useI18n } from "vue-i18n";
import Recorder from "js-audio-recorder"; //mp3插件
@@ -691,6 +838,13 @@ function changeTabVideoType(index) {
tabVideoType.value
);
}
// 模版风格tab
const modelStyleTabList = ref([]);
const modelTabItemActive3 = ref(-1); //模版风格tab栏 比例
function changeModelStyle(index) {
modelTabItemActive3.value = index;
}

// watch(tabSex, (newVal, oldVal) => {
// if (newVal == 0) {
// getModeList("", modelPageNum.value, modelPageSize.value);
@@ -736,7 +890,7 @@ const title =
const textareaContent = ref("");
function insertIcon() {
const textarea = document.getElementById("textInputId");
const icon = "🕗"; // 这里使用了一个星星作为示例图标,你可以替换为你自己的图标
const icon = "🕗";
// 获取光标位置
const startPos = textarea.selectionStart;
const endPos = textarea.selectionEnd;
@@ -754,6 +908,31 @@ function insertIcon() {
const language = ref(""); //选择的语言
const sound = ref(""); // 选择的声音
const soundStyle = ref(""); //选择的风格
// 输入文字判断语种
const getLanguageTimeOut = ref(false); //定时器
watch(
() => textareaContent.value,
() => {
clearTimeout(getLanguageTimeOut.value);
getLanguageTimeOut.value = setTimeout(async () => {
try {
const data = {
paperwork: textareaContent.value,
};
const res = await getLanguageApi(data);
if (res.code == 200) {
language.value = res.data.id;
}
} catch (error) {}
}, 1500);
}
);
watch(
() => language.value,
() => {
chooseType();
}
);
// 语言下拉框内容
const languageOptions = ref([]);
async function voiceTotal() {
@@ -1417,7 +1596,7 @@ async function createVideo() {
sound.value,
soundStyle.value
);
if (res4.data.code != 200) {
if (res4.code != 200) {
ElMessage.error(
lanChange.value == "zh-cn"
? `视频时长预估失败,无法生成视频,您可以换个声音试试`
@@ -1427,14 +1606,14 @@ async function createVideo() {
saveLoading.value = false;
return;
}
if (res4.data.data > 300) {
if (res4.data.time > 300) {
ElMessage.error(
lanChange.value == "zh-cn"
? `预计生成的视频时长约为${formatTime(
res4.data.data
res4.data.time
)},免费用户生成视频时长为300秒,无法生成视频`
: `The video generated is expected to be about ${formatTime(
res4.data.data
res4.data.time
)} long, and the free user-generated video is 300 seconds long and cannot be generated`
);
createLoading.value = false;
@@ -1443,9 +1622,9 @@ async function createVideo() {
}
ElMessage.success(
lanChange.value == "zh-cn"
? `预计生成的视频时长约为${formatTime(res4.data.data)}`
? `预计生成的视频时长约为${formatTime(res4.data.time)}`
: `The video generated is expected to be approximately${formatTime(
res4.data.data
res4.data.time
)} in length`
);
await saveOrUpdate("isCreate");
@@ -1518,8 +1697,82 @@ function NumToFixed(num1, num2) {
}
//#endregion ----------------------------

//#region
//#region AI文案
// 创建websocket
let mySocket = null; //websocket对象
const sendLoading = ref(false); //发送状态
function createWS() {
mySocket = new WebSocket("wss://gptsocket.malls.iformall.com:8010");
mySocket.onopen = () => {
console.log("WebSocket 连接成功1");
sendRequirement();
};
mySocket.onmessage = (event) => {
// console.log("接收到 WebSocket 消息2:", event.data);
if (!event.data) {
return;
}
if (event.data == "___talk_end___") {
sendLoading.value = false;
mySocket.close();
return;
}
answerContent.value = answerContent.value + event.data;
};
mySocket.onclose = () => {
console.log(
"WebSocket 连接关闭3,关闭代码:",
event.code,
"关闭原因:",
event.reason
);
console.log(mySocket.readyState, "链接状态3");
};

mySocket.onerror = (error) => {
ElMessage.error(
lanChange.value == "zh-cn"
? `GPT服务器连接失败,请稍后重试!`
: `GPT Server connection failed, please try again later`
);
sendLoading.value = false;
mySocket.close();
console.error("WebSocket 错误4:", error);
};
}
const problemContent = ref(""); //问题输入框内容
const answerContent = ref(""); //回答输入框内容
// 点击发送需求
async function sendRequirement() {
// loading
sendLoading.value = true;

// 无需求时
if (!problemContent.value) {
sendLoading.value = false;
mySocket.close();
return;
}
const sendMessage = [
{
role: "user",
content: problemContent.value,
},
];
// 如果处于链接状态

if (mySocket.readyState != WebSocket.OPEN) {
createWS();
} else {
answerContent.value = "";
mySocket.send(JSON.stringify(sendMessage));
}
}
// 复制到文案
function copyAnswerContent() {
textareaContent.value = answerContent.value;
document.getElementById("tab-0").click();
}
//#endregion ----------------------------

//#region
@@ -1547,6 +1800,7 @@ onMounted(async () => {
if (route.query.id) {
getModelDetailById();
}
createWS();
});
</script>

@@ -1570,6 +1824,171 @@ onMounted(async () => {
width: 68%;
height: 100%;
padding: 20px;
// 字幕盒子
.subtitlesBoxTop {
z-index: 3;
position: absolute;
top: 50px;
left: 225px;
width: 700px;
// height: 50px;
background-color: #e9ecf1;
border-radius: 20px;
padding: 10px;
box-shadow: rgba(0, 0, 0, 0.5) 0px 0px 15px;
display: flex;
justify-content: flex-start;
align-content: flex-start;
flex-wrap: wrap;
.tab4Item {
display: flex;
justify-content: space-between;
width: 130px;
background-color: rgba(71, 105, 218, 0.1);
text-align: center;
padding: 10px;
height: 80px;
border-radius: 10px;
margin: auto;
// margin-bottom: 10px;
p {
padding-bottom: 5px;
}
}
.SubtitlesSwitch {
width: 100%;
.el-input-number--large {
width: 100px;
}
.el-input-number__increase {
width: none;
}
}
.myColorBox {
position: relative;
width: 25px;
height: 25px;
margin: auto;
border: #000 solid 2px;
cursor: pointer;
.selectColor {
position: absolute;
top: 150%;
left: 50%;
transform: translateX(-50%);
display: flex;
justify-content: flex-start;
flex-wrap: wrap;
width: 142px;
background-color: #ffffff;
z-index: 99;
box-shadow: rgba(0, 0, 0, 0.3) 0px 0px 5px 5px;
&::before {
content: "";
display: block;
position: absolute;
top: -10%;
left: 50%;
transform: translateX(-50%);
width: 0;
height: 0;
border-left: 15px solid transparent;
border-right: 15px solid transparent;
border-bottom: 15px solid white;
}
&-item {
width: 25px;
height: 25px;
margin: 5px 5px;
border: #000 solid 2px;
border-radius: 5px;
cursor: pointer;
}
}
}
}
.subtitlesBoxLeft {
z-index: 3;
position: absolute;
top: 150px;
left: 150px;
width: 150px;
// height: 50px;
background-color: #e9ecf1;
border-radius: 20px;
padding: 10px;
box-shadow: rgba(0, 0, 0, 0.5) 0px 0px 15px;
display: flex;
justify-content: flex-start;
align-content: flex-start;
flex-wrap: wrap;
.tab4Item {
display: flex;
justify-content: space-between;
width: 130px;
background-color: rgba(71, 105, 218, 0.1);
text-align: center;
padding: 10px;
height: 80px;
border-radius: 10px;
margin: auto;
margin-bottom: 10px;
p {
padding-bottom: 5px;
}
}
.SubtitlesSwitch {
width: 100%;
.el-input-number--large {
width: 100px;
}
.el-input-number__increase {
width: none;
}
}
.myColorBox {
position: relative;
width: 25px;
height: 25px;
margin: auto;
border: #000 solid 2px;
cursor: pointer;
.selectColor {
position: absolute;
top: 150%;
left: 50%;
transform: translateX(-50%);
display: flex;
justify-content: flex-start;
flex-wrap: wrap;
width: 142px;
background-color: #ffffff;
z-index: 99;
box-shadow: rgba(0, 0, 0, 0.3) 0px 0px 5px 5px;
&::before {
content: "";
display: block;
position: absolute;
top: -10%;
left: 50%;
transform: translateX(-50%);
width: 0;
height: 0;
border-left: 15px solid transparent;
border-right: 15px solid transparent;
border-bottom: 15px solid white;
}
&-item {
width: 25px;
height: 25px;
margin: 5px 5px;
border: #000 solid 2px;
border-radius: 5px;
cursor: pointer;
}
}
}
}
// 选择模版弹出框
.chooseModelBox {
position: absolute;
@@ -1917,10 +2336,72 @@ onMounted(async () => {
}
}
.tab4 {
display: flex;
justify-content: flex-start;
align-content: flex-start;
flex-wrap: wrap;
// display: flex;
// justify-content: flex-start;
// align-content: flex-start;
// flex-wrap: wrap;
.card4 {
.text {
padding: 10 px;
border: 1px solid #c0c4cc;
.el-button {
float: right;
margin-top: 10px;
}
:deep(.el-textarea__inner) {
cursor: text;
}
:deep(.el-textarea__inner) {
resize: none;
box-shadow: none;
}
i {
font-size: 14px;
float: right;
}
}

p {
margin: 7px 0;
}
.card4Btn {
margin-top: 10px;
border-radius: 5px;
height: 50px;
width: 100%;
color: #fff;
background-color: #000;
text-align: center;
line-height: 50px;
cursor: pointer;
}
.el-button {
width: 100%;
height: 50px;
margin-top: 10px;
}
}
:deep(.el-tabs__item.is-active) {
color: #909393;
background-color: #000;
}

:deep(.el-tabs__nav) {
width: 100%;
}

:deep(.el-tabs__item) {
width: 26%;
}

:deep(.el-tabs__item:hover) {
color: #909393;
}

:deep(.el-tabs__content) {
height: calc(100% - 60px);
padding: 0;
}
.tab4Item {
display: flex;
justify-content: space-between;


+ 49
- 4
src/views/myAPI/index.vue View File

@@ -1,22 +1,67 @@
<template>
<div class="page">
<div class="title">{{ $t("API.comingSoon") }}</div>
<!-- <div class="title">{{ $t("API.comingSoon") }}</div> -->
<!-- 左侧名称 -->
<div class="left">
<div class="scrollBox">
<p>啊实打实大</p>
</div>
</div>
<!-- 右侧介绍 -->
<div class="right">
<div class="scrollBox"></div>
</div>
</div>
</template>

<script setup>
// import { ref } from 'vue'
</script>

<style lang="scss" scoped>
.page {
padding: 30px;
display: flex;
width: 100%;
overflow: hidden;
overflow-y: scroll;
background-color: #fff;
background-color: #f5f5f5;
border-radius: 25px 0 0 0;
min-height: calc(100vh - 80px);
text-align: center;
// text-align: center;
.title {
font-size: 50px;
}
}
.left {
height: calc(100vh - 80px);
width: 30%;
padding: 30px 15px 30px 30px;
font-size: 20px;
background-color: #f5f5f5;

.scrollBox {
padding: 20px;
height: calc(100vh - 80px - 60px);
width: 100%;
overflow-y: scroll;
background-color: #fff;
border-radius: 20px;
box-shadow: rgba(0, 0, 0, 0.5) 0px 0px 15px;
}
}
.right {
height: calc(100vh - 80px);
width: 80%;
padding: 30px 30px 30px 15px;
background-color: #f5f5f5;
.scrollBox {
padding: 20px;
height: calc(100vh - 80px - 60px);
width: 100%;
overflow-y: scroll;
background-color: #fff;
border-radius: 20px;
box-shadow: rgba(0, 0, 0, 0.5) 0px 0px 15px;
}
}
</style>

+ 2
- 1
src/views/myCreating/index.vue View File

@@ -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>


+ 487
- 226
src/views/myStore/index.vue View File

@@ -180,33 +180,117 @@
</div>
</div>
</div>
<!-- 对话框 -->
<el-dialog v-if="false" v-model="showPayDialog" width="60%" center>
<!-- 对话框 v-if="false"-->
<el-dialog v-model="showPayDialog" width="60%" center>
<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 class="title">{{ $t(presentItme.value.title) }}</div> -->
<div class="title">{{ $t(presentItme.value.typeDesc) }}</div>
<div class="money">
<span class="price">{{
lanChange == "zh-cn"
? presentItme.value.rmb + "¥"
: presentItme.value.dollar + "$"
}}</span
>/{{ presentItme.value.validityDuration }}{{ $t("shop.day") }}
</div>
<div
class="authority"
v-for="item in presentItme.value.authority"
:key="item"
>
{{ item }}
<div class="time">
<span>{{ presentItme.value.credit }}</span
>{{ $t("shop.score") }}
</div>
<!-- 套餐内容 -->
<div class="authority">
<div class="authority-item">
{{ $t("shop.InviteGetscore") }}:
<span>
<i>{{ presentItme.value.inviteUserCredit }}</i
>{{ $t("shop.score") }}</span
>
</div>
<div class="authority-item">
{{ $t("shop.createVideoPrice") }}:<span
><i>{{ presentItme.value.videoPrice }}</i
>{{ $t("shop.score") }}</span
>
</div>
<div class="authority-item">
{{ $t("shop.AIGeneratesPhotoPrices") }}:<span
><i>{{ presentItme.value.photoPrice }}</i
>{{ $t("shop.score") }}</span
>
</div>
<div class="authority-item">
{{ $t("shop.UnitChargeDuration") }}:<span
><i>{{ presentItme.value.chargeTime }}</i
>{{ $t("shop.second") }}</span
>
</div>

<div class="authority-item">
{{ $t("shop.Language") }}:<span
><i>{{
presentItme.value.userPackageDetails[0].languageDesc
}}</i></span
>
</div>
<div class="authority-item">
{{ $t("shop.sound") }}:<span
><i>{{
presentItme.value.userPackageDetails[0].soundDesc
}}</i></span
>
</div>
<div class="authority-item">
{{ $t("shop.IndividualVideoDuration") }}:<span
><i>{{ presentItme.value.userPackageDetails[0].videoTime }}</i
>{{ $t("shop.second") }}</span
>
</div>
<div class="authority-item">
{{ $t("shop.Watermark") }}:<span>{{
presentItme.value.userPackageDetails[0].aiPortrait == 0
? $t("shop.yes")
: $t("shop.no")
}}</span>
</div>
<div class="authority-item">
{{ $t("shop.AIGeneratedPortrait") }}:<span>{{
presentItme.value.userPackageDetails[0].aiPortrait == 0
? $t("shop.no")
: $t("shop.yes")
}}</span>
</div>
<div class="authority-item">
{{ $t("shop.PhotoSinging") }}:<span>{{
presentItme.value.userPackageDetails[0].photoSing == 0
? $t("shop.no")
: $t("shop.yes")
}}</span>
</div>
<div class="authority-item">
{{ $t("shop.AIGeneratedText") }}:<span
><i>{{
presentItme.value.userPackageDetails[0].aiCreateTime
}}</i></span
>
</div>
<div class="authority-item">
{{ $t("shop.VideoResolution") }}:<span>{{
presentItme.value.userPackageDetails[0].resolutionRatioDesc
}}</span>
</div>
</div>
</div>
<div class="right">
<div
style="background-color: #07c160; cursor: pointer"
@click="showOrderCode(1)"
@click="showOrderCode(2)"
>
{{ $t("shop.WeChatPay") }}
</div>
<div
style="background-color: #1378fe; cursor: pointer"
@click="showOrderCode(2)"
@click="showOrderCode(4)"
>
{{ $t("shop.Alipay") }}
</div>
@@ -224,15 +308,35 @@
width="30%"
append-to-body
destroy-on-close
@closed="clearCode"
:close-on-click-modal="false"
>
<div class="orderCodeDialog">
<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="305px"
height="305px"
frameborder="0"
></iframe>
</div>
<div class="tips">
{{
lanChange == "zh-cn"
? `扫描二维码进行付款`
: `Scan the QR code for payment`
}}
</div>
<div class="tips">扫描二维码进行付款</div>
<div class="btnBox">
<div>刷新二维码</div>
<div @click="RefreshQR">
{{ lanChange == "zh-cn" ? `刷新二维码` : `Refresh QR code` }}
</div>
</div>
</div>
</el-dialog>
@@ -249,10 +353,13 @@
<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 vueQr from "vue-qr/src/packages/vue-qr.vue";

const route = useRoute();
const router = useRouter();
const { locale } = useI18n();
@@ -262,220 +369,225 @@ 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([
// {
// 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;
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 ------------------------------------
@@ -517,12 +629,127 @@ 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);
async function createPayFunc(orderNumber) {
const data = {
orderNumber,
payVendor: myPayVendor.value,
};
try {
const res = await createPayApi(data);
if (res.code == 200) {
// 支付宝获取iframe内容
if (res.data.body) {
iframeBody.value = res.data.body;
iframeDom.value = document.getElementById("myIframe");
iframeDom.value.srcdoc = iframeBody.value;
}
// 直接获取二维码
if (res.data.codeUrl) {
payCodeUrl.value = res.data.codeUrl;
}
await getStatusOfOrderFunc(orderNumber);
} else {
payErrorHandle();
}
} catch (error) {
payErrorHandle();
}
}
// 获取订单支付状态 payStatus 查询支付状态 0:待支付,2:支付中,3:已支付
async function getStatusOfOrderFunc(orderNumber) {
if (
route.path != "/myStore" ||
orderCodeDialogShow.value == false ||
orderNumber != myOrderNumber.value
) {
return;
}
try {
let payVendor = myPayVendor.value;
const res = await getOrderStatusApi(orderNumber, payVendor);
if (res.code == 200) {
if (res.data.orderStatus == 3) {
orderCodeDialogShow.value = false;
ElMessage.success(
lanChange.value == "zh-cn" ? `支付成功!` : `Payment is successful!`
);
return;
} else {
setTimeout(() => {
getStatusOfOrderFunc(orderNumber);
}, 3000);
}
} 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;
}
// 刷新二维码
function RefreshQR() {
payCodeUrl.value = null;
iframeBody.value = null;
// createOrderFunc();
createPayFunc(myOrderNumber.value);
}
//#endregion ------------------------------------

//#region
@@ -742,7 +969,8 @@ onMounted(async () => {
font-size: 30px;
text-align: center;
}
.price {
.money {
text-align: center;
span {
font-size: 30px;
font-weight: 700;
@@ -750,7 +978,40 @@ onMounted(async () => {
}
}
.authority {
padding: 10px 20px;
margin-top: 10px;
&-item {
display: flex;
justify-content: space-between;
cursor: pointer;
font-weight: 400;
font-size: 14px;
padding: 2px 3px;
color: #7c7c7a;

span {
cursor: pointer;
color: #7c7c7a;
margin-right: 30px;
}
i {
font-size: 20px;
font-style: normal;
margin-right: 5px;
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;
}
}
}
}
.right {
@@ -779,8 +1040,8 @@ onMounted(async () => {
margin: auto;
justify-content: space-evenly;
align-items: center;
width: 300px;
height: 300px;
width: 350px;
height: 350px;
border: 1px solid #ccc;
border-radius: 15px;
overflow: hidden;


+ 944
- 0
src/views/userModel/index.vue View File

@@ -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>

+ 16
- 0
src/views/userModel/videoStatus.js View File

@@ -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"
}
}

+ 7
- 0
src/views/voiceModel/index.vue View File

@@ -0,0 +1,7 @@
<template>
<div></div>
</template>
<script setup>
// import { ref } from 'vue'
</script>
<style lang="scss" scoped></style>

+ 72
- 1
yarn.lock View File

@@ -2289,6 +2289,13 @@ decode-uri-component@^0.2.0:
resolved "https://registry.npmmirror.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz"
integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==

decompress-response@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc"
integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==
dependencies:
mimic-response "^3.1.0"

dedent@0.7.0:
version "0.7.0"
resolved "https://registry.npmmirror.com/dedent/-/dedent-0.7.0.tgz"
@@ -3182,6 +3189,17 @@ glob@7.2.3, glob@^7.1.3:
once "^1.3.0"
path-is-absolute "^1.0.0"

glob@^8.0.1:
version "8.1.0"
resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e"
integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==
dependencies:
fs.realpath "^1.0.0"
inflight "^1.0.4"
inherits "2"
minimatch "^5.0.1"
once "^1.3.0"

global-dirs@^0.1.1:
version "0.1.1"
resolved "https://registry.npmmirror.com/global-dirs/-/global-dirs-0.1.1.tgz"
@@ -3759,6 +3777,11 @@ js-base64@^2.1.9:
resolved "https://registry.npmmirror.com/js-base64/-/js-base64-2.6.4.tgz"
integrity sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==

js-binary-schema-parser@^2.0.2:
version "2.0.3"
resolved "https://registry.yarnpkg.com/js-binary-schema-parser/-/js-binary-schema-parser-2.0.3.tgz#3d7848748e8586e63b34e8911b643f59cfb6396e"
integrity sha512-xezGJmOb4lk/M1ZZLTR/jaBHQ4gG/lqQnJqdIv4721DMggsa1bDVlHXNeHYogaIEHD9vCRv0fcL4hMA+Coarkg==

js-sdsl@^4.1.4:
version "4.4.0"
resolved "https://registry.npmmirror.com/js-sdsl/-/js-sdsl-4.4.0.tgz"
@@ -4299,6 +4322,11 @@ mimic-fn@^4.0.0:
resolved "https://registry.npmmirror.com/mimic-fn/-/mimic-fn-4.0.0.tgz"
integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==

mimic-response@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9"
integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==

min-indent@^1.0.0:
version "1.0.1"
resolved "https://registry.npmmirror.com/min-indent/-/min-indent-1.0.1.tgz"
@@ -4311,6 +4339,13 @@ minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2:
dependencies:
brace-expansion "^1.1.7"

minimatch@^5.0.1:
version "5.1.6"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96"
integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==
dependencies:
brace-expansion "^2.0.1"

minimatch@^6.1.6:
version "6.2.0"
resolved "https://registry.npmjs.org/minimatch/-/minimatch-6.2.0.tgz"
@@ -4565,7 +4600,7 @@ ohash@^1.1.1:
resolved "https://registry.npmjs.org/ohash/-/ohash-1.1.2.tgz"
integrity sha512-9CIOSq5945rI045GFtcO3uudyOkYVY1nyfFxVQp+9BRgslr8jPNiSSrsFGg/BNTUFOLqx0P5tng6G32brIPw0w==

once@^1.3.0:
once@^1.3.0, once@^1.3.1:
version "1.4.0"
resolved "https://registry.npmmirror.com/once/-/once-1.4.0.tgz"
integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==
@@ -4665,6 +4700,11 @@ parent-module@^1.0.0:
dependencies:
callsites "^3.0.0"

parenthesis@^3.1.5:
version "3.1.8"
resolved "https://registry.yarnpkg.com/parenthesis/-/parenthesis-3.1.8.tgz#3457fccb8f05db27572b841dad9d2630b912f125"
integrity sha512-KF/U8tk54BgQewkJPvB4s/US3VQY68BRDpH638+7O/n58TpnwiwnOtGIOsT2/i+M78s61BBpeC83STB88d8sqw==

parse-json@^5.0.0:
version "5.2.0"
resolved "https://registry.npmmirror.com/parse-json/-/parse-json-5.2.0.tgz"
@@ -5271,6 +5311,20 @@ signal-exit@^4.0.1:
resolved "https://registry.npmmirror.com/signal-exit/-/signal-exit-4.0.2.tgz"
integrity sha512-MY2/qGx4enyjprQnFaZsHib3Yadh3IXyV2C321GY0pjGfVBu4un0uDJkwgdxqO+Rdx8JMT8IfJIRwbYVz3Ob3Q==

simple-concat@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f"
integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==

simple-get@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-4.0.1.tgz#4a39db549287c979d352112fa03fd99fd6bc3543"
integrity sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==
dependencies:
decompress-response "^6.0.0"
once "^1.3.1"
simple-concat "^1.0.0"

sirv@^2.0.2:
version "2.0.3"
resolved "https://registry.npmmirror.com/sirv/-/sirv-2.0.3.tgz"
@@ -5471,6 +5525,13 @@ string-argv@^0.3.1:
resolved "https://registry.npmmirror.com/string-argv/-/string-argv-0.3.2.tgz"
integrity sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==

string-split-by@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/string-split-by/-/string-split-by-1.0.0.tgz#53895fb3397ebc60adab1f1e3a131f5372586812"
integrity sha512-KaJKY+hfpzNyet/emP81PJA9hTVSfxNLS9SFTWxdCnnW1/zOOwiV248+EfoX7IQFcBaOp4G5YE6xTJMF+pLg6A==
dependencies:
parenthesis "^3.1.5"

string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
version "4.2.3"
resolved "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz"
@@ -6268,6 +6329,16 @@ vue-i18n@9:
"@intlify/vue-devtools" "9.2.2"
"@vue/devtools-api" "^6.2.1"

vue-qr@^4.0.9:
version "4.0.9"
resolved "https://registry.yarnpkg.com/vue-qr/-/vue-qr-4.0.9.tgz#6cb965dd0c5a0dff947e6ef582ef149b0780b986"
integrity sha512-pAISV94T0MNEYA3NGjykUpsXRE2QfaNxlu9ZhEL6CERgqNc21hJYuP3hRVzAWfBQlgO18DPmZTbrFerJC3+Ikw==
dependencies:
glob "^8.0.1"
js-binary-schema-parser "^2.0.2"
simple-get "^4.0.1"
string-split-by "^1.0.0"

vue-router@^4.0.13:
version "4.0.13"
resolved "https://registry.npmjs.org/vue-router/-/vue-router-4.0.13.tgz"


Loading…
Cancel
Save