Commit aa22ef8339052cde1e85c40515cd591d516b7543
1 parent
f7d384e5
会员地址管理CRUD
Showing
7 changed files
with
433 additions
and
40 deletions
yudao-ui-app/app.scss
yudao-ui-app/pages.json
| ... | ... | @@ -67,13 +67,13 @@ |
| 67 | 67 | } |
| 68 | 68 | }, |
| 69 | 69 | { |
| 70 | - "path": "pages/address/add", | |
| 70 | + "path": "pages/address/create", | |
| 71 | 71 | "style": { |
| 72 | 72 | "navigationBarTitleText": "新增地址" |
| 73 | 73 | } |
| 74 | 74 | }, |
| 75 | 75 | { |
| 76 | - "path": "pages/address/edit", | |
| 76 | + "path": "pages/address/update", | |
| 77 | 77 | "style": { |
| 78 | 78 | "navigationBarTitleText": "修改地址" |
| 79 | 79 | } | ... | ... |
yudao-ui-app/pages/address/add.vue deleted
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
yudao-ui-app/pages/address/list.vue
| 1 | 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 | 29 | </template> |
| 4 | 30 | |
| 5 | 31 | <script> |
| 32 | +import { getAddressList, deleteAddress } from '../../api/address' | |
| 33 | + | |
| 6 | 34 | export default { |
| 7 | 35 | data() { |
| 8 | 36 | return { |
| 9 | - title: '' | |
| 37 | + addressList: [] | |
| 10 | 38 | } |
| 11 | 39 | }, |
| 12 | 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 | 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> | ... | ... |