JointCalculate.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  1. <script setup>
  2. import apiDataEDB from '@/api/dataEDB'
  3. import {ref,reactive, computed,watch} from 'vue'
  4. import SelectEDB from './SelectEDB.vue'
  5. import SelectEDBClassify from '../../components/SelectEDBClassify.vue'
  6. import SelectEDBUnit from '../../components/SelectEDBUnit.vue'
  7. import SelectEDBFrequency from '../../components/SelectEDBFrequency.vue'
  8. import SelectDate from '@/components/SelectDate.vue'
  9. import { showToast } from 'vant'
  10. import { useRoute, useRouter } from 'vue-router'
  11. const route=useRoute()
  12. const router=useRouter()
  13. const props=defineProps({
  14. edbInfo:{
  15. type:Object,
  16. default:null
  17. }
  18. })
  19. watch(
  20. ()=>props.edbInfo,
  21. ()=>{
  22. if(route.query.type==='edit'){
  23. const edbInfoData=props.edbInfo.EdbInfoDetail
  24. if(edbInfoData.Source===24){//累计同比拼接
  25. tabActive.value=2
  26. }else{
  27. tabActive.value=1
  28. jointDate.value=edbInfoData.CalculateFormula
  29. }
  30. const temBeforeEDBInfo=props.edbInfo.CalculateList.find(item => item.FromTag === 'A')
  31. const temAfterEDBInfo=props.edbInfo.CalculateList.find(item => item.FromTag === 'B')
  32. beforeEDBInfo.value={
  33. EdbName:temBeforeEDBInfo.FromEdbName,
  34. EdbInfoId:temBeforeEDBInfo.FromEdbInfoId,
  35. EndDate:temBeforeEDBInfo.EndDate,
  36. StartDate:temBeforeEDBInfo.StartDate
  37. }
  38. afterEBDInfo.value={
  39. EdbName:temAfterEDBInfo.FromEdbName,
  40. EdbInfoId:temAfterEDBInfo.FromEdbInfoId,
  41. EndDate:temAfterEDBInfo.EndDate,
  42. StartDate:temAfterEDBInfo.StartDate
  43. }
  44. baseInfo.name=edbInfoData.EdbName
  45. baseInfo.unit=edbInfoData.Unit
  46. baseInfo.classify=edbInfoData.ClassifyId
  47. baseInfo.frequency=edbInfoData.Frequency
  48. setTimeout(() => {
  49. selectEDBClassifyINS.value?.getSelectClassifyOpt(props.edbInfo.EdbInfoDetail.ClassifyId)//获取选择的分类目录
  50. }, 1000);
  51. }
  52. }
  53. )
  54. //公式说明
  55. const tipsConfig=new Map([
  56. [1,`
  57. 直接拼接说明:<br>
  58. 1、选取拼接日期<br>
  59. 2、在拼接日期之前的数据选择指标A<br>
  60. 3、拼接日期之后的数据选择指标B<br>
  61. 4、新指标的起始日期为A的开始日期,更新时间跟随指标B进行更新<br>
  62. 5、指标A和B可以是原始指标,也可以是计算指标
  63. `],
  64. [2,`
  65. 累计值同比拼接说明:<br>
  66. 1、只支持月频度的指标进行累计值同比拼接<br>
  67. 2、如果出现有空值运算,则返回空值<br>
  68. 3、选取待拼接指标A和同比值指标B<br>
  69. 4、搜索到指标A最后一个12月31日有值的年份,并且向前回溯12个值(12个月),分别乘以下一年同期对应的同比增长率(B),公式为【A*(1+同期增长率(B)/100)】,得到下一年每个月的绝对值,再用新得到的下一年的12个月的值再乘以再下一年同期对应的同比增长率,得到再下一年每个月的绝对值<br>
  70. 5、以此类推,直到运算至指标B的最新值,得到新的序列C<br>
  71. 6、新指标是将序列C和指标A进行直接拼接,拼接日期选取指标A中有值的年份的年末最后一天即12月31日,再与序列C的起始日期做拼接<br>
  72. 7、新指标跟随指标B进行更新
  73. `],
  74. ])
  75. const showTips=ref(false)
  76. const tipsContent=computed(()=>{
  77. return tipsConfig.get(tabActive.value)
  78. })
  79. const tabsArr=ref([{ label: '直接拼接',key: 1 },{ label: '累计同比拼接',key: 2 }])
  80. const tabActive=ref(1)
  81. function handleTabChange(){
  82. jointDate.value=''
  83. beforeEDBInfo.value=null
  84. afterEBDInfo.value=null
  85. baseInfo.name=''
  86. baseInfo.unit=''
  87. baseInfo.classify=''
  88. baseInfo.frequency=''
  89. }
  90. //拼接日期
  91. const jointDate=ref('')
  92. const showSelectJointDate=ref(false)
  93. function handleConfirmJointDate(e){
  94. jointDate.value=e
  95. }
  96. // 选择指标
  97. const selectEDBSearchParams=ref({})
  98. const beforeEDBInfo=ref(null)
  99. const afterEBDInfo=ref(null)
  100. const showSelectEDB=ref(false)
  101. let currentSelectEDBType=''//当前是选择哪个指标
  102. function handleShowSelectEDB(type){
  103. currentSelectEDBType=type
  104. if(tabActive.value===2&&type==='before'){//累计同比值拼接选择待拼接指标搜索指标时Frequency传月度
  105. selectEDBSearchParams.value={Frequency:'月度'}
  106. }else{
  107. selectEDBSearchParams.value={}
  108. }
  109. showSelectEDB.value=true
  110. }
  111. function handleConfirmSelectEDB(e){
  112. if(currentSelectEDBType==='before'){
  113. beforeEDBInfo.value=e
  114. }else{
  115. afterEBDInfo.value=e
  116. }
  117. }
  118. // 基础信息
  119. const edbNameInputFocus=ref(false)
  120. const baseInfo=reactive({
  121. name:'',
  122. unit:'',
  123. classify:'',
  124. frequency:''
  125. })
  126. // 选择单位
  127. const showSelectUnit=ref(false)
  128. function onConfirmSelectUnit(value){
  129. baseInfo.unit=value
  130. }
  131. //选择分类
  132. const showSelectClassify=ref(false)
  133. const classifyStr=ref('')
  134. const selectEDBClassifyINS=ref(null)
  135. function handleConfirmClassify({value,selectedOptions}){
  136. baseInfo.classify=value
  137. classifyStr.value=`${selectedOptions[0].ClassifyName}/${selectedOptions[1].ClassifyName}/${selectedOptions[2].ClassifyName}`
  138. }
  139. //选择频度
  140. const showSelectFrequency=ref(false)
  141. function handleConfirmFrequency(value){
  142. baseInfo.frequency=value
  143. }
  144. // 提交计算
  145. const saveBtnLoading=ref(false)
  146. async function handleSave(){
  147. if(tabActive.value===1&&!jointDate.value){
  148. showToast('拼接日期不能为空')
  149. return
  150. }
  151. if(!beforeEDBInfo.value){
  152. showToast(tabActive.value===1?'指标不能为空':'待拼接指标不能为空')
  153. return
  154. }
  155. if(!afterEBDInfo.value){
  156. showToast(tabActive.value===1?'指标不能为空':'指标不能为空')
  157. return
  158. }
  159. if(!baseInfo.name){
  160. showToast('指标名称不能为空')
  161. return
  162. }
  163. if(!baseInfo.unit){
  164. showToast('指标单位不能为空')
  165. return
  166. }
  167. if(!baseInfo.classify){
  168. showToast('指标目录不能为空')
  169. return
  170. }
  171. if(!baseInfo.frequency){
  172. showToast('指标频度不能为空')
  173. return
  174. }
  175. const baseParams={
  176. ClassifyId:baseInfo.classify,
  177. EdbName:baseInfo.name,
  178. Frequency:baseInfo.frequency,
  179. Unit:baseInfo.unit,
  180. }
  181. const params=tabActive.value===1?{
  182. ...baseParams,
  183. EdbInfoIdArr:[
  184. {EdbInfoId:afterEBDInfo.value.EdbInfoId}
  185. ],
  186. Formula:jointDate.value,
  187. FromEdbInfoId:beforeEDBInfo.value.EdbInfoId,
  188. Source:23
  189. }:{
  190. ...baseParams,
  191. EdbInfoIdArr:[
  192. {EdbInfoId:afterEBDInfo.value.EdbInfoId}
  193. ],
  194. FromEdbInfoId:beforeEDBInfo.value.EdbInfoId,
  195. Source:24
  196. }
  197. saveBtnLoading.value=true
  198. const res=route.query.type==='edit'?await apiDataEDB.editCalculateEDB({...params,EdbInfoId:Number(route.query.edbInfoId)}) : await apiDataEDB.addCalculateEDB(params)
  199. saveBtnLoading.value=false
  200. if(res.Ret===200){
  201. showToast(route.query.type==='edit'?'编辑成功':'新增成功')
  202. setTimeout(() => {
  203. router.back()
  204. }, 1500);
  205. }
  206. }
  207. </script>
  208. <template>
  209. <div class="joint-calculate-wrap">
  210. <van-tabs
  211. v-model:active="tabActive"
  212. sticky
  213. border
  214. title-active-color="#0052D9"
  215. title-inactive-color="#333"
  216. line-width="16px"
  217. @change="handleTabChange"
  218. v-if="$route.query.type!=='edit'"
  219. >
  220. <van-tab
  221. :title="tab.label"
  222. :name="tab.key"
  223. v-for="tab in tabsArr"
  224. :key="tab.key"
  225. />
  226. </van-tabs>
  227. <section class="section select-edb-box">
  228. <van-field
  229. :modelValue="jointDate"
  230. readonly
  231. label="拼接日期"
  232. placeholder="请选择日期"
  233. input-align="right"
  234. right-icon="arrow"
  235. required
  236. @click-input="showSelectJointDate=true"
  237. v-if="tabActive===1"
  238. />
  239. <van-field
  240. label-width="7em"
  241. :label="tabActive===1?'拼接日期之前':'待拼接指标'"
  242. required
  243. right-icon="arrow"
  244. @click-input="handleShowSelectEDB('before')"
  245. >
  246. <template #input>
  247. <div class="edb-info-box">
  248. <div class="edb-info" v-if="beforeEDBInfo">
  249. <span class="name">{{beforeEDBInfo.EdbName}}</span>
  250. <span class="time" v-if="tabActive===1">(起始日期:{{beforeEDBInfo.StartDate}})</span>
  251. <span class="time" v-if="tabActive===2">(截至日期:{{beforeEDBInfo.EndDate}})</span>
  252. </div>
  253. <span class="placeholder" v-else>请选择指标</span>
  254. </div>
  255. </template>
  256. </van-field>
  257. <van-field
  258. label-width="7em"
  259. :label="tabActive===1?'拼接日期之后':'同比值指标'"
  260. right-icon="arrow"
  261. required
  262. @click-input="handleShowSelectEDB('after')"
  263. >
  264. <template #input>
  265. <div class="edb-info-box">
  266. <div class="edb-info" v-if="afterEBDInfo">
  267. <span class="name">{{afterEBDInfo.EdbName}}</span>
  268. <span class="time" v-if="tabActive===1">(最新日期:{{afterEBDInfo.EndDate}})</span>
  269. </div>
  270. <span class="placeholder" v-else>请选择指标</span>
  271. </div>
  272. </template>
  273. </van-field>
  274. </section>
  275. <section class="section baseinfo-box">
  276. <van-field
  277. v-model="baseInfo.name"
  278. label="指标名称"
  279. placeholder="指标名称"
  280. input-align="right"
  281. required
  282. @focus="edbNameInputFocus=true"
  283. @blur="edbNameInputFocus=false"
  284. >
  285. <template #right-icon>
  286. <svg-icon class="edit-icon" name="edit" :color="edbNameInputFocus?'#0052D9':'#333333'"/>
  287. </template>
  288. </van-field>
  289. <van-field
  290. :modelValue="baseInfo.unit"
  291. readonly
  292. label="单位"
  293. placeholder="请选择单位"
  294. input-align="right"
  295. right-icon="arrow"
  296. required
  297. @click-input="showSelectUnit=true"
  298. />
  299. <van-field
  300. :modelValue="classifyStr"
  301. readonly
  302. label="指标目录"
  303. placeholder="请选择指标目录"
  304. input-align="right"
  305. right-icon="arrow"
  306. required
  307. @click-input="showSelectClassify=true"
  308. />
  309. <van-field
  310. :modelValue="baseInfo.frequency"
  311. readonly
  312. label="频度"
  313. placeholder="请选择指标频度"
  314. input-align="right"
  315. right-icon="arrow"
  316. required
  317. @click-input="showSelectFrequency=true"
  318. />
  319. </section>
  320. <div class="formula-intro-btn" @click="showTips=true">
  321. <svg-icon class="icon" name="warning"></svg-icon>
  322. <span>公式说明</span>
  323. </div>
  324. <div class="opt-btns">
  325. <van-button class="primary2" @click="$router.back()">取消</van-button>
  326. <van-button
  327. type="primary"
  328. :loading="saveBtnLoading"
  329. loading-text="计算中..."
  330. @click="handleSave"
  331. >保存</van-button>
  332. </div>
  333. </div>
  334. <!-- 选择拼接日期 -->
  335. <SelectDate v-model:show="showSelectJointDate" @select="handleConfirmJointDate"/>
  336. <!-- 选择指标 -->
  337. <SelectEDB v-model:show="showSelectEDB" :params="selectEDBSearchParams" @select="handleConfirmSelectEDB"/>
  338. <!-- 选择单位 -->
  339. <SelectEDBUnit v-model:show="showSelectUnit" @select="onConfirmSelectUnit"/>
  340. <!-- 选择分类 -->
  341. <SelectEDBClassify ref="selectEDBClassifyINS" :defaultId="baseInfo.classify" v-model:show="showSelectClassify" @select="handleConfirmClassify" />
  342. <!-- 选择频度 -->
  343. <SelectEDBFrequency v-model:show="showSelectFrequency" @select="handleConfirmFrequency"/>
  344. <!-- 公式说明 -->
  345. <van-dialog
  346. v-model:show="showTips"
  347. :title="$route.query.name"
  348. confirmButtonText='知道啦'
  349. >
  350. <div class="edb-formula-tips-html-box" v-html="tipsContent"></div>
  351. </van-dialog>
  352. </template>
  353. <style lang="scss" scoped>
  354. .joint-calculate-wrap{
  355. min-height: 90vh;
  356. background-color: $page-bg-grey;
  357. padding-bottom: 210px ;
  358. }
  359. .section{
  360. background-color: #fff;
  361. margin-bottom: 32px;
  362. }
  363. .select-edb-box{
  364. :deep(.van-cell__right-icon){
  365. align-self: center;
  366. color: #333;
  367. }
  368. .edb-info-box{
  369. width: 100%;
  370. text-align: right;
  371. .placeholder{
  372. color: var(--van-text-color-3);
  373. }
  374. .edb-info{
  375. display: flex;
  376. flex-direction: column;
  377. }
  378. .time{
  379. color: $font-grey_999;
  380. font-size: 24px;
  381. }
  382. }
  383. }
  384. .formula-intro-btn{
  385. width: 180px;
  386. height: 60px;
  387. display: flex;
  388. align-items: center;
  389. justify-content: center;
  390. gap: 5px;
  391. color: $theme-color;
  392. line-height: 1;
  393. background-color: #fff;
  394. border-radius: 32px;
  395. margin-left: auto;
  396. margin-right: var(--van-cell-horizontal-padding);
  397. .icon{
  398. width: 24px;
  399. height: 24px;
  400. }
  401. }
  402. .opt-btns{
  403. position: fixed;
  404. left: 0;
  405. right: 0;
  406. bottom: 0;
  407. background-color: #fff;
  408. z-index: 99;
  409. padding: 48px;
  410. display: flex;
  411. justify-content: space-between;
  412. .van-button{
  413. width: 48%;
  414. }
  415. }
  416. </style>