continuedForm.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501
  1. <template>
  2. <a-spin :spinning="confirmLoading">
  3. <a-tabs default-active-key="1" @change="callback">
  4. <!-- <a-tab-pane key="2" tab="续住记录"></a-tab-pane> -->
  5. <a-tab-pane key="1" tab="操作">
  6. <a-row>
  7. <a-form-model style="margin-bottom: 10px ;">
  8. <a-col :span="24">
  9. <a-form-model-item style="margin-bottom: 10px" :labelCol="labelCol" :wrapperCol="wrapperCol" >
  10. <a-radio-group v-model="model.batchWay" @change="batchWayChange">
  11. <a-radio :value="1">按天数</a-radio>
  12. <a-input-number v-model="model.batchDay" style="margin-right: 30px" @change="batchChangeDay"></a-input-number>
  13. <a-radio :value="2">按预离时间</a-radio>
  14. <a-date-picker
  15. v-model="model.batchTime"
  16. :disabled-date="disabledDate"
  17. show-time
  18. format="YYYY-MM-DD HH:mm:ss"
  19. @change="batchChangeTime" />
  20. </a-radio-group>
  21. </a-form-model-item>
  22. </a-col>
  23. <!-- <a-col :span="12">-->
  24. <!-- <a-button @click="batchChangeDay" type="primary" style="float: right; margin-right: 20px">批量续住</a-button>-->
  25. <!-- </a-col>-->
  26. </a-form-model>
  27. <a-col :span="24">
  28. <a-table
  29. ref="table"
  30. size="middle"
  31. height="450px"
  32. overflow-y="scroll"
  33. bordered
  34. rowKey="id"
  35. :columns="columns"
  36. :dataSource="tableData"
  37. :rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}">
  38. <template slot="newDueOutTime" slot-scope="text, record, index">
  39. <a-date-picker
  40. v-model="record.newDueOutTime"
  41. :disabled-date="disabledDate"
  42. show-time
  43. format="YYYY-MM-DD HH:mm:ss"
  44. @change="timeChange(record)"/>
  45. </template>
  46. <!-- 续住天数-->
  47. <template slot="dayNum" slot-scope="text, record, index">
  48. <a-input-number v-model="record.dayNum" placeholder="请输入续住天数" style="width: 90%" @change="dayChange(record)" />
  49. </template>
  50. <!-- 支付方式-->
  51. <template slot="payType" slot-scope="text, record, index">
  52. <a-select style="width: 100px" v-model="record.payType" :disabled="record.dayNum < 0">
  53. <a-select-option v-for="(item, key) in record.payTypeList" :key="key" :value="item.id" :disabled="item.disable">{{ item.name }}</a-select-option>
  54. </a-select>
  55. </template>
  56. <!-- 支付金额-->
  57. <template slot="payMoney" slot-scope="text, record, index">
  58. <a-input-number :min="0" v-model="record.payMoney" style="width: 80%" :disabled="record.dayNum <= 0"/>
  59. </template>
  60. <template slot="breakfastNum" slot-scope="text, record, index">
  61. <a-input-number :min="0" v-model="record.breakfastNum" style="width: 80%"/>
  62. </template>
  63. <!-- 总费用-->
  64. <template slot="allMoney" slot-scope="text, record, index">
  65. <a>{{record.layoutDayPriceList.reduce((pre,cur)=> pre+cur.price*1,0 ) || 0}}</a>
  66. <a-popover placement="right" v-if="record.dayNum>0">
  67. <template slot="content">
  68. <div style="max-height:400px;overflow:auto;width:100%;">
  69. <div v-for="(item, index) in record.layoutDayPriceList" :key="index">
  70. {{item.dayTime}}
  71. <a-input-number :min="0" v-model="item.price"></a-input-number>
  72. </div>
  73. </div>
  74. </template>
  75. <template slot="title">
  76. <a-input-number :min="0" @change="batchPrice($event,record)" placeholder="批量改价"></a-input-number>
  77. </template>
  78. <a-icon type="edit" />
  79. </a-popover>
  80. </template>
  81. </a-table>
  82. </a-col>
  83. <a-col :span="24" style="text-align: end">
  84. <a-checkbox style="margin-top: 20px; margin-right: 10px" default-checked>打印续住单</a-checkbox>
  85. </a-col>
  86. </a-row>
  87. </a-tab-pane>
  88. </a-tabs>
  89. </a-spin>
  90. </template>
  91. <script>
  92. import {
  93. httpAction,
  94. getAction, postAction
  95. } from '@/api/manage'
  96. import {
  97. formatDate,
  98. validateDuplicateValue
  99. } from '@/utils/util'
  100. import moment from 'moment/moment'
  101. const columns = [
  102. {
  103. title: '房间号',
  104. dataIndex: 'roomName',
  105. width: 80,
  106. align: 'center',
  107. // scopedSlots: { customRender: 'roomId' }
  108. },
  109. {
  110. title: '姓名',
  111. dataIndex: 'customerName',
  112. width: 80,
  113. align: 'center',
  114. // scopedSlots: { customRender: 'roomId' }
  115. },
  116. {
  117. title: '原预离时间',
  118. dataIndex: 'dueOutTime',
  119. width: 120,
  120. align: 'center',
  121. },
  122. {
  123. title: '续住天数',
  124. // dataIndex: 'dayNum',
  125. width: 80,
  126. align: 'center',
  127. scopedSlots: { customRender: 'dayNum' }
  128. },
  129. {
  130. title: '收款方式',
  131. // dataIndex: 'dayNum',
  132. width: 80,
  133. align: 'center',
  134. scopedSlots: { customRender: 'payType' }
  135. },
  136. {
  137. title: '支付金额',
  138. // dataIndex: 'dayNum',
  139. width: 90,
  140. align: 'center',
  141. scopedSlots: { customRender: 'payMoney' }
  142. },
  143. {
  144. title: '早餐券',
  145. width: 80,
  146. align: 'center',
  147. scopedSlots: { customRender: 'breakfastNum' }
  148. },
  149. {
  150. title: '新预离时间',
  151. width: 80,
  152. align: 'center',
  153. scopedSlots: { customRender: 'newDueOutTime' }
  154. },
  155. {
  156. title: '合计房价',
  157. width: 80,
  158. align: 'center',
  159. scopedSlots: { customRender: 'allMoney' }
  160. },
  161. ]
  162. const date = new Date()
  163. const endDate = new Date(date.setDate(date.getDate() + 1))
  164. export default {
  165. name: "ContinuedForm",
  166. components: {},
  167. props: {
  168. //表单禁用
  169. disabled: {
  170. type: Boolean,
  171. default: false,
  172. required: false,
  173. },
  174. },
  175. data() {
  176. return {
  177. model: {
  178. day: 0,
  179. batchDay: 1,
  180. batchTime: moment(endDate).format('yyyy-MM-DD') + ' 13:00',
  181. batchWay: 1
  182. },
  183. labelCol: {
  184. xs: {
  185. span: 24
  186. },
  187. sm: {
  188. span: 5
  189. },
  190. },
  191. wrapperCol: {
  192. xs: {
  193. span: 24
  194. },
  195. sm: {
  196. span: 16
  197. },
  198. },
  199. confirmLoading: false,
  200. payTypeList: [],
  201. tableTypeList: [],
  202. regionList: [],
  203. PriceData: [],
  204. isAddDate: true,
  205. payList: [],
  206. columns: columns,
  207. tableData: [],
  208. selectedRowKeys: [],
  209. selectionRows: [],
  210. };
  211. },
  212. computed: {
  213. // dayDataArr() {
  214. // let arr = [];
  215. // console.log(this.dayNum);
  216. // if (this.dayNum && this.dayNum > 0) {
  217. // arr.length = this.dayNum;
  218. // for (let i = 0; i < arr.length; i++) {
  219. // arr[i] = {
  220. // day: this.addDate(this.model.livingData.livingOrder.dueOutTime, i),
  221. // price: this.model.layout.marketPrice,
  222. // };
  223. // }
  224. // this.PriceData = arr;
  225. // } else {
  226. // return [];
  227. // }
  228. //
  229. // return arr;
  230. // }
  231. },
  232. created() {
  233. var _info = JSON.parse(localStorage.getItem("storeInfo"));
  234. if (_info) {
  235. this.model.hotelId = _info.id;
  236. }
  237. //备份model原始值
  238. this.modelDefault = JSON.parse(JSON.stringify(this.model));
  239. getAction('/business/busRoomPayType/list', {
  240. pageSize: 99999,
  241. pageNo: 1,
  242. }).then((res) => {
  243. if (res.success) {
  244. this.payTypeList = res.result.records;
  245. this.loadDate()
  246. }
  247. });
  248. },
  249. methods: {
  250. loadDate() {
  251. getAction('/business/busRoomBookingOrders/get-continue-order', { bookingOrderId: this.model.bookingOrderId }).then(resp => {
  252. if (resp.success) {
  253. var vipIndex = this.payTypeList.findIndex((t) => t.name.includes('会员'))
  254. var danweiIndex = this.payTypeList.findIndex((t) => t.name.includes('单位'))
  255. this.tableData = resp.result
  256. this.tableData.forEach(e => {
  257. e.newDueOutTime = e.dueOutTime
  258. e.dayNum = 0
  259. e.layoutDayPriceList = []
  260. e.payMoney = 0
  261. let payTypeList = JSON.parse(JSON.stringify(this.payTypeList))
  262. this.$set(payTypeList[vipIndex], 'disable', e.vipCustomerId == null || e.vipCustomerId === '')
  263. this.$set(payTypeList[danweiIndex], 'disable', e.contractTeamId == null || e.contractTeamId === '')
  264. this.$set(e, 'payTypeList', payTypeList)
  265. if (e.id === this.model.livingOrderId) {
  266. this.selectedRowKeys.push(e.id)
  267. this.selectionRows.push(e)
  268. e.dayNum = 1
  269. this.dayChange(e)
  270. }
  271. })
  272. }
  273. })
  274. },
  275. disabledDate(current) {
  276. return current && current < moment().add(-1, 'days').endOf('day')
  277. },
  278. onSelectChange(selectedRowKeys, selectionRows) {
  279. console.log(selectedRowKeys, selectionRows)
  280. this.selectedRowKeys = selectedRowKeys
  281. this.selectionRows = selectionRows
  282. },
  283. changePriceData(record){
  284. let arr = [];
  285. console.log(record.dayNum);
  286. if (record.dayNum && record.dayNum > 0) {
  287. arr.length = record.dayNum;
  288. for (let i = 0; i < arr.length; i++) {
  289. arr[i] = {
  290. dayTime: this.addDate(record.dueOutTime, i),
  291. price: record.roomLayout.marketPrice,
  292. roomLayoutId: record.roomLayout.id,
  293. roomId: record.roomId,
  294. livingOrderId: record.id
  295. };
  296. }
  297. record.layoutDayPriceList = arr;
  298. } else {
  299. record.layoutDayPriceList = [];
  300. }
  301. },
  302. // 批量修改的方式改变
  303. batchWayChange() {
  304. this.batchChangeDay()
  305. this.batchChangeTime()
  306. },
  307. // 批量修改勾选的预离天数
  308. batchChangeDay() {
  309. if (this.model.batchWay === 1) {
  310. this.selectionRows.forEach(e => {
  311. e.dayNum = this.model.batchDay
  312. this.dayChange(e)
  313. })
  314. this.$forceUpdate()
  315. }
  316. },
  317. // 批量修改勾选的预离时间
  318. batchChangeTime() {
  319. if (this.model.batchWay === 2) {
  320. this.selectionRows.forEach(e => {
  321. e.newDueOutTime = this.model.batchTime
  322. this.timeChange(e)
  323. })
  324. this.$forceUpdate()
  325. }
  326. },
  327. // 预离日期改变
  328. timeChange(record) {
  329. let nowDate = new Date()
  330. if (record.newDueOutTime.batchTime < nowDate) {
  331. this.$message.warning('退租时间不能小于当前时间')
  332. return
  333. }
  334. record.dayNum = this.daysBetween(record.dueOutTime, record.newDueOutTime)
  335. this.changePriceData(record)
  336. // this.model.startValue = e._i;
  337. this.$forceUpdate()
  338. },
  339. // 预离天数改变
  340. dayChange(record) {
  341. // if (!this.isAddDate) {
  342. // record.dayNum = -record.dayNum
  343. // }
  344. let newTime = this.addDate(record.dueOutTime, record.dayNum)
  345. if (record.dayNum < 0 && moment(newTime) < moment(endDate.format('yyyy-MM-dd'))) {
  346. record.dayNum = 1
  347. this.dayChange(record)
  348. this.$message.warning('预离时间不能晚于当前时间')
  349. return
  350. }
  351. record.newDueOutTime = newTime
  352. console.log(record)
  353. this.changePriceData(record)
  354. this.$forceUpdate()
  355. },
  356. /**
  357. * 根据传入的数字将日期加上对应的天数
  358. * @param {String} date 日期
  359. * @param {Number} days 天数
  360. * @return {String} 返回日期
  361. */
  362. addDate(date, days) {
  363. console.log(date, days);
  364. let time = new Date(date);
  365. time.setDate(time.getDate() + days);
  366. let m = time.getMonth() + 1;
  367. let d = time.getDate();
  368. if (m < 10) {
  369. m = "0" + m;
  370. }
  371. if (d < 10) {
  372. d = "0" + d;
  373. }
  374. return time.getFullYear() + '-' + m + '-' + d + ' ' + time.getHours() + ':' + (time.getMinutes() < 10 ? "0" + time.getMinutes() : time.getMinutes()) + ':' + (time.getSeconds() < 10 ? "0" + time.getSeconds() : time.getSeconds())
  375. },
  376. //计算两个日期之间相隔多少天
  377. daysBetween(date1, date2) {
  378. const oneDay = 24 * 60 * 60 * 1000; // hours*minutes*seconds*milliseconds
  379. const firstDate = new Date(date1);
  380. const secondDate = new Date(date2);
  381. const diffDays = (secondDate - firstDate) / oneDay;
  382. this.isAddDate = diffDays >= 0;
  383. if (Math.round(diffDays) <= 0) {
  384. this.PriceData = []
  385. }
  386. return Math.round(diffDays);
  387. },
  388. batchPrice(value, record) {
  389. console.log(value)
  390. console.log(record.layoutDayPriceList,'record.layoutDayPriceList')
  391. record.layoutDayPriceList.forEach(item => {
  392. item.price = value
  393. })
  394. this.$forceUpdate()
  395. },
  396. add() {
  397. this.edit(this.modelDefault);
  398. },
  399. edit(record) {
  400. this.model = Object.assign(this.model, {
  401. livingOrderId: record.livingData.livingOrder.id,
  402. bookingOrderId: record.livingData.livingOrder.bookingOrderId,
  403. })
  404. // this.model.startValue = record.livingData.livingOrder.dueOutTime
  405. this.visible = true
  406. this.loadDate()
  407. },
  408. chooseVipPay() {
  409. },
  410. submitForm() {
  411. const that = this
  412. let params = []
  413. if (this.selectionRows.length === 0) {
  414. that.$emit("ok");
  415. return
  416. }
  417. if (this.selectionRows.some(e => e.payMoney > 0 && e.payType == null)) {
  418. this.$message.warning('请选择支付方式')
  419. return
  420. }
  421. this.selectionRows.forEach(e => {
  422. if (e.dayNum === 0) {
  423. return
  424. }
  425. let obj = {
  426. id: e.id,
  427. payType: e.payType,
  428. roomId: e.roomId,
  429. payMoney: e.payMoney,
  430. breakfastNum: e.breakfastNum,
  431. dayNum: e.dayNum == null ? 0 : e.dayNum,
  432. layoutDayPriceList: e.layoutDayPriceList,
  433. dueOutTime: moment(e.newDueOutTime).format('yyyy-MM-DD HH:mm')
  434. }
  435. params.push(obj)
  436. })
  437. httpAction(`/business/busRoomBookingOrders/isBooked`, params, 'post')
  438. .then(res => {
  439. if (!res.success) {
  440. return
  441. }
  442. if (res.result.length > 0) {
  443. let mess = '房间已被预定:'
  444. res.result.forEach(e => {
  445. mess += '\n' + e.customerName + ',电话:' + e.phone + ' 预抵时间:' + e.arrivalTime + '。'
  446. })
  447. mess += '是否续住?'
  448. this.$confirm({
  449. title: '提示',
  450. content: mess,
  451. onOk: function () {
  452. that.confirmLoading = true;
  453. httpAction(`/business/busRoomBookingOrders/continue-living`, params, 'post')
  454. .then((res) => {
  455. if (res.success) {
  456. that.$message.success(res.message)
  457. that.$emit('ok')
  458. } else {
  459. that.$message.warning(res.message);
  460. }
  461. })
  462. .finally(() => {
  463. that.confirmLoading = false;
  464. });
  465. },
  466. })
  467. } else {
  468. that.confirmLoading = true;
  469. httpAction(`/business/busRoomBookingOrders/continue-living`, params, 'post')
  470. .then((res) => {
  471. if (res.success) {
  472. that.$message.success(res.message);
  473. that.$emit("ok");
  474. } else {
  475. that.$message.warning(res.message);
  476. }
  477. })
  478. .finally(() => {
  479. that.confirmLoading = false;
  480. });
  481. }
  482. })
  483. },
  484. callback(key) {
  485. console.log(key)
  486. },
  487. },
  488. };
  489. </script>