mirror of
https://github.com/MrXujiang/h5-Dooring.git
synced 2025-12-15 20:34:17 +00:00
🆕 图标组件添加自定义跳转链接,文本等配置, 图表组件支持第三方api数据导入
This commit is contained in:
parent
5677c906c5
commit
43ab25e253
@ -4,21 +4,39 @@ import { AntdIconProps } from '@ant-design/icons/lib/components/AntdIcon';
|
|||||||
import { AntdIconType } from './icon';
|
import { AntdIconType } from './icon';
|
||||||
import { IIconConfig } from './schema';
|
import { IIconConfig } from './schema';
|
||||||
import logo from '@/assets/05-图标.png';
|
import logo from '@/assets/05-图标.png';
|
||||||
|
|
||||||
interface IconType extends IIconConfig {
|
interface IconType extends IIconConfig {
|
||||||
isTpl?: boolean;
|
isTpl?: boolean;
|
||||||
}
|
}
|
||||||
const XIcon = memo((props: IconType) => {
|
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> &
|
const MyIcon: React.ForwardRefExoticComponent<Pick<AntdIconProps, AntdIconType> &
|
||||||
React.RefAttributes<HTMLSpanElement>> = Icon[type];
|
React.RefAttributes<HTMLSpanElement>> = Icon[type];
|
||||||
|
|
||||||
|
const handleClick = () => {
|
||||||
|
if (!link || window.location.href.indexOf('/editor') > -1) return;
|
||||||
|
window.location.href = link;
|
||||||
|
};
|
||||||
|
|
||||||
return isTpl ? (
|
return isTpl ? (
|
||||||
<div>
|
<div>
|
||||||
<img src={logo} alt="" />
|
<img style={{ width: '100%' }} src={logo} alt="" />
|
||||||
</div>
|
</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>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -1,21 +1,31 @@
|
|||||||
import {
|
import {
|
||||||
ICardPickerConfigType,
|
ICardPickerConfigType,
|
||||||
IColorConfigType,
|
IColorConfigType,
|
||||||
|
ITextConfigType,
|
||||||
INumberConfigType,
|
INumberConfigType,
|
||||||
ISwitchConfigType,
|
ISwitchConfigType,
|
||||||
TCardPickerDefaultType,
|
TCardPickerDefaultType,
|
||||||
TColorDefaultType,
|
TColorDefaultType,
|
||||||
TNumberDefaultType,
|
TNumberDefaultType,
|
||||||
TSwitchDefaultType,
|
TSwitchDefaultType,
|
||||||
|
TTextDefaultType,
|
||||||
} from '@/core/FormComponents/types';
|
} from '@/core/FormComponents/types';
|
||||||
|
|
||||||
export type TIconEditData = Array<
|
export type TIconEditData = Array<
|
||||||
IColorConfigType | INumberConfigType | ISwitchConfigType | ICardPickerConfigType<IconTypes>
|
| IColorConfigType
|
||||||
|
| INumberConfigType
|
||||||
|
| ISwitchConfigType
|
||||||
|
| ICardPickerConfigType<IconTypes>
|
||||||
|
| ITextConfigType
|
||||||
>;
|
>;
|
||||||
export interface IIconConfig {
|
export interface IIconConfig {
|
||||||
color: TColorDefaultType;
|
color: TColorDefaultType;
|
||||||
size: TNumberDefaultType;
|
size: TNumberDefaultType;
|
||||||
|
text: TTextDefaultType;
|
||||||
|
fontSize: TNumberDefaultType;
|
||||||
|
fontColor: TColorDefaultType;
|
||||||
spin: TSwitchDefaultType;
|
spin: TSwitchDefaultType;
|
||||||
|
link: TTextDefaultType;
|
||||||
type: TCardPickerDefaultType<IconTypes>;
|
type: TCardPickerDefaultType<IconTypes>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,6 +89,26 @@ const Icon: IIconSchema = {
|
|||||||
name: '大小',
|
name: '大小',
|
||||||
type: 'Number',
|
type: 'Number',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: 'text',
|
||||||
|
name: '文本',
|
||||||
|
type: 'Text',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'fontSize',
|
||||||
|
name: '文本大小',
|
||||||
|
type: 'Number',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'fontColor',
|
||||||
|
name: '文本颜色',
|
||||||
|
type: 'Color',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'link',
|
||||||
|
name: '跳转链接',
|
||||||
|
type: 'Text',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: 'spin',
|
key: 'spin',
|
||||||
name: '旋转动画',
|
name: '旋转动画',
|
||||||
@ -136,6 +166,10 @@ const Icon: IIconSchema = {
|
|||||||
config: {
|
config: {
|
||||||
color: 'rgba(74,144,226,1)',
|
color: 'rgba(74,144,226,1)',
|
||||||
size: 36,
|
size: 36,
|
||||||
|
text: '图标',
|
||||||
|
fontSize: 14,
|
||||||
|
fontColor: 'rgba(0,0,0,1)',
|
||||||
|
link: '',
|
||||||
spin: false,
|
spin: false,
|
||||||
type: 'CarTwoTone',
|
type: 'CarTwoTone',
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
const template = {
|
const template = {
|
||||||
type: 'Icon',
|
type: 'Icon',
|
||||||
h: 23,
|
h: 36,
|
||||||
displayName: '图标组件',
|
displayName: '图标组件',
|
||||||
};
|
};
|
||||||
export default template;
|
export default template;
|
||||||
|
|||||||
@ -24,3 +24,9 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.apiForm {
|
||||||
|
.formItem {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -114,6 +114,11 @@ class EditableTable extends React.Component<any, any> {
|
|||||||
editable?: undefined;
|
editable?: undefined;
|
||||||
}
|
}
|
||||||
)[];
|
)[];
|
||||||
|
apiForm: {
|
||||||
|
api: string;
|
||||||
|
header: string;
|
||||||
|
dataField: string;
|
||||||
|
};
|
||||||
|
|
||||||
constructor(props: any) {
|
constructor(props: any) {
|
||||||
super(props);
|
super(props);
|
||||||
@ -142,12 +147,20 @@ class EditableTable extends React.Component<any, any> {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
this.apiForm = {
|
||||||
|
api: '',
|
||||||
|
header: '',
|
||||||
|
dataField: '',
|
||||||
|
};
|
||||||
|
|
||||||
const dataSource =
|
const dataSource =
|
||||||
props.data && props.data.map((item: any, i: number) => ({ key: i + '', ...item }));
|
props.data && props.data.map((item: any, i: number) => ({ key: i + '', ...item }));
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
dataSource: dataSource,
|
dataSource: dataSource,
|
||||||
visible: false,
|
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() {
|
render() {
|
||||||
const { dataSource } = this.state;
|
const { dataSource } = this.state;
|
||||||
const components = {
|
const components = {
|
||||||
@ -263,7 +329,6 @@ class EditableTable extends React.Component<any, any> {
|
|||||||
_this.props.onChange && _this.props.onChange(sourceData);
|
_this.props.onChange && _this.props.onChange(sourceData);
|
||||||
};
|
};
|
||||||
reader.readAsBinaryString(file);
|
reader.readAsBinaryString(file);
|
||||||
return true;
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
@ -287,10 +352,13 @@ class EditableTable extends React.Component<any, any> {
|
|||||||
添加行
|
添加行
|
||||||
</Button>
|
</Button>
|
||||||
<Upload {...props}>
|
<Upload {...props}>
|
||||||
<Button type="primary" ghost>
|
<Button type="primary" ghost style={{ marginRight: 16 }}>
|
||||||
导入Excel
|
导入Excel
|
||||||
</Button>
|
</Button>
|
||||||
</Upload>
|
</Upload>
|
||||||
|
<Button type="primary" ghost onClick={this.showApiModal}>
|
||||||
|
第三方API
|
||||||
|
</Button>
|
||||||
<Table
|
<Table
|
||||||
components={components}
|
components={components}
|
||||||
rowClassName={() => 'editable-row'}
|
rowClassName={() => 'editable-row'}
|
||||||
@ -301,6 +369,51 @@ class EditableTable extends React.Component<any, any> {
|
|||||||
scroll={{ y: 240 }}
|
scroll={{ y: 240 }}
|
||||||
/>
|
/>
|
||||||
</Modal>
|
</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>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user