Compare commits
45 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
4929590c81 | |
|
|
567e0abc6a | |
|
|
a26f464ba1 | |
|
|
fdd24a8cc8 | |
|
|
fff9750b2a | |
|
|
f16b3f91a8 | |
|
|
6e48eb02b4 | |
|
|
b07f084341 | |
|
|
96b8cd9366 | |
|
|
363b329070 | |
|
|
51cc8786a0 | |
|
|
ea01036c5a | |
|
|
71f385f0f4 | |
|
|
91bf1da808 | |
|
|
81b12efe6e | |
|
|
40a98dd51a | |
|
|
94dc93868c | |
|
|
a9a358727b | |
|
|
b8e3dcd24a | |
|
|
3ca9d51d4d | |
|
|
73de8a74c0 | |
|
|
5c710ef019 | |
|
|
2e214df7fd | |
|
|
626b40b4e3 | |
|
|
39ee45fee2 | |
|
|
306c0a75ef | |
|
|
5a3d06d037 | |
|
|
e4d8ed5e03 | |
|
|
9541e67508 | |
|
|
285c872822 | |
|
|
f52d28a4e5 | |
|
|
9d71fd9c30 | |
|
|
90a2125ddb | |
|
|
34160dc90c | |
|
|
45a50ed6cc | |
|
|
3b6091db78 | |
|
|
f924d06fa3 | |
|
|
230d459b59 | |
|
|
4f698ce772 | |
|
|
43b1f61f4a | |
|
|
28d1579d4d | |
|
|
759db28f73 | |
|
|
4c5ea92f29 | |
|
|
b817fbd384 | |
|
|
e0f8544c8a |
|
|
@ -8,5 +8,5 @@ type TransformAspectDict<T extends AspectDict<ED, BCT>, ED extends BaseEntityDic
|
|||
[K in keyof T]: T[K] extends (params: infer P, context: BCT) => infer R ? R extends Promise<unknown> ? (params: P, callback?: (result: R, opRecords?: OpRecord<ED>[]) => void, dontPublish?: true, ignoreContext?: true) => R : never : never;
|
||||
};
|
||||
export type AspectDictTrans<ED extends BaseEntityDict, AD extends AspectDict<ED, BCT>, BCT extends AsyncContext<ED>> = TransformAspectDict<AD & CommonAspectDict<ED>, ED, BCT>;
|
||||
export declare const createService: <ED extends BaseEntityDict, AD extends AspectDict<ED, any>>(cache: BasicFeatures<ED>["cache"]) => TransformAspectDict<AD & CommonAspectDict<ED>, ED, any>;
|
||||
export declare const createService: <ED extends BaseEntityDict, AD extends AspectDict<ED, any>>(cache: BasicFeatures<ED>["cache"]) => AspectDictTrans<ED, AD, any>;
|
||||
export {};
|
||||
|
|
|
|||
|
|
@ -1,18 +1,10 @@
|
|||
/// <reference types="react" />
|
||||
import { ED, OakExtraActionProps } from '../../types/AbstractComponent';
|
||||
import { ActionDef } from '../../types/Page';
|
||||
declare const _default: (props: import("../../types/Page").ReactComponentProps<import("oak-domain/lib/types").EntityDict & import("oak-domain/lib/base-app-domain").EntityDict, string | number, false, {
|
||||
entity: string | number;
|
||||
entity: keyof ED;
|
||||
extraActions: OakExtraActionProps[];
|
||||
actions: ActionDef<ED, string | number>[];
|
||||
cascadeActions: {
|
||||
[x: string]: ActionDef<ED, string | number>[] | undefined;
|
||||
id?: ActionDef<ED, string | number>[] | undefined;
|
||||
$$seq$$?: ActionDef<ED, string | number>[] | undefined;
|
||||
$$createAt$$?: ActionDef<ED, string | number>[] | undefined;
|
||||
$$updateAt$$?: ActionDef<ED, string | number>[] | undefined;
|
||||
$$deleteAt$$?: ActionDef<ED, string | number>[] | undefined;
|
||||
};
|
||||
actions: ActionDef<ED, keyof ED>[];
|
||||
cascadeActions: { [K in keyof ED[keyof ED]["Schema"]]?: ActionDef<ED, keyof ED>[]; };
|
||||
onAction: Function;
|
||||
}>) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
|
||||
}>) => React.ReactElement;
|
||||
export default _default;
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
/// <reference types="react" />
|
||||
import { ED } from "../../types/AbstractComponent";
|
||||
import { Item } from './types';
|
||||
declare const _default: (props: import("../..").ReactComponentProps<import("oak-domain/lib/types").EntityDict & import("oak-domain/lib/base-app-domain").EntityDict, string | number, false, {
|
||||
entity: string | number;
|
||||
entity: keyof ED;
|
||||
items: Item[];
|
||||
mode: "default" | "cell" | "table-cell";
|
||||
column: number;
|
||||
fixed: boolean;
|
||||
}>) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
|
||||
}>) => React.ReactElement;
|
||||
export default _default;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
/// <reference types="react" />
|
||||
import { ButtonProps } from 'antd';
|
||||
export type Item = {
|
||||
icon?: string | React.ReactNode;
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
/// <reference types="react" />
|
||||
import { ED } from "../../types/AbstractComponent";
|
||||
import { IMode, Item } from "./type";
|
||||
declare const _default: (props: import("../..").ReactComponentProps<import("oak-domain/lib/types").EntityDict & import("oak-domain/lib/base-app-domain").EntityDict, string | number, false, {
|
||||
entity: string | number;
|
||||
entity: keyof ED;
|
||||
items: Item[];
|
||||
rows: number;
|
||||
column: number;
|
||||
mode: IMode;
|
||||
}>) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
|
||||
}>) => React.ReactElement;
|
||||
export default _default;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
/// <reference types="react" />
|
||||
import { ButtonProps } from 'antd';
|
||||
export type Item = {
|
||||
icon?: string;
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
/// <reference types="react" />
|
||||
declare const _default: (props: import("../..").ReactComponentProps<import("oak-domain/lib/types").EntityDict & import("oak-domain/lib/base-app-domain").EntityDict, string | number, boolean, {
|
||||
value: (string | number)[];
|
||||
option: {
|
||||
value: Array<string | number>;
|
||||
option: Array<{
|
||||
label: string;
|
||||
value: string | number;
|
||||
}[];
|
||||
}>;
|
||||
onSelect: (v: Array<string | number>) => void;
|
||||
disabled: boolean;
|
||||
}>) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
|
||||
}>) => React.ReactElement;
|
||||
export default _default;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,2 @@
|
|||
/// <reference types="wechat-miniprogram" />
|
||||
/// <reference types="react" />
|
||||
declare const _default: (props: import("../../..").ReactComponentProps<import("oak-domain/lib/types").EntityDict & import("oak-domain/lib/base-app-domain").EntityDict, string | number, false, WechatMiniprogram.Component.DataOption>) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
|
||||
declare const _default: (props: import("../../..").ReactComponentProps<import("oak-domain/lib/types").EntityDict & import("oak-domain/lib/base-app-domain").EntityDict, string | number, false, WechatMiniprogram.Component.DataOption>) => React.ReactElement;
|
||||
export default _default;
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@ declare const _default: <ED2 extends ED, T2 extends keyof ED2>(props: ReactCompo
|
|||
column?: number | Record<Breakpoint, number>;
|
||||
entity: T2;
|
||||
attributes: OakAbsAttrDef[];
|
||||
data: Partial<ED2[T2]['Schema']>;
|
||||
data: Partial<ED2[T2]["Schema"]>;
|
||||
title?: string;
|
||||
bordered?: boolean;
|
||||
layout?: 'horizontal' | 'vertical';
|
||||
layout?: "horizontal" | "vertical";
|
||||
}>) => React.ReactElement;
|
||||
export default _default;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
/// <reference types="react" />
|
||||
declare const _default: (props: import("../../..").ReactComponentProps<import("oak-domain/lib/types").EntityDict & import("oak-domain/lib/base-app-domain").EntityDict, string | number, true, {
|
||||
onClicked: (entity: string) => void;
|
||||
}>) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
|
||||
}>) => React.ReactElement;
|
||||
export default _default;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
/// <reference types="react" />
|
||||
import { ED } from '../../types/AbstractComponent';
|
||||
import { ColumnProps } from '../../types/Filter';
|
||||
declare const _default: (props: import("../..").ReactComponentProps<import("oak-domain/lib/types").EntityDict & import("oak-domain/lib/base-app-domain").EntityDict, string | number, true, {
|
||||
entity: string | number;
|
||||
column: ColumnProps<ED, string | number>;
|
||||
}>) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
|
||||
entity: keyof ED;
|
||||
column: ColumnProps<ED, keyof ED>;
|
||||
}>) => React.ReactElement;
|
||||
export default _default;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
/// <reference types="react" />
|
||||
declare const _default: (props: import("../../..").ReactComponentProps<import("oak-domain/lib/types").EntityDict & import("oak-domain/lib/base-app-domain").EntityDict, string | number, false, {
|
||||
onActionClick: (action: string) => void;
|
||||
actions: string[];
|
||||
actionDescriptions: any;
|
||||
iconSize: string;
|
||||
rowNum: number;
|
||||
}>) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
|
||||
}>) => React.ReactElement;
|
||||
export default _default;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,2 @@
|
|||
/// <reference types="wechat-miniprogram" />
|
||||
/// <reference types="react" />
|
||||
declare const _default: (props: import("../../..").ReactComponentProps<import("oak-domain/lib/types").EntityDict & import("oak-domain/lib/base-app-domain").EntityDict, string | number, true, WechatMiniprogram.Component.DataOption>) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
|
||||
declare const _default: (props: import("../../..").ReactComponentProps<import("oak-domain/lib/types").EntityDict & import("oak-domain/lib/base-app-domain").EntityDict, string | number, true, WechatMiniprogram.Component.DataOption>) => React.ReactElement;
|
||||
export default _default;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,2 @@
|
|||
/// <reference types="wechat-miniprogram" />
|
||||
/// <reference types="react" />
|
||||
declare const _default: (props: import("../../..").ReactComponentProps<import("oak-domain/lib/types").EntityDict & import("oak-domain/lib/base-app-domain").EntityDict, "i18n", true, WechatMiniprogram.Component.DataOption>) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
|
||||
declare const _default: (props: import("../../..").ReactComponentProps<import("oak-domain/lib/types").EntityDict & import("oak-domain/lib/base-app-domain").EntityDict, "i18n", true, WechatMiniprogram.Component.DataOption>) => React.ReactElement;
|
||||
export default _default;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,2 @@
|
|||
/// <reference types="wechat-miniprogram" />
|
||||
/// <reference types="react" />
|
||||
declare const _default: (props: import("../../..").ReactComponentProps<import("oak-domain/lib/types").EntityDict & import("oak-domain/lib/base-app-domain").EntityDict, "i18n", false, WechatMiniprogram.Component.DataOption>) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
|
||||
declare const _default: (props: import("../../..").ReactComponentProps<import("oak-domain/lib/types").EntityDict & import("oak-domain/lib/base-app-domain").EntityDict, "i18n", false, WechatMiniprogram.Component.DataOption>) => React.ReactElement;
|
||||
export default _default;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
/// <reference types="react" />
|
||||
declare const _default: (props: import("../..").ReactComponentProps<import("oak-domain/lib/types").EntityDict & import("oak-domain/lib/base-app-domain").EntityDict, string | number, false, {
|
||||
name: string;
|
||||
size: number | null | undefined;
|
||||
color: string;
|
||||
size: number | undefined | null;
|
||||
color: "primary" | "success" | "error" | "waring" | "info" | string;
|
||||
oakClass: string;
|
||||
}>) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
|
||||
}>) => React.ReactElement;
|
||||
export default _default;
|
||||
|
|
|
|||
|
|
@ -10,11 +10,11 @@ declare const _default: <ED2 extends ED, T2 extends keyof ED2>(props: ReactCompo
|
|||
data: RowWithActions<ED2, T2>[];
|
||||
loading: boolean;
|
||||
tablePagination?: React.ReactNode | false;
|
||||
rowSelection?: TableProps<RowWithActions<ED2, T2>>['rowSelection'];
|
||||
rowSelection?: TableProps<RowWithActions<ED2, T2>>["rowSelection"];
|
||||
hideHeader?: boolean;
|
||||
disableSerialNumber?: boolean;
|
||||
size?: 'large' | 'middle' | 'small';
|
||||
scroll?: TableProps<RowWithActions<ED2, T2>>['scroll'];
|
||||
size?: "large" | "middle" | "small";
|
||||
scroll?: TableProps<RowWithActions<ED2, T2>>["scroll"];
|
||||
empty?: React.ReactNode;
|
||||
opWidth?: number;
|
||||
ellipsis?: boolean;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { ED, OakAbsDerivedAttrDef } from '../../../types/AbstractComponent';
|
|||
import { ReactComponentProps } from '../../../types/Page';
|
||||
declare const _default: <ED2 extends ED, T2 extends keyof ED2>(props: ReactComponentProps<ED2, T2, false, {
|
||||
value: string | string[];
|
||||
type: OakAbsDerivedAttrDef['type'];
|
||||
type: OakAbsDerivedAttrDef["type"];
|
||||
color: string;
|
||||
linkUrl: string;
|
||||
}>) => React.ReactElement;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
/// <reference types="react" />
|
||||
declare const _default: (props: import("../..").ReactComponentProps<import("oak-domain/lib/types").EntityDict & import("oak-domain/lib/base-app-domain").EntityDict, string | number, false, {
|
||||
key: string;
|
||||
}>) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
|
||||
}>) => React.ReactElement;
|
||||
export default _default;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
declare const _default: (props: import("../..").ReactComponentProps<import("oak-domain/lib/types").EntityDict & import("oak-domain/lib/base-app-domain").EntityDict, string | number, false, {}>) => React.ReactElement;
|
||||
export default _default;
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
export default OakComponent({
|
||||
isList: false,
|
||||
formData({ props }) {
|
||||
const data = this.consumeNotification();
|
||||
if (data) {
|
||||
if (process.env.OAK_PLATFORM === 'wechatMp') {
|
||||
// lin-ui的message: https://doc.mini.talelin.com/component/response/message.html
|
||||
const type = !data.type || data.type === 'info' ? 'primary' : data.type;
|
||||
wx.lin.showMessage({
|
||||
type: type,
|
||||
content: data.message,
|
||||
icon: data.icon,
|
||||
duration: data.duration,
|
||||
});
|
||||
return {};
|
||||
}
|
||||
return {
|
||||
data,
|
||||
};
|
||||
}
|
||||
return {};
|
||||
},
|
||||
features: ['notification'],
|
||||
properties: {}
|
||||
});
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"l-message": "../../miniprogram_npm/lin-ui/message/index"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
.container {
|
||||
display: flex;
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
<l-message id="#oak-message" />
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
import { NotificationProps } from '../../types/Notification';
|
||||
export default function Render(props: {
|
||||
data: {
|
||||
data: NotificationProps;
|
||||
};
|
||||
}): null;
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
import { useEffect } from 'react';
|
||||
import { useToast } from '../../platforms/native/toast';
|
||||
export default function Render(props) {
|
||||
const toast = useToast();
|
||||
const { data } = props.data;
|
||||
useEffect(() => {
|
||||
if (data) {
|
||||
let type = 'normal';
|
||||
switch (data.type) {
|
||||
case 'error': {
|
||||
type = 'danger';
|
||||
break;
|
||||
}
|
||||
case 'info': {
|
||||
type = 'normal';
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
type = data.type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
let placement = 'top';
|
||||
switch (data.placement) {
|
||||
case 'top':
|
||||
case 'topLeft':
|
||||
case 'topRight': {
|
||||
placement = 'top';
|
||||
break;
|
||||
}
|
||||
case 'bottom':
|
||||
case 'bottomLeft':
|
||||
case 'bottomRight': {
|
||||
placement = 'bottom';
|
||||
break;
|
||||
}
|
||||
// case 'center': {
|
||||
// placement = 'center';
|
||||
// break;
|
||||
// }
|
||||
default: {
|
||||
// placement 其他不支持的类型都默认top
|
||||
placement = 'top';
|
||||
break;
|
||||
}
|
||||
}
|
||||
toast.show(data.description, {
|
||||
type: type,
|
||||
placement: placement,
|
||||
duration: data.duration || 4000,
|
||||
});
|
||||
}
|
||||
}, [data]);
|
||||
return null;
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
import React from 'react';
|
||||
import { NotificationProps } from '../../types/Notification';
|
||||
export default function Render(props: {
|
||||
data: {
|
||||
data: NotificationProps;
|
||||
};
|
||||
}): React.JSX.Element;
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
import React, { useEffect } from 'react';
|
||||
import { notification } from 'antd';
|
||||
export default function Render(props) {
|
||||
const { data, } = props.data;
|
||||
const [notificationApi, contextHolder] = notification.useNotification();
|
||||
useEffect(() => {
|
||||
if (data) {
|
||||
if (data.type) {
|
||||
notificationApi[data.type](data);
|
||||
}
|
||||
else {
|
||||
notificationApi.open(data);
|
||||
}
|
||||
}
|
||||
}, [data]);
|
||||
return <>{contextHolder}</>;
|
||||
}
|
||||
|
|
@ -5,7 +5,7 @@ declare const _default: <ED2 extends ED, T2 extends keyof ED2>(props: ReactCompo
|
|||
style?: React.CSSProperties;
|
||||
className?: string;
|
||||
showQuickJumper?: boolean;
|
||||
size?: 'default' | 'small';
|
||||
size?: "default" | "small";
|
||||
showSizeChanger?: boolean;
|
||||
showTotal?: (total: number, range: [number, number]) => React.ReactNode;
|
||||
}>) => React.ReactElement;
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ MiddleSelect.Option = Select.Option;
|
|||
export default function Render(props) {
|
||||
const { style, className, oakPagination, oakFullpath, newTotal, showQuickJumper, showSizeChanger, size, showTotal, showTitle, } = props.data;
|
||||
const { t, setPageSize, setCurrentPage } = props.methods;
|
||||
const { pageSize, total, currentPage, more, count, getTotal } = oakPagination || {};
|
||||
const { pageSize = 0, total = 0, currentPage = 1, more, count, getTotal } = oakPagination || {};
|
||||
const paginationRef = useRef(null);
|
||||
const [internalInputVal, setInternalInputVal] = useState(currentPage);
|
||||
useEffect(() => {
|
||||
|
|
@ -28,7 +28,7 @@ export default function Render(props) {
|
|||
if (!oakPagination) {
|
||||
return null;
|
||||
}
|
||||
if (total === 0) {
|
||||
if (!total) {
|
||||
return null;
|
||||
}
|
||||
const prefixCls = 'rc-pagination';
|
||||
|
|
|
|||
|
|
@ -1,23 +1,15 @@
|
|||
/// <reference types="react" />
|
||||
import { ED } from '../../types/AbstractComponent';
|
||||
import { RowWithActions } from '../..';
|
||||
declare const _default: (props: import("../..").ReactComponentProps<import("oak-domain/lib/types").EntityDict & import("oak-domain/lib/base-app-domain").EntityDict, string | number, true, {
|
||||
entity: string | number;
|
||||
entity: keyof ED;
|
||||
multiple: boolean;
|
||||
onSelect: (value: [{
|
||||
id: string;
|
||||
}]) => void;
|
||||
title: (row: RowWithActions<ED, keyof ED>) => string;
|
||||
titleLabel: string;
|
||||
filter: {
|
||||
[K: string]: any;
|
||||
};
|
||||
sorter: {
|
||||
$attr: {
|
||||
[K: string]: any;
|
||||
};
|
||||
$direction?: "asc" | "desc" | undefined;
|
||||
}[];
|
||||
filter: ED[keyof ED]["Filter"];
|
||||
sorter: ED[keyof ED]["Sorter"];
|
||||
projection: {};
|
||||
}>) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
|
||||
}>) => React.ReactElement;
|
||||
export default _default;
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
/// <reference types="react" />
|
||||
import { ED, OakAbsRefAttrPickerRender } from '../../types/AbstractComponent';
|
||||
declare const _default: (props: import("../..").ReactComponentProps<import("oak-domain/lib/types").EntityDict & import("oak-domain/lib/base-app-domain").EntityDict, string | number, false, {
|
||||
placeholder: string | undefined;
|
||||
multiple: boolean;
|
||||
entityId: string;
|
||||
entityIds: string[];
|
||||
pickerRender: OakAbsRefAttrPickerRender<ED, string | number>;
|
||||
pickerRender: OakAbsRefAttrPickerRender<ED, keyof ED>;
|
||||
onChange: (value: string[]) => void;
|
||||
}>) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
|
||||
}>) => React.ReactElement;
|
||||
export default _default;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
/// <reference types="react" />
|
||||
declare const _default: (props: import("../../..").ReactComponentProps<import("oak-domain/lib/types").EntityDict & import("oak-domain/lib/base-app-domain").EntityDict, "actionAuth", true, {
|
||||
pathId: string;
|
||||
relations: {
|
||||
|
|
@ -6,5 +5,5 @@ declare const _default: (props: import("../../..").ReactComponentProps<import("o
|
|||
name: string;
|
||||
}[];
|
||||
actions: string[];
|
||||
}>) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
|
||||
}>) => React.ReactElement;
|
||||
export default _default;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
/// <reference types="react" />
|
||||
declare const _default: (props: import("../../../..").ReactComponentProps<import("oak-domain/lib/types").EntityDict & import("oak-domain/lib/base-app-domain").EntityDict, "path", false, {
|
||||
actions: string[];
|
||||
}>) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
|
||||
}>) => React.ReactElement;
|
||||
export default _default;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
/// <reference types="react" />
|
||||
import { EntityDict } from 'oak-domain/lib/base-app-domain';
|
||||
declare const _default: (props: import("../../../..").ReactComponentProps<import("oak-domain/lib/types").EntityDict & EntityDict, "path", true, {
|
||||
entity: string;
|
||||
}>) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
|
||||
}>) => React.ReactElement;
|
||||
export default _default;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
/// <reference types="react" />
|
||||
import { EntityDict } from 'oak-domain/lib/base-app-domain';
|
||||
declare const _default: (props: import("../../../..").ReactComponentProps<import("oak-domain/lib/types").EntityDict & EntityDict, "path", false, {
|
||||
onConfirmed: () => void;
|
||||
entity: string;
|
||||
}>) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
|
||||
}>) => React.ReactElement;
|
||||
export default _default;
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ export default OakComponent({
|
|||
return false;
|
||||
});
|
||||
const schema = this.features.cache.getSchema();
|
||||
const legalSourceEntity = !!schema[choice.entity].relation?.length || choice.entity === 'user';
|
||||
const legalSourceEntity = !!schema[choice.entity].relation?.length || !!choice.entity;
|
||||
this.setState({
|
||||
pathChoice: pathChoice2,
|
||||
pathChosen: pathChosen2,
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ export default function render(props) {
|
|||
<Input disabled value={path.sourceEntity}/>
|
||||
</Form.Item>}
|
||||
{legalSourceEntity && <Form.Item label={t('path:attr.recursive')} help={!recursivable && <span className={Styles.warning}>{t('tips.recursive')}</span>}>
|
||||
<Switch checked={path.recursive} onChange={(checked) => {
|
||||
<Switch checked={!!path.recursive} onChange={(checked) => {
|
||||
update({
|
||||
recursive: checked,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
/// <reference types="react" />
|
||||
declare const _default: (props: import("../../..").ReactComponentProps<import("oak-domain/lib/types").EntityDict & import("oak-domain/lib/base-app-domain").EntityDict, "relationAuth", true, {
|
||||
pathId: string;
|
||||
sourceRelations: {
|
||||
|
|
@ -9,5 +8,5 @@ declare const _default: (props: import("../../..").ReactComponentProps<import("o
|
|||
id: string;
|
||||
name: string;
|
||||
}[];
|
||||
}>) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
|
||||
}>) => React.ReactElement;
|
||||
export default _default;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/// <reference types="react" />
|
||||
import { ED } from '../../types/AbstractComponent';
|
||||
declare const _default: (props: import("../..").ReactComponentProps<import("oak-domain/lib/types").EntityDict & import("oak-domain/lib/base-app-domain").EntityDict, string | number, true, {
|
||||
entity: string | number;
|
||||
entity: keyof ED;
|
||||
attributes: string[];
|
||||
placeholder: string;
|
||||
}>) => import("react").ReactElement<any, string | import("react").JSXElementConstructor<any>>;
|
||||
}>) => React.ReactElement;
|
||||
export default _default;
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import { ED, OakAbsAttrUpsertDef } from '../../types/AbstractComponent';
|
||||
import { ReactComponentProps } from '../../types/Page';
|
||||
declare const _default: <ED2 extends ED, T2 extends keyof ED2, T3 extends string | number = string | number>(props: ReactComponentProps<ED2, T2, false, {
|
||||
declare const _default: <ED2 extends ED, T2 extends keyof ED2, T3 extends keyof ED = keyof ED>(props: ReactComponentProps<ED2, T2, false, {
|
||||
helps: Record<string, string>;
|
||||
entity: T2;
|
||||
attributes: OakAbsAttrUpsertDef<ED2, T2, T3>[];
|
||||
data: ED2[T2]['Schema'];
|
||||
layout: 'horizontal' | 'vertical';
|
||||
mode: 'default' | 'card';
|
||||
data: ED2[T2]["Schema"];
|
||||
layout: "horizontal" | "vertical";
|
||||
mode: "default" | "card";
|
||||
}>) => React.ReactElement;
|
||||
export default _default;
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ export declare abstract class BackendRuntimeContext<ED extends EntityDict & Base
|
|||
eventOperationMap: Record<string, string[]>;
|
||||
getNavigatorState(): {
|
||||
pathname: string;
|
||||
oakFrom?: string | undefined;
|
||||
oakFrom?: string;
|
||||
} | undefined;
|
||||
getSubscriberId(): string | undefined;
|
||||
getBriefEnvironment(): BriefEnv | undefined;
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ export declare class DebugStore<ED extends EntityDict & BaseEntityDict, Cxt exte
|
|||
constructor(storageSchema: StorageSchema<ED>, contextBuilder: (store: DebugStore<ED, Cxt>) => Cxt, authDeduceRelationMap: AuthDeduceRelationMap<ED>, selectFreeEntities?: (keyof ED)[], updateFreeDict?: {
|
||||
[A in keyof ED]?: string[];
|
||||
});
|
||||
checkRelationAsync<T extends keyof ED, Cxt extends AsyncContext<ED>>(entity: T, operation: Omit<ED[T]["Operation"] | ED[T]["Selection"], "id">, context: Cxt): Promise<void>;
|
||||
exec(script: string, txnId?: string): Promise<void>;
|
||||
aggregate<T extends keyof ED, OP extends SelectOption>(entity: T, aggregation: ED[T]["Aggregation"], context: Cxt, option: OP): Promise<AggregationResult<ED[T]["Schema"]>>;
|
||||
begin(option?: TxnOption): Promise<string>;
|
||||
|
|
|
|||
|
|
@ -18,10 +18,9 @@ export class DebugStore extends TreeStore {
|
|||
this.executor = new TriggerExecutor(() => contextBuilder(this));
|
||||
this.relationAuth = new RelationAuth(storageSchema, authDeduceRelationMap, selectFreeEntities, updateFreeDict);
|
||||
}
|
||||
/*
|
||||
checkRelationAsync<T extends keyof ED, Cxt extends AsyncContext<ED>>(entity: T, operation: Omit<ED[T]["Operation"] | ED[T]["Selection"], "id">, context: Cxt): Promise<void> {
|
||||
checkRelationAsync(entity, operation, context) {
|
||||
return this.relationAuth.checkRelationAsync(entity, operation, context);
|
||||
} */
|
||||
}
|
||||
async exec(script, txnId) {
|
||||
throw new Error('debugStore dont support exec script directly');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ export declare class Cache<ED extends EntityDict & BaseEntityDict> extends Featu
|
|||
private cacheStore;
|
||||
private syncEventsCallbacks;
|
||||
private contextBuilder;
|
||||
private refreshing;
|
||||
private executing;
|
||||
private savedEntities;
|
||||
private keepFreshPeriod;
|
||||
private localStorage;
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ export class Cache extends Feature {
|
|||
cacheStore;
|
||||
syncEventsCallbacks;
|
||||
contextBuilder;
|
||||
refreshing = 0;
|
||||
executing = 0;
|
||||
savedEntities;
|
||||
keepFreshPeriod;
|
||||
localStorage;
|
||||
|
|
@ -92,13 +92,13 @@ export class Cache extends Feature {
|
|||
} */
|
||||
async exec(name, params, callback, dontPublish, ignoreContext) {
|
||||
try {
|
||||
this.refreshing++;
|
||||
this.executing++;
|
||||
const { result, opRecords, message } = await this.connector.callAspect(name, params, ignoreContext ? undefined : this.context || this.contextBuilder());
|
||||
callback && callback(result, opRecords);
|
||||
if (opRecords?.length) {
|
||||
this.syncInner(opRecords);
|
||||
}
|
||||
this.refreshing--;
|
||||
this.executing--;
|
||||
if (opRecords && opRecords.length > 0 && !dontPublish) {
|
||||
this.publish();
|
||||
}
|
||||
|
|
@ -109,7 +109,7 @@ export class Cache extends Feature {
|
|||
}
|
||||
catch (e) {
|
||||
// 如果是数据不一致错误,这里可以让用户知道
|
||||
this.refreshing--;
|
||||
this.executing--;
|
||||
if (e instanceof OakException) {
|
||||
const { opRecords } = e;
|
||||
if (opRecords.length) {
|
||||
|
|
@ -440,7 +440,7 @@ export class Cache extends Feature {
|
|||
return;
|
||||
}
|
||||
fetchRows(missedRows) {
|
||||
if (!this.refreshing) {
|
||||
if (!this.executing) {
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
console.warn('缓存被动去获取数据,请查看页面行为并加以优化', missedRows);
|
||||
}
|
||||
|
|
@ -462,7 +462,7 @@ export class Cache extends Feature {
|
|||
const result = this.cacheStore.select(entity, selection, this.context, {
|
||||
dontCollect: true,
|
||||
includedDeleted: true,
|
||||
warnWhenAttributeMiss: !this.refreshing && process.env.NODE_ENV === 'development',
|
||||
warnWhenAttributeMiss: !this.executing && process.env.NODE_ENV === 'development',
|
||||
});
|
||||
rollback && rollback();
|
||||
return result;
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ export default abstract class Console<ED extends EntityDict & BaseEntityDict, OM
|
|||
setContext(entity: keyof ED, entityId: string): void;
|
||||
getContext(): ConsoleContext<ED> | undefined;
|
||||
getAvailMenus(): (OMenu & {
|
||||
sourceEntity?: keyof ED | undefined;
|
||||
sourceEntity?: keyof ED;
|
||||
available: boolean | null;
|
||||
})[];
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
/// <reference types="node" />
|
||||
import { Feature } from '../types/Feature';
|
||||
export declare class Navigator extends Feature {
|
||||
namespace: string;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
/// <reference types="wechat-miniprogram" />
|
||||
import { OakNavigateToParameters } from '../types/Page';
|
||||
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
|
||||
import { EntityDict } from 'oak-domain/lib/types';
|
||||
|
|
|
|||
|
|
@ -75,13 +75,12 @@ export class Navigator extends CommonNavigator {
|
|||
wx.navigateTo({
|
||||
url: url,
|
||||
success: () => {
|
||||
this.leave();
|
||||
this.publish();
|
||||
resolve(undefined);
|
||||
},
|
||||
fail: (err) => reject(err),
|
||||
});
|
||||
this.publish();
|
||||
this.leave();
|
||||
});
|
||||
}
|
||||
// 关闭当前页面,跳转到应用内的某个页面,但不允许跳转到tabBar页面。
|
||||
|
|
@ -94,12 +93,12 @@ export class Navigator extends CommonNavigator {
|
|||
wx.redirectTo({
|
||||
url: url,
|
||||
success: () => {
|
||||
resolve(undefined);
|
||||
this.leave();
|
||||
this.publish();
|
||||
resolve(undefined);
|
||||
},
|
||||
fail: (err) => reject(err),
|
||||
});
|
||||
this.leave();
|
||||
});
|
||||
}
|
||||
//跳转到tabBar页面,并关闭其他所有非tabBar页面,用于跳转到主页。
|
||||
|
|
@ -112,12 +111,12 @@ export class Navigator extends CommonNavigator {
|
|||
wx.switchTab({
|
||||
url: url,
|
||||
success: () => {
|
||||
resolve(undefined);
|
||||
this.leave();
|
||||
this.publish();
|
||||
resolve(undefined);
|
||||
},
|
||||
fail: (err) => reject(err),
|
||||
});
|
||||
this.leave();
|
||||
});
|
||||
}
|
||||
navigateBack(delta) {
|
||||
|
|
@ -128,29 +127,23 @@ export class Navigator extends CommonNavigator {
|
|||
wx.navigateBack({
|
||||
delta: delta || 1,
|
||||
success: () => {
|
||||
resolve(undefined);
|
||||
this.leave();
|
||||
this.publish();
|
||||
resolve(undefined);
|
||||
},
|
||||
fail: (err) => reject(err),
|
||||
});
|
||||
this.leave();
|
||||
});
|
||||
}
|
||||
navigateBackOrRedirectTo(options, state, disableNamespace) {
|
||||
if (!this.enter()) {
|
||||
return;
|
||||
}
|
||||
const pages = getCurrentPages();
|
||||
if (pages.length > 1) {
|
||||
this.leave();
|
||||
return this.navigateBack();
|
||||
}
|
||||
const isTabBar = options?.isTabBar;
|
||||
if (isTabBar) {
|
||||
this.leave();
|
||||
return this.switchTab(options, state, disableNamespace);
|
||||
}
|
||||
this.leave();
|
||||
return this.redirectTo(options, state, disableNamespace);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,8 +56,8 @@ export class Navigator extends CommonNavigator {
|
|||
const { url, props } = this.getUrlAndProps(options, state, disableNamespace);
|
||||
const replaceAction = StackActions.replace(url, props);
|
||||
this.history.dispatch(replaceAction);
|
||||
this.publish();
|
||||
this.leave();
|
||||
this.publish();
|
||||
}
|
||||
async switchTab(options, state, disableNamespace) {
|
||||
if (!this.enter()) {
|
||||
|
|
@ -66,8 +66,8 @@ export class Navigator extends CommonNavigator {
|
|||
const { url, props } = this.getUrlAndProps(options, state, disableNamespace);
|
||||
const jumpToAction = TabActions.jumpTo(url, props);
|
||||
this.history.dispatch(jumpToAction);
|
||||
this.publish();
|
||||
this.leave();
|
||||
this.publish();
|
||||
}
|
||||
async navigateBack(delta) {
|
||||
if (!this.enter()) {
|
||||
|
|
@ -77,10 +77,13 @@ export class Navigator extends CommonNavigator {
|
|||
if (canGoBack) {
|
||||
const popAction = StackActions.pop(delta || 1);
|
||||
this.history.dispatch(popAction);
|
||||
this.leave();
|
||||
this.publish();
|
||||
}
|
||||
else {
|
||||
this.leave();
|
||||
}
|
||||
}
|
||||
navigateBackOrRedirectTo(options, state, disableNamespace) {
|
||||
if (!this.enter()) {
|
||||
return;
|
||||
|
|
@ -88,13 +91,13 @@ export class Navigator extends CommonNavigator {
|
|||
const canGoBack = this.history.canGoBack();
|
||||
if (canGoBack) {
|
||||
this.navigateBack();
|
||||
this.publish();
|
||||
this.leave();
|
||||
this.publish();
|
||||
return;
|
||||
}
|
||||
// 回最顶层
|
||||
this.history.dispatch(StackActions.popToTop());
|
||||
this.publish();
|
||||
this.leave();
|
||||
this.publish();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,10 +15,10 @@ export declare class Navigator extends CommonNavigator {
|
|||
namespace: string;
|
||||
url: string;
|
||||
state: unknown;
|
||||
key: string;
|
||||
pathname: string;
|
||||
search: string;
|
||||
hash: string;
|
||||
key: import("history").Key;
|
||||
pathname: import("history").Pathname;
|
||||
search: import("history").Search;
|
||||
hash: import("history").Hash;
|
||||
};
|
||||
getState(): {
|
||||
pathname: string;
|
||||
|
|
|
|||
|
|
@ -45,8 +45,8 @@ export class Navigator extends CommonNavigator {
|
|||
}
|
||||
const { url, props } = this.getUrlAndProps(options, state, disableNamespace);
|
||||
this.history.push(url, props);
|
||||
this.publish();
|
||||
this.leave();
|
||||
this.publish();
|
||||
}
|
||||
async redirectTo(options, state, disableNamespace) {
|
||||
if (!this.enter()) {
|
||||
|
|
@ -54,8 +54,8 @@ export class Navigator extends CommonNavigator {
|
|||
}
|
||||
const { url, props } = this.getUrlAndProps(options, state, disableNamespace);
|
||||
this.history.replace(url, props);
|
||||
this.publish();
|
||||
this.leave();
|
||||
this.publish();
|
||||
}
|
||||
async switchTab(options, state, disableNamespace) {
|
||||
console.error('浏览器无switchTab');
|
||||
|
|
@ -68,8 +68,8 @@ export class Navigator extends CommonNavigator {
|
|||
return;
|
||||
}
|
||||
this.history.go(delta ? 0 - delta : -1);
|
||||
this.publish();
|
||||
this.leave();
|
||||
this.publish();
|
||||
}
|
||||
navigateBackOrRedirectTo(options, state, disableNamespace) {
|
||||
console.error('浏览器暂无法获得history堆栈');
|
||||
|
|
|
|||
|
|
@ -119,20 +119,20 @@ declare class ListNode<ED extends EntityDict & BaseEntityDict, T extends keyof E
|
|||
removeChild(path: string): void;
|
||||
getChild(path: string): SingleNode<ED, T>;
|
||||
getNamedFilters(): (NamedFilterItem<ED, T> & {
|
||||
applied?: boolean | undefined;
|
||||
applied?: boolean;
|
||||
})[];
|
||||
getNamedFilterByName(name: string): (NamedFilterItem<ED, T> & {
|
||||
applied?: boolean | undefined;
|
||||
applied?: boolean;
|
||||
}) | undefined;
|
||||
setNamedFilters(filters: NamedFilterItem<ED, T>[], refresh?: boolean): void;
|
||||
addNamedFilter(filter: NamedFilterItem<ED, T>, refresh?: boolean): void;
|
||||
removeNamedFilter(filter: NamedFilterItem<ED, T>, refresh?: boolean): void;
|
||||
removeNamedFilterByName(name: string, refresh?: boolean): void;
|
||||
getNamedSorters(): (NamedSorterItem<ED, T> & {
|
||||
applied?: boolean | undefined;
|
||||
applied?: boolean;
|
||||
})[];
|
||||
getNamedSorterByName(name: string): (NamedSorterItem<ED, T> & {
|
||||
applied?: boolean | undefined;
|
||||
applied?: boolean;
|
||||
}) | undefined;
|
||||
setNamedSorters(sorters: NamedSorterItem<ED, T>[], refresh?: boolean): void;
|
||||
addNamedSorter(sorter: NamedSorterItem<ED, T>, refresh?: boolean): void;
|
||||
|
|
@ -170,7 +170,7 @@ declare class ListNode<ED extends EntityDict & BaseEntityDict, T extends keyof E
|
|||
}> | undefined;
|
||||
getProjection(): ED[T]["Projection"] | undefined;
|
||||
private constructFilters;
|
||||
constructSelection(withParent?: true, ignoreNewParent?: boolean, ignoreUnapplied?: true): {
|
||||
constructSelection(withParent?: true, ignoreNewParent?: boolean, ignoreUnapplied?: true, onlyHot?: true): {
|
||||
data: ED[T]["Projection"] | undefined;
|
||||
filter: ED[T]["Filter"] | undefined;
|
||||
sorter: ED[T]["Sorter"];
|
||||
|
|
@ -233,7 +233,7 @@ declare class SingleNode<ED extends EntityDict & BaseEntityDict, T extends keyof
|
|||
saveRefreshResult(data: Record<string, any>): void;
|
||||
refresh(): Promise<void>;
|
||||
clean(lsn?: number, dontPublish?: true): void;
|
||||
private getFilter;
|
||||
getFilter(ignoreNew?: true, onlyHot?: true): ED[T]['Filter'] | undefined;
|
||||
getIntrinsticFilters(): ED[T]["Filter"] | undefined;
|
||||
/**
|
||||
* getParentFilter不能假设一定已经有数据,只能根据当前filter的条件去构造
|
||||
|
|
@ -266,7 +266,6 @@ declare class VirtualNode<ED extends EntityDict & BaseEntityDict> extends Node<E
|
|||
entity: keyof ED;
|
||||
operation: ED[keyof ED]['Operation'];
|
||||
}> | undefined;
|
||||
setExecuting(executing: boolean): void;
|
||||
clean(lsn?: number, dontPublish?: true): void;
|
||||
checkIfClean(node: Node<ED>): boolean;
|
||||
}
|
||||
|
|
@ -328,20 +327,20 @@ export declare class RunningTree<ED extends EntityDict & BaseEntityDict> extends
|
|||
setPageSize<T extends keyof ED>(path: string, pageSize: number): void;
|
||||
setCurrentPage<T extends keyof ED>(path: string, currentPage: number): void;
|
||||
getNamedFilters<T extends keyof ED>(path: string): (NamedFilterItem<ED, keyof ED> & {
|
||||
applied?: boolean | undefined;
|
||||
applied?: boolean;
|
||||
})[];
|
||||
getNamedFilterByName<T extends keyof ED>(path: string, name: string): (NamedFilterItem<ED, keyof ED> & {
|
||||
applied?: boolean | undefined;
|
||||
applied?: boolean;
|
||||
}) | undefined;
|
||||
setNamedFilters<T extends keyof ED>(path: string, filters: NamedFilterItem<ED, T>[], refresh?: boolean): void;
|
||||
addNamedFilter<T extends keyof ED>(path: string, filter: NamedFilterItem<ED, T>, refresh?: boolean): void;
|
||||
removeNamedFilter<T extends keyof ED>(path: string, filter: NamedFilterItem<ED, T>, refresh?: boolean): void;
|
||||
removeNamedFilterByName<T extends keyof ED>(path: string, name: string, refresh?: boolean): void;
|
||||
getNamedSorters<T extends keyof ED>(path: string): (NamedSorterItem<ED, keyof ED> & {
|
||||
applied?: boolean | undefined;
|
||||
applied?: boolean;
|
||||
})[];
|
||||
getNamedSorterByName<T extends keyof ED>(path: string, name: string): (NamedSorterItem<ED, keyof ED> & {
|
||||
applied?: boolean | undefined;
|
||||
applied?: boolean;
|
||||
}) | undefined;
|
||||
setNamedSorters<T extends keyof ED>(path: string, sorters: NamedSorterItem<ED, T>[], refresh?: boolean): void;
|
||||
addNamedSorter<T extends keyof ED>(path: string, sorter: NamedSorterItem<ED, T>, refresh?: boolean): void;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { createOperationsFromModies } from 'oak-domain/lib/store/modi';
|
|||
import { judgeRelation } from "oak-domain/lib/store/relation";
|
||||
import { CreateAtAttribute, UpdateAtAttribute, DeleteAtAttribute } from "oak-domain/lib/types";
|
||||
import { Feature } from '../types/Feature';
|
||||
import { generateNewId } from 'oak-domain/lib/utils/uuid';
|
||||
import { generateNewId, generateNewIdAsync } from 'oak-domain/lib/utils/uuid';
|
||||
export const MODI_NEXT_PATH_SUFFIX = ':next';
|
||||
const START_LSN = 100;
|
||||
function mergeOperation(schema, entity, oper1, oper2) {
|
||||
|
|
@ -459,7 +459,8 @@ class ListNode extends EntityNode {
|
|||
case 'c': {
|
||||
const { e, d } = record;
|
||||
if (e === this.entity) {
|
||||
const { filter } = this.constructSelection(true, true, true);
|
||||
const filters = this.constructFilters(true, true, true);
|
||||
const filter = filters && combineFilters(e, this.schema, filters);
|
||||
if (d instanceof Array) {
|
||||
d.forEach((dd) => tryAddRowToList(dd.id, filter));
|
||||
}
|
||||
|
|
@ -514,7 +515,8 @@ class ListNode extends EntityNode {
|
|||
const { d } = record;
|
||||
for (const entity in d) {
|
||||
if (entity === this.entity) {
|
||||
const { filter } = this.constructSelection(true, true, true);
|
||||
const filters = this.constructFilters(true, true, true);
|
||||
const filter = filters && combineFilters(entity, this.schema, filters);
|
||||
for (const id in d[entity]) {
|
||||
tryAddRowToList(id, filter);
|
||||
}
|
||||
|
|
@ -535,14 +537,14 @@ class ListNode extends EntityNode {
|
|||
/** 检查原本就在的,现在还在不在,
|
||||
* 以及原本不在的,现在是不是满足条件了
|
||||
* (后一种情况也可能原本就满足但不在当前的ids中,这时是判断不出来的,total+1可能不对,但是应该是较少的case)*/
|
||||
const filter = this.constructFilters(true, true, true);
|
||||
const filters = this.constructFilters(true, true, true);
|
||||
if (intersected.length) {
|
||||
const rows = this.cache.get(this.entity, {
|
||||
data: {
|
||||
id: 1,
|
||||
},
|
||||
filter: combineFilters(this.entity, this.schema, [
|
||||
...(filter || []),
|
||||
...(filters || []),
|
||||
{
|
||||
id: {
|
||||
$in: intersected,
|
||||
|
|
@ -560,12 +562,8 @@ class ListNode extends EntityNode {
|
|||
});
|
||||
}
|
||||
if (diffed.length) {
|
||||
diffed.forEach((ele) => {
|
||||
this.sr[ele] = {};
|
||||
if (this.pagination.total) {
|
||||
this.pagination.total++;
|
||||
}
|
||||
});
|
||||
const filter = filters && combineFilters(e, this.schema, filters);
|
||||
diffed.forEach((ele) => tryAddRowToList(ele, filter));
|
||||
}
|
||||
}
|
||||
// hasUpdated = true;
|
||||
|
|
@ -784,7 +782,7 @@ class ListNode extends EntityNode {
|
|||
const ids = Object.keys(this.sr);
|
||||
const operations = this.ulManager.makeOperations();
|
||||
const createIds = operations.filter(o => o.action === 'create').map(o => o.data.id);
|
||||
const { data, sorter, filter } = this.constructSelection(true, false, true);
|
||||
const { data, sorter, filter } = this.constructSelection(true, false, true, true);
|
||||
const ids2 = ids.concat(createIds);
|
||||
/**
|
||||
* 在非modi状态下,当前的逻辑是用当前filter加以过滤,不然就处理不了在列表中操作改变了filter中外联的条件(例如为order创建了一个ship,但查询条件是没有ship)时,列表不发生变化
|
||||
|
|
@ -963,9 +961,10 @@ class ListNode extends EntityNode {
|
|||
} */
|
||||
return projection;
|
||||
}
|
||||
constructFilters(withParent, ignoreNewParent, ignoreUnapplied) {
|
||||
constructFilters(withParent, ignoreNewParent, ignoreUnapplied, onlyHot) {
|
||||
const { filters: ownFilters } = this;
|
||||
const filters = ownFilters.filter(ele => (!ignoreUnapplied || ele.applied === true || ele.applied === undefined) // 如果是undefined,说明不可以移除(构造时就存在),也得返回
|
||||
&& (!onlyHot || ele.hot) // 如果是getFreshValue,则只取hot的敏感过滤条件
|
||||
).map((ele) => {
|
||||
const { filter } = ele;
|
||||
if (typeof filter === 'function') {
|
||||
|
|
@ -989,7 +988,7 @@ class ListNode extends EntityNode {
|
|||
// 返回的filter在上层做check的时候可能被改造掉
|
||||
return cloneDeep(filters);
|
||||
}
|
||||
constructSelection(withParent, ignoreNewParent, ignoreUnapplied) {
|
||||
constructSelection(withParent, ignoreNewParent, ignoreUnapplied, onlyHot) {
|
||||
const { sorters, getTotal } = this;
|
||||
const data = this.getProjection();
|
||||
// assert(data, '取数据时找不到projection信息');
|
||||
|
|
@ -1007,7 +1006,7 @@ class ListNode extends EntityNode {
|
|||
$direction: 'desc'
|
||||
}
|
||||
];
|
||||
const filters = this.constructFilters(withParent, ignoreNewParent, ignoreUnapplied);
|
||||
const filters = this.constructFilters(withParent, ignoreNewParent, ignoreUnapplied, onlyHot);
|
||||
const filters2 = filters?.filter((ele) => !!ele);
|
||||
const filter = filters2 ? combineFilters(this.entity, this.schema, filters2) : undefined;
|
||||
const { currentPage, pageSize } = this.pagination;
|
||||
|
|
@ -1253,7 +1252,7 @@ class SingleNode extends EntityNode {
|
|||
setId(id) {
|
||||
if (id !== this.id) {
|
||||
const operations = this.ulManager.makeOperations();
|
||||
assert(operations.length <= 1);
|
||||
assert(operations.length <= 1, 'singleNode在setId时出现数据不一致');
|
||||
const [operation] = operations;
|
||||
if (operation?.action === 'create') {
|
||||
if (operation.data.id === id) {
|
||||
|
|
@ -1303,8 +1302,8 @@ class SingleNode extends EntityNode {
|
|||
getFreshValue() {
|
||||
const inModiNextBranch = this.isInModiNextBranch();
|
||||
const projection = this.getProjection(false);
|
||||
const id = this.getId();
|
||||
if (projection && id) {
|
||||
const filter = this.getFilter(undefined, true);
|
||||
if (projection && filter) {
|
||||
/**
|
||||
* 这里在非modi状态下,原来的代码是不会去刷新缺失的数据,原因不明,可能是认为页面应当自己负责数据的获取
|
||||
* 在modi状态下,有些外键指向的数据无法预先获取,因此需要加上这个逻辑
|
||||
|
|
@ -1312,11 +1311,10 @@ class SingleNode extends EntityNode {
|
|||
* 先放回来,不知道有什么问题
|
||||
* by Xc 20240229
|
||||
*/
|
||||
const id = this.getId();
|
||||
const result = this.cache.get(this.entity, {
|
||||
data: projection,
|
||||
filter: {
|
||||
id,
|
||||
},
|
||||
filter,
|
||||
}, inModiNextBranch ? undefined : {
|
||||
[id]: this.sr,
|
||||
});
|
||||
|
|
@ -1415,7 +1413,7 @@ class SingleNode extends EntityNode {
|
|||
}
|
||||
setDirty() {
|
||||
const id = this.getId();
|
||||
assert(id);
|
||||
assert(id, "不能对没有id的singleNode设置dirty");
|
||||
this.ulManager.push(this.ulManager.maxLsn, {
|
||||
action: 'update',
|
||||
data: {},
|
||||
|
|
@ -1443,7 +1441,7 @@ class SingleNode extends EntityNode {
|
|||
const childOperations = child.composeOperations(paths?.length ? paths : undefined);
|
||||
if (childOperations) {
|
||||
if (child instanceof SingleNode) {
|
||||
assert(childOperations.length === 1);
|
||||
assert(childOperations.length === 1, 'singleNode在composeOperations时出现数据不一致');
|
||||
this.ulManager.push(lsnMax + 100, {
|
||||
action: 'update',
|
||||
data: {
|
||||
|
|
@ -1455,7 +1453,7 @@ class SingleNode extends EntityNode {
|
|||
});
|
||||
}
|
||||
else {
|
||||
assert(child instanceof ListNode);
|
||||
assert(child instanceof ListNode, 'child必须是ListNode');
|
||||
this.ulManager.push(lsnMax + 100, {
|
||||
action: 'update',
|
||||
data: {
|
||||
|
|
@ -1474,20 +1472,13 @@ class SingleNode extends EntityNode {
|
|||
const [operation] = operations;
|
||||
if (operation) {
|
||||
const { filter, ...rest } = operation;
|
||||
const intrinsticFilter = this.getIntrinsticFilters();
|
||||
const realFilter = this.getFilter(true);
|
||||
return [
|
||||
{
|
||||
entity: this.entity,
|
||||
operation: {
|
||||
...rest,
|
||||
filter: intrinsticFilter ? combineFilters(this.entity, this.schema, [
|
||||
{
|
||||
id: this.getId(),
|
||||
},
|
||||
intrinsticFilter
|
||||
]) : {
|
||||
id: this.getId(),
|
||||
}
|
||||
filter: realFilter,
|
||||
},
|
||||
}
|
||||
];
|
||||
|
|
@ -1552,8 +1543,8 @@ class SingleNode extends EntityNode {
|
|||
const rel = this.judgeRelation(k2);
|
||||
if (rel === 2) {
|
||||
if (value?.entityId) {
|
||||
assert(child instanceof SingleNode);
|
||||
assert(value.entity === child.getEntity());
|
||||
assert(child instanceof SingleNode, 'child必须是singleNode');
|
||||
assert(value.entity === child.getEntity(), 'singleNode的entity必须一致');
|
||||
child.saveRefreshResult({
|
||||
[value.entityId]: this.sr[k2] || {},
|
||||
});
|
||||
|
|
@ -1599,7 +1590,7 @@ class SingleNode extends EntityNode {
|
|||
async refresh() {
|
||||
// SingleNode如果是非根结点,其id应该在第一次refresh的时候来确定
|
||||
const projection = this.getProjection(true);
|
||||
const filter = this.getFilter();
|
||||
const filter = this.getFilter(true);
|
||||
if (projection && filter) {
|
||||
const lr = this.startLoading();
|
||||
if (lr instanceof Promise) {
|
||||
|
|
@ -1643,12 +1634,16 @@ class SingleNode extends EntityNode {
|
|||
}
|
||||
}
|
||||
}
|
||||
getFilter() {
|
||||
getFilter(ignoreNew, onlyHot) {
|
||||
// 如果是新建,等于没有filter
|
||||
const [operation] = this.ulManager.makeOperations();
|
||||
if (operation?.action === 'create') {
|
||||
if (ignoreNew) {
|
||||
return;
|
||||
}
|
||||
const { id } = operation.data;
|
||||
return { id };
|
||||
}
|
||||
// singleNode增加一些限定的filter可以优化后台权限的判断范围和一些trigger的条件
|
||||
// 如果没有this.id则不返回,避免一些奇怪的边界(比如execute以后refresh)
|
||||
if (this.id) {
|
||||
|
|
@ -1656,7 +1651,7 @@ class SingleNode extends EntityNode {
|
|||
id: this.id,
|
||||
};
|
||||
if (this.filters) {
|
||||
filter = combineFilters(this.entity, this.schema, this.filters.map(ele => typeof ele.filter === 'function' ? ele.filter() : ele.filter).concat(filter));
|
||||
filter = combineFilters(this.entity, this.schema, this.filters.filter(ele => !onlyHot || ele.hot).map(ele => typeof ele.filter === 'function' ? ele.filter() : ele.filter).concat(filter));
|
||||
}
|
||||
if (this.parent && this.parent instanceof ListNode && this.parent.getEntity() === this.entity) {
|
||||
const { filter: parentFilter } = this.parent.constructSelection(true, true, true);
|
||||
|
|
@ -1845,10 +1840,6 @@ class VirtualNode extends Node {
|
|||
}
|
||||
return operationss;
|
||||
}
|
||||
setExecuting(executing) {
|
||||
this.executing = executing;
|
||||
this.publish();
|
||||
}
|
||||
clean(lsn, dontPublish) {
|
||||
for (const ele in this.children) {
|
||||
this.children[ele].clean(lsn, true);
|
||||
|
|
@ -2016,6 +2007,7 @@ export class RunningTree extends Feature {
|
|||
assert(!parentNode || parentNode instanceof VirtualNode);
|
||||
node = new VirtualNode(fullPath, path, parentNode, stale);
|
||||
}
|
||||
// 任何临时的修改都需要回滚,上面缓存了一些update操作
|
||||
rollback();
|
||||
if (!parentNode) {
|
||||
assert(!parent && !this.root[path]);
|
||||
|
|
@ -2422,7 +2414,7 @@ export class RunningTree extends Feature {
|
|||
const node = path && this.findNode(path);
|
||||
// assert(node.isDirty());
|
||||
node && node.setExecuting(true);
|
||||
let pollute = false;
|
||||
// let pollute = false;
|
||||
try {
|
||||
let operations = path && this.getOperations(path) || [];
|
||||
if (opers) {
|
||||
|
|
@ -2441,15 +2433,30 @@ export class RunningTree extends Feature {
|
|||
else if (node) {
|
||||
// 老的写法,直接对一个非脏的结点execute某个action,也可以支持
|
||||
assert(node instanceof SingleNode);
|
||||
node.update(this.logSerailNumber, {}, action);
|
||||
pollute = true;
|
||||
operations = node.composeOperations() || [];
|
||||
assert(operations.length === 1);
|
||||
const [operation1] = operations;
|
||||
if (action !== operation1.operation.action) {
|
||||
assert(operation1.operation.action === 'update'); // 如果execute时传action,前面update动作应该只可能是update
|
||||
operation1.operation.action = action;
|
||||
// node.update(this.logSerailNumber, {}, action);
|
||||
// pollute = true;
|
||||
// operations = node.composeOperations() || [];
|
||||
// assert(operations.length === 1);
|
||||
// const [operation1] = operations;
|
||||
// if (action !== operation1.operation.action) {
|
||||
// assert(operation1.operation.action === 'update'); // 如果execute时传action,前面update动作应该只可能是update
|
||||
// operation1.operation.action = action;
|
||||
// }
|
||||
/**
|
||||
* 上述写法会触发publish行为,如:一个close动作会导致页面像下面这样渲染:
|
||||
* opened --> closed(上面的node.update) --> opened(执行成功回来setExecuting时) --> closed(执行成功回来再sync cache后)
|
||||
*/
|
||||
operations.push({
|
||||
entity: node.getEntity(),
|
||||
operation: {
|
||||
id: await generateNewIdAsync(),
|
||||
action,
|
||||
data: {
|
||||
$$updateAt$$: Date.now(),
|
||||
},
|
||||
filter: node.getFilter(true),
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
if (operations.length > 0) {
|
||||
|
|
@ -2479,9 +2486,9 @@ export class RunningTree extends Feature {
|
|||
}
|
||||
catch (err) {
|
||||
node && node.setExecuting(false);
|
||||
if (pollute) {
|
||||
/* if (pollute) {
|
||||
path && this.clean(path);
|
||||
}
|
||||
} */
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -94,11 +94,11 @@ export class SubScriber extends Feature {
|
|||
}
|
||||
});
|
||||
socket.on('data', (opRecords, event) => {
|
||||
this.cache.sync(opRecords);
|
||||
const registered = this.eventMap[event];
|
||||
if (registered) {
|
||||
registered.callbacks.forEach((ele) => ele(event, opRecords));
|
||||
}
|
||||
this.cache.sync(opRecords);
|
||||
});
|
||||
socket.on('error', (errString) => {
|
||||
console.error(errString);
|
||||
|
|
|
|||
|
|
@ -21,10 +21,11 @@ export function onPathSet(option, isPage) {
|
|||
const entity2 = entity instanceof Function ? entity.call(this) : entity;
|
||||
const projection2 = typeof projection === 'function' ? () => projection.call(this) : projection;
|
||||
let filters2 = filters?.map((ele) => {
|
||||
const { filter, '#name': name } = ele;
|
||||
const { filter, '#name': name, hot } = ele;
|
||||
return {
|
||||
filter: typeof filter === 'function' ? () => filter.call(this) : filter,
|
||||
['#name']: name,
|
||||
hot,
|
||||
};
|
||||
});
|
||||
if (oakFilters) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
/// <reference types="wechat-miniprogram" />
|
||||
import { Aspect, EntityDict } from 'oak-domain/lib/types';
|
||||
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
|
||||
import { BasicFeatures } from './features';
|
||||
|
|
@ -6,4 +5,4 @@ import { Feature } from './types/Feature';
|
|||
import { DataOption, OakComponentOption } from './types/Page';
|
||||
import { AsyncContext } from 'oak-domain/lib/store/AsyncRowStore';
|
||||
import { SyncContext } from 'oak-domain/lib/store/SyncRowStore';
|
||||
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, AsyncContext<ED>>>, FD extends Record<string, Feature>, FormedData extends Record<string, any>, TData extends DataOption = {}, TProperty extends DataOption = {}, TMethod extends Record<string, Function> = {}>(option: OakComponentOption<IsList, ED, T, Cxt, FrontCxt, AD, FD, FormedData, TData, TProperty, TMethod>, features: BasicFeatures<ED> & FD): string;
|
||||
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 DataOption = {}, TProperty extends DataOption = {}, TMethod extends Record<string, Function> = {}>(option: OakComponentOption<IsList, ED, T, Cxt, FrontCxt, AD, FD, FormedData, TData, TProperty, TMethod>, features: BasicFeatures<ED> & FD): string;
|
||||
|
|
|
|||
|
|
@ -540,6 +540,13 @@ function translatePropertiesToPropertyDefinitions(properties) {
|
|||
const definitions = {};
|
||||
if (properties) {
|
||||
Object.keys(properties).forEach((prop) => {
|
||||
if (properties[prop] === null) {
|
||||
definitions[prop] = {
|
||||
type: null,
|
||||
value: null,
|
||||
};
|
||||
return;
|
||||
}
|
||||
switch (typeof properties[prop]) {
|
||||
case 'string': {
|
||||
if (properties[prop]) {
|
||||
|
|
@ -684,6 +691,10 @@ export function createComponent(option, features) {
|
|||
hide() {
|
||||
const { hide } = this.oakOption.lifetimes || {};
|
||||
hide && hide.call(this);
|
||||
/**
|
||||
* 不能unsubscribeAll,小程序的页面不会销毁,如果一个页面需要token才能取数据,这时候去了登录页再回来就得依靠feature上的subscribe来refresh
|
||||
* by Xc 20250913
|
||||
*/
|
||||
// this.unsubscribeAll();
|
||||
},
|
||||
resize(resizeOption) {
|
||||
|
|
|
|||
|
|
@ -6,4 +6,4 @@ 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, AsyncContext<ED>>>, 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> & FD): React.ForwardRefExoticComponent<React.RefAttributes<unknown>>;
|
||||
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> & FD): React.ForwardRefExoticComponent<React.RefAttributes<unknown>>;
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import { MessageProps } from './types/Message';
|
|||
import { NotificationProps } from './types/Notification';
|
||||
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, AsyncContext<ED>>>, 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> & FD): {
|
||||
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> & FD): {
|
||||
new (props: ComponentProps<ED, T, TProperty>): {
|
||||
features: BasicFeatures<ED> & FD;
|
||||
oakOption: OakComponentOption<IsList, ED, T, Cxt, FrontCxt, AD, FD, FormedData, TData, TProperty, TMethod>;
|
||||
|
|
@ -25,84 +25,84 @@ export declare function createComponent<IsList extends boolean, ED extends Entit
|
|||
componentDidUpdate(prevProps: Record<string, any>, prevState: Record<string, any>): Promise<void>;
|
||||
render(): React.ReactNode;
|
||||
oakFullpath: string;
|
||||
featuresSubscribed: {
|
||||
featuresSubscribed: Array<{
|
||||
name: string;
|
||||
callback: (args?: any) => void;
|
||||
unsubHandler?: (() => void) | undefined;
|
||||
}[];
|
||||
unsubHandler?: () => void;
|
||||
}>;
|
||||
addFeatureSub(name: string, callback: (args?: any) => void): void;
|
||||
removeFeatureSub(name: string, callback: (args?: any) => void): void;
|
||||
unsubscribeAll(): void;
|
||||
subscribeAll(): void;
|
||||
save(key: string, item: any): Promise<void>;
|
||||
load(key: string): Promise<any>;
|
||||
clear(key?: string | undefined): Promise<void>;
|
||||
clear(key?: string): Promise<void>;
|
||||
setNotification(data: NotificationProps): void;
|
||||
consumeNotification(): NotificationProps | undefined;
|
||||
setMessage(data: MessageProps): Promise<void>;
|
||||
consumeMessage(): MessageProps | undefined;
|
||||
reRender(extra?: Record<string, any> | undefined): void;
|
||||
reRender(extra?: Record<string, any>): void;
|
||||
navigateTo<T2 extends keyof ED>(options: {
|
||||
url: string;
|
||||
} & OakNavigateToParameters<ED, T2>, state?: Record<string, any> | undefined, disableNamespace?: boolean | undefined): Promise<void>;
|
||||
navigateBack(delta?: number | undefined): Promise<void>;
|
||||
redirectTo<T2_1 extends keyof ED>(options: {
|
||||
} & OakNavigateToParameters<ED, T2>, state?: Record<string, any>, disableNamespace?: boolean): Promise<void>;
|
||||
navigateBack(delta?: number): Promise<void>;
|
||||
redirectTo<T2 extends keyof ED>(options: {
|
||||
url: string;
|
||||
} & OakNavigateToParameters<ED, T2_1>, state?: Record<string, any> | undefined, disableNamespace?: boolean | undefined): Promise<void>;
|
||||
} & OakNavigateToParameters<ED, T2>, state?: Record<string, any>, disableNamespace?: boolean): Promise<void>;
|
||||
addItem<T_1 extends keyof ED>(data: Omit<ED[T_1]["CreateSingle"]["data"], "id"> & {
|
||||
id?: string | undefined;
|
||||
}, path?: string | undefined): string;
|
||||
addItems<T_2 extends keyof ED>(data: (Omit<ED[T_2]["CreateSingle"]["data"], "id"> & {
|
||||
id?: string | undefined;
|
||||
})[], path?: string | undefined): string[];
|
||||
removeItem(id: string, path?: string | undefined): void;
|
||||
removeItems(ids: string[], path?: string | undefined): void;
|
||||
updateItem<T_3 extends keyof ED>(data: ED[T_3]["Update"]["data"], id: string, action?: ED[T_3]["Action"] | undefined, path?: string | undefined): void;
|
||||
updateItems<T_4 extends keyof ED>(data: ED[T_4]["Update"]["data"], ids: string[], action?: ED[T_4]["Action"] | undefined, path?: string | undefined): void;
|
||||
recoverItem(id: string, path?: string | undefined): void;
|
||||
recoverItems(ids: string[], path?: string | undefined): void;
|
||||
resetItem(id: string, path?: string | undefined): void;
|
||||
update<T_5 extends keyof ED>(data: ED[T_5]["Update"]["data"], action?: ED[T_5]["Action"] | undefined, path?: string | undefined): void;
|
||||
create<T_6 extends keyof ED>(data: Omit<ED[T_6]["CreateSingle"]["data"], "id">, path?: string | undefined): void;
|
||||
remove(path?: string | undefined): void;
|
||||
isCreation(path?: string | undefined): boolean;
|
||||
clean(lsn?: number | undefined, dontPublish?: true | undefined, path?: string | undefined): void;
|
||||
id?: string;
|
||||
}, path?: string): string;
|
||||
addItems<T_1 extends keyof ED>(data: (Omit<ED[T_1]["CreateSingle"]["data"], "id"> & {
|
||||
id?: string;
|
||||
})[], path?: string): string[];
|
||||
removeItem(id: string, path?: string): void;
|
||||
removeItems(ids: string[], path?: string): void;
|
||||
updateItem<T_1 extends keyof ED>(data: ED[T_1]["Update"]["data"], id: string, action?: ED[T_1]["Action"] | undefined, path?: string): void;
|
||||
updateItems<T_1 extends keyof ED>(data: ED[T_1]["Update"]["data"], ids: string[], action?: ED[T_1]["Action"] | undefined, path?: string): void;
|
||||
recoverItem(id: string, path?: string): void;
|
||||
recoverItems(ids: string[], path?: string): void;
|
||||
resetItem(id: string, path?: string): void;
|
||||
update<T_1 extends keyof ED>(data: ED[T_1]["Update"]["data"], action?: ED[T_1]["Action"] | undefined, path?: string): void;
|
||||
create<T_1 extends keyof ED>(data: Omit<ED[T_1]["CreateSingle"]["data"], "id">, path?: string): void;
|
||||
remove(path?: string): void;
|
||||
isCreation(path?: string): boolean;
|
||||
clean(lsn?: number, dontPublish?: true, path?: string): void;
|
||||
savePoint(): number;
|
||||
t(key: string, params?: object | undefined): string;
|
||||
execute(action?: ED[T]["Action"] | undefined, messageProps?: boolean | MessageProps | undefined, path?: string | undefined, opers?: {
|
||||
t(key: string, params?: object): string;
|
||||
execute(action?: ED[T]["Action"] | undefined, messageProps?: boolean | MessageProps, path?: string, opers?: {
|
||||
entity: T;
|
||||
operation: ED[T]["Operation"];
|
||||
}[] | undefined): Promise<void>;
|
||||
isDirty(path?: string | undefined): boolean;
|
||||
getFreshValue(path?: string | undefined): Partial<import("oak-domain/lib/types").GeneralEntityShape> | Partial<import("oak-domain/lib/types").GeneralEntityShape>[] | undefined;
|
||||
select<T2_2 extends keyof ED>(entity: T2_2, selection: ED[T2_2]["Selection"]): Partial<import("oak-domain/lib/types").GeneralEntityShape>[];
|
||||
checkOperation<T2_3 extends keyof ED>(entity: T2_3, operation: Omit<ED[T2_3]["Operation"], "id">, checkerTypes?: CheckerType[] | undefined, cacheInsensative?: true | undefined): boolean | { [A in ED[T2_3]["Action"]]: boolean | import("oak-domain/lib/types").OakUserException<ED>; }[ED[T2_3]["Action"]];
|
||||
tryExecute(path?: string | undefined, action?: string | undefined): boolean | { [A_1 in ED[keyof ED]["Action"]]: boolean | import("oak-domain/lib/types").OakUserException<ED>; }[ED[keyof ED]["Action"]];
|
||||
getOperations<T_7 extends keyof ED>(path?: string | undefined): {
|
||||
isDirty(path?: string): boolean;
|
||||
getFreshValue(path?: string): Partial<import("oak-domain/lib/types").GeneralEntityShape> | Partial<import("oak-domain/lib/types").GeneralEntityShape>[] | undefined;
|
||||
select<T2 extends keyof ED>(entity: T2, selection: ED[T2]["Selection"]): Partial<import("oak-domain/lib/types").GeneralEntityShape>[];
|
||||
checkOperation<T2 extends keyof ED>(entity: T2, operation: Omit<ED[T2]["Operation"], "id">, checkerTypes?: CheckerType[], cacheInsensative?: true): boolean | { [A in ED[T2]["Action"]]: boolean | import("oak-domain/lib/types").OakUserException<ED>; }[ED[T2]["Action"]];
|
||||
tryExecute(path?: string, action?: string): boolean | { [A in ED[keyof ED]["Action"]]: boolean | import("oak-domain/lib/types").OakUserException<ED>; }[ED[keyof ED]["Action"]];
|
||||
getOperations<T_1 extends keyof ED>(path?: string): {
|
||||
entity: keyof ED;
|
||||
operation: ED[keyof ED]["Operation"];
|
||||
}[] | undefined;
|
||||
refresh(pageNumber?: number | undefined, resetTotal?: boolean | undefined): Promise<void>;
|
||||
refresh(pageNumber?: number, resetTotal?: boolean): Promise<void>;
|
||||
loadMore(): Promise<void>;
|
||||
setId(id: string, path?: string | undefined): void;
|
||||
setId(id: string, path?: string): void;
|
||||
unsetId(): void;
|
||||
getId(path?: string | undefined): string | undefined;
|
||||
setFilters(filters: NamedFilterItem<ED, T>[], path?: string | undefined): void;
|
||||
setNamedFilters(filters: NamedFilterItem<ED, T>[], refresh?: boolean | undefined, path?: string | undefined): void;
|
||||
getFilters(path?: string | undefined): any[] | undefined;
|
||||
getFilterByName(name: string, path?: string | undefined): any;
|
||||
addNamedFilter(namedFilter: NamedFilterItem<ED, T>, refresh?: boolean | undefined, path?: string | undefined): void;
|
||||
removeNamedFilter(namedFilter: NamedFilterItem<ED, T>, refresh?: boolean | undefined, path?: string | undefined): void;
|
||||
removeNamedFilterByName(name: string, refresh?: boolean | undefined, path?: string | undefined): void;
|
||||
setNamedSorters(namedSorters: NamedSorterItem<ED, T>[], refresh?: boolean | undefined, path?: string | undefined): void;
|
||||
getSorters(path?: string | undefined): ED[T]["Sorter"][] | undefined;
|
||||
getSorterByName(name: string, path?: string | undefined): any;
|
||||
addNamedSorter(namedSorter: NamedSorterItem<ED, T>, refresh?: boolean | undefined, path?: string | undefined): void;
|
||||
removeNamedSorter(namedSorter: NamedSorterItem<ED, T>, refresh?: boolean | undefined, path?: string | undefined): void;
|
||||
removeNamedSorterByName(name: string, refresh?: boolean | undefined, path?: string | undefined): void;
|
||||
getPagination(path?: string | undefined): import(".").Pagination | undefined;
|
||||
setPageSize(pageSize: number, path?: string | undefined): void;
|
||||
setCurrentPage(currentPage: number, path?: string | undefined): void;
|
||||
getId(path?: string): string | undefined;
|
||||
setFilters(filters: NamedFilterItem<ED, T>[], path?: string): void;
|
||||
setNamedFilters(filters: NamedFilterItem<ED, T>[], refresh?: boolean, path?: string): void;
|
||||
getFilters(path?: string): any[] | undefined;
|
||||
getFilterByName(name: string, path?: string): any;
|
||||
addNamedFilter(namedFilter: NamedFilterItem<ED, T>, refresh?: boolean, path?: string): void;
|
||||
removeNamedFilter(namedFilter: NamedFilterItem<ED, T>, refresh?: boolean, path?: string): void;
|
||||
removeNamedFilterByName(name: string, refresh?: boolean, path?: string): void;
|
||||
setNamedSorters(namedSorters: NamedSorterItem<ED, T>[], refresh?: boolean, path?: string): void;
|
||||
getSorters(path?: string): ED[T]["Sorter"][] | undefined;
|
||||
getSorterByName(name: string, path?: string): any;
|
||||
addNamedSorter(namedSorter: NamedSorterItem<ED, T>, refresh?: boolean, path?: string): void;
|
||||
removeNamedSorter(namedSorter: NamedSorterItem<ED, T>, refresh?: boolean, path?: string): void;
|
||||
removeNamedSorterByName(name: string, refresh?: boolean, path?: string): void;
|
||||
getPagination(path?: string): import(".").Pagination | undefined;
|
||||
setPageSize(pageSize: number, path?: string): void;
|
||||
setCurrentPage(currentPage: number, path?: string): void;
|
||||
subDataEvents(events: string[], callback: (event: string, opRecords: OpRecord<ED>[]) => void): Promise<() => void>;
|
||||
context: unknown;
|
||||
setState<K extends keyof TData | keyof FormedData | keyof import("./types/Page").OakComponentData<ED, T>>(state: ComponentData<ED, T, FormedData, TData> | ((prevState: Readonly<ComponentData<ED, T, FormedData, TData>>, props: Readonly<ComponentProps<ED, T, TProperty>>) => ComponentData<ED, T, FormedData, TData> | Pick<ComponentData<ED, T, FormedData, TData>, K> | null) | Pick<ComponentData<ED, T, FormedData, TData>, K> | null, callback?: (() => void) | undefined): void;
|
||||
|
|
|
|||
|
|
@ -6,4 +6,4 @@ 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, AsyncContext<ED>>>, 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> & FD): React.ForwardRefExoticComponent<React.RefAttributes<unknown>>;
|
||||
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> & FD): React.ForwardRefExoticComponent<React.RefAttributes<unknown>>;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
/// <reference types="react" />
|
||||
import { Breakpoints } from './context';
|
||||
export interface ResponsiveProviderProps {
|
||||
children?: React.ReactNode;
|
||||
breakpoints?: Breakpoints;
|
||||
}
|
||||
export declare function ResponsiveProvider(props: ResponsiveProviderProps): import("react").FunctionComponentElement<import("react").ProviderProps<{
|
||||
breakpoints?: Breakpoints | undefined;
|
||||
breakpoints?: Breakpoints;
|
||||
}>>;
|
||||
|
|
|
|||
|
|
@ -17,5 +17,5 @@ export declare const keys: Keys;
|
|||
export declare const values: Values;
|
||||
export declare const defaultBreakpoints: Breakpoints;
|
||||
export declare const ResponsiveContext: React.Context<{
|
||||
breakpoints?: Breakpoints | undefined;
|
||||
breakpoints?: Breakpoints;
|
||||
}>;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
/// <reference types="react" />
|
||||
import { BrowserRouterProps } from 'react-router-dom';
|
||||
export interface IBrowserRouterProps extends BrowserRouterProps {
|
||||
namespace: string;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
/// <reference types="react" />
|
||||
import { EntityDict } from 'oak-domain/lib/types/Entity';
|
||||
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
|
||||
import { DataType, DataTypeParams } from 'oak-domain/lib/types/schema/DataTypes';
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
/// <reference types="react" />
|
||||
import { Dayjs } from 'dayjs';
|
||||
import { OakAbsRefAttrPickerDef, ColSpanType, ED } from './AbstractComponent';
|
||||
export type ViewType = 'Input' | 'Select' | 'DatePicker' | 'DatePicker.RangePicker' | 'RefAttr';
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
/// <reference types="react" />
|
||||
export type MapComponent = (props: {
|
||||
id?: string;
|
||||
center?: [number, number];
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { EntityDict } from "oak-domain/lib/types";
|
|||
export type NamedFilterItem<ED extends EntityDict, T extends keyof ED> = {
|
||||
filter: ED[T]['Filter'] | (() => ED[T]['Filter'] | undefined);
|
||||
['#name']?: string;
|
||||
hot?: true;
|
||||
};
|
||||
export type NamedSorterItem<ED extends EntityDict, T extends keyof ED> = {
|
||||
sorter: NonNullable<ED[T]['Sorter']>[number] | (() => ED[T]['Sorter'] | NonNullable<ED[T]['Sorter']>[number] | undefined);
|
||||
|
|
|
|||
|
|
@ -1,14 +1,13 @@
|
|||
export type NotificationProps = {
|
||||
title?: string;
|
||||
content?: string | any;
|
||||
type: 'info' | 'success' | 'warning' | 'error';
|
||||
message: React.ReactNode;
|
||||
description: React.ReactNode;
|
||||
type?: 'info' | 'success' | 'warning' | 'error';
|
||||
actions?: React.ReactNode;
|
||||
icon?: string | boolean;
|
||||
duration?: number;
|
||||
closeIcon?: string | boolean;
|
||||
duration?: number | null;
|
||||
placement?: 'top' | 'topLeft' | 'topRight' | 'bottom' | 'bottomLeft' | 'bottomRight';
|
||||
zIndex?: number;
|
||||
offset?: Array<string | number>;
|
||||
placement?: 'center' | 'top' | 'left' | 'right' | 'bottom' | 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
|
||||
footer: any;
|
||||
closeBtn?: string | boolean | any;
|
||||
onCloseBtnClick?: Function;
|
||||
onDurationEnd?: Function;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
/// <reference types="wechat-miniprogram" />
|
||||
/// <reference types="wechat-miniprogram" />
|
||||
import { Aspect, EntityDict, CheckerType, AggregationResult, OpRecord, OakUserException } from "oak-domain/lib/types";
|
||||
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
|
||||
import { Feature } from './Feature';
|
||||
|
|
@ -82,6 +80,7 @@ interface ComponentOption<IsList extends boolean, ED extends EntityDict & BaseEn
|
|||
filters?: Array<{
|
||||
filter: NonNullable<ED[T]['Filter']> | ((this: ComponentPublicThisType<ED, T, Cxt, FrontCxt, AD, FD, FormedData, IsList, TData, TProperty, TMethod, EMethod>) => ED[T]['Filter'] | undefined);
|
||||
'#name'?: string;
|
||||
hot?: true;
|
||||
}>;
|
||||
/**
|
||||
* 排序器
|
||||
|
|
@ -147,7 +146,7 @@ export type ComponentFullThisType<ED extends EntityDict & BaseEntityDict, T exte
|
|||
triggerEvent: <DetailType = any>(name: string, detail?: DetailType, options?: WechatMiniprogram.Component.TriggerEventOption) => void;
|
||||
oakLifetime: OakLifetime;
|
||||
} & OakCommonComponentMethods<ED, T> & OakListComponentMethods<ED, T> & OakSingleComponentMethods<ED, T>;
|
||||
export type OakComponentOption<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, AsyncContext<ED>>>, FD extends Record<string, Feature>, FormedData extends Record<string, any>, TData extends Record<string, any>, TProperty extends DataOption, TMethod extends Record<string, Function>, EMethod extends Record<string, Function> = {}> = ComponentOption<IsList, ED, T, Cxt, FrontCxt, AD, FD, FormedData, TData, TProperty, TMethod, EMethod> & Partial<{
|
||||
export type OakComponentOption<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>, EMethod extends Record<string, Function> = {}> = ComponentOption<IsList, ED, T, Cxt, FrontCxt, AD, FD, FormedData, TData, TProperty, TMethod, EMethod> & Partial<{
|
||||
/**
|
||||
* 生命周期回调
|
||||
*/
|
||||
|
|
@ -352,7 +351,7 @@ export type OakComponentData<ED extends EntityDict & BaseEntityDict, T extends k
|
|||
type OakListComoponetData<ED extends EntityDict & BaseEntityDict, T extends keyof ED> = {
|
||||
oakPagination?: Pagination;
|
||||
};
|
||||
export type MakeOakComponent<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED>, FrontCxt extends SyncContext<ED>, AD extends Record<string, Aspect<ED, AsyncContext<ED>>>, FD extends Record<string, Feature>> = <IsList extends boolean, T extends keyof ED, FormedData extends DataOption, TData extends DataOption, TProperty extends DataOption, TMethod extends MethodOption>(options: OakComponentOption<IsList, ED, T, Cxt, FrontCxt, AD, FD, FormedData, TData, TProperty, TMethod>) => (props: ReactComponentProps<ED, T, IsList, TProperty>) => React.ReactElement;
|
||||
export type MakeOakComponent<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED>, FrontCxt extends SyncContext<ED>, AD extends Record<string, Aspect<ED, Cxt>>, FD extends Record<string, Feature>> = <IsList extends boolean, T extends keyof ED, FormedData extends DataOption, TData extends DataOption, TProperty extends DataOption, TMethod extends MethodOption>(options: OakComponentOption<IsList, ED, T, Cxt, FrontCxt, AD, FD, FormedData, TData, TProperty, TMethod>) => (props: ReactComponentProps<ED, T, IsList, TProperty>) => React.ReactElement;
|
||||
export type WebComponentCommonMethodNames = 'setNotification' | 'setMessage' | 'navigateTo' | 'navigateBack' | 'redirectTo' | 'clean' | 't' | 'execute' | 'refresh' | 'aggregate' | 'checkOperation' | 'isDirty';
|
||||
export type WebComponentListMethodNames = 'loadMore' | 'setFilters' | 'addNamedFilter' | 'removeNamedFilter' | 'removeNamedFilterByName' | 'setNamedSorters' | 'addNamedSorter' | 'removeNamedSorter' | 'removeNamedSorterByName' | 'setPageSize' | 'setCurrentPage' | 'addItem' | 'addItems' | 'removeItem' | 'removeItems' | 'updateItem' | 'updateItems' | 'resetItem' | 'recoverItem' | 'recoverItems';
|
||||
export type WebComponentSingleMethodNames = 'update' | 'remove' | 'create' | 'isCreation' | 'getId' | 'setId';
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
type UploadFileFn = (options: {
|
||||
file: string | File | Blob;
|
||||
name: string;
|
||||
uploadUrl: string;
|
||||
formData: Record<string, any>;
|
||||
autoInform?: boolean;
|
||||
getPercent?: Function;
|
||||
uploadId?: string;
|
||||
method?: "POST" | "PUT" | "PATCH";
|
||||
isFilePath?: boolean;
|
||||
}) => Promise<{
|
||||
status: number;
|
||||
statusText: string;
|
||||
statusCode?: number;
|
||||
headers: {
|
||||
get(name: string): string | null;
|
||||
};
|
||||
json(): Promise<any>;
|
||||
text(): Promise<string>;
|
||||
errMsg?: string;
|
||||
data?: any;
|
||||
}>;
|
||||
export interface UploadInterface {
|
||||
uploadFile: UploadFileFn;
|
||||
abortUpload(uploadId: string): boolean;
|
||||
abortAllUploads(): void;
|
||||
getUploadStatus(uploadId: string): 'uploading' | 'completed' | 'aborted' | 'not-found';
|
||||
getActiveUploads(): string[];
|
||||
}
|
||||
export {};
|
||||
|
|
@ -0,0 +1 @@
|
|||
export {};
|
||||
|
|
@ -1,3 +1,2 @@
|
|||
/// <reference types="wechat-miniprogram" />
|
||||
export type PromisifyOption<T extends Record<string, any>> = Omit<T, 'success' | 'fail' | 'complete'>;
|
||||
export type PromisifyResult<T extends WechatMiniprogram.AsyncMethodOptionLike> = Promise<Parameters<Exclude<T['success'], undefined>>[0]>;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
/// <reference types="wechat-miniprogram" />
|
||||
import { PromisifyOption } from '../../types/Wx';
|
||||
export declare class Bluetooth {
|
||||
private serverDict;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,21 @@
|
|||
export declare class Upload {
|
||||
uploadFile(file: string | File, name: string, uploadUrl: string, formData: Record<string, any>, autoInform?: boolean): Promise<any>;
|
||||
import { UploadInterface } from "../types/Upload";
|
||||
export declare class Upload implements UploadInterface {
|
||||
uploadFile(options: {
|
||||
file: string | File | Blob;
|
||||
name: string;
|
||||
uploadUrl: string;
|
||||
formData: Record<string, any>;
|
||||
autoInform?: boolean;
|
||||
getPercent?: Function;
|
||||
uploadId?: string;
|
||||
method?: "POST" | "PUT" | "PATCH";
|
||||
isFilePath?: boolean;
|
||||
}): Promise<any>;
|
||||
private controllers;
|
||||
constructor();
|
||||
abortUpload(uploadId: string): boolean;
|
||||
abortAllUploads(): void;
|
||||
getUploadStatus(uploadId: string): 'uploading' | 'completed' | 'aborted' | 'not-found';
|
||||
private generateUploadId;
|
||||
getActiveUploads(): string[];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,35 @@
|
|||
export class Upload {
|
||||
async uploadFile(file, name, uploadUrl, formData, autoInform) {
|
||||
async uploadFile(options) {
|
||||
console.warn('server不会调用此函数');
|
||||
}
|
||||
controllers = new Map();
|
||||
constructor() {
|
||||
this.uploadFile = this.uploadFile.bind(this);
|
||||
this.abortUpload = this.abortUpload.bind(this);
|
||||
this.abortAllUploads = this.abortAllUploads.bind(this);
|
||||
this.getUploadStatus = this.getUploadStatus.bind(this);
|
||||
this.getActiveUploads = this.getActiveUploads.bind(this);
|
||||
}
|
||||
// 中断特定上传
|
||||
abortUpload(uploadId) {
|
||||
console.warn('server不会调用此函数');
|
||||
return false;
|
||||
}
|
||||
// 中断所有上传
|
||||
abortAllUploads() {
|
||||
console.warn('server不会调用此函数');
|
||||
}
|
||||
// 获取上传状态
|
||||
getUploadStatus(uploadId) {
|
||||
console.warn('server不会调用此函数');
|
||||
return 'uploading';
|
||||
}
|
||||
// 生成唯一的上传ID
|
||||
generateUploadId(file, uploadUrl) {
|
||||
return `server不会调用此函数`;
|
||||
}
|
||||
// 获取所有进行中的上传任务
|
||||
getActiveUploads() {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,18 @@
|
|||
export declare class Upload {
|
||||
uploadFile(file: string | File, name: string, uploadUrl: string, formData: Record<string, any>, autoInform?: boolean): Promise<any>;
|
||||
import { UploadInterface } from '../types/Upload';
|
||||
export declare class Upload implements UploadInterface {
|
||||
abortUpload(uploadId: string): boolean;
|
||||
abortAllUploads(): void;
|
||||
getUploadStatus(uploadId: string): 'uploading' | 'completed' | 'aborted' | 'not-found';
|
||||
getActiveUploads(): string[];
|
||||
uploadFile(options: {
|
||||
file: string | File | Blob;
|
||||
name: string;
|
||||
uploadUrl: string;
|
||||
formData: Record<string, any>;
|
||||
autoInform?: boolean;
|
||||
getPercent?: Function;
|
||||
uploadId?: string;
|
||||
method?: "POST" | "PUT" | "PATCH";
|
||||
isFilePath?: boolean;
|
||||
}): Promise<any>;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,50 @@
|
|||
import { promisify } from './promisify';
|
||||
export class Upload {
|
||||
async uploadFile(file, name, uploadUrl, formData, autoInform) {
|
||||
abortUpload(uploadId) {
|
||||
return false;
|
||||
}
|
||||
abortAllUploads() {
|
||||
}
|
||||
getUploadStatus(uploadId) {
|
||||
return 'not-found';
|
||||
}
|
||||
getActiveUploads() {
|
||||
return [];
|
||||
}
|
||||
async uploadFile(options) {
|
||||
const { file, name, uploadUrl, formData, isFilePath, method = "POST" } = options;
|
||||
const isPut = method === "PUT";
|
||||
if (isPut) {
|
||||
if (isFilePath) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const fs = wx.getFileSystemManager();
|
||||
fs.readFile({
|
||||
filePath: file,
|
||||
encoding: 'binary',
|
||||
success: res => {
|
||||
resolve(global.fetch(uploadUrl, {
|
||||
method: "PUT",
|
||||
headers: {
|
||||
'Content-Type': 'application/octet-stream',
|
||||
},
|
||||
body: res.data,
|
||||
}));
|
||||
},
|
||||
fail: err => {
|
||||
reject(err);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
return global.fetch(uploadUrl, {
|
||||
method: "PUT",
|
||||
headers: {
|
||||
'Content-Type': 'application/octet-stream',
|
||||
},
|
||||
body: file,
|
||||
});
|
||||
}
|
||||
else {
|
||||
const wxUploadFile = promisify(wx.uploadFile);
|
||||
const result = await wxUploadFile({
|
||||
url: uploadUrl,
|
||||
|
|
@ -10,4 +54,5 @@ export class Upload {
|
|||
});
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,17 @@
|
|||
export declare class Upload {
|
||||
uploadFile(file: File | string, name: string, uploadUrl: string, formData: Record<string, any>, autoInform?: boolean): Promise<any>;
|
||||
import { UploadInterface } from "../types/Upload";
|
||||
export declare class Upload implements UploadInterface {
|
||||
abortUpload(uploadId: string): boolean;
|
||||
abortAllUploads(): void;
|
||||
getUploadStatus(uploadId: string): 'uploading' | 'completed' | 'aborted' | 'not-found';
|
||||
getActiveUploads(): string[];
|
||||
uploadFile(options: {
|
||||
file: File | string | Blob;
|
||||
name: string;
|
||||
uploadUrl: string;
|
||||
formData: Record<string, any>;
|
||||
autoInform?: boolean;
|
||||
getPercent?: Function;
|
||||
uploadId?: string;
|
||||
method?: "POST" | "PUT" | "PATCH";
|
||||
}): Promise<any>;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,43 @@
|
|||
export class Upload {
|
||||
async uploadFile(file, name, uploadUrl, formData, autoInform) {
|
||||
abortUpload(uploadId) {
|
||||
return false;
|
||||
}
|
||||
abortAllUploads() {
|
||||
}
|
||||
getUploadStatus(uploadId) {
|
||||
return 'not-found';
|
||||
}
|
||||
getActiveUploads() {
|
||||
return [];
|
||||
}
|
||||
async uploadFile(options) {
|
||||
const { file, name, uploadUrl, formData, method = "POST" } = options;
|
||||
const isPut = method === "PUT";
|
||||
if (isPut) {
|
||||
// S3 预签名上传
|
||||
const headers = {};
|
||||
if (file instanceof File) {
|
||||
headers["Content-Type"] = file.type || "application/octet-stream";
|
||||
}
|
||||
const result = await fetch(uploadUrl, {
|
||||
method: "PUT",
|
||||
headers,
|
||||
body: file,
|
||||
});
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
// 表单上传
|
||||
const formData2 = new FormData();
|
||||
for (const key of Object.keys(formData)) {
|
||||
formData2.append(key, formData[key]);
|
||||
}
|
||||
formData2.append(name || 'file', file);
|
||||
const options = {
|
||||
formData2.append(name || "file", file);
|
||||
const result = await fetch(uploadUrl, {
|
||||
method,
|
||||
body: formData2,
|
||||
method: 'POST',
|
||||
};
|
||||
const result = await fetch(uploadUrl, options);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,20 @@
|
|||
export declare class Upload {
|
||||
uploadFile(file: File | string, name: string, uploadUrl: string, formData: Record<string, any>, autoInform?: boolean, getPercent?: Function): Promise<any>;
|
||||
import { UploadInterface } from "../types/Upload";
|
||||
export declare class Upload implements UploadInterface {
|
||||
private controllers;
|
||||
constructor();
|
||||
uploadFile(options: {
|
||||
file: File | string | Blob;
|
||||
name: string;
|
||||
uploadUrl: string;
|
||||
formData: Record<string, any>;
|
||||
autoInform?: boolean;
|
||||
getPercent?: Function;
|
||||
uploadId?: string;
|
||||
method?: "POST" | "PUT" | "PATCH";
|
||||
}): Promise<any>;
|
||||
abortUpload(uploadId: string): boolean;
|
||||
abortAllUploads(): void;
|
||||
getUploadStatus(uploadId: string): 'uploading' | 'completed' | 'aborted' | 'not-found';
|
||||
private generateUploadId;
|
||||
getActiveUploads(): string[];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,51 +1,68 @@
|
|||
export class Upload {
|
||||
// async uploadFile(
|
||||
// file: File | string,
|
||||
// name: string,
|
||||
// uploadUrl: string,
|
||||
// formData: Record<string, any>,
|
||||
// autoInform?: boolean
|
||||
// ): Promise<any> {
|
||||
// const formData2 = new FormData();
|
||||
// for (const key of Object.keys(formData)) {
|
||||
// formData2.append(key, formData[key]);
|
||||
// }
|
||||
// formData2.append(name || 'file', file as File);
|
||||
// const options = {
|
||||
// body: formData2,
|
||||
// method: 'POST',
|
||||
// };
|
||||
// const result = await fetch(uploadUrl, options);
|
||||
// return result;
|
||||
// }
|
||||
async uploadFile(file, name, uploadUrl, formData, autoInform, getPercent) {
|
||||
controllers = new Map();
|
||||
constructor() {
|
||||
this.uploadFile = this.uploadFile.bind(this);
|
||||
this.abortUpload = this.abortUpload.bind(this);
|
||||
this.abortAllUploads = this.abortAllUploads.bind(this);
|
||||
this.getUploadStatus = this.getUploadStatus.bind(this);
|
||||
this.getActiveUploads = this.getActiveUploads.bind(this);
|
||||
}
|
||||
async uploadFile(options) {
|
||||
const { file, name, uploadUrl, formData, getPercent, uploadId, method = "POST" } = options;
|
||||
const isPut = method === "PUT";
|
||||
const id = uploadId || this.generateUploadId(file, uploadUrl);
|
||||
// 如果已有相同ID的上传在进行,先中断它
|
||||
if (this.controllers.has(id)) {
|
||||
this.abortUpload(id);
|
||||
}
|
||||
// 创建新的 AbortController
|
||||
const controller = new AbortController();
|
||||
this.controllers.set(id, controller);
|
||||
// 进度监听模式
|
||||
if (getPercent) {
|
||||
const formData2 = new FormData();
|
||||
Object.entries(formData).forEach(([key, value]) => {
|
||||
formData2.append(key, value);
|
||||
});
|
||||
formData2.append(name || 'file', file);
|
||||
return new Promise((resolve, reject) => {
|
||||
const xhr = new XMLHttpRequest();
|
||||
let percent = 0;
|
||||
xhr.upload.addEventListener('progress', (event) => {
|
||||
// 监听中止信号
|
||||
controller.signal.addEventListener('abort', () => {
|
||||
xhr.abort();
|
||||
reject(new DOMException('Upload aborted', 'AbortError'));
|
||||
});
|
||||
xhr.upload.addEventListener("progress", (event) => {
|
||||
if (event.lengthComputable) {
|
||||
percent = Math.round((event.loaded / event.total) * 100);
|
||||
getPercent(percent);
|
||||
}
|
||||
});
|
||||
xhr.onload = () => {
|
||||
this.controllers.delete(id); // 清理控制器
|
||||
// 构造类似 Response 的对象,支持 headers.get()
|
||||
const headersMap = new Map();
|
||||
const headersStr = xhr.getAllResponseHeaders();
|
||||
headersStr.split('\r\n').forEach(line => {
|
||||
const parts = line.split(': ');
|
||||
if (parts.length === 2) {
|
||||
headersMap.set(parts[0].toLowerCase(), parts[1]);
|
||||
}
|
||||
});
|
||||
const headers = {
|
||||
get: (name) => headersMap.get(name.toLowerCase()) || null,
|
||||
has: (name) => headersMap.has(name.toLowerCase()),
|
||||
forEach: (callback) => {
|
||||
headersMap.forEach(callback);
|
||||
}
|
||||
};
|
||||
if (xhr.status >= 200 && xhr.status < 300) {
|
||||
if (xhr.status === 204) {
|
||||
resolve({ status: 204 }); // 正确返回状态码
|
||||
resolve({ status: 204, headers });
|
||||
}
|
||||
else {
|
||||
try {
|
||||
const data = JSON.parse(xhr.responseText);
|
||||
resolve(data);
|
||||
resolve({ ...data, status: xhr.status, headers });
|
||||
}
|
||||
catch (e) {
|
||||
resolve({ status: xhr.status, raw: xhr.responseText });
|
||||
catch {
|
||||
resolve({ status: xhr.status, raw: xhr.responseText, headers });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -53,23 +70,120 @@ export class Upload {
|
|||
reject(new Error(`HTTP Error: ${xhr.status}`));
|
||||
}
|
||||
};
|
||||
xhr.onerror = () => reject(new Error('Network Error'));
|
||||
xhr.open('POST', uploadUrl);
|
||||
xhr.onerror = () => {
|
||||
this.controllers.delete(id);
|
||||
// 如果不是因为中止导致的错误
|
||||
if (!controller.signal.aborted) {
|
||||
reject(new Error("Network Error"));
|
||||
}
|
||||
};
|
||||
xhr.onabort = () => {
|
||||
this.controllers.delete(id);
|
||||
if (controller.signal.aborted) {
|
||||
reject(new DOMException('Upload aborted', 'AbortError'));
|
||||
}
|
||||
};
|
||||
xhr.open(method, uploadUrl);
|
||||
if (isPut) {
|
||||
// PUT 模式:直接上传文件
|
||||
if (file instanceof File) {
|
||||
xhr.setRequestHeader("Content-Type", file.type || "application/octet-stream");
|
||||
}
|
||||
else if (file instanceof Blob) {
|
||||
xhr.setRequestHeader("Content-Type", "application/octet-stream");
|
||||
}
|
||||
xhr.send(file);
|
||||
}
|
||||
else {
|
||||
// POST / PATCH 模式:构建表单
|
||||
const formData2 = new FormData();
|
||||
Object.entries(formData).forEach(([key, value]) => {
|
||||
formData2.append(key, value);
|
||||
});
|
||||
formData2.append(name || "file", file);
|
||||
xhr.send(formData2);
|
||||
}
|
||||
});
|
||||
}
|
||||
// 无进度监听模式(直接 fetch)
|
||||
try {
|
||||
let result;
|
||||
if (isPut) {
|
||||
// S3 预签名上传
|
||||
const headers = {};
|
||||
if (file instanceof File) {
|
||||
headers["Content-Type"] = file.type || "application/octet-stream";
|
||||
}
|
||||
else if (file instanceof Blob) {
|
||||
headers["Content-Type"] = "application/octet-stream";
|
||||
}
|
||||
result = await fetch(uploadUrl, {
|
||||
method: "PUT",
|
||||
headers,
|
||||
body: file,
|
||||
signal: controller.signal, // 添加中止信号
|
||||
});
|
||||
}
|
||||
else {
|
||||
// 表单上传
|
||||
const formData2 = new FormData();
|
||||
for (const key of Object.keys(formData)) {
|
||||
formData2.append(key, formData[key]);
|
||||
}
|
||||
formData2.append(name || 'file', file);
|
||||
const options = {
|
||||
formData2.append(name || "file", file);
|
||||
result = await fetch(uploadUrl, {
|
||||
method,
|
||||
body: formData2,
|
||||
method: 'POST',
|
||||
};
|
||||
const result = await fetch(uploadUrl, options);
|
||||
signal: controller.signal, // 添加中止信号
|
||||
});
|
||||
}
|
||||
this.controllers.delete(id); // 成功后清理控制器
|
||||
return result;
|
||||
}
|
||||
catch (error) {
|
||||
this.controllers.delete(id); // 失败后清理控制器
|
||||
// 人为中断返回204 使general-business处理成功
|
||||
if (error instanceof DOMException && error.name === 'AbortError') {
|
||||
throw new DOMException('Upload aborted', 'AbortError');
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
// 中断特定上传
|
||||
abortUpload(uploadId) {
|
||||
const controller = this.controllers.get(uploadId);
|
||||
if (controller) {
|
||||
controller.abort();
|
||||
this.controllers.delete(uploadId);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// 中断所有上传
|
||||
abortAllUploads() {
|
||||
this.controllers.forEach((controller, id) => {
|
||||
controller.abort();
|
||||
});
|
||||
this.controllers.clear();
|
||||
}
|
||||
// 获取上传状态
|
||||
getUploadStatus(uploadId) {
|
||||
const controller = this.controllers.get(uploadId);
|
||||
if (!controller)
|
||||
return 'not-found';
|
||||
if (controller.signal.aborted)
|
||||
return 'aborted';
|
||||
return 'uploading';
|
||||
}
|
||||
// 生成唯一的上传ID
|
||||
generateUploadId(file, uploadUrl) {
|
||||
const timestamp = Date.now();
|
||||
const random = Math.random().toString(36).substring(2, 9);
|
||||
const fileInfo = file instanceof File ? `${file.name}-${file.size}` : file instanceof Blob ? `blob-${file.size}` : file;
|
||||
return `${uploadUrl}-${fileInfo}-${timestamp}-${random}`;
|
||||
}
|
||||
// 获取所有进行中的上传任务
|
||||
getActiveUploads() {
|
||||
return Array.from(this.controllers.keys());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,5 +8,5 @@ type TransformAspectDict<T extends AspectDict<ED, BCT>, ED extends BaseEntityDic
|
|||
[K in keyof T]: T[K] extends (params: infer P, context: BCT) => infer R ? R extends Promise<unknown> ? (params: P, callback?: (result: R, opRecords?: OpRecord<ED>[]) => void, dontPublish?: true, ignoreContext?: true) => R : never : never;
|
||||
};
|
||||
export type AspectDictTrans<ED extends BaseEntityDict, AD extends AspectDict<ED, BCT>, BCT extends AsyncContext<ED>> = TransformAspectDict<AD & CommonAspectDict<ED>, ED, BCT>;
|
||||
export declare const createService: <ED extends BaseEntityDict, AD extends AspectDict<ED, any>>(cache: BasicFeatures<ED>["cache"]) => TransformAspectDict<AD & CommonAspectDict<ED>, ED, any>;
|
||||
export declare const createService: <ED extends BaseEntityDict, AD extends AspectDict<ED, any>>(cache: BasicFeatures<ED>["cache"]) => AspectDictTrans<ED, AD, any>;
|
||||
export {};
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ export declare abstract class BackendRuntimeContext<ED extends EntityDict & Base
|
|||
eventOperationMap: Record<string, string[]>;
|
||||
getNavigatorState(): {
|
||||
pathname: string;
|
||||
oakFrom?: string | undefined;
|
||||
oakFrom?: string;
|
||||
} | undefined;
|
||||
getSubscriberId(): string | undefined;
|
||||
getBriefEnvironment(): BriefEnv | undefined;
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ export declare class DebugStore<ED extends EntityDict & BaseEntityDict, Cxt exte
|
|||
constructor(storageSchema: StorageSchema<ED>, contextBuilder: (store: DebugStore<ED, Cxt>) => Cxt, authDeduceRelationMap: AuthDeduceRelationMap<ED>, selectFreeEntities?: (keyof ED)[], updateFreeDict?: {
|
||||
[A in keyof ED]?: string[];
|
||||
});
|
||||
checkRelationAsync<T extends keyof ED, Cxt extends AsyncContext<ED>>(entity: T, operation: Omit<ED[T]["Operation"] | ED[T]["Selection"], "id">, context: Cxt): Promise<void>;
|
||||
exec(script: string, txnId?: string): Promise<void>;
|
||||
aggregate<T extends keyof ED, OP extends SelectOption>(entity: T, aggregation: ED[T]["Aggregation"], context: Cxt, option: OP): Promise<AggregationResult<ED[T]["Schema"]>>;
|
||||
begin(option?: TxnOption): Promise<string>;
|
||||
|
|
|
|||
|
|
@ -21,10 +21,9 @@ class DebugStore extends oak_memory_tree_store_1.TreeStore {
|
|||
this.executor = new TriggerExecutor_1.TriggerExecutor(() => contextBuilder(this));
|
||||
this.relationAuth = new RelationAuth_1.RelationAuth(storageSchema, authDeduceRelationMap, selectFreeEntities, updateFreeDict);
|
||||
}
|
||||
/*
|
||||
checkRelationAsync<T extends keyof ED, Cxt extends AsyncContext<ED>>(entity: T, operation: Omit<ED[T]["Operation"] | ED[T]["Selection"], "id">, context: Cxt): Promise<void> {
|
||||
checkRelationAsync(entity, operation, context) {
|
||||
return this.relationAuth.checkRelationAsync(entity, operation, context);
|
||||
} */
|
||||
}
|
||||
async exec(script, txnId) {
|
||||
throw new Error('debugStore dont support exec script directly');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createDebugStore = void 0;
|
||||
exports.createDebugStore = createDebugStore;
|
||||
const node_schedule_1 = require("node-schedule");
|
||||
const constant_1 = require("../constant/constant");
|
||||
const DebugStore_1 = require("./DebugStore");
|
||||
|
|
@ -223,4 +223,3 @@ function createDebugStore(storageSchema, contextBuilder, triggers, checkers, wat
|
|||
}
|
||||
return store;
|
||||
}
|
||||
exports.createDebugStore = createDebugStore;
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ export declare class Cache<ED extends EntityDict & BaseEntityDict> extends Featu
|
|||
private cacheStore;
|
||||
private syncEventsCallbacks;
|
||||
private contextBuilder;
|
||||
private refreshing;
|
||||
private executing;
|
||||
private savedEntities;
|
||||
private keepFreshPeriod;
|
||||
private localStorage;
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ class Cache extends Feature_1.Feature {
|
|||
cacheStore;
|
||||
syncEventsCallbacks;
|
||||
contextBuilder;
|
||||
refreshing = 0;
|
||||
executing = 0;
|
||||
savedEntities;
|
||||
keepFreshPeriod;
|
||||
localStorage;
|
||||
|
|
@ -95,13 +95,13 @@ class Cache extends Feature_1.Feature {
|
|||
} */
|
||||
async exec(name, params, callback, dontPublish, ignoreContext) {
|
||||
try {
|
||||
this.refreshing++;
|
||||
this.executing++;
|
||||
const { result, opRecords, message } = await this.connector.callAspect(name, params, ignoreContext ? undefined : this.context || this.contextBuilder());
|
||||
callback && callback(result, opRecords);
|
||||
if (opRecords?.length) {
|
||||
this.syncInner(opRecords);
|
||||
}
|
||||
this.refreshing--;
|
||||
this.executing--;
|
||||
if (opRecords && opRecords.length > 0 && !dontPublish) {
|
||||
this.publish();
|
||||
}
|
||||
|
|
@ -112,7 +112,7 @@ class Cache extends Feature_1.Feature {
|
|||
}
|
||||
catch (e) {
|
||||
// 如果是数据不一致错误,这里可以让用户知道
|
||||
this.refreshing--;
|
||||
this.executing--;
|
||||
if (e instanceof Exception_1.OakException) {
|
||||
const { opRecords } = e;
|
||||
if (opRecords.length) {
|
||||
|
|
@ -443,7 +443,7 @@ class Cache extends Feature_1.Feature {
|
|||
return;
|
||||
}
|
||||
fetchRows(missedRows) {
|
||||
if (!this.refreshing) {
|
||||
if (!this.executing) {
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
console.warn('缓存被动去获取数据,请查看页面行为并加以优化', missedRows);
|
||||
}
|
||||
|
|
@ -465,7 +465,7 @@ class Cache extends Feature_1.Feature {
|
|||
const result = this.cacheStore.select(entity, selection, this.context, {
|
||||
dontCollect: true,
|
||||
includedDeleted: true,
|
||||
warnWhenAttributeMiss: !this.refreshing && process.env.NODE_ENV === 'development',
|
||||
warnWhenAttributeMiss: !this.executing && process.env.NODE_ENV === 'development',
|
||||
});
|
||||
rollback && rollback();
|
||||
return result;
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ export default abstract class Console<ED extends EntityDict & BaseEntityDict, OM
|
|||
setContext(entity: keyof ED, entityId: string): void;
|
||||
getContext(): ConsoleContext<ED> | undefined;
|
||||
getAvailMenus(): (OMenu & {
|
||||
sourceEntity?: keyof ED | undefined;
|
||||
sourceEntity?: keyof ED;
|
||||
available: boolean | null;
|
||||
})[];
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.initializeStep1 = exports.initializeStep2 = void 0;
|
||||
exports.initializeStep2 = initializeStep2;
|
||||
exports.initializeStep1 = initializeStep1;
|
||||
const tslib_1 = require("tslib");
|
||||
const cache_1 = require("./cache");
|
||||
const location_1 = require("./location");
|
||||
|
|
@ -43,7 +44,6 @@ function initializeStep2(features, connector, storageSchema, frontendContextBuil
|
|||
subscriber,
|
||||
};
|
||||
}
|
||||
exports.initializeStep2 = initializeStep2;
|
||||
function initializeStep1() {
|
||||
const location = new location_1.Location();
|
||||
const environment = new environment_1.Environment();
|
||||
|
|
@ -60,4 +60,3 @@ function initializeStep1() {
|
|||
navigator,
|
||||
};
|
||||
}
|
||||
exports.initializeStep1 = initializeStep1;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
/// <reference types="node" />
|
||||
import { Feature } from '../types/Feature';
|
||||
export declare class Navigator extends Feature {
|
||||
namespace: string;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
/// <reference types="wechat-miniprogram" />
|
||||
import { OakNavigateToParameters } from '../types/Page';
|
||||
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
|
||||
import { EntityDict } from 'oak-domain/lib/types';
|
||||
|
|
|
|||
|
|
@ -78,13 +78,12 @@ class Navigator extends navigator_common_1.Navigator {
|
|||
wx.navigateTo({
|
||||
url: url,
|
||||
success: () => {
|
||||
this.leave();
|
||||
this.publish();
|
||||
resolve(undefined);
|
||||
},
|
||||
fail: (err) => reject(err),
|
||||
});
|
||||
this.publish();
|
||||
this.leave();
|
||||
});
|
||||
}
|
||||
// 关闭当前页面,跳转到应用内的某个页面,但不允许跳转到tabBar页面。
|
||||
|
|
@ -97,12 +96,12 @@ class Navigator extends navigator_common_1.Navigator {
|
|||
wx.redirectTo({
|
||||
url: url,
|
||||
success: () => {
|
||||
resolve(undefined);
|
||||
this.leave();
|
||||
this.publish();
|
||||
resolve(undefined);
|
||||
},
|
||||
fail: (err) => reject(err),
|
||||
});
|
||||
this.leave();
|
||||
});
|
||||
}
|
||||
//跳转到tabBar页面,并关闭其他所有非tabBar页面,用于跳转到主页。
|
||||
|
|
@ -115,12 +114,12 @@ class Navigator extends navigator_common_1.Navigator {
|
|||
wx.switchTab({
|
||||
url: url,
|
||||
success: () => {
|
||||
resolve(undefined);
|
||||
this.leave();
|
||||
this.publish();
|
||||
resolve(undefined);
|
||||
},
|
||||
fail: (err) => reject(err),
|
||||
});
|
||||
this.leave();
|
||||
});
|
||||
}
|
||||
navigateBack(delta) {
|
||||
|
|
@ -131,29 +130,23 @@ class Navigator extends navigator_common_1.Navigator {
|
|||
wx.navigateBack({
|
||||
delta: delta || 1,
|
||||
success: () => {
|
||||
resolve(undefined);
|
||||
this.leave();
|
||||
this.publish();
|
||||
resolve(undefined);
|
||||
},
|
||||
fail: (err) => reject(err),
|
||||
});
|
||||
this.leave();
|
||||
});
|
||||
}
|
||||
navigateBackOrRedirectTo(options, state, disableNamespace) {
|
||||
if (!this.enter()) {
|
||||
return;
|
||||
}
|
||||
const pages = getCurrentPages();
|
||||
if (pages.length > 1) {
|
||||
this.leave();
|
||||
return this.navigateBack();
|
||||
}
|
||||
const isTabBar = options?.isTabBar;
|
||||
if (isTabBar) {
|
||||
this.leave();
|
||||
return this.switchTab(options, state, disableNamespace);
|
||||
}
|
||||
this.leave();
|
||||
return this.redirectTo(options, state, disableNamespace);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,8 +59,8 @@ class Navigator extends navigator_common_1.Navigator {
|
|||
const { url, props } = this.getUrlAndProps(options, state, disableNamespace);
|
||||
const replaceAction = native_1.StackActions.replace(url, props);
|
||||
this.history.dispatch(replaceAction);
|
||||
this.publish();
|
||||
this.leave();
|
||||
this.publish();
|
||||
}
|
||||
async switchTab(options, state, disableNamespace) {
|
||||
if (!this.enter()) {
|
||||
|
|
@ -69,8 +69,8 @@ class Navigator extends navigator_common_1.Navigator {
|
|||
const { url, props } = this.getUrlAndProps(options, state, disableNamespace);
|
||||
const jumpToAction = native_1.TabActions.jumpTo(url, props);
|
||||
this.history.dispatch(jumpToAction);
|
||||
this.publish();
|
||||
this.leave();
|
||||
this.publish();
|
||||
}
|
||||
async navigateBack(delta) {
|
||||
if (!this.enter()) {
|
||||
|
|
@ -80,10 +80,13 @@ class Navigator extends navigator_common_1.Navigator {
|
|||
if (canGoBack) {
|
||||
const popAction = native_1.StackActions.pop(delta || 1);
|
||||
this.history.dispatch(popAction);
|
||||
this.leave();
|
||||
this.publish();
|
||||
}
|
||||
else {
|
||||
this.leave();
|
||||
}
|
||||
}
|
||||
navigateBackOrRedirectTo(options, state, disableNamespace) {
|
||||
if (!this.enter()) {
|
||||
return;
|
||||
|
|
@ -91,14 +94,14 @@ class Navigator extends navigator_common_1.Navigator {
|
|||
const canGoBack = this.history.canGoBack();
|
||||
if (canGoBack) {
|
||||
this.navigateBack();
|
||||
this.publish();
|
||||
this.leave();
|
||||
this.publish();
|
||||
return;
|
||||
}
|
||||
// 回最顶层
|
||||
this.history.dispatch(native_1.StackActions.popToTop());
|
||||
this.publish();
|
||||
this.leave();
|
||||
this.publish();
|
||||
}
|
||||
}
|
||||
exports.Navigator = Navigator;
|
||||
|
|
|
|||
|
|
@ -15,10 +15,10 @@ export declare class Navigator extends CommonNavigator {
|
|||
namespace: string;
|
||||
url: string;
|
||||
state: unknown;
|
||||
key: string;
|
||||
pathname: string;
|
||||
search: string;
|
||||
hash: string;
|
||||
key: import("history").Key;
|
||||
pathname: import("history").Pathname;
|
||||
search: import("history").Search;
|
||||
hash: import("history").Hash;
|
||||
};
|
||||
getState(): {
|
||||
pathname: string;
|
||||
|
|
|
|||
|
|
@ -48,8 +48,8 @@ class Navigator extends navigator_common_1.Navigator {
|
|||
}
|
||||
const { url, props } = this.getUrlAndProps(options, state, disableNamespace);
|
||||
this.history.push(url, props);
|
||||
this.publish();
|
||||
this.leave();
|
||||
this.publish();
|
||||
}
|
||||
async redirectTo(options, state, disableNamespace) {
|
||||
if (!this.enter()) {
|
||||
|
|
@ -57,8 +57,8 @@ class Navigator extends navigator_common_1.Navigator {
|
|||
}
|
||||
const { url, props } = this.getUrlAndProps(options, state, disableNamespace);
|
||||
this.history.replace(url, props);
|
||||
this.publish();
|
||||
this.leave();
|
||||
this.publish();
|
||||
}
|
||||
async switchTab(options, state, disableNamespace) {
|
||||
console.error('浏览器无switchTab');
|
||||
|
|
@ -71,8 +71,8 @@ class Navigator extends navigator_common_1.Navigator {
|
|||
return;
|
||||
}
|
||||
this.history.go(delta ? 0 - delta : -1);
|
||||
this.publish();
|
||||
this.leave();
|
||||
this.publish();
|
||||
}
|
||||
navigateBackOrRedirectTo(options, state, disableNamespace) {
|
||||
console.error('浏览器暂无法获得history堆栈');
|
||||
|
|
|
|||
|
|
@ -119,20 +119,20 @@ declare class ListNode<ED extends EntityDict & BaseEntityDict, T extends keyof E
|
|||
removeChild(path: string): void;
|
||||
getChild(path: string): SingleNode<ED, T>;
|
||||
getNamedFilters(): (NamedFilterItem<ED, T> & {
|
||||
applied?: boolean | undefined;
|
||||
applied?: boolean;
|
||||
})[];
|
||||
getNamedFilterByName(name: string): (NamedFilterItem<ED, T> & {
|
||||
applied?: boolean | undefined;
|
||||
applied?: boolean;
|
||||
}) | undefined;
|
||||
setNamedFilters(filters: NamedFilterItem<ED, T>[], refresh?: boolean): void;
|
||||
addNamedFilter(filter: NamedFilterItem<ED, T>, refresh?: boolean): void;
|
||||
removeNamedFilter(filter: NamedFilterItem<ED, T>, refresh?: boolean): void;
|
||||
removeNamedFilterByName(name: string, refresh?: boolean): void;
|
||||
getNamedSorters(): (NamedSorterItem<ED, T> & {
|
||||
applied?: boolean | undefined;
|
||||
applied?: boolean;
|
||||
})[];
|
||||
getNamedSorterByName(name: string): (NamedSorterItem<ED, T> & {
|
||||
applied?: boolean | undefined;
|
||||
applied?: boolean;
|
||||
}) | undefined;
|
||||
setNamedSorters(sorters: NamedSorterItem<ED, T>[], refresh?: boolean): void;
|
||||
addNamedSorter(sorter: NamedSorterItem<ED, T>, refresh?: boolean): void;
|
||||
|
|
@ -170,7 +170,7 @@ declare class ListNode<ED extends EntityDict & BaseEntityDict, T extends keyof E
|
|||
}> | undefined;
|
||||
getProjection(): ED[T]["Projection"] | undefined;
|
||||
private constructFilters;
|
||||
constructSelection(withParent?: true, ignoreNewParent?: boolean, ignoreUnapplied?: true): {
|
||||
constructSelection(withParent?: true, ignoreNewParent?: boolean, ignoreUnapplied?: true, onlyHot?: true): {
|
||||
data: ED[T]["Projection"] | undefined;
|
||||
filter: ED[T]["Filter"] | undefined;
|
||||
sorter: ED[T]["Sorter"];
|
||||
|
|
@ -233,7 +233,7 @@ declare class SingleNode<ED extends EntityDict & BaseEntityDict, T extends keyof
|
|||
saveRefreshResult(data: Record<string, any>): void;
|
||||
refresh(): Promise<void>;
|
||||
clean(lsn?: number, dontPublish?: true): void;
|
||||
private getFilter;
|
||||
getFilter(ignoreNew?: true, onlyHot?: true): ED[T]['Filter'] | undefined;
|
||||
getIntrinsticFilters(): ED[T]["Filter"] | undefined;
|
||||
/**
|
||||
* getParentFilter不能假设一定已经有数据,只能根据当前filter的条件去构造
|
||||
|
|
@ -266,7 +266,6 @@ declare class VirtualNode<ED extends EntityDict & BaseEntityDict> extends Node<E
|
|||
entity: keyof ED;
|
||||
operation: ED[keyof ED]['Operation'];
|
||||
}> | undefined;
|
||||
setExecuting(executing: boolean): void;
|
||||
clean(lsn?: number, dontPublish?: true): void;
|
||||
checkIfClean(node: Node<ED>): boolean;
|
||||
}
|
||||
|
|
@ -328,20 +327,20 @@ export declare class RunningTree<ED extends EntityDict & BaseEntityDict> extends
|
|||
setPageSize<T extends keyof ED>(path: string, pageSize: number): void;
|
||||
setCurrentPage<T extends keyof ED>(path: string, currentPage: number): void;
|
||||
getNamedFilters<T extends keyof ED>(path: string): (NamedFilterItem<ED, keyof ED> & {
|
||||
applied?: boolean | undefined;
|
||||
applied?: boolean;
|
||||
})[];
|
||||
getNamedFilterByName<T extends keyof ED>(path: string, name: string): (NamedFilterItem<ED, keyof ED> & {
|
||||
applied?: boolean | undefined;
|
||||
applied?: boolean;
|
||||
}) | undefined;
|
||||
setNamedFilters<T extends keyof ED>(path: string, filters: NamedFilterItem<ED, T>[], refresh?: boolean): void;
|
||||
addNamedFilter<T extends keyof ED>(path: string, filter: NamedFilterItem<ED, T>, refresh?: boolean): void;
|
||||
removeNamedFilter<T extends keyof ED>(path: string, filter: NamedFilterItem<ED, T>, refresh?: boolean): void;
|
||||
removeNamedFilterByName<T extends keyof ED>(path: string, name: string, refresh?: boolean): void;
|
||||
getNamedSorters<T extends keyof ED>(path: string): (NamedSorterItem<ED, keyof ED> & {
|
||||
applied?: boolean | undefined;
|
||||
applied?: boolean;
|
||||
})[];
|
||||
getNamedSorterByName<T extends keyof ED>(path: string, name: string): (NamedSorterItem<ED, keyof ED> & {
|
||||
applied?: boolean | undefined;
|
||||
applied?: boolean;
|
||||
}) | undefined;
|
||||
setNamedSorters<T extends keyof ED>(path: string, sorters: NamedSorterItem<ED, T>[], refresh?: boolean): void;
|
||||
addNamedSorter<T extends keyof ED>(path: string, sorter: NamedSorterItem<ED, T>, refresh?: boolean): void;
|
||||
|
|
|
|||
|
|
@ -462,7 +462,8 @@ class ListNode extends EntityNode {
|
|||
case 'c': {
|
||||
const { e, d } = record;
|
||||
if (e === this.entity) {
|
||||
const { filter } = this.constructSelection(true, true, true);
|
||||
const filters = this.constructFilters(true, true, true);
|
||||
const filter = filters && (0, filter_1.combineFilters)(e, this.schema, filters);
|
||||
if (d instanceof Array) {
|
||||
d.forEach((dd) => tryAddRowToList(dd.id, filter));
|
||||
}
|
||||
|
|
@ -517,7 +518,8 @@ class ListNode extends EntityNode {
|
|||
const { d } = record;
|
||||
for (const entity in d) {
|
||||
if (entity === this.entity) {
|
||||
const { filter } = this.constructSelection(true, true, true);
|
||||
const filters = this.constructFilters(true, true, true);
|
||||
const filter = filters && (0, filter_1.combineFilters)(entity, this.schema, filters);
|
||||
for (const id in d[entity]) {
|
||||
tryAddRowToList(id, filter);
|
||||
}
|
||||
|
|
@ -538,14 +540,14 @@ class ListNode extends EntityNode {
|
|||
/** 检查原本就在的,现在还在不在,
|
||||
* 以及原本不在的,现在是不是满足条件了
|
||||
* (后一种情况也可能原本就满足但不在当前的ids中,这时是判断不出来的,total+1可能不对,但是应该是较少的case)*/
|
||||
const filter = this.constructFilters(true, true, true);
|
||||
const filters = this.constructFilters(true, true, true);
|
||||
if (intersected.length) {
|
||||
const rows = this.cache.get(this.entity, {
|
||||
data: {
|
||||
id: 1,
|
||||
},
|
||||
filter: (0, filter_1.combineFilters)(this.entity, this.schema, [
|
||||
...(filter || []),
|
||||
...(filters || []),
|
||||
{
|
||||
id: {
|
||||
$in: intersected,
|
||||
|
|
@ -563,12 +565,8 @@ class ListNode extends EntityNode {
|
|||
});
|
||||
}
|
||||
if (diffed.length) {
|
||||
diffed.forEach((ele) => {
|
||||
this.sr[ele] = {};
|
||||
if (this.pagination.total) {
|
||||
this.pagination.total++;
|
||||
}
|
||||
});
|
||||
const filter = filters && (0, filter_1.combineFilters)(e, this.schema, filters);
|
||||
diffed.forEach((ele) => tryAddRowToList(ele, filter));
|
||||
}
|
||||
}
|
||||
// hasUpdated = true;
|
||||
|
|
@ -787,7 +785,7 @@ class ListNode extends EntityNode {
|
|||
const ids = Object.keys(this.sr);
|
||||
const operations = this.ulManager.makeOperations();
|
||||
const createIds = operations.filter(o => o.action === 'create').map(o => o.data.id);
|
||||
const { data, sorter, filter } = this.constructSelection(true, false, true);
|
||||
const { data, sorter, filter } = this.constructSelection(true, false, true, true);
|
||||
const ids2 = ids.concat(createIds);
|
||||
/**
|
||||
* 在非modi状态下,当前的逻辑是用当前filter加以过滤,不然就处理不了在列表中操作改变了filter中外联的条件(例如为order创建了一个ship,但查询条件是没有ship)时,列表不发生变化
|
||||
|
|
@ -966,9 +964,10 @@ class ListNode extends EntityNode {
|
|||
} */
|
||||
return projection;
|
||||
}
|
||||
constructFilters(withParent, ignoreNewParent, ignoreUnapplied) {
|
||||
constructFilters(withParent, ignoreNewParent, ignoreUnapplied, onlyHot) {
|
||||
const { filters: ownFilters } = this;
|
||||
const filters = ownFilters.filter(ele => (!ignoreUnapplied || ele.applied === true || ele.applied === undefined) // 如果是undefined,说明不可以移除(构造时就存在),也得返回
|
||||
&& (!onlyHot || ele.hot) // 如果是getFreshValue,则只取hot的敏感过滤条件
|
||||
).map((ele) => {
|
||||
const { filter } = ele;
|
||||
if (typeof filter === 'function') {
|
||||
|
|
@ -992,7 +991,7 @@ class ListNode extends EntityNode {
|
|||
// 返回的filter在上层做check的时候可能被改造掉
|
||||
return (0, lodash_1.cloneDeep)(filters);
|
||||
}
|
||||
constructSelection(withParent, ignoreNewParent, ignoreUnapplied) {
|
||||
constructSelection(withParent, ignoreNewParent, ignoreUnapplied, onlyHot) {
|
||||
const { sorters, getTotal } = this;
|
||||
const data = this.getProjection();
|
||||
// assert(data, '取数据时找不到projection信息');
|
||||
|
|
@ -1010,7 +1009,7 @@ class ListNode extends EntityNode {
|
|||
$direction: 'desc'
|
||||
}
|
||||
];
|
||||
const filters = this.constructFilters(withParent, ignoreNewParent, ignoreUnapplied);
|
||||
const filters = this.constructFilters(withParent, ignoreNewParent, ignoreUnapplied, onlyHot);
|
||||
const filters2 = filters?.filter((ele) => !!ele);
|
||||
const filter = filters2 ? (0, filter_1.combineFilters)(this.entity, this.schema, filters2) : undefined;
|
||||
const { currentPage, pageSize } = this.pagination;
|
||||
|
|
@ -1256,7 +1255,7 @@ class SingleNode extends EntityNode {
|
|||
setId(id) {
|
||||
if (id !== this.id) {
|
||||
const operations = this.ulManager.makeOperations();
|
||||
(0, assert_1.assert)(operations.length <= 1);
|
||||
(0, assert_1.assert)(operations.length <= 1, 'singleNode在setId时出现数据不一致');
|
||||
const [operation] = operations;
|
||||
if (operation?.action === 'create') {
|
||||
if (operation.data.id === id) {
|
||||
|
|
@ -1306,8 +1305,8 @@ class SingleNode extends EntityNode {
|
|||
getFreshValue() {
|
||||
const inModiNextBranch = this.isInModiNextBranch();
|
||||
const projection = this.getProjection(false);
|
||||
const id = this.getId();
|
||||
if (projection && id) {
|
||||
const filter = this.getFilter(undefined, true);
|
||||
if (projection && filter) {
|
||||
/**
|
||||
* 这里在非modi状态下,原来的代码是不会去刷新缺失的数据,原因不明,可能是认为页面应当自己负责数据的获取
|
||||
* 在modi状态下,有些外键指向的数据无法预先获取,因此需要加上这个逻辑
|
||||
|
|
@ -1315,11 +1314,10 @@ class SingleNode extends EntityNode {
|
|||
* 先放回来,不知道有什么问题
|
||||
* by Xc 20240229
|
||||
*/
|
||||
const id = this.getId();
|
||||
const result = this.cache.get(this.entity, {
|
||||
data: projection,
|
||||
filter: {
|
||||
id,
|
||||
},
|
||||
filter,
|
||||
}, inModiNextBranch ? undefined : {
|
||||
[id]: this.sr,
|
||||
});
|
||||
|
|
@ -1418,7 +1416,7 @@ class SingleNode extends EntityNode {
|
|||
}
|
||||
setDirty() {
|
||||
const id = this.getId();
|
||||
(0, assert_1.assert)(id);
|
||||
(0, assert_1.assert)(id, "不能对没有id的singleNode设置dirty");
|
||||
this.ulManager.push(this.ulManager.maxLsn, {
|
||||
action: 'update',
|
||||
data: {},
|
||||
|
|
@ -1446,7 +1444,7 @@ class SingleNode extends EntityNode {
|
|||
const childOperations = child.composeOperations(paths?.length ? paths : undefined);
|
||||
if (childOperations) {
|
||||
if (child instanceof SingleNode) {
|
||||
(0, assert_1.assert)(childOperations.length === 1);
|
||||
(0, assert_1.assert)(childOperations.length === 1, 'singleNode在composeOperations时出现数据不一致');
|
||||
this.ulManager.push(lsnMax + 100, {
|
||||
action: 'update',
|
||||
data: {
|
||||
|
|
@ -1458,7 +1456,7 @@ class SingleNode extends EntityNode {
|
|||
});
|
||||
}
|
||||
else {
|
||||
(0, assert_1.assert)(child instanceof ListNode);
|
||||
(0, assert_1.assert)(child instanceof ListNode, 'child必须是ListNode');
|
||||
this.ulManager.push(lsnMax + 100, {
|
||||
action: 'update',
|
||||
data: {
|
||||
|
|
@ -1477,20 +1475,13 @@ class SingleNode extends EntityNode {
|
|||
const [operation] = operations;
|
||||
if (operation) {
|
||||
const { filter, ...rest } = operation;
|
||||
const intrinsticFilter = this.getIntrinsticFilters();
|
||||
const realFilter = this.getFilter(true);
|
||||
return [
|
||||
{
|
||||
entity: this.entity,
|
||||
operation: {
|
||||
...rest,
|
||||
filter: intrinsticFilter ? (0, filter_1.combineFilters)(this.entity, this.schema, [
|
||||
{
|
||||
id: this.getId(),
|
||||
},
|
||||
intrinsticFilter
|
||||
]) : {
|
||||
id: this.getId(),
|
||||
}
|
||||
filter: realFilter,
|
||||
},
|
||||
}
|
||||
];
|
||||
|
|
@ -1555,8 +1546,8 @@ class SingleNode extends EntityNode {
|
|||
const rel = this.judgeRelation(k2);
|
||||
if (rel === 2) {
|
||||
if (value?.entityId) {
|
||||
(0, assert_1.assert)(child instanceof SingleNode);
|
||||
(0, assert_1.assert)(value.entity === child.getEntity());
|
||||
(0, assert_1.assert)(child instanceof SingleNode, 'child必须是singleNode');
|
||||
(0, assert_1.assert)(value.entity === child.getEntity(), 'singleNode的entity必须一致');
|
||||
child.saveRefreshResult({
|
||||
[value.entityId]: this.sr[k2] || {},
|
||||
});
|
||||
|
|
@ -1602,7 +1593,7 @@ class SingleNode extends EntityNode {
|
|||
async refresh() {
|
||||
// SingleNode如果是非根结点,其id应该在第一次refresh的时候来确定
|
||||
const projection = this.getProjection(true);
|
||||
const filter = this.getFilter();
|
||||
const filter = this.getFilter(true);
|
||||
if (projection && filter) {
|
||||
const lr = this.startLoading();
|
||||
if (lr instanceof Promise) {
|
||||
|
|
@ -1646,12 +1637,16 @@ class SingleNode extends EntityNode {
|
|||
}
|
||||
}
|
||||
}
|
||||
getFilter() {
|
||||
getFilter(ignoreNew, onlyHot) {
|
||||
// 如果是新建,等于没有filter
|
||||
const [operation] = this.ulManager.makeOperations();
|
||||
if (operation?.action === 'create') {
|
||||
if (ignoreNew) {
|
||||
return;
|
||||
}
|
||||
const { id } = operation.data;
|
||||
return { id };
|
||||
}
|
||||
// singleNode增加一些限定的filter可以优化后台权限的判断范围和一些trigger的条件
|
||||
// 如果没有this.id则不返回,避免一些奇怪的边界(比如execute以后refresh)
|
||||
if (this.id) {
|
||||
|
|
@ -1659,7 +1654,7 @@ class SingleNode extends EntityNode {
|
|||
id: this.id,
|
||||
};
|
||||
if (this.filters) {
|
||||
filter = (0, filter_1.combineFilters)(this.entity, this.schema, this.filters.map(ele => typeof ele.filter === 'function' ? ele.filter() : ele.filter).concat(filter));
|
||||
filter = (0, filter_1.combineFilters)(this.entity, this.schema, this.filters.filter(ele => !onlyHot || ele.hot).map(ele => typeof ele.filter === 'function' ? ele.filter() : ele.filter).concat(filter));
|
||||
}
|
||||
if (this.parent && this.parent instanceof ListNode && this.parent.getEntity() === this.entity) {
|
||||
const { filter: parentFilter } = this.parent.constructSelection(true, true, true);
|
||||
|
|
@ -1848,10 +1843,6 @@ class VirtualNode extends Node {
|
|||
}
|
||||
return operationss;
|
||||
}
|
||||
setExecuting(executing) {
|
||||
this.executing = executing;
|
||||
this.publish();
|
||||
}
|
||||
clean(lsn, dontPublish) {
|
||||
for (const ele in this.children) {
|
||||
this.children[ele].clean(lsn, true);
|
||||
|
|
@ -2019,6 +2010,7 @@ class RunningTree extends Feature_1.Feature {
|
|||
(0, assert_1.assert)(!parentNode || parentNode instanceof VirtualNode);
|
||||
node = new VirtualNode(fullPath, path, parentNode, stale);
|
||||
}
|
||||
// 任何临时的修改都需要回滚,上面缓存了一些update操作
|
||||
rollback();
|
||||
if (!parentNode) {
|
||||
(0, assert_1.assert)(!parent && !this.root[path]);
|
||||
|
|
@ -2425,7 +2417,7 @@ class RunningTree extends Feature_1.Feature {
|
|||
const node = path && this.findNode(path);
|
||||
// assert(node.isDirty());
|
||||
node && node.setExecuting(true);
|
||||
let pollute = false;
|
||||
// let pollute = false;
|
||||
try {
|
||||
let operations = path && this.getOperations(path) || [];
|
||||
if (opers) {
|
||||
|
|
@ -2444,15 +2436,30 @@ class RunningTree extends Feature_1.Feature {
|
|||
else if (node) {
|
||||
// 老的写法,直接对一个非脏的结点execute某个action,也可以支持
|
||||
(0, assert_1.assert)(node instanceof SingleNode);
|
||||
node.update(this.logSerailNumber, {}, action);
|
||||
pollute = true;
|
||||
operations = node.composeOperations() || [];
|
||||
(0, assert_1.assert)(operations.length === 1);
|
||||
const [operation1] = operations;
|
||||
if (action !== operation1.operation.action) {
|
||||
(0, assert_1.assert)(operation1.operation.action === 'update'); // 如果execute时传action,前面update动作应该只可能是update
|
||||
operation1.operation.action = action;
|
||||
// node.update(this.logSerailNumber, {}, action);
|
||||
// pollute = true;
|
||||
// operations = node.composeOperations() || [];
|
||||
// assert(operations.length === 1);
|
||||
// const [operation1] = operations;
|
||||
// if (action !== operation1.operation.action) {
|
||||
// assert(operation1.operation.action === 'update'); // 如果execute时传action,前面update动作应该只可能是update
|
||||
// operation1.operation.action = action;
|
||||
// }
|
||||
/**
|
||||
* 上述写法会触发publish行为,如:一个close动作会导致页面像下面这样渲染:
|
||||
* opened --> closed(上面的node.update) --> opened(执行成功回来setExecuting时) --> closed(执行成功回来再sync cache后)
|
||||
*/
|
||||
operations.push({
|
||||
entity: node.getEntity(),
|
||||
operation: {
|
||||
id: await (0, uuid_1.generateNewIdAsync)(),
|
||||
action,
|
||||
data: {
|
||||
$$updateAt$$: Date.now(),
|
||||
},
|
||||
filter: node.getFilter(true),
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
if (operations.length > 0) {
|
||||
|
|
@ -2482,9 +2489,9 @@ class RunningTree extends Feature_1.Feature {
|
|||
}
|
||||
catch (err) {
|
||||
node && node.setExecuting(false);
|
||||
if (pollute) {
|
||||
/* if (pollute) {
|
||||
path && this.clean(path);
|
||||
}
|
||||
} */
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue