Commit 762f5814 authored by zhangwenshuai's avatar zhangwenshuai

temp

parent e03e522d
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
"lint-staged:ts": { "lint-staged:ts": {
"src/**/*.{ts,tsx}": [ "src/**/*.{ts,tsx}": [
"prettier --write", "prettier --write",
"tslint --fix", "tslint --fix"
] ]
} }
} }
import React, { ReactComponentElement } from 'react'; import React from 'react';
import { message, Popover, Modal } from 'antd'; import { message, Popover, Modal } from 'antd';
import { getComponent } from './base'; import { getComponent } from './base';
......
@import '../../common';
.tableCell { .tableCell {
//padding: 0 !important;
&.sortCol { &.sortCol {
background: rgba(92, 153, 255, 0.2); background: @hoverColor;
} }
} }
...@@ -18,23 +19,13 @@ ...@@ -18,23 +19,13 @@
:global(.ant-table-thead > tr > th) { :global(.ant-table-thead > tr > th) {
padding: 0; 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) { :global(.ant-table-tbody > tr > td) {
padding: 0; padding: 0;
height: 40px; height: 40px;
} }
//:global(.ant-table-tbody > tr > td:first-child) {
// border-right: none;
//}
:global(.ant-table-tbody > tr > td:last-child) { :global(.ant-table-tbody > tr > td:last-child) {
text-align: left; text-align: left;
} }
...@@ -48,13 +39,6 @@ ...@@ -48,13 +39,6 @@
background: white; 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) { :global(.ant-table-row-hover) {
.unchecked { .unchecked {
display: block; display: block;
...@@ -80,7 +64,7 @@ ...@@ -80,7 +64,7 @@
box-sizing: border-box; box-sizing: border-box;
&.disabled { &.disabled {
background: #f9f9f9; background: @disabledColor;
&:hover { &:hover {
box-shadow: none; box-shadow: none;
...@@ -88,7 +72,7 @@ ...@@ -88,7 +72,7 @@
} }
&:hover { &:hover {
box-shadow: inset 0 0 0 1px #85b6ff; box-shadow: inset 0 0 0 1px @operateColor;
.showFormBtn { .showFormBtn {
visibility: visible; visibility: visible;
...@@ -106,9 +90,11 @@ ...@@ -106,9 +90,11 @@
.cellNo { .cellNo {
display: flex; display: flex;
align-items: center; align-items: center;
min-width: 50px;
} }
.cellContent { .cellContent {
flex: 1; flex: 1;
overflow: hidden; overflow: hidden;
height: 100%; height: 100%;
...@@ -143,6 +129,11 @@ ...@@ -143,6 +129,11 @@
display: flex; display: flex;
flex-direction: row; flex-direction: row;
background: #fff; background: #fff;
.LeftSideContainer{
box-shadow: 6px 0 6px -4px rgba(0, 0, 0, 0.15);
position: absolute;
z-index: 1;
}
} }
.GridColumn { .GridColumn {
...@@ -157,7 +148,6 @@ ...@@ -157,7 +148,6 @@
z-index: 10; z-index: 10;
background: #fff; background: #fff;
border-left: 1px solid #e8e8e8; border-left: 1px solid #e8e8e8;
box-shadow: 6px 0 6px -4px rgba(0, 0, 0, 0.15);
} }
.LeftSideGrid { .LeftSideGrid {
...@@ -181,7 +171,7 @@ ...@@ -181,7 +171,7 @@
box-sizing: border-box; box-sizing: border-box;
.cellNo { .cellNo {
margin-right: 5px; min-width: 50px;
} }
.cellContent { .cellContent {
...@@ -206,7 +196,7 @@ ...@@ -206,7 +196,7 @@
justify-content: center; justify-content: center;
align-items: center; align-items: center;
text-align: center; text-align: center;
padding: 0 0.5em; padding: 0 .5em;
} }
.headerCell, .headerCell,
......
...@@ -8,6 +8,7 @@ import styles from './Table.less'; ...@@ -8,6 +8,7 @@ import styles from './Table.less';
import { TableProps, TableState } from './interface'; import { TableProps, TableState } from './interface';
import Column from './Column'; import Column from './Column';
import Cell from './Cell'; import Cell from './Cell';
import extendIcon from '../assets/extend.png';
export default class AirTable extends Component<TableProps, TableState> { export default class AirTable extends Component<TableProps, TableState> {
static getDerivedStateFromProps(nextProps: TableProps, prevState: TableState) { static getDerivedStateFromProps(nextProps: TableProps, prevState: TableState) {
...@@ -26,10 +27,11 @@ export default class AirTable extends Component<TableProps, TableState> { ...@@ -26,10 +27,11 @@ export default class AirTable extends Component<TableProps, TableState> {
} }
constructor(props: TableProps) { constructor(props: TableProps) {
super(props); super(props);
const { columns, dataSource, tableId } = props; const { columns, dataSource, tableId, checked = [] } = props;
this.state = { this.state = {
columns, columns,
dataSource, dataSource,
checked,
tableId, tableId,
prevProps: props, prevProps: props,
height: document.body.clientHeight - 193, height: document.body.clientHeight - 193,
...@@ -43,12 +45,24 @@ export default class AirTable extends Component<TableProps, TableState> { ...@@ -43,12 +45,24 @@ export default class AirTable extends Component<TableProps, TableState> {
}; };
this.memoizeLeftCount = memoizeOne(this.getLeftCount); this.memoizeLeftCount = memoizeOne(this.getLeftCount);
this.memoizeData = memoizeOne(this.filterData); this.memoizeData = memoizeOne(this.filterData);
this.indexCount = {};
}
componentDidMount() {
window.addEventListener('resize', this.resize, false);
} }
//重置窗口高度
resize = () => {
this.setState({
height: document.body.clientHeight - 193,
});
};
//获取左侧固定列数量 //获取左侧固定列数量
getLeftCount = (columns: []) => { getLeftCount = (columns: []) => {
let len = 0; let len = 0;
columns.map((item: any) => { columns.map((item: any) => {
item.fixed && len++; if (item.fixed) {
len += 1;
}
}); });
return len; return len;
}; };
...@@ -61,31 +75,104 @@ export default class AirTable extends Component<TableProps, TableState> { ...@@ -61,31 +75,104 @@ export default class AirTable extends Component<TableProps, TableState> {
let i = 0; let i = 0;
this.indexCount = {}; this.indexCount = {};
cloneData.map((item1: any) => { 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), columns.some((temp: any) => temp.columnName === item2.colName),
); );
if (item1.groupId) { if (itemData.groupId) {
if (this.indexCount[item1.groupId]) { if (this.indexCount[itemData.groupId]) {
this.indexCount[item1.groupId].push(item1.id); this.indexCount[itemData.groupId].push(itemData.id);
} else { } else {
i++; i += 1;
this.indexCount[item1.groupId] = [item1.id]; this.indexCount[itemData.groupId] = [itemData.id];
} }
item1.index = i; itemData.index = i;
} }
return item1; return itemData;
}); });
return cloneData; 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) => { onScrollRow = ({ clientHeight, scrollTop }: any) => {
const height = clientHeight + scrollTop || 0; const height = clientHeight + scrollTop || 0;
const { dataSource = [], rowHeight = 40 } = this.state; const { dataSource = [], rowHeight = 40 } = this.state;
const { onScroll } = this.props;
const offset = 100; const offset = 100;
if (dataSource.length === 0) return; if (dataSource.length === 0) return;
if (height + offset >= dataSource.length * rowHeight) { if (height + offset >= dataSource.length * rowHeight && typeof onScroll === 'function') {
this.props.onScroll && this.props.onScroll(); onScroll();
} else return; }
}; };
//渲染表头 //渲染表头
renderHeaderCell = ({ columnIndex, key, rowIndex, style }: any) => { renderHeaderCell = ({ columnIndex, key, rowIndex, style }: any) => {
...@@ -96,7 +183,7 @@ export default class AirTable extends Component<TableProps, TableState> { ...@@ -96,7 +183,7 @@ export default class AirTable extends Component<TableProps, TableState> {
return ( return (
<div key={key} className={styles.leftHeaderCell} style={{ ...style, width: width || 200 }}> <div key={key} className={styles.leftHeaderCell} style={{ ...style, width: width || 200 }}>
<div className={styles.cellNo}> <div className={styles.cellNo}>
<Checkbox /> <Checkbox checked={this.getCheckedAll()} onClick={this.changeCheckboxAll} />
</div> </div>
<div className={styles.cellContent}> <div className={styles.cellContent}>
<Column type={String(columnType)} title={columnChsName} width={width} /> <Column type={String(columnType)} title={columnChsName} width={width} />
...@@ -110,18 +197,93 @@ export default class AirTable extends Component<TableProps, TableState> { ...@@ -110,18 +197,93 @@ export default class AirTable extends Component<TableProps, TableState> {
</div> </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) => { 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) { if (columns.length === 0 || data.length === 0) {
return; return;
} }
const rowData: any = data[rowIndex] || {}; const filterRowData: any = data[rowIndex]; // 过滤掉隐藏项并追加行号的行数据,只在渲染逻辑中使用
const columnData: any = (rowData.rowData && rowData.rowData[columnIndex]) || {}; const rowData: any = dataSource[rowIndex]; // 原始行数据,真实使用的数据
const cellData: [] = columnData.cellValueList || []; const columnConfig: any = columns[columnIndex]; // 列属性
let columnConfig = columns[columnIndex]; const columnData: any = rowData.rowData[columnIndex]; // 列数据
const cellData: any = columnData.cellValueList; // 列数据
let className = styles.indexCell; 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) { if (columnIndex === 0) {
return ( return (
<div <div
...@@ -129,10 +291,36 @@ export default class AirTable extends Component<TableProps, TableState> { ...@@ -129,10 +291,36 @@ export default class AirTable extends Component<TableProps, TableState> {
className={className} className={className}
style={{ style={{
...style, ...style,
...extraIndexCellStyle,
}} }}
> >
<div className={styles.cellContent}> <div className={styles.cellNo}>
<Cell columns={columns} columnConfig={columnConfig} rowData={rowData} cellData={cellData} /> {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>
</div> </div>
); );
...@@ -143,10 +331,27 @@ export default class AirTable extends Component<TableProps, TableState> { ...@@ -143,10 +331,27 @@ export default class AirTable extends Component<TableProps, TableState> {
className={className} className={className}
style={{ style={{
...style, ...style,
...extraIndexCellStyle,
}} }}
> >
<div className={styles.cellContent}> <div className={styles.cellContent} style={extraCellContentStyle}>
<Cell columns={columns} columnConfig={columnConfig} rowData={rowData} cellData={cellData} /> <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>
</div> </div>
); );
...@@ -154,6 +359,8 @@ export default class AirTable extends Component<TableProps, TableState> { ...@@ -154,6 +359,8 @@ export default class AirTable extends Component<TableProps, TableState> {
render() { render() {
const { columns, dataSource, checked } = this.state; const { columns, dataSource, checked } = this.state;
const { changeChecked, operateConfig = {}, hasGroup } = this.props;
const { groupConfig } = operateConfig;
const { overscanColumnCount, overscanRowCount, columnWidth, rowHeight } = this.config; const { overscanColumnCount, overscanRowCount, columnWidth, rowHeight } = this.config;
let { height } = this.state; let { height } = this.state;
if (dataSource.length * rowHeight < height) { if (dataSource.length * rowHeight < height) {
...@@ -171,6 +378,13 @@ export default class AirTable extends Component<TableProps, TableState> { ...@@ -171,6 +378,13 @@ export default class AirTable extends Component<TableProps, TableState> {
{({ onScroll, scrollLeft, scrollTop }: any) => { {({ onScroll, scrollLeft, scrollTop }: any) => {
return ( return (
<div className={styles.GridRow}> <div className={styles.GridRow}>
<div
className={styles.LeftSideContainer}
style={{
width: `${columnWidth * leftCount}px`,
height: `${height + rowHeight}px`,
}}
>
{ {
//左侧表头 //左侧表头
<div <div
...@@ -193,6 +407,8 @@ export default class AirTable extends Component<TableProps, TableState> { ...@@ -193,6 +407,8 @@ export default class AirTable extends Component<TableProps, TableState> {
rowCount={1} rowCount={1}
height={rowHeight} height={rowHeight}
checked={checked} checked={checked}
changeChecked={changeChecked}
groupConfig={groupConfig}
dataSource={dataSource} dataSource={dataSource}
cellRenderer={this.renderHeaderCell} cellRenderer={this.renderHeaderCell}
/> />
...@@ -223,9 +439,11 @@ export default class AirTable extends Component<TableProps, TableState> { ...@@ -223,9 +439,11 @@ export default class AirTable extends Component<TableProps, TableState> {
checked={checked} checked={checked}
dataSource={dataSource} dataSource={dataSource}
columns={columns} columns={columns}
hasGroup={hasGroup}
/> />
</div> </div>
} }
</div>
<div className={styles.GridColumn}> <div className={styles.GridColumn}>
<AutoSizer disableHeight> <AutoSizer disableHeight>
{({ width }: any) => ( {({ width }: any) => (
...@@ -284,6 +502,7 @@ export default class AirTable extends Component<TableProps, TableState> { ...@@ -284,6 +502,7 @@ export default class AirTable extends Component<TableProps, TableState> {
cellRenderer={this.renderBodyCell.bind(this, data)} cellRenderer={this.renderBodyCell.bind(this, data)}
columns={columns} columns={columns}
checked={checked} checked={checked}
hasGroup={hasGroup}
/> />
</div> </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'; ...@@ -11,4 +11,6 @@ import ApolloTable from './apollo-table';
## Normal ApolloTable ## Normal ApolloTable
<div style={{position:"relative",margin:"0 20px"}}>
<ApolloTable>Hi</ApolloTable> <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