基于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.width:''" 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 width: 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>
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 width: 100%; 92 height: 100%; 93 position: fixed; 94 top: 0; 95 left: 0; 96 z-index: 997; 97 } 98 } 99 } 100 </style>
baseDialogForm部分(基于表格的弹出框表单)
1 <template> 2 <el-dialog :title="title" :visible.sync="dialogVisible" :width="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 width: 100% !important; 104 } 105 106 .el-select { 107 width: 100% !important; 108 } 109 </style>
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="width: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>
页面调用
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", width: "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 width: 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>