vue 组件嵌套(ant-design-vue)登录 之用户模块

vue(ant-design-vue)组件嵌套方式

  1. axios跨域

    1. 新建http文件夹

    2. http/apis.js

      1. //将我们http.js中封装好的  get,post.put,delete  导过来
        import {axios_get, axios_post, axios_delete, axios_put} from './index.js'
        
        
        // 书籍管理接口
        // export const getBookList = (params, headers) => axios_get("/books/book/", params, headers)
        
        //用户
        //获取用户信息
        export const getUser = (params, headers) => axios_get("/user/user/", params, headers)
        //登录接口
        export const postLogin = (params, headers) => axios_post("/user/login/", params, headers)
        //注册接口
        export const postRegister = (params, headers) => axios_post("/user/register/", params, headers)
        //搜索
        export const postSearch = (params, headers) => axios_post("/user/search/", params, headers)
        //删除
        export const delUser = (params, headers) => axios_delete("/user/user/" + params.id + '/', headers)
        //修改
        export const upUser = (params, headers) => axios_put("/user/user/" + params.id + '/', params, headers)
        
    3. http/index.js

      1. import axios from 'axios'
        
        // 第一步:设置axios
        axios.defaults.baseURL = "http://192.168.56.100:8888/"
        
        //全局设置网络超时
        axios.defaults.timeout = 10000;
        
        //设置请求头信息
        axios.defaults.headers.post['Content-Type'] = 'application/json';
        axios.defaults.headers.put['Content-Type'] = 'application/json';
        
        
        // 第二:设置拦截器
        /**
         * 请求拦截器(当前端发送请求给后端前进行拦截)
         * 例1:请求拦截器获取token设置到axios请求头中,所有请求接口都具有这个功能
         * 例2:到用户访问某一个页面,但是用户没有登录,前端页面自动跳转 /login/ 页面
         */
        axios.interceptors.request.use(
          config => {
            // 每次发送请求之前判断是否存在token,如果存在,则统一在http请求的header都加上token,不用每次请求都手动添加了
            const token = localStorage.getItem("token")
            // console.log(token)
            if (token) {
              config.headers.Authorization = 'JWT ' + token
            }
            return config;
          },
          error => {
            return Promise.error(error);
          })
        
        axios.interceptors.response.use(
          // 请求成功
          res => res.status === 200 || res.status === 204 || res.status === 202 ? Promise.resolve(res) : Promise.reject(res),
          // 请求失败
          error => {
            if (error.response) {
              // 判断一下返回结果的status == 401?  ==401跳转登录页面。  !=401passs
              // console.log(error.response)
              if (error.response.status === 401) {
                // 跳转不可以使用this.$router.push方法、
                // this.$router.push({path:'/login'})
                window.location.href = "http://127.0.0.1:8888/"
              } else {
                // errorHandle(response.status, response.data.message);
                return Promise.reject(error.response);
              }
              // 请求已发出,但是不在2xx的范围
            } else {
              // 处理断网的情况
              // eg:请求超时或断网时,更新state的network状态
              // network状态在app.vue中控制着一个全局的断网提示组件的显示隐藏
              // 关于断网组件中的刷新重新获取数据,会在断网组件中说明
              // store.commit('changeNetwork', false);
              return Promise.reject(error.response);
            }
          });
        
        
        // 第三:封装axios请求
        // 3.1 封装get请求
        export function axios_get(url, params) {
          return new Promise(
            (resolve, reject) => {
              axios.get(url, {params: params})
                .then(res => {
                  // console.log("封装信息的的res", res)
                  resolve(res.data)
                }).catch(err => {
                reject(err.data)
              })
            }
          )
        }
        
        // 3.2 封装post请求
        export function axios_post(url, data) {
          return new Promise(
            (resolve, reject) => {
              // console.log(data)
              axios.post(url, JSON.stringify(data))
                .then(res => {
                  // console.log("封装信息的的res", res)
                  resolve(res.data)
                }).catch(err => {
                reject(err.data)
              })
            }
          )
        }
        
        // 3.3 封装put请求
        export function axios_put(url, data) {
          return new Promise(
            (resolve, reject) => {
              // console.log(data)
              axios.put(url, JSON.stringify(data))
                .then(res => {
                  // console.log("封装信息的的res", res)
                  resolve(res.data)
                }).catch(err => {
                reject(err.data)
              })
            }
          )
        }
        
        // 3.4 封装delete请求
        export function axios_delete(url, data) {
          return new Promise(
            (resolve, reject) => {
              // console.log(data)
              axios.delete(url, {params: data})
                .then(res => {
                  // console.log("封装信息的的res", res)
                  resolve(res)
                }).catch(err => {
                reject(err)
              })
            }
          )
        }
        
  2. 在components\index.vue

    1. <template>
        <div>
          <a-layout
            id="components-layout-demo-top-side"
            :selected-keys="[current]"
          >
            <a-layout-header class="header">
              <div class="logo"/>
              <a-menu
                theme="dark"
                mode="horizontal"
                :default-selected-keys="['1']"
                :style="{ lineHeight: '64px' }"
              >
                <a-menu-item key="1">
                  nav 1
                </a-menu-item>
                <a-menu-item key="2">
                  nav 2
                </a-menu-item>
                <a-menu-item key="3" style="margin-left: 80%">
                  <Header></Header>
                </a-menu-item>
              </a-menu>
            </a-layout-header>
            <a-layout-content style="padding: 0 50px">
              <a-breadcrumb style="margin: 16px 0">
                <a-breadcrumb-item>Home</a-breadcrumb-item>
                <a-breadcrumb-item>List</a-breadcrumb-item>
                <a-breadcrumb-item>App</a-breadcrumb-item>
              </a-breadcrumb>
              <a-layout style="padding: 24px 0; background: #fff">
                <a-layout-sider width="200" style="background: #fff">
                  <a-menu
                    mode="inline"
                    :default-selected-keys="['1']"
                    :default-open-keys="['sub1']"
                    style="height: 100%"
                    @click="handleClick"
      
                  >
                    <a-sub-menu key="sub1">
                      <span slot="title"><a-icon type="user"/>用户模块</span>
                      <a-menu-item key="test">
                        测试
                      </a-menu-item>
                      <a-menu-item key="usermanage">
                        用户管理
                      </a-menu-item>
                    </a-sub-menu>
                    <a-sub-menu key="sub2">
                      <span slot="title"><a-icon type="laptop"/>工单模块</span>
                      <a-menu-item key="">
                        工单管理
                      </a-menu-item>
      
                    </a-sub-menu>
      <!--              <a-sub-menu key="sub3">-->
      <!--                <span slot="title"><a-icon type="notification"/>subnav 3</span>-->
      <!--                <a-menu-item key="">-->
      <!--                  option9-->
      <!--                </a-menu-item>-->
      <!--              </a-sub-menu>-->
                  </a-menu>
                </a-layout-sider>
                <a-layout-content :style="{ padding: '0 24px', minHeight: '280px' }">
                  <router-view></router-view>
                </a-layout-content>
              </a-layout>
            </a-layout-content>
            <a-layout-footer style="text-align: center">
            </a-layout-footer>
          </a-layout>
        </div>
      
      </template>
      
      <script>
      import Header from "./layout/Header";
      
      
      export default {
        components:{
          Header,
      
        },
        name: "index",
        data() {
          return {
            current: '1',
      
          }
        },
        methods: {
          handleClick(e) {
            // console.log(e)
            this.current = e.key;
            this.$router.push({path: this.current});
          },
        },
      
      
        //钩子方法
        mounted() {
      
        },
        created() {
      
        },
        //监听属性
        watch: {},
        //计算属性
        computed: {}
      }
      </script>
      
      <style scoped>
      #components-layout-demo-top-side .logo {
        width: 120px;
        height: 31px;
        background: rgba(255, 255, 255, 0.2);
        margin: 16px 28px 16px 0;
        float: left;
      }
      </style>
      
      
  3. 新建views文件夹

    1. views/user-manage/ 新建componentes/ButtonComponent.vue

      1. <template>
        
          <div>
            <a-button type="primary" @click="showModal" style="margin-left: 5px">
              + 创建用户
            </a-button>
            <a-modal v-model="visible" title="Basic Modal" @ok="handleOk">
              用户名
              <a-input placeholder="" v-model="username"/>
              密码
              <a-input placeholder="" v-model="password"/>
              手机号
              <a-input placeholder="" v-model="mobile"/>
              电子邮箱
              <a-input placeholder="" v-model="email"/>
            </a-modal>
          </div>
        
        </template>
        
        <script>
        import {postRegister} from "../../../http/apis";
        
        export default {
          name: "ButtonComponent",
          data() {
            return {
              visible: false,
              username: '',
              password: '',
              mobile: '',
              email: '',
            }
          },
          methods: {
            showModal() {
              this.visible = true;
            },
            handleOk() {
              let params = {
                username: this.username,
                password: this.password,
                mobile: this.mobile,
                email: this.email,
              }
              this.$emit('addUser', params)
              // postRegister(params).then(res => {
              //   console.log(res)
              //   this.$router.go(0)
              // })
              this.visible = false;
            },
          },
        
        
          //钩子方法
          mounted() {
          },
          created() {
        
          },
          //监听属性
          watch: {},
          //计算属性
          computed: {}
        }
        </script>
        
        <style scoped>
        
        </style>
        
        
    2. views/user-manage/componentes/SearchComponent.vue

      1. <template>
        
          <div>
            <div>
              <a-input-search class="a-input-search" placeholder="请输入用户名" enter-button @search="onSearch"/>
              <br/><br/>
            </div>
        
        
          </div>
        
        </template>
        
        <script>
        import {postSearch} from "../../../http/apis";
        
        export default {
          name: "SearchComponent",
          data() {
            return {
            }
          },
          methods: {
            onChange(date, dateString) {
              console.log(date, dateString);
            },
            onSearch(value) {
              this.$emit('onSearch',value)
              // console.log(value);
              // postSearch({search_name: value}).then(res => {
              //   console.log(res)
              //   this.user_list = res
              // })
            },
          },
        
        
          //钩子方法
          mounted() {
          },
          created() {
        
          },
          //监听属性
          watch: {},
          //计算属性
          computed: {}
        }
        </script>
        
        <style scoped>
        .a-input-search {
          width: 400px;
          margin-left: 35%;
        
        }
        
        .components-input-demo-size .ant-input {
          width: 200px;
          margin: 0 30px 30px 0;
        }
        </style>
        
        
    3. views/user-manage/componentes/TableComponent.vue

      1. <template>
        
          <div>
            <a-table :columns="columns" :data-source="data" :rowKey="record => record.id" :pagination="pagination">
              <a slot="name" slot-scope="text">{{ text }}</a>
              <span slot="customTitle"><a-icon type="smile-o"/> 名字</span>
              <span slot="tags" slot-scope="tags">
                      <a-tag
                        v-for="tag in tags"
                        :key="tag"
                        :color="tag === 'loser' ? 'volcano' : tag.length > 5 ? 'geekblue' : 'green'"
                      >
                        {{ tag.toUpperCase() }}
                      </a-tag>
            </span>
              <span slot="action" slot-scope="text, record">
                    <a-button type="primary" @click="showModal(text)" style="margin-left: 5px">
              修改
            </a-button>
            <a-modal v-model="visible" title="Basic Modal" @ok="handleOk(text)">
              用户名
              <a-input placeholder="" v-model="username" v-if="pk == uid" />
              用户名
              <a-input placeholder="" v-model="username" disabled="disabled" v-if="pk != uid"  />
              手机号
              <a-input placeholder="" v-model="mobile"/>
              电子邮箱
              <a-input placeholder="" v-model="email"/>
            </a-modal>
                   <a-button type="danger" @click="delUser(text.id)">删除</a-button>
            </span>
            </a-table>
          </div>
        
        </template>
        <script>
        import {delUser, getUser} from "../../../http/apis";
        
        const columns = [
          {
            dataIndex: 'username',
            // key: 'username',
            slots: {title: 'customTitle'},
            scopedSlots: {customRender: 'name'},
          },
          {
            title: '最后一次登录',
            dataIndex: 'date_joined',
            // key: 'mobile',
          },
          {
            title: '电子邮箱',
            dataIndex: 'email',
            // key: 'email',
          },
          {
            title: '手机号',
            // key: 'last_login',
            dataIndex: 'mobile',
            // scopedSlots: {customRender: 'tags'},
          },
          {
            title: '操作',
            // key: 'last_login',
            scopedSlots: {customRender: 'action'},
          },
        ];
        
        // const data = [
        //   {
        //     key: '1',
        //     username: '战三',
        //     mobile: 18548789043,
        //     email: '515@qq.com',
        //     is_superuser: '0',
        //     last_login:'2020-12-09'
        //   },
        // ];
        
        export default {
          name: "TableComponent",
          props: ['data',],
          data() {
            return {
              // data: [],
              columns,
              visible: false,
              username: '',
              mobile: '',
              email: '',
              pk: '',
              pagination: {
                total: 0,
                pageSize: 2,//每页中显示10条数据
                showSizeChanger: true,
                pageSizeOptions: ["5", "10", "20", "30"],//每页中显示的数据
                showTotal: total => `共有 ${total} 条数据`,  //分页中显示总的数据
              },
              uid: localStorage.getItem("uid")
            }
          },
          methods: {
            showModal(text) {
              this.visible = true;
              this.username = text.username
              this.mobile = text.mobile
              this.email = text.email
              this.pk = text.id
            },
            delUser(text) {
              this.$emit('delUser', text)
              //   console.log(text)
              //   delUser({id: text}).then(res => {
              //     console.log(res)
              //     this.$router.go(0)
              //   }).catch(err => {
              //     this.$router.go(0)
              //
              //   })
            },
            handleOk(text) {
              console.log(text.id)
              let params = {
                username: this.username,
                mobile: this.mobile,
                email: this.email,
                password: '1',
                id: this.pk,
              }
              this.$emit('upUser', params)
              this.visible = false;
            },
          },
        
        
          //钩子方法
          mounted() {
          },
          created() {
            // this.showUser()
          },
          //监听属性
          watch: {},
          //计算属性
          computed: {}
        }
        </script>
        
        <style scoped>
        
        </style>
        
        
    4. views/user-manage/ componentes/Crumbs

      1. <template>
          <div>
            <a-breadcrumb separator="" class="a-breadcrumb">
              <a-breadcrumb-item>
                nav  1
              </a-breadcrumb-item>
              <a-breadcrumb-separator>:</a-breadcrumb-separator>
              <a-breadcrumb-item href="">
                用户模块
              </a-breadcrumb-item>
              <a-breadcrumb-separator/>
              <a-breadcrumb-item href="">
                用户管理
              </a-breadcrumb-item>
            </a-breadcrumb>
          </div>
        </template>
        
        <script>
        export default {
          name: "Crumbs",
          data() {
            return {}
          },
          methods: {},
        
        
          //钩子方法
          mounted() {
          },
          created() {
        
          },
          //监听属性
          watch: {},
          //计算属性
          computed: {}
        }
        </script>
        
        <style scoped>
        .a-breadcrumb {
          /*background:red;*/
          color: #1890ff;
          /*margin-top: -15px;*/
          margin-left: -30px;
        }
        </style>
        
        
    5. views/user-manage/ UserManage.vue

      1. <template>
          <div>
            <div id="components-layout-demo-basic">
              <a-layout>
                <a-layout-header style="background: #F0F2F5">
                  <Crumbs></Crumbs>
                  <!--          页内标题-->
                </a-layout-header>
        
        
                <a-layout-content>
                  <!--          搜索组件-->
                  <SearchComponent
                    @onSearch="onSearch"
                  ></SearchComponent>
        
                  <!--          添加按钮-->
                  <ButtonComponent
                    @addUser="addUser"
                    :visible=false
                  >
                  </ButtonComponent>
                </a-layout-content>
        
        
                <a-layout-footer>
                  <!--          展示  删除按钮 修改按钮-->
                  <TableComponent
                    @showUser="showUser"
                    @delUser="delUser"
                    @upUser="upUser"
                    :data="data"
                  >
                  </TableComponent>
                </a-layout-footer>
              </a-layout>
        
            </div>
        
        
          </div>
        </template>
        
        <script>
        import Crumbs from "./componentes/Crumbs";
        import SearchComponent from "./componentes/SearchComponent";
        import ButtonComponent from "./componentes/ButtonComponent";
        import TableComponent from "./componentes/TableComponent";
        import {delUser, getUser, postRegister, postSearch, upUser} from "../../http/apis";
        const key = 'updatable';
        export default {
          components: {
            Crumbs,
            SearchComponent,
            ButtonComponent,
            TableComponent,
          },
          name: "UserManage",
          data() {
            return {
              visible: false,
              data: []
            }
          },
          methods: {
            //展示用户
            showUser() {
              getUser().then(res => {
                console.log(res)
                this.data = res.results
              })
            },
        
            //删除
            delUser(text) {
              const isDel = confirm("确定删除吗")
              if (isDel) {
                delUser({id: text}).then(res => {
                  console.log(res)
                  this.showUser()
                  this.$message.info('删除成功');
                }).catch(err => {
                  console.log(err)
                })
              } else {
        
              }
        
            },
        
            //搜索name mobile email
            onSearch(value) {
              console.log(value);
              postSearch({search_name: value}).then(res => {
                console.log(res)
                const hide = this.$message.loading('Action in progress..', 0);
                setTimeout(hide, 100);
                this.data = res
              })
            },
        
            //添加用户
            addUser(params) {
              console.log(params.id)
              postRegister(params).then(res => {
                console.log(res)
                this.showUser()
                this.visible = false;
                this.$message.loading({content: '添加中...', key});
                setTimeout(() => {
                  this.$message.success({content: '添加成功!', key, duration: 2});
                }, 1000);
        
              })
              this.visible = false;
            },
            //修改用户
            upUser(params) {
        
              upUser(params).then(res => {
                console.log(res)
                this.showUser()
                this.visible = false;
              })
              this.visible = false;
            },
          },
        
        
          //钩子方法
          mounted() {
          },
          created() {
            this.showUser()
        
          },
          //监听属性
          watch: {},
          //计算属性
          computed: {}
        }
        </script>
        
        <style scoped>
        .h3 {
          font-weight: 800;
          margin-left: -3%;
          margin-top: -20px;
        }
        
        </style>
        
        
    6. 登录页面 views/Login.vue

      1. <template>
          <div width=300>
        
            <center><h1>登录</h1></center>
        
            <a-form-item label="用户名" v-bind="formlayout">
        
              <a-input v-model="username"/>
        
            </a-form-item>
            <a-form-item label="密码" v-bind="formlayout">
              <a-input-password v-model="password" placeholder="input password" />
            </a-form-item>
        
            <a-form-item v-bind="buttonlayout">
        
              <a-button type="primary"  @click="submit">登录</a-button>
        
            </a-form-item>
        
          </div>
        </template>
        
        <script type="text/javascript">
        import { postLogin } from '../http/apis';
        
        export default{
        
          data(){
            return{
              username:"",
              password:'',
              //表单样式
              formlayout:{
                //标签
                labelCol:{
                  xs:{span:24},
                  sm:{span:8}
                },
                //文本框
                wrapperCol:{
                  xs:{span:14},
                  sm:{span:6}
                }
              },
              //按钮样式
              buttonlayout:{
                //按钮
                wrapperCol:{
                  xs:{
                    span:24,
                    offset:0
                  },
                  sm:{span:16,offset:8}
                }
              }
            }
        
          },
          //自定义方法
          methods:{
            submit:function(){
              var data={'username':this.username,'password':this.password}
              postLogin(data).then(resp => {
                console.log(resp)
                if(resp.token){
                  localStorage.setItem('token',resp.token)
                  localStorage.setItem('username',resp.username)
                  localStorage.setItem('uid',resp.id)
                  this.$router.push('/')
                }
              }).catch(err=>{
                console.log(err)
                alert('登录失败')
              })
        
            }
          }
        };
        
        
        </script>
        
        <style type="text/css">
        
        
        </style>
        
        
    7. 全局配置src/main.js

      1. // The Vue build version to load with the `import` command
        // (runtime-only or standalone) has been set in webpack.base.conf with an alias.
        import Vue from 'vue'
        import App from './App'
        import router from './router'
        
        Vue.config.productionTip = false
        
        
        import ElementUI from 'element-ui'
        import 'element-ui/lib/theme-chalk/index.css'
        
        Vue.use(ElementUI)
        
        // 使用ant-design-vue
        import Antd from 'ant-design-vue';
        import 'ant-design-vue/dist/antd.css';
        
        Vue.config.productionTip = false
        Vue.use(Antd);
        
        
        /* eslint-disable no-new */
        new Vue({
          el: '#app',
          router,
          components: {App},
          template: '<App/>'
        })
        
        
        //路由守卫  未登录则登录
        router.beforeEach((to, from, next) => {
          // debugger
          if (to.path == '/login' || localStorage.getItem("token")) {
            next()
          } else {
            alert("尚未登录,请先登录")
            return next("/login")
          }
        })
        
        
    8. 路由 router/index.js

      1. import Vue from 'vue'
        import Router from 'vue-router'
        import Home from "../components/layout/Home";
        
        Vue.use(Router)
        const page = name => () => import('@/views/' + name)
        
        
        export default new Router({
          mode: 'history',
          routes: [
            {path: '/login', component: page('Login'), name: '登录'},
            {
              path: '/', component: index, name: 'index',
              children: [
                {path: '/test', component: page('test/Test'), name: '测试页面'},
                {path: '/usermanage', component: page('user-manage/UserManage'), name: '用户模块'},
        
              ]
            },
          ]
        })
        
        
        import VueRouter from 'vue-router'
        import index from "../components/index";
        //import HelloWorld from '@/components/HelloWorld'
        const originalPush = VueRouter.prototype.push
        VueRouter.prototype.push = function push(location) {
          return originalPush.call(this, location).catch(err => err)
        }
        
        
posted @ 2020-11-24 19:21  心-瘾  阅读(2058)  评论(0编辑  收藏  举报