<template>
|
|
<view class="home">
|
|
|
|
<!-- <view class="home-top"> -->
|
|
<!-- <view class="search">
|
|
|
|
<view @click="showSelectArea" class="left-area">
|
|
<image src="@/static/home/address-icon.png"></image>
|
|
<view class="area">{{ area }}</view>
|
|
<image src="../../static/home/arrow-icon.png" mode="aspectFit"></image>
|
|
<view class="parting-line">|</view>
|
|
</view>
|
|
|
|
<view class="center-area">
|
|
<image src="@/static/home/search-icon.png"></image>
|
|
<van-field @click="searchAddress" v-model="queryParams.title" center placeholder="请选择地区" />
|
|
</view>
|
|
|
|
<view class="right-area">
|
|
<view @click="searchAddress" class="search-button">
|
|
搜索
|
|
</view>
|
|
</view>
|
|
|
|
</view> -->
|
|
<!-- </view> -->
|
|
|
|
<view class="banner b-relative">
|
|
<van-swipe class="my-swipe" :autoplay="3000" indicator-color="white">
|
|
<van-swipe-item v-for="item in bannerList" :key="item.id">
|
|
<image class="banner-image" :src="item.image" mode="widthFix"></image>
|
|
</van-swipe-item>
|
|
</van-swipe>
|
|
</view>
|
|
|
|
<view class="home-content">
|
|
|
|
<!-- <view class="banner b-relative">
|
|
<van-swipe class="my-swipe" :autoplay="3000" indicator-color="white">
|
|
<van-swipe-item v-for="item in bannerList" :key="item.id">
|
|
<image class="banner-image" :src="item.image" mode="widthFix"></image>
|
|
</van-swipe-item>
|
|
</van-swipe>
|
|
</view> -->
|
|
|
|
<view class="search">
|
|
|
|
<view @click="showSelectArea" class="left-area">
|
|
<image src="@/static/home/address-icon.png"></image>
|
|
<view class="area">{{ area }}</view>
|
|
<image src="../../static/home/arrow-icon.png" mode="aspectFit"></image>
|
|
<view class="parting-line">|</view>
|
|
</view>
|
|
|
|
<view class="center-area">
|
|
<image src="@/static/home/search-icon.png"></image>
|
|
<van-field @click="searchAddress" v-model="queryParams.title" center placeholder="请选择地区" />
|
|
</view>
|
|
|
|
<view class="right-area">
|
|
<view @click="searchAddress" class="search-button">
|
|
搜索
|
|
</view>
|
|
</view>
|
|
|
|
</view>
|
|
|
|
<view v-if="projectList.length > 0" class="server-list">
|
|
<van-list v-model:loading="loading" :finished="finished" finished-text="没有更多了" ref="list"
|
|
@load="onLoad">
|
|
<view v-for="item in projectList" class="server-item" @click="toServiceDetail(item.id)">
|
|
|
|
<view class="img-box">
|
|
<image :src="item.image" mode="aspectFill"></image>
|
|
</view>
|
|
|
|
<view class="server-info">
|
|
<view class="server-title">{{ item.title }}</view>
|
|
<view class="time-coupon">
|
|
<image src="@/static/home/time-icon.png"></image>
|
|
<view class="time">{{ item.times }}分钟</view>
|
|
<!-- <view class="coupon">{{ item.subTitle }}</view> -->
|
|
</view>
|
|
<view class="price">
|
|
<view class="current-price">
|
|
<text class="unit">¥</text>{{ item.price }}
|
|
</view>
|
|
<view class="original-price">
|
|
<text class="unit">¥</text>{{ item.oldPrice }}
|
|
</view>
|
|
</view>
|
|
<view class="sales-volume">
|
|
<image src="@/static/icons/icon1.png"></image>
|
|
<view class="desc">已售出{{ item.payNum }}+单</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="selective-technician">
|
|
<view @click.stop="selectTechnician(item.id)" class="btn">
|
|
选择技师
|
|
</view>
|
|
</view>
|
|
|
|
</view>
|
|
</van-list>
|
|
</view>
|
|
|
|
<van-empty v-else image="/static/empty/data.png" image-size="400rpx" description="暂无项目" />
|
|
|
|
</view>
|
|
|
|
<selectArea :show="showAeraPro" @close="closeAreaPro" @select="selectArea"></selectArea>
|
|
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
import selectArea from '../../components/selectArea.vue';
|
|
import Position from '@/utils/position.js'
|
|
|
|
export default {
|
|
components: {
|
|
selectArea
|
|
},
|
|
data() {
|
|
return {
|
|
bannerList: [],
|
|
projectList: [],
|
|
queryParams: {
|
|
pageNo: 1,
|
|
pageSize: 10,
|
|
title: ''
|
|
},
|
|
loading: false,
|
|
finished: false,
|
|
technicianList: [],
|
|
showAeraPro: false,
|
|
area: ''
|
|
}
|
|
},
|
|
onShow() {
|
|
this.getBanner()
|
|
this.getProject()
|
|
this.getLocation()
|
|
},
|
|
methods: {
|
|
//list列表滑动到底部自动新增数据列表
|
|
onLoad() {
|
|
this.queryParams.pageSize += 10;
|
|
this.getProject()
|
|
},
|
|
|
|
//获取banner
|
|
getBanner() {
|
|
this.$api('getBanner', {}, res => {
|
|
this.bannerList = res.result;
|
|
})
|
|
},
|
|
|
|
//获取项目列表
|
|
getProject() {
|
|
this.$api('getProjectList', this.queryParams, res => {
|
|
if (res.code == 200) {
|
|
this.projectList = res.result.records;
|
|
} else {
|
|
this.finished = true
|
|
}
|
|
if (this.queryParams.pageSize > res.result.total) {
|
|
this.finished = true
|
|
}
|
|
this.loading = false
|
|
})
|
|
},
|
|
|
|
//获取技师详情
|
|
selectTechnician(id) {
|
|
this.$api('getProjectDetail', {
|
|
id
|
|
}, res => {
|
|
if (res.code == 200) {
|
|
uni.navigateTo({
|
|
url: `/pages/technician/selectTechnician?serviceId=${id}`
|
|
})
|
|
sessionStorage.setItem('technicianList', JSON.stringify(res.result.tenPageList))
|
|
}
|
|
})
|
|
},
|
|
|
|
//跳转技师详情
|
|
toServiceDetail(id) {
|
|
uni.navigateTo({
|
|
url: '/pages/technician/subscribeService?id=' + id
|
|
})
|
|
},
|
|
|
|
//显示选择地区
|
|
showSelectArea() {
|
|
this.showAeraPro = true;
|
|
},
|
|
|
|
//关闭选择地区
|
|
closeAreaPro() {
|
|
this.showAeraPro = false;
|
|
},
|
|
|
|
//选择了地区信息
|
|
selectArea(area) {
|
|
this.area = area;
|
|
this.showAeraPro = false;
|
|
|
|
//后端逻辑
|
|
this.updateSessionPositon(area)
|
|
},
|
|
|
|
//搜索地址
|
|
searchAddress() {
|
|
Position.getLocation(res => {
|
|
Position.selectAddress(res.longitude, res.latitude, success => {
|
|
let address = this.extractProvinceAndCity(success)
|
|
this.queryParams.title = address.city
|
|
})
|
|
})
|
|
},
|
|
|
|
//提取用户选择的地址信息(省市县信息)
|
|
extractProvinceAndCity(res) { //提取用户选择的地址信息(省市)
|
|
if (!res.address && res.name) { //用户直接选择城市的逻辑
|
|
return {
|
|
province: '',
|
|
city: res.name
|
|
};
|
|
}
|
|
|
|
if (res.address) { //用户选择了详细地址,要从详细地址中提取出省市县信息
|
|
// 使用正则表达式匹配省市县
|
|
const regex = /(?<province>[\u4e00-\u9fa5]+?省)(?<city>[\u4e00-\u9fa5]+?(?:市|自治州|盟|地区))/;
|
|
const match = res.address.match(regex);
|
|
if (match) { // 如果匹配成功,则返回省和市的信息
|
|
return {
|
|
province: match.groups.province,
|
|
city: match.groups.city
|
|
};
|
|
}
|
|
}
|
|
|
|
return { //用户没选择地址就点了确定按钮
|
|
province: '',
|
|
city: ''
|
|
}
|
|
},
|
|
|
|
//获取用户详细地址(省市县)
|
|
getLocation() {
|
|
Position.getLocationDetail().then(res => {
|
|
sessionStorage.setItem("position", JSON.stringify(res))
|
|
this.area = res.addressDetail.district
|
|
})
|
|
},
|
|
|
|
//初始化用户所在地区
|
|
initUserArea() {
|
|
if (!sessionStorage.getItem('position')) return this.getLocation()
|
|
let positionInfo = JSON.parse(sessionStorage.getItem('position'))
|
|
this.area = positionInfo.addressDetail.district
|
|
},
|
|
|
|
//更新用户所在区域(更新区县信息)
|
|
updateSessionPositon(area) {
|
|
if (sessionStorage.getItem('position')) {
|
|
let position = JSON.parse(sessionStorage.getItem('position'))
|
|
position.addressDetail.district = area
|
|
sessionStorage.setItem('position', JSON.stringify(position))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.home {
|
|
width: 750rpx;
|
|
background: #F5F5F5;
|
|
margin: 0 auto;
|
|
|
|
.home-top {
|
|
height: 400rpx;
|
|
// height: 350rpx;
|
|
background: linear-gradient(38deg, #4899A6, #60BDA2);
|
|
padding-top: 60rpx;
|
|
}
|
|
|
|
.search {
|
|
height: 82rpx;
|
|
width: 710rpx;
|
|
background: #FFFFFF;
|
|
margin: 20rpx auto;
|
|
border-radius: 41rpx;
|
|
box-sizing: border-box;
|
|
padding: 0 15rpx;
|
|
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
|
|
.left-area,
|
|
.center-area {
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
|
|
.left-area {
|
|
max-width: 160rpx;
|
|
|
|
image {
|
|
flex-shrink: 0;
|
|
width: 26rpx;
|
|
height: 26rpx;
|
|
}
|
|
|
|
.area {
|
|
font-size: 24rpx;
|
|
display: -webkit-box;
|
|
-webkit-line-clamp: 2;
|
|
/* 限制显示两行 */
|
|
-webkit-box-orient: vertical;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
color: #292929;
|
|
}
|
|
|
|
.parting-line {
|
|
flex-shrink: 0;
|
|
font-size: 26rpx;
|
|
color: #ccc;
|
|
margin: 0rpx 5rpx;
|
|
}
|
|
}
|
|
|
|
.center-area {
|
|
display: flex;
|
|
flex-wrap: nowrap;
|
|
align-items: center;
|
|
width: calc(100% - 290rpx);
|
|
|
|
image {
|
|
width: 26rpx;
|
|
height: 26rpx;
|
|
}
|
|
|
|
.van-field {
|
|
background-color: transparent;
|
|
box-sizing: border-box;
|
|
height: 82rpx;
|
|
line-height: 82rpx;
|
|
width: calc(100% - 30rpx);
|
|
padding: 0rpx 10rpx 0rpx 0rpx;
|
|
|
|
input {
|
|
height: 82rpx;
|
|
font-size: 60rpx;
|
|
}
|
|
}
|
|
}
|
|
|
|
.right-area {
|
|
.search-button {
|
|
background: #60BDA2;
|
|
height: 60rpx;
|
|
width: 130rpx;
|
|
font-size: 26rpx;
|
|
border-radius: 35rpx;
|
|
color: white;
|
|
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
.banner {
|
|
box-sizing: border-box;
|
|
|
|
.my-swipe {
|
|
width: 100%;
|
|
margin: 0px auto;
|
|
// border-radius: 20rpx;
|
|
// height: 334rpx;
|
|
overflow: hidden;
|
|
|
|
.van-swipe-item {
|
|
width: 100%;
|
|
|
|
.banner-image {
|
|
width: 100%;
|
|
|
|
image {
|
|
width: 100%;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.home-content {
|
|
width: calc(100% - 40rpx);
|
|
margin: 20rpx 20rpx 0rpx 20rpx;
|
|
// margin: -440rpx 20rpx 0rpx 20rpx;
|
|
// margin: -240rpx 20rpx 0rpx 20rpx;
|
|
|
|
|
|
.server-list {
|
|
padding-bottom: 80rpx;
|
|
|
|
.server-item {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
justify-content: space-between;
|
|
background: white;
|
|
border-radius: 15rpx;
|
|
box-sizing: border-box;
|
|
padding: 15rpx;
|
|
margin: 20rpx 0rpx;
|
|
|
|
.img-box {
|
|
width: 150rpx;
|
|
height: 150rpx;
|
|
border-radius: 10rpx;
|
|
overflow: hidden;
|
|
|
|
image {
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
}
|
|
|
|
.server-info {
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: space-around;
|
|
width: calc(100% - 330rpx);
|
|
box-sizing: border-box;
|
|
padding: 0 10rpx;
|
|
|
|
.server-title {}
|
|
|
|
.time-coupon,
|
|
.price {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
align-items: center;
|
|
}
|
|
|
|
.time-coupon {
|
|
font-size: 26rpx;
|
|
|
|
image {
|
|
width: 22rpx;
|
|
height: 22rpx;
|
|
}
|
|
|
|
.time {
|
|
color: #B8B8B8;
|
|
margin-left: 6rpx;
|
|
}
|
|
|
|
.coupon {
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
background: #F29E45;
|
|
color: white;
|
|
width: 140rpx;
|
|
height: 45rpx;
|
|
border-radius: 10rpx;
|
|
margin-left: 10rpx;
|
|
}
|
|
}
|
|
|
|
.price {
|
|
display: flex;
|
|
align-items: center;
|
|
color: #B8B8B8;
|
|
|
|
.current-price {
|
|
font-size: 30rpx;
|
|
font-weight: 600;
|
|
color: #D34430;
|
|
margin-right: 5rpx;
|
|
}
|
|
|
|
.unit {
|
|
font-size: 20rpx;
|
|
}
|
|
}
|
|
|
|
.sales-volume {
|
|
display: flex;
|
|
align-items: center;
|
|
color: #B8B8B8;
|
|
font-size: 26rpx;
|
|
|
|
image {
|
|
width: 23rpx;
|
|
height: 23rpx;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
.selective-technician {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
align-items: center;
|
|
width: 170rpx;
|
|
|
|
.btn {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
height: 60rpx;
|
|
width: 170rpx;
|
|
border-radius: 40rpx;
|
|
color: white;
|
|
background: linear-gradient(170deg, #53CEAC, #5AC796);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</style>
|