Selaa lähdekoodia

图详情剩余布局,指标详情-数据来源

cxmo 1 vuosi sitten
vanhempi
commit
27dd718af4

+ 7 - 0
src/api/chart.js

@@ -205,5 +205,12 @@ export default{
     setUserLang(params){
         return post('/system/sysuser/config/set',params)
     },
+    /**
+     * 获取指标历史生成记录
+     * @param EdbInfoId
+     */
+    getEdbCreateHistory(params){
+        return get('/datamanage/edb_info/trace',params)
+    },
 
 } 

BIN
src/assets/imgs/chartETA/more-icon.png


+ 423 - 2
src/views/chartETA/ChartDetail.vue

@@ -2,16 +2,22 @@
 import {nextTick, onMounted,ref,reactive} from 'vue'
 import apiChart from '@/api/chart'
 import { useRoute } from 'vue-router'
-import {sameOptionType} from '@/hooks/chart/config'
+import { useWindowSize } from '@vueuse/core'
+import {yearSelectOpt,sameOptionType} from '@/hooks/chart/config'
 import {useChartRender} from '@/hooks/chart/render'
 import moment from 'moment'
+import EdbInfo from './components/EdbInfo.vue'
+import SourceDetail from './components/SourceDetail.vue'
 
 const {options,axisLimitState,chartRender}=useChartRender()
+const { width } = useWindowSize()
 
 const route=useRoute()
 
 //获取图详情
 let chartInfo=ref(null)
+//指标数据
+let edbList=ref([])
 async function getChartDetail(){
     const params=sameOptionType.includes(Number(route.query.chartType))?{
         ChartInfoId:Number(route.query.id),
@@ -27,7 +33,13 @@ async function getChartDetail(){
     const res=await apiChart.chartInfoById(params)
     if(res.Ret!==200) return
     chartInfo.value=res.Data.ChartInfo
+    if(res.Data.ChartInfo.Source===2){
+        edbList.value=[res.Data.EdbInfoList[0]]
+    }else{
+        edbList.value=res.Data.EdbInfoList
+    }
 
+    chartState.yearVal=res.Data.ChartInfo.DateType
     nextTick(()=>{
         chartRender({
             data:res.Data,
@@ -57,6 +69,70 @@ let chartState=reactive({
     calendarType:'公历'
 })
 
+// 切换年份选项
+function handleYearChange(item){
+    chartState.yearVal=item.value
+    chartState.startTime=''
+    chartState.endTime=''
+    reloadChartInfo()
+}
+// 确定日期筛选
+function handleTimeChange(){
+    chartState.startTime=temStartTime.value.join('-')
+    chartState.endTime=temEndTime.value.join('-')
+    chartState.yearVal=6
+    reloadChartInfo()
+    chartState.showTimePop=false
+}
+// 季节图公历\农历切换
+function handleSeasonTypeChange(type){
+    chartState.calendarType=type
+    reloadChartInfo()
+}
+// 选择项发生变化时 非配置项 获取新的图表数据
+async function reloadChartInfo(){
+    const params=sameOptionType.includes(chartInfo.value.ChartType)?{
+        ChartInfoId: chartInfo.value.ChartInfoId,
+        DateType: chartState.yearVal,
+        StartDate: chartState.startTime,
+        EndDate: chartState.endTime,
+    }:{
+        ChartInfoId: chartInfo.value.ChartInfoId,
+        Calendar: chartState.calendarType,//this.calendar_type
+        SeasonStartDate: chartState.startTime,
+        SeasonEndDate:chartState.endTime ,
+    }
+    const res=await apiChart.chartInfoById(params)
+    if(res.Ret!==200) return
+    chartInfo.value=res.Data.ChartInfo
+    chartRender({
+        data:{
+            ...res.Data,
+            ChartInfo:{
+                ...res.Data.ChartInfo,
+                Calendar:chartState.calendarType||'公历'
+            },
+        },
+        renderId:'chart-box',
+        lang:'zh',
+        changeLangIsCheck:false,
+        showChartTitle:false
+    })
+}
+
+// 显示指标详情
+let showEDB=ref(false)
+let showEDBData=ref({})
+function handleShowEDBInfo(item){
+    showEDBData.value=item
+    showEDB.value=true
+}
+//显示数据来源详情
+let showSourceDetail = ref(false)
+function handleShowSourceDetail(){
+    showSourceDetail.value = true
+}
+
 </script>
 
 <template>
@@ -73,12 +149,145 @@ let chartState=reactive({
             <span :class="['val-box',!chartState.startTime?'val-box_grey':'']">{{chartState.startTime||'开始日期'}} ~ {{chartState.endTime||'结束日期'}}</span>
             <van-icon class="right-icon" name="arrow" />
         </div>
+        <!-- pad端时间和操作按钮模块 -->
+        <div class="pad-time-action-wrap">
+            <div class="left-time-box">
+                <template v-if="sameOptionType.includes(chartInfo.ChartType)">
+                    <span :class="['item',chartState.yearVal==''?'active':'']" @click="handleYearChange({value:''})">全部</span>
+                    <span 
+                        :class="['item',chartState.yearVal==item.value?'active':'']"
+                        v-for="item in yearSelectOpt" 
+                        :key="item.value"
+                        @click="handleYearChange(item)"
+                    >{{item.name}}</span>
+                </template>
+                <span 
+                    class="time-box" 
+                    v-if="sameOptionType.includes(chartInfo.ChartType)||chartInfo.ChartType===2"
+                    @click="chartState.showTimePop=true"
+                >{{chartState.startTime?chartState.startTime+'~'+chartState.endTime:'请选择时间段'}}</span>
+            </div>
+            <div class="right-action-box">
+                <div class="item" @click.stop="" >
+                    <img src="@/assets/imgs/chartETA/more-icon.png" alt="">
+                    <span>更多设置</span>
+                </div>
+            </div>
+        </div>
 
         <!-- 图渲染区域 -->
         <div class="chart-render-wrap">
             <div class="chart-box" id="chart-box"></div>
         </div>
-
+        <!-- 手机端选择时间区间模块 -->
+        <div class="select-year-box" v-if="sameOptionType.includes(chartInfo.ChartType)">
+            <span :class="['item',chartState.yearVal==''?'active':'']" @click="handleYearChange({value:''})">全部</span>
+            <span 
+                :class="['item',chartState.yearVal==item.value?'active':'']"
+                v-for="item in yearSelectOpt" 
+                :key="item.value"
+                @click="handleYearChange(item)"
+            >{{item.name}}</span>
+        </div>
+        <!-- 季节图切换公/农历 -->
+        <div class="calendar-type-box" v-if="chartInfo.ChartType === 2">
+            <span 
+                :class="chartState.calendarType=='公历'?'active':''"
+                @click="handleSeasonTypeChange('公历')"
+            >公历</span>
+            <span 
+                :class="chartState.calendarType=='农历'?'active':''"
+                @click="handleSeasonTypeChange('农历')"
+            >农历</span>
+        </div>
+        <!-- 指标模块 -->
+        <div class="edb-list-box">
+            <!-- pad 设置上下限按钮 -->
+            <div class="pad-limit-set-btn" @click="handleShowAxisLimitOpt" v-if="chartInfo.Source!=3&&chartInfo.ChartType!=8">设置上下限</div>
+            <!-- <div class="list-lable">指标信息</div> -->
+            <div class="list-box">
+                <div class="list-item" v-for="item in edbList" :key="item.EdbInfoId" @click="handleShowEDBInfo(item)">
+                    <span class="date">{{item.LatestDate}}</span>
+                    <span class="edb-name van-ellipsis" :style="{color:item.ChartColor}">{{item.EdbName}}</span>
+                    <span class="value">{{item.LatestValue}}</span>
+                </div>
+            </div>
+        </div>
+        <!-- 底部悬浮操作模块 -->
+        <div class="fix-bot-action-box">
+            <div class="item" @click="">
+                <img class="icon" src="@/assets/imgs/icon_arrow.png" alt="">
+                <div>上一张</div>
+            </div>
+            <div class="item" @click="">
+                <img class="icon" style="transform: rotate(180deg);" src="@/assets/imgs/icon_arrow.png" alt="">
+                <div>下一张</div>
+            </div>
+            <div class="item" @click="handleShowAxisLimitOpt" v-if="chartInfo.Source!=3&&chartInfo.ChartType!=8">
+                <img class="icon" src="@/assets/imgs/myETA/icon_limit.png" alt="">
+                <div>上下限</div>
+            </div>
+            <div class="item" @click="showMoreAction=true">
+                <img class="icon" src="@/assets/imgs/myETA/icon_menu.png" alt="">
+                <div>更多</div>
+            </div>
+        </div>
+        <!-- 选择日期弹窗 -->
+        <van-popup 
+            v-model:show="chartState.showTimePop"
+            :position="width>650?'center':'bottom'"
+            :style="width>650?{ width: '400px'}:''"
+        >
+            <div class="time-picker-wrap">
+                <van-picker-group
+                    title="选择起始时间"
+                    :tabs="['开始时间', '结束时间']"
+                    @cancel="chartState.showTimePop=false"
+                    @confirm="handleTimeChange"
+                >
+                    <van-date-picker
+                        v-model="temStartTime"
+                        :min-date="minDate"
+                        :max-date="maxDate"
+                        :columns-type="chartInfo.ChartType==2?['year']:['year','month']"
+                    />
+                    <van-date-picker 
+                        v-model="temEndTime" 
+                        :min-date="minDate" 
+                        :max-date="maxDate"
+                        :columns-type="chartInfo.ChartType==2?['year']:['year','month']"
+                    />
+                </van-picker-group>
+            </div>
+        </van-popup>
+        <!-- 指标详情弹窗 -->
+        <van-popup 
+            v-model:show="showEDB"
+            :position="width>650?'right':'bottom'"
+            round
+            closeable
+            :style="width>650?{ width: '400px', height: '100%' }:''"
+            >
+                <EdbInfo
+                    :show="showEDB"
+                    :data="showEDBData"
+                    :tableData="edbList"
+                    @showSourceDetail="handleShowSourceDetail"
+                />
+        </van-popup>
+        <!--  数据来源弹窗-->
+        <van-popup
+            v-model:show="showSourceDetail"
+            position="center"
+            round
+            closeable
+            :style="{ width: '400px'}"
+        >
+            <SourceDetail
+                :show="showSourceDetail"
+                :EdbInfoId="showEDBData.EdbInfoId"
+            />
+        </van-popup>
     </div>
 </template>
 
@@ -114,5 +323,217 @@ let chartState=reactive({
             }
         }
     }
+    .select-year-box{
+        width: 100vw;
+        position: relative;
+        left: -$page-padding;
+        margin-top: 30px;
+        box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.08);
+        height: 88px;
+        display: flex;
+        align-items: center;
+        overflow-y: auto;
+        padding: 0 $page-padding;
+        &::-webkit-scrollbar{
+            height: 0;
+        }
+        .item{
+            line-height: 88px;
+            position: relative;
+            height: 100%;
+            flex-shrink: 0;
+            display: inline-block;
+            margin-right: 40px;
+            font-size: 32px;
+            color: $font-grey_999;
+            &.active{
+                color: #333;
+                &::after{
+                    content: '';
+                    display: block;
+                    width: 50px;
+                    height: 6px;
+                    border-radius: 3px;
+                    background-color: $theme-color;
+                    position: absolute;
+                    bottom: 0;
+                    left: 50%;
+                    transform: translateX(-50%);
+                }
+            }
+        }
+    }
+    .calendar-type-box{
+        width: 404px;
+        margin: 30px auto;
+        text-align: center;
+        border: 1px solid $theme-color;
+        border-radius: 12px;
+        overflow: hidden;
+        span{
+            display: inline-block;
+            width: 200px;
+            height: 80px;
+            line-height: 80px;
+            color: $theme-color;
+            font-weight: bold;
+            &.active{
+                background-color: $theme-color;
+                color: #fff;
+            }
+        }
+    }
+    .pad-time-action-wrap{
+        display: none;
+    }
+    .edb-list-box{
+        .pad-limit-set-btn{
+            display: none;
+        }
+        .list-lable{
+            font-size: 36px;
+            color: #000;
+            margin-bottom: 20px;
+            margin-top: 40px;
+        }
+        .list-item{
+            padding:18px;
+            display: flex;
+            gap:0 20px;
+            border-bottom: 1px solid #DCDFE6;
+            .edb-name{
+                flex: 1;
+                /* text-align: center; */
+            }
+        }
+    }
+
+    .fix-bot-action-box{
+        position: fixed;
+        left: 0;
+        bottom: 0;
+        right: 0;
+        z-index: 99;
+        background-color: #fff;
+        border-top: 1px solid $border-color;
+        height: 112px;
+        display: flex;
+        align-items: center;
+        .item{
+            height: 100%;
+            flex: 1;
+            display: flex;
+            flex-direction: column;
+            justify-content: center;
+            align-items: center;
+            font-size: 20px;
+            .icon{
+                width: 40px;
+                height: 40px;
+                margin-bottom: 5px;
+            }
+        }
+    }
+    @media screen and (min-width:$media-width){
+        padding:30px;
+        .chart-title{
+            font-size: 16px;
+            font-weight: bold;
+            margin-bottom: 30px;
+        }
+        .chart-box{
+            width: 85%;
+            height: 370px;
+            margin: 0 auto;
+        }
+        .select-time-box,.select-year-box,.fix-bot-action-box{
+            display: none;
+        }
+        .pad-time-action-wrap{
+            display: flex;
+            flex-wrap: wrap;
+            align-items: center;
+            justify-content: space-between;
+            .left-time-box{
+                flex-shrink: 0;
+                margin-bottom: 20px;
+                .item{
+                    display: inline-block;
+                    width: 80px;
+                    height: 36px;
+                    text-align: center;
+                    line-height: 36px;
+                    border: 1px solid $theme-color;
+                    margin-right: 10px;
+                    border-radius: 3px;
+                    &.active{
+                        color: #fff;
+                        background-color: $theme-color;
+                    }
+                }
+                .time-box{
+                    display: inline-block;
+                    padding: 0 15px;
+                    height: 36px;
+                    line-height: 36px;
+                    border: 1px solid $theme-color;
+                    border-radius: 3px;
+                    background-color: #F2F3FF;
+                    color: $theme-color;
+                }
+            }
+            .right-action-box{
+                display: flex;
+                margin-bottom: 20px;
+                .item{
+                    display: flex;
+                    color: $theme-color;
+                    margin-left: 20px;
+                    img{
+                        width: 15px;
+                        height: 15px;
+                        margin-right: 4px;
+                    }
+                }
+            }
+        }
+        .calendar-type-box{
+            width: 224px;
+            margin: 20px auto;
+            border-radius: 4px;
+            span{
+                width: 111px;
+                height: 38px;
+                line-height: 38px;
+            }
+        }
+        .edb-list-box{
+            position: relative;
+            left: -30px;
+            border-top: 1px solid $border-color;
+            width: 100vw;
+            padding: 0 30px;
+            .pad-limit-set-btn{
+                display: block;
+                text-align: right;
+                margin: 20px 0;
+                color: $theme-color;
+            }
+            .list-lable{
+                margin-top: 20px;
+                font-size: 16px;
+                margin-bottom: 14px;
+            }
+            .list-box{
+                border: 1px solid $border-color;
+                .list-item{
+                    padding: 18px;
+                    &:last-child{
+                        border-bottom: none;
+                    }
+                }
+            }
+        }
+    }
 }
 </style>

+ 12 - 2
src/views/chartETA/List.vue

@@ -1,6 +1,7 @@
 <script setup>
 //ETA图库页面
-import {ref,reactive,watch, nextTick} from 'vue'
+import {ref,reactive,watch} from 'vue'
+import { useRouter } from 'vue-router'
 import { showToast,showDialog} from "vant";
 import { useWindowSize } from '@vueuse/core'
 import CatalogTree from './components/CatalogTree.vue';
@@ -12,6 +13,7 @@ import apiChart from '@/api/chart'
 import {useCatalogList} from './hooks/useCatalogList';
 
 const { width } = useWindowSize()
+const router=useRouter()
 
 const {
     optArrChart,//图表操作列表
@@ -25,7 +27,15 @@ const goSearch = ()=>{
 }
 
 //跳转至图表详情页
-const goChartDetail = ()=>{}
+const goChartDetail = (item)=>{
+    router.push({
+        path:'/chartETA/chartdetail',
+        query:{
+            id:item.ChartInfoId,
+            chartType:item.ChartType
+        }
+    })
+}
 
 
 //是否展示目录列表

+ 13 - 0
src/views/chartETA/SetChartENName.vue

@@ -0,0 +1,13 @@
+<script setup>
+//设置图表英文名称
+</script>
+
+<template>
+    <div>
+
+    </div>
+</template>
+
+<style scoped lang="scss">
+
+</style>

+ 167 - 0
src/views/chartETA/components/EdbInfo.vue

@@ -0,0 +1,167 @@
+<script setup>
+import {ref,watch} from 'vue'
+import _ from 'lodash'
+
+
+const props=defineProps({
+    show:{
+        type:Boolean,
+        default:false
+    },
+    data:{
+        type:Object,
+        default:{}
+    },
+    tableData:{
+        type:Array,
+        default:[]
+    },
+})
+
+const temData=ref(_.cloneDeep(props.data)||{})
+
+watch(
+    ()=>props.show,
+    (n)=>{
+        if(!n){
+            temData.value={}
+        }else{
+            temData.value=_.cloneDeep(props.data)
+        }
+    }
+)
+
+const list=[
+    {
+        name:"指标名称",
+        key:"EdbName"
+    },
+    {
+        name:"指标ID",
+        key:"EdbCode"
+    },
+    {
+        name:"更新频度",
+        key:"Frequency"
+    },
+    {
+        name:"单位",
+        key:"Unit"
+    },
+    {
+        name:"起始时间",
+        key:"StartDate"
+    },
+    {
+        name:"最新日期",
+        key:"LatestDate"
+    },
+    {
+        name:"最新值",
+        key:"LatestValue"
+    },
+    {
+        name:"最近更新",
+        key:"LatestDate"
+    },
+    /* {
+        name:"数据来源",
+        key:"SourceName"
+    } */
+]
+const emits = defineEmits(['showSourceDetail'])
+function showDetail(){
+    emits('showSourceDetail')
+}
+
+
+
+</script>
+
+<template>
+    <div class="edb-info-wrap">
+        <div class="top-box">
+            <span class="title">指标详情</span>
+        </div>
+        <div class="con-box">
+            <ul class="info-list">
+                <li class="item" v-for="item in list" :key="item.key">
+                    <span class="lable">{{item.name}}</span>
+                    <span class="text">{{data[item.key]}}</span>
+                </li>
+                <li class="item">
+                    <span class="label">数据来源</span>
+                    <span class="text">{{data['SourceName']}}</span>
+                    <van-icon 
+                        name="arrow" 
+                        color="#999" 
+                        v-if="data['EdbType']===2"
+                        @click="showDetail"/>
+                </li>
+            </ul>
+        </div>
+    </div>
+</template>
+
+<style lang="scss" scoped>
+.edb-info-wrap{
+    .top-box{
+        padding: 32px $page-padding;
+        border-bottom: 1px solid $border-color;
+        .title{
+            font-size: 32px;
+            font-weight: 600;
+        }
+    }
+    .con-box{
+        max-height: 60vh;
+        overflow-y: auto;
+        &::-webkit-scrollbar{
+            display: none;
+        }
+    }
+    .info-list{
+        padding: $page-padding;
+        padding-bottom: 40px;
+        .item{
+            display: flex;
+            justify-content: space-between;
+            padding: 32px 0;
+            border-bottom: 1px solid $border-color;
+            .lable{
+                flex-shrink: 0;
+            }
+            .text{
+                width: 70%;
+                text-align: right;
+                color: $font-grey_999;
+            }
+        }
+    }
+
+}
+@media screen and (min-width:$media-width){
+    .edb-info-wrap{
+        display: flex;
+        flex-direction: column;
+        height: 100%;
+        .top-box{
+            padding: 16px;
+            .title{
+                font-size: 18px;
+            }
+        }
+        .con-box{
+            flex: 1;
+            max-height: 100%;
+        }
+        .info-list{
+            padding: 16px;
+            padding-bottom: 20px;
+            .item{
+                padding: 16px 0;
+            }
+        }
+    }
+}
+</style>

+ 142 - 0
src/views/chartETA/components/SourceDetail.vue

@@ -0,0 +1,142 @@
+<script setup>
+//数据来源详情
+import {ref,watch} from 'vue'
+import apiChart from '@/api/chart'
+const props = defineProps({
+    show:{
+        type:Boolean,
+        default:false
+    },
+    EdbInfoId:{
+        type:Number,
+        default:0
+    }
+})
+
+watch(()=>props.show,()=>{
+    if(props.show){
+        getEdbInfo()
+    }
+})
+
+const edbSourceData = ref([])
+async function getEdbInfo(){
+    const res = await apiChart.getEdbCreateHistory({
+        EdbInfoId:props.EdbInfoId
+    })
+    if(res.Ret!==200) return 
+    edbSourceData.value = flatTreeData([res.Data]||[]).reverse()
+}
+function flatTreeData(tree){
+    let arr = []
+    let concatData=[]
+    for(const item of tree){
+        const {EdbName,RuleTitle} = item
+        concatData.push({EdbName:EdbName||'',RuleTitle:RuleTitle||''})
+        if(item.Child&&item.Child.length){
+            arr = arr.concat(flatTreeData(item.Child))
+        }
+    }
+    arr.push(concatData)
+    return arr
+}
+</script>
+
+<template>
+    <div class="source-detail-wrap">
+        <div class="top-box">
+            <span class="title"> 数据来源</span>
+        </div>
+        <div class="source-arr-wrap">
+            <div class="source-item" v-for="(arr,index) in edbSourceData">
+                <template v-for="item in arr">
+                    <span class="title">{{item.EdbName}}</span>
+                    <span class="text">{{item.RuleTitle}}</span>
+                </template>
+                
+                <div class="line" v-if="index!==edbSourceData.length-1"></div>
+            </div>
+        </div>
+    </div>
+</template>
+
+<style scoped lang="scss">
+.source-detail-wrap{
+    .top-box{
+        padding: 32px $page-padding;
+        border-bottom: 1px solid $border-color;
+        .title{
+            font-size: 32px;
+            font-weight: 600;
+        }
+    }
+
+    .source-arr-wrap{
+        display: flex;
+        flex-direction: column;
+        padding:40px 80px;
+        gap:40px;
+        .source-item{
+            position: relative;
+            .text{
+                display: block;
+                margin: 8px 0;
+                font-size: 12px;
+                color: #00000066;;
+            }
+            .line{
+                position:absolute;
+                left:-33px;
+                top:36px;
+                width:1px;
+                height:100%;
+                background-color: $theme-color;
+            }
+            &::after{
+                content:'';
+                position:absolute;
+                top:0;
+                left:-40px;
+                background-color: $theme-color;
+                width:16px;
+                height:16px;
+                border-radius: 50%;
+                top:8px;
+            }
+        }
+    }
+    @media screen and (min-width:$media-width){
+        .top-box{
+            padding: 16px;
+            .title{
+                font-size: 18px;
+            }
+        }
+
+        .source-arr-wrap{
+            padding:20px 40px;
+            gap:20px;
+            .source-item{
+                .text{
+                    margin: 8px 0;
+                    font-size: 12px;
+                }
+                .line{
+                    position:absolute;
+                    left:-17px;
+                    top:18px;
+                    width:1px;
+                    height:100%;
+                    background-color: $theme-color;
+                }
+                &::after{
+                    left: -20px;
+                    width: 8px;
+                    height: 8px;
+                    top:4px;
+                }
+            }
+        }
+    }
+}
+</style>