Commit aa22ef8339052cde1e85c40515cd591d516b7543

Authored by sfmind
1 parent f7d384e5

会员地址管理CRUD

yudao-ui-app/app.scss
1 /* 页面公共scss */ 1 /* 页面公共scss */
2 .container { 2 .container {
3 background-color: $custom-bg-color; 3 background-color: $custom-bg-color;
  4 + margin: 0;
  5 + padding: 0;
4 box-sizing: border-box; 6 box-sizing: border-box;
5 height: 100%; 7 height: 100%;
6 } 8 }
yudao-ui-app/pages.json
@@ -67,13 +67,13 @@ @@ -67,13 +67,13 @@
67 } 67 }
68 }, 68 },
69 { 69 {
70 - "path": "pages/address/add", 70 + "path": "pages/address/create",
71 "style": { 71 "style": {
72 "navigationBarTitleText": "新增地址" 72 "navigationBarTitleText": "新增地址"
73 } 73 }
74 }, 74 },
75 { 75 {
76 - "path": "pages/address/edit", 76 + "path": "pages/address/update",
77 "style": { 77 "style": {
78 "navigationBarTitleText": "修改地址" 78 "navigationBarTitleText": "修改地址"
79 } 79 }
yudao-ui-app/pages/address/add.vue deleted
1 -<template>  
2 - <view class="container"> </view>  
3 -</template>  
4 -  
5 -<script>  
6 -export default {  
7 - data() {  
8 - return {  
9 - title: ''  
10 - }  
11 - },  
12 - onLoad() {},  
13 - methods: {}  
14 -}  
15 -</script>  
16 -  
17 -<style lang="scss" scoped></style>  
yudao-ui-app/pages/address/create.vue 0 → 100644
  1 +<template>
  2 + <view class="container">
  3 + <view class="address-box">
  4 + <u--form labelPosition="left" :model="formData" :rules="rules" ref="form">
  5 + <u-form-item label="收件人名称" prop="name" labelWidth="90" borderBottom ref="item-name">
  6 + <u-input type="text" maxlength="11" v-model="formData.name" clearable placeholder="请填写收件人名称" border="none"></u-input>
  7 + </u-form-item>
  8 +
  9 + <u-form-item label="手机号" prop="mobile" labelWidth="90" borderBottom ref="item-mobile">
  10 + <u-input type="number" maxlength="11" v-model="formData.mobile" clearable placeholder="请填写手机号" border="none"></u-input>
  11 + </u-form-item>
  12 +
  13 + <u-form-item label="省市地区" prop="areaText" labelWidth="90" borderBottom @click=" regionVisible = true; hideKeyboard()" ref="item-areaText">
  14 + <u--input v-model="formData.areaText" disabled disabledColor="#ffffff" placeholder="请选择省市地区" border="none"></u--input>
  15 + <u-icon slot="right" name="arrow-right"></u-icon>
  16 + <w-picker :visible.sync="regionVisible" mode="region" :value="defaultRegion" default-type="value" :hide-area="false" @confirm="onConfirm($event, 'region')" @cancel="onCancel" ref="region"></w-picker>
  17 + </u-form-item>
  18 +
  19 + <u-form-item label="详细地址" prop="detail" labelWidth="90" borderBottom ref="item-detail">
  20 + <u--textarea placeholder="请输入街道门牌号不低于6个字" v-model="formData.detail" count></u--textarea>
  21 + </u-form-item>
  22 +
  23 + <u-form-item label="默认地址" prop="type" labelWidth="90" borderBottom ref="item-type">
  24 + <u-radio-group v-model="formData.type">
  25 + <u-radio :customStyle="{ marginRight: '16px' }" v-for="(item, index) in typeList" :key="index" :label="item.name" :name="item.value"></u-radio>
  26 + </u-radio-group>
  27 + </u-form-item>
  28 +
  29 + <view class="btn-group">
  30 + <u-button type="primary" text="保存地址" customStyle="margin-top: 50px" @click="handleSubmit"></u-button>
  31 + </view>
  32 + </u--form>
  33 + </view>
  34 + </view>
  35 +</template>
  36 +
  37 +<script>
  38 +import { createAddress } from '../../api/address'
  39 +
  40 +export default {
  41 + data() {
  42 + return {
  43 + regionVisible: false,
  44 + defaultRegion: ['110000', '110100', '110101'],
  45 + typeList: [
  46 + {
  47 + name: '是',
  48 + value: 1
  49 + },
  50 + {
  51 + name: '否',
  52 + value: 2
  53 + }
  54 + ],
  55 + formData: {
  56 + name: '',
  57 + mobile: '',
  58 + areaText: '',
  59 + areaCode: '',
  60 + detail: '',
  61 + detailAddress: '',
  62 + type: 1
  63 + },
  64 + rules: {
  65 + name: [
  66 + {
  67 + type: 'string',
  68 + min: 2,
  69 + max: 12,
  70 + required: true,
  71 + message: '请填写收件人名称',
  72 + trigger: ['blur', 'change']
  73 + },
  74 + {
  75 + message: '收件人名称不能为空',
  76 + // 触发器可以同时用blur和change
  77 + trigger: ['change', 'blur']
  78 + }
  79 + ],
  80 + mobile: [
  81 + {
  82 + type: 'integer',
  83 + required: true,
  84 + message: '请填写手机号',
  85 + trigger: ['blur', 'change']
  86 + },
  87 + {
  88 + // 自定义验证函数,见上说明
  89 + validator: (rule, value, callback) => {
  90 + // 上面有说,返回true表示校验通过,返回false表示不通过
  91 + // uni.$u.test.mobile()就是返回true或者false的
  92 + return uni.$u.test.mobile(value)
  93 + },
  94 + message: '手机号码不正确',
  95 + // 触发器可以同时用blur和change
  96 + trigger: ['change', 'blur']
  97 + }
  98 + ],
  99 + areaText: {
  100 + type: 'string',
  101 + required: true,
  102 + message: '请选择省市地区',
  103 + trigger: ['blur', 'change']
  104 + },
  105 + detailAddress: {
  106 + type: 'string',
  107 + min: 6,
  108 + max: 30,
  109 + required: true,
  110 + message: '请填写详细地址',
  111 + trigger: ['blur', 'change']
  112 + }
  113 + }
  114 + }
  115 + },
  116 + onLoad() {},
  117 + methods: {
  118 + onConfirm(res) {
  119 + this.formData.areaText = res.result
  120 + this.formData.areaCode = res.value[2]
  121 + },
  122 + onCancel() {},
  123 + hideKeyboard() {
  124 + uni.hideKeyboard()
  125 + },
  126 + handleSubmit() {
  127 + this.$refs.form.validate().then(res => {
  128 + this.formData.detailAddress = this.formData.areaText + this.formData.detail
  129 + console.log(this.formData)
  130 + createAddress(this.formData).then(res => {
  131 + uni.$u.toast('地址已保存')
  132 + setTimeout(() => {
  133 + uni.navigateBack()
  134 + }, 1000)
  135 + })
  136 + })
  137 + }
  138 + }
  139 +}
  140 +</script>
  141 +
  142 +<style lang="scss" scoped>
  143 +.address-box {
  144 + width: 690rpx;
  145 + margin: 0 auto;
  146 + padding-top: 30rpx;
  147 +}
  148 +</style>
yudao-ui-app/pages/address/edit.vue deleted
1 -<template>  
2 - <view class="container"> </view>  
3 -</template>  
4 -  
5 -<script>  
6 -export default {  
7 - data() {  
8 - return {  
9 - title: ''  
10 - }  
11 - },  
12 - onLoad() {},  
13 - methods: {}  
14 -}  
15 -</script>  
16 -  
17 -<style lang="scss" scoped></style>  
yudao-ui-app/pages/address/list.vue
1 <template> 1 <template>
2 - <view class="container"> </view> 2 + <view class="container">
  3 + <view class="address-list" v-for="(item, index) in addressList" :key="item.id">
  4 + <view class="address-item" @click="handleClick" @longpress="handleLongPress(item)">
  5 + <view class="left">
  6 + <u-avatar :text="item.name ? item.name.slice(0, 1) : 'U'" fontSize="18" randomBgColor></u-avatar>
  7 + </view>
  8 + <view class="middle">
  9 + <view class="info">
  10 + <view class="name">{{ item.name }}</view>
  11 + <view class="mobile">{{ item.mobile }}</view>
  12 + <u-tag class="type" v-if="item.type === 1" text="默认" plain size="mini" type="success"></u-tag>
  13 + </view>
  14 + <view class="detail">
  15 + <u--text :lines="2" size="14" color="#939393" :text="item.detailAddress"></u--text>
  16 + </view>
  17 + </view>
  18 + <navigator class="right" :url="`/pages/address/update?addressId=${item.id}`" open-type="navigate" hover-class="none">
  19 + <u-icon name="edit-pen" size="28"></u-icon>
  20 + </navigator>
  21 + </view>
  22 + </view>
  23 +
  24 + <navigator class="fixed-btn-box" url="/pages/address/create" open-type="navigate" hover-class="none">
  25 + <u-button type="primary" size="large" text="新增地址"></u-button>
  26 + </navigator>
  27 + <u-safe-bottom customStyle="background: #ffffff"></u-safe-bottom>
  28 + </view>
3 </template> 29 </template>
4 30
5 <script> 31 <script>
  32 +import { getAddressList, deleteAddress } from '../../api/address'
  33 +
6 export default { 34 export default {
7 data() { 35 data() {
8 return { 36 return {
9 - title: '' 37 + addressList: []
10 } 38 }
11 }, 39 },
12 onLoad() {}, 40 onLoad() {},
13 - methods: {} 41 + onShow() {
  42 + this.loadAddressListData()
  43 + },
  44 + methods: {
  45 + loadAddressListData() {
  46 + getAddressList().then(res => {
  47 + this.addressList = res.data
  48 + })
  49 + },
  50 + handleLongPress(item) {
  51 + uni.showModal({
  52 + title: '提示',
  53 + content: `删除收件人[${item.name}${item.mobile}]\n地址:${item.detailAddress.slice(0, 5)}......${item.detailAddress.slice(-6)}?`,
  54 + success: res => {
  55 + if (res.confirm) {
  56 + deleteAddress({ id: item.id }).then(res => {
  57 + uni.$u.toast('地址已删除')
  58 + this.loadAddressListData();
  59 + })
  60 + } else if (res.cancel) {
  61 + //console.log('用户点击取消')
  62 + }
  63 + }
  64 + })
  65 + },
  66 + handleClick(){
  67 + // TODO 提交订单时选择地址逻辑
  68 + }
  69 + }
14 } 70 }
15 </script> 71 </script>
16 72
17 -<style lang="scss" scoped></style> 73 +<style lang="scss" scoped>
  74 +.address-list {
  75 + .address-item {
  76 + padding: 10rpx 0;
  77 + border-bottom: $custom-border-style;
  78 + @include flex-space-between;
  79 + .left {
  80 + margin: 20rpx;
  81 + }
  82 + .middle {
  83 + flex: 1;
  84 + margin: 20rpx;
  85 + @include flex(column);
  86 + .info {
  87 + @include flex-left;
  88 + .name {
  89 + font-size: 30rpx;
  90 + font-weight: 700;
  91 + }
  92 + .mobile {
  93 + font-size: 28rpx;
  94 + margin-left: 15rpx;
  95 + }
  96 + .type {
  97 + margin-left: 15rpx;
  98 + }
  99 + }
  100 + .detail {
  101 + margin-top: 10rpx;
  102 + }
  103 + }
  104 + .right {
  105 + margin: 20rpx;
  106 + }
  107 + }
  108 +}
  109 +
  110 +.fixed-btn-box {
  111 + position: fixed;
  112 + bottom: 0;
  113 + left: 0;
  114 + width: 750rpx;
  115 +}
  116 +</style>
yudao-ui-app/pages/address/update.vue 0 → 100644
  1 +<template>
  2 + <view class="container">
  3 + <view class="address-box">
  4 + <u--form labelPosition="left" :model="formData" :rules="rules" ref="form">
  5 + <u-form-item label="收件人名称" prop="name" labelWidth="90" borderBottom ref="item-name">
  6 + <u-input type="text" maxlength="11" v-model="formData.name" clearable placeholder="请填写收件人名称" border="none"></u-input>
  7 + </u-form-item>
  8 +
  9 + <u-form-item label="手机号" prop="mobile" labelWidth="90" borderBottom ref="item-mobile">
  10 + <u-input type="number" maxlength="11" v-model="formData.mobile" clearable placeholder="请填写手机号" border="none"></u-input>
  11 + </u-form-item>
  12 +
  13 + <u-form-item label="省市地区" prop="areaText" labelWidth="90" borderBottom @click=" regionVisible = true; hideKeyboard()" ref="item-areaText">
  14 + <u--input v-model="formData.areaText" disabled disabledColor="#ffffff" placeholder="请选择省市地区" border="none"></u--input>
  15 + <u-icon slot="right" name="arrow-right"></u-icon>
  16 + <w-picker :visible.sync="regionVisible" mode="region" :value="defaultRegion" default-type="value" :hide-area="false" @confirm="onConfirm($event, 'region')" @cancel="onCancel" ref="region"></w-picker>
  17 + </u-form-item>
  18 +
  19 + <u-form-item label="详细地址" prop="detail" labelWidth="90" borderBottom ref="item-detail">
  20 + <u--textarea placeholder="请输入街道门牌号不低于6个字" v-model="formData.detail" count></u--textarea>
  21 + </u-form-item>
  22 +
  23 + <u-form-item label="默认地址" prop="type" labelWidth="90" borderBottom ref="item-type">
  24 + <u-radio-group v-model="formData.type">
  25 + <u-radio :customStyle="{ marginRight: '16px' }" v-for="(item, index) in typeList" :key="index" :label="item.name" :name="item.value"></u-radio>
  26 + </u-radio-group>
  27 + </u-form-item>
  28 +
  29 + <view class="btn-group">
  30 + <u-button type="primary" text="更新地址" customStyle="margin-top: 50px" @click="handleSubmit"></u-button>
  31 + </view>
  32 + </u--form>
  33 + </view>
  34 + </view>
  35 +</template>
  36 +
  37 +<script>
  38 +import { getAddressById, updateAddress } from '../../api/address'
  39 +
  40 +export default {
  41 + data() {
  42 + return {
  43 + id: '',
  44 + regionVisible: false,
  45 + defaultRegion: ['110000', '110100', '110101'],
  46 + typeList: [
  47 + {
  48 + name: '是',
  49 + value: 1
  50 + },
  51 + {
  52 + name: '否',
  53 + value: 2
  54 + }
  55 + ],
  56 + formData: {
  57 + id: '',
  58 + name: '',
  59 + mobile: '',
  60 + areaText: '',
  61 + areaCode: '',
  62 + detail: '',
  63 + detailAddress: '',
  64 + type: 1
  65 + },
  66 + rules: {
  67 + name: [
  68 + {
  69 + type: 'string',
  70 + min: 2,
  71 + max: 12,
  72 + required: true,
  73 + message: '请填写收件人名称',
  74 + trigger: ['blur', 'change']
  75 + },
  76 + {
  77 + message: '收件人名称不能为空',
  78 + // 触发器可以同时用blur和change
  79 + trigger: ['change', 'blur']
  80 + }
  81 + ],
  82 + mobile: [
  83 + {
  84 + type: 'integer',
  85 + required: true,
  86 + message: '请填写手机号',
  87 + trigger: ['blur', 'change']
  88 + },
  89 + {
  90 + // 自定义验证函数,见上说明
  91 + validator: (rule, value, callback) => {
  92 + // 上面有说,返回true表示校验通过,返回false表示不通过
  93 + // uni.$u.test.mobile()就是返回true或者false的
  94 + return uni.$u.test.mobile(value)
  95 + },
  96 + message: '手机号码不正确',
  97 + // 触发器可以同时用blur和change
  98 + trigger: ['change', 'blur']
  99 + }
  100 + ],
  101 + areaText: {
  102 + type: 'string',
  103 + required: true,
  104 + message: '请选择省市地区',
  105 + trigger: ['blur', 'change']
  106 + },
  107 + detailAddress: {
  108 + type: 'string',
  109 + min: 6,
  110 + max: 30,
  111 + required: true,
  112 + message: '请填写详细地址',
  113 + trigger: ['blur', 'change']
  114 + }
  115 + }
  116 + }
  117 + },
  118 + onLoad(e) {
  119 + if (!e.addressId) {
  120 + uni.$u.toast('请求参数错误')
  121 + } else {
  122 + this.id = e.addressId
  123 + this.loadAddressData()
  124 + }
  125 + },
  126 + methods: {
  127 + loadAddressData() {
  128 + getAddressById({ id: this.id }).then(res => {
  129 + this.formData = res.data
  130 + this.initRegionData()
  131 + })
  132 + },
  133 + initRegionData(){
  134 + //回显 【省市地区】 和 【详细地址】 信息
  135 + if (this.formData.areaCode) {
  136 + const areaCode = this.formData.areaCode + ''
  137 + //通过地区code反解析出【省-市-地区】code
  138 + this.defaultRegion.splice(0, 3, areaCode.substring(0,2).padEnd(6, '0'), areaCode.substring(0,4).padEnd(6, '0'), areaCode)
  139 + this.$nextTick(res => {
  140 + let areaText = this.$refs.region._data.result.result
  141 + this.formData.areaText = areaText
  142 + //通过从完整详细地址除去【省-市-地区】得到后半段地址信息
  143 + this.formData.detail = this.formData.detailAddress.replace(areaText, '')
  144 + this.$forceUpdate();
  145 + })
  146 + }
  147 + },
  148 + onConfirm(res) {
  149 + this.formData.areaText = res.result
  150 + this.formData.areaCode = res.value[2]
  151 + },
  152 + onCancel() {},
  153 + hideKeyboard() {
  154 + uni.hideKeyboard()
  155 + },
  156 + handleSubmit() {
  157 + this.$refs.form.validate().then(res => {
  158 + this.formData.detailAddress = this.formData.areaText + this.formData.detail
  159 + console.log(this.formData)
  160 + updateAddress(this.formData).then(res => {
  161 + uni.$u.toast('地址已更新')
  162 + setTimeout(() => {
  163 + uni.navigateBack()
  164 + }, 1000)
  165 + })
  166 + })
  167 + }
  168 + }
  169 +}
  170 +</script>
  171 +
  172 +<style lang="scss" scoped>
  173 +.address-box {
  174 + width: 690rpx;
  175 + margin: 0 auto;
  176 + padding-top: 30rpx;
  177 +}
  178 +</style>