Commit a30577122180ed8b2a6bb4820d4bfef99655295b
1 parent
eafabeed
完成在场车辆和车辆进出场记录
Showing
8 changed files
with
822 additions
and
0 deletions
src/api/car/carInManageApi.js
0 → 100644
| 1 | +import request from '@/utils/request' | |
| 2 | + | |
| 3 | +// 获取停车场区域列表 | |
| 4 | +export function listParkingAreas(params) { | |
| 5 | + return new Promise((resolve, reject) => { | |
| 6 | + request({ | |
| 7 | + url: '/parkingArea.listParkingAreas', | |
| 8 | + method: 'get', | |
| 9 | + params | |
| 10 | + }).then(response => { | |
| 11 | + const res = response.data | |
| 12 | + resolve(res) | |
| 13 | + }).catch(error => { | |
| 14 | + reject(error) | |
| 15 | + }) | |
| 16 | + }) | |
| 17 | +} | |
| 18 | + | |
| 19 | +// 获取在场车辆列表 | |
| 20 | +export function listCarIns(params) { | |
| 21 | + return new Promise((resolve, reject) => { | |
| 22 | + request({ | |
| 23 | + url: '/iot.getOpenApi', | |
| 24 | + method: 'get', | |
| 25 | + params | |
| 26 | + }).then(response => { | |
| 27 | + const res = response.data | |
| 28 | + if (res.code === 0) { | |
| 29 | + resolve(res) | |
| 30 | + } else { | |
| 31 | + reject(new Error(res.msg || '获取在场车辆失败')) | |
| 32 | + } | |
| 33 | + }).catch(error => { | |
| 34 | + reject(error) | |
| 35 | + }) | |
| 36 | + }) | |
| 37 | +} | |
| 0 | 38 | \ No newline at end of file | ... | ... |
src/api/car/carInoutManageApi.js
0 → 100644
| 1 | +import request from '@/utils/request' | |
| 2 | +import { getCommunityId } from '@/api/community/communityApi' | |
| 3 | + | |
| 4 | +// 获取停车场区域列表 | |
| 5 | +export function listParkingAreas(params) { | |
| 6 | + return new Promise((resolve, reject) => { | |
| 7 | + const communityId = getCommunityId() | |
| 8 | + request({ | |
| 9 | + url: '/parkingArea.listParkingAreas', | |
| 10 | + method: 'get', | |
| 11 | + params: { | |
| 12 | + ...params, | |
| 13 | + communityId | |
| 14 | + } | |
| 15 | + }).then(response => { | |
| 16 | + const res = response.data | |
| 17 | + resolve(res) | |
| 18 | + }).catch(error => { | |
| 19 | + reject(error) | |
| 20 | + }) | |
| 21 | + }) | |
| 22 | +} | |
| 23 | + | |
| 24 | +// 获取进出场记录列表 | |
| 25 | +export function listCarInouts(params) { | |
| 26 | + return new Promise((resolve, reject) => { | |
| 27 | + const communityId = getCommunityId() | |
| 28 | + request({ | |
| 29 | + url: '/iot.getOpenApi', | |
| 30 | + method: 'get', | |
| 31 | + params: { | |
| 32 | + ...params, | |
| 33 | + communityId | |
| 34 | + } | |
| 35 | + }).then(response => { | |
| 36 | + const res = response.data | |
| 37 | + if (res.code === 0) { | |
| 38 | + resolve(res) | |
| 39 | + } else { | |
| 40 | + reject(new Error(res.msg || '获取进出场记录失败')) | |
| 41 | + } | |
| 42 | + }).catch(error => { | |
| 43 | + reject(error) | |
| 44 | + }) | |
| 45 | + }) | |
| 46 | +} | |
| 0 | 47 | \ No newline at end of file | ... | ... |
src/i18n/index.js
| ... | ... | @@ -151,6 +151,8 @@ import { messages as listOwnerCarMessages } from '../views/car/listOwnerCarLang' |
| 151 | 151 | import { messages as hireParkingSpaceMessages } from '../views/car/hireParkingSpaceLang' |
| 152 | 152 | import { messages as carAddParkingSpaceMessages } from '../views/car/carAddParkingSpaceLang' |
| 153 | 153 | import { messages as buyCarMonthCardMessages } from '../views/fee/buyCarMonthCardLang' |
| 154 | +import { messages as carInoutManageMessages } from '../views/car/carInoutManageLang' | |
| 155 | +import { messages as carInManageMessages } from '../views/car/carInManageLang' | |
| 154 | 156 | |
| 155 | 157 | Vue.use(VueI18n) |
| 156 | 158 | |
| ... | ... | @@ -306,6 +308,8 @@ const messages = { |
| 306 | 308 | ...hireParkingSpaceMessages.en, |
| 307 | 309 | ...carAddParkingSpaceMessages.en, |
| 308 | 310 | ...buyCarMonthCardMessages.en, |
| 311 | + ...carInoutManageMessages.en, | |
| 312 | + ...carInManageMessages.en, | |
| 309 | 313 | }, |
| 310 | 314 | zh: { |
| 311 | 315 | ...loginMessages.zh, |
| ... | ... | @@ -457,6 +461,8 @@ const messages = { |
| 457 | 461 | ...hireParkingSpaceMessages.zh, |
| 458 | 462 | ...carAddParkingSpaceMessages.zh, |
| 459 | 463 | ...buyCarMonthCardMessages.zh, |
| 464 | + ...carInoutManageMessages.zh, | |
| 465 | + ...carInManageMessages.zh, | |
| 460 | 466 | } |
| 461 | 467 | } |
| 462 | 468 | ... | ... |
src/router/index.js
| ... | ... | @@ -751,6 +751,16 @@ const routes = [ |
| 751 | 751 | name: '/views/fee/buyCarMonthCard', |
| 752 | 752 | component: () => import('@/views/fee/buyCarMonthCardList.vue') |
| 753 | 753 | }, |
| 754 | + { | |
| 755 | + path:'/pages/property/carInoutManage', | |
| 756 | + name:'/pages/property/carInoutManage', | |
| 757 | + component: () => import('@/views/car/carInoutManageList.vue') | |
| 758 | + }, | |
| 759 | + { | |
| 760 | + path:'/pages/property/carInManage', | |
| 761 | + name:'/pages/property/carInManage', | |
| 762 | + component: () => import('@/views/car/carInManageList.vue') | |
| 763 | + }, | |
| 754 | 764 | // 其他子路由可以在这里添加 |
| 755 | 765 | ] |
| 756 | 766 | }, | ... | ... |
src/views/car/carInManageLang.js
0 → 100644
| 1 | +export const messages = { | |
| 2 | + en: { | |
| 3 | + carInManage: { | |
| 4 | + searchCondition: 'Search Conditions', | |
| 5 | + inputPlateNumber: 'Please enter license plate number', | |
| 6 | + selectVehicleStatus: 'Please select vehicle status', | |
| 7 | + inStatus: 'Entry Status', | |
| 8 | + paymentComplete: 'Payment Completed', | |
| 9 | + exitStatus: 'Exit Status', | |
| 10 | + timeoutRepayment: 'Payment Timeout Repayment', | |
| 11 | + selectPlateType: 'Please select license plate type', | |
| 12 | + temporaryVehicle: 'Temporary Vehicle', | |
| 13 | + forSaleVehicle: 'For Sale Vehicle', | |
| 14 | + monthlyRental: 'Monthly Rental', | |
| 15 | + whitelist: 'Whitelist', | |
| 16 | + blacklist: 'Blacklist', | |
| 17 | + internalVehicle: 'Internal Vehicle', | |
| 18 | + freeVehicle: 'Free Vehicle', | |
| 19 | + enterStartTime: 'Enter start time', | |
| 20 | + enterEndTime: 'Enter end time', | |
| 21 | + search: 'Search', | |
| 22 | + reset: 'Reset', | |
| 23 | + parkedVehicles: 'Parked Vehicles', | |
| 24 | + inoutId: 'In/Out ID', | |
| 25 | + vehicleStatus: 'Vehicle Status', | |
| 26 | + plateNumber: 'License Plate', | |
| 27 | + parkingLot: 'Parking Lot', | |
| 28 | + billingRule: 'Billing Rule', | |
| 29 | + plateType: 'License Plate Type', | |
| 30 | + entryTime: 'Entry Time', | |
| 31 | + parkingDuration: 'Parking Duration', | |
| 32 | + parkingFee: 'Parking Fee', | |
| 33 | + hour: 'hour', | |
| 34 | + minute: 'min' | |
| 35 | + } | |
| 36 | + }, | |
| 37 | + zh: { | |
| 38 | + carInManage: { | |
| 39 | + searchCondition: '查询条件', | |
| 40 | + inputPlateNumber: '请输入车牌号', | |
| 41 | + selectVehicleStatus: '请选择车辆状态', | |
| 42 | + inStatus: '进场状态', | |
| 43 | + paymentComplete: '支付完成', | |
| 44 | + exitStatus: '离场状态', | |
| 45 | + timeoutRepayment: '支付超时重新支付', | |
| 46 | + selectPlateType: '请选择车牌类型', | |
| 47 | + temporaryVehicle: '临时车', | |
| 48 | + forSaleVehicle: '出售车辆', | |
| 49 | + monthlyRental: '月租车', | |
| 50 | + whitelist: '白名单', | |
| 51 | + blacklist: '黑名单', | |
| 52 | + internalVehicle: '内部车', | |
| 53 | + freeVehicle: '免费车', | |
| 54 | + enterStartTime: '进场开始时间', | |
| 55 | + enterEndTime: '进场结束时间', | |
| 56 | + search: '查询', | |
| 57 | + reset: '重置', | |
| 58 | + parkedVehicles: '在场车辆', | |
| 59 | + inoutId: '进出场ID', | |
| 60 | + vehicleStatus: '车辆状态', | |
| 61 | + plateNumber: '车牌号', | |
| 62 | + parkingLot: '停车场', | |
| 63 | + billingRule: '计费规则', | |
| 64 | + plateType: '车牌类型', | |
| 65 | + entryTime: '进场时间', | |
| 66 | + parkingDuration: '在场时间', | |
| 67 | + parkingFee: '停车费用', | |
| 68 | + hour: '小时', | |
| 69 | + minute: '分' | |
| 70 | + } | |
| 71 | + } | |
| 72 | +} | |
| 0 | 73 | \ No newline at end of file | ... | ... |
src/views/car/carInManageList.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <div class="animated fadeInRight car-in-manage-container"> | |
| 3 | + <el-row :gutter="20"> | |
| 4 | + <!-- 左侧停车场区域选择 --> | |
| 5 | + | |
| 6 | + <el-col :span="3" class="padding-r-0"> | |
| 7 | + <div class="border-radius"> | |
| 8 | + <div class="margin-xs-r treeview"> | |
| 9 | + <ul class="list-group text-center border-radius"> | |
| 10 | + <li v-for="(item, index) in carInManageInfo.parkingAreas" :key="index" class="list-group-item node-orgTree" | |
| 11 | + :class="{ 'vc-node-selected': carInManageInfo.conditions.paNum === item.num }" @click="swatchParkingArea(item)"> | |
| 12 | + {{ item.num }} | |
| 13 | + </li> | |
| 14 | + </ul> | |
| 15 | + </div> | |
| 16 | + </div> | |
| 17 | + </el-col> | |
| 18 | + | |
| 19 | + <!-- 右侧内容区域 --> | |
| 20 | + <el-col :span="21"> | |
| 21 | + <!-- 查询条件卡片 --> | |
| 22 | + <el-card class="search-card"> | |
| 23 | + <div slot="header" class="clearfix flex justify-between"> | |
| 24 | + <span>{{ $t('carInManage.searchCondition') }}</span> | |
| 25 | + </div> | |
| 26 | + <el-row :gutter="20"> | |
| 27 | + <el-col :span="6"> | |
| 28 | + <el-input :placeholder="$t('carInManage.inputPlateNumber')" v-model="carInManageInfo.conditions.carNum" | |
| 29 | + clearable @keyup.enter.native="queryCarInoutMethod" /> | |
| 30 | + </el-col> | |
| 31 | + | |
| 32 | + <el-col :span="6"> | |
| 33 | + <el-select v-model="carInManageInfo.conditions.state" :placeholder="$t('carInManage.selectVehicleStatus')" | |
| 34 | + style="width:100%"> | |
| 35 | + <el-option value="" :label="$t('carInManage.selectVehicleStatus')" /> | |
| 36 | + <el-option value="100300" :label="$t('carInManage.inStatus')" /> | |
| 37 | + <el-option value="100400" :label="$t('carInManage.paymentComplete')" /> | |
| 38 | + <el-option value="100500" :label="$t('carInManage.exitStatus')" /> | |
| 39 | + <el-option value="100600" :label="$t('carInManage.timeoutRepayment')" /> | |
| 40 | + </el-select> | |
| 41 | + </el-col> | |
| 42 | + | |
| 43 | + <el-col :span="6"> | |
| 44 | + <el-select v-model="carInManageInfo.conditions.carType" :placeholder="$t('carInManage.selectPlateType')" | |
| 45 | + style="width:100%"> | |
| 46 | + <el-option value="" :label="$t('carInManage.selectPlateType')" /> | |
| 47 | + <el-option value="T" :label="$t('carInManage.temporaryVehicle')" /> | |
| 48 | + <el-option value="S" :label="$t('carInManage.forSaleVehicle')" /> | |
| 49 | + <el-option value="H" :label="$t('carInManage.monthlyRental')" /> | |
| 50 | + <el-option value="W" :label="$t('carInManage.whitelist')" /> | |
| 51 | + <el-option value="B" :label="$t('carInManage.blacklist')" /> | |
| 52 | + <el-option value="I" :label="$t('carInManage.internalVehicle')" /> | |
| 53 | + <el-option value="NM" :label="$t('carInManage.freeVehicle')" /> | |
| 54 | + </el-select> | |
| 55 | + </el-col> | |
| 56 | + | |
| 57 | + <el-col :span="6"> | |
| 58 | + <el-date-picker v-model="carInManageInfo.conditions.startTime" type="datetime" | |
| 59 | + :placeholder="$t('carInManage.enterStartTime')" value-format="yyyy-MM-dd HH:mm:ss" style="width:100%" /> | |
| 60 | + </el-col> | |
| 61 | + | |
| 62 | + <el-col :span="6" class="margin-top-10"> | |
| 63 | + <el-date-picker v-model="carInManageInfo.conditions.endTime" type="datetime" | |
| 64 | + :placeholder="$t('carInManage.enterEndTime')" value-format="yyyy-MM-dd HH:mm:ss" style="width:100%" /> | |
| 65 | + </el-col> | |
| 66 | + | |
| 67 | + <el-col :span="6" class="margin-top-10"> | |
| 68 | + <el-button type="primary" @click="queryCarInoutMethod"> | |
| 69 | + {{ $t('carInManage.search') }} | |
| 70 | + </el-button> | |
| 71 | + <el-button @click="resetCarInoutMethod"> | |
| 72 | + {{ $t('carInManage.reset') }} | |
| 73 | + </el-button> | |
| 74 | + </el-col> | |
| 75 | + </el-row> | |
| 76 | + </el-card> | |
| 77 | + | |
| 78 | + <!-- 在场车辆卡片 --> | |
| 79 | + <el-card class="list-card margin-top-20"> | |
| 80 | + <div slot="header" class="flex justify-between"> | |
| 81 | + <div>{{ $t('carInManage.parkedVehicles') }}</div> | |
| 82 | + </div> | |
| 83 | + | |
| 84 | + <el-table :data="carInManageInfo.carIns" border style="width: 100%" v-loading="loading"> | |
| 85 | + <el-table-column prop="ciId" :label="$t('carInManage.inoutId')" align="center" /> | |
| 86 | + <el-table-column prop="stateName" :label="$t('carInManage.vehicleStatus')" align="center" /> | |
| 87 | + <el-table-column prop="carNum" :label="$t('carInManage.plateNumber')" align="center" /> | |
| 88 | + <el-table-column prop="paNum" :label="$t('carInManage.parkingLot')" align="center" /> | |
| 89 | + <el-table-column prop="feeName" :label="$t('carInManage.billingRule')" align="center" /> | |
| 90 | + <el-table-column prop="carTypeName" :label="$t('carInManage.plateType')" align="center" /> | |
| 91 | + <el-table-column prop="inTime" :label="$t('carInManage.entryTime')" align="center" /> | |
| 92 | + <el-table-column :label="$t('carInManage.parkingDuration')" align="center"> | |
| 93 | + <template slot-scope="scope"> | |
| 94 | + {{ scope.row.hours }} {{ $t('carInManage.hour') }} {{ scope.row.min }} {{ $t('carInManage.minute') }} | |
| 95 | + </template> | |
| 96 | + </el-table-column> | |
| 97 | + <el-table-column :label="$t('carInManage.parkingFee')" align="center"> | |
| 98 | + <template slot-scope="scope"> | |
| 99 | + <span v-if="scope.row.carType !== '1001'">{{ scope.row.payCharge }}</span> | |
| 100 | + <span v-else>-</span> | |
| 101 | + </template> | |
| 102 | + </el-table-column> | |
| 103 | + </el-table> | |
| 104 | + | |
| 105 | + <!-- 分页 --> | |
| 106 | + <el-pagination class="margin-top-20" :current-page.sync="pagination.currentPage" :page-sizes="[10, 20, 30, 50]" | |
| 107 | + :page-size="pagination.pageSize" :total="pagination.total" layout="total, sizes, prev, pager, next, jumper" | |
| 108 | + @size-change="handleSizeChange" @current-change="handleCurrentChange" /> | |
| 109 | + </el-card> | |
| 110 | + </el-col> | |
| 111 | + </el-row> | |
| 112 | + </div> | |
| 113 | +</template> | |
| 114 | + | |
| 115 | +<script> | |
| 116 | +import { listParkingAreas, listCarIns } from '@/api/car/carInManageApi' | |
| 117 | +import { getCommunityId } from '@/api/community/communityApi' | |
| 118 | + | |
| 119 | +export default { | |
| 120 | + name: 'CarInManageList', | |
| 121 | + data() { | |
| 122 | + return { | |
| 123 | + loading: false, | |
| 124 | + pagination: { | |
| 125 | + currentPage: 1, | |
| 126 | + pageSize: 10, | |
| 127 | + total: 0 | |
| 128 | + }, | |
| 129 | + carInManageInfo: { | |
| 130 | + parkingAreas: [], | |
| 131 | + carIns: [], | |
| 132 | + conditions: { | |
| 133 | + state: '', | |
| 134 | + carNum: '', | |
| 135 | + carType: '', | |
| 136 | + startTime: '', | |
| 137 | + endTime: '', | |
| 138 | + paNum: '', | |
| 139 | + iotApiCode: 'listCarInParkingAreaBmoImpl', | |
| 140 | + page: 1, | |
| 141 | + row: 10, | |
| 142 | + communityId: '' | |
| 143 | + } | |
| 144 | + } | |
| 145 | + } | |
| 146 | + }, | |
| 147 | + created() { | |
| 148 | + this.communityId = getCommunityId() | |
| 149 | + this.carInManageInfo.conditions.communityId = this.communityId | |
| 150 | + this.loadParkingAreas() | |
| 151 | + }, | |
| 152 | + methods: { | |
| 153 | + // 加载停车场区域 | |
| 154 | + async loadParkingAreas() { | |
| 155 | + try { | |
| 156 | + const params = { | |
| 157 | + page: 1, | |
| 158 | + row: 100, | |
| 159 | + communityId: this.communityId | |
| 160 | + } | |
| 161 | + const response = await listParkingAreas(params) | |
| 162 | + this.carInManageInfo.parkingAreas = response.parkingAreas || [] | |
| 163 | + | |
| 164 | + if (this.carInManageInfo.parkingAreas.length > 0) { | |
| 165 | + this.carInManageInfo.conditions.paNum = this.carInManageInfo.parkingAreas[0].num | |
| 166 | + this.loadCarIns() | |
| 167 | + } | |
| 168 | + } catch (error) { | |
| 169 | + this.$message.error(this.$t('common.loadFailed')) | |
| 170 | + } | |
| 171 | + }, | |
| 172 | + swatchParkingArea(parkingArea) { | |
| 173 | + this.carInManageInfo.conditions.paNum = parkingArea.num | |
| 174 | + this.loadCarIns() | |
| 175 | + }, | |
| 176 | + | |
| 177 | + // 加载在场车辆 | |
| 178 | + async loadCarIns() { | |
| 179 | + this.loading = true | |
| 180 | + try { | |
| 181 | + // 处理参数 | |
| 182 | + const params = { | |
| 183 | + ...this.carInManageInfo.conditions, | |
| 184 | + page: this.pagination.currentPage, | |
| 185 | + row: this.pagination.pageSize | |
| 186 | + } | |
| 187 | + params.carNum = params.carNum ? params.carNum.trim() : '' | |
| 188 | + | |
| 189 | + // 调用API | |
| 190 | + const response = await listCarIns(params) | |
| 191 | + this.carInManageInfo.carIns = response.data || [] | |
| 192 | + this.pagination.total = response.total || 0 | |
| 193 | + } catch (error) { | |
| 194 | + this.$message.error(this.$t('common.loadFailed')) | |
| 195 | + } finally { | |
| 196 | + this.loading = false | |
| 197 | + } | |
| 198 | + }, | |
| 199 | + | |
| 200 | + // 切换停车场区域 | |
| 201 | + handleAreaChange(val) { | |
| 202 | + this.carInManageInfo.conditions.paNum = val | |
| 203 | + this.loadCarIns() | |
| 204 | + }, | |
| 205 | + | |
| 206 | + // 查询 | |
| 207 | + queryCarInoutMethod() { | |
| 208 | + this.pagination.currentPage = 1 | |
| 209 | + this.loadCarIns() | |
| 210 | + }, | |
| 211 | + | |
| 212 | + // 重置 | |
| 213 | + resetCarInoutMethod() { | |
| 214 | + this.carInManageInfo.conditions = { | |
| 215 | + ...this.carInManageInfo.conditions, | |
| 216 | + state: '', | |
| 217 | + carNum: '', | |
| 218 | + carType: '', | |
| 219 | + startTime: '', | |
| 220 | + endTime: '' | |
| 221 | + } | |
| 222 | + this.pagination.currentPage = 1 | |
| 223 | + this.loadCarIns() | |
| 224 | + }, | |
| 225 | + | |
| 226 | + // 分页大小改变 | |
| 227 | + handleSizeChange(size) { | |
| 228 | + this.pagination.pageSize = size | |
| 229 | + this.loadCarIns() | |
| 230 | + }, | |
| 231 | + | |
| 232 | + // 当前页改变 | |
| 233 | + handleCurrentChange(page) { | |
| 234 | + this.pagination.currentPage = page | |
| 235 | + this.loadCarIns() | |
| 236 | + } | |
| 237 | + } | |
| 238 | +} | |
| 239 | +</script> | |
| 240 | + | |
| 241 | +<style lang="scss" scoped> | |
| 242 | +.car-in-manage-container { | |
| 243 | + padding: 20px; | |
| 244 | + | |
| 245 | + .list-group { | |
| 246 | + padding-left: 0; | |
| 247 | + margin-bottom: 0; | |
| 248 | +} | |
| 249 | + | |
| 250 | +.list-group-item { | |
| 251 | + position: relative; | |
| 252 | + display: block; | |
| 253 | + padding: 10px 15px; | |
| 254 | + margin-bottom: -1px; | |
| 255 | + background-color: #fff; | |
| 256 | + border: 1px solid #ddd; | |
| 257 | + cursor: pointer; | |
| 258 | +} | |
| 259 | + | |
| 260 | +.list-group-item:hover { | |
| 261 | + background-color: #f5f5f5; | |
| 262 | +} | |
| 263 | + | |
| 264 | +.vc-node-selected { | |
| 265 | + background-color: #409EFF; | |
| 266 | + color: white; | |
| 267 | + border-color: #409EFF; | |
| 268 | +} | |
| 269 | + | |
| 270 | + .parking-area-card { | |
| 271 | + height: 100%; | |
| 272 | + | |
| 273 | + .area-radio-group { | |
| 274 | + display: flex; | |
| 275 | + flex-direction: column; | |
| 276 | + | |
| 277 | + .area-radio-button { | |
| 278 | + margin-bottom: 10px; | |
| 279 | + text-align: center; | |
| 280 | + } | |
| 281 | + } | |
| 282 | + } | |
| 283 | + | |
| 284 | + .search-card, | |
| 285 | + .list-card { | |
| 286 | + border-radius: 5px; | |
| 287 | + box-shadow: 0 2px 12px 0 rgba(0, 0, 0, .1); | |
| 288 | + } | |
| 289 | + | |
| 290 | + .margin-top-10 { | |
| 291 | + margin-top: 10px; | |
| 292 | + } | |
| 293 | + | |
| 294 | + .margin-top-20 { | |
| 295 | + margin-top: 20px; | |
| 296 | + } | |
| 297 | +} | |
| 298 | +</style> | |
| 0 | 299 | \ No newline at end of file | ... | ... |
src/views/car/carInoutManageLang.js
0 → 100644
| 1 | +export const messages = { | |
| 2 | + en: { | |
| 3 | + carInoutManage: { | |
| 4 | + searchCondition: 'Search Condition', | |
| 5 | + carNumRequired: 'Required, please enter license plate number', | |
| 6 | + selectCarStatus: 'Select vehicle status', | |
| 7 | + inStatus: 'Entry Status', | |
| 8 | + payCompleted: 'Payment Completed', | |
| 9 | + outStatus: 'Exit Status', | |
| 10 | + payTimeout: 'Payment Timeout', | |
| 11 | + selectCarType: 'Select license plate type', | |
| 12 | + temporaryCar: 'Temporary Car', | |
| 13 | + saleCar: 'Sale Car', | |
| 14 | + monthlyCar: 'Monthly Car', | |
| 15 | + internalCar: 'Internal Car', | |
| 16 | + freeCar: 'Free Car', | |
| 17 | + startTimePlaceholder: 'Please enter start time', | |
| 18 | + endTimePlaceholder: 'Please enter end time', | |
| 19 | + query: 'Search', | |
| 20 | + reset: 'Reset', | |
| 21 | + carInoutRecord: 'In/Out Records', | |
| 22 | + inPhoto: 'Entry Photo', | |
| 23 | + inoutId: 'In/Out ID', | |
| 24 | + carStatus: 'Vehicle Status', | |
| 25 | + carNum: 'License Plate', | |
| 26 | + parkingArea: 'Parking Area', | |
| 27 | + feeRule: 'Billing Rule', | |
| 28 | + carType: 'License Type', | |
| 29 | + inTime: 'Entry Time', | |
| 30 | + outTime: 'Exit Time', | |
| 31 | + parkingTime: 'Parking Duration', | |
| 32 | + chargeAmount: 'Charge Amount', | |
| 33 | + remark: 'Remark', | |
| 34 | + hour: 'hour', | |
| 35 | + minute: 'min', | |
| 36 | + out: 'Exit' | |
| 37 | + } | |
| 38 | + }, | |
| 39 | + zh: { | |
| 40 | + carInoutManage: { | |
| 41 | + searchCondition: '查询条件', | |
| 42 | + carNumRequired: '必填,请填写车牌号', | |
| 43 | + selectCarStatus: '请选择车辆状态', | |
| 44 | + inStatus: '进场状态', | |
| 45 | + payCompleted: '支付完成', | |
| 46 | + outStatus: '离场状态', | |
| 47 | + payTimeout: '支付超时重新支付', | |
| 48 | + selectCarType: '请选择车牌类型', | |
| 49 | + temporaryCar: '临时车', | |
| 50 | + saleCar: '出售车辆', | |
| 51 | + monthlyCar: '月租车', | |
| 52 | + internalCar: '内部车', | |
| 53 | + freeCar: '免费车', | |
| 54 | + startTimePlaceholder: '请填写开始时间', | |
| 55 | + endTimePlaceholder: '请填写结束时间', | |
| 56 | + query: '查询', | |
| 57 | + reset: '重置', | |
| 58 | + carInoutRecord: '进出场记录', | |
| 59 | + inPhoto: '进场图', | |
| 60 | + inoutId: '进出场编号', | |
| 61 | + carStatus: '车辆状态', | |
| 62 | + carNum: '车牌号', | |
| 63 | + parkingArea: '停车场', | |
| 64 | + feeRule: '计费规则', | |
| 65 | + carType: '车牌类型', | |
| 66 | + inTime: '进场时间', | |
| 67 | + outTime: '出场时间', | |
| 68 | + parkingTime: '停车时间', | |
| 69 | + chargeAmount: '收费金额', | |
| 70 | + remark: '说明', | |
| 71 | + hour: '小时', | |
| 72 | + minute: '分', | |
| 73 | + out: '出场' | |
| 74 | + } | |
| 75 | + } | |
| 76 | +} | |
| 0 | 77 | \ No newline at end of file | ... | ... |
src/views/car/carInoutManageList.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <div class="animated fadeInRight"> | |
| 3 | + <el-row :gutter="20"> | |
| 4 | + <el-col :span="3" class="padding-r-0"> | |
| 5 | + <div class="border-radius"> | |
| 6 | + <div class="margin-xs-r treeview"> | |
| 7 | + <ul class="list-group text-center border-radius"> | |
| 8 | + <li v-for="(item, index) in parkingAreas" :key="index" class="list-group-item node-orgTree" | |
| 9 | + :class="{ 'vc-node-selected': conditions.paNum === item.num }" @click="swatchParkingArea(item)"> | |
| 10 | + {{ item.num }} | |
| 11 | + </li> | |
| 12 | + </ul> | |
| 13 | + </div> | |
| 14 | + </div> | |
| 15 | + </el-col> | |
| 16 | + | |
| 17 | + <el-col :span="21"> | |
| 18 | + <el-card class="box-card"> | |
| 19 | + <div slot="header" class=" flex justify-between"> | |
| 20 | + <div>{{ $t('carInoutManage.searchCondition') }}</div> | |
| 21 | + </div> | |
| 22 | + <div class="card-body"> | |
| 23 | + <el-row :gutter="20"> | |
| 24 | + <el-col :span="4"> | |
| 25 | + <el-input v-model="conditions.carNum" :placeholder="$t('carInoutManage.carNumRequired')" clearable /> | |
| 26 | + </el-col> | |
| 27 | + <el-col :span="4"> | |
| 28 | + <el-select v-model="conditions.state" :placeholder="$t('carInoutManage.selectCarStatus')" | |
| 29 | + style="width:100%"> | |
| 30 | + <el-option :label="$t('carInoutManage.selectCarStatus')" value="" /> | |
| 31 | + <el-option :label="$t('carInoutManage.inStatus')" value="100300" /> | |
| 32 | + <el-option :label="$t('carInoutManage.payCompleted')" value="100400" /> | |
| 33 | + <el-option :label="$t('carInoutManage.outStatus')" value="100500" /> | |
| 34 | + <el-option :label="$t('carInoutManage.payTimeout')" value="100600" /> | |
| 35 | + </el-select> | |
| 36 | + </el-col> | |
| 37 | + <el-col :span="4"> | |
| 38 | + <el-select v-model="conditions.carType" :placeholder="$t('carInoutManage.selectCarType')" | |
| 39 | + style="width:100%"> | |
| 40 | + <el-option :label="$t('carInoutManage.selectCarType')" value="" /> | |
| 41 | + <el-option :label="$t('carInoutManage.temporaryCar')" value="1003" /> | |
| 42 | + <el-option :label="$t('carInoutManage.saleCar')" value="S" /> | |
| 43 | + <el-option :label="$t('carInoutManage.monthlyCar')" value="1001" /> | |
| 44 | + <el-option :label="$t('carInoutManage.internalCar')" value="I" /> | |
| 45 | + <el-option :label="$t('carInoutManage.freeCar')" value="NM" /> | |
| 46 | + </el-select> | |
| 47 | + </el-col> | |
| 48 | + <el-col :span="4"> | |
| 49 | + <el-date-picker v-model="conditions.startTime" type="datetime" | |
| 50 | + :placeholder="$t('carInoutManage.startTimePlaceholder')" style="width:100%" /> | |
| 51 | + </el-col> | |
| 52 | + <el-col :span="4"> | |
| 53 | + <el-date-picker v-model="conditions.endTime" type="datetime" | |
| 54 | + :placeholder="$t('carInoutManage.endTimePlaceholder')" style="width:100%" /> | |
| 55 | + </el-col> | |
| 56 | + <el-col :span="4"> | |
| 57 | + <el-button type="primary" size="small" @click="queryCarInoutMethod"> | |
| 58 | + {{ $t('carInoutManage.query') }} | |
| 59 | + </el-button> | |
| 60 | + <el-button size="small" @click="resetCarInoutMethod"> | |
| 61 | + {{ $t('carInoutManage.reset') }} | |
| 62 | + </el-button> | |
| 63 | + </el-col> | |
| 64 | + </el-row> | |
| 65 | + </div> | |
| 66 | + </el-card> | |
| 67 | + | |
| 68 | + <el-card class="box-card" style="margin-top:20px"> | |
| 69 | + <div slot="header" class="flex justify-between"> | |
| 70 | + <div>{{ $t('carInoutManage.carInoutRecord') }}</div> | |
| 71 | + </div> | |
| 72 | + <div class="card-body"> | |
| 73 | + <el-table :data="carInouts" border style="width:100%"> | |
| 74 | + <el-table-column :label="$t('carInoutManage.inPhoto')" align="center" width="100"> | |
| 75 | + <template slot-scope="scope"> | |
| 76 | + <el-image style="width:60px;height:60px;cursor:pointer;" :src="scope.row.photoJpg || '/img/noPhoto.jpg'" | |
| 77 | + :preview-src-list="[scope.row.photoJpg]" fit="cover" /> | |
| 78 | + </template> | |
| 79 | + </el-table-column> | |
| 80 | + <el-table-column prop="inoutId" :label="$t('carInoutManage.inoutId')" align="center" /> | |
| 81 | + <el-table-column :label="$t('carInoutManage.carStatus')" align="center"> | |
| 82 | + <template slot-scope="scope"> | |
| 83 | + {{ scope.row.carInout === '3306' ? $t('carInoutManage.inStatus') : $t('carInoutManage.outStatus') }} | |
| 84 | + ({{ scope.row.stateName }}) | |
| 85 | + </template> | |
| 86 | + </el-table-column> | |
| 87 | + <el-table-column prop="carNum" :label="$t('carInoutManage.carNum')" align="center" /> | |
| 88 | + <el-table-column prop="paNum" :label="$t('carInoutManage.parkingArea')" align="center" /> | |
| 89 | + <el-table-column prop="feeName" :label="$t('carInoutManage.feeRule')" align="center" /> | |
| 90 | + <el-table-column prop="carTypeName" :label="$t('carInoutManage.carType')" align="center" /> | |
| 91 | + <el-table-column prop="inTime" :label="$t('carInoutManage.inTime')" align="center" /> | |
| 92 | + <el-table-column :label="$t('carInoutManage.outTime')" align="center"> | |
| 93 | + <template slot-scope="scope"> | |
| 94 | + {{ scope.row.carInout === '3307' ? scope.row.outTime : '-' }} | |
| 95 | + </template> | |
| 96 | + </el-table-column> | |
| 97 | + <el-table-column :label="$t('carInoutManage.parkingTime')" align="center"> | |
| 98 | + <template slot-scope="scope"> | |
| 99 | + {{ scope.row.hours }}{{ $t('carInoutManage.hour') }}{{ scope.row.min }}{{ $t('carInoutManage.minute') }} | |
| 100 | + </template> | |
| 101 | + </el-table-column> | |
| 102 | + <el-table-column :label="$t('carInoutManage.chargeAmount')" align="center"> | |
| 103 | + <template slot-scope="scope"> | |
| 104 | + <span v-if="scope.row.carType !== 'T'">-</span> | |
| 105 | + <span v-else> | |
| 106 | + {{ scope.row.payCharge }} | |
| 107 | + <span v-if="['100300', '100400', '100600'].includes(scope.row.inState)"> | |
| 108 | + (<a href="javascript:void(0)" @click="carInoutTempCarPayFee(scope.row)"> | |
| 109 | + {{ $t('carInoutManage.out') }} | |
| 110 | + </a>) | |
| 111 | + </span> | |
| 112 | + </span> | |
| 113 | + </template> | |
| 114 | + </el-table-column> | |
| 115 | + <el-table-column prop="remark" :label="$t('carInoutManage.remark')" align="center" /> | |
| 116 | + </el-table> | |
| 117 | + | |
| 118 | + <el-pagination :current-page="page.current" :page-sizes="[10, 20, 30, 50]" :page-size="page.size" | |
| 119 | + layout="total, sizes, prev, pager, next, jumper" :total="page.total" @size-change="handleSizeChange" | |
| 120 | + @current-change="handleCurrentChange" /> | |
| 121 | + </div> | |
| 122 | + </el-card> | |
| 123 | + </el-col> | |
| 124 | + </el-row> | |
| 125 | + </div> | |
| 126 | +</template> | |
| 127 | + | |
| 128 | +<script> | |
| 129 | +import { listParkingAreas, listCarInouts } from '@/api/car/carInoutManageApi' | |
| 130 | +import { getCommunityId } from '@/api/community/communityApi' | |
| 131 | + | |
| 132 | +export default { | |
| 133 | + name: 'CarInoutManageList', | |
| 134 | + data() { | |
| 135 | + return { | |
| 136 | + parkingAreas: [], | |
| 137 | + carInouts: [], | |
| 138 | + conditions: { | |
| 139 | + state: '', | |
| 140 | + carNum: '', | |
| 141 | + carType: '', | |
| 142 | + startTime: '', | |
| 143 | + endTime: '', | |
| 144 | + paNum: '', | |
| 145 | + iotApiCode: 'listCarInoutDetailBmoImpl' | |
| 146 | + }, | |
| 147 | + page: { | |
| 148 | + current: 1, | |
| 149 | + size: 10, | |
| 150 | + total: 0, | |
| 151 | + records: 0 | |
| 152 | + } | |
| 153 | + } | |
| 154 | + }, | |
| 155 | + created() { | |
| 156 | + this.loadParkingArea() | |
| 157 | + }, | |
| 158 | + methods: { | |
| 159 | + async loadParkingArea() { | |
| 160 | + try { | |
| 161 | + const params = { | |
| 162 | + page: 1, | |
| 163 | + row: 100, | |
| 164 | + communityId: getCommunityId() | |
| 165 | + } | |
| 166 | + const res = await listParkingAreas(params) | |
| 167 | + this.parkingAreas = res.parkingAreas || [] | |
| 168 | + if (this.parkingAreas.length > 0) { | |
| 169 | + this.swatchParkingArea(this.parkingAreas[0]) | |
| 170 | + } | |
| 171 | + } catch (error) { | |
| 172 | + console.error('加载停车场区域失败:', error) | |
| 173 | + } | |
| 174 | + }, | |
| 175 | + swatchParkingArea(parkingArea) { | |
| 176 | + this.conditions.paNum = parkingArea.num | |
| 177 | + this.listCarInouts() | |
| 178 | + }, | |
| 179 | + async listCarInouts() { | |
| 180 | + try { | |
| 181 | + const params = { | |
| 182 | + ...this.conditions, | |
| 183 | + page: this.page.current, | |
| 184 | + row: this.page.size, | |
| 185 | + communityId: getCommunityId() | |
| 186 | + } | |
| 187 | + | |
| 188 | + // 处理车牌号空格 | |
| 189 | + if (params.carNum) params.carNum = params.carNum.trim() | |
| 190 | + | |
| 191 | + const res = await listCarInouts(params) | |
| 192 | + this.carInouts = res.data || [] | |
| 193 | + this.page.total = res.total || 0 | |
| 194 | + this.page.records = res.records || 0 | |
| 195 | + } catch (error) { | |
| 196 | + console.error('加载进出场记录失败:', error) | |
| 197 | + } | |
| 198 | + }, | |
| 199 | + queryCarInoutMethod() { | |
| 200 | + this.page.current = 1 | |
| 201 | + this.listCarInouts() | |
| 202 | + }, | |
| 203 | + resetCarInoutMethod() { | |
| 204 | + this.conditions = { | |
| 205 | + state: '', | |
| 206 | + carNum: '', | |
| 207 | + carType: '', | |
| 208 | + startTime: '', | |
| 209 | + endTime: '', | |
| 210 | + paNum: this.conditions.paNum, // 保留当前停车场 | |
| 211 | + iotApiCode: 'listCarInoutDetailBmoImpl' | |
| 212 | + } | |
| 213 | + this.listCarInouts() | |
| 214 | + }, | |
| 215 | + handleSizeChange(val) { | |
| 216 | + this.page.size = val | |
| 217 | + this.listCarInouts() | |
| 218 | + }, | |
| 219 | + handleCurrentChange(val) { | |
| 220 | + this.page.current = val | |
| 221 | + this.listCarInouts() | |
| 222 | + }, | |
| 223 | + carInoutTempCarPayFee(row) { | |
| 224 | + // 出场支付逻辑 | |
| 225 | + console.log('出场支付:', row) | |
| 226 | + } | |
| 227 | + } | |
| 228 | +} | |
| 229 | +</script> | |
| 230 | + | |
| 231 | +<style scoped> | |
| 232 | +.animated { | |
| 233 | + padding: 15px; | |
| 234 | +} | |
| 235 | + | |
| 236 | +.border-radius { | |
| 237 | + border-radius: 4px; | |
| 238 | + overflow: hidden; | |
| 239 | +} | |
| 240 | + | |
| 241 | +.margin-xs-r { | |
| 242 | + margin-right: 5px; | |
| 243 | +} | |
| 244 | + | |
| 245 | +.list-group { | |
| 246 | + padding-left: 0; | |
| 247 | + margin-bottom: 0; | |
| 248 | +} | |
| 249 | + | |
| 250 | +.list-group-item { | |
| 251 | + position: relative; | |
| 252 | + display: block; | |
| 253 | + padding: 10px 15px; | |
| 254 | + margin-bottom: -1px; | |
| 255 | + background-color: #fff; | |
| 256 | + border: 1px solid #ddd; | |
| 257 | + cursor: pointer; | |
| 258 | +} | |
| 259 | + | |
| 260 | +.list-group-item:hover { | |
| 261 | + background-color: #f5f5f5; | |
| 262 | +} | |
| 263 | + | |
| 264 | +.vc-node-selected { | |
| 265 | + background-color: #409EFF; | |
| 266 | + color: white; | |
| 267 | + border-color: #409EFF; | |
| 268 | +} | |
| 269 | + | |
| 270 | +.card-body { | |
| 271 | + padding: 20px; | |
| 272 | +} | |
| 273 | + | |
| 274 | +.el-col { | |
| 275 | + margin-bottom: 15px; | |
| 276 | +} | |
| 277 | +</style> | |
| 0 | 278 | \ No newline at end of file | ... | ... |