You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

523 lines
11 KiB

8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
8 months ago
  1. <template>
  2. <view class="home">
  3. <!-- <view class="home-top"> -->
  4. <!-- <view class="search">
  5. <view @click="showSelectArea" class="left-area">
  6. <image src="@/static/home/address-icon.png"></image>
  7. <view class="area">{{ area }}</view>
  8. <image src="../../static/home/arrow-icon.png" mode="aspectFit"></image>
  9. <view class="parting-line">|</view>
  10. </view>
  11. <view class="center-area">
  12. <image src="@/static/home/search-icon.png"></image>
  13. <van-field @click="searchAddress" v-model="queryParams.title" center placeholder="请选择地区" />
  14. </view>
  15. <view class="right-area">
  16. <view @click="searchAddress" class="search-button">
  17. 搜索
  18. </view>
  19. </view>
  20. </view> -->
  21. <!-- </view> -->
  22. <view class="banner b-relative">
  23. <van-swipe class="my-swipe" :autoplay="3000" indicator-color="white">
  24. <van-swipe-item v-for="item in bannerList" :key="item.id">
  25. <image class="banner-image" :src="item.image" mode="widthFix"></image>
  26. </van-swipe-item>
  27. </van-swipe>
  28. </view>
  29. <view class="home-content">
  30. <!-- <view class="banner b-relative">
  31. <van-swipe class="my-swipe" :autoplay="3000" indicator-color="white">
  32. <van-swipe-item v-for="item in bannerList" :key="item.id">
  33. <image class="banner-image" :src="item.image" mode="widthFix"></image>
  34. </van-swipe-item>
  35. </van-swipe>
  36. </view> -->
  37. <view class="search">
  38. <view @click="showSelectArea" class="left-area">
  39. <image src="@/static/home/address-icon.png"></image>
  40. <view class="area">{{ selectArea.name }}</view>
  41. <image src="../../static/home/arrow-icon.png" mode="aspectFit"></image>
  42. <view class="parting-line">|</view>
  43. </view>
  44. <view class="center-area">
  45. <image src="@/static/home/search-icon.png"></image>
  46. <van-field @click="searchAddress" v-model="queryParams.title" center placeholder="请选择地区" />
  47. </view>
  48. <view class="right-area">
  49. <view @click="searchAddress" class="search-button">
  50. 搜索
  51. </view>
  52. </view>
  53. </view>
  54. <view v-if="projectList.length > 0" class="server-list">
  55. <van-list v-model:loading="loading" :finished="finished" finished-text="没有更多了" ref="list"
  56. @load="onLoad">
  57. <view v-for="item in projectList" class="server-item" @click="toServiceDetail(item.id)">
  58. <view class="img-box">
  59. <image :src="item.image" mode="aspectFill"></image>
  60. </view>
  61. <view class="server-info">
  62. <view class="server-title">{{ item.title }}</view>
  63. <view class="time-coupon">
  64. <image src="@/static/home/time-icon.png"></image>
  65. <view class="time">{{ item.times }}分钟</view>
  66. <!-- <view class="coupon">{{ item.subTitle }}</view> -->
  67. </view>
  68. <view class="price">
  69. <view class="current-price">
  70. <text class="unit"></text>{{ item.price }}
  71. </view>
  72. <view class="original-price">
  73. <text class="unit"></text>{{ item.oldPrice }}
  74. </view>
  75. </view>
  76. <view class="sales-volume">
  77. <image src="@/static/icons/icon1.png"></image>
  78. <view class="desc">已售出{{ item.payNum }}+</view>
  79. </view>
  80. </view>
  81. <view class="selective-technician">
  82. <view @click.stop="selectTechnician(item.id)" class="btn">
  83. 选择技师
  84. </view>
  85. </view>
  86. </view>
  87. </van-list>
  88. </view>
  89. <van-empty v-else image="/static/empty/data.png" image-size="400rpx" description="暂无项目" />
  90. </view>
  91. <selectArea :show="showAeraPro" @close="closeAreaPro" @select="selectArea"></selectArea>
  92. </view>
  93. </template>
  94. <script>
  95. import selectArea from '../../components/selectArea.vue';
  96. import Position from '@/utils/position.js'
  97. export default {
  98. components: {
  99. selectArea
  100. },
  101. data() {
  102. return {
  103. bannerList: [],
  104. projectList: [],
  105. queryParams: {
  106. pageNo: 1,
  107. pageSize: 10,
  108. title: ''
  109. },
  110. loading: false,
  111. finished: false,
  112. technicianList: [],
  113. showAeraPro: false,
  114. area: ''
  115. }
  116. },
  117. onShow() {
  118. this.getBanner()
  119. this.getProject()
  120. this.getLocation()
  121. },
  122. methods: {
  123. //list列表滑动到底部自动新增数据列表
  124. onLoad() {
  125. this.queryParams.pageSize += 10;
  126. this.getProject()
  127. },
  128. //获取banner
  129. getBanner() {
  130. this.$api('getBanner', {}, res => {
  131. this.bannerList = res.result;
  132. })
  133. },
  134. //获取项目列表
  135. getProject() {
  136. this.$api('getProjectList', this.queryParams, res => {
  137. if (res.code == 200) {
  138. this.projectList = res.result.records;
  139. } else {
  140. this.finished = true
  141. }
  142. if (this.queryParams.pageSize > res.result.total) {
  143. this.finished = true
  144. }
  145. this.loading = false
  146. })
  147. },
  148. //获取技师详情
  149. selectTechnician(id) {
  150. this.$api('getProjectDetail', {
  151. id
  152. }, res => {
  153. if (res.code == 200) {
  154. uni.navigateTo({
  155. url: `/pages/technician/selectTechnician?serviceId=${id}`
  156. })
  157. sessionStorage.setItem('technicianList', JSON.stringify(res.result.tenPageList))
  158. }
  159. })
  160. },
  161. //跳转技师详情
  162. toServiceDetail(id) {
  163. uni.navigateTo({
  164. url: '/pages/technician/subscribeService?id=' + id
  165. })
  166. },
  167. //显示选择地区
  168. showSelectArea() {
  169. this.showAeraPro = true;
  170. },
  171. //关闭选择地区
  172. closeAreaPro() {
  173. this.showAeraPro = false;
  174. },
  175. //选择了地区信息
  176. selectArea(area) {
  177. // this.area = area;
  178. this.showAeraPro = false;
  179. },
  180. //搜索地址
  181. searchAddress() {
  182. if(uni.getStorageSync('open_address') == 0){
  183. return
  184. }
  185. Position.getLocation(res => {
  186. Position.selectAddress(res.longitude, res.latitude, success => {
  187. let address = this.extractProvinceAndCity(success)
  188. this.queryParams.title = address.city
  189. })
  190. })
  191. },
  192. //提取用户选择的地址信息(省市县信息)
  193. extractProvinceAndCity(res) { //提取用户选择的地址信息(省市)
  194. if (!res.address && res.name) { //用户直接选择城市的逻辑
  195. return {
  196. province: '',
  197. city: res.name
  198. };
  199. }
  200. if (res.address) { //用户选择了详细地址,要从详细地址中提取出省市县信息
  201. // 使用正则表达式匹配省市县
  202. const regex = /(?<province>[\u4e00-\u9fa5]+?省)(?<city>[\u4e00-\u9fa5]+?(?:市|自治州|盟|地区))/;
  203. const match = res.address.match(regex);
  204. if (match) { // 如果匹配成功,则返回省和市的信息
  205. return {
  206. province: match.groups.province,
  207. city: match.groups.city
  208. };
  209. }
  210. }
  211. return { //用户没选择地址就点了确定按钮
  212. province: '',
  213. city: ''
  214. }
  215. },
  216. //获取用户详细地址(省市县)
  217. getLocation() {
  218. if(uni.getStorageSync('open_address') == 0){
  219. return
  220. }
  221. Position.getLocationDetail().then(res => {
  222. if(!this.selectArea.name && this.configList.open_address == 0){
  223. this.$store.commit('setArea', {
  224. name : res.addressDetail.district
  225. })
  226. }
  227. })
  228. },
  229. }
  230. }
  231. </script>
  232. <style lang="scss" scoped>
  233. .home {
  234. width: 750rpx;
  235. background: #F5F5F5;
  236. margin: 0 auto;
  237. .home-top {
  238. height: 400rpx;
  239. // height: 350rpx;
  240. background: linear-gradient(38deg, #4899A6, #60BDA2);
  241. padding-top: 60rpx;
  242. }
  243. .search {
  244. height: 82rpx;
  245. width: 710rpx;
  246. background: #FFFFFF;
  247. margin: 20rpx auto;
  248. border-radius: 41rpx;
  249. box-sizing: border-box;
  250. padding: 0 15rpx;
  251. display: flex;
  252. align-items: center;
  253. justify-content: space-between;
  254. .left-area,
  255. .center-area {
  256. display: flex;
  257. align-items: center;
  258. }
  259. .left-area {
  260. max-width: 160rpx;
  261. image {
  262. flex-shrink: 0;
  263. width: 26rpx;
  264. height: 26rpx;
  265. }
  266. .area {
  267. font-size: 24rpx;
  268. display: -webkit-box;
  269. -webkit-line-clamp: 2;
  270. /* 限制显示两行 */
  271. -webkit-box-orient: vertical;
  272. overflow: hidden;
  273. text-overflow: ellipsis;
  274. color: #292929;
  275. }
  276. .parting-line {
  277. flex-shrink: 0;
  278. font-size: 26rpx;
  279. color: #ccc;
  280. margin: 0rpx 5rpx;
  281. }
  282. }
  283. .center-area {
  284. display: flex;
  285. flex-wrap: nowrap;
  286. align-items: center;
  287. width: calc(100% - 290rpx);
  288. image {
  289. width: 26rpx;
  290. height: 26rpx;
  291. }
  292. .van-field {
  293. background-color: transparent;
  294. box-sizing: border-box;
  295. height: 82rpx;
  296. line-height: 82rpx;
  297. width: calc(100% - 30rpx);
  298. padding: 0rpx 10rpx 0rpx 0rpx;
  299. input {
  300. height: 82rpx;
  301. font-size: 60rpx;
  302. }
  303. }
  304. }
  305. .right-area {
  306. .search-button {
  307. background: #60BDA2;
  308. height: 60rpx;
  309. width: 130rpx;
  310. font-size: 26rpx;
  311. border-radius: 35rpx;
  312. color: white;
  313. display: flex;
  314. align-items: center;
  315. justify-content: center;
  316. }
  317. }
  318. }
  319. .banner {
  320. box-sizing: border-box;
  321. .my-swipe {
  322. width: 100%;
  323. margin: 0px auto;
  324. // border-radius: 20rpx;
  325. // height: 334rpx;
  326. overflow: hidden;
  327. .van-swipe-item {
  328. width: 100%;
  329. .banner-image {
  330. width: 100%;
  331. image {
  332. width: 100%;
  333. }
  334. }
  335. }
  336. }
  337. }
  338. .home-content {
  339. width: calc(100% - 40rpx);
  340. margin: 20rpx 20rpx 0rpx 20rpx;
  341. // margin: -440rpx 20rpx 0rpx 20rpx;
  342. // margin: -240rpx 20rpx 0rpx 20rpx;
  343. .server-list {
  344. padding-bottom: 80rpx;
  345. .server-item {
  346. display: flex;
  347. flex-wrap: wrap;
  348. justify-content: space-between;
  349. background: white;
  350. border-radius: 15rpx;
  351. box-sizing: border-box;
  352. padding: 15rpx;
  353. margin: 20rpx 0rpx;
  354. .img-box {
  355. width: 150rpx;
  356. height: 150rpx;
  357. border-radius: 10rpx;
  358. overflow: hidden;
  359. image {
  360. width: 100%;
  361. height: 100%;
  362. }
  363. }
  364. .server-info {
  365. display: flex;
  366. flex-direction: column;
  367. justify-content: space-around;
  368. width: calc(100% - 330rpx);
  369. box-sizing: border-box;
  370. padding: 0 10rpx;
  371. .server-title {}
  372. .time-coupon,
  373. .price {
  374. display: flex;
  375. flex-wrap: wrap;
  376. align-items: center;
  377. }
  378. .time-coupon {
  379. font-size: 26rpx;
  380. image {
  381. width: 22rpx;
  382. height: 22rpx;
  383. }
  384. .time {
  385. color: #B8B8B8;
  386. margin-left: 6rpx;
  387. }
  388. .coupon {
  389. display: flex;
  390. justify-content: center;
  391. align-items: center;
  392. background: #F29E45;
  393. color: white;
  394. width: 140rpx;
  395. height: 45rpx;
  396. border-radius: 10rpx;
  397. margin-left: 10rpx;
  398. }
  399. }
  400. .price {
  401. display: flex;
  402. align-items: center;
  403. color: #B8B8B8;
  404. .current-price {
  405. font-size: 30rpx;
  406. font-weight: 600;
  407. color: #D34430;
  408. margin-right: 5rpx;
  409. }
  410. .unit {
  411. font-size: 20rpx;
  412. }
  413. }
  414. .sales-volume {
  415. display: flex;
  416. align-items: center;
  417. color: #B8B8B8;
  418. font-size: 26rpx;
  419. image {
  420. width: 23rpx;
  421. height: 23rpx;
  422. }
  423. }
  424. }
  425. .selective-technician {
  426. display: flex;
  427. flex-wrap: wrap;
  428. align-items: center;
  429. width: 170rpx;
  430. .btn {
  431. display: flex;
  432. align-items: center;
  433. justify-content: center;
  434. height: 60rpx;
  435. width: 170rpx;
  436. border-radius: 40rpx;
  437. color: white;
  438. background: linear-gradient(170deg, #53CEAC, #5AC796);
  439. }
  440. }
  441. }
  442. }
  443. }
  444. }
  445. </style>