Commit 762f5814 authored by zhangwenshuai's avatar zhangwenshuai

temp

parent e03e522d
......@@ -36,7 +36,7 @@
"lint-staged:ts": {
"src/**/*.{ts,tsx}": [
"prettier --write",
"tslint --fix",
"tslint --fix"
]
}
}
import React, { ReactComponentElement } from 'react';
import React from 'react';
import { message, Popover, Modal } from 'antd';
import { getComponent } from './base';
......
@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 {
margin-right: 5px;
min-width: 50px;
}
.cellContent {
......@@ -206,7 +196,7 @@
justify-content: center;
align-items: center;
text-align: center;
padding: 0 0.5em;
padding: 0 .5em;
}
.headerCell,
......
......@@ -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 (item1.groupId) {
if (this.indexCount[item1.groupId]) {
this.indexCount[item1.groupId].push(item1.id);
if (itemData.groupId) {
if (this.indexCount[itemData.groupId]) {
this.indexCount[itemData.groupId].push(itemData.id);
} else {
i++;
this.indexCount[item1.groupId] = [item1.id];
i += 1;
this.indexCount[itemData.groupId] = [itemData.id];
}
item1.index = i;
itemData.index = i;
}
return item1;
return itemData;
});
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>
}
......
//全局布局
@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;
......@@ -11,4 +11,6 @@ import ApolloTable from './apollo-table';
## Normal ApolloTable
<div style={{position:"relative",margin:"0 20px"}}>
<ApolloTable>Hi</ApolloTable>
</div>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment