computedDialog.vue 22 KB

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