vbea 3 лет назад
Родитель
Сommit
a90a603b7f

+ 6 - 2
Strides-Admin/src/components/Pagination.vue

@@ -89,7 +89,12 @@ export default {
   }
 }
 </script>
-
+<style lang="scss" scoped="scoped">
+  @import '../styles/element-ui.scss';
+  .pagination-container ::v-deep .el-pagination.is-background .el-pager li:not(.disabled).active {
+    background-color: $--color-primary;
+  }
+</style>
 <style scoped="scoped">
 .pagination-container {
   background: #fff;
@@ -105,7 +110,6 @@ export default {
 }
 .pagination-container >>> .el-pagination.is-background .el-pager li:not(.disabled).active {
   color: #fff;
-  background-color: #001489;
 }
 .pagination-container >>> .btn-prev,
 .pagination-container >>> .btn-next {

+ 16 - 4
Strides-Admin/src/components/TableAction.vue

@@ -1,12 +1,12 @@
 <template>
   <div class="table-actions">
     <div class="table-action action-edit" @click="handleEdit()" v-if="showEdit">
-      <img src="../assets/ic-update.png"/>
-      <span>Edit</span>
+      <img v-if="showIcon" src="../assets/ic-update.png"/>
+      <span>{{editText}}</span>
      </div>
     <div class="table-action action-delete" @click="handleDelete()" v-if="showDel">
-      <img src="../assets/ic-delete.png" />
-      <span>Delete</span>
+      <img v-if="showIcon" src="../assets/ic-delete.png" />
+      <span>{{deleteText}}</span>
     </div>
   </div>
 </template>
@@ -15,6 +15,14 @@
   export default {
     name: 'TableAction',
     props: {
+      editText: {
+        type: String,
+        default: "Edit"
+      },
+      deleteText: {
+        type: String,
+        default: "Delete"
+      },
       showDel: {
         type: Boolean,
         default: true
@@ -22,6 +30,10 @@
       showEdit: {
         type: Boolean,
         default: true
+      },
+      showIcon: {
+        type: Boolean,
+        default: true
       }
     },
     methods: {

+ 7 - 0
Strides-Admin/src/main.js

@@ -13,6 +13,13 @@ import locale from 'element-ui/lib/locale/lang/en'
 
 Vue.use(ElementUI, { locale })
 Vue.use(vueWaves)
+Vue.prototype.$openRoute = (route) => {
+  let sharpe = "#"
+  if (route.indexOf("/") !== 0) {
+    sharpe += "/";
+  }
+  window.open(location.origin + location.pathname + sharpe + route);
+}
 
 new Vue({
   el: '#app',

+ 2 - 1
Strides-Admin/src/views/charge/Connectors.vue

@@ -312,7 +312,8 @@
         ocpp.sendPerform(api, params).then(res => {
           this.listLoading = false;
           if (res.data.taskId) {
-            this.$router.push({path: '/ocpp-operations/result/' + res.data.taskId});
+            this.$openRoute("/ocpp-operations/result/" + res.data.taskId);
+            //this.$router.push({path: '/ocpp-operations/result/' + res.data.taskId});
           }
         }).catch(err => {
           this.listLoading = false;

+ 2 - 1
Strides-Admin/src/views/charge/RegisteredChargeStations.vue

@@ -303,7 +303,8 @@ export default {
       ocpp.sendPerform("ocppOperations/reset", params).then(res => {
         this.listLoading = false;
         if (res.data.taskId) {
-          this.$router.push({path: '/ocpp-operations/result/' + res.data.taskId});
+          this.$openRoute("/ocpp-operations/result/" + res.data.taskId);
+          //this.$router.push({path: '/ocpp-operations/result/' + res.data.taskId});
         }
       }).catch(err => {
         this.listLoading = false;

+ 69 - 1
Strides-Admin/src/views/charging/ConfigureStations.vue

@@ -46,13 +46,54 @@
         label="Validity Period"
         align="center"
         prop="validityPeriod"/>
+      <el-table-column
+        label="Action"
+        align="center"
+        prop="description">
+        <template slot-scope="{row}">
+          <el-dropdown
+            class="action-dropdown"
+            @command="(v) => handleCommand(v, row)">
+            <i class="el-icon-more icon-action"></i>
+            <el-dropdown-menu slot="dropdown">
+              <el-dropdown-item
+                command="editChargingProfile"
+                v-if="row.description">
+                Edit Charging Profile
+              </el-dropdown-item>
+              <el-dropdown-item
+                command="setChargingProfile"
+                v-else>
+                Set Charging Profile
+              </el-dropdown-item>
+              <el-dropdown-item
+                command="clearChargingProfile"
+                v-if="row.description">
+                Clear Charging Profile
+              </el-dropdown-item>
+            </el-dropdown-menu>
+          </el-dropdown>
+        </template>
+      </el-table-column>
     </el-table>
+    <DialogSetProfiles
+      :visible="actionDialog.visible"
+      :item="actionDialog.item"
+      :isEdit="actionDialog.isEdit"
+      @hide="hideDialog"/>
+    <DialogClearProfiles
+      :item="actionDialog.item"
+      :visible="actionDialog.isClear"
+      @hide="hideDialog"/>
   </div>
 </template>
 
 <script>
 import api from '../../http/api/chargingProfile.js'
+import ocpp from '../../http/api/ocpp'
 import Pagination from '@/components/Pagination'
+import DialogSetProfiles from './components/DialogSetProfiles.vue'
+import DialogClearProfiles from './components/DialogClearProfiles.vue'
 export default {
   data() {
     return {
@@ -68,9 +109,15 @@ export default {
           criteria: ""
         }
       },
+      actionDialog: {
+        item: {},
+        isEdit: false,
+        isClear: false,
+        visible: false
+      }
     }
   },
-  components: { Pagination },
+  components: { Pagination, DialogSetProfiles, DialogClearProfiles },
   created() {
     this.getTableData();
   },
@@ -91,6 +138,27 @@ export default {
       this.$router.push(({
         path: "/charging-profiles/view/" + row.chargingProfilePk
       }))
+    },
+    handleCommand(cb, item) {
+      this[cb](item)
+    },
+    hideDialog() {
+      this.actionDialog.isClear = false;
+      this.actionDialog.visible = false;
+    },
+    setChargingProfile(row) {
+      this.actionDialog.isEdit = false;
+      this.actionDialog.visible = true;
+      this.actionDialog.item = row;
+    },
+    editChargingProfile(row) {
+      this.actionDialog.isEdit = true;
+      this.actionDialog.visible = true;
+      this.actionDialog.item = row;
+    },
+    clearChargingProfile(row) {
+      this.actionDialog.item = row;
+      this.actionDialog.isClear = true;
     }
   }
 }

+ 233 - 0
Strides-Admin/src/views/charging/components/DialogClearProfiles.vue

@@ -0,0 +1,233 @@
+<template>
+  <el-dialog
+    class="dialog-profile"
+    :visible="visible"
+    :before-close="hideDialog"
+    title="Clear Charging Profile">
+    <el-form
+      ref="setForm"
+      :model="params"
+      :rules="rules">
+      <div class="form-row">
+        <div class="label">Filter Type:</div>
+        <el-form-item
+          prop="filterType"
+          class="form-item">
+          <el-select
+            v-model="params.filterType"
+            class="flex-item"
+            clearable
+            @change="changeFilterType">
+            <el-option
+              v-for="(item, index) in filterTypeOptions"
+              :key="index"
+              :label="item.name"
+              :value="item.value"/>
+          </el-select>
+        </el-form-item>
+      </div>
+      <div class="form-row" v-if="params.filterType == 'ChargingProfileId'">
+        <div class="label">CURRENT CHARGING PROFILE:</div>
+        <div
+          class="underline"
+          v-if="item.description"
+          @click="viewProfiles">
+          {{item.description}}
+        </div>
+      </div>
+      <template v-else-if="params.filterType == 'OtherParameters'">
+        <div class="form-row">
+          <div class="label">Charging Profile Purpose:</div>
+          <el-form-item
+            prop="chargingProfilePurpose"
+            class="form-item">
+            <el-select
+              clearable
+              v-model="params.chargingProfilePurpose"
+              class="flex-item">
+              <el-option
+                v-for="(item, index) in chargingPurposeOptions"
+                :key="index"
+                :label="item.name"
+                :value="item.value"/>
+            </el-select>
+          </el-form-item>
+        </div>
+        <div class="form-row">
+          <div class="label">Stack Level (Integer):</div>
+          <el-form-item
+            prop="filterType"
+            class="form-item">
+            <el-input
+              v-model="params.stackLevel"
+              class="flex-item"/>
+          </el-form-item>
+        </div>
+      </template>
+      <div class="flexcc">
+        <el-button
+          class="button"
+          type="primary"
+          :loading="loading"
+          @click="onClearProfiles">
+          CLEAR
+        </el-button>
+      </div>
+    </el-form>
+  </el-dialog>
+</template>
+
+<script>
+import ocpp from '@/http/api/ocpp'
+import chargeProfile from '@/http/api/chargingProfile'
+export default {
+  name: "DialogClearProfiles",
+  props: {
+    visible: {
+      type: Boolean,
+      default: false
+    },
+    item: {
+      type: Object,
+      default: {}
+    }
+  },
+  data() {
+    return {
+      loading: false,
+      params: {
+        filterType: "ChargingProfileId",
+        connectorId: "",
+        stackLevel: "",
+        chargingProfilePurpose: ""
+      },
+      filterTypeOptions: [],
+      chargingProfileOptions: [],
+      chargingPurposeOptions: [],
+      rules: {
+        filterType: {
+          required: true,
+          trigger: 'change',
+          message: 'Please select a type'
+        },
+        chargingProfilePurpose: {
+          required: true,
+          trigger: 'change',
+          message: 'Please select a profile purpose'
+        }
+      }
+    };
+  },
+  mounted() {
+    this.getFilterTypeOptions();
+    this.getProfileOptions();
+  },
+  methods: {
+    hideDialog() {
+      this.$emit("hide");
+      this.params = {
+        filterType: "ChargingProfileId",
+        stackLevel: "",
+        chargingProfilePurpose: ""
+      }
+    },
+    getProfileOptions() {
+      ocpp.getChargingProfileList().then(res => {
+        if (res.data) {
+          this.chargingProfileOptions = res.data;
+        }
+      })
+    },
+    getFilterTypeOptions() {
+      ocpp.getClearChargingProfileFilterType().then(res => {
+        if (res.data) {
+          this.filterTypeOptions = res.data;
+          if (res.data.length > 0) {
+            this.params.filterType = res.data[0].value;
+          }
+        }
+      })
+      this.getPurposeOptions();
+    },
+    getPurposeOptions() {
+      chargeProfile.getPurposeOptionList().then(res => {
+        if (res.data) {
+          this.chargingPurposeOptions = res.data;
+        }
+      })
+    },
+    viewProfiles() {
+      this.$openRoute("/charging-profiles/view/" + this.item.chargingProfilePk);
+    },
+    changeFilterType() {
+      //ChargingProfileId
+      this.params.stackLevel = "";
+      this.params.chargingProfilePurpose = "";
+      this.$refs['setForm'].clearValidate();
+    },
+    onClearProfiles() {
+      this.$refs['setForm'].validate(result => {
+        if (result) {
+          this.clearChargingProfile();
+        }
+      });
+    },
+    clearChargingProfile() {
+      this.loading = true;
+      const params = {
+        stationIds: [this.item.chargeBoxId],
+        ...this.params
+      }
+      if (this.params.filterType == "ChargingProfileId") {
+        params.chargingProfilePk = this.item.chargingProfilePk
+        params.chargingProfilePurpose = undefined;
+      } else {
+        params.connectorId = this.item.connectorId
+      }
+      ocpp.sendPerform("ocppOperations/clearChargingProfile", params).then(res => {
+        this.hideDialog();
+        this.loading = false;
+        if (res.data.taskId) {
+          this.$openRoute("/ocpp-operations/result/" + res.data.taskId);
+          //this.$router.push({path: '/ocpp-operations/result/' + res.data.taskId});
+        }
+      }).catch(err => {
+        this.loading = false;
+        this.$message({
+          type: 'error',
+          message: err
+        })
+      });
+    }
+  }
+}
+</script>
+
+<style scoped>
+.dialog-profile >>> .el-dialog {
+  width: 100%;
+  max-width: 500px;
+}
+.form-row {
+  padding: 10px 0;
+}
+.label {
+  color: #000;
+  font-size: 14px;
+  line-height: 21px;
+  font-weight: bold;
+  padding-bottom: 10px;
+}
+.form-text {
+  color: #333;
+  font-size: 14px;
+}
+.form-item {
+  margin-bottom: 0;
+}
+.button {
+  margin-top: 20px;
+  padding: 10px 40px;
+  border-radius: 2px;
+}
+</style>

+ 172 - 0
Strides-Admin/src/views/charging/components/DialogSetProfiles.vue

@@ -0,0 +1,172 @@
+<template>
+  <el-dialog
+    class="dialog-profile"
+    :visible="visible"
+    :before-close="hideDialog"
+    :title='isEdit ? "Edit Charging Profile" : "Set Charging Profile"'>
+    <el-form
+      ref="setForm"
+      :model="this"
+      :rules="rules">
+      <div class="flexc">
+        <div class="form-row flex1">
+          <div class="label">Station ID:</div>
+          <div class="form-text">{{item.chargeBoxId}}</div>
+        </div>
+        <div class="form-row flex1">
+          <div class="label">Connector ID:</div>
+          <div class="form-text">{{item.connectorId}}</div>
+        </div>
+      </div>
+      <div class="form-row" v-if="isEdit">
+        <div class="label">CURRENT CHARGING PROFILE:</div>
+        <div
+          class="underline"
+          v-if="item.description"
+          @click="viewProfiles">
+          {{item.description}}
+        </div>
+      </div>
+      <div class="form-row">
+        <div class="label">{{isEdit ? "CHANGE CHARGING PROFILE TO:" : "CHARGING PROFILE:"}}</div>
+        <el-form-item
+          prop="chargingProfilePk">
+          <el-select
+            class="flex-item"
+            clearable
+            v-model="chargingProfilePk">
+            <el-option
+              v-for="(item, index) in chargingProfileOptions"
+              :key="index"
+              :label="item.value + ' (' + item.name + ')'"
+              :value="item.value"/>
+          </el-select>
+        </el-form-item>
+      </div>
+      <div class="flexcc">
+        <el-button
+          class="button"
+          type="primary"
+          :loading="loading"
+          @click="onSetProfiles">
+          SET
+        </el-button>
+      </div>
+    </el-form>
+  </el-dialog>
+</template>
+
+<script>
+import ocpp from '@/http/api/ocpp'
+export default {
+  name: "DialogSetProfiles",
+  props: {
+    visible: {
+      type: Boolean,
+      default: false
+    },
+    isEdit: {
+      type: Boolean,
+      default: false
+    },
+    item: {
+      type: Object,
+      default: {}
+    }
+  },
+  data() {
+    return {
+      loading: false,
+      chargingProfilePk: "",
+      chargingProfileOptions: [],
+      rules: {
+        chargingProfilePk: {
+          required: true,
+          trigger: 'change',
+          message: 'Please select a profile'
+        }
+      }
+    };
+  },
+  mounted() {
+    this.getProfileOptions();
+  },
+  methods: {
+    hideDialog() {
+      this.$emit("hide");
+      this.chargingProfilePk = "";
+      this.$nextTick(() => {
+        this.$refs['setForm'].clearValidate();
+      })
+    },
+    getProfileOptions() {
+      ocpp.getChargingProfileList().then(res => {
+        if (res.data) {
+          this.chargingProfileOptions = res.data
+        }
+      })
+    },
+    viewProfiles() {
+      this.$openRoute("/charging-profiles/view/" + this.item.chargingProfilePk)
+      /*this.$router.push(({
+        path: "/charging-profiles/view/" + this.item.chargingProfilePk
+      }))*/
+    },
+    onSetProfiles() {
+      this.$refs['setForm'].validate(result => {
+        if (result) {
+          this.setChargingProfile();
+        }
+      });
+    },
+    setChargingProfile() {
+      this.loading = true;
+      const params = {
+        connectorId: this.item.connectorId,
+        stationIds: [this.item.chargeBoxId],
+        chargingProfilePk: this.chargingProfilePk
+      }
+      ocpp.sendPerform("ocppOperations/setChargingProfile", params).then(res => {
+        this.hideDialog();
+        this.loading = false;
+        if (res.data.taskId) {
+          this.$openRoute("/ocpp-operations/result/" + res.data.taskId);
+          //this.$router.push({path: '/ocpp-operations/result/' + res.data.taskId});
+        }
+      }).catch(err => {
+        this.loading = false;
+        this.$message({
+          type: 'error',
+          message: err
+        })
+      });
+    }
+  }
+}
+</script>
+
+<style scoped>
+.dialog-profile >>> .el-dialog {
+  width: 100%;
+  max-width: 500px;
+}
+.form-row {
+  padding: 10px 0;
+}
+.label {
+  color: #000;
+  font-size: 14px;
+  line-height: 21px;
+  font-weight: bold;
+  padding-bottom: 10px;
+}
+.form-text {
+  color: #333;
+  font-size: 14px;
+}
+.button {
+  margin-top: 20px;
+  padding: 10px 40px;
+  border-radius: 2px;
+}
+</style>