11

479 阅读5分钟

VUE项目-第十一天

01-反馈

姓名 意见或建议
*** 老师辛苦了
*** 老湿你在角色权限那关键部位(角色分配一二三级权限那儿)讲的有点快啊,跟不上咧

  • 代码:听不会 看不会 实践 敲一遍

02-回顾

  • 权限分配
    • 获取所有的权限 rightTree
    • 获取当前角色拥有的权限(不含父级,第三级) rightCheckedList
    • 默认选中拥有的权限
    • 修改权限:不能自动获取数据
    • 主动的去获取选中(包含半选)的权限:tree的dom上提供方法
    • getCheckedKeys getHalfCheckedKeys
    • 最后合并 提交 即可
  • 学习 jQuery (zepto.js) bootstrap vue element-ui
  • 树状控件
    • 数据格式:[{id:'',authName:'',children:[{children:[{},{}]},{}]},{},{}]
    • 显示label: props = {label:'authName'}
  • 树状表格
  • 级联选择器

03-分类参数-组件基础布局

<el-card>
  <el-alert
    title="注意:只有第三级分类才能设置参数。"
    type="warning"
    show-icon>
  </el-alert>
  <el-form style="margin: 15px 0">
    <el-form-item label="选择商品分类:">
      <el-cascader
        expand-trigger="hover"
        :options="categoryList"
        v-model="categoryValues"
        @change="handleChange">
      </el-cascader>
    </el-form-item>
  </el-form>
  <!-- activeName 就是当前选中的tab的name的值  -->
  <el-tabs v-model="activeName" @tab-click="handleClick">
    <el-tab-pane label="动态参数" name="many">
      <el-button type="success" :disabled="disabled">添加动态参数</el-button>
    </el-tab-pane>
    <el-tab-pane label="静态参数" name="only">
      <el-button type="success" :disabled="disabled">添加静态参数</el-button>
    </el-tab-pane>
  </el-tabs>
</el-card>

data () {
  return {
    // 分类级联相关的数据
    categoryList: [],
    categoryValues: [],
    // tabs相关的数据
    activeName: 'many',
    disabled: true
  }
},
methods: {
  handleChange () {
  }
}

04-分类参数-分类级联选择器

<el-cascader
  expand-trigger="hover"
  :options="categoryList"
  v-model="categoryValues"
  :props="{value:'cat_id',label:'cat_name'}"
  @change="handleChange">
</el-cascader>

async getData () {
  // 获取三级分类数据  且赋值给级联组件
  const {data: {data, meta}} = await this.$http.get('categories')
  if (meta.status !== 200) return this.$message.error('获取分类数据失败')
  console.log(data)
  this.categoryList = data
}

05-分类参数-获取参数列表准备

  • 需求:根据当前选中的tab去加载对应的(动态、静态)列表数据
  • 时机:选择了三级分类的时候,切换tab的时候 回去调用 getParams的函数获取参数列表
  • 细节:
    • 只有选择了三级分类才加载数据

    • 怎么通过传参的方式去区别动态还是静态 通过接口文档去判断

    • categories/:id/attributes id是三级分类的ID

    • 区别动态还是静态 :通过 sel 的参数 many动态 only静态

    • 发现:activeName 就是需要的数据

      getParams () { // 获取参数列表数据 获取的两种 // 传递的数据需要准备 三级分类ID 当前选中的参数类型 动态 静态 activeName // 三级分类ID 首先要判断是否有三级分类 const len = this.categoryValues.length if (len === 3) { // 选了三级 const id = this.categoryValues[len - 1] // 发请求获取数据 console.log(id) this.disabled = false } else { // 没选三级 // 清空当前不符合要求的选择 this.categoryValues = [] this.disabled = true } }

获取数据:

// 发请求获取数据
const {data: {data, meta}} = await this.$http.get(`categories/${id}/attributes`, {
  params: {sel: this.activeName}
})
if (meta.status !== 200) return this.$message.error('获取参数数据失败')
// 参数列表获取成功 显示列表 依赖数据  data定义数据
// 给谁赋值数据???  根据当前选中的tab去给  manyAttrs onlyAttrs 赋值
// 根据当前的 activeName 去找到对应的列表  赋值
this[`${this.activeName}Attrs`] = data

// 动态参数列表
manyAttrs: [],
// 静态参数列表
onlyAttrs: []

06-分类参数-渲染动态参数列表

<el-table :data="manyAttrs">
  <el-table-column type="expand">
    <template slot-scope="scope">
      <el-tag v-for="(item,i) in scope.row.attr_vals.split(',')" :key="i" size="normal" closable>{{item}}</el-tag>
    </template>
  </el-table-column>
  <el-table-column label="属性名称" prop="attr_name"></el-table-column>
  <el-table-column label="操作" width="120px">
    <template slot-scope="scope">
      <el-button icon="el-icon-edit" circle></el-button>
      <el-button icon="el-icon-delete" circle></el-button>
    </template>
  </el-table-column>
</el-table>

07-分类参数-渲染静态参数列表

<el-table :data="onlyAttrs">
  <el-table-column type="index" width="100px" align="center"></el-table-column>
  <el-table-column label="属性名称" prop="attr_name"></el-table-column>
  <el-table-column label="属性值">
    <template slot-scope="scope">
      <el-tag size="normal" style="width: 300px">{{scope.row.attr_vals}}</el-tag>
    </template>
  </el-table-column>
  <el-table-column label="操作" width="120px">
    <template slot-scope="scope">
      <el-button icon="el-icon-edit" circle></el-button>
      <el-button icon="el-icon-delete" circle></el-button>
    </template>
  </el-table-column>
</el-table>

08-分类参数-添加参数

  • 添加动态的参数 和 添加静态的参数 对话框可以使用同一个
  • 只是:标题不一致 提交时候参数的类型不一致

准备一个对话框:

<!-- 添加参数对话框 -->
<el-dialog :title="activeName==='many'?'添加动态参数':'添加静态参数'" width="400px" :visible.sync="addDialogFormVisible">
  <el-form ref="addForm" :model="addForm" :rules="addRules" label-width="100px" autocomplete="off">
    <el-form-item label="参数名称" prop="attr_name">
      <el-input v-model="addForm.attr_name"></el-input>
    </el-form-item>
  </el-form>
  <div slot="footer" class="dialog-footer">
    <el-button @click="addDialogFormVisible = false">取 消</el-button>
    <el-button type="primary" @click="addSubmit()">确 定</el-button>
  </div>
</el-dialog>

提交:

showAddDialog () {
  this.addDialogFormVisible = true
  this.$nextTick(() => {
    this.$refs.addForm.resetFields()
  })
},
addSubmit () {
  // 提交添加的参数
  this.$refs.addForm.validate(async valid =>{
    if (valid) {
      // 发请求
      // 获取第三级分类的ID
      const id = this.categoryValues[2]
      const {data: {meta}} = await this.$http.post(`categories/${id}/attributes`, {
        attr_name: this.addForm.attr_name,
        attr_sel: this.activeName
      })
      if (meta.status !== 201) return this.$message.error('添加参数失败')
      this.$message.success('添加参数成功')
      // 更新列表
      this.getParams()
      // 关闭对话框
      this.addDialogFormVisible = false
    }
  })
},

数据:

// 对话框相关数据
addDialogFormVisible: false,
addForm: {
  attr_name: ''
},
addRules: {
  attr_name: [
    {required: true, message: '参数名称必填', trigger: 'blur'}
  ]
}

09-分类参数-删除动态参数

11-分类参数-删除静态参数

  • 根据后台的要求 需要分类的ID 和参数的ID 并不需要参数类型
  • (动态 静态)删除方法是可以在一个函数实现

绑定事件

@click="delParams(scope.row.attr_id)"

// 删除参数
delParams (attrId) {
  this.$confirm('是否删除该参数?', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(async () => {
    // :id 传 分类的ID
    const id = this.categoryValues[2]
    // :attrid 就是当前的参数ID
    const {data: {meta}} = await this.$http.delete(`categories/${id}/attributes/${attrId}`)
    if (meta.status !== 200) return this.$message.error('删除参数失败')
    this.$message.success('删除参数成功')
    // 更新当前的列表
    this.getParams()
  }).catch(() => {})
},

10-分类参数-修改动态参数值

在进行功能开发之前:把之前的遍历方式改变一下,将来比较方便的去进行删除和添加

  • 不是直接使用 attr_vals 而是在js处理数据的时候 转换数组

  • 动态参数的值删除

    <el-tag @close="delTag(scope.row,i)" v-for="(item,i) in scope.row.attr_vals" :key="i" size="normal" closable>{{item}} +添加tag

具体js操作 依赖了计算属性:

// 计算属性:函数的名字就是一个数据的字段名称  使用和data中申明的数据一样
computed: {
  id: function () {
    // 为了严谨  程序更加健壮
    if (this.categoryValues.length === 3) {
      return this.categoryValues[2]
    } else {
      return null
    }
  }
},

// tag关闭事件
async delTag (row, i) {
  // 删除tag的效果  并没有真正的去修改后台的数据
  row.attr_vals.splice(i, 1)
  // 根据现在的arr去修改后台的参数的值
  const {data: {meta}} = await this.$http.put(`categories/${this.id}/attributes/${row.attr_id}`, {
    attr_name: row.attr_name,
    attr_sel: this.activeName,
    attr_vals: row.attr_vals.join(',')
  })
  if (meta.status !== 200) return this.$message.error('更新参数值失败')
  this.$message.success('更新参数值成功')
},
  • 动态参数的值添加
    • 实现 点击添加tag 去显示一个输入框 且 隐藏添加tag

    • input去获取焦点的时候 需要等input显示后去获取 $nextTick

    • 需要给每一行的input加ref属性 需要唯一 input+attr_id

    • 失去焦点 enter键 隐藏输入框 显示tag

      • @blur
      • @keyup.native.enter 注意会触发两次 当前的事件 失去焦点事件
      • native的意思:在组件上绑定的事件是组件的自定义事件,如果想触发原生的事件需要使用native
    • 发送数据 如果 输入的内容是空的 不让提交 (在提交数据后 清空当前输入框的内容)

      <el-tag v-show="!scope.row.inputShow" @click="showInput(scope.row)" :disable-transitions="true" class="w100" size="normal"> +添加tag <el-input v-model="scope.row.inputValue" @blur="hideInput(scope.row)" @keyup.native.enter="hideInput(scope.row)" :ref="'input'+scope.row.attr_id" v-show="scope.row.inputShow" class="w100 newInput">

      // 隐藏input事件 hideInput (row) { row.inputShow = false // 如果输入的内容为空 不能提交
      if (row.inputValue) { // 当前input输入的内容 追加到 attr_vals 中 row.attr_vals.push(row.inputValue) // 把修改好的数据给后台 this.editAttr(row) row.inputValue = '' } }, // 显示input的事件 showInput (row) { row.inputShow = true // dom.focus() 获取焦点 dom 当前行的input console.log(this.refs['input' + row.attr_id])
  this.nextTick(() => { this.refs['input' + row.attr_id].focus()
  })
},
// tag关闭事件
delTag (row, i) {
  // 删除tag的效果  并没有真正的去修改后台的数据
  row.attr_vals.splice(i, 1)
  // 把修改好的数据给后台
  this.editAttr(row)
},
async editAttr (row) {
  // 根据现在的arr去修改后台的参数的值
  const {data: {meta}} = await this.http.put(categories/${this.id}/attributes/${row.attr_id}, { attr_name: row.attr_name, attr_sel: this.activeName, attr_vals: row.attr_vals.join(',') }) if (meta.status !== 200) return this.message.error('更新参数值失败')
  this.message.success('更新参数值成功') },

12-分类参数-修改静态参数值

  • 功能点相同 当作练习

13-商品列表-路由级组件骨架

路由

{path: '/goods', name: 'goods', component: Goods}

组件骨架

<template>
  <div class="goods_container">
  </div>
</template>

<script>
import mixin from './Goods-Mixin'
export default {
  mixins: [mixin]
}
</script>

<style scoped>

</style>

14-商品列表-组件基础布局

15-商品列表-列表展示与分页

<el-breadcrumb separator-class="el-icon-arrow-right">
  <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
  <el-breadcrumb-item>商品管理</el-breadcrumb-item>
  <el-breadcrumb-item>商品列表</el-breadcrumb-item>
</el-breadcrumb>
<el-card>
  <el-row :gutter="20">
    <el-col :span="6">
      <el-input v-model="reqParams.query" placeholder="请输入内容">
        <el-button @click="search()" slot="append" icon="el-icon-search"></el-button>
      </el-input>
    </el-col>
    <el-col :span="18">
      <el-button type="primary"  plain>添加商品</el-button>
    </el-col>
  </el-row>
  <el-table :data="goodsList">
    <el-table-column type="index"></el-table-column>
    <el-table-column label="商品名称" width="300px" prop="goods_name"></el-table-column>
    <el-table-column label="价格" prop="goods_price"></el-table-column>
    <el-table-column label="重量" prop="goods_weight"></el-table-column>
    <el-table-column label="创建时间">
      <template slot-scope="scope">
        {{scope.row.add_time|ft}}
      </template>
    </el-table-column>
    <el-table-column label="操作">
      <template slot-scope="scope">
        <el-button icon="el-icon-edit" circle></el-button>
        <el-button icon="el-icon-delete" @click="delGoods(scope.row.goods_id)" circle></el-button>
      </template>
    </el-table-column>
  </el-table>
  <div class="pager_container">
    <el-pagination
      @current-change="changePager"
      :page-size="reqParams.pagesize"
      :current-page="reqParams.pagenum"
      background
      layout="prev, pager, next"
      :total="total">
    </el-pagination>
  </div>
</el-card>

data () {
  return {
    goodsList: [],
    reqParams: {
      query: '',
      pagenum: 1,
      pagesize: 5
    },
    total: 0
  }
},
mounted () {
  this.getData()
},
methods: {
  async getData () {
    const {data: {data, meta}} = await this.$http.get('goods', {params: this.reqParams})
    if (meta.status !== 200) return this.$message.error('获取商品信息失败')
    this.goodsList = data.goods
    this.total = data.total
  },
  changePager (newPage) {
    this.reqParams.pagenum = newPage
    this.getData()
  },

16-商品列表-搜索商品

<el-input v-model="reqParams.query" placeholder="请输入内容">
  <el-button @click="search()" slot="append" icon="el-icon-search"></el-button>
</el-input>

search () {
  this.reqParams.pagenum = 1
  this.getData()
},

17-商品列表-删除商品

<el-button icon="el-icon-delete" @click="delGoods(scope.row.goods_id)" circle></el-button>

delGoods (id) {
  this.$confirm('是否删除该商品?', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(async () => {
    // 发请求去删除
    const {data: {meta}} = await this.$http.delete(`goods/${id}`)
    if (meta.status !== 200) return this.$message.error('删除商品失败')
    this.$message.success('删除商品成功')
    this.getData()
  }).catch(() => {})
}