🆕 图标组件添加自定义跳转链接,文本等配置, 图表组件支持第三方api数据导入

This commit is contained in:
xujiang 2020-12-27 14:04:17 +08:00
parent 5677c906c5
commit 43ab25e253
5 changed files with 178 additions and 7 deletions

View File

@ -4,21 +4,39 @@ import { AntdIconProps } from '@ant-design/icons/lib/components/AntdIcon';
import { AntdIconType } from './icon';
import { IIconConfig } from './schema';
import logo from '@/assets/05-图标.png';
interface IconType extends IIconConfig {
isTpl?: boolean;
}
const XIcon = memo((props: IconType) => {
const { color, size, type, spin, isTpl } = props;
const { color, size, link, text, fontSize, fontColor, type, spin, isTpl } = props;
const MyIcon: React.ForwardRefExoticComponent<Pick<AntdIconProps, AntdIconType> &
React.RefAttributes<HTMLSpanElement>> = Icon[type];
const handleClick = () => {
if (!link || window.location.href.indexOf('/editor') > -1) return;
window.location.href = link;
};
return isTpl ? (
<div>
<img src={logo} alt="" />
<img style={{ width: '100%' }} src={logo} alt="" />
</div>
) : (
<MyIcon twoToneColor={color} style={{ fontSize: size }} spin={spin} />
<div
style={{
display: 'flex',
width: '100%',
height: '100%',
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'column',
}}
>
<MyIcon twoToneColor={color} style={{ fontSize: size }} spin={spin} onClick={handleClick} />
<div style={{ fontSize, color: fontColor, paddingTop: '6px' }}> {text} </div>
</div>
);
});

View File

@ -1,21 +1,31 @@
import {
ICardPickerConfigType,
IColorConfigType,
ITextConfigType,
INumberConfigType,
ISwitchConfigType,
TCardPickerDefaultType,
TColorDefaultType,
TNumberDefaultType,
TSwitchDefaultType,
TTextDefaultType,
} from '@/core/FormComponents/types';
export type TIconEditData = Array<
IColorConfigType | INumberConfigType | ISwitchConfigType | ICardPickerConfigType<IconTypes>
| IColorConfigType
| INumberConfigType
| ISwitchConfigType
| ICardPickerConfigType<IconTypes>
| ITextConfigType
>;
export interface IIconConfig {
color: TColorDefaultType;
size: TNumberDefaultType;
text: TTextDefaultType;
fontSize: TNumberDefaultType;
fontColor: TColorDefaultType;
spin: TSwitchDefaultType;
link: TTextDefaultType;
type: TCardPickerDefaultType<IconTypes>;
}
@ -79,6 +89,26 @@ const Icon: IIconSchema = {
name: '大小',
type: 'Number',
},
{
key: 'text',
name: '文本',
type: 'Text',
},
{
key: 'fontSize',
name: '文本大小',
type: 'Number',
},
{
key: 'fontColor',
name: '文本颜色',
type: 'Color',
},
{
key: 'link',
name: '跳转链接',
type: 'Text',
},
{
key: 'spin',
name: '旋转动画',
@ -136,6 +166,10 @@ const Icon: IIconSchema = {
config: {
color: 'rgba(74,144,226,1)',
size: 36,
text: '图标',
fontSize: 14,
fontColor: 'rgba(0,0,0,1)',
link: '',
spin: false,
type: 'CarTwoTone',
},

View File

@ -1,6 +1,6 @@
const template = {
type: 'Icon',
h: 23,
h: 36,
displayName: '图标组件',
};
export default template;

View File

@ -24,3 +24,9 @@
}
}
}
.apiForm {
.formItem {
margin-bottom: 16px;
}
}

View File

@ -114,6 +114,11 @@ class EditableTable extends React.Component<any, any> {
editable?: undefined;
}
)[];
apiForm: {
api: string;
header: string;
dataField: string;
};
constructor(props: any) {
super(props);
@ -142,12 +147,20 @@ class EditableTable extends React.Component<any, any> {
},
];
this.apiForm = {
api: '',
header: '',
dataField: '',
};
const dataSource =
props.data && props.data.map((item: any, i: number) => ({ key: i + '', ...item }));
this.state = {
dataSource: dataSource,
visible: false,
apiVisible: false,
apiResult: '',
};
}
@ -203,6 +216,59 @@ class EditableTable extends React.Component<any, any> {
});
};
showApiModal = () => {
this.setState({
apiVisible: true,
});
};
handleAPIOk = () => {
const { dataField } = this.apiForm;
if (dataField) {
let data = this.state.apiResult[dataField];
if (data && data instanceof Array) {
data = data.map((item, i) => ({ key: i + '', ...item }));
this.setState({
dataSource: data,
});
this.props.onChange && this.props.onChange(data);
}
this.setState({
apiVisible: false,
});
}
};
handleAPICancel = () => {
this.setState({
apiVisible: false,
});
};
handleApiField = (type: 'api' | 'header' | 'dataField', v: string) => {
this.apiForm[type] = v;
};
getApiFn = () => {
console.log(this.apiForm);
const { api, header } = this.apiForm;
fetch(api, {
cache: 'no-cache',
headers: Object.assign(
{ 'content-type': 'application/json' },
header ? JSON.parse(header) : {},
),
method: 'GET',
mode: 'cors',
})
.then(res => res.json())
.then(res => {
this.setState({
apiResult: res,
});
});
};
render() {
const { dataSource } = this.state;
const components = {
@ -263,7 +329,6 @@ class EditableTable extends React.Component<any, any> {
_this.props.onChange && _this.props.onChange(sourceData);
};
reader.readAsBinaryString(file);
return true;
},
};
return (
@ -287,10 +352,13 @@ class EditableTable extends React.Component<any, any> {
</Button>
<Upload {...props}>
<Button type="primary" ghost>
<Button type="primary" ghost style={{ marginRight: 16 }}>
Excel
</Button>
</Upload>
<Button type="primary" ghost onClick={this.showApiModal}>
API
</Button>
<Table
components={components}
rowClassName={() => 'editable-row'}
@ -301,6 +369,51 @@ class EditableTable extends React.Component<any, any> {
scroll={{ y: 240 }}
/>
</Modal>
<Modal
title="配置api"
visible={this.state.apiVisible}
onOk={this.handleAPIOk}
onCancel={this.handleAPICancel}
okText="确定"
cancelText="取消"
>
<div className={styles.apiForm}>
<div className={styles.formItem}>
<Input
placeholder="请输入api地址"
onChange={e => this.handleApiField('api', e.target.value)}
/>
</div>
<div className={styles.formItem}>
<Input.TextArea
placeholder="请输入头信息, 如{token: 123456}, 格式必须为json对象"
rows={4}
onChange={e => this.handleApiField('header', e.target.value)}
/>
</div>
<div className={styles.formItem}>
<Button type="primary" onClick={this.getApiFn}>
</Button>
</div>
{this.state.apiResult && (
<>
<div className={styles.formItem}>
<Input.TextArea rows={6} value={JSON.stringify(this.state.apiResult, null, 4)} />
</div>
<div className={styles.formItem}>
<Input
placeholder="设置数据源字段"
onChange={e => this.handleApiField('dataField', e.target.value)}
/>
<p style={{ color: 'red' }}>
, ,
</p>
</div>
</>
)}
</div>
</Modal>
</div>
);
}