detail.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592
  1. <template>
  2. <view class="u-margin-left-20 u-margin-right-20">
  3. <u-navbar :border-bottom="false" :custom-back="goHome" :is-back="true"
  4. back-text="返回" title="房源"></u-navbar>
  5. <view>
  6. <u-swiper :height="750" :interval="5000" :list="swiperlist" effect3d effect3d-previous-margin="20" mode="number"
  7. @click="clickImg"></u-swiper>
  8. </view>
  9. <view class="item u-margin-top-5">
  10. <view class="item-title">
  11. {{ room.type == '整租' ? room.houseNum + room.houseHall + room.toiletNum : room.roomType }}
  12. </view>
  13. <view class="item-price">¥{{ room.price }}/月</view>
  14. </view>
  15. <view class="item" style="display: flex;align-items: center;flex-wrap: wrap;">
  16. <view v-for="(item,index) in tagList" :key="index"
  17. style="background-color: #f5f5f5;color: #606266;margin-right: 15rpx;
  18. margin-top: 15rpx;padding: 0 10rpx;height: 60rpx;line-height: 60rpx;">
  19. {{ item.title }}
  20. </view>
  21. </view>
  22. <!-- 小程序通讯 -->
  23. <button class="clearBtn" open-type="contact" type="default">
  24. <u-cell-group>
  25. <u-cell-item title="服务费另计" value="在线咨询"></u-cell-item>
  26. </u-cell-group>
  27. </button>
  28. <view v-if="room.introduce">
  29. <u-gap bg-color="#f8f8f8" height="10"></u-gap>
  30. <u-card :border="false" :head-border-bottom="false" padding="0" title="房源介绍" title-size="38">
  31. <view slot="body" class="u-padding-top-45 item">
  32. {{ room.introduce }}
  33. </view>
  34. </u-card>
  35. </view>
  36. <u-gap bg-color="#f8f8f8" height="1"></u-gap>
  37. <view style="position: relative;">
  38. <u-card :border="false" :head-border-bottom="false" padding="0" title="小区介绍" title-size="38">
  39. <view slot="body" class="u-padding-top-45">
  40. <view class="u-flex" style="justify-content: space-between;">
  41. <view class="item">
  42. <view>建筑年份:{{ village.year }}</view>
  43. <view>建筑类型:{{ village.type }}</view>
  44. <view>绿化率:{{ village.green }}%</view>
  45. </view>
  46. <image
  47. mode="widthFix"
  48. src="https://img11.360buyimg.com/n7/jfs/t1/94448/29/2734/524808/5dd4cc16E990dfb6b/59c256f85a8c3757.jpg"
  49. style="width: 250rpx;height: 200rpx;"></image>
  50. </view>
  51. </view>
  52. </u-card>
  53. </view>
  54. <u-gap bg-color="#f8f8f8" height="1"></u-gap>
  55. <view style="position: relative;">
  56. <u-card :border="false" :head-border-bottom="false" :title="room.villageName" padding="0" title-size="38">
  57. <view slot="body" class="u-padding-top-45">
  58. <map :latitude="latitude" :longitude="longitude">
  59. <cover-view style='width:100%;height:100%;' @click="clickMap"></cover-view>
  60. </map>
  61. <view
  62. style="margin-top: 30rpx;padding-left: 10rpx;height:80rpx;
  63. line-height: 80rpx;background-color: #fdfdfd;border-radius: 6px;
  64. display: flex;justify-content: space-between;
  65. padding-right: 10rpx;color: #909399;
  66. "
  67. @click="clickMap">
  68. <view>
  69. <u-icon color="#909399" name="map" size="30"></u-icon>
  70. <text style="margin-left: 8rpx;">
  71. 房源直线距离约 {{ distance }} km
  72. </text>
  73. </view>
  74. <view>
  75. <text style="margin-right: 3rpx;">
  76. 导航
  77. </text>
  78. <u-icon color="#909399" name="arrow-right" size="30"></u-icon>
  79. </view>
  80. </view>
  81. <view style="margin-top: 20rpx;margin-left: 10rpx;font-size: 10px;
  82. color: #909399">
  83. *数据仅供参考,请以实际看房为准
  84. </view>
  85. </view>
  86. </u-card>
  87. </view>
  88. <u-gap bg-color="#f8f8f8" height="1"></u-gap>
  89. <view style="position: relative;">
  90. <u-card :border="false" :head-border-bottom="false" padding="0" title="服务介绍" title-size="38">
  91. <view slot="body" class="u-padding-top-35">
  92. <u-cell-group :border="false">
  93. <u-cell-item :arrow="false" :border-bottom="false" hover-class="none" icon="heart"
  94. title="承诺-四大租住承诺,安心有保障"></u-cell-item>
  95. <u-cell-item :arrow="false" :border-bottom="false" hover-class="none" icon="level"
  96. title="品质-两类品质保障,入住更无忧"></u-cell-item>
  97. <u-cell-item :arrow="false" :border-bottom="false" hover-class="none" icon="star"
  98. title="服务-两项日常服务,生活超便捷"></u-cell-item>
  99. <u-cell-item :arrow="false" :border-bottom="false" hover-class="none" icon="rmb"
  100. title="付款-多种付款方式,支付更灵活"></u-cell-item>
  101. </u-cell-group>
  102. </view>
  103. </u-card>
  104. </view>
  105. <u-gap bg-color="#f8f8f8" height="1"></u-gap>
  106. <view style="position: relative;">
  107. <u-card :border="false" :head-border-bottom="false" padding="0" title="房源评价" title-size="38">
  108. <view slot="body" class="u-padding-top-50 u-padding-bottom-50">
  109. <u-cell-group :border="false">
  110. {{ evaluate }}
  111. <text style="float: right;color: #909399;font-size: 13px;">{{ credt }}</text>
  112. </u-cell-group>
  113. </view>
  114. <view slot="foot" style="padding-top: 30rpx;float: right;">
  115. <u-icon name="chat-fill"></u-icon>
  116. <text style="text-align: center;font-size: 12px;margin-left: 5rpx;" @click="moreEval">
  117. 更多评价({{ evalsize }})
  118. </text>
  119. </view>
  120. </u-card>
  121. </view>
  122. <u-gap bg-color="#f8f8f8" height="10"></u-gap>
  123. <view style="position: relative;padding-bottom: 50rpx;">
  124. <u-card :border="false" :head-border-bottom="false" padding="0" title="经纪人" title-size="38">
  125. <view slot="body" class="u-padding-top-45">
  126. <view class="u-flex">
  127. <view class="u-m-r-20">
  128. <u-avatar :src="room.agentAvatar" size="80"></u-avatar>
  129. </view>
  130. <view class="u-flex-1">
  131. <view class="u-font-16 u-p-b-40">{{ room.agentName }}</view>
  132. <!-- <view class="u-font-12 u-p-b-10">{{user.agentPhone}}</view> -->
  133. </view>
  134. </view>
  135. <view class="arrow-right" @click="clickItem">
  136. <view class="phone">
  137. <u-icon class="u-p-l-10" color="#d1d1d1" name="phone"
  138. size="40"
  139. ></u-icon>
  140. </view>
  141. </view>
  142. </view>
  143. </u-card>
  144. <view class="item">
  145. <u-divider>开源字节为您服务</u-divider>
  146. </view>
  147. </view>
  148. <view class="navigation">
  149. <view class="left">
  150. <button class="clearBtn" open-type="contact" style="font-size: 14px;color: #6a6a6a;"
  151. type="default">
  152. <view class="item">
  153. <u-icon :size="40" name="server-fill"></u-icon>
  154. <view class="text">客服</view>
  155. </view>
  156. </button>
  157. <view class="item" @click="heartHouse">
  158. <u-icon v-if="!room.heart" :size="40" name="heart"></u-icon>
  159. <u-icon v-if="room.heart" :size="40" color="#ff9900" name="heart-fill"></u-icon>
  160. <view class="text">收藏</view>
  161. </view>
  162. <button class="clearBtn" open-type="share" style="font-size: 14px;color: #6a6a6a;"
  163. type="default">
  164. <view class="item">
  165. <u-icon :size="40" name="zhuanfa"></u-icon>
  166. <view class="text">分享</view>
  167. </view>
  168. </button>
  169. </view>
  170. <view class="right" @click="clickItem">
  171. <view class="btn">联系经纪人</view>
  172. </view>
  173. </view>
  174. </view>
  175. </template>
  176. <script>
  177. import config from "@/common/config.js" // 全局配置文件
  178. export default {
  179. data() {
  180. return {
  181. room: {
  182. villageName: '',
  183. houseNum: '',
  184. houseHall: '',
  185. toiletNum: '',
  186. roomType: '',
  187. direction: '',
  188. price: '',
  189. introduce: '',
  190. heart: false,
  191. },
  192. village: {
  193. year: '',
  194. type: '',
  195. green: '',
  196. },
  197. swiperlist: [],
  198. tagList: [],
  199. //评价列表
  200. evaluList: [],
  201. user: {},
  202. longitude: 120.14,
  203. latitude: 30.35,
  204. distance: 0,
  205. //自己的评论
  206. ownevalu: '',
  207. houseId: null,
  208. evalsize: 0,
  209. havem: false,
  210. evaluate: '',
  211. credt: ''
  212. }
  213. },
  214. onLoad: function (option) {
  215. let houseId = option.houseId //上个页面传递的参数。
  216. this.houseId = houseId
  217. // 渲染当前房源信息
  218. this.findHouseById(houseId);
  219. // // 在页面中定义激励视频广告
  220. // let videoAd = null
  221. // // 在页面onLoad回调事件中创建激励视频广告实例
  222. // if (wx.createRewardedVideoAd) {
  223. // videoAd = wx.createRewardedVideoAd({
  224. // adUnitId: 'adunit-8cd5789a01a51891'
  225. // })
  226. // videoAd.onLoad(() => {
  227. // console.log('激励视频 成功加载广告')
  228. // })
  229. // videoAd.onError((err) => {})
  230. // videoAd.onClose((res) => {
  231. // console.log('激励视频 成功关闭广告')
  232. // })
  233. // }
  234. // // 用户触发广告后,显示激励视频广告
  235. // if (videoAd) {
  236. // videoAd.show().catch(() => {
  237. // // 失败重试
  238. // videoAd.load()
  239. // .then(() => videoAd.show())
  240. // .catch(err => {
  241. // console.log('激励视频 广告显示失败')
  242. // })
  243. // })
  244. // }
  245. },
  246. methods: {
  247. heartHouse() {
  248. // 判断是否有userId
  249. let lifeData = uni.getStorageSync('lifeData');
  250. let vuex_user = lifeData.vuex_user
  251. if (!vuex_user) {
  252. // 没有userId 则跳转到登录
  253. return uni.reLaunch({
  254. url: '../login/login'
  255. })
  256. }
  257. // 收藏
  258. let url = "api/houseApi/saveHeart";
  259. this.$u.post(url, {
  260. heart: this.room.heart,
  261. houseId: this.room.id,
  262. userId: vuex_user.user.userId,
  263. }).then(result => {
  264. this.room.heart = !this.room.heart
  265. this.$mytip.toast(result.msg)
  266. });
  267. },
  268. goHome() {
  269. uni.reLaunch({
  270. url: '../index/index'
  271. })
  272. },
  273. clickItem() {
  274. //拨打固定电话
  275. uni.makePhoneCall({
  276. phoneNumber: this.room.agentPhone,
  277. });
  278. },
  279. findHouseById(houseId) {
  280. let url = "api/houseApi/findHouseById";
  281. this.$u.get(url, {
  282. id: houseId
  283. }).then(result => {
  284. let room = result.data
  285. if (room.type == 0) {
  286. room.type = '整租'
  287. } else if (room.type == 1) {
  288. room.type = '合租'
  289. }
  290. if (room.roomType == 1) {
  291. room.roomType = '主卧'
  292. } else if (room.roomType == 2) {
  293. room.roomType = '次卧'
  294. } else {
  295. room.roomType = '未知'
  296. }
  297. if (this.$u.test.isEmpty(room.houseNum)) {
  298. room.houseNum = ''
  299. }
  300. if (this.$u.test.isEmpty(room.houseHall)) {
  301. room.houseHall = ''
  302. }
  303. if (this.$u.test.isEmpty(room.toiletNum)) {
  304. room.toiletNum = ''
  305. }
  306. if (this.$u.test.isEmpty(room.floor)) {
  307. room.floor = ''
  308. } else {
  309. room.floor = room.floor + '层'
  310. }
  311. this.swiperlist = room.imageList.map(val => {
  312. let imgUrl = val.imgUrl
  313. if (!imgUrl.includes(config.staticUrl)) {
  314. imgUrl = config.staticUrl + val.imgUrl
  315. } else {
  316. imgUrl = val.imgUrl
  317. }
  318. return {
  319. title: val.imageName,
  320. image: imgUrl
  321. }
  322. })
  323. this.tagList = room.featureList.map(val => {
  324. return {
  325. title: val.feature,
  326. }
  327. })
  328. if (!room.agentAvatar.includes(config.staticUrl)) {
  329. room.agentAvatar = config.staticUrl + room.agentAvatar
  330. }
  331. this.user = room.user
  332. this.village = room.village
  333. this.room = room
  334. // 判断是否收藏
  335. this.selectHouseHeart(houseId);
  336. //查询房源评价
  337. this.selectHouseEvals(houseId);
  338. // 分享自定义标题与图片
  339. let shareTitle = ''
  340. if (room.type == '整租') {
  341. shareTitle = this.village.name + " " + this.room.houseNum + this.room.houseHall + this.room.toiletNum + " " + this.room.decoration + " ¥" + this.room.price + "/月"
  342. } else {
  343. shareTitle = this.village.name + " " + room.roomType + " " + this.room.decoration + " ¥" + this.room.price + "/月"
  344. }
  345. this.$u.mpShare = {
  346. title: shareTitle, // 默认为小程序名称,可自定义
  347. // 支持PNG及JPG,默认为当前页面的截图
  348. imageUrl: this.room.faceUrl,
  349. }
  350. // 添加到浏览历史
  351. let houseHistory = uni.getStorageSync('houseHistory')
  352. if (!houseHistory) {
  353. houseHistory = []
  354. }
  355. // 如果超过20个了,则删除最后一个
  356. if (houseHistory.length >= 20) {
  357. houseHistory.pop()
  358. }
  359. houseHistory.push(this.room)
  360. // 数据去重
  361. const keyArr = [];
  362. houseHistory.forEach((element, index) => {
  363. keyArr.push(element.code); // 通过code来判断
  364. });
  365. const newArr = [];
  366. const newKey = new Set(keyArr); // key去重
  367. newKey.forEach(item => {
  368. const index = keyArr.findIndex(item2 => item2 === item);
  369. newArr.push(houseHistory[index]);
  370. })
  371. uni.setStorageSync('houseHistory', newArr)
  372. // 经纬度
  373. this.longitude = room.longitude
  374. this.latitude = room.latitude
  375. // 计算距离
  376. let lat1 = 39.909
  377. let lng1 = 116.39742
  378. let lat2 = this.latitude
  379. let lng2 = this.longitude
  380. uni.getLocation({
  381. type: 'gcj02',
  382. success: res => {
  383. lat1 = res.latitude
  384. lng1 = res.longitude
  385. this.distance = this.getDistance(lat1, lng1, lat2, lng2);
  386. }
  387. })
  388. });
  389. },
  390. selectHouseHeart(houseId) {
  391. // 判断是否有userId
  392. let lifeData = uni.getStorageSync('lifeData');
  393. let vuex_user = lifeData.vuex_user
  394. if (vuex_user) {
  395. let url = "api/houseApi/selectHouseHeart";
  396. this.$u.get(url, {
  397. houseId: houseId,
  398. userId: vuex_user.user.userId,
  399. }).then(result => {
  400. this.room.heart = result.data
  401. });
  402. }
  403. },
  404. selectHouseEvals(houseId) {
  405. let url = "api/houseApi/selectHouseEvals";
  406. this.$u.get(url, {
  407. houseId: houseId,
  408. pageNum: 1,
  409. pageSize: 1
  410. }).then(result => {
  411. if (result.total > 0) {
  412. this.evaluate = result.rows[0].evaluate;
  413. if (this.evaluate.length > 30) {
  414. this.evaluate = this.evaluate.substring(0, 30) + "......";
  415. }
  416. this.credt = result.rows[0].createTime;
  417. this.havem = true;
  418. this.evalsize = result.total;
  419. }
  420. });
  421. },
  422. moreEval() {
  423. this.$u.route({
  424. url: '/pages/detail/evalList',
  425. params: {
  426. houseId: this.houseId
  427. }
  428. })
  429. },
  430. clickImg(index) {
  431. let imgArr = this.swiperlist.map(val => {
  432. return val.image
  433. })
  434. console.log(imgArr);
  435. // 预览图片
  436. uni.previewImage({
  437. current: index,
  438. urls: imgArr
  439. });
  440. },
  441. clickMap(e) {
  442. uni.openLocation({
  443. longitude: Number(this.longitude),
  444. latitude: Number(this.latitude),
  445. name: this.room.villageName,
  446. address: this.room.address
  447. })
  448. },
  449. getDistance(lat1, lng1, lat2, lng2) {
  450. lat1 = lat1 || 0;
  451. lng1 = lng1 || 0;
  452. lat2 = lat2 || 0;
  453. lng2 = lng2 || 0;
  454. var rad1 = lat1 * Math.PI / 180.0;
  455. var rad2 = lat2 * Math.PI / 180.0;
  456. var a = rad1 - rad2;
  457. var b = lng1 * Math.PI / 180.0 - lng2 * Math.PI / 180.0;
  458. var r = 6378137;
  459. var distance = r * 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(rad1) * Math.cos(rad2) * Math.pow(Math.sin(b / 2), 2)));
  460. return (distance / 1000).toFixed(2);
  461. }
  462. }
  463. }
  464. </script>
  465. <style>
  466. /* page不能写带scope的style标签中,否则无效 */
  467. page {
  468. background-color: rgb(255, 255, 255);
  469. }
  470. </style>
  471. <style lang="scss" scoped>
  472. map {
  473. width: 100%;
  474. height: 350 rpx;
  475. }
  476. .item {
  477. padding: 25 rpx;
  478. line-height: 80 rpx;
  479. margin-top: -30rpx;
  480. }
  481. .item-title {
  482. font-size: 42 rpx;
  483. color: $u-main-color;
  484. font-weight: bold;
  485. }
  486. .item-price {
  487. font-weight: normal;
  488. font-size: 45 rpx;
  489. color: $u-type-warning;
  490. }
  491. .item-desc {
  492. font-weight: normal;
  493. font-size: 36 rpx;
  494. color: $u-tips-color;
  495. }
  496. .arrow-right {
  497. position: absolute;
  498. top: 80 rpx;
  499. right: 28 rpx;
  500. font-weight: normal;
  501. font-size: 28 rpx;
  502. color: $u-tips-color;
  503. .phone {
  504. width: 90 rpx;
  505. height: 90 rpx;
  506. border-radius: 100%;
  507. box-shadow: 0px 1px 20px 0px rgba(0, 0, 0, 0.1);
  508. display: flex;
  509. justify-content: center;
  510. align-items: center;
  511. }
  512. }
  513. .wayClass {
  514. color: #606266;
  515. padding: 30 rpx;
  516. line-height: 50 rpx;
  517. }
  518. .clearBtn {
  519. margin: 0;
  520. padding: 0;
  521. line-height: 1;
  522. background-color: #FFFFFF;
  523. }
  524. .clearBtn::after {
  525. position: unset !important;
  526. border: unset;
  527. }
  528. .navigation {
  529. display: flex;
  530. justify-content: center;
  531. align-items: center;
  532. position: fixed;
  533. left: 0;
  534. right: 0;
  535. bottom: 0;
  536. padding: 0 rpx 15 rpx;
  537. background-color: #ffffff;
  538. box-shadow: 0 -1px 1px 0 rgba(0, 0, 0, 0.05);
  539. z-index: 9999;
  540. .left {
  541. display: flex;
  542. justify-content: center;
  543. align-items: center;
  544. margin-top: 38 rpx;
  545. font-size: 14px;
  546. color: #6a6a6a;
  547. .item {
  548. display: flex;
  549. .text {
  550. margin-left: 4 rpx;
  551. }
  552. }
  553. }
  554. .right {
  555. display: flex;
  556. font-size: 28 rpx;
  557. align-items: center;
  558. .btn {
  559. line-height: 66 rpx;
  560. margin-left: 30 rpx;
  561. padding: 5 rpx 50 rpx;
  562. color: #ffffff;
  563. border-radius: 36 rpx;
  564. background-color: #2979ff;
  565. }
  566. }
  567. }
  568. </style>