zoukankan      html  css  js  c++  java
  • 基于element-ui的后台系统表格、dialog、筛选、自定义按钮、分页的一次性封装

    方便基础业务开发封装的一套组件,基于vue2.5.x和element-ui,可以通过配置自动生成表格展示,表格新增、编辑功能、分页、筛选项、自定义显示表格数据等功能。

    先上演示图片

    ----------------------------------

    筛选部分

     

    -----------------------------------------------------------

    自定义按钮部分

     

    --------------------------------

    表格主体部分

     

     ------------

    整体效果

     

    以下为代码部分,都比较基础简单,就直接贴代码了

    分别有,baseTable,baseDialogForm,customDisplay,filterGroup  4个小组件组成

    baseTable部分(表格主体)

      1 <template>
      2     <div id="myTable">
      3         <filterGroup :filterList="filterConfig.filter_list" :search_list="filterConfig.search_list" v-on="{getFilterData:filterData}"></filterGroup>
      4         <div class="piliang">
      5             <router-link class="btn-link" v-for="item in topBtnConfig" :key="item.title" :to="item.jumpPage?item.jumpAddress:''">
      6                 <el-button type="primary" :icon="item.icon" v-if="item.jumpPage">{{item.title}}</el-button>
      7                 <el-button type="primary" :icon="item.icon" @click="createOrUpdate()" v-else>{{item.title}}</el-button>
      8             </router-link>
      9             <!-- 自定义显示 -->
     10             <customDisplay :customDisplayList="customDisplayList" v-on="{update_custom_display:updateCustomDisplay}"></customDisplay>
     11             <el-button class="float-right" @click="getData(true)" icon="el-icon-refresh" :loading="loading">更新数据</el-button>
     12         </div>
     13         <!--主体内容区,展示表格内容-->
     14         <el-table
     15             class="baseTable"
     16             :data="tableData"
     17             border
     18             size="small"
     19             v-loading="loading"
     20             tooltip-effect="dark"
     21             ref="table"
     22             @selection-change="handleSelectionChange"
     23         >
     24             <el-table-column type="selection" width="55" v-if="otherConfig.needSelect"></el-table-column>
     25             <el-table-column
     26                 v-for="(item,index) in tableConfig"
     27                 :key="index"
     28                 :prop="item.prop"
     29                 :label="item.label"
     30                 :width="item.width?item.''"
     31                 :min-width="item.minWidth?item.minWidth:''"
     32                 :sortable="item.sortable?true:false"
     33                 v-if="customDisplayList[index].show"
     34             >
     35                 <template slot-scope="scope">
     36                     <Cell v-if="item.render" :row="scope.row" :column="item" :index="scope.$index" :render="item.render"></Cell>
     37                     <span v-else>{{scope.row[item.prop]}}</span>
     38                 </template>
     39             </el-table-column>
     40             <el-table-column label="操作" v-if="tableBtnConfig.width" :width="tableBtnConfig.width" fixed="right" class-name="btns">
     41                 <template slot-scope="scope">
     42                     <!--扩展按钮-->
     43                     <el-button
     44                         @click="handleEmit(item.emitName, scope.row)"
     45                         v-if="tableBtnConfig.expands && tableBtnConfig.expands.length>0"
     46                         v-for="(item,index) in tableBtnConfig.expands"
     47                         :key="index"
     48                         :type="item.type?item.type:'primary'"
     49                     >{{item.name}}</el-button>
     50                     <el-button type="warning" v-if="tableBtnConfig.update&&!tableBtnConfig.isUpdateInNewPage" @click="createOrUpdate(scope.row)">编辑</el-button>
     51                     <el-button type="warning" v-else-if="tableBtnConfig.update&&tableBtnConfig.isUpdateInNewPage" @click="goTo(scope.row.id,tableBtnConfig.updateAddress)">编辑</el-button>
     52                     <el-button type="danger" v-if="tableBtnConfig.delete" @click.native="deleteItem(scope.row.id)">删除</el-button>
     53                 </template>
     54             </el-table-column>
     55         </el-table>
     56         <!-- 表格操作按钮 -->
     57         <div class="table-control-box">
     58             <el-button v-if="otherConfig.needSelect" type="info" @click="toggleSelection(tableData)">全选</el-button>
     59             <el-button v-if="otherConfig.needSelect" type="info" @click="batchDelete()">批量删除</el-button>
     60             <pagination class="float-right" :currentPaging="currentPaging" v-on="{sizeChange:handleSizeChange,currentChange:handleCurrentChange}"></pagination>
     61         </div>
     62         <!--按钮触发的表单弹窗-->
     63         <BaseDialogForm
     64             :title="dialogTitle"
     65             :width="formWidth"
     66             ref="dialogForm"
     67             :config="formConfig"
     68             :form-data="formModel"
     69             :err-form="formError"
     70             :is-edit="isEdit"
     71             @submit="dialogSubmit"
     72         ></BaseDialogForm>
     73     </div>
     74 </template>
     75 
     76 <script>
     77 import Cell from "./expand";
     78 import BaseDialogForm from "components/baseDialogForm";
     79 import customDisplay from "./customDisplay";
     80 // 分页
     81 import pagination from "components/pagination";
     82 import filterGroup from "components/filterGroup";
     83 
     84 export default {
     85     name: "baseTable",
     86     components: {
     87         Cell,
     88         BaseDialogForm,
     89         pagination,
     90         filterGroup,
     91         customDisplay
     92     },
     93     props: [
     94         // 表格配置
     95         "tableConfig",
     96         // 表格按钮配置
     97         "tableBtnConfig",
     98         // 数据接口
     99         "theApi",
    100         // 其他表格配置
    101         "otherConfig",
    102         // 上方按钮配置
    103         "topBtnConfig",
    104         // 筛选项配置
    105         "filterConfig",
    106         // 表单标题,例如用户、角色
    107         "formTitle",
    108         "formWidth",
    109         // 表单配置
    110         "formConfig",
    111         //  表格编辑区域宽度
    112         "gridEditWidth",
    113         // 表单的model数据
    114         "formData"
    115     ],
    116     data() {
    117         return {
    118             //  表格加载状态
    119             loading: false,
    120             // 表格展示数据
    121             tableData: [],
    122             multipleSelection: [],
    123             // 全选数据容器
    124             allSelect: false,
    125             // 筛选项
    126             filter_data: {},
    127             // 分页
    128             currentPaging: { currentPage: 1, pageSize: 10, totals: 0 },
    129             // 新增修改模态框title
    130             dialogTitle: "",
    131             // 表单数据
    132             formModel: {},
    133             // 后台输出错误信息
    134             formError: {},
    135             // 是否是编辑
    136             isEdit: false,
    137             // 自定义显示数据
    138             customDisplayList: []
    139         };
    140     },
    141     created() {
    142         this.getData();
    143         this.customInit(this.tableConfig);
    144     },
    145     methods: {
    146         // 根据表格配置生成自定义显示数组
    147         customInit: function(arr = []) {
    148             this.customDisplayList = arr.map(item => {
    149                 return {
    150                     show: true,
    151                     label: item.label
    152                 };
    153             });
    154         },
    155         // 获取列表数据
    156         getData: async function(update = false) {
    157             this.loading = true;
    158             // 默认数据
    159             let default_data = {
    160                 page: this.currentPaging.currentPage,
    161                 per_page: this.currentPaging.pageSize
    162             };
    163             // 筛选数据
    164             let data = Object.assign(default_data, this.filter_data);
    165             const res = await this.theApi.getData(data);
    166             this.loading = false;
    167             if (res.code === 200) {
    168                 update && this.$message.success("数据已更新");
    169                 const respon = res || {};
    170                 this.tableData = respon.data || []; // 给表格赋值
    171                 respon.total && (this.currentPaging.totals = respon.total);
    172             }
    173         },
    174         // 新增 编辑按钮
    175         createOrUpdate(item) {
    176             this.$refs.dialogForm.resetForm();
    177             item
    178                 ? this.getEditData(item.id, () => {
    179                         this.$refs.dialogForm.showDialog();
    180                   })
    181                 : this.$refs.dialogForm.showDialog();
    182             item ? (this.isEdit = true) : (this.isEdit = false);
    183             this.dialogTitle = (item ? "编辑" : "添加") + this.formTitle;
    184         },
    185         // 从后台获取编辑框需要的数据,表格只用作展示作用,所以不从表格内获取数据
    186         getEditData: async function(id, callback) {
    187             const res = await this.theApi.getEdit(id);
    188             if (res.code === 200) {
    189                 this.formModel = Object.assign({}, res.data[0] || {});
    190                 callback && callback();
    191             }
    192         },
    193         // 模态框数据提交
    194         dialogSubmit: async function(data) {
    195             // 根据是否有id判断是新增还是编辑
    196             const res = await this.theApi[data.id ? "editItem" : "addItem"](
    197                 data
    198             );
    199             if (res.code === 200) {
    200                 this.getData();
    201                 this.$message.success(this.dialogTitle + "成功!");
    202             } else {
    203                 // 在表单中输出错误提示
    204                 const errList = res.errors || "";
    205                 if (errList) {
    206                     for (let key in errList) {
    207                         errList[key] = errList[key][0];
    208                     }
    209                     this.formError = errList;
    210                 }
    211             }
    212         },
    213         // 处理相应父组件的事件方法
    214         handleEmit(emitName, row) {
    215             this.$emit(emitName, row);
    216         },
    217         // 编辑跳转页面
    218         goTo: function(id, url) {
    219             this.$router.push({
    220                 path: url,
    221                 query: { id: id }
    222             });
    223         },
    224         // 删除
    225         deleteItem: function(id) {
    226             this.$confirm("是否删除?", "提示", {
    227                 confirmButtonText: "确定",
    228                 cancelButtonText: "取消",
    229                 type: "warning"
    230             })
    231                 .then(() => {
    232                     //ajax
    233                     this.theApi.deleteItem({ id: id }).then(() => {
    234                         if (res.code === 200) {
    235                             this.$message.success("删除成功");
    236                             // 刷新数据
    237                             this.getData();
    238                         }
    239                     });
    240                 })
    241                 .catch(() => {
    242                     this.$message.info("取消删除");
    243                 });
    244         },
    245         // 批量删除
    246         batchDelete: function() {
    247             if (this.multipleSelection[0]) {
    248                 this.$confirm("是否删除选择的条目?", "提示", {
    249                     confirmButtonText: "确定",
    250                     cancelButtonText: "取消",
    251                     type: "warning"
    252                 })
    253                     .then(() => {
    254                         let data = this.multipleSelection;
    255                         //ajax
    256                     })
    257                     .catch(() => {
    258                         this.$message.info("取消删除");
    259                     });
    260             } else {
    261                 this.$message.error("请先选择要删除的条目");
    262             }
    263         },
    264         // 表格选择
    265         handleSelectionChange: function(val) {
    266             this.multipleSelection = val;
    267             this.allSelect = val.length === this.tableData.length;
    268         },
    269         // 全选按钮
    270         toggleSelection: function(rows) {
    271             if (rows && !this.allSelect) {
    272                 rows.forEach(row => {
    273                     this.$refs.table.toggleRowSelection(row, true);
    274                 });
    275             } else {
    276                 this.$refs.table.clearSelection();
    277             }
    278         },
    279         // 分页sizeChange
    280         handleSizeChange: function(val) {
    281             this.currentPaging.pageSize = val;
    282             this.currentPaging.currentPage = 1;
    283             // 更新数据
    284             this.getData();
    285         },
    286         // 分页currentChange
    287         handleCurrentChange: function(val) {
    288             this.currentPaging.currentPage = val;
    289             // 更新数据
    290             this.getData();
    291         },
    292         // 更新自定义显示组件数据
    293         updateCustomDisplay: function(arr) {
    294             this.customDisplayList = arr;
    295         },
    296         // 筛选
    297         filterData: function(obj) {
    298             this.tableData = [];
    299             this.filter_data = JSON.parse(JSON.stringify(obj));
    300             this.currentPaging.currentPage = 1;
    301             // 刷新数据
    302             this.getData();
    303         }
    304     }
    305 };
    306 </script>
    307 
    308 <style lang="less" scoped>
    309 @import "~assets/css/mixin.less";
    310 .baseTable {
    311      100%;
    312     margin: 0.55rem 0;
    313     /* 强制不换行 */
    314     .btns {
    315         .cell {
    316             white-space: nowrap;
    317         }
    318     }
    319     /deep/ thead {
    320         th {
    321             background: lighten(#ebeef5, 3%);
    322             color: #333;
    323             font-size: 14px;
    324         }
    325     }
    326     .icon-text {
    327         .iconfont {
    328             font-size: 14px;
    329             margin-right: 5px;
    330         }
    331     }
    332 }
    333 .table-control-box {
    334     overflow: hidden;
    335 }
    336 .piliang {
    337     margin: 0.55rem 0;
    338     position: relative;
    339     &::after {
    340         .clear;
    341     }
    342     .btn-link {
    343         margin-right: 10px;
    344         float: left;
    345     }
    346     .el-button {
    347         margin-left: 0;
    348     }
    349 }
    350 </style>
    View Code

    customDisplay部分(自定义显示按钮)

      1 <template>
      2     <div id="customDisplay" class="float-left">
      3         <el-button type size="mini" class="float-left" icon="el-icon-setting" @click="customDisplayShow = !customDisplayShow">自定义显示</el-button>
      4         <div class="custom-display-dialog float-left" v-if="customDisplayShow">
      5             <ul class="custom-display-dialog-list">
      6                 <li class="item title">当前展示的信息</li>
      7                 <li class="item">
      8                     <el-checkbox v-model="checkedAll" @change="selectAll">全选</el-checkbox>
      9                 </li>
     10                 <li class="item" v-for="(item,index) in list" :key="index">
     11                     <el-checkbox v-model="item.show" @change="select">{{item.label}}</el-checkbox>
     12                 </li>
     13             </ul>
     14             <!-- model -->
     15             <div class="model" @click="customDisplayShow = false"></div>
     16         </div>
     17     </div>
     18 </template>
     19 
     20 <script>
     21 export default {
     22     // 自定义选择组件
     23     name: "customDisplay",
     24     data() {
     25         return {
     26             customDisplayShow: false,
     27             checkedAll: true,
     28             list: []
     29         };
     30     },
     31     props: ["customDisplayList"],
     32     created: function() {
     33         this.customDisplayList &&
     34             (this.list = JSON.parse(JSON.stringify(this.customDisplayList)));
     35     },
     36     methods: {
     37         // 全选
     38         selectAll: function() {
     39             this.list.map(item => {
     40                 item.show = this.checkedAll;
     41             });
     42             this.$emit("update_custom_display", this.list);
     43         },
     44         // 单选
     45         select: function() {
     46             let _list = this.list;
     47             for (let i = 0; i < _list.length; i++) {
     48                 if (!_list[i].show) {
     49                     this.checkedAll = false;
     50                     break;
     51                 } else {
     52                     this.checkedAll = true;
     53                 }
     54             }
     55             this.$emit("update_custom_display", this.list);
     56         }
     57     }
     58 };
     59 </script>
     60 <style lang="less" scoped>
     61 @import "~assets/css/mixin.less";
     62 #customDisplay {
     63     margin-right: 10px;
     64     .custom-display-dialog {
     65         margin-left: 10px;
     66         position: relative;
     67         z-index: 2200;
     68         .custom-display-dialog-list {
     69             position: absolute;
     70             z-index: 998;
     71             padding: 10px 20px;
     72             background: #fff;
     73             border: 1px solid #ccc;
     74             border-radius: 4px;
     75             box-shadow: 0 0 30px rgba(0, 0, 0, 0.15);
     76             .item {
     77                 margin: 2px 0;
     78                 .el-checkbox {
     79                     display: block;
     80                 }
     81             }
     82             .title {
     83                 font-size: 16px;
     84                 white-space: nowrap;
     85                 margin-bottom: 10px;
     86                 color: #888;
     87                 padding-right: 5px;
     88             }
     89         }
     90         .model {
     91              100%;
     92             height: 100%;
     93             position: fixed;
     94             top: 0;
     95             left: 0;
     96             z-index: 997;
     97         }
     98     }
     99 }
    100 </style>
    View Code

    baseDialogForm部分(基于表格的弹出框表单)

      1 <template>
      2     <el-dialog :title="title" :visible.sync="dialogVisible" :width="width?'80%'">
      3         <el-form :model="formModel" ref="configForm" label-width="100px">
      4             <el-row :gutter="16">
      5                 <el-col :span="item.span?item.span:8" v-for="(item,index) in config" :key="index">
      6                     <el-form-item :prop="item.prop" :rules="item.rules" :label="item.label">
      7                         <!--输入框表单类型-->
      8                         <el-input
      9                             v-if="item.type === 'text' || item.type === 'password' || item.type === 'textarea'"
     10                             :type="item.type"
     11                             v-model="formData[item.prop]"
     12                             :placeholder="item.placeholder?item.placeholder:'请输入'"
     13                         ></el-input>
     14                         <!-- 计数器 -->
     15                         <el-input-number v-if="item.type === 'el-input-number'" v-model="formData[item.prop]" :min="1" :step="1" label="描述文字"></el-input-number>
     16                         <!--checkbox表单类型-->
     17                         <el-checkbox-group v-if="item.type === 'checkbox'" v-model="formData[item.prop]" :placeholder="item.placeholder?item.placeholder:'请选择'">
     18                             <el-checkbox v-for="option in item.data" :label="option.id" :key="option.id">{{option.name}}</el-checkbox>
     19                         </el-checkbox-group>
     20                         <!--radio表单类型-->
     21                         <el-radio-group v-if="item.type === 'radio'" v-model="formData[item.prop]" :placeholder="item.placeholder?item.placeholder:'请选择'">
     22                             <el-radio v-for="option in item.data" :label="option.id" :key="option.id">{{option.name}}</el-radio>
     23                         </el-radio-group>
     24                         <!--下拉选择类型-->
     25                         <el-select v-if="item.type === 'select'" v-model="formData[item.prop]" :placeholder="item.placeholder?item.placeholder:'请选择'">
     26                             <el-option v-for="option in item.data" :key="option.id" :label="option.label" :value="option.id"></el-option>
     27                         </el-select>
     28                         <el-date-picker v-if="item.type === 'datepicker'" v-model="formData[item.prop]" type="date" :placeholder="item.placeholder?item.placeholder:'请选择日期'"></el-date-picker>
     29                     </el-form-item>
     30                 </el-col>
     31             </el-row>
     32         </el-form>
     33 
     34         <span slot="footer" class="dialog-footer">
     35             <el-button @click="dialogVisible = false">取 消</el-button>
     36             <el-button type="primary" @click="submitForm(formModel)">确 定</el-button>
     37         </span>
     38     </el-dialog>
     39 </template>
     40 
     41 <script>
     42 export default {
     43     name: "base-dialog-form",
     44     props: [
     45         "title",
     46         "width",
     47         "visible",
     48         "config",
     49         "formData",
     50         "errForm",
     51         "isEdit"
     52     ],
     53     data() {
     54         return {
     55             formModel: {},
     56             dialogVisible: false,
     57             dialogTitle: ""
     58         };
     59     },
     60     mounted() {
     61         // 将组件上的属性赋值给当前组件内变量,因为props只能单向绑定,还需要监听属性值变化进行父子组件间交互
     62         this.formModel = this.formData;
     63         this.dialogVisible = this.visible;
     64         this.dialogTitle = this.title;
     65     },
     66     methods: {
     67         // 提交表单数据
     68         submitForm(obj) {
     69             console.log(obj);
     70             this.$refs.configForm.validate(valid => {
     71                 if (valid) {
     72                     // 让父组件接收到响应数据
     73                     this.$emit("submit", this.formModel);
     74                     // 关闭模态框
     75                     this.dialogVisible = false;
     76                 } else {
     77                     return false;
     78                 }
     79             });
     80         },
     81         // 重置表单状态
     82         resetForm() {
     83             if (this.$refs.configForm) {
     84                 this.$refs.configForm.resetFields();
     85             }
     86         },
     87         // 展示模态框
     88         showDialog() {
     89             this.dialogVisible = true;
     90         }
     91     },
     92     watch: {
     93         /*实现表单数据的绑定,实时接收父组件的数据变化*/
     94         formData() {
     95             this.formModel = this.formData;
     96         }
     97     }
     98 };
     99 </script>
    100 
    101 <style lang="less" scoped>
    102 .el-input {
    103      100% !important;
    104 }
    105 
    106 .el-select {
    107      100% !important;
    108 }
    109 </style>
    View Code

    filterGroup部分(表格上方筛选项集合)

      1 <template>
      2     <div id="filterGroup">
      3         <div class="filter-container" :class="{'opened':open,'big':open_btn_show}">
      4             <!-- 筛选项 -->
      5             <el-form :inline="true" id="formBox" ref="filterForm">
      6                 <el-form-item label="关键字:" v-if="filterOptions.search">
      7                     <el-input v-popover:popover v-model="filterData.keyword" @keyup.enter.native="getFilterData()" placeholder="请输入关键字" clearable></el-input>
      8                     <el-popover ref="popover" placement="bottom" width="200" trigger="focus" popper-class="search-popover">
      9                         <div v-if="search_list[0]">
     10                             <p class="popover-title">支持的搜索条件</p>
     11                             <ul class="popover-list">
     12                                 <li class="popover-item" v-for="(item, index) in search_list" :key="index">{{item}}</li>
     13                             </ul>
     14                         </div>
     15                         <span v-else>暂无可搜索项</span>
     16                     </el-popover>
     17                 </el-form-item>
     18                 <el-form-item label="分类:" v-if="filterOptions.classify">
     19                     <el-select v-model="filterData.classify">
     20                         <el-option v-for="(item,index) in classifyList" :key="item.value" :label="item.label" :value="item.value"></el-option>
     21                     </el-select>
     22                 </el-form-item>
     23                 <el-form-item label="年份:" v-if="filterOptions.year">
     24                     <el-select v-model="filterData.year">
     25                         <el-option v-for="(item,index) in years" :key="index" :label="item" :value="item"></el-option>
     26                     </el-select>
     27                 </el-form-item>
     28                 <el-form-item label="激活状态:" v-if="filterOptions.activation">
     29                     <el-select v-model="filterData.activation">
     30                         <el-option v-for="(item,index) in activationList" :key="index.value" :label="item.label" :value="item.value"></el-option>
     31                     </el-select>
     32                 </el-form-item>
     33                 <el-form-item label="审核状态:" v-if="filterOptions.examine">
     34                     <el-select v-model="filterData.examine">
     35                         <el-option v-for="(item,index) in examineList" :key="index.value" :label="item.label" :value="item.value"></el-option>
     36                     </el-select>
     37                 </el-form-item>
     38                 <el-form-item label="操作人:" v-if="filterOptions.operator">
     39                     <el-select v-model="filterData.operator">
     40                         <el-option v-for="(item,index) in operatorList" :key="index.value" :label="item.label" :value="item.value"></el-option>
     41                     </el-select>
     42                 </el-form-item>
     43                 <el-form-item label="事件:" v-if="filterOptions.event">
     44                     <el-select v-model="filterData.event">
     45                         <el-option v-for="(item,index) in eventList" :key="index.value" :label="item.label" :value="item.value"></el-option>
     46                     </el-select>
     47                 </el-form-item>
     48                 <el-form-item label="影片推荐:" v-if="filterOptions.recommend">
     49                     <el-cascader :options="recommendList" v-model="filterData.recommend" style="100%;"></el-cascader>
     50                 </el-form-item>
     51                 <el-form-item label="日期:" v-if="filterOptions.date_scope" class="date-filter">
     52                     <el-date-picker
     53                         v-model="filterData.date_scope"
     54                         type="daterange"
     55                         align="right"
     56                         unlink-panels
     57                         range-separator="至"
     58                         start-placeholder="开始日期"
     59                         end-placeholder="结束日期"
     60                         format="yyyy-MM-dd"
     61                         value-format="yyyy-MM-dd"
     62                     ></el-date-picker>
     63                 </el-form-item>
     64                 <el-form-item :class="open_btn_show?'btn':''" v-if="!sure">
     65                     <el-button type="primary" @click="getFilterData()">查 询</el-button>
     66                     <el-button
     67                         v-if="open_btn_show"
     68                         type="primary"
     69                         plain
     70                         @click="open = !open;btn_text = !open?'展开':'收起'"
     71                         :icon="!open?'el-icon-arrow-down':'el-icon-arrow-up'"
     72                     >{{btn_text}}</el-button>
     73                 </el-form-item>
     74                 <el-form-item v-else>
     75                     <el-button type="primary" @click="getFilterData()">确 定</el-button>
     76                 </el-form-item>
     77             </el-form>
     78         </div>
     79         <!-- 筛选结果项 -->
     80         <div class="filter-result-container" v-if="filter_arr[0]">
     81             <ul class="list">
     82                 <li class="item filter-text">
     83                     <i class="iconfont icon-filter"></i>
     84                     <span>检索项:</span>
     85                 </li>
     86                 <li class="item" v-for="item in filter_arr" :key="item.key" v-if="item.title">
     87                     <el-tag :closable="canClearFilter !== false" size="small" class="tag" @close="closeTag(item)">{{`${item.title} : ${item.value}`}}</el-tag>
     88                 </li>
     89                 <li class="item filter-text clearAll" @click="closeAllTag" v-if="showClearAllBtn !== false">清空</li>
     90             </ul>
     91         </div>
     92     </div>
     93 </template>
     94 
     95 <script>
     96 // css
     97 import "components/filterGroup/style.css";
     98 
     99 export default {
    100     // 筛选项
    101     name: "filterGroup",
    102     data() {
    103         return {
    104             // 布局状态
    105             menuType: 1,
    106             contentWidthType: "流式",
    107             isCollapse: false, // 导航是否折叠
    108             open: false,
    109             btn_text: "展开",
    110             open_btn_show: false,
    111             // 映射表
    112             filterOptions: {
    113                 search: false, // 关键字搜索
    114                 classify: false, // 分类
    115                 year: false, // 年份
    116                 activation: false, // 激活状态
    117                 examine: false, // 审核状态
    118                 recommend: false, // 影片推荐
    119                 operator: false, // 操作人
    120                 event: false, // 事件
    121                 date_scope: false // 日期选择范围
    122             },
    123             // 点击查询之后传到父级的筛选项数据
    124             filterData: {},
    125             // 筛选项数组
    126             filter_arr: [],
    127             // 分类
    128             classifyList: [],
    129             // 年份
    130             years: [],
    131             // 激活状态
    132             activationList: [
    133                 {
    134                     value: 1,
    135                     label: "已激活"
    136                 },
    137                 {
    138                     value: -1,
    139                     label: "未激活"
    140                 }
    141             ],
    142             // 审核状态
    143             examineList: [
    144                 {
    145                     value: 1,
    146                     label: "已通过"
    147                 },
    148                 {
    149                     value: 0,
    150                     label: "未审核"
    151                 },
    152                 {
    153                     value: -1,
    154                     label: "驳回"
    155                 }
    156             ],
    157             // 影片推荐
    158             recommendList: [],
    159             // 操作人
    160             operatorList: [],
    161             // 事件
    162             eventList: []
    163         };
    164     },
    165     props: {
    166         // 筛选项配置 外部传入
    167         filterList: Array,
    168         search_list: Array, // 搜索框支持的搜索项
    169         sure: true,
    170         showClearAllBtn: true, // 是否显示清空按钮
    171         canClearFilter: true // 是否能清除单个筛选
    172     },
    173     watch: {
    174         listenContentWidthType(newVal) {
    175             this.contentWidthType = newVal;
    176             this.showBtn();
    177         },
    178         listenMenuType(newVal) {
    179             this.menuType = newVal;
    180             this.showBtn();
    181         },
    182         listenMenuCollapse(newVal) {
    183             this.isCollapse = newVal;
    184             this.showBtn();
    185         }
    186     },
    187     computed: {
    188         listenContentWidthType() {
    189             return this.$store.state.contentWidthType;
    190         },
    191         listenMenuType() {
    192             return this.$store.state.menuType;
    193         },
    194         listenMenuCollapse() {
    195             return this.$store.state.menuCollapse;
    196         },
    197         role() {
    198             return this.$store.state.role;
    199         }
    200     },
    201     created: function() {
    202         // 匹配显示
    203         for (let key in this.filterOptions) {
    204             for (let k in this.filterList) {
    205                 if (this.filterList[k] == key) {
    206                     this.filterOptions[key] = true;
    207                 }
    208             }
    209         }
    210     },
    211     mounted: function() {
    212         const that = this;
    213         // 首页带参数筛选
    214         let default_filter = function() {
    215             // 首页带参数的跳转
    216             if (that.$route.query.show_filter === "1") {
    217                 if (that.open_btn_show) {
    218                     that.open = true;
    219                     that.btn_text = "收起";
    220                 }
    221                 let homePageFilterObj = {};
    222                 that.filterData = homePageFilterObj;
    223                 that.$emit("getFilterData", that.filterData);
    224                 that.initFilter(that.filterData);
    225             }
    226         };
    227         that.showBtn(default_filter);
    228     },
    229     methods: {
    230         // 判断是否需要显示展开收起按钮
    231         showBtn: function(callback) {
    232             // 加上300的延时 因为css切换的过渡时间是.3s
    233             setTimeout(() => {
    234                 const formContainer = document.getElementById("formBox");
    235                 this.open_btn_show =
    236                     formContainer.clientHeight > 50 ? true : false;
    237                 // 回调函数
    238                 callback && callback();
    239             }, 310);
    240         },
    241         // 传递筛选数据
    242         getFilterData() {
    243             let obj = this.filterData;
    244             for (let key in obj) {
    245                 if (obj[key] === "" || obj[key] === null) {
    246                     delete obj[key];
    247                 } else {
    248                     if (key === "date_scope") {
    249                         // 拆分数组
    250                         const [exam_start_time, exam_end_time] = obj[key];
    251                         Object.assign(
    252                             obj,
    253                             { exam_start_time },
    254                             { exam_end_time }
    255                         );
    256                     }
    257                 }
    258             }
    259             this.$emit("getFilterData", obj);
    260             this.initFilter(obj);
    261         },
    262         // 生成筛选项列表数据
    263         initFilter: function(filterList = {}) {
    264             const filter_list = filterList;
    265             let arr = [];
    266             for (let key in filter_list) {
    267                 if (
    268                     filter_list[key] !== "" &&
    269                     filter_list[key] !== undefined &&
    270                     filter_list[key] !== null
    271                 ) {
    272                     arr.push({
    273                         key: key,
    274                         title: this.filterMap(key, filter_list[key]).title,
    275                         value: this.filterMap(key, filter_list[key]).value
    276                     });
    277                 }
    278             }
    279             this.filter_arr = arr;
    280         },
    281         // 筛选项列表字典
    282         filterMap: function(theKey = "", theValue) {
    283             const key = theKey;
    284             const val = theValue;
    285             let item = {};
    286             switch (key) {
    287                 case "keyword":
    288                     item.title = "关键字";
    289                     item.value = val;
    290                     break;
    291                 case "date_scope":
    292                     item.title = "日期";
    293                     item.value = `${val[0]} - ${val[1]}`;
    294                     break;
    295                 case "activation":
    296                     item.title = "激活状态";
    297                     item.value = this.arrayMapFilter(
    298                         this.activationList,
    299                         val
    300                     ).label;
    301                     break;
    302                 default:
    303                     item = {};
    304             }
    305             return item;
    306         },
    307         // 筛选项字典内filter
    308         arrayMapFilter: function(list = [], value = "") {
    309             const arr = JSON.parse(JSON.stringify(list));
    310             let val = value;
    311             arr.filter(el => {
    312                 if (el.value == val) {
    313                     val = el;
    314                 }
    315             });
    316             return val;
    317         },
    318         // 关闭筛选
    319         closeTag: function(item) {
    320             let key = item.key;
    321             // 关联字段清除
    322             if (item.key == "agent_id") {
    323                 //
    324             } else {
    325                 delete this.filterData[key];
    326             }
    327             this.getFilterData();
    328         },
    329         // 清空筛选
    330         closeAllTag: function() {
    331             this.filterData = {};
    332             this.getFilterData();
    333         }
    334     }
    335 };
    336 </script>
    View Code

    页面调用

      1 <template>
      2     <div id="member_list">
      3         <!-- 表格 -->
      4         <baseTable
      5             :theApi="table_ajax"
      6             :table-config="configData.tableConfig"
      7             :top-btn-config="configData.topBtnConfig"
      8             :table-btn-config="configData.tableBtnConfig"
      9             :other-config="configData.otherConfig"
     10             :filter-config="configData.filterConfig"
     11             :grid-edit-width="200"
     12             form-title="会员"
     13             form-width="40%"
     14             :form-config="configData.formConfig"
     15             :form-data="configData.formModel"
     16             @checkRegistration="checkRegistration"
     17             ref="basetable"
     18         ></baseTable>
     19     </div>
     20 </template>
     21 <script>
     22 // api
     23 import * as theApi from "api/enroll/member_list";
     24 import baseTable from "components/baseTable";
     25 // 类型验证
     26 import { checkActivation, checkEntry } from "utils/checkTypes";
     27 // 表单验证
     28 import { checkUserName } from "utils/verify";
     29 export default {
     30     name: "member_list",
     31     data() {
     32         return {
     33             //表格配置
     34             configData: {
     35                 // 其他配置
     36                 otherConfig: {
     37                     needSelect: true // 是否可以多选
     38                 },
     39                 // 表格数据配置
     40                 tableConfig: [
     41                     { label: "ID", prop: "id",  "70" },
     42                     { label: "用户名", prop: "username" },
     43                     { label: "昵称", prop: "nickname" },
     44                     { label: "注册时间", prop: "datetime", sortable: true },
     45                     {
     46                         label: "会员激活状态",
     47                         prop: "member_type",
     48                         render: (h, params) => {
     49                             const { color, text, icon } = checkActivation(
     50                                 params.row.member_type
     51                             );
     52                             return (
     53                                 <div class="icon-text">
     54                                     <i
     55                                         class={`iconfont icon-${icon}`}
     56                                         style={`color:${color}`}
     57                                     />
     58                                     <span style={`color:${color}`}>{text}</span>
     59                                 </div>
     60                             );
     61                         }
     62                     },
     63                     {
     64                         label: "D20报名状态",
     65                         prop: "d20_type",
     66                         render: (h, params) => {
     67                             const { color, text, icon } = checkEntry(
     68                                 params.row.d20_type
     69                             );
     70                             return (
     71                                 <div class="icon-text">
     72                                     <i
     73                                         class={`iconfont icon-${icon}`}
     74                                         style={`color:${color}`}
     75                                     />
     76                                     <span style={`color:${color}`}>{text}</span>
     77                                 </div>
     78                             );
     79                         }
     80                     },
     81                     {
     82                         label: "IDF创投报名状态",
     83                         prop: "idf_type",
     84                         render: (h, params) => {
     85                             const { color, text, icon } = checkEntry(
     86                                 params.row.idf_type
     87                             );
     88                             return (
     89                                 <div class="icon-text">
     90                                     <i
     91                                         class={`iconfont icon-${icon}`}
     92                                         style={`color:${color}`}
     93                                     />
     94                                     <span style={`color:${color}`}>{text}</span>
     95                                 </div>
     96                             );
     97                         }
     98                     }
     99                 ],
    100                 // 表格内按钮配置
    101                 tableBtnConfig: {
    102                      245, //宽度
    103                     update: true, // 编辑
    104                     delete: true, // 删除
    105                     expands: [
    106                         {
    107                             name: "查看报名",
    108                             emitName: "checkRegistration",
    109                             type: "primary"
    110                         }
    111                     ]
    112                 },
    113                 // 表格上方按钮配置
    114                 topBtnConfig: [
    115                     {
    116                         title: "添加会员",
    117                         icon: "el-icon-circle-plus"
    118                     }
    119                 ],
    120                 // 筛选组件配置
    121                 filterConfig: {
    122                     filter_list: ["search", "year", "activation"],
    123                     search_list: ["用户名", "昵称"]
    124                 },
    125                 // table的模态框表单配置,可配置表单类型,验证规则,是否必填,col-span布局可通过span参数配置
    126                 formConfig: [
    127                     {
    128                         span: 24,
    129                         label: "用户名",
    130                         prop: "username",
    131                         type: "text",
    132                         rules: {
    133                             required: true,
    134                             validator: checkUserName,
    135                             trigger: "blur"
    136                         }
    137                     },
    138                     {
    139                         span: 24,
    140                         label: "昵称",
    141                         prop: "nickname",
    142                         type: "text",
    143                         rules: {
    144                             required: true,
    145                             message: "请输入昵称",
    146                             trigger: "blur"
    147                         }
    148                     },
    149                     {
    150                         span: 24,
    151                         label: "密码",
    152                         prop: "password",
    153                         type: "password",
    154                         rules: {
    155                             required: true,
    156                             validator: (rule, value, callback) => {
    157                                 const is_edit = this.$refs.basetable.$refs
    158                                     .dialogForm.isEdit; // 判断当前是编辑还是新增
    159                                 const reg = /^[0-9a-zA-Z_]{6,15}$/; //6-15位数字字母下划线
    160                                 if (!value) {
    161                                     if (!is_edit) {
    162                                         callback(new Error("密码不能为空"));
    163                                     } else {
    164                                         callback(); //可为空
    165                                     }
    166                                 } else if (reg.test(value) == false) {
    167                                     callback(
    168                                         new Error(
    169                                             "密码必须为6~15位,英文与数字或下划线组合"
    170                                         )
    171                                     );
    172                                 } else {
    173                                     callback();
    174                                 }
    175                             },
    176                             trigger: "blur"
    177                         }
    178                     },
    179                     {
    180                         span: 24,
    181                         label: "确认密码",
    182                         prop: "checkpassword",
    183                         type: "password",
    184                         rules: {
    185                             required: true,
    186                             validator: (rule, value, callback) => {
    187                                 const psd = this.$refs.basetable.$refs
    188                                     .dialogForm.formModel.password; // 输入的密码
    189                                 const is_edit = this.$refs.basetable.$refs
    190                                     .dialogForm.isEdit; // 判断当前是编辑还是新增
    191                                 const reg = /^[0-9a-zA-Z_]{6,15}$/; //6-15位数字字母下划线
    192                                 if (!value) {
    193                                     if (!is_edit) {
    194                                         callback(new Error("密码不能为空"));
    195                                     } else {
    196                                         callback(); //可为空
    197                                     }
    198                                 } else if (reg.test(value) == false) {
    199                                     callback(
    200                                         new Error(
    201                                             "密码必须为6~15位,英文与数字或下划线组合"
    202                                         )
    203                                     );
    204                                 } else if (value !== psd) {
    205                                     callback(new Error("两次输入密码不一致!"));
    206                                 } else {
    207                                     callback();
    208                                 }
    209                             },
    210                             trigger: "blur"
    211                         }
    212                     }
    213                 ],
    214                 // 表单基础数据类型,需要预先赋值
    215                 formModel: {
    216                     username: "",
    217                     nickname: "",
    218                     password: "",
    219                     checkpassword: ""
    220                 }
    221             },
    222             // ajax
    223             table_ajax: theApi
    224         };
    225     },
    226     components: { baseTable },
    227     methods: {
    228         checkRegistration: function(row = {}) {
    229             this.$router.push({
    230                 path: "/pages/index/enroll/entry/list",
    231                 query: { id: row.id }
    232             });
    233         }
    234     }
    235 };
    236 </script>
  • 相关阅读:
    django 单表操作
    爬虫学习
    DRF源码分析
    DRF权限和频率限制
    DRF版本和认证源码分析
    request高级部分
    多任务异步爬虫及selenium模块使用
    requests基本使用
    爬虫介绍及环境
    Flask生命周期的源码流程
  • 原文地址:https://www.cnblogs.com/chenzeyongjsj/p/10635977.html
Copyright © 2011-2022 走看看