Browse Source

Merge branch 'eta2.4'

shanbinzhang 2 months ago
parent
commit
7e9f63667b

+ 33 - 6
src/components/sheet.vue

@@ -1,7 +1,25 @@
 <script setup lang='ts'>
-import { PropType,computed,ref } from 'vue';
-import { isMobile } from '@/utils/utils'
- 
+import { PropType,computed,ref, nextTick } from 'vue';
+import { isMobile } from '@/utils/utils';
+import { useResizeTable } from '@/hooks/sheet/useResizeTable.js';
+import { useRoute } from 'vue-router';
+
+const route = useRoute();
+const isCanDrag = computed(() => { //在研报内的研报id
+  return route.query.sourceId ? true :false
+});
+
+const tableRef = ref(null)
+const {
+  columnsWArr,
+  rowsHArr,
+  handleMouseDown,
+  handleMouseMove,
+  handleMouseOut,
+  initTableCellsWid,
+  getSize
+} = useResizeTable(tableRef)
+
 const props = defineProps({
   data: {
     type: Array as PropType<any[]>,
@@ -9,6 +27,9 @@ const props = defineProps({
   },
   config: {
     type: Object
+  },
+  sceneConfig: {  //应用存储信息
+    type: Object
   }
 })
 
@@ -23,25 +44,27 @@ const HtObj=ref({
   2:'right'
 })
 
+initTableCellsWid('init',props.sceneConfig)
 </script>
 
 <template>
 <div :class="['table-wrapper',dynamicSty ]">
   <table 
     cellpadding="0" 
-    cellspacing="0" 
-    :style="`font-size: ${props.config.FontSize||12}px`"
+    cellspacing="0"
+    ref="tableRef"
   >
     <tbody>
       <tr 
         v-for="(item,index) in props.data"
         :key="index"
+        :style="`height:${getSize(index,'height')}`"
       >
         <td 
           :class="['data-cell',{
             'one-bg':(index+1)%2&&index>0,
             'tow-bg': (index+1)%2!==0&&index>0,
-            'head-column': index === 0
+            'head-column': index === 0,
           }]"
           v-for="(cell,cell_index) in item"
           :key="cell_index"
@@ -53,7 +76,11 @@ const HtObj=ref({
             font-style: ${cell.it ? 'italic' : 'normal'};
             background: ${cell.bg};
             text-align: ${HtObj[cell.HorizontalType]};
+            font-size: ${cell.fs||props.config.FontSize||12}px;
+            width:${index==0?getSize(cell_index,'width'):'auto'}
           `"
+          @mousemove="e =>isCanDrag && handleMouseMove(e,index,cell_index)"
+          @mousedown="e =>isCanDrag && handleMouseDown(e,index,cell_index)"
         >
           <!-- 单元格拆分 -->
           <div class="split-word" v-if="cell.ct.s">

+ 245 - 0
src/hooks/sheet/useResizeTable.js

@@ -0,0 +1,245 @@
+import { ref,nextTick } from 'vue';
+import { isMobile } from '@/utils/utils';
+import _ from 'lodash';
+import { useRoute } from 'vue-router';
+import { ElMessage } from 'element-plus';
+
+
+export function useResizeTable(refName) {
+  const route = useRoute();
+
+  const minThresholdColWid = 30,
+    minThresholdColH = 30,
+    moveToDistance=5;
+
+  const MobileCellWID = '120px',MobileCellH = '40px';
+
+  const columnsWArr = ref([])
+  const rowsHArr = ref([])
+  const dragging = ref(false)
+  const dragState=ref({})
+  const dragStateHeight = ref({}) 
+  
+  const handleMouseMove = _.throttle(function(e,rIndex,cIndex) {
+
+    if(isMobile()) return
+
+    // if(rIndex!==0 && cIndex!==0) return
+
+    let target = e.target
+    if (!dragging.value) {
+        let rect = target.getBoundingClientRect();
+
+        if (rect.width > 12 && rect.right - e.pageX < moveToDistance /* && rIndex===0 */) {
+            e.target.style.cursor = 'col-resize'
+        }else if (rect.height > 12 && rect.bottom - e.pageY < moveToDistance /* && cIndex===0 */) {
+            e.target.style.cursor = 'row-resize'
+        } else if (!dragging.value) {
+            e.target.style.cursor = ''
+        }
+    }
+  },20)
+
+
+  const handleMouseDown = _.throttle(function(e,rIndex,cIndex) {
+    if(isMobile()) return
+
+    document.onselectstart = function() { return false; };//解决拖动会选中文字的问题
+
+    if(e.button!=0){
+      return
+    }
+
+    let rect = e.target.getBoundingClientRect();
+
+    if (rect.width > 12 && rect.right - e.pageX < moveToDistance /* && rIndex===0 */) {
+      // 开始拖拽
+      // 当前拖拽的列所在的表格
+      // 当前所在列(单元格)
+      let thEL = e.target
+      dragging.value = true
+
+      thEL.classList.add('noclick')
+      dragState.value = {
+          startMouseLeft: e.clientX, // 鼠标开始的地方
+          columnWidth: rect.width, // th开始拖拽的宽度
+      }
+
+      document.onselectstart = function () {
+          return false
+      }
+      document.ondragstart = function () {
+          return false
+      }
+
+      const endResize = (event) => {
+        if(dragging.value){
+            // 拖拽完毕
+          const { startMouseLeft, columnWidth } = dragState.value;
+          const columnWidthDiff = event.clientX - startMouseLeft;
+          columnsWArr.value[cIndex] = Math.max(minThresholdColWid,columnWidthDiff + columnWidth)
+
+          // console.log(columnsWArr.value[cIndex])
+          // console.log(e.target.offsetWidth)
+          e.target.style.width = columnsWArr.value[cIndex]
+
+          let widthTotal=0
+          columnsWArr.value.forEach((item)=>{
+            widthTotal+=item
+          })
+          // console.log(widthTotal)
+          //多出来的宽度
+          let otherWidth=refName.value.offsetWidth-widthTotal;
+
+          columnsWArr.value.forEach((item,colIndex)=>{
+            if(colIndex!=cIndex){
+              columnsWArr.value[colIndex]= Number(parseFloat(item + otherWidth/columnsWArr.value.length-1).toFixed(2))
+            }
+          })
+
+          setTimeout(()=>{
+            initTableCellsWid('change')
+          },500)
+
+          // event.target.style.cursor = ''
+
+          dragging.value = false
+          dragState.value = {}
+        }
+        document.removeEventListener('mouseup', endResize);
+        document.onselectstart = null
+        document.ondragstart = null
+        thEL.classList.remove('noclick')
+      }
+
+      document.addEventListener('mouseup', endResize);
+    }
+
+
+    if (rect.height > 12 && rect.bottom - e.pageY < moveToDistance /* && cIndex===0 */) {
+      let thEL = e.target
+      dragging.value = true
+
+      thEL.classList.add('noclick')
+      dragStateHeight.value = {
+          startMouseTop: e.clientY,
+          columnHeight: rect.height, 
+      }
+      document.onselectstart = function () {
+          return false
+      }
+      document.ondragstart = function () {
+          return false
+      }
+  
+      const endResize = (event) => {
+        if(dragging.value){
+          // 拖拽完毕
+          const { startMouseTop, columnHeight } = dragStateHeight.value;
+          const columnHeightDiff = event.clientY - startMouseTop
+          rowsHArr.value[rIndex] = Math.max(minThresholdColH,columnHeightDiff + columnHeight)
+
+          setTimeout(()=>{
+            initTableCellsWid('change')
+          },500)
+
+          event.target.style.cursor = ''
+          dragging.value = false
+          dragStateHeight.value = {}
+        }
+        document.removeEventListener('mouseup', endResize);
+        document.onselectstart = null
+        document.ondragstart = null
+        setTimeout(function () {
+            thEL.classList.remove('noclick')
+        }, 0)
+      }
+        document.addEventListener('mouseup', endResize);
+    }
+  },20)
+
+
+  function initTableCellsWid(type='init',sceneConfig) {
+    if(type=='init'){
+      const { HeightList,WidthList } = sceneConfig;
+
+      nextTick(()=>{
+        const table = refName.value;
+        if (table) {
+          if(HeightList&&WidthList) {
+            columnsWArr.value = WidthList.split(',').map(_ =>Number(_));
+            rowsHArr.value = HeightList.split(',').map(_ =>Number(_));
+            nextTick(() => {
+              postSheetHeightMsg()
+            })
+            return
+          }
+
+          const rows=table.rows;
+          const cells = table.rows[0].cells;
+          let widthArr= Array.from(cells).map(cell => cell.offsetWidth);
+          console.log(widthArr)
+
+          let heightArr=Array.from(rows).map(row => row.offsetHeight);
+          console.log(heightArr)
+          
+          columnsWArr.value=widthArr
+          rowsHArr.value=heightArr
+          
+          nextTick(() => {
+            postSheetHeightMsg()
+          }) 
+        }
+      })
+    }else if(type === 'change') {
+      changeTableCellWidSave()
+    }
+  }
+
+  function getSize(index,type) {
+    if(type==='width'){
+      return isMobile() ?  MobileCellWID : (columnsWArr.value[index]?`${columnsWArr.value[index]}px`:'')
+    }else{
+      return isMobile() ? MobileCellH : (rowsHArr.value[index]?`${rowsHArr.value[index]}px`:'20px')
+    }
+  }
+
+  /* 初始化抛出渲染后的表格高度 */
+  function postSheetHeightMsg(type="") {
+      let ele = document.getElementsByClassName('sheet-show-wrapper')[0];
+    
+      let params = {
+        height: ele.offsetHeight,
+        code: route.query.code,
+        uid: route.query.uid||""
+      }
+    
+      window.parent.postMessage(params,'*')
+      type==='update'&&ElMessage.success('更新样式成功')
+  }
+
+  /* 拖拽后抛出参数到外面存储  只在报告编辑页可保存*/
+  function changeTableCellWidSave() {
+    if(!route.query.sourceId || !route.query.uid) return
+    let params = {
+      type:'changeCol',
+      code: route.query.code,
+      sourceId: route.query.sourceId,
+      uid: route.query.uid,
+      columnsWArr:columnsWArr.value.map(_ =>_),
+      rowsHArr:rowsHArr.value.map(_=>_)
+    }
+    console.log(params)
+    window.parent.postMessage(params,'*')
+  }
+
+  return {
+    columnsWArr,
+    rowsHArr,
+    handleMouseMove,
+    handleMouseDown,
+    initTableCellsWid,
+    getSize,
+    postSheetHeightMsg
+  }
+}

+ 4 - 2
src/request/api.ts

@@ -85,8 +85,10 @@ export const ChartApi = {
 
 /* 表格模块 */
 interface IExcelParams {
-	UniqueCode: string | any
-	FromScene: number
+	UniqueCode: string | any;
+	FromScene: number;
+	ReferencedId:number;
+	Uuid: string;
 }
 interface IFreshParams {
 	UniqueCode: string | any

+ 1 - 1
src/views/chartShow/index.vue

@@ -157,7 +157,7 @@ export default defineComponent({
         // setLangFromEnReport();
         document.title = language.value==='zh'?Data.ChartInfo.ChartName:Data.ChartInfo.ChartNameEn;
 
-        state.options = useChartRender(Data,language.value)
+        state.options = useChartRender(Data,language.value as string)
         
         haveData.value = true;
         type === 'refresh' && ElMessage.success('刷新成功');

+ 27 - 15
src/views/sheetShow/index.vue

@@ -3,14 +3,19 @@ import { ref, onMounted, nextTick } from 'vue';
 import { useRoute } from 'vue-router';
 import { SheetApi } from '@/request/api';
 import sheet from '@/components/sheet.vue'
+import { isMobile } from '@/utils/utils';
 import { IUnknowObject } from '@/types';
 import { ElMessage } from 'element-plus';
+import { useResizeTable } from '@/hooks/sheet/useResizeTable';
+
+const { postSheetHeightMsg } = useResizeTable();
 
 const route = useRoute();
 const code = ref(route.query.code || '')
 
 // route.query.fromScene 1智能研报 2研报列表 3英文研报
-
+// verison 2 可拖拽行高列宽 接收参数sourceId (reportId||pptId)  uid插入时唯一编码
+// /sheetshow?code=3be976b227a0531ceda74c1407832a8d&fromScene=2&sourceId=&uid=
 interface InfoType extends IUnknowObject {
   ExcelName: string;
   TableInfo: any;
@@ -33,7 +38,12 @@ const setDefaultSource=(sourceText:string)=>{
 
 const getInfo = async(type='') => {
   loading.value = true;
-  const { Data,Ret } = await SheetApi.getInfo({  UniqueCode: code.value, FromScene: Number(route.query.fromScene||'') });
+  const { Data,Ret } = await SheetApi.getInfo({  
+    UniqueCode: code.value,
+    FromScene: Number(route.query.fromScene||''),
+    ReferencedId: Number(route.query.sourceId||''),
+    Uuid: (route.query.uid as string)||""
+  });
   
   loading.value = false;
   if(Ret !== 200) return
@@ -44,17 +54,6 @@ const getInfo = async(type='') => {
   }
   showData.value = true; 
   type==='refresh'&&ElMessage.success('刷新成功')
-  nextTick(() => {
-    let ele = document.getElementsByClassName('sheet-show-wrapper')[0] as HTMLElement;
-
-    let params = {
-      height: ele.offsetHeight,
-      code: info.value.UniqueCode
-    }
-  
-    window.parent.postMessage(params,'*')
-
-  })
 
 }
 getInfo()
@@ -80,7 +79,11 @@ const refreshSheet = async()=>{
   >
     <!-- <h3 class="title">{{info.ExcelName}}</h3> -->
     
-    <sheet :data="info.TableInfo.TableDataList" :config="info.Config"/>
+    <sheet 
+      :data="info.TableInfo.TableDataList" 
+      :config="info.Config"
+      :sceneConfig="info.ReferencedExcelConfig"
+    />
     <div class="tool sheet-bottom">
       <div class="sheet-source" 
         v-if="info.SourcesFrom&&JSON.parse(info.SourcesFrom).isShow"
@@ -93,7 +96,10 @@ const refreshSheet = async()=>{
       </div>
       <!-- 占位 -->
       <div v-else></div>
-      <span @click="refreshSheet" style="color: #666;">刷新</span>
+      <div class="right-btns">
+        <span @click="postSheetHeightMsg('update')" v-if="route.query.sourceId&&!isMobile()">更新样式</span>
+        <span @click="refreshSheet">刷新</span>
+      </div>
     </div>
   </div>
 </template>
@@ -131,6 +137,12 @@ const refreshSheet = async()=>{
       overflow: hidden;
       text-overflow: ellipsis;
     }
+    .right-btns {
+      display: flex;
+      align-items: center;
+      gap:15px;
+      color: #666;
+    }
   }
 }
 </style>