Connectors.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  1. <template>
  2. <div class="app-container">
  3. <div class="filter-container">
  4. <div class="filter-view">
  5. <div
  6. v-if="sitePk"
  7. class="back-icon"
  8. @click="goBack">
  9. <i class="el-icon el-icon-back"></i>
  10. </div>
  11. <el-select
  12. v-model="filter.pageVo.errorCode"
  13. placeholder="Error Code"
  14. @change="handleFilter"
  15. class="filter-view-item"
  16. clearable>
  17. <el-option
  18. v-for="(item,index) in errCodeOptions"
  19. :key="index"
  20. :label="item.name"
  21. :value="item.value"/>
  22. </el-select>
  23. <el-select
  24. v-model="filter.pageVo.status"
  25. placeholder="Status"
  26. @change="handleFilter"
  27. class="filter-view-item"
  28. clearable>
  29. <el-option
  30. v-for="(item,index) in statusOptions"
  31. :key="index"
  32. :label="item.name"
  33. :value="item.value"/>
  34. </el-select>
  35. <div class="flex1" style="max-width: 500px;">
  36. <el-input
  37. v-model="filter.pageVo.criteria"
  38. prefix-icon="el-icon-search"
  39. placeholder="Search by Station ID, Site Name, Carpark Code, Vendor Error Code"
  40. @keyup.enter.native="handleFilter"
  41. @change="handleFilter"
  42. clearable/>
  43. </div>
  44. <el-button
  45. type="primary"
  46. icon="el-icon-search"
  47. @click="handleFilter">
  48. Search
  49. </el-button>
  50. </div>
  51. </div>
  52. <el-table
  53. v-loading="listLoading"
  54. :data="connectorList"
  55. class="no-border"
  56. style="width: 100%;min-height: 65vh;">
  57. <el-table-column
  58. label="Station ID"
  59. prop="sitePk"
  60. align="center"
  61. min-width="120">
  62. <template slot-scope="{row}">
  63. <span>{{ row.chargeBoxId }}</span>
  64. </template>
  65. </el-table-column>
  66. <el-table-column
  67. label="Site Name"
  68. prop="sitePk"
  69. align="center"
  70. min-width="120">
  71. <template slot-scope="{row}">
  72. <span>{{ row.siteName }}</span>
  73. </template>
  74. </el-table-column>
  75. <el-table-column
  76. label="Carpark Code"
  77. prop="carParkCode"
  78. align="center"
  79. min-width="120"/>
  80. <!--el-table-column
  81. label="Service Provider"
  82. prop="sitePk"
  83. align="center"
  84. width="180">
  85. <template slot-scope="{row}">
  86. <span>{{ row.providerName }}</span>
  87. </template>
  88. </el-table-column-->
  89. <el-table-column
  90. label="ERC"
  91. align="center"
  92. width="120"
  93. v-if="enableEVCPID">
  94. <template slot-scope="{row}">
  95. <span>{{ (row.evcpId || "NA") + "-" + row.connectorId }}</span>
  96. </template>
  97. </el-table-column>
  98. <el-table-column
  99. label="Connector ID"
  100. prop="sitePk"
  101. align="center"
  102. min-width="120">
  103. <template slot-scope="{row}">
  104. <span>{{ row.connectorId }}</span>
  105. </template>
  106. </el-table-column>
  107. <el-table-column
  108. label="Last Status Update"
  109. prop="sitePk"
  110. align="center"
  111. min-width="150">
  112. <template slot-scope="{row}">
  113. <span>{{ row.dateTime }}</span>
  114. </template>
  115. </el-table-column>
  116. <el-table-column
  117. label="Status"
  118. prop="sitePk"
  119. align="center"
  120. min-width="80">
  121. <template slot-scope="{row}">
  122. <span>{{ row.status }}</span>
  123. </template>
  124. </el-table-column>
  125. <el-table-column
  126. label="Error Code"
  127. prop="sitePk"
  128. align="center"
  129. min-width="100">
  130. <template slot-scope="{row}">
  131. <span>{{ row.errorCode }}</span>
  132. </template>
  133. </el-table-column>
  134. <el-table-column
  135. label="Vendor Error Code"
  136. prop="sitePk"
  137. align="center"
  138. min-width="150">
  139. <template slot-scope="{row}">
  140. <span>{{ row.vendorErrorCode }}</span>
  141. </template>
  142. </el-table-column>
  143. <el-table-column
  144. label="Action"
  145. prop="sitePk"
  146. align="center"
  147. width="70">
  148. <template slot-scope="{row}">
  149. <!-- <TableAction /> -->
  150. <el-dropdown
  151. class="action-dropdown"
  152. @command="(v) => handleCommand(v, row)">
  153. <i class="el-icon-more icon-action"></i>
  154. <el-dropdown-menu slot="dropdown">
  155. <el-dropdown-item
  156. command="showConnectorQR">
  157. QRCode
  158. </el-dropdown-item>
  159. <el-dropdown-item
  160. command="showWebPosQR"
  161. v-if="enableWebPos">
  162. WebPosQR
  163. </el-dropdown-item>
  164. <el-dropdown-item
  165. command="changeToAvailable"
  166. v-if='row.status == "Unavailable"'>
  167. Change Availability to Available
  168. </el-dropdown-item>
  169. <el-dropdown-item
  170. command="changeToUnavailable"
  171. v-else>
  172. Change Availability to Unavailable
  173. </el-dropdown-item>
  174. <el-dropdown-item
  175. command="unlockConnector">
  176. Unlock Connector
  177. </el-dropdown-item>
  178. <el-dropdown-item
  179. command="remoteStart"
  180. v-if='row.status == "Preparing"'>
  181. Remote Start Transaction
  182. </el-dropdown-item>
  183. <el-dropdown-item
  184. command="remoteStop"
  185. v-if='row.status == "Charging"'>
  186. Remote Stop Transaction
  187. </el-dropdown-item>
  188. </el-dropdown-menu>
  189. </el-dropdown>
  190. </template>
  191. </el-table-column>
  192. </el-table>
  193. <div class="right">
  194. <pagination
  195. v-show="total > 0"
  196. :total="total"
  197. :page.sync="filter.pageNo"
  198. :limit.sync="filter.pageSize"
  199. @pagination="getConnectorList" />
  200. </div>
  201. <ConnectorTags
  202. :visible="printConnector.visible"
  203. :qrCode="printConnector.qrCode"
  204. @hide="hideConnectorQR"/>
  205. <DialogRemoteOcpp
  206. v-bind="actionDialog"
  207. @hide="hideActionDialog"/>
  208. <WebPosQR
  209. v-bind="webPosDialog"
  210. @hide="hideConnectorQR"/>
  211. </div>
  212. </template>
  213. <script>
  214. import Pagination from '@/components/Pagination'
  215. import TableAction from '@/components/TableAction.vue'
  216. import ConnectorTags from './components/ConnectorTags.vue'
  217. import WebPosQR from './components/WebPosQR.vue'
  218. import DialogRemoteOcpp from './components/DialogRemoteOcpp.vue'
  219. import api from '../../http/api/charge'
  220. import ocpp from '../../http/api/ocpp'
  221. import settings from '../../settings.js'
  222. export default {
  223. components: { Pagination, TableAction, ConnectorTags, DialogRemoteOcpp,WebPosQR },
  224. data() {
  225. return {
  226. filter: {
  227. pageNo: 1,
  228. pageSize: 10,
  229. pageVo: {
  230. criteria: '',
  231. status: '',
  232. errorCode: ''
  233. }
  234. },
  235. listLoading: true,
  236. connectorList: [],
  237. total: 0,
  238. statusOptions: [],
  239. errCodeOptions: [],
  240. printConnector: {
  241. qrCode: "",
  242. visible: false
  243. },
  244. sitePk: "",
  245. actionDialog: {
  246. visible: false,
  247. isStart: true,
  248. item: {}
  249. },
  250. webPosDialog: {
  251. visible: false,
  252. item: {}
  253. },
  254. enableWebPos: settings.enableWebPos,
  255. enableEVCPID: settings.enableEVCPID
  256. }
  257. },
  258. created() {
  259. if (this.$route.params.id) {
  260. this.filter.sitePk = this.sitePk = this.$route.params.id;
  261. }
  262. this.getStatusOption();
  263. this.getErrorCodeOptions();
  264. },
  265. methods: {
  266. goBack() {
  267. this.$router.push({
  268. path: "/site-management-v2/edit/" + this.sitePk
  269. })
  270. },
  271. handleFilter() {
  272. this.filter.pageNo = 1;
  273. this.getConnectorList();
  274. },
  275. getStatusOption() {
  276. api.getStatusList().then(res => {
  277. if (res.data.length > 0) {
  278. res.data.forEach(item => {
  279. this.statusOptions.push({
  280. name: item,
  281. value: item
  282. })
  283. })
  284. }
  285. this.getConnectorList();
  286. }).catch(err => {
  287. this.$message.error(err)
  288. })
  289. },
  290. getErrorCodeOptions() {
  291. api.getErrorCodeOption().then(res => {
  292. if (res.data.length > 0) {
  293. res.data.forEach(item => {
  294. this.errCodeOptions.push({
  295. name: item,
  296. value: item
  297. })
  298. })
  299. }
  300. this.getConnectorList();
  301. }).catch(err => {
  302. this.$message.error(err)
  303. })
  304. },
  305. getConnectorList() {
  306. this.listLoading = true;
  307. api.getConnectorList(this.filter).then(res => {
  308. this.listLoading = false;
  309. this.total = res.total;
  310. this.connectorList = res.data;
  311. }).catch(err => {
  312. this.$message.error(err)
  313. this.listLoading = false;
  314. })
  315. },
  316. handleCommand(cb, item) {
  317. this[cb](item)
  318. },
  319. showConnectorQR(row) {
  320. this.printConnector.visible = true;
  321. this.printConnector.qrCode = row.chargeBoxId + "::" + row.connectorId
  322. },
  323. showWebPosQR(row) {
  324. this.webPosDialog.item = row;
  325. this.webPosDialog.visible = true;
  326. },
  327. unlockConnector(row) {
  328. this.$confirm("Confirm unlock this connector?", "Unlock Connector", {
  329. confirmButtonText: 'Confirm',
  330. cancelButtonText: 'Cancel',
  331. type: 'warning'
  332. }).then(res => {
  333. const params = {
  334. connectorId: row.connectorId,
  335. stationIds: [row.chargeBoxId]
  336. }
  337. this.sendPerform("ocppOperations/unlockConnector", params);
  338. })
  339. },
  340. changeToAvailable(row) {
  341. this.$confirm("Confirm change to available?", "Change Availability", {
  342. confirmButtonText: 'Confirm',
  343. cancelButtonText: 'Cancel',
  344. type: 'warning'
  345. }).then(res => {
  346. const params = {
  347. availType: "OPERATIVE",
  348. connectorId: row.connectorId,
  349. stationIds: [row.chargeBoxId]
  350. }
  351. this.sendPerform("ocppOperations/changeAvailability", params);
  352. })
  353. },
  354. changeToUnavailable(row) {
  355. this.$confirm("Confirm change to unavailable?", "Change Availability", {
  356. confirmButtonText: 'Confirm',
  357. cancelButtonText: 'Cancel',
  358. type: 'warning'
  359. }).then(res => {
  360. const params = {
  361. availType: "INOPERATIVE",
  362. connectorId: row.connectorId,
  363. stationIds: [row.chargeBoxId]
  364. }
  365. this.sendPerform("ocppOperations/changeAvailability", params);
  366. })
  367. },
  368. sendPerform(api, params) {
  369. this.listLoading = true;
  370. ocpp.sendPerform(api, params).then(res => {
  371. this.listLoading = false;
  372. if (res.data.taskId) {
  373. this.$openRoute("/ocpp-operations/result/" + res.data.taskId);
  374. //this.$router.push({path: '/ocpp-operations/result/' + res.data.taskId});
  375. }
  376. }).catch(err => {
  377. this.listLoading = false;
  378. this.$message({
  379. type: 'error',
  380. message: err
  381. })
  382. });
  383. },
  384. remoteStart(row) {
  385. this.actionDialog.visible = true;
  386. this.actionDialog.item = row;
  387. this.actionDialog.isStart = true;
  388. /*this.$confirm("Confirm remote start?", "Remote", {
  389. confirmButtonText: 'Confirm',
  390. cancelButtonText: 'Cancel',
  391. type: 'warning'
  392. }).then(res => {
  393. const params = {
  394. connectorId: row.connectorId,
  395. stationIds: [row.chargeBoxId],
  396. //mobileNumber: ""
  397. }
  398. //this.sendPerform("ocppOperations/remoteStartTransaction", params);
  399. })*/
  400. },
  401. remoteStop(row) {
  402. this.actionDialog.visible = true;
  403. this.actionDialog.item = row;
  404. this.actionDialog.isStart = false;
  405. /*this.$confirm("Confirm remote stop?", "Remote", {
  406. confirmButtonText: 'Confirm',
  407. cancelButtonText: 'Cancel',
  408. type: 'warning'
  409. }).then(res => {
  410. const params = {
  411. availType: "INOPERATIVE",
  412. connectorId: row.connectorId,
  413. stationIds: [row.chargeBoxId]
  414. }
  415. //this.sendPerform("ocppOperations/remoteStopTransaction", params);
  416. })*/
  417. },
  418. hideConnectorQR() {
  419. this.printConnector.visible = false;
  420. this.webPosDialog.visible = false;
  421. },
  422. hideActionDialog() {
  423. this.actionDialog.visible = false;
  424. }
  425. }
  426. }
  427. </script>
  428. <style lang="scss">
  429. .filter-item {
  430. &.el-input {
  431. width: 100%;
  432. .el-input__inner {
  433. width: 100%;
  434. min-width: 300px;
  435. max-width: 500px;
  436. border-radius: 2px;
  437. }
  438. }
  439. }
  440. .back-icon {
  441. width: 30px;
  442. height: 30px;
  443. padding: 10px;
  444. display: flex;
  445. cursor: pointer;
  446. font-size: 18px;
  447. align-items: center;
  448. }
  449. </style>