From 73e0b3791990bd60c06c2c0388aae9f9faf538a6 Mon Sep 17 00:00:00 2001
From: zxl <763096477@qq.com>
Date: 星期三, 25 三月 2026 09:16:50 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/show-demo' into show_demo
---
src/views/dataAnalysis/components/DataReGasStation.vue | 300 ++++++++++++++++++++++
src/views/dataAnalysis/components/CustTypeModal.vue | 180 +++++++++++--
src/components/tools/Logo.vue | 12
src/views/dataAnalysis/components/CustTypeConfig.vue | 32 ++
src/assets/img/sdjt.jpg | 0
src/views/dataAnalysis/CarInfoList.vue | 29 ++
src/views/dataAnalysis/components/DataReLineChart.vue | 202 +++++++++++++++
src/views/dataAnalysis/components/DataRePieChart.vue | 10
8 files changed, 720 insertions(+), 45 deletions(-)
diff --git a/src/assets/img/sdjt.jpg b/src/assets/img/sdjt.jpg
new file mode 100644
index 0000000..598d16f
--- /dev/null
+++ b/src/assets/img/sdjt.jpg
Binary files differ
diff --git a/src/components/tools/Logo.vue b/src/components/tools/Logo.vue
index 43a74f3..48b4230 100644
--- a/src/components/tools/Logo.vue
+++ b/src/components/tools/Logo.vue
@@ -1,15 +1,15 @@
<template>
<router-link :to="{ name: 'dashboard' }">
<div class="flex logo-container flex-center">
- <!-- <img class="logo-img" :src="@/assets/img/logo.png" alt="logo" /> -->
- <img v-if="localInfo.logoPath" class="logo-img" :src="localInfo.logoPath" alt="logo" />
- <img v-else class="logo-img" src="@/assets/img/menuLogo.png" alt="logo" />
+ <img class="logo-img" :src="homeLogo" alt="logo" />
<!-- <h1 class="logo-title" v-if="showTitle">{{ title }}</h1> -->
</div>
</router-link>
</template>
<script>
+import homeLogo from '@/assets/img/sdjt.jpg'
+
export default {
name: 'Logo',
@@ -27,11 +27,8 @@
},
data() {
return {
- localInfo: {},
+ homeLogo,
}
- },
- created() {
- this.localInfo = JSON.parse(localStorage.getItem('localInfo'))
},
}
</script>
@@ -76,4 +73,3 @@
}
}
</style>
-
diff --git a/src/views/dataAnalysis/CarInfoList.vue b/src/views/dataAnalysis/CarInfoList.vue
index 67cc7c5..bfd9e60 100644
--- a/src/views/dataAnalysis/CarInfoList.vue
+++ b/src/views/dataAnalysis/CarInfoList.vue
@@ -44,12 +44,17 @@
/>
</a-form-item>
<a-form-item label="瀹㈡埛绫诲瀷">
- <j-dict-select-tag
+ <a-select
style="width: 180px"
v-model="queryParam.clientType"
placeholder="璇烽�夋嫨"
- dictCode="client_type"
- />
+ allowClear
+ >
+ <a-select-option v-for="item in clientTypeOptions" :key="item.id" :value="item.id">
+ {{ item.clientName }}
+ </a-select-option>
+ </a-select>
+ </a-form-item>
<!-- <a-select style="width: 180px" allowClear v-model="queryParam.clientType" placeholder="璇烽�夋嫨瀹㈡埛绫诲瀷">
<a-select-option :value="1"> 鏅�氬鎴� </a-select-option>
<a-select-option :value="2"> 娼滃湪瀹㈡埛 </a-select-option>
@@ -158,6 +163,7 @@
description: 'CarInfo鍒楄〃',
queryParam: {},
tagList: [], //鎵�鏈夋爣绛鹃泦鍚�
+ clientTypeOptions: [], //瀹㈡埛绫诲瀷鍒楄〃
// 琛ㄥご
columns: [
{
@@ -244,6 +250,14 @@
},
methods: {
+ // 鑾峰彇瀹㈡埛绫诲瀷鍒楄〃
+ getClientTypeOptions() {
+ getAction('/jyz/client/listClientType').then((res) => {
+ if (res.code === 200) {
+ this.clientTypeOptions = res.result
+ }
+ })
+ },
delSlectTag(item) {
console.log(item)
let index = this.selectTagList.findIndex((el) => el == item)
@@ -321,10 +335,19 @@
this.queryParam.orgCode = node.node.dataRef.orgCode
this.loadData()
},
+ // 鑾峰彇瀹㈡埛绫诲瀷鍒楄〃
+ getClientTypeOptions() {
+ getAction('/jyz/client/listClientType').then((res) => {
+ if (res.code === 200) {
+ this.clientTypeOptions = res.result
+ }
+ })
+ },
},
created() {
this.getTagInfo(true)
+ this.getClientTypeOptions()
},
}
</script>
diff --git a/src/views/dataAnalysis/components/CustTypeConfig.vue b/src/views/dataAnalysis/components/CustTypeConfig.vue
index ddca895..3b12660 100644
--- a/src/views/dataAnalysis/components/CustTypeConfig.vue
+++ b/src/views/dataAnalysis/components/CustTypeConfig.vue
@@ -46,6 +46,9 @@
<script>
import CustTypeModal from './CustTypeModal'
import { JeecgListMixin } from '@tievd/cube-block/lib/mixins/JeecgListMixin'
+import { UI_CACHE_DB_DICT_DATA } from '@tievd/cube-block/lib/store/mutation-types'
+import { deleteAction, getAction } from '@tievd/cube-block/lib/api/manage'
+import Vue from 'vue'
export default {
name: 'ActivityList',
@@ -123,6 +126,35 @@
},
methods: {
+ modalFormOk() {
+ this.loadData()
+ this.refreshDictCache()
+ },
+ refreshDictCache() {
+ getAction('/sys/dict/queryAllDictItems').then((res) => {
+ if (res.success) {
+ Vue.ls.remove(UI_CACHE_DB_DICT_DATA)
+ Vue.ls.set(UI_CACHE_DB_DICT_DATA, res.result, 7 * 24 * 60 * 60 * 1000)
+ }
+ })
+ },
+ handleDelete(id) {
+ // 鍒犻櫎鍓嶆竻闄ゅ墠绔瓧鍏哥紦瀛�
+ // 鍒犻櫎鍚庡埛鏂伴〉闈互鏇存柊瀛楀吀缂撳瓨
+ deleteAction(this.url.delete, { id: id })
+ .then((res) => {
+ if (res.success) {
+ this.$message.success(res.message)
+ this.loadData()
+ this.refreshDictCache()
+ } else {
+ this.$message.warning(res.message)
+ }
+ })
+ .finally(() => {
+ this.loading = false
+ })
+ },
transformConfigText(obj) {
var text = ''
if (obj.timeStr == '1,YEARS') {
diff --git a/src/views/dataAnalysis/components/CustTypeModal.vue b/src/views/dataAnalysis/components/CustTypeModal.vue
index 6f675b4..169830c 100644
--- a/src/views/dataAnalysis/components/CustTypeModal.vue
+++ b/src/views/dataAnalysis/components/CustTypeModal.vue
@@ -17,6 +17,9 @@
v-model="clientConfigsList.clientName"
></a-input>
</a-form-item>
+ <div v-if="!clientConfigsList.clientConfigs || clientConfigsList.clientConfigs.length === 0" style="text-align: center">
+ <a-button type="primary" @click="addConditions"> 娣诲姞瑙勫垯 </a-button>
+ </div>
<div v-for="(subItem, subIndex) in clientConfigsList.clientConfigs" :key="subIndex">
<div style="display: flex">
<div>鏉′欢{{ subIndex + 1 }}锛�</div>
@@ -44,34 +47,100 @@
<a-select-option value="1,YEARS"> 杩�1骞� </a-select-option>
</a-select>
</a-form-item>
- <a-form-item :labelCol="labelCol" :wrapperCol="wrapperCol" label="鍔犳补棰戞">
+ <!-- 瑙勫垯绫诲瀷閫夋嫨锛氬姞娌归娆� OR 鍔犳补瓒嬪娍 -->
+ <a-form-item :labelCol="labelCol" :wrapperCol="wrapperCol" label="瑙勫垯绫诲瀷">
<a-select
- :disabled="subItem.timeStr == '7,DAYS' || subItem.timeStr == '30,DAYS'"
style="width: 300px"
- v-model="subItem.countType"
+ v-model="subItem.ruleType"
placeholder="璇烽�夋嫨"
+ @change="ruleTypeChange($event, subIndex)"
>
- <a-select-option :value="1"> 绱 </a-select-option>
- <a-select-option :value="2"> 姣忔湀 </a-select-option>
+ <a-select-option :value="1"> 鍔犳补棰戞 </a-select-option>
+ <a-select-option :value="2"> 鍔犳补瓒嬪娍 </a-select-option>
</a-select>
- <div style="display: flex">
- <a-select style="width: 150px" v-model="subItem.countRef" placeholder="璇烽�夋嫨">
- <a-select-option :value="1"> 澶т簬 </a-select-option>
- <a-select-option :value="0"> 绛変簬 </a-select-option>
- <a-select-option :value="-1"> 灏忎簬 </a-select-option>
+ </a-form-item>
+ <!-- 鍔犳补棰戞閰嶇疆锛坮uleType=1鏃舵樉绀猴級 -->
+ <div v-show="subItem.ruleType == 1">
+ <a-form-item :labelCol="labelCol" :wrapperCol="wrapperCol" label="鍔犳补棰戞">
+ <a-select
+ :disabled="subItem.timeStr == '7,DAYS' || subItem.timeStr == '30,DAYS'"
+ style="width: 300px"
+ v-model="subItem.countType"
+ placeholder="璇烽�夋嫨"
+ >
+ <a-select-option :value="1"> 绱 </a-select-option>
+ <a-select-option :value="2"> 姣忔湀 </a-select-option>
</a-select>
+ <div style="display: flex">
+ <a-select style="width: 150px" v-model="subItem.countRef" placeholder="璇烽�夋嫨">
+ <a-select-option :value="1"> 澶т簬 </a-select-option>
+ <a-select-option :value="0"> 绛変簬 </a-select-option>
+ <a-select-option :value="-1"> 灏忎簬 </a-select-option>
+ </a-select>
+ <a-input
+ style="width: 150px"
+ placeholder="璇疯緭鍏ユ鏁�"
+ onkeyup="if(this.value.length==1){this.value=this.value.replace(/[^1-9]/g,'')}else{this.value=this.value.replace(/\D/g,'')}"
+ onafterpaste="if(this.value.length==1){this.value=this.value.replace(/[^1-9]/g,'0')}else{this.value=this.value.replace(/\D/g,'')}"
+ v-model="subItem.countNum"
+ ></a-input>
+ </div>
+ </a-form-item>
+ </div>
+ <!-- 鍔犳补瓒嬪娍閰嶇疆锛坮uleType=2鏃舵樉绀猴級 -->
+ <div v-show="subItem.ruleType == 2">
+ <a-form-item :labelCol="labelCol" :wrapperCol="wrapperCol" label="鍔犳补瓒嬪娍">
+ <a-select
+ style="width: 300px"
+ v-model="subItem.countTrend"
+ placeholder="璇烽�夋嫨"
+ >
+ <a-select-option :value="1"> 绋冲畾 </a-select-option>
+ <a-select-option :value="2"> 鍑忓皯 </a-select-option>
+ </a-select>
+ <div v-if="subItem.countTrend == 1" style="color: #999; font-size: 12px; margin-top: 5px;">
+ 绋冲畾锛氬巻鍙叉湀鍔犳补娆℃暟鈮ユ鏁� 涓� 杩戞湡鏈堝姞娌规鏁扳墺娆℃暟
+ </div>
+ <div v-if="subItem.countTrend == 2" style="color: #999; font-size: 12px; margin-top: 5px;">
+ 鍑忓皯锛氬巻鍙叉湀鍔犳补娆℃暟鈮ユ鏁� 浣� 杩戞湡鏈堝姞娌规鏁�<娆℃暟
+ </div>
+ </a-form-item>
+ <a-form-item :labelCol="labelCol" :wrapperCol="wrapperCol" label="鍘嗗彶鏈堟暟">
+ <a-select
+ style="width: 140px"
+ v-model="subItem.historyMonths"
+ placeholder="鍘嗗彶鏈堟暟"
+ >
+ <a-select-option :value="3"> 3涓湀 </a-select-option>
+ <a-select-option :value="6"> 6涓湀 </a-select-option>
+ <a-select-option :value="9"> 9涓湀 </a-select-option>
+ <a-select-option :value="12"> 12涓湀 </a-select-option>
+ </a-select>
+ </a-form-item>
+ <a-form-item :labelCol="labelCol" :wrapperCol="wrapperCol" label="杩戞湡鏈堟暟">
+ <a-select
+ style="width: 140px"
+ v-model="subItem.recentMonths"
+ placeholder="杩戞湡鏈堟暟"
+ >
+ <a-select-option :value="1"> 1涓湀 </a-select-option>
+ <a-select-option :value="2"> 2涓湀 </a-select-option>
+ <a-select-option :value="3"> 3涓湀 </a-select-option>
+ </a-select>
+ </a-form-item>
+ <a-form-item :labelCol="labelCol" :wrapperCol="wrapperCol" label="鍥哄畾鍔犳补娆℃暟">
<a-input
style="width: 150px"
- placeholder="璇疯緭鍏ユ鏁�"
+ placeholder="姣忔湀鍥哄畾娆℃暟"
onkeyup="if(this.value.length==1){this.value=this.value.replace(/[^1-9]/g,'')}else{this.value=this.value.replace(/\D/g,'')}"
onafterpaste="if(this.value.length==1){this.value=this.value.replace(/[^1-9]/g,'0')}else{this.value=this.value.replace(/\D/g,'')}"
v-model="subItem.countNum"
></a-input>
- </div>
- </a-form-item>
- </div>
- <div style="text-align: center">
- <a-button type="primary" @click="addConditions"> 澧炲姞鏉′欢 </a-button>
+ </a-form-item>
+ </div>
+ <div style="text-align: center" v-if="subIndex === clientConfigsList.clientConfigs.length - 1">
+ <a-button type="primary" @click="addConditions"> 澧炲姞鏉′欢 </a-button>
+ </div>
</div>
</div>
</a-spin>
@@ -119,6 +188,21 @@
methods: {
moment,
+ buildCondition(condition = {}) {
+ return Object.assign(
+ {
+ ruleType: 1,
+ timeStr: '3,MONTHS',
+ countType: 2,
+ countRef: 1,
+ countNum: 3,
+ countTrend: null,
+ historyMonths: null,
+ recentMonths: null,
+ },
+ condition
+ )
+ },
//鍒犻櫎鏉′欢
delConditions(index) {
console.log(index)
@@ -129,10 +213,46 @@
this.clientConfigsList.clientConfigs[index].countType = 1
}
},
+ trendChange(e, index) {
+ // 閫夋嫨瓒嬪娍鏃讹紝璁剧疆榛樿鍊�
+ if (e > 0) {
+ this.clientConfigsList.clientConfigs[index].historyMonths = 3
+ this.clientConfigsList.clientConfigs[index].recentMonths = 3
+ } else {
+ // 娓呴櫎瓒嬪娍閰嶇疆
+ this.clientConfigsList.clientConfigs[index].historyMonths = null
+ this.clientConfigsList.clientConfigs[index].recentMonths = null
+ }
+ },
+ ruleTypeChange(e, index) {
+ let target = this.clientConfigsList.clientConfigs[index]
+ // 鍒囨崲瑙勫垯绫诲瀷鏃讹紝娓呯┖瀵瑰簲鐨勯厤缃�
+ if (e == 1) {
+ // 鍔犳补棰戞锛氭竻闄よ秼鍔块厤缃�
+ Object.assign(target, {
+ ruleType: 1,
+ countTrend: null,
+ historyMonths: null,
+ recentMonths: null,
+ countType: target.countType || 2,
+ countRef: target.countRef || 1,
+ })
+ } else if (e == 2) {
+ // 鍔犳补瓒嬪娍锛氭竻闄ら娆¢厤缃紝璁剧疆榛樿鍊�
+ Object.assign(target, {
+ ruleType: 2,
+ countType: 2,
+ countRef: 1,
+ countTrend: target.countTrend || 1,
+ historyMonths: target.historyMonths || 3,
+ recentMonths: target.recentMonths || 3,
+ })
+ }
+ },
//鏂板鏉′欢
addConditions(index) {
console.log(index)
- this.clientConfigsList.clientConfigs.push({})
+ this.clientConfigsList.clientConfigs.push(this.buildCondition())
},
disabledDate(current) {
// Can not select days before today and today
@@ -151,7 +271,7 @@
add() {
this.edit({
clientName: '',
- clientConfigs: [{}],
+ clientConfigs: [this.buildCondition()],
})
},
edit(record) {
@@ -163,7 +283,11 @@
// }
this.visible = true
this.model = Object.assign({}, record)
- this.clientConfigsList = record
+ this.clientConfigsList = Object.assign({}, record, {
+ clientConfigs: (record.clientConfigs || []).length
+ ? record.clientConfigs.map((item) => this.buildCondition(item))
+ : [],
+ })
},
close() {
this.$emit('close')
@@ -183,16 +307,20 @@
if (JSON.stringify(el) == '{}') {
isEmpty = true
}
- for (let k in el) {
- if (el[k] == '' || el[k].length == '0') {
+ // 鏍规嵁瑙勫垯绫诲瀷鏍¢獙
+ if (el.ruleType == 1) {
+ // 鍔犳补棰戞锛氭鏌ユ椂闂磋寖鍥淬�佹鏁扮被鍨嬨�佸叧绯汇�佹鏁�
+ if (!el.timeStr || !el.countRef || !el.countType || !el.countNum) {
isEmpty = true
}
- }
- if (!el.timeStr || !el.countRef || !el.countType || !el.countNum) {
- isEmpty = true
- if (el.countRef == 0 || el.countNum == 0) {
- isEmpty = false
+ } else if (el.ruleType == 2) {
+ // 鍔犳补瓒嬪娍锛氭鏌ユ椂闂磋寖鍥淬�佽秼鍔裤�佸巻鍙叉湀鏁般�佽繎鏈熸湀鏁般�佹鏁�
+ if (!el.timeStr || !el.countTrend || !el.historyMonths || !el.recentMonths || !el.countNum) {
+ isEmpty = true
}
+ } else {
+ // 鏈�夋嫨瑙勫垯绫诲瀷
+ isEmpty = true
}
})
if (isEmpty) {
diff --git a/src/views/dataAnalysis/components/DataReGasStation.vue b/src/views/dataAnalysis/components/DataReGasStation.vue
index bb3ed28..a76e57c 100644
--- a/src/views/dataAnalysis/components/DataReGasStation.vue
+++ b/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">
@@ -12,7 +12,7 @@
</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 +31,8 @@
:chartData="trendAnalysisData"
style="width: 100%"
:showpercent="trendAnalysisChartShowPercent"
+ :enablePointClick="true"
+ @chart-click="handleTrendChartClick"
></DataReLineChart>
</div>
<div id="trendAnalysisChartID"></div>
@@ -122,6 +124,41 @@
</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>
<div style="display: flex">
@@ -175,6 +212,33 @@
: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 +247,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: {
@@ -228,10 +293,131 @@
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' },
+ ]
+ }
+ 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', {
@@ -340,15 +526,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() {},
@@ -390,6 +631,7 @@
this.getVehicleStationPieData()
this.getFuelingStationPieData()
this.getTrendAnalysis()
+ this.getOilFreqCompareData()
},
initData() {
this.getCustomerData()
@@ -430,7 +672,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 +682,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 +712,8 @@
font-size: 16px;
}
.fueling-overview-ct {
+ position: relative;
+ z-index: 2;
// margin: 0 12px;
.fueling-overview-block {
display: flex;
@@ -463,5 +729,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>
diff --git a/src/views/dataAnalysis/components/DataReLineChart.vue b/src/views/dataAnalysis/components/DataReLineChart.vue
index 782f712..857fd8d 100644
--- a/src/views/dataAnalysis/components/DataReLineChart.vue
+++ b/src/views/dataAnalysis/components/DataReLineChart.vue
@@ -22,13 +22,204 @@
type: Boolean,
default: false,
},
+ enablePointClick: {
+ type: Boolean,
+ default: false,
+ },
},
data() {
return {
chartEntity: null,
+ zrClickHandler: null,
+ zrMoveHandler: null,
+ zrMouseOutHandler: null,
+ lastHoverIndex: -1,
+ lastEmitName: '',
+ lastEmitAt: 0,
+ lastLegendToggleAt: 0,
}
},
methods: {
+ getOffsetPoint(event) {
+ if (!event) {
+ return null
+ }
+ if (event.offsetX !== undefined && event.offsetY !== undefined) {
+ return [event.offsetX, event.offsetY]
+ }
+ if (event.event && event.event.offsetX !== undefined && event.event.offsetY !== undefined) {
+ return [event.event.offsetX, event.event.offsetY]
+ }
+ return null
+ },
+ isPointInGrid(point) {
+ if (!this.chartEntity || !this.chartEntity.containPixel || !point) {
+ return false
+ }
+ return this.chartEntity.containPixel({ gridIndex: 0 }, point)
+ },
+ getXData() {
+ return this.chartData && this.chartData.xData ? this.chartData.xData : []
+ },
+ resolveNearestIndexByOffsetX(offsetX) {
+ let xData = this.getXData()
+ if (!this.chartEntity || !this.chartEntity.convertToPixel || !xData.length) {
+ return -1
+ }
+ let nearestIndex = -1
+ let minDistance = Number.MAX_VALUE
+ for (let i = 0; i < xData.length; i++) {
+ let xPixel = this.chartEntity.convertToPixel({ xAxisIndex: 0 }, xData[i])
+ if (Array.isArray(xPixel)) {
+ xPixel = xPixel[0]
+ }
+ if (xPixel === undefined || xPixel === null || Number.isNaN(Number(xPixel))) {
+ continue
+ }
+ let distance = Math.abs(Number(offsetX) - Number(xPixel))
+ if (distance < minDistance) {
+ minDistance = distance
+ nearestIndex = i
+ }
+ }
+ if (nearestIndex === -1) {
+ return -1
+ }
+ return nearestIndex
+ },
+ resolveClickIndex(event, params) {
+ let xData = this.getXData()
+ if (!xData.length) {
+ return -1
+ }
+ let point = this.getOffsetPoint(event)
+ if (!this.isPointInGrid(point)) {
+ return -1
+ }
+ if (params && typeof params.dataIndex === 'number' && xData[params.dataIndex] !== undefined) {
+ return params.dataIndex
+ }
+ if (params && params.name) {
+ let nameIndex = xData.findIndex((item) => item === params.name)
+ if (nameIndex > -1) {
+ return nameIndex
+ }
+ }
+ if (this.chartEntity && this.chartEntity.convertFromPixel && event) {
+ let xAxisValue = this.chartEntity.convertFromPixel({ xAxisIndex: 0 }, [event.offsetX, event.offsetY])
+ if (xAxisValue !== undefined && xAxisValue !== null && !Number.isNaN(Number(xAxisValue))) {
+ let xIndex = Math.round(Number(xAxisValue))
+ if (xIndex >= 0 && xIndex < xData.length) {
+ return xIndex
+ }
+ }
+ }
+ if (event && event.offsetX !== undefined && event.offsetX !== null) {
+ return this.resolveNearestIndexByOffsetX(event.offsetX)
+ }
+ return -1
+ },
+ emitChartClickByIndex(index, seriesName) {
+ let xData = this.getXData()
+ if (index < 0 || index >= xData.length) {
+ return
+ }
+ let clickName = xData[index]
+ let now = Date.now()
+ if (this.lastEmitName === clickName && now - this.lastEmitAt < 120) {
+ return
+ }
+ this.lastEmitName = clickName
+ this.lastEmitAt = now
+ this.$emit('chart-click', {
+ name: clickName,
+ seriesName: seriesName || null,
+ })
+ },
+ hideTooltip() {
+ if (!this.chartEntity) {
+ return
+ }
+ this.chartEntity.dispatchAction({
+ type: 'hideTip',
+ })
+ },
+ bindChartClick() {
+ if (!this.chartEntity) {
+ return
+ }
+ this.chartEntity.off('click')
+ if (this.chartEntity.getZr) {
+ let zr = this.chartEntity.getZr()
+ if (this.zrClickHandler) {
+ zr.off('click', this.zrClickHandler)
+ }
+ if (this.zrMoveHandler) {
+ zr.off('mousemove', this.zrMoveHandler)
+ }
+ if (this.zrMouseOutHandler) {
+ zr.off('globalout', this.zrMouseOutHandler)
+ }
+ }
+ if (!this.enablePointClick) {
+ let chartDom = document.getElementById(this.domId)
+ if (chartDom) {
+ chartDom.style.cursor = 'default'
+ }
+ return
+ }
+ let chartDom = document.getElementById(this.domId)
+ if (chartDom) {
+ chartDom.style.cursor = 'pointer'
+ }
+ this.chartEntity.on('legendselectchanged', () => {
+ this.lastLegendToggleAt = Date.now()
+ })
+ this.chartEntity.on('click', (params) => {
+ if (params && params.componentType === 'legend') {
+ return
+ }
+ if (Date.now() - this.lastLegendToggleAt < 180) {
+ return
+ }
+ let index = this.resolveClickIndex(params && params.event ? params.event : null, params)
+ this.emitChartClickByIndex(index, params ? params.seriesName : null)
+ })
+ this.zrMoveHandler = (event) => {
+ let xData = this.getXData()
+ if (!xData.length) {
+ return
+ }
+ let xIndex = this.resolveClickIndex(event, null)
+ if (xIndex < 0 || xIndex >= xData.length) {
+ return
+ }
+ if (this.lastHoverIndex === xIndex) {
+ return
+ }
+ this.lastHoverIndex = xIndex
+ this.chartEntity.dispatchAction({
+ type: 'showTip',
+ seriesIndex: 0,
+ dataIndex: xIndex,
+ })
+ }
+ this.zrMouseOutHandler = () => {
+ this.lastHoverIndex = -1
+ this.hideTooltip()
+ }
+ this.zrClickHandler = (event) => {
+ if (Date.now() - this.lastLegendToggleAt < 180) {
+ return
+ }
+ let index = this.resolveClickIndex(event, null)
+ this.emitChartClickByIndex(index, null)
+ }
+ let zr = this.chartEntity.getZr()
+ zr.on('mousemove', this.zrMoveHandler)
+ zr.on('globalout', this.zrMouseOutHandler)
+ zr.on('click', this.zrClickHandler)
+ },
setChart() {
if (!this.chartEntity) {
let chartDom = document.getElementById(this.domId)
@@ -38,6 +229,8 @@
var option = {
tooltip: {
trigger: 'axis',
+ confine: true,
+ extraCssText: 'pointer-events:none;',
axisPointer: {
// 鍧愭爣杞存寚绀哄櫒锛屽潗鏍囪酱瑙﹀彂鏈夋晥
type: 'line', // 榛樿涓虹洿绾匡紝鍙�変负锛�'line' | 'shadow'
@@ -216,6 +409,7 @@
],
}
option && this.chartEntity.setOption(option, true)
+ this.bindChartClick()
},
setPieUpChart() {
if (!this.chartEntity) {
@@ -241,6 +435,8 @@
var option = {
tooltip: {
trigger: 'axis',
+ confine: true,
+ extraCssText: 'pointer-events:none;',
axisPointer: {
// 鍧愭爣杞存寚绀哄櫒锛屽潗鏍囪酱瑙﹀彂鏈夋晥
type: 'line', // 榛樿涓虹洿绾匡紝鍙�変负锛�'line' | 'shadow'
@@ -299,6 +495,7 @@
series: [...data],
}
option && this.chartEntity.setOption(option, true)
+ this.bindChartClick()
},
setOnlyLineChart() {
if (!this.chartEntity) {
@@ -309,6 +506,8 @@
var option = {
tooltip: {
trigger: 'axis',
+ confine: true,
+ extraCssText: 'pointer-events:none;',
axisPointer: {
// 鍧愭爣杞存寚绀哄櫒锛屽潗鏍囪酱瑙﹀彂鏈夋晥
type: 'line', // 榛樿涓虹洿绾匡紝鍙�変负锛�'line' | 'shadow'
@@ -442,6 +641,7 @@
],
}
option && this.chartEntity.setOption(option, true)
+ this.bindChartClick()
},
},
}
@@ -449,5 +649,7 @@
<style lang="less" scoped>
.line-chart {
height: 20vh;
+ position: relative;
+ overflow: hidden;
}
</style>
diff --git a/src/views/dataAnalysis/components/DataRePieChart.vue b/src/views/dataAnalysis/components/DataRePieChart.vue
index b6db6bf..2adee7e 100644
--- a/src/views/dataAnalysis/components/DataRePieChart.vue
+++ b/src/views/dataAnalysis/components/DataRePieChart.vue
@@ -65,10 +65,10 @@
legend: {
orient: 'vertical',
icon: 'circle',
- right: '0',
- top: '10%',
+ right: '2%',
+ top: 'middle',
itemWidth: 14,
- itemGap: 20,
+ itemGap: 12,
textStyle: {
rich: {
a: {
@@ -106,9 +106,9 @@
emphasis: {
scale: false,
},
- center: ['40%', '50%'],
+ center: ['28%', '52%'],
top: 'center',
- right: '60%',
+ right: '62%',
label: {
show: true,
position: 'inside',
--
Gitblit v1.8.0