zxl
2026-03-25 60e85043cf278f79c21859c0f4ac03e69d9570fc
src/views/dataAnalysis/components/DataReGasStation.vue
@@ -1,5 +1,5 @@
<template>
  <div style="margin-right: 30px" class="data-reMechanism">
  <div style="margin-right: 30px" class="data-reMechanism" :class="{ 'trend-detail-open': trendDetailVisible }">
    <div style="display: flex; align-items: center">
      <div style="margin-right:12px;font-size:16px;font-weight:bold">趋势分析</div>
      <a-radio-group v-model="trendAnalysisType" @change="trendAnalysisTypeChange">
@@ -9,10 +9,11 @@
        <a-radio-button :value="3"> 通过率 </a-radio-button>
        <a-radio-button :value="4"> 客户 </a-radio-button>
        <a-radio-button :value="5"> 流失率 </a-radio-button>
        <a-radio-button :value="6"> 销售金额 </a-radio-button>
      </a-radio-group>
    </div>
    <div>
      <div style="display: flex; align-items: flex-end; flex-direction: column">
      <div class="trend-analysis-chart" :class="{ 'is-modal-open': trendDetailVisible }" style="display: flex; align-items: flex-end; flex-direction: column">
        <a-radio-group
          style="margin: 20px 0"
          size="small"
@@ -31,6 +32,8 @@
          :chartData="trendAnalysisData"
          style="width: 100%"
          :showpercent="trendAnalysisChartShowPercent"
          :enablePointClick="true"
          @chart-click="handleTrendChartClick"
        ></DataReLineChart>
      </div>
      <div id="trendAnalysisChartID"></div>
@@ -120,7 +123,49 @@
            <span style="color: #16b777" v-if="isContrast">{{ contrastObj.rebackRate }}%</span>
          </div>
        </div>
        <div class="fueling-overview-item">
          <div class="fueling-overview-name">销售金额(元)</div>
          <div class="fueling-overview-num">
            <span style="margin-right: 24px">{{ statisTotalObj.totalAmount }}</span>
            <span style="color: #16b777" v-if="isContrast">{{ contrastObj.totalAmount }}</span>
          </div>
        </div>
      </div>
    </div>
    <div class="oil-freq-compare-ct">
      <div class="block-title">活动前后车辆加油频次</div>
      <div class="oil-freq-compare-operator">
        <span>活动前时段</span>
        <a-range-picker
          style="width: 360px; margin: 0 12px"
          :value="beforeTimeRange"
          format="YYYY-MM-DD HH:mm:ss"
          valueFormat="YYYY-MM-DD HH:mm:ss"
          :show-time="{ defaultValue: [moment('00:00:00', 'HH:mm:ss'), moment('23:59:59', 'HH:mm:ss')] }"
          @change="beforeTimeChange"
        />
        <span>活动后时段</span>
        <a-range-picker
          style="width: 360px; margin: 0 12px"
          :value="afterTimeRange"
          format="YYYY-MM-DD HH:mm:ss"
          valueFormat="YYYY-MM-DD HH:mm:ss"
          :show-time="{ defaultValue: [moment('00:00:00', 'HH:mm:ss'), moment('23:59:59', 'HH:mm:ss')] }"
          @change="afterTimeChange"
        />
        <a-button type="primary" @click="getOilFreqCompareData"> 统计频次 </a-button>
      </div>
      <a-table
        class="oil-freq-compare-table"
        rowKey="licenseNum"
        size="middle"
        :columns="oilFreqCompareColumns"
        :dataSource="oilFreqCompareData"
        :loading="oilFreqCompareLoading"
        :scroll="{ y: 420 }"
        :pagination="{ pageSize: 10, showSizeChanger: true, pageSizeOptions: ['10', '20', '50'] }"
      >
      </a-table>
    </div>
    <div>
      <div class="block-title">车型分析</div>
@@ -170,11 +215,58 @@
        </div>
      </div>
    </div>
    <div>
      <div class="block-title">油品类型分析</div>
      <div style="display: flex">
        <div style="width: 70%; display: flex; align-items: center; justify-content: center; color: #999;">
          油品类型销售占比
        </div>
        <div style="width: 30%">
          <a-radio-group v-model="oilTypeSpecies" size="small" @change="oilTypeSpeciesChange">
            <a-radio-button :value="5"> 油品销量 </a-radio-button>
            <a-radio-button :value="6"> 销售金额 </a-radio-button>
          </a-radio-group>
          <DataRePieChart
            style="width: 100%"
            domId="oilTypePie"
            ref="oilTypePieRef"
            :chartData="oilTypePieData"
          ></DataRePieChart>
        </div>
      </div>
    </div>
    <TopTenCustomers
      :customerData="customerObj"
      :typeOneTotal="customerOneTotal"
      :typeTwoTotal="customerTwoTotal"
    ></TopTenCustomers>
    <a-modal
      centered
      width="70%"
      :footer="null"
      v-model="trendDetailVisible"
      :title="trendDetailTitle"
      :zIndex="5000"
      :getContainer="getModalContainer"
      wrapClassName="trend-detail-modal-wrap"
      @cancel="closeTrendDetail"
    >
      <a-table
        size="middle"
        bordered
        :columns="trendDetailColumns"
        :dataSource="trendDetailData"
        :loading="trendDetailLoading"
        :scroll="{ y: 420 }"
        :pagination="{ pageSize: 10, showSizeChanger: true, pageSizeOptions: ['10', '20', '50'] }"
        :rowKey="
          (record, index) => {
            return record.id || record.licenseNum || record.captureTime || record.startTime || index
          }
        "
      >
      </a-table>
    </a-modal>
  </div>
</template>
@@ -183,6 +275,7 @@
import DataReLineChart from './DataReLineChart'
import DataRePieChart from './DataRePieChart'
import { getAction, postAction } from '@tievd/cube-block/lib/api/manage'
import moment from 'moment'
export default {
  name: 'DataReMechanism',
  components: {
@@ -209,6 +302,7 @@
      description: '数据报表(加油站)',
      vehicleTypeSpecies: 1,
      fuelingStationSpecies: 2,
      oilTypeSpecies: 5,
      searchWay: '1',
      isContrast: false,
      activeTime: '',
@@ -223,15 +317,149 @@
      vehicleTypePieData: {}, //车型分析饼图数据
      fuelLevelLineData: {}, //加油位分析折线图数据
      fuelLevelPieData: {}, //加油位分析饼图数据
      oilTypePieData: {}, //油品类型分析饼图数据
      vehicleTypeLineData: {}, //车型分析折线图数据
      trendAnalysisType: 0, //趋势分析选择类型
      trendAnalysisUnit: 'DAYS', //趋势分析选择时间
      trendAnalysisData: {}, //趋势分析数据
      trendAnalysisChart: null, //趋势分析图表
      trendDetailVisible: false,
      trendDetailTitle: '趋势分析明细',
      trendDetailLoading: false,
      trendDetailData: [],
      trendDetailColumns: [],
      beforeStartTime: '',
      beforeEndTime: '',
      afterStartTime: '',
      afterEndTime: '',
      beforeTimeRange: [],
      afterTimeRange: [],
      oilFreqCompareLoading: false,
      oilFreqCompareData: [],
      oilFreqCompareColumns: [
        {
          title: '车牌号',
          align: 'center',
          dataIndex: 'licenseNum',
        },
        {
          title: '活动前加油次数',
          align: 'center',
          dataIndex: 'beforeOilCount',
        },
        {
          title: '活动后加油次数',
          align: 'center',
          dataIndex: 'afterOilCount',
        },
        {
          title: '变化值',
          align: 'center',
          dataIndex: 'diffOilCount',
        },
        {
          title: '变化率',
          align: 'center',
          dataIndex: 'diffRate',
          customRender: function (t) {
            if (t === null || t === undefined) {
              return '--'
            }
            return t + '%'
          },
        },
      ],
    }
  },
  methods: {
    moment,
    getModalContainer() {
      return document.body
    },
    getTrendDetailColumnsByType() {
      let commonIndexColumn = {
        title: '序号',
        dataIndex: '',
        key: 'rowIndex',
        width: 80,
        align: 'center',
        customRender: function (t, r, index) {
          return parseInt(index) + 1
        },
      }
      if (this.trendAnalysisType == 0) {
        return [
          commonIndexColumn,
          { title: '抓拍时间', align: 'center', dataIndex: 'captureTime' },
          { title: '车流量', align: 'center', dataIndex: 'carCount' },
          { title: '车型编码', align: 'center', dataIndex: 'modelCode' },
          { title: '设备编码', align: 'center', dataIndex: 'cameraCode' },
        ]
      }
      if (this.trendAnalysisType == 4 || this.trendAnalysisType == 5) {
        return [
          commonIndexColumn,
          { title: '更新时间', align: 'center', dataIndex: 'updateTimeSelf' },
          { title: '车牌号', align: 'center', dataIndex: 'licenseNum' },
          { title: '客户类型', align: 'center', dataIndex: 'clientName' },
          { title: '累计加油次数', align: 'center', dataIndex: 'oilCount' },
          { title: '累计油品销量', align: 'center', dataIndex: 'oilSum' },
        ]
      }
      if (this.trendAnalysisType == 6) {
        return [
          commonIndexColumn,
          { title: '进站时间', align: 'center', dataIndex: 'startTime' },
          { title: '车牌号', align: 'center', dataIndex: 'licenseNum' },
          { title: '行为类型', align: 'center', dataIndex: 'behaviorText' },
          { title: '加油位', align: 'center', dataIndex: 'oilPosition' },
          { title: '油品销量', align: 'center', dataIndex: 'oilVolume' },
          { title: '销售金额(元)', align: 'center', dataIndex: 'totalAmount' },
          { title: '通过率(分)', align: 'center', dataIndex: 'spandTime' },
        ]
      }
      return [
        commonIndexColumn,
        { title: '进站时间', align: 'center', dataIndex: 'startTime' },
        { title: '车牌号', align: 'center', dataIndex: 'licenseNum' },
        { title: '行为类型', align: 'center', dataIndex: 'behaviorText' },
        { title: '加油位', align: 'center', dataIndex: 'oilPosition' },
        { title: '油品销量', align: 'center', dataIndex: 'oilVolume' },
        { title: '通过率(分)', align: 'center', dataIndex: 'spandTime' },
      ]
    },
    handleTrendChartClick(params) {
      if (!params || !params.name) {
        return
      }
      if (this.$refs.trendAnalysisLineRef && this.$refs.trendAnalysisLineRef.hideTooltip) {
        this.$refs.trendAnalysisLineRef.hideTooltip()
      }
      this.trendDetailVisible = true
      this.trendDetailTitle = '趋势分析明细 - ' + params.name
      this.trendDetailColumns = this.getTrendDetailColumnsByType()
      this.trendDetailLoading = true
      postAction('/jyz/dataTable/statTrendDetail', {
        orgCode: this.selectTreeObj.orgCode,
        startTime: this.startTime,
        endTime: this.endTime,
        trendType: this.trendAnalysisType,
        timeUnit: this.trendAnalysisUnit,
        statTime: params.name,
        seriesName: params.seriesName,
      })
        .then((res) => {
          this.trendDetailData = res.result || []
        })
        .finally(() => {
          this.trendDetailLoading = false
        })
    },
    closeTrendDetail() {
      this.trendDetailVisible = false
      this.trendDetailData = []
    },
    //获取车型/加油位折线图数据
    getVehicleTypeLineData() {
      postAction('/jyz/dataTable/statisMidTable', {
@@ -287,10 +515,29 @@
      this.fuelingStationSpecies = e.target.value
      this.getFuelingStationPieData()
    },
    //获取油品类型饼图数据
    getOilTypePieData() {
      postAction('/jyz/dataTable/statFan', {
        orgCode: this.selectTreeObj.orgCode,
        startTime: this.startTime,
        endTime: this.endTime,
        type: this.oilTypeSpecies,
      }).then((res) => {
        console.log(res)
        this.oilTypePieData = res.result
        this.$nextTick(() => {
          this.$refs.oilTypePieRef.setChart()
        })
      })
    },
    oilTypeSpeciesChange(e) {
      this.oilTypeSpecies = e.target.value
      this.getOilTypePieData()
    },
    //趋势分析类型切换
    trendAnalysisTypeChange(e) {
      let val = e.target.value
      if (val == 0 || val == 2 || val == 3 || val == 5) {
      if (val == 0 || val == 2 || val == 3 || val == 5 || val == 6) {
        this.trendAnalysisChartShowPercent = true
      } else {
        this.trendAnalysisChartShowPercent = false
@@ -340,15 +587,70 @@
        this.contrastObj = res.result
      })
    },
    beforeTimeChange(e, t) {
      this.beforeTimeRange = t
      this.beforeStartTime = t && t.length ? t[0] : ''
      this.beforeEndTime = t && t.length ? t[1] : ''
    },
    afterTimeChange(e, t) {
      this.afterTimeRange = t
      this.afterStartTime = t && t.length ? t[0] : ''
      this.afterEndTime = t && t.length ? t[1] : ''
    },
    setOilFreqDefaultRangeByActivity(activity) {
      if (!activity || !activity.startTime || !activity.endTime) {
        return
      }
      this.afterStartTime = activity.startTime
      this.afterEndTime = activity.endTime
      this.afterTimeRange = [this.afterStartTime, this.afterEndTime]
      let startMoment = moment(activity.startTime)
      let endMoment = moment(activity.endTime)
      let spanSeconds = endMoment.diff(startMoment, 'seconds')
      if (spanSeconds <= 0) {
        return
      }
      this.beforeEndTime = startMoment.format('YYYY-MM-DD HH:mm:ss')
      this.beforeStartTime = startMoment.clone().subtract(spanSeconds, 'seconds').format('YYYY-MM-DD HH:mm:ss')
      this.beforeTimeRange = [this.beforeStartTime, this.beforeEndTime]
    },
    getOilFreqCompareData() {
      if (!this.beforeStartTime || !this.beforeEndTime || !this.afterStartTime || !this.afterEndTime) {
        this.oilFreqCompareData = []
        return
      }
      this.oilFreqCompareLoading = true
      postAction('/jyz/dataTable/statisOilFreqCompare', {
        orgCode: this.selectTreeObj.orgCode,
        beforeStartTime: this.beforeStartTime,
        beforeEndTime: this.beforeEndTime,
        afterStartTime: this.afterStartTime,
        afterEndTime: this.afterEndTime,
      })
        .then((res) => {
          this.oilFreqCompareData = res.result || []
        })
        .finally(() => {
          this.oilFreqCompareLoading = false
        })
    },
    activeTimeChange(e) {
      console.log(e)
      if (e) {
        let item = this.activeOptions.find((el) => el.id == e)
        this.startTime = item.startTime
        this.endTime = item.endTime
        this.setOilFreqDefaultRangeByActivity(item)
      } else {
        this.startTime = ''
        this.endTime = ''
        this.beforeStartTime = ''
        this.beforeEndTime = ''
        this.afterStartTime = ''
        this.afterEndTime = ''
        this.beforeTimeRange = []
        this.afterTimeRange = []
        this.oilFreqCompareData = []
      }
    },
    activeChange() {},
@@ -389,7 +691,9 @@
      this.getVehicleTypeLineData()
      this.getVehicleStationPieData()
      this.getFuelingStationPieData()
      this.getOilTypePieData()
      this.getTrendAnalysis()
      this.getOilFreqCompareData()
    },
    initData() {
      this.getCustomerData()
@@ -398,6 +702,7 @@
      this.getVehicleTypeLineData()
      this.getVehicleStationPieData()
      this.getFuelingStationPieData()
      this.getOilTypePieData()
      this.getTrendAnalysis()
    },
  },
@@ -430,7 +735,7 @@
<style scoped lang="less">
@import '~@assets/less/common.less';
/deep/ .ant-table-content {
  height: 500px;
  height: auto;
  .ant-table-placeholder {
    background: none;
    border: none;
@@ -440,7 +745,29 @@
  background: #fff;
}
.data-reMechanism {
  position: relative;
  isolation: isolate;
  > div {
    position: relative;
    z-index: 2;
  }
  > div:nth-child(2) {
    z-index: 1;
  }
  &.trend-detail-open {
    pointer-events: none;
  }
  .trend-analysis-chart {
    position: relative;
    z-index: 1;
    overflow: hidden;
  }
  .trend-analysis-chart.is-modal-open {
    pointer-events: none;
  }
  .table-operator {
    position: relative;
    z-index: 2;
    margin: 24px 0 0 0;
  }
  .block-title {
@@ -448,6 +775,8 @@
    font-size: 16px;
  }
  .fueling-overview-ct {
    position: relative;
    z-index: 2;
    // margin: 0 12px;
    .fueling-overview-block {
      display: flex;
@@ -463,5 +792,33 @@
      }
    }
  }
  .oil-freq-compare-ct {
    position: relative;
    z-index: 2;
    margin: 8px 12px 24px 12px;
    .oil-freq-compare-operator {
      display: flex;
      align-items: center;
      flex-wrap: wrap;
      gap: 8px 0;
      margin: 12px 0;
    }
    .oil-freq-compare-table {
      /deep/ .ant-table-body {
        min-height: 240px;
      }
      /deep/ .ant-table-pagination.ant-pagination {
        margin: 12px 0 4px 0;
      }
    }
  }
}
</style>
<style lang="less">
.trend-detail-modal-wrap {
  z-index: 5000 !important;
}
.trend-detail-modal-wrap + .ant-modal-mask {
  z-index: 4999 !important;
}
</style>