您的位置:首页 > Web前端 > Vue.js

Django+Vue开发生鲜电商平台之9.个人中心功能开发

2020-07-30 21:04 811 查看

文章目录

  • 三、用户收藏功能完成
  • 四、用户留言功能实现
  • 五、用户收货地址功能开发
  • 一个人想要成功,想要改变命运,有梦想是重要的。……我觉得每个人都应该心中有梦,有胸怀祖国的大志向,找到自己的梦想,认准了就去做,不跟风不动摇。同时,我们不仅仅要自己有梦想,你还应该用自己的梦想去感染和影响别人,因为成功者一定是用自己的梦想去点燃别人的梦想,是时刻播种梦想的人。
    ——李彦宏

    Github和Gitee代码同步更新
    https://github.com/PythonWebProject/Django_Fresh_Ecommerce
    https://gitee.com/Python_Web_Project/Django_Fresh_Ecommerce

    一、DRF的API文档自动生成和功能开发

    现在已经定义了很多接口,为了可以更清晰地了解每个接口的功能和相关使用说明,现在实现API文档生成。

    DRF自动实现了API文档生成,之前在urls.py这已经定义过文档路由为

    url(r'docs/', include_docs_urls(title='生鲜电商')),
    ,进行访问测试如下:

    可以看到,文档均已自动生成,并且可以进行测试,生成了JS等代码可以直接提供给前端进行测试。

    如果报错

    AttributeError: ‘AutoSchema’ object has no attribute ‘get_link’
    需要在settings.py中加入配置:

    # DRF配置
    REST_FRAMEWORK = {
    ...
    'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.AutoSchema',
    ...
    }

    其中,API文档说明是在创建视图时定义的,如定义用户收藏视图如下:

    class UserFavViewSet(mixins.CreateModelMixin, mixins.ListModelMixin, mixins.RetrieveModelMixin, mixins.DestroyModelMixin, viewsets.GenericViewSet):
    '''
    list:
    用户收藏列表
    create:
    创建用户收藏
    retrieve:
    用户收藏详情
    destroy:
    删除用户收藏
    '''
    permission_classes = [IsAuthenticated, IsOwnerOrReadOnly]
    serializer_class = UserFavSerializer
    authentication_classes = [JSONWebTokenAuthentication, SessionAuthentication]
    lookup_field = 'goods_id'
    
    def get_queryset(self):
    return UserFav.objects.filter(user=self.request.user, is_delete=False)

    在注释中可以看到,对于每种类型的请求,都以固定的格式定义了说明;
    并且如果在定义模型、序列化和过滤器时给字段指定了

    help_text
    属性,在文档中会显示Description。

    文档不用手动更新,在后端代码逻辑实现之后就会自动更新,并且提供了Shell、JavaScript和Python等多种测试代码方式。
    并且还提供了权限验证,对于需要验证后才能访问的接口,必须先进行验证,然后才能进行测试,演示如下:

    显然,只有有相关权限才能成功访问,只有存在数据,才会返回数据。

    DRF框架为生成OpenAPI模式提供了内置支持,可以与允许构建API文档的工具一起使用。还有许多出色的第三方文档包。

    二、用户个人信息修改功能实现

    1.通过权限和序列化动态设置获取用户信息

    在个人中心中可以修改姓名、出生日期、性别和电子邮件地址等,在修改之前,需要显示用户信息,所以需要定义获取用户信息的接口,并且需要进行权限验证,apps/users/views.py完善如下:

    class UserViewSet(CreateModelMixin, RetrieveModelMixin, viewsets.GenericViewSet):
    '''
    用户
    create:
    新增用户
    '''
    
    serializer_class = UserRegSerializer
    queryset = User.objects.filter(is_delete=False)
    authentication_classes = [SessionAuthentication, JSONWebTokenAuthentication]
    
    def get_permissions(self):
    '''动态设置权限'''
    if self.action == 'retrieve':
    return [IsAuthenticated]
    elif self.action == 'create':
    return []
    return []
    
    def get_serializer_class(self):
    '''动态设置序列化'''
    if self.action == 'retrieve':
    return UserDetailSerializer
    elif self.action == 'create':
    return UserRegSerializer
    return UserDetailSerializer
    
    def create(self, request, *args, **kwargs):
    serializer = self.get_serializer(data=request.data)
    serializer.is_valid(raise_exception=True)
    user = self.perform_create(serializer)
    re_dict = serializer.data
    payload = jwt_payload_handler(user)
    re_dict['token'] = jwt_encode_handler(payload)
    re_dict['name'] = user.name if user.name else user.username
    headers = self.get_success_headers(re_dict)
    return Response(re_dict, status=status.HTTP_201_CREATED, headers=headers)
    
    def perform_create(self, serializer):
    return serializer.save()
    
    def get_object(self):
    return self.request.user

    apps/users/serializers.py定义序列化如下:

    class UserDetailSerializer(serializers.ModelSerializer):
    '''用户详情序列化'''
    class Meta:
    model = User
    fields = ['name', 'gender', 'birthday', 'email', 'mobile']

    可以看到,这里的权限验证与一般的权限验证又有不同:
    在用户注册时,因为用户还没有账号,会执行

    create(request, *args, **kwargs)
    perform_create(serializer)
    方法,因此这些方法应该对所有用户开放,不进行全年验证;
    而在用户注册之后,修改用户信息需要先获取用户信息,此时执行
    get_object()
    方法,因此需要对该方法进行权限验证。
    所以不能采用原来的权限验证方法,即
    permission_classes = [IsAuthenticated]
    ,而是需要动态设置权限,即重写
    get_permissions()
    方法;除此之外,因为之前定义的用户序列化是针对用户注册功能的,而此时需要获取用户信息,包括name、gender、birthday、email等,与之前用户序列化的username、code、mobile、password等字段有区别,因此需要重新定义一个序列化类UserDetailSerializer,并且对于用户注册和获取信息,UserViewSet也需要实现动态设置序列化,即重写
    get_serializer_class()
    方法。

    演示如下:

    显然,只有当用户成功登录后,才能访问到信息。

    2.Vue接口实现用户信息显示

    在前端,组件为src/views/member/userinfo.vue,如下:

    created () {
    this.getUserInfo();
    },
    
    getUserInfo () { //请求用户信息
    getUserDetail().then((response)=> {
    this.userInfo = response.data;
    }).catch(function (error) {
    console.log(error);
    });
    },

    调用了

    getUserInfo
    接口,在api.js中修改如下:

    //获取用户信息
    export const getUserDetail = () => { return axios.get(`${local_host}/users/1/`) }

    示意如下:

    显然,已经可以同步获取信息。

    3.用户资料修改实现

    要实现修改用户信息,只需要使UserViewSet继承自UpdateModelMixin即可,如下:

    class UserViewSet(CreateModelMixin, UpdateModelMixin, RetrieveModelMixin, viewsets.GenericViewSet):
    '''
    用户
    create:
    新增用户
    update:
    修改用户
    partial_update:
    部分修改
    retrieve:
    用户详情
    '''
    
    serializer_class = UserRegSerializer
    queryset = User.objects.filter(is_delete=False)
    authentication_classes = [SessionAuthentication, JSONWebTokenAuthentication]

    userinfo.vue如下:

    <button class="btn_blue_1" style="border:none;" @click="confirmModify">确认修改</button>
    
    confirmModify () { // 确认修改
    updateUserInfo(this.userInfo).then((response)=> {
    alert('修改成功');
    }).catch(function (error) {
    console.log(error);
    });
    }

    调用了updateUserInfo接口,api.js中修改如下:

    //修改用户信息
    export const updateUserInfo = params => { return axios.patch(`${local_host}/users/1/`, params) }

    先查询当前用户数据如下:

    +----+--------------------------------------------------------------------------------+----------------------------+--------------+----------+------------+-----------+----------+-----------+----------------------------+--------+------------+--------+-------------+-------------+-----------+
    | id | password                                                                       | last_login                 | is_superuser | username | first_name | last_name | is_staff | is_active | date_joined                | name   | birthday   | gender | mobile      | email       | is_delete |
    +----+--------------------------------------------------------------------------------+----------------------------+--------------+----------+------------+-----------+----------+-----------+----------------------------+--------+------------+--------+-------------+-------------+-----------+
    |  1 | pbkdf2_sha256$180000$wpfCm77Dcpee$rHfFjBNZ2SzLLHdd0ZtbiIRqNB86VvgwTJv6ZCXTbfk= | 2020-07-30 16:12:00.000000 |            1 | admin    | Corley     | XXX       |        1 |         1 | 2020-07-20 10:12:00.000000 | Corley | 2020-07-15 | female | 13311111111 | 123@123.com |         0 |
    +----+--------------------------------------------------------------------------------+----------------------------+--------------+----------+------------+-----------+----------+-----------+----------------------------+--------+------------+--------+-------------+-------------+-----------+
    1 row in set (0.01 sec)

    此时修改数据演示如下:

    显然,刷新页面,数据已经修改,再查询数据据库,如下:

    +----+--------------------------------------------------------------------------------+----------------------------+--------------+----------+------------+-----------+----------+-----------+----------------------------+---------+------------+--------+-------------+-------------+-----------+
    | id | password                                                                       | last_login                 | is_superuser | username | first_name | last_name | is_staff | is_active | date_joined                | name    | birthday   | gender | mobile      | email       | is_delete |
    +----+--------------------------------------------------------------------------------+----------------------------+--------------+----------+------------+-----------+----------+-----------+----------------------------+---------+------------+--------+-------------+-------------+-----------+
    |  1 | pbkdf2_sha256$180000$wpfCm77Dcpee$rHfFjBNZ2SzLLHdd0ZtbiIRqNB86VvgwTJv6ZCXTbfk= | 2020-07-30 16:12:00.000000 |            1 | admin    | Corley     | XXX       |        1 |         1 | 2020-07-20 10:12:00.000000 | Corley2 | 2020-07-30 | male   | 13311111111 | 124@123.com |         0 |
    +----+--------------------------------------------------------------------------------+----------------------------+--------------+----------+------------+-----------+----------+-----------+----------------------------+---------+------------+--------+-------------+-------------+-----------+
    1 row in set (0.00 sec)

    也印证了数据已经被修改。

    说明
    之前在前端测试时,发现用户登录后5分钟左右后登录状态就失效,需要重新登录才能正常访问,我就很郁闷了,明明已经设置JWT过期时间为7天了,怎么没效果啊,今天再去仔细看了看设置,看来确实是我错了,我设置的是

    JWT_REFRESH_EXPIRATION_DELTA
    为7天,也就是在这个时间段内刷新JWT可以保持登录状态,而不是我所认为的过期时间,我需要设置的是
    JWT_EXPIRATION_DELTA
    ,这才是真正的JWT过期的时间,JWT过期后,只要还在设置的刷新过期时间之内,就可以刷新JWT以继续保持登录状态,具体可参考博文https://www.jianshu.com/p/a60efb8bac35,现在我的JWT配置如下:

    # JWT配置
    JWT_AUTH = {
    # 过期时间
    'JWT_EXPIRATION_DELTA': datetime.timedelta(days=7),
    # 刷新过期时间
    'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(days=30),
    # 请求头前缀
    'JWT_AUTH_HEADER_PREFIX': 'JWT',
    }

    三、用户收藏功能完成

    之前在商品详情页已经实现了用户收藏的部分功能,即在商品详情页添加和删除收藏,这里在用户中心完善用户收藏功能。

    为了在用户中心显示已收藏商品的具体信息,在apps/user_operation/serializers.py中定义嵌套序列化如下:

    class UserFavDetailSerializer(serializers.ModelSerializer):
    goods = GoodsSerializer()
    
    class Meta:
    model = UserFav
    fields = ['id', 'goods']

    视图完善如下:

    class UserFavViewSet(mixins.CreateModelMixin, mixins.ListModelMixin, mixins.RetrieveModelMixin, mixins.DestroyModelMixin, viewsets.GenericViewSet):
    '''
    list:
    用户收藏列表
    create:
    创建用户收藏
    retrieve:
    用户收藏详情
    destroy:
    删除用户收藏
    '''
    permission_classes = [IsAuthenticated, IsOwnerOrReadOnly]
    serializer_class = UserFavSerializer
    authentication_classes = [JSONWebTokenAuthentication, SessionAuthentication]
    lookup_field = 'goods_id'
    
    def get_queryset(self):
    return UserFav.objects.filter(user=self.request.user, is_delete=False)
    def get_serializer_class(self):
    '''动态设置序列化'''
    if self.action == 'list':
    return UserFavDetailSerializer
    elif self.action == 'create':
    return UserFavSerializer
    return UserFavSerializer
    

    进行测试如下:

    前端src/views/member/collection.vue如下:

    <tr v-for="(item,index) in collections">
    <td bgcolor="#ffffff">
    <router-link :to="'/app/home/productDetail/'+item.goods.id" class="f6" target="_blank">{{item.goods.name}}</router-link>
    </td>
    <td bgcolor="#ffffff">本店价<span class="goods-price">¥{{item.goods.shop_price}}元</span>
    </td>
    <td align="center" bgcolor="#ffffff">
    <a class="f6" @click="deletePro(index, item.goods.id)">删除</a>
    </td>
    </tr>
    
    created () {
    this.getCollection();
    },
    
    getCollection () { //获取收藏列表
    getAllFavs().then((response)=> {
    this.collections = response.data;
    }).catch(function (error) {
    console.log(error);
    });
    },
    
    deletePro (index, id) { //删除收藏商品
    alert('您确定要从收藏夹中删除选定的商品吗?');
    delFav(id).then((response)=> {
    this.collections.splice(index,1);
    alert('已删除商品');
    }).catch(function (error) {
    console.log(error);
    });
    }

    可以看到,初始化时先调用

    getCollection()
    方法获取收藏,调用了
    getAllFavs
    接口,得到数据之后通过for循环显示出来;在删除时调用
    deletePro(index, item.goods.id)
    方法,调用了
    delFav
    接口,api.js修改如下:

    //收藏
    export const addFav = params => { return axios.post(`${local_host}/userfavs/`, params) }
    
    //取消收藏
    export const delFav = goodsId => { return axios.delete(`${local_host}/userfavs/`+goodsId+'/') }
    
    export const getAllFavs = () => { return axios.get(`${local_host}/userfavs/`) }
    
    //判断是否收藏
    export const getFav = goodsId => { return axios.get(`${local_host}/userfavs/`+goodsId+'/') }

    演示如下:

    再查询数据库如下:

    +----+----------------------------+-----------+----------+---------+
    | id | add_time                   | is_delete | goods_id | user_id |
    +----+----------------------------+-----------+----------+---------+
    |  1 | 2020-07-29 17:02:39.893993 |         0 |       25 |       1 |
    |  2 | 2020-07-29 17:02:49.268221 |         0 |       15 |       1 |
    |  3 | 2020-07-29 17:02:57.410071 |         0 |        5 |       1 |
    |  6 | 2020-07-29 18:23:00.000000 |         0 |        3 |       1 |
    +----+----------------------------+-----------+----------+---------+
    4 rows in set (0.01 sec)

    显然,收藏数据同步。

    四、用户留言功能实现

    用户留言包括添加、获取和删除等功能。

    先实现添加功能,序列化apps/user_operation/serializers.py如下:

    class LeavingMessageSerializer(serializers.ModelSerializer):
    user = serializers.HiddenField(default=serializers.CurrentUserDefault())
    
    class Meta:
    model = UserLeavingMessage
    fields = ['id', 'user', 'message_type', 'subject', 'message', 'file']

    视图定义如下:

    class LeavingMessageViewSet(mixins.CreateModelMixin, mixins.ListModelMixin, mixins.DestroyModelMixin, viewsets.GenericViewSet):
    '''
    list:
    留言列表
    create:
    添加留言
    delete:
    删除留言
    '''
    
    permission_classes = [IsAuthenticated, IsOwnerOrReadOnly]
    authentication_classes = [JSONWebTokenAuthentication, SessionAuthentication]
    serializer_class = LeavingMessageSerializer
    
    def get_queryset(self):
    return UserLeavingMessage.objects.filter(user=self.request.user, is_delete=False)

    配置路由如下:

    # 配置留言路由
    router.register(r'messages', LeavingMessageViewSet, basename='messages')

    进行测试如下:

    显然,添加留言成功,再查看数据库:

    +----+--------------+--------------+--------------------------------------+------------------+----------------------------+-----------+---------+
    | id | message_type | subject      | message                              | file             | add_time                   | is_delete | user_id |
    +----+--------------+--------------+--------------------------------------+------------------+----------------------------+-----------+---------+
    |  1 |            4 | 售后服务     | 售后服务售后服务售后服务             | 客户服务.jpg     | 2020-07-30 17:51:15.337881 |         0 |       1 |
    +----+--------------+--------------+--------------------------------------+------------------+----------------------------+-----------+---------+
    1 row in set (0.00 sec)

    留言还有一个add_time字段,但是希望不手动输入时间、而是自动生成,因此需要定义覆盖add_time字段,并且需要设置

    read_only
    属性,表示add_time字段只返回而不提交,如下:

    class LeavingMessageSerializer(serializers.ModelSerializer):
    user = serializers.HiddenField(default=serializers.CurrentUserDefault())
    add_time = serializers.DateTimeField(read_only=True)
    
    class Meta:
    model = UserLeavingMessage
    fields = ['id', 'user', 'message_type', 'subject', 'message', 'file', 'add_time']

    read_only
    属性包含在API输出中,但在创建或更新操作期间不应包含在输入中,设置为True以确保序列化表示形式时使用该字段,而在反序列化期间创建或更新实例时不使用该字段。

    此时再进行测试如下:

    可以看到,此时显示出add_time字段,但是并不需要提交时间。

    前端src/views/member/message.vue如下:

    <li v-for="(item,index) in messageAll">
    <div>
    <span v-if="item.message_type===1">留言:</span>
    <span v-if="item.message_type===2">投诉:</span>
    <span v-if="item.message_type===3">询问:</span>
    <span v-if="item.message_type===4">售后:</span>
    <span v-if="item.message_type===5">求购:</span>
    <span>{{item.subject}}</span>
    <span>({{item.add_time}})</span>
    </div>
    <div>
    {{item.message}}
    </div>
    <div>
    <a @click="deleteMessage(index, item.id)">删除</a>
    <a :href="(item.file)">查看上传的文件</a>
    
    </div>
    
    </li>
    
    <form action="" method="post" enctype="multipart/form-data" name="formMsg">
    <table width="100%" border="0" cellpadding="3">
    <tbody><tr>
    <td align="right">留言类型:</td>
    <td>
    <input type="radio" id="one" value="1" v-model="message_type">
    <label for="one">留言</label>
    <input type="radio" id="two" value="2" v-model="message_type">
    <label for="two">投诉</label>
    <input type="radio" id="three" value="3" v-model="message_type">
    <label for="three">询问</label>
    <input type="radio" id="four" value="4" v-model="message_type">
    <label for="four">售后</label>
    <input type="radio" id="five" value="5" v-model="message_type">
    <label for="five">求购</label>
    
    <!-- <input name="msg_type" type="radio" value="0" checked="checked">
    留言                        <input type="radio" name="msg_type" value="1">
    投诉                        <input type="radio" name="msg_type" value="2">
    询问                        <input type="radio" name="msg_type" value="3">
    售后                        <input type="radio" name="msg_type" value="4">
    求购 -->
    </td>
    </tr>
    <tr>
    <td align="right">主题:</td>
    <td><input name="msg_title" type="text" size="30" class="inputBg" v-model="subject"></td>
    </tr>
    <tr>
    <td align="right" valign="top">留言内容:</td>
    <td><textarea name="msg_content" cols="50" rows="4" wrap="virtual" class="B_blue" v-model="message"></textarea></td>
    </tr>
    <tr>
    <td align="right">上传文件:</td>
    <td><input type="file" name="message_img" size="45" class="inputBg" @change="preview"></td>
    </tr>
    <tr>
    <td>&nbsp;</td>
    <td><input type="hidden" name="act" value="act_add_message">
    <!-- <input type="submit" value="提 交" class="bnt_bonus"> -->
    <a class="btn_blue_1" @click="submitMessage">提交</a>
    </td>
    </tr>
    <tr>
    <td>&nbsp;</td>
    <td>
    <font color="red">小提示:</font><br>
    您可以上传以下格式的文件:<br>gif、jpg、png、word、excel、txt、zip、ppt、pdf                      </td>
    </tr>
    </tbody></table>
    </form>
    
    created () {
    this.getMessage();
    },
    
    submitMessage () { //提交留言
    const formData = new FormData();
    formData.append('file',this.file);
    formData.append('subject',this.subject);
    formData.append('message',this.message);
    formData.append('message_type',this.message_type);
    addMessage(formData).then((response)=> {
    this.getMessage();
    
    }).catch(function (error) {
    console.log(error);
    });
    },
    getMessage () { //获取留言
    getMessages().then((response)=> {
    console.log(response.data);
    this.messageAll = response.data;
    }).catch(function (error) {
    console.log(error);
    });
    },
    deleteMessage (index, id) { // 删除留言
    delMessages(id).then((response)=> {
    alert("删除成功")
    this.messageAll.splice(index,1);
    }).catch(function (error) {
    console.log(error);
    });
    },

    可以看到,在初始化时调用

    getMessage()
    方法,并调用
    getMessage
    接口,获取到数据后头盖骨for循环展示出来;在新增留言时,调用
    submitMessage()
    方法,并调用
    addMessage
    接口提交;删除留言时调用
    deleteMessage(index, id)
    方法,调用
    delMessages
    接口实现,api.js修改如下:

    //获取留言
    export const getMessages = () => {return axios.get(`${local_host}/messages/`)}
    
    //添加留言
    export const addMessage = params => {return axios.post(`${local_host}/messages/`, params, {headers:{ 'Content-Type': 'multipart/form-data' }})}
    
    //删除留言
    export const delMessages = messageId => {return axios.delete(`${local_host}/messages/`+messageId+'/')}

    在新增留言时,需要上传文件,从API中可以看到,提交新增的留言时,在Header中增加了Content-Type为

    multipart/form-data
    ,来支持上传文件,同时DRF提供了MultiPartParser类,来解析多部分HTML表单内容,支持文件上传。

    进行测试如下:

    显然,操作成功。

    五、用户收货地址功能开发

    在user_operation中开发收货地址功能。

    先在models.py中修改UserAddress模型如下:

    class UserAddress(models.Model):
    '''用户收货地址'''
    user = models.ForeignKey(User, verbose_name='用户', null=True, on_delete=models.SET_NULL)
    province = models.CharField(max_length=50, default='', verbose_name='省份')
    city = models.CharField(max_length=50, default='', verbose_name='城市')
    district = models.CharField(max_length=80, default='', verbose_name='区域')
    address = models.CharField(max_length=100, default='', verbose_name='详细地址')
    signer_name = models.CharField(max_length=20, default='', verbose_name='签收人')
    signer_mobile = models.CharField(max_length=11, default='', verbose_name='联系电话')
    
    add_time = models.DateTimeField(default=datetime.now, verbose_name=u'添加时间')
    is_delete = models.BooleanField(default=False, verbose_name='是否删除')
    
    class Meta:
    verbose_name = '收货地址'
    verbose_name_plural = verbose_name
    
    def __str__(self):
    return self.address

    修改之后映射数据库,然后定义序列化如下:

    class AddressSerializer(serializers.ModelSerializer):
    user = serializers.HiddenField(default=serializers.CurrentUserDefault())
    add_time = serializers.DateTimeField(read_only=True, format='%Y-%m-%d %H:%M')
    
    class Meta:
    model = UserAddress
    fields = ['id', 'user', 'province', 'city', 'district', 'address', 'signer_name', 'add_time', 'signer_mobile']

    再定义视图如下:

    class AddressViewSet(viewsets.ModelViewSet):
    '''
    收货地址管理
    list:
    收货地址列表
    create:
    新建收货地址
    update:
    更新收货地址
    delete:
    删除收货地址
    '''
    
    permission_classes = [IsAuthenticated, IsOwnerOrReadOnly]
    authentication_classes = [JSONWebTokenAuthentication, SessionAuthentication]
    serializer_class = AddressSerializer
    
    def get_queryset(self):
    return UserAddress.objects.filter(user=self.request.user, is_delete=False)

    可以看到,

    AddressViewSet
    继承自
    viewsets.ModelViewSet
    ,大大减少了之前继承自
    mixins.ListModelMixin, mixins.CreateModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin, viewsets.GenericViewSet
    的代码量,但是可以达到一样的效果。

    配置路由如下:

    # 配置收货地址路由
    router.register(r'address', AddressViewSet, basename='address')

    进行测试如下:

    创建数据成功。

    前端src/views/member/receive.vue如下:

    <table width="100%" border="0" cellpadding="5" cellspacing="1" bgcolor="#dddddd" v-for="(item, index) in receiveInfoArr">
    <tbody>
    <tr>
    <td align="right" bgcolor="#ffffff">配送区域:</td>
    <td colspan="3" align="left" bgcolor="#ffffff">
    <div class="addr" @click="bubble(index)">
    <v-distpicker :province="item.province" :city="item.city" :area="item.district" @province="updateProvince"  @city="updateCity" @area="updateArea"></v-distpicker>
    </div>
    </td>
    </tr>
    <tr>
    <td align="right" bgcolor="#ffffff">收货人姓名:</td>
    <td align="left" bgcolor="#ffffff"><input name="consignee" type="text" class="inputBg" id="consignee_0" value="ssss" v-model="item.signer_name">
    <span :class = "{error:item.signer_name==''}">(必填)</span>
    </td>
    
    </tr>
    <tr>
    <td align="right" bgcolor="#ffffff">详细地址:</td>
    <td align="left" bgcolor="#ffffff"><input name="address" type="text" class="inputBg" id="address_0" v-model="item.address">
    <span :class = "{error:item.address==''}">(必填)</span></td>
    </tr>
    <tr>
    
    <td align="right" bgcolor="#ffffff">手机:</td>
    <td align="left" bgcolor="#ffffff"><input name="mobile" type="text" class="inputBg" id="mobile_0" v-model="item.signer_mobile"><span :class = "{error:item.signer_mobile==''}">(必填)</span></td>
    </tr>
    <tr>
    <td align="right" bgcolor="#ffffff">&nbsp;</td>
    <td colspan="3" align="center" bgcolor="#ffffff">
    <!-- <input type="submit" name="submit" class="bnt_blue_2" value="新增收货地址"> -->
    
    <button class="bnt_blue_2" @click="confirmUpdate(item.id, index)">确定修改</button>
    <button class="bnt_blue_2" @click="deleteInfo(item.id)">删除</button>
    <!-- <input type="hidden" name="act" value="act_edit_address">
    <input name="address_id" type="hidden" value="320"> -->
    </td>
    </tr>
    </tbody>
    </table>
    
    <table width="100%" border="0" cellpadding="5" cellspacing="1" bgcolor="#dddddd">
    <tbody>
    <tr>
    <td align="right" bgcolor="#ffffff">配送区域:</td>
    <td colspan="3" align="left" bgcolor="#ffffff">
    <div class="addr">
    <!-- <v-distpicker :placeholder="newInfo.dist" @province="getProvince" @city="getCity" @selected="getArea"></v-distpicker> -->
    <v-distpicker :province="newInfo.province" :city="newInfo.city" :area="newInfo.district" @province="getProvince" @city="getCity" @area="getArea"></v-distpicker>
    </div>
    </td>
    </tr>
    <tr>
    <td align="right" bgcolor="#ffffff">收货人姓名:</td>
    <td align="left" bgcolor="#ffffff"><input name="consignee" type="text" class="inputBg" id="consignee_0" value="ssss" v-model="newInfo.signer_name">
    <span :class = "{error:newInfo.signer_name==''}">(必填)</span> </td>
    
    </tr>
    <tr>
    <td align="right" bgcolor="#ffffff">详细地址:</td>
    <td align="left" bgcolor="#ffffff"><input name="address" type="text" class="inputBg" id="address_0" v-model="newInfo.address">
    <span :class = "{error:newInfo.address==''}">(必填)</span></td>
    </tr>
    <tr>
    
    <td align="right" bgcolor="#ffffff">手机:</td>
    <td align="left" bgcolor="#ffffff"><input name="mobile" type="text" class="inputBg" id="mobile_0" v-model="newInfo.signer_mobile"><span :class = "{error:newInfo.signer_mobile==''}">(必填)</span></td>
    </tr>
    <tr>
    <td align="right" bgcolor="#ffffff">&nbsp;</td>
    <td colspan="3" align="center" bgcolor="#ffffff">
    <!-- <input type="submit" name="submit" class="bnt_blue_2" value="新增收货地址"> -->
    <button class="bnt_blue_2" @click="addReceive">新增收货地址</button>
    
    <!-- <input type="hidden" name="act" value="act_edit_address">
    <input name="address_id" type="hidden" value="320"> -->
    </td>
    </tr>
    </tbody>
    </table>
    
    created () {
    this.getReceiveInfo();
    },
    
    updateProvince (data) {
    this.receiveInfoArr[this.currentIndex].province = data.value;
    },
    updateCity (data) {
    this.receiveInfoArr[this.currentIndex].city = data.value;
    },
    updateArea (data) {
    this.receiveInfoArr[this.currentIndex].district = data.value;
    },
    
    getProvince (data) {
    this.newInfo.province = data.value;
    },
    getCity (data) {
    this.newInfo.city = data.value;
    },
    getArea (data) {
    this.newInfo.district = data.value;
    },
    getReceiveInfo() { //获取收件人信息
    getAddress().then((response)=> {
    console.log(response.data);
    this.receiveInfoArr = response.data;
    
    }).catch(function (error) {
    console.log(error);
    });
    
    },
    
    addReceive () { //提交收获信息
    addAddress(this.newInfo).then((response)=> {
    alert('添加成功');
    // 重置新的
    this.getReceiveInfo();
    this.newInfo = Object.assign({}, this.newInfoEmpty);
    
    }).catch(function (error) {
    console.log(error);
    });
    },
    confirmUpdate (id, index) { // 更新收获信息
    updateAddress(id, this.receiveInfoArr[index]).then((response)=> {
    alert('修改成功');
    this.getReceiveInfo();
    }).catch(function (error) {
    console.log(error);
    });
    
    },
    deleteInfo (id, index) { // 删除收获人信息
    delAddress(id).then((response)=> {
    alert('删除成功');
    this.getReceiveInfo();
    }).catch(function (error) {
    console.log(error);
    });
    }

    可以看到,在初始化时调用

    getReceiveInfo()
    方法获取收货地址信息,调用了
    getAddress
    接口,获取到数据后通过for循环显示到前端;修改每个字段分别调用相应的update方法,并调用
    confirmUpdate (id, index)
    方法更新数据,最后调用
    updateAddress
    接口实现更新;增加收货地址调用
    addReceive()
    方法,并调用
    updateAddress
    接口实现新增数据;删除数据调用
    deleteInfo(id, index)
    方法,并通过
    delAddress
    接口实现删除。

    api.js中对应接口修改如下:

    //添加收货地址
    export const addAddress = params => {return axios.post(`${local_host}/address/`, params)}
    
    //删除收货地址
    export const delAddress = addressId => {return axios.delete(`${local_host}/address/`+addressId+'/')}
    
    //修改收货地址
    export const updateAddress = (addressId, params) => {return axios.patch(`${local_host}/address/`+addressId+'/', params)}
    
    //获取收货地址
    export const getAddress = () => {return axios.get(`${local_host}/address/`)}

    演示如下:

    显然,已经可以正常增、删、改、查收货地址。

    内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: