Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
啊嘞嘞EC
vue-vben-admin
提交
9c2f3f30
V
vue-vben-admin
项目概览
啊嘞嘞EC
/
vue-vben-admin
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
V
vue-vben-admin
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
9c2f3f30
编写于
12月 31, 2020
作者:
V
vben
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
refactor(table): refactor table #150 #148 #146 #130 #76
上级
f3a70eed
变更
35
显示空白变更内容
内联
并排
Showing
35 changed file
with
1099 addition
and
454 deletion
+1099
-454
CHANGELOG.zh_CN.md
CHANGELOG.zh_CN.md
+51
-8
mock/demo/table-demo.ts
mock/demo/table-demo.ts
+8
-0
src/components/Form/index.ts
src/components/Form/index.ts
+3
-0
src/components/Form/src/components/ApiSelect.vue
src/components/Form/src/components/ApiSelect.vue
+4
-1
src/components/Menu/src/useOpenKeys.ts
src/components/Menu/src/useOpenKeys.ts
+5
-3
src/components/Table/index.ts
src/components/Table/index.ts
+1
-2
src/components/Table/src/BasicTable.vue
src/components/Table/src/BasicTable.vue
+34
-43
src/components/Table/src/componentMap.ts
src/components/Table/src/componentMap.ts
+4
-4
src/components/Table/src/components/EditTableHeaderIcon.vue
src/components/Table/src/components/EditTableHeaderIcon.vue
+2
-1
src/components/Table/src/components/HeaderCell.vue
src/components/Table/src/components/HeaderCell.vue
+55
-0
src/components/Table/src/components/TableAction.vue
src/components/Table/src/components/TableAction.vue
+3
-4
src/components/Table/src/components/editable/CellComponent.ts
...components/Table/src/components/editable/CellComponent.ts
+33
-0
src/components/Table/src/components/editable/EditableCell.vue
...components/Table/src/components/editable/EditableCell.vue
+359
-0
src/components/Table/src/components/editable/helper.ts
src/components/Table/src/components/editable/helper.ts
+26
-0
src/components/Table/src/components/editable/index.ts
src/components/Table/src/components/editable/index.ts
+52
-0
src/components/Table/src/components/renderEditable.tsx
src/components/Table/src/components/renderEditable.tsx
+0
-241
src/components/Table/src/components/renderExpandIcon.tsx
src/components/Table/src/components/renderExpandIcon.tsx
+0
-14
src/components/Table/src/components/settings/ColumnSetting.vue
...omponents/Table/src/components/settings/ColumnSetting.vue
+1
-1
src/components/Table/src/const.ts
src/components/Table/src/const.ts
+4
-0
src/components/Table/src/hooks/useColumns.ts
src/components/Table/src/hooks/useColumns.ts
+65
-8
src/components/Table/src/hooks/useDataSource.ts
src/components/Table/src/hooks/useDataSource.ts
+59
-3
src/components/Table/src/hooks/useTable.ts
src/components/Table/src/hooks/useTable.ts
+38
-10
src/components/Table/src/hooks/useTableScroll.ts
src/components/Table/src/hooks/useTableScroll.ts
+5
-2
src/components/Table/src/props.ts
src/components/Table/src/props.ts
+9
-1
src/components/Table/src/style/editable-cell.less
src/components/Table/src/style/editable-cell.less
+0
-39
src/components/Table/src/style/index.less
src/components/Table/src/style/index.less
+10
-6
src/components/Table/src/types/componentType.ts
src/components/Table/src/types/componentType.ts
+1
-2
src/components/Table/src/types/table.ts
src/components/Table/src/types/table.ts
+42
-14
src/layouts/default/sider/MixSider.vue
src/layouts/default/sider/MixSider.vue
+5
-0
src/router/menus/modules/demo/comp.ts
src/router/menus/modules/demo/comp.ts
+9
-0
src/utils/dateUtil.ts
src/utils/dateUtil.ts
+7
-4
src/views/demo/table/EditCellTable.vue
src/views/demo/table/EditCellTable.vue
+100
-26
src/views/demo/table/EditRowTable.vue
src/views/demo/table/EditRowTable.vue
+96
-15
src/views/demo/table/FixedColumn.vue
src/views/demo/table/FixedColumn.vue
+1
-1
src/views/demo/table/tableData.tsx
src/views/demo/table/tableData.tsx
+7
-1
未找到文件。
CHANGELOG.zh_CN.md
浏览文件 @
9c2f3f30
## Wip
### ✨ 表格破坏性更新
-
重构了可编辑单元格及可编辑行。具体看示例。写法已改变。针对可编辑表格。
-
表格编辑支持表单校验
-
在表格列配置增加了以下配置
```
bash
{
# 默认是否显示列。不显示的可以在列配置打开
defaultHidden?: boolean
;
# 列头右侧帮助文本
helpMessage?: string | string[]
;
# 自定义格式化 单元格内容。 支持时间/枚举自动转化
format?: CellFormat
;
# Editable
# 是否是可编辑单元格
edit?: boolean
;
# 是否是可编辑行
editRow?: boolean
;
# 编辑状态。
editable?: boolean
;
# 编辑组件
editComponent?: ComponentType
;
# 所对应组件的参数
editComponentProps?: Recordable
;
# 校验
editRule?: boolean |
((
text: string, record: Recordable
)
=>
Promise<string>
)
;
# 值枚举转化
editValueMap?:
(
value: any
)
=>
string
;
# 触发编辑正航
record.onEditRow?:
()
=>
void
;
}
```
### ✨ 表格重构
-
新增
`clickToRowSelect`
属性。用于控制点击行是否选中勾选框
-
监听行点击事件
-
表格列配置按钮增加 列拖拽,列固定功能。
-
表格列配置新增
`defaultHidden`
属性。用于默认隐藏。可在表格列配置勾选显示
-
更强大的列配置
-
useTable:支持动态改变参数。可以传入
`Ref`
类型与
`Computed`
类型进行动态更改
-
useTable:新增返回
`getForm`
函数。可以用于操作表格内的表单
-
修复表格已知的问题
### ✨ Features
-
新增
`v-ripple`
水波纹指令
...
...
@@ -12,14 +62,6 @@
-
form: 新增远程下拉
`ApiSelect`
及示例
-
form: 新增
`autoFocusFirstItem`
配置。用于配置是否聚焦表单第一个输入框
-
useForm: 支持动态改变参数。可以传入
`Ref`
类型与
`Computed`
类型进行动态更改
-
table: 新增
`clickToRowSelect`
属性。用于控制点击行是否选中勾选狂
-
table: 监听行点击事件
-
table: 表格列配置按钮增加 列拖拽,列固定功能。
-
table:表格列配置新增
`defaultHidden`
属性。用于默认隐藏。可在表格列配置勾选显示
### ✨ Refactor
-
重构表单,解决已知 bug
### ⚡ Performance Improvements
...
...
@@ -30,6 +72,7 @@
### 🎫 Chores
-
升级
`ant-design-vue`
到
`2.0.0-rc.7`
-
升级
`vue`
到
`3.0.5`
### 🐛 Bug Fixes
...
...
mock/demo/table-demo.ts
浏览文件 @
9c2f3f30
...
...
@@ -10,6 +10,14 @@ const demoList = (() => {
endTime
:
'
@datetime
'
,
address
:
'
@city()
'
,
name
:
'
@cname()
'
,
name1
:
'
@cname()
'
,
name2
:
'
@cname()
'
,
name3
:
'
@cname()
'
,
name4
:
'
@cname()
'
,
name5
:
'
@cname()
'
,
name6
:
'
@cname()
'
,
name7
:
'
@cname()
'
,
name8
:
'
@cname()
'
,
'
no|100000-10000000
'
:
100000
,
'
status|1
'
:
[
'
normal
'
,
'
enable
'
,
'
disable
'
],
});
...
...
src/components/Form/index.ts
浏览文件 @
9c2f3f30
...
...
@@ -9,4 +9,7 @@ export * from './src/types/formItem';
export
{
useComponentRegister
}
from
'
./src/hooks/useComponentRegister
'
;
export
{
useForm
}
from
'
./src/hooks/useForm
'
;
export
{
default
as
ApiSelect
}
from
'
./src/components/ApiSelect.vue
'
;
export
{
default
as
RadioButtonGroup
}
from
'
./src/components/RadioButtonGroup.vue
'
;
export
{
BasicForm
};
src/components/Form/src/components/ApiSelect.vue
浏览文件 @
9c2f3f30
...
...
@@ -50,7 +50,8 @@
labelField
:
propTypes
.
string
.
def
(
'
label
'
),
valueField
:
propTypes
.
string
.
def
(
'
value
'
),
},
setup
(
props
)
{
emits
:
[
'
options-change
'
,
'
change
'
],
setup
(
props
,
{
emit
})
{
const
options
=
ref
<
OptionsItem
[]
>
([]);
const
loading
=
ref
(
false
);
const
attrs
=
useAttrs
();
...
...
@@ -86,11 +87,13 @@
const
res
=
await
api
(
props
.
params
);
if
(
Array
.
isArray
(
res
))
{
options
.
value
=
res
;
emit
(
'
options-change
'
,
unref
(
options
));
return
;
}
if
(
props
.
resultField
)
{
options
.
value
=
get
(
res
,
props
.
resultField
)
||
[];
}
emit
(
'
options-change
'
,
unref
(
options
));
}
catch
(
error
)
{
console
.
warn
(
error
);
}
finally
{
...
...
src/components/Menu/src/useOpenKeys.ts
浏览文件 @
9c2f3f30
...
...
@@ -15,7 +15,7 @@ export function useOpenKeys(
mode
:
Ref
<
MenuModeEnum
>
,
accordion
:
Ref
<
boolean
>
)
{
const
{
getCollapsed
}
=
useMenuSetting
();
const
{
getCollapsed
,
getIsMixSidebar
}
=
useMenuSetting
();
function
setOpenKeys
(
path
:
string
)
{
if
(
mode
.
value
===
MenuModeEnum
.
HORIZONTAL
)
{
...
...
@@ -30,7 +30,9 @@ export function useOpenKeys(
}
const
getOpenKeys
=
computed
(()
=>
{
return
unref
(
getCollapsed
)
?
menuState
.
collapsedOpenKeys
:
menuState
.
openKeys
;
const
collapse
=
unref
(
getIsMixSidebar
)
?
false
:
unref
(
getCollapsed
);
return
collapse
?
menuState
.
collapsedOpenKeys
:
menuState
.
openKeys
;
});
/**
...
...
@@ -42,7 +44,7 @@ export function useOpenKeys(
}
function
handleOpenChange
(
openKeys
:
string
[])
{
if
(
unref
(
mode
)
===
MenuModeEnum
.
HORIZONTAL
||
!
unref
(
accordion
))
{
if
(
unref
(
mode
)
===
MenuModeEnum
.
HORIZONTAL
||
!
unref
(
accordion
)
||
unref
(
getIsMixSidebar
)
)
{
menuState
.
openKeys
=
openKeys
;
}
else
{
// const menuList = toRaw(menus.value);
...
...
src/components/Table/index.ts
浏览文件 @
9c2f3f30
...
...
@@ -3,7 +3,6 @@ import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
export
{
default
as
BasicTable
}
from
'
./src/BasicTable.vue
'
;
export
{
default
as
TableAction
}
from
'
./src/components/TableAction.vue
'
;
// export { default as TableImg } from './src/components/TableImg.vue';
export
{
renderEditableCell
,
renderEditableRow
}
from
'
./src/components/renderEditable
'
;
export
{
default
as
EditTableHeaderIcon
}
from
'
./src/components/EditTableHeaderIcon.vue
'
;
export
const
TableImg
=
createAsyncComponent
(()
=>
import
(
'
./src/components/TableImg.vue
'
));
...
...
@@ -17,4 +16,4 @@ export { useTable } from './src/hooks/useTable';
export
type
{
FormSchema
,
FormProps
}
from
'
/@/components/Form/src/types/form
'
;
export
type
{
EditRecordRow
}
from
'
./src/components/
renderE
ditable
'
;
export
type
{
EditRecordRow
}
from
'
./src/components/
e
ditable
'
;
src/components/Table/src/BasicTable.vue
浏览文件 @
9c2f3f30
...
...
@@ -34,19 +34,19 @@
<
template
#[item]=
"data"
v-for=
"item in Object.keys($slots)"
>
<slot
:name=
"item"
v-bind=
"data"
/>
</
template
>
<
template
#
[`
header-
${
column.dataIndex
}`]
v-for=
"column in columns"
:key=
"column.dataIndex"
>
<HeaderCell
:column=
"column"
/>
</
template
>
</Table>
</div>
</template>
<
script
lang=
"ts"
>
import
type
{
BasicTableProps
,
TableActionType
,
SizeType
,
SorterResult
}
from
'
./types/table
'
;
import
{
PaginationProps
}
from
'
./types/pagination
'
;
import
type
{
BasicTableProps
,
TableActionType
,
SizeType
}
from
'
./types/table
'
;
import
{
defineComponent
,
ref
,
computed
,
unref
}
from
'
vue
'
;
import
{
Table
}
from
'
ant-design-vue
'
;
import
{
BasicForm
,
useForm
}
from
'
/@/components/Form/index
'
;
import
{
isFunction
}
from
'
/@/utils/is
'
;
import
{
omit
}
from
'
lodash-es
'
;
import
{
usePagination
}
from
'
./hooks/usePagination
'
;
...
...
@@ -61,15 +61,20 @@
import
{
createTableContext
}
from
'
./hooks/useTableContext
'
;
import
{
useTableFooter
}
from
'
./hooks/useTableFooter
'
;
import
{
useTableForm
}
from
'
./hooks/useTableForm
'
;
import
{
useExpose
}
from
'
/@/hooks/core/useExpose
'
;
import
{
useDesign
}
from
'
/@/hooks/web/useDesign
'
;
import
{
basicProps
}
from
'
./props
'
;
import
{
useExpose
}
from
'
/@/hooks/core/useExpose
'
;
import
{
createAsyncComponent
}
from
'
/@/utils/factory/createAsyncComponent
'
;
import
'
./style/index.less
'
;
import
{
useDesign
}
from
'
/@/hooks/web/useDesign
'
;
export
default
defineComponent
({
props
:
basicProps
,
components
:
{
Table
,
BasicForm
},
components
:
{
Table
,
BasicForm
,
HeaderCell
:
createAsyncComponent
(()
=>
import
(
'
./components/HeaderCell.vue
'
)),
},
emits
:
[
'
fetch-success
'
,
'
fetch-error
'
,
...
...
@@ -80,6 +85,8 @@
'
row-contextmenu
'
,
'
row-mouseenter
'
,
'
row-mouseleave
'
,
'
edit-end
'
,
'
edit-cancel
'
,
],
setup
(
props
,
{
attrs
,
emit
,
slots
})
{
const
tableElRef
=
ref
<
ComponentRef
>
(
null
);
...
...
@@ -96,15 +103,19 @@
const
{
getLoading
,
setLoading
}
=
useLoading
(
getProps
);
const
{
getPaginationInfo
,
getPagination
,
setPagination
}
=
usePagination
(
getProps
);
const
{
getSortFixedColumns
,
getColumns
,
setColumns
,
getColumnsRef
,
getCacheColumns
,
}
=
useColumns
(
getProps
,
getPaginationInfo
);
getRowSelection
,
getRowSelectionRef
,
getSelectRows
,
clearSelectedRowKeys
,
getSelectRowKeys
,
deleteSelectRowByKey
,
setSelectedRowKeys
,
}
=
useRowSelection
(
getProps
,
emit
);
const
{
handleTableChange
,
getDataSourceRef
,
getDataSource
,
setTableData
,
...
...
@@ -112,6 +123,7 @@
getRowKey
,
reload
,
getAutoCreateKey
,
updateTableData
,
}
=
useDataSource
(
getProps
,
{
...
...
@@ -119,19 +131,15 @@
setLoading
,
setPagination
,
getFieldsValue
:
formActions
.
getFieldsValue
,
clearSelectedRowKeys
,
},
emit
);
const
{
getRowSelection
,
getRowSelectionRef
,
getSelectRows
,
clearSelectedRowKeys
,
getSelectRowKeys
,
deleteSelectRowByKey
,
setSelectedRowKeys
,
}
=
useRowSelection
(
getProps
,
emit
);
const
{
getViewColumns
,
getColumns
,
setColumns
,
getColumnsRef
,
getCacheColumns
}
=
useColumns
(
getProps
,
getPaginationInfo
);
const
{
getScrollRef
,
redoHeight
}
=
useTableScroll
(
getProps
,
...
...
@@ -178,7 +186,7 @@
tableLayout
:
'
fixed
'
,
rowSelection
:
unref
(
getRowSelectionRef
),
rowKey
:
unref
(
getRowKey
),
columns
:
unref
(
get
SortFixed
Columns
),
columns
:
unref
(
get
View
Columns
),
pagination
:
unref
(
getPaginationInfo
),
dataSource
:
unref
(
getDataSourceRef
),
footer
:
unref
(
getFooterProps
),
...
...
@@ -197,26 +205,6 @@
return
!!
unref
(
getDataSourceRef
).
length
;
});
function
handleTableChange
(
pagination
:
PaginationProps
,
// @ts-ignore
filters
:
Partial
<
Recordable
<
string
[]
>>
,
sorter
:
SorterResult
)
{
const
{
clearSelectOnPageChange
,
sortFn
}
=
unref
(
getProps
);
if
(
clearSelectOnPageChange
)
{
clearSelectedRowKeys
();
}
setPagination
(
pagination
);
if
(
sorter
&&
isFunction
(
sortFn
))
{
const
sortInfo
=
sortFn
(
sorter
);
fetch
({
sortInfo
});
return
;
}
fetch
();
}
function
setProps
(
props
:
Partial
<
BasicTableProps
>
)
{
innerPropsRef
.
value
=
{
...
unref
(
innerPropsRef
),
...
props
};
}
...
...
@@ -239,6 +227,8 @@
getPaginationRef
:
getPagination
,
getColumns
,
getCacheColumns
,
emit
,
updateTableData
,
getSize
:
()
=>
{
return
unref
(
getBindValues
).
size
as
SizeType
;
},
...
...
@@ -265,6 +255,7 @@
replaceFormSlotKey
,
getFormSlotKeys
,
prefixCls
,
columns
:
getViewColumns
,
};
},
});
...
...
src/components/Table/src/componentMap.ts
浏览文件 @
9c2f3f30
import
{
Component
}
from
'
vue
'
;
import
type
{
Component
}
from
'
vue
'
;
import
{
Input
,
Select
,
Checkbox
,
InputNumber
,
Switch
}
from
'
ant-design-vue
'
;
import
{
ComponentType
}
from
'
./types/componentType
'
;
import
type
{
ComponentType
}
from
'
./types/componentType
'
;
import
{
ApiSelect
}
from
'
/@/components/Form
'
;
const
componentMap
=
new
Map
<
ComponentType
,
Component
>
();
componentMap
.
set
(
'
Input
'
,
Input
);
componentMap
.
set
(
'
InputPassword
'
,
Input
.
Password
);
componentMap
.
set
(
'
InputNumber
'
,
InputNumber
);
componentMap
.
set
(
'
Select
'
,
Select
);
componentMap
.
set
(
'
ApiSelect
'
,
ApiSelect
);
componentMap
.
set
(
'
Switch
'
,
Switch
);
componentMap
.
set
(
'
Checkbox
'
,
Checkbox
);
componentMap
.
set
(
'
CheckboxGroup
'
,
Checkbox
.
Group
);
export
function
add
(
compName
:
ComponentType
,
component
:
Component
)
{
componentMap
.
set
(
compName
,
component
);
...
...
src/components/Table/src/components/EditTableHeaderIcon.vue
浏览文件 @
9c2f3f30
<
template
>
<span>
<slot
/>
{{
title
}}
<FormOutlined
class=
"ml-2"
/>
<FormOutlined
/>
</span>
</
template
>
<
script
lang=
"ts"
>
...
...
src/components/Table/src/components/HeaderCell.vue
0 → 100644
浏览文件 @
9c2f3f30
<
template
>
<EditTableHeaderCell
v-if=
"getIsEdit"
>
{{
getTitle
}}
</EditTableHeaderCell>
<span
v-else
>
{{
getTitle
}}
</span>
<BasicHelp
v-if=
"getHelpMessage"
:text=
"getHelpMessage"
:class=
"`$
{prefixCls}__help`" />
</
template
>
<
script
lang=
"ts"
>
import
type
{
PropType
}
from
'
vue
'
;
import
type
{
BasicColumn
}
from
'
../types/table
'
;
import
{
defineComponent
,
computed
}
from
'
vue
'
;
import
{
createAsyncComponent
}
from
'
/@/utils/factory/createAsyncComponent
'
;
import
{
useDesign
}
from
'
/@/hooks/web/useDesign
'
;
export
default
defineComponent
({
name
:
'
TableHeaderCell
'
,
components
:
{
EditTableHeaderCell
:
createAsyncComponent
(()
=>
import
(
'
./EditTableHeaderIcon.vue
'
)),
BasicHelp
:
createAsyncComponent
(()
=>
import
(
'
/@/components/Basic/src/BasicHelp.vue
'
)),
},
props
:
{
column
:
{
type
:
Object
as
PropType
<
BasicColumn
>
,
default
:
{},
},
},
setup
(
props
)
{
const
{
prefixCls
}
=
useDesign
(
'
basic-table-header-cell
'
);
const
getIsEdit
=
computed
(()
=>
{
return
!!
props
.
column
?.
edit
;
});
const
getTitle
=
computed
(()
=>
{
return
props
.
column
?.
customTitle
;
});
const
getHelpMessage
=
computed
(()
=>
{
return
props
.
column
?.
helpMessage
;
});
return
{
prefixCls
,
getIsEdit
,
getTitle
,
getHelpMessage
};
},
});
</
script
>
<
style
lang=
"less"
>
@prefix-cls: ~'@{namespace}-basic-table-header-cell';
.@{prefix-cls} {
&__help {
margin-left: 8px;
color: rgba(0, 0, 0, 0.65) !important;
}
}
</
style
>
src/components/Table/src/components/TableAction.vue
浏览文件 @
9c2f3f30
<
template
>
<div
:class=
"[prefixCls, getAlign]"
>
<template
v-for=
"(action, index) in getActions"
:key=
"`$
{index}`">
<template
v-for=
"(action, index) in getActions"
:key=
"`$
{index}
-${action.label}
`">
<PopConfirmButton
v-bind=
"action"
>
<Icon
:icon=
"action.icon"
class=
"mr-1"
v-if=
"action.icon"
/>
{{
action
.
label
}}
</PopConfirmButton>
<Divider
type=
"vertical"
v-if=
"divider && index
<
getActions.length
"
/>
</
template
>
<Dropdown
:trigger=
"['hover']"
:dropMenuList=
"getDropList"
>
<Dropdown
:trigger=
"['hover']"
:dropMenuList=
"getDropList"
v-if=
"dropDownActions"
>
<slot
name=
"more"
/>
<a-button
type=
"link"
size=
"small"
v-if=
"!$slots.more"
>
<MoreOutlined
class=
"icon-more"
/>
...
...
@@ -61,7 +60,7 @@
});
const
getDropList
=
computed
(()
=>
{
return
props
.
dropDownActions
.
map
((
action
,
index
)
=>
{
return
(
props
.
dropDownActions
||
[])
.
map
((
action
,
index
)
=>
{
const
{
label
}
=
action
;
return
{
...
action
,
...
...
src/components/Table/src/components/editable/CellComponent.ts
0 → 100644
浏览文件 @
9c2f3f30
import
type
{
FunctionalComponent
,
defineComponent
}
from
'
vue
'
;
import
type
{
ComponentType
}
from
'
../../types/componentType
'
;
import
{
componentMap
}
from
'
/@/components/Table/src/componentMap
'
;
import
{
Popover
}
from
'
ant-design-vue
'
;
import
{
h
}
from
'
vue
'
;
export
interface
ComponentProps
{
component
:
ComponentType
;
rule
:
boolean
;
popoverVisible
:
boolean
;
ruleMessage
:
string
;
}
export
const
CellComponent
:
FunctionalComponent
=
(
{
component
=
'
Input
'
,
rule
=
true
,
ruleMessage
,
popoverVisible
}:
ComponentProps
,
{
attrs
}
)
=>
{
const
Comp
=
componentMap
.
get
(
component
)
as
typeof
defineComponent
;
const
DefaultComp
=
h
(
Comp
,
attrs
);
if
(
!
rule
)
{
return
DefaultComp
;
}
return
h
(
Popover
,
{
overlayClassName
:
'
edit-cell-rule-popover
'
,
visible
:
!!
popoverVisible
},
{
default
:
()
=>
DefaultComp
,
content
:
()
=>
ruleMessage
,
}
);
};
src/components/Table/src/components/editable/EditableCell.vue
0 → 100644
浏览文件 @
9c2f3f30
<
template
>
<div
:class=
"prefixCls"
>
<div
v-show=
"!isEdit"
:class=
"`$
{prefixCls}__normal`" @click="handleEdit">
{{
value
||
'
'
}}
<FormOutlined
:class=
"`$
{prefixCls}__normal-icon`" v-if="!column.editRow" />
</div>
<div
v-if=
"isEdit"
:class=
"`$
{prefixCls}__wrapper`" v-click-outside="onClickOutside">
<CellComponent
v-bind=
"getComponentProps"
:component=
"getComponent"
:style=
"getWrapperStyle"
:popoverVisible=
"getRuleVisible"
:rule=
"getRule"
:ruleMessage=
"ruleMessage"
size=
"small"
ref=
"elRef"
@
change=
"handleChange"
@
options-change=
"handleOptionsChange"
@
pressEnter=
"handleSubmit"
>
</CellComponent>
<div
:class=
"`$
{prefixCls}__action`" v-if="!getRowEditable">
<CheckOutlined
:class=
"[`$
{prefixCls}__icon`, 'mx-2']" @click="handleSubmit" />
<CloseOutlined
:class=
"`$
{prefixCls}__icon `" @click="handleCancel" />
</div>
</div>
</div>
</
template
>
<
script
lang=
"ts"
>
import
type
{
CSSProperties
,
PropType
}
from
'
vue
'
;
import
type
{
BasicColumn
}
from
'
../../types/table
'
;
import
{
defineComponent
,
ref
,
unref
,
nextTick
,
computed
,
watchEffect
,
toRaw
}
from
'
vue
'
;
import
{
FormOutlined
,
CloseOutlined
,
CheckOutlined
}
from
'
@ant-design/icons-vue
'
;
import
{
useDesign
}
from
'
/@/hooks/web/useDesign
'
;
import
{
isString
,
isBoolean
,
isFunction
,
isNumber
,
isArray
}
from
'
/@/utils/is
'
;
import
clickOutside
from
'
/@/directives/clickOutside
'
;
import
{
CellComponent
}
from
'
./CellComponent
'
;
import
{
useTableContext
}
from
'
../../hooks/useTableContext
'
;
import
{
propTypes
}
from
'
/@/utils/propTypes
'
;
import
{
createPlaceholderMessage
}
from
'
./helper
'
;
import
type
{
EditRecordRow
}
from
'
./index
'
;
export
default
defineComponent
({
name
:
'
EditableCell
'
,
components
:
{
FormOutlined
,
CloseOutlined
,
CheckOutlined
,
CellComponent
},
props
:
{
value
:
{
type
:
[
String
,
Number
,
Boolean
,
Object
]
as
PropType
<
string
|
number
|
boolean
|
Recordable
>
,
default
:
''
,
},
record
:
{
type
:
Object
as
PropType
<
EditRecordRow
>
,
},
column
:
{
type
:
Object
as
PropType
<
BasicColumn
>
,
default
:
{},
},
index
:
propTypes
.
number
,
},
directives
:
{
clickOutside
,
},
setup
(
props
)
{
const
table
=
useTableContext
();
const
isEdit
=
ref
(
false
);
const
elRef
=
ref
<
any
>
(
null
);
const
ruleVisible
=
ref
(
false
);
const
ruleMessage
=
ref
(
''
);
const
optionsRef
=
ref
<
LabelValueOptions
>
([]);
const
currentValueRef
=
ref
<
any
>
(
props
.
value
);
const
defaultValueRef
=
ref
<
any
>
(
props
.
value
);
const
{
prefixCls
}
=
useDesign
(
'
editable-cell
'
);
const
getComponent
=
computed
(()
=>
props
.
column
?.
editComponent
||
'
Input
'
);
const
getRule
=
computed
(()
=>
props
.
column
?.
editRule
);
const
getRuleVisible
=
computed
(()
=>
{
return
unref
(
ruleMessage
)
&&
unref
(
ruleVisible
);
});
const
getIsCheckComp
=
computed
(()
=>
{
const
component
=
unref
(
getComponent
);
return
[
'
Checkbox
'
,
'
Switch
'
].
includes
(
component
);
});
const
getComponentProps
=
computed
(()
=>
{
const
compProps
=
props
.
column
?.
editComponentProps
??
{};
const
component
=
unref
(
getComponent
);
const
apiSelectProps
:
Recordable
=
{};
if
(
component
===
'
ApiSelect
'
)
{
apiSelectProps
.
cache
=
true
;
}
const
isCheckValue
=
unref
(
getIsCheckComp
);
const
valueField
=
isCheckValue
?
'
checked
'
:
'
value
'
;
const
val
=
unref
(
currentValueRef
);
const
value
=
isCheckValue
?
(
isNumber
(
val
)
&&
isBoolean
(
val
)
?
val
:
!!
val
)
:
val
;
return
{
placeholder
:
createPlaceholderMessage
(
unref
(
getComponent
)),
...
apiSelectProps
,
...
compProps
,
[
valueField
]:
value
,
};
});
const
getValues
=
computed
(()
=>
{
const
{
editComponentProps
,
editValueMap
}
=
props
.
column
;
const
value
=
unref
(
currentValueRef
);
if
(
editValueMap
&&
isFunction
(
editValueMap
))
{
return
editValueMap
(
value
);
}
const
component
=
unref
(
getComponent
);
if
(
!
component
.
includes
(
'
Select
'
))
{
return
value
;
}
const
options
:
LabelValueOptions
=
editComponentProps
?.
options
??
(
unref
(
optionsRef
)
||
[]);
const
option
=
options
.
find
((
item
)
=>
`
${
item
.
value
}
`
===
`
${
value
}
`
);
return
option
?.
label
;
});
const
getWrapperStyle
=
computed
(
():
CSSProperties
=>
{
if
(
unref
(
getIsCheckComp
)
||
unref
(
getRowEditable
))
{
return
{};
}
return
{
width
:
'
calc(100% - 48px)
'
,
};
}
);
const
getRowEditable
=
computed
(()
=>
{
const
{
editable
}
=
props
.
record
||
{};
return
!!
editable
;
});
watchEffect
(()
=>
{
defaultValueRef
.
value
=
props
.
value
;
});
watchEffect
(()
=>
{
const
{
editable
}
=
props
.
column
;
if
(
isBoolean
(
editable
)
||
isBoolean
(
unref
(
getRowEditable
)))
{
isEdit
.
value
=
!!
editable
||
unref
(
getRowEditable
);
}
});
function
handleEdit
()
{
if
(
unref
(
getRowEditable
)
||
unref
(
props
.
column
?.
editRow
))
return
;
ruleMessage
.
value
=
''
;
isEdit
.
value
=
true
;
nextTick
(()
=>
{
const
el
=
unref
(
elRef
);
el
?.
focus
?.();
});
}
async
function
handleChange
(
e
:
any
)
{
const
component
=
unref
(
getComponent
);
if
(
e
?.
target
&&
Reflect
.
has
(
e
.
target
,
'
value
'
))
{
currentValueRef
.
value
=
(
e
as
ChangeEvent
).
target
.
value
;
}
if
(
component
===
'
Checkbox
'
)
{
currentValueRef
.
value
=
(
e
as
ChangeEvent
).
target
.
checked
;
}
else
if
(
isString
(
e
)
||
isBoolean
(
e
)
||
isNumber
(
e
))
{
currentValueRef
.
value
=
e
;
}
handleSubmiRule
();
}
async
function
handleSubmiRule
()
{
const
{
column
,
record
}
=
props
;
const
{
editRule
}
=
column
;
const
currentValue
=
unref
(
currentValueRef
);
if
(
editRule
)
{
if
(
isBoolean
(
editRule
)
&&
!
currentValue
&&
!
isNumber
(
currentValue
))
{
ruleVisible
.
value
=
true
;
const
component
=
unref
(
getComponent
);
const
message
=
createPlaceholderMessage
(
component
);
ruleMessage
.
value
=
message
;
return
false
;
}
if
(
isFunction
(
editRule
))
{
const
res
=
await
editRule
(
currentValue
,
record
as
Recordable
);
if
(
!!
res
)
{
ruleMessage
.
value
=
res
;
ruleVisible
.
value
=
true
;
return
false
;
}
else
{
ruleMessage
.
value
=
''
;
return
true
;
}
}
}
ruleMessage
.
value
=
''
;
return
true
;
}
async
function
handleSubmit
()
{
const
isPass
=
await
handleSubmiRule
();
if
(
!
isPass
)
return
false
;
const
{
column
,
index
}
=
props
;
const
{
key
,
dataIndex
}
=
column
;
// const value = unref(currentValueRef);
if
(
!
key
||
!
dataIndex
)
return
;
const
dataKey
=
(
dataIndex
||
key
)
as
string
;
const
record
=
await
table
.
updateTableData
(
index
,
dataKey
,
unref
(
getValues
));
table
.
emit
?.(
'
edit-end
'
,
{
record
,
index
,
key
,
value
:
unref
(
currentValueRef
)
});
isEdit
.
value
=
false
;
}
function
handleCancel
()
{
isEdit
.
value
=
false
;
currentValueRef
.
value
=
defaultValueRef
.
value
;
table
.
emit
?.(
'
edit-cancel
'
,
unref
(
currentValueRef
));
}
function
onClickOutside
()
{
if
(
props
.
column
?.
editable
||
unref
(
getRowEditable
))
{
return
;
}
const
component
=
unref
(
getComponent
);
if
(
component
.
includes
(
'
Input
'
))
{
handleCancel
();
}
}
// only ApiSelect
function
handleOptionsChange
(
options
:
LabelValueOptions
)
{
optionsRef
.
value
=
options
;
}
function
initCbs
(
cbs
:
'
submitCbs
'
|
'
validCbs
'
|
'
cancelCbs
'
,
handle
:
Fn
)
{
if
(
props
.
record
)
{
/* eslint-disable */
isArray
(
props
.
record
[
cbs
])
?
props
.
record
[
cbs
].
push
(
handle
)
:
(
props
.
record
[
cbs
]
=
[
handle
]);
}
}
if
(
props
.
record
)
{
initCbs
(
'
submitCbs
'
,
handleSubmit
);
initCbs
(
'
validCbs
'
,
handleSubmiRule
);
initCbs
(
'
cancelCbs
'
,
handleCancel
);
/* eslint-disable */
props
.
record
.
onCancelEdit
=
()
=>
{
isArray
(
props
.
record
?.
cancelCbs
)
&&
props
.
record
?.
cancelCbs
.
forEach
((
fn
)
=>
fn
());
};
/* eslint-disable */
props
.
record
.
onSubmitEdit
=
async
()
=>
{
if
(
isArray
(
props
.
record
?.
submitCbs
))
{
const
validFns
=
props
.
record
?.
validCbs
||
[];
const
res
=
await
Promise
.
all
(
validFns
.
map
((
fn
)
=>
fn
()));
const
pass
=
res
.
every
((
item
)
=>
!!
item
);
if
(
!
pass
)
return
;
const
submitFns
=
props
.
record
?.
submitCbs
||
[];
submitFns
.
forEach
((
fn
)
=>
fn
());
return
true
;
}
// isArray(props.record?.submitCbs) && props.record?.submitCbs.forEach((fn) => fn());
};
}
return
{
isEdit
,
prefixCls
,
handleEdit
,
currentValueRef
,
handleSubmit
,
handleChange
,
handleCancel
,
elRef
,
getComponent
,
getRule
,
onClickOutside
,
ruleMessage
,
getRuleVisible
,
getComponentProps
,
handleOptionsChange
,
getWrapperStyle
,
getRowEditable
,
};
},
});
</
script
>
<
style
lang=
"less"
>
@prefix-cls: ~'@{namespace}-editable-cell';
.edit-cell-rule-popover {
// .ant-popover-arrow {
// // border-color: transparent @error-color @error-color transparent !important;
// }
.ant-popover-inner-content {
padding: 4px 8px;
color: @error-color;
// border: 1px solid @error-color;
border-radius: 2px;
}
}
.@{prefix-cls} {
position: relative;
&__wrapper {
display: flex;
align-items: center;
justify-content: center;
}
&__icon {
&:hover {
transform: scale(1.2);
svg {
color: @primary-color;
}
}
}
&__normal {
padding-right: 48px;
&-icon {
position: absolute;
top: 4px;
right: 0;
display: none;
width: 20px;
cursor: pointer;
}
}
&:hover {
.@{prefix-cls}__normal-icon {
display: inline-block;
}
}
}
</
style
>
src/components/Table/src/components/editable/helper.ts
0 → 100644
浏览文件 @
9c2f3f30
import
{
ComponentType
}
from
'
../../types/componentType
'
;
import
{
useI18n
}
from
'
/@/hooks/web/useI18n
'
;
const
{
t
}
=
useI18n
();
/**
* @description: 生成placeholder
*/
export
function
createPlaceholderMessage
(
component
:
ComponentType
)
{
if
(
component
.
includes
(
'
Input
'
))
{
return
t
(
'
component.form.input
'
);
}
if
(
component
.
includes
(
'
Picker
'
))
{
return
t
(
'
component.form.choose
'
);
}
if
(
component
.
includes
(
'
Select
'
)
||
component
.
includes
(
'
Checkbox
'
)
||
component
.
includes
(
'
Radio
'
)
||
component
.
includes
(
'
Switch
'
)
)
{
return
t
(
'
component.form.choose
'
);
}
return
''
;
}
src/components/Table/src/components/editable/index.ts
0 → 100644
浏览文件 @
9c2f3f30
import
type
{
BasicColumn
}
from
'
/@/components/Table/src/types/table
'
;
import
{
h
}
from
'
vue
'
;
import
EditableCell
from
'
./EditableCell.vue
'
;
interface
Params
{
text
:
string
;
record
:
Recordable
;
index
:
number
;
}
export
function
renderEditCell
(
column
:
BasicColumn
)
{
return
({
text
:
value
,
record
,
index
}:
Params
)
=>
{
record
.
onEdit
=
async
(
edit
:
boolean
,
submit
=
false
)
=>
{
if
(
!
submit
)
{
record
.
editable
=
edit
;
}
if
(
!
edit
&&
submit
)
{
const
res
=
await
record
.
onSubmitEdit
?.();
if
(
res
)
{
record
.
editable
=
false
;
return
true
;
}
return
false
;
}
// cancel
if
(
!
edit
&&
!
submit
)
{
record
.
onCancelEdit
?.();
}
return
true
;
};
return
h
(
EditableCell
,
{
value
,
record
,
column
,
index
,
});
};
}
export
type
EditRecordRow
<
T
=
Hash
<
any
>>
=
{
onEdit
:
(
editable
:
boolean
,
submit
?:
boolean
)
=>
Promise
<
boolean
>
;
editable
:
boolean
;
onCancel
:
Fn
;
onSubmit
:
Fn
;
submitCbs
:
Fn
[];
cancelCbs
:
Fn
[];
validCbs
:
Fn
[];
}
&
T
;
src/components/Table/src/components/renderEditable.tsx
已删除
100644 → 0
浏览文件 @
f3a70eed
import
'
../style/editable-cell.less
'
;
import
{
defineComponent
,
PropType
,
ref
,
unref
,
nextTick
,
watchEffect
}
from
'
vue
'
;
import
{
ClickOutSide
}
from
'
/@/components/ClickOutSide
'
;
import
{
RenderEditableCellParams
}
from
'
../types/table
'
;
import
{
ComponentType
}
from
'
../types/componentType
'
;
import
{
componentMap
}
from
'
../componentMap
'
;
import
{
isString
,
isBoolean
,
isArray
}
from
'
/@/utils/is
'
;
import
{
FormOutlined
,
CloseOutlined
,
CheckOutlined
}
from
'
@ant-design/icons-vue
'
;
const
prefixCls
=
'
editable-cell
'
;
const
EditableCell
=
defineComponent
({
name
:
'
EditableCell
'
,
props
:
{
value
:
{
type
:
String
as
PropType
<
string
>
,
default
:
''
,
},
componentProps
:
{
type
:
Object
as
PropType
<
any
>
,
default
:
null
,
},
dataKey
:
{
type
:
String
as
PropType
<
string
>
,
default
:
''
,
},
dataIndex
:
{
type
:
String
as
PropType
<
string
>
,
default
:
''
,
},
component
:
{
type
:
String
as
PropType
<
ComponentType
>
,
default
:
'
Input
'
,
},
editable
:
{
type
:
Boolean
as
PropType
<
boolean
>
,
default
:
false
,
},
editRow
:
{
type
:
Boolean
as
PropType
<
boolean
>
,
default
:
false
,
},
record
:
{
type
:
Object
as
PropType
<
EditRecordRow
>
,
},
placeholder
:
{
type
:
String
as
PropType
<
string
>
,
default
:
''
,
},
},
emits
:
[
'
submit
'
,
'
cancel
'
],
setup
(
props
,
{
attrs
,
emit
})
{
const
elRef
=
ref
<
any
>
(
null
);
const
isEditRef
=
ref
(
false
);
const
currentValueRef
=
ref
<
string
|
boolean
>
(
props
.
value
);
const
defaultValueRef
=
ref
<
string
|
boolean
>
(
props
.
value
);
watchEffect
(()
=>
{
defaultValueRef
.
value
=
props
.
value
;
if
(
isBoolean
(
props
.
editable
))
{
isEditRef
.
value
=
props
.
editable
;
}
});
function
handleChange
(
e
:
any
)
{
if
(
e
&&
e
.
target
&&
Reflect
.
has
(
e
.
target
,
'
value
'
))
{
currentValueRef
.
value
=
(
e
as
ChangeEvent
).
target
.
value
;
}
if
(
isString
(
e
)
||
isBoolean
(
e
))
{
currentValueRef
.
value
=
e
;
}
}
function
handleEdit
()
{
isEditRef
.
value
=
true
;
nextTick
(()
=>
{
const
el
=
unref
(
elRef
);
el
&&
el
.
focus
();
});
}
function
handleCancel
()
{
isEditRef
.
value
=
false
;
currentValueRef
.
value
=
defaultValueRef
.
value
;
emit
(
'
cancel
'
);
}
if
(
props
.
record
)
{
/* eslint-disable */
isArray
(
props
.
record
.
submitCbs
)
?
props
.
record
.
submitCbs
.
push
(
handleSubmit
)
:
(
props
.
record
.
submitCbs
=
[
handleSubmit
]);
/* eslint-disable */
isArray
(
props
.
record
.
cancelCbs
)
?
props
.
record
.
cancelCbs
.
push
(
handleCancel
)
:
(
props
.
record
.
cancelCbs
=
[
handleCancel
]);
/* eslint-disable */
props
.
record
.
onCancel
=
()
=>
{
isArray
(
props
.
record
?.
cancelCbs
)
&&
props
.
record
?.
cancelCbs
.
forEach
((
fn
)
=>
fn
());
};
/* eslint-disable */
props
.
record
.
onSubmit
=
()
=>
{
isArray
(
props
.
record
?.
submitCbs
)
&&
props
.
record
?.
submitCbs
.
forEach
((
fn
)
=>
fn
());
};
}
function
handleSubmit
()
{
const
{
dataKey
,
dataIndex
}
=
props
;
if
(
!
dataKey
||
!
dataIndex
)
return
;
if
(
props
.
record
)
{
/* eslint-disable */
props
.
record
[
dataIndex
]
=
unref
(
currentValueRef
)
as
string
;
}
isEditRef
.
value
=
false
;
}
function
onClickOutside
()
{
if
(
props
.
editRow
)
return
;
const
{
component
}
=
props
;
if
(
component
&&
component
.
includes
(
'
Input
'
))
{
handleCancel
();
}
}
function
renderValue
()
{
const
{
value
}
=
props
;
if
(
props
.
editRow
)
{
return
!
unref
(
isEditRef
)
?
value
:
null
;
}
return
(
!
unref
(
isEditRef
)
&&
(
<
div
class
=
{
`
${
prefixCls
}
__normal`
}
onClick
=
{
handleEdit
}
>
{
value
}
<
FormOutlined
class
=
{
`
${
prefixCls
}
__normal-icon`
}
/>
</
div
>
)
);
}
return
()
=>
{
const
{
component
,
componentProps
=
{}
}
=
props
;
const
Comp
=
componentMap
.
get
(
component
!
)
as
any
;
return
(
<
div
class
=
{
prefixCls
}
>
{
unref
(
isEditRef
)
&&
(
<
ClickOutSide
onClickOutside
=
{
onClickOutside
}
>
{
()
=>
(
<
div
class
=
{
`
${
prefixCls
}
__wrapper`
}
>
<
Comp
placeholder
=
{
props
.
placeholder
}
{
...{
...
attrs
,
...
componentProps
,
}
}
style
=
{
{
width
:
'
calc(100% - 48px)
'
}
}
ref
=
{
elRef
}
value
=
{
unref
(
currentValueRef
)
}
size
=
"small"
onChange
=
{
handleChange
}
onPressEnter
=
{
handleSubmit
}
/>
{
!
props
.
editRow
&&
(
<
div
class
=
{
`
${
prefixCls
}
__action`
}
>
<
CheckOutlined
class
=
{
[
`
${
prefixCls
}
__icon`
,
'
mx-2
'
]
}
onClick
=
{
handleSubmit
}
/>
<
CloseOutlined
class
=
{
[
`
${
prefixCls
}
__icon `
]
}
onClick
=
{
handleCancel
}
/>
</
div
>
)
}
</
div
>
)
}
</
ClickOutSide
>
)
}
{
renderValue
()
}
</
div
>
);
};
},
});
export
function
renderEditableCell
({
dataIndex
,
component
,
componentProps
=
{},
placeholder
,
}:
RenderEditableCellParams
)
{
return
({
text
,
record
}:
{
text
:
string
;
record
:
EditRecordRow
})
=>
{
return
(
<
EditableCell
{
...
componentProps
}
placeholder
=
{
placeholder
}
value
=
{
text
}
record
=
{
record
}
dataKey
=
{
record
.
key
}
dataIndex
=
{
dataIndex
}
component
=
{
component
}
/>
);
};
}
export
function
renderEditableRow
({
dataIndex
,
component
,
componentProps
=
{},
placeholder
,
}:
RenderEditableCellParams
)
{
return
({
text
,
record
}:
{
text
:
string
;
record
:
EditRecordRow
})
=>
{
return
(
<
EditableCell
{
...
componentProps
}
value
=
{
text
}
placeholder
=
{
placeholder
}
editRow
=
{
true
}
editable
=
{
record
.
editable
}
dataKey
=
{
record
.
key
}
record
=
{
record
}
dataIndex
=
{
dataIndex
}
component
=
{
component
}
/>
);
};
}
export
type
EditRecordRow
<
T
=
Hash
<
any
>>
=
{
editable
:
boolean
;
onCancel
:
Fn
;
onSubmit
:
Fn
;
submitCbs
:
Fn
[];
cancelCbs
:
Fn
[];
}
&
T
;
src/components/Table/src/components/renderExpandIcon.tsx
已删除
100644 → 0
浏览文件 @
f3a70eed
import
{
BasicArrow
}
from
'
/@/components/Basic
'
;
export
default
()
=>
{
return
(
props
:
Recordable
)
=>
{
return
(
<
BasicArrow
onClick
=
{
(
e
:
Event
)
=>
{
props
.
onExpand
(
props
.
record
,
e
);
}
}
expand
=
{
props
.
expanded
}
/>
);
};
};
src/components/Table/src/components/settings/ColumnSetting.vue
浏览文件 @
9c2f3f30
...
...
@@ -184,7 +184,7 @@
const
ret
:
Options
[]
=
[];
table
.
getColumns
({
ignoreIndex
:
true
,
ignoreAction
:
true
}).
forEach
((
item
)
=>
{
ret
.
push
({
label
:
item
.
title
as
string
,
label
:
(
item
.
title
as
string
)
||
(
item
.
customTitle
as
string
)
,
value
:
(
item
.
dataIndex
||
item
.
title
)
as
string
,
...
item
,
});
...
...
src/components/Table/src/const.ts
浏览文件 @
9c2f3f30
...
...
@@ -32,6 +32,10 @@ export function DEFAULT_SORT_FN(sortInfo: SorterResult) {
};
}
export
function
DEFAULT_FILTER_FN
(
data
:
Partial
<
Recordable
<
string
[]
>>
)
{
return
data
;
}
// 表格单元格默认布局
export
const
DEFAULT_ALIGN
=
'
center
'
;
...
...
src/components/Table/src/hooks/useColumns.ts
浏览文件 @
9c2f3f30
import
{
BasicColumn
,
BasicTableProps
,
GetColumnsParams
}
from
'
../types/table
'
;
import
{
PaginationProps
}
from
'
../types/pagination
'
;
import
type
{
BasicColumn
,
BasicTableProps
,
CellFormat
,
GetColumnsParams
}
from
'
../types/table
'
;
import
type
{
PaginationProps
}
from
'
../types/pagination
'
;
import
{
unref
,
ComputedRef
,
Ref
,
computed
,
watchEffect
,
ref
,
toRaw
}
from
'
vue
'
;
import
{
isBoolean
,
isArray
,
isString
}
from
'
/@/utils/is
'
;
import
{
isBoolean
,
isArray
,
isString
,
isObject
}
from
'
/@/utils/is
'
;
import
{
DEFAULT_ALIGN
,
PAGE_SIZE
,
INDEX_COLUMN_FLAG
,
ACTION_COLUMN_FLAG
}
from
'
../const
'
;
import
{
useI18n
}
from
'
/@/hooks/web/useI18n
'
;
import
{
isEqual
,
cloneDeep
}
from
'
lodash-es
'
;
import
{
isFunction
}
from
'
/@/utils/is
'
;
import
{
formatToDate
}
from
'
/@/utils/dateUtil
'
;
import
{
renderEditCell
}
from
'
../components/editable
'
;
const
{
t
}
=
useI18n
();
...
...
@@ -127,8 +130,30 @@ export function useColumns(
return
columns
;
});
const
getSortFixedColumns
=
computed
(()
=>
{
return
useFixedColumn
(
unref
(
getColumnsRef
));
const
getViewColumns
=
computed
(()
=>
{
const
viewColumns
=
sortFixedColumn
(
unref
(
getColumnsRef
));
viewColumns
.
forEach
((
column
)
=>
{
const
{
slots
,
dataIndex
,
customRender
,
format
,
edit
,
editRow
,
flag
}
=
column
;
if
(
!
slots
||
!
slots
?.
title
)
{
column
.
slots
=
{
title
:
`header-
${
dataIndex
}
`
,
...(
slots
||
{})
};
column
.
customTitle
=
column
.
title
;
Reflect
.
deleteProperty
(
column
,
'
title
'
);
}
const
isDefaultAction
=
[
INDEX_COLUMN_FLAG
,
ACTION_COLUMN_FLAG
].
includes
(
flag
!
);
if
(
!
customRender
&&
format
&&
!
edit
&&
!
isDefaultAction
)
{
column
.
customRender
=
({
text
,
record
,
index
})
=>
{
return
formatCell
(
text
,
format
,
record
,
index
);
};
}
// edit table
if
((
edit
||
editRow
)
&&
!
isDefaultAction
)
{
column
.
customRender
=
renderEditCell
(
column
);
}
});
return
viewColumns
;
});
watchEffect
(()
=>
{
...
...
@@ -191,7 +216,7 @@ export function useColumns(
}
if
(
sort
)
{
columns
=
use
FixedColumn
(
columns
);
columns
=
sort
FixedColumn
(
columns
);
}
return
columns
;
...
...
@@ -200,10 +225,10 @@ export function useColumns(
return
cacheColumns
;
}
return
{
getColumnsRef
,
getCacheColumns
,
getColumns
,
setColumns
,
get
SortFixed
Columns
};
return
{
getColumnsRef
,
getCacheColumns
,
getColumns
,
setColumns
,
get
View
Columns
};
}
export
function
use
FixedColumn
(
columns
:
BasicColumn
[])
{
function
sort
FixedColumn
(
columns
:
BasicColumn
[])
{
const
fixedLeftColumns
:
BasicColumn
[]
=
[];
const
fixedRightColumns
:
BasicColumn
[]
=
[];
const
defColumns
:
BasicColumn
[]
=
[];
...
...
@@ -224,3 +249,35 @@ export function useFixedColumn(columns: BasicColumn[]) {
return
resultColumns
;
}
// format cell
export
function
formatCell
(
text
:
string
,
format
:
CellFormat
,
record
:
Recordable
,
index
:
number
)
{
if
(
!
format
)
{
return
text
;
}
// custom function
if
(
isFunction
(
format
))
{
return
format
(
text
,
record
,
index
);
}
try
{
// date type
const
DATE_FORMAT_PREFIX
=
'
date|
'
;
if
(
isString
(
format
)
&&
format
.
startsWith
(
DATE_FORMAT_PREFIX
))
{
const
dateFormat
=
format
.
replace
(
DATE_FORMAT_PREFIX
,
''
);
if
(
!
dateFormat
)
{
return
text
;
}
return
formatToDate
(
text
,
dateFormat
);
}
// enum
if
(
isObject
(
format
)
&&
Reflect
.
has
(
format
,
'
size
'
))
{
return
format
.
get
(
text
);
}
}
catch
(
error
)
{
return
text
;
}
}
src/components/Table/src/hooks/useDataSource.ts
浏览文件 @
9c2f3f30
import
type
{
BasicTableProps
,
FetchParams
}
from
'
../types/table
'
;
import
type
{
BasicTableProps
,
FetchParams
,
SorterResult
}
from
'
../types/table
'
;
import
type
{
PaginationProps
}
from
'
../types/pagination
'
;
import
{
ref
,
unref
,
ComputedRef
,
computed
,
onMounted
,
watchEffect
}
from
'
vue
'
;
import
{
ref
,
unref
,
ComputedRef
,
computed
,
onMounted
,
watchEffect
,
reactive
}
from
'
vue
'
;
import
{
useTimeoutFn
}
from
'
/@/hooks/core/useTimeout
'
;
...
...
@@ -16,12 +16,28 @@ interface ActionType {
setPagination
:
(
info
:
Partial
<
PaginationProps
>
)
=>
void
;
setLoading
:
(
loading
:
boolean
)
=>
void
;
getFieldsValue
:
()
=>
Recordable
;
clearSelectedRowKeys
:
()
=>
void
;
}
interface
SearchState
{
sortInfo
:
Recordable
;
filterInfo
:
Record
<
string
,
string
[]
>
;
}
export
function
useDataSource
(
propsRef
:
ComputedRef
<
BasicTableProps
>
,
{
getPaginationInfo
,
setPagination
,
setLoading
,
getFieldsValue
}:
ActionType
,
{
getPaginationInfo
,
setPagination
,
setLoading
,
getFieldsValue
,
clearSelectedRowKeys
,
}:
ActionType
,
emit
:
EmitType
)
{
const
searchState
=
reactive
<
SearchState
>
({
sortInfo
:
{},
filterInfo
:
{},
});
const
dataSourceRef
=
ref
<
Recordable
[]
>
([]);
watchEffect
(()
=>
{
...
...
@@ -29,6 +45,32 @@ export function useDataSource(
!
api
&&
dataSource
&&
(
dataSourceRef
.
value
=
dataSource
);
});
function
handleTableChange
(
pagination
:
PaginationProps
,
filters
:
Partial
<
Recordable
<
string
[]
>>
,
sorter
:
SorterResult
)
{
const
{
clearSelectOnPageChange
,
sortFn
,
filterFn
}
=
unref
(
propsRef
);
if
(
clearSelectOnPageChange
)
{
clearSelectedRowKeys
();
}
setPagination
(
pagination
);
const
params
:
Recordable
=
{};
if
(
sorter
&&
isFunction
(
sortFn
))
{
const
sortInfo
=
sortFn
(
sorter
);
searchState
.
sortInfo
=
sortInfo
;
params
.
sortInfo
=
sortInfo
;
}
if
(
filters
&&
isFunction
(
filterFn
))
{
const
filterInfo
=
filterFn
(
filters
);
searchState
.
filterInfo
=
filterInfo
;
params
.
filterInfo
=
filterInfo
;
}
fetch
(
params
);
}
function
setTableKey
(
items
:
any
[])
{
if
(
!
items
||
!
Array
.
isArray
(
items
))
return
;
items
.
forEach
((
item
)
=>
{
...
...
@@ -75,6 +117,14 @@ export function useDataSource(
return
unref
(
dataSourceRef
);
});
async
function
updateTableData
(
index
:
number
,
key
:
string
,
value
:
any
)
{
const
record
=
dataSourceRef
.
value
[
index
];
if
(
record
)
{
dataSourceRef
.
value
[
index
][
key
]
=
value
;
}
return
dataSourceRef
.
value
[
index
];
}
async
function
fetch
(
opt
?:
FetchParams
)
{
const
{
api
,
searchInfo
,
fetchSetting
,
beforeFetch
,
afterFetch
,
useSearchForm
}
=
unref
(
propsRef
...
...
@@ -94,6 +144,8 @@ export function useDataSource(
pageParams
[
sizeField
]
=
pageSize
;
}
const
{
sortInfo
=
{},
filterInfo
}
=
searchState
;
let
params
:
Recordable
=
{
...
pageParams
,
...(
useSearchForm
?
getFieldsValue
()
:
{}),
...
...
@@ -101,6 +153,8 @@ export function useDataSource(
...(
opt
?
opt
.
searchInfo
:
{}),
...(
opt
?
opt
.
sortInfo
:
{}),
...(
opt
?
opt
.
filterInfo
:
{}),
...
sortInfo
,
...
filterInfo
,
};
if
(
beforeFetch
&&
isFunction
(
beforeFetch
))
{
params
=
beforeFetch
(
params
)
||
params
;
...
...
@@ -175,5 +229,7 @@ export function useDataSource(
getAutoCreateKey
,
fetch
,
reload
,
updateTableData
,
handleTableChange
,
};
}
src/components/Table/src/hooks/useTable.ts
浏览文件 @
9c2f3f30
import
type
{
BasicTableProps
,
TableActionType
,
FetchParams
,
BasicColumn
}
from
'
../types/table
'
;
import
type
{
PaginationProps
}
from
'
../types/pagination
'
;
import
type
{
DynamicProps
}
from
'
/@/types/utils
'
;
import
{
getDynamicProps
}
from
'
/@/utils
'
;
import
{
ref
,
onUnmounted
,
unref
}
from
'
vue
'
;
import
{
isProdMode
}
from
'
/@/utils/env
'
;
import
{
isInSetup
}
from
'
/@/utils/helper/vueHelper
'
;
import
{
error
}
from
'
/@/utils/log
'
;
import
{
watchEffect
}
from
'
vue
'
;
import
type
{
FormActionType
}
from
'
/@/components/Form
'
;
type
Props
=
Partial
<
DynamicProps
<
BasicTableProps
>>
;
export
function
useTable
(
tableProps
?:
P
artial
<
BasicTableProps
>
):
[(
instance
:
TableActionType
)
=>
void
,
TableActionType
]
{
tableProps
?:
P
rops
):
[(
instance
:
TableActionType
,
formInstance
:
FormActionType
)
=>
void
,
TableActionType
]
{
isInSetup
();
const
tableRef
=
ref
<
Nullable
<
TableActionType
>>
(
null
);
const
loadedRef
=
ref
<
Nullable
<
boolean
>>
(
false
);
const
formRef
=
ref
<
Nullable
<
FormActionType
>>
(
null
);
function
register
(
instance
:
TableActionType
)
{
function
register
(
instance
:
TableActionType
,
formInstance
:
FormActionType
)
{
isProdMode
()
&&
onUnmounted
(()
=>
{
tableRef
.
value
=
null
;
...
...
@@ -24,20 +32,29 @@ export function useTable(
return
;
}
tableRef
.
value
=
instance
;
tableProps
&&
instance
.
setProps
(
tableProps
);
formRef
.
value
=
formInstance
;
// tableProps && instance.setProps(tableProps);
loadedRef
.
value
=
true
;
watchEffect
(()
=>
{
tableProps
&&
instance
.
setProps
(
getDynamicProps
(
tableProps
));
});
}
function
getTableInstance
():
TableActionType
{
const
table
=
unref
(
tableRef
);
if
(
!
table
)
{
throw
new
Error
(
'
table is undefined!
'
);
error
(
'
The table instance has not been obtained yet, please make sure the table is presented when performing the table operation!
'
);
}
return
table
;
return
table
as
TableActionType
;
}
const
methods
:
TableActionType
=
{
reload
:
(
opt
?:
FetchParams
)
=>
{
const
methods
:
TableActionType
&
{
getForm
:
()
=>
FormActionType
;
}
=
{
reload
:
async
(
opt
?:
FetchParams
)
=>
{
getTableInstance
().
reload
(
opt
);
},
setProps
:
(
props
:
Partial
<
BasicTableProps
>
)
=>
{
...
...
@@ -54,7 +71,6 @@ export function useTable(
},
getColumns
:
({
ignoreIndex
=
false
}:
{
ignoreIndex
?:
boolean
}
=
{})
=>
{
const
columns
=
getTableInstance
().
getColumns
({
ignoreIndex
})
||
[];
return
columns
;
},
setColumns
:
(
columns
:
BasicColumn
[])
=>
{
...
...
@@ -87,7 +103,19 @@ export function useTable(
getSize
:
()
=>
{
return
getTableInstance
().
getSize
();
},
}
as
TableActionType
;
updateTableData
:
(
index
:
number
,
key
:
string
,
value
:
any
)
=>
{
return
getTableInstance
().
updateTableData
(
index
,
key
,
value
);
},
getRowSelection
:
()
=>
{
return
getTableInstance
().
getRowSelection
();
},
getCacheColumns
:
()
=>
{
return
getTableInstance
().
getCacheColumns
();
},
getForm
:
()
=>
{
return
unref
(
formRef
)
as
FormActionType
;
},
};
return
[
register
,
methods
];
}
src/components/Table/src/hooks/useTableScroll.ts
浏览文件 @
9c2f3f30
...
...
@@ -121,7 +121,7 @@ export function useTableScroll(
width
+=
60
;
}
// TODO props
// TODO props
dth ?? 0;
const
NORMAL_WIDTH
=
150
;
const
columns
=
unref
(
columnsRef
);
...
...
@@ -135,7 +135,10 @@ export function useTableScroll(
if
(
len
!==
0
)
{
width
+=
len
*
NORMAL_WIDTH
;
}
return
width
;
const
table
=
unref
(
tableElRef
);
const
tableWidth
=
table
?.
$el
?.
offsetWidth
??
0
;
return
tableWidth
>
width
?
tableWidth
-
24
:
width
;
});
const
getScrollRef
=
computed
(()
=>
{
...
...
src/components/Table/src/props.ts
浏览文件 @
9c2f3f30
...
...
@@ -9,21 +9,29 @@ import type {
TableRowSelection
,
}
from
'
./types/table
'
;
import
type
{
FormProps
}
from
'
/@/components/Form
'
;
import
{
DEFAULT_SORT_FN
,
FETCH_SETTING
}
from
'
./const
'
;
import
{
DEFAULT_
FILTER_FN
,
DEFAULT_
SORT_FN
,
FETCH_SETTING
}
from
'
./const
'
;
import
{
propTypes
}
from
'
/@/utils/propTypes
'
;
// 注释看 types/table
export
const
basicProps
=
{
clickToRowSelect
:
propTypes
.
bool
.
def
(
true
),
tableSetting
:
{
type
:
Object
as
PropType
<
TableSetting
>
,
},
inset
:
propTypes
.
bool
,
sortFn
:
{
type
:
Function
as
PropType
<
(
sortInfo
:
SorterResult
)
=>
any
>
,
default
:
DEFAULT_SORT_FN
,
},
filterFn
:
{
type
:
Function
as
PropType
<
(
data
:
Partial
<
Recordable
<
string
[]
>>
)
=>
any
>
,
default
:
DEFAULT_FILTER_FN
,
},
showTableSetting
:
propTypes
.
bool
,
autoCreateKey
:
propTypes
.
bool
.
def
(
true
),
striped
:
propTypes
.
bool
.
def
(
true
),
...
...
src/components/Table/src/style/editable-cell.less
已删除
100644 → 0
浏览文件 @
f3a70eed
@prefix-cls: ~'editable-cell';
.@{prefix-cls} {
position: relative;
&__wrapper {
display: flex;
align-items: center;
}
&__icon {
&:hover {
transform: scale(1.2);
svg {
color: @primary-color;
}
}
}
&__normal {
padding-right: 48px;
&-icon {
position: absolute;
top: 4px;
right: 0;
display: none;
width: 20px;
cursor: pointer;
}
}
&:hover {
.@{prefix-cls}__normal-icon {
display: inline-block;
}
}
}
src/components/Table/src/style/index.less
浏览文件 @
9c2f3f30
...
...
@@ -133,7 +133,10 @@
overflow-y: scroll !important;
}
.ant-table-fixed-right .ant-table-header {
.ant-table-fixed-right {
right: -1px;
.ant-table-header {
border-left: 1px solid @border-color !important;
.ant-table-fixed {
...
...
@@ -144,6 +147,7 @@
}
}
}
}
.ant-table-fixed-left {
.ant-table-header {
...
...
src/components/Table/src/types/componentType.ts
浏览文件 @
9c2f3f30
export
type
ComponentType
=
|
'
Input
'
|
'
InputPassword
'
|
'
InputNumber
'
|
'
Select
'
|
'
ApiSelect
'
|
'
Checkbox
'
|
'
CheckboxGroup
'
|
'
Switch
'
;
src/components/Table/src/types/table.ts
浏览文件 @
9c2f3f30
...
...
@@ -6,9 +6,10 @@ import type {
TableRowSelection
as
ITableRowSelection
,
}
from
'
ant-design-vue/lib/table/interface
'
;
import
{
ComponentType
}
from
'
./componentType
'
;
import
{
VueNode
}
from
'
/@/utils/propTypes
'
;
// import { ColumnProps } from './column';
export
declare
type
SortOrder
=
'
ascend
'
|
'
descend
'
;
export
interface
TableCurrentDataSource
<
T
=
any
>
{
export
interface
TableCurrentDataSource
<
T
=
Recordable
>
{
currentDataSource
:
T
[];
}
...
...
@@ -53,7 +54,7 @@ export interface ColumnFilterItem {
children
?:
any
;
}
export
interface
TableCustomRecord
<
T
=
any
>
{
export
interface
TableCustomRecord
<
T
=
Recordable
>
{
record
?:
T
;
index
?:
number
;
}
...
...
@@ -65,18 +66,11 @@ export interface SorterResult {
columnKey
:
string
;
}
export
interface
RenderEditableCellParams
{
dataIndex
:
string
;
component
?:
ComponentType
;
componentProps
?:
any
;
placeholder
?:
string
;
}
export
interface
FetchParams
{
searchInfo
?:
any
;
searchInfo
?:
Recordable
;
page
?:
number
;
sortInfo
?:
any
;
filterInfo
?:
any
;
sortInfo
?:
Recordable
;
filterInfo
?:
Recordable
;
}
export
interface
GetColumnsParams
{
...
...
@@ -89,7 +83,7 @@ export type SizeType = 'default' | 'middle' | 'small' | 'large';
export
interface
TableActionType
{
reload
:
(
opt
?:
FetchParams
)
=>
Promise
<
void
>
;
getSelectRows
:
<
T
=
any
>
()
=>
T
[];
getSelectRows
:
<
T
=
Recordable
>
()
=>
T
[];
clearSelectedRowKeys
:
()
=>
void
;
getSelectRowKeys
:
()
=>
string
[];
deleteSelectRowByKey
:
(
key
:
string
)
=>
void
;
...
...
@@ -106,6 +100,8 @@ export interface TableActionType {
getSize
:
()
=>
SizeType
;
getRowSelection
:
()
=>
TableRowSelection
<
Recordable
>
;
getCacheColumns
:
()
=>
BasicColumn
[];
emit
?:
EmitType
;
updateTableData
:
(
index
:
number
,
key
:
string
,
value
:
any
)
=>
Recordable
;
}
export
interface
FetchSetting
{
...
...
@@ -131,6 +127,8 @@ export interface BasicTableProps<T = any> {
clickToRowSelect
?:
boolean
;
// 自定义排序方法
sortFn
?:
(
sortInfo
:
SorterResult
)
=>
any
;
// 排序方法
filterFn
?:
(
data
:
Partial
<
Recordable
<
string
[]
>>
)
=>
any
;
// 取消表格的默认padding
inset
?:
boolean
;
// 显示表格设置
...
...
@@ -141,7 +139,7 @@ export interface BasicTableProps<T = any> {
// 是否自动生成key
autoCreateKey
?:
boolean
;
// 计算合计行的方法
summaryFunc
?:
(...
arg
:
any
)
=>
any
[];
summaryFunc
?:
(...
arg
:
any
)
=>
Recordable
[];
// 是否显示合计行
showSummary
?:
boolean
;
// 是否可拖拽列
...
...
@@ -374,13 +372,43 @@ export interface BasicTableProps<T = any> {
onExpandedRowsChange
?:
(
expandedRows
:
string
[]
|
number
[])
=>
void
;
}
export
type
CellFormat
=
|
string
|
((
text
:
string
,
record
:
Recordable
,
index
:
number
)
=>
string
|
number
)
|
Map
<
string
|
number
,
any
>
;
// @ts-ignore
export
interface
BasicColumn
extends
ColumnProps
{
children
?:
BasicColumn
[];
filters
?:
{
text
:
string
;
value
:
string
;
children
?:
|
unknown
[]
|
(((
props
:
Record
<
string
,
unknown
>
)
=>
unknown
[])
&
(()
=>
unknown
[])
&
(()
=>
unknown
[]));
}[];
//
flag
?:
'
INDEX
'
|
'
DEFAULT
'
|
'
CHECKBOX
'
|
'
RADIO
'
|
'
ACTION
'
;
customTitle
?:
VueNode
;
slots
?:
Indexable
;
// Whether to hide the column by default, it can be displayed in the column configuration
defaultHidden
?:
boolean
;
// Help text for table column header
helpMessage
?:
string
|
string
[];
format
?:
CellFormat
;
// Editable
edit
?:
boolean
;
editRow
?:
boolean
;
editable
?:
boolean
;
editComponent
?:
ComponentType
;
editComponentProps
?:
Recordable
;
editRule
?:
boolean
|
((
text
:
string
,
record
:
Recordable
)
=>
Promise
<
string
>
);
editValueMap
?:
(
value
:
any
)
=>
string
;
onEditRow
?:
()
=>
void
;
}
src/layouts/default/sider/MixSider.vue
浏览文件 @
9c2f3f30
...
...
@@ -351,6 +351,11 @@
position: absolute;
top: 10px;
right: 30px;
&--dot {
top: 50%;
margin-top: -3px;
}
}
&__title {
...
...
src/router/menus/modules/demo/comp.ts
浏览文件 @
9c2f3f30
...
...
@@ -52,6 +52,9 @@ const menu: MenuModule = {
{
path
:
'
table
'
,
name
:
t
(
'
routes.demo.table.table
'
),
tag
:
{
dot
:
true
,
},
children
:
[
{
path
:
'
basic
'
,
...
...
@@ -108,10 +111,16 @@ const menu: MenuModule = {
{
path
:
'
editCellTable
'
,
name
:
t
(
'
routes.demo.table.editCellTable
'
),
tag
:
{
dot
:
true
,
},
},
{
path
:
'
editRowTable
'
,
name
:
t
(
'
routes.demo.table.editRowTable
'
),
tag
:
{
dot
:
true
,
},
},
],
},
...
...
src/utils/dateUtil.ts
浏览文件 @
9c2f3f30
...
...
@@ -3,12 +3,15 @@ import moment from 'moment';
const
DATE_TIME_FORMAT
=
'
YYYY-MM-DD HH:mm
'
;
const
DATE_FORMAT
=
'
YYYY-MM-DD
'
;
export
function
formatToDateTime
(
date
:
moment
.
MomentInput
=
null
):
string
{
return
moment
(
date
).
format
(
DATE_TIME_FORMAT
);
export
function
formatToDateTime
(
date
:
moment
.
MomentInput
=
null
,
format
=
DATE_TIME_FORMAT
):
string
{
return
moment
(
date
).
format
(
format
);
}
export
function
formatToDate
(
date
:
moment
.
MomentInput
=
null
):
string
{
return
moment
(
date
).
format
(
DATE_FORMAT
);
export
function
formatToDate
(
date
:
moment
.
MomentInput
=
null
,
format
=
DATE_FORMAT
):
string
{
return
moment
(
date
).
format
(
format
);
}
export
const
formatAgo
=
(
str
:
string
|
number
)
=>
{
...
...
src/views/demo/table/EditCellTable.vue
浏览文件 @
9c2f3f30
<
template
>
<div
class=
"p-4"
>
<BasicTable
@
register=
"registerTable"
>
<template
#customId
>
<EditTableHeaderIcon
title=
"Id"
/>
</
template
>
<
template
#customName
>
<EditTableHeaderIcon
title=
"姓名"
/>
</
template
>
<BasicTable
@
register=
"registerTable"
@
edit-end=
"handleEditEnd"
@
edit-cancel=
"handleEditCancel"
>
</BasicTable>
</div>
</
template
>
<
script
lang=
"ts"
>
import
{
defineComponent
}
from
'
vue
'
;
import
{
BasicTable
,
useTable
,
BasicColumn
,
renderEditableCell
,
EditTableHeaderIcon
,
}
from
'
/@/components/Table
'
;
import
{
BasicTable
,
useTable
,
BasicColumn
,
EditTableHeaderIcon
}
from
'
/@/components/Table
'
;
import
{
optionsListApi
}
from
'
/@/api/demo/select
'
;
import
{
demoListApi
}
from
'
/@/api/demo/table
'
;
const
columns
:
BasicColumn
[]
=
[
{
// title: 'ID',
title
:
'
输入框
'
,
dataIndex
:
'
name
'
,
edit
:
true
,
editComponentProps
:
{
prefix
:
'
$
'
,
},
width
:
200
,
},
{
title
:
'
默认输入状态
'
,
dataIndex
:
'
name7
'
,
edit
:
true
,
editable
:
true
,
width
:
200
,
},
{
title
:
'
输入框校验
'
,
dataIndex
:
'
name1
'
,
edit
:
true
,
// 默认必填校验
editRule
:
true
,
width
:
200
,
},
{
title
:
'
输入框函数校验
'
,
dataIndex
:
'
name2
'
,
edit
:
true
,
editRule
:
async
(
text
)
=>
{
if
(
text
===
'
2
'
)
{
return
'
不能输入该值
'
;
}
return
''
;
},
width
:
200
,
},
{
title
:
'
数字输入框
'
,
dataIndex
:
'
id
'
,
slots
:
{
title
:
'
customId
'
},
customRender
:
renderEditableCell
({
dataIndex
:
'
id
'
}),
edit
:
true
,
editRule
:
true
,
editComponent
:
'
InputNumber
'
,
width
:
200
,
},
{
// title: '姓名',
dataIndex
:
'
name
'
,
slots
:
{
title
:
'
customName
'
},
customRender
:
renderEditableCell
({
dataIndex
:
'
name
'
,
}),
title
:
'
下拉框
'
,
dataIndex
:
'
name3
'
,
edit
:
true
,
editComponent
:
'
Select
'
,
editComponentProps
:
{
options
:
[
{
label
:
'
Option1
'
,
value
:
'
1
'
,
},
{
title
:
'
地址
'
,
dataIndex
:
'
address
'
,
sorter
:
true
,
label
:
'
Option2
'
,
value
:
'
2
'
,
},
],
},
width
:
200
,
},
{
title
:
'
远程下拉
'
,
dataIndex
:
'
name4
'
,
edit
:
true
,
editComponent
:
'
ApiSelect
'
,
editComponentProps
:
{
api
:
optionsListApi
,
},
width
:
200
,
},
{
title
:
'
勾选框
'
,
dataIndex
:
'
name5
'
,
edit
:
true
,
editComponent
:
'
Checkbox
'
,
editValueMap
:
(
value
)
=>
{
return
value
?
'
是
'
:
'
否
'
;
},
width
:
200
,
},
{
title
:
'
开关
'
,
dataIndex
:
'
name6
'
,
edit
:
true
,
editComponent
:
'
Switch
'
,
editValueMap
:
(
value
)
=>
{
return
value
?
'
开
'
:
'
关
'
;
},
width
:
200
,
},
];
export
default
defineComponent
({
...
...
@@ -50,10 +113,21 @@
api
:
demoListApi
,
columns
:
columns
,
showIndexColumn
:
false
,
bordered
:
true
,
});
function
handleEditEnd
({
record
,
index
,
key
,
value
}:
Recordable
)
{
console
.
log
(
record
,
index
,
key
,
value
);
}
function
handleEditCancel
()
{
console
.
log
(
'
cancel
'
);
}
return
{
registerTable
,
handleEditEnd
,
handleEditCancel
,
};
},
});
...
...
src/views/demo/table/EditRowTable.vue
浏览文件 @
9c2f3f30
...
...
@@ -15,24 +15,105 @@
TableAction
,
BasicColumn
,
ActionItem
,
renderEditableRow
,
EditTableHeaderIcon
,
EditRecordRow
,
}
from
'
/@/components/Table
'
;
import
{
optionsListApi
}
from
'
/@/api/demo/select
'
;
import
{
demoListApi
}
from
'
/@/api/demo/table
'
;
const
columns
:
BasicColumn
[]
=
[
{
title
:
'
ID
'
,
title
:
'
输入框
'
,
dataIndex
:
'
name
'
,
editRow
:
true
,
editComponentProps
:
{
prefix
:
'
$
'
,
},
width
:
200
,
},
{
title
:
'
默认输入状态
'
,
dataIndex
:
'
name7
'
,
editRow
:
true
,
width
:
200
,
},
{
title
:
'
输入框校验
'
,
dataIndex
:
'
name1
'
,
editRow
:
true
,
// 默认必填校验
editRule
:
true
,
width
:
200
,
},
{
title
:
'
输入框函数校验
'
,
dataIndex
:
'
name2
'
,
editRow
:
true
,
editRule
:
async
(
text
)
=>
{
if
(
text
===
'
2
'
)
{
return
'
不能输入该值
'
;
}
return
''
;
},
width
:
200
,
},
{
title
:
'
数字输入框
'
,
dataIndex
:
'
id
'
,
customRender
:
renderEditableRow
({
dataIndex
:
'
id
'
}),
editRow
:
true
,
editRule
:
true
,
editComponent
:
'
InputNumber
'
,
width
:
200
,
},
{
title
:
'
姓名
'
,
dataIndex
:
'
name
'
,
customRender
:
renderEditableRow
({
dataIndex
:
'
name
'
,
}),
title
:
'
下拉框
'
,
dataIndex
:
'
name3
'
,
editRow
:
true
,
editComponent
:
'
Select
'
,
editComponentProps
:
{
options
:
[
{
label
:
'
Option1
'
,
value
:
'
1
'
,
},
{
label
:
'
Option2
'
,
value
:
'
2
'
,
},
],
},
width
:
200
,
},
{
title
:
'
远程下拉
'
,
dataIndex
:
'
name4
'
,
editRow
:
true
,
editComponent
:
'
ApiSelect
'
,
editComponentProps
:
{
api
:
optionsListApi
,
},
width
:
200
,
},
{
title
:
'
勾选框
'
,
dataIndex
:
'
name5
'
,
editRow
:
true
,
editComponent
:
'
Checkbox
'
,
editValueMap
:
(
value
)
=>
{
return
value
?
'
是
'
:
'
否
'
;
},
width
:
200
,
},
{
title
:
'
开关
'
,
dataIndex
:
'
name6
'
,
editRow
:
true
,
editComponent
:
'
Switch
'
,
editValueMap
:
(
value
)
=>
{
return
value
?
'
开
'
:
'
关
'
;
},
width
:
200
,
},
];
export
default
defineComponent
({
...
...
@@ -55,19 +136,19 @@
function
handleEdit
(
record
:
EditRecordRow
)
{
currentEditKeyRef
.
value
=
record
.
key
;
record
.
editable
=
true
;
record
.
onEdit
?.(
true
)
;
}
function
handleCancel
(
record
:
EditRecordRow
)
{
currentEditKeyRef
.
value
=
''
;
record
.
editable
=
false
;
record
.
onCancel
&&
record
.
onCancel
();
record
.
onEdit
?.(
false
,
true
);
}
function
handleSave
(
record
:
EditRecordRow
)
{
async
function
handleSave
(
record
:
EditRecordRow
)
{
const
pass
=
await
record
.
onEdit
?.(
false
,
true
);
if
(
pass
)
{
currentEditKeyRef
.
value
=
''
;
record
.
editable
=
false
;
record
.
onSubmit
&&
record
.
onSubmit
();
}
}
function
createActions
(
record
:
EditRecordRow
,
column
:
BasicColumn
):
ActionItem
[]
{
...
...
src/views/demo/table/FixedColumn.vue
浏览文件 @
9c2f3f30
...
...
@@ -41,7 +41,6 @@
{
title
:
'
地址
'
,
dataIndex
:
'
address
'
,
width
:
260
,
},
{
title
:
'
编号
'
,
...
...
@@ -67,6 +66,7 @@
api
:
demoListApi
,
columns
:
columns
,
rowSelection
:
{
type
:
'
radio
'
},
bordered
:
true
,
actionColumn
:
{
width
:
160
,
title
:
'
Action
'
,
...
...
src/views/demo/table/tableData.tsx
浏览文件 @
9c2f3f30
...
...
@@ -7,12 +7,16 @@ export function getBasicColumns(): BasicColumn[] {
title
:
'
ID
'
,
dataIndex
:
'
id
'
,
fixed
:
'
left
'
,
width
:
4
00
,
width
:
2
00
,
},
{
title
:
'
姓名
'
,
dataIndex
:
'
name
'
,
width
:
150
,
filters
:
[
{
text
:
'
Male
'
,
value
:
'
male
'
},
{
text
:
'
Female
'
,
value
:
'
female
'
},
],
},
{
title
:
'
地址
'
,
...
...
@@ -22,11 +26,13 @@ export function getBasicColumns(): BasicColumn[] {
title
:
'
编号
'
,
dataIndex
:
'
no
'
,
width
:
150
,
sorter
:
true
,
defaultHidden
:
true
,
},
{
title
:
'
开始时间
'
,
width
:
120
,
sorter
:
true
,
dataIndex
:
'
beginTime
'
,
},
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录