AddStation.vue 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737
  1. <template>
  2. <div class="card-container">
  3. <el-form
  4. :model="addForm"
  5. :rules="rule"
  6. v-loading="loading"
  7. ref="addForm"
  8. label-width="160px"
  9. label-position="left">
  10. <div class="flexr">
  11. <div class="card-content flex1">
  12. <div class="section-title">Charge Station Information</div>
  13. <el-row :gutter="20">
  14. <el-col :xs="24" :md="24">
  15. <el-form-item
  16. label="Charge Station ID:"
  17. prop="chargeBoxId"
  18. label-width="160px">
  19. <el-input
  20. class="add-text"
  21. v-model="addForm.chargeBoxId"
  22. placeholder=""
  23. maxlength="30"
  24. readonly
  25. v-if="isEdit"/>
  26. <el-input
  27. class="add-text"
  28. v-model="addForm.chargeBoxId"
  29. placeholder=""
  30. maxlength="30"
  31. @blur="formatStationId"
  32. v-else/>
  33. </el-form-item>
  34. </el-col>
  35. </el-row>
  36. <el-row :gutter="20" v-if="enableEVCPID">
  37. <el-col :xs="24" :md="24">
  38. <el-form-item
  39. label="EVCPID:"
  40. prop="evcpId"
  41. label-width="160px">
  42. <el-input
  43. class="add-text"
  44. v-model="addForm.evcpId"
  45. placeholder=""
  46. maxlength="20"/>
  47. </el-form-item>
  48. </el-col>
  49. </el-row>
  50. <el-row :gutter="20" v-if="false">
  51. <el-col :span="24">
  52. <el-form-item
  53. label="Insert connector status after start/stop transaction">
  54. <el-switch v-model="addForm.insertConnectorStatusAfterTransactionMsg"/>
  55. </el-form-item>
  56. </el-col>
  57. </el-row>
  58. <div class="section-title">Service Provider</div>
  59. <el-row :gutter="20">
  60. <el-col :span="24">
  61. <el-form-item
  62. label="Service Provider:"
  63. prop="providerPk"
  64. label-width="160px">
  65. <el-select
  66. class="add-text"
  67. v-model="addForm.providerPk"
  68. placeholder="Select">
  69. <el-option
  70. v-for="(item, index) in providerOptions"
  71. :key="index"
  72. :label="item.providerName"
  73. :value="item.providerPk"/>
  74. </el-select>
  75. </el-form-item>
  76. </el-col>
  77. </el-row>
  78. <div class="section-title">Location of Station</div>
  79. <el-row :gutter="20">
  80. <el-col :xs="24" :md="24">
  81. <el-form-item
  82. label="Site of Station:"
  83. prop="sitePk"
  84. label-width="160px">
  85. <el-select
  86. class="add-text"
  87. filterable
  88. remote
  89. v-model="addForm.sitePk"
  90. :remote-method="filterSite"
  91. placeholder="Select with search">
  92. <el-option
  93. v-for="(item, index) in siteOptions"
  94. :key="index"
  95. :label="item.siteName"
  96. :value="item.sitePk"/>
  97. </el-select>
  98. </el-form-item>
  99. </el-col>
  100. </el-row>
  101. <el-row :gutter="20">
  102. <el-col :xs="24" :md="24">
  103. <el-form-item
  104. label="Additional Notes:"
  105. label-width="160px">
  106. <el-input
  107. class="add-text"
  108. type="textarea"
  109. maxlength="300"
  110. :autosize="autosize"
  111. v-model="addForm.note"
  112. placeholder=""/>
  113. </el-form-item>
  114. </el-col>
  115. </el-row>
  116. <el-row :gutter="20">
  117. <el-col :xs="24" :md="24">
  118. <el-form-item
  119. label="Lot Number:"
  120. label-width="160px">
  121. <el-input
  122. class="add-text"
  123. maxlength="300"
  124. v-model="addForm.lotNumber"
  125. placeholder=""/>
  126. </el-form-item>
  127. </el-col>
  128. </el-row>
  129. <el-row :gutter="20">
  130. <el-col :xs="24" :md="24">
  131. <el-form-item
  132. label="Level:"
  133. label-width="160px">
  134. <el-input
  135. class="add-text"
  136. maxlength="300"
  137. v-model="addForm.level"
  138. placeholder=""/>
  139. </el-form-item>
  140. </el-col>
  141. <el-col :xs="24" :md="24">
  142. <el-form-item
  143. label="Registration Status:"
  144. label-width="160px"
  145. prop="registrationStatus">
  146. <el-select
  147. class="add-text"
  148. v-model="addForm.registrationStatus"
  149. placeholder="">
  150. <el-option
  151. v-for="(item, index) in registerOptions"
  152. :key="index"
  153. :label="item"
  154. :value="item"/>
  155. </el-select>
  156. </el-form-item>
  157. </el-col>
  158. </el-row>
  159. </div>
  160. <div class="card-content flex1">
  161. <div class="section-title">Charge Station Specifications</div>
  162. <el-row :gutter="20">
  163. <el-col :xs="24" :md="24">
  164. <el-form-item
  165. label="Endpoint Address:"
  166. label-width="210px"
  167. class="info-item">
  168. <span class="info-text">{{addForm.endpointAddress}}</span>
  169. </el-form-item>
  170. </el-col>
  171. <el-col :xs="24" :md="24">
  172. <el-form-item
  173. label="Charge Point Vendor:"
  174. label-width="210px"
  175. class="info-item">
  176. <span class="info-text">{{addForm.chargePointVendor}}</span>
  177. </el-form-item>
  178. </el-col>
  179. <el-col :xs="24" :md="24">
  180. <el-form-item
  181. label="Charge Point Serial Number:"
  182. label-width="210px"
  183. class="info-item">
  184. <span class="info-text">{{addForm.chargePointSerialNumber}}</span>
  185. </el-form-item>
  186. </el-col>
  187. <el-col :xs="24" :md="24">
  188. <el-form-item
  189. label="Charge Box Serial Number:"
  190. label-width="210px"
  191. class="info-item">
  192. <span class="info-text">{{addForm.chargeBoxSerialNumber}}</span>
  193. </el-form-item>
  194. </el-col>
  195. <el-col :xs="24" :md="24">
  196. <el-form-item
  197. label="Firmware Version:"
  198. label-width="210px"
  199. class="info-item">
  200. <span class="info-text">{{addForm.fwVersion}}</span>
  201. </el-form-item>
  202. </el-col>
  203. <el-col :xs="24" :md="24">
  204. <el-form-item
  205. label="Firmware Update Timestamp:"
  206. label-width="210px"
  207. class="info-item">
  208. <span class="info-text">{{addForm.fwUpdateTimestamp}}</span>
  209. </el-form-item>
  210. </el-col>
  211. <el-col :xs="24" :md="24">
  212. <el-form-item
  213. label="IMSI:"
  214. label-width="210px"
  215. class="info-item">
  216. <span class="info-text">{{addForm.imsi}}</span>
  217. </el-form-item>
  218. </el-col>
  219. <el-col :xs="24" :md="24">
  220. <el-form-item
  221. label="Last Heartbeat Timestamp:"
  222. label-width="210px"
  223. class="info-item">
  224. <span class="info-text">{{addForm.lastHeartbeatTimestamp}}</span>
  225. </el-form-item>
  226. </el-col>
  227. <el-col :xs="24" :md="24">
  228. <el-form-item
  229. label="OCPP Protocol:"
  230. label-width="210px"
  231. class="info-item">
  232. <span class="info-text">{{addForm.ocppProtocol}}</span>
  233. </el-form-item>
  234. </el-col>
  235. <el-col :xs="24" :md="24">
  236. <el-form-item
  237. label="Charge Point Model:"
  238. label-width="210px"
  239. class="info-item">
  240. <span class="info-text">{{addForm.chargePointModel}}</span>
  241. </el-form-item>
  242. </el-col>
  243. <el-col :xs="24" :md="24">
  244. <el-form-item
  245. label="ICCID:"
  246. label-width="210px"
  247. class="info-item">
  248. <span class="info-text">{{addForm.iccid}}</span>
  249. </el-form-item>
  250. </el-col>
  251. <el-col :xs="24" :md="24">
  252. <el-form-item
  253. label="Meter Type:"
  254. label-width="210px"
  255. class="info-item">
  256. <span class="info-text">{{addForm.meterType}}</span>
  257. </el-form-item>
  258. </el-col>
  259. <el-col :xs="24" :md="24">
  260. <el-form-item
  261. label="Meter Serial Number:"
  262. label-width="210px"
  263. class="info-item">
  264. <span class="info-text">{{addForm.meterSerialNumber}}</span>
  265. </el-form-item>
  266. </el-col>
  267. <el-col :xs="24" :md="24">
  268. <el-form-item
  269. label="Diagnostics Status:"
  270. label-width="210px"
  271. class="info-item">
  272. <span class="info-text">{{addForm.diagnosticsStatus}}</span>
  273. </el-form-item>
  274. </el-col>
  275. <el-col :xs="24" :md="24">
  276. <el-form-item
  277. label="Diagnostics Timestamp:"
  278. label-width="210px"
  279. class="info-item">
  280. <span class="info-text">{{addForm.diagnosticsTimestamp}}</span>
  281. </el-form-item>
  282. </el-col>
  283. </el-row>
  284. </div>
  285. </div>
  286. <div class="card-content flex1">
  287. <div class="section-title">Websocket urls</div>
  288. <div class="urls-group">
  289. <div class="urls-item" v-for="(item, index) in socketUrls" :key="index">
  290. <span class="urls-title">{{item.urlName + " URL:"}}</span>
  291. <span class="copy-url" @click="e => copyUrls(e, item.urlValue)">
  292. <i class="el-icon-document-copy"></i>
  293. {{item.urlValue}}
  294. </span>
  295. </div>
  296. </div>
  297. </div>
  298. <div class="card-content flex1" v-if="addForm.connectorInfo.length">
  299. <div class="section-title">Connector Settings</div>
  300. <div class="rate-list-view" v-for="(item, index) in addForm.connectorInfo" :key="index">
  301. <el-form-item
  302. label="Connector ID:"
  303. label-width="120px"
  304. :prop="'connectorInfo.' + index + '.connectorId'"
  305. :rules="rule.connectorInfo.connectorId">
  306. <el-input
  307. class="rate-text center"
  308. v-model.number="item.connectorId"
  309. maxlength="5"
  310. readonly
  311. placeholder=""/>
  312. </el-form-item>
  313. <el-form-item
  314. label="Charge Type:"
  315. label-width="120px"
  316. :prop="'connectorInfo.' + index + '.chargeTypePk'"
  317. :rules="rule.connectorInfo.chargeTypePk">
  318. <el-select
  319. class="rate-text"
  320. v-model="item.chargeTypePk"
  321. placeholder="">
  322. <el-option
  323. v-for="(item, index) in chargeTypeOptions"
  324. :key="index"
  325. :label="item.chargeType"
  326. :value="item.chargeTypePk"/>
  327. </el-select>
  328. </el-form-item>
  329. </div>
  330. </div>
  331. <div class="card-content flexcr">
  332. <div class="buttons">
  333. <el-button
  334. type="primary"
  335. class="cancel-button"
  336. @click="handleClickCancleButton">
  337. Cancel
  338. </el-button>
  339. <el-button
  340. style="margin-left: 20px;"
  341. type="primary"
  342. @click="handleClickConfigUpateButton">
  343. Save
  344. </el-button>
  345. </div>
  346. <div
  347. class="update-by"
  348. v-if="isEdit">
  349. <span
  350. class="add-text"
  351. :title='"CREATED BY " + addForm.createdBy + " ON " + addForm.createdOn'>
  352. LAST UPDATED BY {{addForm.updatedBy}} TIMESTAMP: {{addForm.updatedOn}}
  353. </span>
  354. </div>
  355. </div>
  356. </el-form>
  357. </div>
  358. </template>
  359. <script>
  360. //import { mapState } from 'vuex'
  361. import site from '../../http/api/site'
  362. import station from '../../http/api/charge'
  363. import provider from '../../http/api/provider'
  364. import handleClipboard from '@/utils/clipboard'
  365. import settings from '../../settings'
  366. export default {
  367. data() {
  368. return {
  369. loading: true,
  370. autosize: {
  371. minRows: 3,
  372. maxRows: 6
  373. },
  374. rule: {
  375. // "address": {
  376. // "zipCode": {
  377. // required: true,
  378. // trigger: 'blur',
  379. // message: 'Please type postal code'
  380. // },
  381. // "country": {
  382. // required: true,
  383. // trigger: 'change',
  384. // message: 'Please select country'
  385. // },
  386. // "city": {
  387. // required: true,
  388. // trigger: 'blur',
  389. // message: 'Please type city'
  390. // },
  391. // "street": {
  392. // required: true,
  393. // trigger: 'blur',
  394. // message: 'Please type street'
  395. // },
  396. // "houseNumber": {
  397. // required: true,
  398. // trigger: 'blur',
  399. // message: 'Please type unit number'
  400. // }
  401. // },
  402. "sitePk": {
  403. required: true,
  404. trigger: 'change',
  405. message: 'Please select a site'
  406. },
  407. "providerPk": {
  408. required: true,
  409. trigger: 'change',
  410. message: 'Please select a provider'
  411. },
  412. "chargeBoxId": {
  413. required: true,
  414. trigger: 'blur',
  415. message: 'Please type charge station id'
  416. },
  417. "evcpId": {
  418. required: false,
  419. trigger: 'blur',
  420. message: 'Please type EVCPID'
  421. },
  422. "registrationStatus": {
  423. required: true,
  424. trigger: 'change',
  425. message: 'Please select a status'
  426. },
  427. 'ocpp': [{
  428. required: true,
  429. trigger: 'blur',
  430. message: 'Please type ocpp',
  431. }, {
  432. pattern: /^\d{1,}(.{0,1}\d{1,})$/,
  433. trigger: 'blur',
  434. message: 'Please type a correct ocpp'
  435. }],
  436. 'timeLimit': [{
  437. required: true,
  438. trigger: 'change',
  439. }],
  440. 'connectorInfo': {
  441. 'connectorPk': [{
  442. required: true,
  443. trigger: 'blur',
  444. message: 'Please type Connector ID',
  445. }],
  446. 'chargeTypePk': [{
  447. required: true,
  448. trigger: 'blur',
  449. message: 'Please type Charge Type',
  450. }]
  451. }
  452. },
  453. addForm: {
  454. sitePk: '',
  455. providerPk: '',
  456. /*address: {
  457. country: '',
  458. city: '',
  459. street: '',
  460. zipCode: ''
  461. },*/
  462. chargeBoxId: '',
  463. registrationStatus: '',
  464. //description: '',
  465. //adminAddress: '',
  466. note: '',
  467. insertConnectorStatusAfterTransactionMsg: false,
  468. connectorInfo: [],
  469. //timeLimit: ''
  470. level: '',
  471. lotNumber: '',
  472. evcpId: ''
  473. },
  474. socketUrls: [],
  475. chargeTypeOptions: [],
  476. registerOptions: [],
  477. providerOptions: [],
  478. siteOptions: [],
  479. siteKeyword: '',
  480. defConnectorInfo: {
  481. connectorPk: '',
  482. chargeTypePk: ''
  483. },
  484. isEdit: false,
  485. enableEVCPID: settings.enableEVCPID
  486. }
  487. },
  488. created() {
  489. this.getRegisterOptions()
  490. if (this.$route.params.id) {
  491. this.isEdit = true;
  492. this.getChargeTypes();
  493. this.getStationInfo();
  494. }
  495. },
  496. methods: {
  497. async getChargeTypes() {
  498. const res = await site.getChargeTypeList()
  499. if (res.data && res.data.length > 0) {
  500. this.chargeTypeOptions = res.data
  501. //this.defConnectorInfo.chargeTypePk = res.data[0].chargeTypePk;
  502. }
  503. },
  504. async getRegisterOptions() {
  505. const res = await station.getRegistrationStatusList();
  506. if (res.data && res.data.length > 0) {
  507. this.registerOptions = res.data;
  508. if (!this.isEdit) {
  509. this.addForm.registrationStatus = res.data[0];
  510. }
  511. }
  512. this.getAllSite();
  513. },
  514. getAllSite() {
  515. site.getAllSiteList({siteName: this.siteKeyword}).then(res => {
  516. if (res.data && res.data.length > 0) {
  517. this.siteOptions = res.data
  518. }
  519. }).finally(() => {
  520. this.getAllProvider();
  521. this.getStationUrls();
  522. });
  523. },
  524. getStationInfo() {
  525. station.getStationInfo({chargeBoxPk: this.$route.params.id}).then(res => {
  526. if (res.data) {
  527. this.addForm = res.data
  528. delete this.addForm.address
  529. }
  530. }).catch(err => {
  531. this.$message({
  532. message: err,
  533. type: 'error'
  534. })
  535. });
  536. },
  537. getStationUrls() {
  538. station.getStationUrls().then(res => {
  539. if (res.data) {
  540. this.socketUrls = res.data
  541. }
  542. }).catch(err => {
  543. this.$message({
  544. message: err,
  545. type: 'error'
  546. })
  547. })
  548. },
  549. getAllProvider() {
  550. provider.getAllServiceProvider().then(res => {
  551. if (res.data && res.data.length > 0) {
  552. this.providerOptions = res.data
  553. if (!this.isEdit) {
  554. this.addForm.providerPk = res.data[0].providerPk
  555. }
  556. }
  557. }).finally(() => {
  558. this.loading = false;
  559. });
  560. },
  561. filterSite(word) {
  562. this.siteKeyword = word
  563. this.getAllSite();
  564. },
  565. addConnector() {
  566. this.addForm.connectorInfo.push(Object.assign({}, this.defConnectorInfo));
  567. },
  568. delConnector(index) {
  569. this.addForm.connectorInfo.splice(index, 1);
  570. },
  571. formatStationId() {
  572. let id = "" + this.addForm.chargeBoxId;
  573. id = id.toUpperCase().replace(/\s/g, "");
  574. this.addForm.chargeBoxId = id;
  575. },
  576. handleClickCancleButton() {
  577. this.loading = false;
  578. this.$nextTick(() => {
  579. this.$router.replace({
  580. path: "/charge-station-management/registered-charge-stations"
  581. })
  582. })
  583. },
  584. handleClickConfigUpateButton() {
  585. this.$refs['addForm'].validate(result => {
  586. if (result) {
  587. this.isEdit ? this.updateStation() : this.addStation();
  588. }
  589. })
  590. },
  591. addStation() {
  592. this.loading = true;
  593. station.addStation(this.addForm).then(res => {
  594. this.$message({
  595. message: 'Add station successfully',
  596. type: 'success'
  597. })
  598. this.handleClickCancleButton();
  599. }).catch(err => {
  600. this.loading = false;
  601. this.$message({
  602. message: err,
  603. type: 'error'
  604. })
  605. });
  606. },
  607. updateStation() {
  608. this.loading = true;
  609. station.updateStation(this.addForm).then(res => {
  610. this.$message({
  611. message: 'Edit station successfully',
  612. type: 'success'
  613. });
  614. this.handleClickCancleButton();
  615. }).catch(err => {
  616. this.loading = false;
  617. this.$message({
  618. message: err,
  619. type: 'error'
  620. })
  621. })
  622. },
  623. copyUrls(e, url) {
  624. handleClipboard(url, e)
  625. }
  626. }
  627. }
  628. </script>
  629. <style scoped="scoped" lang='scss'>
  630. @import '../../styles/variables.scss';
  631. .card-container {
  632. width: 100%;
  633. padding: 20px 60px;
  634. min-height: $mainAppMinHeight;
  635. background-color: #F0F5FC;
  636. }
  637. .card-content {
  638. margin: 0 8px 16px;
  639. padding: 15px 50px;
  640. border-radius: 6px;
  641. background-color: white;
  642. }
  643. .section-title {
  644. color: #333;
  645. margin-top: 20px;
  646. margin-bottom: 30px;
  647. font-size: 15px;
  648. user-select: none;
  649. line-height: 24px;
  650. font-weight: 700;
  651. font-family: sans-serif;
  652. text-transform: uppercase;
  653. }
  654. .add-text {
  655. width: 100%;
  656. font-size: 14px;
  657. max-width: 300px;
  658. }
  659. .add-text ::v-deep .el-textarea__inner {
  660. font-family: sans-serif;
  661. }
  662. .hr {
  663. height: 2px;
  664. margin: 10px -40px;
  665. background-color: #F0F5FC;
  666. }
  667. .hr-full {
  668. height: 2px;
  669. margin: 20px -80px;
  670. background-color: #F0F5FC;
  671. }
  672. .rate-list-view {
  673. display: flex;
  674. flex-wrap: wrap;
  675. align-items: center;
  676. }
  677. .rate-text {
  678. max-width: 150px;
  679. padding-right: 14px;
  680. }
  681. .list-item-icon {
  682. width: 30px;
  683. height: 30px;
  684. cursor: pointer;
  685. margin: 0 10px 22px;
  686. }
  687. .buttons {
  688. padding-top: 15px;
  689. padding-bottom: 15px;
  690. }
  691. @media screen and (max-width: 500px) {
  692. .card-container {
  693. padding: 0px;
  694. }
  695. .card-content {
  696. padding: 15px 30px;
  697. }
  698. }
  699. .info-item {
  700. margin-bottom: 0;
  701. }
  702. .info-text {
  703. color: #888;
  704. }
  705. .urls-item {
  706. display: flex;
  707. padding: 5px 0;
  708. font-size: 14px;
  709. align-items: center;
  710. }
  711. .urls-title {
  712. width: 85px;
  713. margin-right: 10px;
  714. text-align: right;
  715. white-space: nowrap;
  716. }
  717. .copy-url {
  718. color: #888;
  719. display: flex;
  720. cursor: pointer;
  721. font-size: 14px;
  722. align-items: center;
  723. transition: all .4s;
  724. word-break: break-all;
  725. }
  726. .copy-url i {
  727. padding: 5px;
  728. font-size: 16px;
  729. }
  730. .copy-url:hover,
  731. .copy-url:active {
  732. color: #000;
  733. }
  734. </style>