Quellcode durchsuchen

运营分析调整

yangzj vor 2 Jahren
Ursprung
Commit
46f5f45268
44 geänderte Dateien mit 4308 neuen und 575 gelöschten Zeilen
  1. 5 1
      common/apiurl.js
  2. 8 0
      common/http.api.js
  3. 203 185
      pages.json
  4. 0 0
      pages/dataOverview/operationalAnalysis copy/components/arrearsAnalysis.vue
  5. 0 0
      pages/dataOverview/operationalAnalysis copy/components/incomeAnalysis.vue
  6. 0 0
      pages/dataOverview/operationalAnalysis copy/components/paymentMethod.vue
  7. 0 0
      pages/dataOverview/operationalAnalysis copy/components/revenueAnalysis.vue
  8. 0 0
      pages/dataOverview/operationalAnalysis copy/components/revenueRanking.vue
  9. 0 0
      pages/dataOverview/operationalAnalysis copy/components/sectionAnalysis.vue
  10. 0 0
      pages/dataOverview/operationalAnalysis copy/components/sourceOfPayment.vue
  11. 0 0
      pages/dataOverview/operationalAnalysis copy/components/tollCollectorPerformance.vue
  12. 0 0
      pages/dataOverview/operationalAnalysis copy/components/trafficFlow.vue
  13. 52 0
      pages/dataOverview/operationalAnalysis copy/operationalAnalysis.scss
  14. 349 0
      pages/dataOverview/operationalAnalysis copy/operationalAnalysis.vue
  15. 50 51
      pages/dataOverview/operationalAnalysis/operationalAnalysis.scss
  16. 175 337
      pages/dataOverview/operationalAnalysis/operationalAnalysis.vue
  17. 122 0
      pages/operationalAnalysis/parkModel/components/arrearsAnalysis.vue
  18. 183 0
      pages/operationalAnalysis/parkModel/components/incomeAnalysis.vue
  19. 219 0
      pages/operationalAnalysis/parkModel/components/parkingLotAnalysis.vue
  20. 100 0
      pages/operationalAnalysis/parkModel/components/paymentMethod.vue
  21. 143 0
      pages/operationalAnalysis/parkModel/components/revenueAnalysis.vue
  22. 76 0
      pages/operationalAnalysis/parkModel/components/revenueRanking.vue
  23. 180 0
      pages/operationalAnalysis/parkModel/components/sectionAnalysis.vue
  24. 180 0
      pages/operationalAnalysis/parkModel/components/sourceOfPayment.vue
  25. 149 0
      pages/operationalAnalysis/parkModel/components/tollCollectorPerformance.vue
  26. 152 0
      pages/operationalAnalysis/parkModel/components/trafficFlow.vue
  27. 272 0
      pages/operationalAnalysis/parkModel/index.vue
  28. 120 0
      pages/operationalAnalysis/roadModel/components/arrearsAnalysis.vue
  29. 182 0
      pages/operationalAnalysis/roadModel/components/incomeAnalysis.vue
  30. 96 0
      pages/operationalAnalysis/roadModel/components/paymentMethod.vue
  31. 140 0
      pages/operationalAnalysis/roadModel/components/revenueAnalysis.vue
  32. 76 0
      pages/operationalAnalysis/roadModel/components/revenueRanking.vue
  33. 180 0
      pages/operationalAnalysis/roadModel/components/sectionAnalysis.vue
  34. 180 0
      pages/operationalAnalysis/roadModel/components/sourceOfPayment.vue
  35. 149 0
      pages/operationalAnalysis/roadModel/components/tollCollectorPerformance.vue
  36. 152 0
      pages/operationalAnalysis/roadModel/components/trafficFlow.vue
  37. 272 0
      pages/operationalAnalysis/roadModel/index.vue
  38. 35 0
      pages/operationalAnalysis/styles/analysis.scss
  39. 1 1
      pages/patrolManagement/deviceAbnormalRecords/deviceAbnormalRecords.vue
  40. 23 0
      static/icons/operationalAnalysisIcons/arrearage-analysis-icon.svg
  41. 21 0
      static/icons/operationalAnalysisIcons/payment-method-icon.svg
  42. 21 0
      static/icons/operationalAnalysisIcons/revenue-analysis-icon.svg
  43. 21 0
      static/icons/operationalAnalysisIcons/section-analysis-icon.svg
  44. 21 0
      static/icons/operationalAnalysisIcons/shouru-analysis-icon.svg

+ 5 - 1
common/apiurl.js

@@ -49,7 +49,11 @@ export const apiurl = {
 		// 获取支付来源分析接口
 		getPaySourceDataUrl: '/admin/overview/payplat',
 		// 获取支付来源分析(停车场)接口
-		getParkingPaySourceDataUrl: '/admin/overview/parkpayplat'
+		getParkingPaySourceDataUrl: '/admin/overview/parkpayplat',
+		// 获取停车场分析营收金额接口
+		getParkingLotRevenueAmountUrl: '/admin/reportparking/amt',
+		// 获取停车场分车流量统计接口
+		getParkingLotTrafficVolumeUrl: '/admin/reportparking/vehicle'
 	},
 	// 统计报表模块接口
 	statisticalReport: {

+ 8 - 0
common/http.api.js

@@ -101,6 +101,14 @@ const install = (Vue, vm) => {
 		getParkingPaySourceDataApi: (params = {}) => vm.$u.http.get(apiurl.operationalAnalysis.getParkingPaySourceDataUrl, {
 			params
 		}),
+		// 获取停车场分析营收金额
+		getParkingLotRevenueAmountApi: (params = {}) => vm.$u.http.get(apiurl.operationalAnalysis.getParkingLotRevenueAmountUrl, {
+			params
+		}),
+		// 获取停车场分车流量统计
+		getParkingLotTrafficVolumeApi: (params = {}) => vm.$u.http.get(apiurl.operationalAnalysis.getParkingLotTrafficVolumeUrl, {
+			params
+		}),
 	};
 	// 统计报表模块
 	let statisticalReportApi = {

+ 203 - 185
pages.json

@@ -1,187 +1,205 @@
 {
-	"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
-		{
-			"path": "pages/index/index",
-			"style": {
-				"navigationBarTitleText": "首页",
-				"navigationStyle": "custom"
-			}
-		}, {
-			"path": "pages/login/login",
-			"style": {
-				"navigationBarTitleText": "登录",
-				"enablePullDownRefresh": false,
-				"navigationStyle": "custom"
-			}
-
-		}, {
-			"path": "pages/dataOverview/todayOverview/todayOverview",
-			"style": {
-				"navigationBarTitleText": "今日概况",
-				"enablePullDownRefresh": false,
-				"navigationBarBackgroundColor": "#1767F2",
-				"navigationBarTextStyle": "white"
-			}
-
-		}, {
-			"path": "pages/dataOverview/operationalAnalysis/operationalAnalysis",
-			"style": {
-				"navigationBarTitleText": "运营分析",
-				"enablePullDownRefresh": false,
-				"navigationBarBackgroundColor": "#1767F2",
-				"navigationBarTextStyle": "white"
-			}
-
-		}, {
-			"path": "pages/dataOverview/statisticalReport/statisticalReport",
-			"style": {
-				"navigationBarTitleText": "统计报表",
-				"enablePullDownRefresh": false,
-				"navigationBarBackgroundColor": "#1767F2",
-				"navigationBarTextStyle": "white"
-			}
-
-		}, {
-			"path": "pages/orderManagement/parkingRecord/parkingRecord",
-			"style": {
-				"navigationBarTitleText": "停车记录",
-				"enablePullDownRefresh": false,
-				"navigationBarBackgroundColor": "#1767F2",
-				"navigationBarTextStyle": "white"
-			}
-
-		}, {
-			"path": "pages/orderManagement/arrearageRecord/arrearageRecord",
-			"style": {
-				"navigationBarTitleText": "欠费记录",
-				"enablePullDownRefresh": false,
-				"navigationBarBackgroundColor": "#1767F2",
-				"navigationBarTextStyle": "white"
-			}
-
-		}, {
-			"path": "pages/orderManagement/collectionRecord/collectionRecord",
-			"style": {
-				"navigationBarTitleText": "收款记录",
-				"enablePullDownRefresh": false,
-				"navigationBarBackgroundColor": "#1767F2",
-				"navigationBarTextStyle": "white"
-			}
-
-		}, {
-			"path": "pages/orderManagement/feeEvasionRecord/feeEvasionRecord",
-			"style": {
-				"navigationBarTitleText": "逃费记录",
-				"enablePullDownRefresh": false,
-				"navigationBarBackgroundColor": "#1767F2",
-				"navigationBarTextStyle": "white"
-			}
-
-		}, {
-			"path": "pages/orderManagement/voidRecord/voidRecord",
-			"style": {
-				"navigationBarTitleText": "作废记录",
-				"enablePullDownRefresh": false,
-				"navigationBarBackgroundColor": "#1767F2",
-				"navigationBarTextStyle": "white"
-			}
-
-		}, {
-			"path": "pages/orderManagement/recoveryRecord/recoveryRecord",
-			"style": {
-				"navigationBarTitleText": "追缴记录",
-				"enablePullDownRefresh": false,
-				"navigationBarBackgroundColor": "#1767F2",
-				"navigationBarTextStyle": "white"
-			}
-
-		}, {
-			"path": "pages/patrolManagement/patrolRecord/patrolRecord",
-			"style": {
-				"navigationBarTitleText": "巡检记录",
-				"enablePullDownRefresh": false,
-				"navigationBarBackgroundColor": "#1767F2",
-				"navigationBarTextStyle": "white"
-			}
-
-		}, {
-			"path": "pages/patrolManagement/deviceAbnormalRecords/deviceAbnormalRecords",
-			"style": {
-				"navigationBarTitleText": "设备异常记录",
-				"enablePullDownRefresh": true,
-				"navigationBarBackgroundColor": "#1767F2",
-				"navigationBarTextStyle": "white"
-			}
-
-		}, {
-			"path": "pages/patrolManagement/deviceAbnormalRecords/recordsDetails/recordsDetails",
-			"style": {
-				"navigationBarTitleText": "设备异常记录详情",
-				"enablePullDownRefresh": false,
-				"navigationBarBackgroundColor": "#1767F2",
-				"navigationBarTextStyle": "white"
-			}
-
-		}, {
-			"path": "pages/collectorManagement/performanceRanking/performanceRanking",
-			"style": {
-				"navigationBarTitleText": "业绩排名",
-				"enablePullDownRefresh": false,
-				"navigationBarBackgroundColor": "#1767F2",
-				"navigationBarTextStyle": "white"
-			}
-
-		}, {
-			"path": "pages/collectorManagement/performanceAnalysis/performanceAnalysis",
-			"style": {
-				"navigationBarTitleText": "业绩分析",
-				"enablePullDownRefresh": false,
-				"navigationBarBackgroundColor": "#1767F2",
-				"navigationBarTextStyle": "white"
-			}
-
-		}, {
-			"path": "pages/collectorManagement/assessmentRanking/assessmentRanking",
-			"style": {
-				"navigationBarTitleText": "考核排名",
-				"enablePullDownRefresh": false,
-				"navigationBarBackgroundColor": "#1767F2",
-				"navigationBarTextStyle": "white"
-			}
-
-		}, {
-			"path": "pages/collectorManagement/assessmentAnalysis/assessmentAnalysis",
-			"style": {
-				"navigationBarTitleText": "考核分析",
-				"enablePullDownRefresh": false,
-				"navigationBarBackgroundColor": "#1767F2",
-				"navigationBarTextStyle": "white"
-			}
-
-		}, {
-			"path": "pages/collectorManagement/shiftScheduling/shiftScheduling",
-			"style": {
-				"navigationBarTitleText": "排班情况",
-				"enablePullDownRefresh": false,
-				"navigationBarBackgroundColor": "#1767F2",
-				"navigationBarTextStyle": "white"
-			}
-
-		}, {
-			"path": "pages/patrolManagement/emergencyDisposalRecords/emergencyDisposalRecords",
-			"style": {
-				"navigationBarTitleText": "应急处置记录",
-				"enablePullDownRefresh": false,
-				"navigationBarBackgroundColor": "#1767F2",
-				"navigationBarTextStyle": "white"
-			}
-
-		}
-	],
-	"globalStyle": {
-		"navigationBarTextStyle": "black",
-		"navigationBarTitleText": "智慧停车运营端",
-		"navigationBarBackgroundColor": "#F8F8F8",
-		"backgroundColor": "#F8F8F8"
-	}
+  "pages": [
+    {
+      "path": "pages/index/index",
+      "style": {
+        "navigationBarTitleText": "首页",
+        "navigationStyle": "custom"
+      }
+    },
+    {
+      "path": "pages/login/login",
+      "style": {
+        "navigationBarTitleText": "登录",
+        "enablePullDownRefresh": false,
+        "navigationStyle": "custom"
+      }
+    },
+    {
+      "path": "pages/dataOverview/todayOverview/todayOverview",
+      "style": {
+        "navigationBarTitleText": "今日概况",
+        "enablePullDownRefresh": false,
+        "navigationBarBackgroundColor": "#1767F2",
+        "navigationBarTextStyle": "white"
+      }
+    },
+    {
+      "path": "pages/dataOverview/operationalAnalysis/operationalAnalysis",
+      "style": {
+        "navigationBarTitleText": "运营分析",
+        "enablePullDownRefresh": false,
+        "navigationBarBackgroundColor": "#1767F2",
+        "navigationBarTextStyle": "white"
+      }
+    },
+    {
+      "path": "pages/dataOverview/statisticalReport/statisticalReport",
+      "style": {
+        "navigationBarTitleText": "统计报表",
+        "enablePullDownRefresh": false,
+        "navigationBarBackgroundColor": "#1767F2",
+        "navigationBarTextStyle": "white"
+      }
+    },
+    {
+      "path": "pages/orderManagement/parkingRecord/parkingRecord",
+      "style": {
+        "navigationBarTitleText": "停车记录",
+        "enablePullDownRefresh": false,
+        "navigationBarBackgroundColor": "#1767F2",
+        "navigationBarTextStyle": "white"
+      }
+    },
+    {
+      "path": "pages/orderManagement/arrearageRecord/arrearageRecord",
+      "style": {
+        "navigationBarTitleText": "欠费记录",
+        "enablePullDownRefresh": false,
+        "navigationBarBackgroundColor": "#1767F2",
+        "navigationBarTextStyle": "white"
+      }
+    },
+    {
+      "path": "pages/orderManagement/collectionRecord/collectionRecord",
+      "style": {
+        "navigationBarTitleText": "收款记录",
+        "enablePullDownRefresh": false,
+        "navigationBarBackgroundColor": "#1767F2",
+        "navigationBarTextStyle": "white"
+      }
+    },
+    {
+      "path": "pages/orderManagement/feeEvasionRecord/feeEvasionRecord",
+      "style": {
+        "navigationBarTitleText": "逃费记录",
+        "enablePullDownRefresh": false,
+        "navigationBarBackgroundColor": "#1767F2",
+        "navigationBarTextStyle": "white"
+      }
+    },
+    {
+      "path": "pages/orderManagement/voidRecord/voidRecord",
+      "style": {
+        "navigationBarTitleText": "作废记录",
+        "enablePullDownRefresh": false,
+        "navigationBarBackgroundColor": "#1767F2",
+        "navigationBarTextStyle": "white"
+      }
+    },
+    {
+      "path": "pages/orderManagement/recoveryRecord/recoveryRecord",
+      "style": {
+        "navigationBarTitleText": "追缴记录",
+        "enablePullDownRefresh": false,
+        "navigationBarBackgroundColor": "#1767F2",
+        "navigationBarTextStyle": "white"
+      }
+    },
+    {
+      "path": "pages/patrolManagement/patrolRecord/patrolRecord",
+      "style": {
+        "navigationBarTitleText": "巡检记录",
+        "enablePullDownRefresh": false,
+        "navigationBarBackgroundColor": "#1767F2",
+        "navigationBarTextStyle": "white"
+      }
+    },
+    {
+      "path": "pages/patrolManagement/deviceAbnormalRecords/deviceAbnormalRecords",
+      "style": {
+        "navigationBarTitleText": "设备异常记录",
+        "enablePullDownRefresh": true,
+        "navigationBarBackgroundColor": "#1767F2",
+        "navigationBarTextStyle": "white"
+      }
+    },
+    {
+      "path": "pages/patrolManagement/deviceAbnormalRecords/recordsDetails/recordsDetails",
+      "style": {
+        "navigationBarTitleText": "设备异常记录详情",
+        "enablePullDownRefresh": false,
+        "navigationBarBackgroundColor": "#1767F2",
+        "navigationBarTextStyle": "white"
+      }
+    },
+    {
+      "path": "pages/collectorManagement/performanceRanking/performanceRanking",
+      "style": {
+        "navigationBarTitleText": "业绩排名",
+        "enablePullDownRefresh": false,
+        "navigationBarBackgroundColor": "#1767F2",
+        "navigationBarTextStyle": "white"
+      }
+    },
+    {
+      "path": "pages/collectorManagement/performanceAnalysis/performanceAnalysis",
+      "style": {
+        "navigationBarTitleText": "业绩分析",
+        "enablePullDownRefresh": false,
+        "navigationBarBackgroundColor": "#1767F2",
+        "navigationBarTextStyle": "white"
+      }
+    },
+    {
+      "path": "pages/collectorManagement/assessmentRanking/assessmentRanking",
+      "style": {
+        "navigationBarTitleText": "考核排名",
+        "enablePullDownRefresh": false,
+        "navigationBarBackgroundColor": "#1767F2",
+        "navigationBarTextStyle": "white"
+      }
+    },
+    {
+      "path": "pages/collectorManagement/assessmentAnalysis/assessmentAnalysis",
+      "style": {
+        "navigationBarTitleText": "考核分析",
+        "enablePullDownRefresh": false,
+        "navigationBarBackgroundColor": "#1767F2",
+        "navigationBarTextStyle": "white"
+      }
+    },
+    {
+      "path": "pages/collectorManagement/shiftScheduling/shiftScheduling",
+      "style": {
+        "navigationBarTitleText": "排班情况",
+        "enablePullDownRefresh": false,
+        "navigationBarBackgroundColor": "#1767F2",
+        "navigationBarTextStyle": "white"
+      }
+    },
+    {
+      "path": "pages/patrolManagement/emergencyDisposalRecords/emergencyDisposalRecords",
+      "style": {
+        "navigationBarTitleText": "应急处置记录",
+        "enablePullDownRefresh": false,
+        "navigationBarBackgroundColor": "#1767F2",
+        "navigationBarTextStyle": "white"
+      }
+    },
+    {
+      "path": "pages/operationalAnalysis/roadModel/index",
+      "style": {
+        "navigationBarTitleText": "路段分析",
+        "enablePullDownRefresh": false,
+        "navigationBarBackgroundColor": "#1767F2",
+        "navigationBarTextStyle": "white"
+      }
+    },
+    {
+      "path": "pages/operationalAnalysis/parkModel/index",
+      "style": {
+        "navigationBarTitleText": "停车场分析",
+        "enablePullDownRefresh": false,
+        "navigationBarBackgroundColor": "#1767F2",
+        "navigationBarTextStyle": "white"
+      }
+    }
+  ],
+  "globalStyle": {
+    "navigationBarTextStyle": "black",
+    "navigationBarTitleText": "智慧停车运营端",
+    "navigationBarBackgroundColor": "#F8F8F8",
+    "backgroundColor": "#F8F8F8"
+  }
 }

pages/dataOverview/operationalAnalysis/components/arrearsAnalysis.vue → pages/dataOverview/operationalAnalysis copy/components/arrearsAnalysis.vue


pages/dataOverview/operationalAnalysis/components/incomeAnalysis.vue → pages/dataOverview/operationalAnalysis copy/components/incomeAnalysis.vue


pages/dataOverview/operationalAnalysis/components/paymentMethod.vue → pages/dataOverview/operationalAnalysis copy/components/paymentMethod.vue


pages/dataOverview/operationalAnalysis/components/revenueAnalysis.vue → pages/dataOverview/operationalAnalysis copy/components/revenueAnalysis.vue


pages/dataOverview/operationalAnalysis/components/revenueRanking.vue → pages/dataOverview/operationalAnalysis copy/components/revenueRanking.vue


pages/dataOverview/operationalAnalysis/components/sectionAnalysis.vue → pages/dataOverview/operationalAnalysis copy/components/sectionAnalysis.vue


pages/dataOverview/operationalAnalysis/components/sourceOfPayment.vue → pages/dataOverview/operationalAnalysis copy/components/sourceOfPayment.vue


pages/dataOverview/operationalAnalysis/components/tollCollectorPerformance.vue → pages/dataOverview/operationalAnalysis copy/components/tollCollectorPerformance.vue


pages/dataOverview/operationalAnalysis/components/trafficFlow.vue → pages/dataOverview/operationalAnalysis copy/components/trafficFlow.vue


+ 52 - 0
pages/dataOverview/operationalAnalysis copy/operationalAnalysis.scss

@@ -0,0 +1,52 @@
+.operation {
+	padding: 15px;
+	font-family: PingFangSC-Regular, PingFang SC;
+	&-header {
+		background-color: #fff;
+		border-radius: 5px;
+		padding: 15px;
+		display: flex;
+		justify-content: space-between;
+		align-items: center;
+		margin-bottom: 10px;
+		&-left {
+			display: flex;
+			align-items: center;
+			text {
+				margin-left: 5px;
+				color: #434343;
+				font-size: 15px;
+			}
+		}
+		&-right {
+			.tab {
+				display: flex;
+				border: solid 1px #1767F2;
+				&-item {
+					width: 40px;
+					height: 28px;
+					line-height: 28px;
+					text-align: center;
+					border-right: solid 1px #1767F2;
+					color: #1767F2;
+					font-size: 16px;
+					&:last-child {
+						border-right: none;
+					}
+				}
+				.active {
+					background-color: #1767f2;
+					color: #fff;
+				}
+			}
+		}
+	}
+	.mix-box {
+		&-1 {
+			background-color: #fff;
+			border-radius: 5px;
+			margin-bottom: 10px;
+			padding: 15px;
+		}
+	}
+}

+ 349 - 0
pages/dataOverview/operationalAnalysis copy/operationalAnalysis.vue

@@ -0,0 +1,349 @@
+<!-- 运营分析 -->
+<template>
+	<view class="operation">
+		<view class="operation-header">
+			<view class="operation-header-left" @click="typePicker = true">
+				<u-icon name="arrow-down" color="#000" size="15"></u-icon>
+				<text>{{ currentType.text }}</text>
+			</view>
+			<view class="operation-header-right">
+				<view class="tab">
+					<view class="tab-item" v-for="(item, index) in tabList" :key="index"
+						:class="{'active': tabCur === item.value}" @click="tabClick(item)">{{ item.label }}</view>
+				</view>
+			</view>
+		</view>
+		<view class="operation-main">
+			<template v-if="currentType.value === 1">
+				<RevenueAnalysis ref="revenueAnalysis" :type="currentType.type" :title="title"/>
+			</template>
+			<template v-else-if="currentType.value === 2">
+				<RevenueAnalysis ref="revenueAnalysis" :type="currentType.type" :title="title"/>
+			</template>
+			<template v-else-if="currentType.value === 3">
+				<RevenueRanking ref="revenueRanking" :title="title"/>
+			</template>
+			<template v-else-if="currentType.value === 4">
+				<TrafficFlow ref="trafficFlow" :title="title"/>
+			</template>
+			<template v-else-if="currentType.value === 5">
+				<TollCollectorPerformance ref="tollCollectorPerformance" type="table" :title="title"/>
+			</template>
+			<template v-else-if="currentType.value === 6">
+				<TollCollectorPerformance ref="tollCollectorPerformance" type="line" :title="title"/>
+			</template>
+			<template v-else-if="currentType.value === 7">
+				<SectionAnalysis ref="sectionAnalysis" :title="title"/>
+			</template>
+			<template v-else-if="currentType.value === 8">
+				<ArrearsAnalysis ref="arrearsAnalysis" :title="title"/>
+			</template>
+			<template v-else-if="currentType.value === 9">
+				<IncomeAnalysis ref="incomeAnalysis" :title="title"/>
+			</template>
+			<template v-else-if="currentType.value === 10">
+				<PaymentMethod ref="paymentMethod" :title="title"/>
+			</template>
+			<template v-else-if="currentType.value === 11">
+				<SourceOfPayment ref="sourceOfPayment" :title="title"/>
+			</template>
+		</view>
+		<!-- 分析类型 -->
+		<u-picker :show="typePicker" :columns="typeList" @confirm="typeConfirm" @cancel="typePicker = false"></u-picker>
+		<!-- 年 -->
+		<u-picker :show="yearPicker" :columns="yearList" :defaultIndex="defaultYear" @confirm="yearConfirm"
+			@cancel="yearPicker = false"></u-picker>
+		<!-- 月 -->
+		<u-picker :show="monthPicker" :columns="monthList" :defaultIndex="defaultMonth" @confirm="monthConfirm"
+			@cancel="monthPicker = false"></u-picker>
+		<!-- 日 -->
+		<u-picker :show="dayPicker" :columns="dayList" :defaultIndex="defaultDay" @confirm="dayConfirm"
+			@cancel="dayPicker = false"></u-picker>
+	</view>
+</template>
+
+<script>
+	import RevenueAnalysis from './components/revenueAnalysis.vue'
+	import RevenueRanking from './components/revenueRanking.vue'
+	import TrafficFlow from './components/trafficFlow.vue'
+	import TollCollectorPerformance from './components/tollCollectorPerformance.vue'
+	import SectionAnalysis from './components/sectionAnalysis.vue'
+	import ArrearsAnalysis from './components/arrearsAnalysis.vue'
+	import IncomeAnalysis from './components/incomeAnalysis.vue'
+	import SourceOfPayment from './components/sourceOfPayment.vue'
+	import PaymentMethod from './components/paymentMethod.vue'
+	export default {
+		components: {
+			RevenueAnalysis,
+			RevenueRanking,
+			TrafficFlow,
+			TollCollectorPerformance,
+			SectionAnalysis,
+			ArrearsAnalysis,
+			IncomeAnalysis,
+			SourceOfPayment,
+			PaymentMethod
+		},
+		data() {
+			return {
+				tabList: [{
+						label: '年',
+						value: 2
+					},
+					{
+						label: '月',
+						value: 1
+					},
+					{
+						label: '日',
+						value: 0
+					}
+				],
+				tabCur: 2,
+				// 参数
+				params: {
+					reportType: 2,
+					queryDate: ''
+				},
+				// 类型
+				typePicker: false,
+				currentType: {},
+				typeList: [
+					[{
+							text: '营收分析(折线)',
+							value: 1,
+							type: 'line',
+							key: 'revenueAnalysis'
+						},
+						{
+							text: '营收分析(柱状)',
+							value: 2,
+							type: 'column',
+							key: 'revenueAnalysis'
+						},
+						{
+							text: '路段/停车场营收排行',
+							value: 3,
+							key: 'revenueRanking'
+						},
+						{
+							text: '车流量分析',
+							value: 4,
+							key: 'trafficFlow'
+						},
+						// {
+						// 	text: '收费员业绩排行',
+						// 	value: 5,
+						// 	key: 'tollCollectorPerformance'
+						// },
+						// {
+						// 	text: '收费员业绩分析',
+						// 	value: 6,
+						// 	key: 'tollCollectorPerformance'
+						// },
+						{
+							text: '路段分析',
+							value: 7,
+							key: 'sectionAnalysis'
+						},
+						{
+							text: '欠费分析',
+							value: 8,
+							key: 'arrearsAnalysis'
+						},
+						{
+							text: '收入分析',
+							value: 9,
+							key: 'incomeAnalysis'
+						},
+						{
+							text: '支付方式占比',
+							value: 10,
+							key: 'paymentMethod'
+						},
+						{
+							text: '支付来源分析',
+							value: 11,
+							key: 'sourceOfPayment'
+						}
+					]
+				],
+				title: '',
+				// 年
+				yearPicker: false,
+				yearList: this.getYearList(),
+				defaultYear: [4],
+				currentYear: '',
+				yearObj: {},
+				// 月
+				monthPicker: false,
+				monthList: this.getMonthList(),
+				defaultMonth: [],
+				currentMonth: '01',
+				monthObj: {},
+				// 日
+				dayPicker: false,
+				dayList: this.getDayList(),
+				defaultDay: [],
+				currentDay: '01',
+				dayObj: {}
+			}
+		},
+		onShow() {
+			this.currentType = this.typeList[0][0]
+			this.defaultSetVal();
+		},
+		methods: {
+			defaultSetVal() {
+				this.currentYear = this.yearList[0][4].value
+				this.title = this.yearList[0][4].text
+				this.yearObj = this.yearList[0][4]
+				this.params.queryDate = `${this.currentYear}-${this.currentMonth}-${this.currentDay}`
+				setTimeout(() => {
+					this.$refs[this.currentType.key].getData(this.params)
+				}, 100)
+			},
+			getYearList() {
+				const date = new Date()
+				const year = date.getFullYear();
+				const list = [
+					[]
+				]
+				for (let i = year - 4; i < year + 1; i++) {
+					const obj = {
+						text: String(i),
+						value: String(i)
+					}
+					list[0].push(obj)
+				}
+				return list
+			},
+			getMonthList() {
+				const date = new Date()
+				const month = date.getMonth()
+				const list = [
+					[]
+				]
+				for (let i = 1; i < 13; i++) {
+					const obj = {
+						text: String(i),
+						value: String(i)
+					}
+					if (i < 10) {
+						obj.text = '0' + i
+						obj.value = '0' + i
+					}
+					list[0].push(obj)
+				}
+				setTimeout(() => {
+					this.defaultMonth = [0]
+				}, 1000)
+				return list
+			},
+			getDayList() {
+				const date = new Date()
+				const year = date.getFullYear()
+				let month = date.getMonth()
+				if (this.monthObj) {
+					month = parseInt(this.monthObj.value)
+				}
+				const day = date.getDate()
+				const dayLen = (new Date(year, month, 0)).getDate()
+				const list = [
+					[]
+				]
+				for (let i = 1; i < dayLen + 1; i++) {
+					const obj = {
+						text: String(i),
+						value: String(i)
+					}
+					if (i < 10) {
+						obj.text = '0' + i
+						obj.value = '0' + i
+					}
+					list[0].push(obj)
+				}
+				setTimeout(() => {
+					this.defaultDay = [0]
+				}, 1000)
+				return list
+			},
+			/**
+			 * 点击tab
+			 * @param {Object} item
+			 */
+			tabClick(item) {
+				this.tabCur = item.value
+				switch (item.value) {
+					case 0:
+						this.dayPicker = true
+						break
+					case 1:
+						this.monthPicker = true
+						break
+					case 2:
+						this.yearPicker = true
+						break
+				}
+				this.params.reportType = this.tabCur
+			},
+			/**
+			 * 选择器确认
+			 * @param {Object} e
+			 */
+			typeConfirm(e) {
+				this.currentType = e.value[0]
+				setTimeout(() => {
+					this.$refs[this.currentType.key].getData(this.params)
+					this.typePicker = false
+				}, 100)
+			},
+			yearConfirm(e) {
+				this.defaultYear = [e.indexs[0]]
+				this.title = e.value[0].text
+				this.currentYear = e.value[0].value
+				this.yearObj = e.value[0]
+				this.params.queryDate = `${this.currentYear}-${this.currentMonth}-${this.currentDay}`
+				setTimeout(() => {
+					this.$refs[this.currentType.key].getData(this.params)
+				}, 100)
+				this.yearPicker = false
+			},
+			monthConfirm(e) {
+				this.defaultMonth = [e.indexs[0]]
+				this.currentMonth = e.value[0].value
+				this.monthObj = e.value[0]
+				this.title = `${this.yearObj.text}-${this.monthObj.text}`
+				this.params.queryDate = `${this.currentYear}-${this.currentMonth}-${this.currentDay}`
+				setTimeout(() => {
+					this.$refs[this.currentType.key].getData(this.params)
+				}, 100)
+				this.monthPicker = false
+				this.dayList = this.getDayList()
+			},
+			dayConfirm(e) {
+				this.defaultDay = [e.indexs[0]]
+				this.title = e.value[0].text
+				this.currentDay = e.value[0].value
+				this.dayObj = e.value[0]
+				this.title = `${this.yearObj.text}-${this.monthObj.text}-${this.dayObj.text}`
+				this.params.queryDate = `${this.currentYear}-${this.currentMonth}-${this.currentDay}`
+				setTimeout(() => {
+					this.$refs[this.currentType.key].getData(this.params)
+				}, 100)
+				this.dayPicker = false
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	page {
+		background-color: #1767F2;
+		min-height: calc(100vh - 44px);
+	}
+</style>
+
+<style lang="scss" scoped>
+	@import './operationalAnalysis.scss';
+</style>

+ 50 - 51
pages/dataOverview/operationalAnalysis/operationalAnalysis.scss

@@ -1,52 +1,51 @@
 .operation {
-	padding: 15px;
-	font-family: PingFangSC-Regular, PingFang SC;
-	&-header {
-		background-color: #fff;
-		border-radius: 5px;
-		padding: 15px;
-		display: flex;
-		justify-content: space-between;
-		align-items: center;
-		margin-bottom: 10px;
-		&-left {
-			display: flex;
-			align-items: center;
-			text {
-				margin-left: 5px;
-				color: #434343;
-				font-size: 15px;
-			}
-		}
-		&-right {
-			.tab {
-				display: flex;
-				border: solid 1px #1767F2;
-				&-item {
-					width: 40px;
-					height: 28px;
-					line-height: 28px;
-					text-align: center;
-					border-right: solid 1px #1767F2;
-					color: #1767F2;
-					font-size: 16px;
-					&:last-child {
-						border-right: none;
-					}
-				}
-				.active {
-					background-color: #1767f2;
-					color: #fff;
-				}
-			}
-		}
-	}
-	.mix-box {
-		&-1 {
-			background-color: #fff;
-			border-radius: 5px;
-			margin-bottom: 10px;
-			padding: 15px;
-		}
-	}
-}
+  padding: 15px;
+  font-family: PingFangSC-Regular, PingFang SC;
+  &-header {
+    width: 100%;
+    border: solid 1px #fff;
+    display: flex;
+    justify-content: space-between;
+    border-radius: 5px;
+    margin-bottom: 18px;
+    &-item {
+      width: 50%;
+      text-align: center;
+      line-height: 49px;
+      color: #fff;
+      font-size: 20px;
+      font-family: PingFangSC-Regular, PingFang SC;
+    }
+    .active {
+      background-color: #fff;
+      color: #434343;
+    }
+  }
+  &-main {
+    padding: 30px 15px 0;
+    background-color: #fff;
+    border-radius: 5px;
+    &-menu {
+      display: flex;
+      flex-wrap: wrap;
+      &-item {
+        width: calc(33% - 20px);
+        text-align: center;
+        margin-right: 30px;
+        margin-bottom: 29px;
+        &:nth-child(3n) {
+          margin-right: 0;
+        }
+        .image {
+          width: 88px;
+          margin: 0 auto 16px;
+        }
+        .name {
+          white-space: nowrap;
+          overflow: hidden;
+          text-overflow: ellipsis;
+        }
+      }
+    }
+  }
+}

+ 175 - 337
pages/dataOverview/operationalAnalysis/operationalAnalysis.vue

@@ -1,349 +1,187 @@
 <!-- 运营分析 -->
 <template>
-	<view class="operation">
-		<view class="operation-header">
-			<view class="operation-header-left" @click="typePicker = true">
-				<u-icon name="arrow-down" color="#000" size="15"></u-icon>
-				<text>{{ currentType.text }}</text>
-			</view>
-			<view class="operation-header-right">
-				<view class="tab">
-					<view class="tab-item" v-for="(item, index) in tabList" :key="index"
-						:class="{'active': tabCur === item.value}" @click="tabClick(item)">{{ item.label }}</view>
-				</view>
-			</view>
-		</view>
-		<view class="operation-main">
-			<template v-if="currentType.value === 1">
-				<RevenueAnalysis ref="revenueAnalysis" :type="currentType.type" :title="title"/>
-			</template>
-			<template v-else-if="currentType.value === 2">
-				<RevenueAnalysis ref="revenueAnalysis" :type="currentType.type" :title="title"/>
-			</template>
-			<template v-else-if="currentType.value === 3">
-				<RevenueRanking ref="revenueRanking" :title="title"/>
-			</template>
-			<template v-else-if="currentType.value === 4">
-				<TrafficFlow ref="trafficFlow" :title="title"/>
-			</template>
-			<template v-else-if="currentType.value === 5">
-				<TollCollectorPerformance ref="tollCollectorPerformance" type="table" :title="title"/>
-			</template>
-			<template v-else-if="currentType.value === 6">
-				<TollCollectorPerformance ref="tollCollectorPerformance" type="line" :title="title"/>
-			</template>
-			<template v-else-if="currentType.value === 7">
-				<SectionAnalysis ref="sectionAnalysis" :title="title"/>
-			</template>
-			<template v-else-if="currentType.value === 8">
-				<ArrearsAnalysis ref="arrearsAnalysis" :title="title"/>
-			</template>
-			<template v-else-if="currentType.value === 9">
-				<IncomeAnalysis ref="incomeAnalysis" :title="title"/>
-			</template>
-			<template v-else-if="currentType.value === 10">
-				<PaymentMethod ref="paymentMethod" :title="title"/>
-			</template>
-			<template v-else-if="currentType.value === 11">
-				<SourceOfPayment ref="sourceOfPayment" :title="title"/>
-			</template>
-		</view>
-		<!-- 分析类型 -->
-		<u-picker :show="typePicker" :columns="typeList" @confirm="typeConfirm" @cancel="typePicker = false"></u-picker>
-		<!-- 年 -->
-		<u-picker :show="yearPicker" :columns="yearList" :defaultIndex="defaultYear" @confirm="yearConfirm"
-			@cancel="yearPicker = false"></u-picker>
-		<!-- 月 -->
-		<u-picker :show="monthPicker" :columns="monthList" :defaultIndex="defaultMonth" @confirm="monthConfirm"
-			@cancel="monthPicker = false"></u-picker>
-		<!-- 日 -->
-		<u-picker :show="dayPicker" :columns="dayList" :defaultIndex="defaultDay" @confirm="dayConfirm"
-			@cancel="dayPicker = false"></u-picker>
-	</view>
+  <view class="operation">
+    <view class="operation-header">
+      <view
+        class="operation-header-item"
+        v-for="(item, index) in tabList"
+        :key="index"
+        :class="{ active: tabCur === item.key }"
+        @click="tabCur = item.key"
+      >
+        <text>{{ item.label }}</text>
+      </view>
+    </view>
+    <view class="operation-main">
+      <template v-if="tabCur === 'road'">
+        <view class="operation-main-menu">
+          <view
+            class="operation-main-menu-item"
+            v-for="(item, index) in roadMenuList"
+            :key="index"
+            @click="jumpPage(item.url, item.params)"
+          >
+            <view class="image">
+              <u--image :showLoading="true" :src="item.icon" width="88px" height="88px" />
+            </view>
+            <view class="name">
+              <text>{{ item.name }}</text>
+            </view>
+          </view>
+        </view>
+      </template>
+      <template v-if="tabCur === 'park'">
+        <view class="operation-main-menu">
+          <view
+            class="operation-main-menu-item"
+            v-for="(item, index) in parkMenuList"
+            :key="index"
+            @click="jumpPage(item.url, item.params)"
+          >
+            <view class="image">
+              <u--image :showLoading="true" :src="item.icon" width="88px" height="88px" />
+            </view>
+            <view class="name">
+              <text>{{ item.name }}</text>
+            </view>
+          </view>
+        </view>
+      </template>
+    </view>
+  </view>
 </template>
 
 <script>
-	import RevenueAnalysis from './components/revenueAnalysis.vue'
-	import RevenueRanking from './components/revenueRanking.vue'
-	import TrafficFlow from './components/trafficFlow.vue'
-	import TollCollectorPerformance from './components/tollCollectorPerformance.vue'
-	import SectionAnalysis from './components/sectionAnalysis.vue'
-	import ArrearsAnalysis from './components/arrearsAnalysis.vue'
-	import IncomeAnalysis from './components/incomeAnalysis.vue'
-	import SourceOfPayment from './components/sourceOfPayment.vue'
-	import PaymentMethod from './components/paymentMethod.vue'
-	export default {
-		components: {
-			RevenueAnalysis,
-			RevenueRanking,
-			TrafficFlow,
-			TollCollectorPerformance,
-			SectionAnalysis,
-			ArrearsAnalysis,
-			IncomeAnalysis,
-			SourceOfPayment,
-			PaymentMethod
-		},
-		data() {
-			return {
-				tabList: [{
-						label: '年',
-						value: 2
-					},
-					{
-						label: '月',
-						value: 1
-					},
-					{
-						label: '日',
-						value: 0
-					}
-				],
-				tabCur: 2,
-				// 参数
-				params: {
-					reportType: 2,
-					queryDate: ''
-				},
-				// 类型
-				typePicker: false,
-				currentType: {},
-				typeList: [
-					[{
-							text: '营收分析(折线)',
-							value: 1,
-							type: 'line',
-							key: 'revenueAnalysis'
-						},
-						{
-							text: '营收分析(柱状)',
-							value: 2,
-							type: 'column',
-							key: 'revenueAnalysis'
-						},
-						{
-							text: '路段/停车场营收排行',
-							value: 3,
-							key: 'revenueRanking'
-						},
-						{
-							text: '车流量分析',
-							value: 4,
-							key: 'trafficFlow'
-						},
-						// {
-						// 	text: '收费员业绩排行',
-						// 	value: 5,
-						// 	key: 'tollCollectorPerformance'
-						// },
-						// {
-						// 	text: '收费员业绩分析',
-						// 	value: 6,
-						// 	key: 'tollCollectorPerformance'
-						// },
-						{
-							text: '路段分析',
-							value: 7,
-							key: 'sectionAnalysis'
-						},
-						{
-							text: '欠费分析',
-							value: 8,
-							key: 'arrearsAnalysis'
-						},
-						{
-							text: '收入分析',
-							value: 9,
-							key: 'incomeAnalysis'
-						},
-						{
-							text: '支付方式占比',
-							value: 10,
-							key: 'paymentMethod'
-						},
-						{
-							text: '支付来源分析',
-							value: 11,
-							key: 'sourceOfPayment'
-						}
-					]
-				],
-				title: '',
-				// 年
-				yearPicker: false,
-				yearList: this.getYearList(),
-				defaultYear: [4],
-				currentYear: '',
-				yearObj: {},
-				// 月
-				monthPicker: false,
-				monthList: this.getMonthList(),
-				defaultMonth: [],
-				currentMonth: '01',
-				monthObj: {},
-				// 日
-				dayPicker: false,
-				dayList: this.getDayList(),
-				defaultDay: [],
-				currentDay: '01',
-				dayObj: {}
-			}
-		},
-		onShow() {
-			this.currentType = this.typeList[0][0]
-			this.defaultSetVal();
-		},
-		methods: {
-			defaultSetVal() {
-				this.currentYear = this.yearList[0][4].value
-				this.title = this.yearList[0][4].text
-				this.yearObj = this.yearList[0][4]
-				this.params.queryDate = `${this.currentYear}-${this.currentMonth}-${this.currentDay}`
-				setTimeout(() => {
-					this.$refs[this.currentType.key].getData(this.params)
-				}, 100)
-			},
-			getYearList() {
-				const date = new Date()
-				const year = date.getFullYear();
-				const list = [
-					[]
-				]
-				for (let i = year - 4; i < year + 1; i++) {
-					const obj = {
-						text: String(i),
-						value: String(i)
-					}
-					list[0].push(obj)
-				}
-				return list
-			},
-			getMonthList() {
-				const date = new Date()
-				const month = date.getMonth()
-				const list = [
-					[]
-				]
-				for (let i = 1; i < 13; i++) {
-					const obj = {
-						text: String(i),
-						value: String(i)
-					}
-					if (i < 10) {
-						obj.text = '0' + i
-						obj.value = '0' + i
-					}
-					list[0].push(obj)
-				}
-				setTimeout(() => {
-					this.defaultMonth = [0]
-				}, 1000)
-				return list
-			},
-			getDayList() {
-				const date = new Date()
-				const year = date.getFullYear()
-				let month = date.getMonth()
-				if (this.monthObj) {
-					month = parseInt(this.monthObj.value)
-				}
-				const day = date.getDate()
-				const dayLen = (new Date(year, month, 0)).getDate()
-				const list = [
-					[]
-				]
-				for (let i = 1; i < dayLen + 1; i++) {
-					const obj = {
-						text: String(i),
-						value: String(i)
-					}
-					if (i < 10) {
-						obj.text = '0' + i
-						obj.value = '0' + i
-					}
-					list[0].push(obj)
-				}
-				setTimeout(() => {
-					this.defaultDay = [0]
-				}, 1000)
-				return list
-			},
-			/**
-			 * 点击tab
-			 * @param {Object} item
-			 */
-			tabClick(item) {
-				this.tabCur = item.value
-				switch (item.value) {
-					case 0:
-						this.dayPicker = true
-						break
-					case 1:
-						this.monthPicker = true
-						break
-					case 2:
-						this.yearPicker = true
-						break
-				}
-				this.params.reportType = this.tabCur
-			},
-			/**
-			 * 选择器确认
-			 * @param {Object} e
-			 */
-			typeConfirm(e) {
-				this.currentType = e.value[0]
-				setTimeout(() => {
-					this.$refs[this.currentType.key].getData(this.params)
-					this.typePicker = false
-				}, 100)
-			},
-			yearConfirm(e) {
-				this.defaultYear = [e.indexs[0]]
-				this.title = e.value[0].text
-				this.currentYear = e.value[0].value
-				this.yearObj = e.value[0]
-				this.params.queryDate = `${this.currentYear}-${this.currentMonth}-${this.currentDay}`
-				setTimeout(() => {
-					this.$refs[this.currentType.key].getData(this.params)
-				}, 100)
-				this.yearPicker = false
-			},
-			monthConfirm(e) {
-				this.defaultMonth = [e.indexs[0]]
-				this.currentMonth = e.value[0].value
-				this.monthObj = e.value[0]
-				this.title = `${this.yearObj.text}-${this.monthObj.text}`
-				this.params.queryDate = `${this.currentYear}-${this.currentMonth}-${this.currentDay}`
-				setTimeout(() => {
-					this.$refs[this.currentType.key].getData(this.params)
-				}, 100)
-				this.monthPicker = false
-				this.dayList = this.getDayList()
-			},
-			dayConfirm(e) {
-				this.defaultDay = [e.indexs[0]]
-				this.title = e.value[0].text
-				this.currentDay = e.value[0].value
-				this.dayObj = e.value[0]
-				this.title = `${this.yearObj.text}-${this.monthObj.text}-${this.dayObj.text}`
-				this.params.queryDate = `${this.currentYear}-${this.currentMonth}-${this.currentDay}`
-				setTimeout(() => {
-					this.$refs[this.currentType.key].getData(this.params)
-				}, 100)
-				this.dayPicker = false
-			}
-		}
-	}
+export default {
+  data() {
+    return {
+      tabList: [
+        { key: 'road', label: '路段' },
+        { key: 'park', label: '停车场' }
+      ],
+      tabCur: 'road',
+      roadMenuList: [
+        {
+          icon: '/static/icons/operationalAnalysisIcons/section-analysis-icon.svg',
+          name: '路段分析',
+          url: 'pages/operationalAnalysis/roadModel/index',
+          params: {
+            title: '路段分析',
+            key: 'sectionAnalysis'
+          }
+        },
+        {
+          icon: '/static/icons/operationalAnalysisIcons/arrearage-analysis-icon.svg',
+          name: '欠费分析',
+          url: 'pages/operationalAnalysis/roadModel/index',
+          params: {
+            title: '欠费分析',
+            key: 'arrearsAnalysis'
+          }
+        },
+        {
+          icon: '/static/icons/operationalAnalysisIcons/revenue-analysis-icon.svg',
+          name: '营收分析',
+          url: 'pages/operationalAnalysis/roadModel/index',
+          params: {
+            title: '营收分析',
+            key: 'revenueAnalysis'
+          }
+        },
+        {
+          icon: '/static/icons/operationalAnalysisIcons/shouru-analysis-icon.svg',
+          name: '收入分析',
+          url: 'pages/operationalAnalysis/roadModel/index',
+          params: {
+            title: '收入分析',
+            key: 'incomeAnalysis'
+          }
+        },
+        {
+          icon: '/static/icons/operationalAnalysisIcons/payment-method-icon.svg',
+          name: '支付方式占比',
+          url: 'pages/operationalAnalysis/roadModel/index',
+          params: {
+            title: '支付方式占比',
+            key: 'paymentMethod'
+          }
+        }
+      ],
+      parkMenuList: [
+        {
+          icon: '/static/icons/operationalAnalysisIcons/section-analysis-icon.svg',
+          name: '停车场分析',
+          url: 'pages/operationalAnalysis/parkModel/index',
+          params: {
+            title: '停车场分析',
+            key: 'parkingLotAnalysis'
+          }
+        },
+        {
+          icon: '/static/icons/operationalAnalysisIcons/arrearage-analysis-icon.svg',
+          name: '欠费分析',
+          url: 'pages/operationalAnalysis/parkModel/index',
+          params: {
+            title: '欠费分析',
+            key: 'arrearsAnalysis'
+          }
+        },
+        {
+          icon: '/static/icons/operationalAnalysisIcons/revenue-analysis-icon.svg',
+          name: '营收分析',
+          url: 'pages/operationalAnalysis/parkModel/index',
+          params: {
+            title: '营收分析',
+            key: 'revenueAnalysis'
+          }
+        },
+        {
+          icon: '/static/icons/operationalAnalysisIcons/shouru-analysis-icon.svg',
+          name: '收入分析',
+          url: 'pages/operationalAnalysis/parkModel/index',
+          params: {
+            title: '收入分析',
+            key: 'incomeAnalysis'
+          }
+        },
+        {
+          icon: '/static/icons/operationalAnalysisIcons/payment-method-icon.svg',
+          name: '支付方式占比',
+          url: 'pages/operationalAnalysis/parkModel/index',
+          params: {
+            title: '支付方式占比',
+            key: 'paymentMethod'
+          }
+        }
+      ]
+    };
+  },
+  onShow() {},
+  methods: {
+    /**
+     * 跳转指定页面
+     * @param {*} url
+     * @param {*} params
+     * @param {*} type
+     */
+    jumpPage(url, params, type = 'navigateTo') {
+      uni.$u.route({
+        url,
+        params,
+        type
+      });
+    }
+  }
+};
 </script>
 
 <style lang="scss">
-	page {
-		background-color: #1767F2;
-		min-height: calc(100vh - 44px);
-	}
+page {
+  background-color: #1767f2;
+  min-height: calc(100vh - 44px);
+}
 </style>
 
 <style lang="scss" scoped>
-	@import './operationalAnalysis.scss';
+@import './operationalAnalysis.scss';
 </style>

+ 122 - 0
pages/operationalAnalysis/parkModel/components/arrearsAnalysis.vue

@@ -0,0 +1,122 @@
+<!-- 欠费分析 -->
+<template>
+  <view class="arrears">
+    <view class="arrears-line">
+      <LineChart v-if="hasData" :chartData="chartData" :title="title" :opts="opts" />
+      <view class="empty" v-else>
+        <u-empty></u-empty>
+      </view>
+    </view>
+    <u-loading-page :loading="loading" loading-text="loading..."></u-loading-page>
+  </view>
+</template>
+
+<script>
+import LineChart from '@/components/lineChart.vue';
+export default {
+  components: {
+    LineChart
+  },
+  props: {
+    title: {
+      type: String,
+      default: ''
+    },
+    opts: {
+      type: Object,
+      default: () => {
+        return {
+          enableScroll: true,
+          xAxis: {
+            rotateLabel: true,
+            scrollShow: true,
+            itemCount: 8
+          },
+          yAxis: {
+            showTitle: true,
+            splitNumber: 5,
+            data: [
+              {
+                title: '元',
+                titleOffsetY: -3
+              }
+            ]
+          },
+          legend: {
+            show: true
+          },
+          dataLabel: false,
+          padding: [20, 0, 10, 0],
+          extra: {
+            column: {
+              width: 20
+            }
+          }
+        };
+      }
+    }
+  },
+  data() {
+    return {
+      chartData: {
+        categories: [],
+        series: []
+      },
+      hasData: false,
+      loading: false
+    };
+  },
+  methods: {
+    getData({ reportType, queryDate }) {
+      this.hasData = false;
+      this.chartData.categories = [];
+      this.chartData.series = [];
+      this.loading = true;
+      this.getParkingData({
+        reportType,
+        queryDate
+      });
+    },
+    getParkingData({ reportType, queryDate }) {
+      uni.$u.api.operationalAnalysisApi
+        .getParkingArrearsDataApi({
+          reportType,
+          queryDate
+        })
+        .then((res) => {
+          if (res.code === 200) {
+            if (res.data.itemList && res.data.itemList.length) {
+              this.chartData.series[0] = {
+                name: '停车场',
+                data: []
+              };
+              this.chartData.series[0].data = res.data.itemList.map((item) => {
+                return item.amt;
+              });
+              if (!this.chartData.categories.length) {
+                this.chartData.categories = res.data.itemList.map((item) => {
+                  return item.statisTime;
+                });
+              }
+              this.hasData = true;
+            } else {
+              this.hasData = false;
+            }
+          }
+          this.loading = false;
+        });
+    }
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+.arrears {
+  background-color: #fff;
+  border-radius: 5px;
+
+  .empty {
+    padding: 15px;
+  }
+}
+</style>

+ 183 - 0
pages/operationalAnalysis/parkModel/components/incomeAnalysis.vue

@@ -0,0 +1,183 @@
+<!-- 收入分析 -->
+<template>
+  <view class="revenue">
+    <view class="revenue-search">
+      <view class="revenue-search-item" @click="incomeTypePicker = true">
+        <u--input
+          placeholder="请输入内容"
+          v-model="searchContent.text"
+          suffixIcon="arrow-down"
+          :readonly="true"
+        />
+      </view>
+    </view>
+    <view class="revenue-line">
+      <ColumnChart
+        v-if="chartData.series[0].data.length"
+        :chartData="chartData"
+        :title="title"
+        :opts="opts"
+      />
+      <view class="empty" v-else>
+        <u-empty></u-empty>
+      </view>
+    </view>
+    <u-picker
+      :show="incomeTypePicker"
+      :columns="dictList"
+      @confirm="incomeTypeConfirm"
+      @cancel="incomeTypePicker = false"
+    ></u-picker>
+    <u-loading-page :loading="loading" loading-text="loading..."></u-loading-page>
+  </view>
+</template>
+
+<script>
+import ColumnChart from '@/components/columnChart.vue';
+export default {
+  components: {
+    ColumnChart
+  },
+  props: {
+    title: {
+      type: String,
+      default: ''
+    },
+    opts: {
+      type: Object,
+      default: () => {
+        return {
+          enableScroll: true,
+          xAxis: {
+            rotateLabel: false,
+            scrollShow: true,
+            itemCount: 8
+          },
+          yAxis: {
+            showTitle: true,
+            splitNumber: 5,
+            data: [
+              {
+                title: '元',
+                titleOffsetY: -3
+              }
+            ]
+          },
+          legend: {
+            show: false
+          },
+          dataLabel: false,
+          padding: [20, 0, 10, 0],
+          extra: {
+            column: {
+              width: 20
+            }
+          }
+        };
+      }
+    }
+  },
+  data() {
+    return {
+      loading: false,
+      chartData: {
+        categories: [],
+        series: [
+          {
+            name: '收入',
+            data: []
+          }
+        ]
+      },
+      searchContent: {
+        text: '',
+        value: ''
+      },
+      dictList: [[]],
+      incomeTypePicker: false,
+      reportType: '',
+      queryDate: ''
+    };
+  },
+  methods: {
+    getData({ reportType, queryDate }) {
+      this.reportType = reportType;
+      this.queryDate = queryDate;
+      this.loading = true;
+      this.getDict();
+    },
+    getDict() {
+      uni.$u.api.getDictApi({ type: 'income_type' }).then((res) => {
+        if (res.code === 200) {
+          let list = res.data.map((item) => {
+            return {
+              text: item.dictLabel,
+              value: item.dictValue
+            };
+          });
+          this.dictList = [list];
+          if (!this.searchContent.value) {
+            this.searchContent = this.dictList[0][0];
+          }
+          this.getIncomeData();
+        }
+      });
+    },
+    getIncomeData() {
+      this.chartData.categories = [];
+      this.chartData.series[0].data = [];
+      this.chartData.series[0].name = this.searchContent.text;
+      uni.$u.api.operationalAnalysisApi
+        .getParkingIncomeDataApi({
+          reportType: this.reportType,
+          queryDate: this.queryDate,
+          incomeType: this.searchContent.value
+        })
+        .then((res) => {
+          if (res.code === 200) {
+            if (res.data.itemList && res.data.itemList.length) {
+              this.chartData.categories = res.data.itemList.map((item) => {
+                return item.statisTime;
+              });
+              this.chartData.series[0].data = res.data.itemList.map((item) => {
+                return item.amt;
+              });
+            }
+          }
+          this.loading = false;
+        });
+    },
+    incomeTypeConfirm(e) {
+      this.searchContent = e.value[0];
+      this.getIncomeData();
+      this.incomeTypePicker = false;
+    },
+    searchClick() {
+      // this.getIncomeData()
+    }
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+.revenue {
+  background-color: #fff;
+  border-radius: 5px;
+  &-search {
+    margin-bottom: 12px;
+    padding: 19px 15px 0 15px;
+    display: flex;
+    &-item {
+      width: 48%;
+      margin-right: 2%;
+      &-btn {
+        width: 50%;
+        height: 38px;
+      }
+    }
+  }
+}
+.empty {
+  padding: 15px;
+}
+</style>

+ 219 - 0
pages/operationalAnalysis/parkModel/components/parkingLotAnalysis.vue

@@ -0,0 +1,219 @@
+<!-- 停车场分析 -->
+<template>
+  <view class="section">
+    <!-- 营收趋势分析 -->
+    <view class="section-part">
+      <view class="section-part-title">
+        <text>|</text>营收趋势分析
+      </view>
+      <view class="section-part-content">
+        <ColumnChart
+          v-if="revenueTrendsData.series[0].data.length"
+          :chartData="revenueTrendsData"
+          :title="title"
+          :opts="opts1"
+        />
+        <view class="empty" v-else>
+          <u-empty></u-empty>
+        </view>
+      </view>
+    </view>
+    <view class="section-part">
+      <view class="section-part-title">
+        <text>|</text>车流量统计
+      </view>
+      <view class="section-part-content">
+        <ColumnChart
+          v-if="trafficFlowData.series[0].data.length"
+          :chartData="trafficFlowData"
+          :title="title"
+          :opts="opts2"
+        />
+        <view class="empty" v-else>
+          <u-empty></u-empty>
+        </view>
+      </view>
+    </view>
+    <u-loading-page :loading="loading" loading-text="loading..."></u-loading-page>
+  </view>
+</template>
+
+<script>
+import ColumnChart from '@/components/columnChart.vue';
+export default {
+  components: {
+    ColumnChart
+  },
+  props: {
+    title: {
+      type: String,
+      default: ''
+    }
+  },
+  data() {
+    return {
+      loading: false,
+      opts1: {
+        enableScroll: true,
+        xAxis: {
+          rotateLabel: true,
+          scrollShow: true,
+          itemCount: 8
+        },
+        yAxis: {
+          showTitle: true,
+          splitNumber: 5,
+          data: [
+            {
+              title: '收益(元)',
+              titleOffsetY: -3
+            }
+          ]
+        },
+        legend: {
+          show: false
+        },
+        dataLabel: false,
+        padding: [20, 0, 10, 0],
+        extra: {
+          column: {
+            width: 20
+          }
+        }
+      },
+      opts2: {
+        enableScroll: true,
+        xAxis: {
+          rotateLabel: true,
+          scrollShow: true,
+          itemCount: 8
+        },
+        yAxis: {
+          showTitle: true,
+          splitNumber: 5,
+          data: [
+            {
+              title: '车辆(辆)',
+              titleOffsetY: 0,
+              titleOffsetX: 10
+            }
+          ]
+        },
+        legend: {
+          show: false
+        },
+        dataLabel: false,
+        padding: [10, 0, 10, 0],
+        extra: {
+          column: {
+            width: 20
+          }
+        }
+      },
+      revenueTrendsData: {
+        categories: [],
+        series: [
+          {
+            name: '',
+            data: []
+          }
+        ]
+      },
+      trafficFlowData: {
+        categories: [],
+        series: [
+          {
+            name: '',
+            data: []
+          }
+        ]
+      }
+    };
+  },
+  methods: {
+    getData({ reportType, queryDate }) {
+      this.reportType = reportType;
+      this.queryDate = queryDate;
+      this.loading = true;
+      this.getRevenueTrendsData();
+      this.getRoadTrafficFlowData();
+    },
+    getRevenueTrendsData() {
+      uni.$u.api.operationalAnalysisApi
+        .getParkingLotRevenueAmountApi({
+          reportType: this.reportType,
+          queryDate: this.queryDate
+        })
+        .then((res) => {
+          if (res.code === 200) {
+            if (res.data.itemList && res.data.itemList.length) {
+              this.revenueTrendsData.categories = res.data.itemList.map(
+                (item) => {
+                  return item.roadName;
+                }
+              );
+              this.revenueTrendsData.series[0].data = res.data.itemList.map(
+                (item) => {
+                  return item.amt;
+                }
+              );
+            } else {
+              this.revenueTrendsData.categories = [];
+              this.revenueTrendsData.series[0].data = [];
+            }
+          }
+          this.loading = false;
+        });
+    },
+    getRoadTrafficFlowData() {
+      uni.$u.api.operationalAnalysisApi
+        .getParkingLotTrafficVolumeApi({
+          reportType: this.reportType,
+          queryDate: this.queryDate
+        })
+        .then((res) => {
+          if (res.code === 200) {
+            if (res.data.itemList && res.data.itemList.length) {
+              this.trafficFlowData.categories = res.data.itemList.map(
+                (item) => {
+                  return item.roadName;
+                }
+              );
+              this.trafficFlowData.series[0].data = res.data.itemList.map(
+                (item) => {
+                  return item.vehicleCount;
+                }
+              );
+            } else {
+              this.trafficFlowData.categories = [];
+              this.trafficFlowData.series[0].data = [];
+            }
+          }
+          this.loading = false;
+        });
+    }
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+.section {
+  &-part {
+    background-color: #fff;
+    border-radius: 5px;
+    margin-bottom: 10px;
+
+    &-title {
+      padding: 15px;
+
+      text {
+        color: #f00;
+        margin-right: 5px;
+      }
+    }
+  }
+  .empty {
+    padding: 15px;
+  }
+}
+</style>

+ 100 - 0
pages/operationalAnalysis/parkModel/components/paymentMethod.vue

@@ -0,0 +1,100 @@
+<!-- 支付占比分析分析 -->
+<template>
+	<view class="revenue-box">
+		<view class="revenue-line revenue">
+			<PieChart v-if="chartData.series[0].data.length" :chartData="chartData" :title="`停车场(${title})`"/>
+			<view class="empty" v-else>
+				<u-empty></u-empty>
+			</view>
+		</view>
+		<u-loading-page :loading="loading" loading-text="loading..."></u-loading-page>
+	</view>
+</template>
+
+<script>
+	import PieChart from '@/components/pieChart.vue'
+	export default {
+		components: {
+			PieChart
+		},
+		props: {
+			title: {
+				type: String,
+				default: ''
+			}
+		},
+		data() {
+			return {
+				loading: false,
+				reportType: '',
+				queryDate: '',
+				paySourceList: [],
+				chartData: {
+					series: [{
+						data: []
+					}]
+				}
+			}
+		},
+		created() {
+			this.getDict()
+		},
+		methods: {
+			getData({ reportType, queryDate }) {
+				this.reportType = reportType
+				this.queryDate = queryDate
+				this.loading = true
+				this.getPaymentWaysData()
+			},
+			getDict() {
+				uni.$u.api.getDictApi({  type: 'pay_source'}).then(res => {
+					if (res.code === 200) {
+						this.paySourceList = res.data
+					}
+				})
+			},
+			getPaymentWaysData() {
+				uni.$u.api.operationalAnalysisApi.getParkingPaymentWaysDataApi({
+					reportType: this.reportType,
+					queryDate: this.queryDate
+				}).then(res => {
+					if (res.code === 200) {
+						if (res.data.itemList && res.data.itemList.length) {
+							let list = res.data.itemList.map(item => {
+								return {
+									name: this.getDictLabel(item.paySource),
+									value: item.amt
+								}
+							})
+							this.chartData.series[0].data = list
+						} else {
+							this.chartData.series[0].data = []
+						}
+					}
+					this.loading = false
+				})
+			},
+			getDictLabel(value) {
+				let name
+				this.paySourceList.forEach(item => {
+					if (item.dictValue == value) {
+						name = item.dictLabel
+					}
+				})
+				if (!name) name = '其他'
+				return name
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.revenue {
+		background-color: #fff;
+		border-radius: 5px;
+		margin-bottom: 10px;
+		.empty {
+			padding: 15px;
+		}
+	}
+</style>

+ 143 - 0
pages/operationalAnalysis/parkModel/components/revenueAnalysis.vue

@@ -0,0 +1,143 @@
+<!-- 营收分析 -->
+<template>
+  <view class="revenue">
+    <template v-if="type === 'line'">
+      <view class="revenue-line">
+        <LineChart v-if="hasData" :chartData="chartData" :title="title" :opts="opts" />
+        <view class="empty" v-else>
+          <u-empty></u-empty>
+        </view>
+      </view>
+    </template>
+    <template v-else>
+      <view class="revenue-line">
+        <ColumnChart v-if="hasData" :chartData="chartData" :title="title" :opts="opts" />
+        <view class="empty" v-else>
+          <u-empty></u-empty>
+        </view>
+      </view>
+    </template>
+    <u-loading-page :loading="loading" loading-text="loading..."></u-loading-page>
+  </view>
+</template>
+
+<script>
+import LineChart from '@/components/lineChart.vue';
+import ColumnChart from '@/components/columnChart.vue';
+export default {
+  components: {
+    LineChart,
+    ColumnChart
+  },
+  props: {
+    type: {
+      type: String,
+      default: 'line'
+    },
+    title: {
+      type: String,
+      default: ''
+    },
+    params: {
+      type: Object,
+      default: () => {}
+    }
+  },
+  data() {
+    return {
+      loading: false,
+      chartData: {
+        categories: [],
+        series: []
+      },
+      hasData: false,
+      opts: {
+        enableScroll: true,
+        tooltip: {
+          trigger: 'axis'
+        },
+        xAxis: {
+          rotateLabel: true,
+          scrollShow: true,
+          itemCount: 8
+        },
+        yAxis: {
+          showTitle: true,
+          splitNumber: 5,
+          data: [
+            {
+              title: '收益(元)',
+              titleOffsetY: -3
+            }
+          ]
+        },
+        legend: {
+          show: true
+        },
+        dataLabel: false,
+        padding: [20, 10, 10, 10],
+        extra: {
+          column: {
+            width: 20
+          }
+        }
+      }
+    };
+  },
+  methods: {
+    /**
+     * 获取数据
+     */
+    getData({ reportType, queryDate }) {
+      this.hasData = false;
+      this.chartData.categories = [];
+      this.chartData.series = [];
+      this.loading = true;
+      this.getParkingData({ reportType, queryDate });
+    },
+    /**
+     * 停车场数据
+     */
+    getParkingData({ reportType, queryDate }) {
+      uni.$u.api.operationalAnalysisApi
+        .getParkingRevenueDataApi({
+          reportType,
+          queryDate
+        })
+        .then((res) => {
+          if (res.code === 200) {
+            if (res.data.itemList && res.data.itemList.length) {
+              this.chartData.series[0] = {
+                name: '停车场',
+                data: []
+              };
+              this.chartData.series[0].data = res.data.itemList.map((item) => {
+                return item.amt;
+              });
+              if (!this.chartData.categories.length) {
+                this.chartData.categories = res.data.itemList.map((item) => {
+                  return item.statisTime;
+                });
+              }
+              this.hasData = true;
+            } else {
+              this.hasData = false;
+            }
+						this.loading = false
+          }
+        });
+    }
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+.revenue {
+  background-color: #fff;
+  border-radius: 5px;
+
+  .empty {
+    padding: 15px;
+  }
+}
+</style>

+ 76 - 0
pages/operationalAnalysis/parkModel/components/revenueRanking.vue

@@ -0,0 +1,76 @@
+<!-- 路段/停车场营收排行 -->
+<template>
+	<view class="ranking">
+		<TableRanking :loading="loading" :title="title" :tableTh="tableTh" :tableData="tableData" @pageChange="pageChange"/>
+	</view>
+</template>
+
+<script>
+	import TableRanking from '@/components/tableRanking.vue'
+	export default {
+		components: {
+			TableRanking
+		},
+		props: {
+			title: {
+				type: String,
+				default: ''
+			},
+			tableTh: {
+				type: Array,
+				default: () => [
+					{ field: '路段编号', key: 'roadNo' },
+					{ field: '路段名称', key: 'roadName' },
+					{ field: '收益(元)', key: 'amt' }
+				]
+			}
+		},
+		data() {
+			return {
+				tableData: {
+					current: 1,
+					total: 0,
+					list: []
+				},
+				reportType: '',
+				queryDate: '',
+				loading: false
+			}
+		},
+		methods: {
+			getData({ reportType, queryDate }) {
+				this.reportType = reportType
+				this.queryDate = queryDate
+				this.tableData.current = 1
+				this.getList()
+			},
+			getList() {
+				this.loading = true
+				uni.$u.api.operationalAnalysisApi.getParkingLotRevenueDataApi({
+					pageNum: this.tableData.current,
+					pageSize: 10,
+					reportType: this.reportType,
+					queryDate: this.queryDate
+				}).then(res => {
+					if (res.code === 200) {
+						this.tableData.list = res.rows
+						this.tableData.total = res.total
+					}
+					this.loading = false
+				}).catch(() => {
+					this.loading = false
+				})
+			},
+			pageChange(current) {
+				this.tableData.current = current
+				this.getList()
+			}
+		}
+	}
+</script>
+<style lang="scss" scoped>
+	.ranking-title {
+		text-align: center;
+		margin-bottom: 10px;
+	}
+</style>

+ 180 - 0
pages/operationalAnalysis/parkModel/components/sectionAnalysis.vue

@@ -0,0 +1,180 @@
+<!-- 路段分析 -->
+<template>
+	<view class="section">
+		<!-- 营收趋势分析 -->
+		<view class="section-part">
+			<view class="section-part-title"><text>|</text>营收趋势分析</view>
+			<view class="section-part-content">
+				<ColumnChart v-if="revenueTrendsData.series[0].data.length" :chartData="revenueTrendsData" :title="title" :opts="opts1"/>
+				<view class="empty" v-else>
+					<u-empty></u-empty>
+				</view>
+			</view>
+		</view>
+		<view class="section-part">
+			<view class="section-part-title"><text>|</text>车流量统计</view>
+			<view class="section-part-content">
+				<ColumnChart v-if="trafficFlowData.series[0].data.length" :chartData="trafficFlowData" :title="title" :opts="opts2"/>
+				<view class="empty" v-else>
+					<u-empty></u-empty>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import ColumnChart from '@/components/columnChart.vue'
+	export default {
+		components: {
+			ColumnChart
+		},
+		props: {
+			title: {
+				type: String,
+				default: ''
+			}
+		},
+		data() {
+			return {
+				opts1: {
+					enableScroll: true,
+					xAxis: {
+						rotateLabel: true,
+						scrollShow: true,
+						itemCount: 8
+					},
+					yAxis: {
+						showTitle: true,
+						splitNumber: 5,
+						data: [{
+							title: '收益(元)',
+							titleOffsetY: -3
+						}]
+					},
+					legend: {
+						show: false
+					},
+					dataLabel: false,
+					padding: [20, 0, 10, 0],
+					extra: {
+						column: {
+							width: 20
+						}
+					}
+				},
+				opts2: {
+					enableScroll: true,
+					xAxis: {
+						rotateLabel: true,
+						scrollShow: true,
+						itemCount: 8
+					},
+					yAxis: {
+						showTitle: true,
+						splitNumber: 5,
+						data: [{
+							title: '车辆(辆)',
+							titleOffsetY: 0,
+							titleOffsetX: 10
+						}]
+					},
+					legend: {
+						show: false
+					},
+					dataLabel: false,
+					padding: [10, 0, 10, 0],
+					extra: {
+						column: {
+							width: 20
+						}
+					}
+				},
+				revenueTrendsData: {
+					categories: [],
+					series: [{
+						name: '',
+						data: []
+					}]
+				},
+				trafficFlowData: {
+					categories: [],
+					series: [{
+						name: '',
+						data: []
+					}]
+				}
+			}
+		},
+		methods: {
+			getData({ reportType, queryDate }) {
+				this.reportType = reportType
+				this.queryDate = queryDate
+				this.getRevenueTrendsData()
+				this.getRoadTrafficFlowData()
+			},
+			getRevenueTrendsData() {
+				uni.$u.api.operationalAnalysisApi.getRevenueTrendsDataApi({
+					reportType: this.reportType,
+					queryDate: this.queryDate
+				}).then(res => {
+					if (res.code === 200) {
+						if (res.data.itemList && res.data.itemList.length) {
+							this.revenueTrendsData.categories = res.data.itemList.map(item => {
+								return item.roadName
+							})
+							this.revenueTrendsData.series[0].data = res.data.itemList.map(item => {
+								return item.amt
+							})
+						} else {
+							this.revenueTrendsData.categories = []
+							this.revenueTrendsData.series[0].data = []
+						}
+					}
+				})
+			},
+			getRoadTrafficFlowData() {
+				uni.$u.api.operationalAnalysisApi.getRoadTrafficFlowDataApi({
+					reportType: this.reportType,
+					queryDate: this.queryDate
+				}).then(res => {
+					if (res.code === 200) {
+						if (res.data.itemList && res.data.itemList.length) {
+							this.trafficFlowData.categories = res.data.itemList.map(item => {
+								return item.roadName
+							})
+							this.trafficFlowData.series[0].data = res.data.itemList.map(item => {
+								return item.vehicleCount
+							})
+						} else {
+							this.trafficFlowData.categories = []
+							this.trafficFlowData.series[0].data = []
+						}
+					}
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.section {
+		&-part {
+			background-color: #fff;
+			border-radius: 5px;
+			margin-bottom: 10px;
+
+			&-title {
+				padding: 15px;
+
+				text {
+					color: #f00;
+					margin-right: 5px;
+				}
+			}
+		}
+		.empty {
+			padding: 15px;
+		}
+	}
+</style>

+ 180 - 0
pages/operationalAnalysis/parkModel/components/sourceOfPayment.vue

@@ -0,0 +1,180 @@
+<!-- 支付来源分析 -->
+<template>
+	<view class="revenue">
+		<view class="revenue-line">
+			<LineChart v-if="hasData" :chartData="chartData" :title="title" :opts="opts" />
+			<view class="empty" v-else>
+				<u-empty></u-empty>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import LineChart from '@/components/lineChart.vue'
+	export default {
+		components: {
+			LineChart
+		},
+		props: {
+			title: {
+				type: String,
+				default: ''
+			},
+			opts: {
+				type: Object,
+				default: () => {
+					return {
+						xAxis: {
+							rotateLabel: true
+						},
+						yAxis: {
+							showTitle: true,
+							splitNumber: 5,
+							data: [{
+								title: '元',
+								titleOffsetY: -5
+							}]
+						},
+						legend: {
+							show: true
+						},
+						dataLabel: false,
+						extra: {
+							column: {
+								width: 20
+							}
+						}
+					}
+				}
+			}
+		},
+		data() {
+			return {
+				paySourceList: [],
+				chartData: {
+					categories: [],
+					series: []
+				},
+				hasData: false
+			}
+		},
+		created() {
+			this.getDict()
+		},
+		methods: {
+			getData({
+				reportType,
+				queryDate
+			}) {
+				this.hasData = false
+				this.chartData.categories = []
+				this.chartData.series = []
+				this.getPaySourceData({
+					reportType,
+					queryDate
+				})
+			},
+			getDict() {
+				uni.$u.api.getDictApi({
+					type: 'pay_platform'
+				}).then(res => {
+					if (res.code === 200) {
+						this.paySourceList = res.data
+					}
+				})
+			},
+			getPaySourceData({
+				reportType,
+				queryDate
+			}) {
+				uni.$u.api.operationalAnalysisApi.getPaySourceDataApi({
+					reportType,
+					queryDate
+				}).then(res => {
+					if (res.code === 200) {
+						if (res.data.itemList && res.data.itemList.length) {
+							this.chartData.series[0] = {
+								name: '路段',
+								data: []
+							}
+							let cateList = []
+							res.data.itemList.forEach(item => {
+								cateList.push(this.getDictLabel(item.payPlatform))
+							})
+							this.chartData.categories = cateList
+							this.chartData.series[0].data = res.data.itemList.map(item => {
+								return item.amt
+							})
+						}
+						this.getParkingData({ reportType, queryDate })
+					}
+				})
+			},
+			getParkingData({
+				reportType,
+				queryDate
+			}) {
+				uni.$u.api.operationalAnalysisApi.getParkingPaySourceDataApi({
+					reportType,
+					queryDate
+				}).then(res => {
+					if (res.code === 200) {
+						if (res.data.itemList && res.data.itemList.length) {
+							if (this.chartData.series.length) {
+								this.chartData.series[1] = {
+									name: '停车场',
+									data: []
+								}
+								this.chartData.series[1].data = res.data.itemList.map(item => {
+									return item.amt
+								})
+							} else {
+								this.chartData.series[0] = {
+									name: '停车场',
+									data: []
+								}
+								this.chartData.series[0].data = res.data.itemList.map(item => {
+									return item.amt
+								})
+							}
+							if (!this.chartData.categories.length) {
+								let cateList = []
+								res.data.itemList.forEach(item => {
+									cateList.push(this.getDictLabel(item.payPlatform))
+								})
+								this.chartData.categories = cateList
+							}
+							this.hasData = true
+						} else if (this.chartData.series.length === 1) {
+							this.hasData = true
+						} else if (!this.chartData.series.length) {
+							this.hasData = false
+						}
+					}
+				})
+			},
+			getDictLabel(value) {
+				let name
+				this.paySourceList.forEach(item => {
+					if (item.dictValue == value) {
+						name = item.dictLabel
+					}
+				})
+				if (!name) name = '其他'
+				return name
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.revenue {
+		background-color: #fff;
+		border-radius: 5px;
+
+		.empty {
+			padding: 15px;
+		}
+	}
+</style>

+ 149 - 0
pages/operationalAnalysis/parkModel/components/tollCollectorPerformance.vue

@@ -0,0 +1,149 @@
+<!-- 收费员业绩 -->
+<template>
+	<view class="performance">
+		<template v-if="type === 'table'">
+			<TableRanking :loading="loading" :title="title" :tableTh="tableTh" :tableData="tableData"  @pageChange="pageChange"/>
+		</template>
+		<template v-else>
+			<LineChart v-if="chartData.series[0].data.length" :chartData="chartData" :title="title" :opts="opts"/>
+			<view class="empty" v-else>
+				<u-empty></u-empty>
+			</view>
+		</template>
+	</view>
+</template>
+
+<script>
+	import TableRanking from '@/components/tableRanking.vue'
+	import LineChart from '@/components/lineChart.vue'
+	export default {
+		components: {
+			TableRanking,
+			LineChart
+		},
+		props: {
+			type: {
+				type: String,
+				default: 'table'
+			},
+			title: {
+				type: String,
+				default: ''
+			},
+			tableTh: {
+				type: Array,
+				default: () => [
+					{ width: 100, field: '工号', key: 'payeeNo' },
+					{ width: 100, field: '姓名', key: 'payeeName' },
+					{ width: 100, field: '收益(元)', key: 'amt' }
+				]
+			},
+		},
+		data() {
+			return {
+				chartData: {
+					categories: [],
+					series: [{
+						name: '',
+						data: []
+					}]
+				},
+				tableData: {
+					current: 1,
+					total: 0,
+					list: []
+				},
+				reportType: '',
+				queryDate: '',
+				loading: false,
+				opts: {
+					enableScroll: true,
+					xAxis: {
+						rotateLabel: true,
+						scrollShow: true,
+						itemCount: 8
+					},
+					yAxis: {
+						showTitle: true,
+						splitNumber: 5,
+						data: [{
+							title: '元',
+							titleOffsetY: -3
+						}]
+					},
+					legend: {
+						show: false
+					},
+					dataLabel: false,
+					padding: [20, 10, 10, 10],
+					extra: {
+						column: {
+							width: 20
+						}
+					}
+				}
+			}
+		},
+		methods: {
+			getData({ reportType, queryDate }) {
+				if (this.type === 'table') {
+					this.tableData.current = 1
+					this.getTableData({ reportType, queryDate })
+				} else {
+					this.getChartData({ reportType, queryDate })
+				}
+			},
+			getTableData({ reportType, queryDate }) {
+				this.loading = true
+				uni.$u.api.operationalAnalysisApi.getTollCollectorPerformanceApi({
+					pageNum: this.tableData.current,
+					pageSize: 10,
+					reportType,
+					queryDate
+				}).then(res => {
+					if (res.code === 200) {
+						this.tableData.list = res.rows
+						this.tableData.total = res.total
+					}
+					this.loading = false
+				}).catch(() => {
+					this.loading = false
+				})
+			},
+			getChartData({ reportType, queryDate }) {
+				uni.$u.api.operationalAnalysisApi.getTollCollectorPerformanceApi({
+					reportType,
+					queryDate
+				}).then(res => {
+					if (res.code === 200) {
+						if (res.rows && res.rows.length) {
+							this.chartData.categories = res.rows.map(item => {
+								return item.payeeName
+							})
+							this.chartData.series[0].data = res.rows.map(item => {
+								return item.amt
+							})
+						} else {
+							this.chartData.categories = []
+							this.chartData.series[0].data = []
+						}
+					}
+				})
+			},
+			pageChange(current) {
+				this.tableData.current = current
+				this.getTableData()
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.performance {
+		background-color: #fff;
+		border-radius: 5px;
+		.empty {
+			padding: 15px;
+		}
+	}
+</style>

+ 152 - 0
pages/operationalAnalysis/parkModel/components/trafficFlow.vue

@@ -0,0 +1,152 @@
+<!-- 车流量分析 -->
+<template>
+	<view class="revenue">
+		<view class="revenue-line">
+			<LineChart v-if="hasData" :chartData="chartData" :title="title" :opts="opts" />
+			<view class="empty" v-else>
+				<u-empty></u-empty>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import LineChart from '@/components/lineChart.vue'
+	export default {
+		components: {
+			LineChart
+		},
+		props: {
+			title: {
+				type: String,
+				default: ''
+			},
+			opts: {
+				type: Object,
+				default: () => {
+					return {
+						enableScroll: true,
+						xAxis: {
+							rotateLabel: true,
+							scrollShow: true,
+							itemCount: 8
+						},
+						yAxis: {
+							showTitle: true,
+							splitNumber: 5,
+							data: [{
+								title: '辆',
+								titleOffsetY: -3
+							}]
+						},
+						legend: {
+							show: true
+						},
+						dataLabel: false,
+						padding: [20, 10, 10, 10],
+						extra: {
+							column: {
+								width: 20
+							}
+						}
+					}
+				}
+			}
+		},
+		data() {
+			return {
+				chartData: {
+					categories: [],
+					series: []
+				},
+				reportType: '',
+				queryDate: '',
+				hasData: false
+			}
+		},
+		methods: {
+			getData({
+				reportType,
+				queryDate
+			}) {
+				this.chartData.categories = []
+				this.chartData.series = []
+				this.reportType = reportType
+				this.queryDate = queryDate
+				this.hasData = false;
+				this.getRoadData({ reportType, queryDate });
+			},
+			getRoadData({ reportType, queryDate }) {
+				uni.$u.api.operationalAnalysisApi.getTrafficFlowDataApi({
+					reportType,
+					queryDate
+				}).then(res => {
+					if (res.code === 200) {
+						if (res.data.itemList && res.data.itemList.length) {
+							this.chartData.series[0] = {
+								name: '路段',
+								data: []
+							}
+							this.chartData.categories = res.data.itemList.map(item => {
+								return item.statisTime
+							})
+							this.chartData.series[0].data = res.data.itemList.map(item => {
+								return item.vehicleCount
+							})
+						}
+					}
+					this.getParkingData({ reportType, queryDate });
+				})
+			},
+			getParkingData({ reportType, queryDate }) {
+				uni.$u.api.operationalAnalysisApi.getParkingTrafficFlowDataApi({
+					reportType,
+					queryDate
+				}).then(res => {
+					if (res.code === 200) {
+						if (res.data.itemList && res.data.itemList.length) {
+							if (this.chartData.series.length) {
+								this.chartData.series[1] = {
+									name: '停车场',
+									data: []
+								}
+								this.chartData.series[1].data = res.data.itemList.map(item => {
+									return item.vehicleCount
+								})
+							} else {
+								this.chartData.series[0] = {
+									name: '停车场',
+									data: []
+								}
+								this.chartData.series[0].data = res.data.itemList.map(item => {
+									return item.vehicleCount
+								})
+							}
+							if (!this.chartData.categories.length) {
+								this.chartData.categories = res.data.itemList.map(item => {
+									return item.statisTime
+								})
+							}
+							this.hasData = true
+						} else if (this.chartData.series.length === 1) {
+							this.hasData = true
+						} else if (!this.chartData.series.length) {
+							this.hasData = false
+						}
+					}
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.revenue {
+		background-color: #fff;
+		border-radius: 5px;
+
+		.empty {
+			padding: 15px;
+		}
+	}
+</style>

+ 272 - 0
pages/operationalAnalysis/parkModel/index.vue

@@ -0,0 +1,272 @@
+<!--
+ * @Description: 运营分析停车场模块
+ * @Author: 空白格
+ * @Date: 2022-08-02 15:32:15
+ * @LastEditors: 空白格
+ * @LastEditTime: 2022-08-02 16:22:52
+ * @FilePath: \parking_operation\pages\operationalAnalysis\parkModel\index.vue
+ * @Copyright: Copyright (c) 2016~2022 by 空白格, All Rights Reserved. 
+-->
+<template>
+  <view class="analysis">
+    <view class="analysis-header">
+      <view class="analysis-header-left">&nbsp;</view>
+      <view class="analysis-header-right">
+        <view class="tab">
+          <view
+            class="tab-item"
+            v-for="(item, index) in tabList"
+            :key="index"
+            :class="{ active: tabCur === item.value }"
+            @click="tabClick(item)"
+          >{{ item.label }}</view>
+        </view>
+      </view>
+    </view>
+    <view class="analysis-main">
+      <template v-if="templateKey === 'parkingLotAnalysis'">
+        <parking-lot-analysis ref="parkingLotAnalysis" :title="title" />
+      </template>
+      <template v-else-if="templateKey === 'arrearsAnalysis'">
+        <arrears-analysis ref="arrearsAnalysis" :title="title" />
+      </template>
+      <template v-else-if="templateKey === 'revenueAnalysis'">
+        <revenue-analysis ref="revenueAnalysis" :title="title" />
+      </template>
+      <template v-else-if="templateKey === 'incomeAnalysis'">
+        <income-analysis ref="incomeAnalysis" :title="title"/>
+      </template>
+      <template v-else-if="templateKey === 'paymentMethod'">
+        <payment-method ref="paymentMethod" :title="title"/>
+      </template>
+    </view>
+    <!-- 年 -->
+    <u-picker
+      :show="yearPicker"
+      :columns="yearList"
+      :defaultIndex="defaultYear"
+      @confirm="yearConfirm"
+      @cancel="yearPicker = false"
+    ></u-picker>
+    <!-- 月 -->
+    <u-picker
+      :show="monthPicker"
+      :columns="monthList"
+      :defaultIndex="defaultMonth"
+      @confirm="monthConfirm"
+      @cancel="monthPicker = false"
+    ></u-picker>
+    <!-- 日 -->
+    <u-picker
+      :show="dayPicker"
+      :columns="dayList"
+      :defaultIndex="defaultDay"
+      @confirm="dayConfirm"
+      @cancel="dayPicker = false"
+    ></u-picker>
+  </view>
+</template>
+
+<script>
+import ParkingLotAnalysis from './components/parkingLotAnalysis.vue';
+import ArrearsAnalysis from './components/arrearsAnalysis.vue';
+import RevenueAnalysis from './components/revenueAnalysis.vue';
+import IncomeAnalysis from './components/incomeAnalysis.vue'
+import PaymentMethod from './components/paymentMethod.vue'
+export default {
+  components: {
+    ParkingLotAnalysis,
+    ArrearsAnalysis,
+    RevenueAnalysis,
+    IncomeAnalysis,
+    PaymentMethod
+  },
+  data() {
+    return {
+      tabList: [
+        {
+          label: '年',
+          value: 2
+        },
+        {
+          label: '月',
+          value: 1
+        },
+        {
+          label: '日',
+          value: 0
+        }
+      ],
+      tabCur: 2,
+      templateKey: '',
+      title: '',
+      // 参数
+      params: {
+        reportType: 2,
+        queryDate: ''
+      },
+      // 年
+      yearPicker: false,
+      yearList: this.getYearList(),
+      defaultYear: [4],
+      currentYear: '',
+      yearObj: {},
+      // 月
+      monthPicker: false,
+      monthList: this.getMonthList(),
+      defaultMonth: [],
+      currentMonth: '01',
+      monthObj: {},
+      // 日
+      dayPicker: false,
+      dayList: this.getDayList(),
+      defaultDay: [],
+      currentDay: '01',
+      dayObj: {}
+    };
+  },
+  onLoad(options) {
+    uni.setNavigationBarTitle({
+      title: options.title || '停车场分析'
+    });
+    this.templateKey = options.key;
+  },
+  onShow() {
+    this.defaultSetVal();
+  },
+  methods: {
+    defaultSetVal() {
+      this.currentYear = this.yearList[0][4].value;
+      this.title = this.yearList[0][4].text;
+      this.yearObj = this.yearList[0][4];
+      this.params.queryDate = `${this.currentYear}-${this.currentMonth}-${this.currentDay}`;
+      this.$nextTick(() => {
+        this.$refs[this.templateKey].getData(this.params);
+      });
+    },
+    getYearList() {
+      const date = new Date();
+      const year = date.getFullYear();
+      const list = [[]];
+      for (let i = year - 4; i < year + 1; i++) {
+        const obj = {
+          text: String(i),
+          value: String(i)
+        };
+        list[0].push(obj);
+      }
+      return list;
+    },
+    getMonthList() {
+      const date = new Date();
+      const month = date.getMonth();
+      const list = [[]];
+      for (let i = 1; i < 13; i++) {
+        const obj = {
+          text: String(i),
+          value: String(i)
+        };
+        if (i < 10) {
+          obj.text = '0' + i;
+          obj.value = '0' + i;
+        }
+        list[0].push(obj);
+      }
+      setTimeout(() => {
+        this.defaultMonth = [0];
+      }, 1000);
+      return list;
+    },
+    getDayList() {
+      const date = new Date();
+      const year = date.getFullYear();
+      let month = date.getMonth();
+      if (this.monthObj) {
+        month = parseInt(this.monthObj.value);
+      }
+      const day = date.getDate();
+      const dayLen = new Date(year, month, 0).getDate();
+      const list = [[]];
+      for (let i = 1; i < dayLen + 1; i++) {
+        const obj = {
+          text: String(i),
+          value: String(i)
+        };
+        if (i < 10) {
+          obj.text = '0' + i;
+          obj.value = '0' + i;
+        }
+        list[0].push(obj);
+      }
+      setTimeout(() => {
+        this.defaultDay = [0];
+      }, 1000);
+      return list;
+    },
+    /**
+     * 点击tab
+     * @param {Object} item
+     */
+    tabClick(item) {
+      this.tabCur = item.value;
+      switch (item.value) {
+        case 0:
+          this.dayPicker = true;
+          break;
+        case 1:
+          this.monthPicker = true;
+          break;
+        case 2:
+          this.yearPicker = true;
+          break;
+      }
+      this.params.reportType = this.tabCur;
+    },
+    yearConfirm(e) {
+      this.defaultYear = [e.indexs[0]];
+      this.title = e.value[0].text;
+      this.currentYear = e.value[0].value;
+      this.yearObj = e.value[0];
+      this.params.queryDate = `${this.currentYear}-${this.currentMonth}-${this.currentDay}`;
+      this.$nextTick(() => {
+        this.$refs[this.templateKey].getData(this.params);
+      });
+      this.yearPicker = false;
+    },
+    monthConfirm(e) {
+      this.defaultMonth = [e.indexs[0]];
+      this.currentMonth = e.value[0].value;
+      this.monthObj = e.value[0];
+      this.title = `${this.yearObj.text}-${this.monthObj.text}`;
+      this.params.queryDate = `${this.currentYear}-${this.currentMonth}-${this.currentDay}`;
+      this.$nextTick(() => {
+        this.$refs[this.templateKey].getData(this.params);
+      });
+      this.monthPicker = false;
+      this.dayList = this.getDayList();
+    },
+    dayConfirm(e) {
+      this.defaultDay = [e.indexs[0]];
+      this.title = e.value[0].text;
+      this.currentDay = e.value[0].value;
+      this.dayObj = e.value[0];
+      this.title = `${this.yearObj.text}-${this.monthObj.text}-${this.dayObj.text}`;
+      this.params.queryDate = `${this.currentYear}-${this.currentMonth}-${this.currentDay}`;
+      this.$nextTick(() => {
+        this.$refs[this.templateKey].getData(this.params);
+      });
+      this.dayPicker = false;
+    }
+  }
+};
+</script>
+
+<style lang="scss">
+page {
+  background-color: #1767f2;
+  min-height: calc(100vh - 44px);
+}
+</style>
+<style lang="scss" scoped>
+@import './../styles/analysis.scss';
+</style>

+ 120 - 0
pages/operationalAnalysis/roadModel/components/arrearsAnalysis.vue

@@ -0,0 +1,120 @@
+<!-- 欠费分析 -->
+<template>
+	<view class="arrears">
+		<view class="arrears-line">
+			<LineChart v-if="hasData" :chartData="chartData" :title="title" :opts="opts" />
+			<view class="empty" v-else>
+				<u-empty></u-empty>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import LineChart from '@/components/lineChart.vue'
+	export default {
+		components: {
+			LineChart
+		},
+		props: {
+			title: {
+				type: String,
+				default: ''
+			},
+			opts: {
+				type: Object,
+				default: () => {
+					return {
+						enableScroll: true,
+						xAxis: {
+							rotateLabel: true,
+							scrollShow: true,
+							itemCount: 8
+						},
+						yAxis: {
+							showTitle: true,
+							splitNumber: 5,
+							data: [{
+								title: '元',
+								titleOffsetY: -3
+							}]
+						},
+						legend: {
+							show: true
+						},
+						dataLabel: false,
+						padding: [20, 0, 10, 0],
+						extra: {
+							column: {
+								width: 20
+							}
+						}
+					}
+				}
+			}
+		},
+		data() {
+			return {
+				chartData: {
+					categories: [],
+					series: []
+				},
+				hasData: false
+			}
+		},
+		methods: {
+			getData({
+				reportType,
+				queryDate
+			}) {
+				this.hasData = false
+				this.chartData.categories = []
+				this.chartData.series = []
+				this.getRoadData({
+					reportType,
+					queryDate
+				})
+			},
+			getRoadData({
+				reportType,
+				queryDate
+			}) {
+				uni.$u.api.operationalAnalysisApi.getArrearsDataApi({
+					reportType,
+					queryDate
+				}).then(res => {
+					if (res.code === 200) {
+						if (res.data.itemList && res.data.itemList.length) {
+							this.chartData.series[0] = {
+								name: '路段',
+								data: []
+							}
+							this.chartData.categories = res.data.itemList.map(item => {
+								return item.statisTime
+							})
+							this.chartData.series[0].data = res.data.itemList.map(item => {
+								return item.amt
+							})
+						}
+						if (this.chartData.series.length && this.chartData.series[0].data.length) {
+							this.hasData = true
+						} else {
+							this.hasData = false
+						}
+					}
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.arrears {
+		background-color: #fff;
+		border-radius: 5px;
+
+		.empty {
+			padding: 15px;
+		}
+	}
+</style>

+ 182 - 0
pages/operationalAnalysis/roadModel/components/incomeAnalysis.vue

@@ -0,0 +1,182 @@
+<!-- 收入分析 -->
+<template>
+  <view class="revenue">
+    <view class="revenue-search">
+      <view class="revenue-search-item" @click="incomeTypePicker = true">
+        <u--input
+          placeholder="请输入内容"
+          v-model="searchContent.text"
+          suffixIcon="arrow-down"
+          :readonly="true"
+        ></u--input>
+      </view>
+      <view class="revenue-search-item">
+        <!-- <u-button text="搜索" type="primary" class="revenue-search-item-btn" @click="searchClick"></u-button> -->
+      </view>
+    </view>
+    <view class="revenue-line">
+      <ColumnChart
+        v-if="chartData.series[0].data.length"
+        :chartData="chartData"
+        :title="title"
+        :opts="opts"
+      />
+      <view class="empty" v-else>
+        <u-empty></u-empty>
+      </view>
+    </view>
+    <u-picker
+      :show="incomeTypePicker"
+      :columns="dictList"
+      @confirm="incomeTypeConfirm"
+      @cancel="incomeTypePicker = false"
+    ></u-picker>
+  </view>
+</template>
+
+<script>
+import ColumnChart from '@/components/columnChart.vue';
+export default {
+  components: {
+    ColumnChart
+  },
+  props: {
+    title: {
+      type: String,
+      default: ''
+    },
+    opts: {
+      type: Object,
+      default: () => {
+        return {
+          enableScroll: true,
+          xAxis: {
+            rotateLabel: false,
+            scrollShow: true,
+            itemCount: 8
+          },
+          yAxis: {
+            showTitle: true,
+            splitNumber: 5,
+            data: [
+              {
+                title: '元',
+                titleOffsetY: -3
+              }
+            ]
+          },
+          legend: {
+            show: false
+          },
+          dataLabel: false,
+          padding: [20, 0, 10, 0],
+          extra: {
+            column: {
+              width: 20
+            }
+          }
+        };
+      }
+    }
+  },
+  data() {
+    return {
+      chartData: {
+        categories: [[]],
+        series: [
+          {
+            name: '路段',
+            data: []
+          }
+        ]
+      },
+      searchContent: {
+        text: '',
+        value: ''
+      },
+      dictList: [[]],
+      incomeTypePicker: false,
+      reportType: '',
+      queryDate: ''
+    };
+  },
+  methods: {
+    getData({ reportType, queryDate }) {
+      this.reportType = reportType;
+      this.queryDate = queryDate;
+      this.getDict();
+    },
+    getDict() {
+      uni.$u.api.getDictApi({ type: 'income_type' }).then((res) => {
+        if (res.code === 200) {
+          let list = res.data.map((item) => {
+            return {
+              text: item.dictLabel,
+              value: item.dictValue
+            };
+          });
+          this.dictList = [list];
+          if (!this.searchContent.value) {
+            this.searchContent = this.dictList[0][0];
+          }
+          this.getIncomeData();
+        }
+      });
+    },
+    getIncomeData() {
+      this.chartData.categories = [];
+      this.chartData.series[0].data = [];
+      this.chartData.series[0].name = this.searchContent.text
+      uni.$u.api.operationalAnalysisApi
+        .getIncomeDataApi({
+          reportType: this.reportType,
+          queryDate: this.queryDate,
+          incomeType: this.searchContent.value
+        })
+        .then((res) => {
+          if (res.code === 200) {
+            if (res.data.itemList && res.data.itemList.length) {
+              this.chartData.categories = res.data.itemList.map((item) => {
+                return item.statisTime;
+              });
+              this.chartData.series[0].data = res.data.itemList.map((item) => {
+                return item.amt;
+              });
+            }
+          }
+        });
+    },
+    incomeTypeConfirm(e) {
+      this.searchContent = e.value[0];
+      this.getIncomeData();
+      this.incomeTypePicker = false;
+    },
+    searchClick() {
+      // this.getIncomeData()
+    }
+  }
+};
+</script>
+
+<style lang="scss" scoped>
+.revenue {
+  background-color: #fff;
+  border-radius: 5px;
+  &-search {
+    margin-bottom: 12px;
+    padding: 19px 15px 0 15px;
+    display: flex;
+    &-item {
+      width: 48%;
+      margin-right: 2%;
+      &-btn {
+        width: 50%;
+        height: 38px;
+      }
+    }
+  }
+}
+.empty {
+  padding: 15px;
+}
+</style>

+ 96 - 0
pages/operationalAnalysis/roadModel/components/paymentMethod.vue

@@ -0,0 +1,96 @@
+<!-- 支付占比分析分析 -->
+<template>
+	<view class="revenue-box">
+		<view class="revenue-line revenue">
+			<PieChart v-if="chartData.series[0].data.length" :chartData="chartData" :title="`路段(${title})`"/>
+			<view class="empty" v-else>
+				<u-empty></u-empty>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import PieChart from '@/components/pieChart.vue'
+	export default {
+		components: {
+			PieChart
+		},
+		props: {
+			title: {
+				type: String,
+				default: ''
+			}
+		},
+		data() {
+			return {
+				reportType: '',
+				queryDate: '',
+				paySourceList: [],
+				chartData: {
+					series: [{
+						data: []
+					}]
+				}
+			}
+		},
+		created() {
+			this.getDict()
+		},
+		methods: {
+			getData({ reportType, queryDate }) {
+				this.reportType = reportType
+				this.queryDate = queryDate
+				this.getPaymentWaysData()
+			},
+			getDict() {
+				uni.$u.api.getDictApi({  type: 'pay_source'}).then(res => {
+					if (res.code === 200) {
+						this.paySourceList = res.data
+					}
+				})
+			},
+			getPaymentWaysData() {
+				uni.$u.api.operationalAnalysisApi.getPaymentWaysDataApi({
+					reportType: this.reportType,
+					queryDate: this.queryDate
+				}).then(res => {
+					if (res.code === 200) {
+						if (res.data.itemList && res.data.itemList.length) {
+							let list = res.data.itemList.map(item => {
+								return {
+									name: this.getDictLabel(item.paySource),
+									value: item.amt
+								}
+							})
+							this.chartData.series[0].data = list
+						} else {
+							this.chartData.series[0].data = []
+						}
+					}
+				})
+			},
+			getDictLabel(value) {
+				let name
+				this.paySourceList.forEach(item => {
+					if (item.dictValue == value) {
+						name = item.dictLabel
+					}
+				})
+				if (!name) name = '其他'
+				return name
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.revenue {
+		background-color: #fff;
+		border-radius: 5px;
+		margin-bottom: 10px;
+		.empty {
+			padding: 15px;
+		}
+	}
+</style>

+ 140 - 0
pages/operationalAnalysis/roadModel/components/revenueAnalysis.vue

@@ -0,0 +1,140 @@
+<!-- 营收分析 -->
+<template>
+	<view class="revenue">
+		<template v-if="type === 'line'">
+			<view class="revenue-line">
+				<LineChart v-if="hasData"
+					:chartData="chartData" :title="title" :opts="opts" />
+				<view class="empty" v-else>
+					<u-empty></u-empty>
+				</view>
+			</view>
+		</template>
+		<template v-else>
+			<view class="revenue-line">
+				<ColumnChart v-if="hasData"
+					:chartData="chartData" :title="title" :opts="opts" />
+				<view class="empty" v-else>
+					<u-empty></u-empty>
+				</view>
+			</view>
+		</template>
+	</view>
+</template>
+
+<script>
+	import LineChart from '@/components/lineChart.vue'
+	import ColumnChart from '@/components/columnChart.vue'
+	export default {
+		components: {
+			LineChart,
+			ColumnChart
+		},
+		props: {
+			type: {
+				type: String,
+				default: 'line'
+			},
+			title: {
+				type: String,
+				default: ''
+			},
+			params: {
+				type: Object,
+				default: () => {}
+			}
+		},
+		data() {
+			return {
+				chartData: {
+					categories: [],
+					series: []
+				},
+				hasData: false,
+				opts: {
+					enableScroll: true,
+					tooltip: {
+						trigger: 'axis'
+					},
+					xAxis: {
+						rotateLabel: true,
+						scrollShow: true,
+						itemCount: 8
+					},
+					yAxis: {
+						showTitle: true,
+						splitNumber: 5,
+						data: [{
+							title: '收益(元)',
+							titleOffsetY: -3
+						}]
+					},
+					legend: {
+						show: true
+					},
+					dataLabel: false,
+					padding: [20, 10, 10, 10],
+					extra: {
+						column: {
+							width: 20
+						}
+					}
+				}
+			}
+		},
+		methods: {
+			/**
+			 * 获取数据
+			 */
+			getData({
+				reportType,
+				queryDate
+			}) {
+				this.hasData = false
+				this.chartData.categories = []
+				this.chartData.series = []
+				this.getRoadData({ reportType, queryDate })
+			},
+			/**
+			 * 路段数据
+			 */
+			getRoadData({ reportType, queryDate }) {
+				uni.$u.api.operationalAnalysisApi.getRevenueDataApi({
+					reportType,
+					queryDate
+				}).then(res => {
+					if (res.code === 200) {
+						if (res.data.itemList && res.data.itemList.length) {
+							this.chartData.series[0] = {
+								name: '路段',
+								data: []
+							}
+							this.chartData.categories = res.data.itemList.map(item => {
+								return item.statisTime
+							})
+							this.chartData.series[0].data = res.data.itemList.map(item => {
+								return item.amt
+							})
+						}
+						if (this.chartData.series.length && this.chartData.series[0].data.length) {
+							this.hasData = true
+						} else {
+							this.hasData = false
+						}
+					}
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.revenue {
+		background-color: #fff;
+		border-radius: 5px;
+
+		.empty {
+			padding: 15px;
+		}
+	}
+</style>

+ 76 - 0
pages/operationalAnalysis/roadModel/components/revenueRanking.vue

@@ -0,0 +1,76 @@
+<!-- 路段/停车场营收排行 -->
+<template>
+	<view class="ranking">
+		<TableRanking :loading="loading" :title="title" :tableTh="tableTh" :tableData="tableData" @pageChange="pageChange"/>
+	</view>
+</template>
+
+<script>
+	import TableRanking from '@/components/tableRanking.vue'
+	export default {
+		components: {
+			TableRanking
+		},
+		props: {
+			title: {
+				type: String,
+				default: ''
+			},
+			tableTh: {
+				type: Array,
+				default: () => [
+					{ field: '路段编号', key: 'roadNo' },
+					{ field: '路段名称', key: 'roadName' },
+					{ field: '收益(元)', key: 'amt' }
+				]
+			}
+		},
+		data() {
+			return {
+				tableData: {
+					current: 1,
+					total: 0,
+					list: []
+				},
+				reportType: '',
+				queryDate: '',
+				loading: false
+			}
+		},
+		methods: {
+			getData({ reportType, queryDate }) {
+				this.reportType = reportType
+				this.queryDate = queryDate
+				this.tableData.current = 1
+				this.getList()
+			},
+			getList() {
+				this.loading = true
+				uni.$u.api.operationalAnalysisApi.getParkingLotRevenueDataApi({
+					pageNum: this.tableData.current,
+					pageSize: 10,
+					reportType: this.reportType,
+					queryDate: this.queryDate
+				}).then(res => {
+					if (res.code === 200) {
+						this.tableData.list = res.rows
+						this.tableData.total = res.total
+					}
+					this.loading = false
+				}).catch(() => {
+					this.loading = false
+				})
+			},
+			pageChange(current) {
+				this.tableData.current = current
+				this.getList()
+			}
+		}
+	}
+</script>
+<style lang="scss" scoped>
+	.ranking-title {
+		text-align: center;
+		margin-bottom: 10px;
+	}
+</style>

+ 180 - 0
pages/operationalAnalysis/roadModel/components/sectionAnalysis.vue

@@ -0,0 +1,180 @@
+<!-- 路段分析 -->
+<template>
+	<view class="section">
+		<!-- 营收趋势分析 -->
+		<view class="section-part">
+			<view class="section-part-title"><text>|</text>营收趋势分析</view>
+			<view class="section-part-content">
+				<ColumnChart v-if="revenueTrendsData.series[0].data.length" :chartData="revenueTrendsData" :title="title" :opts="opts1"/>
+				<view class="empty" v-else>
+					<u-empty></u-empty>
+				</view>
+			</view>
+		</view>
+		<view class="section-part">
+			<view class="section-part-title"><text>|</text>车流量统计</view>
+			<view class="section-part-content">
+				<ColumnChart v-if="trafficFlowData.series[0].data.length" :chartData="trafficFlowData" :title="title" :opts="opts2"/>
+				<view class="empty" v-else>
+					<u-empty></u-empty>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import ColumnChart from '@/components/columnChart.vue'
+	export default {
+		components: {
+			ColumnChart
+		},
+		props: {
+			title: {
+				type: String,
+				default: ''
+			}
+		},
+		data() {
+			return {
+				opts1: {
+					enableScroll: true,
+					xAxis: {
+						rotateLabel: true,
+						scrollShow: true,
+						itemCount: 8
+					},
+					yAxis: {
+						showTitle: true,
+						splitNumber: 5,
+						data: [{
+							title: '收益(元)',
+							titleOffsetY: -3
+						}]
+					},
+					legend: {
+						show: false
+					},
+					dataLabel: false,
+					padding: [20, 0, 10, 0],
+					extra: {
+						column: {
+							width: 20
+						}
+					}
+				},
+				opts2: {
+					enableScroll: true,
+					xAxis: {
+						rotateLabel: true,
+						scrollShow: true,
+						itemCount: 8
+					},
+					yAxis: {
+						showTitle: true,
+						splitNumber: 5,
+						data: [{
+							title: '车辆(辆)',
+							titleOffsetY: 0,
+							titleOffsetX: 10
+						}]
+					},
+					legend: {
+						show: false
+					},
+					dataLabel: false,
+					padding: [10, 0, 10, 0],
+					extra: {
+						column: {
+							width: 20
+						}
+					}
+				},
+				revenueTrendsData: {
+					categories: [],
+					series: [{
+						name: '',
+						data: []
+					}]
+				},
+				trafficFlowData: {
+					categories: [],
+					series: [{
+						name: '',
+						data: []
+					}]
+				}
+			}
+		},
+		methods: {
+			getData({ reportType, queryDate }) {
+				this.reportType = reportType
+				this.queryDate = queryDate
+				this.getRevenueTrendsData()
+				this.getRoadTrafficFlowData()
+			},
+			getRevenueTrendsData() {
+				uni.$u.api.operationalAnalysisApi.getRevenueTrendsDataApi({
+					reportType: this.reportType,
+					queryDate: this.queryDate
+				}).then(res => {
+					if (res.code === 200) {
+						if (res.data.itemList && res.data.itemList.length) {
+							this.revenueTrendsData.categories = res.data.itemList.map(item => {
+								return item.roadName
+							})
+							this.revenueTrendsData.series[0].data = res.data.itemList.map(item => {
+								return item.amt
+							})
+						} else {
+							this.revenueTrendsData.categories = []
+							this.revenueTrendsData.series[0].data = []
+						}
+					}
+				})
+			},
+			getRoadTrafficFlowData() {
+				uni.$u.api.operationalAnalysisApi.getRoadTrafficFlowDataApi({
+					reportType: this.reportType,
+					queryDate: this.queryDate
+				}).then(res => {
+					if (res.code === 200) {
+						if (res.data.itemList && res.data.itemList.length) {
+							this.trafficFlowData.categories = res.data.itemList.map(item => {
+								return item.roadName
+							})
+							this.trafficFlowData.series[0].data = res.data.itemList.map(item => {
+								return item.vehicleCount
+							})
+						} else {
+							this.trafficFlowData.categories = []
+							this.trafficFlowData.series[0].data = []
+						}
+					}
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.section {
+		&-part {
+			background-color: #fff;
+			border-radius: 5px;
+			margin-bottom: 10px;
+
+			&-title {
+				padding: 15px;
+
+				text {
+					color: #f00;
+					margin-right: 5px;
+				}
+			}
+		}
+		.empty {
+			padding: 15px;
+		}
+	}
+</style>

+ 180 - 0
pages/operationalAnalysis/roadModel/components/sourceOfPayment.vue

@@ -0,0 +1,180 @@
+<!-- 支付来源分析 -->
+<template>
+	<view class="revenue">
+		<view class="revenue-line">
+			<LineChart v-if="hasData" :chartData="chartData" :title="title" :opts="opts" />
+			<view class="empty" v-else>
+				<u-empty></u-empty>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import LineChart from '@/components/lineChart.vue'
+	export default {
+		components: {
+			LineChart
+		},
+		props: {
+			title: {
+				type: String,
+				default: ''
+			},
+			opts: {
+				type: Object,
+				default: () => {
+					return {
+						xAxis: {
+							rotateLabel: true
+						},
+						yAxis: {
+							showTitle: true,
+							splitNumber: 5,
+							data: [{
+								title: '元',
+								titleOffsetY: -5
+							}]
+						},
+						legend: {
+							show: true
+						},
+						dataLabel: false,
+						extra: {
+							column: {
+								width: 20
+							}
+						}
+					}
+				}
+			}
+		},
+		data() {
+			return {
+				paySourceList: [],
+				chartData: {
+					categories: [],
+					series: []
+				},
+				hasData: false
+			}
+		},
+		created() {
+			this.getDict()
+		},
+		methods: {
+			getData({
+				reportType,
+				queryDate
+			}) {
+				this.hasData = false
+				this.chartData.categories = []
+				this.chartData.series = []
+				this.getPaySourceData({
+					reportType,
+					queryDate
+				})
+			},
+			getDict() {
+				uni.$u.api.getDictApi({
+					type: 'pay_platform'
+				}).then(res => {
+					if (res.code === 200) {
+						this.paySourceList = res.data
+					}
+				})
+			},
+			getPaySourceData({
+				reportType,
+				queryDate
+			}) {
+				uni.$u.api.operationalAnalysisApi.getPaySourceDataApi({
+					reportType,
+					queryDate
+				}).then(res => {
+					if (res.code === 200) {
+						if (res.data.itemList && res.data.itemList.length) {
+							this.chartData.series[0] = {
+								name: '路段',
+								data: []
+							}
+							let cateList = []
+							res.data.itemList.forEach(item => {
+								cateList.push(this.getDictLabel(item.payPlatform))
+							})
+							this.chartData.categories = cateList
+							this.chartData.series[0].data = res.data.itemList.map(item => {
+								return item.amt
+							})
+						}
+						this.getParkingData({ reportType, queryDate })
+					}
+				})
+			},
+			getParkingData({
+				reportType,
+				queryDate
+			}) {
+				uni.$u.api.operationalAnalysisApi.getParkingPaySourceDataApi({
+					reportType,
+					queryDate
+				}).then(res => {
+					if (res.code === 200) {
+						if (res.data.itemList && res.data.itemList.length) {
+							if (this.chartData.series.length) {
+								this.chartData.series[1] = {
+									name: '停车场',
+									data: []
+								}
+								this.chartData.series[1].data = res.data.itemList.map(item => {
+									return item.amt
+								})
+							} else {
+								this.chartData.series[0] = {
+									name: '停车场',
+									data: []
+								}
+								this.chartData.series[0].data = res.data.itemList.map(item => {
+									return item.amt
+								})
+							}
+							if (!this.chartData.categories.length) {
+								let cateList = []
+								res.data.itemList.forEach(item => {
+									cateList.push(this.getDictLabel(item.payPlatform))
+								})
+								this.chartData.categories = cateList
+							}
+							this.hasData = true
+						} else if (this.chartData.series.length === 1) {
+							this.hasData = true
+						} else if (!this.chartData.series.length) {
+							this.hasData = false
+						}
+					}
+				})
+			},
+			getDictLabel(value) {
+				let name
+				this.paySourceList.forEach(item => {
+					if (item.dictValue == value) {
+						name = item.dictLabel
+					}
+				})
+				if (!name) name = '其他'
+				return name
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.revenue {
+		background-color: #fff;
+		border-radius: 5px;
+
+		.empty {
+			padding: 15px;
+		}
+	}
+</style>

+ 149 - 0
pages/operationalAnalysis/roadModel/components/tollCollectorPerformance.vue

@@ -0,0 +1,149 @@
+<!-- 收费员业绩 -->
+<template>
+	<view class="performance">
+		<template v-if="type === 'table'">
+			<TableRanking :loading="loading" :title="title" :tableTh="tableTh" :tableData="tableData"  @pageChange="pageChange"/>
+		</template>
+		<template v-else>
+			<LineChart v-if="chartData.series[0].data.length" :chartData="chartData" :title="title" :opts="opts"/>
+			<view class="empty" v-else>
+				<u-empty></u-empty>
+			</view>
+		</template>
+	</view>
+</template>
+
+<script>
+	import TableRanking from '@/components/tableRanking.vue'
+	import LineChart from '@/components/lineChart.vue'
+	export default {
+		components: {
+			TableRanking,
+			LineChart
+		},
+		props: {
+			type: {
+				type: String,
+				default: 'table'
+			},
+			title: {
+				type: String,
+				default: ''
+			},
+			tableTh: {
+				type: Array,
+				default: () => [
+					{ width: 100, field: '工号', key: 'payeeNo' },
+					{ width: 100, field: '姓名', key: 'payeeName' },
+					{ width: 100, field: '收益(元)', key: 'amt' }
+				]
+			},
+		},
+		data() {
+			return {
+				chartData: {
+					categories: [],
+					series: [{
+						name: '',
+						data: []
+					}]
+				},
+				tableData: {
+					current: 1,
+					total: 0,
+					list: []
+				},
+				reportType: '',
+				queryDate: '',
+				loading: false,
+				opts: {
+					enableScroll: true,
+					xAxis: {
+						rotateLabel: true,
+						scrollShow: true,
+						itemCount: 8
+					},
+					yAxis: {
+						showTitle: true,
+						splitNumber: 5,
+						data: [{
+							title: '元',
+							titleOffsetY: -3
+						}]
+					},
+					legend: {
+						show: false
+					},
+					dataLabel: false,
+					padding: [20, 10, 10, 10],
+					extra: {
+						column: {
+							width: 20
+						}
+					}
+				}
+			}
+		},
+		methods: {
+			getData({ reportType, queryDate }) {
+				if (this.type === 'table') {
+					this.tableData.current = 1
+					this.getTableData({ reportType, queryDate })
+				} else {
+					this.getChartData({ reportType, queryDate })
+				}
+			},
+			getTableData({ reportType, queryDate }) {
+				this.loading = true
+				uni.$u.api.operationalAnalysisApi.getTollCollectorPerformanceApi({
+					pageNum: this.tableData.current,
+					pageSize: 10,
+					reportType,
+					queryDate
+				}).then(res => {
+					if (res.code === 200) {
+						this.tableData.list = res.rows
+						this.tableData.total = res.total
+					}
+					this.loading = false
+				}).catch(() => {
+					this.loading = false
+				})
+			},
+			getChartData({ reportType, queryDate }) {
+				uni.$u.api.operationalAnalysisApi.getTollCollectorPerformanceApi({
+					reportType,
+					queryDate
+				}).then(res => {
+					if (res.code === 200) {
+						if (res.rows && res.rows.length) {
+							this.chartData.categories = res.rows.map(item => {
+								return item.payeeName
+							})
+							this.chartData.series[0].data = res.rows.map(item => {
+								return item.amt
+							})
+						} else {
+							this.chartData.categories = []
+							this.chartData.series[0].data = []
+						}
+					}
+				})
+			},
+			pageChange(current) {
+				this.tableData.current = current
+				this.getTableData()
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.performance {
+		background-color: #fff;
+		border-radius: 5px;
+		.empty {
+			padding: 15px;
+		}
+	}
+</style>

+ 152 - 0
pages/operationalAnalysis/roadModel/components/trafficFlow.vue

@@ -0,0 +1,152 @@
+<!-- 车流量分析 -->
+<template>
+	<view class="revenue">
+		<view class="revenue-line">
+			<LineChart v-if="hasData" :chartData="chartData" :title="title" :opts="opts" />
+			<view class="empty" v-else>
+				<u-empty></u-empty>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import LineChart from '@/components/lineChart.vue'
+	export default {
+		components: {
+			LineChart
+		},
+		props: {
+			title: {
+				type: String,
+				default: ''
+			},
+			opts: {
+				type: Object,
+				default: () => {
+					return {
+						enableScroll: true,
+						xAxis: {
+							rotateLabel: true,
+							scrollShow: true,
+							itemCount: 8
+						},
+						yAxis: {
+							showTitle: true,
+							splitNumber: 5,
+							data: [{
+								title: '辆',
+								titleOffsetY: -3
+							}]
+						},
+						legend: {
+							show: true
+						},
+						dataLabel: false,
+						padding: [20, 10, 10, 10],
+						extra: {
+							column: {
+								width: 20
+							}
+						}
+					}
+				}
+			}
+		},
+		data() {
+			return {
+				chartData: {
+					categories: [],
+					series: []
+				},
+				reportType: '',
+				queryDate: '',
+				hasData: false
+			}
+		},
+		methods: {
+			getData({
+				reportType,
+				queryDate
+			}) {
+				this.chartData.categories = []
+				this.chartData.series = []
+				this.reportType = reportType
+				this.queryDate = queryDate
+				this.hasData = false;
+				this.getRoadData({ reportType, queryDate });
+			},
+			getRoadData({ reportType, queryDate }) {
+				uni.$u.api.operationalAnalysisApi.getTrafficFlowDataApi({
+					reportType,
+					queryDate
+				}).then(res => {
+					if (res.code === 200) {
+						if (res.data.itemList && res.data.itemList.length) {
+							this.chartData.series[0] = {
+								name: '路段',
+								data: []
+							}
+							this.chartData.categories = res.data.itemList.map(item => {
+								return item.statisTime
+							})
+							this.chartData.series[0].data = res.data.itemList.map(item => {
+								return item.vehicleCount
+							})
+						}
+					}
+					this.getParkingData({ reportType, queryDate });
+				})
+			},
+			getParkingData({ reportType, queryDate }) {
+				uni.$u.api.operationalAnalysisApi.getParkingTrafficFlowDataApi({
+					reportType,
+					queryDate
+				}).then(res => {
+					if (res.code === 200) {
+						if (res.data.itemList && res.data.itemList.length) {
+							if (this.chartData.series.length) {
+								this.chartData.series[1] = {
+									name: '停车场',
+									data: []
+								}
+								this.chartData.series[1].data = res.data.itemList.map(item => {
+									return item.vehicleCount
+								})
+							} else {
+								this.chartData.series[0] = {
+									name: '停车场',
+									data: []
+								}
+								this.chartData.series[0].data = res.data.itemList.map(item => {
+									return item.vehicleCount
+								})
+							}
+							if (!this.chartData.categories.length) {
+								this.chartData.categories = res.data.itemList.map(item => {
+									return item.statisTime
+								})
+							}
+							this.hasData = true
+						} else if (this.chartData.series.length === 1) {
+							this.hasData = true
+						} else if (!this.chartData.series.length) {
+							this.hasData = false
+						}
+					}
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.revenue {
+		background-color: #fff;
+		border-radius: 5px;
+
+		.empty {
+			padding: 15px;
+		}
+	}
+</style>

+ 272 - 0
pages/operationalAnalysis/roadModel/index.vue

@@ -0,0 +1,272 @@
+<!--
+ * @Description: 运营分析路段模块
+ * @Author: 空白格
+ * @Date: 2022-08-02 16:47:29
+ * @LastEditors: 空白格
+ * @LastEditTime: 2022-08-02 17:16:28
+ * @FilePath: \parking_operation\pages\operationalAnalysis\roadModel\index.vue
+ * @Copyright: Copyright (c) 2016~2022 by 空白格, All Rights Reserved. 
+-->
+<template>
+  <view class="analysis">
+    <view class="analysis-header">
+      <view class="analysis-header-left">&nbsp;</view>
+      <view class="analysis-header-right">
+        <view class="tab">
+          <view
+            class="tab-item"
+            v-for="(item, index) in tabList"
+            :key="index"
+            :class="{ active: tabCur === item.value }"
+            @click="tabClick(item)"
+          >{{ item.label }}</view>
+        </view>
+      </view>
+    </view>
+    <view class="analysis-main">
+      <template v-if="templateKey === 'sectionAnalysis'">
+        <section-analysis ref="sectionAnalysis" :title="title" />
+      </template>
+      <template v-else-if="templateKey === 'arrearsAnalysis'">
+        <arrears-analysis ref="arrearsAnalysis" :title="title" />
+      </template>
+      <template v-else-if="templateKey === 'revenueAnalysis'">
+        <revenue-analysis ref="revenueAnalysis" :title="title" />
+      </template>
+      <template v-else-if="templateKey === 'incomeAnalysis'">
+        <income-analysis ref="incomeAnalysis" :title="title" />
+      </template>
+      <template v-else-if="templateKey === 'paymentMethod'">
+        <payment-method ref="paymentMethod" :title="title" />
+      </template>
+    </view>
+    <!-- 年 -->
+    <u-picker
+      :show="yearPicker"
+      :columns="yearList"
+      :defaultIndex="defaultYear"
+      @confirm="yearConfirm"
+      @cancel="yearPicker = false"
+    ></u-picker>
+    <!-- 月 -->
+    <u-picker
+      :show="monthPicker"
+      :columns="monthList"
+      :defaultIndex="defaultMonth"
+      @confirm="monthConfirm"
+      @cancel="monthPicker = false"
+    ></u-picker>
+    <!-- 日 -->
+    <u-picker
+      :show="dayPicker"
+      :columns="dayList"
+      :defaultIndex="defaultDay"
+      @confirm="dayConfirm"
+      @cancel="dayPicker = false"
+    ></u-picker>
+  </view>
+</template>
+
+<script>
+import SectionAnalysis from './components/sectionAnalysis.vue';
+import ArrearsAnalysis from './components/arrearsAnalysis.vue';
+import RevenueAnalysis from './components/revenueAnalysis.vue';
+import IncomeAnalysis from './components/incomeAnalysis.vue';
+import PaymentMethod from './components/paymentMethod.vue';
+export default {
+  components: {
+    SectionAnalysis,
+    ArrearsAnalysis,
+    RevenueAnalysis,
+    IncomeAnalysis,
+    PaymentMethod
+  },
+  data() {
+    return {
+      tabList: [
+        {
+          label: '年',
+          value: 2
+        },
+        {
+          label: '月',
+          value: 1
+        },
+        {
+          label: '日',
+          value: 0
+        }
+      ],
+      tabCur: 2,
+      templateKey: '',
+      title: '',
+      // 参数
+      params: {
+        reportType: 2,
+        queryDate: ''
+      },
+      // 年
+      yearPicker: false,
+      yearList: this.getYearList(),
+      defaultYear: [4],
+      currentYear: '',
+      yearObj: {},
+      // 月
+      monthPicker: false,
+      monthList: this.getMonthList(),
+      defaultMonth: [],
+      currentMonth: '01',
+      monthObj: {},
+      // 日
+      dayPicker: false,
+      dayList: this.getDayList(),
+      defaultDay: [],
+      currentDay: '01',
+      dayObj: {}
+    };
+  },
+  onLoad(options) {
+    uni.setNavigationBarTitle({
+      title: options.title || '路段分析'
+    });
+    this.templateKey = options.key;
+  },
+  onShow() {
+    this.defaultSetVal();
+  },
+  methods: {
+    defaultSetVal() {
+      this.currentYear = this.yearList[0][4].value;
+      this.title = this.yearList[0][4].text;
+      this.yearObj = this.yearList[0][4];
+      this.params.queryDate = `${this.currentYear}-${this.currentMonth}-${this.currentDay}`;
+      this.$nextTick(() => {
+        this.$refs[this.templateKey].getData(this.params);
+      });
+    },
+    getYearList() {
+      const date = new Date();
+      const year = date.getFullYear();
+      const list = [[]];
+      for (let i = year - 4; i < year + 1; i++) {
+        const obj = {
+          text: String(i),
+          value: String(i)
+        };
+        list[0].push(obj);
+      }
+      return list;
+    },
+    getMonthList() {
+      const date = new Date();
+      const month = date.getMonth();
+      const list = [[]];
+      for (let i = 1; i < 13; i++) {
+        const obj = {
+          text: String(i),
+          value: String(i)
+        };
+        if (i < 10) {
+          obj.text = '0' + i;
+          obj.value = '0' + i;
+        }
+        list[0].push(obj);
+      }
+      setTimeout(() => {
+        this.defaultMonth = [0];
+      }, 1000);
+      return list;
+    },
+    getDayList() {
+      const date = new Date();
+      const year = date.getFullYear();
+      let month = date.getMonth();
+      if (this.monthObj) {
+        month = parseInt(this.monthObj.value);
+      }
+      const day = date.getDate();
+      const dayLen = new Date(year, month, 0).getDate();
+      const list = [[]];
+      for (let i = 1; i < dayLen + 1; i++) {
+        const obj = {
+          text: String(i),
+          value: String(i)
+        };
+        if (i < 10) {
+          obj.text = '0' + i;
+          obj.value = '0' + i;
+        }
+        list[0].push(obj);
+      }
+      setTimeout(() => {
+        this.defaultDay = [0];
+      }, 1000);
+      return list;
+    },
+    /**
+     * 点击tab
+     * @param {Object} item
+     */
+    tabClick(item) {
+      this.tabCur = item.value;
+      switch (item.value) {
+        case 0:
+          this.dayPicker = true;
+          break;
+        case 1:
+          this.monthPicker = true;
+          break;
+        case 2:
+          this.yearPicker = true;
+          break;
+      }
+      this.params.reportType = this.tabCur;
+    },
+    yearConfirm(e) {
+      this.defaultYear = [e.indexs[0]];
+      this.title = e.value[0].text;
+      this.currentYear = e.value[0].value;
+      this.yearObj = e.value[0];
+      this.params.queryDate = `${this.currentYear}-${this.currentMonth}-${this.currentDay}`;
+      this.$nextTick(() => {
+        this.$refs[this.templateKey].getData(this.params);
+      });
+      this.yearPicker = false;
+    },
+    monthConfirm(e) {
+      this.defaultMonth = [e.indexs[0]];
+      this.currentMonth = e.value[0].value;
+      this.monthObj = e.value[0];
+      this.title = `${this.yearObj.text}-${this.monthObj.text}`;
+      this.params.queryDate = `${this.currentYear}-${this.currentMonth}-${this.currentDay}`;
+      this.$nextTick(() => {
+        this.$refs[this.templateKey].getData(this.params);
+      });
+      this.monthPicker = false;
+      this.dayList = this.getDayList();
+    },
+    dayConfirm(e) {
+      this.defaultDay = [e.indexs[0]];
+      this.title = e.value[0].text;
+      this.currentDay = e.value[0].value;
+      this.dayObj = e.value[0];
+      this.title = `${this.yearObj.text}-${this.monthObj.text}-${this.dayObj.text}`;
+      this.params.queryDate = `${this.currentYear}-${this.currentMonth}-${this.currentDay}`;
+      this.$nextTick(() => {
+        this.$refs[this.templateKey].getData(this.params);
+      });
+      this.dayPicker = false;
+    }
+  }
+};
+</script>
+
+<style lang="scss">
+page {
+  background-color: #1767f2;
+  min-height: calc(100vh - 44px);
+}
+</style>
+<style lang="scss" scoped>
+@import './../styles/analysis.scss';
+</style>

+ 35 - 0
pages/operationalAnalysis/styles/analysis.scss

@@ -0,0 +1,35 @@
+.analysis {
+  padding: 15px;
+  font-family: PingFangSC-Regular, PingFang SC;
+  &-header {
+    background-color: #fff;
+    border-radius: 5px;
+    padding: 15px;
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin-bottom: 10px;
+    &-right {
+      .tab {
+        display: flex;
+        border: solid 1px #1767f2;
+        &-item {
+          width: 40px;
+          height: 28px;
+          line-height: 28px;
+          text-align: center;
+          border-right: solid 1px #1767f2;
+          color: #1767f2;
+          font-size: 16px;
+          &:last-child {
+            border-right: none;
+          }
+        }
+        .active {
+          background-color: #1767f2;
+          color: #fff;
+        }
+      }
+    }
+  }
+}

+ 1 - 1
pages/patrolManagement/deviceAbnormalRecords/deviceAbnormalRecords.vue

@@ -29,7 +29,7 @@
 			return {
 				recordList: [],
 				status: 'loadmore',
-				page: 1
+				page: 1,
 			}
 		},
 		onShow() {

Datei-Diff unterdrückt, da er zu groß ist
+ 23 - 0
static/icons/operationalAnalysisIcons/arrearage-analysis-icon.svg


Datei-Diff unterdrückt, da er zu groß ist
+ 21 - 0
static/icons/operationalAnalysisIcons/payment-method-icon.svg


Datei-Diff unterdrückt, da er zu groß ist
+ 21 - 0
static/icons/operationalAnalysisIcons/revenue-analysis-icon.svg


Datei-Diff unterdrückt, da er zu groß ist
+ 21 - 0
static/icons/operationalAnalysisIcons/section-analysis-icon.svg


Datei-Diff unterdrückt, da er zu groß ist
+ 21 - 0
static/icons/operationalAnalysisIcons/shouru-analysis-icon.svg