| @@ -5,6 +5,6 @@ NODE_ENV='development' | |||
| VITE_APP_TITLE = 'Metavatar-PC' | |||
| VITE_APP_PORT = 3000 | |||
| # VITE_APP_BASE_API = 'https://photo.metavatar.cc/C' | |||
| VITE_APP_BASE_API = 'https://phototest.metavatar.cc/C' | |||
| # VITE_APP_BASE_API = 'https://phototest.metavatar.cc/C/api' | |||
| @@ -5,5 +5,5 @@ NODE_ENV='production' | |||
| VITE_APP_TITLE = 'Metavatar-PC' | |||
| VITE_APP_PORT = 3000 | |||
| # VITE_APP_BASE_API = 'https://photo.metavatar.cc/C' | |||
| VITE_APP_BASE_API = 'https://photo.metavatar.cc/C' | |||
| # VITE_APP_BASE_API = 'https://photo.metavatar.cc/C/C' | |||
| @@ -1,7 +1,7 @@ | |||
| import request from "@/utils/request.js"; | |||
| /** | |||
| * @description 获取人脸列表 | |||
| * @description 获取系统人脸列表 | |||
| * @params pageNum, pageSize | |||
| * @returns data | |||
| */ | |||
| @@ -13,7 +13,7 @@ export function personPhotoList(pageNum, pageSize, sendType) { | |||
| } | |||
| /** | |||
| * @description 获取人脸列表 | |||
| * @description 获取个人人脸列表 | |||
| * @params pageNum, pageSize | |||
| * @returns data | |||
| */ | |||
| @@ -25,7 +25,7 @@ export function personPhotoUserListList(pageNum, pageSize, sendType) { | |||
| } | |||
| /** | |||
| * @description 上传图片 | |||
| * @description 保存图片 | |||
| * @params data | |||
| * @returns data | |||
| */ | |||
| @@ -61,6 +61,31 @@ export function delImgApi(id) { | |||
| }) | |||
| } | |||
| /** | |||
| * @description 检测图片是否敏感(百度) | |||
| * @params id | |||
| * @returns data | |||
| */ | |||
| export function checkPhotoApi(material) { | |||
| return request({ | |||
| url: `api/personPhoto/checkPhoto?material=${material}`, | |||
| method: 'get', | |||
| }) | |||
| } | |||
| /** | |||
| * @description 检测人脸(邃芒) | |||
| * @params id | |||
| * @returns data | |||
| */ | |||
| export function checkFaceApi(data) { | |||
| return request({ | |||
| url: `suimang/image_qualit`, | |||
| method: 'post', | |||
| data: { img: data } | |||
| }) | |||
| } | |||
| /** | |||
| * @description 上传音频 | |||
| * @params data | |||
| @@ -13,7 +13,10 @@ | |||
| ></path> | |||
| </svg> | |||
| </el-icon> | |||
| <span class="loadingText">{{ $t("myCreating.loading") }}</span> | |||
| <span class="loadingText" | |||
| ><span v-if="tips">{{ $t(`myCreating.${tips}`) }},</span | |||
| >{{ $t("myCreating.loading1") }}</span | |||
| > | |||
| </div> | |||
| </div> | |||
| </template> | |||
| @@ -27,6 +30,9 @@ const props = defineProps({ | |||
| isLoading: { | |||
| required: true, //是否必传 | |||
| }, | |||
| tips: { | |||
| required: false, //是否必传 | |||
| }, | |||
| }); | |||
| </script> | |||
| <style lang="scss" scoped> | |||
| @@ -96,6 +96,10 @@ export default { | |||
| delete: "Delete", | |||
| more: "More", | |||
| loading: "Loading , just a moment", | |||
| loading1: "just a moment", | |||
| sensitiveness: "Sensitive information is being tested", | |||
| chackFace: "Face detection in progress", | |||
| upLoadPictures: "Uploading pictures", | |||
| noList: "Nothing here. How about making one ?", | |||
| goCreate: "Go Create !", | |||
| manuscript: "Manuscript", | |||
| @@ -108,6 +112,7 @@ export default { | |||
| edit:'Edit', | |||
| upSharpness:'Upgrade image quality', | |||
| upSharpnessTips:'If you are satisfied with the preview, you can click here to improve the video sharpness ~', | |||
| freeUserTip:'Free user-generated videos are limited to 1 minute', | |||
| }, | |||
| // 个人账户 | |||
| @@ -95,7 +95,11 @@ export default { | |||
| download: "下载", | |||
| delete: "删除", | |||
| more: "更多", | |||
| loading: "加载中,请稍等哦", | |||
| loading: "加载中,请稍等", | |||
| loading1: "请稍等", | |||
| sensitiveness: "正在进行敏感信息检测", | |||
| chackFace: "正在进行人脸检测", | |||
| upLoadPictures: "正在上传图片", | |||
| noList: "暂无没有作品哦,快去尝试制作你的第一个视频吧!", | |||
| goCreate: "去创作", | |||
| manuscript: "草稿", | |||
| @@ -108,6 +112,7 @@ export default { | |||
| edit:'编辑', | |||
| upSharpness:'升级画质', | |||
| upSharpnessTips:'如果对预览效果满意,您可以点击此处来提升视频清晰度~', | |||
| freeUserTip:'免费用户生成视频时长限制为1分钟', | |||
| }, | |||
| // 个人账户 | |||
| @@ -2,7 +2,6 @@ | |||
| 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'] | |||
| @@ -271,7 +270,6 @@ 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']> | |||
| @@ -8,7 +8,9 @@ import { store } from '@/store/index'; // 因为不是在setup环境而是js | |||
| const userInfoPinia = userInfoModules(store); //pinia | |||
| // 开发环境需以 "/api" 拼接,其他环境需以 "/C" 拼接 | |||
| const env = process.env.NODE_ENV == 'development' ? "/api" : "/C" | |||
| // const env = process.env.NODE_ENV == 'development' ? "" : "" | |||
| // console.log(process.env.NODE_ENV, 'env') | |||
| console.log(env) | |||
| /** | |||
| @@ -77,6 +77,7 @@ | |||
| <my-loading | |||
| style="margin-top: 150px" | |||
| :isLoading="compressionImgLoad" | |||
| :tips="imgUploadTips" | |||
| ></my-loading> | |||
| <div v-if="!compressionImgLoad" class="trueImg inmiddle"> | |||
| <div class="imgBox"> | |||
| @@ -693,6 +694,8 @@ import { | |||
| personPhotoUserListList, | |||
| awsImgUpload, | |||
| delImgApi, | |||
| checkPhotoApi, | |||
| checkFaceApi, | |||
| videoUpload, | |||
| saveImgApi, | |||
| uploadProgressApi, | |||
| @@ -712,7 +715,8 @@ import { useI18n } from "vue-i18n"; | |||
| import Recorder from "js-audio-recorder"; //mp3插件 | |||
| import imageCompression from "browser-image-compression"; //压缩图片插件 | |||
| import { useRoute, useRouter } from "vue-router"; | |||
| import axios from "axios"; | |||
| import { loginApi } from "@/api/auth"; | |||
| //#endregion --------------------------------- | |||
| const route = useRoute(); | |||
| @@ -831,6 +835,7 @@ async function deleteFaceImg(id) { | |||
| //#endregion ------------------------------ | |||
| //#region 预览图片 | |||
| const imgUploadTips = ref(null); // 图片检测loading的文字提示 | |||
| const compressionImgLoad = ref(false); | |||
| async function lookImg(e) { | |||
| if (e.target.files[0]) { | |||
| @@ -842,20 +847,63 @@ async function lookImg(e) { | |||
| compressionImgLoad.value = true; | |||
| // 压缩配置 | |||
| const options = { | |||
| maxSizeMB: 2, // 最大压缩大小为 1MB | |||
| maxSizeMB: 4, // 最大压缩大小为 4MB | |||
| useWebWorker: true, // 使用 Web Worker 进行压缩,提高性能 | |||
| }; | |||
| const compressedFile = await imageCompression(e.target.files[0], options); | |||
| imgUrl.value = URL.createObjectURL(compressedFile); | |||
| imgData.value = compressedFile; | |||
| showUploadBtn.value = 4; | |||
| submitImgBtn.value = true; | |||
| compressionImgLoad.value = false; | |||
| await changeFile(); | |||
| imgUploadTips.value = "sensitiveness"; | |||
| try { | |||
| await getImageBase64(compressedFile).then(async (base64) => { | |||
| const res = await checkFaceApi(base64); | |||
| console.log(res); | |||
| // axios({ | |||
| // method: "post", | |||
| // url: "https://phototest.metavatar.cc/suimang/image_qualit", | |||
| // // headers: { | |||
| // // "content-type": "multipart/form-data", | |||
| // // token: AccessToken, | |||
| // // "Access-Control-Allow-Credentials": true, | |||
| // // }, | |||
| // data: { img: base64 }, | |||
| // }).then(async (res) => { | |||
| // // const res2 = await checkPhotoApi(compressedFile); | |||
| // // // const res = await checkFaceApi(compressedFile); | |||
| // // imgUrl.value = URL.createObjectURL(compressedFile); | |||
| // // imgData.value = compressedFile; | |||
| // // showUploadBtn.value = 4; | |||
| // // submitImgBtn.value = true; | |||
| // // compressionImgLoad.value = false; | |||
| // // await changeFile(); | |||
| // }); | |||
| }); | |||
| } catch (error) { | |||
| ElMessage.error( | |||
| lanChange.value == "zh-cn" | |||
| ? `图片涉及敏感内容,上传失败` | |||
| : `Image related to sensitive content, upload failed` | |||
| ); | |||
| showFace.value = 1; | |||
| showUploadBtn.value = 2; | |||
| compressionImgLoad.value = false; | |||
| imgUploadTips.value = null; | |||
| } | |||
| } else { | |||
| return; | |||
| } | |||
| } | |||
| // blob转base64 | |||
| function getImageBase64(blob) { | |||
| return new Promise((resolve, reject) => { | |||
| const reader = new FileReader(); | |||
| reader.readAsDataURL(blob); | |||
| reader.onload = () => { | |||
| const base64 = reader.result; | |||
| resolve(base64); | |||
| }; | |||
| reader.onerror = (error) => reject(error); | |||
| }); | |||
| } | |||
| //#endregion ------------------ | |||
| // 标题 | |||
| @@ -874,6 +922,7 @@ function chooSystemImg(params) { | |||
| } | |||
| // 上传图片 | |||
| async function changeFile() { | |||
| imgUploadTips.value = "upLoadPictures"; | |||
| compressionImgLoad.value = true; | |||
| showUploadBtn.value = 3; | |||
| imgUrl.value = URL.createObjectURL(imgData.value); | |||
| @@ -906,8 +955,10 @@ async function changeFile() { | |||
| submitImgBtn.value = false; | |||
| console.log(123654); | |||
| showUploadBtn.value = 1; | |||
| imgUploadTips.value = null; | |||
| } catch (error) { | |||
| ElMessage.error(error); | |||
| ElMessage.error(lanChange.value == "zh-cn" ? `上传失败` : `Upload failure`); | |||
| imgUploadTips.value = null; | |||
| } | |||
| } | |||
| // 点击个人仓库tab | |||
| @@ -1157,8 +1208,8 @@ const handleFileChange = async () => { | |||
| if (uploadAudioTime.value > 60) { | |||
| ElMessage.error( | |||
| lanChange.value == "zh-cn" | |||
| ? `上传失败,上传音频时长最多为60秒` | |||
| : `Description Failed to upload audio files. The maximum duration of uploading audio files is 60 seconds` | |||
| ? `上传失败,免费用户上传音频时长最多为60秒` | |||
| : `Upload failed, free users can upload audio for up to 60 seconds` | |||
| ); | |||
| audioUrl.value = null; | |||
| audioData.value = null; | |||
| @@ -1168,8 +1219,8 @@ const handleFileChange = async () => { | |||
| if (file.size / 1048576 > 3) { | |||
| ElMessage.error( | |||
| lanChange.value == "zh-cn" | |||
| ? `上传失败,上传音频大小最大为3MB` | |||
| : `Description Upload failed. The maximum size of uploaded audio is 3MB` | |||
| ? `上传失败,免费用户上传音频大小最大为3MB` | |||
| : `Failed to upload. The maximum size of audio uploaded by free users is 3MB` | |||
| ); | |||
| audioUrl.value = null; | |||
| audioData.value = null; | |||
| @@ -1509,8 +1560,8 @@ async function uploadMusic() { | |||
| if (uploadAudioTime.value > 60) { | |||
| ElMessage.error( | |||
| lanChange.value == "zh-cn" | |||
| ? `上传失败,上传音频时长最多为60秒` | |||
| : `Description Failed to upload audio files. The maximum duration of uploading audio files is 60 seconds` | |||
| ? `上传失败,免费用户上传音频时长最多为60秒` | |||
| : `Upload failed, free users can upload audio for up to 60 seconds` | |||
| ); | |||
| return; | |||
| } | |||
| @@ -1518,8 +1569,8 @@ async function uploadMusic() { | |||
| if (file.size / 1048576 > 3) { | |||
| ElMessage.error( | |||
| lanChange.value == "zh-cn" | |||
| ? `上传失败,上传音频大小最大为3MB` | |||
| : `Description Upload failed. The maximum size of uploaded audio is 3MB` | |||
| ? `上传失败,免费用户上传音频大小最大为3MB` | |||
| : `Failed to upload. The maximum size of audio uploaded by free users is 3MB` | |||
| ); | |||
| return; | |||
| } | |||
| @@ -126,6 +126,11 @@ | |||
| center | |||
| > | |||
| <div class="videoBox"> | |||
| <!-- 免费用户1分钟 --> | |||
| <div v-if="false" class="overtimeTips"> | |||
| <img src="../../assets/img/tips.png" alt="" /> | |||
| {{ $t("myCreating.freeUserTip") }} | |||
| </div> | |||
| <video | |||
| v-if="presentItem.videoPlayUrl" | |||
| controls="true" | |||
| @@ -706,6 +711,23 @@ onMounted(() => { | |||
| // justify-content: space-between; | |||
| width: 100%; | |||
| padding: 20px; | |||
| .overtimeTips { | |||
| // width: 60%; | |||
| // display: inline-block; | |||
| padding: 5px; | |||
| margin-bottom: 10px; | |||
| background-color: #ccc; | |||
| border-radius: 5px; | |||
| line-height: 20px; | |||
| color: #000; | |||
| text-align: center; | |||
| img { | |||
| width: 20px; | |||
| height: 20px; | |||
| vertical-align: middle; | |||
| margin-right: 5px; | |||
| } | |||
| } | |||
| video { | |||
| width: 100%; | |||
| max-height: 600px; | |||
| @@ -53,10 +53,32 @@ export default defineConfig(({ mode }: ConfigEnv): UserConfig => { | |||
| proxy: { | |||
| // 反向代理解决跨域 | |||
| "/api": { | |||
| // target: https://phototest.metavatar.cc/C, // 线上接口地址 | |||
| target: env.VITE_APP_BASE_API, // 线上接口地址 | |||
| changeOrigin: true, | |||
| rewrite: (path) => path.replace(/^\/api/, ""), | |||
| }, | |||
| "/api/suimang": { | |||
| // target: https://phototest.metavatar.cc/C, // 线上接口地址 | |||
| target:'https://phototest.metavatar.cc/', // 线上接口地址 | |||
| changeOrigin: true, | |||
| rewrite: (path) => path.replace(/^\/api\/suimang/, "/suimang"), | |||
| // pathRewrite: { | |||
| // "^/api/suimang": "/suimang", | |||
| // } | |||
| }, | |||
| "/suimang": { | |||
| // target: https://phototest.metavatar.cc/C, // 线上接口地址 | |||
| target:'https://phototest.metavatar.cc/', // 线上接口地址 | |||
| changeOrigin: true, | |||
| rewrite: (path) => path.replace(/^\/suimang/, '/suimang/image_qualit') | |||
| // pathRewrite: { | |||
| // "^/api/suimang": "/suimang", | |||
| // } | |||
| }, | |||
| }, | |||
| }, | |||
| plugins: [ | |||