FormulaCalculate.vue 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879
  1. <script setup>
  2. import apiDataEDB from '@/api/dataEDB'
  3. import { showToast } from 'vant';
  4. import {computed, reactive, ref,watch} from 'vue'
  5. import SelectEDB from './SelectEDB.vue'
  6. import EDBHistory from '@/views/dataEDB/components/EDBHistory.vue'
  7. import SelectEDBClassify from '../../components/SelectEDBClassify.vue'
  8. import SelectEDBUnit from '../../components/SelectEDBUnit.vue'
  9. import SelectEDBFrequency from '../../components/SelectEDBFrequency.vue'
  10. import {calculateTypeTipsMap,MAXADDEDBNUM} from '../../util/config'
  11. import {generateSeriesArray} from '@/views/dataEDB/util/util.js'
  12. import { useRoute, useRouter } from 'vue-router';
  13. import {useToHistoryPage} from '@/hooks/edb/useToHistoryPage'
  14. const {toHistoryPage} = useToHistoryPage()
  15. import SelectDate from '@/components/SelectDate.vue'
  16. const route=useRoute()
  17. const router=useRouter()
  18. const props=defineProps({
  19. edbInfo:{
  20. type:Object,
  21. default:null
  22. }
  23. })
  24. watch(
  25. ()=>props.edbInfo,
  26. ()=>{
  27. if(['edit','preview'].includes(route.query.type)){
  28. edbList.value=props.edbInfo.CalculateList.map(item=>{
  29. return {
  30. tag:item.FromTag,
  31. target:item.FromEdbInfoId,
  32. startDate:item.StartDate,
  33. endDate:item.EndDate,
  34. name:item.FromEdbName
  35. }
  36. })
  37. formulaList.value= JSON.parse(props.edbInfo.EdbInfoDetail.CalculateFormula).map(_ =>({
  38. formula: _.f,
  39. date: _.d
  40. }))
  41. baseInfo.name=props.edbInfo.EdbInfoDetail.EdbName
  42. baseInfo.unit=props.edbInfo.EdbInfoDetail.Unit
  43. baseInfo.classify=props.edbInfo.EdbInfoDetail.ClassifyId
  44. baseInfo.frequency=props.edbInfo.EdbInfoDetail.Frequency
  45. baseInfo.nullValueWay=props.edbInfo.EdbInfoDetail.EmptyType
  46. baseInfo.maxNullWay=props.edbInfo.EdbInfoDetail.MaxEmptyType
  47. nullWayStr.value = nullWayOptions.value.find(_ =>_.value===baseInfo.nullValueWay).label
  48. maxNullStr.value = maxNullWayOptions.value.find(_=>_.value===baseInfo.maxNullWay).label
  49. if(props.edbInfo.EdbInfoDetail.Extra){
  50. const ExtraObj=JSON.parse(props.edbInfo.EdbInfoDetail.Extra)
  51. baseInfo.timeSeriesVal=ExtraObj.DateTag
  52. timeSeriesVal.value=timeSeriesOpts.value.find(_=>_.value===baseInfo.timeSeriesVal).label
  53. }
  54. setTimeout(() => {
  55. selectEDBClassifyINS.value?.getSelectClassifyOpt(props.edbInfo.EdbInfoDetail.ClassifyId)//获取选择的分类目录
  56. }, 1000);
  57. }
  58. }
  59. )
  60. // 预览页面
  61. const isPreview=ref(route.query.type==='preview'||false)
  62. const letterOpts = generateSeriesArray()||[];//字母数据
  63. //公式说明
  64. const showTips=ref(false)
  65. const tips = ref('')
  66. const tipsContent=ref(calculateTypeTipsMap.get(Number(route.query.source))||'')
  67. //选择的指标集合
  68. const edbList=ref([
  69. {
  70. tag:letterOpts[0],
  71. target:'',
  72. startDate:'',
  73. endDate:'',
  74. name:'',
  75. EdbType:0
  76. },
  77. {
  78. tag:letterOpts[1],
  79. target:'',
  80. startDate:'',
  81. endDate:'',
  82. name:'',
  83. EdbType:0
  84. },
  85. {
  86. tag:letterOpts[2],
  87. target:'',
  88. startDate:'',
  89. endDate:'',
  90. name:'',
  91. EdbType:0
  92. },
  93. {
  94. tag:letterOpts[3],
  95. target:'',
  96. startDate:'',
  97. endDate:'',
  98. name:'',
  99. EdbType:0
  100. }
  101. ])
  102. function handleAddEdbList(){
  103. if(edbList.value.length>=MAXADDEDBNUM){
  104. showToast('添加指标个数已达上限')
  105. return
  106. }
  107. let tag = edbList.value[edbList.value.length-1].tag;
  108. let index = letterOpts.findIndex(item => item === tag);
  109. const item = {
  110. tag: letterOpts[index+1],
  111. target: '',
  112. start_date: '',
  113. end_date: '',
  114. name:'',
  115. EdbType:0
  116. };
  117. edbList.value.push(item);
  118. }
  119. function handleDeleteEDBItem(index){
  120. edbList.value.splice(index, 1)
  121. }
  122. // 选择指标
  123. const showSelectEDB=ref(false)
  124. let whichIndex=0
  125. function handleShowSelectEDB(index){
  126. if(isPreview.value) return
  127. whichIndex=index
  128. showSelectEDB.value=true
  129. }
  130. function handleConfirmSelectEDB(e){
  131. edbList.value[whichIndex].target=e.EdbInfoId
  132. edbList.value[whichIndex].startDate=e.StartDate
  133. edbList.value[whichIndex].endDate=e.EndDate
  134. edbList.value[whichIndex].name=e.EdbName
  135. edbList.value[whichIndex].EdbType=e.EdbType
  136. }
  137. // 显示指标溯源
  138. const showEDBHistory=ref(false)
  139. const edbHistoryId=ref(0)
  140. function handleShowEDBHistory(item){
  141. //计算指标打开弹窗,基础指标打开新页面
  142. if(item.EdbType===2){
  143. /* edbHistoryId.value=item.target
  144. showEDBHistory.value=true */
  145. toHistoryPage(item.target)
  146. }else{
  147. const routerEl=router.resolve({
  148. path:'/dataEDB/detail',
  149. query:{
  150. edbInfoId:item.target
  151. }
  152. })
  153. window.open(routerEl.href,'_blank')
  154. }
  155. }
  156. // 计算公式
  157. const formulaVal=ref('')
  158. // 基础信息
  159. const edbNameInputFocus=ref(false)
  160. const baseInfo=reactive({
  161. name:'',
  162. unit:'',
  163. classify:'',
  164. frequency:'',
  165. nullValueWay: 1,
  166. maxNullWay: 1,
  167. timeSeriesVal:'',
  168. })
  169. // 选择单位
  170. const showSelectUnit=ref(false)
  171. function onConfirmSelectUnit(value){
  172. baseInfo.unit=value
  173. }
  174. //选择分类
  175. const showSelectClassify=ref(false)
  176. const classifyStr=ref('')
  177. const selectEDBClassifyINS=ref(null)
  178. function handleConfirmClassify({value,selectedOptions}){
  179. if(selectedOptions.length===0){
  180. baseInfo.classify=''
  181. classifyStr.value=''
  182. return
  183. }
  184. baseInfo.classify=value
  185. const textArr=selectedOptions.map(item=>item.ClassifyName)
  186. classifyStr.value=`${textArr.join('/')}`
  187. }
  188. //选择频度
  189. const showSelectFrequency=ref(false)
  190. function handleConfirmFrequency(value){
  191. baseInfo.frequency=value
  192. }
  193. /* 公式改为列表 */
  194. const formulaList = ref([{ formula: '' }])
  195. const showSelectFormulaDate = ref(false)
  196. const selectDateItem = ref({})
  197. //日期时间段
  198. const formulaDateArr = computed(() => {
  199. return formulaList.value.map(_ => _.date).filter(_ => _).sort((a,b) => new Date(a)-new Date(b))
  200. })
  201. /* 新增公式分段 */
  202. function addFormulaHandle() {
  203. let addItem = {
  204. formula: formulaList.value[formulaList.value.length-1].formula,
  205. date: ''
  206. }
  207. formulaList.value.push(addItem)
  208. }
  209. /* 移除公式 */
  210. function removeFormulaItem(index) {
  211. formulaList.value.splice(index,1)
  212. }
  213. /* 选择日期 检验 */
  214. function handleConfirmFormulaDate(val) {
  215. const { startDate,endDate } = edbList.value[0];
  216. if(!startDate) {
  217. selectDateItem.value.date = val;
  218. return
  219. }
  220. let dateStamp = new Date(val).getTime(),
  221. startStamp = new Date(startDate).getTime(),
  222. endStamp = new Date(endDate).getTime();
  223. if (dateStamp > endStamp || dateStamp < startStamp) {
  224. return showToast('分段日期必须在第一个指标日期区间')
  225. }
  226. else if(formulaList.value.filter(_ => _.date===val).length>1) {
  227. return showToast('分段日期不可重复')
  228. }
  229. selectDateItem.value.date = val;
  230. }
  231. //空值处理弹窗
  232. const nullWayStr = ref('查找前后35天最近值')
  233. const showNullValPoup = ref(false)
  234. const nullWayOptions = ref([
  235. { label: '查找前后35天最近值',value: 0 },
  236. { label: '不计算',value: 1 },
  237. { label: '前值填充',value: 2 },
  238. { label: '后值填充',value: 3 },
  239. { label: '等于0',value: 4 },
  240. ])
  241. function onConfirmNullWay(e) {
  242. baseInfo.nullValueWay = e.selectedValues[0]
  243. nullWayStr.value = e.selectedOptions[0].label
  244. showNullValPoup.value = false
  245. }
  246. /* max空值处理显示 当输入的公式包含MAX、MIN且空值处理为0时,输入公式失焦后出现右侧选项; */
  247. const showMaxNullDeal = computed(()=> {
  248. let haveMaxOrMin = formulaList.value.some(_ => _.formula.toUpperCase().includes('MAX') || _.formula.toUpperCase().includes('MIN'))
  249. return haveMaxOrMin && baseInfo.nullValueWay===4
  250. })
  251. //max空值处理
  252. const maxNullStr = ref('等于0')
  253. const showMaxNullValPoup = ref(false)
  254. const maxNullWayOptions = ref([
  255. { label: '等于0',value: 1 },
  256. { label: '跳过空值',value: 2 },
  257. ])
  258. function onConfirmMaxNullWay(e) {
  259. baseInfo.maxNullWay = e.selectedValues[0]
  260. maxNullStr.value = e.selectedOptions[0].label
  261. showMaxNullValPoup.value = false
  262. }
  263. // 生成指标时间序列
  264. const timeSeriesVal=ref('')
  265. const showTimeSeries=ref(false)
  266. const timeSeriesOpts=computed(()=>{
  267. let arr=[]
  268. arr=edbList.value.filter(item=>item.target).map(item=>{
  269. return {
  270. label:`指标${item.tag}`,
  271. value:item.tag
  272. }
  273. })
  274. arr.push(
  275. {
  276. label:'所有指标时间序列并集',
  277. value:'all',
  278. }
  279. )
  280. return arr
  281. })
  282. function onConfirmTimeSeries(e){
  283. baseInfo.timeSeriesVal=e.selectedValues[0]
  284. timeSeriesVal.value=e.selectedOptions[0].label
  285. showTimeSeries.value=false
  286. }
  287. //一些文案提示
  288. const formTips = ref({
  289. 'null-val': `1、查找前后35天最近值:在参与计算的日期序列上某指标无值时,该指标往前/往后找距离最近的值作为当天的值进行计算,遍历允许跨年,往前最多35天,往后最多35天<br>
  290. 2、不计算:只要有一个指标在某个日期没有值(即空值),则计算指标在该日期没有值 <br>
  291. 3、前值填充:空值优先以最近的前值填充,没有前值时,用后值填充 <br>
  292. 4、后值填充:空值优先以最近的后值填充,没有前值时,用后值填充 <br>
  293. 5、等于0:空值以0值参与计算 <br>
  294. 注意:此处缺失值的处理,作用于数据全部时间段`,
  295. 'max-null-val': `MAX、MIN公式中指标存在空值时按如下规则处理:<br>
  296. 1、等于0,空值用0参与计算;<br>
  297. 2、跳过空值,去除空值指标,剩余指标进行计算,若该日期所有指标均为空值,则该日期无值;`,
  298. 'formula':`1、支持新增分段,实现不同分段使用不同的计算公式,若未新增分段,则所有日期序列用统一公式计算<br>
  299. 2、新增分段需配置新公式和时间节点,在时间节点之前(不含)使用新公式,在时间节点之后(含)使用已配置公式,每个分段公式支持修改<br>
  300. 3、分段时间节点不允许重复,不允许超出第一个指标的日期区间`
  301. })
  302. // 提交计算
  303. async function handleSave(){
  304. if(!formulaList.value[0].formula){
  305. showToast('计算公式不能为空')
  306. return
  307. }
  308. if(!baseInfo.name){
  309. showToast('指标名称不能为空')
  310. return
  311. }
  312. if(!baseInfo.unit){
  313. showToast('指标单位不能为空')
  314. return
  315. }
  316. if(!baseInfo.classify){
  317. showToast('指标目录不能为空')
  318. return
  319. }
  320. if(!baseInfo.frequency){
  321. showToast('指标频度不能为空')
  322. return
  323. }
  324. const arr=edbList.value.filter(item=>item.target).map(item=>{
  325. return {
  326. EdbInfoId: item.target,
  327. FromTag: item.tag,
  328. }
  329. })
  330. let CalculateFormula = JSON.stringify(formulaList.value
  331. .filter((_,index) => index===0||(index>0&&_.formula&&_.date))
  332. .map(_ => ({ f:_.formula,d: _.date }))
  333. )
  334. const params={
  335. CalculateFormula,
  336. ClassifyId:baseInfo.classify,
  337. EdbName:baseInfo.name,
  338. Frequency:baseInfo.frequency,
  339. Unit:baseInfo.unit,
  340. EdbInfoIdArr:arr,
  341. EmptyType:baseInfo.nullValueWay,
  342. MaxEmptyType:baseInfo.maxNullWay,
  343. Extra:JSON.stringify({
  344. DateTag:baseInfo.timeSeriesVal
  345. })
  346. }
  347. const edbInfoId=route.query.edbInfoId
  348. const res=edbInfoId?await apiDataEDB.editCalculateFormula({...params,EdbInfoId:Number(edbInfoId)}):await apiDataEDB.addCalculateFormula(params)
  349. if(res.Ret===200){
  350. showToast(res.Msg)
  351. setTimeout(() => {
  352. if(edbInfoId){
  353. router.back()
  354. }else{
  355. router.replace({
  356. path:'/dataEDB/detail',
  357. query:{
  358. edbInfoId:res.Data.EdbInfoId
  359. }
  360. })
  361. }
  362. }, 1500);
  363. }
  364. }
  365. </script>
  366. <template>
  367. <div class="formula-calculate-wrap">
  368. <section class="section select-edb-box">
  369. <van-swipe-cell v-for="(item,index) in edbList" :key="item.tag" :disabled="index<4||isPreview">
  370. <van-field
  371. :label="item.tag"
  372. :right-icon="!isPreview?'arrow':''"
  373. @click-input="handleShowSelectEDB(index)"
  374. :disabled="isPreview"
  375. >
  376. <template #left-icon>
  377. <div class="left-icon">
  378. <svg-icon name="edb-history-tag" size="24px" v-if="item.target" @click="handleShowEDBHistory(item)"/>
  379. </div>
  380. </template>
  381. <template #input>
  382. <div class="edb-info-box">
  383. <div class="edb-info" v-if="item.target">
  384. <span class="name">{{item.name}}</span>
  385. <span class="time">{{item.startDate}}至{{item.endDate}}</span>
  386. </div>
  387. <span class="placeholder" v-else>请选择指标</span>
  388. </div>
  389. </template>
  390. </van-field>
  391. <template #right>
  392. <van-button square type="danger" text="删除" @click="handleDeleteEDBItem(index)"/>
  393. </template>
  394. </van-swipe-cell>
  395. <div class="add-edb-box" @click="handleAddEdbList" v-if="!isPreview">
  396. <img src="@/assets/imgs/icon01.png" alt="">
  397. <span>添加更多参数</span>
  398. </div>
  399. </section>
  400. <section class="section formula-box">
  401. <div class="section">
  402. <van-field
  403. v-model="nullWayStr"
  404. required
  405. input-align="right"
  406. readonly
  407. @click-input="showNullValPoup = true"
  408. :right-icon="!isPreview?'arrow':''"
  409. :disabled="isPreview"
  410. >
  411. <template #label>
  412. <span>
  413. 空值处理
  414. <svg-icon class="icon" name="warning" @click="showTips=true;tips=formTips['null-val']"></svg-icon>
  415. </span>
  416. </template>
  417. </van-field>
  418. <van-field
  419. v-model="maxNullStr"
  420. required
  421. input-align="right"
  422. readonly
  423. @click-input="showMaxNullValPoup = true"
  424. :right-icon="!isPreview?'arrow':''"
  425. :disabled="isPreview"
  426. v-if="showMaxNullDeal"
  427. >
  428. <template #label>
  429. <span>
  430. MAX、MIN空值处理
  431. <svg-icon class="icon" name="warning" @click="showTips=true;tips=formTips['max-null-val']"></svg-icon>
  432. </span>
  433. </template>
  434. </van-field>
  435. <van-field
  436. v-model="timeSeriesVal"
  437. input-align="right"
  438. readonly
  439. @click-input="showTimeSeries = true"
  440. :right-icon="!isPreview?'arrow':''"
  441. :disabled="isPreview"
  442. label="生成指标时间序列"
  443. label-width="140px"
  444. placeholder="请选择"
  445. />
  446. </div>
  447. <div class="van-cell formula-wrap">
  448. <label class="van-cell__title van-field__label--required">计算公式
  449. <svg-icon class="icon" name="warning" @click="showTips=true;tips=formTips['formula']"></svg-icon>
  450. </label>
  451. <ul class="formula-list">
  452. <li class="formula-item" v-for="(item,index) in formulaList" :key="index">
  453. <template v-if="formulaDateArr.length&&(item.date||!index)">
  454. <span v-if="index===0" class="date-section-text">{{formulaDateArr[formulaDateArr.length-1]}}(含)之后</span>
  455. <span v-else-if="item.date===formulaDateArr[0]" class="date-section-text">{{formulaDateArr[0]}}之前</span>
  456. <span v-else class="date-section-text">{{formulaDateArr[formulaDateArr.findIndex(_ =>_ ===item.date)-1]}}(含)—{{item.date}}</span>
  457. </template>
  458. <van-field
  459. v-model="item.formula"
  460. placeholder="输入公式"
  461. required
  462. :disabled="isPreview"
  463. class="formula-input"
  464. />
  465. <van-button type="default" size="small" v-if="index===0&&!isPreview" @click="addFormulaHandle" style="margin-left: 10px;">添加分段</van-button>
  466. <template v-else>
  467. <van-field
  468. v-model="item.date"
  469. placeholder="日期"
  470. required
  471. :disabled="isPreview"
  472. readonly
  473. class="formula-input"
  474. style="margin: 0 20px;"
  475. @click-input="showSelectFormulaDate=true;selectDateItem=item;"
  476. />
  477. <van-icon name="clear" color="#333" size="20" @click="removeFormulaItem(index)" v-if="!isPreview"/>
  478. </template>
  479. </li>
  480. <li class="formula-tips">
  481. <p class="en-text-wrap">公式示例:A*0.5+B*C*1.2+120-MAX(A,B,C)</p>
  482. <p class="en-text-wrap">函数支持:MAX(),MIN(),ln(A),log(a,A),abs(),exp(),pow(),round()</p>
  483. </li>
  484. </ul>
  485. </div>
  486. <!-- <van-field
  487. label="计算公式"
  488. required
  489. >
  490. <template #input>
  491. <div style="margin-left:auto">
  492. <input class="formula-input" :disabled="isPreview" type="text" placeholder="请输入公式" v-model="formulaVal">
  493. <div class="formula-tips">
  494. <p class="en-text-wrap">公式示例:A*0.5+B*C*1.2+120-MAX(A,B,C)</p>
  495. <p class="en-text-wrap">函数支持:MAX(),MIN(),ln(A),log(a,A)</p>
  496. </div>
  497. </div>
  498. </template>
  499. </van-field> -->
  500. </section>
  501. <section class="section baseinfo-box">
  502. <van-field
  503. v-model="baseInfo.name"
  504. label="指标名称"
  505. placeholder="指标名称"
  506. input-align="right"
  507. required
  508. @focus="edbNameInputFocus=true"
  509. @blur="edbNameInputFocus=false"
  510. :disabled="isPreview"
  511. >
  512. <template #right-icon>
  513. <svg-icon v-if="!isPreview" class="edit-icon" name="edit" :color="edbNameInputFocus?'#0052D9':'#333333'"/>
  514. </template>
  515. </van-field>
  516. <van-field
  517. :modelValue="baseInfo.unit"
  518. readonly
  519. label="单位"
  520. placeholder="请选择单位"
  521. input-align="right"
  522. :right-icon="!isPreview?'arrow':''"
  523. required
  524. @click-input="showSelectUnit=true"
  525. :disabled="isPreview"
  526. />
  527. <van-field
  528. :modelValue="classifyStr"
  529. readonly
  530. label="指标目录"
  531. placeholder="请选择指标目录"
  532. input-align="right"
  533. :right-icon="!isPreview?'arrow':''"
  534. required
  535. @click-input="showSelectClassify=true"
  536. :disabled="isPreview"
  537. />
  538. <van-field
  539. :modelValue="baseInfo.frequency"
  540. readonly
  541. label="频度"
  542. placeholder="请选择指标频度"
  543. input-align="right"
  544. :right-icon="!isPreview?'arrow':''"
  545. required
  546. @click-input="showSelectFrequency=true"
  547. :disabled="isPreview"
  548. />
  549. </section>
  550. <div class="formula-intro-btn" @click="showTips=true;tips=tipsContent">
  551. <svg-icon class="icon" name="warning"></svg-icon>
  552. <span>公式说明</span>
  553. </div>
  554. <div class="opt-btns" v-if="!isPreview">
  555. <van-button class="primary2" @click="$router.back()">取消</van-button>
  556. <van-button type="primary" @click="handleSave">生成计算指标</van-button>
  557. </div>
  558. </div>
  559. <!-- 选择指标 -->
  560. <SelectEDB v-model:show="showSelectEDB" @select="handleConfirmSelectEDB"/>
  561. <!-- 指标溯源 -->
  562. <EDBHistory v-model:show="showEDBHistory" :edbInfoId="edbHistoryId"/>
  563. <!-- 选择单位 -->
  564. <SelectEDBUnit v-model:show="showSelectUnit" @select="onConfirmSelectUnit"/>
  565. <!-- 选择分类 -->
  566. <SelectEDBClassify ref="selectEDBClassifyINS" :defaultId="baseInfo.classify" v-model:show="showSelectClassify" @select="handleConfirmClassify" />
  567. <!-- 选择频度 -->
  568. <SelectEDBFrequency v-model:show="showSelectFrequency" @select="handleConfirmFrequency"/>
  569. <!-- 选择日期 -->
  570. <SelectDate v-model:show="showSelectFormulaDate" @select="handleConfirmFormulaDate"/>
  571. <!-- 公式说明 -->
  572. <van-dialog
  573. v-model:show="showTips"
  574. confirmButtonText='知道啦'
  575. >
  576. <div class="edb-formula-tips-html-box" v-html="tips"></div>
  577. </van-dialog>
  578. <!-- 空值处理方式 -->
  579. <van-popup
  580. :show="showNullValPoup"
  581. round
  582. position="bottom"
  583. >
  584. <van-picker
  585. title=""
  586. :columns="nullWayOptions"
  587. :columns-field-names="{
  588. text: 'label',
  589. value: 'value'
  590. }"
  591. @cancel="showNullValPoup=false"
  592. @confirm="onConfirmNullWay"
  593. />
  594. </van-popup>
  595. <!-- MAX空值处理方式 -->
  596. <van-popup
  597. :show="showMaxNullValPoup"
  598. round
  599. position="bottom"
  600. >
  601. <van-picker
  602. title=""
  603. :columns="maxNullWayOptions"
  604. :columns-field-names="{
  605. text: 'label',
  606. value: 'value'
  607. }"
  608. @cancel="showMaxNullValPoup=false"
  609. @confirm="onConfirmMaxNullWay"
  610. />
  611. </van-popup>
  612. <!-- 选择生成指标时间序列 -->
  613. <van-popup
  614. :show="showTimeSeries"
  615. round
  616. position="bottom"
  617. >
  618. <van-picker
  619. title=""
  620. :columns="timeSeriesOpts"
  621. :columns-field-names="{
  622. text: 'label',
  623. value: 'value'
  624. }"
  625. @cancel="showTimeSeries=false"
  626. @confirm="onConfirmTimeSeries"
  627. />
  628. </van-popup>
  629. </template>
  630. <style lang="scss" scoped>
  631. .formula-calculate-wrap{
  632. min-height: 90vh;
  633. background-color: $page-bg-grey;
  634. padding-bottom: 210px ;
  635. }
  636. .section{
  637. background-color: #fff;
  638. margin-bottom: 32px;
  639. }
  640. .select-edb-box{
  641. .left-icon{
  642. width: 48px;
  643. height: 48px;
  644. }
  645. :deep(.van-cell__right-icon){
  646. align-self: center;
  647. color: #333;
  648. }
  649. .edb-info-box{
  650. width: 100%;
  651. text-align: right;
  652. .placeholder{
  653. color: var(--van-text-color-3);
  654. }
  655. .edb-info{
  656. display: flex;
  657. flex-direction: column;
  658. }
  659. .time{
  660. color: $font-grey_999;
  661. font-size: 24px;
  662. }
  663. }
  664. .add-edb-box{
  665. display: flex;
  666. justify-content: flex-end;
  667. align-items: center;
  668. color: $theme-color;
  669. font-size: 32px;
  670. padding: 32px var(--van-cell-horizontal-padding);
  671. img{
  672. width: 48px;
  673. height: 48px;
  674. }
  675. }
  676. }
  677. .formula-box{
  678. .formula-input{
  679. display: block;
  680. box-sizing: border-box;
  681. background-color: $page-bg-grey;
  682. padding: 12px 32px;
  683. border-radius: 12px;
  684. line-height: 1.7;
  685. width: 100%;
  686. flex: 1;
  687. }
  688. .formula-tips{
  689. font-size: 24px;
  690. color: $font-grey_999;
  691. }
  692. }
  693. .baseinfo-box{
  694. .edit-icon{
  695. width: 48px;
  696. height: 48px;
  697. }
  698. }
  699. .formula-intro-btn{
  700. width: 180px;
  701. height: 60px;
  702. display: flex;
  703. align-items: center;
  704. justify-content: center;
  705. gap: 5px;
  706. color: $theme-color;
  707. line-height: 1;
  708. background-color: #fff;
  709. border-radius: 32px;
  710. margin-left: auto;
  711. margin-right: var(--van-cell-horizontal-padding);
  712. .icon{
  713. width: 24px;
  714. height: 24px;
  715. }
  716. }
  717. .opt-btns{
  718. position: fixed;
  719. left: 0;
  720. right: 0;
  721. bottom: 0;
  722. background-color: #fff;
  723. z-index: 99;
  724. padding: 48px;
  725. display: flex;
  726. justify-content: space-between;
  727. .van-button{
  728. width: 48%;
  729. max-width: 300PX;
  730. }
  731. }
  732. .formula-wrap {
  733. display: block;
  734. .formula-list { margin-top: 15px; }
  735. .formula-item {
  736. display: flex;
  737. align-items: center;
  738. position: relative;
  739. padding: 20px 0;
  740. .date-section-text {
  741. position: absolute;
  742. top: -15px;
  743. }
  744. }
  745. }
  746. @media screen and (min-width:$media-width){
  747. .formula-calculate-wrap{
  748. padding-bottom: 105px;
  749. }
  750. .section{
  751. margin-bottom: 16px;
  752. }
  753. .select-edb-box{
  754. .left-icon{
  755. width: 24px;
  756. height: 24px;
  757. }
  758. .edb-info-box{
  759. .time{
  760. font-size: 12px;
  761. }
  762. }
  763. .add-edb-box{
  764. font-size: 16px;
  765. padding: 16px var(--van-cell-horizontal-padding);
  766. img{
  767. width: 24px;
  768. height: 24px;
  769. }
  770. }
  771. }
  772. .formula-box{
  773. .formula-input{
  774. padding: 6px 16px;
  775. border-radius: 6px;
  776. }
  777. .formula-tips{
  778. font-size: 12px;
  779. }
  780. }
  781. .baseinfo-box{
  782. .edit-icon{
  783. width: 24px;
  784. height: 24px;
  785. }
  786. }
  787. .formula-intro-btn{
  788. width: 90px;
  789. height: 30px;
  790. gap: 2px;
  791. border-radius: 16px;
  792. .icon{
  793. width: 12px;
  794. height: 12px;
  795. }
  796. }
  797. .opt-btns{
  798. padding: 24px;
  799. justify-content: center;
  800. gap: 10px;
  801. }
  802. .formula-wrap .formula-item {
  803. display: flex;
  804. align-items: center;
  805. position: relative;
  806. padding: 15px 0;
  807. .date-section-text {
  808. position: absolute;
  809. top: -10px;
  810. }
  811. }
  812. }
  813. </style>