import styles from './ReactVisualEditor.less';
import {
  createVisualBlock,
  ReactVisualEditorBlock,
  ReactVisualEditorComponent,
  ReactVisualEditorConfig,
  ReactVisualEditorValue,
} from './ReactVisualEditor.utils';
import React, { useMemo, useRef } from 'react';
import ReactDom from 'react-dom';
import { ReactVisualBlock } from './ReactVisualBlock';
import { useCallbackRef } from './../hook/useCallbackRef';
import { useVisualCommand } from './ReactVisualEditor.command';
import { createEvent } from './../plugin/event';
import classNames from 'classnames';
import { $$dialog } from './../service/dialog/$$dialog';
import { notification, Radio, Modal, Input, Collapse, Space } from 'antd';
import { $$dropdown, DropdownItem } from './../service/dropdown/$$dropdown';
import useState from 'react-usestateref';
import Drawer, { PlacementInfo } from './Drawer';
const { Panel } = Collapse;
import { ReactVisualBlockResize, ReactVisualBlockResizeDirection } from './ReactVisualBlockResize';
import deepcopy from 'deepcopy';
import { ReactVisualOperator } from './ReactVisualOperator';
import { setLocalStorage, getLocalStorage, TEMPLATE_KEY } from './../localStorage';
import { visualConfig } from './visual.config';
import defaultData from './../defaultData';
import { getData } from './../requests/example';
export interface Fs {
  name: string;
  age: number;
}
export const ReactVisualEditor: React.FC<{
  value?: ReactVisualEditorValue;
  containerSize?: {
    height: string;
    width: string;
  };
}> = (props) => {
  const [preview, setPreview] = useState(false); // 当前是否处于预览状态
  const [editing, setEditing] = useState(true); // 当前是否处于编辑状态
  const [selectIndex, setSelectIndex] = useState(-1); // 当前选中的block的索引
  const [editorValue, setEditorValue] = useState<ReactVisualEditorValue>(
    props.value || defaultData,
  );
  const [dragstart] = useState(() => createEvent());
  const [dragend] = useState(() => createEvent());
  const [menuVisible, setMenuVisible] = useState(false); //菜单栏是否展开
  const [operatorVisible, setOperatorVisible] = useState(false); //属性栏是否展开
  const selectBlock = useMemo(
    () => editorValue.blocks[selectIndex] as ReactVisualEditorBlock | undefined,
    [editorValue.blocks, selectIndex],
  );
  /**
   * container dom对象的引用
   */
  const containerRef = useRef({} as HTMLDivElement);

  /**
   * body dom对象的引用
   */
  const bodyRef = useRef({} as HTMLDivElement);

  /**
   * container dom对象的样式
   */
  const containerStyles = useMemo(() => {
    return {
      height: props.containerSize?.height || `1200px`,
      width: props.containerSize?.width || `2550px`,
      backgroundSize: 'cover',
      overflow: 'hidden',
      background: editorValue.container.backgroundImage
        ? `url('${editorValue.container.backgroundImage}')`
        : editorValue.container.background,
    };
  }, [
    editorValue.container.height,
    editorValue.container.width,
    editorValue.container.backgroundImage,
    editorValue.container.themeColor,
    props.containerSize
  ]);

  const classes = useMemo(
    () => classNames([styles.reactVisualEditor, preview && styles.reactVisualEditorPreview]),
    [preview],
  );

  /**
   * 计算当前编辑的数据中，那些block元素是选中的，那些未选中的
   */
  const focusData = useMemo(() => {
    const focus: ReactVisualEditorBlock[] = [];
    const unFocus: ReactVisualEditorBlock[] = [];
    editorValue.blocks.forEach((block) => {
      (block.focus ? focus : unFocus).push(block);
    });
    return { focus, unFocus };
  }, [editorValue.blocks]);

  /**
   * 对外暴露的方法
   */
  const methods = {
    updateValue: (value: ReactVisualEditorValue) => {
      setEditorValue({ ...value });
    },
    /**
     * 更新blocks，触发重新渲染
     */
    updateBlocks: (blocks: ReactVisualEditorBlock[]) => {
      setEditorValue({ ...editorValue, blocks: [...blocks] });
    },
    /**
     * 清空选中的元素
     */
    clearFocus: (external?: ReactVisualEditorBlock) => {
      (!!external ? focusData.focus.filter((item) => item !== external) : focusData.focus).forEach(
        (block) => {
          block.focus = false;
        },
      );
      methods.updateBlocks(editorValue.blocks);
    },
    /**
     * 显示(导出)block数据
     */
    showBlockData: (block: ReactVisualEditorBlock) => {
      $$dialog.textarea(JSON.stringify(block), { editReadonly: true, title: '节点数据' });
    },
    /**
     * 导入block数据
     */
    importBlockData: async (block: ReactVisualEditorBlock) => {
      const text = await $$dialog.textarea('', { title: '请输入导入的节点内容JSON字符串' });
      try {
        const data = JSON.parse(text || '');
        commander.updateBlock(data, block);
      } catch (e) {
        console.error(e);
        notification.open({
          message: '导入失败！',
          description: '导入的数据格式不正常，请检查！',
        });
      }
    },
  };

  /**
   * 拖拽处理逻辑，处理从menu菜单中拖拽预定义的组件到容器中
   */
  const menuDraggier = (() => {
    const dragData = useRef({
      dragComponent: null as null | ReactVisualEditorComponent,
    });

    const block = {
      dragstart: useCallbackRef(
        (e: React.DragEvent<HTMLDivElement>, dragComponent: ReactVisualEditorComponent) => {
          containerRef.current.addEventListener('dragenter', container.dragenter);
          containerRef.current.addEventListener('dragover', container.dragover);
          containerRef.current.addEventListener('dragleave', container.dragleave);
          containerRef.current.addEventListener('drop', container.drop);
          dragData.current.dragComponent = dragComponent;
          dragstart.emit();
        },
      ),
      dragend: useCallbackRef((e: React.DragEvent<HTMLDivElement>) => {
        containerRef.current.removeEventListener('dragenter', container.dragenter);
        containerRef.current.removeEventListener('dragover', container.dragover);
        containerRef.current.removeEventListener('dragleave', container.dragleave);
        containerRef.current.removeEventListener('drop', container.drop);
      }),
    };

    const container = {
      dragenter: useCallbackRef((e: DragEvent) => {
        e.dataTransfer!.dropEffect = 'move';
      }),
      dragover: useCallbackRef((e: DragEvent) => {
        e.preventDefault();
      }),
      dragleave: useCallbackRef((e: DragEvent) => {
        e.dataTransfer!.dropEffect = 'none';
      }),
      drop: useCallbackRef((e: DragEvent) => {
        methods.updateBlocks([
          ...editorValue.blocks,
          createVisualBlock({
            top: e.offsetY,
            left: e.offsetX,
            component: dragData.current.dragComponent!,
          }),
        ]);
        setTimeout(dragend.emit);
      }),
    };

    return block;
  })();

  /**
   * 处理block元素的选中事件
   */
  const focusHandler = (() => {
    const block = (
      e: React.MouseEvent<HTMLDivElement>,
      block: ReactVisualEditorBlock,
      index: number,
    ) => {
      if (preview) return;
      if (e.button === 2) {
        /*右键不做任何处理*/
        return;
      }
      if (e.shiftKey) {
        /*如果摁住了shift键，如果此时没有选中的block，就选中这个block，否则令这个block的选中状态取反*/
        if (focusData.focus.length <= 1) {
          block.focus = true;
        } else {
          block.focus = !block.focus;
        }
        methods.updateBlocks(editorValue.blocks);
      } else {
        /*如果点击的这个block没有被选中，才清空这个其他选中的block，否则不做任何事情。放置拖拽多个block，取消其他block的选中状态*/
        if (!block.focus) {
          block.focus = true;
          methods.clearFocus(block);
        }
      }
      setSelectIndex(block.focus ? index : -1);
      setTimeout(() => blockDraggier.mousedown(e, block));
    };
    const container = (e: React.MouseEvent<HTMLDivElement>) => {
      if (preview) return;
      if (e.target !== e.currentTarget) {
        return;
      }
      if (!e.shiftKey) {
        methods.clearFocus();
        setSelectIndex(-1);
      }
    };
    return {
      block,
      container,
    };
  })();

  /**
   * 处理block元素在container容器内的拖拽动作
   */
  const blockDraggier = (() => {
    const [mark, setMark] = useState({ x: null as null | number, y: null as null | number });

    const dragData = useRef({
      startX: 0, // 拖拽开始时，鼠标的left
      startY: 0, // 拖拽开始的时候，鼠标的top值
      moveX: 0, // 拖拽过程中鼠标的left值
      moveY: 0, // 拖拽过程中，鼠标的top值
      shiftKey: false, // 当前是否摁住了shift键
      body: {
        startScrollTop: 0, // 拖拽开始时，body的scrollTop值
        moveScrollTop: 0, // 拖拽过程中，固定body的scrollTop值
      },
      startLeft: 0, // 拖拽开始的时候，拖拽的block的left
      startTop: 0, // 拖拽开始的时候，拖拽的block的top
      startPosArray: [] as { top: number; left: number }[], // 拖拽开始的时候，所有选中的block元素的top值以及left值
      dragging: false, // 当前是否处于拖拽状态
      /**
       * markLines 拖拽元素的时候，计算当前未选中的数据中，与拖拽元素之间应该显示的辅助线
       */
      markLines: {
        /*横向辅助线*/
        x: [] as { left: number; showLeft: number }[],
        /*纵向辅助线*/
        y: [] as { top: number; showTop: number }[],
      },
    });

    const handleMove = useCallbackRef(() => {
      if (!dragData.current.dragging) {
        dragData.current.dragging = true;
        dragstart.emit();
      }

      let {
        moveX,
        moveY,
        body,
        shiftKey,
        startX,
        startY,
        startPosArray,
        markLines,
        startLeft,
        startTop,
      } = dragData.current;
      moveY = moveY + (body.moveScrollTop - body.startScrollTop);

      if (shiftKey) {
        if (Math.abs(moveX - startX) > Math.abs(moveY - startY)) {
          moveY = startY;
        } else {
          moveX = startX;
        }
      }

      const now = {
        mark: {
          x: null as null | number,
          y: null as null | number,
        },
        top: startTop + moveY - startY,
        left: startLeft + moveX - startX,
      };

      for (let i = 0; i < markLines.y.length; i++) {
        const { top, showTop } = markLines.y[i];
        if (Math.abs(now.top - top) < 5) {
          moveY = top + startY - startTop;
          now.mark.y = showTop;
        }
      }
      for (let i = 0; i < markLines.x.length; i++) {
        const { left, showLeft } = markLines.x[i];
        if (Math.abs(now.left - left) < 5) {
          moveX = left + startX - startLeft;
          now.mark.x = showLeft;
        }
      }

      const durX = moveX - startX,
        durY = moveY - startY;
      console.log('e.clientX', durX);
      focusData.focus.forEach((block, index) => {
        const { left, top } = startPosArray[index];
        block.top = top + durY;
        block.left = left + durX;
      });
      methods.updateBlocks(editorValue.blocks);
      setMark(now.mark);
    });
    const mousedown = useCallbackRef(
      (e: React.MouseEvent<HTMLDivElement>, block: ReactVisualEditorBlock) => {
        e.stopPropagation();
        document.addEventListener('mouseup', mouseup);
        document.addEventListener('mousemove', mousemove);

        bodyRef.current.addEventListener('scroll', scroll);
        dragData.current = {
          startX: e.clientX,
          startY: e.clientY,
          moveX: e.clientX,
          moveY: e.clientY,
          shiftKey: e.shiftKey,
          body: {
            startScrollTop: bodyRef.current.scrollTop,
            moveScrollTop: bodyRef.current.scrollTop,
          },
          startLeft: block.left,
          startTop: block.top,
          startPosArray: focusData.focus.map(({ top, left }) => ({ top, left })),
          dragging: false,
          markLines: (() => {
            const x: { left: number; showLeft: number }[] = [];
            const y: { top: number; showTop: number }[] = [];
            const { unFocus } = focusData;
            unFocus.forEach((b) => {
              y.push({ top: b.top, showTop: b.top }); // 顶部对顶部
              y.push({
                top: b.top + b.height / 2 - block.height / 2,
                showTop: b.top + b.height / 2,
              }); // 中间对中间
              y.push({ top: b.top + b.height - block.height, showTop: b.top + b.height }); // 底部对齐底部
              y.push({ top: b.top - block.height, showTop: b.top }); // 底部对齐顶部
              y.push({ top: b.top + b.height, showTop: b.top + b.height }); // 顶部对齐底部

              x.push({ left: b.left, showLeft: b.left }); // 左侧对齐左侧
              x.push({
                left: b.left + b.width / 2 - block.width / 2,
                showLeft: b.left + b.width / 2,
              }); // 中间对中间
              x.push({ left: b.left + b.width - block.width, showLeft: b.left + b.width }); // 右侧对齐右侧
              x.push({ left: b.left - block.width, showLeft: b.left }); // 右侧对齐左侧
              x.push({ left: b.left + b.width, showLeft: b.left + b.width }); // 左侧对齐右侧
            });

            return { x, y };
          })(),
        };
      },
    );
    const mousemove = useCallbackRef((e: MouseEvent) => {
      console.log('mousemove');
      dragData.current.moveX = e.clientX;
      dragData.current.moveY = e.clientY;
      handleMove();
    });
    const mouseup = useCallbackRef((e: MouseEvent) => {
      console.log('mouseup');
      document.removeEventListener('mousemove', mousemove);
      document.removeEventListener('mouseup', mouseup);
      bodyRef.current.removeEventListener('scroll', scroll);
      setMark({ x: null, y: null });
      if (dragData.current.dragging) {
        dragend.emit();
      }
    });
    const scroll = useCallbackRef((e: Event) => {
      dragData.current.body.moveScrollTop = (e.target as HTMLDivElement).scrollTop;
      handleMove();
    });

    return {
      mousedown,
      mark,
    };
  })();

  /**
   * 处理block元素拖拽调整大小的拖拽动作
   */
  const resizeDraggier = (() => {
    const dragData = useRef({
      block: {} as ReactVisualEditorBlock, // 拖拽开始的时候，拖拽的block元素对象应用
      startX: 0, // 拖拽开始的时候，鼠标的left
      startY: 0, // 拖拽开始的时候，鼠标的top值
      direction: {
        // 拖拽的指示点，是什么方向的点，如果是偏顶部，左侧的点，在拖拽的时候，差值要取反，并且还需要修改block的top或者left值
        horizontal: ReactVisualBlockResizeDirection.start,
        vertical: ReactVisualBlockResizeDirection.start,
      },
      startBlock: {
        top: 0, // 拖拽开始的时候，block的top值
        left: 0, // 拖拽开始的时候，block的left值
        height: 0, // 拖拽开始的时候，block的高度
        width: 0, // 拖拽开始的时候，block的宽度
      },
      dragging: false, // 第一次move的时候才需要派发dragstart事件
    });
    const mousedown = useCallbackRef(
      (
        e: React.MouseEvent<HTMLDivElement>,
        direction: {
          horizontal: ReactVisualBlockResizeDirection;
          vertical: ReactVisualBlockResizeDirection;
        },
        block: ReactVisualEditorBlock,
      ) => {
        e.stopPropagation();
        document.addEventListener('mousemove', mousemove);
        document.addEventListener('mouseup', mouseup);
        dragData.current = {
          block,
          startX: e.clientX,
          startY: e.clientY,
          direction,
          startBlock: { ...deepcopy(block) },
          dragging: false,
        };
      },
    );
    const mousemove = useCallbackRef((e: MouseEvent) => {
      if (!dragData.current.dragging) {
        dragData.current.dragging = true;
        dragstart.emit();
      }
      let { clientX: moveX, clientY: moveY } = e;
      const { startX, startY, startBlock, direction, block } = dragData.current;
      if (direction.horizontal === ReactVisualBlockResizeDirection.center) {
        moveX = startX;
      }
      if (direction.vertical === ReactVisualBlockResizeDirection.center) {
        moveY = startY;
      }

      let durX = moveX - startX;
      let durY = moveY - startY;

      if (direction.vertical === ReactVisualBlockResizeDirection.start) {
        durY = -durY;
        block!.top = startBlock.top - durY;
      }
      if (direction.horizontal === ReactVisualBlockResizeDirection.start) {
        durX = -durX;
        block!.left = startBlock.left - durX;
      }

      const width = startBlock.width + durX;
      const height = startBlock.height + durY;
      block!.width = width;
      block!.height = height;
      block!.hasResize = true;
      methods.updateBlocks(editorValue.blocks);
    });
    const mouseup = useCallbackRef((e: MouseEvent) => {
      document.removeEventListener('mousemove', mousemove);
      document.removeEventListener('mouseup', mouseup);
      if (dragData.current.dragging) {
        setTimeout(dragend.emit);
      }
    });

    return {
      mousedown,
    };
  })();

  /**
   * 命令管理对象
   */
  const commander = useVisualCommand({
    value: editorValue,
    focusData,
    updateBlocks: methods.updateBlocks,
    updateValue: methods.updateValue,
    dragstart,
    dragend,
  });
  const ListMode: React.FC<{ list: Array<{ name: string; obj: {} }>; isSave?: boolean }> = ({
    isSave = false,
    ...prop
  }) => {
    const [show, setShow] = useState(true);
    const [addValue, setAddValue, refAddValue] = useState('1');
    const [value, setValue, refValue] = useState(
      prop.list.length > 0 ? prop.list[0].name : refAddValue.current,
    );
    const onChange = (ev: any) => {
      setValue(ev.target.value);
    };
    return (
      <Modal
        centered={true}
        destroyOnClose={true}
        title={isSave ? '保存模板' : '选择模板'}
        visible={show}
        onCancel={() => setShow(false)}
        onOk={() => {
          if (isSave) {
            if (value && value !== '1' && value !== '') {
              setLocalStorage(value, JSON.stringify(editorValue));
              setShow(false);
            } else {
              notification.warning({ message: '提示', description: '请输入模板名称' });
            }
          } else {
            for (let i = 0; i < prop.list.length; i++) {
              if (prop.list[i].name === value) {
                commander.updateValue(JSON.parse(prop.list[i].obj) as ReactVisualEditorValue);
                break;
              }
            }
            setShow(false);
          }
        }}
      >
        <Radio.Group onChange={onChange} value={refValue.current}>
          <Space direction="vertical">
            {prop.list.map((item, index) => {
              return (
                <Radio value={item.name} key={index}>
                  {item.name}
                </Radio>
              );
            })}
            {isSave && (
              <Radio value={refAddValue.current}>
                <Input
                  onChange={(v) => {
                    if (refAddValue.current === refValue.current) {
                      setValue(v.target.value);
                    }
                    setAddValue(v.target.value);
                  }}
                  placeholder={'增加新模板'}
                />
              </Radio>
            )}
          </Space>
        </Radio.Group>
      </Modal>
    );
  };
  const handler = {
    onContextMenuBlock: (e: React.MouseEvent<HTMLDivElement>, block: ReactVisualEditorBlock) => {
      e.preventDefault();
      e.stopPropagation();

      $$dropdown({
        reference: e.nativeEvent,
        render: () => (
          <>
            <DropdownItem icon="icon-place-top" onClick={commander.placeTop}>
              置顶节点
            </DropdownItem>
            <DropdownItem icon="icon-place-bottom" onClick={commander.placeBottom}>
              置底节点
            </DropdownItem>
            <DropdownItem icon="icon-delete" onClick={commander.delete}>
              删除节点
            </DropdownItem>
            <DropdownItem icon="icon-browse" onClick={() => methods.showBlockData(block)}>
              查看数据
            </DropdownItem>
            <DropdownItem icon="icon-import" onClick={() => methods.importBlockData(block)}>
              导入数据
            </DropdownItem>
          </>
        ),
      });
    },
  };
  const buttons: {
    label: string | (() => string);
    icon: string | (() => string);
    tip?: string | (() => string);
    handler: () => void;
  }[] = [
    { label: '撤销', icon: 'icon-back', handler: commander.undo, tip: 'ctrl+z' },
    { label: '重做', icon: 'icon-forward', handler: commander.redo, tip: 'ctrl+y, ctrl+shift+z' },
    {
      label: () => (preview ? '预览模式' : '编辑模式'),
      icon: () => (preview ? 'icon-edit' : 'icon-browse'),
      handler: () => {
        if (!preview) {
          methods.clearFocus();
        }
        setPreview(!preview);
      },
    },
    {
      label: () => (menuVisible ? '关闭菜单' : '打开菜单'),
      icon: () => (preview ? 'icon-edit' : 'icon-browse'),
      handler: () => {
        setMenuVisible(!menuVisible);
      },
    },
    {
      label: '选择模板',
      icon: 'icon-import',
      handler: async () => {
        const childApen = document.createElement('div');
        const list = getLocalStorage(TEMPLATE_KEY);
        ReactDom.render(<ListMode list={list} />, childApen);
      },
    },
    {
      label: '导入',
      icon: 'icon-import',
      handler: async () => {
        const text = await $$dialog.textarea('', { title: '请输入导入的JSON字符串' });
        try {
          const data = JSON.parse(text || '');
          commander.updateValue(data);
        } catch (e) {
          console.error(e);
          notification.open({
            message: '导入失败！',
            description: '导入的数据格式不正常，请检查！',
          });
        }
      },
    },
    {
      label: '保存',
      icon: 'icon-export',
      handler: () => {
        const childApen = document.createElement('div');
        const list = getLocalStorage(TEMPLATE_KEY);
        ReactDom.render(<ListMode list={list} isSave={true} />, childApen);
      },
    },
    { label: '置顶', icon: 'icon-place-top', handler: () => commander.placeTop(), tip: 'ctrl+up' },
    {
      label: '置底',
      icon: 'icon-place-bottom',
      handler: () => commander.placeBottom(),
      tip: 'ctrl+down',
    },
    {
      label: '删除',
      icon: 'icon-delete',
      handler: commander.delete,
      tip: 'ctrl+d, backspace, delete',
    },
    { label: '清空', icon: 'icon-reset', handler: commander.clear },
    {
      label: () => (operatorVisible ? '关闭属性栏' : '展开属性栏'),
      icon: 'icon-close',
      handler: () => {
        setOperatorVisible(!operatorVisible);
      },
    },
  ];
  /**
   *
   * @returns 分类菜单栏组件
   */
  const previewElement = () => {
    const dataArr: any = [];
    visualConfig.componentArray.map((mapItem) => {
      if (dataArr.length == 0) {
        dataArr.push({ type: mapItem.type, List: [mapItem] });
      } else {
        let res = dataArr.some((item: any) => {
          if (item.type === mapItem.type) {
            item.List.push(mapItem);
            return true;
          }
        });
        if (!res) {
          //如果没找相同的类型的组添加一个新对象
          dataArr.push({ type: mapItem.type, List: [mapItem] });
        }
      }
    });
    return dataArr;
  };
  return (
    <div className={classes} style={containerStyles}>
      <Drawer
        placement={PlacementInfo.left}
        onClose={() => {
          setMenuVisible(false);
        }}
        visible={menuVisible}
      >
        <div className={styles.reactVisualEditorMenu}>
          <Collapse accordion ghost={true}>
            {previewElement().map((item: any, index: any) => {
              return (
                <Panel
                  header={<div style={{ color: '#fff', fontSize: '20px' }}>{item.type}</div>}
                  key={index}
                >
                  {item.List.map((component: any, index1: any) => {
                    return (
                      <div
                        className={styles.reactVisualEditorMenuItem}
                        key={index + index1}
                        draggable
                        onDragStart={(e) => menuDraggier.dragstart(e, component)}
                        onDragEnd={menuDraggier.dragend}
                      >
                        <div className={styles.reactVisualEditorMenuItemName}>{component.name}</div>
                        {component.preview()}
                      </div>
                    );
                  })}
                </Panel>
              );
            })}
          </Collapse>
        </div>
      </Drawer>
      <div className={styles.reactVisualEditorHead}>
        {buttons.map((btn, index) => {
          const label = typeof btn.label === 'function' ? btn.label() : btn.label;
          const icon = typeof btn.icon === 'function' ? btn.icon() : btn.icon;
          return (
            <div className={styles.reactVisualEditorHeadBtn} key={index} onClick={btn.handler}>
              <i className={`iconfont ${icon}`} />
              <span>{label}</span>
            </div>
          );
        })}
      </div>
      <Drawer
        placement={PlacementInfo.right}
        onClose={() => {
          setOperatorVisible(false);
        }}
        visible={operatorVisible}
      >
        <ReactVisualOperator
          selectBlock={selectBlock}
          value={editorValue}
          updateValue={commander.updateValue}
          updateBlock={commander.updateBlock}
          config={visualConfig}
        />
      </Drawer>
      <div className={styles.reactVisualEditorBody} ref={bodyRef}>
        <div
          className={styles.reactVisualEditorContainer}
          ref={containerRef}
          style={containerStyles}
          onMouseDown={focusHandler.container}
        >
          {editorValue.blocks.map((block, index) => (
            <ReactVisualBlock
              key={index}
              block={block}
              config={visualConfig}
              onMouseDown={(e) => focusHandler.block(e, block, index)}
              onContextMenu={(e) => handler.onContextMenuBlock(e, block)}
              click={(pro:any)=>{
                preview&&pro&&pro['jumpUrl']&&
                getData(pro['jumpUrl']).then((res)=>{
                    if(res){
                        setEditorValue({...res})
                    }
                })
              }}
            >
              {block.focus &&
                !!visualConfig.componentMap[block.componentKey] &&
                !!visualConfig.componentMap[block.componentKey].resize &&
                (visualConfig.componentMap[block.componentKey].resize!.width ||
                  visualConfig.componentMap[block.componentKey].resize!.height) && (
                  <ReactVisualBlockResize
                    component={visualConfig.componentMap[block.componentKey]}
                    onMouseDown={(e, direction) => resizeDraggier.mousedown(e, direction, block)}
                  />
                )}
            </ReactVisualBlock>
          ))}

          {blockDraggier.mark.x != null && (
            <div
              className={styles.reactVisualEditorMarkX}
              style={{ left: `${blockDraggier.mark.x}px` }}
            />
          )}
          {blockDraggier.mark.y != null && (
            <div
              className={styles.reactVisualEditorMarkY}
              style={{ top: `${blockDraggier.mark.y}px` }}
            />
          )}
        </div>
      </div>
    </div>
  );
};
