美容行业门店服务预约小程序。美容行业门店服务预约小程序,适用于线下个体户,有自己的品牌或者门店的商家,店主,做美容,美发,医美,按摩等服务性质行业的在线预约,管理,可实现客户在线查看,服务预约,到期提醒,商家在线管理服务项目,服务订单 ,处理服务 ,通知客户等,增强门店品牌效应,展示产品,提高服务产品营销传播途径,给客户带来信任感,降低销售阻力。
<template>
<view class="pages-user-login" v-if="isLoad">
<view class="flex-center flex-column" style="height: 100vh">
<view class="logo-img mb-md">
<view class="h5-image logo-img" :style="{ backgroundImage : `url('${configInfo.app_logo}')`}">
view>
view>
<image mode="aspectFill" lazy-load class="logo-img mb-md" :src="configInfo.app_logo">image>
<view class="f-caption c-caption">{{configInfo.app_text}}view>
<view style="height: 200rpx;">view>
<view @tap.stop="toChooseLogin('weixin')" class="login-btn wechat flex-center f-title c-base radius" :style="{
background: `linear-gradient(90deg, ${primaryColor} 0%, ${subColor} 99%)`}"><i
class="iconfont icon-weixin mr-md">i>微信登录
view>
<view @tap.stop="toChooseLogin('apple')" class="login-btn apple flex-center f-title c-black radius"
v-if="is_ios_login"><i class="iconfont icon-apple mr-sm">i>Sign in with Apple
view>
view>
<uni-popup ref="show_rule_item" type="center" :maskClick="false">
<view class="common-popup-content fill-base pd-lg radius-34">
<view class="title">温馨提示view>
<view class="f-desc c-title mt-lg">
登录即表示您已详细阅读并同意<span @tap.stop="$util.goUrl({url:`/user/pages/protocol`})"
:style="{color:primaryColor}">
《隐私政策》
span>与<span @tap.stop="$util.goUrl({url:`/user/pages/information`})"
:style="{color:primaryColor}">
《服务协议》
span>
view>
<view class="button">
<view @tap.stop="$refs.show_rule_item.close()" class="item-child">取消view>
<view @tap.stop="toConfirm" class="item-child" :style="{background: primaryColor,color:'#fff'}">确定
view>
view>
view>
uni-popup>
view>
template>
<script>
import {
mapState,
mapActions,
mapMutations
} from 'vuex';
import siteInfo from '@/siteinfo.js';
export default {
components: {},
data() {
return {
isLoad: false,
is_ios_login: false
}
},
async onLoad(options) {
let [syserr, sysinfo] = await uni.getSystemInfo()
let {
browserVersion = '',
platform
} = sysinfo
this.is_ios_login = platform === 'ios' && browserVersion.split('.')[0] * 1 > 12
if (!this.configInfo.id) {
await this.getConfigInfo()
}
this.isLoad = true
},
computed: mapState({
primaryColor: state => state.config.configInfo.primaryColor,
subColor: state => state.config.configInfo.subColor,
configInfo: state => state.config.configInfo,
commonOptions: state => state.user.commonOptions,
autograph: state => state.user.autograph,
appLogin: state => state.user.appLogin,
loginType: state => state.user.loginType,
loginPage: state => state.user.loginPage,
userInfo: state => state.user.userInfo,
}),
methods: {
...mapActions(['getConfigInfo', 'getUserInfo']),
...mapMutations(['updateConfigItem', 'updateUserItem', 'updateOrderItem']),
toChooseLogin(type) {
this.updateUserItem({
key: 'loginType',
val: type
})
this.$refs.show_rule_item.open()
},
toConfirm() {
this.$refs.show_rule_item.close()
// #ifdef H5
this.toGzhLogin()
// #endif
// #ifdef APP-PLUS
this.toAppLogin()
// #endif
},
// 公众号登录
async toGzhLogin() {
let {
siteroot,
gzh_appid
} = siteInfo
this.updateUserItem({
key: 'isGzhLogin',
val: true
})
this.updateUserItem({
key: 'autograph',
val: ''
})
this.updateUserItem({
key: 'commonOptions',
val: this.commonOptions
})
let {
loginPage
} = this
let url = siteroot.split('/index.php')[0]
let href = `${url}/h5/#${loginPage}`
let pageUrl = window.location.href;
let redirect_uri = encodeURIComponent(href)
let authUrl =
`https://open.weixin.qq.com/connect/oauth2/authorize?appid=${gzh_appid}&redirect_uri=${redirect_uri}&response_type=code&scope=snsapi_userinfo&state=1&connect_redirect=1#wechat_redirect`;
window.location.href = authUrl
},
//APP登录
async toAppLogin() {
this.$refs.show_rule_item.close()
let {
loginType: provider
} = this
try {
let [providerErr, providerData] = await uni.getProvider({
service: 'oauth',
});
if (providerErr) {
this.$util.showToast({
title: providerErr
})
return
}
let [loginErr, loginData] = await uni.login({
provider
});
if (loginErr) {
this.$util.showToast({
title: loginErr
})
return
}
let [infoErr, infoData] = await uni.getUserInfo({
provider
})
if (infoErr) {
this.$util.showToast({
title: infoErr
})
return
}
let {
userInfo = {}
} = infoData
let {
openId = ''
} = userInfo
if (!openId) return
this.$util.showLoading({
title: "登录中..."
})
try {
let param = {
type: provider == 'weixin' ? 2 : 3,
param: {
data: userInfo
},
init: 1
}
this.toConfirmLogin(param)
} catch (e) {
this.$util.hideAll()
}
} catch (e) {
this.$util.showToast({
title: `没有获取到用户信息,请确认已登录`
});
}
},
async toConfirmLogin(login_params) {
let {
loginType
} = this
let {
type,
param,
init = 0
} = login_params
let methodType = {
1: 'webLogin',
2: 'appLogin',
3: 'iosLogin'
}
let methodModel = methodType[type]
let user_info = await this.$api.base[methodModel](param)
if (init == 1) {
this.updateUserItem({
key: 'appLogin',
val: param.data
})
}
let {
autograph,
data
} = user_info
this.$util.hideAll()
this.updateUserItem({
key: 'isShowLogin',
val: false
})
this.updateUserItem({
key: 'userInfo',
val: data
})
this.updateUserItem({
key: 'autograph',
val: autograph
})
let {
phone = ''
} = data
let {
short_code_status = 0
} = this.configInfo
let isToPhone = loginType == 'weixin' && short_code_status && !phone
let url = isToPhone ? `/user/pages/phone` : this.loginPage || `/pages/service`
let pageArr = ['/pages/service', '/pages/technician', '/pages/order', '/pages/mine']
let openType = isToPhone || pageArr.includes(url) ? `reLaunch` : `navigateBack`
this.$util.goUrl({
url: (isToPhone || pageArr.includes(url)) ? url : 1,
openType
})
}
}
}
script>
<style lang="scss">
page {
background: #fff;
height: 100%;
}
.pages-user-login {
.logo-img {
width: 160rpx;
height: 160rpx;
}
.login-btn {
width: 220pt;
height: 44pt;
font-size: 15pt;
border: 1rpx solid #000;
transform: rotateZ(360deg);
.iconfont {
font-size: 19pt;
}
}
.wechat {
border: none;
font-size: 13pt;
box-shadow: 0 18rpx 9rpx 0 rgba(0, 188, 82, 0.07);
}
.apple {
margin-top: 40rpx;
}
.banner-info {
width: 100%;
.banner-img {
width: 100%;
height: 100%;
}
.swiper-to-home {
width: 122rpx;
height: 47rpx;
z-index: 999;
right: 40rpx;
top: 80rpx;
background: rgba(0, 0, 0, 0.3);
}
}
}
style>
<view class="pages-mine" v-if="isLoad">
<uni-nav-bar :fixed="true" :shadow="false" :statusBar="true"
:title="userPageType == 2?'我是'+$t('action.attendantName'):'我的'" color="#ffffff"
:backgroundColor="primaryColor">
uni-nav-bar>
<view :style="{height:`${configInfo.navBarHeight}px`}">view>
<image mode="aspectFill" lazy-load class="mine-bg abs" :src="configInfo[image_type[userPageType]]">image>
<block v-if="userPageType == 1">
<view class="pd-lg" style="height: 292rpx">
<view class="pt-lg rel"
:class="[{ 'flex-warp':userInfo && userInfo.nickName }, { 'flex-center': !userInfo || (userInfo && !userInfo.nickName) } ]">
<auth :needAuth="true" :must="true" :haveGo="false" class="avatar_view" style="width:120rpx">
<view class="avatar_view">
<image mode="aspectFill" class="avatar radius"
:src="userInfo.avatarUrl || `https://lbqny.migugu.com/admin/anmo/mine/default_user.png`">
image>
<view class="text" :style="{color:primaryColor}"
v-if="userInfo.id && mineInfo.is_admin == 1">
代理商
view>
view>
auth>
<auth :needAuth="true" :must="true" :haveGo="false" class="flex-1"
v-if="!userInfo || (userInfo && !userInfo.nickName)">
<view class="f-md-title text-bold ml-md" :style="{color:configInfo[font_type[userPageType]]}">登录
view>
auth>
<view class="flex-1 ml-md mt-sm rel" :style="{color:configInfo[font_type[userPageType]]}" v-else>
<view class="flex-between">
<auth :needAuth="true" :must="true" :haveGo="false">
<view class="flex-y-center f-title text-bold">
<view class="mr-sm max-300 ellipsis">
{{ userInfo.nickName || '默认用户' }}
view>
<i class="flex-1 iconfont iconbianjiziliao">i>
view>
auth>
<view @tap.stop="$util.goUrl({url:`/user/pages/setting`})" class="notice-item ml-md">
<i class="iconfont icon-xitong text-bold">i>
view>
view>
<view class="flex-center">
<view class="member-tag flex-center mt-sm pl-md pr-md f-caption radius ">
<i class="iconfont iconhuiyuanka mr-sm">i>
{{ mineInfo.coach_status === 2 ? mineInfo.coach_level && mineInfo.coach_level.length > 0 && mineInfo.coach_level.title ? mineInfo.coach_level.title : $t('action.attendantName') : '普通用户' }}
view>
<view @tap.stop="$util.goUrl({url:`/agent/pages/index?agent=0`})"
class="member-tag flex-center mt-sm ml-md pl-md pr-md f-caption radius "
v-if="mineInfo.mobilenode_auth">
<i class="iconfont iconqiehuanyonghuduan mr-sm">i>
切换管理员
view>
<view class="flex-1">view>
view>
view>
view>
view>
<auth :needAuth="userInfo && (!userInfo.phone || !userInfo.nickName)" :must="true"
:type="!userInfo.phone ? 'phone' : 'userInfo'" @go="$util.toCheckLogin({url:`/user/pages/stored/list`})"
v-if="configInfo.recharge_status">
<view class="flex-center pd-lg mt-md ml-md mr-md fill-base box-shadow radius-20 rel">
<view class="flex-1 mr-lg c-title">
<view class="f-paragraph">我的余额view>
<view class="f-big-title text-bold">{{ mineInfo.balance || 0 }}view>
view>
<view class="store-btn flex-center f-paragraph c-base radius" :style="{background:primaryColor}">
立即充值
view>
view>
auth>
<auth :needAuth="userInfo && (!userInfo.phone || !userInfo.nickName)" :must="true"
:type="!userInfo.phone ? 'phone' : 'userInfo'" @go="toAtv" style="width: 100%"
v-if="mineInfo.is_atv_status === 1">
<view style="height: 14rpx;">view>
<image mode="aspectFill" class="share-atv-img"
src="https://lbqny.migugu.com/admin/anmo/mine/share_atv.png">image>
auth>
<view class="mine-menu-list box-shadow fill-base radius-16"
:style="{margin:mineInfo.is_atv_status === 1 ? '10rpx 30rpx 0 30rpx' : ''}">
<view @tap="$util.toCheckLogin({url:`/pages/order`})"
class="menu-title flex-between pl-lg pr-md b-1px-b">
<view class="f-paragraph c-title text-bold">我的订单view>
<view class="flex-y-center f-caption c-paragraph">全部订单<i class="iconfont icon-right">i>view>
view>
<view class="flex-warp pt-lg pb-lg">
<view @tap.stop="toJump('orderList', index)"
class="item-child flex-center flex-column f-caption c-paragraph" style="width:20%"
v-for="(item, index) in orderList" :key="index">
<i class="iconfont" :class="item.icon" :style="{color:primaryColor}">i>
<view class="mt-sm">{{ item.text }}view>
view>
view>
view>