runningTree的边界容错

This commit is contained in:
Xu Chang 2023-11-23 15:33:23 +08:00
parent f023e98125
commit ce35a8c292
96 changed files with 1905 additions and 1051 deletions

View File

@ -1,3 +1,4 @@
import React from 'react';
import { WebComponentProps } from '../../types/Page';
import { ED } from '../../types/AbstractComponent';
import { EntityDict } from 'oak-domain/lib/types/Entity';
@ -14,4 +15,4 @@ export default function Render(props: WebComponentProps<ED, keyof EntityDict, fa
}[];
}, {
makeItems: (isMobile: boolean) => void;
}>): import("react/jsx-runtime").JSX.Element;
}>): React.JSX.Element;

View File

@ -1,5 +1,4 @@
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
import { useEffect } from 'react';
import React, { useEffect } from 'react';
import { Space, Button, Divider, Popover, Typography, } from 'antd';
import { MoreOutlined, } from '@ant-design/icons';
import Style from './mobile.module.less';
@ -12,5 +11,22 @@ export default function Render(props) {
useEffect(() => {
makeItems(isMobile);
}, [zhCNKeys]);
return (_jsxs("div", { className: Style.container, children: [items && items.map((ele, index) => (_jsxs(_Fragment, { children: [_jsx("div", { className: Style.btn, onClick: ele.onClick, children: _jsx(Typography.Link, { children: ele.label }) }), index !== items.length - 1 && (_jsx(Divider, { type: "vertical" }))] }))), moreItems && moreItems.length > 0 && (_jsx(Divider, { type: "vertical" })), moreItems && moreItems.length > 0 && (_jsx(Popover, { placement: 'topRight', content: _jsx(Space, { direction: "vertical", children: moreItems.map((ele) => (_jsx(Button, { size: "small", type: "link", onClick: ele.onClick, children: ele.label }))) }), trigger: "click", children: _jsx(Button, { type: "link", icon: (_jsx(MoreOutlined, {})) }) }))] }));
return (<div className={Style.container}>
{items && items.map((ele, index) => (<>
<div className={Style.btn} onClick={ele.onClick}>
<Typography.Link>
{ele.label}
</Typography.Link>
</div>
{index !== items.length - 1 && (<Divider type="vertical"></Divider>)}
</>))}
{moreItems && moreItems.length > 0 && (<Divider type="vertical"/>)}
{moreItems && moreItems.length > 0 && (<Popover placement='topRight' content={<Space direction="vertical">
{moreItems.map((ele) => (<Button size="small" type="link" onClick={ele.onClick}>
{ele.label}
</Button>))}
</Space>} trigger="click">
<Button type="link" icon={(<MoreOutlined />)}/>
</Popover>)}
</div>);
}

View File

@ -1,3 +1,4 @@
import React from 'react';
import { ActionDef, WebComponentProps } from '../../types/Page';
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
import { ED, OakExtraActionProps } from '../../types/AbstractComponent';
@ -23,5 +24,5 @@ export default function Render(props: WebComponentProps<ED, keyof EntityDict, fa
onAction: (action?: string, cascadeAction?: CascadeActionProps) => void;
}, {
makeItems: () => void;
}>): import("react/jsx-runtime").JSX.Element;
}>): React.JSX.Element;
export {};

View File

@ -1,18 +1,21 @@
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
import { useEffect } from 'react';
import React, { useEffect } from 'react';
import { Space, Button, Modal, } from 'antd';
import Style from './web.module.less';
const { confirm } = Modal;
function ItemComponent(props) {
const { label, type, onClick } = props;
if (type === 'button') {
return (_jsx(Button, { onClick: () => onClick(), children: label }));
return (<Button onClick={() => onClick()}>
{label}
</Button>);
}
return _jsx("a", { onClick: (e) => {
return <a onClick={(e) => {
onClick();
e.stopPropagation();
return false;
}, children: label });
}}>
{label}
</a>;
}
export default function Render(props) {
const { methods, data } = props;
@ -22,7 +25,13 @@ export default function Render(props) {
useEffect(() => {
makeItems();
}, [zhCNKeys, actions, cascadeActions, extraActions]);
return (_jsx("div", { className: Style.panelContainer, children: _jsx(Space, { align: 'center', size: 12, style: { width: '100%' }, wrap: true, children: _jsx(_Fragment, { children: items?.map((ele, index) => {
return (_jsx(ItemComponent, { label: ele.label, type: "a", onClick: ele.onClick }));
}) }) }) }));
return (<div className={Style.panelContainer}>
<Space align='center' size={12} style={{ width: '100%' }} wrap>
<>
{items?.map((ele, index) => {
return (<ItemComponent label={ele.label} type="a" onClick={ele.onClick}/>);
})}
</>
</Space>
</div>);
}

View File

@ -1,3 +1,4 @@
import React from 'react';
import { SpaceProps } from 'antd';
import { WebComponentProps } from '../../types/Page';
import { EntityDict } from 'oak-domain/lib/base-app-domain';
@ -17,4 +18,4 @@ export default function Render(props: WebComponentProps<EntityDict, keyof Entity
okText: string;
cancelText: string;
};
}>): import("react/jsx-runtime").JSX.Element | null;
}>): React.JSX.Element | null;

View File

@ -1,16 +1,18 @@
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import React from 'react';
import { Space, Button, Modal, Dropdown, Typography, } from 'antd';
import Style from './web.module.less';
const { confirm } = Modal;
function ItemComponent(props) {
const { type, buttonProps, render, onClick, text } = props;
if (type === 'button') {
return (_jsx(Button, { ...buttonProps, onClick: onClick, children: text }));
return (<Button {...buttonProps} onClick={onClick}>
{text}
</Button>);
}
if (render) {
return _jsx("div", { onClick: onClick, children: render });
return <div onClick={onClick}>{render}</div>;
}
return _jsx("a", { onClick: onClick, children: text });
return <a onClick={onClick}>{text}</a>;
}
export default function Render(props) {
const { methods, data } = props;
@ -76,20 +78,12 @@ export default function Render(props) {
return null;
}
if (mode === 'table-cell') {
return (_jsxs(Space, { ...spaceProps, children: [newItems?.map((ele, index) => {
return (_jsx(ItemComponent, { ...ele, onClick: ele.onClick2, text: ele.text }));
}), moreItems && moreItems.length > 0 && (_jsx(Dropdown, { menu: {
items: moreItems.map((ele, index) => ({
label: ele.text,
key: index,
})),
onClick: (e) => {
const item = moreItems[e.key];
item.onClick2();
},
}, placement: "top", arrow: true, children: _jsx("a", { onClick: (e) => e.preventDefault(), children: "\u66F4\u591A" }) }))] }));
}
return (_jsxs("div", { className: Style.panelContainer, children: [moreItems && moreItems.length > 0 && (_jsx(Dropdown, { menu: {
return (<Space {...spaceProps}>
{newItems?.map((ele, index) => {
return (<ItemComponent {...ele} onClick={ele.onClick2} text={ele.text}/>);
})}
{moreItems && moreItems.length > 0 && (<Dropdown menu={{
items: moreItems.map((ele, index) => ({
label: ele.text,
key: index,
@ -98,7 +92,28 @@ export default function Render(props) {
const item = moreItems[e.key];
item.onClick2();
},
}, arrow: true, children: _jsx(Typography, { className: Style.more, children: "\u66F4\u591A" }) })), _jsx(Space, { ...spaceProps, children: newItems?.map((ele, index) => {
return (_jsx(ItemComponent, { type: "button", ...ele, onClick: ele.onClick2, text: ele.text }));
}) })] }));
}} placement="top" arrow>
<a onClick={(e) => e.preventDefault()}>更多</a>
</Dropdown>)}
</Space>);
}
return (<div className={Style.panelContainer}>
{moreItems && moreItems.length > 0 && (<Dropdown menu={{
items: moreItems.map((ele, index) => ({
label: ele.text,
key: index,
})),
onClick: (e) => {
const item = moreItems[e.key];
item.onClick2();
},
}} arrow>
<Typography className={Style.more}>更多</Typography>
</Dropdown>)}
<Space {...spaceProps}>
{newItems?.map((ele, index) => {
return (<ItemComponent type="button" {...ele} onClick={ele.onClick2} text={ele.text}/>);
})}
</Space>
</div>);
}

View File

@ -1,3 +1,4 @@
import React from 'react';
import { WebComponentProps } from '../../types/Page';
import { EntityDict } from 'oak-domain/lib/base-app-domain';
import { IMode, Item } from './type';
@ -17,4 +18,4 @@ export default function Render(props: WebComponentProps<EntityDict, keyof Entity
okText: string;
cancelText: string;
};
}>): import("react/jsx-runtime").JSX.Element | null;
}>): React.JSX.Element | null;

View File

@ -1,5 +1,4 @@
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useEffect, useState } from 'react';
import React, { useEffect, useState } from 'react';
import { Button, Modal, Typography, } from 'antd';
import OakIcon from '../icon';
import classNames from 'classnames';
@ -8,7 +7,7 @@ const { confirm } = Modal;
function ItemComponent(props) {
const { icon, buttonProps, render, onClick, iconRender, iconProps, mode, text, } = props;
if (render) {
return _jsx("div", { onClick: onClick, children: render });
return <div onClick={onClick}>{render}</div>;
}
const { style = {}, rootStyle = {}, bgColor } = iconProps || {};
let icon2;
@ -16,16 +15,23 @@ function ItemComponent(props) {
icon2 = iconRender;
}
else if (typeof icon === 'string') {
icon2 = (_jsx(OakIcon, { name: icon, className: classNames(Style.icon, {
icon2 = (<OakIcon name={icon} className={classNames(Style.icon, {
[Style.iconWhite]: !!bgColor,
}), style: style }));
})} style={style}/>);
}
else {
icon2 = icon;
}
return (_jsx(Button, { className: Style.btn, type: "text", ...buttonProps, onClick: onClick, children: _jsxs("div", { className: Style.space, children: [mode === 'card' && !!icon2 ? (_jsx("div", { className: Style.iconBox, style: Object.assign({}, bgColor && {
backgroundColor: bgColor,
}, rootStyle), children: icon2 })) : (icon2), _jsx(Typography, { children: text })] }) }));
return (<Button className={Style.btn} type="text" {...buttonProps} onClick={onClick}>
<div className={Style.space}>
{mode === 'card' && !!icon2 ? (<div className={Style.iconBox} style={Object.assign({}, bgColor && {
backgroundColor: bgColor,
}, rootStyle)}>
{icon2}
</div>) : (icon2)}
<Typography>{text}</Typography>
</div>
</Button>);
}
export default function Render(props) {
const { methods, data } = props;
@ -74,61 +80,76 @@ export default function Render(props) {
if (!newItems || newItems.length === 0) {
return null;
}
return (_jsxs("div", { className: Style.tabContainer, children: [_jsx("div", { className: Style.scrollBox, children: _jsx("div", { id: id, className: Style.scrollView, onScroll: (e) => {
const scrollLeft = e.target.scrollLeft;
setSlideLeft(scrollLeft * slideRatio);
}, children: _jsx("div", { className: Style.tabView, children: tabNums.map((tabNum, index) => {
return (_jsx("div", { className: Style.btnContainer, children: newItems
.filter((btn, index2) => (tabNum - 1) * count <
index2 + 1 &&
index2 + 1 <= tabNum * count)
.map((ele, index2) => {
const { label, action } = ele;
let text;
if (label) {
text = label;
return (<div className={Style.tabContainer}>
<div className={Style.scrollBox}>
<div id={id} className={Style.scrollView} onScroll={(e) => {
const scrollLeft = e.target.scrollLeft;
setSlideLeft(scrollLeft * slideRatio);
}}>
<div className={Style.tabView}>
{tabNums.map((tabNum, index) => {
return (<div className={Style.btnContainer}>
{newItems
.filter((btn, index2) => (tabNum - 1) * count <
index2 + 1 &&
index2 + 1 <= tabNum * count)
.map((ele, index2) => {
const { label, action } = ele;
let text;
if (label) {
text = label;
}
else {
text = getActionName(action);
}
let onClick = async () => {
if (ele.onClick) {
ele.onClick(ele);
return;
}
};
if (ele.alerted) {
onClick = async () => {
const { title, content, okText, cancelText, } = getAlertOptions(ele);
confirm({
title,
content,
okText,
cancelText,
onOk: async () => {
if (ele.onClick) {
ele.onClick(ele);
return;
}
else {
text = getActionName(action);
}
let onClick = async () => {
if (ele.onClick) {
ele.onClick(ele);
return;
}
};
if (ele.alerted) {
onClick = async () => {
const { title, content, okText, cancelText, } = getAlertOptions(ele);
confirm({
title,
content,
okText,
cancelText,
onOk: async () => {
if (ele.onClick) {
ele.onClick(ele);
return;
}
},
});
};
}
return (_jsx("div", { className: classNames(Style.btnBox, {
[Style.btnBox_top]: newItems.length >
column &&
index2 >
column - 1,
}), style: {
height: `calc(100% / ${newItems.length >
column
? rows
: 1})`,
width: `calc(100% / ${column})`,
}, children: _jsx(ItemComponent, { ...ele, onClick: onClick, mode: mode, text: text }) }, index2));
}) }));
}) }) }) }), slideShow && (_jsx("div", { className: Style.slideBar, children: _jsx("div", { className: Style.slideShow, style: {
width: slideWidth,
marginLeft: slideLeft <= 1 ? 0 : slideLeft,
} }) }))] }));
},
});
};
}
return (<div key={index2} className={classNames(Style.btnBox, {
[Style.btnBox_top]: newItems.length >
column &&
index2 >
column - 1,
})} style={{
height: `calc(100% / ${newItems.length >
column
? rows
: 1})`,
width: `calc(100% / ${column})`,
}}>
<ItemComponent {...ele} onClick={onClick} mode={mode} text={text}/>
</div>);
})}
</div>);
})}
</div>
</div>
</div>
{slideShow && (<div className={Style.slideBar}>
<div className={Style.slideShow} style={{
width: slideWidth,
marginLeft: slideLeft <= 1 ? 0 : slideLeft,
}}/>
</div>)}
</div>);
}

View File

@ -1,3 +1,4 @@
import React from 'react';
import { EntityDict } from 'oak-domain/lib/types/Entity';
import { WebComponentProps } from '../../types/Page';
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
@ -25,5 +26,5 @@ export default function Render(props: WebComponentProps<EntityDict & BaseEntityD
column: ColumnMapType;
renderData: AttrRender[];
judgeAttributes: OakAbsAttrJudgeDef[];
}, {}>): import("react/jsx-runtime").JSX.Element;
}, {}>): React.JSX.Element;
export {};

View File

@ -1,4 +1,4 @@
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import React from 'react';
import { Space, Image } from 'antd-mobile';
import styles from './mobile.module.less';
// type Width = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl';
@ -7,25 +7,53 @@ function RenderRow(props) {
const { type, label, value } = props;
if (type === 'image') {
if (value instanceof Array) {
return (_jsxs("div", { className: styles.renderRow, children: [_jsx("div", { className: styles.renderLabel, children: label }), _jsx(Space, { wrap: true, children: value.map((ele) => (_jsx(Image, { width: 70, height: 70, src: ele, fit: "contain" }))) })] }));
return (<div className={styles.renderRow}>
<div className={styles.renderLabel}>
{label}
</div>
<Space wrap>
{value.map((ele) => (<Image width={70} height={70} src={ele} fit="contain"/>))}
</Space>
</div>);
}
else {
return (_jsxs("div", { className: styles.renderRow, children: [_jsx("div", { className: styles.renderLabel, children: label }), _jsx(Space, { wrap: true, children: _jsx(Image, { width: 70, height: 70, src: value, fit: "contain" }) })] }));
return (<div className={styles.renderRow}>
<div className={styles.renderLabel}>
{label}
</div>
<Space wrap>
<Image width={70} height={70} src={value} fit="contain"/>
</Space>
</div>);
}
}
return (_jsxs("div", { className: styles.renderRow, children: [_jsx("div", { className: styles.renderLabel, children: label }), _jsx("div", { className: styles.renderValue, children: value ? String(value) : '--' })] }));
return (<div className={styles.renderRow}>
<div className={styles.renderLabel}>
{label}
</div>
<div className={styles.renderValue}>{value ? String(value) : '--'}</div>
</div>);
}
export default function Render(props) {
const { methods, data: oakData } = props;
const { t } = methods;
const { title, renderData, entity, judgeAttributes, data, } = oakData;
return (_jsxs("div", { className: styles.panel, children: [title && (_jsx("div", { className: styles.title, children: title })), _jsx("div", { className: styles.panel_content, children: _jsx(Space, { direction: "vertical", style: { '--gap': '10px' }, children: judgeAttributes && judgeAttributes.map((ele) => {
let renderValue = getValue(data, ele.path, ele.entity, ele.attr, ele.attrType, t);
let renderLabel = getLabel(ele.attribute, ele.entity, ele.attr, t);
const renderType = getType(ele.attribute, ele.attrType);
if ([null, '', undefined].includes(renderValue)) {
renderValue = t('not_filled_in');
}
return (_jsx(RenderRow, { label: renderLabel, value: renderValue, type: renderType }));
}) }) })] }));
return (<div className={styles.panel}>
{title && (<div className={styles.title}>
{title}
</div>)}
<div className={styles.panel_content}>
<Space direction="vertical" style={{ '--gap': '10px' }}>
{judgeAttributes && judgeAttributes.map((ele) => {
let renderValue = getValue(data, ele.path, ele.entity, ele.attr, ele.attrType, t);
let renderLabel = getLabel(ele.attribute, ele.entity, ele.attr, t);
const renderType = getType(ele.attribute, ele.attrType);
if ([null, '', undefined].includes(renderValue)) {
renderValue = t('not_filled_in');
}
return (<RenderRow label={renderLabel} value={renderValue} type={renderType}/>);
})}
</Space>
</div>
</div>);
}

View File

@ -1,3 +1,4 @@
import React from 'react';
import { Breakpoint } from 'antd';
import { EntityDict } from 'oak-domain/lib/types/Entity';
import { WebComponentProps } from '../../types/Page';
@ -17,4 +18,4 @@ export default function Render(props: WebComponentProps<EntityDict & BaseEntityD
column: number | Record<Breakpoint, number>;
renderData: AttrRender[];
judgeAttributes: OakAbsAttrJudgeDef[];
}, {}>): import("react/jsx-runtime").JSX.Element;
}, {}>): React.JSX.Element;

View File

@ -1,4 +1,4 @@
import { jsx as _jsx } from "react/jsx-runtime";
import React from 'react';
import { Tag, Descriptions, Image, Space } from 'antd';
import { getLabel, getType, getValue } from '../../utils/usefulFn';
import { get } from 'oak-domain/lib/utils/lodash';
@ -6,14 +6,20 @@ function RenderRow(props) {
const { type, value, color } = props;
if (type === 'image') {
if (value instanceof Array) {
return (_jsx(Space, { wrap: true, children: value.map((ele) => (_jsx(Image, { width: 100, height: 100, src: ele, style: { objectFit: 'contain' } }))) }));
return (<Space wrap>
{value.map((ele) => (<Image width={100} height={100} src={ele} style={{ objectFit: 'contain' }}/>))}
</Space>);
}
else {
return (_jsx(Space, { wrap: true, children: _jsx(Image, { width: 100, height: 100, src: value, style: { objectFit: 'contain' } }) }));
return (<Space wrap>
<Image width={100} height={100} src={value} style={{ objectFit: 'contain' }}/>
</Space>);
}
}
if (type === 'enum') {
_jsx(Tag, { color: color, children: value });
<Tag color={color}>
{value}
</Tag>;
}
return value;
}
@ -21,7 +27,8 @@ export default function Render(props) {
const { methods, data: oakData } = props;
const { t } = methods;
const { entity, title, colorDict, bordered, column, renderData, layout = "horizontal", judgeAttributes, data, } = oakData;
return (_jsx(Descriptions, { title: title, column: column, bordered: bordered, layout: layout, children: judgeAttributes?.map((ele) => {
return (<Descriptions title={title} column={column} bordered={bordered} layout={layout}>
{judgeAttributes?.map((ele) => {
let renderValue = getValue(data, ele.path, ele.entity, ele.attr, ele.attrType, t);
let renderLabel = getLabel(ele.attribute, ele.entity, ele.attr, t);
const renderType = getType(ele.attribute, ele.attrType);
@ -30,6 +37,9 @@ export default function Render(props) {
}
const stateValue = get(data, ele.path);
const color = colorDict && colorDict[ele.entity]?.[ele.attr]?.[stateValue] || 'default';
return (_jsx(Descriptions.Item, { label: renderLabel, span: ele.attribute.span || 1, children: _jsx(RenderRow, { type: renderType, value: renderValue, color: color }) }));
}) }));
return (<Descriptions.Item label={renderLabel} span={ele.attribute.span || 1}>
<RenderRow type={renderType} value={renderValue} color={color}/>
</Descriptions.Item>);
})}
</Descriptions>);
}

View File

@ -1,3 +1,4 @@
/// <reference types="react" />
import { WebComponentProps } from '../../../types/Page';
import { EntityDict } from 'oak-domain/lib/types/Entity';
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
@ -14,5 +15,5 @@ export default function render(props: WebComponentProps<ED, keyof ED, true, {
}>;
}, {
onEntityClicked: (entity: string) => void;
}>): import("react/jsx-runtime").JSX.Element;
}>): import("react").JSX.Element;
export {};

View File

@ -1,6 +1,7 @@
import { jsx as _jsx } from "react/jsx-runtime";
import Styles from './web.module.less';
export default function render(props) {
const { t } = props.methods;
return (_jsx("div", { className: Styles.container, children: t('useWideScreen') }));
return (<div className={Styles.container}>
{t('useWideScreen')}
</div>);
}

View File

@ -1,3 +1,4 @@
/// <reference types="react" />
import { WebComponentProps } from '../../../types/Page';
import { EntityDict } from 'oak-domain/lib/types/Entity';
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
@ -14,5 +15,5 @@ export default function render(props: WebComponentProps<ED, keyof ED, true, {
}>;
}, {
onEntityClicked: (entity: string) => void;
}>): import("react/jsx-runtime").JSX.Element;
}>): import("react").JSX.Element;
export {};

View File

@ -1,4 +1,3 @@
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
import { Switch, Input, Form } from 'antd';
import ReactEcharts from 'echarts-for-react';
import { useState } from 'react';
@ -37,54 +36,68 @@ export default function render(props) {
});
}
}
return (_jsxs("div", { className: Styles.container, children: [_jsxs(Form, { style: {
margin: 20,
}, children: [_jsx(Form.Item, { label: "filter", children: _jsx(_Fragment, { children: _jsx(Input, { onChange: ({ currentTarget }) => setSearch(currentTarget.value), allowClear: true }) }) }), _jsx(Form.Item, { label: "strict mode", children: _jsx(_Fragment, { children: _jsx(Switch, { checked: strict, onChange: (checked) => setStrict(checked) }) }) })] }), _jsx(ReactEcharts, { style: { width: '100%', height: '100%', minHeight: 750 }, option: {
tooltip: {},
series: [
{
type: 'graph',
layout: 'force',
force: {
initLayout: 'circular',
gravity: 0,
repulsion: [10, 80],
edgeLength: [10, 50]
},
data: data2,
links: links2,
lineStyle: {
opacity: 0.9,
width: 2,
curveness: 0
},
label: {
show: true
},
autoCurveness: true,
roam: true,
draggable: true,
edgeSymbol: ['none', 'arrow'],
edgeSymbolSize: 7,
emphasis: {
scale: true,
label: {
show: true,
},
focus: 'adjacency',
lineStyle: {
width: 10
}
}
},
],
}, notMerge: true, lazyUpdate: false, onEvents: {
click: (info) => {
const { data, dataType } = info;
if (dataType === 'node') {
const { name } = data;
onEntityClicked(name);
}
return (<div className={Styles.container}>
<Form style={{
margin: 20,
}}>
<Form.Item label="filter">
<>
<Input onChange={({ currentTarget }) => setSearch(currentTarget.value)} allowClear/>
</>
</Form.Item>
<Form.Item label="strict mode">
<>
<Switch checked={strict} onChange={(checked) => setStrict(checked)}/>
</>
</Form.Item>
</Form>
<ReactEcharts style={{ width: '100%', height: '100%', minHeight: 750 }} option={{
tooltip: {},
series: [
{
type: 'graph',
layout: 'force',
force: {
initLayout: 'circular',
gravity: 0,
repulsion: [10, 80],
edgeLength: [10, 50]
},
} })] }));
data: data2,
links: links2,
lineStyle: {
opacity: 0.9,
width: 2,
curveness: 0
},
label: {
show: true
},
autoCurveness: true,
roam: true,
draggable: true,
edgeSymbol: ['none', 'arrow'],
edgeSymbolSize: 7,
emphasis: {
scale: true,
label: {
show: true,
},
focus: 'adjacency',
lineStyle: {
width: 10
}
}
},
],
}} notMerge={true} lazyUpdate={false} onEvents={{
click: (info) => {
const { data, dataType } = info;
if (dataType === 'node') {
const { name } = data;
onEntityClicked(name);
}
},
}}/>
</div>);
}

View File

@ -1,3 +1,4 @@
import React from 'react';
import { WebComponentProps } from '../../types/Page';
import { ED } from '../../types/AbstractComponent';
import { ColumnProps, ValueType, ViewType } from '../../types/Filter';
@ -16,4 +17,4 @@ export default function Render<ED2 extends ED>(props: WebComponentProps<ED2, key
}, {
getNamedFilter: (name: string) => Record<string, any>;
setFilterAndResetFilter: (viewType: ViewType, value?: ValueType) => void;
}>): import("react/jsx-runtime").JSX.Element | null;
}>): React.JSX.Element | null;

View File

@ -1,4 +1,4 @@
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
import React from 'react';
import { Input, Form, Select, DatePicker, } from 'antd';
import dayjs from 'dayjs';
import weekday from 'dayjs/plugin/weekday';
@ -34,14 +34,16 @@ export default function Render(props) {
}
let V;
if (column.render) {
return (_jsx(Form.Item, { label: label, name: name, children: _jsx(_Fragment, { children: column.render }) }));
return (<Form.Item label={label} name={name}>
<>{column.render}</>
</Form.Item>);
}
switch (viewType) {
case 'Input': {
V = (_jsx(Input, { placeholder: placeholder || t('placeholder.input'), onChange: (e) => {
V = (<Input placeholder={placeholder || t('placeholder.input')} onChange={(e) => {
const val = e.target.value;
setFilterAndResetFilter(viewType, val);
}, allowClear: true, onPressEnter: () => { } }));
}} allowClear onPressEnter={() => { }}/>);
break;
}
case 'Select': {
@ -52,13 +54,13 @@ export default function Render(props) {
value: ele.value,
}));
const multiple = ['$in', '$nin'].includes(op || '');
V = (_jsx(Select, { mode: multiple ? 'multiple' : undefined, allowClear: true, placeholder: placeholder || t('placeholder.select'), onChange: (value) => {
V = (<Select mode={multiple ? 'multiple' : undefined} allowClear placeholder={placeholder || t('placeholder.select')} onChange={(value) => {
let value2 = multiple ? value : [value];
if (value === undefined || value === null) {
value2 = [];
}
setFilterAndResetFilter(viewType, value2);
}, options: options2 }));
}} options={options2}/>);
break;
}
case 'DatePicker': {
@ -66,21 +68,19 @@ export default function Render(props) {
const { showTime = false } = dateProps || {};
//assert(op, '选择时间,算子必须传入');
const unitOfTime = 'day';
V = (_jsx(DatePicker, { placeholder: placeholder || t('placeholder.select'), style: { width: '100%' }, format: "YYYY-MM-DD", showTime: showTime, onChange: (date, dateString) => {
V = (<DatePicker placeholder={placeholder || t('placeholder.select')} style={{ width: '100%' }} format="YYYY-MM-DD" showTime={showTime} onChange={(date, dateString) => {
setFilterAndResetFilter(viewType, date);
} }));
}}/>);
break;
}
case 'DatePicker.RangePicker': {
const { dateProps } = column;
const { showTime = false } = dateProps || {};
V = (_jsx(DatePicker.RangePicker
V = (<DatePicker.RangePicker
// placeholder={placeholder || t('placeholder.select')}
, {
// placeholder={placeholder || t('placeholder.select')}
style: { width: '100%' }, showTime: showTime, onChange: (dates, dateStrings) => {
style={{ width: '100%' }} showTime={showTime} onChange={(dates, dateStrings) => {
setFilterAndResetFilter(viewType, dates);
} }));
}}/>);
break;
}
case 'RefAttr': {
@ -88,13 +88,15 @@ export default function Render(props) {
const filter = getNamedFilter(name);
const value = get(filter, getOp(column), '');
const multiple = ['$in', '$nin'].includes(op || '');
V = (_jsx(RefAttr, { placeholder: placeholder || t('placeholder.select'), multiple: multiple, entityIds: value ? (multiple ? value : [value]) : [], pickerRender: Object.assign({}, column.refProps), onChange: (ids) => {
V = (<RefAttr placeholder={placeholder || t('placeholder.select')} multiple={multiple} entityIds={value ? (multiple ? value : [value]) : []} pickerRender={Object.assign({}, column.refProps)} onChange={(ids) => {
setFilterAndResetFilter(viewType, ids);
} }));
}}/>);
break;
}
}
return (_jsx(Form.Item, { label: label, name: name, children: _jsx(_Fragment, { children: V }) }));
return (<Form.Item label={label} name={name}>
<>{V}</>
</Form.Item>);
}
function assertMessage(attr, attrType, op, ops) {
return `attr为【${attr}】, 传入的算子【${op}】不支持,类型【${attrType}】只支持【${JSON.stringify(ops)}`;

View File

@ -1,3 +1,4 @@
import React from 'react';
import { WebComponentProps } from '../../types/Page';
import { ED } from '../../types/AbstractComponent';
import { ColSpanType, ColumnProps } from '../../types/Filter';
@ -18,5 +19,5 @@ export default function Render<ED2 extends ED>(props: WebComponentProps<ED, keyo
width: Width;
}, {
getNamedFilters: () => Record<string, any>[];
}>): import("react/jsx-runtime").JSX.Element | null;
}>): React.JSX.Element | null;
export {};

View File

@ -1,5 +1,4 @@
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useState } from 'react';
import React, { useState } from 'react';
import { Button, Space, Form, Badge, Row, Col } from 'antd';
import { DownOutlined, UpOutlined } from '@ant-design/icons';
import Filter from '../filter2';
@ -63,7 +62,9 @@ export default function Render(props) {
tfColumns.forEach((column, index) => {
const { colSpan } = column;
const colSpan2 = getSpan(colSpan || 1, mergedColumn);
const item = (_jsx(Col, { span: gridColumn * colSpan2, children: _jsx(Filter, { column: column, entity: entity, oakPath: oakFullpath }) }));
const item = (<Col span={gridColumn * colSpan2}>
<Filter column={column} entity={entity} oakPath={oakFullpath}/>
</Col>);
if (index === 0) {
firstItem = item;
}
@ -136,18 +137,40 @@ export default function Render(props) {
const buttonItemLayout = formLayout === 'horizontal'
? { wrapperCol: { span: 18, offset: 6 } }
: null;
items.push(_jsx(Col, { span: _gridColumn, children: _jsx(Form.Item, { ...buttonItemLayout, children: _jsxs(Space, { className: Style.actionBox, children: [_jsx(Badge, { count: count, children: _jsx(Button, { type: "default", onClick: () => {
filterNames.forEach((ele) => removeNamedFilterByName(ele));
form.resetFields();
refresh();
}, children: t('common::reset') }) }), _jsx(Button, { type: "primary", onClick: () => {
if (typeof onSearch === 'function') {
onSearch();
return;
}
refresh();
}, children: t('common::select') }), showExpandButton && (_jsx(Button, { type: "link", onClick: () => {
setOpen(!open);
}, children: _jsxs(Space, { children: [open ? t('common::shrink') : t('common::expand'), open ? _jsx(UpOutlined, {}) : _jsx(DownOutlined, {})] }) }))] }) }) }));
return (_jsx(Form, { form: form, ...formItemLayout, layout: formLayout, children: _jsx(Row, { gutter: [16, 16], children: items }) }));
items.push(<Col span={_gridColumn}>
<Form.Item {...buttonItemLayout}>
<Space className={Style.actionBox}>
<Badge count={count}>
<Button type="default" onClick={() => {
filterNames.forEach((ele) => removeNamedFilterByName(ele));
form.resetFields();
refresh();
}}>
{t('common::reset')}
</Button>
</Badge>
<Button type="primary" onClick={() => {
if (typeof onSearch === 'function') {
onSearch();
return;
}
refresh();
}}>
{t('common::select')}
</Button>
{showExpandButton && (<Button type="link" onClick={() => {
setOpen(!open);
}}>
<Space>
{open ? t('common::shrink') : t('common::expand')}
{open ? <UpOutlined /> : <DownOutlined />}
</Space>
</Button>)}
</Space>
</Form.Item>
</Col>);
return (<Form form={form} {...formItemLayout} layout={formLayout}>
<Row gutter={[16, 16]}>{items}</Row>
</Form>);
}

View File

@ -8,4 +8,4 @@ export default function Render(props: WebComponentProps<EntityDict, keyof Entity
size?: string;
className?: string;
style?: React.CSSProperties;
}, {}>): import("react/jsx-runtime").JSX.Element;
}, {}>): React.JSX.Element;

View File

@ -1,4 +1,4 @@
import { jsx as _jsx } from "react/jsx-runtime";
import React from 'react';
import './web.less';
export default function Render(props) {
const { data } = props;
@ -11,5 +11,5 @@ export default function Render(props) {
if (className) {
class_name += ' ' + className;
}
return (_jsx("span", { className: class_name, style: Object.assign(style, size && { fontSize: size }, color && !isColor && { color }) }));
return (<span className={class_name} style={Object.assign(style, size && { fontSize: size }, color && !isColor && { color })}></span>);
}

View File

@ -1,3 +1,4 @@
import React from 'react';
type Props = {
mode?: 'select';
selected?: boolean;
@ -9,5 +10,5 @@ type Props = {
onClick?: () => void;
type?: 'fill' | 'contain' | 'cover' | 'none' | 'scale-down' | 'initial' | 'inherit';
};
declare function ImgBox(props: Props): import("react/jsx-runtime").JSX.Element;
declare function ImgBox(props: Props): React.JSX.Element;
export default ImgBox;

View File

@ -1,46 +1,60 @@
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useState } from 'react';
import React, { useState } from 'react';
import styles from './index.module.less';
import { Space, Checkbox, Divider, Modal, Image } from 'antd';
import { EyeOutlined, } from '@ant-design/icons';
const { confirm } = Modal;
function MaskView(props) {
const { selected, onClick, setVisibleTrue } = props;
return (_jsx("div", { className: selected ? styles['mask-checked'] : styles.mask, onClick: onClick, children: _jsxs("div", { className: styles.row2, children: [_jsx(Checkbox, { checked: selected }), _jsx(Space, { size: 0, split: _jsx(Divider, { type: "vertical" }), children: _jsx(EyeOutlined, { style: {
color: 'white',
fontSize: '1.4em',
}, onClick: (e) => {
setVisibleTrue();
e.stopPropagation();
} }) })] }) }));
return (<div className={selected ? styles['mask-checked'] : styles.mask} onClick={onClick}>
<div className={styles.row2}>
<Checkbox checked={selected}/>
<Space size={0} split={<Divider type="vertical"/>}>
<EyeOutlined style={{
color: 'white',
fontSize: '1.4em',
}} onClick={(e) => {
setVisibleTrue();
e.stopPropagation();
}}/>
</Space>
</div>
</div>);
}
function ImgBox(props) {
const { width, height, bordered = false, type = 'contain', src, alt, mode, selected, onClick } = props;
const [visible, setVisible] = useState(false);
if (bordered) {
return (_jsxs("div", { className: styles.imgBoxBorder, children: [mode === 'select' && (_jsx(MaskView, { selected: selected, onClick: () => onClick && onClick(), setVisibleTrue: () => {
setVisible(true);
} })), _jsx("img", { width: width || 72, height: height || 72, src: src, style: {
objectFit: type,
borderRadius: 8,
}, alt: 'img' || alt }), _jsx(Image, { style: { display: 'none' }, src: src, preview: {
visible,
src,
onVisibleChange: (value) => {
setVisible(value);
},
} })] }));
}
return (_jsxs("div", { className: styles.imgBox, children: [mode === 'select' && (_jsx(MaskView, { selected: selected, onClick: () => onClick && onClick(), setVisibleTrue: () => {
return (<div className={styles.imgBoxBorder}>
{mode === 'select' && (<MaskView selected={selected} onClick={() => onClick && onClick()} setVisibleTrue={() => {
setVisible(true);
} })), _jsx("img", { width: width || 72, height: height || 72, src: src, style: {
objectFit: type,
}, alt: 'img' || alt }), _jsx(Image, { style: { display: 'none' }, src: src, preview: {
visible,
src,
onVisibleChange: (value) => {
setVisible(value);
},
} })] }));
}}/>)}
<img width={width || 72} height={height || 72} src={src} style={{
objectFit: type,
borderRadius: 8,
}} alt={'img' || alt}/>
<Image style={{ display: 'none' }} src={src} preview={{
visible,
src,
onVisibleChange: (value) => {
setVisible(value);
},
}}/>
</div>);
}
return (<div className={styles.imgBox}>
{mode === 'select' && (<MaskView selected={selected} onClick={() => onClick && onClick()} setVisibleTrue={() => {
setVisible(true);
}}/>)}
<img width={width || 72} height={height || 72} src={src} style={{
objectFit: type,
}} alt={'img' || alt}/>
<Image style={{ display: 'none' }} src={src} preview={{
visible,
src,
onVisibleChange: (value) => {
setVisible(value);
},
}}/>
</div>);
}
export default ImgBox;

View File

@ -1,7 +1,8 @@
import React from 'react';
import { EntityDict } from 'oak-domain/lib/types/Entity';
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
import { ListButtonProps } from '../../../types/AbstractComponent';
import { WebComponentProps } from '../../../types/Page';
export default function Render(props: WebComponentProps<EntityDict & BaseEntityDict, keyof EntityDict, false, {
items: ListButtonProps[];
}, {}>): import("react/jsx-runtime").JSX.Element;
}, {}>): React.JSX.Element;

View File

@ -1,4 +1,4 @@
import { jsx as _jsx } from "react/jsx-runtime";
import React from 'react';
// TODO 应该是要antd-mobile组件
import { FloatButton } from 'antd';
import { BarsOutlined, } from '@ant-design/icons';
@ -8,7 +8,9 @@ export default function Render(props) {
const { items } = data;
if (items && items.length === 1) {
const item = items[0];
return (_jsx(FloatButton, { shape: "circle", type: "primary", style: { right: 24 }, icon: item.icon, description: item.icon ? null : item.label, onClick: () => item.onClick() }));
return (<FloatButton shape="circle" type="primary" style={{ right: 24 }} icon={item.icon} description={item.icon ? null : item.label} onClick={() => item.onClick()}/>);
}
return (_jsx(FloatButton.Group, { shape: 'circle', trigger: "click", type: "primary", style: { right: 24 }, icon: _jsx(BarsOutlined, {}), children: items && items.map((ele) => (_jsx(FloatButton, { icon: ele.icon, description: ele.icon ? null : ele.label, onClick: () => ele.onClick() }))) }));
return (<FloatButton.Group shape='circle' trigger="click" type="primary" style={{ right: 24 }} icon={<BarsOutlined />}>
{items && items.map((ele) => (<FloatButton icon={ele.icon} description={ele.icon ? null : ele.label} onClick={() => ele.onClick()}/>))}
</FloatButton.Group>);
}

View File

@ -1,7 +1,8 @@
import React from 'react';
import { EntityDict } from 'oak-domain/lib/types/Entity';
import { WebComponentProps } from '../../../types/Page';
import { ListButtonProps } from '../../../types/AbstractComponent';
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
export default function Render(props: WebComponentProps<EntityDict & BaseEntityDict, keyof EntityDict, false, {
items: ListButtonProps[];
}, {}>): import("react/jsx-runtime").JSX.Element;
}, {}>): React.JSX.Element;

View File

@ -1,8 +1,12 @@
import { jsx as _jsx } from "react/jsx-runtime";
import React from 'react';
import { Space, Button } from 'antd';
export default function Render(props) {
const { methods, data: oakData } = props;
const { items } = oakData;
// 为了i18更新时能够重新渲染
return (_jsx(Space, { children: items.filter((ele) => ele.show).map((ele) => (_jsx(Button, { type: ele.type, onClick: ele.onClick, children: ele.label }))) }));
return (<Space>
{items.filter((ele) => ele.show).map((ele) => (<Button type={ele.type} onClick={ele.onClick}>
{ele.label}
</Button>))}
</Space>);
}

View File

@ -1,2 +1,3 @@
declare function ColumnSetting(): import("react/jsx-runtime").JSX.Element;
import React from 'react';
declare function ColumnSetting(): React.JSX.Element;
export default ColumnSetting;

View File

@ -1,5 +1,4 @@
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useContext, useEffect, useState } from 'react';
import React, { useContext, useEffect, useState } from 'react';
import { SettingOutlined, VerticalAlignBottomOutlined, VerticalAlignTopOutlined, } from '@ant-design/icons';
import { Popover, Space, Tooltip, Tree, Button } from 'antd';
import Style from './index.module.less';
@ -9,15 +8,29 @@ import { useFeatures } from '../../../platforms/web';
function ListItem(props) {
const features = useFeatures();
const { disabled, title, onSelect, showToBottom, showToTop, onMoveTop, onMoveBottom, } = props;
return (_jsxs("div", { className: Style.listItemView, onClick: onSelect, children: [_jsx("div", { className: Style.listItemTitle, children: title }), !disabled ? (_jsxs("div", { className: Style.listIconView, children: [_jsx(Tooltip, { title: features.locales.t('leftPin'), children: showToTop && (_jsx("div", { className: Style.listIcon, onClick: (e) => {
e.stopPropagation();
e.preventDefault();
onMoveTop();
}, children: _jsx(VerticalAlignTopOutlined, {}) })) }), _jsx(Tooltip, { title: features.locales.t('rightPin'), children: showToBottom && (_jsx("div", { className: Style.listIcon, onClick: (e) => {
e.stopPropagation();
e.preventDefault();
onMoveBottom();
}, children: _jsx(VerticalAlignBottomOutlined, {}) })) })] })) : null] }));
return (<div className={Style.listItemView} onClick={onSelect}>
<div className={Style.listItemTitle}>{title}</div>
{!disabled ? (<div className={Style.listIconView}>
<Tooltip title={features.locales.t('leftPin')}>
{showToTop && (<div className={Style.listIcon} onClick={(e) => {
e.stopPropagation();
e.preventDefault();
onMoveTop();
}}>
<VerticalAlignTopOutlined />
</div>)}
</Tooltip>
<Tooltip title={features.locales.t('rightPin')}>
{showToBottom && (<div className={Style.listIcon} onClick={(e) => {
e.stopPropagation();
e.preventDefault();
onMoveBottom();
}}>
<VerticalAlignBottomOutlined />
</div>)}
</Tooltip>
</div>) : null}
</div>);
}
function ColumnSetting() {
const features = useFeatures();
@ -71,7 +84,7 @@ function ColumnSetting() {
setTableAttributes([...tableAttributes]);
}
};
const listDom = (_jsx(Tree, { itemHeight: 24, draggable: true, checkable: true, onDrop: (info) => {
const listDom = (<Tree itemHeight={24} draggable={true} checkable={true} onDrop={(info) => {
const dropKey = info.node.key;
const dragKey = info.dragNode.key;
const { dropPosition, dropToGap } = info;
@ -79,9 +92,20 @@ function ColumnSetting() {
? dropPosition + 1
: dropPosition;
move(dragKey, dropKey, position);
}, blockNode: true, onCheck: (checkedKeys, e) => {
}} blockNode onCheck={(checkedKeys, e) => {
onCheck(e.node);
}, titleRender: (node) => (_jsx(ListItem, { disabled: node.disabled, title: node.title, nodeKey: node.key, showToTop: node.keyIndex !== 0, showToBottom: node.keyIndex !== treeData.length - 1, onSelect: () => onCheck(node), onMoveTop: () => move(node.key, treeData[0].key, 0), onMoveBottom: () => move(node.key, treeData[treeData.length - 1].key, treeData.length + 1) })), checkedKeys: checkedKeys, showLine: false, treeData: treeData }));
return (_jsx(Popover, { arrow: false, title: _jsxs("div", { className: Style.titleView, children: [_jsx("strong", { children: features.locales.t('columnSetting') }), _jsx(Button, { type: "link", onClick: onReset, children: features.locales.t('common::reset') })] }), trigger: "click", placement: "bottomRight", content: _jsx(Space, { children: listDom }), children: _jsx(Tooltip, { title: features.locales.t('columnSetting'), children: _jsx("div", { className: Style.iconBox, children: _jsx(SettingOutlined, {}) }) }) }));
}} titleRender={(node) => (<ListItem disabled={node.disabled} title={node.title} nodeKey={node.key} showToTop={node.keyIndex !== 0} showToBottom={node.keyIndex !== treeData.length - 1} onSelect={() => onCheck(node)} onMoveTop={() => move(node.key, treeData[0].key, 0)} onMoveBottom={() => move(node.key, treeData[treeData.length - 1].key, treeData.length + 1)}/>)} checkedKeys={checkedKeys} showLine={false} treeData={treeData}/>);
return (<Popover arrow={false} title={<div className={Style.titleView}>
<strong>{features.locales.t('columnSetting')}</strong>
<Button type="link" onClick={onReset}>
{features.locales.t('common::reset')}
</Button>
</div>} trigger="click" placement="bottomRight" content={<Space>{listDom}</Space>}>
<Tooltip title={features.locales.t('columnSetting')}>
<div className={Style.iconBox}>
<SettingOutlined />
</div>
</Tooltip>
</Popover>);
}
export default ColumnSetting;

View File

@ -1,3 +1,4 @@
import React from 'react';
import { EntityDict } from 'oak-domain/lib/types/Entity';
import { WebComponentProps } from '../../../types/Page';
import { OakAbsDerivedAttrDef } from '../../../types/AbstractComponent';
@ -6,4 +7,4 @@ export default function Render(props: WebComponentProps<EntityDict & BaseEntityD
value: string | string[];
type: OakAbsDerivedAttrDef['type'];
color: string;
}, {}>): import("react/jsx-runtime").JSX.Element;
}, {}>): React.JSX.Element;

View File

@ -1,4 +1,4 @@
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
import React from 'react';
import { Space, Typography } from 'antd';
import ImgBox from '../../imgBox';
const { Link, Text } = Typography;
@ -6,19 +6,29 @@ export default function Render(props) {
const { methods, data: oakData } = props;
const { value, type, color } = oakData;
if (value === null || value === '' || value === undefined) {
return (_jsx(_Fragment, { children: "--" }));
return (<>--</>);
}
else if (type === 'image') {
if (value instanceof Array) {
return (_jsx(Space, { children: value.map((ele) => (_jsx(ImgBox, { src: ele, width: 100, height: 60 }))) }));
return (<Space>
{value.map((ele) => (<ImgBox src={ele} width={100} height={60}/>))}
</Space>);
}
return (_jsx(ImgBox, { src: value, width: 100, height: 60 }));
return (<ImgBox src={value} width={100} height={60}/>);
}
else if (type === 'link') {
if (value instanceof Array) {
return (_jsx(Space, { direction: "vertical", children: value.map((ele) => (_jsx(Link, { href: ele, target: "_blank", ellipsis: true, children: ele }))) }));
return (<Space direction="vertical">
{value.map((ele) => (<Link href={ele} target="_blank" ellipsis>
{ele}
</Link>))}
</Space>);
}
return (_jsx(Link, { href: value, target: "_blank", ellipsis: true, children: value }));
return (<Link href={value} target="_blank" ellipsis>
{value}
</Link>);
}
return (_jsx(Text, { ellipsis: true, children: value }));
return (<Text ellipsis>
{value}
</Text>);
}

View File

@ -1,3 +1,4 @@
import React from 'react';
import { EntityDict } from 'oak-domain/lib/types/Entity';
import { WebComponentProps } from '../../../types/Page';
import { OakAbsDerivedAttrDef } from '../../../types/AbstractComponent';
@ -7,4 +8,4 @@ export default function Render(props: WebComponentProps<EntityDict & BaseEntityD
type: OakAbsDerivedAttrDef['type'];
color: string;
linkUrl: string;
}, {}>): import("react/jsx-runtime").JSX.Element;
}, {}>): React.JSX.Element;

View File

@ -1,4 +1,4 @@
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
import React from 'react';
import { Space, Tag, Tooltip, Typography } from 'antd';
import ImgBox from '../../imgBox';
const { Link } = Typography;
@ -6,7 +6,7 @@ export default function Render(props) {
const { methods, data: oakData } = props;
const { value, type, color, linkUrl } = oakData;
if (value === null || value === '' || value === undefined) {
return (_jsx(_Fragment, { children: "--" }));
return (<>--</>);
}
// 属性类型是enum要使用标签
else if (type === 'enum') {
@ -18,26 +18,38 @@ export default function Render(props) {
if (renderColor === 'danger') {
renderColor = 'error';
}
return (_jsx(Tag, { color: renderColor, children: value }));
return (<Tag color={renderColor}>
{value}
</Tag>);
}
else if (type === 'image') {
if (value instanceof Array) {
return (_jsx(Space, { children: value.map((ele) => (_jsx(ImgBox, { src: ele, width: 120, height: 70 }))) }));
return (<Space>
{value.map((ele) => (<ImgBox src={ele} width={120} height={70}/>))}
</Space>);
}
return (_jsx(ImgBox, { src: value, width: 120, height: 70 }));
return (<ImgBox src={value} width={120} height={70}/>);
}
else if (type === 'link') {
let href = linkUrl;
if (value instanceof Array) {
return (_jsx(Space, { direction: "vertical", children: value.map((ele) => {
return (<Space direction="vertical">
{value.map((ele) => {
href = ele;
if (linkUrl) {
href = linkUrl;
}
return (_jsx(Link, { href: href, children: ele }));
}) }));
return (<Link href={href}>
{ele}
</Link>);
})}
</Space>);
}
return (_jsx(Link, { href: href, children: value }));
return (<Link href={href}>
{value}
</Link>);
}
return (_jsx(Tooltip, { placement: "topLeft", title: value, children: value }));
return (<Tooltip placement="topLeft" title={value}>
{value}
</Tooltip>);
}

View File

@ -1,3 +1,4 @@
import React from 'react';
import { ButtonProps } from 'antd';
type buttonProps = {
label: string;
@ -9,5 +10,5 @@ type ToolBarProps = {
buttonGroup?: buttonProps[];
reload: () => void;
};
declare function ToolBar(props: ToolBarProps): import("react/jsx-runtime").JSX.Element;
declare function ToolBar(props: ToolBarProps): React.JSX.Element;
export default ToolBar;

View File

@ -1,4 +1,4 @@
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import React from 'react';
import { Space, Tooltip } from 'antd';
import { ReloadOutlined } from '@ant-design/icons';
import ButtonGroup from '../buttonGroup';
@ -8,8 +8,21 @@ import Style from './index.module.less';
function ToolBar(props) {
const { title, buttonGroup, reload } = props;
const features = useFeatures();
return (_jsxs("div", { className: Style.toolbarContainer, children: [_jsx("div", { className: Style.title, children: title }), _jsx("div", { className: Style.toolbarRight, children: _jsxs(Space, { children: [buttonGroup && buttonGroup.length > 0 && (_jsx(ButtonGroup, { items: buttonGroup })), _jsx(Tooltip, { title: features.locales.t('reload'), children: _jsx("div", { className: Style.reloadIconBox, onClick: () => {
reload();
}, children: _jsx(ReloadOutlined, {}) }) }), _jsx(ColumnSetting, {})] }) })] }));
return (<div className={Style.toolbarContainer}>
<div className={Style.title}>{title}</div>
<div className={Style.toolbarRight}>
<Space>
{buttonGroup && buttonGroup.length > 0 && (<ButtonGroup items={buttonGroup}/>)}
<Tooltip title={features.locales.t('reload')}>
<div className={Style.reloadIconBox} onClick={() => {
reload();
}}>
<ReloadOutlined />
</div>
</Tooltip>
<ColumnSetting />
</Space>
</div>
</div>);
}
export default ToolBar;

View File

@ -25,5 +25,5 @@ export default function Render(props: WebComponentProps<EntityDict & BaseEntityD
type: 'single' | 'multiple' | 'none';
}) => void;
};
}, {}>): import("react/jsx-runtime").JSX.Element;
}, {}>): React.JSX.Element;
export {};

View File

@ -1,5 +1,4 @@
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { useState } from 'react';
import React, { useState } from 'react';
import { Spin } from 'antd';
import ActionBtn from '../actionBtn';
import styles from './mobile.module.less';
@ -11,32 +10,55 @@ export default function Render(props) {
const { oakLoading, entity, extraActions, mobileData, onAction, disabledOp = false, rowSelection } = data;
const useSelect = !!rowSelection?.type;
const [selectedRowKeys, setSelectedRowKeys] = useState([]);
return (_jsx("div", { className: styles.container, children: oakLoading ? (_jsx("div", { className: styles.loadingView, children: _jsx(Spin, { size: 'large' }) })) : (_jsx(_Fragment, { children: mobileData && mobileData.map((ele) => (_jsxs("div", { style: { display: 'flex', alignItems: 'center', flex: 1 }, children: [useSelect && (_jsx(Checkbox, { checked: selectedRowKeys.includes(ele.record.id), onChange: (checked) => {
if (checked) {
selectedRowKeys.push(ele.record.id);
setSelectedRowKeys([...selectedRowKeys]);
}
else {
const index = selectedRowKeys.findIndex((ele2) => ele2 === ele.record.id);
selectedRowKeys.splice(index, 1);
setSelectedRowKeys([...selectedRowKeys]);
}
} })), _jsxs("div", { className: styles.card, onClick: () => {
const index = selectedRowKeys.findIndex((ele2) => ele2 === ele.record?.id);
let keys = selectedRowKeys;
if (rowSelection?.type === 'checkbox') {
if (index !== -1) {
keys.splice(index, 1);
}
else {
keys.push(ele.record?.id);
}
setSelectedRowKeys([...selectedRowKeys]);
}
else {
keys = [ele.record?.id];
setSelectedRowKeys([ele.record?.id]);
}
rowSelection?.onChange && rowSelection?.onChange(keys, ele.record, { type: rowSelection.type === 'checkbox' ? 'multiple' : 'single' });
}, children: [_jsx("div", { className: styles.cardContent, children: ele.data.map((ele2) => (_jsxs("div", { className: styles.textView, children: [_jsx("div", { className: styles.label, children: ele2.label }), _jsx("div", { className: styles.value, children: _jsx(RenderCell, { value: ele2.value, type: ele2.type }) })] }))) }), !disabledOp && (_jsx("div", { style: { display: 'flex', alignItems: 'center', padding: 10 }, children: _jsx(ActionBtn, { entity: entity, extraActions: extraActions, actions: ele.record?.['#oakLegalActions'], cascadeActions: ele.record?.['#oakLegalCascadeActions'], onAction: (action, cascadeAction) => onAction && onAction(ele.record, action, cascadeAction) }) }))] })] }))) })) }));
return (<div className={styles.container}>
{oakLoading ? (<div className={styles.loadingView}>
<Spin size='large'/>
</div>) : (<>
{mobileData && mobileData.map((ele) => (<div style={{ display: 'flex', alignItems: 'center', flex: 1 }}>
{useSelect && (<Checkbox checked={selectedRowKeys.includes(ele.record.id)} onChange={(checked) => {
if (checked) {
selectedRowKeys.push(ele.record.id);
setSelectedRowKeys([...selectedRowKeys]);
}
else {
const index = selectedRowKeys.findIndex((ele2) => ele2 === ele.record.id);
selectedRowKeys.splice(index, 1);
setSelectedRowKeys([...selectedRowKeys]);
}
}}/>)}
<div className={styles.card} onClick={() => {
const index = selectedRowKeys.findIndex((ele2) => ele2 === ele.record?.id);
let keys = selectedRowKeys;
if (rowSelection?.type === 'checkbox') {
if (index !== -1) {
keys.splice(index, 1);
}
else {
keys.push(ele.record?.id);
}
setSelectedRowKeys([...selectedRowKeys]);
}
else {
keys = [ele.record?.id];
setSelectedRowKeys([ele.record?.id]);
}
rowSelection?.onChange && rowSelection?.onChange(keys, ele.record, { type: rowSelection.type === 'checkbox' ? 'multiple' : 'single' });
}}>
<div className={styles.cardContent}>
{ele.data.map((ele2) => (<div className={styles.textView}>
<div className={styles.label}>
{ele2.label}
</div>
<div className={styles.value}>
<RenderCell value={ele2.value} type={ele2.type}/>
</div>
</div>))}
</div>
{!disabledOp && (<div style={{ display: 'flex', alignItems: 'center', padding: 10 }}>
<ActionBtn entity={entity} extraActions={extraActions} actions={ele.record?.['#oakLegalActions']} cascadeActions={ele.record?.['#oakLegalCascadeActions']} onAction={(action, cascadeAction) => onAction && onAction(ele.record, action, cascadeAction)}/>
</div>)}
</div>
</div>))}
</>)}
</div>);
}

View File

@ -1,3 +1,4 @@
import React from 'react';
import { TableProps } from 'antd';
import { EntityDict } from 'oak-domain/lib/types/Entity';
import { WebComponentProps } from '../../types/Page';
@ -21,4 +22,4 @@ export default function Render(props: WebComponentProps<EntityDict & BaseEntityD
i18n: any;
hideHeader?: boolean;
judgeAttributes: OakAbsAttrJudgeDef[];
}, {}>): import("react/jsx-runtime").JSX.Element;
}, {}>): React.JSX.Element;

View File

@ -1,5 +1,4 @@
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
import { useState, useEffect, useContext } from 'react';
import React, { useState, useEffect, useContext } from 'react';
import { Table } from 'antd';
import { assert } from 'oak-domain/lib/utils/assert';
import { get } from 'oak-domain/lib/utils/lodash';
@ -44,7 +43,7 @@ export default function Render(props) {
const stateValue = get(row, ele.path);
let href = '';
if ([null, undefined, ''].includes(stateValue)) {
return _jsx(_Fragment, {});
return <></>;
}
const color = colorDict && colorDict[ele.entity]?.[ele.attr]?.[stateValue];
if (type === 'enum' && !color) {
@ -53,7 +52,7 @@ export default function Render(props) {
if (type === 'link') {
href = getLinkUrl(ele.attribute, { oakId: row?.id });
}
return (_jsx(TableCell, { color: color, value: value, type: type, linkUrl: href }));
return (<TableCell color={color} value={value} type={type} linkUrl={href}/>);
}
};
if (width) {
@ -79,26 +78,26 @@ export default function Render(props) {
render: (value, row) => {
const oakActions = row?.['#oakLegalActions'];
// assert(!!oakActions, '行数据中不存在#oakLegalActions, 请禁用(disableOp:true)或添加actions')
return (_jsx(ActionBtn, { entity: entity, extraActions: extraActions, actions: oakActions || [], cascadeActions: row?.['#oakLegalCascadeActions'], onAction: (action, cascadeAction) => onAction && onAction(row, action, cascadeAction) }));
return (<ActionBtn entity={entity} extraActions={extraActions} actions={oakActions || []} cascadeActions={row?.['#oakLegalCascadeActions']} onAction={(action, cascadeAction) => onAction && onAction(row, action, cascadeAction)}/>);
}
});
}
setTabelColumns(tableColumns);
}
}, [data, zhCNKeys, schema, tableAttributes]);
return (_jsx(Table, { rowKey: "id", rowSelection: rowSelection?.type && {
return (<Table rowKey="id" rowSelection={rowSelection?.type && {
type: rowSelection?.type,
selectedRowKeys,
onChange: (selectedRowKeys, row, info) => {
rowSelection?.onChange &&
rowSelection?.onChange(selectedRowKeys, row, info);
},
}, loading: loading, dataSource: data, columns: tableColumns, pagination: tablePagination, scroll: showScroll
}} loading={loading} dataSource={data} columns={tableColumns} pagination={tablePagination} scroll={showScroll
? {
scrollToFirstRowOnChange: true,
x: 1200,
}
: {}, onRow: (record) => {
: {}} onRow={(record) => {
return {
onClick: () => {
const index = selectedRowKeys.findIndex((ele) => ele === record.id);
@ -119,5 +118,5 @@ export default function Render(props) {
rowSelection?.onChange(keys, row, { type: 'all' });
},
};
}, showHeader: !hideHeader }));
}} showHeader={!hideHeader}></Table>);
}

View File

@ -38,5 +38,5 @@ export declare const TableContext: React.Context<{
setSchema: ((schema: any) => void) | undefined;
onReset: (() => void) | undefined;
}>;
declare const ProList: <ED2 extends ED, T extends keyof ED2>(props: Props<ED2, T>) => import("react/jsx-runtime").JSX.Element;
declare const ProList: <ED2 extends ED, T extends keyof ED2>(props: Props<ED2, T>) => React.JSX.Element;
export default ProList;

View File

@ -1,5 +1,4 @@
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { createContext, useEffect, useState } from 'react';
import React, { createContext, useEffect, useState } from 'react';
import { translateAttributes } from '../../utils/usefulFn';
import List from '../list';
import ToolBar from '../list/toolBar';
@ -57,7 +56,7 @@ const ProList = (props) => {
const totalStr = features.locales.t('total number of rows');
return `${totalStr}${total > 999 ? `${total} +` : total}`;
};
return (_jsx(TableContext.Provider, { value: {
return (<TableContext.Provider value={{
tableAttributes,
entity: entity,
schema,
@ -66,22 +65,28 @@ const ProList = (props) => {
onReset: () => {
initTableAttributes();
},
}, children: _jsxs("div", { className: Style.container, children: [!isMobile && (_jsx(ToolBar, { title: title, buttonGroup: buttonGroup, reload: () => {
onReload && onReload();
} })), isMobile && _jsx(ButtonGroup, { items: buttonGroup }), _jsx(List, { entity: entity, extraActions: extraActions, onAction: onAction, disabledOp: disabledOp, attributes: attributes, data: !disableSerialNumber
? data?.map((ele, index) => {
if (tablePagination) {
const total = tablePagination.total || 0;
const pageSize = tablePagination.pageSize || 20; //条数
const current = tablePagination.current || 1; //当前页
ele['#'] =
pageSize * (current - 1) +
(index + 1);
}
return ele;
})
: data, loading: loading, tablePagination: Object.assign({
showTotal,
}, tablePagination), rowSelection: rowSelection })] }) }));
}}>
<div className={Style.container}>
{!isMobile && (<ToolBar title={title} buttonGroup={buttonGroup} reload={() => {
onReload && onReload();
}}/>)}
{isMobile && <ButtonGroup items={buttonGroup}/>}
<List entity={entity} extraActions={extraActions} onAction={onAction} disabledOp={disabledOp} attributes={attributes} data={!disableSerialNumber
? data?.map((ele, index) => {
if (tablePagination) {
const total = tablePagination.total || 0;
const pageSize = tablePagination.pageSize || 20; //条数
const current = tablePagination.current || 1; //当前页
ele['#'] =
pageSize * (current - 1) +
(index + 1);
}
return ele;
})
: data} loading={loading} tablePagination={Object.assign({
showTotal,
}, tablePagination)} rowSelection={rowSelection}/>
</div>
</TableContext.Provider>);
};
export default ProList;

View File

@ -1,3 +1,4 @@
import React from "react";
type LocationProps = {
poiName?: string;
coordinate?: [number, number];
@ -15,5 +16,5 @@ export type Poi = {
detail: string;
coordinate: [number, number];
};
export default function Location(props: LocationProps): import("react/jsx-runtime").JSX.Element;
export default function Location(props: LocationProps): React.JSX.Element;
export {};

View File

@ -1,4 +1,3 @@
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import React, { useState, useRef, useEffect } from "react";
import { Row, Col, Input, List, Empty, Spin, } from 'antd';
import { SearchOutlined, CheckCircleFilled } from '@ant-design/icons';
@ -31,39 +30,67 @@ export default function Location(props) {
}
}, [searchValue]);
const center = currentPoi?.coordinate || props.coordinate;
const Locate = (_jsx(List, { className: Styles["location-list"], header: _jsx(Input, { ref: searchRef, placeholder: "\u8BF7\u8F93\u5165\u5B8C\u6574\u540D\u79F0\uFF08\u5982\u201C\u6D59\u6C5F\u5927\u5B66\u201D\uFF09\u800C\u975E\u7B80\u79F0\uFF08\u5982\u201C\u6D59\u5927\u201D\uFF09", value: searchValue, allowClear: true, onChange: (e) => {
const Locate = (<List className={Styles["location-list"]} header={<Input ref={searchRef} placeholder="请输入完整名称(如“浙江大学”)而非简称(如“浙大”)" value={searchValue} allowClear onChange={(e) => {
setSearchValue(e.target.value);
}, prefix: _jsx(SearchOutlined, {}), onFocus: () => {
}} prefix={<SearchOutlined />} onFocus={() => {
setMode('searchPoi');
}, onBlur: () => {
} }), children: mode === 'searchPoi' && (_jsx(React.Fragment, { children: searchLoading ? (_jsx("div", { className: Styles['location-list-meta'], children: _jsx(Spin, { delay: 0, spinning: true, size: "default" }) })) : (pois?.length
}} onBlur={() => {
}}/>}>
{mode === 'searchPoi' && (<React.Fragment>
{searchLoading ? (<div className={Styles['location-list-meta']}>
<Spin delay={0} spinning size="default"/>
</div>) : (pois?.length
? pois.map((poi, index) => {
return (_jsx("div", { onClick: () => {
return (<div key={poi.id} onClick={() => {
setCurrentPoi(poi);
props.onLocated({
poiName: poi.detail,
coordinate: poi.coordinate,
areaId: poi.areaId,
});
}, children: _jsx(List.Item, { actions: [
_jsx("div", { style: {
width: 24,
}, children: currentPoi?.id ===
poi.id && (_jsx(CheckCircleFilled, { className: Styles['location-list-checked'] })) }),
], children: _jsx(List.Item.Meta, { title: poi.detail }) }) }, poi.id));
}}>
<List.Item actions={[
<div style={{
width: 24,
}}>
{currentPoi?.id ===
poi.id && (<CheckCircleFilled className={Styles['location-list-checked']}/>)}
</div>,
]}>
<List.Item.Meta title={poi.detail}/>
</List.Item>
</div>);
})
: (_jsx("div", { className: Styles['location-list-meta'], children: _jsx(Empty, { description: `没有${searchValue}相关的地名搜索结果`, image: Empty.PRESENTED_IMAGE_SIMPLE }) }))) })) }));
: (<div className={Styles['location-list-meta']}>
<Empty description={`没有${searchValue}相关的地名搜索结果`} image={Empty.PRESENTED_IMAGE_SIMPLE}/>
</div>))}
</React.Fragment>)}
</List>);
if (window.innerWidth > 480) {
return (_jsxs(Row, { gutter: [16, 16], style: {
return (<Row gutter={[16, 16]} style={{
width: '100%',
minHeight: 600,
}, children: [_jsx(Col, { xs: 24, sm: 14, children: _jsx(Map, { style: { height: '100%' }, id: "location-map", center: center, markers: center ? [center] : undefined }) }), _jsx(Col, { xs: 24, sm: 10, children: Locate })] }));
}}>
<Col xs={24} sm={14}>
<Map style={{ height: '100%' }} id="location-map" center={center} markers={center ? [center] : undefined}/>
</Col>
<Col xs={24} sm={10}>
{Locate}
</Col>
</Row>);
}
return (_jsxs(Col, { style: {
return (<Col style={{
width: '100%',
height: '100%',
display: 'flex',
flexDirection: 'column',
alignItems: 'stretch',
}, children: [_jsx(Row, { children: _jsx(Map, { style: { height: 400, width: '100%' }, id: "location-map", center: center, markers: center ? [center] : undefined }) }), _jsx(Row, { style: { flex: 1, marginLeft: 5, marginRight: 5 }, children: Locate })] }));
}}>
<Row>
<Map style={{ height: 400, width: '100%' }} id="location-map" center={center} markers={center ? [center] : undefined}/>
</Row>
<Row style={{ flex: 1, marginLeft: 5, marginRight: 5 }}>
{Locate}
</Row>
</Col>);
}

View File

@ -1,3 +1,4 @@
import React from 'react';
import 'ol/ol.css';
type MapProps = {
id?: string;
@ -10,5 +11,5 @@ type MapProps = {
autoLocate?: boolean;
markers?: Array<[number, number]>;
};
export default function Map(props: MapProps): import("react/jsx-runtime").JSX.Element;
export default function Map(props: MapProps): React.JSX.Element;
export {};

View File

@ -1,6 +1,5 @@
import { jsx as _jsx } from "react/jsx-runtime";
import { assert } from 'oak-domain/lib/utils/assert';
import { useEffect, useState } from 'react';
import React, { useEffect, useState } from 'react';
import OlMap from 'ol/Map';
import Feature from 'ol/Feature';
import XYZ from 'ol/source/XYZ';
@ -117,5 +116,5 @@ export default function Map(props) {
map.render();
}
}, [props.markers]);
return (_jsx("div", { id: `map-${id || prefix}`, className: Styles.map, style: props.style }));
return (<div id={`map-${id || prefix}`} className={Styles.map} style={props.style}/>);
}

View File

@ -1,3 +1,4 @@
import React from 'react';
type Props = {
items: Array<{
title: string;
@ -5,5 +6,5 @@ type Props = {
}>;
title: string;
};
export default function Render(props: Props): import("react/jsx-runtime").JSX.Element;
export default function Render(props: Props): React.JSX.Element;
export {};

View File

@ -1,18 +1,21 @@
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
import React from 'react';
import { Breadcrumb, Divider } from 'antd';
export default function Render(props) {
const { items, title } = props;
const items2 = items.concat({ title });
return (_jsxs(_Fragment, { children: [_jsx(Breadcrumb, { items: items2.map((ele) => {
const { title, href } = ele;
if (href) {
return {
title,
href,
};
}
return {
title,
};
}) }), _jsx(Divider, { style: { marginTop: 4 } })] }));
return (<>
<Breadcrumb items={items2.map((ele) => {
const { title, href } = ele;
if (href) {
return {
title,
href,
};
}
return {
title,
};
})}/>
<Divider style={{ marginTop: 4 }}/>
</>);
}

View File

@ -23,5 +23,5 @@ type PageHeaderProps = {
type ED = EntityDict & BaseEntityDict;
export default function Render(props: WebComponentProps<ED, keyof ED, false, PageHeaderProps, {
goBack: (delta?: number) => void;
}>): import("react/jsx-runtime").JSX.Element;
}>): React.JSX.Element;
export {};

View File

@ -1,4 +1,4 @@
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import React from 'react';
import { Row, Col, Button } from 'antd';
import { ArrowLeftOutlined } from '@ant-design/icons';
import classNames from 'classnames';
@ -7,13 +7,35 @@ export default function Render(props) {
const { style, className, children, title, subTitle, extra, showBack = false, onBack, backIcon, delta, contentMargin = true, contentStyle, contentClassName, tags, showHeader = true, } = props.data;
const { t, goBack } = props.methods;
const prefixCls = 'oak';
return (_jsxs("div", { style: style, className: classNames(`${prefixCls}-pageHeader`, className), children: [showHeader && (title || showBack || subTitle || tags || extra) && (_jsx("div", { className: `${prefixCls}-pageHeader-header`, children: _jsxs(Row, { justify: "center", children: [_jsxs(Col, { flex: "auto", className: `${prefixCls}-pageHeader-header-col`, children: [showBack && (_jsx(Button, { type: "text", className: `${prefixCls}-pageHeader-header-back`, onClick: () => {
if (typeof onBack === 'function') {
onBack();
return;
}
goBack(delta);
}, children: backIcon || (_jsx(ArrowLeftOutlined, { className: `${prefixCls}-pageHeader-header-backIcon` })) })), title && (_jsx("span", { className: `${prefixCls}-pageHeader-header-title`, children: title })), subTitle && (_jsx("span", { className: `${prefixCls}-pageHeader-header-subTitle`, children: subTitle })), tags] }), _jsx(Col, { flex: "auto", children: extra })] }) })), _jsx("div", { style: contentStyle, className: classNames(`${prefixCls}-pageHeader-content`, contentClassName, {
[`${prefixCls}-pageHeader-content-margin`]: contentMargin,
}), children: children })] }));
return (<div style={style} className={classNames(`${prefixCls}-pageHeader`, className)}>
{showHeader && (title || showBack || subTitle || tags || extra) && (<div className={`${prefixCls}-pageHeader-header`}>
<Row justify="center">
<Col flex="auto" className={`${prefixCls}-pageHeader-header-col`}>
{showBack && (<Button type="text" className={`${prefixCls}-pageHeader-header-back`} onClick={() => {
if (typeof onBack === 'function') {
onBack();
return;
}
goBack(delta);
}}>
{backIcon || (<ArrowLeftOutlined className={`${prefixCls}-pageHeader-header-backIcon`}/>)}
</Button>)}
{title && (<span className={`${prefixCls}-pageHeader-header-title`}>
{title}
</span>)}
{subTitle && (<span className={`${prefixCls}-pageHeader-header-subTitle`}>
{subTitle}
</span>)}
{tags}
</Col>
<Col flex="auto">{extra}</Col>
</Row>
</div>)}
<div style={contentStyle} className={classNames(`${prefixCls}-pageHeader-content`, contentClassName, {
[`${prefixCls}-pageHeader-content-margin`]: contentMargin,
})}>
{children}
</div>
</div>);
}

View File

@ -1,3 +1,4 @@
import React from 'react';
import { WebComponentProps, RowWithActions } from '../../types/Page';
import { ED } from '../../types/AbstractComponent';
export default function Render(props: WebComponentProps<ED, keyof ED, false, {
@ -7,4 +8,4 @@ export default function Render(props: WebComponentProps<ED, keyof ED, false, {
onSelect: (rows: RowWithActions<ED, keyof ED>[]) => void;
multiple: boolean;
titleLabel: string;
}, {}>): import("react/jsx-runtime").JSX.Element;
}, {}>): React.JSX.Element;

View File

@ -1,4 +1,4 @@
import { jsx as _jsx } from "react/jsx-runtime";
import React from 'react';
import { Empty } from 'antd';
import AbstractList from '../list';
export default function Render(props) {
@ -9,12 +9,14 @@ export default function Render(props) {
title: titleLabel,
}];
if (rows && rows.length) {
return (_jsx(AbstractList, { entity: entity, data: rows, loading: oakLoading, attributes: [titleLabel], disabledOp: true, rowSelection: {
return (<AbstractList entity={entity} data={rows} loading={oakLoading} attributes={[titleLabel]} disabledOp={true} rowSelection={{
type: multiple ? 'checkbox' : 'radio',
onChange: (selectRowKeys, selectedRows, info) => {
onSelect(selectedRows);
}
} }));
}}/>);
}
return (_jsx("div", { children: _jsx(Empty, { image: Empty.PRESENTED_IMAGE_SIMPLE }) }));
return (<div>
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE}/>
</div>);
}

View File

@ -1,3 +1,4 @@
import React from 'react';
import { EntityDict } from 'oak-domain/lib/types/Entity';
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
import { OakAbsRefAttrPickerRender } from '../../types/AbstractComponent';
@ -16,5 +17,5 @@ export default function render(props: WebComponentProps<ED, keyof EntityDict, fa
pickerRender: OakAbsRefAttrPickerRender<ED, keyof ED>;
onChange: (value: string[]) => void;
schema: StorageSchema<EntityDict & BaseEntityDict>;
}>): import("react/jsx-runtime").JSX.Element;
}>): React.JSX.Element;
export {};

View File

@ -1,5 +1,4 @@
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useState } from 'react';
import React, { useState } from 'react';
import { Checkbox, Input, Radio, Popup, Space, Selector, } from 'antd-mobile';
import Picker from '../picker';
import { combineFilters } from 'oak-domain/lib/store/filter';
@ -12,70 +11,79 @@ export default function render(props) {
const [dynamicSorter, setDynamicSorter] = useState(undefined);
const [dynamicProjection, setDynamicProjection] = useState(undefined);
if (!data && mode !== 'list') {
return _jsx("div", { children: " loading... " });
return <div> loading... </div>;
}
else {
switch (mode) {
case 'select': {
return (_jsx(Selector, { value: [entityId], onChange: (value) => {
return (<Selector value={[entityId]} onChange={(value) => {
onChange(value);
}, options: data.map((ele) => ({
}} options={data.map((ele) => ({
value: ele.id,
label: ele.title,
})), multiple: multiple }));
}))} multiple={multiple}></Selector>);
}
case 'radio': {
if (multiple) {
return (_jsx(Checkbox.Group, { value: entityIds, onChange: (value) => onChange(value), children: data.map((ele) => (_jsx(Checkbox, { value: ele.id, children: ele.title }))) }));
return (<Checkbox.Group value={entityIds} onChange={(value) => onChange(value)}>
{data.map((ele) => (<Checkbox value={ele.id}>{ele.title}</Checkbox>))}
</Checkbox.Group>);
}
return (_jsx(Radio.Group, { onChange: (value) => onChange([value]), value: entityId, children: data.map((ele) => (_jsx(Radio, { value: ele.id, children: ele.title }))) }));
return (<Radio.Group onChange={(value) => onChange([value])} value={entityId}>
{data.map((ele) => (<Radio value={ele.id}>{ele.title}</Radio>))}
</Radio.Group>);
}
case 'list': {
const { entity, projection, title, titleLabel, filter, sorter, required, getDynamicSelectors, } = pickerRender;
return (_jsxs(Space, { children: [_jsx(Input, { value: renderValue, clearable: !required, onClick: async () => {
if (getDynamicSelectors) {
// todo 这段代码没测过
const { projection: dynamicProjection2, filter: dynamicFilter2, sorter: dynamicSorter2, } = await getDynamicSelectors();
if (dynamicFilter2 || filter) {
setDynamicFilter(combineFilters(entity, schema, [
dynamicFilter2,
filter,
]));
}
if (dynamicSorter2 || sorter) {
setDynamicSorter(dynamicSorter2 || sorter);
}
if (dynamicProjection2 || projection) {
setDynamicProjection(dynamicProjection2 || projection);
}
}
else {
if (filter) {
setDynamicFilter(filter);
}
if (sorter) {
setDynamicSorter(sorter);
}
if (projection) {
setDynamicProjection(projection);
}
}
setVisible(true);
}, onChange: (value) => {
if (!value) {
onChange([]);
}
} }), _jsx(Popup, { visible: visibile, closeOnMaskClick: true, onClose: () => {
setDynamicFilter(undefined);
setDynamicProjection(undefined);
setDynamicSorter(undefined);
setVisible(false);
}, destroyOnClose: true, showCloseButton: true, bodyStyle: {
height: '80%',
}, children: _jsx(Picker, { multiple: false, oakPath: `$refAttr-picker-${entity}`, entity: entity, title: title, titleLabel: titleLabel, filter: dynamicFilter, sorter: dynamicSorter, projection: dynamicProjection, onSelect: (data) => {
onChange(data.map((ele) => ele.id));
setVisible(false);
} }) })] }));
return (<Space>
<Input value={renderValue} clearable={!required} onClick={async () => {
if (getDynamicSelectors) {
// todo 这段代码没测过
const { projection: dynamicProjection2, filter: dynamicFilter2, sorter: dynamicSorter2, } = await getDynamicSelectors();
if (dynamicFilter2 || filter) {
setDynamicFilter(combineFilters(entity, schema, [
dynamicFilter2,
filter,
]));
}
if (dynamicSorter2 || sorter) {
setDynamicSorter(dynamicSorter2 || sorter);
}
if (dynamicProjection2 || projection) {
setDynamicProjection(dynamicProjection2 || projection);
}
}
else {
if (filter) {
setDynamicFilter(filter);
}
if (sorter) {
setDynamicSorter(sorter);
}
if (projection) {
setDynamicProjection(projection);
}
}
setVisible(true);
}} onChange={(value) => {
if (!value) {
onChange([]);
}
}}/>
<Popup visible={visibile} closeOnMaskClick={true} onClose={() => {
setDynamicFilter(undefined);
setDynamicProjection(undefined);
setDynamicSorter(undefined);
setVisible(false);
}} destroyOnClose={true} showCloseButton={true} bodyStyle={{
height: '80%',
}}>
<Picker multiple={false} oakPath={`$refAttr-picker-${entity}`} entity={entity} title={title} titleLabel={titleLabel} filter={dynamicFilter} sorter={dynamicSorter} projection={dynamicProjection} onSelect={(data) => {
onChange(data.map((ele) => ele.id));
setVisible(false);
}}/>
</Popup>
</Space>);
}
}
}

View File

@ -1,3 +1,4 @@
import React from 'react';
import { EntityDict } from 'oak-domain/lib/types/Entity';
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
import { OakAbsRefAttrPickerRender } from '../../types/AbstractComponent';
@ -16,5 +17,5 @@ export default function render(props: WebComponentProps<ED, keyof EntityDict, fa
onChange: (value: string[]) => void;
placeholder: string;
schema: StorageSchema<EntityDict & BaseEntityDict>;
}>): import("react/jsx-runtime").JSX.Element;
}>): React.JSX.Element;
export {};

View File

@ -1,5 +1,4 @@
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useState } from 'react';
import React, { useState } from 'react';
import { Checkbox, Input, Radio, Modal, Space, Select, } from 'antd';
import Picker from '../picker';
import { combineFilters } from 'oak-domain/lib/store/filter';
@ -12,13 +11,13 @@ export default function render(props) {
const [dynamicSorter, setDynamicSorter] = useState(undefined);
const [dynamicProjection, setDynamicProjection] = useState(undefined);
if (!data && mode !== 'list') {
return _jsx("div", { children: " loading... " });
return <div> loading... </div>;
}
else {
switch (mode) {
case 'select': {
const entityId = entityIds && entityIds[0];
return (_jsx(Select, { placeholder: placeholder, mode: multiple ? 'multiple' : undefined, value: multiple ? entityIds : entityId, onChange: (value) => {
return (<Select placeholder={placeholder} mode={multiple ? 'multiple' : undefined} value={multiple ? entityIds : entityId} onChange={(value) => {
if (typeof value === 'string') {
onChange([value]);
}
@ -28,68 +27,73 @@ export default function render(props) {
else if (value instanceof Array) {
onChange(value);
}
}, options: data.map((ele) => ({
}} options={data.map((ele) => ({
value: ele.id,
label: ele.title,
})), allowClear: !pickerRender.required }));
}))} allowClear={!pickerRender.required}></Select>);
}
case 'radio': {
const entityId = entityIds && entityIds[0];
if (multiple) {
return (_jsx(Checkbox.Group, { options: data.map((ele) => ({
return (<Checkbox.Group options={data.map((ele) => ({
value: ele.id,
label: ele.title,
})), value: entityIds, onChange: (value) => onChange(value) }));
}))} value={entityIds} onChange={(value) => onChange(value)}/>);
}
return (_jsx(Radio.Group, { onChange: ({ target }) => onChange(target.value), value: entityId, options: data.map((ele) => ({
return (<Radio.Group onChange={({ target }) => onChange(target.value)} value={entityId} options={data.map((ele) => ({
value: ele.id,
label: ele.title,
})) }));
}))}></Radio.Group>);
}
case 'list': {
const { entity, projection, title, titleLabel, filter, sorter, required, getDynamicSelectors, } = pickerRender;
return (_jsxs(Space, { children: [_jsx(Input, { placeholder: placeholder, value: renderValue, allowClear: !required, onClick: async () => {
if (getDynamicSelectors) {
// todo 这段代码没测过
const { projection: dynamicProjection2, filter: dynamicFilter2, sorter: dynamicSorter2, } = await getDynamicSelectors();
if (dynamicFilter2 || filter) {
setDynamicFilter(combineFilters(entity, schema, [
dynamicFilter2,
filter,
]));
}
if (dynamicSorter2 || sorter) {
setDynamicSorter(dynamicSorter2 || sorter);
}
if (dynamicProjection2 || projection) {
setDynamicProjection(dynamicProjection2 || projection);
}
}
else {
if (filter) {
setDynamicFilter(filter);
}
if (sorter) {
setDynamicSorter(sorter);
}
if (projection) {
setDynamicProjection(projection);
}
}
setVisible(true);
}, onChange: ({ currentTarget }) => {
if (!currentTarget.value) {
onChange([]);
}
} }), _jsx(Modal, { title: `选择${t(`${pickerRender.entity}:name`)}`, open: visibile, closable: true, onCancel: () => {
setDynamicFilter(undefined);
setDynamicProjection(undefined);
setDynamicSorter(undefined);
setVisible(false);
}, destroyOnClose: true, footer: null, children: _jsx(Picker, { multiple: false, oakPath: `$refAttr-picker-${entity}`, entity: entity, title: title, titleLabel: titleLabel, filter: dynamicFilter, sorter: dynamicSorter, projection: dynamicProjection || projection, onSelect: (data) => {
onChange(data.map((ele) => ele.id));
setVisible(false);
} }) })] }));
return (<Space>
<Input placeholder={placeholder} value={renderValue} allowClear={!required} onClick={async () => {
if (getDynamicSelectors) {
// todo 这段代码没测过
const { projection: dynamicProjection2, filter: dynamicFilter2, sorter: dynamicSorter2, } = await getDynamicSelectors();
if (dynamicFilter2 || filter) {
setDynamicFilter(combineFilters(entity, schema, [
dynamicFilter2,
filter,
]));
}
if (dynamicSorter2 || sorter) {
setDynamicSorter(dynamicSorter2 || sorter);
}
if (dynamicProjection2 || projection) {
setDynamicProjection(dynamicProjection2 || projection);
}
}
else {
if (filter) {
setDynamicFilter(filter);
}
if (sorter) {
setDynamicSorter(sorter);
}
if (projection) {
setDynamicProjection(projection);
}
}
setVisible(true);
}} onChange={({ currentTarget }) => {
if (!currentTarget.value) {
onChange([]);
}
}}/>
<Modal title={`选择${t(`${pickerRender.entity}:name`)}`} open={visibile} closable={true} onCancel={() => {
setDynamicFilter(undefined);
setDynamicProjection(undefined);
setDynamicSorter(undefined);
setVisible(false);
}} destroyOnClose={true} footer={null}>
<Picker multiple={false} oakPath={`$refAttr-picker-${entity}`} entity={entity} title={title} titleLabel={titleLabel} filter={dynamicFilter} sorter={dynamicSorter} projection={dynamicProjection || projection} onSelect={(data) => {
onChange(data.map((ele) => ele.id));
setVisible(false);
}}/>
</Modal>
</Space>);
}
}
}

View File

@ -1,3 +1,4 @@
/// <reference types="react" />
import { WebComponentProps } from '../../../types/Page';
import { EntityDict } from 'oak-domain/lib/types/Entity';
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
@ -23,5 +24,5 @@ export default function render(props: WebComponentProps<ED, 'actionAuth', true,
onChange: (checked: boolean, relationId: string, path: string, actionAuth?: ED['actionAuth']['Schema'][]) => void;
onChange2: (checked: boolean, relationId: string, paths: string[], actionAuths: ED['actionAuth']['Schema'][], actionAuth?: ED['actionAuth']['Schema']) => void;
confirm: () => void;
}>): import("react/jsx-runtime").JSX.Element;
}>): import("react").JSX.Element;
export {};

View File

@ -1,4 +1,3 @@
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
import { Table, Checkbox, Button, Row, Typography, Space } from 'antd';
const { Title, Text } = Typography;
import { difference, intersection } from 'oak-domain/lib/utils/lodash';
@ -6,59 +5,116 @@ import ActionAuthListSingle from '../../relation/single';
export default function render(props) {
const { cascadeEntityActions, oakDirty, actions, entity, actionAuthList } = props.data;
const { onChange, t, clean, confirm, onChange2 } = props.methods;
return (_jsxs(Space, { direction: "vertical", style: { width: '100%' }, children: [_jsx(ActionAuthListSingle, { entity: entity }), _jsx(Table, { columns: [
{
key: '1',
title: '源对象',
width: 100,
render: (value, record) => {
const { sourceEntity } = record;
return sourceEntity;
},
},
{
key: '1',
title: '路径',
width: 200,
render: (value, record) => {
const { paths } = record;
return paths.map((ele, index) => {
if (index === 0) {
return ele;
}
else {
return _jsxs(_Fragment, { children: [_jsx("br", {}), ele] });
}
});
},
},
{
fixed: 'right',
title: '相关角色',
key: 'operation',
width: 300,
render: (value, record) => {
// const { relations, actionAuths, path } = record;
const { relations, relationSelections } = record;
return (_jsx("div", { style: {
width: '100%',
display: 'flex',
flexWrap: 'wrap',
}, children: relationSelections.map((ele) => {
return (<Space direction="vertical" style={{ width: '100%' }}>
<ActionAuthListSingle entity={entity}/>
<Table columns={[
{
key: '1',
title: '源对象',
width: 100,
render: (value, record) => {
const { sourceEntity } = record;
return sourceEntity;
},
},
{
key: '1',
title: '路径',
width: 200,
render: (value, record) => {
const { paths } = record;
return paths.map((ele, index) => {
if (index === 0) {
return ele;
}
else {
return <><br />{ele}</>;
}
});
},
},
{
fixed: 'right',
title: '相关角色',
key: 'operation',
width: 300,
render: (value, record) => {
// const { relations, actionAuths, path } = record;
const { relations, relationSelections } = record;
return (<div style={{
width: '100%',
display: 'flex',
flexWrap: 'wrap',
}}>
{/* {
relations?.map(
(r) => {
let checked = false, indeterminate = false;
if (actions && actions.length > 0) {
const relation = relations.find((ele2) => ele2.relationId === ele.id && !ele2.$$deleteAt$$);
if (relation) {
const { deActions } = relation;
checked = difference(actions, deActions).length === 0;
indeterminate = !checked && intersection(actions, deActions).length > 0;
// filter出对应path的actionAuth来决定relation的check
// sort deActions长的在后不然会影响checked
const actionAuthsByPath = actionAuths?.filter((ele) => ele.paths.includes(path[1]))
.sort((a, b) => b.deActions.length - a.deActions.length);
if (actionAuthsByPath && actions.length > 0) {
for (const aa of actionAuthsByPath) {
// 1.relationId相同deActions也要相同
// 如果path中存在多对一的情况要使用name进行判断
if (!aa.$$deleteAt$$ && (aa.relationId === r.id
|| (record.path.includes('$') && aa.relation?.name === r.name))
) {
const { deActions } = aa;
checked = difference(actions, deActions).length === 0;
indeterminate = !checked && intersection(actions, deActions).length > 0;
break;
}
}
}
return _jsx(Checkbox, { disabled: actions.length === 0, checked: checked, indeterminate: indeterminate, onChange: ({ target }) => {
onChange2(target.checked, ele.id, record.paths, relations);
}, children: ele.name });
}) }));
}
}
], dataSource: actionAuthList, pagination: false }), _jsxs(Row, { justify: "end", style: { marginTop: 20, padding: 5 }, children: [_jsx(Button, { style: { marginRight: 10 }, type: 'primary', disabled: !oakDirty, onClick: () => confirm(), children: t("confirm") }), _jsx(Button, { disabled: !oakDirty, onClick: () => clean(), children: t("reset") })] })] }));
return (
<Checkbox
disabled={actions.length === 0}
checked={checked}
indeterminate={indeterminate}
onChange={({ target }) => {
const { checked } = target;
const actionAuths2 = actionAuths?.filter(
ele => ele.relationId === r.id || (record.path.includes('$') && ele.relation?.name === r.name)
);
onChange(checked, r.id, path[1], actionAuths2)
}}
>
{r.name}
</Checkbox>
)
}
)
} */}
{relationSelections.map((ele) => {
let checked = false, indeterminate = false;
if (actions && actions.length > 0) {
const relation = relations.find((ele2) => ele2.relationId === ele.id && !ele2.$$deleteAt$$);
if (relation) {
const { deActions } = relation;
checked = difference(actions, deActions).length === 0;
indeterminate = !checked && intersection(actions, deActions).length > 0;
}
}
return <Checkbox disabled={actions.length === 0} checked={checked} indeterminate={indeterminate} onChange={({ target }) => {
onChange2(target.checked, ele.id, record.paths, relations);
}}>
{ele.name}
</Checkbox>;
})}
</div>);
}
}
]} dataSource={actionAuthList} pagination={false}/>
<Row justify="end" style={{ marginTop: 20, padding: 5 }}>
<Button style={{ marginRight: 10 }} type='primary' disabled={!oakDirty} onClick={() => confirm()}>
{t("confirm")}
</Button>
<Button disabled={!oakDirty} onClick={() => clean()}>
{t("reset")}
</Button>
</Row>
</Space>);
}

View File

@ -1,3 +1,4 @@
/// <reference types="react" />
import { WebComponentProps } from '../../../types/Page';
import { EntityDict } from 'oak-domain/lib/types/Entity';
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
@ -13,5 +14,5 @@ export default function render(props: WebComponentProps<ED, 'actionAuth', true,
}, {
onChange: (actions: string[], path: any, actionAuth?: ED['actionAuth']['OpSchema']) => void;
confirm: () => void;
}>): import("react/jsx-runtime").JSX.Element;
}>): import("react").JSX.Element;
export {};

View File

@ -1,42 +1,61 @@
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { Table, Checkbox, Button, Row } from 'antd';
import { Typography } from 'antd';
const { Title, Text } = Typography;
export default function render(props) {
const { cascadeEntityActions, oakDirty, entity, relationName } = props.data;
const { onChange, t, clean, confirm } = props.methods;
return (_jsxs(_Fragment, { children: [_jsxs(Row, { justify: "center", style: { margin: 20, padding: 10 }, children: [_jsxs(Row, { style: { marginRight: 10 }, children: [_jsx(Title, { level: 4, children: "\u5F53\u524D\u5BF9\u8C61\uFF1A" }), _jsx(Text, { code: true, children: entity })] }), _jsxs(Row, { children: [_jsx(Title, { level: 4, children: "\u5F53\u524D\u89D2\u8272\uFF1A" }), _jsx(Text, { code: true, children: relationName })] })] }), _jsx(Table, { columns: [
{
key: '1',
title: '目标对象',
width: 100,
render: (value, record) => {
const { path } = record;
return path[0];
},
},
{
key: '1',
title: '路径',
width: 200,
render: (value, record) => {
const { path } = record;
return path[1];
},
},
{
fixed: 'right',
title: '操作',
key: 'operation',
width: 300,
render: (value, record) => {
const { actions, actionAuth, path } = record;
return (_jsx(Checkbox.Group, { style: {
width: '100%',
display: 'flex',
flexWrap: 'wrap',
}, options: actions, value: actionAuth?.deActions, onChange: (value) => onChange(value, path, actionAuth) }));
}
}
], dataSource: cascadeEntityActions, pagination: false }), _jsxs(Row, { justify: "end", style: { marginTop: 20, padding: 5 }, children: [_jsx(Button, { style: { marginRight: 10 }, type: 'primary', disabled: !oakDirty, onClick: () => confirm(), children: t("confirm") }), _jsx(Button, { disabled: !oakDirty, onClick: () => clean(), children: t("reset") })] })] }));
return (<>
<Row justify="center" style={{ margin: 20, padding: 10 }}>
<Row style={{ marginRight: 10 }}>
<Title level={4}>当前对象</Title>
<Text code>{entity}</Text>
</Row>
<Row>
<Title level={4}>当前角色</Title>
<Text code>{relationName}</Text>
</Row>
</Row>
<Table columns={[
{
key: '1',
title: '目标对象',
width: 100,
render: (value, record) => {
const { path } = record;
return path[0];
},
},
{
key: '1',
title: '路径',
width: 200,
render: (value, record) => {
const { path } = record;
return path[1];
},
},
{
fixed: 'right',
title: '操作',
key: 'operation',
width: 300,
render: (value, record) => {
const { actions, actionAuth, path } = record;
return (<Checkbox.Group style={{
width: '100%',
display: 'flex',
flexWrap: 'wrap',
}} options={actions} value={actionAuth?.deActions} onChange={(value) => onChange(value, path, actionAuth)}/>);
}
}
]} dataSource={cascadeEntityActions} pagination={false}/>
<Row justify="end" style={{ marginTop: 20, padding: 5 }}>
<Button style={{ marginRight: 10 }} type='primary' disabled={!oakDirty} onClick={() => confirm()}>
{t("confirm")}
</Button>
<Button disabled={!oakDirty} onClick={() => clean()}>
{t("reset")}
</Button>
</Row>
</>);
}

View File

@ -1,3 +1,4 @@
import React from 'react';
import { WebComponentProps } from '../../../types/Page';
import { EntityDict } from 'oak-domain/lib/types/Entity';
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
@ -16,5 +17,5 @@ export default function render(props: WebComponentProps<ED, 'actionAuth', true,
entity: keyof ED;
openTip: boolean;
onClose: () => void;
}, {}>): import("react/jsx-runtime").JSX.Element;
}, {}>): React.JSX.Element;
export {};

View File

@ -1,5 +1,4 @@
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { useState, useEffect } from 'react';
import React, { useState, useEffect } from 'react';
import { Table, Checkbox, Button, Space, } from 'antd';
import { Typography } from 'antd';
const { Title, Text } = Typography;
@ -15,60 +14,70 @@ export default function render(props) {
}));
setDatasource(tableRows);
}, [relations]);
return (_jsxs(Space, { direction: "vertical", style: { width: '100%' }, children: [_jsx(Space, { children: _jsx(Text, { style: { fontSize: 16 }, children: "\u6388\u6743" }) }), _jsx(Table, { rowKey: 'relationId', dataSource: datasource, columns: [
{
width: 200,
dataIndex: 'relation',
title: '角色',
},
{
dataIndex: 'actions',
title: '操作权限',
render: (value, row) => {
const options = value.map((ele) => ({
label: ele,
value: ele,
}));
const actionAuth = rows
.filter((ele) => ele.relationId === row.relationId)
.sort((a, b) => b.deActions.length - a.deActions.length)?.[0];
const defaultValue = actionAuth
? actionAuth.deActions
: [];
return (_jsx(Checkbox.Group, { style: {
width: '100%',
display: 'flex',
flexWrap: 'wrap',
}, options: options, defaultValue: defaultValue, onChange: (checkedArr) => {
const path2 = path.replaceAll('(user)', '');
if (!actionAuth) {
/* methods.addItem({
relationId:
row.relationId || '',
paths: [path2],
deActions:
checkedArr as string[],
destEntity: entity as string,
}); */
}
else {
methods.updateItem({
deActions: checkedArr,
}, actionAuth.id);
}
if (!checkedArr.length && actionAuth) {
methods.removeItem(actionAuth.id);
}
} }));
},
},
], pagination: false }), _jsx("div", { style: {
display: 'flex',
width: '100%',
justifyContent: 'flex-end',
padding: 8,
}, children: _jsx(Button, { disabled: !path, type: "primary", onClick: () => {
methods.execute();
onClose();
}, children: "\u4FDD\u5B58\u5E76\u5173\u95ED" }) })] }));
return (<Space direction="vertical" style={{ width: '100%' }}>
<Space>
<Text style={{ fontSize: 16 }}>授权</Text>
</Space>
<Table rowKey={'relationId'} dataSource={datasource} columns={[
{
width: 200,
dataIndex: 'relation',
title: '角色',
},
{
dataIndex: 'actions',
title: '操作权限',
render: (value, row) => {
const options = value.map((ele) => ({
label: ele,
value: ele,
}));
const actionAuth = rows
.filter((ele) => ele.relationId === row.relationId)
.sort((a, b) => b.deActions.length - a.deActions.length)?.[0];
const defaultValue = actionAuth
? actionAuth.deActions
: [];
return (<Checkbox.Group style={{
width: '100%',
display: 'flex',
flexWrap: 'wrap',
}} options={options} defaultValue={defaultValue} onChange={(checkedArr) => {
const path2 = path.replaceAll('(user)', '');
if (!actionAuth) {
/* methods.addItem({
relationId:
row.relationId || '',
paths: [path2],
deActions:
checkedArr as string[],
destEntity: entity as string,
}); */
}
else {
methods.updateItem({
deActions: checkedArr,
}, actionAuth.id);
}
if (!checkedArr.length && actionAuth) {
methods.removeItem(actionAuth.id);
}
}}/>);
},
},
]} pagination={false}></Table>
<div style={{
display: 'flex',
width: '100%',
justifyContent: 'flex-end',
padding: 8,
}}>
<Button disabled={!path} type="primary" onClick={() => {
methods.execute();
onClose();
}}>
保存并关闭
</Button>
</div>
</Space>);
}

View File

@ -1,3 +1,4 @@
/// <reference types="react" />
import { EntityDict } from 'oak-domain/lib/types/Entity';
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
import { WebComponentProps } from '../../../types/Page';
@ -16,5 +17,5 @@ export default function render(props: WebComponentProps<ED, keyof ED, false, {
}, {
onActionsSelected: (actions: string[]) => void;
onRelationsSelected: (relationIds: string[]) => void;
}>): import("react/jsx-runtime").JSX.Element;
}>): import("react").JSX.Element;
export {};

View File

@ -1,4 +1,3 @@
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { Row, Col, Tabs, Checkbox } from 'antd';
import { Typography } from 'antd';
const { Title, Text } = Typography;
@ -13,20 +12,22 @@ export default function render(props) {
{
label: 'deduceRelation',
key: 'deduceRelation',
children: (_jsxs("div", { style: {
children: (<div style={{
width: '100%',
height: '100%',
minHeight: 600,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}, children: ["\u5BF9\u8C61\u7684actionAuth\u5DF2\u88ABdeduce\u5230[", _jsx("b", { children: deduceRelationAttr }), "]\u5C5E\u6027\u4E0A"] }))
}}>
对象的actionAuth已被deduce到[<b>{deduceRelationAttr}</b>]
</div>)
},
] : [
{
label: 'actionAuth',
key: 'actionAuth',
children: (_jsx(ActionAuth, { entity: entity, oakPath: oakFullpath && `${oakFullpath}.actionAuths`, actions: checkedActions }))
children: (<ActionAuth entity={entity} oakPath={oakFullpath && `${oakFullpath}.actionAuths`} actions={checkedActions}/>)
}
];
/* if (hasDirectActionAuth) {
@ -76,15 +77,38 @@ export default function render(props) {
// }
// );
// }
const ActionSelector = actions && (_jsxs(Row, { style: { width: '100%' }, justify: "center", align: "middle", children: [_jsxs(Text, { strong: true, children: [t('action'), ":"] }), _jsx(Row, { style: { flex: 1, marginLeft: 10 }, justify: "start", align: "middle", wrap: true, children: _jsx(Checkbox.Group, { options: actions, value: checkedActions, onChange: (value) => onActionsSelected(value), style: {
display: 'flex',
flexWrap: 'wrap',
} }) })] }));
const RelationSelector = relations && (_jsxs(Row, { style: { width: '100%' }, justify: "center", align: "middle", children: [_jsxs(Text, { strong: true, children: [t('relation'), ":"] }), _jsx(Row, { style: { flex: 1, marginLeft: 10 }, justify: "start", align: "middle", wrap: true, children: _jsx(Checkbox.Group, { options: relations.map(ele => ({ label: ele.name, value: ele.id })), value: relationIds, onChange: (value) => onRelationsSelected(value), style: {
display: 'flex',
flexWrap: 'wrap',
} }) })] }));
const ActionSelector = actions && (<Row style={{ width: '100%' }} justify="center" align="middle">
<Text strong>{t('action')}:</Text>
<Row style={{ flex: 1, marginLeft: 10 }} justify="start" align="middle" wrap>
<Checkbox.Group options={actions} value={checkedActions} onChange={(value) => onActionsSelected(value)} style={{
display: 'flex',
flexWrap: 'wrap',
}}/>
</Row>
</Row>);
const RelationSelector = relations && (<Row style={{ width: '100%' }} justify="center" align="middle">
<Text strong>{t('relation')}:</Text>
<Row style={{ flex: 1, marginLeft: 10 }} justify="start" align="middle" wrap>
<Checkbox.Group options={relations.map(ele => ({ label: ele.name, value: ele.id }))} value={relationIds} onChange={(value) => onRelationsSelected(value)} style={{
display: 'flex',
flexWrap: 'wrap',
}}/>
</Row>
</Row>);
const showActionSelector = ['actionAuth', 'directActionAuth'].includes(tab);
const showRelationSelector = ['relationAuth', 'directRelationAuth'].includes(tab);
return (_jsxs("div", { className: Styles.container, children: [_jsxs(Row, { justify: "center", style: { margin: 20, padding: 10, minHeight: 100 }, align: "middle", children: [_jsx(Col, { span: 8, children: _jsxs(Row, { style: { width: '100%' }, justify: "center", align: "middle", children: [_jsxs(Text, { strong: true, children: [t('actionAuth:attr.destEntity'), ":"] }), _jsx(Text, { code: true, style: { marginLeft: 10 }, children: entity })] }) }), _jsx(Col, { span: 12, children: showActionSelector ? ActionSelector : (showRelationSelector && RelationSelector) })] }), _jsx(Tabs, { defaultActiveKey: "1", type: "card", size: "large", items: items, onChange: (key) => setTab(key) })] }));
return (<div className={Styles.container}>
<Row justify="center" style={{ margin: 20, padding: 10, minHeight: 100 }} align="middle">
<Col span={8}>
<Row style={{ width: '100%' }} justify="center" align="middle">
<Text strong>{t('actionAuth:attr.destEntity')}:</Text>
<Text code style={{ marginLeft: 10 }}>{entity}</Text>
</Row>
</Col>
<Col span={12}>
{showActionSelector ? ActionSelector : (showRelationSelector && RelationSelector)}
</Col>
</Row>
<Tabs defaultActiveKey="1" type="card" size="large" items={items} onChange={(key) => setTab(key)}/>
</div>);
}

View File

@ -1,3 +1,4 @@
/// <reference types="react" />
import { WebComponentProps } from '../../../types/Page';
import { EntityDict } from 'oak-domain/lib/types/Entity';
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
@ -14,5 +15,5 @@ export default function render(props: WebComponentProps<ED, keyof ED, true, {
}>;
}, {
onEntityClicked: (entity: string) => void;
}>): import("react/jsx-runtime").JSX.Element;
}>): import("react").JSX.Element;
export {};

View File

@ -1,4 +1,3 @@
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
import { Switch, Input, Form } from 'antd';
import ReactEcharts from 'echarts-for-react';
import { useState } from 'react';
@ -37,54 +36,68 @@ export default function render(props) {
});
}
}
return (_jsxs("div", { className: Styles.container, children: [_jsxs(Form, { style: {
margin: 20,
}, children: [_jsx(Form.Item, { label: "filter", children: _jsx(_Fragment, { children: _jsx(Input, { onChange: ({ currentTarget }) => setSearch(currentTarget.value), allowClear: true }) }) }), _jsx(Form.Item, { label: "strict mode", children: _jsx(_Fragment, { children: _jsx(Switch, { checked: strict, onChange: (checked) => setStrict(checked) }) }) })] }), _jsx(ReactEcharts, { style: { width: '100%', height: '100%', minHeight: 750 }, option: {
tooltip: {},
series: [
{
type: 'graph',
layout: 'force',
force: {
initLayout: 'circular',
gravity: 0,
repulsion: [10, 80],
edgeLength: [10, 50]
},
data: data2,
links: links2,
lineStyle: {
opacity: 0.9,
width: 2,
curveness: 0
},
label: {
show: true
},
autoCurveness: true,
roam: true,
draggable: true,
edgeSymbol: ['none', 'arrow'],
edgeSymbolSize: 7,
emphasis: {
scale: true,
label: {
show: true,
},
focus: 'adjacency',
lineStyle: {
width: 10
}
}
},
],
}, notMerge: true, lazyUpdate: false, onEvents: {
click: (info) => {
const { data, dataType } = info;
if (dataType === 'node') {
const { name } = data;
onEntityClicked(name);
}
return (<div className={Styles.container}>
<Form style={{
margin: 20,
}}>
<Form.Item label="filter">
<>
<Input onChange={({ currentTarget }) => setSearch(currentTarget.value)} allowClear/>
</>
</Form.Item>
<Form.Item label="strict mode">
<>
<Switch checked={strict} onChange={(checked) => setStrict(checked)}/>
</>
</Form.Item>
</Form>
<ReactEcharts style={{ width: '100%', height: '100%', minHeight: 750 }} option={{
tooltip: {},
series: [
{
type: 'graph',
layout: 'force',
force: {
initLayout: 'circular',
gravity: 0,
repulsion: [10, 80],
edgeLength: [10, 50]
},
} })] }));
data: data2,
links: links2,
lineStyle: {
opacity: 0.9,
width: 2,
curveness: 0
},
label: {
show: true
},
autoCurveness: true,
roam: true,
draggable: true,
edgeSymbol: ['none', 'arrow'],
edgeSymbolSize: 7,
emphasis: {
scale: true,
label: {
show: true,
},
focus: 'adjacency',
lineStyle: {
width: 10
}
}
},
],
}} notMerge={true} lazyUpdate={false} onEvents={{
click: (info) => {
const { data, dataType } = info;
if (dataType === 'node') {
const { name } = data;
onEntityClicked(name);
}
},
}}/>
</div>);
}

View File

@ -1,3 +1,4 @@
/// <reference types="react" />
import { RowWithActions, WebComponentProps } from '../../../types/Page';
import { EntityDict } from 'oak-domain/lib/types/Entity';
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
@ -9,5 +10,5 @@ export default function render(props: WebComponentProps<ED, 'relation', true, {
onClicked: (relationId: string) => any;
}, {
setEntityFilter: (filter: string) => void;
}>): import("react/jsx-runtime").JSX.Element | null;
}>): import("react").JSX.Element | null;
export {};

View File

@ -1,15 +1,25 @@
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
import { List, Tag, Input } from 'antd-mobile';
import Styles from './web.module.less';
export default function render(props) {
const { entities, entity, relations, onClicked } = props.data;
const { t, setEntityFilter } = props.methods;
if (entities) {
return (_jsxs(_Fragment, { children: [!entity &&
_jsx(_Fragment, { children: _jsx("div", { className: Styles.inputDiv, children: _jsx(Input, { placeholder: t('searchTip'), clearable: true, onChange: (val) => setEntityFilter(val) }) }) }), entities.map((e) => {
const rs = relations.filter(ele => ele.entity === e);
return (_jsx(List, { header: t(`${e}:name`) + ` (${e})`, children: rs.map((r) => (_jsx(List.Item, { extra: r.entityId && _jsx(Tag, { color: 'primary', fill: 'outline', children: t('hasEntityId') }), onClick: () => onClicked(r.id), children: t(`${e}:r.${r.name}`) + ` (${r.name})` }))) }));
})] }));
return (<>
{!entity &&
<>
<div className={Styles.inputDiv}>
<Input placeholder={t('searchTip')} clearable onChange={(val) => setEntityFilter(val)}/>
</div>
</>}
{entities.map((e) => {
const rs = relations.filter(ele => ele.entity === e);
return (<List header={t(`${e}:name`) + ` (${e})`}>
{rs.map((r) => (<List.Item extra={r.entityId && <Tag color='primary' fill='outline'>{t('hasEntityId')}</Tag>} onClick={() => onClicked(r.id)}>
{t(`${e}:r.${r.name}`) + ` (${r.name})`}
</List.Item>))}
</List>);
})}
</>);
}
return null;
}

View File

@ -1,3 +1,4 @@
import React from 'react';
import { RowWithActions, WebComponentProps } from '../../../types/Page';
import { EntityDict } from 'oak-domain/lib/types/Entity';
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
@ -9,5 +10,5 @@ export default function render(props: WebComponentProps<ED, 'relation', true, {
onClicked: (relationId: string) => any;
}, {
setEntityFilter: (filter: string) => void;
}>): import("react/jsx-runtime").JSX.Element | null;
}>): React.JSX.Element | null;
export {};

View File

@ -1,15 +1,26 @@
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
import React from 'react';
import { Card, Button, Input } from 'antd';
import Styles from './web.pc.module.less';
export default function render(props) {
const { entities, entity, relations, onClicked } = props.data;
const { t, setEntityFilter } = props.methods;
if (entities) {
return (_jsxs(_Fragment, { children: [!entity &&
_jsx(_Fragment, { children: _jsx("div", { className: Styles.inputDiv, children: _jsx(Input, { placeholder: t('searchTip'), allowClear: true, onChange: ({ currentTarget }) => setEntityFilter(currentTarget.value) }) }) }), entities.map((e) => {
const rs = relations.filter(ele => ele.entity === e);
return (_jsx(Card, { title: t(`${e}:name`) + ` (${e})`, style: { margin: 10 }, children: rs.map((r) => (_jsx(Button, { type: r.entityId ? 'primary' : 'link', onClick: () => onClicked(r.id), children: t(`${e}:r.${r.name}`) + ` (${r.name})` }))) }));
})] }));
return (<>
{!entity &&
<>
<div className={Styles.inputDiv}>
<Input placeholder={t('searchTip')} allowClear onChange={({ currentTarget }) => setEntityFilter(currentTarget.value)}/>
</div>
</>}
{entities.map((e) => {
const rs = relations.filter(ele => ele.entity === e);
return (<Card title={t(`${e}:name`) + ` (${e})`} style={{ margin: 10 }}>
{rs.map((r) => (<Button type={r.entityId ? 'primary' : 'link'} onClick={() => onClicked(r.id)}>
{t(`${e}:r.${r.name}`) + ` (${r.name})`}
</Button>))}
</Card>);
})}
</>);
}
return null;
}

View File

@ -1,3 +1,4 @@
/// <reference types="react" />
import { WebComponentProps } from '../../../types/Page';
import { EntityDict } from 'oak-domain/lib/types/Entity';
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
@ -10,5 +11,5 @@ export default function render(props: WebComponentProps<ED, 'relationAuth', true
}, {
onChange: (checked: boolean, relationId: string, path: string, relationAuths?: ED['relationAuth']['OpSchema'][]) => void;
confirm: () => void;
}>): import("react/jsx-runtime").JSX.Element;
}>): import("react").JSX.Element;
export {};

View File

@ -1,4 +1,3 @@
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { Table, Checkbox, Button, Row } from 'antd';
import { Typography } from 'antd';
const { Title, Text } = Typography;
@ -6,52 +5,66 @@ import { intersection, difference } from 'oak-domain/lib/utils/lodash';
export default function render(props) {
const { relationIds, relationAuths, oakDirty, auths, sourceRelations } = props.data;
const { onChange, t, clean, confirm } = props.methods;
return (_jsxs(_Fragment, { children: [_jsx(Table, { columns: [
{
key: '1',
title: t('relationAuth:attr.sourceEntity'),
width: 100,
render: (value, record) => record[2],
},
{
key: '1',
title: t('relationAuth:attr.path'),
width: 200,
render: (value, record) => record[1],
},
{
fixed: 'right',
title: t('grantedRoles'),
key: 'roles',
width: 300,
render: (value, record) => {
const sourceEntity = record[2];
const relations = sourceRelations.filter(ele => ele.entity === sourceEntity && !relationIds.includes(ele.id));
return (_jsx("div", { style: {
width: '100%',
display: 'flex',
flexWrap: 'wrap',
}, children: relations?.map((r) => {
const disabled = relationIds.length === 0;
let checked = false, indeterminate = false;
if (!disabled && relationAuths) {
const includedRelationIds = [];
for (const auth of relationAuths) {
if (!auth.$$deleteAt$$ && auth.sourceRelationId === r.id /* && auth.path === record[1] */) {
includedRelationIds.push(auth.destRelationId);
}
}
checked = difference(relationIds, includedRelationIds).length === 0;
indeterminate = !checked && intersection(relationIds, includedRelationIds).length > 0;
return (<>
<Table columns={[
{
key: '1',
title: t('relationAuth:attr.sourceEntity'),
width: 100,
render: (value, record) => record[2],
},
{
key: '1',
title: t('relationAuth:attr.path'),
width: 200,
render: (value, record) => record[1],
},
{
fixed: 'right',
title: t('grantedRoles'),
key: 'roles',
width: 300,
render: (value, record) => {
const sourceEntity = record[2];
const relations = sourceRelations.filter(ele => ele.entity === sourceEntity && !relationIds.includes(ele.id));
return (<div style={{
width: '100%',
display: 'flex',
flexWrap: 'wrap',
}}>
{relations?.map((r) => {
const disabled = relationIds.length === 0;
let checked = false, indeterminate = false;
if (!disabled && relationAuths) {
const includedRelationIds = [];
for (const auth of relationAuths) {
if (!auth.$$deleteAt$$ && auth.sourceRelationId === r.id /* && auth.path === record[1] */) {
includedRelationIds.push(auth.destRelationId);
}
return (_jsx(Checkbox, { disabled: disabled, checked: checked, indeterminate: indeterminate, onChange: ({ target }) => {
const { checked } = target;
const refRelationAuths = relationAuths?.filter(ele => ele.sourceRelationId === r.id /*&& ele.path === record[1] */
&& relationIds.includes(ele.destRelationId));
onChange(checked, r.id, record[1], refRelationAuths);
}, children: r.name }));
}) }));
}
}
], dataSource: auths, pagination: false }), _jsxs(Row, { justify: "end", style: { marginTop: 20, padding: 5 }, children: [_jsx(Button, { style: { marginRight: 10 }, type: 'primary', disabled: !oakDirty, onClick: () => confirm(), children: t("confirm") }), _jsx(Button, { disabled: !oakDirty, onClick: () => clean(), children: t("reset") })] })] }));
}
checked = difference(relationIds, includedRelationIds).length === 0;
indeterminate = !checked && intersection(relationIds, includedRelationIds).length > 0;
}
return (<Checkbox disabled={disabled} checked={checked} indeterminate={indeterminate} onChange={({ target }) => {
const { checked } = target;
const refRelationAuths = relationAuths?.filter(ele => ele.sourceRelationId === r.id /*&& ele.path === record[1] */
&& relationIds.includes(ele.destRelationId));
onChange(checked, r.id, record[1], refRelationAuths);
}}>
{r.name}
</Checkbox>);
})}
</div>);
}
}
]} dataSource={auths} pagination={false}/>
<Row justify="end" style={{ marginTop: 20, padding: 5 }}>
<Button style={{ marginRight: 10 }} type='primary' disabled={!oakDirty} onClick={() => confirm()}>
{t("confirm")}
</Button>
<Button disabled={!oakDirty} onClick={() => clean()}>
{t("reset")}
</Button>
</Row>
</>);
}

View File

@ -1,3 +1,4 @@
/// <reference types="react" />
import { WebComponentProps } from '../../../types/Page';
import { EntityDict } from 'oak-domain/lib/types/Entity';
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
@ -14,5 +15,5 @@ export default function render(props: WebComponentProps<ED, 'relationAuth', true
}, {
onChange: (relationId: string, checked: boolean, relationAuthId?: string, path?: string) => void;
confirm: () => void;
}>): import("react/jsx-runtime").JSX.Element;
}>): import("react").JSX.Element;
export {};

View File

@ -1,72 +1,98 @@
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { Table, Checkbox, Button, Row } from 'antd';
import { Typography } from 'antd';
const { Title, Text } = Typography;
export default function render(props) {
const { cascadeEntityRelations, oakDirty, entity, relationName } = props.data;
const { onChange, t, clean, confirm } = props.methods;
return (_jsxs("div", { style: {
return (<div style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'stretch',
width: '100%'
}, children: [_jsxs(Row, { justify: "center", style: { margin: 20, padding: 10 }, children: [_jsxs(Row, { style: { marginRight: 10 }, children: [_jsx(Title, { level: 4, children: "\u5F53\u524D\u5BF9\u8C61\uFF1A" }), _jsx(Text, { code: true, children: entity })] }), _jsxs(Row, { children: [_jsx(Title, { level: 4, children: "\u5F53\u524D\u89D2\u8272\uFF1A" }), _jsx(Text, { code: true, children: relationName })] })] }), _jsx(Table, { columns: [
{
key: '1',
title: '对象',
width: 100,
render: (value, record) => {
const { entity } = record;
return entity;
},
},
{
key: '1',
title: '路径',
width: 200,
render: (value, record) => {
const { path } = record;
return path;
},
},
{
fixed: 'right',
title: '角色',
key: 'operation',
width: 300,
render: (value, record) => {
const { relations, authedRelations, path } = record;
// 可能存在定制的relation
const customizedRelationsAuthed = [];
const relationIdAuthed = [];
authedRelations.forEach((ele) => {
if (!ele.$$deleteAt$$) {
if (relations.find(ele2 => ele2.id === ele.destRelationId)) {
relationIdAuthed.push(ele.destRelationId);
}}>
<Row justify="center" style={{ margin: 20, padding: 10 }}>
<Row style={{ marginRight: 10 }}>
<Title level={4}>当前对象</Title>
<Text code>{entity}</Text>
</Row>
<Row>
<Title level={4}>当前角色</Title>
<Text code>{relationName}</Text>
</Row>
</Row>
<Table columns={[
{
key: '1',
title: '对象',
width: 100,
render: (value, record) => {
const { entity } = record;
return entity;
},
},
{
key: '1',
title: '路径',
width: 200,
render: (value, record) => {
const { path } = record;
return path;
},
},
{
fixed: 'right',
title: '角色',
key: 'operation',
width: 300,
render: (value, record) => {
const { relations, authedRelations, path } = record;
// 可能存在定制的relation
const customizedRelationsAuthed = [];
const relationIdAuthed = [];
authedRelations.forEach((ele) => {
if (!ele.$$deleteAt$$) {
if (relations.find(ele2 => ele2.id === ele.destRelationId)) {
relationIdAuthed.push(ele.destRelationId);
}
else {
customizedRelationsAuthed.push(ele.destRelation);
}
}
});
return (<div style={{
width: '100%',
display: 'flex',
flexWrap: 'wrap',
}}>
{relations.map((ele) => {
const authed = relationIdAuthed.includes(ele.id);
return (<Checkbox key={ele.id} checked={authed} onChange={({ target }) => {
const { checked } = target;
const relationAuth = authedRelations.find(ele2 => ele2.destRelationId === ele.id);
if (relationAuth) {
onChange(ele.id, checked, relationAuth.id);
}
else {
customizedRelationsAuthed.push(ele.destRelation);
onChange(ele.id, checked, undefined, path);
}
}
});
return (_jsxs("div", { style: {
width: '100%',
display: 'flex',
flexWrap: 'wrap',
}, children: [relations.map((ele) => {
const authed = relationIdAuthed.includes(ele.id);
return (_jsx(Checkbox, { checked: authed, onChange: ({ target }) => {
const { checked } = target;
const relationAuth = authedRelations.find(ele2 => ele2.destRelationId === ele.id);
if (relationAuth) {
onChange(ele.id, checked, relationAuth.id);
}
else {
onChange(ele.id, checked, undefined, path);
}
}, children: ele.display || ele.name }, ele.id));
}), customizedRelationsAuthed.map((ele) => _jsx(Checkbox, { checked: true, disabled: true, children: ele.display || ele.name }, ele.id))] }));
}
}
], dataSource: cascadeEntityRelations, pagination: false }), _jsxs(Row, { justify: "end", style: { marginTop: 20, padding: 5 }, children: [_jsx(Button, { style: { marginRight: 10 }, type: 'primary', disabled: !oakDirty, onClick: () => confirm(), children: t("confirm") }), _jsx(Button, { disabled: !oakDirty, onClick: () => clean(), children: t("reset") })] })] }));
}}>
{ele.display || ele.name}
</Checkbox>);
})}
{customizedRelationsAuthed.map((ele) => <Checkbox key={ele.id} checked={true} disabled={true}>
{ele.display || ele.name}
</Checkbox>)}
</div>);
}
}
]} dataSource={cascadeEntityRelations} pagination={false}/>
<Row justify="end" style={{ marginTop: 20, padding: 5 }}>
<Button style={{ marginRight: 10 }} type='primary' disabled={!oakDirty} onClick={() => confirm()}>
{t("confirm")}
</Button>
<Button disabled={!oakDirty} onClick={() => clean()}>
{t("reset")}
</Button>
</Row>
</div>);
}

View File

@ -1,3 +1,4 @@
/// <reference types="react" />
import { EntityDict } from 'oak-domain/lib/types/Entity';
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
import { WebComponentProps } from '../../../types/Page';
@ -10,5 +11,5 @@ export default function render(props: WebComponentProps<ED, keyof ED, false, {
getNodes: (entity: keyof ED) => void;
checkSelectRelation: () => boolean;
resolveP: (path: string) => string;
}>): import("react/jsx-runtime").JSX.Element;
}>): import("react").JSX.Element;
export {};

View File

@ -1,4 +1,3 @@
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
import { Row, Col, Space, Button, Modal, Breadcrumb, Tag } from 'antd';
import { Typography } from 'antd';
const { Title, Text } = Typography;
@ -10,42 +9,91 @@ export default function render(props) {
const { getNodes, checkSelectRelation, resolveP } = methods;
const [open, setOpen] = useState(false);
const [breadcrumbItems, setBreadcrumbItems] = useState([]);
return (_jsxs(Space, { direction: "vertical", style: { width: '100%' }, children: [_jsx(Button, { onClick: () => setOpen(true), children: "\u8BBE\u7F6E" }), _jsx(Modal, { title: `权限设置`, open: open, destroyOnClose: true, footer: null, onCancel: () => {
setBreadcrumbItems([]);
setOpen(false);
}, width: 900, children: _jsxs(Space, { direction: "vertical", style: { width: '100%', marginTop: 16 }, size: 16, children: [_jsxs(Space, { direction: "vertical", children: [_jsx(Text, { style: { fontSize: 16 }, children: "\u8DEF\u5F84" }), _jsx(Space, { style: { width: '100%' }, wrap: true, children: (breadcrumbItems && breadcrumbItems.length > 0) ? (_jsxs(_Fragment, { children: [_jsx(Breadcrumb, { items: breadcrumbItems.map((ele, index) => ({
title: (_jsx("a", { onClick: () => {
if (checkSelectRelation()) {
return;
}
const newItems = breadcrumbItems.slice(0, index + 1);
setBreadcrumbItems(newItems);
const entity = ele.includes('$') ? ele.split('$')[0] : ele;
getNodes(entity);
}, children: ele }))
})) }), _jsx(Button, { size: "small", type: "link", onClick: () => {
setBreadcrumbItems([]);
getNodes(entity);
}, children: "\u6E05\u7A7A" })] })) : (_jsx(Text, { type: "secondary", children: "\u8BF7\u5148\u9009\u62E9\u7ED3\u70B9" })) })] }), _jsx(Space, { direction: "vertical", style: { width: '100%' }, children: _jsxs(Space, { direction: "vertical", style: { width: '100%' }, children: [_jsx(Text, { style: { fontSize: 16 }, children: "\u7ED3\u70B9" }), _jsxs(Row, { gutter: 24, children: [_jsx(Col, { span: 2, children: _jsx(Text, { style: { whiteSpace: 'nowrap' }, children: "\u5916\u952E" }) }), _jsx(Col, { span: 22, children: _jsx(Space, { wrap: true, children: entityDNode.map((ele) => (_jsx(Tag, { style: { cursor: 'pointer' }, color: "processing", bordered: false, onClick: () => {
if (checkSelectRelation()) {
return;
}
breadcrumbItems.push(ele);
setBreadcrumbItems(breadcrumbItems);
const path = breadcrumbItems.join('.');
const entity = resolveP(path);
getNodes(entity);
}, children: ele }))) }) })] }), _jsxs(Row, { gutter: 24, children: [_jsx(Col, { span: 2, children: _jsx(Text, { style: { whiteSpace: 'nowrap', marginRight: 16 }, children: "\u53CD\u6307\u7ED3\u70B9" }) }), _jsx(Col, { span: 22, children: _jsx(Space, { wrap: true, children: entitySNode.map((ele) => (_jsx(Tag, { style: { cursor: 'pointer' }, color: "cyan", bordered: false, onClick: () => {
if (checkSelectRelation()) {
return;
}
const preNode = breadcrumbItems[breadcrumbItems.length - 1] || entity;
const parentEntity = preNode.includes('$') ? preNode.split('$')[0] : preNode;
breadcrumbItems.push(`${ele}$${parentEntity}`);
setBreadcrumbItems(breadcrumbItems);
getNodes(ele);
}, children: ele }))) }) })] })] }) }), _jsx(ActionAuthList, { oakPath: "$actionAuthList-cpn", entity: entity, path: breadcrumbItems.join('.'), onClose: () => {
setBreadcrumbItems([]);
setOpen(false);
}, oakAutoUnmount: true })] }) })] }));
return (<Space direction="vertical" style={{ width: '100%' }}>
<Button onClick={() => setOpen(true)}>设置</Button>
<Modal title={`权限设置`} open={open} destroyOnClose={true} footer={null} onCancel={() => {
setBreadcrumbItems([]);
setOpen(false);
}} width={900}>
<Space direction="vertical" style={{ width: '100%', marginTop: 16 }} size={16}>
<Space direction="vertical">
<Text style={{ fontSize: 16 }}>路径</Text>
<Space style={{ width: '100%' }} wrap>
{(breadcrumbItems && breadcrumbItems.length > 0) ? (<>
<Breadcrumb items={breadcrumbItems.map((ele, index) => ({
title: (<a onClick={() => {
if (checkSelectRelation()) {
return;
}
const newItems = breadcrumbItems.slice(0, index + 1);
setBreadcrumbItems(newItems);
const entity = ele.includes('$') ? ele.split('$')[0] : ele;
getNodes(entity);
}}>
{ele}
</a>)
}))}/>
<Button size="small" type="link" onClick={() => {
setBreadcrumbItems([]);
getNodes(entity);
}}>
清空
</Button>
</>) : (<Text type="secondary"></Text>)}
</Space>
</Space>
<Space direction="vertical" style={{ width: '100%' }}>
<Space direction="vertical" style={{ width: '100%' }}>
<Text style={{ fontSize: 16 }}>结点</Text>
<Row gutter={24}>
<Col span={2}>
<Text style={{ whiteSpace: 'nowrap' }}>外键</Text>
</Col>
<Col span={22}>
<Space wrap>
{entityDNode.map((ele) => (<Tag style={{ cursor: 'pointer' }} color="processing" bordered={false} onClick={() => {
if (checkSelectRelation()) {
return;
}
breadcrumbItems.push(ele);
setBreadcrumbItems(breadcrumbItems);
const path = breadcrumbItems.join('.');
const entity = resolveP(path);
getNodes(entity);
}}>
{ele}
</Tag>))}
</Space>
</Col>
</Row>
<Row gutter={24}>
<Col span={2}>
<Text style={{ whiteSpace: 'nowrap', marginRight: 16 }}>反指结点</Text>
</Col>
<Col span={22}>
<Space wrap>
{entitySNode.map((ele) => (<Tag style={{ cursor: 'pointer' }} color={"cyan"} bordered={false} onClick={() => {
if (checkSelectRelation()) {
return;
}
const preNode = breadcrumbItems[breadcrumbItems.length - 1] || entity;
const parentEntity = preNode.includes('$') ? preNode.split('$')[0] : preNode;
breadcrumbItems.push(`${ele}$${parentEntity}`);
setBreadcrumbItems(breadcrumbItems);
getNodes(ele);
}}>
{ele}
</Tag>))}
</Space>
</Col>
</Row>
</Space>
</Space>
<ActionAuthList oakPath="$actionAuthList-cpn" entity={entity} path={breadcrumbItems.join('.')} onClose={() => {
setBreadcrumbItems([]);
setOpen(false);
}} oakAutoUnmount={true}/>
</Space>
</Modal>
</Space>);
}

View File

@ -1,3 +1,4 @@
import React from 'react';
import { WebComponentProps } from '../../types/Page';
import { ED } from '../../types/AbstractComponent';
import { EntityDict } from 'oak-domain/lib/types/Entity';
@ -8,4 +9,4 @@ export default function Render(props: WebComponentProps<ED, keyof EntityDict, fa
searchChange: (value: string) => void;
searchConfirm: (value: string) => void;
searchClear: () => void;
}>): import("react/jsx-runtime").JSX.Element;
}>): React.JSX.Element;

View File

@ -1,8 +1,8 @@
import { jsx as _jsx } from "react/jsx-runtime";
import React from 'react';
import { SearchBar } from 'antd-mobile';
export default function Render(props) {
const { methods, data } = props;
const { t, searchChange, searchConfirm, searchClear } = methods;
const { searchValue, placeholder = '请输入' } = data;
return (_jsx(SearchBar, { value: searchValue, placeholder: placeholder, showCancelButton: true, onChange: searchChange, onSearch: searchConfirm, onClear: () => searchClear() }));
return (<SearchBar value={searchValue} placeholder={placeholder} showCancelButton onChange={searchChange} onSearch={searchConfirm} onClear={() => searchClear()}/>);
}

View File

@ -1,3 +1,4 @@
import React from 'react';
import { WebComponentProps } from '../../types/Page';
import { ED } from '../../types/AbstractComponent';
import { EntityDict } from 'oak-domain/lib/types/Entity';
@ -6,4 +7,4 @@ export default function Render(props: WebComponentProps<ED, keyof EntityDict, fa
}, {
searchChange: (value: string) => void;
searchConfirm: (value: string) => void;
}>): import("react/jsx-runtime").JSX.Element;
}>): React.JSX.Element;

View File

@ -1,9 +1,9 @@
import { jsx as _jsx } from "react/jsx-runtime";
import React from 'react';
import { Input, } from 'antd';
const { Search } = Input;
export default function Render(props) {
const { methods, data } = props;
const { t, searchChange, searchConfirm } = methods;
const { searchValue, oakLoading, } = data;
return (_jsx(Search, { loading: oakLoading, value: searchValue, onChange: ({ target: { value } }) => searchChange(value), onSearch: (value) => searchConfirm(value), placeholder: "", allowClear: true }));
return (<Search loading={oakLoading} value={searchValue} onChange={({ target: { value } }) => searchChange(value)} onSearch={(value) => searchConfirm(value)} placeholder="" allowClear/>);
}

View File

@ -1,3 +1,4 @@
import React from 'react';
import { EntityDict } from 'oak-domain/lib/types/Entity';
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
type ED = EntityDict & BaseEntityDict;
@ -10,5 +11,5 @@ export default function render<T extends keyof ED>(props: WebComponentProps<ED,
layout?: 'horizontal' | 'vertical';
mode?: 'default' | 'card';
children: any;
}>): import("react/jsx-runtime").JSX.Element;
}>): React.JSX.Element;
export {};

View File

@ -1,5 +1,4 @@
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { useState } from 'react';
import React, { useState } from 'react';
import { Form, Input, TextArea, DatePicker, Grid, Popup, Radio, Stepper, Switch, Button, } from 'antd-mobile';
import OakIcon from '../icon';
import RefAttr from '../refAttr';
@ -16,17 +15,17 @@ function makeAttrInput(attrRender, onValueChange, t, label) {
case 'varchar':
case 'char':
case 'poiName': {
return (_jsx(Input, { clearable: !required, placeholder: placeholder || `请输入${label}`, value: value, defaultValue: defaultValue, maxLength: maxLength, onChange: (value) => {
return (<Input clearable={!required} placeholder={placeholder || `请输入${label}`} value={value} defaultValue={defaultValue} maxLength={maxLength} onChange={(value) => {
onValueChange(value);
} }));
}}/>);
}
case 'text': {
return (_jsx(TextArea, { autoSize: true, placeholder: `请输入${label}`, defaultValue: defaultValue, value: value || '', rows: 6, showCount: true, maxLength: maxLength || 1000, onChange: (value) => {
return (<TextArea autoSize={true} placeholder={`请输入${label}`} defaultValue={defaultValue} value={value || ''} rows={6} showCount={true} maxLength={maxLength || 1000} onChange={(value) => {
onValueChange(value);
} }));
}}/>);
}
case 'int': {
return (_jsx(Stepper, { min: min, max: max, defaultValue: defaultValue, value: value, digits: 0, onChange: (value) => onValueChange(value) }));
return (<Stepper min={min} max={max} defaultValue={defaultValue} value={value} digits={0} onChange={(value) => onValueChange(value)}/>);
}
case 'decimal': {
const precision = params?.precision || 10;
@ -36,13 +35,13 @@ function makeAttrInput(attrRender, onValueChange, t, label) {
const threshold = Math.pow(10, precision - scale);
const max = threshold - scaleValue; // 小数在这里可能会有bug
const min = 0 - max; */
return (_jsx(Stepper, { min: min, max: max, defaultValue: defaultValue, value: value, digits: scale, step: scaleValue, onChange: (value) => onValueChange(value) }));
return (<Stepper min={min} max={max} defaultValue={defaultValue} value={value} digits={scale} step={scaleValue} onChange={(value) => onValueChange(value)}/>);
}
case 'money': {
// money在数据上统一用分来存储
const valueShowed = parseFloat((value / 100).toFixed(2));
const defaultValueShowed = parseFloat((defaultValue / 100).toFixed(2));
return (_jsx(Stepper, { min: 0, defaultValue: defaultValueShowed, value: valueShowed, digits: 2, step: 0.01, formatter: value => `${value}`, parser: text => parseFloat(text.replace('¥', '')), onChange: (value) => {
return (<Stepper min={0} defaultValue={defaultValueShowed} value={valueShowed} digits={2} step={0.01} formatter={value => `${value}`} parser={text => parseFloat(text.replace('¥', ''))} onChange={(value) => {
if (value !== null) {
const v2 = Math.round(value * 100);
onValueChange(v2);
@ -50,57 +49,83 @@ function makeAttrInput(attrRender, onValueChange, t, label) {
else {
onValueChange(value);
}
} }));
}}/>);
}
case 'datetime':
case 'date': {
const precision = type === 'date' ? 'day' : 'second';
const format = type === 'date' ? 'YYYY-MM-DD' : 'YYYY-MM-DD HH:mm:ss';
return (_jsxs("div", { style: { display: 'flex', alignItems: 'center' }, children: [_jsx(DatePicker, { visible: dt, onClose: () => setDt(false), precision: precision, value: new Date(value), defaultValue: new Date(), min: min ? new Date(min) : undefined, max: max ? new Date(max) : undefined, children: value => dayjs(value).format(format) }), _jsx(Button, { onClick: () => setDt(true), children: type === 'date' ? t('chooseDate') : t('chooseDatetime') })] }));
return (<div style={{ display: 'flex', alignItems: 'center' }}>
<DatePicker visible={dt} onClose={() => setDt(false)} precision={precision} value={new Date(value)} defaultValue={new Date()} min={min ? new Date(min) : undefined} max={max ? new Date(max) : undefined}>
{value => dayjs(value).format(format)}
</DatePicker>
<Button onClick={() => setDt(true)}>
{type === 'date' ? t('chooseDate') : t('chooseDatetime')}
</Button>
</div>);
}
case 'time': {
return (_jsx("div", { children: "\u5F85\u5B9E\u73B0" }));
return (<div>待实现</div>);
}
case 'boolean': {
return (_jsx(Switch, { checkedText: _jsx(OakIcon, { name: "right" }), uncheckedText: _jsx(OakIcon, { name: "close" }), checked: value, onChange: (checked) => {
return (<Switch checkedText={<OakIcon name="right"/>} uncheckedText={<OakIcon name="close"/>} checked={value} onChange={(checked) => {
onValueChange(checked);
} }));
}}/>);
}
case 'enum': {
return (_jsx(Radio.Group, { value: value, onChange: (value) => onValueChange(value), children: enumeration.map(({ label, value }) => (_jsx(Radio, { value: value, children: t(label) }))) }));
return (<Radio.Group value={value} onChange={(value) => onValueChange(value)}>
{enumeration.map(({ label, value }) => (<Radio value={value}>{t(label)}</Radio>))}
</Radio.Group>);
}
case 'ref': {
return (_jsx(RefAttr, { multiple: false, entityId: value, pickerRender: attrRender, onChange: (value) => { onValueChange(value[0]); } }));
return (<RefAttr multiple={false} entityId={value} pickerRender={attrRender} onChange={(value) => { onValueChange(value[0]); }}/>);
}
case 'coordinate': {
const { coordinate } = value || {};
const { extra } = attrRender;
const poiNameAttr = extra?.poiName || 'poiName';
const areaIdAttr = extra?.areaId || 'areaId';
return (_jsxs(_Fragment, { children: [_jsxs(Popup, { closeOnMaskClick: true, destroyOnClose: true, position: 'bottom', visible: sl, onClose: () => setSl(false), bodyStyle: {
height: '100%',
display: 'flex',
flexDirection: 'column',
alignItems: 'stretch',
}, children: [_jsx("div", { style: { flex: 1 }, children: _jsx(Location, { coordinate: coordinate, onLocated: (poi) => setPoi(poi) }) }), _jsxs(Grid, { columns: 2, gap: 8, children: [_jsx(Button, { block: true, color: "primary", disabled: !poi, onClick: () => {
if (poi) {
const { poiName, coordinate, areaId } = poi;
onValueChange({
type: 'point',
coordinate,
}, {
[poiNameAttr]: poiName,
[areaIdAttr]: areaId,
});
}
setSl(false);
}, children: t('common::action.confirm') }), _jsx(Button, { block: true, fill: "outline", onClick: () => {
setSl(false);
}, children: t('common::action.cancel') })] })] }), _jsx("div", { style: {
display: 'flex',
width: '100%',
alignItems: 'center',
}, onClick: () => setSl(true), children: _jsx(Map, { undragable: true, unzoomable: true, zoom: 13, disableWheelZoom: true, style: { height: 200, flex: 1 }, autoLocate: true, center: coordinate, markers: coordinate ? [coordinate] : undefined }) })] }));
return (<>
<Popup closeOnMaskClick={true} destroyOnClose={true} position='bottom' visible={sl} onClose={() => setSl(false)} bodyStyle={{
height: '100%',
display: 'flex',
flexDirection: 'column',
alignItems: 'stretch',
}}>
<div style={{ flex: 1 }}>
<Location coordinate={coordinate} onLocated={(poi) => setPoi(poi)}/>
</div>
<Grid columns={2} gap={8}>
<Button block color="primary" disabled={!poi} onClick={() => {
if (poi) {
const { poiName, coordinate, areaId } = poi;
onValueChange({
type: 'point',
coordinate,
}, {
[poiNameAttr]: poiName,
[areaIdAttr]: areaId,
});
}
setSl(false);
}}>
{t('common::action.confirm')}
</Button>
<Button block fill="outline" onClick={() => {
setSl(false);
}}>
{t('common::action.cancel')}
</Button>
</Grid>
</Popup>
<div style={{
display: 'flex',
width: '100%',
alignItems: 'center',
}} onClick={() => setSl(true)}>
<Map undragable={true} unzoomable={true} zoom={13} disableWheelZoom={true} style={{ height: 200, flex: 1 }} autoLocate={true} center={coordinate} markers={coordinate ? [coordinate] : undefined}/>
</div>
</>);
}
default: {
throw new Error(`【Abstract Update】无法支持的数据类别${type}的渲染`);
@ -110,7 +135,8 @@ function makeAttrInput(attrRender, onValueChange, t, label) {
export default function render(props) {
const { renderData = [], helps, layout = 'horizontal', mode = 'default', entity } = props.data;
const { update, t } = props.methods;
return (_jsx(Form, { layout: layout, mode: mode, children: renderData.map((ele) => {
return (<Form layout={layout} mode={mode}>
{renderData.map((ele) => {
// 因为i18n渲染机制的缘故t必须放到这里来计算
const { label, attr, type, required } = ele;
let label2 = label;
@ -129,16 +155,21 @@ export default function render(props) {
label2 = t(`${entity}:attr.${attr}`);
}
}
return (_jsx(Form.Item, { label: label2, rules: [
return (<Form.Item label={label2} rules={[
{
required: !!required,
},
], help: helps && helps[attr], children: _jsx(_Fragment, { children: makeAttrInput(ele, (value, extra) => {
const { attr } = ele;
update({
[attr]: value,
...extra,
});
}, t, label2) }) }));
}) }));
]} help={helps && helps[attr]}>
<>
{makeAttrInput(ele, (value, extra) => {
const { attr } = ele;
update({
[attr]: value,
...extra,
});
}, t, label2)}
</>
</Form.Item>);
})}
</Form>);
}

View File

@ -1,3 +1,4 @@
import React from 'react';
import { EntityDict } from 'oak-domain/lib/types/Entity';
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
import { AttrUpsertRender } from '../../types/AbstractComponent';
@ -9,5 +10,5 @@ export default function render<T extends keyof ED>(props: WebComponentProps<ED,
helps?: Record<string, string>;
layout?: 'horizontal' | 'vertical';
children: any;
}>): import("react/jsx-runtime").JSX.Element;
}>): React.JSX.Element;
export {};

View File

@ -1,5 +1,4 @@
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { useState } from 'react';
import React, { useState } from 'react';
import { Form, Input, InputNumber, Radio, Modal, Button, DatePicker, Space, Switch, } from 'antd';
import OakIcon from '../icon';
const { TextArea } = Input;
@ -16,14 +15,14 @@ function makeAttrInput(attrRender, onValueChange, t, label) {
case 'varchar':
case 'char':
case 'poiName': {
return (_jsx(Input, { allowClear: !required, placeholder: placeholder || `请输入${label}`, value: value, defaultValue: defaultValue, maxLength: maxLength, onChange: ({ target: { value } }) => {
return (<Input allowClear={!required} placeholder={placeholder || `请输入${label}`} value={value} defaultValue={defaultValue} maxLength={maxLength} onChange={({ target: { value } }) => {
onValueChange(value);
} }));
}}/>);
}
case 'text': {
return (_jsx(TextArea, { allowClear: !required, placeholder: `请输入${label}`, defaultValue: defaultValue, value: value, rows: 6, maxLength: maxLength || 1000, onChange: ({ target: { value } }) => {
return (<TextArea allowClear={!required} placeholder={`请输入${label}`} defaultValue={defaultValue} value={value} rows={6} maxLength={maxLength || 1000} onChange={({ target: { value } }) => {
onValueChange(value);
} }));
}}/>);
}
case 'int': {
/* const SIGNED_THRESHOLDS = {
@ -38,7 +37,7 @@ function makeAttrInput(attrRender, onValueChange, t, label) {
4: [0, 4294967295],
8: [0, Number.MAX_SAFE_INTEGER],
}; */
return (_jsx(InputNumber, { min: min, max: max, keyboard: true, defaultValue: defaultValue, value: value, precision: 0, onChange: (value) => onValueChange(value) }));
return (<InputNumber min={min} max={max} keyboard={true} defaultValue={defaultValue} value={value} precision={0} onChange={(value) => onValueChange(value)}/>);
}
case 'decimal': {
const precision = params?.precision || 10;
@ -48,13 +47,13 @@ function makeAttrInput(attrRender, onValueChange, t, label) {
const threshold = Math.pow(10, precision - scale);
const max = threshold - scaleValue; // 小数在这里可能会有bug
const min = 0 - max; */
return (_jsx(InputNumber, { min: min, max: max, keyboard: true, defaultValue: defaultValue, value: value, precision: scale, step: scaleValue, onChange: (value) => onValueChange(value) }));
return (<InputNumber min={min} max={max} keyboard={true} defaultValue={defaultValue} value={value} precision={scale} step={scaleValue} onChange={(value) => onValueChange(value)}/>);
}
case 'money': {
// money在数据上统一用分来存储
const valueShowed = parseFloat((value / 100).toFixed(2));
const defaultValueShowed = parseFloat((defaultValue / 100).toFixed(2));
return (_jsx(InputNumber, { min: 0, keyboard: true, defaultValue: defaultValueShowed, value: valueShowed, precision: 2, step: 0.01, addonAfter: "\uFFE5", onChange: (value) => {
return (<InputNumber min={0} keyboard={true} defaultValue={defaultValueShowed} value={valueShowed} precision={2} step={0.01} addonAfter="¥" onChange={(value) => {
if (value !== null) {
const v2 = Math.round(value * 100);
onValueChange(v2);
@ -62,64 +61,82 @@ function makeAttrInput(attrRender, onValueChange, t, label) {
else {
onValueChange(value);
}
} }));
}}/>);
}
case 'datetime':
case 'date':
case 'time': {
const mode = type === 'time' ? 'time' : 'date';
return (_jsx(DatePicker, { allowClear: !required, showTime: type === 'datetime', placeholder: placeholder, format: "YYYY-MM-DD HH:mm:ss", mode: mode, value: dayjs(value), onChange: (value) => {
return (<DatePicker allowClear={!required} showTime={type === 'datetime'} placeholder={placeholder} format="YYYY-MM-DD HH:mm:ss" mode={mode} value={dayjs(value)} onChange={(value) => {
if (value) {
onValueChange(value.valueOf());
}
else {
onValueChange(null);
}
} }));
}}/>);
}
case 'boolean': {
return (_jsx(Switch, { checkedChildren: _jsx(OakIcon, { name: "right" }), unCheckedChildren: _jsx(OakIcon, { name: "close" }), checked: value, onChange: (checked) => {
return (<Switch checkedChildren={<OakIcon name="right"/>} unCheckedChildren={<OakIcon name="close"/>} checked={value} onChange={(checked) => {
onValueChange(checked);
} }));
}}/>);
}
case 'enum': {
return (_jsx(Radio.Group, { value: value, onChange: ({ target }) => onValueChange(target.value), children: enumeration.map(({ label, value }) => (_jsx(Radio, { value: value, children: t(label) }))) }));
return (<Radio.Group value={value} onChange={({ target }) => onValueChange(target.value)}>
{enumeration.map(({ label, value }) => (<Radio value={value}>{t(label)}</Radio>))}
</Radio.Group>);
}
case 'ref': {
return (_jsx(RefAttr, { multiple: false, entityId: value, pickerRender: attrRender, onChange: (value) => {
return (<RefAttr multiple={false} entityId={value} pickerRender={attrRender} onChange={(value) => {
onValueChange(value[0]);
} }));
}}/>);
}
case 'coordinate': {
const { coordinate } = value || {};
const { extra } = attrRender;
const poiNameAttr = extra?.poiName || 'poiName';
const areaIdAttr = extra?.areaId || 'areaId';
return (_jsxs(_Fragment, { children: [_jsx(Modal, { width: "80vw", open: sl, closable: false, onCancel: () => setSl(false), okText: "\u786E\u8BA4", cancelText: "\u53D6\u6D88", okButtonProps: {
disabled: !poi,
}, onOk: () => {
if (poi) {
const { poiName, coordinate, areaId } = poi;
onValueChange({
type: 'point',
coordinate,
}, {
[poiNameAttr]: poiName,
[areaIdAttr]: areaId,
});
}
setSl(false);
}, children: _jsx(Location, { coordinate: coordinate, onLocated: (poi) => setPoi(poi) }) }), _jsx("div", { style: {
display: 'flex',
flexDirection: 'column',
width: '100%',
}, children: _jsxs(Space, { direction: "vertical", size: 8, children: [_jsx(Space, { align: "center", children: _jsx(Button, { type: "dashed", onClick: () => {
setSl(true);
}, children: value ? '重选位置' : '选择位置' }) }), _jsx("div", { style: {
display: 'flex',
flexDirection: 'column',
width: '100%',
}, children: _jsx(Map, { undragable: true, disableWheelZoom: true, style: { height: 300 }, autoLocate: true, center: coordinate, markers: coordinate ? [coordinate] : undefined }) })] }) })] }));
return (<>
<Modal width="80vw" open={sl} closable={false} onCancel={() => setSl(false)} okText="确认" cancelText="取消" okButtonProps={{
disabled: !poi,
}} onOk={() => {
if (poi) {
const { poiName, coordinate, areaId } = poi;
onValueChange({
type: 'point',
coordinate,
}, {
[poiNameAttr]: poiName,
[areaIdAttr]: areaId,
});
}
setSl(false);
}}>
<Location coordinate={coordinate} onLocated={(poi) => setPoi(poi)}/>
</Modal>
<div style={{
display: 'flex',
flexDirection: 'column',
width: '100%',
}}>
<Space direction="vertical" size={8}>
<Space align="center">
<Button type="dashed" onClick={() => {
setSl(true);
}}>
{value ? '重选位置' : '选择位置'}
</Button>
</Space>
<div style={{
display: 'flex',
flexDirection: 'column',
width: '100%',
}}>
<Map undragable={true} disableWheelZoom={true} style={{ height: 300 }} autoLocate={true} center={coordinate} markers={coordinate ? [coordinate] : undefined}/>
</div>
</Space>
</div>
</>);
}
default: {
throw new Error(`【Abstract Update】无法支持的数据类别${type}的渲染`);
@ -129,7 +146,8 @@ function makeAttrInput(attrRender, onValueChange, t, label) {
export default function render(props) {
const { renderData = [], helps, entity } = props.data;
const { update, t } = props.methods;
return (_jsx(Form, { labelCol: { span: 4 }, layout: "horizontal", children: renderData.map((ele) => {
return (<Form labelCol={{ span: 4 }} layout="horizontal">
{renderData.map((ele) => {
// 因为i18n渲染机制的缘故t必须放到这里来计算
const { label, attr, type, required } = ele;
let label2 = label;
@ -147,16 +165,21 @@ export default function render(props) {
// label2 = t(`${entity}:attr.${attr}`);
// }
// }
return (_jsx(Form.Item, { label: label2, rules: [
return (<Form.Item label={label2} rules={[
{
required: !!required,
},
], help: helps && helps[attr], name: required ? attr : '', children: _jsx(_Fragment, { children: makeAttrInput(ele, (value, extra) => {
const { attr } = ele;
update({
[attr]: value,
...extra,
});
}, t, label2) }) }));
}) }));
]} help={helps && helps[attr]} name={required ? attr : ''}>
<>
{makeAttrInput(ele, (value, extra) => {
const { attr } = ele;
update({
[attr]: value,
...extra,
});
}, t, label2)}
</>
</Form.Item>);
})}
</Form>);
}

View File

@ -278,6 +278,7 @@ class ListNode extends Node {
this.filters = filters || [];
this.sorters = sorters || [];
this.getTotal = getTotal;
this.sr = {};
this.pagination = pagination ? {
...pagination,
currentPage: pagination.currentPage - 1,
@ -661,7 +662,7 @@ class ListNode extends Node {
};
}
else {
this.sr = data;
this.sr = data || {};
}
for (const k in this.children) {
const child = this.children[k];
@ -1091,19 +1092,23 @@ class SingleNode extends Node {
for (const k of keys) {
const child = this.children[k];
const rel = this.judgeRelation(k);
if (rel === 2 && value.entityId) {
assert(child instanceof SingleNode);
assert(value.entity === child.getEntity());
child.saveRefreshResult({
[value.entityId]: this.sr[k] || {},
});
if (rel === 2) {
if (value?.entityId) {
assert(child instanceof SingleNode);
assert(value.entity === child.getEntity());
child.saveRefreshResult({
[value.entityId]: this.sr[k] || {},
});
}
}
else if (typeof rel === 'string' && value[`${k}Id`]) {
assert(child instanceof SingleNode);
assert(rel === child.getEntity());
child.saveRefreshResult({
[value[`${k}Id`]]: this.sr[k] || {},
});
else if (typeof rel === 'string') {
if (value && value[`${k}Id`]) {
assert(child instanceof SingleNode);
assert(rel === child.getEntity());
child.saveRefreshResult({
[value[`${k}Id`]]: this.sr[k] || {},
});
}
}
else {
assert(rel instanceof Array);

9
es/page.native.d.ts vendored Normal file
View File

@ -0,0 +1,9 @@
import { CommonAspectDict } from 'oak-common-aspect';
import { Aspect, EntityDict } from 'oak-domain/lib/types';
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
import { BasicFeatures } from './features';
import { Feature } from './types/Feature';
import { DataOption, OakComponentOption } from './types/Page';
import { SyncContext } from 'oak-domain/lib/store/SyncRowStore';
import { AsyncContext } from 'oak-domain/lib/store/AsyncRowStore';
export declare function createComponent<IsList extends boolean, ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends AsyncContext<ED>, FrontCxt extends SyncContext<ED>, AD extends Record<string, Aspect<ED, Cxt>>, FD extends Record<string, Feature>, FormedData extends Record<string, any>, TData extends Record<string, any> = {}, TProperty extends DataOption = {}, TMethod extends Record<string, Function> = {}>(option: OakComponentOption<IsList, ED, T, Cxt, FrontCxt, AD, FD, FormedData, TData, TProperty, TMethod>, features: BasicFeatures<ED, Cxt, FrontCxt, AD & CommonAspectDict<ED, Cxt>> & FD): void;

44
es/page.native.js Normal file
View File

@ -0,0 +1,44 @@
import { createComponent as createReactComponent } from './page.react';
const DEFAULT_REACH_BOTTOM_DISTANCE = 50;
export function createComponent(option, features) {
const BaseComponent = createReactComponent(option, features);
class Component extends BaseComponent {
scrollEvent = () => {
this.checkReachBottom();
};
registerPageScroll() {
window.addEventListener('scroll', this.scrollEvent);
}
unregisterPageScroll() {
window.removeEventListener('scroll', this.scrollEvent);
}
checkReachBottom() {
if (!this.supportPullDownRefresh()) {
return;
}
const isCurrentReachBottom = document.body.scrollHeight -
(window.innerHeight + window.scrollY) <=
DEFAULT_REACH_BOTTOM_DISTANCE;
if (!this.isReachBottom && isCurrentReachBottom && option.isList) {
this.isReachBottom = true;
// 执行触底事件
this.loadMore();
return;
}
this.isReachBottom = isCurrentReachBottom;
}
async componentDidMount() {
this.registerPageScroll();
await super.componentDidMount();
}
componentWillUnmount() {
this.unregisterPageScroll();
super.componentWillUnmount();
}
render() {
const { oakPullDownRefreshLoading } = this.state;
const Render = super.render();
return Render;
}
}
}

View File

@ -1,4 +1,3 @@
import { jsx as _jsx } from "react/jsx-runtime";
import { assert } from 'oak-domain/lib/utils/assert';
import React from 'react';
import { get } from 'oak-domain/lib/utils/lodash';
@ -617,11 +616,11 @@ export function createComponent(option, features) {
if (this.oakOption.entity && !this.state.oakFullpath) {
return null;
}
return (_jsx(Render, { methods: this.methodProps, data: {
return (<Render methods={this.methodProps} data={{
...this.defaultProperties,
...this.state,
...this.props,
} }));
}}/>);
}
}
;

View File

@ -1,4 +1,4 @@
import { jsx as _jsx } from "react/jsx-runtime";
import React from 'react';
import { withRouter, PullToRefresh } from './platforms/web';
import { createComponent as createReactComponent } from './page.react';
const DEFAULT_REACH_BOTTOM_DISTANCE = 50;
@ -41,7 +41,7 @@ export function createComponent(option, features) {
const { oakPullDownRefreshLoading } = this.state;
const Render = super.render();
if (this.supportPullDownRefresh()) {
return (_jsx(PullToRefresh, { onRefresh: async () => {
return (<PullToRefresh onRefresh={async () => {
this.setState({
oakPullDownRefreshLoading: true,
});
@ -49,7 +49,7 @@ export function createComponent(option, features) {
this.setState({
oakPullDownRefreshLoading: false,
});
}, refreshing: oakPullDownRefreshLoading, distanceToRefresh: DEFAULT_REACH_BOTTOM_DISTANCE, indicator: {
}} refreshing={oakPullDownRefreshLoading} distanceToRefresh={DEFAULT_REACH_BOTTOM_DISTANCE} indicator={{
activate: this.t('common::ptrActivate', {
'#oakModule': 'oak-frontend-base',
}),
@ -62,7 +62,9 @@ export function createComponent(option, features) {
finish: this.t('common::ptrFinish', {
'#oakModule': 'oak-frontend-base',
}),
}, children: Render }));
}}>
{Render}
</PullToRefresh>);
}
return Render;
}

View File

@ -1,7 +1,7 @@
import { jsx as _jsx } from "react/jsx-runtime";
import React from 'react';
import PullToRefresh from 'rmc-pull-to-refresh';
import './PullToRefresh.css';
const OakPullToRefresh = (props) => {
return _jsx(PullToRefresh, { ...props, prefixCls: "oak-pull-to-refresh" });
return <PullToRefresh {...props} prefixCls="oak-pull-to-refresh"/>;
};
export default OakPullToRefresh;

View File

@ -1,4 +1,3 @@
import { jsx as _jsx } from "react/jsx-runtime";
import React from 'react';
// @ts-ignore
import { useLocation, useParams } from 'react-router-dom';
@ -83,8 +82,8 @@ const withRouter = (Component, { path, properties }) => {
params = Object.assign(params, getParams(location, properties), routerParams);
routeMatch = true;
}
return (_jsx(Component, { ...rest, ...params, width: width, location: location, ref: forwardedRef, routeMatch: routeMatch }));
return (<Component {...rest} {...params} width={width} location={location} ref={forwardedRef} routeMatch={routeMatch}/>);
};
return React.forwardRef((props, ref) => _jsx(ComponentWithRouterProp, { ...props, forwardedRef: ref }));
return React.forwardRef((props, ref) => <ComponentWithRouterProp {...props} forwardedRef={ref}/>);
};
export default withRouter;

View File

@ -281,6 +281,7 @@ class ListNode extends Node {
this.filters = filters || [];
this.sorters = sorters || [];
this.getTotal = getTotal;
this.sr = {};
this.pagination = pagination ? {
...pagination,
currentPage: pagination.currentPage - 1,
@ -664,7 +665,7 @@ class ListNode extends Node {
};
}
else {
this.sr = data;
this.sr = data || {};
}
for (const k in this.children) {
const child = this.children[k];
@ -1094,19 +1095,23 @@ class SingleNode extends Node {
for (const k of keys) {
const child = this.children[k];
const rel = this.judgeRelation(k);
if (rel === 2 && value.entityId) {
(0, assert_1.assert)(child instanceof SingleNode);
(0, assert_1.assert)(value.entity === child.getEntity());
child.saveRefreshResult({
[value.entityId]: this.sr[k] || {},
});
if (rel === 2) {
if (value?.entityId) {
(0, assert_1.assert)(child instanceof SingleNode);
(0, assert_1.assert)(value.entity === child.getEntity());
child.saveRefreshResult({
[value.entityId]: this.sr[k] || {},
});
}
}
else if (typeof rel === 'string' && value[`${k}Id`]) {
(0, assert_1.assert)(child instanceof SingleNode);
(0, assert_1.assert)(rel === child.getEntity());
child.saveRefreshResult({
[value[`${k}Id`]]: this.sr[k] || {},
});
else if (typeof rel === 'string') {
if (value && value[`${k}Id`]) {
(0, assert_1.assert)(child instanceof SingleNode);
(0, assert_1.assert)(rel === child.getEntity());
child.saveRefreshResult({
[value[`${k}Id`]]: this.sr[k] || {},
});
}
}
else {
(0, assert_1.assert)(rel instanceof Array);

9
lib/page.native.d.ts vendored Normal file
View File

@ -0,0 +1,9 @@
import { CommonAspectDict } from 'oak-common-aspect';
import { Aspect, EntityDict } from 'oak-domain/lib/types';
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
import { BasicFeatures } from './features';
import { Feature } from './types/Feature';
import { DataOption, OakComponentOption } from './types/Page';
import { SyncContext } from 'oak-domain/lib/store/SyncRowStore';
import { AsyncContext } from 'oak-domain/lib/store/AsyncRowStore';
export declare function createComponent<IsList extends boolean, ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends AsyncContext<ED>, FrontCxt extends SyncContext<ED>, AD extends Record<string, Aspect<ED, Cxt>>, FD extends Record<string, Feature>, FormedData extends Record<string, any>, TData extends Record<string, any> = {}, TProperty extends DataOption = {}, TMethod extends Record<string, Function> = {}>(option: OakComponentOption<IsList, ED, T, Cxt, FrontCxt, AD, FD, FormedData, TData, TProperty, TMethod>, features: BasicFeatures<ED, Cxt, FrontCxt, AD & CommonAspectDict<ED, Cxt>> & FD): void;

48
lib/page.native.js Normal file
View File

@ -0,0 +1,48 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createComponent = void 0;
const page_react_1 = require("./page.react");
const DEFAULT_REACH_BOTTOM_DISTANCE = 50;
function createComponent(option, features) {
const BaseComponent = (0, page_react_1.createComponent)(option, features);
class Component extends BaseComponent {
scrollEvent = () => {
this.checkReachBottom();
};
registerPageScroll() {
window.addEventListener('scroll', this.scrollEvent);
}
unregisterPageScroll() {
window.removeEventListener('scroll', this.scrollEvent);
}
checkReachBottom() {
if (!this.supportPullDownRefresh()) {
return;
}
const isCurrentReachBottom = document.body.scrollHeight -
(window.innerHeight + window.scrollY) <=
DEFAULT_REACH_BOTTOM_DISTANCE;
if (!this.isReachBottom && isCurrentReachBottom && option.isList) {
this.isReachBottom = true;
// 执行触底事件
this.loadMore();
return;
}
this.isReachBottom = isCurrentReachBottom;
}
async componentDidMount() {
this.registerPageScroll();
await super.componentDidMount();
}
componentWillUnmount() {
this.unregisterPageScroll();
super.componentWillUnmount();
}
render() {
const { oakPullDownRefreshLoading } = this.state;
const Render = super.render();
return Render;
}
}
}
exports.createComponent = createComponent;

View File

@ -385,6 +385,7 @@ class ListNode<
this.filters = filters || [];
this.sorters = sorters || [];
this.getTotal = getTotal;
this.sr = {};
this.pagination = pagination ? {
...pagination,
currentPage: pagination.currentPage - 1,
@ -825,7 +826,7 @@ class ListNode<
};
}
else {
this.sr = data;
this.sr = data || {};
}
for (const k in this.children) {
const child = this.children[k];
@ -1320,19 +1321,23 @@ class SingleNode<ED extends EntityDict & BaseEntityDict,
for (const k of keys) {
const child = this.children[k]!;
const rel = this.judgeRelation(k);
if (rel === 2 && value.entityId) {
assert(child instanceof SingleNode);
assert(value.entity === child.getEntity());
child.saveRefreshResult({
[value.entityId!]: this.sr![k] || {},
});
if (rel === 2) {
if (value?.entityId) {
assert(child instanceof SingleNode);
assert(value.entity === child.getEntity());
child.saveRefreshResult({
[value.entityId!]: this.sr![k] || {},
});
}
}
else if (typeof rel === 'string' && value[`${k}Id`]) {
assert(child instanceof SingleNode);
assert(rel === child.getEntity());
child.saveRefreshResult({
[value[`${k}Id`] as string]: this.sr![k] || {},
});
else if (typeof rel === 'string') {
if (value && value[`${k}Id`]) {
assert(child instanceof SingleNode);
assert(rel === child.getEntity());
child.saveRefreshResult({
[value[`${k}Id`] as string]: this.sr![k] || {},
});
}
}
else {
assert (rel instanceof Array);

100
src/page.native.ts Normal file
View File

@ -0,0 +1,100 @@
import React from 'react';
import { RefreshControl, View, StyleSheet, } from 'react-native';
import { CommonAspectDict } from 'oak-common-aspect';
import { Aspect, EntityDict } from 'oak-domain/lib/types';
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
import { BasicFeatures } from './features';
import { Feature } from './types/Feature';
import {
DataOption,
OakComponentOption,
} from './types/Page';
import { SyncContext } from 'oak-domain/lib/store/SyncRowStore';
import { AsyncContext } from 'oak-domain/lib/store/AsyncRowStore';
import { createComponent as createReactComponent } from './page.react';
const DEFAULT_REACH_BOTTOM_DISTANCE = 50;
export function createComponent<
IsList extends boolean,
ED extends EntityDict & BaseEntityDict,
T extends keyof ED,
Cxt extends AsyncContext<ED>,
FrontCxt extends SyncContext<ED>,
AD extends Record<string, Aspect<ED, Cxt>>,
FD extends Record<string, Feature>,
FormedData extends Record<string, any>,
TData extends Record<string, any> = {},
TProperty extends DataOption = {},
TMethod extends Record<string, Function> = {}
>(
option: OakComponentOption<
IsList,
ED,
T,
Cxt,
FrontCxt,
AD,
FD,
FormedData,
TData,
TProperty,
TMethod
>,
features: BasicFeatures<ED, Cxt, FrontCxt, AD & CommonAspectDict<ED, Cxt>> & FD,
) {
const BaseComponent = createReactComponent<
IsList, ED, T, Cxt, FrontCxt, AD, FD, FormedData, TData, TProperty, TMethod
>(option, features);
class Component extends BaseComponent {
private scrollEvent = () => {
this.checkReachBottom();
};
private registerPageScroll() {
window.addEventListener('scroll', this.scrollEvent);
}
private unregisterPageScroll() {
window.removeEventListener('scroll', this.scrollEvent);
}
private checkReachBottom() {
if (!this.supportPullDownRefresh()) {
return;
}
const isCurrentReachBottom =
document.body.scrollHeight -
(window.innerHeight + window.scrollY) <=
DEFAULT_REACH_BOTTOM_DISTANCE;
if (!this.isReachBottom && isCurrentReachBottom && option.isList) {
this.isReachBottom = true;
// 执行触底事件
this.loadMore();
return;
}
this.isReachBottom = isCurrentReachBottom;
}
async componentDidMount() {
this.registerPageScroll();
await super.componentDidMount();
}
componentWillUnmount(): void {
this.unregisterPageScroll();
super.componentWillUnmount();
}
render(): React.ReactNode {
const { oakPullDownRefreshLoading } = this.state;
const Render = super.render();
return Render;
}
}
}