mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2026-06-11 18:02:27 +00:00
Compare commits
9 Commits
main
...
@alilc/low
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7e43814008 | ||
|
|
987f4cea54 | ||
|
|
c18bc0261c | ||
|
|
c228907fe4 | ||
|
|
1e9e388ce9 | ||
|
|
67dabb04be | ||
|
|
9019c96f43 | ||
|
|
79db4ac97f | ||
|
|
1eb9addd8d |
@ -2,6 +2,30 @@
|
||||
|
||||
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
||||
|
||||
### [1.0.4-beta.1](https://github.com/alibaba/lowcode-engine/compare/@alilc/lowcode-code-generator@1.0.4-beta.0...@alilc/lowcode-code-generator@1.0.4-beta.1) (2022-04-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 🐛 解决 react 中 jsx 出码的时候对于循环数据漏包 __$evalArray 的问题 ([987f4ce](https://github.com/alibaba/lowcode-engine/commit/987f4cea54ef8a75d0b63a0268b5a20b2938b8a7))
|
||||
|
||||
### [1.0.4-beta.0](https://github.com/alibaba/lowcode-engine/compare/@alilc/lowcode-code-generator@1.0.3...@alilc/lowcode-code-generator@1.0.4-beta.0) (2022-04-10)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **material-parser:** check module before install it; fix default value issue in ts parser ([fc452f7](https://github.com/alibaba/lowcode-engine/commit/fc452f7166f02acfba6076c1a9425e6f5880b5f6))
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* 🐛 修正 i18n 里面的一个参数命名问题 ([1e9e388](https://github.com/alibaba/lowcode-engine/commit/1e9e388ce9104d76c4f6d9bc513c57e5059d7982))
|
||||
* 🐛 解决出码缺乏对于 i18n 数据的 params 的处理的问题 ([1eb9add](https://github.com/alibaba/lowcode-engine/commit/1eb9addd8df2323f9aabac87af32ac2efcd6bf22)), closes [#288](https://github.com/alibaba/lowcode-engine/issues/288)
|
||||
* 🐛 解决小程序环境没有 window, 而 rax 出码中却默认在 __$eval 中用到 window 的问题 ([67dabb0](https://github.com/alibaba/lowcode-engine/commit/67dabb04beb32b6e94eb1276222e53b416e47c9d))
|
||||
* Fix the conversion failure of some props expressions under Slot props of low-code components ([7db5461](https://github.com/alibaba/lowcode-engine/commit/7db5461706c739fac673b2466bc2fda7661242e4))
|
||||
* fix unnecessary props calculation ([f1fed75](https://github.com/alibaba/lowcode-engine/commit/f1fed75f39be8289ede1ec558b04428a69e25b5f))
|
||||
* 修正 react 框架出码中在严格模式对 methods 和 context 的处理 ([79db4ac](https://github.com/alibaba/lowcode-engine/commit/79db4ac97f34f24b7f7460fb3fc67521967f8cc5))
|
||||
|
||||
### [1.0.3](https://github.com/alibaba/lowcode-engine/compare/@alilc/lowcode-code-generator@1.0.2...@alilc/lowcode-code-generator@1.0.3) (2022-03-29)
|
||||
|
||||
|
||||
|
||||
@ -6,4 +6,5 @@ module.exports = {
|
||||
collectCoverage: false,
|
||||
collectCoverageFrom: ['src/**/*.{ts,tsx}', '!**/node_modules/**', '!**/vendor/**'],
|
||||
testMatch: ['<rootDir>/tests/**/*.test.ts'],
|
||||
setupFiles: ['./jest.setup.js'],
|
||||
};
|
||||
|
||||
12
modules/code-generator/jest.setup.js
Normal file
12
modules/code-generator/jest.setup.js
Normal file
@ -0,0 +1,12 @@
|
||||
// 对于 standalone 模式的专门 polyfills
|
||||
if (process.env.TEST_TARGET === 'standalone') {
|
||||
// 模拟浏览器环境
|
||||
global.window = global;
|
||||
global.self = global;
|
||||
|
||||
// 将所有测试用例里面的 './src' 都替换为 './dist/standalone'
|
||||
jest.mock('./src', () => require('./dist/standalone'));
|
||||
}
|
||||
|
||||
// 如果在调试模式下,则不限制超时时间
|
||||
jest.setTimeout(typeof v8debug === 'object' ? Infinity : 30 * 1000);
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@alilc/lowcode-code-generator",
|
||||
"version": "1.0.3",
|
||||
"version": "1.0.4-beta.1",
|
||||
"description": "出码引擎 for LowCode Engine",
|
||||
"license": "MIT",
|
||||
"main": "lib/index.js",
|
||||
@ -75,6 +75,7 @@
|
||||
"change-case": "^3.1.0",
|
||||
"commander": "^6.1.0",
|
||||
"debug": "^4.3.2",
|
||||
"fp-ts": "^2.11.9",
|
||||
"fs-extra": "9.x",
|
||||
"glob": "^7.2.0",
|
||||
"html-entities": "^2.3.2",
|
||||
@ -85,6 +86,7 @@
|
||||
"lodash-es": "^4.17.21",
|
||||
"mock-fs": "^5.1.2",
|
||||
"moment": "^2.29.1",
|
||||
"nanomatch": "^1.2.13",
|
||||
"node-fetch": "2.x",
|
||||
"path-browserify": "^1.0.1",
|
||||
"prettier": "^2.5.1",
|
||||
|
||||
55
modules/code-generator/scripts/run-demo-project
Executable file
55
modules/code-generator/scripts/run-demo-project
Executable file
@ -0,0 +1,55 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
// @ts-check
|
||||
const program = require('commander');
|
||||
const { spawnSync } = require('child_process');
|
||||
const glob = require('glob');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const _ = require('lodash');
|
||||
|
||||
program
|
||||
.option('--npm <npm>', 'specify the npm command location or alias')
|
||||
.arguments('<project>')
|
||||
.action((project, options) => {
|
||||
try {
|
||||
if (!fs.existsSync(project)) {
|
||||
throw new Error(`Project ${project} does not exist`);
|
||||
}
|
||||
|
||||
const getProjectActualPath = [
|
||||
() => path.resolve(process.cwd(), project),
|
||||
() =>
|
||||
path.resolve(
|
||||
process.cwd(),
|
||||
path.join(
|
||||
project,
|
||||
path.dirname(glob.sync('*/package.json', { cwd: project })[0] || ''),
|
||||
),
|
||||
),
|
||||
]
|
||||
.map((x) => _.memoize(x))
|
||||
.find((x) => fs.existsSync(path.join(x(), 'package.json')));
|
||||
|
||||
if (!getProjectActualPath) {
|
||||
throw new Error(`Project ${project} is not a valid project(no package.json)`);
|
||||
}
|
||||
|
||||
const projectActualPath = getProjectActualPath();
|
||||
if (path.resolve(process.cwd(), project) !== projectActualPath) {
|
||||
console.log('Changing directory to', path.relative(process.cwd(), projectActualPath));
|
||||
}
|
||||
|
||||
process.chdir(projectActualPath);
|
||||
|
||||
const npm = options.npm || 'npm';
|
||||
const cmd = `${npm} install && ${npm} start`;
|
||||
console.log('# %s', cmd);
|
||||
spawnSync(cmd, { stdio: 'inherit', shell: true });
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
|
||||
program.parse(process.argv);
|
||||
@ -638,6 +638,7 @@ export default function createHelloWorldProjectBuilder() {
|
||||
CodeGen.plugins.react.reactCommonDeps(),
|
||||
CodeGen.plugins.common.esmodule({ fileType: 'jsx' }),
|
||||
CodeGen.plugins.react.containerClass(),
|
||||
CodeGen.plugins.react.containerInjectContext(),
|
||||
CodeGen.plugins.react.containerInjectUtils(),
|
||||
CodeGen.plugins.react.containerInjectDataSourceEngine(),
|
||||
CodeGen.plugins.react.containerInjectI18n(),
|
||||
@ -659,6 +660,7 @@ export default function createHelloWorldProjectBuilder() {
|
||||
CodeGen.plugins.react.reactCommonDeps(),
|
||||
CodeGen.plugins.common.esmodule({ fileType: 'jsx' }),
|
||||
CodeGen.plugins.react.containerClass(),
|
||||
CodeGen.plugins.react.containerInjectContext(),
|
||||
CodeGen.plugins.react.containerInjectUtils(),
|
||||
CodeGen.plugins.react.containerInjectDataSourceEngine(),
|
||||
CodeGen.plugins.react.containerInjectI18n(),
|
||||
|
||||
@ -5,6 +5,7 @@ import {
|
||||
CodeGeneratorError,
|
||||
ICodeChunk,
|
||||
ICompiledModule,
|
||||
IContextData,
|
||||
IModuleBuilder,
|
||||
IParseResult,
|
||||
ISchemaParser,
|
||||
@ -23,6 +24,7 @@ export function createModuleBuilder(
|
||||
plugins: BuilderComponentPlugin[];
|
||||
postProcessors: PostProcessor[];
|
||||
mainFileName?: string;
|
||||
contextData?: IContextData;
|
||||
} = {
|
||||
plugins: [],
|
||||
postProcessors: [],
|
||||
@ -41,7 +43,13 @@ export function createModuleBuilder(
|
||||
|
||||
let files: ResultFile[] = [];
|
||||
|
||||
const { chunks } = await chunkGenerator.run(input);
|
||||
const { chunks } = await chunkGenerator.run(input, {
|
||||
ir: input,
|
||||
chunks: [],
|
||||
depNames: [],
|
||||
contextData: options.contextData || {},
|
||||
});
|
||||
|
||||
chunks.forEach((fileChunkList) => {
|
||||
const content = linker.link(fileChunkList);
|
||||
const file = createResultFile(
|
||||
|
||||
@ -14,7 +14,7 @@ import { SchemaParser } from '../parser/SchemaParser';
|
||||
import { createResultDir, addDirectory, addFile } from '../utils/resultHelper';
|
||||
|
||||
import { createModuleBuilder } from './ModuleBuilder';
|
||||
import { ProjectPreProcessor, ProjectPostProcessor } from '../types/core';
|
||||
import { ProjectPreProcessor, ProjectPostProcessor, IContextData } from '../types/core';
|
||||
import { CodeGeneratorError } from '../types/error';
|
||||
|
||||
interface IModuleInfo {
|
||||
@ -36,6 +36,10 @@ export interface ProjectBuilderInitOptions {
|
||||
projectPreProcessors?: ProjectPreProcessor[];
|
||||
/** 项目级别的后置处理器 */
|
||||
projectPostProcessors?: ProjectPostProcessor[];
|
||||
/** 是否处于严格模式 */
|
||||
inStrictMode?: boolean;
|
||||
/** 一些额外的上下文数据 */
|
||||
extraContextData?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
export class ProjectBuilder implements IProjectBuilder {
|
||||
@ -57,6 +61,12 @@ export class ProjectBuilder implements IProjectBuilder {
|
||||
/** 项目级别的后置处理器 */
|
||||
private projectPostProcessors: ProjectPostProcessor[];
|
||||
|
||||
/** 是否处于严格模式 */
|
||||
public readonly inStrictMode: boolean;
|
||||
|
||||
/** 一些额外的上下文数据 */
|
||||
public readonly extraContextData: IContextData;
|
||||
|
||||
constructor({
|
||||
template,
|
||||
plugins,
|
||||
@ -64,6 +74,8 @@ export class ProjectBuilder implements IProjectBuilder {
|
||||
schemaParser = new SchemaParser(),
|
||||
projectPreProcessors = [],
|
||||
projectPostProcessors = [],
|
||||
inStrictMode = false,
|
||||
extraContextData = {},
|
||||
}: ProjectBuilderInitOptions) {
|
||||
this.template = template;
|
||||
this.plugins = plugins;
|
||||
@ -71,6 +83,8 @@ export class ProjectBuilder implements IProjectBuilder {
|
||||
this.schemaParser = schemaParser;
|
||||
this.projectPreProcessors = projectPreProcessors;
|
||||
this.projectPostProcessors = projectPostProcessors;
|
||||
this.inStrictMode = inStrictMode;
|
||||
this.extraContextData = extraContextData;
|
||||
}
|
||||
|
||||
async generateProject(originalSchema: ProjectSchema | string): Promise<ResultDir> {
|
||||
@ -264,6 +278,12 @@ export class ProjectBuilder implements IProjectBuilder {
|
||||
builders[pluginName] = createModuleBuilder({
|
||||
plugins: this.plugins[pluginName],
|
||||
postProcessors: this.postProcessors,
|
||||
contextData: {
|
||||
inStrictMode: this.inStrictMode,
|
||||
tolerateEvalErrors: true,
|
||||
evalErrorsHandler: '',
|
||||
...this.extraContextData,
|
||||
},
|
||||
...options,
|
||||
});
|
||||
}
|
||||
|
||||
@ -25,16 +25,8 @@ import i18n from './plugins/project/i18n';
|
||||
import utils from './plugins/project/utils';
|
||||
import prettier from './postprocessor/prettier';
|
||||
|
||||
// 引入常用工具
|
||||
import * as utilsCommon from './utils/common';
|
||||
import * as utilsCompositeType from './utils/compositeType';
|
||||
import * as utilsJsExpression from './utils/jsExpression';
|
||||
import * as utilsJsSlot from './utils/jsSlot';
|
||||
import * as utilsNodeToJSX from './utils/nodeToJSX';
|
||||
import * as utilsResultHelper from './utils/resultHelper';
|
||||
import * as utilsTemplateHelper from './utils/templateHelper';
|
||||
import * as utilsValidate from './utils/validate';
|
||||
import * as utilsSchema from './utils/schema';
|
||||
// 引入全局常用工具
|
||||
import * as globalUtils from './utils';
|
||||
|
||||
import * as CONSTANTS from './const';
|
||||
|
||||
@ -85,17 +77,7 @@ export default {
|
||||
postprocessor: {
|
||||
prettier,
|
||||
},
|
||||
utils: {
|
||||
common: utilsCommon,
|
||||
compositeType: utilsCompositeType,
|
||||
jsExpression: utilsJsExpression,
|
||||
jsSlot: utilsJsSlot,
|
||||
nodeToJSX: utilsNodeToJSX,
|
||||
resultHelper: utilsResultHelper,
|
||||
templateHelper: utilsTemplateHelper,
|
||||
validate: utilsValidate,
|
||||
schema: utilsSchema,
|
||||
},
|
||||
utils: globalUtils,
|
||||
chunkNames: {
|
||||
COMMON_CHUNK_NAME,
|
||||
CLASS_DEFINE_CHUNK_NAME,
|
||||
|
||||
@ -134,19 +134,6 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
||||
],
|
||||
});
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JSX,
|
||||
name: CLASS_DEFINE_CHUNK_NAME.InsPrivateMethod,
|
||||
content: `
|
||||
_i18nText(t) {
|
||||
const locale = this._context.getLocale();
|
||||
return t[locale] ?? t[String(locale).replace('-', '_')] ?? t[t.use || 'zh_CN'] ?? t.en_US;
|
||||
}
|
||||
`,
|
||||
linkAfter: [RAX_CHUNK_NAME.ClassRenderEnd],
|
||||
});
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JSX,
|
||||
|
||||
@ -10,6 +10,7 @@ import {
|
||||
IContainerInfo,
|
||||
} from '../../../types';
|
||||
import { RAX_CHUNK_NAME } from './const';
|
||||
import { DEFAULT_LINK_AFTER } from '../../../const';
|
||||
|
||||
export interface PluginConfig {
|
||||
fileType: string;
|
||||
@ -46,6 +47,16 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
|
||||
linkAfter: [COMMON_CHUNK_NAME.ExternalDepsImport],
|
||||
});
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: cfg.fileType,
|
||||
name: CLASS_DEFINE_CHUNK_NAME.ConstructorContent,
|
||||
content: `
|
||||
__$$i18n._inject2(this);
|
||||
`,
|
||||
linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.ConstructorContent]],
|
||||
});
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: cfg.fileType,
|
||||
|
||||
@ -29,6 +29,11 @@ import { RAX_CHUNK_NAME } from './const';
|
||||
|
||||
export interface PluginConfig extends RaxFrameworkOptions {
|
||||
fileType?: string;
|
||||
|
||||
/**
|
||||
* 数据源的 handlers 的映射配置
|
||||
* @deprecated 请使用 datasourceConfig.handlersPackages 来配置
|
||||
*/
|
||||
dataSourceHandlersPackageMap?: Record<string, string>;
|
||||
}
|
||||
|
||||
|
||||
@ -62,6 +62,7 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
|
||||
|
||||
const ir = next.ir as IContainerInfo;
|
||||
const rootScope = Scope.createRootScope();
|
||||
const { tolerateEvalErrors = true, evalErrorsHandler = '' } = next.contextData;
|
||||
|
||||
// Rax 构建到小程序的时候,不能给组件起起别名,得直接引用,故这里将所有的别名替换掉
|
||||
// 先收集下所有的 alias 的映射
|
||||
@ -86,7 +87,9 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
|
||||
// 3. 通过 this.xxx 能拿到的东西太多了,而且自定义的 methods 可能会无意间破坏 Rax 框架或小程序框架在页面 this 上的东东
|
||||
const customHandlers: HandlerSet<string> = {
|
||||
expression(input: JSExpression, scope: IScope) {
|
||||
return transformJsExpr(generateExpression(input, scope), scope);
|
||||
return transformJsExpr(generateExpression(input, scope), scope, {
|
||||
dontWrapEval: !tolerateEvalErrors,
|
||||
});
|
||||
},
|
||||
function(input, scope: IScope) {
|
||||
return transformThis2Context(input.value || 'null', scope);
|
||||
@ -138,17 +141,14 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
|
||||
type: ChunkType.STRING,
|
||||
fileType: cfg.fileType,
|
||||
name: COMMON_CHUNK_NAME.CustomContent,
|
||||
content: `
|
||||
|
||||
content: [
|
||||
tolerateEvalErrors &&
|
||||
`
|
||||
function __$$eval(expr) {
|
||||
try {
|
||||
return expr();
|
||||
} catch (err) {
|
||||
try {
|
||||
if (window.handleEvalError) {
|
||||
window.handleEvalError('Failed to evaluate: ', expr, err);
|
||||
}
|
||||
} catch (e) {}
|
||||
} catch (error) {
|
||||
${evalErrorsHandler}
|
||||
}
|
||||
}
|
||||
|
||||
@ -156,16 +156,57 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
|
||||
const res = __$$eval(expr);
|
||||
return Array.isArray(res) ? res : [];
|
||||
}
|
||||
|
||||
`,
|
||||
`
|
||||
function __$$createChildContext(oldContext, ext) {
|
||||
return Object.assign({}, oldContext, ext);
|
||||
}
|
||||
|
||||
`,
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join('\n'),
|
||||
linkAfter: [COMMON_CHUNK_NAME.FileExport],
|
||||
});
|
||||
|
||||
return next;
|
||||
|
||||
function generateRaxLoopCtrl(
|
||||
nodeItem: NodeSchema,
|
||||
scope: IScope,
|
||||
config?: NodeGeneratorConfig,
|
||||
next?: NodePlugin,
|
||||
): CodePiece[] {
|
||||
if (nodeItem.loop) {
|
||||
const loopItemName = nodeItem.loopArgs?.[0] || 'item';
|
||||
const loopIndexName = nodeItem.loopArgs?.[1] || 'index';
|
||||
const subScope = scope.createSubScope([loopItemName, loopIndexName]);
|
||||
const pieces: CodePiece[] = next ? next(nodeItem, subScope, config) : [];
|
||||
|
||||
const loopDataExpr = tolerateEvalErrors
|
||||
? `__$$evalArray(() => (${transformThis2Context(
|
||||
generateCompositeType(nodeItem.loop, scope, { handlers: config?.handlers }),
|
||||
scope,
|
||||
)}))`
|
||||
: `(${transformThis2Context(
|
||||
generateCompositeType(nodeItem.loop, scope, { handlers: config?.handlers }),
|
||||
scope,
|
||||
)})`;
|
||||
|
||||
pieces.unshift({
|
||||
value: `${loopDataExpr}.map((${loopItemName}, ${loopIndexName}) => ((__$$context) => (`,
|
||||
type: PIECE_TYPE.BEFORE,
|
||||
});
|
||||
|
||||
pieces.push({
|
||||
value: `))(__$$createChildContext(__$$context, { ${loopItemName}, ${loopIndexName} })))`,
|
||||
type: PIECE_TYPE.AFTER,
|
||||
});
|
||||
|
||||
return pieces;
|
||||
}
|
||||
|
||||
return next ? next(nodeItem, scope, config) : [];
|
||||
}
|
||||
};
|
||||
|
||||
return plugin;
|
||||
@ -189,39 +230,6 @@ function isImportAliasDefineChunk(chunk: ICodeChunk): chunk is ICodeChunk & {
|
||||
);
|
||||
}
|
||||
|
||||
function generateRaxLoopCtrl(
|
||||
nodeItem: NodeSchema,
|
||||
scope: IScope,
|
||||
config?: NodeGeneratorConfig,
|
||||
next?: NodePlugin,
|
||||
): CodePiece[] {
|
||||
if (nodeItem.loop) {
|
||||
const loopItemName = nodeItem.loopArgs?.[0] || 'item';
|
||||
const loopIndexName = nodeItem.loopArgs?.[1] || 'index';
|
||||
const subScope = scope.createSubScope([loopItemName, loopIndexName]);
|
||||
const pieces: CodePiece[] = next ? next(nodeItem, subScope, config) : [];
|
||||
|
||||
const loopDataExpr = `__$$evalArray(() => (${transformThis2Context(
|
||||
generateCompositeType(nodeItem.loop, scope, { handlers: config?.handlers }),
|
||||
scope,
|
||||
)}))`;
|
||||
|
||||
pieces.unshift({
|
||||
value: `${loopDataExpr}.map((${loopItemName}, ${loopIndexName}) => ((__$$context) => (`,
|
||||
type: PIECE_TYPE.BEFORE,
|
||||
});
|
||||
|
||||
pieces.push({
|
||||
value: `))(__$$createChildContext(__$$context, { ${loopItemName}, ${loopIndexName} })))`,
|
||||
type: PIECE_TYPE.AFTER,
|
||||
});
|
||||
|
||||
return pieces;
|
||||
}
|
||||
|
||||
return next ? next(nodeItem, scope, config) : [];
|
||||
}
|
||||
|
||||
function generateNodeAttrForRax(
|
||||
this: { cfg: PluginConfig },
|
||||
attrData: { attrName: string; attrValue: CompositeValue },
|
||||
|
||||
@ -0,0 +1,91 @@
|
||||
import { CLASS_DEFINE_CHUNK_NAME } from '../../../const/generator';
|
||||
|
||||
import { Scope } from '../../../utils/Scope';
|
||||
|
||||
import {
|
||||
BuilderComponentPlugin,
|
||||
BuilderComponentPluginFactory,
|
||||
ChunkType,
|
||||
FileType,
|
||||
ICodeStruct,
|
||||
IContainerInfo,
|
||||
} from '../../../types';
|
||||
import { DEFAULT_LINK_AFTER } from '../../../const';
|
||||
|
||||
export interface PluginConfig {
|
||||
fileType: string;
|
||||
}
|
||||
|
||||
const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) => {
|
||||
const cfg: PluginConfig = {
|
||||
fileType: FileType.JSX,
|
||||
...config,
|
||||
};
|
||||
|
||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||
const next: ICodeStruct = {
|
||||
...pre,
|
||||
};
|
||||
|
||||
const ir = next.ir as IContainerInfo;
|
||||
const scope = Scope.createRootScope();
|
||||
|
||||
const { inStrictMode } = next.contextData;
|
||||
if (!inStrictMode) {
|
||||
// 非严格模式下,上下文就是自己
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: cfg.fileType,
|
||||
name: CLASS_DEFINE_CHUNK_NAME.InsVar,
|
||||
content: `
|
||||
_context = this;
|
||||
`,
|
||||
linkAfter: [CLASS_DEFINE_CHUNK_NAME.Start],
|
||||
});
|
||||
} else {
|
||||
// 严格模式下的上下文只保留协议中规定的那些
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: cfg.fileType,
|
||||
name: CLASS_DEFINE_CHUNK_NAME.InsVar,
|
||||
content: `
|
||||
_context = this._createContext();
|
||||
`,
|
||||
linkAfter: [CLASS_DEFINE_CHUNK_NAME.Start],
|
||||
});
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: cfg.fileType,
|
||||
name: CLASS_DEFINE_CHUNK_NAME.InsPrivateMethod,
|
||||
content: `
|
||||
_createContext() {
|
||||
const self = this;
|
||||
const context = {
|
||||
get state() { return self.state; },
|
||||
setState(newState, callback) { self.setState(newState, callback); },
|
||||
get dataSourceMap() { return self._dataSourceEngine.dataSourceMap || {}; },
|
||||
async reloadDataSource() { await self._dataSourceEngine.reloadDataSource(); },
|
||||
get utils() { return self.utils; },
|
||||
get page() { return context; },
|
||||
get component() { return context; },
|
||||
get props() { return self.props; },
|
||||
get constants() { return self.constants; },
|
||||
get $() { return self.$ },
|
||||
get $$() { return self.$$ },
|
||||
...this._methods,
|
||||
};
|
||||
|
||||
return context;
|
||||
}
|
||||
`,
|
||||
linkAfter: DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.InsPrivateMethod],
|
||||
});
|
||||
}
|
||||
|
||||
return next;
|
||||
};
|
||||
return plugin;
|
||||
};
|
||||
|
||||
export default pluginFactory;
|
||||
@ -31,13 +31,34 @@ import { isContainerSchema } from '../../../utils/schema';
|
||||
import { REACT_CHUNK_NAME } from './const';
|
||||
|
||||
export interface PluginConfig {
|
||||
fileType: string;
|
||||
fileType?: string;
|
||||
|
||||
/**
|
||||
* 数据源配置
|
||||
*/
|
||||
datasourceConfig?: {
|
||||
/** 数据源引擎的版本 */
|
||||
engineVersion?: string;
|
||||
|
||||
/** 数据源引擎的包名 */
|
||||
enginePackage?: string;
|
||||
|
||||
/** 数据源 handlers 的版本 */
|
||||
handlersVersion?: {
|
||||
[key: string]: string;
|
||||
};
|
||||
|
||||
/** 数据源 handlers 的包名 */
|
||||
handlersPackages?: {
|
||||
[key: string]: string;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) => {
|
||||
const cfg: PluginConfig = {
|
||||
fileType: FileType.JSX,
|
||||
const cfg = {
|
||||
...config,
|
||||
fileType: config?.fileType || FileType.JSX,
|
||||
};
|
||||
|
||||
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||
@ -65,7 +86,9 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
|
||||
};
|
||||
|
||||
const handlerFactoryExportName = `create${changeCase.pascal(dsType)}Handler`;
|
||||
const handlerPkgName = `@alilc/lowcode-datasource-${changeCase.kebab(dsType)}-handler`;
|
||||
const handlerPkgName =
|
||||
cfg.datasourceConfig?.handlersPackages?.[dsType] ||
|
||||
`@alilc/lowcode-datasource-${changeCase.kebab(dsType)}-handler`;
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
|
||||
@ -33,7 +33,7 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
|
||||
name: COMMON_CHUNK_NAME.InternalDepsImport,
|
||||
// TODO: 下面这个路径有没有更好的方式来获取?而非写死
|
||||
content: `
|
||||
import { i18n as _$$i18n } from '../../i18n';
|
||||
import * as __$$i18n from '../../i18n';
|
||||
`,
|
||||
linkAfter: [COMMON_CHUNK_NAME.ExternalDepsImport],
|
||||
});
|
||||
@ -41,13 +41,11 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: cfg.fileType,
|
||||
name: CLASS_DEFINE_CHUNK_NAME.InsMethod,
|
||||
name: CLASS_DEFINE_CHUNK_NAME.ConstructorContent,
|
||||
content: `
|
||||
i18n = (i18nKey) => {
|
||||
return _$$i18n(i18nKey);
|
||||
}
|
||||
__$$i18n._inject2(this);
|
||||
`,
|
||||
linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.InsMethod]],
|
||||
linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.ConstructorContent]],
|
||||
});
|
||||
|
||||
return next;
|
||||
|
||||
@ -83,6 +83,23 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
|
||||
`,
|
||||
linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.InsMethod]],
|
||||
});
|
||||
} else {
|
||||
// useRef 为 false 的时候是指没有组件在 props 中配置 ref 属性,但这个时候其实也可能有代码访问 this.$/$$ 所以还是加上个空的代码
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: cfg.fileType,
|
||||
name: CLASS_DEFINE_CHUNK_NAME.InsMethod,
|
||||
content: ` $ = () => null; `,
|
||||
linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.InsMethod]],
|
||||
});
|
||||
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: cfg.fileType,
|
||||
name: CLASS_DEFINE_CHUNK_NAME.InsMethod,
|
||||
content: ` $$ = () => []; `,
|
||||
linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.InsMethod]],
|
||||
});
|
||||
}
|
||||
|
||||
return next;
|
||||
|
||||
@ -11,6 +11,7 @@ import {
|
||||
ICodeStruct,
|
||||
IContainerInfo,
|
||||
} from '../../../types';
|
||||
import { isValidIdentifier } from '../../../utils/validate';
|
||||
|
||||
export interface PluginConfig {
|
||||
fileType: string;
|
||||
@ -28,8 +29,13 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
|
||||
};
|
||||
|
||||
const ir = next.ir as IContainerInfo;
|
||||
const { inStrictMode } = next.contextData;
|
||||
|
||||
if (ir.methods) {
|
||||
if (!ir.methods) {
|
||||
return next;
|
||||
}
|
||||
|
||||
// 将这些 methods 都定义到 class 上
|
||||
const { methods } = ir;
|
||||
const chunks = Object.keys(methods).map<ICodeChunk>((methodName) => ({
|
||||
type: ChunkType.STRING,
|
||||
@ -38,8 +44,22 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
|
||||
content: generateFunction(methods[methodName], { name: methodName, isMember: true }),
|
||||
linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.InsMethod]],
|
||||
}));
|
||||
|
||||
next.chunks.push(...chunks);
|
||||
|
||||
// 严格模式下需要将这些方法都挂到上下文中
|
||||
if (inStrictMode) {
|
||||
next.chunks.push({
|
||||
type: ChunkType.STRING,
|
||||
fileType: cfg.fileType,
|
||||
name: CLASS_DEFINE_CHUNK_NAME.ConstructorContent,
|
||||
content: Object.keys(ir.methods)
|
||||
.map((methodName) =>
|
||||
isValidIdentifier(methodName) ? `.${methodName}` : `[${JSON.stringify(methodName)}]`,
|
||||
)
|
||||
.map((method) => `this._context${method} = this${method};`)
|
||||
.join('\n'),
|
||||
linkAfter: [...DEFAULT_LINK_AFTER[CLASS_DEFINE_CHUNK_NAME.ConstructorContent]],
|
||||
});
|
||||
}
|
||||
|
||||
return next;
|
||||
|
||||
@ -42,12 +42,14 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
|
||||
...pre,
|
||||
};
|
||||
|
||||
const { tolerateEvalErrors = true, evalErrorsHandler = '' } = next.contextData;
|
||||
|
||||
// 这里会将内部的一些子上下文的访问(this.xxx)转换为 __$$context.xxx 的形式
|
||||
// 与 Rax 所不同的是,这里不会将最顶层的 this 转换掉
|
||||
const customHandlers: HandlerSet<string> = {
|
||||
expression(input: JSExpression, scope: IScope) {
|
||||
expression(input: JSExpression, scope: IScope, config) {
|
||||
return transformJsExpr(generateExpression(input, scope), scope, {
|
||||
dontWrapEval: true,
|
||||
dontWrapEval: !(config?.tolerateEvalErrors ?? tolerateEvalErrors),
|
||||
dontTransformThis2ContextAtRootScope: true,
|
||||
});
|
||||
},
|
||||
@ -69,6 +71,7 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
|
||||
const generatorPlugins: NodeGeneratorConfig = {
|
||||
handlers: customHandlers,
|
||||
tagMapping: (v) => nodeTypeMapping[v] || v,
|
||||
tolerateEvalErrors,
|
||||
};
|
||||
|
||||
if (next.contextData.useRefApi) {
|
||||
@ -100,8 +103,8 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
|
||||
fileType: cfg.fileType,
|
||||
name: REACT_CHUNK_NAME.ClassRenderJSX,
|
||||
content: `
|
||||
const __$$context = this;
|
||||
const { state } = this;
|
||||
const __$$context = this._context || this;
|
||||
const { state } = __$$context;
|
||||
return ${jsxContent};
|
||||
`,
|
||||
linkAfter: [REACT_CHUNK_NAME.ClassRenderStart, REACT_CHUNK_NAME.ClassRenderPre],
|
||||
@ -111,7 +114,23 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
|
||||
type: ChunkType.STRING,
|
||||
fileType: cfg.fileType,
|
||||
name: COMMON_CHUNK_NAME.CustomContent,
|
||||
content: `
|
||||
content: [
|
||||
tolerateEvalErrors &&
|
||||
`
|
||||
function __$$eval(expr) {
|
||||
try {
|
||||
return expr();
|
||||
} catch (error) {
|
||||
${evalErrorsHandler}
|
||||
}
|
||||
}
|
||||
|
||||
function __$$evalArray(expr) {
|
||||
const res = __$$eval(expr);
|
||||
return Array.isArray(res) ? res : [];
|
||||
}
|
||||
`,
|
||||
`
|
||||
function __$$createChildContext(oldContext, ext) {
|
||||
const childContext = {
|
||||
...oldContext,
|
||||
@ -121,6 +140,9 @@ const pluginFactory: BuilderComponentPluginFactory<PluginConfig> = (config?) =>
|
||||
return childContext;
|
||||
}
|
||||
`,
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join('\n'),
|
||||
linkAfter: [COMMON_CHUNK_NAME.FileExport],
|
||||
});
|
||||
return next;
|
||||
|
||||
@ -18,7 +18,10 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
||||
type: ChunkType.STRING,
|
||||
fileType: FileType.JSX,
|
||||
name: COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||
content: 'import React from \'react\';',
|
||||
content: `
|
||||
// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。
|
||||
// 例外:react 框架的导出名和各种组件名除外。
|
||||
import React from \'react\';`,
|
||||
linkAfter: [],
|
||||
});
|
||||
|
||||
|
||||
@ -23,11 +23,9 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
||||
fileType: FileType.JS,
|
||||
name: COMMON_CHUNK_NAME.FileMainContent,
|
||||
content: `
|
||||
import IntlMessageFormat from 'intl-messageformat';
|
||||
|
||||
const i18nConfig = ${i18nStr};
|
||||
|
||||
let locale = 'en-US';
|
||||
let locale = typeof navigator === 'object' && typeof navigator.language === 'string' ? navigator.language : 'zh-CN';
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -35,23 +33,65 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const msg = i18nConfig && i18nConfig[locale] && i18nConfig[locale][id] || defaultMessage;
|
||||
const isEmptyVariables = variables => (
|
||||
Array.isArray(variables) && variables.length === 0
|
||||
|| typeof variables === 'object' && (!variables || Object.keys(variables).length === 0)
|
||||
);
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) => (
|
||||
typeof msg === 'string'
|
||||
? msg.replace(/\\\$\\{(\\w+)\\}/g, (match, key) => variables?.[key] ?? '')
|
||||
: msg
|
||||
);
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg = i18nConfig[locale]?.[id] ?? i18nConfig[locale.replace('-', '_')]?.[id] ?? defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn('[i18n]: unknown message id: %o (locale=%o)', id, locale);
|
||||
return \`\${id}\`;
|
||||
return fallback === undefined ? \`\${id}\` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
return format(msg, variables);
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
}
|
||||
|
||||
const i18n = id => {
|
||||
return i18nFormat({ id });
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace('-', '_')]
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, t.params);
|
||||
}
|
||||
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || "zh_CN"] ?? t.en_US, t.params);
|
||||
}
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale, setLocale: target.setLocale
|
||||
});
|
||||
}
|
||||
}
|
||||
`,
|
||||
linkAfter: [
|
||||
COMMON_CHUNK_NAME.ExternalDepsImport,
|
||||
@ -72,6 +112,7 @@ const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
||||
setLocale,
|
||||
i18n,
|
||||
i18nFormat,
|
||||
_inject2,
|
||||
};
|
||||
`,
|
||||
linkAfter: [
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
import { IProjectBuilder } from '../types';
|
||||
import { IProjectBuilder, IProjectBuilderOptions } from '../types';
|
||||
|
||||
import { createProjectBuilder } from '../generator/ProjectBuilder';
|
||||
|
||||
import esmodule from '../plugins/common/esmodule';
|
||||
import containerClass from '../plugins/component/react/containerClass';
|
||||
import containerInitState from '../plugins/component/react/containerInitState';
|
||||
import containerInjectContext from '../plugins/component/react/containerInjectContext';
|
||||
import containerInjectUtils from '../plugins/component/react/containerInjectUtils';
|
||||
import containerInjectDataSourceEngine from '../plugins/component/react/containerInjectDataSourceEngine';
|
||||
import containerInjectI18n from '../plugins/component/react/containerInjectI18n';
|
||||
@ -21,8 +22,14 @@ import icejs from '../plugins/project/framework/icejs';
|
||||
|
||||
import { prettier } from '../postprocessor';
|
||||
|
||||
export default function createIceJsProjectBuilder(): IProjectBuilder {
|
||||
export interface IceJsProjectBuilderOptions extends IProjectBuilderOptions {}
|
||||
|
||||
export default function createIceJsProjectBuilder(
|
||||
options?: IceJsProjectBuilderOptions,
|
||||
): IProjectBuilder {
|
||||
return createProjectBuilder({
|
||||
inStrictMode: options?.inStrictMode,
|
||||
extraContextData: { ...options },
|
||||
template: icejs.template,
|
||||
plugins: {
|
||||
components: [
|
||||
@ -31,6 +38,7 @@ export default function createIceJsProjectBuilder(): IProjectBuilder {
|
||||
fileType: 'jsx',
|
||||
}),
|
||||
containerClass(),
|
||||
containerInjectContext(),
|
||||
containerInjectUtils(),
|
||||
containerInjectDataSourceEngine(),
|
||||
containerInjectI18n(),
|
||||
@ -53,6 +61,7 @@ export default function createIceJsProjectBuilder(): IProjectBuilder {
|
||||
fileType: 'jsx',
|
||||
}),
|
||||
containerClass(),
|
||||
containerInjectContext(),
|
||||
containerInjectUtils(),
|
||||
containerInjectDataSourceEngine(),
|
||||
containerInjectI18n(),
|
||||
@ -86,6 +95,7 @@ export default function createIceJsProjectBuilder(): IProjectBuilder {
|
||||
export const plugins = {
|
||||
containerClass,
|
||||
containerInitState,
|
||||
containerInjectContext,
|
||||
containerInjectUtils,
|
||||
containerInjectI18n,
|
||||
containerInjectDataSourceEngine,
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { IProjectBuilder } from '../types';
|
||||
import { IProjectBuilder, IProjectBuilderOptions } from '../types';
|
||||
|
||||
import { createProjectBuilder } from '../generator/ProjectBuilder';
|
||||
|
||||
@ -22,8 +22,14 @@ import raxApp from '../plugins/project/framework/rax';
|
||||
import { prettier } from '../postprocessor';
|
||||
import { RaxFrameworkOptions } from '../plugins/project/framework/rax/types/RaxFrameworkOptions';
|
||||
|
||||
export default function createRaxProjectBuilder(options?: RaxFrameworkOptions): IProjectBuilder {
|
||||
export interface RaxProjectBuilderOptions extends IProjectBuilderOptions, RaxFrameworkOptions {}
|
||||
|
||||
export default function createRaxProjectBuilder(
|
||||
options?: RaxProjectBuilderOptions,
|
||||
): IProjectBuilder {
|
||||
return createProjectBuilder({
|
||||
inStrictMode: options?.inStrictMode,
|
||||
extraContextData: { ...options },
|
||||
template: raxApp.template,
|
||||
plugins: {
|
||||
components: [
|
||||
|
||||
@ -25,16 +25,8 @@ import i18n from './plugins/project/i18n';
|
||||
import utils from './plugins/project/utils';
|
||||
import prettier from './postprocessor/prettier';
|
||||
|
||||
// 引入常用工具
|
||||
import * as utilsCommon from './utils/common';
|
||||
import * as utilsCompositeType from './utils/compositeType';
|
||||
import * as utilsJsExpression from './utils/jsExpression';
|
||||
import * as utilsJsSlot from './utils/jsSlot';
|
||||
import * as utilsNodeToJSX from './utils/nodeToJSX';
|
||||
import * as utilsResultHelper from './utils/resultHelper';
|
||||
import * as utilsTemplateHelper from './utils/templateHelper';
|
||||
import * as utilsValidate from './utils/validate';
|
||||
import * as utilsSchema from './utils/schema';
|
||||
// 引入全局常用工具
|
||||
import * as globalUtils from './utils';
|
||||
|
||||
import * as CONSTANTS from './const';
|
||||
|
||||
@ -54,7 +46,6 @@ export default {
|
||||
rax,
|
||||
},
|
||||
publishers: {
|
||||
// TODO: 增加 web 端的 zip publisher
|
||||
zip: createZipPublisher,
|
||||
},
|
||||
plugins: {
|
||||
@ -85,17 +76,7 @@ export default {
|
||||
postprocessor: {
|
||||
prettier,
|
||||
},
|
||||
utils: {
|
||||
common: utilsCommon,
|
||||
compositeType: utilsCompositeType,
|
||||
jsExpression: utilsJsExpression,
|
||||
jsSlot: utilsJsSlot,
|
||||
nodeToJSX: utilsNodeToJSX,
|
||||
resultHelper: utilsResultHelper,
|
||||
templateHelper: utilsTemplateHelper,
|
||||
validate: utilsValidate,
|
||||
schema: utilsSchema,
|
||||
},
|
||||
utils: globalUtils,
|
||||
chunkNames: {
|
||||
COMMON_CHUNK_NAME,
|
||||
CLASS_DEFINE_CHUNK_NAME,
|
||||
|
||||
@ -59,8 +59,19 @@ export interface IBaseCodeStruct {
|
||||
|
||||
export interface ICodeStruct extends IBaseCodeStruct {
|
||||
ir: any;
|
||||
// FIXME: 这个方案不太好,想清楚场景,结构化表达,不要那么通用
|
||||
contextData: Record<string, any>;
|
||||
contextData: IContextData;
|
||||
}
|
||||
|
||||
/** 上下文数据,用来在插件之间共享一些数据 */
|
||||
export interface IContextData extends IProjectBuilderOptions {
|
||||
/** 是否使用了 Ref 的 API (this.$/this.$$) */
|
||||
useRefApi?: boolean;
|
||||
|
||||
/**
|
||||
* 其他自定义数据
|
||||
* (三方自定义插件也可以在此放一些数据,建议起个长一点的名称,用自己的插件名做前缀,以防冲突)
|
||||
*/
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
export type BuilderComponentPlugin = (initStruct: ICodeStruct) => Promise<ICodeStruct>;
|
||||
@ -125,6 +136,33 @@ export interface IProjectPlugins {
|
||||
[slotName: string]: BuilderComponentPlugin[];
|
||||
}
|
||||
|
||||
export interface IProjectBuilderOptions {
|
||||
/** 是否处于严格模式(默认: 否) */
|
||||
inStrictMode?: boolean;
|
||||
|
||||
/**
|
||||
* 是否要容忍对 JSExpression 求值时的异常
|
||||
* 默认:true
|
||||
* 注: 如果容忍异常,则会在求值时包裹 try-catch 块,
|
||||
* catch 到异常时默认会抛出一个 CustomEvent 事件里面包含异常信息和求值的表达式
|
||||
*/
|
||||
tolerateEvalErrors?: boolean;
|
||||
|
||||
/**
|
||||
* 容忍异常的时候的的错误处理语句块
|
||||
* 默认: 无
|
||||
* 您可以设置为一个语句块,比如:
|
||||
* window.dispatchEvent(new CustomEvent('lowcode-eval-error', { error, expr }))
|
||||
*
|
||||
* 一般可以结合埋点监控模块用来监控求值异常
|
||||
*
|
||||
* 其中:
|
||||
* - error: 异常信息
|
||||
* - expr: 求值的表达式
|
||||
*/
|
||||
evalErrorsHandler?: string;
|
||||
}
|
||||
|
||||
export interface IProjectBuilder {
|
||||
generateProject: (schema: ProjectSchema | string) => Promise<ResultDir>;
|
||||
}
|
||||
@ -179,6 +217,7 @@ export interface HandlerSet<T> {
|
||||
export interface CompositeValueGeneratorOptions {
|
||||
handlers?: HandlerSet<string>;
|
||||
nodeGenerator?: NodeGenerator<string>;
|
||||
tolerateEvalErrors?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -15,7 +15,10 @@ export interface CodePiece {
|
||||
type: PIECE_TYPE;
|
||||
}
|
||||
|
||||
export interface AttrData { attrName: string; attrValue: CompositeValue }
|
||||
export interface AttrData {
|
||||
attrName: string;
|
||||
attrValue: CompositeValue;
|
||||
}
|
||||
// 对 JSX 出码的理解,目前定制点包含 【包装】【标签名】【属性】
|
||||
export type AttrPlugin = BaseGenerator<AttrData, CodePiece[], NodeGeneratorConfig>;
|
||||
export type NodePlugin = BaseGenerator<NodeSchema, CodePiece[], NodeGeneratorConfig>;
|
||||
@ -26,4 +29,12 @@ export interface NodeGeneratorConfig {
|
||||
attrPlugins?: AttrPlugin[];
|
||||
nodePlugins?: NodePlugin[];
|
||||
self?: NodeGenerator<string>;
|
||||
|
||||
/**
|
||||
* 是否要容忍对 JSExpression 求值时的异常
|
||||
* 默认:true
|
||||
* 注: 如果容忍异常,则会在求值时包裹 try-catch 块 -- 通过 __$$eval / __$$evalArray
|
||||
* catch 到异常时默认会抛出一个 CustomEvent 事件里面包含异常信息和求值的表达式
|
||||
*/
|
||||
tolerateEvalErrors?: boolean;
|
||||
}
|
||||
|
||||
1
modules/code-generator/src/typings.d.ts
vendored
Normal file
1
modules/code-generator/src/typings.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
declare module 'nanomatch';
|
||||
@ -57,7 +57,11 @@ function generateObject(
|
||||
options: CompositeValueGeneratorOptions = {},
|
||||
): string {
|
||||
if (value.type === 'i18n') {
|
||||
return `this._i18nText(${JSON.stringify(value)})`;
|
||||
// params 可能会绑定变量,这里需要处理下
|
||||
if (value.params && typeof value.params === 'object') {
|
||||
return `this._i18nText(${generateUnknownType(_.omit(value, 'type'), scope, options)})`;
|
||||
}
|
||||
return `this._i18nText(${JSON.stringify(_.omit(value, 'type'))})`; // TODO: 优化:这里可以考虑提取成个常量...
|
||||
}
|
||||
|
||||
const body = Object.keys(value)
|
||||
|
||||
28
modules/code-generator/src/utils/index.ts
Normal file
28
modules/code-generator/src/utils/index.ts
Normal file
@ -0,0 +1,28 @@
|
||||
// 本文件是要导出到外面的,注意只导出比较稳定的东西
|
||||
import * as common from './common';
|
||||
import * as compositeType from './compositeType';
|
||||
import * as jsExpression from './jsExpression';
|
||||
import * as jsSlot from './jsSlot';
|
||||
import * as nodeToJSX from './nodeToJSX';
|
||||
import * as resultHelper from './resultHelper';
|
||||
import * as templateHelper from './templateHelper';
|
||||
import * as validate from './validate';
|
||||
import * as schema from './schema';
|
||||
import * as version from './version';
|
||||
import * as scope from './Scope';
|
||||
import * as expressionParser from './expressionParser';
|
||||
|
||||
export {
|
||||
common,
|
||||
compositeType,
|
||||
jsExpression,
|
||||
jsSlot,
|
||||
nodeToJSX,
|
||||
resultHelper,
|
||||
templateHelper,
|
||||
validate,
|
||||
schema,
|
||||
version,
|
||||
scope,
|
||||
expressionParser,
|
||||
};
|
||||
@ -79,10 +79,11 @@ export function isJsCode(value: unknown): boolean {
|
||||
|
||||
export function generateExpression(value: any, scope: IScope): string {
|
||||
if (isJSExpression(value)) {
|
||||
const exprVal = (value as JSExpression).value;
|
||||
const exprVal = (value as JSExpression).value.trim();
|
||||
if (!exprVal) {
|
||||
return 'null';
|
||||
}
|
||||
|
||||
const afterProcessWithLocals = transformExpressionLocalRef(exprVal, scope);
|
||||
return afterProcessWithLocals;
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import _ from 'lodash';
|
||||
import { pipe } from 'fp-ts/function';
|
||||
import { NodeSchema, isNodeSchema, NodeDataType, CompositeValue } from '@alilc/lowcode-types';
|
||||
|
||||
import {
|
||||
@ -17,6 +18,7 @@ import { getStaticExprValue } from './common';
|
||||
import { executeFunctionStack } from './aopHelper';
|
||||
import { encodeJsxStringNode } from './encodeJsxAttrString';
|
||||
import { unwrapJsExprQuoteInJsx } from './jsxHelpers';
|
||||
import { transformThis2Context } from '../core/jsx/handlers/transformThis2Context';
|
||||
|
||||
function mergeNodeGeneratorConfig(
|
||||
cfg1: NodeGeneratorConfig,
|
||||
@ -255,6 +257,8 @@ export function generateReactLoopCtrl(
|
||||
next?: NodePlugin,
|
||||
): CodePiece[] {
|
||||
if (nodeItem.loop) {
|
||||
const tolerateEvalErrors = config?.tolerateEvalErrors ?? true;
|
||||
|
||||
const loopItemName = nodeItem.loopArgs?.[0] || 'item';
|
||||
const loopIndexName = nodeItem.loopArgs?.[1] || 'index';
|
||||
|
||||
@ -262,9 +266,20 @@ export function generateReactLoopCtrl(
|
||||
const subScope = scope.createSubScope([loopItemName, loopIndexName]);
|
||||
const pieces: CodePiece[] = next ? next(nodeItem, subScope, config) : [];
|
||||
|
||||
const loopDataExpr = generateCompositeType(nodeItem.loop, scope, {
|
||||
// 生成循环变量表达式
|
||||
const loopDataExpr = pipe(
|
||||
nodeItem.loop,
|
||||
// 将 JSExpression 转换为 JS 表达式代码:
|
||||
(expr) =>
|
||||
generateCompositeType(expr, scope, {
|
||||
handlers: config?.handlers,
|
||||
});
|
||||
tolerateEvalErrors: false, // 这个内部不需要包 try catch, 下面会统一加的
|
||||
}),
|
||||
// 将 this.xxx 转换为 __$$context.xxx:
|
||||
(expr) => transformThis2Context(expr, scope, { ignoreRootScope: true }),
|
||||
// 如果要容忍错误,则包一层 try catch (基于助手函数 __$$evalArray)
|
||||
(expr) => (tolerateEvalErrors ? `__$$evalArray(() => (${expr}))` : expr),
|
||||
);
|
||||
|
||||
pieces.unshift({
|
||||
value: `(${loopDataExpr}).map((${loopItemName}, ${loopIndexName}) => ((__$$context) => (`,
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { ResultFile, ResultDir } from '@alilc/lowcode-types';
|
||||
import nm from 'nanomatch';
|
||||
|
||||
import { CodeGeneratorError } from '../types/error';
|
||||
import { FlattenFile } from '../types/file';
|
||||
@ -47,12 +48,204 @@ export function flattenResult(dir: ResultDir, cwd = ''): FlattenFile[] {
|
||||
return [
|
||||
...dir.files.map(
|
||||
(file): FlattenFile => ({
|
||||
pathName: `${cwd ? `${cwd}/` : ''}${file.name}${file.ext ? `.${file.ext}` : ''}`,
|
||||
pathName: joinPath(cwd, `${file.name}${file.ext ? `.${file.ext}` : ''}`),
|
||||
content: file.content,
|
||||
}),
|
||||
),
|
||||
].concat(
|
||||
...dir.dirs.map((subDir) =>
|
||||
flattenResult(subDir, [cwd, subDir.name].filter((x) => x !== '' && x !== '.').join('/'))),
|
||||
);
|
||||
].concat(...dir.dirs.map((subDir) => flattenResult(subDir, joinPath(cwd, subDir.name))));
|
||||
}
|
||||
|
||||
export type GlobOptions = {
|
||||
/** 是否查找 ".xxx" 文件, 默认: 否 */
|
||||
dot?: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
* 查找文件
|
||||
* @param result 出码结果
|
||||
* @param fileGlobExpr 文件名匹配表达式
|
||||
* @param resultDirPath 出码结果的路径(默认是 '.')
|
||||
* @returns 匹配的第一个文件或 null (找不到)
|
||||
*/
|
||||
export function findFile(
|
||||
result: ResultDir,
|
||||
fileGlobExpr: string,
|
||||
options: GlobOptions = {},
|
||||
resultDirPath = getResultNameOrDefault(result, ''),
|
||||
): ResultFile | null {
|
||||
const maxDepth = !/\/|\*\*/.test(fileGlobExpr) ? 1 : undefined; // 如果 glob 表达式里面压根不会匹配子目录,则深度限制为 1
|
||||
const files = scanFiles(result, resultDirPath, maxDepth);
|
||||
|
||||
for (let [filePath, file] of files) {
|
||||
if (nm.isMatch(filePath, fileGlobExpr, options)) {
|
||||
return file;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用 glob 语法查找多个文件
|
||||
* @param result 出码结果
|
||||
* @param fileGlobExpr 文件名匹配表达式
|
||||
* @param resultDirPath 出码结果的路径(默认是 '.')
|
||||
* @returns 找到的文件列表的迭代器 [ [文件路径, 文件信息], ... ]
|
||||
*/
|
||||
export function* globFiles(
|
||||
result: ResultDir,
|
||||
fileGlobExpr: string,
|
||||
options: GlobOptions = {},
|
||||
resultDirPath = getResultNameOrDefault(result, ''),
|
||||
): IterableIterator<[string, ResultFile]> {
|
||||
const files = scanFiles(result, resultDirPath);
|
||||
|
||||
for (let [filePath, file] of files) {
|
||||
if (nm.isMatch(filePath, fileGlobExpr, options)) {
|
||||
yield [filePath, file];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 遍历所有的文件
|
||||
*/
|
||||
export function* scanFiles(
|
||||
result: ResultDir,
|
||||
resultDirPath = getResultNameOrDefault(result, ''),
|
||||
maxDepth = 10000,
|
||||
): IterableIterator<[string, ResultFile]> {
|
||||
for (let file of result.files) {
|
||||
const fileName = getFileNameWithExt(file);
|
||||
yield [joinPath(resultDirPath, fileName), file];
|
||||
}
|
||||
|
||||
for (let subDir of result.dirs) {
|
||||
yield* scanFiles(subDir, joinPath(resultDirPath, subDir.name), maxDepth - 1);
|
||||
}
|
||||
}
|
||||
|
||||
export function getFileNameWithExt(file: ResultFile) {
|
||||
return `${file.name}${file.ext ? `.${file.ext}` : ''}`;
|
||||
}
|
||||
|
||||
function getResultNameOrDefault(result: ResultDir, defaultDir = '/') {
|
||||
return result.name && result.name !== '.' ? result.name : defaultDir;
|
||||
}
|
||||
|
||||
function joinPath(...pathParts: string[]): string {
|
||||
return pathParts
|
||||
.filter((x) => x !== '' && x !== '.')
|
||||
.join('/')
|
||||
.replace(/\\+/g, '/')
|
||||
.replace(/\/+/g, '/');
|
||||
}
|
||||
|
||||
export function* scanDirs(
|
||||
result: ResultDir,
|
||||
resultDirPath = getResultNameOrDefault(result, ''),
|
||||
maxDepth = 10000,
|
||||
): IterableIterator<[string, ResultDir]> {
|
||||
yield [resultDirPath, result];
|
||||
|
||||
for (let subDir of result.dirs) {
|
||||
yield* scanDirs(subDir, joinPath(resultDirPath, subDir.name), maxDepth - 1);
|
||||
}
|
||||
}
|
||||
|
||||
export function* globDirs(
|
||||
result: ResultDir,
|
||||
dirGlobExpr: string,
|
||||
options: GlobOptions = {},
|
||||
resultDirPath = getResultNameOrDefault(result, ''),
|
||||
): IterableIterator<[string, ResultDir]> {
|
||||
const dirs = scanDirs(result, resultDirPath);
|
||||
|
||||
for (let [dirPath, dir] of dirs) {
|
||||
if (nm.isMatch(dirPath, dirGlobExpr, options)) {
|
||||
yield [dirPath, dir];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function findDir(
|
||||
result: ResultDir,
|
||||
dirGlobExpr: string,
|
||||
options: GlobOptions = {},
|
||||
resultDirPath = getResultNameOrDefault(result, ''),
|
||||
): ResultDir | null {
|
||||
const dirs = scanDirs(result, resultDirPath);
|
||||
|
||||
for (let [dirPath, dir] of dirs) {
|
||||
if (nm.isMatch(dirPath, dirGlobExpr, options)) {
|
||||
return dir;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从结果中移除一些文件
|
||||
* @param result 出码结果目录
|
||||
* @param filePathGlobExpr 要移除的文件路径(glob 表达式)
|
||||
* @param globOptions glob 参数
|
||||
* @returns 移除了多少文件
|
||||
*/
|
||||
export function removeFilesFromResult(
|
||||
result: ResultDir,
|
||||
filePathGlobExpr: string,
|
||||
globOptions: GlobOptions = {},
|
||||
): number {
|
||||
let removedCount = 0;
|
||||
const [dirPath, fileName] = splitPath(filePathGlobExpr);
|
||||
|
||||
const dirs = dirPath ? globDirs(result, dirPath) : [['', result] as const];
|
||||
for (let [, dir] of dirs) {
|
||||
const files = globFiles(dir, fileName, globOptions, '.');
|
||||
for (let [, file] of files) {
|
||||
dir.files.splice(dir.files.indexOf(file), 1);
|
||||
removedCount += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return removedCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从结果中移除一些目录
|
||||
* @param result 出码结果目录
|
||||
* @param dirPathGlobExpr 要移除的目录路径(glob 表达式)
|
||||
* @param globOptions glob 参数
|
||||
* @returns 移除了多少文件
|
||||
*/
|
||||
export function removeDirsFromResult(
|
||||
result: ResultDir,
|
||||
dirPathGlobExpr: string,
|
||||
globOptions: GlobOptions = {},
|
||||
): number {
|
||||
let removedCount = 0;
|
||||
const [dirPath, fileName] = splitPath(dirPathGlobExpr);
|
||||
|
||||
const dirs = dirPath ? globDirs(result, dirPath) : [['', result] as const];
|
||||
for (let [, dir] of dirs) {
|
||||
const foundDirs = globDirs(dir, fileName, globOptions, '.');
|
||||
for (let [, foundDir] of foundDirs) {
|
||||
dir.dirs.splice(dir.dirs.indexOf(foundDir), 1);
|
||||
removedCount += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return removedCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将文件路径拆分为目录路径和文件名
|
||||
* @param filePath
|
||||
* @returns [fileDirPath, fileName]
|
||||
*/
|
||||
function splitPath(filePath: string) {
|
||||
const parts = filePath.split('/');
|
||||
const fileName = parts.pop() || '';
|
||||
return [joinPath(...parts), fileName];
|
||||
}
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
import IntlMessageFormat from 'intl-messageformat';
|
||||
|
||||
const i18nConfig = {};
|
||||
|
||||
let locale = 'en-US';
|
||||
let locale = typeof navigator === 'object' && typeof navigator.language === 'string' ? navigator.language : 'zh-CN';
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -10,22 +8,61 @@ const setLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const msg = (i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) || defaultMessage;
|
||||
const isEmptyVariables = (variables) =>
|
||||
(Array.isArray(variables) && variables.length === 0) ||
|
||||
(typeof variables === 'object' && (!variables || Object.keys(variables).length === 0));
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) =>
|
||||
typeof msg === 'string' ? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? '') : msg;
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg = i18nConfig[locale]?.[id] ?? i18nConfig[locale.replace('-', '_')]?.[id] ?? defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn('[i18n]: unknown message id: %o (locale=%o)', id, locale);
|
||||
return `${id}`;
|
||||
return fallback === undefined ? `${id}` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
return format(msg, variables);
|
||||
};
|
||||
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace('-', '_')];
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, t.params);
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || 'zh_CN'] ?? t.en_US, t.params);
|
||||
};
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale,
|
||||
setLocale: target.setLocale,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const i18n = (id) => {
|
||||
return i18nFormat({ id });
|
||||
};
|
||||
|
||||
export { getLocale, setLocale, i18n, i18nFormat };
|
||||
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||
|
||||
@ -33,6 +33,8 @@ class Home$$Page extends Component {
|
||||
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
} /* end of constructor */
|
||||
|
||||
componentDidMount() {
|
||||
@ -63,11 +65,6 @@ class Home$$Page extends Component {
|
||||
);
|
||||
} /* end of render */
|
||||
|
||||
_i18nText(t) {
|
||||
const locale = this._context.getLocale();
|
||||
return t[locale] ?? t[String(locale).replace('-', '_')] ?? t[t.use || 'zh_CN'] ?? t.en_US;
|
||||
}
|
||||
|
||||
_createContext() {
|
||||
const self = this;
|
||||
const context = {
|
||||
@ -132,13 +129,7 @@ export default Home$$Page;
|
||||
function __$$eval(expr) {
|
||||
try {
|
||||
return expr();
|
||||
} catch (err) {
|
||||
try {
|
||||
if (window.handleEvalError) {
|
||||
window.handleEvalError('Failed to evaluate: ', expr, err);
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
function __$$evalArray(expr) {
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
import IntlMessageFormat from 'intl-messageformat';
|
||||
|
||||
const i18nConfig = {};
|
||||
|
||||
let locale = 'en-US';
|
||||
let locale = typeof navigator === 'object' && typeof navigator.language === 'string' ? navigator.language : 'zh-CN';
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -10,22 +8,61 @@ const setLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const msg = (i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) || defaultMessage;
|
||||
const isEmptyVariables = (variables) =>
|
||||
(Array.isArray(variables) && variables.length === 0) ||
|
||||
(typeof variables === 'object' && (!variables || Object.keys(variables).length === 0));
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) =>
|
||||
typeof msg === 'string' ? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? '') : msg;
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg = i18nConfig[locale]?.[id] ?? i18nConfig[locale.replace('-', '_')]?.[id] ?? defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn('[i18n]: unknown message id: %o (locale=%o)', id, locale);
|
||||
return `${id}`;
|
||||
return fallback === undefined ? `${id}` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
return format(msg, variables);
|
||||
};
|
||||
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace('-', '_')];
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, t.params);
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || 'zh_CN'] ?? t.en_US, t.params);
|
||||
};
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale,
|
||||
setLocale: target.setLocale,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const i18n = (id) => {
|
||||
return i18nFormat({ id });
|
||||
};
|
||||
|
||||
export { getLocale, setLocale, i18n, i18nFormat };
|
||||
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||
|
||||
@ -68,6 +68,8 @@ class Home$$Page extends Component {
|
||||
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
} /* end of constructor */
|
||||
|
||||
componentDidMount() {
|
||||
@ -166,11 +168,6 @@ class Home$$Page extends Component {
|
||||
);
|
||||
} /* end of render */
|
||||
|
||||
_i18nText(t) {
|
||||
const locale = this._context.getLocale();
|
||||
return t[locale] ?? t[String(locale).replace('-', '_')] ?? t[t.use || 'zh_CN'] ?? t.en_US;
|
||||
}
|
||||
|
||||
_createContext() {
|
||||
const self = this;
|
||||
const context = {
|
||||
@ -339,13 +336,7 @@ export default Home$$Page;
|
||||
function __$$eval(expr) {
|
||||
try {
|
||||
return expr();
|
||||
} catch (err) {
|
||||
try {
|
||||
if (window.handleEvalError) {
|
||||
window.handleEvalError('Failed to evaluate: ', expr, err);
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
function __$$evalArray(expr) {
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
import IntlMessageFormat from 'intl-messageformat';
|
||||
|
||||
const i18nConfig = {};
|
||||
|
||||
let locale = 'en-US';
|
||||
let locale = typeof navigator === 'object' && typeof navigator.language === 'string' ? navigator.language : 'zh-CN';
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -10,22 +8,61 @@ const setLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const msg = (i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) || defaultMessage;
|
||||
const isEmptyVariables = (variables) =>
|
||||
(Array.isArray(variables) && variables.length === 0) ||
|
||||
(typeof variables === 'object' && (!variables || Object.keys(variables).length === 0));
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) =>
|
||||
typeof msg === 'string' ? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? '') : msg;
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg = i18nConfig[locale]?.[id] ?? i18nConfig[locale.replace('-', '_')]?.[id] ?? defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn('[i18n]: unknown message id: %o (locale=%o)', id, locale);
|
||||
return `${id}`;
|
||||
return fallback === undefined ? `${id}` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
return format(msg, variables);
|
||||
};
|
||||
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace('-', '_')];
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, t.params);
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || 'zh_CN'] ?? t.en_US, t.params);
|
||||
};
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale,
|
||||
setLocale: target.setLocale,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const i18n = (id) => {
|
||||
return i18nFormat({ id });
|
||||
};
|
||||
|
||||
export { getLocale, setLocale, i18n, i18nFormat };
|
||||
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||
|
||||
@ -37,6 +37,8 @@ class Detail$$Page extends Component {
|
||||
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
} /* end of constructor */
|
||||
|
||||
componentDidMount() {
|
||||
@ -72,11 +74,6 @@ class Detail$$Page extends Component {
|
||||
);
|
||||
} /* end of render */
|
||||
|
||||
_i18nText(t) {
|
||||
const locale = this._context.getLocale();
|
||||
return t[locale] ?? t[String(locale).replace('-', '_')] ?? t[t.use || 'zh_CN'] ?? t.en_US;
|
||||
}
|
||||
|
||||
_createContext() {
|
||||
const self = this;
|
||||
const context = {
|
||||
@ -141,13 +138,7 @@ export default Detail$$Page;
|
||||
function __$$eval(expr) {
|
||||
try {
|
||||
return expr();
|
||||
} catch (err) {
|
||||
try {
|
||||
if (window.handleEvalError) {
|
||||
window.handleEvalError('Failed to evaluate: ', expr, err);
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
function __$$evalArray(expr) {
|
||||
|
||||
@ -37,6 +37,8 @@ class Home$$Page extends Component {
|
||||
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
} /* end of constructor */
|
||||
|
||||
componentDidMount() {
|
||||
@ -72,11 +74,6 @@ class Home$$Page extends Component {
|
||||
);
|
||||
} /* end of render */
|
||||
|
||||
_i18nText(t) {
|
||||
const locale = this._context.getLocale();
|
||||
return t[locale] ?? t[String(locale).replace('-', '_')] ?? t[t.use || 'zh_CN'] ?? t.en_US;
|
||||
}
|
||||
|
||||
_createContext() {
|
||||
const self = this;
|
||||
const context = {
|
||||
@ -141,13 +138,7 @@ export default Home$$Page;
|
||||
function __$$eval(expr) {
|
||||
try {
|
||||
return expr();
|
||||
} catch (err) {
|
||||
try {
|
||||
if (window.handleEvalError) {
|
||||
window.handleEvalError('Failed to evaluate: ', expr, err);
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
function __$$evalArray(expr) {
|
||||
|
||||
@ -37,6 +37,8 @@ class List$$Page extends Component {
|
||||
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
} /* end of constructor */
|
||||
|
||||
componentDidMount() {
|
||||
@ -75,11 +77,6 @@ class List$$Page extends Component {
|
||||
);
|
||||
} /* end of render */
|
||||
|
||||
_i18nText(t) {
|
||||
const locale = this._context.getLocale();
|
||||
return t[locale] ?? t[String(locale).replace('-', '_')] ?? t[t.use || 'zh_CN'] ?? t.en_US;
|
||||
}
|
||||
|
||||
_createContext() {
|
||||
const self = this;
|
||||
const context = {
|
||||
@ -144,13 +141,7 @@ export default List$$Page;
|
||||
function __$$eval(expr) {
|
||||
try {
|
||||
return expr();
|
||||
} catch (err) {
|
||||
try {
|
||||
if (window.handleEvalError) {
|
||||
window.handleEvalError('Failed to evaluate: ', expr, err);
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
function __$$evalArray(expr) {
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
import IntlMessageFormat from 'intl-messageformat';
|
||||
|
||||
const i18nConfig = {};
|
||||
|
||||
let locale = 'en-US';
|
||||
let locale = typeof navigator === 'object' && typeof navigator.language === 'string' ? navigator.language : 'zh-CN';
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -10,22 +8,61 @@ const setLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const msg = (i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) || defaultMessage;
|
||||
const isEmptyVariables = (variables) =>
|
||||
(Array.isArray(variables) && variables.length === 0) ||
|
||||
(typeof variables === 'object' && (!variables || Object.keys(variables).length === 0));
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) =>
|
||||
typeof msg === 'string' ? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? '') : msg;
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg = i18nConfig[locale]?.[id] ?? i18nConfig[locale.replace('-', '_')]?.[id] ?? defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn('[i18n]: unknown message id: %o (locale=%o)', id, locale);
|
||||
return `${id}`;
|
||||
return fallback === undefined ? `${id}` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
return format(msg, variables);
|
||||
};
|
||||
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace('-', '_')];
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, t.params);
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || 'zh_CN'] ?? t.en_US, t.params);
|
||||
};
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale,
|
||||
setLocale: target.setLocale,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const i18n = (id) => {
|
||||
return i18nFormat({ id });
|
||||
};
|
||||
|
||||
export { getLocale, setLocale, i18n, i18nFormat };
|
||||
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||
|
||||
@ -35,6 +35,8 @@ class Home$$Page extends Component {
|
||||
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
} /* end of constructor */
|
||||
|
||||
componentDidMount() {
|
||||
@ -67,11 +69,6 @@ class Home$$Page extends Component {
|
||||
);
|
||||
} /* end of render */
|
||||
|
||||
_i18nText(t) {
|
||||
const locale = this._context.getLocale();
|
||||
return t[locale] ?? t[String(locale).replace('-', '_')] ?? t[t.use || 'zh_CN'] ?? t.en_US;
|
||||
}
|
||||
|
||||
_createContext() {
|
||||
const self = this;
|
||||
const context = {
|
||||
@ -136,13 +133,7 @@ export default Home$$Page;
|
||||
function __$$eval(expr) {
|
||||
try {
|
||||
return expr();
|
||||
} catch (err) {
|
||||
try {
|
||||
if (window.handleEvalError) {
|
||||
window.handleEvalError('Failed to evaluate: ', expr, err);
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
function __$$evalArray(expr) {
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
import IntlMessageFormat from 'intl-messageformat';
|
||||
|
||||
const i18nConfig = {
|
||||
'zh-CN': {
|
||||
'hello-world': '你好,世界!',
|
||||
@ -9,7 +7,7 @@ const i18nConfig = {
|
||||
},
|
||||
};
|
||||
|
||||
let locale = 'en-US';
|
||||
let locale = typeof navigator === 'object' && typeof navigator.language === 'string' ? navigator.language : 'zh-CN';
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -17,22 +15,61 @@ const setLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const msg = (i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) || defaultMessage;
|
||||
const isEmptyVariables = (variables) =>
|
||||
(Array.isArray(variables) && variables.length === 0) ||
|
||||
(typeof variables === 'object' && (!variables || Object.keys(variables).length === 0));
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) =>
|
||||
typeof msg === 'string' ? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? '') : msg;
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg = i18nConfig[locale]?.[id] ?? i18nConfig[locale.replace('-', '_')]?.[id] ?? defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn('[i18n]: unknown message id: %o (locale=%o)', id, locale);
|
||||
return `${id}`;
|
||||
return fallback === undefined ? `${id}` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
return format(msg, variables);
|
||||
};
|
||||
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace('-', '_')];
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, t.params);
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || 'zh_CN'] ?? t.en_US, t.params);
|
||||
};
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale,
|
||||
setLocale: target.setLocale,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const i18n = (id) => {
|
||||
return i18nFormat({ id });
|
||||
};
|
||||
|
||||
export { getLocale, setLocale, i18n, i18nFormat };
|
||||
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||
|
||||
@ -33,6 +33,8 @@ class Home$$Page extends Component {
|
||||
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
} /* end of constructor */
|
||||
|
||||
componentDidMount() {
|
||||
@ -69,11 +71,6 @@ class Home$$Page extends Component {
|
||||
);
|
||||
} /* end of render */
|
||||
|
||||
_i18nText(t) {
|
||||
const locale = this._context.getLocale();
|
||||
return t[locale] ?? t[String(locale).replace('-', '_')] ?? t[t.use || 'zh_CN'] ?? t.en_US;
|
||||
}
|
||||
|
||||
_createContext() {
|
||||
const self = this;
|
||||
const context = {
|
||||
@ -138,13 +135,7 @@ export default Home$$Page;
|
||||
function __$$eval(expr) {
|
||||
try {
|
||||
return expr();
|
||||
} catch (err) {
|
||||
try {
|
||||
if (window.handleEvalError) {
|
||||
window.handleEvalError('Failed to evaluate: ', expr, err);
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
function __$$evalArray(expr) {
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
import IntlMessageFormat from 'intl-messageformat';
|
||||
|
||||
const i18nConfig = {
|
||||
'zh-CN': {
|
||||
'hello-world': '你好,世界!',
|
||||
@ -9,7 +7,7 @@ const i18nConfig = {
|
||||
},
|
||||
};
|
||||
|
||||
let locale = 'en-US';
|
||||
let locale = typeof navigator === 'object' && typeof navigator.language === 'string' ? navigator.language : 'zh-CN';
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -17,22 +15,61 @@ const setLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const msg = (i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) || defaultMessage;
|
||||
const isEmptyVariables = (variables) =>
|
||||
(Array.isArray(variables) && variables.length === 0) ||
|
||||
(typeof variables === 'object' && (!variables || Object.keys(variables).length === 0));
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) =>
|
||||
typeof msg === 'string' ? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? '') : msg;
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg = i18nConfig[locale]?.[id] ?? i18nConfig[locale.replace('-', '_')]?.[id] ?? defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn('[i18n]: unknown message id: %o (locale=%o)', id, locale);
|
||||
return `${id}`;
|
||||
return fallback === undefined ? `${id}` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
return format(msg, variables);
|
||||
};
|
||||
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace('-', '_')];
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, t.params);
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || 'zh_CN'] ?? t.en_US, t.params);
|
||||
};
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale,
|
||||
setLocale: target.setLocale,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const i18n = (id) => {
|
||||
return i18nFormat({ id });
|
||||
};
|
||||
|
||||
export { getLocale, setLocale, i18n, i18nFormat };
|
||||
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||
|
||||
@ -35,6 +35,8 @@ class Home$$Page extends Component {
|
||||
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
} /* end of constructor */
|
||||
|
||||
componentDidMount() {
|
||||
@ -75,11 +77,6 @@ class Home$$Page extends Component {
|
||||
);
|
||||
} /* end of render */
|
||||
|
||||
_i18nText(t) {
|
||||
const locale = this._context.getLocale();
|
||||
return t[locale] ?? t[String(locale).replace('-', '_')] ?? t[t.use || 'zh_CN'] ?? t.en_US;
|
||||
}
|
||||
|
||||
_createContext() {
|
||||
const self = this;
|
||||
const context = {
|
||||
@ -144,13 +141,7 @@ export default Home$$Page;
|
||||
function __$$eval(expr) {
|
||||
try {
|
||||
return expr();
|
||||
} catch (err) {
|
||||
try {
|
||||
if (window.handleEvalError) {
|
||||
window.handleEvalError('Failed to evaluate: ', expr, err);
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
function __$$evalArray(expr) {
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
import IntlMessageFormat from 'intl-messageformat';
|
||||
|
||||
const i18nConfig = {
|
||||
'zh-CN': {
|
||||
'hello-world': '你好,世界!',
|
||||
@ -9,7 +7,7 @@ const i18nConfig = {
|
||||
},
|
||||
};
|
||||
|
||||
let locale = 'en-US';
|
||||
let locale = typeof navigator === 'object' && typeof navigator.language === 'string' ? navigator.language : 'zh-CN';
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -17,22 +15,61 @@ const setLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const msg = (i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) || defaultMessage;
|
||||
const isEmptyVariables = (variables) =>
|
||||
(Array.isArray(variables) && variables.length === 0) ||
|
||||
(typeof variables === 'object' && (!variables || Object.keys(variables).length === 0));
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) =>
|
||||
typeof msg === 'string' ? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? '') : msg;
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg = i18nConfig[locale]?.[id] ?? i18nConfig[locale.replace('-', '_')]?.[id] ?? defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn('[i18n]: unknown message id: %o (locale=%o)', id, locale);
|
||||
return `${id}`;
|
||||
return fallback === undefined ? `${id}` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
return format(msg, variables);
|
||||
};
|
||||
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace('-', '_')];
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, t.params);
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || 'zh_CN'] ?? t.en_US, t.params);
|
||||
};
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale,
|
||||
setLocale: target.setLocale,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const i18n = (id) => {
|
||||
return i18nFormat({ id });
|
||||
};
|
||||
|
||||
export { getLocale, setLocale, i18n, i18nFormat };
|
||||
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||
|
||||
@ -33,6 +33,8 @@ class Home$$Page extends Component {
|
||||
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
} /* end of constructor */
|
||||
|
||||
componentDidMount() {
|
||||
@ -69,11 +71,6 @@ class Home$$Page extends Component {
|
||||
);
|
||||
} /* end of render */
|
||||
|
||||
_i18nText(t) {
|
||||
const locale = this._context.getLocale();
|
||||
return t[locale] ?? t[String(locale).replace('-', '_')] ?? t[t.use || 'zh_CN'] ?? t.en_US;
|
||||
}
|
||||
|
||||
_createContext() {
|
||||
const self = this;
|
||||
const context = {
|
||||
@ -138,13 +135,7 @@ export default Home$$Page;
|
||||
function __$$eval(expr) {
|
||||
try {
|
||||
return expr();
|
||||
} catch (err) {
|
||||
try {
|
||||
if (window.handleEvalError) {
|
||||
window.handleEvalError('Failed to evaluate: ', expr, err);
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
function __$$evalArray(expr) {
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
import IntlMessageFormat from 'intl-messageformat';
|
||||
|
||||
const i18nConfig = {
|
||||
'zh-CN': {
|
||||
'hello-world': '你好,世界!',
|
||||
@ -9,7 +7,7 @@ const i18nConfig = {
|
||||
},
|
||||
};
|
||||
|
||||
let locale = 'en-US';
|
||||
let locale = typeof navigator === 'object' && typeof navigator.language === 'string' ? navigator.language : 'zh-CN';
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -17,22 +15,61 @@ const setLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const msg = (i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) || defaultMessage;
|
||||
const isEmptyVariables = (variables) =>
|
||||
(Array.isArray(variables) && variables.length === 0) ||
|
||||
(typeof variables === 'object' && (!variables || Object.keys(variables).length === 0));
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) =>
|
||||
typeof msg === 'string' ? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? '') : msg;
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg = i18nConfig[locale]?.[id] ?? i18nConfig[locale.replace('-', '_')]?.[id] ?? defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn('[i18n]: unknown message id: %o (locale=%o)', id, locale);
|
||||
return `${id}`;
|
||||
return fallback === undefined ? `${id}` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
return format(msg, variables);
|
||||
};
|
||||
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace('-', '_')];
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, t.params);
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || 'zh_CN'] ?? t.en_US, t.params);
|
||||
};
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale,
|
||||
setLocale: target.setLocale,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const i18n = (id) => {
|
||||
return i18nFormat({ id });
|
||||
};
|
||||
|
||||
export { getLocale, setLocale, i18n, i18nFormat };
|
||||
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||
|
||||
@ -35,6 +35,8 @@ class Home$$Page extends Component {
|
||||
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
} /* end of constructor */
|
||||
|
||||
componentDidMount() {
|
||||
@ -75,11 +77,6 @@ class Home$$Page extends Component {
|
||||
);
|
||||
} /* end of render */
|
||||
|
||||
_i18nText(t) {
|
||||
const locale = this._context.getLocale();
|
||||
return t[locale] ?? t[String(locale).replace('-', '_')] ?? t[t.use || 'zh_CN'] ?? t.en_US;
|
||||
}
|
||||
|
||||
_createContext() {
|
||||
const self = this;
|
||||
const context = {
|
||||
@ -144,13 +141,7 @@ export default Home$$Page;
|
||||
function __$$eval(expr) {
|
||||
try {
|
||||
return expr();
|
||||
} catch (err) {
|
||||
try {
|
||||
if (window.handleEvalError) {
|
||||
window.handleEvalError('Failed to evaluate: ', expr, err);
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
function __$$evalArray(expr) {
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
import IntlMessageFormat from 'intl-messageformat';
|
||||
|
||||
const i18nConfig = {
|
||||
'zh-CN': {
|
||||
'hello-world': '你好,世界!',
|
||||
@ -9,7 +7,7 @@ const i18nConfig = {
|
||||
},
|
||||
};
|
||||
|
||||
let locale = 'en-US';
|
||||
let locale = typeof navigator === 'object' && typeof navigator.language === 'string' ? navigator.language : 'zh-CN';
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -17,22 +15,61 @@ const setLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const msg = (i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) || defaultMessage;
|
||||
const isEmptyVariables = (variables) =>
|
||||
(Array.isArray(variables) && variables.length === 0) ||
|
||||
(typeof variables === 'object' && (!variables || Object.keys(variables).length === 0));
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) =>
|
||||
typeof msg === 'string' ? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? '') : msg;
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg = i18nConfig[locale]?.[id] ?? i18nConfig[locale.replace('-', '_')]?.[id] ?? defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn('[i18n]: unknown message id: %o (locale=%o)', id, locale);
|
||||
return `${id}`;
|
||||
return fallback === undefined ? `${id}` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
return format(msg, variables);
|
||||
};
|
||||
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace('-', '_')];
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, t.params);
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || 'zh_CN'] ?? t.en_US, t.params);
|
||||
};
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale,
|
||||
setLocale: target.setLocale,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const i18n = (id) => {
|
||||
return i18nFormat({ id });
|
||||
};
|
||||
|
||||
export { getLocale, setLocale, i18n, i18nFormat };
|
||||
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||
|
||||
@ -35,6 +35,8 @@ class Home$$Page extends Component {
|
||||
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
} /* end of constructor */
|
||||
|
||||
componentDidMount() {
|
||||
@ -78,11 +80,6 @@ class Home$$Page extends Component {
|
||||
);
|
||||
} /* end of render */
|
||||
|
||||
_i18nText(t) {
|
||||
const locale = this._context.getLocale();
|
||||
return t[locale] ?? t[String(locale).replace('-', '_')] ?? t[t.use || 'zh_CN'] ?? t.en_US;
|
||||
}
|
||||
|
||||
_createContext() {
|
||||
const self = this;
|
||||
const context = {
|
||||
@ -147,13 +144,7 @@ export default Home$$Page;
|
||||
function __$$eval(expr) {
|
||||
try {
|
||||
return expr();
|
||||
} catch (err) {
|
||||
try {
|
||||
if (window.handleEvalError) {
|
||||
window.handleEvalError('Failed to evaluate: ', expr, err);
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
function __$$evalArray(expr) {
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
import IntlMessageFormat from 'intl-messageformat';
|
||||
|
||||
const i18nConfig = {
|
||||
'zh-CN': {
|
||||
'hello-world': '你好,世界!',
|
||||
@ -9,7 +7,7 @@ const i18nConfig = {
|
||||
},
|
||||
};
|
||||
|
||||
let locale = 'en-US';
|
||||
let locale = typeof navigator === 'object' && typeof navigator.language === 'string' ? navigator.language : 'zh-CN';
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -17,22 +15,61 @@ const setLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const msg = (i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) || defaultMessage;
|
||||
const isEmptyVariables = (variables) =>
|
||||
(Array.isArray(variables) && variables.length === 0) ||
|
||||
(typeof variables === 'object' && (!variables || Object.keys(variables).length === 0));
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) =>
|
||||
typeof msg === 'string' ? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? '') : msg;
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg = i18nConfig[locale]?.[id] ?? i18nConfig[locale.replace('-', '_')]?.[id] ?? defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn('[i18n]: unknown message id: %o (locale=%o)', id, locale);
|
||||
return `${id}`;
|
||||
return fallback === undefined ? `${id}` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
return format(msg, variables);
|
||||
};
|
||||
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace('-', '_')];
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, t.params);
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || 'zh_CN'] ?? t.en_US, t.params);
|
||||
};
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale,
|
||||
setLocale: target.setLocale,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const i18n = (id) => {
|
||||
return i18nFormat({ id });
|
||||
};
|
||||
|
||||
export { getLocale, setLocale, i18n, i18nFormat };
|
||||
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||
|
||||
@ -35,6 +35,8 @@ class Home$$Page extends Component {
|
||||
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
} /* end of constructor */
|
||||
|
||||
componentDidMount() {
|
||||
@ -80,11 +82,6 @@ class Home$$Page extends Component {
|
||||
);
|
||||
} /* end of render */
|
||||
|
||||
_i18nText(t) {
|
||||
const locale = this._context.getLocale();
|
||||
return t[locale] ?? t[String(locale).replace('-', '_')] ?? t[t.use || 'zh_CN'] ?? t.en_US;
|
||||
}
|
||||
|
||||
_createContext() {
|
||||
const self = this;
|
||||
const context = {
|
||||
@ -149,13 +146,7 @@ export default Home$$Page;
|
||||
function __$$eval(expr) {
|
||||
try {
|
||||
return expr();
|
||||
} catch (err) {
|
||||
try {
|
||||
if (window.handleEvalError) {
|
||||
window.handleEvalError('Failed to evaluate: ', expr, err);
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
function __$$evalArray(expr) {
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
import IntlMessageFormat from 'intl-messageformat';
|
||||
|
||||
const i18nConfig = {};
|
||||
|
||||
let locale = 'en-US';
|
||||
let locale = typeof navigator === 'object' && typeof navigator.language === 'string' ? navigator.language : 'zh-CN';
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -10,22 +8,61 @@ const setLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const msg = (i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) || defaultMessage;
|
||||
const isEmptyVariables = (variables) =>
|
||||
(Array.isArray(variables) && variables.length === 0) ||
|
||||
(typeof variables === 'object' && (!variables || Object.keys(variables).length === 0));
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) =>
|
||||
typeof msg === 'string' ? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? '') : msg;
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg = i18nConfig[locale]?.[id] ?? i18nConfig[locale.replace('-', '_')]?.[id] ?? defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn('[i18n]: unknown message id: %o (locale=%o)', id, locale);
|
||||
return `${id}`;
|
||||
return fallback === undefined ? `${id}` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
return format(msg, variables);
|
||||
};
|
||||
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace('-', '_')];
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, t.params);
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || 'zh_CN'] ?? t.en_US, t.params);
|
||||
};
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale,
|
||||
setLocale: target.setLocale,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const i18n = (id) => {
|
||||
return i18nFormat({ id });
|
||||
};
|
||||
|
||||
export { getLocale, setLocale, i18n, i18nFormat };
|
||||
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||
|
||||
@ -40,6 +40,8 @@ class Aaaa$$Page extends Component {
|
||||
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
} /* end of constructor */
|
||||
|
||||
componentDidMount() {
|
||||
@ -70,11 +72,6 @@ class Aaaa$$Page extends Component {
|
||||
);
|
||||
} /* end of render */
|
||||
|
||||
_i18nText(t) {
|
||||
const locale = this._context.getLocale();
|
||||
return t[locale] ?? t[String(locale).replace('-', '_')] ?? t[t.use || 'zh_CN'] ?? t.en_US;
|
||||
}
|
||||
|
||||
_createContext() {
|
||||
const self = this;
|
||||
const context = {
|
||||
@ -161,13 +158,7 @@ export default Aaaa$$Page;
|
||||
function __$$eval(expr) {
|
||||
try {
|
||||
return expr();
|
||||
} catch (err) {
|
||||
try {
|
||||
if (window.handleEvalError) {
|
||||
window.handleEvalError('Failed to evaluate: ', expr, err);
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
function __$$evalArray(expr) {
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
import IntlMessageFormat from 'intl-messageformat';
|
||||
|
||||
const i18nConfig = {
|
||||
'zh-CN': {
|
||||
'hello-world': '你好,世界!',
|
||||
@ -9,7 +7,7 @@ const i18nConfig = {
|
||||
},
|
||||
};
|
||||
|
||||
let locale = 'en-US';
|
||||
let locale = typeof navigator === 'object' && typeof navigator.language === 'string' ? navigator.language : 'zh-CN';
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -17,22 +15,61 @@ const setLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const msg = (i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) || defaultMessage;
|
||||
const isEmptyVariables = (variables) =>
|
||||
(Array.isArray(variables) && variables.length === 0) ||
|
||||
(typeof variables === 'object' && (!variables || Object.keys(variables).length === 0));
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) =>
|
||||
typeof msg === 'string' ? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? '') : msg;
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg = i18nConfig[locale]?.[id] ?? i18nConfig[locale.replace('-', '_')]?.[id] ?? defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn('[i18n]: unknown message id: %o (locale=%o)', id, locale);
|
||||
return `${id}`;
|
||||
return fallback === undefined ? `${id}` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
return format(msg, variables);
|
||||
};
|
||||
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace('-', '_')];
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, t.params);
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || 'zh_CN'] ?? t.en_US, t.params);
|
||||
};
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale,
|
||||
setLocale: target.setLocale,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const i18n = (id) => {
|
||||
return i18nFormat({ id });
|
||||
};
|
||||
|
||||
export { getLocale, setLocale, i18n, i18nFormat };
|
||||
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||
|
||||
@ -33,6 +33,8 @@ class Home$$Page extends Component {
|
||||
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
} /* end of constructor */
|
||||
|
||||
componentDidMount() {
|
||||
@ -70,11 +72,6 @@ class Home$$Page extends Component {
|
||||
);
|
||||
} /* end of render */
|
||||
|
||||
_i18nText(t) {
|
||||
const locale = this._context.getLocale();
|
||||
return t[locale] ?? t[String(locale).replace('-', '_')] ?? t[t.use || 'zh_CN'] ?? t.en_US;
|
||||
}
|
||||
|
||||
_createContext() {
|
||||
const self = this;
|
||||
const context = {
|
||||
@ -152,13 +149,7 @@ export default Home$$Page;
|
||||
function __$$eval(expr) {
|
||||
try {
|
||||
return expr();
|
||||
} catch (err) {
|
||||
try {
|
||||
if (window.handleEvalError) {
|
||||
window.handleEvalError('Failed to evaluate: ', expr, err);
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
function __$$evalArray(expr) {
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
import IntlMessageFormat from 'intl-messageformat';
|
||||
|
||||
const i18nConfig = {};
|
||||
|
||||
let locale = 'en-US';
|
||||
let locale = typeof navigator === 'object' && typeof navigator.language === 'string' ? navigator.language : 'zh-CN';
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -10,22 +8,61 @@ const setLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const msg = (i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) || defaultMessage;
|
||||
const isEmptyVariables = (variables) =>
|
||||
(Array.isArray(variables) && variables.length === 0) ||
|
||||
(typeof variables === 'object' && (!variables || Object.keys(variables).length === 0));
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) =>
|
||||
typeof msg === 'string' ? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? '') : msg;
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg = i18nConfig[locale]?.[id] ?? i18nConfig[locale.replace('-', '_')]?.[id] ?? defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn('[i18n]: unknown message id: %o (locale=%o)', id, locale);
|
||||
return `${id}`;
|
||||
return fallback === undefined ? `${id}` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
return format(msg, variables);
|
||||
};
|
||||
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace('-', '_')];
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, t.params);
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || 'zh_CN'] ?? t.en_US, t.params);
|
||||
};
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale,
|
||||
setLocale: target.setLocale,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const i18n = (id) => {
|
||||
return i18nFormat({ id });
|
||||
};
|
||||
|
||||
export { getLocale, setLocale, i18n, i18nFormat };
|
||||
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||
|
||||
@ -36,6 +36,8 @@ class Example$$Page extends Component {
|
||||
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
} /* end of constructor */
|
||||
|
||||
componentDidMount() {
|
||||
@ -72,11 +74,6 @@ class Example$$Page extends Component {
|
||||
);
|
||||
} /* end of render */
|
||||
|
||||
_i18nText(t) {
|
||||
const locale = this._context.getLocale();
|
||||
return t[locale] ?? t[String(locale).replace('-', '_')] ?? t[t.use || 'zh_CN'] ?? t.en_US;
|
||||
}
|
||||
|
||||
_createContext() {
|
||||
const self = this;
|
||||
const context = {
|
||||
@ -163,13 +160,7 @@ export default Example$$Page;
|
||||
function __$$eval(expr) {
|
||||
try {
|
||||
return expr();
|
||||
} catch (err) {
|
||||
try {
|
||||
if (window.handleEvalError) {
|
||||
window.handleEvalError('Failed to evaluate: ', expr, err);
|
||||
}
|
||||
} catch (e) {}
|
||||
}
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
function __$$evalArray(expr) {
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
import IntlMessageFormat from "intl-messageformat";
|
||||
|
||||
const i18nConfig = {};
|
||||
|
||||
let locale = "en-US";
|
||||
let locale =
|
||||
typeof navigator === "object" && typeof navigator.language === "string"
|
||||
? navigator.language
|
||||
: "zh-CN";
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -10,24 +11,67 @@ const setLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const isEmptyVariables = (variables) =>
|
||||
(Array.isArray(variables) && variables.length === 0) ||
|
||||
(typeof variables === "object" &&
|
||||
(!variables || Object.keys(variables).length === 0));
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) =>
|
||||
typeof msg === "string"
|
||||
? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? "")
|
||||
: msg;
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg =
|
||||
(i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) ||
|
||||
i18nConfig[locale]?.[id] ??
|
||||
i18nConfig[locale.replace("-", "_")]?.[id] ??
|
||||
defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn("[i18n]: unknown message id: %o (locale=%o)", id, locale);
|
||||
return `${id}`;
|
||||
return fallback === undefined ? `${id}` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
return format(msg, variables);
|
||||
};
|
||||
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace("-", "_")];
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, t.params);
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || "zh_CN"] ?? t.en_US, t.params);
|
||||
};
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale,
|
||||
setLocale: target.setLocale,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const i18n = (id) => {
|
||||
return i18nFormat({ id });
|
||||
};
|
||||
|
||||
export { getLocale, setLocale, i18n, i18nFormat };
|
||||
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。
|
||||
// 例外:react 框架的导出名和各种组件名除外。
|
||||
import React from "react";
|
||||
|
||||
import { Form, Input, NumberPicker, Select, Button } from "@alifd/next";
|
||||
@ -10,11 +12,13 @@ import { create as __$$createDataSourceEngine } from "@alilc/lowcode-datasource-
|
||||
|
||||
import utils, { RefsManager } from "../../utils";
|
||||
|
||||
import { i18n as _$$i18n } from "../../i18n";
|
||||
import * as __$$i18n from "../../i18n";
|
||||
|
||||
import "./index.css";
|
||||
|
||||
class Test$$Page extends React.Component {
|
||||
_context = this;
|
||||
|
||||
_dataSourceConfig = this._defineDataSourceConfig();
|
||||
_dataSourceEngine = __$$createDataSourceEngine(this._dataSourceConfig, this, {
|
||||
runtimeConfig: true,
|
||||
@ -39,6 +43,8 @@ class Test$$Page extends React.Component {
|
||||
|
||||
this._refsManager = new RefsManager();
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
|
||||
this.state = { text: "outter" };
|
||||
}
|
||||
|
||||
@ -113,10 +119,6 @@ class Test$$Page extends React.Component {
|
||||
};
|
||||
}
|
||||
|
||||
i18n = (i18nKey) => {
|
||||
return _$$i18n(i18nKey);
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this._dataSourceEngine.reloadDataSource();
|
||||
|
||||
@ -124,12 +126,12 @@ class Test$$Page extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const __$$context = this;
|
||||
const { state } = this;
|
||||
const __$$context = this._context || this;
|
||||
const { state } = __$$context;
|
||||
return (
|
||||
<div ref={this._refsManager.linkRef("outterView")} autoLoading={true}>
|
||||
<Form
|
||||
labelCol={this.state.colNum}
|
||||
labelCol={__$$eval(() => this.state.colNum)}
|
||||
style={{}}
|
||||
ref={this._refsManager.linkRef("testForm")}
|
||||
>
|
||||
@ -150,11 +152,11 @@ class Test$$Page extends React.Component {
|
||||
</Form.Item>
|
||||
<div style={{ textAlign: "center" }}>
|
||||
<Button.Group>
|
||||
{["a", "b", "c"].map((item, index) =>
|
||||
{__$$evalArray(() => ["a", "b", "c"]).map((item, index) =>
|
||||
((__$$context) =>
|
||||
!!(index >= 1) && (
|
||||
!!__$$eval(() => index >= 1) && (
|
||||
<Button type="primary" style={{ margin: "0 5px 0 5px" }}>
|
||||
{item}
|
||||
{__$$eval(() => item)}
|
||||
</Button>
|
||||
))(__$$createChildContext(__$$context, { item, index }))
|
||||
)}
|
||||
@ -168,6 +170,17 @@ class Test$$Page extends React.Component {
|
||||
|
||||
export default Test$$Page;
|
||||
|
||||
function __$$eval(expr) {
|
||||
try {
|
||||
return expr();
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
function __$$evalArray(expr) {
|
||||
const res = __$$eval(expr);
|
||||
return Array.isArray(res) ? res : [];
|
||||
}
|
||||
|
||||
function __$$createChildContext(oldContext, ext) {
|
||||
const childContext = {
|
||||
...oldContext,
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
import IntlMessageFormat from "intl-messageformat";
|
||||
|
||||
const i18nConfig = {};
|
||||
|
||||
let locale = "en-US";
|
||||
let locale =
|
||||
typeof navigator === "object" && typeof navigator.language === "string"
|
||||
? navigator.language
|
||||
: "zh-CN";
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -10,24 +11,67 @@ const setLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const isEmptyVariables = (variables) =>
|
||||
(Array.isArray(variables) && variables.length === 0) ||
|
||||
(typeof variables === "object" &&
|
||||
(!variables || Object.keys(variables).length === 0));
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) =>
|
||||
typeof msg === "string"
|
||||
? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? "")
|
||||
: msg;
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg =
|
||||
(i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) ||
|
||||
i18nConfig[locale]?.[id] ??
|
||||
i18nConfig[locale.replace("-", "_")]?.[id] ??
|
||||
defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn("[i18n]: unknown message id: %o (locale=%o)", id, locale);
|
||||
return `${id}`;
|
||||
return fallback === undefined ? `${id}` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
return format(msg, variables);
|
||||
};
|
||||
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace("-", "_")];
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, t.params);
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || "zh_CN"] ?? t.en_US, t.params);
|
||||
};
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale,
|
||||
setLocale: target.setLocale,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const i18n = (id) => {
|
||||
return i18nFormat({ id });
|
||||
};
|
||||
|
||||
export { getLocale, setLocale, i18n, i18nFormat };
|
||||
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。
|
||||
// 例外:react 框架的导出名和各种组件名除外。
|
||||
import React from "react";
|
||||
|
||||
import { Page } from "@alilc/b6-page";
|
||||
@ -10,11 +12,13 @@ import { create as __$$createDataSourceEngine } from "@alilc/lowcode-datasource-
|
||||
|
||||
import utils from "../../utils";
|
||||
|
||||
import { i18n as _$$i18n } from "../../i18n";
|
||||
import * as __$$i18n from "../../i18n";
|
||||
|
||||
import "./index.css";
|
||||
|
||||
class Aaaa$$Page extends React.Component {
|
||||
_context = this;
|
||||
|
||||
_dataSourceConfig = this._defineDataSourceConfig();
|
||||
_dataSourceEngine = __$$createDataSourceEngine(this._dataSourceConfig, this, {
|
||||
runtimeConfig: true,
|
||||
@ -36,9 +40,15 @@ class Aaaa$$Page extends React.Component {
|
||||
|
||||
this.utils = utils;
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
|
||||
this.state = {};
|
||||
}
|
||||
|
||||
$ = () => null;
|
||||
|
||||
$$ = () => [];
|
||||
|
||||
_defineDataSourceConfig() {
|
||||
const _this = this;
|
||||
return {
|
||||
@ -60,17 +70,13 @@ class Aaaa$$Page extends React.Component {
|
||||
};
|
||||
}
|
||||
|
||||
i18n = (i18nKey) => {
|
||||
return _$$i18n(i18nKey);
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this._dataSourceEngine.reloadDataSource();
|
||||
}
|
||||
|
||||
render() {
|
||||
const __$$context = this;
|
||||
const { state } = this;
|
||||
const __$$context = this._context || this;
|
||||
const { state } = __$$context;
|
||||
return (
|
||||
<div title="" backgroundColor="#fff" textColor="#333" style={{}}>
|
||||
<Text
|
||||
@ -85,6 +91,17 @@ class Aaaa$$Page extends React.Component {
|
||||
|
||||
export default Aaaa$$Page;
|
||||
|
||||
function __$$eval(expr) {
|
||||
try {
|
||||
return expr();
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
function __$$evalArray(expr) {
|
||||
const res = __$$eval(expr);
|
||||
return Array.isArray(res) ? res : [];
|
||||
}
|
||||
|
||||
function __$$createChildContext(oldContext, ext) {
|
||||
const childContext = {
|
||||
...oldContext,
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
import IntlMessageFormat from "intl-messageformat";
|
||||
|
||||
const i18nConfig = {
|
||||
"zh-CN": {
|
||||
"i18n-jwg27yo4": "你好",
|
||||
@ -11,7 +9,10 @@ const i18nConfig = {
|
||||
},
|
||||
};
|
||||
|
||||
let locale = "en-US";
|
||||
let locale =
|
||||
typeof navigator === "object" && typeof navigator.language === "string"
|
||||
? navigator.language
|
||||
: "zh-CN";
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -19,24 +20,67 @@ const setLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const isEmptyVariables = (variables) =>
|
||||
(Array.isArray(variables) && variables.length === 0) ||
|
||||
(typeof variables === "object" &&
|
||||
(!variables || Object.keys(variables).length === 0));
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) =>
|
||||
typeof msg === "string"
|
||||
? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? "")
|
||||
: msg;
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg =
|
||||
(i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) ||
|
||||
i18nConfig[locale]?.[id] ??
|
||||
i18nConfig[locale.replace("-", "_")]?.[id] ??
|
||||
defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn("[i18n]: unknown message id: %o (locale=%o)", id, locale);
|
||||
return `${id}`;
|
||||
return fallback === undefined ? `${id}` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
return format(msg, variables);
|
||||
};
|
||||
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace("-", "_")];
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, t.params);
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || "zh_CN"] ?? t.en_US, t.params);
|
||||
};
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale,
|
||||
setLocale: target.setLocale,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const i18n = (id) => {
|
||||
return i18nFormat({ id });
|
||||
};
|
||||
|
||||
export { getLocale, setLocale, i18n, i18nFormat };
|
||||
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||
|
||||
@ -1,14 +1,18 @@
|
||||
// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。
|
||||
// 例外:react 框架的导出名和各种组件名除外。
|
||||
import React from "react";
|
||||
|
||||
import { Form, Input, NumberPicker, Select, Button } from "@alifd/next";
|
||||
|
||||
import utils, { RefsManager } from "../../utils";
|
||||
|
||||
import { i18n as _$$i18n } from "../../i18n";
|
||||
import * as __$$i18n from "../../i18n";
|
||||
|
||||
import "./index.css";
|
||||
|
||||
class Test$$Page extends React.Component {
|
||||
_context = this;
|
||||
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
@ -16,6 +20,8 @@ class Test$$Page extends React.Component {
|
||||
|
||||
this._refsManager = new RefsManager();
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
|
||||
this.state = { text: "outter" };
|
||||
}
|
||||
|
||||
@ -27,26 +33,22 @@ class Test$$Page extends React.Component {
|
||||
return this._refsManager.getAll(refName);
|
||||
};
|
||||
|
||||
i18n = (i18nKey) => {
|
||||
return _$$i18n(i18nKey);
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
console.log("componentDidMount");
|
||||
}
|
||||
|
||||
render() {
|
||||
const __$$context = this;
|
||||
const { state } = this;
|
||||
const __$$context = this._context || this;
|
||||
const { state } = __$$context;
|
||||
return (
|
||||
<div ref={this._refsManager.linkRef("outterView")} autoLoading={true}>
|
||||
<Form
|
||||
labelCol={this.state.colNum}
|
||||
labelCol={__$$eval(() => this.state.colNum)}
|
||||
style={{}}
|
||||
ref={this._refsManager.linkRef("testForm")}
|
||||
>
|
||||
<Form.Item
|
||||
label={this.i18n("i18n-jwg27yo4")}
|
||||
label={__$$eval(() => this.i18n("i18n-jwg27yo4"))}
|
||||
name="name"
|
||||
initValue="李雷"
|
||||
>
|
||||
@ -90,6 +92,17 @@ class Test$$Page extends React.Component {
|
||||
|
||||
export default Test$$Page;
|
||||
|
||||
function __$$eval(expr) {
|
||||
try {
|
||||
return expr();
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
function __$$evalArray(expr) {
|
||||
const res = __$$eval(expr);
|
||||
return Array.isArray(res) ? res : [];
|
||||
}
|
||||
|
||||
function __$$createChildContext(oldContext, ext) {
|
||||
const childContext = {
|
||||
...oldContext,
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
import IntlMessageFormat from "intl-messageformat";
|
||||
|
||||
const i18nConfig = {
|
||||
"zh-CN": {
|
||||
"i18n-jwg27yo4": "你好",
|
||||
@ -11,7 +9,10 @@ const i18nConfig = {
|
||||
},
|
||||
};
|
||||
|
||||
let locale = "en-US";
|
||||
let locale =
|
||||
typeof navigator === "object" && typeof navigator.language === "string"
|
||||
? navigator.language
|
||||
: "zh-CN";
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -19,24 +20,67 @@ const setLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const isEmptyVariables = (variables) =>
|
||||
(Array.isArray(variables) && variables.length === 0) ||
|
||||
(typeof variables === "object" &&
|
||||
(!variables || Object.keys(variables).length === 0));
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) =>
|
||||
typeof msg === "string"
|
||||
? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? "")
|
||||
: msg;
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg =
|
||||
(i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) ||
|
||||
i18nConfig[locale]?.[id] ??
|
||||
i18nConfig[locale.replace("-", "_")]?.[id] ??
|
||||
defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn("[i18n]: unknown message id: %o (locale=%o)", id, locale);
|
||||
return `${id}`;
|
||||
return fallback === undefined ? `${id}` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
return format(msg, variables);
|
||||
};
|
||||
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace("-", "_")];
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, t.params);
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || "zh_CN"] ?? t.en_US, t.params);
|
||||
};
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale,
|
||||
setLocale: target.setLocale,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const i18n = (id) => {
|
||||
return i18nFormat({ id });
|
||||
};
|
||||
|
||||
export { getLocale, setLocale, i18n, i18nFormat };
|
||||
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。
|
||||
// 例外:react 框架的导出名和各种组件名除外。
|
||||
import React from "react";
|
||||
|
||||
import Super, {
|
||||
@ -13,7 +15,7 @@ import SuperOther from "@alifd/next";
|
||||
|
||||
import utils from "../../utils";
|
||||
|
||||
import { i18n as _$$i18n } from "../../i18n";
|
||||
import * as __$$i18n from "../../i18n";
|
||||
|
||||
import "./index.css";
|
||||
|
||||
@ -24,26 +26,30 @@ const SelectOption = Select.Option;
|
||||
const SearchTable = SearchTableExport.default;
|
||||
|
||||
class Test$$Page extends React.Component {
|
||||
_context = this;
|
||||
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
this.utils = utils;
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
|
||||
this.state = {};
|
||||
}
|
||||
|
||||
i18n = (i18nKey) => {
|
||||
return _$$i18n(i18nKey);
|
||||
};
|
||||
$ = () => null;
|
||||
|
||||
$$ = () => [];
|
||||
|
||||
componentDidMount() {}
|
||||
|
||||
render() {
|
||||
const __$$context = this;
|
||||
const { state } = this;
|
||||
const __$$context = this._context || this;
|
||||
const { state } = __$$context;
|
||||
return (
|
||||
<div>
|
||||
<Super title={this.state.title} />
|
||||
<Super title={__$$eval(() => this.state.title)} />
|
||||
<SuperSub />
|
||||
<SuperOther />
|
||||
<Button />
|
||||
@ -60,6 +66,17 @@ class Test$$Page extends React.Component {
|
||||
|
||||
export default Test$$Page;
|
||||
|
||||
function __$$eval(expr) {
|
||||
try {
|
||||
return expr();
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
function __$$evalArray(expr) {
|
||||
const res = __$$eval(expr);
|
||||
return Array.isArray(res) ? res : [];
|
||||
}
|
||||
|
||||
function __$$createChildContext(oldContext, ext) {
|
||||
const childContext = {
|
||||
...oldContext,
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
import IntlMessageFormat from "intl-messageformat";
|
||||
|
||||
const i18nConfig = {};
|
||||
|
||||
let locale = "en-US";
|
||||
let locale =
|
||||
typeof navigator === "object" && typeof navigator.language === "string"
|
||||
? navigator.language
|
||||
: "zh-CN";
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -10,24 +11,67 @@ const setLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const isEmptyVariables = (variables) =>
|
||||
(Array.isArray(variables) && variables.length === 0) ||
|
||||
(typeof variables === "object" &&
|
||||
(!variables || Object.keys(variables).length === 0));
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) =>
|
||||
typeof msg === "string"
|
||||
? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? "")
|
||||
: msg;
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg =
|
||||
(i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) ||
|
||||
i18nConfig[locale]?.[id] ??
|
||||
i18nConfig[locale.replace("-", "_")]?.[id] ??
|
||||
defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn("[i18n]: unknown message id: %o (locale=%o)", id, locale);
|
||||
return `${id}`;
|
||||
return fallback === undefined ? `${id}` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
return format(msg, variables);
|
||||
};
|
||||
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace("-", "_")];
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, t.params);
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || "zh_CN"] ?? t.en_US, t.params);
|
||||
};
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale,
|
||||
setLocale: target.setLocale,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const i18n = (id) => {
|
||||
return i18nFormat({ id });
|
||||
};
|
||||
|
||||
export { getLocale, setLocale, i18n, i18nFormat };
|
||||
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。
|
||||
// 例外:react 框架的导出名和各种组件名除外。
|
||||
import React from "react";
|
||||
|
||||
import {
|
||||
@ -15,7 +17,7 @@ import { create as __$$createDataSourceEngine } from "@alilc/lowcode-datasource-
|
||||
|
||||
import utils, { RefsManager } from "../../utils";
|
||||
|
||||
import { i18n as _$$i18n } from "../../i18n";
|
||||
import * as __$$i18n from "../../i18n";
|
||||
|
||||
import "./index.css";
|
||||
|
||||
@ -24,6 +26,8 @@ const NextBlockCell = NextBlock.Cell;
|
||||
const AliSearchTable = AliSearchTableExport.default;
|
||||
|
||||
class Test$$Page extends React.Component {
|
||||
_context = this;
|
||||
|
||||
_dataSourceConfig = this._defineDataSourceConfig();
|
||||
_dataSourceEngine = __$$createDataSourceEngine(this._dataSourceConfig, this, {
|
||||
runtimeConfig: true,
|
||||
@ -45,6 +49,8 @@ class Test$$Page extends React.Component {
|
||||
|
||||
this._refsManager = new RefsManager();
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
|
||||
this.state = { text: "outter", isShowDialog: false };
|
||||
}
|
||||
|
||||
@ -81,10 +87,6 @@ class Test$$Page extends React.Component {
|
||||
};
|
||||
}
|
||||
|
||||
i18n = (i18nKey) => {
|
||||
return _$$i18n(i18nKey);
|
||||
};
|
||||
|
||||
componentWillUnmount() {
|
||||
console.log("will umount");
|
||||
}
|
||||
@ -133,8 +135,8 @@ class Test$$Page extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const __$$context = this;
|
||||
const { state } = this;
|
||||
const __$$context = this._context || this;
|
||||
const { state } = __$$context;
|
||||
return (
|
||||
<div
|
||||
ref={this._refsManager.linkRef("outterView")}
|
||||
@ -188,7 +190,7 @@ class Test$$Page extends React.Component {
|
||||
flex={true}
|
||||
>
|
||||
<AliSearchTable
|
||||
dataSource={this.state.users.data}
|
||||
dataSource={__$$eval(() => this.state.users.data)}
|
||||
rowKey="workid"
|
||||
columns={[
|
||||
{ title: "花名", dataIndex: "cname" },
|
||||
@ -263,6 +265,17 @@ class Test$$Page extends React.Component {
|
||||
|
||||
export default Test$$Page;
|
||||
|
||||
function __$$eval(expr) {
|
||||
try {
|
||||
return expr();
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
function __$$evalArray(expr) {
|
||||
const res = __$$eval(expr);
|
||||
return Array.isArray(res) ? res : [];
|
||||
}
|
||||
|
||||
function __$$createChildContext(oldContext, ext) {
|
||||
const childContext = {
|
||||
...oldContext,
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
import IntlMessageFormat from "intl-messageformat";
|
||||
|
||||
const i18nConfig = {};
|
||||
|
||||
let locale = "en-US";
|
||||
let locale =
|
||||
typeof navigator === "object" && typeof navigator.language === "string"
|
||||
? navigator.language
|
||||
: "zh-CN";
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -10,24 +11,67 @@ const setLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const isEmptyVariables = (variables) =>
|
||||
(Array.isArray(variables) && variables.length === 0) ||
|
||||
(typeof variables === "object" &&
|
||||
(!variables || Object.keys(variables).length === 0));
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) =>
|
||||
typeof msg === "string"
|
||||
? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? "")
|
||||
: msg;
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg =
|
||||
(i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) ||
|
||||
i18nConfig[locale]?.[id] ??
|
||||
i18nConfig[locale.replace("-", "_")]?.[id] ??
|
||||
defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn("[i18n]: unknown message id: %o (locale=%o)", id, locale);
|
||||
return `${id}`;
|
||||
return fallback === undefined ? `${id}` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
return format(msg, variables);
|
||||
};
|
||||
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace("-", "_")];
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, t.params);
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || "zh_CN"] ?? t.en_US, t.params);
|
||||
};
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale,
|
||||
setLocale: target.setLocale,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const i18n = (id) => {
|
||||
return i18nFormat({ id });
|
||||
};
|
||||
|
||||
export { getLocale, setLocale, i18n, i18nFormat };
|
||||
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。
|
||||
// 例外:react 框架的导出名和各种组件名除外。
|
||||
import React from "react";
|
||||
|
||||
import {
|
||||
@ -22,7 +24,7 @@ import { AliAutoSearchTable } from "@alife/mc-assets-1935/build/lowcode/index.js
|
||||
|
||||
import utils, { RefsManager } from "../../utils";
|
||||
|
||||
import { i18n as _$$i18n } from "../../i18n";
|
||||
import * as __$$i18n from "../../i18n";
|
||||
|
||||
import "./index.css";
|
||||
|
||||
@ -31,6 +33,8 @@ const NextBlockCell = NextBlock.Cell;
|
||||
const AliAutoSearchTableDefault = AliAutoSearchTable.default;
|
||||
|
||||
class Test$$Page extends React.Component {
|
||||
_context = this;
|
||||
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
@ -38,6 +42,8 @@ class Test$$Page extends React.Component {
|
||||
|
||||
this._refsManager = new RefsManager();
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
|
||||
this.state = {
|
||||
name: "nongzhou",
|
||||
gateways: [],
|
||||
@ -55,10 +61,6 @@ class Test$$Page extends React.Component {
|
||||
return this._refsManager.getAll(refName);
|
||||
};
|
||||
|
||||
i18n = (i18nKey) => {
|
||||
return _$$i18n(i18nKey);
|
||||
};
|
||||
|
||||
componentWillUnmount() {
|
||||
/* ... */
|
||||
}
|
||||
@ -90,8 +92,8 @@ class Test$$Page extends React.Component {
|
||||
componentDidMount() {}
|
||||
|
||||
render() {
|
||||
const __$$context = this;
|
||||
const { state } = this;
|
||||
const __$$context = this._context || this;
|
||||
const { state } = __$$context;
|
||||
return (
|
||||
<div
|
||||
ref={this._refsManager.linkRef("outterView")}
|
||||
@ -150,7 +152,7 @@ class Test$$Page extends React.Component {
|
||||
width: "400px",
|
||||
display: "inline-block",
|
||||
}}
|
||||
options={this.state.gateways}
|
||||
options={__$$eval(() => this.state.gateways)}
|
||||
mode="single"
|
||||
defaultValue={["auto-edd-uniproxy"]}
|
||||
labelInValue={true}
|
||||
@ -218,7 +220,7 @@ class Test$$Page extends React.Component {
|
||||
</Button>
|
||||
<Modal
|
||||
title="创建发布单"
|
||||
visible={this.state.modalVisible}
|
||||
visible={__$$eval(() => this.state.modalVisible)}
|
||||
footer=""
|
||||
__events={{
|
||||
eventDataList: [
|
||||
@ -315,7 +317,7 @@ class Test$$Page extends React.Component {
|
||||
</Modal>
|
||||
<AliAutoSearchTableDefault
|
||||
rowKey="key"
|
||||
dataSource={this.state.records}
|
||||
dataSource={__$$eval(() => this.state.records)}
|
||||
columns={[
|
||||
{
|
||||
title: "发布名称",
|
||||
@ -340,7 +342,7 @@ class Test$$Page extends React.Component {
|
||||
},
|
||||
{ title: "发布时间", dataIndex: "publish_id" },
|
||||
]}
|
||||
actions={this.actions || []}
|
||||
actions={__$$eval(() => this.actions || [])}
|
||||
getActions={function () {
|
||||
return this.getActions.apply(
|
||||
this,
|
||||
@ -360,6 +362,17 @@ class Test$$Page extends React.Component {
|
||||
|
||||
export default Test$$Page;
|
||||
|
||||
function __$$eval(expr) {
|
||||
try {
|
||||
return expr();
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
function __$$evalArray(expr) {
|
||||
const res = __$$eval(expr);
|
||||
return Array.isArray(res) ? res : [];
|
||||
}
|
||||
|
||||
function __$$createChildContext(oldContext, ext) {
|
||||
const childContext = {
|
||||
...oldContext,
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
import IntlMessageFormat from "intl-messageformat";
|
||||
|
||||
const i18nConfig = {};
|
||||
|
||||
let locale = "en-US";
|
||||
let locale =
|
||||
typeof navigator === "object" && typeof navigator.language === "string"
|
||||
? navigator.language
|
||||
: "zh-CN";
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -10,24 +11,67 @@ const setLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const isEmptyVariables = (variables) =>
|
||||
(Array.isArray(variables) && variables.length === 0) ||
|
||||
(typeof variables === "object" &&
|
||||
(!variables || Object.keys(variables).length === 0));
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) =>
|
||||
typeof msg === "string"
|
||||
? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? "")
|
||||
: msg;
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg =
|
||||
(i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) ||
|
||||
i18nConfig[locale]?.[id] ??
|
||||
i18nConfig[locale.replace("-", "_")]?.[id] ??
|
||||
defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn("[i18n]: unknown message id: %o (locale=%o)", id, locale);
|
||||
return `${id}`;
|
||||
return fallback === undefined ? `${id}` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
return format(msg, variables);
|
||||
};
|
||||
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace("-", "_")];
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, t.params);
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || "zh_CN"] ?? t.en_US, t.params);
|
||||
};
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale,
|
||||
setLocale: target.setLocale,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const i18n = (id) => {
|
||||
return i18nFormat({ id });
|
||||
};
|
||||
|
||||
export { getLocale, setLocale, i18n, i18nFormat };
|
||||
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。
|
||||
// 例外:react 框架的导出名和各种组件名除外。
|
||||
import React from "react";
|
||||
|
||||
import { Form, Input, NumberPicker, Select, Button } from "@alifd/next";
|
||||
@ -10,11 +12,13 @@ import { create as __$$createDataSourceEngine } from "@alilc/lowcode-datasource-
|
||||
|
||||
import utils, { RefsManager } from "../../utils";
|
||||
|
||||
import { i18n as _$$i18n } from "../../i18n";
|
||||
import * as __$$i18n from "../../i18n";
|
||||
|
||||
import "./index.css";
|
||||
|
||||
class Test$$Page extends React.Component {
|
||||
_context = this;
|
||||
|
||||
_dataSourceConfig = this._defineDataSourceConfig();
|
||||
_dataSourceEngine = __$$createDataSourceEngine(this._dataSourceConfig, this, {
|
||||
runtimeConfig: true,
|
||||
@ -39,6 +43,8 @@ class Test$$Page extends React.Component {
|
||||
|
||||
this._refsManager = new RefsManager();
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
|
||||
this.state = { text: "outter" };
|
||||
}
|
||||
|
||||
@ -113,10 +119,6 @@ class Test$$Page extends React.Component {
|
||||
};
|
||||
}
|
||||
|
||||
i18n = (i18nKey) => {
|
||||
return _$$i18n(i18nKey);
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this._dataSourceEngine.reloadDataSource();
|
||||
|
||||
@ -124,12 +126,12 @@ class Test$$Page extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const __$$context = this;
|
||||
const { state } = this;
|
||||
const __$$context = this._context || this;
|
||||
const { state } = __$$context;
|
||||
return (
|
||||
<div ref={this._refsManager.linkRef("outterView")} autoLoading={true}>
|
||||
<Form
|
||||
labelCol={this.state.colNum}
|
||||
labelCol={__$$eval(() => this.state.colNum)}
|
||||
style={{}}
|
||||
ref={this._refsManager.linkRef("testForm")}
|
||||
>
|
||||
@ -150,11 +152,11 @@ class Test$$Page extends React.Component {
|
||||
</Form.Item>
|
||||
<div style={{ textAlign: "center" }}>
|
||||
<Button.Group>
|
||||
{["a", "b", "c"].map((item, index) =>
|
||||
{__$$evalArray(() => ["a", "b", "c"]).map((item, index) =>
|
||||
((__$$context) =>
|
||||
!!false && (
|
||||
<Button type="primary" style={{ margin: "0 5px 0 5px" }}>
|
||||
{item}
|
||||
{__$$eval(() => item)}
|
||||
</Button>
|
||||
))(__$$createChildContext(__$$context, { item, index }))
|
||||
)}
|
||||
@ -168,6 +170,17 @@ class Test$$Page extends React.Component {
|
||||
|
||||
export default Test$$Page;
|
||||
|
||||
function __$$eval(expr) {
|
||||
try {
|
||||
return expr();
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
function __$$evalArray(expr) {
|
||||
const res = __$$eval(expr);
|
||||
return Array.isArray(res) ? res : [];
|
||||
}
|
||||
|
||||
function __$$createChildContext(oldContext, ext) {
|
||||
const childContext = {
|
||||
...oldContext,
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
import IntlMessageFormat from "intl-messageformat";
|
||||
|
||||
const i18nConfig = {};
|
||||
|
||||
let locale = "en-US";
|
||||
let locale =
|
||||
typeof navigator === "object" && typeof navigator.language === "string"
|
||||
? navigator.language
|
||||
: "zh-CN";
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -10,24 +11,67 @@ const setLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const isEmptyVariables = (variables) =>
|
||||
(Array.isArray(variables) && variables.length === 0) ||
|
||||
(typeof variables === "object" &&
|
||||
(!variables || Object.keys(variables).length === 0));
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) =>
|
||||
typeof msg === "string"
|
||||
? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? "")
|
||||
: msg;
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg =
|
||||
(i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) ||
|
||||
i18nConfig[locale]?.[id] ??
|
||||
i18nConfig[locale.replace("-", "_")]?.[id] ??
|
||||
defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn("[i18n]: unknown message id: %o (locale=%o)", id, locale);
|
||||
return `${id}`;
|
||||
return fallback === undefined ? `${id}` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
return format(msg, variables);
|
||||
};
|
||||
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace("-", "_")];
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, t.params);
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || "zh_CN"] ?? t.en_US, t.params);
|
||||
};
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale,
|
||||
setLocale: target.setLocale,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const i18n = (id) => {
|
||||
return i18nFormat({ id });
|
||||
};
|
||||
|
||||
export { getLocale, setLocale, i18n, i18nFormat };
|
||||
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。
|
||||
// 例外:react 框架的导出名和各种组件名除外。
|
||||
import React from "react";
|
||||
|
||||
import {
|
||||
@ -21,13 +23,15 @@ import {
|
||||
|
||||
import utils, { RefsManager } from "../../utils";
|
||||
|
||||
import { i18n as _$$i18n } from "../../i18n";
|
||||
import * as __$$i18n from "../../i18n";
|
||||
|
||||
import "./index.css";
|
||||
|
||||
const NextBlockCell = NextBlock.Cell;
|
||||
|
||||
class Test$$Page extends React.Component {
|
||||
_context = this;
|
||||
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
@ -35,6 +39,8 @@ class Test$$Page extends React.Component {
|
||||
|
||||
this._refsManager = new RefsManager();
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
|
||||
this.state = {
|
||||
books: [],
|
||||
currentStep: 0,
|
||||
@ -97,10 +103,6 @@ class Test$$Page extends React.Component {
|
||||
return this._refsManager.getAll(refName);
|
||||
};
|
||||
|
||||
i18n = (i18nKey) => {
|
||||
return _$$i18n(i18nKey);
|
||||
};
|
||||
|
||||
componentDidUpdate(prevProps, prevState, snapshot) {}
|
||||
|
||||
componentWillUnmount() {}
|
||||
@ -189,8 +191,8 @@ class Test$$Page extends React.Component {
|
||||
componentDidMount() {}
|
||||
|
||||
render() {
|
||||
const __$$context = this;
|
||||
const { state } = this;
|
||||
const __$$context = this._context || this;
|
||||
const { state } = __$$context;
|
||||
return (
|
||||
<div
|
||||
ref={this._refsManager.linkRef("outterView")}
|
||||
@ -198,7 +200,7 @@ class Test$$Page extends React.Component {
|
||||
>
|
||||
<Modal
|
||||
title="是否修改"
|
||||
visible={this.state.isModifyDialogVisible}
|
||||
visible={__$$eval(() => this.state.isModifyDialogVisible)}
|
||||
okText="确认"
|
||||
okType=""
|
||||
forceRender={false}
|
||||
@ -291,13 +293,13 @@ class Test$$Page extends React.Component {
|
||||
flex={true}
|
||||
style={{ marginBottom: "24px" }}
|
||||
>
|
||||
<Steps current={this.state.currentStep}>
|
||||
<Steps current={__$$eval(() => this.state.currentStep)}>
|
||||
<Steps.Step title="版本申请" description="" />
|
||||
<Steps.Step title="机器配置" subTitle="" description="" />
|
||||
<Steps.Step title="项目审批" description="" />
|
||||
</Steps>
|
||||
</NextP>
|
||||
{!!(this.state.currentStep === 0) && (
|
||||
{!!__$$eval(() => this.state.currentStep === 0) && (
|
||||
<NextP
|
||||
wrap={false}
|
||||
type="body2"
|
||||
@ -345,7 +347,9 @@ class Test$$Page extends React.Component {
|
||||
{ name: "onValuesChange", disabled: true },
|
||||
],
|
||||
}}
|
||||
initialValues={this.state.customerProjectInfo}
|
||||
initialValues={__$$eval(
|
||||
() => this.state.customerProjectInfo
|
||||
)}
|
||||
onValuesChange={function () {
|
||||
this.onValuesChange.apply(
|
||||
this,
|
||||
@ -389,10 +393,11 @@ class Test$$Page extends React.Component {
|
||||
{ label: "UI定制", value: "4", disabled: false },
|
||||
]}
|
||||
style={{ width: "600px" }}
|
||||
disabled={
|
||||
disabled={__$$eval(
|
||||
() =>
|
||||
this.state.customerProjectInfo.id > 0 &&
|
||||
!this.state.isModifyStatus
|
||||
}
|
||||
)}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
@ -407,11 +412,12 @@ class Test$$Page extends React.Component {
|
||||
>
|
||||
<Select
|
||||
style={{ width: "600px" }}
|
||||
options={this.state.versionLinesArray}
|
||||
disabled={
|
||||
options={__$$eval(() => this.state.versionLinesArray)}
|
||||
disabled={__$$eval(
|
||||
() =>
|
||||
this.state.customerProjectInfo.id > 0 &&
|
||||
!this.state.isModifyStatus
|
||||
}
|
||||
)}
|
||||
placeholder="请选择版本线"
|
||||
/>
|
||||
</Form.Item>
|
||||
@ -440,10 +446,11 @@ class Test$$Page extends React.Component {
|
||||
<Input
|
||||
placeholder="公司简称-产品名称-版本类型"
|
||||
style={{ width: "600px" }}
|
||||
disabled={
|
||||
disabled={__$$eval(
|
||||
() =>
|
||||
this.state.customerProjectInfo.id > 0 &&
|
||||
!this.state.isModifyStatus
|
||||
}
|
||||
)}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
@ -460,10 +467,11 @@ class Test$$Page extends React.Component {
|
||||
>
|
||||
<DatePicker
|
||||
style={{ width: "600px" }}
|
||||
disabled={
|
||||
disabled={__$$eval(
|
||||
() =>
|
||||
this.state.customerProjectInfo.id > 0 &&
|
||||
!this.state.isModifyStatus
|
||||
}
|
||||
)}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
@ -482,10 +490,11 @@ class Test$$Page extends React.Component {
|
||||
value={3}
|
||||
style={{ width: "600px" }}
|
||||
placeholder="单位(台)使用该版本的机器数量+预计出货量,请如实填写"
|
||||
disabled={
|
||||
disabled={__$$eval(
|
||||
() =>
|
||||
this.state.customerProjectInfo.id > 0 &&
|
||||
!this.state.isModifyStatus
|
||||
}
|
||||
)}
|
||||
min={0}
|
||||
size="middle"
|
||||
/>
|
||||
@ -541,7 +550,7 @@ class Test$$Page extends React.Component {
|
||||
</Form>
|
||||
</NextP>
|
||||
)}
|
||||
{!!(this.state.currentStep === 1) && (
|
||||
{!!__$$eval(() => this.state.currentStep === 1) && (
|
||||
<NextP
|
||||
wrap={false}
|
||||
type="body2"
|
||||
@ -590,7 +599,9 @@ class Test$$Page extends React.Component {
|
||||
{ name: "onValuesChange", disabled: true },
|
||||
],
|
||||
}}
|
||||
initialValues={this.state.customerProjectInfo}
|
||||
initialValues={__$$eval(
|
||||
() => this.state.customerProjectInfo
|
||||
)}
|
||||
onValuesChange={function () {
|
||||
this.onValuesChange.apply(
|
||||
this,
|
||||
@ -612,11 +623,12 @@ class Test$$Page extends React.Component {
|
||||
>
|
||||
<Select
|
||||
style={{ width: "600px" }}
|
||||
options={this.state.projectModalsArray}
|
||||
disabled={
|
||||
options={__$$eval(() => this.state.projectModalsArray)}
|
||||
disabled={__$$eval(
|
||||
() =>
|
||||
this.state.customerProjectInfo.id > 0 &&
|
||||
!this.state.isModifyStatus
|
||||
}
|
||||
)}
|
||||
placeholder="请选择设备类型"
|
||||
/>
|
||||
</Form.Item>
|
||||
@ -636,10 +648,11 @@ class Test$$Page extends React.Component {
|
||||
value={3}
|
||||
style={{ width: "600px" }}
|
||||
placeholder="例如1280"
|
||||
disabled={
|
||||
disabled={__$$eval(
|
||||
() =>
|
||||
this.state.customerProjectInfo.id > 0 &&
|
||||
!this.state.isModifyStatus
|
||||
}
|
||||
)}
|
||||
min={0}
|
||||
/>
|
||||
</Form.Item>
|
||||
@ -659,10 +672,11 @@ class Test$$Page extends React.Component {
|
||||
value={3}
|
||||
style={{ width: "600px" }}
|
||||
placeholder="例如720"
|
||||
disabled={
|
||||
disabled={__$$eval(
|
||||
() =>
|
||||
this.state.customerProjectInfo.id > 0 &&
|
||||
!this.state.isModifyStatus
|
||||
}
|
||||
)}
|
||||
min={0}
|
||||
/>
|
||||
</Form.Item>
|
||||
@ -682,10 +696,11 @@ class Test$$Page extends React.Component {
|
||||
value={3}
|
||||
style={{ width: "600px" }}
|
||||
placeholder="请输入尺寸"
|
||||
disabled={
|
||||
disabled={__$$eval(
|
||||
() =>
|
||||
this.state.customerProjectInfo.id > 0 &&
|
||||
!this.state.isModifyStatus
|
||||
}
|
||||
)}
|
||||
min={0}
|
||||
/>
|
||||
</Form.Item>
|
||||
@ -701,10 +716,11 @@ class Test$$Page extends React.Component {
|
||||
value={3}
|
||||
style={{ width: "600px" }}
|
||||
placeholder="UI定制项目必填"
|
||||
disabled={
|
||||
disabled={__$$eval(
|
||||
() =>
|
||||
this.state.customerProjectInfo.id > 0 &&
|
||||
!this.state.isModifyStatus
|
||||
}
|
||||
)}
|
||||
min={0}
|
||||
/>
|
||||
</Form.Item>
|
||||
@ -725,10 +741,11 @@ class Test$$Page extends React.Component {
|
||||
<Input
|
||||
placeholder="请输入芯片名称"
|
||||
style={{ width: "600px" }}
|
||||
disabled={
|
||||
disabled={__$$eval(
|
||||
() =>
|
||||
this.state.customerProjectInfo.id > 0 &&
|
||||
!this.state.isModifyStatus
|
||||
}
|
||||
)}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
@ -747,10 +764,11 @@ class Test$$Page extends React.Component {
|
||||
value={3}
|
||||
style={{ width: "600px" }}
|
||||
placeholder="请输入芯片核数"
|
||||
disabled={
|
||||
disabled={__$$eval(
|
||||
() =>
|
||||
this.state.customerProjectInfo.id > 0 &&
|
||||
!this.state.isModifyStatus
|
||||
}
|
||||
)}
|
||||
defaultValue=""
|
||||
min={0}
|
||||
/>
|
||||
@ -765,11 +783,12 @@ class Test$$Page extends React.Component {
|
||||
>
|
||||
<Select
|
||||
style={{ width: "600px" }}
|
||||
options={this.state.instructionsArray}
|
||||
disabled={
|
||||
options={__$$eval(() => this.state.instructionsArray)}
|
||||
disabled={__$$eval(
|
||||
() =>
|
||||
this.state.customerProjectInfo.id > 0 &&
|
||||
!this.state.isModifyStatus
|
||||
}
|
||||
)}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
@ -786,11 +805,12 @@ class Test$$Page extends React.Component {
|
||||
>
|
||||
<Select
|
||||
style={{ width: "600px" }}
|
||||
options={this.state.osVersionsArray}
|
||||
disabled={
|
||||
options={__$$eval(() => this.state.osVersionsArray)}
|
||||
disabled={__$$eval(
|
||||
() =>
|
||||
this.state.customerProjectInfo.id > 0 &&
|
||||
!this.state.isModifyStatus
|
||||
}
|
||||
)}
|
||||
placeholder="请选择系统版本"
|
||||
/>
|
||||
</Form.Item>
|
||||
@ -827,11 +847,12 @@ class Test$$Page extends React.Component {
|
||||
type="primary"
|
||||
htmlType="submit"
|
||||
style={{ float: "right", marginLeft: "20px" }}
|
||||
loading={
|
||||
loading={__$$eval(
|
||||
() =>
|
||||
this.state.LOADING_ADD_OR_UPDATE_CUSTOMER_PROJECT
|
||||
}
|
||||
)}
|
||||
>
|
||||
{this.state.secondCommitText}
|
||||
{__$$eval(() => this.state.secondCommitText)}
|
||||
</Button>
|
||||
<Button
|
||||
type="primary"
|
||||
@ -860,7 +881,7 @@ class Test$$Page extends React.Component {
|
||||
</Form>
|
||||
</NextP>
|
||||
)}
|
||||
{!!(this.state.currentStep === 2) && (
|
||||
{!!__$$eval(() => this.state.currentStep === 2) && (
|
||||
<NextP
|
||||
wrap={false}
|
||||
type="body2"
|
||||
@ -923,7 +944,7 @@ class Test$$Page extends React.Component {
|
||||
style={{ width: "200px" }}
|
||||
/>
|
||||
<Steps.Step
|
||||
title={this.state.thirdAuditText}
|
||||
title={__$$eval(() => this.state.thirdAuditText)}
|
||||
subTitle=""
|
||||
description=""
|
||||
style={{ width: "200px" }}
|
||||
@ -980,9 +1001,11 @@ class Test$$Page extends React.Component {
|
||||
);
|
||||
}.bind(this)}
|
||||
>
|
||||
{this.state.thirdButtonText}
|
||||
{__$$eval(() => this.state.thirdButtonText)}
|
||||
</Button>
|
||||
{!!(this.state.customerProjectInfo.status > 2) && (
|
||||
{!!__$$eval(
|
||||
() => this.state.customerProjectInfo.status > 2
|
||||
) && (
|
||||
<Button
|
||||
type="primary"
|
||||
htmlType="submit"
|
||||
@ -1021,6 +1044,17 @@ class Test$$Page extends React.Component {
|
||||
|
||||
export default Test$$Page;
|
||||
|
||||
function __$$eval(expr) {
|
||||
try {
|
||||
return expr();
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
function __$$evalArray(expr) {
|
||||
const res = __$$eval(expr);
|
||||
return Array.isArray(res) ? res : [];
|
||||
}
|
||||
|
||||
function __$$createChildContext(oldContext, ext) {
|
||||
const childContext = {
|
||||
...oldContext,
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
import IntlMessageFormat from "intl-messageformat";
|
||||
|
||||
const i18nConfig = {};
|
||||
|
||||
let locale = "en-US";
|
||||
let locale =
|
||||
typeof navigator === "object" && typeof navigator.language === "string"
|
||||
? navigator.language
|
||||
: "zh-CN";
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -10,24 +11,67 @@ const setLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const isEmptyVariables = (variables) =>
|
||||
(Array.isArray(variables) && variables.length === 0) ||
|
||||
(typeof variables === "object" &&
|
||||
(!variables || Object.keys(variables).length === 0));
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) =>
|
||||
typeof msg === "string"
|
||||
? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? "")
|
||||
: msg;
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg =
|
||||
(i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) ||
|
||||
i18nConfig[locale]?.[id] ??
|
||||
i18nConfig[locale.replace("-", "_")]?.[id] ??
|
||||
defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn("[i18n]: unknown message id: %o (locale=%o)", id, locale);
|
||||
return `${id}`;
|
||||
return fallback === undefined ? `${id}` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
return format(msg, variables);
|
||||
};
|
||||
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace("-", "_")];
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, t.params);
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || "zh_CN"] ?? t.en_US, t.params);
|
||||
};
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale,
|
||||
setLocale: target.setLocale,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const i18n = (id) => {
|
||||
return i18nFormat({ id });
|
||||
};
|
||||
|
||||
export { getLocale, setLocale, i18n, i18nFormat };
|
||||
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。
|
||||
// 例外:react 框架的导出名和各种组件名除外。
|
||||
import React from "react";
|
||||
|
||||
import { Page, Table } from "@alilc/lowcode-components";
|
||||
@ -8,11 +10,13 @@ import { create as __$$createDataSourceEngine } from "@alilc/lowcode-datasource-
|
||||
|
||||
import utils from "../../utils";
|
||||
|
||||
import { i18n as _$$i18n } from "../../i18n";
|
||||
import * as __$$i18n from "../../i18n";
|
||||
|
||||
import "./index.css";
|
||||
|
||||
class Example$$Page extends React.Component {
|
||||
_context = this;
|
||||
|
||||
_dataSourceConfig = this._defineDataSourceConfig();
|
||||
_dataSourceEngine = __$$createDataSourceEngine(this._dataSourceConfig, this, {
|
||||
runtimeConfig: true,
|
||||
@ -32,9 +36,15 @@ class Example$$Page extends React.Component {
|
||||
|
||||
this.utils = utils;
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
|
||||
this.state = {};
|
||||
}
|
||||
|
||||
$ = () => null;
|
||||
|
||||
$$ = () => [];
|
||||
|
||||
_defineDataSourceConfig() {
|
||||
const _this = this;
|
||||
return {
|
||||
@ -56,21 +66,17 @@ class Example$$Page extends React.Component {
|
||||
};
|
||||
}
|
||||
|
||||
i18n = (i18nKey) => {
|
||||
return _$$i18n(i18nKey);
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this._dataSourceEngine.reloadDataSource();
|
||||
}
|
||||
|
||||
render() {
|
||||
const __$$context = this;
|
||||
const { state } = this;
|
||||
const __$$context = this._context || this;
|
||||
const { state } = __$$context;
|
||||
return (
|
||||
<div>
|
||||
<Table
|
||||
dataSource={this.dataSourceMap["userList"]}
|
||||
dataSource={__$$eval(() => this.dataSourceMap["userList"])}
|
||||
columns={[
|
||||
{ dataIndex: "name", title: "姓名" },
|
||||
{ dataIndex: "age", title: "年龄" },
|
||||
@ -83,6 +89,17 @@ class Example$$Page extends React.Component {
|
||||
|
||||
export default Example$$Page;
|
||||
|
||||
function __$$eval(expr) {
|
||||
try {
|
||||
return expr();
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
function __$$evalArray(expr) {
|
||||
const res = __$$eval(expr);
|
||||
return Array.isArray(res) ? res : [];
|
||||
}
|
||||
|
||||
function __$$createChildContext(oldContext, ext) {
|
||||
const childContext = {
|
||||
...oldContext,
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。
|
||||
// 例外:react 框架的导出名和各种组件名除外。
|
||||
import React from "react";
|
||||
|
||||
import { Switch } from "@alifd/next";
|
||||
@ -8,11 +10,13 @@ import { create as __$$createDataSourceEngine } from "@alilc/lowcode-datasource-
|
||||
|
||||
import utils from "../../utils";
|
||||
|
||||
import { i18n as _$$i18n } from "../../i18n";
|
||||
import * as __$$i18n from "../../i18n";
|
||||
|
||||
import "./index.css";
|
||||
|
||||
class Index$$Page extends React.Component {
|
||||
_context = this;
|
||||
|
||||
_dataSourceConfig = this._defineDataSourceConfig();
|
||||
_dataSourceEngine = __$$createDataSourceEngine(this._dataSourceConfig, this, {
|
||||
runtimeConfig: true,
|
||||
@ -32,9 +36,15 @@ class Index$$Page extends React.Component {
|
||||
|
||||
this.utils = utils;
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
|
||||
this.state = {};
|
||||
}
|
||||
|
||||
$ = () => null;
|
||||
|
||||
$$ = () => [];
|
||||
|
||||
_defineDataSourceConfig() {
|
||||
const _this = this;
|
||||
return {
|
||||
@ -59,27 +69,24 @@ class Index$$Page extends React.Component {
|
||||
};
|
||||
}
|
||||
|
||||
i18n = (i18nKey) => {
|
||||
return _$$i18n(i18nKey);
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
this._dataSourceEngine.reloadDataSource();
|
||||
}
|
||||
|
||||
render() {
|
||||
const __$$context = this;
|
||||
const { state } = this;
|
||||
const __$$context = this._context || this;
|
||||
const { state } = __$$context;
|
||||
return (
|
||||
<div>
|
||||
<div>
|
||||
{this.dataSourceMap.todos.data.map((item, index) =>
|
||||
{__$$evalArray(() => this.dataSourceMap.todos.data).map(
|
||||
(item, index) =>
|
||||
((__$$context) => (
|
||||
<div>
|
||||
<Switch
|
||||
checkedChildren="开"
|
||||
unCheckedChildren="关"
|
||||
checked={item.done}
|
||||
checked={__$$eval(() => item.done)}
|
||||
/>
|
||||
</div>
|
||||
))(__$$createChildContext(__$$context, { item, index }))
|
||||
@ -92,6 +99,17 @@ class Index$$Page extends React.Component {
|
||||
|
||||
export default Index$$Page;
|
||||
|
||||
function __$$eval(expr) {
|
||||
try {
|
||||
return expr();
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
function __$$evalArray(expr) {
|
||||
const res = __$$eval(expr);
|
||||
return Array.isArray(res) ? res : [];
|
||||
}
|
||||
|
||||
function __$$createChildContext(oldContext, ext) {
|
||||
const childContext = {
|
||||
...oldContext,
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
import IntlMessageFormat from "intl-messageformat";
|
||||
|
||||
const i18nConfig = {};
|
||||
|
||||
let locale = "en-US";
|
||||
let locale =
|
||||
typeof navigator === "object" && typeof navigator.language === "string"
|
||||
? navigator.language
|
||||
: "zh-CN";
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -10,24 +11,67 @@ const setLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const isEmptyVariables = (variables) =>
|
||||
(Array.isArray(variables) && variables.length === 0) ||
|
||||
(typeof variables === "object" &&
|
||||
(!variables || Object.keys(variables).length === 0));
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) =>
|
||||
typeof msg === "string"
|
||||
? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? "")
|
||||
: msg;
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg =
|
||||
(i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) ||
|
||||
i18nConfig[locale]?.[id] ??
|
||||
i18nConfig[locale.replace("-", "_")]?.[id] ??
|
||||
defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn("[i18n]: unknown message id: %o (locale=%o)", id, locale);
|
||||
return `${id}`;
|
||||
return fallback === undefined ? `${id}` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
return format(msg, variables);
|
||||
};
|
||||
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace("-", "_")];
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, t.params);
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || "zh_CN"] ?? t.en_US, t.params);
|
||||
};
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale,
|
||||
setLocale: target.setLocale,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const i18n = (id) => {
|
||||
return i18nFormat({ id });
|
||||
};
|
||||
|
||||
export { getLocale, setLocale, i18n, i18nFormat };
|
||||
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
import IntlMessageFormat from "intl-messageformat";
|
||||
|
||||
const i18nConfig = {};
|
||||
|
||||
let locale = "en-US";
|
||||
let locale =
|
||||
typeof navigator === "object" && typeof navigator.language === "string"
|
||||
? navigator.language
|
||||
: "zh-CN";
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -10,24 +11,67 @@ const setLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const isEmptyVariables = (variables) =>
|
||||
(Array.isArray(variables) && variables.length === 0) ||
|
||||
(typeof variables === "object" &&
|
||||
(!variables || Object.keys(variables).length === 0));
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) =>
|
||||
typeof msg === "string"
|
||||
? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? "")
|
||||
: msg;
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg =
|
||||
(i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) ||
|
||||
i18nConfig[locale]?.[id] ??
|
||||
i18nConfig[locale.replace("-", "_")]?.[id] ??
|
||||
defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn("[i18n]: unknown message id: %o (locale=%o)", id, locale);
|
||||
return `${id}`;
|
||||
return fallback === undefined ? `${id}` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
return format(msg, variables);
|
||||
};
|
||||
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace("-", "_")];
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, t.params);
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || "zh_CN"] ?? t.en_US, t.params);
|
||||
};
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale,
|
||||
setLocale: target.setLocale,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const i18n = (id) => {
|
||||
return i18nFormat({ id });
|
||||
};
|
||||
|
||||
export { getLocale, setLocale, i18n, i18nFormat };
|
||||
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。
|
||||
// 例外:react 框架的导出名和各种组件名除外。
|
||||
import React from "react";
|
||||
|
||||
import {
|
||||
@ -25,7 +27,7 @@ import {
|
||||
|
||||
import utils, { RefsManager } from "../../utils";
|
||||
|
||||
import { i18n as _$$i18n } from "../../i18n";
|
||||
import * as __$$i18n from "../../i18n";
|
||||
|
||||
import "./index.css";
|
||||
|
||||
@ -36,6 +38,8 @@ const AliAutoSearchTableDefault = AliAutoSearchTable.default;
|
||||
const NextBlockCell = NextBlock.Cell;
|
||||
|
||||
class Test$$Page extends React.Component {
|
||||
_context = this;
|
||||
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
@ -43,6 +47,8 @@ class Test$$Page extends React.Component {
|
||||
|
||||
this._refsManager = new RefsManager();
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
|
||||
this.state = {
|
||||
pkgs: [],
|
||||
total: 0,
|
||||
@ -71,10 +77,6 @@ class Test$$Page extends React.Component {
|
||||
return this._refsManager.getAll(refName);
|
||||
};
|
||||
|
||||
i18n = (i18nKey) => {
|
||||
return _$$i18n(i18nKey);
|
||||
};
|
||||
|
||||
componentDidUpdate(prevProps, prevState, snapshot) {}
|
||||
|
||||
componentWillUnmount() {}
|
||||
@ -181,8 +183,8 @@ class Test$$Page extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const __$$context = this;
|
||||
const { state } = this;
|
||||
const __$$context = this._context || this;
|
||||
const { state } = __$$context;
|
||||
return (
|
||||
<div
|
||||
ref={this._refsManager.linkRef("outterView")}
|
||||
@ -190,7 +192,7 @@ class Test$$Page extends React.Component {
|
||||
>
|
||||
<Modal
|
||||
title="查看结果"
|
||||
visible={this.state.resultVisible}
|
||||
visible={__$$eval(() => this.state.resultVisible)}
|
||||
footer={
|
||||
<Button
|
||||
type="primary"
|
||||
@ -236,10 +238,11 @@ class Test$$Page extends React.Component {
|
||||
width="720px"
|
||||
centered={true}
|
||||
>
|
||||
{this.state.results.map((item, index) =>
|
||||
{__$$evalArray(() => this.state.results).map((item, index) =>
|
||||
((__$$context) => (
|
||||
<AliAutoDivDefault style={{ width: "100%" }}>
|
||||
{!!(
|
||||
{!!__$$eval(
|
||||
() =>
|
||||
__$$context.state.results &&
|
||||
__$$context.state.results.length > 0
|
||||
) && (
|
||||
@ -275,16 +278,22 @@ class Test$$Page extends React.Component {
|
||||
</AliAutoDivDefault>
|
||||
)}
|
||||
<Typography.Text>
|
||||
{__$$context.formatResult(item)}
|
||||
{__$$eval(() => __$$context.formatResult(item))}
|
||||
</Typography.Text>
|
||||
{!!item.download_link && (
|
||||
<Typography.Link href={item.download_link} target="_blank">
|
||||
{!!__$$eval(() => item.download_link) && (
|
||||
<Typography.Link
|
||||
href={__$$eval(() => item.download_link)}
|
||||
target="_blank"
|
||||
>
|
||||
{" "}
|
||||
- 点击下载
|
||||
</Typography.Link>
|
||||
)}
|
||||
{!!item.release_notes && (
|
||||
<Typography.Link href={item.release_notes} target="_blank">
|
||||
{!!__$$eval(() => item.release_notes) && (
|
||||
<Typography.Link
|
||||
href={__$$eval(() => item.release_notes)}
|
||||
target="_blank"
|
||||
>
|
||||
{" "}
|
||||
- 跳转发布节点
|
||||
</Typography.Link>
|
||||
@ -363,7 +372,7 @@ class Test$$Page extends React.Component {
|
||||
<Form.Item label="项目名称/渠道号" name="channel_id">
|
||||
<Select
|
||||
style={{ width: "280px" }}
|
||||
options={this.state.projects}
|
||||
options={__$$eval(() => this.state.projects)}
|
||||
showArrow={true}
|
||||
tokenSeparators={[]}
|
||||
showSearch={true}
|
||||
@ -410,13 +419,14 @@ class Test$$Page extends React.Component {
|
||||
flex={true}
|
||||
>
|
||||
<ConfigProvider locale="zh-CN">
|
||||
{!!(
|
||||
{!!__$$eval(
|
||||
() =>
|
||||
!this.state.isSearch ||
|
||||
(this.state.isSearch && this.state.pkgs.length > 0)
|
||||
) && (
|
||||
<AliAutoSearchTableDefault
|
||||
rowKey="key"
|
||||
dataSource={this.state.pkgs}
|
||||
dataSource={__$$eval(() => this.state.pkgs)}
|
||||
columns={[
|
||||
{
|
||||
title: "ID",
|
||||
@ -431,14 +441,13 @@ class Test$$Page extends React.Component {
|
||||
width: 142,
|
||||
render: (text, record, index) =>
|
||||
((__$$context) =>
|
||||
text
|
||||
.split(",")
|
||||
.map((item, index) =>
|
||||
__$$evalArray(() => text.split(",")).map(
|
||||
(item, index) =>
|
||||
((__$$context) => (
|
||||
<Typography.Text
|
||||
style={{ display: "block" }}
|
||||
>
|
||||
{item}
|
||||
{__$$eval(() => item)}
|
||||
</Typography.Text>
|
||||
))(
|
||||
__$$createChildContext(__$$context, {
|
||||
@ -461,7 +470,8 @@ class Test$$Page extends React.Component {
|
||||
render: (text, record, index) =>
|
||||
((__$$context) => (
|
||||
<Tooltip
|
||||
title={(text || []).map((item, index) =>
|
||||
title={__$$evalArray(() => text || []).map(
|
||||
(item, index) =>
|
||||
((__$$context) => (
|
||||
<Typography.Text
|
||||
style={{
|
||||
@ -469,7 +479,12 @@ class Test$$Page extends React.Component {
|
||||
color: "#FFFFFF",
|
||||
}}
|
||||
>
|
||||
{item.channelId + " / " + item.version}
|
||||
{__$$eval(
|
||||
() =>
|
||||
item.channelId +
|
||||
" / " +
|
||||
item.version
|
||||
)}
|
||||
</Typography.Text>
|
||||
))(
|
||||
__$$createChildContext(__$$context, {
|
||||
@ -480,7 +495,7 @@ class Test$$Page extends React.Component {
|
||||
)}
|
||||
>
|
||||
<Typography.Text>
|
||||
{text[0].version}
|
||||
{__$$eval(() => text[0].version)}
|
||||
</Typography.Text>
|
||||
</Tooltip>
|
||||
))(
|
||||
@ -504,9 +519,9 @@ class Test$$Page extends React.Component {
|
||||
render: (text, record, index) =>
|
||||
((__$$context) => [
|
||||
<Typography.Text>
|
||||
{__$$context.statusDesc[text]}
|
||||
{__$$eval(() => __$$context.statusDesc[text])}
|
||||
</Typography.Text>,
|
||||
!!(text === 2) && (
|
||||
!!__$$eval(() => text === 2) && (
|
||||
<Icon
|
||||
type="SyncOutlined"
|
||||
size={16}
|
||||
@ -550,12 +565,15 @@ class Test$$Page extends React.Component {
|
||||
dataIndex: "jenkins_link",
|
||||
render: (text, record, index) =>
|
||||
((__$$context) => [
|
||||
!!text && (
|
||||
<Typography.Link href={text} target="_blank">
|
||||
!!__$$eval(() => text) && (
|
||||
<Typography.Link
|
||||
href={__$$eval(() => text)}
|
||||
target="_blank"
|
||||
>
|
||||
查看
|
||||
</Typography.Link>
|
||||
),
|
||||
!!!text && (
|
||||
!!__$$eval(() => !text) && (
|
||||
<Typography.Text>暂无</Typography.Text>
|
||||
),
|
||||
])(
|
||||
@ -573,7 +591,7 @@ class Test$$Page extends React.Component {
|
||||
width: 120,
|
||||
render: (text, record, index) =>
|
||||
((__$$context) => [
|
||||
!!text && (
|
||||
!!__$$eval(() => text) && (
|
||||
<Typography.Link
|
||||
href="http://rivermap.alibaba.net/dashboard/testExecute"
|
||||
target="_blank"
|
||||
@ -581,7 +599,7 @@ class Test$$Page extends React.Component {
|
||||
查看
|
||||
</Typography.Link>
|
||||
),
|
||||
!!!text && (
|
||||
!!__$$eval(() => !text) && (
|
||||
<Typography.Text>暂无</Typography.Text>
|
||||
),
|
||||
])(
|
||||
@ -666,7 +684,7 @@ class Test$$Page extends React.Component {
|
||||
);
|
||||
}.bind(__$$context)}
|
||||
ghost={false}
|
||||
href={text}
|
||||
href={__$$eval(() => text)}
|
||||
>
|
||||
查看
|
||||
</Button>
|
||||
@ -738,7 +756,7 @@ class Test$$Page extends React.Component {
|
||||
]}
|
||||
actions={[]}
|
||||
pagination={{
|
||||
total: this.state.total,
|
||||
total: __$$eval(() => this.state.total),
|
||||
defaultPageSize: 8,
|
||||
onPageChange: function () {
|
||||
return this.onPageChange.apply(
|
||||
@ -764,9 +782,9 @@ class Test$$Page extends React.Component {
|
||||
align="left"
|
||||
flex={true}
|
||||
>
|
||||
{!!(this.state.pkgs.length < 1 && this.state.isSearch) && (
|
||||
<Empty description="暂无数据" />
|
||||
)}
|
||||
{!!__$$eval(
|
||||
() => this.state.pkgs.length < 1 && this.state.isSearch
|
||||
) && <Empty description="暂无数据" />}
|
||||
</NextP>
|
||||
</NextBlockCell>
|
||||
</NextBlock>
|
||||
@ -778,6 +796,17 @@ class Test$$Page extends React.Component {
|
||||
|
||||
export default Test$$Page;
|
||||
|
||||
function __$$eval(expr) {
|
||||
try {
|
||||
return expr();
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
function __$$evalArray(expr) {
|
||||
const res = __$$eval(expr);
|
||||
return Array.isArray(res) ? res : [];
|
||||
}
|
||||
|
||||
function __$$createChildContext(oldContext, ext) {
|
||||
const childContext = {
|
||||
...oldContext,
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
import IntlMessageFormat from "intl-messageformat";
|
||||
|
||||
const i18nConfig = {};
|
||||
|
||||
let locale = "en-US";
|
||||
let locale =
|
||||
typeof navigator === "object" && typeof navigator.language === "string"
|
||||
? navigator.language
|
||||
: "zh-CN";
|
||||
|
||||
const getLocale = () => locale;
|
||||
|
||||
@ -10,24 +11,67 @@ const setLocale = (target) => {
|
||||
locale = target;
|
||||
};
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage }, variables) => {
|
||||
const isEmptyVariables = (variables) =>
|
||||
(Array.isArray(variables) && variables.length === 0) ||
|
||||
(typeof variables === "object" &&
|
||||
(!variables || Object.keys(variables).length === 0));
|
||||
|
||||
// 按低代码规范里面的要求进行变量替换
|
||||
const format = (msg, variables) =>
|
||||
typeof msg === "string"
|
||||
? msg.replace(/\$\{(\w+)\}/g, (match, key) => variables?.[key] ?? "")
|
||||
: msg;
|
||||
|
||||
const i18nFormat = ({ id, defaultMessage, fallback }, variables) => {
|
||||
const msg =
|
||||
(i18nConfig && i18nConfig[locale] && i18nConfig[locale][id]) ||
|
||||
i18nConfig[locale]?.[id] ??
|
||||
i18nConfig[locale.replace("-", "_")]?.[id] ??
|
||||
defaultMessage;
|
||||
if (msg == null) {
|
||||
console.warn("[i18n]: unknown message id: %o (locale=%o)", id, locale);
|
||||
return `${id}`;
|
||||
return fallback === undefined ? `${id}` : fallback;
|
||||
}
|
||||
|
||||
if (!variables || !variables.length) {
|
||||
return msg;
|
||||
return format(msg, variables);
|
||||
};
|
||||
|
||||
const i18n = (id, params) => {
|
||||
return i18nFormat({ id }, params);
|
||||
};
|
||||
|
||||
// 将国际化的一些方法注入到目标对象&上下文中
|
||||
const _inject2 = (target) => {
|
||||
target.i18n = i18n;
|
||||
target.getLocale = getLocale;
|
||||
target.setLocale = (locale) => {
|
||||
setLocale(locale);
|
||||
target.forceUpdate();
|
||||
};
|
||||
target._i18nText = (t) => {
|
||||
// 优先取直接传过来的语料
|
||||
const localMsg = t[locale] ?? t[String(locale).replace("-", "_")];
|
||||
if (localMsg != null) {
|
||||
return format(localMsg, t.params);
|
||||
}
|
||||
|
||||
return new IntlMessageFormat(msg, locale).format(variables);
|
||||
// 其次用项目级别的
|
||||
const projectMsg = i18nFormat({ id: t.key, fallback: null }, t.params);
|
||||
if (projectMsg != null) {
|
||||
return projectMsg;
|
||||
}
|
||||
|
||||
// 兜底用 use 指定的或默认语言的
|
||||
return format(t[t.use || "zh_CN"] ?? t.en_US, t.params);
|
||||
};
|
||||
|
||||
// 注入到上下文中去
|
||||
if (target._context && target._context !== target) {
|
||||
Object.assign(target._context, {
|
||||
i18n,
|
||||
getLocale,
|
||||
setLocale: target.setLocale,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const i18n = (id) => {
|
||||
return i18nFormat({ id });
|
||||
};
|
||||
|
||||
export { getLocale, setLocale, i18n, i18nFormat };
|
||||
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。
|
||||
// 例外:react 框架的导出名和各种组件名除外。
|
||||
import React from "react";
|
||||
|
||||
import {
|
||||
@ -25,7 +27,7 @@ import {
|
||||
|
||||
import utils, { RefsManager } from "../../utils";
|
||||
|
||||
import { i18n as _$$i18n } from "../../i18n";
|
||||
import * as __$$i18n from "../../i18n";
|
||||
|
||||
import "./index.css";
|
||||
|
||||
@ -36,6 +38,8 @@ const AliAutoSearchTableDefault = AliAutoSearchTable.default;
|
||||
const NextBlockCell = NextBlock.Cell;
|
||||
|
||||
class Test$$Page extends React.Component {
|
||||
_context = this;
|
||||
|
||||
constructor(props, context) {
|
||||
super(props);
|
||||
|
||||
@ -43,6 +47,8 @@ class Test$$Page extends React.Component {
|
||||
|
||||
this._refsManager = new RefsManager();
|
||||
|
||||
__$$i18n._inject2(this);
|
||||
|
||||
this.state = {
|
||||
pkgs: [],
|
||||
total: 0,
|
||||
@ -79,10 +85,6 @@ class Test$$Page extends React.Component {
|
||||
return this._refsManager.getAll(refName);
|
||||
};
|
||||
|
||||
i18n = (i18nKey) => {
|
||||
return _$$i18n(i18nKey);
|
||||
};
|
||||
|
||||
componentDidUpdate(prevProps, prevState, snapshot) {}
|
||||
|
||||
componentWillUnmount() {}
|
||||
@ -207,8 +209,8 @@ class Test$$Page extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const __$$context = this;
|
||||
const { state } = this;
|
||||
const __$$context = this._context || this;
|
||||
const { state } = __$$context;
|
||||
return (
|
||||
<div
|
||||
ref={this._refsManager.linkRef("outterView")}
|
||||
@ -216,7 +218,7 @@ class Test$$Page extends React.Component {
|
||||
>
|
||||
<Modal
|
||||
title="查看结果"
|
||||
visible={this.state.resultVisible}
|
||||
visible={__$$eval(() => this.state.resultVisible)}
|
||||
footer={
|
||||
<Button
|
||||
type="primary"
|
||||
@ -267,7 +269,9 @@ class Test$$Page extends React.Component {
|
||||
maskClosable={true}
|
||||
>
|
||||
<AliAutoDivDefault style={{ width: "100%" }}>
|
||||
{!!(this.state.results && this.state.results.length > 0) && (
|
||||
{!!__$$eval(
|
||||
() => this.state.results && this.state.results.length > 0
|
||||
) && (
|
||||
<AliAutoDivDefault
|
||||
style={{
|
||||
width: "100%",
|
||||
@ -299,20 +303,26 @@ class Test$$Page extends React.Component {
|
||||
</Button>
|
||||
</AliAutoDivDefault>
|
||||
)}
|
||||
{this.state.results.map((item, index) =>
|
||||
{__$$evalArray(() => this.state.results).map((item, index) =>
|
||||
((__$$context) => (
|
||||
<AliAutoDivDefault style={{ width: "100%", marginTop: "10px" }}>
|
||||
<Typography.Text>
|
||||
{__$$context.formatResult(item)}
|
||||
{__$$eval(() => __$$context.formatResult(item))}
|
||||
</Typography.Text>
|
||||
{!!item.download_link && (
|
||||
<Typography.Link href={item.download_link} target="_blank">
|
||||
{!!__$$eval(() => item.download_link) && (
|
||||
<Typography.Link
|
||||
href={__$$eval(() => item.download_link)}
|
||||
target="_blank"
|
||||
>
|
||||
{" "}
|
||||
- 点击下载
|
||||
</Typography.Link>
|
||||
)}
|
||||
{!!item.release_notes && (
|
||||
<Typography.Link href={item.release_notes} target="_blank">
|
||||
{!!__$$eval(() => item.release_notes) && (
|
||||
<Typography.Link
|
||||
href={__$$eval(() => item.release_notes)}
|
||||
target="_blank"
|
||||
>
|
||||
{" "}
|
||||
- 跳转发布节点
|
||||
</Typography.Link>
|
||||
@ -376,7 +386,7 @@ class Test$$Page extends React.Component {
|
||||
preserve={true}
|
||||
scrollToFirstError={true}
|
||||
size="middle"
|
||||
values={this.state.searchValues}
|
||||
values={__$$eval(() => this.state.searchValues)}
|
||||
>
|
||||
<Form.Item
|
||||
label="项目名称/渠道号"
|
||||
@ -386,7 +396,7 @@ class Test$$Page extends React.Component {
|
||||
>
|
||||
<Select
|
||||
style={{ width: "320px" }}
|
||||
options={this.state.projects}
|
||||
options={__$$eval(() => this.state.projects)}
|
||||
showArrow={false}
|
||||
tokenSeparators={[]}
|
||||
showSearch={true}
|
||||
@ -452,14 +462,16 @@ class Test$$Page extends React.Component {
|
||||
<Form.Item label="构建人" name="user_id">
|
||||
<Select
|
||||
style={{ width: "210px" }}
|
||||
options={this.state.userOptions}
|
||||
options={__$$eval(() => this.state.userOptions)}
|
||||
showSearch={true}
|
||||
defaultActiveFirstOption={false}
|
||||
size="middle"
|
||||
bordered={true}
|
||||
filterOption={true}
|
||||
optionFilterProp="label"
|
||||
notFoundContent={this.userNotFoundContent}
|
||||
notFoundContent={__$$eval(
|
||||
() => this.userNotFoundContent
|
||||
)}
|
||||
showArrow={false}
|
||||
placeholder="请输入构建人"
|
||||
__events={{
|
||||
@ -566,13 +578,14 @@ class Test$$Page extends React.Component {
|
||||
align="left"
|
||||
flex={true}
|
||||
>
|
||||
{!!(
|
||||
{!!__$$eval(
|
||||
() =>
|
||||
!this.state.isSearch ||
|
||||
(this.state.isSearch && this.state.pkgs.length > 0)
|
||||
) && (
|
||||
<AliAutoSearchTableDefault
|
||||
rowKey="key"
|
||||
dataSource={this.state.pkgs}
|
||||
dataSource={__$$eval(() => this.state.pkgs)}
|
||||
columns={[
|
||||
{ title: "ID", dataIndex: "id", key: "name", width: 80 },
|
||||
{
|
||||
@ -582,12 +595,11 @@ class Test$$Page extends React.Component {
|
||||
width: 142,
|
||||
render: (text, record, index) =>
|
||||
((__$$context) =>
|
||||
text
|
||||
.split(",")
|
||||
.map((item, index) =>
|
||||
__$$evalArray(() => text.split(",")).map(
|
||||
(item, index) =>
|
||||
((__$$context) => (
|
||||
<Typography.Text style={{ display: "block" }}>
|
||||
{item}
|
||||
{__$$eval(() => item)}
|
||||
</Typography.Text>
|
||||
))(
|
||||
__$$createChildContext(__$$context, {
|
||||
@ -610,7 +622,8 @@ class Test$$Page extends React.Component {
|
||||
render: (text, record, index) =>
|
||||
((__$$context) => (
|
||||
<Tooltip
|
||||
title={(text || []).map((item, index) =>
|
||||
title={__$$evalArray(() => text || []).map(
|
||||
(item, index) =>
|
||||
((__$$context) => (
|
||||
<Typography.Text
|
||||
style={{
|
||||
@ -618,7 +631,10 @@ class Test$$Page extends React.Component {
|
||||
color: "#FFFFFF",
|
||||
}}
|
||||
>
|
||||
{item.channelId + " / " + item.version}
|
||||
{__$$eval(
|
||||
() =>
|
||||
item.channelId + " / " + item.version
|
||||
)}
|
||||
</Typography.Text>
|
||||
))(
|
||||
__$$createChildContext(__$$context, {
|
||||
@ -629,7 +645,7 @@ class Test$$Page extends React.Component {
|
||||
)}
|
||||
>
|
||||
<Typography.Text>
|
||||
{text[0].version}
|
||||
{__$$eval(() => text[0].version)}
|
||||
</Typography.Text>
|
||||
</Tooltip>
|
||||
))(
|
||||
@ -653,9 +669,9 @@ class Test$$Page extends React.Component {
|
||||
render: (text, record, index) =>
|
||||
((__$$context) => [
|
||||
<Typography.Text>
|
||||
{__$$context.statusDesc[text]}
|
||||
{__$$eval(() => __$$context.statusDesc[text])}
|
||||
</Typography.Text>,
|
||||
!!(text === 2) && (
|
||||
!!__$$eval(() => text === 2) && (
|
||||
<Icon
|
||||
type="SyncOutlined"
|
||||
size={16}
|
||||
@ -699,12 +715,17 @@ class Test$$Page extends React.Component {
|
||||
dataIndex: "jenkins_link",
|
||||
render: (text, record, index) =>
|
||||
((__$$context) => [
|
||||
!!text && (
|
||||
<Typography.Link href={text} target="_blank">
|
||||
!!__$$eval(() => text) && (
|
||||
<Typography.Link
|
||||
href={__$$eval(() => text)}
|
||||
target="_blank"
|
||||
>
|
||||
查看
|
||||
</Typography.Link>
|
||||
),
|
||||
!!!text && <Typography.Text>暂无</Typography.Text>,
|
||||
!!__$$eval(() => !text) && (
|
||||
<Typography.Text>暂无</Typography.Text>
|
||||
),
|
||||
])(
|
||||
__$$createChildContext(__$$context, {
|
||||
text,
|
||||
@ -720,7 +741,7 @@ class Test$$Page extends React.Component {
|
||||
width: 120,
|
||||
render: (text, record, index) =>
|
||||
((__$$context) => [
|
||||
!!text && (
|
||||
!!__$$eval(() => text) && (
|
||||
<Typography.Link
|
||||
href="http://rivermap.alibaba.net/dashboard/testExecute"
|
||||
target="_blank"
|
||||
@ -728,7 +749,9 @@ class Test$$Page extends React.Component {
|
||||
查看
|
||||
</Typography.Link>
|
||||
),
|
||||
!!!text && <Typography.Text>暂无</Typography.Text>,
|
||||
!!__$$eval(() => !text) && (
|
||||
<Typography.Text>暂无</Typography.Text>
|
||||
),
|
||||
])(
|
||||
__$$createChildContext(__$$context, {
|
||||
text,
|
||||
@ -811,7 +834,7 @@ class Test$$Page extends React.Component {
|
||||
);
|
||||
}.bind(__$$context)}
|
||||
ghost={false}
|
||||
href={text}
|
||||
href={__$$eval(() => text)}
|
||||
>
|
||||
查看
|
||||
</Button>
|
||||
@ -883,7 +906,7 @@ class Test$$Page extends React.Component {
|
||||
]}
|
||||
actions={[]}
|
||||
pagination={{
|
||||
total: this.state.total,
|
||||
total: __$$eval(() => this.state.total),
|
||||
defaultPageSize: 10,
|
||||
onPageChange: function () {
|
||||
return this.onPageChange.apply(
|
||||
@ -915,9 +938,9 @@ class Test$$Page extends React.Component {
|
||||
align="left"
|
||||
flex={true}
|
||||
>
|
||||
{!!(this.state.pkgs.length < 1 && this.state.isSearch) && (
|
||||
<Empty description="暂无数据" />
|
||||
)}
|
||||
{!!__$$eval(
|
||||
() => this.state.pkgs.length < 1 && this.state.isSearch
|
||||
) && <Empty description="暂无数据" />}
|
||||
</NextP>
|
||||
</NextBlockCell>
|
||||
</NextBlock>
|
||||
@ -929,6 +952,17 @@ class Test$$Page extends React.Component {
|
||||
|
||||
export default Test$$Page;
|
||||
|
||||
function __$$eval(expr) {
|
||||
try {
|
||||
return expr();
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
function __$$evalArray(expr) {
|
||||
const res = __$$eval(expr);
|
||||
return Array.isArray(res) ? res : [];
|
||||
}
|
||||
|
||||
function __$$createChildContext(oldContext, ext) {
|
||||
const childContext = {
|
||||
...oldContext,
|
||||
|
||||
@ -0,0 +1,52 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"componentsMap": [
|
||||
{
|
||||
"package": "react-greetings",
|
||||
"version": "1.0.0",
|
||||
"componentName": "Greetings",
|
||||
"exportName": "Greetings",
|
||||
"destructuring": true
|
||||
}
|
||||
],
|
||||
"componentsTree": [
|
||||
{
|
||||
"componentName": "Page",
|
||||
"id": "node_ocl137q7oc1",
|
||||
"fileName": "test",
|
||||
"props": { "style": {} },
|
||||
"lifeCycles": {},
|
||||
"dataSource": { "list": [] },
|
||||
"state": {
|
||||
"name": "lowcode world"
|
||||
},
|
||||
"methods": {},
|
||||
"children": [
|
||||
{
|
||||
"componentName": "Greetings",
|
||||
"id": "node_ocl137q7oc4",
|
||||
"props": {
|
||||
"content": {
|
||||
"type": "i18n",
|
||||
"key": "greetings.hello",
|
||||
"params": {
|
||||
"name": {
|
||||
"type": "JSExpression",
|
||||
"value": "this.state.name"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"i18n": {
|
||||
"zh_CN": {
|
||||
"greetings.hello": "${name}, 你好!"
|
||||
},
|
||||
"en_US": {
|
||||
"greetings.hello": "Hello, ${name}!"
|
||||
}
|
||||
}
|
||||
}
|
||||
54
modules/code-generator/tests/bugfix/i18n-with-params.test.ts
Normal file
54
modules/code-generator/tests/bugfix/i18n-with-params.test.ts
Normal file
@ -0,0 +1,54 @@
|
||||
import CodeGenerator from '../../src';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { ProjectSchema } from '@alilc/lowcode-types';
|
||||
import { createDiskPublisher } from '../helpers/solutionHelper';
|
||||
|
||||
const testCaseBaseName = path.basename(__filename, '.test.ts');
|
||||
const inputSchemaJsonFile = path.join(__dirname, `${testCaseBaseName}.schema.json`);
|
||||
const outputDir = path.join(__dirname, `${testCaseBaseName}.generated`);
|
||||
|
||||
jest.setTimeout(60 * 60 * 1000);
|
||||
|
||||
describe(testCaseBaseName, () => {
|
||||
test('default import', async () => {
|
||||
await exportProject(inputSchemaJsonFile, outputDir, {});
|
||||
|
||||
const generatedPageFileContent = readOutputTextFile('demo-project/src/pages/Test/index.jsx');
|
||||
expect(generatedPageFileContent).toContain(
|
||||
`
|
||||
<Greetings
|
||||
content={this._i18nText({
|
||||
key: "greetings.hello",
|
||||
params: { name: this.state.name },
|
||||
})}
|
||||
/>
|
||||
`.trim(),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
function exportProject(
|
||||
importPath: string,
|
||||
outputPath: string,
|
||||
mergeSchema?: Partial<ProjectSchema>,
|
||||
) {
|
||||
const schemaJsonStr = fs.readFileSync(importPath, { encoding: 'utf8' });
|
||||
const schema = { ...JSON.parse(schemaJsonStr), ...mergeSchema };
|
||||
const builder = CodeGenerator.solutions.icejs({ tolerateEvalErrors: false });
|
||||
|
||||
return builder.generateProject(schema).then(async (result) => {
|
||||
const publisher = createDiskPublisher();
|
||||
await publisher.publish({
|
||||
project: result,
|
||||
outputPath,
|
||||
projectSlug: 'demo-project',
|
||||
createProjectFolder: true,
|
||||
});
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
function readOutputTextFile(outputFilePath: string): string {
|
||||
return fs.readFileSync(path.resolve(outputDir, outputFilePath), 'utf-8');
|
||||
}
|
||||
@ -2,6 +2,7 @@ import CodeGenerator from '../../src';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { ProjectSchema } from '@alilc/lowcode-types';
|
||||
import { createDiskPublisher } from '../helpers/solutionHelper';
|
||||
|
||||
const testCaseBaseName = path.basename(__filename, '.test.ts');
|
||||
const inputSchemaJsonFile = path.join(__dirname, `${testCaseBaseName}.schema.json`);
|
||||
@ -205,7 +206,7 @@ function exportProject(
|
||||
|
||||
return builder.generateProject(schema).then(async (result) => {
|
||||
// displayResultInConsole(result);
|
||||
const publisher = CodeGenerator.publishers.disk();
|
||||
const publisher = createDiskPublisher();
|
||||
await publisher.publish({
|
||||
project: result,
|
||||
outputPath,
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import CodeGenerator from '../../src';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { createDiskPublisher } from '../helpers/solutionHelper';
|
||||
|
||||
const testCaseBaseName = path.basename(__filename, '.test.ts');
|
||||
|
||||
@ -31,7 +32,7 @@ function exportProject(inputPath: string, outputPath: string) {
|
||||
|
||||
return builder.generateProject(newSchema).then(async (result) => {
|
||||
// displayResultInConsole(result);
|
||||
const publisher = CodeGenerator.publishers.disk();
|
||||
const publisher = createDiskPublisher();
|
||||
await publisher.publish({
|
||||
project: result,
|
||||
outputPath,
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import CodeGenerator from '../../src';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { createDiskPublisher } from '../helpers/solutionHelper';
|
||||
|
||||
const testCaseBaseName = path.basename(__filename, '.test.ts');
|
||||
|
||||
@ -31,7 +32,7 @@ function exportProject(inputPath: string, outputPath: string) {
|
||||
|
||||
return builder.generateProject(newSchema).then(async (result) => {
|
||||
// displayResultInConsole(result);
|
||||
const publisher = CodeGenerator.publishers.disk();
|
||||
const publisher = createDiskPublisher();
|
||||
await publisher.publish({
|
||||
project: result,
|
||||
outputPath,
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import CodeGenerator from '../../src';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { createDiskPublisher } from '../helpers/solutionHelper';
|
||||
|
||||
const testCaseBaseName = path.basename(__filename, '.test.ts');
|
||||
|
||||
@ -37,7 +38,7 @@ function exportProject(inputPath: string, outputPath: string) {
|
||||
|
||||
return builder.generateProject(newSchema).then(async (result) => {
|
||||
// displayResultInConsole(result);
|
||||
const publisher = CodeGenerator.publishers.disk();
|
||||
const publisher = createDiskPublisher();
|
||||
await publisher.publish({
|
||||
project: result,
|
||||
outputPath,
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import CodeGenerator from '../../src';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { createDiskPublisher } from '../helpers/solutionHelper';
|
||||
|
||||
const testCaseBaseName = path.basename(__filename, '.test.ts');
|
||||
|
||||
@ -25,7 +26,7 @@ function exportProject(inputPath: string, outputPath: string) {
|
||||
|
||||
return builder.generateProject(newSchema).then(async (result) => {
|
||||
// displayResultInConsole(result);
|
||||
const publisher = CodeGenerator.publishers.disk();
|
||||
const publisher = createDiskPublisher();
|
||||
await publisher.publish({
|
||||
project: result,
|
||||
outputPath,
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import CodeGenerator from '../../src';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { createDiskPublisher } from '../helpers/solutionHelper';
|
||||
|
||||
test('page-element1', async () => {
|
||||
const inputSchemaJsonFile = path.join(__dirname, 'page-element1.schema.json');
|
||||
@ -67,7 +68,7 @@ function exportProject(inputPath: string, outputPath: string) {
|
||||
|
||||
return builder.generateProject(newSchema).then(async (result) => {
|
||||
// displayResultInConsole(result);
|
||||
const publisher = CodeGenerator.publishers.disk();
|
||||
const publisher = createDiskPublisher();
|
||||
await publisher.publish({
|
||||
project: result,
|
||||
outputPath,
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import CodeGenerator from '../../src';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { createDiskPublisher } from '../helpers/solutionHelper';
|
||||
|
||||
test('page-element2', async () => {
|
||||
const inputSchemaJsonFile = path.join(__dirname, 'page-element2.schema.json');
|
||||
@ -67,7 +68,7 @@ function exportProject(inputPath: string, outputPath: string) {
|
||||
|
||||
return builder.generateProject(newSchema).then(async (result) => {
|
||||
// displayResultInConsole(result);
|
||||
const publisher = CodeGenerator.publishers.disk();
|
||||
const publisher = createDiskPublisher();
|
||||
await publisher.publish({
|
||||
project: result,
|
||||
outputPath,
|
||||
|
||||
@ -0,0 +1,677 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"componentsMap": [
|
||||
{
|
||||
"package": "@alilc/antd-lowcode",
|
||||
"version": "0.5.4",
|
||||
"exportName": "Typography",
|
||||
"main": "dist/antd-lowcode.esm.js",
|
||||
"destructuring": true,
|
||||
"subName": "Text",
|
||||
"componentName": "Typography.Text"
|
||||
},
|
||||
{
|
||||
"package": "@alilc/antd-lowcode",
|
||||
"version": "0.5.4",
|
||||
"exportName": "Select",
|
||||
"main": "dist/antd-lowcode.esm.js",
|
||||
"destructuring": true,
|
||||
"componentName": "Select"
|
||||
},
|
||||
{
|
||||
"package": "@alilc/antd-lowcode",
|
||||
"version": "0.5.4",
|
||||
"exportName": "Space",
|
||||
"main": "dist/antd-lowcode.esm.js",
|
||||
"destructuring": true,
|
||||
"componentName": "Space"
|
||||
},
|
||||
{
|
||||
"package": "@alilc/antd-lowcode",
|
||||
"version": "0.5.4",
|
||||
"exportName": "Button",
|
||||
"main": "dist/antd-lowcode.esm.js",
|
||||
"destructuring": true,
|
||||
"componentName": "Button"
|
||||
},
|
||||
{
|
||||
"package": "@alilc/antd-lowcode",
|
||||
"version": "0.5.4",
|
||||
"exportName": "InputNumber",
|
||||
"main": "dist/antd-lowcode.esm.js",
|
||||
"destructuring": true,
|
||||
"componentName": "InputNumber"
|
||||
},
|
||||
{
|
||||
"package": "@alilc/antd-lowcode",
|
||||
"version": "0.5.4",
|
||||
"exportName": "Form",
|
||||
"main": "dist/antd-lowcode.esm.js",
|
||||
"destructuring": true,
|
||||
"subName": "Item",
|
||||
"componentName": "Form.Item"
|
||||
},
|
||||
{
|
||||
"package": "@alilc/antd-lowcode",
|
||||
"version": "0.5.4",
|
||||
"exportName": "Input",
|
||||
"main": "dist/antd-lowcode.esm.js",
|
||||
"destructuring": true,
|
||||
"subName": "TextArea",
|
||||
"componentName": "Input.TextArea"
|
||||
},
|
||||
{
|
||||
"package": "@alilc/antd-lowcode",
|
||||
"version": "0.5.4",
|
||||
"exportName": "Form",
|
||||
"main": "dist/antd-lowcode.esm.js",
|
||||
"destructuring": true,
|
||||
"componentName": "Form"
|
||||
},
|
||||
{
|
||||
"package": "@alilc/antd-lowcode",
|
||||
"version": "0.5.4",
|
||||
"exportName": "Modal",
|
||||
"main": "dist/antd-lowcode.esm.js",
|
||||
"destructuring": true,
|
||||
"componentName": "Modal"
|
||||
},
|
||||
{
|
||||
"package": "@alife/mc-assets-1935",
|
||||
"version": "0.1.16",
|
||||
"exportName": "AliAutoSearchTable",
|
||||
"main": "build/lowcode/index.js",
|
||||
"destructuring": true,
|
||||
"subName": "default",
|
||||
"componentName": "AliAutoSearchTableDefault"
|
||||
},
|
||||
{
|
||||
"package": "@alilc/antd-lowcode",
|
||||
"version": "0.5.4",
|
||||
"exportName": "Card",
|
||||
"main": "dist/antd-lowcode.esm.js",
|
||||
"destructuring": true,
|
||||
"componentName": "Card"
|
||||
},
|
||||
{
|
||||
"package": "@alife/container",
|
||||
"version": "0.3.7",
|
||||
"exportName": "P",
|
||||
"main": "lib/index.js",
|
||||
"destructuring": true,
|
||||
"subName": "",
|
||||
"componentName": "NextP"
|
||||
},
|
||||
{
|
||||
"package": "@alife/container",
|
||||
"version": "0.3.7",
|
||||
"exportName": "Block",
|
||||
"main": "lib/index.js",
|
||||
"destructuring": true,
|
||||
"subName": "Cell",
|
||||
"componentName": "NextBlockCell"
|
||||
},
|
||||
{
|
||||
"package": "@alife/container",
|
||||
"version": "0.3.7",
|
||||
"exportName": "Block",
|
||||
"main": "lib/index.js",
|
||||
"destructuring": true,
|
||||
"subName": "",
|
||||
"componentName": "NextBlock"
|
||||
},
|
||||
{
|
||||
"devMode": "lowcode",
|
||||
"componentName": "Slot"
|
||||
},
|
||||
{
|
||||
"package": "@alife/container",
|
||||
"version": "0.3.7",
|
||||
"exportName": "Page",
|
||||
"main": "lib/index.js",
|
||||
"destructuring": true,
|
||||
"subName": "",
|
||||
"componentName": "NextPage"
|
||||
},
|
||||
{
|
||||
"devMode": "lowcode",
|
||||
"componentName": "Page"
|
||||
}
|
||||
],
|
||||
"componentsTree": [
|
||||
{
|
||||
"componentName": "Page",
|
||||
"id": "node_dockcviv8fo1",
|
||||
"props": {
|
||||
"ref": "outterView",
|
||||
"style": {
|
||||
"height": "100%"
|
||||
}
|
||||
},
|
||||
"fileName": "test",
|
||||
"dataSource": {
|
||||
"list": []
|
||||
},
|
||||
"css": "body {\n font-size: 12px;\n}\n\n.botton {\n width: 100px;\n color: #ff00ff\n}",
|
||||
"lifeCycles": {
|
||||
"componentDidMount": {
|
||||
"type": "JSFunction",
|
||||
"value": "function() { /* ... */ }"
|
||||
},
|
||||
"componentWillUnmount": {
|
||||
"type": "JSFunction",
|
||||
"value": "function() { /* ... */ }"
|
||||
},
|
||||
"componentDidUpdate": {
|
||||
"type": "JSFunction",
|
||||
"value": "function() { /* ... */ }"
|
||||
}
|
||||
},
|
||||
"methods": {
|
||||
"onChange": {
|
||||
"type": "JSFunction",
|
||||
"value": "function() { /* ... */ }"
|
||||
},
|
||||
"getActions": {
|
||||
"type": "JSFunction",
|
||||
"value": "function() { /* ... */ }"
|
||||
},
|
||||
"onCreateOrder": {
|
||||
"type": "JSFunction",
|
||||
"value": "function() { /* ... */ }"
|
||||
},
|
||||
"onCancelModal": {
|
||||
"type": "JSFunction",
|
||||
"value": "function() { /* ... */ }"
|
||||
},
|
||||
"onConfirmCreateOrder": {
|
||||
"type": "JSFunction",
|
||||
"value": "function() { /* ... */ }"
|
||||
}
|
||||
},
|
||||
"state": {
|
||||
"name": "nongzhou",
|
||||
"gateways": [],
|
||||
"selectedGateway": null,
|
||||
"records": [],
|
||||
"modalVisible": false
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"componentName": "NextPage",
|
||||
"id": "node_ocknqx3esma",
|
||||
"props": {
|
||||
"columns": 12,
|
||||
"headerDivider": true,
|
||||
"placeholderStyle": {
|
||||
"gridRowEnd": "span 1",
|
||||
"gridColumnEnd": "span 12"
|
||||
},
|
||||
"placeholder": "页面主体内容:拖拽Block布局组件到这里",
|
||||
"header": {
|
||||
"type": "JSSlot",
|
||||
"title": "header"
|
||||
},
|
||||
"headerProps": {
|
||||
"background": "surface"
|
||||
},
|
||||
"footer": {
|
||||
"type": "JSSlot",
|
||||
"title": "footer"
|
||||
},
|
||||
"minHeight": "100vh",
|
||||
"style": {
|
||||
"cursor": "pointer"
|
||||
}
|
||||
},
|
||||
"title": "页面",
|
||||
"children": [
|
||||
{
|
||||
"componentName": "NextBlock",
|
||||
"id": "node_ocknqx3esmb",
|
||||
"props": {
|
||||
"prefix": "next-",
|
||||
"placeholderStyle": {
|
||||
"height": "100%"
|
||||
},
|
||||
"noPadding": false,
|
||||
"noBorder": false,
|
||||
"background": "surface",
|
||||
"layoutmode": "O",
|
||||
"colSpan": 12,
|
||||
"rowSpan": 1,
|
||||
"childTotalColumns": 12
|
||||
},
|
||||
"title": "区块",
|
||||
"children": [
|
||||
{
|
||||
"componentName": "NextBlockCell",
|
||||
"id": "node_ocknqx3esmc",
|
||||
"props": {
|
||||
"title": "",
|
||||
"prefix": "next-",
|
||||
"placeholderStyle": {
|
||||
"height": "100%"
|
||||
},
|
||||
"layoutmode": "O",
|
||||
"childTotalColumns": 12,
|
||||
"isAutoContainer": true,
|
||||
"colSpan": 12,
|
||||
"rowSpan": 1
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"componentName": "NextP",
|
||||
"id": "node_ocknqx3esm1j",
|
||||
"props": {
|
||||
"wrap": false,
|
||||
"type": "body2",
|
||||
"verAlign": "middle",
|
||||
"textSpacing": true,
|
||||
"align": "left",
|
||||
"full": true,
|
||||
"flex": true
|
||||
},
|
||||
"title": "段落",
|
||||
"children": [
|
||||
{
|
||||
"componentName": "Card",
|
||||
"id": "node_ocknqx3esm1k",
|
||||
"props": {
|
||||
"title": ""
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"componentName": "Space",
|
||||
"id": "node_ocknqx3esm1n",
|
||||
"props": {
|
||||
"size": 0,
|
||||
"align": "center",
|
||||
"direction": "horizontal"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"componentName": "Typography.Text",
|
||||
"id": "node_ocknqx3esm1l",
|
||||
"props": {
|
||||
"children": "所在网关:"
|
||||
}
|
||||
},
|
||||
{
|
||||
"componentName": "Select",
|
||||
"id": "node_ocknqx3esm1m",
|
||||
"props": {
|
||||
"style": {
|
||||
"marginTop": "16px",
|
||||
"marginRight": "16px",
|
||||
"marginBottom": "16px",
|
||||
"marginLeft": "16px",
|
||||
"width": "400px",
|
||||
"display": "inline-block"
|
||||
},
|
||||
"options": {
|
||||
"type": "JSExpression",
|
||||
"value": "this.state.gateways"
|
||||
},
|
||||
"mode": "single",
|
||||
"defaultValue": ["auto-edd-uniproxy"],
|
||||
"labelInValue": true,
|
||||
"showSearch": true,
|
||||
"allowClear": false,
|
||||
"placeholder": "请选取网关",
|
||||
"showArrow": true,
|
||||
"loading": false,
|
||||
"tokenSeparators": [],
|
||||
"__events": {
|
||||
"eventDataList": [
|
||||
{
|
||||
"type": "componentEvent",
|
||||
"name": "onChange",
|
||||
"relatedEventName": "onChange"
|
||||
}
|
||||
],
|
||||
"eventList": [
|
||||
{
|
||||
"name": "onBlur",
|
||||
"disabled": false
|
||||
},
|
||||
{
|
||||
"name": "onChange",
|
||||
"disabled": true
|
||||
},
|
||||
{
|
||||
"name": "onDeselect",
|
||||
"disabled": false
|
||||
},
|
||||
{
|
||||
"name": "onFocus",
|
||||
"disabled": false
|
||||
},
|
||||
{
|
||||
"name": "onInputKeyDown",
|
||||
"disabled": false
|
||||
},
|
||||
{
|
||||
"name": "onMouseEnter",
|
||||
"disabled": false
|
||||
},
|
||||
{
|
||||
"name": "onMouseLeave",
|
||||
"disabled": false
|
||||
},
|
||||
{
|
||||
"name": "onPopupScroll",
|
||||
"disabled": false
|
||||
},
|
||||
{
|
||||
"name": "onSearch",
|
||||
"disabled": false
|
||||
},
|
||||
{
|
||||
"name": "onSelect",
|
||||
"disabled": false
|
||||
},
|
||||
{
|
||||
"name": "onDropdownVisibleChange",
|
||||
"disabled": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"onChange": {
|
||||
"type": "JSFunction",
|
||||
"value": "function(){this.onChange.apply(this,Array.prototype.slice.call(arguments).concat([])) }"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"componentName": "Button",
|
||||
"id": "node_ockntwgdsn7",
|
||||
"props": {
|
||||
"type": "primary",
|
||||
"children": "创建发布单",
|
||||
"style": {
|
||||
"display": "block",
|
||||
"marginTop": "20px",
|
||||
"marginBottom": "20px"
|
||||
},
|
||||
"__events": {
|
||||
"eventDataList": [
|
||||
{
|
||||
"type": "componentEvent",
|
||||
"name": "onClick",
|
||||
"relatedEventName": "onCreateOrder"
|
||||
}
|
||||
],
|
||||
"eventList": [
|
||||
{
|
||||
"name": "onClick",
|
||||
"disabled": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"onClick": {
|
||||
"type": "JSFunction",
|
||||
"value": "function(){this.onCreateOrder.apply(this,Array.prototype.slice.call(arguments).concat([])) }"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"componentName": "Modal",
|
||||
"id": "node_ockntx4eo9p",
|
||||
"props": {
|
||||
"title": "创建发布单",
|
||||
"visible": {
|
||||
"type": "JSExpression",
|
||||
"value": "this.state.modalVisible"
|
||||
},
|
||||
"footer": "",
|
||||
"__events": {
|
||||
"eventDataList": [
|
||||
{
|
||||
"type": "componentEvent",
|
||||
"name": "onCancel",
|
||||
"relatedEventName": "onCancelModal"
|
||||
}
|
||||
],
|
||||
"eventList": [
|
||||
{
|
||||
"name": "onCancel",
|
||||
"disabled": true
|
||||
},
|
||||
{
|
||||
"name": "onOk",
|
||||
"disabled": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"onCancel": {
|
||||
"type": "JSFunction",
|
||||
"value": "function(){this.onCancelModal.apply(this,Array.prototype.slice.call(arguments).concat([])) }"
|
||||
},
|
||||
"zIndex": 2000
|
||||
},
|
||||
"hidden": true,
|
||||
"children": [
|
||||
{
|
||||
"componentName": "Form",
|
||||
"id": "node_ockntx4eo9s",
|
||||
"props": {
|
||||
"labelCol": {
|
||||
"span": 6
|
||||
},
|
||||
"wrapperCol": {
|
||||
"span": 14
|
||||
},
|
||||
"onFinish": {
|
||||
"type": "JSFunction",
|
||||
"value": "function(){this.onConfirmCreateOrder.apply(this,Array.prototype.slice.call(arguments).concat([])) }"
|
||||
},
|
||||
"name": "basic",
|
||||
"__events": {
|
||||
"eventDataList": [
|
||||
{
|
||||
"type": "componentEvent",
|
||||
"name": "onFinish",
|
||||
"relatedEventName": "onConfirmCreateOrder"
|
||||
}
|
||||
],
|
||||
"eventList": [
|
||||
{
|
||||
"name": "onFinish",
|
||||
"disabled": true
|
||||
},
|
||||
{
|
||||
"name": "onFinishFailed",
|
||||
"disabled": false
|
||||
},
|
||||
{
|
||||
"name": "onFieldsChange",
|
||||
"disabled": false
|
||||
},
|
||||
{
|
||||
"name": "onValuesChange",
|
||||
"disabled": false
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"componentName": "Form.Item",
|
||||
"id": "node_ockntx4eo91k",
|
||||
"props": {
|
||||
"label": "发布批次"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"componentName": "InputNumber",
|
||||
"id": "node_ockntx4eo91l",
|
||||
"props": {
|
||||
"value": 3,
|
||||
"min": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"componentName": "Form.Item",
|
||||
"id": "node_ockntx4eo91r",
|
||||
"props": {
|
||||
"label": "批次间隔时间"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"componentName": "InputNumber",
|
||||
"id": "node_ockntx4eo91s",
|
||||
"props": {
|
||||
"value": 3
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"componentName": "Form.Item",
|
||||
"id": "node_ockntx4eo91y",
|
||||
"props": {
|
||||
"label": "备注 "
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"componentName": "Input.TextArea",
|
||||
"id": "node_ockntx4eo91z",
|
||||
"props": {
|
||||
"rows": 3,
|
||||
"placeholder": "请输入"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"componentName": "Form.Item",
|
||||
"id": "node_ockntx4eo9v",
|
||||
"props": {
|
||||
"wrapperCol": {
|
||||
"offset": 6
|
||||
},
|
||||
"style": {
|
||||
"flexDirection": "row",
|
||||
"alignItems": "flex-end",
|
||||
"justifyContent": "center",
|
||||
"display": "flex"
|
||||
},
|
||||
"labelAlign": "right"
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"componentName": "Button",
|
||||
"id": "node_ockntx4eo9w",
|
||||
"props": {
|
||||
"type": "primary",
|
||||
"children": "提交",
|
||||
"htmlType": "submit"
|
||||
}
|
||||
},
|
||||
{
|
||||
"componentName": "Button",
|
||||
"id": "node_ockntx4eo9x",
|
||||
"props": {
|
||||
"style": {
|
||||
"marginLeft": 20
|
||||
},
|
||||
"children": "取消",
|
||||
"__events": {
|
||||
"eventDataList": [
|
||||
{
|
||||
"type": "componentEvent",
|
||||
"name": "onClick",
|
||||
"relatedEventName": "onCancelModal"
|
||||
}
|
||||
],
|
||||
"eventList": [
|
||||
{
|
||||
"name": "onClick",
|
||||
"disabled": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"onClick": {
|
||||
"type": "JSFunction",
|
||||
"value": "function(){this.onCancelModal.apply(this,Array.prototype.slice.call(arguments).concat([])) }"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"componentName": "AliAutoSearchTableDefault",
|
||||
"id": "node_ocknqx3esm1q",
|
||||
"props": {
|
||||
"rowKey": "key",
|
||||
"dataSource": {
|
||||
"type": "JSExpression",
|
||||
"value": "this.state.records"
|
||||
},
|
||||
"columns": [
|
||||
{
|
||||
"title": "发布名称",
|
||||
"dataIndex": "order_name",
|
||||
"key": "name"
|
||||
},
|
||||
{
|
||||
"title": "类型",
|
||||
"dataIndex": "order_type_desc",
|
||||
"key": "age"
|
||||
},
|
||||
{
|
||||
"title": "发布状态",
|
||||
"dataIndex": "order_status_desc",
|
||||
"key": "address"
|
||||
},
|
||||
{
|
||||
"title": "发布人",
|
||||
"dataIndex": "creator_name"
|
||||
},
|
||||
{
|
||||
"title": "当前批次/总批次",
|
||||
"dataIndex": "cur_batch_no"
|
||||
},
|
||||
{
|
||||
"title": "发布机器/总机器",
|
||||
"dataIndex": "pubblish_ip_finish_num"
|
||||
},
|
||||
{
|
||||
"title": "发布时间",
|
||||
"dataIndex": "publish_id"
|
||||
}
|
||||
],
|
||||
"actions": {
|
||||
"type": "JSExpression",
|
||||
"value": "this.actions || []"
|
||||
},
|
||||
"getActions": {
|
||||
"type": "JSFunction",
|
||||
"value": "function(){ return this.getActions.apply(this,Array.prototype.slice.call(arguments).concat([])) }"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"i18n": {}
|
||||
}
|
||||
@ -0,0 +1,57 @@
|
||||
import CodeGenerator from '../../src';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { ProjectSchema } from '@alilc/lowcode-types';
|
||||
import { createDiskPublisher } from '../helpers/solutionHelper';
|
||||
import { IceJsProjectBuilderOptions } from '../../src/solutions/icejs';
|
||||
|
||||
const testCaseBaseName = path.basename(__filename, '.test.ts');
|
||||
const inputSchemaJsonFile = path.join(__dirname, `${testCaseBaseName}.schema.json`);
|
||||
const outputDir = path.join(__dirname, `${testCaseBaseName}.generated`);
|
||||
|
||||
jest.setTimeout(60 * 60 * 1000);
|
||||
|
||||
describe(testCaseBaseName, () => {
|
||||
test('methods will be set to context in constructor', async () => {
|
||||
await exportProject(inputSchemaJsonFile, outputDir, {}, { inStrictMode: true });
|
||||
|
||||
const generatedPageFileContent = readOutputTextFile('demo-project/src/pages/Test/index.jsx');
|
||||
expect(generatedPageFileContent).not.toContain('_context = this;');
|
||||
expect(generatedPageFileContent).toContain('_context = this._createContext();');
|
||||
expect(generatedPageFileContent).toContain(
|
||||
`
|
||||
this._context.onChange = this.onChange;
|
||||
this._context.getActions = this.getActions;
|
||||
this._context.onCreateOrder = this.onCreateOrder;
|
||||
this._context.onCancelModal = this.onCancelModal;
|
||||
this._context.onConfirmCreateOrder = this.onConfirmCreateOrder;
|
||||
`.trim(),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
function exportProject(
|
||||
importPath: string,
|
||||
outputPath: string,
|
||||
mergeSchema?: Partial<ProjectSchema>,
|
||||
options?: IceJsProjectBuilderOptions,
|
||||
) {
|
||||
const schemaJsonStr = fs.readFileSync(importPath, { encoding: 'utf8' });
|
||||
const schema = { ...JSON.parse(schemaJsonStr), ...mergeSchema };
|
||||
const builder = CodeGenerator.solutions.icejs(options);
|
||||
|
||||
return builder.generateProject(schema).then(async (result) => {
|
||||
const publisher = createDiskPublisher();
|
||||
await publisher.publish({
|
||||
project: result,
|
||||
outputPath,
|
||||
projectSlug: 'demo-project',
|
||||
createProjectFolder: true,
|
||||
});
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
function readOutputTextFile(outputFilePath: string): string {
|
||||
return fs.readFileSync(path.resolve(outputDir, outputFilePath), 'utf-8');
|
||||
}
|
||||
@ -0,0 +1,58 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"componentsMap": [
|
||||
{
|
||||
"package": "react-greetings",
|
||||
"version": "1.0.0",
|
||||
"componentName": "Greetings",
|
||||
"exportName": "Greetings",
|
||||
"destructuring": true
|
||||
}
|
||||
],
|
||||
"componentsTree": [
|
||||
{
|
||||
"componentName": "Page",
|
||||
"id": "node_ocl137q7oc1",
|
||||
"fileName": "test",
|
||||
"props": { "style": {} },
|
||||
"lifeCycles": {},
|
||||
"dataSource": { "list": [] },
|
||||
"state": {
|
||||
"name": "lowcode world",
|
||||
"users": null
|
||||
},
|
||||
"methods": {},
|
||||
"children": [
|
||||
{
|
||||
"componentName": "Greetings",
|
||||
"id": "node_ocl137q7oc4",
|
||||
"loop": {
|
||||
"type": "JSExpression",
|
||||
"value": "this.state.users"
|
||||
},
|
||||
"loopArgs": ["item", ""],
|
||||
"props": {
|
||||
"content": {
|
||||
"type": "i18n",
|
||||
"key": "greetings.hello",
|
||||
"params": {
|
||||
"name": {
|
||||
"type": "JSExpression",
|
||||
"value": "this.item"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"i18n": {
|
||||
"zh_CN": {
|
||||
"greetings.hello": "${name}, 你好!"
|
||||
},
|
||||
"en_US": {
|
||||
"greetings.hello": "Hello, ${name}!"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,52 @@
|
||||
import CodeGenerator from '../../src';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { ProjectSchema } from '@alilc/lowcode-types';
|
||||
import { createDiskPublisher } from '../helpers/solutionHelper';
|
||||
import { IceJsProjectBuilderOptions } from '../../src/solutions/icejs';
|
||||
|
||||
const testCaseBaseName = path.basename(__filename, '.test.ts');
|
||||
const inputSchemaJsonFile = path.join(__dirname, `${testCaseBaseName}.schema.json`);
|
||||
const outputDir = path.join(__dirname, `${testCaseBaseName}.generated`);
|
||||
|
||||
jest.setTimeout(60 * 60 * 1000);
|
||||
|
||||
test('loop should be generated link __$$evalArray(xxx).map', async () => {
|
||||
await exportProject(
|
||||
inputSchemaJsonFile,
|
||||
outputDir,
|
||||
{},
|
||||
{ inStrictMode: true, tolerateEvalErrors: true },
|
||||
);
|
||||
|
||||
const generatedPageFileContent = readOutputTextFile('demo-project/src/pages/Test/index.jsx');
|
||||
expect(generatedPageFileContent).toContain(
|
||||
'{__$$evalArray(() => this.state.users).map((item, index) =>',
|
||||
);
|
||||
});
|
||||
|
||||
function exportProject(
|
||||
importPath: string,
|
||||
outputPath: string,
|
||||
mergeSchema?: Partial<ProjectSchema>,
|
||||
options?: IceJsProjectBuilderOptions,
|
||||
) {
|
||||
const schemaJsonStr = fs.readFileSync(importPath, { encoding: 'utf8' });
|
||||
const schema = { ...JSON.parse(schemaJsonStr), ...mergeSchema };
|
||||
const builder = CodeGenerator.solutions.icejs(options);
|
||||
|
||||
return builder.generateProject(schema).then(async (result) => {
|
||||
const publisher = createDiskPublisher();
|
||||
await publisher.publish({
|
||||
project: result,
|
||||
outputPath,
|
||||
projectSlug: 'demo-project',
|
||||
createProjectFolder: true,
|
||||
});
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
function readOutputTextFile(outputFilePath: string): string {
|
||||
return fs.readFileSync(path.resolve(outputDir, outputFilePath), 'utf-8');
|
||||
}
|
||||
@ -0,0 +1,70 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"componentsMap": [
|
||||
{
|
||||
"package": "react-greetings",
|
||||
"version": "1.0.0",
|
||||
"componentName": "Greetings",
|
||||
"exportName": "Greetings",
|
||||
"destructuring": true
|
||||
}
|
||||
],
|
||||
"componentsTree": [
|
||||
{
|
||||
"componentName": "Page",
|
||||
"id": "node_ocl137q7oc1",
|
||||
"fileName": "test",
|
||||
"props": { "style": {} },
|
||||
"lifeCycles": {},
|
||||
"dataSource": { "list": [] },
|
||||
"state": {
|
||||
"name": "lowcode world",
|
||||
"users": null
|
||||
},
|
||||
"methods": {},
|
||||
"children": [
|
||||
{
|
||||
"componentName": "Greetings",
|
||||
"id": "node_ocl137q7oc4",
|
||||
"loop": {
|
||||
"type": "JSExpression",
|
||||
"value": "this.state.users"
|
||||
},
|
||||
"loopArgs": ["item", ""],
|
||||
"props": {
|
||||
"content": {
|
||||
"type": "i18n",
|
||||
"key": "greetings.hello",
|
||||
"params": { "name": { "type": "JSExpression", "value": "this.item" } }
|
||||
}
|
||||
},
|
||||
"children": [
|
||||
{
|
||||
"componentName": "Greetings",
|
||||
"id": "node_ocl137q7oc4",
|
||||
"loop": {
|
||||
"type": "JSExpression",
|
||||
"value": "this.state.messages"
|
||||
},
|
||||
"loopArgs": ["msg", ""],
|
||||
"props": {
|
||||
"content": {
|
||||
"type": "JSExpression",
|
||||
"value": "this.msg"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"i18n": {
|
||||
"zh_CN": {
|
||||
"greetings.hello": "${name}, 你好!"
|
||||
},
|
||||
"en_US": {
|
||||
"greetings.hello": "Hello, ${name}!"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,56 @@
|
||||
import CodeGenerator from '../../src';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { ProjectSchema } from '@alilc/lowcode-types';
|
||||
import { createDiskPublisher } from '../helpers/solutionHelper';
|
||||
import { IceJsProjectBuilderOptions } from '../../src/solutions/icejs';
|
||||
|
||||
const testCaseBaseName = path.basename(__filename, '.test.ts');
|
||||
const inputSchemaJsonFile = path.join(__dirname, `${testCaseBaseName}.schema.json`);
|
||||
const outputDir = path.join(__dirname, `${testCaseBaseName}.generated`);
|
||||
|
||||
jest.setTimeout(60 * 60 * 1000);
|
||||
|
||||
test('loop should be generated link __$$evalArray(xxx).map', async () => {
|
||||
await exportProject(
|
||||
inputSchemaJsonFile,
|
||||
outputDir,
|
||||
{},
|
||||
{ inStrictMode: true, tolerateEvalErrors: true },
|
||||
);
|
||||
|
||||
const generatedPageFileContent = readOutputTextFile('demo-project/src/pages/Test/index.jsx');
|
||||
expect(generatedPageFileContent).toContain(
|
||||
'{__$$evalArray(() => this.state.users).map((item, index) =>',
|
||||
);
|
||||
|
||||
expect(generatedPageFileContent).toContain(
|
||||
'{__$$evalArray(() => __$$context.state.messages).map(',
|
||||
);
|
||||
});
|
||||
|
||||
function exportProject(
|
||||
importPath: string,
|
||||
outputPath: string,
|
||||
mergeSchema?: Partial<ProjectSchema>,
|
||||
options?: IceJsProjectBuilderOptions,
|
||||
) {
|
||||
const schemaJsonStr = fs.readFileSync(importPath, { encoding: 'utf8' });
|
||||
const schema = { ...JSON.parse(schemaJsonStr), ...mergeSchema };
|
||||
const builder = CodeGenerator.solutions.icejs(options);
|
||||
|
||||
return builder.generateProject(schema).then(async (result) => {
|
||||
const publisher = createDiskPublisher();
|
||||
await publisher.publish({
|
||||
project: result,
|
||||
outputPath,
|
||||
projectSlug: 'demo-project',
|
||||
createProjectFolder: true,
|
||||
});
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
function readOutputTextFile(outputFilePath: string): string {
|
||||
return fs.readFileSync(path.resolve(outputDir, outputFilePath), 'utf-8');
|
||||
}
|
||||
@ -1,6 +1,14 @@
|
||||
import { run } from '../src/cli';
|
||||
|
||||
describe('cli', () => {
|
||||
// standalone 模式下不需要测试 cli
|
||||
if (process.env.TEST_TARGET === 'standalone') {
|
||||
it('should ignore', () => {
|
||||
expect(true).toBe(true);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
it('should works for the default example-schema.json', async () => {
|
||||
const res = await run(['example-schema.json'], {
|
||||
solution: 'icejs',
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user