123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575 |
- <script setup>
- import apiDataEDB from '@/api/dataEDB'
- import {calculateTypeTipsMap} from '../../util/config'
- import {ref,reactive,watch} from 'vue'
- import SelectEDB from './SelectEDB.vue'
- import SelectEDBClassify from '../../components/SelectEDBClassify.vue'
- import SelectEDBUnit from '../../components/SelectEDBUnit.vue'
- import SelectEDBFrequency from '../../components/SelectEDBFrequency.vue'
- import SelectDateRange from '@/components/SelectDateRange.vue'
- import EDBHistory from '@/views/dataEDB/components/EDBHistory.vue'
- import { showToast } from 'vant'
- import { useRoute, useRouter } from 'vue-router'
- import moment from 'moment'
- import {useToHistoryPage} from '@/hooks/edb/useToHistoryPage'
- const {toHistoryPage} = useToHistoryPage()
- const route=useRoute()
- const router=useRouter()
- const props=defineProps({
- edbInfo:{
- type:Object,
- default:null
- }
- })
- watch(
- ()=>props.edbInfo,
- ()=>{
- if(['edit','preview'].includes(route.query.type)){
- props.edbInfo.CalculateList.forEach(item=>{
- if(item.FromTag==='A'){
- independentEDBInfo.value={
- EdbInfoId:item.FromEdbInfoId,
- EdbName:item.FromEdbName,
- StartDate:item.StartDate,
- EndDate:item.EndDate
- }
- selfMoveType.value=item.MoveValue===0?0:1
- selfMoveVal.value=item.MoveValue
- }
- if(item.FromTag==='B'){
- dependentEDBInfo.value={
- EdbInfoId:item.FromEdbInfoId,
- EdbName:item.FromEdbName,
- StartDate:item.StartDate,
- EndDate:item.EndDate
- }
- }
- })
- fittingDate.value=props.edbInfo.EdbInfoDetail.CalculateFormula.split(',')
- baseInfo.name=props.edbInfo.EdbInfoDetail.EdbName
- baseInfo.unit=props.edbInfo.EdbInfoDetail.Unit
- baseInfo.classify=props.edbInfo.EdbInfoDetail.ClassifyId
- baseInfo.frequency=props.edbInfo.EdbInfoDetail.Frequency
- setTimeout(() => {
- selectEDBClassifyINS.value?.getSelectClassifyOpt(props.edbInfo.EdbInfoDetail.ClassifyId)//获取选择的分类目录
- }, 1000);
- getEDBCorrelationIndex()
- }
- }
- )
- // 预览页面
- const isPreview=ref(route.query.type==='preview'||false)
- const source=ref(Number(route.query.source)||0)//计算类型
- //公式说明
- const showTips=ref(false)
- const tipsContent=ref(calculateTypeTipsMap.get(['toMonthSeason','accumulate'].includes(route.query.source)? route.query.source: Number(route.query.source))||'')
- // 获取两个指标的相关系数
- const correlationIndex=ref('')
- async function getEDBCorrelationIndex(){
- if(!independentEDBInfo.value||!dependentEDBInfo.value||fittingDate.value.length===0) return correlationIndex.value=''
- if(selfMoveType.value===1&&!selfMoveVal.value) return correlationIndex.value=''
- const params={
- Formula:fittingDate.value.join(','),
- EdbInfoIdArr:[
- {
- EdbInfoId:independentEDBInfo.value.EdbInfoId,
- FromTag: 'A',
- MoveValue:selfMoveType.value===0?0:Number(selfMoveVal.value)
- },
- {
- EdbInfoId:dependentEDBInfo.value.EdbInfoId,
- FromTag: 'B',
- MoveValue:0
- }
- ]
- }
- const res=await apiDataEDB.edbCorrelationIndex(params)
- if(res.Ret===200){
- correlationIndex.value=res.Data
- }
- }
- // 选择指标
- const showSelectEDB=ref(false)
- const independentEDBInfo=ref(null)//自变量指标
- const dependentEDBInfo=ref(null)//因变量指标
- let currentSelectEDBType=''
- function handleShowSelectEDB(type){
- if(isPreview.value) return
- currentSelectEDBType=type
- showSelectEDB.value=true
- }
- function handleConfirmSelectEDB(e){
- if(currentSelectEDBType==='independent'){
- independentEDBInfo.value=e
- baseInfo.unit=e.Unit
- baseInfo.frequency=e.Frequency
- selectEDBClassifyINS.value?.getSelectClassifyOpt(e.ClassifyId)
- }else{
- dependentEDBInfo.value=e
- }
- if(independentEDBInfo.value&&dependentEDBInfo.value){
- baseInfo.name=`${dependentEDBInfo.value.EdbName}拟合残差/${independentEDBInfo.value.EdbName}`
- }
- getEDBCorrelationIndex()
- }
- // 类型
- const selfMoveType=ref(0)
- const selfMoveVal=ref('')
- function handleSelfMoveTypeChange(){
- selfMoveVal.value=''
- getEDBCorrelationIndex()
- }
- //拟合时间段
- const showFittingDate=ref(false)
- const fittingDate=ref([])
- function handleConfirmFittingDate(e){
- // 日期间隔不得少于两天
- const diff=moment(e[1]).diff(e[0],'days')
- if(diff<2){
- showToast('日期间隔不得少于两天')
- return
- }
- fittingDate.value=e
- getEDBCorrelationIndex()
- }
- // 基础信息
- const edbNameInputFocus=ref(false)
- const baseInfo=reactive({
- name:'',
- unit:'',
- classify:'',
- frequency:''
- })
- // 选择单位
- const showSelectUnit=ref(false)
- function onConfirmSelectUnit(value){
- baseInfo.unit=value
- }
- //选择分类
- const showSelectClassify=ref(false)
- const classifyStr=ref('')
- const selectEDBClassifyINS=ref(null)
- function handleConfirmClassify({value,selectedOptions}){
- if(selectedOptions.length===0){
- baseInfo.classify=''
- classifyStr.value=''
- return
- }
- baseInfo.classify=value
- const textArr=selectedOptions.map(item=>item.ClassifyName)
- classifyStr.value=`${textArr.join('/')}`
- }
- //选择频度
- const showSelectFrequency=ref(false)
- function handleConfirmFrequency(value){
- baseInfo.frequency=value
- }
- // 提交计算
- const saveBtnLoading=ref(false)
- async function handleSave(){
- if(!independentEDBInfo.value){
- showToast('自变量不能为空')
- return
- }
- if(!dependentEDBInfo.value){
- showToast('因变量不能为空')
- return
- }
- if(fittingDate.value.length===0){
- showToast('拟合时间段不能为空')
- return
- }
- if(!baseInfo.name){
- showToast('指标名称不能为空')
- return
- }
- if(!baseInfo.unit){
- showToast('指标单位不能为空')
- return
- }
- if(!baseInfo.classify){
- showToast('指标目录不能为空')
- return
- }
- if(!baseInfo.frequency){
- showToast('指标频度不能为空')
- return
- }
- const params={
- Source: source.value,
- EdbName: baseInfo.name,
- Unit: baseInfo.unit,
- ClassifyId: baseInfo.classify,
- Frequency: baseInfo.frequency,
- Formula:fittingDate.value.join(','),
- EdbInfoIdArr:[
- {
- EdbInfoId:independentEDBInfo.value.EdbInfoId,
- FromTag: 'A',
- MoveValue:selfMoveType.value===0?0:Number(selfMoveVal.value)
- },
- {
- EdbInfoId:dependentEDBInfo.value.EdbInfoId,
- FromTag: 'B',
- MoveValue:0
- }
- ]
- }
- saveBtnLoading.value=true
- const res=route.query.type==='edit'?await apiDataEDB.editCalculateEDB({...params,EdbInfoId:Number(route.query.edbInfoId)}) : await apiDataEDB.addCalculateEDB(params)
- saveBtnLoading.value=false
- if(res.Ret===200){
- showToast(res.Msg)
- setTimeout(() => {
- if(route.query.type==='edit'){
- router.back()
- }else{
- router.replace({
- path:'/dataEDB/detail',
- query:{
- edbInfoId:res.Data.EdbInfoId
- }
- })
- }
- }, 1500);
- }
- }
- //点击选择的指标左侧图标查看指标详情
- const showEDBHistory=ref(false)// 显示指标溯源
- const edbHistoryId=ref(0)
- function handleShowEDBHistory(data){
- //计算指标打开弹窗,基础指标打开新页面
- if(data.EdbType===2){
- /* edbHistoryId.value=data.EdbInfoId
- showEDBHistory.value=true */
- toHistoryPage(data.EdbInfoId)
- }else{
- const routerEl=router.resolve({
- path:'/dataEDB/detail',
- query:{
- edbInfoId:data.EdbInfoId
- }
- })
- window.open(routerEl.href,'_blank')
- }
- }
- </script>
- <template>
- <div class="fitting-residuals-wrap">
- <section class="section select-edb-box">
- <van-field
- label="自变量"
- required
- :right-icon="!isPreview?'arrow':''"
- @click-input="handleShowSelectEDB('independent')"
- :disabled="isPreview"
- >
- <template #left-icon>
- <div class="left-icon" v-if="independentEDBInfo" @click="handleShowEDBHistory(independentEDBInfo)">
- <svg-icon name="edb-history-tag" size="24px"/>
- </div>
- </template>
- <template #input>
- <div class="edb-info-box">
- <div class="edb-info" v-if="independentEDBInfo">
- <span class="name">{{independentEDBInfo.EdbName}}</span>
- <span class="time">{{independentEDBInfo.StartDate}}至{{independentEDBInfo.EndDate}}</span>
- </div>
- <span class="placeholder" v-else>请选择指标</span>
- </div>
- </template>
- </van-field>
- <van-cell>
- <div class="self-move-type-box">
- <van-radio-group :disabled="isPreview" v-model="selfMoveType" shape="dot" direction="horizontal" @change="handleSelfMoveTypeChange">
- <van-radio :name="0">标准指标</van-radio>
- <van-radio :name="1">领先天数</van-radio>
- </van-radio-group>
- <div class="day-box" v-show="selfMoveType===1">
- <input class="input" :disabled="isPreview" type="number" :min="0" v-model="selfMoveVal" @change="getEDBCorrelationIndex()">
- <span>天</span>
- </div>
- </div>
- </van-cell>
- <van-field
- label="因变量"
- required
- :right-icon="!isPreview?'arrow':''"
- @click-input="handleShowSelectEDB('dependent')"
- :disabled="isPreview"
- >
- <template #left-icon>
- <div class="left-icon" v-if="dependentEDBInfo" @click="handleShowEDBHistory(dependentEDBInfo)">
- <svg-icon name="edb-history-tag" size="24px"/>
- </div>
- </template>
- <template #input>
- <div class="edb-info-box">
- <div class="edb-info" v-if="dependentEDBInfo">
- <span class="name">{{dependentEDBInfo.EdbName}}</span>
- <span class="time">{{dependentEDBInfo.StartDate}}至{{dependentEDBInfo.EndDate}}</span>
- </div>
- <span class="placeholder" v-else>请选择指标</span>
- </div>
- </template>
- </van-field>
- <van-field
- label="拟合时间段"
- :right-icon="!isPreview?'arrow':''"
- required
- @click-input="()=>{if(isPreview) return false ;showFittingDate=true}"
- :disabled="isPreview"
- >
- <template #input>
- <div class="edb-info-box">
- <div class="edb-info" v-if="fittingDate.length>0">
- <span class="name">{{fittingDate[0]}}~{{fittingDate[1]}}</span>
- <span class="time" v-if="correlationIndex">相关系数:{{correlationIndex}}</span>
- </div>
- <span class="placeholder" v-else>请选择时间段</span>
- </div>
- </template>
- </van-field>
- </section>
- <section class="section baseinfo-box">
- <van-field
- v-model="baseInfo.name"
- label="指标名称"
- placeholder="指标名称"
- input-align="right"
- required
- @focus="edbNameInputFocus=true"
- @blur="edbNameInputFocus=false"
- :disabled="isPreview"
- >
- <template #right-icon>
- <svg-icon v-if="!isPreview" class="edit-icon" name="edit" :color="edbNameInputFocus?'#0052D9':'#333333'"/>
- </template>
- </van-field>
- <van-field
- :modelValue="baseInfo.unit"
- readonly
- label="单位"
- placeholder="请选择单位"
- input-align="right"
- :right-icon="!isPreview?'arrow':''"
- required
- @click-input="showSelectUnit=true"
- :disabled="isPreview"
- />
- <van-field
- :modelValue="classifyStr"
- readonly
- label="指标目录"
- placeholder="请选择指标目录"
- input-align="right"
- :right-icon="!isPreview?'arrow':''"
- required
- @click-input="showSelectClassify=true"
- :disabled="isPreview"
- />
- <van-field
- :modelValue="baseInfo.frequency"
- readonly
- label="频度"
- placeholder="请选择指标频度"
- input-align="right"
- :right-icon="!isPreview?'arrow':''"
- required
- @click-input="showSelectFrequency=true"
- :disabled="isPreview"
- />
- </section>
- <div class="formula-intro-btn" @click="showTips=true">
- <svg-icon class="icon" name="warning"></svg-icon>
- <span>公式说明</span>
- </div>
- <div class="opt-btns" v-if="!isPreview">
- <van-button class="primary2" @click="$router.back()">取消</van-button>
- <van-button
- type="primary"
- :loading="saveBtnLoading"
- loading-text="计算中..."
- @click="handleSave"
- >拟合残差计算</van-button>
- </div>
- </div>
- <!-- 选择指标 -->
- <SelectEDB v-model:show="showSelectEDB" :params="{FilterSource:1}" @select="handleConfirmSelectEDB"/>
- <!-- 选择时间段 -->
- <SelectDateRange v-model:show="showFittingDate" @select="handleConfirmFittingDate"/>
- <!-- 选择单位 -->
- <SelectEDBUnit v-model:show="showSelectUnit" @select="onConfirmSelectUnit"/>
- <!-- 选择分类 -->
- <SelectEDBClassify ref="selectEDBClassifyINS" :defaultId="baseInfo.classify" v-model:show="showSelectClassify" @select="handleConfirmClassify" />
- <!-- 选择频度 -->
- <SelectEDBFrequency v-model:show="showSelectFrequency" @select="handleConfirmFrequency"/>
- <!-- 指标溯源 -->
- <EDBHistory v-model:show="showEDBHistory" :edbInfoId="edbHistoryId"/>
- <!-- 公式说明 -->
- <van-dialog
- v-model:show="showTips"
- :title="$route.query.name"
- confirmButtonText='知道啦'
- >
- <div class="edb-formula-tips-html-box" v-html="tipsContent"></div>
- </van-dialog>
- </template>
- <style lang="scss" scoped>
- .fitting-residuals-wrap{
- min-height: 90vh;
- background-color: $page-bg-grey;
- padding-bottom: 210px ;
- }
- .section{
- background-color: #fff;
- margin-bottom: 32px;
- }
- .self-move-type-box{
- padding: 20px 0;
- display: flex;
- justify-content: space-between;
- .day-box{
- display: flex;
- align-items: center;
- gap: 5px;
- .input{
- width: 80px;
- height: 48px;
- border: 1px solid #DCDCDC;
- border-radius: 6px;
- text-align: center;
- padding: 0 10px;
- color: #333;
- }
- }
- }
- .select-edb-box{
- :deep(.van-cell__right-icon){
- align-self: center;
- color: #333;
- }
- .edb-info-box{
- width: 100%;
- text-align: right;
- .placeholder{
- color: var(--van-text-color-3);
- }
- .edb-info{
- display: flex;
- flex-direction: column;
- }
- .time{
- color: $font-grey_999;
- font-size: 24px;
- }
- }
- }
- .formula-intro-btn{
- width: 180px;
- height: 60px;
- display: flex;
- align-items: center;
- justify-content: center;
- gap: 5px;
- color: $theme-color;
- line-height: 1;
- background-color: #fff;
- border-radius: 32px;
- margin-left: auto;
- margin-right: var(--van-cell-horizontal-padding);
- .icon{
- width: 24px;
- height: 24px;
- }
- }
- .opt-btns{
- position: fixed;
- left: 0;
- right: 0;
- bottom: 0;
- background-color: #fff;
- z-index: 99;
- padding: 48px;
- display: flex;
- justify-content: space-between;
- .van-button{
- width: 48%;
- max-width: 300PX;
- }
- }
- @media screen and (min-width:$media-width){
- .fitting-residuals-wrap{
- padding-bottom: 105px;
- }
- .section{
- margin-bottom: 16px;
- }
- .self-move-type-box{
- padding: 10px 0;
- .day-box{
- gap: 5px;
- .input{
- width: 40px;
- height: 24px;
- border-radius: 3px;
- padding: 0 5px;
- }
- }
- }
- .select-edb-box{
- .edb-info-box{
- .time{
- font-size: 12px;
- }
- }
- }
- .formula-intro-btn{
- width: 90px;
- height: 30px;
- gap: 2px;
- border-radius: 16px;
- .icon{
- width: 12px;
- height: 12px;
- }
- }
- .opt-btns{
- padding: 24px;
- justify-content: center;
- gap: 10px;
- }
- }
- </style>
|