congzc 2 anni fa
parent
commit
7bc825ecc5
13 ha cambiato i file con 7352 aggiunte e 34 eliminazioni
  1. +1
    -0
      package.json
  2. +22
    -0
      src/apis/createVideo.js
  3. +2
    -1
      src/lang/package/en.ts
  4. +3
    -2
      src/lang/package/zh-cn.ts
  5. +1
    -0
      src/layout/components/Sidebar/Logo.vue
  6. +1
    -1
      src/layout/components/Sidebar/index.vue
  7. +1
    -1
      src/layout/index.vue
  8. +2
    -0
      src/types/components.d.ts
  9. +510
    -0
      src/views/createVideo/index copy.vue
  10. +331
    -29
      src/views/createVideo/index.vue
  11. +3
    -0
      vite.config.ts
  12. +6470
    -0
      yarn-error.log
  13. +5
    -0
      yarn.lock

+ 1
- 0
package.json Vedi File

@@ -20,6 +20,7 @@
"axios": "^1.3.4", "axios": "^1.3.4",
"echarts": "^5.2.2", "echarts": "^5.2.2",
"element-plus": "^2.3.1", "element-plus": "^2.3.1",
"js-audio-recorder": "^1.0.7",
"nprogress": "^0.2.0", "nprogress": "^0.2.0",
"path-browserify": "^1.0.1", "path-browserify": "^1.0.1",
"path-to-regexp": "^6.2.0", "path-to-regexp": "^6.2.0",


+ 22
- 0
src/apis/createVideo.js Vedi File

@@ -0,0 +1,22 @@
import request from "@/utils/request.js";

/**
* @description 上传图片
* @params ticket
* @returns data
*/
export function awsImgUpload(formData) {
return request({
url: `/api/upload/awsImgUpload`,
method: 'post',
data: formData
})
}

export function awsMp3Upload(formData) {
return request({
url: `/api/upload/awsImgUpload`,
method: 'post',
data: formData
})
}

+ 2
- 1
src/lang/package/en.ts Vedi File

@@ -40,7 +40,8 @@ export default {
languages: "Languages", languages: "Languages",
voices: "Voices", voices: "Voices",
styles: "Styles", styles: "Styles",
reload: "Reload",
reselect: "reselect",
sureUpload:'Confirm upload',
generateVideo: "Generate Video", generateVideo: "Generate Video",
}, },




+ 3
- 2
src/lang/package/zh-cn.ts Vedi File

@@ -32,7 +32,7 @@ export default {
createVideo: { createVideo: {
title: "创作视频", title: "创作视频",
typeScript: "输入文案", typeScript: "输入文案",
uploadAudio: "上传频",
uploadAudio: "上传频",
aiScript: "AI生成文本", aiScript: "AI生成文本",
typeTitle: "输入标题", typeTitle: "输入标题",
confirm: "确定", confirm: "确定",
@@ -40,7 +40,8 @@ export default {
languages: "选择语言", languages: "选择语言",
voices: "选择声音", voices: "选择声音",
styles: "选择风格", styles: "选择风格",
reload: "重新上传",
reselect: "重新选择",
sureUpload:'确认上传',
generateVideo: "生成视频", generateVideo: "生成视频",
}, },




+ 1
- 0
src/layout/components/Sidebar/Logo.vue Vedi File

@@ -55,6 +55,7 @@ const logo = ref(new URL(`../../../assets/logo.png`, import.meta.url).href);
// https://cn.vuejs.org/guide/built-ins/transition.html#the-transition-component // https://cn.vuejs.org/guide/built-ins/transition.html#the-transition-component


.left-top-box { .left-top-box {
height: 80px;
background-color: #000; background-color: #000;
} }




+ 1
- 1
src/layout/components/Sidebar/index.vue Vedi File

@@ -76,7 +76,7 @@ function routerTo(url: RouteLocationRaw) {
<style lang="scss" scoped> <style lang="scss" scoped>
.myRouter { .myRouter {
position: relative; position: relative;
height: calc(100% - 50px);
height: calc(100% - 80px);
padding: 200px 20px 0; padding: 200px 20px 0;
color: #fff; color: #fff;




+ 1
- 1
src/layout/index.vue Vedi File

@@ -18,7 +18,7 @@
<!--主页面--> <!--主页面-->
<app-main /> <app-main />


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


+ 2
- 0
src/types/components.d.ts Vedi File

@@ -21,6 +21,7 @@ declare module '@vue/runtime-core' {
ElIcon: typeof import('element-plus/es')['ElIcon'] ElIcon: typeof import('element-plus/es')['ElIcon']
ElInput: typeof import('element-plus/es')['ElInput'] ElInput: typeof import('element-plus/es')['ElInput']
ElOption: typeof import('element-plus/es')['ElOption'] ElOption: typeof import('element-plus/es')['ElOption']
ElProgress: typeof import('element-plus/es')['ElProgress']
ElRow: typeof import('element-plus/es')['ElRow'] ElRow: typeof import('element-plus/es')['ElRow']
ElScrollbar: typeof import('element-plus/es')['ElScrollbar'] ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
ElSelect: typeof import('element-plus/es')['ElSelect'] ElSelect: typeof import('element-plus/es')['ElSelect']
@@ -28,6 +29,7 @@ declare module '@vue/runtime-core' {
ElTabPane: typeof import('element-plus/es')['ElTabPane'] ElTabPane: typeof import('element-plus/es')['ElTabPane']
ElTabs: typeof import('element-plus/es')['ElTabs'] ElTabs: typeof import('element-plus/es')['ElTabs']
ElTooltip: typeof import('element-plus/es')['ElTooltip'] ElTooltip: typeof import('element-plus/es')['ElTooltip']
ElUpload: typeof import('element-plus/es')['ElUpload']
GithubCorner: typeof import('./../components/GithubCorner/index.vue')['default'] GithubCorner: typeof import('./../components/GithubCorner/index.vue')['default']
Hamburger: typeof import('./../components/Hamburger/index.vue')['default'] Hamburger: typeof import('./../components/Hamburger/index.vue')['default']
IconSelect: typeof import('./../components/IconSelect/index.vue')['default'] IconSelect: typeof import('./../components/IconSelect/index.vue')['default']


+ 510
- 0
src/views/createVideo/index copy.vue Vedi File

@@ -0,0 +1,510 @@
<template>
<div class="page flex justify-around">
<!-- 左侧栏 -->
<div class="left">
<!-- 顶部 -->
<!-- 有图片时 -->
<div class="left-top" v-show="imgUrl">
<el-row class="justify-between">
<!-- title框 -->
<div class="flex justify-between" style="width: 300px">
<el-input
v-model="title"
:placeholder="$t('createVideo.typeTitle')"
/>
<el-icon class="icon-edit"><i-ep-edit /></el-icon>
</div>
<!-- 上传按钮 -->
<button class="uploadBtn">
{{ $t("createVideo.reload") }}
<input type="file" @change="changeFile" />
</button>
</el-row>
<!-- 中间展示大图 -->
<div class="bigImg inmiddle">
<img :src="imgUrl" alt="" class="inmiddle" />
</div>
</div>
<!-- 没有图片时 -->
<div class="left-top" v-show="!imgUrl">
<!-- 中间展示大图 -->
<div class="noImg">
<div class="trueImg inmiddle">
<div class="icon">✔</div>
</div>
<div class="upload inmiddle">
+
<input type="file" @change="changeFile" />
</div>
<div class="falseImg inmiddle">
<div><div class="icon">×</div></div>
<div><div class="icon">×</div></div>
<div><div class="icon">×</div></div>
</div>
</div>
</div>

<!-- 底部 -->
<div class="left-bottom">
<div class="ai">
<div class="aiAvatar"></div>
<div style="margin-left: 20px">Generate By Ai</div>
</div>
<div class="faceList scrolly">
<div class="faceItem" v-for="item in 7" :key="item">
<div class="img"></div>
<!-- <img src="" alt="" /> -->
<p>{{ item }}name</p>
</div>
</div>
</div>
</div>
<!-- 右侧栏 -->
<div class="right">
<el-tabs type="border-card" class="tabs">
<!-- ----------------------------- 1 -->
<el-tab-pane :label="$t('createVideo.typeScript')">
<div class="card1">111111111111111111</div>
</el-tab-pane>
<!-- ------------------------ 2 -->
<el-tab-pane :label="$t('createVideo.uploadAudio')">
<div class="card2">
<!-- 录制MP3上传语音 -->
<div class="uploadAudio">
<button @click="startRecording">开始录音</button>
<button @click="stopRecording">停止录音</button>
<button @click="playRecording">播放录音</button>
<audio v-if="audioUrl" controls :src="audioUrl"></audio>
<button v-if="audioUrl" @click="uploadAudio">上传音频</button>
</div>
<!-- 上传视频 -->
<div class="uploadVideo">
<input type="file" ref="fileInput" @change="handleFileChange" />
<video
v-if="videoSrc"
:src="videoSrc"
ref="videoPlayer"
controls
></video>
</div>
</div>
</el-tab-pane>
<!-- ----------------------- 3 -->
<el-tab-pane :label="$t('createVideo.aiScript')">
<div class="card3">
<div class="text">
<el-input
v-model="title"
:placeholder="$t('createVideo.typeTitle')"
/>
<el-button type="primary">
{{ $t("createVideo.confirm") }}
</el-button>
<el-input
v-model="title"
:rows="15"
type="textarea"
:placeholder="$t('createVideo.aiText')"
/>
<el-icon :size="20">
<Edit />
</el-icon>
</div>
<p>{{ $t("createVideo.languages") }}</p>
<el-select
v-model="language"
placeholder="Select"
style="width: 100%"
>
<el-option
v-for="item in languageOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<p>{{ $t("createVideo.voices") }}</p>
<el-select
v-model="language"
placeholder="Select"
style="width: 100%"
>
<el-option
v-for="item in languageOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<p>{{ $t("createVideo.styles") }}</p>
<el-select
v-model="language"
placeholder="Select"
style="width: 100%"
>
<el-option
v-for="item in languageOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<el-button type="primary">{{
$t("createVideo.generateVideo")
}}</el-button>
</div>
</el-tab-pane>
</el-tabs>
</div>
</div>
</template>
<script setup>
import { ref } from "vue";
import { getCurrentInstance } from "vue";
import Recorder from "js-audio-recorder";
// 标题
let title = ref("");
// 上传图片
let imgUrl = ref("");
function changeFile(e) {
imgUrl.value = URL.createObjectURL(e.target.files[0]);
}

// $t在script中的使用

const {
appContext: {
config: { globalProperties },
},
} = getCurrentInstance();

const string = "createVideo.typeScript";
const t = globalProperties.$t(string);
// 录制MP3上传语音

const parameter = {
sampleBits: 16, // 采样位数,支持 8 或 16,默认是16
sampleRate: 8000, // 采样率,支持 11025、16000、22050、24000、44100、48000,根据浏览器默认值,我的chrome是48000
numChannels: 1, // 声道,支持 1 或 2, 默认是1
};
const recorder = new Recorder(parameter);
const isRecording = ref(false);
const audioUrl = ref(null);

const startRecording = async () => {
if (!isRecording.value) {
try {
await recorder.start();
console.log("Recording started");
isRecording.value = true;
} catch (error) {
console.error(error);
}
}
};

const stopRecording = async () => {
if (isRecording.value) {
try {
const recording = await recorder.stop();
audioUrl.value = URL.createObjectURL(recorder.getWAVBlob());
isRecording.value = false;
} catch (error) {
console.error(error);
}
}
};

const playRecording = () => {
if (audioUrl.value) {
const audio = new Audio(audioUrl.value);
audio.play();
}
};
const uploadAudio = () => {};

// 上传视频功能
const fileInput = ref(null);
const videoSrc = ref(null);
const handleFileChange = () => {
const file = fileInput.value.files[0];
if (file) {
const videoUrl = URL.createObjectURL(file);
videoSrc.value = videoUrl;
}
};

// card3的
let language = ref("");

let languageOptions = reactive([
{
value: "Option1",
label: "Option1",
},
{
value: "Option2",
label: "Option2",
},
]);
</script>

<style lang="scss" scoped>
.page {
// height: calc(100vh - 84px);
height: 887px;
padding: 20px 0 0 40px;
background-color: #fff;
border-radius: 25px 0 0;
}

.left {
width: 70%;
height: 100%;

:deep(.el-input__wrapper) {
border: none;
border-bottom: 2px solid #000;
border-radius: 0;
box-shadow: none;
}

.el-icon.icon-edit {
width: 35px;
height: 35px;
font-size: 35px;
color: #8c939d;
text-align: center;
}

&-top {
position: relative;
width: 100%;
height: 65%;

.uploadBtn {
position: relative;
}

.bigImg {
display: flex;
align-items: center;
justify-content: space-between;
width: 80%;
height: 88%;
margin-top: 20px;

img {
max-width: 100%;
max-height: 100%;
}
}

.noImg {
position: relative;
width: 100%;
height: 100%;
border: 1px solid #000;

.trueImg {
top: 60px;
width: 100px;
height: 100px;
background-color: green;
border-radius: 50%;
}

.upload {
top: 200px;
width: 100px;
height: 100px;
font-size: 50px;
line-height: 100px;
text-align: center;
background-color: pink;
border-radius: 50%;
}

.falseImg {
top: 350px;
// background-color: #795562;
display: flex;
justify-content: space-evenly;
width: 500px;
height: 100px;

> div {
position: relative;
width: 100px;
height: 100px;
background-color: #ccc;
border-radius: 50%;
}
}
}

// 公共类名
input {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0;
}

.icon {
position: absolute;
right: 2px;
width: 30px;
height: 30px;
font-size: 20px;
font-weight: 700;
line-height: 26px;
text-align: center;
border: 2px solid #000;
border-radius: 50%;
}
}

&-bottom {
width: 100%;
height: 32%;
margin-top: 10px;

.ai {
width: 100%;

.aiAvatar {
width: 100px;
height: 100px;
margin-left: 25px;
background-color: pink;
border-radius: 50%;
}
}

.faceList {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
width: 100%;
height: 130px;

.faceItem {
width: 150px;
height: 150px;
padding: 0 25px;
line-height: 30px;
text-align: center;

p {
height: 30px;
}

.img {
width: 100px;
height: 100px;
background-color: green;
border-radius: 50%;
}
}
}
}
}

.right {
width: 25%;
height: 100%;
background-color: green;

:deep(.el-tabs--border-card) {
font-size: 20px;
border: none;
}

.tabs {
height: 100%;
.card2 {
padding: 10px;
> div {
position: relative;
margin-top: 10px;
width: 100%;
height: 100px;
border-radius: 10px;
background-color: red;
overflow: hidden;
transition: all 0.3s;
&:hover {
transform: translateY(-10px);
box-shadow: #00000026 2px 2px 2px 2px;
}
}
.uploadAudio {
margin-bottom: 20px;
}
.uploadVideo {
input {
position: absolute;
width: 100%;
height: 100%;
opacity: 0;
}
video {
width: 100%;
height: 100%;
}
}
}
.card3 {
.text {
padding: 10px;
border: 1px solid #000;

.el-button {
float: right;
margin-top: 10px;
}

:deep(.el-textarea__inner) {
resize: none;
box-shadow: none;
}
}

p {
margin: 10px 0;
}

> .el-button {
width: 100%;
height: 50px;
margin-top: 10px;
}
}

:deep(.el-tabs__item.is-active) {
color: #909393;
background-color: #000;
}

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

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

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

:deep(.el-tabs__content) {
height: calc(100% - 60px);
padding: 0;
}
}
}
</style>

+ 331
- 29
src/views/createVideo/index.vue Vedi File

@@ -15,10 +15,15 @@
<el-icon class="icon-edit"><i-ep-edit /></el-icon> <el-icon class="icon-edit"><i-ep-edit /></el-icon>
</div> </div>
<!-- 上传按钮 --> <!-- 上传按钮 -->
<button class="uploadBtn">
{{ $t("createVideo.reload") }}
<input type="file" @change="changeFile" />
</button>
<div class="btnBox">
<button class="uploadBtn">
{{ $t("createVideo.reselect") }}
<input type="file" @change="lookImg" />
</button>
<button class="uploadBtn" @click="changeFile">
{{ $t("createVideo.sureUpload") }}
</button>
</div>
</el-row> </el-row>
<!-- 中间展示大图 --> <!-- 中间展示大图 -->
<div class="bigImg inmiddle"> <div class="bigImg inmiddle">
@@ -34,7 +39,17 @@
</div> </div>
<div class="upload inmiddle"> <div class="upload inmiddle">
+ +
<input type="file" @change="changeFile" />
<input type="file" @change="lookImg" />
<!-- <el-upload
class="el-upload"
v-model="fileList"
multiple
:on-preview="handlePreview"
:on-remove="handleRemove"
:before-remove="beforeRemove"
:limit="3"
:on-exceed="handleExceed"
/> -->
</div> </div>
<div class="falseImg inmiddle"> <div class="falseImg inmiddle">
<div><div class="icon">×</div></div> <div><div class="icon">×</div></div>
@@ -51,10 +66,15 @@
<div style="margin-left: 20px">Generate By Ai</div> <div style="margin-left: 20px">Generate By Ai</div>
</div> </div>
<div class="faceList scrolly"> <div class="faceList scrolly">
<div class="faceItem" v-for="item in 7" :key="item">
<div class="img"></div>
<!-- <img src="" alt="" /> -->
<p>{{ item }}name</p>
<div
class="faceItem pointer"
@click="setImgUrl(item.material)"
v-for="item in AiFace"
:key="item.id"
>
<!-- <div class="img"></div> -->
<img :src="item.material" alt="" />
<p>{{ item.title }}</p>
</div> </div>
</div> </div>
</div> </div>
@@ -64,19 +84,117 @@
<el-tabs type="border-card" class="tabs"> <el-tabs type="border-card" class="tabs">
<!-- ----------------------------- 1 --> <!-- ----------------------------- 1 -->
<el-tab-pane :label="$t('createVideo.typeScript')"> <el-tab-pane :label="$t('createVideo.typeScript')">
<div class="card1">111111111111111111</div>
<div class="card1">
<div class="text">
<el-input
v-model="title"
:placeholder="$t('createVideo.typeTitle')"
/>
<el-button type="primary">
{{ $t("createVideo.confirm") }}
</el-button>
<el-input
v-model="title"
:rows="15"
type="textarea"
:placeholder="$t('createVideo.aiText')"
/>
<el-icon :size="20">
<Edit />
</el-icon>
</div>
<p>{{ $t("createVideo.languages") }}</p>
<el-select
v-model="language"
placeholder="Select"
style="width: 100%"
>
<el-option
v-for="item in languageOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<p>{{ $t("createVideo.voices") }}</p>
<el-select
v-model="language"
placeholder="Select"
style="width: 100%"
>
<el-option
v-for="item in languageOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<p>{{ $t("createVideo.styles") }}</p>
<el-select
v-model="language"
placeholder="Select"
style="width: 100%"
>
<el-option
v-for="item in languageOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<el-button type="primary">{{
$t("createVideo.generateVideo")
}}</el-button>
</div>
</el-tab-pane> </el-tab-pane>
<!-- ------------------------ 2 --> <!-- ------------------------ 2 -->
<el-tab-pane :label="$t('createVideo.uploadAudio')"> <el-tab-pane :label="$t('createVideo.uploadAudio')">
<div class="card2"> <div class="card2">
<div class="uploadVideo">
<!-- 录制MP3上传语音 -->
<div
class="uploadAudio"
:class="audioUrl ? 'uploadAudioAvtion' : ''"
>
<div class="btnBox">
<button
class="pointer"
:disabled="!isRecording"
@click="startRecording"
>
开始录音
</button>
<button
class="pointer"
@click="stopRecording"
:disabled="isRecording"
>
停止录音
</button>
</div>
<!-- <button @click="playRecording">播放录音</button> -->
<audio v-if="audioUrl" controls :src="audioUrl"></audio>
<button v-if="audioUrl" @click="uploadAudio" class="pointer">
上传音频
</button>
</div>
<!-- 上传视频 -->
<div
class="uploadVideo"
style="text-align: center; line-height: 70px"
>
上传视频
<input type="file" ref="fileInput" @change="handleFileChange" /> <input type="file" ref="fileInput" @change="handleFileChange" />
<video ref="videoPlayer" controls></video>
<video
v-if="videoSrc"
:src="videoSrc"
ref="videoPlayer"
controls
></video>
</div> </div>
</div> </div>
</el-tab-pane> </el-tab-pane>
<!-- ----------------------- 3 --> <!-- ----------------------- 3 -->
<el-tab-pane :label="$t('createVideo.aiScript')">
<el-tab-pane v-if="false" :label="$t('createVideo.aiScript')">
<div class="card3"> <div class="card3">
<div class="text"> <div class="text">
<el-input <el-input
@@ -147,27 +265,115 @@
<script setup> <script setup>
import { ref } from "vue"; import { ref } from "vue";
import { getCurrentInstance } from "vue"; import { getCurrentInstance } from "vue";
import Recorder from "js-audio-recorder";
import axios from "axios";
import { awsImgUpload, awsMp3Upload } from "@/apis/createVideo";
import { ElMessage } from "element-plus";
// 获取AI头像
const AiFace = ref([]);
function getAiFace() {
axios({
url: "https://photo.metavatar.cc/C//api/personPhoto/list?pageNum=1&pageSize=1",
method: "get",
}).then((res) => {
AiFace.value = res.data.data.list;
console.log(res.data.data.list);
});
}
getAiFace();

// 标题 // 标题
let title = ref(""); let title = ref("");
// 上传图片 // 上传图片
let imgUrl = ref(""); let imgUrl = ref("");
function changeFile(e) {
const imgData = ref("");
// 预览图片
function lookImg(e) {
imgUrl.value = URL.createObjectURL(e.target.files[0]); imgUrl.value = URL.createObjectURL(e.target.files[0]);
imgData.value = e.target.files[0];
}
// 上传图片
async function changeFile() {
imgUrl.value = URL.createObjectURL(imgData.value);
let formData = new FormData();
const timestamp = Date.now();
formData.append("file", imgData.value, timestamp + ".png");
try {
const res = await awsImgUpload(formData);
ElMessage.success("上传成功!");
} catch (error) {
ElMessage.error(error);
}
} }


// $t在script中的使用
// 点击aifece
function setImgUrl(url) {
imgUrl.value = url;
}


const {
appContext: {
config: { globalProperties },
},
} = getCurrentInstance();
// 录制MP3上传语音
const parameter = {
sampleBits: 16, // 采样位数,支持 8 或 16,默认是16
sampleRate: 8000, // 采样率,支持 11025、16000、22050、24000、44100、48000,根据浏览器默认值,我的chrome是48000
numChannels: 1, // 声道,支持 1 或 2, 默认是1
};
const recorder = new Recorder(parameter);
const isRecording = ref(true);
const audioUrl = ref(null);
const audioData = ref("");

const startRecording = async () => {
try {
await recorder.start();
console.log("Recording started");
isRecording.value = false;
} catch (error) {
console.error(error);
}
};

const stopRecording = async () => {
try {
const recording = await recorder.stop();
audioUrl.value = URL.createObjectURL(recorder.getWAVBlob());
audioData.value = recorder.getWAVBlob();
isRecording.value = true;
} catch (error) {
console.error(error);
}
};


const string = "createVideo.typeScript";
const t = globalProperties.$t(string);
const playRecording = () => {
if (audioUrl.value) {
const audio = new Audio(audioUrl.value);
audio.play();
}
};
async function uploadAudio(params) {
let formData = new FormData();
const timestamp = Date.now();
formData.append("file", audioData.value, timestamp + ".mp3");
try {
const res = await awsMp3Upload(formData);
ElMessage.success("上传成功!");
} catch (error) {
ElMessage.error(error);
}
}

// 上传视频功能
const fileInput = ref(null);
const videoSrc = ref(null);
const handleFileChange = () => {
const file = fileInput.value.files[0];
if (file) {
const videoUrl = URL.createObjectURL(file);
videoSrc.value = videoUrl;
}
};


// card3的 // card3的
let language = reactive("");
let language = ref("");


let languageOptions = reactive([ let languageOptions = reactive([
{ {
@@ -179,6 +385,16 @@ let languageOptions = reactive([
label: "Option2", label: "Option2",
}, },
]); ]);

// $t在script中的使用
const {
appContext: {
config: { globalProperties },
},
} = getCurrentInstance();

const string = "createVideo.typeScript";
const t = globalProperties.$t(string);
</script> </script>


<style lang="scss" scoped> <style lang="scss" scoped>
@@ -216,6 +432,14 @@ let languageOptions = reactive([


.uploadBtn { .uploadBtn {
position: relative; position: relative;
padding: 5px 10px;
margin-left: 10px;
border-radius: 5px;
transition: all 0.3s;
&:hover {
background-color: #000;
color: #fff;
}
} }


.bigImg { .bigImg {
@@ -245,7 +469,14 @@ let languageOptions = reactive([
background-color: green; background-color: green;
border-radius: 50%; border-radius: 50%;
} }

.el-upload {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0;
}
.upload { .upload {
top: 200px; top: 200px;
width: 100px; width: 100px;
@@ -333,11 +564,13 @@ let languageOptions = reactive([
p { p {
height: 30px; height: 30px;
} }

img {
width: 100%;
}
.img { .img {
width: 100px; width: 100px;
height: 100px; height: 100px;
background-color: green;
// background-color: green;
border-radius: 50%; border-radius: 50%;
} }
} }
@@ -357,21 +590,90 @@ let languageOptions = reactive([


.tabs { .tabs {
height: 100%; height: 100%;
.card1 {
.text {
padding: 10px;
border: 1px solid #000;

.el-button {
float: right;
margin-top: 10px;
}

:deep(.el-textarea__inner) {
resize: none;
box-shadow: none;
}
}

p {
margin: 10px 0;
}

> .el-button {
width: 100%;
height: 50px;
margin-top: 10px;
}
}
.card2 { .card2 {
padding: 10px; padding: 10px;
.uploadVideo {
> div {
position: relative; position: relative;
margin-top: 10px; margin-top: 10px;
width: 100%; width: 100%;
height: 100px;
border: #000 1px solid;
border-radius: 10px; border-radius: 10px;
background-color: red;

overflow: hidden;
transition: all 0.3s;
box-shadow: #00000026 2px 2px 2px 2px;
&:hover {
transform: translateY(-10px);
}
}
.uploadAudio {
padding: 20px;
margin-bottom: 20px;
height: 70px;
.btnBox {
display: flex;
justify-content: space-between;
margin-bottom: 10px;
}
audio {
height: 50px;
width: 100%;
}
button {
border-radius: 10px;
height: 30px;
line-height: 22px;
padding: 5px 10px;
background-color: #fff;
transition: all 0.3s;
&:hover {
background-color: #000;

color: #fff;
}
}
}
.uploadAudioAvtion {
height: 170px;
}
.uploadVideo {
height: 100px;
input { input {
position: absolute; position: absolute;
width: 100%; width: 100%;
height: 100%; height: 100%;
opacity: 0; opacity: 0;
} }
video {
width: 100%;
height: 100%;
}
} }
} }
.card3 { .card3 {


+ 3
- 0
vite.config.ts Vedi File

@@ -96,5 +96,8 @@ export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
symbolId: "icon-[dir]-[name]", symbolId: "icon-[dir]-[name]",
}), }),
], ],
define: {
global:{}
}
}; };
}); });

+ 6470
- 0
yarn-error.log
File diff soppresso perché troppo grande
Vedi File


+ 5
- 0
yarn.lock Vedi File

@@ -3722,6 +3722,11 @@ jiti@^1.16.0, jiti@^1.18.2:
resolved "https://registry.npmmirror.com/jiti/-/jiti-1.18.2.tgz" resolved "https://registry.npmmirror.com/jiti/-/jiti-1.18.2.tgz"
integrity sha512-QAdOptna2NYiSSpv0O/BwoHBSmz4YhpzJHyi+fnMRTXFjp7B8i/YG5Z8IfusxB1ufjcD2Sre1F3R+nX3fvy7gg== integrity sha512-QAdOptna2NYiSSpv0O/BwoHBSmz4YhpzJHyi+fnMRTXFjp7B8i/YG5Z8IfusxB1ufjcD2Sre1F3R+nX3fvy7gg==


js-audio-recorder@^1.0.7:
version "1.0.7"
resolved "https://registry.yarnpkg.com/js-audio-recorder/-/js-audio-recorder-1.0.7.tgz#01501cb9eb143d57994b42bd5ae97974fda18908"
integrity sha512-JiDODCElVHGrFyjGYwYyNi7zCbKk9va9C77w+zCPMmi4C6ix7zsX2h3ddHugmo4dOTOTCym9++b/wVW9nC0IaA==

js-base64@^2.1.9: js-base64@^2.1.9:
version "2.6.4" version "2.6.4"
resolved "https://registry.npmmirror.com/js-base64/-/js-base64-2.6.4.tgz" resolved "https://registry.npmmirror.com/js-base64/-/js-base64-2.6.4.tgz"


Caricamento…
Annulla
Salva