Browse Source

生成指标

Karsa 1 year ago
parent
commit
e954458eaa

+ 36 - 41
src/api/modules/sheetApi.js

@@ -260,82 +260,77 @@ export const getDateLatelyData = params => {
 /* =====自定义分析==== */
 
 export const sheetAnalysisInterface = {
-	/**
-	 * 获取分类
-	 * @returns 
-	 */
-	classifyList: params =>{
-		return http.get('/datamanage/excel_classify/list',params)
-	},
 
 	/**
-	 * 新增分类
-	 * @param {*} params  "ExcelClassifyName": "分类1-2"
+	 * 移动表格
+	 * @param {*} params ExcelClassifyId ExcelInfoId PrevExcelInfoId NextExcelInfoId
 	 * @returns 
 	 */
-	classifyAdd: params =>{
-		return http.post('/datamanage/excel_classify/add',params)
+	sheetMove: params => {
+		return http.post('/datamanage/excel_info/move',params)
 	},
-
+	
 	/**
-	 * 编辑分类
-	 * @param {*} params  ExcelClassifyName ExcelClassifyId
+	 * 新增表格
+	 * @param {*} params ExcelName ExcelClassifyId ExcelImage Content
 	 * @returns 
 	 */
-	classifyEdit: params =>{
-		return http.post('/datamanage/excel_classify/edit',params)
+	excelSheetAdd: params => {
+		return http.post('/custom_analysis/add',params)
 	},
 
 	/**
-	 * 删除分类检测
-	 * @param {*} params ExcelClassifyId ExcelInfoId
+	 * 获取详情
+	 * @param {*} params UniqueCode
 	 * @returns 
 	 */
-	classifyDelCheck: params =>{
-		return  http.post('/datamanage/excel_classify/delete/check',params)
+	getExcelDetail: params => {
+		return http.get('/custom_analysis/excel/base',params)
 	},
 
 	/**
-	 * 删除分类
-	 * @param {*} params ExcelClassifyId ExcelInfoId
+	 * 分页加载celldata
+	 * @param {*} params  UniqueCode Page
 	 * @returns 
 	 */
-	classifyDel: params =>{
-		return  http.post('/datamanage/excel_classify/delete',params)
+	getExcelDataByPage: params => {
+		return http.get('/custom_analysis/excel/data',params)
 	},
 
 	/**
-	 * 移动分类
-	 * @param {*} params ClassifyId "PrevClassifyId":1, "NextClassifyId":2,
-	 * @returns 
+	 * 表格保存
+	 * @param {*} params ExcelName ExcelInfoId ExcelClassifyId ExcelImage Content
 	 */
-	classifyMove: params =>{
-		return  http.post('/datamanage/excel_classify/move',params)
+	sheetEdit: params => {
+		return http.post('/custom_analysis/save',params)
 	},
 
 	/**
-	 * 移动表格
-	 * @param {*} params ExcelClassifyId ExcelInfoId PrevExcelInfoId NextExcelInfoId
+	 * 生成指标
+	 * @param {*} params  
+	 * EdbName ExcelInfoId ClassifyId Frequency Unit DateSequenceVal DataSequenceVal DateSequenceStr DataSequenceStr
 	 * @returns 
 	 */
-	sheetMove: params => {
-		return http.post('/datamanage/excel_info/move',params)
+	edbAddBysheet: params => {
+		return http.post('/custom_analysis/edb/add',params)
 	},
 
 	/**
-	 * 表格列表
-	 * @param {*} params  CurrentIndex  PageSize  ExcelClassifyId 
+	 * 指标编辑
+	 * @param {*} params 
+	 * EdbName ExcelInfoId EdbInfoId ClassifyId Frequency Unit DateSequenceVal DataSequenceVal
+	 * @returns 
 	 */
-	sheetList: params => {
-		return http.get('/datamanage/excel_info/list',params)
+	edbEditBysheet: params => {
+		return http.post('/custom_analysis/edb/edit',params)
 	},
 
 	/**
-	 * 表格分类
-	 * @param {*} params 
+	 * 获取表格生成的指标列表
+	 * @param {*} params ExcelInfoId
 	 * @returns 
 	 */
-	excelClassifyOne: params => {
-		return http.get('/datamanage/excel_classify/items',params)
+	edbListBySheet: params => {
+		return http.get('/custom_analysis/edb/list',params)
 	}
 }

BIN
src/assets/img/home/loading.gif


+ 0 - 5
src/routes/modules/chartRoutes.js

@@ -126,11 +126,6 @@ export default [
 				name:"生成指标",
 				component:()=>import('@/views/datasheet_manage/customAnalysis/addAnalysisSheet.vue')
 			},
-			{
-				path:"lookTaregtBySheet",
-				name:"查看指标",
-				component:()=>import('@/views/datasheet_manage/customAnalysis/addAnalysisSheet.vue')
-			},
 		]
 	},
 

+ 2 - 2
src/views/dataEntry_manage/databaseList.vue

@@ -1160,9 +1160,9 @@ export default {
 		editNode(node,data) {
 			this.dialog_title = '编辑';
 			if(data.EdbCode) {
-				/* 编辑指标 */
+				/* 编辑指标 基础弹窗 */
 				
-				(data.EdbType===1 || [58,59,67,68].includes(data.Source)) && dataBaseInterface.targetDetail({
+				(data.EdbType===1 || [58,59,67,68,74].includes(data.Source)) && dataBaseInterface.targetDetail({
 					EdbInfoId: data.EdbInfoId
 				}).then(res => {
 					if(res.Ret === 200) {

+ 19 - 7
src/views/datasheet_manage/common/option.js

@@ -21,7 +21,6 @@ export function initSheet(container,options={},sheetInfo={}) {
       image: false, // 插入图片
       link: false, // 插入链接
     },
-    ...options,
     hook: {
       updated: (a,b,c,d,e)=> {
 
@@ -37,7 +36,8 @@ export function initSheet(container,options={},sheetInfo={}) {
           })
         }
       }
-    }
+    },
+    ...options
   }
 
   luckysheet.create(configOpt)
@@ -47,12 +47,24 @@ export function initSheet(container,options={},sheetInfo={}) {
 /* 保存表格关联截图 手动选区截图再清空选区 */
 export const getSheetImage = (data) => {
   const { celldata } = data;
-  
-  const r_arr = celldata.map(_ => _.c);
-  let r_start = celldata[0].r,
-    r_end = celldata[celldata.length-1].r,
-    c_start = Math.min(...r_arr),
+
+  //超过1000个就不遍历了
+  let r_start,r_end,c_start,c_end;
+  if(celldata.length > 1000) {
+    const splitData = celldata.slice(0,1000);
+    const r_arr = splitData.map(_ => _.c);
+    r_start = splitData[0].r;
+    r_end = splitData[splitData.length-1].r;
+    c_start = Math.min(...r_arr);
     c_end = Math.max(...r_arr);
+
+  }else {
+    const r_arr = celldata.map(_ => _.c);
+    r_start = celldata[0].r;
+    r_end = celldata[celldata.length-1].r;
+    c_start = Math.min(...r_arr);
+    c_end = Math.max(...r_arr);
+  }
   
   luckysheet.setRangeShow({row:[r_start,r_end],column:[c_start,c_end]},{show: false})
   let img = luckysheet.getScreenshot()

+ 1 - 0
src/views/datasheet_manage/components/sheetClassifyDia.vue

@@ -84,6 +84,7 @@ export default {
 				'/sheetList': this.sheetClassifyApi,
 				'/sheetTimeList': this.sheetClassifyApi,
 				'/sheetMixedList': this.sheetClassifyApi,
+				'/sheetAnalysisList': this.sheetClassifyApi,
 				'/commordityChartBase': this.commodityClassifyApi,
 				'/chartrelevance':this.relevanceClassifyApi,
 				'/fittingEquationList': this.fittingEquationClassifyApi,

+ 218 - 25
src/views/datasheet_manage/customAnalysis/addAnalysisSheet.vue

@@ -1,12 +1,14 @@
 <template>
   <div class="addSheet-wrap">
-    <div :class="['main',{'full-height':$route.path!=='/addAnalysisSheet'}]">
+    
+    <createTargetForm ref="createTargetRef" @save="handleCreateTarget" v-if="$route.path==='/createTaregtBySheet'"/>
+
+
+    <div class="main">
       <div class="left-section">
         <el-tabs 
           v-model="selectIndex" 
           type="card"
-          @tab-remove="handleRemoveSheet"
-          @tab-click="handleSwitchSheet"
         >
           <el-tab-pane
             :key="item.name"
@@ -15,19 +17,33 @@
             :name="String(index)"
           />
         </el-tabs>
-        <div class="sheet-wrapper" v-loading="isLoading">
+        <div class="sheet-wrapper">
           <Sheet ref="sheetRef" :option="sheetConfig" v-if="sheetConfig.data"/>
+
+          <dataLoading :loading="isLoading"/>
         </div>
 
         <!-- <tableNoData text="暂无数据" v-else/> -->
       </div>
 
-      <rightSection v-if="$route.path!=='/addAnalysisSheet'"/>
+      <!-- 指标列表 -->
+      <rightSection 
+        ref="edbWrapRef"
+        v-if="$route.path==='/createTaregtBySheet'"
+        :list="edbList"
+        @choose="chooseEdbHandle"
+      />
     </div>
 
 
     <!-- 上传文件 -->
-    <bottomSection v-if="$route.path==='/addAnalysisSheet'" :sheetList="sheetConfig.data||[]"/>
+    <bottomSection
+      ref="bottomSecRef"
+      v-if="$route.path==='/addAnalysisSheet'" 
+      :sheetList="sheetConfig.data||[]"
+      :classifyArr="classifyArr"
+      @save="handleAddSheet"
+    />
 
   </div>
 </template>
@@ -38,8 +54,10 @@ import Sheet from '../components/SheetExcel.vue';
 import { getSheetImage } from '../common/option';
 import bottomSection from './components/bottomSection.vue'
 import rightSection from './components/rightSection.vue';
+import createTargetForm from './components/createTargetForm.vue';
+import { escape } from '@antv/x6/lib/util/string/string';
 export default {
-  components: { Sheet,bottomSection,rightSection },
+  components: { Sheet,bottomSection,rightSection,createTargetForm },
   computed: {
     files() {
       return this.$store.state.sheet.files;
@@ -54,11 +72,24 @@ export default {
       maxPage:0,
 
       selectIndex: '0',
+      classifyArr: [],
       sheetConfig: {
         showsheetbar: true,
-        // enablePage: true
-        data: null
-      }
+        data: null,
+        hook: {
+          //选区时
+          rangeSelect: (sheet,range) => {
+            if(this.$refs.createTargetRef && this.$refs.createTargetRef.selectArea && !this.$refs.createTargetRef.isLockUpdate) this.getRangeCell()
+          }
+        }
+      },
+
+      sheetDetailInfo: {},
+      sheetDataPage: 2,
+      sheetAllcellData:[],//全部单元格数据 分页push
+      dataToalPage: 0,
+
+      edbList: [],//生成的指标列表
     }
   },
   methods: {
@@ -75,7 +106,7 @@ export default {
 
     /* 获取分类 */
     getClassify() {
-      sheetInterface.excelClassifyOne().then(res => {
+      sheetInterface.excelClassifyOne({Source: 4}).then(res => {
         if(res.Ret !==200) return
         
         this.classifyArr = res.Data.AllNodes || [];
@@ -86,7 +117,9 @@ export default {
       let len = this.sheetConfig.data.length;
       for(let i =0;i<len;i++) {
         if(this.allSheetData[i].celldata[this.currentPage*this.pageSize]) {
-          this.sheetConfig.data[i].celldata = this.sheetConfig.data[i].celldata.concat(this.allSheetData[i].celldata.slice(this.currentPage*this.pageSize, (this.currentPage+1)*this.pageSize))
+          let concatData = this.allSheetData[i].celldata.slice(this.currentPage*this.pageSize, (this.currentPage+1)*this.pageSize);
+
+          // this.sheetConfig.data[i].celldata = this.sheetConfig.data[i].celldata.concat(concatData) 
           // this.$refs.sheetRef.init()
         }
         continue
@@ -110,18 +143,20 @@ export default {
       //   config: _.config
       // }));
       // this.maxPage = Math.max(...sheets.map(_ =>  Math.ceil(_.celldata.length / this.pageSize)))
+      console.log(sheets)
 
       this.sheetConfig.data = sheets.map(_ => ({
         index: _.index, //工作表索引
-        order: _.order, //工作表的下标
+        order: Number(_.order), //工作表的下标
         name: _.name,
         calcChain: _.calcChain,
         config: _.config,
         celldata: _.celldata,
       }));
       
-      //辣鸡插件连更新数据的api都没有 做切片加载都做不了
-      // this.loadDataSync();
+      //辣鸡插件连更新数据的api都没有
+       //  this.loadDataSync();
+      
       this.isLoading = false;
     },
 
@@ -157,12 +192,10 @@ export default {
 
 
     /* 保存表格 */
-    saveSheetHandle: _.debounce(async function() {
-      const { name,classify } = this.sheetForm;
+    handleAddSheet: _.debounce(async function() {
       luckysheet.exitEditMode()
-      let data = luckysheet.getAllSheets()[0]
-      if(!name || !classify) return this.$message.warning(name ? '请选择表格分类' : '请输入表格名称')
-      if(!data.celldata.length) return this.$message.warning('请输入表格内容');
+      let data = luckysheet.getAllSheets().filter(_ => this.$refs.bottomSecRef.sheetChecked.includes(_.name));
+      console.log(data)
 
       this.loading = this.$loading({
 				target:'.addSheet-wrap',
@@ -171,15 +204,15 @@ export default {
 				spinner: 'el-icon-loading',
 				background: 'rgba(255, 255, 255, 0.6)'
 			});
-      let img = getSheetImage(data);
+      let img = getSheetImage(data[0]);
 			const form  = new FormData();
 			form.append('Image', img);
 			const { Data } = await sheetInterface.uploadImg(form)
 
       data.luckysheet_select_save = [];
-      const res = await sheetInterface.sheetAdd({
-        ExcelName: name,
-        ExcelClassifyId: classify,
+      const res = await sheetInterface.sheetAnalysisInterface.excelSheetAdd({
+        ExcelName: this.uploadSheetsList[0].name,
+        ExcelClassifyId: this.$refs.bottomSecRef.select_classify,
         ExcelImage: Data.ResourceUrl,
         Content: JSON.stringify(data)
       })
@@ -191,22 +224,182 @@ export default {
       const { ExcelInfoId, UniqueCode } = res.Data;
       
       this.$router.replace({
-        path: '/sheetList',
+        path: '/sheetAnalysisList',
         query: {
           code: UniqueCode,
           id: ExcelInfoId
         }
       })
     },300),
+
+     /* 获取表格详情 */
+    getDetailHandle() {
+      this.isLoading = true;
+      sheetInterface.sheetAnalysisInterface.getExcelDetail({
+        UniqueCode: this.$route.query.code,
+      }).then((res) => {
+        if (res.Ret !== 200) return;
+
+        this.sheetDetailInfo = res.Data.ExcelInfo;
+        this.dataToalPage =  Math.max(...res.Data.SheetList.map(_ => _.PageNum));
+        this.sheetAllcellData = res.Data.SheetList.map(_ => JSON.parse(_.Data.Data));
+
+        this.getCellData(res.Data.SheetList)
+      });
+    },
+
+    //分页获取表格数据
+    async getCellData(sheets) {
+
+      let res = await sheetInterface.sheetAnalysisInterface.getExcelDataByPage({
+        UniqueCode: this.$route.query.code,
+        Page: this.sheetDataPage
+      })
+
+      if(res.Ret !== 200) return
+
+      for(let i = 0;i<this.sheetAllcellData.length;i++) {
+        if(res.Data[i].Data) {
+          this.sheetAllcellData[i] = [...this.sheetAllcellData[i],...JSON.parse(res.Data[i].Data.Data)]
+        }
+        continue
+      }
+      
+      //数据继续加载或渲染表格
+      if(this.sheetDataPage < this.dataToalPage) {
+        this.sheetDataPage++;
+        this.getCellData(sheets)
+      }else {
+        this.sheetConfig.data = sheets.map((_,index) => ({
+          // index: _.Sort, //工作表索引
+          order: _.Sort, //工作表的下标
+          name: _.SheetName,
+          calcChain: JSON.parse(_.CalcChain),
+          config: JSON.parse(_.Config),
+          celldata: this.sheetAllcellData[index],
+        }))
+
+        this.isLoading = false;
+        this.getTargetList()
+      }
+    },
+
+
+    /* 获取选取对应单元格数组和拼接选取的公式 
+      Sheet1!$A$1:$A$25
+      Sheet1!$E:$E
+    */
+    getRangeCell: _.debounce(function() {
+      let sheet = luckysheet.getSheet();
+      let rangeArr = luckysheet.getRangeAxis();
+
+      if(rangeArr.length > 1) return this.$message.warning('同时只允许选择一块区域');
+      //检查选取是否满足同行/同列
+      if(!this.checkRangeVaild(rangeArr[0])) return this.$message.warning('序列只允许选择同行或同列');
+
+      let rangeCells = luckysheet.getRangeValue().flat().map(_=>_?_.m:'');
+
+      let format = `${sheet.name}!${this.formatStr(rangeArr[0])}`;
+
+      console.log(format)
+      this.$refs.createTargetRef.setFormula(format,rangeCells)
+    },300),
+
+    //检验同行同列
+    checkRangeVaild(range) {
+      let reg = /^([A-Z]+)(\d+)$/;
+      let arr = range.split(':').map(_ => [_.match(reg)[1],_.match(reg)[2]]);
+      
+      if(arr.length ===1) return true;
+
+      if(arr[0][0] === arr[1][0] || arr[0][1] === arr[1][1]) {
+        return true
+      }else {
+        return false
+      }
+    },
+
+    formatStr(inputRange) {
+      // 将字母和数字前面都拼接"$"
+      const parts = inputRange.split(':');
+      if (parts.length === 2) {
+          const start = parts[0].replace(/(^[A-Z]+)(\d+)$/, '$$$1$$$2');
+          const end = parts[1].replace(/(^[A-Z]+)(\d+)$/, '$$$1$$$2');
+          return start + ':' + end;
+      }
+      return inputRange;
+      
+    },
+    
+    /* 生成指标 */
+    async handleCreateTarget() {
+      console.log(this.$refs.createTargetRef.formData)
+      const { edbInfoId,
+        dateSeries,
+        valueSeries,
+        dateArr,
+        valueArr,
+				edbName,
+				classify,
+				frequency,
+				unit } = this.$refs.createTargetRef.formData;
+      let params = {
+        EdbName: edbName,
+        ExcelInfoId: this.sheetDetailInfo.ExcelInfoId,
+        ClassifyId: classify,
+        Frequency: frequency,
+        Unit: unit,
+        DateSequenceVal: dateArr,
+        DataSequenceVal: valueArr,
+        DateSequenceStr: dateSeries,
+        DataSequenceStr: valueSeries
+      }
+      const res = edbInfoId 
+        ? await sheetInterface.sheetAnalysisInterface.edbEditBysheet({...params,EdbInfoId: edbInfoId})
+        : await sheetInterface.sheetAnalysisInterface.edbAddBysheet(params)
+
+      if(res.Ret !== 200) return
+
+      this.$message.success(res.Msg)
+
+      if(!edbInfoId) this.$refs.createTargetRef.initData();
+
+      this.getTargetList()
+    },
+
+    /* 获取生成指标列表 */
+    async getTargetList() {
+      const res = await sheetInterface.sheetAnalysisInterface.edbListBySheet({
+        ExcelInfoId: this.sheetDetailInfo.ExcelInfoId
+      })
+
+      if(res.Ret !== 200) return
+      
+      this.edbList = res.Data || [];
+    },
+
+    /* 选择指标列表更新表单信息和区域选中 */
+    chooseEdbHandle() {
+
+      if(this.$refs.edbWrapRef.selectEdb.EdbInfoId) {
+        this.$refs.createTargetRef.initData(this.$refs.edbWrapRef.selectEdb)
+      } else {
+        this.$refs.createTargetRef.initData()
+      }
+    }
     
   },
   mounted() {
     this.getClassify();
+    //上传文件的解析渲染
     if(this.files) {
       this.uploadSheetsList =  Object.values(this.files);
       this.handelTranslateData()
       this.$store.commit('sheet/SET_UPLOADFIlES',null)
     }
+
+    //详情的渲染
+    if(this.$route.query.code) this.getDetailHandle();
   }
 }
 </script>

+ 13 - 9
src/views/datasheet_manage/customAnalysis/components/bottomSection.vue

@@ -3,7 +3,7 @@
 
     <!-- 无同名 -->
     <div>
-      <div class="page-list">
+      <div class="page-list" v-if="sheetPages.length">
         <el-checkbox :indeterminate="isIndeterminate" v-model="checkAll" @change="handleCheckAllChange" style="margin-right:30px">全部</el-checkbox>
         <el-checkbox-group v-model="sheetChecked" @change="handleCheckedChange">
           <el-checkbox v-for="item in sheetPages" :label="item" :key="item">{{item}}</el-checkbox>
@@ -12,7 +12,7 @@
 
       <div>
         <el-select 
-          v-model="classify"
+          v-model="select_classify"
           placeholder="请选择表格目录"
           clearable
           style="width:350px;"
@@ -69,36 +69,40 @@ export default {
   props: {
     sheetList: {
       type: Array
+    },
+    classifyArr: {
+      type: Array
     }
   },
   watch: {
     sheetList(nval) {
       this.sheetPages = nval.map(_ => _.name)
+      this.sheetChecked = this.sheetPages;
     }
   },
   data() {
     return {
       isIndeterminate: false,
-      checkAll: false,
-      sheetPages: this.sheetList.map(_ => _.name),
+      checkAll: true,
+      sheetPages: [],
       sheetChecked: [],
 
-      sheetForm: {},
-      classifyArr: [],
+      select_classify: '',
+      classifyArr: this.classifyArr,
     }
   },
   methods:{
     saveSheetHandle() {
       if(!this.sheetChecked.length) return this.$message.warning('请选择要保存的sheet页')
-    },
+      if(!this.select_classify) return this.$message.warning('请选择分类')
 
-    initStatus() {
-      this.sheetChecked = [];
+      this.$emit('save')
     },
 
     handleCheckedChange(val){
       this.checkAll = val.length === this.sheetPages.length;
       this.isIndeterminate = val.length > 0 && val.length < this.sheetPages.length;
+      console.log(this.sheetChecked)
     },
     handleCheckAllChange(val){
       this.sheetChecked = val ? this.sheetPages : [];

+ 249 - 0
src/views/datasheet_manage/customAnalysis/components/createTargetForm.vue

@@ -0,0 +1,249 @@
+<template>
+  <div class="create-form-cont">
+    <el-form
+      ref="formRef"
+      label-position="left"
+      hide-required-asterisk
+      inline
+      label-width="0"
+      :model="formData"
+      :rules="formRules"
+    >
+      <el-form-item prop="dateSeries">
+        <el-input v-model="formData.dateSeries" placeholder="请选择日期序列" @focus="selectArea='date'" @change="changeFormat('date')" @keyup.native="e => { e.keyCode===13 && initSelect()}" :class="{'select': selectArea==='date'}"></el-input>
+      </el-form-item>
+      <el-form-item prop="valueSeries">
+        <el-input v-model="formData.valueSeries" placeholder="请选择数值序列" @focus="selectArea='value'" @change="changeFormat('value')" @keyup.native="e => { e.keyCode===13 && initSelect()}" :class="{'select': selectArea==='value'}"></el-input>
+      </el-form-item>
+
+      <el-form-item prop="edbName">
+        <el-input v-model="formData.edbName" placeholder="指标名称" @focus="initSelect"></el-input>
+      </el-form-item>
+      <el-form-item prop="classify">
+        <el-cascader
+          v-model="formData.classify"
+          :options="classifyOption"
+          style="width: 100%"
+          @focus="initSelect"
+          :props="{
+            label: 'ClassifyName',
+            value: 'ClassifyId',
+            children: 'Children',
+            emitPath: false,
+          }"
+          clearable
+          placeholder="请选择所属目录"
+        />
+      </el-form-item>
+      <el-form-item prop="frequency">
+        <el-select
+          v-model="formData.frequency"
+          placeholder="请选择频率"
+          style="width: 100%"
+          @focus="initSelect"
+          clearable
+        >
+          <el-option
+            v-for="item in frequencyArr"
+            :key="item"
+            :label="item"
+            :value="item"
+          >
+          </el-option>
+        </el-select>
+      </el-form-item>
+      <el-form-item prop="unit">
+        <selectUnit v-model="formData.unit" @click.native="initSelect"/>
+      </el-form-item>
+      
+      <el-form-item>
+        <el-button type="primary" @click="handleSaveTarget">保存</el-button>
+      </el-form-item>
+    </el-form>
+  </div>
+</template>
+<script>
+import {dataBaseInterface} from '@/api/api.js'
+export default {
+  data() {
+    return {
+      selectArea: '',
+      formData: {
+        edbInfoId: 0,
+        dateSeries: '',
+        valueSeries: '',
+        dateArr:[],
+        valueArr: [],
+				edbName:'',
+				classify:'',
+				frequency: '',
+				unit:'',
+      },
+      formRules: {
+        // dateSeries: [{ required: true, message: '日期序列不能为空', trigger: 'blur' }],
+        // valueSeries: [{ required: true, message: '数值序列不能为空', trigger: 'blur' }],
+        edbName: [{ required: true, message: '指标名称不能为空', trigger: 'blur' }],
+        classify: [{ required: true, message: '目录不能为空', trigger: 'blur' }],
+        frequency: [{ required: true, message: '频率不能为空', trigger: 'blur' }],
+        unit: [{ required: true, message: '单位不能为空', trigger: 'blur' }],
+      },
+      frequencyArr:['日度','周度','旬度','月度','季度','年度'],
+      classifyOption: [],
+
+      isLockUpdate: false,//防止手动改变公式设置选区出发hook事件又更新公式和值 手动设置值即可
+    };
+  },
+  methods: {
+
+    /* 选区时更新公式 */
+    setFormula(formula,arr) {
+      if(!this.selectArea) return
+      //更新日期序列公式
+      if(this.selectArea === 'date') {
+        this.formData.dateArr = arr;
+        this.formData.dateSeries = formula
+      }else if(this.selectArea === 'value') {
+        //更新数值序列公式
+        this.formData.valueArr = arr;
+         this.formData.valueSeries = formula
+      }
+
+      console.log(this.formData)
+    },
+
+    /* 获取分类 */
+		getMenu() {
+			dataBaseInterface.menuListV3().then((res) => {
+				if (res.Ret !== 200) return
+
+				this.classifyOption = res.Data.AllNodes || [];
+			});
+		},
+
+    /* 改变公式 */
+    changeFormat(type) {
+      this.isLockUpdate = true;
+      this.setRangeShow(type==='date'?this.formData.dateSeries:this.formData.valueSeries)
+      
+      let rangeArr = luckysheet.getRangeAxis();
+
+      //检查选取是否满足同行/同列
+      if(!this.$parent.checkRangeVaild(rangeArr[0])){
+        type==='date'?this.formData.dateSeries = '':this.formData.valueSeries ='';
+        return this.$message.warning('序列只允许选择同行或同列');
+      } 
+
+      let rangeCells = luckysheet.getRangeValue().flat().map(_=>_?_.m:'');
+      //更新公式关联的数据数组
+      type==='date' ? this.formData.dateArr = rangeCells : this.formData.valueArr = rangeCells;
+      console.log(this.formData)
+      this.isLockUpdate = false;
+    },
+
+    initSelect() {
+      this.selectArea = ''
+    },
+
+    initData(data=null) {
+      this.initSelect()
+      if(data) {
+        this.formData = {
+          edbInfoId: data.EdbInfoId,
+          dateSeries: data.DateSequenceStr,
+          valueSeries: data.DataSequenceStr,
+          dateArr:[],
+          valueArr: [],
+          edbName: data.EdbName,
+          classify: data.ClassifyId,
+          frequency: data.Frequency,
+          unit: data.Unit,
+        }
+
+        this.setRangeShow([data.DateSequenceStr,data.DataSequenceStr]);
+      }else {
+        this.formData = {
+          edbInfoId: 0,
+          dateSeries: '',
+          valueSeries: '',
+          dateArr:[],
+          valueArr: [],
+          edbName:'',
+          classify:'',
+          frequency: '',
+          unit:'',
+        }
+        
+        this.setRangeShow(['A1','A1'])
+      }
+    },
+
+    /* 解析公式显示选区 */
+    setRangeShow(range) {
+      
+      //初始化多选区
+      let rangeArr = [];
+      if(Array.isArray(range)) {
+        range.forEach(_ => {
+          rangeArr.push(this.splitFormula(_))
+        })
+      }else {
+        rangeArr = [this.splitFormula(range)]
+      }
+      luckysheet.setRangeShow(rangeArr)
+    },
+
+    /* 解析公式 */
+    splitFormula(formula) {
+      let str = formula.substr(formula.indexOf('!')+1).replace(/\$/g,'')
+      return str
+    },
+
+    /* 保存 */
+    async handleSaveTarget() {
+      if(!this.formData.dateSeries) return this.$message.warning('日期序列不能为空')
+      if(!this.formData.valueSeries) return this.$message.warning('数值序列不能为空')
+
+      await this.$refs.formRef.validate();
+      this.initSelect();
+      this.$emit('save')
+    },
+  },
+  
+  mounted() {
+    this.getMenu()
+  },
+};
+</script>
+<style scoped lang="scss">
+.create-form-cont {
+  background: #fff;
+  margin-bottom: 20px;
+  display: flex;
+  flex-wrap: wrap;
+  padding: 20px;
+  .el-form-item {
+    margin-bottom: 20px;
+    /* .select {
+      &::before {
+        content: '';
+        position: absolute;
+        left: 0;
+        right: 0;
+        top: 0;
+        bottom: 0;
+        border: 2px dashed #18ad18;
+        border-radius: 4px;
+      }
+    } */
+  }
+}
+</style>
+
+<style lang="scss">
+  .create-form-cont {
+    .select .el-input__inner {
+       border: 2px dashed #18ad18;
+      border-radius: 4px;
+    }
+  }
+</style>

+ 40 - 99
src/views/datasheet_manage/customAnalysis/components/rightSection.vue

@@ -1,113 +1,62 @@
 <template>
   <div class="right-section-wrapper">
-    <!-- 生成指标 -->
     <div class="create-cont">
-      <div class="head">生成指标</div>
-      <div class="form-bottom">
-        <el-form
-          ref="diaForm"
-          label-position="top"
-          hide-required-asterisk
-          label-width="80px"
-          :model="formData"
-        >
-          <el-form-item prop="dateSeries">
-            <span slot="label">分类名称</span>
-            <el-input v-model="formData.dateSeries"></el-input>
-          </el-form-item>
-          <el-form-item prop="valueSeries">
-            <span slot="label">数值序列</span>
-            <el-input v-model="formData.valueSeries"></el-input>
-          </el-form-item>
-
-          <el-form-item prop="edbName">
-            <span slot="label">指标名称</span>
-            <el-input
-            v-model="formData.edbName"
-            placeholder="指标名称"></el-input>
-          </el-form-item>
-          <el-form-item prop="menu">
-            <span slot="label">所属目录</span>
-            <el-cascader
-              v-model="formData.menu"
-              :options="classifyOption"
-              style="width:100%"
-              :props="{
-                label: 'ClassifyName',
-                value: 'ClassifyId',
-                children: 'Children',
-                emitPath: false
-              }"
-              clearable
-              placeholder="请选择所属目录"
-            />
-          </el-form-item>
-          <el-form-item prop="frequency">
-            <span slot="label">频率</span>
-            <el-select 
-              v-model="formData.frequency" 
-              placeholder="请选择频率"
-              style="width:100%"
-              clearable
-            >
-              <el-option
-                v-for="item in frequencyArr"
-                :key="item"
-                :label="item"
-                :value="item">
-              </el-option>
-            </el-select>
-          </el-form-item>
-          <el-form-item prop="unit">
-            <span slot="label">单位</span>
-            <selectUnit 
-              v-model="formData.unit" 
-            />
-          </el-form-item>
-        </el-form>
-        <el-button type="primary" style="width:100%;margin-top:50px">保存</el-button>
-      </div>
-    </div>
-
-    <!-- 查看指标 -->
-    <!-- <div class="create-cont">
-      <ul class="edb-list">
-        <li class="edb-item" v-for="(item,index) in edbList" :key="index">
+      <ul class="edb-list" v-if="edbList.length">
+        <li :class="['edb-item',{'selected':selectEdb.EdbInfoId===item.EdbInfoId}]" v-for="(item,index) in edbList" :key="index" @click="chooseEdb(item)">
           <span>{{item.EdbName}}</span>
           <div class="item-right">
-            <i class="el-icon-edit" style="margin-right:10px" @click.stop="editEdbSettingHandle"/>
-            <img :src="$icons.jupm_icon" alt="">
+            <!-- <i class="el-icon-edit" style="margin-right:10px" @click.stop="editEdbSettingHandle"/> -->
+            <img :src="$icons.jupm_icon" alt="" @click.stop="linkToEdbBase(item)">
           </div>
         </li>
       </ul>
-    </div> -->
+      <div style="padding-top: 50px;" v-else>
+        <tableNoData text="暂无指标"/>
+      </div>
+    </div>
   </div>
 </template>
 <script>
 export default {
+  props: {
+    list: {
+      type: Array
+    }
+  },
+  watch: {
+    list(nval) {
+      this.edbList = nval;
+    }
+  },
   data() {
     return {
-      formData: {
-        dateSeries: '',
-        valueSeries: '',
-				edbName:'',
-				menu:'',
-				frequency: '',
-				unit:'',
-      },
-      frequencyArr:['日度','周度','旬度','月度','季度','年度'],
-      classifyOption: [],
-
-      edbList:[{EdbName:'111'}]
+      edbList:[],
+      selectEdb: {},
     }
   },
   mounted(){
 
   },
   methods:{
-    /* 改变的依赖区域 */
-    editEdbSettingHandle() {
 
+    chooseEdb(item) {
+      if(item.EdbInfoId === this.selectEdb.EdbInfoId) {
+        this.selectEdb = {};
+      }else {
+        this.selectEdb = item;
+      }
+
+      this.$emit('choose')
+    },
+
+    //跳转指标库
+    linkToEdbBase({UniqueCode,EdbInfoId,ClassifyId}) {
+      let {href} = this.$router.resolve({path:'/database', query: {
+        code: UniqueCode,
+        id: EdbInfoId,
+        classifyId:ClassifyId
+      }});
+			window.open(href,'_blank');
     }
   },
 }
@@ -122,17 +71,9 @@ export default {
   background: #FFF;
   margin-left: 20px;
   .create-cont {
-    .head {
-      padding: 14px;
-      text-align: center;
-      border-bottom: 1px solid #C8CDD9;
-    }
-    .form-bottom {
-      padding: 30px;
-    }
-
     .edb-list {
       padding: 30px;
+      overflow-y: auto;
       .edb-item {
         display: flex;
         align-items: center;
@@ -142,7 +83,7 @@ export default {
         border-radius: 4px;
         border: 1px solid #C8CDD9;
         background: #FFF;
-        &.slect { 
+        &.selected { 
           border-color: $theme-color; background: #ECF2FE;
         }
         .item-right {

+ 0 - 23
src/views/datasheet_manage/customAnalysis/createTargetEditor.vue

@@ -1,23 +0,0 @@
-<template>
-  <div>
-
-  </div>
-</template>
-<script>
-export default {
-  data() {
-    return {
-
-    }
-  },
-  mounted(){
-
-  },
-  methods:{
-
-  },
-}
-</script>
-<style scoped lang='scss'>
-
-</style>

+ 103 - 110
src/views/datasheet_manage/customAnalysis/list.vue

@@ -11,8 +11,7 @@
       <div class="main-left left" id="left" v-show="!isSlideLeft">
         <div class="datasheet_top">
           
-          <el-button 
-            v-permission="permissionBtn.etaTablePermission.etaTable_excel"
+          <el-button
             type="primary" 
             style="margin-right:20px"
             :loading="isUploadLoading"
@@ -20,9 +19,7 @@
           >上传文件</el-button>
           <input type="file" @change="fileSelected" id="file"  style="display: none;">
           
-          <el-button>
-            <el-checkbox v-model="isShowMe"  @change="() => { getTreeData();getPublicList() }">只看我的</el-checkbox>
-          </el-button>
+          <el-checkbox v-model="isShowMe"  @change="() => { getTreeData();getPublicList() }">只看我的</el-checkbox>
         </div>
         <div class="search-cont">
           <el-select
@@ -142,7 +139,7 @@
         :style="isSlideLeft ? 'width:100%' : 'width:80%'"
       >
         <!-- 表格详情 -->
-        <div class="sheet-detail-wrapper" v-if="select_id">
+        <div class="sheet-detail-wrapper" v-if="select_id" >
           <div class="detail-top">
             <span class="author"
               >作者:{{ sheetDetailInfo.SysUserRealName }}</span
@@ -162,51 +159,24 @@
               v-else
             >
               {{ sheetDetailInfo.ExcelName }}
-              <i class="el-icon-edit" v-if="sheetDetailInfo.Source === 1" />
+              <i class="el-icon-edit"/>
             </span>
             <ul class="action-ul">
-              <li
-                class="editsty"
-                v-if="
-                  sheetDetailInfo.Button.OpButton&&permissionBtn.checkPermissionBtn(permissionBtn.etaTablePermission.etaTable_excel_save)
-                "
-              >
-                生成指标
-              </li>
-              <li
-                class="editsty"
-                v-if="
-                  sheetDetailInfo.Button.OpButton&&permissionBtn.checkPermissionBtn(permissionBtn.etaTablePermission.etaTable_excel_save)
-                "
-              >
-                更新文件
-              </li>
-              <li
-                class="editsty"
-                @click="saveHandle"
-                v-if="
-                  sheetDetailInfo.Button.OpButton&&permissionBtn.checkPermissionBtn(permissionBtn.etaTablePermission.etaTable_excel_save)
-                "
-              >
-                保存
-              </li>
+              <li class="editsty" @click="HandleToPath">生成指标</li>
+              <li class="editsty" @click="refreshSheet">刷新</li>
+              <li class="editsty" @click="saveHandle">保存</li>
               <li
                 class="editsty"
                 @click="saveOtherHandle"
-                v-if="sheetDetailInfo.Button.CopyButton&&permissionBtn.checkPermissionBtn(permissionBtn.etaTablePermission.etaTable_customize_otherSave)"
               >
                 另存为
               </li>
-              <li v-if="isDownLoadShow(sheetDetailInfo)"
-                class="editsty" @click="downloadExcel(sheetDetailInfo)">
+              <li class="editsty" @click="downloadExcel
+              (sheetDetailInfo)">
                 下载
               </li>
               <li
                 class="deletesty"
-                v-if="
-                  sheetDetailInfo.Button && sheetDetailInfo.Button.DeleteButton
-                  &&isDeleteShow(sheetDetailInfo)
-                "
                 @click="delSheetHandle({cell:sheetDetailInfo, type:'del'})"
               >
                 删除
@@ -214,17 +184,14 @@
             </ul>
           </div>
 
+          <dataLoading :loading="isSheetLoading"/>
+
           <!-- 表格 -->
           <div class="sheet-wrap">
             <Sheet
               ref="sheetRef"
-              :option="{
-                data: [{
-                  ...JSON.parse(sheetDetailInfo.Content),
-                  scrollTop: 0,
-                  scrollLeft: 0
-                }]
-              }"
+              v-if="sheetConfigOpt.data"
+              :option="sheetConfigOpt"
               :sheetInfo="{
                 ExcelInfoId: sheetDetailInfo.ExcelInfoId,
                 ExcelName: sheetDetailInfo.ExcelName,
@@ -366,6 +333,14 @@ export default {
       select_id: "", //选中的表格id
       sheetDetailInfo: {},
       sheet_title: "", //表格标题 双击标题修改时来存储最新值
+      sheetConfigOpt: {
+        showsheetbar: true,
+        data: null
+      },
+      sheetDataPage: 2,
+      sheetAllcellData:[],//全部单元格数据 分页push
+      dataToalPage: 0,
+      isSheetLoading: false,
 
       /* 表格列表 */
       publicHaveMove: true, //是否还有列表数据
@@ -389,7 +364,11 @@ export default {
         ],
       },
 
-      isShowMe: false
+      isShowMe: false,
+
+      sourceMap: {
+        '/sheetAnalysisList': 4,
+      },
     };
   },
   watch: {
@@ -402,6 +381,10 @@ export default {
     },
     /* 表格id */
     select_id(newval) {
+      this.sheetDataPage = 2,
+      this.sheetAllcellData = [],//全部单元格数据 分页push
+      this.dataToalPage = 0;
+      this.sheetConfigOpt.data = null;
       newval && this.getDetailHandle();
     },
 
@@ -436,7 +419,7 @@ export default {
 
     /* 获取表格分类 */
     getTreeData(params = null) {
-      sheetInterface.classifyList().then((res) => {
+      sheetInterface.classifyList({Source: this.sourceMap[this.$route.path],IsShowMe: this.isShowMe}).then((res) => {
         const { Ret, Data } = res;
         if (Ret !== 200) return;
 
@@ -458,6 +441,7 @@ export default {
             Keyword: query,
             CurrentIndex: 1,
             PageSize: 10000,
+            Source: this.sourceMap[this.$route.path]
           })
           .then((res) => {
             if (res.Ret !== 200) return;
@@ -533,6 +517,7 @@ export default {
         .classifyDel({
           ExcelClassifyId,
           ExcelInfoId,
+          Source: this.sourceMap[this.$route.path]
         })
         .then((res) => {
           if (res.Ret !== 200) return;
@@ -584,22 +569,8 @@ export default {
 
     /* 下载数据 */
     downloadExcel(cell) {
-      const { Source, FileUrl, ExcelInfoId, ExcelName } = cell;
-      let value = "";
-      if (Source === 1) {
-        value = FileUrl;
-        this.downLoad(value, ExcelName);
-      } else if ([2, 3].includes(Source)) {
-        value = `${this.downExcelFileUrl}&ExcelInfoId=${ExcelInfoId}`;
-
-        const a = document.createElement("a");
-        a.href = value;
-        a.target = "_blank";
-        a.download = ExcelName;
-        a.style.display = "none";
-        document.body.append(a);
-        a.click();
-      }
+      const { FileUrl, ExcelName } = cell;
+      this.downLoad(FileUrl, ExcelName);
     },
 
     downLoad(url, filename) {
@@ -622,8 +593,7 @@ export default {
     /* 保存表格 */
     saveHandle: _.debounce(async function () {
       luckysheet.exitEditMode();
-      let data = luckysheet.getAllSheets()[0];
-      if (!data.celldata.length) return this.$message.warning("请输入表格内容");
+      let data = luckysheet.getAllSheets();
 
       this.loading = this.$loading({
         target: ".dataSheet-container",
@@ -633,14 +603,14 @@ export default {
         background: "rgba(255, 255, 255, 0.6)",
       });
 
-      let img = getSheetImage(data);
+      let img = getSheetImage(data[0]);
       const form = new FormData();
       form.append("Image", img);
       const { Data } = await sheetInterface.uploadImg(form);
 
       data.luckysheet_select_save = [];
       const { ExcelInfoId, ExcelName, ExcelClassifyId } = this.sheetDetailInfo;
-      const res = await sheetInterface.sheetEdit({
+      const res = await sheetInterface.sheetAnalysisInterface.sheetEdit({
         ExcelInfoId,
         ExcelName,
         ExcelClassifyId,
@@ -652,7 +622,7 @@ export default {
       this.$message.success("保存成功");
       this.getTreeData();
 
-      this.getDetailHandle();
+      // this.getDetailHandle();
     }, 300),
 
     /* 获取表格列表 */
@@ -662,6 +632,8 @@ export default {
           CurrentIndex: this.sheet_page,
           PageSize: this.sheet_pages_size,
           ExcelClassifyId: this.select_classify || 0,
+          Source: this.sourceMap[this.$route.path],
+          IsShowMe: this.isShowMe 
         })
         .then((res) => {
           if (res.Ret !== 200) return;
@@ -694,25 +666,58 @@ export default {
 
     /* 获取表格详情 */
     getDetailHandle() {
-      sheetInterface
-        .sheetDetail({
-          ExcelInfoId: this.select_id,
-        })
-        .then((res) => {
-          if (res.Ret !== 200) return;
+      this.isSheetLoading = true;
+      sheetInterface.sheetAnalysisInterface.getExcelDetail({
+        UniqueCode: this.select_node,
+      }).then((res) => {
+        if (res.Ret !== 200) return;
 
-          this.sheetDetailInfo = res.Data;
+        this.sheetDetailInfo = res.Data.ExcelInfo;
+        this.dataToalPage =  Math.max(...res.Data.SheetList.map(_ => _.PageNum));
+        this.sheetAllcellData = res.Data.SheetList.map(_ => JSON.parse(_.Data.Data));
 
-          this.$nextTick(() => {
-            this.sheetDetailInfo.Source === 1 && this.$refs.sheetRef.init();
+        this.getCellData(res.Data.SheetList)
+      });
+    },
 
-            this.sheetDetailInfo.Source === 2 &&
-              this.$refs.customTableRef.initSheetData(res.Data.TableData);
+    //分页获取表格数据
+    async getCellData(sheets) {
 
-            this.sheetDetailInfo.Source === 3 &&
-              this.$refs.mixedTableRef.initData(res.Data.TableData);
-          });
-        });
+      let res = await sheetInterface.sheetAnalysisInterface.getExcelDataByPage({
+        UniqueCode: this.select_node,
+        Page: this.sheetDataPage
+      })
+
+      if(res.Ret !== 200) return
+      console.log(this.sheetAllcellData)
+
+      for(let i = 0;i<this.sheetAllcellData.length;i++) {
+        if(res.Data[i].Data) {
+          this.sheetAllcellData[i] = [...this.sheetAllcellData[i],...JSON.parse(res.Data[i].Data.Data)]
+        }
+
+        continue
+      }
+      
+      //数据继续加载或渲染表格
+      if(this.sheetDataPage < this.dataToalPage) {
+        this.sheetDataPage++;
+        this.getCellData(sheets)
+      }else {
+        console.log(this.sheetAllcellData)
+        this.sheetConfigOpt.data = sheets.map((_,index) => ({
+          // index: _.Sort, //工作表索引
+          order: _.Sort, //工作表的下标
+          name: _.SheetName,
+          calcChain: JSON.parse(_.CalcChain),
+          config: JSON.parse(_.Config),
+          celldata: this.sheetAllcellData[index],
+        }))
+
+        console.log(this.sheetConfigOpt)
+
+        this.isSheetLoading = false;
+      }
     },
 
     /* 删除表格 */
@@ -729,29 +734,6 @@ export default {
         .catch(() => {});
     },
 
-    /* 编辑 */
-    goEditHandle() {
-      let path = {
-        2: "/addCustomSheet",
-        3: "addMixedSheet",
-      };
-      this.$router.push({
-        path: path[this.sheetDetailInfo.Source],
-        query: { id: this.sheetDetailInfo.ExcelInfoId },
-      });
-    },
-
-    /* 刷新表格 */
-    refreshSheet: _.debounce(async function () {
-      const res = await sheetInterface.refreshCustomSheet({
-        ExcelInfoId: this.sheetDetailInfo.ExcelInfoId,
-      });
-
-      if (res.Ret !== 200) return;
-      this.$message.success("刷新成功");
-      this.getDetailHandle();
-    }, 300),
-
     /* 表格另存为 */
     saveOtherHandle() {
       this.saveOtherForm.name = this.sheetDetailInfo.ExcelName + "(1)";
@@ -775,7 +757,7 @@ export default {
       const res = await sheetInterface.copyExcel({
         ExcelInfoId: this.sheetDetailInfo.ExcelInfoId,
         ExcelName: name,
-        ExcelClassifyId: classify,
+        ExcelClassifyId: classify
       });
 
       if (res.Ret !== 200) return;
@@ -785,6 +767,11 @@ export default {
       this.getTreeData();
     },
 
+    /* 刷新表格 */
+    refreshSheet() {
+
+    },
+
     /* 重绘右侧区域宽度 */
     reloadRightWid() {
       let total_wid = $(".data-sheet-main")[0].offsetWidth;
@@ -824,11 +811,16 @@ export default {
 
         this.$store.commit('sheet/SET_UPLOADFIlES',[file])
         this.$router.push({ path: '/addAnalysisSheet' });
-
-
       } 
 		},
 
+    //跳转生成指标
+    HandleToPath() {
+      this.$router.push({ path: '/createTaregtBySheet',query: {
+        code: this.sheetDetailInfo.UniqueCode 
+      }});
+    }
+
   },
   mounted() {
     if (this.$route.query.code) {
@@ -950,6 +942,7 @@ $normal-font: 14px;
 
     .main-right {
       width: 80%;
+      position: relative;
       .sheet-detail-wrapper {
         height: 100%;
         border: 1px solid #ececec;