Commit 5f14696a authored by zhangwenshuai's avatar zhangwenshuai

finish input textarea select date number

parent cdafc0f7
......@@ -15,6 +15,7 @@
position: absolute;
z-index: 1;
width: 100%;
height: 100%;
top: 0;
left: 0;
}
import React, { useState } from 'react';
import React, { useEffect, useState } from 'react';
import { message } from 'antd';
import { config } from './config';
import s from './Cell.less';
......@@ -11,7 +11,7 @@ interface CellData {
}
const Cell = (props: CellProps) => {
const { columnConfig, cellClassName, cellStyle, rowData, cellData, emitChangeCell } = props;
const { width, columnType, columnName, requiredFlag } = columnConfig || {};
const { width, columnType, columnName, requiredFlag, renderDetailCell, renderEditCell } = columnConfig || {};
if (config[String(columnType)] === undefined) {
return null;
......@@ -19,6 +19,10 @@ const Cell = (props: CellProps) => {
const Comp = config[String(columnType)].component;
const [status, setStatus] = useState('detail');
useEffect(() => {
setStatus('detail');
}, [cellData]);
const changeCellData = (changedValue) => {
console.log('onChange', changedValue);
};
......@@ -29,6 +33,7 @@ const Cell = (props: CellProps) => {
temp.push({ text: item.text, value: item.value });
});
if (_.isEqual(temp, changedValue)) {
setStatus('detail');
return;
}
changeValue(changedValue, optionValue);
......@@ -67,7 +72,11 @@ const Cell = (props: CellProps) => {
}
};
const renderDetailCell = () => {
const selfRenderDetailCell = () => {
let detailCell = null;
if (typeof renderDetailCell === 'function') {
detailCell = renderDetailCell({ cellData, rowData, columnConfig });
}
return (
<div
className={s.detailCell}
......@@ -75,37 +84,46 @@ const Cell = (props: CellProps) => {
setStatus('edit');
}}
>
<Comp.Detail value={cellData} columnConfig={columnConfig} />
{detailCell}
{!detailCell && <Comp.Detail value={cellData} columnConfig={columnConfig} />}
</div>
);
};
const renderEditCell = () => {
const selfRenderEditCell = () => {
let editCell = null;
if (typeof renderEditCell === 'function') {
editCell = renderEditCell({ cellData, rowData, columnConfig });
}
return (
<div
className={s.editCell}
onBlur={() => {
setStatus('detail');
}}
// onBlur={() => {
// setStatus('detail');
// }}
>
<Comp
value={cellData}
columnConfig={columnConfig}
onChange={changeCellData}
onEmitChange={emitChangeCellData}
style={{
minHeight: cellStyle.height,
borderRadius: 0,
}}
/>
{editCell}
{!editCell && (
<Comp
value={cellData}
columnConfig={columnConfig}
onChange={changeCellData}
onEmitChange={emitChangeCellData}
style={{
minHeight: cellStyle.height,
borderRadius: 0,
}}
/>
)}
</div>
);
};
return (
<div className={cellClassName} style={{ ...cellStyle, width: width || 200 }}>
{status === 'detail' && renderDetailCell()}
{status === 'edit' && renderEditCell()}
{status === 'detail' && selfRenderDetailCell()}
{status === 'edit' && selfRenderEditCell()}
</div>
);
};
......
......@@ -105,7 +105,7 @@ export default class AirTable extends Component<TableProps, TableState> {
onScroll = ({ clientHeight, scrollHeight, scrollTop }: any) => {
const height = clientHeight + scrollTop || 0;
const { onScroll, distanceToLoad = 100 } = this.props;
if (height + distanceToLoad >= scrollHeight && typeof onScroll === 'function') {
if (scrollTop > 0 && height + distanceToLoad >= scrollHeight && typeof onScroll === 'function') {
onScroll();
}
};
......
export const formatStr = 'YYYY-MM-DD HH:mm:ss';
export const emptyModel = [{ text: '', value: '' }];
const emptyFormat = (value) => {};
export const SetFormatter = {
INPUT: (event) => {
const node = event.currentTarget || {};
return [{ value: node.value, text: node.value }];
INPUT: (value) => {
if (!value) {
return emptyModel;
}
return [{ value: value, text: value }];
},
SEARCH: (val) => {
if (!val || typeof val !== 'object') return val;
......
......@@ -9,8 +9,11 @@ export const config: any = {
component: require('./edit/input').default,
setFormatter: SetFormatter['INPUT'],
getFormatter: GetFormatter['INPUT'],
componentAttr: {
autoFocus: true,
emitTrigger: 'onBlur',
},
detail: require('./detail/input').default,
icon: require('../../assets/type/text.png'),
},
'2': {
name: '超链接',
......@@ -25,7 +28,7 @@ export const config: any = {
getFormatter: GetFormatter['TEXTAREA'],
setFormatter: SetFormatter['TEXTAREA'],
componentAttr: {
autoSize: true,
autoFocus: true,
emitTrigger: 'onBlur',
},
detail: require('./detail/textarea').default,
......@@ -50,6 +53,8 @@ export const config: any = {
componentAttr: {
labelInValue: true,
allowClear: true,
autoFocus: true,
emitTrigger: 'onBlur',
},
getFormatter: GetFormatter['SELECT'],
setFormatter: SetFormatter['SELECT'],
......@@ -62,6 +67,8 @@ export const config: any = {
labelInValue: true,
mode: 'tags',
maxTagCount: 3,
autoFocus: true,
emitTrigger: 'onBlur',
},
getFormatter: GetFormatter['MULTIPLE_SELECT'],
setFormatter: SetFormatter['MULTIPLE_SELECT'],
......@@ -82,6 +89,8 @@ export const config: any = {
name: '数字输入',
component: require('./edit/number').default,
componentAttr: {
autoFocus: true,
emitTrigger: 'onBlur',
precision: 2,
},
setFormatter: SetFormatter['NUMBER'],
......
import React from 'react';
import React, { useState } from 'react';
import { DatePicker } from 'antd';
import styles from './styles.less';
import { DateProps } from '../editInterface';
import { ApolloDateProps } from '../editInterface';
import { antiAssign } from '@/apollo-table/utils/utils';
export default function(props: DateProps) {
const { value, placeholder, allowClear, disabled, format, showTime,onChange } = props;
const ApolloDate = (props: ApolloDateProps) => {
const { onChange, emitTrigger, onEmitChange, showTime } = props;
const selfProps = antiAssign(props, ['columnConfig', 'value', 'onChange', 'emitTrigger', 'onEmitChange']);
let trigger = emitTrigger;
if (showTime) {
trigger = 'onOk';
}
const [value, setValue] = useState(props.value);
const changeValue = (value, dateString) => {
setValue(value);
if (typeof onChange === 'function') {
onChange(value, dateString);
}
if (!trigger || trigger === 'onChange') {
emitChange(value);
}
};
const selfProps = { value, placeholder, allowClear, disabled, format, showTime,onChange };
const emitChange = (value) => {
if (typeof onEmitChange === 'function') {
onEmitChange(value);
}
};
const onOk = (value) => {
emitChange(value);
};
if (trigger === 'onOk') {
selfProps.onOk = onOk;
}
return (
<div className={styles.container}>
<DatePicker {...selfProps} />
<DatePicker className={styles.date} {...selfProps} value={value} onChange={changeValue} />
</div>
);
}
};
export default ApolloDate;
......@@ -2,16 +2,19 @@
position: relative;
top: 0;
left: 0;
.input {
padding-right: 100px;
}
.wordNumber {
position: absolute;
color: #E1E1E1FF;
font-size: 12px;
right: 7px;
top: 7px;
width: 100%;
height: 100%;
font-size: 0;
.date {
width: 100%;
height: 100%;
border-radius: 0;
div {
height: 100%;
}
:global(.ant-calendar-picker-input.ant-input) {
height: 100%;
border-radius: 0;
}
}
}
import { DatePickerProps } from 'antd/es/date-picker/interface';
import { TextAreaProps } from 'antd/es/input';
import { TextAreaProps, InputProps } from 'antd/es/input';
import { InputNumberProps } from 'antd/es/input-number';
import { SelectProps } from 'antd/es/select';
export interface CommonProps {
onEmitChange?: Function;
emitTrigger?: string;
}
export interface InputProps extends CommonProps {
maxLength: number;
export interface ApolloInputProps extends InputProps, CommonProps {
value: string | undefined;
}
export interface LinkProps extends CommonProps {
value: any[];
......@@ -26,12 +28,9 @@ export interface SearchProps extends CommonProps {
tableId?: number;
paramsJson?: any;
}
export interface SelectProps extends CommonProps {
export interface ApolloSelectProps extends SelectProps, CommonProps {
isMultiple?: boolean;
maxCount?: number;
tableId?: number;
options?: any[];
allowClear?: boolean;
}
export interface RateProps {
value: number;
......@@ -41,21 +40,8 @@ export interface RateProps {
onChange: any;
disabled?: boolean;
}
export interface NumberProps {
export interface ApolloNumberProps extends InputNumberProps, CommonProps {
value: number | undefined;
onChange: Function;
cellData?: any[];
floatRange?: number;
rowId?: number;
columnConfig?: any;
precision: number;
min: number;
max: number;
step?: number | string;
}
export interface NumberState {
prevProps: NumberProps;
value: number | undefined;
cellData?: any[];
}
export interface DateProps extends DatePickerProps {}
export interface ApolloDateProps extends DatePickerProps, CommonProps {}
import React from 'react';
import React, { useState, useEffect } from 'react';
import { Input } from 'antd';
import styles from './styles.less';
import { InputProps } from '../editInterface';
import { antiAssign } from '@/apollo-table/utils/utils';
import { ApolloInputProps } from '../editInterface';
export default function(props: InputProps) {
const { value, maxLength, placeholder,onChange } = props;
const selfProps = { value, maxLength, placeholder,onChange };
const ApolloInput = (props: ApolloInputProps) => {
const { maxLength, onChange, emitTrigger, onEmitChange, style } = props;
const selfProps = antiAssign(props, ['value', 'onChange', 'emitTrigger', 'onEmitChange', 'style']);
const [value, setValue] = useState(props.value);
useEffect(() => {
setValue(props.value);
}, [props.value]);
const changeValue = (e) => {
setValue(e.target.value);
if (typeof onChange === 'function') {
onChange(e.target.value);
}
if (!emitTrigger || emitTrigger === 'onChange') {
emitChange(e);
}
};
const emitChange = (e) => {
if (typeof onEmitChange === 'function') {
onEmitChange(e.target.value);
}
};
if (emitTrigger === 'onBlur') {
selfProps.onBlur = emitChange;
}
const newStyle:any = {
...style
};
if (maxLength && style) {
newStyle.minHeight = Number(style.minHeight) + 10;
newStyle.paddingBottom = 18;
}
return (
<div className={styles.container}>
<Input className={styles.input} {...selfProps} />
{maxLength && (
<Input
className={styles.input}
style={newStyle}
{...selfProps}
value={value}
onChange={changeValue}
/>
{!!maxLength && (
<span className={styles.wordNumber}>
已输入{(value || '').length || 0}/{maxLength}
已输入{(value || '').length}/{maxLength}
</span>
)}
</div>
);
}
};
export default ApolloInput;
......@@ -2,16 +2,15 @@
position: relative;
top: 0;
left: 0;
.input {
padding-right: 100px;
//padding-bottom: 18px;
}
.wordNumber {
position: absolute;
color: #E1E1E1FF;
right: 12px;
bottom: 2px;
color: #e1e1e1ff;
font-size: 12px;
right: 7px;
top: 7px;
}
}
import React, { Component } from 'react';
import { InputNumber, Modal } from 'antd';
import React, { useEffect, useState } from 'react';
import { InputNumber } from 'antd';
import styles from './styles.less';
import { NumberProps, NumberState } from '../editInterface';
import { ApolloNumberProps } from '../editInterface';
import { antiAssign } from '@/apollo-table/utils/utils';
export default class extends Component<NumberProps, NumberState> {
static getDerivedStateFromProps(nextProps: NumberProps, prevState: NumberState) {
const { prevProps } = prevState;
let nextState: NumberState = {
...prevState,
prevProps: nextProps,
value: nextProps.value,
cellData: nextProps.cellData,
};
if (JSON.stringify(prevProps.value) !== JSON.stringify(nextProps.value)) {
nextState.value = nextProps.value;
const ApolloNumber = (props: ApolloNumberProps) => {
const { onChange, emitTrigger, onEmitChange } = props;
const selfProps = antiAssign(props, ['value', 'onChange', 'emitTrigger', 'onEmitChange']);
const [value, setValue] = useState(props.value);
useEffect(() => {
setValue(props.value);
}, [props.value]);
const changeValue = (value) => {
setValue(value);
if (typeof onChange === 'function') {
onChange(value);
}
if (JSON.stringify(prevProps.cellData) !== JSON.stringify(nextProps.cellData)) {
nextState.cellData = nextProps.cellData;
if (!emitTrigger || emitTrigger === 'onChange') {
emitChange(value);
}
return nextState;
}
constructor(props: NumberProps) {
super(props);
const { value, cellData } = props;
this.state = {
prevProps: props,
value,
cellData,
};
}
onChange = (changedValue: number | undefined) => {
this.setState({
value: changedValue,
});
};
resetValue = () => {
const { cellData } = this.state;
this.setState({
value: cellData && cellData.length > 0 ? cellData[0].value : undefined,
cellData,
});
const onBlur = (e) => {
emitChange(e.target.value);
};
onBlur = (e: any) => {
const {
onChange,
floatRange,
columnConfig: { columnChsName },
rowId,
} = this.props;
const { cellData } = this.state;
const originValue = Array.isArray(cellData) && cellData.length > 0 ? cellData[0].value : undefined;
// 检测浮动条件:编辑时,有浮动标记,原值不为0
if (rowId && floatRange && originValue && Number(originValue) !== 0) {
// 新值默认取0只用于计算,对应清空操作
const changedValue = e.target.value || 0;
const range = Math.abs(Number(changedValue) - Number(originValue)) / Number(originValue);
if (Number(range) > Number(floatRange)) {
const confirm = Modal.confirm({
title: '确认提示',
content: `${columnChsName}变更浮动较大,是否确认提交?`,
onOk: () => {
onChange({ changedValue: e.target.value, isBlur: true });
},
onCancel: () => {
this.resetValue();
confirm.destroy();
},
});
return;
}
const emitChange = (value) => {
if (typeof onEmitChange === 'function') {
onEmitChange(value);
}
onChange({ changedValue: e.target.value, isBlur: true });
};
render() {
const { value } = this.state;
const { precision, min, max } = this.props;
const selfProps = { value, precision, min, max };
return (
<div className={styles.container}>
<InputNumber {...selfProps} onChange={this.onChange} onBlur={this.onBlur} value={value} />
</div>
);
if (emitTrigger === 'onBlur') {
selfProps.onBlur = onBlur;
}
}
return (
<div className={styles.container}>
<InputNumber className={styles.number} {...selfProps} value={value} onChange={changeValue} />
</div>
);
};
export default ApolloNumber;
.container {
position: relative;
top: 0;
left: 0;
.number {
width: 100%;
:global(.ant-input-number-input-wrap){
height: 100%;
input {
height: 100%;
}
}
}
}
import React from 'react';
import React, { useEffect, useState } from 'react';
import { Select } from 'antd';
import { SelectProps } from '../editInterface';
import { ApolloSelectProps } from '../editInterface';
import { antiAssign } from '@/apollo-table/utils/utils';
import styles from './styles.less';
export default function(props: SelectProps) {
const { options = [], allowClear, disabled, placeholder, value, onChange, isMultiple } = props;
const selfProps: any = { allowClear, disabled, placeholder, value, onChange };
const ApolloSelect = (props: ApolloSelectProps) => {
const { options = [], onChange, emitTrigger, onEmitChange, isMultiple } = props;
const selfProps = antiAssign(props, ['value', 'onChange', 'emitTrigger', 'onEmitChange', 'isMultiple', 'options']);
const [value, setValue] = useState(props.value);
const [option, setOption] = useState(undefined);
useEffect(() => {
setValue(props.value);
setOption(undefined);
}, [props.value]);
const changeValue = (value, option) => {
setValue(value);
setOption(option);
if (typeof onChange === 'function') {
onChange(value, option);
}
if (!emitTrigger || emitTrigger === 'onChange') {
emitChange(value, option);
}
};
const emitChange = (value, option) => {
if (typeof onEmitChange === 'function') {
onEmitChange(value, option);
}
};
const onBlur = () => {
emitChange(value, option);
};
if (emitTrigger === 'onBlur') {
selfProps.onBlur = onBlur;
}
if (isMultiple) {
selfProps.mode = 'multiple';
}
return (
<Select {...selfProps}>
{options.map((item) => (
<Select.Option key={item.id} value={item.id}>
{item.name}
</Select.Option>
))}
</Select>
<div className={styles.container} onBlur={onBlur}>
<Select className={styles.select} {...selfProps} value={value} onChange={changeValue}>
{options.map((item) => (
<Select.Option key={item.id} value={item.id}>
{item.name}
</Select.Option>
))}
</Select>
</div>
);
}
};
export default ApolloSelect;
.container {
position: relative;
top: 0;
left: 0;
width: 100%;
height: 100%;
font-size: 0;
.select {
width: 100%;
height: 100%;
border-radius: 0;
:global(.ant-select-selection--single) {
height: 100%;
border-radius: 0;
}
}
}
......@@ -4,7 +4,7 @@ import styles from './styles.less';
import { antiAssign } from '@/apollo-table/utils/utils';
import { ApolloTextAreaProps } from '../editInterface';
const TextArea = (props: ApolloTextAreaProps) => {
const ApolloTextArea = (props: ApolloTextAreaProps) => {
const { maxLength, onChange, emitTrigger, onEmitChange } = props;
const selfProps = antiAssign(props, ['value', 'onChange', 'emitTrigger', 'onEmitChange']);
const [value, setValue] = useState(props.value);
......@@ -31,11 +31,14 @@ const TextArea = (props: ApolloTextAreaProps) => {
}
return (
<div className={styles.container}>
<Input.TextArea className={styles.input} {...selfProps} value={value} onChange={changeValue} />
{maxLength && (
<span className={styles.wordNumber}>{`已输入${(value || '').length}/${maxLength}`}</span>
)}
<Input.TextArea
className={styles.input}
{...selfProps}
value={value}
onChange={changeValue}
/>
{!!maxLength && <span className={styles.wordNumber}>{`已输入${(value || '').length}/${maxLength}`}</span>}
</div>
);
};
export default TextArea;
export default ApolloTextArea;
......@@ -5,9 +5,6 @@
.input {
padding-bottom: 18px;
}
textarea {
padding-bottom: 18px;
}
.wordNumber {
position: absolute;
right: 12px;
......
......@@ -68,12 +68,12 @@ export const getComponent = (type: string) => {
}
};
// 触发修改回调
onEmitChange = (changedValue: any) => {
onEmitChange = (changedValue: any,option:any) => {
const { columnConfig } = this.state;
const { onEmitChange } = this.props;
let value = setFormat(columnConfig, changedValue);
if (typeof onEmitChange === 'function') {
onEmitChange(value,changedValue);
onEmitChange(value,option);
}
};
......
......@@ -80,7 +80,7 @@ export interface CellProps {
cellData: any;
emitChangeCell: Function;
cellClassName?: string;
cellStyle: object;
cellStyle: any;
}
export interface CellState {
status: string;
......
.row{
.row {
color: green;
}
.xxx {
color: blue;
}
......@@ -2,7 +2,8 @@ import React, { useState, useEffect, useCallback } from 'react';
import _ from 'lodash';
import ApolloTable from '../apollo-table';
import { getColumnConfig, getDataSource, addOrUpdateDataSource } from './serives';
import { message } from 'antd';
import { Input, message, DatePicker } from 'antd';
import moment from 'moment';
import s from './demo1.less';
const rowStyle = ({ rowIndex }) => {
......@@ -31,7 +32,7 @@ const Demo1 = (props) => {
const res = await getColumnConfig({ tableId });
if (res && res.success && res.data) {
const arr = Array.isArray(res.data) ? res.data : [];
setColumns(arr);
setColumns(formatColumns(arr));
}
};
getColumnsList();
......@@ -43,7 +44,7 @@ const Demo1 = (props) => {
hasNextPage: false,
nextPage: 1,
});
const [flush,setFlush]=useState(false);
const [flush, setFlush] = useState(false);
useEffect(() => {
const getDataList = async () => {
const data = {
......@@ -85,6 +86,45 @@ const Demo1 = (props) => {
fetchData(true);
}
};
const renderDetailCell = (data) => {
const { columnConfig, cellData } = data;
const record = data.rowData;
const { id, rowData } = record;
const { columnName } = columnConfig;
if (columnName === 'customerNameInput') {
return <div className={s.xxx}>{cellData[0] && cellData[0].text}</div>;
}
};
const renderEditCell = (data) => {
const { columnConfig, cellData } = data;
const record = data.rowData;
const { id, rowData } = record;
const { columnName } = columnConfig;
if (columnName === 'followUpDate') {
const value = moment(cellData[0] && cellData[0].value);
return (
<div className={s.xxx}>
<DatePicker
value={value}
getPopupContainer={(trigger) => {
return trigger.parentElement;
}}
/>
</div>
);
}
};
const formatColumns = (columns) => {
columns.map((item) => {
if (item.columnName === 'followUpDate') {
item.renderDetailCell = renderDetailCell;
// item.renderEditCell = renderEditCell;
}
return item;
});
return columns;
};
return (
<ApolloTable
rowStyle={rowStyle}
......
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