jwyu 1 жил өмнө
parent
commit
c54e7bd326

+ 13 - 0
src/api/modules/chartApi.js

@@ -410,6 +410,14 @@ const dataBaseInterface = {
 	edbAddBatch: params => {
 		return http.post('/datamanage/edb_info/batch/add',params)
 	},
+	// 批量计算指标时获取当前筛选条件下选择的指标
+	getBatchFilterAddEdbList:params=>{
+		return http.get('/datamanage/edb_info/calculate/multi/choice',params)
+	},
+	//批量计算指标时待选指标的搜索列表
+	getBatchAddEdbSearchList:params=>{
+		return http.get('/datamanage/edb_info/calculate/multi/search',params)
+	},
 	//========================================chart
 	// /**
 	//  * 
@@ -839,6 +847,11 @@ const dataBaseInterface = {
 		return http.post('/datamanage/edb_info/calculate/batch/save/batch',params)
 	},
 
+	//批量计算编辑
+	batchCalculateTargetEdit: params => {
+		return http.post('/datamanage/edb_info/calculate/batch/edit/batch',params)
+	},
+
 	/**
 	 * 获取计算指标与基础指标关联信息
 	 * @param EdbInfoId

+ 356 - 0
src/views/dataEntry_manage/databaseComponents/batchComputedSave.vue

@@ -0,0 +1,356 @@
+<template>
+    <div class="batch-computed-save-wrap">
+        <el-table 
+            :data="list" 
+            border 
+            height="500px"
+        >
+            <el-table-column label="指标全称" align="center" prop="EdbName"/>
+            <el-table-column label="生成指标名称" align="center">
+                <template slot-scope="scope">
+                    <el-input :disabled="operationForm.view" v-model="scope.row.name" placeholder="请填写指标名称" style="width:100%"/>
+                </template>
+            </el-table-column>
+            <el-table-column label="单位" align="center" width="200px">
+                <template slot-scope="scope">
+                    <selectUnit :disabled="operationForm.view||[6].includes(sourceTypeVal)" v-model="scope.row.unit"/>
+                </template>
+            </el-table-column>
+            <el-table-column label="频度" align="center" width="200px">
+                <template slot-scope="scope">
+                    <el-select
+						v-model="scope.row.frequency"
+						placeholder="请选择频率"
+                        @change="handleFrequencyChange(scope)"
+                        :disabled="operationForm.view||[5,6,14,61,63].includes(sourceTypeVal)"
+					>
+						<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">目录</span>
+                    <el-radio-group :disabled="operationForm.view" v-model="classifyType" @change="handleClassifyTypeChange">
+                        <el-radio :label="0">分目录</el-radio>
+                        <el-radio :label="1">同目录</el-radio>
+                    </el-radio-group>
+                </template>
+                <template slot-scope="{row,$index}">
+                    <el-cascader
+						v-model="row.classify"
+						:options="classifyOpt"
+						:props="levelProps"
+						placeholder="请选择指标目录"
+                        :disabled="(classifyType===1&&$index>0)||operationForm.view"
+                        @change="handleClassifyChange(row,$index)"
+					/>
+                </template>
+            </el-table-column>
+        </el-table>
+        <div style="text-align:center;margin:60px 0 40px 0" v-if="!operationForm.view">
+            <el-button type="primary" plain @click="handleClose">取消</el-button>
+            <el-button type="primary" @click="handleSubmit" :loading="loading">{{loading ? '批量计算中...' : '批量计算'}}</el-button>
+        </div>
+    </div>
+</template>
+
+<script>
+import { dataBaseInterface } from '@/api/api.js';
+import {generateSeriesArray} from './util'
+const tag_arr = generateSeriesArray();
+export default {
+    props:{
+        computedType:null,
+        subComputedType:null,
+        selectList:null,
+        formData:null,
+        select_target:null,
+        operationForm:null,
+        isEdit:false
+    },
+    computed: {
+        sourceTypeVal(){
+            if(!this.computedType) return 0
+            if(this.subComputedType) return this.subComputedType
+            return ['withNum','withEDB'].includes(this.computedType)?4:this.computedType
+        }
+    },
+    data() {
+        return {
+            frequencyArr: ['日度', '周度','旬度','月度', '季度', '年度'],
+
+            list:[],
+
+            classifyType:0,
+            classifyOpt: [],
+			levelProps: {
+				label: 'ClassifyName',
+				value: 'ClassifyId',
+				children: 'Children',
+				checkStrictly: true,
+                emitPath:false
+			},
+
+            loading:false,
+
+            computedArr:[],//多指标求和\平均的指标数组
+        }
+    },
+    mounted() {
+        this.initData()
+        this.getClassifyOpt()
+    },
+    methods: {
+        // 初始化数据
+        initData(){
+            let arr=[]
+
+            // 如果是多指标求和\平均
+            if(this.computedType==='multipleEDB'){
+                this.computedArr=this.selectList
+                // 如果是编辑时
+                if(this.isEdit){
+                    this.list=[{
+                        EdbName:this.operationForm.EdbInfoDetail.EdbName,
+                        EdbInfoId:this.operationForm.EdbInfoDetail.EdbInfoId,
+                        name:this.operationForm.EdbInfoDetail.EdbName,
+                        unit:this.operationForm.EdbInfoDetail.Unit,
+                        frequency:this.operationForm.EdbInfoDetail.Frequency,
+                        classify:this.operationForm.EdbInfoDetail.ClassifyId
+                    }]
+                    return
+                }
+                arr=[{...this.selectList[0]}]
+            }else{
+                arr=this.selectList
+            }
+            
+            
+            arr.forEach(item=>{
+                this.setDefaultVal(item)
+            })
+            
+        },
+        // 设置默认值
+        setDefaultVal(item){
+            const obj={
+                EdbName:item.EdbName,
+                EdbInfoId:item.EdbInfoId,
+                name:'',
+                unit:'',
+                frequency:'',
+                classify:''
+            }
+            const tMap=new Map([
+				['日度','D'],
+				['周度','W'],
+				['旬度','T'],
+				['月度','M'],
+				['季度','Q'],
+				['年度','Y'],
+			])
+			const name_map = {
+                4:item.EdbName,
+				5: `${item.EdbName}转月值`,
+				8: `${item.EdbName}/${this.formData.nNum}${tMap.get(item.Frequency)}MA`,
+				14: `${item.EdbName}/日频`,
+				6: `${item.EdbName}同比`,
+				7: `${item.EdbName}同差`,
+				12: `${item.EdbName}${this.formData.nNum}${item.Frequency.slice(0,1)}环比`,
+				13: `${item.EdbName}${this.formData.nNum}${item.Frequency.slice(0,1)}环差`,
+				35: `${item.EdbName}超季节性/${this.formData.nNum}年${this.formData.calendarType==='公历'?'':'/'+this.formData.calendarType}`,
+				52: `${item.EdbName}年化值`,
+				51: `${item.EdbName}/${this.formData.frequency.substr(0,1)}频`,
+				61:  `${item.EdbName}转季值`,
+				62:  `${item.EdbName}累计值/${this.formData.frequency}`,
+				63:  `${item.EdbName}年初至今累计值`,
+                72:`${item.EdbName}指数修匀`,
+				75: `${item.EdbName}日均值`,
+                81:item.EdbName,
+                82:item.EdbName,
+			}
+			
+			let frequerncyMap = {
+				14: '日度',
+				61: '季度',
+                62:this.formData.frequency,
+                51:this.formData.frequency,
+			}
+
+            obj.name=name_map[this.sourceTypeVal] || ''
+            obj.frequency=frequerncyMap[this.sourceTypeVal]|| item.Frequency
+            obj.classify=item.ClassifyId||''
+
+            if([5,8,14,7,35,75].includes(this.sourceTypeVal)){
+                obj.unit=item.Unit
+            }else if([4].includes(this.sourceTypeVal)){
+                obj.unit=''
+            }else{
+                obj.unit='无'
+            }
+            
+
+            this.list.push(obj)
+        },
+        // 频度变化 修改指标名
+		handleFrequencyChange(e){
+			if(!this.sourceTypeVal||![51,62].includes(this.sourceTypeVal)) return;
+            const obj=this.list[e.$index]
+			const name_map = {
+				51: `${obj.EdbName}/${obj.frequency.substr(0,1)}频`,
+				62:  `${obj.EdbName}累计值/${obj.frequency}`,
+			}
+			this.list[e.$index].name=name_map[this.sourceTypeVal]
+		},
+
+        // 同目录修改
+        handleClassifyChange(e,index){
+            if(this.classifyType===1){
+                // 修改所有的指标的目录为第一个
+                this.list.forEach(item=>{
+                    item.classify=e.classify
+                })
+            }
+        },
+
+        handleClassifyTypeChange(){
+            this.handleClassifyChange(this.list[0])
+        },
+
+        // 提交计算
+        async handleSubmit(){
+            const edbList=this.list.map((item,index)=>{
+                return{
+                    CalculateId:tag_arr[index],
+                    ClassifyId:item.classify,
+                    EdbName:item.name,
+                    Frequency:item.frequency,
+                    Unit:item.unit,
+                    FromEdbInfoId:this.isEdit?0:item.EdbInfoId,
+                    EdbInfoId:this.isEdit?item.EdbInfoId:0
+                }
+            })
+            const valueMap = {
+				51: 'valueType',
+                72:'alphaValue'
+			}
+            const params={
+                EdbList:edbList,
+                Formula:valueMap[this.sourceTypeVal] ? String(this.formData[valueMap[this.sourceTypeVal]]) : String(this.formData.nNum),
+                Source:this.sourceTypeVal,
+                CalculateFormula:this.sourceTypeVal===4? JSON.stringify([{f:this.formData.formula,d:''}]) : this.formData.formula,
+                EdbInfoIdArr:this.select_target?[{EdbInfoId:this.select_target,FromTag:'B'}]:[],
+                MoveType:0,
+                MoveFrequency:'',
+                Calendar:this.formData.calendarType,
+                EmptyType: this.formData.nullValueWay,
+				MaxEmptyType: this.formData.maxNullWay,
+                Extra:JSON.stringify({
+                    LastValType:this.formData.newValue,
+                    DateTag:this.formData.timeSeriesVal
+                })
+            }
+            // 处理多指标求和\平均 情况的数据
+            if(this.computedType==='multipleEDB'){
+                const arr=this.computedArr.map((item,index)=>{
+                    return{
+                        EdbInfoId:item.EdbInfoId,
+                        FromTag:tag_arr[index]
+                    }
+                })
+                params.EdbInfoIdArr=arr
+            }
+            console.log(params);
+
+            let isEnough = params.EdbList.every(item => item.EdbName&&item.Unit&&item.ClassifyId&&item.Frequency)
+            if(!isEnough) return this.$message.warning('请填写完整信息');
+
+            this.loading=true
+            const tipMsg=setTimeout(() => {
+                this.$message.success('请等待计算完成,该过程可能持续2-3分钟')
+            }, 500);
+            const res=this.isEdit?await dataBaseInterface.batchCalculateTargetEdit(params) : await dataBaseInterface.batchCalculateTargetAdd(params)
+            this.loading=false
+            clearTimeout(tipMsg)
+            
+            if(res.Ret !== 200) return
+
+            const { Fail,Success } = res.Data;
+
+            if(Fail.length) {
+                let message = '';
+                Fail.forEach(item => {
+                    message+=`${item.CalculateId}:${item.Msg}</br>`
+                })
+
+                this.$message({
+                    dangerouslyUseHTMLString: true,
+                    message,
+                    type: 'error'
+                })
+                this.dealFailHandle(Fail)
+            }else {
+                this.$message.success('添加成功');
+                // this.init();
+                this.$emit('addCallBack','add',{ code:Success[0].UniqueCode,id:Success[0].EdbInfoId,classifyId:Success[0].ClassifyId});
+            }
+
+        },
+
+        // 处理批量添加失败的指标
+        dealFailHandle(data){
+            let temarr=[]
+            data.forEach(item=>{
+                const index=tag_arr.indexOf(item.CalculateId)
+                temarr.push(this.list[index])
+            })
+            this.list=temarr
+        },
+
+
+        handleClose(){
+            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 getClassifyOpt(){
+            const res=await dataBaseInterface.menuListV3()
+            if (res.Ret !== 200) return
+            this.filterNodes(res.Data.AllNodes||[]);
+			this.classifyOpt = res.Data.AllNodes || [];
+        },
+    },
+}
+</script>
+
+<style lang="scss">
+.batch-computed-save-wrap{
+    .el-input{
+        input{
+            border: none;
+            text-align: center;
+        }
+    }
+    .el-table tr{
+        background-color: #fff !important;
+        &:hover>td{
+            background-color: transparent !important; /* 或者其他想要的颜色值 */
+        }
+    }
+}
+</style>

+ 982 - 0
src/views/dataEntry_manage/databaseComponents/batchComputedV2.vue

@@ -0,0 +1,982 @@
+<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="showSave?'批量计算-结果保存':'批量计算-选择指标和计算公式'"
+	>
+        <div class="batch-computed-wrap" v-if="!showSave">
+            <el-form inline :disabled="operationForm.view">
+            <div class="type-wrap">
+                <div style="margin-right:50px">
+                    <span>计算公式</span>
+                    <el-select :disabled="isEdit" v-model="computedType" @change="handleComputedTypeChange" placeholder="请选择">
+                        <el-option 
+                            v-for="opt in computedBatchTypes" 
+                            :key="opt.type" 
+                            :label="opt.name"
+                            :value="opt.type"
+                        />
+                    </el-select>
+                </div>
+                <div style="flex:1">
+                    <!-- 累计值转月/季值 -->
+                    <el-form-item v-if="computedType=='toMonthSeason'">
+                        <el-radio-group v-model="subComputedType" @change="handleComputedSubTypeChange">
+                            <el-radio :label="5">转月值</el-radio>
+                            <el-radio :label="61">转季值</el-radio>
+                        </el-radio-group>
+                    </el-form-item>
+
+                    <!-- N期移动均值、N期环比值、N期环差值 -->
+                    <el-form-item required v-if="[8,12,13].includes(computedType)" label="N等于" style="width:280px">
+                        <el-input v-model="formData.nNum" placeholder="请输入N数值" type="number" style="width:200px"></el-input>
+                    </el-form-item>
+
+                    <!-- 超级季节性 -->
+                    <template v-if="computedType==35">
+                    <el-form-item required label="N等于" style="width:280px">
+                        <el-input v-model="formData.nNum" placeholder="请输入N数值" type="number" style="width:200px"></el-input>
+                    </el-form-item>
+                    <el-form-item label="日历"  style="width:180px">
+                        <el-select v-model="formData.calendarType" style="width:120px">
+                            <el-option label="公历" value="公历"></el-option>
+                            <el-option label="农历" value="农历"></el-option>
+                        </el-select>
+                    </el-form-item>
+                    </template>
+
+                    <!-- 降频 -->
+                    <template v-if="computedType==51">
+                    <el-form-item required label="频度" style="width:180px">
+                        <el-select v-model="formData.frequency" style="width:120px">
+                            <el-option v-for="opt in frequencyArr" :key="opt" :label="opt" :value="opt"></el-option>
+                        </el-select>
+                    </el-form-item>
+                    <el-form-item label="数据取值"  style="width:200px">
+                        <el-select v-model="formData.valueType" style="width:120px">
+                            <el-option key="期末值" label="期末值" value="期末值"/>
+							<el-option key="平均值" label="平均值" value="平均值"/>
+                        </el-select>
+                    </el-form-item>
+                    </template>
+
+                    <!-- 累计值 -->
+                    <template v-if="computedType=='accumulate'">
+                    <el-form-item>
+                        <el-radio v-model="subComputedType" :label="62">累计值</el-radio>
+                    </el-form-item>
+                    <el-form-item required label="频度" style="width:180px" v-if="subComputedType==62">
+                        <el-select v-model="formData.frequency" style="width:120px">
+                            <el-option v-for="opt in frequencyArr" :key="opt" :label="opt" :value="opt"></el-option>
+                        </el-select>
+                    </el-form-item>
+                    <el-form-item label="最新值处理"  style="width:210px" v-if="subComputedType==62">
+                        <el-select v-model="formData.newValue" style="width:120px">
+                            <el-option label="默认" :value="0"/>
+							<el-option label="均值填充" :value="1"/>
+                        </el-select>
+                    </el-form-item>
+                    <el-form-item>
+                        <el-radio v-model="subComputedType" :label="63">年初至今累计值</el-radio>
+                    </el-form-item>
+                    </template>
+
+                    <!-- 指数修匀 -->
+                    <template v-if="computedType==72">
+                    <el-form-item required label="alpha值" style="width:220px">
+                        <el-input v-model.trim="formData.alphaValue" style="width:140px" placeholder="请输入alpha值"></el-input>
+                    </el-form-item>
+                    </template>
+
+                    <!-- 与常数计算 -->
+                    <template v-if="computedType=='withNum'">
+                    <el-form-item required label="公式">
+                        <el-input v-model="formData.formula" placeholder="请输入公式" clearable style="width: 200px"/>
+                        <span>公式示例:A+100,或A*2</span>
+                    </el-form-item>
+                    </template>
+
+                    <!-- 与单指标计算 -->
+                    <template v-if="computedType=='withEDB'">
+                    <el-form-item required label="指标B">
+                        <el-select
+                            v-model="select_target"
+                            v-loadMore="searchLoad"
+                            :filterable="!select_target"
+                            clearable
+                            placeholder="请输入指标名称"
+                            style="width: 250px"
+                            remote
+                            :remote-method="getTarget"
+                            @click.native="inputFocusHandle"
+                            @change="chooseTarget"
+                            @blur="search_have_more = false"
+                        >
+                            <i slot="prefix" class="el-input__icon el-icon-search"></i>
+                            <el-option
+                                v-for="item in searchOptions"
+                                :key="item.EdbInfoId"
+                                :label="$parent.currentLang==='en'?(item.EdbNameEn||item.EdbName):item.EdbName"
+                                :value="item.EdbInfoId"
+                            />
+                        </el-select>
+                    </el-form-item>
+                    <el-form-item required label="公式">
+                        <el-input v-model="formData.formula" placeholder="请输入公式" clearable style="width: 200px"/>
+                        <span>公式示例:A+B,或A/B,A/(A+B)</span>
+                    </el-form-item>
+                    <el-form-item label="生成指标时间序列">
+                        <el-cascader
+							v-model="formData.timeSeriesVal"
+							style="width:180px"
+							:options="timeSeriesOpt"
+							:props="{emitPath:false}"
+							:show-all-levels="false"
+							placeholder="请选择"
+						></el-cascader>
+                    </el-form-item>
+                    <el-form-item label="空值处理">
+                        <el-select
+							v-model="formData.nullValueWay"
+							placeholder="请选择"
+                            style="width:180px"
+						>
+							<el-option
+								v-for="item in nullWayOptions"
+								:key="item.value"
+								:label="item.label"
+								:value="item.value"
+							>
+							</el-option>
+						</el-select>
+                    </el-form-item>
+                    <el-form-item label="MAX、MIN空值处理" v-if="showMaxNullDeal">
+                        <el-select
+							v-model="formData.maxNullWay"
+							placeholder="请选择"
+						>
+							<el-option label="等于0" :value="1" />
+							<el-option label="跳过空值" :value="2" />
+						</el-select>
+                    </el-form-item>
+                    </template>
+
+                    <!-- 多指标求和/平均 -->
+                    <template v-if="computedType=='multipleEDB'">
+                    <el-form-item style="margin-right:30px">
+                    <el-radio-group :disabled="isEdit" v-model="subComputedType">
+                        <el-radio :label="81">求和</el-radio>
+                        <el-radio :label="82">求平均</el-radio>
+                    </el-radio-group>
+                    </el-form-item>
+                    <el-form-item label="生成指标时间序列">
+                        <el-cascader
+							v-model="formData.timeSeriesVal"
+							style="width:180px"
+							:options="timeSeriesOpt"
+							:props="{emitPath:false}"
+							:show-all-levels="false"
+							placeholder="请选择"
+						></el-cascader>
+                    </el-form-item>
+                    <el-form-item label="空值处理">
+                        <el-select
+							v-model="formData.nullValueWay"
+							placeholder="请选择"
+                            style="width:180px"
+						>
+							<el-option
+								v-for="item in nullWayOptions"
+								:key="item.value"
+								:label="item.label"
+								:value="item.value"
+							>
+							</el-option>
+						</el-select>
+                    </el-form-item>
+                    </template>
+
+
+                </div>
+            </div>
+            </el-form>
+            <div class="filter-wrap" style="margin-top:20px">
+                <p style="margin-bottom:10px">待选指标(选择指标数量不超过{{MAXAddNUM}})</p>
+                <div>
+                    <el-cascader
+						v-model="filter.classify"
+						:options="classifyOpt"
+						:props="classifyProps"
+						clearable
+                        collapse-tags
+						placeholder="指标分类"
+                        style="width: 240px"
+                        @change="handleFilter"
+					/>
+                    <el-select
+						v-model="filter.frequency"
+						placeholder="请选择频率"
+						style="width: 140px"
+						clearable
+                        multiple
+                        collapse-tags
+                        @change="handleFilter"
+                        :disabled="[5,61].includes(subComputedType)"
+					>
+						<el-option
+							v-for="item in frequencyArr"
+							:key="item"
+							:label="item"
+							:value="item"
+						>
+						</el-option>
+					</el-select>
+                    <el-cascader
+                        v-model="filter.user"
+                        placeholder="创建人"
+                        :options="sysUserOpts"
+                        :props="sysUserProps"
+                        collapse-tags
+                        :show-all-levels="false"
+                        clearable
+                        filterable
+                        style="width:240px"
+                        @change="handleFilter"
+                    />
+                    <el-input 
+                        placeholder="指标ID/指标名称" 
+                        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="列表全选" 
+                        v-model="isCheckAll" 
+                        :indeterminate="isCheckIndeterminate" 
+                        style="margin-left:10px"
+                        @change="listCheckAllChange"
+                        :disabled="operationForm.view"
+                    />
+                </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"/>
+                        <el-table-column label="指标全称" show-overflow-tooltip align="center" prop="EdbName"/>
+                        <el-table-column label="最新日期" align="center" prop="EndDate" width="120px" />
+                        <el-table-column label="最新值" align="center" show-overflow-tooltip prop="EndValue" width="80px"/>
+                        <el-table-column label="创建人" align="center" show-overflow-tooltip prop="SysUserRealName" width="80px"/>
+                        <el-table-column label="频度" align="center" prop="Frequency" width="50px"/>
+                        <el-table-column label="单位" show-overflow-tooltip align="center" prop="Unit" width="50px"/>
+                    </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"
+                    />
+                </div>
+                <div style="padding-top:200px;margin:0 30px">
+                    <el-button type="primary" :disabled="operationForm.view" :loading="addLoading" @click="getAddEdbListData">加入已选指标</el-button>
+                </div>
+                <div class="right-box">
+                    <el-table 
+                        :data="selectList" 
+                        border 
+                        height="500px"
+                    >
+                        <el-table-column label="序号" width="50px" align="center" prop="No" v-if="computedType=='multipleEDB'">
+                            <template slot-scope="scope">
+                                {{scope.$index|getNoText}}
+                            </template>
+                        </el-table-column>
+                        <el-table-column label="指标全称" show-overflow-tooltip align="center" prop="EdbName"/>
+                        <el-table-column width="50px" align="center" v-if="!operationForm.view">
+                            <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="">
+                            </template>
+                            <template slot-scope="scope">
+                                <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>
+                <el-button type="primary" @click="handleNextStep">下一步</el-button>
+            </div>
+        </div>
+        <!-- 结果保存 -->
+        <batchComputedSave 
+            :select_target="select_target"
+            :computedType="computedType" 
+            :subComputedType="subComputedType" 
+            :selectList="selectList" 
+            :formData="formData" 
+            :isEdit="isEdit"
+            :operationForm="operationForm"
+            @close="showSave=false" 
+            @addCallBack="handleAddSuccess"
+            v-else
+        />
+    </el-dialog>
+</template>
+
+<script>
+import mPage from '@/components/mPage.vue'
+import {computedBatchTypesV2} from './util'
+import { dataBaseInterface,departInterence } from '@/api/api.js';
+import batchComputedSave from './batchComputedSave.vue';
+import {generateSeriesArray} from './util'
+const tag_arr = generateSeriesArray();
+export default {
+    components:{mPage,batchComputedSave},
+    props:{
+        isShow:{
+            type: Boolean
+        },
+        operationForm: {
+			type: Object,
+		},
+        type: {
+			type: Number
+		},
+    },
+    filters:{
+        getNoText(e){
+            return tag_arr[e]
+        }
+    },
+    computed:{
+        // 最大添加指标的上限
+        MAXAddNUM(){
+            let num=50
+            if(this.computedType=='multipleEDB'){
+                num=100
+            }
+            return num
+        },
+        /* max空值处理显示 当输入的公式包含MAX、MIN且空值处理为0时,输入公式失焦后出现右侧选项; */
+		showMaxNullDeal() {
+			let haveMaxOrMin =  this.formData.formula.toUpperCase().includes('MAX') || this.formData.formula.toUpperCase().includes('MIN')
+
+			return haveMaxOrMin && this.formData.nullValueWay===4
+		},
+        timeSeriesOpt(){
+            let arr=[
+                {
+                    label:`指标A`,
+                    value:'A'
+                },
+                {
+                    label:`指标B`,
+                    value:'B'
+                }
+            ]
+            if(this.computedType=='multipleEDB'){
+                arr=this.selectList.map((item,index)=>{
+                    return{
+                        label:`指标${tag_arr[index]}`,
+                        value:tag_arr[index]
+                    }
+                })
+            }
+            return [
+                {
+                    label:'指定指标时间序列',
+					value:'0',
+                    children:arr
+                },
+                {
+					label:'所有指标时间序列并集',
+					value:'all',
+				}
+            ]
+        },
+
+        frequencyArr(){
+            if(this.computedType==75){
+                return ['周度','旬度','月度', '季度', '年度']
+            }
+            return ['日度', '周度','旬度','月度', '季度', '年度']
+        }
+    },
+    watch: {
+        isShow(n){
+            if(!n){
+                this.subComputedType=''
+                this.select_target=''
+                this.selectList=[]
+                this.tableDataCheckedList=[]
+                this.tableDataIds=[]
+                this.isCheckAll=false
+                this.isCheckIndeterminate=false
+                this.checkAllStatus=false
+                this.selectionReactCancel=false
+                this.isEdit=false
+                this.showSave=false
+                this.computedType=computedBatchTypesV2[0].type
+                this.filter={
+                    classify:'',
+                    frequency:'',
+                    user:'',
+                    keyword:''
+                }
+                this.formData={
+                    nNum:1,
+                    calendarType:'公历',
+                    frequency:'',
+                    valueType:'期末值',
+                    newValue:0,
+                    alphaValue:'',
+                    formula:'',
+                    timeSeriesVal:'A',
+                    nullValueWay:0,
+                    maxNullWay:1,
+                }
+            }else{
+                // 编辑多指标求和\平均
+                if([81,82].includes(this.type)){
+                    this.initData()
+                }
+                this.handleFilter()
+            }
+        }
+    },
+    data() {
+        return {
+            showSave:false,//显示结果保存模块
+            computedBatchTypes:computedBatchTypesV2,//计算类型筛选项
+            computedType:computedBatchTypesV2[0].type,//当前选中的计算类型
+            subComputedType:'',//二级计算类型
+            formData:{
+                nNum:1,
+                calendarType:'公历',
+                frequency:'',
+                valueType:'期末值',
+                newValue:0,
+                alphaValue:'',
+                formula:'',
+                timeSeriesVal:'A',
+                nullValueWay:0,
+                maxNullWay:1,
+            },
+
+            select_target:'',
+			searchOptions:[],//指标列表
+            search_have_more:false,
+            search_page: 1,
+			current_search: '',
+
+            filter:{
+                classify:'',
+                frequency:'',
+                user:'',
+                keyword:''
+            },
+
+            // frequencyArr: ['日度', '周度','旬度','月度', '季度', '年度'],
+            classifyOpt: [],
+			classifyProps: {
+				label: 'ClassifyName',
+				value: 'ClassifyId',
+				children: 'Children',
+				multiple: true,
+                emitPath:false
+			},
+            sysUserOpts:[],
+            sysUserProps:{
+                value: "AdminId",
+                label: "RealName",
+                children: "ChildrenList",
+                multiple: true,
+                emitPath:false
+            },
+
+            nullWayOptions: [
+				{ label: '查找前后35天最近值',value: 0 },
+				{ label: '不计算',value: 1 },
+				{ label: '前值填充',value: 2 },
+				{ label: '后值填充',value: 3 },
+				{ label: '等于0',value: 4 },
+			],
+
+            isCheckAll:false,//是否全选
+            isCheckIndeterminate:false,// 标志列表当前是全选状态还是不是全选状态和 isCheckAll不一样
+            checkAllStatus:false,
+            selectionReactCancel:false,// 是否不触发 selection的逻辑
+
+            listLoading:false,
+            page:1,
+            pageSize:20,
+            total:0,
+            list:[],
+
+            tableDataCheckedList:[],
+            tableDataIds:[],
+
+            selectList:[],//添加到右侧的数据
+            addLoading:false,
+
+            isEdit:false,//是否为多指标求和等编辑
+
+        }
+    },
+    mounted() {
+        this.getClassifyOpt()
+        this.getEDBList()
+        this.getSysUserList()
+    },
+    
+    methods: {
+        // 编辑时初始化数据
+        initData(){
+            this.isEdit=true
+            const arr=this.operationForm.CalculateList||[]
+            this.selectList=arr.map(item=>{
+                return {
+                    ClassifyId:item.ClassifyId,
+                    EdbInfoId:item.FromEdbInfoId,
+                    EdbName:item.FromEdbName,
+                    Frequency:item.Frequency,
+                    Unit:item.Unit
+                }
+            })
+            this.computedType='multipleEDB'
+            this.subComputedType=this.type
+            this.formData.timeSeriesVal=this.operationForm.EdbInfoDetail.Extra?JSON.parse(this.operationForm.EdbInfoDetail.Extra).DateTag:'A'
+            this.formData.nullValueWay=this.operationForm.EdbInfoDetail.EmptyType||0
+
+        },
+        //批量计算成功回调
+        handleAddSuccess(type,params){
+            this.$emit('addCallBack',type,params)
+        },
+        // 跳转下一步
+        handleNextStep(){
+            if(this.selectList.length===0){
+                this.$message.warning('请选择指标')
+                return
+            }
+            if([8,12,13,35].includes(this.computedType) && !this.formData.nNum){
+                this.$message.warning('请输入N数值')
+                return
+            }
+            if([51].includes(this.computedType)&& !this.formData.frequency){
+                this.$message.warning('请选择频度')
+                return
+            }
+            if(['accumulate'].includes(this.computedType)&&this.subComputedType==62&& !this.formData.frequency){
+                this.$message.warning('请选择频度')
+                return
+            }
+            if(this.computedType==72&&!this.formData.alphaValue){
+                this.$message.warning('请输入alpha值')
+                return
+            }
+            if(this.computedType==72&&(Number(this.formData.alphaValue)<=0||Number(this.formData.alphaValue)>=1)){
+                this.$message.warning('请输入>0,<1的数值的alpha值')
+                return
+            }
+            if(this.computedType=='withEDB'&&!this.select_target){
+                this.$message.warning('请选择指标B')
+                return
+            }
+            if(['withNum','withEDB'].includes(this.computedType)&&!this.formData.formula){
+                this.$message.warning('请输入公式')
+                return
+            }
+
+            this.isCheckAll=false
+            this.isCheckIndeterminate=false
+            this.checkAllStatus=false
+            this.tableDataCheckedList=[]
+            this.tableDataIds=[]
+
+            this.showSave=true
+        },
+
+        // 点击加入已选指标库
+        async getAddEdbListData(){
+            if(!(this.isCheckAll || this.isCheckIndeterminate ) || (!(this.list && this.list.length>0))){
+                this.$message.warning('请选择指标')
+                return
+            }
+            if(this.selectList.length>=this.MAXAddNUM){
+                this.$message.warning('已达批量添加指标数量上限')
+                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.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)
+        },
+
+        // 切换计算类型
+        handleComputedTypeChange(){
+            this.subComputedType=''
+            this.select_target=''
+            this.formData={
+                nNum:1,
+                calendarType:'公历',
+                frequency:'',
+                valueType:'期末值',
+                newValue:0,
+                alphaValue:'',
+                formula:'',
+                timeSeriesVal:'A',
+                nullValueWay:0,
+                maxNullWay:1,
+            }
+            this.filter={
+                classify:'',
+                frequency:'',
+                user:'',
+                keyword:''
+            }
+            this.selectList=[]
+            if(this.computedType=='toMonthSeason'){
+                this.subComputedType=5
+                this.filter.frequency=['月度']
+            }else if(this.computedType=='accumulate'){
+                this.subComputedType=62
+            }else if(this.computedType=='multipleEDB'){
+                this.subComputedType=81
+            }
+            this.handleFilter()
+        },
+        handleComputedSubTypeChange(){
+            if(this.subComputedType==61){
+                this.filter.frequency=['季度']
+            }
+            if(this.subComputedType==5){
+                this.filter.frequency=['月度']
+            }
+            this.selectList=[]
+            this.handleFilter()
+        },
+
+        /* 指标列表 */
+		getTarget(query) {
+			this.search_page = 1;
+			this.current_search = query;
+			this.searchApi(this.current_search);
+		},
+
+		/* 聚焦获取当前检索 */
+		inputFocusHandle(e) {
+			this.search_page = 1;
+			this.current_search = e.target.value;
+			this.searchApi(this.current_search);
+		},
+
+		searchApi(query,page=1) {
+			dataBaseInterface.targetSearchByPage({
+				KeyWord:query,
+				CurrentIndex: page,
+				FilterSource:  1,
+				Frequency: ''
+			}).then(res => {
+				if(res.Ret !== 200) return
+				const { List,Paging } = res.Data;
+				this.search_have_more = page < Paging.Pages;
+				let arr = page === 1 ? List : this.searchOptions.concat(List);
+
+				this.searchOptions = arr;
+					
+			})
+		},
+
+		searchLoad() {
+			if(!this.search_have_more) return;
+			this.searchApi(this.current_search,++this.search_page)
+		},
+
+        handleClose(){
+            this.showSave=false
+            this.$emit('close')
+        },
+        handleCloseSelf(){//仅仅关闭批量计算弹窗
+            this.$emit('closeSelf')
+        },
+
+        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(','):'',
+                NotFrequency:this.computedType==75?'日度':''
+            })
+            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)
+        },
+
+
+
+    },
+}
+</script>
+
+<style lang="scss">
+.batch-computed-dialog{
+    max-width: 1200px;
+    width:90vw;
+	overflow: hidden;
+}
+.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>

+ 93 - 6
src/views/dataEntry_manage/databaseComponents/computedDialog.vue

@@ -70,6 +70,24 @@
 				添加更多参数
 			</span>
 			<div class="computed-min">
+				<div class="computed-section" v-if="edbSource !== 'predict'">
+					<div>
+						<label class="label">生成指标时间序列</label>
+						<div style="width:200px;display: inline-block;">
+							<el-cascader
+								v-model="selectTimeSeriesVal"
+								style="width:100%"
+								:options="timeSeriesOpt"
+								:props="{emitPath:false}"
+								:show-all-levels="false"
+								placeholder="请选择"
+								:disabled="calulateForm.view"
+							></el-cascader>
+						</div>
+						
+					</div>
+				</div>
+
 				<div class="computed-section">
 					<div>
 						<label class="label">空值处理
@@ -121,7 +139,7 @@
 					</el-input> -->
 					<ul class="formula-list">
 						<li style="margin-bottom: 15px;">
-							<el-input placeholder="请输入公式" v-model="formulaList[0].formula" clearable :disabled="calulateForm.view" style="width: 220px"/>
+							<el-input placeholder="请输入公式" v-model="formulaList[0].formula" clearable :disabled="calulateForm.view" style="width: 600px"/>
 							
 							<span v-if="formulaDateArr.length" class="date-section-text">{{formulaDateArr[formulaDateArr.length-1]}}(含)之后</span>
 
@@ -243,8 +261,11 @@ import { dataBaseInterface } from '@/api/api.js';
 import * as preDictEdbInterface from '@/api/modules/predictEdbApi.js';
 import { formRules } from '../databaseComponents/util';
 import { unitArr } from '@/utils/defaultOptions';
-const tag_arr = [];
-for(let i=0;i<26;i++) tag_arr.push(String.fromCharCode(65+i));
+import {generateSeriesArray} from './util'
+const MAXEDBNUM=50//最大可添加的指标数量
+const tag_arr = generateSeriesArray();
+
+// for(let i=0;i<26;i++) tag_arr.push(String.fromCharCode(65+i));
 export default {
 	name: '',
 	props: {
@@ -280,6 +301,28 @@ export default {
 
 		formulaDateArr() {
 			return this.formulaList.map(_ => _.date).filter(_ => _).sort((a,b) => new Date(a)-new Date(b))
+		},
+
+		timeSeriesOpt(){
+			const arr=[
+				{
+					label:'指定指标时间序列',
+					value:'0',
+					children:[]
+				},
+				{
+					label:'所有指标时间序列并集',
+					value:'all',
+				}
+			]
+			arr[0].children=this.addList.filter(item=>item.target).map(item=>{
+				return {
+					label:`指标${item.tag}`,
+					value:item.tag
+				}
+			})
+
+			return arr
 		}
 	},
 	watch: {
@@ -310,9 +353,43 @@ export default {
 					EdbName: item.edb_name,
 				}))
 
+				if(this.calulateForm.Extra){
+					const ExtraObj=JSON.parse(this.calulateForm.Extra)
+					this.selectTimeSeriesVal=ExtraObj.DateTag
+				}
+				
+
+
 				this.getNewestDate();
 			}
 		},
+
+		'addList':{
+			handler(n){
+				if(this.selectTimeSeriesVal=='all') return
+				const arr=this.addList.filter(item=>item.target).map(item=>{
+					return {
+						label:`指标${item.tag}`,
+						value:item.tag
+					}
+				})
+				if(!arr.length) return
+				if(!this.selectTimeSeriesVal){
+					this.selectTimeSeriesVal=arr[0].value
+				}else{//已经有选择的值了
+					let flag=false
+					arr.forEach(item=>{
+						if(item.value==this.selectTimeSeriesVal){
+							flag=true
+						}
+					})
+					if(!flag){
+						this.selectTimeSeriesVal=arr[0].value
+					}
+				}
+			},
+			deep:true
+		}
 	},
 	data() {
 		return {
@@ -381,6 +458,9 @@ export default {
 				{ label: '后值填充',value: 3 },
 				{ label: '等于0',value: 4 },
 			],
+
+			selectTimeSeriesVal:'',
+
 			formTips: {
 				'null-val': `1、查找前后35天最近值:在参与计算的日期序列上某指标无值时,该指标往前/往后找距离最近的值作为当天的值进行计算,遍历允许跨年,往前最多35天,往后最多35天<br>
 				2、不计算:只要有一个指标在某个日期没有值(即空值),则计算指标在该日期没有值 <br>
@@ -421,7 +501,8 @@ export default {
 		},
 		/* 添加额外的指标列 */
 		addTargetHandle() {
-			if(this.addList.length >= 26) return this.$message.warning('添加指标个数已达上限')
+			const MAXNUM=this.edbSource === 'predict'?26:MAXEDBNUM
+			if(this.addList.length >=MAXNUM) return this.$message.warning('添加指标个数已达上限')
 			let tag = this.addList[this.addList.length-1].tag;
 			let index = tag_arr.findIndex(item => item === tag);
 			const item = {
@@ -535,7 +616,10 @@ export default {
 					Unit: this.formData.unit,
 					EdbInfoIdArr,
 					EmptyType: nullValueWay,
-					MaxEmptyType: maxNullWay
+					MaxEmptyType: maxNullWay,
+					Extra:JSON.stringify({
+						DateTag:this.selectTimeSeriesVal
+					})
 				};
 				this.dataloading = true;
 
@@ -655,7 +739,7 @@ export default {
 		width: 6px !important;
 	}
 	.el-dialog__body {
-		max-height: 700px;
+		max-height: 840px;
 		overflow: auto;
 	}
 	.dialog-main {
@@ -709,6 +793,9 @@ export default {
 			.computed-section {
 				display: flex;
 				margin-top: 20px;
+				.el-cascader .el-input {
+					width: 100%;
+				}
 			}
 			.label {
 				padding:10px 10px 10px 0;

+ 10 - 5
src/views/dataEntry_manage/databaseComponents/diffusionIndexDia.vue

@@ -96,7 +96,7 @@
 			<selectUnit 
 			  	v-model="formData.unit" 
 				style="width:340px" 
-				:disabled="!operationForm.edb_id&&[6,7].includes(type)"
+				:disabled="type===53"
 			/>
           </el-form-item>
           <el-form-item label="指标目录" prop="menu" style="margin-right: 40px;">
@@ -150,11 +150,12 @@
 
 <script>
 import { dataBaseInterface } from '@/api/api.js';
-import { formRules } from './util';
+import { formRules,generateSeriesArray } from './util';
 import * as preDictEdbInterface from '@/api/modules/predictEdbApi.js';
 import { unitArr } from '@/utils/defaultOptions';
-const tag_arr = [];
-for(let i=0;i<26;i++) tag_arr.push(String.fromCharCode(65+i));
+const MAXEDBNUM=50//最大可添加的指标数量
+const tag_arr = generateSeriesArray();
+// for(let i=0;i<26;i++) tag_arr.push(String.fromCharCode(65+i));
 export default {
 	name:'',
 	props: {
@@ -205,6 +206,9 @@ export default {
 
 				this.formData.select_date.length && this.formData.date_type === 2 && this.setConcatDate()
 			}
+			if(newval&&this.type===53&&!this.operationForm.edb_id){
+				this.formData.unit='无'
+			}
 		}
 	},
 	data () {
@@ -368,7 +372,8 @@ export default {
 
 		/* 添加指标 */
 		addTargetHandle() {
-			if(this.targetList.length === 26) return this.$message.warning('添加指标个数已达上限')
+			const NUM=this.isPredict?26:MAXEDBNUM
+			if(this.targetList.length === NUM) return this.$message.warning('添加指标个数已达上限')
 			let tag = this.targetList[this.targetList.length-1].tag;
 			let index = tag_arr.findIndex(item => item === tag);
 			const item = {

+ 7 - 0
src/views/dataEntry_manage/databaseComponents/fittingResidueDia.vue

@@ -390,6 +390,13 @@ export default {
 					? this.formData.self_edb_date = [choose_obj.StartDate,choose_obj.EndDate]
 					: this.formData.depend_edb_date = [choose_obj.StartDate,choose_obj.EndDate]
 
+				// 设置目录、频度、单位
+				if(type==='self'){
+					this.formData.menu=choose_obj.ClassifyId
+					this.formData.unit=choose_obj.Unit
+					this.formData.frequency=choose_obj.Frequency
+				}
+				
 			}
 			this.getCorrelationIndex();
 		},

+ 14 - 0
src/views/dataEntry_manage/databaseComponents/jointTargetDia.vue

@@ -79,6 +79,7 @@
 							:remote-method="query=>{searchHandle(query)}"
 							@click.native="inputFocusHandle"
 							@blur="search_have_more = false"
+							@change="chooseTarget(formData.after_edb,'searchOptions')"
 						>
 							<i slot="prefix" class="el-input__icon el-icon-search"></i>
 							<el-option
@@ -106,6 +107,7 @@
 						:remote-method="query=>{searchHandle(query,'month')}"
 						@click.native="e => {inputFocusHandle(e,'month')} "
 						@blur="search_have_more = false"
+						@change="chooseTarget(formData.old_stay_edb,'searchMonthOptions')"
 						>
 							<i slot="prefix" class="el-input__icon el-icon-search"></i>
 							<el-option
@@ -354,6 +356,18 @@ export default {
 		};
 	},
 	methods: {
+		// 选中指标更新默认值
+		chooseTarget(val,key){
+			if(!val) return
+			const arr=key==='searchMonthOptions'?this.searchMonthOptions:this.searchOptions
+			let obj = arr.find(item => item.EdbInfoId === val);
+			console.log(obj);
+			this.formData.edb_name=`${obj.EdbName}/拼接`
+			this.formData.menu=obj.ClassifyId||''
+			this.formData.frequency=obj.Frequency
+			this.formData.unit=obj.Unit
+		},
+
 		/* 搜索 */
 		searchHandle(query,type) {
 			this.search_page = 1;

+ 76 - 18
src/views/dataEntry_manage/databaseComponents/operationDialog.vue

@@ -106,7 +106,7 @@
 						ref="form"
 						label-position="right"
 						inline
-						label-width="80px"
+						label-width="100px"
 						:model="formData"
 						:rules="formRules"
 						:disabled="operationForm.view"
@@ -133,6 +133,7 @@
 								min="0"
 								size="mini"
 								v-model="formData.moveVal"
+								@change="refreshTarget"
 								@keyup.native="filterCode(formData)"
 							></el-input>
 							<el-select
@@ -181,6 +182,7 @@
 								style="width: 340px"
 								clearable
 								:disabled="[5,14,61,63].includes(type)||(!operationForm.edb_id&&[6,7,75].includes(type))"
+								@change="handleFrequencyChange"
 							>
 								<el-option
 									v-for="item in frequencyArr"
@@ -226,6 +228,12 @@
 								<el-option key="平均值" label="平均值" value="平均值"/>
 							</el-select>
 						</el-form-item>
+						<el-form-item label="最新值处理" prop="new_value" v-if="type===62">
+							<el-select v-model="formData.new_value" placeholder="请选择" style="width: 340px">
+								<el-option label="默认" value=""></el-option>
+								<el-option label="均值填充" :value="'均值填充'" v-if="hasNewValueOpt"></el-option> 
+							</el-select>
+						</el-form-item>
 					</el-form>
 				</div>
 			</div>
@@ -267,6 +275,12 @@ export default {
 			type: Object,
 		}
 	},
+	computed: {
+		// 累计值计算时 均值填充判断标识
+		frequencyChangeFlag(){
+			return this.tableData[0]?`${this.tableData[0].Frequency}转${this.formData.frequency}`:''
+		}
+	},
 	watch: {
 		isOperation(newval) {
 			newval && this.getMenu();
@@ -298,10 +312,16 @@ export default {
 					moveType,
 					moveUnit,
 					moveVal,
-					calendar_type
+					calendar_type,
+					new_value:''
 				}
 				this.getDataList();
 
+				if(backData.Extra){
+					const ExtraObj=JSON.parse(backData.Extra)
+					this.formData.new_value=ExtraObj.LastValType==1?'均值填充':''
+				}
+
 				//回显时的默认options
 				this.searchOptions = [
 					{
@@ -316,6 +336,15 @@ export default {
 				: [62,63].includes(this.type)
 				? [{ label: '累计值',key: 62 },{ label: '年初至今累计值',key: 63 }]
 				: []
+		},
+		frequencyChangeFlag(n){
+			const arr=['日度转周度','日度转旬度','周度转旬度']
+			if(n&&arr.includes(n)){
+				this.hasNewValueOpt=false
+				this.formData.new_value=''
+			}else{
+				this.hasNewValueOpt=true
+			}
 		}
 	},
 	data () {
@@ -362,14 +391,14 @@ export default {
 				[5,'累计值转月/季值'],
 				[6,'同比值'],
 				[7,'同差值'],
-				[8,'N数值移动平均计算'],
-				[12,'N数值环比值'],
-				[13,'N数值环差值'],
+				[8,'N期移动均值'],
+				[12,'N环比值'],
+				[13,'N环差值'],
 				[14,'升频'],
 				[22,'时间移位'],
 				[35,'超季节性'],
 				[40,'数据调整'],
-				[52,'年化'],
+				[52,'年化'],
 				[51,'降频'],
 				[61,'累计值转月/季值'],
 				[62,'累计值'],
@@ -403,7 +432,8 @@ export default {
 				moveUnit: '天',
 				moveVal: '',
 				calendar_type: '公历',
-				value_type: '期末值'
+				value_type: '期末值',
+				new_value:'',
 			},
 			formRules,
 			unitArr,
@@ -439,6 +469,8 @@ export default {
 
 			sourceList: [],
 
+			hasNewValueOpt:true,//最新值处理的选项
+
 		};
 	},
 	methods: {
@@ -585,7 +617,8 @@ export default {
 				moveUnit: '天',
 				moveVal: '',
 				calendar_type: '公历',
-				value_type: '期末值'
+				value_type: '期末值',
+				new_value:''
 			};
 			this.$refs.form.resetFields();
 		},
@@ -613,6 +646,9 @@ export default {
 					MoveFrequency: this.formData.moveUnit,
 					MoveType: this.formData.moveType, 
 					Calendar: this.formData.calendar_type,
+					Extra:JSON.stringify({
+						LastValType:this.formData.new_value==='均值填充'?1:0
+					})
 				}
 
 				const res = this.operationForm.edb_id 
@@ -655,6 +691,26 @@ export default {
 			this.formData.targetName = name_map[this.type] || '';
 		},
 
+		// 频度变化 修改指标名
+		handleFrequencyChange(){
+			if(!this.select_target||this.operationForm.edb_id) return;
+			let obj = this.searchOptions.find(item => item.EdbInfoId === this.select_target);
+			const name_map = {
+				51: `${obj.EdbName}/${this.formData.frequency.substr(0,1)}频`,
+				62:  `${obj.EdbName}累计值/${this.formData.frequency}`,
+			}
+			this.formData.targetName=name_map[this.type] || ''
+		},
+
+		// 时间位移-移动方式修改 修改指标名
+		refreshTarget(){
+			if(this.type==22){
+				if(!this.select_target||this.operationForm.edb_id) return;
+				let obj = this.searchOptions.find(item => item.EdbInfoId === this.select_target);
+				this.formData.targetName=`${obj.EdbName}${this.moveTypeOpions.filter(item=>item.key===this.formData.moveType)[0].label}${this.formData.moveVal}${this.formData.moveUnit}`
+			}
+		},
+
 		/* 单位默认同步基础指标
 		同比 同差 频度同步 单位无 
 		转月 平均值 频度单位同步
@@ -676,20 +732,21 @@ export default {
 				['年度','Y'],
 			])
 			const name_map = {
-				5: obj.EdbName,
+				5: `${obj.EdbName}转月值`,
 				8: `${obj.EdbName}/${this.formData.n_num}${tMap.get(obj.Frequency)}MA`,
-				14: `${obj.EdbName}/${obj.Frequency}升频`,
+				14: `${obj.EdbName}/频`,
 				6: `${obj.EdbName}同比`,
 				7: `${obj.EdbName}同差`,
 				12: `${obj.EdbName}${this.formData.n_num}${obj.Frequency.slice(0,1)}环比`,
 				13: `${obj.EdbName}${this.formData.n_num}${obj.Frequency.slice(0,1)}环差`,
 				35: `${obj.EdbName}超季节性/${this.formData.n_num}年${this.formData.calendar_type==='公历'?'':'/'+this.formData.calendar_type}`,
-				52: `${obj.EdbName}年化`,
-				51: `${obj.EdbName}/${obj.Frequency}降频`,
-				61:  obj.EdbName,
-				62:  obj.EdbName,
-				63:  obj.EdbName,
-				75: `${obj.EdbName}日均值`
+				52: `${obj.EdbName}年化值`,
+				51: `${obj.EdbName}/${obj.Frequency.substr(0,1)}频`,
+				61:  `${obj.EdbName}转季值`,
+				62:  `${obj.EdbName}累计值/${obj.Frequency}`,
+				63:  `${obj.EdbName}年初至今累计值`,
+				75: `${obj.EdbName}日均值`,
+				22:	`${obj.EdbName}${this.moveTypeOpions.filter(item=>item.key===this.formData.moveType)[0].label}${this.formData.moveVal}${this.formData.moveUnit}`
 			}
 			
 			let frequerncyMap = {
@@ -702,13 +759,14 @@ export default {
 				targetName: name_map[this.type] || '',
 				frequency: frequerncyMap[this.type] || obj.Frequency,
 				unit: [5,8,14,7,35,75].includes(this.type) ? obj.Unit : '无',
-				menu: this.type===75 ? obj.ClassifyId : '',
+				menu: obj.ClassifyId || '',
 				n_num: 1,
 				moveType: 1,
 				moveUnit: '天',
 				moveVal: '',
 				calendar_type: this.formData.calendar_type,
-				value_type: this.formData.value_type
+				value_type: this.formData.value_type,
+				new_value:''
 			}
 		},
         handleSelectBtnClick(){

+ 90 - 5
src/views/dataEntry_manage/databaseComponents/util.js

@@ -52,15 +52,15 @@ export const computedTypes = [
 		type:7
 	},
 	{
-		name:'N数值移动平均计算',
+		name:'N期移动均值',
 		type:8
 	},
 	{
-		name:'N数值环比值',
+		name:'N环比值',
 		type:12
 	},
 	{
-		name:'N数值环差值',
+		name:'N环差值',
 		type:13
 	},
 	{
@@ -84,7 +84,7 @@ export const computedTypes = [
 		type: 37
 	},
 	{
-		name: '年化',
+		name: '年化',
 		type: 52
 	},
 	{
@@ -153,6 +153,74 @@ export const computedBatchTypes = [
 	}
 ]
 
+//批量指标类型
+export const computedBatchTypesV2=[
+	{
+		name:'同比值',
+		type:6
+	},
+	{
+		name:'同差值',
+		type:7
+	},
+	{
+		name:'累计值转月/季值',
+		type:'toMonthSeason'
+	},
+	{
+		name:'N期移动均值',
+		type:8
+	},
+	{
+		name:'N期环比值',
+		type:12
+	},
+	{
+		name:'N期环差值',
+		type:13
+	},
+	{
+		name:'升频',
+		type:14
+	},
+	{
+		name:'超级季节性',
+		type:35
+	},
+	{
+		name:'年化值',
+		type:52
+	},
+	{
+		name:'降频',
+		type:51
+	},
+	{
+		name: '累计值',
+		type: 'accumulate'
+	},
+	{
+		name:'指数修匀',
+		type:72
+	},
+	{
+		name:'日均值',
+		type: 75
+	},
+	{
+		name:'与常数计算',
+		type:'withNum'
+	},
+	{
+		name:'与单指标计算',
+		type:'withEDB'
+	},
+	{
+		name:'多指标求和/平均',
+		type:'multipleEDB',//81求和 82求平均
+	},
+]
+
 //频度
 export const frequencyArr = ['日度','周度','旬度','月度','季度','年度']
 //添加基础指标来源 已改为从接口获取 datamanage/edb_source/list
@@ -485,4 +553,21 @@ export const THSCommonIndexFuturesCodeArr=[
 	{value:'ths_chg_ratio_future',label:"涨跌幅"},
 	{value:'ths_swing_d_future',label:"日振幅"},
 	{value:'ths_open_interest_future',label:"持仓量"},
-]
+]
+
+// 生成序列数组
+export function generateSeriesArray(){
+	let result = [];
+	const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
+	for(let i=0;i<26;i++) result.push(String.fromCharCode(65+i))
+	for (let i = 0; i < 26; i++) {
+		const firstChar = alphabet[i];
+
+		for (let j = 0; j < 26; j++) {
+			const secondChar = alphabet[j];
+			result.push(firstChar + secondChar);
+		}
+	}
+
+	return result;
+}

+ 61 - 6
src/views/dataEntry_manage/databaseList.vue

@@ -65,6 +65,13 @@
 			<!-- <target-tree /> -->
 			<div class="main-left left" id="left" v-show="isMainLeftShow">
 				<div class="tree-cont">
+					<div style="padding-bottom:20px;padding-right:20px;display:flex;justify-content:space-between">
+						<span>目录</span>
+						<el-checkbox 
+							v-model="IsOnlyMe"
+							@change="onlyMeHandler"
+						>只看我的</el-checkbox>
+					</div>
 					<div class="target_tree">
 					<el-tree
 						ref="menuTree"
@@ -370,14 +377,16 @@
 		width="920px"
 		v-dialogDrag>
 			<div class="dialog-computed-header">
-				<el-radio-group v-model="computed_source" size="medium" @change="computed_type = 0">
+				<el-radio-group :value="1" size="medium">
 					<el-radio-button :label="1">常规计算</el-radio-button>
+					<span @click="showBatchComputedPop=true">
 					<el-radio-button :label="2">批量计算</el-radio-button>
+					</span>
 				</el-radio-group>
 			</div>
 			<ul class="computed-ul">
 				<li
-					:class="['cpmputed-li',{'act':item.type === computed_type}]" 
+					:class="['cpmputed-li',item.type === computed_type?'act':'']" 
 					v-for="item in computedTypes" 
 					:key="item.type" 
 					@click="changeComputedType(item.type)">
@@ -491,6 +500,16 @@
 			@addCallBack="addComputedCallBack"
 			@lookHistory="id => {toHistoryPage(id,$route.matched);lookEdbId=id;}"
 		/>
+
+		<!-- 批量计算指标 -->
+		<batchComputedV2 
+			:isShow="showBatchComputedPop" 
+			:type="computed_type"
+			:operationForm="operationForm"
+			@close="isOpenComputed=false;showBatchComputedPop=false" 
+			@closeSelf="handleCloseBatchPopSelf"
+			@addCallBack="addComputedCallBack"
+		/>
 	</div>
 </template>
 
@@ -519,6 +538,7 @@ import EdbLabelList from '@/components/edbLabelList.vue';
 import chartTrendRender from './databaseComponents/chartTrendRender.vue';
 import edbDetailData from './databaseComponents/edbDetailData.vue';
 import SmoothEdbDialog from './databaseComponents/smoothEdbDialog.vue';
+import batchComputedV2 from './databaseComponents/batchComputedV2.vue';
 export default {
 	name: '',
 	components: {
@@ -543,6 +563,7 @@ export default {
 		chartTrendRender,
 		edbDetailData,
 		SmoothEdbDialog,
+		batchComputedV2
 	},
 	directives: {
 		drag(el, bindings,vnode) {
@@ -580,6 +601,7 @@ export default {
 	},
 	data() {
 		return {
+			IsOnlyMe:false,//只看我的
 			showData: false,
 			search_txt: '', //搜索词
 			searchOptions:[],//搜索到的筛选列表
@@ -736,6 +758,8 @@ export default {
 			activeName:'second',
 
 			isMainLeftShow:true,
+
+			showBatchComputedPop:false,
 		};
 	},
 	watch: {
@@ -851,7 +875,7 @@ export default {
 		/* 获取树分类数据 */
 		getTreeData(params) {
 			
-			dataBaseInterface.targetCatalog({ParentId:0}).then(res=>{
+			dataBaseInterface.targetCatalog({IsOnlyMe:this.IsOnlyMe,ParentId:0}).then(res=>{
 				if(res.Ret===200){
 					const arr=res.Data.AllNodes || []
 					this.treeData=arr.map(item=>{
@@ -962,6 +986,7 @@ export default {
 				PageSize:this.PageSize,
 				CurrentIndex:this.CurrentIndex,
 				ClassifyId:this.select_classifyId,
+				IsOnlyMe:this.IsOnlyMe
 			}).then(res=>{
 				if(res.Ret!==200) return
 				if(res.Data){
@@ -1608,6 +1633,7 @@ export default {
 			this.calulateList = [];
 			this.calulateForm = {};
 			this.operationForm = {};
+			this.computed_type=0
 			this.isOpenComputed = true;
 		},
 		/* 新增计算指标回调 */
@@ -1616,6 +1642,9 @@ export default {
 			this.computed_source = 1;
 			this.showAssociateChart=false
 			this.showAssociateComputeData=false
+			this.showBatchComputedPop=false
+			this.isOpenComputed = false
+			console.log(type, params);
 			// this.getTreeData();
 			type === 'add' ? this.getTreeData(params) : this.getTreeData();
 			type === 'edit' && this.initGetData()
@@ -1711,7 +1740,7 @@ export default {
 						end_date: item.EndDate
 					}
 				})
-				const { EdbInfoId,CalculateFormula,EdbName,Unit,Frequency,EmptyType,MaxEmptyType } = res.EdbInfoDetail;
+				const { EdbInfoId,CalculateFormula,EdbName,Unit,Frequency,EmptyType,MaxEmptyType,Extra } = res.EdbInfoDetail;
 				/* 公式和表单 */
 				this.calulateForm =  {
 					edb_id: EdbInfoId,
@@ -1722,9 +1751,18 @@ export default {
 					frequency: Frequency,
 					emptyType: EmptyType,
 					maxEmptyType: MaxEmptyType,
+					Extra,
 					view
 				};
 			} else  {
+				// 多指标求和求平均
+				if([81,82].includes(type)){
+					this.operationForm={...res,view}
+					this.showBatchComputedPop=true
+					return
+				}
+
+
 				let dataInfo = res.EdbInfoDetail;
 				let old_edb = res.CalculateList;
 
@@ -1734,6 +1772,7 @@ export default {
 					frequency: dataInfo.Frequency,
 					unit: dataInfo.Unit,
 					menu: menuArrId||[],
+					Extra:dataInfo.Extra,
 					view
 				}
 
@@ -1770,6 +1809,7 @@ export default {
 						view
 					}
 				}
+				
 			}
 		},
 
@@ -1916,13 +1956,21 @@ export default {
 				this.dynamicNode&&this.resetNodeStyle(this.dynamicNode)
 			})
 		},
+		//只看我的
+		onlyMeHandler(){
+			this.getTreeData()
+
+			this.CurrentIndex = 1;
+			this.$refs.listRef.scrollTop = 0;
+			this.getEdbChartList();
+		},
 		//绑定el-tree的load属性
 		async getLazyTreeData (node,resolve){
 			if(node.level===0){
 				resolve(this.treeData)
 			}else{
 				let arr=[]
-				const res=await dataBaseInterface.targetCatalog({ParentId:node.data.ClassifyId})
+				const res=await dataBaseInterface.targetCatalog({ParentId:node.data.ClassifyId,IsOnlyMe:this.IsOnlyMe})
 				if (res.Ret === 200) {
 					const temarr = res.Data.AllNodes || [];
 					arr=temarr.map(item=>{
@@ -1972,6 +2020,13 @@ export default {
 		// 添加wind wsd指标成功
 		addTargetSuccess(params){
 			this.getTreeData(params);
+		},
+
+		handleCloseBatchPopSelf(){
+			this.showBatchComputedPop=false
+			this.$nextTick(()=>{//重新打开计算指标选择类型弹窗
+				this.isOpenComputed=true
+			})
 		}
 	},
 	//离开页面时保存标签
@@ -2087,7 +2142,7 @@ export default {
 			}
 			.target_tree {
 				color: #333;
-				height: calc(100vh - 350px);
+				height: calc(100vh - 400px); 
 				overflow: auto;
 				.label-input .el-input__inner {
 					height: 25px;