address-create.vue 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. <template>
  2. <view class="address-create">
  3. <tui-skeleton v-if="isRequest" :loadingType="3" :isLoading="true"></tui-skeleton>
  4. <view class="form-control">
  5. <label for="shouHuoRen">收货人姓名</label>
  6. <input
  7. class="input"
  8. type="text"
  9. id="shouHuoRen"
  10. placeholder="请输入收货人姓名"
  11. placeholder-class="placeholder"
  12. v-model="formData.shouHuoRen"
  13. maxlength="20"
  14. />
  15. </view>
  16. <tui-divider :height="dividerHeight"></tui-divider>
  17. <view class="form-control">
  18. <label for="mobile">联系方式</label>
  19. <input
  20. class="input"
  21. type="text"
  22. id="mobile"
  23. v-model="formData.mobile"
  24. placeholder="请输入联系方式"
  25. placeholder-class="placeholder"
  26. maxlength="20"
  27. />
  28. </view>
  29. <tui-divider :height="dividerHeight"></tui-divider>
  30. <view class="form-control">
  31. <label for="name">收货地址</label>
  32. <uni-data-picker
  33. v-model="formData.townId"
  34. :localdata="cityData"
  35. popup-title="请选地区"
  36. :map="{ text: 'name', value: 'id' }"
  37. class="input picker"
  38. ></uni-data-picker>
  39. </view>
  40. <tui-divider :height="dividerHeight"></tui-divider>
  41. <view class="form-control">
  42. <textarea
  43. class="input"
  44. v-model="formData.address"
  45. placeholder="详细地址:如道路、门牌号、小区、楼房号、单元室等"
  46. placeholder-class="placeholder"
  47. maxlength="100"
  48. />
  49. </view>
  50. <tui-divider :height="dividerHeight"></tui-divider>
  51. <!-- 默认地址 -->
  52. <view class="set-default">
  53. <text>设为默认地址</text>
  54. <switch :checked="isDefault" color="#f83c6c" class="switch" @change="switchChange" />
  55. </view>
  56. <view class="confirm">
  57. <tui-button type="base" :size="28" width="650rpx" height="88rpx" shape="circle" @click="submit">
  58. 保存
  59. </tui-button>
  60. </view>
  61. </view>
  62. </template>
  63. <script>
  64. import { fetchCityList } from '@/services/api/common.js'
  65. import { saveAddress } from '@/services/api/user.js'
  66. import { validation } from '@/components/common/tui-validation/tui-validation.min.js'
  67. import { objAssign } from '@/common/utils.js'
  68. import { mapGetters } from 'vuex'
  69. export default {
  70. data() {
  71. return {
  72. type: 'add',
  73. isRequest: true,
  74. dividerHeight: 40,
  75. isDefault: false,
  76. cityData: [],
  77. pickerValue: '',
  78. // 表单数据
  79. formData: {
  80. addressId: '', // 当前地址id
  81. userId: '', // 用户id
  82. shouHuoRen: '', //收货人
  83. townId: '', //区ID
  84. address: '', //地址
  85. mobile: '', //手机
  86. defaultFlag: 0 //是否默认收货地址(0 不是默认,1 默认)
  87. },
  88. // 表单验证规则
  89. rules: [
  90. { name: 'userId', rule: ['required'], msg: ['用户ID不能为空'] },
  91. { name: 'shouHuoRen', rule: ['required'], msg: ['收货人姓名不能为空'] },
  92. { name: 'townId', rule: ['required'], msg: ['收货地址不能为空'] },
  93. { name: 'address', rule: ['required'], msg: ['详细地址不能为空'] },
  94. { name: 'mobile', rule: ['required'], msg: ['联系方式不能为空'] }
  95. ]
  96. }
  97. },
  98. computed: {
  99. ...mapGetters(['userId'])
  100. },
  101. onLoad(options) {
  102. this.type = options.type
  103. this.formData.userId = this.userId
  104. this.fetchCityList()
  105. if (this.type === 'edit') {
  106. this.initFormData()
  107. }
  108. },
  109. beforeDestroy() {
  110. uni.removeStorageSync('eidtAddress')
  111. },
  112. methods: {
  113. // 初始化表单数据
  114. initFormData() {
  115. const address = uni.getStorageSync('eidtAddress')
  116. objAssign(this.formData, address)
  117. this.formData.townId = address.townId + 'T'
  118. this.formData.defaultFlag = parseInt(address.defaultFlag)
  119. this.isDefault = Boolean(this.formData.defaultFlag)
  120. },
  121. // 默认状态修改
  122. switchChange(e) {
  123. this.isDefault = e.target.value
  124. this.formData.defaultFlag = Number(this.isDefault)
  125. },
  126. // 提交保存
  127. async submit() {
  128. console.log(this.formData)
  129. const valide = validation(this.formData, this.rules)
  130. if (valide) {
  131. return this.$toast.error(valide)
  132. }
  133. try {
  134. const params = { ...this.formData, townId: parseInt(this.formData.townId) }
  135. const res = await saveAddress(params)
  136. this.$toast.success('已保存该收货地址')
  137. if (this.type === 'choose') {
  138. this.$router.addRefreshType('chooseAddress')
  139. uni.setStorageSync('CHOOSE_ADDRESS', res.data)
  140. setTimeout(() => this.$router.navigateBack(), 1000)
  141. } else {
  142. this.$router.addRefreshType('createAddressBack')
  143. setTimeout(() => this.$router.navigateBack(), 1000)
  144. }
  145. } catch (e) {
  146. console.log(e)
  147. }
  148. },
  149. // 获取城市列表
  150. async fetchCityList() {
  151. try {
  152. const res = await fetchCityList()
  153. this.cityData = this.formatCityList(res.data)
  154. console.log(this.cityData)
  155. } catch (e) {
  156. console.log(e)
  157. } finally {
  158. this.isRequest = false
  159. }
  160. },
  161. // 处理城市列表k-v
  162. formatCityList(list = []) {
  163. const result = []
  164. // 判断是否非空数组
  165. function notEmptyArr(arr) {
  166. return arr && arr instanceof Array && arr.length > 0
  167. }
  168. list.forEach(item => {
  169. const obj = {}
  170. // obj.id = item.townId || item.cityId || item.provinceId
  171. if (item.townId) {
  172. obj.id = item.townId + 'T'
  173. } else if (item.cityId) {
  174. obj.id = item.cityId + 'C'
  175. } else {
  176. obj.id = item.provinceId + 'P'
  177. }
  178. obj.name = item.name
  179. let children = []
  180. if (notEmptyArr(item.cityList)) {
  181. children = item.cityList
  182. }
  183. if (notEmptyArr(item.townList)) {
  184. children = item.townList
  185. }
  186. if (children.length > 0) {
  187. obj.children = this.formatCityList(children)
  188. }
  189. result.push(obj)
  190. })
  191. return result
  192. }
  193. }
  194. }
  195. </script>
  196. <style scoped>
  197. .form-control >>> .input-value-border {
  198. border: 0;
  199. }
  200. .form-control >>> .selected-item-active,
  201. .form-control >>> .check {
  202. border-color: #f83c6c;
  203. }
  204. .picker >>> .input-value,
  205. .picker >>> .selected-list {
  206. padding: 0 !important;
  207. }
  208. </style>
  209. <style lang="scss" scoped>
  210. .address-create {
  211. height: 100vh;
  212. padding: 0 24rpx;
  213. padding-top: 24rpx;
  214. background-color: #fff;
  215. box-sizing: border-box;
  216. color: #333;
  217. .form-control {
  218. @extend .cm-flex-between;
  219. // padding: 24rpx 0;
  220. font-size: 28rpx;
  221. label {
  222. width: 160rpx;
  223. }
  224. .input {
  225. flex: 1;
  226. }
  227. .picker {
  228. max-width: 564rpx;
  229. }
  230. }
  231. .set-default {
  232. @extend .cm-flex-between;
  233. justify-content: flex-start;
  234. text {
  235. font-size: 28rpx;
  236. }
  237. .switch {
  238. transform: scale(0.6);
  239. }
  240. }
  241. .confirm {
  242. @extend .cm-flex-center;
  243. margin-top: 80rpx;
  244. }
  245. }
  246. </style>