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.
 
 
 
 
xxdj1/pages/service.vue

855 lines
20 KiB

<template>
<view class="pages-home">
<view class="map-info">
<!-- <view class="position" @tap.stop="toChooseLocation" >
<i class="iconfont iconjuli mr-sm"></i>
<view class="map-text max-400 ellipsis">
{{location&&location.province ?location.province : isLoad ? '定位失败' : '定位中...'}}
</view>
</view> -->
<view class="input" @click="goSearch">
<u--input
placeholder="查找技师或服务"
prefixIcon="search"
shape="circle"
:disabled="true"
prefixIconStyle="font-size: 34rpx;color: #A9B4BD"
></u--input>
</view>
</view>
<!-- :style="{height:banner.length > 0?`464rpx`:`84rpx`}" -->
<!-- :class="[{'rel':banner.length >0}]" -->
<view >
<u-swiper :list="banner" keyName="img" interval="5000" :height="260"></u-swiper>
<!-- <banner :list="banner" :height="580" :margin="0" :autoplay="true" :indicatorActiveColor="primaryColor" :dotWidth="20"
:dotBottom="30" v-if="banner.length > 0">
</banner> -->
<view class="tab">
<view class="tabItem" v-for="(item,index) in gridList" :key="index" @click="getItemHandle(item)">
<auth :needAuth="userInfo && (!userInfo.phone || !userInfo.nickName)" :must="true"
:type="!userInfo.phone ? 'phone' : 'userInfo'" @go="toAtv" v-if="item.name=='邀请有礼'">
<view>
<image :src="item.img" mode=""></image>
<view class="text">{{item.name}}</view>
</view>
</auth>
<image :src="item.img" mode="" v-if="item.name!='邀请有礼'"></image>
<view class="text" v-if="item.name!='邀请有礼'">{{item.name}}</view>
</view>
</view>
<view class="gridContainer">
<view class="sectionTitle">
<image src="../static/titleicon.png" mode="" lazy-load></image>
<text>推荐技师</text>
</view>
<swiper class="swiper" circular :indicator-dots="false" :autoplay="false" :interval="2000"
:duration="1000" previous-margin="108px" next-margin="108px">
<swiper-item class="recommendItem" v-for="(item, index) in picList" :key="index">
<view style="margin:0 8rpx;position:relative;border-radius: 27rpx;overflow: hidden;">
<image :src="item.work_img" mode="aspectFill" lazy-load></image>
<view class="flag new" v-if="item.coach_type_status==3">新人</view>
<view class="flag people" v-if="item.coach_type_status==2">推荐</view>
<view class="flag people" v-if="item.coach_type_status==1">销冠</view>
<view class="nameText">
{{item.coach_name}}
</view>
</view>
</swiper-item>
</swiper>
<!-- <u-scroll-list :indicator="false">
<view class="recommendItem" v-for="(item, index) in picList" :key="index">
<image :src="item.work_img"></image>
<view class="flag new" v-if="item.coach_type_status==3">新人</view>
<view class="flag people" v-if="item.coach_type_status==2">推荐</view>
<view class="flag people" v-if="item.coach_type_status==1">销冠</view>
</view>
</u-scroll-list> -->
</view>
<!-- <view class="search-box flex-center fill-base ml-md mr-md radius"
:class="[{'mt-md':banner.length ==0}]">
<view style="width: 92%;">
<tab @change="handerTabChange" :isLine="false" :list="tabList" :activeIndex="activeIndex*1"
:activeColor="primaryColor" :width="100/tabList.length + '%'" height="84rpx"></tab>
</view>
<view style="width: 8%;"></view>
</view> -->
</view>
<view class="sectionTitle" style="padding:0 24rpx;">
<image src="../static/xiangmu.png" mode=""></image>
<text>服务项目</text>
</view>
<view @tap.stop="goDetail(index)" class="list-item flex-center mt-md ml-md mr-md pd-lg fill-base radius-16"
v-for="(item, index) in list.data" :key="index">
<image mode="aspectFill" class="cover radius-16" lazy-load :src="item.cover"></image>
<view class="flex-1 ml-md" style="max-width: 450rpx;">
<view class="flex-between">
<view class="f-title itemTitle max-270 ellipsis">{{ item.title }}</view>
</view>
<view class="subTitle ellipsis">{{ item.sub_title || '' }}
</view>
<view class="timeInfo">
<view class="time-long">
<image src="../static/time.png" mode=""></image>
<text>{{ item.time_long }}分钟</text>
</view>
<view class="lookNum">超{{ item.total_sale }}人选择</view>
<!-- <view class="flex-y-baseline f-icontext c-warning ml-sm mr-sm">¥<view class="f-sm-title">
{{ item.price }}
</view>
</view>
<view class="text-delete" v-if="item.init_price">¥{{ item.init_price }}</view> -->
</view>
<view class="priceContent">
<text>¥{{ item.price }}</text>
<view class="item-btn flex-center f-caption c-base" :style="{ background: primaryColor }">
选择技师
</view>
</view>
</view>
</view>
<load-more :noMore="list.current_page >= list.last_page && list.data.length > 0" :loading="loading"
v-if="loading">
</load-more>
<abnor v-if="!loading && list.data.length <= 0 && list.current_page == 1"></abnor>
<view class="space-footer"></view>
<uni-popup ref="coupon_item" type="center" :maskClick="false">
<view class="coupon-popup f_r_c_c">
<image class="bg-img" src="https://lbqnyv2.migugu.com/bianzu3.png" mode=""></image>
<i @tap.stop="$refs.coupon_item.close()" class="iconfont icon-close c-base"></i>
</image>
<view class="coupon-info f_c_m_c">
<view class="tops f_c_m_c">
<view class="">
成功领取
</view>
<view class="">
卡券将放入“我的-我的卡券”
</view>
</view>
<view class="lists f_r_c_c">
<scroll-view scroll-y style="width: 420rpx;height:100%;">
<view class="list f_r_sb_c" v-for="(item, index) in couponList" :key="index">
<image src="/static/coupon/coupon.png" mode="aspectFill"></image>
<view class="f_r_sb_c">
<view class="f_c_m_c">
<view class="price">
{{item.discount}}
</view>
<view class="price_text">
{{item.full*1>0?`满${item.full}可用`:`立减`}}
</view>
</view>
<view class="title f_r_m_c">
<view class="ellipsis-3">
{{item.title}}
</view>
</view>
</view>
</view>
</scroll-view>
</view>
</view>
<view class="btns f_r_c_c" @tap.stop="userGetCoupon">
<view class="f_r_c_c">
领取到卡包
</view>
</view>
</view>
</uni-popup>
<!-- <view :style="{height: `${configInfo.tabbarHeight}px`}"></view> -->
<!-- <tabbar :cur="0"></tabbar> -->
</view>
</template>
<script>
import {
mapState,
mapActions,
mapMutations
} from "vuex"
// import tabbar from "@/components/tabbar.vue"
export default {
// components: {
// tabbar
// },
data() {
return {
couponList: [], //优惠券
isLoad: false,
isLoadBanner: false,
options: {},
loading: true,
lockTap: false,
gridList:[
{img:'../static/t1.png',name:'领券中心'},
{img:'../static/t2.png',name:'邀请有礼'},
{img:'../static/t3.png',name:'联系客服'},
{img:'../static/t4.png',name:'技师招募'},
],
picList:[
// {img:'../static/i.png',new:1,people:0},
// {img:'../static/i.png',new:1,people:0},
// {img:'../static/i.png',new:1,people:0},
// {img:'../static/i.png',new:1,people:0},
// {img:'../static/i.png',new:0,people:1},
// {img:'../static/i.png',new:0,people:0},
// {img:'../static/i.png',new:0,people:0},
],
banner:[]
}
},
computed: mapState({
// location: state => state.user.location,
pageActive: state => state.service.pageActive,
activeIndex: state => state.service.activeIndex,
tabList: state => state.service.tabList,
param: state => state.service.param,
commonOptions: state => state.user.commonOptions,
list: state => state.service.list,
// banner: state => state.service.banner,
primaryColor: state => state.config.configInfo.primaryColor,
subColor: state => state.config.configInfo.subColor,
configInfo: state => state.config.configInfo,
autograph: state => state.user.autograph,
userInfo: state => state.user.userInfo,
mineInfo: state => state.user.mineInfo,
userPageType: state => state.user.userPageType,
}),
onShow() {
this.getServiceIndex()
},
async onLoad(options) {
this.getRecommend()
this.$util.showLoading()
options = await this.updateCommonOptions(options)
this.options = options
if (this.pageActive) {
this.$util.setNavigationBarColor({
bg: this.primaryColor
})
this.isLoad = true
this.loading = false
this.$util.hideAll()
return
}else{
this.$util.setNavigationBarColor({
bg: '#08BF77'
})
}
// await this.getMineInfo()
await this.initIndex()
this.updateServiceItem({
key: 'pageActive',
val: true
})
console.log(this.banner,"88888")
},
onPullDownRefresh() {
// #ifndef APP-PLUS
uni.showNavigationBarLoading()
// #endif
this.initRefresh();
uni.stopPullDownRefresh()
},
onReachBottom() {
if (this.list.current_page >= this.list.last_page || this.loading) return;
this.loading = true;
this.getList(this.param.page + 1);
},
onShareAppMessage(e) {
let {
id: pid
} = this.userInfo
let path = `/pages/service?pid=${pid}`
this.$util.log(path)
return {
title: '',
imageUrl: '',
path,
}
},
methods: {
...mapActions(['getConfigInfo', 'getUserInfo', 'getMineInfo','updateCommonOptions', 'getServiceList']),
...mapMutations(['updateServiceItem','updateUserItem']),
async toAtv() {
if (!this.mineInfo.is_atv) {
this.$util.showToast({
title: `暂无活动`
})
return
}
let options = this.commonOptions
options.coupon_atv_id = 0
await this.updateCommonOptions(options)
this.$util.goUrl({
url: `/user/pages/coupon/share`
})
},
async getServiceIndex(param) {
let d = await this.$api.service.indexBanner(param);
console.log(d,"====");
this.banner = d.banner;
// let {
// banner
// } = d
// commit('updateServiceItem', {
// key: 'banner',
// val: banner
// })
},
async initIndex(refresh = false) {
// #ifdef H5
// if (!refresh && this.$jweixin.isWechat()) {
// await this.$jweixin.initJssdk();
// this.toAppShare()
// }
// #endif
if (!this.configInfo.id || refresh) {
await this.getConfigInfo()
}
await this.getServiceIndex()
this.isLoad = true
this.isLoadBanner = true
// await Promise.all([this.getList(1), this.getCouponList()])
await Promise.all([this.getList(1)])
this.$util.setNavigationBarColor({
bg: this.primaryColor
})
},
async getRecommend(){
let res = await this.$api.service.serviceCoachList({
sort_field:'distance',
sort_order:'asc',
limit:10
})
console.log(res,"ooo")
this.picList = res.data
let arr = res.data
if(this.picList.length<3){
this.picList.push(...arr)
}else{
this.picList = res.data
}
},
getItemHandle(item){
console.log("点击项",this.configInfo)
if(item.name=="领券中心"){
this.$util.goUrl({
url: '/user/pages/coupon/list'
})
}
if(item.name=="联系客服"){
let {
mobile: mobile,
im_type
} = this.configInfo
// #ifdef MP-WEIXIN
if (im_type == 2) return
// #endif
this.$util.goUrl({
url:mobile,
openType: 'call'
})
}
if(item.name=="技师招募"){
if(this.userPageType==1){
uni.navigateTo({
url:"/technician/pages/apply"
})
}else{
uni.navigateTo({
url:"/user/pages/gonggao/item?id=1"
})
}
}
},
initRefresh() {
this.isLoadBanner = false
this.initIndex(true)
},
toAppShare() {
let {
id: pid
} = this.userInfo
let title = '首页'
let page_url = window.location.href
if (page_url.includes('?pid=')) {
page_url = page_url.split('?pid=')[0]
}
let href = `${page_url}?pid=${pid}`
let imageUrl = ''
this.$jweixin.wxReady(() => {
this.$jweixin.showOptionMenu()
this.$jweixin.shareAppMessage(title, '', href, imageUrl)
this.$jweixin.shareTimelineMessage(title, href, imageUrl)
})
},
async userGetCoupon() {
console.log("=====userGetCoupon")
let ids = []
this.couponList.forEach(v => {
ids.push(v.id)
})
let res = await this.$api.service.userGetCoupon({
coupon_id: ids
})
this.$util.showToast({
title: `领取成功`
})
setTimeout(() => {
this.$util.goUrl({
url: '/user/pages/coupon/list'
})
}, 1000)
this.$refs.coupon_item.close()
this.loading = false
this.$util.hideAll()
},
async getCouponList() {
let list = await this.$api.service.couponList()
this.couponList = list
if (list.length > 0 && this.isLoad) {
this.$refs.coupon_item.open()
}
this.loading = false
this.$util.hideAll()
},
async getList(page = 0) {
if (page) {
let param = this.$util.deepCopy(this.param)
param.page = page
this.updateServiceItem({
key: 'param',
val: param
})
}
let {
list: oldList,
param,
tabList,
activeIndex
} = this
let {
sort,
sign
} = tabList[activeIndex]
let desc = activeIndex == 0 || sign == 1 ? '' : 'desc'
param.sort = `${sort} ${desc}`
await this.getServiceList(param)
this.loading = false
this.$util.hideAll()
},
handerTabChange(index) {
this.updateServiceItem({
key: 'activeIndex',
val: index
})
let tabList = this.$util.deepCopy(this.tabList)
let {
is_sign,
sign,
} = tabList[index];
if (is_sign) {
tabList[index].sign = sign == 0 ? 1 : 0;
}
this.updateServiceItem({
key: 'tabList',
val: tabList
})
this.$util.showLoading()
uni.pageScrollTo({
scrollTop: 0
})
this.getList(1)
},
// 详情
goDetail(index) {
let {
id
} = this.list.data[index]
let url = `/user/pages/detail?id=${id}`
this.$util.goUrl({
url
})
},
// async toChooseLocation(e) {
// await this.$util.checkAuth({
// type: 'userLocation'
// })
// let [, {
// address = '',
// longitude: lng,
// latitude: lat,
// province = '',
// city = '',
// district = '',
// }] = await uni.chooseLocation();
// if (!lng) return
// let location = {
// lng,
// lat,
// address,
// province,
// city,
// district
// }
// this.updateUserItem({
// key: 'location',
// val: location
// })
// },
goSearch(){
this.$util.goUrl({
url: `/pages/technician`
})
}
}
}
</script>
<style lang="scss">
.pages-home {
background-color: #ffffff;
min-height:calc(100vh);
position:relative;
.map-info{
// background-color: red;
position:absolute;
z-index:99;
width:100%;
top:20rpx;
padding:21rpx;
display:flex;
.position{
color:#ffffff;
display: flex;
align-items: center;
}
.input{
flex:1;
margin-left:30rpx;
/deep/.u-input--circle{
background-color: #EEFDF8;
}
}
}
.search-box {
width: 710rpx;
bottom: 0;
z-index: 9;
overflow: hidden;
}
.tab{
background-color: #ffffff;
border-radius: 30rpx 30rpx 0rpx 0rpx;
margin-top: -58rpx;
position: relative;
z-index: 99;
display:flex;
align-items: center;
justify-content: space-between;
padding:45rpx;
.tabItem{
text-align: center;
image{
width:100rpx;
height:100rpx;
}
.text{
margin-top:25rpx;
font-size: 26rpx;
font-family: Alibaba PuHuiTi;
font-weight: 400;
color: #333333;
}
}
}
.sectionTitle{
display:flex;
align-items: center;
margin-bottom:21rpx;
image{
width:34rpx;
height:39rpx;
}
text{
font-size: 34rpx;
font-family: Alibaba PuHuiTi;
font-weight: 400;
color: #333333;
margin-left:15rpx;
}
}
.gridContainer{
margin-top:13rpx;
padding:0 24rpx;
.recommendItem{
// width:240rpx;
// height:300rpx;
// background: #aaaaaa;
// border-radius: 27rpx;
// overflow: hidden;
// margin-right:24rpx;
// position: relative;
image{
// width:240rpx;
width:100%;
height:300rpx;
border-radius: 27rpx;
}
.nameText{
position: absolute;
height:50rpx;
bottom:0rpx;
line-height:50rpx;
background-color: rgba(0, 0, 0, 0.5);
color:#ffffff;
z-index:99;
width:100%;
text-align: center;
}
.flag{
width: 100rpx;
height: 50rpx;line-height: 50rpx;text-align: center;
background: #08BF77;
position: absolute;
border-radius: 27rpx 0px 27rpx 0px;
top:0;
left:0;
font-size: 24rpx;
color:#ffffff;
}
.new{
background: #08BF77;
}
.people{
background: #F4563C;
}
}
}
.list-item {
background: #F4F7F6;
.cover {
width: 200rpx;
height: 200rpx;
}
.itemTitle{
color:#333333;
font-size: 34rpx;
}
.subTitle{
color: #C0C5CA;
font-size: 24rpx;
margin-top:6rpx;
}
.timeInfo{
margin:15rpx 0;
display:flex;
align-items: center;
justify-content: space-between;
}
.time-long {
display: flex;
align-items: center;
image{
width:30rpx;
height:30rpx;
}
text{
color: #71787E;
font-size: 24rpx;
margin-left:14rpx;
}
// min-width: 72rpx;
// height: 30rpx;
// padding: 0 5rpx;
// background: linear-gradient(270deg, #4C545A 0%, #282B34 100%);
// border-radius: 4rpx;
// font-size: 20rpx;
// color: #FFEEB9;
// margin-right: 16rpx;
}
.lookNum{
color: #71787E;
font-size: 24rpx;
}
.priceContent{
display: flex;
align-items: center;
justify-content: space-between;
text{
color: #F4563C;
font-size:30rpx;
}
.item-btn {
// width: 160rpx;
// line-height: 54rpx;
text-align: center;
// height: 54rpx;
padding:15rpx 33rpx;
background: #08BF77;
border: 1px solid #EAEAEA;
border-radius: 27px;
}
}
.f-icontext {
font-size: 18rpx;
}
.text-delete {
font-size: 20rpx;
color: #B9B9B9;
}
}
}
.coupon-popup {
width: 658rpx;
height: 865rpx;
position: relative;
.bg-img {
width: 100%;
height: 100%;
}
.icon-close {
font-size: 60rpx;
position: absolute;
top: 50rpx;
right: 60rpx;
z-index: 999;
}
.coupon-info {
position: absolute;
width: 100%;
height: 100%;
bottom: 0;
left: 0;
.tops {
width: 480rpx;
color: #FB4523;
position: absolute;
top: 260rpx;
>view:nth-child(1) {
font-weight: bold;
font-size: 30rpx;
}
}
.lists {
width: 500rpx;
height: 300rpx;
padding: 10rpx;
overflow-x: hidden;
position: absolute;
bottom: 222rpx;
.list {
width: 420rpx;
height: 130rpx;
margin-bottom: 10rpx;
margin-top: 5rpx;
position: relative;
>image {
width: 100%;
height: 100%;
}
>view {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 8rpx;
>view:nth-child(1) {
width: 38%;
}
>view:nth-child(2) {
display: flex;
justify-content: center;
flex: 1;
padding: 0 15rpx;
box-sizing: border-box;
}
.price {
font-size: 30rpx;
color: #FB4523;
}
.title {
font-size: 30rpx;
line-height: 36rpx;
font-weight: bold;
}
.price_text {
color: #ccc;
}
}
}
}
}
view.btns {
width: 100%;
position: absolute;
height: 82rpx;
bottom: 18rpx;
left: 0;
>view {
width: 422rpx;
height: 82rpx;
border-radius: 40rpx;
font-size: 34rpx;
color: #FFFFFF;
}
}
}
</style>