Bladeren bron

编辑草稿

dev
congzc 2 jaren geleden
bovenliggende
commit
119df6ad08
11 gewijzigde bestanden met toevoegingen van 239 en 293 verwijderingen
  1. +13
    -0
      src/apis/createVideo.js
  2. +2
    -0
      src/lang/package/en.ts
  3. +2
    -0
      src/lang/package/zh-cn.ts
  4. +16
    -52
      src/layout/components/Navbar.vue
  5. +1
    -1
      src/permission.ts
  6. +0
    -203
      src/router/index copy.ts
  7. +1
    -0
      src/types/components.d.ts
  8. +2
    -2
      src/utils/request.js
  9. +114
    -24
      src/views/createVideo/index.vue
  10. +13
    -3
      src/views/myCreating/index.vue
  11. +75
    -8
      src/views/myStore/index.vue

+ 13
- 0
src/apis/createVideo.js Bestand weergeven

@@ -167,4 +167,17 @@ export function createVideoApi(data) {
method: 'POST',
data
})
}


/**
* @description 根据作品id查询作品信息
* @params data
* @returns data
*/
export function findByIdApi(id) {
return request({
url: `/api/userPhotoVideo/findById?id=${id}`,
method: 'get',
})
}

+ 2
- 0
src/lang/package/en.ts Bestand weergeven

@@ -35,6 +35,7 @@ export default {
navbar: {
account: "Account",
logout: "Logout",
goLogin:'Go and log in'
},

// 创作视频
@@ -100,6 +101,7 @@ export default {
successed: "Successed",
failed: "Failed",
msg1: "Obtain one video production time",

},

// 商店


+ 2
- 0
src/lang/package/zh-cn.ts Bestand weergeven

@@ -35,6 +35,7 @@ export default {
navbar: {
account: "账户",
logout: "注销",
goLogin:'登录'
},

// 创作视频
@@ -100,6 +101,7 @@ export default {
successed: "支付成功",
failed: "支付失败",
msg1: "获得视频制作次数一次",

},

// 商店


+ 16
- 52
src/layout/components/Navbar.vue Bestand weergeven

@@ -9,64 +9,26 @@
/>
<breadcrumb />
</div>
<!-- 右侧导航设置 -->
<div class="flex" v-if="false">
<!-- 导航栏设置(窄屏隐藏)-->
<div class="setting-container" v-if="device !== 'mobile'">
<!--全屏 -->
<div class="setting-item" @click="toggle" v-if="false">
<svg-icon
:icon-class="isFullscreen ? 'exit-fullscreen' : 'fullscreen'"
/>
</div>
<!-- 布局大小 -->
<el-tooltip
content="布局大小"
effect="dark"
placement="bottom"
v-if="false"
>
<size-select class="setting-item" />
</el-tooltip>
</div>
<!-- 用户头像 -->
<span class="account" @click="routerTo">个人账户</span>
<el-dropdown trigger="click" v-if="false">
<div class="avatar-container">
<img :src="userStore.avatar + '?imageView2/1/w/80/h/80'" />
<i-ep-caret-bottom class="w-3 h-3" />
</div>
<template #dropdown>
<el-dropdown-menu>
<router-link to="/">
<el-dropdown-item>{{ $t("navbar.dashboard") }}</el-dropdown-item>
</router-link>
<a target="_blank" href="https://github.com/hxrui">
<el-dropdown-item>Github</el-dropdown-item>
</a>
<a target="_blank" href="https://gitee.com/haoxr">
<el-dropdown-item>{{ $t("navbar.gitee") }}</el-dropdown-item>
</a>
<a target="_blank" href="https://www.cnblogs.com/haoxianrui/">
<el-dropdown-item>{{ $t("navbar.document") }}</el-dropdown-item>
</a>
<el-dropdown-item divided @click="logout">
{{ $t("navbar.logout") }}
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
<!-- 显示的,以上代码作废 -->

<div style="position: absolute; left: 30px; font-size: 26px">
{{ $t(routeName as string) }}
</div>
<!--语言选择-->
<lang-select class="navItem" style="color: #ffffff" />

<div class="avatar" @click="routerTo"></div>
<div class="navItem" @click="routerTo">{{ $t("navbar.account") }}</div>
<div class="navItem" @click="logout" style="margin-left: 10px">
<!-- <div class="avatar" v-if="AccessToken" @click="routerTo"></div> -->
<div class="navItem" v-if="AccessToken" @click="routerTo">
{{ $t("navbar.account") }}
</div>
<div class="navItem" v-if="!AccessToken" @click="router.push('login')">
{{ $t("navbar.goLogin") }}
</div>
<div
class="navItem"
v-if="AccessToken"
@click="logout"
style="margin-left: 10px"
>
{{ $t("navbar.logout") }}
</div>
</div>
@@ -96,6 +58,7 @@ const router = useRouter();

const { device } = storeToRefs(appStore); // 设备类型:desktop-宽屏设备 || mobile-窄屏设备

const AccessToken = localStorage.getItem("AccessToken"); // 登录状态
/**
* 左侧菜单栏显示/隐藏
*/
@@ -207,6 +170,7 @@ watch(
.navItem {
cursor: pointer;
transition: all 0.3s;
margin-right: 10px;
&:hover {
color: #4769da;
}


+ 1
- 1
src/permission.ts Bestand weergeven

@@ -9,7 +9,7 @@ NProgress.configure({ showSpinner: false }); // 进度条
const permissionStore = usePermissionStoreHook();

// 白名单路由
const whiteList = ["/login", "/signSucceed"];
const whiteList = ["/login", "/signSucceed",'/createVideo','/myStore'];

router.beforeEach(async (to, from, next) => {
NProgress.start();


+ 0
- 203
src/router/index copy.ts Bestand weergeven

@@ -1,203 +0,0 @@
import { createRouter, createWebHashHistory, RouteRecordRaw } from "vue-router";
import { getCurrentInstance } from "vue";

export const Layout = () => import("@/layout/index.vue");

// 静态路由
export const constantRoutes: RouteRecordRaw[] = [
{
path: "/redirect",
component: Layout,
meta: { hidden: true },
children: [
{
path: "/redirect/:path(.*)",
component: () => import("@/views/redirect/index.vue"),
},
],
},
// 登录
{
path: "/login",
component: () => import("@/views/login/index.vue"),
meta: { hidden: true },
name:'login'
},
{
path: "/signSucceed",
component: () => import("@/views/signSucceed/index.vue"),
meta: { hidden: true },
},
// 创建视频
{
path: "/",
component: Layout,
redirect: "/createVideo",
children: [
{
path: "createVideo",
component: () => import("@/views/createVideo/index.vue"),
name: "createVideo",
meta: {
title: "createVideo",
icon: "homepage",
affix: true,
name: "createVideo.title",
},
},
],
},
// 视频列表
{
path: "/",
component: Layout,
redirect: "/myCreating",
children: [
{
path: "myCreating",
component: () => import("@/views/myCreating/index.vue"),
name: "myCreating",
meta: {
title: "myCreating",
icon: "homepage",
affix: true,
name: "myCreating.title",
},
},
],
},
// 个人账户
{
path: "/",
component: Layout,
redirect: "/myAccount",
children: [
{
path: "myAccount",
component: () => import("@/views/myAccount/index.vue"),
name: "myAccount",
meta: {
title: "myAccount",
icon: "homepage",
affix: true,
name: "account.title",
},
},
],
},
// 商店
{
path: "/",
component: Layout,
redirect: "/myStore",
children: [
{
path: "myStore",
component: () => import("@/views/myStore/index.vue"),
name: "myStore",
meta: {
title: "myStore",
icon: "homepage",
affix: true,
name: "shop.title",
},
},
],
},

// {
// path: "/dashboard",
// component: Layout,
// redirect: "/dashboard",
// children: [
// {
// path: "dashboard",
// component: () => import("@/views/dashboard/index.vue"),
// name: "Dashboard",
// meta: { title: "dashboard", icon: "homepage", affix: true },
// },
// {
// path: "401",
// component: () => import("@/views/error-page/401.vue"),
// meta: { hidden: true },
// },
// {
// path: "404",
// component: () => import("@/views/error-page/404.vue"),
// meta: { hidden: true },
// },
// ],
// },

// 外部链接
/*{
path: '/external-link',
component: Layout,
children: [
{
path: 'https://www.cnblogs.com/haoxianrui/',
meta: { title: '外部链接', icon: 'link' }
}
]
}*/
// 多级嵌套路由
/* {
path: '/nested',
component: Layout,
redirect: '/nested/level1/level2',
name: 'Nested',
meta: {title: '多级菜单', icon: 'nested'},
children: [
{
path: 'level1',
component: () => import('@/views/nested/level1/index.vue'),
name: 'Level1',
meta: {title: '菜单一级'},
redirect: '/nested/level1/level2',
children: [
{
path: 'level2',
component: () => import('@/views/nested/level1/level2/index.vue'),
name: 'Level2',
meta: {title: '菜单二级'},
redirect: '/nested/level1/level2/level3',
children: [
{
path: 'level3-1',
component: () => import('@/views/nested/level1/level2/level3/index1.vue'),
name: 'Level3-1',
meta: {title: '菜单三级-1'}
},
{
path: 'level3-2',
component: () => import('@/views/nested/level1/level2/level3/index2.vue'),
name: 'Level3-2',
meta: {title: '菜单三级-2'}
}
]
}
]
},
]
}*/
];

/**
* 创建路由
*/
const router = createRouter({
history: createWebHashHistory(),
routes: constantRoutes as RouteRecordRaw[],
// 刷新时,滚动条位置还原
// 2023-5-23 添加平滑滚动 YWQ
scrollBehavior: () => ({ behavior: "smooth", left: 0, top: 0 }),
});

/**
* 重置路由
*/
export function resetRouter() {
router.replace({ path: "/login" });
}

export default router;

+ 1
- 0
src/types/components.d.ts Bestand weergeven

@@ -81,6 +81,7 @@ declare module '@vue/runtime-core' {
WangEditor: typeof import('./../components/WangEditor/index.vue')['default']
}
export interface ComponentCustomProperties {
vInfiniteScroll: typeof import('element-plus/es')['ElInfiniteScroll']
vLoading: typeof import('element-plus/es')['ElLoadingDirective']
}
}

+ 2
- 2
src/utils/request.js Bestand weergeven

@@ -35,8 +35,8 @@ request.interceptors.request.use(
request.interceptors.response.use(
function (response) {
let code = response.data.code
// 当token无效(过期或损坏)时
if (code == 1052) {
// 当token无效(过期或损坏)时 1053为未登录
if (code == 1052 || code == 1053) {
localStorage.removeItem("AccessToken");
router.push("/login");
ElMessage.error("登录过期,请重新登录!");


+ 114
- 24
src/views/createVideo/index.vue Bestand weergeven

@@ -13,6 +13,7 @@
style="width: 300px"
>
<el-input
maxlength="15"
v-model="title"
:placeholder="$t('createVideo.typeTitle')"
/>
@@ -130,20 +131,26 @@
<div
class="pointer"
:class="showFace == 0 ? 'tabAvtive' : ''"
@click="ChangeShowFaceList(0)"
@click="showFace = 0"
>
{{ $t("createVideo.availableMould") }}
</div>
<div
v-if="AccessToken"
class="pointer"
:class="showFace == 1 ? 'tabAvtive' : ''"
@click="ChangeShowFaceList(1)"
@click="showFace = 1"
>
{{ $t("createVideo.personalWarehouse") }}
</div>
</div>
<!-- 系统相册 -->
<div class="faceList" v-if="showFace == 0">
<div
class="faceList"
v-if="showFace == 0"
v-infinite-scroll="loadMoreAiFaceSystem"
:infinite-scroll-disabled="overLoadSystem"
>
<!-- 上传图片组件 -->
<div v-if="showFace == 1" class="faceItem" @click="clickAddBtn">
<span class="uploadImg">+ </span>
@@ -164,7 +171,12 @@
</div>
</div>
<!-- 个人相册 -->
<div class="faceList" v-if="showFace == 1">
<div
class="faceList"
v-if="showFace == 1"
v-infinite-scroll="loadMoreAiFaceUser"
:infinite-scroll-disabled="overLoadUser"
>
<!-- 上传图片组件 -->
<div v-if="showFace == 1" class="faceItem" @click="clickAddBtn">
<span class="uploadImg">+ </span>
@@ -210,8 +222,8 @@
<span
class="pointer"
@click="getPreviewAudio"
style="margin-right: 10px; font-size: 30px"
>🕬</span
style="margin-right: 10px; font-size: 20px"
>🔊</span
>
<span class="pointer" @click="insertIcon">🕗</span>
</div>
@@ -460,20 +472,26 @@ import {
saveOrUpdateApi,
createVideoApi,
previewAudioApi,
findByIdApi,
} from "@/apis/createVideo";
import { useI18n } from "vue-i18n";
import Recorder from "js-audio-recorder"; //mp3插件
import imageCompression from "browser-image-compression"; //压缩图片插件

import { useRoute, useRouter } from "vue-router";
const route = useRoute();
const router = useRouter();
const { locale } = useI18n();
const lanChange = ref(locale);

const AccessToken = localStorage.getItem("AccessToken"); // 判断有没有登录

//#region 头像区的逻辑
// 获取AI头像
const AiFaceList = ref([]);
const userAiFaceList = ref([]);
const AiFaceList = ref([]); //系统相册列表
const userAiFaceList = ref([]); //个人相册列表
const feceItemLoading = ref(false);
const feceItemLoading2 = ref(false);

function getAiFaceList(pageNum, pageSize, sendType) {
feceItemLoading.value = true;
personPhotoList(pageNum, pageSize, sendType)
@@ -498,16 +516,43 @@ function getAiFaceUserList(pageNum, pageSize, sendType) {
console.log(err, "err");
});
}
const pageNumSystem = ref(1);
const overLoadSystem = ref(false); //禁用系统相册加载更多
const pageNumUser = ref(1);
const overLoadUser = ref(false); //禁用个人相册加载更多
//系统相册触底加载更多
function loadMoreAiFaceSystem() {
pageNumSystem.value += 1;
personPhotoList(pageNumSystem.value, 10, 1)
.then((res) => {
AiFaceList.value.push(...res.data.list);
if (res.data.list.length == 0) {
overLoadSystem.value = true;
pageNumSystem.value = pageNumSystem.value - 1;
}
})
.catch((err) => {
console.log(err, "err");
});
}
//个人相册触底加载更多
function loadMoreAiFaceUser() {
pageNumUser.value += 1;
personPhotoUserListList(pageNumUser.value, 10, 3)
.then((res) => {
if (res.data.list.length == 0) {
overLoadUser.value = true;
pageNumUser.value = pageNumUser.value - 1;
}
userAiFaceList.value.push(...res.data.list);
})
.catch((err) => {
console.log(err, "err");
});
}
// 选择显示的face列表
const showFace = ref("0");
function ChangeShowFaceList(index) {
AiFaceList.value = null;
if (index == 0) {
getAiFaceList(1, 100, 1);
}
if (index == 1) {
getAiFaceUserList(1, 100, 3);
}
showFace.value = index;
}
const faceItemActive = ref(); //高亮处理和当前选择图片的ID
@@ -518,6 +563,7 @@ function setImgUrl(url, id) {
submitImgBtn.value = false;
imgUrl.value = url;
}
// 删除个人相册照片
async function deleteFaceImg(id) {
const msg =
lanChange.value == "zh-cn"
@@ -534,7 +580,10 @@ async function deleteFaceImg(id) {
const res = await delImgApi(id);
imgUrl.value = null;
faceItemActive.value = null;
getAiFaceUserList(1, 100, 3);
userAiFaceList.value = [];
getAiFaceUserList(1, 10, 3);
pageNumUser.value = 1;
overLoadUser.value = false;
} catch (error) {
ElMessage.error(errpr);
}
@@ -598,7 +647,10 @@ async function changeFile() {
// 重新获取列表
compressionImgLoad.value = false;
showUploadBtn.value = 4;
getAiFaceUserList(1, 100, 3);
userAiFaceList.value = [];
getAiFaceUserList(1, 10, 3);
pageNumUser.value = 1;
overLoadUser.value = false;
if (res2.code == 200) {
ElMessage.success(
lanChange.value == "zh-cn" ? `上传成功` : `Upload successfully`
@@ -697,8 +749,14 @@ async function getPreviewAudio() {
sound.value,
soundStyle.value
);
if (!res.data.data) {
ElMessage.error(
lanChange.value == "zh-cn"
? `暂时无法试听,请稍后重试`
: `Unable to listen, please try again later`
);
}
previewAudioUrl.value = res.data.data;
console.log(previewAudioUrl.value);
} catch (error) {
ElMessage.error(error);
}
@@ -798,6 +856,7 @@ async function uploadProgress(videoId, isSaveVideo) {
}
// 定义参数
const saveOrUpdateData = {
id: id.value, //从草稿或者重新编辑回到创建视频时有id
title: title.value,
personPhotoId: faceItemActive.value, //任务照片id,
voiceFrom: tabFrom.value, //:声音来源 1:来自选择模板,2:来自用户上传
@@ -808,11 +867,13 @@ async function uploadProgress(videoId, isSaveVideo) {
};
try {
const res3 = await saveOrUpdateApi(saveOrUpdateData); // 保存数据
// 这个if判断是不是仅仅保存视频
if (isSaveVideo == "saveVideo") {
ElMessage.success(
lanChange.value == "zh-cn" ? `已保存为草稿` : `Saved as draft`
);
createLoading.value = false;
router.push("/myCreating");
return;
}
const res4 = await createVideoApi({ id: res3.data.id }); // 生成视频
@@ -824,6 +885,7 @@ async function uploadProgress(videoId, isSaveVideo) {
);
}
createLoading.value = false;
router.push("/myCreating");
} catch (error) {
ElMessage.error(error);
createLoading.value = false;
@@ -844,6 +906,7 @@ async function saveOrUpdate(index, isSaveVideo) {
}
tabFrom.value = index;
const saveOrUpdateData = {
id: id.value, //从草稿或者重新编辑回到创建视频时有id
title: title.value,
personPhotoId: faceItemActive.value, //任务照片id,
voiceFrom: tabFrom.value, //:声音来源 1:来自选择模板,2:来自用户上传
@@ -856,11 +919,13 @@ async function saveOrUpdate(index, isSaveVideo) {
createLoading.value = true;
try {
const res2 = await saveOrUpdateApi(saveOrUpdateData); // 保存数据
// 这个if判断是不是仅仅保存视频
if (isSaveVideo == "saveVideo") {
ElMessage.success(
lanChange.value == "zh-cn" ? `已保存为草稿` : `Saved as draft`
);
createLoading.value = false;
router.push("/myCreating");
return;
}
const res3 = await createVideoApi({ id: res2.data.id }); // 生成视频
@@ -872,6 +937,7 @@ async function saveOrUpdate(index, isSaveVideo) {
);
}
createLoading.value = false;
router.push("/myCreating");
} catch (error) {
ElMessage.error(error);
createLoading.value = false;
@@ -888,6 +954,26 @@ async function saveOrUpdate(index, isSaveVideo) {
}
//#endregion ----------------------------

//#region 根据作品id查询作品信息并回显
const id = ref(null); //作品的id
async function findById(findId) {
const res = await findByIdApi(findId);
id.value = res.data.id;
title.value = res.data.title; //标题回显
faceItemActive.value = res.data.personPhotoId; //aiface高亮和图片id
tabFrom.value = res.data.voiceFrom; //输入文案还是上传mp3模式
textareaContent.value = res.data.paperwork; //文案内容
afterSaveAudioId.value = res.data.voiceMaterialId; //保存音频后得到的id
imgUrl.value = res.data.personPhotoUrl; //图片回显
audioUrl.value = res.data.voiceMaterialUrl; // mp3回显
language.value = res.data.voiceInfo.languageId;
await chooseType(language.value);
sound.value = res.data.voiceMouldId; //声音id
chooseStyle();
soundStyle.value = res.data.speakTypeStr; //选择风格
}
//#endregion ----------------------------

//#region

//#endregion ----------------------------
@@ -902,11 +988,15 @@ const {
const string = "createVideo.typeScript";
const t = globalProperties.$t(string);

onMounted(() => {
getAiFaceList(1, 100, 1);
getAiFaceUserList(1, 100, 3);
voiceTotal();
chooseType();
onMounted(async () => {
getAiFaceList(1, 10, 1);
if (AccessToken) {
getAiFaceUserList(1, 10, 3);
}
await voiceTotal();
if (route.query.id) {
findById(route.query.id);
}
});
</script>



+ 13
- 3
src/views/myCreating/index.vue Bestand weergeven

@@ -116,7 +116,7 @@
</el-icon>
<span class="loadingText">{{ $t("myCreating.loading") }}</span>
</div>
<!-- 预览作品 -->
<!-- 弹出框预览作品 -->
<el-dialog
destroy-on-close
class="elDialog"
@@ -165,13 +165,23 @@
<template #footer v-if="!presentItem.videoPlayUrl">
<span class="dialog-footer">
<!-- dialog编辑按钮 -->
<button class="elBtn" type="primary" @click.stop="">
<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>
</template>
</el-dialog>

<!-- 分页 -->
<div v-if="!isLoading" class="pagination">
<el-pagination
v-model:current-page="pageNum"


+ 75
- 8
src/views/myStore/index.vue Bestand weergeven

@@ -57,18 +57,41 @@
</div>
</div>
<div class="right">
<div style="background-color: #07c160">
<div style="background-color: #07c160" @click="showOrderCode(1)">
{{ $t("shop.WeChatPay") }}
</div>
<div style="background-color: #1378fe">{{ $t("shop.Alipay") }}</div>
<div style="background-color: #0070ba">Paypal</div>
<div style="background-color: #1378fe" @click="showOrderCode(2)">
{{ $t("shop.Alipay") }}
</div>
<div style="background-color: #0070ba" @click="showOrderCode(3)">
Paypal
</div>
</div>
</div>
<!-- 二维码弹出框 -->
<el-dialog
v-model="orderCodeDialogShow"
width="30%"
append-to-body
destroy-on-close
>
<div class="orderCodeDialog">
<div class="codeImg">
<img src="../../assets/img/false1.png" alt="" />
</div>
<div class="tips">扫描二维码进行付款</div>
<div class="btnBox">
<div>刷新二维码</div>
</div>
</div>
</el-dialog>
</el-dialog>
</div>
</template>

<script setup>
const title = ref("");
//#region 各个套餐的逻辑
const list = reactive([
{
color: "#f3af00",
@@ -133,19 +156,30 @@ const list = reactive([
],
},
]);

const showPayDialog = ref(false);
const presentItme = reactive({});
const showPayDialog = ref(false); //套餐信息dialog显示隐藏
const presentItme = reactive({}); //点击的套餐项
function clickPayDialog(item) {
presentItme.value = item;
console.log(presentItme);
showPayDialog.value = true;
}
function showOrderCode(type) {
orderCodeDialogShow.value = true;
}
//#endregion ------------------------------------

//#region 点击套餐内的支付
const orderCodeDialogShow = ref(false);
//#endregion ------------------------------------

//#region

//#endregion ------------------------------------
</script>

<style lang="scss" scoped>
.page {
height: 1200px;
height: calc(100vh - 80px);
padding: 20px 0 0 20px;
background-color: #fff;
border-radius: 25px 0 0;
@@ -162,7 +196,7 @@ function clickPayDialog(item) {
// -ms-overflow-style: none; /* 隐藏滚动条(IE、Edge) */
.item {
width: 350px;
height: 100%;
height: 800px;
margin-left: 50px;
background-color: #fffefd;
flex-shrink: 0; /* 防止缩小宽度 */
@@ -296,4 +330,37 @@ function clickPayDialog(item) {
}
}
}
.orderCodeDialog {
width: 100%;
.codeImg {
display: flex;
justify-content: space-evenly;
img {
width: 300px;
height: 300px;
}
}
.tips {
padding-top: 10px;
text-align: center;
}
.btnBox {
padding: 15px 40px;
display: flex;
justify-content: space-evenly;
> div {
padding: 10px 20px;
color: #000;
background-color: #fff;
border: #000 solid 1px;
border-radius: 10px;
transition: all 0.3s;
cursor: pointer;
&:hover {
color: #fff;
background-color: #000;
}
}
}
}
</style>

Laden…
Annuleren
Opslaan