From 09cd9c30b4ddf4b29365c2d8693b2a2f0726552d Mon Sep 17 00:00:00 2001 From: du <13220750630.163.com> Date: 星期二, 10 六月 2025 10:51:07 +0800 Subject: [PATCH] 模板中心的新增弹窗的修改 --- easegen-front/package.json | 1 easegen-front/src/assets/imgs/1.png | 0 easegen-front/src/assets/imgs/2.png | 0 easegen-front/src/views/digitalcourse/template/TemplateForm.vue | 459 ++++++++++++++++++++++++++++++++++++-------------------- easegen-front/src/views/digitalcourse/digitalhumans/AuditForm.vue | 18 +- 5 files changed, 305 insertions(+), 173 deletions(-) diff --git a/easegen-front/package.json b/easegen-front/package.json index 6444f0a..943e5da 100644 --- a/easegen-front/package.json +++ b/easegen-front/package.json @@ -57,6 +57,7 @@ "face-api.js": "^0.22.2", "fast-xml-parser": "^4.3.2", "highlight.js": "^11.9.0", + "html2canvas": "^1.4.1", "jsencrypt": "^3.3.2", "lodash-es": "^4.17.21", "markdown-it": "^14.1.0", diff --git a/easegen-front/src/assets/imgs/1.png b/easegen-front/src/assets/imgs/1.png new file mode 100644 index 0000000..fce48cf --- /dev/null +++ b/easegen-front/src/assets/imgs/1.png Binary files differ diff --git a/easegen-front/src/assets/imgs/2.png b/easegen-front/src/assets/imgs/2.png new file mode 100644 index 0000000..92fc48a --- /dev/null +++ b/easegen-front/src/assets/imgs/2.png Binary files differ diff --git a/easegen-front/src/views/digitalcourse/digitalhumans/AuditForm.vue b/easegen-front/src/views/digitalcourse/digitalhumans/AuditForm.vue index d3a1916..86bd4e1 100644 --- a/easegen-front/src/views/digitalcourse/digitalhumans/AuditForm.vue +++ b/easegen-front/src/views/digitalcourse/digitalhumans/AuditForm.vue @@ -18,8 +18,8 @@ </el-form-item> <el-form-item v-if="(formData.useModel == 2 || formData.useModel == 3) && !(formData.videoUrl || formData.fixVideoUrl) " :label="t('digitalhumans.video')" prop="videoUrl"> <UploadFile v-if="!(formData.videoUrl || formData.fixVideoUrl)" v-model="formData.videoUrl" :fileType="['mp4']" :limit="1" @on-success="handleFileSuccess('fixVideoUrl', $event)"/> - - + + <!-- 鎾斁mov瑙嗛 --> <!-- 涓嬮潰鐨勬槸鍘熸湰鐨� --> @@ -63,11 +63,11 @@ </el-input> <!-- 淇濈暀鍘熸湁鐨勪笂浼犲姛鑳� --> <div class="text-gray-500 text-sm">{{ t('digitalhumans.orUploadVideo') }}</div> - <UploadFile - v-model="formData.fixVideoUrl" - :fileType="['mp4','mov']" - :limit="1" - :file-size="1024" + <UploadFile + v-model="formData.fixVideoUrl" + :fileType="['mp4','mov']" + :limit="1" + :file-size="1024" @on-success="handleFileSuccess('fixVideoUrl', $event)" /> </div> @@ -181,7 +181,7 @@ message.warning(t('digitalhumans.pleaseInputVideoUrl')) return } - + // 楠岃瘉URL鏍煎紡 try { new URL(formData.value.fixVideoUrl) @@ -216,7 +216,7 @@ message.success(t('common.createSuccess')) } else { await DigitalHumansApi.updateDigitalHumans(data) - message.success(t('common.updateSuccess')) + message.success('寮�濮嬪彈鐞�') } dialogVisible.value = false // 鍙戦�佹搷浣滄垚鍔熺殑浜嬩欢 diff --git a/easegen-front/src/views/digitalcourse/template/TemplateForm.vue b/easegen-front/src/views/digitalcourse/template/TemplateForm.vue index c353bee..b877e91 100644 --- a/easegen-front/src/views/digitalcourse/template/TemplateForm.vue +++ b/easegen-front/src/views/digitalcourse/template/TemplateForm.vue @@ -5,117 +5,34 @@ :model="formData" :rules="formRules" label-width="200px" - v-loading="formLoading" - > + v-loading="formLoading"> <el-row> <el-col :span="12"> - <el-form-item :label="t('template.name')" prop="templateName"> - <el-input v-model="formData.templateName" maxlength="50" :placeholder="t('common.inputText') + t('template.name')" /> + <el-form-item label="妯℃澘鍚嶇О" prop="templateName"> + <el-input v-model="formData.templateName" maxlength="50" placeholder="璇疯緭鍏ユā鏉垮悕绉�" /> </el-form-item> </el-col> <el-col :span="12"> - <el-form-item :label="t('template.isShowBackground')" prop="showBackground"> - <el-select v-model="formData.showBackground" :placeholder="t('common.selectText') + t('template.isShowBackground')"> - <el-option - v-for="dict in getIntDictOptions(DICT_TYPE.IS_OR_NOT)" - :key="dict.value" - :label="dict.label" - :value="dict.value" - /> - </el-select> - </el-form-item> - </el-col> - </el-row> - <el-row> - <el-col :span="12"> - <el-form-item :label="t('template.isShowDigitalPeople')" prop="showDigitalHuman"> - <el-select v-model="formData.showDigitalHuman" :placeholder="t('common.selectText') + t('template.isShowDigitalPeople')"> - <el-option - v-for="dict in getIntDictOptions(DICT_TYPE.IS_OR_NOT)" - :key="dict.value" - :label="dict.label" - :value="dict.value" - /> - </el-select> - </el-form-item> - </el-col> - <el-col :span="12"> - <el-form-item :label="t('template.isShowPPt')" prop="showPpt"> - <el-select v-model="formData.showPpt" :placeholder="t('common.selectText') + t('template.isShowPPt')"> - <el-option - v-for="dict in getIntDictOptions(DICT_TYPE.IS_OR_NOT)" - :key="dict.value" - :label="dict.label" - :value="dict.value" - /> - </el-select> - </el-form-item> - </el-col> - </el-row> - <el-row> - <el-col :span="24"> - <el-form-item :label="t('template.templateSize')" prop="templateSize"> - <el-select - style="width: 100%" - v-model="formData.templateSize" - clearable - :placeholder="t('common.selectText') + t('template.templateSize')" - class="!w-240px" - @change="changeTemplateSize" + <el-form-item label="鑳屾櫙鍥剧墖" prop="templateName"> + <el-upload + v-model:file-list="fileList" + class="upload-demo" + :action="getUploadUrl" + :auto-upload="false" + :limit="2" + :on-exceed="handleExceed" + :before-upload="beforeUpload" + :on-change="handleChange" + accept="image/*" + :show-file-list="false" > - <el-option - v-for="dict in getStrDictOptions(DICT_TYPE.TEMPLATE_SIZE)" - :key="dict.value" - :label="dict.label" - :value="dict.value" - /> - </el-select> - </el-form-item> - </el-col> - <el-col :span="12"> - <el-form-item :label="t('template.pptWidth')" prop="pptW"> - <el-input type="number" v-model="formData.pptW" :placeholder="t('common.inputText') + t('template.pptWidth')" /> - </el-form-item> - </el-col> - <el-col :span="12"> - <el-form-item :label="t('template.pptHeight')" prop="pptH"> - <el-input type="number" v-model="formData.pptH" :placeholder="t('common.inputText') + t('template.pptHeight')" /> - </el-form-item> - </el-col> - </el-row> - <el-row> - <el-col :span="12"> - <el-form-item :label="t('template.leftPositionPPT')" prop="pptX"> - <el-input type="number" v-model="formData.pptX" :placeholder="t('common.inputText') + t('template.topPositionPPT')" /> - </el-form-item> - </el-col> - <el-col :span="12"> - <el-form-item :label="t('template.topPositionPPT')" prop="pptY"> - <el-input type="number" v-model="formData.pptY" :placeholder="t('common.inputText') + t('template.leftPositionPPT')" /> - </el-form-item> - </el-col> - </el-row> - <el-row> - <el-col :span="12"> - <el-form-item :label="t('template.digitalPeopleWidth')" prop="humanW"> - <el-input type="number" disabled v-model="formData.humanW" :placeholder="t('common.inputText') + t('template.digitalPeopleWidth')" /> - </el-form-item> - </el-col> - <el-col :span="12"> - <el-form-item :label="t('template.digitalPeopleHeight')" prop="humanH"> - <el-input type="number" disabled v-model="formData.humanH" :placeholder="t('common.inputText') + t('template.digitalPeopleHeight')" /> - </el-form-item> - </el-col> - </el-row> - <el-row> - <el-col :span="12"> - <el-form-item :label="t('template.leftPositionDigitalPeople')" prop="humanX"> - <el-input type="number" v-model="formData.humanX" :placeholder="t('common.inputText') + t('template.topPositionDigitalPeople')" /> - </el-form-item> - </el-col> - <el-col :span="12"> - <el-form-item :label="t('template.topPositionDigitalPeople')" prop="humanY"> - <el-input type="number" v-model="formData.humanY" :placeholder="t('common.inputText') + t('template.leftPositionDigitalPeople')" /> + <el-button type="primary">涓婁紶鍥剧墖</el-button> + <template #tip> + <div class="el-upload__tip"> + 鍙兘涓婁紶jpg/png鏂囦欢 + </div> + </template> + </el-upload> </el-form-item> </el-col> </el-row> @@ -130,18 +47,72 @@ </el-col> </el-row> <el-row> - <el-col :span="12"> - <el-form-item :label="t('template.backgroundImage')" prop="bgImage"> - <UploadImg v-model="formData.bgImage" /> - </el-form-item> + <el-col :span="18"> + <div ref="captureElement" style="width: 802px; height: 452px;border: 1px solid #C0C0C0;box-sizing: border-box;position: relative"> + <img :src="lastUploadedFileUrl" style="width: 100%; height: 100%" v-if="lastUploadedFileUrl!=''" /> + <Vue3DraggableResizable + v-if="isChecked1" + :w="640" + :h="360" + :x="349" + :y="92" + v-model:w="formData.humanW" + v-model:h="formData.humanH" + v-model:x="formData.humanX" + v-model:y="formData.humanY" + :lock-aspect-ratio="true" + :minW="350" + > + <img + src="@/assets/imgs/1.png" + style="width: 100%; height: 100%; object-fit: contain;" + /> + </Vue3DraggableResizable> + <Vue3DraggableResizable + v-if="isChecked" + :w="505" + :h="290" + :x="40" + :y="50" + v-model:w="formData.pptW" + v-model:h="formData.pptH" + v-model:x="formData.pptX" + v-model:y="formData.pptY" + :lock-aspect-ratio="false" + :parent="true" + :minW="350" + > + <img + src="@/assets/imgs/2.png" + style="width: 100%; height: 100%; object-fit: cover;" + /> + </Vue3DraggableResizable> + + </div> </el-col> - <el-col :span="12"> - <el-form-item :label="t('template.reviewImage')" prop="previewImage"> - <UploadImg v-model="formData.previewImage" /> - </el-form-item> + <el-col :span="6"> + <div style="width: 100%;height: 452px;border: 1px solid #C0C0C0;box-sizing: border-box"> + <div class="image-checkbox-wrapper" @click="toggleCheck"> + <img src="@/assets/imgs/2.png" alt="ppt绀轰緥鍥剧墖" class="checkbox-image" /> + <input + type="checkbox" + v-model="isChecked" + class="checkbox-input" + @click.stop + /> + </div> + <div class="image-checkbox-wrapper" @click="toggleCheck1"> + <img src="@/assets/imgs/1.png" alt="鏁板瓧浜虹ず渚嬪浘鐗�" class="checkbox-image" /> + <input + type="checkbox" + v-model="isChecked1" + class="checkbox-input" + @click.stop + /> + </div> + </div> </el-col> </el-row> - </el-form> <template #footer> <el-button @click="submitForm" type="primary" :disabled="formLoading">{{ t('common.ok') }}</el-button> @@ -153,8 +124,77 @@ import { TemplateApi, TemplateVO } from '@/api/digitalcourse/template' import { DICT_TYPE, getIntDictOptions, getStrDictOptions } from '@/utils/dict' import {getUserProfile} from "@/api/system/user/profile"; +import html2canvas from 'html2canvas'; /** 妯℃澘 琛ㄥ崟 */ defineOptions({ name: 'TemplateForm' }) +import { ElMessage } from 'element-plus'; +import {updateFile} from "@/api/infra/file"; +import Vue3DraggableResizable from 'vue3-draggable-resizable' +import 'vue3-draggable-resizable/dist/Vue3DraggableResizable.css' +const getUploadUrl = import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + '/infra/file/upload' +const fileList = ref([]); +const lastUploadedFileUrl = ref(''); + +const handleExceed = () => { + ElMessage.warning('鍙兘涓婁紶涓�涓枃浠�'); +}; +const isChecked = ref(false); +const isChecked1 = ref(false); +const toggleCheck = () => { + isChecked.value = !isChecked.value; + if (isChecked.value==true) { + formData.value.showPpt=1 + }else if (isChecked.value==false) { + formData.value.showPpt=0 + } +}; +const toggleCheck1 = () => { + isChecked1.value =!isChecked1.value; + if (isChecked1.value==true) { + formData.value.showDigitalHuman=1 + }else if (isChecked1.value==false) { + formData.value.showDigitalHuman=0 + } +} +const beforeUpload = (file) => { + const isImage = file.type.startsWith('image/'); + const isLt2M = file.size / 1024 / 1024 < 2; + + if (!isImage) { + ElMessage.error('鍙兘涓婁紶鍥剧墖鏍煎紡鐨勬枃浠�!'); + return false; + } + if (!isLt2M) { + ElMessage.error('鍥剧墖澶у皬涓嶈兘瓒呰繃2MB!'); + return false; + } + return true; +}; +async function updataImage(formData1) { + const response= await updateFile(formData1) + console.log(response.data) + if (response) { + formData.value.bgImage=response.data + ElMessage.success('涓婁紶鎴愬姛'); + } +} + +const handleChange = (file, files) => { + // 褰撴枃浠跺彉鍖栨椂锛屽彧淇濈暀鏈�鍚庝竴涓枃浠� + if (files.length > 1) { + fileList.value = [files[files.length - 1]]; + } + console.log(file) + const raw=file.raw + console.log(raw) + lastUploadedFileUrl.value = URL.createObjectURL(raw); + console.log(lastUploadedFileUrl.value) + const formData1 = new FormData(); + formData1.append('file', raw); + updataImage(formData1) +}; + + const { t } = useI18n() // 鍥介檯鍖� const message = useMessage() // 娑堟伅寮圭獥 @@ -165,18 +205,18 @@ const formType = ref('') // 琛ㄥ崟鐨勭被鍨嬶細create - 鏂板锛泆pdate - 淇敼 const formData = ref({ id: undefined, - showBackground: undefined, + showBackground: 1, templateName: undefined, showDigitalHuman: undefined, showPpt: undefined, - pptW: undefined, - pptH: undefined, - pptX: '40', - pptY: '77', - humanW: undefined, - humanH: undefined, - humanX: '349', - humanY: '92', + pptW: 505, + pptH: 290, + pptX: 40, + pptY: 50, + humanW: 640, + humanH: 360, + humanX: 349, + humanY: 92, bgImage: undefined, }) const formRules = reactive({ @@ -225,64 +265,155 @@ } } defineExpose({ open }) // 鎻愪緵 open 鏂规硶锛岀敤浜庢墦寮�寮圭獥 -const changeTemplateSize = () => { - console.log(formData.value.templateSize) - const screenWidth = window.screen.width; - const screenHeight = window.screen.height; - if(formData.value.templateSize=='16:9'){ - formData.value.humanW = screenWidth / 3; - formData.value.humanH = screenHeight / 3; - formData.value.pptW = '505'; - formData.value.pptH = '290'; - }else if(formData.value.templateSize=='9:16'){ - formData.value.humanH = screenWidth / 3; - formData.value.humanW = screenHeight / 3; - formData.value.pptH = '505'; - formData.value.pptW = '290'; - } -} /** 鎻愪氦琛ㄥ崟 */ const emit = defineEmits(['success']) // 瀹氫箟 success 浜嬩欢锛岀敤浜庢搷浣滄垚鍔熷悗鐨勫洖璋� const submitForm = async () => { - // 鏍¢獙琛ㄥ崟 - await formRef.value.validate() - // 鎻愪氦璇锋眰 - formLoading.value = true - try { - const data = formData.value as unknown as TemplateVO - if (formType.value === 'create') { - await TemplateApi.createTemplate(data) - message.success(t('common.createSuccess')) - } else { - await TemplateApi.updateTemplate(data) - message.success(t('common.updateSuccess')) + const imageFile = await saveAsImage(); + if (imageFile) { + const formData1 = new FormData(); + formData1.append('file', imageFile); + const response = await updateFile(formData1); + formData.value.previewImage = response.data; + // 鏍¢獙琛ㄥ崟 + await formRef.value.validate() + // 鎻愪氦璇锋眰 + formLoading.value = true + try { + formData.value.humanX=formData.value.humanX.toString() + formData.value.humanY=formData.value.humanY.toString() + formData.value.pptX=formData.value.pptX.toString() + formData.value.pptY=formData.value.pptY.toString() + formData.value.pptW=formData.value.pptW.toString() + formData.value.pptH=formData.value.pptH.toString() + const data = formData.value as unknown as TemplateVO + + console.log(formData.value) + if (formType.value === 'create') { + await TemplateApi.createTemplate(data) + message.success(t('common.createSuccess')) + } else { + await TemplateApi.updateTemplate(data) + message.success(t('common.updateSuccess')) + } + dialogVisible.value = false + // 鍙戦�佹搷浣滄垚鍔熺殑浜嬩欢 + emit('success') + } finally { + formLoading.value = false } - dialogVisible.value = false - // 鍙戦�佹搷浣滄垚鍔熺殑浜嬩欢 - emit('success') - } finally { + }else { + ElMessage.error('淇濆瓨鎴浘澶辫触'); formLoading.value = false } + } /** 閲嶇疆琛ㄥ崟 */ const resetForm = () => { formData.value = { id: undefined, - showBackground: undefined, + showBackground: 1, showDigitalHuman: undefined, showPpt: undefined, - pptW: undefined, - pptH: undefined, + pptW: 505, + pptH: 290, + pptX: 40, + pptY: 50, + humanW: 640, + humanH: 360, + humanX: 349, + humanY: 92, bgImage: undefined, - pptX: '40', - pptY: '77', - humanW: undefined, - humanH: undefined, - humanX: '349', - humanY: '92', zg:1, + templateSize: '16:9', } formRef.value?.resetFields() } +const captureElement = ref<HTMLElement | null>(null); +const saveAsImage = async () => { + if (!captureElement.value) { + console.error('DOM 鍏冪礌鏈壘鍒帮紒'); + return; + } + try { + const canvas = await html2canvas(captureElement.value, { + backgroundColor: null, + scale: 1, + useCORS: true, + }); + + return new Promise((resolve) => { + canvas.toBlob((blob) => { + const file = new File([blob], 'screenshot.png', { + type: 'image/png', + }); + resolve(file); + }, 'image/png'); + }); + } + catch (error) { + console.error('鐢熸垚鍥剧墖澶辫触:', error); + return null; + } + +} +onMounted(() => { + console.log('DOM 宸叉覆鏌�:', captureElement.value); +}); + </script> +<style scoped lang="scss"> +.image-checkbox-container { + display: inline-block; + position: relative; +} + +.image-checkbox-wrapper { + position: relative; + cursor: pointer; +} + +.checkbox-image { + width: 230px; + height: 150px; + object-fit: cover; + border-radius: 4px; + border: 1px solid #ddd; + transition: all 0.3s; + margin-left: 20px; + margin-top: 20px; +} + +.checkbox-input { + position: absolute; + top: 30px; + left: 30px; + width: 20px; + height: 20px; + cursor: pointer; + z-index: 2; + appearance: none; /* 闅愯棌榛樿鏍峰紡 */ + -webkit-appearance: none; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 4px; +} + +/* 閫変腑鐘舵�佹牱寮� */ +.checkbox-input:checked { + background-color: #409eff; /* 钃濊壊鑳屾櫙 */ + border-color: #409eff; /* 钃濊壊杈规 */ + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='white'%3E%3Cpath d='M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41L9 16.17z'/%3E%3C/svg%3E"); + background-repeat: no-repeat; + background-position: center; + background-size: 14px; +} + +.image-checkbox-wrapper:hover .checkbox-image { + border-color: #ddd; +} + +.checkbox-input:checked ~ .checkbox-image { + border: 1px solid #ddd; /* 閫変腑鏃朵繚鎸佺伆鑹�1px杈规 */ +} +</style> -- Gitblit v1.9.3