const ButtonConfig = { add: { icon: 'el-icon-circle-plus-outline', label: '新增' } } // { // keepalive?: false, // singlePage?: false, // condition?: Object, // list: Function, // transform?: Function // buttons?: [ // { type: String, icon: String, label: String, on: Function } // ], // filters?: [ // { key: String, type: 'select', placeholder: String, ...SelectSchema }, // { key: String, type: 'search', placeholder: String } // ], // cols: [ // { prop: String, label: String, render?: Function | Array } // ] // } export default { provide () { return { table: this } }, props: { schema: { type: Object, required: true }, proxy: { type: Object, default: null } }, data () { return { customOptions: null, buttons: null, filters: null } }, computed: { hasHeader () { return this.$scopedSlots.header || this.buttons?.length || this.filters?.length }, tableData () { const { transformData } = this.schema return transformData ? transformData(this.options.list) : this.options.list }, options: { get () { return this.proxy || this.customOptions }, set (val) { if (this.proxy) { this.$emit('update:proxy', val) } else { this.customOptions = val this.onPagination() } } }, isManualPagination () { return this.schema.singlePage } }, watch: { proxy () { this.queueStatus() }, schema: { handler () { this.customOptions = this.createOptions(this.schema.condition) this.buttons = this.schema.buttons?.map(({ type, ...item }) => { return { ...ButtonConfig[type], ...item } }) const filterMap = {} this.filters = this.schema.filters?.map(filter => { filterMap[filter.key] = filter return { ...filter, loading: false, loaded: !!filter.remote } }) this.filterMap = filterMap this.queueStatus() }, immediate: true } }, activated () { if (this.schema.keepalive) { this.onPagination() } }, methods: { queueStatus () { if (!this.$flushing) { this.$flushing = true this.$nextTick(this.flushStatus) } }, flushStatus () { this.$flushing = false this.onPagination() }, createOptions (condition) { return { loading: false, error: false, params: { pageSize: this.pageSize, pageNum: 1, ...condition }, totalCount: 0, list: [] } }, filterInvokes (data) { return this.schema.invokes.filter(({ render }) => !render || render(data)) }, onPagination () { const options = this.options if (!options.loading) { options.loading = true const { list, transform } = this.schema list(options.params).then( ({ data, totalCount }) => { options.loading = false options.error = false options.totalCount = totalCount || data.length if (this.isManualPagination) { const { pageNum, pageSize } = options.params data = data.slice((pageNum - 1) * pageSize, pageNum * pageSize) } if (data.length === 0) { const { pageNum, pageSize } = options.params if (pageNum > 1) { return this.pageTo(totalCount ? Math.ceil(totalCount / pageSize) : 1) } } options.list = transform ? data.map(transform) : data }, () => { options.loading = false options.error = true options.totalCount = 0 options.list = [] } ) } }, onClickButton ({ on }) { if (on) { on(this.options.params, this) } }, onChange () { this.pageTo(1) }, getInst () { return this.$refs.table }, getData () { return this.options.list }, setData (data) { this.options.list = data }, info () { const options = this.options return { totalCount: options.totalCount, ...options.params } }, getCondition () { return this.options.params }, mergeCondition (condition) { const params = { ...this.options.params, pageNum: 1, ...condition } if (this.options.loading) { this.options = this.createOptions(params) } else { this.options.params = params } this.onPagination() }, resetCondition (condition) { const params = this.options.params condition && Object.keys(condition).forEach(key => { const paramValue = params[key] if (paramValue != null && paramValue !== '') { const value = condition[key] const filter = this.filterMap[key] switch (filter?.key) { case 'select': if (paramValue !== value) { params[key] = filter.placeholder ? void 0 : value } break case 'search': if (new RegExp(paramValue).test(value)) { params[key] = '' } break default: params[key] = value break } } }) this.onChange() }, pageTo (pageNum) { if (pageNum >= 1) { return this.mergeCondition({ pageNum }) } this.mergeCondition({ pageNum: this.options.params.pageNum }) }, decrease (count) { const options = this.options if (options.list.length <= count) { return this.pageTo(options.params.pageNum - 1) } this.pageTo() } } }