diff --git a/jero-web/src/components/jero/JTable.vue b/jero-web/src/components/jero/JTable.vue
index caa10e05..8428c4c0 100644
--- a/jero-web/src/components/jero/JTable.vue
+++ b/jero-web/src/components/jero/JTable.vue
@@ -10,9 +10,12 @@
v-bind="$attrs"
v-on="$listeners">
-
-
+
+
+
+
+
-
+
@@ -99,6 +102,7 @@ export default {
},
data () {
return {
+ // settingVisible: false,
// 设置表格
settingColumns: [
{ title: '列名', dataIndex: 'title', align: 'center', ellipsis: true, width: 150 },
@@ -116,17 +120,6 @@ export default {
selfScroll: {}
}
},
- computed: {
- slots () {
- const slots = []
- for (const column of this.columns) {
- if (column.scopedSlots && column.scopedSlots.customRender) {
- slots.push(column.scopedSlots.customRender)
- }
- }
- return slots
- }
- },
watch: {
// 配置列改变,将配置转换成配置表格数据
settingColumnsObj: {
@@ -145,7 +138,7 @@ export default {
return
}
dataSource.push({
- title: col.title, // 用于显示的字段
+ title: col.title || col.columnTitle, // 用于显示的字段
key: tempKey, // 用于存储的字段
hide: this.settingColumnsObj.hide.includes(tempKey), // 是否隐藏
freeze: this.settingColumnsObj.freeze.includes(tempKey), // 是否冻结
@@ -154,24 +147,85 @@ export default {
})
})
this.settingDataSource = dataSource
- this.setResultColumns()
+ // 自定义列配置修改后,更新表格字段
+ this.setResultColumns(this.columns)
}
}
},
methods: {
+ // 将父组件的columns进行处理:增加设置列按钮
+ setResultColumns (columns) {
+ // 深度克隆,防止直接修改父组件数据
+ columns = cloneDeep(columns)
+ // 设置按钮插槽配置
+ const settingOption = {
+ filterDropdown: 'settingDropdown',
+ filterIcon: 'settingIcon'
+ }
+ let findActionIndex = columns.findIndex(col => col && (getKey(col) === actionKey))
+ // 将设置按钮放到表格右上角,如果有操作栏就固定到右侧(操作栏固定右侧,没有的话就最后一列)
+ if (findActionIndex === -1) {
+ findActionIndex = columns.length - 1
+ }
+ if (columns[findActionIndex].scopedSlots instanceof Object) {
+ Object.assign(columns[findActionIndex].scopedSlots, settingOption)
+ } else {
+ columns[findActionIndex].scopedSlots = settingOption
+ }
+ // 自定义设置弹框(尝试解决表格刷新丢失弹框的问题)此方法会出现两个弹框
+ // columns[findActionIndex].filterDropdownVisible = this.settingVisible
+ // columns[findActionIndex].onFilterDropdownVisibleChange = (visible) => {
+ // this.settingVisible = visible
+ // }
+
+ // 最后过滤掉需要隐藏的字段,按定位进行排序
+ const startArr = [] // 冻结左侧的列
+ const midArr = [] // 没有冻结的列
+ const endArr = [] // 冻结右侧的列(只能是action,暂时不能自定义固定右侧)
+ columns.forEach(col => {
+ const key = getKey(col)
+ const fixed = this.settingColumnsObj.freeze.includes(key)
+ col.hide = this.settingColumnsObj.hide.includes(key)
+ col.fixed = key === actionKey ? 'right' : fixed
+ // 如果是字符串就转换成数字(因为实现拖拽,单位只能是px)
+ col.width = col.width && parseInt(col.width + '')
+ // 如果没有最小宽度就获取统一设置的最小宽度
+ col.minWidth = (col.minWidth && parseInt(col.minWidth + '')) || this.columnMinWidth
+ if (!col.hide) {
+ // 如果没有宽度就取minWidth(不添加原数据的width属性,这里只对需要固定的minWidth生效)
+ const width = col.width || col.minWidth
+ switch (col.fixed) {
+ case true:
+ case 'left':
+ startArr.push({ ...col, width })
+ break
+ case 'right':
+ endArr.push({ ...col, width })
+ break
+ default:
+ midArr.push(col)
+ }
+ }
+ })
+ // 更新父组件的数据,将排序后的进行渲染
+ this.$emit('update:columns', columns)
+ this.resultColumns = [...startArr, ...midArr, ...endArr]
+ return this.resultColumns
+ },
// 初始化表格拖拽
- initDrag (tbCols) {
+ initDrag (columns) {
+ columns = cloneDeep(columns)
// 没有边框就不能拖拽
if (!this.bordered) {
return
}
// 如果没有任何列开启拖拽就不需要拖拽
- if (!tbCols.some(col => col.resizable)) {
+ if (!columns.some(col => col.resizable)) {
return
}
// 第一步:列宽映射
const draggingMap = {}
- tbCols.forEach((col) => {
+ columns.forEach((col) => {
draggingMap[col.dataIndex || col.key] = col.width
})
const draggingState = Vue.observable(draggingMap)
@@ -194,7 +248,7 @@ export default {
if (key === 'selection-column') {
col = {}
} else {
- col = this.columns.find(col => getKey(col) === key)
+ col = columns.find(col => getKey(col) === key)
}
// 没有开启拖拽 或 没有宽度 或 有定位,都不能拖拽(防止布局异常,至少有一列不设width并且不能有fixed)
if (!col.resizable || !col.width || !!col.fixed) {
@@ -219,6 +273,8 @@ export default {
} else {
this.selfScroll = scroll
}
+ // 修改列宽后,更新表格字段
+ this.setResultColumns(columns)
}
// 停止拖拽监听
const onDragstop = () => {
@@ -249,60 +305,6 @@ export default {
)
}
},
- /**
- * 将父组件的columns进行处理:增加设置列按钮
- */
- setResultColumns () {
- // 深度克隆,防止直接修改父组件数据
- const columns = cloneDeep(this.columns)
- // 设置按钮插槽配置
- const settingOption = {
- filterDropdown: 'settingDropdown',
- filterIcon: 'settingIcon'
- }
- let findActionIndex = columns.findIndex(col => col && (getKey(col) === actionKey))
- // 将设置按钮放到表格右上角,如果有操作栏就固定到右侧(操作栏固定右侧,没有的话就最后一列)
- if (findActionIndex === -1) {
- findActionIndex = columns.length - 1
- }
- if (columns[findActionIndex].scopedSlots instanceof Object) {
- Object.assign(columns[findActionIndex].scopedSlots, settingOption)
- } else {
- columns[findActionIndex].scopedSlots = settingOption
- }
- // 最后过滤掉需要隐藏的字段,按定位进行排序
- const startArr = [] // 冻结左侧的列
- const midArr = [] // 没有冻结的列
- const endArr = [] // 冻结右侧的列(只能是action,暂时不能自定义固定右侧)
- columns.forEach(col => {
- const key = getKey(col)
- const fixed = this.settingColumnsObj.freeze.includes(key)
- col.hide = this.settingColumnsObj.hide.includes(key)
- col.fixed = key === actionKey ? 'right' : fixed
- // 如果是字符串就转换成数字(因为实现拖拽,单位只能是px)
- col.width = parseInt(col.width + '')
- // 如果没有最小宽度就获取统一设置的最小宽度
- col.minWidth = parseInt(col.minWidth + '') || this.columnMinWidth
- if (!col.hide) {
- // 如果没有宽度就取minWidth(不添加原数据的width属性,这里只对需要固定的minWidth生效)
- const width = col.width || col.minWidth
- switch (col.fixed) {
- case true:
- case 'left':
- startArr.push({ ...col, width })
- break
- case 'right':
- endArr.push({ ...col, width })
- break
- default:
- midArr.push(col)
- }
- }
- })
- // 更新父组件的数据,将排序后的进行渲染
- this.$emit('update:columns', columns)
- this.resultColumns = [...startArr, ...midArr, ...endArr]
- },
/**
* 配置表中复选框改变状态的事件
* @param text 修改前的状态
@@ -322,15 +324,13 @@ export default {
}
this.saveSetting()
/**
- * 弹框消失问题 冻结列会导致dom结构改变而从局部更新丢失弹框
- * 情况1:原本显示没有冻结列,新增第一个冻结列
- * 情况2:原本有且只剩一个冻结列,取消最后一个冻结列
+ * 弹框消失问题 冻结列出现和消失会导致dom结构改变而从更新结构丢失弹框
* 解决方案,刷新前获取dom,刷新后再次获取,如果获取不一致就触发点击事件点开弹框
*/
const beforeIsFixed = !!this.$refs.table.$el.querySelector('.ant-table-fixed-left')
this.$nextTick(() => {
const afterIsFixed = !!this.$refs.table.$el.querySelector('.ant-table-fixed-left')
- // console.log(beforeIsFixed, afterIsFixed)
+ // console.log(beforeIsFixed !== afterIsFixed)
if (beforeIsFixed !== afterIsFixed) {
this.$refs.settingBtn.$el.click()
}
diff --git a/jero-web/src/components/jero/README_JTable.md b/jero-web/src/components/jero/README_JTable.md
index e713a372..0b24e523 100644
--- a/jero-web/src/components/jero/README_JTable.md
+++ b/jero-web/src/components/jero/README_JTable.md
@@ -52,7 +52,7 @@
在[示例](#示例)中,设定了一个 `ref="table"` 的属性,那么在vue中就可以使用`this.$refs.table`获取到该表格的实例,并调取其中的方法。
假如我要调取`resteColumns`方法,就可以这么写:`this.$refs.table.resteColumns()`
-### columns和scroll为什么要使用`.sync`
+### `columns`和`scroll`为什么要使用`.sync`
保证父组件和子组件数据同步
@@ -60,35 +60,68 @@
`scroll`拖拽后会把最新的总宽度同步
-### 对原ATable的使用有哪些限制
+### 对原`a-table`的使用有哪些限制
- 操作列的`dataIndex`或`key`必须为`action`
- - 带有设置的列不能使用`scopedSlots.filterIcon` 和 `scopedSlots.filterDropdown`
+ - 带有设置的列不能使用`scopedSlots.filterIcon` 和 `scopedSlots.filterDropdown`(没有操作列时,设置在最后一列)
- `scroll.x`和`width`必须是数字,不支持百分比
+ - 使用作用域插槽,需要使用解构赋值,里面有三个参数`{text, record, index}`,可参考[示例](#示例)写法
+
+### 拖拽后没有设置宽度的列会被缩小
+
+ - 设置scroll.x配置一个默认宽度即可
+
+### 出现空白列
+
+ - 设置至少一列没有width(没有width不能被拖拽)
+ - 建议没有`width`的列不能手动控制隐藏和冻结,使用`disabledHide`和`disabledFreeze`或者`hideSettingColumn`
+
+### `resizable`没有效果
+
+ - 需要设置`resizable: true`,要有`width`,且不能有`fixed`
+
+### 自定义列的弹框会消失
+
+ - 因为冻结列的出现或消失会刷新表格结构导致弹框丢失
+ - 设置一个冻结列始终存在,不可被手动控制隐藏和取消冻结即可
### 注意事项
+ - `table-key`该属性为全局每个表的唯一属性,建议使用路由+命名的方式,如[示例](#示例)中设置
- 固定头和列(ant-design-vue自带的问题) :若列头与内容不对齐或出现列重复,请指定固定列的宽度 width。如果指定 width 不生效或出现白色垂直空隙,请尝试建议留一列不设宽度以适应弹性布局,或者检查是否有超长连续字段破坏布局。
建议指定 scroll.x 为大于表格宽度的固定值。注意,且非固定列宽度之和不要超过 `scroll.x`。
- - `table-key`该属性为全局每个表的唯一属性,建议使用路由+命名的方式,如[示例](#示例)中设置
## 示例
```vue
-
重置表格配置
-
清空本表缓存
-
清空全局JTable缓存
+
+
重置表格配置
+
清空本表缓存
+
清空全局JTable缓存
+
-
+
+ {{ text }}
+ Name
+
+
+ {{ tag.toUpperCase() }}
+
+
+
Delete
+
+
+ Footer:{{ currentPageData }}
+
@@ -108,7 +145,6 @@ import JTable from '@comp/jero/JTable'
export default {
name: 'Demo',
components: { JTable },
-
data () {
const columns = [
{
@@ -126,7 +162,7 @@ export default {
fixed: true,
title: '#',
ellipsis: true,
- dataIndex: 'key',
+ dataIndex: 'key'
},
{
resizable: true,
@@ -134,6 +170,20 @@ export default {
dataIndex: 'date',
width: 200
},
+ {
+ // 标题使用插槽使用这个代替title(用于设置里显示列名)
+ columnTitle: 'Name',
+ dataIndex: 'name',
+ key: 'name',
+ slots: { title: 'customTitle' },
+ scopedSlots: { customRender: 'name' }
+ },
+ {
+ title: 'Tags',
+ key: 'tags',
+ dataIndex: 'tags',
+ scopedSlots: { customRender: 'tags' }
+ },
{
resizable: true, // 可拖拽属性
title: 'Amount',
@@ -148,9 +198,13 @@ export default {
},
{
title: 'Note',
- dataIndex: 'note'
+ dataIndex: 'note',
// 保留一列自适应
// width: 100
+ // 建议:没有宽度的列至少一列禁止自定义(解决冻结或隐藏列导致出现空列)
+ // disabledHide: true,
+ // disabledFreeze: true,
+ hideSettingColumn: true
},
{
title: 'Action',
@@ -163,6 +217,8 @@ export default {
const dataSource = [
{
key: 0,
+ name: 'John Brown',
+ tags: ['nice', 'developer'],
date: '2018-02-11',
amount: 120,
type: 'income',
@@ -170,6 +226,8 @@ export default {
},
{
key: 1,
+ name: 'Jim Green',
+ tags: ['loser'],
date: '2018-03-11',
amount: 243,
type: 'income',
@@ -177,6 +235,8 @@ export default {
},
{
key: 2,
+ name: 'Joe Black',
+ tags: ['cool', 'teacher'],
date: '2018-04-11',
amount: 98,
type: 'income',
@@ -184,7 +244,7 @@ export default {
}
]
return {
- scroll: { x: 1000 },
+ scroll: { x: 1400 },
columns: columns,
dataSource: dataSource,
selectedRowKeys: []
@@ -192,7 +252,7 @@ export default {
},
methods: {
// 还原表格初始配置
- resetTable() {
+ resetTable () {
this.$refs.table.resteColumns()
},
// 清除当前表格缓存
diff --git a/jero-web/src/views/demo/list/JTableList.vue b/jero-web/src/views/demo/list/JTableList.vue
index 7fd16644..affd8ebc 100644
--- a/jero-web/src/views/demo/list/JTableList.vue
+++ b/jero-web/src/views/demo/list/JTableList.vue
@@ -8,12 +8,24 @@
+
+ {{ text }}
+ Name
+
+
+ {{ tag.toUpperCase() }}
+
+
Delete
+
+
+ Footer:{{ currentPageData }}
+
@@ -61,6 +77,20 @@ export default {
dataIndex: 'date',
width: 200
},
+ {
+ // 标题使用插槽使用这个代替title(用于设置里显示列名)
+ columnTitle: 'Name',
+ dataIndex: 'name',
+ key: 'name',
+ slots: { title: 'customTitle' },
+ scopedSlots: { customRender: 'name' }
+ },
+ {
+ title: 'Tags',
+ key: 'tags',
+ dataIndex: 'tags',
+ scopedSlots: { customRender: 'tags' }
+ },
{
resizable: true, // 可拖拽属性
title: 'Amount',
@@ -75,9 +105,13 @@ export default {
},
{
title: 'Note',
- dataIndex: 'note'
+ dataIndex: 'note',
// 保留一列自适应
// width: 100
+ // 建议:没有宽度的列至少一列禁止自定义(解决冻结或隐藏列导致出现空列)
+ // disabledHide: true,
+ // disabledFreeze: true,
+ hideSettingColumn: true
},
{
title: 'Action',
@@ -90,6 +124,8 @@ export default {
const dataSource = [
{
key: 0,
+ name: 'John Brown',
+ tags: ['nice', 'developer'],
date: '2018-02-11',
amount: 120,
type: 'income',
@@ -97,6 +133,8 @@ export default {
},
{
key: 1,
+ name: 'Jim Green',
+ tags: ['loser'],
date: '2018-03-11',
amount: 243,
type: 'income',
@@ -104,6 +142,8 @@ export default {
},
{
key: 2,
+ name: 'Joe Black',
+ tags: ['cool', 'teacher'],
date: '2018-04-11',
amount: 98,
type: 'income',