ChainForm.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. <template><page-meta :root-font-size="fontSize+'px'"></page-meta>
  2. <member-base :show="false"><view class="div container member-chain-form">
  3. <view class="div common-header-wrap">
  4. <view :style="'height:'+navHeight+'px'"></view>
  5. <view class="common-header-holder"></view>
  6. <view class="common-header-fixed">
  7. <title-header />
  8. <uni-nav-bar :title="getTitle" class="common-header" left-icon="back" @clickLeft="goBack">
  9. </uni-nav-bar>
  10. </view>
  11. </view>
  12. <view class="div main-content">
  13. <flex-line class="field-line" :show-border="true"><text class="span field-name">姓名</text><view class="div field-line-right" slot="right"><input class="field-input" v-model="address_info.address_realname" /></view></flex-line>
  14. <flex-line class="field-line" :show-border="true"><text class="span field-name">手机</text><view class="div field-line-right" slot="right"><input class="field-input" v-model="address_info.address_mob_phone" /></view></flex-line>
  15. <flex-line :is-link="true" :show-border="true">
  16. <text class="span">地区</text>
  17. <view class="div" @click="onRegion" slot="right">
  18. <text class="span" v-if="address_info.area_info">{{address_info.area_info}}</text>
  19. <text class="span" v-else>请选择地区</text>
  20. </view>
  21. </flex-line>
  22. <flex-line :is-link="true" :show-border="true">
  23. <text class="span">代收点</text>
  24. <view class="div" @click="showPopup('showChain')" slot="right">
  25. <text class="span" v-if="address_info.address_detail">{{address_info.address_detail}}</text>
  26. <text class="span" v-else>请选择代收点</text>
  27. </view>
  28. </flex-line>
  29. <flex-line :show-border="true"><text class="span line-name">默认地址</text><view class="div" slot="right"><switch @change="switchChange" :checked="!!address_info.address_is_default"></switch></view></flex-line>
  30. <view class="div pt-10 pb-10"><view class="div common-btn ds-button-large" @click="submit">{{getSumitTitle}}</view></view>
  31. </view>
  32. <region-picker ref="picker" v-on:onConfirm="onPickerConfirm"></region-picker>
  33. <uni-popup background-color="#fff" ref="showChain" type="right" >
  34. <view :style="'width:'+screenWidth+'px'" class="scroll-view-wrapper common-popup-wrapper">
  35. <view class="div common-header-wrap">
  36. <view :style="'height:'+navHeight+'px'"></view>
  37. <view class="common-header-holder"></view>
  38. <view class="common-header-fixed">
  39. <title-header />
  40. <uni-nav-bar title="代收点列表" class="common-header" left-icon="back" @clickLeft="hidePopup('showChain')">
  41. </uni-nav-bar>
  42. </view>
  43. </view>
  44. <view class="scroll-view-wrapper scroll-view div common-popup-content">
  45. <scroll-view style="position: absolute;top:0;right:0;left:0;bottom:0" class="scroll-view div" @scrolltolower="loadMore" scroll-y="true">
  46. <view class="div" v-if="chainList && chainList.length">
  47. <view class="div top-wrapper" v-for="(item,index) in chainList" :key="index" @click="setChain(item)">
  48. <view class="div title-wrapper">
  49. <label class="title">{{ item.chain_addressname }}</label>
  50. <label class="title">{{ item.chain_mobile }}<text class="span" v-if="item.chain_telephony">{{ item.chain_telephony }}</text></label>
  51. </view>
  52. <label class="desc address-text">{{item.chain_area_info}}&nbsp;{{item.chain_address}}</label>
  53. <view class="div bottom-line"></view>
  54. </view>
  55. </view>
  56. <empty-record v-else-if="chainList && !chainList.length"></empty-record>
  57. </scroll-view>
  58. </view>
  59. </view>
  60. </uni-popup>
  61. </view></member-base>
  62. </template>
  63. <script>
  64. import {getFontSize} from '@/util/common'
  65. import TitleHeader from '../../TitleHeader'
  66. import MemberBase from '../MemberBase'
  67. import { getPointByAddress } from '../../../util/bmap'
  68. import RegionPicker from '../../RegionPicker'
  69. import EmptyRecord from '../../EmptyRecord'
  70. import { getAddressInfo, addChain, getChainList } from '../../../api/memberAddress'
  71. import flexLine from '../../flexLine'
  72. export default {
  73. components:{
  74. TitleHeader,
  75. MemberBase,
  76. flexLine,
  77. RegionPicker,
  78. EmptyRecord
  79. },
  80. computed:{
  81. fontSize(){
  82. return getFontSize()
  83. },
  84. isAddMode () {
  85. let mode = this.action
  86. // add: 添加地址,edit: 编辑地址
  87. if (mode === 'add') {
  88. return true
  89. } else {
  90. return false
  91. }
  92. },
  93. getTitle () {
  94. if (this.isAddMode) {
  95. return '新增地址'
  96. } else {
  97. return '修改收货地址'
  98. }
  99. },
  100. getSumitTitle () {
  101. let isFromCheckout = this.isFromCheckout
  102. if (isFromCheckout) {
  103. return '保存并使用'
  104. } else {
  105. return '保存'
  106. }
  107. }
  108. },
  109. data(){
  110. return {
  111. navHeight: 0,
  112. isFromCheckout:0,
  113. action:'',
  114. screenWidth:0,
  115. chainList: [],
  116. params: { 'page': 0, 'per_page': 10 },
  117. loading: false, // 是否加载更多
  118. isMore: true, // 是否有更多
  119. popMap: false,
  120. address_id: 0,
  121. address_info: {
  122. address_is_default: true
  123. }
  124. }
  125. },
  126. onLoad: function (option) {
  127. this.action=option.action
  128. this.isFromCheckout=option.isFromCheckout
  129. if (!this.isAddMode) {
  130. this.address_id = option.address_id
  131. getAddressInfo(this.address_id).then(res => {
  132. this.address_info = res.result.address_info
  133. if (res.result.address_info.address_is_default === '1') {
  134. this.address_info.address_is_default = true
  135. } else {
  136. this.address_info.address_is_default = false
  137. }
  138. }).catch(function (error) {
  139. uni.showToast({icon:'none',title: error.message})
  140. })
  141. }
  142. this.loadMore()
  143. },
  144. mounted(){
  145. // #ifdef MP-WEIXIN
  146. this.navHeight = uni.getMenuButtonBoundingClientRect().top
  147. // #endif
  148. this.screenWidth=uni.getSystemInfoSync().screenWidth
  149. },
  150. methods:{
  151. switchChange(e){
  152. this.address_info.address_is_default=e.detail.value
  153. },
  154. showPopup(id){
  155. this.$refs[id].open()
  156. },
  157. hidePopup(id){
  158. this.$refs[id].close()
  159. },
  160. loadMore () {
  161. if (this.loading) {
  162. return
  163. }
  164. this.params.page = ++this.params.page
  165. if (this.isMore) {
  166. this.loading = true
  167. this.getChainList(true)
  168. }
  169. },
  170. reload () {
  171. // 重新加载数据
  172. this.params.page = 0
  173. this.isMore = true
  174. this.chainList = false
  175. this.loadMore()
  176. },
  177. getChainList () {
  178. getChainList(this.params, this.address_info.area_id).then(res => {
  179. if (res.result.hasmore) {
  180. this.isMore = true
  181. } else {
  182. this.isMore = false
  183. }
  184. if (this.chainList) {
  185. this.chainList = this.chainList.concat(res.result.chain_list)
  186. } else {
  187. this.chainList = res.result.chain_list
  188. }
  189. this.loading = false
  190. }).catch(function (error) {
  191. uni.hideLoading()
  192. uni.showToast({icon:'none',title: error.message})
  193. this.loading = false
  194. })
  195. },
  196. setChain (item) {
  197. this.address_info.chain_id = item.chain_id
  198. this.address_info.address_detail = item.chain_address
  199. this.hidePopup('showChain')
  200. this.$forceUpdate()
  201. },
  202. goBack () {
  203. uni.navigateBack({delta:1})
  204. },
  205. getPosition () {
  206. getPointByAddress(this.address_info.area_info + this.address_info.address_detail).then(res => {
  207. if (res.result.location) {
  208. this.address_info.address_longitude = res.result.location.lng
  209. this.address_info.address_latitude = res.result.location.lat
  210. }
  211. }).catch(function (error) {
  212. uni.showToast({icon:'none',title: error.message})
  213. })
  214. },
  215. setPosition (lat, lng, name) {
  216. this.popMap = false
  217. this.address_info.address_detail = name
  218. this.address_info.address_longitude = lng
  219. this.address_info.address_latitude = lat
  220. },
  221. submit () {
  222. if (this.address_info.address_realname === '') {
  223. uni.showToast({icon:'none',title: '请填写收件人姓名'})
  224. return
  225. }
  226. if (this.address_info.address_realname.length === 0) {
  227. uni.showToast({icon:'none',title: '请填写收件人姓名'})
  228. return
  229. }
  230. if (this.address_info.address_realname.length < 2 || this.address_info.address_realname.length > 15) {
  231. uni.showToast({icon:'none',title: '2-15个字符限制'})
  232. return
  233. }
  234. if (this.address_info.address_mob_phone === '') {
  235. uni.showToast({icon:'none',title: '请填写手机号码'})
  236. return
  237. }
  238. if (this.address_info.address_mob_phone.length === 0) {
  239. uni.showToast({icon:'none',title: '请填写手机号码'})
  240. return
  241. }
  242. if (this.address_info.area_id === 0 || this.address_info.area_id === undefined) {
  243. uni.showToast({icon:'none',title: '请选择所在地区'})
  244. return
  245. }
  246. if (this.address_info.chain_id === 0 || this.address_info.chain_id === undefined) {
  247. uni.showToast({icon:'none',title: '请选择代收点'})
  248. return
  249. }
  250. addChain(this.address_info).then(
  251. (response) => {
  252. uni.hideLoading()
  253. this.updateSelectedAddress()
  254. }, (error) => {
  255. uni.hideLoading()
  256. uni.showToast({icon:'none',title: error.message})
  257. })
  258. },
  259. onRegion (picker, values) {
  260. this.$refs.picker.show()
  261. },
  262. onPickerConfirm (values) {
  263. if (this.address_info.area_id != values[2].area_id) {
  264. this.address_info.chain_id = 0
  265. this.address_info.address_detail = ''
  266. }
  267. this.address_info.area_info = this.getRegionStr(values)
  268. this.address_info.area_id = values[2].area_id
  269. this.address_info.city_id = values[1].area_id
  270. this.reload()
  271. this.$forceUpdate()
  272. },
  273. getRegionStr (values) {
  274. let title = ''
  275. for (let i = 0; i < values.length; i++) {
  276. const element = values[i]
  277. if (i !== 0) {
  278. title = title + ' ' + element.area_name
  279. } else {
  280. title = title + element.area_name
  281. }
  282. }
  283. return title
  284. },
  285. updateSelectedAddress () {
  286. uni.navigateBack({delta:1})
  287. }
  288. }
  289. }
  290. </script>
  291. <style lang="scss">
  292. .member-chain-form .address-line-wrapper .mint-cell-title{flex:unset;width: 5rem}
  293. .member-chain-form .address-line-wrapper .mint-cell-value{flex:1;text-align: right; display: block;}
  294. </style>
  295. <style lang="scss" scoped>
  296. .scroll-view-wrapper{display: flex;flex-direction: column;}
  297. .scroll-view{flex:1}
  298. .main-content{background: #fff;padding:0 $pageSpace}
  299. .right-arrow{transform: rotate(-90deg);color:#ddd;font-size:$fontSize;display: inline-block;}
  300. .input-wrap{position: relative;
  301. .i{position: absolute;right:0;top:0;line-height: 2.4rem;display: block;width:2rem;text-align: center;font-size:$h1}
  302. }
  303. .top-wrapper {
  304. position: relative;
  305. flex: 1;
  306. display: flex;
  307. flex-direction: column;
  308. justify-content: flex-start;
  309. align-items: stretch;
  310. }
  311. .top-wrapper .title-wrapper {
  312. height:1rem;
  313. display: flex;
  314. flex-direction: row;
  315. justify-content: flex-start;
  316. align-items: center;
  317. margin-top:0.5rem;
  318. margin-left:0.5rem;
  319. }
  320. .top-wrapper .title {
  321. font-size:$h2;
  322. color: #333;
  323. margin-left:0.5rem;
  324. }
  325. .top-wrapper .desc {
  326. color: #7c7f88;
  327. font-size:$subFontSize;
  328. }
  329. .top-wrapper .address-text {
  330. margin-top:0.5rem;
  331. margin-bottom:0.5rem;
  332. margin-left:1rem;
  333. margin-right:0.5rem;
  334. }
  335. .top-wrapper .bottom-line {
  336. position: absolute;
  337. height: 1px;
  338. left:0.5rem;
  339. bottom: 0;
  340. right:0.5rem;
  341. background-color: #e8eaed;
  342. }
  343. .address-line{display: inline-block;max-width: 50%;overflow: hidden;text-overflow: ellipsis;white-space: nowrap}
  344. </style>