import T from 'ant-design-vue/es/table/Table' import get from 'lodash.get' import draggable from 'vuedraggable' import columnSetting from './columnSetting' import './index.less' export default { components: { draggable, columnSetting }, data () { return { needTotalList: [], selectedRows: [], selectedRowKeys: [], localLoading: false, localDataSource: [], localPagination: Object.assign({}, this.pagination), isFullscreen: false, customSize: this.size, columnsSetting: [] } }, props: Object.assign({}, T.props, { rowKey: { type: [String, Function], default: 'key' }, data: { type: Function, required: true }, pageNum: { type: Number, default: 1 }, pageSize: { type: Number, default: 10 }, showSizeChanger: { type: Boolean, default: true }, size: { type: String, default: 'middle' }, /** * alert: { * show: true, * clear: Function * } */ alert: { type: [Object, Boolean], default: null }, rowSelection: { type: Object, default: null }, /** @Deprecated */ showAlertInfo: { type: Boolean, default: false }, showPagination: { type: String | Boolean, default: 'auto' }, /** * enable page URI mode * * e.g: * /users/1 * /users/2 * /users/3?queryParam=test * ... */ pageURI: { type: Boolean, default: false }, extraTool: { type: Array, default: () => ([]) } }), watch: { 'localPagination.current' (val) { this.pageURI && this.$router.push({ ...this.$route, name: this.$route.name, params: Object.assign({}, this.$route.params, { pageNo: val }) }) }, pageNum (val) { Object.assign(this.localPagination, { current: val }) }, pageSize (val) { Object.assign(this.localPagination, { pageSize: val }) }, showSizeChanger (val) { Object.assign(this.localPagination, { showSizeChanger: val }) }, columns(v) { this.columnsSetting = v } }, created () { const { pageNo } = this.$route.params const localPageNum = this.pageURI && (pageNo && parseInt(pageNo)) || this.pageNum this.localPagination = ['auto', true].includes(this.showPagination) && Object.assign({}, this.localPagination, { current: localPageNum, pageSize: this.pageSize, showSizeChanger: this.showSizeChanger, showTotal: (total, range) => { return range[0] + '-' + range[1] + '共' + total + '条' } }) || false this.needTotalList = this.initTotalList(this.columns) this.loadData() this.columnsSetting = this.columns }, methods: { /** * 表格重新加载方法 * 如果参数为 true, 则强制刷新到第一页 * @param Boolean bool */ refresh (bool = false) { bool && (this.localPagination = Object.assign({}, { current: 1, pageSize: this.pageSize })) this.loadData() }, /** * 加载数据方法 * @param {Object} pagination 分页选项器 * @param {Object} filters 过滤条件 * @param {Object} sorter 排序条件 */ loadData (pagination, filters, sorter) { this.localLoading = true const parameter = Object.assign({ pageNo: (pagination && pagination.current) || this.showPagination && this.localPagination.current || this.pageNum, pageSize: (pagination && pagination.pageSize) || this.showPagination && this.localPagination.pageSize || this.pageSize }, (sorter && sorter.field && { sortField: sorter.field }) || {}, (sorter && sorter.order && { sortOrder: sorter.order }) || {}, { ...filters } ) const result = this.data(parameter) // 对接自己的通用数据接口需要修改下方代码中的 r.pageNo, r.totalCount, r.data // eslint-disable-next-line if ((typeof result === 'object' || typeof result === 'function') && typeof result.then === 'function') { result.then(r => { if (r == null) { this.localLoading = false return } this.localPagination = this.showPagination && Object.assign({}, this.localPagination, { current: r.pageNo, // pageNo, // 返回结果中的当前分页数 total: r.totalRows, // totalCount, // 返回结果中的总记录数 showSizeChanger: this.showSizeChanger, pageSize: (pagination && pagination.pageSize) || this.localPagination.pageSize }) || false // 后端数据rows为null保存修复 if (r.rows == null) { r.rows = [] } // 为防止删除数据后导致页面当前页面数据长度为 0 ,自动翻页到上一页 if (r.rows.length === 0 && this.showPagination && this.localPagination.current > 1) { this.localPagination.current-- this.loadData() return } // 这里用于判断接口是否有返回 r.totalCount 且 this.showPagination = true 且 pageNo 和 pageSize 存在 且 totalCount 小于等于 pageNo * pageSize 的大小 // 当情况满足时,表示数据不满足分页大小,关闭 table 分页功能 try { if ((['auto', true].includes(this.showPagination) && r.totalCount <= (r.totalPage * this.localPagination.pageSize))) { this.localPagination.hideOnSinglePage = true } } catch (e) { this.localPagination = false } // 返回结果中的数组数据 if (this.showPagination === false) { // 因为按住小诺的套路,不分页的直接是在data中,我们在界面中直接就是返回了data this.localDataSource = r } else { this.localDataSource = r.rows } this.localLoading = false }) } }, initTotalList (columns) { const totalList = [] columns && columns instanceof Array && columns.forEach(column => { if (column.needTotal) { totalList.push({ ...column, total: 0 }) } }) return totalList }, /** * 用于更新已选中的列表数据 total 统计 * @param selectedRowKeys * @param selectedRows */ updateSelect (selectedRowKeys, selectedRows) { this.selectedRows = selectedRows this.selectedRowKeys = selectedRowKeys const list = this.needTotalList this.needTotalList = list.map(item => { return { ...item, total: selectedRows.reduce((sum, val) => { const total = sum + parseInt(get(val, item.dataIndex)) return isNaN(total) ? 0 : total }, 0) } }) }, /** * 清空 table 已选中项 */ clearSelected () { if (this.rowSelection) { this.rowSelection.onChange([], []) this.updateSelect([], []) } }, /** * 刷新并清空已选 */ clearRefreshSelected (bool = false) { this.refresh(bool) this.clearSelected() }, /** * 处理交给 table 使用者去处理 clear 事件时,内部选中统计同时调用 * @param callback * @returns {*} */ renderClear (callback) { if (this.selectedRowKeys.length <= 0) return null return ( { callback() this.clearSelected() }}>清空 ) }, renderAlert () { // 绘制统计列数据 // eslint-disable-next-line no-unused-vars const needTotalItems = this.needTotalList.map((item) => { return ( {item.title}总计 {!item.customRender ? item.total : item.customRender(item.total)} ) }) // 绘制 清空 按钮 // eslint-disable-next-line no-unused-vars const clearItem = (typeof this.alert.clear === 'boolean' && this.alert.clear) ? ( this.renderClear(this.clearSelected) ) : (this.alert !== null && typeof this.alert.clear === 'function') ? ( this.renderClear(this.alert.clear) ) : null // 绘制 alert 组件 // 统一先去除alert组件 return ( ) }, columnChange(val) { this.columnsSetting = val }, renderHeader () { let tools = [ { icon: 'reload', title: '刷新', onClick: () => { this.refresh() } }, { icon: 'column-height', title: '密度', isDropdown: true, menu: () => { const onClick = ({ key }) => { this.customSize = key } return ( 默认 中等 紧凑 ) }, onClick: () => { } }, { icon: 'setting', title: '列设置', isDropdown: true, menu: () => { return }, onClick: () => { } } ] if (this.extraTool.length) { tools = tools.concat(this.extraTool) } return (
{this.$scopedSlots.operator && this.$scopedSlots.operator()}
{ tools.map(tool => { if (tool.isDropdown) { return ( { tool.menu() } ) } return ( ) }) }
) /* return ( ) */ } }, render () { let props = {} const localKeys = Object.keys(this.$data) const showAlert = (typeof this.alert === 'object' && this.alert !== null && this.alert.show) && typeof this.rowSelection.selectedRowKeys !== 'undefined' || this.alert Object.keys(T.props).forEach(k => { const localKey = `local${k.substring(0, 1).toUpperCase()}${k.substring(1)}` if (localKeys.includes(localKey)) { props[k] = this[localKey] return props[k] } if (k === 'rowSelection') { if (showAlert && this.rowSelection) { // 如果需要使用alert,则重新绑定 rowSelection 事件 props[k] = { ...this.rowSelection, selectedRows: this.selectedRows, selectedRowKeys: this.selectedRowKeys, onChange: (selectedRowKeys, selectedRows) => { this.updateSelect(selectedRowKeys, selectedRows) typeof this[k].onChange !== 'undefined' && this[k].onChange(selectedRowKeys, selectedRows) } } return props[k] } else if (!this.rowSelection) { // 如果没打算开启 rowSelection 则清空默认的选择项 props[k] = null return props[k] } } this[k] && (props[k] = this[k]) // 此处配置表格大小与要显示的列 props = { ...props, size: this.customSize, columns: this.columnsSetting.filter(value => value.checked === undefined || value.checked) } return props[k] }) const table = ( { this.$emit('expand', expanded, record) } }> { Object.keys(this.$slots).map(name => ()) } ) return (
{ this.renderHeader() } { showAlert ? this.renderAlert() : null } { table }
) } }