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/src/views/digitalcourse/template/TemplateForm.vue |  459 ++++++++++++++++++++++++++++++++++++--------------------
 1 files changed, 295 insertions(+), 164 deletions(-)

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