amis-editor+React

983 阅读2分钟

amis-editor+React 18

react.js - react集成amis(低代码)保姆级教程 - 个人文章 - SegmentFault 思否

可视化编辑器 (baidu.com)

这次又接手一个掉头发的需求,在react项目中实现低代码表单可视化编辑,最终在领导“高明(没钱买)”的调研下,选择了百度的开源amis产品,至于为啥用react,这是甲方的爹要求的,非我等喽啰可以决定

起步

  • 项目是搭建好了架子交给我的,在之前项目已经实现了基础的后台管理系统该有的功能,我拿着一脸懵,因为之前一段时间一直开发的项目都是vue2或vue3,并且该项目使用vite作为编译工具
  • 从项目熟悉开始,打开package.json看里面的依赖,然后看路由,看axios封装文件,慢慢熟悉项目

安装amis-editor

  • 目标明确,跳过amis,直接弄amis-editor,打开文档不知道是我自己蠢逼的原因还是文档过于简单,安装完依赖后,按文档操作全是报错
  • 其实这里完全按照文档操作会有问题

image.png

第一个坑

  • 如果你只是安装了amis-editor,你会发现你根本无法打开,你还必须看文档的“快速开始”章节,安装mox等一系列依赖,但是文档中好像并未在明显地方提及

第二个坑

  • 光是npm i mox ...还是不行,因为amis兼容mox的版本在4.x.x,如果版本高了依旧会报错,所以记录好版本
npm install mobx@4.15.7 mobx-react@6.3.1 mobx-state-tree@3.17.3 --legacy-peer-deps
  • 这样安装完应该是正确的版本

第三个坑

  • 样式问题:我的解决方式是把官方demo的代码拉到本地,把它所有的样式文件全部拷贝到我的项目中
  • 但是还是无法避免的有问题,比如高度没有限制,导致整个页面变得很长,不符合需求
.Editor-Demo{
    .Editor-inner {
		position: relative;
		flex: 1 1 auto;
		overflow-x: hidden;
		overflow-y: auto;
		.ae-Editor {
			height: 100%;
		}
	}
}
  • 找了许久,发现是内部容器没有限制,所以限制一下

目前

  • 到目前为止,项目能正常操作,但是控制台还有很多很多报错,所以会有后续内容
  • 目前代码
import { Card, message } from "antd";
import { Editor, ShortcutKey } from "amis-editor";
import { useState, useEffect } from "react";
import { useSearchParams, useNavigate } from "react-router-dom";
import { useAliveController } from "react-activation";

export default function TestAmis() {
	const [messageApi, contextHolder] = message.useMessage();
	const [preview, setPreview] = useState(true);
	const [searchParams] = useSearchParams();
	const navigate = useNavigate();
	const { dropScope } = useAliveController();
	const [initialSchema, setInitialSchema] = useState({
		type: "page",
		title: "新增表单",
		body: []
	});

	const id = searchParams.get("id");
        
	useEffect(() => {
		id && getDetail();
	}, [id]);

	const getDetail = async () => {
		const { data } = await getObj(id!);
		setInitialSchema(JSON.parse(data.formValue));
	};

	const onChange = (value: any) => {
		setInitialSchema(value);
	};

	const onSubmit = async () => {
		const params = {
			id,
			formName: initialSchema.title,
			formValue: JSON.stringify(initialSchema)
		};

		id ? await editObj(params) : await addObj(params);
		messageApi.open({
			type: "success",
			content: `${id ? "修改" : "新增"}成功`,
			duration: 2,
			onClose: async () => {
				let url = `/teamWork/formManage`;
				await dropScope("formManage");
				navigate(url);
			}
		});
	};
	return (
		<>
			{contextHolder}
			<Card>
				{/* <h1>AMIS 编辑器</h1> */}
				<div className="Editor-Demo">
					<div className="Editor-header">
						<div className="Editor-title">amis 可视化编辑器</div>

						<div className="Editor-view-mode-group-container">
							<div className="Editor-view-mode-group">
								<div className={`Editor-view-mode-btn editor-header-icon is-active`}>
									{/* <Icon icon="pc-preview" title="PC模式" /> */}
									pc模式
								</div>
								<div className={`Editor-view-mode-btn editor-header-icon`}>
									{/* <Icon icon="h5-preview" title="移动模式" /> */}
									移动模式
								</div>
							</div>
						</div>

						<div className="Editor-header-actions">
							<ShortcutKey />
							<div
								className={`header-action-btn m-1 ${preview ? "primary" : ""}`}
								onClick={() => {
									setPreview(!preview);
								}}
							>
								{preview ? "编辑" : "预览"}
							</div>
							<div className={`header-action-btn exit-btn`} onClick={onSubmit}>
								保存
							</div>
						</div>
					</div>
					<div className="Editor-inner">
						<Editor value={initialSchema} onChange={onChange} />
					</div>
				</div>
			</Card>
		</>
	);
}