|
|
@@ -0,0 +1,521 @@
|
|
|
+<template>
|
|
|
+ <div class="app-container">
|
|
|
+ <div class="filter-container">
|
|
|
+ <el-form
|
|
|
+ :model="filter"
|
|
|
+ v-bind:inline="true"
|
|
|
+ label-position="left"
|
|
|
+ label-width="0px"
|
|
|
+ style="width: 100%;">
|
|
|
+ <div class="filter-view">
|
|
|
+ <div>
|
|
|
+ <el-date-picker
|
|
|
+ v-model="filter.pageCriteria.dateRange"
|
|
|
+ type="daterange"
|
|
|
+ range-separator="-"
|
|
|
+ :clearable="false"
|
|
|
+ start-placeholder="Start Date"
|
|
|
+ end-placeholder="End Date"
|
|
|
+ value-format="yyyy-MM-dd"
|
|
|
+ @change="handleFilter"/>
|
|
|
+ </div>
|
|
|
+ <el-select
|
|
|
+ class="filter-view-item"
|
|
|
+ v-model="filter.pageCriteria.transactionStatus"
|
|
|
+ placeholder="Charging Status"
|
|
|
+ @change="handleFilter"
|
|
|
+ clearable>
|
|
|
+ <el-option
|
|
|
+ v-for="(item, index) in filterOptions"
|
|
|
+ :key="index"
|
|
|
+ :label="item.value"
|
|
|
+ :value="item.key"/>
|
|
|
+ </el-select>
|
|
|
+ <el-select
|
|
|
+ class="filter-view-item"
|
|
|
+ v-model="filter.pageCriteria.chargingPlatform"
|
|
|
+ placeholder="Charging Platform"
|
|
|
+ @change="changeUserType"
|
|
|
+ clearable>
|
|
|
+ <el-option
|
|
|
+ v-for="item in chargePlatOptions"
|
|
|
+ :key="item"
|
|
|
+ :label="item"
|
|
|
+ :value="item" />
|
|
|
+ </el-select>
|
|
|
+ <el-select
|
|
|
+ class="filter-view-item"
|
|
|
+ v-model="filter.pageCriteria.userType"
|
|
|
+ placeholder="User Type"
|
|
|
+ @change="changeUserType"
|
|
|
+ clearable>
|
|
|
+ <el-option
|
|
|
+ v-for="item in userTypeOptions"
|
|
|
+ :key="item"
|
|
|
+ :label="item"
|
|
|
+ :value="item" />
|
|
|
+ </el-select>
|
|
|
+ <el-select
|
|
|
+ class="filter-view-item group-select"
|
|
|
+ :class="{hide: groupOptions.length == 0}"
|
|
|
+ v-model="filter.pageCriteria.groupPk"
|
|
|
+ placeholder="Group Name"
|
|
|
+ @change="handleFilter"
|
|
|
+ clearable>
|
|
|
+ <el-option
|
|
|
+ v-for="(item,index) in groupOptions"
|
|
|
+ :key="index"
|
|
|
+ :label="item.name"
|
|
|
+ :value="item.value"/>
|
|
|
+ </el-select>
|
|
|
+ <el-select
|
|
|
+ class="filter-view-item"
|
|
|
+ v-model="filter.pageCriteria.paymentMethod"
|
|
|
+ placeholder="Credit Type"
|
|
|
+ @change="handleFilter"
|
|
|
+ clearable>
|
|
|
+ <el-option
|
|
|
+ v-for="item in payTypeOptions"
|
|
|
+ :key="item.key"
|
|
|
+ :label="item.value"
|
|
|
+ :value="item.key" />
|
|
|
+ </el-select>
|
|
|
+ <div style="flex: 1; max-width: 500px;">
|
|
|
+ <el-input
|
|
|
+ v-model="filter.pageCriteria.criteria"
|
|
|
+ prefix-icon="el-icon-search"
|
|
|
+ placeholder="Search by Station ID, Vehicle, Transaction ID, Email, Carpark Code"
|
|
|
+ @keyup.enter.native="handleFilter"
|
|
|
+ @change="handleFilter"
|
|
|
+ clearable/>
|
|
|
+ </div>
|
|
|
+ <!-- <div>
|
|
|
+ <el-button
|
|
|
+ type="primary"
|
|
|
+ icon="el-icon-search"
|
|
|
+ @click="handleFilter">
|
|
|
+ Search
|
|
|
+ </el-button>
|
|
|
+ </div> -->
|
|
|
+ </div>
|
|
|
+ </el-form>
|
|
|
+ </div>
|
|
|
+ <el-table
|
|
|
+ v-loading="listLoading"
|
|
|
+ :data="tableList"
|
|
|
+ class="no-border"
|
|
|
+ style="width: 100%;min-height: 65vh;">
|
|
|
+ <el-table-column
|
|
|
+ min-width="120"
|
|
|
+ label="Transaction ID"
|
|
|
+ align="center">
|
|
|
+ <template slot-scope="{row}">
|
|
|
+ <span
|
|
|
+ class="link-type"
|
|
|
+ @click="viewTransiction(row)">
|
|
|
+ {{ row.transactionPk }}
|
|
|
+ </span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <!--el-table-column
|
|
|
+ label="User ID"
|
|
|
+ align="center"
|
|
|
+ width="80">
|
|
|
+ <template slot-scope="{row}">
|
|
|
+ <span>{{ row.userPk }}</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column-->
|
|
|
+ <el-table-column
|
|
|
+ label="Email"
|
|
|
+ align="center"
|
|
|
+ min-width="100">
|
|
|
+ <template slot-scope="{row}">
|
|
|
+ <span :title="row.email">{{ row.email }}</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <!--el-table-column
|
|
|
+ label="Phone No."
|
|
|
+ align="center">
|
|
|
+ <template slot-scope="{row}">
|
|
|
+ <span :title="row.phoneNo">{{ row.phoneNo }}</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column-->
|
|
|
+ <el-table-column
|
|
|
+ label="Charging Platform"
|
|
|
+ align="center"
|
|
|
+ min-width="120">
|
|
|
+ <template slot-scope="{row}">
|
|
|
+ <span :title="row.chargingPlatform">{{ row.chargingPlatform }}</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column
|
|
|
+ label="User Type"
|
|
|
+ align="center"
|
|
|
+ min-width="120">
|
|
|
+ <template slot-scope="{row}">
|
|
|
+ <span :title="row.userType">{{ row.userType }}</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column
|
|
|
+ label="Credit Type"
|
|
|
+ prop="paymentMethod"
|
|
|
+ align="center"
|
|
|
+ min-width="120"/>
|
|
|
+ <!-- <el-table-column
|
|
|
+ label="Vehicle"
|
|
|
+ align="center"
|
|
|
+ prop="vehicle"
|
|
|
+ min-width="120">
|
|
|
+ <template slot-scope="{row}" v-if="row.vehicles">
|
|
|
+ <span
|
|
|
+ v-for="(item, idx) in row.vehicles"
|
|
|
+ :key="idx"
|
|
|
+ style="display: block;"
|
|
|
+ :title="item">
|
|
|
+ {{item}}
|
|
|
+ </span>
|
|
|
+ </template>
|
|
|
+ </el-table-column> -->
|
|
|
+ <el-table-column
|
|
|
+ label="Station ID"
|
|
|
+ align="center"
|
|
|
+ min-width="120">
|
|
|
+ <template slot-scope="{row}">
|
|
|
+ <div
|
|
|
+ class="link-detail"
|
|
|
+ @click="viewTransiction(row)"
|
|
|
+ :title="row.chargeBoxId">
|
|
|
+ {{ row.chargeBoxId }}
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column
|
|
|
+ label="Carpark Code"
|
|
|
+ prop="carParkCode"
|
|
|
+ align="center"
|
|
|
+ min-width="90"/>
|
|
|
+ <el-table-column
|
|
|
+ min-width="90"
|
|
|
+ label="Connector"
|
|
|
+ align="center">
|
|
|
+ <template slot-scope="{row}">
|
|
|
+ <span>{{ row.connectorId }}</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column
|
|
|
+ label="Start Date/Time"
|
|
|
+ align="center"
|
|
|
+ min-width="140">
|
|
|
+ <template slot-scope="{row}">
|
|
|
+ <span :title="row.chargingStartTime">{{ row.chargingStartTime }}</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column
|
|
|
+ label="End Date/Time"
|
|
|
+ align="center"
|
|
|
+ min-width="140">
|
|
|
+ <template slot-scope="{row}">
|
|
|
+ <span :title="row.chargingStopTime">{{ row.chargingStopTime }}</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column
|
|
|
+ label="Power"
|
|
|
+ align="center"
|
|
|
+ min-width="120">
|
|
|
+ <template slot-scope="{row}">
|
|
|
+ <span :title="row.totalPowerStr">{{ row.totalPowerStr }}</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column
|
|
|
+ label="Rate"
|
|
|
+ align="center"
|
|
|
+ min-width="150">
|
|
|
+ <template slot-scope="{row}" v-if="row.rate && row.rate.rateItems">
|
|
|
+ <span
|
|
|
+ v-for="(item, idx) in row.rate.rateItems"
|
|
|
+ :key="idx"
|
|
|
+ style="display: block;"
|
|
|
+ :title="item">
|
|
|
+ {{item.discountRate}}
|
|
|
+ </span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column
|
|
|
+ label="Duration"
|
|
|
+ align="center"
|
|
|
+ min-width="100">
|
|
|
+ <template slot-scope="{row}">
|
|
|
+ <span :title="row.duration">{{ row.duration }}</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <!-- <el-table-column
|
|
|
+ label="Total Min"
|
|
|
+ align="center"
|
|
|
+ min-width="100">
|
|
|
+ <template slot-scope="{row}">
|
|
|
+ <span :title="row.totalMin">{{ row.totalMin }}</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column> -->
|
|
|
+ <el-table-column
|
|
|
+ label="Charges"
|
|
|
+ align="center"
|
|
|
+ min-width="100">
|
|
|
+ <template slot-scope="{row}">
|
|
|
+ <span :title="row.charge">{{ row.charge }}</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <!-- <el-table-column
|
|
|
+ label="Invoice"
|
|
|
+ align="center"
|
|
|
+ min-width="80">
|
|
|
+ <template slot-scope="{row}">
|
|
|
+ <i
|
|
|
+ class="download-invoice el-icon-download"
|
|
|
+ title="Download"
|
|
|
+ @click="downloadPdf(row.transactionPk)"></i>
|
|
|
+ </template>
|
|
|
+ </el-table-column> -->
|
|
|
+ </el-table>
|
|
|
+ <div class="right">
|
|
|
+ <pagination
|
|
|
+ v-show="total > 0"
|
|
|
+ :total="total"
|
|
|
+ :page.sync="filter.pageNum"
|
|
|
+ :limit.sync="filter.pageSize"
|
|
|
+ @pagination="getList" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import Pagination from '@/components/Pagination'
|
|
|
+import api from '../../http/api/transaction'
|
|
|
+import apiUser from '../../http/api/apiUser.js'
|
|
|
+import financial from '@/http/api/financial'
|
|
|
+import { parseTime } from '@/utils'
|
|
|
+
|
|
|
+export default {
|
|
|
+ components: { Pagination },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ filter: {
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 10,
|
|
|
+ pageCriteria: {
|
|
|
+ groupPk: "",
|
|
|
+ criteria: "",
|
|
|
+ userType: "",
|
|
|
+ dateRange: [],
|
|
|
+ paymentMethod: "",
|
|
|
+ chargingPlatform : "",
|
|
|
+ transactionStatus: ""
|
|
|
+ }
|
|
|
+ },
|
|
|
+ groupOptions: [],
|
|
|
+ filterOptions: [],
|
|
|
+ payTypeOptions: [],
|
|
|
+ userTypeOptions: [],
|
|
|
+ chargePlatOptions: [],
|
|
|
+ listLoading: true,
|
|
|
+ tableList: [],
|
|
|
+ total: 0,
|
|
|
+ listQuery: {
|
|
|
+ page: 1,
|
|
|
+ limit: 10,
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ created() {
|
|
|
+ this.init();
|
|
|
+ this.getUserTypeOption();
|
|
|
+ this.getPaymentTypeOption();
|
|
|
+ this.getChargePlatformList();
|
|
|
+ this.getFilters();
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ init() {
|
|
|
+ const date = new Date();
|
|
|
+ const year = date.getFullYear();
|
|
|
+ const month = date.getMonth();
|
|
|
+ const firstDay = new Date(year, month, 1);
|
|
|
+ //const lastDay = new Date(year, month + 1, 0);
|
|
|
+ this.filter.pageCriteria.dateRange = [
|
|
|
+ parseTime(firstDay, "{y}-{m}-{d}"),
|
|
|
+ parseTime(date, "{y}-{m}-{d}")
|
|
|
+ ]
|
|
|
+ },
|
|
|
+ handleFilter() {
|
|
|
+ this.filter.pageNum = 1;
|
|
|
+ this.getList();
|
|
|
+ },
|
|
|
+ getFilters() {
|
|
|
+ api.getTransactionStatus().then(res => {
|
|
|
+ if (res.data) {
|
|
|
+ this.filterOptions = res.data
|
|
|
+ this.filter.pageCriteria.transactionStatus = res.data[0].value
|
|
|
+ this.getList()
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+ changeUserType() {
|
|
|
+ this.filter.pageCriteria.groupPk = "";
|
|
|
+ this.getGroupOptions();
|
|
|
+ },
|
|
|
+ getGroupOptions() {
|
|
|
+ if (this.filter.pageCriteria.userType == "") {
|
|
|
+ this.groupOptions = [];
|
|
|
+ this.getList();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this.listLoading = true;
|
|
|
+ apiUser.getGroupByType(this.filter.pageCriteria.userType).then(res => {
|
|
|
+ if (res.data) {
|
|
|
+ this.groupOptions = res.data
|
|
|
+ } else {
|
|
|
+ this.groupOptions = []
|
|
|
+ }
|
|
|
+ }).catch(err => {
|
|
|
+ this.$message({
|
|
|
+ message: err,
|
|
|
+ type: 'error'
|
|
|
+ })
|
|
|
+ this.groupOptions = []
|
|
|
+ }).finally(() => {
|
|
|
+ setTimeout(() => {
|
|
|
+ this.getList();
|
|
|
+ }, 100)
|
|
|
+ })
|
|
|
+ },
|
|
|
+ getUserTypeOption() {
|
|
|
+ apiUser.getUserTypeOptions().then(res => {
|
|
|
+ if (res.data) {
|
|
|
+ this.userTypeOptions = res.data
|
|
|
+ }
|
|
|
+ }).catch(error => {
|
|
|
+ this.$message({
|
|
|
+ message: error,
|
|
|
+ type: 'error'
|
|
|
+ })
|
|
|
+ })
|
|
|
+ },
|
|
|
+ getPaymentTypeOption() {
|
|
|
+ financial.getPaymentTypeOptions().then(res => {
|
|
|
+ if (res.data) {
|
|
|
+ this.payTypeOptions = res.data
|
|
|
+ }
|
|
|
+ }).catch(error => {
|
|
|
+ this.$message({
|
|
|
+ message: error,
|
|
|
+ type: 'error'
|
|
|
+ })
|
|
|
+ })
|
|
|
+ },
|
|
|
+ getChargePlatformList() {
|
|
|
+ financial.getChargePlatformOptions().then(res => {
|
|
|
+ if (res.data) {
|
|
|
+ this.chargePlatOptions = res.data
|
|
|
+ }
|
|
|
+ }).catch(error => {
|
|
|
+ this.$message({
|
|
|
+ message: error,
|
|
|
+ type: 'error'
|
|
|
+ })
|
|
|
+ })
|
|
|
+ },
|
|
|
+ getList() {
|
|
|
+ this.listLoading = true;
|
|
|
+ api.getTransactionPagesV2(this.filter).then(res => {
|
|
|
+ if (res.data.records && res.data.totalRow) {
|
|
|
+ this.tableList = res.data.records;
|
|
|
+ this.total = res.data.totalRow;
|
|
|
+ } else {
|
|
|
+ this.tableList = []
|
|
|
+ this.total = 0
|
|
|
+ }
|
|
|
+ }).catch(err => {
|
|
|
+ this.$message({
|
|
|
+ type: "error",
|
|
|
+ message: err
|
|
|
+ })
|
|
|
+ this.tableList = []
|
|
|
+ this.total = 0
|
|
|
+ }).finally(() => {
|
|
|
+ this.listLoading = false
|
|
|
+ })
|
|
|
+ },
|
|
|
+ async downloadPdf(id) {
|
|
|
+ try {
|
|
|
+ this.listLoading = true;
|
|
|
+ const res = await api.downloadInvoice(id);
|
|
|
+ if (res && res.size > 0) {
|
|
|
+ const name = 'T' + id + '-' + new Date().getTime() + '.pdf'
|
|
|
+ this.downloadFile(res, name);
|
|
|
+ } else {
|
|
|
+ this.$message.error('Empty files');
|
|
|
+ }
|
|
|
+ } catch (err) {
|
|
|
+ this.$message({
|
|
|
+ type: "error",
|
|
|
+ message: err
|
|
|
+ })
|
|
|
+ } finally {
|
|
|
+ this.listLoading = false;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ downloadFile(res, fileName) {
|
|
|
+ const blob = new Blob([res], {
|
|
|
+ type: 'application/pdf;charset=utf-8'
|
|
|
+ })
|
|
|
+ // let href = window.URL.createObjectURL(blob)
|
|
|
+ if ('download' in document.createElement('a')) {
|
|
|
+ // 非IE下载
|
|
|
+ const elink = document.createElement('a')
|
|
|
+ elink.download = fileName
|
|
|
+ elink.style.display = 'none'
|
|
|
+ elink.href = URL.createObjectURL(blob)
|
|
|
+ document.body.appendChild(elink)
|
|
|
+ elink.click()
|
|
|
+ URL.revokeObjectURL(elink.href) // 释放URL 对象
|
|
|
+ document.body.removeChild(elink)
|
|
|
+ } else {
|
|
|
+ // IE10+下载
|
|
|
+ navigator.msSaveBlob(blob, fileName)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ viewTransiction(row) {
|
|
|
+ this.$router.push({
|
|
|
+ path: "/station-activities/transactions/v2/" + row.chargingPk
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+<style scoped="scoped">
|
|
|
+ .table-link {
|
|
|
+ color: #333;
|
|
|
+ display: inline-block;
|
|
|
+ cursor: pointer;
|
|
|
+ white-space: nowrap;
|
|
|
+ text-decoration: underline;
|
|
|
+ }
|
|
|
+ .table-link:hover {
|
|
|
+ color: #1290BF;
|
|
|
+ text-decoration: none;
|
|
|
+ }
|
|
|
+ .el-table >>> tr div {
|
|
|
+ word-break: break-word;
|
|
|
+ }
|
|
|
+ .download-invoice {
|
|
|
+ color: #0000FF;
|
|
|
+ cursor: pointer;
|
|
|
+ }
|
|
|
+ .group-select {
|
|
|
+ overflow: hidden;
|
|
|
+ transition: all .3s;
|
|
|
+ }
|
|
|
+ .group-select.hide {
|
|
|
+ margin: 0;
|
|
|
+ min-width: 0;
|
|
|
+ max-width: 0;
|
|
|
+ }
|
|
|
+</style>
|