修改了初始化的逻辑和模板

This commit is contained in:
Xu Chang 2024-06-27 18:38:02 +08:00
parent f076a0422f
commit 975154d82d
28 changed files with 105 additions and 492 deletions

View File

@ -25,16 +25,22 @@ const prompt = [
message: 'version', message: 'version',
default: '1.0.0', default: '1.0.0',
}, },
{
type: 'input',
name: 'title',
message: 'title of the project shown in App/Html'
},
{ {
type: 'input', type: 'input',
name: 'description', name: 'description',
message: 'description', message: 'description',
}, },
{
name: 'useOgb',
type: 'confirm',
message: 'add oak-general-business into dependency?',
default: true,
}, {
name: 'moreDeps',
type: 'input',
message: 'do you have more dependent oak-family libraries? type their names, use comma as separator.',
default: '',
}
]; ];
/** /**
* 将项目的依赖关系加入 * 将项目的依赖关系加入
@ -137,10 +143,16 @@ async function create(dirName, cmd) {
message: `name`, message: `name`,
default: dirName, default: dirName,
}; };
prompt.unshift(nameOption); const titleOption = {
type: 'input',
name: 'title',
message: 'title of the project shown in App/Html',
default: dirName,
};
prompt.unshift(nameOption, titleOption);
const isDev = cmd.dev ? true : false; const isDev = cmd.dev ? true : false;
const isModule = cmd.module ? true : false; const isModule = cmd.module ? true : false;
const { name, version, title, description } = await inquirer_1.default.prompt(prompt); const { name, version, title, description, useOgb, moreDeps } = await inquirer_1.default.prompt(prompt);
// 获取tsconfig.json内容 // 获取tsconfig.json内容
const tsconfigJson = (0, template_1.tsConfigJsonContent)(); const tsconfigJson = (0, template_1.tsConfigJsonContent)();
const tsConfigBuildJson = (0, template_1.tsConfigBuildJsonContent)(); const tsConfigBuildJson = (0, template_1.tsConfigBuildJsonContent)();
@ -197,27 +209,16 @@ async function create(dirName, cmd) {
(0, file_handle_1.copyFolder)(currentPath, rootPath); (0, file_handle_1.copyFolder)(currentPath, rootPath);
await createWechatMpBoilplate(weChatMpRootPath, isDev); await createWechatMpBoilplate(weChatMpRootPath, isDev);
await createWebBoilplate(webRootPath, isDev); await createWebBoilplate(webRootPath, isDev);
if (!shelljs_1.default.which('npm')) { /* if (!shell.which('npm')) {
(0, tip_style_1.Warn)((0, tip_style_1.warn)('Sorry, this script requires npm! Please install npm!')); Warn(warn('Sorry, this script requires npm! Please install npm!'));
shelljs_1.default.exit(1); shell.exit(1);
} }
/* Success(`${success(`Waiting...`)}`);
Success(`${success(`Waiting...`)}`);
Success(`${success(`Dependencies are now being installed`)}`); Success(`${success(`Dependencies are now being installed`)}`);
shell.cd(dirName).exec('npm install'); */ shell.cd(dirName).exec('npm install'); */
(0, rename_1.renameProject)(rootPath, name, title, DEFAULT_PROJECT_NAME, DEFAULT_PROJECT_TITLE);
} }
(0, tip_style_1.Success)(`${(0, tip_style_1.success)(`Successfully created project ${(0, tip_style_1.primary)(name)}, directory name is ${(0, tip_style_1.primary)(dirName)}`)}`); (0, tip_style_1.Success)(`${(0, tip_style_1.success)(`Successfully created project ${(0, tip_style_1.primary)(name)}, directory name is ${(0, tip_style_1.primary)(dirName)}`)}`);
const { useOgb, moreDeps } = await inquirer_1.default.prompt([{
name: 'useOgb',
type: 'confirm',
message: 'add oak-general-business into dependency?',
default: true,
}, {
name: 'moreDeps',
type: 'input',
message: 'do you have more dependent oak-family libraries? type their names, use comma as separator.',
default: '',
}]);
const deps = []; const deps = [];
if (useOgb) { if (useOgb) {
deps.push('oak-general-business'); deps.push('oak-general-business');
@ -242,6 +243,7 @@ async function create(dirName, cmd) {
}); });
// 创建package.json // 创建package.json
(0, file_handle_1.checkFileExistsAndCreate)(packageJsonPath, packageJson, enum_1.checkFileExistsAndCreateType.FILE); (0, file_handle_1.checkFileExistsAndCreate)(packageJsonPath, packageJson, enum_1.checkFileExistsAndCreateType.FILE);
(0, rename_1.renameProject)(rootPath, name, title, DEFAULT_PROJECT_NAME, DEFAULT_PROJECT_TITLE);
(0, tip_style_1.Success)(`${(0, tip_style_1.success)(`Ok, type 'npm install' to install libs, then start!`)}`); (0, tip_style_1.Success)(`${(0, tip_style_1.success)(`Ok, type 'npm install' to install libs, then start!`)}`);
} }
catch (err) { catch (err) {

2
lib/interface.d.ts vendored
View File

@ -23,6 +23,8 @@ export interface PromptInput {
version: string; version: string;
description: string; description: string;
title: string; title: string;
useOgb: boolean;
moreDeps: string;
} }
/** /**
* @name project.config.json * @name project.config.json

View File

@ -18,6 +18,11 @@ async function renameProject(dir, name, title, placeholderName, placeholderTitle
const htmlContent = (0, fs_1.readFileSync)(htmlFilePath, 'utf-8'); const htmlContent = (0, fs_1.readFileSync)(htmlFilePath, 'utf-8');
const newHtmlContent = htmlContent.replace(new RegExp(placeholderTitle, 'g'), title).replace(new RegExp(placeholderTitle.toLowerCase(), 'g'), title.toLowerCase()); const newHtmlContent = htmlContent.replace(new RegExp(placeholderTitle, 'g'), title).replace(new RegExp(placeholderTitle.toLowerCase(), 'g'), title.toLowerCase());
(0, fs_1.writeFileSync)(htmlFilePath, newHtmlContent, 'utf-8'); (0, fs_1.writeFileSync)(htmlFilePath, newHtmlContent, 'utf-8');
// index.tsx下的title
const indexTsxPath = (0, path_1.join)(dir, 'web', 'src/index.tsx');
const tsxContent = (0, fs_1.readFileSync)(indexTsxPath, 'utf-8');
const newTsxlContent = tsxContent.replace(new RegExp(placeholderName, 'g'), name).replace(new RegExp(placeholderName.toLowerCase(), 'g'), name.toLowerCase());
(0, fs_1.writeFileSync)(indexTsxPath, newTsxlContent, 'utf-8');
// replace wechatMp下project.config.json中的projectname // replace wechatMp下project.config.json中的projectname
// todo现在这个是在wechatMp/src目录下的可能是搞错了待修正 // todo现在这个是在wechatMp/src目录下的可能是搞错了待修正
const pcjFilePath = (0, path_1.join)(dir, 'wechatMp', 'src', 'project.config.json'); const pcjFilePath = (0, path_1.join)(dir, 'wechatMp', 'src', 'project.config.json');

View File

@ -56,16 +56,22 @@ const prompt = [
message: 'version', message: 'version',
default: '1.0.0', default: '1.0.0',
}, },
{
type: 'input',
name: 'title',
message: 'title of the project shown in App/Html'
},
{ {
type: 'input', type: 'input',
name: 'description', name: 'description',
message: 'description', message: 'description',
}, },
{
name: 'useOgb',
type: 'confirm',
message: 'add oak-general-business into dependency?',
default: true,
}, {
name: 'moreDeps',
type: 'input',
message: 'do you have more dependent oak-family libraries? type their names, use comma as separator.',
default: '',
}
]; ];
/** /**
@ -220,11 +226,17 @@ export async function create(dirName: string, cmd: any) {
message: `name`, message: `name`,
default: dirName, default: dirName,
}; };
prompt.unshift(nameOption); const titleOption = {
type: 'input',
name: 'title',
message: 'title of the project shown in App/Html',
default: dirName,
};
prompt.unshift(nameOption, titleOption);
const isDev = cmd.dev ? true : false; const isDev = cmd.dev ? true : false;
const isModule = cmd.module ? true : false; const isModule = cmd.module ? true : false;
const { name, version, title, description }: PromptInput = await inquirer.prompt( const { name, version, title, description, useOgb, moreDeps }: PromptInput = await inquirer.prompt(
prompt prompt
); );
@ -311,19 +323,16 @@ export async function create(dirName: string, cmd: any) {
await createWechatMpBoilplate(weChatMpRootPath, isDev); await createWechatMpBoilplate(weChatMpRootPath, isDev);
await createWebBoilplate(webRootPath, isDev); await createWebBoilplate(webRootPath, isDev);
if (!shell.which('npm')) { /* if (!shell.which('npm')) {
Warn(warn('Sorry, this script requires npm! Please install npm!')); Warn(warn('Sorry, this script requires npm! Please install npm!'));
shell.exit(1); shell.exit(1);
} }
/* Success(`${success(`Waiting...`)}`); Success(`${success(`Waiting...`)}`);
Success(`${success(`Dependencies are now being installed`)}`); Success(`${success(`Dependencies are now being installed`)}`);
shell.cd(dirName).exec('npm install'); */ shell.cd(dirName).exec('npm install'); */
renameProject(rootPath, name, title, DEFAULT_PROJECT_NAME, DEFAULT_PROJECT_TITLE);
} }
Success( Success(
`${success( `${success(
`Successfully created project ${primary( `Successfully created project ${primary(
@ -332,17 +341,6 @@ export async function create(dirName: string, cmd: any) {
)}` )}`
); );
const { useOgb, moreDeps } = await inquirer.prompt([{
name: 'useOgb',
type: 'confirm',
message: 'add oak-general-business into dependency?',
default: true,
}, {
name: 'moreDeps',
type: 'input',
message: 'do you have more dependent oak-family libraries? type their names, use comma as separator.',
default: '',
}]);
const deps = [] as string[]; const deps = [] as string[];
if (useOgb) { if (useOgb) {
deps.push('oak-general-business'); deps.push('oak-general-business');
@ -381,6 +379,7 @@ export async function create(dirName: string, cmd: any) {
checkFileExistsAndCreateType.FILE checkFileExistsAndCreateType.FILE
); );
renameProject(rootPath, name, title, DEFAULT_PROJECT_NAME, DEFAULT_PROJECT_TITLE);
Success( Success(
`${success( `${success(
`Ok, type 'npm install' to install libs, then start!` `Ok, type 'npm install' to install libs, then start!`

View File

@ -26,6 +26,8 @@ export interface PromptInput {
version: string, version: string,
description: string, description: string,
title: string, title: string,
useOgb: boolean;
moreDeps: string;
} }
/** /**

View File

@ -26,6 +26,12 @@ export async function renameProject(dir: string, name: string, title: string, pl
const newHtmlContent = htmlContent.replace(new RegExp(placeholderTitle, 'g'), title).replace(new RegExp(placeholderTitle.toLowerCase(), 'g'), title.toLowerCase()); const newHtmlContent = htmlContent.replace(new RegExp(placeholderTitle, 'g'), title).replace(new RegExp(placeholderTitle.toLowerCase(), 'g'), title.toLowerCase());
writeFileSync(htmlFilePath, newHtmlContent, 'utf-8'); writeFileSync(htmlFilePath, newHtmlContent, 'utf-8');
// index.tsx下的title
const indexTsxPath = join(dir, 'web', 'src/index.tsx');
const tsxContent = readFileSync(indexTsxPath, 'utf-8');
const newTsxlContent = tsxContent.replace(new RegExp(placeholderName, 'g'), name).replace(new RegExp(placeholderName.toLowerCase(), 'g'), name.toLowerCase());
writeFileSync(indexTsxPath, newTsxlContent, 'utf-8');
// replace wechatMp下project.config.json中的projectname // replace wechatMp下project.config.json中的projectname
// todo现在这个是在wechatMp/src目录下的可能是搞错了待修正 // todo现在这个是在wechatMp/src目录下的可能是搞错了待修正
const pcjFilePath = join(dir, 'wechatMp', 'src', 'project.config.json'); const pcjFilePath = join(dir, 'wechatMp', 'src', 'project.config.json');

View File

@ -1,12 +0,0 @@
import { EntityDict } from '@project/oak-app-domain';
import { RuntimeContext } from './RuntimeContext';
import { BackendRuntimeContext as DependentBackendRuntimeContext } from './DependentContext';
export class BackendRuntimeContext extends DependentBackendRuntimeContext<EntityDict> implements RuntimeContext {
async toString() {
const data = await this.getSerializedData();
return JSON.stringify(data);
}
};
export default BackendRuntimeContext;

View File

@ -1,17 +0,0 @@
import { EntityDict } from '@project/oak-app-domain';
import {
FrontendRuntimeContext as DependentFrontendRuntimeContext,
} from './DependentContext';
import { RuntimeContext } from './RuntimeContext';
export class FrontendRuntimeContext
extends DependentFrontendRuntimeContext<EntityDict>
implements RuntimeContext
{
async toString() {
const data = await this.getSerializedData();
return JSON.stringify(data);
}
}
export default FrontendRuntimeContext;

View File

@ -1,4 +1,4 @@
import initialize from './initialize.dev'; import initialize from './initialize.frontend';
export default initialize; export default initialize;
console.log('不应该走到这里'); console.log('不应该走到这里');

View File

@ -81,7 +81,7 @@
work correctly both with client-side routing and a non-root public URL. work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`. Learn how to configure a non-root public URL by running `npm run build`.
--> -->
<title></title> <title>oak template project</title>
</head> </head>
<body> <body>

View File

@ -1 +0,0 @@
@import '@project/config/styles/web/index.less'; // 少量公共样式

View File

@ -1,19 +0,0 @@
import React from 'react';
import './App.less';
import AppContainer from './AppContainer';
import AppRouter from './AppRouter';
import AppError from './AppError';
function App(props: { error?: any }) {
if (props.error) {
return <AppError error={props.error} />;
}
return (
<AppContainer>
<AppRouter />
</AppContainer>
);
}
export default App;

View File

@ -1,24 +0,0 @@
import React, { lazy } from 'react';
const Message = lazy(() => import('oak-frontend-base/es/components/message'));
const DebugPanel = lazy(() => import('oak-frontend-base/es/components/func/debugPanel'));
type AppContainerProps = {
children?: React.ReactNode;
};
const AppContainer = (props: AppContainerProps) => {
const { children } = props;
return (
<React.Fragment>
<React.Suspense fallback={<></>}>
<Message />
</React.Suspense>
{children}
<React.Suspense fallback={<></>}>
{process.env.NODE_ENV === 'development' && <DebugPanel />}
</React.Suspense>
</React.Fragment>
);
};
export default AppContainer;

View File

@ -1,121 +0,0 @@
import React, { lazy } from 'react';
import { Button, Space } from 'antd';
import {
OakException,
OakExternalException,
OakNetworkException,
OakServerProxyException,
} from 'oak-domain/lib/types/Exception';
import { ECode } from 'oak-frontend-base/es/types/ErrorPage';
const ErrorPage = lazy(() => import('oak-frontend-base/es/components/errorPage'));
interface ErrorProps {
error: any;
}
function Error(props: ErrorProps) {
const { error } = props;
if (error instanceof OakException) {
if (error instanceof OakNetworkException) {
// 网络中断出现的异常
return (
<ErrorPage
code={ECode.error}
title="网络异常"
desc="抱歉,网络访问失败!"
>
<ErrorMessage error={error} />
<Button
type="primary"
onClick={async () => {
window.location.reload();
}}
>
</Button>
</ErrorPage>
);
}
if (error instanceof OakServerProxyException) {
// 服务器代理异常
return (
<ErrorPage
code={ECode.error}
title="服务器代理异常"
desc="抱歉,服务器代理出现错误!"
>
<ErrorMessage error={error} />
<Button
type="primary"
onClick={async () => {
window.location.reload();
}}
>
</Button>
</ErrorPage>
);
}
return (
<ErrorPage
code={ECode.error}
title="系统内部错误"
desc="抱歉,系统内部错误,我们的技术人员正在快马加鞭的修复"
>
<ErrorMessage error={error} />
<Button
type="primary"
onClick={async () => {
window.location.reload();
}}
>
</Button>
</ErrorPage>
);
}
return (
<ErrorPage
code={ECode.error}
title="数据缓存失效"
desc="抱歉,数据缓存失效,需要清除缓存,请点击【清除缓存】"
>
<ErrorMessage error={error} />
<Button
type="primary"
onClick={async () => {
(global as any).features.localStorage.clear();
window.location.reload();
}}
>
</Button>
</ErrorPage>
);
}
function ErrorMessage(props: { error: any }) {
const { error } = props;
if (process.env.NODE_ENV === 'development') {
return (
<span
style={{
marginBottom: 24,
color: 'red',
fontSize: 14,
marginLeft: 24,
marginRight: 24,
}}
>
{typeof error === 'object' ? error.message : error}
</span>
);
}
return null;
}
export default Error;

View File

@ -1,99 +0,0 @@
import React from 'react';
import { Routes, Route, Outlet, useLocation } from 'react-router-dom';
import { IRouter, IBrowserRouterProps, IMeta } from './types/router';
import routers from './app/routers';
import Loading from './app/components/Loading';
import useFeatures from '@project/hooks/useFeatures';
type TRenderRoutes = (
routes?: IRouter[],
breadcrumbs?: string[]
) => React.ReactNode[] | null;
/**
*
* @param routes
* @param breadcrumb
*/
const renderRoutes: TRenderRoutes = (routes = [], breadcrumb = []) => {
if (routes.length === 0) return null;
return routes.map((route, index: number) => {
const { Component, children, namespace, meta, isFirst, customRouter } =
route;
let currentBreadcrumb = breadcrumb;
let props = {};
if (isFirst) {
props = {
index: true,
};
} else {
props = {
path: route.path,
};
}
return (
<Route
{...props}
key={index}
element={
<Guard
Component={Component}
meta={meta}
breadcrumb={currentBreadcrumb}
namespace={namespace}
customRouter={customRouter}
/>
}
>
{renderRoutes(children, currentBreadcrumb)}
</Route>
);
});
};
const Guard = React.memo(
(props: {
Component?: React.FC<IBrowserRouterProps> | (() => any);
namespace?: string;
meta?: IMeta;
breadcrumb: string[];
customRouter?: boolean;
}) => {
const { Component, namespace, meta, breadcrumb, customRouter } = props;
const features = useFeatures();
const location = useLocation();
const { pathname } = location;
const path = namespace ? pathname.slice(namespace.length) : pathname;
const i18nNs = `taicang-p-${
path.startsWith('/')
? path.slice(1).replaceAll(/\//g, '-')
: path.replaceAll(/\//g, '-')
}`;
if (i18nNs) {
const windowTitle = features.locales.hasKey(`${i18nNs}.pageTitle`);
if (windowTitle) {
breadcrumb.push(windowTitle);
window.document.title = windowTitle;
}
}
return Component ? (
<React.Suspense fallback={<Loading />}>
<Component
oakDisablePulldownRefresh={meta?.oakDisablePulldownRefresh}
namespace={namespace || ''}
customRouter={customRouter}
/>
</React.Suspense>
) : (
<Outlet />
);
}
);
const AppRouter = React.memo(() => (
<Routes>{renderRoutes(routers)}</Routes>
));
export default AppRouter;

View File

@ -1,3 +1,5 @@
@import '@project/config/styles/web/index.less'; // 少量公共样式
body { body {
margin: 0; margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',

View File

@ -1,26 +1,12 @@
import './utils/polyfill';
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom/client'; import { EntityDict } from '@project/oak-app-domain';
import { createBrowserHistory } from 'history';
import { unstable_HistoryRouter as HistoryRouter } from 'react-router-dom';
import { ConfigProvider } from 'antd';
import { StyleProvider, legacyLogicalPropertiesTransformer } from '@ant-design/cssinjs';
import dayjs from 'dayjs';
import 'dayjs/locale/zh-cn';
import zhCN from 'antd/locale/zh_CN';
import {
ResponsiveProvider,
FeaturesProvider,
} from 'oak-frontend-base/es/platforms/web';
import './index.less'; import './index.less';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { handler as exceptionHandler } from '@project/exceptionHandler'; import { handler as exceptionHandler } from '@project/exceptionHandler';
import initializeFeatures from '@project/initializeFeatures'; import initializeFeatures from '@project/initializeFeatures';
import initialize from 'oak-frontend-base/es/platforms/web/initialize';
import routers from './app/routers';
import { features } from './initialize'; import { features } from './initialize';
dayjs.locale('zh-cn');
window.addEventListener('unhandledrejection', async (event) => { window.addEventListener('unhandledrejection', async (event) => {
// 全局捕获异常处理 // 全局捕获异常处理
@ -31,13 +17,6 @@ window.addEventListener('unhandledrejection', async (event) => {
} }
}); });
const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement
);
const history = createBrowserHistory();
features.navigator.setHistory(history);
const init = async () => { const init = async () => {
let error; let error;
try { try {
@ -45,33 +24,8 @@ const init = async () => {
} catch (err) { } catch (err) {
error = err; error = err;
} }
// 抓到异常处理 1、token过期 2、网络断了 3、接口请求失败
root.render(
<HistoryRouter history={history as any}>
<ResponsiveProvider>
<FeaturesProvider features={features as any}>
<ConfigProvider
locale={zhCN}
>
<StyleProvider initialize<EntityDict>(features, 'oak_template', routers, undefined, error);
hashPriority="high"
transformers={[
legacyLogicalPropertiesTransformer,
]}
>
<App error={error} />
</StyleProvider>
</ConfigProvider>
</FeaturesProvider>
</ResponsiveProvider>
</HistoryRouter>
);
}; };
init(); init();
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3"><g fill="#61DAFB"><path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/><circle cx="420.9" cy="296.5" r="45.7"/><path d="M520.5 78.1z"/></g></svg>

Before

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -1,15 +0,0 @@
import { ReportHandler } from 'web-vitals';
const reportWebVitals = (onPerfEntry?: ReportHandler) => {
if (onPerfEntry && onPerfEntry instanceof Function) {
import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
getCLS(onPerfEntry);
getFID(onPerfEntry);
getFCP(onPerfEntry);
getLCP(onPerfEntry);
getTTFB(onPerfEntry);
});
}
};
export default reportWebVitals;

View File

@ -1,5 +0,0 @@
// jest-dom adds custom jest matchers for asserting on DOM nodes.
// allows you to do things like:
// expect(element).toHaveTextContent(/react/i)
// learn more: https://github.com/testing-library/jest-dom
import '@testing-library/jest-dom';

View File

@ -1,51 +0,0 @@
import { BrowserRouterProps } from 'react-router-dom';
export interface IBrowserRouterProps extends BrowserRouterProps {
namespace: string;
oakDisablePulldownRefresh?: boolean;
navigationBarTitleText?: string;
customRouter?: boolean; //表示自定义路由
}
export type IMeta = {
navigationBarTitleText?: string;
Icon?: React.FC;
oakDisablePulldownRefresh?: boolean;
}
export interface IRouter {
path: string;
/**
*
*/
isFirst?: boolean;
namespace?: string;
customRouter?: boolean; //表示自定义路由
Component?: React.FC<IBrowserRouterProps> | (() => any);
/**
*
*/
isFullPage?: boolean;
/**
* meta
*/
meta?: IMeta;
children?: IRouter[];
}
// 文件path
type FilePath = string;
// 路由path 如果不传 就直接 文件Path当作路由path
type RoutePath = string | undefined | null;
// 设置根路由
type IsFirst = boolean;
// 项目路径别名
export type Project = '@project';
// [项目别名, 文件path[嵌套路由顶层path],设置根路由, 路由path]
export type Page<T> = [Project, FilePath, Array<T>?, IsFirst?, RoutePath?];

View File

@ -1,6 +0,0 @@
export function getAppType() {
if (/MicroMessenger/i.test(window.navigator.userAgent)) {
return 'wechatPublic';
}
return 'web';
}

View File

@ -1,15 +0,0 @@
Object.assign(global, {
fetch: fetch,
getRandomValues: async function getRandomValues(length: number) {
if (length > 65536) {
throw new Error('Can only request a maximum of 65536 bytes');
}
const randomValues = window.crypto.getRandomValues(
new Uint8Array(length)
);
return new Uint8Array(randomValues);
},
});

View File

@ -0,0 +1,11 @@
import { EntityDict } from '@project/oak-app-domain';
import { RuntimeContext } from './RuntimeContext';
export class BackendRuntimeContext extends BaseBackendRuntimeContext<EntityDict> implements RuntimeContext {
async toString() {
const data = await this.getSerializedData();
return JSON.stringify(data);
}
};
export default BackendRuntimeContext;

View File

@ -0,0 +1,11 @@
import { EntityDict } from '@project/oak-app-domain';
import { RuntimeContext } from './RuntimeContext';
export class FrontendRuntimeContext extends BaseFrontendRuntimeContext<EntityDict> implements RuntimeContext {
async toString() {
const data = await this.getSerializedData();
return JSON.stringify(data);
}
}
export default FrontendRuntimeContext;

View File

@ -29,8 +29,7 @@ export default function initialize() {
totalData = mergeConcatMany([data] as Array<typeof data>)!, totalData = mergeConcatMany([data] as Array<typeof data>)!,
totalImportations = mergeConcatMany([importations] as Array<typeof importations>)!, totalImportations = mergeConcatMany([importations] as Array<typeof importations>)!,
totalExportations = mergeConcatMany([exportations] as Array<typeof exportations>)!, totalExportations = mergeConcatMany([exportations] as Array<typeof exportations>)!,
totalCommon = mergeConcatMany([common] as Array<typeof common>)!, totalCommon = mergeConcatMany([common] as Array<typeof common>)!;
totalRender = mergeConcatMany([render] as Array<typeof render>)!;
const debugConnector = new DebugConnector<EntityDict, BackendRuntimeContext, FrontendRuntimeContext>( const debugConnector = new DebugConnector<EntityDict, BackendRuntimeContext, FrontendRuntimeContext>(
storageSchema, storageSchema,
@ -48,13 +47,14 @@ export default function initialize() {
); );
const totalFeatures = {} as FeatureDict & BasicFeatures<EntityDict>; const totalFeatures = {} as FeatureDict & BasicFeatures<EntityDict>;
// @ts-ignore
const { features } = initFrontend<EntityDict, BackendRuntimeContext, FrontendRuntimeContext>( const { features } = initFrontend<EntityDict, BackendRuntimeContext, FrontendRuntimeContext>(
storageSchema, storageSchema,
(store) => new FrontendRuntimeContext(store, totalFeatures), (store) => new FrontendRuntimeContext(store, totalFeatures),
debugConnector, debugConnector,
totalCheckers, totalCheckers,
totalCommon, totalCommon,
totalRender render
); );
Object.assign(totalFeatures, features); Object.assign(totalFeatures, features);

View File

@ -24,6 +24,7 @@ export default function initialize() {
totalRender = mergeConcatMany([render] as Array<typeof render>)!; totalRender = mergeConcatMany([render] as Array<typeof render>)!;
const totalFeatures = {} as FeatureDict & BasicFeatures<EntityDict>; const totalFeatures = {} as FeatureDict & BasicFeatures<EntityDict>;
// @ts-ignore
const { features } = initFrontend<EntityDict, BackendRuntimeContext, FrontendRuntimeContext>( const { features } = initFrontend<EntityDict, BackendRuntimeContext, FrontendRuntimeContext>(
storageSchema, storageSchema,
(store) => new FrontendRuntimeContext(store, totalFeatures), (store) => new FrontendRuntimeContext(store, totalFeatures),

View File

@ -2,7 +2,11 @@ import { FeatureDict } from '@project/features';
import { BasicFeatures } from 'oak-frontend-base/es/features'; import { BasicFeatures } from 'oak-frontend-base/es/features';
import { EntityDict } from '@project/oak-app-domain'; import { EntityDict } from '@project/oak-app-domain';
/**
* Initialize your features when app loads.
* If you use the oak-general-business, then remember to call the initial function in "oak-general-business/es/features/index".
* @param features
*/
export default async function initialize(features: FeatureDict & BasicFeatures<EntityDict>) { export default async function initialize(features: FeatureDict & BasicFeatures<EntityDict>) {
// 项目自己的features如果有初始化写在这里
} }