detail.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528
  1. <template>
  2. <div class="container">
  3. <el-form
  4. ref="form"
  5. :model="form"
  6. :rules="rules"
  7. label-width="150px"
  8. label-position="top">
  9. <div class="content">
  10. <div class="section-title">Rate Config</div>
  11. <div class="flexcr">
  12. <el-form-item
  13. label="Name:"
  14. prop="rateName"
  15. class="add-input">
  16. <el-input
  17. v-model="form.rateName"/>
  18. </el-form-item>
  19. <el-form-item
  20. label="Country:"
  21. prop="countryCode"
  22. class="add-input">
  23. <el-select
  24. v-model="form.countryCode">
  25. <el-option
  26. v-for="item in options.country"
  27. :key="item.name"
  28. :label="item.name"
  29. :value="item.value" />
  30. </el-select>
  31. </el-form-item>
  32. <!-- <el-form-item
  33. label="Rate Type:"
  34. prop="rateType"
  35. class="add-input">
  36. <el-input
  37. v-model="form.rateType"/>
  38. </el-form-item> -->
  39. </div>
  40. <div class="flexcr" v-if="false">
  41. <label class="el-form-item__label">Repeat:</label>
  42. <div class="repeat-view">
  43. (&nbsp;
  44. <div
  45. class="link-type"
  46. v-for="(item, index) in options.shortcut"
  47. :key="index"
  48. @click="handleShortcut(item)">
  49. <span>{{item.name}}</span>
  50. </div>
  51. &nbsp;)
  52. <el-tooltip
  53. effect="dark"
  54. content="This is an items for quickly selecting the repeats"
  55. placement="right">
  56. <i class="el-icon-question icon-help"></i>
  57. </el-tooltip>
  58. </div>
  59. </div>
  60. <div style="margin-bottom: 10px;" v-if="false">
  61. <el-checkbox-group
  62. v-model="form.repeats">
  63. <el-checkbox-button
  64. v-for="(item, index) in options.repeat"
  65. :label="item.value"
  66. :key="index">
  67. {{item.name}}
  68. </el-checkbox-button>
  69. </el-checkbox-group>
  70. </div>
  71. <div class="flexcr" v-if="false">
  72. <el-form-item
  73. label="All Day:"
  74. class="add-input">
  75. <el-switch
  76. v-model="form.allDay"
  77. @change="changeAllday"
  78. disabled/>
  79. </el-form-item>
  80. <template v-if="form.allDay">
  81. <el-form-item
  82. label="Start Time:"
  83. class="add-input">
  84. <el-input disabled/>
  85. </el-form-item>
  86. <el-form-item
  87. label="End Time:"
  88. class="add-input">
  89. <el-input disabled/>
  90. </el-form-item>
  91. </template>
  92. <template v-else>
  93. <el-form-item
  94. label="Start Time:"
  95. class="add-input"
  96. prop="startTime">
  97. <el-time-picker
  98. v-model="form.startTime"
  99. format="HH:mm"
  100. value-format="HH:mm"
  101. clearable/>
  102. </el-form-item>
  103. <el-form-item
  104. label="End Time:"
  105. class="add-input"
  106. prop="endTime">
  107. <el-time-picker
  108. v-model="form.endTime"
  109. format="HH:mm"
  110. value-format="HH:mm"
  111. clearable/>
  112. </el-form-item>
  113. </template>
  114. </div>
  115. </div>
  116. <div class="content">
  117. <div class="section-title flexcr">
  118. CHARGE SITE RATE
  119. <div class="section-sub-title">(Currency Used: {{currencyData[form.countryCode]}})</div>
  120. </div>
  121. <charge-rate
  122. v-model="ratesForm.chargeRates"/>
  123. </div>
  124. <div class="content" v-if="false">
  125. <div class="section-title flexcr">
  126. SPECIAL CHARGE RATE
  127. <div class="section-sub-title">(Currency Used: {{currencyData[form.countryCode]}})</div>
  128. </div>
  129. <charge-rate
  130. isSpecial
  131. v-model="ratesForm.specialChargeRates"/>
  132. </div>
  133. <div class="content flexcr">
  134. <div class="buttons">
  135. <el-button
  136. @click="onBack"
  137. type="primary"
  138. class="cancel-button">
  139. Cancel
  140. </el-button>
  141. <el-button
  142. @click="onClickSave"
  143. type="primary"
  144. :loading="loadingSave">
  145. &nbsp;Save&nbsp;
  146. </el-button>
  147. </div>
  148. <div class="update-by" v-if="isEdit">
  149. <span
  150. class="add-text"
  151. :title='"CREATED BY " + form.createdBy + " ON " + form.createdOn'>
  152. LAST UPDATED BY {{form.updatedBy}} TIMESTAMP: {{form.updatedOn}}
  153. </span>
  154. </div>
  155. </div>
  156. </el-form>
  157. </div>
  158. </template>
  159. <script>
  160. import site from '../../http/api/site'
  161. import api from '../../http/api/rates'
  162. import settings from '../../settings.js'
  163. import ChargeRate from '../site/components/ChargeRate'
  164. export default {
  165. data() {
  166. return {
  167. loading: false,
  168. loadingSave: false,
  169. isEdit: false,
  170. form: {
  171. dynamicRateId: "",
  172. rateName: "",
  173. countryCode: settings.defaultCountry,
  174. repeats: [],
  175. allDay: true,
  176. startTime: "",
  177. endTime: "",
  178. rates: [],
  179. specialRates: []
  180. },
  181. options: {
  182. country: [],
  183. repeat: [],
  184. shortcut: [{
  185. name: "Daily",
  186. value: [],
  187. all: true
  188. },{
  189. name: "Weekday",
  190. value: ["Mon","Tue","Wed","Thu","Fri"]
  191. },{
  192. name: "Weekend",
  193. value: ["Sat","Sun"]
  194. }, {
  195. name: "None",
  196. value: []
  197. }]
  198. },
  199. currencyData: {
  200. SG: "S$"
  201. },
  202. ratesForm: {
  203. chargeRates: [{
  204. rate: '',
  205. rateType: '',
  206. chargeTypePk: '',
  207. dynamicRateItemId: ''
  208. }],
  209. specialChargeRates: [{
  210. rate: '',
  211. rateType: '',
  212. chargeTypePk: '',
  213. groupPk: ''
  214. }]
  215. },
  216. rules: {
  217. rateName: {
  218. required: true,
  219. trigger: "blur",
  220. message: "Please input rate name"
  221. },
  222. startTime: {
  223. required: true,
  224. trigger: "change",
  225. message: "Please select start time"
  226. },
  227. endTime: {
  228. required: true,
  229. trigger: "change",
  230. message: "Please select end time"
  231. }
  232. },
  233. }
  234. },
  235. components: {ChargeRate},
  236. created() {
  237. this.loading = true;
  238. this.getCountryOptions();
  239. this.getRepeatOptions();
  240. if (this.$route.params.id) {
  241. this.isEdit = true;
  242. this.getRateDetail();
  243. }
  244. },
  245. methods: {
  246. onBack() {
  247. this.$nextTick(() => {
  248. this.$router.replace({
  249. path: "/site-management/rate-configuration"
  250. })
  251. })
  252. },
  253. getCountryOptions() {
  254. site.getCountryList().then(res => {
  255. if (res.data) {
  256. this.options.country = res.data
  257. const sign = {}
  258. res.data.forEach(item => {
  259. sign[item.value] = item.currencySymbol
  260. })
  261. this.currencyData = sign;
  262. }
  263. }).catch(err => {
  264. this.$message({
  265. type: 'error',
  266. message: err
  267. })
  268. this.loading = false;
  269. })
  270. },
  271. getRepeatOptions() {
  272. api.getRepeatOptions().then(res => {
  273. if (res.data) {
  274. this.options.repeat = res.data;
  275. this.handleShortcut(this.options.shortcut[0]);
  276. }
  277. }).catch(err => {
  278. this.$message({
  279. type: 'error',
  280. message: err
  281. })
  282. }).finally(() => {
  283. this.loading = false;
  284. })
  285. },
  286. getRateDetail() {
  287. this.loading = true;
  288. api.getDynamicRateInfo({
  289. dynamicRateId: this.$route.params.id
  290. }).then(res => {
  291. if (res.data) {
  292. this.form = res.data;
  293. if (res.data.rates && res.data.rates.length) {
  294. this.ratesForm.chargeRates = res.data.rates;
  295. }
  296. }
  297. }).catch(err => {
  298. this.$message({
  299. type: 'error',
  300. message: err
  301. })
  302. }).finally(() => {
  303. this.loading = false;
  304. })
  305. },
  306. handleShortcut(shortcut) {
  307. const select = []
  308. if (shortcut.all) {
  309. this.options.repeat.forEach(item => {
  310. select.push(item.value)
  311. })
  312. } else {
  313. select.push(...shortcut.value)
  314. }
  315. this.form.repeats = select;
  316. },
  317. changeAllday(all) {
  318. if (all) {
  319. this.form.startTime = "";
  320. this.form.endTime = "";
  321. this.$refs.form.clearValidate()
  322. }
  323. },
  324. onClickSave() {
  325. this.$refs.form.validate(result => {
  326. if (result) {
  327. if (this.form.repeats.length == 0) {
  328. this.$message({
  329. message: "Please select at least one repeat day",
  330. type: 'error',
  331. duration: 3000,
  332. })
  333. return;
  334. }
  335. const rates = [];
  336. this.ratesForm.chargeRates.forEach(item => {
  337. if (item.rate) {
  338. rates.push(item);
  339. }
  340. })
  341. this.ratesForm.specialChargeRates.forEach(item => {
  342. if (item.rate) {
  343. rates.push(item);
  344. }
  345. })
  346. if (rates.length == 0) {
  347. this.$message({
  348. message: "Please add at least one site rate",
  349. type: 'error',
  350. duration: 3000,
  351. })
  352. return;
  353. }
  354. this.form.rates = rates;
  355. this.loadingSave = true;
  356. this.isEdit ? this.updateRateData() : this.addRateData();
  357. }
  358. });
  359. },
  360. addRateData() {
  361. api.addDynamicRate(this.form).then(res => {
  362. this.$message({
  363. type: 'success',
  364. message: "Successfully added"
  365. });
  366. this.onBack();
  367. }).catch(err => {
  368. this.$message({
  369. type: 'error',
  370. message: err
  371. });
  372. }).finally(() => {
  373. this.loadingSave = false;
  374. });
  375. },
  376. updateRateData() {
  377. api.updateDynamicRate(this.form).then(res => {
  378. this.$message({
  379. type: 'success',
  380. message: "Successfully updated"
  381. });
  382. this.onBack();
  383. }).catch(err => {
  384. this.$message({
  385. type: 'error',
  386. message: err
  387. });
  388. }).finally(() => {
  389. this.loadingSave = false;
  390. });
  391. }
  392. }
  393. }
  394. </script>
  395. <style lang="scss" scoped>
  396. @import '../../styles/variables.scss';
  397. .container {
  398. width: 100%;
  399. padding: 20px 60px;
  400. min-height: $mainAppMinHeight;
  401. background-color: #F0F5FC;
  402. }
  403. .content {
  404. margin: 0 8px 16px;
  405. padding: 15px 80px;
  406. border-radius: 6px;
  407. background-color: white;
  408. }
  409. .section-title {
  410. color: #333;
  411. margin-top: 20px;
  412. margin-bottom: 30px;
  413. font-size: 15px;
  414. user-select: none;
  415. line-height: 24px;
  416. font-weight: bold;
  417. font-family: sans-serif;
  418. text-transform: uppercase;
  419. }
  420. .section-sub-title {
  421. font-size: 14px;
  422. padding-left: 5px;
  423. font-weight: normal;
  424. }
  425. .add-text {
  426. width: 100%;
  427. min-width: 100px;
  428. max-width: 300px;
  429. }
  430. .add-text ::v-deep .el-textarea__inner {
  431. font-family: sans-serif;
  432. }
  433. .add-input {
  434. width: 100%;
  435. min-width: 100px;
  436. max-width: 250px;
  437. margin-right: 10px;
  438. ::v-deep .el-input,
  439. ::v-deep .el-select {
  440. width: 100%;
  441. }
  442. }
  443. .icon-help {
  444. color: #999;
  445. font-size: 15px;
  446. cursor: pointer;
  447. }
  448. .form-photo {
  449. flex: 1;
  450. ::v-deep .el-form-item__label {
  451. padding: 12px;
  452. line-height: 16px;
  453. }
  454. .photo-uploader {
  455. margin-right: 10px;
  456. .uploader-image {
  457. width: 180px;
  458. height: 120px;
  459. text-align: left;
  460. }
  461. ::v-deep img {
  462. object-fit: cover;
  463. }
  464. .avatar-uploader-icon {
  465. border: 1px dashed #d9d9d9;
  466. border-radius: 6px;
  467. cursor: pointer;
  468. font-size: 28px;
  469. color: #8c939d;
  470. width: 120px;
  471. height: 120px;
  472. line-height: 120px;
  473. text-align: center;
  474. }
  475. }
  476. }
  477. .repeat-view {
  478. display: flex;
  479. font-size: 14px;
  480. font-weight: bold;
  481. align-items: center;
  482. padding: 0 10px 10px;
  483. .link-type + .link-type {
  484. margin-left: 5px;
  485. &::before {
  486. color: #333;
  487. content: "|";
  488. font-size: 15px;
  489. font-weight: normal;
  490. padding-right: 5px;
  491. }
  492. }
  493. }
  494. .hr {
  495. height: 2px;
  496. margin: 10px -40px;
  497. background-color: #F0F5FC;
  498. }
  499. .buttons {
  500. padding-top: 15px;
  501. padding-bottom: 15px;
  502. }
  503. @media screen and (max-width: 1200px) {
  504. .add-input {
  505. min-width: 80px;
  506. max-width: 200px;
  507. }
  508. }
  509. @media screen and (max-width: 500px) {
  510. .container {
  511. padding: 0px;
  512. }
  513. .content {
  514. padding: 15px 30px;
  515. }
  516. .add-input {
  517. max-width: unset;
  518. }
  519. }
  520. </style>