Compare commits

...

99 Commits
master ... dev

Author SHA1 Message Date
  chutingting 6ab79212fe edit 1 year ago
  chutingting fd520ba2dc edit 1 year ago
  chutingting 2a1699a22b edit 1 year ago
  chutingting 8200692e68 edit 1 year ago
  chutingting 46aa2178be Merge branch 'ctt_dev' into dev 1 year ago
  chutingting 51d3cca8ad 生成文本 1 year ago
  chutingting 2e04075a55 Merge branch 'ctt_dev' into dev 1 year ago
  chutingting 7b52f5489e edit title 1 year ago
  chutingting f11a1b9266 Merge branch 'ctt_dev' into dev 1 year ago
  chutingting 32efebeb00 edit 1 year ago
  chutingting fa7462c376 Merge branch 'ctt_dev' into dev 1 year ago
  chutingting d398ae67b0 edit 1 year ago
  chutingting 402b7fb583 Merge branch 'ctt_dev' into dev 1 year ago
  chutingting 59e1dc524b edit title 1 year ago
  chutingting 49e818dd1b Merge branch 'ctt_dev' into dev 1 year ago
  chutingting 839d0187b5 edit api 1 year ago
  chutingting c57b72a200 Merge branch 'ctt_dev' into dev 1 year ago
  chutingting 160a196f97 edit time 1 year ago
  chutingting 35d2f84af5 Merge branch 'ctt_dev' into dev 1 year ago
  chutingting 6b83764334 0.2-2.0 1 year ago
  chutingting 663c23daec Merge branch 'ctt_dev' into dev 1 year ago
  chutingting dfbf58c9cf edit zindex 1 year ago
  chutingting e6f0f6a1d3 Merge branch 'ctt_dev' into dev 1 year ago
  chutingting 7edfa614f0 选中 1 year ago
  chutingting bba94a60d3 Merge branch 'ctt_dev' into dev 1 year ago
  chutingting 6069139fbc edit z 1 year ago
  chutingting e3819ec876 edit bug 1 year ago
  chutingting 1d86a399b2 del <<< 1 year ago
  chutingting 033edd82c1 edit 1 year ago
  chutingting b20b31fb89 Merge branch 'ctt_dev' into dev 1 year ago
  chutingting 58addd5730 scroll 1 year ago
  chutingting c74bc464f4 Merge branch 'ctt_dev' into dev 1 year ago
  chutingting 3ad78b3403 edit store 1 year ago
  chutingting 950b7df682 Merge branch 'ctt_dev' into dev 1 year ago
  chutingting e7a19528a5 edit css 1 year ago
  chutingting 554da99452 edit brn 1 year ago
  chutingting 3e27cd327f Merge branch 'ctt_dev' into dev 1 year ago
  chutingting 7e81f3d01f edit api 1 year ago
  chutingting b5f14fede7 Merge branch 'ctt_dev' into dev 1 year ago
  chutingting 8141254955 edit 1 year ago
  chutingting cb50dc5d39 Merge branch 'ctt_dev' into dev 1 year ago
  chutingting 989b30db37 add api 1 year ago
  chutingting 8feb90eb08 Merge branch 'ctt_dev' into dev 1 year ago
  chutingting 7f22868ba4 edit 1 year ago
  chutingting d84265284b Merge branch 'ctt_dev' into dev 1 year ago
  chutingting f6c2c026e7 edit text 1 year ago
  chutingting fbf81777a9 Merge branch 'ctt_dev' into dev 1 year ago
  chutingting 6ed3529c76 扣币 1 year ago
  chutingting ed308e3b5a Merge branch 'ctt_dev' into dev 1 year ago
  chutingting f707fb32e8 gpt 1 year ago
  chutingting 6a44a097b0 Merge branch 'ctt_dev' into dev 1 year ago
  chutingting 7151d06fc5 url 1 year ago
  chutingting d117cdedcf Merge branch 'ctt_dev' into dev 1 year ago
  chutingting 211f69236b 图片检验 1 year ago
  chutingting a243eaa438 Merge branch 'ctt_dev' into dev 1 year ago
  chutingting 4ca7040149 lang 1 year ago
  chutingting 0626bbf500 Merge branch 'ctt_dev' into dev 1 year ago
  chutingting 8e55ff3bad edit 1 year ago
  chutingting 952e2d5086 私人定制 1 year ago
  chutingting bf8c02b7d9 Merge branch 'ctt_dev' into dev 1 year ago
  chutingting 8ef05dfe4c 校验视频 1 year ago
  chutingting 3d8f2222cb Merge branch 'ctt_dev' into dev 1 year ago
  chutingting 0a714db591 edit qrcode 1 year ago
  chutingting aff24e3fe8 Merge branch 'ctt_dev' into dev 1 year ago
  chutingting 4d35512fa0 rem 1 year ago
  chutingting 1fa971c933 Merge branch 'ctt_dev' into dev 1 year ago
  chutingting 7958f5ab55 edit css 1 year ago
  chutingting 2559a9de1f Merge branch 'ctt_dev' into dev 1 year ago
  chutingting 6709710325 edit font 1 year ago
  chutingting 0c3d8db5b2 Merge branch 'ctt_dev' into dev 1 year ago
  chutingting 46199d670d del rem 1 year ago
  chutingting bd7fb0d798 Merge branch 'ctt_dev' into dev 1 year ago
  chutingting 9c23f77397 订单详情 1 year ago
  chutingting a948491b70 Merge branch 'ctt_dev' into dev 1 year ago
  chutingting b37aa42c96 订单 1 year ago
  chutingting a9a5602285 edit 1 year ago
  chutingting a607c1b042 ts 1 year ago
  chutingting 73063a7d6d 订单 1 year ago
  chutingting b1f302eaec edit 1 year ago
  chutingting 68c3e279cb edit 1 year ago
  chutingting 37d6d4f994 username 1 year ago
  chutingting e5c1449d5f 支付 1 year ago
  chutingting 93903fef14 支付 1 year ago
  chutingting b72534ac83 支付 1 year ago
  chutingting 39f9567d79 商店 1 year ago
  chutingting 7357522f0d 增加我的 1 year ago
  chutingting d09946669c 增加我的列表 1 year ago
  chutingting ac2822f97d test 1 year ago
  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
42 changed files with 4972 additions and 1016 deletions
Split View
  1. +3
    -1
      .env.development
  2. +1
    -1
      .env.test
  3. BIN
      dist.zip
  4. +1
    -1
      index.html
  5. +1
    -0
      package.json
  6. +39
    -0
      src/apis/api.js
  7. +65
    -4
      src/apis/createVideo.js
  8. +81
    -0
      src/apis/my.js
  9. +2
    -1
      src/apis/myCreating.js
  10. +40
    -1
      src/apis/myStore.js
  11. +39
    -0
      src/apis/pay.js
  12. BIN
      src/assets/img/alipay.png
  13. BIN
      src/assets/img/gpt.png
  14. BIN
      src/assets/img/weChat.png
  15. +17
    -12
      src/components/EditPosition.vue
  16. +42
    -14
      src/components/cutImg.vue
  17. +51
    -0
      src/components/myLoadingIcon2.vue
  18. +59
    -0
      src/lang/package/en.ts
  19. +59
    -0
      src/lang/package/zh-cn.ts
  20. +80
    -13
      src/layout/index.vue
  21. +108
    -8
      src/router/index.ts
  22. +1
    -0
      src/store/modules/userInfo.js
  23. +4
    -0
      src/types/auto-imports.d.ts
  24. +11
    -0
      src/types/components.d.ts
  25. +2
    -2
      src/utils/request.js
  26. +141
    -0
      src/views/api/demo.html
  27. +125
    -0
      src/views/api/index.vue
  28. +755
    -148
      src/views/createVideo/index.vue
  29. +17
    -8
      src/views/login/index.vue
  30. +207
    -0
      src/views/my/coindeduc.vue
  31. +193
    -0
      src/views/my/recharge.vue
  32. +0
    -22
      src/views/myAPI/index.vue
  33. +2
    -1
      src/views/myCreating/index.vue
  34. +1152
    -0
      src/views/myStore/index copy.vue
  35. +303
    -445
      src/views/myStore/index.vue
  36. +7
    -0
      src/views/privatization/index.vue
  37. +6
    -0
      src/views/separation/index.vue
  38. +944
    -0
      src/views/userModel/index.vue
  39. +16
    -0
      src/views/userModel/videoStatus.js
  40. +7
    -0
      src/views/voiceModel/index.vue
  41. +6
    -0
      src/views/voiceprint/index.vue
  42. +385
    -334
      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://m.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
- 1
index.html View File

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


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


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

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

+ 65
- 4
src/apis/createVideo.js View File

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

+ 81
- 0
src/apis/my.js View File

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

+ 2
- 1
src/apis/myCreating.js View File

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

+ 40
- 1
src/apis/myStore.js View File

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


+ 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'
})
}

BIN
src/assets/img/alipay.png View File

Before After
Width: 200  |  Height: 200  |  Size: 3.7 KiB

BIN
src/assets/img/gpt.png View File

Before After
Width: 80  |  Height: 80  |  Size: 9.3 KiB

BIN
src/assets/img/weChat.png View File

Before After
Width: 200  |  Height: 200  |  Size: 4.0 KiB

+ 17
- 12
src/components/EditPosition.vue View File

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


+ 42
- 14
src/components/cutImg.vue View File

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


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

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

@@ -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...',
}
};

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

@@ -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: '支付中...',
}
};

+ 80
- 13
src/layout/index.vue View File

@@ -23,39 +23,68 @@
</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("cooperate.title") }}</span>
</template>
<el-menu-item-group>
<el-menu-item index="1-1" @click="router.push('/api')">{{ $t("cooperate.api.title") }}</el-menu-item>
<el-menu-item index="1-2" @click="router.push('/privatization')">{{ $t("cooperate.privatization.title") }} </el-menu-item>
</el-menu-item-group>
</el-sub-menu>
<el-sub-menu index="2">
<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 +95,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 +133,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 +200,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 +253,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 +269,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 +295,6 @@ const updateShowTalkUsDialog = (newValue: any) => {
vertical-align: sub;
}
}

&:hover {
// background: rgba(255, 255, 255, 0.2);
color: #000;
@@ -261,7 +321,7 @@ const updateShowTalkUsDialog = (newValue: any) => {
}
}
.rightBox {
width: 1690px;
width: calc(100% - 230px);
// background-color: #000;
.nav {
display: flex;
@@ -280,4 +340,11 @@ const updateShowTalkUsDialog = (newValue: any) => {
}
}
}
.el-menu{
border: none;
:deep .el-sub-menu__title, :deep .el-menu-item{
font-size: 18px;
}

}
</style>

+ 108
- 8
src/router/index.ts View File

@@ -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 = 'Metavatar-' + (to.query.p || from.query.p || localStorage.getItem("title") || '慧影')
})
/**
* 重置路由
*/


+ 1
- 0
src/store/modules/userInfo.js View File

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


+ 4
- 0
src/types/auto-imports.d.ts View File

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


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

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


+ 2
- 2
src/utils/request.js View File

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


+ 141
- 0
src/views/api/demo.html View File

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

+ 125
- 0
src/views/api/index.vue View File

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

+ 755
- 148
src/views/createVideo/index.vue
File diff suppressed because it is too large
View File


+ 17
- 8
src/views/login/index.vue View File

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


+ 207
- 0
src/views/my/coindeduc.vue View File

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

+ 193
- 0
src/views/my/recharge.vue View File

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

+ 0
- 22
src/views/myAPI/index.vue View File

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

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


+ 1152
- 0
src/views/myStore/index copy.vue
File diff suppressed because it is too large
View File


+ 303
- 445
src/views/myStore/index.vue View File

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


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

@@ -0,0 +1,7 @@

<!--
* @Description: 定制分身
-->
<template>
<iframe src="/priMakeHtml/siyouhuabushu/index.shtml" style="width: 100%;height:86vh"></iframe>
</template>

+ 6
- 0
src/views/separation/index.vue View File

@@ -0,0 +1,6 @@
<!--
* @Description: 定制声纹
-->
<template>
<iframe src="/priMakeHtml/dingzhifenshen/index.shtml" style="width: 100%;height:86vh"></iframe>
</template>

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

+ 6
- 0
src/views/voiceprint/index.vue View File

@@ -0,0 +1,6 @@
<!--
* @Description: 定制分身
-->
<template>
<iframe src="/priMakeHtml/dingzhishengwen/index.shtml" style="width: 100%;height:86vh"></iframe>
</template>

+ 385
- 334
yarn.lock
File diff suppressed because it is too large
View File


Loading…
Cancel
Save