405 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
			
		
		
	
	
			405 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
| <template>
 | |
|   <div class="ai-table" :class="[isShowBorder ? 'ai-table__border' : 'ai-table__noborder']">
 | |
|     <el-table :data="tableData"
 | |
|               header-cell-class-name="ai-table__header"
 | |
|               cell-class-name="ai-table__cell"
 | |
|               row-class-name="ai-table__row"
 | |
|               :class="{'ai-header__border': isShowBorder}"
 | |
|               :ref="refName"
 | |
|               :size="tableSize"
 | |
|               :stripe="stripe"
 | |
|               :tooltip-effect="tooltipEffect"
 | |
|               @selection-change="handleSelectionChange"
 | |
|               v-on="$listeners"
 | |
|               v-bind="$attrs"
 | |
|               v-loading="loading">
 | |
|       <template v-for="colConfig in colConfigs.filter(e=>!e.hide)">
 | |
|         <slot v-if="colConfig.slot && colConfig.slot !== 'options'" :name="colConfig.slot"/>
 | |
|         <component
 | |
|             :key="colConfig.id"
 | |
|             v-else-if="colConfig.component"
 | |
|             :is="colConfig.component"
 | |
|             :col-config="colConfig">
 | |
|         </component>
 | |
|         <el-table-column
 | |
|             v-else-if="colConfig.dict"
 | |
|             :key="colConfig.id"
 | |
|             v-bind="colConfig">
 | |
|           <span slot-scope="{row}" :style="{color:colConfig.color||dict.getColor(colConfig.dict, row[colConfig.prop])}">
 | |
|             {{ dict.getLabel(colConfig.dict, row[colConfig.prop]) }}
 | |
|           </span>
 | |
|         </el-table-column>
 | |
|         <el-table-column
 | |
|             v-else-if="colConfig.openType"
 | |
|             :key="colConfig.id"
 | |
|             v-bind="colConfig">
 | |
|           <template v-slot="{row}">
 | |
|             <ai-open-data :type="colConfig.openType" :openid="row[colConfig.prop]"/>
 | |
|           </template>
 | |
|         </el-table-column>
 | |
|         <el-table-column
 | |
|             v-else-if="colConfig.type"
 | |
|             :key="colConfig.id"
 | |
|             v-bind="colConfig"
 | |
|             :width="colConfig.width || 100"/>
 | |
|         <el-table-column v-else v-bind="colConfig" :key="colConfig.id"
 | |
|                          :show-overflow-tooltip="colConfig['show-overflow-tooltip'] != false">
 | |
|           <template slot-scope="scope">
 | |
|             <render-slot v-if="colConfig.render" :render="colConfig.render" :row="scope.row" :index="scope.$index"
 | |
|                          :column="colConfig"/>
 | |
|             <span v-else>{{ getValue(colConfig, scope.row) }}</span>
 | |
|           </template>
 | |
|         </el-table-column>
 | |
|       </template>
 | |
|       <slot class="table-options" name="options"/>
 | |
|       <template #empty>
 | |
|         <slot v-if="$scopedSlots.empty" name="empty"/>
 | |
|         <div v-else class="no-data" style="height:160px;"/>
 | |
|       </template>
 | |
|     </el-table>
 | |
|     <div class="pagination newPagination" v-if="isShowPagination">
 | |
|       <el-pagination
 | |
|           background
 | |
|           :current-page="page.current"
 | |
|           :total="page.total"
 | |
|           :page-size="page.size"
 | |
|           v-bind="$attrs"
 | |
|           :page-sizes="pageSizes"
 | |
|           :layout="layout"
 | |
|           :pager-count="page.pagerCount"
 | |
|           @size-change="handleSizeChange"
 | |
|           @current-change="handleChange">
 | |
|         <div class="paginationPre">
 | |
|           <el-checkbox v-if="isHasPaginationBtnsSlot" :disabled="!tableData.length" :indeterminate="isIndeterminate"
 | |
|                        :value="checkAll" @click.native="toggleAllSelection">全选
 | |
|           </el-checkbox>
 | |
|           <slot name="pagination"/>
 | |
|           <div class="pagination-btns">
 | |
|             <slot name="paginationBtns"></slot>
 | |
|           </div>
 | |
|           <div class="paginationPre-total" :style="{marginLeft: isHasPaginationBtnsSlot ? '24px' : 0}">共<label class="color-primary">{{ page.total }}</label>条记录
 | |
|           </div>
 | |
|         </div>
 | |
|       </el-pagination>
 | |
|     </div>
 | |
|   </div>
 | |
| </template>
 | |
| 
 | |
| <script>
 | |
| import moment from 'dayjs'
 | |
| import dict from "../../lib/js/dict"
 | |
| 
 | |
| export default {
 | |
|   name: 'AiTable',
 | |
|   model: {
 | |
|     prop: "tableData",
 | |
|     event: "change"
 | |
|   },
 | |
|   props: {
 | |
|     colConfigs: {type: Array, required: true},
 | |
|     tableData: {type: Array, required: true, default: () => []},
 | |
|     current: {default: 1},
 | |
|     size: {default: 10},
 | |
|     isShowPagination: {type: Boolean, default: true},
 | |
|     total: Number,
 | |
|     layout: {type: String, default: 'slot,->, prev, pager, next, sizes, jumper'},
 | |
|     stripe: {type: Boolean, default: true},
 | |
|     loading: {type: Boolean, default: false},
 | |
|     tooltipEffect: String,
 | |
|     tableSize: String,
 | |
|     tableRef: String,
 | |
|     dict: {default: () => dict},
 | |
|     pagerCount: {default: 5},
 | |
|     pageSizes: {default: () => [10, 20, 50, 100]},
 | |
|     pageConfig: Object
 | |
|   },
 | |
|   data() {
 | |
|     return {
 | |
|       name: '',
 | |
|       chooseList: [],
 | |
|       defaultPage: {}
 | |
|     }
 | |
|   },
 | |
|   components: {
 | |
|     renderSlot: {
 | |
|       functional: true,
 | |
|       props: {
 | |
|         row: Object,
 | |
|         render: Function,
 | |
|         index: Number,
 | |
|         column: {type: Object, default: null},
 | |
|       },
 | |
|       render: (h, data) => {
 | |
|         const params = {
 | |
|           row: data.props.row,
 | |
|           index: data.props.index
 | |
|         }
 | |
|         if (data.props.column) {
 | |
|           params.column = data.props.column
 | |
|         }
 | |
|         return data.props.render(h, params)
 | |
|       }
 | |
|     }
 | |
|   },
 | |
|   computed: {
 | |
|     refName: v => v.tableRef || `aiTable${new Date().getTime()}`,
 | |
|     isShowBorder: v => !!v.$attrs.border || v.$attrs.border === '',
 | |
|     isHasPaginationBtnsSlot: v => v.$scopedSlots.paginationBtns,
 | |
|     isIndeterminate: v => v.chooseList.length > 0 && v.chooseList.length < v.tableData.length,
 | |
|     checkAll: v => v.chooseList.length == v.tableData.length && v.tableData !== 0,
 | |
|     page() {
 | |
|       return {
 | |
|         current: this.current,
 | |
|         size: this.size,
 | |
|         total: this.total,
 | |
|         pagerCount: this.pagerCount,
 | |
|         ...this.pageConfig
 | |
|       }
 | |
|     },
 | |
|   },
 | |
|   methods: {
 | |
|     handleChange(current) {
 | |
|       this.$emit('update:current', current)
 | |
|       this.$emit('update:pageConfig', {...this.pageConfig, current})
 | |
|       this.$nextTick(() => {
 | |
|         this.$emit('getList')
 | |
|       })
 | |
|     },
 | |
|     handleSizeChange(size) {
 | |
|       this.$emit('update:size', size)
 | |
|       this.$emit('update:pageConfig', {...this.pageConfig, size})
 | |
|       this.$nextTick(() => {
 | |
|         this.$emit('getList')
 | |
|       })
 | |
|     },
 | |
|     handleSelectionChange(e) {
 | |
|       this.chooseList = e
 | |
|       this.$emit('handleSelectionChange', e)
 | |
|     },
 | |
|     getValue(colConfig, row) {
 | |
|       if (typeof colConfig.format === 'function') {
 | |
|         return colConfig.format.call(this, row[colConfig.prop])
 | |
|       }
 | |
|       if (colConfig.dateFormat) {
 | |
|         return moment(row[colConfig.prop]).format(colConfig.dateFormat)
 | |
|       }
 | |
| 
 | |
|       return row[colConfig.prop] === 0 || row[colConfig.prop] ? row[colConfig.prop] : '-'
 | |
|     },
 | |
|     /**
 | |
|      * 表格方法代理
 | |
|      */
 | |
|     clearSelection() {
 | |
|       this.$refs[this.refName].clearSelection()
 | |
|     },
 | |
|     toggleRowSelection() {
 | |
|       console.log(22)
 | |
|       this.$refs[this.refName].toggleRowSelection(...arguments)
 | |
|     },
 | |
|     toggleAllSelection() {
 | |
|       this.$refs[this.refName].toggleAllSelection()
 | |
|     },
 | |
|     toggleRowExpansion() {
 | |
|       this.$refs[this.refName].toggleRowExpansion(...arguments)
 | |
|     },
 | |
|     setCurrentRow() {
 | |
|       this.$refs[this.refName].setCurrentRow(...arguments)
 | |
|     },
 | |
|     clearSort() {
 | |
|       this.$refs[this.refName].clearSort()
 | |
|     },
 | |
|     clearFilter() {
 | |
|       this.$refs[this.refName].clearFilter(...arguments)
 | |
|     },
 | |
|     doLayout() {
 | |
|       this.$refs[this.refName].doLayout()
 | |
|     },
 | |
|     sort() {
 | |
|       this.$refs[this.refName].sort(...arguments)
 | |
|     },
 | |
|   }
 | |
| }
 | |
| </script>
 | |
| 
 | |
| <style lang="scss" scoped>
 | |
| .ai-table {
 | |
|   .color-primary {
 | |
|     color: $primaryColor;
 | |
|   }
 | |
| 
 | |
|   :deep( .ai-header__border .ai-table__header ) {
 | |
|     border-bottom: 1px solid $borderColor !important;
 | |
|     border-right: 1px solid $borderColor !important;
 | |
|   }
 | |
| 
 | |
|   :deep( .el-table--border ) {
 | |
|     border: 1px solid $borderColor;
 | |
|     border-right: none;
 | |
|     border-bottom: none;
 | |
|   }
 | |
| 
 | |
|   :deep( .el-table ) {
 | |
|     color: #222;
 | |
| 
 | |
|     .caret-wrapper {
 | |
|       height: 24px;
 | |
| 
 | |
|       .ascending {
 | |
|         top: 1px;
 | |
|       }
 | |
| 
 | |
|       .descending {
 | |
|         bottom: 1px;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     thead {
 | |
|       color: #555
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   :deep( .cell ) {
 | |
|     line-height: 24px;
 | |
|   }
 | |
| 
 | |
|   :deep( .el-table__header ) {
 | |
|     th {
 | |
|       padding: 8px 0;
 | |
|     }
 | |
| 
 | |
|     tr {
 | |
|       .cell {
 | |
|         font-weight: 700;
 | |
|       }
 | |
| 
 | |
|       th:first-child {
 | |
|         .cell {
 | |
|           padding-left: 40px !important;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   :deep( .el-table__body ) {
 | |
|     tr td:first-child .cell {
 | |
|       padding-left: 40px !important;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   :deep( .el-table__fixed-right ) {
 | |
|     .el-table__body {
 | |
|       tr td:first-child .cell {
 | |
|         padding-left: 0 !important;
 | |
|         padding-right: 0;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   :deep( .ai-table__header ) {
 | |
|     border-bottom: none;
 | |
|     background: #F3F4F5;
 | |
|   }
 | |
| 
 | |
|   :deep(.el-pager ) {
 | |
|     li.active + li {
 | |
|       border-left: 1px solid $borderColor;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   .newPagination {
 | |
|     width: 100%;
 | |
|     display: flex;
 | |
|     align-items: center;
 | |
|     height: 64px;
 | |
|     padding: 0 40px !important;
 | |
| 
 | |
|     .el-pagination {
 | |
|       width: 100%;
 | |
|       padding: 0;
 | |
|     }
 | |
| 
 | |
|     .paginationPre {
 | |
|       display: flex;
 | |
|       height: 28px;
 | |
|       line-height: 1;
 | |
|       font-size: 14px;
 | |
|       font-weight: normal;
 | |
|       align-items: center;
 | |
| 
 | |
|       .pagination-btns {
 | |
|         display: flex;
 | |
|         align-items: center;
 | |
|         gap: 8px;
 | |
|         color: $primaryColor !important;
 | |
| 
 | |
|         :deep( span), :deep( div ) {
 | |
|           font-size: 12px;
 | |
|           cursor: pointer;
 | |
|           color: $primaryColor !important;
 | |
| 
 | |
|           &:hover {
 | |
|             opacity: 0.8;
 | |
|           }
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       .paginationPre-total {
 | |
|         font-size: 12px;
 | |
|         color: #555;
 | |
| 
 | |
|         label {
 | |
|           padding: 0 2px;
 | |
|           font-weight: 700;
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       & > * + * {
 | |
|         margin-left: 24px;
 | |
|       }
 | |
| 
 | |
|       :deep( .el-pagination button), .el-pagination span:not([class*=suffix]) {
 | |
|         line-height: 1 !important;
 | |
|       }
 | |
| 
 | |
|       :deep(.el-checkbox ) {
 | |
|         display: flex;
 | |
|         align-items: center;
 | |
| 
 | |
|         .el-checkbox__input, .el-checkbox__inner {
 | |
|           width: 14px;
 | |
|           height: 14px;
 | |
|           min-width: 0 !important;
 | |
|           line-height: 1 !important;
 | |
|         }
 | |
| 
 | |
|         .el-checkbox__label {
 | |
|           font-size: 12px;
 | |
|           color: #222222;
 | |
|           height: auto !important;
 | |
|           line-height: 1 !important;
 | |
|           padding-left: 3px !important;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| .ai-table__noborder {
 | |
|   :deep( .el-table td), :deep( .el-table th.is-center ) {
 | |
|     border: none;
 | |
|   }
 | |
| 
 | |
|   .el-table::before {
 | |
|     display: none;
 | |
|   }
 | |
| 
 | |
|   :deep( .el-table--striped .el-table__body tr.el-table__row--striped td ) {
 | |
|     background: #F5F6F9;
 | |
|   }
 | |
| 
 | |
|   :deep( .el-table__fixed-right::before), :deep( .el-table__fixed::before ) {
 | |
|     display: none;
 | |
|   }
 | |
| }
 | |
| </style>
 |