Procházet zdrojové kódy

Merge branch 'eta1.5.6'

Karsa před 9 měsíci
rodič
revize
605991bf8a

+ 23 - 1
src/api/modules/sheetApi.js

@@ -263,7 +263,7 @@ export const insertData = params => {
  * @returns 
  */
 export const getDateLatelyData = params => {
-	return http.get('/datamanage/edb_info/date_data/before_after',params)
+	return http.post('/datamanage/edb_info/date_data/before_after',params)
 }
 
 /**
@@ -309,6 +309,28 @@ export const getRefreshResult = (params)=>{
     return http.post('/datamanage/excel_info/table/batch_refresh/result',params)
 }
 
+
+/**
+ * 日期计算
+ * @param {
+ * 	Formula,
+ * 	DateList: [{Date,Tag}]
+ * } params 
+ * @returns 
+ */
+export const getDateCalculate = params => {
+	return http.post('/datamanage/excel_info/mixed/date_calculate',params)
+}
+
+/**
+ * 根据id获取指标基础信息 无数据
+ * @param {*EdbInfoIds} params 
+ * @returns 
+ */
+export const getEdbBaseInfo = params => {
+	return http.get('/datamanage/excel_info/base_edb_info',params)
+}
+
 /* =====自定义分析==== */
 
 export const sheetAnalysisInterface = {

+ 2 - 2
src/routes/modules/chartRoutes.js

@@ -102,7 +102,7 @@ export default [
 		children:[
 			{
 				path:"sheetList",
-				name:"在线Excel",
+				name:"共享表格",
 				component:()=>import('@/views/datasheet_manage/sheetList.vue')
 			},
 			{
@@ -121,7 +121,7 @@ export default [
 				component:()=>import('@/views/datasheet_manage/addSheet.vue'),
 				meta: { 
 					pathFrom: "sheetList",
-					pathName: "在线Excel",
+					pathName: "共享表格",
 				}
 			},
 			{

+ 2 - 2
src/utils/calculate.js

@@ -21,9 +21,9 @@ function multiply(a, b) {
 
 // 除法
 function divide(a, b) {
-  const precision = getPrecision(b) - getPrecision(a);
+  const precision = Math.max(getPrecision(b), getPrecision(a));
   const divisor = Math.pow(10, precision);
-  return Math.round((a / b) * divisor) / divisor;
+  return (a * divisor) / (b * divisor);
 }
 
 // 获取浮点数的精度

+ 4 - 1
src/views/chartRelevance_manage/components/selectTarget.vue

@@ -73,7 +73,7 @@
       remote
       clearable
       placeholder="请选择指标名称"
-      :style="`width: 100%; ${filter?'margin-top: 20px':''}`"
+      :style="`width: ${width}; ${filter?'margin-top: 20px':''}`"
       :remote-method="searchHandle"
       @click.native="inputFocusHandle"
       @change="handleSelectTarget"
@@ -113,6 +113,9 @@ export default {
       },
       filter: { //是否要预测和eta的筛选
         default: true
+      },
+      width: {
+        default:'100%'
       }
     },
     watch:{

+ 13 - 12
src/views/datasheet_manage/addSheet.vue

@@ -11,19 +11,20 @@
           </el-input>
         </li>
         <li>
-          <el-select 
-            v-model="sheetForm.classify" 
-            placeholder="请选择表格分类"
-            style="width:240px"
+          <el-cascader
+            v-model="sheetForm.classify"
+            :options="classifyArr"
+            style="width:240px;"
+            :props="{
+              label: 'ExcelClassifyName',
+              value: 'ExcelClassifyId',
+              children: 'Children',
+              emitPath: false,
+              checkStrictly: true
+            }"
             clearable
-          >
-							<el-option
-								v-for="item in classifyArr"
-								:key="item.ExcelClassifyId"
-								:label="item.ExcelClassifyName"
-								:value="item.ExcelClassifyId"
-              />
-						</el-select>
+            placeholder="请选择表格分类"
+          />
         </li>
       </ul>
       <div v-if="updateTime" style="color:#999999;margin-right: 30px;">最近保存时间:{{ updateTime }}</div>

+ 115 - 7
src/views/datasheet_manage/common/customTable.js

@@ -1,3 +1,4 @@
+import { multiply,divide } from '@/utils/calculate';
 // 字母列标
 export function getColumnHeaderCode(len) {
   let tag_arr = [];
@@ -138,23 +139,24 @@ export function setCellBg(e) {
 export function getRightClickMenu(pos,canEdit=false) {
 
   let cellMenu = [
-    { label: "根据表格中日期选择指标值", key: "choose-target" },
+    { label: "根据日期选择指标值", key: "choose-target" },
     // { label: "插入指标值", key: "insert-value" },
-    { label: "导入系统日期", key: "insert-sys-date" },
-    { label: "导入指标日期", key: "insert-edb-date" },
+    { label: "导入日期", key: "insert-date" },
+    // { label: "导入指标日期", key: "insert-edb-date" },
+    { label: "日期计算", key: "insert-date-calculate" },
     { label: "指标计算",
       key: "insert-edb-calculate",
       children: [
         { label: '累计值转月/季值',source: 1,fromEdbKey:5 },
         { label: '同比值',source: 3,fromEdbKey:6 },
         { label: '同差值',source: 4,fromEdbKey:7 },
-        { label: 'N数值移动平均计算',source: 5,fromEdbKey:8 },
-        { label: 'N数值环比值',source: 6,fromEdbKey:12 },
-        { label: 'N数值环差值',source: 7,fromEdbKey:13 },
+        { label: 'N期移动均值',source: 5,fromEdbKey:8 },
+        { label: 'N环比值',source: 6,fromEdbKey:12 },
+        { label: 'N环差值',source: 7,fromEdbKey:13 },
         { label: '升频',source: 8,fromEdbKey:14 },
         { label: '时间移位',source: 10,fromEdbKey:22 },
         { label: '超季节性',source: 11,fromEdbKey:35 },
-        { label: '年化',source: 12,fromEdbKey:52 },
+        { label: '年化',source: 12,fromEdbKey:52 },
         { label: '降频',source: 9,fromEdbKey:51 },
         { label: '累计值',source: 13,fromEdbKey:62 },
         { label: '指数修匀',source: 15,fromEdbKey:'alpha' },
@@ -261,3 +263,109 @@ export function findCellKeyByFactor(str) {
 
   return el ? (el.dataset.key||'') : null;
 }
+
+/* 判断值是否是一个数字或数字字符串 */
+export function isNumberVal(value) {
+   let reg = /^[-]?(?:\d*\.?\d+|\d+%|\d*\.\d+%)$/;
+   
+   return reg.test(value);
+}
+
+/* 增加减少小数点位数 */
+export function transDecimalPlace(str,{pn,nt}) {
+
+  if(!isNumberVal(str)) return '';
+
+  let s = str.replace(/%/,''),
+      decimalPlaces = getDecimalPlaces(str),
+      decimalNum=pn;
+  
+  //是否是原数字后设置百分比的
+  let transPercent = (nt==='percent'&&!str.endsWith('%')) ? true : false;
+
+  //原百分比设置为数字的
+  let transDecimal = (nt==='number'&&str.endsWith('%')) ? true : false
+
+  //后缀 百分号
+  let suffix = ((str.endsWith('%')&&nt!=='number')||transPercent) ? '%' : '';
+
+  let num = parseFloat(s);
+
+  if(decimalPlaces===0) { //整数
+    if(transPercent) {
+      return decimalNum > 0 
+        ? `${multiply(num,100)}.${'0'.repeat(decimalNum)}${suffix}`
+        : `${multiply(num,100)}${suffix}`;
+    }
+
+    if(transDecimal) {
+      return decimalNum > 0 
+        ? `${divide(num,100)}${'0'.repeat(decimalNum)}`
+        : `${divide(num,100)}`;
+    }
+
+    // 补零
+    return decimalNum > 0 
+      ? `${s}.${'0'.repeat(decimalNum)}${suffix}`
+      : `${s}${suffix}`;
+  }
+
+  if(decimalNum > 0) {
+    let addPointStr = `${s}${'0'.repeat(decimalNum)}`;
+    
+    return transPercent 
+      ? `${parseFloat(multiply(num,100)).toFixed(decimalPlaces+decimalNum-2)}${suffix}`
+      : transDecimal
+        ? `${parseFloat(divide(num,100)).toFixed(decimalPlaces+decimalNum+2)}`
+        : `${addPointStr}${suffix}`
+  }else {
+    let maxDecimal = Math.max(0,decimalNum+decimalPlaces);
+    let maxDecimalPercent = Math.max(0,maxDecimal-2);
+
+    return transPercent 
+      ? `${parseFloat(multiply(num,100)).toFixed(maxDecimalPercent)}${suffix}`
+      : transDecimal
+        ? `${parseFloat(divide(num,100)).toFixed(maxDecimal+2)}`
+        : `${parseFloat(num.toFixed(maxDecimal))}${suffix}`
+  }
+}
+
+/* 计算小数点位数 */
+export function getDecimalPlaces(numStr) {
+  // 移除百分号,如果有的话
+  numStr = numStr.replace('%', '');
+
+  // 如果没有小数点,说明小数点位数为 0
+  if (!numStr.includes('.')) {
+    return 0;
+  }
+
+  // 获取当前小数点后的位数
+  const decimalPlaces = numStr.split('.')[1].length;
+
+  return decimalPlaces;
+}
+
+/* 格式化单元格值 显示转换 */
+export function transNumPercentType(str,type) {
+  console.log(str,type)
+
+  let isPercent = str.endsWith('%'),s=str.replace(/%/,'');
+  
+  if(isPercent && type==='percent') { //百分数转百分
+    return str
+  }
+
+  if(!isPercent && type==='number') { //数字转数字
+    return str
+  }
+
+  let num = parseFloat(s)
+
+  if(type==='percent') {
+    const percenStr = parseFloat(multiply(num,100)) + '%';
+    return percenStr;
+  }else {
+    return parseFloat(divide(num,100));
+  }
+}

+ 236 - 89
src/views/datasheet_manage/components/MixedTable.vue

@@ -1,6 +1,9 @@
 <template>
   <div class="table-wrapper" @keydown="handlekeyDownKeys">
     <template v-if="config.data.length">
+
+      <!-- 工具栏 -->
+      <toolBarSection v-if="!disabled" :cell="selectCell" @updateCell="updateCellStyle"/>
       
       <!-- 公式显示区 -->
       <div class="formula-wrapper" v-if="!disabled">
@@ -64,8 +67,9 @@
             >
 
             <!-- 插入单元格禁止编辑 -->
+            <!-- [4,5,6,7,8].includes(cell.DataType)&&!cell.CanEdit -->
             <template 
-              v-if="([4,5,6,7].includes(cell.DataType)&&!cell.CanEdit)
+              v-if="!cell.CanEdit
               ||disabled
               ||(cell.DataType===1&&[1,2].includes(cell.DataTimeType))"
             >
@@ -96,9 +100,19 @@
                   :data-rindex="rowHeader[index]"
                   :data-cindex="columnHeader[cell_index]"
                   :data-key="cell.Uid"
-                >{{ cell.ShowValue }}</span>
+                >{{ cell.ShowStyle?cell.ShowFormatValue:cell.ShowValue }}</span>
               </el-popover>
 
+              <!-- 数字格式化显示 -->
+              <span 
+                v-else-if="cell.ShowStyle"
+                :data-rindex="rowHeader[index]"
+                :data-cindex="columnHeader[cell_index]"
+                :data-key="cell.Uid"
+              >
+                {{cell.ShowFormatValue}}
+              </span>
+
               <span
                 :data-rindex="rowHeader[index]"
                 :data-cindex="columnHeader[cell_index]"
@@ -111,17 +125,19 @@
                 v-else
                 v-model="cell.Value"
                 :ref="`inputRef${cell.Uid}`"
-                :fetch-suggestions="searchTarget"
                 popper-class="edb-select-popover"
                 :data-key="cell.Uid"
                 :data-rindex="rowHeader[index]"
                 :data-cindex="columnHeader[cell_index]"
-                :highlight-first-item="cell.DataType===2"
-                @select="selectTarget($event,cell)"
-                @click="clickCell($event, cell)"
+                :fetch-suggestions="searchTarget"
                 @change.native="changeVal($event, cell)"
                 @keydown.native="keyEnterHandle($event,cell)"
+                @blur="() => {$set(cell,'CanEdit',false)}"
               >
+                <!-- @select="selectTarget($event,cell)"
+                  @click="clickCell($event, cell)"
+                :highlight-first-item="cell.DataType===2"
+                 -->
                 <template slot-scope="scope">
                     <edbDetailPopover :info="scope.item">
                       <div slot="reference" v-if="cell.DataType===2" class="edb-item">
@@ -139,14 +155,33 @@
       </table>
 
       <!-- 右键菜单 -->
-      <div class="contextMenu-wrapper" id="contextMenu-wrapper" @mouseleave="hideContextMenu">
+      <div class="contextMenu-wrapper" id="contextMenu-wrapper" @mouseleave="()=>{activeNames=[];hideContextMenu()}">
         <div :class="['item',{'deletesty': menu.key==='reset'}]" v-for="menu in config.contextMenuOption" :key="menu.key" @click="handleContext(menu.key)">
-          {{menu.label}}
+          <span v-if="!menu.children">{{menu.label}}</span>
           
-          <i class="el-icon-arrow-right" v-if="menu.children"></i>
+          <el-collapse v-model="activeNames" @change="handleChange" v-if="menu.children">
+            <el-collapse-item name="1">
+              <template slot="title">
+                 {{menu.label}}
+              </template>
+              
+              <div class="subMenu-wrapper">
+                <div slot="reference" class="item" v-for="submenu in menu.children" :key="submenu.key" @click="edbCalculateInsertOpen(submenu)">
+                    <el-popover
+                      width="300"
+                      trigger="hover"
+                      placement="right"
+                    >
+                      <div v-html="formulaTip.get(submenu.fromEdbKey)"></div>
+                      <div slot="reference" style="width:100%">{{submenu.label}}</div>   
+                    </el-popover>
+                </div>
+              </div>
+            </el-collapse-item>
+          </el-collapse>  
 
           <!-- 二级菜单 -->
-          <div class="subMenu-wrapper" v-if="menu.children">
+          <!-- <div class="subMenu-wrapper" v-if="menu.children">
             <div slot="reference" class="item" v-for="submenu in menu.children" :key="submenu.key" @click="edbCalculateInsertOpen(submenu)">
                 <el-popover
                   width="300"
@@ -157,7 +192,7 @@
                   <div slot="reference" style="width:100%">{{submenu.label}}</div>   
                 </el-popover>
             </div>
-          </div>
+          </div> -->
         </div>
       </div>
     </template>
@@ -169,6 +204,7 @@
     <!-- 选择指标 -->
     <selectTargetValueDia
       :isShow.sync="isSelectTargetValueDialog"
+      :info="insertTargetValueInfo"
       @insert="insertSelectData"
       ref="selectTargetValueRef"
     />
@@ -187,6 +223,14 @@
       :info="insertCalculateInfo"
       @insert="insertCalculateData"
     />
+
+    <!-- 日期计算弹窗 -->
+    <calculateDateDia
+      ref="calculateDateDiaRef"
+      :isShow.sync="isInsertCalculateDate"
+      :info="insertCalculateDateInfo"
+      @insert="insertCalculateDateValue"
+    />
   </div>
 </template>
 <script>
@@ -206,7 +250,9 @@ import {
   findCellByFactor,
   splitString,
   toUpperCase,
-  findCellKeyByFactor
+  findCellKeyByFactor,
+  isNumberVal,
+  transDecimalPlace
 } from "../common/customTable";
 import * as sheetInterface from "@/api/modules/sheetApi.js";
 import { dataBaseInterface } from '@/api/api.js';
@@ -214,6 +260,8 @@ import md5 from '@/utils/md5.js';
 import selectTargetValueDia from './selectTargetValueDia.vue';
 import insertDateDia from './insertDateDia.vue';
 import calculateEdbDia from './calculateEdbDia.vue';
+import calculateDateDia from './calculateDateDia.vue';
+import toolBarSection from './toolBarSection.vue';
 import { formulaTip } from '@/views/dataEntry_manage/databaseComponents/util';
 export default {
   props: {
@@ -222,7 +270,13 @@ export default {
       default: false,
     }
   },
-  components: { selectTargetValueDia,insertDateDia,calculateEdbDia },
+  components: { 
+    selectTargetValueDia,
+    insertDateDia,
+    calculateEdbDia,
+    calculateDateDia,
+    toolBarSection
+  },
   computed: {
     //列头
     columnHeader() {
@@ -259,15 +313,14 @@ export default {
     return {
       config: {
         /* 单元格类型 
-          1手动日期格 DataTimeType 0
-          2指标格 
+          1手动日期格 DataTimeType 0 /系统日期导入格 DataTimeType 1  /指标日期导入格 DataTimeType 2
+          2指标格 //eta1.5.6又弃用了
           3自定义输入 
-          4插入值 表格里有关联的日期和指标格  //隐藏 又不要这个功能
+          4插入值 表格里有关联的日期和指标格  // eta1.1.6弃用
           5弹窗里的插入值 有关联日期格 
           6公式计算单元格 
-          1系统日期导入格 DataTimeType 1
-          1指标日期导入格 DataTimeType 2
           7指标计算的插入值单元格
+          8日期计算值单元格
         */
         data: [], 
         contextMenuOption: [],
@@ -281,7 +334,8 @@ export default {
 
       insertRelationArr: [], //表格单元格依赖关系数组
 
-      isSelectTargetValueDialog: false,
+      isSelectTargetValueDialog: false,//选择指标插入值弹窗
+      insertTargetValueInfo: {},//编辑 关联info
 
       cellrelationEdbInfo: {}, //指标浮窗信息
 
@@ -290,11 +344,7 @@ export default {
       calculateClickCell: null,//双击公式单元格时的单元格信息 用于之后选其他单元格拼接公式
 
       isInsertDateDialog: false,//导入日期弹窗
-      insertDateInfo: {
-        key: '',
-      },
-
-      calculateChainList: [],//公式链 key数组 后端需要
+      insertDateInfo: {},
 
       isInsertCalculate: false,//插入指标计算值
       insertCalculateInfo: {},//指标计算单元格info
@@ -303,6 +353,11 @@ export default {
       
       hasInit:false,
 
+      isInsertCalculateDate: false,//日期计算弹窗
+      insertCalculateDateInfo: {},//日期计算info
+
+      activeNames: []
+
     };
   },
   mounted() {
@@ -310,8 +365,10 @@ export default {
   },
   methods: {
 
-    /* 输入时实时搜索 满足日期格式不搜索 有=视为输入公式不搜索 */
+    /* 输入时实时搜索 满足日期格式不搜索 有=视为输入公式不搜索  eta1.5.6弃用了*/
     async searchTarget(query,cb) {
+      return cb([])
+      
       //又要过滤掉2020-05-这样的奇葩其他格式 不让检索
       let dateOtherRegex = /^(?:(?:19|20)\d\d)([-])(0[1-9]|1[0-2])(-?)$/
       if(!query
@@ -344,13 +401,6 @@ export default {
       
       setFocus(e);
 
-      /* 如果当前有公式单元格在编辑就拼接当前单元格进公式 */
-      // if(this.calculateClickCell && this.calculateClickCell.Uid!==cell.Uid) {
-      //   console.log(this.calculateClickCell)
-      //   const { cindex,rindex } = e.target.dataset;
-      //   this.calculateClickCell.Value += `${cindex}${rindex}`
-      // }
-
       //是插值单元格时寻找关联依赖的单元格 设置选框
       if([4,5,7].includes(cell.DataType)) {
         const { key } = e.target.dataset;
@@ -362,10 +412,13 @@ export default {
       }
 
       //选择指标弹窗打开时选择日期更新弹窗数据
-      this.isSelectTargetValueDialog&&this.$refs.selectTargetValueRef.chooseEdb(this.$refs.selectTargetValueRef.edbInfo)
+      this.isSelectTargetValueDialog&&this.$refs.selectTargetValueRef.changeRleationDate(this.selectCell)
 
       //计算指标弹窗打开时选择日期更新弹窗数据
-      this.isInsertCalculate&&this.$refs.calculateEdbDiaRef.showResult&&this.$refs.calculateEdbDiaRef.calculateHandle()
+      this.isInsertCalculate&&this.$refs.calculateEdbDiaRef.changeRleationDate(this.selectCell)
+
+      //日期计算弹窗打开选中日期框时且有选中item时更新选中值
+      cell.DataType===1&&this.isInsertCalculateDate&&this.$refs.calculateDateDiaRef.selectIndex&&this.$refs.calculateDateDiaRef.setSelectItemValue(this.selectCell)
     },
 
     /* 插入值 往左往上寻找同行同列是否有符合条件的一指标一日期 */
@@ -389,17 +442,6 @@ export default {
       const res = await sheetInterface.insertData({EdbInfoId,Date})
       if(res.Ret !==200) return
 
-      //日期无值也要建立关联关系
-      // if(!res.Data&&!DataTimeType){
-      //   this.selectCell.DataType = 3;
-      //   this.selectCell.DataTimeType = 0;
-      //   this.selectCell.ShowValue = '';
-      //   this.selectCell.Value = '';
-      //   this.selectCell.DataTime = '';
-      //   this.selectCell.EdbInfoId = 0;
-      //   this.$message.warning('所选指标的所选日期无值')
-      //   return
-      // }
 
       res.Data ? this.$message.success('插入成功') : this.$message.warning('当前日期暂无值') 
 
@@ -507,7 +549,6 @@ export default {
       // 是日期格式 DataType为1
       // 自定义内容 DataType 3
       //有=号为输入公式 DataType 6
-
       const {value} = e.target;
       if(!value){ //无值重置单元格
         cell.DataType = 3;
@@ -526,6 +567,7 @@ export default {
           cell.DataType = 1;
           cell.Extra='';
           cell.ShowValue = dateFormat;
+          cell.DataTime = dateFormat;
           cell.Value = dateFormat;
         }else if(value.startsWith('=')) { //公式单元格
           cell.DataType = 6;
@@ -546,6 +588,12 @@ export default {
         }
       }
 
+      /* 不是数字类型,清除原来设置的格式 */
+      if(!isNumberVal(value)){
+        cell.ShowStyle = '';
+        cell.ShowStyle = '';
+      } ;
+
       //判断是否是有插入值的依赖单元格 更新值或重置关系
       this.checkCellRelation(cell)
     },
@@ -625,6 +673,7 @@ export default {
             cell.DataTime = '';
             cell.ShowValue = '';
             cell.Value = '';
+            cell.ShowStyle = ''
           }
         })
       })
@@ -689,7 +738,7 @@ export default {
         pos = 'cell'
       }
       this.config.contextMenuOption = pos === 'cell' 
-        ? getRightClickMenu(pos,(cell.DataType===1&&[1,2].includes(cell.DataTimeType))||cell.DataType===7)
+        ? getRightClickMenu(pos,(cell.DataType===1&&[1,2].includes(cell.DataTimeType))||[5,7,8].includes(cell.DataType))
         : getRightClickMenu(pos)
 
       this.$nextTick(() => {
@@ -720,9 +769,12 @@ export default {
     /* 右键事件 */
     async handleContext(key) {
 
+      //可右键编辑的单元格类型
       let editHandlesMap = {
         1: this.insertDateOpen,
-        7: this.edbCalculateInsertOpen
+        5: this.selectTargetOpen,
+        7: this.edbCalculateInsertOpen,
+        8: this.insertDateCalculateOpen
       }
 
       const keyMap = {
@@ -733,8 +785,9 @@ export default {
         'insert-row-down': this.insertRow,//向下插入行
         'insert-value': this.insertValue,//插入值
         'choose-target': this.selectTargetOpen,//选择指标插入值
-        'insert-sys-date': this.insertDateOpen,//导入系统日期
-        'insert-edb-date': this.insertDateOpen,//导入指标日期
+        'insert-date': this.insertDateOpen,//导入系统日期
+        // 'insert-edb-date': this.insertDateOpen,//导入指标日期
+        'insert-date-calculate': this.insertDateCalculateOpen,//日期计算弹窗
         'reset': this.clearCell, //清空
         'cell-edit': this.selectCell ? editHandlesMap[this.selectCell.DataType] : null
       }
@@ -745,38 +798,49 @@ export default {
 
     /* 打开选择指标弹窗  
     打开弹窗后仍可以在页面上点击 多存一个选择指标时的当前单元格信息 */
-    selectTargetOpen() {
+    selectTargetOpen(type) {
       this.insertTargetCell = this.selectCell;
       resetDialogCellStyle();
       setRelationStyle({ key:this.insertTargetCell.Uid },'td-choose-insert-target')
+      if(type === 'cell-edit') {
+        this.insertTargetValueInfo = {
+          ...this.insertTargetCell
+        }
+      }else {
+        this.insertTargetValueInfo = {}
+      }
       this.isSelectTargetValueDialog = true;
 
-      this.isInsertCalculate = false;
-      this.$refs.calculateEdbDiaRef.initData();
+      this.resetDialogStatus('insertEdbVal')
     },
 
     /* 插入选择指标的值 */
-    insertSelectData({ edbId,value,date }) {
+    insertSelectData({ edbId,value,relationDate,relationUid,str }) {
 
       this.insertTargetCell.DataType = 5;
       this.insertTargetCell.ShowValue = value;
-      this.insertTargetCell.Value = value;
+      this.insertTargetCell.Value = str;
       this.insertTargetCell.EdbInfoId = edbId;
-      this.insertTargetCell.DataTime = date;
+      this.insertTargetCell.DataTime = relationDate;
+      this.insertTargetCell.ShowFormatValue = this.insertTargetCell.ShowStyle ? transDecimalPlace(value,JSON.parse(this.insertTargetCell.ShowStyle)) : '';
 
-      this.$message.success('插入成功')
+      value ? this.$message.success('插入成功') : this.$message.warning('该日期当前无值')
 
       //如果有关联表格日期就建立新的关联关系
-      if(date) {
+      if(relationDate&&relationUid) {
         let relation = {
           insert_cell: {
             key: this.insertTargetCell.Uid,
-            relation_date: this.selectCell.Uid,
+            relation_date: relationUid,
             relation_edb: '',
           }
         }
   
         this.setRelation(relation,5);
+      }else { //重新插值后之后原来有关联的清除关系
+        let haveIndex = this.insertRelationArr.findIndex(_ => _.key===this.insertTargetCell.Uid);
+        haveIndex!==-1 && this.insertRelationArr.splice(haveIndex,1)
+        resetRelationStyle();
       }
 
     },
@@ -791,6 +855,8 @@ export default {
       this.selectCell.DataTime = '';
       this.selectCell.DataTimeType = 0;
       this.selectCell.EdbInfoId = 0;
+      this.selectCell.ShowStyle = '';
+      this.selectCell.ShowFormatValue = '';
 
       this.checkCellRelation(this.selectCell)
     },
@@ -903,22 +969,32 @@ export default {
       resetDialogCellStyle();
 
       if(type === 'cell-edit') { //编辑日期
-        const { DataTimeType } = this.insertTargetCell;
         this.insertDateInfo = {
-          key: DataTimeType===1? 'insert-sys-date' : 'insert-edb-date',
           ...this.insertTargetCell
         }
       }else {
         this.insertDateInfo = {
-          key:type
+          // key:type
         }
       }
       this.isInsertDateDialog = true;
+      this.resetDialogStatus();
+    },
 
-      this.isSelectTargetValueDialog = false;
-      this.$refs.selectTargetValueRef.initData();
-      this.isInsertCalculate = false;
-      this.$refs.calculateEdbDiaRef.initData();
+    /* 弹窗都是无遮罩的 弹一个就重置其他的 */
+    resetDialogStatus(type='init') {
+      if(type!=='insertEdbVal') {
+        this.$refs.selectTargetValueRef&&this.$refs.selectTargetValueRef.initData();
+        this.isSelectTargetValueDialog = false;
+      }
+      if(type!=='insertEdbCalculateVal') {
+        this.$refs.calculateEdbDiaRef&&this.$refs.calculateEdbDiaRef.initData();
+        this.isInsertCalculate = false;
+      }
+      if(type!=='insertDateCalculateVal') {
+        this.$refs.calculateDateDiaRef&&this.$refs.calculateDateDiaRef.initData();
+        this.isInsertCalculateDate = false;
+      }
     },
 
     /* 插入系统/指标日期 */
@@ -947,7 +1023,7 @@ export default {
 
         this.insertCalculateInfo = {
           ...menuInfo,
-          formStr: Value,
+          ...this.insertTargetCell
         }
       }else {
         this.insertCalculateInfo = {
@@ -956,34 +1032,68 @@ export default {
       }
       this.isInsertCalculate = true;
 
-      this.isSelectTargetValueDialog = false;
-      this.$refs.selectTargetValueRef.initData();
+      this.resetDialogStatus('insertEdbCalculateVal')
     },
 
     /* 导入指标计算值 */
     insertCalculateData(item) {
-      console.log(item)
-      const { InsertValue,EdbInfoId,Str,Date } = item;
+      // console.log(item)
+      const { InsertValue,EdbInfoId,Str,relationDate,relationUid } = item;
       this.insertTargetCell.DataType = 7;
       this.insertTargetCell.ShowValue = InsertValue;
       this.insertTargetCell.Value = Str;
       this.insertTargetCell.EdbInfoId = EdbInfoId;
-      this.insertTargetCell.DataTime = Date;
+      this.insertTargetCell.DataTime = relationDate;
+      this.insertTargetCell.ShowFormatValue = this.insertTargetCell.ShowStyle ? transDecimalPlace(InsertValue,JSON.parse(this.insertTargetCell.ShowStyle)) : '';
 
-      this.$message.success('插入成功')
+      InsertValue ? this.$message.success('插入成功') : this.$message.warning('该日期当前无值')
 
       //如果有关联表格日期就建立新的关联关系
-      if(Date) {
+      if(relationDate&&relationUid) {
         let relation = {
           insert_cell: {
             key: this.insertTargetCell.Uid,
-            relation_date: this.selectCell.Uid,
+            relation_date: relationUid,
             relation_edb: '',
           }
         }
   
         this.setRelation(relation,7);
+      }else { //重新插值后之后原来有关联的清除关系
+        let haveIndex = this.insertRelationArr.findIndex(_ => _.key===this.insertTargetCell.Uid);
+        haveIndex!==-1 && this.insertRelationArr.splice(haveIndex,1)
+        resetRelationStyle();
+      }
+    },
+
+    /* 日期计算弹窗 */
+    insertDateCalculateOpen(type) {
+      this.insertTargetCell = this.selectCell;
+      resetDialogCellStyle()
+      setRelationStyle({ key:this.insertTargetCell.Uid },'td-choose-insert-target')
+
+      if(type === 'cell-edit') { //编辑
+        this.insertCalculateDateInfo = {
+          ...this.insertTargetCell
+        }
+      }else {
+        this.insertCalculateDateInfo = {}
       }
+      this.isInsertCalculateDate = true;
+      this.resetDialogStatus('insertDateCalculateVal');
+    },
+
+    /* 插入日期计算值 */
+    insertCalculateDateValue(data) {
+      const { insertValue,str } = data;
+      this.insertTargetCell.DataType = 8;
+      this.insertTargetCell.ShowValue = insertValue;
+      this.insertTargetCell.Value = str;
+      this.insertTargetCell.EdbInfoId = 0;
+      this.insertTargetCell.DataTime = '';
+      this.insertTargetCell.ShowFormatValue = this.insertTargetCell.ShowStyle ? transDecimalPlace(insertValue,JSON.parse(this.insertTargetCell.ShowStyle)) : '';
+
+      this.$message.success('插入成功')
     },
 
     /* 初始化8行5列 */
@@ -999,6 +1109,8 @@ export default {
         this.config.data = new Array(8).fill("").map((_,_rindex) => {
           return new Array(5).fill("").map((cell,_cindex) => ({
             ShowValue: "",
+            ShowStyle: '',
+            ShowFormatValue: '',
             Value: "",
             DataType: 3,
             DataTimeType: 0,
@@ -1041,10 +1153,14 @@ export default {
         cell.Value = this.copyCellItem.Value;
         cell.DataTime = this.copyCellItem.DataTime;
         cell.EdbInfoId = this.copyCellItem.EdbInfoId;
+        cell.ShowStyle = this.copyCellItem.ShowStyle;
+        cell.ShowFormatValue = this.copyCellItem.ShowFormatValue;
       }else {
         cell.DataType = 3;
         cell.ShowValue = this.copyCellItem.ShowValue;
         cell.Value = this.copyCellItem.ShowValue;
+        cell.ShowStyle = this.copyCellItem.ShowStyle;
+        cell.ShowFormatValue = this.copyCellItem.ShowFormatValue;
         cell.DataTime = '';
         cell.EdbInfoId = 0;
       }
@@ -1053,26 +1169,24 @@ export default {
       e.preventDefault();
     },
 
-    /* 单元格enter时切换编辑状态 */
+    /* 单元格enter失焦 */
     keyEnterHandle(e,cell) {
       if(e.keyCode===13) {
         //非得搞个要回车失焦
         e.target.nodeName && e.target.blur();
         this.$refs[`inputRef${e.target.dataset.key}`]&&this.$refs[`inputRef${e.target.dataset.key}`][0].close()
 
-        cell.DataType===6 && this.$set(cell,'CanEdit',false)
-        // this.calculateClickCell = null
+        // cell.DataType===6 && this.$set(cell,'CanEdit',false)
+        // this.$set(cell,'CanEdit',false)
       }
     },
 
-    /* 支持公式单元格双击切换状态 */
+    /* 双击切换状态 插值单元格不允许切换 可切换类型1,2,3,6*/
     dblClickCellHandle(e,cell) {
-      if(this.disabled || cell.DataType!==6) return
+      if(this.disabled || ![1,2,3,6].includes(cell.DataType) || [1,2].includes(cell.DataTimeType)) return
 
       this.$set(cell,'CanEdit',true)
-
-      // this.calculateClickCell = cell;
-      // setRelationStyle({ key:cell.Uid },'td-choose-insert-target')
+      console.log(cell)
 
       this.$nextTick(() => {
         if(e.target.childNodes[0].childNodes[0].childNodes[1].nodeName==='INPUT') e.target.childNodes[0].childNodes[0].childNodes[1].focus();
@@ -1096,6 +1210,13 @@ export default {
       if(e.keyCode === 9) {
         e.preventDefault();
       }
+    },
+
+    /* 改变单元格显示文本 */
+    updateCellStyle({ShowStyle,ShowFormatValue}) {
+      
+      this.$set(this.selectCell,'ShowStyle',ShowStyle)
+      this.$set(this.selectCell,'ShowFormatValue',ShowFormatValue)
     }
   },
 };
@@ -1237,6 +1358,9 @@ export default {
     left: -9999px;
     background: #fff;
     padding: 10px 0;
+    min-width: 180px;
+    max-height: 400px;
+    overflow-y: auto;
     /* border: 1px solid #999; */
     box-shadow: 0 1px 4px #999;
     .item {
@@ -1251,15 +1375,21 @@ export default {
     }
 
     .subMenu-wrapper {
-      display: none;
+      width: 180px;
+      /* display: none; */
       padding: 10px 0;
-      box-shadow: 0 1px 4px #999;
-      background: #fff;
-      position: absolute;
-      right: -172px;
+      /* box-shadow: 0 1px 4px #999; */
+      /* background: #fff; */
+      /* position: absolute;
+      right: -178px;
       top:-205px;
       max-height: 400px;
-      overflow-y: auto;
+      overflow-y: auto; */
+      .item {
+        &:hover {
+          background: #fff;
+        }
+      }
     }
   }
 }
@@ -1291,4 +1421,21 @@ export default {
     }
   }
 }
+.el-collapse {
+  border: none !important;
+  .el-collapse-item__header {
+    padding: 0;
+    height: auto;
+    line-height: normal;
+    margin-bottom: 0 !important;
+    background: transparent !important;
+  }
+  .el-collapse-item__wrap {
+    background: transparent !important;
+    border: none !important;
+  }
+  .el-collapse-item__content {
+    padding: 0 !important;
+  }
+}
 </style>

+ 288 - 0
src/views/datasheet_manage/components/calculateDateDia.vue

@@ -0,0 +1,288 @@
+<template>
+<div v-dialogDrag v-if="isShow" >
+	<div class="calculate-date-dialog el-dialog" >
+		<div class="header el-dialog__header">
+			<span>日期计算</span>
+			<i class="el-icon-close" @click="cancelHandle"/>
+		</div>
+		<div class="dialog-main">
+			<ul class="add-cont">
+				<li class="add-li" v-for="(list, index) in addList" :key="index">
+					<span class="li-tag">{{ list.Tag }}</span>
+          <el-input
+						v-model="list.Date"
+						placeholder="选择日期"
+						style="width: 240px"
+						readonly
+						@focus="selectIndex=index+1"
+						@keyup.native="e => { e.keyCode===13 && initSelect}" 
+						:class="{'select': selectIndex===index+1}"
+					/>
+					
+					<i
+						class="el-icon-error del-tag"
+						v-if="index > 1"
+						@click="addList.splice(index,1)"
+					/>
+				</li>
+			</ul>
+			<div class="add-icon" @click="addTargetHandle">
+				<i
+					class="el-icon-circle-plus-outline"
+					style="color: #5882ef; font-size: 16px"
+				/>
+				添加更多日期
+			</div>
+			<div class="computed-min">
+				<div class="computed-section">
+					<label class="label">计算公式</label>
+					<el-input placeholder="请输入公式" v-model="formula" clearable @focus="initSelect">
+					</el-input>
+				</div>	
+        <div class="example-txt">公式示例:A-B 以数字形式返回日期A和日期B的天数差</div>
+			</div>
+		</div>
+		<div class="dia-bot">
+			<el-button
+				type="primary"
+				style="margin-right: 20px"
+				@click="saveHandle"
+				>确定</el-button
+			>
+			<el-button type="primary" plain @click="cancelHandle">取消</el-button>
+		</div>
+	</div>
+</div>
+</template>
+
+<script>
+import * as sheetInterface from "@/api/modules/sheetApi.js";
+import { resetDialogCellStyle,findCellByKey } from "../common/customTable";
+const tag_arr = [];
+for(let i=0;i<26;i++) tag_arr.push(String.fromCharCode(65+i));
+export default {
+	name: '',
+	props: {
+		isShow: {
+			type: Boolean,
+		},
+		info: {
+			type: Object,
+		}
+	},
+	watch: {
+		isShow(newval) {
+			if(!newval) return
+
+			/* 回显 */
+			if(this.info.Value) {
+				let valueObj = JSON.parse(this.info.Value);
+
+				this.formula = valueObj.Formula;
+				//日期有动态日期更新的问题 需要每次找单元格信息重新赋值最新的日期
+				this.addList = valueObj.RelationCellList.map(_ => ({
+					..._,
+					Date: findCellByKey(this.$parent.config.data,_.Uid).ShowValue
+				}));
+			}
+			
+		},
+	},
+	data() {
+		return {
+			selectIndex: 1,//默认选中第一个框
+			addList: [
+				{
+					Tag: tag_arr[0],
+					Uid: '', //关联表格中日期格子的uid
+					Date: '',
+				},
+				{
+					Tag: tag_arr[1],
+					Uid: '',
+					Date: '',
+				},
+			],
+			formula: '', //计算公式
+
+		};
+	},
+	methods: {
+		/* 添加额外的指标列 */
+		addTargetHandle() {
+			if(this.addList.length >= 26) return this.$message.warning('添加指标个数已达上限')
+			let tag = this.addList[this.addList.length-1].Tag;
+			let index = tag_arr.findIndex(item => item === tag);
+			const item = {
+				Tag: tag_arr[index+1],
+				Uid: '',
+				Date: ''
+			};
+			this.addList.push(item);
+		},
+
+		/* 选择日期时更新选中item的值 */
+		setSelectItemValue(cell) {
+			let item = this.addList[this.selectIndex-1];
+
+			this.$set(this.addList,this.selectIndex-1,{
+				...item,
+				Uid: cell.Uid,
+				Date: cell.ShowValue
+			})
+		},
+
+		async saveHandle() {
+			if (!this.formula) return this.$message.warning('计算公式不能为空');
+
+			let dateList = this.addList.filter(_ => _.Date&&_.Uid);
+			const res = await sheetInterface.getDateCalculate({
+				Formula: this.formula,
+				DateList: dateList
+			})
+			if(res.Ret !== 200) return
+
+			let backData = {
+				insertValue: res.Data.ShowValue,
+        str: JSON.stringify({
+					Formula: this.formula,
+					RelationCellList: dateList
+				})
+			}
+
+			this.$emit('insert',backData)
+			this.cancelHandle()
+		},
+
+		initSelect() {
+			this.selectIndex = 0;
+		},
+
+		initData() {
+			this.selectIndex = 1;
+			this.addList = [
+				{
+					Tag: tag_arr[0],
+					Uid: '',
+					Date: '',
+				},
+				{
+					Tag: tag_arr[1],
+					Uid: '',
+					Date: '',
+				},
+			];
+			this.formula = '';
+
+		},
+		cancelHandle() {
+			this.initData();
+			this.$emit('update:isShow',false);
+			resetDialogCellStyle()
+		},
+	},
+	mounted() {},
+};
+</script>
+<style lang="scss" scoped>
+@import "~@/styles/theme-vars.scss";
+.calculate-date-dialog {
+	width:750px;
+	background: #fff;
+  position: fixed;
+  top: 20%;
+  left: 50%;
+  border-radius: 2px;
+  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
+  z-index: 9999;
+	overflow: hidden;
+	div::-webkit-scrollbar {
+		width: 6px !important;
+	}
+	.header { 
+    font-size: 16px;
+    background: $theme-color;
+    color: #fff;
+    padding: 15px;
+    display: flex;
+    align-content: center;
+    justify-content: space-between;
+    .el-icon-close {
+      font-size: 20px;
+      cursor: pointer;
+    }
+  }
+	.dialog-main {
+		padding: 25px 42px 25px 25px;
+		
+		@media screen and (max-height:850px){
+			box-sizing: border-box;
+			height: 65vh;
+			overflow-y: auto;
+		}
+		.el-cascader .el-input {
+			width: 340px;
+		}
+		.add-cont {
+			display: flex;
+			flex-wrap: wrap;
+			justify-content: space-between;
+			max-height: 300px;
+			overflow: hidden;
+			overflow-y: auto;
+			padding-right: 40px;
+			.add-li {
+				position: relative;
+				margin-bottom: 48px;
+				.li-tag {
+					font-size: 16px;
+					margin-right: 8px;
+				}
+				.del-tag {
+					position: absolute;
+					right: -30px;
+					top: 12px;
+					font-size: 16px;
+					cursor: pointer;
+				}
+			}
+		}
+		.add-icon {
+			margin:10px 0;
+			font-size: 16px;
+			color: #5882ef;
+			cursor: pointer;
+		}
+		.computed-min {
+			margin: 50px 0;
+			padding-bottom: 40px;
+			border-bottom: 1px dashed #aab4cc;
+			.computed-section {
+				display: flex;
+				margin-top: 20px;
+			}
+			.label {
+				padding:10px 10px 10px 0;
+			}
+			.example-txt {
+				margin-top: 10px;
+				padding-left: 60px;
+				color: #999;
+			}
+		}
+	}
+	.dia-bot {
+		padding-bottom: 40px;
+		display: flex;
+		justify-content: center;
+	}
+}
+</style>
+<style lang="scss">
+  .calculate-date-dialog {
+    .select .el-input__inner {
+      border: 2px dashed #18ad18;
+      border-radius: 4px;
+    }
+  }
+</style>

+ 133 - 64
src/views/datasheet_manage/components/calculateEdbDia.vue

@@ -13,7 +13,7 @@
           <template v-if="info.fromEdbKey===5">
             <el-radio-group 
               v-model="formData.source"
-              @change="changeSource"
+              @change="()=>{ $refs.selectRef.targetTypeChange();changeSource() }"
             >
               <el-radio :label="1">累计值转月</el-radio>
               <el-radio :label="2">累计值转季值</el-radio>
@@ -23,7 +23,7 @@
           <template v-else-if="info.fromEdbKey===62"> 
             <el-radio-group 
               v-model="formData.source"
-              @change="changeSource"
+              @change="()=>{ $refs.selectRef.targetTypeChange(); changeSource() }"
             >
               <el-radio :label="13">累计值</el-radio>
               <el-radio :label="14">年初至今累计值</el-radio>
@@ -46,7 +46,7 @@
                 v-for="(item,index) in edbArrFromTable" 
                 :key="index"
                 @click="selectTableEdbHandle(item)"
-              >{{ item.ShowValue }}</el-tag>
+              >{{ item.EdbName }}</el-tag>
           </div>
         </section>
         
@@ -70,7 +70,6 @@
 								style="width: 100px"
 								placeholder=""
 								size="mini"
-								@change="changeParams"
 							>
 								<el-option
 									v-for="item in moveTypeOpions"
@@ -87,14 +86,12 @@
 								size="mini"
 								v-model="formData.moveVal"
 								@keyup.native="filterCode(formData)"
-                @change="changeParams"
 							></el-input>
 							<el-select
 								v-model="formData.moveUnit"
 								size="mini"
 								placeholder=""
 								style="width: 100px"
-                @change="changeParams"
 							>
 								<el-option
 									v-for="item in fre_options"
@@ -112,7 +109,6 @@
 								style="width: 200px"
 								placeholder="请输入N数值"
 								type="number"
-								@change="changeParams"
 							/>
 						</el-form-item>
 
@@ -121,7 +117,6 @@
 								v-model="formData.calendarType"
 								placeholder="请选择日历"
 								style="width: 200px"
-								@change="changeParams"
 							>
 								<el-option
 									v-for="item in calendarOptions"
@@ -139,7 +134,6 @@
 								placeholder="请选择频度"
 								style="width: 200px"
 								clearable
-                @change="changeParams"
 							>
 								<el-option
 									v-for="item in frequencyArr"
@@ -156,7 +150,6 @@
 								v-model="formData.valueType"
 								placeholder="请选择数据取值类型"
 								style="width: 200px"
-                @change="changeParams"
 							>
 								<el-option key="期末值" label="期末值" value="期末值"/>
 								<el-option key="平均值" label="平均值" value="平均值"/>
@@ -168,14 +161,42 @@
                 v-model="formData.alphaValue" 
                 placeholder="请选择alpha值"
                 style="width: 200px"
-                @change="changeParams"
               />
 						</el-form-item>
 					</el-form>
         </section>
 
+        <section>
+          <!-- 依赖日期选择方式 -->
+          <ul class="date-select-cont">
+            <li class="flex">
+              <div class="flex">
+                <el-radio v-model="dateSelectForm.Type" :label="1">指标最新日期</el-radio>
+                <div>
+                  <label class="el-form-item__label">期数前移</label>
+                  <el-input
+                    v-model="dateSelectForm.MoveForward"
+                    type="number"
+                    :min="0"
+                    style="margin-right:10px;width:80px"
+                    @change="e => {dateSelectForm.MoveForward=Number(e);}"
+                  />期
+                </div>
+              </div>
+              <div class="flex">
+                <el-radio v-model="dateSelectForm.Type" :label="2" style="margin-left:50px">表格日期</el-radio>
+                <span v-if="dateSelectForm.relationDate&&dateSelectForm.Type===2">{{dateSelectForm.relationDate}}</span>
+
+              </div>
+            </li>
+            <li>
+              <dateMoveWaySec ref="dateMoveWayRef"/>
+            </li>
+          </ul>
+        </section>
+
         <!-- 计算结果 -->
-        <section class="result-section" v-if="showResult">
+        <!-- <section class="result-section" v-if="showResult">
           <label>计算结果:</label>
           <ul class="data-cont" v-if="calculateShowData.length">
               <li 
@@ -189,11 +210,10 @@
           </ul>
 
           <tableNoData text="无对应的数据" size="mini" v-else/>
-        </section>
+        </section> -->
 
         <section class="bot">
-          <el-button type="primary" @click="insertData" v-if="showResult">插入值</el-button>
-          <el-button type="primary" @click="calculateHandle" v-else>计算</el-button>
+          <el-button type="primary" @click="calculateHandle">插入值</el-button>
           <el-button type="primary" plain @click="cancelHandle">取消</el-button>
 
         </section>
@@ -207,9 +227,10 @@
 import { dataBaseInterface } from '@/api/api.js';
 import * as sheetInterface from "@/api/modules/sheetApi.js";
 import * as preDictEdbInterface from '@/api/modules/predictEdbApi.js';
-import { resetDialogCellStyle } from "../common/customTable";
+import { resetDialogCellStyle,findCellByKey } from "../common/customTable";
 import selectTarget from '@/views/chartRelevance_manage/components/selectTarget.vue';
 import edbDetailSection from './edbDetailSection.vue';
+import dateMoveWaySec from './dateMoveWaySection.vue'
 import { formRules } from '@/views/dataEntry_manage/databaseComponents/util';
 export default {
   props: {
@@ -220,30 +241,17 @@ export default {
       type: Object
     }
   },
-  components: { selectTarget,edbDetailSection },
-  computed: {
-    edbArrFromTable() {
-      let arr = this.$parent.config.data.flat().filter(_ =>_.DataType === 2);
-      let filterArr =  []
-      
-      arr.forEach(item => {
-        if(filterArr.findIndex(_ => _.EdbInfoId===item.EdbInfoId)===-1) {
-          filterArr.push(item)
-        }
-      })
-      
-       return filterArr
-    }
-  },
+  components: { selectTarget,edbDetailSection,dateMoveWaySec },
   watch: {
     isShow(nval) {
       if(!nval) return
-      console.log(this.info)
-      const { source,formStr } = this.info;
+      
+      this.getTableEdbList()
+      const { source } = this.info;
 
       this.formData.source = source;
       //回显
-      if(formStr) {
+      if(this.info.Value) {
         const {
           Source,
           Frequency,
@@ -251,8 +259,11 @@ export default {
           EdbInfoId,
           MoveFrequency,
           MoveType, 
-          Calendar 
-        } = JSON.parse(formStr);
+          Calendar,
+          DataTime,
+          MoveForward,
+          DateChange
+        } = JSON.parse(this.info.Value);
 
         this.formData = {
           source: Source,
@@ -265,7 +276,18 @@ export default {
           valueType: Formula,
           alphaValue: Formula,
         }
+
+        this.dateSelectForm = {
+          Type: DataTime ? 2 : 1,
+          MoveForward: MoveForward || 0,
+          relationUid: this.info.DataTime ? this.getRelationCellKey() : '',
+          relationDate: this.info.DataTime ? this.getNewCellDate() : '',//日期会动态更新 需要找关联单元格最新的数据
+        }
         this.selectTableEdbHandle({EdbInfoId})
+
+        this.$nextTick(() => {
+          DateChange&&this.$refs.dateMoveWayRef.initData(DateChange)
+        })
       }
     }
   },
@@ -286,6 +308,8 @@ export default {
       formRules,
       frequencyArr: ['日度', '周度','旬度', '月度', '季度', '年度'],
 
+      edbArrFromTable: [],
+
       showResult: false,
       calculateShowData: [], //计算全部数据
       chooseItem: {
@@ -311,12 +335,56 @@ export default {
 				{label: '公历',key: 1},
 				{label: '农历',key: 2},
 			],
+
+      dateSelectForm: {
+        Type:1,
+        MoveForward: 0,
+        relationDate: '',//关联的表格日期
+        relationUid: '',//关联格子的uid
+      }
     }
   },
   mounted(){
 
   },
   methods:{
+    /* 获取表格中关联的表格列表 单元格2 5 7*/
+    async getTableEdbList() {
+        let arr = this.$parent.config.data.flat().filter(_ =>[2,5,7].includes(_.DataType)).map(_ => _.EdbInfoId);
+        let filterArr =  Array.from(new Set(arr));
+
+        if(!filterArr.length) return
+
+        let res = await sheetInterface.getEdbBaseInfo({EdbInfoIds: filterArr.join(',')})
+        if(res.Ret !==200) return
+
+        this.edbArrFromTable = res.Data.List;
+    },
+
+    // 在选择表格中日期的话在弹窗中显示所选日期 关联uid
+    changeRleationDate(cell) {
+      this.dateSelectForm.relationDate=cell.DataType===1 ? cell.ShowValue : '';
+      this.dateSelectForm.relationUid=this.dateSelectForm.relationDate ? cell.Uid : '';
+    },
+
+    /* 找日期关联的key 本来想存在单元格内部后端不想动原来结构 还是自己根据关联关系找吧 */
+    getRelationCellKey() {
+      let relationObj = this.$parent.insertRelationArr.find(_=> _.key === this.info.Uid)
+      if(!relationObj) return ''
+
+      return relationObj.relation_date.key
+    },
+
+    /* 先找关联日期的key  再根据key找单元格数据取到最新的日期 */
+    getNewCellDate() {
+      let relationKey = this.getRelationCellKey();
+      if(!relationKey) return '';
+
+      let relationDateCell = findCellByKey(this.$parent.config.data,relationKey)
+      
+      return relationDateCell.ShowValue
+    },
+
     /* 计算结果 */
     async calculateHandle() {
       await this.$refs.form.validate();
@@ -336,7 +404,10 @@ export default {
         'alpha': 'alphaValue'
       }
 
-      let DataTime = this.$parent.selectCell.DataType === 1 ? this.$parent.selectCell.ShowValue : ''
+      let DataTime = '';
+      if(this.dateSelectForm.Type===2) { //选框为表格日期再去取Date
+        DataTime = this.dateSelectForm.relationDate
+      }
 
       let params = {
         DataTime,
@@ -346,43 +417,29 @@ export default {
         EdbInfoId: this.selectEdbInfo.EdbInfoId,
         MoveFrequency: moveUnit,
         MoveType: moveType, 
-        Calendar: calendarType
+        Calendar: calendarType,
+        MoveForward: this.dateSelectForm.MoveForward,
+        DateChange: this.$refs.dateMoveWayRef.dateChangeArr,
       }
 
       const res = await sheetInterface.getMixedCalculateData(params)
       if(res.Ret!==200) return 
 
       this.showResult = true;
-      this.calculateShowData = res.Data.List || [];
-
-      // if(!this.calculateShowData.length && DataTime) return this.$message.warning('所选指标所选日期无值')
-
-      let InsertValue = this.calculateShowData.length 
-        ? (this.calculateShowData.find(_ => _.DataTime===DataTime) ? this.calculateShowData.find(_ => _.DataTime===DataTime).Value.toString() : this.calculateShowData[0].Value.toString()) 
-        : ''
-      this.chooseItem = {
-          Date:DataTime,
-          EdbInfoId: this.selectEdbInfo.EdbInfoId,
-          InsertValue,
-          Str: JSON.stringify(params)
-        }
       
-    },
-
-    /* 已计算过改参数重新计算 */
-    changeParams() {
-      this.showResult && this.calculateHandle()
-    },
-
-    /* 插入值 */
-    insertData() {
+      this.chooseItem = {
+        relationDate: DataTime,
+        relationUid: this.dateSelectForm.Type===2 ? this.dateSelectForm.relationUid : '',
+        EdbInfoId: this.selectEdbInfo.EdbInfoId,
+        InsertValue: res.Data.ShowValue||"",
+        Str: JSON.stringify(params)
+      }
 
-      // if(this.$parent.selectCell.DataType !== 1) return this.$message.warning('请在表格中选择日期')
-        
-      if(!this.calculateShowData.length) return this.$message.warning('该日期无数据')
+      // if(!this.calculateShowData.length) return this.$message.warning('该日期无数据')
       
       this.$emit('insert',this.chooseItem)
       this.cancelHandle();
+      
     },
 
     /* 选择指标 */
@@ -414,7 +471,7 @@ export default {
       const { EdbInfoId,EdbInfoType,EdbName,Frequency } = res.Data;
 
       if(this.formData.source===1&&Frequency!=='月度') return this.$message.warning('只能选择月度指标')
-      else if(this.formData.source===2&&Frequency!=='季度') return this.$message.warning('能选择季度指标')
+      else if(this.formData.source===2&&Frequency!=='季度') return this.$message.warning('能选择季度指标')
       else if(this.formData.source===8&&Frequency==='日度') return this.$message.warning('不能选择日度指标')
       else if(this.formData.source===14&&Frequency==='年度') return this.$message.warning('不能选择年度指标')
 
@@ -446,6 +503,8 @@ export default {
 				calendarType: '公历',
 				valueType: '期末值'
       }
+      this.dateSelectForm = {Type:1,MoveForward: 0,relationDate: '',relationUid: ''}
+      this.$refs.dateMoveWayRef&&this.$refs.dateMoveWayRef.initData();
     },
 
     cancelHandle() {
@@ -516,6 +575,16 @@ export default {
         }
       }
     }
+
+    .date-select-cont {
+      li {
+        margin: 20px 0;
+      }
+      .flex {
+        display: flex;
+        align-items: center;
+      }
+    }
   }
 }  
 </style>

+ 173 - 0
src/views/datasheet_manage/components/dateMoveWaySection.vue

@@ -0,0 +1,173 @@
+<template>
+  <div class="date-change-ways">
+    <div class="header date-item">
+      <label class="el-form-item__label">日期变换</label>
+                
+      <el-select v-model="dateChangeSelect" placeholder="请选择" style="width:110px">
+        <el-option label="日期位移" :value="1"/>
+        <el-option label="指定频率" :value="2"/>
+      </el-select>
+
+      <el-button type="text" style="margin: 0 10px;" @click="addDateChange">添加</el-button>
+    </div>
+    
+    <ul v-if="dateChangeArr.length" class="date-change-list">
+      <li v-for="(dateItem,index) in dateChangeArr" :key="dateItem.ChangeType" class="date-change-li">
+
+        <div v-if="dateItem.ChangeType===1" class="date-item">
+          <el-tag type="info" style="margin-right:15px">日期位移</el-tag>
+          <div>
+            <el-input
+              v-model="dateItem.Day"
+              type="number"
+              style="margin-right:10px;width:80px"
+              @change="e => {dateItem.Day=Number(e);}"
+            />天
+            <el-input
+              v-model="dateItem.Month"
+              type="number"
+              style="margin-right:10px;width:80px"
+              @change="e => {dateItem.Month=Number(e);}"
+            />月
+            <el-input
+              v-model="dateItem.Year"
+              type="number"
+              style="margin-right:10px;width:80px"
+              @change="e => {dateItem.Year=Number(e);}"
+            />年
+          </div>
+          <i class="el-icon-delete" @click="removeDateItem(index)"></i>
+        </div>
+
+        <div v-else-if="dateItem.ChangeType===2" class="date-item">
+          <el-tag type="info" style="margin-right:15px">指定频率</el-tag>
+          <el-select
+              style="max-width: 120px;"
+              v-model="dateItem.Frequency"
+              placeholder="请选择频度"
+              @change="dateItem.FrequencyDay=frequencyDaysOptions[0].name;"
+          >
+            <el-option
+                v-for="item in frequencyOptions"
+                :key="item.value"
+                :label="item.name"
+                :value="item.value"
+            />
+          </el-select>
+
+          <el-select
+              style="max-width: 120px;margin:0 10px"
+              v-model="dateItem.FrequencyDay"
+              placeholder="请选择"
+          >
+            <el-option
+                v-for="item in frequencyDaysOptions"
+                :key="item.name"
+                :label="item.name"
+                :value="item.name"
+            />
+          </el-select>
+
+          <i class="el-icon-delete" @click="removeDateItem(index)"></i>
+        </div>
+      </li>
+    </ul>
+  </div>
+</template>
+<script>
+export default {
+  computed: {
+    frequencyDaysOptions() {
+      let typeMap = {
+        '本周': [
+          { name: '周一' },
+          { name: '周二' },
+          { name: '周三' },
+          { name: '周四' },
+          { name: '周五' },
+          { name: '周六' },
+          { name: '周日' },
+        ]
+      }
+      
+      let obj = this.dateChangeArr.find(_ => _.ChangeType===2);
+      if(!obj) return []
+
+      return typeMap[obj.Frequency] 
+        ? typeMap[obj.Frequency] 
+        : [{name:'第一天'},{name:'最后一天'}]
+    }
+  },
+  data() {
+    return {
+      dateChangeSelect: 1,
+      dateChangeArr: [],
+
+      frequencyOptions: [
+        { name: '本周', value: '本周' },
+        { name: '本旬', value: '本旬' },
+        { name: '本月', value: '本月' },
+        { name: '本季', value: '本季' },
+        { name: '本半年', value: '本半年' },
+        { name: '本年', value: '本年' },
+      ],
+    }
+  },
+  methods:{
+    /* 提加日期变换数组 */
+    addDateChange() {
+      let haveObj = this.dateChangeArr.find(_ => _.ChangeType===this.dateChangeSelect);
+      if(haveObj) return this.$message.warning(this.dateChangeSelect===1?'已添加日期位移':'已添加指定频率')
+      let item = {
+        ChangeType: this.dateChangeSelect,
+        Day: 0,
+        Month: 0,
+        Year: 0,
+        Frequency: '本周',
+        FrequencyDay: '周一'
+      }
+
+      this.dateChangeArr.push(item)
+    },
+
+    /* 参数更新时刷数据 */
+    changeParams() {
+      this.$emit('updateData')
+    },
+
+    initData(data=null) {
+      if(data) {
+        this.dateChangeArr = data || [];
+      }else {
+        this.dateChangeSelect = 1;
+        this.dateChangeArr = []
+      }
+    },
+
+    removeDateItem(index) {
+      this.dateChangeArr.splice(index,1)
+    }
+  },
+}
+</script>
+<style scoped lang='scss'>
+.date-change-ways {
+  padding-left: 20px;
+  .date-change-list {
+    padding-left: 68px;
+  }
+  .date-change-li {
+    margin: 10px 0;
+  }
+  .date-item {
+    display: flex;
+    align-items: center;
+    .el-icon-delete {
+      color: #f00;
+      font-size: 16px;
+      margin:0 10px;
+      cursor: pointer;
+    }
+  }
+}
+</style>

+ 108 - 166
src/views/datasheet_manage/components/insertDateDia.vue

@@ -3,86 +3,21 @@
 		:visible.sync="isShow"
 		:close-on-click-modal="false"
 		:modal-append-to-body='false'
-    :title="titleMap[info.key]"
+    title="导入日期"
 		@close="cancelHandle"
 		custom-class="dialog"
 		center
-		width="560px"
+		width="650px"
 		v-dialogDrag>
 			<div class="dialog-main">
-          <!-- 导入系统日期 -->
-            <ul v-if="info.key==='insert-sys-date'">
-              <li class="form-item">
-                <label>导入方式</label>
-                <el-select
-                    v-model="formData.Source"
-                    placeholder="请选择导入方式"
-                    @change="init('form')"
-                >
-                  <el-option
-                      v-for="item in wayOptions"
-                      :key="item.value"
-                      :label="item.name"
-                      :value="item.value"
-                  />
-                </el-select>
 
-                <template v-if="formData.Source===3">
-                  <el-select
-                      style="max-width: 120px;margin:0 10px"
-                      v-model="formData.Frequency"
-                      placeholder="请选择频度"
-                      @change="formData.Day=frequencyDaysOptions[0].name"
-                  >
-                    <el-option
-                        v-for="item in frequencyOptions"
-                        :key="item.value"
-                        :label="item.name"
-                        :value="item.value"
-                    />
-                  </el-select>
-
-                  <el-select
-                      style="max-width: 120px;"
-                      v-model="formData.Day"
-                      placeholder="请选择"
-                  >
-                    <el-option
-                        v-for="item in frequencyDaysOptions"
-                        :key="item.name"
-                        :label="item.name"
-                        :value="item.name"
-                    />
-                  </el-select>
-                </template>
-
-                <el-tooltip effect="dark" style="margin-left:10px">
-                  <div
-                    slot="content"
-                    v-html="tips[info.key]"
-                    style="line-height: 20px;"
-                  ></div>
-                  <i class="el-icon-question" style="font-size:18px;"/>
-                </el-tooltip>
-              </li>
-              <template v-if="formData.Source===2">
-                <li class="form-item">
-                  <label>天数</label>
-                  <el-input
-                    v-model="formData.CalculateNum"
-                    type="number"
-                    style="margin-right:10px;width:200px"
-                    @change="e => {formData.CalculateNum=Number(e)}"
-                  />
-                  {{formData.CalculateFrequency}}
-                </li>
-                <li style="color:#999">示例:5,表示当前日期+5天的日期; -5,表示当前日期-5天的日期;</li>
-              </template>
-            </ul>
-
-          <!-- 导入指标日期 -->
-          <ul v-else> 
+          <ul>
             <li class="form-item">
+              <el-radio 
+                v-model="dateChangeSelect"
+                style="margin-right:12px"
+                :label="2"
+              >指标日期</el-radio>
 
               <selectTarget
                 :defaultId="search_edb"
@@ -90,29 +25,47 @@
                 ref="selectRef"
                 @select="e => { selectEdbInfo = e ||{} }"
                 :filter="false"
+                width="240px"
               />
-
-              <el-tooltip effect="dark" style="margin-left:10px">
-                <div
-                  slot="content"
-                  v-html="tips[info.key]"
-                  style="line-height: 20px;"
-                ></div>
-                <i class="el-icon-question" style="font-size:18px;"/>
-              </el-tooltip>
+              
+              <span v-show="selectEdbInfo.Frequency" style="margin: 0 10px">频度: {{ selectEdbInfo.Frequency }}</span>
+              <span v-show="selectEdbInfo.LatestDate">最新日期: {{ selectEdbInfo.LatestDate }}</span>
             </li>
-            <li class="form-item" v-if="selectEdbInfo.Frequency">
-              <label>更新频度</label>
-              {{ selectEdbInfo.Frequency }}
+            <li class="form-item" style="padding-left:10px">
+              <label class="el-form-item__label">期数前移</label>
+              <el-input
+                v-model="formData.MoveForward"
+                type="number"
+                :min="0"
+                style="margin-right:10px;width:80px"
+                @change="e => {formData.MoveForward=Number(e)}"
+              />期
             </li>
-            <li class="form-item" v-if="selectEdbInfo.LatestDate">
-              <label>最新日期</label>
-              {{ selectEdbInfo.LatestDate }}
+            <li class="form-item">
+              <el-radio 
+                v-model="dateChangeSelect"
+                :label="1"
+                style="margin-right:12px"
+              >系统日期</el-radio>
+              
+              <span>{{ $moment().format('YYYY-MM-DD') }}</span>
+            </li>
+            <li class="form-item">
+              <dateMoveWaySec ref="dateMoveWayRef"/>
             </li>
           </ul>
 			</div>
+
+      <el-popover
+        placement="top-start"
+        width="500"
+        trigger="click">
+        <p style="padding:20px;line-height:25px;" v-html="tips"/>
+        <el-button slot="reference" class="tip-label" type="text">公式说明</el-button>
+      </el-popover>
+
 			<div class="dia-bot">
-				<el-button type="primary" style="margin-right:20px" @click="saveInsertHandle">保存</el-button>
+				<el-button type="primary" style="margin-right:20px" @click="saveInsertHandle">确定</el-button>
 				<el-button type="primary" plain @click="cancelHandle">取消</el-button>
 			</div>
 	</el-dialog>
@@ -121,6 +74,7 @@
 import * as sheetInterface from "@/api/modules/sheetApi.js";
 import { dataBaseInterface } from '@/api/api.js';
 import selectTarget from '@/views/chartRelevance_manage/components/selectTarget.vue'
+import dateMoveWaySec from './dateMoveWaySection.vue'
 export default {
   props: {
     isShow: {
@@ -130,17 +84,21 @@ export default {
       type: Object
     }
   },
-  components: { selectTarget },
+  components: { selectTarget,dateMoveWaySec },
   watch: {
     isShow : { 
       async handler(nval) {
         if(nval && this.info.Value) { //处理日期编辑回显
           const valueObj = JSON.parse(this.info.Value);
 
+          // this.formData = {
+          //   ...this.formData,
+          //   ...valueObj
+          // }
           this.formData = {
-            ...this.formData,
-            ...valueObj
+            MoveForward: valueObj.MoveForward
           }
+          this.dateChangeSelect = this.info.DataTimeType;
 
           if(this.info.DataTimeType===2) { //指标日期时获取指标详情
             const { Data } = await dataBaseInterface.targetDetail({EdbInfoId: valueObj.EdbInfoId})
@@ -151,69 +109,44 @@ export default {
             this.search_edb = valueObj.EdbInfoId;
             this.searchOptions = [this.selectEdbInfo];
           }
+
+          this.$nextTick(() => {
+            this.$refs.dateMoveWayRef&&this.$refs.dateMoveWayRef.initData(valueObj.DateChange)
+          })
         }
       }
     }  
 
   },
-  computed: {
-    frequencyDaysOptions() {
-      let typeMap = {
-        '本周': [
-          { name: '周一' },
-          { name: '周二' },
-          { name: '周三' },
-          { name: '周四' },
-          { name: '周五' },
-          { name: '周六' },
-          { name: '周日' },
-        ]
-      }
-      return typeMap[this.formData.Frequency] 
-        ? typeMap[this.formData.Frequency] 
-        : [{name:'第一天'},{name:'最后一天'}]
-    }
-  },
+
   data() {
     return {
       formData: {
-        Source: 1,
-        Frequency: '本周',
-        Day: '周一',
-        CalculateNum: 0,
-        CalculateFrequency: '日'
+        // Source: 1,
+        // Frequency: '本周',
+        // Day: '周一',
+        // CalculateNum: 0,
+        // CalculateFrequency: '日'
+        MoveForward: 0,
       },
 
-      wayOptions: [
-        { name: '直接导入', value: 1 },
-        { name: '日期计算', value: 2 },
-        { name: '指定频率', value: 3 },
-      ],
-      frequencyOptions: [
-        { name: '本周', value: '本周' },
-        { name: '本旬', value: '本旬' },
-        { name: '本月', value: '本月' },
-        { name: '本季', value: '本季' },
-        { name: '本半年', value: '本半年' },
-        { name: '本年', value: '本年' },
-      ],
-
-      search_edb: '',
-      searchOptions:[],
+      tips: `
+        公式说明:<br>
+        1、指标日期:取所选指标最新日期,跟随最新日期更新。<br>
+        2、系统日期:取系统日期,跟随系统日期更新。<br>
+        3、日期位移示例:<br>
+        原日期 2023/10/12,日期位移函数设置为5天0月0年,则转换后日期为2023/10/17。<br>
+        原日期 2023/10/12,日期位移函数设置为30天0月0年,则转换后日期为2023/11/11。<br>
+        原日期2023/10/30,日期位移函数设置为0天1月0年,则转换后日期为2023/11/30。<br>
+        原日期2023/10/31,日期位移函数设置为0天1月0年,则转换后日期为2023/12/1。<br>
+        4、日期位移与指定频率互相叠加,示例:<br>
+        原日期 2023/10/12, 先日期位移1月(2023/11/12),后频率设置本月最后一天,则转化后的日期为2023/11/30。<br>
+        原日期 2023/10/12 ,先频率设置本月最后一天(2023/10/31),后日期位移1月,则转化后的日期为2023/12/1。
+      `,
 
-      titleMap: {
-        'insert-sys-date': '导入系统日期',
-        'insert-edb-date': '导入指标日期'
-      },
+      selectEdbInfo: {},
 
-      tips: {
-        'insert-sys-date': `1、直接导入:直接取系统日期,跟随系统日期更新<br>
-        2、日期计算:取系统日期进行公式计算,跟随系统日期更新 <br>
-        3、指定频率:取系统日期相关的指定日期,跟随系统日期更新`,
-        'insert-edb-date': '取指标的最新日期,跟随指标最新日期更新'
-      },
-
-      selectEdbInfo: {}
+      dateChangeSelect: 2,//日期方式选择 1系统日期 2指标日期
 
     }
   },
@@ -221,48 +154,51 @@ export default {
     // 保存插入信息
     async saveInsertHandle() {
 
-      if(this.info.key==='insert-edb-date' && !this.selectEdbInfo.EdbInfoId) return this.$message.warning('请选择指标')
+      if(this.dateChangeSelect===2 && !this.selectEdbInfo.EdbInfoId) return this.$message.warning('请选择指标')
       
       let backData = {}
       //插入系统日期
-      if(this.info.key==='insert-sys-date') {
+      // if(this.info.key==='insert-sys-date') {
+
+        let valueParam = {
+          EdbInfoId: this.selectEdbInfo.EdbInfoId||0,
+          MoveForward: this.formData.MoveForward,
+          DateChange: this.$refs.dateMoveWayRef.dateChangeArr
+        }
+
         let { Data } = await sheetInterface.getSystemDate({
-          DataTimeType: 1,
-          Value: JSON.stringify(this.formData)
+          DataTimeType: this.dateChangeSelect,
+          Value: JSON.stringify(valueParam)
         })
         
         backData = {
           insertValue: Data.Date,
-          dataTimeType: 1,
-          str: JSON.stringify(this.formData)
-        }
-      }else { //指标日期
-        backData = {
-          insertValue: this.selectEdbInfo.LatestDate,
-          dataTimeType: 2,
-          str:  JSON.stringify({EdbInfoId: this.selectEdbInfo.EdbInfoId})
+          dataTimeType: this.dateChangeSelect,
+          str: JSON.stringify(valueParam)
         }
-      }
+      // }else { //指标日期
+      //   backData = {
+      //     insertValue: this.selectEdbInfo.LatestDate,
+      //     dataTimeType: 2,
+      //     str:  JSON.stringify({EdbInfoId: this.selectEdbInfo.EdbInfoId})
+      //   }
+      // }
       this.$emit('insert',backData)
       this.cancelHandle()
     },
 
-    init(type='') {
+    init() {
 
       this.formData = {
-        Source: this.formData.Source,
-        Frequency: '本周',
-        Day: '周一',
-        CalculateNum: 0,
-        CalculateFrequency: '日'
+        MoveForward: 0,
       }
 
       this.search_edb = '';
       this.searchOptions = [];
       if(this.$refs.selectRef) this.$refs.selectRef.search_txt='';
-
-      if(!type) this.formData.Source = 1;
       this.selectEdbInfo = {}
+      this.dateChangeSelect = 2;
+      this.$refs.dateMoveWayRef.initData();
     },
     cancelHandle() {
       this.init()
@@ -273,9 +209,9 @@ export default {
 </script>
 <style scoped lang='scss'>
 .dialog-main {
-  padding: 20px;
+  padding: 0 20px;
   .form-item { 
-    margin: 15px 0; 
+    margin: 20px 0; 
     display: flex;
     align-items: center;
     label { width: 80px;flex-shrink: 0; }
@@ -286,4 +222,10 @@ export default {
   display: flex;
   justify-content: center;
 }
+.tip-label {
+  position: absolute;
+  bottom: 20px;
+  right: 20px;
+  cursor: pointer;
+}
 </style>

+ 133 - 24
src/views/datasheet_manage/components/selectTargetValueDia.vue

@@ -12,18 +12,45 @@
         @select="chooseEdb"
       />
 
-      <ul class="data-cont">
+      <!-- <ul class="data-cont">
         <template v-if="result.List&&result.List.length">
           <li 
             v-for="(item,index) in result.List" 
             :key="index" 
-            :class="[{'choose': item.DataTime===chooseItem.date || (!chooseItem.date&&index===0)},'data-li']"
+            :class="[{'choose': item.DataTime===result.Date},'data-li']"
           >
             <span>{{item.DataTime}}</span>
             <span style="min-width:150px">{{item.Value}}</span>
           </li>
         </template>
         <tableNoData size="mini" v-else/>
+      </ul> -->
+
+      <!-- 依赖日期选择方式 -->
+      <ul class="date-select-cont">
+        <li class="flex">
+          <div class="flex">
+            <el-radio v-model="dateSelectForm.Type" :label="1">指标最新日期</el-radio>
+            <div>
+              <label class="el-form-item__label">期数前移</label>
+              <el-input
+                v-model="dateSelectForm.MoveForward"
+                type="number"
+                :min="0"
+                style="margin-right:10px;width:80px"
+                @change="e => {dateSelectForm.MoveForward=Number(e);}"
+              />期
+            </div>
+          </div>
+          <div class="flex">
+            <el-radio v-model="dateSelectForm.Type" :label="2" style="margin-left:50px">表格日期</el-radio>
+            <span v-if="dateSelectForm.relationDate&&dateSelectForm.Type===2">{{dateSelectForm.relationDate}}</span>
+
+          </div>
+        </li>
+        <li>
+          <dateMoveWaySec ref="dateMoveWayRef"/>
+        </li>
       </ul>
 
       <div class="dia-bot">
@@ -39,15 +66,41 @@
 </template>
 <script>
 import * as sheetInterface from "@/api/modules/sheetApi.js";
+import { dataBaseInterface } from '@/api/api.js';
 import selectTarget from '@/views/chartRelevance_manage/components/selectTarget.vue';
-import { resetDialogCellStyle } from "../common/customTable";
+import { resetDialogCellStyle,findCellByKey } from "../common/customTable";
+import dateMoveWaySec from './dateMoveWaySection.vue'
 export default {
   props: {
     isShow: {
       type: Boolean,
+    },
+    info: {
+      type: Object
+    }
+  },
+  components: { selectTarget,dateMoveWaySec },
+  watch: {
+    isShow(nval) {
+      if(!nval) return
+
+      console.log(this.info)
+      if(this.info.DataType===5) {
+        const valueObj = this.info.Value ? JSON.parse(this.info.Value) : {};
+        this.dateSelectForm = {
+          Type: this.info.DataTime ? 2 : 1,
+          MoveForward: valueObj.MoveForward || 0,
+          relationDate: this.info.DataTime ? this.getNewCellDate() : '',//日期会动态更新 需要找关联单元格最新的数据
+          relationUid: this.info.DataTime ? this.getRelationCellKey() : ''
+        }
+
+        this.getEdbInfo(this.info.EdbInfoId);
+        this.$nextTick(() => {
+          valueObj.DateChange&&this.$refs.dateMoveWayRef.initData(valueObj.DateChange)
+        })
+      }
     }
   },
-  components: { selectTarget },
   data() {
     return {
       result: {},
@@ -55,6 +108,13 @@ export default {
       chooseItem: {
         edbId: 0,
         value:''
+      },
+
+      dateSelectForm: {
+        Type:1,
+        MoveForward: 0,
+        relationDate: '',//关联的表格日期
+        relationUid: '',//关联格子的uid
       }
     }
   },
@@ -67,38 +127,76 @@ export default {
       } 
 
       this.edbInfo = edb;
+    },
+
+    // 在选择表格中日期的话在弹窗中显示所选日期 关联uid
+    changeRleationDate(cell) {
+      this.dateSelectForm.relationDate=cell.DataType===1 ? cell.ShowValue : '';
+      this.dateSelectForm.relationUid=this.dateSelectForm.relationDate ? cell.Uid : '';
+    },
+
+    /* 获取指标信息回显 */
+    async getEdbInfo(EdbInfoId) {
+      const { Data } = await dataBaseInterface.targetDetail({EdbInfoId})
+
+      const { EdbName,LatestDate,Frequency } = Data;
+      this.edbInfo = { EdbName,LatestDate,Frequency,EdbInfoId };
+      this.$refs.selectRef.search_txt = EdbName;
+    },
+
+    /* 找日期关联的key 本来想存在单元格内部后端不想动原来结构 还是自己根据关联关系找吧 */
+    getRelationCellKey() {
+      let relationObj = this.$parent.insertRelationArr.find(_=> _.key === this.info.Uid)
+      if(!relationObj) return ''
+
+      return relationObj.relation_date.key
+    },
+
+    /* 先找关联日期的key  再根据key找单元格数据取到最新的日期 */
+    getNewCellDate() {
+      let relationKey = this.getRelationCellKey();
+      if(!relationKey) return '';
+
+      let relationDateCell = findCellByKey(this.$parent.config.data,relationKey)
+      
+      return relationDateCell.ShowValue
+    },
 
-      let Date = this.$parent.selectCell.DataType === 1 ? this.$parent.selectCell.ShowValue : ''
+
+    //插入值的时候再去计算结果
+    async insertData() {
+      if(!this.edbInfo) return this.$message.warning('请先选择指标')
+
+      let Date='';
+      if(this.dateSelectForm.Type===2) { //选框为表格日期再去取Date
+        Date = this.dateSelectForm.relationDate;
+      }
 
       const res = await sheetInterface.getDateLatelyData({ 
-        EdbInfoId: edb.EdbInfoId,
+        EdbInfoId: this.edbInfo.EdbInfoId,
+        MoveForward: this.dateSelectForm.MoveForward,
+        DateChange: this.$refs.dateMoveWayRef.dateChangeArr,
         Date
       })
       if(res.Ret !== 200) return
 
       this.result = res.Data;
-      // if(!this.result.Date && Date) return this.$message.warning('所选指标所选日期无值')
 
       let value = (this.result.List&&this.result.List.length)
-        ? (this.result.List.find(_ => _.DataTime===Date) ? this.result.List.find(_ => _.DataTime===Date).Value.toString() : this.result.List[0].Value.toString()) 
+        ? this.result.List.find(_ => _.DataTime===this.result.Date) ? this.result.List.find(_ => _.DataTime===this.result.Date).Value.toString() : ''
         : ''
+
       this.chooseItem = {
-        date: Date,
-        edbId: edb.EdbInfoId,
-        value
+        relationDate: Date,
+        relationUid: this.dateSelectForm.Type===2 ? this.dateSelectForm.relationUid : '',
+        edbId: this.edbInfo.EdbInfoId,
+        value,
+        str: JSON.stringify({
+          MoveForward: this.dateSelectForm.MoveForward,
+          DateChange: this.$refs.dateMoveWayRef.dateChangeArr
+        })
       }
 
-      console.log( this.chooseItem)
-
-    },
-
-    insertData() {
-      // if(this.$parent.selectCell.DataType !== 1){
-      //   this.$message.warning('请在表格中选择日期')
-      //   return
-      // }
-      if(!this.chooseItem.value) return this.$message.warning('该日期无数据')
-
       this.$emit('insert',this.chooseItem)
       this.cancelHandle();
     },
@@ -108,6 +206,8 @@ export default {
       this.result = {};
       this.edbInfo=null;
       this.chooseItem = { edbId: 0,value: '',date: '' }
+      this.dateSelectForm = {Type:1,MoveForward: 0,relationDate: '',relationUid: '',}
+      this.$refs.dateMoveWayRef&&this.$refs.dateMoveWayRef.initData();
     },
 
     cancelHandle() {
@@ -125,7 +225,7 @@ export default {
   position: fixed;
   top: 20%;
   left: 55%;
-  width: 500px;
+  width: 650px;
   border-radius: 2px;
   box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
   z-index: 9999;
@@ -164,10 +264,19 @@ export default {
       }
     }
     .dia-bot {
-      margin-top: 20px; 
+      margin-top: 30px; 
       display: flex;
       justify-content: center;
     }
+    .date-select-cont {
+      li {
+        margin: 20px 0;
+      }
+      .flex {
+        display: flex;
+        align-items: center;
+      }
+    }
   }
 }
 </style>

+ 13 - 2
src/views/datasheet_manage/components/sheetClassifyDia.vue

@@ -20,6 +20,9 @@
 				:model="formData"
 				:rules="formRules">
 				
+          <el-form-item label="上级目录" prop="classify_name" v-if="formData.parentClassifyId">
+            <span>{{formData.parentName}}</span>
+          </el-form-item>
           <el-form-item label="分类名称" prop="classify_name">
             <el-input
             v-model="formData.classify_name"
@@ -96,9 +99,17 @@ export default {
 
 		/* 表格分类接口 */
 		async sheetClassifyApi(classify_name,classify_id) {
+			const { parentClassifyId } = this.formData;
+
+			let params = {
+				ExcelClassifyName:classify_name,
+				Source: this.$parent.sourceMap[this.$route.path],
+				ParentId: parentClassifyId
+			}
+
 			const { Ret,Msg } = !classify_id
-        ? await sheetInterface.classifyAdd({ ExcelClassifyName:classify_name,Source: this.$parent.sourceMap[this.$route.path] })
-        : await sheetInterface.classifyEdit({ ExcelClassifyName:classify_name, ExcelClassifyId:classify_id,Source: this.$parent.sourceMap[this.$route.path] })
+        ? await sheetInterface.classifyAdd(params)
+        : await sheetInterface.classifyEdit({ ExcelClassifyId:classify_id,...params })
         
       if( Ret !== 200) return
       this.$message.success(Msg);

+ 197 - 0
src/views/datasheet_manage/components/toolBarSection.vue

@@ -0,0 +1,197 @@
+<template>
+  <!-- 混合表格顶部工具栏 -->
+  <div class="toolbar-wrapper">
+    <div 
+      class="tool-btn-item" v-for="tool in toolIcons" 
+      :key="tool.key" 
+      @click="dealToolHandles(tool)"
+    >
+      <button>
+        <!-- icon -->
+        <template v-if="tool.type==='icon'">
+          <span class="icon-wrap" v-html="tool.icon"></span>
+        </template>
+
+        <template v-if="tool.type==='select'">
+          <el-select 
+            v-model="option.nt" 
+            style="width: 90px" 
+            size="small" 
+            v-if="tool.key==='cell-type-edit'"
+            @change="changeCellType"
+          >
+            <el-option
+              v-for="item in numberTypeOptions"
+              :key="item.key"
+              :value="item.key"
+              :label="item.label"
+            >
+            </el-option>
+          </el-select>
+        </template>
+      </button>
+    </div>
+  </div>
+</template>
+<script>
+import { transDecimalPlace,isNumberVal,getDecimalPlaces,transNumPercentType } from '../common/customTable';
+export default {
+  props: {
+    cell: {
+      type: Object,
+    },
+  },
+  watch: {
+    cell(nval) {
+      if(nval.ShowStyle) {
+        this.option = {
+          ...JSON.parse(nval.ShowStyle)
+        }
+      }else {
+        this.option = {
+          nt: "",//numberType
+          pn: 0,//ponitNum
+        }
+      }
+    }
+  },
+  data() {
+    return {
+      option: {
+        nt: "",//numberType  number percent
+        pn: 0,//ponitNum
+      },
+
+      toolIcons: [
+        {
+          icon: `<svg viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+              <g id="increase-decimal" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+                  <g id="Increase-Decimal" transform="translate(1.000000, 1.000000)">
+                      <polygon id="Shape" fill="#333" fill-rule="nonzero" transform="translate(3.500000, 2.500000) rotate(-270.000000) translate(-3.500000, -2.500000) " points="3.5 6 6 3.5 4 3.5 4 -1 3 -1 3 3.5 1 3.5"></polygon>
+                      <path d="M12,0 C12.6360153,0 13.1340996,0.274932615 13.4942529,0.84097035 C13.8314176,1.37466307 14,2.09433962 14,3 C14,3.90566038 13.8314176,4.62533693 13.4942529,5.15902965 C13.1340996,5.71698113 12.6360153,6 12,6 C11.3563218,6 10.8582375,5.71698113 10.5057471,5.15902965 C10.1685824,4.62533693 10,3.90566038 10,3 C10,2.09433962 10.1685824,1.37466307 10.5057471,0.84097035 C10.8582375,0.274932615 11.3563218,0 12,0 Z M12,0.800539084 C11.5632184,0.800539084 11.256705,1.05121294 11.0804598,1.56873315 C10.9578544,1.91644205 10.8965517,2.393531 10.8965517,3 C10.8965517,3.59838275 10.9578544,4.0754717 11.0804598,4.43126685 C11.256705,4.94070081 11.5632184,5.19946092 12,5.19946092 C12.4291188,5.19946092 12.7356322,4.94070081 12.9195402,4.43126685 C13.0421456,4.0754717 13.1034483,3.59838275 13.1034483,3 C13.1034483,2.393531 13.0421456,1.91644205 12.9195402,1.56873315 C12.7356322,1.05121294 12.4291188,0.800539084 12,0.800539084 Z" id="0" fill="#333"></path>
+                      <path d="M12,8 C12.6360153,8 13.1340996,8.27493261 13.4942529,8.84097035 C13.8314176,9.37466307 14,10.0943396 14,11 C14,11.9056604 13.8314176,12.6253369 13.4942529,13.1590296 C13.1340996,13.7169811 12.6360153,14 12,14 C11.3563218,14 10.8582375,13.7169811 10.5057471,13.1590296 C10.1685824,12.6253369 10,11.9056604 10,11 C10,10.0943396 10.1685824,9.37466307 10.5057471,8.84097035 C10.8582375,8.27493261 11.3563218,8 12,8 Z M12,8.80053908 C11.5632184,8.80053908 11.256705,9.05121294 11.0804598,9.56873315 C10.9578544,9.91644205 10.8965517,10.393531 10.8965517,11 C10.8965517,11.5983827 10.9578544,12.0754717 11.0804598,12.4312668 C11.256705,12.9407008 11.5632184,13.1994609 12,13.1994609 C12.4291188,13.1994609 12.7356322,12.9407008 12.9195402,12.4312668 C13.0421456,12.0754717 13.1034483,11.5983827 13.1034483,11 C13.1034483,10.393531 13.0421456,9.91644205 12.9195402,9.56873315 C12.7356322,9.05121294 12.4291188,8.80053908 12,8.80053908 Z" id="0-copy" fill="#333"></path>
+                      <path d="M6,8 C6.63601533,8 7.13409962,8.27493261 7.49425287,8.84097035 C7.83141762,9.37466307 8,10.0943396 8,11 C8,11.9056604 7.83141762,12.6253369 7.49425287,13.1590296 C7.13409962,13.7169811 6.63601533,14 6,14 C5.35632184,14 4.85823755,13.7169811 4.50574713,13.1590296 C4.16858238,12.6253369 4,11.9056604 4,11 C4,10.0943396 4.16858238,9.37466307 4.50574713,8.84097035 C4.85823755,8.27493261 5.35632184,8 6,8 Z M6,8.80053908 C5.56321839,8.80053908 5.25670498,9.05121294 5.08045977,9.56873315 C4.95785441,9.91644205 4.89655172,10.393531 4.89655172,11 C4.89655172,11.5983827 4.95785441,12.0754717 5.08045977,12.4312668 C5.25670498,12.9407008 5.56321839,13.1994609 6,13.1994609 C6.42911877,13.1994609 6.73563218,12.9407008 6.91954023,12.4312668 C7.04214559,12.0754717 7.10344828,11.5983827 7.10344828,11 C7.10344828,10.393531 7.04214559,9.91644205 6.91954023,9.56873315 C6.73563218,9.05121294 6.42911877,8.80053908 6,8.80053908 Z" id="0-copy-2" fill="#333"></path>
+                      <path d="M7.99363057,4 C8.27388535,4 8.50318471,4.08917197 8.70700637,4.29299363 C8.89808917,4.48407643 9,4.72611465 9,5.00636943 C9,5.2866242 8.89808917,5.51592357 8.70700637,5.71974522 C8.50318471,5.89808917 8.27388535,6 7.99363057,6 C7.7133758,6 7.47133758,5.89808917 7.29299363,5.71974522 C7.08917197,5.51592357 7,5.2866242 7,5.00636943 C7,4.72611465 7.08917197,4.48407643 7.29299363,4.29299363 C7.47133758,4.08917197 7.7133758,4 7.99363057,4 Z" id="." fill="#333"></path>
+                      <path d="M0.993630573,12 C1.27388535,12 1.50318471,12.089172 1.70700637,12.2929936 C1.89808917,12.4840764 2,12.7261146 2,13.0063694 C2,13.2866242 1.89808917,13.5159236 1.70700637,13.7197452 C1.50318471,13.8980892 1.27388535,14 0.993630573,14 C0.713375796,14 0.47133758,13.8980892 0.292993631,13.7197452 C0.0891719745,13.5159236 0,13.2866242 0,13.0063694 C0,12.7261146 0.0891719745,12.4840764 0.292993631,12.2929936 C0.47133758,12.089172 0.713375796,12 0.993630573,12 Z" id=".-copy" fill="#333"></path>
+                  </g>
+              </g>
+          </svg>`,
+          key: "add-point",
+          type: 'icon',
+          title: '增加小数位数'
+        },
+        { 
+          icon: `<svg viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+              <g id="decrease-decimal" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+                  <g transform="translate(1.000000, 1.000000)">
+                      <polygon id="Shape" fill="#333" fill-rule="nonzero" transform="translate(3.500000, 10.500000) rotate(-90.000000) translate(-3.500000, -10.500000) " points="3.5 14 6 11.5 4 11.5 4 7 3 7 3 11.5 1 11.5"></polygon>
+                      <path d="M12,0 C12.6360153,0 13.1340996,0.274932615 13.4942529,0.84097035 C13.8314176,1.37466307 14,2.09433962 14,3 C14,3.90566038 13.8314176,4.62533693 13.4942529,5.15902965 C13.1340996,5.71698113 12.6360153,6 12,6 C11.3563218,6 10.8582375,5.71698113 10.5057471,5.15902965 C10.1685824,4.62533693 10,3.90566038 10,3 C10,2.09433962 10.1685824,1.37466307 10.5057471,0.84097035 C10.8582375,0.274932615 11.3563218,0 12,0 Z M12,0.800539084 C11.5632184,0.800539084 11.256705,1.05121294 11.0804598,1.56873315 C10.9578544,1.91644205 10.8965517,2.393531 10.8965517,3 C10.8965517,3.59838275 10.9578544,4.0754717 11.0804598,4.43126685 C11.256705,4.94070081 11.5632184,5.19946092 12,5.19946092 C12.4291188,5.19946092 12.7356322,4.94070081 12.9195402,4.43126685 C13.0421456,4.0754717 13.1034483,3.59838275 13.1034483,3 C13.1034483,2.393531 13.0421456,1.91644205 12.9195402,1.56873315 C12.7356322,1.05121294 12.4291188,0.800539084 12,0.800539084 Z" id="0" fill="#333"></path>
+                      <path d="M12,8 C12.6360153,8 13.1340996,8.27493261 13.4942529,8.84097035 C13.8314176,9.37466307 14,10.0943396 14,11 C14,11.9056604 13.8314176,12.6253369 13.4942529,13.1590296 C13.1340996,13.7169811 12.6360153,14 12,14 C11.3563218,14 10.8582375,13.7169811 10.5057471,13.1590296 C10.1685824,12.6253369 10,11.9056604 10,11 C10,10.0943396 10.1685824,9.37466307 10.5057471,8.84097035 C10.8582375,8.27493261 11.3563218,8 12,8 Z M12,8.80053908 C11.5632184,8.80053908 11.256705,9.05121294 11.0804598,9.56873315 C10.9578544,9.91644205 10.8965517,10.393531 10.8965517,11 C10.8965517,11.5983827 10.9578544,12.0754717 11.0804598,12.4312668 C11.256705,12.9407008 11.5632184,13.1994609 12,13.1994609 C12.4291188,13.1994609 12.7356322,12.9407008 12.9195402,12.4312668 C13.0421456,12.0754717 13.1034483,11.5983827 13.1034483,11 C13.1034483,10.393531 13.0421456,9.91644205 12.9195402,9.56873315 C12.7356322,9.05121294 12.4291188,8.80053908 12,8.80053908 Z" id="0-copy" fill="#333"></path>
+                      <path d="M6,0 C6.63601533,0 7.13409962,0.274932615 7.49425287,0.84097035 C7.83141762,1.37466307 8,2.09433962 8,3 C8,3.90566038 7.83141762,4.62533693 7.49425287,5.15902965 C7.13409962,5.71698113 6.63601533,6 6,6 C5.35632184,6 4.85823755,5.71698113 4.50574713,5.15902965 C4.16858238,4.62533693 4,3.90566038 4,3 C4,2.09433962 4.16858238,1.37466307 4.50574713,0.84097035 C4.85823755,0.274932615 5.35632184,0 6,0 Z M6,0.800539084 C5.56321839,0.800539084 5.25670498,1.05121294 5.08045977,1.56873315 C4.95785441,1.91644205 4.89655172,2.393531 4.89655172,3 C4.89655172,3.59838275 4.95785441,4.0754717 5.08045977,4.43126685 C5.25670498,4.94070081 5.56321839,5.19946092 6,5.19946092 C6.42911877,5.19946092 6.73563218,4.94070081 6.91954023,4.43126685 C7.04214559,4.0754717 7.10344828,3.59838275 7.10344828,3 C7.10344828,2.393531 7.04214559,1.91644205 6.91954023,1.56873315 C6.73563218,1.05121294 6.42911877,0.800539084 6,0.800539084 Z" id="0-copy-2" fill="#333"></path>
+                      <path d="M7.99363057,12 C8.27388535,12 8.50318471,12.089172 8.70700637,12.2929936 C8.89808917,12.4840764 9,12.7261146 9,13.0063694 C9,13.2866242 8.89808917,13.5159236 8.70700637,13.7197452 C8.50318471,13.8980892 8.27388535,14 7.99363057,14 C7.7133758,14 7.47133758,13.8980892 7.29299363,13.7197452 C7.08917197,13.5159236 7,13.2866242 7,13.0063694 C7,12.7261146 7.08917197,12.4840764 7.29299363,12.2929936 C7.47133758,12.089172 7.7133758,12 7.99363057,12 Z" id="." fill="#333"></path>
+                      <path d="M0.993630573,4 C1.27388535,4 1.50318471,4.08917197 1.70700637,4.29299363 C1.89808917,4.48407643 2,4.72611465 2,5.00636943 C2,5.2866242 1.89808917,5.51592357 1.70700637,5.71974522 C1.50318471,5.89808917 1.27388535,6 0.993630573,6 C0.713375796,6 0.47133758,5.89808917 0.292993631,5.71974522 C0.0891719745,5.51592357 0,5.2866242 0,5.00636943 C0,4.72611465 0.0891719745,4.48407643 0.292993631,4.29299363 C0.47133758,4.08917197 0.713375796,4 0.993630573,4 Z" id=".-copy" fill="#333"></path>
+                  </g>
+              </g>
+          </svg>`, 
+          key: "del-point", 
+          type: 'icon',
+          title: '减少小数位数' 
+        },
+        { 
+          icon: '',
+          key: 'cell-type-edit',
+          type:'select',
+          title:'' 
+        }
+      ],
+
+      numberTypeOptions: [
+        { label: "数字", key: "number" },
+        { label: "百分位", key: "percent" },
+      ],
+    };
+  },
+  methods: {
+    dealToolHandles({key}) {
+      //单元格不是数字就不用转了
+      if(!isNumberVal(this.cell.ShowValue)) return
+
+      const handlesMap = {
+        'add-point': this.changeCellPoint,
+        'del-point': this.changeCellPoint,
+      }
+
+      handlesMap[key]&&handlesMap[key](key)
+    },
+
+    /* 处理小数点位数 */
+    changeCellPoint(key) {
+      let value = _.cloneDeep(this.cell.ShowValue)
+      key==='add-point' ? this.option.pn++ : this.option.pn--;
+      
+      //判断小数点后尾数 整数最小pn为0 小数最小为负位数
+      if(this.option.pn <= parseInt(`-${getDecimalPlaces(value)}`)) {
+        this.option.pn = parseInt(`-${getDecimalPlaces(value)}`)
+      }
+
+      //百分比格式的话 pn最小为位数-2
+      if(this.option.nt==='percent' && this.option.pn <= parseInt(`-${getDecimalPlaces(value)-2}`)) {
+        this.option.pn = parseInt(`-${getDecimalPlaces(value)-2}`)
+      }
+
+      let nval = transDecimalPlace(value,this.option)
+      // console.log(nval)
+
+      this.$emit('updateCell',{
+        ShowStyle: JSON.stringify(this.option),
+        ShowFormatValue: nval
+      })
+    },
+
+    /* 处理百分位或数字格式 */
+    changeCellType() {
+      if(!isNumberVal(this.cell.ShowValue)) return
+      this.option.pn = 0
+
+      let value = _.cloneDeep(this.cell.ShowValue)
+
+      let nval = transNumPercentType(value,this.option.nt)
+
+      this.$emit('updateCell',{
+        ShowStyle: JSON.stringify(this.option),
+        ShowFormatValue: nval
+      })
+    }
+  },
+};
+</script>
+<style scoped lang="scss">
+.toolbar-wrapper {
+  width: fit-content;
+  display: flex;
+  overflow: hidden;
+  background: #fff;
+  border: 1px solid #ccc;
+  border-bottom: none;
+  padding: 2px 12px;
+  .tool-btn-item {
+    margin: 5px;
+    display: flex;
+    align-items: center;
+    button {
+      border: none;
+      padding: 4px;
+      background: #fff;
+      &:hover {
+        background: #ccc;
+      }
+
+      .icon-wrap {
+        width: 20px;
+        height: 20px;
+        display: inline-block;
+      }
+    }
+  }
+}
+</style>

+ 16 - 2
src/views/datasheet_manage/customAnalysis/components/bottomSection.vue

@@ -11,7 +11,7 @@
       </div>
 
       <div>
-        <el-select 
+        <!-- <el-select 
           v-model="select_classify"
           placeholder="请选择表格目录"
           clearable
@@ -23,7 +23,21 @@
             :label="item.ExcelClassifyName"
             :value="item.ExcelClassifyId"
           />
-        </el-select>
+        </el-select> -->
+        <el-cascader
+          v-model="select_classify"
+          :options="classifyArr"
+          style="width:350px;"
+          :props="{
+            label: 'ExcelClassifyName',
+            value: 'ExcelClassifyId',
+            children: 'Children',
+            emitPath: false,
+            checkStrictly: true
+          }"
+          clearable
+          placeholder="请选择表格分类"
+        />
         <el-button type="primary" style="margin-left:30px" @click="saveSheetHandle">保存</el-button>
           <el-tooltip class="item" effect="dark" content="根据用户选择的sheet页上传文件" placement="top-start">
           <i class="el-icon-warning"/>

+ 37 - 1
src/views/datasheet_manage/customAnalysis/list.vue

@@ -96,6 +96,14 @@
                   alt=""
                   style="width: 14px; height: 14px; margin-right: 8px"
                 />
+                 <!-- 添加子 -->
+								<img
+									src="~@/assets/img/set_m/add.png"
+									alt=""
+									style="width: 14px; height: 14px; margin-right: 8px"
+									@click.stop="addNode(node,data)"
+									v-if="!data.ExcelInfoId&&isSheetBtnShow('classifyOpt_edit')&&node.level<3"
+								/>
                 <img
                   src="~@/assets/img/set_m/edit.png"
                   alt=""
@@ -496,17 +504,45 @@ export default {
       this.dialog_title = "添加";
       this.classifyForm = {
         classify_name: "",
+        parentClassifyId: 0,
+        parentName:''
+      };
+      this.classifyDia = true;
+    },
+
+    // 递归节点
+		getNodeParentData(data,arr){
+			if(data.level===0) return
+			arr.push({ExcelClassifyName:data.data.ExcelClassifyName,ExcelClassifyId:data.data.ExcelClassifyId})
+			this.getNodeParentData(data.parent,arr)
+			return arr
+		},
+
+    /* 添加节点 */
+    addNode(node,data) {
+      let arr = []
+      arr = this.getNodeParentData(node,arr).reverse();
+      this.dialog_title = "添加";
+      /* 编辑目录 */
+      this.classifyForm = {
+        classify_name: "",
+        parentClassifyId: data.ExcelClassifyId,
+        parentName: arr.map(_=>_.ExcelClassifyName).join('/')
       };
       this.classifyDia = true;
     },
 
     /* 编辑节点 */
-    editNode(node, { ExcelClassifyName, ExcelClassifyId }) {
+    editNode(node, { ExcelClassifyName, ExcelClassifyId,ParentId }) {
+      let arr = []
+      arr = ParentId ? this.getNodeParentData(node.parent,arr).reverse() : [];
       this.dialog_title = "编辑";
       /* 编辑目录 */
       this.classifyForm = {
         classify_name: ExcelClassifyName,
         classify_id: ExcelClassifyId,
+        parentClassifyId: ParentId,
+        parentName: arr.map(_=>_.ExcelClassifyName).join('/')
       };
       this.classifyDia = true;
     },

+ 18 - 2
src/views/datasheet_manage/customSheetEdit.vue

@@ -26,7 +26,7 @@
             </el-input>
           </li>
           <li>
-            <el-select 
+            <!-- <el-select 
               v-model="sheetForm.classify" 
               placeholder="请选择表格分类"
               style="width:240px;"
@@ -38,7 +38,23 @@
                   :label="item.ExcelClassifyName"
                   :value="item.ExcelClassifyId"
                 />
-              </el-select>
+              </el-select> -->
+
+
+            <el-cascader
+              v-model="sheetForm.classify"
+              :options="classifyArr"
+              style="width:240px;"
+              :props="{
+                label: 'ExcelClassifyName',
+                value: 'ExcelClassifyId',
+                children: 'Children',
+                emitPath: false,
+                checkStrictly: true
+              }"
+              clearable
+              placeholder="请选择表格分类"
+            />
           </li>
           <li>
             <el-select 

+ 23 - 17
src/views/datasheet_manage/mixedSheetEdit.vue

@@ -6,24 +6,25 @@
           <el-input
             v-model="sheetForm.name"
             placeholder="请输入表格名称"
-            style="width:240px"
+            style="width:220px"
             clearable>
           </el-input>
         </li>
         <li>
-          <el-select 
-            v-model="sheetForm.classify" 
-            placeholder="请选择表格分类"
+          <el-cascader
+            v-model="sheetForm.classify"
+            :options="classifyArr"
+            style="width:220px;"
+            :props="{
+              label: 'ExcelClassifyName',
+              value: 'ExcelClassifyId',
+              children: 'Children',
+              emitPath: false,
+              checkStrictly: true
+            }"
             clearable
-            style="min-width:240px"
-          >
-							<el-option
-								v-for="item in classifyArr"
-								:key="item.ExcelClassifyId"
-								:label="item.ExcelClassifyName"
-								:value="item.ExcelClassifyId"
-              />
-						</el-select>
+            placeholder="请选择表格分类"
+          />
         </li>
         <li>
           表格说明
@@ -41,6 +42,7 @@
       </ul>
       <div>
         <span v-if="updateTime" style="color:#999999 ;">最近保存时间:{{updateTime}}</span>
+        <el-button type="primary" size="medium" @click="()=>{ sheetInit=false;getDetail('refresh')}" style="margin-left:10px" icon="el-icon-refresh-right">更新</el-button>
         <el-button type="primary" size="medium" @click="saveSheetHandle" style="margin-left:10px" v-if="hasPermission">保存</el-button>
         <el-button type="primary" size="medium" plain @click="backHandle">返回</el-button>
       </div>
@@ -97,9 +99,11 @@ export default {
       sheetId: this.$route.query.id || '',
       classifyArr: [],
       rules: `表格说明:<br>
-        1、手动输入:单击每个单元格可直接输入文本、数字、日期(格式示例:2023-05-23),输入内容可匹配指标名称,ETA指标库和ETA预测指标库指标均可搜索,在下拉框中选择指标,则该单元格为已选指标行/列。<br>
-        2、插入指标值:右键单元格,点击“插入指标值”,则查询该单元格行、列最近的日期和指标名称,将查找到的指标对应日期的值填入该单元格,指标值总是在右下角。<br>
-        3、更新与计算规则:表格中指标值的日期不自动更新,数值不支持单元格计算`,
+        1、手动输入:单击每个单元格可直接输入文本、数字、日期(格式示例:2023-05-23)<br>
+        2、根据表格中日期选择指标值:在弹窗中搜索并选择指标,默认选择指标最新日期,可插入指标值,随着指标更新;也支持选择指标后,在表格中选择或输入一个日期,则插入该指标在选定日期的值。<br>
+        3、导入日期:导入系统或指标相关的日期,可进一步进行日期变换,跟随系统日期或指标日期更新。<br>
+        4、日期计算:对表格中日期进行计算。<br>
+        5、指标计算:选择指标进行计算,插入指标计算值。`,
       sheetForm: {
         sheetType: 1
       },
@@ -124,7 +128,7 @@ export default {
     },
 
     /* 获取表格详情 */
-    async getDetail() {
+    async getDetail(type='init') {
       if(!this.sheetId) return
 
       const res = await sheetInterface.sheetDetail({
@@ -153,6 +157,8 @@ export default {
       this.updateTime =  this.$moment(ModifyTime).format('YYYY-MM-DD HH:mm:ss')
 
       this.$refs.mixedTableRef.initData(TableData);
+      
+      type==='refresh' && this.$message.success('表格数据已更新')
     },
 
     /* 获取分类 */

+ 72 - 18
src/views/datasheet_manage/mixins/classifyMixin.js

@@ -77,7 +77,7 @@ export default {
 					? 'auto'
 					: width <= 260
 					? 90
-					: 0.7 * width;
+					: 0.6 * width;
 			this.$set(node, 'Nodewidth', label_wid + 'px');
 		},200),
 
@@ -118,6 +118,7 @@ export default {
         this.new_label !== data.ClassifyName && sheetInterface.classifyEdit({
           ExcelClassifyId: data.ExcelClassifyId,
           ExcelClassifyName: this.new_label,
+          ParentId: data.ParentId,
           Source: this.sourceMap[this.$route.path]
         }).then(res => {
           if(res.Ret !== 200) return
@@ -131,11 +132,67 @@ export default {
     dropOverHandle(b, a, i, e) {
       // console.log(i, a);
       // 被拖拽节点对应的 Node、结束拖拽时最后进入的节点、被拖拽节点的放置位置
-      // 一/二级目录
-      if ([1].includes(b.level)) this.handleMoveCatalogue(b, a, i, e);
+      let isSheet = b.data.ExcelInfoId ? true : false;
+      let list=a.parent.childNodes;
+			let targetIndex=0,PrevClassifyId=0,NextClassifyId=0,ParentClassifyId=0;
+      
+			let ClassifyId=isSheet?0:b.data.ExcelClassifyId,ExcelInfoId=isSheet?b.data.ExcelInfoId:0,PrevExcelInfoId=0,NextExcelInfoId=0;
 
-      // 指标层
-      if (b.level === 2) this.handleMoveSheet(b, a, i, e);
+
+      if(i!=='inner'){
+				ParentClassifyId=a.parent.data.ExcelClassifyId||0
+				list.forEach((item,index)=>{
+					if(isSheet){
+						if(item.data.ExcelInfoId===b.data.ExcelInfoId){
+							targetIndex=index
+						}
+					}else{
+						if(item.data.ExcelClassifyId===b.data.ExcelClassifyId){
+							targetIndex=index
+						}
+					}
+					
+				})
+				
+				
+				if(targetIndex===0){
+					const data=list[targetIndex+1].data
+					NextClassifyId=data.ExcelInfoId?0:data.ExcelClassifyId
+					NextExcelInfoId=data.ExcelInfoId?data.ExcelInfoId:0
+				}else if(targetIndex===list.length-1){
+					const data=list[targetIndex-1].data
+					PrevClassifyId=data.ExcelInfoId?0:data.ExcelClassifyId
+					PrevExcelInfoId=data.ExcelInfoId?data.ExcelInfoId:0
+				}else{
+					const pData=list[targetIndex-1].data
+					PrevClassifyId=pData.ExcelInfoId?0:pData.ExcelClassifyId
+
+					PrevExcelInfoId=pData.ExcelInfoId?pData.ExcelInfoId:0
+
+					const nData=list[targetIndex+1].data
+					NextClassifyId=nData.ExcelInfoId?0:nData.ExcelClassifyId
+					NextExcelInfoId=nData.ExcelInfoId?nData.ExcelInfoId:0
+				}
+			}else{
+				ParentClassifyId=a.data.ExcelClassifyId||0
+			}
+      
+      let params = {
+        ClassifyId,
+        ParentClassifyId,
+        NextClassifyId,
+        PrevClassifyId,
+        ExcelInfoId,
+        NextExcelInfoId,
+        PrevExcelInfoId,
+        Source: this.sourceMap[this.$route.path]
+      }
+      sheetInterface.classifyMove(params)
+        .then((res) => {
+          if (res.Ret !== 200) return;
+          this.$message.success("移动成功!");
+          this.getTreeData();
+        });
     },
 
     // 移动的为一级目录
@@ -273,20 +330,17 @@ export default {
     /* 判断节点是否能被拖入 */
     canDropHandle(draggingNode, dropNode, type) {
       let canDrop = false;
-      // 移动的是一级目录
-      if (draggingNode.level === 1 && dropNode.level === 1 &&type!=='inner') {
-        canDrop = true;
-      }
 
-      // 二级
-      if (draggingNode.level === 2) {
-        if (
-          (dropNode.level === 1 && type === "inner") ||
-          (dropNode.level === 2 && type !== "inner")
-        ) {
-          canDrop = true;
-        }
-      }
+      // 指标
+			if(draggingNode.data.ExcelInfoId){
+				if(!(dropNode.level===1&&type!=='inner')){
+					canDrop=true
+				}
+			}else{//目录
+				if((dropNode.level+1==draggingNode.level&&type==='inner')||(dropNode.level===draggingNode.level&&type!=='inner')){
+					canDrop=true
+				}
+			}
 
       return canDrop;
     },

+ 53 - 3
src/views/datasheet_manage/sheetList.vue

@@ -12,9 +12,17 @@
         <div class="datasheet_top">
           <el-button v-if="permissionBtn.checkPermissionBtn(permissionBtn.etaTablePermission.etaTable_excel)&&sourceMap[$route.path]===1" type="primary" style="margin-right:20px" @click="goAddSheetHandle"
           >添加Excel表格</el-button >
+
           <el-button v-if="permissionBtn.checkPermissionBtn(permissionBtn.etaTablePermission.etaTable_customize_data_sheetAdd)&&sourceMap[$route.path]===2" type="primary" style="margin-right:20px" @click="goAddSheetHandle">添加时间序列表格</el-button >
+
           <el-button v-if="permissionBtn.checkPermissionBtn(permissionBtn.etaTablePermission.etaTable_customize_mix_sheetAdd)&&sourceMap[$route.path]===3" type="primary" @click="goAddSheetHandle">添加混合表格</el-button >
 
+          <el-checkbox 
+            v-model="isShowMe"
+            style="margin-left:20px"
+            @change="() => { getTreeData();getPublicList() }"
+          >只看我的</el-checkbox>
+
         </div>
         <div class="search-cont">
           <el-select
@@ -90,6 +98,14 @@
                   alt=""
                   style="width: 14px; height: 14px; margin-right: 8px"
                 />
+                <!-- 添加子 -->
+								<img
+									src="~@/assets/img/set_m/add.png"
+									alt=""
+									style="width: 14px; height: 14px; margin-right: 8px"
+									@click.stop="addNode(node,data)"
+									v-if="!data.ExcelInfoId&&isSheetBtnShow('classifyOpt_edit')&&node.level<3"
+								/>
                 <img
                   src="~@/assets/img/set_m/edit.png"
                   alt=""
@@ -425,6 +441,8 @@ export default {
       },
       autoSaveType:'',//自动保存类型,有的自动保存后需要其他操作
       cancelAutoSave:false, //自动保存时延迟的
+
+      isShowMe: false//只看我的
     };
   },
   watch: {
@@ -502,7 +520,10 @@ export default {
 
     /* 获取表格分类 */
     getTreeData(params = null) {
-      sheetInterface.classifyList({Source: this.sourceMap[this.$route.path]}).then((res) => {
+      sheetInterface.classifyList({
+        Source: this.sourceMap[this.$route.path],
+        IsShowMe: this.isShowMe
+      }).then((res) => {
         const { Ret, Data } = res;
         if (Ret !== 200) return;
 
@@ -552,17 +573,45 @@ export default {
       this.dialog_title = "添加";
       this.classifyForm = {
         classify_name: "",
+        parentClassifyId: 0,
+        parentName:''
+      };
+      this.classifyDia = true;
+    },
+
+    // 递归节点
+		getNodeParentData(data,arr){
+			if(data.level===0) return
+			arr.push({ExcelClassifyName:data.data.ExcelClassifyName,ExcelClassifyId:data.data.ExcelClassifyId})
+			this.getNodeParentData(data.parent,arr)
+			return arr
+		},
+
+    /* 添加节点 */
+    addNode(node,data) {
+      let arr = []
+      arr = this.getNodeParentData(node,arr).reverse();
+      this.dialog_title = "添加";
+      /* 编辑目录 */
+      this.classifyForm = {
+        classify_name: "",
+        parentClassifyId: data.ExcelClassifyId,
+        parentName: arr.map(_=>_.ExcelClassifyName).join('/')
       };
       this.classifyDia = true;
     },
 
     /* 编辑节点 */
-    editNode(node, { ExcelClassifyName, ExcelClassifyId }) {
+    editNode(node, { ExcelClassifyName, ExcelClassifyId,ParentId }) {
+      let arr = []
+      arr = ParentId ? this.getNodeParentData(node.parent,arr).reverse() : [];
       this.dialog_title = "编辑";
       /* 编辑目录 */
       this.classifyForm = {
         classify_name: ExcelClassifyName,
         classify_id: ExcelClassifyId,
+        parentClassifyId: ParentId,
+        parentName: arr.map(_=>_.ExcelClassifyName).join('/')
       };
       this.classifyDia = true;
     },
@@ -774,7 +823,8 @@ export default {
         CurrentIndex: this.sheet_page,
         PageSize: this.sheet_pages_size,
         ExcelClassifyId: this.select_classify || 0,
-        Source: this.sourceMap[this.$route.path]
+        Source: this.sourceMap[this.$route.path],
+        IsShowMe: this.isShowMe
       }).then((res) => {
         if (res.Ret !== 200) return;