Browse Source

资料填报-照片上传格式问题,折叠面板样式问题

duy 1 day ago
parent
commit
1d8cfda2af

+ 79 - 97
src/components/plugins/table-form/hc-form-upload.vue

@@ -1,22 +1,11 @@
 <template>
     <div class="upload-container">
         <el-upload
-            v-loading="isLoading"
-            drag
-            :accept="accept" 
-            :action="action" 
-            :class="isFocus ? 'is-focus' : ''"
-            :disabled="isLoading" 
-            :headers="getHeader()" 
-            :keyname="isKeyName"
-            :on-error="formUploadError"
-            :on-progress="uploadprogress" 
-            :placeholder="placeholder" 
-            :show-file-list="false"
-            class="hc-upload-table-form"
-            element-loading-text="上传中..." 
-            @exceed="formUploadExceed" 
-            @success="formUploadSuccess"
+            v-loading="isLoading" drag :accept="IMAGE_MIME.join(',')" :action="action"
+            :class="isFocus ? 'is-focus' : ''" :disabled="isLoading" :headers="getHeader()" :keyname="isKeyName"
+            :on-error="formUploadError" :on-progress="uploadProgress" :on-exceed="formUploadExceed"
+            :placeholder="placeholder" :show-file-list="false" class="hc-upload-table-form"
+            element-loading-text="上传中..." :before-upload="beforeUpload" @success="formUploadSuccess"
         >
             <img v-if="isSrc" :src="isSrc" alt="" class="hc-table-form-img">
             <div v-else class="hc-table-form-icon">
@@ -26,39 +15,19 @@
                 <el-link type="warning" size="small" @click.stop="handlePreview">
                     预览
                 </el-link>
-                
-                
-              
                 <el-link type="danger" size="small" @click.stop="delTableFormFile">
                     删除
                 </el-link>
             </div>
-            <input 
-                :id="isKeyName" 
-                v-model="isSrc" 
-                class="hc-upload-input-src" 
-                @blur="handleBlur" 
-                @focus="handleFocus"
-            >
+            <input :id="isKeyName" v-model="isSrc" class="hc-upload-input-src" @blur="handleBlur" @focus="handleFocus">
         </el-upload>
 
         <!-- 预览弹窗 -->
-        <el-dialog 
-            v-model="previewVisible" 
-            title="图片预览" 
-           
-            :before-close="handleClose"
-            class="hc-modal-border"
-        >
+        <el-dialog v-model="previewVisible" title="图片预览" :before-close="handleClose" class="hc-modal-border">
             <div class="preview-container">
-                <div 
-                    class="preview-image-wrapper"
-                    :style="{ transform: `rotate(${rotation}deg)` }"
-                >
-                    <img 
-                        :src="previewSrc" 
-                        alt="预览图片" 
-                        class="preview-image"
+                <div class="preview-image-wrapper" :style="{ transform: `rotate(${rotation}deg)` }">
+                    <img
+                        :src="previewSrc" alt="预览图片" class="preview-image"
                         :style="{ maxHeight: `calc(100vh - 200px)` }"
                     >
                 </div>
@@ -70,13 +39,7 @@
             <template #footer>
                 <div class="dialog-footer text-center">
                     <el-button hc-btn size="large" type="info" @click="previewVisible = false">取消</el-button>
-                    <el-button  
-                        size="large"
-                        hc-btn
-                        type="primary" 
-                        :loading="confirmLoading"
-                        @click="confirmRotation"
-                    >
+                    <el-button size="large" hc-btn type="primary" :loading="confirmLoading" @click="confirmRotation">
                         确定
                     </el-button>
                 </div>
@@ -86,7 +49,7 @@
 </template>
 
 <script setup>
-import { onMounted, ref, watch } from 'vue'
+import { ref, watch } from 'vue'
 import { getHeader } from 'hc-vue3-ui'
 import { ElMessage } from 'element-plus'
 
@@ -107,7 +70,7 @@ const props = defineProps({
 })
 
 // 事件
-const emit = defineEmits(['success', 'del', 'rotate-success'])
+const emit = defineEmits(['success', 'del', 'rotateSuccess'])
 
 // 变量
 const isLoading = ref(false)
@@ -119,28 +82,49 @@ const confirmLoading = ref(false)
 const previewVisible = ref(false)
 const previewSrc = ref('')
 const rotation = ref(0)
-const dialogWidth = ref('65%')
+// const dialogWidth = ref('65%')
 const rotatedBlob = ref(null)
 
 const action = '/api/blade-manager/exceltab/add-buss-imginfo'
-const accept = 'image/png,image/jpg,image/jpeg'
+const IMAGE_WHITE_EXT = ['png', 'jpg', 'jpeg'] // 图片白名单扩展名(不区分大小写)
+const IMAGE_MIME = ['image/png', 'image/jpeg', 'image/jpg'] // MIME 也同步
+// const accept = 'image/png,image/jpg,image/jpeg'
 const oldUrl = ref('')
 // 监听props变化
-watch(() => [props.src, props.keyname], 
-([src, keyname]) => {
-    isSrc.value = src
- 
+watch(() => [props.src, props.keyname],
+    ([src, keyname]) => {
+        isSrc.value = src
+
         // 只在initialSrc未设置时才赋值(保留第一次的src)
-    if (oldUrl.value === '' && src) {
-        oldUrl.value = src
-        console.log( oldUrl.value, ' oldUrl.value')
-        
+        if (oldUrl.value === '' && src) {
+            oldUrl.value = src
+            console.log(oldUrl.value, ' oldUrl.value')
+
+        }
+        isKeyName.value = keyname
+    }, { immediate: true })
+
+function isImageAllow(file) {
+    // 1. 后缀名校验(不区分大小写)
+    const ext = file.name.split('.').pop()?.toLowerCase() || ''
+    if (!IMAGE_WHITE_EXT.includes(ext)) return false
+
+    // 2. MIME 校验(可选,双保险)
+    if (!IMAGE_MIME.includes(file.type)) return false
+
+    return true
+}
+
+const beforeUpload = (rawFile) => {
+    if (!isImageAllow(rawFile)) {
+        ElMessage.error('仅支持 png、jpg、jpeg 格式')
+        return false // 阻断上传
     }
-    isKeyName.value = keyname
-}, { immediate: true })
+    return true
+}
 
 // 上传进度
-const uploadprogress = () => {
+const uploadProgress = () => {
     isLoading.value = true
 }
 
@@ -149,7 +133,7 @@ const formUploadSuccess = (res) => {
     isLoading.value = false
     if (res.code === 200) {
         const link = res.data?.link || ''
-        
+
         emit('success', {
             res,
             src: link,
@@ -178,10 +162,10 @@ const delTableFormFile = () => {
 // 焦点状态管理
 const isFocus = ref(false)
 const handleFocus = () => {
- isFocus.value = true 
+    isFocus.value = true
 }
 const handleBlur = () => {
- isFocus.value = false 
+    isFocus.value = false
 }
 
 // 预览图片
@@ -223,10 +207,7 @@ const confirmRotation = async () => {
         const formData = new FormData()
         formData.append('file', blob, `rotated-${Date.now()}.png`)
         // 添加新参数
-  
-        
         formData.append('oldUrl', oldUrl.value)
-      
 
         // 调用上传接口
         const response = await fetch(action, {
@@ -236,7 +217,6 @@ const confirmRotation = async () => {
         })
 
         const res = await response.json()
-        
         if (res.code === 200) {
             const link = res.data?.link || ''
             isSrc.value = link
@@ -245,7 +225,7 @@ const confirmRotation = async () => {
                 src: link,
                 key: isKeyName.value,
             })
-            emit('rotate-success', {
+            emit('rotateSuccess', {
                 src: link,
                 rotation: rotation.value,
                 key: isKeyName.value,
@@ -266,30 +246,30 @@ const confirmRotation = async () => {
 const rotateImageAndGetBlob = (imageUrl, degrees) => {
     return new Promise((resolve, reject) => {
         const img = new Image()
-       
-    
+
+
         img.crossOrigin = 'anonymous'
         img.onload = function () {
             const canvas = document.createElement('canvas')
             const ctx = canvas.getContext('2d')
-            
+
             // 根据旋转角度设置画布尺寸
             const radians = (degrees * Math.PI) / 180
             let width = img.width
             let height = img.height
-            
+
             if (degrees % 180 !== 0) {
                 [width, height] = [height, width]
             }
-            
+
             canvas.width = width
             canvas.height = height
-            
+
             // 旋转画布
             ctx.translate(width / 2, height / 2)
             ctx.rotate(radians)
             ctx.drawImage(img, -img.width / 2, -img.height / 2)
-            
+
             // 转换为Blob
             canvas.toBlob(blob => {
                 if (blob) {
@@ -307,7 +287,7 @@ const rotateImageAndGetBlob = (imageUrl, degrees) => {
 
 <style lang="scss" scoped>
 .upload-container {
-  
+
     width: 100%;
     height: 100%;
 }
@@ -319,11 +299,12 @@ const rotateImageAndGetBlob = (imageUrl, degrees) => {
     height: 100%;
     border-radius: 3px;
 
-    &.is-focus, &:hover {
+    &.is-focus,
+    &:hover {
         background-color: #eddac4;
         box-shadow: 0 0 0 1.5px var(--el-color-primary) inset;
     }
-    
+
     .hc-upload-input-src {
         position: absolute;
         z-index: -1;
@@ -349,29 +330,29 @@ const rotateImageAndGetBlob = (imageUrl, degrees) => {
 }
 
 .hc-table-form-actions {
-   position: absolute;
+    position: absolute;
     top: 10px;
-  display: flex;
-  gap: 4px;
+    display: flex;
+    gap: 4px;
+
+
+
 
 
-   
-    
-    
 }
 
 .preview-container {
     display: flex;
     flex-direction: column;
     align-items: center;
-    overflow-y:auto ;
+    overflow-y: auto;
     max-height: 600px;
-   
+
 }
 
 .preview-image-wrapper {
     transition: transform 0.3s ease;
-  
+
 }
 
 .preview-image {
@@ -389,22 +370,23 @@ const rotateImageAndGetBlob = (imageUrl, degrees) => {
 </style>
 
 <style lang="scss">
-.hc-upload-table-form{
+.hc-upload-table-form {
     border-radius: 3px;
     transition: box-shadow 0.3s, background-color 0.3s;
-    
-    &.is-focus, &:hover {
+
+    &.is-focus,
+    &:hover {
         background-color: #eddac4;
         box-shadow: 0 0 0 1.5px var(--el-color-primary) inset;
     }
-    
-    .el-upload-dragger{
-        height:100%;
+
+    .el-upload-dragger {
+        height: 100%;
         width: 100%;
         background-color: transparent;
         padding: 10px;
         text-align: left;
-        border:none;
+        border: none;
     }
 }
 </style>

+ 6 - 1
src/styles/app/element.scss

@@ -11,6 +11,11 @@
 .data-fill-list-box .el-collapse-item .el-collapse-item__header {
     border: 0;
     width: 100%;
+
+    .el-collapse-item__title {
+        display: flex;
+        flex: 1;
+    }
     .hc-collapse-item-header .item-title {
         text-align: left;
     }
@@ -40,6 +45,6 @@
     margin-left: 4px;
     margin-right: 0;
 }
-.el-table .cell{
+.el-table .cell {
     white-space: pre-wrap;
 }

+ 10 - 11
src/views/data-fill/collapse-form/index.vue

@@ -849,11 +849,7 @@ onMounted(() => {
     const enableFormulaDescription = getStoreValue('enableFormulaDescription')
     isOpenFormulaDescription.value = enableFormulaDescription ?? false
 
-    document.getElementById('app').addEventListener('click', e => {
-        if (!(e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') || !e.target.id.includes('key')) {
-            formulaDescriptionVisible.value = false
-        }
-    })
+    document.getElementById('app').addEventListener('click', e => onBlurFormulaDescription(e))
 
     const isBulk = getStoreValue('isEnableBulk')
     isEnableBulk.value = isBulk ?? true
@@ -861,9 +857,11 @@ onMounted(() => {
     if (isBulk) setMountOnEventKey()
 })
 
-onUnmounted(() => {
-    document.getElementById('app').removeEventListener('click')
-})
+const onBlurFormulaDescription = (e) => {
+    if (!(e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') || !e.target.id.includes('key')) {
+        formulaDescriptionVisible.value = false
+    }
+}
 
 //处理变动的数据
 const changeFormData = ref({
@@ -1299,9 +1297,9 @@ const submitinsertData = async () => {
         const refs = await getFormRef(pkeyId)
         const itemFormData = refs?.getFormData()
         const { code, val, posVal } = await insertDataRef.value?.submitinsertData(
-                itemNode,
-                itemFormData[KeyName],
-            )
+            itemNode,
+            itemFormData[KeyName],
+        )
         if (code === 200 && val) {
             itemFormData[KeyName] = val
             refs?.setFormData(itemFormData)
@@ -1988,6 +1986,7 @@ onDeactivated(() => {
 //页面被卸载
 onUnmounted(() => {
     HTableForm.unmountEventKey()
+    document.getElementById('app').removeEventListener('click', onBlurFormulaDescription)
 })
 
 const setMountOnEventKey = () => {