src/framework/M3.tsx (79 lines of code) (raw):

import React, { useState, useEffect } from 'react'; import { M3Prop, MViewer } from './MViewer'; import { MViewerDebug } from './MViewerDebug'; import editorMap from './editorMap'; import { MFieldSchema, M3UISpec, MFieldSchemaAnonymity } from "../../src/framework/Schema"; import _ from "lodash"; // 外部 schema 转化为内部 function deal(fieldSchema: MFieldSchemaAnonymity | MFieldSchema) { if(fieldSchema.arrayMember){ deal(fieldSchema.arrayMember); } else if(fieldSchema.objectFields){ for(let f of fieldSchema.objectFields){ deal(f); } } else { let opt = fieldSchema.option ?? fieldSchema.setFields ?? fieldSchema.enumFields if (opt) { if (typeof opt === 'string') { fieldSchema.option = opt.split(" ").map( aEnum => { const kv = aEnum.split("="); return { label: kv[0], value: kv[1] ?? kv[0] }; } ); } else { fieldSchema.option = opt } } fieldSchema.openOption = fieldSchema.openOption ?? fieldSchema.setOpen ?? fieldSchema.enumOpen if (!fieldSchema.type && fieldSchema.editor) { Object.assign(fieldSchema, editorMap[fieldSchema.editor]) } } } // 标准化 schema function standardSchema(schema: MFieldSchema | MFieldSchema[], layout?: M3UISpec) { const _schema = _.cloneDeep(schema) if (_.isArray(_schema)) { _schema.forEach(item => { deal(item) }) const temp: MFieldSchema = { name: '__root__', type: 'object', objectFields: _schema } if (layout) { temp.uispec = layout } return _.cloneDeep(temp) } else { deal(_schema) return _schema } } const M3 = (props: React.PropsWithChildren<M3Prop & { debug?: boolean }>) => { const [prevProp, setPrevProp] = useState(props); let [database, setDatabase] = useState(_.cloneDeep(props.database)) let [schema, setSchema] = useState(standardSchema(props.schema)) let [k, setK] = useState(0) // debug 属性为真 且 页面地址携带 debug 参数,开启调试模式 let debug = props.debug || (window.location.search.indexOf("debug") >= 0 || window.location.hash.indexOf("debug") >= 0); useEffect(() => { if(props.schema != prevProp.schema) { setSchema(standardSchema(props.schema)) setPrevProp(props); setK(++k) } }, [props.schema]) useEffect(() => { if(props.database != prevProp.database) { setDatabase(_.cloneDeep(props.database)) setPrevProp(props); setK(++k) } }, [props.database]) return ( debug ? <MViewerDebug key={k} {...props} database={database} schema={schema} /> : <MViewer key={k} {...props} database={database} schema={schema} /> ); } export default M3;