@@ -5,6 +5,6 @@ NODE_ENV='development' | |||||
VITE_APP_TITLE = 'Metavatar-PC' | VITE_APP_TITLE = 'Metavatar-PC' | ||||
VITE_APP_PORT = 3000 | 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' | ||||
# VITE_APP_BASE_API = 'https://phototest.metavatar.cc/C/api' | |||||
@@ -5,5 +5,5 @@ NODE_ENV='production' | |||||
VITE_APP_TITLE = 'Metavatar-PC' | VITE_APP_TITLE = 'Metavatar-PC' | ||||
VITE_APP_PORT = 3000 | 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' | ||||
# VITE_APP_BASE_API = 'https://photo.metavatar.cc/C/C' |
@@ -1,7 +1,7 @@ | |||||
import request from "@/utils/request.js"; | import request from "@/utils/request.js"; | ||||
/** | /** | ||||
* @description 获取人脸列表 | |||||
* @description 获取系统人脸列表 | |||||
* @params pageNum, pageSize | * @params pageNum, pageSize | ||||
* @returns data | * @returns data | ||||
*/ | */ | ||||
@@ -13,7 +13,7 @@ export function personPhotoList(pageNum, pageSize, sendType) { | |||||
} | } | ||||
/** | /** | ||||
* @description 获取人脸列表 | |||||
* @description 获取个人人脸列表 | |||||
* @params pageNum, pageSize | * @params pageNum, pageSize | ||||
* @returns data | * @returns data | ||||
*/ | */ | ||||
@@ -25,7 +25,7 @@ export function personPhotoUserListList(pageNum, pageSize, sendType) { | |||||
} | } | ||||
/** | /** | ||||
* @description 上传图片 | |||||
* @description 保存图片 | |||||
* @params data | * @params data | ||||
* @returns 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 上传音频 | * @description 上传音频 | ||||
* @params data | * @params data | ||||
@@ -13,7 +13,10 @@ | |||||
></path> | ></path> | ||||
</svg> | </svg> | ||||
</el-icon> | </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> | ||||
</div> | </div> | ||||
</template> | </template> | ||||
@@ -27,6 +30,9 @@ const props = defineProps({ | |||||
isLoading: { | isLoading: { | ||||
required: true, //是否必传 | required: true, //是否必传 | ||||
}, | }, | ||||
tips: { | |||||
required: false, //是否必传 | |||||
}, | |||||
}); | }); | ||||
</script> | </script> | ||||
<style lang="scss" scoped> | <style lang="scss" scoped> | ||||
@@ -96,6 +96,10 @@ export default { | |||||
delete: "Delete", | delete: "Delete", | ||||
more: "More", | more: "More", | ||||
loading: "Loading , just a moment", | 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 ?", | noList: "Nothing here. How about making one ?", | ||||
goCreate: "Go Create !", | goCreate: "Go Create !", | ||||
manuscript: "Manuscript", | manuscript: "Manuscript", | ||||
@@ -108,6 +112,7 @@ export default { | |||||
edit:'Edit', | edit:'Edit', | ||||
upSharpness:'Upgrade image quality', | upSharpness:'Upgrade image quality', | ||||
upSharpnessTips:'If you are satisfied with the preview, you can click here to improve the video sharpness ~', | 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: "下载", | download: "下载", | ||||
delete: "删除", | delete: "删除", | ||||
more: "更多", | more: "更多", | ||||
loading: "加载中,请稍等哦", | |||||
loading: "加载中,请稍等", | |||||
loading1: "请稍等", | |||||
sensitiveness: "正在进行敏感信息检测", | |||||
chackFace: "正在进行人脸检测", | |||||
upLoadPictures: "正在上传图片", | |||||
noList: "暂无没有作品哦,快去尝试制作你的第一个视频吧!", | noList: "暂无没有作品哦,快去尝试制作你的第一个视频吧!", | ||||
goCreate: "去创作", | goCreate: "去创作", | ||||
manuscript: "草稿", | manuscript: "草稿", | ||||
@@ -108,6 +112,7 @@ export default { | |||||
edit:'编辑', | edit:'编辑', | ||||
upSharpness:'升级画质', | upSharpness:'升级画质', | ||||
upSharpnessTips:'如果对预览效果满意,您可以点击此处来提升视频清晰度~', | upSharpnessTips:'如果对预览效果满意,您可以点击此处来提升视频清晰度~', | ||||
freeUserTip:'免费用户生成视频时长限制为1分钟', | |||||
}, | }, | ||||
// 个人账户 | // 个人账户 | ||||
@@ -2,7 +2,6 @@ | |||||
export {} | export {} | ||||
declare global { | declare global { | ||||
const EffectScope: typeof import('vue')['EffectScope'] | const EffectScope: typeof import('vue')['EffectScope'] | ||||
const ElForm: typeof import('element-plus/es')['ElForm'] | |||||
const ElMessage: typeof import('element-plus/es')['ElMessage'] | const ElMessage: typeof import('element-plus/es')['ElMessage'] | ||||
const ElMessageBox: typeof import('element-plus/es')['ElMessageBox'] | const ElMessageBox: typeof import('element-plus/es')['ElMessageBox'] | ||||
const asyncComputed: typeof import('@vueuse/core')['asyncComputed'] | const asyncComputed: typeof import('@vueuse/core')['asyncComputed'] | ||||
@@ -271,7 +270,6 @@ import { UnwrapRef } from 'vue' | |||||
declare module 'vue' { | declare module 'vue' { | ||||
interface ComponentCustomProperties { | interface ComponentCustomProperties { | ||||
readonly EffectScope: UnwrapRef<typeof import('vue')['EffectScope']> | 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 ElMessage: UnwrapRef<typeof import('element-plus/es')['ElMessage']> | ||||
readonly ElMessageBox: UnwrapRef<typeof import('element-plus/es')['ElMessageBox']> | readonly ElMessageBox: UnwrapRef<typeof import('element-plus/es')['ElMessageBox']> | ||||
readonly asyncComputed: UnwrapRef<typeof import('@vueuse/core')['asyncComputed']> | readonly asyncComputed: UnwrapRef<typeof import('@vueuse/core')['asyncComputed']> | ||||
@@ -8,7 +8,9 @@ import { store } from '@/store/index'; // 因为不是在setup环境而是js | |||||
const userInfoPinia = userInfoModules(store); //pinia | const userInfoPinia = userInfoModules(store); //pinia | ||||
// 开发环境需以 "/api" 拼接,其他环境需以 "/C" 拼接 | // 开发环境需以 "/api" 拼接,其他环境需以 "/C" 拼接 | ||||
const env = process.env.NODE_ENV == 'development' ? "/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(process.env.NODE_ENV, 'env') | ||||
console.log(env) | |||||
/** | /** | ||||
@@ -77,6 +77,7 @@ | |||||
<my-loading | <my-loading | ||||
style="margin-top: 150px" | style="margin-top: 150px" | ||||
:isLoading="compressionImgLoad" | :isLoading="compressionImgLoad" | ||||
:tips="imgUploadTips" | |||||
></my-loading> | ></my-loading> | ||||
<div v-if="!compressionImgLoad" class="trueImg inmiddle"> | <div v-if="!compressionImgLoad" class="trueImg inmiddle"> | ||||
<div class="imgBox"> | <div class="imgBox"> | ||||
@@ -693,6 +694,8 @@ import { | |||||
personPhotoUserListList, | personPhotoUserListList, | ||||
awsImgUpload, | awsImgUpload, | ||||
delImgApi, | delImgApi, | ||||
checkPhotoApi, | |||||
checkFaceApi, | |||||
videoUpload, | videoUpload, | ||||
saveImgApi, | saveImgApi, | ||||
uploadProgressApi, | uploadProgressApi, | ||||
@@ -712,7 +715,8 @@ import { useI18n } from "vue-i18n"; | |||||
import Recorder from "js-audio-recorder"; //mp3插件 | import Recorder from "js-audio-recorder"; //mp3插件 | ||||
import imageCompression from "browser-image-compression"; //压缩图片插件 | import imageCompression from "browser-image-compression"; //压缩图片插件 | ||||
import { useRoute, useRouter } from "vue-router"; | import { useRoute, useRouter } from "vue-router"; | ||||
import axios from "axios"; | |||||
import { loginApi } from "@/api/auth"; | |||||
//#endregion --------------------------------- | //#endregion --------------------------------- | ||||
const route = useRoute(); | const route = useRoute(); | ||||
@@ -831,6 +835,7 @@ async function deleteFaceImg(id) { | |||||
//#endregion ------------------------------ | //#endregion ------------------------------ | ||||
//#region 预览图片 | //#region 预览图片 | ||||
const imgUploadTips = ref(null); // 图片检测loading的文字提示 | |||||
const compressionImgLoad = ref(false); | const compressionImgLoad = ref(false); | ||||
async function lookImg(e) { | async function lookImg(e) { | ||||
if (e.target.files[0]) { | if (e.target.files[0]) { | ||||
@@ -842,20 +847,63 @@ async function lookImg(e) { | |||||
compressionImgLoad.value = true; | compressionImgLoad.value = true; | ||||
// 压缩配置 | // 压缩配置 | ||||
const options = { | const options = { | ||||
maxSizeMB: 2, // 最大压缩大小为 1MB | |||||
maxSizeMB: 4, // 最大压缩大小为 4MB | |||||
useWebWorker: true, // 使用 Web Worker 进行压缩,提高性能 | useWebWorker: true, // 使用 Web Worker 进行压缩,提高性能 | ||||
}; | }; | ||||
const compressedFile = await imageCompression(e.target.files[0], options); | 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 { | } else { | ||||
return; | 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 ------------------ | //#endregion ------------------ | ||||
// 标题 | // 标题 | ||||
@@ -874,6 +922,7 @@ function chooSystemImg(params) { | |||||
} | } | ||||
// 上传图片 | // 上传图片 | ||||
async function changeFile() { | async function changeFile() { | ||||
imgUploadTips.value = "upLoadPictures"; | |||||
compressionImgLoad.value = true; | compressionImgLoad.value = true; | ||||
showUploadBtn.value = 3; | showUploadBtn.value = 3; | ||||
imgUrl.value = URL.createObjectURL(imgData.value); | imgUrl.value = URL.createObjectURL(imgData.value); | ||||
@@ -906,8 +955,10 @@ async function changeFile() { | |||||
submitImgBtn.value = false; | submitImgBtn.value = false; | ||||
console.log(123654); | console.log(123654); | ||||
showUploadBtn.value = 1; | showUploadBtn.value = 1; | ||||
imgUploadTips.value = null; | |||||
} catch (error) { | } catch (error) { | ||||
ElMessage.error(error); | |||||
ElMessage.error(lanChange.value == "zh-cn" ? `上传失败` : `Upload failure`); | |||||
imgUploadTips.value = null; | |||||
} | } | ||||
} | } | ||||
// 点击个人仓库tab | // 点击个人仓库tab | ||||
@@ -1157,8 +1208,8 @@ const handleFileChange = async () => { | |||||
if (uploadAudioTime.value > 60) { | if (uploadAudioTime.value > 60) { | ||||
ElMessage.error( | ElMessage.error( | ||||
lanChange.value == "zh-cn" | 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; | audioUrl.value = null; | ||||
audioData.value = null; | audioData.value = null; | ||||
@@ -1168,8 +1219,8 @@ const handleFileChange = async () => { | |||||
if (file.size / 1048576 > 3) { | if (file.size / 1048576 > 3) { | ||||
ElMessage.error( | ElMessage.error( | ||||
lanChange.value == "zh-cn" | 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; | audioUrl.value = null; | ||||
audioData.value = null; | audioData.value = null; | ||||
@@ -1509,8 +1560,8 @@ async function uploadMusic() { | |||||
if (uploadAudioTime.value > 60) { | if (uploadAudioTime.value > 60) { | ||||
ElMessage.error( | ElMessage.error( | ||||
lanChange.value == "zh-cn" | 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; | return; | ||||
} | } | ||||
@@ -1518,8 +1569,8 @@ async function uploadMusic() { | |||||
if (file.size / 1048576 > 3) { | if (file.size / 1048576 > 3) { | ||||
ElMessage.error( | ElMessage.error( | ||||
lanChange.value == "zh-cn" | 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; | return; | ||||
} | } | ||||
@@ -126,6 +126,11 @@ | |||||
center | center | ||||
> | > | ||||
<div class="videoBox"> | <div class="videoBox"> | ||||
<!-- 免费用户1分钟 --> | |||||
<div v-if="false" class="overtimeTips"> | |||||
<img src="../../assets/img/tips.png" alt="" /> | |||||
{{ $t("myCreating.freeUserTip") }} | |||||
</div> | |||||
<video | <video | ||||
v-if="presentItem.videoPlayUrl" | v-if="presentItem.videoPlayUrl" | ||||
controls="true" | controls="true" | ||||
@@ -706,6 +711,23 @@ onMounted(() => { | |||||
// justify-content: space-between; | // justify-content: space-between; | ||||
width: 100%; | width: 100%; | ||||
padding: 20px; | 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 { | video { | ||||
width: 100%; | width: 100%; | ||||
max-height: 600px; | max-height: 600px; | ||||
@@ -53,10 +53,32 @@ export default defineConfig(({ mode }: ConfigEnv): UserConfig => { | |||||
proxy: { | proxy: { | ||||
// 反向代理解决跨域 | // 反向代理解决跨域 | ||||
"/api": { | "/api": { | ||||
// target: https://phototest.metavatar.cc/C, // 线上接口地址 | |||||
target: env.VITE_APP_BASE_API, // 线上接口地址 | target: env.VITE_APP_BASE_API, // 线上接口地址 | ||||
changeOrigin: true, | changeOrigin: true, | ||||
rewrite: (path) => path.replace(/^\/api/, ""), | 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: [ | plugins: [ | ||||