Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
A
airtable
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
web_component
airtable
Commits
762f5814
Commit
762f5814
authored
Dec 07, 2019
by
zhangwenshuai
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
temp
parent
e03e522d
Changes
7
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
357 additions
and
106 deletions
+357
-106
.fatherrc.ts
.fatherrc.ts
+0
-0
package.json
package.json
+1
-1
Cell.tsx
src/apollo-table/component/Cell.tsx
+1
-1
Table.less
src/apollo-table/component/Table.less
+14
-24
Table.tsx
src/apollo-table/component/Table.tsx
+299
-80
common.less
src/common.less
+40
-0
index.mdx
src/index.mdx
+2
-0
No files found.
.
umirc.library
.ts
→
.
fatherrc
.ts
View file @
762f5814
File moved
package.json
View file @
762f5814
...
...
@@ -36,7 +36,7 @@
"lint-staged:ts"
:
{
"src/**/*.{ts,tsx}"
:
[
"prettier --write"
,
"tslint --fix"
,
"tslint --fix"
]
}
}
src/apollo-table/component/Cell.tsx
View file @
762f5814
import
React
,
{
ReactComponentElement
}
from
'react'
;
import
React
from
'react'
;
import
{
message
,
Popover
,
Modal
}
from
'antd'
;
import
{
getComponent
}
from
'./base'
;
...
...
src/apollo-table/component/Table.less
View file @
762f5814
@import '../../common';
.tableCell {
//padding: 0 !important;
&.sortCol {
background:
rgba(92, 153, 255, 0.2)
;
background:
@hoverColor
;
}
}
...
...
@@ -18,23 +19,13 @@
:global(.ant-table-thead > tr > th) {
padding: 0;
//margin-bottom: 1px;
//text-align: center;
}
//:global(.ant-table-thead > tr > th:first-child) {
// border-right: none;
//}
:global(.ant-table-tbody > tr > td) {
padding: 0;
height: 40px;
}
//:global(.ant-table-tbody > tr > td:first-child) {
// border-right: none;
//}
:global(.ant-table-tbody > tr > td:last-child) {
text-align: left;
}
...
...
@@ -48,13 +39,6 @@
background: white;
}
//:global(.ant-table-bordered.ant-table-fixed-header
// .ant-table-header
// + .ant-table-body
// > table) {
// border-top: 0px solid #e8e8e8;
//}
:global(.ant-table-row-hover) {
.unchecked {
display: block;
...
...
@@ -80,7 +64,7 @@
box-sizing: border-box;
&.disabled {
background:
#f9f9f9
;
background:
@disabledColor
;
&:hover {
box-shadow: none;
...
...
@@ -88,7 +72,7 @@
}
&:hover {
box-shadow: inset 0 0 0 1px
#85b6ff
;
box-shadow: inset 0 0 0 1px
@operateColor
;
.showFormBtn {
visibility: visible;
...
...
@@ -106,9 +90,11 @@
.cellNo {
display: flex;
align-items: center;
min-width: 50px;
}
.cellContent {
flex: 1;
overflow: hidden;
height: 100%;
...
...
@@ -143,6 +129,11 @@
display: flex;
flex-direction: row;
background: #fff;
.LeftSideContainer{
box-shadow: 6px 0 6px -4px rgba(0, 0, 0, 0.15);
position: absolute;
z-index: 1;
}
}
.GridColumn {
...
...
@@ -157,7 +148,6 @@
z-index: 10;
background: #fff;
border-left: 1px solid #e8e8e8;
box-shadow: 6px 0 6px -4px rgba(0, 0, 0, 0.15);
}
.LeftSideGrid {
...
...
@@ -181,7 +171,7 @@
box-sizing: border-box;
.cellNo {
m
argin-right: 5
px;
m
in-width: 50
px;
}
.cellContent {
...
...
@@ -206,7 +196,7 @@
justify-content: center;
align-items: center;
text-align: center;
padding: 0
0
.5em;
padding: 0 .5em;
}
.headerCell,
...
...
src/apollo-table/component/Table.tsx
View file @
762f5814
...
...
@@ -8,6 +8,7 @@ import styles from './Table.less';
import
{
TableProps
,
TableState
}
from
'./interface'
;
import
Column
from
'./Column'
;
import
Cell
from
'./Cell'
;
import
extendIcon
from
'../assets/extend.png'
;
export
default
class
AirTable
extends
Component
<
TableProps
,
TableState
>
{
static
getDerivedStateFromProps
(
nextProps
:
TableProps
,
prevState
:
TableState
)
{
...
...
@@ -26,10 +27,11 @@ export default class AirTable extends Component<TableProps, TableState> {
}
constructor
(
props
:
TableProps
)
{
super
(
props
);
const
{
columns
,
dataSource
,
tableId
}
=
props
;
const
{
columns
,
dataSource
,
tableId
,
checked
=
[]
}
=
props
;
this
.
state
=
{
columns
,
dataSource
,
checked
,
tableId
,
prevProps
:
props
,
height
:
document
.
body
.
clientHeight
-
193
,
...
...
@@ -43,12 +45,24 @@ export default class AirTable extends Component<TableProps, TableState> {
};
this
.
memoizeLeftCount
=
memoizeOne
(
this
.
getLeftCount
);
this
.
memoizeData
=
memoizeOne
(
this
.
filterData
);
this
.
indexCount
=
{};
}
componentDidMount
()
{
window
.
addEventListener
(
'resize'
,
this
.
resize
,
false
);
}
//重置窗口高度
resize
=
()
=>
{
this
.
setState
({
height
:
document
.
body
.
clientHeight
-
193
,
});
};
//获取左侧固定列数量
getLeftCount
=
(
columns
:
[])
=>
{
let
len
=
0
;
columns
.
map
((
item
:
any
)
=>
{
item
.
fixed
&&
len
++
;
if
(
item
.
fixed
)
{
len
+=
1
;
}
});
return
len
;
};
...
...
@@ -61,31 +75,104 @@ export default class AirTable extends Component<TableProps, TableState> {
let
i
=
0
;
this
.
indexCount
=
{};
cloneData
.
map
((
item1
:
any
)
=>
{
item1
.
rowData
=
item1
.
rowData
.
filter
((
item2
:
any
)
=>
const
itemData
=
item1
;
itemData
.
rowData
=
itemData
.
rowData
.
filter
((
item2
:
any
)
=>
columns
.
some
((
temp
:
any
)
=>
temp
.
columnName
===
item2
.
colName
),
);
if
(
item
1
.
groupId
)
{
if
(
this
.
indexCount
[
item
1
.
groupId
])
{
this
.
indexCount
[
item
1
.
groupId
].
push
(
item1
.
id
);
if
(
item
Data
.
groupId
)
{
if
(
this
.
indexCount
[
item
Data
.
groupId
])
{
this
.
indexCount
[
item
Data
.
groupId
].
push
(
itemData
.
id
);
}
else
{
i
++
;
this
.
indexCount
[
item
1
.
groupId
]
=
[
item1
.
id
];
i
+=
1
;
this
.
indexCount
[
item
Data
.
groupId
]
=
[
itemData
.
id
];
}
item
1
.
index
=
i
;
item
Data
.
index
=
i
;
}
return
item
1
;
return
item
Data
;
});
return
cloneData
;
};
//下拉加载
// 复选框选择
changeCheckbox
=
(
record
:
any
,
flag
:
boolean
)
=>
{
const
{
changeChecked
,
hasGroup
}
=
this
.
props
;
const
{
checked
,
dataSource
}
=
this
.
state
;
let
temp
=
checked
.
slice
();
if
(
flag
)
{
if
(
hasGroup
)
{
const
selected
=
dataSource
.
filter
((
item
:
any
)
=>
{
return
item
.
groupId
===
record
.
groupId
;
});
temp
=
temp
.
concat
(
selected
);
}
else
{
temp
.
push
(
record
);
}
}
else
{
if
(
hasGroup
)
{
temp
=
temp
.
filter
((
item
:
any
)
=>
{
return
item
.
groupId
!==
record
.
groupId
;
});
}
const
index
=
temp
.
findIndex
((
item
:
any
)
=>
{
return
item
.
id
===
record
.
id
;
});
temp
.
splice
(
index
,
1
);
}
if
(
typeof
changeChecked
===
'function'
)
{
changeChecked
({
checked
:
temp
});
}
};
// 检测当前分组是否全部选中
getCheckedAll
=
()
=>
{
const
{
checked
,
dataSource
}
=
this
.
state
;
const
temp
=
checked
.
slice
();
const
result
=
temp
.
filter
((
v
:
any
)
=>
{
return
dataSource
.
some
((
item
:
any
)
=>
{
return
item
.
id
===
v
.
id
;
});
});
return
result
.
length
===
dataSource
.
length
&&
result
.
length
!==
0
;
};
// 全选/反选
changeCheckboxAll
=
()
=>
{
const
{
checked
,
dataSource
}
=
this
.
state
;
const
{
changeChecked
}
=
this
.
props
;
const
temp
=
checked
.
slice
();
const
flag
=
this
.
getCheckedAll
();
let
result
=
[];
if
(
flag
)
{
result
=
temp
.
concat
(
dataSource
).
filter
((
v
:
any
)
=>
{
return
(
temp
.
some
((
item
:
any
)
=>
{
return
item
.
id
===
v
.
id
;
})
&&
!
dataSource
.
some
((
item
:
any
)
=>
{
return
item
.
id
===
v
.
id
;
})
);
});
}
else
{
result
=
temp
.
concat
(
dataSource
.
filter
((
v
:
any
)
=>
{
return
!
temp
.
some
((
item
:
any
)
=>
{
return
item
.
id
===
v
.
id
;
});
}),
);
}
if
(
typeof
changeChecked
===
'function'
)
{
changeChecked
({
checked
:
result
});
}
};
// 下拉加载
onScrollRow
=
({
clientHeight
,
scrollTop
}:
any
)
=>
{
const
height
=
clientHeight
+
scrollTop
||
0
;
const
{
dataSource
=
[],
rowHeight
=
40
}
=
this
.
state
;
const
{
onScroll
}
=
this
.
props
;
const
offset
=
100
;
if
(
dataSource
.
length
===
0
)
return
;
if
(
height
+
offset
>=
dataSource
.
length
*
rowHeight
)
{
this
.
props
.
onScroll
&&
this
.
props
.
onScroll
();
}
else
return
;
if
(
height
+
offset
>=
dataSource
.
length
*
rowHeight
&&
typeof
onScroll
===
'function'
)
{
onScroll
();
}
};
//渲染表头
renderHeaderCell
=
({
columnIndex
,
key
,
rowIndex
,
style
}:
any
)
=>
{
...
...
@@ -96,7 +183,7 @@ export default class AirTable extends Component<TableProps, TableState> {
return
(
<
div
key=
{
key
}
className=
{
styles
.
leftHeaderCell
}
style=
{
{
...
style
,
width
:
width
||
200
}
}
>
<
div
className=
{
styles
.
cellNo
}
>
<
Checkbox
/>
<
Checkbox
checked=
{
this
.
getCheckedAll
()
}
onClick=
{
this
.
changeCheckboxAll
}
/>
</
div
>
<
div
className=
{
styles
.
cellContent
}
>
<
Column
type=
{
String
(
columnType
)
}
title=
{
columnChsName
}
width=
{
width
}
/>
...
...
@@ -110,18 +197,93 @@ export default class AirTable extends Component<TableProps, TableState> {
</
div
>
);
};
// 渲染首列复选框
renderCheckbox
=
(
record
:
any
,
rowIndex
:
number
)
=>
{
const
{
checked
}
=
this
.
state
;
const
{
hasGroup
}
=
this
.
props
;
const
flag
=
checked
.
some
((
item
:
any
)
=>
{
return
item
.
id
===
record
.
id
;
});
let
checkbox
=
flag
?
(
<
Checkbox
checked=
{
true
}
onClick=
{
this
.
changeCheckbox
.
bind
(
this
,
record
,
false
)
}
/>
)
:
(
<>
<
Checkbox
className=
{
styles
.
unchecked
}
checked=
{
false
}
onClick=
{
this
.
changeCheckbox
.
bind
(
this
,
record
,
true
)
}
/>
<
div
className=
{
styles
.
no
}
>
{
record
.
index
||
rowIndex
+
1
}
</
div
>
</>
);
if
(
hasGroup
)
{
if
(
this
.
indexCount
[
record
.
groupId
][
Math
.
floor
((
this
.
indexCount
[
record
.
groupId
].
length
-
1
)
/
2
)]
!==
record
.
id
)
{
// 填充透明的复选框使样式保持一致
checkbox
=
<
Checkbox
style=
{
{
opacity
:
0
}
}
/>;
}
}
return
checkbox
;
};
//渲染数据
renderBodyCell
=
(
data
:
[],
{
columnIndex
,
key
,
rowIndex
,
style
}:
any
)
=>
{
const
{
columns
}
=
this
.
state
;
const
{
columns
,
dataSource
}
=
this
.
state
;
const
{
updateData
,
hasGroup
,
showForm
=
()
=>
{},
delData
,
getData
,
extraMenu
,
noAdd
,
noEdit
,
noDel
,
tableId
,
flush
,
}
=
this
.
props
;
if
(
columns
.
length
===
0
||
data
.
length
===
0
)
{
return
;
}
const
rowData
:
any
=
data
[
rowIndex
]
||
{};
const
columnData
:
any
=
(
rowData
.
rowData
&&
rowData
.
rowData
[
columnIndex
])
||
{};
const
cellData
:
[]
=
columnData
.
cellValueList
||
[];
let
columnConfig
=
columns
[
columnIndex
];
const
filterRowData
:
any
=
data
[
rowIndex
];
// 过滤掉隐藏项并追加行号的行数据,只在渲染逻辑中使用
const
rowData
:
any
=
dataSource
[
rowIndex
];
// 原始行数据,真实使用的数据
const
columnConfig
:
any
=
columns
[
columnIndex
];
// 列属性
const
columnData
:
any
=
rowData
.
rowData
[
columnIndex
];
// 列数据
const
cellData
:
any
=
columnData
.
cellValueList
;
// 列数据
let
className
=
styles
.
indexCell
;
// 只读列不可编辑样式
if
(
columnConfig
.
readOnlyFlag
||
rowData
.
isLocked
||
noEdit
)
{
className
+=
`
${
styles
.
disabled
}
`
;
}
let
extraIndexCellStyle
=
{};
let
extraCellContentStyle
=
{};
if
(
hasGroup
)
{
if
(
columnConfig
.
splitFlag
)
{
// 正常列额外样式
extraIndexCellStyle
=
{
borderTop
:
this
.
indexCount
[
rowData
.
groupId
][
0
]
!==
rowData
.
id
?
'1px solid #F7F7F7'
:
'1px solid #e8e8e8'
,
borderBottom
:
rowIndex
+
1
<
data
.
length
?
0
:
'1px solid #e8e8e8'
,
};
}
else
{
// 不可拆分列额外样式
extraIndexCellStyle
=
{
borderTop
:
this
.
indexCount
[
rowData
.
groupId
][
0
]
!==
rowData
.
id
?
0
:
'1px solid #e8e8e8'
,
borderBottom
:
rowIndex
+
1
<
data
.
length
?
0
:
'1px solid #e8e8e8'
,
};
// 不可拆分列数据样式
extraCellContentStyle
=
{
display
:
this
.
indexCount
[
rowData
.
groupId
][
Math
.
floor
((
this
.
indexCount
[
rowData
.
groupId
].
length
-
1
)
/
2
)
]
!==
rowData
.
id
?
'none'
:
'auto'
,
};
}
}
if
(
columnIndex
===
0
)
{
return
(
<
div
...
...
@@ -129,10 +291,36 @@ export default class AirTable extends Component<TableProps, TableState> {
className=
{
className
}
style=
{
{
...
style
,
...
extraIndexCellStyle
,
}
}
>
<
div
className=
{
styles
.
cellContent
}
>
<
Cell
columns=
{
columns
}
columnConfig=
{
columnConfig
}
rowData=
{
rowData
}
cellData=
{
cellData
}
/>
<
div
className=
{
styles
.
cellNo
}
>
{
this
.
renderCheckbox
(
filterRowData
,
rowIndex
)
}
<
img
alt=
"edit"
className=
{
styles
.
showFormBtn
}
src=
{
extendIcon
}
onClick=
{
showForm
.
bind
(
this
,
{
rowId
:
rowData
.
id
})
}
/>
</
div
>
<
div
className=
{
styles
.
cellContent
}
style=
{
extraCellContentStyle
}
>
<
Cell
columns=
{
columns
}
columnConfig=
{
columnConfig
}
rowData=
{
rowData
}
cellData=
{
cellData
}
updateData=
{
updateData
}
showForm=
{
showForm
}
delData=
{
delData
}
hasGroup=
{
hasGroup
}
getData=
{
getData
}
extraMenu=
{
extraMenu
}
noAdd=
{
noAdd
}
noEdit=
{
noEdit
}
noDel=
{
noDel
}
tableId=
{
tableId
}
flush=
{
flush
}
/>
</
div
>
</
div
>
);
...
...
@@ -143,10 +331,27 @@ export default class AirTable extends Component<TableProps, TableState> {
className=
{
className
}
style=
{
{
...
style
,
...
extraIndexCellStyle
,
}
}
>
<
div
className=
{
styles
.
cellContent
}
>
<
Cell
columns=
{
columns
}
columnConfig=
{
columnConfig
}
rowData=
{
rowData
}
cellData=
{
cellData
}
/>
<
div
className=
{
styles
.
cellContent
}
style=
{
extraCellContentStyle
}
>
<
Cell
columns=
{
columns
}
columnConfig=
{
columnConfig
}
rowData=
{
rowData
}
cellData=
{
cellData
}
updateData=
{
updateData
}
showForm=
{
showForm
}
delData=
{
delData
}
hasGroup=
{
hasGroup
}
getData=
{
getData
}
extraMenu=
{
extraMenu
}
noAdd=
{
noAdd
}
noEdit=
{
noEdit
}
noDel=
{
noDel
}
tableId=
{
tableId
}
flush=
{
flush
}
/>
</
div
>
</
div
>
);
...
...
@@ -154,6 +359,8 @@ export default class AirTable extends Component<TableProps, TableState> {
render
()
{
const
{
columns
,
dataSource
,
checked
}
=
this
.
state
;
const
{
changeChecked
,
operateConfig
=
{},
hasGroup
}
=
this
.
props
;
const
{
groupConfig
}
=
operateConfig
;
const
{
overscanColumnCount
,
overscanRowCount
,
columnWidth
,
rowHeight
}
=
this
.
config
;
let
{
height
}
=
this
.
state
;
if
(
dataSource
.
length
*
rowHeight
<
height
)
{
...
...
@@ -171,6 +378,13 @@ export default class AirTable extends Component<TableProps, TableState> {
{
({
onScroll
,
scrollLeft
,
scrollTop
}:
any
)
=>
{
return
(
<
div
className=
{
styles
.
GridRow
}
>
<
div
className=
{
styles
.
LeftSideContainer
}
style=
{
{
width
:
`${columnWidth * leftCount}px`
,
height
:
`${height + rowHeight}px`
,
}
}
>
{
//左侧表头
<
div
...
...
@@ -193,6 +407,8 @@ export default class AirTable extends Component<TableProps, TableState> {
rowCount=
{
1
}
height=
{
rowHeight
}
checked=
{
checked
}
changeChecked=
{
changeChecked
}
groupConfig=
{
groupConfig
}
dataSource=
{
dataSource
}
cellRenderer=
{
this
.
renderHeaderCell
}
/>
...
...
@@ -223,9 +439,11 @@ export default class AirTable extends Component<TableProps, TableState> {
checked=
{
checked
}
dataSource=
{
dataSource
}
columns=
{
columns
}
hasGroup=
{
hasGroup
}
/>
</
div
>
}
</
div
>
<
div
className=
{
styles
.
GridColumn
}
>
<
AutoSizer
disableHeight
>
{
({
width
}:
any
)
=>
(
...
...
@@ -284,6 +502,7 @@ export default class AirTable extends Component<TableProps, TableState> {
cellRenderer=
{
this
.
renderBodyCell
.
bind
(
this
,
data
)
}
columns=
{
columns
}
checked=
{
checked
}
hasGroup=
{
hasGroup
}
/>
</
div
>
}
...
...
src/common.less
0 → 100644
View file @
762f5814
//全局布局
@secondSliderBg: #F8FAFA; //二级菜单背景
@contentBg: #F5F5F5; //内容区背景
//全局color
@primaryColor: #04B4AD; //主题色 --关键行动点,操作状态、重要信息高亮,图形化等场
@textPrimaryColor: #2C3F53; //重要文字颜色 --用于重要级文字信息、内页标题信息(label)
@textGeneralColor: #5A6876; //普通文字颜色 --用于普通级段落信息、内标题信息(如详情段落标题信息)(value)
@textSupplyColor: #848F9B; //辅助文字颜色 --用于辅助、次要文字信息、普通按钮描边
@textHolderColor: #AEB4BA; // --用于表格输入框文字提示、缺省图下方文案
@borderColor: #ECECEC; // --分割线及边框颜色
@tableHoverBgColor: #F9FBFF; // --用于表格的选中底色
@disabledColor: #F9F9F9; //禁用颜色
@errorColor: #FF5363; //错误提示颜色
@hoverColor: #04B4AD; //鼠标悬停颜色
@operateColor: #04B4AD; //表格操作按钮颜色
// 菜单颜色
@sliderWidth: 70px; //一级菜单宽度
@secondSliderWidth: 180px; //二级菜单宽度
@headerHeight: 60px; //三级标题菜单高度
//全局字号
@textFontLgX: 18px; //标题
@textFontLg: 16px; //小标题&需醒目区别的正文
@textFontGen: 14px; //正文
@textFontSm: 12px; //正文和辅助文字
//全局间距
@marginLgX: 24px;
@marginLg: 16px;
@marginGen: 10px;
@marginSm: 8px;
@marginSmX: 5px;
@paddingLgX: 24px;
@paddingLg: 16px;
@paddingGen: 10px;
@paddingSm: 8px;
@paddingSmX: 5px;
//全局圆角
@borderRadius: 4px;
src/index.mdx
View file @
762f5814
...
...
@@ -11,4 +11,6 @@ import ApolloTable from './apollo-table';
## Normal ApolloTable
<div style={{position:"relative",margin:"0 20px"}}>
<ApolloTable>Hi</ApolloTable>
</div>
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment