Parcourir la source

fix: pdf 终极版

lvkun996 il y a 4 mois
Parent
commit
513813bf02

+ 8 - 1
src/App.vue

@@ -4,4 +4,11 @@
   <RouterView />
 </template>
 
-<style scoped></style>
+<style scoped>
+* {
+  letter-spacing: 0; /* 确保文字间距一致 */
+  line-height: normal; /* 避免行高不一致 */
+  font-family: inherit; /* 确保字体正确继承 */
+  text-rendering: optimizeLegibility; /* 优化文字渲染 */
+}
+</style>

BIN
src/assets/images/clazz-cover.png


+ 12 - 16
src/components/table.vue

@@ -1,5 +1,5 @@
 <template>
-  <div class="record-table" ref="recordTableDom" >
+  <div class="record-table" :style="{width: template ? '120%' : '100%'}" ref="recordTableDom" >
 
     <div class="table-header">
       <template v-for="col in props.columns" :key="col.key">
@@ -18,8 +18,8 @@
     <div class="table-row" v-for="(row, index) in props.data" :key="index">
       <template v-for="col in props.columns" :key="col.key">
         <div 
-          v-if="col.spanRow" 
-          class="table-row-cell"  
+          v-if="col.spanRow"
+          class="table-row-cell"
           :style="{width: col.width + 'px',borderBottom: 'none', height: row.list.length * 34 + 'px', borderRight: '1px solid #eee' }"
         >
           {{ row[col.key] }}
@@ -52,6 +52,7 @@
 import html2canvas from 'html2canvas'
 import { ref } from "vue"
 import { useId } from 'flicker-vue-hooks'
+
 const props = defineProps({
   data: {
     type: Array,
@@ -60,20 +61,17 @@ const props = defineProps({
   columns: {
     type: Array,
     default: () => []
+  },
+  template: {
+    type: Boolean,
+    default: false
   }
 })
 
 const recordTableDom = ref()
-const id = ref()
 
 const getChartImg = () => {
   return new Promise((resolve) => {
-    console.log("id:", id);
-    
-
-    id.value = useId()
-
-    // html2canvas(document.querySelector('#'+ id.value)!).then(canvas => {
     html2canvas(recordTableDom.value).then(canvas => {
       resolve(canvas.toDataURL(''))
     })
@@ -84,17 +82,15 @@ defineExpose({
   getChartImg
 })
 
-
-// const 
-
 </script>
 
 
 <style scoped lang="scss">
+
+
 .record-table {
-  width: 100%;
   border: 1px solid #eee;
-  
+  position: relative;
   .table-header {
     display: flex;
     background-color: rgb(51, 179, 92);
@@ -125,7 +121,7 @@ defineExpose({
         .child-title {
           width: 100%;
           height: 34px;
-          line-height: 34px;
+          line-height: 17px;
           display: flex;
           justify-content: center;
           align-items: center;

+ 3 - 1
src/types/customize.d.ts

@@ -1362,6 +1362,7 @@ export interface IGraderRecord {
   "semesters": string[],
   "teacherIds": string[],
   "year": number
+  abilityList: {list: any[]}[]
 }
 
 
@@ -1373,7 +1374,8 @@ export function defaultGradeDomain(): IGraderRecord[]{
       "schoolId": "",
       "semesters": [],
       "teacherIds": [],
-      "year": 0
+      "year": 0,
+      abilityList: [{list: []}]
     }
   ]
 }

+ 4 - 4
src/utils/exportPdf.js

@@ -850,8 +850,8 @@ export const exportSmartCenter = async (schoolData, cb) => {
     }
 
     const createPdfContent = async () => {
-        const r =  await splitImageAndGeneratePDF(_schoolData.studentDomainDomImg, 710)
-        console.log('r:', r);
+        // const r =  await splitImageAndGeneratePDF(_schoolData.studentDomainDomImg, 710)
+        // console.log('r:', r);
 
         return [
             cover,
@@ -879,7 +879,7 @@ export const exportSmartCenter = async (schoolData, cb) => {
             _schoolData._reportDomain.map(item =>[H3Template(item.title),  imgTemplate1(item.img), brakePage]),
             brakePage,
             H2Template("(5) 各年级各领域能力表现阶段汇总"),
-            _schoolData._gradeDomainDom.map(item =>[H3Template(item.title),  imgTemplate(item.img), brakePage]),
+            _schoolData._gradeDomainDom.map(item =>[H3Template(item.title),  ...(item.img.map(item => imgTemplate1(item))), brakePage]),
             brakePage,
             H1Template("3. 全园教师及学生数据分析"),
             H2Template("(1) 所有老师观察记录分布明细"),
@@ -887,7 +887,7 @@ export const exportSmartCenter = async (schoolData, cb) => {
             brakePage,
             H2Template("(2) 所有学生各领域表现阶段明细"),
             emptyTemplate(),
-            ...r
+            ..._schoolData.studentDomainDomImg.map(item => imgTemplate1(item))
             // imgTemplate(_schoolData.studentDomainDomImg),
         ]
     }

+ 139 - 32
src/views/customize/SmartCenter.vue

@@ -5,6 +5,9 @@
       <div class="smart-center-name">
         {{baseCount.schoolName}}
       </div>
+      <div class='smart-center-class' >
+        {{baseCount.reportType}}
+      </div>
       <div class="smart-center-date">
         <div class="smart-center-date-title" >成长阶段:</div>
         <div class="smart-center-date-value" >{{baseCount.dateRange}}</div>
@@ -123,6 +126,30 @@
         </div>
       </div>
 
+      <!-- 生成pdf图片区域 -->
+      <div class="pdfDom" >
+        <template
+          v-for="(item, index) in computedGradeDomainDomain"
+          :key="index" 
+        >
+          <Table 
+            v-for="(ei, i) in item"
+            :ref="el => el && ei.classLevelCode && pdfGradeDomainDom.push({el, classLevelCode: ei.classLevelCode, i})" 
+            :key="i" 
+            :columns="testColumns"
+            :data="ei.data"
+          />
+        </template>
+        
+        <Table 
+          :ref="el => pdfStudentDom.push(el)" 
+          v-for="(item, index) in computedStudentDomain"
+          :key="index" 
+          :columns="studentColumns"  
+          :data="item" 
+        />
+      </div>
+      
     <exportButton :loading="loading" @export="exportReport" />
   </div>
 </template>
@@ -139,7 +166,7 @@ import { getImageUrl, getAppToken } from "@/utils";
   // @ts-ignore
 import { exportSmartCenter } from "@/utils/exportPdf.js";
 import { storeToRefs } from "pinia";
-import { onMounted, ref } from 'vue';
+import { onMounted, ref, nextTick, computed } from 'vue';
 import { useRoute } from "vue-router";
 import html2canvas from 'html2canvas'
 const { p, type } = useRoute().query!;
@@ -151,8 +178,6 @@ const { getCenterBaseCount, getCenteClassRecord, getCenteReportDmain, getCenteRe
   getCenteStudentDomain, getCenteTeacherRecord, getCenteGradeDomain
  } = centerStore;
 
-
-
 const tableDom = ref()
 
 const reportSceneDom = ref({})
@@ -165,6 +190,21 @@ const teacherRecordDom = ref()
 
 const studentDomainDom = ref()
 
+const computedStudentDomain = computed(() => splitIntoChunks(studentDomain.value, 11))
+
+const computedGradeDomainDomain = computed(() => {
+  const a = gradeDomain.value.map(item => {
+    return item.abilityList.map( ability => ({data: [({list: ability.list, domainName: ability.domainName})], classLevelCode: item.classLevelCode}) )
+  })
+  console.log('a:', a);
+  return a
+})
+
+
+const pdfStudentDom = ref([])
+
+const pdfGradeDomainDom = ref([])
+
 const classColumns = ref([
   {title: '班级', key: 'className'},
   {title: '教师数量', key: 'teacher'},
@@ -188,16 +228,19 @@ const gradeDomainColumns = ref([
 
 const teacherColumns = ref([
   {  title: '教师',   key: 'teacherName' },
-  {  title: '观察记录数',   key: 'education' },
-  {  title: '观察学生数量', key: 'students' },
-  {  title: '未记录', key: 'tactics' }
+  {  title: '观察记录数',   key: 'totalRecord' },
+  {  title: '家园共育策略',   key: 'up', child: [
+    {  title: '一日活动',   key: 'education' },
+    {  title: '家园共育',   key: 'tactics' },
+  ]},
+  {  title: '观察学生数量', key: 'students' }
 ])
 
 const studentColumns = ref(
   [
-    {title: '姓名', key: 'babyName'},
+    {title: '姓名', key: 'babyName', width: 80},
     {title: '行为记录', key: 'behavior'},
-    {title: '观察进阶', key: 'up', width: 240,child: [
+    {title: '观察进阶', key: 'up', width: 200,child: [
         {  title: 's1',   key: 's1' },
         {  title: 's2',   key: 's2' },
         {  title: 's3',   key: 's3' },
@@ -237,13 +280,27 @@ const htmlToPng = (id: string) => {
   })
  }
 
+
+ function splitIntoChunks(arr, chunkSize) {
+  const result = [];
+  for (let i = 0; i < arr.length; i += chunkSize) {
+    result.push(arr.slice(i, i + chunkSize));
+  }
+  return result;
+}
+
 const exportReport = () =>  {
   loading.value = true
-
-  html2canvas(document.querySelector('#cover')!).then(async canvas => {
   
+  const style = document.createElement('style');
+  document.head.appendChild(style);
+  style.sheet?.insertRule('body > div:last-child img { display: inline-block; }');
+  html2canvas(document.querySelector('#cover')!).then(async canvas => {
+    
     const cover =  canvas.toDataURL('')
 
+    
+
     const record = await htmlToPng('#capture')
 
 
@@ -264,51 +321,80 @@ const exportReport = () =>  {
     for (let index = 0; index < Object.keys(reportSceneDom.value).length; index++) {
       const key = reportSceneDomKeys[index]
       if (reportSceneDom.value[key].el) {
-        // @ts-ignore
+     
         const img = await reportSceneDom.value[key].el.getChartImg()
         
-        // @ts-ignore
+     
         _reportScene.push({  img: img,   title: reportSceneDom.value[key].title })
       }
     }
 
-    console.log('reportDomain.value:', reportDomainDom.value);
 
     for (let index = 0; index < Object.keys(reportDomainDom.value).length; index++) {
       const key = reportDomainDomKeys[index]
       console.log('key:', key);
 
       if (reportDomainDom.value[key].el) {
-         // @ts-ignore
+
         const img =  await reportDomainDom.value[key].el.getChartImg()
-        console.log('img--over:', key);
-        // @ts-ignore
+
+
         _reportDomain.push({  img: img,  title: reportDomainDom.value[key].title })
       }
      
     }
 
-    console.log('gradeDomainDom.value:', gradeDomainDom.value);
+    const _pdfGradeDomainDom = []
+
+
+    for (let index = 0; index < pdfGradeDomainDom.value.length; index++) {
+      const dom = pdfGradeDomainDom.value[index]
+      const _index = _pdfGradeDomainDom.findIndex(item => item.classLevelCode === dom.classLevelCode && item.i === dom.i)
+      if (_index === -1) _pdfGradeDomainDom.push(dom)
+    }
     
 
     for (let index = 0; index < gradeDomainDomKeys.length; index++) {
       const key = gradeDomainDomKeys[index]
-      console.log(' gradeDomainDom.value[key].el:',  key);
-      // @ts-ignore
-      if (gradeDomainDom.value[key].el) {
-        const img = gradeDomainDom.value[key] && await gradeDomainDom.value[key].el.getChartImg()
-        // @ts-ignore
-        _gradeDomainDom.push({  img: img,  title: gradeDomainDom.value[key].title })
+      const title = levelIdMap.value.get(Number(key)) + '各领域能力表现阶段汇总'
+
+      
+      const doms = _pdfGradeDomainDom.filter(item => item.classLevelCode === Number(key)).map( childrenItem =>  childrenItem.el)
+      console.log('doms:', doms);
+      
+      const img = []
+      for (let i = 0; i < doms.length; i++) {
+        img.push(await doms[i].getChartImg())
       }
- 
+      _gradeDomainDom.push({title, img})
     }
 
+
+    // 第一版
+    // for (let index = 0; index < gradeDomainDomKeys.length; index++) {
+    //   const key = gradeDomainDomKeys[index]
+ 
+    //   if (gradeDomainDom.value[key].el) {
+    //     const img = gradeDomainDom.value[key] && await gradeDomainDom.value[key].el.getChartImg()
+   
+    //     _gradeDomainDom.push({  img: img,  title: gradeDomainDom.value[key].title })
+    //   }
+ 
+    // }
+
     const teacherRecordDomImg =  await teacherRecordDom.value.getChartImg()
-    const studentDomainDomImg =  await studentDomainDom.value.getChartImg()
 
-    console.log('reportDomain.value:', _gradeDomainDom);
-    
 
+    const studentDomainDomImg = []
+    for (let index = 0; index < pdfStudentDom.value.length; index++) {
+      const el = pdfStudentDom.value[index];
+      
+      const img = await el.getChartImg()
+      studentDomainDomImg.push(img)
+    }
+
+  
+    style.remove();
     exportSmartCenter({
       cover,
       baseInfo: `${baseCount.value.schoolName}班级${baseCount.value.classCount}个, 共有学生${baseCount.value.behavior}名个 ,在本评估周期内共统计到教师的观察记录${baseCount.value.behavior} 条,观察记录到学生${baseCount.value.done.length}名,未观察到的学生${baseCount.value.notDone.length}名。`,
@@ -325,12 +411,8 @@ const exportReport = () =>  {
         loading.value = false
       }
     })
-
-    
   })
 
-  
-
 }
 
 onMounted(async () => {
@@ -348,7 +430,10 @@ onMounted(async () => {
   getCenteReportScene( $par)
   getCenteStudentDomain( $par)
   getCenteTeacherRecord( $par)
-  getCenteGradeDomain( $par)
+  getCenteGradeDomain( $par).then(() => {
+  })
+
+
 })
 </script>
 
@@ -374,6 +459,23 @@ $font-size-H5: 14px;
       top: 240px;
       font-size: 18px;
     }
+    .smart-center-class {
+      height: 34px;
+      position: absolute;
+      left: 20px;
+      top: 200px;
+      font-size: 16px;
+      color: #fff;
+      background-color: #e6aab3;
+      padding: 0px 18px;
+      box-sizing: border-box;
+      border-radius: 12px;
+      font-weight: 500;
+      text-align: center;
+      // line-height: 34px;
+      line-height: 34px;
+      display: inline-block;
+    }
     .smart-center-date {
       position: absolute;
       left: 20px;
@@ -480,4 +582,9 @@ $font-size-H5: 14px;
 }
 
 
+.pdfDom {
+  position: fixed;
+  z-index: 1;
+}
+
 </style>