任务三 工单1
本工单主要目的需要完成效果图:
1、当用户点击首页板块中自取区域,由于用户亲自到店拿取,小程序直接跳转到点餐配送页面选取饮品,同时在/store/index.js中改变orderType状态。通过uni.switchTab()跳转到tabBar中“点餐页面”。点击自取交互代码如下:
takein() {//点击自取
//通过SET_ORDER_TYPE方法设置orderType 为自取
this.$store.commit('SET_ORDER_TYPE', 'takein')
uni.switchTab({
url: '/pages/menu/menu'
})
}
2、当用户点击首页板块中的外卖区域时,系统会通过/store/index.js中的getters来获取isLogin状态。
如果用户未登录,则会被重定向至login.vue登录界面,以进行登录授权并获取用户信息,随后将这些信息存储在/store/index.js的member中。如果用户已经登录,则会直接跳转至“我的地址”界面。以下是外卖交互的代码示例:
takeout() {//点击外卖
if(!this.isLogin) {//判断是否登录
uni.navigateTo({url: '/pages/login/login'})//跳转登录页面
return
}
uni.navigateTo({
url: "/pages/address/address" //进入我的地址页面
})
}
在pages文件夹中创建一个新的address.vue页面,并在pages.json文件里对address页面的样式进行配置。
★3、完成“我的地址”页面布局,利用/api/addresses.js获取的用户配送地址信息来完善布局。通过检查addresses数组的长度来判断用户是否拥有地址信息。


uni-swipe-action-item组件包含两个参数,其效果对应图3.1.5
:right-options="swipeOption"//右侧可滑动,swipeOption为设置参数对象
@click="handleSwipeClick(address.id)"//click事件为滑动出区域的交互

点击任一uni-swipe-action-item,即可选择配送地址,并将其存储在全局管理文件store中的address对象里;触发滑动显示的删除按钮,将删除已添加的地址,具体效果见图3.1.6。代码示例如下:
...
...
methods:{
...mapMutations(['SET_ADDRESS', 'SET_ADDRESSES', 'SET_ORDER_TYPE']),
chooseAddress(address) {
this.SET_ADDRESS(address) //添加派送的地址
this.SET_ORDER_TYPE('takeout') //设置状态,自取还是外卖
uni.switchTab({
url: '/pages/menu/menu'
})
},
handleSwipeClick(id) { //删除按钮点击
uni.showModal({
title: '提示',
content: '确定要删除?',
success: res => {
if (res.confirm) {
const index = this.addresses.findIndex(item => item.id == id)//流式处理,通过比较id在addresses找到选择中的一个
const addresses = JSON.parse(JSON.stringify(this.addresses))//json格式转对象
addresses.splice(index, 1) //切分,删除
this.SET_ADDRESSES(addresses)//重置addresses
uni.showToast({
title: '删除成功!',
icon: 'success'
})
}
}
})
}
}

到此为止,详细代码如下:
address.vue代码
<template>
<!-- 我的地址 -->
<view class="container">
<view class="main">
<!-- 用户无地址 画面 -->
<view v-if="!addresses.length" class="no-address-tips">
<view class="mb-30">暂无地址信息</view>
<view>请点击底部按钮添加地址信息</view>
</view>
<!-- 用户有地址 画面 -->
<template v-else>
<!-- 地址列表 -->
<uni-swipe-action>
<uni-swipe-action-item class="address-wrapper" :right-options="swipeOption"
@click="handleSwipeClick(address.id)" v-for="(address, index) in addresses" :key="index">
<view class="address" @tap="chooseAddress(address)">
<view class="left flex-fill overflow-hidden mr-20">
<view class="font-size-lg font-weight-bold text-truncate" style="margin-bottom: 10rpx;">
{{ address.street }}
</view>
<view class="font-size-sm text-color-assist">
{{ address.accept_name }} {{ !address.sex? '先生' : '女士' }} {{ address.mobile }}
</view>
</view>
<image src="/static/images/edit.png" class="edit-icon"></image>
</view>
</uni-swipe-action-item>
</uni-swipe-action>
</template>
</view>
<!-- 新增地址按钮 -->
<view class="btn-box">
<button type="primary" size="default">新增地址</button>
</view>
</view>
</template>
<script>
import {
mapState,mapMutations
} from 'vuex'
export default {
data() {
return {
swipeOption: [{
text: '删除',
style: {
backgroundColor: '#D12E32'
}
}]
};
},
computed: {
...mapState(['addresses'])//获取addresses数据
},
methods:{
...mapMutations(['SET_ADDRESS', 'SET_ADDRESSES', 'SET_ORDER_TYPE']),
chooseAddress(address) {
this.SET_ADDRESS(address) //添加派送的地址
this.SET_ORDER_TYPE('takeout') //设置状态,自取还是外卖
uni.switchTab({
url: '/pages/menu/menu'
})
},
handleSwipeClick(id) { //删除按钮点击
uni.showModal({
title: '提示',
content: '确定要删除?',
success: res => {
if (res.confirm) {
const index = this.addresses.findIndex(item => item.id == id)//流式处理,通过比较id在addresses找到选择中的一个
const addresses = JSON.parse(JSON.stringify(this.addresses))//json格式转对象
addresses.splice(index, 1) //切分,删除
this.SET_ADDRESSES(addresses)//重置addresses
uni.showToast({
title: '删除成功!',
icon: 'success'
})
}
}
})
},
}
}
</script>
<style lang="scss" scoped>
.container {
width: 100%;
height: 100%;
}
.main {
width: 100%;
padding: 30rpx;
display: flex;
flex-direction: column;
padding-bottom: 100rpx;
.no-address-tips {
text-align: center;
margin-top: 100rpx;
}
.address-wrapper {
margin-bottom: 30rpx;
}
.address {
width: 100%;
padding: 40rpx 30rpx;
background-color: #FFFFFF;
display: flex;
justify-content: space-between;
align-items: center;
.right {
flex: 1;
overflow: hidden;
display: flex;
flex-direction: column;
}
.edit-icon {
width: 50rpx;
height: 50rpx;
flex-shrink: 0;
}
}
}
.btn-box {
height: 100rpx;
background-color: #FFFFFF;
box-shadow: 0 0 20rpx rgba($color: $text-color-assist, $alpha: 0.1);
position: fixed;
bottom: 0;
left: 0;
right: 0;
padding: 10rpx 0;
display: flex;
align-items: center;
justify-content: center;
button {
height: 80rpx;
width: 80%;
border-radius: 50rem !important;
display: flex;
align-items: center;
justify-content: center;
}
}
</style>
★4、点击下方新增地址按钮,即可跳转至“新增地址”界面。在该界面中,新建add.vue页面,并对pages.json文件中的style属性进行调整,以完成页面布局。布局效果如图3.1.8所示。为了简化布局过程,引入了自定义控件/components/list-cell/list-cell,如图3.1.7所示。通过data数据中的form对象,可以装载list-cell绑定的各项数据(包括收货人姓名、性别、联系方式、收货人地址、门牌号等)。
在填写完毕后,点击保存按钮,数据将通过store全局管理文件中的SET_ADDRESSES方法存储到用户地址信息中,并返回至前一页面。


请注意,若用户未填写收货人姓名、联系方式、地址、门牌号等必要信息,应使用uni.showToast进行交互提示,告知用户缺少哪些信息。如图3.1.9所示

到此为止涉及跳转代码如下:
address.vue
<!-- 新增地址按钮 -->
<view class="btn-box">
<button type="primary" size="default" @tap="add">新增地址</button>
</view>
add() {//新增地址
uni.navigateTo({
url: '/pages/address/add'
})
},
add.vue 新增地址页面
<template>
<view class="container">
<view class="form-box">
<view class="form">
<list-cell :hover="false">
<view class="form-input">
<view class="label">收货人</view>
<input class="input" placeholder="请输入收货人" v-model="form.accept_name"
placeholder-class="text-color-assist" />
</view>
</list-cell>
<list-cell :hover="false">
<view class="form-input">
<view class="label">性别</view>
<view class="radio-group">
<view class="radio" :class="{'checked': !form.sex}" style="margin-right: 10rpx;"
@tap="form.sex=0">先生</view>
<view class="radio" :class="{'checked': form.sex}" @tap="form.sex=1">女士</view>
</view>
</view>
</list-cell>
<list-cell :hover="false">
<view class="form-input">
<view class="label">联系方式</view>
<input class="input" placeholder="请输入收货人联系方式" v-model="form.mobile"
placeholder-class="text-color-assist" type="number" />
</view>
</list-cell>
<list-cell :hover="false">
<view class="form-input">
<view class="label">收货地址</view>
<input class="input" placeholder="请选择收货地址" v-model="form.street"
placeholder-class="text-color-assist" />
</view>
</list-cell>
<list-cell :hover="false">
<view class="form-input">
<view class="label">门牌号</view>
<input class="input" placeholder="请输入收货人详细地址" v-model="form.door_number"
placeholder-class="text-color-assist" />
</view>
</list-cell>
</view>
<view class="btn-section">
<button type="primary" size="default" @tap="save">保存</button>
</view>
</view>
</view>
</template>
<script>
import listCell from '@/components/list-cell/list-cell'
import {mapState,mapMutations} from 'vuex'
export default {
components: {
listCell
},
data() {
return {
form: {
accept_name: '',
sex: 0,
mobile: '',
street: '',
door_number: ''
}
}
},
computed: {
...mapState(['addresses'])
},
methods: {
...mapMutations(['SET_ADDRESSES']),
save() {//新增地址
if (!this.form.accept_name) {
uni.showToast({
title: '请输入收货人',
icon:'none'
});
return
}
if (!this.form.mobile) {
uni.showToast({
title: '请输入联系方式',
icon:'none'
});
return
}
if (!this.form.street) {
uni.showToast({
title: '请输入收货人收货地址',
icon:'none'
});
return
}
if (!this.form.door_number) {
uni.showToast({
title: '请输入收货人详细地址',
icon:'none'
});
return
}
this.form.id = this.addresses.length//加入一个对象的id
this.addresses.push(this.form)//加到数组中
this.SET_ADDRESSES(this.addresses)
uni.navigateBack()
}
}
}
</script>
<style lang="scss" scoped>
.form-box {
width: 100%;
height: 100%;
padding: 30rpx;
display: flex;
flex-direction: column;
color: $text-color-base;
.form-input {
display: flex;
align-items: center;
width: 100%;
}
.label {
width: 200rpx;
font-size: $font-size-lg;
color: $text-color-base;
font-weight: 500;
}
.input {
flex: 1;
display: flex;
align-items: center;
}
.radio-group {
display: flex;
justify-content: flex-start;
.radio {
padding: 10rpx 30rpx;
border-radius: 6rpx;
border: 2rpx solid $text-color-assist;
color: $text-color-assist;
font-size: $font-size-base;
&.checked {
background-color: $color-primary;
color: $text-color-white;
border: 2rpx solid $color-primary;
}
}
}
.btn-section {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
button {
font-size: $font-size-base;
height: 90rpx;
border-radius: 50rem !important;
width: 85%;
display: flex;
align-items: center;
justify-content: center;
}
}
}
</style>
网友评论