index.vue 16 KB

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