computedDialog.vue 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846
  1. <template>
  2. <el-dialog
  3. :visible.sync="isOpenComputed"
  4. :close-on-click-modal="false"
  5. :modal-append-to-body="false"
  6. @close="cancelHandle"
  7. custom-class="computed-dialog fit-screen-dialog"
  8. center
  9. top="6vh"
  10. v-dialogDrag
  11. >
  12. <div slot="title" style="display: flex; align-items: center">
  13. <img
  14. :src="$icons.computed"
  15. style="color: #fff; width: 16px; height: 16px; margin-right: 5px"
  16. />
  17. <span style="font-size: 16px">{{ titleMap.get(title) }}</span>
  18. </div>
  19. <div class="dialog-main">
  20. <ul class="add-cont">
  21. <li class="add-li" v-for="(list, index) in addList" :key="index">
  22. <span class="li-tag">{{ list.tag }}</span>
  23. <el-select
  24. v-model="list.target"
  25. v-loadMore="searchLoad"
  26. :filterable="!list.target"
  27. clearable
  28. :placeholder="$t('Edb.InputHolderAll.input_name')"
  29. style="width: 400px"
  30. @change="chooseTarget"
  31. @clear="clearHandle(index)"
  32. :disabled="calulateForm.view"
  33. remote
  34. :remote-method="searchTarget"
  35. @click.native="inputFocusHandle"
  36. >
  37. <i slot="prefix" class="el-input__icon el-icon-search"></i>
  38. <el-option
  39. v-for="item in searchOptions"
  40. :key="item.EdbInfoId"
  41. :label="$parent.currentLang==='en'?(item.EdbNameEn||item.EdbName):item.EdbName"
  42. :value="item.EdbInfoId"
  43. :disabled="!item.HaveOperaAuth"
  44. >
  45. <edbDetailPopover :info="item">
  46. <div slot="reference">
  47. <img
  48. :src="$icons.lock_ico2"
  49. width="18"
  50. height="18"
  51. style="vertical-align:middle"
  52. v-if="!item.HaveOperaAuth"
  53. />
  54. {{$parent.currentLang==='en'?(item.EdbNameEn||item.EdbName):item.EdbName}}
  55. </div>
  56. </edbDetailPopover>
  57. </el-option>
  58. </el-select>
  59. <i class="el-icon-tickets" style="color:#409EFF;font-size:18px" @click="$emit('lookHistory',list.target)" v-if="list.target"/>
  60. <i
  61. class="el-icon-error del-tag"
  62. v-if="index > 3 && !calulateForm.view"
  63. @click="delTarget(index)"
  64. />
  65. <span :class="{
  66. 'target-date': true,
  67. 'newest': list.end_date===newestDate
  68. }" v-if="list.start_date">{{
  69. `${list.start_date}${$t('Common.to')}${list.end_date}`
  70. }}</span>
  71. </li>
  72. </ul>
  73. <span class="add-icon" @click="addTargetHandle" v-if="!calulateForm.view">
  74. <i
  75. class="el-icon-circle-plus-outline"
  76. style="color: #5882ef; font-size: 16px"
  77. />
  78. <!-- 添加更多参数 -->{{$t('EtaBasePage.add_more_param')}}
  79. </span>
  80. <div class="computed-min">
  81. <div class="computed-section" v-if="edbSource !== 'predict'">
  82. <div>
  83. <label class="label"><!-- 生成指标时间序列 -->{{$t('EtaBasePage.create_edb_time_index')}}</label>
  84. <div style="width:200px;display: inline-block;">
  85. <el-cascader
  86. v-model="selectTimeSeriesVal"
  87. style="width:100%"
  88. :options="timeSeriesOpt"
  89. :props="{emitPath:false}"
  90. :show-all-levels="false"
  91. placeholder="请选择"
  92. :disabled="calulateForm.view"
  93. ></el-cascader>
  94. </div>
  95. </div>
  96. </div>
  97. <div class="computed-section">
  98. <div>
  99. <label class="label"><!-- 空值处理 -->{{$t('EtaBasePage.null_val_deal')}}
  100. <el-tooltip placement="top">
  101. <div slot="content" v-html="formTips['null-val']" style="width:300px;line-height:20px;"/>
  102. <i class="el-icon-question"/>
  103. </el-tooltip>
  104. </label>
  105. <el-select
  106. v-model="nullValueForm.nullValueWay"
  107. placeholder="请选择"
  108. :disabled="calulateForm.view"
  109. >
  110. <el-option
  111. v-for="item in nullWayOptions"
  112. :key="item.value"
  113. :label="item.label"
  114. :value="item.value"
  115. >
  116. </el-option>
  117. </el-select>
  118. </div>
  119. <div style="margin-left: 120px" v-if="showMaxNullDeal">
  120. <label class="label"><!-- MAX、MIN空值处理 --> {{$t('EtaBasePage.max_null_val')}}
  121. <el-tooltip placement="top">
  122. <div slot="content" v-html="formTips['max-null-val']" style="width:300px;line-height:20px;"/>
  123. <i class="el-icon-question"/>
  124. </el-tooltip>
  125. </label>
  126. <el-select
  127. v-model="nullValueForm.maxNullWay"
  128. placeholder="请选择"
  129. :disabled="calulateForm.view"
  130. >
  131. <el-option label="等于0" :value="1" />
  132. <el-option label="跳过空值" :value="2" />
  133. </el-select>
  134. </div>
  135. </div>
  136. <div class="computed-section">
  137. <label class="label"><!-- 计算公式 -->{{$t('EtaBasePage.calculate_formula')}}
  138. <el-tooltip placement="top">
  139. <div slot="content" v-html="formTips['formula']" style="width:300px;line-height:20px;"/>
  140. <i class="el-icon-question"/>
  141. </el-tooltip>
  142. </label>
  143. <!-- <el-input placeholder="请输入公式" v-model="formula" clearable :disabled="calulateForm.view">
  144. </el-input> -->
  145. <ul class="formula-list">
  146. <li style="margin-bottom: 15px;">
  147. <el-input :placeholder="$t('EtaBasePage.input_formula_msg')" v-model="formulaList[0].formula" clearable :disabled="calulateForm.view" style="width: 600px"/>
  148. <span v-if="formulaDateArr.length" class="date-section-text">{{formulaDateArr[formulaDateArr.length-1]}}(含)之后</span>
  149. <span class="example-txt">{{$t('EtaBasePage.formula_examp')}}:A*0.5+B*C*1.2+120-MAX(A,B,C) &nbsp;{{$t('EtaBasePage.func_examp')}}:MAX(),MIN(),ln(A),log(a,A),abs(),exp(),pow(),round()</span>
  150. </li>
  151. <li class="formula-item" v-for="(item,index) in formulaList.slice(1)" :key="index+1">
  152. <el-input
  153. :placeholder="$t('EtaBasePage.input_formula_msg')"
  154. v-model="item.formula"
  155. clearable
  156. :disabled="calulateForm.view"
  157. style="width: 220px"
  158. />
  159. <el-date-picker
  160. v-model="item.date"
  161. type="date"
  162. value-format="yyyy-MM-dd"
  163. style="margin: 0 10px;width: 220px"
  164. :placeholder="$t('EtaBasePage.input_date_msg')"
  165. :disabled="calulateForm.view"
  166. @change="selectFormulaDate($event,item)"
  167. />
  168. <i class="el-icon-circle-close" style="font-size:20px;" v-if="!calulateForm.view" @click="removeFormulaItem(index+1)"/>
  169. <template v-if="formulaDateArr.length&&item.date">
  170. <span v-if="item.date===formulaDateArr[0]" class="date-section-text">{{formulaDateArr[0]}}之前</span>
  171. <span v-else class="date-section-text">{{formulaDateArr[formulaDateArr.findIndex(_ =>_ ===item.date)-1]}}(含)——{{item.date}}</span>
  172. </template>
  173. </li>
  174. </ul>
  175. </div>
  176. <el-button
  177. v-if="!calulateForm.view"
  178. icon="el-icon-plus"
  179. style="margin-left:70px;"
  180. @click="addFormulaHandle"
  181. ><!-- 新增分段 -->{{$t('EtaBasePage.add_segm')}}</el-button>
  182. </div>
  183. <el-form
  184. ref="diaForm"
  185. label-position="right"
  186. inline
  187. label-width="120px"
  188. :model="formData"
  189. :rules="formRules"
  190. :disabled="calulateForm.view"
  191. >
  192. <el-form-item :label="$t('Edb.Detail.e_name')" prop="targetName">
  193. <el-input
  194. v-model="formData.targetName"
  195. style="width: 340px"
  196. :placeholder="$t('Edb.InputHolderAll.input_name')"
  197. />
  198. </el-form-item>
  199. <el-form-item :label="$t('Edb.Detail.e_unit')" prop="unit">
  200. <selectUnit v-model="formData.unit" style="width: 340px" />
  201. </el-form-item>
  202. <el-form-item :label="$t('Edb.Detail.e_menu')" prop="menu">
  203. <el-cascader
  204. v-model="formData.menu"
  205. :options="options"
  206. :props="levelProps"
  207. clearable
  208. :placeholder="$t('Edb.InputHolderAll.input_menu')"
  209. />
  210. </el-form-item>
  211. <el-form-item :label="$t('Edb.Detail.e_fre')" prop="frequency">
  212. <el-select
  213. v-model="formData.frequency"
  214. :placeholder="$t('Edb.InputHolderAll.input_fre')"
  215. style="width: 340px"
  216. clearable
  217. >
  218. <el-option
  219. v-for="item in frequencyArr"
  220. :key="item"
  221. :label="item"
  222. :value="item"
  223. >
  224. </el-option>
  225. </el-select>
  226. </el-form-item>
  227. </el-form>
  228. </div>
  229. <div class="dia-bot" v-if="!calulateForm.view">
  230. <el-button
  231. type="primary"
  232. style="margin-right: 20px"
  233. @click="saveHandle"
  234. :loading="dataloading"
  235. v-if="title==='计算指标'"
  236. ><!-- 生成计算指标 -->{{$t('Edb.CalculateBtns.calculate')}}</el-button
  237. >
  238. <el-button
  239. type="primary"
  240. style="margin-right: 20px"
  241. @click="saveHandle"
  242. v-else
  243. ><!-- 保存 -->{{$t('Dialog.confirm_save_btn')}}</el-button
  244. >
  245. <el-button type="primary" plain @click="cancelHandle('cancel')"><!-- 取消 -->{{$t('Dialog.cancel_btn')}}</el-button>
  246. </div>
  247. <el-popover
  248. placement="top-start"
  249. width="360"
  250. trigger="click">
  251. <p style="padding:30px;line-height:25px;" v-html="$parent.tips.get(type)"/>
  252. <span slot="reference" class="tip-label"><!-- 公式说明 -->{{$t('Edb.formula_instru')}}</span>
  253. </el-popover>
  254. </el-dialog>
  255. </template>
  256. <script>
  257. import { dataBaseInterface } from '@/api/api.js';
  258. import * as preDictEdbInterface from '@/api/modules/predictEdbApi.js';
  259. import { formRules,frequencyArr } from '../databaseComponents/util';
  260. import { unitArr } from '@/utils/defaultOptions';
  261. import {generateSeriesArray} from './util'
  262. const MAXEDBNUM=50//最大可添加的指标数量
  263. const tag_arr = generateSeriesArray();
  264. // for(let i=0;i<26;i++) tag_arr.push(String.fromCharCode(65+i));
  265. export default {
  266. name: '',
  267. props: {
  268. isOpenComputed: {
  269. type: Boolean,
  270. },
  271. title: {
  272. type: String,
  273. default: '计算指标',
  274. },
  275. calulateForm: {
  276. type: Object,
  277. },
  278. calulateList: {
  279. type: Array,
  280. },
  281. edbSource: { // ''||'predict'
  282. type: String,
  283. default: ''
  284. }
  285. },
  286. computed: {
  287. type() {
  288. return this.edbSource ? 31 : 4;
  289. },
  290. /* max空值处理显示 当输入的公式包含MAX、MIN且空值处理为0时,输入公式失焦后出现右侧选项; */
  291. showMaxNullDeal() {
  292. let haveMaxOrMin = this.formulaList.some(_ => _.formula.toUpperCase().includes('MAX') || _.formula.toUpperCase().includes('MIN'))
  293. return haveMaxOrMin && this.nullValueForm.nullValueWay===4
  294. },
  295. formulaDateArr() {
  296. return this.formulaList.map(_ => _.date).filter(_ => _).sort((a,b) => new Date(a)-new Date(b))
  297. },
  298. timeSeriesOpt(){
  299. const arr=[
  300. {
  301. label:'指定指标时间序列',
  302. value:'0',
  303. children:[]
  304. },
  305. {
  306. label:'所有指标时间序列并集',
  307. value:'all',
  308. }
  309. ]
  310. arr[0].children=this.addList.filter(item=>item.target).map(item=>{
  311. return {
  312. label:`指标${item.tag}`,
  313. value:item.tag
  314. }
  315. })
  316. return arr
  317. }
  318. },
  319. watch: {
  320. isOpenComputed(newval) {
  321. newval && this.getMenu();
  322. // newval && this.searchTarget('');
  323. /* 回显 */
  324. if (this.calulateList.length && newval) {
  325. this.addList = _.cloneDeep(this.calulateList);
  326. this.formulaList = JSON.parse(this.calulateForm.formula).map(_ => ({
  327. formula: _.f,
  328. date: _.d||''
  329. }));
  330. this.formData = {
  331. targetName: this.calulateForm.targetName,
  332. unit: this.calulateForm.unit,
  333. menu: this.calulateForm.menu,
  334. frequency: this.calulateForm.frequency,
  335. };
  336. this.nullValueForm = {
  337. nullValueWay: this.calulateForm.emptyType,
  338. maxNullWay: this.calulateForm.maxEmptyType,
  339. }
  340. this.searchOptions = this.calulateList.map(item => ({
  341. EdbInfoId: item.target,
  342. EdbName: item.edb_name,
  343. }))
  344. if(this.calulateForm.Extra){
  345. const ExtraObj=JSON.parse(this.calulateForm.Extra)
  346. this.selectTimeSeriesVal=ExtraObj.DateTag
  347. }
  348. this.getNewestDate();
  349. }
  350. },
  351. 'addList':{
  352. handler(n){
  353. if(this.selectTimeSeriesVal=='all') return
  354. const arr=this.addList.filter(item=>item.target).map(item=>{
  355. return {
  356. label:`指标${item.tag}`,
  357. value:item.tag
  358. }
  359. })
  360. if(!arr.length) return
  361. if(!this.selectTimeSeriesVal){
  362. this.selectTimeSeriesVal=arr[0].value
  363. }else{//已经有选择的值了
  364. let flag=false
  365. arr.forEach(item=>{
  366. if(item.value==this.selectTimeSeriesVal){
  367. flag=true
  368. }
  369. })
  370. if(!flag){
  371. this.selectTimeSeriesVal=arr[0].value
  372. }
  373. }
  374. },
  375. deep:true
  376. }
  377. },
  378. data() {
  379. return {
  380. options: [],
  381. levelProps: {
  382. label: 'ClassifyName',
  383. value: 'ClassifyId',
  384. children: 'Children',
  385. checkStrictly: true
  386. },
  387. frequencyArr,
  388. formRules,
  389. unitArr,
  390. addList: [
  391. {
  392. tag: tag_arr[0],
  393. target: '',
  394. start_date: '',
  395. end_date: '',
  396. },
  397. {
  398. tag: tag_arr[1],
  399. target: '',
  400. start_date: '',
  401. end_date: '',
  402. },
  403. {
  404. tag: tag_arr[2],
  405. target: '',
  406. start_date: '',
  407. end_date: '',
  408. },
  409. {
  410. tag: tag_arr[3],
  411. target: '',
  412. start_date: '',
  413. end_date: '',
  414. },
  415. ],
  416. searchOptions: [],
  417. formula: '', //计算公式
  418. formulaList: [ //公式数组
  419. { formula: '', }
  420. ],
  421. dataloading: false,
  422. formData: {
  423. targetName: '',
  424. unit: '',
  425. menu: '',
  426. frequency: '',
  427. },
  428. search_have_more: false,
  429. search_page: 1,
  430. current_search:'',
  431. newestDate: '',
  432. nullValueForm: {
  433. nullValueWay: 0,
  434. maxNullWay: 1
  435. },//空值处理
  436. nullWayOptions: [
  437. { label: '查找前后35天最近值',value: 0 },
  438. { label: '不计算',value: 1 },
  439. { label: '前值填充',value: 2 },
  440. { label: '后值填充',value: 3 },
  441. { label: '等于0',value: 4 },
  442. ],
  443. selectTimeSeriesVal:'',
  444. formTips: {
  445. 'null-val': `1、查找前后35天最近值:在参与计算的日期序列上某指标无值时,该指标往前/往后找距离最近的值作为当天的值进行计算,遍历允许跨年,往前最多35天,往后最多35天<br>
  446. 2、不计算:只要有一个指标在某个日期没有值(即空值),则计算指标在该日期没有值 <br>
  447. 3、前值填充:空值优先以最近的前值填充,没有前值时,用后值填充 <br>
  448. 4、后值填充:空值优先以最近的后值填充,没有前值时,用后值填充 <br>
  449. 5、等于0:空值以0值参与计算 <br>
  450. 注意:此处缺失值的处理,作用于数据全部时间段`,
  451. 'max-null-val': `MAX、MIN公式中指标存在空值时按如下规则处理:<br>
  452. 1、等于0,空值用0参与计算;<br>
  453. 2、跳过空值,去除空值指标,剩余指标进行计算,若该日期所有指标均为空值,则该日期无值;`,
  454. 'formula':`1、支持新增分段,实现不同分段使用不同的计算公式,若未新增分段,则所有日期序列用统一公式计算<br>
  455. 2、新增分段需配置新公式和时间节点,在时间节点之前(不含)使用新公式,在时间节点之后(含)使用已配置公式,每个分段公式支持修改<br>
  456. 3、分段时间节点不允许重复,不允许超出第一个指标的日期区间`
  457. },
  458. titleMap: new Map([
  459. ['计算指标',this.$t('EtaBasePage.calculate_title')],
  460. ['编辑计算指标',this.$t('EtaBasePage.calculate_edit_title')],
  461. ['查看计算指标',this.$t('EtaBasePage.calculate_view_title')],
  462. ])
  463. };
  464. },
  465. methods: {
  466. /* 获取目录结构 */
  467. async getMenu() {
  468. const res = this.edbSource === 'predict'
  469. ? await preDictEdbInterface.classifyListV2()
  470. : await dataBaseInterface.menuListV3()
  471. if (res.Ret !== 200) return
  472. this.filterNodes(res.Data.AllNodes||[]);
  473. this.options = res.Data.AllNodes || [];
  474. },
  475. // 递归改变第三级目录结构
  476. filterNodes(arr) {
  477. arr.length &&
  478. arr.forEach((item) => {
  479. item.Children.length && this.filterNodes(item.Children);
  480. if (!item.Children.length) {
  481. delete item.Children;
  482. }
  483. });
  484. },
  485. /* 添加额外的指标列 */
  486. addTargetHandle() {
  487. const MAXNUM=this.edbSource === 'predict'?26:MAXEDBNUM
  488. if(this.addList.length >=MAXNUM) return this.$message.warning(this.$t('EtaBasePage.num_overrun_msg'))
  489. let tag = this.addList[this.addList.length-1].tag;
  490. let index = tag_arr.findIndex(item => item === tag);
  491. const item = {
  492. tag: tag_arr[index+1],
  493. target: '',
  494. start_date: '',
  495. end_date: ''
  496. };
  497. this.addList.push(item);
  498. },
  499. /* 搜索指标 */
  500. searchTarget(query) {
  501. this.search_page = 1;
  502. this.current_search = query;
  503. this.searchApi(this.current_search);
  504. },
  505. /* 聚焦获取当前检索 */
  506. inputFocusHandle(e) {
  507. this.search_page = 1;
  508. this.current_search = e.target.value;
  509. this.searchApi(this.current_search);
  510. },
  511. async searchApi(query,page=1) {
  512. const res = this.edbSource === 'predict'
  513. ? await preDictEdbInterface.edbSearch({
  514. Keyword: query,
  515. CurrentIndex: page,
  516. FilterSource: this.type === 45 ? 3 : this.type === 66 ? 6 : 1,
  517. Frequency: this.type===64?'季度': ''
  518. })
  519. : await dataBaseInterface.targetSearchByPage({
  520. KeyWord:query,
  521. CurrentIndex: page,
  522. FilterSource: this.type === 14 ? 3 : this.type === 63 ? 6 : 1,
  523. Frequency: this.type===61?'季度': ''
  524. })
  525. if(res.Ret !== 200) return
  526. const { List,Paging } = res.Data;
  527. this.search_have_more = page < Paging.Pages;
  528. this.searchOptions = page === 1 ? List : this.searchOptions.concat(List);
  529. },
  530. searchLoad() {
  531. if(!this.search_have_more) return;
  532. this.searchApi(this.current_search,++this.search_page)
  533. },
  534. /* 选中指标 显示开始日期结束日期 */
  535. chooseTarget(val) {
  536. if (val) {
  537. const choose_obj = this.searchOptions.find(
  538. (item) => item.EdbInfoId === val
  539. );
  540. this.addList.forEach((list) => {
  541. if (list.target === val) {
  542. list.start_date = choose_obj.StartDate;
  543. list.end_date = choose_obj.EndDate;
  544. this.getNewestDate();
  545. }
  546. });
  547. }
  548. },
  549. /* 获取所选日期最早日期 */
  550. getNewestDate() {
  551. let dateArr = this.addList.filter(_ => _.end_date).map(_ => new Date(_.end_date).getTime())
  552. let earliestDate = Math.min(...dateArr);
  553. let sameDateArr = dateArr.filter(_ => _===earliestDate)
  554. if(dateArr.length === 1 || sameDateArr.length===dateArr.length) {
  555. this.newestDate = '';
  556. return
  557. }
  558. this.newestDate = this.$moment(Math.min(...dateArr)).format('YYYY-MM-DD');
  559. },
  560. /* 清空指标和关联日期 */
  561. clearHandle(index) {
  562. this.addList[index].start_date = '';
  563. this.addList[index].end_date = '';
  564. this.getNewestDate();
  565. },
  566. // 删除指标
  567. delTarget(index) {
  568. this.addList.splice(index, 1);
  569. this.getNewestDate();
  570. },
  571. async saveHandle() {
  572. if (!this.formulaList[0].formula) return this.$message.warning(/* '计算公式不能为空' */this.$t('EtaBasePage.input_formula_valid'));
  573. await this.$refs.diaForm.validate();
  574. // 指标id数组
  575. let EdbInfoIdArr = this.addList.filter((item) => item.target).map((item) => ({
  576. EdbInfoId: item.target,
  577. FromTag: item.tag,
  578. }));
  579. let formulaArr = this.formulaList
  580. .filter((_,index) => index===0||(index>0&&_.formula&&_.date))
  581. .map(_ => ({f: _.formula,d: _.date}))
  582. const { nullValueWay,maxNullWay } = this.nullValueForm;
  583. let params = {
  584. CalculateFormula: JSON.stringify(formulaArr),
  585. ClassifyId: this.formData.menu[this.formData.menu.length - 1] || 0,
  586. EdbName: this.formData.targetName,
  587. Frequency: this.formData.frequency,
  588. Unit: this.formData.unit,
  589. EdbInfoIdArr,
  590. EmptyType: nullValueWay,
  591. MaxEmptyType: maxNullWay,
  592. Extra:JSON.stringify({
  593. DateTag:this.selectTimeSeriesVal
  594. })
  595. };
  596. this.dataloading = true;
  597. let res;
  598. if(this.edbSource === 'predict') {
  599. res = await preDictEdbInterface.calculateEdbSave(this.calulateForm.edb_id ? {...params,EdbInfoId:this.calulateForm.edb_id } : params)
  600. }else {
  601. res = this.calulateForm.edb_id
  602. ? await dataBaseInterface.calculateEdit({...params,EdbInfoId: this.calulateForm.edb_id})
  603. : await dataBaseInterface.calculateAdd(params)
  604. }
  605. this.dataloading = false;
  606. if (res.Ret !== 200) return
  607. this.$message.success(res.Msg);
  608. this.calulateForm.edb_id
  609. ? this.$emit('addCallBack','edit')
  610. : this.$emit('addCallBack','add',{ code:res.Data.UniqueCode,id:res.Data.EdbInfoId,classifyId:params.ClassifyId });
  611. this.init();
  612. },
  613. /* 新增公式分段 */
  614. addFormulaHandle() {
  615. let addItem = {
  616. formula: this.formulaList[this.formulaList.length-1].formula,
  617. date: ''
  618. }
  619. this.formulaList.push(addItem)
  620. },
  621. /* 移除公式 */
  622. removeFormulaItem(index) {
  623. this.formulaList.splice(index,1)
  624. },
  625. /* 选择日期 检验排 */
  626. selectFormulaDate(val,item) {
  627. console.log(val,item)
  628. const { start_date,end_date } = this.addList[0];
  629. if(!start_date) return
  630. let dateStamp = new Date(val).getTime(),
  631. startStamp = new Date(start_date).getTime(),
  632. endStamp = new Date(end_date).getTime();
  633. if (dateStamp > endStamp || dateStamp < startStamp) {
  634. item.date = '';
  635. return this.$message.warning('分段日期必须在第一个指标日期区间')
  636. }
  637. else if(this.formulaList.filter(_ => _.date===val).length>1) {
  638. item.date = '';
  639. return this.$message.warning('分段日期不可重复')
  640. }
  641. },
  642. init() {
  643. this.$refs.diaForm.resetFields();
  644. this.addList = [
  645. {
  646. tag: tag_arr[0],
  647. target: '',
  648. start_date: '',
  649. end_date: '',
  650. },
  651. {
  652. tag: tag_arr[1],
  653. target: '',
  654. start_date: '',
  655. end_date: '',
  656. },
  657. {
  658. tag: tag_arr[2],
  659. target: '',
  660. start_date: '',
  661. end_date: '',
  662. },
  663. {
  664. tag: tag_arr[3],
  665. target: '',
  666. start_date: '',
  667. end_date: '',
  668. },
  669. ];
  670. this.searchOptions = [];
  671. this.formula = '';
  672. this.formData = {
  673. targetName: '',
  674. unit: '',
  675. menu: '',
  676. frequency: '',
  677. };
  678. this.formulaList = [
  679. { formula: '' }
  680. ]
  681. this.nullValueForm = {
  682. nullValueWay: 0,
  683. maxNullWay: 1
  684. }
  685. },
  686. cancelHandle(type) {
  687. this.init();
  688. this.$emit('cancel');
  689. type==='cancel' && !this.calulateForm.edb_id && this.$emit('openPrev');
  690. },
  691. },
  692. mounted() {},
  693. };
  694. </script>
  695. <style lang="scss">
  696. .computed-dialog {
  697. max-width: 1200px !important;
  698. width:85vw;
  699. overflow: hidden;
  700. div::-webkit-scrollbar {
  701. width: 6px !important;
  702. }
  703. .el-dialog__body {
  704. max-height: 840px;
  705. overflow: auto;
  706. }
  707. .dialog-main {
  708. padding: 25px 42px 25px 25px;
  709. @media screen and (max-height:850px){
  710. box-sizing: border-box;
  711. height: 65vh;
  712. overflow-y: auto;
  713. }
  714. .el-cascader .el-input {
  715. width: 340px;
  716. }
  717. .add-cont {
  718. display: flex;
  719. flex-wrap: wrap;
  720. justify-content: space-between;
  721. .add-li {
  722. position: relative;
  723. margin-bottom: 48px;
  724. .li-tag {
  725. font-size: 16px;
  726. margin-right: 8px;
  727. }
  728. .del-tag {
  729. position: absolute;
  730. right: -30px;
  731. top: 12px;
  732. font-size: 16px;
  733. cursor: pointer;
  734. }
  735. .target-date {
  736. color: #5882ef;
  737. position: absolute;
  738. bottom: -25px;
  739. left: 24px;
  740. &.newest {
  741. color: #f00;
  742. }
  743. }
  744. }
  745. }
  746. .add-icon {
  747. font-size: 16px;
  748. color: #5882ef;
  749. cursor: pointer;
  750. }
  751. .computed-min {
  752. margin: 50px 0;
  753. padding-bottom: 40px;
  754. border-bottom: 1px dashed #aab4cc;
  755. .computed-section {
  756. display: flex;
  757. margin-top: 20px;
  758. .el-cascader .el-input {
  759. width: 100%;
  760. }
  761. }
  762. .label {
  763. padding:10px 10px 10px 0;
  764. }
  765. .example-txt {
  766. display: block;
  767. margin-top: 10px;
  768. }
  769. .formula-item {
  770. display: flex;
  771. align-items: center;
  772. margin-bottom: 15px;
  773. }
  774. .date-section-text {
  775. margin-left: 15px;
  776. }
  777. }
  778. }
  779. .dia-bot {
  780. padding-bottom: 40px;
  781. display: flex;
  782. justify-content: center;
  783. }
  784. .tip-label {
  785. position: absolute;
  786. bottom: 30px;
  787. right: 30px;
  788. color: #409EFF;
  789. cursor: pointer;
  790. }
  791. }
  792. </style>