소스 검색

Merge branch 'ETA1.8.5'

jwyu 5 달 전
부모
커밋
2208aa51c0

+ 61 - 0
src/api/modules/sheetApi.js

@@ -141,6 +141,67 @@ export const uploadImg = params => {
   return http.get('/datamanage/excel_info/table_data',params)
 }
 
+// 平衡表获取子表列表
+export const getBalanceChildTable=params=>{
+	return http.get('/datamanage/excel_info/child_table',params)
+}
+
+// 平衡表修改子表名称
+export const balanceChildTableRename=params=>{
+	return http.post('/datamanage/excel_info/rename',params)
+}
+
+//获取平衡表协作人数据
+export const getBalanceTableWorker=params=>{
+	return http.get('/datamanage/excel_info/worker',params)
+}
+
+//设置平衡表协作人数据
+export const setBalanceTableWorker=params=>{
+	return http.post('/datamanage/excel_info/worker/save',params)
+}
+
+//获取平衡表中图表数据
+export const getBalanceChartData=params=>{
+	return http.get('/datamanage/excel_info/balance/chart_list',params)
+}
+
+//平衡表中新增图表数据
+export const addBalanceChart=params=>{
+	return http.post('/datamanage/excel_info/balance/chart_add',params)
+}
+
+//平衡表中编辑图表数据
+export const editBalanceChart=params=>{
+	return http.post('/datamanage/excel_info/balance/chart_edit',params)
+}
+
+//平衡表中删除图表
+export const delBalanceChart=params=>{
+	return http.post('/datamanage/excel_info/balance/chart_del',params)
+}
+
+//平衡表季节图预览 获取数据
+export const balanceSeasonChart=params=>{
+	return http.post('/datamanage/excel_info/balance/chartLegend/preview',params)
+}
+
+//平衡表获取版本列表
+export const balanceTableVersion=params=>{
+	return http.get('/datamanage/excel_info/balance/version',params)
+}
+
+//平衡表存为静态表
+export const balanceTableSaveStatic=params=>{
+	return http.post('/datamanage/excel_info/balance/static/add',params)
+}
+
+//平衡表静态表重命名
+export const balanceStaticTableRename=params=>{
+	return http.post('/datamanage/excel_info/balance/version/modify',params)
+}
+
+
 /* =====自定义表格====== */
 
 /**

+ 20 - 0
src/lang/modules/ETATables/En.js

@@ -83,6 +83,18 @@ export default {
     table_data_update_msg: "The table data has been updated",
     formula_lable: "Formula",
     parent_directory_lable: "Parent directory",
+    add_balance_table_btn:'Add Balance Sheet',
+    Co_editor:'Co-editor',
+    save_static_table:'Save as a static table',
+    save_static_table_tip:'Please enter the version name',
+    static_table_version_name:'Version name',
+    chart_source_placehoder:'please enter data source',
+    left_limit:'Left axis limits',
+    right_limit:'Right axis limits',
+    right_two_limit:'limits of the right second axis',
+    y_limit:'Vertical axis limits',
+    time_serial:'Time Series',
+    value_serial:'numerical sequence',
     not_allow_edit:'Currently not editable'
   },
 
@@ -159,4 +171,12 @@ export default {
     lagging_lable: "lagging",
     select_metric: "Please select a metric",
   },
+
+  /* 平衡表  */
+  BalanceSheet:{
+    version:'Version',
+    active_table:'Active',
+    save_static_table:'Save as a static table',
+    only_edit:'Editable',
+  },
 };

+ 21 - 0
src/lang/modules/ETATables/Zh.js

@@ -83,6 +83,18 @@ export default {
     table_data_update_msg: "表格数据已更新",
     formula_lable: "公式",
     parent_directory_lable: "上级目录",
+    add_balance_table_btn:'添加平衡表',
+    Co_editor:'协作人',
+    save_static_table:'存为静态表',
+    save_static_table_tip:'请输入版本名称',
+    static_table_version_name:'版本名称',
+    chart_source_placehoder:'请输入数据来源',
+    left_limit:'左轴上下限',
+    right_limit:'右轴上下限',
+    right_two_limit:'右二轴上下限',
+    y_limit:'纵轴上下限',
+    time_serial:'时间序列',
+    value_serial:'数值序列',
     not_allow_edit:'当前不可编辑'
   },
 
@@ -171,4 +183,13 @@ export default {
   lagging_lable: "滞后",
   select_metric: "请选择指标",
   },
+
+  /* 平衡表  */
+  BalanceSheet:{
+    version:'版本',
+    active_table:'动态表',
+    save_static_table:'存为静态表',
+    only_edit:'只看可编辑',
+    
+  },
 };

+ 22 - 0
src/lang/modules/ETATables/commonLang.js

@@ -82,6 +82,10 @@ export default {
       en: "Insertion Successful",
       zh: "插入成功",
     },
+    is_del_balance_chart_msg:{
+      en:'After deletion, this chart will no longer be referenced. Are you sure to delete it?',
+      zh:'删除后该图表将不能再引用,确认删除吗?',
+    },
   },
   Date: {
     monday: {
@@ -219,6 +223,24 @@ export default {
       en: "Insert row below",
     },
   },
+  BalanceSheetTable:{
+    name:{
+      zh: "名称",
+      en: "Name",
+    },
+    creator:{
+      zh: "创建人",
+      en: "Creator",
+    },
+    updater:{
+      zh: "更新人",
+      en: "Updater",
+    },
+    update_time:{
+      zh: "更新时间 ",
+      en: "Updating Time",
+    }
+  }
 };
 
 //ETable

+ 2 - 0
src/lang/modules/systemManage/OperateAuth.js

@@ -53,6 +53,7 @@ export const OperateAuthEn = {
     tab_sub_sheet1:'Custom analysis',
     tab_sub_sheet2:'Time Series Table',
     tab_sub_sheet3:'Mixed Table ',
+    tab_sub_sheet4:'Balance Table ',
     label_count: 'Quantity',
     label_checked:'Selected',
     ph_see_user:'Please select visible users',
@@ -124,6 +125,7 @@ export const OperateAuthZh = {
     tab_sub_sheet1:'自定义分析',
     tab_sub_sheet2:'时间序列表格',
     tab_sub_sheet3:'混合表格',
+    tab_sub_sheet4:'平衡表',
     label_count: '数量',
     label_checked:'已选',
     ph_see_user:'请选择可见用户',

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

@@ -223,6 +223,33 @@ export default [
 					name_en:"Generated pointer"
 				}
 			},
+			{
+				path:"sheetBalanceList",
+				name:"平衡表",
+				component:()=>import('@/views/datasheet_manage/sheetList.vue'),
+				meta:{
+					name_en:'Balance Sheet'
+				}
+			},
+			{
+				path:"viewBalanceSheet",
+				name:"平衡表",
+				component:()=>import('@/views/datasheet_manage/balanceSheetEdit.vue'),
+				meta:{
+					name_en:'Balance Sheet'
+				}
+			},
+			{
+				path:"editBalanceSheet",
+				name:"编辑平衡表",
+				component:()=>import('@/views/datasheet_manage/balanceSheetEdit.vue'),
+				meta: {
+					name_en:'Edit Balance sheet',
+					pathFrom: "sheetBalanceList",
+					pathName: "平衡表",
+					pathName_en:'Balance Sheet'
+				}
+			},
 		]
 	},
 

+ 10 - 0
src/utils/buttonConfig.js

@@ -464,6 +464,16 @@ export const etaTablePermission = {
     etaTable_analysis_del:'etaTable:analysis:del',//删除
     etaTable_analysis_save:'etaTable:analysis:save',//保存
     etaTable_analysis_edit:'etaTable:analysis:edit',//编辑
+
+    // 平衡表
+    etaTable_customize_balance_sheetAdd:'etaTable:customize:balance:sheetAdd',//添加
+    etaTable_customize_balance_del:'etaTable:customize:balance:del',//删除
+    etaTable_customize_balance_download:'etaTable:customize:balance:download',//下载
+    etaTable_customize_balance_otherSave:'etaTable:customize:balance:otherSave',//另存为
+    etaTable_customize_balance_refresh:'etaTable:customize:balance:refresh',//刷新
+    etaTable_customize_balance_edit:'etaTable:customize:balance:edit',//编辑
+    etaTable_customize_balance_classifyOpt_delete:'etaTable:customize:balance:classifyOpt:delete',//删除分类
+    etaTable_customize_balance_classifyOpt_edit:'etaTable:customize:balance:classifyOpt:edit',//添加/编辑分类
 }
 /*
  * --------------------------------------------------------------------------ETA逻辑------------------------------------------------

+ 2 - 2
src/views/chartRelevance_manage/components/selectTarget.vue

@@ -208,10 +208,10 @@ export default {
                 14: 6
               }
 
-              let FilterSource = (this.$route.path==='/addMixedSheet' && this.$parent.isCalculateDia)
+              let FilterSource = (['/addMixedSheet','/editBalanceSheet'].includes(this.$route.path) && this.$parent.isCalculateDia)
                 ? filterMap[this.$parent.formData.source]||1 
                 : 1;
-              let Frequency = (this.$route.path==='/addMixedSheet' && this.$parent.isCalculateDia && this.$parent.formData.source===2)
+              let Frequency = (['/addMixedSheet','/editBalanceSheet'].includes(this.$route.path) && this.$parent.isCalculateDia && this.$parent.formData.source===2)
                 ? '季度' 
                 : ''
               res = await sheetInterface.searchTarget({

+ 5 - 5
src/views/dataEntry_manage/mixins/chartPublic.js

@@ -480,7 +480,7 @@ export const chartSetMixin = {
         placeholder:/* '请输入图表名称' */this.$t('Chart.InputHolderAll.input_common',{label:this.$t('Chart.Detail.chart_name')})
       })
 
-      if([1,2,5].includes(this.chartInfo.Source)){ //需要设置指标的
+      if([1,2,5,11].includes(this.chartInfo.Source)){ //需要设置指标的
         this.tableData.map(item =>{
             this.formItemArray.chartsList.push([
               {
@@ -749,7 +749,7 @@ export const chartSetMixin = {
         const useTableLimit = ['/predictEdb','/addpredictEdb','/editpredictEdb','/chartThemeSet'].includes(this.$route.path)
         //非ETA图库图表也不设置自定义上下限,相关性和统计特征也会用到曲线图
         //若chartInfo.Source为1,需在之前调用setLimitData
-        const isETASource = this.chartInfo.Source===1
+        const isETASource = [1,11].includes(this.chartInfo.Source)
         let minLimit = 0,maxLimit = 0
         if(useTableLimit||!isETASource){
             minLimit = newval[sameSideIndex].MinData
@@ -1090,7 +1090,7 @@ export const chartSetMixin = {
       const chartDataHandle=this.calendar_type === '农历'?
                             this.isPredictorChart?chartData.DataList.List.filter((item, index) => index > 0):
                             chartData.DataList.filter((item, index) => index > 0):
-                            chartData.DataList
+                            chartData.DataList||[]
        /* 主题样式*/
        const chartTheme =  this.chartInfo.ChartThemeStyle ? JSON.parse(this.chartInfo.ChartThemeStyle) : null;
 
@@ -1099,7 +1099,7 @@ export const chartSetMixin = {
 
         //获取对应轴的上下限
         //预测指标-走势图;图表配置-主题设置;不使用自定义上下限,剔除
-        const useTableLimit = ['/predictEdb','/chartThemeSet','/addpredictEdb','/editpredictEdb'].includes(this.$route.path)
+        const useTableLimit = ['/predictEdb','/chartThemeSet','/addpredictEdb','/editpredictEdb','/viewBalanceSheet','/editBalanceSheet'].includes(this.$route.path)
         let minLimit = 0,maxLimit = 0
         if(useTableLimit){
             minLimit = chartData.MinData
@@ -1234,7 +1234,7 @@ export const chartSetMixin = {
             enabled: false,
           };
 
-
+          console.log('季节图配置');
       this.options = {
         colors: colors.slice(-chartDataHandle.length),
         series: seasonData,

+ 638 - 0
src/views/datasheet_manage/balanceSheetEdit.vue

@@ -0,0 +1,638 @@
+<template>
+  <div class="balance-sheet-detail-wrap">
+    <noDataAuth class="no-auth-box" v-if="!excelInfo.HaveOperaAuth&&isView" :text="$t('MsgPrompt.no_sheet_auth')"/>
+    <div class="wrap-top">
+      <ul class="form-ul">
+        <li>
+          <el-input
+            v-model="sheetForm.name"
+            :placeholder="$t('OnlineExcelPage.please_table_name_ipt')"
+            style="width: 200px"
+            clearable
+            :disabled="isView||isStaticTable"
+          >
+          </el-input>
+        </li>
+        <li>
+          <el-cascader
+            v-model="sheetForm.classify"
+            :options="classifyArr"
+            style="width: 120px"
+            :props="{
+              label: 'ExcelClassifyName',
+              value: 'ExcelClassifyId',
+              children: 'Children',
+              emitPath: false,
+              checkStrictly: true,
+            }"
+            :placeholder="$t('OnlineExcelPage.select_table_category')"
+            :disabled="isView||isStaticTable"
+          />
+        </li>
+        <li v-if="excelInfo.Button&&excelInfo.Button.OpWorkerButton">
+          <el-cascader
+            v-model="sheetForm.user"
+            :options="userList"
+            style="width: 120px"
+            :show-all-levels="false"
+            collapse-tags
+            :props="{
+              label: 'NodeName',
+              value: 'NodeId',
+              children: 'Children',
+              multiple: true,
+              emitPath: false,
+              checkStrictly: false,
+            }"
+            clearable
+            :placeholder="$t('OnlineExcelPage.Co_editor')"
+            :disabled="isView||isStaticTable"
+          />
+        </li>
+      </ul>
+      <div class="form-ul">
+        <span>{{ $t("BalanceSheet.version") }}</span>
+        <el-select
+          v-model="sheetForm.version"
+          style="width: 90px; margin-right: 5px"
+          @change="handleVersionChange"
+        >
+          <el-option
+            v-for="item in versionOpts"
+            :key="item.ExcelInfoId"
+            :label="item.VersionName"
+            :value="item.ExcelInfoId"
+          ></el-option>
+        </el-select>
+        <!-- 存为静态表按钮 -->
+        <el-button type="primary" @click="handleShowSaveStaticTable" v-if="!isView&&!isStaticTable">{{
+          $t("BalanceSheet.save_static_table")
+        }}</el-button>
+        <!-- 静态表操作 -->
+        <span v-if="!isView&&isStaticTable">
+        <span
+          class="editsty"
+          @click="handleShowSaveStaticTable('rename')"
+          style="margin-right: 10px"
+          >{{$t('MyEtaPage.option_op_rename')}}</span
+        >
+        <span
+          class="deletesty"
+          @click="handleStaticTableDel"
+          >{{$t("Table.delete_btn")}}</span
+        >
+        </span>
+        <div>
+          <!-- {{ $t("OnlineExcelPage.table_explaination_text") }} -->
+          <el-tooltip effect="dark">
+            <div
+              slot="content"
+              v-html="rules"
+              style="line-height: 20px; width: 350px"
+            ></div>
+            <i class="el-icon-question" />
+          </el-tooltip>
+        </div>
+      </div>
+      <div>
+        <span v-if="updateTime" style="color: #999999"
+          >{{ $t("OnlineExcelPage.recent_save_time_info")
+          }}{{ updateTime }}</span
+        >
+        <!-- 预览页面操作按钮 -->
+        <template v-if="isView">
+          <!-- <div> -->
+          <span
+            class="editsty"
+            @click="itemHandle(excelInfo, 'edit')"
+            style="margin-right: 10px"
+            v-if="isSheetBtnShow('edit')&&excelInfo.Button&&excelInfo.Button.OpButton"
+            >{{excelInfo.CanEdit?$t("ETable.Btn.edit_btn"):excelInfo.Editor+$t('OnlineExcelPage.editing_msg')}}</span
+          >
+          <span
+            class="editsty"
+            @click="itemHandle(excelInfo, 'refresh')"
+            style="margin-right: 10px"
+            v-if="isSheetBtnShow('refresh')&&excelInfo.Button&&excelInfo.Button.RefreshButton"
+            >{{ $t("ETable.Btn.refresh_btn") }}</span
+          >
+          <span
+            class="editsty"
+            @click="itemHandle(excelInfo, 'save')"
+            style="margin-right: 10px"
+            v-if="isSheetBtnShow('otherSave')&&excelInfo.Button&&excelInfo.Button.CopyButton"
+            >{{ $t("ETable.Btn.save_as") }}</span
+          >
+          <span
+            class="editsty"
+            @click="itemHandle(excelInfo, 'download')"
+            style="margin-right: 10px"
+            v-if="isSheetBtnShow('download')&&excelInfo.HaveOperaAuth"
+            >{{ $t("ETable.Btn.download_btn") }}</span
+          >
+          <span
+            class="deletesty"
+            @click="itemHandle(excelInfo, 'del')"
+            style="margin-right: 10px"
+            v-if="isSheetBtnShow('del')&&excelInfo.Button&&excelInfo.Button.DeleteButton"
+            >{{ $t("Table.delete_btn") }}</span
+          >
+          <!-- </div> -->
+        </template>
+        <!-- icon="el-icon-refresh-right" -->
+        <el-button
+          type="primary"
+          size="medium"
+          :loading="updating"
+          @click="updateHandle"
+          style="margin-left: 10px"
+          v-if="!isView"
+          >{{
+            updating
+              ? $t("ETable.Btn.renewing_btn")
+              : $t("ETable.Btn.renew_btn")
+          }}</el-button
+        >
+        <el-button
+          type="primary"
+          size="medium"
+          @click="saveSheetHandle"
+          style="margin-left: 10px"
+          v-if="!isView"
+          >{{ $t("ETable.Btn.save_btn") }}</el-button
+        >
+        <el-button type="primary" size="medium" plain @click="backHandle">{{
+          $t("ETable.Btn.back_btn")
+        }}</el-button>
+      </div>
+    </div>
+
+    <BalanceTable 
+      ref="balanceTableRef"
+      :disabled="isView"
+      :isStaticTable="isStaticTable"
+    />
+
+    <!-- 存为静态表弹窗 -->
+    <el-dialog
+      :visible.sync="showSaveStaticTable"
+      :close-on-click-modal="false"
+      :modal-append-to-body='false'
+      :title="isStaticTable?$t('MyEtaPage.option_op_rename'):$t('OnlineExcelPage.save_static_table')"
+      @close="showSaveStaticTable=false"
+      custom-class="dialog"
+      center
+      width="500px"
+      v-dialogDrag
+    >
+      <div style="text-align:center">
+        <span>{{$t('OnlineExcelPage.static_table_version_name')}}</span>
+        <el-input v-model="staticTableName" :placeholder="$t('OnlineExcelPage.save_static_table_tip')"></el-input>
+      </div>
+      <div class="dia-bot" style="text-align:center;padding:30px 0">
+				<el-button type="primary" style="margin-right:20px" @click="createdStaticTable">{{$t('ETable.Btn.save_btn')}}</el-button>
+				<el-button type="primary" plain @click="showSaveStaticTable=false">{{$t('ETable.Btn.cancel_btn')}}</el-button>
+			</div>
+    </el-dialog>
+
+    <!-- 表格另存 -->
+    <m-dialog
+      :show.sync="isSaveOther"
+      width="650px"
+      :title="$t('ETable.Btn.save_as')"
+      @close="cancelSaveOther"
+    >
+      <div style="padding-left: 80px">
+        <el-form
+          ref="formRef"
+          label-position="left"
+          hide-required-asterisk
+          label-width="80px"
+          :model="saveOtherForm"
+          :rules="saveOtherFormRule"
+        >
+          <el-form-item :label="$t('OnlineExcelPage.excel_name_ipt')" prop="name">
+            <el-input
+              v-model="saveOtherForm.name"
+              style="width: 80%"
+              :placeholder="$t('OnlineExcelPage.please_table_name_ipt')"
+            />
+          </el-form-item>
+          <el-form-item :label="$t('OnlineExcelPage.table_classification_label')" prop="classify">
+            <el-cascader
+              v-model="saveOtherForm.classify"
+              :options="classifyArr"
+              :props="{
+                label: 'ExcelClassifyName',
+                value: 'ExcelClassifyId',
+                children: 'Children',
+                emitPath: false,
+                checkStrictly: true,
+              }"
+              style="width: 80%"
+              :placeholder="$t('OnlineExcelPage.select_appropriate_category_lable')"
+              class="sheet-classify-cascader"
+            />
+          </el-form-item>
+        </el-form>
+      </div>
+      <div style="display: flex; justify-content: center; margin-top: 30px">
+        <el-button
+          type="primary"
+          style="margin-right: 60px"
+          @click="saveCopyOther"
+          >{{$t('Dialog.confirm_save_btn')}}</el-button
+        >
+        <el-button type="primary" plain @click="cancelSaveOther"
+          >{{$t('Dialog.cancel_btn')}}</el-button
+        >
+      </div>
+    </m-dialog>
+
+  </div>
+</template>
+
+<script>
+import * as sheetInterface from '@/api/modules/sheetApi.js';
+import { departInterence } from "@/api/api.js";
+import moment from 'moment';
+import mDialog from "@/components/mDialog.vue";
+import BalanceTable from './components/BalanceTable.vue';
+import BalanceTableMixin from './mixins/balanceTableMixin'
+export default {
+  mixins:[BalanceTableMixin],
+  components: {
+    BalanceTable,
+    mDialog
+  },
+  computed: {
+    downExcelFileUrl() {
+      let url = `${
+        process.env.VUE_APP_API_ROOT
+      }/datamanage/excel_info/table/download?${localStorage.getItem("auth")}`;
+      return url;
+    },
+    rules() {
+      return this.$t('OnlineExcelPage.TableInstructionsText') || ''
+    },
+    isView(){
+      return this.$route.path==='/viewBalanceSheet'
+    },
+    // 当前是否为静态表
+    isStaticTable(){
+      let flag=false
+      this.versionOpts.forEach(item=>{
+        if(item.ExcelInfoId===this.sheetForm.version&&item.BalanceType==1){
+          flag=true
+        }
+      })
+      return flag
+    },
+    saveOtherFormRule(){
+      return {
+        name: [
+          { required: true, message: this.$t('OnlineExcelPage.table_name_empty_msg') , trigger: "blur" },
+        ],
+        classify: [
+          { required: true, message: this.$t('OnlineExcelPage.cannot_be_empty_table') , trigger: "blur" },
+        ],
+      }
+    }
+  },
+  data() {
+    return {
+      sheetId: this.$route.query.id || '',
+      excelInfo:{},
+
+      updating:false,
+
+      sheetForm: {
+        name: '',
+        classify: '',
+        user: '',
+        version: Number(this.$route.query.id),
+      },
+      classifyArr: [],
+      userList: [],//系统用户
+      updateTime: moment().format('YYYY-MM-DD HH:mm:ss'),
+      versionOpts: [],
+
+      showSaveStaticTable:false,//存为静态表弹窗
+      staticTableName:moment().format('YYYY-MM-DD'),
+
+      /* 另存为 */
+      isSaveOther: false,
+      saveOtherForm: {
+        name: '',
+				classify: ''
+      },
+
+    }
+  },
+  created() {
+    this.getClassify();
+    this.getSystemUserList()
+    this.getChildTable()
+    this.getDetail()
+    this.getVersionList()
+  },
+  beforeRouteLeave(to,from,next){
+    console.log('退出编辑',from);
+    if(from.path==='/editBalanceSheet'){
+      this.markFinishStatus()
+    }
+    next()
+  },
+  methods: {
+    // 获取版本列表
+    getVersionList(){
+      sheetInterface.balanceTableVersion({ExcelInfoId:this.sheetId}).then(res=>{
+        if(res.Ret===200){
+          const arr=res.Data.List||[]
+          if(this.$i18nt.locale!=='zh'){
+            arr[0].VersionName='Active'
+          }
+          this.versionOpts=arr
+        }
+      })
+    },
+
+    handleVersionChange(){
+      this.getChildTable()
+    },
+
+    cancelSaveOther() {
+      this.$refs.formRef.resetFields();
+      this.saveOtherForm = {
+        name: '',
+				classify: ''
+      };
+      this.isSaveOther = false;
+    },
+
+    /* 另存为 */
+    async saveCopyOther() {
+      await this.$refs.formRef.validate();
+      let { classify, name } = this.saveOtherForm;
+
+      const res = await sheetInterface.copyExcel({
+        ExcelInfoId: this.excelInfo.ExcelInfoId,
+        ExcelName: name,
+        ExcelClassifyId: classify,
+      });
+
+      if (res.Ret !== 200) return;
+
+      this.$message.success(this.$t('MsgPrompt.saved_msg') );
+      this.cancelSaveOther();
+    },
+
+    handleShowSaveStaticTable(type){
+      console.log(type);
+      if(type==='rename'){
+        this.versionOpts.forEach(item=>{
+          if(item.ExcelInfoId===this.sheetForm.version){
+            this.staticTableName=item.VersionName
+          }
+        })
+      }else{
+        this.staticTableName=this.$moment().format('YYYY-MM-DD')
+      }
+      this.showSaveStaticTable=true
+    },
+    // 创建/重命名静态表
+    createdStaticTable(){
+      if(!this.staticTableName){
+        this.$message.warning(this.$t('OnlineExcelPage.save_static_table_tip'))
+        return
+      }
+      // 重命名
+      if(this.isStaticTable){
+        sheetInterface.balanceStaticTableRename({
+          ExcelInfoId:Number(this.sheetForm.version),
+          VersionName:this.staticTableName
+        }).then(res=>{
+          if(res.Ret===200){
+            this.$message.success(res.Msg);
+            this.getVersionList()
+            this.showSaveStaticTable=false
+            this.$refs.balanceTableRef.getChartList()//更新图表数据
+          }
+        })
+        return
+      }
+
+      sheetInterface.balanceTableSaveStatic({
+        ExcelInfoId:Number(this.sheetForm.version),
+        VersionName:this.staticTableName
+      }).then(res=>{
+        if(res.Ret===200){
+          this.getVersionList()
+          this.sheetForm.version=res.Data.ExcelInfoId
+          this.getChildTable()
+          this.showSaveStaticTable=false
+        }
+      })
+    },
+
+    // 删除当前静态表
+    handleStaticTableDel(){
+      this.$confirm(this.$t('ETable.Msg.is_del_table_msg') , this.$t('Confirm.prompt') , {
+        confirmButtonText:  this.$t('Dialog.confirm_btn'),
+        cancelButtonText: this.$t('Dialog.cancel_btn'),
+        type: "warning",
+      }).then(()=>{
+        sheetInterface.classifyDel({
+          ExcelClassifyId:0,
+          ExcelInfoId:Number(this.sheetForm.version),
+          Source: 5
+        }).then(res=>{
+          if(res.Ret===200){
+            this.$message.success(res.Msg);
+            this.sheetForm.version=Number(this.sheetId)
+            this.getVersionList()
+            this.getChildTable()
+          }
+        })
+      }).catch(()=>{})
+    },
+
+    //获取所有子表数据
+    async getChildTable(){
+      if(!this.sheetForm.version) return
+      const res = await sheetInterface.getBalanceChildTable({
+				ParentId: Number(this.sheetForm.version)
+			})
+      if(res.Ret !== 200)  return
+      this.$refs.balanceTableRef.initSheetListData(res.Data.List||[]);
+
+    },
+
+    /* 获取表格详情 */
+    async getDetail(type='init') {
+      if(!this.sheetId) return
+      const res = await sheetInterface.sheetDetail({
+				ExcelInfoId: Number(this.sheetId)
+			})
+      if(res.Ret !== 200)  return
+      this.excelInfo=res.Data
+      const { ExcelName,ExcelClassifyId,TableData,ModifyTime,Button } = res.Data;
+      this.sheetForm.name=ExcelName
+      this.sheetForm.classify=ExcelClassifyId
+      this.getTableWorker()
+    },
+
+    // 保存父表基础信息
+    async saveTableInfo(){
+      let params = {
+        ExcelInfoId:Number(this.sheetId),
+        ExcelName: this.sheetForm.name,
+        ExcelType: 1,
+        ExcelClassifyId: this.sheetForm.classify,
+        ExcelImage: '',
+        Source: 5,
+        TableData: {
+          CellRelation:"[]",
+          Data:[]
+        }
+      };
+      const res=await sheetInterface.sheetEdit(params)
+    },
+
+    //获取协作人
+    async getTableWorker(){
+      const res=await sheetInterface.getBalanceTableWorker({
+        ExcelInfoId:Number(this.sheetId)
+      })
+      if(res.Ret !== 200)  return
+      const arr=res.Data.List||[]
+      this.sheetForm.user=arr.map(e=>e.SysUserId)
+    },
+
+    // 保存设置的协作人
+    async setTableWorker(){
+      if(!this.excelInfo.Button.OpWorkerButton) return
+      const res=await sheetInterface.setBalanceTableWorker({
+        ExcelInfoId:Number(this.sheetId),
+        SysUserIds:this.sheetForm.user?this.sheetForm.user.join(','):''
+      })
+      if(res.Ret !== 200)  return
+    },
+
+    //点击保存
+    saveSheetHandle(){
+      this.setTableWorker()// 保存协作人
+      this.saveTableInfo()// 保存父表基础信息
+      this.$refs.balanceTableRef.saveChildSheet('manualSave')
+      this.$refs.balanceTableRef.getChartList()//更新图表数据
+
+    },
+
+    // 点击更新
+    async updateHandle(){
+      if(this.updating) return
+      this.updating=true
+      // 保存一次
+      await this.$refs.balanceTableRef.saveChildSheet()
+      // 重新获取当前子表的数据
+      this.$refs.balanceTableRef.getSheetDetail('refresh')
+    },
+
+    backHandle(){
+      this.$router.back()
+    },
+
+
+    /* 获取分类 */
+    getClassify() {
+      sheetInterface.excelClassifyOne({ Source: 5 }).then(res => {
+        if (res.Ret !== 200) return
+
+        this.classifyArr = res.Data.AllNodes || [];
+      })
+    },
+
+    // 递归处理数组
+    deleteUserEmpty(arr) {
+      arr.length && arr.forEach(item => {
+        item.Children && item.Children.length && this.deleteUserEmpty(item.Children)
+        if (!item.Children || !item.Children.length) {
+          delete item.Children
+        }
+      })
+    },
+
+    getSystemUserList() {
+      departInterence.getSystemUser({
+        KeyWord: ''
+      }).then(res => {
+        if (res.Ret === 200) {
+          this.deleteUserEmpty(res.Data || [])
+          this.userList = res.Data || []
+        }
+      })
+    },
+
+    //更新编辑状态
+    markFinishStatus(){
+      if(!this.sheetId) return
+      sheetInterface.markSheetEditStatus({ExcelInfoId:Number(this.sheetId),Status:2}).then(res=>{
+        if(res.Ret != 200) return 
+      })
+    },
+
+    isSheetBtnShow(type){
+      return this.permissionBtn.isShowBtn('etaTablePermission',`etaTable_customize_balance_${type}`)
+    }
+  },
+}
+</script>
+
+<style lang="scss">
+.sheet-classify-cascader .el-input {
+	width: 100%;
+}
+</style>
+<style scoped lang="scss">
+* {
+  box-sizing: border-box;
+}
+.balance-sheet-detail-wrap {
+  min-width: 1070px;
+  min-height: calc(100vh - 120px);
+  position: relative;
+  .no-auth-box{
+    position: absolute;
+    z-index: 99;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    top: 0;
+    background-color: #F2F6FA;
+  }
+  .wrap-top {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin-bottom: 20px;
+    padding: 20px;
+    background: #fff;
+    border: 1px solid #ececec;
+    border-radius: 4px;
+    box-shadow: 0 3px 6px rgba(0, 0, 0, 0.05);
+    display: flex;
+    z-index: 1;
+    .form-ul {
+      //   flex: 1;
+      display: flex;
+      align-items: center;
+      gap: 0 5px;
+      li {
+        &:first-child {
+          padding-top: 0;
+        }
+      }
+    }
+  }
+}
+</style>

+ 5 - 1
src/views/datasheet_manage/common/customTable.js

@@ -147,7 +147,11 @@ export function setCellBg(e) {
 }
 
 //右键菜单
-export function getRightClickMenu(pos,canEdit=false) {
+export function getRightClickMenu(pos,canEdit=false,isStaticTable=false) {
+  // 如果是静态表则只有清空功能
+  if(isStaticTable){
+    return [{ label: bus.$i18nt ? bus.$i18nt.t('SystemManage.ReportApprove.clear_btn'):"清空", key: "reset" }]
+  }
 
   let cellMenu = [
     { label: bus.$i18nt ? bus.$i18nt.t('Edb.CalculatesAll.select_date'):"根据日期选择指标值", key: "choose-target" },

+ 995 - 0
src/views/datasheet_manage/components/BalanceAddChart.vue

@@ -0,0 +1,995 @@
+<template>
+  <div v-dialogDrag v-if="isShow">
+    <div class="balance-add-chart-wrap el-dialog">
+      <div class="header el-dialog__header">
+        <span>{{ $t("Chart.add_chart_btn") }}</span>
+        <i class="el-icon-close" @click="cancelHandle" />
+      </div>
+      <div class="dialog-main">
+        <el-form
+          label-position="left"
+          hide-required-asterisk
+          label-width="80px"
+          :model="formData"
+          :rules="formRules"
+          inline
+        >
+          <div class="item-tr">
+            <!-- 图表名称 -->
+            <el-form-item
+              :label="$t('Chart.Detail.chart_name')"
+              prop="chartName"
+            >
+              <el-input
+                v-model="formData.chartName"
+                :placeholder="$t('Dialog.require_vaild')"
+                style="width: 200px"
+              ></el-input>
+            </el-form-item>
+            <!-- 数据来源 -->
+            <el-form-item :label="$t('Edb.Detail.source')" prop="chartSource">
+              <el-input
+                v-model="formData.chartSource"
+                :placeholder="$t('OnlineExcelPage.chart_source_placehoder')"
+                style="width: 150px"
+              ></el-input>
+              <el-switch
+                style="display: inline-block"
+                v-model="formData.showChartSource"
+              >
+              </el-switch>
+            </el-form-item>
+          </div>
+          <div class="item-tr">
+            <!-- 图表类型 -->
+            <el-form-item :label="$t('SystemManage.ChartSet.label01')" prop="chartType">
+              <el-select v-model="formData.chartType" style="width: 200px" @change="handleChartTypeChange">
+                <el-option
+                  :label="item.label"
+                  :value="item.key"
+                  v-for="item in chartTypeOpts"
+                  :key="item.key"
+                ></el-option>
+              </el-select>
+            </el-form-item>
+            <!--  上下限 -->
+            <el-form-item v-if="formData.chartType == 1">
+              <span
+                style="display: inline-block; margin-right: 20px"
+                v-if="hasLeftAxis"
+              >
+                <span>
+                  <!-- 左轴上下限 -->
+                  {{$t('OnlineExcelPage.left_limit')}}</span>
+                <el-input
+                  class="number-input"
+                  size="mini"
+                  type="number"
+                  style="width: 60px"
+                  v-model="formData.leftMin"
+                ></el-input>
+                <span>{{$t('Common.to')}}</span>
+                <el-input
+                  class="number-input"
+                  size="mini"
+                  type="number"
+                  style="width: 60px"
+                  v-model="formData.leftMax"
+                ></el-input>
+              </span>
+              <span
+                style="display: inline-block; margin-right: 20px"
+                v-if="hasRightAxis"
+              >
+                <span>
+                  <!-- 右轴上下限 -->
+                  {{$t('OnlineExcelPage.right_limit')}}
+                </span>
+                <el-input
+                  class="number-input"
+                  size="mini"
+                  type="number"
+                  style="width: 60px"
+                  v-model="formData.rightMin"
+                ></el-input>
+                <span>{{$t('Common.to')}}</span>
+                <el-input
+                  class="number-input"
+                  size="mini"
+                  type="number"
+                  style="width: 60px"
+                  v-model="formData.rightMax"
+                ></el-input>
+              </span>
+              <span
+                style="display: inline-block; margin-right: 20px"
+                v-if="hasRightTwoAxis"
+              >
+                <span>
+                  <!-- 右二轴上下限 -->
+                  {{$t('OnlineExcelPage.right_two_limit')}}
+                </span>
+                <el-input
+                  class="number-input"
+                  size="mini"
+                  type="number"
+                  style="width: 60px"
+                  v-model="formData.rightTwoMin"
+                ></el-input>
+                <span>{{$t('Common.to')}}</span>
+                <el-input
+                  class="number-input"
+                  size="mini"
+                  type="number"
+                  style="width: 60px"
+                  v-model="formData.rightTwoMax"
+                ></el-input>
+              </span>
+            </el-form-item>
+            <el-form-item v-if="formData.chartType == 2">
+              <span style="display: inline-block; margin-right: 20px">
+                <span>
+                  <!-- 纵轴上下限 -->
+                  {{$t('OnlineExcelPage.y_limit')}}
+                </span>
+                <el-input
+                  class="number-input"
+                  size="mini"
+                  type="number"
+                  style="width: 60px"
+                  v-model="formData.leftMin"
+                ></el-input>
+                <span>{{$t('Common.to')}}</span>
+                <el-input
+                  class="number-input"
+                  size="mini"
+                  type="number"
+                  style="width: 60px"
+                  v-model="formData.leftMax"
+                ></el-input>
+              </span>
+            </el-form-item>
+            <el-form-item v-if="formData.chartType == 4">
+              <span
+                style="display: inline-block; margin-right: 20px"
+                v-if="edbList[0].axis===1"
+              >
+                <span>
+                  <!-- 纵轴上下限 -->
+                  {{$t('OnlineExcelPage.y_limit')}}</span>
+                <el-input
+                  class="number-input"
+                  size="mini"
+                  type="number"
+                  style="width: 60px"
+                  v-model="formData.leftMin"
+                ></el-input>
+                <span>{{$t('Common.to')}}</span>
+                <el-input
+                  class="number-input"
+                  size="mini"
+                  type="number"
+                  style="width: 60px"
+                  v-model="formData.leftMax"
+                ></el-input>
+              </span>
+              <span
+                style="display: inline-block; margin-right: 20px"
+                v-if="edbList[0].axis===0"
+              >
+                <span>
+                  <!-- 纵轴上下限 -->
+                  {{$t('OnlineExcelPage.y_limit')}}
+                </span>
+                <el-input
+                  class="number-input"
+                  size="mini"
+                  type="number"
+                  style="width: 60px"
+                  v-model="formData.rightMin"
+                ></el-input>
+                <span>{{$t('Common.to')}}</span>
+                <el-input
+                  class="number-input"
+                  size="mini"
+                  type="number"
+                  style="width: 60px"
+                  v-model="formData.rightMax"
+                ></el-input>
+              </span>
+            </el-form-item>
+          </div>
+          <!-- 指标模块 -->
+          <div class="item-tr" v-for="(item, index) in edbList" :key="item.tag">
+            <img
+              @click="handleDelEdb(index)"
+              v-if="edbList.length > 1"
+              src="~@/assets/img/icons/delete-red.png"
+              style="width: 16px; position: relative; top: 3px; cursor: pointer"
+              alt=""
+            />
+            <span class="edb-tag-box">{{$t('Edb.eta_name')}}{{ item.tag }}</span>
+            <el-form-item :label="$t('OnlineExcelPage.time_serial')" label-width="70px">
+              <el-input
+                :class="{'select_input': selectInput===item.tag+'_timeSerial'}"
+                v-model="item.timeSerial"
+                :placeholder="$t('CustomAnalysisPage.select_date_sequence')"
+                style="width: 150px"
+                @focus="handleChooseInput(item.tag+'_timeSerial')"
+              ></el-input>
+            </el-form-item>
+            <el-form-item :label="$t('OnlineExcelPage.value_serial')" label-width="70px">
+              <el-input
+                :class="{'select_input': selectInput===item.tag+'_valueSerial'}"
+                v-model="item.valueSerial"
+                :placeholder="$t('CustomAnalysisPage.select_date_numerical')"
+                style="width: 150px"
+                @focus="handleChooseInput(item.tag+'_valueSerial')"
+                @change="handleValInputChange"
+              ></el-input>
+            </el-form-item>
+            <el-form-item :label="$t('Table.edb_name')" label-width="70px">
+              <el-input
+                v-model="item.name"
+                :placeholder="$t('Edb.InputHolderAll.input_name')"
+                style="width: 120px"
+              ></el-input>
+            </el-form-item>
+            <el-form-item :label="$t('Table.unit')" label-width="40px">
+              <el-input
+                v-model="item.unit"
+                :placeholder="$t('Edb.InputHolderAll.input_unit')"
+                style="width: 90px"
+              ></el-input>
+            </el-form-item>
+            <div
+              style="
+                display: flex;
+                align-items: center;
+                justify-content: center;
+                gap: 0 40px;
+                margin-bottom: 20px;
+              "
+              v-if="formData.chartType !== 2"
+            > 
+              <!-- 堆积柱状图只有第一个指标有设置左右轴和逆序功能 -->
+              <template v-if="!(formData.chartType ===4&&index>0)">
+              <el-radio-group v-model="item.axis" size="mini" @change="handleAxisChange">
+                <el-radio-button :label="1">{{
+                  $t("Chart.Detail.l_axis")
+                }}</el-radio-button>
+                <el-radio-button :label="0">{{
+                  $t("Chart.Detail.r_axis")
+                }}</el-radio-button>
+                <el-radio-button
+                  :label="2"
+                  :disabled="
+                    !hasRightAxis ||
+                    (item.axis === 0 &&
+                      edbList.filter((_) => _.axis === 0).length === 1)
+                  "
+                  >{{ $t("Chart.Detail.rtwo_axis") }}</el-radio-button
+                >
+              </el-radio-group>
+              <!-- 逆序 -->
+              <el-checkbox v-model="item.IsOrder">{{
+                $t("Chart.Detail.re_order")
+              }}</el-checkbox>
+              </template>
+              <el-radio-group v-model="item.EdbInfoType" size="mini">
+                <!-- 标准指标 -->
+                <el-radio :label="1">{{
+                  $t("Chart.Detail.stand_lead")
+                }}</el-radio>
+                <!-- 领先指标 -->
+                <el-radio :label="0">{{
+                  $t("Chart.Detail.leading_lead")
+                }}</el-radio>
+              </el-radio-group>
+              <span v-if="item.EdbInfoType === 0">
+                <span><!-- 领先 -->{{ $t("EtaChartAddPage.label_lead") }}</span>
+                <el-input
+                  class="number-input"
+                  size="mini"
+                  type="number"
+                  min="0"
+                  style="width: 60px"
+                  v-model="item.leadVal"
+                  @keyup.native="filterCode(item)"
+                ></el-input>
+                <el-select
+                  v-model="item.leadUnit"
+                  style="width: 60px"
+                  placeholder=""
+                  size="mini"
+                >
+                  <el-option
+                    v-for="item in fre_options"
+                    :key="item"
+                    :label="item"
+                    :value="item"
+                  >
+                  </el-option>
+                </el-select>
+              </span>
+            </div>
+          </div>
+          <!-- 季节图配置 -->
+          <div class="item-tr" style="display: flex;align-items:center;justify-content:center" v-if="formData.chartType === 2">
+            <div class="xaxis-range-tip">
+              {{ $t("EtaChartAddPage.label_xserie_range")
+              }}<!-- 横坐标显示范围 -->
+              <!-- <el-tooltip>
+                <div
+                  slot="content"
+                  v-html="$t('EtaChartAddPage.xserie_range_tip')"
+                ></div>
+                <img
+                  src="~@/assets/img/icons/question_mark_black.png"
+                  style="height: 16px; cursor: pointer; margin-left: 6px"
+                />
+              </el-tooltip> -->
+            </div>
+            <el-date-picker
+              style="width: 100px;margin-left:30px"
+              v-model="SeasonExtraConfig.XStartDate"
+              value-format="MM-dd"
+              popper-class="x-range-picker-date"
+              format="MM-dd"
+              :placeholder="$t('Common.ph_time_start')"
+              :clearable="false"
+            ></el-date-picker>
+            <el-date-picker
+              style="width: 100px;margin-left:10px"
+              v-model="SeasonExtraConfig.XEndDate"
+              value-format="MM-dd"
+              popper-class="x-range-picker-date"
+              format="MM-dd"
+              :placeholder="$t('Common.ph_time_end')"
+              :clearable="false"
+            ></el-date-picker>
+            <!-- 跨年 -->
+            <el-checkbox
+              style="margin-left:20px;margin-right:30px"
+              :label="$t('EtaChartAddPage.label_cross_year')" 
+              v-model="SeasonExtraConfig.JumpYear" 
+              :disabled="SeasonExtraConfig.isSpanYearDisable"
+            ></el-checkbox>
+            <!-- 春节对齐 -->
+            <el-radio-group v-model="SeasonExtraConfig.type" size="mini">
+              <!-- 公历 -->
+              <el-radio-button label="公历">{{$t('Chart.calendar_gre')}}</el-radio-button>
+              <!-- 农历 -->
+              <el-radio-button label="农历">{{$t('Chart.calendar_lunar')}}</el-radio-button>
+            </el-radio-group>
+          </div>
+          <!-- 季节图设置图例名称按钮 -->
+          <div
+            class="add-edb-btn"
+            style="color: #0052d9; cursor: pointer"
+            v-if="formData.chartType === 2"
+            @click="handleShowEditLegend"
+          >
+            <span>{{$t('EtaChartAddPage.label_legend_set')}}<!-- 图例名称设置 --></span>
+						<img style="width:15px" src="~@/assets/img/icons/edit-blue.png" />
+          </div>
+
+          <!-- 添加指标按钮 -->
+          <div
+            class="add-edb-btn"
+            style="color: #0052d9; cursor: pointer;display:inline-block"
+            @click="handleAddEdb"
+            v-if="formData.chartType !== 2"
+          >
+            <!-- 添加指标 -->
+            {{$t('SteelChemicalPage.add_edb')}}
+          </div>
+        </el-form>
+      </div>
+      <div class="dia-bot">
+        <el-button type="primary" plain @click="cancelHandle">{{
+          $t("ETable.Btn.cancel_btn")
+        }}</el-button>
+        <el-button
+          type="primary"
+          style="margin-right: 20px"
+          @click="saveHandle"
+          >{{ $t("Dialog.confirm_btn") }}</el-button
+        >
+      </div>
+    </div>
+
+    <!-- 季节性 图例设置 -->
+		<LegendEditDia
+      :isEditLegend="legendEditDiaShow"
+			:legendList="SeasonExtraConfig.ChartLegend"
+      @cancel="legendEditDiaShow = false"
+      @saveLegend="saveLegend"
+    />
+  </div>
+</template>
+
+<script>
+import * as sheetInterface from "@/api/modules/sheetApi.js";
+import LegendEditDia from '@/views/dataEntry_manage/components/LegendEditDia.vue';
+import { generateSeriesArray } from '@/views/dataEntry_manage/databaseComponents/util'
+import {etaBaseConfigInterence} from '@/api/modules/etaBaseConfigApi.js';
+const tag_arr = generateSeriesArray();
+const MAX_ADD_NUM = 30//添加指标最大数量
+export default {
+  components:{LegendEditDia},
+  props: {
+    isShow: {
+      type: Boolean,
+    },
+    ExcelInfoId:0
+  },
+  watch: {
+    'formData.chartType':{
+      handler(newVal,oldVal){
+        if(newVal===2&&this.edbList.length>1){
+          this.formData.chartType = oldVal;
+					return this.$message.warning(/* '您选择的图表样式为季节性图表,只支持单指标画图' */this.$t('Chart.OptMsg.season_one_msg'));
+        }
+      }
+    }
+  },
+  computed: {
+    hasLeftAxis() {
+      return this.edbList.some(item => item.axis === 1)
+    },
+    hasRightAxis() {
+      return this.edbList.some(item => item.axis === 0)
+    },
+    hasRightTwoAxis() {
+      return this.edbList.some(item => item.axis === 2)
+    },
+  },
+  data() {
+    return {
+      fre_options: ['年', '季', '月', '周', '天'], //领先指标频度配置
+      chartTypeOpts: [
+        { label: /* '曲线图' */this.$t('Chart.ChartType.spline_name'), key: 1 },
+        { label: /* '季节性图' */this.$t('Chart.ChartType.season_name'), key: 2 },
+        { label: /* '堆积柱状图' */this.$t('Chart.ChartType.stack_column_name'), key: 4 },
+      ],
+      formData: {
+        chartName: '',
+        chartSource: '平衡表',
+        showChartSource: false,
+        chartType: 1,
+        leftMin: 0,
+        leftMax: 0,
+        rightMin: 0,
+        rightMax: 0,
+        rightTwoMin: 0,
+        rightTwoMax: 0,
+      },
+      // 季节性图和额外配置
+			SeasonExtraConfig:{
+				ChartLegend:[], // 图例名称数组
+				XStartDate:"01-01", // 横坐标显示范围 - 开始
+				XEndDate:"12-31", // 横坐标显示范围-结束
+				JumpYear:false, //是否跨年
+        isSpanYearDisable:false,
+        type:'公历',
+			},
+      legendEditDiaShow:false,
+
+      formRules: {},
+
+      edbList: [],//sheet1!$A$3:$A$13
+      selectInput:'',
+
+      editChartInfoId:0,//编辑时的图表id
+
+      commonShowChartSource:false,//是否显示图表来源的公共配置
+    }
+  },
+  created() {
+    this.edbList.push(this.createEbdListItem('A'))
+    this.getChartCommonConfig()
+  },
+  methods: {
+    // 季节图点击编辑图例
+    async handleShowEditLegend(){
+      // 如果没有选择指标数据
+      if(!(this.edbList[0].timeSerial&&this.edbList[0].valueSerial)){
+        this.legendEditDiaShow=true
+        return
+      }
+      // 获取当前选择的 时间序列和数值序列的值
+      const dateObj=this.getSeriesNum(this.edbList[0].timeSerial)
+      const valueObj=this.getSeriesNum(this.edbList[0].valueSerial)
+      const dateArr=this.findLimitData(dateObj.start,dateObj.end).valueArr
+      const valueArr=this.findLimitData(valueObj.start,valueObj.end).valueArr
+      const params={
+        DateArr:dateArr,
+        DataArr:valueArr,
+        Calendar:this.SeasonExtraConfig.type,
+        SeasonExtraConfig:{
+          ChartLegend:this.SeasonExtraConfig.ChartLegend,// 图例名称数组
+          XStartDate:this.SeasonExtraConfig.XStartDate,
+          XEndDate:this.SeasonExtraConfig.XEndDate,
+          JumpYear:this.SeasonExtraConfig.JumpYear?1:0
+        }
+      }
+      console.log(params);
+      const res=await sheetInterface.balanceSeasonChart(params)
+      if(res.Ret===200){
+        const arr=res.Data.List||[]
+        const temarr=arr.map(item=>{
+          return {Name:item.Years,Value:item.ChartLegend}
+        })
+        this.SeasonExtraConfig.ChartLegend=this.SeasonExtraConfig.type==='公历'?temarr:temarr.filter((item,index)=>index>0)
+        this.legendEditDiaShow=true
+      }
+      
+    },
+
+    // 编辑时初始化数据
+    initEditData(e){
+      console.log('edit回显数据',e);
+      const {ChartInfo,EdbInfoList,ExcelEdbList}=e
+      this.editChartInfoId=ChartInfo.ChartInfoId
+      this.formData.chartName=ChartInfo.ChartName
+      this.formData.chartSource=JSON.parse(ChartInfo.SourcesFrom).text
+      this.formData.showChartSource=JSON.parse(ChartInfo.SourcesFrom).isShow
+      this.formData.chartType=ChartInfo.ChartType
+      this.formData.leftMin=ChartInfo.LeftMin?Number(ChartInfo.LeftMin):0
+      this.formData.leftMax=ChartInfo.LeftMax?Number(ChartInfo.LeftMax):0
+      this.formData.rightMin=ChartInfo.RightMin?Number(ChartInfo.RightMin):0
+      this.formData.rightMax=ChartInfo.RightMax?Number(ChartInfo.RightMax):0
+      this.formData.rightTwoMin=ChartInfo.Right2Min?Number(ChartInfo.Right2Min):0
+      this.formData.rightTwoMax=ChartInfo.Right2Max?Number(ChartInfo.Right2Max):0
+      if(ChartInfo.ChartType===2&&ChartInfo.SeasonExtraConfig){
+        this.SeasonExtraConfig.ChartLegend=JSON.parse(ChartInfo.SeasonExtraConfig).ChartLegend
+        this.SeasonExtraConfig.XStartDate=JSON.parse(ChartInfo.SeasonExtraConfig).XStartDate
+        this.SeasonExtraConfig.XEndDate=JSON.parse(ChartInfo.SeasonExtraConfig).XEndDate
+        this.SeasonExtraConfig.JumpYear=JSON.parse(ChartInfo.SeasonExtraConfig).JumpYear?true:false
+        this.SeasonExtraConfig.type=ChartInfo.Calendar
+      }
+
+      // 回显
+      const arr=EdbInfoList||[]
+      let temEdbList=[]
+      arr.forEach((item,index)=>{
+        temEdbList.push({
+          tag: ExcelEdbList[index].FromTag,
+          ExcelChartEdbId:item.EdbInfoId,
+          timeSerial: ExcelEdbList[index].DateSequenceStr,
+          valueSerial: ExcelEdbList[index].DataSequenceStr,
+          maxData:item.MaxData,//选中数据的最大值
+          minData:item.MinData,//选中数据的最小值
+          name: item.EdbAliasName,
+          unit:item.Unit,
+          axis: item.IsAxis,//哪个轴 1左轴 0右轴 2右二轴
+          EdbInfoType: item.EdbInfoType,//指标类型 1标准指标 0领先指标
+          leadVal: item.LeadValue,//领先值
+          leadUnit: item.LeadUnit,//领先单位 
+          IsOrder: item.IsOrder,//是否逆序
+        })
+      })
+
+      this.edbList=temEdbList
+      
+
+    },
+
+    // 点击选中哪个指标的时间\数值序列
+    handleChooseInput(e){
+      this.selectInput=e
+    },
+
+    // 指标轴改变
+    handleAxisChange(){
+      this.updateLimit()
+    },
+
+    // 通过字符串sheet1!$A$3:$A$13 获取开始和结束序列号
+    getSeriesNum(str){
+      // 正则表达式模式,确保格式正确且感叹号后面有两个$,冒号前后各两个$
+      const formatPattern = /^.*!\$[A-Z0-9]+\$[A-Z0-9]+:\$[A-Z0-9]+\$[A-Z0-9]/;
+      // 检查字符串是否符合格式要求
+      if (formatPattern.test(str)) {
+          // 正则表达式模式,用于提取美元符号后的值
+          let extractPattern = /\$([A-Z0-9]+)/g;
+
+          // 存储匹配结果的数组
+          let matches = [];
+          let match;
+
+          // 使用正则表达式的exec方法来找到所有匹配
+          while ((match = extractPattern.exec(str)) !== null) {
+              // 将匹配的字符数字转换为数字类型并存储
+              let value = match[1];
+              if (!isNaN(value)) {
+                  matches.push(Number(value));
+              } else {
+                  matches.push(value); // 保留非数字值(如字母)
+              }
+          }
+
+          // 获取出开始和结束单元格序号
+          let start={
+            col:0,
+            row:0
+          },
+          end={
+            col:0,
+            row:0
+          };
+          start.col=this.$parent.columnHeader.findIndex(_e=>_e===matches[0])
+          start.row=matches[1]-1
+          end.col=this.$parent.columnHeader.findIndex(_e=>_e===matches[2])
+          end.row=matches[3]-1
+
+          return {
+            start,
+            end
+          }
+
+      } else {
+          console.log("字符串格式不符合要求");
+          this.$message.warning('格式不合法')
+          return false
+      }
+    },
+
+    // 手动输入数值序列改变
+    handleValInputChange(str){
+      console.log('数值序列改变',str);
+      const obj=this.getSeriesNum(str)
+      if(!obj) return
+      this.tableSelect(obj.start,obj.end,str)
+    },
+
+    // 选中的序列
+    tableSelect(start,end,str){
+      console.log(start,end,str);
+      if(this.selectInput){
+
+        //查找到是哪个指标
+        const tag=this.selectInput.split('_')[0]
+        const type=this.selectInput.split('_')[1]
+        this.edbList.forEach(edb => {
+          if(edb.tag===tag){
+            if(type==='timeSerial'){
+              edb.timeSerial=str
+            }
+            if(type==='valueSerial'){
+              edb.valueSerial=str
+              edb.maxData=this.findLimitData(start,end).maxData
+              edb.minData=this.findLimitData(start,end).minData
+              this.updateLimit()
+            }
+          }
+        });
+      }
+    },
+
+    // 根据选择的数据更新上下限
+    updateLimit(){
+      let leftArr=[],rightArr=[],rightTwoArr=[];
+      this.edbList.forEach(item=>{
+        if(item.axis===1){
+          leftArr.push(...[item.minData,item.maxData])
+        }
+        if(item.axis===0){
+          rightArr.push(...[item.minData,item.maxData])
+        }
+        if(item.axis===2){
+          rightTwoArr.push(...[item.minData,item.maxData])
+        }
+      })
+      this.formData.leftMin=leftArr.length?Math.min(...leftArr):0
+      this.formData.leftMax=leftArr.length?Math.max(...leftArr):0
+      this.formData.rightMin=rightArr.length? Math.min(...rightArr):0
+      this.formData.rightMax=rightArr.length? Math.max(...rightArr):0
+      this.formData.rightTwoMin=rightTwoArr.length? Math.min(...rightTwoArr):0
+      this.formData.rightTwoMax=rightTwoArr.length? Math.max(...rightTwoArr):0
+    },
+
+    // 找出选择的最大最小值
+    findLimitData(start,end){
+      let minData=0,maxData=0;
+      const data=this.$parent.config.data
+      // console.log(data);
+      let numArr=[]
+      // 判断是选择的同行还是同列
+      if(start.col===end.col&&start.row!=end.row){//同列
+        for (let index = start.row; index <= end.row; index++) {
+         numArr.push(data[index][start.col].ShowValue)
+        }
+      }
+      if(start.col!=end.col&&start.row==end.row){//同行
+        const rowData=data[start.row]
+        for (let index = start.col; index <= end.col; index++) {
+          numArr.push(rowData[index].ShowValue)
+        }
+      }
+      //只选择了一个单元格
+      if(start.row===end.row&&start.col===end.col){
+        numArr.push(data[start.row][start.col].ShowValue)
+      }
+
+      const valueArr=JSON.parse(JSON.stringify(numArr))
+
+      numArr=[...new Set(numArr)]
+      numArr=numArr.filter(item=>!isNaN(item)).map(Number)
+      
+      if(numArr.length!==0){
+        maxData=Math.max(...numArr)
+        minData=Math.min(...numArr)
+      }
+
+      // console.log(numArr);
+      // console.log(minData,maxData);
+      return{
+        valueArr,
+        maxData,
+        minData
+      }
+    },
+
+    // 图例编辑接口保存
+		saveLegend(copyList){
+			if(copyList && copyList.length>0){
+				this.SeasonExtraConfig.ChartLegend = copyList
+				this.legendEditDiaShow=false
+			}
+		},
+
+    // 图表类型切换
+    handleChartTypeChange(){
+      this.edbList.forEach(item=>{
+        item.axis=1
+      })
+    },
+
+    //添加指标
+    handleAddEdb() {
+      if (this.edbList.length === MAX_ADD_NUM) {
+        this.$message.warning(this.$t('EtaBasePage.num_overrun_msg'))
+        return
+      }
+      const t = this.edbList[this.edbList.length - 1].tag
+      const index = tag_arr.findIndex(item => item === t);
+      const obj = this.createEbdListItem(tag_arr[index + 1])
+      this.edbList.push(obj)
+
+    },
+    createEbdListItem(t) {
+      return {
+        tag: t,
+        ExcelChartEdbId:0,
+        timeSerial: '',
+        valueSerial: '',
+        maxData:0,//选中数据的最大值
+        minData:0,//选中数据的最小值
+        name: '',
+        unit:'',
+        axis: 1,//哪个轴 1左轴 0右轴 2右二轴
+        EdbInfoType: 1,//指标类型 1标准指标 0领先指标
+        leadVal: 0,//领先值
+        leadUnit: '',//领先单位 
+        IsOrder: false,//是否逆序
+      }
+    },
+
+    handleDelEdb(index) {
+      this.edbList.splice(index, 1)
+    },
+    // 初始化表单
+    initData() {
+      this.editChartInfoId=0
+      this.formData={
+        chartName: '',
+        chartSource: '平衡表',
+        showChartSource: this.commonShowChartSource|| false,
+        chartType: 1,
+        leftMin: 0,
+        leftMax: 0,
+        rightMin: 0,
+        rightMax: 0,
+        rightTwoMin: 0,
+        rightTwoMax: 0,
+      }
+      this.SeasonExtraConfig={
+        ChartLegend:[], // 图例名称数组
+				XStartDate:"01-01", // 横坐标显示范围 - 开始
+				XEndDate:"12-31", // 横坐标显示范围-结束
+				JumpYear:false, //是否跨年
+        isSpanYearDisable:false,
+        type:'公历',
+      }
+      this.edbList=[]
+      this.selectInput=''
+      this.edbList.push(this.createEbdListItem('A'))
+    },
+    async saveHandle() { 
+      const params={
+        ExcelInfoId:this.ExcelInfoId,
+        ChartInfoId:this.editChartInfoId||0,
+        ChartEdbInfoList:[],
+        ChartName:this.formData.chartName,
+        ChartType:this.formData.chartType,
+        SourcesFrom:JSON.stringify({
+          text:this.formData.chartSource,
+          isShow:this.formData.showChartSource
+        }),
+        LeftMin:`${this.formData.leftMin}`,
+        LeftMax:`${this.formData.leftMax}`,
+        RightMin:`${this.formData.rightMin}`,
+        RightMax:`${this.formData.rightMax}`,
+        Right2Min:`${this.formData.rightTwoMin}`,
+        Right2Max:`${this.formData.rightTwoMax}`,
+        MinMaxSave:1,
+        Source:11
+      }
+
+      // 季节图横坐标范围必须有
+      if(params.ChartType===2){
+        params.SeasonExtraConfig={
+          ChartLegend:this.SeasonExtraConfig.ChartLegend,// 图例名称数组
+          XStartDate:this.SeasonExtraConfig.XStartDate,
+          XEndDate:this.SeasonExtraConfig.XEndDate,
+          JumpYear:this.SeasonExtraConfig.JumpYear?1:0
+        }
+        params.Calendar=this.SeasonExtraConfig.type
+
+        //季节图横坐标范围必须有
+        if(!(params.SeasonExtraConfig.XStartDate&&params.SeasonExtraConfig.XEndDate)){
+          this.$message.warning('横坐标显示范围不能为空');
+          return
+        }
+
+      }
+      if(!params.ChartName){
+        this.$message.warning('请填写图表名称')
+        return
+      }
+
+      // 处理指标数据
+      let arr=[]
+      this.edbList.forEach(item=>{
+        arr.push({
+          FromTag:item.tag,
+          ExcelChartEdbId:item.ExcelChartEdbId,
+          EdbName:item.name,
+          Unit:item.unit,
+          IsAxis:item.axis,
+          IsOrder:item.IsOrder,
+          EdbInfoType:item.EdbInfoType,
+          LeadUnit:item.leadUnit,
+          LeadValue:Number(item.leadVal),
+          MaxData:item.maxData,
+          MinData:item.minData,
+          DateSequenceStr:item.timeSerial,
+          DataSequenceStr:item.valueSerial
+        })
+      })
+      params.ChartEdbInfoList=arr
+      // 检测选择的指标名称是否填写了
+      for (let index = 0; index < params.ChartEdbInfoList.length; index++) {
+        const item = params.ChartEdbInfoList[index];
+        if(!item.EdbName) return this.$message.warning(`第${index+1}个指标名称未填写`)
+      }
+
+      const res=this.editChartInfoId?await sheetInterface.editBalanceChart(params):await sheetInterface.addBalanceChart(params)
+      if(res.Ret===200){
+        this.$message.success(this.$t('MsgPrompt.add_msg2'));
+        this.initData()
+        this.$emit('success')
+      }
+    },
+    cancelHandle() {
+      this.$emit('update:isShow', false);
+      this.initData()
+    },
+
+    /* 领先指标 过滤负数 小数点*/
+    filterCode(item) {
+      item.leadVal = item.leadVal.replace(/[^\.\d]/g, '').replace('.', '');
+    },
+
+    // 获取图表公共的是否显示来源配置
+    async getChartCommonConfig(){
+      const res = await etaBaseConfigInterence.getBaseConfig()
+      if(res.Ret===200){
+        this.commonShowChartSource=res.Data.ChartSourceDisplay=='true'?true:false
+        this.formData.showChartSource=this.commonShowChartSource
+      }
+    }
+    
+
+  }
+}
+</script>
+
+<style lang="scss">
+.balance-add-chart-wrap {
+  .number-input {
+    input {
+      padding: 0;
+    }
+  }
+  .select_input .el-input__inner {
+       border: 2px dashed #18ad18;
+      border-radius: 4px;
+    }
+}
+    /*他不要下拉选择框 QAQ */
+.x-range-picker-date {
+	display: none;
+}
+.dia-bot{
+  text-align: center;
+}
+</style>
+<style lang="scss" scoped>
+@import "~@/styles/theme-vars.scss";
+.balance-add-chart-wrap {
+  width: 985px;
+  background: #fff;
+  position: fixed;
+  top: 20%;
+  // left: 50%;
+  right: 10%;
+  border-radius: 2px;
+  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
+  z-index: 999;
+  overflow: hidden;
+  .el-input {
+    width: 100%;
+  }
+  .number-input {
+    input {
+      padding: 0;
+    }
+  }
+  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;
+    }
+  }
+  .dia-bot {
+    padding-bottom: 40px;
+    display: flex;
+    justify-content: center;
+  }
+  .dialog-main {
+    padding: 25px;
+    max-height: 600px;
+    overflow-y: auto;
+    .item-tr {
+      .edb-tag-box {
+        display: inline-block;
+        line-height: 40px;
+        width: 80px;
+      }
+    }
+
+    @media screen and (max-height: 850px) {
+      box-sizing: border-box;
+      height: 65vh;
+      overflow-y: auto;
+    }
+    .el-cascader .el-input {
+      width: 340px;
+    }
+  }
+}
+
+</style>

+ 160 - 0
src/views/datasheet_manage/components/BalanceSheetChartItem.vue

@@ -0,0 +1,160 @@
+<template>
+    <div class="chart-item-wrap">
+        <div class="chart-item-box">
+            <div style="text-align:center">{{chartInfo.ChartName}}</div>
+            <Chart 
+                :options="options" 
+                :chartInfo="chartInfo" 
+                :index="chartInfo.ChartInfoId"
+                height="330px"
+                ref="chartRef"
+            />
+        </div>
+        <div class="opt-box">
+            <span v-if="JSON.parse(chartInfo.SourcesFrom).isShow">{{$t('Chart.Detail.source')}}:{{ JSON.parse(chartInfo.SourcesFrom).text}}</span>
+            <span></span>
+            <div>
+                <!-- 加入我的图库 -->
+                <span class="btn-o" @click="handleAddMyChart" v-if="!isStaticTable">{{$t('Chart.chart_addmy_btn')}}</span>
+                <!-- 编辑 -->
+                <span class="btn-o" v-if="!disabled" @click="handleEditChart">{{$t('Chart.chart_edit_btn')}}</span>
+                <!-- 删除 -->
+                <span class="btn-o" v-if="!disabled" style="color:#f00" @click="handleDelChart">{{$t('Chart.chart_del_btn')}}</span>
+            </div>
+        </div>
+
+        <!-- 加入我的图库弹窗 -->
+        <addMyClassifyDia
+            :isAddMyDialog="isAddMyChart"
+            :add_id="add_chart_id"
+            :add_ids="add_ids"
+            @cancel="isAddMyChart = false"
+            @addSuccess="addMySuccess"
+        />
+    </div>
+</template>
+
+<script>
+import { dataBaseInterface } from '@/api/api.js';
+import { chartSetMixin } from '@/views/dataEntry_manage/mixins/chartPublic'
+import Chart from '@/views/dataEntry_manage/components/chart';
+import addMyClassifyDia from '@/views/dataEntry_manage/components/addMyClassifyDia';
+export default {
+    components:{Chart,addMyClassifyDia},
+    props:{
+        chartData:{},
+        disabled: { //是否只预览
+            type: Boolean,
+            default: false,
+        },
+        isStaticTable:{
+            type: Boolean,
+            default: false,
+        }
+    },
+    mixins: [chartSetMixin],
+    watch: {
+        chartData:{
+            handler(nval){
+                console.log('图表数据',nval);
+                this.initData(nval)
+            },
+            deep:true,
+            immediate:true
+        }
+    },
+    data() {
+        return {
+            chartInfo: {}, //图表信息
+
+            isAddMyChart:false,//加入图库弹窗
+            add_chart_id: 0, //要加入的图表
+            add_ids:[],//加入时已有的分类
+        }
+    },
+    methods: {
+        initData(data){
+            this.chartInfo=data.ChartInfo
+            this.tableData=data.EdbInfoList
+            this.calendar_type=data.ChartInfo.Calendar
+            //初始化上下限
+            this.setLimitData(this.tableData)
+            this.tableData.length&&this.setChartOptionHandle(this.tableData)
+        },
+
+        // 编辑图表
+        handleEditChart(){
+            this.$emit('edit',this.chartData)
+        },
+
+        handleDelChart(){
+            this.$confirm(this.$t('ETable.Msg.is_del_balance_chart_msg') , this.$t('Confirm.prompt') , {
+                confirmButtonText:  this.$t('Dialog.confirm_btn'),
+                cancelButtonText: this.$t('Dialog.cancel_btn'),
+                type: "warning",
+            }).then(() => {
+                this.$emit('delete',this.chartData)
+            }).catch(() => {});
+            
+        },
+
+        /* 加入我的图库成功 */
+        addMySuccess(params){
+            this.isAddMyChart = false;
+            this.chartInfo.IsAdd = true;
+            this.chartInfo.MyChartId = params.MyChartInfoId;
+            this.chartInfo.MyChartClassifyId = params.MyChartClassifyId
+
+            // 如果没有图表图片则生成一次
+            if(!this.chartInfo.ChartImage) {
+                this.getChartImg()
+            }
+        },
+        async getChartImg(){
+            let svg = this.$refs.chartRef.chart.getSVG({
+                chart: {
+                width: 340,
+                height: 230,
+                }
+            });
+            let form = new FormData();
+            form.append('Img', svg);
+            let { Data } = await dataBaseInterface.uploadImgSvg(form);
+
+            await dataBaseInterface.setChartImage({
+                ChartInfoId: this.chartInfo.ChartInfoId,
+                ImageUrl: Data.ResourceUrl,
+            });
+        },
+
+        handleAddMyChart(){
+            this.add_chart_id = this.chartInfo.ChartInfoId;
+            //已有的分类ids
+            this.add_ids = this.chartInfo.MyChartClassifyId ? this.chartInfo.MyChartClassifyId.split(',').map(item => Number(item)) : [];
+            this.isAddMyChart = true;
+        }
+    },
+}
+</script>
+
+<style lang="scss" scoped>
+.chart-item-wrap{
+    margin-bottom: 20px;
+    .chart-item-box{
+        padding: 10px;
+        border: 1px solid #C8CDD9;
+        border-radius: 8px;
+    }
+    .opt-box{
+        margin-top: 5px;
+        display: flex;
+        justify-content: space-between;
+        .btn-o{
+            display: inline-block;
+            margin-left: 5px;
+            cursor: pointer;
+            color: #0052D9;
+        }
+    }
+}
+</style>

+ 157 - 0
src/views/datasheet_manage/components/BalanceSheetList.vue

@@ -0,0 +1,157 @@
+<template>
+  <div style="flex: 1">
+    <div>{{$t('OnlineExcelPage.all_table_num',{count:total})}}</div>
+    <el-table border :data="list" height="calc(100vh - 150px)" ref="tableRef">
+      <el-table-column
+        v-for="item in tableColums"
+        :key="item.label"
+        :label="item.label"
+        :prop="item.key"
+        :width="item.width"
+        align="center"
+      >
+        <template slot-scope="{ row }">
+          <span v-if="item.key === 'ModifyTime'">{{
+            row.ModifyTime | getTime
+          }}</span>
+          <span v-else-if="item.key === 'ExcelName'" style="cursor: pointer;" @click="goDetail(row)">{{
+            row.ExcelName
+          }}</span>
+          <span v-else>{{ row[item.key] }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column
+        width="260"
+        align="center"
+        :label="$t('Table.column_operations')"
+      >
+        <template slot-scope="{ row }">
+          <span
+            class="editsty"
+            @click="itemHandle(row, 'edit')"
+            style="margin-right: 10px"
+            v-if="$parent.isSheetBtnShow('edit')&&row.Button.OpButton"
+            >{{row.CanEdit?$t("ETable.Btn.edit_btn"):row.Editor+$t('OnlineExcelPage.editing_msg')}}</span
+          >
+          <span
+            class="editsty"
+            @click="itemHandle(row, 'refresh')"
+            style="margin-right: 10px"
+            v-if="$parent.isSheetBtnShow('refresh')&&row.Button.RefreshButton"
+            >{{ $t("ETable.Btn.refresh_btn") }}</span
+          >
+          <span
+            class="editsty"
+            @click="itemHandle(row, 'save')"
+            style="margin-right: 10px"
+            v-if="$parent.isSheetBtnShow('otherSave')&&row.Button.CopyButton"
+            >{{ $t("ETable.Btn.save_as") }}</span
+          >
+          <span
+            class="editsty"
+            @click="itemHandle(row, 'download')"
+            style="margin-right: 10px"
+            v-if="$parent.isSheetBtnShow('download')&&row.HaveOperaAuth"
+            >{{ $t("ETable.Btn.download_btn") }}</span
+          >
+          <span
+            class="deletesty"
+            @click="itemHandle(row, 'del')"
+            style="margin-right: 10px"
+            v-if="$parent.isSheetBtnShow('del')&&row.Button.DeleteButton"
+            >{{ $t("Table.delete_btn") }}</span
+          >
+        </template>
+      </el-table-column>
+
+      <div slot="empty" style="padding: 50px 0 50px">
+        <tableNoData :text="$t('Confirm.prompt_slogan')" size="mini" />
+      </div>
+    </el-table>
+  </div>
+</template>
+
+<script>
+import * as sheetInterface from "@/api/modules/sheetApi.js";
+import BalanceTableMixin from '../mixins/balanceTableMixin'
+import moment from 'moment'
+export default {
+  mixins:[BalanceTableMixin],
+  props: {
+    total: {
+      type: Number
+    },
+    list: [],
+    finished: false,
+    loading: false
+  },
+  filters: {
+    getTime(e) {
+      return moment(e).format('YYYY-MM-DD HH:mm:ss')
+    }
+  },
+  computed: {
+    tableColums() {
+      return [
+        {
+          label: this.$t('ETable.BalanceSheetTable.name'),
+          key: 'ExcelName',
+        },
+        {
+          label: this.$t('ETable.BalanceSheetTable.creator'),
+          key: 'SysUserRealName',
+          width: '120px',
+        },
+        {
+          label: this.$t('ETable.BalanceSheetTable.updater'),
+          key: 'UpdateUserRealName',
+          width: '120px',
+        },
+        {
+          label: this.$t('ETable.BalanceSheetTable.update_time'),
+          key: 'ModifyTime',
+          width: '160px',
+        },
+      ]
+    }
+  },
+  data() {
+    return {
+      sheetRefreshing:false
+    }
+  },
+  mounted() {
+    this.$refs.tableRef.bodyWrapper.addEventListener('mousewheel', this.handleScroll)
+  },
+  beforeDestroy() {
+    this.$refs.tableRef.bodyWrapper.removeEventListener('mousewheel', this.handleScroll)
+  },
+  methods: {
+    //查看平衡表
+    goDetail(data){
+      this.$router.push({
+          path:'/viewBalanceSheet',
+          query:{
+            id:data.ExcelInfoId
+          }
+      })
+    },
+
+    handleScroll(event) {
+      const target = event.target;
+      //滚动方向
+      const scrollDirection = event.deltaY > 0 ? 'down' : 'up'
+      if (scrollDirection === 'up'||this.loading||this.finished) return
+      const dom = $('.el-table__body-wrapper')[0]
+      const { clientHeight, scrollTop, scrollHeight } = dom
+      // 计算是否到达底部
+      if (scrollHeight - (clientHeight + scrollTop) <= 200) {
+        this.$emit('loadMoreHandle')
+      }
+    },
+  },
+}
+</script>
+
+<style>
+</style>

+ 2083 - 0
src/views/datasheet_manage/components/BalanceTable.vue

@@ -0,0 +1,2083 @@
+<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">
+        <span style="flex-shrink: 0; color: #c0c4cc">{{
+          $t("OnlineExcelPage.formula_lable")
+        }}</span>
+        <el-input
+          v-if="selectCell && selectCell.DataType === 6"
+          v-model="selectCell.Value"
+          @change="updateValueByFormula"
+        />
+      </div>
+      <!-- startSelectTable?'text-select-disabled111':'' -->
+      <div class="table-content-wrap">
+        <div class="left-wrap">
+          <div style="padding:20px;background-color: #fff;" @mouseleave="endSelection">
+          <div class="table-wrap">
+            <table
+              width="auto"
+              border="0"
+              class="table"
+              :style="disabled ? 'width:100%' : ''"
+            >
+              <thead>
+                <tr>
+                  <!-- 行头 -->
+                  <th class="th-tg sm"></th>
+
+                  <!-- 列头 -->
+                  <th
+                    v-for="(item, index) in columnHeader"
+                    :key="index"
+                    class="th-tg th-col"
+                    :data-cindex="item"
+                    :data-rindex="-1"
+                    @contextmenu.prevent="rightClickHandle"
+                  >
+                    {{ item }}
+                  </th>
+                </tr>
+              </thead>
+
+              <tbody>
+                <tr v-for="(row, index) in config.data" :key="index">
+                  <!-- 行头 -->
+                  <th
+                    class="th-tg th-row sm"
+                    @contextmenu.prevent="rightClickHandle"
+                    :data-rindex="rowHeader[index]"
+                    :data-cindex="-1"
+                  >
+                    {{ rowHeader[index] }}
+                  </th>
+
+                  <td
+                    v-for="(cell, cell_index) in row"
+                    :key="`${index}_${cell_index}`"
+                    :data-rindex="rowHeader[index]"
+                    :data-cindex="columnHeader[cell_index]"
+                    :data-key="cell.Uid"
+                    @click="clickCell($event, cell)"
+                    @dblclick="dblClickCellHandle($event, cell)"
+                    @contextmenu.prevent="rightClickHandle($event, cell)"
+                    @mouseenter="getRelationEdbInfo(cell)"
+                    @copy="copyCellHandle($event, cell)"
+                    @paste="pasteCellHandle($event, cell)"
+
+                    @mousedown="startSelection(index, cell_index)"
+                    @mouseover="extendSelection(index, cell_index)"
+                    @mouseup="endSelection"
+                    :class="{ 
+                      'td_selected': isSelected(index, cell_index),
+                      'text-select-disabled':startSelectTable
+                    }"
+                  >
+                    <!-- 插入单元格禁止编辑 -->
+                    <!-- [4,5,6,7,8].includes(cell.DataType)&&!cell.CanEdit -->
+                    <template
+                      v-if="
+                        !cell.CanEdit ||
+                        disabled ||
+                        (cell.DataType === 1 &&
+                          [1, 2].includes(cell.DataTimeType))
+                      "
+                    >
+                      <!-- 单元格类型5 7显示指标浮窗 -->
+                      <el-popover
+                        v-if="[5, 7].includes(cell.DataType) && !disabled"
+                        placement="top-start"
+                        width="350"
+                        trigger="hover"
+                      >
+                        <ul>
+                          <li style="display: flex; margin: 10px">
+                            <label style="min-width: 80px">{{
+                              $t("OnlineExcelPage.indicator_name_lbl")
+                            }}</label>
+                            {{ cellrelationEdbInfo.EdbName }}
+                          </li>
+                          <li style="display: flex; margin: 10px">
+                            <label style="min-width: 80px">{{
+                              $t("OnlineExcelPage.lastest_date_lab")
+                            }}</label>
+                            {{ cellrelationEdbInfo.LatestDate }}
+                          </li>
+                          <li style="display: flex; margin: 10px">
+                            <label style="min-width: 80px">{{
+                              $t("Table.edb_id")
+                            }}</label>
+                            {{ cellrelationEdbInfo.EdbCode }}
+                          </li>
+                        </ul>
+                        <span
+                          slot="reference"
+                          :data-rindex="rowHeader[index]"
+                          :data-cindex="columnHeader[cell_index]"
+                          :data-key="cell.Uid"
+                          >{{
+                            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]"
+                        :data-key="cell.Uid"
+                        v-else
+                        >{{ cell.ShowValue }}</span
+                      >
+                    </template>
+
+                    <el-autocomplete
+                      v-else
+                      v-model="cell.Value"
+                      :ref="`inputRef${cell.Uid}`"
+                      popper-class="edb-select-popover"
+                      :data-key="cell.Uid"
+                      :data-rindex="rowHeader[index]"
+                      :data-cindex="columnHeader[cell_index]"
+                      :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"
+                          >
+                            <span class="edb-item-name text_oneLine">{{
+                              scope.item.EdbName
+                            }}</span>
+                            <i
+                              class="el-icon-check"
+                              style="color: #0052d9; font-size: 18px"
+                            />
+                          </div>
+
+                          <div slot="reference" v-else>
+                            {{ scope.item.EdbName }}
+                          </div>
+                        </edbDetailPopover>
+                      </template>
+                    </el-autocomplete>
+                  </td>
+                </tr>
+              </tbody>
+            </table>
+          </div>
+          </div>
+          <!-- 底部sheet -->
+          <div class="bot-sheet-box">
+            <ul class="sheet-list">
+              <div
+                class="sheet-item"
+                v-for="(item, index) in sheetOpts"
+                :key="item.ExcelInfoId"
+                @contextmenu.prevent="handleShowSheetDel(index)"
+                @mouseleave="item.showDel=false"
+              >
+                <div class="del-box" v-show="item.showDel" @click="delChildSheet">
+                  <span>{{$t('Table.delete_btn')}}</span>
+                </div>
+
+                <div
+                  :class="['el-button el-button--default el-button--mini box',activeSheetId===item.ExcelInfoId?'active':'']"
+                  size="mini"
+                  @dblclick="handleDbclickSheet(item)"
+                  @click="clickChangeSheet(item)"
+                >
+                  <span class="text" v-if="!item.isEdit">{{ item.ExcelName }}</span>
+                  <input
+                    ref="sheetInput"
+                    v-else
+                    class="input"
+                    type="text"
+                    v-model="temSheetInputVal"
+                    @blur="handleModifySheetName"
+                    @keyup.enter="handleModifySheetName"
+                  />
+                </div>
+              </div>
+
+              <el-button
+                size="mini"
+                icon="el-icon-plus"
+                @click="handleAddSheet"
+                v-if="!disabled&&sheetOpts.length < 10"
+              ></el-button>
+            </ul>
+            <el-button type="text" icon="el-icon-plus" @click="isShowAddChart=true" v-if="!disabled">{{$t('Chart.add_chart_btn')}}</el-button>
+          </div>
+        </div>
+        <!-- 图表模块 -->
+        <div class="right-wrap" v-if="chartList.length>0">
+          <div class="chart-list">
+            <BalanceSheetChartItem 
+              :chartData="item"
+              :disabled="disabled"
+              :isStaticTable="isStaticTable"
+              v-for="item in chartList" 
+              :key="item.ChartInfo.ChartInfoId"
+              @edit="handleEditChart"
+              @delete="handleDelChart"
+
+            />
+          </div>
+          
+        </div>
+      </div>
+
+      <!-- 右键菜单 -->
+      <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)"
+        >
+          <span v-if="!menu.children">{{ menu.label }}</span>
+
+          <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 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> -->
+        </div>
+      </div>
+    </template>
+
+    <div class="nodata" v-else>
+      <tableNoData :text="$t('Table.prompt_slogan')" />
+    </div>
+
+    <!-- 选择指标 -->
+    <selectTargetValueDia
+      :isShow.sync="isSelectTargetValueDialog"
+      :info="insertTargetValueInfo"
+      @insert="insertSelectData"
+      ref="selectTargetValueRef"
+    />
+
+    <!-- 插入系统/指标日期弹窗 -->
+    <insertDateDia
+      :isShow.sync="isInsertDateDialog"
+      :info="insertDateInfo"
+      @insert="insertDatehandle"
+    />
+
+    <!-- 指标计算弹窗 -->
+    <calculateEdbDia
+      ref="calculateEdbDiaRef"
+      :isShow.sync="isInsertCalculate"
+      :info="insertCalculateInfo"
+      @insert="insertCalculateData"
+    />
+
+    <!-- 日期计算弹窗 -->
+    <calculateDateDia
+      ref="calculateDateDiaRef"
+      :isShow.sync="isInsertCalculateDate"
+      :info="insertCalculateDateInfo"
+      @insert="insertCalculateDateValue"
+    />
+
+    <!-- 添加图表 -->
+    <BalanceAddChart
+      ref="balanceAddChart"
+      :isShow.sync="isShowAddChart"
+      :ExcelInfoId="activeSheetId"
+      @success="addChartSuccess"
+    />
+  </div>
+</template>
+<script>
+import {
+  getRowHeaderCode,
+  getColumnHeaderCode,
+  selectCellStyle,
+  selectMoreCellStyle,
+  setRelationStyle,
+  getRightClickMenu,
+  checkDateFormat,
+  setFocus,
+  findCellByKey,
+  resetRelationStyle,
+  resetDialogCellStyle,
+  extractFactorsFromFormula,
+  findCellByFactorMixed,
+  splitString,
+  toUpperCase,
+  findCellKeyByFactor,
+  isNumberVal,
+  transDecimalPlace
+} from "../common/customTable";
+import * as sheetInterface from "@/api/modules/sheetApi.js";
+import { dataBaseInterface } from '@/api/api.js';
+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';
+import BalanceAddChart from './BalanceAddChart.vue';
+import BalanceSheetChartItem from './BalanceSheetChartItem.vue';
+
+let autoSaveInterval=null;//自动保存定时器
+let dblclickInterval=null;//双击事件的定时器 为了解决同一个元素双击事件重复触发单击事件的问题
+
+export default {
+  props: {
+    disabled: { //是否只预览
+      type: Boolean,
+      default: false,
+    },
+    isStaticTable:{//当前是否为静态表
+      type: Boolean,
+      default: false,
+    }
+  },
+  components: {
+    selectTargetValueDia,
+    insertDateDia,
+    calculateEdbDia,
+    calculateDateDia,
+    toolBarSection,
+    BalanceAddChart,
+    BalanceSheetChartItem
+  },
+  computed: {
+    //列头
+    columnHeader() {
+      return getColumnHeaderCode(
+        this.config.data[0] ? this.config.data[0].length : 0
+      );
+    },
+    //行头
+    rowHeader() {
+      let total_length = this.config.data.length;
+      // console.log(this.config.data)
+      return getRowHeaderCode(total_length);
+    },
+  },
+
+  data() {
+    return {
+      config: {
+        /* 单元格类型 
+          1手动日期格 DataTimeType 0 /系统日期导入格 DataTimeType 1  /指标日期导入格 DataTimeType 2
+          2指标格 //eta1.5.6又弃用了
+          3自定义输入 
+          4插入值 表格里有关联的日期和指标格  // eta1.1.6弃用了
+          5弹窗里的插入值 有关联日期格 
+          6公式计算单元格 
+          7指标计算的插入值单元格
+          8日期计算值单元格
+        */
+        data: [],
+        contextMenuOption: [],
+      },
+
+      selectCell: {},//选中单元格info
+
+      rightClickCell: {},//右键单元格 key c r
+
+      insertTargetCell: {},//选择右键插入时的单元格 可和右键单元格不一样 key c r
+
+      insertRelationArr: [], //表格单元格依赖关系数组
+
+      isSelectTargetValueDialog: false,//选择指标插入值弹窗
+      insertTargetValueInfo: {},//编辑 关联info
+
+      cellrelationEdbInfo: {}, //指标浮窗信息
+
+      copyCellItem: {},//复制时的单元格信息 用于粘贴赋值
+
+      calculateClickCell: null,//双击公式单元格时的单元格信息 用于之后选其他单元格拼接公式
+
+      isInsertDateDialog: false,//导入日期弹窗
+      insertDateInfo: {},
+
+      isInsertCalculate: false,//插入指标计算值
+      insertCalculateInfo: {},//指标计算单元格info
+
+      formulaTip,
+
+      hasInit: false,
+
+      isInsertCalculateDate: false,//日期计算弹窗
+      insertCalculateDateInfo: {},//日期计算info
+
+      activeNames: [],
+
+
+      sheetOpts: [
+        // {
+        //   ...
+        //   isEdit: false,//双击后修改名称置为true
+        //   showDel: false
+        // }
+      ],//表格sheet
+      temSheetInputVal: '',
+      activeSheetId:0,//当前子表id
+
+      isShowAddChart:false,//添加图表
+      chartList:[],//当前平衡表图表数据
+
+      startSelectTable:false,//开始选择单元格
+      selectionStart: null,
+      selectionEnd: null,
+      selectedCells: []
+    };
+  },
+  mounted() {
+    if(!this.disabled){
+      // 每分钟自动保存一次
+      autoSaveInterval=setInterval(() => {
+        this.saveChildSheet()
+      }, 60*1000);
+    }
+    
+  },
+  beforeDestroy(){
+    // 清除自动保存定时器
+    clearInterval(autoSaveInterval)
+  },
+  methods: {
+    // 获取图表数据
+    async getChartList(){
+      const res = await sheetInterface.getBalanceChartData({
+				ExcelInfoId: Number(this.activeSheetId)
+			})
+      if(res.Ret!==200) return 
+      this.chartList=res.Data.List||[]
+    },
+
+    // 添加图表成功回调
+    addChartSuccess(){
+      this.isShowAddChart=false
+      this.getChartList()
+    },
+
+    // 编辑图表
+    handleEditChart(e){
+      this.isShowAddChart=true
+      this.$refs.balanceAddChart.initEditData(e)
+    },
+    //删除图表
+    handleDelChart(e){
+      sheetInterface.delBalanceChart({ChartInfoId:e.ChartInfo.ChartInfoId}).then(res=>{
+        if(res.Ret===200){
+          this.chartList=this.chartList.filter(item=>item.ChartInfo.ChartInfoId!==e.ChartInfo.ChartInfoId)
+        }
+      })
+    },
+
+
+    startSelection(startRow, startCol) {
+      // 只有添加图标弹窗弹起时有效
+      if(!this.isShowAddChart) return
+      if(this.disabled) return
+      console.log('开始选择');
+      this.startSelectTable=true
+      this.selectionStart = { row: startRow, col: startCol };
+      this.selectionEnd = { row: startRow, col: startCol };
+      this.selectedCells = [];
+    },
+    extendSelection(endRow, endCol) {
+      if(this.disabled) return
+      if (this.selectionStart) {
+        const start = this.selectionStart;
+        const end = { row: endRow, col: endCol };
+        const minRow = Math.min(start.row, end.row);
+        const maxRow = Math.max(start.row, end.row);
+        const minCol = Math.min(start.col, end.col);
+        const maxCol = Math.max(start.col, end.col);
+        this.selectedCells = [];
+        for (let row = minRow; row <= maxRow; row++) {
+          for (let col = minCol; col <= maxCol; col++) {
+            this.selectedCells.push({ row, col });
+          }
+        }
+        this.selectionEnd = end;
+      }
+    },
+    // 选择表格结束
+    endSelection() {
+      // 只有添加图标弹窗弹起时有效
+      if(!this.isShowAddChart) return
+      if(this.disabled) return
+      console.log('结束选择');
+      // console.log(this.selectedCells);
+      // console.log(this.selectionStart,this.selectionEnd);
+      if(this.selectionStart){
+        // 找到当前sheet 数据
+        const sobj=this.sheetOpts.filter(_e=>_e.ExcelInfoId===this.activeSheetId)[0]
+        // 如果选择的不是同行或者同列 
+        if(!(this.selectionStart.col==this.selectionEnd.col||this.selectionStart.row==this.selectionEnd.row)){
+          this.$message.warning(this.$t('CustomAnalysisPage.only_allowed_select_msg'));
+          return
+        }
+        // 判断选择的顺序如果是从后往前选择交换 start 和end
+        if((this.selectionStart.col==this.selectionEnd.col&&this.selectionStart.row>this.selectionEnd.row)||(this.selectionStart.row==this.selectionEnd.row&&this.selectionStart.col>this.selectionEnd.col)){
+          const temStart=JSON.parse(JSON.stringify(this.selectionStart))
+          const temEnd=JSON.parse(JSON.stringify(this.selectionEnd))
+          this.selectionEnd=temStart
+          this.selectionStart=temEnd
+        }
+
+
+        const str=`${sobj.ExcelName}!$${this.columnHeader[this.selectionStart.col]}$${this.selectionStart.row+1}:$${this.columnHeader[this.selectionEnd.col]}$${this.selectionEnd.row+1}`
+        this.$refs.balanceAddChart.tableSelect(this.selectionStart,this.selectionEnd,str)
+      }
+      
+      this.selectionStart = null;
+      this.startSelectTable=false
+      this.removeTextSelection()
+    },
+    isSelected(row, col) {
+      return this.selectedCells.some(cell => cell.row === row && cell.col === col);
+    },
+
+    removeTextSelection() {
+        if (window.getSelection) {
+            if (window.getSelection().empty) {
+                // Chrome, Firefox, Opera
+                window.getSelection().empty();
+            } else if (window.getSelection().removeAllRanges) {
+                // IE/Edge
+                window.getSelection().removeAllRanges();
+            }
+        } else if (document.selection) { // for IE < 9
+            document.selection.empty();
+        }
+    },
+
+    // 点击添加sheet
+    async handleAddSheet() {
+      // 先自动保存一次
+      const flag=await this.saveChildSheet()
+      if(!flag) return
+      this.sheetOpts.push({
+        ExcelName: '',
+        ExcelInfoId:0,
+        isEdit: true,
+        showDel: false
+      })
+      this.temSheetInputVal = ''
+      // 自动切换到新增的sheet
+      this.changeSheet(this.sheetOpts[this.sheetOpts.length-1])
+      this.$nextTick(() => {
+        this.$refs.sheetInput[0].focus()
+      })
+    },
+    // 双击编辑sheet名称
+    handleDbclickSheet(item) {
+      if(this.disabled) return
+      clearTimeout(dblclickInterval)//清除双击事件的定时器
+      item.isEdit = true
+      this.temSheetInputVal = item.ExcelName
+      this.$nextTick(() => {
+        this.$refs.sheetInput[0].focus()
+      })
+    },
+    // 修改sheet名称
+    handleModifySheetName() {
+      console.log('修改名称');
+      // 名称为空
+      if (!this.temSheetInputVal) {
+        this.$confirm('图表名称未填写', '提示', {
+          confirmButtonText: '输入表名',
+          cancelButtonText: '取消创建',
+          type: 'warning'
+        }).then(() => {
+          this.$nextTick(() => {
+            this.$refs.sheetInput[0].focus()
+          })
+        }).catch(() => {
+          if(this.activeSheetId===0){//当是新增表格时
+            this.sheetOpts = this.sheetOpts.filter(e => e.ExcelInfoId)
+            // 自动切换sheet
+            this.changeSheet(this.sheetOpts[this.sheetOpts.length-1])
+
+          }else{// 当编辑子表名称时 重置掉好了
+            this.sheetOpts.forEach(_e=>{
+              _e.isEdit=false
+            })
+          }
+          
+        });
+
+        return
+      }
+      // 如果activeSheetId=0 则是新增的子表
+      if(this.activeSheetId===0){
+        this.createNewChildSheet()
+        return
+      }
+
+      // 修改sheet名称
+      sheetInterface.balanceChildTableRename({
+        ExcelName:this.temSheetInputVal,
+        ExcelInfoId:this.activeSheetId
+      }).then(res=>{
+        if(res.Ret===200){
+          this.sheetOpts.forEach(item => {
+            if (item.ExcelInfoId===this.activeSheetId) {
+              item.ExcelName = this.temSheetInputVal
+              item.isEdit = false
+            }
+          })
+        }
+      })
+      
+    },
+    // 右键显示删除sheet
+    handleShowSheetDel(index) {
+      if(this.disabled) return
+      if (this.sheetOpts.length === 1) return
+      this.sheetOpts[index].showDel = true
+      // 切换到该子表
+      this.changeSheet(this.sheetOpts[index])
+    },
+
+    // 初始化子表列表数据
+    initSheetListData(data){
+      console.log(data);
+      this.sheetOpts=data.map(item=>{
+        return{
+          ...item,
+          isEdit:false,
+          showDel:false
+        }
+      })
+      this.changeSheet(this.sheetOpts[0])
+    },
+
+    // 切换sheet
+    changeSheet(item){
+      this.activeSheetId=item.ExcelInfoId
+      this.getSheetDetail()
+    },
+
+    // 点击切换子表
+    async clickChangeSheet(item){
+      if(this.isShowAddChart){
+        this.$message.warning('添加图表时禁止切换')
+        return
+      }
+      clearTimeout(dblclickInterval)//清除双击事件的定时器
+      dblclickInterval=setTimeout(async () => {
+        if(item.ExcelInfoId===this.activeSheetId) return
+        //保存一次
+        const flag=this.disabled?true:await this.saveChildSheet()
+        if(!flag) return
+        this.changeSheet(item)
+      }, 150);
+      
+    },
+
+    /* 获取表格详情 */
+    async getSheetDetail(type) {
+      // 如果是新增一个子表此时为0 直接创建一个空表
+      if(this.activeSheetId===0) {
+        this.initData(null);
+        return
+      }
+
+      const res = await sheetInterface.sheetDetail({
+				ExcelInfoId: Number(this.activeSheetId)
+			})
+      if(type==='refresh'){
+        this.$parent.updating=false
+      }
+
+      if(res.Ret !== 200)  return
+      // this.isCanEdit = res.Data.CanEdit
+      // if(!res.Data.CanEdit){
+      //   this.$message.warning(`${res.Data.Editor}${this.$t('OnlineExcelPage.currently_editing_msg') }`)
+      //   setTimeout(()=>{
+      //     this.backHandle()
+      //   },2000)
+      //   return 
+      // }
+
+      const { ExcelName,ExcelClassifyId,TableData,ModifyTime,Button } = res.Data;
+      // this.sheetButton=Button
+      // this.sheetForm.name=ExcelName
+      // this.sheetForm.classify=ExcelClassifyId
+
+      // this.$nextTick(()=>{
+      //   this.sheetInit=true
+      // })
+      this.updateTime =  this.$moment(ModifyTime).format('YYYY-MM-DD HH:mm:ss')
+
+      this.initData(TableData);
+
+      // 获取平衡表中的图表
+      this.getChartList()
+      
+      type==='refresh' && this.$message.success(this.$t('OnlineExcelPage.table_data_update_msg') )
+    },
+
+    // 新增子表
+    async createNewChildSheet(){
+      // 判断是否重名
+      const isDupName=this.sheetOpts.some(e=>e.ExcelName===this.temSheetInputVal)
+      if(isDupName) {
+        this.$confirm('此名称已被使用,请尝试其他名称', this.$t('Dialog.warn_tit'), {
+          confirmButtonText: this.$t('Dialog.confirm_btn'),
+          type: 'warning',
+          showClose:false,
+          center:true,
+          showCancelButton:false
+        }).then(()=>{
+          this.$nextTick(() => {
+            this.$refs.sheetInput[0].focus()
+          })
+        })
+
+        return
+      }
+      const params={
+        ExcelName: this.temSheetInputVal,
+        ExcelType: 1,
+        ExcelImage: '',
+        ExcelClassifyId:0,//写死
+        Source: 5,
+        ParentId:Number(this.$route.query.id),
+        TableData: {
+          CellRelation:"[]",
+          Data:[]
+        }
+      }
+      const res=await sheetInterface.sheetAdd(params)
+      if(res.Ret===200){
+        this.changeSheet({ExcelInfoId:res.Data.ExcelInfoId})
+        // 更新sheetOpts 内容
+        this.sheetOpts.forEach(item=>{
+          if(item.ExcelInfoId===0){
+            item.ExcelInfoId=res.Data.ExcelInfoId
+            item.ExcelName=this.temSheetInputVal
+            item.isEdit=false
+          }
+        })
+      }else{
+        //创建子表失败 删除sheetOpts这个数据 并且切换到左边一个表
+        const index=this.sheetOpts.findIndex(_e=>_e.ExcelInfoId===this.activeSheetId)
+        this.changeSheet(this.sheetOpts[index-1])
+        this.sheetOpts.splice(index,1)
+      }
+    },
+
+    // 保存子表 type:manualSave 手动保存
+    async saveChildSheet(type){
+      console.log('执行保存表格操作');
+      const item=this.sheetOpts.filter(e=>e.ExcelInfoId===this.activeSheetId)[0]
+      // console.log(item);
+      // console.log(this.sheetOpts,this.activeSheetId);
+      if(!this.activeSheetId) return
+      const params={
+        ExcelInfoId:this.activeSheetId,
+        ExcelName: item.ExcelName,
+        ExcelType: 1,
+        ExcelClassifyId: 0,
+        ExcelImage:'',
+        Source: 5,
+        ParentId:Number(this.$route.query.id),
+        TableData: this.getSaveParams()
+      }
+      const res = await sheetInterface.sheetEdit(params)
+      if(res.Ret !==200) return false
+      if(res.Data.Status==1){//有人在编辑 不允许编辑返回到列表
+        this.$message.warning(res.Data.Msg)
+        setTimeout(() => {
+          this.$router.back()
+        }, 1000);
+        return false
+      }
+      // 更新保存时间
+      this.$parent.updateTime=this.$moment().format('YYYY-MM-DD HH:mm:ss')
+      type==='manualSave'&&this.$message.success(this.$t('MsgPrompt.saved_msg'))
+      return true
+    },
+
+    //删除子表
+    async delChildSheet(){
+      await this.$confirm(this.$t('ETable.Msg.is_del_table_msg') , this.$t('Confirm.prompt') , {
+        confirmButtonText:  this.$t('Dialog.confirm_btn'),
+        cancelButtonText: this.$t('Dialog.cancel_btn'),
+        type: "warning",
+      })
+      const res=await sheetInterface.classifyDel({
+        ExcelInfoId:this.activeSheetId
+      })
+      if(res.Ret!==200) return
+      this.$message.success(res.Msg);
+      const index=this.sheetOpts.findIndex(_e=>_e.ExcelInfoId===this.activeSheetId)
+      if(index===0){
+        this.changeSheet(this.sheetOpts[index+1])
+      }else{
+        this.changeSheet(this.sheetOpts[index-1])
+      }
+      this.sheetOpts.splice(index,1)
+    },
+
+    
+
+
+
+    /* 输入时实时搜索 满足日期格式不搜索 有=视为输入公式不搜索  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
+        || checkDateFormat(query)
+        || dateOtherRegex.test(query)
+        || query.startsWith('=')
+      ) return cb([])
+
+      const { DataType, EdbInfoId } = this.selectCell;
+
+      const res = DataType === 2
+        ? await dataBaseInterface.targetDetail({ EdbInfoId })
+        : await sheetInterface.searchTarget({
+          KeyWord: query,
+          CurrentIndex: 1,
+          PageSize: 1000
+        })
+      if (res.Ret !== 200) return
+
+      let arr = DataType === 2 ? [res.Data] : (res.Data.List || [])
+      cb(arr);
+    },
+
+    /* 单击 */
+    clickCell(e, cell) {
+      if (this.disabled) return
+
+      selectCellStyle(e);
+      this.selectCell = cell;
+
+      setFocus(e);
+
+      //是插值单元格时寻找关联依赖的单元格 设置选框
+      if ([4, 5, 7].includes(cell.DataType)) {
+        const { key } = e.target.dataset;
+        if (!this.insertRelationArr.find(_ => _.key === key)) return
+        let { relation_date, relation_edb } = this.insertRelationArr.find(_ => _.key === key)
+
+        relation_date.key && setRelationStyle(relation_date)
+        relation_edb.key && setRelationStyle(relation_edb)
+      }
+
+      //选择指标弹窗打开时选择日期更新弹窗数据
+      this.isSelectTargetValueDialog && this.$refs.selectTargetValueRef.changeRleationDate(this.selectCell)
+
+      //计算指标弹窗打开时选择日期更新弹窗数据
+      this.isInsertCalculate && this.$refs.calculateEdbDiaRef.changeRleationDate(this.selectCell)
+
+      //日期计算弹窗打开选中日期框时且有选中item时更新选中值
+      cell.DataType === 1 && this.isInsertCalculateDate && this.$refs.calculateDateDiaRef.selectIndex && this.$refs.calculateDateDiaRef.setSelectItemValue(this.selectCell)
+    },
+
+    /* 插入值 往左往上寻找同行同列是否有符合条件的一指标一日期 */
+    async insertValue() {
+
+      let params = this.findNearestCell();
+      console.log(params)
+      if (!params) {
+        this.selectCell.DataType = 3;
+        this.selectCell.DataTimeType = 0;
+        this.selectCell.ShowValue = '';
+        this.selectCell.Value = '';
+        this.selectCell.DataTime = '';
+        this.selectCell.EdbInfoId = 0;
+        this.$message.warning(this.$t('OnlineExcelPage.no_here_val_msg'));
+        return
+      }
+
+      const { EdbInfoId, Date, DataTimeType } = params
+
+      const res = await sheetInterface.insertData({ EdbInfoId, Date })
+      if (res.Ret !== 200) return
+
+
+      res.Data ? this.$message.success(this.$t('OnlineExcelPage.insert_success_msg')) : this.$message.warning(this.$t('OnlineExcelPage.the_date_no_val_msg'))
+
+      this.selectCell.DataType = 4;
+      this.selectCell.ShowValue = res.Data;
+      this.selectCell.Value = res.Data;
+      this.selectCell.EdbInfoId = EdbInfoId;
+      this.selectCell.DataTime = Date;
+
+      this.setRelation(params)
+    },
+
+    // 建立插入单元格和依赖单元格关联关系
+    setRelation(data, cellType = 4) {
+      const { insert_cell } = data;
+
+      let relation_obj = {
+        type: cellType,
+        key: insert_cell.key,
+        relation_date: {
+          type: 1,
+          key: insert_cell.relation_date
+        },
+        relation_edb: {
+          type: 2,
+          key: insert_cell.relation_edb
+        }
+      }
+
+      let haveIndex = this.insertRelationArr.findIndex(_ => _.key === insert_cell.key);
+      if (haveIndex === -1) {
+        this.insertRelationArr.push(relation_obj)
+      } else {
+        this.insertRelationArr.splice(haveIndex, 1, relation_obj)
+      }
+      console.log(this.insertRelationArr)
+    },
+
+    /* 向左向上找出所有格子 找出离插入单元格最近的两个符合条件的单元格 看是否满足一指标一日期的条件
+      不满足就无法插入值
+    */
+    findNearestCell() {
+      let { rindex, cindex, key } = this.rightClickCell;
+
+      let index_row = this.rowHeader.findIndex(_ => _ === rindex);
+      let index_col = this.columnHeader.findIndex(_ => _ === cindex);
+
+      //同行左侧所有格子
+      let row_cell_arr = this.config.data[index_row].filter((_, cell_index) => cell_index < index_col);
+      //同列上侧所有格子
+      let col_cell_arr = this.config.data.filter((row, row_index) => row_index < index_row).map(row => row[index_col]);
+
+      if (!row_cell_arr.length || !col_cell_arr.length) {
+        return null
+      }
+
+      //寻找最近的符合1 2类型的两个格子
+      let params = null;
+
+      for (let i = row_cell_arr.length - 1; i >= 0; i--) {
+        for (let j = col_cell_arr.length - 1; j >= 0; j--) {
+          if (!params) {
+            if ((row_cell_arr[i].DataType === 1 && col_cell_arr[j].DataType === 2)
+              || (row_cell_arr[i].DataType === 2 && col_cell_arr[j].DataType === 1)) {
+              params = {
+                DataTimeType: row_cell_arr[i].DataType === 1 ? row_cell_arr[i].DataTimeType : col_cell_arr[j].DataTimeType,
+                Date: row_cell_arr[i].DataType === 1 ? row_cell_arr[i].ShowValue : col_cell_arr[j].ShowValue,
+                EdbInfoId: row_cell_arr[i].DataType === 2 ? row_cell_arr[i].EdbInfoId : col_cell_arr[j].EdbInfoId,
+                insert_cell: {
+                  key,
+                  relation_date: row_cell_arr[i].DataType === 1 ? row_cell_arr[i].Uid : col_cell_arr[j].Uid,
+                  relation_edb: row_cell_arr[i].DataType === 2 ? row_cell_arr[i].Uid : col_cell_arr[j].Uid,
+                },
+              }
+              break
+            }
+          }
+        }
+      }
+      return params;
+
+    },
+
+    /* 选择指标 单元格类型为2 已经是指标单元格了就重置单元格 否则就视为选择指标*/
+    selectTarget(e, cell) {
+      const { EdbName, EdbInfoId } = e;
+
+      //如果已经是指标单元格了再次点击就清空
+      if (cell.DataType === 2 && cell.EdbInfoId) {
+        this.clearCell()
+      } else {
+        cell.DataType = 2;
+        cell.DataTime = '';
+        cell.ShowValue = EdbName;
+        cell.Value = EdbName;
+        cell.EdbInfoId = EdbInfoId;
+      }
+
+      this.checkCellRelation(cell)
+    },
+
+    /* 输入框失焦 设置单元格类型 处理关联关系 */
+    async changeVal(e, cell) {
+
+      // 是日期格式 DataType为1
+      // 自定义内容 DataType 3
+      //有=号为输入公式 DataType 6
+      const { value } = e.target;
+      if (!value) { //无值重置单元格
+        cell.DataType = 3;
+        cell.ShowValue = value;
+        cell.Value = value;
+        cell.EdbInfoId = 0;
+        cell.DataTime = '';
+        cell.Extra = ''
+      } else {
+        //指标类型不做格式处理
+        if (cell.DataType === 2) return
+
+        console.log(checkDateFormat(value))
+        let dateFormat = checkDateFormat(value);
+        if (dateFormat) { //是日期格式
+          cell.DataType = 1;
+          cell.Extra = '';
+          cell.ShowValue = dateFormat;
+          cell.DataTime = dateFormat;
+          cell.Value = dateFormat;
+        } else if (value.startsWith('=')) { //公式单元格
+          cell.DataType = 6;
+          let calculateVal = await this.getValueByFormula(value);
+          if (!calculateVal) return
+          cell.ShowValue = calculateVal;
+          //处理公式关系
+          this.$set(cell, 'Extra', this.dealFormulaConstruction(value))
+
+
+        } else {//自定义值
+          cell.DataType = 3;
+          cell.ShowValue = value;
+          cell.Value = value;
+          cell.EdbInfoId = 0;
+          cell.DataTime = '';
+          cell.Extra = ''
+        }
+      }
+
+      /* 不是数字类型,清除原来设置的格式 */
+      if (!isNumberVal(value)) {
+        cell.ShowStyle = '';
+        cell.ShowStyle = '';
+      };
+
+      //判断是否是有插入值的依赖单元格 更新值或重置关系
+      this.checkCellRelation(cell)
+    },
+
+    /* 当前单元格是否和插入值有关联 无就不管 */
+    async checkCellRelation(cell) {
+      if (!this.insertRelationArr.length) return
+
+      const key = cell.Uid;
+
+      //有关联的N组数组
+      let haveRelationArr = this.insertRelationArr.filter(_ => _.relation_date.key === key || _.relation_edb.key === key);
+
+      if (!haveRelationArr.length) return
+
+      //去处理每一组关联的情况
+      haveRelationArr.forEach(async (relation) => {
+        const { relation_date, relation_edb, type } = relation;
+
+        if ((relation_date.key === key && cell.DataType === 1) || (relation_edb.key === key && cell.DataType === 2)) { //单元格类型不变只变值仍有关联关系 更新值
+
+          //类型4的表格插值才调接口刷数据 之后关联的有其他类型插值 区分一下
+          if (type === 4) {
+
+            //刷新插入值结果
+            let params = null;
+            if (relation_date.key === key && cell.DataType === 1) { //修改的是依赖日期格
+              let { EdbInfoId } = findCellByKey(this.config.data, relation.key)
+              params = {
+                EdbInfoId,
+                Date: cell.ShowValue
+              }
+
+            } else if (relation_edb.key === key && cell.DataType === 2) { //修改的依赖指标格
+              let { ShowValue } = findCellByKey(this.config.data, relation_date.key)
+              params = {
+                EdbInfoId: cell.EdbInfoId,
+                Date: ShowValue
+              }
+            }
+
+            const res = await sheetInterface.insertData(params)
+            if (res.Ret !== 200) return
+
+            //现在日期无值也不清除关系了
+            // !res.Data && this.updateInsertCell(relation.key);
+
+            this.config.data.forEach(row => {
+              row.forEach(cell => {
+                if (cell.Uid === relation.key) {
+                  cell.DataType = relation.type;
+                  cell.ShowValue = res.Data;
+                  cell.Value = res.Data;
+                  cell.EdbInfoId = params.EdbInfoId;
+                  cell.DataTime = params.Date;
+                }
+              })
+            })
+          }
+
+
+        } else {
+          // 清除插入值单元格式和关联关系
+          this.updateInsertCell(relation.key);
+        }
+      })
+
+    },
+
+    // 清除插入值单元格式和关联关系
+    updateInsertCell(key) {
+      this.config.data.forEach(row => {
+        row.forEach(cell => {
+          if (cell.Uid === key) {
+            cell.DataType = 3;
+            cell.EdbInfoId = 0;
+            cell.DataTime = '';
+            cell.ShowValue = '';
+            cell.Value = '';
+            cell.ShowStyle = ''
+          }
+        })
+      })
+
+      let relationIndex = this.insertRelationArr.findIndex(_ => _.key === key)
+      this.insertRelationArr.splice(relationIndex, 1)
+    },
+
+    /* 输入公式的计算值 */
+    async getValueByFormula(val) {
+
+      // 提取因数数组
+      let factors = extractFactorsFromFormula(val)
+      console.log(factors)
+
+      //根据因数找单元格
+      let isAllCell = factors.some(_ => findCellByFactorMixed(this.config.data, _) === null || isNaN(findCellByFactorMixed(this.config.data, _)))
+      if (isAllCell) {
+        this.$message.warning(this.$t('OnlineExcelPage.formula_val_error_msg'))
+        return '';
+      }
+
+      let TagMap = {};
+      factors.forEach(_ => {
+        if (!TagMap[_]) {
+          TagMap[_] = Number(findCellByFactorMixed(this.config.data, _))
+        }
+      });
+
+      const res = await sheetInterface.calculateCustomCellData({
+        CalculateFormula: val,
+        TagMap
+      })
+      if (res.Ret !== 200) return
+      return res.Data
+    },
+
+    /* 顶部公式改变 */
+    async updateValueByFormula(value) {
+      this.changeVal({ target: { value } }, this.selectCell)
+    },
+
+    /* 右键 */
+    rightClickHandle(e, cell) {
+      if (this.disabled) return
+
+      const { rindex, cindex, key } = e.target.dataset;
+      this.rightClickCell = {
+        rindex,
+        cindex,
+        key
+      }
+
+      this.selectCell = cell;
+
+      let pos;
+      if (rindex === '-1') { //列头处
+        pos = 'col'
+      } else if (cindex === '-1') { //行头
+        pos = 'row'
+      } else {//单元格
+        pos = 'cell'
+      }
+      this.config.contextMenuOption = pos === 'cell'
+        ? getRightClickMenu(pos, (cell.DataType === 1 && [1, 2].includes(cell.DataTimeType)) || [5, 7, 8].includes(cell.DataType),this.isStaticTable)
+        : getRightClickMenu(pos)
+
+      this.$nextTick(() => {
+        let dom = $('#contextMenu-wrapper')[0];
+
+        if (e.clientY > window.innerHeight / 2) {
+          dom.style.left = e.clientX - 3 + 'px';
+          dom.style.top = e.clientY - dom.offsetHeight - 3 + 'px';
+        } else {
+          dom.style.left = e.clientX - 3 + 'px';
+          dom.style.top = e.clientY - 3 + 'px';
+        }
+
+        ['col', 'row'].includes(pos) && selectMoreCellStyle(e);
+        pos === 'cell' && this.clickCell(e, cell);
+
+      })
+
+    },
+
+    /*  */
+    hideContextMenu() {
+      const dom = $('#contextMenu-wrapper')[0];
+      dom.style.left = '-9999px';
+      dom.style.top = '-9999px';
+    },
+
+    /* 右键事件 */
+    async handleContext(key) {
+
+      //可右键编辑的单元格类型
+      let editHandlesMap = {
+        1: this.insertDateOpen,
+        5: this.selectTargetOpen,
+        7: this.edbCalculateInsertOpen,
+        8: this.insertDateCalculateOpen
+      }
+
+      const keyMap = {
+        'del': this.delColOrRow,//删除
+        'insert-col-left': this.insertCol,//向左插入列
+        'insert-col-right': this.insertCol,//向右插入列
+        'insert-row-up': this.insertRow,//向上插入行
+        'insert-row-down': this.insertRow,//向下插入行
+        'insert-value': this.insertValue,//插入值
+        'choose-target': this.selectTargetOpen,//选择指标插入值
+        '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
+      }
+      keyMap[key] && keyMap[key](key)
+
+      key !== 'insert-edb-calculate' && this.hideContextMenu()
+    },
+
+    /* 打开选择指标弹窗  
+    打开弹窗后仍可以在页面上点击 多存一个选择指标时的当前单元格信息 */
+    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.resetDialogStatus('insertEdbVal')
+    },
+
+    /* 插入选择指标的值 */
+    insertSelectData({ edbId, value, relationDate, relationUid, str }) {
+
+      this.insertTargetCell.DataType = 5;
+      this.insertTargetCell.ShowValue = value;
+      this.insertTargetCell.Value = str;
+      this.insertTargetCell.EdbInfoId = edbId;
+      this.insertTargetCell.DataTime = relationDate;
+      this.insertTargetCell.ShowFormatValue = this.insertTargetCell.ShowStyle ? transDecimalPlace(value, JSON.parse(this.insertTargetCell.ShowStyle)) : '';
+
+      value ? this.$message.success(this.$t('ETable.Msg.insertion_success_msg')) : this.$message.warning(this.$t('ETable.Msg.date_no_data'))
+
+      //如果有关联表格日期就建立新的关联关系
+      if (relationDate && relationUid) {
+        let relation = {
+          insert_cell: {
+            key: this.insertTargetCell.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();
+      }
+
+    },
+
+    /* 清除单元格内容 格式 关联关系 */
+    clearCell() {
+      if ([4, 5].includes(this.selectCell.DataType)) resetRelationStyle();
+
+      this.selectCell.DataType = 3;
+      this.selectCell.ShowValue = '';
+      this.selectCell.Value = '';
+      this.selectCell.DataTime = '';
+      this.selectCell.DataTimeType = 0;
+      this.selectCell.EdbInfoId = 0;
+      this.selectCell.ShowStyle = '';
+      this.selectCell.ShowFormatValue = '';
+
+      this.checkCellRelation(this.selectCell)
+    },
+
+    /* 删除行列 */
+    delColOrRow() {
+      let { rindex, cindex } = this.rightClickCell;
+
+      if (rindex === '-1') { //删除列
+        console.log('删除列', cindex)
+
+        if (this.columnHeader.length === 1) return this.$message.warning(this.$t('OnlineExcelPage.keep_one_column_msg'))
+
+        let index = this.columnHeader.findIndex(_ => _ === cindex);
+
+        //删除时清除关系
+        if (this.insertRelationArr.length) {
+          let delCellIds = this.config.data.map(row => row[index].Uid);
+
+          this.clearRelationInsertCell(delCellIds);
+        }
+
+        this.config.data.forEach(row => {
+          row.splice(index, 1)
+        })
+      } else if (cindex === '-1') { //删除行
+        console.log('删除行', rindex)
+
+        if (this.rowHeader.length === 1) return this.$message.warning(this.$t('OnlineExcelPage.keep_one_row_msg'))
+
+        let index = this.rowHeader.findIndex(_ => _ === rindex)
+
+        if (this.insertRelationArr.length) {
+          //删除时清除关系
+          let delCellIds = this.config.data[index].map(cell => cell.Uid);
+
+          this.clearRelationInsertCell(delCellIds);
+        }
+
+        this.config.data.splice(index, 1)
+
+      }
+    },
+
+    /* 删除时清除关联关系 和删除单元格有关联的插入值单元格和 */
+    clearRelationInsertCell(delCellIds) {
+      //清除关联插入值得单元格
+      let haveRelationArr = this.insertRelationArr.filter(_ => delCellIds.includes(_.relation_date.key) || delCellIds.includes(_.relation_edb.key));
+      // console.log(haveRelationArr)
+
+      haveRelationArr.forEach(relation => {
+        !delCellIds.includes(relation) && this.updateInsertCell(relation.key);
+      })
+
+      this.insertRelationArr = this.insertRelationArr.filter(_ => !delCellIds.includes(_.key) && !delCellIds.includes(_.relation_date.key) && !delCellIds.includes(_.relation_edb.key))
+    },
+
+    /* 插入列 */
+    insertCol(key) {
+      let { cindex } = this.rightClickCell;
+
+      let index = this.columnHeader.findIndex(_ => _ === cindex);
+
+      this.config.data.forEach((row, rindex) => {
+        row.splice(key === 'insert-col-left' ? index : index + 1, 0, {
+          ShowValue: "",
+          Value: "",
+          DataType: 3,
+          DataTime: "",
+          EdbInfoId: 0,
+          Uid: md5.hex_md5(`${new Date().getTime()}${rindex}`)
+        })
+      })
+
+    },
+
+    /* 插入行 */
+    insertRow(key) {
+      let { rindex } = this.rightClickCell;
+
+      let index = this.rowHeader.findIndex(_ => _ === rindex)
+
+      let row = new Array(this.columnHeader.length).fill("").map((_, cindex) => ({
+        ShowValue: "",
+        Value: "",
+        DataType: 3,
+        DataTime: "",
+        EdbInfoId: 0,
+        Uid: md5.hex_md5(`${new Date().getTime()}${cindex}`)
+      }));
+
+      this.config.data.splice(key === 'insert-row-up' ? index : index + 1, 0, row)
+
+    },
+
+    /* 单元格类型5 浮到上面展示指标信息浮窗 */
+    async getRelationEdbInfo({ EdbInfoId, DataType }) {
+      if (![5, 7].includes(DataType) || this.disabled) return
+
+      const res = await dataBaseInterface.targetDetail({ EdbInfoId })
+
+      if (res.Ret !== 200) return
+
+      this.cellrelationEdbInfo = res.Data;
+    },
+
+    /* 导入系统/指标日期弹窗 */
+    insertDateOpen(type) {
+      this.insertTargetCell = this.selectCell;
+      resetDialogCellStyle();
+
+      if (type === 'cell-edit') { //编辑日期
+        this.insertDateInfo = {
+          ...this.insertTargetCell
+        }
+      } else {
+        this.insertDateInfo = {
+          // key:type
+        }
+      }
+      this.isInsertDateDialog = true;
+      this.resetDialogStatus();
+    },
+
+    /* 弹窗都是无遮罩的 弹一个就重置其他的 */
+    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;
+      }
+      if (type !== 'balanceAddChart') {
+        this.$refs.balanceAddChart && this.$refs.balanceAddChart.initData();
+        this.isShowAddChart = false;
+      }
+    },
+
+    /* 插入系统/指标日期 */
+    insertDatehandle({ insertValue, dataTimeType, str }) {
+
+      this.insertTargetCell.DataType = 1;
+      this.insertTargetCell.DataTimeType = dataTimeType;
+      this.insertTargetCell.ShowValue = insertValue;
+      this.insertTargetCell.Value = str;
+      this.insertTargetCell.EdbInfoId = 0;
+      this.insertTargetCell.DataTime = insertValue;
+    },
+
+    /* 指标计算弹窗 */
+    edbCalculateInsertOpen(item) {
+      this.insertTargetCell = this.selectCell;
+      resetDialogCellStyle();
+      setRelationStyle({ key: this.insertTargetCell.Uid }, 'td-choose-insert-target');
+
+      if (item === 'cell-edit') { //编辑
+        const { Value } = this.insertTargetCell;
+
+        let menuInfo = this.config.contextMenuOption
+          .find(_ => _.key === 'insert-edb-calculate').children
+          .find(menu => menu.source === JSON.parse(Value).Source);
+
+        this.insertCalculateInfo = {
+          ...menuInfo,
+          ...this.insertTargetCell
+        }
+      } else {
+        this.insertCalculateInfo = {
+          ...item
+        }
+      }
+      this.isInsertCalculate = true;
+
+      this.resetDialogStatus('insertEdbCalculateVal')
+    },
+
+    /* 导入指标计算值 */
+    insertCalculateData(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 = relationDate;
+      this.insertTargetCell.ShowFormatValue = this.insertTargetCell.ShowStyle ? transDecimalPlace(InsertValue, JSON.parse(this.insertTargetCell.ShowStyle)) : '';
+
+      InsertValue ? this.$message.success(this.$t('ETable.Msg.insertion_success_msg')) : this.$message.warning(this.$t('ETable.Msg.date_no_data'))
+
+      //如果有关联表格日期就建立新的关联关系
+      if (relationDate && relationUid) {
+        let relation = {
+          insert_cell: {
+            key: this.insertTargetCell.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(this.$t('ETable.Msg.insertion_success_msg'))
+    },
+
+    /* 初始化8行5列 */
+    initData(initData = null) {
+      console.log('initData');
+      this.hasInit = false
+      if (initData&&initData.Data.length>0) {
+        const { CellRelation, Data } = initData;
+        this.config.data = Data;
+        this.insertRelationArr = JSON.parse(CellRelation);
+      } else {
+
+        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,
+            DataTime: "",
+            EdbInfoId: 0,
+            Uid: md5.hex_md5(`${new Date().getTime()}${_rindex}${_cindex}`)
+          }));
+        });
+      }
+      this.$nextTick(() => {
+        this.hasInit = true
+      })
+    },
+
+    /* 处理因数结构 =a1+b1 => [{ Tag: a,Row:1,Key:'' }] */
+    dealFormulaConstruction(val) {
+      // 提取因数数组
+      let factors = extractFactorsFromFormula(val)
+      let arr = factors.map(str => ({
+        Tag: splitString(toUpperCase(str))[0],
+        Row: splitString(toUpperCase(str))[1],
+        Key: findCellKeyByFactor(str)
+      }))
+      return JSON.stringify(arr)
+    },
+
+
+    /* 要支持复制粘贴把公式也带过去 公式单元格类型为6 其余就正常复制文本 */
+    copyCellHandle(e, cell) {
+      this.copyCellItem = cell;
+      // 阻止默认的复制操作
+      e.preventDefault();
+    },
+
+    /* 要支持复制粘贴把公式也带过去 公式单元格类型为6 其余就正常复制文本 */
+    pasteCellHandle(e, cell) {
+      if (this.copyCellItem.DataType === 6) {
+        cell.DataType = this.copyCellItem.DataType;
+        cell.ShowValue = this.copyCellItem.ShowValue;
+        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;
+      }
+
+      // 阻止默认的粘贴操作
+      e.preventDefault();
+    },
+
+    /* 单元格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.$set(cell,'CanEdit',false)
+      }
+    },
+
+    /* 双击切换状态 插值单元格不允许切换 可切换类型1,2,3,6*/
+    dblClickCellHandle(e, cell) {
+      if (this.disabled || ![1, 2, 3, 6].includes(cell.DataType) || [1, 2].includes(cell.DataTimeType)) return
+
+      this.$set(cell, 'CanEdit', true)
+      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();
+      })
+    },
+
+    /* 处理保存的参数 */
+    getSaveParams() {
+      const { data } = this.config;
+
+      let params = {
+        CellRelation: JSON.stringify(this.insertRelationArr),
+        Data: data
+      }
+
+      return params
+    },
+
+    /* tab禁掉 */
+    handlekeyDownKeys(e) {
+      if (e.keyCode === 9) {
+        e.preventDefault();
+      }
+    },
+
+    /* 改变单元格显示文本 */
+    updateCellStyle({ ShowStyle, ShowFormatValue }) {
+
+      this.$set(this.selectCell, 'ShowStyle', ShowStyle)
+      this.$set(this.selectCell, 'ShowFormatValue', ShowFormatValue)
+    }
+  },
+};
+</script>
+<style scoped lang="scss">
+.nodata {
+  text-align: center;
+  font-size: 16px;
+  color: #666;
+  padding: 100px 0;
+}
+.table-wrapper {
+  width: 100%;
+  overflow: auto;
+  .table-content-wrap {
+    display: flex;
+    .left-wrap {
+      flex: 1;
+      overflow: hidden;
+      .text-select-disabled{
+        -webkit-user-select: none;
+        -moz-user-select: none;
+        -ms-user-select: none;
+        user-select: none;
+      }
+    }
+    .right-wrap {
+      width: 400px;
+      margin-left: 20px;
+      flex-shrink: 0;
+      .chart-list{
+        background-color: #fff;
+        height: 100%;
+        height: calc(100vh - 440px);
+        overflow-y: auto;
+        padding: 20px;
+      }
+    }
+  }
+  .table-wrap {
+    width: 100%;
+    background-color: #fff;
+    // padding: 20px;
+    height: calc(100vh - 480px);
+    overflow: auto;
+  }
+  .bot-sheet-box {
+    margin-top: 20px;
+    display: flex;
+    justify-content: space-between;
+    .sheet-list {
+      flex: 1;
+      font-size: 12px;
+      display: flex;
+      align-items: center;
+      flex-wrap: wrap;
+      gap: 10px;
+      .sheet-item {
+        position: relative;
+        .del-box {
+          position: absolute;
+          background-color: #fff;
+          padding: 5px;
+          top: -22px;
+          right: -16px;
+          z-index: 10;
+          width: 40px;
+          text-align: center;
+          cursor: pointer;
+        }
+      }
+      .input {
+        width: 75px;
+        background-color: transparent;
+        border: none;
+        box-sizing: border-box;
+        color: #0033ff;
+        text-align: center;
+      }
+      .box {
+        max-width: 120px;
+        min-width: 75px;
+        text-align: center;
+        background-color: #eff4ff;
+        .text {
+          display: block;
+          overflow: hidden;
+          white-space: nowrap;
+          text-overflow: ellipsis;
+        }
+      }
+      .active {
+        background-color: #fff;
+        color: #0033ff;
+      }
+    }
+  }
+
+  .formula-wrapper {
+    height: 42px;
+    display: flex;
+    align-items: center;
+    background: #fff;
+    border-radius: 4px;
+    box-shadow: 0 3px 6px rgba(0, 0, 0, 0.05);
+    border: 1px solid #dcdfe6;
+    margin-bottom: 15px;
+    padding: 0 15px;
+  }
+  .table td,
+  th {
+    width: 104px;
+    min-width: 104px;
+    height: 35px;
+    max-height: 35px;
+    background: #fff;
+    text-align: center;
+    word-break: break-all;
+    border: 1px solid #dcdfe6;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    position: relative;
+    color: #606266;
+
+    &.td-chose::after {
+      position: absolute;
+      top: 0;
+      left: 0;
+      right: 0;
+      bottom: 0;
+      content: "";
+      display: block;
+      outline: 0;
+      border: 2px solid #0033ff;
+      box-shadow: 0 0 5px rgba(73, 177, 249, 0.5);
+    }
+    &.td-relation::after {
+      position: absolute;
+      top: 0;
+      left: 0;
+      right: 0;
+      bottom: 0;
+      content: "";
+      display: block;
+      outline: 0;
+      border: 2px dashed #0033ff;
+      box-shadow: 0 0 5px rgba(73, 177, 249, 0.5);
+    }
+    &.td-col-select::after {
+      position: absolute;
+      top: 0;
+      left: 0;
+      right: 0;
+      bottom: 0;
+      content: "";
+      display: block;
+      outline: 0;
+      border: 1px solid rgb(24, 173, 24);
+      border-bottom: none;
+      border-top: none;
+    }
+    &.td-row-select::after {
+      position: absolute;
+      top: 0;
+      left: 0;
+      right: 0;
+      bottom: 0;
+      content: "";
+      display: block;
+      outline: 0;
+      border: 1px solid rgb(24, 173, 24);
+      border-left: none;
+      border-right: none;
+    }
+    &.td-choose-insert-target::after {
+      position: absolute;
+      top: 0;
+      left: 0;
+      right: 0;
+      bottom: 0;
+      content: "";
+      display: block;
+      outline: 0;
+      border: 2px dashed orange;
+      box-shadow: 0 0 5px rgba(73, 177, 249, 0.5);
+    }
+  }
+
+  .th-tg {
+    background: #ebeef5;
+    &:hover {
+      cursor: pointer;
+      background: #ddd;
+      /* border: 2px solid #409eff; */
+    }
+    &.sm {
+      width: 36px;
+      min-width: 36px;
+      max-width: 36px;
+    }
+  }
+  //整行选中
+  tr {
+    position: relative;
+    &.choose-all::after {
+      position: absolute;
+      top: 0;
+      left: 0;
+      right: 0;
+      bottom: 0;
+      content: "";
+      display: block;
+      outline: 0;
+      border: 2px solid #5897fb;
+      box-shadow: 0 0 5px rgba(73, 177, 249, 0.5);
+    }
+  }
+
+  .td_selected{
+    background-color: #F5F7F9!important;
+  }
+
+  .contextMenu-wrapper {
+    position: fixed;
+    z-index: 99;
+    top: -9999px;
+    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 {
+      padding: 10px 25px;
+      cursor: pointer;
+      &:hover {
+        background-color: #f5f7fa;
+      }
+      &:hover .subMenu-wrapper {
+        display: block;
+      }
+    }
+
+    .subMenu-wrapper {
+      width: 180px;
+      /* display: none; */
+      padding: 10px 0;
+      /* box-shadow: 0 1px 4px #999; */
+      /* background: #fff; */
+      /* position: absolute;
+      right: -178px;
+      top:-205px;
+      max-height: 400px;
+      overflow-y: auto; */
+      .item {
+        &:hover {
+          background: #fff;
+        }
+      }
+    }
+  }
+}
+</style>
+<style lang="scss">
+.table-wrapper {
+  td {
+    .el-input__inner {
+      border: none;
+      outline: none;
+      text-align: center;
+      height: 34px;
+      line-height: 34px;
+    }
+  }
+  .el-input.is-disabled .el-input__inner {
+    background-color: #fff;
+  }
+  .bot-sheet-box {
+    .el-button + .el-button {
+      margin-left: 0;
+    }
+  }
+}
+.formula-wrapper .el-input__inner {
+  border: none;
+  outline: none;
+}
+.edb-select-popover {
+  width: 300px !important;
+  .edb-item {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    .edb-item-name {
+      max-width: 260px;
+    }
+  }
+}
+.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>

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

@@ -105,7 +105,8 @@ export default {
 				'/chartrelevance':this.relevanceClassifyApi,
 				'/fittingEquationList': this.fittingEquationClassifyApi,
 				'/statisticFeatureList': this.statisticFeatureClassifyApi,
-				'/crossVarietyChartList': this.crossVarietyClassifyApi
+				'/crossVarietyChartList': this.crossVarietyClassifyApi,
+				'/sheetBalanceList':this.sheetClassifyApi,
 			}
 			handleMap[this.$route.path] && handleMap[this.$route.path](classify_name,classify_id)
 		},

+ 1 - 1
src/views/datasheet_manage/components/toolBarSection.vue

@@ -43,7 +43,7 @@ export default {
   },
   watch: {
     cell(nval) {
-      if(nval.ShowStyle) {
+      if(nval&&nval.ShowStyle) {
         this.option = {
           ...JSON.parse(nval.ShowStyle)
         }

+ 119 - 0
src/views/datasheet_manage/mixins/balanceTableMixin.js

@@ -0,0 +1,119 @@
+// 平衡表
+import * as sheetInterface from "@/api/modules/sheetApi.js";
+export default {
+  computed: {
+    downExcelFileUrl() {
+      let url = `${
+        process.env.VUE_APP_API_ROOT
+      }/datamanage/excel_info/table/download?${localStorage.getItem("auth")}`;
+      return url;
+    },
+  },
+  methods: {
+    itemHandle(data, type) {
+      if (type === "edit") {
+        this.handleEdit(data);
+        return;
+      }
+      if (type === "refresh") {
+        this.refreshSheetEdb(data.ExcelInfoId);
+        return;
+      }
+      if (type === "save") {
+        if(this.$route.path==='/sheetBalanceList'){
+            this.$parent.sheetDetailInfo = data;
+            this.$parent.saveOtherHandle();
+        }else{
+            this.saveOtherForm.name = data.ExcelName + "(1)";
+            this.isSaveOther = true;
+        }
+        
+        return;
+      }
+      if (type === "download") {
+        const value = `${this.downExcelFileUrl}&ExcelInfoId=${data.ExcelInfoId}`;
+
+        const a = document.createElement("a");
+        a.href = value;
+        a.target = "_blank";
+        a.download = data.ExcelName;
+        a.style.display = "none";
+        document.body.append(a);
+        a.click();
+        return;
+      }
+      if (type === "del") {
+        if(this.$route.path==='/sheetBalanceList'){
+            this.$emit("delSheetHandle", { cell: data, type: "del-list" });
+        }else{
+            this.$confirm(this.$t('ETable.Msg.is_del_table_msg') , this.$t('Confirm.prompt') , {
+                confirmButtonText:  this.$t('Dialog.confirm_btn'),
+                cancelButtonText: this.$t('Dialog.cancel_btn'),
+                type: "warning",
+              })
+                .then(() => {
+                    this.handleDelExcel(data)
+                })
+                .catch(() => {});
+            
+        }
+        
+        return;
+      }
+    },
+
+    handleDelExcel(data){
+        sheetInterface.classifyDel({
+          ExcelClassifyId:data.ExcelClassifyId,
+          ExcelInfoId:data.ExcelInfoId,
+          Source: 5
+        })
+        .then((res) => {
+          if (res.Ret !== 200) return;
+          this.$message.success(res.Msg);
+            this.$router.back()
+        });
+    },
+
+    // 去编辑
+    async handleEdit(data) {
+      const res = await sheetInterface.markSheetEditStatus({ ExcelInfoId: data.ExcelInfoId, Status: 1 });
+      if (res.Ret !== 200) return;
+      if (res.Data.Status == 0) {
+        this.$router.push({
+          path: "/editBalanceSheet",
+          query: {
+            id: data.ExcelInfoId,
+          },
+        });
+      } else if (res.Data.Status == 1) {
+        //编辑中
+        const text = `${res.Data.Editor}${this.$t("OnlineExcelPage.editing_msg")}`;
+        if(this.$route.path==='/sheetBalanceList'){
+            this.$emit("updateEdit", {
+                ExcelInfoId: data.ExcelInfoId,
+                Editor: res.Data.Editor,
+            });
+        }else{
+            this.excelInfo.Editor=res.Data.Editor
+            this.excelInfo.CanEdit=false
+        }
+        
+        this.$message.warning("当前" + text);
+      }
+    },
+
+    /* 刷新表格 */
+    refreshSheetEdb: _.debounce(async function (id) {
+      if (this.sheetRefreshing) return;
+      this.sheetRefreshing = true;
+      const res = await sheetInterface.refreshCustomSheet({
+        ExcelInfoId: id,
+      });
+      this.sheetRefreshing = false;
+
+      if (res.Ret !== 200) return;
+      this.$message.success(this.$t("ETable.Msg.refresh_success_msg"));
+    }, 300),
+  },
+};

+ 2 - 1
src/views/datasheet_manage/mixins/classifyMixin.js

@@ -353,7 +353,8 @@ export default {
         '/sheetList': 'etaTable_excel',
         '/sheetTimeList': 'etaTable_customize_data',
         '/sheetMixedList': 'etaTable_customize_mix',
-        '/sheetAnalysisList': 'etaTable_analysis'
+        '/sheetAnalysisList': 'etaTable_analysis',
+        '/sheetBalanceList':'etaTable_customize_balance'
       }
       return this.permissionBtn.isShowBtn('etaTablePermission',`${sheetType[this.$route.path]}_${type}`)
     }

+ 182 - 9
src/views/datasheet_manage/sheetList.vue

@@ -16,12 +16,13 @@
           <el-button v-if="permissionBtn.checkPermissionBtn(permissionBtn.etaTablePermission.etaTable_customize_data_sheetAdd)&&sourceMap[$route.path]===2" type="primary" style="margin-right:20px" @click="goAddSheetHandle">{{$t('OnlineExcelPage.add_timeline_table_btn')}}</el-button >
 
           <el-button v-if="permissionBtn.checkPermissionBtn(permissionBtn.etaTablePermission.etaTable_customize_mix_sheetAdd)&&sourceMap[$route.path]===3" type="primary" @click="goAddSheetHandle">{{$t('OnlineExcelPage.add_mixed_table_btn')}}</el-button >
+          <el-button v-if="permissionBtn.checkPermissionBtn(permissionBtn.etaTablePermission.etaTable_customize_balance_sheetAdd)&&sourceMap[$route.path]===5" type="primary" @click="showAddBalanceTable=true">{{$t('OnlineExcelPage.add_balance_table_btn')}}</el-button >
 
           <el-checkbox 
             v-model="isShowMe"
             style="margin-left:20px"
             @change="() => { getTreeData();getPublicList() }"
-          >{{$t('Chart.only_see_mine')}}</el-checkbox>
+          >{{sourceMap[$route.path]===5?$t('BalanceSheet.only_edit'):$t('Chart.only_see_mine')}}</el-checkbox>
 
         </div>
         <div class="search-cont">
@@ -161,10 +162,30 @@
         </span>
       </div>
 
+      <!-- 平衡表列表 -->
       <div
         class="main-right"
         id="right"
         :style="isSlideLeft ? 'width:100%' : 'width:80%'"
+        v-if="sourceMap[$route.path]===5"
+      >
+        <BalanceSheetList 
+          :total="sheet_total" 
+          :list="sheetList"
+          :finished="!publicHaveMove"
+          :loading="sheetLoading"
+          @loadMoreHandle="loadMoreHandle"
+          @delSheetHandle="delSheetHandle"
+          @downloadExcel="downloadExcel"
+          @updateEdit="balanceSheetUpdateEdit"
+        />
+      </div>
+
+      <div
+        v-else
+        class="main-right"
+        id="right"
+        :style="isSlideLeft ? 'width:100%' : 'width:80%'"
       >
         <!-- 表格详情 -->
         <div class="sheet-detail-wrapper" v-if="select_id">
@@ -345,6 +366,7 @@
                 value: 'ExcelClassifyId',
                 children: 'Children',
                 emitPath: false,
+                checkStrictly: true,
               }"
               style="width: 80%"
               :placeholder="$t('OnlineExcelPage.select_appropriate_category_lable')"
@@ -365,6 +387,58 @@
         >
       </div>
     </m-dialog>
+
+    <!-- 新增平衡表弹窗 -->
+    <m-dialog
+      :show.sync="showAddBalanceTable"
+      width="650px"
+      :title="$t('OnlineExcelPage.add_balance_table_btn')"
+      @close="showAddBalanceTable=false"
+    >
+      <el-form 
+        :model="balanceTableForm" 
+        :rules="balanceTableFormRule" 
+        ref="addBalanceForm" 
+        label-width="140px" 
+        class="add-balance-wrap"
+      >
+        <el-form-item :label="$t('OnlineExcelPage.excel_name_ipt')" prop="name">
+          <el-input 
+            v-model="balanceTableForm.name" 
+            :placeholder="$t('OnlineExcelPage.please_table_name_ipt')"
+            style="width:350px"
+          ></el-input>
+        </el-form-item>
+        <el-form-item :label="$t('SteelChemicalPage.label_edb_classify')" prop="classify">
+          <el-cascader
+            v-model="balanceTableForm.classify"
+            :options="balanceClassifyOpts"
+            :props="{
+              label: 'ExcelClassifyName',
+              value: 'ExcelClassifyId',
+              children: 'Children',
+              emitPath: false,
+              checkStrictly: true,
+            }"
+            clearable
+            :placeholder="$t('OnlineExcelPage.select_table_category')"
+            style="width:350px"
+          />
+        </el-form-item>
+      </el-form>
+
+      <div style="display: flex; justify-content: center; margin-top: 30px">
+        <el-button
+          type="primary"
+          style="margin-right: 60px"
+          @click="handleConfirmAddBalanceTable"
+          >{{$t('Dialog.confirm_save_btn')}}</el-button
+        >
+        <el-button type="primary" plain @click="showAddBalanceTable=false"
+          >{{$t('Dialog.cancel_btn')}}</el-button
+        >
+      </div>
+    </m-dialog>
   </div>
 </template>
 
@@ -378,9 +452,11 @@ import { getSheetImage } from "./common/option";
 import CustomTable from "./components/CustomTable.vue";
 import MixedTable from "./components/MixedTable.vue";
 import sheetListWrap from "./components/sheetListWrap.vue"
+import BalanceSheetList from './components/BalanceSheetList.vue';
+
 export default {
   name: "",
-  components: { mDialog, classifyDia, Sheet, CustomTable, MixedTable,sheetListWrap },
+  components: { mDialog, classifyDia, Sheet, CustomTable, MixedTable,sheetListWrap,BalanceSheetList },
   mixins: [leftMixin],
   beforeRouteLeave(to,from,next){
     if(from.path=='/sheetList'){
@@ -396,11 +472,11 @@ export default {
       return url;
     },
     classifyOptions() {
-      let options = this.treeData.map((_) => ({
-        ExcelClassifyId: _.ExcelClassifyId,
-        ExcelClassifyName: _.ExcelClassifyName,
-      }));
-      return options;
+      // let options = this.treeData.map((_) => ({
+      //   ExcelClassifyId: _.ExcelClassifyId,
+      //   ExcelClassifyName: _.ExcelClassifyName,
+      // }));
+      return this.balanceClassifyOpts;
     },
     saveOtherFormRule(){
       return {
@@ -445,7 +521,8 @@ export default {
       sheetList: [],
       sheet_total: 0,
       sheet_page: 1,
-      sheet_pages_size: 16,
+      sheet_pages_size: this.$route.path==='/sheetBalanceList'?30:16,
+      sheetLoading:false,
 
       /* 另存为 */
       isSaveOther: false,
@@ -458,6 +535,7 @@ export default {
         '/sheetList': 1,
         '/sheetTimeList': 2,
         '/sheetMixedList': 3,
+        '/sheetBalanceList': 5,
       },
       saveTime:"",
       editButtonText:"",
@@ -471,6 +549,18 @@ export default {
       isShowMe: false,//只看我的
 
       sheetRefreshing:false,//表格刷新状态
+
+      showAddBalanceTable:false,//创建平衡表弹窗
+      balanceTableForm:{
+        name:'',
+        classify:''
+      },
+      balanceTableFormRule:{
+        name:[{ required: true, message: '请输入表格名称', trigger: 'blur' },],
+        classify:[{ required: true, message: '请选择分类', trigger: 'change' },]
+      },
+      balanceClassifyOpts:[],//平衡表分类数据
+
     };
   },
   watch: {
@@ -527,6 +617,54 @@ export default {
     }
   },
   methods: {
+    // 获取平衡表分类
+    getBalanceClassifyOpts(){
+      sheetInterface.excelClassifyOne({ Source: this.sourceMap[this.$route.path] }).then(res => {
+        if (res.Ret !== 200) return
+
+        this.balanceClassifyOpts = res.Data.AllNodes || [];
+      })
+    },
+    //确认新增平衡表
+    handleConfirmAddBalanceTable(){
+      this.$refs.addBalanceForm.validate((valid) => {
+          if (valid) {
+
+            let params = {
+              ExcelName: this.balanceTableForm.name,
+              ExcelType: 1,
+              ExcelClassifyId: this.balanceTableForm.classify,
+              ExcelImage: '',
+              Source: 5,
+              TableData: {
+                CellRelation:"[]",
+                Data:[]
+              }
+            };
+            sheetInterface.sheetAdd(params).then(res=>{
+              if(res.Ret===200){
+                this.$router.push({
+                  path:'/editBalanceSheet',
+                  query:{
+                    id:res.Data.ExcelInfoId
+                  }
+                })
+              }
+            })
+          } 
+        });
+    },
+    // 更新平衡表编辑状态
+    balanceSheetUpdateEdit(data){
+      // 找到哪个表格
+      this.sheetList.forEach(item => {
+        if(item.ExcelInfoId===data.ExcelInfoId){
+          item.CanEdit=false
+          item.Editor=data.Editor
+        }
+      });
+    },
+
     /* 添加表格 */
     goAddSheetHandle() {
       if (!this.treeData.length) return this.$message.warning(this.$t('OnlineExcelPage.please_table_classification_msg') );
@@ -562,6 +700,10 @@ export default {
           params && this.selectCurrentNode(params);
         });
       });
+      // 更新一下分类把 新增平衡表时要
+      if([3,5].includes(this.sourceMap[this.$route.path])){
+        this.getBalanceClassifyOpts()
+      }
     },
 
     /* 搜索表格 */
@@ -585,6 +727,18 @@ export default {
     /* 选中分类变化时 */
     nodeChange({ UniqueCode, ExcelInfoId, ExcelClassifyId }, node) {
       console.log(this.select_id,ExcelInfoId,'UniqueCode');
+
+      // 点击的是平衡表模块的表格直接进入预览页
+      if(this.sourceMap[this.$route.path]===5&&ExcelInfoId>0){
+        this.$router.push({
+            path:'/viewBalanceSheet',
+            query:{
+              id:ExcelInfoId
+            }
+        })
+        return
+      }
+
       this.search_txt = "";
       this.select_node = UniqueCode;
       this.select_classify = !ExcelInfoId ? ExcelClassifyId : 0;
@@ -733,7 +887,7 @@ export default {
       if (Source === 1) {
         value = FileUrl;
         this.downLoad(value, ExcelName);
-      } else if ([2, 3].includes(Source)) {
+      } else if ([2, 3,5].includes(Source)) {
         value = `${this.downExcelFileUrl}&ExcelInfoId=${ExcelInfoId}`;
 
         const a = document.createElement("a");
@@ -852,6 +1006,7 @@ export default {
     },1500),
     /* 获取表格列表 */
     getPublicList() {
+      this.sheetLoading=true
       sheetInterface.sheetList({
         CurrentIndex: this.sheet_page,
         PageSize: this.sheet_pages_size,
@@ -859,6 +1014,7 @@ export default {
         Source: this.sourceMap[this.$route.path],
         IsShowMe: this.isShowMe
       }).then((res) => {
+        this.sheetLoading=false
         if (res.Ret !== 200) return;
 
         this.publicHaveMove = res.Data
@@ -870,11 +1026,19 @@ export default {
             : [...this.sheetList, ...res.Data.List]
           : [];
         this.sheet_total = res.Data ? res.Data.Paging.Totals : 0;
+      }).catch(()=>{
+        this.sheetLoading=false
       });
     },
 
     /* 加载更多 */
     loadMoreHandle: _.throttle(function () {
+      // 平衡表加载下一页
+      if(this.sourceMap[this.$route.path]==5){
+        this.sheet_page++;
+        this.getPublicList();
+        return
+      }
       let scrollTop = this.$refs.sheetListWrap.$refs.listRef.scrollTop;
       let clientHeight = this.$refs.sheetListWrap.$refs.listRef.clientHeight;
       let scrollHeight = this.$refs.sheetListWrap.$refs.listRef.scrollHeight;
@@ -1003,6 +1167,10 @@ export default {
       this.$message.success(this.$t('MsgPrompt.saved_msg') );
       this.cancelSaveOther();
       this.getTreeData();
+      if(this.sourceMap[this.$route.path]==5){
+        this.sheet_page=1
+        this.getPublicList();
+      }
     },
 
     /* 重绘右侧区域宽度 */
@@ -1319,6 +1487,11 @@ $normal-font: 14px;
 </style>
 
 <style lang="scss">
+.add-balance-wrap{
+  .el-input{
+    width: 100%;
+  }
+}
 .dataSheet-container {
   .label-input .el-input__inner {
     height: 25px;

+ 15 - 12
src/views/mychart_manage/components/chartDetailDia.vue

@@ -59,7 +59,7 @@
                 placeholder="年份日期选择"
                 @change="seasonYearChange"
               /> -->
-              <div v-else-if="chartInfo.ChartType === 2" @click="openDateDia" class="date-setting">
+              <div v-else-if="chartInfo.ChartType === 2&&chartInfo.Source!==11" @click="openDateDia" class="date-setting">
                 {{ season_year && season_year.length>0 ? season_year[0]+'~'+season_year[1]:"年份日期选择" }}
               </div>
             </div>
@@ -121,7 +121,7 @@
                 v-permission="permissionBtn.myETAPermission.myChart_edit"
                 class="span-item"
                 style="margin-left: 7px"
-                v-if="chartInfo.Button.IsEdit"
+                v-if="chartInfo.Button.IsEdit&&chartInfo.Source!==11"
                 @click="editChartHandle"
               >
                 <span> <i class="el-icon-edit" />&nbsp;<!-- 编辑 -->{{$t('Chart.chart_edit_btn')}} </span>
@@ -139,7 +139,7 @@
                 v-permission="permissionBtn.myETAPermission.myChart_otherSave"
                 class="span-item"
                 style="margin-left: 7px"
-                v-if="chartInfo.Button.IsCopy"
+                v-if="chartInfo.Button.IsCopy&&chartInfo.Source!==11"
                 @click="saveChartOtherHandle"
               >
                 <span> <i class="el-icon-document-add" />&nbsp;<!-- 另存为 -->{{$t('Chart.chart_copy_btn')}} </span>
@@ -195,6 +195,7 @@
                 class="span-item"
                 style="margin-left: 7px"
                 @click="openLangInfoDia"
+                v-if="chartInfo.Source!==11"
               >
                 <span> <img style="width: 16px;vertical-align: middle" :src="$icons.to_en" />&nbsp;<!-- 编辑信息 -->{{$t('Edb.detail_en_btn')}} </span>
               </span>
@@ -413,6 +414,7 @@
                 </template>
               </el-table-column>
               <el-table-column
+                v-if="chartInfo.Source!==11"
                 :label="$t('Table.column_operations')"
                 key="Copy"
                 align="center"
@@ -485,6 +487,7 @@
 </template>
 
 <script>
+import * as sheetInterface from "@/api/modules/sheetApi.js";
 import { dataBaseInterface,mychartInterface } from '@/api/api.js';
 import futuresInterface from '@/api/modules/futuresBaseApi';
 import chartRelevanceApi from '@/api/modules/chartRelevanceApi';
@@ -590,7 +593,7 @@ export default {
     },
     tableData: {
       handler(newval) {
-        newval.length && !this.chartInfo.WarnMsg && this.chartInfo.Source===1&& this.setChartOptionHandle(newval);
+        newval.length && !this.chartInfo.WarnMsg && [1,11].includes(this.chartInfo.Source)&& this.setChartOptionHandle(newval);
       },
       deep: true,
     },
@@ -640,7 +643,7 @@ export default {
           
           if(!this.chartInfo.HaveOperaAuth) return
 
-          if(this.chartInfo.Source===1) {
+          if([1,11].includes(this.chartInfo.Source)) {
             //处理下历史默认来源
             this.setDefaultSourceFrom();
             
@@ -750,6 +753,7 @@ export default {
    async getPreviewChartInfo() {
       let dateArray=this.chartInfo.ChartType==2?this.season_year:this.select_date
       let params = {
+        ChartSource:this.chartInfo.Source,
         ChartType: this.chartInfo.ChartType,
         DateType: this.year_select,
         StartDate: [5 , 6].includes(this.year_select)
@@ -870,6 +874,8 @@ export default {
         res=await statisticFeatureInterface.refreshChart({ ChartInfoId })
       }else if(Source===10) {
         res=await crossVarietyInterface.refreshChart({ ChartInfoId })
+      }else if(Source===11){
+        res=await sheetInterface.refreshCustomSheet({ChartInfoId});
       }
      
         this.refreshLoading = false;
@@ -1175,12 +1181,9 @@ export default {
     },
 
     /* 删除方法 */
-    delHandle(ChartInfoId) {
-      dataBaseInterface
-        .delChartClassify({
-          ChartInfoId,
-        })
-        .then((res) => {
+    async delHandle(ChartInfoId) {
+      const res=this.chartInfo.Source==11?await sheetInterface.delBalanceChart({ChartInfoId}):await dataBaseInterface.delChartClassify({ChartInfoId})
+
           if (res.Ret !== 200) return;
           this.$message.success(res.Msg);
           sessionStorage.removeItem('myChartbeforeOptions');
@@ -1195,7 +1198,7 @@ export default {
 
           // //只有一个图表且删除了 则展示缺省
           this.isNoChart = !this.allChart.length ? true : false;
-        });
+        
     },
 
     /* 转base64 */

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

@@ -209,7 +209,7 @@
                   />
                 </div>
                 <img
-                  :src="(chart.Source===1&&!chart.HaveOperaAuth) ? $icons.lock_big : chart.ChartImage"
+                  :src="([1,11].includes(chart.Source)&&!chart.HaveOperaAuth) ? $icons.lock_big : chart.ChartImage"
                   alt=""
                   class="chart-img"
                   @click="viewChartDetail(chart)"

+ 1 - 1
src/views/ppt_manage/mixins/pptMixins.js

@@ -225,7 +225,7 @@ export default {
       if(!Data) return 
       this.chartInfo = Data.ChartInfo;
       if(!this.chartInfo) return
-      if(this.chartInfo.Source === 1) { //常规图
+      if([1,11].includes(this.chartInfo.Source)) { //常规图
         //处理下历史默认来源
         this.setDefaultSourceFrom();
         

+ 1 - 0
src/views/system_manage/dataOperaAuth.vue

@@ -314,6 +314,7 @@ export default {
         { label: /* '自定义分析' */this.$t('SystemManage.OperateAuth.tab_sub_sheet1'), key: 4 },
         { label:/*  '时间序列表格' */this.$t('SystemManage.OperateAuth.tab_sub_sheet2'), key: 2 },
         { label: /* '混合表格' */this.$t('SystemManage.OperateAuth.tab_sub_sheet3'), key: 3 },
+        { label: /* '平衡表' */this.$t('SystemManage.OperateAuth.tab_sub_sheet4'), key: 5 },
       ]
 
       return this.currAuthSet===1 ? subTabs : subTabs.filter(_ => _.key!==4)