湘妃到家前端代码仓库
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.
 
 
 
 
 

527 lines
11 KiB

<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">{{ selectArea.name }}</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) {
uni.navigateTo({
url: `/pages/technician/selectTechnician?serviceId=${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;
},
//搜索地址
searchAddress() {
if(uni.getStorageSync('open_address') == 0){
return
}
// Position.getLocation(res => {
Position.selectAddress(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() {
if(uni.getStorageSync('open_address') == 0){
return
}
Position.getLocationDetail().then(res => {
if(!this.selectArea.name && this.configList.open_address == 0){
this.$store.commit('setArea', {
name : res.addressDetail.district
})
}
})
},
}
}
</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>