方便基礎業務開發封裝的一套組件,基於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>