新的架构和接口(web部分)

This commit is contained in:
Xu Chang 2022-10-19 13:14:55 +08:00
parent ec34d5972a
commit d2f0dfe05d
38 changed files with 2995 additions and 5951 deletions

View File

@ -1,7 +1,7 @@
import { EntityDict, OperateOption, 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, Context } from 'oak-domain/lib/types';
import { Checker, CheckerType, Context } from 'oak-domain/lib/types';
import { TreeStore } from 'oak-memory-tree-store';
export declare class CacheStore<ED extends EntityDict & BaseEntityDict, Cxt extends Context<ED>> extends TreeStore<ED, Cxt> {
private executor;
@ -10,6 +10,7 @@ export declare class CacheStore<ED extends EntityDict & BaseEntityDict, Cxt exte
constructor(storageSchema: StorageSchema<ED>, contextBuilder: () => (store: CacheStore<ED, Cxt>) => Cxt, getFullDataFn?: () => any, resetInitialDataFn?: () => void);
operate<T extends keyof ED, OP extends OperateOption>(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>;
select<T extends keyof ED, S extends ED[T]['Selection'], OP extends SelectOption>(entity: T, selection: S, context: Cxt, option: OP): Promise<import("oak-domain/lib/types").SelectionResult<ED[T]["Schema"], S["data"]>>;
registerChecker<T extends keyof ED>(checker: Checker<ED, T, Cxt>): void;
/**

View File

@ -4,6 +4,7 @@ exports.CacheStore = void 0;
var tslib_1 = require("tslib");
var TriggerExecutor_1 = require("oak-domain/lib/store/TriggerExecutor");
var oak_memory_tree_store_1 = require("oak-memory-tree-store");
var assert_1 = tslib_1.__importDefault(require("assert"));
var CacheStore = /** @class */ (function (_super) {
tslib_1.__extends(CacheStore, _super);
function CacheStore(storageSchema, contextBuilder, getFullDataFn, resetInitialDataFn) {
@ -99,6 +100,48 @@ var CacheStore = /** @class */ (function (_super) {
});
});
};
CacheStore.prototype.check = function (entity, operation, context, checkerTypes) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var action, checkers, checkers_1, checkers_1_1, checker, e_1_1;
var e_1, _a;
return tslib_1.__generator(this, function (_b) {
switch (_b.label) {
case 0:
action = operation.action;
checkers = this.executor.getCheckers(entity, action, checkerTypes);
(0, assert_1.default)(context.getCurrentTxnId());
if (!checkers) return [3 /*break*/, 8];
_b.label = 1;
case 1:
_b.trys.push([1, 6, 7, 8]);
checkers_1 = tslib_1.__values(checkers), checkers_1_1 = checkers_1.next();
_b.label = 2;
case 2:
if (!!checkers_1_1.done) return [3 /*break*/, 5];
checker = checkers_1_1.value;
return [4 /*yield*/, checker.fn({ operation: operation }, context, {})];
case 3:
_b.sent();
_b.label = 4;
case 4:
checkers_1_1 = checkers_1.next();
return [3 /*break*/, 2];
case 5: return [3 /*break*/, 8];
case 6:
e_1_1 = _b.sent();
e_1 = { error: e_1_1 };
return [3 /*break*/, 8];
case 7:
try {
if (checkers_1_1 && !checkers_1_1.done && (_a = checkers_1.return)) _a.call(checkers_1);
}
finally { if (e_1) throw e_1.error; }
return [7 /*endfinally*/];
case 8: return [2 /*return*/];
}
});
});
};
CacheStore.prototype.select = function (entity, selection, context, option) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var autoCommit, result, err_3;

View File

@ -1,4 +1,4 @@
import { EntityDict, OperateOption, SelectOption, OpRecord, Context, AspectWrapper, SelectionResult } from 'oak-domain/lib/types';
import { EntityDict, OperateOption, SelectOption, OpRecord, Context, AspectWrapper, SelectionResult, CheckerType } from 'oak-domain/lib/types';
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
import { CommonAspectDict } from 'oak-common-aspect';
import { Feature } from '../types/Feature';
@ -22,19 +22,20 @@ export declare class Cache<ED extends EntityDict & BaseEntityDict, Cxt extends C
* @param operation
* @returns
*/
testOperation<T extends keyof ED>(entity: T, operation: ED[T]['Operation']): Promise<boolean>;
tryRedoOperations<T extends keyof ED>(entity: T, operations: ED[T]['Operation'][]): Promise<boolean>;
checkOperation<T extends keyof ED>(entity: T, action: ED[T]['Action'], filter?: ED[T]['Update']['filter'], checkerTypes?: CheckerType[]): Promise<boolean>;
/**
* cache中重做一些动作modi
* @param entity
* @param selection
* @param opers
*/
tryRedoOperations<T extends keyof ED, S extends ED[T]['Selection']>(entity: T, selection: S, opers: Array<{
tryRedoOperationsThenSelect<T extends keyof ED, S extends ED[T]['Selection']>(entity: T, selection: S, opers: Array<{
entity: keyof ED;
operation: ED[keyof ED]['Operation'];
}>): Promise<SelectionResult<ED[T]["Schema"], S["data"]>>;
get<T extends keyof ED, S extends ED[T]['Selection']>(entity: T, selection: S, params?: SelectOption): Promise<import("oak-domain/lib/types").SelectRowShape<ED[T]["Schema"], S["data"]>[]>;
judgeRelation(entity: keyof ED, attr: string): string | 0 | 1 | string[] | 2;
judgeRelation(entity: keyof ED, attr: string): string | 0 | 2 | 1 | string[];
bindOnSync(callback: (opRecords: OpRecord<ED>[]) => Promise<void>): void;
unbindOnSync(callback: (opRecords: OpRecord<ED>[]) => Promise<void>): void;
getCachedData(): { [T in keyof ED]?: ED[T]["OpSchema"][] | undefined; };

View File

@ -78,13 +78,11 @@ var Cache = /** @class */ (function (_super) {
var result;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
(0, selection_1.reinforceSelection)(this.cacheStore.getSchema(), entity, selection);
return [4 /*yield*/, this.getAspectWrapper().exec('count', {
entity: entity,
selection: selection,
option: option,
})];
case 0: return [4 /*yield*/, this.getAspectWrapper().exec('count', {
entity: entity,
selection: selection,
option: option,
})];
case 1:
result = (_a.sent()).result;
return [2 /*return*/, result];
@ -121,9 +119,67 @@ var Cache = /** @class */ (function (_super) {
* @param operation
* @returns
*/
Cache.prototype.testOperation = function (entity, operation) {
Cache.prototype.tryRedoOperations = function (entity, operations) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var context, err_1;
var context, operations_1, operations_1_1, operation, e_1_1, err_1;
var e_1, _a;
return tslib_1.__generator(this, function (_b) {
switch (_b.label) {
case 0:
context = this.contextBuilder();
return [4 /*yield*/, context.begin()];
case 1:
_b.sent();
_b.label = 2;
case 2:
_b.trys.push([2, 12, , 14]);
_b.label = 3;
case 3:
_b.trys.push([3, 8, 9, 10]);
operations_1 = tslib_1.__values(operations), operations_1_1 = operations_1.next();
_b.label = 4;
case 4:
if (!!operations_1_1.done) return [3 /*break*/, 7];
operation = operations_1_1.value;
return [4 /*yield*/, this.cacheStore.operate(entity, operation, context, {
dontCollect: true,
dontCreateOper: true,
})];
case 5:
_b.sent();
_b.label = 6;
case 6:
operations_1_1 = operations_1.next();
return [3 /*break*/, 4];
case 7: return [3 /*break*/, 10];
case 8:
e_1_1 = _b.sent();
e_1 = { error: e_1_1 };
return [3 /*break*/, 10];
case 9:
try {
if (operations_1_1 && !operations_1_1.done && (_a = operations_1.return)) _a.call(operations_1);
}
finally { if (e_1) throw e_1.error; }
return [7 /*endfinally*/];
case 10: return [4 /*yield*/, context.rollback()];
case 11:
_b.sent();
return [3 /*break*/, 14];
case 12:
err_1 = _b.sent();
return [4 /*yield*/, context.rollback()];
case 13:
_b.sent();
throw err_1;
case 14: return [2 /*return*/, true];
}
});
});
};
Cache.prototype.checkOperation = function (entity, action, filter, checkerTypes) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var context, operation, err_2;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
@ -131,26 +187,28 @@ var Cache = /** @class */ (function (_super) {
return [4 /*yield*/, context.begin()];
case 1:
_a.sent();
operation = {
action: action,
filter: filter,
data: {},
};
_a.label = 2;
case 2:
_a.trys.push([2, 5, , 7]);
return [4 /*yield*/, this.cacheStore.operate(entity, operation, context, {
dontCollect: true,
dontCreateOper: true,
})];
return [4 /*yield*/, this.cacheStore.check(entity, operation, context, checkerTypes)];
case 3:
_a.sent();
return [4 /*yield*/, context.rollback()];
case 4:
_a.sent();
return [3 /*break*/, 7];
return [2 /*return*/, true];
case 5:
err_1 = _a.sent();
err_2 = _a.sent();
return [4 /*yield*/, context.rollback()];
case 6:
_a.sent();
throw err_1;
case 7: return [2 /*return*/, true];
return [2 /*return*/, false];
case 7: return [2 /*return*/];
}
});
});
@ -161,10 +219,10 @@ var Cache = /** @class */ (function (_super) {
* @param selection
* @param opers
*/
Cache.prototype.tryRedoOperations = function (entity, selection, opers) {
Cache.prototype.tryRedoOperationsThenSelect = function (entity, selection, opers) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var result, context, opers_1, opers_1_1, oper, e_1_1, err_2, missedRows;
var e_1, _a;
var result, context, opers_1, opers_1_1, oper, e_2_1, err_3, missedRows;
var e_2, _a;
return tslib_1.__generator(this, function (_b) {
switch (_b.label) {
case 0:
@ -193,14 +251,14 @@ var Cache = /** @class */ (function (_super) {
return [3 /*break*/, 3];
case 6: return [3 /*break*/, 9];
case 7:
e_1_1 = _b.sent();
e_1 = { error: e_1_1 };
e_2_1 = _b.sent();
e_2 = { error: e_2_1 };
return [3 /*break*/, 9];
case 8:
try {
if (opers_1_1 && !opers_1_1.done && (_a = opers_1.return)) _a.call(opers_1);
}
finally { if (e_1) throw e_1.error; }
finally { if (e_2) throw e_2.error; }
return [7 /*endfinally*/];
case 9:
if (!true) return [3 /*break*/, 19];
@ -217,9 +275,9 @@ var Cache = /** @class */ (function (_super) {
_b.sent();
return [2 /*return*/, result];
case 13:
err_2 = _b.sent();
if (!(err_2 instanceof Exception_1.OakRowUnexistedException)) return [3 /*break*/, 15];
missedRows = err_2.getRows();
err_3 = _b.sent();
if (!(err_3 instanceof Exception_1.OakRowUnexistedException)) return [3 /*break*/, 15];
missedRows = err_3.getRows();
return [4 /*yield*/, this.getAspectWrapper().exec('fetchRows', missedRows)];
case 14:
_b.sent();
@ -227,7 +285,7 @@ var Cache = /** @class */ (function (_super) {
case 15: return [4 /*yield*/, context.rollback()];
case 16:
_b.sent();
throw err_2;
throw err_3;
case 17: return [3 /*break*/, 18];
case 18: return [3 /*break*/, 9];
case 19: return [2 /*return*/];

View File

@ -1,122 +1,112 @@
import { EntityDict, Context, DeduceUpdateOperation, StorageSchema, OpRecord, SelectRowShape, DeduceOperation, AspectWrapper } from "oak-domain/lib/types";
import { EntityDict, Context, StorageSchema, OpRecord, SelectRowShape, DeduceSorterItem, AspectWrapper } from "oak-domain/lib/types";
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
import { CommonAspectDict } from 'oak-common-aspect';
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>;
protected action?: ED[T]['Action'];
protected dirty?: string;
protected updateData: DeduceUpdateOperation<ED[T]['OpSchema']>['data'];
protected dirty?: boolean;
protected cache: Cache<ED, Cxt, AD>;
protected refreshing: boolean;
private beforeExecute?;
private afterExecute?;
abstract onCacheSync(opRecords: OpRecord<ED>[]): Promise<void>;
abstract refreshValue(): void;
private syncHandler;
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>, action?: ED[T]['Action'], updateData?: DeduceUpdateOperation<ED[T]['OpSchema']>['data']);
protected loading: boolean;
protected loadingMore: boolean;
protected executing: boolean;
protected operations: Operation<ED, T>[];
protected modiIds: string[];
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>);
getEntity(): T;
protected abstract setForeignKey(attr: string, entity: keyof ED, id: string | undefined): Promise<void>;
private setLocalUpdateData;
setUpdateData(attr: string, value: any): Promise<void>;
getUpdateData(): import("oak-domain/lib/types").DeduceUpdateOperationData<ED[T]["OpSchema"]>;
setMultiUpdateData(updateData: DeduceUpdateOperation<ED[T]['OpSchema']>['data']): Promise<void>;
setDirty(): Promise<void>;
setAction(action: ED[T]['Action']): Promise<void>;
protected abstract getChildPath(child: Node<ED, keyof ED, Cxt, AD>): string;
/**
* modi
*/
getModiIds(child: Node<ED, keyof ED, Cxt, AD>): string[];
setDirty(): void;
isDirty(): boolean;
isLoading(): boolean;
isLoadingMore(): boolean;
isExecuting(): boolean;
setExecuting(executing: boolean): void;
getParent(): Node<ED, keyof ED, Cxt, AD> | undefined;
getProjection(): Promise<ED[T]["Selection"]["data"]>;
setBeforeExecute(_beforeExecute?: (updateData: DeduceUpdateOperation<ED[T]['OpSchema']>['data'], action: ED[T]['Action']) => Promise<void>): void;
setAfterExecute(_afterExecute?: (updateData: DeduceUpdateOperation<ED[T]['OpSchema']>['data'], action: ED[T]['Action']) => Promise<void>): void;
getBeforeExecute(): ((updateData: import("oak-domain/lib/types").DeduceUpdateOperationData<ED[T]["OpSchema"]>, action: ED[T]["Action"]) => Promise<void>) | undefined;
getAfterExecute(): ((updateData: import("oak-domain/lib/types").DeduceUpdateOperationData<ED[T]["OpSchema"]>, action: ED[T]["Action"]) => Promise<void>) | undefined;
destroy(): void;
protected judgeRelation(attr: string): string | 0 | 1 | string[] | 2;
protected getProjection(): Promise<ED[T]["Selection"]["data"]>;
protected judgeRelation(attr: string): string | 0 | 2 | 1 | string[];
protected contains(filter: ED[T]['Selection']['filter'], conditionalFilter: ED[T]['Selection']['filter']): boolean;
protected repel(filter1: ED[T]['Selection']['filter'], filter2: ED[T]['Selection']['filter']): boolean;
}
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 newBorn;
private filters;
private sorters;
private pagination;
private projectionShape;
private ids;
private syncHandler;
protected getChildPath(child: Node<ED, keyof ED, Cxt, AD>): string;
onCacheSync(records: OpRecord<ED>[]): Promise<void>;
destroy(): void;
setForeignKey(attr: string, entity: keyof ED, id: string | undefined): Promise<void>;
refreshValue(): void;
constructor(entity: T, schema: StorageSchema<ED>, cache: Cache<ED, Cxt, AD>, projection: ED[T]['Selection']['data'] | (() => Promise<ED[T]['Selection']['data']>), projectionShape: ED[T]['Selection']['data'], parent?: Node<ED, keyof ED, Cxt, AD>, action?: ED[T]['Action'], updateData?: DeduceUpdateOperation<ED[T]['OpSchema']>['data'], 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']>), projectionShape: ED[T]['Selection']['data'], parent?: Node<ED, keyof ED, Cxt, AD>, filters?: NamedFilterItem<ED, T>[], sorters?: NamedSorterItem<ED, T>[], pagination?: Pagination);
getPagination(): Pagination;
setPagination(pagination: Pagination): void;
setPagination(pagination: Pagination): Promise<void>;
getChild(path: string, newBorn?: true): SingleNode<ED, T, Cxt, AD> | undefined;
getChildren(): SingleNode<ED, T, Cxt, AD>[];
getNewBorn(): SingleNode<ED, T, Cxt, AD>[];
addChild(path: string, node: SingleNode<ED, T, Cxt, AD>): void;
removeChild(path: string): void;
setValue(value: SelectRowShape<ED[T]['OpSchema'], ED[T]['Selection']['data']>[] | undefined): Promise<void>;
private appendValue;
getNamedFilters(): NamedFilterItem<ED, T>[];
getNamedFilterByName(name: string): NamedFilterItem<ED, T> | undefined;
setNamedFilters(filters: NamedFilterItem<ED, T>[]): void;
addNamedFilter(filter: NamedFilterItem<ED, T>): void;
removeNamedFilter(filter: NamedFilterItem<ED, T>): void;
removeNamedFilterByName(name: string): void;
setNamedFilters(filters: NamedFilterItem<ED, T>[], refresh?: boolean): Promise<void>;
addNamedFilter(filter: NamedFilterItem<ED, T>, refresh?: boolean): Promise<void>;
removeNamedFilter(filter: NamedFilterItem<ED, T>, refresh?: boolean): Promise<void>;
removeNamedFilterByName(name: string, refresh?: boolean): Promise<void>;
getNamedSorters(): NamedSorterItem<ED, T>[];
getNamedSorterByName(name: string): NamedSorterItem<ED, T> | undefined;
setNamedSorters(sorters: NamedSorterItem<ED, T>[]): void;
addNamedSorter(sorter: NamedSorterItem<ED, T>): void;
removeNamedSorter(sorter: NamedSorterItem<ED, T>): void;
removeNamedSorterByName(name: string): void;
getFreshValue(): Array<SelectRowShape<ED[T]['Schema'], ED[T]['Selection']['data']> | undefined>;
getAction(): "update" | ED[T]["Action"];
composeOperation(action?: string, execute?: boolean): Promise<DeduceOperation<ED[T]['Schema']> | DeduceOperation<ED[T]['Schema']>[] | undefined>;
refresh(): Promise<void>;
setNamedSorters(sorters: NamedSorterItem<ED, T>[], refresh?: boolean): Promise<void>;
addNamedSorter(sorter: NamedSorterItem<ED, T>, refresh?: boolean): Promise<void>;
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>;
composeOperations(): Promise<Operation<ED, T, false>[] | undefined>;
getProjection(): Promise<ED[T]['Selection']['data']>;
constructSelection(withParent?: true): Promise<{
data: ED[T]["Selection"]["data"];
filters: ED[T]["Selection"]["filter"][];
sorter: DeduceSorterItem<ED[T]["Schema"]>[];
}>;
refresh(pageNumber?: number, getCount?: true, append?: boolean): Promise<void>;
loadMore(): Promise<void>;
setCurrentPage<T extends keyof ED>(currentPage: number, append?: boolean): Promise<void>;
resetUpdateData(): Promise<void>;
pushNewBorn(options: Pick<CreateNodeOptions<ED, T>, 'updateData' | 'beforeExecute' | 'afterExecute'>): Promise<SingleNode<ED, T, Cxt, AD>>;
popNewBorn(path: string): void;
/**
* updateData和当前的某项是否相等
* @param from
* @param to
* @returns
*/
private judgeTheSame;
setUniqueChildren(data: Pick<CreateNodeOptions<ED, T>, 'updateData' | 'beforeExecute' | 'afterExecute'>[]): Promise<void>;
toggleChild(data: Pick<CreateNodeOptions<ED, T>, 'updateData' | 'beforeExecute' | 'afterExecute'>, checked: boolean): Promise<void>;
clean(): void;
}
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 value?;
private freshValue?;
private children;
onCacheSync(records: OpRecord<ED>[]): Promise<void>;
constructor(entity: T, schema: StorageSchema<ED>, cache: Cache<ED, Cxt, AD>, projection: ED[T]['Selection']['data'] | (() => Promise<ED[T]['Selection']['data']>), projectionShape: ED[T]['Selection']['data'], parent?: Node<ED, keyof ED, Cxt, AD>, action?: ED[T]['Action'], updateData?: DeduceUpdateOperation<ED[T]['OpSchema']>['data']);
constructor(entity: T, schema: StorageSchema<ED>, cache: Cache<ED, Cxt, AD>, projection: ED[T]['Selection']['data'] | (() => Promise<ED[T]['Selection']['data']>), projectionShape: ED[T]['Selection']['data'], parent?: Node<ED, keyof ED, Cxt, AD>);
protected getChildPath(child: Node<ED, keyof ED, Cxt, AD>): string;
destroy(): void;
getChild(path: string): SingleNode<ED, keyof ED, Cxt, AD> | ListNode<ED, keyof ED, Cxt, AD>;
setId(id: string): Promise<void>;
getChildren(): {
[K: string]: SingleNode<ED, keyof ED, Cxt, AD> | ListNode<ED, keyof ED, Cxt, AD>;
};
addChild(path: string, node: SingleNode<ED, keyof ED, Cxt, AD> | ListNode<ED, keyof ED, Cxt, AD>): void;
removeChild(path: string): void;
refreshValue(): void;
setValue(value: SelectRowShape<ED[T]['OpSchema'], ED[T]['Selection']['data']> | undefined): Promise<void>;
getFreshValue(ignoreRemoved?: boolean): (SelectRowShape<ED[T]["OpSchema"], ED[T]["Selection"]["data"]> & import("oak-domain/lib/types").DeduceUpdateOperationData<ED[T]["OpSchema"]>) | SelectRowShape<ED[T]["Schema"], ED[T]["Selection"]["data"]> | undefined;
getAction(): "create" | "update" | ED[T]["Action"];
composeOperation(action2?: string, execute?: boolean): Promise<DeduceUpdateOperation<ED[T]["Schema"]> | undefined>;
refresh(scene: string): Promise<void>;
resetUpdateData(attrs?: string[]): Promise<void>;
setForeignKey(attr: string, entity: keyof ED, id: string | undefined): Promise<void>;
getFreshValue(): Promise<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>;
composeOperations(): Promise<Operation<ED, T, false>[] | undefined>;
getProjection(): Promise<ED[T]["Selection"]["data"]>;
refresh(): Promise<void>;
clean(): void;
getOtmFilter<T2 extends keyof ED>(childNode: ListNode<ED, keyof ED, Cxt, AD>): ED[T2]['Selection']['filter'];
}
export declare type CreateNodeOptions<ED extends EntityDict & BaseEntityDict, T extends keyof ED> = {
path: string;
parent?: string;
entity: T;
isList?: boolean;
isPicker?: boolean;
@ -124,12 +114,9 @@ export declare type CreateNodeOptions<ED extends EntityDict & BaseEntityDict, T
pagination?: Pagination;
filters?: NamedFilterItem<ED, T>[];
sorters?: NamedSorterItem<ED, T>[];
action?: ED[T]['Action'];
beforeExecute?: (operations: ED[T]['Operation'][]) => Promise<void>;
afterExecute?: (operations: ED[T]['Operation'][]) => Promise<void>;
id?: string;
ids?: string[];
updateData?: DeduceUpdateOperation<ED[T]['OpSchema']>['data'];
beforeExecute?: (updateData: DeduceUpdateOperation<ED[T]['OpSchema']>['data'], action: ED[T]['Action']) => Promise<void>;
afterExecute?: (updateData: DeduceUpdateOperation<ED[T]['OpSchema']>['data'], action: ED[T]['Action']) => Promise<void>;
};
export declare class RunningTree<ED extends EntityDict & BaseEntityDict, Cxt extends Context<ED>, AD extends CommonAspectDict<ED, Cxt>> extends Feature<ED, Cxt, AD> {
private cache;
@ -139,19 +126,17 @@ export declare class RunningTree<ED extends EntityDict & BaseEntityDict, Cxt ext
createNode<T extends keyof ED>(options: CreateNodeOptions<ED, T>): Promise<ListNode<ED, T, Cxt, AD> | SingleNode<ED, T, Cxt, AD>>;
private findNode;
destroyNode(path: string): void;
private applyOperation;
getFreshValue(path: string): (SelectRowShape<ED[keyof ED]["OpSchema"], ED[keyof ED]["Selection"]["data"]> & import("oak-domain/lib/types").DeduceUpdateOperationData<ED[keyof ED]["OpSchema"]>) | SelectRowShape<ED[keyof ED]["Schema"], ED[keyof ED]["Selection"]["data"]> | (SelectRowShape<ED[keyof ED]["Schema"], ED[keyof ED]["Selection"]["data"]> | undefined)[] | undefined;
getFreshValue(path: string): Promise<SelectRowShape<ED[keyof ED]["Schema"], ED[keyof ED]["Selection"]["data"]>> | Promise<SelectRowShape<ED[keyof ED]["Schema"], ED[keyof ED]["Selection"]["data"]>[]>;
isDirty(path: string): boolean;
private setUpdateDataInner;
setUpdateData(path: string, attr: string, value: any): Promise<void>;
setAction<T extends keyof ED>(path: string, action: ED[T]['Action']): Promise<void>;
setForeignKey(parent: string, attr: string, id: string | undefined): Promise<void>;
addForeignKeys(parent: string, attr: string, ids: string[]): Promise<void>;
setUniqueForeignKeys(parent: string, attr: string, ids: string[]): Promise<void>;
addOperation<T extends keyof ED>(path: string, operation: Omit<ED[T]['Operation'], 'id'>, 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;
setPageSize<T extends keyof ED>(path: string, pageSize: number): void;
setId(path: string, id: string): Promise<void>;
setPageSize<T extends keyof ED>(path: string, pageSize: number): Promise<void>;
setCurrentPage<T extends keyof ED>(path: string, currentPage: number): Promise<void>;
getNamedFilters<T extends keyof ED>(path: string): NamedFilterItem<ED, keyof ED>[];
getNamedFilterByName<T extends keyof ED>(path: string, name: string): NamedFilterItem<ED, keyof ED> | undefined;
@ -165,16 +150,9 @@ export declare class RunningTree<ED extends EntityDict & BaseEntityDict, Cxt ext
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>;
testAction(path: string, action: string, execute?: boolean): Promise<{
node: SingleNode<ED, keyof ED, Cxt, AD> | ListNode<ED, keyof ED, Cxt, AD>;
operation: DeduceOperation<ED[keyof ED]["Schema"]> | DeduceOperation<ED[keyof ED]["Schema"]>[];
}>;
private beforeExecute;
execute(path: string, action: string): Promise<DeduceOperation<ED[keyof ED]["Schema"]> | DeduceOperation<ED[keyof ED]["Schema"]>[]>;
pushNode<T extends keyof ED>(path: string, options: Pick<CreateNodeOptions<ED, T>, 'updateData' | 'beforeExecute' | 'afterExecute'>): Promise<SingleNode<ED, keyof ED, Cxt, AD>>;
removeNode(parent: string, path: string): Promise<void>;
resetUpdateData(path: string): Promise<void>;
toggleNode(path: string, nodeData: Record<string, any>, checked: boolean): Promise<void>;
tryExecute(path: string): Promise<void>;
execute(path: string): Promise<void>;
clean(path: string): void;
getRoot(): Record<string, SingleNode<ED, keyof ED, Cxt, AD> | ListNode<ED, keyof ED, Cxt, AD>>;
}
export {};

File diff suppressed because it is too large Load Diff

View File

@ -29,9 +29,6 @@ function initialize(storageSchema, createFeatures, frontendContextBuilder, backe
// 初始化i8n配置
var i18n = (0, i18n_1.getI18next)(i18nOptions);
Object.assign(global, {
OakPage: function (options) {
return (0, page_mp_1.createPage)(options, features, exceptionRouterDict);
},
OakComponent: function (options) {
return (0, page_mp_1.createComponent)(options, features, exceptionRouterDict);
},

View File

@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
exports.initialize = void 0;
var tslib_1 = require("tslib");
require("./utils/wx.polyfill");
var page_web_1 = require("./page.web");
var page_web2_1 = require("./page.web2");
var initialize_dev_1 = require("./initialize-dev");
var i18n_1 = require("./platforms/web/i18n");
function initialize(storageSchema, createFeatures, frontendContextBuilder, backendContextBuilder, aspectDict, exceptionRouters, triggers, checkers, watchers, initialData, actionDict, i18nOptions) {
@ -29,11 +29,8 @@ function initialize(storageSchema, createFeatures, frontendContextBuilder, backe
// 初始化i8n配置
var i18n = (0, i18n_1.getI18next)(i18nOptions);
Object.assign(global, {
OakPage: function (options) {
return (0, page_web_1.createPage)(options, features, exceptionRouterDict);
},
OakComponent: function (options) {
return (0, page_web_1.createComponent)(options, features, exceptionRouterDict);
return (0, page_web2_1.createComponent)(options, features, exceptionRouterDict);
},
});
return {

View File

@ -29,9 +29,6 @@ function initialize(storageSchema, createFeatures, frontendContextBuilder, excep
// 初始化locales
var i18n = (0, i18n_1.getI18next)(i18nOptions);
Object.assign(global, {
OakPage: function (options) {
return (0, page_mp_1.createPage)(options, features, exceptionRouterDict);
},
OakComponent: function (options) {
return (0, page_mp_1.createComponent)(options, features, exceptionRouterDict);
},

View File

@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
exports.initialize = void 0;
var tslib_1 = require("tslib");
require("./utils/wx.polyfill");
var page_web_1 = require("./page.web");
var page_web2_1 = require("./page.web2");
var initialize_prod_1 = require("./initialize-prod");
var i18n_1 = require("./platforms/web/i18n");
function initialize(storageSchema, createFeatures, frontendContextBuilder, exceptionRouters, connector, checkers, actionDict, i18nOptions) {
@ -29,11 +29,8 @@ function initialize(storageSchema, createFeatures, frontendContextBuilder, excep
// 初始化i8n配置
var i18n = (0, i18n_1.getI18next)(i18nOptions);
Object.assign(global, {
OakPage: function (options) {
return (0, page_web_1.createPage)(options, features, exceptionRouterDict);
},
OakComponent: function (options) {
return (0, page_web_1.createComponent)(options, features, exceptionRouterDict);
return (0, page_web2_1.createComponent)(options, features, exceptionRouterDict);
},
});
return {

21
lib/page.common.d.ts vendored
View File

@ -1,21 +0,0 @@
/// <reference types="wechat-miniprogram" />
import { CommonAspectDict } from 'oak-common-aspect';
import { Aspect, Context, EntityDict } from 'oak-domain/lib/types';
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
import { BasicFeatures } from './features';
import { ExceptionHandler } from './types/ExceptionRoute';
import { Feature } from './types/Feature';
import { OakCommonComponentMethods, OakComponentData, OakComponentProperties, OakHiddenComponentMethods, OakListComponentMethods, OakComponentOnlyMethods, OakPageMethods, OakPageOption } from './types/Page';
export declare type ComponentProps<TProperty extends WechatMiniprogram.Component.PropertyOption> = WechatMiniprogram.Component.PropertyOptionToData<OakComponentProperties & TProperty>;
export declare type ComponentData<ED extends EntityDict & BaseEntityDict, T extends keyof ED, FormedData extends WechatMiniprogram.Component.DataOption, TData extends WechatMiniprogram.Component.DataOption> = TData & FormedData & OakComponentData<ED, T>;
export declare type ComponentThisType<ED extends EntityDict & BaseEntityDict, T extends keyof ED, FormedData extends WechatMiniprogram.Component.DataOption, IsList extends boolean, TData extends WechatMiniprogram.Component.DataOption, TProperty extends WechatMiniprogram.Component.PropertyOption, TMethod extends WechatMiniprogram.Component.MethodOption> = ThisType<{
state: ComponentData<ED, T, FormedData, TData>;
props: ComponentProps<TProperty>;
setState: (data: any, callback?: () => void) => Promise<void>;
triggerEvent: <DetailType = any>(name: string, detail?: DetailType, options?: WechatMiniprogram.Component.TriggerEventOption) => void;
} & TMethod & OakCommonComponentMethods<ED, T> & OakHiddenComponentMethods & (IsList extends true ? OakListComponentMethods<ED, T> : {})>;
export declare function makeHiddenComponentMethods<ED extends EntityDict & BaseEntityDict, T extends keyof ED, FormedData extends WechatMiniprogram.Component.DataOption, IsList extends boolean, TData extends WechatMiniprogram.Component.DataOption, TProperty extends WechatMiniprogram.Component.PropertyOption, TMethod extends WechatMiniprogram.Component.MethodOption>(): OakHiddenComponentMethods & ComponentThisType<ED, T, FormedData, IsList, TData, TProperty, TMethod>;
export declare function makeCommonComponentMethods<ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends Context<ED>, AD extends Record<string, Aspect<ED, Cxt>>, FD extends Record<string, Feature<ED, Cxt, AD & CommonAspectDict<ED, Cxt>>>, FormedData extends WechatMiniprogram.Component.DataOption, Proj extends ED[T]['Selection']['data'], IsList extends boolean, TData extends WechatMiniprogram.Component.DataOption = {}, TProperty extends WechatMiniprogram.Component.PropertyOption = {}, TMethod extends WechatMiniprogram.Component.MethodOption = {}>(features: BasicFeatures<ED, Cxt, AD & CommonAspectDict<ED, Cxt>> & FD, exceptionRouterDict: Record<string, ExceptionHandler>, formData: OakPageOption<ED, T, Cxt, AD, FD, Proj, FormedData, IsList, TData, TProperty, TMethod>['formData']): Omit<OakCommonComponentMethods<ED, T>, 'navigateTo' | 'navigateBack' | 'resolveInput' | 'redirectTo' | 't'> & ComponentThisType<ED, T, FormedData, IsList, TData, TProperty, TMethod>;
export declare function makeComponentOnlyMethods<ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends Context<ED>, AD extends Record<string, Aspect<ED, Cxt>>, FD extends Record<string, Feature<ED, Cxt, AD & CommonAspectDict<ED, Cxt>>>, FormedData extends WechatMiniprogram.Component.DataOption, Proj extends ED[T]['Selection']['data'], IsList extends boolean, TData extends WechatMiniprogram.Component.DataOption = {}, TProperty extends WechatMiniprogram.Component.PropertyOption = {}, TMethod extends WechatMiniprogram.Component.MethodOption = {}>(formData: OakPageOption<ED, T, Cxt, AD, FD, Proj, FormedData, IsList, TData, TProperty, TMethod>['formData'], entity: T | undefined, actions: ED[T]['Action'][] | undefined): OakComponentOnlyMethods & ComponentThisType<ED, T, FormedData, IsList, TData, TProperty, TMethod>;
export declare function makeListComponentMethods<ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends Context<ED>, AD extends Record<string, Aspect<ED, Cxt>>, FD extends Record<string, Feature<ED, Cxt, AD & CommonAspectDict<ED, Cxt>>>, FormedData extends WechatMiniprogram.Component.DataOption, IsList extends boolean, TData extends WechatMiniprogram.Component.DataOption = {}, TProperty extends WechatMiniprogram.Component.PropertyOption = {}, TMethod extends WechatMiniprogram.Component.MethodOption = {}>(features: BasicFeatures<ED, Cxt, AD & CommonAspectDict<ED, Cxt>> & FD): OakListComponentMethods<ED, T> & ComponentThisType<ED, T, FormedData, IsList, TData, TProperty, TMethod>;
export declare function makePageMethods<ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends Context<ED>, AD extends Record<string, Aspect<ED, Cxt>>, FD extends Record<string, Feature<ED, Cxt, AD & CommonAspectDict<ED, Cxt>>>, FormedData extends WechatMiniprogram.Component.DataOption, Proj extends ED[T]['Selection']['data'], IsList extends boolean, TData extends WechatMiniprogram.Component.DataOption = {}, TProperty extends WechatMiniprogram.Component.PropertyOption = {}, TMethod extends WechatMiniprogram.Component.MethodOption = {}>(features: BasicFeatures<ED, Cxt, AD & CommonAspectDict<ED, Cxt>> & FD, options: OakPageOption<ED, T, Cxt, AD, FD, Proj, FormedData, IsList, TData, TProperty, TMethod>): OakPageMethods & ComponentThisType<ED, T, FormedData, IsList, TData, TProperty, TMethod>;

File diff suppressed because it is too large Load Diff

12
lib/page.common2.d.ts vendored Normal file
View File

@ -0,0 +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/Page2';
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>, legalExceptions?: Array<string>, path?: string): Promise<void>;
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>;

392
lib/page.common2.js Normal file
View File

@ -0,0 +1,392 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.setUpdateData = 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");
var Feature_1 = require("./types/Feature");
function subscribe() {
var _this = this;
if (!this.subscribed) {
this.subscribed = (0, Feature_1.subscribe)(function () { return _this.reRender(); });
}
}
exports.subscribe = subscribe;
function unsubscribe() {
if (this.subscribed) {
this.subscribed();
this.subscribed = undefined;
}
}
exports.unsubscribe = unsubscribe;
function onPathSet(option) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var _a, props, state, oakEntity, oakPath, oakProjection, oakIsPicker, oakFilters, oakSorters, oakId, entity, path, projection, isList, filters, sorters, pagination, features, filters2, oakFilters2, _loop_1, filters_1, filters_1_1, ele, proj, sorters2, oakSorters2, _loop_2, sorters_1, sorters_1_1, ele, oakPath2;
var e_1, _b, e_2, _c;
return tslib_1.__generator(this, function (_d) {
switch (_d.label) {
case 0:
_a = this, props = _a.props, state = _a.state;
oakEntity = props.oakEntity, oakPath = props.oakPath, oakProjection = props.oakProjection, oakIsPicker = props.oakIsPicker, oakFilters = props.oakFilters, oakSorters = props.oakSorters, oakId = props.oakId;
entity = option.entity, path = option.path, projection = option.projection, isList = option.isList, filters = option.filters, sorters = option.sorters, pagination = option.pagination;
features = this.features;
filters2 = [];
if (oakFilters) {
oakFilters2 = typeof oakFilters === 'string' ? JSON.parse(oakFilters) : oakFilters;
filters2.push.apply(filters2, tslib_1.__spreadArray([], tslib_1.__read(oakFilters2), false));
}
else if (filters) {
_loop_1 = function (ele) {
var _e;
var filter = ele.filter, name_1 = ele["#name"];
filters2.push((_e = {
filter: typeof filter === 'function'
? function () {
return filter({
features: features,
props: props,
state: state
});
}
: filter
},
_e['#name'] = name_1,
_e));
};
try {
for (filters_1 = tslib_1.__values(filters), filters_1_1 = filters_1.next(); !filters_1_1.done; filters_1_1 = filters_1.next()) {
ele = filters_1_1.value;
_loop_1(ele);
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (filters_1_1 && !filters_1_1.done && (_b = filters_1.return)) _b.call(filters_1);
}
finally { if (e_1) throw e_1.error; }
}
}
proj = oakProjection && (typeof oakProjection === 'string' ? JSON.parse(oakProjection) : oakProjection);
if (!proj && projection) {
proj = typeof projection === 'function'
? function () {
return projection({
features: features,
props: props,
state: state,
});
}
: projection;
}
sorters2 = [];
if (oakSorters) {
oakSorters2 = typeof oakSorters === 'string' ? JSON.parse(oakSorters) : oakSorters;
sorters2.push.apply(sorters2, tslib_1.__spreadArray([], tslib_1.__read(oakSorters2), false));
}
else if (sorters) {
_loop_2 = function (ele) {
var _f;
var sorter = ele.sorter, name_2 = ele["#name"];
sorters.push((_f = {
sorter: typeof sorter === 'function'
? function () {
return sorter({
features: features,
props: props,
state: state,
});
}
: sorter
},
_f['#name'] = name_2,
_f));
};
try {
for (sorters_1 = tslib_1.__values(sorters), sorters_1_1 = sorters_1.next(); !sorters_1_1.done; sorters_1_1 = sorters_1.next()) {
ele = sorters_1_1.value;
_loop_2(ele);
}
}
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {
try {
if (sorters_1_1 && !sorters_1_1.done && (_c = sorters_1.return)) _c.call(sorters_1);
}
finally { if (e_2) throw e_2.error; }
}
}
oakPath2 = oakPath || path;
(0, assert_1.assert)(oakPath2, '没有正确的path信息请检查是否配置正确');
return [4 /*yield*/, features.runningTree.createNode({
path: oakPath2,
entity: (oakEntity || entity),
isList: isList,
isPicker: oakIsPicker,
projection: proj,
pagination: pagination,
filters: filters2,
sorters: sorters2,
id: oakId,
})];
case 1:
_d.sent();
Object.assign(this.state, {
oakEntity: (oakEntity || entity),
oakFullpath: oakPath2,
oakIsReady: true,
});
return [2 /*return*/];
}
});
});
}
exports.onPathSet = onPathSet;
function reRender(option, extra) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var features, formData, rows, oakDirty, oakLoading, oakLoadingMore, oakExecuting, data, _a, k, data, _b;
var _c;
return tslib_1.__generator(this, function (_d) {
switch (_d.label) {
case 0:
features = this.features;
formData = option.formData;
if (!(this.state.oakEntity && this.state.oakFullpath)) return [3 /*break*/, 5];
return [4 /*yield*/, this.features.runningTree.getFreshValue(this.state.oakFullpath)];
case 1:
rows = _d.sent();
oakDirty = this.features.runningTree.isDirty(this.state.oakFullpath);
oakLoading = this.features.runningTree.isLoading(this.state.oakFullpath);
oakLoadingMore = this.features.runningTree.isLoadingMore(this.state.oakFullpath);
oakExecuting = this.features.runningTree.isExecuting(this.state.oakFullpath);
if (!formData) return [3 /*break*/, 3];
return [4 /*yield*/, formData.call(this, {
data: rows,
features: features,
props: this.props,
})];
case 2:
_a = _d.sent();
return [3 /*break*/, 4];
case 3:
_a = {};
_d.label = 4;
case 4:
data = _a;
for (k in data) {
if (data[k] === undefined) {
Object.assign(data, (_c = {},
_c[k] = null,
_c));
}
}
Object.assign(data, { oakDirty: oakDirty, oakLoading: oakLoading, oakLoadingMore: oakLoadingMore, oakExecuting: oakExecuting });
if (extra) {
Object.assign(data, extra);
}
this.setState(data);
return [3 /*break*/, 9];
case 5:
if (!formData) return [3 /*break*/, 7];
return [4 /*yield*/, formData.call(this, {
features: features,
props: this.props,
})];
case 6:
_b = _d.sent();
return [3 /*break*/, 8];
case 7:
_b = {};
_d.label = 8;
case 8:
data = _b;
if (extra) {
Object.assign(data, extra);
}
this.setState(data);
_d.label = 9;
case 9: return [2 /*return*/];
}
});
});
}
exports.reRender = reRender;
function refresh() {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var err_1;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!(this.state.oakEntity && this.state.oakFullpath)) return [3 /*break*/, 4];
_a.label = 1;
case 1:
_a.trys.push([1, 3, , 4]);
return [4 /*yield*/, this.features.runningTree.refresh(this.state.oakFullpath)];
case 2:
_a.sent();
return [3 /*break*/, 4];
case 3:
err_1 = _a.sent();
this.setMessage({
type: 'error',
content: err_1.message,
});
return [3 /*break*/, 4];
case 4: return [2 /*return*/];
}
});
});
}
exports.refresh = refresh;
function loadMore() {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var err_2;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!(this.state.oakEntity && this.state.oakFullpath)) return [3 /*break*/, 4];
_a.label = 1;
case 1:
_a.trys.push([1, 3, , 4]);
return [4 /*yield*/, this.features.runningTree.loadMore(this.state.oakFullpath)];
case 2:
_a.sent();
return [3 /*break*/, 4];
case 3:
err_2 = _a.sent();
this.setMessage({
type: 'error',
content: err_2.message,
});
return [3 /*break*/, 4];
case 4: return [2 /*return*/];
}
});
});
}
exports.loadMore = loadMore;
function execute(legalExceptions, path) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var fullpath, result, err_3, attr, name_3;
var _a;
return tslib_1.__generator(this, function (_b) {
switch (_b.label) {
case 0:
if (this.state.oakExecuting) {
return [2 /*return*/];
}
this.setState({
oakFocused: {},
});
_b.label = 1;
case 1:
_b.trys.push([1, 3, , 4]);
fullpath = path
? "".concat(this.state.oakFullpath, ".").concat(path)
: this.state.oakFullpath;
return [4 /*yield*/, this.features.runningTree.execute(fullpath)];
case 2:
result = _b.sent();
this.setMessage({
type: 'success',
content: '操作成功',
});
return [2 /*return*/, result];
case 3:
err_3 = _b.sent();
if (err_3 instanceof types_1.OakException) {
if (err_3 instanceof types_1.OakInputIllegalException) {
attr = err_3.getAttributes()[0];
this.setState({
oakFocused: (_a = {},
_a[attr] = true,
_a),
});
this.setMessage({
type: 'warning',
content: err_3.message,
});
}
else {
name_3 = err_3.constructor.name;
if (legalExceptions && legalExceptions.includes(name_3)) {
// 如果调用时就知道有异常,直接抛出
this.setState({
oakExecuting: false,
});
throw err_3;
}
}
}
else {
this.setMessage({
type: 'warning',
content: err_3.message,
});
}
throw err_3;
case 4: return [2 /*return*/];
}
});
});
}
exports.execute = execute;
function callPicker(attr, params) {
if (params === void 0) { params = {}; }
if (this.state.oakExecuting) {
return;
}
var relation = this.features.cache.judgeRelation(this.state.oakEntity, attr);
var subEntity;
if (relation === 2) {
subEntity = attr;
}
else {
(0, assert_1.assert)(typeof relation === 'string');
subEntity = relation;
}
var url = "/pickers/".concat(subEntity, "?oakIsPicker=true&oakParentEntity=").concat(this.state.oakEntity, "&oakParent=").concat(this.state.oakFullpath, "&oakPath=").concat(attr);
for (var k in params) {
url += "&".concat(k, "=").concat(JSON.stringify(params[k]));
}
this.navigateTo({
url: url,
});
}
exports.callPicker = callPicker;
function setUpdateData(attr, data) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var id;
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*/, generateNewId()];
case 2:
id = _c.sent();
return [4 /*yield*/, this.addOperation({
action: 'create',
data: (_b = {
id: id
},
_b[attr] = data,
_b)
})];
case 3:
_c.sent();
this.setProps({ oakId: id });
_c.label = 4;
case 4: return [2 /*return*/];
}
});
});
}
exports.setUpdateData = setUpdateData;

2
lib/page.mp.d.ts vendored
View File

@ -5,6 +5,6 @@ import { Aspect, Context, EntityDict } from 'oak-domain/lib/types';
import { BasicFeatures } from './features';
import { ExceptionHandler } from './types/ExceptionRoute';
import { Feature } from './types/Feature';
import { OakComponentOption, OakPageOption } from './types/Page';
import { OakComponentOption, OakPageOption } from './types/Page2';
export declare function createPage<ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends Context<ED>, AD extends Record<string, Aspect<ED, Cxt>>, FD extends Record<string, Feature<ED, Cxt, AD & CommonAspectDict<ED, Cxt>>>, 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: OakPageOption<ED, T, Cxt, AD, FD, Proj, FormedData, IsList, TData, TProperty, TMethod>, features: BasicFeatures<ED, Cxt, AD & CommonAspectDict<ED, Cxt>> & FD, exceptionRouterDict: Record<string, ExceptionHandler>): string;
export declare function createComponent<ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends Context<ED>, AD extends Record<string, Aspect<ED, Cxt>>, FD extends Record<string, Feature<ED, Cxt, AD & CommonAspectDict<ED, Cxt>>>, 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, FormedData, IsList, TData, TProperty, TMethod>, features: BasicFeatures<ED, Cxt, AD & CommonAspectDict<ED, Cxt>> & FD, exceptionRouterDict: Record<string, ExceptionHandler>): string;

View File

@ -5,7 +5,7 @@ var tslib_1 = require("tslib");
var lodash_1 = require("oak-domain/lib/utils/lodash");
var url_1 = tslib_1.__importDefault(require("url"));
var assert_1 = require("oak-domain/lib/utils/assert");
var page_common_1 = require("./page.common");
var page_common2_1 = require("./page.common2");
var i18n_1 = require("./platforms/wechatMp/i18n");
function makeCommonComponentMethods(features, exceptionRouterDict, formData) {
return tslib_1.__assign({ t: function (key, params) {
@ -154,10 +154,10 @@ function makeCommonComponentMethods(features, exceptionRouterDict, formData) {
},
}));
});
} }, (0, page_common_1.makeCommonComponentMethods)(features, exceptionRouterDict, formData));
} }, (0, page_common2_1.makeCommonComponentMethods)(features, exceptionRouterDict, formData));
}
function makePageMethods(features, options) {
var _a = (0, page_common_1.makePageMethods)(features, options), onPullDownRefresh = _a.onPullDownRefresh, onLoad = _a.onLoad, rest = tslib_1.__rest(_a, ["onPullDownRefresh", "onLoad"]);
var _a = (0, page_common2_1.makePageMethods)(features, options), onPullDownRefresh = _a.onPullDownRefresh, onLoad = _a.onLoad, rest = tslib_1.__rest(_a, ["onPullDownRefresh", "onLoad"]);
return tslib_1.__assign({ onPullDownRefresh: function () {
return tslib_1.__awaiter(this, void 0, void 0, function () {
return tslib_1.__generator(this, function (_a) {
@ -207,10 +207,10 @@ function makePageMethods(features, options) {
}
function createPage(options, features, exceptionRouterDict) {
var formData = options.formData, isList = options.isList, entity = options.entity, actions = options.actions;
var hiddenMethods = (0, page_common_1.makeHiddenComponentMethods)();
var hiddenMethods = (0, page_common2_1.makeHiddenComponentMethods)();
var commonMethods = makeCommonComponentMethods(features, exceptionRouterDict, formData);
var listMethods = (0, page_common_1.makeListComponentMethods)(features);
var onlyMethods = (0, page_common_1.makeComponentOnlyMethods)(formData, entity, actions);
var listMethods = (0, page_common2_1.makeListComponentMethods)(features);
var onlyMethods = (0, page_common2_1.makeComponentOnlyMethods)(formData, entity, actions);
var _a = makePageMethods(features, options), onLoad = _a.onLoad, onPullDownRefresh = _a.onPullDownRefresh, onReachBottom = _a.onReachBottom, restPageMethods = tslib_1.__rest(_a, ["onLoad", "onPullDownRefresh", "onReachBottom"]);
var methods = options.methods, lifetimes = options.lifetimes, pageLifetimes = options.pageLifetimes;
return Component({
@ -350,10 +350,10 @@ function createPage(options, features, exceptionRouterDict) {
exports.createPage = createPage;
function createComponent(options, features, exceptionRouterDict) {
var formData = options.formData, isList = options.isList, entity = options.entity, methods = options.methods, lifetimes = options.lifetimes, pageLifetimes = options.pageLifetimes, data = options.data, properties = options.properties, actions = options.actions, observers = options.observers, restOptions = tslib_1.__rest(options, ["formData", "isList", "entity", "methods", "lifetimes", "pageLifetimes", "data", "properties", "actions", "observers"]);
var hiddenMethods = (0, page_common_1.makeHiddenComponentMethods)();
var hiddenMethods = (0, page_common2_1.makeHiddenComponentMethods)();
var commonMethods = makeCommonComponentMethods(features, exceptionRouterDict, formData);
var listMethods = (0, page_common_1.makeListComponentMethods)(features);
var onlyMethods = (0, page_common_1.makeComponentOnlyMethods)(formData, entity, actions);
var listMethods = (0, page_common2_1.makeListComponentMethods)(features);
var onlyMethods = (0, page_common2_1.makeComponentOnlyMethods)(formData, entity, actions);
return Component(tslib_1.__assign({ data: Object.assign({}, data, {
oakEntity: '',
oakFullpath: '',

11
lib/page.web.d.ts vendored
View File

@ -1,11 +0,0 @@
/// <reference types="wechat-miniprogram" />
import React from 'react';
import { CommonAspectDict } from 'oak-common-aspect';
import { Aspect, Context, EntityDict } from 'oak-domain/lib/types';
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
import { BasicFeatures } from './features';
import { ExceptionHandler } from './types/ExceptionRoute';
import { Feature } from './types/Feature';
import { OakComponentOption, OakPageOption } from './types/Page';
export declare function createPage<ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends Context<ED>, AD extends Record<string, Aspect<ED, Cxt>>, FD extends Record<string, Feature<ED, Cxt, AD & CommonAspectDict<ED, Cxt>>>, 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: OakPageOption<ED, T, Cxt, AD, FD, Proj, FormedData, IsList, TData, TProperty, TMethod>, features: BasicFeatures<ED, Cxt, AD & CommonAspectDict<ED, Cxt>> & FD, exceptionRouterDict: Record<string, ExceptionHandler>): React.ForwardRefExoticComponent<React.RefAttributes<unknown>>;
export declare function createComponent<ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends Context<ED>, AD extends Record<string, Aspect<ED, Cxt>>, FD extends Record<string, Feature<ED, Cxt, AD & CommonAspectDict<ED, Cxt>>>, 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, FormedData, IsList, TData, TProperty, TMethod>, features: BasicFeatures<ED, Cxt, AD & CommonAspectDict<ED, Cxt>> & FD, exceptionRouterDict: Record<string, ExceptionHandler>): React.ForwardRefExoticComponent<React.RefAttributes<unknown>>;

View File

@ -1,430 +0,0 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createComponent = exports.createPage = void 0;
var tslib_1 = require("tslib");
var jsx_runtime_1 = require("react/jsx-runtime");
var react_1 = tslib_1.__importDefault(require("react"));
var web_1 = require("./platforms/web");
var lodash_1 = require("oak-domain/lib/utils/lodash");
var page_common_1 = require("./page.common");
function makeCommonComponentMethods(features, exceptionRouterDict, formData) {
return tslib_1.__assign({ t: function (key, params) {
// common: {
// GREETING: 'Hello {{name}}, nice to see you.',
// },
// t('common:GREETING', {name: "John Doe" })
return this.props.t(key, params);
}, resolveInput: function (input, keys) {
var currentTarget = input.currentTarget, target = input.target;
var value = Object.assign({}, currentTarget, target).value;
var dataset = currentTarget.dataset;
var result = {
dataset: dataset,
value: value,
};
if (keys) {
keys.forEach(function (k) {
var _a;
return Object.assign(result, (_a = {},
_a[k] = target[k],
_a));
});
}
return result;
}, navigateBack: function (option) {
var _this = this;
var delta = (option || {}).delta;
return new Promise(function (resolve, reject) {
try {
_this.props.navigate(delta || -1);
resolve(undefined);
}
catch (err) {
reject(err);
}
});
}, navigateTo: function (options, state, disableNamespace) {
var url = options.url, events = options.events, fail = options.fail, complete = options.complete, success = options.success, rest = tslib_1.__rest(options, ["url", "events", "fail", "complete", "success"]);
var url2 = url.includes('?')
? url.concat(this.state.oakFullpath
? "&oakFrom=".concat(this.state.oakFullpath)
: '')
: url.concat(this.state.oakFullpath ? "?oakFrom=".concat(this.state.oakFullpath) : '');
for (var param in rest) {
var param2 = param;
if (rest[param2] !== undefined) {
url2 += "".concat(url2.includes('?') ? '&' : '?').concat(param, "=").concat(typeof rest[param2] === 'string'
? rest[param2]
: JSON.stringify(rest[param2]));
}
}
// 路由传入namespace
if (!disableNamespace && this.props.namespace) {
url2 =
(this.props.namespace.startsWith('/') ? '' : '/') +
(this.props.namespace === '/' ? '' : this.props.namespace) +
(url2.startsWith('/') ? '' : '/') +
url2;
}
return this.props.navigate(url2, { replace: false, state: state });
}, redirectTo: function (options, state, disableNamespace) {
var url = options.url, events = options.events, fail = options.fail, complete = options.complete, success = options.success, rest = tslib_1.__rest(options, ["url", "events", "fail", "complete", "success"]);
var url2 = url.includes('?')
? url.concat(this.state.oakFullpath
? "&oakFrom=".concat(this.state.oakFullpath)
: '')
: url.concat(this.state.oakFullpath
? "?oakFrom=".concat(this.state.oakFullpath)
: '');
for (var param in rest) {
var param2 = param;
if (rest[param2] !== undefined) {
url2 += "".concat(url2.includes('?') ? '&' : '?').concat(param, "=").concat(typeof rest[param2] === 'string'
? rest[param2]
: JSON.stringify(rest[param2]));
}
}
// 路由传入namespace
if (!disableNamespace && this.props.namespace) {
url2 =
(this.props.namespace.startsWith('/') ? '' : '/') +
(this.props.namespace === '/' ? '' : this.props.namespace) +
(url2.startsWith('/') ? '' : '/') +
url2;
}
return this.props.navigate(url2, { replace: true, state: state });
} }, (0, page_common_1.makeCommonComponentMethods)(features, exceptionRouterDict, formData));
}
function makePageMethods(features, options) {
var _a = (0, page_common_1.makePageMethods)(features, options), onPullDownRefresh = _a.onPullDownRefresh, rest = tslib_1.__rest(_a, ["onPullDownRefresh"]);
return tslib_1.__assign({ onPullDownRefresh: function () {
return tslib_1.__awaiter(this, void 0, void 0, function () {
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, onPullDownRefresh.call(this)];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
} }, rest);
}
function translateObservers(observers) {
return {
fn: function (prevProps, prevState) {
var e_1, _a, e_2, _b;
var _c = this, state = _c.state, props = _c.props;
for (var obs in observers) {
var keys = obs.split(',').map(function (ele) { return ele.trim(); });
var changed = false;
try {
for (var keys_1 = (e_1 = void 0, tslib_1.__values(keys)), keys_1_1 = keys_1.next(); !keys_1_1.done; keys_1_1 = keys_1.next()) {
var k = keys_1_1.value;
if (k.includes('*')) {
throw new Error('web模式下带*的observer通配符暂不支持');
}
if ((0, lodash_1.get)(props, k) !== (0, lodash_1.get)(prevProps, k) ||
(0, lodash_1.get)(state, k) !== (0, lodash_1.get)(prevState, k)) {
changed = true;
break;
}
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (keys_1_1 && !keys_1_1.done && (_a = keys_1.return)) _a.call(keys_1);
}
finally { if (e_1) throw e_1.error; }
}
var args = [];
if (changed) {
try {
for (var keys_2 = (e_2 = void 0, tslib_1.__values(keys)), keys_2_1 = keys_2.next(); !keys_2_1.done; keys_2_1 = keys_2.next()) {
var k = keys_2_1.value;
args.push((0, lodash_1.get)(props, k) === undefined
? (0, lodash_1.get)(state, k)
: (0, lodash_1.get)(props, k));
}
}
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {
try {
if (keys_2_1 && !keys_2_1.done && (_b = keys_2.return)) _b.call(keys_2);
}
finally { if (e_2) throw e_2.error; }
}
observers[obs].apply(this, args);
}
}
},
};
}
function makeMiniprogramCompatibleFunctions() {
return {
triggerEvent: function (name, detail, option) {
throw new Error('method not implemented yet');
},
animate: function (selector, frames, duration, timeline) {
throw new Error('method not implemented yet');
},
clearAnimation: function (selector, option, callback) {
throw new Error('method not implemented yet');
},
};
}
var DEFAULT_REACH_BOTTOM_DISTANCE = 50;
function createPage(options, features, exceptionRouterDict) {
var _a = options, formData = _a.formData, isList = _a.isList, render = _a.render, actions = _a.actions, entity = _a.entity;
var hiddenMethods = (0, page_common_1.makeHiddenComponentMethods)();
var commonMethods = makeCommonComponentMethods(features, exceptionRouterDict, formData);
var listMethods = (0, page_common_1.makeListComponentMethods)(features);
var onlyMethods = (0, page_common_1.makeComponentOnlyMethods)(formData, entity, actions);
var _b = makePageMethods(features, options), onLoad = _b.onLoad, onPullDownRefresh = _b.onPullDownRefresh, onReachBottom = _b.onReachBottom, restPageMethods = tslib_1.__rest(_b, ["onLoad", "onPullDownRefresh", "onReachBottom"]);
var methods = options.methods, lifetimes = options.lifetimes, pageLifetimes = options.pageLifetimes, data = options.data, observers = options.observers;
var fn = translateObservers(observers).fn;
var OakPageWrapper = /** @class */ (function (_super) {
tslib_1.__extends(OakPageWrapper, _super);
function OakPageWrapper(props) {
var _a, _b, _c, _d, _e, _f;
var _this = _super.call(this, props) || this;
_this.features = features;
_this.isReachBottom = false;
_this.componentDidUpdate = fn;
_this.scrollEvent = function () {
_this.checkReachBottom();
};
_this.state = (data || {});
for (var m in commonMethods) {
Object.assign(_this, (_a = {},
_a[m] = commonMethods[m].bind(_this),
_a));
}
for (var m in listMethods) {
Object.assign(_this, (_b = {},
_b[m] = listMethods[m].bind(_this),
_b));
}
for (var m in hiddenMethods) {
Object.assign(_this, (_c = {},
_c[m] = hiddenMethods[m].bind(_this),
_c));
}
for (var m in onlyMethods) {
Object.assign(_this, (_d = {},
_d[m] = onlyMethods[m].bind(_this),
_d));
}
for (var m in restPageMethods) {
Object.assign(_this, (_e = {},
_e[m] = restPageMethods[m].bind(_this),
_e));
}
if (methods) {
var onPullDownRefresh_1 = methods.onPullDownRefresh, onReachBottom_1 = methods.onReachBottom, restMethods = tslib_1.__rest(methods, ["onPullDownRefresh", "onReachBottom"]);
for (var m in restMethods) {
Object.assign(_this, (_f = {},
_f[m] = restMethods[m].bind(_this),
_f));
}
}
(lifetimes === null || lifetimes === void 0 ? void 0 : lifetimes.created) && lifetimes.created.call(_this);
return _this;
}
OakPageWrapper.prototype.registerPageScroll = function () {
var _a = this.props.useBodyScroll, useBodyScroll = _a === void 0 ? false : _a;
if (useBodyScroll) {
window.addEventListener('scroll', this.scrollEvent);
}
else {
this.lv && this.lv.addEventListener('scroll', this.scrollEvent);
}
};
OakPageWrapper.prototype.unregisterPageScroll = function () {
var _a = this.props.useBodyScroll, useBodyScroll = _a === void 0 ? false : _a;
if (useBodyScroll) {
window.removeEventListener('scroll', this.scrollEvent);
}
else {
this.lv && this.lv.removeEventListener('scroll', this.scrollEvent);
}
};
OakPageWrapper.prototype.checkReachBottom = function () {
var isCurrentReachBottom = document.body.scrollHeight -
(window.innerHeight + window.scrollY) <=
DEFAULT_REACH_BOTTOM_DISTANCE;
if (!this.isReachBottom && isCurrentReachBottom) {
this.isReachBottom = true;
// 执行触底事件
if (methods === null || methods === void 0 ? void 0 : methods.onReachBottom) {
methods.onReachBottom.call(this);
return;
}
if (this.props.width === 'xs') {
onReachBottom.call(this);
}
return;
}
this.isReachBottom = isCurrentReachBottom;
};
OakPageWrapper.prototype.componentDidMount = function () {
return tslib_1.__awaiter(this, void 0, void 0, function () {
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
this.registerPageScroll();
return [4 /*yield*/, onLoad.call(this, this.props)];
case 1:
_a.sent();
typeof formData === 'function' && hiddenMethods.subscribe.call(this);
typeof formData === 'function' && commonMethods.reRender.call(this);
(methods === null || methods === void 0 ? void 0 : methods.onReady) && methods.onReady.call(this);
(lifetimes === null || lifetimes === void 0 ? void 0 : lifetimes.attached) && lifetimes.attached.call(this);
(lifetimes === null || lifetimes === void 0 ? void 0 : lifetimes.ready) && lifetimes.ready.call(this);
(pageLifetimes === null || pageLifetimes === void 0 ? void 0 : pageLifetimes.show) && pageLifetimes.show.call(this);
return [2 /*return*/];
}
});
});
};
OakPageWrapper.prototype.componentWillUnmount = function () {
return tslib_1.__awaiter(this, void 0, void 0, function () {
return tslib_1.__generator(this, function (_a) {
this.unregisterPageScroll();
this.state.oakFullpath && features.runningTree.destroyNode(this.state.oakFullpath);
typeof formData === 'function' && hiddenMethods.unsubscribe.call(this);
(methods === null || methods === void 0 ? void 0 : methods.onUnload) && methods.onUnload.call(this);
(lifetimes === null || lifetimes === void 0 ? void 0 : lifetimes.detached) && lifetimes.detached.call(this);
return [2 /*return*/];
});
});
};
OakPageWrapper.prototype.render = function () {
var _this = this;
var Render = render.call(this);
var oakLoading = this.state.oakLoading;
var _a = this.props, enablePullDownRefresh = _a.enablePullDownRefresh, _b = _a.useBodyScroll, useBodyScroll = _b === void 0 ? false : _b;
if (enablePullDownRefresh && this.props.width === 'xs') {
var child = react_1.default.cloneElement((0, jsx_runtime_1.jsx)(web_1.PullToRefresh, { onRefresh: function () {
if (methods === null || methods === void 0 ? void 0 : methods.onPullDownRefresh) {
methods.onPullDownRefresh.call(_this);
}
else {
onPullDownRefresh.call(_this);
}
}, refreshing: oakLoading, distanceToRefresh: DEFAULT_REACH_BOTTOM_DISTANCE, indicator: {
activate: commonMethods.t.call(this, 'common:ptrActivate'),
deactivate: commonMethods.t.call(this, 'common:ptrDeactivate'),
release: commonMethods.t.call(this, 'common:ptrRelease'),
finish: commonMethods.t.call(this, 'common:ptrFinish'),
} }), {
getScrollContainer: function () { return useBodyScroll ? document.body : _this.lv; },
}, Render);
return useBodyScroll ? (child) : ((0, jsx_runtime_1.jsx)("div", tslib_1.__assign({ ref: function (el) { return (_this.lv = el); }, style: { height: '100%', overflow: 'auto' } }, { children: child })));
}
return Render;
};
return OakPageWrapper;
}(react_1.default.PureComponent));
// 可能有问题by Xc
Object.assign(OakPageWrapper, makeMiniprogramCompatibleFunctions());
return (0, web_1.withRouter)(OakPageWrapper, false, options.path);
}
exports.createPage = createPage;
function createComponent(options, features, exceptionRouterDict) {
var _a = options, formData = _a.formData, isList = _a.isList, entity = _a.entity, methods = _a.methods, lifetimes = _a.lifetimes, pageLifetimes = _a.pageLifetimes, data = _a.data, properties = _a.properties, observers = _a.observers, actions = _a.actions, render = _a.render;
var hiddenMethods = (0, page_common_1.makeHiddenComponentMethods)();
var commonMethods = makeCommonComponentMethods(features, exceptionRouterDict, formData);
var listMethods = (0, page_common_1.makeListComponentMethods)(features);
var onlyMethods = (0, page_common_1.makeComponentOnlyMethods)(formData, entity, actions);
var fn = translateObservers(observers).fn;
var OakComponentWrapper = /** @class */ (function (_super) {
tslib_1.__extends(OakComponentWrapper, _super);
function OakComponentWrapper(props) {
var _a, _b, _c, _d, _e;
var _this = _super.call(this, props) || this;
_this.features = features;
_this.isReachBottom = false;
_this.state = (data || {});
for (var m in commonMethods) {
Object.assign(_this, (_a = {},
_a[m] = commonMethods[m].bind(_this),
_a));
}
for (var m in listMethods) {
Object.assign(_this, (_b = {},
_b[m] = listMethods[m].bind(_this),
_b));
}
for (var m in hiddenMethods) {
Object.assign(_this, (_c = {},
_c[m] = hiddenMethods[m].bind(_this),
_c));
}
for (var m in onlyMethods) {
Object.assign(_this, (_d = {},
_d[m] = onlyMethods[m].bind(_this),
_d));
}
if (methods) {
for (var m in methods) {
Object.assign(_this, (_e = {},
_e[m] = methods[m].bind(_this),
_e));
}
}
(lifetimes === null || lifetimes === void 0 ? void 0 : lifetimes.created) && lifetimes.created.call(_this);
return _this;
}
OakComponentWrapper.prototype.componentDidMount = function () {
return tslib_1.__awaiter(this, void 0, void 0, function () {
return tslib_1.__generator(this, function (_a) {
typeof formData === 'function' && hiddenMethods.subscribe.call(this);
this.setOakActions();
this.registerReRender();
(lifetimes === null || lifetimes === void 0 ? void 0 : lifetimes.attached) && lifetimes.attached.call(this);
(lifetimes === null || lifetimes === void 0 ? void 0 : lifetimes.ready) && lifetimes.ready.call(this);
(pageLifetimes === null || pageLifetimes === void 0 ? void 0 : pageLifetimes.show) && pageLifetimes.show.call(this);
return [2 /*return*/];
});
});
};
OakComponentWrapper.prototype.componentWillUnmount = function () {
return tslib_1.__awaiter(this, void 0, void 0, function () {
return tslib_1.__generator(this, function (_a) {
typeof formData === 'function' && hiddenMethods.unsubscribe.call(this);
(lifetimes === null || lifetimes === void 0 ? void 0 : lifetimes.detached) && lifetimes.detached.call(this);
return [2 /*return*/];
});
});
};
OakComponentWrapper.prototype.componentDidUpdate = function (prevProps, prevState) {
if (this.props.oakPath &&
prevProps.oakPath !== this.props.oakPath) {
this.onPropsChanged({
path: this.props.oakPath,
});
}
if (this.props.oakParent &&
prevProps.oakParent !== this.props.oakParent) {
this.onPropsChanged({
parent: this.props.oakParent,
});
}
fn === null || fn === void 0 ? void 0 : fn.call(this, prevProps, prevState);
};
OakComponentWrapper.prototype.render = function () {
var Render = render.call(this);
return Render;
};
OakComponentWrapper.prototype.triggerEvent = function (name, detail, options) {
// 需要兼容
};
return OakComponentWrapper;
}(react_1.default.PureComponent));
// 可能有问题by Xc
Object.assign(OakComponentWrapper, makeMiniprogramCompatibleFunctions());
return (0, web_1.withRouter)(OakComponentWrapper, true);
}
exports.createComponent = createComponent;

11
lib/page.web2.d.ts vendored Normal file
View File

@ -0,0 +1,11 @@
/// <reference types="wechat-miniprogram" />
/// <reference types="wechat-miniprogram" />
import React from 'react';
import { CommonAspectDict } from 'oak-common-aspect';
import { Aspect, Context, EntityDict } from 'oak-domain/lib/types';
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
import { BasicFeatures } from './features';
import { ExceptionHandler } from './types/ExceptionRoute';
import { Feature } from './types/Feature';
import { OakComponentOption } from './types/Page2';
export declare function createComponent<ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends Context<ED>, AD extends Record<string, Aspect<ED, Cxt>>, FD extends Record<string, Feature<ED, Cxt, AD & CommonAspectDict<ED, Cxt>>>, 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> = {}>(option: OakComponentOption<ED, T, Cxt, AD, FD, Proj, FormedData, IsList, TData, TProperty, TMethod>, features: BasicFeatures<ED, Cxt, AD & CommonAspectDict<ED, Cxt>> & FD, exceptionRouterDict: Record<string, ExceptionHandler>): React.ForwardRefExoticComponent<React.RefAttributes<unknown>>;

588
lib/page.web2.js Normal file
View File

@ -0,0 +1,588 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createComponent = void 0;
var tslib_1 = require("tslib");
var jsx_runtime_1 = require("react/jsx-runtime");
/// <reference path="../node_modules/@types/wechat-miniprogram/index.d.ts" />
var assert_1 = tslib_1.__importDefault(require("assert"));
var react_1 = tslib_1.__importDefault(require("react"));
var web_1 = require("./platforms/web");
var lodash_1 = require("oak-domain/lib/utils/lodash");
var page_common2_1 = require("./page.common2");
var OakComponentBase = /** @class */ (function (_super) {
tslib_1.__extends(OakComponentBase, _super);
function OakComponentBase() {
return _super !== null && _super.apply(this, arguments) || this;
}
OakComponentBase.prototype.subscribe = function () {
page_common2_1.subscribe.call(this);
};
OakComponentBase.prototype.unsubscribe = function () {
page_common2_1.unsubscribe.call(this);
};
OakComponentBase.prototype.onPathSet = function () {
page_common2_1.onPathSet.call(this, this.option);
};
OakComponentBase.prototype.triggerEvent = function (name, detail, options) {
};
OakComponentBase.prototype.sub = function (type, callback) {
this.features.eventBus.sub(type, callback);
};
OakComponentBase.prototype.unsub = function (type, callback) {
this.features.eventBus.unsub(type, callback);
};
OakComponentBase.prototype.pub = function (type, options) {
this.features.eventBus.pub(type, options);
};
OakComponentBase.prototype.unsubAll = function (type) {
this.features.eventBus.unsubAll(type);
};
OakComponentBase.prototype.save = function (key, item) {
this.features.localStorage.save(key, item);
};
OakComponentBase.prototype.load = function (key) {
return this.features.localStorage.load(key);
};
OakComponentBase.prototype.clear = function () {
this.features.localStorage.clear();
};
OakComponentBase.prototype.resolveInput = function (input, keys) {
var currentTarget = input.currentTarget, target = input.target;
var value = Object.assign({}, currentTarget, target).value;
var dataset = currentTarget.dataset;
var result = {
dataset: dataset,
value: value,
};
if (keys) {
keys.forEach(function (k) {
var _a;
return Object.assign(result, (_a = {},
_a[k] = target[k],
_a));
});
}
return result;
};
OakComponentBase.prototype.setNotification = function (data) {
this.features.notification.setNotification(data);
};
OakComponentBase.prototype.consumeNotification = function () {
return this.features.notification.consumeNotification();
};
OakComponentBase.prototype.setMessage = function (data) {
this.features.message.setMessage(data);
};
OakComponentBase.prototype.consumeMessage = function () {
return this.features.message.consumeMessage();
};
OakComponentBase.prototype.reRender = function (extra) {
return page_common2_1.reRender.call(this, this.option, extra);
};
OakComponentBase.prototype.navigateTo = function (options, state, disableNamespace) {
var url = options.url, rest = tslib_1.__rest(options, ["url"]);
var url2 = url.includes('?')
? url.concat(this.state.oakFullpath
? "&oakFrom=".concat(this.state.oakFullpath)
: '')
: url.concat(this.state.oakFullpath ? "?oakFrom=".concat(this.state.oakFullpath) : '');
for (var param in rest) {
var param2 = param;
if (rest[param2] !== undefined) {
url2 += "".concat(url2.includes('?') ? '&' : '?').concat(param, "=").concat(typeof rest[param2] === 'string'
? rest[param2]
: JSON.stringify(rest[param2]));
}
}
// 路由传入namespace
if (!disableNamespace && this.props.namespace) {
url2 =
(this.props.namespace.startsWith('/') ? '' : '/') +
(this.props.namespace === '/' ? '' : this.props.namespace) +
(url2.startsWith('/') ? '' : '/') +
url2;
}
return this.props.navigate(url2, { replace: false, state: state });
};
OakComponentBase.prototype.navigateBack = function (option) {
var _this = this;
var delta = (option || {}).delta;
return new Promise(function (resolve, reject) {
try {
_this.props.navigate(delta || -1);
resolve(undefined);
}
catch (err) {
reject(err);
}
});
};
OakComponentBase.prototype.redirectTo = function (options, state, disableNamespace) {
var url = options.url, rest = tslib_1.__rest(options, ["url"]);
var url2 = url.includes('?')
? url.concat(this.state.oakFullpath
? "&oakFrom=".concat(this.state.oakFullpath)
: '')
: url.concat(this.state.oakFullpath
? "?oakFrom=".concat(this.state.oakFullpath)
: '');
for (var param in rest) {
var param2 = param;
if (rest[param2] !== undefined) {
url2 += "".concat(url2.includes('?') ? '&' : '?').concat(param, "=").concat(typeof rest[param2] === 'string'
? rest[param2]
: JSON.stringify(rest[param2]));
}
}
// 路由传入namespace
if (!disableNamespace && this.props.namespace) {
url2 =
(this.props.namespace.startsWith('/') ? '' : '/') +
(this.props.namespace === '/' ? '' : this.props.namespace) +
(url2.startsWith('/') ? '' : '/') +
url2;
}
return this.props.navigate(url2, { replace: true, state: state });
};
OakComponentBase.prototype.setProps = function (props, usingState) {
var url = window.location.pathname;
if (usingState) {
return this.props.navigate(url, { replace: true, state: props });
}
else {
// 这里nodejs的url用不了先简单写一个
var url2 = void 0;
var search = window.location.search;
if (!search) {
var search_1 = '';
for (var k in props) {
if (search_1) {
search_1 + '&';
}
if (props[k] !== undefined) {
search_1 += "".concat(k, "=").concat(typeof props[k] === 'string' ? props[k] : JSON.stringify(props[k]));
}
}
url2 = "".concat(url, "?").concat(search_1);
}
else {
(0, assert_1.default)(search.startsWith('?'));
var searchParams = search.slice(1).split('&');
var _loop_1 = function (k) {
var origin_1 = searchParams.find(function (ele) { return ele.startsWith("".concat(k, "=")); });
if (origin_1) {
var idx = searchParams.indexOf(origin_1);
searchParams.splice(idx, 1);
searchParams.push("".concat(k, "=").concat(typeof props[k] === 'string' ? props[k] : JSON.stringify(props[k])));
}
else {
searchParams.push("".concat(k, "=").concat(typeof props[k] === 'string' ? props[k] : JSON.stringify(props[k])));
}
};
for (var k in props) {
_loop_1(k);
}
url2 = "".concat(url, "?").concat(searchParams.join('&'));
}
return this.props.navigate(url2, { replace: true });
}
};
OakComponentBase.prototype.addOperation = function (operation, beforeExecute, afterExecute) {
return this.features.runningTree.addOperation(this.state.oakFullpath, operation, beforeExecute, afterExecute);
};
OakComponentBase.prototype.cleanOperation = function () {
return this.features.runningTree.clean(this.state.oakFullpath);
};
OakComponentBase.prototype.t = function (key, params) {
return this.props.t(key, params);
};
OakComponentBase.prototype.callPicker = function (attr, params) {
if (params === void 0) { params = {}; }
return page_common2_1.callPicker.call(this, attr, params);
};
OakComponentBase.prototype.execute = function () {
return page_common2_1.execute.call(this);
};
OakComponentBase.prototype.checkOperation = function (entity, action, filter, checkerTypes) {
return this.features.cache.checkOperation(entity, action, filter, checkerTypes);
};
OakComponentBase.prototype.tryExecute = function () {
return this.features.runningTree.tryExecute(this.state.oakFullpath);
};
OakComponentBase.prototype.refresh = function () {
return page_common2_1.refresh.call(this);
};
OakComponentBase.prototype.setUpdateData = function (attr, data) {
return page_common2_1.setUpdateData.call(this, attr, data);
};
OakComponentBase.prototype.loadMore = function () {
return page_common2_1.loadMore.call(this);
};
OakComponentBase.prototype.setId = function (id) {
return this.features.runningTree.setId(this.state.oakFullpath, id);
};
OakComponentBase.prototype.setFilters = function (filters) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.features.runningTree.setNamedFilters(this.state.oakFullpath, filters)];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
};
OakComponentBase.prototype.getFilters = function () {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var namedFilters, filters;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!this.state.oakFullpath) return [3 /*break*/, 2];
namedFilters = this.features.runningTree.getNamedFilters(this.state.oakFullpath);
return [4 /*yield*/, Promise.all(namedFilters.map(function (_a) {
var filter = _a.filter;
if (typeof filter === 'function') {
return filter();
}
return filter;
}))];
case 1:
filters = _a.sent();
return [2 /*return*/, filters];
case 2: return [2 /*return*/];
}
});
});
};
OakComponentBase.prototype.getFilterByName = function (name) {
if (this.state.oakFullpath) {
var filter = this.features.runningTree.getNamedFilterByName(this.state.oakFullpath, name);
if (filter === null || filter === void 0 ? void 0 : filter.filter) {
if (typeof filter.filter === 'function') {
return filter.filter();
}
return filter.filter;
}
}
};
OakComponentBase.prototype.addNamedFilter = function (namedFilter, refresh) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.features.runningTree.addNamedFilter(this.state.oakFullpath, namedFilter, refresh)];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
};
OakComponentBase.prototype.removeNamedFilter = function (namedFilter, refresh) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.features.runningTree.removeNamedFilter(this.state.oakFullpath, namedFilter, refresh)];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
};
OakComponentBase.prototype.removeNamedFilterByName = function (name, refresh) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.features.runningTree.removeNamedFilterByName(this.state.oakFullpath, name, refresh)];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
};
OakComponentBase.prototype.setNamedSorters = function (namedSorters) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.features.runningTree.setNamedSorters(this.state.oakFullpath, namedSorters)];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
};
OakComponentBase.prototype.getSorters = function () {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var namedSorters, sorters;
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!this.state.oakFullpath) return [3 /*break*/, 2];
namedSorters = this.features.runningTree.getNamedSorters(this.state.oakFullpath);
return [4 /*yield*/, Promise.all(namedSorters.map(function (_a) {
var sorter = _a.sorter;
if (typeof sorter === 'function') {
return sorter();
}
return sorter;
}))];
case 1:
sorters = (_a.sent()).filter(function (ele) { return !!ele; });
return [2 /*return*/, sorters];
case 2: return [2 /*return*/];
}
});
});
};
OakComponentBase.prototype.getSorterByName = function (name) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
var sorter;
return tslib_1.__generator(this, function (_a) {
if (this.state.oakFullpath) {
sorter = this.features.runningTree.getNamedSorterByName(this.state.oakFullpath, name);
if (sorter === null || sorter === void 0 ? void 0 : sorter.sorter) {
if (typeof sorter.sorter === 'function') {
return [2 /*return*/, sorter.sorter()];
}
return [2 /*return*/, sorter.sorter];
}
}
return [2 /*return*/];
});
});
};
OakComponentBase.prototype.addNamedSorter = function (namedSorter, refresh) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.features.runningTree.addNamedSorter(this.state.oakFullpath, namedSorter, refresh)];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
};
OakComponentBase.prototype.removeNamedSorter = function (namedSorter, refresh) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.features.runningTree.removeNamedSorter(this.state.oakFullpath, namedSorter, refresh)];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
};
OakComponentBase.prototype.removeNamedSorterByName = function (name, refresh) {
return tslib_1.__awaiter(this, void 0, void 0, function () {
return tslib_1.__generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.features.runningTree.removeNamedSorterByName(this.state.oakFullpath, name, refresh)];
case 1:
_a.sent();
return [2 /*return*/];
}
});
});
};
OakComponentBase.prototype.getPagination = function () {
if (this.state.oakFullpath) {
return this.features.runningTree.getPagination(this.state.oakFullpath);
}
};
OakComponentBase.prototype.setPageSize = function (pageSize) {
this.features.runningTree.setPageSize(this.state.oakFullpath, pageSize);
};
OakComponentBase.prototype.setCurrentPage = function (currentPage) {
(0, assert_1.default)(currentPage !== 0);
if (this.state.oakEntity && this.state.oakFullpath) {
this.features.runningTree.setCurrentPage(this.state.oakFullpath, currentPage);
}
};
return OakComponentBase;
}(react_1.default.PureComponent));
function translateObservers(observers) {
return {
fn: function (prevProps, prevState) {
var e_1, _a, e_2, _b;
var _c = this, state = _c.state, props = _c.props;
for (var obs in observers) {
var keys = obs.split(',').map(function (ele) { return ele.trim(); });
var changed = false;
try {
for (var keys_1 = (e_1 = void 0, tslib_1.__values(keys)), keys_1_1 = keys_1.next(); !keys_1_1.done; keys_1_1 = keys_1.next()) {
var k = keys_1_1.value;
if (k.includes('*')) {
throw new Error('web模式下带*的observer通配符暂不支持');
}
if ((0, lodash_1.get)(props, k) !== (0, lodash_1.get)(prevProps, k) ||
(0, lodash_1.get)(state, k) !== (0, lodash_1.get)(prevState, k)) {
changed = true;
break;
}
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (keys_1_1 && !keys_1_1.done && (_a = keys_1.return)) _a.call(keys_1);
}
finally { if (e_1) throw e_1.error; }
}
var args = [];
if (changed) {
try {
for (var keys_2 = (e_2 = void 0, tslib_1.__values(keys)), keys_2_1 = keys_2.next(); !keys_2_1.done; keys_2_1 = keys_2.next()) {
var k = keys_2_1.value;
args.push((0, lodash_1.get)(props, k) === undefined
? (0, lodash_1.get)(state, k)
: (0, lodash_1.get)(props, k));
}
}
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {
try {
if (keys_2_1 && !keys_2_1.done && (_b = keys_2.return)) _b.call(keys_2);
}
finally { if (e_2) throw e_2.error; }
}
observers[obs].apply(this, args);
}
}
},
};
}
var DEFAULT_REACH_BOTTOM_DISTANCE = 50;
function createComponent(option, features, exceptionRouterDict) {
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 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.isReachBottom = false;
_this.scrollEvent = function () {
_this.checkReachBottom();
};
if (methods) {
for (var m in methods) {
Object.assign(_this, (_a = {},
_a[m] = methods[m].bind(_this),
_a));
}
}
_this.state = Object.assign({}, data, {
oakLoading: false,
oakLoadingMore: false,
oakIsReady: false,
oakExeucting: false,
oakDirty: false,
});
(lifetimes === null || lifetimes === void 0 ? void 0 : lifetimes.created) && lifetimes.created.call(_this);
return _this;
}
// todo 这里还需要根据path和location来判断自己是不是page
OakComponentWrapper.prototype.iAmThePage = function () {
return !!path;
};
OakComponentWrapper.prototype.supportPullDownRefresh = function () {
return this.props.width === 'xs' && this.iAmThePage();
};
OakComponentWrapper.prototype.registerPageScroll = function () {
var _a = this.props.useBodyScroll, useBodyScroll = _a === void 0 ? false : _a;
if (useBodyScroll) {
window.addEventListener('scroll', this.scrollEvent);
}
else {
this.lv && this.lv.addEventListener('scroll', this.scrollEvent);
}
};
OakComponentWrapper.prototype.unregisterPageScroll = function () {
var _a = this.props.useBodyScroll, useBodyScroll = _a === void 0 ? false : _a;
if (useBodyScroll) {
window.removeEventListener('scroll', this.scrollEvent);
}
else {
this.lv && this.lv.removeEventListener('scroll', this.scrollEvent);
}
};
OakComponentWrapper.prototype.checkReachBottom = function () {
if (!this.supportPullDownRefresh()) {
return;
}
var isCurrentReachBottom = document.body.scrollHeight -
(window.innerHeight + window.scrollY) <=
DEFAULT_REACH_BOTTOM_DISTANCE;
if (!this.isReachBottom && isCurrentReachBottom && option.isList) {
this.isReachBottom = true;
// 执行触底事件
this.loadMore();
return;
}
this.isReachBottom = isCurrentReachBottom;
};
OakComponentWrapper.prototype.componentDidMount = function () {
this.registerPageScroll();
this.subscribe();
var oakPath = this.props.oakPath;
if (oakPath || this.iAmThePage() && path) {
this.onPathSet();
}
else {
this.reRender();
}
(lifetimes === null || lifetimes === void 0 ? void 0 : lifetimes.attached) && lifetimes.attached.call(this);
(lifetimes === null || lifetimes === void 0 ? void 0 : lifetimes.ready) && lifetimes.ready.call(this);
(lifetimes === null || lifetimes === void 0 ? void 0 : lifetimes.show) && lifetimes.show.call(this);
};
OakComponentWrapper.prototype.componentWillUnmount = function () {
this.state.oakFullpath && this.features.runningTree.destroyNode(this.state.oakFullpath);
(lifetimes === null || lifetimes === void 0 ? void 0 : lifetimes.detached) && lifetimes.detached.call(this);
this.unsubscribe();
this.unregisterPageScroll();
};
OakComponentWrapper.prototype.componentDidUpdate = function (prevProps, prevState) {
if (!prevProps.oakPath && this.props.oakPath) {
this.onPathSet();
}
if (this.props.oakId !== prevProps.oakId) {
this.setId(this.props.oakId);
}
// todo 这里似乎还可能对oakProjection这些东西加以更新等遇到再添加 by Xc
fn && fn.call(this, prevProps, prevState);
};
OakComponentWrapper.prototype.render = function () {
var _this = this;
var Render = render.call(this);
var oakLoading = this.state.oakLoading;
var _a = this.props.useBodyScroll, useBodyScroll = _a === void 0 ? false : _a;
if (this.supportPullDownRefresh()) {
var child = react_1.default.cloneElement((0, jsx_runtime_1.jsx)(web_1.PullToRefresh, { onRefresh: function () {
_this.refresh();
}, refreshing: oakLoading, distanceToRefresh: DEFAULT_REACH_BOTTOM_DISTANCE, indicator: {
activate: this.t('common:ptrActivate'),
deactivate: this.t('common:ptrDeactivate'),
release: this.t('common:ptrRelease'),
finish: this.t('common:ptrFinish'),
} }), {
getScrollContainer: function () { return useBodyScroll ? document.body : _this.lv; },
}, Render);
return useBodyScroll ? (child) : ((0, jsx_runtime_1.jsx)("div", tslib_1.__assign({ ref: function (el) { return (_this.lv = el); }, style: { height: '100%', overflow: 'auto' } }, { children: child })));
}
return Render;
};
return OakComponentWrapper;
}(OakComponentBase));
;
return (0, web_1.withRouter)(OakComponentWrapper, false, option.path);
}
exports.createComponent = createComponent;

View File

@ -1,110 +0,0 @@
var Interpreter = (function (r) {
var o = '';
function i(r, n) {
return r
? 'string' == typeof r
? r
: r
.reduce(function (r, t) {
return r.concat([
(function (n, e) {
if (((e = e || {}), 'string' == typeof n))
return n;
{
var r, t, u;
if (n[2] && 'object' == typeof n[2])
return (
(r = Object.keys(n[2]).reduce(
function (r, t) {
return (
(r[t] = i(
n[2][t],
e
)),
r
);
},
{}
)),
(t = r[e[0]]),
void 0 !== (u = e[n[0]])
? r[u.toString()] ||
r.other ||
o
: t || r.other || o
);
}
if ('object' == typeof n && 0 < n.length)
return (function r(t, n, e) {
void 0 === e && (e = 0);
if (!n || !t || t.length <= 0)
return '';
n = n[t[e]];
if ('string' == typeof n) return n;
if ('number' == typeof n)
return n.toString();
if (!n)
return '{'.concat(
t.join('.'),
'}'
);
return r(t, n, ++e);
})(n[0].split('.'), e, 0);
return '';
})(t, n),
]);
}, [])
.join('')
: o;
}
function c(r, t, n) {
return (
('object' == typeof r &&
((t = t).constructor && 'Array' === t.constructor
? t
: t
.replace(getRegExp('\[', 'ig'), '.')
.replace(getRegExp('\]', 'ig'), '')
.split('.')
).reduce(function (r, t) {
return (r || {})[t];
}, r)) ||
n
);
}
function f(r) {
var t = r;
return (t =
r && -1 !== r.indexOf(':')
? r.replace(getRegExp(':', 'ig'), '.')
: t);
}
function g(r, t, n) {
var e = f(n),
r = r[t];
return (r && (r[e] || c(r, e))) || n;
}
return (
(r.getMessageInterpreter = function () {
function u(r, t, n, e) {
return i(
(function (r, t, n, e) {
var u = f(r);
if (!(n = t[n])) return g(t, e, r);
var o = n[u];
return (o = o || c(n, u)) ? o : g(t, e, r);
})(r, e, n, n),
t
);
}
return function (r, t, n, e) {
return 3 === arguments.length
? u(r, null, t, n)
: 4 === arguments.length
? u(r, t, n, e)
: '';
};
}),
r
);
})({});

View File

@ -41,6 +41,9 @@ function Action(target, propertyName, descriptor) {
switch (_a.label) {
case 0:
mActionStackDepth++;
if (mActionStackDepth > 20) {
console.error("action[".concat(method.name, "]\u8C03\u7528\u7684\u5C42\u7EA7\u8D85\u8FC7\u4E8620\uFF0C\u8BF7\u68C0\u67E5\u662F\u5426\u5B58\u5728\u65E0\u9650\u9012\u5F52"));
}
_a.label = 1;
case 1:
_a.trys.push([1, 3, , 4]);

2
lib/types/Page.d.ts vendored
View File

@ -162,7 +162,7 @@ export declare type OakCommonComponentMethods<ED extends EntityDict & BaseEntity
execute: (action: ED[T]['Action'], legalExceptions?: Array<string>, path?: string) => Promise<DeduceOperation<ED[T]['Schema']> | DeduceOperation<ED[T]['Schema']>[] | undefined>;
};
export declare type OakListComponentMethods<ED extends EntityDict & BaseEntityDict, T extends keyof ED> = {
pushNode: (path?: string, options?: Pick<CreateNodeOptions<ED, keyof ED>, 'updateData' | 'beforeExecute' | 'afterExecute'>) => Promise<void>;
pushNode: (path?: string, options?: CreateNodeOptions<ED, keyof ED>) => Promise<void>;
removeNode: (parent: string, path: string) => Promise<void>;
setFilters: (filters: NamedFilterItem<ED, T>[]) => Promise<void>;
getFilters: () => Promise<ED[T]['Selection']['filter'][] | undefined>;

195
lib/types/Page2.d.ts vendored Normal file
View File

@ -0,0 +1,195 @@
/// <reference types="wechat-miniprogram" />
/// <reference types="react" />
import { Aspect, Context, EntityDict, DeduceSorterItem, SelectRowShape, CheckerType } from "oak-domain/lib/types";
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
import { CommonAspectDict } from 'oak-common-aspect';
import { Feature } from './Feature';
import { Pagination } from "./Pagination";
import { BasicFeatures } from "../features";
import { NamedFilterItem, NamedSorterItem } from './NamedCondition';
import { NotificationProps } from './Notification';
import { MessageProps } from './Message';
declare type RowSelected<ED extends EntityDict & BaseEntityDict, T extends keyof ED, Proj extends ED[T]['Selection']['data'] = Required<ED[T]['Selection']['data']>> = SelectRowShape<ED[T]['Schema'], Proj> | undefined;
interface ComponentOption<ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends Context<ED>, AD extends Record<string, Aspect<ED, Cxt>>, FD extends Record<string, Feature<ED, Cxt, AD & CommonAspectDict<ED, Cxt>>>, Proj extends ED[T]['Selection']['data'], FormedData extends Record<string, any>, IsList extends boolean, TProperty extends WechatMiniprogram.Component.PropertyOption = {}> {
entity?: T;
path?: string;
isList: IsList;
projection?: Proj | ((options: {
features: BasicFeatures<ED, Cxt, AD & CommonAspectDict<ED, Cxt>> & FD;
props: Partial<WechatMiniprogram.Component.PropertyOptionToData<TProperty>>;
state: Record<string, any>;
}) => Promise<Proj>);
append?: boolean;
pagination?: Pagination;
filters?: Array<{
filter: ED[T]['Selection']['filter'] | ((options: {
features: BasicFeatures<ED, Cxt, AD & CommonAspectDict<ED, Cxt>> & FD;
props: Partial<WechatMiniprogram.Component.PropertyOptionToData<TProperty>>;
state: Record<string, any>;
}) => Promise<ED[T]['Selection']['filter']> | undefined);
'#name'?: string;
}>;
sorters?: Array<{
sorter: DeduceSorterItem<ED[T]['Schema']> | ((options: {
features: BasicFeatures<ED, Cxt, AD & CommonAspectDict<ED, Cxt>> & FD;
props: Partial<WechatMiniprogram.Component.PropertyOptionToData<TProperty>>;
state: Record<string, any>;
}) => Promise<DeduceSorterItem<ED[T]['Schema']>>);
'#name'?: string;
}>;
formData?: (options: {
data: IsList extends true ? RowSelected<ED, T, Proj>[] : RowSelected<ED, T, Proj>;
features: BasicFeatures<ED, Cxt, AD & CommonAspectDict<ED, Cxt>> & FD;
props: Partial<WechatMiniprogram.Component.PropertyOptionToData<TProperty>>;
}) => Promise<FormedData>;
ns?: T | T[];
}
export declare type MiniprogramStyleMethods = {
animate(selector: string, keyFrames: WechatMiniprogram.Component.KeyFrame[], duration: number, callback?: () => void): void;
clearAnimation(selector: string, options?: WechatMiniprogram.Component.ClearAnimationOptions, callback?: () => void): void;
triggerEvent: <DetailType = any>(name: string, detail?: DetailType, options?: WechatMiniprogram.Component.TriggerEventOption) => void;
};
export declare type ComponentProps<IsList extends boolean, TProperty extends WechatMiniprogram.Component.PropertyOption> = IsList extends true ? WechatMiniprogram.Component.PropertyOptionToData<OakListComponentProperties & OakComponentProperties & TProperty> : WechatMiniprogram.Component.PropertyOptionToData<OakComponentProperties & TProperty>;
export declare type ComponentData<ED extends EntityDict & BaseEntityDict, T extends keyof ED, FormedData extends WechatMiniprogram.Component.DataOption, TData extends WechatMiniprogram.Component.DataOption> = TData & FormedData & OakComponentData<ED, T>;
export declare type ComponentPublicThisType<ED extends EntityDict & BaseEntityDict, T extends keyof ED, Cxt extends Context<ED>, AD extends Record<string, Aspect<ED, Cxt>>, FD extends Record<string, Feature<ED, Cxt, AD & CommonAspectDict<ED, Cxt>>>, FormedData extends Record<string, any>, IsList extends boolean, TData extends Record<string, any> = {}, TProperty extends WechatMiniprogram.Component.PropertyOption = {}, TMethod extends WechatMiniprogram.Component.MethodOption = {}> = {
features: FD & BasicFeatures<ED, Cxt, AD & CommonAspectDict<ED, Cxt>>;
state: ComponentData<ED, T, FormedData, TData>;
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>> = {
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;
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<ED, Cxt, AD & CommonAspectDict<ED, Cxt>>>, 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;
methods: TMethod;
lifetimes: {
created?(): void;
attached?(): void;
ready?(): void;
moved?(): void;
detached?(): void;
error?(err: Error): void;
show?(): void;
hide?(): void;
};
observers: Record<string, (...args: any[]) => any>;
}> & Partial<{
wechatMp: {
externalClasses?: string[];
options?: Partial<WechatMiniprogram.Component.ComponentOptions> | undefined;
};
}> & ThisType<ComponentPublicThisType<ED, T, Cxt, AD, FD, FormedData, IsList, TData, TProperty, TMethod>>;
export declare type OakComponentProperties = {
oakEntity: StringConstructor;
oakPath: StringConstructor;
oakId: StringConstructor;
oakProjection: StringConstructor;
oakFrom: StringConstructor;
oakParentEntity: StringConstructor;
enablePullDownRefresh: BooleanConstructor;
};
export declare type OakListComponentProperties = {
oakFilters: StringConstructor;
oakSorters: StringConstructor;
oakIsPicker: BooleanConstructor;
};
export declare type OakNavigateToParameters<ED extends EntityDict & BaseEntityDict, T extends keyof ED> = {
oakId?: string;
oakEntity?: T;
oakPath?: string;
oakParent?: string;
oakProjection?: ED[T]['Selection']['data'];
oakSorters?: Array<NamedSorterItem<ED, T>>;
oakFilters?: Array<NamedFilterItem<ED, T>>;
oakIsPicker?: boolean;
[k: string]: any;
};
export declare type OakHiddenComponentMethods = {
subscribed?: () => void;
subscribe: () => void;
unsubscribe: () => void;
};
export declare type OakCommonComponentMethods<ED extends EntityDict & BaseEntityDict, T extends keyof ED> = {
sub: (type: string, callback: Function) => void;
unsub: (type: string, callback: Function) => void;
pub: (type: string, options?: any) => void;
unsubAll: (type: string) => void;
save: (key: string, item: any) => void;
load: (key: string) => any;
clear: () => void;
resolveInput: <K extends string>(input: any, keys?: K[]) => {
dataset?: Record<string, any>;
value?: string;
} & {
[k in K]?: any;
};
setNotification: (data: NotificationProps) => void;
consumeNotification: () => NotificationProps | undefined;
setMessage: (data: MessageProps) => void;
consumeMessage: () => MessageProps | undefined;
reRender: (extra?: Record<string, any>) => Promise<void>;
navigateTo: <T2 extends keyof ED>(options: {
url: string;
} & OakNavigateToParameters<ED, T2>, state?: Record<string, any>, disableNamespace?: boolean) => Promise<void>;
navigateBack: (option?: {
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>;
setProps: (props: Record<string, any>, usingState?: true) => void;
resetUpdateData: () => void;
addOperation: (operation: Omit<ED[T]['Operation'], 'id'>, beforeExecute?: () => Promise<void>, afterExecute?: () => Promise<void>) => Promise<void>;
cleanOperation: () => void;
t(key: string, params?: object): string;
callPicker: (attr: string, params: Record<string, any>) => void;
execute: () => Promise<void>;
checkOperation: (ntity: T, action: ED[T]['Action'], filter?: ED[T]['Update']['filter'], checkerTypes?: CheckerType[]) => Promise<boolean>;
tryExecute: () => Promise<void>;
refresh: (extra?: any) => Promise<void>;
setUpdateData: (data: string, attr: any) => Promise<void>;
};
export declare type OakListComponentMethods<ED extends EntityDict & BaseEntityDict, T extends keyof ED> = {
loadMore: () => Promise<void>;
setFilters: (filters: NamedFilterItem<ED, T>[]) => Promise<void>;
getFilters: () => Promise<ED[T]['Selection']['filter'][] | undefined>;
getFilterByName: (name: string) => Promise<ED[T]['Selection']['filter']> | undefined;
addNamedFilter: (filter: NamedFilterItem<ED, T>, refresh?: boolean) => Promise<void>;
removeNamedFilter: (filter: NamedFilterItem<ED, T>, refresh?: boolean) => Promise<void>;
removeNamedFilterByName: (name: string, refresh?: boolean) => Promise<void>;
setNamedSorters: (sorters: NamedSorterItem<ED, T>[]) => Promise<void>;
getSorters: () => Promise<ED[T]['Selection']['sorter'] | undefined>;
getSorterByName: (name: string) => Promise<DeduceSorterItem<ED[T]['Schema']> | undefined>;
addNamedSorter: (filter: NamedSorterItem<ED, T>, refresh?: boolean) => Promise<void>;
removeNamedSorter: (filter: NamedSorterItem<ED, T>, refresh?: boolean) => Promise<void>;
removeNamedSorterByName: (name: string, refresh?: boolean) => Promise<void>;
getPagination: () => Pagination | undefined;
setPageSize: (pageSize: number) => void;
setCurrentPage: (current: number) => void;
};
declare type ComponentOnPropsChangeOption = {
path?: string;
parent?: string;
};
export declare type OakComponentOnlyMethods = {
onPropsChanged: (options: ComponentOnPropsChangeOption) => void;
registerReRender: () => void;
setOakActions: () => void;
};
export declare type OakComponentData<ED extends EntityDict & BaseEntityDict, T extends keyof ED> = {
oakExecuting: boolean;
oakFocused: object;
oakDirty: boolean;
oakLoading: boolean;
oakLoadingMore: boolean;
oakEntity: T;
oakIsReady: boolean;
oakFullpath: string;
};
export declare type MakeOakComponent<ED extends EntityDict & BaseEntityDict, Cxt extends Context<ED>, AD extends Record<string, Aspect<ED, Cxt>>, FD extends Record<string, Feature<ED, Cxt, AD & CommonAspectDict<ED, Cxt>>>> = <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 {};

3
lib/types/Page2.js Normal file
View File

@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
;

View File

@ -85,7 +85,7 @@ export class Cache<
selection: ED[T]['Selection'],
option?: OP
) {
reinforceSelection(this.cacheStore!.getSchema(), entity, selection);
// reinforceSelection(this.cacheStore!.getSchema(), entity, selection);
const { result } = await this.getAspectWrapper().exec('count', {
entity,
selection,

View File

@ -1,5 +1,5 @@
import { assert } from 'oak-domain/lib/utils/assert';
import { cloneDeep, pull, set, unset } from "oak-domain/lib/utils/lodash";
import { cloneDeep, pull, set, unset, merge } from "oak-domain/lib/utils/lodash";
import { combineFilters, contains, repel, same } from "oak-domain/lib/store/filter";
import { createOperationsFromModies } from 'oak-domain/lib/store/modi';
import { judgeRelation } from "oak-domain/lib/store/relation";
@ -31,6 +31,7 @@ abstract class Node<ED extends EntityDict & BaseEntityDict, T extends keyof ED,
protected loadingMore: boolean;
protected executing: boolean;
protected operations: Operation<ED, T>[];
protected modiIds: string[]; // 对象所关联的modi的id
constructor(entity: T, schema: StorageSchema<ED>, cache: Cache<ED, Cxt, AD>,
projection: ED[T]['Selection']['data'] | (() => Promise<ED[T]['Selection']['data']>),
@ -45,12 +46,35 @@ abstract class Node<ED extends EntityDict & BaseEntityDict, T extends keyof ED,
this.loadingMore = false;
this.executing = false;
this.operations = [];
this.modiIds = [];
}
getEntity() {
return this.entity;
}
protected abstract getChildPath(child: Node<ED, keyof ED, Cxt, AD>): string;
/**
* modi
*/
getModiIds(child: Node<ED, keyof ED, Cxt, AD>): string[] {
const childPath = this.getChildPath(child);
if (childPath.includes(':')) {
const { modiIds } = this;
// 如果是需要modi的路径在这里应该就可以返回了目前应该不存在modi嵌套modi
return modiIds;
}
const { toModi } = this.schema[this.entity];
if (toModi) {
// 如果这就是一个toModi的对象则不用再向上查找了
return [];
}
if (this.parent) {
return this.parent.getModiIds(this);
}
return [];
}
setDirty() {
if (!this.dirty) {
@ -85,8 +109,8 @@ abstract class Node<ED extends EntityDict & BaseEntityDict, T extends keyof ED,
return this.parent;
}
async getProjection() {
return typeof this.projection === 'function' ? await this.projection() : this.projection;
protected async getProjection() {
return typeof this.projection === 'function' ? await this.projection() : cloneDeep(this.projection);
}
protected judgeRelation(attr: string) {
@ -310,6 +334,18 @@ class ListNode<
private syncHandler: (records: OpRecord<ED>[]) => Promise<void>;
protected getChildPath(child: Node<ED, keyof ED, Cxt, AD>): string {
let idx = 0;
for (const child2 of this.children) {
if (child === child2) {
return `${idx}`;
}
idx ++;
}
assert(false);
}
async onCacheSync(records: OpRecord<ED>[]): Promise<void> {
// 只需要处理insert
if (this.loading) {
@ -342,7 +378,7 @@ class ListNode<
if (createdIds.length > 0) {
const currentIds = this.ids;
const { sorter, filters } = await this.constructSelection();
const { sorter, filters } = await this.constructSelection(true);
filters.push({
id: {
$in: currentIds.concat(createdIds),
@ -560,6 +596,31 @@ class ListNode<
}
}
}
// 如果本结点是在modi路径上需要将modi更新之后再得到后项
const modiIds = this.parent ? this.parent.getModiIds(this) : [];
const operations = modiIds.map(
ele => ({
entity: 'modi',
operation: {
action: 'apply',
data: {},
filter: {
id: ele,
},
}
})
) as Array<{
entity: keyof ED;
operation: ED[keyof ED]['Operation'];
}>;
operations.push(...this.operations.map(
ele => ({
entity: this.entity,
operation: ele.oper,
})
));
const { result } = await this.cache.tryRedoOperationsThenSelect(this.entity, {
data: projection,
filter: {
@ -567,12 +628,7 @@ class ListNode<
$in: ids,
}
} as any,
}, this.operations.map(
ele => ({
entity: this.entity,
operation: ele.oper,
})
));
}, operations);
return result;
}
@ -612,10 +668,19 @@ class ListNode<
return operations;
}
private async constructSelection() {
async getProjection(): Promise<ED[T]['Selection']['data']> {
const projection = await super.getProjection();
if (this.children.length > 0) {
const subProjection = await this.children[0].getProjection();
return merge(projection, subProjection);
}
return projection;
}
async constructSelection(withParent?: true) {
const { filters, sorters } = this;
const proj = await this.getProjection();
assert(proj, "取数据时找不到projection信息");
const data = await this.getProjection();
assert(data, "取数据时找不到projection信息");
const sorterArr = (
await Promise.all(
sorters.map(async (ele) => {
@ -638,11 +703,15 @@ class ListNode<
})
);
const filterOfParent = (this.parent as SingleNode<ED, keyof ED, Cxt, AD>)?.getOtmFilter<T>(this);
filterArr.push(filterOfParent as any);
if (withParent) {
const filterOfParent = (this.parent as SingleNode<ED, keyof ED, Cxt, AD>)?.getOtmFilter<T>(this);
if (filterOfParent) {
filterArr.push(filterOfParent as any);
}
}
return {
projection: proj,
data,
filters: filterArr.filter(ele => !!ele) as ED[T]['Selection']['filter'][],
sorter: sorterArr,
}
@ -658,7 +727,7 @@ class ListNode<
this.loading = true;
}
const currentPage3 = typeof pageNumber === 'number' ? pageNumber : currentPage;
const { projection, filters, sorter } = await this.constructSelection();
const { data: projection, filters, sorter } = await this.constructSelection(true);
try {
const { data, count } = await this.cache.refresh(
entity,
@ -746,97 +815,15 @@ class SingleNode<ED extends EntityDict & BaseEntityDict,
parent?: Node<ED, keyof ED, Cxt, AD>) {
super(entity, schema, cache, projection, parent);
this.children = {};
}
const ownKeys: string[] = [];
const attrs = Object.keys(projectionShape);
const { toModi } = schema[entity];
attrs.forEach(
(attr) => {
const proj = typeof projection === 'function' ? async () => {
const projection2 = await projection();
return projection2[attr];
} : projection[attr];
const rel = this.judgeRelation(attr);
if (rel === 2) {
const node = new SingleNode(attr, this.schema, this.cache, proj, projectionShape[attr], this);
Object.assign(this.children, {
[attr]: node,
});
if (toModi && attr !== 'modi$entity') {
const node2 = new SingleNode(attr, this.schema, this.cache, proj, projectionShape[attr], this);
Object.assign(this.children, {
[`${attr}:prev`]: node2,
});
}
}
else if (typeof rel === 'string') {
const node = new SingleNode(rel, this.schema, this.cache, proj, projectionShape[attr], this);
Object.assign(this.children, {
[attr]: node,
});
if (toModi && attr !== 'modi$entity') {
const node2 = new SingleNode(attr, this.schema, this.cache, proj, projectionShape[attr], this);
Object.assign(this.children, {
[`${attr}:prev`]: node2,
});
}
}
else if (typeof rel === 'object' && rel instanceof Array) {
const { data: subProjectionShape } = projectionShape[attr] as ED[keyof ED]['Selection'];
const proj = typeof projection === 'function' ? async () => {
const projection2 = await projection();
return projection2[attr].data;
} : projection[attr].data;
const filter = typeof projection === 'function' ? async () => {
const projection2 = await projection();
return projection2[attr].filter;
} : projection[attr].filter;
const sorters = typeof projection === 'function' ? async () => {
const projection2 = await projection();
return projection2[attr].sorter;
} : projection[attr].sorter;
const node = new ListNode(rel[0], this.schema, this.cache, proj, subProjectionShape, this);
if (filter) {
node.addNamedFilter({
filter,
});
}
if (sorters && sorters instanceof Array) {
// todo 没有处理projection是一个function的case
sorters.forEach(
ele => node.addNamedSorter({
sorter: ele
})
);
}
Object.assign(this.children, {
[attr]: node,
});
if (toModi && attr !== 'modi$entity') {
const node2 = new ListNode(rel[0], this.schema, this.cache, proj, subProjectionShape, this);
if (filter) {
node2.addNamedFilter({
filter,
});
}
if (sorters && sorters instanceof Array) {
// todo 没有处理projection是一个function的case
sorters.forEach(
ele => node2.addNamedSorter({
sorter: ele
})
);
}
Object.assign(this.children, {
[`${attr}:prev`]: node2,
});
}
}
else {
ownKeys.push(attr);
}
protected getChildPath(child: Node<ED, keyof ED, Cxt, AD>): string {
for (const k in this.children) {
if (child === this.children[k]) {
return k;
}
);
}
assert(false);
}
destroy(): void {
@ -929,17 +916,36 @@ class SingleNode<ED extends EntityDict & BaseEntityDict,
async getFreshValue(): Promise<SelectRowShape<ED[T]['Schema'], ED[T]['Selection']['data']>> {
const projection = typeof this.projection === 'function' ? await this.projection() : this.projection;
// 如果本结点是在modi路径上需要将modi更新之后再得到后项
const modiIds = this.parent ? this.parent.getModiIds(this) : [];
const operations = modiIds.map(
ele => ({
entity: 'modi',
operation: {
action: 'apply',
data: {},
filter: {
id: ele,
},
}
})
) as Array<{
entity: keyof ED;
operation: ED[keyof ED]['Operation'];
}>;
operations.push(...this.operations.map(
ele => ({
entity: this.entity,
operation: ele.oper,
})
));
const { result } = await this.cache.tryRedoOperationsThenSelect(this.entity, {
data: projection,
filter: {
id: this.id,
} as any,
}, this.operations.map(
ele => ({
entity: this.entity,
operation: ele.oper
})
));
}, operations);
return result[0];
}
@ -999,12 +1005,15 @@ class SingleNode<ED extends EntityDict & BaseEntityDict,
}
}
}
const sliceIdx = ele.indexOf(':');
const ele2 = sliceIdx > 0 ? ele.slice(0, sliceIdx) : ele;
return {
oper: {
id: 'dummy', // 因为肯定会被merge掉所以无所谓了
action: 'update',
data: {
[ele]: subOper,
[ele2]: subOper,
},
filter: {
id: this.id,
@ -1041,6 +1050,33 @@ class SingleNode<ED extends EntityDict & BaseEntityDict,
return operations;
}
async getProjection() {
const projection = await super.getProjection();
for (const k in this.children) {
if (k.indexOf(':') === -1) {
const rel = this.judgeRelation(k);
if (rel === 2 || typeof rel === 'string') {
const subProjection = await this.children[k].getProjection();
Object.assign(projection, {
[k]: subProjection,
});
}
else {
const child = this.children[k];
assert(rel instanceof Array && child instanceof ListNode);
const subSelection = await child.constructSelection();
const subEntity = child.getEntity();
Object.assign(projection, {
[k]: Object.assign(subSelection, {
$entity: subEntity,
})
});
}
}
}
return projection;
}
async refresh() {
const projection = await this.getProjection();
if (this.id) {
@ -1052,6 +1088,11 @@ class SingleNode<ED extends EntityDict & BaseEntityDict,
id: this.id,
},
} as any);
// 对于modi对象在此缓存
if (this.schema[this.entity].toModi) {
const { modi$entity } = value;
this.modiIds = (modi$entity as Array<{ id: string }>).map(ele => ele.id);
}
this.loading = false;
}
catch (err) {
@ -1073,7 +1114,9 @@ class SingleNode<ED extends EntityDict & BaseEntityDict,
getOtmFilter<T2 extends keyof ED>(childNode: ListNode<ED, keyof ED, Cxt, AD>): ED[T2]['Selection']['filter'] {
for (const key in this.children) {
if (childNode === this.children[key]) {
const rel = this.judgeRelation(key);
const sliceIdx = key.indexOf(':');
const key2 = sliceIdx > 0 ? key.slice(0, sliceIdx) : key;
const rel = this.judgeRelation(key2);
assert(rel instanceof Array);
if (rel[1]) {
// 基于普通外键的一对多
@ -1174,7 +1217,6 @@ export class RunningTree<
sorters,
pagination
);
node.refresh();
} else {
node = new SingleNode<ED, T, Cxt, AD>(
entity,
@ -1184,9 +1226,6 @@ export class RunningTree<
projectionShape,
parentNode
);
if (id) {
node.setId(id);
}
}
if (parentNode) {
parentNode.addChild(path, node as any);
@ -1194,6 +1233,12 @@ export class RunningTree<
assert(!parent && !this.root[path]);
this.root[path] = node;
}
if (isList) {
node.refresh();
}
else if (id) {
(<SingleNode<ED, T, Cxt, AD>>node).setId(id);
}
return node;
}

View File

@ -19,8 +19,8 @@ import { BasicFeatures } from './features';
import { ActionDictOfEntityDict } from 'oak-domain/lib/types/Action';
import { CommonAspectDict } from 'oak-common-aspect';
import { ExceptionHandler, ExceptionRouters } from './types/ExceptionRoute';
import { OakComponentOption, OakPageOption } from './types/Page';
import { createComponent, createPage } from './page.mp';
import { OakComponentOption } from './types/Page2';
import { createComponent } from './page.mp';
import { initialize as initDev } from './initialize-dev';
import { getI18next, I18nOptions } from './platforms/wechatMp/i18n';
@ -73,6 +73,7 @@ export function initialize<
Object.assign(global, {
OakComponent: <
T extends keyof ED,
Proj extends ED[T]['Selection']['data'],
FormedData extends WechatMiniprogram.Component.DataOption,
IsList extends boolean,
TData extends WechatMiniprogram.Component.DataOption = {},
@ -85,6 +86,7 @@ export function initialize<
Cxt,
AD,
FD,
Proj,
FormedData,
IsList,
TData,

View File

@ -18,8 +18,8 @@ import { BasicFeatures } from './features';
import { ActionDictOfEntityDict } from 'oak-domain/lib/types/Action';
import { CommonAspectDict } from 'oak-common-aspect';
import { ExceptionHandler, ExceptionRouters } from './types/ExceptionRoute';
import { OakComponentOption, OakPageOption } from './types/Page';
import { createComponent, createPage } from './page.mp';
import { OakComponentOption } from './types/Page2';
import { createComponent } from './page.mp';
import { initialize as initProd } from './initialize-prod';
import { getI18next, I18nOptions } from './platforms/wechatMp/i18n';
@ -60,44 +60,9 @@ export function initialize<
const i18n = getI18next(i18nOptions);
Object.assign(global, {
OakPage: <
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: OakPageOption<
ED,
T,
Cxt,
AD,
FD,
Proj,
FormedData,
IsList,
TData,
TProperty,
TMethod
>
) =>
createPage<
ED,
T,
Cxt,
AD,
FD,
Proj,
FormedData,
IsList,
TData,
TProperty,
TMethod
>(options, features, exceptionRouterDict),
OakComponent: <
T extends keyof ED,
Proj extends ED[T]['Selection']['data'],
FormedData extends WechatMiniprogram.Component.DataOption,
IsList extends boolean,
TData extends WechatMiniprogram.Component.DataOption = {},
@ -110,6 +75,7 @@ export function initialize<
Cxt,
AD,
FD,
Proj,
FormedData,
IsList,
TData,

View File

@ -18,8 +18,8 @@ import { BasicFeatures } from './features';
import { ActionDictOfEntityDict } from 'oak-domain/lib/types/Action';
import { CommonAspectDict } from 'oak-common-aspect';
import { ExceptionHandler, ExceptionRouters } from './types/ExceptionRoute';
import { OakComponentOption, OakPageOption } from './types/Page';
import { createComponent, createPage } from './page.web';
import { OakComponentOption } from './types/Page2';
import { createComponent } from './page.web2';
import { initialize as initProd } from './initialize-prod';
import { getI18next, I18nOptions } from './platforms/web/i18n';
@ -61,46 +61,11 @@ export function initialize<
const i18n = getI18next(i18nOptions);
Object.assign(global, {
OakPage: <
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: OakPageOption<
ED,
T,
Cxt,
AD,
FD,
Proj,
FormedData,
IsList,
TData,
TProperty,
TMethod
>
) =>
createPage<
ED,
T,
Cxt,
AD,
FD,
Proj,
FormedData,
IsList,
TData,
TProperty,
TMethod
>(options, features, exceptionRouterDict),
OakComponent: <
T extends keyof ED,
FormedData extends WechatMiniprogram.Component.DataOption,
IsList extends boolean,
Proj extends ED[T]['Selection']['data'],
TData extends WechatMiniprogram.Component.DataOption = {},
TProperty extends WechatMiniprogram.Component.PropertyOption = {},
TMethod extends WechatMiniprogram.Component.MethodOption = {}
@ -111,6 +76,7 @@ export function initialize<
Cxt,
AD,
FD,
Proj,
FormedData,
IsList,
TData,
@ -124,6 +90,7 @@ export function initialize<
Cxt,
AD,
FD,
Proj,
FormedData,
IsList,
TData,

View File

@ -1,950 +0,0 @@
import { assert } from 'oak-domain/lib/utils/assert';
import { CommonAspectDict } from 'oak-common-aspect';
import {
Aspect,
Context,
DeduceSorterItem,
EntityDict,
OakException,
OakInputIllegalException,
} from 'oak-domain/lib/types';
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
import { BasicFeatures } from './features';
import { ExceptionHandler } from './types/ExceptionRoute';
import { Feature, subscribe } from './types/Feature';
import { NamedFilterItem, NamedSorterItem } from './types/NamedCondition';
import {
OakCommonComponentMethods,
OakComponentData,
OakComponentOption,
OakComponentProperties,
OakHiddenComponentMethods,
OakListComponentMethods,
OakComponentOnlyMethods,
OakPageMethods,
OakPageOption,
} from './types/Page';
export type ComponentProps<
TProperty extends WechatMiniprogram.Component.PropertyOption
> = WechatMiniprogram.Component.PropertyOptionToData<
OakComponentProperties & TProperty
>;
export type ComponentData<
ED extends EntityDict & BaseEntityDict,
T extends keyof ED,
FormedData extends WechatMiniprogram.Component.DataOption,
TData extends WechatMiniprogram.Component.DataOption
> = TData & FormedData & OakComponentData<ED, T>;
export type ComponentThisType<
ED extends EntityDict & BaseEntityDict,
T extends keyof ED,
FormedData extends WechatMiniprogram.Component.DataOption,
IsList extends boolean,
TData extends WechatMiniprogram.Component.DataOption,
TProperty extends WechatMiniprogram.Component.PropertyOption,
TMethod extends WechatMiniprogram.Component.MethodOption
> = ThisType<
{
state: ComponentData<ED, T, FormedData, TData>;
props: ComponentProps<TProperty>;
setState: (data: any, callback?: () => void) => Promise<void>;
triggerEvent: <DetailType = any>(
name: string,
detail?: DetailType,
options?: WechatMiniprogram.Component.TriggerEventOption
) => void;
} & TMethod &
OakCommonComponentMethods<ED, T> &
OakHiddenComponentMethods &
(IsList extends true ? OakListComponentMethods<ED, T> : {})
>;
export function makeHiddenComponentMethods<
ED extends EntityDict & BaseEntityDict,
T extends keyof ED,
FormedData extends WechatMiniprogram.Component.DataOption,
IsList extends boolean,
TData extends WechatMiniprogram.Component.DataOption,
TProperty extends WechatMiniprogram.Component.PropertyOption,
TMethod extends WechatMiniprogram.Component.MethodOption
>(): OakHiddenComponentMethods &
ComponentThisType<ED, T, FormedData, IsList, TData, TProperty, TMethod> {
return {
subscribe() {
if (!this.subscribed) {
this.subscribed = subscribe(() => this.reRender());
}
},
unsubscribe() {
if (this.subscribed) {
this.subscribed();
this.subscribed = undefined;
}
},
};
}
export function makeCommonComponentMethods<
ED extends EntityDict & BaseEntityDict,
T extends keyof ED,
Cxt extends Context<ED>,
AD extends Record<string, Aspect<ED, Cxt>>,
FD extends Record<string, Feature<ED, Cxt, AD & CommonAspectDict<ED, Cxt>>>,
FormedData extends WechatMiniprogram.Component.DataOption,
Proj extends ED[T]['Selection']['data'],
IsList extends boolean,
TData extends WechatMiniprogram.Component.DataOption = {},
TProperty extends WechatMiniprogram.Component.PropertyOption = {},
TMethod extends WechatMiniprogram.Component.MethodOption = {}
>(
features: BasicFeatures<ED, Cxt, AD & CommonAspectDict<ED, Cxt>> & FD,
exceptionRouterDict: Record<string, ExceptionHandler>,
formData: OakPageOption<
ED,
T,
Cxt,
AD,
FD,
Proj,
FormedData,
IsList,
TData,
TProperty,
TMethod
>['formData']
): Omit<
OakCommonComponentMethods<ED, T>,
'navigateTo' | 'navigateBack' | 'resolveInput' | 'redirectTo' | 't'
> &
ComponentThisType<ED, T, FormedData, IsList, TData, TProperty, TMethod> {
return {
sub(type: string, callback: Function) {
features.eventBus.sub(type, callback);
},
unsub(type: string, callback: Function) {
features.eventBus.unsub(type, callback);
},
pub(type: string, options?: any) {
features.eventBus.pub(type, options);
},
unsubAll(type: string) {
features.eventBus.unsubAll(type);
},
save(key, item) {
features.localStorage.save(key, item);
},
load(key) {
return features.localStorage.load(key);
},
clear() {
features.localStorage.clear();
},
setNotification(data) {
features.notification.setNotification(data);
},
consumeNotification() {
return features.notification.consumeNotification();
},
setMessage(data) {
features.message.setMessage(data);
},
consumeMessage() {
return features.message.consumeMessage();
},
async reRender(extra) {
if (this.state.oakEntity && this.state.oakFullpath) {
const rows = features.runningTree.getFreshValue(
this.state.oakFullpath
);
const dirty = features.runningTree.isDirty(
this.state.oakFullpath
);
const oakLegalActions = [];
if (this.state.newOakActions) {
for (const action of this.state.newOakActions) {
try {
await features.runningTree.testAction(
this.state.oakFullpath,
action
);
oakLegalActions.push(action);
} catch (e) {
if (e instanceof OakInputIllegalException) {
oakLegalActions.push(action);
}
}
}
}
const data: Record<string, any> = formData
? await formData.call(this, {
data: rows as any,
features,
props: this.props,
legalActions: oakLegalActions,
})
: {};
for (const k in data) {
if (data[k] === undefined) {
Object.assign(data, {
[k]: null,
});
}
}
Object.assign(data, { oakDirty: dirty });
if (extra) {
Object.assign(data, extra);
}
Object.assign(data, {
oakLegalActions,
});
this.setState(data);
} else {
/**
* data属性为undefined
* 使oakpage的entity属性为空也不行
*/
const data: Record<string, any> = formData
? await formData.call(this, {
features,
props: this.props,
} as any)
: {};
if (extra) {
Object.assign(data, extra);
}
this.setState(data);
}
},
callPicker(attr: string, params: Record<string, any>) {
if (this.state.oakExecuting) {
return;
}
const relation = features.cache.judgeRelation(
this.state.oakEntity,
attr
);
let subEntity: string;
if (relation === 2) {
subEntity = attr;
} else {
assert(typeof relation === 'string');
subEntity = relation;
}
let url = `/pickers/${subEntity}?oakIsPicker=true&oakParentEntity=${this.state.oakEntity}&oakParent=${this.state.oakFullpath}&oakPath=${attr}`;
for (const k in params) {
url += `&${k}=${JSON.stringify(params[k])}`;
}
this.navigateTo({
url,
});
},
async setForeignKey(id: string, goBackDelta: number = -1) {
if (this.state.oakExecuting) {
return;
}
const { oakIsPicker, oakParent, oakPath } = this.state;
assert(oakIsPicker);
await features.runningTree.setForeignKey(oakParent, oakPath, id);
if (goBackDelta !== 0) {
this.navigateBack({
delta: goBackDelta,
});
}
},
async addForeignKeys(ids: string[], goBackDelta: number = -1) {
if (this.state.oakExecuting) {
return;
}
const { oakIsPicker, oakParent, oakPath } = this.state;
assert(oakIsPicker);
await features.runningTree.addForeignKeys(oakParent, oakPath, ids);
if (goBackDelta !== 0) {
this.navigateBack({
delta: goBackDelta,
});
}
},
async setUniqueForeignKeys(ids: string[], goBackDelta: number = -1) {
if (this.state.oakExecuting) {
return;
}
const { oakIsPicker, oakParent, oakPath } = this.state;
assert(oakIsPicker);
await features.runningTree.setUniqueForeignKeys(oakParent, oakPath, ids);
if (goBackDelta !== 0) {
this.navigateBack({
delta: goBackDelta,
});
}
},
async toggleNode(
nodeData: Record<string, any>,
checked: boolean,
path?: string
) {
const fullpath = path
? `${this.state.oakFullpath}.${path}`
: this.state.oakFullpath;
await features.runningTree.toggleNode(fullpath, nodeData, checked);
},
async execute(action, legalExceptions, path) {
if (this.state.oakExecuting) {
return;
}
this.setState({
oakExecuting: true,
oakFocused: {},
});
try {
const fullpath = path
? `${this.state.oakFullpath}.${path}`
: this.state.oakFullpath;
const result = await features.runningTree.execute(
fullpath,
action
);
this.setState({ oakExecuting: false });
this.setMessage({
type: 'success',
content: '操作成功',
});
return result;
} catch (err) {
if (err instanceof OakException) {
if (err instanceof OakInputIllegalException) {
const attr = err.getAttributes()[0];
this.setState({
oakFocused: {
[attr]: true,
},
oakExecuting: false,
});
this.setMessage({
type: 'warning',
content: err.message,
});
} else {
const { name } = err.constructor;
const handler = exceptionRouterDict[name];
if (legalExceptions && legalExceptions.includes(name)) {
// 如果调用时就知道有异常,直接抛出
this.setState({
oakExecuting: false,
});
throw err;
} else if (handler) {
const {
hidden,
level,
handler: fn,
router,
disableNamespace,
} = handler;
if (!hidden) {
this.setState({
oakExecuting: false,
});
this.setMessage({
type: level || 'warning',
content: err.message,
});
} else {
this.setState({
oakExecuting: false,
});
}
if (fn) {
fn(err);
return;
} else if (router) {
this.setState({
oakExecuting: false,
});
this.navigateTo(
{
url: router,
},
{
exception: err.toString(),
},
disableNamespace
);
}
} else {
this.setState({
oakExecuting: false,
});
this.setMessage({
type: 'warning',
content: err.message,
});
}
}
} else {
this.setState({
oakExecuting: false,
});
this.setMessage({
type: 'warning',
content: (err as Error).message,
});
}
throw err;
}
},
resetUpdateData() {
return features.runningTree.resetUpdateData(this.state.oakFullpath);
},
async setAction(action, path) {
const fullpath = path
? `${this.state.oakFullpath}.${path}`
: this.state.oakFullpath;
return features.runningTree.setAction(fullpath, action);
},
async setUpdateData(attr, value) {
if (this.state.oakExecuting) {
return;
}
return features.runningTree.setUpdateData(
this.state.oakFullpath,
attr,
value
);
},
};
}
export function makeComponentOnlyMethods<
ED extends EntityDict & BaseEntityDict,
T extends keyof ED,
Cxt extends Context<ED>,
AD extends Record<string, Aspect<ED, Cxt>>,
FD extends Record<string, Feature<ED, Cxt, AD & CommonAspectDict<ED, Cxt>>>,
FormedData extends WechatMiniprogram.Component.DataOption,
Proj extends ED[T]['Selection']['data'],
IsList extends boolean,
TData extends WechatMiniprogram.Component.DataOption = {},
TProperty extends WechatMiniprogram.Component.PropertyOption = {},
TMethod extends WechatMiniprogram.Component.MethodOption = {}
>(
formData: OakPageOption<
ED,
T,
Cxt,
AD,
FD,
Proj,
FormedData,
IsList,
TData,
TProperty,
TMethod
>['formData'],
entity: T | undefined,
actions: ED[T]['Action'][] | undefined,
): OakComponentOnlyMethods &
ComponentThisType<ED, T, FormedData, IsList, TData, TProperty, TMethod> {
return {
onPropsChanged(params) {
const path2 = params.hasOwnProperty('path')
? params.path!
: this.props.oakPath;
const parent2 = params.hasOwnProperty('parent')
? params.parent!
: this.props.oakParent;
const oakFullpath2 = `${parent2 || ''}${
parent2 && path2 ? '.' : ''
}${path2 || ''}`;
if (oakFullpath2) {
if (oakFullpath2 !== this.state.oakFullpath) {
this.setState({
oakFullpath: oakFullpath2,
oakEntity: entity as string,
});
typeof formData === 'function' && this.reRender();
}
}
},
registerReRender() {
const { oakPath, oakParent } = this.props;
if (oakParent || oakPath) {
const oakFullpath = `${oakParent || ''}${
oakParent && oakPath ? '.' : ''
}${oakPath || ''}`;
this.setState(
{
oakFullpath,
oakEntity: entity as any,
},
() => {
typeof formData === 'function' &&
this.reRender.call(this);
}
);
} else {
typeof formData === 'function' && this.reRender.call(this);
}
},
setOakActions() {
const { oakActions } = this.props;
this.setState({
newOakActions:
oakActions && JSON.parse(oakActions).length > 0
? JSON.parse(oakActions)
: actions || [],
});
},
};
}
export function makeListComponentMethods<
ED extends EntityDict & BaseEntityDict,
T extends keyof ED,
Cxt extends Context<ED>,
AD extends Record<string, Aspect<ED, Cxt>>,
FD extends Record<string, Feature<ED, Cxt, AD & CommonAspectDict<ED, Cxt>>>,
FormedData extends WechatMiniprogram.Component.DataOption,
IsList extends boolean,
TData extends WechatMiniprogram.Component.DataOption = {},
TProperty extends WechatMiniprogram.Component.PropertyOption = {},
TMethod extends WechatMiniprogram.Component.MethodOption = {}
>(
features: BasicFeatures<ED, Cxt, AD & CommonAspectDict<ED, Cxt>> & FD
): OakListComponentMethods<ED, T> &
ComponentThisType<ED, T, FormedData, IsList, TData, TProperty, TMethod> {
return {
async pushNode(path, options) {
const path2 = path
? `${this.state.oakFullpath}.${path}`
: this.state.oakFullpath;
await features.runningTree.pushNode(path2, options || {});
},
async removeNode(parent, path) {
const path2 = parent
? `${this.state.oakFullpath}.${parent}`
: this.state.oakFullpath;
await features.runningTree.removeNode(path2, path);
},
async getFilters() {
if (this.state.oakFullpath) {
const namedFilters = features.runningTree.getNamedFilters(
this.state.oakFullpath
);
const filters = await Promise.all(
namedFilters.map(({ filter }) => {
if (typeof filter === 'function') {
return filter();
}
return filter;
})
);
return filters;
}
},
async getFilterByName(name) {
if (this.state.oakFullpath) {
const filter = features.runningTree.getNamedFilterByName(
this.state.oakFullpath,
name
);
if (filter?.filter) {
if (typeof filter.filter === 'function') {
return filter.filter();
}
return filter.filter;
}
}
},
async addNamedFilter(namedFilter, refresh = false) {
await features.runningTree.addNamedFilter(
this.state.oakFullpath,
namedFilter,
refresh
);
},
async removeNamedFilter(namedFilter, refresh = false) {
await features.runningTree.removeNamedFilter(
this.state.oakFullpath,
namedFilter,
refresh
);
},
async removeNamedFilterByName(name, refresh = false) {
await features.runningTree.removeNamedFilterByName(
this.state.oakFullpath,
name,
refresh
);
},
async setNamedSorters(namedSorters) {
await features.runningTree.setNamedSorters(
this.state.oakFullpath,
namedSorters
);
},
async getSorters() {
if (this.state.oakFullpath) {
const namedSorters = features.runningTree.getNamedSorters(
this.state.oakFullpath
);
const sorters = (
await Promise.all(
namedSorters.map(({ sorter }) => {
if (typeof sorter === 'function') {
return sorter();
}
return sorter;
})
)
).filter((ele) => !!ele) as DeduceSorterItem<ED[T]['Schema']>[];
return sorters;
}
},
async getSorterByName(name) {
if (this.state.oakFullpath) {
const sorter = features.runningTree.getNamedSorterByName(
this.state.oakFullpath,
name
);
if (sorter?.sorter) {
if (typeof sorter.sorter === 'function') {
return sorter.sorter();
}
return sorter.sorter;
}
}
},
async addNamedSorter(namedSorter, refresh = false) {
await features.runningTree.addNamedSorter(
this.state.oakFullpath,
namedSorter,
refresh
);
},
async removeNamedSorter(namedSorter, refresh = false) {
await features.runningTree.removeNamedSorter(
this.state.oakFullpath,
namedSorter,
refresh
);
},
async removeNamedSorterByName(name, refresh = false) {
await features.runningTree.removeNamedSorterByName(
this.state.oakFullpath,
name,
refresh
);
},
async setFilters(filters) {
await features.runningTree.setNamedFilters(
this.state.oakFullpath,
filters
);
},
getPagination() {
if (this.state.oakFullpath) {
return features.runningTree.getPagination(this.state.oakFullpath);
}
},
async setPageSize(pageSize: number, refresh = true) {
features.runningTree.setPageSize(
this.state.oakFullpath,
pageSize,
);
if (refresh) {
this.refresh();
}
},
async setCurrentPage(currentPage: number) {
assert(currentPage !== 0);
if (this.state.oakEntity && this.state.oakFullpath) {
this.setState({
oakLoading: true,
});
try {
await features.runningTree.setCurrentPage(
this.state.oakFullpath,
currentPage
);
this.setState({
oakLoading: false,
});
} catch (err) {
this.setState({
oakLoading: false,
});
this.setMessage({
type: 'error',
content: (err as Error).message,
});
}
}
},
};
}
export function makePageMethods<
ED extends EntityDict & BaseEntityDict,
T extends keyof ED,
Cxt extends Context<ED>,
AD extends Record<string, Aspect<ED, Cxt>>,
FD extends Record<string, Feature<ED, Cxt, AD & CommonAspectDict<ED, Cxt>>>,
FormedData extends WechatMiniprogram.Component.DataOption,
Proj extends ED[T]['Selection']['data'],
IsList extends boolean,
TData extends WechatMiniprogram.Component.DataOption = {},
TProperty extends WechatMiniprogram.Component.PropertyOption = {},
TMethod extends WechatMiniprogram.Component.MethodOption = {}
>(
features: BasicFeatures<ED, Cxt, AD & CommonAspectDict<ED, Cxt>> & FD,
options: OakPageOption<
ED,
T,
Cxt,
AD,
FD,
Proj,
FormedData,
IsList,
TData,
TProperty,
TMethod
>
): OakPageMethods &
ComponentThisType<ED, T, FormedData, IsList, TData, TProperty, TMethod> {
return {
async refresh() {
if (this.state.oakEntity && this.state.oakFullpath) {
this.setState({
oakLoading: true,
});
try {
await features.runningTree.refresh(this.state.oakFullpath);
this.setState({
oakLoading: false,
});
// this.setMessage({
// type: 'success',
// content: '访问成功',
// })
} catch (err) {
this.setMessage({
type: 'error',
content: (err as Error).message,
});
}
}
},
async onPullDownRefresh() {
await this.refresh();
},
async loadMore() {
if (
this.state.oakEntity &&
this.state.oakFullpath &&
options.isList
) {
this.setState({
oakMoreLoading: true,
});
try {
await features.runningTree.loadMore(this.state.oakFullpath);
this.setState({
oakMoreLoading: false,
});
} catch (err) {
this.setState({
oakMoreLoading: false,
});
this.setMessage({
type: 'error',
content: (err as Error).message,
});
}
}
},
async onReachBottom() {
await this.loadMore();
},
async onLoad(pageOption) {
return new Promise(async (resolve, reject) => {
try {
const {
oakId,
oakEntity,
oakPath,
oakProjection,
oakParent,
oakSorters,
oakFilters,
oakIsPicker,
oakFrom,
oakActions,
...props
} = this.props;
if (oakEntity || options.entity) {
assert(!(options.isList && oakId));
const filters: NamedFilterItem<ED, T>[] = [];
if (oakFilters?.length > 0) {
// 这里在跳页面的时候用this.navigate应该可以限制传过来的filter的格式
const oakFilters2 = JSON.parse(oakFilters);
filters.push(...oakFilters2);
} else if (options.filters) {
for (const ele of options.filters) {
const { filter, '#name': name } = ele;
filters.push({
filter:
typeof filter === 'function'
? () =>
filter({
features,
props: this.props,
onLoadOptions: pageOption,
})
: filter,
['#name']: name,
});
}
}
let proj = oakProjection && JSON.parse(oakProjection);
if (!proj && options.projection) {
const { projection } = options;
proj =
typeof projection === 'function'
? () =>
projection({
features,
props: this.props,
onLoadOptions: pageOption,
})
: projection;
}
let sorters: NamedSorterItem<ED, T>[] = [];
if (oakSorters?.length > 0) {
// 这里在跳页面的时候用this.navigate应该可以限制传过来的sorter的格式
const oakSorters2 = JSON.parse(oakSorters);
sorters.push(...oakSorters2);
} else if (options.sorters) {
for (const ele of options.sorters) {
const { sorter, '#name': name } = ele;
sorters.push({
sorter:
typeof sorter === 'function'
? () =>
sorter({
features,
props: this.props,
onLoadOptions: pageOption,
})
: sorter,
['#name']: name,
});
}
}
const oakPath2 = oakPath || options.path;
assert(
oakPath2,
'没有正确的path信息请检查是否配置正确'
);
const path2 = oakParent
? `${oakParent}:${oakPath2}`
: oakPath2;
const node = await features.runningTree.createNode({
path: path2,
entity: (oakEntity || options.entity) as T,
isList: options.isList,
isPicker: oakIsPicker,
projection: proj,
pagination: options.pagination,
filters,
sorters,
id: oakId,
});
await this.setState(
{
oakEntity: node.getEntity(),
oakFullpath: path2,
oakFrom,
},
async () => {
this.setOakActions();
this.refresh();
options.methods?.onLoad &&
(await options.methods.onLoad.call(
this,
pageOption
));
resolve();
}
);
} else {
options.methods?.onLoad &&
(await options.methods.onLoad.call(
this,
pageOption
));
resolve();
}
} catch (e) {
reject(e);
}
});
},
};
}

View File

@ -121,7 +121,7 @@ export async function onPathSet<
oakFullpath: oakPath2,
oakIsReady: true,
});
await this.refresh();
// await this.refresh();
}
export async function reRender<
@ -285,7 +285,7 @@ export function callPicker<
assert(typeof relation === 'string');
subEntity = relation;
}
let url = `/pickers/${subEntity}?oakIsPicker=true&oakParentEntity=${this.state.oakEntity}&oakParent=${this.state.oakFullpath}&oakPath=${attr}`;
let url = `/pickers/${subEntity}?oakIsPicker=true&oakParentEntity=${this.state.oakEntity as string}&oakParent=${this.state.oakFullpath}&oakPath=${attr}`;
for (const k in params) {
url += `&${k}=${JSON.stringify(params[k])}`;
}

View File

@ -12,7 +12,7 @@ import {
OakComponentOption,
OakPageMethods,
OakPageOption,
} from './types/Page';
} from './types/Page2';
import {
ComponentThisType,
makeHiddenComponentMethods,
@ -20,7 +20,7 @@ import {
makeComponentOnlyMethods,
makeCommonComponentMethods as makeCommon,
makePageMethods as makePage,
} from './page.common';
} from './page.common2';
import {
getI18nInstanceWechatMp,
CURRENT_LOCALE_KEY,

View File

@ -1,678 +0,0 @@
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, Context, EntityDict } from 'oak-domain/lib/types';
import { EntityDict as BaseEntityDict } from 'oak-domain/lib/base-app-domain';
import { BasicFeatures } from './features';
import { ExceptionHandler } from './types/ExceptionRoute';
import { Feature } from './types/Feature';
import {
MiniprogramStyleMethods,
OakCommonComponentMethods,
OakComponentData,
OakComponentOption,
OakPageData,
OakPageMethods,
OakPageOption,
OakPageProperties,
} from './types/Page';
import {
ComponentThisType,
makeHiddenComponentMethods,
makeListComponentMethods,
makeComponentOnlyMethods,
makeCommonComponentMethods as makeCommon,
makePageMethods as makePage,
ComponentData,
ComponentProps,
} from './page.common';
function makeCommonComponentMethods<
ED extends EntityDict & BaseEntityDict,
T extends keyof ED,
Cxt extends Context<ED>,
AD extends Record<string, Aspect<ED, Cxt>>,
FD extends Record<string, Feature<ED, Cxt, AD & CommonAspectDict<ED, Cxt>>>,
FormedData extends WechatMiniprogram.Component.DataOption,
Proj extends ED[T]['Selection']['data'],
IsList extends boolean,
TData extends WechatMiniprogram.Component.DataOption = {},
TProperty extends WechatMiniprogram.Component.PropertyOption = {},
TMethod extends WechatMiniprogram.Component.MethodOption = {}
>(
features: BasicFeatures<ED, Cxt, AD & CommonAspectDict<ED, Cxt>> & FD,
exceptionRouterDict: Record<string, ExceptionHandler>,
formData: OakPageOption<
ED,
T,
Cxt,
AD,
FD,
Proj,
FormedData,
IsList,
TData,
TProperty,
TMethod
>['formData']
): OakCommonComponentMethods<ED, T> &
ComponentThisType<ED, T, FormedData, IsList, TData, TProperty, TMethod> {
return {
t(key: string, params?: object) {
// common: {
// GREETING: 'Hello {{name}}, nice to see you.',
// },
// t('common:GREETING', {name: "John Doe" })
return this.props.t(key, params);
},
resolveInput(input: React.BaseSyntheticEvent, keys) {
const { currentTarget, target } = input;
const { value } = Object.assign({}, currentTarget, target);
const { dataset } = currentTarget;
const result = {
dataset,
value,
};
if (keys) {
keys.forEach((k) =>
Object.assign(result, {
[k]: target[k],
})
);
}
return result;
},
navigateBack(option) {
const { delta } = option || {};
return new Promise((resolve, reject) => {
try {
this.props.navigate(delta || -1);
resolve(undefined);
} catch (err) {
reject(err);
}
});
},
navigateTo(options, state, disableNamespace) {
const { url, events, fail, complete, success, ...rest } = options;
let url2 = url.includes('?')
? url.concat(
this.state.oakFullpath
? `&oakFrom=${this.state.oakFullpath}`
: ''
)
: url.concat(
this.state.oakFullpath ? `?oakFrom=${this.state.oakFullpath}` : ''
);
for (const param in rest) {
const param2 = param as unknown as keyof typeof rest;
if (rest[param2] !== undefined) {
url2 += `${url2.includes('?') ? '&' : '?'}${param}=${
typeof rest[param2] === 'string'
? rest[param2]
: JSON.stringify(rest[param2])
}`;
}
}
// 路由传入namespace
if (!disableNamespace && this.props.namespace) {
url2 =
(this.props.namespace.startsWith('/') ? '' : '/') +
(this.props.namespace === '/' ? '' : this.props.namespace) +
(url2.startsWith('/') ? '' : '/') +
url2;
}
return this.props.navigate(url2, { replace: false, state });
},
redirectTo(options, state, disableNamespace) {
const { url, events, fail, complete, success, ...rest } = options;
let url2 = url.includes('?')
? url.concat(
this.state.oakFullpath
? `&oakFrom=${this.state.oakFullpath}`
: ''
)
: url.concat(
this.state.oakFullpath
? `?oakFrom=${this.state.oakFullpath}`
: ''
);
for (const param in rest) {
const param2 = param as unknown as keyof typeof rest;
if (rest[param2] !== undefined) {
url2 += `${url2.includes('?') ? '&' : '?'}${param}=${
typeof rest[param2] === 'string'
? rest[param2]
: JSON.stringify(rest[param2])
}`;
}
}
// 路由传入namespace
if (!disableNamespace && this.props.namespace) {
url2 =
(this.props.namespace.startsWith('/') ? '' : '/') +
(this.props.namespace === '/' ? '' : this.props.namespace) +
(url2.startsWith('/') ? '' : '/') +
url2;
}
return this.props.navigate(url2, { replace: true, state });
},
...makeCommon(features, exceptionRouterDict, formData),
};
}
function makePageMethods<
ED extends EntityDict & BaseEntityDict,
T extends keyof ED,
Cxt extends Context<ED>,
AD extends Record<string, Aspect<ED, Cxt>>,
FD extends Record<string, Feature<ED, Cxt, AD & CommonAspectDict<ED, Cxt>>>,
FormedData extends WechatMiniprogram.Component.DataOption,
Proj extends ED[T]['Selection']['data'],
IsList extends boolean,
TData extends WechatMiniprogram.Component.DataOption = {},
TProperty extends WechatMiniprogram.Component.PropertyOption = {},
TMethod extends WechatMiniprogram.Component.MethodOption = {}
>(
features: BasicFeatures<ED, Cxt, AD & CommonAspectDict<ED, Cxt>> & FD,
options: OakPageOption<
ED,
T,
Cxt,
AD,
FD,
Proj,
FormedData,
IsList,
TData,
TProperty,
TMethod
>
): OakPageMethods &
ComponentThisType<ED, T, FormedData, IsList, TData, TProperty, TMethod> {
const { onPullDownRefresh, ...rest } = makePage(features, options);
return {
async onPullDownRefresh() {
await onPullDownRefresh.call(this);
},
...rest,
};
}
function translateObservers(
observers?: Record<string, (...args: any[]) => any>
): { fn: React.Component['componentDidUpdate'] } & ThisType<React.Component> {
return {
fn(prevProps, prevState) {
const { state, props } = this;
for (const obs in observers) {
const keys = obs.split(',').map((ele) => ele.trim());
let changed = false;
for (const k of keys) {
if (k.includes('*')) {
throw new Error('web模式下带*的observer通配符暂不支持');
}
if (
get(props, k) !== get(prevProps, k) ||
get(state, k) !== get(prevState, k)
) {
changed = true;
break;
}
}
const args = [];
if (changed) {
for (const k of keys) {
args.push(
get(props, k) === undefined
? get(state, k)
: get(props, k)
);
}
observers[obs].apply(this, args);
}
}
},
};
}
function makeMiniprogramCompatibleFunctions(): MiniprogramStyleMethods &
ThisType<React.Component> {
return {
triggerEvent(name, detail, option) {
throw new Error('method not implemented yet');
},
animate(selector, frames, duration, timeline) {
throw new Error('method not implemented yet');
},
clearAnimation(selector, option, callback) {
throw new Error('method not implemented yet');
},
};
}
const DEFAULT_REACH_BOTTOM_DISTANCE = 50;
export function createPage<
ED extends EntityDict & BaseEntityDict,
T extends keyof ED,
Cxt extends Context<ED>,
AD extends Record<string, Aspect<ED, Cxt>>,
FD extends Record<string, Feature<ED, Cxt, AD & CommonAspectDict<ED, Cxt>>>,
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: OakPageOption<
ED,
T,
Cxt,
AD,
FD,
Proj,
FormedData,
IsList,
TData,
TProperty,
TMethod
>,
features: BasicFeatures<ED, Cxt, AD & CommonAspectDict<ED, Cxt>> & FD,
exceptionRouterDict: Record<string, ExceptionHandler>
) {
const { formData, isList, render, actions, entity } =
options as OakPageOption<
ED,
T,
Cxt,
AD,
FD,
Proj,
FormedData,
IsList,
TData,
TProperty,
TMethod
> & {
render: () => React.ReactNode &
ComponentThisType<
ED,
T,
FormedData,
IsList,
TData,
TProperty,
TMethod
>;
};
const hiddenMethods = makeHiddenComponentMethods();
const commonMethods = makeCommonComponentMethods(
features,
exceptionRouterDict,
formData
);
const listMethods = makeListComponentMethods(features);
const onlyMethods = makeComponentOnlyMethods(formData, entity, actions);
const { onLoad, onPullDownRefresh, onReachBottom, ...restPageMethods } =
makePageMethods(features, options);
const { methods, lifetimes, pageLifetimes, data, observers } = options;
const { fn } = translateObservers(observers);
class OakPageWrapper extends React.PureComponent<
ComponentProps<TProperty>,
ComponentData<ED, T, FormedData, TData>
> {
constructor(props: any) {
super(props);
this.state = (data || {}) as any;
for (const m in commonMethods) {
Object.assign(this, {
[m]: commonMethods[m as keyof typeof commonMethods]!.bind(
this
),
});
}
for (const m in listMethods) {
Object.assign(this, {
[m]: listMethods[m as keyof typeof listMethods]!.bind(this),
});
}
for (const m in hiddenMethods) {
Object.assign(this, {
[m]: hiddenMethods[m as keyof typeof hiddenMethods]!.bind(
this
),
});
}
for (const m in onlyMethods) {
Object.assign(this, {
[m]: onlyMethods[m as keyof typeof onlyMethods]!.bind(this),
});
}
for (const m in restPageMethods) {
Object.assign(this, {
[m]: restPageMethods[
m as keyof typeof restPageMethods
]!.bind(this),
});
}
if (methods) {
const { onPullDownRefresh, onReachBottom, ...restMethods } =
methods;
for (const m in restMethods) {
Object.assign(this, {
[m]: restMethods[m as keyof typeof restMethods]!.bind(
this
),
});
}
}
lifetimes?.created && lifetimes.created.call(this);
}
features = features;
isReachBottom = false;
componentDidUpdate = fn;
scrollEvent = () => {
this.checkReachBottom();
};
registerPageScroll() {
const { useBodyScroll = false } = this.props;
if (useBodyScroll) {
window.addEventListener('scroll', this.scrollEvent);
}
else {
(this as any).lv && (this as any).lv.addEventListener('scroll', this.scrollEvent);
}
}
unregisterPageScroll() {
const { useBodyScroll = false } = this.props;
if (useBodyScroll) {
window.removeEventListener('scroll', this.scrollEvent);
}
else {
(this as any).lv && (this as any).lv.removeEventListener('scroll', this.scrollEvent);
}
}
checkReachBottom() {
const isCurrentReachBottom =
document.body.scrollHeight -
(window.innerHeight + window.scrollY) <=
DEFAULT_REACH_BOTTOM_DISTANCE;
if (!this.isReachBottom && isCurrentReachBottom) {
this.isReachBottom = true;
// 执行触底事件
if (methods?.onReachBottom) {
methods.onReachBottom.call(this);
return;
}
if (this.props.width === 'xs') {
onReachBottom.call(this);
}
return;
}
this.isReachBottom = isCurrentReachBottom;
}
async componentDidMount() {
this.registerPageScroll();
await onLoad.call(this, this.props);
typeof formData === 'function' && hiddenMethods.subscribe.call(this);
typeof formData === 'function' && commonMethods.reRender.call(this);
methods?.onReady && methods.onReady.call(this);
lifetimes?.attached && lifetimes.attached.call(this);
lifetimes?.ready && lifetimes.ready.call(this);
pageLifetimes?.show && pageLifetimes.show.call(this);
}
async componentWillUnmount() {
this.unregisterPageScroll();
this.state.oakFullpath && features.runningTree.destroyNode(this.state.oakFullpath);
typeof formData === 'function' && hiddenMethods.unsubscribe.call(this);
methods?.onUnload && methods.onUnload.call(this);
lifetimes?.detached && lifetimes.detached.call(this);
}
render(): React.ReactNode {
const Render = render.call(this);
const { oakLoading } = this.state;
const { enablePullDownRefresh, useBodyScroll = false } = this.props;
if (enablePullDownRefresh && this.props.width === 'xs') {
const child = React.cloneElement(
<PullToRefresh
onRefresh={() => {
if (methods?.onPullDownRefresh) {
methods.onPullDownRefresh.call(this);
} else {
onPullDownRefresh.call(this);
}
}}
refreshing={oakLoading}
distanceToRefresh={DEFAULT_REACH_BOTTOM_DISTANCE}
indicator={{
activate: commonMethods.t.call(
this,
'common:ptrActivate'
),
deactivate: commonMethods.t.call(
this,
'common:ptrDeactivate'
),
release: commonMethods.t.call(
this,
'common:ptrRelease'
),
finish: commonMethods.t.call(
this,
'common:ptrFinish'
),
}}
/>,
{
getScrollContainer: () => useBodyScroll ? document.body : (this as any).lv,
},
Render
);
return useBodyScroll ? (
child
) : (
<div
ref={(el) => ((this as any).lv = el)}
style={{ height: '100%', overflow: 'auto' }}
>
{child}
</div>
);
}
return Render;
}
}
// 可能有问题by Xc
Object.assign(OakPageWrapper, makeMiniprogramCompatibleFunctions());
return withRouter(OakPageWrapper, false, options.path);
}
export function createComponent<
ED extends EntityDict & BaseEntityDict,
T extends keyof ED,
Cxt extends Context<ED>,
AD extends Record<string, Aspect<ED, Cxt>>,
FD extends Record<string, Feature<ED, Cxt, AD & CommonAspectDict<ED, Cxt>>>,
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,
FormedData,
IsList,
TData,
TProperty,
TMethod
>,
features: BasicFeatures<ED, Cxt, AD & CommonAspectDict<ED, Cxt>> & FD,
exceptionRouterDict: Record<string, ExceptionHandler>,
) {
const {
formData,
isList,
entity,
methods,
lifetimes,
pageLifetimes,
data,
properties,
observers,
actions,
render,
} = options as OakComponentOption<
ED,
T,
Cxt,
AD,
FD,
FormedData,
IsList,
TData,
TProperty,
TMethod
> & {
render: () => React.ReactNode &
ComponentThisType<
ED,
T,
FormedData,
IsList,
TData,
TProperty,
TMethod
>;
};
const hiddenMethods = makeHiddenComponentMethods();
const commonMethods = makeCommonComponentMethods(
features,
exceptionRouterDict,
formData
);
const listMethods = makeListComponentMethods(features);
const onlyMethods = makeComponentOnlyMethods(formData, entity, actions);
const { fn } = translateObservers(observers);
class OakComponentWrapper extends React.PureComponent<
ComponentProps<TProperty>,
OakComponentData<ED, T>
> {
constructor(props: any) {
super(props);
this.state = (data || {}) as any;
for (const m in commonMethods) {
Object.assign(this, {
[m]: commonMethods[m as keyof typeof commonMethods]!.bind(
this
),
});
}
for (const m in listMethods) {
Object.assign(this, {
[m]: listMethods[m as keyof typeof listMethods]!.bind(this),
});
}
for (const m in hiddenMethods) {
Object.assign(this, {
[m]: hiddenMethods[m as keyof typeof hiddenMethods]!.bind(this),
});
}
for (const m in onlyMethods) {
Object.assign(this, {
[m]: onlyMethods[m as keyof typeof onlyMethods]!.bind(this),
});
}
if (methods) {
for (const m in methods) {
Object.assign(this, {
[m]: methods[m as keyof typeof methods]!.bind(this),
});
}
}
lifetimes?.created && lifetimes.created.call(this);
}
features = features;
isReachBottom = false;
async componentDidMount() {
typeof formData === 'function' && hiddenMethods.subscribe.call(this);
(this as any).setOakActions();
(this as any).registerReRender();
lifetimes?.attached && lifetimes.attached.call(this);
lifetimes?.ready && lifetimes.ready.call(this);
pageLifetimes?.show && pageLifetimes.show.call(this);
}
async componentWillUnmount() {
typeof formData === 'function' && hiddenMethods.unsubscribe.call(this);
lifetimes?.detached && lifetimes.detached.call(this);
}
componentDidUpdate(
prevProps: Readonly<ComponentProps<TProperty>>,
prevState: Readonly<OakComponentData<ED, T>>
) {
if (
this.props.oakPath &&
prevProps.oakPath !== this.props.oakPath
) {
(this as any).onPropsChanged({
path: this.props.oakPath,
});
}
if (
this.props.oakParent &&
prevProps.oakParent !== this.props.oakParent
) {
(this as any).onPropsChanged({
parent: this.props.oakParent,
});
}
fn?.call(this, prevProps, prevState);
}
render(): React.ReactNode {
const Render = render.call(this);
return Render;
}
triggerEvent<DetailType = any>(
name: string,
detail?: DetailType,
options?: WechatMiniprogram.Component.TriggerEventOption
) {
// 需要兼容
}
}
// 可能有问题by Xc
Object.assign(OakComponentWrapper, makeMiniprogramCompatibleFunctions());
return withRouter(OakComponentWrapper, true);
}

View File

@ -10,14 +10,9 @@ import { BasicFeatures } from './features';
import { ExceptionHandler } from './types/ExceptionRoute';
import { NamedFilterItem, NamedSorterItem } from './types/NamedCondition';
import { Feature } from './types/Feature';
import { CreateNodeOptions } from './features/runningTree';
import {
ComponentData,
ComponentFullThisType,
ComponentProps,
MiniprogramStyleMethods,
OakCommonComponentMethods,
OakComponentData,
OakComponentOption,
OakNavigateToParameters,
} from './types/Page2';

View File

@ -37,6 +37,9 @@ export function subscribe(callback: () => any) {
const method = descriptor.value!;
descriptor.value = async function (...params: any[]) {
mActionStackDepth++;
if (mActionStackDepth > 20) {
console.error(`action[${method.name}]调用的层级超过了20请检查是否存在无限递归`);
}
let result;
try {
result = await method.apply(this, params);

View File

@ -289,10 +289,7 @@ export type OakCommonComponentMethods<
export type OakListComponentMethods<ED extends EntityDict & BaseEntityDict, T extends keyof ED> = {
pushNode: (
path?: string,
options?: Pick<
CreateNodeOptions<ED, keyof ED>,
'updateData' | 'beforeExecute' | 'afterExecute'
>
options?: CreateNodeOptions<ED, keyof ED>
) => Promise<void>;
removeNode: (parent: string, path: string) => Promise<void>;
setFilters: (filters: NamedFilterItem<ED, T>[]) => Promise<void>;

View File

@ -72,7 +72,6 @@
],
"include": [
"src/**/*.ts",
"src/page.web.tsx",
],
"exclude": [
"node_modules",