续小u项目后台管理(2.0)

一、实现菜单管理弹框的基本静态骨架

页面

<el-dialog
      :before-close="cancel"
      center
      :title="isAdd ? '添加菜单' : '修改菜单'"
      :visible.sync="isShow"
    >
      <el-form ref="menuForm" :model="menuForm" :rules="rules">
        <el-form-item
          :label-width="formLabelWidth"
          label="菜单名称"
          prop="title"
        >
          <el-input v-model="menuForm.title" autocomplete="off"></el-input>
        </el-form-item>
        <el-form-item :label-width="formLabelWidth" label="上级菜单" prop="pid">
          <el-select v-model="menuForm.pid" placeholder="请选择上级菜单">
            <el-option label="顶级菜单" :value="0"></el-option>
            <el-option
              v-for="item in menulist"
              :key="item.id"
              :label="item.title"
              :value="item.id"
            ></el-option>
          </el-select>
        </el-form-item>
        <el-form-item :label-width="formLabelWidth" label="菜单类型">
          <el-radio v-model="menuForm.type" :label="1">目录</el-radio>
          <el-radio v-model="menuForm.type" :label="2">菜单</el-radio>
        </el-form-item>
        <el-form-item :label-width="formLabelWidth" label="菜单图标">
          <el-input v-model="menuForm.icon" autocomplete="off"></el-input>
        </el-form-item>
        <el-form-item :label-width="formLabelWidth" label="菜单地址">
          <el-input v-model="menuForm.url" autocomplete="off"></el-input>
        </el-form-item>
        <el-form-item :label-width="formLabelWidth" label="状态">
          <el-switch
            v-model="menuForm.status"
            active-color="#13ce66"
            inactive-color="#ff4949"
            :active-value="1"
            :inactive-value="2"
          >
          </el-switch>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="cancel">取 消</el-button>
        <el-button type="primary" @click="comfirm">确 定</el-button>
      </div>
    </el-dialog>

js代码

// 引入封装好的接口
import { menuAdd, menuInfo, menuEdit } from "../../request/api";
//引入辅助性函数
import { mapActions, mapGetters } from "vuex";
export default {
  data() {
    return {
       // 先声明一个菜单表单对象
      menuForm: {
        pid: 0, //上级分类编号  注意:顶级菜单-0
        title: "", //菜单名称
        icon: "", //图标
        type: 1, //类型 1目录2菜单
        url: "", //菜单地址
        status: 1, //状态   1正常2禁用   number类型
      },
      formLabelWidth: "120px",
      rules: {
        title: [
          // required必须的 必传项
          { required: true, message: "请输入菜单名称", trigger: "blur" },
          { min: 2, max: 6, message: "长度在 2 到 6 个字符", trigger: "blur" },
        ],
        pid: [{ required: true, message: "请选择上级菜单", trigger: "change" }],
      },
    };
  },
  computed: {
    ...mapGetters({
      menulist: "menu/getMenuList",
    }),
  },
  props: ["isShow", "isAdd"],
  methods: {
    //获取一条数据的方法
    lookup(id) {
      console.log(id,'iiiiii');
      menuInfo({
        id,
      }).then((res) => {
        console.log(res, "一条数据");
        this.menuForm = res.list;
        this.menuForm.id = id;
      });
    },
    ...mapActions({
      getMenu: "menu/changeMenuAction",
    }),
    //封装一个取消事件
    cancel() {
      this.$emit("cancel", false);
      //调用重置事件
      this.reset();
    },
    //封装一个重置事件
    reset() {
      //清空输入内容
      this.menuForm = {
        pid: 0, //上级分类编号  注意:顶级菜单-0
        title: "", //菜单名称
        icon: "", //图标
        type: 1, //类型 1目录2菜单
        url: "", //菜单地址
        status: 1, //状态   1正常2禁用   number类型
      };
      //清空验证规则
      // resetFields	对整个表单进行重置,将所有字段值重置为初始值并移除校验结果
      this.$refs.menuForm.resetFields();
    },
    //封装一个确定事件
    comfirm() {
      this.$refs.menuForm.validate(async (flag) => {
        console.log(flag);
        if (flag) {
          //通过属性isAdd去区分 区分是添加还是编辑
          if (this.isAdd) {
            //添加接口
            // console.log(this.menuForm, "菜单的表单对象");
            // console.log("添加");
            let res = await menuAdd(this.menuForm);
            // console.log(res, "添加菜单");
            if (res.code == 200) {
              this.$message.success(res.msg);
              //添加成功之后关闭弹框
              this.cancel();
              //重新触发行动
              this.getMenu();
            } else {
              this.$message.error(res.msg);
            }
          } else {
            //调用编辑接口
            console.log("编辑");
            let res = await menuEdit(this.menuForm);
            console.log(res, "添加菜单");
            if (res.code == 200) {
              this.$message.success(res.msg);
              //添加成功之后关闭弹框
              this.cancel();
              //重新触发行动
              this.getMenu();
            } else {
              this.$message.error(res.msg);
            }
          }
        } else {
          console.log("验证失败");
        }
      });
    },
  },
};

二、实现通过添加或者编辑打开不同的弹框

菜单页面

<template>
  <div>
    <!-- 面包屑导航 -->
    <el-breadcrumb separator="/">
      <el-breadcrumb-item :to="{ path: '/home' }">首页</el-breadcrumb-item>
      <el-breadcrumb-item><a href="#">菜单管理</a></el-breadcrumb-item>
    </el-breadcrumb>
        <!-- 添加按钮 -->
    <el-button @click="addDialog" plain class="btn" type="primary" size="small">添加</el-button>
    <!-- 列表的渲染 -->
    <v-list @edit="edit"></v-list>
    <!-- 弹框组件 -->
    <v-dialog ref='digInfo' :isAdd = 'isAdd' @cancel="cancel" :isShow = 'isShow'></v-dialog>
  </div>
</template>

菜单逻辑

//引入list组件
import vList from './list.vue'
//引入弹框组件
import vDialog from './dialog.vue'
export default {
  data() {
    return {
        isShow:false, //用于控制弹框的显示隐藏
        isAdd:true  //用来告知弹框是新增还是修改
    };
  },
  components:{
      vList,
      vDialog
  },
  methods:{
      //封装一个添加按钮事件,目的 打开弹框
      addDialog(){
          //打开弹框
          this.isShow = true
          //告诉弹框你是新增
          this.isAdd = true
      },
      //子控制父 去关闭弹框
      cancel(e){
        this.isShow = e
      },
      //封装一个列表的自定义事件
      edit(e){
        //打开弹框
        this.isShow = true
        //告诉弹框你是编辑
        this.isAdd = false
        this.$refs.digInfo.lookup(e)
        // console.log(e,'eeeeeeeee');
      }
  }
};

三、实现点击内容以及验证规则的重置 和实现点击删除按钮出现弹框

 //封装一个重置事件
    reset() {
      //清空输入内容
      this.menuForm = {
        pid: 0, //上级分类编号  注意:顶级菜单-0
        title: "", //菜单名称
        icon: "", //图标
        type: 1, //类型 1目录2菜单
        url: "", //菜单地址
        status: 1, //状态   1正常2禁用   number类型
      };
      //清空验证规则
      // resetFields	对整个表单进行重置,将所有字段值重置为初始值并移除校验结果
      this.$refs.menuForm.resetFields()
    },


//封装一个删除事件
    del() {
      this.$confirm("你确定要删除这条数据吗", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          console.log('准备调用删除接口');
        })
        .catch(() => {
          this.$message({
            type: "info",
            message: "已取消删除",
          });
        });
    },

四、有大量的接口,封装一个接口文件

  // 引入核心库
import axios from "axios";
//通过querystring去进行转化
import qsString from 'querystring'

//设置基础地址
let baseUrl = "/api";

//拦截器之请求拦截器
axios.interceptors.request.use((req) => {
  return req;
});

//拦截器之响应拦截器
axios.interceptors.response.use((res) => {
  return res.data;
});

/* 
    全局封装get 方法
    url 地址
    params参数
*/

export const get = (url, params = {}) => {
  return new Promise((resolve, reject) => {
    //调用axios中的get方法
    axios
      .get(baseUrl + url, {
        params,
      })
      .then((res) => {
        resolve(res);
      })
      .catch((err) => {
        reject(err);
      });
  });
};
/* 
封装post方法
    url 地址
    params参数
    isFile 是否含有上传文件
*/
/* 
表单提交(post方式比较特殊)
content-type

值	描述
application/x-www-form-urlencoded	在发送前编码所有字符(默认)

multipart/form-data	
不对字符编码。
在使用包含文件上传控件的表单时,必须使用该值。

*/
export const post = (url, params = {}, isFile = false) => {
    let data = {}
    if(isFile){
        data = new FormData()
        for(let i in params){
            data.append(i,params[i])
        }
    }else{
         data = qsString.stringify(params)
        // data=params
    }
  return new Promise((resolve, reject) => {
    axios
      .post(baseUrl + url, data)
      .then((res) => {
        resolve(res);
      })
      .catch((err) => {
        reject(err);
      });
  });
};
//引入封装好的方法
import {get,post} from './index'

/* =============菜单管理=============== */
// 封装一个菜单添加的接口
export const menuAdd = data=>post('/menuadd',data)

五、实现菜单的添加接口调用

      this.$refs.menuForm.validate(async (flag) => {
        console.log(flag);
        if (flag) {
          //通过属性isAdd去区分 区分是添加还是编辑
          if (this.isAdd) {
            //添加接口
            // console.log(this.menuForm, "菜单的表单对象");
            // console.log("添加");
            let res = await menuAdd(this.menuForm);
            // console.log(res, "添加菜单");
            if(res.code==200){
              this.$message.success(res.msg)
              //添加成功之后关闭弹框
              this.cancel()
            }else{
              this.$message.error(res.msg)
            }
          } else {
            //调用编辑接口
            console.log("编辑");
          }
        } else {
          console.log("验证失败");
        }
      });

六、把列表拆分出去,因为添加,编辑,删除成功之后都需要重新获取列表,就是有很多地方都用到这个列表,然后把放到vuex中

注意:

当我们添加、编辑、删除成功之后我们要重新获取列表,同时添加菜单的上级菜单列表也要用到列表接口

我们发现很多组件和方法都用到了这个列表,我们准备把它放置在vuex中

//引入封装好的接口
import { menuList } from "../../../request/api";
const state = {
  menulist: [],
};

const getters = {
  getMenuList(state) {
    return state.menulist;
  },
};

const mutations = {
    REQ_MENULIST(state,payload){
        state.menulist = payload
    }
};

const actions = {
  async changeMenuAction({commit}) {
    let res = await menuList();
    // console.log(res, "菜单列表");
    commit('REQ_MENULIST',res.list)
  },
};

export default {
  state,
  getters,
  mutations,
  actions,
  //命名空间
  namespaced: true,
};
import Vue from 'vue'
import Vuex from 'vuex'
import menu from './modules/menu'

Vue.use(Vuex)

export default new Vuex.Store({
  modules: {
    menu
  }
})

在页面中使用vuex

//辅助性函数
import {mapGetters,mapActions} from 'vuex'
export default {
  computed:{
    ...mapGetters({
      getMenu:'menu/getMenuList'
    })
  },
  mounted() {
    this.getMenuList();
  },
  methods: {
    ...mapActions({
      getMenuList:'menu/changeMenuAction'
    }),
    //封装一个编辑事件用来告知父组件打开弹框
    edit() {
      this.$emit("edit");
    },
    //封装一个删除事件
    del() {
      this.$confirm("你确定要删除这条数据吗", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          console.log("准备调用删除接口");
        })
        .catch(() => {
          this.$message({
            type: "info",
            message: "已取消删除",
          });
        });
    },
  },
};

七、table树形结构

    <el-table row-key="id" 
    :tree-props="{children: 'children'}"
    default-expand-all
    :data="getMenu" border style="width: 100%">
    
    row-key	行数据的 Key,用来优化 Table 的渲染;在使用 reserve-selection 功能与显示树形数据时,该属性是必填的。类型为 String 时,支持多层访问:user.info.id,但不支持 user.info[0].id,此种情况请使用 Function。	
 default-expand-all	是否默认展开所有行,当 Table 包含展开行存在或者为树形表格时有效
  tree-props	渲染嵌套数据的配置选项

八、实现删除接口

          menuDel({
            id,
          }).then((res) => {
            if (res.code == 200) {
              this.$message.success(res.msg);
              //重新触发行动
              this.getMenuList();
            } else {
              this.$message.error(res.msg);
            }
          });

九、编辑数据回显

list页面

    //通过点击事件,然后子传父($emit),把id传过去
    edit(id) {
      this.$emit("edit",id);
    },

menu逻辑

      //封装一个列表的自定义事件
      edit(e){
        //打开弹框
        this.isShow = true
        //告诉弹框你是编辑
        this.isAdd = false
        // 通过ref 也可以控制子组件的事件,用子组件的封装好的回显函数
        this.$refs.digInfo.lookup(e)
        // console.log(e,'eeeeeeeee');
      }

弹框逻辑

    //获取一条数据的方法
    lookup(id) {
        传过来的id
      // console.log(id,'iiiiii');
    // 调用单条数据的接口 
      menuInfo({
        id,
      }).then((res) => {
        console.log(res, "一条数据");
        this.menuForm = res.list;
        this.menuForm.id = id;
      });
    },

十、实现编辑接口的调用

            //调用编辑接口
            console.log("编辑");
            let res = await menuEdit(this.menuForm);
            // console.log(res, "添加菜单");
            if (res.code == 200) {
              this.$message.success(res.msg);
              //添加成功之后关闭弹框
              this.cancel();
              //重新触发行动
              this.getMenu();
            } else {
              this.$message.error(res.msg);
            }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值