|
@@ -0,0 +1,419 @@
|
|
|
+<template>
|
|
|
+ <!-- 换脸弹窗 -->
|
|
|
+ <a-modal
|
|
|
+ v-if="faceShowStatus"
|
|
|
+ title="换脸操作"
|
|
|
+ :visible="faceShowStatus"
|
|
|
+ :confirmLoading="confirmLoading"
|
|
|
+ dialog-class="change-face-modal"
|
|
|
+ @ok="handlePolicyOperationSure"
|
|
|
+ @cancel="handlePolicyOperationCancel"
|
|
|
+ >
|
|
|
+ <div class="face-right-div-p">
|
|
|
+ <a-radio-group v-model="faceType" button-style="solid" @change="handleFaceTypeChange">
|
|
|
+ <a-radio-button value="a">人脸合成</a-radio-button>
|
|
|
+ <a-radio-button value="b">合成列表</a-radio-button>
|
|
|
+ </a-radio-group>
|
|
|
+ <span v-if="faceType === 'b'" class="add-acount-policy-btn">
|
|
|
+ <a-button type="primary" @click="handleRefresh">刷新</a-button>
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ <a-form-model
|
|
|
+ v-if="faceType === 'a'"
|
|
|
+ class="policy-operation-form"
|
|
|
+ ref="policyOperationForm"
|
|
|
+ :model="policyOperationForm"
|
|
|
+ :label-col="labelCol"
|
|
|
+ :wrapper-col="wrapperCol"
|
|
|
+ >
|
|
|
+ <a-form-model-item label="图片上传">
|
|
|
+ <a-upload
|
|
|
+ name="avatar"
|
|
|
+ list-type="picture-card"
|
|
|
+ class="avatar-uploader"
|
|
|
+ :show-upload-list="false"
|
|
|
+ :before-upload="beforeUpload"
|
|
|
+ >
|
|
|
+ <div v-if="imageUrl" class="upload-img-class">
|
|
|
+ <div class="img-flex-url">
|
|
|
+ <img :src="imageUrl" alt="avatar"/>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div v-else>
|
|
|
+ <a-icon type="plus" style="margin-top: 10px;"/>
|
|
|
+ <div class="ant-upload-text">Upload</div>
|
|
|
+ </div>
|
|
|
+ </a-upload>
|
|
|
+ <p style="margin: 0;">1、请保证脸部无遮挡、光线充足</p>
|
|
|
+ <p style="margin: 0;">2、视频、照片中只能出现一张人脸</p>
|
|
|
+ </a-form-model-item>
|
|
|
+ </a-form-model>
|
|
|
+ <div v-else-if="faceType === 'b'" class="face-right-div">
|
|
|
+ <a-table
|
|
|
+ class="face-right-table"
|
|
|
+ ref="table"
|
|
|
+ size="middle"
|
|
|
+ bordered
|
|
|
+ :columns="settlementColumns"
|
|
|
+ :dataSource="dataSource"
|
|
|
+ :pagination="false"
|
|
|
+ >
|
|
|
+ <span slot="input_video_url" slot-scope="text, record">
|
|
|
+ <video :src="record.input_video_url" style="width:100px" controls></video>
|
|
|
+ </span>
|
|
|
+ <span slot="input_image_url" slot-scope="text, record">
|
|
|
+ <img v-if="text" :src="text" style="width:60px">
|
|
|
+ <img v-if="!text" src="@/assets/noImg.png" style="width:60px">
|
|
|
+ </span>
|
|
|
+ <span slot="actions" slot-scope="text, record">
|
|
|
+ <a :disabled="!faceShowList.projectId || record.status !== 'finished'" @click="handlePushData(record)">推送</a>
|
|
|
+ <a-divider type="vertical"/>
|
|
|
+ <a @click="handleDownLoadData(record)" :disabled="record.status !== 'finished'">下载</a>
|
|
|
+ </span>
|
|
|
+ </a-table>
|
|
|
+ <a-pagination
|
|
|
+ class="pagin-table-class"
|
|
|
+ :total="totalAll"
|
|
|
+ :show-total="total => `共 ${totalAll} 条`"
|
|
|
+ size="small"
|
|
|
+ :current="defaultCurrent"
|
|
|
+ :defaultPageSize="2"
|
|
|
+ @change="onShowSizeChange"
|
|
|
+ @showSizeChange="onShowSizeChange"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </a-modal>
|
|
|
+</template>
|
|
|
+<script>
|
|
|
+import {mapGetters} from 'vuex';
|
|
|
+import {fileInsertV2} from '@/api/actor';
|
|
|
+import {getAction, postAction} from '@/api/manage';
|
|
|
+
|
|
|
+import BMF from 'browser-md5-file';
|
|
|
+let COS = require('cos-js-sdk-v5');
|
|
|
+let cos = new COS({
|
|
|
+ SecretId: 'AKIDE6IpMi8fJQRCg1iuWzFajjRs43kbbets',
|
|
|
+ SecretKey: 'tXzuwMfplTTK3c9GFUyETilasvQfePu9'
|
|
|
+});
|
|
|
+
|
|
|
+export default {
|
|
|
+ name: 'change-face',
|
|
|
+ props: {
|
|
|
+ status: {
|
|
|
+ type: Boolean,
|
|
|
+ default: false
|
|
|
+ },
|
|
|
+ defaultList: {
|
|
|
+ type: Object,
|
|
|
+ default: () => {}
|
|
|
+ }
|
|
|
+ },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ confirmLoading: false,
|
|
|
+ departValueInfoModality: [],
|
|
|
+ departValueInfoMod: [],
|
|
|
+ departValueInfoSence: [],
|
|
|
+ getProjectId: '',
|
|
|
+ defaultCurrent: 1,
|
|
|
+ dataAllList: [],
|
|
|
+ totalAll: 0,
|
|
|
+ uploadType: 'face',
|
|
|
+ dataSource: [],
|
|
|
+ settlementColumns: [
|
|
|
+ {
|
|
|
+ title: '视频',
|
|
|
+ dataIndex: 'input_video_url',
|
|
|
+ align: 'center',
|
|
|
+ width: 150,
|
|
|
+ scopedSlots: {customRender: 'input_video_url'}
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '人脸',
|
|
|
+ dataIndex: 'input_image_url',
|
|
|
+ align: 'center',
|
|
|
+ width: 150,
|
|
|
+ scopedSlots: {customRender: 'input_image_url'}
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '状态',
|
|
|
+ align: 'center',
|
|
|
+ dataIndex: 'status',
|
|
|
+ width: 100
|
|
|
+ },
|
|
|
+ {
|
|
|
+ title: '操作',
|
|
|
+ align: 'center',
|
|
|
+ dataIndex: 'actions',
|
|
|
+ width: 130,
|
|
|
+ scopedSlots: {customRender: 'actions'}
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ labelCol: {span: 4},
|
|
|
+ wrapperCol: {span: 16},
|
|
|
+ imageUrl: '',
|
|
|
+ faceShowStatus: false,
|
|
|
+ faceType: 'a',
|
|
|
+ policyOperationForm: {},
|
|
|
+ urlResult: '',
|
|
|
+ md5Result: ''
|
|
|
+ };
|
|
|
+ },
|
|
|
+ watch: {
|
|
|
+ status(newVal) {
|
|
|
+ this.faceShowStatus = newVal;
|
|
|
+ },
|
|
|
+ defaultList(newVal) {
|
|
|
+ if (newVal) {
|
|
|
+ this.faceShowList = newVal;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ ...mapGetters(['userInfo']),
|
|
|
+ // 分页操作按钮
|
|
|
+ onShowSizeChange(current, pageSize) {
|
|
|
+ this.defaultCurrent = current;
|
|
|
+ const defaultData = [...this.dataAllList];
|
|
|
+ this.dataSource = [...defaultData.slice(2 * current - 2, 2 * current)];
|
|
|
+ },
|
|
|
+ handleFaceTypeChange(e) {
|
|
|
+ if (e.target.value === 'b') {
|
|
|
+ this.handleInitTable();
|
|
|
+ this.handleGetMaterialTagInfo();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ handleInitTable() {
|
|
|
+ const paramsData = {
|
|
|
+ videoMd5: this.faceShowList.projectId ? this.faceShowList.code : this.faceShowList.videoCode
|
|
|
+ };
|
|
|
+ // http://192.168.1.34:8000
|
|
|
+ // http://faceswap.tjyourong.com.cn
|
|
|
+ postAction('http://faceswap.tjyourong.com.cn/jeecg-boot/task/query', paramsData).then(result => {
|
|
|
+ if (result.code === 0) {
|
|
|
+ this.dataAllList = result.data;
|
|
|
+ this.dataSource = result.data.slice(0, 2);
|
|
|
+ this.totalAll = result.data.length ? result.data.length : 0;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ this.$message.error(result.message);
|
|
|
+ }
|
|
|
+ }).catch(error => {
|
|
|
+ console.log(error, 'eeee');
|
|
|
+ });
|
|
|
+ },
|
|
|
+ handleGetDetailList() {
|
|
|
+ getAction('/ctop/materialInfo/queryById', {
|
|
|
+ id: this.faceShowList.projectId ? this.faceShowList.code : this.faceShowList.videoCode
|
|
|
+ }).then(res => {
|
|
|
+ if (res.success) {
|
|
|
+ this.getProjectId = res.result.projectId;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+ handleGetMaterialTagInfo() {
|
|
|
+ getAction('/ctop/materialTagInfo/detail', {
|
|
|
+ code: this.faceShowList.projectId ? this.faceShowList.code : this.faceShowList.videoCode
|
|
|
+ }).then(res => {
|
|
|
+ if (res.success) {
|
|
|
+ this.departValueInfoModality = res.modalityTagList.map(item => item.tagId);
|
|
|
+ this.departValueInfoMod = res.modTagList.map(item => item.tagId);
|
|
|
+ this.departValueInfoSence = res.senceTagList.map(item => item.tagId);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+ // TODO 推送操作
|
|
|
+ handlePushData(list) {
|
|
|
+ const paramsData = {
|
|
|
+ projectId: this.faceShowList.projectId, // 项目选择
|
|
|
+ ascription: {
|
|
|
+ planId: 'e9ca23d68d884d4ebb19d07889727dae',
|
|
|
+ shotId: 'e9ca23d68d884d4ebb19d07889727dae',
|
|
|
+ clipId: 'e9ca23d68d884d4ebb19d07889727dae'
|
|
|
+ },
|
|
|
+ status: '1',
|
|
|
+ code: list.output_video_md5,
|
|
|
+ url: list.output_video_url && list.output_video_url.split(':')[1],
|
|
|
+ type: 'VIDEO',
|
|
|
+ userId: this.userInfo().id,
|
|
|
+ modalityTagList: this.departValueInfoModality, // 形式标签
|
|
|
+ senceTagList: this.departValueInfoSence, // 场景标签
|
|
|
+ modTagList: this.departValueInfoMod // 基调标签
|
|
|
+ };
|
|
|
+ const that = this;
|
|
|
+ this.$confirm({
|
|
|
+ title: '提示',
|
|
|
+ content: '是否进行推送操作',
|
|
|
+ onOk() {
|
|
|
+ fileInsertV2(paramsData).then(res => {
|
|
|
+ if (res.code === 0) {
|
|
|
+ that.handlePolicyOperationCancel();
|
|
|
+ that.$emit('sureface');
|
|
|
+ that.$message.success('素材已经同步到未审核列表,请进入查看');
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ that.$message.error(res.message);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+ // 下载操作
|
|
|
+ handleDownLoadData(list) {
|
|
|
+ const randomTime = new Date().getTime() + '_check.mp4';
|
|
|
+ fetch(list.output_video_url)
|
|
|
+ .then(res => res.blob())
|
|
|
+ .then(blob => {
|
|
|
+ const a = document.createElement('a');
|
|
|
+ document.body.appendChild(a);
|
|
|
+ a.style.display = 'none';
|
|
|
+ // 使用获取到的blob对象创建的url
|
|
|
+ const url = window.URL.createObjectURL(blob);
|
|
|
+ a.href = url;
|
|
|
+ // 指定下载的文件名
|
|
|
+ a.download = randomTime;
|
|
|
+ a.click()
|
|
|
+ document.body.removeChild(a);
|
|
|
+ // 移除blob对象的url
|
|
|
+ window.URL.revokeObjectURL(url);
|
|
|
+ });
|
|
|
+ },
|
|
|
+ // 刷新按钮
|
|
|
+ handleRefresh() {
|
|
|
+ this.defaultCurrent = 1;
|
|
|
+ this.handleInitTable();
|
|
|
+ },
|
|
|
+ checkTv(data) {
|
|
|
+ const index = data.lastIndexOf(".");
|
|
|
+ let tv_id = '';
|
|
|
+ tv_id = data.substring(index);
|
|
|
+ if(tv_id !== ".mp4" && tv_id !== ".rmvb" && tv_id !== ".avi" && tv_id !== ".ts") {
|
|
|
+ return data + '.mp4';
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ return data;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 确定按钮
|
|
|
+ handlePolicyOperationSure() {
|
|
|
+ if (this.faceType === 'a') {
|
|
|
+ this.confirmLoading = true;
|
|
|
+ if (!this.md5Result) {
|
|
|
+ this.$message.error('请上传图片');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ const paramsData = {
|
|
|
+ inputVideoUrl: this.checkTv(this.faceShowList.url),
|
|
|
+ inputImageUrl: this.urlResult,
|
|
|
+ videoMd5: this.faceShowList.projectId ? this.faceShowList.code : this.faceShowList.videoCode,
|
|
|
+ imageMd5: this.md5Result,
|
|
|
+ createBy: this.userInfo().id
|
|
|
+ };
|
|
|
+ postAction('http://faceswap.tjyourong.com.cn/jeecg-boot/task/single', paramsData).then(result => {
|
|
|
+ if (result.code === 0) {
|
|
|
+ this.handlePolicyOperationCancel();
|
|
|
+ this.$emit('sureface');
|
|
|
+ this.$message.success('图片上传成功');
|
|
|
+ this.confirmLoading = false;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ this.$message.success('目标图片已存在,请下载视频');
|
|
|
+ this.faceType = 'b';
|
|
|
+ this.handleInitTable();
|
|
|
+ this.handleGetMaterialTagInfo();
|
|
|
+ this.confirmLoading = false;
|
|
|
+ }
|
|
|
+ }).catch(error => {
|
|
|
+ console.log(error, 'eeee');
|
|
|
+ this.confirmLoading = false;
|
|
|
+ });
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ this.handlePolicyOperationCancel();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 取消按钮
|
|
|
+ handlePolicyOperationCancel() {
|
|
|
+ this.faceType = 'a';
|
|
|
+ this.imageUrl = '';
|
|
|
+ this.urlResult = '';
|
|
|
+ this.md5Result = '';
|
|
|
+ this.$emit('closeface');
|
|
|
+ },
|
|
|
+ getBase64(img, callback) {
|
|
|
+ const reader = new FileReader();
|
|
|
+ reader.addEventListener('load', () => callback(reader.result));
|
|
|
+ reader.readAsDataURL(img);
|
|
|
+ },
|
|
|
+ beforeUpload(info) {
|
|
|
+ const isZip = info.type.includes('png') || info.type.includes('jpeg');
|
|
|
+ if (!isZip) {
|
|
|
+ this.$message.error('请上传正确类型的图片');
|
|
|
+ this.imageUrl = '';
|
|
|
+ this.urlResult = '';
|
|
|
+ this.md5Result = '';
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this.handleMd5(info);
|
|
|
+ this.cosUpload(info);
|
|
|
+ this.getBase64(info, imageUrl => {
|
|
|
+ this.imageUrl = imageUrl;
|
|
|
+ });
|
|
|
+ },
|
|
|
+ handleMd5(file) {
|
|
|
+ let bmf = new BMF();
|
|
|
+ let that = this;
|
|
|
+ return new Promise(function (resolve, reject) {
|
|
|
+ bmf.md5(file, (err, md5) => {
|
|
|
+ that.md5Result = md5;
|
|
|
+ });
|
|
|
+ });
|
|
|
+ },
|
|
|
+ cosUpload(file) {
|
|
|
+ let that = this;
|
|
|
+ let date = new Date();
|
|
|
+ let y = date.getFullYear();
|
|
|
+ let MM = date.getMonth() + 1;
|
|
|
+ MM = MM < 10 ? '0' + MM : MM;
|
|
|
+ let d = date.getDate();
|
|
|
+ d = d < 10 ? '0' + d : d;
|
|
|
+ let timeElse = new Date().getTime();
|
|
|
+ let arr = file.name.split('.');
|
|
|
+ let str = '';
|
|
|
+ for (let i = 0; i < arr.length; i++) {
|
|
|
+ if (i === arr.length - 1) {
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ if (i === arr.length - 2) {
|
|
|
+ str += arr[i];
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ str += arr[i] + '.';
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ cos.putObject(
|
|
|
+ {
|
|
|
+ Bucket: 'media-1301855440',
|
|
|
+ Region: 'ap-chongqing',
|
|
|
+ // 存储桶所在地域,必须字段
|
|
|
+ Key: that.uploadType + '/' + y + '-' + MM + '-' + d + '/' + str + '-' + timeElse + '.' + arr[arr.length - 1],
|
|
|
+ StorageClass: 'STANDARD',
|
|
|
+ Body: file // 上传文件对象
|
|
|
+ },
|
|
|
+ function (err, data) {
|
|
|
+ if (err) {
|
|
|
+ that.$message.error('上传失败!!!' + err);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ that.loadingElse = false;
|
|
|
+ that.urlResult = 'http://' + data.Location;
|
|
|
+ }
|
|
|
+ );
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+<style lang="less">
|
|
|
+ @import "change-face";
|
|
|
+</style>
|