AddStation.vue 22 KB

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