congzc před 1 rokem
rodič
revize
d71a798bcc
9 změnil soubory, kde provedl 596 přidání a 102 odebrání
  1. +2
    -1
      src/lang/package/en.ts
  2. +1
    -0
      src/lang/package/zh-cn.ts
  3. +133
    -0
      src/layout/index copy.vue
  4. +232
    -73
      src/layout/index.vue
  5. +19
    -0
      src/router/index.ts
  6. +7
    -0
      src/styles/my.scss
  7. +55
    -28
      src/views/createVideo/index.vue
  8. +131
    -0
      src/views/moveImg/index.vue
  9. +16
    -0
      src/views/moveImg/videoStatus.js

+ 2
- 1
src/lang/package/en.ts Zobrazit soubor

@@ -84,7 +84,8 @@ export default {
// uploadImgTip2:'Please upload unobstructed frontal photo',
uploadImgTip2:'please upload a clear frontal photo',
entered:'entered'
entered:'entered',
subtitles:"subtitles",
},

// 我的视频


+ 1
- 0
src/lang/package/zh-cn.ts Zobrazit soubor

@@ -83,6 +83,7 @@ export default {
uploadImgTip1:'点此上传图片',
uploadImgTip2:'请确保上传图片为无遮挡的正脸图片',
entered:'已输入',
subtitles:"字幕",
},

// 我的视频


+ 133
- 0
src/layout/index copy.vue Zobrazit soubor

@@ -0,0 +1,133 @@
<template>
<div :class="classObj" class="app-wrapper">
<!-- 手机设备侧边栏打开遮罩层 -->
<div
v-if="classObj.mobile && classObj.openSidebar"
class="drawer-bg"
@click="handleOutsideClick"
></div>

<Sidebar class="sidebar-container" />

<div :class="{ hasTagsView: showTagsView }" class="main-container">
<div :class="{ 'fixed-header': fixedHeader }">
<navbar />
<tags-view v-if="showTagsView" />
</div>

<!--主页面-->
<app-main />

<!-- 设置面板 -->
<RightPanel v-if="showSettings">
<settings />
</RightPanel>
</div>
</div>
</template>

<script setup lang="ts">
import { computed, watchEffect } from "vue";
import { useWindowSize } from "@vueuse/core";
import { AppMain, Navbar, Settings, TagsView } from "./components/index";
import SignSucceed from "../views/signSucceed/index.vue";
import Sidebar from "./components/Sidebar/index.vue";
import RightPanel from "@/components/RightPanel/index.vue";

import { useAppStore } from "@/store/modules/app";
import { useSettingsStore } from "@/store/modules/settings";
import { useRoute, useRouter } from "vue-router";
const route = useRoute();
const { params } = route;
const { width } = useWindowSize();

/**
* 响应式布局容器固定宽度
*
* 大屏(>=1200px)
* 中屏(>=992px)
* 小屏(>=768px)
*/
const WIDTH = 992;

const appStore = useAppStore();
const settingsStore = useSettingsStore();

const fixedHeader = computed(() => settingsStore.fixedHeader);
const showTagsView = computed(() => settingsStore.tagsView);
const showSettings = computed(() => settingsStore.showSettings);

const classObj = computed(() => ({
hideSidebar: !appStore.sidebar.opened,
openSidebar: appStore.sidebar.opened,
withoutAnimation: appStore.sidebar.withoutAnimation,
mobile: appStore.device === "mobile",
}));

watchEffect(() => {
if (width.value < WIDTH) {
appStore.toggleDevice("mobile");
appStore.closeSideBar(true);
} else {
appStore.toggleDevice("desktop");

if (width.value >= 1200) {
//大屏
appStore.openSideBar(true);
} else {
appStore.closeSideBar(true);
}
}
});

function handleOutsideClick() {
appStore.closeSideBar(false);
}

onMounted(() => {});
</script>

<style lang="scss" scoped>
.app-wrapper {
&::after {
display: table;
clear: both;
content: "";
}

position: relative;
width: 100%;
height: 100%;
e &.mobile.openSidebar {
position: fixed;
top: 0;
}
}

.fixed-header {
position: fixed;
top: 0;
right: 0;
z-index: 9;
width: calc(100% - #{$sideBarWidth});
transition: width 0.28s;
}

.hideSidebar .fixed-header {
width: calc(100% - 54px);
}

.mobile .fixed-header {
width: 100%;
}

.drawer-bg {
position: absolute;
top: 0;
z-index: 999;
width: 100%;
height: 100%;
background: #000;
opacity: 0.3;
}
</style>

+ 232
- 73
src/layout/index.vue Zobrazit soubor

@@ -1,27 +1,101 @@
<template>
<div :class="classObj" class="app-wrapper">
<!-- 手机设备侧边栏打开遮罩层 -->
<div
v-if="classObj.mobile && classObj.openSidebar"
class="drawer-bg"
@click="handleOutsideClick"
></div>

<Sidebar class="sidebar-container" />

<div :class="{ hasTagsView: showTagsView }" class="main-container">
<div :class="{ 'fixed-header': fixedHeader }">
<navbar />
<tags-view v-if="showTagsView" />
<div class="app-wrapper">
<!-- 侧边栏 -->
<div class="Sidebar">
<div class="imgBox">
<img
class="boxCentreImg"
src="../assets//img/left-top-logo.png"
alt=""
/>
</div>
<!-- 侧边路由列表 -->
<div class="myRouter">
<!-- 创建视频页 -->
<div class="myRouter-item" @click="router.push('/createVideo')">
<div class="icon">
<el-icon><i-ep-edit /></el-icon>
</div>
{{ $t("createVideo.title") }}
</div>
<!-- 我的视频 -->
<div class="myRouter-item" @click="router.push('/myCreating')">
<div class="icon">
<el-icon><i-ep-menu /></el-icon>
</div>
{{ $t("myCreating.title") }}
</div>
<!-- 测试功能页 -->
<div
v-if="false"
class="myRouter-item"
@click="router.push('/moveImg')"
>
<div class="icon">
<el-icon><i-ep-edit /></el-icon>
</div>
{{ $t("createVideo.title") }}
</div>
<!-- 商店 -->
<div class="myRouter-item pricing" @click="router.push('/myStore')">
<div class="icon">
<el-icon><i-ep-Goods /></el-icon>
</div>
{{ $t("shop.title") }}
</div>
<!-- api -->
<div class="myRouter-item API" @click="router.push('/APIAccess')">
<div class="icon">
<el-icon><i-ep-DocumentAdd /></el-icon>
</div>
{{ $t("API.title") }}
</div>
</div>
</div>
<!-- 右边显示部分 -->
<div class="rightBox">
<!-- nav栏 -->
<div class="nav">
<!-- 路由名字 -->
<div style="position: absolute; left: 30px; font-size: 26px">
{{ $t(routeName as string) }}
</div>
<!-- 语言 -->
<!--语言选择-->
<el-tooltip
style="cursor: pointer; z-index: 999"
class="box-item"
effect="dark"
:content="$t('navbar.LanguageChange')"
placement="top-start"
>
<lang-select class="navItem" style="color: #ffffff" />
</el-tooltip>
<!-- 账户 -->
<div
class="navItem"
v-if="AccessToken"
@click="router.push('myAccount')"
>
{{ $t("navbar.account") }}
</div>
<!-- 登录 -->
<div class="navItem" v-if="!AccessToken" @click="router.push('login')">
{{ $t("navbar.goLogin") }}
</div>

<!--主页面-->
<app-main />

<!-- 设置面板 -->
<RightPanel v-if="showSettings">
<settings />
</RightPanel>
<!-- 注销 -->
<div
class="navItem"
v-if="AccessToken"
@click="logout"
style="margin-left: 10px"
>
{{ $t("navbar.logout") }}
</div>
</div>
<!-- 主页面 -->
<app-main style="background-color: #000" />
</div>
</div>
</template>
@@ -29,18 +103,42 @@
<script setup lang="ts">
import { computed, watchEffect } from "vue";
import { useWindowSize } from "@vueuse/core";
import { AppMain, Navbar, Settings, TagsView } from "./components/index";
import SignSucceed from "../views/signSucceed/index.vue";
import Sidebar from "./components/Sidebar/index.vue";
import RightPanel from "@/components/RightPanel/index.vue";
import { AppMain, Navbar } from "./components/index";

import LangSelect from "@/components/LangSelect/index.vue";
import { useAppStore } from "@/store/modules/app";
import { useSettingsStore } from "@/store/modules/settings";
// import { useSettingsStore } from "@/store/modules/settings";
import { useRoute, useRouter } from "vue-router";
import { useI18n } from "vue-i18n";

import { userInfoModules } from "@/store/modules/userInfo";

const userInfoPinia = userInfoModules();
const route = useRoute();
const router = useRouter();
const { params } = route;
const { width } = useWindowSize();

const AccessToken = localStorage.getItem("AccessToken");
// 当前语言状态与国际化组件
const { locale } = useI18n();
const lanChange = ref(locale);
function logout() {
const msg =
(lanChange.value as string) == "zh-cn"
? "确定退出登录吗?"
: "Are you sure to log out?";
const notice = (lanChange.value as string) == "zh-cn" ? "提示" : "Notice";
const confirm = (lanChange.value as string) == "zh-cn" ? "确定" : "Confirm";
const cancel = (lanChange.value as string) == "zh-cn" ? "取消" : "Cancel";
ElMessageBox.confirm(msg, notice, {
confirmButtonText: confirm,
cancelButtonText: cancel,
}).then(() => {
userInfoPinia.loginOut();
router.push(`/login`);
localStorage.removeItem("AccessToken");
});
}
/**
* 响应式布局容器固定宽度
*
@@ -51,18 +149,7 @@ const { width } = useWindowSize();
const WIDTH = 992;

const appStore = useAppStore();
const settingsStore = useSettingsStore();

const fixedHeader = computed(() => settingsStore.fixedHeader);
const showTagsView = computed(() => settingsStore.tagsView);
const showSettings = computed(() => settingsStore.showSettings);

const classObj = computed(() => ({
hideSidebar: !appStore.sidebar.opened,
openSidebar: appStore.sidebar.opened,
withoutAnimation: appStore.sidebar.withoutAnimation,
mobile: appStore.device === "mobile",
}));
// const settingsStore = useSettingsStore();

watchEffect(() => {
if (width.value < WIDTH) {
@@ -79,6 +166,13 @@ watchEffect(() => {
}
}
});
const routeName = ref(route.meta.name);
watch(
() => route.meta.name,
(newName) => {
routeName.value = newName;
}
);

function handleOutsideClick() {
appStore.closeSideBar(false);
@@ -87,47 +181,112 @@ function handleOutsideClick() {
onMounted(() => {});
</script>

<!-- 新样式 -->
<style lang="scss" scoped>
.app-wrapper {
&::after {
display: table;
clear: both;
content: "";
width: 1920px;
display: flex;
}
.Sidebar {
width: 230px;
background-color: #000;
height: 100vh;
color: #fff;
.imgBox {
width: 100%;
height: 80px;
position: relative;
img {
max-width: 80%;
max-height: 80%;
}
}
.myRouter {
position: relative;
height: calc(100% - 80px);
padding: 200px 20px 0;
color: #fff;
// color: #868593;

position: relative;
width: 100%;
height: 100%;
e &.mobile.openSidebar {
position: fixed;
top: 0;
}
}
&-item {
display: flex;
width: 100%;
height: 50px;
padding-left: 10px;
font-size: 20px;
font-weight: 500;
line-height: 50px;
text-align: center;
cursor: pointer;
// border-bottom: 2px solid #fff;
transition: all 0.3s;
border-radius: 5px;
margin-bottom: 20px;
margin-right: 20px;
border-bottom: 2px solid #fff;
.icon {
width: 40px;
height: 40px;
color: #fff;
border-radius: 50%;

.fixed-header {
position: fixed;
top: 0;
right: 0;
z-index: 9;
width: calc(100% - #{$sideBarWidth});
transition: width 0.28s;
}
.el-icon {
width: 25px;
height: 25px;
font-size: 25px;
// color: #797a9f;
color: #fff;
text-align: center;
vertical-align: sub;
}
}

.hideSidebar .fixed-header {
width: calc(100% - 54px);
}
&:hover {
// background: rgba(255, 255, 255, 0.2);
color: #000;
background: #fff;
.el-icon {
// color: #d4d0ff;
color: #000;
}
}
}

.mobile .fixed-header {
width: 100%;
.pricing {
position: absolute;
bottom: 80px;
width: calc(100% - 40px);
text-align: center;
}
.API {
position: absolute;
bottom: 20px;
width: calc(100% - 40px);
text-align: center;
}
}
}

.drawer-bg {
position: absolute;
top: 0;
z-index: 999;
width: 100%;
height: 100%;
background: #000;
opacity: 0.3;
.rightBox {
width: 1690px;
// background-color: #000;
.nav {
position: relative;
display: flex;
justify-content: flex-end;
align-items: center;
margin-right: 20px;
width: 100%;
height: 80px;
background-color: #000;
padding: 30px;
// padding: 30px 30px 0 1500px;
color: #fff;
.navItem {
font-size: 16px;
margin-right: 30px;
color: #fff;
cursor: pointer;
}
}
}
</style>

+ 19
- 0
src/router/index.ts Zobrazit soubor

@@ -123,6 +123,25 @@ export const constantRoutes: RouteRecordRaw[] = [
},
],
},
// 测试页面
{
path: "/",
component: Layout,
redirect: "/moveImg",
children: [
{
path: "moveImg",
component: () => import("@/views/moveImg/index.vue"),
name: "moveImg",
meta: {
title: "moveImg",
icon: "homepage",
affix: true,
name: "moveImg.title",
},
},
],
},
// {
// path: "/dashboard",
// component: Layout,


+ 7
- 0
src/styles/my.scss Zobrazit soubor

@@ -3,6 +3,13 @@ body {
// font-size: 14px;
}

.boxCentreImg {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}

.inmiddle {
position: absolute;
// top: 50%;


+ 55
- 28
src/views/createVideo/index.vue Zobrazit soubor

@@ -1,7 +1,7 @@
<template>
<div class="page flex justify-around">
<!-- 左侧栏 -->
<div class="left scrolly">
<div class="left ">
<!-- 顶部 -->
<!-- 选中AiFace -->
<div class="left-top" v-show="showUploadBtn == 1">
@@ -24,6 +24,11 @@
<div class="bigImg inmiddle">
<img :src="imgUrl" alt="" class="inmiddle" />
</div>
<!-- 字幕开关 -->
<div v-if="imgUrl" class="SubtitlesSwitch">
<p>{{ $t('createVideo.subtitles') }}</p>
<el-switch v-model="SubtitlesSwitch" />
</div>
</div>
<!-- 选中需要上传的图片前 -->
<div class="left-top" v-show="showUploadBtn == 2">
@@ -151,6 +156,7 @@
v-if="showFace == 0"
v-infinite-scroll="loadMoreAiFaceSystem"
:infinite-scroll-disabled="overLoadSystem"
infinite-scroll-distance="10"
>
<!-- 上传图片组件 -->
<div v-if="showFace == 1" class="faceItem" @click="clickAddBtn">
@@ -177,6 +183,7 @@
v-if="showFace == 1"
v-infinite-scroll="loadMoreAiFaceUser"
:infinite-scroll-disabled="overLoadUser"
infinite-scroll-distance="10"
>
<!-- 上传图片组件 -->
<div v-if="showFace == 1" class="faceItem" @click="clickAddBtn">
@@ -207,8 +214,7 @@
<div
class="Aipicture"
v-if="showFace == 2"
v-infinite-scroll="loadMoreAiFaceUser"
:infinite-scroll-disabled="overLoadUser"

>
<div class="title">
<el-icon><i-ep-Lock /></el-icon>
@@ -747,7 +753,7 @@ const AiFaceList = ref([]); //系统相册列表
const userAiFaceList = ref([]); //个人相册列表
const feceItemLoading = ref(false);
const feceItemLoading2 = ref(false);
const pageSize = ref(30); //加载页数
function getAiFaceList(pageNum, pageSize, sendType) {
feceItemLoading.value = true;
personPhotoList(pageNum, pageSize, sendType)
@@ -779,7 +785,7 @@ const overLoadUser = ref(false); //禁用个人相册加载更多
//系统相册触底加载更多
function loadMoreAiFaceSystem() {
pageNumSystem.value += 1;
personPhotoList(pageNumSystem.value, 20, 1)
personPhotoList(pageNumSystem.value, pageSize.value, 1)
.then((res) => {
AiFaceList.value.push(...res.data.list);
if (res.data.list.length == 0) {
@@ -793,8 +799,9 @@ function loadMoreAiFaceSystem() {
}
//个人相册触底加载更多
function loadMoreAiFaceUser() {
console.log(12333212311);
pageNumUser.value += 1;
personPhotoUserListList(pageNumUser.value, 20, 3)
personPhotoUserListList(pageNumUser.value, pageSize.value, 3)
.then((res) => {
if (res.data.list.length == 0) {
overLoadUser.value = true;
@@ -837,7 +844,7 @@ async function deleteFaceImg(id) {
imgUrl.value = null;
faceItemActive.value = null;
userAiFaceList.value = [];
getAiFaceUserList(1, 10, 3);
getAiFaceUserList(1, pageSize.value, 3);
pageNumUser.value = 1;
overLoadUser.value = false;
} catch (error) {
@@ -953,7 +960,7 @@ async function changeFile() {
compressionImgLoad.value = false;
showUploadBtn.value = 4;
userAiFaceList.value = [];
getAiFaceUserList(1, 10, 3);
getAiFaceUserList(1, pageSize.value, 3);
pageNumUser.value = 1;
overLoadUser.value = false;
faceItemActive.value = res2.data.id;
@@ -1903,6 +1910,10 @@ function copyAnswerContent() {
}
//#endregion ----------------------------

//#region 字幕部分
const SubtitlesSwitch=ref(false) //字幕开关
//#endregion ----------------------------

//#region

//#endregion ----------------------------
@@ -1920,9 +1931,9 @@ const t = globalProperties.$t(string);

//#region 页面初始化
onMounted(async () => {
getAiFaceList(1, 20, 1);
getAiFaceList(1, pageSize.value, 1);
if (AccessToken) {
getAiFaceUserList(1, 20, 3);
getAiFaceUserList(1, pageSize.value, 3);
await getmusicListPerson(
musicListPageNumPerson.value,
musicListPageSize.value
@@ -1963,7 +1974,6 @@ onUnmounted(() => {
<style lang="scss" scoped>
.page {
// height: 1000px;
height: 1000px;
height: calc(100vh - 80px);
// padding: 20px 0 0 40px;
background-color: #fff;
@@ -1971,13 +1981,15 @@ onUnmounted(() => {
}

.left {

width: 68%;
// height: 860px;
height: 1000px;
max-height: 100%;
// height: 1000px;
// max-height: 100%;
padding: 20px;
overflow: hidden;
overflow-y: scroll;
// overflow-y: scroll;
height: 100%;
:deep(.el-input__wrapper) {
border: none;
border-bottom: 2px solid #000;
@@ -1985,6 +1997,7 @@ onUnmounted(() => {
box-shadow: none;
}


.el-icon.icon-edit {
width: 35px;
height: 35px;
@@ -1998,8 +2011,10 @@ onUnmounted(() => {
width: 100%;
// height: 65%;
// height: 580px;
height: 65%;

height: 67%;
// height: calc(70vh - 80px );
z-index: 9999;
margin-bottom: 10px;
.uploadBtn {
position: relative;
padding: 10px 15px;
@@ -2205,12 +2220,22 @@ onUnmounted(() => {
}
}
}
.SubtitlesSwitch {
position: absolute;
right: 0;
top: 0px;
padding: 10px;
border-radius: 20px;
background-color: #f1f2f6;
text-align: center;
}
}

&-bottom {
width: 100%;
height: 32%;
margin-top: 10px;
height: 30%;
// height: calc(30vh - 80px );
// margin-top: 10px;
.tab {
padding: 10px;
> div {
@@ -2238,16 +2263,17 @@ onUnmounted(() => {
flex-wrap: wrap;
justify-content: flex-start;
width: 100%;
height: 220px;
// height: 220px;
height: 90%;
overflow-y: scroll;
.faceItem {
position: relative;
margin-right: 30px;
margin-bottom: 35px;
width: 150px;
height: 150px;
width: 100px;
height: 100px;
// padding: 0 25px;
line-height: 150px;
line-height: 100px;
text-align: center;
border-radius: 50%;
background-color: #fbf8f8;
@@ -2263,8 +2289,8 @@ onUnmounted(() => {
right: 0;
bottom: 0;
z-index: 3;
width: 150px;
height: 150px;
width: 100px;
height: 100px;
border-radius: 50%;
background-color: #fbf8f8;
overflow: hidden;
@@ -2279,7 +2305,7 @@ onUnmounted(() => {
.deleteIcon {
position: absolute;
top: 0;
right: 15px;
right: -5px;
z-index: 999;
width: 25px;
height: 25px;
@@ -2291,7 +2317,7 @@ onUnmounted(() => {
cursor: pointer;
}
.uploadImg {
line-height: 145px;
line-height: 100px;
font-size: 50px;
font-weight: 700;
text-align: center;
@@ -2413,8 +2439,8 @@ onUnmounted(() => {
.right {
width: 32%;
// height: 860px;
height: 1000px;
max-height: 100%;
// height: 1000px;
// max-height: 100%;
padding: 30px 30px 20px 30px;
background-color: #f1f2f6;
border-radius: 30px 0 0 0;
@@ -2422,6 +2448,7 @@ onUnmounted(() => {
z-index: 2;
overflow: hidden;
overflow-y: scroll;
height: 100%;
.subscript {
position: absolute;
top: 30px;


+ 131
- 0
src/views/moveImg/index.vue Zobrazit soubor

@@ -0,0 +1,131 @@
<template>
<div class="page">
<div class="canvasBox">
<canvas class="canvas" id="canvas" width="960" height="540">
<!-- 背景图 -->
<!-- <div class="bjImg">
<img src="../../assets/img/lake.jpg" alt="" />
</div> -->
<!-- 数字人 -->
<!-- <div class="people"></div> -->
<!-- 素材 -->
<!-- <div class="other"></div> -->
</canvas>
<img
style="display: none; width: 200px; height: 200px"
id="bjImg"
src="../../assets/img/star.png"
alt=""
/>
</div>
<div class="container">
<div class="box red"></div>
<div class="box white"></div>
<div class="box green"></div>
</div>
</div>
</template>

<script setup>
//#region 导入
import { fabric } from "fabric";

//#endregion ---------------------------

//#region 画布交互
let canvas = new fabric.Canvas("canvas");

//#endregion ---------------------------

onMounted(() => {
let canvas = new fabric.Canvas("canvas");
let imgElement = document.getElementById("bjImg"); //声明我们的图片
let imgInstance = new fabric.Image(imgElement, {
//设置图片位置和样子
// left: 100,
// top: 100,
// width: 400,
// height: 200,
// angle: 30, //设置图形顺时针旋转角度
});
console.log(imgInstance);
canvas.add(imgInstance);
// canvas.on("mouse:up", function (options) {
// console.log(options.e.clientX, options.e.clientY);
// });
});
</script>

<style lang="scss" scoped>
.page {
position: relative;
padding: 10px;
}
.canvasBox {
// position: absolute;
// top: 50%;
// left: 50%;
// transform: translate(-50%);
width: 100%;
height: 100%;
.canvas-container {
}
background-color: green;
.canvas {
background-color: skyblue;
.bjImg {
position: absolute;
top: 0;
left: 0;
width: 100px;
height: 100px;
z-index: 999;
img {
width: 100px;
height: 100px;
}
}
.people {
}
.other {
}
}
}
</style>

<style lang="scss" scoped>
.container {
display: flex;
align-items: center;
justify-content: space-between;
width: 80px;
height: 20px;
perspective: 500px;
transition: transform 0.5s;
}

.box {
width: 20px;
height: 20px;
transition: transform 0.5s;
transform-style: preserve-3d;
}

.red {
background-color: red;
}

.white {
background-color: white;
transform: translateZ(20px);
}

.green {
background-color: green;
transform: translateZ(-20px);
}

.container:hover .box {
transform: rotateY(180deg);
}
</style>

+ 16
- 0
src/views/moveImg/videoStatus.js Zobrazit soubor

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

Načítá se…
Zrušit
Uložit