| @@ -21,38 +21,38 @@ | |||
| <script> | |||
| //#region 禁用网页滚动 | |||
| const keyCodeMap = { | |||
| // 91: true, // command | |||
| 61: true, | |||
| 107: true, // 数字键盘 + | |||
| 109: true, // 数字键盘 - | |||
| 173: true, // 火狐 - 号 | |||
| 187: true, // + | |||
| 189: true, // - | |||
| }; | |||
| // 覆盖ctrl||command + ‘+’/‘-’ | |||
| document.onkeydown = function (event) { | |||
| const e = event || window.event; | |||
| const ctrlKey = e.ctrlKey || e.metaKey; | |||
| if (ctrlKey && keyCodeMap[e.keyCode]) { | |||
| e.preventDefault(); | |||
| } else if (e.detail) { // Firefox | |||
| event.returnValue = false; | |||
| } | |||
| }; | |||
| // 覆盖鼠标滑动 | |||
| document.body.addEventListener('wheel', (e) => { | |||
| if (e.ctrlKey) { | |||
| if (e.deltaY < 0) { | |||
| e.preventDefault(); | |||
| return false; | |||
| } | |||
| if (e.deltaY > 0) { | |||
| e.preventDefault(); | |||
| return false; | |||
| } | |||
| } | |||
| }, { passive: false }); | |||
| // const keyCodeMap = { | |||
| // // 91: true, // command | |||
| // 61: true, | |||
| // 107: true, // 数字键盘 + | |||
| // 109: true, // 数字键盘 - | |||
| // 173: true, // 火狐 - 号 | |||
| // 187: true, // + | |||
| // 189: true, // - | |||
| // }; | |||
| // // 覆盖ctrl||command + ‘+’/‘-’ | |||
| // document.onkeydown = function (event) { | |||
| // const e = event || window.event; | |||
| // const ctrlKey = e.ctrlKey || e.metaKey; | |||
| // if (ctrlKey && keyCodeMap[e.keyCode]) { | |||
| // e.preventDefault(); | |||
| // } else if (e.detail) { // Firefox | |||
| // event.returnValue = false; | |||
| // } | |||
| // }; | |||
| // // 覆盖鼠标滑动 | |||
| // document.body.addEventListener('wheel', (e) => { | |||
| // if (e.ctrlKey) { | |||
| // if (e.deltaY < 0) { | |||
| // e.preventDefault(); | |||
| // return false; | |||
| // } | |||
| // if (e.deltaY > 0) { | |||
| // e.preventDefault(); | |||
| // return false; | |||
| // } | |||
| // } | |||
| // }, { passive: false }); | |||
| //#endregion ----------------------------------- | |||
| //#region | |||
| @@ -41,7 +41,8 @@ export default { | |||
| navbar: { | |||
| account: "Account", | |||
| logout: "Logout", | |||
| goLogin:'Go and log in' | |||
| goLogin:'Go and log in', | |||
| LanguageChange:'Language switching' | |||
| }, | |||
| // 创作视频 | |||
| @@ -79,6 +80,8 @@ export default { | |||
| copy:'Copy to text', | |||
| tooltip1:'Click to listen', | |||
| tooltip2:'Add Pause', | |||
| uploadImgTip1:'Click here to upload pictures', | |||
| uploadImgTip2:'Please ensure that the uploaded image is an open face image', | |||
| }, | |||
| // 我的视频 | |||
| @@ -41,7 +41,8 @@ export default { | |||
| navbar: { | |||
| account: "账户", | |||
| logout: "注销", | |||
| goLogin:'登录' | |||
| goLogin:'登录', | |||
| LanguageChange:'语言切换' | |||
| }, | |||
| // 创作视频 | |||
| @@ -79,6 +80,8 @@ export default { | |||
| copy:'复制到文案', | |||
| tooltip1:'点击试听', | |||
| tooltip2:'添加停顿', | |||
| uploadImgTip1:'点此上传图片', | |||
| uploadImgTip2:'请确保上传图片为无遮挡的正脸图片', | |||
| }, | |||
| // 我的视频 | |||
| @@ -25,7 +25,8 @@ const tagsViewStore = useTagsViewStore(); | |||
| min-height: calc(100vh - 80px); | |||
| // overflow: hidden; | |||
| // background-color: var(--el-bg-color-page); | |||
| background-color: #000; | |||
| // background-color: #000; | |||
| background: linear-gradient(to bottom, black 30%, white 70%); | |||
| } | |||
| .fixed-header + .app-main { | |||
| @@ -14,7 +14,14 @@ | |||
| {{ $t(routeName as string) }} | |||
| </div> | |||
| <!--语言选择--> | |||
| <lang-select class="navItem" style="color: #ffffff" /> | |||
| <el-tooltip | |||
| class="box-item" | |||
| effect="dark" | |||
| :content="$t('navbar.LanguageChange')" | |||
| placement="top-start" | |||
| > | |||
| <lang-select class="navItem" style="color: #ffffff" /> | |||
| </el-tooltip> | |||
| <!-- <div | |||
| class="avatar" | |||
| @@ -196,9 +203,10 @@ watch( | |||
| } | |||
| } | |||
| .navItem { | |||
| font-size: 16px; | |||
| cursor: pointer; | |||
| transition: all 0.3s; | |||
| margin-right: 10px; | |||
| margin-right: 20px; | |||
| &:hover { | |||
| color: #4769da; | |||
| } | |||
| @@ -25,7 +25,7 @@ | |||
| <div class="icon"> | |||
| <el-icon><i-ep-DocumentAdd /></el-icon> | |||
| </div> | |||
| API Access | |||
| {{ $t("API.title") }} | |||
| </div> | |||
| </div> | |||
| </div> | |||
| @@ -2,6 +2,7 @@ | |||
| export {} | |||
| declare global { | |||
| const EffectScope: typeof import('vue')['EffectScope'] | |||
| const ElForm: typeof import('element-plus/es')['ElForm'] | |||
| const ElMessage: typeof import('element-plus/es')['ElMessage'] | |||
| const ElMessageBox: typeof import('element-plus/es')['ElMessageBox'] | |||
| const asyncComputed: typeof import('@vueuse/core')['asyncComputed'] | |||
| @@ -270,6 +271,7 @@ import { UnwrapRef } from 'vue' | |||
| declare module 'vue' { | |||
| interface ComponentCustomProperties { | |||
| readonly EffectScope: UnwrapRef<typeof import('vue')['EffectScope']> | |||
| readonly ElForm: UnwrapRef<typeof import('element-plus/es')['ElForm']> | |||
| 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']> | |||
| @@ -1,7 +1,7 @@ | |||
| <template> | |||
| <div class="page flex justify-around"> | |||
| <!-- 左侧栏 --> | |||
| <div class="left"> | |||
| <div class="left scrolly"> | |||
| <!-- 顶部 --> | |||
| <!-- 选中AiFace --> | |||
| <div class="left-top" v-show="showUploadBtn == 1"> | |||
| @@ -40,7 +40,11 @@ | |||
| <div class="icon">✔</div> | |||
| </div> | |||
| <div v-if="!compressionImgLoad" class="upload inmiddle"> | |||
| + | |||
| <p> | |||
| <el-icon><i-ep-FolderAdd /></el-icon> | |||
| </p> | |||
| <span>{{ $t("createVideo.uploadImgTip1") }}</span> | |||
| <span>{{ $t("createVideo.uploadImgTip2") }}</span> | |||
| <input accept="image/*" type="file" @change="lookImg" /> | |||
| </div> | |||
| <div v-if="!compressionImgLoad" class="falseImg inmiddle"> | |||
| @@ -242,7 +246,7 @@ | |||
| </div> | |||
| </div> | |||
| <!-- 右侧栏 --> | |||
| <div class="right"> | |||
| <div class="right scrolly"> | |||
| <div class="subscript"> | |||
| <!-- <span>GPT</span> --> | |||
| <img src="../../assets/img/gpttotext.png" alt="" /> | |||
| @@ -257,7 +261,7 @@ | |||
| maxlength="3000" | |||
| id="textInputId" | |||
| v-model="textareaContent" | |||
| :rows="15" | |||
| :rows="12" | |||
| type="textarea" | |||
| :placeholder="$t('createVideo.aiText')" | |||
| /> | |||
| @@ -380,22 +384,36 @@ | |||
| <el-icon class="icon-Headset"><i-ep-Headset /></el-icon> | |||
| {{ $t("createVideo.uploadAudio") }} | |||
| </p> | |||
| <div class="uploadVideo"> | |||
| <div | |||
| class="uploadVideo" | |||
| :class=" | |||
| audioUrl && showAudioWhich == 1 ? 'uploadAudioAvtion2' : '' | |||
| " | |||
| > | |||
| <el-icon><i-ep-FolderAdd /></el-icon> | |||
| <!-- fileInput.value.files[0] e.target.value = null --> | |||
| <input | |||
| accept="audio/*" | |||
| type="file" | |||
| ref="fileInput" | |||
| @click="e.target.value = null" | |||
| @click="handleFileClick" | |||
| @change="handleFileChange" | |||
| /> | |||
| <div class="AudioBox" v-if="audioUrl && showAudioWhich == 1"> | |||
| <audio controls :src="audioUrl" id="uploadAudio"></audio> | |||
| </div> | |||
| </div> | |||
| <!-- 录制MP3上传语音 --> | |||
| <p> | |||
| <el-icon class="icon-Mic"><i-ep-Mic /></el-icon> | |||
| {{ $t("createVideo.recordedAudio") }} | |||
| </p> | |||
| <div class="uploadAudio"> | |||
| <div | |||
| class="uploadAudio" | |||
| :class=" | |||
| audioUrl && showAudioWhich == 2 ? 'uploadAudioAvtion' : '' | |||
| " | |||
| > | |||
| <div class="btnBox"> | |||
| <button | |||
| class="pointer" | |||
| @@ -412,10 +430,13 @@ | |||
| {{ $t("createVideo.stopRecorded") }} | |||
| </button> | |||
| </div> | |||
| <div class="AudioBox" v-if="audioUrl && showAudioWhich == 2"> | |||
| <audio controls :src="audioUrl" id="uploadAudio"></audio> | |||
| </div> | |||
| </div> | |||
| <div class="AudioBox" v-if="audioUrl"> | |||
| <!-- <div class="AudioBox" v-if="audioUrl"> | |||
| <audio controls :src="audioUrl" id="uploadAudio"></audio> | |||
| </div> | |||
| </div> --> | |||
| <!-- 保存视频 --> | |||
| <el-button | |||
| @click="saveOrUpdate(2, 'saveVideo')" | |||
| @@ -968,7 +989,7 @@ async function getPreviewAudio() { | |||
| if (!res.data.data) { | |||
| ElMessage.error( | |||
| lanChange.value == "zh-cn" | |||
| ? `暂时无法试听,请稍后重试1` | |||
| ? `暂时无法试听,请稍后重试` | |||
| : `Unable to listen, please try again later` | |||
| ); | |||
| previewAudioLoading.value = false; | |||
| @@ -984,7 +1005,7 @@ async function getPreviewAudio() { | |||
| } catch (error) { | |||
| ElMessage.error( | |||
| lanChange.value == "zh-cn" | |||
| ? `暂时无法试听,请稍后重试2` | |||
| ? `暂时无法试听,请稍后重试` | |||
| : `Unable to listen, please try again later` | |||
| ); | |||
| previewAudioLoading.value = false; | |||
| @@ -993,6 +1014,10 @@ async function getPreviewAudio() { | |||
| } | |||
| //#endregion | |||
| //#region card2的逻辑 | |||
| const showAudioWhich = ref(0); // 哪个音乐控件显示 | |||
| //#endregion ---------------------------- | |||
| //#region 录制MP3上传语音 | |||
| const parameter = { | |||
| sampleBits: 16, // 采样位数,支持 8 或 16,默认是16 | |||
| @@ -1006,6 +1031,11 @@ const audioData = ref(""); | |||
| const videoId = ref(null); //上传mp3的videoId,创建视频会用到 | |||
| const startRecording = async () => { | |||
| if (showAudioWhich.value != 2) { | |||
| audioUrl.value = null; | |||
| audioData.value = null; | |||
| showAudioWhich.value = 2; | |||
| } | |||
| try { | |||
| await recorder.start(); | |||
| console.log("Recording started"); | |||
| @@ -1021,7 +1051,7 @@ const stopRecording = async () => { | |||
| audioUrl.value = URL.createObjectURL(recorder.getWAVBlob()); | |||
| audioData.value = recorder.getWAVBlob(); | |||
| isRecording.value = true; | |||
| console.log(document.getElementById("uploadAudio").duration); | |||
| // console.log(document.getElementById("uploadAudio").duration); | |||
| } catch (error) { | |||
| console.error(error); | |||
| } | |||
| @@ -1066,7 +1096,17 @@ const fileInput = ref(null); | |||
| let intervalId = null; // 用于存储 setInterval 的返回值 | |||
| const uploadAudioTime = ref(null); // 音频时长 | |||
| // 点击上传input | |||
| function handleFileClick(e) { | |||
| showAudioWhich.value = 0; | |||
| audioUrl.value = null; | |||
| audioData.value = null; | |||
| e.target.value = null; | |||
| } | |||
| // 上传input触发change | |||
| const handleFileChange = async () => { | |||
| await stopRecording(); | |||
| showAudioWhich.value = 1; | |||
| const file = fileInput.value.files[0]; | |||
| if (file) { | |||
| @@ -1076,7 +1116,7 @@ const handleFileChange = async () => { | |||
| // 进行大小时长限制 | |||
| await countAudioTime(audio2); | |||
| // 限制60秒 | |||
| if (uploadAudioTime.value > 60) { | |||
| if (uploadAudioTime.value > 960) { | |||
| ElMessage.error( | |||
| lanChange.value == "zh-cn" | |||
| ? `上传失败,您上传的文件时长与您的权益不匹配` | |||
| @@ -1087,7 +1127,7 @@ const handleFileChange = async () => { | |||
| return; | |||
| } | |||
| // 限制3mb | |||
| if (file.size / 1048576 > 3) { | |||
| if (file.size / 1048576 > 93) { | |||
| ElMessage.error( | |||
| lanChange.value == "zh-cn" | |||
| ? `上传失败,您上传的文件大小与您的权益不匹配` | |||
| @@ -1619,8 +1659,8 @@ onUnmounted(() => { | |||
| <style lang="scss" scoped> | |||
| .page { | |||
| // height: 1000px; | |||
| height: calc(100vh - 80px); | |||
| height: 1000px; | |||
| height: calc(100vh - 80px); | |||
| // padding: 20px 0 0 40px; | |||
| background-color: #fff; | |||
| border-radius: 25px 0 0; | |||
| @@ -1630,7 +1670,10 @@ onUnmounted(() => { | |||
| width: 68%; | |||
| // height: 860px; | |||
| height: 1000px; | |||
| max-height: 100%; | |||
| padding: 20px; | |||
| overflow: hidden; | |||
| overflow-y: scroll; | |||
| :deep(.el-input__wrapper) { | |||
| border: none; | |||
| border-bottom: 2px solid #000; | |||
| @@ -1704,7 +1747,7 @@ onUnmounted(() => { | |||
| } | |||
| .trueImg { | |||
| position: relative; | |||
| top: 60px; | |||
| top: 4%; | |||
| width: 100px; | |||
| height: 100px; | |||
| border-radius: 50%; | |||
| @@ -1725,18 +1768,41 @@ onUnmounted(() => { | |||
| opacity: 0; | |||
| } | |||
| .upload { | |||
| top: 200px; | |||
| width: 100px; | |||
| height: 100px; | |||
| top: 30%; | |||
| width: 400px; | |||
| height: 200px; | |||
| padding-top: 10px; | |||
| font-size: 50px; | |||
| line-height: 100px; | |||
| text-align: center; | |||
| background-color: #ccc; | |||
| border-radius: 50%; | |||
| border-radius: 30px; | |||
| box-shadow: rgba(0, 0, 0, 0.3) 0px 0px 5px 5px; | |||
| p { | |||
| position: absolute; | |||
| top: 50%; | |||
| left: 50%; | |||
| transform: translate(-50%, -50%); | |||
| z-index: -1; | |||
| opacity: 0.1; | |||
| .el-icon { | |||
| width: 200px; | |||
| height: 200px; | |||
| font-size: 150px; | |||
| } | |||
| } | |||
| span { | |||
| display: block; | |||
| font-size: 16px; | |||
| font-weight: 900; | |||
| line-height: 16px; | |||
| text-align: center; | |||
| margin-bottom: 130px; | |||
| } | |||
| } | |||
| .falseImg { | |||
| top: 350px; | |||
| top: 75%; | |||
| // background-color: #795562; | |||
| display: flex; | |||
| justify-content: space-evenly; | |||
| @@ -1864,7 +1930,7 @@ onUnmounted(() => { | |||
| flex-wrap: wrap; | |||
| justify-content: flex-start; | |||
| width: 100%; | |||
| height: 180px; | |||
| height: 220px; | |||
| overflow-y: scroll; | |||
| .faceItem { | |||
| position: relative; | |||
| @@ -2040,12 +2106,14 @@ onUnmounted(() => { | |||
| width: 32%; | |||
| // height: 860px; | |||
| height: 1000px; | |||
| max-height: 100%; | |||
| padding: 30px 30px 20px 30px; | |||
| background-color: #f1f2f6; | |||
| border-radius: 30px 0 0 0; | |||
| position: relative; | |||
| z-index: 2; | |||
| overflow: hidden; | |||
| overflow-y: scroll; | |||
| .subscript { | |||
| position: absolute; | |||
| top: 30px; | |||
| @@ -2083,7 +2151,7 @@ onUnmounted(() => { | |||
| min-height: 100%; | |||
| padding: 20px 20px 0px 20px; | |||
| border-radius: 20px; | |||
| overflow-y: scroll; | |||
| .card1 { | |||
| .text { | |||
| padding: 10px; | |||
| @@ -2138,8 +2206,10 @@ onUnmounted(() => { | |||
| .card2 { | |||
| padding: 10px; | |||
| .el-icon { | |||
| flex: 1; | |||
| // color: red; | |||
| vertical-align: text-top; | |||
| transition: all 0.3s; | |||
| } | |||
| > div { | |||
| position: relative; | |||
| @@ -2154,6 +2224,7 @@ onUnmounted(() => { | |||
| transform: translateY(-10px); | |||
| } | |||
| } | |||
| // 录制mp3部分 | |||
| .uploadAudio { | |||
| padding: 20px; | |||
| // margin-top: 30px; | |||
| @@ -2186,34 +2257,35 @@ onUnmounted(() => { | |||
| .uploadAudioAvtion { | |||
| height: 170px; | |||
| } | |||
| .uploadAudioAvtion2 { | |||
| // height: 220px !important; | |||
| } | |||
| // 上传音频部分 | |||
| .uploadVideo { | |||
| display: flex; | |||
| justify-content: space-between; | |||
| align-items: center; | |||
| text-align: center; | |||
| margin-bottom: 20px; | |||
| height: 100px; | |||
| font-size: 50px; | |||
| font-weight: 700; | |||
| line-height: 100px; | |||
| transition: all 0.3s; | |||
| input { | |||
| position: absolute; | |||
| top: 0; | |||
| left: 0; | |||
| width: 100%; | |||
| height: 100%; | |||
| height: 100px; | |||
| opacity: 0; | |||
| } | |||
| video { | |||
| position: absolute; | |||
| top: 0; | |||
| left: 0; | |||
| z-index: -1; | |||
| width: 100%; | |||
| height: 100%; | |||
| cursor: pointer; | |||
| } | |||
| } | |||
| .AudioBox { | |||
| display: flex; | |||
| justify-content: space-around; | |||
| padding: 20px; | |||
| padding: 10px; | |||
| transition: all 0.3s; | |||
| } | |||
| > .el-button { | |||
| @@ -17,15 +17,22 @@ | |||
| :rules="loginRules" | |||
| class="login-form" | |||
| > | |||
| <div class="flex text-white items-center py-4"> | |||
| <span class="text-2xl flex-1 text-center">{{ | |||
| <div class="flex text-white items-center"> | |||
| <span class="flex-1 text-center">{{ | |||
| $t("login.title") + " " + $t("login.login") | |||
| }}</span> | |||
| <lang-select style="color: #fff" /> | |||
| <el-tooltip | |||
| class="box-item" | |||
| effect="dark" | |||
| :content="$t('navbar.LanguageChange')" | |||
| placement="top-start" | |||
| > | |||
| <lang-select class="navItem" style="color: #ffffff" /> | |||
| </el-tooltip> | |||
| </div> | |||
| <el-form-item prop="email"> | |||
| <div class="p-2 text-white"> | |||
| <div class="text-white"> | |||
| <svg-icon icon-class="user" /> | |||
| </div> | |||
| <el-input | |||
| @@ -39,7 +46,7 @@ | |||
| </el-form-item> | |||
| <el-form-item prop="password"> | |||
| <span class="p-2 text-white"> | |||
| <span class="text-white"> | |||
| <svg-icon icon-class="password" /> | |||
| </span> | |||
| <el-input | |||
| @@ -61,7 +68,7 @@ | |||
| <!-- 验证码 --> | |||
| <el-form-item prop="verifyCode"> | |||
| <span class="p-2 text-white"> | |||
| <span class="text-white"> | |||
| <svg-icon icon-class="verify_code" /> | |||
| </span> | |||
| <el-input | |||
| @@ -122,15 +129,22 @@ | |||
| :rules="loginRules" | |||
| class="login-form" | |||
| > | |||
| <div class="flex text-white items-center py-4"> | |||
| <span class="text-2xl flex-1 text-center">{{ | |||
| <div class="flex text-white items-center"> | |||
| <span class="flex-1 text-center">{{ | |||
| $t("login.title") + " " + $t("login.register") | |||
| }}</span> | |||
| <lang-select style="color: #fff" /> | |||
| <el-tooltip | |||
| class="box-item" | |||
| effect="dark" | |||
| :content="$t('navbar.LanguageChange')" | |||
| placement="top-start" | |||
| > | |||
| <lang-select class="navItem" style="color: #ffffff" /> | |||
| </el-tooltip> | |||
| </div> | |||
| <el-form-item prop="email"> | |||
| <div class="p-2 text-white"> | |||
| <div class="text-white"> | |||
| <svg-icon icon-class="user" /> | |||
| </div> | |||
| <el-input | |||
| @@ -144,7 +158,7 @@ | |||
| </el-form-item> | |||
| <el-form-item prop="password"> | |||
| <span class="p-2 text-white"> | |||
| <span class="text-white"> | |||
| <svg-icon icon-class="password" /> | |||
| </span> | |||
| <el-input | |||
| @@ -164,7 +178,7 @@ | |||
| </el-form-item> | |||
| <el-form-item prop="confirmPassword"> | |||
| <span class="p-2 text-white"> | |||
| <span class="text-white"> | |||
| <svg-icon icon-class="password" /> | |||
| </span> | |||
| <el-input | |||
| @@ -229,15 +243,22 @@ | |||
| :rules="loginRules" | |||
| class="login-form" | |||
| > | |||
| <div class="flex text-white items-center py-4"> | |||
| <span class="text-2xl flex-1 text-center">{{ | |||
| <div class="flex text-white items-center"> | |||
| <span class="flex-1 text-center">{{ | |||
| $t("login.title") + " " + $t("login.forgetPwdTitle") | |||
| }}</span> | |||
| <lang-select style="color: #fff" /> | |||
| <el-tooltip | |||
| class="box-item" | |||
| effect="dark" | |||
| :content="$t('navbar.LanguageChange')" | |||
| placement="top-start" | |||
| > | |||
| <lang-select class="navItem" style="color: #ffffff" /> | |||
| </el-tooltip> | |||
| </div> | |||
| <el-form-item prop="email"> | |||
| <div class="p-2 text-white"> | |||
| <div class="text-white"> | |||
| <svg-icon icon-class="user" /> | |||
| </div> | |||
| <el-input | |||
| @@ -290,15 +311,22 @@ | |||
| :rules="loginRules" | |||
| class="login-form" | |||
| > | |||
| <div class="flex text-white items-center py-4"> | |||
| <span class="text-2xl flex-1 text-center">{{ | |||
| <div class="flex text-white items-center"> | |||
| <span class="flex-1 text-center">{{ | |||
| $t("login.title") + " " + $t("login.resetPassword") | |||
| }}</span> | |||
| <lang-select style="color: #fff" /> | |||
| <el-tooltip | |||
| class="box-item" | |||
| effect="dark" | |||
| :content="$t('navbar.LanguageChange')" | |||
| placement="top-start" | |||
| > | |||
| <lang-select class="navItem" style="color: #ffffff" /> | |||
| </el-tooltip> | |||
| </div> | |||
| <el-form-item prop="oldPassword"> | |||
| <span class="p-2 text-white"> | |||
| <span class="text-white"> | |||
| <svg-icon icon-class="password" /> | |||
| </span> | |||
| <el-input | |||
| @@ -318,7 +346,7 @@ | |||
| </el-form-item> | |||
| <el-form-item prop="password"> | |||
| <span class="p-2 text-white"> | |||
| <span class="text-white"> | |||
| <svg-icon icon-class="password" /> | |||
| </span> | |||
| <el-input | |||
| @@ -338,7 +366,7 @@ | |||
| </el-form-item> | |||
| <el-form-item prop="confirmPassword4"> | |||
| <span class="p-2 text-white"> | |||
| <span class="text-white"> | |||
| <svg-icon icon-class="password" /> | |||
| </span> | |||
| <el-input | |||
| @@ -404,15 +432,22 @@ | |||
| :rules="loginRules" | |||
| class="login-form" | |||
| > | |||
| <div class="flex text-white items-center py-4"> | |||
| <span class="text-2xl flex-1 text-center">{{ | |||
| <div class="flex text-white items-center"> | |||
| <span class="flex-1 text-center">{{ | |||
| $t("login.title") + " " + $t("login.setNewPwd") | |||
| }}</span> | |||
| <lang-select style="color: #fff" /> | |||
| <el-tooltip | |||
| class="box-item" | |||
| effect="dark" | |||
| :content="$t('navbar.LanguageChange')" | |||
| placement="top-start" | |||
| > | |||
| <lang-select class="navItem" style="color: #ffffff" /> | |||
| </el-tooltip> | |||
| </div> | |||
| <el-form-item prop="newPwd"> | |||
| <div class="p-2 text-white"> | |||
| <div class="text-white"> | |||
| <svg-icon icon-class="password" /> | |||
| </div> | |||
| <el-input | |||
| @@ -432,7 +467,7 @@ | |||
| </span> | |||
| </el-form-item> | |||
| <el-form-item prop="confirmNewPwd"> | |||
| <div class="p-2 text-white"> | |||
| <div class="text-white"> | |||
| <svg-icon icon-class="password" /> | |||
| </div> | |||
| <el-input | |||
| @@ -1019,6 +1054,8 @@ onMounted(() => { | |||
| .login-container { | |||
| position: relative; | |||
| width: 100%; | |||
| // width: 1920px; | |||
| // height: 1080px; | |||
| min-height: 100%; | |||
| overflow: hidden; | |||
| // background-color: #2d3a4b; | |||
| @@ -1063,6 +1100,15 @@ onMounted(() => { | |||
| &:hover { | |||
| backdrop-filter: blur(7px); | |||
| } | |||
| .items-center { | |||
| padding: 20px; | |||
| font-size: 30px; | |||
| } | |||
| .el-form-item { | |||
| .text-white { | |||
| padding: 8px; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -169,6 +169,9 @@ | |||
| destroy-on-close | |||
| @close="closeInfoDialog" | |||
| > | |||
| <div class="LoadingBox" v-if="submitUserInfoLoading"> | |||
| <my-Loading-Icon v-if="submitUserInfoLoading"></my-Loading-Icon> | |||
| </div> | |||
| <el-row> | |||
| <el-col :span="4"> {{ $t("public.avatar") }}: </el-col> | |||
| <el-col :span="20"> | |||
| @@ -242,18 +245,23 @@ async function chooseImg(e) { | |||
| dialogAvatarData.value = null; | |||
| // 压缩配置 | |||
| const options = { | |||
| maxSizeMB: 2, // 最大压缩大小为 1MB | |||
| useWebWorker: true, // 使用 Web Worker 进行压缩,提高性能 | |||
| maxSizeMB: 2, // 最大压缩大小为 2MB | |||
| useWebWorker: false, // 使用 Web Worker 进行压缩,提高性能 | |||
| }; | |||
| const compressedFile = await imageCompression(e.target.files[0], options); | |||
| dialogAvatarUrl.value = URL.createObjectURL(compressedFile); | |||
| dialogAvatarData.value = compressedFile; | |||
| // 不压缩图片 | |||
| // dialogAvatarUrl.value = e.target.files[0]; | |||
| // dialogAvatarData.value = e.target.files[0]; | |||
| } else { | |||
| return; | |||
| } | |||
| } | |||
| const submitUserInfoLoading = ref(false); | |||
| // 上传编辑信息 | |||
| async function submitUserInfo() { | |||
| submitUserInfoLoading.value = true; | |||
| if (dialogAvatarData.value) { | |||
| let formData = new FormData(); | |||
| const timestamp = Date.now(); | |||
| @@ -270,6 +278,7 @@ async function submitUserInfo() { | |||
| ); | |||
| await userInfoPinia.getUserInfo(); | |||
| showEditInfoDialog.value = false; | |||
| submitUserInfoLoading.value = false; | |||
| router.go(0); | |||
| } catch (error) { | |||
| ElMessage.error( | |||
| @@ -277,6 +286,7 @@ async function submitUserInfo() { | |||
| ? `修改失败,请稍后重试` | |||
| : `The modification failed. Please try again later` | |||
| ); | |||
| submitUserInfoLoading.value = false; | |||
| } | |||
| } else { | |||
| const data = { | |||
| @@ -289,6 +299,7 @@ async function submitUserInfo() { | |||
| ); | |||
| await userInfoPinia.getUserInfo(); | |||
| showEditInfoDialog.value = false; | |||
| submitUserInfoLoading.value = false; | |||
| router.go(0); | |||
| } catch (error) { | |||
| ElMessage.error( | |||
| @@ -296,6 +307,7 @@ async function submitUserInfo() { | |||
| ? `修改失败,请稍后重试` | |||
| : `The modification failed. Please try again later` | |||
| ); | |||
| submitUserInfoLoading.value = false; | |||
| } | |||
| } | |||
| } | |||
| @@ -453,8 +465,9 @@ function routerTo(url) { | |||
| top: 50%; | |||
| left: 50%; | |||
| transform: translate(-50%, -50%); | |||
| max-width: 100%; | |||
| max-height: 100%; | |||
| width: 100%; | |||
| height: 100%; | |||
| object-fit: cover; | |||
| } | |||
| } | |||
| @@ -800,6 +813,20 @@ function routerTo(url) { | |||
| } | |||
| .editInfoDialog { | |||
| position: relative; | |||
| overflow: hidden; | |||
| .LoadingBox { | |||
| position: absolute; | |||
| top: 0; | |||
| left: 0; | |||
| width: 100%; | |||
| height: 100%; | |||
| z-index: 999; | |||
| opacity: 0.8; | |||
| border-radius: 30px; | |||
| padding-top: 150px; | |||
| background-color: #ccc; | |||
| } | |||
| .el-row { | |||
| display: flex; | |||
| justify-content: space-evenly; | |||