vbea пре 3 година
родитељ
комит
7ee14fbeb6

+ 12 - 0
Strides-Admin/src/http/api/userManagement.js

@@ -10,6 +10,18 @@ const functionUris = {
   deleteUser: "/delDevicesUser",
 }
 
+export default {
+  userTopup(params) {
+    return post(moduleName + "/manualTopUp", params)
+  },
+  pageChargeHistory(params) {
+    return post(moduleName + "/viewingChargingHistory", params)
+  },
+  pageTopupHistory(params) {
+    return post(moduleName + "/viewingTopUpHistory", params)
+  }
+}
+
 export function fetchList(
   query = {
     limit: 10,

+ 24 - 2
Strides-Admin/src/router/UserRouter.js

@@ -34,7 +34,7 @@ export default {
       }
     },
     {
-      path: 'update-user',
+      path: 'update-user/:id',
       component: () => import('@/views/user/UserDetail'),
       name: 'userDetail',
       hidden: true,
@@ -44,6 +44,28 @@ export default {
         affix: true,
         activeMenu: '/user-management/index'
       }
-    },
+    },{
+      path: 'topup-history/:id',
+      component: () => import('@/views/user/hisTopUp'),
+      name: 'userDetail',
+      hidden: true,
+      meta: {
+        title: 'Top Up History',
+        icon: 'user-management',
+        affix: true,
+        activeMenu: '/user-management/index'
+      }
+    },{
+      path: 'charging-history/:id',
+      component: () => import('@/views/user/hisCharge'),
+      name: 'userDetail',
+      hidden: true,
+      meta: {
+        title: 'Charging History',
+        icon: 'user-management',
+        affix: true,
+        activeMenu: '/user-management/index'
+      }
+    }
   ],
 }

+ 4 - 4
Strides-Admin/src/views/site/AddSite.vue

@@ -35,7 +35,7 @@
                   v-model="siteForm.siteInformation.longitude"
                   class="input-text" />
             </el-form-item>
-            <el-form-item
+            <!-- <el-form-item
               prop="siteInformation.type"
               label="Type:">
               <div class="type-row" v-for="(item, index) in siteTypeTable">
@@ -52,7 +52,7 @@
                   placeholder="End Time"
                   :disabled="isSiteTypeEnable(index)"/>
               </div>
-            </el-form-item>
+            </el-form-item> -->
           </el-col>
 
           <el-col :span="12">
@@ -172,7 +172,7 @@
             </el-col>
           </el-row>
         </el-form>
-      <!-- <div class="sparator"></div>
+      <div class="sparator"></div>
       <div class="section-title">
         TIME CONFIGURATION
       </div>
@@ -214,7 +214,7 @@
             </el-time-picker>
           </template>
         </el-table-column>
-      </el-table> -->
+      </el-table>
         <!-- prop="siteInformation.type"
         label="Type">
         <el-select

+ 27 - 6
Strides-Admin/src/views/site/SiteManagement.vue

@@ -76,16 +76,23 @@
           </template>
       </el-table-column>
       <el-table-column
-        label="No.Of Stations"
+        label="Total Stations"
         prop="stationNo"
-        align="center"
-        width="120">
+        align="center">
           <template slot-scope="{row}">
             <span>{{ row.stationNo }}</span>
           </template>
       </el-table-column>
       <el-table-column
-        label="No.Of Connectors"
+        label="Stations in Use"
+        prop="stationNo"
+        align="center">
+          <template slot-scope="{row}">
+            <span>{{ row.stationInUse || "0" }}</span>
+          </template>
+      </el-table-column>
+      <el-table-column
+        label="Total Connectors"
         prop="connectorNo"
         align="center"
         class-name="fixed-width">
@@ -93,6 +100,15 @@
             <span>{{ row.connectorNo }}</span>
           </template>
       </el-table-column>
+      <el-table-column
+        label="Connectors in Use"
+        prop="connectorNo"
+        align="center"
+        class-name="fixed-width">
+          <template slot-scope="{row}">
+            <span>{{ row.connectorInUse || "0" }}</span>
+          </template>
+      </el-table-column>
       <el-table-column
         v-if="visible.actions"
         label="Action"
@@ -183,6 +199,11 @@ export default {
       }).then((response) => {
         this.list = response.data
         this.total = response.total
+      }).catch(err => {
+        this.$message({
+          message: err,
+          type: 'error'
+        })
       }).finally(() => {
         this.listLoading = false
       })
@@ -218,7 +239,7 @@ export default {
           .then(() => {
             this.$notify({
               title: 'Success',
-              message: `delete user success ${row.siteName}`,
+              message: `delete site success ${row.siteName}`,
               type: 'success',
               duration: 2000
             })
@@ -226,7 +247,7 @@ export default {
           }).catch(() => {
             this.$notify({
               title: 'Failed',
-              message: `Delete User Error: ${error}`,
+              message: `Delete site error: ${error}`,
               type: 'error',
               duration: 5000
             })

+ 4 - 4
Strides-Admin/src/views/site/UpdateSite.vue

@@ -55,7 +55,7 @@
                     :value="item.value" />
               </el-select>
             </el-form-item-->
-            <el-form-item
+            <!-- <el-form-item
               prop="siteInformation.type"
               label="Type:">
               <div class="type-row" v-for="(item, index) in siteTypeTable">
@@ -72,7 +72,7 @@
                   placeholder="End Time"
                   :disabled="isSiteTypeEnable(index)"/>
               </div>
-            </el-form-item>
+            </el-form-item> -->
           </el-col>
 
           <el-col :span="12">
@@ -198,7 +198,7 @@
           </el-row>
         </el-form>
         <div class="sparator"></div>
-        <!-- <div class="section-title">
+        <div class="section-title">
           TIME CONFIGURATION
         </div>
         <el-table
@@ -240,7 +240,7 @@
             </template>
           </el-table-column>
         </el-table>
-        <div class="sparator"></div> -->
+        <div class="sparator"></div>
         <div class="section-title">
           ADDRESS
         </div>

+ 123 - 0
Strides-Admin/src/views/user/TopUp.vue

@@ -0,0 +1,123 @@
+<template>
+  <el-dialog
+    title="MANUAL TOP UP"
+    :visible="visible"
+    custom-class="toptop-dialog"
+    :before-close="hideDialog"
+    :close-on-click-modal="false">
+    <el-form
+      ref="topUpForm"
+      :model="this"
+      :rules="rules"
+      label-width="140px"
+      label-position="left">
+      <el-form-item
+        label="Current Amount:">
+        <el-input
+          class="input-text"
+          :value="userInfo.currencySymbol + ' ' + userInfo.credit"
+          readonly/>
+      </el-form-item>
+      <el-form-item
+        label="Top Up Amount:"
+        prop="amount">
+        <el-input
+          class="input-text"
+          v-model="amount"
+          maxlength="5"
+          :placeholder="userInfo.currencySymbol"/>
+      </el-form-item>
+      <div class="flexcc" style="padding-top: 20px;">
+        <el-button
+          class="cancel-button"
+          @click="hideDialog">
+          Cancel
+        </el-button>
+        <el-button
+          type="primary"
+          @click="clickTopUp"
+          :loading="loading">
+          Top Up
+        </el-button>
+      </div>
+    </el-form>
+  </el-dialog>
+</template>
+
+<script>
+import api from '@/http/api/userManagement'
+export default {
+  name: "TopUp",
+  props: {
+    visible: {
+      type: Boolean,
+      default: false
+    },
+    userInfo: {
+      type: Object,
+      default: {}
+    }
+  },
+  data() {
+    return {
+      amount: "",
+      rules: {
+        amount: [{
+          required: true,
+          trigger: 'blur',
+          message: 'Please type amount',
+        }, {
+          pattern: /^[1-9]+\d*.?\d*$/,
+          trigger: 'blur',
+          message: 'Please type a correct number'
+        }]
+      },
+      loading: false
+    };
+  },
+  mounted() {
+    
+  },
+  methods: {
+    hideDialog() {
+      this.$emit("hide");
+    },
+    clickTopUp() {
+      this.$refs.topUpForm.validate((valid) => {
+        if (valid) {
+          this.toTopUp();
+        }
+      })
+    },
+    toTopUp() {
+      this.loading = true;
+      api.userTopup({
+        userPk: this.userInfo.userPk,
+        amount: this.amount
+      }).then(res => {
+        this.loading = false;
+        this.$message({
+          message: res.msg,
+          type: 'success',
+        })
+        this.amount = ""
+        this.$emit("success")
+      }).catch(err => {
+        this.loading = false;
+        this.$message({
+          message: err,
+          type: 'error',
+        })
+      })
+    }
+  }
+}
+</script>
+
+<style>
+  .toptop-dialog {
+    width: 100%;
+    padding: 0 10px;
+    max-width: 520px;
+  }
+</style>

+ 129 - 51
Strides-Admin/src/views/user/UserDetail.vue

@@ -5,18 +5,16 @@
         ref="userRef"
         :model="userModel"
         :rules="rules"
-        label-width="130px"
-        label-position="left"
-      >
+        label-width="140px"
+        label-position="left">
+        <div class="section-title">
+          Profile
+        </div>
         <el-row>
-          <div class="section-title">
-            Profile
-          </div>
-          <el-col :span="12">
+          <el-col :xs="24" :md="12">
             <el-form-item
               prop='profile.nickName'
-              label="Display Name:"
-            >
+              label="Display Name:">
               <el-input
                 class="input-text"
                 v-model="userModel.profile.nickName"
@@ -50,6 +48,53 @@
               </div>
             </el-form-item>
           </el-col>
+          <el-col :xs="24" :md="12" v-if="isEdit">
+            <el-form-item
+              label="Charging History:">
+              <div class="flexc">
+                <el-input
+                  class="input-text input-text-1"
+                  v-model="userInfo.chargingCount"
+                  readonly
+                />
+                <el-button
+                  type="primary"
+                  @click="toHistoryCharge">
+                  VIEW HISTORY
+                </el-button>
+              </div>
+            </el-form-item>
+            <el-form-item
+              label="Top-up History:">
+              <div class="flexc">
+                <el-input
+                  class="input-text input-text-1"
+                  v-model="userInfo.topUpCount"
+                  readonly
+                />
+                <el-button
+                  type="primary"
+                  @click="toHistoryTopup">
+                  VIEW HISTORY
+                </el-button>
+              </div>
+            </el-form-item>
+            <el-form-item
+              label="Credit Amount:">
+              <div class="flexc">
+                <el-input
+                  class="input-text input-text-1"
+                  :value="userInfo.currencySymbol + ' ' + userInfo.credit"
+                  readonly
+                />
+                <el-button
+                  type="success"
+                  @click="showTopupModal">
+                  TOP UP
+                </el-button>
+              </div>
+            </el-form-item>
+          </el-col>
         </el-row>
 
         <div class="sparator" ></div>
@@ -57,7 +102,7 @@
           Address
         </div>
         <el-row :gutter="20">
-          <el-col :span="12">
+          <el-col :xs="24" :md="12">
             <el-form-item
               label="Country:"
               prop="address.country"
@@ -73,7 +118,7 @@
               </el-select>
             </el-form-item>
           </el-col>
-          <el-col :span="12">
+          <el-col :xs="24" :md="12">
             <el-form-item
               label="Street:"
               prop="address.street"
@@ -85,7 +130,7 @@
           </el-col>
         </el-row>
         <el-row :gutter="20">
-          <el-col :span="12">
+          <el-col :xs="24" :md="12">
             <el-form-item
               label="City:"
               prop="address.city"
@@ -95,7 +140,7 @@
                 v-model="userModel.address.city" />
             </el-form-item>
           </el-col>
-          <el-col :span="12">
+          <el-col :xs="24" :md="12">
             <el-form-item
               label="Postal Code:"
               prop="address.zipCode"
@@ -139,15 +184,18 @@
               class="vehicle-input"
               v-model="vehicle.licensePlate" />
           </el-form-item>
-          <img
-            class="list-item-icon"
-            @click="handleClickSubVehicleButton(vehicle, index)"
-            src="../../assets/form-list-sub.png"/>
-          <img
-            v-if="index === userModel.vehicleList.length - 1"
-            class="list-item-icon"
-            @click="handleClickAddVehicleButton"
-            src="../../assets/form-list-add.png"/>
+          <div>
+            <img
+              class="list-item-icon"
+              @click="handleClickSubVehicleButton(vehicle, index)"
+              src="../../assets/form-list-sub.png"/>
+            <img
+              v-if="index === userModel.vehicleList.length - 1"
+              class="list-item-icon"
+              @click="handleClickAddVehicleButton"
+              src="../../assets/form-list-add.png"/>
+          </div>
+          
         </div>
 
         <div class="sparator" style="margin: 10px -80px;"></div>
@@ -167,6 +215,11 @@
         </div>
       </el-form>
     </div>
+    <TopUp
+      :visible="showTopup"
+      :userInfo="userInfo"
+      @hide="hideTopupModal"
+      @success="hideTopupModal(true)"/>
   </div>
 </template>
 
@@ -180,34 +233,22 @@ import {
 import { mapState } from 'vuex'
 import site from '../../http/api/site'
 import {getCountryList} from '../../utils/index.js'
-
+import TopUp from './TopUp.vue'
 export default {
   name: 'UserDetial',
   computed: {
     ...mapState('userManagement', ['selectedUser']),
   },
-  mounted() {
-    this.getCountryList()
-    if (this.selectedUser.userId) {
-      this.getUserInfo()
-    } else {
-      this.userModel.profile.hasAreaCode = true
-      this.userModel.vehicleList.push({
-        brand: '',
-        model: '',
-        licensePlate: '',
-      })
-    }
-  },
-  beforeRouteLeave(to, form, next) {
-    this.$store.commit('userManagement/RESET_SELECTED_USER')
-    next()
-  },
+  components: {TopUp},
   data() {
     return {
       loading: false,
       countryOptions: [],
       areaCodeOptions: [],
+      userInfo: {
+        credit: 0,
+        currencySymbol: "$"
+      },
       userModel: {
         profile: {
           userPk: '',
@@ -290,8 +331,28 @@ export default {
           }],
         }
       },
+      isEdit: false,
+      showTopup: false
+    }
+  },
+  mounted() {
+    this.getCountryList()
+    if (this.$route.params.id) {
+      this.isEdit = true;
+      this.getUserInfo()
+    } else {
+      this.userModel.profile.hasAreaCode = true
+      this.userModel.vehicleList.push({
+        brand: '',
+        model: '',
+        licensePlate: '',
+      })
     }
   },
+  beforeRouteLeave(to, form, next) {
+    this.$store.commit('userManagement/RESET_SELECTED_USER')
+    next()
+  },
   methods: {
     handleClickSubVehicleButton(vehicle, index) {
       const callback = () => {
@@ -428,7 +489,7 @@ export default {
       return phone
     },*/
     getUserInfo() {
-      getUser(this.selectedUser.userId)
+      getUser(this.$route.params.id)
       .then(({ data }) => {
         const {
           userPk,
@@ -442,10 +503,10 @@ export default {
         } = data
         this.userModel.profile.nickName = nickName
         this.userModel.profile.email = email
-        this.userModel.profile.areaCode = callingCode
+        this.userModel.profile.areaCode = callingCode + ""
         this.userModel.profile.phoneNumber = phone //this.getPhoneNumber(phone)
         this.userModel.profile.userPk = userPk
-
+        this.userInfo = data;
         const {
           street = '',
           zipCode = '',
@@ -476,12 +537,28 @@ export default {
 
         this.userModel.ocppTagResponse = ocppTagResponse
       })
+    },
+    showTopupModal() {
+      this.showTopup = true
+    },
+    hideTopupModal(success) {
+      this.showTopup = false;
+      if (success) {
+        this.getUserInfo()
+      }
+    },
+    toHistoryCharge() {
+      this.$router.push("/user-management/charging-history/" + this.$route.params.id)
+    },
+    toHistoryTopup() {
+      this.$router.push("/user-management/topup-history/" + this.$route.params.id)
     }
-  },
+  }
 }
 </script>
 
 <style scoped lang='scss'>
+  @import '../../styles/element-ui.scss';
   @import '../../styles/variables.scss';
 
   .view-container {
@@ -518,6 +595,11 @@ export default {
     width: 100%;
     max-width: 300px;
   }
+  
+  .input-text-1 {
+    flex: 1;
+    margin-right: 10px;
+  }
 
   .area-code {
     width: 75px;
@@ -531,6 +613,7 @@ export default {
 
   .vehicle-list-view-item {
     display: flex;
+    flex-wrap: wrap;
     align-items: center;
   }
 
@@ -549,19 +632,14 @@ export default {
   .cancel-button {
     width: 94px;
     height: 40px;
-    color: #555;
-    background: #FFFFFF;
-    border: 1px solid #001489;
-    box-sizing: border-box;
-    border-radius: 4px;
   }
 
   .confirm-button {
     width: 94px;
     height: 40px;
     margin-left: 20px;
-    background: #001489;
-    border: 1px solid #001489;
+    background: $--color-primary;
+    border: 1px solid $--color-primary;
     box-sizing: border-box;
     border-radius: 4px;
   }

+ 2 - 2
Strides-Admin/src/views/user/UserManagement.vue

@@ -193,8 +193,8 @@ export default {
       this.$router.push({ path: '/user-management/add-user' })
     },
     handleUpdateUser(user, index) {
-      this.$store.commit('userManagement/SET_SELECTED_USER', user)
-      this.$router.push({ path: '/user-management/update-user' })
+      //this.$store.commit('userManagement/SET_SELECTED_USER', user)
+      this.$router.push({ path: '/user-management/update-user/' + user.userId })
     },
     handleDeleteUser(row, index) {
       this.$confirm('Are you sure you want to delete this user?', 'Delete', {

+ 135 - 0
Strides-Admin/src/views/user/hisCharge.vue

@@ -0,0 +1,135 @@
+<template>
+  <div class="app-container">
+    <div class="filter-container">
+      <div class="flexc">
+        <div class="back-icon" @click="goBack">
+          <i class="el-icon el-icon-back"></i>
+        </div>
+        <div class="section-title">Charging History</div>
+      </div>
+    </div>
+    <el-table
+      v-loading="loading"
+      :data="tableData.list"
+      fit>
+      <el-table-column
+        :label="item.label"
+        align="center"
+        class-name="fixed-width"
+        v-for="(item, index) in columns"
+        :key="index"
+        :width="item.width"
+        :prop="item.prop"/>
+      </el-table>
+    </el-table>
+    <div class="right">
+      <Pagination
+        v-show="tableData.total > 0"
+        :total="tableData.total"
+        :page.sync="tableData.pageNo"
+        :limit.sync="tableData.pageSize"
+        @pagination="getTableData" />
+    </div>
+  </div>
+</template>
+
+<script>
+import api from '@/http/api/userManagement'
+import Pagination from '@/components/Pagination'
+export default {
+  data() {
+    return {
+      loading: false,
+      tableData: {
+        pageSize: 10,
+        pageNo: 1,
+        total: 0,
+        list: []
+      },
+      columns: [{
+        prop: "transactionId",
+        label: "Transaction ID"
+      },{
+        prop: "vehicle",
+        label: "Vehicle"
+      },{
+        prop: "chargeBoxId",
+        label: "Station ID"
+      },{
+        prop: "connectorId",
+        label: "Connector"
+      },{
+        prop: "startDateTime",
+        label: "Start Date/Time"
+      },{
+        prop: "endDateTime",
+        label: "End Date/Time"
+      },{
+        prop: "power",
+        label: "Power (kWh)"
+      },{
+        prop: "rate",
+        label: "Rate"
+      },{
+        prop: "charges",
+        label: "Charges"
+      }]
+    }
+  },
+  components: { Pagination },
+  created() {
+    if (this.$route.params.id) {
+      this.getTableData()
+    }
+  },
+  methods: {
+    goBack() {
+      this.$router.push({ path: '/user-management/update-user/' + this.$route.params.id })
+    },
+    getTableData() {
+      this.loading = true;
+      api.pageChargeHistory({
+        pageNo: this.tableData.pageNo,
+        pageSize: this.tableData.pageSize,
+        pageVo: {
+          userPk: this.$route.params.id
+        }
+      }).then(res => {
+        this.loading = false;
+        if (res.total) {
+          this.tableData.list = res.data
+          this.tableData.total = res.total
+        }
+      }).catch(err => {
+        this.loading = false;
+        this.$message({
+          message: err,
+          type: 'error',
+        })
+      })
+    }
+  }
+}
+</script>
+
+<style scoped>
+  .back-icon {
+    width: 44px;
+    height: 44px;
+    padding: 10px;
+    display: flex;
+    cursor: pointer;
+    font-size: 18px;
+    align-items: center;
+  }
+  .section-title {
+    color: #333333;
+    font-size: 16px;
+    line-height: 24px;
+    margin-top: 10px;
+    margin-bottom: 10px;
+    font-weight: 500;
+    font-family: sans-serif;
+    text-transform: uppercase;
+  }
+</style>

+ 129 - 0
Strides-Admin/src/views/user/hisTopUp.vue

@@ -0,0 +1,129 @@
+<template>
+  <div class="app-container">
+    <div class="filter-container">
+      <div class="flexc">
+        <div class="back-icon" @click="goBack">
+          <i class="el-icon el-icon-back"></i>
+        </div>
+        <div class="section-title">Top Up History</div>
+      </div>
+    </div>
+    <el-table
+      v-loading="loading"
+      :data="tableData.list"
+      fit>
+      <el-table-column
+        :label="item.label"
+        align="center"
+        class-name="fixed-width"
+        v-for="(item, index) in columns"
+        :key="index"
+        :width="item.width"
+        :prop="item.prop"/>
+      </el-table>
+    </el-table>
+    <div class="right">
+      <Pagination
+        v-show="tableData.total > 0"
+        :total="tableData.total"
+        :page.sync="tableData.pageNo"
+        :limit.sync="tableData.pageSize"
+        @pagination="getTableData" />
+    </div>
+  </div>
+</template>
+
+<script>
+import api from '@/http/api/userManagement'
+import Pagination from '@/components/Pagination'
+export default {
+  data() {
+    return {
+      loading: false,
+      tableData: {
+        pageSize: 10,
+        pageNo: 1,
+        total: 0,
+        list: []
+      },
+      columns: [{
+        prop: "transactionId",
+        label: "Transaction ID"
+      },{
+        prop: "topUpType",
+        label: "Top Up Type"
+      },{
+        prop: "amount",
+        label: "Amount"
+      },{
+        prop: "creationTime",
+        label: "Creation Time"
+      },{
+        prop: "paymentStatus",
+        label: "Payment Status"
+      },{
+        prop: "paymentReference",
+        label: "Payment Reference"
+      },{
+        prop: "updateTime",
+        label: "Update Time"
+      }]
+    }
+  },
+  components: { Pagination },
+  created() {
+    if (this.$route.params.id) {
+      this.getTableData()
+    }
+  },
+  methods: {
+    goBack() {
+      this.$router.push({ path: '/user-management/update-user/' + this.$route.params.id })
+    },
+    getTableData() {
+      this.loading = true;
+      api.pageTopupHistory({
+        pageNo: this.tableData.pageNo,
+        pageSize: this.tableData.pageSize,
+        pageVo: {
+          userPk: this.$route.params.id
+        }
+      }).then(res => {
+        this.loading = false;
+        if (res.total) {
+          this.tableData.list = res.data
+          this.tableData.total = res.total
+        }
+      }).catch(err => {
+        this.loading = false;
+        this.$message({
+          message: err,
+          type: 'error',
+        })
+      })
+    }
+  }
+}
+</script>
+
+<style scoped>
+  .back-icon {
+    width: 44px;
+    height: 44px;
+    padding: 10px;
+    display: flex;
+    cursor: pointer;
+    font-size: 18px;
+    align-items: center;
+  }
+  .section-title {
+    color: #333333;
+    font-size: 16px;
+    line-height: 24px;
+    margin-top: 10px;
+    margin-bottom: 10px;
+    font-weight: 500;
+    font-family: sans-serif;
+    text-transform: uppercase;
+  }
+</style>