congzc 2 år sedan
förälder
incheckning
fa80517283
5 ändrade filer med 235 tillägg och 67 borttagningar
  1. +2
    -1
      package.json
  2. +2
    -0
      src/types/components.d.ts
  3. +170
    -61
      src/views/createVideo/index.vue
  4. +49
    -5
      src/views/myAccount/index.vue
  5. +12
    -0
      yarn.lock

+ 2
- 1
package.json Visa fil

@@ -18,6 +18,7 @@
"@wangeditor/editor": "^5.0.0", "@wangeditor/editor": "^5.0.0",
"@wangeditor/editor-for-vue": "^5.1.10", "@wangeditor/editor-for-vue": "^5.1.10",
"axios": "^1.3.4", "axios": "^1.3.4",
"browser-image-compression": "^2.0.2",
"echarts": "^5.2.2", "echarts": "^5.2.2",
"element-plus": "^2.3.1", "element-plus": "^2.3.1",
"js-audio-recorder": "^1.0.7", "js-audio-recorder": "^1.0.7",
@@ -72,4 +73,4 @@
"repository": "https://gitee.com/youlaiorg/vue3-element-admin.git", "repository": "https://gitee.com/youlaiorg/vue3-element-admin.git",
"author": "有来开源组织", "author": "有来开源组织",
"license": "MIT" "license": "MIT"
}
}

+ 2
- 0
src/types/components.d.ts Visa fil

@@ -39,8 +39,10 @@ declare module '@vue/runtime-core' {
IEpEdit: typeof import('~icons/ep/edit')['default'] IEpEdit: typeof import('~icons/ep/edit')['default']
IEpGoods: typeof import('~icons/ep/goods')['default'] IEpGoods: typeof import('~icons/ep/goods')['default']
IEpMenu: typeof import('~icons/ep/menu')['default'] IEpMenu: typeof import('~icons/ep/menu')['default']
IEpMic: typeof import('~icons/ep/mic')['default']
IEpSearch: typeof import('~icons/ep/search')['default'] IEpSearch: typeof import('~icons/ep/search')['default']
IEpSetting: typeof import('~icons/ep/setting')['default'] IEpSetting: typeof import('~icons/ep/setting')['default']
IEpVideoCamera: typeof import('~icons/ep/video-camera')['default']
IEpVideoPlay: typeof import('~icons/ep/video-play')['default'] IEpVideoPlay: typeof import('~icons/ep/video-play')['default']
LangSelect: typeof import('./../components/LangSelect/index.vue')['default'] LangSelect: typeof import('./../components/LangSelect/index.vue')['default']
MultiUpload: typeof import('./../components/Upload/MultiUpload.vue')['default'] MultiUpload: typeof import('./../components/Upload/MultiUpload.vue')['default']


+ 170
- 61
src/views/createVideo/index.vue Visa fil

@@ -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>
<!-- 上传按钮 --> <!-- 上传按钮 -->
<div class="btnBox">
<div class="btnBox" v-show="submitImgBtn">
<button class="uploadBtn"> <button class="uploadBtn">
{{ $t("createVideo.reselect") }} {{ $t("createVideo.reselect") }}
<input type="file" @change="lookImg" />
<input
accept="image/*"
type="file"
@click="e.target.value = null"
@change="lookImg"
/>
</button> </button>
<button class="uploadBtn" @click="changeFile"> <button class="uploadBtn" @click="changeFile">
{{ $t("createVideo.sureUpload") }} {{ $t("createVideo.sureUpload") }}
@@ -39,17 +44,12 @@
</div> </div>
<div class="upload inmiddle"> <div class="upload inmiddle">
+ +
<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"
/> -->
<input
accept="image/*"
type="file"
@click="e.target.value = null"
@change="lookImg"
/>
</div> </div>
<div class="falseImg inmiddle"> <div class="falseImg inmiddle">
<div><div class="icon">×</div></div> <div><div class="icon">×</div></div>
@@ -89,8 +89,9 @@
<my-loading :isLoading="feceItemLoading"></my-loading> <my-loading :isLoading="feceItemLoading"></my-loading>
<!-- face列表 --> <!-- face列表 -->
<div <div
:class="faceItemActive == item.id ? 'faceItemActive' : ''"
class="faceItem pointer" class="faceItem pointer"
@click="setImgUrl(item.material)"
@click="setImgUrl(item.material, item.id)"
v-for="item in AiFaceList" v-for="item in AiFaceList"
:key="item.id" :key="item.id"
> >
@@ -115,15 +116,15 @@
<el-button type="primary"> <el-button type="primary">
{{ $t("createVideo.confirm") }} {{ $t("createVideo.confirm") }}
</el-button> </el-button>
<!-- 文本域 -->
<el-input <el-input
v-model="title"
id="textInputId"
v-model="textareaContent"
:rows="15" :rows="15"
type="textarea" type="textarea"
:placeholder="$t('createVideo.aiText')" :placeholder="$t('createVideo.aiText')"
/> />
<el-icon :size="20">
<Edit />
</el-icon>
<div @click="insertIcon">🕗</div>
</div> </div>
<p>{{ $t("createVideo.languages") }}</p> <p>{{ $t("createVideo.languages") }}</p>
<el-select <el-select
@@ -145,7 +146,7 @@
style="width: 100%" style="width: 100%"
> >
<el-option <el-option
v-for="item in languageOptions"
v-for="item in soundOptions"
:key="item.value" :key="item.value"
:label="item.label" :label="item.label"
:value="item.value" :value="item.value"
@@ -158,13 +159,13 @@
style="width: 100%" style="width: 100%"
> >
<el-option <el-option
v-for="item in languageOptions"
v-for="item in soundStyleOptions"
:key="item.value" :key="item.value"
:label="item.label" :label="item.label"
:value="item.value" :value="item.value"
/> />
</el-select> </el-select>
<el-button type="primary">{{
<el-button color="#000" type="primary">{{
$t("createVideo.generateVideo") $t("createVideo.generateVideo")
}}</el-button> }}</el-button>
</div> </div>
@@ -172,7 +173,26 @@
<!-- ------------------------ 2 --> <!-- ------------------------ 2 -->
<el-tab-pane :label="$t('createVideo.uploadAudio')"> <el-tab-pane :label="$t('createVideo.uploadAudio')">
<div class="card2"> <div class="card2">
<!-- 上传视频 -->
<p>
<el-icon class="icon-VideoCamera"><i-ep-VideoCamera /></el-icon>
上传视频
</p>
<div class="uploadVideo">
+
<input type="file" ref="fileInput" @change="handleFileChange" />
<video
v-if="videoSrc"
:src="videoSrc"
ref="videoPlayer"
controls
></video>
</div>
<!-- 录制MP3上传语音 --> <!-- 录制MP3上传语音 -->
<p>
<el-icon class="icon-Mic"><i-ep-Mic /></el-icon>
录制音频
</p>
<div <div
class="uploadAudio" class="uploadAudio"
:class="audioUrl ? 'uploadAudioAvtion' : ''" :class="audioUrl ? 'uploadAudioAvtion' : ''"
@@ -199,20 +219,9 @@
上传音频 上传音频
</button> </button>
</div> </div>
<!-- 上传视频 -->
<div
class="uploadVideo"
style="text-align: center; line-height: 70px"
>
上传视频
<input type="file" ref="fileInput" @change="handleFileChange" />
<video
v-if="videoSrc"
:src="videoSrc"
ref="videoPlayer"
controls
></video>
</div>
<el-button color="#000" type="primary">{{
$t("createVideo.generateVideo")
}}</el-button>
</div> </div>
</el-tab-pane> </el-tab-pane>
<!-- ----------------------- 3 --> <!-- ----------------------- 3 -->
@@ -287,13 +296,14 @@


<script setup> <script setup>
import { getCurrentInstance } from "vue"; import { getCurrentInstance } from "vue";
import Recorder from "js-audio-recorder";
import { import {
personPhotoList, personPhotoList,
awsImgUpload, awsImgUpload,
videoUpload, videoUpload,
saveImgApi, saveImgApi,
} from "@/apis/createVideo"; } from "@/apis/createVideo";
import Recorder from "js-audio-recorder"; //mp3插件
import imageCompression from "browser-image-compression"; //压缩图片插件


// 获取AI头像 // 获取AI头像
const AiFaceList = ref([]); const AiFaceList = ref([]);
@@ -319,14 +329,27 @@ function ChangeShowFaceList(index) {
const title = ref(""); const title = ref("");


// 上传图片 // 上传图片
const imgUrl = ref("");
const imgData = ref("");
const showUploadBtn = ref(false);
const imgUrl = ref(""); //图片回显路径
const imgData = ref(""); // 上传图片文件
const showUploadBtn = ref(false); //上传图片+号的显示隐藏
const submitImgBtn = ref(false); //右上角俩按钮显示与隐藏

// 预览图片 // 预览图片
function lookImg(e) {
imgUrl.value = URL.createObjectURL(e.target.files[0]);
imgData.value = e.target.files[0];
async function lookImg(e) {
// imgUrl.value = URL.createObjectURL(e.target.files[0]);
// imgData.value = e.target.files[0];
// showUploadBtn.value = false;
// submitImgBtn.value = true;
// 压缩配置
const options = {
maxSizeMB: 2, // 最大压缩大小为 1MB
useWebWorker: true, // 使用 Web Worker 进行压缩,提高性能
};
const compressedFile = await imageCompression(e.target.files[0], options);
imgUrl.value = URL.createObjectURL(compressedFile);
imgData.value = compressedFile;
showUploadBtn.value = false; showUploadBtn.value = false;
submitImgBtn.value = true;
} }
// 上传图片 // 上传图片
async function changeFile() { async function changeFile() {
@@ -346,14 +369,75 @@ async function changeFile() {
ElMessage.error(error); ElMessage.error(error);
} }
} }
const faceItemActive = ref();
// 点击aifece // 点击aifece
function setImgUrl(url) {
function setImgUrl(url, id) {
faceItemActive.value = id;
showUploadBtn.value = false; showUploadBtn.value = false;
submitImgBtn.value = false;
imgUrl.value = url; imgUrl.value = url;
} }


// 录制MP3上传语音
//#region card1的逻辑
const textareaContent = ref("");
function insertIcon() {
const textarea = document.getElementById("textInputId");
const icon = "🕗"; // 这里使用了一个星星作为示例图标,你可以替换为你自己的图标

// 获取光标位置
const startPos = textarea.selectionStart;
const endPos = textarea.selectionEnd;

console.log(startPos);
console.log(endPos);
// 在光标位置插入图标
textareaContent.value =
textareaContent.value.substring(0, startPos) +
icon +
textareaContent.value.substring(endPos, textareaContent.value.length);

// 设置光标位置为插入图标后的位置
const newCursorPos = startPos + icon.length;
textarea.setSelectionRange(newCursorPos, newCursorPos);
textarea.focus();
}
const language = ref("");
const sound = ref("");
const soundStyle = ref("");

const languageOptions = reactive([
{
value: "0",
label: "中文",
},
{
value: "1",
label: "English",
},
]);
const soundOptions = reactive([
{
value: "0",
label: "老人",
},
{
value: "1",
label: "小孩",
},
]);
const soundStyleOptions = reactive([
{
value: "0",
label: "生气",
},
{
value: "1",
label: "抑郁",
},
]);
//#endregion

//#region 录制MP3上传语音
const parameter = { const parameter = {
sampleBits: 16, // 采样位数,支持 8 或 16,默认是16 sampleBits: 16, // 采样位数,支持 8 或 16,默认是16
sampleRate: 8000, // 采样率,支持 11025、16000、22050、24000、44100、48000,根据浏览器默认值,我的chrome是48000 sampleRate: 8000, // 采样率,支持 11025、16000、22050、24000、44100、48000,根据浏览器默认值,我的chrome是48000
@@ -402,8 +486,9 @@ async function uploadAudio(params) {
ElMessage.error(error); ElMessage.error(error);
} }
} }
//#endregion ------------------------------------


// 上传视频功能
//#region 上传视频功能
const fileInput = ref(null); const fileInput = ref(null);
const videoSrc = ref(null); const videoSrc = ref(null);
const handleFileChange = () => { const handleFileChange = () => {
@@ -413,20 +498,11 @@ const handleFileChange = () => {
videoSrc.value = videoUrl; videoSrc.value = videoUrl;
} }
}; };
//#endregion --------------------------------------


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


let languageOptions = reactive([
{
value: "Option1",
label: "Option1",
},
{
value: "Option2",
label: "Option2",
},
]);
//#endregion ---------------------------


// $t在script中的使用 // $t在script中的使用
const { const {
@@ -603,6 +679,7 @@ onMounted(() => {
} }


.faceList { .faceList {
padding: 3px;
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
justify-content: flex-start; justify-content: flex-start;
@@ -611,7 +688,7 @@ onMounted(() => {
overflow-y: scroll; overflow-y: scroll;
.faceItem { .faceItem {
position: relative; position: relative;
margin-right: 10px;
margin-right: 13px;
margin-bottom: 10px; margin-bottom: 10px;
width: 150px; width: 150px;
height: 150px; height: 150px;
@@ -619,7 +696,9 @@ onMounted(() => {
line-height: 150px; line-height: 150px;
text-align: center; text-align: center;
border-radius: 50%; border-radius: 50%;
border: 2px solid #000;
background-color: #fbf8f8;
border: 2px solid #fff;
box-shadow: rgba(0, 0, 0, 0.3) 0px 0px 3px 3px;
overflow: hidden; overflow: hidden;
input { input {
position: absolute; position: absolute;
@@ -647,6 +726,15 @@ onMounted(() => {
border-radius: 50%; border-radius: 50%;
} }
} }
.faceItemActive {
background: linear-gradient(
270deg,
rgb(201, 113, 255) 24.97%,
rgb(92, 121, 252) 100%
);
// border: 2px solid #fff;
// box-shadow: rgba(0, 0, 0, 0.3) 0px 0px 3px 3px;
}
} }
} }
} }
@@ -667,7 +755,6 @@ onMounted(() => {
.text { .text {
padding: 10px; padding: 10px;
border: 1px solid #000; border: 1px solid #000;

.el-button { .el-button {
float: right; float: right;
margin-top: 10px; margin-top: 10px;
@@ -688,9 +775,18 @@ onMounted(() => {
height: 50px; height: 50px;
margin-top: 10px; margin-top: 10px;
} }

:deep(.el-input .is-focus) {
// box-shadow: none !important;
// box-shadow: 0 0 0 1px #000 !important;
}
} }
.card2 { .card2 {
padding: 10px; padding: 10px;
.el-icon {
// color: red;
vertical-align: text-top;
}
> div { > div {
position: relative; position: relative;
margin-top: 10px; margin-top: 10px;
@@ -707,6 +803,7 @@ onMounted(() => {
} }
.uploadAudio { .uploadAudio {
padding: 20px; padding: 20px;
// margin-top: 30px;
margin-bottom: 20px; margin-bottom: 20px;
height: 70px; height: 70px;
.btnBox { .btnBox {
@@ -736,7 +833,13 @@ onMounted(() => {
height: 170px; height: 170px;
} }
.uploadVideo { .uploadVideo {
text-align: center;

margin-bottom: 20px;
height: 100px; height: 100px;
font-size: 50px;
font-weight: 700;
line-height: 100px;
input { input {
position: absolute; position: absolute;
width: 100%; width: 100%;
@@ -748,6 +851,12 @@ onMounted(() => {
height: 100%; height: 100%;
} }
} }
> .el-button {
width: 100%;
height: 50px;
margin-top: 10px;
// background-color: #000;
}
} }
.card3 { .card3 {
.text { .text {


+ 49
- 5
src/views/myAccount/index.vue Visa fil

@@ -30,7 +30,13 @@
</div> </div>
<!-- 邀请码 --> <!-- 邀请码 -->
<div class="left-three border flex justify-between"> <div class="left-three border flex justify-between">
<div class="codeImg"></div>
<div class="codeImg">
<img
ref="codeImgRef"
src="https://formall.oss-accelerate.aliyuncs.com/1003/dongzhanxiziguoji.png"
alt=""
/>
</div>
<div class="other"> <div class="other">
<div v-if="currentLan == 'en'"> <div v-if="currentLan == 'en'">
<span>Invite friends to get</span> <span>Invite friends to get</span>
@@ -43,11 +49,19 @@
<span>邀请更多好友</span> <span>邀请更多好友</span>
<span class="bigWord">免费</span> <span class="bigWord">免费</span>
<span>生成视频!</span> <span>生成视频!</span>
<p>
邀请码:
<span id="InviteCodeId">qweiuqkljzxcahdouiahsd</span>
</p>
</div> </div>


<div class="btns"> <div class="btns">
<span class="myBtn">{{ $t("account.copyCode") }}</span>
<span class="myBtn">{{ $t("account.saveCode") }}</span>
<span class="myBtn" @click="copyInviteCode">{{
$t("account.copyCode")
}}</span>
<span class="myBtn" @click="DownloadCodeImg">{{
$t("account.saveCode")
}}</span>
</div> </div>
</div> </div>
</div> </div>
@@ -97,9 +111,31 @@
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import { useRouter } from "vue-router"; import { useRouter } from "vue-router";
const { locale } = useI18n(); const { locale } = useI18n();

const currentLan = ref(locale); const currentLan = ref(locale);


//#region 二维码区域
// 点击复制邀请码
function copyInviteCode() {
const inviteCode = document.getElementById("InviteCodeId").innerText;
navigator.clipboard
.writeText(inviteCode)
.then(() => {
ElMessage.success("邀请码已复制到剪贴板");
})
.catch((error) => {
ElMessage.error("无法复制邀请码:", error);
});
}
// 下载二维码图片
const codeImgRef = ref();
function DownloadCodeImg() {
const link = document.createElement("a");
link.href = codeImgRef.value.src;
link.download = "image.jpg";
link.click();
}
//#endregion

const router = useRouter(); const router = useRouter();
function routerTo(url) { function routerTo(url) {
router.push(url); router.push(url);
@@ -183,10 +219,18 @@ function routerTo(url) {


&-three { &-three {
.codeImg { .codeImg {
position: relative;
width: 120px; width: 120px;
height: 120px; height: 120px;
margin-right: 10px; margin-right: 10px;
background-color: red;
// background-color: red;
img {
position: absolute;
top: 50%;
transform: translateY(-50%);
width: 100%;
max-height: 100%;
}
} }


.other { .other {


+ 12
- 0
yarn.lock Visa fil

@@ -1737,6 +1737,13 @@ braces@^3.0.2, braces@~3.0.2:
dependencies: dependencies:
fill-range "^7.0.1" fill-range "^7.0.1"


browser-image-compression@^2.0.2:
version "2.0.2"
resolved "https://registry.npmmirror.com/browser-image-compression/-/browser-image-compression-2.0.2.tgz#4d5ef8882e9e471d6d923715ceb9034499d14eaa"
integrity sha512-pBLlQyUf6yB8SmmngrcOw3EoS4RpQ1BcylI3T9Yqn7+4nrQTXJD4sJDe5ODnJdrvNMaio5OicFo75rDyJD2Ucw==
dependencies:
uzip "0.20201231.0"

browserslist@^4.21.3, browserslist@^4.21.5: browserslist@^4.21.3, browserslist@^4.21.5:
version "4.21.5" version "4.21.5"
resolved "https://registry.npmmirror.com/browserslist/-/browserslist-4.21.5.tgz" resolved "https://registry.npmmirror.com/browserslist/-/browserslist-4.21.5.tgz"
@@ -6150,6 +6157,11 @@ util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1:
resolved "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz" resolved "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz"
integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==


uzip@0.20201231.0:
version "0.20201231.0"
resolved "https://registry.npmmirror.com/uzip/-/uzip-0.20201231.0.tgz#9e64b065b9a8ebf26eb7583fe8e77e1d9a15ed14"
integrity sha512-OZeJfZP+R0z9D6TmBgLq2LHzSSptGMGDGigGiEe0pr8UBe/7fdflgHlHBNDASTXB5jnFuxHpNaJywSg8YFeGng==

v8-compile-cache-lib@^3.0.1: v8-compile-cache-lib@^3.0.1:
version "3.0.1" version "3.0.1"
resolved "https://registry.npmmirror.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz" resolved "https://registry.npmmirror.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz"


Laddar…
Avbryt
Spara