uniapp 学习笔记三十四 加载用户地址列表和默认地址的在线数据修改
uniapp 学习笔记三十四 加载用户地址列表和默认地址的在线数据修改
order.vue
<template>
<view>
<view @click="handleAddress" class="padding flex align-center justify-between">
<view class="" v-if="orderAddress">
{{orderAddress.username}},{{orderAddress.phone}}
<view class="">
{{orderAddress.city}}
{{orderAddress.region}}
{{orderAddress.detail}}
</view>
</view>
<view class="" v-else>
请选择地址
</view>
<text class="cuIcon-right"></text>
</view>
<view class="padding">
配送时间
</view>
<view class="padding flex justify-between">
<view class="">
选择配送日期
</view>
<view class="">
选择配送时间
</view>
</view>
<view class="flex padding" v-for="(item,index) in 1">
<view class="flex align-center">
<!-- <text :class="['iconfont','icon-youxiajiaogouxuan','margin-right',{'yellow':item.isCheck}]"></text> -->
<image class="poster margin-right" :src="item.img" mode=""></image>
</view>
<view class="flex justify-between info">
<view class="">
<!-- {{item.name}} -->蛋糕
<view class="margin-tb-xs"> Fraction </view>
<!-- Y{{item.list[item.idx].price}} -->
</view>
<view class="flex flex-direction align-end">
<view class="edit margin-bottom-xs">
<text class="iconfont icon-bianjishuru"></text>
</view>
<!-- {{item.list[item.idx].spec}} -->
X
<!-- {{item.num}} -->
</view>
</view>
</view>
<view class="fixed padding flex justify-between align-center">
总计
<view class="">
199
</view>
<button class="cu-btn bg-brown">立即支付</button>
</view>
</view>
</template>
<script>
import {mapGetters} from 'vuex'
export default {
data() {
return {
};
},
computed:{
...mapGetters({
'orderAddress':'address/orderAddress'
})
},
methods:{
handleAddress(){
uni.navigateTo({
url:'../address/address'
})
}
}
}
</script>
<style lang="scss">
.poster{
width: 180upx;
height: 180upx;
background-color: #d8d8d8;
}
.info{
width: 60%;
.edit{
width: 80upx;
height: 80upx;
text-align: center;
line-height: 80upx;
background-color: #e6e6e6;
border-radius: 50%;
}
}
.flex.align-end{
min-width: 210upx;
}
.icon-youxiajiaogouxuan{
color: #e7e7e7;
}
.cu-btn.lg{
width: 50%;
}
.fixed {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
box-shadow: 0 0 10upx 2upx rgba(0, 0, 0, 0.2);
}
</style>
address.vue
<template>
<view>
<view
v-for="(item,index) in addressList"
class="margin-sm u-border padding"
:class="{'default':item.isdefault}"
>
<view class="default-cont">默</view>
<view class="flex justify-between">
<view class="flex align-center">
<text
class="iconfont icon-checkbox-xuanzhong margin-right"
:class="{'color-9898':checkedIdx==index||item.isdefault}"
@click="handleCheckAddress(index)"
></text>
<view class="">
{{item.username}},{{item.phone}}
<view class="">
{{item.city}}
{{item.region}}
{{item.detail}}
</view>
</view>
</view>
<view class="edit margin-bottom-sm">
<text class="iconfont icon-bianjishuru"></text>
</view>
</view>
<view class="flex justify-around align-center margin-top">
<view v-if="item.isdefault" class="">
默认地址
</view>
<view v-else class="" @click="handleDefault(index)">
设为默认
</view>
<u-line length="15" direction="col"></u-line>
<view class="">
删除地址
</view>
</view>
</view>
<view class="text-center">
<button @click="handleAddAddress" class="cu-btn bg-brown">新增地址</button>
</view>
</view>
</template>
<script>
import {mapState,mapMutations} from 'vuex'
export default {
data() {
return {
};
},
computed: {
...mapState({
addressList:state=>state.address.addressList,
checkedIdx:state=>state.address.checkedIdx,
userInfo:state=>state.user.userInfo
})
},
methods:{
...mapMutations({
'handleDefault':'address/addressDefaultMut',
'handleCheckAddress':'address/addressCheckMut'
}),
handleAddAddress(){
uni.navigateTo({
url:'address-detail'
})
},
handleDefault(idx){
let obj = {"requests":[]};
this.addressList.forEach((item,i)=>{
let bool = i===idx;
obj.requests.push({
"method":"PUT",
"path":`/1.1/classes/address/${item.objectId}`,
"body":{
"isdefault":bool
}
})
})
//批量操作在线数据
this.$post('/1.1/batch',obj).then(res=>{
this.$store.commit('address/addressDefaultMut',idx)
})
}
}
}
</script>
<style lang="scss">
.edit{
width: 80upx;
height: 80upx;
text-align: center;
line-height: 80upx;
background-color: #e6e6e6;
border-radius: 50%;
}
.cu-btn.lg{
width: 50%;
}
.fixed {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
box-shadow: 0 0 10upx 2upx rgba(0, 0, 0, 0.2);
}
.icon-checkbox-xuanzhong{
width: 50upx;
height: 50upx;
font-size: 50upx;
text-align: center;
line-height: 50upx;
color: #e6e6e6;
background-color: #e6e6e6;
border-radius: 20%;
}
.default{
position: relative;
overflow: hidden;
.default-cont{
padding: 20upx 10upx 10upx;
width: 100upx;
background-color: #fae456;
font-size: 12upx;
text-align: center;
position: absolute;
top: -20upx;
right: -40upx;
transform: rotate(45deg);
display: block;
}
}
.default-cont{
display: none;
}
</style>
address.js
import {$post,$get} from '@/utils/request.js'
export default{
namespaced:true,
state(){
return{
checkedIdx:-1, //记录用户勾选的地址
addressList:[
/* {
username:'曹国舅',
phone:'13010101010',
city:'北京',
region:'朝阳区',
detail:'朝阳路周家井',
isdefault:true
},{
username:'何仙姑',
phone:'13010101010',
city:'北京',
region:'海淀区',
detail:'中关村二街',
isdefault:false
},{
username:'吕洞宾',
phone:'13010101010',
city:'北京',
region:'门头沟',
detail:'黑山大街',
isdefault:false
} */
]
}
},
getters:{
orderAddress(state){ // 订单中的地址
// 根据 checkedIdx 与 isdefault 共同得到一个地址对象
let {checkedIdx,addressList} = state
if (checkedIdx!=-1) {
return addressList[checkedIdx]
}
let len = addressList.length
for(let i=0;i<len;i++){
if(addressList[i].isdefault){
return addressList[i]
}
}
}
},
mutations:{
addressDefaultMut(state,idx){ //设为默认
state.addressList.forEach((item,i)=>{
if(i==idx){
item.isdefault = true
}else{
item.isdefault = false
}
})
},
addressCheckMut(state,idx){
//选取地址
state.checkedIdx = idx
//点选返回
uni.navigateBack({
delta:1
})
},
addressAddMut(state,addressObj){
//新增地址
state.addressList.push(addressObj)
},
addressInitMut(state,addressArr){
//初始化地址列表
state.addressList = addressArr
}
},
actions:{
addressAddAct(context,addressObj){
$post('/1.1/classes/address',addressObj).then(({objectId})=>{
// console.log(res);
context.commit('addressAddMut',{
...addressObj,
objectId
})
uni.navigateBack({
delta:1
})
})
},
addressInitAct(context,userid){
let url = `/1.1/classes/address?where={"userid":"${userid}"}`
$get(url).then(({results})=>{
// console.log(url,res);
context.commit('addressInitMut',results)
})
}
}
}
APP.vue
<script>
export default {
onLaunch: function() {
console.log('App Launch')
//全局生命周期
try{
const value = uni.getStorageSync('userInfo');
if (value) {
console.log(value);
this.$store.commit('user/initInfo',value)
this.$store.dispatch('address/addressInitAct',value.objectId)
}
}catch(e){
//TODO handle the exception
console.log('提取用户信息失败');
}
},
onShow: function() {
console.log('App Show')
},
onHide: function() {
console.log('App Hide')
}
}
</script>
<style lang="scss">
/* 注意要写在第一行,同时给style标签加入lang="scss"属性 */
@import "@/uni_modules/uview-ui/index.scss";
/*每个页面公共css */
@import url("@/common/uni.css");
</style>
user.js
import {$post} from '../utils/request.js'
export default {
namespaced:true, //开启命名空间后,访问所有属性都需要带模块名
state(){
return {
userInfo:null
}
},
mutations:{
initInfo(state,info){
// 存入状态机变量
state.userInfo = info
}
},
actions:{
userLoginAct(context,info){
$post('/1.1/login',info).then(res=>{
console.log('PostUser:',res)
let {code} = res
if (code) {
let title = code == 211 ? '账号不存在' : '密码错误'
uni.showToast({
title,
icon:'none'
})
return
}
context.commit('initInfo',res)
// 存入本地存储
uni.setStorage({
key:'userInfo',
data:res
})
// 返回上一页
uni.navigateBack({
delta:1
})
})
}
}
}
address-detail.vue
<template>
<view>
<map class="map"></map>
<!-- 此处需要设置 manifest.json 中的地图key 需要到地图api供应商申请key 自行百度 -->
<form @submit="handleSubmit">
<view class="cu-form-group margin-top">
<view class="title">
<text class="cuIcon-friendfill"></text>
</view>
<input class="text-right" placeholder="请输入姓名" name="username"/>
</view>
<view class="cu-form-group">
<view class="title">
<text class="cuIcon-mobilefill"></text>
</view>
<input class="text-right" placeholder="请输入电话" name="phone"/>
</view>
<view class="cu-form-group">
<view class="title">
<text class="cuIcon-locationfill"></text>
</view>
<picker :range="regionArr" @change="handleRegion">
<view class="picker">
{{regionIdx==-1?'请选择区域':regionArr[regionIdx]}}
</view>
</picker>
</view>
<view class="cu-form-group">
<view class="title">
<text class="cuIcon-locationfill"></text>
</view>
<input class="text-right" placeholder="请输入详细地址" name="detail"/>
</view>
<view class="padding">
<button form-type="submit" class="cu-btn bg-brown block">确定</button>
</view>
</form>
</view>
</template>
<script>
import {mapState} from 'vuex'
export default {
data() {
return {
regionArr:[
'东城区',
'西城区',
'朝阳区',
'海淀区',
'石景山区',
'大兴区',
'通州区',
'顺义区',
'房山区'
],
regionIdx:-1
};
},
computed:{
...mapState({
userInfo:state=>state.user.userInfo
})
},
methods:{
handleRegion(ev){
console.log(ev);
let {value} = ev.detail;
this.regionIdx = value
},
handleSubmit(ev){
let {value} = ev.detail
let {regionArr,regionIdx} = this
value.city = '北京市'
value.region = regionArr[regionIdx]
value.isdefault = false
value.userid = this.userInfo.objectId
this.$store.dispatch('address/addressAddAct',value)
}
}
}
</script>
<style lang="scss">
.map{
height: 400upx;
width: 100%;
}
</style>