zoukankan      html  css  js  c++  java
  • Vue 表格自定义树形组件,行,列表可传入等

    1.组件,BaseTable 下有两个文件,index.vue ,extend.js

    index.vue代码

    <template>
      <div class="crud">
        <!--crud头部,包含列表标题和可操作按钮-->
        <el-row class="crud-header">
          <!--<el-col :span="8">{{formTitle}}列表</el-col>-->
          <el-col :span="24">
            <el-button type="success" size="mini" v-if="gridBtnConfig.create" @click="createOrUpdate(null)">
              <i class="el-icon-plus"></i> 新增
            </el-button>
    
            <!-- 标记为single的按钮不需要禁用,不依赖选择数据-->
            <el-button :disabled="!item.single && multipleSelection.length === 0" size="mini"
                       @click="handleEmit(item.emitName,'outer')"
                       v-for="(item,index) in outerButton" :key="index" :type="item.type?item.type:'primary'">
              <svg-icon v-if="item.icon" :icon-class="item.icon"></svg-icon>
              {{item.name}}
            </el-button>
            <el-button :disabled="multipleSelection.length === 0" size="mini" v-if="gridBtnConfig.delete" type="danger"
                       @click="remove(2)">
              <svg-icon icon-class="delete"></svg-icon>
              删除
            </el-button>
          </el-col>
        </el-row>
    
        <!--crud主体内容区,展示表格内容-->
        <el-table
          ref="multipleTable"
          v-loading="listLoading" element-loading-text="请等待"
          :data="showGridData"
          @selection-change="handleSelectionChange"
          border
          :stripe="true"
          :header-cell-style="{'textAlign':'center'}"
          style=" 100%">
          <el-table-column
            v-if="!hideMultiple"
            fixed="left"
            type="selection"
            width="55">
          </el-table-column>
          <el-table-column
            v-if="hideMultiple"
            fixed="left"
            label="序号"
            type="index"
            width="55">
          </el-table-column>
          <el-table-column
            v-for="(item,index) in gridConfig"
            :key="index"
            :prop="item.prop"
            :label="item.label"
            :align="nameLeft(item.label)"
            show-overflow-tooltip
            :width="item.width?item.''">
            <template slot-scope="scope">
              <span v-if="item.filter" ref="yifutian">{{walkProperty(item.prop,scope.row)||walkProperty(item.prop,scope.row)==0? item.filter(walkProperty(item.prop,scope.row)) : '--'}}</span>
              <Cell
                v-if="item.render"
                :row="scope.row"
                :column="item"
                :index="scope.$index"
                :render="item.render"></Cell>
              <span v-if="!item.render&&!item.filter">
                <span v-if="!item.template" ref="yifutian">{{walkProperty(item.prop,scope.row)||walkProperty(item.prop,scope.row)==0 ? walkProperty(item.prop,scope.row) : '--'}}</span>
                <a style="color: #1582cf;cursor: pointer;" v-else @click="handleEmit(item.emitName,'inner',scope.row)">{{walkProperty(item.prop,scope.row)||walkProperty(item.prop,scope.row)==0 ? walkProperty(item.prop,scope.row) : '--'}}</a>
              </span>
            </template>
          </el-table-column>
          <el-table-column v-if="!hideEditArea" label="操作" :width="gridEditWidth?gridEditWidth:200" fixed="right">
            <template slot-scope="scope">
              <el-tooltip v-if="gridBtnConfig.update" effect="dark" content="修改" placement="top">
                <span style="color: #409EFF" class="edit-icon" @click="createOrUpdate(scope.row)"><svg-icon
                  icon-class="xg"></svg-icon></span>
              </el-tooltip>
              <el-tooltip v-if="gridBtnConfig.view" effect="dark" content="查看" placement="top">
                <span style="color: #409EFF" class="edit-icon" @click="viewDetail(scope.row)"><svg-icon
                  icon-class="view"></svg-icon></span>
              </el-tooltip>
              <!--扩展按钮,如果扩展按钮设置了动态显示隐藏的条件,则需要根据条件显示隐藏-->
              <el-tooltip v-for="(item,index) in innerButton" :key="index" :type="item.type?item.type:'primary'"
                          v-if="(!item.hideJudge)||(item.hideJudge &&  walkProperty(item.hideJudge.key,scope.row) === item.hideJudge.val && (item.hideJudge.key2 ? walkProperty(item.hideJudge.key2,scope.row) === item.hideJudge.val2 : true))"
                          effect="dark" :content="item.name" placement="top">
                <span :style="{color:item.iconColor?item.iconColor:'#409EFF'}" class="edit-icon"
                      @click="handleEmit(item.emitName,'inner',scope.row)"><svg-icon
                  :icon-class="item.icon?item.icon:'xg'"></svg-icon></span>
              </el-tooltip>
              <el-tooltip v-if="gridBtnConfig.singleDelete" effect="dark" content="删除" placement="top">
                <span style="color: #F56C6C" class="edit-icon" @click="remove(1,scope.row)"><svg-icon
                  icon-class="delete"></svg-icon></span>
              </el-tooltip>
            </template>
          </el-table-column>
    
        </el-table>
    
        <!--crud的分页组件-->
        <div class="crud-pagination">
          <!--如果不是异步请求展示数据,需要隐藏分页-->
          <el-pagination
            v-if="isAsync"
            @size-change="handleSizeChange"
            @current-change="handleCurrentChange"
            :current-page="currentPage"
            :page-sizes="pageSizes?pageSizes:[10, 20, 30, 40]"
            :page-size="currentPageSize"
            layout="total, sizes, prev, pager, next, jumper"
            :total="dataTotal">
          </el-pagination>
        </div>
    
        <!--crud按钮触发的表单弹窗-->
        <BaseDialogForm :width="dialogWidth" :label-width="dialogLabelWidth" :title="dialogTitle" ref="dialogForm"
                        :config="formConfig"
                        :form-data="formModel"
                        @submit="dialogSubmit"></BaseDialogForm>
    
        <!--查看详情模态框-->
        <gx-dialog
          title="查看详情"
          :visible.sync="detailDialogVisible"
          :width="dialogWidth ? dialogWidth : '1300px'">
          <ViewDetail :config="infoConfig?infoConfig:formConfig" :data="detailData"></ViewDetail>
        </gx-dialog>
    
        <el-dialog
          title="提示"
          :close-on-click-modal="false"
          :visible.sync="deletess"
          width="400px">
          <i class="el-icon-info" style="color:#E6A23C;"></i>
          <span>此操作将永久删除数据, 是否继续?</span>
          <span slot="footer" class="dialog-footer">
             <el-button type="primary" @click="deletes" size="mini">确 定</el-button>
             <el-button @click="qxss" size="mini">取 消</el-button>
          </span>
        </el-dialog>
      </div>
    </template>
    
    <script>
      import BaseDialogForm from '@/components/BaseDialogForm/index.vue'
      import ViewDetail from '@/components/ViewDetail/index.vue'
      import GxDialog from "../GxDialog/index"
      /*用render渲染自定义template*/
      import Cell from './expand';
    
      export default {
        name: "base-crud",
        components: {
          BaseDialogForm,
          ViewDetail,
          GxDialog,
          Cell
        },
        props: [
          //
          'pageSizes',
          // 表单标题,例如用户、角色
          'formTitle',
          // 表单配置
          'formConfig',
          //详情的字段配置
          'infoConfig',
          // 表单的model数据
          'formData',
          // 表格配置
          'gridConfig',
          // 表格按钮配置
          'gridBtnConfig',
          // 表格死数据
          'gridData',
          // 数据接口
          'apiService',
          // 判断是否是异步数据
          'isAsync',
          //  表格编辑区域宽度
          'gridEditWidth',
          //  是否隐藏表格操作
          'hideEditArea',
          // 自定义新增和修改操作,覆盖组件内的新增和删除逻辑
          'selfCreateAndUpdate',
          //是否显示多选,若不显示多选,则显示列表序号
          'hideMultiple',
          //数据的id标识字符串
          'idKey',
          //表格获取数据默认传入的参数
          'gridParams',
          //
          'Update',
          //  禁止删除的条件配置
          'forbiddenData',
          //  操作的模态框宽度
          'dialogWidth',
          // 操作模态框中的表单label宽度
          'dialogLabelWidth',
          //  状态颜色区别配置数组:[[未处理],[已处理],[已过期],[其它状态]]
          'statusobj'
        ],
        data() {
          return {
            // 新增修改模态框title
            dialogTitle: '',
            // 展示的表格数据,数据来源可能是父组件传递的固定数据,可能是接口请求数据
            showGridData: [],
            // 当前页码
            currentPage: 1,
            // 每页显示数量
            currentPageSize: 10,
            // 列表数据总数
            dataTotal: 0,
            // 选中行数据
            selectedRow: '',
            // 表单数据
            formModel: {},
            //  保留多选的表格数据
            multipleSelection: [],
            //  扩展按钮,包括表格内按钮和表格外的批量操作按钮
            innerButton: [],
            outerButton: [],
            //  详情数据
            detailData: {},
            detailDialogVisible: false,
            //  是否是新增
            isCreate: true,
            // 数据加载
            listLoading: false,
            //  查询参数
            searchParams: {},
            //删除的数据
            ids: [],
            //删除的弹框
            deletess: false,
            color: true,
            statusObj: ''
          }
        },
        mounted() {
          //初始化扩展按钮
          if (this.gridBtnConfig.expands && this.gridBtnConfig.expands.length > 0) {
            //内部按钮,只操作单行数据
            this.innerButton = this.gridBtnConfig.expands.filter(item => item.editType === 'inner');
            //外部按钮,操作批量数据
            this.outerButton = this.gridBtnConfig.expands.filter(item => item.editType === 'outer');
          }
          this.getData();
          this.statusObj = this.statusobj ? this.statusobj : [['未提交'], ['已提交', '已批复', '审批通过', '待上报', '已批复', '已撤回'], ['审核中', '返回修改'], ['已上报', '待批复'], ['审批不通过']];
        },
        methods: {
          nameLeft(name) {
            let a = name.substr(name.length - 2, 2);
            // console.log(name.indexOf('名称'),a);
            if (a == '名称') {
              return 'left'
            } else {
              return 'center'
            }
          },
          // 获取列表数据
          getData() {
            this.listLoading = true;
            //没有定义api,直接返回,不进行请求
            if (!this.apiService) {
              this.listLoading = false;
              this.showGridData = this.gridData;
              return;
            }
            let params = {
              current: this.currentPage,
              size: this.currentPageSize
            };
    
            params = Object.assign({}, params, this.gridParams, this.searchParams);
    
            this.apiService.list(params).then(res => {
              this.showGridData = res.page.list;
              this.dataTotal = res.page.totalCount;
              this.listLoading = false;
              //请求数据完成
              this.$emit('getDataOver', res.page.list);
            });
          },
          //查询
          search(params) {
            this.currentPage = 1
            this.currentPageSize = 10
            this.searchParams = Object.assign({}, params);
            this.getData();
          },
          //清空查询
          clearSearch() {
            this.searchParams = {};
            this.getData();
          },
          // 查看详情
          viewDetail(row) {
            this.detailData = Object.assign({}, row);
            this.detailDialogVisible = true;
          },
          createOrUpdate(item) {
            // 如果配置了覆盖组件内新增和修改按钮时执行
            if (this.selfCreateAndUpdate) {
              this.$emit('createOrUpdate', item);
              return;
            }
    
            this.$refs.dialogForm.resetForm();
    
            this.formModel = item ? Object.assign({}, item) : Object.assign({}, this.formData);
            this.dialogTitle = (item ? '修改' : '新增') + this.formTitle;
            this.isCreate = !item;
    
            this.$refs.dialogForm.showDialog();
          },
          // 处理相应父组件的事件方法
          handleEmit(emitName, type, row) {
            // 如果是表格内按钮,只需要回传单行数据,表格外按钮,则需要回传批量数据
            if (type === 'inner') {
              this.$emit(emitName, row);
            }
            else {
              this.$emit(emitName, this.multipleSelection);
            }
          },
          handleCurrentChange(page) {
            this.currentPage = page;
            this.getData();
          },
          handleSizeChange(size) {
            this.currentPageSize = size;
            this.getData();
          },
          // 处理点击行
          handleRowClick(row, event, column) {
            this.selectedRow = Object.assign({}, row);
          },
          // 模态框数据提交
          dialogSubmit(data) {
            if (this.Update) {
              this.$emit('Update', data);
              return;
            }
            this.apiService[this.isCreate ? 'create' : 'update'](data).then(res => {
              this.$message.success(this.dialogTitle + '成功!');
              this.getData();
              this.$refs.dialogForm.hideDialog();
            })
          },
          hideDialog() {
            this.$refs.dialogForm.hideDialog();
          },
          //处理多选改变时
          handleSelectionChange(val) {
            this.multipleSelection = val;
          },
          // 切换当前行的选中状态
          toggleSelection(rows) {
            if (rows) {
              this.$nextTick(()=>{
                rows.forEach(row => {
                  this.$refs.multipleTable.toggleRowSelection(row);
                });
              })
            } else {
              this.$refs.multipleTable.clearSelection();
            }
          },
          //删除方法
          remove(type, data) {
            this.ids = [];
    
            //type为1代表单个删除,2代表批量删除
            if (type === 1) {
              this.ids = [data[this.idKey ? this.idKey : 'id']];
            } else {
              //如果上传了禁止删除的条件,进入下面条件处理
              if (this.forbiddenData) {
                let key = this.forbiddenData.key;
                let arr = this.forbiddenData.data;
    
                let boolean = false;
                this.multipleSelection.forEach(item => {
                  arr.forEach(val => {
                    if (val === item[key]) {
                      return (boolean = true);
                    }
                  });
                  //如果已经有禁止删除项,退出遍历,优化性能
                  if (boolean) {
                    return false;
                  }
                });
    
                if (boolean) {
                  return this.$notify({
                    title: '警告',
                    message: '您选择的数据包含禁止删除项,请重新选择数据进行删除!!!',
                    type: 'warning',
                    position: 'top-left',
                    duration: 2000
                  });
                }
              }
    
              this.ids = this.multipleSelection.map(item => item[this.idKey ? this.idKey : 'id']);
            }
    
            // this.$confirm('此操作将永久删除数据, 是否继续?', '提示', {
            //   showCancelButton: true,
            //   confirmButtonText: '确定',
            //   cancelButtonText: '取消',
            //   confirmButtonClass:'confirmButtonClass',
            //   type: 'warning'
            // }).then(() => {
            //   this.apiService.delete(ids).then(res => {
            //     this.$message({
            //       type: 'success',
            //       message: '删除成功!'
            //     });
            //
            //     this.getData();
            //   })
            // }).catch(() => {
            //   this.$message({
            //     type: 'info',
            //     message: '已取消删除'
            //   });
            //
            //
            // });
            this.deletess = true
          },
          deletes() {
            this.apiService.delete(this.ids).then(res => {
              this.$message({
                type: 'success',
                message: '删除成功!'
              });
    
              this.getData();
              this.deletess = false
            })
    
          },
          qxss() {
            this.deletess = false
            this.$message({
              type: 'info',
              message: '已取消删除'
            });
    
          },
    
          walkProperty(prop, data) {
            //a.b
            if (prop && prop.indexOf('.') !== -1) {
              let path = prop.split('.'), i, v = data;//[a, b]
              while (i = path.shift()) {
                if (v && v[i]) {
                  v = v[i];
                }
                else {
                  v = '';
                }
              }
              return v;
            }
            else {
              return data[prop];
            }
          },
          //清空多选
          clearSelection() {
            //清空多选的选中
            this.$refs.multipleTable && this.$refs.multipleTable.clearSelection();
          },
          shangse() {
            let i = 1;
            let elementArrays = this.$refs.yifutian;
            if (!elementArrays) {
              return;
            }
            this.statusObj.forEach(obj => {
              obj.forEach(obj2 => {
                elementArrays.forEach(item => {
                  let str = item.innerText;
                  if (str === obj2) {
                    item.setAttribute('class', 'class' + i);
                  }
                })
              });
              i++;
            });
          },
          setGridParams(data) {
            this.search(data);
          }
        },
        watch: {
          // 防止表格预置数据不成功,涉及生命周期问题
          gridData() {
            this.showGridData = this.gridData;
            this.dataTotal = this.showGridData.length;
          },
          showGridData: function () {
            this.$nextTick(function () {
              this.shangse();
            })
          }
        },
      }
    
    </script>
    <style rel="stylesheet/scss" lang="scss" scoped>
      .crud {
        .crud-header {
          margin-bottom: 10px;
          line-height: 40px;
        }
    
        .crud-pagination {
          text-align: right;
          margin-top: 10px;
        }
    
        /*表格内编辑图标*/
        .edit-icon {
          font-size: 20px;
          margin-right: 10px;
          cursor: pointer;
        }
        /*未处理*/
        .class1 {
          color: #999999;
          padding: 5px;
        }
        /*已处理*/
        .class2 {
          color: #06AC4D;
          padding: 5px;
        }
        /*已过期*/
        .class3 {
          color: #FBBE42;
          padding: 5px;
        }
        /*其它状态*/
        .class4 {
          color: #3DB5FC;
          padding: 5px;
        }
    
        .class5 {
          color: #FC5454;
          padding: 5px;
        }
      }
    </style>
    <style>
      .confirmButtonClass {
        color: #fff;
        background-color: #0597D2 !important;
        border-color: #0597D2 !important;
      }
    
    </style>

    --extend.js代码

    export default {
        name: 'TableExpand',
        functional: true,
        props: {
            row: Object,
            render: Function,
            index: Number,
            column: {
                type: Object,
                default: null
            }
        },
        render: (h, ctx) => {
            const params = {
                row: ctx.props.row,
                index: ctx.props.index
            };
            if (ctx.props.column) params.column = ctx.props.column;
            return ctx.props.render(h, params);
        }
    };

    2.以上是两个组件的代码,下面将介绍调用及传入数据的格式

    --调用组件

    引入组件,且注册组件

    import BaseTable from '@/components/BaseTable/index.vue'
    注册加入components
    components: {
          BaseTable
        },
    
    调用组件
    
     <BaseTable :api-service="informationApi" :grid-config="INFO_CONFIG.gridConfig"
                      :grid-btn-config="INFO_CONFIG.gridBtnConfig"
                      ref="crud" :grid-edit-width="80"
                      :is-async="true" :hide-edit-area="true">
            </BaseTable>
    
    传入数据的Js数据格式:
    
    const INFO_CONFIG = {
      gridConfig: [
        {label: '设备代码', prop: 'sbdm',  '150'},
        {label: '设备名称', prop: 'sbmc'},
        {label: '型号规格', prop: 'xh'},
        {label: '计量单位', prop: 'jldw', filter: equipmentUnitFilter},
        {label: '类型', prop: 'lx'},
        {label: '厂家', prop: 'cj'},
        {label: '是否是计量设备', prop: 'sfjlsb', filter: filterJLSB},
        {label: '筹供单位', prop: 'cgdw', filter: filterGCDW},
        {label: '使用年限(月)', prop: 'synx'},
      ],
      //操作按钮
      gridBtnConfig: {
        create: false, update: false, delete: false, view: false
      }
    }
    注意informationApi:是API 调用地址,如果需要直接传入数据,需要更组件中的逻辑,apiService传入true,不需要请求数据,出入gridData=[],即表格显示的数据,组件中传入的参数都写了注释,根据需做出更改吧
    关注博客,后期更新Vue表单组件。
  • 相关阅读:
    在navgationController中添加UISegmentedControl
    Static Const
    .pch头文件的添加
    数据库设计一对一多对多
    数据库链接
    File增删改查
    线程
    售票情景解读synchronized和Lock两种锁的区别
    [Spring Boot]使用自定义注解统一请求返回值
    JAVA希尔排序代码
  • 原文地址:https://www.cnblogs.com/wangliko/p/13223823.html
Copyright © 2011-2022 走看看