index.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706
  1. <template>
  2. <view class="page" :style="{'padding-top':mt+'px'}">
  3. <c-nav-bar title="房态" :showIcon="false" :titleStyle="titleStyle"></c-nav-bar>
  4. <view class="leftFixed" v-if="leftData.length!=0" :style="{'top':(mt+1)+'px'}">
  5. <view class="tj" :style="{'top':mt+'px'}"></view>
  6. <view class="year">
  7. <u-icon name="calendar-fill" color="#B9C2D2" size="40" style="margin-bottom:10rpx;"></u-icon>
  8. <text style="font-size: 24rpx;">2024</text>
  9. </view>
  10. <view v-for="(item,key,i) in leftData" :key="i" class="fixedItem">
  11. <view class="head" v-if="indexArr[i]==key.split('-')[0]">
  12. <text>{{key.split('-')[0]}}F</text>
  13. <view class="rightIcon" @click="open(i,key.split('-')[0],false)" v-if="opens[i]">
  14. <text>收起</text>
  15. <u-icon name="arrow-up-fill" size="18" style="margin-left: 10rpx;"></u-icon>
  16. </view>
  17. <view class="rightIcon" @click="open(i,key.split('-')[0],true)" v-else>
  18. <text>展开</text>
  19. <u-icon name="arrow-down-fill" size="18" style="margin-left: 10rpx;"></u-icon>
  20. </view>
  21. </view>
  22. <template v-if="opens[i]">
  23. <view class="roomType" :style="{'left':scrollLeft+'px'}">{{key.split('-')[1]}}</view>
  24. <text v-for="(item2,index2) in item" class="roomNumber">
  25. {{item2.roomNumber}}
  26. </text>
  27. </template>
  28. </view>
  29. </view>
  30. <view>
  31. <view class="content" v-if="xdata.length!=0">
  32. <view class="tj" :style="{'top':mt+'px'}">
  33. <text class="label">房间总数:</text>
  34. <text>{{info.totalRooms}}</text>
  35. <text class="label">在入住房间数:</text>
  36. <text>{{info.checkinRooms}}</text>
  37. <text class="label">待入住房间数:</text>
  38. <text>{{info.bookRooms}}</text>
  39. </view>
  40. <view class="date">
  41. <view class="item">
  42. <u-icon name="calendar-fill" color="#B9C2D2" size="40" style="margin-bottom:10rpx;"></u-icon>
  43. <text style="font-size: 24rpx;">2024</text>
  44. </view>
  45. <view class="item" v-for="(item,keynme,index) in xdata" :key="index">
  46. <text>{{item.rentDate.substring(5)}}</text>
  47. <text>{{weeks[item.rentWeek]}}</text>
  48. <text>剩{{item.spareRooms}}</text>
  49. </view>
  50. </view>
  51. <view class="floorData" v-if="leftData.length!=0">
  52. <view v-for="(item,key,i) in leftData" :key="i" style="margin-bottom: 16rpx;">
  53. <view class="head" v-if="indexArr[i]==key.split('-')[0]" style="opacity: 0;">
  54. <text>{{key.split('-')[0]}}F</text>
  55. <view class="rightIcon" @click="open(i,key.split('-')[0],false)" v-if="opens[i]">
  56. <text>收起</text>
  57. <u-icon name="arrow-up-fill" size="18" style="margin-left: 10rpx;"></u-icon>
  58. </view>
  59. <view class="rightIcon" @click="open(i,key.split('-')[0],true)" v-else>
  60. <text>展开</text>
  61. <u-icon name="arrow-down-fill" size="18" style="margin-left: 10rpx;"></u-icon>
  62. </view>
  63. </view>
  64. <template v-if="opens[i]">
  65. <view class="roomType" style="opacity: 0;">{{key.split('-')[1]}}</view>
  66. <view class="table">
  67. <view class="tr" v-for="(item2,index2) in item" :key="index2">
  68. <view class="td" :style="{'left':scrollLeft+'px'}">{{item2.roomNumber}}</view>
  69. <view class="td" v-for="(roomData,ind) in xdata" :key="ind"
  70. :class="'s'+delDataStatus(item2.roomNumber,item2.houseBaseId,roomData.roomDataList,'status')">
  71. <!-- 空置房-->
  72. <template
  73. v-if="delDataStatus(item2.roomNumber,item2.houseBaseId,roomData.roomDataList,'status') == 1">
  74. <view
  75. @click="check(item2.roomNumber,item2.houseBaseId,roomData,i + '-'+index2+ '-'+ ind)"
  76. class="cellBox">
  77. {{item2.roomNumber|delDataStatus(item2.houseBaseId,roomData.roomDataList,'price')}}
  78. </view>
  79. </template>
  80. <template v-else>
  81. <view
  82. @click="tabCli(item2.roomNumber,item2.houseBaseId,roomData.roomDataList)"
  83. class="tdP">
  84. <text>{{item2.roomNumber|delDataStatus(item2.houseBaseId,roomData.roomDataList,'guestName')}}</text>
  85. <text>{{item2.roomNumber|delDataStatus(item2.houseBaseId,roomData.roomDataList,'status')}}</text>
  86. </view>
  87. </template>
  88. <!-- 点击时状态 -->
  89. <view class="cover" v-if="checkPosition.indexOf(i + '-'+index2+ '-'+ ind) > -1"
  90. @click="check(item2.roomNumber,item2.houseBaseId,roomData,i + '-'+index2+ '-'+ ind)">
  91. <u-icon name="checkbox-mark" size="36" color="#fff"></u-icon>
  92. </view>
  93. </view>
  94. </view>
  95. </view>
  96. </template>
  97. </view>
  98. </view>
  99. </view>
  100. <view class="opration" v-if="checkDataRoomId.length!=0">
  101. <text @click="areaShow=true">关房</text>
  102. <text @click="createOrder()">新增</text>
  103. </view>
  104. </view>
  105. <Tabbar :tabbarIndex="1"></Tabbar>
  106. <!-- 关房 -->
  107. <u-picker :itemHeight="88" :immediateChange="true" :show="areaShow" :columns="areaTxt" title="房态选择"
  108. :defaultIndex="passengerDefault" @cancel="areaShow=false;clearData();"
  109. @confirm="passengerConfirm"></u-picker>
  110. </view>
  111. </template>
  112. <script>
  113. var that;
  114. export default {
  115. data() {
  116. return {
  117. homestayId: this.$store.state.moduleHouse.homestayId,
  118. areaShow: false,
  119. passengerDefault: [0],
  120. info:{},
  121. areaTxt: [
  122. ['清洁中', '暂停使用', '保留房', '空置房']
  123. ],
  124. area: [{
  125. label: '清洁中',
  126. id: 4
  127. }, {
  128. label: '暂停使用',
  129. id: 5
  130. }, {
  131. label: '保留房',
  132. id: 6
  133. }, {
  134. label: '空置房',
  135. id: 0
  136. }],
  137. titleStyle: {
  138. fontSize: '34rpx',
  139. fontWeight: "bold",
  140. },
  141. dateArr: [1, 2, 3, 4, 5],
  142. xdata: [], //纵向列
  143. leftData: [], //横向列,
  144. indexArr: [], //楼层索引,
  145. opens: [],
  146. statusTxt: {
  147. '-1': '待确定',
  148. '1': '已预订',
  149. '2': '已入住',
  150. '3': '已退房',
  151. '4': '清洁中',
  152. '5': '暂停使用',
  153. '6': '保留房',
  154. },
  155. weeks: ["周日", "周一", "周二", "周三", "周四", "周五", "周六"],
  156. checkPosition: [],
  157. checkDataDate: [],
  158. checkPrice: [],
  159. checkDataRoomId: [],
  160. checkStatus: '',
  161. scrollLeft: 0
  162. }
  163. },
  164. onLoad() {
  165. that = this;
  166. this.getLeftData();
  167. this.getData();
  168. this.getTj();
  169. },
  170. filters: {
  171. delDataStatus(roomNumber, id, roomId, name) {
  172. for (let i = 0; i < roomId.length; i++) {
  173. if (id == roomId[i].houseBaseId && roomNumber == roomId[i].roomNumber) {
  174. if (name == "status") {
  175. return that.statusTxt[roomId[i][name]]
  176. } else {
  177. return roomId[i][name] || ''
  178. }
  179. }
  180. }
  181. },
  182. },
  183. methods: {
  184. init() {
  185. this.getLeftData();
  186. this.getData();
  187. this.$forceUpdate();
  188. },
  189. getTj() {
  190. this.$api.get('/merchant/hotel/room/state/getRoomStateCount', {
  191. homestayId: this.homestayId
  192. }).then(res => {
  193. if (res.data.code == 0) {
  194. this.info = res.data.data;
  195. }
  196. })
  197. },
  198. scroll(e) {
  199. //this.scrollLeft = e.detail.scrollLeft; // div 到左边的距离
  200. //console.log(e)
  201. },
  202. //关房
  203. tabCli(roomNumber, id, roomId) {
  204. this.clearData();
  205. if (roomNumber) {
  206. let obj = {};
  207. for (let i = 0; i < roomId.length; i++) {
  208. if (id == roomId[i].houseBaseId && roomNumber == roomId[i].roomNumber) {
  209. obj = roomId[i];
  210. }
  211. }
  212. //已预订,已入住
  213. if (obj.status == 1 || obj.status == 2 || obj.status == -1) {
  214. let orderId = obj.orderId;
  215. uni.navigateTo({
  216. url: "/pages/house/orderInfo?orderId=" + orderId
  217. })
  218. //到详情
  219. } else {
  220. //更改状态
  221. this.areaShow = true;
  222. this.checkDataRoomId = [obj.id];
  223. this.checkStatus = obj.status;
  224. }
  225. }
  226. },
  227. //确定关房
  228. passengerConfirm(e) {
  229. let status = this.area[e.indexs[0]].id;
  230. this.$api.post('/merchant/hotel/room/state/updRoomState', {
  231. roomIds: this.checkDataRoomId,
  232. status: status
  233. }).then(res => {
  234. if (res.data.code == 0) {
  235. console.log(res.data)
  236. this.clearData();
  237. this.areaShow = false;
  238. this.init()
  239. }
  240. })
  241. },
  242. //新增订单
  243. createOrder() {
  244. this.clearData()
  245. uni.navigateTo({
  246. url: '/pages/house/createOrder?roomId=' + this.checkDataRoomId
  247. })
  248. },
  249. //展开收起
  250. open(i, F, val) {
  251. this.opens[i] = !this.opens[i];
  252. let list = this.leftData;
  253. for (var i = 0; i < Object.keys(list).length; i++) {
  254. var index = i; // 索引
  255. var key = Object.keys(list)[i].split('-')[0]; // key
  256. if (F == key) {
  257. this.opens[index] = val;
  258. }
  259. }
  260. this.$forceUpdate();
  261. },
  262. delDataStatus(roomNumber, id, roomId, name) {
  263. for (let i = 0; i < roomId.length; i++) {
  264. if (id == roomId[i].houseBaseId && roomNumber == roomId[i].roomNumber) {
  265. return roomId[i][name] + 1;
  266. }
  267. }
  268. },
  269. clearData() {
  270. setTimeout(() => {
  271. this.checkDataDate = [];
  272. this.checkPrice = [];
  273. this.checkDataRoomId = [];
  274. this.checkPosition = [];
  275. }, 1500);
  276. },
  277. //选择房间
  278. check(roomNumber, id, item, position) {
  279. for (let i = 0; i < item.roomDataList.length; i++) {
  280. if (
  281. id == item.roomDataList[i].houseBaseId &&
  282. roomNumber == item.roomDataList[i].roomNumber
  283. ) {
  284. //宫格位置标识
  285. if (item.roomDataList[i].status == 0) {
  286. if (this.checkPosition.indexOf(position) < 0) {
  287. this.checkPosition.push(position);
  288. } else {
  289. let index = this.checkPosition.findIndex(
  290. (pos) => pos == position
  291. ); //选中的索引位置
  292. this.checkPosition.splice(index, 1);
  293. }
  294. //房间id
  295. if (this.checkDataRoomId.indexOf(item.roomDataList[i].id) < 0) {
  296. this.checkDataRoomId.push(item.roomDataList[i].id);
  297. } else {
  298. let index = this.checkDataRoomId.findIndex(
  299. (roomId) => roomId == item.roomDataList[i].id
  300. );
  301. this.checkDataRoomId.splice(index, 1);
  302. }
  303. //日期
  304. if (this.checkPosition.indexOf(position) > -1) {
  305. this.checkDataDate.push(item.rentDate);
  306. this.checkPrice.push(item.roomDataList[i].price)
  307. } else {
  308. let index = this.checkDataDate.findIndex(
  309. (date) => date == item.rentDate
  310. );
  311. this.checkDataDate.splice(index, 1);
  312. //价格
  313. let index2 = this.checkPrice.findIndex(
  314. (price) => price == item.price
  315. );
  316. this.checkPrice.splice(index2, 1);
  317. }
  318. if (this.checkPosition.length == 0) {
  319. this.checkDataDate = [];
  320. this.checkPrice = [];
  321. }
  322. console.log(this.checkDataDate);
  323. console.log(this.checkDataRoomId)
  324. }
  325. }
  326. }
  327. },
  328. getLeftData() {
  329. this.$api.get(`/merchant/hotel/room/state/getHouseCategoryData/${this.homestayId}`).then(res => {
  330. console.log(res)
  331. if (res.data.code == 0) {
  332. // for (let i; i < res.data.data.length; i++) {
  333. // res.data.data[i].open = true;
  334. // }
  335. for (let i in res.data.data) {
  336. let F = i.split('-')[0];
  337. if (this.indexArr.indexOf(F) < 0) {
  338. this.indexArr.push(F);
  339. this.opens.push(true)
  340. } else {
  341. this.indexArr.push('');
  342. this.opens.push(true)
  343. }
  344. }
  345. this.leftData = res.data.data;
  346. console.log(this.leftData)
  347. console.log(this.indexArr)
  348. }
  349. })
  350. },
  351. getData() {
  352. this.$api.get('/merchant/hotel/room/state/getDateRoomList', {
  353. homestayId: this.homestayId,
  354. nowDate: '',
  355. status: ''
  356. }).then(res => {
  357. if (res.data.code == 0) {
  358. this.xdata = res.data.data;
  359. }
  360. })
  361. }
  362. }
  363. }
  364. </script>
  365. <style scoped lang="less">
  366. .opration {
  367. height: 140rpx;
  368. padding: 0 30rpx;
  369. background-color: #fff;
  370. position: fixed;
  371. bottom: 0;
  372. left: 0;
  373. width: 100%;
  374. z-index: 9;
  375. display: flex;
  376. align-items: center;
  377. justify-content: space-between;
  378. box-sizing: border-box;
  379. text {
  380. display: inline-block;
  381. width: 160rpx;
  382. text-align: center;
  383. line-height: 56rpx;
  384. border: 1rpx solid #D1D1D1;
  385. height: 56rpx;
  386. border-radius: 64rpx;
  387. font-size: 24rpx;
  388. color: #999;
  389. &:last-child {
  390. background-color: #1372FF;
  391. color: #fff;
  392. border: 0;
  393. }
  394. }
  395. }
  396. .page {
  397. background: #F3F4F4;
  398. padding-bottom: 40rpx;
  399. box-sizing: border-box;
  400. overflow-x: auto;
  401. .content {
  402. }
  403. }
  404. .tj {
  405. padding: 30rpx 0;
  406. text-align: center;
  407. height: 98rpx;
  408. box-sizing: border-box;
  409. position: absolute;
  410. width: 750rpx;
  411. left: 0;
  412. text {
  413. font-size: 28rpx;
  414. color: #f44;
  415. font-weight: bold;
  416. margin: 0 10rpx;
  417. &.label {
  418. color: #333;
  419. margin: 0
  420. }
  421. }
  422. }
  423. .date {
  424. display: flex;
  425. position: relative;
  426. border: 1rpx solid #E9F0F5;
  427. margin-bottom: 30rpx;
  428. margin-top:98rpx;
  429. .item {
  430. min-width: 130rpx;
  431. width: 130rpx;
  432. height: 136rpx;
  433. display: flex;
  434. flex-direction: column;
  435. align-items: center;
  436. justify-content: center;
  437. font-size: 20rpx;
  438. border-right: 1rpx solid #E9F0F5;
  439. background-color: #fff;
  440. &:last-child {
  441. border: 0;
  442. }
  443. text {
  444. &:nth-child(2) {
  445. margin: 6rpx 0;
  446. }
  447. }
  448. }
  449. }
  450. .head,
  451. .roomType {
  452. padding: 0 30rpx;
  453. display: flex;
  454. width: 400rpx;
  455. // justify-content: space-between;
  456. }
  457. .head {
  458. // position: absolute;
  459. // top: 0;
  460. // left: 0;
  461. &>text {
  462. &:first-child {
  463. font-size: 32rpx;
  464. margin-right: 30rpx;
  465. }
  466. }
  467. .rightIcon {
  468. display: flex;
  469. align-items: center;
  470. font-size: 24rpx;
  471. color: #1F2425;
  472. }
  473. }
  474. .roomType {
  475. // position: absolute;
  476. // top: 40rpx;
  477. // left: 0;
  478. color: #333;
  479. font-size: 24rpx;
  480. position: relative;
  481. padding-left: 44rpx;
  482. margin: 20rpx 0 16rpx;
  483. &::after {
  484. position: absolute;
  485. content: "";
  486. height: 24rpx;
  487. width: 5rpx;
  488. background-color: #1372FF;
  489. left: 30rpx;
  490. top: 4rpx;
  491. z-index: 1;
  492. }
  493. }
  494. .floorData {
  495. .table {
  496. border: 1rpx solid #E9F0F5;
  497. width: auto;
  498. min-width: 100%;
  499. .tr {
  500. border-bottom: 1rpx solid #E9F0F5;
  501. display: flex;
  502. align-items: center;
  503. background-color: #fff;
  504. position: relative;
  505. &:last-child {
  506. border: 0;
  507. }
  508. .td {
  509. // &:first-child {
  510. // position: absolute;
  511. // left: 0;
  512. // top: 0;
  513. // z-index: 1;
  514. // }
  515. display: flex;
  516. align-items: center;
  517. justify-content: center;
  518. position: relative;
  519. width: 130rpx;
  520. min-width: 130rpx;
  521. height: 83rpx;
  522. border-right: 1rpx solid #E9F0F5;
  523. background-color: #fff;
  524. color: #1F2425;
  525. font-size: 20rpx;
  526. .tdP,
  527. .cellBox {
  528. display: flex;
  529. width: 100%;
  530. height: 100%;
  531. flex-direction: column;
  532. align-items: center;
  533. justify-content: center;
  534. }
  535. &:last-child {
  536. border: 0;
  537. }
  538. //已预订
  539. &.s2 {
  540. background-color: rgba(29, 202, 104, 0.1);
  541. color: rgb(29, 202, 104);
  542. text {
  543. &:first-child {
  544. margin-bottom: 6rpx;
  545. color: #1F2425;
  546. }
  547. }
  548. }
  549. // 已入住
  550. &.s3 {
  551. color: rgb(19, 114, 255);
  552. background-color: rgba(19, 114, 255, 0.1);
  553. text {
  554. &:first-child {
  555. margin-bottom: 6rpx;
  556. color: #1F2425;
  557. }
  558. }
  559. }
  560. // 已退房
  561. &.s4 {
  562. color: rgb(219, 41, 195);
  563. background-color: rgba(219, 41, 195, 0.1);
  564. }
  565. //待确定
  566. &.s0 {
  567. color: rgb(25, 185, 197);
  568. background-color: rgba(25, 185, 197, 0.1);
  569. }
  570. //清洁中
  571. &.s5 {
  572. color: rgb(237, 86, 86);
  573. background-color: rgba(237, 86, 86, 0.1);
  574. }
  575. //暂停使用
  576. &.s6 {
  577. color: rgb(41, 60, 115);
  578. background-color: rgba(41, 60, 115, 0.1);
  579. }
  580. //保留房
  581. &.s7 {
  582. color: rgb(132, 68, 244);
  583. background-color: rgba(132, 68, 244, 0.1);
  584. }
  585. }
  586. }
  587. .cover {
  588. position: absolute;
  589. top: 0;
  590. left: 0;
  591. bottom: 0;
  592. right: 0;
  593. background-color: #1372FF;
  594. color: #fff;
  595. text-align: center;
  596. display: flex;
  597. flex-direction: column;
  598. justify-content: center;
  599. align-items: center;
  600. }
  601. }
  602. }
  603. .small {
  604. padding-top: 68rpx !important;
  605. .roomType {
  606. top: 0 !important;
  607. }
  608. }
  609. .pd0 {
  610. padding: 0 !important;
  611. }
  612. .leftFixed {
  613. width: 72rpx;
  614. position: absolute;
  615. left: 0;
  616. // top: 232rpx;
  617. z-index: 12;
  618. .tj{
  619. width: 0;
  620. position: relative;
  621. }
  622. .year {
  623. min-width: 130rpx;
  624. width: 130rpx;
  625. height: 136rpx;
  626. display: flex;
  627. flex-direction: column;
  628. align-items: center;
  629. justify-content: center;
  630. font-size: 20rpx;
  631. border-right: 1rpx solid #E9F0F5;
  632. background-color: #fff;
  633. margin-bottom: 35rpx;
  634. }
  635. .fixedItem {
  636. display: flex;
  637. flex-direction: column;
  638. margin-bottom: 16rpx;
  639. .roomNumber {
  640. height: 83rpx;
  641. line-height:83rpx;
  642. display: inline-block;
  643. border-bottom: 1rpx solid #E9F0F5;
  644. width: 130rpx;
  645. text-align: center;
  646. background-color: #fff;
  647. box-shadow: 3px 0 5px #eae5e5;
  648. }
  649. }
  650. }
  651. </style>