一些定义上的修正
This commit is contained in:
parent
31c5a334eb
commit
b66d409e1f
|
|
@ -1,17 +1,13 @@
|
|||
import { DeduceCreateSingleOperation, DeduceRemoveOperation, DeduceUpdateOperation, EntityDict, OperationResult, OpRecord, SelectOption } from 'oak-domain/lib/types/Entity';
|
||||
import { EntityDict, OperationResult, OpRecord, SelectOption } from 'oak-domain/lib/types/Entity';
|
||||
import { StorageSchema } from "oak-domain/lib/types/Storage";
|
||||
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
|
||||
import { Checker, CheckerType, Context } from 'oak-domain/lib/types';
|
||||
import { TreeStore, TreeStoreOperateOption } from 'oak-memory-tree-store';
|
||||
interface CachStoreOperation extends TreeStoreOperateOption {
|
||||
inSync?: boolean;
|
||||
}
|
||||
export declare class CacheStore<ED extends EntityDict & BaseEntityDict, Cxt extends Context<ED>> extends TreeStore<ED, Cxt> {
|
||||
private executor;
|
||||
private getFullDataFn?;
|
||||
private resetInitialDataFn?;
|
||||
constructor(storageSchema: StorageSchema<ED>, contextBuilder: () => (store: CacheStore<ED, Cxt>) => Cxt, getFullDataFn?: () => any, resetInitialDataFn?: () => void);
|
||||
protected updateAbjointRow<T extends keyof ED>(entity: T, operation: DeduceCreateSingleOperation<ED[T]['Schema']> | DeduceUpdateOperation<ED[T]['Schema']> | DeduceRemoveOperation<ED[T]['Schema']>, context: Cxt, option?: CachStoreOperation): Promise<number>;
|
||||
operate<T extends keyof ED, OP extends TreeStoreOperateOption>(entity: T, operation: ED[T]['Operation'], context: Cxt, option: OP): Promise<OperationResult<ED>>;
|
||||
sync(opRecords: Array<OpRecord<ED>>, context: Cxt): Promise<void>;
|
||||
check<T extends keyof ED>(entity: T, operation: ED[T]['Operation'], context: Cxt, checkerTypes?: CheckerType[]): Promise<void>;
|
||||
|
|
@ -28,4 +24,3 @@ export declare class CacheStore<ED extends EntityDict & BaseEntityDict, Cxt exte
|
|||
*/
|
||||
resetInitialData(): void;
|
||||
}
|
||||
export {};
|
||||
|
|
|
|||
|
|
@ -17,28 +17,6 @@ var CacheStore = /** @class */ (function (_super) {
|
|||
_this.resetInitialDataFn = resetInitialDataFn;
|
||||
return _this;
|
||||
}
|
||||
CacheStore.prototype.updateAbjointRow = function (entity, operation, context, option) {
|
||||
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
||||
var action, data, attributes, key;
|
||||
var _a;
|
||||
return tslib_1.__generator(this, function (_b) {
|
||||
if (!(option === null || option === void 0 ? void 0 : option.inSync)) {
|
||||
action = operation.action, data = operation.data;
|
||||
if (action === 'create') {
|
||||
attributes = this.getSchema()[entity].attributes;
|
||||
for (key in attributes) {
|
||||
if (data[key] === undefined) {
|
||||
Object.assign(data, (_a = {},
|
||||
_a[key] = null,
|
||||
_a));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return [2 /*return*/, _super.prototype.updateAbjointRow.call(this, entity, operation, context, option)];
|
||||
});
|
||||
});
|
||||
};
|
||||
CacheStore.prototype.operate = function (entity, operation, context, option) {
|
||||
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
||||
var autoCommit, result, err_1;
|
||||
|
|
@ -100,9 +78,7 @@ var CacheStore = /** @class */ (function (_super) {
|
|||
_a.label = 2;
|
||||
case 2:
|
||||
_a.trys.push([2, 4, , 7]);
|
||||
return [4 /*yield*/, _super.prototype.sync.call(this, opRecords, context, {
|
||||
inSync: true,
|
||||
})];
|
||||
return [4 /*yield*/, _super.prototype.sync.call(this, opRecords, context, {})];
|
||||
case 3:
|
||||
result = _a.sent();
|
||||
return [3 /*break*/, 7];
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ export declare class DebugStore<ED extends EntityDict & BaseEntityDict, Cxt exte
|
|||
private executor;
|
||||
private rwLock;
|
||||
constructor(storageSchema: StorageSchema<ED>, contextBuilder: (cxtString?: string) => (store: RowStore<ED, Cxt>) => Promise<Cxt>);
|
||||
protected updateAbjointRow<T extends keyof ED, OP extends DebugStoreOperateOption>(entity: T, operation: ED[T]['CreateSingle'] | ED[T]['Update'] | ED[T]['Remove'], context: Cxt, option?: OP): Promise<number>;
|
||||
protected cascadeUpdate<T extends keyof ED, OP extends DebugStoreOperateOption>(entity: T, operation: DeduceCreateOperation<ED[T]["Schema"]> | DeduceUpdateOperation<ED[T]["Schema"]> | DeduceRemoveOperation<ED[T]["Schema"]>, context: Cxt, option: OP): Promise<import("oak-domain/lib/types").OperationResult<ED>>;
|
||||
protected cascadeSelect<T extends keyof ED, S extends ED[T]["Selection"], OP extends DebugStoreSelectOption>(entity: T, selection: S, context: Cxt, option: OP): Promise<SelectRowShape<ED[T]['Schema'], S['data']>[]>;
|
||||
operate<T extends keyof ED, OP extends DebugStoreOperateOption>(entity: T, operation: ED[T]['Operation'], context: Cxt, option: OP): Promise<import("oak-domain/lib/types").OperationResult<ED>>;
|
||||
|
|
|
|||
|
|
@ -15,26 +15,6 @@ var DebugStore = /** @class */ (function (_super) {
|
|||
_this.rwLock = new concurrent_1.RWLock();
|
||||
return _this;
|
||||
}
|
||||
DebugStore.prototype.updateAbjointRow = function (entity, operation, context, option) {
|
||||
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
||||
var action, data, attributes, key;
|
||||
var _a;
|
||||
return tslib_1.__generator(this, function (_b) {
|
||||
action = operation.action, data = operation.data;
|
||||
if (action === 'create') {
|
||||
attributes = this.getSchema()[entity].attributes;
|
||||
for (key in attributes) {
|
||||
if (data[key] === undefined) {
|
||||
Object.assign(data, (_a = {},
|
||||
_a[key] = null,
|
||||
_a));
|
||||
}
|
||||
}
|
||||
}
|
||||
return [2 /*return*/, _super.prototype.updateAbjointRow.call(this, entity, operation, context, option)];
|
||||
});
|
||||
});
|
||||
};
|
||||
DebugStore.prototype.cascadeUpdate = function (entity, operation, context, option) {
|
||||
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
||||
var result;
|
||||
|
|
|
|||
|
|
@ -5,24 +5,18 @@ import { NamedFilterItem, NamedSorterItem } from "../types/NamedCondition";
|
|||
import { Cache } from './cache';
|
||||
import { Pagination } from '../types/Pagination';
|
||||
import { Feature } from '../types/Feature';
|
||||
declare type Operation<ED extends EntityDict & BaseEntityDict, T extends keyof ED, OmitId extends boolean = false> = {
|
||||
oper: OmitId extends true ? Omit<ED[T]['Operation'], 'id'> : ED[T]['Operation'];
|
||||
beforeExecute?: () => Promise<void>;
|
||||
afterExecute?: () => Promise<void>;
|
||||
};
|
||||
declare abstract class Node<ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends Context<ED>, AD extends CommonAspectDict<ED, Cxt>> {
|
||||
protected entity: T;
|
||||
protected schema: StorageSchema<ED>;
|
||||
protected projection: ED[T]['Selection']['data'] | (() => Promise<ED[T]['Selection']['data']>);
|
||||
protected parent?: Node<ED, keyof ED, Cxt, AD> | VirtualNode;
|
||||
protected parent?: SingleNode<ED, keyof ED, Cxt, AD> | ListNode<ED, T, Cxt, AD> | VirtualNode;
|
||||
protected dirty?: boolean;
|
||||
protected cache: Cache<ED, Cxt, AD>;
|
||||
protected loading: boolean;
|
||||
protected loadingMore: boolean;
|
||||
protected executing: boolean;
|
||||
protected operations: Operation<ED, T>[];
|
||||
protected modiIds: string[] | undefined;
|
||||
constructor(entity: T, schema: StorageSchema<ED>, cache: Cache<ED, Cxt, AD>, projection: ED[T]['Selection']['data'] | (() => Promise<ED[T]['Selection']['data']>), parent?: Node<ED, keyof ED, Cxt, AD> | VirtualNode);
|
||||
constructor(entity: T, schema: StorageSchema<ED>, cache: Cache<ED, Cxt, AD>, projection: ED[T]['Selection']['data'] | (() => Promise<ED[T]['Selection']['data']>), parent?: SingleNode<ED, keyof ED, Cxt, AD> | ListNode<ED, T, Cxt, AD> | VirtualNode);
|
||||
getEntity(): T;
|
||||
getSchema(): StorageSchema<ED>;
|
||||
protected abstract getChildPath(child: Node<ED, keyof ED, Cxt, AD>): string;
|
||||
|
|
@ -40,7 +34,7 @@ declare abstract class Node<ED extends EntityDict & BaseEntityDict, T extends ke
|
|||
isLoadingMore(): boolean;
|
||||
isExecuting(): boolean;
|
||||
setExecuting(executing: boolean): void;
|
||||
getParent(): Node<ED, keyof ED, Cxt, AD> | VirtualNode | undefined;
|
||||
getParent(): SingleNode<ED, keyof ED, Cxt, AD> | ListNode<ED, T, Cxt, AD> | VirtualNode | undefined;
|
||||
protected getProjection(): Promise<ED[T]["Selection"]["data"]>;
|
||||
protected judgeRelation(attr: string): string | 0 | 1 | 2 | string[];
|
||||
protected contains(filter: ED[T]['Selection']['filter'], conditionalFilter: ED[T]['Selection']['filter']): boolean;
|
||||
|
|
@ -48,6 +42,7 @@ declare abstract class Node<ED extends EntityDict & BaseEntityDict, T extends ke
|
|||
}
|
||||
declare class ListNode<ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends Context<ED>, AD extends CommonAspectDict<ED, Cxt>> extends Node<ED, T, Cxt, AD> {
|
||||
private children;
|
||||
private updates;
|
||||
private filters;
|
||||
private sorters;
|
||||
private pagination;
|
||||
|
|
@ -58,7 +53,7 @@ declare class ListNode<ED extends EntityDict & BaseEntityDict, T extends keyof E
|
|||
checkIfClean(): void;
|
||||
onCacheSync(records: OpRecord<ED>[]): Promise<void>;
|
||||
destroy(): void;
|
||||
constructor(entity: T, schema: StorageSchema<ED>, cache: Cache<ED, Cxt, AD>, projection: ED[T]['Selection']['data'] | (() => Promise<ED[T]['Selection']['data']>), parent?: Node<ED, keyof ED, Cxt, AD> | VirtualNode, filters?: NamedFilterItem<ED, T>[], sorters?: NamedSorterItem<ED, T>[], pagination?: Pagination);
|
||||
constructor(entity: T, schema: StorageSchema<ED>, cache: Cache<ED, Cxt, AD>, projection: ED[T]['Selection']['data'] | (() => Promise<ED[T]['Selection']['data']>), parent?: SingleNode<ED, keyof ED, Cxt, AD> | VirtualNode, filters?: NamedFilterItem<ED, T>[], sorters?: NamedSorterItem<ED, T>[], pagination?: Pagination);
|
||||
getPagination(): Pagination;
|
||||
setPagination(pagination: Pagination): Promise<void>;
|
||||
getChild(path: string): SingleNode<ED, T, Cxt, AD> | undefined;
|
||||
|
|
@ -78,13 +73,22 @@ declare class ListNode<ED extends EntityDict & BaseEntityDict, T extends keyof E
|
|||
removeNamedSorter(sorter: NamedSorterItem<ED, T>, refresh?: boolean): Promise<void>;
|
||||
removeNamedSorterByName(name: string, refresh: boolean): Promise<void>;
|
||||
getFreshValue(): Promise<Array<SelectRowShape<ED[T]['Schema'], ED[T]['Selection']['data']>>>;
|
||||
addOperation(oper: Omit<ED[T]['Operation'], 'id'>, beforeExecute?: Operation<ED, T>['beforeExecute'], afterExecute?: Operation<ED, T>['afterExecute']): Promise<void>;
|
||||
addItem(item: Omit<ED[T]['CreateSingle']['data'], 'id'>, beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>): Promise<void>;
|
||||
removeItem(id: string, beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>): Promise<void>;
|
||||
recoverItem(id: string): Promise<void>;
|
||||
/**
|
||||
* 目前只支持根据itemId进行更新
|
||||
* @param data
|
||||
* @param id
|
||||
* @param beforeExecute
|
||||
* @param afterExecute
|
||||
*/
|
||||
updateItem(data: ED[T]['Update']['data'], id: string, action?: ED[T]['Action'], beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>): Promise<void>;
|
||||
updateItems(data: Record<string, ED[T]['Update']['data']>, action?: ED[T]['Action']): Promise<void>;
|
||||
doBeforeTrigger(): Promise<void>;
|
||||
doAfterTrigger(): Promise<void>;
|
||||
getParentFilter(childNode: SingleNode<ED, T, Cxt, AD>): Promise<ED[T]['Selection']['filter'] | undefined>;
|
||||
composeOperations(): Promise<(ED[T]["Operation"] & {
|
||||
entity: T;
|
||||
})[] | undefined>;
|
||||
composeOperations(): Promise<any[] | undefined>;
|
||||
getProjection(): Promise<ED[T]['Selection']['data']>;
|
||||
constructSelection(withParent?: true, disableOperation?: boolean): Promise<{
|
||||
data: ED[T]["Selection"]["data"];
|
||||
|
|
@ -100,7 +104,9 @@ declare class ListNode<ED extends EntityDict & BaseEntityDict, T extends keyof E
|
|||
declare class SingleNode<ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends Context<ED>, AD extends CommonAspectDict<ED, Cxt>> extends Node<ED, T, Cxt, AD> {
|
||||
private id?;
|
||||
private children;
|
||||
constructor(entity: T, schema: StorageSchema<ED>, cache: Cache<ED, Cxt, AD>, projection: ED[T]['Selection']['data'] | (() => Promise<ED[T]['Selection']['data']>), parent?: Node<ED, keyof ED, Cxt, AD> | VirtualNode, id?: string);
|
||||
private operation?;
|
||||
constructor(entity: T, schema: StorageSchema<ED>, cache: Cache<ED, Cxt, AD>, projection: ED[T]['Selection']['data'] | (() => Promise<ED[T]['Selection']['data']>), parent?: SingleNode<ED, keyof ED, Cxt, AD> | ListNode<ED, T, Cxt, AD> | VirtualNode, id?: string);
|
||||
private tryGetParentFilter;
|
||||
protected getChildPath(child: Node<ED, keyof ED, Cxt, AD>): string;
|
||||
setLoading(loading: boolean): void;
|
||||
checkIfClean(): void;
|
||||
|
|
@ -117,11 +123,14 @@ declare class SingleNode<ED extends EntityDict & BaseEntityDict, T extends keyof
|
|||
getFreshValue(disableOperation?: boolean): Promise<SelectRowShape<ED[T]['Schema'], ED[T]['Selection']['data']> | undefined>;
|
||||
doBeforeTrigger(): Promise<void>;
|
||||
doAfterTrigger(): Promise<void>;
|
||||
addOperation(oper: Omit<ED[T]['Operation'], 'id'>, beforeExecute?: Operation<ED, T>['beforeExecute'], afterExecute?: Operation<ED, T>['afterExecute']): Promise<void>;
|
||||
composeOperations(): Promise<(ED[T]["Operation"] & {
|
||||
create(data: Partial<Omit<ED[T]['CreateSingle']['data'], 'id'>>, beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>): Promise<void>;
|
||||
update(data: ED[T]['Update']['data'], action?: ED[T]['Action'], beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>): Promise<void>;
|
||||
remove(beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>): Promise<void>;
|
||||
composeOperations(): Promise<Array<{
|
||||
entity: T;
|
||||
})[] | undefined>;
|
||||
getProjection(withDecendants?: boolean): Promise<ED[keyof ED]["Selection"]["data"]>;
|
||||
operation: ED[T]['Update'];
|
||||
}> | undefined>;
|
||||
getProjection(withDecendants?: boolean): Promise<ED[T]["Selection"]["data"]>;
|
||||
refresh(): Promise<void>;
|
||||
clean(): void;
|
||||
getParentFilter<T2 extends keyof ED>(childNode: Node<ED, keyof ED, Cxt, AD>, disableOperation?: boolean): Promise<ED[T2]['Selection']['filter'] | undefined>;
|
||||
|
|
@ -133,7 +142,7 @@ declare class VirtualNode {
|
|||
getActiveModies(child: any): Promise<undefined>;
|
||||
setDirty(): void;
|
||||
addChild(path: string, child: SingleNode<any, any, any, any> | ListNode<any, any, any, any>): void;
|
||||
getChild(path: string): ListNode<any, any, any, any> | SingleNode<any, any, any, any> | undefined;
|
||||
getChild(path: string): SingleNode<any, any, any, any> | ListNode<any, any, any, any> | undefined;
|
||||
getParent(): undefined;
|
||||
destroy(): void;
|
||||
getFreshValue(): Promise<undefined>;
|
||||
|
|
@ -170,13 +179,19 @@ export declare class RunningTree<ED extends EntityDict & BaseEntityDict, Cxt ext
|
|||
destroyNode(path: string): void;
|
||||
getFreshValue(path: string): Promise<SelectRowShape<ED[keyof ED]["Schema"], ED[keyof ED]["Selection"]["data"]> | undefined> | Promise<SelectRowShape<ED[keyof ED]["Schema"], ED[keyof ED]["Selection"]["data"]>[]> | undefined;
|
||||
isDirty(path: string): boolean;
|
||||
addOperation<T extends keyof ED>(path: string, operation: Omit<ED[T]['Operation'], 'id'>, beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>): Promise<void>;
|
||||
addItem<T extends keyof ED>(path: string, data: Omit<ED[T]['CreateSingle']['data'], 'id'>, beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>): Promise<void>;
|
||||
removeItem(path: string, id: string, beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>): Promise<void>;
|
||||
updateItem<T extends keyof ED>(path: string, data: ED[T]['Update']['data'], id: string, action?: ED[T]['Action'], beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>): Promise<void>;
|
||||
recoverItem(path: string, id: string): Promise<void>;
|
||||
create<T extends keyof ED>(path: string, data: Omit<ED[T]['CreateSingle']['data'], 'id'>, beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>): Promise<void>;
|
||||
update<T extends keyof ED>(path: string, data: ED[T]['Update']['data'], action?: ED[T]['Action'], beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>): Promise<void>;
|
||||
remove(path: string, beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>): Promise<void>;
|
||||
isLoading(path: string): boolean;
|
||||
isLoadingMore(path: string): boolean;
|
||||
isExecuting(path: string): boolean;
|
||||
refresh(path: string): Promise<void>;
|
||||
loadMore(path: string): Promise<void>;
|
||||
getPagination<T extends keyof ED>(path: string): Pagination;
|
||||
getPagination(path: string): Pagination;
|
||||
setId(path: string, id: string): Promise<void>;
|
||||
unsetId(path: string): Promise<void>;
|
||||
getId(path: string): string | undefined;
|
||||
|
|
@ -193,14 +208,10 @@ export declare class RunningTree<ED extends EntityDict & BaseEntityDict, Cxt ext
|
|||
setNamedSorters<T extends keyof ED>(path: string, sorters: NamedSorterItem<ED, T>[], refresh?: boolean): Promise<void>;
|
||||
addNamedSorter<T extends keyof ED>(path: string, sorter: NamedSorterItem<ED, T>, refresh?: boolean): Promise<void>;
|
||||
removeNamedSorter<T extends keyof ED>(path: string, sorter: NamedSorterItem<ED, T>, refresh?: boolean): Promise<void>;
|
||||
removeNamedSorterByName<T extends keyof ED>(path: string, name: string, refresh?: boolean): Promise<void>;
|
||||
removeNamedSorterByName(path: string, name: string, refresh?: boolean): Promise<void>;
|
||||
tryExecute(path: string): Promise<boolean>;
|
||||
getOperations(path: string): Promise<any[] | (ED[keyof ED]["Operation"] & {
|
||||
entity: keyof ED;
|
||||
})[] | undefined>;
|
||||
execute<T extends keyof ED>(path: string, operation?: Omit<ED[T]['Operation'], 'id'>): Promise<any[] | (ED[keyof ED]["Operation"] & {
|
||||
entity: keyof ED;
|
||||
})[]>;
|
||||
getOperations(path: string): Promise<any[] | undefined>;
|
||||
execute<T extends keyof ED>(path: string, data?: ED[T]['Update']['data'] | Record<string, ED[T]['Update']['data']>, action?: ED[T]['Action']): Promise<any[]>;
|
||||
clean(path: string): Promise<void>;
|
||||
getRoot(): Record<string, VirtualNode | SingleNode<ED, keyof ED, Cxt, AD> | ListNode<ED, keyof ED, Cxt, AD>>;
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -7,3 +7,4 @@ export * from './utils/upload';
|
|||
export * from './types/Notification';
|
||||
export * from './types/Message';
|
||||
export * from './utils/bluetooth';
|
||||
export * from './types/Page';
|
||||
|
|
|
|||
|
|
@ -9,3 +9,4 @@ tslib_1.__exportStar(require("./utils/upload"), exports);
|
|||
tslib_1.__exportStar(require("./types/Notification"), exports);
|
||||
tslib_1.__exportStar(require("./types/Message"), exports);
|
||||
tslib_1.__exportStar(require("./utils/bluetooth"), exports);
|
||||
tslib_1.__exportStar(require("./types/Page"), exports);
|
||||
|
|
|
|||
|
|
@ -1,16 +1,12 @@
|
|||
import { Context, EntityDict } from 'oak-domain/lib/types';
|
||||
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
|
||||
import { OakComponentOption, ComponentFullThisType } from './types/Page';
|
||||
export declare function subscribe<ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends Context<ED>>(this: ComponentFullThisType<ED, T, Cxt>): void;
|
||||
export declare function unsubscribe<ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends Context<ED>>(this: ComponentFullThisType<ED, T, Cxt>): void;
|
||||
export declare function onPathSet<ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends Context<ED>>(this: ComponentFullThisType<ED, T, Cxt>, option: OakComponentOption<ED, T, Cxt, any, any, any, any, any, {}, {}, {}>): Promise<void>;
|
||||
export declare function reRender<ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends Context<ED>>(this: ComponentFullThisType<ED, T, Cxt>, option: OakComponentOption<ED, T, Cxt, any, any, any, any, any, {}, {}, {}>, extra?: Record<string, any>): Promise<void>;
|
||||
export declare function refresh<ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends Context<ED>>(this: ComponentFullThisType<ED, T, Cxt>): Promise<void>;
|
||||
export declare function loadMore<ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends Context<ED>>(this: ComponentFullThisType<ED, T, Cxt>): Promise<void>;
|
||||
export declare function execute<ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends Context<ED>>(this: ComponentFullThisType<ED, T, Cxt>, operation?: Omit<ED[T]['Operation'], 'id'>, path?: string): Promise<any[] | (ED[keyof ED]["Operation"] & {
|
||||
entity: keyof ED;
|
||||
})[]>;
|
||||
export declare function callPicker<ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends Context<ED>>(this: ComponentFullThisType<ED, T, Cxt>, attr: string, params?: Record<string, any>): void;
|
||||
export declare function setUpdateData<ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends Context<ED>>(this: ComponentFullThisType<ED, T, Cxt>, attr: string, data: any): Promise<void>;
|
||||
export declare function setMultiAttrUpdateData<ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends Context<ED>>(this: ComponentFullThisType<ED, T, Cxt>, data: Record<string, any>): Promise<void>;
|
||||
export declare function destroyNode<ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends Context<ED>>(this: ComponentFullThisType<ED, T, Cxt>): void;
|
||||
export declare function subscribe<ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends Context<ED>>(this: ComponentFullThisType<ED, T, any, Cxt>): void;
|
||||
export declare function unsubscribe<ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends Context<ED>>(this: ComponentFullThisType<ED, T, any, Cxt>): void;
|
||||
export declare function onPathSet<ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends Context<ED>>(this: ComponentFullThisType<ED, T, any, Cxt>, option: OakComponentOption<ED, T, Cxt, any, any, any, any, any, {}, {}, {}>): Promise<void>;
|
||||
export declare function reRender<ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends Context<ED>>(this: ComponentFullThisType<ED, T, any, Cxt>, option: OakComponentOption<ED, T, Cxt, any, any, any, any, any, {}, {}, {}>, extra?: Record<string, any>): Promise<void>;
|
||||
export declare function refresh<ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends Context<ED>>(this: ComponentFullThisType<ED, T, any, Cxt>): Promise<void>;
|
||||
export declare function loadMore<ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends Context<ED>>(this: ComponentFullThisType<ED, T, any, Cxt>): Promise<void>;
|
||||
export declare function execute<ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends Context<ED>>(this: ComponentFullThisType<ED, T, any, Cxt>, data?: ED[T]['Update']['data'] | Record<string, ED[T]['Update']['data']>, path?: string): Promise<any[]>;
|
||||
export declare function callPicker<ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends Context<ED>>(this: ComponentFullThisType<ED, T, any, Cxt>, attr: string, params?: Record<string, any>): void;
|
||||
export declare function destroyNode<ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends Context<ED>>(this: ComponentFullThisType<ED, T, any, Cxt>): void;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.destroyNode = exports.setMultiAttrUpdateData = exports.setUpdateData = exports.callPicker = exports.execute = exports.loadMore = exports.refresh = exports.reRender = exports.onPathSet = exports.unsubscribe = exports.subscribe = void 0;
|
||||
exports.destroyNode = exports.callPicker = exports.execute = exports.loadMore = exports.refresh = exports.reRender = exports.onPathSet = exports.unsubscribe = exports.subscribe = void 0;
|
||||
var tslib_1 = require("tslib");
|
||||
var assert_1 = require("oak-domain/lib/utils/assert");
|
||||
var types_1 = require("oak-domain/lib/types");
|
||||
|
|
@ -138,13 +138,11 @@ function onPathSet(option) {
|
|||
Object.assign(this.state, {
|
||||
oakEntity: entity2,
|
||||
oakFullpath: oakPath2,
|
||||
oakIsReady: true,
|
||||
});
|
||||
return [3 /*break*/, 4];
|
||||
case 2:
|
||||
Object.assign(this.state, {
|
||||
oakFullpath: oakPath2,
|
||||
oakIsReady: true,
|
||||
});
|
||||
// 创建virtualNode
|
||||
return [4 /*yield*/, features.runningTree.createNode({
|
||||
|
|
@ -265,7 +263,6 @@ function reRender(option, extra) {
|
|||
this.setState(data);
|
||||
return [3 /*break*/, 15];
|
||||
case 11:
|
||||
if (!this.state.oakFullpath) return [3 /*break*/, 15];
|
||||
if (!formData) return [3 /*break*/, 13];
|
||||
return [4 /*yield*/, formData.call(this, {
|
||||
features: features,
|
||||
|
|
@ -346,53 +343,26 @@ function loadMore() {
|
|||
});
|
||||
}
|
||||
exports.loadMore = loadMore;
|
||||
function execute(operation, path) {
|
||||
function execute(data, path) {
|
||||
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
||||
var fullpath, result, err_4, attrs, entity_1, message, attrNames;
|
||||
var _this = this;
|
||||
var fullpath, result;
|
||||
return tslib_1.__generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
if (this.state.oakExecuting) {
|
||||
throw new Error('请仔细设计按钮状态,不要允许重复点击!');
|
||||
}
|
||||
_a.label = 1;
|
||||
fullpath = path ? "".concat(this.state.oakFullpath, ".").concat(path) : this.state.oakFullpath;
|
||||
return [4 /*yield*/, this.features.runningTree.execute(fullpath, data)];
|
||||
case 1:
|
||||
_a.trys.push([1, 4, , 5]);
|
||||
fullpath = path
|
||||
? "".concat(this.state.oakFullpath, ".").concat(path)
|
||||
: this.state.oakFullpath;
|
||||
return [4 /*yield*/, this.features.runningTree.execute(fullpath, operation)];
|
||||
case 2:
|
||||
result = _a.sent();
|
||||
return [4 /*yield*/, this.setMessage({
|
||||
type: 'success',
|
||||
content: '操作成功',
|
||||
})];
|
||||
case 3:
|
||||
case 2:
|
||||
_a.sent();
|
||||
return [2 /*return*/, result];
|
||||
case 4:
|
||||
err_4 = _a.sent();
|
||||
if (err_4 instanceof types_1.OakUserException) {
|
||||
if (err_4 instanceof types_1.OakInputIllegalException) {
|
||||
attrs = err_4.getAttributes();
|
||||
entity_1 = err_4.getEntity();
|
||||
message = err_4.message;
|
||||
attrNames = attrs.map(function (attr) { return _this.t("".concat(entity_1, ":attr.").concat(attr)); }).filter(function (ele) { return !!ele; });
|
||||
this.setMessage({
|
||||
type: 'error',
|
||||
content: attrNames.length > 0 ? "\u300C".concat(attrNames.join(','), "\u300D").concat(message) : message,
|
||||
});
|
||||
throw err_4;
|
||||
}
|
||||
}
|
||||
this.setMessage({
|
||||
type: 'error',
|
||||
content: err_4.message,
|
||||
});
|
||||
throw err_4;
|
||||
case 5: return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
@ -421,62 +391,6 @@ function callPicker(attr, params) {
|
|||
});
|
||||
}
|
||||
exports.callPicker = callPicker;
|
||||
function setUpdateData(attr, data) {
|
||||
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
||||
var _a, _b;
|
||||
return tslib_1.__generator(this, function (_c) {
|
||||
switch (_c.label) {
|
||||
case 0:
|
||||
(0, assert_1.assert)(attr.indexOf('.') === -1, 'setUpdateData只能设置当前对象属性,子层对象请写完整的addOperation');
|
||||
if (!this.props.oakId) return [3 /*break*/, 1];
|
||||
return [2 /*return*/, this.addOperation({
|
||||
action: 'update',
|
||||
data: (_a = {},
|
||||
_a[attr] = data,
|
||||
_a)
|
||||
})];
|
||||
case 1: return [4 /*yield*/, this.addOperation({
|
||||
action: 'create',
|
||||
data: (_b = {},
|
||||
_b[attr] = data,
|
||||
_b)
|
||||
})];
|
||||
case 2:
|
||||
_c.sent();
|
||||
_c.label = 3;
|
||||
case 3: return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
exports.setUpdateData = setUpdateData;
|
||||
function setMultiAttrUpdateData(data) {
|
||||
return tslib_1.__awaiter(this, void 0, void 0, function () {
|
||||
var key;
|
||||
return tslib_1.__generator(this, function (_a) {
|
||||
switch (_a.label) {
|
||||
case 0:
|
||||
for (key in data) {
|
||||
(0, assert_1.assert)(key.indexOf('.') === -1, 'setMultiAttrUpdateData只能设置当前对象属性,子层对象请写完整的addOperation');
|
||||
}
|
||||
if (!this.props.oakId) return [3 /*break*/, 1];
|
||||
return [2 /*return*/, this.addOperation({
|
||||
action: 'update',
|
||||
data: data,
|
||||
})];
|
||||
case 1: return [4 /*yield*/, this.addOperation({
|
||||
action: 'create',
|
||||
data: data,
|
||||
})];
|
||||
case 2:
|
||||
_a.sent();
|
||||
_a.label = 3;
|
||||
case 3: return [2 /*return*/];
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
exports.setMultiAttrUpdateData = setMultiAttrUpdateData;
|
||||
function destroyNode() {
|
||||
(0, assert_1.assert)(this.state.oakFullpath);
|
||||
this.features.runningTree.destroyNode(this.state.oakFullpath);
|
||||
|
|
|
|||
166
lib/page.web.js
166
lib/page.web.js
|
|
@ -21,7 +21,7 @@ var OakComponentBase = /** @class */ (function (_super) {
|
|||
page_common_1.unsubscribe.call(this);
|
||||
};
|
||||
OakComponentBase.prototype.onPathSet = function () {
|
||||
return page_common_1.onPathSet.call(this, this.option);
|
||||
return page_common_1.onPathSet.call(this, this.oakOption);
|
||||
};
|
||||
OakComponentBase.prototype.triggerEvent = function (name, detail, options) {
|
||||
};
|
||||
|
|
@ -77,7 +77,7 @@ var OakComponentBase = /** @class */ (function (_super) {
|
|||
return this.features.message.consumeMessage();
|
||||
};
|
||||
OakComponentBase.prototype.reRender = function (extra) {
|
||||
return page_common_1.reRender.call(this, this.option, extra);
|
||||
return page_common_1.reRender.call(this, this.oakOption, extra);
|
||||
};
|
||||
OakComponentBase.prototype.navigateTo = function (options, state, disableNamespace) {
|
||||
var url = options.url, rest = tslib_1.__rest(options, ["url"]);
|
||||
|
|
@ -184,11 +184,28 @@ var OakComponentBase = /** @class */ (function (_super) {
|
|||
return this.props.navigate(url2, { replace: true });
|
||||
}
|
||||
} */
|
||||
OakComponentBase.prototype.addOperation = function (operation, beforeExecute, afterExecute, path) {
|
||||
var path2 = path ? "".concat(this.state.oakFullpath, ".").concat(path) : this.state.oakFullpath;
|
||||
return this.features.runningTree.addOperation(path2, operation, beforeExecute, afterExecute);
|
||||
OakComponentBase.prototype.addItem = function (data, beforeExecute, afterExecute) {
|
||||
return this.features.runningTree.addItem(this.state.oakFullpath, data, beforeExecute, afterExecute);
|
||||
};
|
||||
OakComponentBase.prototype.cleanOperation = function (path) {
|
||||
OakComponentBase.prototype.removeItem = function (id, beforeExecute, afterExecute) {
|
||||
return this.features.runningTree.removeItem(this.state.oakFullpath, id, beforeExecute, afterExecute);
|
||||
};
|
||||
OakComponentBase.prototype.updateItem = function (data, id, action, beforeExecute, afterExecute) {
|
||||
return this.features.runningTree.updateItem(this.state.oakFullpath, data, id, action, beforeExecute, afterExecute);
|
||||
};
|
||||
OakComponentBase.prototype.recoverItem = function (id) {
|
||||
return this.features.runningTree.recoverItem(this.state.oakFullpath, id);
|
||||
};
|
||||
OakComponentBase.prototype.create = function (data, beforeExecute, afterExecute) {
|
||||
return this.features.runningTree.create(this.state.oakFullpath, data, beforeExecute, afterExecute);
|
||||
};
|
||||
OakComponentBase.prototype.update = function (data, action, beforeExecute, afterExecute) {
|
||||
return this.features.runningTree.update(this.state.oakFullpath, data, action, beforeExecute, afterExecute);
|
||||
};
|
||||
OakComponentBase.prototype.remove = function (beforeExecute, afterExecute) {
|
||||
return this.features.runningTree.remove(this.state.oakFullpath, beforeExecute, afterExecute);
|
||||
};
|
||||
OakComponentBase.prototype.clean = function (path) {
|
||||
var path2 = path ? "".concat(this.state.oakFullpath, ".").concat(path) : this.state.oakFullpath;
|
||||
return this.features.runningTree.clean(path2);
|
||||
};
|
||||
|
|
@ -199,8 +216,8 @@ var OakComponentBase = /** @class */ (function (_super) {
|
|||
if (params === void 0) { params = {}; }
|
||||
return page_common_1.callPicker.call(this, attr, params);
|
||||
};
|
||||
OakComponentBase.prototype.execute = function (operation) {
|
||||
return page_common_1.execute.call(this, operation);
|
||||
OakComponentBase.prototype.execute = function (data) {
|
||||
return page_common_1.execute.call(this, data);
|
||||
};
|
||||
OakComponentBase.prototype.getFreshValue = function (path) {
|
||||
var path2 = path ? "".concat(this.state.oakFullpath, ".").concat(path) : this.state.oakFullpath;
|
||||
|
|
@ -220,12 +237,6 @@ var OakComponentBase = /** @class */ (function (_super) {
|
|||
OakComponentBase.prototype.refresh = function () {
|
||||
return page_common_1.refresh.call(this);
|
||||
};
|
||||
OakComponentBase.prototype.setUpdateData = function (attr, data) {
|
||||
return page_common_1.setUpdateData.call(this, attr, data);
|
||||
};
|
||||
OakComponentBase.prototype.setMultiAttrUpdateData = function (data) {
|
||||
return page_common_1.setMultiAttrUpdateData.call(this, data);
|
||||
};
|
||||
OakComponentBase.prototype.loadMore = function () {
|
||||
return page_common_1.loadMore.call(this);
|
||||
};
|
||||
|
|
@ -477,34 +488,141 @@ function translateObservers(observers) {
|
|||
}
|
||||
var DEFAULT_REACH_BOTTOM_DISTANCE = 50;
|
||||
function createComponent(option, features) {
|
||||
var _a = option, data = _a.data, projection = _a.projection, properties = _a.properties, entity = _a.entity, methods = _a.methods, lifetimes = _a.lifetimes, observers = _a.observers, render = _a.render, path = _a.path;
|
||||
var _a = option, data = _a.data, methods = _a.methods, lifetimes = _a.lifetimes, observers = _a.observers, getRender = _a.getRender, path = _a.path;
|
||||
var fn = translateObservers(observers).fn;
|
||||
var OakComponentWrapper = /** @class */ (function (_super) {
|
||||
tslib_1.__extends(OakComponentWrapper, _super);
|
||||
function OakComponentWrapper(props) {
|
||||
var _a;
|
||||
var _this = _super.call(this, props) || this;
|
||||
_this.features = features;
|
||||
_this.option = option;
|
||||
_this.oakOption = option;
|
||||
_this.isReachBottom = false;
|
||||
_this.scrollEvent = function () {
|
||||
_this.checkReachBottom();
|
||||
};
|
||||
var methodProps = {
|
||||
t: function (key, params) { return _this.t(key, params); },
|
||||
execute: function (data) {
|
||||
return _this.execute(data);
|
||||
},
|
||||
refresh: function () {
|
||||
return _this.refresh();
|
||||
},
|
||||
setNotification: function (data) {
|
||||
return _this.setNotification(data);
|
||||
},
|
||||
setMessage: function (data) {
|
||||
return _this.setMessage(data);
|
||||
},
|
||||
navigateTo: function (options, state, disableNamespace) {
|
||||
return _this.navigateTo(options, state, disableNamespace);
|
||||
},
|
||||
navigateBack: function (options) {
|
||||
return _this.navigateBack(options);
|
||||
},
|
||||
redirectTo: function (options, state, disableNamespace) {
|
||||
return _this.redirectTo(options, state, disableNamespace);
|
||||
},
|
||||
clean: function (path) {
|
||||
return _this.clean(path);
|
||||
}
|
||||
};
|
||||
if (option.isList) {
|
||||
Object.assign(methodProps, {
|
||||
addItem: function (data, beforeExecute, afterExecute) {
|
||||
return _this.addItem(data, beforeExecute, afterExecute);
|
||||
},
|
||||
removeItem: function (id, beforeExecute, afterExecute) {
|
||||
return _this.removeItem(id, beforeExecute, afterExecute);
|
||||
},
|
||||
updateItem: function (data, id, action, beforeExecute, afterExecute) {
|
||||
return _this.updateItem(data, id, action, beforeExecute, afterExecute);
|
||||
},
|
||||
setFilters: function (filters) {
|
||||
return _this.setFilters(filters);
|
||||
},
|
||||
addNamedFilter: function (filter, refresh) {
|
||||
return _this.addNamedFilter(filter, refresh);
|
||||
},
|
||||
removeNamedFilter: function (filter, refresh) {
|
||||
return _this.removeNamedFilter(filter, refresh);
|
||||
},
|
||||
removeNamedFilterByName: function (name, refresh) {
|
||||
return _this.removeNamedFilterByName(name, refresh);
|
||||
},
|
||||
setNamedSorters: function (sorters) {
|
||||
return _this.setNamedSorters(sorters);
|
||||
},
|
||||
addNamedSorter: function (sorter, refresh) {
|
||||
return _this.addNamedSorter(sorter, refresh);
|
||||
},
|
||||
removeNamedSorter: function (sorter, refresh) {
|
||||
return _this.removeNamedSorter(sorter, refresh);
|
||||
},
|
||||
removeNamedSorterByName: function (name, refresh) {
|
||||
return _this.removeNamedSorterByName(name, refresh);
|
||||
},
|
||||
setPageSize: function (pageSize) {
|
||||
return _this.setPageSize(pageSize);
|
||||
},
|
||||
setCurrentPage: function (current) {
|
||||
return _this.setCurrentPage(current);
|
||||
},
|
||||
loadMore: function () {
|
||||
return _this.loadMore();
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
Object.assign(methodProps, {
|
||||
create: function (data, beforeExecute, afterExecute) {
|
||||
return _this.create(data, beforeExecute, afterExecute);
|
||||
},
|
||||
update: function (data, action, beforeExecute, afterExecute) {
|
||||
return _this.update(data, action, beforeExecute, afterExecute);
|
||||
},
|
||||
remove: function (beforeExecute, afterExecute) {
|
||||
return _this.remove(beforeExecute, afterExecute);
|
||||
},
|
||||
});
|
||||
}
|
||||
if (methods) {
|
||||
for (var m in methods) {
|
||||
Object.assign(_this, (_a = {},
|
||||
_a[m] = methods[m].bind(_this),
|
||||
var _loop_1 = function (m) {
|
||||
var _a, _b;
|
||||
Object.assign(this_1, (_a = {},
|
||||
_a[m] = function () {
|
||||
var _a;
|
||||
var args = [];
|
||||
for (var _i = 0; _i < arguments.length; _i++) {
|
||||
args[_i] = arguments[_i];
|
||||
}
|
||||
return (_a = methods[m]).call.apply(_a, tslib_1.__spreadArray([_this], tslib_1.__read(args), false));
|
||||
},
|
||||
_a));
|
||||
Object.assign(methodProps, (_b = {},
|
||||
_b[m] = function () {
|
||||
var _a;
|
||||
var args = [];
|
||||
for (var _i = 0; _i < arguments.length; _i++) {
|
||||
args[_i] = arguments[_i];
|
||||
}
|
||||
return (_a = methods[m]).call.apply(_a, tslib_1.__spreadArray([_this], tslib_1.__read(args), false));
|
||||
},
|
||||
_b));
|
||||
};
|
||||
var this_1 = this;
|
||||
for (var m in methods) {
|
||||
_loop_1(m);
|
||||
}
|
||||
}
|
||||
_this.state = Object.assign({}, data, {
|
||||
oakLoading: false,
|
||||
oakLoadingMore: false,
|
||||
oakPullDownRefreshLoading: false,
|
||||
oakIsReady: false,
|
||||
oakExecuting: false,
|
||||
oakDirty: false,
|
||||
});
|
||||
_this.methodProps = methodProps;
|
||||
(lifetimes === null || lifetimes === void 0 ? void 0 : lifetimes.created) && lifetimes.created.call(_this);
|
||||
return _this;
|
||||
}
|
||||
|
|
@ -596,9 +714,9 @@ function createComponent(option, features) {
|
|||
};
|
||||
OakComponentWrapper.prototype.render = function () {
|
||||
var _this = this;
|
||||
var Render = render.call(this);
|
||||
var oakPullDownRefreshLoading = this.state.oakPullDownRefreshLoading;
|
||||
var _a = this.props.oakDisablePulldownRefresh, oakDisablePulldownRefresh = _a === void 0 ? false : _a;
|
||||
var Render = getRender.call(this);
|
||||
if (this.supportPullDownRefresh() && !oakDisablePulldownRefresh) {
|
||||
var Child = react_1.default.cloneElement((0, jsx_runtime_1.jsx)(web_1.PullToRefresh, { onRefresh: function () { return tslib_1.__awaiter(_this, void 0, void 0, function () {
|
||||
return tslib_1.__generator(this, function (_a) {
|
||||
|
|
@ -619,10 +737,10 @@ function createComponent(option, features) {
|
|||
finish: this.t('common:ptrFinish'),
|
||||
} }), {
|
||||
getScrollContainer: function () { return document.body; },
|
||||
}, Render);
|
||||
}, (0, jsx_runtime_1.jsx)(Render, { methods: this.methodProps, data: tslib_1.__assign(tslib_1.__assign({}, this.state), this.props) }));
|
||||
return Child;
|
||||
}
|
||||
return Render;
|
||||
return (0, jsx_runtime_1.jsx)(Render, { methods: this.methodProps, data: tslib_1.__assign(tslib_1.__assign({}, this.state), this.props) });
|
||||
};
|
||||
return OakComponentWrapper;
|
||||
}(OakComponentBase));
|
||||
|
|
|
|||
|
|
@ -58,14 +58,15 @@ export declare type ComponentPublicThisType<ED extends EntityDict & BaseEntityDi
|
|||
props: ComponentProps<IsList, TProperty>;
|
||||
setState: (data: Partial<ComponentData<ED, T, FormedData, TData>>, callback?: () => void) => void;
|
||||
triggerEvent: <DetailType = any>(name: string, detail?: DetailType, options?: WechatMiniprogram.Component.TriggerEventOption) => void;
|
||||
} & TMethod & OakCommonComponentMethods<ED, T> & (IsList extends true ? OakListComponentMethods<ED, T> : {});
|
||||
export declare type ComponentFullThisType<ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends Context<ED>> = {
|
||||
} & TMethod & OakCommonComponentMethods<ED, T> & (IsList extends true ? OakListComponentMethods<ED, T> : OakSingleComponentMethods<ED, T>);
|
||||
export declare type ComponentFullThisType<ED extends EntityDict & BaseEntityDict, T extends keyof ED, IsList extends boolean, Cxt extends Context<ED>> = {
|
||||
subscribed?: () => void;
|
||||
features: BasicFeatures<ED, Cxt, CommonAspectDict<ED, Cxt>>;
|
||||
state: OakComponentData<ED, T>;
|
||||
props: ComponentProps<true, {}>;
|
||||
setState: (data: Partial<OakComponentData<ED, T>>, callback?: () => void) => void;
|
||||
triggerEvent: <DetailType = any>(name: string, detail?: DetailType, options?: WechatMiniprogram.Component.TriggerEventOption) => void;
|
||||
} & OakCommonComponentMethods<ED, T> & OakListComponentMethods<ED, T> & OakHiddenComponentMethods;
|
||||
} & OakCommonComponentMethods<ED, T> & (IsList extends true ? OakListComponentMethods<ED, T> : OakSingleComponentMethods<ED, T>);
|
||||
export declare type OakComponentOption<ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends Context<ED>, AD extends Record<string, Aspect<ED, Cxt>>, FD extends Record<string, Feature>, Proj extends ED[T]['Selection']['data'], FormedData extends Record<string, any>, IsList extends boolean, TData extends Record<string, any>, TProperty extends WechatMiniprogram.Component.PropertyOption, TMethod extends Record<string, Function>> = ComponentOption<ED, T, Cxt, AD, FD, Proj, FormedData, IsList, TProperty> & Partial<{
|
||||
data?: TData;
|
||||
properties: TProperty;
|
||||
|
|
@ -146,20 +147,22 @@ export declare type OakCommonComponentMethods<ED extends EntityDict & BaseEntity
|
|||
delta: number;
|
||||
}) => Promise<void>;
|
||||
redirectTo: <T2 extends keyof ED>(options: Parameters<typeof wx.redirectTo>[0] & OakNavigateToParameters<ED, T2>, state?: Record<string, any>, disableNamespace?: boolean) => Promise<void>;
|
||||
addOperation: (operation: Omit<ED[T]['Operation'], 'id'>, beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>, path?: string) => Promise<void>;
|
||||
cleanOperation: (path?: string) => void;
|
||||
clean: (path?: string) => void;
|
||||
t(key: string, params?: object): string;
|
||||
callPicker: (attr: string, params: Record<string, any>) => void;
|
||||
execute: (operation?: Omit<ED[T]['Operation'], 'id'>, path?: string) => Promise<ED[T]['Operation'][]>;
|
||||
execute: (data?: ED[T]['Update']['data'] | Record<string, ED[T]['Update']['data']>, path?: string) => Promise<ED[T]['Operation'][]>;
|
||||
checkOperation: (ntity: T, action: ED[T]['Action'], filter?: ED[T]['Update']['filter'], checkerTypes?: CheckerType[]) => Promise<boolean>;
|
||||
tryExecute: (path?: string) => Promise<boolean>;
|
||||
getOperations: (path?: string) => Promise<ED[T]['Operation'][] | undefined>;
|
||||
refresh: (extra?: any) => Promise<void>;
|
||||
setUpdateData: (data: string, attr: any) => Promise<void>;
|
||||
setMultiAttrUpdateData: (data: Record<string, any>) => Promise<void>;
|
||||
refresh: () => Promise<void>;
|
||||
};
|
||||
export declare type OakSingleComponentMethods<ED extends EntityDict & BaseEntityDict, T extends keyof ED> = {
|
||||
setId: (id: string) => Promise<void>;
|
||||
unsetId: () => void;
|
||||
getId: () => string | undefined;
|
||||
create: (data: Omit<ED[T]['CreateSingle']['data'], 'id'>, beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>) => Promise<void>;
|
||||
update: (data: ED[T]['Update']['data'], action?: ED[T]['Action'], beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>) => Promise<void>;
|
||||
remove: (beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>) => Promise<void>;
|
||||
};
|
||||
export declare type OakListComponentMethods<ED extends EntityDict & BaseEntityDict, T extends keyof ED> = {
|
||||
loadMore: () => Promise<void>;
|
||||
|
|
@ -178,6 +181,9 @@ export declare type OakListComponentMethods<ED extends EntityDict & BaseEntityDi
|
|||
getPagination: () => Pagination | undefined;
|
||||
setPageSize: (pageSize: number) => void;
|
||||
setCurrentPage: (current: number) => void;
|
||||
addItem: (data: Omit<ED[T]['CreateSingle']['data'], 'id'>, beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>) => Promise<void>;
|
||||
removeItem: (id: string, beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>) => Promise<void>;
|
||||
updateItem: (data: ED[T]['Update']['data'], id: string, action?: ED[T]['Action'], beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>) => Promise<void>;
|
||||
};
|
||||
declare type ComponentOnPropsChangeOption = {
|
||||
path?: string;
|
||||
|
|
@ -200,9 +206,15 @@ export declare type OakComponentData<ED extends EntityDict & BaseEntityDict, T e
|
|||
oakLoadingMore: boolean;
|
||||
oakPullDownRefreshLoading: boolean;
|
||||
oakEntity: T;
|
||||
oakIsReady: boolean;
|
||||
oakFullpath: string;
|
||||
oakLegalActions?: ED[T]['Action'][];
|
||||
};
|
||||
export declare type MakeOakComponent<ED extends EntityDict & BaseEntityDict, Cxt extends Context<ED>, AD extends Record<string, Aspect<ED, Cxt>>, FD extends Record<string, Feature>> = <T extends keyof ED, Proj extends ED[T]['Selection']['data'], FormedData extends WechatMiniprogram.Component.DataOption, IsList extends boolean, TData extends WechatMiniprogram.Component.DataOption, TProperty extends WechatMiniprogram.Component.PropertyOption, TMethod extends WechatMiniprogram.Component.MethodOption>(options: OakComponentOption<ED, T, Cxt, AD, FD, Proj, FormedData, IsList, TData, TProperty, TMethod>) => React.ComponentType<any>;
|
||||
export declare type WebComponentCommonMethodNames = 'setNotification' | 'setMessage' | 'navigateTo' | 'navigateBack' | 'redirectTo' | 'clean' | 't' | 'execute' | 'refresh';
|
||||
export declare type WebComponentListMethodNames = 'loadMore' | 'setFilters' | 'addNamedFilter' | 'removeNamedFilter' | 'removeNamedFilterByName' | 'setNamedSorters' | 'addNamedSorter' | 'removeNamedSorter' | 'removeNamedSorterByName' | 'setPageSize' | 'setCurrentPage' | 'addItem' | 'removeItem' | 'updateItem';
|
||||
export declare type WebComponentSingleMethodNames = 'create' | 'update' | 'remove';
|
||||
export declare type WebComponentProps<ED extends EntityDict & BaseEntityDict, T extends keyof ED, IsList extends boolean, TData extends WechatMiniprogram.Component.DataOption = {}, TMethod extends WechatMiniprogram.Component.MethodOption = {}> = {
|
||||
methods: TMethod & Pick<OakCommonComponentMethods<ED, T>, WebComponentCommonMethodNames> & (IsList extends true ? Pick<OakListComponentMethods<ED, T>, WebComponentListMethodNames> : Pick<OakSingleComponentMethods<ED, T>, WebComponentSingleMethodNames>);
|
||||
data: TData & OakComponentData<ED, T> & (IsList extends true ? OakListComponentProperties : {});
|
||||
};
|
||||
export {};
|
||||
|
|
|
|||
|
|
@ -6,9 +6,7 @@ import { Checker, CheckerType, Context, Trigger } from 'oak-domain/lib/types';
|
|||
import { TreeStore, TreeStoreOperateOption } from 'oak-memory-tree-store';
|
||||
import assert from 'assert';
|
||||
|
||||
interface CachStoreOperation extends TreeStoreOperateOption {
|
||||
inSync?: boolean;
|
||||
};
|
||||
interface CachStoreOperation extends TreeStoreOperateOption {};
|
||||
|
||||
export class CacheStore<
|
||||
ED extends EntityDict & BaseEntityDict,
|
||||
|
|
@ -32,24 +30,6 @@ export class CacheStore<
|
|||
this.resetInitialDataFn = resetInitialDataFn;
|
||||
}
|
||||
|
||||
protected async updateAbjointRow<T extends keyof ED>(entity: T, operation: DeduceCreateSingleOperation<ED[T]['Schema']> | DeduceUpdateOperation<ED[T]['Schema']> | DeduceRemoveOperation<ED[T]['Schema']>, context: Cxt, option?: CachStoreOperation): Promise<number> {
|
||||
if (!option?.inSync) {
|
||||
// 如果不是同步,需要补齐所有的null属性
|
||||
const { action, data } = operation;
|
||||
if (action === 'create') {
|
||||
const { attributes } = this.getSchema()[entity];
|
||||
for (const key in attributes) {
|
||||
if (data[key] === undefined) {
|
||||
Object.assign(data, {
|
||||
[key]: null,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.updateAbjointRow(entity, operation, context, option);
|
||||
}
|
||||
|
||||
async operate<T extends keyof ED, OP extends TreeStoreOperateOption>(
|
||||
entity: T,
|
||||
operation: ED[T]['Operation'],
|
||||
|
|
@ -89,9 +69,7 @@ export class CacheStore<
|
|||
let result;
|
||||
|
||||
try {
|
||||
result = await super.sync<CachStoreOperation>(opRecords, context, {
|
||||
inSync: true,
|
||||
});
|
||||
result = await super.sync<CachStoreOperation>(opRecords, context, {});
|
||||
} catch (err) {
|
||||
if (autoCommit) {
|
||||
await context.rollback();
|
||||
|
|
|
|||
|
|
@ -22,26 +22,6 @@ export class DebugStore<ED extends EntityDict & BaseEntityDict, Cxt extends Cont
|
|||
this.rwLock = new RWLock();
|
||||
}
|
||||
|
||||
protected async updateAbjointRow<T extends keyof ED, OP extends DebugStoreOperateOption>(
|
||||
entity: T,
|
||||
operation: ED[T]['CreateSingle'] | ED[T]['Update'] | ED[T]['Remove'],
|
||||
context: Cxt,
|
||||
option?: OP) {
|
||||
// 对于create动作,没有值的属性要置NULL
|
||||
const { action, data } = operation;
|
||||
if (action === 'create') {
|
||||
const { attributes } = this.getSchema()[entity];
|
||||
for (const key in attributes) {
|
||||
if (data[key] === undefined) {
|
||||
Object.assign(data, {
|
||||
[key]: null,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.updateAbjointRow(entity, operation, context, option);
|
||||
}
|
||||
|
||||
protected async cascadeUpdate<T extends keyof ED, OP extends DebugStoreOperateOption>(entity: T, operation: DeduceCreateOperation<ED[T]["Schema"]> | DeduceUpdateOperation<ED[T]["Schema"]> | DeduceRemoveOperation<ED[T]["Schema"]>, context: Cxt, option: OP) {
|
||||
if (!option.blockTrigger) {
|
||||
await this.executor.preOperation(entity, operation, context, option);
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ abstract class Node<ED extends EntityDict & BaseEntityDict, T extends keyof ED,
|
|||
// protected fullPath: string;
|
||||
protected schema: StorageSchema<ED>;
|
||||
protected projection: ED[T]['Selection']['data'] | (() => Promise<ED[T]['Selection']['data']>); // 只在Page层有
|
||||
protected parent?: Node<ED, keyof ED, Cxt, AD> | VirtualNode;
|
||||
protected parent?: SingleNode<ED, keyof ED, Cxt, AD> | ListNode<ED, T, Cxt, AD> | VirtualNode;
|
||||
protected dirty?: boolean;
|
||||
protected cache: Cache<ED, Cxt, AD>;
|
||||
protected loading: boolean;
|
||||
|
|
@ -34,7 +34,7 @@ abstract class Node<ED extends EntityDict & BaseEntityDict, T extends keyof ED,
|
|||
|
||||
constructor(entity: T, schema: StorageSchema<ED>, cache: Cache<ED, Cxt, AD>,
|
||||
projection: ED[T]['Selection']['data'] | (() => Promise<ED[T]['Selection']['data']>),
|
||||
parent?: Node<ED, keyof ED, Cxt, AD> | VirtualNode) {
|
||||
parent?: SingleNode<ED, keyof ED, Cxt, AD> | ListNode<ED, T, Cxt, AD> | VirtualNode) {
|
||||
this.entity = entity;
|
||||
this.schema = schema;
|
||||
this.cache = cache;
|
||||
|
|
@ -44,7 +44,7 @@ abstract class Node<ED extends EntityDict & BaseEntityDict, T extends keyof ED,
|
|||
this.loading = false;
|
||||
this.loadingMore = false;
|
||||
this.executing = false;
|
||||
this.modiIds = undefined;
|
||||
this.modiIds = undefined;
|
||||
}
|
||||
|
||||
getEntity() {
|
||||
|
|
@ -617,7 +617,7 @@ class ListNode<
|
|||
projection:
|
||||
| ED[T]['Selection']['data']
|
||||
| (() => Promise<ED[T]['Selection']['data']>),
|
||||
parent?: Node<ED, keyof ED, Cxt, AD> | VirtualNode,
|
||||
parent?: SingleNode<ED, keyof ED, Cxt, AD> | VirtualNode,
|
||||
filters?: NamedFilterItem<ED, T>[],
|
||||
sorters?: NamedSorterItem<ED, T>[],
|
||||
pagination?: Pagination
|
||||
|
|
@ -783,7 +783,7 @@ class ListNode<
|
|||
if (operation.action === 'create') {
|
||||
const { data } = operation;
|
||||
assert(!(data instanceof Array));
|
||||
createdIds.push(data.id);
|
||||
createdIds.push(data.id);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -818,15 +818,14 @@ class ListNode<
|
|||
filter: combineFilters([filter, { id: { $in: createdIds } }].filter(ele => !!ele), true),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
const result = await this.cache.tryRedoOperationsThenSelect(this.entity, selection, operations);
|
||||
return result;
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
async addItem(item: Omit<ED[T]['CreateSingle']['data'], 'id'>, beforeExecute: () => Promise<void>, afterExecute: () => Promise<void>) {
|
||||
assert(Object.keys(this.children).length === 0, ``);
|
||||
async addItem(item: Omit<ED[T]['CreateSingle']['data'], 'id'>, beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>) {
|
||||
const id = await generateNewId();
|
||||
assert(!this.updates[id]);
|
||||
this.updates[id] = {
|
||||
|
|
@ -841,19 +840,25 @@ class ListNode<
|
|||
this.setDirty();
|
||||
}
|
||||
|
||||
async removeItem(id: string, beforeExecute: () => Promise<void>, afterExecute: () => Promise<void>) {
|
||||
this.updates[id] = {
|
||||
beforeExecute,
|
||||
afterExecute,
|
||||
operation: {
|
||||
id: await generateNewId(),
|
||||
action: 'remove',
|
||||
data: {},
|
||||
filter: {
|
||||
id,
|
||||
},
|
||||
} as ED[T]['Remove'],
|
||||
};
|
||||
async removeItem(id: string, beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>) {
|
||||
if (this.updates[id] && this.updates[id].operation.action === 'create') {
|
||||
// 如果是新增项,在这里抵消
|
||||
unset(this.updates, id);
|
||||
}
|
||||
else {
|
||||
this.updates[id] = {
|
||||
beforeExecute,
|
||||
afterExecute,
|
||||
operation: {
|
||||
id: await generateNewId(),
|
||||
action: 'remove',
|
||||
data: {},
|
||||
filter: {
|
||||
id,
|
||||
},
|
||||
} as ED[T]['Remove'],
|
||||
};
|
||||
}
|
||||
this.setDirty();
|
||||
}
|
||||
|
||||
|
|
@ -863,11 +868,23 @@ class ListNode<
|
|||
unset(this.updates, id);
|
||||
}
|
||||
|
||||
async updateItem(data: ED[T]['Update']['data'], id: string, beforeExecute: () => Promise<void>, afterExecute: () => Promise<void>) {
|
||||
/**
|
||||
* 目前只支持根据itemId进行更新
|
||||
* @param data
|
||||
* @param id
|
||||
* @param beforeExecute
|
||||
* @param afterExecute
|
||||
*/
|
||||
async updateItem(data: ED[T]['Update']['data'], id: string, action?: ED[T]['Action'], beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>) {
|
||||
assert(Object.keys(this.children).length === 0, `更新子结点应该落在相应的component上`);
|
||||
if (this.updates[id]) {
|
||||
const { operation } = this.updates[id];
|
||||
const { data: dataOrigin } = operation;
|
||||
merge(dataOrigin, data);
|
||||
if (action && operation.action !== action) {
|
||||
assert(operation.action === 'update');
|
||||
operation.action = action;
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.updates[id] = {
|
||||
|
|
@ -875,7 +892,7 @@ class ListNode<
|
|||
afterExecute,
|
||||
operation: {
|
||||
id: await generateNewId(),
|
||||
action: 'update',
|
||||
action: action || 'update',
|
||||
data,
|
||||
filter: {
|
||||
id,
|
||||
|
|
@ -886,6 +903,12 @@ class ListNode<
|
|||
this.setDirty();
|
||||
}
|
||||
|
||||
async updateItems(data: Record<string, ED[T]['Update']['data']>, action?: ED[T]['Action']) {
|
||||
for (const id in data) {
|
||||
await this.updateItem(data[id], id, action);
|
||||
}
|
||||
}
|
||||
|
||||
async doBeforeTrigger(): Promise<void> {
|
||||
for (const k in this.updates) {
|
||||
const update = this.updates[k];
|
||||
|
|
@ -913,16 +936,7 @@ class ListNode<
|
|||
}
|
||||
|
||||
async getParentFilter(childNode: SingleNode<ED, T, Cxt, AD>): Promise<ED[T]['Selection']['filter'] | undefined> {
|
||||
/* let idx = 0;
|
||||
while (idx < this.ids!.length) {
|
||||
if (this.children[idx] === childNode) {
|
||||
return {
|
||||
id: this.ids![idx],
|
||||
}
|
||||
}
|
||||
idx++;
|
||||
} */
|
||||
for(const id in this.children) {
|
||||
for (const id in this.children) {
|
||||
if (this.children[id] === childNode) {
|
||||
return {
|
||||
id,
|
||||
|
|
@ -935,52 +949,32 @@ class ListNode<
|
|||
if (!this.dirty) {
|
||||
return;
|
||||
}
|
||||
const childOperations = await Promise.all(
|
||||
Object.keys(this.children).map(
|
||||
async ele => {
|
||||
const child = this.children[ele];
|
||||
const childOperations = await child.composeOperations();
|
||||
if (childOperations) {
|
||||
assert(childOperations.length === 1);
|
||||
return childOperations[0];
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
const operations: ED[T]['Operation'][] = cloneDeep(this.operations.map(ele => ele.oper));
|
||||
for (const oper of childOperations) {
|
||||
if (oper) {
|
||||
const {
|
||||
index,
|
||||
eliminated,
|
||||
} = findOperationToMerge(this.entity, this.schema, oper, operations);
|
||||
if (index) {
|
||||
// 可以合并
|
||||
const result = mergeOperationOper(this.entity, this.schema, oper, index);
|
||||
if (result) {
|
||||
// 说明相互抵消了
|
||||
pull(operations, index);
|
||||
}
|
||||
else {
|
||||
}
|
||||
}
|
||||
else {
|
||||
operations.push(oper);
|
||||
}
|
||||
|
||||
|
||||
for (const eli of eliminated) {
|
||||
if (eli) {
|
||||
pull(operations, eli);
|
||||
}
|
||||
}
|
||||
const childOperations: Record<string, ED[T]['Update']> = {};
|
||||
for (const id in this.children) {
|
||||
const childOperation = await this.children[id].composeOperations();
|
||||
if (childOperation) {
|
||||
assert(childOperation.length === 1);
|
||||
childOperations[id] = childOperation[0].operation;
|
||||
}
|
||||
}
|
||||
|
||||
const operations: ED[T]['Operation'][] = [];
|
||||
for (const id in this.updates) {
|
||||
const operation = cloneDeep(this.updates[id].operation);
|
||||
if (childOperations[id]) {
|
||||
const childOperation = childOperations[id];
|
||||
// 在list有operation在singleNode上也有目前只允许一种情况,即list上create,在single上update
|
||||
assert(operation.action === 'create' && childOperation.action === 'update');
|
||||
Object.assign(operation.data, childOperation.data);
|
||||
unset(childOperations, id);
|
||||
}
|
||||
operations.push(operation);
|
||||
}
|
||||
operations.push(...Object.values(childOperations));
|
||||
await repairOperations(this.entity, this.schema, operations);
|
||||
return operations.map(
|
||||
ele => Object.assign(ele, {
|
||||
ele => Object.assign({
|
||||
operation: ele,
|
||||
entity: this.entity,
|
||||
})
|
||||
);
|
||||
|
|
@ -1078,7 +1072,7 @@ class ListNode<
|
|||
if (getCount) {
|
||||
this.pagination.total = count;
|
||||
}
|
||||
|
||||
|
||||
const ids = data.map(
|
||||
ele => ele.id!
|
||||
) as string[];
|
||||
|
|
@ -1115,7 +1109,7 @@ class ListNode<
|
|||
|
||||
clean() {
|
||||
this.dirty = undefined;
|
||||
this.operations = [];
|
||||
this.updates = {};
|
||||
|
||||
for (const k in this.children) {
|
||||
this.children[k].clean();
|
||||
|
|
@ -1131,15 +1125,38 @@ class SingleNode<ED extends EntityDict & BaseEntityDict,
|
|||
private children: {
|
||||
[K: string]: SingleNode<ED, keyof ED, Cxt, AD> | ListNode<ED, keyof ED, Cxt, AD>;
|
||||
};
|
||||
private operation?: {
|
||||
beforeExecute?: () => Promise<void>;
|
||||
afterExecute?: () => Promise<void>;
|
||||
operation: ED[T]['CreateSingle'] | ED[T]['Update'] | ED[T]['Remove'];
|
||||
};
|
||||
|
||||
constructor(entity: T, schema: StorageSchema<ED>, cache: Cache<ED, Cxt, AD>,
|
||||
projection: ED[T]['Selection']['data'] | (() => Promise<ED[T]['Selection']['data']>),
|
||||
parent?: Node<ED, keyof ED, Cxt, AD> | VirtualNode, id?: string) {
|
||||
parent?: SingleNode<ED, keyof ED, Cxt, AD> | ListNode<ED, T, Cxt, AD> | VirtualNode, id?: string) {
|
||||
super(entity, schema, cache, projection, parent);
|
||||
this.children = {};
|
||||
if (id) {
|
||||
this.id = id;
|
||||
}
|
||||
else {
|
||||
// 若没有父结点上的filter,则一定是create动作
|
||||
this.tryGetParentFilter()
|
||||
.then(
|
||||
() => this.create({})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private async tryGetParentFilter(disableOperation?: boolean) {
|
||||
const parent = this.getParent();
|
||||
if (parent instanceof SingleNode) {
|
||||
const filter = await parent.getParentFilter<T>(this, disableOperation);
|
||||
return filter;
|
||||
}
|
||||
else if (parent instanceof ListNode) {
|
||||
return await parent.getParentFilter(this);
|
||||
}
|
||||
}
|
||||
|
||||
protected getChildPath(child: Node<ED, keyof ED, Cxt, AD>): string {
|
||||
|
|
@ -1159,7 +1176,7 @@ class SingleNode<ED extends EntityDict & BaseEntityDict,
|
|||
}
|
||||
|
||||
checkIfClean(): void {
|
||||
if (this.operations.length > 0) {
|
||||
if (this.operation) {
|
||||
return;
|
||||
}
|
||||
for (const k in this.children) {
|
||||
|
|
@ -1219,33 +1236,17 @@ class SingleNode<ED extends EntityDict & BaseEntityDict,
|
|||
operation: ED[keyof ED]['Operation'];
|
||||
}> : [];
|
||||
let filter = this.id && { id: this.id } as ED[T]['Selection']['filter'];
|
||||
if (!filter && !disableOperation) {
|
||||
// 可能是create
|
||||
const createOper = this.operations.find(
|
||||
(ele) => ele.oper.action === 'create'
|
||||
) as { oper: ED[T]['CreateSingle'] };
|
||||
if (createOper) {
|
||||
assert(createOper.oper.data.id);
|
||||
filter = {
|
||||
id: createOper.oper.data.id
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (!filter) {
|
||||
// 还可能是来自父级的外键
|
||||
const parent = this.getParent();
|
||||
if (parent instanceof ListNode || parent instanceof SingleNode) {
|
||||
filter = await parent.getParentFilter(this, disableOperation);
|
||||
}
|
||||
filter = await this.tryGetParentFilter(disableOperation);
|
||||
}
|
||||
if (filter) {
|
||||
if (!disableOperation) {
|
||||
operations.push(...this.operations.map(
|
||||
ele => ({
|
||||
entity: this.entity,
|
||||
operation: ele.oper,
|
||||
})
|
||||
));
|
||||
if (!disableOperation && this.operation) {
|
||||
operations.push({
|
||||
entity: this.entity,
|
||||
operation: this.operation.operation,
|
||||
});
|
||||
}
|
||||
const result = await this.cache.tryRedoOperationsThenSelect(this.entity, {
|
||||
data: projection,
|
||||
|
|
@ -1257,10 +1258,8 @@ class SingleNode<ED extends EntityDict & BaseEntityDict,
|
|||
|
||||
|
||||
async doBeforeTrigger(): Promise<void> {
|
||||
for (const operation of this.operations) {
|
||||
if (operation.beforeExecute) {
|
||||
await operation.beforeExecute();
|
||||
}
|
||||
if (this.operation?.beforeExecute) {
|
||||
await this.operation.beforeExecute();
|
||||
}
|
||||
|
||||
for (const k in this.children) {
|
||||
|
|
@ -1269,12 +1268,9 @@ class SingleNode<ED extends EntityDict & BaseEntityDict,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
async doAfterTrigger(): Promise<void> {
|
||||
for (const operation of this.operations) {
|
||||
if (operation.afterExecute) {
|
||||
await operation.afterExecute();
|
||||
}
|
||||
if (this.operation?.afterExecute) {
|
||||
await this.operation.afterExecute();
|
||||
}
|
||||
|
||||
for (const k in this.children) {
|
||||
|
|
@ -1283,133 +1279,125 @@ class SingleNode<ED extends EntityDict & BaseEntityDict,
|
|||
}
|
||||
}
|
||||
|
||||
async addOperation(oper: Omit<ED[T]['Operation'], 'id'>, beforeExecute?: Operation<ED, T>['beforeExecute'], afterExecute?: Operation<ED, T>['afterExecute']) {
|
||||
if (this.id) {
|
||||
if (oper.action === 'create') {
|
||||
oper.action = 'update';
|
||||
}
|
||||
if (!oper.filter) {
|
||||
Object.assign(oper, {
|
||||
async create(data: Partial<Omit<ED[T]['CreateSingle']['data'], 'id'>>, beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>) {
|
||||
const id = await generateNewId();
|
||||
this.id = id;
|
||||
this.operation = {
|
||||
operation: {
|
||||
id: await generateNewId(),
|
||||
action: 'create',
|
||||
data: Object.assign({}, data, { id }),
|
||||
},
|
||||
beforeExecute,
|
||||
afterExecute,
|
||||
};
|
||||
this.setDirty();
|
||||
}
|
||||
|
||||
async update(data: ED[T]['Update']['data'], action?: ED[T]['Action'], beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>) {
|
||||
if (!this.operation) {
|
||||
const operation: ED[T]['Update'] = {
|
||||
id: await generateNewId(),
|
||||
action: action || 'update',
|
||||
data,
|
||||
};
|
||||
if (this.id) {
|
||||
Object.assign(operation, {
|
||||
filter: {
|
||||
id: this.id,
|
||||
},
|
||||
});
|
||||
}
|
||||
else {
|
||||
assert(oper.filter.id === this.id);
|
||||
}
|
||||
}
|
||||
const operation = {
|
||||
oper,
|
||||
beforeExecute,
|
||||
afterExecute,
|
||||
};
|
||||
if (this.operations.length === 0) {
|
||||
// 处理一下create
|
||||
if (oper.action === 'create') {
|
||||
const id = await generateNewId();
|
||||
Object.assign(oper.data, {
|
||||
id,
|
||||
});
|
||||
}
|
||||
Object.assign(oper, { id: await generateNewId() });
|
||||
this.operations.push(operation as Operation<ED, T>);
|
||||
this.operation = {
|
||||
operation,
|
||||
beforeExecute,
|
||||
afterExecute,
|
||||
};
|
||||
}
|
||||
else {
|
||||
// singleNode上应当有且只有一个operation,无论什么情况
|
||||
const result = mergeOperationOper(this.entity, this.schema, oper, this.operations[0].oper);
|
||||
assert(!result);
|
||||
const { operation } = this.operation;
|
||||
assert(['create', 'update', action].includes(operation.action));
|
||||
Object.assign(operation.data, data);
|
||||
if (action && operation.action !== action) {
|
||||
operation.action = action;
|
||||
}
|
||||
}
|
||||
this.setDirty();
|
||||
}
|
||||
|
||||
async composeOperations() {
|
||||
async remove(beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>) {
|
||||
const operation: ED[T]['Remove'] = {
|
||||
id: await generateNewId(),
|
||||
action: 'remove',
|
||||
data: {},
|
||||
};
|
||||
if (this.id) {
|
||||
Object.assign(operation, {
|
||||
filter: {
|
||||
id: this.id,
|
||||
},
|
||||
});
|
||||
}
|
||||
this.operation = {
|
||||
operation,
|
||||
beforeExecute,
|
||||
afterExecute,
|
||||
};
|
||||
this.setDirty();
|
||||
}
|
||||
|
||||
async composeOperations(): Promise<Array<{
|
||||
entity: T;
|
||||
operation: ED[T]['Update'];
|
||||
}> | undefined> {
|
||||
if (!this.dirty) {
|
||||
return;
|
||||
}
|
||||
const childOperations = await Promise.all(
|
||||
Object.keys(this.children).map(
|
||||
async (ele) => {
|
||||
const child = this.children[ele];
|
||||
const childOperations = await child!.composeOperations();
|
||||
let subOper;
|
||||
if (childOperations) {
|
||||
if (child instanceof SingleNode) {
|
||||
subOper = childOperations[0];
|
||||
}
|
||||
else {
|
||||
assert(child instanceof ListNode);
|
||||
subOper = childOperations;
|
||||
}
|
||||
}
|
||||
let operation: ED[T]['Update'] = this.operation ? cloneDeep(this.operation.operation) : {
|
||||
id: await generateNewId(),
|
||||
action: 'update',
|
||||
data: {},
|
||||
}; // 如果本结点是create,在初始化时就应该置上operation
|
||||
if (this.id && !operation.filter) {
|
||||
Object.assign(operation, {
|
||||
filter: {
|
||||
id: this.id,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (subOper) {
|
||||
const sliceIdx = ele.indexOf(':');
|
||||
const ele2 = sliceIdx > 0 ? ele.slice(0, sliceIdx) : ele;
|
||||
if (this.id) {
|
||||
return {
|
||||
id: 'dummy', // 因为肯定会被merge掉,所以无所谓了
|
||||
action: 'update',
|
||||
data: {
|
||||
[ele2]: subOper,
|
||||
},
|
||||
filter: {
|
||||
id: this.id,
|
||||
}
|
||||
} as ED[T]['Operation'];
|
||||
}
|
||||
else {
|
||||
return {
|
||||
id: 'dummy', // 因为肯定会被merge掉,所以无所谓了
|
||||
action: 'create',
|
||||
data: {
|
||||
[ele2]: subOper,
|
||||
},
|
||||
} as ED[T]['Operation'];
|
||||
}
|
||||
for (const ele in this.children) {
|
||||
const child = this.children[ele];
|
||||
const childOperations = await child!.composeOperations();
|
||||
const sliceIdx = ele.indexOf(':');
|
||||
const ele2 = sliceIdx > 0 ? ele.slice(0, sliceIdx) : ele;
|
||||
if (childOperations) {
|
||||
if (child instanceof SingleNode) {
|
||||
assert(childOperations.length === 1);
|
||||
assert(!operation.data[ele2]); // 多对一的子结点不应该有多项
|
||||
Object.assign(operation.data, {
|
||||
[ele2]: childOperations[0].operation,
|
||||
});
|
||||
}
|
||||
else {
|
||||
assert(child instanceof ListNode);
|
||||
const childOpers = childOperations.map(
|
||||
ele => ele.operation
|
||||
);
|
||||
if (operation.data[ele2]) {
|
||||
operation.data[ele2].push(...childOpers);
|
||||
}
|
||||
else {
|
||||
operation.data[ele2] = childOpers;
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const operations: ED[T]['Operation'][] = [];
|
||||
if (this.operations.length > 0) {
|
||||
assert(this.operations.length === 1);
|
||||
// 这里不能直接改this.operations,只能克隆一个新的
|
||||
operations.push(cloneDeep(this.operations[0].oper));
|
||||
}
|
||||
else {
|
||||
if (this.id) {
|
||||
operations.push({
|
||||
id: await generateNewId(),
|
||||
action: 'update',
|
||||
data: {},
|
||||
filter: {
|
||||
id: this.id,
|
||||
} as any,
|
||||
});
|
||||
}
|
||||
else {
|
||||
operations.push({
|
||||
id: await generateNewId(),
|
||||
action: 'create',
|
||||
data: {
|
||||
id: await generateNewId(),
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
for (const oper of childOperations) {
|
||||
if (oper) {
|
||||
mergeOperationOper(this.entity, this.schema, oper, operations[0]); // SingleNode貌似不可能不merge成功
|
||||
}
|
||||
}
|
||||
await repairOperations(this.entity, this.schema, operations);
|
||||
return operations.map(
|
||||
ele => Object.assign(ele, {
|
||||
entity: this.entity,
|
||||
})
|
||||
);
|
||||
return [{
|
||||
entity: this.entity,
|
||||
operation,
|
||||
}];
|
||||
}
|
||||
|
||||
async getProjection(withDecendants?: boolean) {
|
||||
|
|
@ -1455,8 +1443,10 @@ class SingleNode<ED extends EntityDict & BaseEntityDict,
|
|||
|
||||
async refresh() {
|
||||
// SingleNode如果是非根结点,其id应该在第一次refresh的时候来确定
|
||||
if (!this.id) {
|
||||
let id = this.id;
|
||||
if (!id) {
|
||||
if (this.parent instanceof ListNode) {
|
||||
// list的子项不需要refresh,由list负责刷新数据
|
||||
assert(this.parent.getEntity() === this.entity);
|
||||
// id = this.parent.getChildPath(this);
|
||||
// this.id = id;
|
||||
|
|
@ -1465,16 +1455,16 @@ class SingleNode<ED extends EntityDict & BaseEntityDict,
|
|||
else if (this.parent instanceof SingleNode) {
|
||||
const parentFilter = await this.parent.getParentFilter(this);
|
||||
if (parentFilter) {
|
||||
const { id } = parentFilter;
|
||||
this.id = id;
|
||||
const { id: id2 } = parentFilter!;
|
||||
id = id2;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!this.id) {
|
||||
if (!id) {
|
||||
return;
|
||||
}
|
||||
const projection = await this.getProjection();
|
||||
const filter = { id: this.id };
|
||||
const filter = { id };
|
||||
this.setLoading(true);
|
||||
try {
|
||||
const { data: [value] } = await this.cache.refresh(this.entity, {
|
||||
|
|
@ -1496,14 +1486,14 @@ class SingleNode<ED extends EntityDict & BaseEntityDict,
|
|||
|
||||
clean() {
|
||||
this.dirty = undefined;
|
||||
this.operations = [];
|
||||
this.operation = undefined;
|
||||
|
||||
for (const child in this.children) {
|
||||
this.children[child]!.clean();
|
||||
}
|
||||
}
|
||||
|
||||
async getParentFilter<T2 extends keyof ED>(childNode: Node<ED, keyof ED, Cxt, AD>, disableOperation?: boolean): Promise<ED[T2]['Selection']['filter'] | undefined> {
|
||||
async getParentFilter<T2 extends keyof ED>(childNode: Node<ED, keyof ED, Cxt, AD>, disableOperation?: boolean): Promise<ED[T2]['Selection']['filter'] | undefined> {
|
||||
const value = (await this.getFreshValue(disableOperation))!;
|
||||
if (!value) {
|
||||
return;
|
||||
|
|
@ -1729,7 +1719,7 @@ export class RunningTree<
|
|||
ED extends EntityDict & BaseEntityDict,
|
||||
Cxt extends Context<ED>,
|
||||
AD extends CommonAspectDict<ED, Cxt>
|
||||
> extends Feature {
|
||||
> extends Feature {
|
||||
private cache: Cache<ED, Cxt, AD>;
|
||||
private schema: StorageSchema<ED>;
|
||||
private root: Record<
|
||||
|
|
@ -1769,7 +1759,7 @@ export class RunningTree<
|
|||
// 目前只有一种情况合法,即parentNode是list,列表中的位置移动引起的重用
|
||||
if (parentNode instanceof ListNode) {
|
||||
}
|
||||
else if (process.env.NODE_ENV === 'development') {
|
||||
else if (process.env.NODE_ENV === 'development') {
|
||||
console.error(`创建node时发现已有结点,不能重用。「${fullPath}」`);
|
||||
}
|
||||
return;
|
||||
|
|
@ -1777,6 +1767,7 @@ export class RunningTree<
|
|||
|
||||
if (entity) {
|
||||
if (isList) {
|
||||
assert(!(parentNode instanceof ListNode));
|
||||
node = new ListNode<ED, T, Cxt, AD>(
|
||||
entity,
|
||||
this.schema!,
|
||||
|
|
@ -1793,7 +1784,7 @@ export class RunningTree<
|
|||
this.schema!,
|
||||
this.cache,
|
||||
projection!,
|
||||
parentNode,
|
||||
parentNode as VirtualNode, // 过编译
|
||||
id
|
||||
);
|
||||
}
|
||||
|
|
@ -1860,11 +1851,52 @@ export class RunningTree<
|
|||
return node ? node.isDirty() : false;
|
||||
}
|
||||
|
||||
@Action
|
||||
async addOperation<T extends keyof ED>(path: string, operation: Omit<ED[T]['Operation'], 'id'>, beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>) {
|
||||
async addItem<T extends keyof ED>(path: string, data: Omit<ED[T]['CreateSingle']['data'], 'id'>, beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>) {
|
||||
const node = this.findNode(path);
|
||||
assert(node && (node instanceof SingleNode || node instanceof ListNode));
|
||||
await node.addOperation(operation, beforeExecute, afterExecute);
|
||||
assert(node instanceof ListNode);
|
||||
await node.addItem(data, beforeExecute, afterExecute);
|
||||
}
|
||||
|
||||
@Action
|
||||
async removeItem(path: string, id: string, beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>) {
|
||||
const node = this.findNode(path);
|
||||
assert(node instanceof ListNode);
|
||||
await node.removeItem(id, beforeExecute, afterExecute);
|
||||
}
|
||||
|
||||
@Action
|
||||
async updateItem<T extends keyof ED>(path: string, data: ED[T]['Update']['data'], id: string, action?: ED[T]['Action'], beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>) {
|
||||
const node = this.findNode(path);
|
||||
assert(node instanceof ListNode);
|
||||
await node.updateItem(data, id, action, beforeExecute, afterExecute);
|
||||
}
|
||||
|
||||
@Action
|
||||
async recoverItem(path: string, id: string) {
|
||||
const node = this.findNode(path);
|
||||
assert(node instanceof ListNode);
|
||||
await node.recoverItem(id);
|
||||
}
|
||||
|
||||
@Action
|
||||
async create<T extends keyof ED>(path: string, data: Omit<ED[T]['CreateSingle']['data'], 'id'>, beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>) {
|
||||
const node = this.findNode(path);
|
||||
assert(node instanceof SingleNode);
|
||||
await node.create(data, beforeExecute, afterExecute);
|
||||
}
|
||||
|
||||
@Action
|
||||
async update<T extends keyof ED>(path: string, data: ED[T]['Update']['data'], action?: ED[T]['Action'], beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>) {
|
||||
const node = this.findNode(path);
|
||||
assert (node instanceof SingleNode);
|
||||
await node.update(data, action, beforeExecute, afterExecute);
|
||||
}
|
||||
|
||||
@Action
|
||||
async remove(path: string, beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>) {
|
||||
const node = this.findNode(path);
|
||||
assert(node instanceof SingleNode);
|
||||
await node.remove(beforeExecute, afterExecute);
|
||||
}
|
||||
|
||||
isLoading(path: string) {
|
||||
|
|
@ -1904,7 +1936,7 @@ export class RunningTree<
|
|||
await node.loadMore();
|
||||
}
|
||||
|
||||
getPagination<T extends keyof ED>(path: string) {
|
||||
getPagination(path: string) {
|
||||
const node = this.findNode(path);
|
||||
assert(node instanceof ListNode);
|
||||
return node.getPagination();
|
||||
|
|
@ -2054,7 +2086,7 @@ export class RunningTree<
|
|||
}
|
||||
|
||||
@Action
|
||||
async removeNamedSorterByName<T extends keyof ED>(
|
||||
async removeNamedSorterByName(
|
||||
path: string,
|
||||
name: string,
|
||||
refresh: boolean = false
|
||||
|
|
@ -2080,11 +2112,16 @@ export class RunningTree<
|
|||
}
|
||||
|
||||
@Action
|
||||
async execute<T extends keyof ED>(path: string, operation?: Omit<ED[T]['Operation'], 'id'>) {
|
||||
async execute<T extends keyof ED>(path: string, data?: ED[T]['Update']['data'] | Record<string, ED[T]['Update']['data']>, action?: ED[T]['Action']) {
|
||||
const node = this.findNode(path)!;
|
||||
if (operation) {
|
||||
assert(node instanceof ListNode || node instanceof SingleNode);
|
||||
await node.addOperation(operation);
|
||||
if (data) {
|
||||
if(node instanceof SingleNode) {
|
||||
await node.update(data, action);
|
||||
}
|
||||
else {
|
||||
assert(node instanceof ListNode);
|
||||
node.updateItems(data);
|
||||
}
|
||||
}
|
||||
assert(node.isDirty());
|
||||
|
||||
|
|
@ -2093,7 +2130,7 @@ export class RunningTree<
|
|||
await node.doBeforeTrigger();
|
||||
const operations = (await node.composeOperations())!;
|
||||
|
||||
// 这里理论上virtualNode下面可以有多个不同的entity的组件,但实际中不应当出现这样的设计
|
||||
// 这里理论上virtualNode下面也可以有多个不同的entity的组件,但实际中不应当出现这样的设计
|
||||
const entities = uniq(
|
||||
operations.filter(ele => !!ele).map(
|
||||
ele => ele.entity
|
||||
|
|
@ -2102,7 +2139,7 @@ export class RunningTree<
|
|||
|
||||
await this.aspectWrapper.exec('operate', {
|
||||
entity: entities[0],
|
||||
operation: operations.filter(ele => !!ele),
|
||||
operation: operations.filter(ele => !!ele).map(ele => ele.operation),
|
||||
});
|
||||
|
||||
await node.doAfterTrigger();
|
||||
|
|
|
|||
|
|
@ -7,4 +7,5 @@ export * from './features/localStorage';
|
|||
export * from './utils/upload';
|
||||
export * from './types/Notification';
|
||||
export * from './types/Message';
|
||||
export * from './utils/bluetooth';
|
||||
export * from './utils/bluetooth';
|
||||
export * from './types/Page';
|
||||
|
|
@ -18,7 +18,7 @@ import { unset } from 'oak-domain/lib/utils/lodash';
|
|||
export function subscribe<
|
||||
ED extends EntityDict & BaseEntityDict,
|
||||
T extends keyof ED,
|
||||
Cxt extends Context<ED>>(this: ComponentFullThisType<ED, T, Cxt>): void {
|
||||
Cxt extends Context<ED>>(this: ComponentFullThisType<ED, T, any, Cxt>): void {
|
||||
if (!this.subscribed) {
|
||||
this.subscribed = FeactureSubscribe(() => this.reRender());
|
||||
}
|
||||
|
|
@ -27,7 +27,7 @@ export function subscribe<
|
|||
export function unsubscribe<
|
||||
ED extends EntityDict & BaseEntityDict,
|
||||
T extends keyof ED,
|
||||
Cxt extends Context<ED>>(this: ComponentFullThisType<ED, T, Cxt>): void {
|
||||
Cxt extends Context<ED>>(this: ComponentFullThisType<ED, T, any, Cxt>): void {
|
||||
if (this.subscribed) {
|
||||
this.subscribed();
|
||||
this.subscribed = undefined;
|
||||
|
|
@ -38,7 +38,7 @@ export async function onPathSet<
|
|||
ED extends EntityDict & BaseEntityDict,
|
||||
T extends keyof ED,
|
||||
Cxt extends Context<ED>>(
|
||||
this: ComponentFullThisType<ED, T, Cxt>,
|
||||
this: ComponentFullThisType<ED, T, any, Cxt>,
|
||||
option: OakComponentOption<ED, T, Cxt, any, any, any, any, any, {}, {}, {}>) {
|
||||
const { props, state } = this;
|
||||
const { oakPath, oakProjection, oakIsPicker, oakFilters, oakSorters, oakId } = props;
|
||||
|
|
@ -142,7 +142,7 @@ export async function reRender<
|
|||
ED extends EntityDict & BaseEntityDict,
|
||||
T extends keyof ED,
|
||||
Cxt extends Context<ED>>(
|
||||
this: ComponentFullThisType<ED, T, Cxt>,
|
||||
this: ComponentFullThisType<ED, T, any, Cxt>,
|
||||
option: OakComponentOption<ED, T, Cxt, any, any, any, any, any, {}, {}, {}>,
|
||||
extra?: Record<string, any>) {
|
||||
const { features } = this;
|
||||
|
|
@ -224,7 +224,7 @@ export async function reRender<
|
|||
});
|
||||
|
||||
this.setState(data);
|
||||
} else if (this.state.oakFullpath) {
|
||||
} else {
|
||||
const data: Record<string, any> = formData
|
||||
? await formData.call(this, {
|
||||
features,
|
||||
|
|
@ -244,7 +244,7 @@ export async function refresh<
|
|||
ED extends EntityDict & BaseEntityDict,
|
||||
T extends keyof ED,
|
||||
Cxt extends Context<ED>>(
|
||||
this: ComponentFullThisType<ED, T, Cxt>
|
||||
this: ComponentFullThisType<ED, T, any, Cxt>
|
||||
) {
|
||||
if (this.state.oakFullpath) {
|
||||
try {
|
||||
|
|
@ -261,7 +261,7 @@ export async function refresh<
|
|||
export async function loadMore<
|
||||
ED extends EntityDict & BaseEntityDict,
|
||||
T extends keyof ED,
|
||||
Cxt extends Context<ED>>(this: ComponentFullThisType<ED, T, Cxt>) {
|
||||
Cxt extends Context<ED>>(this: ComponentFullThisType<ED, T, any, Cxt>) {
|
||||
if (this.state.oakEntity && this.state.oakFullpath) {
|
||||
try {
|
||||
await this.features.runningTree.loadMore(this.state.oakFullpath);
|
||||
|
|
@ -278,8 +278,8 @@ export async function execute<
|
|||
ED extends EntityDict & BaseEntityDict,
|
||||
T extends keyof ED,
|
||||
Cxt extends Context<ED>>(
|
||||
this: ComponentFullThisType<ED, T, Cxt>,
|
||||
operation?: Omit<ED[T]['Operation'], 'id'>,
|
||||
this: ComponentFullThisType<ED, T, any, Cxt>,
|
||||
data?: ED[T]['Update']['data'] | Record<string, ED[T]['Update']['data']>,
|
||||
path?: string) {
|
||||
if (this.state.oakExecuting) {
|
||||
throw new Error('请仔细设计按钮状态,不要允许重复点击!');
|
||||
|
|
@ -287,49 +287,20 @@ export async function execute<
|
|||
/* this.setState({
|
||||
oakFocused: undefined,
|
||||
}); */
|
||||
try {
|
||||
const fullpath = path
|
||||
? `${this.state.oakFullpath}.${path}`
|
||||
: this.state.oakFullpath;
|
||||
const result = await this.features.runningTree.execute(fullpath, operation);
|
||||
await this.setMessage({
|
||||
type: 'success',
|
||||
content: '操作成功',
|
||||
});
|
||||
return result;
|
||||
} catch (err) {
|
||||
if (err instanceof OakUserException) {
|
||||
if (err instanceof OakInputIllegalException) {
|
||||
const attrs = err.getAttributes();
|
||||
const entity = err.getEntity();
|
||||
const message = err.message;
|
||||
/* this.setState({
|
||||
oakFocused: {
|
||||
attr: attrs[0],
|
||||
message,
|
||||
},
|
||||
oakExecuting: false,
|
||||
}); */
|
||||
const attrNames = attrs.map(attr => this.t(`${entity}:attr.${attr}`)).filter(ele => !!ele);
|
||||
this.setMessage({
|
||||
type: 'error',
|
||||
content: attrNames.length > 0 ? `「${attrNames.join(',')}」${message}` : message,
|
||||
});
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
this.setMessage({
|
||||
type: 'error',
|
||||
content: (err as Error).message,
|
||||
});
|
||||
throw err;
|
||||
}
|
||||
|
||||
const fullpath = path ? `${this.state.oakFullpath}.${path}` : this.state.oakFullpath;
|
||||
const result = await this.features.runningTree.execute(fullpath, data);
|
||||
await this.setMessage({
|
||||
type: 'success',
|
||||
content: '操作成功',
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
export function callPicker<
|
||||
ED extends EntityDict & BaseEntityDict,
|
||||
T extends keyof ED,
|
||||
Cxt extends Context<ED>>(this: ComponentFullThisType<ED, T, Cxt>, attr: string, params: Record<string, any> = {}) {
|
||||
Cxt extends Context<ED>>(this: ComponentFullThisType<ED, T, any, Cxt>, attr: string, params: Record<string, any> = {}) {
|
||||
if (this.state.oakExecuting) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -354,55 +325,12 @@ export function callPicker<
|
|||
});
|
||||
}
|
||||
|
||||
export async function setUpdateData<
|
||||
ED extends EntityDict & BaseEntityDict,
|
||||
T extends keyof ED,
|
||||
Cxt extends Context<ED>>(this: ComponentFullThisType<ED, T, Cxt>, attr: string, data: any) {
|
||||
assert(attr.indexOf('.') === -1, 'setUpdateData只能设置当前对象属性,子层对象请写完整的addOperation')
|
||||
if (this.props.oakId) {
|
||||
return this.addOperation({
|
||||
action: 'update',
|
||||
data: {
|
||||
[attr]: data,
|
||||
}
|
||||
} as ED[T]['Update']);
|
||||
}
|
||||
else {
|
||||
await this.addOperation({
|
||||
action: 'create',
|
||||
data: {
|
||||
[attr]: data,
|
||||
}
|
||||
} as ED[T]['CreateSingle']);
|
||||
}
|
||||
}
|
||||
|
||||
export async function setMultiAttrUpdateData<
|
||||
ED extends EntityDict & BaseEntityDict,
|
||||
T extends keyof ED,
|
||||
Cxt extends Context<ED>>(this: ComponentFullThisType<ED, T, Cxt>, data: Record<string, any>) {
|
||||
for (const key in data) {
|
||||
assert(key.indexOf('.') === -1, 'setMultiAttrUpdateData只能设置当前对象属性,子层对象请写完整的addOperation');
|
||||
}
|
||||
if (this.props.oakId) {
|
||||
return this.addOperation({
|
||||
action: 'update',
|
||||
data,
|
||||
} as ED[T]['Update']);
|
||||
}
|
||||
else {
|
||||
await this.addOperation({
|
||||
action: 'create',
|
||||
data,
|
||||
} as ED[T]['CreateSingle']);
|
||||
}
|
||||
}
|
||||
|
||||
export function destroyNode<
|
||||
ED extends EntityDict & BaseEntityDict,
|
||||
T extends keyof ED,
|
||||
Cxt extends Context<ED>>(
|
||||
this: ComponentFullThisType<ED, T, Cxt>) {
|
||||
ED extends EntityDict & BaseEntityDict,
|
||||
T extends keyof ED,
|
||||
Cxt extends Context<ED>>(
|
||||
this: ComponentFullThisType<ED, T, any, Cxt>) {
|
||||
assert(this.state.oakFullpath);
|
||||
this.features.runningTree.destroyNode(this.state.oakFullpath);
|
||||
unset(this.state, ['oakFullpath', 'oakEntity']);
|
||||
|
|
|
|||
188
src/page.web.tsx
188
src/page.web.tsx
|
|
@ -4,7 +4,7 @@ import React from 'react';
|
|||
import { withRouter, PullToRefresh } from './platforms/web';
|
||||
import { get } from 'oak-domain/lib/utils/lodash';
|
||||
import { CommonAspectDict } from 'oak-common-aspect';
|
||||
import { Aspect, CheckerType, Context, DeduceSorterItem, EntityDict } from 'oak-domain/lib/types';
|
||||
import { Action, Aspect, CheckerType, Context, DeduceSorterItem, EntityDict } from 'oak-domain/lib/types';
|
||||
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
|
||||
import { BasicFeatures } from './features';
|
||||
import { NamedFilterItem, NamedSorterItem } from './types/NamedCondition';
|
||||
|
|
@ -14,11 +14,14 @@ import {
|
|||
ComponentProps,
|
||||
OakComponentOption,
|
||||
OakNavigateToParameters,
|
||||
WebComponentCommonMethodNames,
|
||||
WebComponentListMethodNames,
|
||||
WebComponentSingleMethodNames,
|
||||
} from './types/Page';
|
||||
|
||||
import {
|
||||
subscribe, unsubscribe, onPathSet, reRender, refresh,
|
||||
loadMore, execute, callPicker, setUpdateData, setMultiAttrUpdateData,
|
||||
loadMore, execute, callPicker,
|
||||
destroyNode,
|
||||
} from './page.common';
|
||||
import { MessageProps } from './types/Message';
|
||||
|
|
@ -38,7 +41,7 @@ abstract class OakComponentBase<
|
|||
TMethod extends WechatMiniprogram.Component.MethodOption
|
||||
> extends React.PureComponent<ComponentProps<IsList, TProperty>, ComponentData<ED, T, FormedData, TData>> {
|
||||
abstract features: FD & BasicFeatures<ED, Cxt, AD & CommonAspectDict<ED, Cxt>>;
|
||||
abstract option: OakComponentOption<ED, T, Cxt, AD, FD, Proj, FormedData, IsList, TData, TProperty, TMethod>;
|
||||
abstract oakOption: OakComponentOption<ED, T, Cxt, AD, FD, Proj, FormedData, IsList, TData, TProperty, TMethod>;
|
||||
|
||||
subscribe() {
|
||||
subscribe.call(this as any);
|
||||
|
|
@ -49,7 +52,7 @@ abstract class OakComponentBase<
|
|||
}
|
||||
|
||||
onPathSet() {
|
||||
return onPathSet.call(this as any, this.option as any);
|
||||
return onPathSet.call(this as any, this.oakOption as any);
|
||||
}
|
||||
|
||||
triggerEvent<DetailType = any>(
|
||||
|
|
@ -123,10 +126,10 @@ abstract class OakComponentBase<
|
|||
}
|
||||
|
||||
reRender(extra?: Record<string, any>) {
|
||||
return reRender.call(this as any, this.option as any, extra);
|
||||
return reRender.call(this as any, this.oakOption as any, extra);
|
||||
}
|
||||
|
||||
navigateTo(options: { url: string } & OakNavigateToParameters<ED, T>, state?: Record<string, any>, disableNamespace?: boolean) {
|
||||
navigateTo<T2 extends keyof ED>(options: { url: string } & OakNavigateToParameters<ED, T2>, state?: Record<string, any>, disableNamespace?: boolean) {
|
||||
const { url, ...rest } = options;
|
||||
let url2 = url.includes('?')
|
||||
? url.concat(
|
||||
|
|
@ -158,7 +161,7 @@ abstract class OakComponentBase<
|
|||
return this.props.navigate(url2, { replace: false, state });
|
||||
}
|
||||
|
||||
navigateBack(option: { delta?: number }) {
|
||||
navigateBack(option?: { delta?: number }) {
|
||||
const { delta } = option || {};
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
|
|
@ -170,7 +173,7 @@ abstract class OakComponentBase<
|
|||
});
|
||||
}
|
||||
|
||||
redirectTo(options: { url: string } & OakNavigateToParameters<ED, T>, state?: Record<string, any>, disableNamespace?: boolean) {
|
||||
redirectTo<T2 extends keyof ED>(options: { url: string } & OakNavigateToParameters<ED, T2>, state?: Record<string, any>, disableNamespace?: boolean) {
|
||||
const { url, ...rest } = options;
|
||||
let url2 = url.includes('?')
|
||||
? url.concat(
|
||||
|
|
@ -245,12 +248,35 @@ abstract class OakComponentBase<
|
|||
}
|
||||
} */
|
||||
|
||||
addOperation(operation: Omit<ED[T]['Operation'], 'id'>, beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>, path?: string) {
|
||||
const path2 = path ? `${this.state.oakFullpath}.${path}` : this.state.oakFullpath;
|
||||
return this.features.runningTree.addOperation(path2, operation, beforeExecute, afterExecute);
|
||||
addItem<T extends keyof ED>(data: Omit<ED[T]['CreateSingle']['data'], 'id'>, beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>) {
|
||||
return this.features.runningTree.addItem(this.state.oakFullpath, data, beforeExecute, afterExecute);
|
||||
}
|
||||
|
||||
cleanOperation(path?: string) {
|
||||
removeItem(id: string, beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>) {
|
||||
return this.features.runningTree.removeItem(this.state.oakFullpath, id, beforeExecute, afterExecute);
|
||||
}
|
||||
|
||||
updateItem<T extends keyof ED>(data: ED[T]['Update']['data'], id: string, action?: ED[T]['Action'], beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>) {
|
||||
return this.features.runningTree.updateItem(this.state.oakFullpath, data, id, action, beforeExecute, afterExecute);
|
||||
}
|
||||
|
||||
recoverItem(id: string) {
|
||||
return this.features.runningTree.recoverItem(this.state.oakFullpath, id);
|
||||
}
|
||||
|
||||
create<T extends keyof ED>(data: Omit<ED[T]['CreateSingle']['data'], 'id'>, beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>) {
|
||||
return this.features.runningTree.create(this.state.oakFullpath, data, beforeExecute, afterExecute);
|
||||
}
|
||||
|
||||
update<T extends keyof ED>(data: ED[T]['Update']['data'], action?: ED[T]['Action'], beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>) {
|
||||
return this.features.runningTree.update(this.state.oakFullpath, data, action, beforeExecute, afterExecute);
|
||||
}
|
||||
|
||||
remove(beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>) {
|
||||
return this.features.runningTree.remove(this.state.oakFullpath, beforeExecute, afterExecute);
|
||||
}
|
||||
|
||||
clean(path?: string) {
|
||||
const path2 = path ? `${this.state.oakFullpath}.${path}` : this.state.oakFullpath;
|
||||
return this.features.runningTree.clean(path2);
|
||||
}
|
||||
|
|
@ -263,12 +289,12 @@ abstract class OakComponentBase<
|
|||
return callPicker.call(this as any, attr, params);
|
||||
}
|
||||
|
||||
execute(operation?: ED[T]['Operation']) {
|
||||
return execute.call(this as any, operation);
|
||||
execute(data?: ED[T]['Update']['data'] | Record<string, ED[T]['Update']['data']>) {
|
||||
return execute.call(this as any, data);
|
||||
}
|
||||
|
||||
getFreshValue(path?: string) {
|
||||
const path2 = path? `${this.state.oakFullpath}.${path}` : this.state.oakFullpath;
|
||||
const path2 = path ? `${this.state.oakFullpath}.${path}` : this.state.oakFullpath;
|
||||
return this.features.runningTree.getFreshValue(path2) as Promise<ED[keyof ED]['Schema'][] | ED[keyof ED]['Schema'] | undefined>;
|
||||
}
|
||||
|
||||
|
|
@ -290,14 +316,6 @@ abstract class OakComponentBase<
|
|||
return refresh.call(this as any);
|
||||
}
|
||||
|
||||
setUpdateData(attr: string, data: any) {
|
||||
return setUpdateData.call(this as any, attr, data);
|
||||
}
|
||||
|
||||
setMultiAttrUpdateData(data: Record<string, any>) {
|
||||
return setMultiAttrUpdateData.call(this as any, data);
|
||||
}
|
||||
|
||||
loadMore() {
|
||||
return loadMore.call(this as any);
|
||||
}
|
||||
|
|
@ -534,7 +552,7 @@ export function createComponent<
|
|||
features: BasicFeatures<ED, Cxt, AD & CommonAspectDict<ED, Cxt>> & FD,
|
||||
) {
|
||||
const {
|
||||
data, projection, properties, entity, methods, lifetimes, observers, Render, path
|
||||
data, methods, lifetimes, observers, getRender, path
|
||||
} = option as OakComponentOption<
|
||||
ED,
|
||||
T,
|
||||
|
|
@ -548,28 +566,121 @@ export function createComponent<
|
|||
TProperty,
|
||||
TMethod
|
||||
> & {
|
||||
Render: React.ComponentType<any>;
|
||||
getRender: () => React.ComponentType<any>;
|
||||
};
|
||||
|
||||
|
||||
const { fn } = translateObservers(observers);
|
||||
const props = {} as Record<string, any>;
|
||||
class OakComponentWrapper extends OakComponentBase<ED, T, Cxt, AD, FD, Proj, FormedData, IsList, TData, TProperty, TMethod> {
|
||||
features = features;
|
||||
option = option;
|
||||
oakOption = option;
|
||||
isReachBottom = false;
|
||||
methodProps: Record<string, Function>;
|
||||
|
||||
constructor(props: ComponentProps<IsList, TProperty>) {
|
||||
super(props);
|
||||
const methodProps: Record<string, Function> = {
|
||||
const methodProps: Record<WebComponentCommonMethodNames, Function> = {
|
||||
t: (key: string, params?: object) => this.t(key, params),
|
||||
execute: async (data: Record<string, any>) => {
|
||||
await this.setMultiAttrUpdateData(data);
|
||||
await this.execute();
|
||||
execute: (data: Record<string, any>) => {
|
||||
return this.execute(data);
|
||||
},
|
||||
tryExecute: async (data: Record<string, any>, path?: string) => this.tryExecute(path),
|
||||
};
|
||||
refresh: () => {
|
||||
return this.refresh();
|
||||
},
|
||||
setNotification: (data: NotificationProps) => {
|
||||
return this.setNotification(data);
|
||||
},
|
||||
setMessage: (data: MessageProps) => {
|
||||
return this.setMessage(data);
|
||||
},
|
||||
navigateTo: <T2 extends keyof ED>(
|
||||
options: { url: string } & OakNavigateToParameters<ED, T2>,
|
||||
state?: Record<string, any>,
|
||||
disableNamespace?: boolean
|
||||
) => {
|
||||
return this.navigateTo(options, state, disableNamespace);
|
||||
},
|
||||
navigateBack: (options?: { delta: number }) => {
|
||||
return this.navigateBack(options);
|
||||
},
|
||||
redirectTo: <T2 extends keyof ED>(
|
||||
options: Parameters<typeof wx.redirectTo>[0] &
|
||||
OakNavigateToParameters<ED, T2>,
|
||||
state?: Record<string, any>,
|
||||
disableNamespace?: boolean
|
||||
) => {
|
||||
return this.redirectTo(options, state, disableNamespace);
|
||||
},
|
||||
clean: (path?: string) => {
|
||||
return this.clean(path);
|
||||
}
|
||||
};
|
||||
if (option.isList) {
|
||||
Object.assign(methodProps, {
|
||||
addItem: (data: Omit<ED[T]['CreateSingle']['data'], 'id'>, beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>) => {
|
||||
return this.addItem(data, beforeExecute, afterExecute);
|
||||
},
|
||||
removeItem: (id: string, beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>) => {
|
||||
return this.removeItem(id, beforeExecute, afterExecute);
|
||||
},
|
||||
updateItem: (data: ED[T]['Update']['data'], id: string, action?: ED[T]['Action'], beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>) => {
|
||||
return this.updateItem(data, id, action, beforeExecute, afterExecute);
|
||||
},
|
||||
setFilters: (filters: NamedFilterItem<ED, T>[]) => {
|
||||
return this.setFilters(filters);
|
||||
},
|
||||
addNamedFilter: (filter: NamedFilterItem<ED, T>, refresh?: boolean) => {
|
||||
return this.addNamedFilter(filter, refresh);
|
||||
},
|
||||
removeNamedFilter: (
|
||||
filter: NamedFilterItem<ED, T>,
|
||||
refresh?: boolean
|
||||
) => {
|
||||
return this.removeNamedFilter(filter, refresh);
|
||||
},
|
||||
removeNamedFilterByName: (name: string, refresh?: boolean) => {
|
||||
return this.removeNamedFilterByName(name, refresh);
|
||||
},
|
||||
setNamedSorters: (sorters: NamedSorterItem<ED, T>[]) => {
|
||||
return this.setNamedSorters(sorters);
|
||||
},
|
||||
addNamedSorter: (sorter: NamedSorterItem<ED, T>, refresh?: boolean) => {
|
||||
return this.addNamedSorter(sorter, refresh);
|
||||
},
|
||||
removeNamedSorter: (
|
||||
sorter: NamedSorterItem<ED, T>,
|
||||
refresh?: boolean
|
||||
) => {
|
||||
return this.removeNamedSorter(sorter, refresh);
|
||||
},
|
||||
removeNamedSorterByName: (name: string, refresh?: boolean) => {
|
||||
return this.removeNamedSorterByName(name, refresh);
|
||||
},
|
||||
setPageSize: (pageSize: number) => {
|
||||
return this.setPageSize(pageSize);
|
||||
},
|
||||
setCurrentPage: (current: number) => {
|
||||
return this.setCurrentPage(current);
|
||||
},
|
||||
loadMore: () => {
|
||||
return this.loadMore();
|
||||
}
|
||||
} as Record<WebComponentListMethodNames, Function>);
|
||||
}
|
||||
else {
|
||||
Object.assign(methodProps, {
|
||||
create: (data: Omit<ED[T]['CreateSingle']['data'], 'id'>, beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>) => {
|
||||
return this.create(data, beforeExecute, afterExecute);
|
||||
},
|
||||
update: (data: ED[T]['Update']['data'], action: ED[T]['Action'], beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>) => {
|
||||
return this.update(data, action, beforeExecute, afterExecute);
|
||||
},
|
||||
remove: (beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>) => {
|
||||
return this.remove(beforeExecute, afterExecute);
|
||||
},
|
||||
} as Record<WebComponentSingleMethodNames, Function>);
|
||||
}
|
||||
|
||||
if (methods) {
|
||||
for (const m in methods) {
|
||||
Object.assign(this, {
|
||||
|
|
@ -673,6 +784,7 @@ export function createComponent<
|
|||
render(): React.ReactNode {
|
||||
const { oakPullDownRefreshLoading } = this.state;
|
||||
const { oakDisablePulldownRefresh = false } = this.props;
|
||||
const Render = getRender.call(this);
|
||||
|
||||
if (this.supportPullDownRefresh() && !oakDisablePulldownRefresh) {
|
||||
const Child = React.cloneElement(
|
||||
|
|
@ -694,11 +806,17 @@ export function createComponent<
|
|||
{
|
||||
getScrollContainer: () => document.body,
|
||||
},
|
||||
<Render method={this.methodProps} data={this.state}/>
|
||||
<Render methods={this.methodProps} data={{
|
||||
...this.state,
|
||||
...this.props,
|
||||
}} />
|
||||
);
|
||||
return Child;
|
||||
}
|
||||
return <Render method={this.methodProps} data={this.state}/>;
|
||||
return <Render methods={this.methodProps} data={{
|
||||
...this.state,
|
||||
...this.props,
|
||||
}}/>;
|
||||
}
|
||||
};
|
||||
return withRouter(OakComponentWrapper, option);
|
||||
|
|
|
|||
|
|
@ -116,13 +116,15 @@ export type ComponentPublicThisType<
|
|||
detail?: DetailType,
|
||||
options?: WechatMiniprogram.Component.TriggerEventOption
|
||||
) => void;
|
||||
} & TMethod & OakCommonComponentMethods<ED, T> & (IsList extends true ? OakListComponentMethods<ED, T> : {});
|
||||
} & TMethod & OakCommonComponentMethods<ED, T> & (IsList extends true ? OakListComponentMethods<ED, T> : OakSingleComponentMethods<ED, T>);
|
||||
|
||||
export type ComponentFullThisType<
|
||||
ED extends EntityDict & BaseEntityDict,
|
||||
T extends keyof ED,
|
||||
IsList extends boolean,
|
||||
Cxt extends Context<ED>
|
||||
> = {
|
||||
subscribed?: () => void;
|
||||
features: BasicFeatures<ED, Cxt, CommonAspectDict<ED, Cxt>>;
|
||||
state: OakComponentData<ED, T>;
|
||||
props: ComponentProps<true, {}>;
|
||||
|
|
@ -135,7 +137,7 @@ export type ComponentFullThisType<
|
|||
detail?: DetailType,
|
||||
options?: WechatMiniprogram.Component.TriggerEventOption
|
||||
) => void;
|
||||
} & OakCommonComponentMethods<ED, T> & OakListComponentMethods<ED, T> & OakHiddenComponentMethods;
|
||||
} & OakCommonComponentMethods<ED, T> & (IsList extends true ? OakListComponentMethods<ED, T> : OakSingleComponentMethods<ED, T>);
|
||||
|
||||
export type OakComponentOption<
|
||||
ED extends EntityDict & BaseEntityDict,
|
||||
|
|
@ -247,23 +249,26 @@ export type OakCommonComponentMethods<
|
|||
disableNamespace?: boolean
|
||||
) => Promise<void>;
|
||||
// setProps: (props: Record<string, any>, usingState?: true) => void;
|
||||
addOperation: (operation: Omit<ED[T]['Operation'], 'id'>, beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>, path?: string) => Promise<void>;
|
||||
cleanOperation: (path?: string) => void;
|
||||
|
||||
clean: (path?: string) => void;
|
||||
|
||||
t(key: string, params?: object): string;
|
||||
callPicker: (attr: string, params: Record<string, any>) => void;
|
||||
execute: (operation?: Omit<ED[T]['Operation'], 'id'>, path?: string) => Promise<ED[T]['Operation'][]>;
|
||||
execute: (data?: ED[T]['Update']['data'] | Record<string, ED[T]['Update']['data']>, path?: string) => Promise<ED[T]['Operation'][]>;
|
||||
checkOperation: (ntity: T, action: ED[T]['Action'], filter?: ED[T]['Update']['filter'], checkerTypes?: CheckerType[]) => Promise<boolean>;
|
||||
tryExecute: (path?: string) => Promise<boolean>;
|
||||
getOperations: (path?: string) => Promise<ED[T]['Operation'][] | undefined>;
|
||||
refresh: (extra?: any) => Promise<void>;
|
||||
setUpdateData: (data: string, attr: any) => Promise<void>;
|
||||
setMultiAttrUpdateData: (data: Record<string, any>) => Promise<void>;
|
||||
setId: (id: string) => Promise<void>;
|
||||
unsetId: () => void;
|
||||
getId: () => string | undefined;
|
||||
refresh: () => Promise<void>;
|
||||
};
|
||||
|
||||
export type OakSingleComponentMethods<ED extends EntityDict & BaseEntityDict, T extends keyof ED> = {
|
||||
setId: (id: string) => Promise<void>;
|
||||
unsetId: () => void;
|
||||
getId: () => string | undefined;
|
||||
create: (data: Omit<ED[T]['CreateSingle']['data'], 'id'>, beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>) => Promise<void>;
|
||||
update: (data: ED[T]['Update']['data'], action?: ED[T]['Action'], beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>) => Promise<void>;
|
||||
remove: (beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>) => Promise<void>;
|
||||
}
|
||||
|
||||
export type OakListComponentMethods<ED extends EntityDict & BaseEntityDict, T extends keyof ED> = {
|
||||
loadMore: () => Promise<void>;
|
||||
setFilters: (filters: NamedFilterItem<ED, T>[]) => Promise<void>;
|
||||
|
|
@ -291,6 +296,10 @@ export type OakListComponentMethods<ED extends EntityDict & BaseEntityDict, T ex
|
|||
getPagination: () => Pagination | undefined;
|
||||
setPageSize: (pageSize: number) => void;
|
||||
setCurrentPage: (current: number) => void;
|
||||
|
||||
addItem: (data: Omit<ED[T]['CreateSingle']['data'], 'id'>, beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>) => Promise<void>;
|
||||
removeItem: (id: string, beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>) => Promise<void>;
|
||||
updateItem: (data: ED[T]['Update']['data'], id: string, action?: ED[T]['Action'], beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>) => Promise<void>;
|
||||
};
|
||||
|
||||
type ComponentOnPropsChangeOption = {
|
||||
|
|
@ -307,21 +316,21 @@ export type OakComponentOnlyMethods = {
|
|||
export type OakComponentData<
|
||||
ED extends EntityDict & BaseEntityDict,
|
||||
T extends keyof ED
|
||||
> = {
|
||||
oakExecuting: boolean;
|
||||
oakAllowExecuting: boolean | OakUserException;
|
||||
oakFocused: {
|
||||
attr: string;
|
||||
message: string;
|
||||
> = {
|
||||
oakExecuting: boolean;
|
||||
oakAllowExecuting: boolean | OakUserException;
|
||||
oakFocused: {
|
||||
attr: string;
|
||||
message: string;
|
||||
};
|
||||
oakDirty: boolean;
|
||||
oakLoading: boolean;
|
||||
oakLoadingMore: boolean;
|
||||
oakPullDownRefreshLoading: boolean;
|
||||
oakEntity: T;
|
||||
oakFullpath: string;
|
||||
oakLegalActions?: ED[T]['Action'][];
|
||||
};
|
||||
oakDirty: boolean;
|
||||
oakLoading: boolean;
|
||||
oakLoadingMore: boolean;
|
||||
oakPullDownRefreshLoading: boolean;
|
||||
oakEntity: T;
|
||||
oakFullpath: string;
|
||||
oakLegalActions?: ED[T]['Action'][];
|
||||
};
|
||||
|
||||
export type MakeOakComponent<
|
||||
ED extends EntityDict & BaseEntityDict,
|
||||
|
|
@ -351,3 +360,24 @@ export type MakeOakComponent<
|
|||
TMethod
|
||||
>
|
||||
) => React.ComponentType<any>;
|
||||
|
||||
// 暴露给组件的方法
|
||||
export type WebComponentCommonMethodNames = 'setNotification' | 'setMessage' | 'navigateTo' | 'navigateBack' | 'redirectTo' | 'clean' | 't' | 'execute' | 'refresh';
|
||||
|
||||
// 暴露给list组件的方法
|
||||
export type WebComponentListMethodNames = 'loadMore' | 'setFilters' | 'addNamedFilter' | 'removeNamedFilter' | 'removeNamedFilterByName' | 'setNamedSorters'
|
||||
| 'addNamedSorter' | 'removeNamedSorter' | 'removeNamedSorterByName' | 'setPageSize' | 'setCurrentPage' | 'addItem' | 'removeItem' | 'updateItem';
|
||||
|
||||
// 暴露给single组件的方法
|
||||
export type WebComponentSingleMethodNames = 'create' | 'update' | 'remove';
|
||||
|
||||
export type WebComponentProps<
|
||||
ED extends EntityDict & BaseEntityDict,
|
||||
T extends keyof ED,
|
||||
IsList extends boolean,
|
||||
TData extends WechatMiniprogram.Component.DataOption = {},
|
||||
TMethod extends WechatMiniprogram.Component.MethodOption = {}> = {
|
||||
methods: TMethod & Pick<OakCommonComponentMethods<ED, T>, WebComponentCommonMethodNames>
|
||||
& (IsList extends true ? Pick<OakListComponentMethods<ED, T>, WebComponentListMethodNames> : Pick<OakSingleComponentMethods<ED, T>, WebComponentSingleMethodNames>);
|
||||
data: TData & OakComponentData<ED, T> & (IsList extends true ? OakListComponentProperties : {});
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue