Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
JackySoft committed Oct 9, 2024
2 parents e0653f9 + 5cdcadc commit cb91a5b
Show file tree
Hide file tree
Showing 10 changed files with 315 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { Form, TreeSelect, Divider, Select, Input, FormInstance } from 'antd';
import { useEffect, useState } from 'react';
import { ComponentMethodType } from '@/packages/types';
import { ComponentMethodParams, ComponentMethodType } from '@/packages/types';
import { usePageStore } from '@/stores/pageStore';
import styles from './index.module.less';
import VariableBind from '@/components/VariableBind/VariableBind';

/**
* 调用各个组件暴露的方法
Expand All @@ -13,6 +14,7 @@ const ComponentMethods = ({ form }: { form: FormInstance }) => {
const state = usePageStore();

const [methods, setMethods] = useState<ComponentMethodType[]>([]);
const [methodParams, setMethodParams] = useState<ComponentMethodParams[]>([]);

useEffect(() => {
const target = form.getFieldValue('target');
Expand All @@ -32,6 +34,13 @@ const ComponentMethods = ({ form }: { form: FormInstance }) => {
form.setFieldValue('methodName', methodName);
};

const handleChangeMethod = (value: string) => {
const targetMethod = methods.find((item) => item.name === value);
if (!targetMethod) return;
update(targetMethod?.title);
setMethodParams(targetMethod?.params || []);
};

return (
<>
<div className={styles.desc}>
Expand All @@ -50,14 +59,36 @@ const ComponentMethods = ({ form }: { form: FormInstance }) => {
/>
</Form.Item>
<Form.Item label="组件方法" name={'method'} rules={[{ required: true, message: '请选择调用的方法' }]}>
<Select onChange={(val) => update(methods.find((item) => item.name === val)?.title)} placeholder="请选择要调用的组件方法">
<Select onChange={(val) => handleChangeMethod(val)} placeholder="请选择要调用的组件方法">
{methods.map((item) => (
<Select.Option key={item.name} value={item.name}>
{item.title}
</Select.Option>
))}
</Select>
</Form.Item>

{methodParams.map((item, index) => (
<Form.Item
label={item.title}
name={'params' + index}
rules={item.required ? [{ required: true, message: '请选择调用的方法' }] : []}
key={'params' + index}
>
{item.type === 'select' ? (
<Select placeholder="请选择">
{item.options?.map((i) => (
<Select.Option key={i.value} value={i.value}>
{i.label}
</Select.Option>
))}
</Select>
) : (
<VariableBind placeholder="参数值" />
)}
</Form.Item>
))}

<Form.Item label="方法名称" name={'methodName'} hidden>
<Input />
</Form.Item>
Expand Down
5 changes: 5 additions & 0 deletions packages/editor/src/config/components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,11 @@ const components = [
name: '头像',
type: 'Avatar',
},
{
icon: '',
name: '二维码',
type: 'QRCode',
},
],
},
{
Expand Down
53 changes: 53 additions & 0 deletions packages/editor/src/packages/Basic/QRCode/QRCode.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import React, { forwardRef, ReactNode, useEffect, useImperativeHandle, useMemo, useState } from 'react';
import { QRCode } from 'antd';
import { ComponentType } from '@/packages/types';
import { omit } from 'lodash-es';

export type QRStatus = 'active' | 'expired' | 'loading' | 'scanned';

/*泛型只需要定义组件本身用到的属性*/
export interface IConfig {
value: string;
type?: 'canvas' | 'svg';
icon?: string;
size?: number;
iconSize?: number | { width: number; height: number };
color?: string;
bgColor?: string;
bordered?: boolean;
errorLevel?: 'L' | 'M' | 'Q' | 'H';
status: QRStatus;
}
/**
*
* @param props 组件本身属性
* @param style 组件样式
* @returns
*/
const MQRCode = ({ id, type, config }: ComponentType<IConfig>, ref: any) => {
const [statusEffect, setStatusEffect] = useState<QRStatus>(config.props.status);
const [visible, setVisible] = useState(true);
// 对外暴露方法
useImperativeHandle(ref, () => {
return {
show() {
setVisible(true);
},
hide() {
setVisible(false);
},
changeQRCodeStatus(status: QRStatus) {
setStatusEffect(status);
},
};
});

useEffect(() => {
setStatusEffect(config.props.status);
}, [config.props.status]);

const props = omit(config.props, ['status']);

return visible && <QRCode data-id={id} data-type={type} style={config.style} {...props} status={statusEffect}></QRCode>;
};
export default forwardRef(MQRCode);
158 changes: 158 additions & 0 deletions packages/editor/src/packages/Basic/QRCode/Schema.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
/**
* 组件配置和属性值
*/
export default {
// 组件属性配置JSON
attrs: [
{
type: 'Title',
label: '基础设置',
key: 'basic',
},
{
type: 'Variable',
label: '扫描后的结果',
name: 'value',
props: {
placeholder: '请输入',
},
},
{
type: 'Select',
label: '渲染类型',
name: 'type',
props: {
options: [
{ value: 'canvas', label: 'canvas' },
{ value: 'svg', label: 'svg' },
],
},
},
{
type: 'Variable',
label: '图片地址',
name: 'icon',
tooltip: '二维码中图片的地址(目前只支持图片地址)',
props: {
placeholder: '请输入图片地址',
},
},
{
type: 'InputNumber',
label: '二维码大小',
name: 'size',
props: {
placeholder: '二维码大小',
},
},
{
type: 'InputNumber',
label: '图片宽度',
name: ['iconSize', 'width'],
props: {
placeholder: '二维码中图片的宽度',
},
},
{
type: 'InputNumber',
label: '图片高度',
name: ['iconSize', 'height'],
props: {
placeholder: '二维码中图片的高度',
},
},
{
type: 'Variable',
label: '二维码颜色',
name: 'color',
props: {
placeholder: '请输入',
},
},
{
type: 'Variable',
label: '二维码背景颜色',
name: 'bgColor',
props: {
placeholder: '请输入',
},
},
{
type: 'Switch',
label: '是否有边框',
name: 'bordered',
},
{
type: 'Select',
label: '纠错等级',
name: 'errorLevel',
props: {
options: [
{ value: 'L', label: 'L' },
{ value: 'M', label: 'M' },
{ value: 'Q', label: 'Q' },
{ value: 'H', label: 'H' },
],
},
},
{
type: 'Select',
label: '二维码状态',
name: 'status',
props: {
options: [
{ value: 'active', label: 'active' },
{ value: 'expired', label: 'expired' },
{ value: 'loading', label: 'loading' },
{ value: 'scanned', label: 'scanned' },
],
},
},
],
config: {
// 组件默认属性值
props: {
value: 'https://ant.design',
type: 'canvas',
size: 160,
icon: 'https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg',
iconSize: { width: 40, height: 40 },
color: '#000',
bgColor: 'transparent',
bordered: true,
errorLevel: 'M',
status: 'active',
},
// 组件样式
style: {},
// 事件
events: [],
},
// 组件事件
events: [],
methods: [
{
name: 'changeQRCodeStatus',
title: '改变二维码状态',
params: [
{
name: 'status',
title: '状态值',
required: true,
type: 'select',
options: [
{ value: 'active', label: 'active' },
{ value: 'expired', label: 'expired' },
{ value: 'loading', label: 'loading' },
{ value: 'scanned', label: 'scanned' },
],
},
{
name: 'text',
title: '测试参数',
type: 'input',
},
],
},
],
};
2 changes: 2 additions & 0 deletions packages/editor/src/packages/Basic/QRCode/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default as QRCode } from './QRCode';
export { default as QRCodeConfig } from './Schema';
1 change: 1 addition & 0 deletions packages/editor/src/packages/Basic/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ export { Icon, IconConfig } from './Icon';
export { Avatar, AvatarConfig } from './Avatar';
export { Statistic, StatisticConfig } from './Statistic';
export { CountDown, CountDownConfig } from './CountDown';
export { QRCode, QRCodeConfig } from './QRCode';
1 change: 0 additions & 1 deletion packages/editor/src/packages/FeedBack/Result/Result.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ export interface IConfig {
*/
const MResult = ({ id, type, config }: ComponentType<IConfig>, ref: any) => {
const [visible, setVisible] = useState(true);
console.log(id, type, config, 'ppp');
// 对外暴露方法
useImperativeHandle(ref, () => {
return {
Expand Down
9 changes: 9 additions & 0 deletions packages/editor/src/packages/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,12 +153,21 @@ export interface NotificationAction {
duration: number;
}

export interface ComponentMethodParams {
name: string;
title: string;
required: boolean;
type: 'select' | 'input';
options?: Array<{ label: string; value: string }>;
}

/**
* 组件方法类型
*/
export interface ComponentMethodType {
name: string;
title: string;
params: ComponentMethodParams[];
}

/**
Expand Down
53 changes: 53 additions & 0 deletions packages/materials/Basic/QRCode/QRCode.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { forwardRef, useEffect, useImperativeHandle, useState } from 'react';
import { QRCode } from 'antd';
import { ComponentType } from '../../types';
import { omit } from 'lodash-es';

export type QRStatus = 'active' | 'expired' | 'loading' | 'scanned';

/*泛型只需要定义组件本身用到的属性*/
export interface IConfig {
value: string;
type?: 'canvas' | 'svg';
icon?: string;
size?: number;
iconSize?: number | { width: number; height: number };
color?: string;
bgColor?: string;
bordered?: boolean;
errorLevel?: 'L' | 'M' | 'Q' | 'H';
status: QRStatus;
}
/**
*
* @param props 组件本身属性
* @param style 组件样式
* @returns
*/
const MQRCode = ({ config }: ComponentType<IConfig>, ref: any) => {
const [statusEffect, setStatusEffect] = useState<QRStatus>(config.props.status);
const [visible, setVisible] = useState(true);
// 对外暴露方法
useImperativeHandle(ref, () => {
return {
show() {
setVisible(true);
},
hide() {
setVisible(false);
},
changeQRCodeStatus(status: QRStatus) {
setStatusEffect(status);
},
};
});

useEffect(() => {
setStatusEffect(config.props.status);
}, [config.props.status]);

const props = omit(config.props, ['status']);

return visible && <QRCode style={config.style} {...props} status={statusEffect}></QRCode>;
};
export default forwardRef(MQRCode);
1 change: 1 addition & 0 deletions packages/materials/Basic/QRCode/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as QRCode } from './QRCode';

0 comments on commit cb91a5b

Please sign in to comment.