jamis
Version:
一种支持通过JSON配置方式生成页面的组件库
352 lines (351 loc) • 10 kB
TypeScript
import type { ActionObject, BaseSchemaScoped, BaseSchemaWithoutType, ReactPropsBase, RendererProps, SchemaBoolean, SchemaClassName, SchemaExpression } from 'jamis-core';
import type { CSSProperties, ReactNode } from 'react';
import type React from 'react';
import type { Location } from 'history';
import type { SchemaApi, SchemaCollection, SchemaObject, TourConfig } from '../types';
import type { IAppStore } from './AppStore';
export interface RouterHook {
/**
* 检查是否拦截, `true`表示要拦截, 执行failback逻辑; `false`代表放过
*/
checkExpression: SchemaBoolean;
/** 拦截后发起的动作 */
failbackAction?: ActionObject | ActionObject[];
/**
* 是否停止渲染路由的schema, 默认是 true.
* 当你配置了failbackAction, 而没有配置 failbackSchema时, 阻止schema的渲染
*/
stopRender?: boolean;
/** 拦截后使用的schema */
failbackSchema?: SchemaObject;
}
export interface AppRouter {
/**
* 菜单文字
*/
label?: string;
/**
* 菜单图标,比如: FileOutlined
*/
icon?: string;
/**
* 路由规则, 比如:/banner/:id。当地址以 / 打头,则不继承上层的路径,否则将集成父级页面的路径。
* 也可以是外部链接
*/
url?: string;
/**
* 单纯的地址。可以设置外部链接。
*/
link?: string;
/**
* 当url或者link是绝对地址时, 设置打开策略
*/
target?: '_self' | '_blank' | '_parent' | '_top';
/**
* 当match url 时跳转到目标地址.没有配置 schema 和 shcemaApi 时有效.
*/
redirect?: string;
/**
* 当match url 转成渲染目标地址的页面.没有配置 schema 和 shcemaApi 时有效.
*/
rewrite?: string;
/**
* 不要出现多个,如果出现多个只有第一个有用。在路由找不到的时候作为默认页面。
*/
isDefaultPage?: boolean;
/**
* 二选一,如果配置了 url 一定要配置。否则不知道如何渲染。
*/
schema?: SchemaCollection;
schemaApi?: SchemaApi;
/**
* 页面schema提供者, 和前面的schema/schemaApi互斥, 优先级从前往后
* @deprecated 请使用`schemaApi.fetcherProvider`来替代
*/
schemaProvider?: (data: JSObject, store: IAppStore) => Promise<SchemaCollection>;
/**
* 是否嵌套在父路由里
*/
nested?: boolean;
/**
* 支持多层级。
*/
children?: Array<AppRouter>;
/** 是否默认展开, 只对有非叶子节点有效, 默认不展开 */
initialOpen?: boolean;
/**
* 菜单上的类名
*/
className?: SchemaClassName;
/**
* 是否在导航中可见,适合于那种需要携带参数才显示的页面。比如具体某个数据的编辑页面。
*/
visible?: boolean;
/**
* 默认是自动,即:自己选中或者有孩子节点选中则展开。
* 如果配置成 always 或者配置成 true 则永远展开。
* 如果配置成 false 则永远不展开。
*/
/** 内部使用, 不可在schema里使用, 使用`url` */
path?: string;
/** 内部使用, 暂时似乎无用 */
index?: number;
/** 路由唯一id, 未指定时使用guid */
id?: string;
/**
* 路由的hooks配置
*/
hooks?: Record<'beforeEnter', RouterHook | RouterHook[]>;
/**
* 运行后有效的beforeEnter hook
*/
__activeHookBeforeEnter?: RouterHook;
[key: string]: any;
}
/**
* @deprecated 请使用 AppRouter 替代
*/
export type AppPage = AppRouter;
/**
* App 渲染器,适合 JSSDK 用来做多页渲染。
*
*/
export interface AppSchema extends BaseSchemaScoped {
/**
* 指定为 app 类型。
*/
type: 'app';
api?: SchemaApi;
/**
* 系统名称
*/
brandName?: SchemaCollection;
/**
* brand的样式类名
*/
brandClassName?: SchemaClassName;
/**
* brand点击跳转的url
*/
brandLink?: string;
brankLinkClassName?: SchemaClassName;
/**
* logo 图片地址,可以是 svg。
*/
logo?: string;
/**
* 顶部区域
*/
header?: SchemaCollection;
/**
* 元素`.cxd-Layout-header`的样式类
*/
headerClassName?: SchemaClassName;
headerBarClassName?: SchemaClassName;
/**
* 内容区(包括aside)样式类名
*/
contentClassName?: SchemaClassName;
contentStyle?: React.CSSProperties;
/**
* 内容体部分(不包括aside)样式类名
*/
bodyClassName?: SchemaClassName;
bodyStyle?: React.CSSProperties;
/**
* 边栏
*/
aside?: {
/**
* 是否展示
*/
visible?: SchemaBoolean;
visibleOn?: SchemaExpression;
/**
* 边栏菜单前面的区域
*/
beforeRegion?: SchemaCollection;
/**
* 边栏菜单后面的区域
*/
afterRegion?: SchemaCollection;
/**
* 边栏菜单的样式类
*/
className?: SchemaClassName;
style?: CSSProperties;
navClassName?: SchemaClassName;
navStyle?: CSSProperties;
/**
* 子菜单列表样式类
*/
subListClassName?: SchemaClassName;
/**
* 边栏菜单项的样式类
*/
linkClassName?: SchemaClassName;
/**
* 是否显示收起/展开按钮, 默认是 true
*/
showFoldBtn?: boolean;
foldBtnClassName?: SchemaClassName;
};
/**
* 页面集合。
*/
pages?: Array<AppRouter> | AppRouter;
/**
* 所有路由页面的公共样式类
*/
pageClassName?: SchemaClassName;
/**
* 所有路由页面的公共样式
*/
pageStyle?: CSSProperties;
/**
* 底部区域。
*/
footer?: SchemaCollection;
footerClassName?: SchemaClassName;
/**
* css 类名。
*/
className?: SchemaClassName;
/**
* 显示面包屑路径。
*/
showBreadcrumb?: boolean;
showBreadcrumbOn?: SchemaExpression;
/**
* 显示面包屑完整路径。
*/
showFullBreadcrumbPath?: boolean;
showFullBreadcrumbPathOn?: SchemaBoolean;
/**
* 显示面包屑首页路径。
*/
showBreadcrumbHomePath?: boolean;
showBreadcrumbHomePathOn?: boolean;
breadcrumbClassName?: SchemaClassName;
/**
* 父路由只是展开, 不去跳转
*/
parentToggleExpand?: boolean;
/**
* 控制是否显示菊花
*/
showLoading?: boolean;
showLoadingOn?: SchemaExpression;
/**
* 移动端下的左右抽屉的样式类
*/
navDrawerClassName?: SchemaClassName;
/**
* 移动端下的左右抽屉内容区的样式类
*/
navDrawerContentClassName?: SchemaClassName;
tour?: boolean;
tourOn?: SchemaBoolean;
tourConfig?: TourConfig;
}
/**
* 路由占位组件
*/
export interface AppRouterSchema extends BaseSchemaWithoutType {
type: 'app-router';
routerId: string;
}
export interface AppProps extends RendererProps, Omit<AppSchema, 'type' | 'className' | 'data'> {
children?: JSX.Element | ((props?: any) => JSX.Element);
store: IAppStore;
headerClassName?: string;
contentClassName?: string;
bodyClassName?: string;
breadcrumbClassName?: string;
footerClassName?: string;
pageClassName?: string;
aside: Required<AppSchema>['aside'];
location?: Location;
}
export interface AppRouterProps extends RendererProps, AppRouterSchema {
routerId: string;
}
export interface AsideNavProps extends ReactPropsBase {
id?: string;
subListClassName?: SchemaClassName;
/** 是否收缩起来 */
folded?: boolean;
navigations: Array<NavigationObject>;
/**
* 父路由是否可以展开/收起
*/
expandable?: boolean;
/**
* 父路由初始展开层级
*/
expandInitialLevel?: number;
renderLink: (item: {
link: LinkItem;
key: string | number;
toggleExpand?: (link: LinkItem, e?: React.MouseEvent) => void;
depth?: number;
}) => ReactNode;
/**
* 是否选中
*/
checkIsActive: (link: LinkItem) => boolean | undefined;
checkIsOpen: (link: LinkItem) => boolean;
}
export interface AsideNavLinkProps {
folded?: boolean;
link: LinkItem;
depth: number;
key: string | number;
/**
* 父路由只是展开, 不去跳转。
*/
parentToggleExpand?: boolean;
linkClassName?: SchemaClassName;
filterClassName: (className: SchemaClassName) => string | undefined;
/**
* 渲染出内部的路由链接, 为了兼容examples里使用react-router的场景.
* 此时不需要设置`onNavClick`
*/
renderRouterLink?: (linkClassName: string, children: JSX.Element[]) => JSX.Element;
/**
* 内部路由点击跳转逻辑, 当透传renderRouterLink时可以不用传递
*/
onNavClick?: (e: React.MouseEvent<HTMLAnchorElement>) => void;
/**
* 展开父项的函数, 如果不传, 表示默认全部展开, 无法收缩
*/
toggleExpand?: (link: LinkItem, e?: React.MouseEvent<Element, MouseEvent> | undefined) => void;
}
export interface NavigationObject {
label: string;
children?: LinkItem[];
prefix?: JSX.Element;
affix?: JSX.Element;
className?: SchemaClassName;
path?: string;
initialOpen?: boolean;
active?: boolean;
open?: boolean;
[propName: string]: any;
}
export interface LinkItem {
id?: number;
label: string;
hidden?: boolean;
open?: boolean;
active?: boolean;
className?: SchemaClassName;
children?: Array<LinkItem>;
path?: string;
target?: '_self' | '_blank' | '_parent' | '_top';
icon?: string;
visible?: boolean;
badge?: string;
badgeClassName?: SchemaClassName;
component?: React.ComponentType;
}