浏览代码

区间分析

mayday 7 月之前
父节点
当前提交
707a6a4662

+ 4 - 0
src/api/modules/intervalAnalysis.js

@@ -58,6 +58,10 @@ export default{
   chartAdd:params=>{
     return http.post('/range_analysis/chart_info/add',params)
   },
+  // 图表编辑
+  chartEdit:params=>{
+    return http.post('/range_analysis/chart_info/edit',params)
+  },
   // 图表详情
   chartInfo:params=>{
     return http.get('/range_analysis/chart_info/detail',params)

+ 2 - 2
src/components/chart/chartListTableWrap.vue

@@ -64,7 +64,7 @@ export default {
         {
           colKey: 'SysUserRealName',
           title: '创建人',
-          width:'120px'
+          width:'100px'
         },
         {
           colKey: 'CreateTime',
@@ -79,7 +79,7 @@ export default {
         {
           colKey: 'opt',
           title: '操作',
-          width:'220px'
+          width:'200px'
         },
       ]
     }

+ 129 - 33
src/views/intervalAnalysis/addChart.vue

@@ -29,17 +29,20 @@
         <div class="type-box">
           <span
             :class="['item', computedType == 0 ? 'active' : '']"
-            @click="computedType = 0"
+            @click="handleComputedTypeChange(0)"
             >单指标</span
           >
           <span
             :class="['item', computedType == 1 ? 'active' : '']"
-            @click="computedType = 1"
+            @click="handleComputedTypeChange(1)"
             >选择多指标</span
           >
         </div>
-        <!-- 单指标模块 -->
-        <singleEdbWrap ref="singleEdbWrap" />
+        <!-- 指标计算模块 -->
+        <edbComputedWrap 
+          :computedType="computedType"
+          @showBatchSelectEdb="handleShowBatchSelectEdb" 
+          ref="edbComputedWrap" />
       </div>
 
       <span class="move-btn resize" v-drag id="resize"></span>
@@ -81,12 +84,12 @@
               size="medium"
               type="primary" 
               class="year-btn"
-              @click="updateEdbHandle(entryType)" 
+              @click="updateEdbHandle" 
               @command="edbCommandHandle"
             >
               {{$t('StatisticAnalysis.ChartRelevance.update_edb')}}
               <el-dropdown-menu slot="dropdown">
-                <el-dropdown-item :command="{entryType,scence:'saveOther'}">{{$t('Table.save_as')}}</el-dropdown-item>
+                <el-dropdown-item :command="{scence:'saveOther'}">{{$t('Table.save_as')}}</el-dropdown-item>
               </el-dropdown-menu>
             </el-dropdown>
             <el-button
@@ -264,11 +267,19 @@
     <!-- 单指标计算保存指标 -->
     <saveSingleEdb 
       :isShow="showSingleEdbSave"
-      :singleEdbData="intervalAnalysisChartData"
+      :singleEdbData="singleEdbData"
       :tableData="tableData"
       @close="showSingleEdbSave = false"
     />
 
+    <!-- 多指标计算保存指标 -->
+    <saveMultipleEdb 
+      :isShow="showMultipleEdbSave"
+      :singleEdbData="singleEdbData"
+      :tableData="tableData"
+      @close="showMultipleEdbSave = false"
+    />
+
     <!-- 图表设置 -->
     <chartSetWrap 
       :isShow="showChartSet"
@@ -277,12 +288,29 @@
       :tableData="tableData"
       @close="showChartSet = false"
     />
+
+    <!-- 多指标选择 -->
+    <batchSelectEdb 
+      ref="batchSelectEdb"
+      :isShow="showBatchSelectEdb"
+      @close="showBatchSelectEdb=false"
+      @success="handleBatchSelectEdbSuccess"
+    />
+
+    <!-- 图表另存 -->
+    <SaveChartOther
+      :show.sync="isShowSaveOther"
+      fromType=""
+      source="interval_analysis"
+      :data="chartInfo"
+    />
+
   </div>
 </template>
 
 <script>
 import Chart from '@/views/dataEntry_manage/components/chart';
-import singleEdbWrap from './components/singleEdbWrap.vue';
+import edbComputedWrap from './components/edbComputedWrap.vue';
 import apiIntervalAnalysis from '@/api/modules/intervalAnalysis'
 import { chartSetMixin } from '@/views/dataEntry_manage/mixins/chartPublic';
 import edbTableSection from '@/views/chartRelevance_manage/crossVarietyAnalysis/components/edbTableSection.vue';
@@ -290,15 +318,21 @@ import DateChooseDia from '@/views/dataEntry_manage/components/DateChooseDia';
 import saveChart from './components/saveChart.vue'
 import saveSingleEdb from './components/saveSingleEdb.vue';
 import chartSetWrap from './components/chartSetWrap.vue'
+import batchSelectEdb from './components/batchSelectEdb.vue';
+import SaveChartOther from '@/views/dataEntry_manage/components/SaveChartOther';
+import saveMultipleEdb from './components/saveMultipleEdb.vue';
 export default {
   components: {
-    singleEdbWrap,
+    edbComputedWrap,
     Chart,
     edbTableSection,
     DateChooseDia,
     saveChart,
     saveSingleEdb,
-    chartSetWrap
+    chartSetWrap,
+    batchSelectEdb,
+    SaveChartOther,
+    saveMultipleEdb
   },
   directives: {
     drag(el, bindings) {
@@ -345,15 +379,40 @@ export default {
       showSingleEdbSave:false,//单指标计算保存指标
       singleEdbData:null,
 
+      showMultipleEdbSave:false,//多指标计算保存指标
+
       showChartSet:false,//图表设置
+
+      showBatchSelectEdb:false,//显示多指标选择
+
+      isShowSaveOther: false,//另存为
     }
   },
   methods: {
+    handleBatchSelectEdbSuccess(e){
+      this.$refs.edbComputedWrap.initMultipleEdbParams(e)
+    },
+    handleShowBatchSelectEdb(e){
+      this.$refs.batchSelectEdb.initData(e)
+      this.showBatchSelectEdb=true
+    },
+    handleComputedTypeChange(type){
+      if(this.$route.query.id&&type!==this.computedType){
+        this.$message.warning('编辑状态不允许切换计算类型')
+        return
+      }
+      this.computedType=type
+      if(type===1&&this.$refs.edbComputedWrap.edbList.length===0){
+        this.showBatchSelectEdb=true
+      }
+    },
     // 保存指标
     handleShowSaveEdb(){
+      this.singleEdbData=this.$refs.edbComputedWrap.getParams()
       if(this.computedType===0){
-        this.singleEdbData=this.$refs.singleEdbWrap.getParams()
         this.showSingleEdbSave=true
+      }else{
+        this.showMultipleEdbSave=true
       }
     },
 
@@ -361,10 +420,33 @@ export default {
       this.showChartSet=true
     },
 
-    // 保存图
+    //更新图
+    updateEdbHandle(){
+      const edbParams = this.$refs.edbComputedWrap.getParams()
+      const params = {
+        ChartEdbInfoList: edbParams.ChartEdbInfoList,
+        ExtraConfig: JSON.stringify(edbParams.ExtraConfig),
+        ChartClassifyId: this.chartInfo.ChartClassifyId,
+        ChartName: this.chartName,
+        ChartType: 1,
+        DateType: this.year_select,
+        ChartInfoId:Number(this.$route.query.id)
+      }
+      apiIntervalAnalysis.chartEdit(params).then(res => {
+        if (res.Ret === 200) {
+					this.$message.success(this.$t('MsgPrompt.saved_msg'))
+        }
+      })
+    },
+
+    //另存为
+    edbCommandHandle(e){
+      this.isShowSaveOther=true
+    },
+
+    // 新增图
     handleSaveChart(e) {
-      console.log(e);
-      const edbParams = this.$refs.singleEdbWrap.getParams()
+      const edbParams = this.$refs.edbComputedWrap.getParams()
       const params = {
         ChartEdbInfoList: edbParams.ChartEdbInfoList,
         ExtraConfig: JSON.stringify(edbParams.ExtraConfig),
@@ -375,16 +457,24 @@ export default {
       }
       apiIntervalAnalysis.chartAdd(params).then(res => {
         if (res.Ret === 200) {
-					this.$message.success('MsgPrompt.saved_msg')
+					this.$message.success(this.$t('MsgPrompt.saved_msg'))
           this.showSaveChart = false
+          setTimeout(() => {
+            this.$router.replace({
+              path:'/rangeAnalysis',
+              query:{
+                code:res.Data.UniqueCode,
+                id:res.Data.ChartInfoId
+              }
+            })
+          }, 1500);
         }
       })
     },
 
     //计算绘图
     async handleComputed() {
-
-      const edbParams = this.$refs.singleEdbWrap.getParams()
+      const edbParams = this.$refs.edbComputedWrap.getParams()
       const params = {
         ...edbParams,
         DateType: this.year_select,
@@ -408,18 +498,22 @@ export default {
     },
 
     initChartName(data) {
+      const calculateTypeMap={
+				0:'Average()',
+				1:'Sum()',
+				2:'Growth Rate()',
+				3:'Annualized Growth Rate()',
+				4:'Max()',
+				5:'Min()'
+			}
+      let edbName=''
       if (this.computedType === 0) {//单指标计算
-				const calculateTypeMap={
-					0:'Average()',
-					1:'Sum()',
-					2:'Growth Rate()',
-					3:'Annualized Growth Rate()',
-					4:'Max()',
-					5:'Min()'
-				}
-				const edbName=this.$i18nt.locale==='zh'?data.EdbInfoList[0].EdbName:data.EdbInfoList[0].EdbNameEn||data.EdbInfoList[0].EdbName
-				this.chartName=`${edbName}${calculateTypeMap[data.DataResp.CalculateType]}`
+				edbName=this.$i18nt.locale==='zh'?data.EdbInfoList[0].EdbName:data.EdbInfoList[0].EdbNameEn||data.EdbInfoList[0].EdbName
+				
+      }else{
+        edbName=data.DataResp.SeriesName
       }
+      this.chartName=`${edbName}${calculateTypeMap[data.DataResp.CalculateType]}`
     },
 
     /* 年份改变 重新刷新图表接口  保存当前的图表配置和上下限 只改变图表 */
@@ -494,9 +588,7 @@ export default {
       const {ChartInfo,DataResp,EdbInfoList}=data
       this.computedType=DataResp.EdbInfoMode
       this.chartName=this.$i18nt.locale==='zh'?ChartInfo.ChartName:ChartInfo.ChartNameEn
-      if(DataResp.EdbInfoMode===0){
-        this.$refs.singleEdbWrap.initData(data)
-      }
+      this.$refs.edbComputedWrap.initData(data)
     },
 
 
@@ -528,7 +620,7 @@ export default {
 }
 </script>
 
-<style lang="scss" scoped>
+<style lang="scss">
 .add-chart-page {
   .slide-icon {
     padding: 20px 0;
@@ -572,7 +664,7 @@ export default {
     }
     .left-content {
       padding: 20px;
-      max-height: calc(100vh - 190px);
+      max-height: calc(100% - 120px);
       overflow-y: auto;
       .type-box {
         .item {
@@ -763,6 +855,7 @@ export default {
         padding: 10px;
       }
       .year-btn,
+      .year-btn .el-button--medium,
       .btn-sty {
         font-size: $font-normal;
       }
@@ -778,13 +871,16 @@ export default {
       .min-data-input {
         margin-top: 230px;
       }
-      .year-btn {
+      .year-btn,.year-btn .el-button--medium {
         font-size: $font-small;
         margin-left: 5px;
         margin-right: 5px;
         margin-bottom: 5px;
         padding: 6px 12px;
       }
+      .year-btn .el-button--medium{
+        margin: 0 0px;
+      }
       .btn-sty {
         font-size: $font-small;
         margin-left: 5px;

+ 408 - 174
src/views/intervalAnalysis/components/batchSelectEdb.vue

@@ -1,217 +1,144 @@
 <template>
-  <el-dialog
-    :visible.sync="isShow"
-    :close-on-click-modal="false"
-    :modal-append-to-body="false"
-    @close="handleClose"
-    custom-class="batch-computed-dialog fit-screen-dialog"
-    center
-    top="5vh"
-    v-dialogDrag
-    title="批量选择指标"
-  >
+  <el-dialog :visible.sync="isShow" :close-on-click-modal="false" :modal-append-to-body="false" @close="handleClose" custom-class="batch-computed-dialog fit-screen-dialog" center top="5vh" v-dialogDrag title="批量选择指标">
     <div class="batch-computed-wrap">
       <div class="filter-wrap" style="margin-top: 20px">
-        <p style="margin-bottom: 10px">
-          {{ $t("EtaBasePage.pending_metrics", { num: 100 }) }}
-        </p>
+        <div style="position: relative;top: -20px;">
+          <el-radio-group v-model="edbType">
+            <el-radio :label="0" style="margin-right: 15px"><!-- ETA指标 -->{{ $t("Edb.eta_name") }}</el-radio>
+            <el-radio :label="1"><!-- ETA预测指标 -->{{ $t("Edb.eta_predictor_name") }}</el-radio>
+          </el-radio-group>
+        </div>
         <div>
-          <el-cascader
-            v-model="filter.classify"
-            :options="classifyOpt"
-            :props="classifyProps"
-            clearable
-            collapse-tags
-            :placeholder="$t('EtaBasePage.label_classify')"
-            style="width: 240px"
-            @change="handleFilter"
-          />
-          <el-select
-            v-model="filter.frequency"
-            :placeholder="$t('EtaBasePage.select_frequency')"
-            style="width: 140px"
-            clearable
-            multiple
-            collapse-tags
-            @change="handleFilter"
-            :disabled="[5, 61].includes(subComputedType)"
-          >
-            <el-option
-              v-for="item in frequencyArr"
-              :key="item.value"
-              :label="item.label"
-              :value="item.value"
-            >
+          <el-cascader key="isAssociativeSub" v-if="isAssociativeSub" v-model="filter.classify" :options="classifyOpt" :props="classifyProps" clearable collapse-tags :placeholder="$t('EtaBasePage.label_classify')" style="width: 200px" @change="handleFilter" />
+          <el-cascader key="notAssociativeSub" v-else v-model="filter.classify" :options="classifyOpt" :props="classifyProps" clearable collapse-tags :placeholder="$t('EtaBasePage.label_classify')" style="width: 200px" @change="handleFilter" />
+          <span>
+            <span>关联子分类</span>
+            <el-switch v-model="isAssociativeSub" @change="handleAssociativeSubChange"></el-switch>
+          </span>
+          <el-select v-model="filter.frequency" :placeholder="$t('EtaBasePage.select_frequency')" style="width: 140px" clearable multiple collapse-tags @change="handleFilter">
+            <el-option v-for="item in frequencyArr" :key="item.value" :label="item.value" :value="item.value">
             </el-option>
           </el-select>
-          <el-cascader
-            v-model="filter.user"
-            :placeholder="$t('EtaBasePage.table_col_creator')"
-            :options="sysUserOpts"
-            :props="sysUserProps"
-            collapse-tags
-            :show-all-levels="false"
-            clearable
-            filterable
-            style="width: 240px"
-            @change="handleFilter"
-          />
-          <el-input
-            :placeholder="$t('Edb.InputHolderAll.input_name_orid')"
-            v-model="filter.keyword"
-            style="width: 200px"
-            @keydown.enter.native="handleFilter"
-          >
+          <el-cascader v-model="filter.user" :placeholder="$t('EtaBasePage.table_col_creator')" :options="sysUserOpts" :props="sysUserProps" collapse-tags :show-all-levels="false" clearable filterable
+            style="width: 240px" @change="handleFilter" />
+          <el-input :placeholder="$t('Edb.InputHolderAll.input_name_orid')" v-model="filter.keyword" style="width: 200px" @keydown.enter.native="handleFilter">
             <i slot="prefix" class="el-input__icon el-icon-search"></i>
           </el-input>
-          <el-checkbox
-            :label="$t('EtaBasePage.label_all_check')"
-            v-model="isCheckAll"
-            :indeterminate="isCheckIndeterminate"
-            style="margin-left: 10px"
-            @change="listCheckAllChange"
-            :disabled="operationForm.view"
-          />
+          <el-checkbox :label="$t('EtaBasePage.label_all_check')" v-model="isCheckAll" :indeterminate="isCheckIndeterminate" style="margin-left: 10px" @change="listCheckAllChange" />
         </div>
       </div>
       <div class="table-wrap">
         <div class="left-box">
-          <el-table
-            :data="list"
-            border
-            @sort-change="sortChange"
-            @selection-change="selectionChange"
-            ref="edbDataRef"
-            @select="selectHandle"
-            @select-all="selectAllHandle"
-            height="500px"
-            v-loading="listLoading"
-          >
-            <el-table-column
-              type="selection"
-              min-width="50"
-              align="center"
-              :selectable="filterEdbAuth"
-            />
-            <el-table-column
-              :label="$t('EtaBasePage.full_metric_name')"
-              show-overflow-tooltip
-              align="center"
-              :prop="$parent.currentLang === 'en' ? 'EdbNameEn' : 'EdbName'"
-            />
-            <el-table-column
-              :label="$t('Edb.Detail.e_latest_date')"
-              align="center"
-              prop="EndDate"
-              width="120px"
-            />
-            <el-table-column
-              :label="$t('Edb.Detail.e_latest_value')"
-              align="center"
-              show-overflow-tooltip
-              prop="EndValue"
-              width="80px"
-            />
-            <el-table-column
-              :label="$t('EtaBasePage.table_col_creator')"
-              align="center"
-              show-overflow-tooltip
-              prop="SysUserRealName"
-              width="80px"
-            />
-            <el-table-column
-              :label="$t('Edb.Detail.e_fre')"
-              align="center"
-              prop="Frequency"
-              width="50px"
-            >
+          <el-table :data="list" border @sort-change="sortChange" @selection-change="selectionChange" ref="edbDataRef" @select="selectHandle" @select-all="selectAllHandle" height="500px" v-loading="listLoading">
+            <el-table-column type="selection" min-width="50" align="center" :selectable="filterEdbAuth" />
+            <el-table-column :label="$t('EtaBasePage.full_metric_name')" show-overflow-tooltip align="center" :prop="$parent.currentLang === 'en' ? 'EdbNameEn' : 'EdbName'" />
+            <el-table-column :label="$t('Edb.Detail.e_latest_date')" align="center" prop="EndDate" width="120px" />
+            <el-table-column :label="$t('Edb.Detail.e_latest_value')" align="center" show-overflow-tooltip prop="EndValue" width="80px" />
+            <el-table-column :label="$t('EtaBasePage.table_col_creator')" align="center" show-overflow-tooltip prop="SysUserRealName" width="80px" />
+            <el-table-column :label="$t('Edb.Detail.e_fre')" align="center" prop="Frequency" width="50px">
               <template slot-scope="scope">
                 <span>{{ getFrequencyTrans(scope.row.Frequency) }}</span>
               </template>
             </el-table-column>
-            <el-table-column
-              :label="$t('Edb.Detail.e_unit')"
-              show-overflow-tooltip
-              align="center"
-              :prop="$parent.currentLang === 'en' ? 'UnitEn' : 'Unit'"
-              width="50px"
-            >
+            <el-table-column :label="$t('Edb.Detail.e_unit')" show-overflow-tooltip align="center" :prop="$parent.currentLang === 'en' ? 'UnitEn' : 'Unit'" width="50px">
               <template slot-scope="scope">
                 <span>{{ getUnitTrans(scope.row.Unit) }}</span>
               </template>
             </el-table-column>
           </el-table>
-          <m-page
-            style="margin-top: 10px"
-            class="table-page"
-            v-show="total"
-            :total="total"
-            :pageSize="pageSize"
-            :page_no="page"
-            :pagercount="5"
-            @handleCurrentChange="pageNumberChange"
-          />
+          <m-page style="margin-top: 10px" class="table-page" v-show="total" :total="total" :pageSize="pageSize" :page_no="page" :pagercount="5" @handleCurrentChange="pageNumberChange" />
         </div>
         <div style="padding-top: 200px; margin: 0 30px">
-          <el-button
-            type="primary"
-            :disabled="operationForm.view"
-            :loading="addLoading"
-            @click="getAddEdbListData"
-          >
-            <!-- 加入已选指标 -->
+          <el-button type="primary" :loading="addLoading" @click="getAddEdbListData">
             {{ $t("EtaBasePage.add_to_selections") }}
           </el-button>
         </div>
         <div class="right-box">
           <el-table :data="selectList" border height="500px">
-            <el-table-column
-              :label="$t('EtaBasePage.full_metric_name')"
-              show-overflow-tooltip
-              align="center"
-              :prop="$parent.currentLang === 'en' ? 'EdbNameEn' : 'EdbName'"
-            />
-            <el-table-column
-              width="50px"
-              align="center"
-              v-if="!operationForm.view"
-            >
+            <el-table-column :label="$t('EtaBasePage.full_metric_name')" show-overflow-tooltip align="center" :prop="$parent.currentLang === 'en' ? 'EdbNameEn' : 'EdbName'" />
+            <el-table-column width="50px" align="center">
               <template slot="header" slot-scope="scope">
-                <img
-                  @click="handleDelSelect('all')"
-                  style="width: 15px; height: 15px; cursor: pointer"
-                  src="~@/assets/img/ai_m/delete.png"
-                  alt=""
-                />
+                <img @click="handleDelSelect('all')" style="width: 15px; height: 15px; cursor: pointer" src="~@/assets/img/ai_m/delete.png" alt="" />
               </template>
               <template slot-scope="scope">
-                <img
-                  @click="handleDelSelect(scope)"
-                  style="width: 15px; height: 15px; cursor: pointer"
-                  src="~@/assets/img/ai_m/delete.png"
-                  alt=""
-                />
+                <img @click="handleDelSelect(scope)" style="width: 15px; height: 15px; cursor: pointer" src="~@/assets/img/ai_m/delete.png" alt="" />
               </template>
             </el-table-column>
           </el-table>
         </div>
       </div>
       <div style="text-align: center; margin: 60px 0 40px 0">
-        <el-button type="primary" plain @click="handleCloseSelf">{{
+        <el-button type="primary" plain @click="handleClose">{{
           $t("Dialog.cancel_btn")
         }}</el-button>
-        <el-button type="primary" @click="handleNextStep">{{
-          $t("Dialog.next_step")
-        }}</el-button>
+        <el-button type="primary" @click="handleNextStep">{{ $t("Dialog.confirm_btn") }}</el-button>
+        <div style="float:right;width: 300px;display: flex;align-items: center;">
+          <span style="flex-shrink: 0;">指标系列名称</span>
+          <el-input v-model="seriesName"></el-input>
+        </div>
       </div>
     </div>
   </el-dialog>
 </template>
 
 <script>
+import { dataBaseInterface, departInterence } from '@/api/api.js';
+import mPage from '@/components/mPage.vue'
 export default {
+  components:{mPage},
+  props: {
+    isShow: {
+      type: Boolean,
+      default: false
+    },
+  },
+  computed: {
+    frequencyArr() {
+      return [
+        {
+          value: '日度',
+          label: /* '日度'  */this.$t('Edb.FreAll.day'),
+        },
+        {
+          value: '周度',
+          label: /* '周度' */this.$t('Edb.FreAll.week'),
+        },
+        {
+          value: '旬度',
+          label: /* '旬度' */this.$t('Edb.FreAll.dekad'),
+        },
+        {
+          value: '月度',
+          label: /* '月度' */this.$t('Edb.FreAll.month'),
+        },
+        {
+          value: '季度',
+          label: /* '季度' */ this.$t('Edb.FreAll.quarter'),
+        },
+
+        {
+          value: '年度',
+          label: /* '年度' */ this.$t('Edb.FreAll.year'),
+        }
+      ]
+    },
+    classifyProps(){
+      return {
+        label: 'ClassifyName',
+        value: 'ClassifyId',
+        children: 'Children',
+        multiple: true,
+        emitPath: false,
+        checkStrictly:!this.isAssociativeSub
+      }
+    }
+  },
   data() {
     return {
+      MAXAddNUM:100,
+
+      edbType: 0,//0指标库 1预测指标库
+
       select_target: '',
       searchOptions: [],//指标列表
       search_have_more: false,
@@ -225,14 +152,8 @@ export default {
         keyword: ''
       },
 
+      isAssociativeSub: true,//是否关联子分类
       classifyOpt: [],
-      classifyProps: {
-        label: 'ClassifyName',
-        value: 'ClassifyId',
-        children: 'Children',
-        multiple: true,
-        emitPath: false
-      },
       sysUserOpts: [],
       sysUserProps: {
         value: "AdminId",
@@ -259,10 +180,323 @@ export default {
       selectList: [],//添加到右侧的数据
       addLoading: false,
 
+      seriesName:'Series',
+
     }
   },
+  mounted() {
+    this.getClassifyOpt()
+    this.getSysUserList()
+    this.getEDBList()
+  },
+  methods: {
+    initData(e){
+      this.selectList=e.edbList
+      this.seriesName=e.seriesName
+    },
+    handleNextStep(){
+      if(this.selectList.length===0){
+        this.$message.warning(/* "请选择指标"  */this.$t('Edb.InputHolderAll.input_select_edb'))
+        return
+      }
+      if(!this.seriesName){
+        this.$message.warning(this.$t('Chart.Vailds.serie_name_msg'))
+        return
+      }
+      this.$emit('success',{
+        seriesName:this.seriesName,
+        edbList:this.selectList
+      })
+      this.$emit('close')
+    },
+
+
+    handleClose() {
+      this.$emit('close')
+    },
+
+    handleAssociativeSubChange(){
+      this.filter.classify=''
+    },
+
+    // 点击加入已选指标库
+    async getAddEdbListData() {
+      if (!(this.isCheckAll || this.isCheckIndeterminate) || (!(this.list && this.list.length > 0))) {
+        this.$message.warning(/* "请选择指标"  */this.$t('Edb.InputHolderAll.input_select_edb'))
+        return
+      }
+      if (this.selectList.length >= this.MAXAddNUM) {
+        this.$message.warning(/* "已达批量添加指标数量上限"  */this.$t('EtaBasePage.limit_indicators_msg'))
+        return
+      }
+      const params = {
+        SysUserIds: this.filter.user ? this.filter.user.join(',') : '',
+        ClassifyIds: this.filter.classify ? this.filter.classify.join(',') : '',
+        Keyword: this.filter.keyword,
+        Frequency: this.filter.frequency ? this.filter.frequency.join(',') : '',
+        SelectAll: this.checkAllStatus,
+        EdbInfoIds: this.tableDataCheckedList.join(',')
+      }
+      this.addLoading = true
+      const res = await dataBaseInterface.getBatchFilterAddEdbList(params)
+      this.addLoading = false
+      if (res.Ret != 200) return
+      // 加入到已选指标中 要去重
+      const arr = res.Data.SearchItem || []
+      const temArr = this.mergeAndDistinct(this.selectList, arr)
+      // 截取数组 防止数量溢出
+      this.selectList = temArr.filter(_ => _.HaveOperaAuth).slice(0, this.MAXAddNUM)
+    },
+    mergeAndDistinct(arr1, arr2) {
+      // 合并两个数组
+      const mergedArray = arr1.concat(arr2);
+
+      // 根据 EdbInfoId 字段进行去重
+      const distinctArray = mergedArray.filter((item, index, self) => {
+        return index === self.findIndex(t => t.EdbInfoId === item.EdbInfoId);
+      });
+
+      return distinctArray;
+    },
+
+    // 删除已选指标库指标
+    handleDelSelect(e) {
+      if (this.operationForm.view) return
+      if (e === 'all') {
+        this.selectList = []
+        return
+      }
+      const index = e.$index
+      this.selectList.splice(index, 1)
+    },
+
+    filterNodes(arr) {
+      arr.length &&
+        arr.forEach((item) => {
+          item.Children.length && this.filterNodes(item.Children);
+          if (!item.Children.length) {
+            delete item.Children;
+          }
+        });
+    },
+
+    // 获取指标分类
+    async getClassifyOpt() {
+      const res = await dataBaseInterface.menuListV3()
+      if (res.Ret !== 200) return
+      this.filterNodes(res.Data.AllNodes || []);
+      this.classifyOpt = res.Data.AllNodes || [];
+    },
+
+    // 获取所有系统用户
+    async getSysUserList() {
+      const res = await departInterence.getQuestionAdminList();
+      if (res.Ret === 200) {
+        this.sysUserOpts = res.Data.List || [];
+      }
+    },
+
+    // 获取指标列表
+    async getEDBList(type) {
+      this.listLoading = true
+      const res = await dataBaseInterface.getBatchAddEdbSearchList({
+        CurrentIndex: this.page,
+        PageSize: this.pageSize,
+        SysUserIds: this.filter.user ? this.filter.user.join(',') : '',
+        ClassifyIds: this.filter.classify ? this.filter.classify.join(',') : '',
+        Keyword: this.filter.keyword,
+        Frequency: this.filter.frequency ? this.filter.frequency.join(',') : '',
+      })
+      this.listLoading = false
+      if (res.Ret === 200) {
+        this.list = res.Data.SearchItem || []
+        this.total = res.Data.Paging.Totals || 0
+
+        if (this.list.length > 0) {
+          this.tableDataIds = this.list.map(it => it.EdbInfoId)
+        } else {
+          this.tableDataIds = []
+        }
+
+        if (type == 'adjustSelection') {
+          this.adjustSelection()
+        } else {
+
+          this.isCheckAll = false
+          this.checkAllStatus = false
+          this.isCheckIndeterminate = false
+
+          this.listCheckAllChange(this.isCheckAll)
+        }
+      }
+    },
+
+    pageNumberChange(e) {
+      this.page = e
+      this.getEDBList('adjustSelection')
+    },
+
+    handleFilter(e) {
+      this.page = 1
+      this.list = []
+      this.getEDBList()
+    },
+
+    // 切换列表全选按钮状态
+    listCheckAllChange(check) {
+      this.tableDataCheckedList = []
+      this.checkAllStatus = check
+      if (check) {
+        // 全选
+        this.$refs.edbDataRef && this.$refs.edbDataRef.clearSelection()
+        this.$refs.edbDataRef && this.$refs.edbDataRef.toggleAllSelection()
+      } else {
+        //全不选
+        this.$refs.edbDataRef && this.$refs.edbDataRef.clearSelection()
+      }
+    },
+
+    selectionChange(val) {
+      if (this.selectionReactCancel) return
+
+      // selectAllHandle的触发在selectionChange后面,将selectionChange的逻辑延迟一下
+      setTimeout(() => {
+        // 去重
+        let duplicateArr = Array.from(new Set(this.tableDataCheckedList))
+
+        if ((duplicateArr.length == this.total && (!this.checkAllStatus))
+          || (duplicateArr.length == 0 && this.checkAllStatus)) {
+          this.isCheckAll = true
+          this.isCheckIndeterminate = false
+        } else if ((duplicateArr.length == 0 && (!this.checkAllStatus))
+          || (duplicateArr.length == this.total && this.checkAllStatus)) {
+          this.isCheckAll = false
+          this.isCheckIndeterminate = false
+        } else {
+          this.isCheckAll = false
+          this.isCheckIndeterminate = true
+        }
+      }, 1)
+
+    },
+
+    //用户手动勾选数据行的 Checkbox 时触发的事件	
+    selectHandle(selection, row) {
+      if (this.selectionReactCancel) return
+
+      let check = false
+      if (selection.some(it => it.EdbInfoId == row.EdbInfoId)) {
+        // 勾选
+        // 勾选
+        if (this.checkAllStatus) {
+          check = false
+        } else {
+          check = true
+        }
+      } else {
+        // 取消勾选
+        if (this.checkAllStatus) {
+          check = true
+        } else {
+          check = false
+        }
+      }
+      if (check) {
+        this.tableDataCheckedList.push(row.EdbInfoId)
+      } else {
+        this.tableDataCheckedList = this.tableDataCheckedList.filter(it => it != row.EdbInfoId)
+      }
+    },
+
+    // 用户手动勾选全选 Checkbox 时触发的事件
+    selectAllHandle(selection) {
+      if (this.selectionReactCancel) return
+      let check = false; // 从tableDataCheckedList 添加还是删除
+      if (selection && selection.length > 0) {
+        // 全选
+        if (this.checkAllStatus) {
+          check = false
+        } else {
+          check = true
+        }
+      } else {
+        // 全不选
+        if (this.checkAllStatus) {
+          check = true
+        } else {
+          check = false
+        }
+      }
+      if (check) {
+        this.tableDataCheckedList = [...this.tableDataCheckedList, ...this.tableDataIds]
+      } else {
+        this.tableDataCheckedList = this.tableDataCheckedList.filter(it => !this.tableDataIds.includes(it))
+      }
+    },
+
+    adjustSelection() {
+      this.selectionReactCancel = true
+      if (!this.checkAllStatus) {
+        this.tableDataCheckedList.map(it => {
+          let row = this.list.find(da => da.EdbInfoId == it)
+          if (row) {
+            setTimeout(() => {
+              this.$refs.edbDataRef.toggleRowSelection(row, true)
+            }, 10)
+          }
+        })
+      } else {
+        this.$refs.edbDataRef.toggleAllSelection()
+        this.tableDataCheckedList.map(it => {
+          let row = this.list.find(da => da.EdbInfoId == it)
+          if (row) {
+            setTimeout(() => {
+              this.$refs.edbDataRef.toggleRowSelection(row, false)
+            }, 50)
+          }
+        })
+      }
+      setTimeout(() => {
+        this.selectionReactCancel = false
+      }, 50)
+    },
+
+    filterEdbAuth(row) {
+      return row.HaveOperaAuth
+    }
+  }
 }
 </script>
 
-<style>
+<style lang="scss">
+.batch-computed-dialog {
+  max-width: 1200px;
+  width: 90vw;
+  overflow: hidden;
+
+  .el-input {
+    width: 100%;
+  }
+}
+
+.batch-computed-wrap {
+  .type-wrap {
+    display: flex;
+  }
+
+  .table-wrap {
+    margin-top: 20px;
+    display: flex;
+    justify-content: space-between;
+
+    .left-box {
+      width: 50%;
+    }
+
+    .right-box {
+      flex: 1;
+      flex-shrink: 0;
+    }
+  }
+}
 </style>

+ 30 - 2
src/views/intervalAnalysis/components/chartSetWrap.vue

@@ -45,7 +45,7 @@
           </div>
           <div class="item-box" v-for="item,index in seriesArr" :key="item.EdbInfoId">
             <div class="label-box">
-              <div class="line-box"></div>
+              <div class="line-box" :style="getLineColor(item,index)"></div>
             </div>
             <div class="content-box">
               <el-input
@@ -100,6 +100,7 @@
 
 <script>
 import * as chartThemeInterface from '@/api/modules/chartThemeApi';
+import { defaultOpts } from '@/utils/defaultOptions'
 export default {
   props: {
     isShow: {
@@ -110,11 +111,22 @@ export default {
     chartInfo: {},
     tableData: [],
   },
+  computed: {
+    colorArr(){
+      const defaultColors=defaultOpts.colors
+      let themeColors=[]
+      if(this.chartInfo&&this.chartInfo.ChartThemeStyle){
+        themeColors=JSON.parse(this.chartInfo.ChartThemeStyle).colorsOptions||[]
+      }
+      return themeColors.length>0?themeColors:defaultColors
+    }
+  },
   watch: {
     isShow(n){
       if(n){
         this.formData.name=this.chartName
-        this.seriesArr=this.tableData||[]
+        const temArr=this.tableData||[]
+        this.seriesArr=JSON.parse(JSON.stringify(temArr))
         this.getThemeList()
       }
     }
@@ -141,6 +153,18 @@ export default {
       this.$emit("close");
     },
 
+    getLineColor(item,index){
+      let color=''
+      if(item.ChartColor){
+        color=item.ChartColor
+      }else{
+        const lineIndex=index%this.colorArr.length
+        color=this.colorArr[lineIndex]
+      }
+      
+      return {backgroundColor:color}
+    },
+
     /* 获取主题列表  type init时重新设置默认样式和主题*/
     async getThemeList(type = null) {
       let res = await chartThemeInterface.getThemeBySource({ ChartType: this.chartInfo.ChartType, Source: 1 })
@@ -174,6 +198,10 @@ div{
         width: 100px;
         padding-right: 12px;
         text-align: right;
+        .line-box{
+          width: 100%;
+          height: 2px;
+        }
       }
       .content-box{
         flex: 1;

+ 82 - 14
src/views/intervalAnalysis/components/singleEdbWrap.vue → src/views/intervalAnalysis/components/edbComputedWrap.vue

@@ -1,6 +1,6 @@
 <template>
   <div class="single-edb-wrap">
-    <div class="search-cont section">
+    <div class="search-cont section" v-if="computedType===0">
       <div>
         <label><!-- 选择指标 -->{{ $t("Edb.choose_edb") }}:</label>
         <el-radio-group v-model="edbFromType">
@@ -54,7 +54,7 @@
       </el-select>
     </div>
     <!-- 区间划分 -->
-    <div class="item-box section">
+    <div class="item-box section" v-if="computedType===0">
       <span class="label">区间划分</span>
       <div class="con-box">
         <el-select v-model="dateRangeType" style="width: 90%">
@@ -67,6 +67,12 @@
         </el-select>
       </div>
     </div>
+    <!-- 多指标计算 -->
+    <div class="multiple-box" v-if="computedType===1&&edbList.length>0">
+      <div class="name">{{seriesName}}</div>
+      <img class="icon" src="~@/assets/img/icons/edit_blue_new.png" alt="" @click="handleShowEditBatchSelectEbd">
+      <img class="icon" src="~@/assets/img/icons/delete-red.png" alt="" @click="handleDelBatchSelectEbd">
+    </div>
     <!-- 智能划分模块 -->
     <template v-if="dateRangeType === 0">
       <!-- 起始日期 -->
@@ -390,6 +396,9 @@ import * as preDictEdbInterface from '@/api/modules/predictEdbApi.js';
 import dateMoveWaySec from '@/views/datasheet_manage/components/dateMoveWaySection.vue'
 
 export default {
+  props:{
+    computedType:0,//类型 0单指标 1多指标
+  },
   components: { dateMoveWaySec },
   computed: {
     // 区间划分类型选项数据
@@ -507,26 +516,58 @@ export default {
       yearDateEnd: '',//跨年划分后一年
 
 
+      edbList:[],//多指标计算时 选择的指标数据
+      seriesName:'',//多指标计算时填写的名称
+
 
     }
   },
   methods: {
-    // 
-    getParams() {
-      this.startDateConfig.dateTransfData=this.$refs.startDateMoveWaySec.dateChangeArr||[]
-      this.endDateConfig.dateTransfData=this.$refs.endDateMoveWaySec.dateChangeArr||[]
+    // 更新多指标计算时的数据
+    initMultipleEdbParams(data){
+      this.dateRangeType=0
+      this.edbList=data.edbList
+      this.seriesName=data.seriesName
+    },
+    handleShowEditBatchSelectEbd(){
+      this.$emit('showBatchSelectEdb',{
+        edbList:this.edbList,
+        seriesName:this.seriesName
+      })
+    },
+    handleDelBatchSelectEbd(){
+      this.edbList=[]
+      this.seriesName=''
+    },
 
-      const params = {
-        ChartEdbInfoList: [
-          {
-            EdbInfoId: this.edbInfoId||0,
+    // 获取参数
+    getParams() {
+      if(this.dateRangeType===0){
+        this.startDateConfig.dateTransfData=this.$refs.startDateMoveWaySec.dateChangeArr||[]
+        this.endDateConfig.dateTransfData=this.$refs.endDateMoveWaySec.dateChangeArr||[]
+      }
+      let _EdbAliasName=''
+      if(this.computedType===0){
+        const selectItem=this.searchOptions.find(i=>i.EdbInfoId===this.edbInfoId)
+        _EdbAliasName=this.$i18nt.locale==='zh'?selectItem.EdbName:selectItem.EdbNameEn
+      }
+      
+      const edbList=this.computedType===0?[{
+            EdbInfoId: this.edbInfoId,
             IsAxis: 1,
-            EdbAliasName: '',
-          }
-        ],
+            EdbAliasName: _EdbAliasName,
+          }]:this.edbList.map(_i=>{
+            return {
+              EdbInfoId: _i.EdbInfoId,
+              IsAxis: 1,
+              EdbAliasName: this.$i18nt.locale==='zh'?_i.EdbName:_i.EdbNameEn,
+            }
+          })
+      const params = {
+        ChartEdbInfoList: edbList,
 
         ExtraConfig:{
-          EdbInfoMode: 0,//指标模式 0: 单指标,1: 多指标
+          EdbInfoMode: this.computedType,//指标模式 0: 单指标,1: 多指标
           DateRangeType: this.dateRangeType,
           AutoDateConf: {//智能划分数据
             IsAutoStartDate: this.startDateConfig.startDateType,
@@ -566,6 +607,7 @@ export default {
             Value: this.dataConvert.value,
             Unit: this.dataConvert.unit
           },
+          SeriesName:this.seriesName
         }
       }
 
@@ -655,6 +697,17 @@ export default {
       this.yearDateStart=DataResp.YearDateConf.StartDay
       this.yearDateEnd=DataResp.YearDateConf.EndDay
 
+      if(DataResp.EdbInfoMode===1){//多指标计算
+        this.seriesName=DataResp.SeriesName
+        this.edbList=EdbInfoList.map(_i=>{
+          return _i
+        })
+      }else{
+        this.edbInfoId=EdbInfoList[0].EdbInfoId
+        this.edbFromType=EdbInfoList[0].EdbInfoType
+        this.searchOptions=EdbInfoList||[]
+      }
+
     },
   },
 }
@@ -681,6 +734,21 @@ export default {
       flex: 1;
     }
   }
+  .multiple-box{
+    background-color: #f5f5f5;
+    display: flex;
+    align-items: center;
+    padding: 10px;
+    .name{
+      flex: 1;
+    }
+    .icon{
+      width: 20px;
+      height: 20px;
+      margin-left: 5px;
+      cursor: pointer;
+    }
+  }
 }
 </style>
 <style lang="scss">

+ 165 - 0
src/views/intervalAnalysis/components/saveMultipleEdb.vue

@@ -0,0 +1,165 @@
+<template>
+	<el-dialog :modal-append-to-body="false" title="保存指标" :visible.sync="isShow" :close-on-click-modal="false" @close="cancelHandle" center v-dialogDrag>
+		<div class="save-chart-wrap">
+			<el-table :data="list" border height="500px">
+				<el-table-column :label="$t('EtaBasePage.full_metric_name')" align="center" :prop="$parent.currentLang === 'en' ? 'EdbNameEn' : 'EdbName'" />
+				<el-table-column :label="$t('EtaBasePage.gen_metric_name_label')" align="center">
+					<template slot-scope="scope">
+						<el-input v-model="scope.row.name" :placeholder="$t('EtaBasePage.metric_name_input')" style="width:100%" />
+					</template>
+				</el-table-column>
+				<el-table-column label="单位" align="center" width="200px">
+					<template slot-scope="scope">
+						<selectUnit v-model="scope.row.unit" />
+					</template>
+				</el-table-column>
+				<el-table-column :label="$t('Edb.Detail.e_fre')" align="center" width="200px">
+					<template slot-scope="scope">
+						<el-select v-model="scope.row.frequency" :placeholder="$t('EtaBasePage.select_frequency')" @change="handleFrequencyChange(scope)">
+							<el-option v-for="item in frequencyArr" :key="item" :label="item" :value="item">
+							</el-option>
+						</el-select>
+					</template>
+				</el-table-column>
+				<el-table-column align="center" width="300px">
+					<template slot="header" slot-scope="scope">
+						<span style="margin-right:40px;display:inline-block"> <!-- 目录 -->{{ $t('EtaBasePage.catalogue_directory') }}</span>
+						<el-radio-group v-model="classifyType" @change="handleClassifyTypeChange">
+							<el-radio :label="0"><!-- 分目录 -->{{ $t('EtaBasePage.subdirectory_radio') }}</el-radio>
+							<el-radio :label="1"><!-- 同目录 -->{{ $t('EtaBasePage.directory_radio') }}</el-radio>
+						</el-radio-group>
+					</template>
+					<template slot-scope="{row,$index}">
+						<el-cascader v-model="row.classify" :options="classifyOpt" :props="classifyProps" :placeholder="$t('Edb.InputHolderAll.input_menu')" @change="handleClassifyChange(row, $index)" />
+					</template>
+				</el-table-column>
+			</el-table>
+
+			<div class="dia-bot">
+				<el-button type="primary" style="margin-right: 20px" @click="saveHandle"><!-- 保存 -->{{ $t("Dialog.confirm_save_btn") }}</el-button>
+				<el-button type="primary" plain @click="cancelHandle"><!-- 取消 -->{{ $t("Dialog.cancel_btn") }}</el-button>
+			</div>
+		</div>
+	</el-dialog>
+</template>
+
+<script>
+import { dataBaseInterface } from "@/api/api.js";
+import apiIntervalAnalysis from "@/api/modules/intervalAnalysis";
+import * as preDictEdbInterface from '@/api/modules/predictEdbApi.js';
+import { frequencyArr } from "@/views/dataEntry_manage/databaseComponents/util";
+export default {
+	props: {
+		isShow: {
+			type: Boolean,
+			default: false,
+		},
+		tableData: [],
+		singleEdbData: {},
+	},
+	watch: {
+		isShow(n) {
+			if (n) {
+				const edbData = this.tableData || [];
+				if (edbData) {
+					const calculateTypeMap = {
+						0: "Average()",
+						1: "Sum()",
+						2: "Growth Rate()",
+						3: "Annualized Growth Rate()",
+						4: "Max()",
+						5: "Min()",
+					};
+					this.list=edbData.map(item=>{
+						return {
+							EdbName:item.EdbName,
+							EdbNameEn:item.EdbNameEn,
+							name:`${this.$i18nt.locale === "zh" ? item.EdbName : item.EdbNameEn}${calculateTypeMap[this.singleEdbData.ExtraConfig.CalculateType]}`,
+							unit:item.Unit,
+							frequency:item.Frequency,
+							classify:''
+						}
+					})
+
+
+					this.getClassifyOpts();
+				}
+			}
+		},
+	},
+	data() {
+		return {
+			list: [],
+			classifyType:1,
+
+			classifyOpts: [],
+			classifyProps: {
+				label: "ClassifyName",
+				value: "ClassifyId",
+				children: "Children",
+				checkStrictly: true,
+				emitPath: false,
+			},
+			frequencyArr,
+		};
+	},
+	methods: {
+		async saveHandle() {
+			await this.$refs.diaForm.validate();
+		},
+
+		cancelHandle() {
+			this.$emit("close");
+		},
+
+		// 递归改变第三级目录结构
+		filterNodes(arr) {
+			arr.length &&
+				arr.forEach((item) => {
+					item.Children.length && this.filterNodes(item.Children);
+					if (!item.Children.length) {
+						delete item.Children;
+					}
+				});
+		},
+
+		async getClassifyOpts() {
+			const res=await dataBaseInterface.menuListV3();
+			// const res = this.tableData[0].EdbInfoType === 1 ? await preDictEdbInterface.classifyListV2() : await dataBaseInterface.menuListV3();
+			if (res.Ret === 200) {
+				this.filterNodes(res.Data.AllNodes || []);
+				this.classifyOpts = res.Data.AllNodes || [];
+			}
+		},
+	},
+};
+</script>
+
+<style lang="scss">
+.el-dialog{
+	max-width: 1200px;
+  width: 90vw;
+}
+.save-chart-wrap {
+	.el-input {
+		width: 100%;
+	}
+	.el-input{
+        input{
+            border: none;
+            text-align: center;
+        }
+    }
+    .el-table tr{
+        background-color: #fff !important;
+        &:hover>td{
+            background-color: transparent !important; /* 或者其他想要的颜色值 */
+        }
+    }
+
+	.dia-bot {
+		margin: 30px 0;
+		text-align: center;
+	}
+}
+</style>

+ 1 - 0
src/views/intervalAnalysis/components/saveSingleEdb.vue

@@ -64,6 +64,7 @@
 <script>
 import { dataBaseInterface } from '@/api/api.js';
 import apiIntervalAnalysis from '@/api/modules/intervalAnalysis'
+import * as preDictEdbInterface from '@/api/modules/predictEdbApi.js';
 import { frequencyArr } from '@/views/dataEntry_manage/databaseComponents/util'
 export default {
   props: {

+ 2 - 1
src/views/intervalAnalysis/mixin/leftMixin.js

@@ -135,7 +135,8 @@ export default {
 
     /* 根据unicode展开树结构并选中当前图表 重置图表配置 日期区间 */
     selectCurrentNode({ code, id, type }) {
-      
+      this.select_id=id
+	  
     },
 
     // 递归节点