mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2026-01-24 18:58:11 +00:00
Merge branch 'v/0.8.0' into polyfill/vision
This commit is contained in:
commit
9950e12006
@ -7,8 +7,7 @@
|
|||||||
"lib"
|
"lib"
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"compile": "rimraf lib && tsc",
|
"build": "rimraf lib && tsc",
|
||||||
"build": "rimraf lib && webpack",
|
|
||||||
"demo": "ts-node -r tsconfig-paths/register ./src/demo/main.ts",
|
"demo": "ts-node -r tsconfig-paths/register ./src/demo/main.ts",
|
||||||
"test": "ava"
|
"test": "ava"
|
||||||
},
|
},
|
||||||
@ -24,11 +23,7 @@
|
|||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
"ts-loader": "^6.2.2",
|
"ts-loader": "^6.2.2",
|
||||||
"ts-node": "^7.0.1",
|
"ts-node": "^7.0.1",
|
||||||
"tsconfig-paths": "^3.9.0",
|
"tsconfig-paths": "^3.9.0"
|
||||||
"tsconfig-paths-webpack-plugin": "^3.2.0",
|
|
||||||
"webpack": "^4.42.1",
|
|
||||||
"webpack-cli": "^3.3.11",
|
|
||||||
"webpack-node-externals": "^1.7.2"
|
|
||||||
},
|
},
|
||||||
"ava": {
|
"ava": {
|
||||||
"compileEnhancements": false,
|
"compileEnhancements": false,
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { IResultDir, IResultFile } from '@/types';
|
import { IResultDir, IResultFile } from '../types';
|
||||||
|
|
||||||
import CodeGenerator from '@/index';
|
import CodeGenerator from '../index';
|
||||||
import { createDiskPublisher } from '@/publisher/disk';
|
import { createDiskPublisher } from '../publisher/disk';
|
||||||
import demoSchema from './simpleDemo';
|
import demoSchema from './simpleDemo';
|
||||||
|
|
||||||
function flatFiles(rootName: string | null, dir: IResultDir): IResultFile[] {
|
function flatFiles(rootName: string | null, dir: IResultDir): IResultFile[] {
|
||||||
|
|||||||
@ -1,9 +1,4 @@
|
|||||||
import { IProjectSchema } from '@/types';
|
import { IProjectSchema } from '../types';
|
||||||
|
|
||||||
// meta: {
|
|
||||||
// title: '测试',
|
|
||||||
// router: '/',
|
|
||||||
// },
|
|
||||||
|
|
||||||
const demoData: IProjectSchema = {
|
const demoData: IProjectSchema = {
|
||||||
version: '1.0.0',
|
version: '1.0.0',
|
||||||
|
|||||||
@ -11,10 +11,10 @@ import {
|
|||||||
PostProcessor,
|
PostProcessor,
|
||||||
} from '../types';
|
} from '../types';
|
||||||
|
|
||||||
import ResultDir from '@/model/ResultDir';
|
import ResultDir from '../model/ResultDir';
|
||||||
import SchemaParser from '@/parser/SchemaParser';
|
import SchemaParser from '../parser/SchemaParser';
|
||||||
|
|
||||||
import { createModuleBuilder } from '@/generator/ModuleBuilder';
|
import { createModuleBuilder } from '../generator/ModuleBuilder';
|
||||||
|
|
||||||
interface IModuleInfo {
|
interface IModuleInfo {
|
||||||
moduleName?: string;
|
moduleName?: string;
|
||||||
@ -67,7 +67,7 @@ export class ProjectBuilder implements IProjectBuilder {
|
|||||||
// Parse / Format
|
// Parse / Format
|
||||||
|
|
||||||
// Preprocess
|
// Preprocess
|
||||||
// Colllect Deps
|
// Collect Deps
|
||||||
// Parse JSExpression
|
// Parse JSExpression
|
||||||
const parseResult: IParseResult = schemaParser.parse(schema);
|
const parseResult: IParseResult = schemaParser.parse(schema);
|
||||||
let buildResult: IModuleInfo[] = [];
|
let buildResult: IModuleInfo[] = [];
|
||||||
|
|||||||
@ -2,9 +2,9 @@
|
|||||||
* 低代码引擎的出码模块,负责将编排产出的 Schema 转换成实际可执行的代码。
|
* 低代码引擎的出码模块,负责将编排产出的 Schema 转换成实际可执行的代码。
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
import { createProjectBuilder } from '@/generator/ProjectBuilder';
|
import { createProjectBuilder } from './generator/ProjectBuilder';
|
||||||
import { createDiskPublisher } from '@/publisher/disk';
|
import { createDiskPublisher } from './publisher/disk';
|
||||||
import createIceJsProjectBuilder from '@/solutions/icejs';
|
import createIceJsProjectBuilder from './solutions/icejs';
|
||||||
|
|
||||||
export * from './types';
|
export * from './types';
|
||||||
|
|
||||||
|
|||||||
@ -6,10 +6,8 @@
|
|||||||
import { SUPPORT_SCHEMA_VERSION_LIST } from '../const';
|
import { SUPPORT_SCHEMA_VERSION_LIST } from '../const';
|
||||||
|
|
||||||
import { handleChildren } from '../utils/children';
|
import { handleChildren } from '../utils/children';
|
||||||
import { uniqueArray } from '../utils/common';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ChildNodeItem,
|
|
||||||
ChildNodeType,
|
ChildNodeType,
|
||||||
CodeGeneratorError,
|
CodeGeneratorError,
|
||||||
CompatibilityError,
|
CompatibilityError,
|
||||||
@ -86,7 +84,7 @@ class SchemaParser implements ISchemaParser {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new CodeGeneratorError(`Can't find anything to generator.`);
|
throw new CodeGeneratorError(`Can't find anything to generate.`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 建立所有容器的内部依赖索引
|
// 建立所有容器的内部依赖索引
|
||||||
|
|||||||
@ -5,7 +5,6 @@ import {
|
|||||||
ChunkType,
|
ChunkType,
|
||||||
FileType,
|
FileType,
|
||||||
ICodeStruct,
|
ICodeStruct,
|
||||||
IContainerInfo,
|
|
||||||
} from '../../../types';
|
} from '../../../types';
|
||||||
|
|
||||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import {
|
|||||||
IJSExpression,
|
IJSExpression,
|
||||||
} from '../../../types';
|
} from '../../../types';
|
||||||
|
|
||||||
import { handleChildren } from '@/utils/children';
|
import { handleChildren } from '../../../utils/children';
|
||||||
import { generateCompositeType } from '../../utils/compositeType';
|
import { generateCompositeType } from '../../utils/compositeType';
|
||||||
import { REACT_CHUNK_NAME } from './const';
|
import { REACT_CHUNK_NAME } from './const';
|
||||||
|
|
||||||
|
|||||||
@ -1,12 +1,12 @@
|
|||||||
import { COMMON_CHUNK_NAME } from '@/const/generator';
|
import { COMMON_CHUNK_NAME } from '../../const/generator';
|
||||||
import { generateCompositeType } from '@/plugins/utils/compositeType';
|
import { generateCompositeType } from '../../plugins/utils/compositeType';
|
||||||
import {
|
import {
|
||||||
BuilderComponentPlugin,
|
BuilderComponentPlugin,
|
||||||
ChunkType,
|
ChunkType,
|
||||||
FileType,
|
FileType,
|
||||||
ICodeStruct,
|
ICodeStruct,
|
||||||
IProjectInfo,
|
IProjectInfo,
|
||||||
} from '@/types';
|
} from '../../types';
|
||||||
|
|
||||||
// TODO: How to merge this logic to common deps
|
// TODO: How to merge this logic to common deps
|
||||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { COMMON_CHUNK_NAME } from '@/const/generator';
|
import { COMMON_CHUNK_NAME } from '../../../../../const/generator';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
BuilderComponentPlugin,
|
BuilderComponentPlugin,
|
||||||
@ -6,7 +6,7 @@ import {
|
|||||||
FileType,
|
FileType,
|
||||||
ICodeStruct,
|
ICodeStruct,
|
||||||
IProjectInfo,
|
IProjectInfo,
|
||||||
} from '@/types';
|
} from '../../../../../types';
|
||||||
|
|
||||||
// TODO: How to merge this logic to common deps
|
// TODO: How to merge this logic to common deps
|
||||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { COMMON_CHUNK_NAME } from '@/const/generator';
|
import { COMMON_CHUNK_NAME } from '../../../../../const/generator';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
BuilderComponentPlugin,
|
BuilderComponentPlugin,
|
||||||
@ -6,7 +6,7 @@ import {
|
|||||||
FileType,
|
FileType,
|
||||||
ICodeStruct,
|
ICodeStruct,
|
||||||
IProjectInfo,
|
IProjectInfo,
|
||||||
} from '@/types';
|
} from '../../../../../types';
|
||||||
|
|
||||||
// TODO: How to merge this logic to common deps
|
// TODO: How to merge this logic to common deps
|
||||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { COMMON_CHUNK_NAME } from '@/const/generator';
|
import { COMMON_CHUNK_NAME } from '../../../../../const/generator';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
BuilderComponentPlugin,
|
BuilderComponentPlugin,
|
||||||
@ -6,7 +6,7 @@ import {
|
|||||||
FileType,
|
FileType,
|
||||||
ICodeStruct,
|
ICodeStruct,
|
||||||
IProjectInfo,
|
IProjectInfo,
|
||||||
} from '@/types';
|
} from '../../../../../types';
|
||||||
|
|
||||||
// TODO: How to merge this logic to common deps
|
// TODO: How to merge this logic to common deps
|
||||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { COMMON_CHUNK_NAME } from '@/const/generator';
|
import { COMMON_CHUNK_NAME } from '../../../../../const/generator';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
BuilderComponentPlugin,
|
BuilderComponentPlugin,
|
||||||
@ -7,7 +7,7 @@ import {
|
|||||||
ICodeStruct,
|
ICodeStruct,
|
||||||
IPackageJSON,
|
IPackageJSON,
|
||||||
IProjectInfo,
|
IProjectInfo,
|
||||||
} from '@/types';
|
} from '../../../../../types';
|
||||||
|
|
||||||
interface IIceJsPackageJSON extends IPackageJSON {
|
interface IIceJsPackageJSON extends IPackageJSON {
|
||||||
ideMode: {
|
ideMode: {
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { COMMON_CHUNK_NAME } from '@/const/generator';
|
import { COMMON_CHUNK_NAME } from '../../../../../const/generator';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
BuilderComponentPlugin,
|
BuilderComponentPlugin,
|
||||||
@ -6,7 +6,7 @@ import {
|
|||||||
FileType,
|
FileType,
|
||||||
ICodeStruct,
|
ICodeStruct,
|
||||||
IRouterInfo,
|
IRouterInfo,
|
||||||
} from '@/types';
|
} from '../../../../../types';
|
||||||
|
|
||||||
// TODO: How to merge this logic to common deps
|
// TODO: How to merge this logic to common deps
|
||||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import ResultFile from '@/model/ResultFile';
|
import ResultFile from '../../../../../../model/ResultFile';
|
||||||
import { IResultFile } from '@/types';
|
import { IResultFile } from '../../../../../../types';
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
export default function getFile(): [string[], IResultFile] {
|
||||||
const file = new ResultFile(
|
const file = new ResultFile(
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import ResultFile from '@/model/ResultFile';
|
import ResultFile from '../../../../../../model/ResultFile';
|
||||||
import { IResultFile } from '@/types';
|
import { IResultFile } from '../../../../../../types';
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
export default function getFile(): [string[], IResultFile] {
|
||||||
const file = new ResultFile(
|
const file = new ResultFile(
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import ResultFile from '@/model/ResultFile';
|
import ResultFile from '../../../../../../model/ResultFile';
|
||||||
import { IResultFile } from '@/types';
|
import { IResultFile } from '../../../../../../types';
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
export default function getFile(): [string[], IResultFile] {
|
||||||
const file = new ResultFile(
|
const file = new ResultFile(
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import ResultFile from '@/model/ResultFile';
|
import ResultFile from '../../../../../../model/ResultFile';
|
||||||
import { IResultFile } from '@/types';
|
import { IResultFile } from '../../../../../../types';
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
export default function getFile(): [string[], IResultFile] {
|
||||||
const file = new ResultFile(
|
const file = new ResultFile(
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import ResultFile from '@/model/ResultFile';
|
import ResultFile from '../../../../../../model/ResultFile';
|
||||||
import { IResultFile } from '@/types';
|
import { IResultFile } from '../../../../../../types';
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
export default function getFile(): [string[], IResultFile] {
|
||||||
const file = new ResultFile(
|
const file = new ResultFile(
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import ResultFile from '@/model/ResultFile';
|
import ResultFile from '../../../../../../model/ResultFile';
|
||||||
import { IResultFile } from '@/types';
|
import { IResultFile } from '../../../../../../types';
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
export default function getFile(): [string[], IResultFile] {
|
||||||
const file = new ResultFile(
|
const file = new ResultFile(
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import ResultFile from '@/model/ResultFile';
|
import ResultFile from '../../../../../../model/ResultFile';
|
||||||
import { IResultFile } from '@/types';
|
import { IResultFile } from '../../../../../../types';
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
export default function getFile(): [string[], IResultFile] {
|
||||||
const file = new ResultFile(
|
const file = new ResultFile(
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import ResultFile from '@/model/ResultFile';
|
import ResultFile from '../../../../../../model/ResultFile';
|
||||||
import { IResultFile } from '@/types';
|
import { IResultFile } from '../../../../../../types';
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
export default function getFile(): [string[], IResultFile] {
|
||||||
const file = new ResultFile(
|
const file = new ResultFile(
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import ResultFile from '@/model/ResultFile';
|
import ResultFile from '../../../../../../model/ResultFile';
|
||||||
import { IResultFile } from '@/types';
|
import { IResultFile } from '../../../../../../types';
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
export default function getFile(): [string[], IResultFile] {
|
||||||
const file = new ResultFile(
|
const file = new ResultFile(
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import ResultFile from '@/model/ResultFile';
|
import ResultFile from '../../../../../../model/ResultFile';
|
||||||
import { IResultFile } from '@/types';
|
import { IResultFile } from '../../../../../../types';
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
export default function getFile(): [string[], IResultFile] {
|
||||||
const file = new ResultFile(
|
const file = new ResultFile(
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import ResultFile from '@/model/ResultFile';
|
import ResultFile from '../../../../../../../../../../../model/ResultFile';
|
||||||
import { IResultFile } from '@/types';
|
import { IResultFile } from '../../../../../../../../../../../types';
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
export default function getFile(): [string[], IResultFile] {
|
||||||
const file = new ResultFile(
|
const file = new ResultFile(
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import ResultFile from '@/model/ResultFile';
|
import ResultFile from '../../../../../../../../../../../model/ResultFile';
|
||||||
import { IResultFile } from '@/types';
|
import { IResultFile } from '../../../../../../../../../../../types';
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
export default function getFile(): [string[], IResultFile] {
|
||||||
const file = new ResultFile(
|
const file = new ResultFile(
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import ResultFile from '@/model/ResultFile';
|
import ResultFile from '../../../../../../../../../../../model/ResultFile';
|
||||||
import { IResultFile } from '@/types';
|
import { IResultFile } from '../../../../../../../../../../../types';
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
export default function getFile(): [string[], IResultFile] {
|
||||||
const file = new ResultFile(
|
const file = new ResultFile(
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import ResultFile from '@/model/ResultFile';
|
import ResultFile from '../../../../../../../../../../../model/ResultFile';
|
||||||
import { IResultFile } from '@/types';
|
import { IResultFile } from '../../../../../../../../../../../types';
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
export default function getFile(): [string[], IResultFile] {
|
||||||
const file = new ResultFile(
|
const file = new ResultFile(
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import ResultFile from '@/model/ResultFile';
|
import ResultFile from '../../../../../../../../../../../model/ResultFile';
|
||||||
import { IResultFile } from '@/types';
|
import { IResultFile } from '../../../../../../../../../../../types';
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
export default function getFile(): [string[], IResultFile] {
|
||||||
const file = new ResultFile(
|
const file = new ResultFile(
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import ResultFile from '@/model/ResultFile';
|
import ResultFile from '../../../../../../../../../model/ResultFile';
|
||||||
import { IResultFile } from '@/types';
|
import { IResultFile } from '../../../../../../../../../types';
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
export default function getFile(): [string[], IResultFile] {
|
||||||
const file = new ResultFile(
|
const file = new ResultFile(
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import ResultFile from '@/model/ResultFile';
|
import ResultFile from '../../../../../../../../../model/ResultFile';
|
||||||
import { IResultFile } from '@/types';
|
import { IResultFile } from '../../../../../../../../../types';
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
export default function getFile(): [string[], IResultFile] {
|
||||||
const file = new ResultFile(
|
const file = new ResultFile(
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import ResultFile from '@/model/ResultFile';
|
import ResultFile from '../../../../../../model/ResultFile';
|
||||||
import { IResultFile } from '@/types';
|
import { IResultFile } from '../../../../../../types';
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
export default function getFile(): [string[], IResultFile] {
|
||||||
const file = new ResultFile(
|
const file = new ResultFile(
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import ResultFile from '@/model/ResultFile';
|
import ResultFile from '../../../../../../model/ResultFile';
|
||||||
import { IResultFile } from '@/types';
|
import { IResultFile } from '../../../../../../types';
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
export default function getFile(): [string[], IResultFile] {
|
||||||
const file = new ResultFile(
|
const file = new ResultFile(
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import ResultFile from '@/model/ResultFile';
|
import ResultFile from '../../../../../../model/ResultFile';
|
||||||
import { IResultFile } from '@/types';
|
import { IResultFile } from '../../../../../../types';
|
||||||
|
|
||||||
export default function getFile(): [string[], IResultFile] {
|
export default function getFile(): [string[], IResultFile] {
|
||||||
const file = new ResultFile(
|
const file = new ResultFile(
|
||||||
|
|||||||
@ -1,5 +1,9 @@
|
|||||||
import ResultDir from '@/model/ResultDir';
|
import ResultDir from '../../../../../model/ResultDir';
|
||||||
import { IProjectTemplate, IResultDir, IResultFile } from '@/types';
|
import {
|
||||||
|
IProjectTemplate,
|
||||||
|
IResultDir,
|
||||||
|
IResultFile,
|
||||||
|
} from '../../../../../types';
|
||||||
|
|
||||||
import file12 from './files/abc.json';
|
import file12 from './files/abc.json';
|
||||||
import file11 from './files/build.json';
|
import file11 from './files/build.json';
|
||||||
|
|||||||
@ -1,12 +1,12 @@
|
|||||||
import { COMMON_CHUNK_NAME } from '@/const/generator';
|
import { COMMON_CHUNK_NAME } from '../../const/generator';
|
||||||
import { generateCompositeType } from '@/plugins/utils/compositeType';
|
import { generateCompositeType } from '../../plugins/utils/compositeType';
|
||||||
import {
|
import {
|
||||||
BuilderComponentPlugin,
|
BuilderComponentPlugin,
|
||||||
ChunkType,
|
ChunkType,
|
||||||
FileType,
|
FileType,
|
||||||
ICodeStruct,
|
ICodeStruct,
|
||||||
IProjectInfo,
|
IProjectInfo,
|
||||||
} from '@/types';
|
} from '../../types';
|
||||||
|
|
||||||
// TODO: How to merge this logic to common deps
|
// TODO: How to merge this logic to common deps
|
||||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||||
|
|||||||
@ -1,13 +1,12 @@
|
|||||||
import { COMMON_CHUNK_NAME } from '@/const/generator';
|
import { COMMON_CHUNK_NAME } from '../../const/generator';
|
||||||
import { generateCompositeType } from '@/plugins/utils/compositeType';
|
|
||||||
// import { } from '@/plugins/utils/jsExpression';
|
|
||||||
import {
|
import {
|
||||||
BuilderComponentPlugin,
|
BuilderComponentPlugin,
|
||||||
ChunkType,
|
ChunkType,
|
||||||
FileType,
|
FileType,
|
||||||
ICodeStruct,
|
ICodeStruct,
|
||||||
IUtilInfo,
|
IUtilInfo,
|
||||||
} from '@/types';
|
} from '../../types';
|
||||||
|
|
||||||
// TODO: How to merge this logic to common deps
|
// TODO: How to merge this logic to common deps
|
||||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { CompositeArray, CompositeValue, ICompositeObject } from '@/types';
|
import { CompositeArray, CompositeValue, ICompositeObject } from '../../types';
|
||||||
import { generateValue, isJsExpression } from './jsExpression';
|
import { generateValue, isJsExpression } from './jsExpression';
|
||||||
|
|
||||||
function generateArray(value: CompositeArray): string {
|
function generateArray(value: CompositeArray): string {
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import prettier from 'prettier';
|
import prettier from 'prettier';
|
||||||
|
|
||||||
import { PostProcessor } from '@/types';
|
import { PostProcessor } from '../../types';
|
||||||
|
|
||||||
const PARSERS = ['css', 'scss', 'less', 'json', 'html', 'vue'];
|
const PARSERS = ['css', 'scss', 'less', 'json', 'html', 'vue'];
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { CodeGeneratorError, IResultDir } from '@/types';
|
import { CodeGeneratorError, IResultDir } from '../../types';
|
||||||
|
|
||||||
export type PublisherFactory<T, U> = (configuration?: Partial<T>) => U;
|
export type PublisherFactory<T, U> = (configuration?: Partial<T>) => U;
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { existsSync, mkdir, writeFile } from 'fs';
|
import { existsSync, mkdir, writeFile } from 'fs';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
|
|
||||||
import { IResultDir, IResultFile } from '@/types';
|
import { IResultDir, IResultFile } from '../../types';
|
||||||
|
|
||||||
export const writeFolder = async (
|
export const writeFolder = async (
|
||||||
folder: IResultDir,
|
folder: IResultDir,
|
||||||
|
|||||||
@ -1,27 +1,27 @@
|
|||||||
import { IProjectBuilder } from '@/types';
|
import { IProjectBuilder } from '../types';
|
||||||
|
|
||||||
import { createProjectBuilder } from '@/generator/ProjectBuilder';
|
import { createProjectBuilder } from '../generator/ProjectBuilder';
|
||||||
|
|
||||||
import esmodule from '@/plugins/common/esmodule';
|
import esmodule from '../plugins/common/esmodule';
|
||||||
import containerClass from '@/plugins/component/react/containerClass';
|
import containerClass from '../plugins/component/react/containerClass';
|
||||||
import containerInitState from '@/plugins/component/react/containerInitState';
|
import containerInitState from '../plugins/component/react/containerInitState';
|
||||||
// import containerInjectUtils from '@/plugins/component/react/containerInjectUtils';
|
import containerInjectUtils from '../plugins/component/react/containerInjectUtils';
|
||||||
import containerLifeCycle from '@/plugins/component/react/containerLifeCycle';
|
import containerLifeCycle from '../plugins/component/react/containerLifeCycle';
|
||||||
import containerMethod from '@/plugins/component/react/containerMethod';
|
import containerMethod from '../plugins/component/react/containerMethod';
|
||||||
import jsx from '@/plugins/component/react/jsx';
|
import jsx from '../plugins/component/react/jsx';
|
||||||
import reactCommonDeps from '@/plugins/component/react/reactCommonDeps';
|
import reactCommonDeps from '../plugins/component/react/reactCommonDeps';
|
||||||
import css from '@/plugins/component/style/css';
|
import css from '../plugins/component/style/css';
|
||||||
import constants from '@/plugins/project/constants';
|
import constants from '../plugins/project/constants';
|
||||||
import iceJsEntry from '@/plugins/project/framework/icejs/plugins/entry';
|
import iceJsEntry from '../plugins/project/framework/icejs/plugins/entry';
|
||||||
import iceJsEntryHtml from '@/plugins/project/framework/icejs/plugins/entryHtml';
|
import iceJsEntryHtml from '../plugins/project/framework/icejs/plugins/entryHtml';
|
||||||
import iceJsGlobalStyle from '@/plugins/project/framework/icejs/plugins/globalStyle';
|
import iceJsGlobalStyle from '../plugins/project/framework/icejs/plugins/globalStyle';
|
||||||
import iceJsPackageJSON from '@/plugins/project/framework/icejs/plugins/packageJSON';
|
import iceJsPackageJSON from '../plugins/project/framework/icejs/plugins/packageJSON';
|
||||||
import iceJsRouter from '@/plugins/project/framework/icejs/plugins/router';
|
import iceJsRouter from '../plugins/project/framework/icejs/plugins/router';
|
||||||
import template from '@/plugins/project/framework/icejs/template';
|
import template from '../plugins/project/framework/icejs/template';
|
||||||
import i18n from '@/plugins/project/i18n';
|
import i18n from '../plugins/project/i18n';
|
||||||
import utils from '@/plugins/project/utils';
|
import utils from '../plugins/project/utils';
|
||||||
|
|
||||||
import { prettier } from '@/postprocessor';
|
import { prettier } from '../postprocessor';
|
||||||
|
|
||||||
export default function createIceJsProjectBuilder(): IProjectBuilder {
|
export default function createIceJsProjectBuilder(): IProjectBuilder {
|
||||||
return createProjectBuilder({
|
return createProjectBuilder({
|
||||||
@ -31,7 +31,7 @@ export default function createIceJsProjectBuilder(): IProjectBuilder {
|
|||||||
reactCommonDeps,
|
reactCommonDeps,
|
||||||
esmodule,
|
esmodule,
|
||||||
containerClass,
|
containerClass,
|
||||||
// containerInjectUtils,
|
containerInjectUtils,
|
||||||
containerInitState,
|
containerInitState,
|
||||||
containerLifeCycle,
|
containerLifeCycle,
|
||||||
containerMethod,
|
containerMethod,
|
||||||
@ -42,7 +42,7 @@ export default function createIceJsProjectBuilder(): IProjectBuilder {
|
|||||||
reactCommonDeps,
|
reactCommonDeps,
|
||||||
esmodule,
|
esmodule,
|
||||||
containerClass,
|
containerClass,
|
||||||
// containerInjectUtils,
|
containerInjectUtils,
|
||||||
containerInitState,
|
containerInitState,
|
||||||
containerLifeCycle,
|
containerLifeCycle,
|
||||||
containerMethod,
|
containerMethod,
|
||||||
|
|||||||
@ -143,3 +143,8 @@ export interface IProjectBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type PostProcessor = (content: string, fileType: string) => string;
|
export type PostProcessor = (content: string, fileType: string) => string;
|
||||||
|
|
||||||
|
// TODO: temp interface, need modify
|
||||||
|
export interface IPluginOptions {
|
||||||
|
fileDirDepth: number;
|
||||||
|
}
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import {
|
|||||||
ChildNodeType,
|
ChildNodeType,
|
||||||
IComponentNodeItem,
|
IComponentNodeItem,
|
||||||
IJSExpression,
|
IJSExpression,
|
||||||
} from '@/types';
|
} from '../types';
|
||||||
|
|
||||||
// tslint:disable-next-line: no-empty
|
// tslint:disable-next-line: no-empty
|
||||||
const noop = () => [];
|
const noop = () => [];
|
||||||
|
|||||||
@ -1,17 +1,12 @@
|
|||||||
{
|
{
|
||||||
"extends": "../../tsconfig.json",
|
"extends": "../../tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "es5",
|
|
||||||
"strictNullChecks": true,
|
|
||||||
"inlineSources": false,
|
|
||||||
"lib": ["es6"],
|
|
||||||
"downlevelIteration": true,
|
|
||||||
"paths": {
|
|
||||||
"@/*": ["./src/*"]
|
|
||||||
},
|
|
||||||
"outDir": "./lib",
|
"outDir": "./lib",
|
||||||
|
"lib": [
|
||||||
|
"es6"
|
||||||
|
],
|
||||||
"types": ["node"],
|
"types": ["node"],
|
||||||
"baseUrl": "." /* Base directory to resolve non-absolute module names. */
|
"baseUrl": ".", /* Base directory to resolve non-absolute module names. */
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"src/**/*"
|
"src/**/*"
|
||||||
|
|||||||
@ -1,31 +0,0 @@
|
|||||||
const path = require('path');
|
|
||||||
const nodeExternals = require('webpack-node-externals');
|
|
||||||
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
mode: 'production',
|
|
||||||
target: 'node',
|
|
||||||
entry: {
|
|
||||||
index: './src/index.ts',
|
|
||||||
// demo: './src/demo/main.ts',
|
|
||||||
},
|
|
||||||
module: {
|
|
||||||
rules: [
|
|
||||||
{
|
|
||||||
test: /\.tsx?$/,
|
|
||||||
use: 'ts-loader',
|
|
||||||
exclude: /node_modules/,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
resolve: {
|
|
||||||
extensions: [ '.tsx', '.ts', '.js' ],
|
|
||||||
plugins: [new TsconfigPathsPlugin({/* options: see below */})],
|
|
||||||
},
|
|
||||||
output: {
|
|
||||||
// filename: 'bundle.js',
|
|
||||||
filename: '[name].js',
|
|
||||||
path: path.resolve(__dirname, 'lib'),
|
|
||||||
},
|
|
||||||
externals: [nodeExternals()], // in order to ignore all modules in node_modules folder
|
|
||||||
};
|
|
||||||
@ -1053,6 +1053,14 @@
|
|||||||
"name": "maxTagCount",
|
"name": "maxTagCount",
|
||||||
"title": "最多显示多少个 tag",
|
"title": "最多显示多少个 tag",
|
||||||
"setter": "ExpressionSetter"
|
"setter": "ExpressionSetter"
|
||||||
|
}, {
|
||||||
|
"name": "color",
|
||||||
|
"title": "颜色选择",
|
||||||
|
"setter": "ColorSetter"
|
||||||
|
}, {
|
||||||
|
"name": "json",
|
||||||
|
"title": "JSON设置",
|
||||||
|
"setter": "JsonSetter"
|
||||||
}, {
|
}, {
|
||||||
"name": "MixinSetter",
|
"name": "MixinSetter",
|
||||||
"placeholder": "混合",
|
"placeholder": "混合",
|
||||||
@ -1081,11 +1089,14 @@
|
|||||||
}, {
|
}, {
|
||||||
"label": "左",
|
"label": "左",
|
||||||
"value": "l"
|
"value": "l"
|
||||||
}]
|
}],
|
||||||
|
"defaultValue": "l"
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
"name": "NumberSetter",
|
"name": "NumberSetter",
|
||||||
"props": {}
|
"props": {
|
||||||
|
"defaultValue": 5
|
||||||
|
}
|
||||||
}, {
|
}, {
|
||||||
"name": "BoolSetter",
|
"name": "BoolSetter",
|
||||||
"props": {}
|
"props": {}
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import Preview from './plugins/provider';
|
|||||||
app.registerRenderer(Renderer);
|
app.registerRenderer(Renderer);
|
||||||
|
|
||||||
// 注册布局组件,可注册多个
|
// 注册布局组件,可注册多个
|
||||||
app.registerLayout('BasicLayout', BasicLayout);
|
app.registerLayout(BasicLayout, { componentName: 'BasicLayout' });
|
||||||
|
|
||||||
// 注册页面 Loading
|
// 注册页面 Loading
|
||||||
app.registerLoading(FusionLoading);
|
app.registerLoading(FusionLoading);
|
||||||
|
|||||||
@ -3,6 +3,17 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [0.9.1](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-material-parser@0.9.0...@ali/lowcode-material-parser@0.9.1) (2020-04-01)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* fix bug of missing ajv ([a37d655](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/commit/a37d655))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="0.9.0"></a>
|
<a name="0.9.0"></a>
|
||||||
# [0.9.0](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-material-parser@0.8.4...@ali/lowcode-material-parser@0.9.0) (2020-03-31)
|
# [0.9.0](https://gitlab.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/compare/@ali/lowcode-material-parser@0.8.4...@ali/lowcode-material-parser@0.9.0) (2020-03-31)
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ali/lowcode-material-parser",
|
"name": "@ali/lowcode-material-parser",
|
||||||
"version": "0.9.0",
|
"version": "0.9.1",
|
||||||
"description": "material parser for Ali lowCode engine",
|
"description": "material parser for Ali lowCode engine",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"files": [
|
"files": [
|
||||||
@ -13,8 +13,6 @@
|
|||||||
"@types/js-yaml": "^3.12.2",
|
"@types/js-yaml": "^3.12.2",
|
||||||
"@types/lodash": "^4.14.149",
|
"@types/lodash": "^4.14.149",
|
||||||
"@types/semver": "^7.1.0",
|
"@types/semver": "^7.1.0",
|
||||||
"ajv": "^6.10.2",
|
|
||||||
"better-ajv-errors": "^0.6.4",
|
|
||||||
"globby": "^10.0.1",
|
"globby": "^10.0.1",
|
||||||
"jest": "^24.8.0",
|
"jest": "^24.8.0",
|
||||||
"jest-watch-typeahead": "^0.3.1",
|
"jest-watch-typeahead": "^0.3.1",
|
||||||
@ -48,6 +46,7 @@
|
|||||||
"@babel/parser": "^7.8.4",
|
"@babel/parser": "^7.8.4",
|
||||||
"@babel/traverse": "^7.8.4",
|
"@babel/traverse": "^7.8.4",
|
||||||
"@babel/types": "^7.8.3",
|
"@babel/types": "^7.8.3",
|
||||||
|
"ajv": "^6.12.0",
|
||||||
"ast-types": "^0.13.3",
|
"ast-types": "^0.13.3",
|
||||||
"cross-spawn-promise": "^0.10.2",
|
"cross-spawn-promise": "^0.10.2",
|
||||||
"debug": "^4.1.1",
|
"debug": "^4.1.1",
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@ali/lowcode-runtime",
|
"name": "@ali/lowcode-runtime",
|
||||||
"version": "0.8.7",
|
"version": "0.8.9",
|
||||||
"description": "Runtime for Ali lowCode engine",
|
"description": "Runtime for Ali lowCode engine",
|
||||||
"files": [
|
"files": [
|
||||||
"es",
|
"es",
|
||||||
|
|||||||
@ -1,6 +1,11 @@
|
|||||||
import { ReactType } from 'react';
|
import { ReactType } from 'react';
|
||||||
import Provider from './provider';
|
import Provider from './provider';
|
||||||
|
|
||||||
|
export interface ILayoutOptions {
|
||||||
|
componentName?: string;
|
||||||
|
props?: any;
|
||||||
|
}
|
||||||
|
|
||||||
export default class Container {
|
export default class Container {
|
||||||
private renderer: ReactType | null = null;
|
private renderer: ReactType | null = null;
|
||||||
private layouts: { [key: string]: ReactType } = {};
|
private layouts: { [key: string]: ReactType } = {};
|
||||||
@ -11,7 +16,11 @@ export default class Container {
|
|||||||
this.renderer = renderer;
|
this.renderer = renderer;
|
||||||
}
|
}
|
||||||
|
|
||||||
registerLayout(componentName: string, Layout: ReactType): any {
|
registerLayout(Layout: ReactType, options: ILayoutOptions): any {
|
||||||
|
if (!options) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const { componentName } = options;
|
||||||
if (!componentName || !Layout) {
|
if (!componentName || !Layout) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { ReactType } from 'react';
|
import { ReactType } from 'react';
|
||||||
import Container from './container';
|
import Container, { ILayoutOptions } from './container';
|
||||||
import run from './run';
|
import run from './run';
|
||||||
|
|
||||||
class App {
|
class App {
|
||||||
@ -17,8 +17,8 @@ class App {
|
|||||||
this.container.registerRenderer(renderer);
|
this.container.registerRenderer(renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
registerLayout(componentName: string, Layout: ReactType): any {
|
registerLayout(Layout: ReactType, options: ILayoutOptions): any {
|
||||||
this.container.registerLayout(componentName, Layout);
|
this.container.registerLayout(Layout, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
registerLoading(component: ReactType) {
|
registerLoading(component: ReactType) {
|
||||||
|
|||||||
@ -27,7 +27,7 @@ interface IHistoryConfig {
|
|||||||
basement?: string;
|
basement?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface IAppData {
|
export interface IAppData {
|
||||||
history?: HistoryMode;
|
history?: HistoryMode;
|
||||||
layout?: ILayoutConfig;
|
layout?: ILayoutConfig;
|
||||||
routes?: IRouterConfig;
|
routes?: IRouterConfig;
|
||||||
@ -36,6 +36,7 @@ interface IAppData {
|
|||||||
componentsMap?: IComponentMap[];
|
componentsMap?: IComponentMap[];
|
||||||
utils?: IUtils;
|
utils?: IUtils;
|
||||||
constants?: IConstants;
|
constants?: IConstants;
|
||||||
|
i18n?: I18n;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ComponentProps {
|
export interface ComponentProps {
|
||||||
@ -92,6 +93,13 @@ export interface ComponentModel {
|
|||||||
loopArgs?: string[];
|
loopArgs?: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface I18n {
|
||||||
|
'zh-CN': { [key: string]: string };
|
||||||
|
'en-US': { [key: string]: string };
|
||||||
|
}
|
||||||
|
|
||||||
|
type Locale = 'zh-CN' | 'en-US';
|
||||||
|
|
||||||
// export interface IProvider {
|
// export interface IProvider {
|
||||||
// init?(): void;
|
// init?(): void;
|
||||||
// getAppData?(appkey: string): Promise<IAppData | undefined>;
|
// getAppData?(appkey: string): Promise<IAppData | undefined>;
|
||||||
@ -109,6 +117,7 @@ export default class Provider {
|
|||||||
private componentsMap: IComponentMap[] = [];
|
private componentsMap: IComponentMap[] = [];
|
||||||
private history: HistoryMode = 'hash';
|
private history: HistoryMode = 'hash';
|
||||||
private containerId = '';
|
private containerId = '';
|
||||||
|
private i18n: I18n | null = null;
|
||||||
private lazyElementsMap: { [key: string]: any } = {};
|
private lazyElementsMap: { [key: string]: any } = {};
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
@ -118,15 +127,16 @@ export default class Provider {
|
|||||||
async(): Promise<IAppConfig> {
|
async(): Promise<IAppConfig> {
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
const appData = await this.getAppData();
|
const appData: IAppData = await this.getAppData();
|
||||||
if (!appData) {
|
if (!appData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const { history, layout, routes, containerId, components, componentsMap, utils, constants } = appData;
|
const { history, layout, routes, containerId, components, componentsMap, utils, constants, i18n } = appData;
|
||||||
this.setHistory(history);
|
this.setHistory(history);
|
||||||
this.setLayoutConfig(layout);
|
this.setLayoutConfig(layout);
|
||||||
this.setRouterConfig(routes);
|
this.setRouterConfig(routes);
|
||||||
this.setContainerId(containerId);
|
this.setContainerId(containerId);
|
||||||
|
this.setI18n(i18n);
|
||||||
this.registerComponents(components);
|
this.registerComponents(components);
|
||||||
this.registerComponentsMap(componentsMap);
|
this.registerComponentsMap(componentsMap);
|
||||||
this.registerUtils(utils);
|
this.registerUtils(utils);
|
||||||
@ -220,6 +230,13 @@ export default class Provider {
|
|||||||
this.containerId = id;
|
this.containerId = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setI18n(i18n: I18n) {
|
||||||
|
if (!i18n) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.i18n = i18n;
|
||||||
|
}
|
||||||
|
|
||||||
setlazyElement(pageId: string, cache: any) {
|
setlazyElement(pageId: string, cache: any) {
|
||||||
if (!pageId || !cache) {
|
if (!pageId || !cache) {
|
||||||
return;
|
return;
|
||||||
@ -281,6 +298,13 @@ export default class Provider {
|
|||||||
return this.containerId;
|
return this.containerId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getI18n(locale?: Locale) {
|
||||||
|
if (!this.i18n) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return locale ? this.i18n[locale] : this.i18n;
|
||||||
|
}
|
||||||
|
|
||||||
getlazyElement(pageId: string) {
|
getlazyElement(pageId: string) {
|
||||||
if (!pageId) {
|
if (!pageId) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -1 +1,140 @@
|
|||||||
通用设置器
|
通用设置器
|
||||||
|
|
||||||
|
## 使用文档
|
||||||
|
- name:绑定props属性key,类型为string
|
||||||
|
- setter:setter组件内容,类型可以为string或object,当为string时,指setter名,当为object时:
|
||||||
|
- componentName:setter名,类型为string
|
||||||
|
- props:setter属性,类型为object
|
||||||
|
|
||||||
|
## 使用demo
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"name": "TextAreaSetter",
|
||||||
|
"setter": "TextAreaSetter"
|
||||||
|
}, {
|
||||||
|
"name": "date",
|
||||||
|
"title": "测试日期",
|
||||||
|
"setter": "DateSetter"
|
||||||
|
}, {
|
||||||
|
"name": "date",
|
||||||
|
"title": "测试日期-年",
|
||||||
|
"setter": "DateYearSetter"
|
||||||
|
}, {
|
||||||
|
"name": "date",
|
||||||
|
"title": "测试日期-月",
|
||||||
|
"setter": "DateMonthSetter"
|
||||||
|
}, {
|
||||||
|
"name": "date",
|
||||||
|
"title": "测试日期-区间",
|
||||||
|
"setter": "DateRangeSetter"
|
||||||
|
}, {
|
||||||
|
"name": "mode",
|
||||||
|
"title": "选择器模式",
|
||||||
|
"setter": {
|
||||||
|
"componentName": "RadioGroupSetter",
|
||||||
|
"props": {
|
||||||
|
"defaultValue": "single",
|
||||||
|
"dataSource": [{
|
||||||
|
"value": "single",
|
||||||
|
"label": "single"
|
||||||
|
}, {
|
||||||
|
"value": "multiple",
|
||||||
|
"label": "multiple"
|
||||||
|
}, {
|
||||||
|
"value": "tag",
|
||||||
|
"label": "tag"
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"name": "mode",
|
||||||
|
"title": "选择器模式",
|
||||||
|
"setter": {
|
||||||
|
"componentName": "SelectSetter",
|
||||||
|
"props": {
|
||||||
|
"defaultValue": "single",
|
||||||
|
"dataSource": [{
|
||||||
|
"value": "single",
|
||||||
|
"label": "single"
|
||||||
|
}, {
|
||||||
|
"value": "multiple",
|
||||||
|
"label": "multiple"
|
||||||
|
}, {
|
||||||
|
"value": "tag",
|
||||||
|
"label": "tag"
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"name": "value",
|
||||||
|
"title": "受控值",
|
||||||
|
"setter": "StringSetter"
|
||||||
|
}, {
|
||||||
|
"name": "hasBorder",
|
||||||
|
"title": "是否有边框",
|
||||||
|
"setter": {
|
||||||
|
"componentName": "BoolSetter",
|
||||||
|
"props": {
|
||||||
|
"defaultValue": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"name": "maxTagCount",
|
||||||
|
"title": "最多显示多少个 tag",
|
||||||
|
"setter": "NumberSetter"
|
||||||
|
}, {
|
||||||
|
"name": "maxTagCount",
|
||||||
|
"title": "最多显示多少个 tag",
|
||||||
|
"setter": "ExpressionSetter"
|
||||||
|
}, {
|
||||||
|
"name": "color",
|
||||||
|
"title": "颜色选择",
|
||||||
|
"setter": "ColorSetter"
|
||||||
|
}, {
|
||||||
|
"name": "json",
|
||||||
|
"title": "JSON设置",
|
||||||
|
"setter": "JsonSetter"
|
||||||
|
}, {
|
||||||
|
"name": "MixinSetter",
|
||||||
|
"placeholder": "混合",
|
||||||
|
"setter": {
|
||||||
|
"componentName": "MixinSetter",
|
||||||
|
"props": {
|
||||||
|
"types": [{
|
||||||
|
"name": "StringSetter",
|
||||||
|
"props": {}
|
||||||
|
}, {
|
||||||
|
"name": "TextAreaSetter",
|
||||||
|
"props": {}
|
||||||
|
}, {
|
||||||
|
"name": "SelectSetter",
|
||||||
|
"props": {
|
||||||
|
"hasClear": true,
|
||||||
|
"dataSource": [{
|
||||||
|
"label": "上",
|
||||||
|
"value": "t"
|
||||||
|
}, {
|
||||||
|
"label": "右",
|
||||||
|
"value": "r"
|
||||||
|
}, {
|
||||||
|
"label": "下",
|
||||||
|
"value": "b"
|
||||||
|
}, {
|
||||||
|
"label": "左",
|
||||||
|
"value": "l"
|
||||||
|
}],
|
||||||
|
"defaultValue": "l"
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"name": "NumberSetter",
|
||||||
|
"props": {
|
||||||
|
"defaultValue": 5
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"name": "BoolSetter",
|
||||||
|
"props": {}
|
||||||
|
}],
|
||||||
|
"defaultType": "SelectSetter"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
@ -1,375 +0,0 @@
|
|||||||
import React, { PureComponent } from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { Select, Balloon } from '@alife/next';
|
|
||||||
import * as acorn from 'acorn';
|
|
||||||
|
|
||||||
import { isJSExpression, generateI18n } from './locale/utils';
|
|
||||||
import zhCN from './locale/zh-CN';
|
|
||||||
|
|
||||||
const { Option, AutoComplete } = Select;
|
|
||||||
const { Tooltip } = Balloon;
|
|
||||||
const helpMap = {
|
|
||||||
this: '容器上下文对象',
|
|
||||||
'this.state': '容器的state',
|
|
||||||
'this.props': '容器的props',
|
|
||||||
'this.context': '容器的context',
|
|
||||||
'this.page': '页面上下文对象',
|
|
||||||
'this.component': '组件上下文对象',
|
|
||||||
'this.constants': '应用常量对象',
|
|
||||||
'this.utils': '应用工具对象',
|
|
||||||
'this.dataSourceMap': '容器数据源Map',
|
|
||||||
'this.field': '表单Field对象',
|
|
||||||
};
|
|
||||||
|
|
||||||
export default class ExpressionView extends PureComponent {
|
|
||||||
static displayName = 'Expression';
|
|
||||||
static propTypes = {
|
|
||||||
context: PropTypes.object,
|
|
||||||
dataSource: PropTypes.array,
|
|
||||||
locale: PropTypes.string,
|
|
||||||
messages: PropTypes.object,
|
|
||||||
onChange: PropTypes.func,
|
|
||||||
placeholder: PropTypes.string,
|
|
||||||
value: PropTypes.string,
|
|
||||||
};
|
|
||||||
static defaultProps = {
|
|
||||||
context: {},
|
|
||||||
dataSource: [],
|
|
||||||
locale: 'zh-CN',
|
|
||||||
messages: zhCN,
|
|
||||||
onChange: () => {},
|
|
||||||
placeholder: '',
|
|
||||||
value: '',
|
|
||||||
};
|
|
||||||
expression: React.RefObject<unknown>;
|
|
||||||
i18n: any;
|
|
||||||
t: void;
|
|
||||||
$input: any;
|
|
||||||
listenerFun: (event: any) => void;
|
|
||||||
|
|
||||||
static getInitValue(val: { value: any; match: (arg0: RegExp) => any }) {
|
|
||||||
if (isJSExpression(val)) {
|
|
||||||
if (typeof val === 'object') {
|
|
||||||
return val.value;
|
|
||||||
} else if (typeof val === 'string') {
|
|
||||||
let arr = val.match(/^\{\{(.*?)\}\}$/);
|
|
||||||
if (arr) return arr[1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
constructor(props: Readonly<{}>) {
|
|
||||||
super(props);
|
|
||||||
this.expression = React.createRef();
|
|
||||||
this.i18n = generateI18n(props.locale, props.messages);
|
|
||||||
this.state = {
|
|
||||||
value: ExpressionView.getInitValue(props.value),
|
|
||||||
context: props.context || {},
|
|
||||||
dataSource: props.dataSource || [],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
static getDerivedStateFromProps(props: { value: any }, state: { preValue: any }) {
|
|
||||||
let curValue = ExpressionView.getInitValue(props.value);
|
|
||||||
if (curValue !== state.preValue) {
|
|
||||||
return {
|
|
||||||
preValue: curValue,
|
|
||||||
value: curValue,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
onChange(value: string, actionType: string) {
|
|
||||||
let realInputValue = value;
|
|
||||||
let realDataSource = null;
|
|
||||||
const cursorIndex = this.getInputCursorPosition();
|
|
||||||
let nextCursorIndex: number;
|
|
||||||
//更新值
|
|
||||||
if (actionType === 'itemClick' || actionType === 'enter') {
|
|
||||||
let curValue = this.state.value;
|
|
||||||
if (curValue) {
|
|
||||||
//如果是非.结束,则替换当前这个变量;
|
|
||||||
let preStr = curValue.substr(0, cursorIndex);
|
|
||||||
let nextStr = curValue.substr(cursorIndex);
|
|
||||||
let preArr = preStr.split('.');
|
|
||||||
let preArrLen = preArr.length;
|
|
||||||
let tarPreStr = '';
|
|
||||||
if (!preArr[preArrLen - 1]) {
|
|
||||||
//如果是.结束,则增加到.后面
|
|
||||||
if (preArr[preArrLen - 2] === 'this') {
|
|
||||||
preArr = preArr.slice(0, preArrLen - 2);
|
|
||||||
preArr.push(value);
|
|
||||||
tarPreStr = preArr.join('.');
|
|
||||||
} else {
|
|
||||||
tarPreStr = preStr + value;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (preArr[preArrLen - 2] === 'this') {
|
|
||||||
preArr = preArr.slice(0, preArrLen - 2);
|
|
||||||
} else {
|
|
||||||
preArr = preArr.slice(0, preArrLen - 1);
|
|
||||||
}
|
|
||||||
preArr.push(value);
|
|
||||||
tarPreStr = preArr.join('.');
|
|
||||||
}
|
|
||||||
realInputValue = tarPreStr + nextStr;
|
|
||||||
realDataSource = this.getDataSource(tarPreStr + '.') || [];
|
|
||||||
nextCursorIndex = tarPreStr.length;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let tarPreStr = value.substr(0, cursorIndex);
|
|
||||||
if (tarPreStr) {
|
|
||||||
let lastChar = tarPreStr.charAt(tarPreStr.length - 1);
|
|
||||||
if (lastChar === '.') {
|
|
||||||
realDataSource = this.getDataSource(tarPreStr) || [];
|
|
||||||
} else {
|
|
||||||
realDataSource = this.getDataSource(tarPreStr + '.');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
realDataSource = this.getDataSource('this.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//更新数据源
|
|
||||||
let newState = {
|
|
||||||
value: realInputValue,
|
|
||||||
};
|
|
||||||
if (realDataSource !== null) newState.dataSource = realDataSource;
|
|
||||||
this.setState(newState, () => {
|
|
||||||
nextCursorIndex && this.setInputCursorPosition(nextCursorIndex);
|
|
||||||
});
|
|
||||||
//默认加上变量表达式
|
|
||||||
this.t && clearTimeout(this.t);
|
|
||||||
this.t = setTimeout(() => {
|
|
||||||
const { onChange } = this.props;
|
|
||||||
// realInputValue = realInputValue ? `{{${realInputValue}}}` : undefined;
|
|
||||||
onChange &&
|
|
||||||
onChange({
|
|
||||||
type: 'JSExpression',
|
|
||||||
value: realInputValue,
|
|
||||||
});
|
|
||||||
}, 300);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取AutoComplete数据源
|
|
||||||
* @param {String}
|
|
||||||
* @return {Array}
|
|
||||||
*/
|
|
||||||
getDataSource(tempStr: string): Array<any> {
|
|
||||||
if (tempStr === '' || /[^\w\.]$/.test(tempStr)) {
|
|
||||||
return this.getDataSource('this.') || [];
|
|
||||||
} else if (/\w\.$/.test(tempStr)) {
|
|
||||||
let currentField = this.getCurrentFiled(tempStr);
|
|
||||||
if (!currentField) return null;
|
|
||||||
let tempKeys = this.getObjectKeys(currentField.str);
|
|
||||||
tempKeys = this.getContextKeys(tempKeys);
|
|
||||||
if (!tempKeys) return null;
|
|
||||||
//给默认情况增加this
|
|
||||||
if (tempStr === 'this.') {
|
|
||||||
tempKeys = tempKeys.map((item: string) => {
|
|
||||||
return 'this.' + item;
|
|
||||||
});
|
|
||||||
tempKeys.unshift('this');
|
|
||||||
}
|
|
||||||
return tempKeys;
|
|
||||||
} else if (/\.$/.test(tempStr)) {
|
|
||||||
return [];
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取光标前的对象字符串,语法解析获取对象字符串
|
|
||||||
* @param {String} str 模板字符串
|
|
||||||
* @return {String} 光标前的对象字符串
|
|
||||||
*/
|
|
||||||
getCurrentFiled(str: string | any[]) {
|
|
||||||
str += 'x'; //.后面加一个x字符,便于acorn解析
|
|
||||||
try {
|
|
||||||
let astTree = acorn.parse(str);
|
|
||||||
let right = astTree.body[0].expression.right || astTree.body[0].expression;
|
|
||||||
if (right.type === 'MemberExpression') {
|
|
||||||
let { start, end } = right;
|
|
||||||
str = str.slice(start, end);
|
|
||||||
return { str, start, end };
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取输入的上下文信息
|
|
||||||
* @param {Array}
|
|
||||||
* @return {Array}
|
|
||||||
*/
|
|
||||||
getContextKeys(keys: any) {
|
|
||||||
// let context = {};
|
|
||||||
// const { appHelper } = this.context;
|
|
||||||
// const activeKey = appHelper && appHelper.activeKey;
|
|
||||||
// if (!activeKey) return;
|
|
||||||
// const activeCtx = appHelper.schemaHelper.compCtxMap && appHelper.schemaHelper.compCtxMap[activeKey];
|
|
||||||
// if (!activeCtx) return null;
|
|
||||||
// let __self = activeCtx;
|
|
||||||
// if (keys && keys.length > 1) {
|
|
||||||
// keys.shift(0);
|
|
||||||
// let path = '/' + keys.join('/');
|
|
||||||
// path = path.replace(/[\[\]]/g, '/');
|
|
||||||
// context = jsonuri.get(__self, path);
|
|
||||||
// if (context && typeof context === 'object') {
|
|
||||||
// return this.filterKey(context);
|
|
||||||
// }
|
|
||||||
// } else if (keys && keys[0] === 'this') {
|
|
||||||
// return this.filterKey(__self);
|
|
||||||
// }
|
|
||||||
// return null;
|
|
||||||
return ['page', 'component'];
|
|
||||||
}
|
|
||||||
|
|
||||||
/*过滤key */
|
|
||||||
filterKey(obj: any) {
|
|
||||||
let filterKeys = [
|
|
||||||
'reloadDataSource',
|
|
||||||
'REACT_HOT_LOADER_RENDERED_GENERATION',
|
|
||||||
'refs',
|
|
||||||
'updater',
|
|
||||||
'appHelper',
|
|
||||||
'isReactComponent',
|
|
||||||
'forceUpdate',
|
|
||||||
'setState',
|
|
||||||
'isPureReactComponent',
|
|
||||||
];
|
|
||||||
let result = [];
|
|
||||||
for (let key in obj) {
|
|
||||||
if (key.indexOf('_') !== 0 && filterKeys.indexOf(key) === -1) {
|
|
||||||
result.push(key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据输入项进行筛选
|
|
||||||
* @param {String}
|
|
||||||
* @param {String}
|
|
||||||
* @return {Boolen}
|
|
||||||
*/
|
|
||||||
filterOption(inputValue: string, item: { value: string | any[] }) {
|
|
||||||
const cursorIndex = this.getInputCursorPosition();
|
|
||||||
let preStr = inputValue.substr(0, cursorIndex);
|
|
||||||
let lastKey = preStr.split('.').slice(-1);
|
|
||||||
if (!lastKey) return true;
|
|
||||||
if (item.value.indexOf(lastKey) > -1) return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { value, dataSource } = this.state;
|
|
||||||
const { placeholder } = this.props;
|
|
||||||
const isValObject = !!(value == '[object Object]');
|
|
||||||
let title = isValObject
|
|
||||||
? this.i18n('valueIllegal')
|
|
||||||
: (value || placeholder || this.i18n('jsExpression')).toString();
|
|
||||||
const cursorIndex = this.getInputCursorPosition();
|
|
||||||
let childNode = cursorIndex ? (
|
|
||||||
<div className="cursor-blink">
|
|
||||||
{title.substr(0, cursorIndex)}
|
|
||||||
<b>|</b>
|
|
||||||
{title.substr(cursorIndex)}
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
title
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div ref={this.expression} style={{ width: '100%', display: 'inline-block' }}>
|
|
||||||
<Tooltip
|
|
||||||
triggerType={isValObject ? ['click'] : ['focus']}
|
|
||||||
align="tl"
|
|
||||||
popupClassName="code-input-overlay"
|
|
||||||
trigger={
|
|
||||||
isValObject ? (
|
|
||||||
value
|
|
||||||
) : (
|
|
||||||
<AutoComplete
|
|
||||||
{...this.props}
|
|
||||||
style={{ width: '100%' }}
|
|
||||||
dataSource={dataSource}
|
|
||||||
placeholder={placeholder || this.i18n('jsExpression')}
|
|
||||||
value={value}
|
|
||||||
disabled={isValObject}
|
|
||||||
innerBefore={<span style={{ color: '#999', marginLeft: 4 }}>{'{{'}</span>}
|
|
||||||
innerAfter={<span style={{ color: '#999', marginRight: 4 }}>{'}}'}</span>}
|
|
||||||
itemRender={({ value }) => {
|
|
||||||
return (
|
|
||||||
<Option key={value} text={value} value={value}>
|
|
||||||
<div className="code-input-value">{value}</div>
|
|
||||||
<div className="code-input-help">{helpMap[value]}</div>
|
|
||||||
</Option>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
onChange={this.onChange.bind(this)}
|
|
||||||
filter={this.filterOption.bind(this)}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{childNode}
|
|
||||||
</Tooltip>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
this.$input = this.findInputElement();
|
|
||||||
if (this.$input) {
|
|
||||||
this.listenerFun = (event) => {
|
|
||||||
let isMoveKey = !!(event.type == 'keyup' && ~[37, 38, 39, 91].indexOf(event.keyCode));
|
|
||||||
let isMouseup = event.type == 'mouseup';
|
|
||||||
if (isMoveKey || isMouseup) {
|
|
||||||
let dataSource = this.getDataSource(this.state.value) || [];
|
|
||||||
this.setState({
|
|
||||||
dataSource,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
this.$input.addEventListener('keyup', this.listenerFun, false);
|
|
||||||
this.$input.addEventListener('mouseup', this.listenerFun, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
componentWillUnmount() {
|
|
||||||
if (this.listenerFun && this.$input) {
|
|
||||||
this.$input.removeEventListener('keyup', this.listenerFun, false);
|
|
||||||
this.$input.removeEventListener('mouseup', this.listenerFun, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 获取Input输入框DOM节点
|
|
||||||
*/
|
|
||||||
findInputElement() {
|
|
||||||
return this.expression.current.children[0].getElementsByTagName('input')[0];
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* 获取光标位置
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
getInputCursorPosition() {
|
|
||||||
if (!this.$input) return;
|
|
||||||
return this.$input.selectionStart;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* 字符串取得对象keys
|
|
||||||
*/
|
|
||||||
getObjectKeys(str: string) {
|
|
||||||
let keys = [];
|
|
||||||
if (str) keys = str.split('.');
|
|
||||||
return keys.slice(0, keys.length - 1);
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* 设置input组件光标位置在闭合}前
|
|
||||||
*/
|
|
||||||
setInputCursorPosition(idx: number) {
|
|
||||||
this.$input.setSelectionRange(idx, idx);
|
|
||||||
this.forceUpdate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,471 +0,0 @@
|
|||||||
import { Component, isValidElement, ReactElement, ReactNode, PureComponent } from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import MonacoEditor from 'react-monaco-editor';
|
|
||||||
import classNames from 'classnames';
|
|
||||||
import { Icon } from '@alifd/next';
|
|
||||||
import ObjectButton from '@ali/iceluna-comp-object-button';
|
|
||||||
import FormItem from '@ali/iceluna-comp-form/lib/item';
|
|
||||||
import { serialize, jsonuri, generateI18n } from '@ali/iceluna-sdk/lib/utils';
|
|
||||||
|
|
||||||
import Snippets from './locale/snippets';
|
|
||||||
import zhCN from './locale/zh-CN';
|
|
||||||
import './index.scss';
|
|
||||||
|
|
||||||
let registerApiAndSnippetStatus = false; //判断注册api机制
|
|
||||||
|
|
||||||
class MonacoEditorDefaultView extends PureComponent {
|
|
||||||
static displayName = 'MonacoEditorDefault';
|
|
||||||
static propTypes = {
|
|
||||||
locale: PropTypes.string,
|
|
||||||
messages: PropTypes.object
|
|
||||||
};
|
|
||||||
static defaultProps = {
|
|
||||||
locale: 'zh-CN',
|
|
||||||
messages: zhCN,
|
|
||||||
width: '100%',
|
|
||||||
height: '100%',
|
|
||||||
language: 'javascript',
|
|
||||||
autoFocus: false, //自动获得焦点
|
|
||||||
autoSubmit: true, //自动提交
|
|
||||||
placeholder: '', //默认占位内容
|
|
||||||
btnText: '提交',
|
|
||||||
btnSize: 'small',
|
|
||||||
rules: [], //校验规则
|
|
||||||
options: {
|
|
||||||
readOnly: false,
|
|
||||||
automaticLayout: true,
|
|
||||||
folding: true, //默认开启折叠代码功能
|
|
||||||
lineNumbers: 'on',
|
|
||||||
wordWrap: 'off',
|
|
||||||
formatOnPaste: true,
|
|
||||||
fontSize: 12,
|
|
||||||
tabSize: 2,
|
|
||||||
scrollBeyondLastLine: false,
|
|
||||||
fixedOverflowWidgets: false,
|
|
||||||
snippetSuggestions: 'top',
|
|
||||||
minimap: {
|
|
||||||
enabled: true
|
|
||||||
},
|
|
||||||
scrollbar: {
|
|
||||||
vertical: 'hidden',
|
|
||||||
horizontal: 'hidden',
|
|
||||||
verticalScrollbarSize: 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.strValue = '';
|
|
||||||
this.i18n = generateI18n(props.locale, props.messages);
|
|
||||||
this.editorRef = React.createRef();
|
|
||||||
this.options = Object.assign({}, MonacoEditorDefaultView.defaultProps.options, props.options);
|
|
||||||
this.fullScreenOptions = {
|
|
||||||
...this.options,
|
|
||||||
lineNumbers: 'on',
|
|
||||||
folding: true,
|
|
||||||
scrollBeyondLastLine: true,
|
|
||||||
minimap: {
|
|
||||||
enabled: true
|
|
||||||
}
|
|
||||||
};
|
|
||||||
this.state = {
|
|
||||||
isFullScreen: false
|
|
||||||
};
|
|
||||||
this.onChange = this.onChange.bind(this);
|
|
||||||
this.onSubmit = this.onSubmit.bind(this);
|
|
||||||
this.fullScreen = this.fullScreen.bind(this);
|
|
||||||
this.format = this.format.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidUpdate() {
|
|
||||||
//如果是全屏操作,获得焦点,光标保留在原来位置;
|
|
||||||
if (this.position) {
|
|
||||||
this.editor.focus();
|
|
||||||
this.editor.setPosition(this.position);
|
|
||||||
delete this.position;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
componentDidMount() {
|
|
||||||
this.editorNode = this.editorRef.current; //记录当前dom节点;
|
|
||||||
this.editorParentNode = this.editorNode.parentNode; //记录父节点;
|
|
||||||
//自动获得焦点, 格式化需要时间
|
|
||||||
if (this.props.autoFocus) {
|
|
||||||
setTimeout(() => {
|
|
||||||
this.editor.setPosition({
|
|
||||||
column: 4,
|
|
||||||
lineNumber: 2
|
|
||||||
});
|
|
||||||
this.editor.focus();
|
|
||||||
}, 100);
|
|
||||||
}
|
|
||||||
//快捷键编码
|
|
||||||
let CtrlCmd = 2048;
|
|
||||||
let KEY_S = 49;
|
|
||||||
let Shift = 1024;
|
|
||||||
let KEY_F = 36;
|
|
||||||
let KEY_B = 32;
|
|
||||||
let Escape = 9;
|
|
||||||
|
|
||||||
this.editor.addCommand(CtrlCmd | KEY_S, () => {
|
|
||||||
this.onSubmit(); //保存快捷键
|
|
||||||
});
|
|
||||||
this.editor.addCommand(CtrlCmd | Shift | KEY_F, () => {
|
|
||||||
this.fullScreen(); //全屏快捷键
|
|
||||||
});
|
|
||||||
this.editor.addCommand(CtrlCmd | KEY_B, () => {
|
|
||||||
this.format(); //美化快捷键
|
|
||||||
});
|
|
||||||
this.editor.addCommand(Escape, () => {
|
|
||||||
this.props.onEscape && this.props.onEscape();
|
|
||||||
});
|
|
||||||
//注册api
|
|
||||||
this.editor.submit = this.onSubmit;
|
|
||||||
this.editor.format = this.format;
|
|
||||||
this.editor.fullScreen = this.fullScreen;
|
|
||||||
this.editor.toJson = this.toJson;
|
|
||||||
this.editor.toObject = this.toObject;
|
|
||||||
this.editor.toFunction = this.toFunction;
|
|
||||||
//针对object情况,改写setValue和getValue api
|
|
||||||
if (this.props.language === 'object') {
|
|
||||||
let getValue = this.editor.getValue;
|
|
||||||
let setValue = this.editor.setValue;
|
|
||||||
this.editor.getValue = () => {
|
|
||||||
return getValue.call(this.editor).substring(this.valuePrefix.length);
|
|
||||||
};
|
|
||||||
this.editor.setValue = value => {
|
|
||||||
return setValue.call(this.editor, [this.valuePrefix + value]);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const {
|
|
||||||
value,
|
|
||||||
placeholder,
|
|
||||||
style,
|
|
||||||
className,
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
language,
|
|
||||||
theme,
|
|
||||||
options,
|
|
||||||
editorWillMount,
|
|
||||||
editorDidMount,
|
|
||||||
autoSubmit,
|
|
||||||
btnText,
|
|
||||||
btnSize,
|
|
||||||
registerApi
|
|
||||||
} = this.props;
|
|
||||||
|
|
||||||
const { isFullScreen } = this.state;
|
|
||||||
this.valuePrefix = ''; //值前缀
|
|
||||||
if (language === 'object') this.valuePrefix = 'export default ';
|
|
||||||
if (!this.isFullScreenAction) {
|
|
||||||
//将值转换成目标值
|
|
||||||
let nowValue = this.valueHandler(value || placeholder, language);
|
|
||||||
let curValue = this.valueHandler(this.strValue, language);
|
|
||||||
if (nowValue !== curValue) this.strValue = nowValue;
|
|
||||||
if (language === 'object') this.strValue = this.strValue || placeholder || '{\n\t\n}'; //设置初始化值
|
|
||||||
if (language === 'json' && this.strValue === '{}') this.strValue = '{\n\t\n}';
|
|
||||||
}
|
|
||||||
this.isFullScreenAction = false;
|
|
||||||
//真实高亮语言
|
|
||||||
let tarLanguage = language;
|
|
||||||
if (language === 'object' || language === 'function') {
|
|
||||||
tarLanguage = 'javascript';
|
|
||||||
}
|
|
||||||
let classes = classNames('monaco-editor-wrap', {
|
|
||||||
['monaco-fullscreen']: !!isFullScreen,
|
|
||||||
['monaco-nofullscreen']: !isFullScreen
|
|
||||||
});
|
|
||||||
let tarStyle = Object.assign({ minHeight: 360, width, height }, style);
|
|
||||||
return (
|
|
||||||
<div className={className} style={tarStyle}>
|
|
||||||
<div ref={this.editorRef} style={{ height: '100%', minHeight: 300 }} className={classes}>
|
|
||||||
<MonacoEditor
|
|
||||||
value={this.valuePrefix + this.strValue}
|
|
||||||
width="100%"
|
|
||||||
height="100%"
|
|
||||||
language={tarLanguage}
|
|
||||||
theme={theme || window.__monacoTheme || 'vs-dark'}
|
|
||||||
options={isFullScreen ? this.fullScreenOptions : this.options}
|
|
||||||
onChange={this.onChange}
|
|
||||||
editorWillMount={editorWillMount}
|
|
||||||
editorDidMount={(editor, monaco) => {
|
|
||||||
this.editor = editor;
|
|
||||||
// registerApi({ editor });
|
|
||||||
this.registerApiAndSnippet(monaco);
|
|
||||||
editorDidMount && editorDidMount.call(this, arguments);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<a
|
|
||||||
onClick={this.fullScreen}
|
|
||||||
className="monaco_fullscreen_icon"
|
|
||||||
title={
|
|
||||||
isFullScreen ? `${this.i18n('cancelFullScreen')} cmd+shift+f` : `${this.i18n('fullScreen')} cmd+shift+f`
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Icon type={isFullScreen ? 'quxiaoquanping' : 'quanping'} />
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
//值变化
|
|
||||||
onChange(curValue) {
|
|
||||||
if (curValue === this.valuePrefix + this.strValue) return;
|
|
||||||
const { onAfterChange, language, autoSubmit, onChange } = this.props;
|
|
||||||
this.strValue = curValue; //记录当前格式
|
|
||||||
if (this.ct) clearTimeout(this.ct);
|
|
||||||
this.ct = setTimeout(() => {
|
|
||||||
this.position = this.editor.getPosition();
|
|
||||||
let ret = this.resultHandler(curValue, language);
|
|
||||||
if (autoSubmit) onChange && onChange(ret.value);
|
|
||||||
onAfterChange && onAfterChange(ret.value, ret.error, this.editor);
|
|
||||||
}, 300);
|
|
||||||
}
|
|
||||||
|
|
||||||
//提交动作
|
|
||||||
onSubmit() {
|
|
||||||
const { onSubmit, onChange, language } = this.props;
|
|
||||||
let curValue = this.editor.getValue();
|
|
||||||
let ret = this.resultHandler(curValue, language);
|
|
||||||
if (!ret.error) onChange && onChange(ret.value);
|
|
||||||
onSubmit && onSubmit(ret.value, ret.error, this.editor);
|
|
||||||
}
|
|
||||||
|
|
||||||
//值类型转换处理
|
|
||||||
valueHandler(value, language) {
|
|
||||||
let tarValue = value || '';
|
|
||||||
if (language === 'json') {
|
|
||||||
if (value && typeof value === 'object') {
|
|
||||||
tarValue = JSON.stringify(value, null, 2);
|
|
||||||
} else if (value && typeof value === 'string') {
|
|
||||||
try {
|
|
||||||
let ret = this.toJson(value);
|
|
||||||
if (!ret.error) tarValue = JSON.stringify(ret.value, null, 2);
|
|
||||||
} catch (err) {}
|
|
||||||
}
|
|
||||||
} else if (language === 'function') {
|
|
||||||
if (typeof value === 'function') {
|
|
||||||
tarValue = value.toString();
|
|
||||||
}
|
|
||||||
if (tarValue && typeof tarValue === 'string') {
|
|
||||||
tarValue = js_beautify(tarValue, { indent_size: 2, indent_empty_lines: true });
|
|
||||||
}
|
|
||||||
} else if (language === 'object') {
|
|
||||||
//先转成对象,在进行序列化和格式化;
|
|
||||||
value = value || {};
|
|
||||||
if (value && typeof value === 'object') {
|
|
||||||
try {
|
|
||||||
tarValue = serialize(value, { unsafe: true });
|
|
||||||
tarValue = js_beautify(tarValue, { indent_size: 2, indent_empty_lines: true });
|
|
||||||
} catch (err) {}
|
|
||||||
} else if (typeof value === 'string') {
|
|
||||||
try {
|
|
||||||
let ret = this.resultHandler(value, 'object');
|
|
||||||
tarValue = ret.error ? ret.value : serialize(ret.value, { unsafe: true });
|
|
||||||
tarValue = js_beautify(tarValue, { indent_size: 2, indent_empty_lines: true });
|
|
||||||
} catch (err) {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return tarValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
//结果处理
|
|
||||||
resultHandler(value, language) {
|
|
||||||
let ret = { value };
|
|
||||||
if (language === 'json') {
|
|
||||||
ret = this.toJson(value);
|
|
||||||
} else if (language === 'object') {
|
|
||||||
ret = this.toObject(value);
|
|
||||||
} else if (language === 'function') {
|
|
||||||
ret = this.toFunction(value);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
//设置全屏时的动作
|
|
||||||
fullScreen() {
|
|
||||||
if (!this.editorRef) return;
|
|
||||||
//还原到原来位置;
|
|
||||||
this.position = this.editor.getPosition();
|
|
||||||
if (this.state.isFullScreen) {
|
|
||||||
if (this.editorParentNode) {
|
|
||||||
if (this.editorParentNode.firstChild) {
|
|
||||||
this.editorParentNode.insertBefore(this.editorNode, this.editorParentNode.firstChild);
|
|
||||||
} else {
|
|
||||||
this.editorParentNode.appendChild(this.editorNode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
document.body.appendChild(this.editorNode);
|
|
||||||
}
|
|
||||||
let nextFs = !this.state.isFullScreen;
|
|
||||||
this.isFullScreenAction = true; //记录是全屏幕操作
|
|
||||||
this.setState(
|
|
||||||
{
|
|
||||||
isFullScreen: nextFs
|
|
||||||
},
|
|
||||||
() => {
|
|
||||||
this.editor.updateOptions(nextFs ? this.fullScreenOptions : this.options);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
//美化代码
|
|
||||||
format() {
|
|
||||||
if (!this.editor) return;
|
|
||||||
if (/^\$_obj?\{.*?\}$/m.test(this.editor.getValue())) return;
|
|
||||||
if (this.props.language === 'json' || this.props.language === 'object' || this.props.language === 'function') {
|
|
||||||
let tarValue = js_beautify(this.editor.getValue(), { indent_size: 2 });
|
|
||||||
this.editor.setValue(tarValue);
|
|
||||||
} else if (this.props.language === 'less' || this.props.language === 'css' || this.props.language === 'scss') {
|
|
||||||
let tarValue = css_beautify(this.editor.getValue(), { indent_size: 2 });
|
|
||||||
this.editor.setValue(tarValue);
|
|
||||||
} else {
|
|
||||||
this.editor.getAction('editor.action.formatDocument').run();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//校验是否是json
|
|
||||||
toJson(value) {
|
|
||||||
try {
|
|
||||||
let obj = new Function(`'use strict'; return ${value.replace(/[\r\n\t]/g, '')}`)();
|
|
||||||
if (typeof obj === 'object' && obj) {
|
|
||||||
let tarValue = new Function(`'use strict'; return ${value}`)();
|
|
||||||
return { value: JSON.parse(JSON.stringify(tarValue)) };
|
|
||||||
}
|
|
||||||
return { error: this.i18n('jsonIllegal'), value };
|
|
||||||
} catch (err) {
|
|
||||||
return { error: err, value };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//校验是否为object对象
|
|
||||||
toObject(value) {
|
|
||||||
try {
|
|
||||||
let obj = new Function(`'use strict';return ${value}`)();
|
|
||||||
if (obj && typeof obj === 'object') {
|
|
||||||
if (jsonuri.isCircular(obj)) return { error: this.i18n('circularRef'), value };
|
|
||||||
return { value: obj };
|
|
||||||
} else {
|
|
||||||
return { error: this.i18n('objectIllegal'), value };
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
return { error: err, value };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//校验是否为function
|
|
||||||
toFunction(value) {
|
|
||||||
try {
|
|
||||||
let fun = new Function(`'use strict';return ${value}`)();
|
|
||||||
if (fun && typeof fun === 'function') {
|
|
||||||
return { value: fun };
|
|
||||||
} else {
|
|
||||||
return { error: this.i18n('functionIllegal'), value };
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
return { error: err, value };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//注册api和代码片段
|
|
||||||
registerApiAndSnippet(monaco) {
|
|
||||||
if (registerApiAndSnippetStatus) return;
|
|
||||||
registerApiAndSnippetStatus = true;
|
|
||||||
//注册this.提示的方法;
|
|
||||||
let thisSuggestions = [];
|
|
||||||
Snippets.map(item => {
|
|
||||||
if (!item.label || !item.kind || !item.insertText) return;
|
|
||||||
let tarItem = Object.assign(item, {
|
|
||||||
label: item.label,
|
|
||||||
kind: monaco.languages.CompletionItemKind[item.kind],
|
|
||||||
insertText: item.insertText
|
|
||||||
});
|
|
||||||
if (item.insertTextRules)
|
|
||||||
tarItem.insertTextRules = monaco.languages.CompletionItemInsertTextRule[item.insertTextRules];
|
|
||||||
thisSuggestions.push(tarItem);
|
|
||||||
});
|
|
||||||
monaco.languages.registerCompletionItemProvider('javascript', {
|
|
||||||
provideCompletionItems: (model, position) => {
|
|
||||||
let textUntilPosition = model.getValueInRange({
|
|
||||||
startLineNumber: position.lineNumber,
|
|
||||||
startColumn: 1,
|
|
||||||
endLineNumber: position.lineNumber,
|
|
||||||
endColumn: position.column
|
|
||||||
});
|
|
||||||
let match = textUntilPosition.match(/(^this\.)|(\sthis\.)/);
|
|
||||||
let suggestions = match ? thisSuggestions : [];
|
|
||||||
return { suggestions: suggestions };
|
|
||||||
},
|
|
||||||
triggerCharacters: ['.']
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class Title extends Component<{ title: TitleContent; onClick?: () => void }> {
|
|
||||||
static defaultProps = {
|
|
||||||
locale: 'zh-CN',
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const self = this;
|
|
||||||
const { locale, messages, id, value, onChange, __parent = {}, rules, objectButtonProps, ...restProps } = this.props;
|
|
||||||
let tarRestProps = { ...restProps };
|
|
||||||
let tarObjProps = { ...objectButtonProps };
|
|
||||||
tarObjProps.className = 'luna-monaco-button';
|
|
||||||
if (tarRestProps['data-meta']) {
|
|
||||||
delete tarRestProps['data-meta'];
|
|
||||||
tarObjProps['data-meta'] = 'Field';
|
|
||||||
}
|
|
||||||
tarObjProps.id = id;
|
|
||||||
tarObjProps.value = value;
|
|
||||||
tarObjProps.onChange = onChange;
|
|
||||||
let tarRule = [];
|
|
||||||
//判断,如果是json,function, object等类型,自动追加校验规则;
|
|
||||||
if (tarRestProps.language && ['json', 'function', 'object'].includes(tarRestProps.language)) {
|
|
||||||
if (['json', 'object'].includes(tarRestProps.language)) {
|
|
||||||
tarRule.push({
|
|
||||||
validator: function(rule, value, callback) {
|
|
||||||
if (typeof value !== 'object') {
|
|
||||||
callback(self.i18n('formatError'));
|
|
||||||
} else {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
tarRule.push({
|
|
||||||
validator: function(rule, value, callback) {
|
|
||||||
if (typeof value !== 'function') {
|
|
||||||
callback(self.i18n('formatError'));
|
|
||||||
} else {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (rules && Array.isArray(rules) && rules.length) {
|
|
||||||
tarRule = tarRule.concat(rules);
|
|
||||||
}
|
|
||||||
if (__parent && __parent.rules) {
|
|
||||||
tarRule = tarRule.concat(__parent.rules);
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<ObjectButton
|
|
||||||
locale={locale}
|
|
||||||
messages={messages}
|
|
||||||
{...tarObjProps}
|
|
||||||
__parent={__parent}
|
|
||||||
>
|
|
||||||
<FormItem name="nrs_temp_field" rules={tarRule}>
|
|
||||||
<MonacoEditorDefaultView {...tarRestProps} />
|
|
||||||
</FormItem>
|
|
||||||
</ObjectButton>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,93 +0,0 @@
|
|||||||
// mixin
|
|
||||||
.lowcode-setter-mixin > * {
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
.lowcode-setter-mixin {
|
|
||||||
width: 86%;
|
|
||||||
}
|
|
||||||
.lowcode-setter-mixin .next-input {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
.lowcode-setter-mixin .next-select-trigger {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
// function
|
|
||||||
:global {
|
|
||||||
.nrs-monaco-form {
|
|
||||||
.next-form-item:last-child {
|
|
||||||
margin: 0 !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.monaco-editor-wrap {
|
|
||||||
min-height: 300px;
|
|
||||||
.monaco_fullscreen_icon {
|
|
||||||
position: absolute;
|
|
||||||
line-height: 1;
|
|
||||||
z-index: 7;
|
|
||||||
color: #ddd;
|
|
||||||
&:hover {
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.btns-eare {
|
|
||||||
text-align: left;
|
|
||||||
line-height: initial;
|
|
||||||
margin-top: 5px;
|
|
||||||
// button{
|
|
||||||
// margin-right: 10px;
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
&.monaco-nofullscreen {
|
|
||||||
position: relative !important;
|
|
||||||
.monaco_fullscreen_icon {
|
|
||||||
position: absolute;
|
|
||||||
top: 5px;
|
|
||||||
right: 5px;
|
|
||||||
line-height: 1;
|
|
||||||
z-index: 7;
|
|
||||||
i:before {
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&.monaco-fullscreen {
|
|
||||||
position: fixed !important;
|
|
||||||
height: 100% !important;
|
|
||||||
width: 100% !important;
|
|
||||||
border: 0;
|
|
||||||
margin: 0;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
z-index: 1001;
|
|
||||||
overflow: hidden;
|
|
||||||
.monaco_fullscreen_icon {
|
|
||||||
top: 10px;
|
|
||||||
right: 10px;
|
|
||||||
i:before {
|
|
||||||
font-size: 24px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.luna-monaco-button button {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
.luna-monaco-button-dialog {
|
|
||||||
.next-dialog-body {
|
|
||||||
padding: 0;
|
|
||||||
.next-form-item {
|
|
||||||
height: 100%;
|
|
||||||
margin-bottom: 0;
|
|
||||||
.next-form-item-control,
|
|
||||||
.next-form-item-control > div {
|
|
||||||
height: 100% !important;
|
|
||||||
}
|
|
||||||
.next-form-item-help {
|
|
||||||
position: absolute;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -2,6 +2,8 @@ import { registerSetter } from '@ali/lowcode-globals';
|
|||||||
import { DatePicker, Input, Radio, Select, Switch, NumberPicker } from '@alifd/next';
|
import { DatePicker, Input, Radio, Select, Switch, NumberPicker } from '@alifd/next';
|
||||||
import ExpressionSetter from './expression-setter';
|
import ExpressionSetter from './expression-setter';
|
||||||
import MixinSetter from './mixin-setter';
|
import MixinSetter from './mixin-setter';
|
||||||
|
import ColorSetter from './color-setter';
|
||||||
|
import JsonSetter from './json-setter';
|
||||||
import EventsSetter from './events-setter';
|
import EventsSetter from './events-setter';
|
||||||
import StyleSetter from './style-setter';
|
import StyleSetter from './style-setter';
|
||||||
|
|
||||||
@ -49,6 +51,8 @@ const builtinSetters = {
|
|||||||
DateRangeSetter,
|
DateRangeSetter,
|
||||||
EventsSetter,
|
EventsSetter,
|
||||||
StyleSetter,
|
StyleSetter,
|
||||||
|
ColorSetter,
|
||||||
|
JsonSetter,
|
||||||
};
|
};
|
||||||
|
|
||||||
export function registerSetters() {
|
export function registerSetters() {
|
||||||
|
|||||||
@ -1,301 +0,0 @@
|
|||||||
import React, { PureComponent } from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import classNames from 'classnames';
|
|
||||||
import { Dropdown, Button, Menu, Icon, Input, NumberPicker, Switch, Select, Radio, DatePicker } from '@alifd/next';
|
|
||||||
|
|
||||||
import { isJSExpression, generateI18n } from './locale/utils';
|
|
||||||
import Expression from './expression-setter';
|
|
||||||
import zhCN from './locale/zh-CN';
|
|
||||||
import './index.scss';
|
|
||||||
|
|
||||||
const { Group: RadioGroup } = Radio;
|
|
||||||
// const isJSExpression = (obj) => {
|
|
||||||
// if(typeof obj === 'object' && obj.type === 'JSExpression') {
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
|
|
||||||
export default class Mixin extends PureComponent {
|
|
||||||
static displayName = 'Mixin';
|
|
||||||
static propTypes = {
|
|
||||||
locale: PropTypes.string,
|
|
||||||
messages: PropTypes.object,
|
|
||||||
defaultType: PropTypes.string,
|
|
||||||
types: PropTypes.arrayOf(PropTypes.string),
|
|
||||||
onlyChangeType: PropTypes.bool,
|
|
||||||
inputProps: PropTypes.object,
|
|
||||||
expressionProps: PropTypes.object,
|
|
||||||
monacoEditorProps: PropTypes.object,
|
|
||||||
switchProps: PropTypes.object,
|
|
||||||
selectProps: PropTypes.object,
|
|
||||||
radioGroupProps: PropTypes.object,
|
|
||||||
};
|
|
||||||
static defaultProps = {
|
|
||||||
locale: 'zh-CN',
|
|
||||||
messages: zhCN,
|
|
||||||
types: ['StringSetter', 'ExpressionSetter', 'NumberSetter', 'BoolSetter', 'SelectSetter', 'RadioGroupSetter'],
|
|
||||||
};
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
let type = judgeTypeHandler(props, {});
|
|
||||||
this.i18n = generateI18n(props.locale, props.messages);
|
|
||||||
this.state = {
|
|
||||||
preType: type,
|
|
||||||
type
|
|
||||||
};
|
|
||||||
}
|
|
||||||
static getDerivedStateFromProps(props, state) {
|
|
||||||
if ('value' in props) {
|
|
||||||
let curType = judgeTypeHandler(props, state);
|
|
||||||
if (curType !== state.preType) {
|
|
||||||
return {
|
|
||||||
type: curType
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
changeType(type) {
|
|
||||||
if (typeof type === 'object' || type === this.state.type) return;
|
|
||||||
let { onlyChangeType, value, onChange } = this.props;
|
|
||||||
if (onlyChangeType) {
|
|
||||||
this.setState({ type });
|
|
||||||
onChange && onChange(value);
|
|
||||||
} else {
|
|
||||||
let newValue = undefined;
|
|
||||||
if (this.typeMap[type]['props']) {
|
|
||||||
if (this.typeMap[type]['props']['value'] !== undefined) {
|
|
||||||
newValue = this.typeMap[type]['props']['value'];
|
|
||||||
} else if (this.typeMap[type]['props']['defaultValue'] !== undefined) {
|
|
||||||
newValue = this.typeMap[type]['props']['defaultValue'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (type === 'BoolSetter' && newValue === undefined) {
|
|
||||||
newValue = false; //给切换到switch默认值为false
|
|
||||||
}
|
|
||||||
this.setState({ type });
|
|
||||||
onChange && onChange(newValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
render() {
|
|
||||||
const {
|
|
||||||
style = {},
|
|
||||||
className,
|
|
||||||
locale,
|
|
||||||
messages,
|
|
||||||
types = [],
|
|
||||||
defaultType,
|
|
||||||
// inputProps,
|
|
||||||
// expressionProps,
|
|
||||||
// monacoEditorProps,
|
|
||||||
// numberPickerProps,
|
|
||||||
// switchProps,
|
|
||||||
// selectProps,
|
|
||||||
// radioGroupProps,
|
|
||||||
...restProps
|
|
||||||
} = this.props;
|
|
||||||
this.typeMap = {
|
|
||||||
StringSetter: {
|
|
||||||
label: this.i18n('input'),
|
|
||||||
component: Input,
|
|
||||||
// props: inputProps
|
|
||||||
},
|
|
||||||
ExpressionSetter: {
|
|
||||||
label: this.i18n('expression'),
|
|
||||||
component: Expression,
|
|
||||||
// props: expressionProps
|
|
||||||
},
|
|
||||||
// MonacoEditor: {
|
|
||||||
// label: this.i18n('monacoEditor'),
|
|
||||||
// component: MonacoEditor,
|
|
||||||
// props: monacoEditorProps
|
|
||||||
// },
|
|
||||||
NumberSetter: {
|
|
||||||
label: this.i18n('numberPicker'),
|
|
||||||
component: NumberPicker,
|
|
||||||
},
|
|
||||||
BoolSetter: {
|
|
||||||
label: this.i18n('bool'),
|
|
||||||
component: Switch,
|
|
||||||
},
|
|
||||||
SelectSetter: {
|
|
||||||
label: this.i18n('select'),
|
|
||||||
component: Select,
|
|
||||||
},
|
|
||||||
RadioGroupSetter: {
|
|
||||||
label: this.i18n('radio'),
|
|
||||||
component: RadioGroup,
|
|
||||||
},
|
|
||||||
TextAreaSetter: {
|
|
||||||
label: this.i18n('textarea'),
|
|
||||||
component: Input.TextArea,
|
|
||||||
},
|
|
||||||
DateSetter: {
|
|
||||||
label: this.i18n('date'),
|
|
||||||
component: DatePicker,
|
|
||||||
},
|
|
||||||
DateYearSetter: {
|
|
||||||
label: this.i18n('dateYear'),
|
|
||||||
component: DatePicker,
|
|
||||||
},
|
|
||||||
DateMonthSetter: {
|
|
||||||
label: this.i18n('dateMonth'),
|
|
||||||
component: DatePicker,
|
|
||||||
},
|
|
||||||
DateRangeSetter: {
|
|
||||||
label: this.i18n('dateRange'),
|
|
||||||
component: DatePicker,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let realTypes = [];
|
|
||||||
types.forEach( el => {
|
|
||||||
const { name, props } = el;
|
|
||||||
if (this.typeMap[name]) {
|
|
||||||
this.typeMap[name].props = props;
|
|
||||||
realTypes.push(name);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
let moreBtnNode = null;
|
|
||||||
//如果只有2种,且有变量表达式,则直接展示变量按钮
|
|
||||||
if (realTypes.length > 1) {
|
|
||||||
let isTwoType = !!(realTypes.length === 2 && ~realTypes.indexOf('ExpressionSetter'));
|
|
||||||
let btnProps = {
|
|
||||||
size: 'small',
|
|
||||||
text: true,
|
|
||||||
style: {
|
|
||||||
position: 'absolute',
|
|
||||||
left: '100%',
|
|
||||||
top: 0,
|
|
||||||
bottom: 0,
|
|
||||||
margin: 'auto 0 auto 8px',
|
|
||||||
padding: 0,
|
|
||||||
width: 16,
|
|
||||||
height: 16,
|
|
||||||
lineHeight: '16px',
|
|
||||||
textAlign: 'center'
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if (isTwoType) {
|
|
||||||
btnProps.onClick = this.changeType.bind(this, realTypes.indexOf(this.state.type) ? realTypes[0] : realTypes[1]);
|
|
||||||
}
|
|
||||||
let triggerNode = (
|
|
||||||
<Button {...btnProps} size={isTwoType ? 'large' : 'small'}>
|
|
||||||
<Icon type={isTwoType ? 'edit' : 'ellipsis'} />
|
|
||||||
</Button>
|
|
||||||
);
|
|
||||||
if (isTwoType) {
|
|
||||||
moreBtnNode = triggerNode;
|
|
||||||
} else {
|
|
||||||
let MenuItems = [];
|
|
||||||
realTypes.map(type => {
|
|
||||||
if (this.typeMap[type]) {
|
|
||||||
MenuItems.push(<Menu.Item key={type}>{this.typeMap[type]['label']}</Menu.Item>);
|
|
||||||
} else {
|
|
||||||
console.error(
|
|
||||||
this.i18n('typeError', {
|
|
||||||
type
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
let MenuNode = (
|
|
||||||
<Menu
|
|
||||||
selectMode="single"
|
|
||||||
hasSelectedIcon={false}
|
|
||||||
selectedKeys={this.state.type}
|
|
||||||
onItemClick={this.changeType.bind(this)}
|
|
||||||
>
|
|
||||||
{MenuItems}
|
|
||||||
</Menu>
|
|
||||||
);
|
|
||||||
|
|
||||||
moreBtnNode = (
|
|
||||||
<Dropdown trigger={triggerNode} triggerType="click">
|
|
||||||
{MenuNode}
|
|
||||||
</Dropdown>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let TargetNode = this.typeMap[this.state.type] ? this.typeMap[this.state.type]['component'] : 'div';
|
|
||||||
let targetProps = this.typeMap[this.state.type] ? this.typeMap[this.state.type]['props'] : {};
|
|
||||||
|
|
||||||
// 特殊处理Switch的值
|
|
||||||
if (['BoolSetter', 'RadioGroupSetter'].includes(this.state.type)) {
|
|
||||||
restProps.checked = this.props.checked !== undefined ? this.props.checked : this.props.value;
|
|
||||||
}
|
|
||||||
//判断如果Mixin内部有设置onChange, 则同时触发2处onChange
|
|
||||||
if (targetProps && targetProps.onChange && typeof targetProps.onChange === 'function') {
|
|
||||||
let tarOnChange = targetProps.onChange;
|
|
||||||
targetProps.onChange = function() {
|
|
||||||
tarOnChange.apply(null, arguments);
|
|
||||||
restProps.onChange && restProps.onChange.apply(null, arguments);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
let tarStyle = { position: 'relative', ...style };
|
|
||||||
let classes = classNames(className, 'lowcode-setter-mixin');
|
|
||||||
return (
|
|
||||||
<div style={tarStyle} className={classes}>
|
|
||||||
<TargetNode {...restProps} {...targetProps} />
|
|
||||||
{moreBtnNode}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 判断值类型
|
|
||||||
function judgeTypeHandler(props, state) {
|
|
||||||
let { defaultType, types, value } = props;
|
|
||||||
let selectProps: { dataSource: any[]; };
|
|
||||||
let radioGroupProps: { dataSource: any[]; };
|
|
||||||
let typeKeys: any[] = [];
|
|
||||||
types.forEach( el => {
|
|
||||||
typeKeys.push(el.name);
|
|
||||||
})
|
|
||||||
|
|
||||||
types.forEach((el: { name: string; props: {}; }) => {
|
|
||||||
if (el.name === 'SelectSetter') {selectProps === el.props;}
|
|
||||||
if (el.name === 'RadioGroupSetter') {radioGroupProps === el.props;}
|
|
||||||
})
|
|
||||||
if (!defaultType || !typeKeys) return;
|
|
||||||
// 如果defaultType不在typeKeys列表中,默认返回typeKeys的第一项
|
|
||||||
if (!typeKeys.includes(defaultType)) return typeKeys[0];
|
|
||||||
if (isJSExpression(value)) return 'ExpressionSetter';
|
|
||||||
if (value && typeof value === 'string') {
|
|
||||||
if (~typeKeys.indexOf('SelectSetter') && selectProps && selectProps.dataSource) {
|
|
||||||
let hasOption = selectProps.dataSource.some(item => {
|
|
||||||
if (typeof item === 'string' && item === value) return true;
|
|
||||||
if (typeof item === 'object' && item.value === value) return true;
|
|
||||||
});
|
|
||||||
if (hasOption) return 'SelectSetter';
|
|
||||||
}
|
|
||||||
if (~typeKeys.indexOf('RadioGroupSetter') && radioGroupProps && radioGroupProps.dataSource) {
|
|
||||||
let hasOption = radioGroupProps.dataSource.some(item => {
|
|
||||||
if (typeof item === 'object' && item.value === value) return true;
|
|
||||||
});
|
|
||||||
if (hasOption) return 'RadioGroupSetter';
|
|
||||||
}
|
|
||||||
if (~typeKeys.indexOf('StringSetter')) return 'StringSetter';
|
|
||||||
}
|
|
||||||
if (typeof value === 'number') {
|
|
||||||
if (~typeKeys.indexOf('SelectSetter') && selectProps && selectProps.dataSource) {
|
|
||||||
let hasOption = selectProps.dataSource.some(item => {
|
|
||||||
if (typeof item === 'object' && item.value === value) return true;
|
|
||||||
});
|
|
||||||
if (hasOption) return 'Select';
|
|
||||||
}
|
|
||||||
if (~typeKeys.indexOf('RadioGroupSetter') && radioGroupProps && radioGroupProps.dataSource) {
|
|
||||||
let hasOption = radioGroupProps.dataSource.some(item => {
|
|
||||||
if (typeof item === 'object' && item.value === value) return true;
|
|
||||||
});
|
|
||||||
if (hasOption) return 'RadioGroupSetter';
|
|
||||||
}
|
|
||||||
if (~typeKeys.indexOf('NumberSetter')) return 'NumberSetter';
|
|
||||||
}
|
|
||||||
if (~typeKeys.indexOf('NumberSetter') && typeof value === 'number') return 'NumberSetter';
|
|
||||||
if (~typeKeys.indexOf('BoolSetter') && (value === false || value === true)) return 'BoolSetter';
|
|
||||||
if (Array.isArray(value)) {
|
|
||||||
if (~typeKeys.indexOf('SelectSetter') && typeof value[0] === 'string') return 'SelectSetter';
|
|
||||||
}
|
|
||||||
return state.type || defaultType;
|
|
||||||
}
|
|
||||||
@ -11,120 +11,3 @@
|
|||||||
.lowcode-setter-mixin .next-select-trigger {
|
.lowcode-setter-mixin .next-select-trigger {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
// json-setter
|
|
||||||
// :global {
|
|
||||||
.nrs-monaco-form {
|
|
||||||
.next-form-item:last-child {
|
|
||||||
margin: 0 !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.monaco-editor-wrap {
|
|
||||||
.luna-monaco-button .next-icon-first {
|
|
||||||
height: 26px;
|
|
||||||
}
|
|
||||||
.monaco_fullscreen_icon {
|
|
||||||
position: absolute;
|
|
||||||
line-height: 1;
|
|
||||||
z-index: 7;
|
|
||||||
color: #ddd;
|
|
||||||
&:hover {
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.btns-eare {
|
|
||||||
text-align: left;
|
|
||||||
line-height: initial;
|
|
||||||
margin-top: 5px;
|
|
||||||
// button{
|
|
||||||
// margin-right: 10px;
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
&.monaco-nofullscreen {
|
|
||||||
position: relative !important;
|
|
||||||
.monaco_fullscreen_icon {
|
|
||||||
position: absolute;
|
|
||||||
top: 5px;
|
|
||||||
right: 5px;
|
|
||||||
line-height: 1;
|
|
||||||
z-index: 7;
|
|
||||||
i:before {
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&.monaco-fullscreen {
|
|
||||||
position: fixed !important;
|
|
||||||
height: 100% !important;
|
|
||||||
width: 100% !important;
|
|
||||||
border: 0;
|
|
||||||
margin: 0;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
z-index: 1001;
|
|
||||||
overflow: hidden;
|
|
||||||
.monaco_fullscreen_icon {
|
|
||||||
top: 10px;
|
|
||||||
right: 10px;
|
|
||||||
i:before {
|
|
||||||
font-size: 24px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.luna-monaco-button button {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
.luna-monaco-button-dialog {
|
|
||||||
.next-dialog-body {
|
|
||||||
padding: 0;
|
|
||||||
.next-form-item {
|
|
||||||
height: 100%;
|
|
||||||
margin-bottom: 0;
|
|
||||||
.next-form-item-control,
|
|
||||||
.next-form-item-control > div {
|
|
||||||
height: 100% !important;
|
|
||||||
}
|
|
||||||
.next-form-item-help {
|
|
||||||
position: absolute;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// }
|
|
||||||
// color-setter
|
|
||||||
.lowcode-color-box {
|
|
||||||
margin-right: -5px;
|
|
||||||
padding: 3px 0 3px 3px;
|
|
||||||
width: 26px;
|
|
||||||
height: 26px;
|
|
||||||
display: inline-block;
|
|
||||||
div {
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
border: 1px solid #ddd;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.next-balloon-normal.lowcode-color-content {
|
|
||||||
padding: 0;
|
|
||||||
background: #ffffff;
|
|
||||||
border-radius: 0;
|
|
||||||
border: 1px solid #e5e5e5;
|
|
||||||
box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.1);
|
|
||||||
&:after {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.sketch-picker {
|
|
||||||
border-radius: 0 !important;
|
|
||||||
border: none !important;
|
|
||||||
box-shadow: none !important;
|
|
||||||
.flexbox-fix {
|
|
||||||
input {
|
|
||||||
width: 100% !important;
|
|
||||||
min-width: 30px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,22 +1,13 @@
|
|||||||
import React, { PureComponent } from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { Dropdown, Button, Menu, Icon, Input, NumberPicker, Switch, Select, Radio, DatePicker } from '@alifd/next';
|
import { Dropdown, Button, Menu, Icon } from '@alifd/next';
|
||||||
import MonacoEditor from '@ali/iceluna-comp-monaco-editor';
|
import { getSetter } from '@ali/lowcode-globals';
|
||||||
|
|
||||||
import { isJSExpression, generateI18n } from './locale/utils';
|
import { generateI18n } from './locale/utils';
|
||||||
import Expression from '../expression-setter';
|
|
||||||
import zhCN from './locale/zh-CN';
|
import zhCN from './locale/zh-CN';
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
|
|
||||||
const { Group: RadioGroup } = Radio;
|
|
||||||
// const isJSExpression = (obj) => {
|
|
||||||
// if(typeof obj === 'object' && obj.type === 'JSExpression') {
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
|
|
||||||
export default class Mixin extends PureComponent {
|
export default class Mixin extends PureComponent {
|
||||||
static displayName = 'Mixin';
|
static displayName = 'Mixin';
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
@ -24,7 +15,6 @@ export default class Mixin extends PureComponent {
|
|||||||
messages: PropTypes.object,
|
messages: PropTypes.object,
|
||||||
defaultType: PropTypes.string,
|
defaultType: PropTypes.string,
|
||||||
types: PropTypes.arrayOf(PropTypes.string),
|
types: PropTypes.arrayOf(PropTypes.string),
|
||||||
onlyChangeType: PropTypes.bool,
|
|
||||||
inputProps: PropTypes.object,
|
inputProps: PropTypes.object,
|
||||||
expressionProps: PropTypes.object,
|
expressionProps: PropTypes.object,
|
||||||
monacoEditorProps: PropTypes.object,
|
monacoEditorProps: PropTypes.object,
|
||||||
@ -35,41 +25,32 @@ export default class Mixin extends PureComponent {
|
|||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
locale: 'zh-CN',
|
locale: 'zh-CN',
|
||||||
messages: zhCN,
|
messages: zhCN,
|
||||||
types: ['StringSetter', 'ExpressionSetter', 'NumberSetter', 'BoolSetter', 'SelectSetter', 'RadioGroupSetter'],
|
types: [{
|
||||||
|
"name": "StringSetter",
|
||||||
|
"props": {}
|
||||||
|
}],
|
||||||
};
|
};
|
||||||
constructor(props) {
|
typeMap: any;
|
||||||
|
i18n: (key: any, values?: {}) => string | void | (string | void)[];
|
||||||
|
constructor(props: Readonly<{}>) {
|
||||||
super(props);
|
super(props);
|
||||||
let type = judgeTypeHandler(props, {});
|
let type = props.defaultType;// judgeTypeHandler(props, {});
|
||||||
this.i18n = generateI18n(props.locale, props.messages);
|
this.i18n = generateI18n(props.locale, props.messages);
|
||||||
this.state = {
|
this.state = {
|
||||||
preType: type,
|
preType: type,
|
||||||
type
|
type
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
static getDerivedStateFromProps(props, state) {
|
changeType(type: string) {
|
||||||
if ('value' in props) {
|
|
||||||
let curType = judgeTypeHandler(props, state);
|
|
||||||
if (curType !== state.preType) {
|
|
||||||
return {
|
|
||||||
type: curType
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
changeType(type) {
|
|
||||||
if (typeof type === 'object' || type === this.state.type) return;
|
if (typeof type === 'object' || type === this.state.type) return;
|
||||||
let { onlyChangeType, value, onChange } = this.props;
|
let { onChange } = this.props;
|
||||||
if (onlyChangeType) {
|
|
||||||
this.setState({ type });
|
|
||||||
onChange && onChange(value);
|
|
||||||
} else {
|
|
||||||
let newValue = undefined;
|
let newValue = undefined;
|
||||||
if (this.typeMap[type]['props']) {
|
const setterProps = this.typeMap[type]['props'];
|
||||||
if (this.typeMap[type]['props']['value'] !== undefined) {
|
if (setterProps) {
|
||||||
newValue = this.typeMap[type]['props']['value'];
|
if (setterProps.value !== undefined) {
|
||||||
} else if (this.typeMap[type]['props']['defaultValue'] !== undefined) {
|
newValue = setterProps.value;
|
||||||
newValue = this.typeMap[type]['props']['defaultValue'];
|
} else if (setterProps.defaultValue !== undefined) {
|
||||||
|
newValue = setterProps.defaultValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (type === 'BoolSetter' && newValue === undefined) {
|
if (type === 'BoolSetter' && newValue === undefined) {
|
||||||
@ -78,7 +59,6 @@ export default class Mixin extends PureComponent {
|
|||||||
this.setState({ type });
|
this.setState({ type });
|
||||||
onChange && onChange(newValue);
|
onChange && onChange(newValue);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
style = {},
|
style = {},
|
||||||
@ -87,75 +67,21 @@ export default class Mixin extends PureComponent {
|
|||||||
messages,
|
messages,
|
||||||
types = [],
|
types = [],
|
||||||
defaultType,
|
defaultType,
|
||||||
// inputProps,
|
|
||||||
// expressionProps,
|
|
||||||
// monacoEditorProps,
|
|
||||||
// numberPickerProps,
|
|
||||||
// switchProps,
|
|
||||||
// selectProps,
|
|
||||||
// radioGroupProps,
|
|
||||||
...restProps
|
...restProps
|
||||||
} = this.props;
|
} = this.props;
|
||||||
this.typeMap = {
|
this.typeMap = {};
|
||||||
StringSetter: {
|
let realTypes: any[] = [];
|
||||||
label: this.i18n('input'),
|
types.forEach( (el: { name: any; props: any; }) => {
|
||||||
component: Input,
|
|
||||||
// props: inputProps
|
|
||||||
},
|
|
||||||
ExpressionSetter: {
|
|
||||||
label: this.i18n('expression'),
|
|
||||||
component: Expression,
|
|
||||||
// props: expressionProps
|
|
||||||
},
|
|
||||||
// MonacoEditor: {
|
|
||||||
// label: this.i18n('monacoEditor'),
|
|
||||||
// component: MonacoEditor,
|
|
||||||
// props: monacoEditorProps
|
|
||||||
// },
|
|
||||||
NumberSetter: {
|
|
||||||
label: this.i18n('numberPicker'),
|
|
||||||
component: NumberPicker,
|
|
||||||
},
|
|
||||||
BoolSetter: {
|
|
||||||
label: this.i18n('bool'),
|
|
||||||
component: Switch,
|
|
||||||
},
|
|
||||||
SelectSetter: {
|
|
||||||
label: this.i18n('select'),
|
|
||||||
component: Select,
|
|
||||||
},
|
|
||||||
RadioGroupSetter: {
|
|
||||||
label: this.i18n('radio'),
|
|
||||||
component: RadioGroup,
|
|
||||||
},
|
|
||||||
TextAreaSetter: {
|
|
||||||
label: this.i18n('textarea'),
|
|
||||||
component: Input.TextArea,
|
|
||||||
},
|
|
||||||
DateSetter: {
|
|
||||||
label: this.i18n('date'),
|
|
||||||
component: DatePicker,
|
|
||||||
},
|
|
||||||
DateYearSetter: {
|
|
||||||
label: this.i18n('dateYear'),
|
|
||||||
component: DatePicker,
|
|
||||||
},
|
|
||||||
DateMonthSetter: {
|
|
||||||
label: this.i18n('dateMonth'),
|
|
||||||
component: DatePicker,
|
|
||||||
},
|
|
||||||
DateRangeSetter: {
|
|
||||||
label: this.i18n('dateRange'),
|
|
||||||
component: DatePicker,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let realTypes = [];
|
|
||||||
types.forEach( el => {
|
|
||||||
const { name, props } = el;
|
const { name, props } = el;
|
||||||
if (this.typeMap[name]) {
|
const Setter = getSetter(name);
|
||||||
this.typeMap[name].props = props;
|
if (Setter) {
|
||||||
realTypes.push(name);
|
this.typeMap[name] = {
|
||||||
|
label: name,
|
||||||
|
component: Setter.component,
|
||||||
|
props,
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
realTypes.push(name);
|
||||||
})
|
})
|
||||||
let moreBtnNode = null;
|
let moreBtnNode = null;
|
||||||
//如果只有2种,且有变量表达式,则直接展示变量按钮
|
//如果只有2种,且有变量表达式,则直接展示变量按钮
|
||||||
@ -188,7 +114,7 @@ export default class Mixin extends PureComponent {
|
|||||||
if (isTwoType) {
|
if (isTwoType) {
|
||||||
moreBtnNode = triggerNode;
|
moreBtnNode = triggerNode;
|
||||||
} else {
|
} else {
|
||||||
let MenuItems = [];
|
let MenuItems: {} | null | undefined = [];
|
||||||
realTypes.map(type => {
|
realTypes.map(type => {
|
||||||
if (this.typeMap[type]) {
|
if (this.typeMap[type]) {
|
||||||
MenuItems.push(<Menu.Item key={type}>{this.typeMap[type]['label']}</Menu.Item>);
|
MenuItems.push(<Menu.Item key={type}>{this.typeMap[type]['label']}</Menu.Item>);
|
||||||
@ -218,85 +144,16 @@ export default class Mixin extends PureComponent {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let TargetNode = this.typeMap[this.state.type] ? this.typeMap[this.state.type]['component'] : 'div';
|
let TargetNode = this.typeMap[this.state.type]['component'] || 'div';
|
||||||
let targetProps = this.typeMap[this.state.type] ? this.typeMap[this.state.type]['props'] : {};
|
let targetProps = this.typeMap[this.state.type]['props'] || {};
|
||||||
|
|
||||||
// 特殊处理Switch的值
|
|
||||||
if (['BoolSetter', 'RadioGroupSetter'].includes(this.state.type)) {
|
|
||||||
restProps.checked = this.props.checked !== undefined ? this.props.checked : this.props.value;
|
|
||||||
}
|
|
||||||
//判断如果Mixin内部有设置onChange, 则同时触发2处onChange
|
|
||||||
if (targetProps && targetProps.onChange && typeof targetProps.onChange === 'function') {
|
|
||||||
let tarOnChange = targetProps.onChange;
|
|
||||||
targetProps.onChange = function() {
|
|
||||||
tarOnChange.apply(null, arguments);
|
|
||||||
restProps.onChange && restProps.onChange.apply(null, arguments);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
let tarStyle = { position: 'relative', ...style };
|
let tarStyle = { position: 'relative', ...style };
|
||||||
let classes = classNames(className, 'lowcode-setter-mixin');
|
let classes = classNames(className, 'lowcode-setter-mixin');
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={tarStyle} className={classes}>
|
<div style={tarStyle} className={classes} >
|
||||||
<TargetNode {...restProps} {...targetProps} />
|
<TargetNode {...restProps} {...targetProps} />
|
||||||
{moreBtnNode}
|
{moreBtnNode}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 判断值类型
|
|
||||||
function judgeTypeHandler(props, state) {
|
|
||||||
let { defaultType, types, value } = props;
|
|
||||||
let selectProps: { dataSource: any[]; };
|
|
||||||
let radioGroupProps: { dataSource: any[]; };
|
|
||||||
let typeKeys: any[] = [];
|
|
||||||
types.forEach( el => {
|
|
||||||
typeKeys.push(el.name);
|
|
||||||
})
|
|
||||||
|
|
||||||
types.forEach((el: { name: string; props: {}; }) => {
|
|
||||||
if (el.name === 'SelectSetter') {selectProps === el.props;}
|
|
||||||
if (el.name === 'RadioGroupSetter') {radioGroupProps === el.props;}
|
|
||||||
})
|
|
||||||
if (!defaultType || !typeKeys) return;
|
|
||||||
// 如果defaultType不在typeKeys列表中,默认返回typeKeys的第一项
|
|
||||||
if (!typeKeys.includes(defaultType)) return typeKeys[0];
|
|
||||||
if (isJSExpression(value)) return 'ExpressionSetter';
|
|
||||||
if (value && typeof value === 'string') {
|
|
||||||
if (~typeKeys.indexOf('SelectSetter') && selectProps && selectProps.dataSource) {
|
|
||||||
let hasOption = selectProps.dataSource.some(item => {
|
|
||||||
if (typeof item === 'string' && item === value) return true;
|
|
||||||
if (typeof item === 'object' && item.value === value) return true;
|
|
||||||
});
|
|
||||||
if (hasOption) return 'SelectSetter';
|
|
||||||
}
|
|
||||||
if (~typeKeys.indexOf('RadioGroupSetter') && radioGroupProps && radioGroupProps.dataSource) {
|
|
||||||
let hasOption = radioGroupProps.dataSource.some(item => {
|
|
||||||
if (typeof item === 'object' && item.value === value) return true;
|
|
||||||
});
|
|
||||||
if (hasOption) return 'RadioGroupSetter';
|
|
||||||
}
|
|
||||||
if (~typeKeys.indexOf('StringSetter')) return 'StringSetter';
|
|
||||||
}
|
|
||||||
if (typeof value === 'number') {
|
|
||||||
if (~typeKeys.indexOf('SelectSetter') && selectProps && selectProps.dataSource) {
|
|
||||||
let hasOption = selectProps.dataSource.some(item => {
|
|
||||||
if (typeof item === 'object' && item.value === value) return true;
|
|
||||||
});
|
|
||||||
if (hasOption) return 'Select';
|
|
||||||
}
|
|
||||||
if (~typeKeys.indexOf('RadioGroupSetter') && radioGroupProps && radioGroupProps.dataSource) {
|
|
||||||
let hasOption = radioGroupProps.dataSource.some(item => {
|
|
||||||
if (typeof item === 'object' && item.value === value) return true;
|
|
||||||
});
|
|
||||||
if (hasOption) return 'RadioGroupSetter';
|
|
||||||
}
|
|
||||||
if (~typeKeys.indexOf('NumberSetter')) return 'NumberSetter';
|
|
||||||
}
|
|
||||||
if (~typeKeys.indexOf('NumberSetter') && typeof value === 'number') return 'NumberSetter';
|
|
||||||
if (~typeKeys.indexOf('BoolSetter') && (value === false || value === true)) return 'BoolSetter';
|
|
||||||
if (Array.isArray(value)) {
|
|
||||||
if (~typeKeys.indexOf('SelectSetter') && typeof value[0] === 'string') return 'SelectSetter';
|
|
||||||
}
|
|
||||||
return state.type || defaultType;
|
|
||||||
}
|
|
||||||
|
|||||||
@ -1,242 +0,0 @@
|
|||||||
export default [
|
|
||||||
{
|
|
||||||
label: 'constants',
|
|
||||||
kind: 'Class',
|
|
||||||
insertText: 'constants',
|
|
||||||
detail: '应用全局常量',
|
|
||||||
documentation: '应用范围定义的通用常量'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'utils',
|
|
||||||
kind: 'Class',
|
|
||||||
insertText: 'utils',
|
|
||||||
detail: '应用全局公共函数',
|
|
||||||
documentation: '应用范围扩展的公共函数'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'state',
|
|
||||||
kind: 'Enum',
|
|
||||||
insertText: 'state',
|
|
||||||
detail: '当前所在容器组件内部状态',
|
|
||||||
documentation: 'React Class内部状态state'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'setState',
|
|
||||||
kind: 'Function',
|
|
||||||
insertText: 'setState({\n\t$0\n})',
|
|
||||||
insertTextRules: 'InsertAsSnippet',
|
|
||||||
detail: '设置当前所在容器组件的state数据',
|
|
||||||
documentation: '原生React方法,会自动更新组件视图'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'reloadDataSource',
|
|
||||||
kind: 'Function',
|
|
||||||
insertText: 'reloadDataSource(${1:${2:namespace}, ${3:false}, ${4:callback}})',
|
|
||||||
insertTextRules: 'InsertAsSnippet',
|
|
||||||
detail: '刷新当前所在的容器组件',
|
|
||||||
documentation: '触发当前所在的容器组件,重新发送异步请求,并用最新数据更新视图'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'location',
|
|
||||||
kind: 'Class',
|
|
||||||
insertText: 'location',
|
|
||||||
detail: '路由解析对象'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'location.query',
|
|
||||||
kind: 'Value',
|
|
||||||
insertText: 'location.query.${1:xxxx}',
|
|
||||||
insertTextRules: 'InsertAsSnippet',
|
|
||||||
detail: '从路由解析对象中获取参数信息'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'history',
|
|
||||||
kind: 'Class',
|
|
||||||
insertText: 'history',
|
|
||||||
detail: '路由历史对象'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'React',
|
|
||||||
kind: 'Keyword',
|
|
||||||
insertText: 'React',
|
|
||||||
detail: 'React对象'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'ReactDOM',
|
|
||||||
kind: 'Keyword',
|
|
||||||
insertText: 'ReactDOM',
|
|
||||||
detail: 'ReactDom对象'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'ReactDOM.findDOMNode',
|
|
||||||
kind: 'Function',
|
|
||||||
insertText: 'ReactDOM.findDOMNode(${1:this.refs.xxxx})',
|
|
||||||
insertTextRules: 'InsertAsSnippet',
|
|
||||||
detail: 'ReactDom查找真实dom node'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Dialog.alert',
|
|
||||||
kind: 'Method',
|
|
||||||
insertText: [
|
|
||||||
'Dialog.alert({',
|
|
||||||
"\tcontent: '${1:Alert content}',",
|
|
||||||
"\ttitle: '${2:Title}',",
|
|
||||||
'\tonOk: () => {',
|
|
||||||
'\t\t$3',
|
|
||||||
'\t}',
|
|
||||||
'})'
|
|
||||||
].join('\n'),
|
|
||||||
insertTextRules: 'InsertAsSnippet',
|
|
||||||
detail: 'alert弹框 By Fusion'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Dialog.confirm',
|
|
||||||
kind: 'Method',
|
|
||||||
insertText: [
|
|
||||||
'Dialog.confirm({',
|
|
||||||
"\tcontent: '${1:Confirm content}',",
|
|
||||||
"\ttitle: '${2:Title}',",
|
|
||||||
'\tonOk: () => {',
|
|
||||||
'\t\t$3',
|
|
||||||
'\t},',
|
|
||||||
'\tonCancel: () => {',
|
|
||||||
'\t\t$4',
|
|
||||||
'\t}',
|
|
||||||
'})'
|
|
||||||
].join('\n'),
|
|
||||||
insertTextRules: 'InsertAsSnippet',
|
|
||||||
detail: '确认弹出框 By Fusion'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Message.success',
|
|
||||||
kind: 'Method',
|
|
||||||
insertText: 'Message.success(${1:content})',
|
|
||||||
insertTextRules: 'InsertAsSnippet',
|
|
||||||
detail: '成功反馈提示 By Fusion'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Message.error',
|
|
||||||
kind: 'Method',
|
|
||||||
insertText: 'Message.error(${1:content})',
|
|
||||||
insertTextRules: 'InsertAsSnippet',
|
|
||||||
detail: '错误反馈提示 By Fusion'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Message.help',
|
|
||||||
kind: 'Method',
|
|
||||||
insertText: 'Message.help(${1:content})',
|
|
||||||
insertTextRules: 'InsertAsSnippet',
|
|
||||||
detail: '帮助反馈提示 By Fusion'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Message.loading',
|
|
||||||
kind: 'Method',
|
|
||||||
insertText: 'Message.loading(${1:content})',
|
|
||||||
insertTextRules: 'InsertAsSnippet',
|
|
||||||
detail: 'loading反馈提示 By Fusion'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Message.notice',
|
|
||||||
kind: 'Method',
|
|
||||||
insertText: 'Message.notice(${1:content})',
|
|
||||||
insertTextRules: 'InsertAsSnippet',
|
|
||||||
detail: '注意反馈提示 By Fusion'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Message.waining',
|
|
||||||
kind: 'Method',
|
|
||||||
insertText: 'Message.waining(${1:content})',
|
|
||||||
insertTextRules: 'InsertAsSnippet',
|
|
||||||
detail: '警告反馈提示 By Fusion'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Modal.confirm',
|
|
||||||
kind: 'Method',
|
|
||||||
insertText: [
|
|
||||||
'Modal.confirm({',
|
|
||||||
"\tcontent: '${1:Confirm content}',",
|
|
||||||
"\ttitle: '${2:Title}',",
|
|
||||||
'\tonOk: () => {',
|
|
||||||
'\t\t$3',
|
|
||||||
'\t},',
|
|
||||||
'\tonCancel: () => {',
|
|
||||||
'\t\t$4',
|
|
||||||
'\t}',
|
|
||||||
'})'
|
|
||||||
].join('\n'),
|
|
||||||
insertTextRules: 'InsertAsSnippet',
|
|
||||||
detail: '确认弹出框 By Antd'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Modal.info',
|
|
||||||
kind: 'Method',
|
|
||||||
insertText: [
|
|
||||||
'Modal.info({',
|
|
||||||
"\tcontent: '${1:Info content}',",
|
|
||||||
"\ttitle: '${2:Title}',",
|
|
||||||
'\tonOk: () => {',
|
|
||||||
'\t\t$3',
|
|
||||||
'\t},',
|
|
||||||
'\tonCancel: () => {',
|
|
||||||
'\t\t$4',
|
|
||||||
'\t}',
|
|
||||||
'})'
|
|
||||||
].join('\n'),
|
|
||||||
insertTextRules: 'InsertAsSnippet',
|
|
||||||
detail: '信息弹出框 By Antd'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Modal.success',
|
|
||||||
kind: 'Method',
|
|
||||||
insertText: [
|
|
||||||
'Modal.success({',
|
|
||||||
"\tcontent: '${1:Success content}',",
|
|
||||||
"\ttitle: '${2:Title}',",
|
|
||||||
'\tonOk: () => {',
|
|
||||||
'\t\t$3',
|
|
||||||
'\t},',
|
|
||||||
'\tonCancel: () => {',
|
|
||||||
'\t\t$4',
|
|
||||||
'\t}',
|
|
||||||
'})'
|
|
||||||
].join('\n'),
|
|
||||||
insertTextRules: 'InsertAsSnippet',
|
|
||||||
detail: '成功弹出框 By Antd'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Modal.error',
|
|
||||||
kind: 'Method',
|
|
||||||
insertText: [
|
|
||||||
'Modal.error({',
|
|
||||||
"\tcontent: '${1:Error content}',",
|
|
||||||
"\ttitle: '${2:Title}',",
|
|
||||||
'\tonOk: () => {',
|
|
||||||
'\t\t$3',
|
|
||||||
'\t},',
|
|
||||||
'\tonCancel: () => {',
|
|
||||||
'\t\t$4',
|
|
||||||
'\t}',
|
|
||||||
'})'
|
|
||||||
].join('\n'),
|
|
||||||
insertTextRules: 'InsertAsSnippet',
|
|
||||||
detail: '错误弹出框 By Antd'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Modal.warning',
|
|
||||||
kind: 'Method',
|
|
||||||
insertText: [
|
|
||||||
'Modal.warning({',
|
|
||||||
"\tcontent: '${1:Warning content}',",
|
|
||||||
"\ttitle: '${2:Title}',",
|
|
||||||
'\tonOk: () => {',
|
|
||||||
'\t\t$3',
|
|
||||||
'\t},',
|
|
||||||
'\tonCancel: () => {',
|
|
||||||
'\t\t$4',
|
|
||||||
'\t}',
|
|
||||||
'})'
|
|
||||||
].join('\n'),
|
|
||||||
insertTextRules: 'InsertAsSnippet',
|
|
||||||
detail: '警告弹出框 By Antd'
|
|
||||||
}
|
|
||||||
];
|
|
||||||
Loading…
x
Reference in New Issue
Block a user