Browse Source

Merge branch 'master' of http://gogs.gisvg.com/YDM/museums-ui

wwj 4 months ago
parent
commit
d2d08771bc
1 changed files with 160 additions and 21 deletions
  1. 160 21
      src/views/museums/specimeninfo/index.vue

+ 160 - 21
src/views/museums/specimeninfo/index.vue

@@ -331,7 +331,7 @@
           @click="handleExport"
           @click="handleExport"
           :loading="exportLoading"
           :loading="exportLoading"
         >
         >
-          <Icon icon="ep:upload" class="mr-5px" /> 导出
+          <Icon icon="ep:upload" class="mr-5px" /> 导出excel
         </el-button>
         </el-button>
         <el-button
         <el-button
           type="success"
           type="success"
@@ -468,17 +468,48 @@
 <!--  制作标签弹窗-->
 <!--  制作标签弹窗-->
   <el-dialog v-model="dialogTableVisible" title="标签制作" width="800">
   <el-dialog v-model="dialogTableVisible" title="标签制作" width="800">
     <div>
     <div>
-      <el-form :model="form" label-width="auto" style="max-width: 600px">
+      <el-form-item label="尺寸">
-      <el-form-item label="Activity zone">
+        <el-radio-group v-model="formData.size">
-        <el-select v-model="form.region" placeholder="please select your zone">
+          <el-radio :value="1">90:54</el-radio>
-          <el-option
+          <el-radio :value="2">90:50</el-radio>
-            v-for="item in optionsLabel"
+          <el-radio :value="3">5:5</el-radio>
-            :key="item.value"
+        </el-radio-group>
-            :label="item.label"
-            :value="item.value"
-          />
-        </el-select>
       </el-form-item>
       </el-form-item>
+      <el-form :model="formData" label-width="auto" style="max-width: 750px">
+        <el-form-item label="标题">
+          <el-select v-model="formData.content" placeholder="请选择字段">
+            <el-option
+              v-for="item in optionsLabel"
+              :key="item.value"
+              :label="item.label"
+              :value="item.value"
+            />
+          </el-select>
+        </el-form-item>
+
+        <div v-for="(item, index) in formData.contentItems" :key="index" style="margin-top: 10px">
+          <el-form-item>
+            <div style="float: left; margin-right: 5px">
+              <el-button type="primary" :icon="Delete" size="small" @click="removeContentItem(index)" />
+            </div>
+            <div style="float: left">内容{{ index + 1 }}:</div>
+            <el-select v-model="item.value" placeholder="请选择字段" style="float: left; width: 40%">
+              <el-option
+                v-for="opt in optionsLabel"
+                :key="opt.value"
+                :label="opt.label"
+                :value="opt.value"
+              />
+            </el-select>
+          </el-form-item>
+
+        </div>
+
+        <el-form-item>
+          <el-button type="success" @click="addContentItem">增加内容</el-button>
+          <el-button type="primary" @click="onSubmit">导出图片</el-button>
+          <el-button @click="dialogTableVisible = false">取消</el-button>
+        </el-form-item>
       </el-form>
       </el-form>
     </div>
     </div>
   </el-dialog>
   </el-dialog>
@@ -490,12 +521,15 @@
 
 
 <script setup lang="ts">
 <script setup lang="ts">
 import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
 import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
+import { Plus,Delete } from '@element-plus/icons-vue'
 import {dateFormatter, formatDate} from '@/utils/formatTime'
 import {dateFormatter, formatDate} from '@/utils/formatTime'
 import download from '@/utils/download'
 import download from '@/utils/download'
 import { SpecimenInfoApi, SpecimenInfoVO } from '@/api/museums/specimeninfo'
 import { SpecimenInfoApi, SpecimenInfoVO } from '@/api/museums/specimeninfo'
 import SpecimenInfoForm from './SpecimenInfoForm.vue'
 import SpecimenInfoForm from './SpecimenInfoForm.vue'
 import SpecimenImportForm from './SpecimenImportForm.vue'
 import SpecimenImportForm from './SpecimenImportForm.vue'
 import  ImageImportForm from './imageImportForm.vue'
 import  ImageImportForm from './imageImportForm.vue'
+import JSZip from 'jszip';
+import { saveAs } from 'file-saver';
 /** 标本管理 列表 */
 /** 标本管理 列表 */
 defineOptions({ name: 'SpecimenInfo' })
 defineOptions({ name: 'SpecimenInfo' })
 
 
@@ -546,6 +580,18 @@ const queryParams = reactive({
   operator: undefined,
   operator: undefined,
   entryDate: []
   entryDate: []
 })
 })
+//标签打印的表单
+const formData = ref({
+  content: undefined,
+  selectedData: [] as SpecimenInfoVO[],
+  contentItems: [] as { label: string; value: string }[],
+  size:1,
+  sizeMap: {
+    1: { width: 900, height: 540 },
+    2: { width: 900, height: 500 },
+    3: { width: 500, height: 500 }
+  }
+})
 const queryFormRef = ref() // 搜索的表单
 const queryFormRef = ref() // 搜索的表单
 const exportLoading = ref(false) // 导出的加载中
 const exportLoading = ref(false) // 导出的加载中
 
 
@@ -641,14 +687,15 @@ const handleExport = async () => {
 }
 }
 //字段类型
 //字段类型
 const optionsLabel = [
 const optionsLabel = [
-  {
+
-    value: 'specimenNumber',
-    label: '标本编号',
-  },
   {
   {
     value: 'chineseName',
     value: 'chineseName',
     label: '中文名称',
     label: '中文名称',
   },
   },
+  {
+    value: 'specimenNumber',
+    label: '标本编号',
+  },
   {
   {
     value: 'specimenType',
     value: 'specimenType',
     label: '标本类型',
     label: '标本类型',
@@ -718,12 +765,8 @@ const optionsLabel = [
   },
   },
 
 
   {
   {
-    value: 'source',
+    value: 'acquisitionTime',
-    label: '来源',
+    label: '入藏时间',
-  },
-  {
-    value: 'provider',
-    label: '标本提供者',
   },
   },
 
 
 ]
 ]
@@ -732,6 +775,18 @@ const optionsLabel = [
 
 
 const selectedlabel = ref<any[]>([]) // 选中的标本
 const selectedlabel = ref<any[]>([]) // 选中的标本
 const dialogTableVisible = ref(false) //弹窗开关
 const dialogTableVisible = ref(false) //弹窗开关
+//标签内容新增
+const addContentItem = () => {
+  if (formData.value.contentItems.length >= 4) {
+    message.warning('最多添加4个标签内容')
+    return
+  }
+  formData.value.contentItems.push({ label: '', value: '' })
+}
+//标签内容删除
+const removeContentItem = (index: number) => {
+  formData.value.contentItems.splice(index, 1)
+}
 /** 处理选中变化 */
 /** 处理选中变化 */
 const handleSelectionChange = (selection: any[]) => {
 const handleSelectionChange = (selection: any[]) => {
   selectedlabel.value = selection
   selectedlabel.value = selection
@@ -748,12 +803,17 @@ const labelExport = async () => {
       return
       return
     }
     }
     dialogTableVisible.value = true
     dialogTableVisible.value = true
+    // 将选中的数据传递给对话框
+    formData.value.selectedData = selectedlabel.value
 
 
   } catch {
   } catch {
   } finally {
   } finally {
     exportLoading.value = false
     exportLoading.value = false
   }
   }
 }
 }
+
+
+
 /** 初始化 **/
 /** 初始化 **/
 onMounted(() => {
 onMounted(() => {
   getList()
   getList()
@@ -778,5 +838,84 @@ const handleSegmentedChange = (value: string) => {
   queryParams.specimenType = value
   queryParams.specimenType = value
   handleQuery()
   handleQuery()
 }
 }
+
+//标签导出
+const onSubmit = async () => {
+  try {
+    const selectedData = formData.value.selectedData
+    const labels = selectedData.map(item => {
+      const content = formData.value.contentItems
+        .map(contentItem => {
+          const label = optionsLabel.find(opt => opt.value === contentItem.value)?.label
+          const value = item[contentItem.value]
+          if (value !== null && value !== undefined && value !== '') {
+            return `${label}:${value}`
+          }
+          return ''
+        })
+        .filter(Boolean) // 过滤掉空字符串
+        .join('\n') // 每个内容项换行
+
+      return {
+        title: item[formData.value.content],
+        content: content
+      }
+    })
+    const zip = new JSZip();
+    // 生成标签图片的逻辑
+    for (const label of labels) {
+      const canvas = document.createElement('canvas')
+      const ctx = canvas.getContext('2d')
+      if (ctx) {
+        const size = formData.value.sizeMap[formData.value.size]
+        canvas.width = size.width
+        canvas.height = size.height
+        ctx.fillStyle = 'white'
+        ctx.fillRect(0, 0, canvas.width, canvas.height)
+
+        // 设置文本对齐方式为居中
+        ctx.textAlign = 'center'
+        // 设置字体样式
+        ctx.font = `${Math.min(size.width, size.height) * 0.2}px Arial`
+        // 设置文本颜色
+        ctx.fillStyle = 'black'
+        // 绘制标题
+        ctx.fillText(label.title, canvas.width / 2, size.height * 0.3)
+
+        // 设置文本对齐方式为左对齐
+        ctx.textAlign = 'left'
+        // 设置字体样式
+        ctx.font = `${Math.min(size.width, size.height) * 0.08}px Arial`
+        // 绘制内容
+        const lines = label.content.split('\n')
+        let y = size.height * 0.45
+        for (const line of lines) {
+          ctx.fillText(line, size.width * 0.15, y)
+          y += Math.min(size.width, size.height) * 0.15 // 每行间隔
+        }
+
+        // 将画布转换为数据URL
+        const dataUrl = canvas.toDataURL('image/png')
+        // 将数据URL转换为Blob
+        const response = await fetch(dataUrl)
+        const blob = await response.blob()
+
+        // 将Blob添加到压缩文件中
+        zip.file(`${label.title}.png`, blob)
+      }
+    }
+    // 生成压缩文件
+    const content = await zip.generateAsync({ type: 'blob' });
+    // 下载压缩文件
+    saveAs(content, 'labels.zip');
+    message.success('标签图片已导出')
+  } catch (error) {
+    message.error('导出失败')
+  } finally {
+    dialogTableVisible.value = false
+  }
+}
 </script>
 </script>
 
 
+
+