Browse Source

增加收货地址管理

Administrator 7 years ago
parent
commit
05941c970f

+ 247 - 0
components/mobile/base/addressEdit.vue

@@ -0,0 +1,247 @@
+<template>
+  <div class="shipments_address_edit">
+    <div class="form_line" ref="addressContent">
+      <ul class="list-unstyled" >
+        <li>
+          <div class="com_left pull-left"><span>*</span>发货人姓名:</div>
+          <div class="form_input">
+            <input type="text" placeholder="请输入您的姓名" v-model="params.name" maxlength="10">
+          </div>
+        </li>
+        <li>
+          <div class="com_left pull-left"><span>*</span>联系电话:</div>
+          <div class="form_input">
+            <input type="tel" placeholder="请输入您的联系电话" v-model="params.tel" maxlength="11">
+          </div>
+        </li>
+        <li>
+          <div class="com_left pull-left">邮箱:</div>
+          <div class="form_input">
+            <input type="email" placeholder="请输入正确邮箱,用于接收订单提醒" v-model="params.email">
+          </div>
+        </li>
+        <li>
+          <div class="com_left pull-left"><span>*</span>所在地区:</div>
+          <div class="form_input" @click="addressShow = true">
+            <span v-text="params.area || '选择地区'">选择地区</span>
+          </div>
+        </li>
+        <li>
+          <div class="com_left pull-left"><span>*</span>详细地址:</div>
+          <div class="form_input">
+            <input type="text" placeholder="请您填写详细地址,街道名、门牌号等" v-model="params.detailAddress" maxlength="30">
+          </div>
+        </li>
+        <li>
+          <div class="com_left pull-left"><span>*</span>默认地址:</div>
+          <div class="form_input">
+            <el-switch
+              v-model="isActive"
+              on-text="ON"
+              off-text="OFF">
+            </el-switch>
+          </div>
+        </li>
+      </ul>
+    </div>
+    <div class="control clearfix">
+      <div class="cancel" @click="storeInfosave('cancel')">取消</div>
+      <div class="save" @click="storeInfosave()">保存</div>
+    </div>
+    <select-address :isShow="addressShow" @closeAction="addressData"></select-address>
+    <remind-box :title="collectResult" :timeoutCount="timeoutCount"></remind-box>
+    <div v-if="storeI && false"></div>
+  </div>
+</template>
+
+<script>
+  import BScroll from 'better-scroll'
+  import { RemindBox } from '~components/mobile/common'
+  import SelectAddress from './SelectAddress.vue'
+  export default {
+    name: 'AddressEditView',
+    props: {
+      data: {
+        type: Object,
+        default: {}
+      },
+      isSend: {
+        default: true,
+        type: Boolean
+      },
+      isPersonal: {
+        default: true,
+        type: Boolean
+      }
+    },
+    data() {
+      return {
+        params: {
+          area: '',
+          detailAddress: '',
+          email: '',
+          tel: '',
+          name: '',
+          province: '',
+          city: '',
+          district: ''
+        },
+        isActive: false,
+        addressShow: false,
+        timeoutCount: 0,
+        collectResult: ''
+      }
+    },
+    methods: {
+      editClick () {
+        this.$store.dispatch('mobileAddress/loadAddressData', {count: 10, page: 1, isSend: this.isSend, sorting: { 'num': 'ASC' }})
+        this.$emit('isEditEvent', [], false)
+      },
+      addressData (type) {
+        this.addressShow = false
+        if (type) {
+          this.params.area = `${type.province},${type.city},${type.area}`
+          this.params.province = type.province
+          this.params.city = type.city
+          this.params.district = type.area
+        }
+      },
+      setRemindText (str) {
+        this.collectResult = str
+        this.timeoutCount++
+      },
+      storeInfosave(_tp) {
+        this.BScroll.refresh()
+        if (_tp === 'cancel') {
+          this.editClick()
+          return false
+        }
+        if (!this.params.name || this.params.name === '') {
+          this.setRemindText('发货人姓名不能为空')
+          return false
+        }
+        if (!this.params.tel || this.params.tel === '' || !/^1[3|4|5|6|7|8|9][0-9]{9}$/.test(this.params.tel)) {
+          this.setRemindText('请输入正确的手机号码')
+          return false
+        }
+        if (this.params.email && !/^([a-zA-Z0-9_.-])+@(([a-zA-Z0-9-])+.)+([a-zA-Z0-9]{2,4})+$/.test(this.params.email)) {
+          this.setRemindText('请输入正确的邮箱')
+          return false
+        }
+        if (!this.params.area || this.params.area === '') {
+          this.setRemindText('请选择所在地区')
+          return false
+        }
+        if (!this.params.detailAddress || this.params.detailAddress === '') {
+          this.setRemindText('请填写详细地址信息')
+          return false
+        }
+        this.$http.post(`/trade/address/shipping/save?isPersonal=${this.isPersonal}&isSetTop=${this.isActive}&send=${this.isSend}`, this.params)
+          .then(() => {
+            this.setRemindText('保存成功')
+            this.editClick()
+          }).catch(err => {
+            this.collectResult = err.response.data
+            this.timeoutCount++
+            this.params = this.data
+          })
+      }
+    },
+    computed: {
+      storeI() {
+        let str = JSON.stringify(this.$store.state.option.storeStatus.data)
+        this.storeInfo = JSON.parse(str)
+        return ''
+      },
+      isAdmin () {
+        return this.user.data.userUU === this.user.data.enterprise.enAdminuu
+      }
+    },
+    components: {
+      RemindBox,
+      SelectAddress
+    },
+    mounted() {
+      this.$nextTick(() => {
+        if (this.data) {
+          this.params = this.baseUtils.deepCopy(this.data)
+        }
+        if (this.BScroll) {
+          this.BScroll.refresh()
+        } else {
+          this.BScroll = new BScroll(this.$refs.addressContent, {
+            click: true
+          })
+        }
+      })
+    }
+  }
+</script>
+
+<style lang="scss" scoped>
+  .shipments_address_edit{
+    .control {
+      width: 90%;
+      margin: 0.4rem auto 0rem;
+      height: .88rem;
+      line-height: 0.88rem;
+      .save {
+        border-radius: 3px;
+        width: 48%;
+        color: #fff;
+        text-align: center;
+        height: .88rem;
+        line-height: 0.88rem;
+        background: #3e82f5;
+        float: right;
+      }
+      .cancel {
+        border-radius: 3px;
+        width: 48%;
+        background: #acabab;
+        color: #fff;
+        text-align: center;
+        height: .88rem;
+        line-height: 0.88rem;
+        float: left;
+      }
+    }
+    .form_line{
+      margin:.2rem;
+      padding:.2rem;
+      background: #ffffff;
+      border-radius:.05rem;
+      ul{
+        li{
+          line-height: 1.2rem;
+          height:1.2rem;
+          border-bottom:1px solid #d3d3d3;
+          vertical-align: middle;
+          &:last-child{
+            border:none;
+          }
+          .com_left{
+            width:1.85rem;
+            color:#4c8cf7;
+            text-align: right;
+            font-size: .28rem;
+            span{
+              color:#ff3333;
+            }
+          }
+          .form_input{
+            margin-left:1.85rem;
+            padding-right:.2rem;
+            input{
+              width:100%;
+              line-height: .3rem;
+              height:.3rem;
+              border:none;
+              font-size: .28rem;
+            }
+          }
+        }
+      }
+    }
+  }
+</style>

+ 266 - 0
components/mobile/base/addressView.vue

@@ -0,0 +1,266 @@
+<template>
+  <div class="address_info">
+    <div class="add_rule">
+      <a @click="editClick()"><i class="iconfont icon-add"></i>{{isSend ? '新增发货地址' : '新增收货地址'}}</a>
+    </div>
+    <div class="deleteKuang" v-if="showLogout">
+      <div class="kuangContent">
+        <div class="title">系统提示</div>
+        <div class="titleinfo">是否删除?</div>
+        <div class="K_btn">
+          <div class="cancelBtn" @click="showLogout = false">取消</div>
+          <div class="answerBtn" @click="goNext">确定</div>
+        </div>
+      </div>
+    </div>
+    <ul class="list-unstyled">
+      <li v-for="(item, index) in listInfo.content">
+        <div class="wrapper-line">
+          <div class="name pull-left">{{isSend ? '发货地址:' : '收货地址:'}}</div>
+          <div class="name-text">{{item.area}}{{item.detailAddress}}</div>
+        </div>
+        <div class="wrapper-line">
+          <div class="name pull-left">{{isSend ? '发货人:' : '收货人:'}}</div>
+          <div class="name-text">{{item.name}}</div>
+        </div>
+        <div class="wrapper-line">
+          <div class="name pull-left">电话:</div>
+          <div class="name-text">{{item.tel}}</div>
+        </div>
+        <div class="item-bottom clearfix">
+          <div class="pull-left" >
+            <label class="bottom-modal-check mobile-cart-check" :class="{active: item.num === 1}">
+              <input type="checkbox" @change="setActiveClick(item.id)">
+              <span>默认地址</span>
+            </label>
+          </div>
+          <div class="pull-right" >
+            <span @click="editClick(item)"><i class="iconfont icon-edit"></i>修改</span>
+            <span @click="deleteClick(item.id, index)"><i class="iconfont icon-lajitong"></i>删除</span>
+          </div>
+        </div>
+      </li>
+    </ul>
+
+    <!--<pull-up :fixId="'logistics-content'"-->
+    <!--:searchMore="isSearchSearchingMore"-->
+    <!--:allPage="allPage"-->
+    <!--:page="param.page"-->
+    <!--@pullUpAction="getMoreSearch"></pull-up>-->
+  </div>
+</template>
+
+<script type="text/javascript">
+  import { PullUp } from '~components/mobile/common'
+  export default {
+    name: 'AddressInfoView',
+    props: {
+      isSend: {
+        default: true,
+        type: Boolean
+      }
+    },
+    data() {
+      return {
+        showLogout: false,
+        // 保存操作数据的序号
+        saveId: {
+          id: '',
+          active: 0
+        },
+        param: {
+          count: 10,
+          page: 1,
+          sorting: { 'num': 'asc' }
+        }
+      }
+    },
+    methods: {
+      // 设置默认地址
+      setActiveClick (type) {
+        this.$http.put(`/trade/address/settop/${type}`).then(() => {
+          this.$store.dispatch('mobileAddress/loadAddressData', {count: 10, page: 1, isSend: this.isSend, sorting: { 'num': 'ASC' }})
+        })
+      },
+      // 删除事件
+      deleteClick (type, index) {
+        this.saveId.id = type
+        this.saveId.active = index
+        this.showLogout = true
+      },
+      goNext () {
+        this.$http.put(`/trade/address/delete/${this.saveId.id}`)
+          .then(() => {
+            this.$store.dispatch('mobileAddress/loadAddressData', {count: 10, page: 1, isSend: this.isSend, sorting: { 'num': 'ASC' }})
+            this.showLogout = false
+          })
+      },
+      // 编辑事件
+      editClick (type) {
+        this.$emit('isEditEvent', type || {}, true)
+      },
+      // 加载更多
+      getMoreSearch() {}
+    },
+    computed: {
+      listInfo() {
+        let list = this.baseUtils.deepCopy(this.$store.state.mobileAddress.address.data)
+        list.content = list.content.sort((a, b) => { return a.num - b.num })
+        return list
+      },
+      allPage() {
+        return this.listInfo.totalElements
+      }
+    },
+    components: {
+      PullUp
+    }
+  }
+</script>
+
+<style lang="scss" scoped>
+  @mixin overFlowHidden {
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+  }
+  @mixin lineHeight($value) {
+    height: $value;
+    line-height: $value;
+  }
+  .deleteKuang {
+    position: fixed;
+    background: rgba(0,0,0,0.5);
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    z-index: 9999;
+    .kuangContent {
+      border-radius: 5px;
+      background: #fff;
+      width: 5rem;
+      position: absolute;
+      left: 50%;
+      top: 50%;
+      transform: translate3d(-50%, -50%, 0);
+      overflow: hidden;
+      .titleinfo {
+        font-size: .3rem;
+        color: #666;
+        text-align: center;
+        margin-top: 0.5rem;
+        margin-bottom: 0.1rem;
+      }
+      .title {
+        background: #5078cb;
+        height: .7rem;
+        line-height: .7rem;
+        font-size: .3rem;
+        color: #fff;
+        text-align: center;
+      }
+      .info {
+        color: #f00;
+        text-align: center;
+      }
+      .K_btn {
+        margin-top: 0.4rem;
+        line-height: 0.7rem;
+        height: 0.7rem;
+        &::after{
+          clear: both;
+          display: block;
+          content: ' ';
+          visibility: hidden;
+          zoom: 1;
+        }
+        div {
+          float: left;
+          width: 50%;
+          font-size: 0.3rem;
+          text-align: center;
+          &.cancelBtn {
+            background: #b4b5b9;
+            color: #333;
+          }
+          &.answerBtn {
+            background: #5078cb;
+            color: #fff;
+          }
+        }
+      }
+    }
+  }
+  .add_rule{
+    position:absolute;
+    bottom:.2rem;
+    left:0;
+    right:0;
+    a{
+      display:block;
+      margin: 0 auto;
+      width:95%;
+      height:.78rem;
+      line-height: .78rem;
+      text-align: center;
+      font-size: .32rem;
+      color:#fff;
+      background: #3f84f6;
+      border-radius:.05rem;
+      i{
+        margin-right:.05rem;
+      }
+    }
+  }
+  .address_info{
+    padding:.2rem .2rem 1.2rem;
+    ul {
+      li {
+        margin-bottom: 0.2rem;
+        padding: 0.3rem 0.24rem 0;
+        border: 1px solid #e4e6e9;
+        border-radius: 5px;
+        background: #fefefe;
+        .wrapper-line {
+          margin-bottom: 0.16rem;
+          .name{
+            display:inline-block;
+            text-align: right;
+            width:1.5rem;
+          }
+          .name-text {
+            margin-left:1.5rem;
+            word-break: break-all;
+            word-wrap: break-word;
+            font-size: 0.28rem;
+            color: #333;
+          }
+        }
+        .item-bottom {
+          color: #333;
+          @include lineHeight(0.8rem);
+          font-size: 0.26rem;
+          text-align: center;
+          border-top: 1px solid #d3d3d3;
+          .pull-left {
+            text-align: left;
+          }
+          .pull-right {
+            width: 50%;
+            text-align: right;
+          }
+          span{
+            font-size: 0.28rem;
+            margin-right:.2rem;
+            i {
+              font-size: 0.34rem;
+              vertical-align: middle;
+            }
+          }
+
+        }
+      }
+    }
+  }
+</style>

+ 3 - 1
components/mobile/base/index.js

@@ -4,5 +4,7 @@ import LinkUser from './LinkUser.vue'
 import ModalWrapper from './ModalWrapper.vue'
 import BottomModalWrapper from './BottomModalWrapper.vue'
 import SelectAddress from './SelectAddress.vue'
+import AddressView from './addressView.vue'
+import AddressEdit from './addressEdit'
 
-export { SearchHeader, SearchHeader2, LinkUser, ModalWrapper, BottomModalWrapper, SelectAddress }
+export { SearchHeader, SearchHeader2, LinkUser, ModalWrapper, BottomModalWrapper, SelectAddress, AddressView, AddressEdit }

+ 157 - 0
pages/mobile/user/address.vue

@@ -0,0 +1,157 @@
+<template>
+  <div class="mobile-fix-content user-info">
+    <div class="info">
+      <div class="line">
+        <input type="file"
+               class="file-input"
+               name="name"
+               accept="image/jpeg,image/jpg,image/gif,image/bmp,image/png"
+               @change="uploadImg"/>
+        <span><i class="iconfont icon-tuxiang-" style="font-size: .29rem;"></i>头像:</span>
+        <span class="describe"><img :src="imageUploadUrl ? imageUploadUrl : info.imageUrl ? info.imageUrl : '/images/component/default.png'" alt="">
+          <i class="iconfont icon-xiangyou"></i></span>
+      </div>
+      <div class="line">
+        <span><i class="iconfont icon-yonghuming"></i>用户名:</span>
+        <span class="describe">{{info.userName}}</span>
+      </div>
+      <div class="line" @click="jumpSet('email')">
+        <span><i class="iconfont icon-youxiang"></i>邮箱:</span>
+        <span class="describe">{{info.userEmail}}
+        <i class="iconfont icon-xiangyou"></i>
+        </span>
+      </div>
+      <div class="line" @click="jumpSet('mobile')">
+        <span><i class="iconfont icon-shouji"></i>手机:</span>
+        <span class="describe">{{info.userTel}}
+        <i class="iconfont icon-xiangyou"></i>
+        </span>
+      </div>
+    </div>
+  </div>
+</template>
+<script>
+  export default {
+    props: {
+      info: {
+        default: {},
+        type: Object
+      }
+    },
+    data () {
+      return {
+        imageUploadUrl: ''
+      }
+    },
+    mounted: function () {
+      this.$nextTick(() => {
+        if (!this.$store.state.option.user.logged) {
+          this.$router.push('/auth/login?returnUrl=' + window.location.href)
+        }
+      })
+    },
+    computed: {
+      getEmail () {
+        return this.$store.state.user.updateUser.email.data.content
+      },
+      getMobile () {
+        return this.$store.state.user.updateUser.mobile.data.content
+      }
+    },
+    methods: {
+      uploadImg (e) {
+        let file = e.target.files[0]
+        if (file) {
+          let param = new FormData()
+          param.append('image', file, file.name)
+          let config = {
+            headers: {'Content-Type': 'multipart/form-data'}
+          }
+          this.$http.post('/api/images', param, config)
+            .then(response => {
+              if (response.data) {
+                let imageUrl = response.data[0].path
+                this.$http.post('/basic/user/setImageUrl', {imageUrl: imageUrl})
+                  .then(response => {
+                    if (response.data) {
+                      this.imageUploadUrl = response.data.imageUrl
+                      this.$store.dispatch('loadUserInfo')
+                    }
+                  })
+              }
+            })
+        }
+      },
+      jumpSet (info) {
+        if (info === 'email') {
+          window.location.href = decodeURIComponent(this.getEmail)
+        } else if (info === 'mobile') {
+          window.location.href = decodeURIComponent(this.getMobile)
+        }
+      }
+    }
+  }
+</script>
+<style lang="scss">
+  .mobile-fix-content {
+    background: #f1f3f6;
+  }
+  .user-info {
+    .info {
+      width: 7.1rem;
+      background: #fff;
+      margin: 0 auto;
+      height: 4.66rem;
+      padding: 0 .24rem;
+      font-size: .28rem;
+      color: #999;
+      border-radius: .05rem;
+      margin-top: .3rem;
+      .line {
+        position: relative;
+        overflow: hidden;
+        text-overflow: ellipsis;
+        white-space: nowrap;
+        height: 1.16rem;
+        line-height: 1.16rem;
+        border-bottom: .01rem solid #d9d9d9;
+        &:last-child {
+          border-bottom: none;
+        }
+        input{
+          position: absolute;
+          top: 0;
+          left: 0;
+          height: 1.16rem;
+          width: 100%;
+          opacity: 0;
+        }
+        span{
+          display: inline-block;
+          font-size: 0.28rem;
+          color: #226ce7;
+          text-align: left;
+          i{
+            margin-right: .15rem;
+            font-size: .3rem;
+            color: #f8953c;
+          }
+        }
+        span.describe {
+          float: right;
+          color: #333;
+          i{
+            margin: 0 0 0 .1rem;
+            font-size: .24rem;
+            color: #bebebe;
+          }
+          img{
+            width: .58rem;
+            height: .58rem;
+            /*border: 1px solid #bebebe;*/
+          }
+        }
+      }
+    }
+  }
+</style>

+ 2 - 1
plugins/element-ui.js

@@ -1,5 +1,5 @@
 import Vue from 'vue'
-import { Message, Breadcrumb, BreadcrumbItem, Tree, Pagination, Upload, Dialog, DatePicker } from 'element-ui'
+import { Message, Breadcrumb, BreadcrumbItem, Tree, Pagination, Upload, Dialog, DatePicker, Switch } from 'element-ui'
 
 Vue.use(Breadcrumb)
 Vue.use(BreadcrumbItem)
@@ -8,5 +8,6 @@ Vue.use(Pagination)
 Vue.use(Upload)
 Vue.use(Dialog)
 Vue.use(DatePicker)
+Vue.use(Switch)
 
 Vue.prototype.$message = Message

+ 43 - 0
store/mobileAddress.js

@@ -0,0 +1,43 @@
+import axios from '~plugins/axios'
+/**
+ * 发 收货地址管理数据
+ */
+export const state = () => ({
+  // 收发货切换
+  send: true,
+  // 地址数据
+  address: {
+    fetching: false,
+    data: []
+  }
+})
+
+export const mutations = {
+  SET_SEND (state, result) {
+    state.send = result || true
+  },
+  REQUEST_ADDRESS (state) {
+    state.address.fetching = true
+  },
+  REQUEST_ADDRESS_SUCCESS (state, result) {
+    state.address.fetching = false
+    state.address.data = result
+  },
+  REQUEST_ADDRESS_FAILURE (state) {
+    state.address.fetching = false
+  }
+}
+
+export const actions = {
+  // 获取地址数据
+  loadAddressData ({ commit }, params = {}) {
+    commit('REQUEST_ADDRESS')
+    return axios.get('/trade/address/page', params)
+      .then(response => {
+        commit('REQUEST_ADDRESS_SUCCESS', response.data)
+      }, err => {
+        commit('REQUEST_ADDRESS_FAILURE', err)
+      })
+  }
+}
+