mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2026-03-12 02:46:08 +00:00
feat: add a new built-in solution icejs3 which is corresponding to the latest icejs framework
This commit is contained in:
parent
a6e768f8e9
commit
7879a63638
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@alilc/lowcode-code-generator",
|
"name": "@alilc/lowcode-code-generator",
|
||||||
"version": "1.0.8",
|
"version": "1.1.0",
|
||||||
"description": "出码引擎 for LowCode Engine",
|
"description": "出码引擎 for LowCode Engine",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import { createModuleBuilder } from './generator/ModuleBuilder';
|
|||||||
import { createDiskPublisher } from './publisher/disk';
|
import { createDiskPublisher } from './publisher/disk';
|
||||||
import { createZipPublisher } from './publisher/zip';
|
import { createZipPublisher } from './publisher/zip';
|
||||||
import createIceJsProjectBuilder, { plugins as reactPlugins } from './solutions/icejs';
|
import createIceJsProjectBuilder, { plugins as reactPlugins } from './solutions/icejs';
|
||||||
|
import createIce3JsProjectBuilder, { plugins as icejs3Plugins } from './solutions/icejs3';
|
||||||
import createRaxAppProjectBuilder, { plugins as raxPlugins } from './solutions/rax-app';
|
import createRaxAppProjectBuilder, { plugins as raxPlugins } from './solutions/rax-app';
|
||||||
|
|
||||||
// 引入说明
|
// 引入说明
|
||||||
@ -32,6 +33,7 @@ import * as CONSTANTS from './const';
|
|||||||
|
|
||||||
// 引入内置解决方案模块
|
// 引入内置解决方案模块
|
||||||
import icejs from './plugins/project/framework/icejs';
|
import icejs from './plugins/project/framework/icejs';
|
||||||
|
import icejs3 from './plugins/project/framework/icejs3';
|
||||||
import rax from './plugins/project/framework/rax';
|
import rax from './plugins/project/framework/rax';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@ -39,10 +41,12 @@ export default {
|
|||||||
createModuleBuilder,
|
createModuleBuilder,
|
||||||
solutions: {
|
solutions: {
|
||||||
icejs: createIceJsProjectBuilder,
|
icejs: createIceJsProjectBuilder,
|
||||||
|
icejs3: createIce3JsProjectBuilder,
|
||||||
rax: createRaxAppProjectBuilder,
|
rax: createRaxAppProjectBuilder,
|
||||||
},
|
},
|
||||||
solutionParts: {
|
solutionParts: {
|
||||||
icejs,
|
icejs,
|
||||||
|
icejs3,
|
||||||
rax,
|
rax,
|
||||||
},
|
},
|
||||||
publishers: {
|
publishers: {
|
||||||
@ -74,6 +78,9 @@ export default {
|
|||||||
i18n,
|
i18n,
|
||||||
utils,
|
utils,
|
||||||
},
|
},
|
||||||
|
icejs3: {
|
||||||
|
...icejs3Plugins,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
postprocessor: {
|
postprocessor: {
|
||||||
prettier,
|
prettier,
|
||||||
|
|||||||
@ -16,7 +16,7 @@ import {
|
|||||||
IWithDependency,
|
IWithDependency,
|
||||||
} from '../../types';
|
} from '../../types';
|
||||||
|
|
||||||
import { isValidIdentifier, isValidComponentName } from '../../utils/validate';
|
import { isValidIdentifier } from '../../utils/validate';
|
||||||
|
|
||||||
// TODO: main 这个信息到底怎么用,是不是外部包不需要使用?
|
// TODO: main 这个信息到底怎么用,是不是外部包不需要使用?
|
||||||
const DEP_MAIN_BLOCKLIST = ['lib', 'lib/index', 'es', 'es/index', 'main'];
|
const DEP_MAIN_BLOCKLIST = ['lib', 'lib/index', 'es', 'es/index', 'main'];
|
||||||
@ -261,7 +261,7 @@ function buildPackageImport(
|
|||||||
if (!isValidIdentifier(name)) {
|
if (!isValidIdentifier(name)) {
|
||||||
throw new CodeGeneratorError(`Invalid Identifier [${name}]`);
|
throw new CodeGeneratorError(`Invalid Identifier [${name}]`);
|
||||||
}
|
}
|
||||||
if (info.nodeIdentifier && !isValidComponentName(info.nodeIdentifier)) {
|
if (info.nodeIdentifier && !isValidIdentifier(info.nodeIdentifier)) {
|
||||||
throw new CodeGeneratorError(`Invalid Identifier [${info.nodeIdentifier}]`);
|
throw new CodeGeneratorError(`Invalid Identifier [${info.nodeIdentifier}]`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@ -0,0 +1,17 @@
|
|||||||
|
import template from './template';
|
||||||
|
import globalStyle from './plugins/globalStyle';
|
||||||
|
import packageJSON from './plugins/packageJSON';
|
||||||
|
import layout from './plugins/layout';
|
||||||
|
import appConfig from './plugins/appConfig';
|
||||||
|
import buildConfig from './plugins/buildConfig';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
template,
|
||||||
|
plugins: {
|
||||||
|
appConfig,
|
||||||
|
buildConfig,
|
||||||
|
globalStyle,
|
||||||
|
packageJSON,
|
||||||
|
layout,
|
||||||
|
},
|
||||||
|
};
|
||||||
@ -0,0 +1,50 @@
|
|||||||
|
import {
|
||||||
|
BuilderComponentPlugin,
|
||||||
|
BuilderComponentPluginFactory,
|
||||||
|
ChunkType,
|
||||||
|
FileType,
|
||||||
|
ICodeStruct,
|
||||||
|
} from '../../../../../types';
|
||||||
|
import { COMMON_CHUNK_NAME } from '../../../../../const/generator';
|
||||||
|
|
||||||
|
export interface AppConfigPluginConfig {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function getContent() {
|
||||||
|
return `import { defineAppConfig } from 'ice';
|
||||||
|
|
||||||
|
// App config, see https://v3.ice.work/docs/guide/basic/app
|
||||||
|
export default defineAppConfig(() => ({
|
||||||
|
// Set your configs here.
|
||||||
|
app: {
|
||||||
|
rootId: 'App',
|
||||||
|
},
|
||||||
|
router: {
|
||||||
|
type: 'browser',
|
||||||
|
basename: '/',
|
||||||
|
},
|
||||||
|
}));`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const pluginFactory: BuilderComponentPluginFactory<AppConfigPluginConfig> = () => {
|
||||||
|
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||||
|
const next: ICodeStruct = {
|
||||||
|
...pre,
|
||||||
|
};
|
||||||
|
|
||||||
|
next.chunks.push({
|
||||||
|
type: ChunkType.STRING,
|
||||||
|
fileType: FileType.TS,
|
||||||
|
name: COMMON_CHUNK_NAME.FileMainContent,
|
||||||
|
content: getContent(),
|
||||||
|
linkAfter: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
return next;
|
||||||
|
};
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default pluginFactory;
|
||||||
@ -0,0 +1,165 @@
|
|||||||
|
import {
|
||||||
|
BuilderComponentPlugin,
|
||||||
|
BuilderComponentPluginFactory,
|
||||||
|
ChunkType,
|
||||||
|
FileType,
|
||||||
|
ICodeStruct,
|
||||||
|
} from '../../../../../types';
|
||||||
|
import { COMMON_CHUNK_NAME } from '../../../../../const/generator';
|
||||||
|
import { format } from '../../../../../utils/format';
|
||||||
|
import { getThemeInfo } from '../../../../../utils/theme';
|
||||||
|
|
||||||
|
export interface BuildConfigPluginConfig {
|
||||||
|
|
||||||
|
/** 包名 */
|
||||||
|
themePackage?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getContent(cfg?: BuildConfigPluginConfig, routesContent?: string) {
|
||||||
|
return `
|
||||||
|
import { join } from 'path';
|
||||||
|
import { defineConfig } from '@ice/app';
|
||||||
|
import _ from 'lodash';
|
||||||
|
import fusion from '@ice/plugin-fusion';
|
||||||
|
import locales from '@ice/plugin-moment-locales';
|
||||||
|
import type { Plugin } from '@ice/app/esm/types';
|
||||||
|
|
||||||
|
interface PluginOptions {
|
||||||
|
id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const plugin: Plugin<PluginOptions> = (options) => ({
|
||||||
|
// name 可选,插件名称
|
||||||
|
name: 'plugin-name',
|
||||||
|
// setup 必选,用于定制工程构建配置
|
||||||
|
setup: ({ onGetConfig, modifyUserConfig }) => {
|
||||||
|
modifyUserConfig('codeSplitting', 'page');
|
||||||
|
|
||||||
|
onGetConfig((config) => {
|
||||||
|
config.entry = {
|
||||||
|
web: join(process.cwd(), '.ice/entry.client.tsx'),
|
||||||
|
};
|
||||||
|
|
||||||
|
config.cssFilename = '[name].css';
|
||||||
|
|
||||||
|
config.configureWebpack = config.configureWebpack || [];
|
||||||
|
config.configureWebpack?.push((webpackConfig) => {
|
||||||
|
if (webpackConfig.output) {
|
||||||
|
webpackConfig.output.filename = '[name].js';
|
||||||
|
webpackConfig.output.chunkFilename = '[name].js';
|
||||||
|
}
|
||||||
|
return webpackConfig;
|
||||||
|
});
|
||||||
|
|
||||||
|
config.swcOptions = _.merge(config.swcOptions, {
|
||||||
|
compilationConfig: {
|
||||||
|
jsc: {
|
||||||
|
transform: {
|
||||||
|
react: {
|
||||||
|
runtime: 'classic',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 解决 webpack publicPath 问题
|
||||||
|
config.transforms = config.transforms || [];
|
||||||
|
config.transforms.push((source: string, id: string) => {
|
||||||
|
if (id.includes('.ice/entry.client.tsx')) {
|
||||||
|
let code = \`
|
||||||
|
if (!__webpack_public_path__?.startsWith('http') && document.currentScript) {
|
||||||
|
// @ts-ignore
|
||||||
|
__webpack_public_path__ = document.currentScript.src.replace(/^(.*\\\\/)[^/]+$/, '$1');
|
||||||
|
window.__ICE_ASSETS_MANIFEST__ = window.__ICE_ASSETS_MANIFEST__ || {};
|
||||||
|
window.__ICE_ASSETS_MANIFEST__.publicPath = __webpack_public_path__;
|
||||||
|
}
|
||||||
|
\`;
|
||||||
|
code += source;
|
||||||
|
return { code };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// The project config, see https://v3.ice.work/docs/guide/basic/config
|
||||||
|
const minify = process.env.NODE_ENV === 'production' ? 'swc' : false;
|
||||||
|
export default defineConfig(() => ({
|
||||||
|
ssr: false,
|
||||||
|
ssg: false,
|
||||||
|
minify,
|
||||||
|
${routesContent}
|
||||||
|
externals: {
|
||||||
|
react: 'React',
|
||||||
|
'react-dom': 'ReactDOM',
|
||||||
|
'react-dom/client': 'ReactDOM',
|
||||||
|
'@alifd/next': 'Next',
|
||||||
|
lodash: 'var window._',
|
||||||
|
'@alilc/lowcode-engine': 'var window.AliLowCodeEngine',
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
fusion(${cfg?.themePackage ? `{
|
||||||
|
importStyle: 'sass',
|
||||||
|
themePackage: '${getThemeInfo(cfg.themePackage).name}',
|
||||||
|
}` : `{
|
||||||
|
importStyle: true,
|
||||||
|
}`}),
|
||||||
|
locales(),
|
||||||
|
plugin(),
|
||||||
|
]
|
||||||
|
}));
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRoutesContent(navData: any, needShell = true) {
|
||||||
|
const routes = [
|
||||||
|
'routes: {',
|
||||||
|
' defineRoutes: route => {',
|
||||||
|
];
|
||||||
|
function _getRoutes(nav: any, _routes: string[] = []) {
|
||||||
|
const { slug, children } = nav;
|
||||||
|
if (children && children.length > 0) {
|
||||||
|
children.forEach((_nav: any) => _getRoutes(_nav, _routes));
|
||||||
|
} else if (slug) {
|
||||||
|
_routes.push(`route('/${slug}', '${slug}/index.jsx');`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (needShell) {
|
||||||
|
routes.push(" route('/', 'layout.jsx', () => {");
|
||||||
|
}
|
||||||
|
navData?.forEach((nav: any) => {
|
||||||
|
_getRoutes(nav, routes);
|
||||||
|
});
|
||||||
|
if (needShell) {
|
||||||
|
routes.push(' });');
|
||||||
|
}
|
||||||
|
routes.push(' }'); // end of defineRoutes
|
||||||
|
routes.push(' },'); // end of routes
|
||||||
|
return routes.join('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
const pluginFactory: BuilderComponentPluginFactory<BuildConfigPluginConfig> = (cfg?) => {
|
||||||
|
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||||
|
const next: ICodeStruct = {
|
||||||
|
...pre,
|
||||||
|
};
|
||||||
|
|
||||||
|
const { navConfig } = next.contextData;
|
||||||
|
const routesContent = navConfig?.data ? getRoutesContent(navConfig.data, true) : '';
|
||||||
|
|
||||||
|
next.chunks.push({
|
||||||
|
type: ChunkType.STRING,
|
||||||
|
fileType: FileType.MTS,
|
||||||
|
name: COMMON_CHUNK_NAME.FileMainContent,
|
||||||
|
content: format(getContent(cfg, routesContent)),
|
||||||
|
linkAfter: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
return next;
|
||||||
|
};
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default pluginFactory;
|
||||||
@ -0,0 +1,56 @@
|
|||||||
|
import { COMMON_CHUNK_NAME } from '../../../../../const/generator';
|
||||||
|
|
||||||
|
import {
|
||||||
|
BuilderComponentPlugin,
|
||||||
|
BuilderComponentPluginFactory,
|
||||||
|
ChunkType,
|
||||||
|
FileType,
|
||||||
|
ICodeStruct,
|
||||||
|
IProjectInfo,
|
||||||
|
} from '../../../../../types';
|
||||||
|
|
||||||
|
const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
||||||
|
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||||
|
const next: ICodeStruct = {
|
||||||
|
...pre,
|
||||||
|
};
|
||||||
|
|
||||||
|
const ir = next.ir as IProjectInfo;
|
||||||
|
|
||||||
|
next.chunks.push({
|
||||||
|
type: ChunkType.STRING,
|
||||||
|
fileType: FileType.SCSS,
|
||||||
|
name: COMMON_CHUNK_NAME.StyleDepsImport,
|
||||||
|
content: `
|
||||||
|
// 引入默认全局样式
|
||||||
|
@import '@alifd/next/reset.scss';
|
||||||
|
`,
|
||||||
|
linkAfter: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
next.chunks.push({
|
||||||
|
type: ChunkType.STRING,
|
||||||
|
fileType: FileType.SCSS,
|
||||||
|
name: COMMON_CHUNK_NAME.StyleCssContent,
|
||||||
|
content: `
|
||||||
|
body {
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
linkAfter: [COMMON_CHUNK_NAME.StyleDepsImport],
|
||||||
|
});
|
||||||
|
|
||||||
|
next.chunks.push({
|
||||||
|
type: ChunkType.STRING,
|
||||||
|
fileType: FileType.SCSS,
|
||||||
|
name: COMMON_CHUNK_NAME.StyleCssContent,
|
||||||
|
content: ir.css || '',
|
||||||
|
linkAfter: [COMMON_CHUNK_NAME.StyleDepsImport],
|
||||||
|
});
|
||||||
|
|
||||||
|
return next;
|
||||||
|
};
|
||||||
|
return plugin;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default pluginFactory;
|
||||||
@ -0,0 +1,41 @@
|
|||||||
|
import {
|
||||||
|
BuilderComponentPlugin,
|
||||||
|
BuilderComponentPluginFactory,
|
||||||
|
ChunkType,
|
||||||
|
FileType,
|
||||||
|
ICodeStruct,
|
||||||
|
} from '../../../../../types';
|
||||||
|
import { COMMON_CHUNK_NAME } from '../../../../../const/generator';
|
||||||
|
|
||||||
|
const pluginFactory: BuilderComponentPluginFactory<unknown> = () => {
|
||||||
|
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||||
|
const next: ICodeStruct = {
|
||||||
|
...pre,
|
||||||
|
};
|
||||||
|
|
||||||
|
next.chunks.push({
|
||||||
|
type: ChunkType.STRING,
|
||||||
|
fileType: FileType.JSX,
|
||||||
|
name: COMMON_CHUNK_NAME.FileMainContent,
|
||||||
|
content: `
|
||||||
|
import { Outlet } from 'ice';
|
||||||
|
import BasicLayout from '@/layouts/BasicLayout';
|
||||||
|
|
||||||
|
export default function Layout() {
|
||||||
|
return (
|
||||||
|
<BasicLayout>
|
||||||
|
<Outlet />
|
||||||
|
</BasicLayout>
|
||||||
|
);;
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
linkAfter: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
return next;
|
||||||
|
};
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default pluginFactory;
|
||||||
@ -0,0 +1,119 @@
|
|||||||
|
import { PackageJSON } from '@alilc/lowcode-types';
|
||||||
|
|
||||||
|
import { COMMON_CHUNK_NAME } from '../../../../../const/generator';
|
||||||
|
|
||||||
|
import {
|
||||||
|
BuilderComponentPlugin,
|
||||||
|
BuilderComponentPluginFactory,
|
||||||
|
ChunkType,
|
||||||
|
FileType,
|
||||||
|
ICodeStruct,
|
||||||
|
IProjectInfo,
|
||||||
|
} from '../../../../../types';
|
||||||
|
import { buildDataSourceDependencies } from '../../../../../utils/dataSource';
|
||||||
|
|
||||||
|
interface IIceJs3PackageJSON extends PackageJSON {
|
||||||
|
originTemplate: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type IceJs3PackageJsonPluginConfig = {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据源配置
|
||||||
|
*/
|
||||||
|
datasourceConfig?: {
|
||||||
|
|
||||||
|
/** 数据源引擎的版本 */
|
||||||
|
engineVersion?: string;
|
||||||
|
|
||||||
|
/** 数据源引擎的包名 */
|
||||||
|
enginePackage?: string;
|
||||||
|
|
||||||
|
/** 数据源 handlers 的版本 */
|
||||||
|
handlersVersion?: {
|
||||||
|
[key: string]: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 数据源 handlers 的包名 */
|
||||||
|
handlersPackages?: {
|
||||||
|
[key: string]: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/** 包名 */
|
||||||
|
packageName?: string;
|
||||||
|
|
||||||
|
/** 版本 */
|
||||||
|
packageVersion?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const pluginFactory: BuilderComponentPluginFactory<IceJs3PackageJsonPluginConfig> = (cfg) => {
|
||||||
|
const plugin: BuilderComponentPlugin = async (pre: ICodeStruct) => {
|
||||||
|
const next: ICodeStruct = {
|
||||||
|
...pre,
|
||||||
|
};
|
||||||
|
|
||||||
|
const ir = next.ir as IProjectInfo;
|
||||||
|
|
||||||
|
const packageJson: IIceJs3PackageJSON = {
|
||||||
|
name: cfg?.packageName || 'icejs3-demo-app',
|
||||||
|
version: cfg?.packageVersion || '0.1.5',
|
||||||
|
description: 'icejs 3 轻量级模板,使用 JavaScript,仅包含基础的 Layout。',
|
||||||
|
dependencies: {
|
||||||
|
moment: '^2.24.0',
|
||||||
|
react: '^18.2.0',
|
||||||
|
'react-dom': '^18.2.0',
|
||||||
|
'react-router': '^6.9.0',
|
||||||
|
'react-router-dom': '^6.9.0',
|
||||||
|
'intl-messageformat': '^9.3.6',
|
||||||
|
'@alifd/next': '1.26.15',
|
||||||
|
'@ice/runtime': '^1.0.0',
|
||||||
|
// 数据源相关的依赖:
|
||||||
|
...buildDataSourceDependencies(ir, cfg?.datasourceConfig),
|
||||||
|
},
|
||||||
|
devDependencies: {
|
||||||
|
'@ice/app': '^3.0.0',
|
||||||
|
'@types/react': '^18.0.0',
|
||||||
|
'@types/react-dom': '^18.0.0',
|
||||||
|
'@types/node': '^18.11.17',
|
||||||
|
'@ice/plugin-fusion': '^1.0.1',
|
||||||
|
'@ice/plugin-moment-locales': '^1.0.0',
|
||||||
|
eslint: '^6.0.1',
|
||||||
|
stylelint: '^13.2.0',
|
||||||
|
},
|
||||||
|
scripts: {
|
||||||
|
start: 'ice start',
|
||||||
|
build: 'ice build',
|
||||||
|
lint: 'npm run eslint && npm run stylelint',
|
||||||
|
eslint: 'eslint --cache --ext .js,.jsx ./',
|
||||||
|
stylelint: 'stylelint ./**/*.scss',
|
||||||
|
},
|
||||||
|
engines: {
|
||||||
|
node: '>=14.0.0',
|
||||||
|
},
|
||||||
|
repository: {
|
||||||
|
type: 'git',
|
||||||
|
url: 'http://gitlab.xxx.com/msd/leak-scan/tree/master',
|
||||||
|
},
|
||||||
|
private: true,
|
||||||
|
originTemplate: '@alifd/scaffold-lite-js',
|
||||||
|
};
|
||||||
|
|
||||||
|
ir.packages.forEach((packageInfo) => {
|
||||||
|
packageJson.dependencies[packageInfo.package] = packageInfo.version;
|
||||||
|
});
|
||||||
|
|
||||||
|
next.chunks.push({
|
||||||
|
type: ChunkType.JSON,
|
||||||
|
fileType: FileType.JSON,
|
||||||
|
name: COMMON_CHUNK_NAME.FileMainContent,
|
||||||
|
content: packageJson,
|
||||||
|
linkAfter: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
return next;
|
||||||
|
};
|
||||||
|
return plugin;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default pluginFactory;
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
import { ResultFile } from '@alilc/lowcode-types';
|
||||||
|
import { createResultFile } from '../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
|
export default function getFile(): [string[], ResultFile] {
|
||||||
|
const file = createResultFile(
|
||||||
|
'README',
|
||||||
|
'md',
|
||||||
|
'This project is generated by lowcode-code-generator & lowcode-solution-icejs3.',
|
||||||
|
);
|
||||||
|
|
||||||
|
return [[], file];
|
||||||
|
}
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
import { ResultFile } from '@alilc/lowcode-types';
|
||||||
|
import { createResultFile } from '../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
|
export default function getFile(): [string[], ResultFile] {
|
||||||
|
const file = createResultFile(
|
||||||
|
'.browserslistrc',
|
||||||
|
'',
|
||||||
|
`defaults
|
||||||
|
ios_saf 9
|
||||||
|
`,
|
||||||
|
);
|
||||||
|
|
||||||
|
return [[], file];
|
||||||
|
}
|
||||||
@ -0,0 +1,41 @@
|
|||||||
|
import { ResultFile } from '@alilc/lowcode-types';
|
||||||
|
import { createResultFile } from '../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
|
/* eslint-disable max-len */
|
||||||
|
export default function getFile(): [string[], ResultFile] {
|
||||||
|
const file = createResultFile(
|
||||||
|
'document',
|
||||||
|
'tsx',
|
||||||
|
`import React from 'react';
|
||||||
|
import { Meta, Title, Links, Main, Scripts } from 'ice';
|
||||||
|
|
||||||
|
export default function Document() {
|
||||||
|
return (
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charSet="utf-8" />
|
||||||
|
<meta name="description" content="ice.js 3 lite scaffold" />
|
||||||
|
<link rel="icon" href="/favicon.ico" />
|
||||||
|
<link rel="stylesheet" href="//alifd.alicdn.com/npm/@alifd/next/1.21.16/next.min.css" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
|
||||||
|
<Meta />
|
||||||
|
<Title />
|
||||||
|
<Links />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<Main />
|
||||||
|
<script crossOrigin="anonymous" src="//g.alicdn.com/code/lib/react/18.2.0/umd/react.development.js" />
|
||||||
|
<script crossOrigin="anonymous" src="//g.alicdn.com/code/lib/react-dom/18.2.0/umd/react-dom.development.js" />
|
||||||
|
<script crossOrigin="anonymous" src="//g.alicdn.com/code/lib/??react-router/6.9.0/react-router.production.min.js,react-router-dom/6.9.0/react-router-dom.production.min.js" />
|
||||||
|
<script crossOrigin="anonymous" src="//alifd.alicdn.com/npm/@alifd/next/1.26.15/next.min.js" />
|
||||||
|
<script crossOrigin="anonymous" src="//g.alicdn.com/code/lib/prop-types/15.7.2/prop-types.js" />
|
||||||
|
<script crossOrigin="anonymous" src="//g.alicdn.com/platform/c/??lodash/4.6.1/lodash.min.js,immutable/3.7.6/dist/immutable.min.js" />
|
||||||
|
<Scripts />
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
);
|
||||||
|
}`,
|
||||||
|
);
|
||||||
|
|
||||||
|
return [['src'], file];
|
||||||
|
}
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
import { ResultFile } from '@alilc/lowcode-types';
|
||||||
|
import { createResultFile } from '../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
|
export default function getFile(): [string[], ResultFile] {
|
||||||
|
const file = createResultFile(
|
||||||
|
'.gitignore',
|
||||||
|
'',
|
||||||
|
`
|
||||||
|
# See https://help.github.com/ignore-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# production
|
||||||
|
build/
|
||||||
|
dist/
|
||||||
|
tmp/
|
||||||
|
lib/
|
||||||
|
|
||||||
|
# misc
|
||||||
|
.idea/
|
||||||
|
.happypack
|
||||||
|
.DS_Store
|
||||||
|
*.swp
|
||||||
|
*.dia~
|
||||||
|
.ice
|
||||||
|
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
index.module.scss.d.ts
|
||||||
|
`,
|
||||||
|
);
|
||||||
|
|
||||||
|
return [[], file];
|
||||||
|
}
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
import { ResultFile } from '@alilc/lowcode-types';
|
||||||
|
import { createResultFile } from '../../../../../../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
|
export default function getFile(): [string[], ResultFile] {
|
||||||
|
const file = createResultFile(
|
||||||
|
'index',
|
||||||
|
'jsx',
|
||||||
|
`
|
||||||
|
import React from 'react';
|
||||||
|
import styles from './index.module.scss';
|
||||||
|
|
||||||
|
export default function Footer() {
|
||||||
|
return (
|
||||||
|
<p className={styles.footer}>
|
||||||
|
<span className={styles.logo}>Alibaba Fusion</span>
|
||||||
|
<br />
|
||||||
|
<span className={styles.copyright}>© 2019-现在 Alibaba Fusion & ICE</span>
|
||||||
|
</p>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
);
|
||||||
|
|
||||||
|
return [['src', 'layouts', 'BasicLayout', 'components', 'Footer'], file];
|
||||||
|
}
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
import { ResultFile } from '@alilc/lowcode-types';
|
||||||
|
import { createResultFile } from '../../../../../../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
|
export default function getFile(): [string[], ResultFile] {
|
||||||
|
const file = createResultFile(
|
||||||
|
'index',
|
||||||
|
'module.scss',
|
||||||
|
`
|
||||||
|
.footer {
|
||||||
|
line-height: 20px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
);
|
||||||
|
|
||||||
|
return [['src', 'layouts', 'BasicLayout', 'components', 'Footer'], file];
|
||||||
|
}
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
import { ResultFile } from '@alilc/lowcode-types';
|
||||||
|
import { createResultFile } from '../../../../../../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
|
export default function getFile(): [string[], ResultFile] {
|
||||||
|
const file = createResultFile(
|
||||||
|
'index',
|
||||||
|
'jsx',
|
||||||
|
`
|
||||||
|
import React from 'react';
|
||||||
|
import { Link } from 'ice';
|
||||||
|
import styles from './index.module.scss';
|
||||||
|
|
||||||
|
export default function Logo({ image, text, url }) {
|
||||||
|
return (
|
||||||
|
<div className="logo">
|
||||||
|
<Link to={url || '/'} className={styles.logo}>
|
||||||
|
{image && <img src={image} alt="logo" />}
|
||||||
|
<span>{text}</span>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
);
|
||||||
|
|
||||||
|
return [['src', 'layouts', 'BasicLayout', 'components', 'Logo'], file];
|
||||||
|
}
|
||||||
@ -0,0 +1,31 @@
|
|||||||
|
import { ResultFile } from '@alilc/lowcode-types';
|
||||||
|
import { createResultFile } from '../../../../../../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
|
export default function getFile(): [string[], ResultFile] {
|
||||||
|
const file = createResultFile(
|
||||||
|
'index',
|
||||||
|
'module.scss',
|
||||||
|
`
|
||||||
|
.logo{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
color: $color-text1-1;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 22px;
|
||||||
|
|
||||||
|
&:visited, &:link {
|
||||||
|
color: $color-text1-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
height: 24px;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
);
|
||||||
|
|
||||||
|
return [['src', 'layouts', 'BasicLayout', 'components', 'Logo'], file];
|
||||||
|
}
|
||||||
@ -0,0 +1,79 @@
|
|||||||
|
import { ResultFile } from '@alilc/lowcode-types';
|
||||||
|
import { createResultFile } from '../../../../../../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
|
export default function getFile(): [string[], ResultFile] {
|
||||||
|
const file = createResultFile(
|
||||||
|
'index',
|
||||||
|
'jsx',
|
||||||
|
`import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { Link, useLocation } from 'ice';
|
||||||
|
import { Nav } from '@alifd/next';
|
||||||
|
import { asideMenuConfig } from '../../menuConfig';
|
||||||
|
|
||||||
|
const { SubNav } = Nav;
|
||||||
|
const NavItem = Nav.Item;
|
||||||
|
|
||||||
|
function getNavMenuItems(menusData) {
|
||||||
|
if (!menusData) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return menusData
|
||||||
|
.filter(item => item.name && !item.hideInMenu)
|
||||||
|
.map((item, index) => getSubMenuOrItem(item, index));
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSubMenuOrItem(item, index) {
|
||||||
|
if (item.children && item.children.some(child => child.name)) {
|
||||||
|
const childrenItems = getNavMenuItems(item.children);
|
||||||
|
|
||||||
|
if (childrenItems && childrenItems.length > 0) {
|
||||||
|
const subNav = (
|
||||||
|
<SubNav key={index} icon={item.icon} label={item.name}>
|
||||||
|
{childrenItems}
|
||||||
|
</SubNav>
|
||||||
|
);
|
||||||
|
return subNav;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const navItem = (
|
||||||
|
<NavItem key={item.path} icon={item.icon}>
|
||||||
|
<Link to={item.path}>{item.name}</Link>
|
||||||
|
</NavItem>
|
||||||
|
);
|
||||||
|
return navItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Navigation = (props, context) => {
|
||||||
|
const location = useLocation();
|
||||||
|
const { pathname } = location;
|
||||||
|
const { isCollapse } = context;
|
||||||
|
return (
|
||||||
|
<Nav
|
||||||
|
type="primary"
|
||||||
|
selectedKeys={[pathname]}
|
||||||
|
defaultSelectedKeys={[pathname]}
|
||||||
|
embeddable
|
||||||
|
openMode="single"
|
||||||
|
iconOnly={isCollapse}
|
||||||
|
hasArrow={false}
|
||||||
|
mode={isCollapse ? 'popup' : 'inline'}
|
||||||
|
>
|
||||||
|
{getNavMenuItems(asideMenuConfig)}
|
||||||
|
</Nav>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
Navigation.contextTypes = {
|
||||||
|
isCollapse: PropTypes.bool,
|
||||||
|
};
|
||||||
|
export default Navigation;
|
||||||
|
`,
|
||||||
|
);
|
||||||
|
|
||||||
|
return [['src', 'layouts', 'BasicLayout', 'components', 'PageNav'], file];
|
||||||
|
}
|
||||||
@ -0,0 +1,92 @@
|
|||||||
|
import { ResultFile } from '@alilc/lowcode-types';
|
||||||
|
import { createResultFile } from '../../../../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
|
export default function getFile(): [string[], ResultFile] {
|
||||||
|
const file = createResultFile(
|
||||||
|
'index',
|
||||||
|
'jsx',
|
||||||
|
`
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
import { Shell, ConfigProvider } from '@alifd/next';
|
||||||
|
import PageNav from './components/PageNav';
|
||||||
|
import Logo from './components/Logo';
|
||||||
|
import Footer from './components/Footer';
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
const throttle = function(type, name, obj = window) {
|
||||||
|
let running = false;
|
||||||
|
|
||||||
|
const func = () => {
|
||||||
|
if (running) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
running = true;
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
obj.dispatchEvent(new CustomEvent(name));
|
||||||
|
running = false;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
obj.addEventListener(type, func);
|
||||||
|
};
|
||||||
|
|
||||||
|
throttle('resize', 'optimizedResize');
|
||||||
|
})();
|
||||||
|
|
||||||
|
export default function BasicLayout({ children }) {
|
||||||
|
const getDevice = width => {
|
||||||
|
const isPhone =
|
||||||
|
typeof navigator !== 'undefined' && navigator && navigator.userAgent.match(/phone/gi);
|
||||||
|
|
||||||
|
if (width < 680 || isPhone) {
|
||||||
|
return 'phone';
|
||||||
|
}
|
||||||
|
if (width < 1280 && width > 680) {
|
||||||
|
return 'tablet';
|
||||||
|
}
|
||||||
|
return 'desktop';
|
||||||
|
};
|
||||||
|
|
||||||
|
const [device, setDevice] = useState(getDevice(NaN));
|
||||||
|
window.addEventListener('optimizedResize', e => {
|
||||||
|
setDevice(getDevice(e && e.target && e.target.innerWidth));
|
||||||
|
});
|
||||||
|
return (
|
||||||
|
<ConfigProvider device={device}>
|
||||||
|
<Shell
|
||||||
|
type="dark"
|
||||||
|
style={{
|
||||||
|
minHeight: '100vh',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Shell.Branding>
|
||||||
|
<Logo
|
||||||
|
image="https://img.alicdn.com/tfs/TB1.ZBecq67gK0jSZFHXXa9jVXa-904-826.png"
|
||||||
|
text="Logo"
|
||||||
|
/>
|
||||||
|
</Shell.Branding>
|
||||||
|
<Shell.Navigation
|
||||||
|
direction="hoz"
|
||||||
|
style={{
|
||||||
|
marginRight: 10,
|
||||||
|
}}
|
||||||
|
></Shell.Navigation>
|
||||||
|
<Shell.Action></Shell.Action>
|
||||||
|
<Shell.Navigation>
|
||||||
|
<PageNav />
|
||||||
|
</Shell.Navigation>
|
||||||
|
|
||||||
|
<Shell.Content>{children}</Shell.Content>
|
||||||
|
<Shell.Footer>
|
||||||
|
<Footer />
|
||||||
|
</Shell.Footer>
|
||||||
|
</Shell>
|
||||||
|
</ConfigProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
);
|
||||||
|
|
||||||
|
return [['src', 'layouts', 'BasicLayout'], file];
|
||||||
|
}
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
import { ResultFile } from '@alilc/lowcode-types';
|
||||||
|
import { createResultFile } from '../../../../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
|
export default function getFile(): [string[], ResultFile] {
|
||||||
|
const file = createResultFile(
|
||||||
|
'menuConfig',
|
||||||
|
'js',
|
||||||
|
`
|
||||||
|
const headerMenuConfig = [];
|
||||||
|
const asideMenuConfig = [
|
||||||
|
{
|
||||||
|
name: 'Dashboard',
|
||||||
|
path: '/',
|
||||||
|
icon: 'smile',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
export { headerMenuConfig, asideMenuConfig };
|
||||||
|
`,
|
||||||
|
);
|
||||||
|
|
||||||
|
return [['src', 'layouts', 'BasicLayout'], file];
|
||||||
|
}
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
import { ResultFile } from '@alilc/lowcode-types';
|
||||||
|
import { createResultFile } from '../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
|
export default function getFile(): [string[], ResultFile] {
|
||||||
|
const file = createResultFile(
|
||||||
|
'tsconfig',
|
||||||
|
'json',
|
||||||
|
`
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"baseUrl": "./",
|
||||||
|
"module": "ESNext",
|
||||||
|
"target": "ESNext",
|
||||||
|
"lib": ["DOM", "ESNext", "DOM.Iterable"],
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"noImplicitReturns": true,
|
||||||
|
"noImplicitThis": true,
|
||||||
|
"noImplicitAny": false,
|
||||||
|
"importHelpers": true,
|
||||||
|
"strictNullChecks": true,
|
||||||
|
"suppressImplicitAnyIndexErrors": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["./src/*"],
|
||||||
|
"ice": [".ice"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"include": ["src", ".ice"],
|
||||||
|
"exclude": ["build"]
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
);
|
||||||
|
|
||||||
|
return [[], file];
|
||||||
|
}
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
import { ResultFile } from '@alilc/lowcode-types';
|
||||||
|
import { createResultFile } from '../../../../../../utils/resultHelper';
|
||||||
|
|
||||||
|
export default function getFile(): [string[], ResultFile] {
|
||||||
|
const file = createResultFile(
|
||||||
|
'typings.d',
|
||||||
|
'ts',
|
||||||
|
`/// <reference types="@ice/app/types" />
|
||||||
|
|
||||||
|
export {};
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
g_config: Record<string, any>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
);
|
||||||
|
|
||||||
|
return [['src'], file];
|
||||||
|
}
|
||||||
@ -0,0 +1,57 @@
|
|||||||
|
import { IProjectTemplate } from '../../../../../types';
|
||||||
|
import { generateStaticFiles } from './static-files';
|
||||||
|
|
||||||
|
const icejs3Template: IProjectTemplate = {
|
||||||
|
slots: {
|
||||||
|
components: {
|
||||||
|
path: ['src', 'components'],
|
||||||
|
fileName: 'index',
|
||||||
|
},
|
||||||
|
pages: {
|
||||||
|
path: ['src', 'pages'],
|
||||||
|
fileName: 'index',
|
||||||
|
},
|
||||||
|
entry: {
|
||||||
|
path: ['src'],
|
||||||
|
fileName: 'app',
|
||||||
|
},
|
||||||
|
constants: {
|
||||||
|
path: ['src'],
|
||||||
|
fileName: 'constants',
|
||||||
|
},
|
||||||
|
utils: {
|
||||||
|
path: ['src'],
|
||||||
|
fileName: 'utils',
|
||||||
|
},
|
||||||
|
i18n: {
|
||||||
|
path: ['src'],
|
||||||
|
fileName: 'i18n',
|
||||||
|
},
|
||||||
|
globalStyle: {
|
||||||
|
path: ['src'],
|
||||||
|
fileName: 'global',
|
||||||
|
},
|
||||||
|
packageJSON: {
|
||||||
|
path: [],
|
||||||
|
fileName: 'package',
|
||||||
|
},
|
||||||
|
appConfig: {
|
||||||
|
path: ['src'],
|
||||||
|
fileName: 'app',
|
||||||
|
},
|
||||||
|
buildConfig: {
|
||||||
|
path: [],
|
||||||
|
fileName: 'ice.config',
|
||||||
|
},
|
||||||
|
layout: {
|
||||||
|
path: ['src', 'pages'],
|
||||||
|
fileName: 'layout',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
generateTemplate() {
|
||||||
|
return generateStaticFiles();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default icejs3Template;
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
import { ResultDir } from '@alilc/lowcode-types';
|
||||||
|
import { createResultDir } from '../../../../../utils/resultHelper';
|
||||||
|
import { runFileGenerator } from '../../../../../utils/templateHelper';
|
||||||
|
|
||||||
|
import file1 from './files/gitignore';
|
||||||
|
import file2 from './files/README.md';
|
||||||
|
import file3 from './files/browserslistrc';
|
||||||
|
import file4 from './files/typings';
|
||||||
|
import file5 from './files/document';
|
||||||
|
import file6 from './files/src/layouts/BasicLayout/components/Footer/index.jsx';
|
||||||
|
import file7 from './files/src/layouts/BasicLayout/components/Footer/index.style';
|
||||||
|
import file8 from './files/src/layouts/BasicLayout/components/Logo/index.jsx';
|
||||||
|
import file9 from './files/src/layouts/BasicLayout/components/Logo/index.style';
|
||||||
|
import file10 from './files/src/layouts/BasicLayout/components/PageNav/index.jsx';
|
||||||
|
import file11 from './files/src/layouts/BasicLayout/index.jsx';
|
||||||
|
import file12 from './files/src/layouts/BasicLayout/menuConfig.js';
|
||||||
|
|
||||||
|
export function generateStaticFiles(root = createResultDir('.')): ResultDir {
|
||||||
|
runFileGenerator(root, file1);
|
||||||
|
runFileGenerator(root, file2);
|
||||||
|
runFileGenerator(root, file3);
|
||||||
|
runFileGenerator(root, file4);
|
||||||
|
runFileGenerator(root, file5);
|
||||||
|
runFileGenerator(root, file6);
|
||||||
|
runFileGenerator(root, file7);
|
||||||
|
runFileGenerator(root, file8);
|
||||||
|
runFileGenerator(root, file9);
|
||||||
|
runFileGenerator(root, file10);
|
||||||
|
runFileGenerator(root, file11);
|
||||||
|
runFileGenerator(root, file12);
|
||||||
|
|
||||||
|
return root;
|
||||||
|
}
|
||||||
109
modules/code-generator/src/solutions/icejs3.ts
Normal file
109
modules/code-generator/src/solutions/icejs3.ts
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
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 containerInjectConstants from '../plugins/component/react/containerInjectConstants';
|
||||||
|
import containerInjectI18n from '../plugins/component/react/containerInjectI18n';
|
||||||
|
import containerLifeCycle from '../plugins/component/react/containerLifeCycle';
|
||||||
|
import containerMethod from '../plugins/component/react/containerMethod';
|
||||||
|
import jsx from '../plugins/component/react/jsx';
|
||||||
|
import reactCommonDeps from '../plugins/component/react/reactCommonDeps';
|
||||||
|
import css from '../plugins/component/style/css';
|
||||||
|
import constants from '../plugins/project/constants';
|
||||||
|
import i18n from '../plugins/project/i18n';
|
||||||
|
import utils from '../plugins/project/utils';
|
||||||
|
|
||||||
|
import icejs3 from '../plugins/project/framework/icejs3';
|
||||||
|
|
||||||
|
import { prettier } from '../postprocessor';
|
||||||
|
|
||||||
|
export type IceJs3ProjectBuilderOptions = IProjectBuilderOptions;
|
||||||
|
|
||||||
|
export default function createIceJsProjectBuilder(
|
||||||
|
options?: IceJs3ProjectBuilderOptions,
|
||||||
|
): IProjectBuilder {
|
||||||
|
return createProjectBuilder({
|
||||||
|
inStrictMode: options?.inStrictMode,
|
||||||
|
extraContextData: { ...options },
|
||||||
|
template: icejs3.template,
|
||||||
|
plugins: {
|
||||||
|
components: [
|
||||||
|
reactCommonDeps(),
|
||||||
|
esmodule({
|
||||||
|
fileType: 'jsx',
|
||||||
|
}),
|
||||||
|
containerClass(),
|
||||||
|
containerInjectContext(),
|
||||||
|
containerInjectUtils(),
|
||||||
|
containerInjectDataSourceEngine(),
|
||||||
|
containerInjectI18n(),
|
||||||
|
containerInitState(),
|
||||||
|
containerLifeCycle(),
|
||||||
|
containerMethod(),
|
||||||
|
jsx({
|
||||||
|
nodeTypeMapping: {
|
||||||
|
Div: 'div',
|
||||||
|
Component: 'div',
|
||||||
|
Page: 'div',
|
||||||
|
Block: 'div',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
css(),
|
||||||
|
],
|
||||||
|
pages: [
|
||||||
|
reactCommonDeps(),
|
||||||
|
esmodule({
|
||||||
|
fileType: 'jsx',
|
||||||
|
}),
|
||||||
|
containerClass(),
|
||||||
|
containerInjectContext(),
|
||||||
|
containerInjectUtils(),
|
||||||
|
containerInjectDataSourceEngine(),
|
||||||
|
containerInjectI18n(),
|
||||||
|
containerInjectConstants(),
|
||||||
|
containerInitState(),
|
||||||
|
containerLifeCycle(),
|
||||||
|
containerMethod(),
|
||||||
|
jsx({
|
||||||
|
nodeTypeMapping: {
|
||||||
|
Div: 'div',
|
||||||
|
Component: 'div',
|
||||||
|
Page: 'div',
|
||||||
|
Block: 'div',
|
||||||
|
Box: 'div',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
css(),
|
||||||
|
],
|
||||||
|
constants: [constants()],
|
||||||
|
utils: [esmodule(), utils('react')],
|
||||||
|
i18n: [i18n()],
|
||||||
|
globalStyle: [icejs3.plugins.globalStyle()],
|
||||||
|
packageJSON: [icejs3.plugins.packageJSON()],
|
||||||
|
buildConfig: [icejs3.plugins.buildConfig()],
|
||||||
|
appConfig: [icejs3.plugins.appConfig()],
|
||||||
|
layout: [icejs3.plugins.layout()],
|
||||||
|
},
|
||||||
|
postProcessors: [prettier()],
|
||||||
|
customizeBuilderOptions: options?.customizeBuilderOptions,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export const plugins = {
|
||||||
|
containerClass,
|
||||||
|
containerInitState,
|
||||||
|
containerInjectContext,
|
||||||
|
containerInjectUtils,
|
||||||
|
containerInjectI18n,
|
||||||
|
containerInjectDataSourceEngine,
|
||||||
|
containerLifeCycle,
|
||||||
|
containerMethod,
|
||||||
|
jsx,
|
||||||
|
commonDeps: reactCommonDeps,
|
||||||
|
};
|
||||||
12
modules/code-generator/src/utils/format.ts
Normal file
12
modules/code-generator/src/utils/format.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import prettier from 'prettier';
|
||||||
|
import parserBabel from 'prettier/parser-babel';
|
||||||
|
|
||||||
|
export function format(content: string, options = {}) {
|
||||||
|
return prettier.format(content, {
|
||||||
|
parser: 'babel',
|
||||||
|
plugins: [parserBabel],
|
||||||
|
singleQuote: true,
|
||||||
|
jsxSingleQuote: false,
|
||||||
|
...options,
|
||||||
|
});
|
||||||
|
}
|
||||||
20
modules/code-generator/src/utils/theme.ts
Normal file
20
modules/code-generator/src/utils/theme.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
/**
|
||||||
|
* 获取主题信息
|
||||||
|
* @param theme theme 形如 @alife/theme-97 或者 @alife/theme-97@^1.0.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface ThemeInfo {
|
||||||
|
name: string;
|
||||||
|
version?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getThemeInfo(theme: string): ThemeInfo {
|
||||||
|
const sepIdx = theme.indexOf('@', 1);
|
||||||
|
if (sepIdx === -1) {
|
||||||
|
return { name: theme };
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
name: theme.slice(0, sepIdx),
|
||||||
|
version: theme.slice(sepIdx + 1),
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
defaults
|
||||||
|
ios_saf 9
|
||||||
|
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
# See https://help.github.com/ignore-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# production
|
||||||
|
build/
|
||||||
|
dist/
|
||||||
|
tmp/
|
||||||
|
lib/
|
||||||
|
|
||||||
|
# misc
|
||||||
|
.idea/
|
||||||
|
.happypack
|
||||||
|
.DS_Store
|
||||||
|
*.swp
|
||||||
|
*.dia~
|
||||||
|
.ice
|
||||||
|
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
index.module.scss.d.ts
|
||||||
|
|
||||||
@ -0,0 +1 @@
|
|||||||
|
This project is generated by lowcode-code-generator & lowcode-solution-icejs3.
|
||||||
@ -0,0 +1,90 @@
|
|||||||
|
import { join } from 'path';
|
||||||
|
import { defineConfig } from '@ice/app';
|
||||||
|
import _ from 'lodash';
|
||||||
|
import fusion from '@ice/plugin-fusion';
|
||||||
|
import locales from '@ice/plugin-moment-locales';
|
||||||
|
import type { Plugin } from '@ice/app/esm/types';
|
||||||
|
|
||||||
|
interface PluginOptions {
|
||||||
|
id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const plugin: Plugin<PluginOptions> = (options) => ({
|
||||||
|
// name 可选,插件名称
|
||||||
|
name: 'plugin-name',
|
||||||
|
// setup 必选,用于定制工程构建配置
|
||||||
|
setup: ({ onGetConfig, modifyUserConfig }) => {
|
||||||
|
modifyUserConfig('codeSplitting', 'page');
|
||||||
|
|
||||||
|
onGetConfig((config) => {
|
||||||
|
config.entry = {
|
||||||
|
web: join(process.cwd(), '.ice/entry.client.tsx'),
|
||||||
|
};
|
||||||
|
|
||||||
|
config.cssFilename = '[name].css';
|
||||||
|
|
||||||
|
config.configureWebpack = config.configureWebpack || [];
|
||||||
|
config.configureWebpack?.push((webpackConfig) => {
|
||||||
|
if (webpackConfig.output) {
|
||||||
|
webpackConfig.output.filename = '[name].js';
|
||||||
|
webpackConfig.output.chunkFilename = '[name].js';
|
||||||
|
}
|
||||||
|
return webpackConfig;
|
||||||
|
});
|
||||||
|
|
||||||
|
config.swcOptions = _.merge(config.swcOptions, {
|
||||||
|
compilationConfig: {
|
||||||
|
jsc: {
|
||||||
|
transform: {
|
||||||
|
react: {
|
||||||
|
runtime: 'classic',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// 解决 webpack publicPath 问题
|
||||||
|
config.transforms = config.transforms || [];
|
||||||
|
config.transforms.push((source: string, id: string) => {
|
||||||
|
if (id.includes('.ice/entry.client.tsx')) {
|
||||||
|
let code = `
|
||||||
|
if (!__webpack_public_path__?.startsWith('http') && document.currentScript) {
|
||||||
|
// @ts-ignore
|
||||||
|
__webpack_public_path__ = document.currentScript.src.replace(/^(.*\\/)[^/]+$/, '$1');
|
||||||
|
window.__ICE_ASSETS_MANIFEST__ = window.__ICE_ASSETS_MANIFEST__ || {};
|
||||||
|
window.__ICE_ASSETS_MANIFEST__.publicPath = __webpack_public_path__;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
code += source;
|
||||||
|
return { code };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// The project config, see https://v3.ice.work/docs/guide/basic/config
|
||||||
|
const minify = process.env.NODE_ENV === 'production' ? 'swc' : false;
|
||||||
|
export default defineConfig(() => ({
|
||||||
|
ssr: false,
|
||||||
|
ssg: false,
|
||||||
|
minify,
|
||||||
|
|
||||||
|
externals: {
|
||||||
|
react: 'React',
|
||||||
|
'react-dom': 'ReactDOM',
|
||||||
|
'react-dom/client': 'ReactDOM',
|
||||||
|
'@alifd/next': 'Next',
|
||||||
|
lodash: 'var window._',
|
||||||
|
'@alilc/lowcode-engine': 'var window.AliLowCodeEngine',
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
fusion({
|
||||||
|
importStyle: true,
|
||||||
|
}),
|
||||||
|
locales(),
|
||||||
|
plugin(),
|
||||||
|
],
|
||||||
|
}));
|
||||||
|
|
||||||
@ -0,0 +1,44 @@
|
|||||||
|
{
|
||||||
|
"name": "icejs3-demo-app",
|
||||||
|
"version": "0.1.5",
|
||||||
|
"description": "icejs 3 轻量级模板,使用 JavaScript,仅包含基础的 Layout。",
|
||||||
|
"dependencies": {
|
||||||
|
"moment": "^2.24.0",
|
||||||
|
"react": "^18.2.0",
|
||||||
|
"react-dom": "^18.2.0",
|
||||||
|
"react-router": "^6.9.0",
|
||||||
|
"react-router-dom": "^6.9.0",
|
||||||
|
"intl-messageformat": "^9.3.6",
|
||||||
|
"@alifd/next": "1.19.18",
|
||||||
|
"@ice/runtime": "^1.0.0",
|
||||||
|
"@alilc/lowcode-datasource-engine": "^1.0.0",
|
||||||
|
"@alilc/lowcode-datasource-url-params-handler": "^1.0.0",
|
||||||
|
"@alilc/lowcode-datasource-fetch-handler": "^1.0.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@ice/app": "^3.0.0",
|
||||||
|
"@types/react": "^18.0.0",
|
||||||
|
"@types/react-dom": "^18.0.0",
|
||||||
|
"@types/node": "^18.11.17",
|
||||||
|
"@ice/plugin-fusion": "^1.0.1",
|
||||||
|
"@ice/plugin-moment-locales": "^1.0.0",
|
||||||
|
"eslint": "^6.0.1",
|
||||||
|
"stylelint": "^13.2.0"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"start": "ice start",
|
||||||
|
"build": "ice build",
|
||||||
|
"lint": "npm run eslint && npm run stylelint",
|
||||||
|
"eslint": "eslint --cache --ext .js,.jsx ./",
|
||||||
|
"stylelint": "stylelint ./**/*.scss"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "http://gitlab.xxx.com/msd/leak-scan/tree/master"
|
||||||
|
},
|
||||||
|
"private": true,
|
||||||
|
"originTemplate": "@alifd/scaffold-lite-js"
|
||||||
|
}
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
import { defineAppConfig } from 'ice';
|
||||||
|
|
||||||
|
// App config, see https://v3.ice.work/docs/guide/basic/app
|
||||||
|
export default defineAppConfig(() => ({
|
||||||
|
// Set your configs here.
|
||||||
|
app: {
|
||||||
|
rootId: 'App',
|
||||||
|
},
|
||||||
|
router: {
|
||||||
|
type: 'browser',
|
||||||
|
basename: '/',
|
||||||
|
},
|
||||||
|
}));
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
const __$$constants = { ENV: 'prod', DOMAIN: 'xxx.xxx.com' };
|
||||||
|
|
||||||
|
export default __$$constants;
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Meta, Title, Links, Main, Scripts } from 'ice';
|
||||||
|
|
||||||
|
export default function Document() {
|
||||||
|
return (
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charSet="utf-8" />
|
||||||
|
<meta name="description" content="ice.js 3 lite scaffold" />
|
||||||
|
<link rel="icon" href="/favicon.ico" />
|
||||||
|
<link rel="stylesheet" href="//alifd.alicdn.com/npm/@alifd/next/1.21.16/next.min.css" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
|
||||||
|
<Meta />
|
||||||
|
<Title />
|
||||||
|
<Links />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<Main />
|
||||||
|
<script crossOrigin="anonymous" src="//g.alicdn.com/code/lib/react/18.2.0/umd/react.development.js" />
|
||||||
|
<script crossOrigin="anonymous" src="//g.alicdn.com/code/lib/react-dom/18.2.0/umd/react-dom.development.js" />
|
||||||
|
<script crossOrigin="anonymous" src="//g.alicdn.com/code/lib/??react-router/6.9.0/react-router.production.min.js,react-router-dom/6.9.0/react-router-dom.production.min.js" />
|
||||||
|
<script crossOrigin="anonymous" src="//alifd.alicdn.com/npm/@alifd/next/1.26.15/next.min.js" />
|
||||||
|
<script crossOrigin="anonymous" src="//g.alicdn.com/code/lib/prop-types/15.7.2/prop-types.js" />
|
||||||
|
<script crossOrigin="anonymous" src="//g.alicdn.com/platform/c/??lodash/4.6.1/lodash.min.js,immutable/3.7.6/dist/immutable.min.js" />
|
||||||
|
<Scripts />
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
// 引入默认全局样式
|
||||||
|
@import '@alifd/next/reset.scss';
|
||||||
|
|
||||||
|
body {
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
.table {
|
||||||
|
width: 100px;
|
||||||
|
}
|
||||||
@ -0,0 +1,77 @@
|
|||||||
|
const i18nConfig = {};
|
||||||
|
|
||||||
|
let locale =
|
||||||
|
typeof navigator === 'object' && typeof navigator.language === 'string'
|
||||||
|
? navigator.language
|
||||||
|
: 'zh-CN';
|
||||||
|
|
||||||
|
const getLocale = () => locale;
|
||||||
|
|
||||||
|
const setLocale = (target) => {
|
||||||
|
locale = target;
|
||||||
|
};
|
||||||
|
|
||||||
|
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 fallback === undefined ? `${id}` : fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 其次用项目级别的
|
||||||
|
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,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import styles from './index.module.scss';
|
||||||
|
|
||||||
|
export default function Footer() {
|
||||||
|
return (
|
||||||
|
<p className={styles.footer}>
|
||||||
|
<span className={styles.logo}>Alibaba Fusion</span>
|
||||||
|
<br />
|
||||||
|
<span className={styles.copyright}>© 2019-现在 Alibaba Fusion & ICE</span>
|
||||||
|
</p>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
.footer {
|
||||||
|
line-height: 20px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import { Link } from 'ice';
|
||||||
|
import styles from './index.module.scss';
|
||||||
|
|
||||||
|
export default function Logo({ image, text, url }) {
|
||||||
|
return (
|
||||||
|
<div className="logo">
|
||||||
|
<Link to={url || '/'} className={styles.logo}>
|
||||||
|
{image && <img src={image} alt="logo" />}
|
||||||
|
<span>{text}</span>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
|
||||||
|
.logo{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
color: $color-text1-1;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 22px;
|
||||||
|
|
||||||
|
&:visited, &:link {
|
||||||
|
color: $color-text1-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
height: 24px;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,68 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { Link, useLocation } from 'ice';
|
||||||
|
import { Nav } from '@alifd/next';
|
||||||
|
import { asideMenuConfig } from '../../menuConfig';
|
||||||
|
|
||||||
|
const { SubNav } = Nav;
|
||||||
|
const NavItem = Nav.Item;
|
||||||
|
|
||||||
|
function getNavMenuItems(menusData) {
|
||||||
|
if (!menusData) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return menusData
|
||||||
|
.filter(item => item.name && !item.hideInMenu)
|
||||||
|
.map((item, index) => getSubMenuOrItem(item, index));
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSubMenuOrItem(item, index) {
|
||||||
|
if (item.children && item.children.some(child => child.name)) {
|
||||||
|
const childrenItems = getNavMenuItems(item.children);
|
||||||
|
|
||||||
|
if (childrenItems && childrenItems.length > 0) {
|
||||||
|
const subNav = (
|
||||||
|
<SubNav key={index} icon={item.icon} label={item.name}>
|
||||||
|
{childrenItems}
|
||||||
|
</SubNav>
|
||||||
|
);
|
||||||
|
return subNav;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const navItem = (
|
||||||
|
<NavItem key={item.path} icon={item.icon}>
|
||||||
|
<Link to={item.path}>{item.name}</Link>
|
||||||
|
</NavItem>
|
||||||
|
);
|
||||||
|
return navItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Navigation = (props, context) => {
|
||||||
|
const location = useLocation();
|
||||||
|
const { pathname } = location;
|
||||||
|
const { isCollapse } = context;
|
||||||
|
return (
|
||||||
|
<Nav
|
||||||
|
type="primary"
|
||||||
|
selectedKeys={[pathname]}
|
||||||
|
defaultSelectedKeys={[pathname]}
|
||||||
|
embeddable
|
||||||
|
openMode="single"
|
||||||
|
iconOnly={isCollapse}
|
||||||
|
hasArrow={false}
|
||||||
|
mode={isCollapse ? 'popup' : 'inline'}
|
||||||
|
>
|
||||||
|
{getNavMenuItems(asideMenuConfig)}
|
||||||
|
</Nav>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
Navigation.contextTypes = {
|
||||||
|
isCollapse: PropTypes.bool,
|
||||||
|
};
|
||||||
|
export default Navigation;
|
||||||
|
|
||||||
@ -0,0 +1,81 @@
|
|||||||
|
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
import { Shell, ConfigProvider } from '@alifd/next';
|
||||||
|
import PageNav from './components/PageNav';
|
||||||
|
import Logo from './components/Logo';
|
||||||
|
import Footer from './components/Footer';
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
const throttle = function(type, name, obj = window) {
|
||||||
|
let running = false;
|
||||||
|
|
||||||
|
const func = () => {
|
||||||
|
if (running) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
running = true;
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
obj.dispatchEvent(new CustomEvent(name));
|
||||||
|
running = false;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
obj.addEventListener(type, func);
|
||||||
|
};
|
||||||
|
|
||||||
|
throttle('resize', 'optimizedResize');
|
||||||
|
})();
|
||||||
|
|
||||||
|
export default function BasicLayout({ children }) {
|
||||||
|
const getDevice = width => {
|
||||||
|
const isPhone =
|
||||||
|
typeof navigator !== 'undefined' && navigator && navigator.userAgent.match(/phone/gi);
|
||||||
|
|
||||||
|
if (width < 680 || isPhone) {
|
||||||
|
return 'phone';
|
||||||
|
}
|
||||||
|
if (width < 1280 && width > 680) {
|
||||||
|
return 'tablet';
|
||||||
|
}
|
||||||
|
return 'desktop';
|
||||||
|
};
|
||||||
|
|
||||||
|
const [device, setDevice] = useState(getDevice(NaN));
|
||||||
|
window.addEventListener('optimizedResize', e => {
|
||||||
|
setDevice(getDevice(e && e.target && e.target.innerWidth));
|
||||||
|
});
|
||||||
|
return (
|
||||||
|
<ConfigProvider device={device}>
|
||||||
|
<Shell
|
||||||
|
type="dark"
|
||||||
|
style={{
|
||||||
|
minHeight: '100vh',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Shell.Branding>
|
||||||
|
<Logo
|
||||||
|
image="https://img.alicdn.com/tfs/TB1.ZBecq67gK0jSZFHXXa9jVXa-904-826.png"
|
||||||
|
text="Logo"
|
||||||
|
/>
|
||||||
|
</Shell.Branding>
|
||||||
|
<Shell.Navigation
|
||||||
|
direction="hoz"
|
||||||
|
style={{
|
||||||
|
marginRight: 10,
|
||||||
|
}}
|
||||||
|
></Shell.Navigation>
|
||||||
|
<Shell.Action></Shell.Action>
|
||||||
|
<Shell.Navigation>
|
||||||
|
<PageNav />
|
||||||
|
</Shell.Navigation>
|
||||||
|
|
||||||
|
<Shell.Content>{children}</Shell.Content>
|
||||||
|
<Shell.Footer>
|
||||||
|
<Footer />
|
||||||
|
</Shell.Footer>
|
||||||
|
</Shell>
|
||||||
|
</ConfigProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
const headerMenuConfig = [];
|
||||||
|
const asideMenuConfig = [
|
||||||
|
{
|
||||||
|
name: 'Dashboard',
|
||||||
|
path: '/',
|
||||||
|
icon: 'smile',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
export { headerMenuConfig, asideMenuConfig };
|
||||||
|
|
||||||
@ -0,0 +1,195 @@
|
|||||||
|
// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。
|
||||||
|
// 例外:react 框架的导出名和各种组件名除外。
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { Form, Input, NumberPicker, Select, Button } from '@alifd/next';
|
||||||
|
|
||||||
|
import { createUrlParamsHandler as __$$createUrlParamsRequestHandler } from '@alilc/lowcode-datasource-url-params-handler';
|
||||||
|
|
||||||
|
import { createFetchHandler as __$$createFetchRequestHandler } from '@alilc/lowcode-datasource-fetch-handler';
|
||||||
|
|
||||||
|
import { create as __$$createDataSourceEngine } from '@alilc/lowcode-datasource-engine/runtime';
|
||||||
|
|
||||||
|
import utils, { RefsManager } from '../../utils';
|
||||||
|
|
||||||
|
import * as __$$i18n from '../../i18n';
|
||||||
|
|
||||||
|
import __$$constants from '../../constants';
|
||||||
|
|
||||||
|
import './index.css';
|
||||||
|
|
||||||
|
class Test$$Page extends React.Component {
|
||||||
|
_context = this;
|
||||||
|
|
||||||
|
_dataSourceConfig = this._defineDataSourceConfig();
|
||||||
|
_dataSourceEngine = __$$createDataSourceEngine(this._dataSourceConfig, this, {
|
||||||
|
runtimeConfig: true,
|
||||||
|
requestHandlersMap: {
|
||||||
|
urlParams: __$$createUrlParamsRequestHandler(window.location.search),
|
||||||
|
fetch: __$$createFetchRequestHandler(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
get dataSourceMap() {
|
||||||
|
return this._dataSourceEngine.dataSourceMap || {};
|
||||||
|
}
|
||||||
|
|
||||||
|
reloadDataSource = async () => {
|
||||||
|
await this._dataSourceEngine.reloadDataSource();
|
||||||
|
};
|
||||||
|
|
||||||
|
get constants() {
|
||||||
|
return __$$constants || {};
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(props, context) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.utils = utils;
|
||||||
|
|
||||||
|
this._refsManager = new RefsManager();
|
||||||
|
|
||||||
|
__$$i18n._inject2(this);
|
||||||
|
|
||||||
|
this.state = { text: 'outter' };
|
||||||
|
}
|
||||||
|
|
||||||
|
$ = (refName) => {
|
||||||
|
return this._refsManager.get(refName);
|
||||||
|
};
|
||||||
|
|
||||||
|
$$ = (refName) => {
|
||||||
|
return this._refsManager.getAll(refName);
|
||||||
|
};
|
||||||
|
|
||||||
|
_defineDataSourceConfig() {
|
||||||
|
const _this = this;
|
||||||
|
return {
|
||||||
|
list: [
|
||||||
|
{
|
||||||
|
id: 'urlParams',
|
||||||
|
type: 'urlParams',
|
||||||
|
isInit: function () {
|
||||||
|
return undefined;
|
||||||
|
}.bind(_this),
|
||||||
|
options: function () {
|
||||||
|
return undefined;
|
||||||
|
}.bind(_this),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'user',
|
||||||
|
type: 'fetch',
|
||||||
|
options: function () {
|
||||||
|
return {
|
||||||
|
method: 'GET',
|
||||||
|
uri: 'https://shs.xxx.com/mock/1458/demo/user',
|
||||||
|
isSync: true,
|
||||||
|
};
|
||||||
|
}.bind(_this),
|
||||||
|
dataHandler: function (response) {
|
||||||
|
if (!response.data.success) {
|
||||||
|
throw new Error(response.data.message);
|
||||||
|
}
|
||||||
|
return response.data.data;
|
||||||
|
},
|
||||||
|
isInit: function () {
|
||||||
|
return undefined;
|
||||||
|
}.bind(_this),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'orders',
|
||||||
|
type: 'fetch',
|
||||||
|
options: function () {
|
||||||
|
return {
|
||||||
|
method: 'GET',
|
||||||
|
uri: 'https://shs.xxx.com/mock/1458/demo/orders',
|
||||||
|
isSync: true,
|
||||||
|
};
|
||||||
|
}.bind(_this),
|
||||||
|
dataHandler: function (response) {
|
||||||
|
if (!response.data.success) {
|
||||||
|
throw new Error(response.data.message);
|
||||||
|
}
|
||||||
|
return response.data.data.result;
|
||||||
|
},
|
||||||
|
isInit: function () {
|
||||||
|
return undefined;
|
||||||
|
}.bind(_this),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
dataHandler: function (dataMap) {
|
||||||
|
console.info('All datasources loaded:', dataMap);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this._dataSourceEngine.reloadDataSource();
|
||||||
|
|
||||||
|
console.log('componentDidMount');
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const __$$context = this._context || this;
|
||||||
|
const { state } = __$$context;
|
||||||
|
return (
|
||||||
|
<div ref={this._refsManager.linkRef('outterView')} autoLoading={true}>
|
||||||
|
<Form
|
||||||
|
labelCol={__$$eval(() => this.state.colNum)}
|
||||||
|
style={{}}
|
||||||
|
ref={this._refsManager.linkRef('testForm')}
|
||||||
|
>
|
||||||
|
<Form.Item label="姓名:" name="name" initValue="李雷">
|
||||||
|
<Input placeholder="请输入" size="medium" style={{ width: 320 }} />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item label="年龄:" name="age" initValue="22">
|
||||||
|
<NumberPicker size="medium" type="normal" />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item label="职业:" name="profession">
|
||||||
|
<Select
|
||||||
|
dataSource={[
|
||||||
|
{ label: '教师', value: 't' },
|
||||||
|
{ label: '医生', value: 'd' },
|
||||||
|
{ label: '歌手', value: 's' },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
<div style={{ textAlign: 'center' }}>
|
||||||
|
<Button.Group>
|
||||||
|
{__$$evalArray(() => ['a', 'b', 'c']).map((item, index) =>
|
||||||
|
((__$$context) =>
|
||||||
|
!!__$$eval(() => index >= 1) && (
|
||||||
|
<Button type="primary" style={{ margin: '0 5px 0 5px' }}>
|
||||||
|
{__$$eval(() => item)}
|
||||||
|
</Button>
|
||||||
|
))(__$$createChildContext(__$$context, { item, index }))
|
||||||
|
)}
|
||||||
|
</Button.Group>
|
||||||
|
</div>
|
||||||
|
</Form>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
...ext,
|
||||||
|
};
|
||||||
|
childContext.__proto__ = oldContext;
|
||||||
|
return childContext;
|
||||||
|
}
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
import { Outlet } from 'ice';
|
||||||
|
import BasicLayout from '@/layouts/BasicLayout';
|
||||||
|
|
||||||
|
export default function Layout() {
|
||||||
|
return (
|
||||||
|
<BasicLayout>
|
||||||
|
<Outlet />
|
||||||
|
</BasicLayout>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
/// <reference types="@ice/app/types" />
|
||||||
|
|
||||||
|
export {};
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
g_config: Record<string, any>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,47 @@
|
|||||||
|
import { createRef } from 'react';
|
||||||
|
|
||||||
|
export class RefsManager {
|
||||||
|
constructor() {
|
||||||
|
this.refInsStore = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
clearNullRefs() {
|
||||||
|
Object.keys(this.refInsStore).forEach((refName) => {
|
||||||
|
const filteredInsList = this.refInsStore[refName].filter(
|
||||||
|
(insRef) => !!insRef.current
|
||||||
|
);
|
||||||
|
if (filteredInsList.length > 0) {
|
||||||
|
this.refInsStore[refName] = filteredInsList;
|
||||||
|
} else {
|
||||||
|
delete this.refInsStore[refName];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
get(refName) {
|
||||||
|
this.clearNullRefs();
|
||||||
|
if (this.refInsStore[refName] && this.refInsStore[refName].length > 0) {
|
||||||
|
return this.refInsStore[refName][0].current;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
getAll(refName) {
|
||||||
|
this.clearNullRefs();
|
||||||
|
if (this.refInsStore[refName] && this.refInsStore[refName].length > 0) {
|
||||||
|
return this.refInsStore[refName].map((i) => i.current);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
linkRef(refName) {
|
||||||
|
const refIns = createRef();
|
||||||
|
this.refInsStore[refName] = this.refInsStore[refName] || [];
|
||||||
|
this.refInsStore[refName].push(refIns);
|
||||||
|
return refIns;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {};
|
||||||
276
modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo1/schema.json5
vendored
Normal file
276
modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo1/schema.json5
vendored
Normal file
@ -0,0 +1,276 @@
|
|||||||
|
{
|
||||||
|
"version": "1.0.0",
|
||||||
|
"componentsMap": [
|
||||||
|
{
|
||||||
|
"componentName": "Button",
|
||||||
|
"package": "@alifd/next",
|
||||||
|
"version": "1.19.18",
|
||||||
|
"destructuring": true,
|
||||||
|
"exportName": "Button"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"componentName": "Button.Group",
|
||||||
|
"package": "@alifd/next",
|
||||||
|
"version": "1.19.18",
|
||||||
|
"destructuring": true,
|
||||||
|
"exportName": "Button",
|
||||||
|
"subName": "Group"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"componentName": "Input",
|
||||||
|
"package": "@alifd/next",
|
||||||
|
"version": "1.19.18",
|
||||||
|
"destructuring": true,
|
||||||
|
"exportName": "Input"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"componentName": "Form",
|
||||||
|
"package": "@alifd/next",
|
||||||
|
"version": "1.19.18",
|
||||||
|
"destructuring": true,
|
||||||
|
"exportName": "Form"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"componentName": "Form.Item",
|
||||||
|
"package": "@alifd/next",
|
||||||
|
"version": "1.19.18",
|
||||||
|
"destructuring": true,
|
||||||
|
"exportName": "Form",
|
||||||
|
"subName": "Item"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"componentName": "NumberPicker",
|
||||||
|
"package": "@alifd/next",
|
||||||
|
"version": "1.19.18",
|
||||||
|
"destructuring": true,
|
||||||
|
"exportName": "NumberPicker"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"componentName": "Select",
|
||||||
|
"package": "@alifd/next",
|
||||||
|
"version": "1.19.18",
|
||||||
|
"destructuring": true,
|
||||||
|
"exportName": "Select"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"componentsTree": [
|
||||||
|
{
|
||||||
|
"componentName": "Page",
|
||||||
|
"id": "node$1",
|
||||||
|
"meta": {
|
||||||
|
"title": "测试",
|
||||||
|
"router": "/"
|
||||||
|
},
|
||||||
|
"props": {
|
||||||
|
"ref": "outterView",
|
||||||
|
"autoLoading": true
|
||||||
|
},
|
||||||
|
"fileName": "test",
|
||||||
|
"state": {
|
||||||
|
"text": "outter"
|
||||||
|
},
|
||||||
|
"lifeCycles": {
|
||||||
|
"componentDidMount": {
|
||||||
|
"type": "JSFunction",
|
||||||
|
"value": "function() { console.log('componentDidMount'); }"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dataSource: {
|
||||||
|
list: [
|
||||||
|
{
|
||||||
|
id: 'urlParams',
|
||||||
|
type: 'urlParams',
|
||||||
|
},
|
||||||
|
// 示例数据源:https://shs.xxx.com/mock/1458/demo/user
|
||||||
|
{
|
||||||
|
id: 'user',
|
||||||
|
type: 'fetch',
|
||||||
|
options: {
|
||||||
|
method: 'GET',
|
||||||
|
uri: 'https://shs.xxx.com/mock/1458/demo/user',
|
||||||
|
isSync: true,
|
||||||
|
},
|
||||||
|
dataHandler: {
|
||||||
|
type: 'JSExpression',
|
||||||
|
value: 'function (response) {\nif (!response.data.success){\n throw new Error(response.data.message);\n }\n return response.data.data;\n}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// 示例数据源:https://shs.xxx.com/mock/1458/demo/orders
|
||||||
|
{
|
||||||
|
id: 'orders',
|
||||||
|
type: 'fetch',
|
||||||
|
options: {
|
||||||
|
method: 'GET',
|
||||||
|
uri: "https://shs.xxx.com/mock/1458/demo/orders",
|
||||||
|
isSync: true,
|
||||||
|
},
|
||||||
|
dataHandler: {
|
||||||
|
type: 'JSExpression',
|
||||||
|
value: 'function (response) {\nif (!response.data.success){\n throw new Error(response.data.message);\n }\n return response.data.data.result;\n}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
dataHandler: {
|
||||||
|
type: 'JSExpression',
|
||||||
|
value: 'function (dataMap) {\n console.info("All datasources loaded:", dataMap);\n}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"componentName": "Form",
|
||||||
|
"id": "node$2",
|
||||||
|
"props": {
|
||||||
|
"labelCol": {
|
||||||
|
"type": "JSExpression",
|
||||||
|
"value": "this.state.colNum"
|
||||||
|
},
|
||||||
|
"style": {},
|
||||||
|
"ref": "testForm"
|
||||||
|
},
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"componentName": "Form.Item",
|
||||||
|
"id": "node$3",
|
||||||
|
"props": {
|
||||||
|
"label": "姓名:",
|
||||||
|
"name": "name",
|
||||||
|
"initValue": "李雷"
|
||||||
|
},
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"componentName": "Input",
|
||||||
|
"id": "node$4",
|
||||||
|
"props": {
|
||||||
|
"placeholder": "请输入",
|
||||||
|
"size": "medium",
|
||||||
|
"style": {
|
||||||
|
"width": 320
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"componentName": "Form.Item",
|
||||||
|
"id": "node$5",
|
||||||
|
"props": {
|
||||||
|
"label": "年龄:",
|
||||||
|
"name": "age",
|
||||||
|
"initValue": "22"
|
||||||
|
},
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"componentName": "NumberPicker",
|
||||||
|
"id": "node$6",
|
||||||
|
"props": {
|
||||||
|
"size": "medium",
|
||||||
|
"type": "normal"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"componentName": "Form.Item",
|
||||||
|
"id": "node$7",
|
||||||
|
"props": {
|
||||||
|
"label": "职业:",
|
||||||
|
"name": "profession"
|
||||||
|
},
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"componentName": "Select",
|
||||||
|
"id": "node$8",
|
||||||
|
"props": {
|
||||||
|
"dataSource": [
|
||||||
|
{
|
||||||
|
"label": "教师",
|
||||||
|
"value": "t"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "医生",
|
||||||
|
"value": "d"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "歌手",
|
||||||
|
"value": "s"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"componentName": "Div",
|
||||||
|
"id": "node$9",
|
||||||
|
"props": {
|
||||||
|
"style": {
|
||||||
|
"textAlign": "center"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"componentName": "Button.Group",
|
||||||
|
"id": "node$a",
|
||||||
|
"props": {},
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"componentName": "Button",
|
||||||
|
"id": "node$b",
|
||||||
|
"condition": {
|
||||||
|
"type": "JSExpression",
|
||||||
|
"value": "this.index >= 1"
|
||||||
|
},
|
||||||
|
"loop": ["a", "b", "c"],
|
||||||
|
"props": {
|
||||||
|
"type": "primary",
|
||||||
|
"style": {
|
||||||
|
"margin": "0 5px 0 5px"
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"type": "JSExpression",
|
||||||
|
"value": "this.item"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"constants": {
|
||||||
|
"ENV": "prod",
|
||||||
|
"DOMAIN": "xxx.xxx.com"
|
||||||
|
},
|
||||||
|
"css": "body {font-size: 12px;} .table { width: 100px;}",
|
||||||
|
"config": {
|
||||||
|
"sdkVersion": "1.0.3",
|
||||||
|
"historyMode": "hash",
|
||||||
|
"targetRootID": "J_Container",
|
||||||
|
"layout": {
|
||||||
|
"componentName": "BasicLayout",
|
||||||
|
"props": {
|
||||||
|
"logo": "...",
|
||||||
|
"name": "测试网站"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"theme": {
|
||||||
|
"package": "@alife/theme-fusion",
|
||||||
|
"version": "^0.1.0",
|
||||||
|
"primary": "#ff9966"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"name": "demo应用",
|
||||||
|
"git_group": "appGroup",
|
||||||
|
"project_name": "app_demo",
|
||||||
|
"description": "这是一个测试应用",
|
||||||
|
"spma": "spa23d",
|
||||||
|
"creator": "月飞"
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
defaults
|
||||||
|
ios_saf 9
|
||||||
|
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
# See https://help.github.com/ignore-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# production
|
||||||
|
build/
|
||||||
|
dist/
|
||||||
|
tmp/
|
||||||
|
lib/
|
||||||
|
|
||||||
|
# misc
|
||||||
|
.idea/
|
||||||
|
.happypack
|
||||||
|
.DS_Store
|
||||||
|
*.swp
|
||||||
|
*.dia~
|
||||||
|
.ice
|
||||||
|
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
index.module.scss.d.ts
|
||||||
|
|
||||||
@ -0,0 +1 @@
|
|||||||
|
This project is generated by lowcode-code-generator & lowcode-solution-icejs3.
|
||||||
@ -0,0 +1,90 @@
|
|||||||
|
import { join } from 'path';
|
||||||
|
import { defineConfig } from '@ice/app';
|
||||||
|
import _ from 'lodash';
|
||||||
|
import fusion from '@ice/plugin-fusion';
|
||||||
|
import locales from '@ice/plugin-moment-locales';
|
||||||
|
import type { Plugin } from '@ice/app/esm/types';
|
||||||
|
|
||||||
|
interface PluginOptions {
|
||||||
|
id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const plugin: Plugin<PluginOptions> = (options) => ({
|
||||||
|
// name 可选,插件名称
|
||||||
|
name: 'plugin-name',
|
||||||
|
// setup 必选,用于定制工程构建配置
|
||||||
|
setup: ({ onGetConfig, modifyUserConfig }) => {
|
||||||
|
modifyUserConfig('codeSplitting', 'page');
|
||||||
|
|
||||||
|
onGetConfig((config) => {
|
||||||
|
config.entry = {
|
||||||
|
web: join(process.cwd(), '.ice/entry.client.tsx'),
|
||||||
|
};
|
||||||
|
|
||||||
|
config.cssFilename = '[name].css';
|
||||||
|
|
||||||
|
config.configureWebpack = config.configureWebpack || [];
|
||||||
|
config.configureWebpack?.push((webpackConfig) => {
|
||||||
|
if (webpackConfig.output) {
|
||||||
|
webpackConfig.output.filename = '[name].js';
|
||||||
|
webpackConfig.output.chunkFilename = '[name].js';
|
||||||
|
}
|
||||||
|
return webpackConfig;
|
||||||
|
});
|
||||||
|
|
||||||
|
config.swcOptions = _.merge(config.swcOptions, {
|
||||||
|
compilationConfig: {
|
||||||
|
jsc: {
|
||||||
|
transform: {
|
||||||
|
react: {
|
||||||
|
runtime: 'classic',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// 解决 webpack publicPath 问题
|
||||||
|
config.transforms = config.transforms || [];
|
||||||
|
config.transforms.push((source: string, id: string) => {
|
||||||
|
if (id.includes('.ice/entry.client.tsx')) {
|
||||||
|
let code = `
|
||||||
|
if (!__webpack_public_path__?.startsWith('http') && document.currentScript) {
|
||||||
|
// @ts-ignore
|
||||||
|
__webpack_public_path__ = document.currentScript.src.replace(/^(.*\\/)[^/]+$/, '$1');
|
||||||
|
window.__ICE_ASSETS_MANIFEST__ = window.__ICE_ASSETS_MANIFEST__ || {};
|
||||||
|
window.__ICE_ASSETS_MANIFEST__.publicPath = __webpack_public_path__;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
code += source;
|
||||||
|
return { code };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// The project config, see https://v3.ice.work/docs/guide/basic/config
|
||||||
|
const minify = process.env.NODE_ENV === 'production' ? 'swc' : false;
|
||||||
|
export default defineConfig(() => ({
|
||||||
|
ssr: false,
|
||||||
|
ssg: false,
|
||||||
|
minify,
|
||||||
|
|
||||||
|
externals: {
|
||||||
|
react: 'React',
|
||||||
|
'react-dom': 'ReactDOM',
|
||||||
|
'react-dom/client': 'ReactDOM',
|
||||||
|
'@alifd/next': 'Next',
|
||||||
|
lodash: 'var window._',
|
||||||
|
'@alilc/lowcode-engine': 'var window.AliLowCodeEngine',
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
fusion({
|
||||||
|
importStyle: true,
|
||||||
|
}),
|
||||||
|
locales(),
|
||||||
|
plugin(),
|
||||||
|
],
|
||||||
|
}));
|
||||||
|
|
||||||
@ -0,0 +1,48 @@
|
|||||||
|
{
|
||||||
|
"name": "icejs3-demo-app",
|
||||||
|
"version": "0.1.5",
|
||||||
|
"description": "icejs 3 轻量级模板,使用 JavaScript,仅包含基础的 Layout。",
|
||||||
|
"dependencies": {
|
||||||
|
"moment": "^2.24.0",
|
||||||
|
"react": "^18.2.0",
|
||||||
|
"react-dom": "^18.2.0",
|
||||||
|
"react-router": "^6.9.0",
|
||||||
|
"react-router-dom": "^6.9.0",
|
||||||
|
"intl-messageformat": "^9.3.6",
|
||||||
|
"@alifd/next": "1.26.15",
|
||||||
|
"@ice/runtime": "^1.0.0",
|
||||||
|
"@alilc/lowcode-datasource-engine": "^1.0.0",
|
||||||
|
"@alilc/lowcode-datasource-url-params-handler": "^1.0.0",
|
||||||
|
"@alilc/b6-page": "^0.1.0",
|
||||||
|
"@alilc/b6-text": "^0.1.0",
|
||||||
|
"@alilc/b6-compact-legao-builtin": "1.x",
|
||||||
|
"antd": "3.x",
|
||||||
|
"@alilc/b6-util-mocks": "1.x"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@ice/app": "^3.0.0",
|
||||||
|
"@types/react": "^18.0.0",
|
||||||
|
"@types/react-dom": "^18.0.0",
|
||||||
|
"@types/node": "^18.11.17",
|
||||||
|
"@ice/plugin-fusion": "^1.0.1",
|
||||||
|
"@ice/plugin-moment-locales": "^1.0.0",
|
||||||
|
"eslint": "^6.0.1",
|
||||||
|
"stylelint": "^13.2.0"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"start": "ice start",
|
||||||
|
"build": "ice build",
|
||||||
|
"lint": "npm run eslint && npm run stylelint",
|
||||||
|
"eslint": "eslint --cache --ext .js,.jsx ./",
|
||||||
|
"stylelint": "stylelint ./**/*.scss"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "http://gitlab.xxx.com/msd/leak-scan/tree/master"
|
||||||
|
},
|
||||||
|
"private": true,
|
||||||
|
"originTemplate": "@alifd/scaffold-lite-js"
|
||||||
|
}
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
import { defineAppConfig } from 'ice';
|
||||||
|
|
||||||
|
// App config, see https://v3.ice.work/docs/guide/basic/app
|
||||||
|
export default defineAppConfig(() => ({
|
||||||
|
// Set your configs here.
|
||||||
|
app: {
|
||||||
|
rootId: 'App',
|
||||||
|
},
|
||||||
|
router: {
|
||||||
|
type: 'browser',
|
||||||
|
basename: '/',
|
||||||
|
},
|
||||||
|
}));
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
const __$$constants = {};
|
||||||
|
|
||||||
|
export default __$$constants;
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Meta, Title, Links, Main, Scripts } from 'ice';
|
||||||
|
|
||||||
|
export default function Document() {
|
||||||
|
return (
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charSet="utf-8" />
|
||||||
|
<meta name="description" content="ice.js 3 lite scaffold" />
|
||||||
|
<link rel="icon" href="/favicon.ico" />
|
||||||
|
<link rel="stylesheet" href="//alifd.alicdn.com/npm/@alifd/next/1.21.16/next.min.css" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
|
||||||
|
<Meta />
|
||||||
|
<Title />
|
||||||
|
<Links />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<Main />
|
||||||
|
<script crossOrigin="anonymous" src="//g.alicdn.com/code/lib/react/18.2.0/umd/react.development.js" />
|
||||||
|
<script crossOrigin="anonymous" src="//g.alicdn.com/code/lib/react-dom/18.2.0/umd/react-dom.development.js" />
|
||||||
|
<script crossOrigin="anonymous" src="//g.alicdn.com/code/lib/??react-router/6.9.0/react-router.production.min.js,react-router-dom/6.9.0/react-router-dom.production.min.js" />
|
||||||
|
<script crossOrigin="anonymous" src="//alifd.alicdn.com/npm/@alifd/next/1.26.15/next.min.js" />
|
||||||
|
<script crossOrigin="anonymous" src="//g.alicdn.com/code/lib/prop-types/15.7.2/prop-types.js" />
|
||||||
|
<script crossOrigin="anonymous" src="//g.alicdn.com/platform/c/??lodash/4.6.1/lodash.min.js,immutable/3.7.6/dist/immutable.min.js" />
|
||||||
|
<Scripts />
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
// 引入默认全局样式
|
||||||
|
@import '@alifd/next/reset.scss';
|
||||||
|
|
||||||
|
body {
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
}
|
||||||
@ -0,0 +1,77 @@
|
|||||||
|
const i18nConfig = {};
|
||||||
|
|
||||||
|
let locale =
|
||||||
|
typeof navigator === 'object' && typeof navigator.language === 'string'
|
||||||
|
? navigator.language
|
||||||
|
: 'zh-CN';
|
||||||
|
|
||||||
|
const getLocale = () => locale;
|
||||||
|
|
||||||
|
const setLocale = (target) => {
|
||||||
|
locale = target;
|
||||||
|
};
|
||||||
|
|
||||||
|
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 fallback === undefined ? `${id}` : fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 其次用项目级别的
|
||||||
|
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,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import styles from './index.module.scss';
|
||||||
|
|
||||||
|
export default function Footer() {
|
||||||
|
return (
|
||||||
|
<p className={styles.footer}>
|
||||||
|
<span className={styles.logo}>Alibaba Fusion</span>
|
||||||
|
<br />
|
||||||
|
<span className={styles.copyright}>© 2019-现在 Alibaba Fusion & ICE</span>
|
||||||
|
</p>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
.footer {
|
||||||
|
line-height: 20px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import { Link } from 'ice';
|
||||||
|
import styles from './index.module.scss';
|
||||||
|
|
||||||
|
export default function Logo({ image, text, url }) {
|
||||||
|
return (
|
||||||
|
<div className="logo">
|
||||||
|
<Link to={url || '/'} className={styles.logo}>
|
||||||
|
{image && <img src={image} alt="logo" />}
|
||||||
|
<span>{text}</span>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
|
||||||
|
.logo{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
color: $color-text1-1;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 22px;
|
||||||
|
|
||||||
|
&:visited, &:link {
|
||||||
|
color: $color-text1-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
height: 24px;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,68 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { Link, useLocation } from 'ice';
|
||||||
|
import { Nav } from '@alifd/next';
|
||||||
|
import { asideMenuConfig } from '../../menuConfig';
|
||||||
|
|
||||||
|
const { SubNav } = Nav;
|
||||||
|
const NavItem = Nav.Item;
|
||||||
|
|
||||||
|
function getNavMenuItems(menusData) {
|
||||||
|
if (!menusData) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return menusData
|
||||||
|
.filter(item => item.name && !item.hideInMenu)
|
||||||
|
.map((item, index) => getSubMenuOrItem(item, index));
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSubMenuOrItem(item, index) {
|
||||||
|
if (item.children && item.children.some(child => child.name)) {
|
||||||
|
const childrenItems = getNavMenuItems(item.children);
|
||||||
|
|
||||||
|
if (childrenItems && childrenItems.length > 0) {
|
||||||
|
const subNav = (
|
||||||
|
<SubNav key={index} icon={item.icon} label={item.name}>
|
||||||
|
{childrenItems}
|
||||||
|
</SubNav>
|
||||||
|
);
|
||||||
|
return subNav;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const navItem = (
|
||||||
|
<NavItem key={item.path} icon={item.icon}>
|
||||||
|
<Link to={item.path}>{item.name}</Link>
|
||||||
|
</NavItem>
|
||||||
|
);
|
||||||
|
return navItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Navigation = (props, context) => {
|
||||||
|
const location = useLocation();
|
||||||
|
const { pathname } = location;
|
||||||
|
const { isCollapse } = context;
|
||||||
|
return (
|
||||||
|
<Nav
|
||||||
|
type="primary"
|
||||||
|
selectedKeys={[pathname]}
|
||||||
|
defaultSelectedKeys={[pathname]}
|
||||||
|
embeddable
|
||||||
|
openMode="single"
|
||||||
|
iconOnly={isCollapse}
|
||||||
|
hasArrow={false}
|
||||||
|
mode={isCollapse ? 'popup' : 'inline'}
|
||||||
|
>
|
||||||
|
{getNavMenuItems(asideMenuConfig)}
|
||||||
|
</Nav>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
Navigation.contextTypes = {
|
||||||
|
isCollapse: PropTypes.bool,
|
||||||
|
};
|
||||||
|
export default Navigation;
|
||||||
|
|
||||||
@ -0,0 +1,81 @@
|
|||||||
|
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
import { Shell, ConfigProvider } from '@alifd/next';
|
||||||
|
import PageNav from './components/PageNav';
|
||||||
|
import Logo from './components/Logo';
|
||||||
|
import Footer from './components/Footer';
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
const throttle = function(type, name, obj = window) {
|
||||||
|
let running = false;
|
||||||
|
|
||||||
|
const func = () => {
|
||||||
|
if (running) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
running = true;
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
obj.dispatchEvent(new CustomEvent(name));
|
||||||
|
running = false;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
obj.addEventListener(type, func);
|
||||||
|
};
|
||||||
|
|
||||||
|
throttle('resize', 'optimizedResize');
|
||||||
|
})();
|
||||||
|
|
||||||
|
export default function BasicLayout({ children }) {
|
||||||
|
const getDevice = width => {
|
||||||
|
const isPhone =
|
||||||
|
typeof navigator !== 'undefined' && navigator && navigator.userAgent.match(/phone/gi);
|
||||||
|
|
||||||
|
if (width < 680 || isPhone) {
|
||||||
|
return 'phone';
|
||||||
|
}
|
||||||
|
if (width < 1280 && width > 680) {
|
||||||
|
return 'tablet';
|
||||||
|
}
|
||||||
|
return 'desktop';
|
||||||
|
};
|
||||||
|
|
||||||
|
const [device, setDevice] = useState(getDevice(NaN));
|
||||||
|
window.addEventListener('optimizedResize', e => {
|
||||||
|
setDevice(getDevice(e && e.target && e.target.innerWidth));
|
||||||
|
});
|
||||||
|
return (
|
||||||
|
<ConfigProvider device={device}>
|
||||||
|
<Shell
|
||||||
|
type="dark"
|
||||||
|
style={{
|
||||||
|
minHeight: '100vh',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Shell.Branding>
|
||||||
|
<Logo
|
||||||
|
image="https://img.alicdn.com/tfs/TB1.ZBecq67gK0jSZFHXXa9jVXa-904-826.png"
|
||||||
|
text="Logo"
|
||||||
|
/>
|
||||||
|
</Shell.Branding>
|
||||||
|
<Shell.Navigation
|
||||||
|
direction="hoz"
|
||||||
|
style={{
|
||||||
|
marginRight: 10,
|
||||||
|
}}
|
||||||
|
></Shell.Navigation>
|
||||||
|
<Shell.Action></Shell.Action>
|
||||||
|
<Shell.Navigation>
|
||||||
|
<PageNav />
|
||||||
|
</Shell.Navigation>
|
||||||
|
|
||||||
|
<Shell.Content>{children}</Shell.Content>
|
||||||
|
<Shell.Footer>
|
||||||
|
<Footer />
|
||||||
|
</Shell.Footer>
|
||||||
|
</Shell>
|
||||||
|
</ConfigProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
const headerMenuConfig = [];
|
||||||
|
const asideMenuConfig = [
|
||||||
|
{
|
||||||
|
name: 'Dashboard',
|
||||||
|
path: '/',
|
||||||
|
icon: 'smile',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
export { headerMenuConfig, asideMenuConfig };
|
||||||
|
|
||||||
@ -0,0 +1,118 @@
|
|||||||
|
// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。
|
||||||
|
// 例外:react 框架的导出名和各种组件名除外。
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { Page } from '@alilc/b6-page';
|
||||||
|
|
||||||
|
import { Text } from '@alilc/b6-text';
|
||||||
|
|
||||||
|
import { createUrlParamsHandler as __$$createUrlParamsRequestHandler } from '@alilc/lowcode-datasource-url-params-handler';
|
||||||
|
|
||||||
|
import { create as __$$createDataSourceEngine } from '@alilc/lowcode-datasource-engine/runtime';
|
||||||
|
|
||||||
|
import utils from '../../utils';
|
||||||
|
|
||||||
|
import * as __$$i18n from '../../i18n';
|
||||||
|
|
||||||
|
import __$$constants from '../../constants';
|
||||||
|
|
||||||
|
import './index.css';
|
||||||
|
|
||||||
|
class Aaaa$$Page extends React.Component {
|
||||||
|
_context = this;
|
||||||
|
|
||||||
|
_dataSourceConfig = this._defineDataSourceConfig();
|
||||||
|
_dataSourceEngine = __$$createDataSourceEngine(this._dataSourceConfig, this, {
|
||||||
|
runtimeConfig: true,
|
||||||
|
requestHandlersMap: {
|
||||||
|
urlParams: __$$createUrlParamsRequestHandler(window.location.search),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
get dataSourceMap() {
|
||||||
|
return this._dataSourceEngine.dataSourceMap || {};
|
||||||
|
}
|
||||||
|
|
||||||
|
reloadDataSource = async () => {
|
||||||
|
await this._dataSourceEngine.reloadDataSource();
|
||||||
|
};
|
||||||
|
|
||||||
|
get constants() {
|
||||||
|
return __$$constants || {};
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(props, context) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.utils = utils;
|
||||||
|
|
||||||
|
__$$i18n._inject2(this);
|
||||||
|
|
||||||
|
this.state = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
$ = () => null;
|
||||||
|
|
||||||
|
$$ = () => [];
|
||||||
|
|
||||||
|
_defineDataSourceConfig() {
|
||||||
|
const _this = this;
|
||||||
|
return {
|
||||||
|
list: [
|
||||||
|
{
|
||||||
|
id: 'urlParams',
|
||||||
|
type: 'urlParams',
|
||||||
|
description: 'URL参数',
|
||||||
|
options: function () {
|
||||||
|
return {
|
||||||
|
uri: '',
|
||||||
|
};
|
||||||
|
}.bind(_this),
|
||||||
|
isInit: function () {
|
||||||
|
return undefined;
|
||||||
|
}.bind(_this),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this._dataSourceEngine.reloadDataSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const __$$context = this._context || this;
|
||||||
|
const { state } = __$$context;
|
||||||
|
return (
|
||||||
|
<div title="" backgroundColor="#fff" textColor="#333" style={{}}>
|
||||||
|
<Text
|
||||||
|
content="欢迎使用 BuildSuccess!sadsad"
|
||||||
|
style={{}}
|
||||||
|
fieldId="text_kp6ci11t"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
...ext,
|
||||||
|
};
|
||||||
|
childContext.__proto__ = oldContext;
|
||||||
|
return childContext;
|
||||||
|
}
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
import { Outlet } from 'ice';
|
||||||
|
import BasicLayout from '@/layouts/BasicLayout';
|
||||||
|
|
||||||
|
export default function Layout() {
|
||||||
|
return (
|
||||||
|
<BasicLayout>
|
||||||
|
<Outlet />
|
||||||
|
</BasicLayout>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
/// <reference types="@ice/app/types" />
|
||||||
|
|
||||||
|
export {};
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
g_config: Record<string, any>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,61 @@
|
|||||||
|
import legaoBuiltin from '@alilc/b6-compact-legao-builtin';
|
||||||
|
|
||||||
|
import { message, Modal as modal } from 'antd';
|
||||||
|
|
||||||
|
import { mocks } from '@alilc/b6-util-mocks';
|
||||||
|
|
||||||
|
import { createRef } from 'react';
|
||||||
|
|
||||||
|
export class RefsManager {
|
||||||
|
constructor() {
|
||||||
|
this.refInsStore = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
clearNullRefs() {
|
||||||
|
Object.keys(this.refInsStore).forEach((refName) => {
|
||||||
|
const filteredInsList = this.refInsStore[refName].filter(
|
||||||
|
(insRef) => !!insRef.current
|
||||||
|
);
|
||||||
|
if (filteredInsList.length > 0) {
|
||||||
|
this.refInsStore[refName] = filteredInsList;
|
||||||
|
} else {
|
||||||
|
delete this.refInsStore[refName];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
get(refName) {
|
||||||
|
this.clearNullRefs();
|
||||||
|
if (this.refInsStore[refName] && this.refInsStore[refName].length > 0) {
|
||||||
|
return this.refInsStore[refName][0].current;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
getAll(refName) {
|
||||||
|
this.clearNullRefs();
|
||||||
|
if (this.refInsStore[refName] && this.refInsStore[refName].length > 0) {
|
||||||
|
return this.refInsStore[refName].map((i) => i.current);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
linkRef(refName) {
|
||||||
|
const refIns = createRef();
|
||||||
|
this.refInsStore[refName] = this.refInsStore[refName] || [];
|
||||||
|
this.refInsStore[refName].push(refIns);
|
||||||
|
return refIns;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
legaoBuiltin,
|
||||||
|
|
||||||
|
message,
|
||||||
|
|
||||||
|
mocks,
|
||||||
|
|
||||||
|
modal,
|
||||||
|
};
|
||||||
123
modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo2-utils-name-alias/schema.json5
vendored
Normal file
123
modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo2-utils-name-alias/schema.json5
vendored
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
{
|
||||||
|
version: '1.0.0',
|
||||||
|
componentsMap: [
|
||||||
|
{
|
||||||
|
package: '@alilc/b6-page',
|
||||||
|
version: '^0.1.0',
|
||||||
|
componentName: 'Page',
|
||||||
|
destructuring: true,
|
||||||
|
exportName: 'Page',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
package: '@alilc/b6-text',
|
||||||
|
version: '^0.1.0',
|
||||||
|
componentName: 'Text',
|
||||||
|
destructuring: true,
|
||||||
|
exportName: 'Text',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
componentsTree: [
|
||||||
|
{
|
||||||
|
componentName: 'Page',
|
||||||
|
id: 'node_ockp6ci0hm1',
|
||||||
|
props: {
|
||||||
|
title: '',
|
||||||
|
backgroundColor: '#fff',
|
||||||
|
textColor: '#333',
|
||||||
|
style: {},
|
||||||
|
},
|
||||||
|
fileName: 'aaaa',
|
||||||
|
dataSource: {
|
||||||
|
list: [
|
||||||
|
{
|
||||||
|
id: 'urlParams',
|
||||||
|
type: 'urlParams',
|
||||||
|
description: 'URL参数',
|
||||||
|
options: {
|
||||||
|
uri: '',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
componentName: 'Text',
|
||||||
|
id: 'node_ockp6ci0hm2',
|
||||||
|
props: {
|
||||||
|
content: '欢迎使用 BuildSuccess!sadsad',
|
||||||
|
style: {},
|
||||||
|
fieldId: 'text_kp6ci11t',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
meta: {
|
||||||
|
router: '/aaaa',
|
||||||
|
},
|
||||||
|
methodsModule: {
|
||||||
|
type: 'JSModule',
|
||||||
|
compiled: '"use strict";\n\nObject.defineProperty(exports, "__esModule", {\n value: true\n});\nexports.helloPage = helloPage;\n\n/**\n * Private, and can be re-used functions\n * Actions panel help documentation:\n * @see https://yuque.antfin.com/docs/share/89ca7965-6387-4e3a-9964-81929ed48f1e\n */\nfunction printLog(obj) {\n console.info(obj);\n}\n/**\n * page function\n */\n\n\nfunction helloPage() {\n console.log(\'hello page\');\n}',
|
||||||
|
source: "/**\n * Private, and can be re-used functions\n * Actions panel help documentation:\n * @see https://yuque.antfin.com/docs/share/89ca7965-6387-4e3a-9964-81929ed48f1e\n */\nfunction printLog(obj) {\n console.info(obj);\n}\n\n/**\n * page function\n */\nexport function helloPage() {\n console.log('hello page');\n}",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
i18n: {},
|
||||||
|
utils: [
|
||||||
|
{
|
||||||
|
name: 'legaoBuiltin',
|
||||||
|
type: 'npm',
|
||||||
|
content: {
|
||||||
|
exportName: 'legaoBuiltin',
|
||||||
|
package: '@alilc/b6-compact-legao-builtin',
|
||||||
|
version: '1.x',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'message',
|
||||||
|
type: 'npm',
|
||||||
|
content: {
|
||||||
|
package: 'antd',
|
||||||
|
version: '3.x',
|
||||||
|
destructuring: true,
|
||||||
|
exportName: 'message',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'mocks',
|
||||||
|
type: 'npm',
|
||||||
|
content: {
|
||||||
|
package: '@alilc/b6-util-mocks',
|
||||||
|
version: '1.x',
|
||||||
|
exportName: 'mocks',
|
||||||
|
destructuring: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'modal',
|
||||||
|
type: 'npm',
|
||||||
|
content: {
|
||||||
|
package: 'antd',
|
||||||
|
version: '3.x',
|
||||||
|
destructuring: true,
|
||||||
|
exportName: 'Modal',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
constants: {},
|
||||||
|
dataSource: {
|
||||||
|
list: [],
|
||||||
|
},
|
||||||
|
config: {
|
||||||
|
sdkVersion: '1.0.3',
|
||||||
|
historyMode: 'hash',
|
||||||
|
targetRootID: 'root',
|
||||||
|
miniAppBuildType: 'runtime',
|
||||||
|
},
|
||||||
|
meta: {
|
||||||
|
name: 'jinyuan-test2',
|
||||||
|
git_group: 'b6',
|
||||||
|
project_name: 'jinyuan-test2',
|
||||||
|
description: '瑾源测试',
|
||||||
|
spma: 'spmademo',
|
||||||
|
creator: '张三',
|
||||||
|
},
|
||||||
|
}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
defaults
|
||||||
|
ios_saf 9
|
||||||
|
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
# See https://help.github.com/ignore-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# production
|
||||||
|
build/
|
||||||
|
dist/
|
||||||
|
tmp/
|
||||||
|
lib/
|
||||||
|
|
||||||
|
# misc
|
||||||
|
.idea/
|
||||||
|
.happypack
|
||||||
|
.DS_Store
|
||||||
|
*.swp
|
||||||
|
*.dia~
|
||||||
|
.ice
|
||||||
|
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
index.module.scss.d.ts
|
||||||
|
|
||||||
@ -0,0 +1 @@
|
|||||||
|
This project is generated by lowcode-code-generator & lowcode-solution-icejs3.
|
||||||
@ -0,0 +1,90 @@
|
|||||||
|
import { join } from 'path';
|
||||||
|
import { defineConfig } from '@ice/app';
|
||||||
|
import _ from 'lodash';
|
||||||
|
import fusion from '@ice/plugin-fusion';
|
||||||
|
import locales from '@ice/plugin-moment-locales';
|
||||||
|
import type { Plugin } from '@ice/app/esm/types';
|
||||||
|
|
||||||
|
interface PluginOptions {
|
||||||
|
id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const plugin: Plugin<PluginOptions> = (options) => ({
|
||||||
|
// name 可选,插件名称
|
||||||
|
name: 'plugin-name',
|
||||||
|
// setup 必选,用于定制工程构建配置
|
||||||
|
setup: ({ onGetConfig, modifyUserConfig }) => {
|
||||||
|
modifyUserConfig('codeSplitting', 'page');
|
||||||
|
|
||||||
|
onGetConfig((config) => {
|
||||||
|
config.entry = {
|
||||||
|
web: join(process.cwd(), '.ice/entry.client.tsx'),
|
||||||
|
};
|
||||||
|
|
||||||
|
config.cssFilename = '[name].css';
|
||||||
|
|
||||||
|
config.configureWebpack = config.configureWebpack || [];
|
||||||
|
config.configureWebpack?.push((webpackConfig) => {
|
||||||
|
if (webpackConfig.output) {
|
||||||
|
webpackConfig.output.filename = '[name].js';
|
||||||
|
webpackConfig.output.chunkFilename = '[name].js';
|
||||||
|
}
|
||||||
|
return webpackConfig;
|
||||||
|
});
|
||||||
|
|
||||||
|
config.swcOptions = _.merge(config.swcOptions, {
|
||||||
|
compilationConfig: {
|
||||||
|
jsc: {
|
||||||
|
transform: {
|
||||||
|
react: {
|
||||||
|
runtime: 'classic',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// 解决 webpack publicPath 问题
|
||||||
|
config.transforms = config.transforms || [];
|
||||||
|
config.transforms.push((source: string, id: string) => {
|
||||||
|
if (id.includes('.ice/entry.client.tsx')) {
|
||||||
|
let code = `
|
||||||
|
if (!__webpack_public_path__?.startsWith('http') && document.currentScript) {
|
||||||
|
// @ts-ignore
|
||||||
|
__webpack_public_path__ = document.currentScript.src.replace(/^(.*\\/)[^/]+$/, '$1');
|
||||||
|
window.__ICE_ASSETS_MANIFEST__ = window.__ICE_ASSETS_MANIFEST__ || {};
|
||||||
|
window.__ICE_ASSETS_MANIFEST__.publicPath = __webpack_public_path__;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
code += source;
|
||||||
|
return { code };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// The project config, see https://v3.ice.work/docs/guide/basic/config
|
||||||
|
const minify = process.env.NODE_ENV === 'production' ? 'swc' : false;
|
||||||
|
export default defineConfig(() => ({
|
||||||
|
ssr: false,
|
||||||
|
ssg: false,
|
||||||
|
minify,
|
||||||
|
|
||||||
|
externals: {
|
||||||
|
react: 'React',
|
||||||
|
'react-dom': 'ReactDOM',
|
||||||
|
'react-dom/client': 'ReactDOM',
|
||||||
|
'@alifd/next': 'Next',
|
||||||
|
lodash: 'var window._',
|
||||||
|
'@alilc/lowcode-engine': 'var window.AliLowCodeEngine',
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
fusion({
|
||||||
|
importStyle: true,
|
||||||
|
}),
|
||||||
|
locales(),
|
||||||
|
plugin(),
|
||||||
|
],
|
||||||
|
}));
|
||||||
|
|
||||||
@ -0,0 +1,42 @@
|
|||||||
|
{
|
||||||
|
"name": "icejs3-demo-app",
|
||||||
|
"version": "0.1.5",
|
||||||
|
"description": "icejs 3 轻量级模板,使用 JavaScript,仅包含基础的 Layout。",
|
||||||
|
"dependencies": {
|
||||||
|
"moment": "^2.24.0",
|
||||||
|
"react": "^18.2.0",
|
||||||
|
"react-dom": "^18.2.0",
|
||||||
|
"react-router": "^6.9.0",
|
||||||
|
"react-router-dom": "^6.9.0",
|
||||||
|
"intl-messageformat": "^9.3.6",
|
||||||
|
"@alifd/next": "1.19.18",
|
||||||
|
"@ice/runtime": "^1.0.0",
|
||||||
|
"@alilc/lowcode-datasource-engine": "^1.0.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@ice/app": "^3.0.0",
|
||||||
|
"@types/react": "^18.0.0",
|
||||||
|
"@types/react-dom": "^18.0.0",
|
||||||
|
"@types/node": "^18.11.17",
|
||||||
|
"@ice/plugin-fusion": "^1.0.1",
|
||||||
|
"@ice/plugin-moment-locales": "^1.0.0",
|
||||||
|
"eslint": "^6.0.1",
|
||||||
|
"stylelint": "^13.2.0"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"start": "ice start",
|
||||||
|
"build": "ice build",
|
||||||
|
"lint": "npm run eslint && npm run stylelint",
|
||||||
|
"eslint": "eslint --cache --ext .js,.jsx ./",
|
||||||
|
"stylelint": "stylelint ./**/*.scss"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.0.0"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "http://gitlab.xxx.com/msd/leak-scan/tree/master"
|
||||||
|
},
|
||||||
|
"private": true,
|
||||||
|
"originTemplate": "@alifd/scaffold-lite-js"
|
||||||
|
}
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
import { defineAppConfig } from 'ice';
|
||||||
|
|
||||||
|
// App config, see https://v3.ice.work/docs/guide/basic/app
|
||||||
|
export default defineAppConfig(() => ({
|
||||||
|
// Set your configs here.
|
||||||
|
app: {
|
||||||
|
rootId: 'App',
|
||||||
|
},
|
||||||
|
router: {
|
||||||
|
type: 'browser',
|
||||||
|
basename: '/',
|
||||||
|
},
|
||||||
|
}));
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
const __$$constants = { ENV: 'prod', DOMAIN: 'xxx.xxx.com' };
|
||||||
|
|
||||||
|
export default __$$constants;
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Meta, Title, Links, Main, Scripts } from 'ice';
|
||||||
|
|
||||||
|
export default function Document() {
|
||||||
|
return (
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charSet="utf-8" />
|
||||||
|
<meta name="description" content="ice.js 3 lite scaffold" />
|
||||||
|
<link rel="icon" href="/favicon.ico" />
|
||||||
|
<link rel="stylesheet" href="//alifd.alicdn.com/npm/@alifd/next/1.21.16/next.min.css" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
|
||||||
|
<Meta />
|
||||||
|
<Title />
|
||||||
|
<Links />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<Main />
|
||||||
|
<script crossOrigin="anonymous" src="//g.alicdn.com/code/lib/react/18.2.0/umd/react.development.js" />
|
||||||
|
<script crossOrigin="anonymous" src="//g.alicdn.com/code/lib/react-dom/18.2.0/umd/react-dom.development.js" />
|
||||||
|
<script crossOrigin="anonymous" src="//g.alicdn.com/code/lib/??react-router/6.9.0/react-router.production.min.js,react-router-dom/6.9.0/react-router-dom.production.min.js" />
|
||||||
|
<script crossOrigin="anonymous" src="//alifd.alicdn.com/npm/@alifd/next/1.26.15/next.min.js" />
|
||||||
|
<script crossOrigin="anonymous" src="//g.alicdn.com/code/lib/prop-types/15.7.2/prop-types.js" />
|
||||||
|
<script crossOrigin="anonymous" src="//g.alicdn.com/platform/c/??lodash/4.6.1/lodash.min.js,immutable/3.7.6/dist/immutable.min.js" />
|
||||||
|
<Scripts />
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
// 引入默认全局样式
|
||||||
|
@import '@alifd/next/reset.scss';
|
||||||
|
|
||||||
|
body {
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
.table {
|
||||||
|
width: 100px;
|
||||||
|
}
|
||||||
@ -0,0 +1,86 @@
|
|||||||
|
const i18nConfig = {
|
||||||
|
'zh-CN': {
|
||||||
|
'i18n-jwg27yo4': '你好',
|
||||||
|
'i18n-jwg27yo3': '中国',
|
||||||
|
},
|
||||||
|
'en-US': {
|
||||||
|
'i18n-jwg27yo4': 'Hello',
|
||||||
|
'i18n-jwg27yo3': 'China',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let locale =
|
||||||
|
typeof navigator === 'object' && typeof navigator.language === 'string'
|
||||||
|
? navigator.language
|
||||||
|
: 'zh-CN';
|
||||||
|
|
||||||
|
const getLocale = () => locale;
|
||||||
|
|
||||||
|
const setLocale = (target) => {
|
||||||
|
locale = target;
|
||||||
|
};
|
||||||
|
|
||||||
|
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 fallback === undefined ? `${id}` : fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 其次用项目级别的
|
||||||
|
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,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export { getLocale, setLocale, i18n, i18nFormat, _inject2 };
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import styles from './index.module.scss';
|
||||||
|
|
||||||
|
export default function Footer() {
|
||||||
|
return (
|
||||||
|
<p className={styles.footer}>
|
||||||
|
<span className={styles.logo}>Alibaba Fusion</span>
|
||||||
|
<br />
|
||||||
|
<span className={styles.copyright}>© 2019-现在 Alibaba Fusion & ICE</span>
|
||||||
|
</p>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
.footer {
|
||||||
|
line-height: 20px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copyright {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import { Link } from 'ice';
|
||||||
|
import styles from './index.module.scss';
|
||||||
|
|
||||||
|
export default function Logo({ image, text, url }) {
|
||||||
|
return (
|
||||||
|
<div className="logo">
|
||||||
|
<Link to={url || '/'} className={styles.logo}>
|
||||||
|
{image && <img src={image} alt="logo" />}
|
||||||
|
<span>{text}</span>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
|
||||||
|
.logo{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
color: $color-text1-1;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 14px;
|
||||||
|
line-height: 22px;
|
||||||
|
|
||||||
|
&:visited, &:link {
|
||||||
|
color: $color-text1-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
height: 24px;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,68 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { Link, useLocation } from 'ice';
|
||||||
|
import { Nav } from '@alifd/next';
|
||||||
|
import { asideMenuConfig } from '../../menuConfig';
|
||||||
|
|
||||||
|
const { SubNav } = Nav;
|
||||||
|
const NavItem = Nav.Item;
|
||||||
|
|
||||||
|
function getNavMenuItems(menusData) {
|
||||||
|
if (!menusData) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return menusData
|
||||||
|
.filter(item => item.name && !item.hideInMenu)
|
||||||
|
.map((item, index) => getSubMenuOrItem(item, index));
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSubMenuOrItem(item, index) {
|
||||||
|
if (item.children && item.children.some(child => child.name)) {
|
||||||
|
const childrenItems = getNavMenuItems(item.children);
|
||||||
|
|
||||||
|
if (childrenItems && childrenItems.length > 0) {
|
||||||
|
const subNav = (
|
||||||
|
<SubNav key={index} icon={item.icon} label={item.name}>
|
||||||
|
{childrenItems}
|
||||||
|
</SubNav>
|
||||||
|
);
|
||||||
|
return subNav;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const navItem = (
|
||||||
|
<NavItem key={item.path} icon={item.icon}>
|
||||||
|
<Link to={item.path}>{item.name}</Link>
|
||||||
|
</NavItem>
|
||||||
|
);
|
||||||
|
return navItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Navigation = (props, context) => {
|
||||||
|
const location = useLocation();
|
||||||
|
const { pathname } = location;
|
||||||
|
const { isCollapse } = context;
|
||||||
|
return (
|
||||||
|
<Nav
|
||||||
|
type="primary"
|
||||||
|
selectedKeys={[pathname]}
|
||||||
|
defaultSelectedKeys={[pathname]}
|
||||||
|
embeddable
|
||||||
|
openMode="single"
|
||||||
|
iconOnly={isCollapse}
|
||||||
|
hasArrow={false}
|
||||||
|
mode={isCollapse ? 'popup' : 'inline'}
|
||||||
|
>
|
||||||
|
{getNavMenuItems(asideMenuConfig)}
|
||||||
|
</Nav>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
Navigation.contextTypes = {
|
||||||
|
isCollapse: PropTypes.bool,
|
||||||
|
};
|
||||||
|
export default Navigation;
|
||||||
|
|
||||||
@ -0,0 +1,81 @@
|
|||||||
|
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
import { Shell, ConfigProvider } from '@alifd/next';
|
||||||
|
import PageNav from './components/PageNav';
|
||||||
|
import Logo from './components/Logo';
|
||||||
|
import Footer from './components/Footer';
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
const throttle = function(type, name, obj = window) {
|
||||||
|
let running = false;
|
||||||
|
|
||||||
|
const func = () => {
|
||||||
|
if (running) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
running = true;
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
obj.dispatchEvent(new CustomEvent(name));
|
||||||
|
running = false;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
obj.addEventListener(type, func);
|
||||||
|
};
|
||||||
|
|
||||||
|
throttle('resize', 'optimizedResize');
|
||||||
|
})();
|
||||||
|
|
||||||
|
export default function BasicLayout({ children }) {
|
||||||
|
const getDevice = width => {
|
||||||
|
const isPhone =
|
||||||
|
typeof navigator !== 'undefined' && navigator && navigator.userAgent.match(/phone/gi);
|
||||||
|
|
||||||
|
if (width < 680 || isPhone) {
|
||||||
|
return 'phone';
|
||||||
|
}
|
||||||
|
if (width < 1280 && width > 680) {
|
||||||
|
return 'tablet';
|
||||||
|
}
|
||||||
|
return 'desktop';
|
||||||
|
};
|
||||||
|
|
||||||
|
const [device, setDevice] = useState(getDevice(NaN));
|
||||||
|
window.addEventListener('optimizedResize', e => {
|
||||||
|
setDevice(getDevice(e && e.target && e.target.innerWidth));
|
||||||
|
});
|
||||||
|
return (
|
||||||
|
<ConfigProvider device={device}>
|
||||||
|
<Shell
|
||||||
|
type="dark"
|
||||||
|
style={{
|
||||||
|
minHeight: '100vh',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Shell.Branding>
|
||||||
|
<Logo
|
||||||
|
image="https://img.alicdn.com/tfs/TB1.ZBecq67gK0jSZFHXXa9jVXa-904-826.png"
|
||||||
|
text="Logo"
|
||||||
|
/>
|
||||||
|
</Shell.Branding>
|
||||||
|
<Shell.Navigation
|
||||||
|
direction="hoz"
|
||||||
|
style={{
|
||||||
|
marginRight: 10,
|
||||||
|
}}
|
||||||
|
></Shell.Navigation>
|
||||||
|
<Shell.Action></Shell.Action>
|
||||||
|
<Shell.Navigation>
|
||||||
|
<PageNav />
|
||||||
|
</Shell.Navigation>
|
||||||
|
|
||||||
|
<Shell.Content>{children}</Shell.Content>
|
||||||
|
<Shell.Footer>
|
||||||
|
<Footer />
|
||||||
|
</Shell.Footer>
|
||||||
|
</Shell>
|
||||||
|
</ConfigProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
|
||||||
|
const headerMenuConfig = [];
|
||||||
|
const asideMenuConfig = [
|
||||||
|
{
|
||||||
|
name: 'Dashboard',
|
||||||
|
path: '/',
|
||||||
|
icon: 'smile',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
export { headerMenuConfig, asideMenuConfig };
|
||||||
|
|
||||||
@ -0,0 +1,119 @@
|
|||||||
|
// 注意: 出码引擎注入的临时变量默认都以 "__$$" 开头,禁止在搭建的代码中直接访问。
|
||||||
|
// 例外:react 框架的导出名和各种组件名除外。
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { Form, Input, NumberPicker, Select, Button } from '@alifd/next';
|
||||||
|
|
||||||
|
import utils, { RefsManager } from '../../utils';
|
||||||
|
|
||||||
|
import * as __$$i18n from '../../i18n';
|
||||||
|
|
||||||
|
import __$$constants from '../../constants';
|
||||||
|
|
||||||
|
import './index.css';
|
||||||
|
|
||||||
|
class Test$$Page extends React.Component {
|
||||||
|
_context = this;
|
||||||
|
|
||||||
|
get constants() {
|
||||||
|
return __$$constants || {};
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(props, context) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.utils = utils;
|
||||||
|
|
||||||
|
this._refsManager = new RefsManager();
|
||||||
|
|
||||||
|
__$$i18n._inject2(this);
|
||||||
|
|
||||||
|
this.state = { text: 'outter' };
|
||||||
|
}
|
||||||
|
|
||||||
|
$ = (refName) => {
|
||||||
|
return this._refsManager.get(refName);
|
||||||
|
};
|
||||||
|
|
||||||
|
$$ = (refName) => {
|
||||||
|
return this._refsManager.getAll(refName);
|
||||||
|
};
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
console.log('componentDidMount');
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const __$$context = this._context || this;
|
||||||
|
const { state } = __$$context;
|
||||||
|
return (
|
||||||
|
<div ref={this._refsManager.linkRef('outterView')} autoLoading={true}>
|
||||||
|
<Form
|
||||||
|
labelCol={__$$eval(() => this.state.colNum)}
|
||||||
|
style={{}}
|
||||||
|
ref={this._refsManager.linkRef('testForm')}
|
||||||
|
>
|
||||||
|
<Form.Item
|
||||||
|
label={__$$eval(() => this.i18n('i18n-jwg27yo4'))}
|
||||||
|
name="name"
|
||||||
|
initValue="李雷"
|
||||||
|
>
|
||||||
|
<Input placeholder="请输入" size="medium" style={{ width: 320 }} />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item label="年龄:" name="age" initValue="22">
|
||||||
|
<NumberPicker size="medium" type="normal" />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item label="职业:" name="profession">
|
||||||
|
<Select
|
||||||
|
dataSource={[
|
||||||
|
{ label: '教师', value: 't' },
|
||||||
|
{ label: '医生', value: 'd' },
|
||||||
|
{ label: '歌手', value: 's' },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
<div style={{ textAlign: 'center' }}>
|
||||||
|
<Button.Group>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
style={{ margin: '0 5px 0 5px' }}
|
||||||
|
htmlType="submit"
|
||||||
|
>
|
||||||
|
提交
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
type="normal"
|
||||||
|
style={{ margin: '0 5px 0 5px' }}
|
||||||
|
htmlType="reset"
|
||||||
|
>
|
||||||
|
重置
|
||||||
|
</Button>
|
||||||
|
</Button.Group>
|
||||||
|
</div>
|
||||||
|
</Form>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
...ext,
|
||||||
|
};
|
||||||
|
childContext.__proto__ = oldContext;
|
||||||
|
return childContext;
|
||||||
|
}
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
import { Outlet } from 'ice';
|
||||||
|
import BasicLayout from '@/layouts/BasicLayout';
|
||||||
|
|
||||||
|
export default function Layout() {
|
||||||
|
return (
|
||||||
|
<BasicLayout>
|
||||||
|
<Outlet />
|
||||||
|
</BasicLayout>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
/// <reference types="@ice/app/types" />
|
||||||
|
|
||||||
|
export {};
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
g_config: Record<string, any>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,47 @@
|
|||||||
|
import { createRef } from 'react';
|
||||||
|
|
||||||
|
export class RefsManager {
|
||||||
|
constructor() {
|
||||||
|
this.refInsStore = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
clearNullRefs() {
|
||||||
|
Object.keys(this.refInsStore).forEach((refName) => {
|
||||||
|
const filteredInsList = this.refInsStore[refName].filter(
|
||||||
|
(insRef) => !!insRef.current
|
||||||
|
);
|
||||||
|
if (filteredInsList.length > 0) {
|
||||||
|
this.refInsStore[refName] = filteredInsList;
|
||||||
|
} else {
|
||||||
|
delete this.refInsStore[refName];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
get(refName) {
|
||||||
|
this.clearNullRefs();
|
||||||
|
if (this.refInsStore[refName] && this.refInsStore[refName].length > 0) {
|
||||||
|
return this.refInsStore[refName][0].current;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
getAll(refName) {
|
||||||
|
this.clearNullRefs();
|
||||||
|
if (this.refInsStore[refName] && this.refInsStore[refName].length > 0) {
|
||||||
|
return this.refInsStore[refName].map((i) => i.current);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
linkRef(refName) {
|
||||||
|
const refIns = createRef();
|
||||||
|
this.refInsStore[refName] = this.refInsStore[refName] || [];
|
||||||
|
this.refInsStore[refName].push(refIns);
|
||||||
|
return refIns;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {};
|
||||||
256
modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo2/schema.json5
vendored
Normal file
256
modules/code-generator/tests/fixtures/test-cases/icejs3-app/demo2/schema.json5
vendored
Normal file
@ -0,0 +1,256 @@
|
|||||||
|
{
|
||||||
|
"version": "1.0.0",
|
||||||
|
"componentsMap": [
|
||||||
|
{
|
||||||
|
"componentName": "Button",
|
||||||
|
"package": "@alifd/next",
|
||||||
|
"version": "1.19.18",
|
||||||
|
"destructuring": true,
|
||||||
|
"exportName": "Button"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"componentName": "Button.Group",
|
||||||
|
"package": "@alifd/next",
|
||||||
|
"version": "1.19.18",
|
||||||
|
"destructuring": true,
|
||||||
|
"exportName": "Button",
|
||||||
|
"subName": "Group"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"componentName": "Input",
|
||||||
|
"package": "@alifd/next",
|
||||||
|
"version": "1.19.18",
|
||||||
|
"destructuring": true,
|
||||||
|
"exportName": "Input"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"componentName": "Form",
|
||||||
|
"package": "@alifd/next",
|
||||||
|
"version": "1.19.18",
|
||||||
|
"destructuring": true,
|
||||||
|
"exportName": "Form"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"componentName": "Form.Item",
|
||||||
|
"package": "@alifd/next",
|
||||||
|
"version": "1.19.18",
|
||||||
|
"destructuring": true,
|
||||||
|
"exportName": "Form",
|
||||||
|
"subName": "Item"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"componentName": "NumberPicker",
|
||||||
|
"package": "@alifd/next",
|
||||||
|
"version": "1.19.18",
|
||||||
|
"destructuring": true,
|
||||||
|
"exportName": "NumberPicker"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"componentName": "Select",
|
||||||
|
"package": "@alifd/next",
|
||||||
|
"version": "1.19.18",
|
||||||
|
"destructuring": true,
|
||||||
|
"exportName": "Select"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"componentsTree": [
|
||||||
|
{
|
||||||
|
"componentName": "Page",
|
||||||
|
"id": "node$1",
|
||||||
|
"meta": {
|
||||||
|
"title": "测试",
|
||||||
|
"router": "/"
|
||||||
|
},
|
||||||
|
"props": {
|
||||||
|
"ref": "outterView",
|
||||||
|
"autoLoading": true
|
||||||
|
},
|
||||||
|
"fileName": "test",
|
||||||
|
"state": {
|
||||||
|
"text": "outter"
|
||||||
|
},
|
||||||
|
"lifeCycles": {
|
||||||
|
"componentDidMount": {
|
||||||
|
"type": "JSFunction",
|
||||||
|
"value": "function() { console.log('componentDidMount'); }"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"componentName": "Form",
|
||||||
|
"id": "node$2",
|
||||||
|
"props": {
|
||||||
|
"labelCol": {
|
||||||
|
"type": "JSExpression",
|
||||||
|
"value": "this.state.colNum"
|
||||||
|
},
|
||||||
|
"style": {},
|
||||||
|
"ref": "testForm"
|
||||||
|
},
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"componentName": "Form.Item",
|
||||||
|
"id": "node$3",
|
||||||
|
"props": {
|
||||||
|
"label": {
|
||||||
|
type: 'JSExpression',
|
||||||
|
value: 'this.i18n("i18n-jwg27yo4")',
|
||||||
|
},
|
||||||
|
"name": "name",
|
||||||
|
"initValue": "李雷"
|
||||||
|
},
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"componentName": "Input",
|
||||||
|
"id": "node$4",
|
||||||
|
"props": {
|
||||||
|
"placeholder": "请输入",
|
||||||
|
"size": "medium",
|
||||||
|
"style": {
|
||||||
|
"width": 320
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"componentName": "Form.Item",
|
||||||
|
"id": "node$5",
|
||||||
|
"props": {
|
||||||
|
"label": "年龄:",
|
||||||
|
"name": "age",
|
||||||
|
"initValue": "22"
|
||||||
|
},
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"componentName": "NumberPicker",
|
||||||
|
"id": "node$6",
|
||||||
|
"props": {
|
||||||
|
"size": "medium",
|
||||||
|
"type": "normal"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"componentName": "Form.Item",
|
||||||
|
"id": "node$7",
|
||||||
|
"props": {
|
||||||
|
"label": "职业:",
|
||||||
|
"name": "profession"
|
||||||
|
},
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"componentName": "Select",
|
||||||
|
"id": "node$8",
|
||||||
|
"props": {
|
||||||
|
"dataSource": [
|
||||||
|
{
|
||||||
|
"label": "教师",
|
||||||
|
"value": "t"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "医生",
|
||||||
|
"value": "d"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "歌手",
|
||||||
|
"value": "s"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"componentName": "Div",
|
||||||
|
"id": "node$9",
|
||||||
|
"props": {
|
||||||
|
"style": {
|
||||||
|
"textAlign": "center"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"componentName": "Button.Group",
|
||||||
|
"id": "node$a",
|
||||||
|
"props": {},
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"componentName": "Button",
|
||||||
|
"id": "node$b",
|
||||||
|
"props": {
|
||||||
|
"type": "primary",
|
||||||
|
"style": {
|
||||||
|
"margin": "0 5px 0 5px"
|
||||||
|
},
|
||||||
|
"htmlType": "submit"
|
||||||
|
},
|
||||||
|
"children": [
|
||||||
|
"提交"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"componentName": "Button",
|
||||||
|
"id": "node$d",
|
||||||
|
"props": {
|
||||||
|
"type": "normal",
|
||||||
|
"style": {
|
||||||
|
"margin": "0 5px 0 5px"
|
||||||
|
},
|
||||||
|
"htmlType": "reset"
|
||||||
|
},
|
||||||
|
"children": [
|
||||||
|
"重置"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"constants": {
|
||||||
|
"ENV": "prod",
|
||||||
|
"DOMAIN": "xxx.xxx.com"
|
||||||
|
},
|
||||||
|
"i18n": {
|
||||||
|
"zh-CN": {
|
||||||
|
"i18n-jwg27yo4": "你好",
|
||||||
|
"i18n-jwg27yo3": "中国"
|
||||||
|
},
|
||||||
|
"en-US": {
|
||||||
|
"i18n-jwg27yo4": "Hello",
|
||||||
|
"i18n-jwg27yo3": "China"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"css": "body {font-size: 12px;} .table { width: 100px;}",
|
||||||
|
"config": {
|
||||||
|
"sdkVersion": "1.0.3",
|
||||||
|
"historyMode": "hash",
|
||||||
|
"targetRootID": "J_Container",
|
||||||
|
"layout": {
|
||||||
|
"componentName": "BasicLayout",
|
||||||
|
"props": {
|
||||||
|
"logo": "...",
|
||||||
|
"name": "测试网站"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"theme": {
|
||||||
|
"package": "@alife/theme-fusion",
|
||||||
|
"version": "^0.1.0",
|
||||||
|
"primary": "#ff9966"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"name": "demo应用",
|
||||||
|
"git_group": "appGroup",
|
||||||
|
"project_name": "app_demo",
|
||||||
|
"description": "这是一个测试应用",
|
||||||
|
"spma": "spa23d",
|
||||||
|
"creator": "月飞"
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
defaults
|
||||||
|
ios_saf 9
|
||||||
|
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
# See https://help.github.com/ignore-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# production
|
||||||
|
build/
|
||||||
|
dist/
|
||||||
|
tmp/
|
||||||
|
lib/
|
||||||
|
|
||||||
|
# misc
|
||||||
|
.idea/
|
||||||
|
.happypack
|
||||||
|
.DS_Store
|
||||||
|
*.swp
|
||||||
|
*.dia~
|
||||||
|
.ice
|
||||||
|
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
index.module.scss.d.ts
|
||||||
|
|
||||||
@ -0,0 +1 @@
|
|||||||
|
This project is generated by lowcode-code-generator & lowcode-solution-icejs3.
|
||||||
@ -0,0 +1,90 @@
|
|||||||
|
import { join } from 'path';
|
||||||
|
import { defineConfig } from '@ice/app';
|
||||||
|
import _ from 'lodash';
|
||||||
|
import fusion from '@ice/plugin-fusion';
|
||||||
|
import locales from '@ice/plugin-moment-locales';
|
||||||
|
import type { Plugin } from '@ice/app/esm/types';
|
||||||
|
|
||||||
|
interface PluginOptions {
|
||||||
|
id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const plugin: Plugin<PluginOptions> = (options) => ({
|
||||||
|
// name 可选,插件名称
|
||||||
|
name: 'plugin-name',
|
||||||
|
// setup 必选,用于定制工程构建配置
|
||||||
|
setup: ({ onGetConfig, modifyUserConfig }) => {
|
||||||
|
modifyUserConfig('codeSplitting', 'page');
|
||||||
|
|
||||||
|
onGetConfig((config) => {
|
||||||
|
config.entry = {
|
||||||
|
web: join(process.cwd(), '.ice/entry.client.tsx'),
|
||||||
|
};
|
||||||
|
|
||||||
|
config.cssFilename = '[name].css';
|
||||||
|
|
||||||
|
config.configureWebpack = config.configureWebpack || [];
|
||||||
|
config.configureWebpack?.push((webpackConfig) => {
|
||||||
|
if (webpackConfig.output) {
|
||||||
|
webpackConfig.output.filename = '[name].js';
|
||||||
|
webpackConfig.output.chunkFilename = '[name].js';
|
||||||
|
}
|
||||||
|
return webpackConfig;
|
||||||
|
});
|
||||||
|
|
||||||
|
config.swcOptions = _.merge(config.swcOptions, {
|
||||||
|
compilationConfig: {
|
||||||
|
jsc: {
|
||||||
|
transform: {
|
||||||
|
react: {
|
||||||
|
runtime: 'classic',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// 解决 webpack publicPath 问题
|
||||||
|
config.transforms = config.transforms || [];
|
||||||
|
config.transforms.push((source: string, id: string) => {
|
||||||
|
if (id.includes('.ice/entry.client.tsx')) {
|
||||||
|
let code = `
|
||||||
|
if (!__webpack_public_path__?.startsWith('http') && document.currentScript) {
|
||||||
|
// @ts-ignore
|
||||||
|
__webpack_public_path__ = document.currentScript.src.replace(/^(.*\\/)[^/]+$/, '$1');
|
||||||
|
window.__ICE_ASSETS_MANIFEST__ = window.__ICE_ASSETS_MANIFEST__ || {};
|
||||||
|
window.__ICE_ASSETS_MANIFEST__.publicPath = __webpack_public_path__;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
code += source;
|
||||||
|
return { code };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// The project config, see https://v3.ice.work/docs/guide/basic/config
|
||||||
|
const minify = process.env.NODE_ENV === 'production' ? 'swc' : false;
|
||||||
|
export default defineConfig(() => ({
|
||||||
|
ssr: false,
|
||||||
|
ssg: false,
|
||||||
|
minify,
|
||||||
|
|
||||||
|
externals: {
|
||||||
|
react: 'React',
|
||||||
|
'react-dom': 'ReactDOM',
|
||||||
|
'react-dom/client': 'ReactDOM',
|
||||||
|
'@alifd/next': 'Next',
|
||||||
|
lodash: 'var window._',
|
||||||
|
'@alilc/lowcode-engine': 'var window.AliLowCodeEngine',
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
fusion({
|
||||||
|
importStyle: true,
|
||||||
|
}),
|
||||||
|
locales(),
|
||||||
|
plugin(),
|
||||||
|
],
|
||||||
|
}));
|
||||||
|
|
||||||
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