merged
This commit is contained in:
commit
6aa4189cfc
|
|
@ -16,6 +16,7 @@ declare abstract class Node<ED extends EntityDict, T extends keyof ED, Cxt exten
|
|||
private beforeExecute?;
|
||||
private afterExecute?;
|
||||
abstract onCachSync(opRecords: OpRecord<ED>[]): Promise<void>;
|
||||
abstract refreshValue(): void;
|
||||
constructor(entity: T, schema: StorageSchema<ED>, cache: Cache<ED, Cxt, AD>, projection: ED[T]['Selection']['data'] | (() => Promise<ED[T]['Selection']['data']>), parent?: Node<ED, keyof ED, Cxt, AD>, action?: ED[T]['Action'], updateData?: DeduceUpdateOperation<ED[T]['OpSchema']>['data']);
|
||||
getEntity(): T;
|
||||
setUpdateData(attr: string, value: any): void;
|
||||
|
|
@ -43,6 +44,7 @@ declare class ListNode<ED extends EntityDict, T extends keyof ED, Cxt extends Co
|
|||
private pagination;
|
||||
private projectionShape;
|
||||
onCachSync(records: OpRecord<ED>[]): 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);
|
||||
getChild(path: string): SingleNode<ED, T, Cxt, AD>;
|
||||
getChildren(): SingleNode<ED, T, Cxt, AD>[];
|
||||
|
|
@ -61,7 +63,7 @@ declare class ListNode<ED extends EntityDict, T extends keyof ED, Cxt extends Co
|
|||
addNamedSorter(sorter: NamedSorterItem<ED, T>): void;
|
||||
removeNamedSorter(sorter: NamedSorterItem<ED, T>): void;
|
||||
removeNamedSorterByName(name: string): void;
|
||||
getValue(): SelectRowShape<ED[T]['Schema'], ED[T]['Selection']['data']>[];
|
||||
getFreshValue(): SelectRowShape<ED[T]['Schema'], ED[T]['Selection']['data']>[];
|
||||
getAction(): "update" | ED[T]["Action"];
|
||||
composeOperation(action?: string, realId?: boolean): Promise<DeduceOperation<ED[T]['Schema']> | DeduceOperation<ED[T]['Schema']>[] | undefined>;
|
||||
refresh(scene: string): Promise<void>;
|
||||
|
|
@ -72,6 +74,7 @@ declare class ListNode<ED extends EntityDict, T extends keyof ED, Cxt extends Co
|
|||
declare class SingleNode<ED extends EntityDict, T extends keyof ED, Cxt extends Context<ED>, AD extends Record<string, Aspect<ED, Cxt>>> extends Node<ED, T, Cxt, AD> {
|
||||
private id?;
|
||||
private value?;
|
||||
private freshValue?;
|
||||
private children;
|
||||
onCachSync(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']);
|
||||
|
|
@ -80,13 +83,14 @@ declare class SingleNode<ED extends EntityDict, T extends keyof ED, Cxt extends
|
|||
[K: string]: SingleNode<ED, keyof ED, Cxt, AD> | ListNode<ED, keyof ED, Cxt, AD>;
|
||||
};
|
||||
removeChild(path: string): void;
|
||||
refreshValue(): void;
|
||||
setValue(value: SelectRowShape<ED[T]['OpSchema'], ED[T]['Selection']['data']>): void;
|
||||
updateValue(value: SelectRowShape<ED[T]['Schema'], ED[T]['Selection']['data']>): void;
|
||||
getValue(): SelectRowShape<ED[T]['Schema'], ED[T]['Selection']['data']>;
|
||||
getFreshValue(): SelectRowShape<ED[T]['Schema'], ED[T]['Selection']['data']>;
|
||||
getAction(): "create" | "update" | ED[T]["Action"];
|
||||
composeOperation(action2?: string, realId?: boolean): Promise<import("oak-domain/lib/types").DeduceCreateMultipleOperation<ED[T]["Schema"]> | DeduceUpdateOperation<ED[T]["Schema"]> | undefined>;
|
||||
refresh(scene: string): Promise<void>;
|
||||
resetUpdateData(): void;
|
||||
setForeignKey(attr: string, id: string): Promise<void>;
|
||||
}
|
||||
export declare type CreateNodeOptions<ED extends EntityDict, T extends keyof ED> = {
|
||||
path: string;
|
||||
|
|
@ -115,12 +119,12 @@ export declare class RunningTree<ED extends EntityDict, Cxt extends Context<ED>,
|
|||
destroyNode(path: string): void;
|
||||
setStorageSchema(schema: StorageSchema<ED>): void;
|
||||
private applyOperation;
|
||||
getValue(path: string): Promise<(SelectRowShape<ED[keyof ED]["Schema"], ED[keyof ED]["Selection"]["data"]> | undefined)[]>;
|
||||
getFreshValue(path: string): 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(path: string, id: string): Promise<void>;
|
||||
setForeignKey(parent: string, attr: string, id: string): Promise<void>;
|
||||
refresh(path: string): 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;
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ class Node {
|
|||
setUpdateData(attr, value) {
|
||||
(0, lodash_1.set)(this.updateData, attr, value);
|
||||
this.setDirty();
|
||||
this.refreshValue();
|
||||
}
|
||||
getUpdateData() {
|
||||
return this.updateData;
|
||||
|
|
@ -54,6 +55,7 @@ class Node {
|
|||
setMultiUpdateData(updateData) {
|
||||
(0, lodash_1.assign)(this.updateData, updateData);
|
||||
this.setDirty();
|
||||
this.refreshValue();
|
||||
}
|
||||
setDirty() {
|
||||
if (!this.dirty) {
|
||||
|
|
@ -66,6 +68,7 @@ class Node {
|
|||
setAction(action) {
|
||||
this.action = action;
|
||||
this.setDirty();
|
||||
this.refreshValue();
|
||||
}
|
||||
isDirty() {
|
||||
return this.dirty;
|
||||
|
|
@ -145,7 +148,7 @@ class ListNode extends Node {
|
|||
}
|
||||
}
|
||||
if (createdIds.length > 0 || removeIds) {
|
||||
const currentIds = this.children.map(ele => ele.getValue().id);
|
||||
const currentIds = this.children.map(ele => ele.getFreshValue().id);
|
||||
const filter = (0, filter_1.combineFilters)([{
|
||||
id: {
|
||||
$in: currentIds.concat(createdIds),
|
||||
|
|
@ -169,6 +172,8 @@ class ListNode extends Node {
|
|||
this.setValue(value);
|
||||
}
|
||||
}
|
||||
refreshValue() {
|
||||
}
|
||||
constructor(entity, schema, cache, projection, projectionShape, parent, action, updateData, filters, sorters, pagination) {
|
||||
super(entity, schema, cache, projection, parent, action, updateData);
|
||||
this.projectionShape = projectionShape;
|
||||
|
|
@ -181,7 +186,14 @@ class ListNode extends Node {
|
|||
getChild(path) {
|
||||
const idx = parseInt(path, 10);
|
||||
(0, assert_1.default)(typeof idx === 'number');
|
||||
return this.children[idx];
|
||||
if (idx < this.children.length) {
|
||||
return this.children[idx];
|
||||
}
|
||||
else {
|
||||
const idx2 = idx - this.children.length;
|
||||
// assert(idx2 < this.newBorn.length); // 在删除结点时可能还是会跑到
|
||||
return this.newBorn[idx2];
|
||||
}
|
||||
}
|
||||
getChildren() {
|
||||
return this.children;
|
||||
|
|
@ -200,15 +212,11 @@ class ListNode extends Node {
|
|||
this.children.splice(idx, 1);
|
||||
}
|
||||
setValue(value) {
|
||||
this.children = [];
|
||||
value.forEach((ele, idx) => {
|
||||
if (this.children[idx]) {
|
||||
this.children[idx].setValue(ele);
|
||||
}
|
||||
else {
|
||||
const node = new SingleNode(this.entity, this.schema, this.cache, this.projection, this.projectionShape, this);
|
||||
this.children[idx] = node;
|
||||
node.setValue(ele);
|
||||
}
|
||||
const node = new SingleNode(this.entity, this.schema, this.cache, this.projection, this.projectionShape, this);
|
||||
this.children[idx] = node;
|
||||
node.setValue(ele);
|
||||
});
|
||||
}
|
||||
getNamedFilters() {
|
||||
|
|
@ -279,9 +287,18 @@ class ListNode extends Node {
|
|||
this.sorters.splice(fIndex, 1);
|
||||
}
|
||||
}
|
||||
getValue() {
|
||||
const value = this.children.map(ele => ele.getValue());
|
||||
return value;
|
||||
getFreshValue() {
|
||||
const value = this.children.map(ele => ele.getFreshValue());
|
||||
if (this.isDirty()) {
|
||||
const action = this.action || 'update';
|
||||
if (action === 'remove') {
|
||||
return []; // 这个可能跑到吗?
|
||||
}
|
||||
return value.map(ele => (0, lodash_1.assign)({}, ele, this.updateData));
|
||||
}
|
||||
else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
getAction() {
|
||||
(0, assert_1.default)(this.dirty);
|
||||
|
|
@ -379,6 +396,7 @@ class ListNode extends Node {
|
|||
class SingleNode extends Node {
|
||||
id;
|
||||
value;
|
||||
freshValue;
|
||||
children;
|
||||
async onCachSync(records) {
|
||||
let needReGetValue = false;
|
||||
|
|
@ -439,7 +457,7 @@ class SingleNode extends Node {
|
|||
id: this.id,
|
||||
}
|
||||
}, 'onCacheSync');
|
||||
this.updateValue(value);
|
||||
this.setValue(value);
|
||||
}
|
||||
}
|
||||
constructor(entity, schema, cache, projection, projectionShape, parent, action, updateData) {
|
||||
|
|
@ -508,6 +526,20 @@ class SingleNode extends Node {
|
|||
removeChild(path) {
|
||||
(0, lodash_1.unset)(this.children, path);
|
||||
}
|
||||
refreshValue() {
|
||||
const action = this.action || (this.isDirty() ? 'update' : '');
|
||||
if (!action) {
|
||||
this.freshValue = this.value;
|
||||
}
|
||||
else {
|
||||
if (action === 'remove') {
|
||||
this.freshValue = undefined;
|
||||
}
|
||||
else {
|
||||
this.freshValue = (0, lodash_1.assign)({}, this.value, this.updateData);
|
||||
}
|
||||
}
|
||||
}
|
||||
setValue(value) {
|
||||
for (const attr in this.children) {
|
||||
const node = this.children[attr];
|
||||
|
|
@ -531,22 +563,16 @@ class SingleNode extends Node {
|
|||
}
|
||||
this.id = value.id;
|
||||
this.value = value;
|
||||
this.refreshValue();
|
||||
}
|
||||
updateValue(value) {
|
||||
if (!this.value) {
|
||||
this.value = {};
|
||||
}
|
||||
(0, lodash_1.assign)(this.value, value);
|
||||
// todo,可能的一对多和多对一的子结点上的处理
|
||||
}
|
||||
getValue() {
|
||||
const value = this.value ? (0, lodash_1.cloneDeep)(this.value) : {};
|
||||
getFreshValue() {
|
||||
const freshValue = this.freshValue ? (0, lodash_1.cloneDeep)(this.freshValue) : {};
|
||||
for (const k in this.children) {
|
||||
(0, lodash_1.assign)(value, {
|
||||
[k]: this.children[k].getValue(),
|
||||
(0, lodash_1.assign)(freshValue, {
|
||||
[k]: this.children[k].getFreshValue(),
|
||||
});
|
||||
}
|
||||
return value;
|
||||
return freshValue;
|
||||
}
|
||||
getAction() {
|
||||
return this.action || (this.id ? 'update' : 'create');
|
||||
|
|
@ -597,6 +623,35 @@ class SingleNode extends Node {
|
|||
for (const attr in this.children) {
|
||||
this.children[attr].resetUpdateData();
|
||||
}
|
||||
this.refreshValue();
|
||||
}
|
||||
async setForeignKey(attr, id) {
|
||||
const rel = this.judgeRelation(attr);
|
||||
let subEntity;
|
||||
if (rel === 2) {
|
||||
this.setMultiUpdateData({
|
||||
entity: attr,
|
||||
entityId: id,
|
||||
});
|
||||
subEntity = attr;
|
||||
}
|
||||
else {
|
||||
(0, assert_1.default)(typeof rel === 'string');
|
||||
this.setUpdateData(`${attr}Id`, id);
|
||||
subEntity = rel;
|
||||
}
|
||||
// 如果修改了外键且对应的外键上有子结点,在这里把子结点的value更新掉
|
||||
if (this.children[attr]) {
|
||||
const proj = typeof this.projection === 'function' ? await this.projection() : this.projection;
|
||||
const subProj = proj[attr];
|
||||
const [value] = await this.cache.get(subEntity, {
|
||||
data: subProj,
|
||||
filter: {
|
||||
id,
|
||||
},
|
||||
}, 'SingleNode:setForeignKey');
|
||||
this.children[attr].setValue(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
class RunningTree extends Feature_1.Feature {
|
||||
|
|
@ -810,14 +865,9 @@ class RunningTree extends Feature_1.Feature {
|
|||
}
|
||||
}
|
||||
}
|
||||
async getValue(path) {
|
||||
async getFreshValue(path) {
|
||||
const node = this.findNode(path);
|
||||
let value = node.getValue();
|
||||
if (node.isDirty()) {
|
||||
const operation = await node.composeOperation();
|
||||
const projection = await node.getProjection();
|
||||
value = (await this.applyOperation(node.getEntity(), (0, lodash_1.cloneDeep)(value), operation, projection, path));
|
||||
}
|
||||
let value = node.getFreshValue();
|
||||
return value instanceof Array ? value : [value];
|
||||
}
|
||||
isDirty(path) {
|
||||
|
|
@ -851,20 +901,10 @@ class RunningTree extends Feature_1.Feature {
|
|||
const node = this.findNode(path);
|
||||
node.setAction(action);
|
||||
}
|
||||
async setForeignKey(path, id) {
|
||||
throw new Error('method not implemented');
|
||||
const node = this.findNode(path);
|
||||
const parent = node.getParent();
|
||||
const attr = path.slice(path.lastIndexOf('.') + 1);
|
||||
const rel = (0, relation_1.judgeRelation)(this.schema, parent.getEntity(), attr);
|
||||
if (rel === 2) {
|
||||
parent.setUpdateData('entity', node.getEntity());
|
||||
parent.setUpdateData('entityId', id);
|
||||
}
|
||||
else {
|
||||
(0, assert_1.default)(typeof rel === 'string');
|
||||
parent.setUpdateData(`${attr}Id`, id);
|
||||
}
|
||||
async setForeignKey(parent, attr, id) {
|
||||
const parentNode = this.findNode(parent);
|
||||
(0, assert_1.default)(parentNode instanceof SingleNode);
|
||||
parentNode.setForeignKey(attr, id);
|
||||
}
|
||||
async refresh(path) {
|
||||
const node = this.findNode(path);
|
||||
|
|
@ -1017,7 +1057,7 @@ class RunningTree extends Feature_1.Feature {
|
|||
const parentNode = this.findNode(parent);
|
||||
const node = parentNode.getChild(path);
|
||||
(0, assert_1.default)(parentNode instanceof ListNode && node instanceof SingleNode); // 现在应该不可能remove一个list吧,未来对list的处理还要细化
|
||||
if (node.getValue().id) {
|
||||
if (node.getFreshValue().id) {
|
||||
// 如果有id,说明是删除数据
|
||||
await this.getAspectProxy().operate({
|
||||
entity: node.getEntity(),
|
||||
|
|
@ -1025,7 +1065,7 @@ class RunningTree extends Feature_1.Feature {
|
|||
action: 'remove',
|
||||
data: {},
|
||||
filter: {
|
||||
id: node.getValue().id,
|
||||
id: node.getFreshValue().id,
|
||||
},
|
||||
}
|
||||
}, parent);
|
||||
|
|
|
|||
|
|
@ -4,3 +4,4 @@ export * from './types/Feature';
|
|||
export * from './types/ExceptionRoute';
|
||||
export { BasicFeatures } from './features';
|
||||
export * from './features/cache';
|
||||
export * from './features/upload';
|
||||
|
|
|
|||
|
|
@ -1,7 +1,11 @@
|
|||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
|
|
@ -16,3 +20,4 @@ Object.defineProperty(exports, "InitializeWechatMp", { enumerable: true, get: fu
|
|||
__exportStar(require("./types/Feature"), exports);
|
||||
__exportStar(require("./types/ExceptionRoute"), exports);
|
||||
__exportStar(require("./features/cache"), exports);
|
||||
__exportStar(require("./features/upload"), exports);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,11 @@
|
|||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
||||
var desc = Object.getOwnPropertyDescriptor(m, k);
|
||||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
||||
desc = { enumerable: true, get: function() { return m[k]; } };
|
||||
}
|
||||
Object.defineProperty(o, k2, desc);
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ declare type OakComponentMethods<ED extends EntityDict, T extends keyof ED> = {
|
|||
subscribed?: () => void;
|
||||
subscribe: () => void;
|
||||
unsubscribe: () => void;
|
||||
reRender: (extra?: any) => Promise<void>;
|
||||
reRender: (extra?: Record<string, any>) => Promise<void>;
|
||||
pushNode: (path?: string, options?: Pick<CreateNodeOptions<ED, keyof ED>, 'updateData' | 'beforeExecute' | 'afterExecute'>) => void;
|
||||
removeNode: (parent: string, path: string) => void;
|
||||
setUpdateData: (attr: string, input: any) => void;
|
||||
|
|
|
|||
|
|
@ -49,9 +49,9 @@ function createPageOptions(options, doSubscribe, features, exceptionRouterDict)
|
|||
newOakActions: Array,
|
||||
},
|
||||
methods: {
|
||||
async reRender() {
|
||||
async reRender(extra) {
|
||||
if (this.data.oakFullpath) {
|
||||
const $rows = await features.runningTree.getValue(this.data.oakFullpath);
|
||||
const $rows = await features.runningTree.getFreshValue(this.data.oakFullpath);
|
||||
const data = await formData.call(this, $rows, features);
|
||||
for (const k in data) {
|
||||
if (data[k] === undefined) {
|
||||
|
|
@ -79,6 +79,9 @@ function createPageOptions(options, doSubscribe, features, exceptionRouterDict)
|
|||
oakLegalActions,
|
||||
});
|
||||
}
|
||||
if (extra) {
|
||||
(0, lodash_1.assign)(data, extra);
|
||||
}
|
||||
this.setData(data);
|
||||
}
|
||||
},
|
||||
|
|
@ -352,9 +355,9 @@ function createPageOptions(options, doSubscribe, features, exceptionRouterDict)
|
|||
};
|
||||
}));
|
||||
}
|
||||
const path2 = oakParent ? `${oakParent}:${oakPath || options.path}` : oakPath || options.path;
|
||||
const node = await features.runningTree.createNode({
|
||||
path: oakPath || options.path,
|
||||
parent: oakParent,
|
||||
path: path2,
|
||||
entity: (oakEntity || options.entity),
|
||||
isList,
|
||||
isPicker: oakIsPicker,
|
||||
|
|
@ -364,10 +367,10 @@ function createPageOptions(options, doSubscribe, features, exceptionRouterDict)
|
|||
sorters,
|
||||
id: oakId,
|
||||
});
|
||||
const oakFullpath = oakParent ? `${oakParent}.${oakPath || options.path}` : oakPath || options.path;
|
||||
// const oakFullpath = oakParent ? `${oakParent}.${oakPath || options.path}` : oakPath || options.path;
|
||||
this.setData({
|
||||
oakEntity: node.getEntity(),
|
||||
oakFullpath,
|
||||
oakFullpath: path2,
|
||||
oakFrom,
|
||||
newOakActions: oakActions && JSON.parse(oakActions).length > 0 ? JSON.parse(oakActions) : options.actions || [],
|
||||
});
|
||||
|
|
@ -433,9 +436,9 @@ function createComponentOptions(options, features, doSubscribe, exceptionRouterD
|
|||
this.subscribed = undefined;
|
||||
}
|
||||
},
|
||||
async reRender() {
|
||||
async reRender(extra) {
|
||||
if (this.data.oakFullpath) {
|
||||
const $rows = await features.runningTree.getValue(this.data.oakFullpath);
|
||||
const $rows = await features.runningTree.getFreshValue(this.data.oakFullpath);
|
||||
const data = await formData.call(this, $rows, features);
|
||||
for (const k in data) {
|
||||
if (data[k] === undefined) {
|
||||
|
|
@ -463,6 +466,9 @@ function createComponentOptions(options, features, doSubscribe, exceptionRouterD
|
|||
oakLegalActions,
|
||||
});
|
||||
} */
|
||||
if (extra) {
|
||||
(0, lodash_1.assign)(data, extra);
|
||||
}
|
||||
this.setData(data);
|
||||
}
|
||||
},
|
||||
|
|
@ -472,7 +478,9 @@ function createComponentOptions(options, features, doSubscribe, exceptionRouterD
|
|||
if (path2 && parent2) {
|
||||
const oakFullpath2 = `${parent2}.${path2}`;
|
||||
if (oakFullpath2 !== this.data.oakFullpath) {
|
||||
this.data.oakFullpath = oakFullpath2;
|
||||
this.setData({
|
||||
oakFullpath: oakFullpath2,
|
||||
});
|
||||
this.reRender();
|
||||
}
|
||||
}
|
||||
|
|
@ -576,7 +584,10 @@ function createComponentOptions(options, features, doSubscribe, exceptionRouterD
|
|||
async ready() {
|
||||
const { oakPath, oakParent } = this.data;
|
||||
if (oakParent && oakPath) {
|
||||
this.data.oakFullpath = `${oakParent}.${oakPath}`;
|
||||
const oakFullpath = `${oakParent}.${oakPath}`;
|
||||
this.setData({
|
||||
oakFullpath,
|
||||
});
|
||||
this.reRender();
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ abstract class Node<ED extends EntityDict, T extends keyof ED, Cxt extends Conte
|
|||
|
||||
abstract onCachSync(opRecords: OpRecord<ED>[]): Promise<void>;
|
||||
|
||||
abstract refreshValue(): void;
|
||||
|
||||
constructor(entity: T, schema: StorageSchema<ED>, cache: Cache<ED, Cxt, AD>,
|
||||
projection: ED[T]['Selection']['data'] | (() => Promise<ED[T]['Selection']['data']>),
|
||||
parent?: Node<ED, keyof ED, Cxt, AD>, action?: ED[T]['Action'],
|
||||
|
|
@ -49,6 +51,7 @@ abstract class Node<ED extends EntityDict, T extends keyof ED, Cxt extends Conte
|
|||
setUpdateData(attr: string, value: any) {
|
||||
set(this.updateData, attr, value);
|
||||
this.setDirty();
|
||||
this.refreshValue();
|
||||
}
|
||||
|
||||
getUpdateData() {
|
||||
|
|
@ -58,6 +61,7 @@ abstract class Node<ED extends EntityDict, T extends keyof ED, Cxt extends Conte
|
|||
setMultiUpdateData(updateData: DeduceUpdateOperation<ED[T]['OpSchema']>['data']) {
|
||||
assign(this.updateData, updateData);
|
||||
this.setDirty();
|
||||
this.refreshValue();
|
||||
}
|
||||
|
||||
setDirty() {
|
||||
|
|
@ -72,6 +76,7 @@ abstract class Node<ED extends EntityDict, T extends keyof ED, Cxt extends Conte
|
|||
setAction(action: ED[T]['Action']) {
|
||||
this.action = action;
|
||||
this.setDirty();
|
||||
this.refreshValue();
|
||||
}
|
||||
|
||||
isDirty() {
|
||||
|
|
@ -170,7 +175,7 @@ class ListNode<ED extends EntityDict,
|
|||
}
|
||||
if (createdIds.length > 0 || removeIds) {
|
||||
const currentIds = this.children.map(
|
||||
ele => ele.getValue().id
|
||||
ele => ele.getFreshValue().id
|
||||
) as string[];
|
||||
|
||||
const filter = combineFilters([{
|
||||
|
|
@ -179,17 +184,19 @@ class ListNode<ED extends EntityDict,
|
|||
}
|
||||
}, ...(this.filters).map(ele => ele.filter)]);
|
||||
|
||||
const sorterss = await Promise.all(this.sorters.map(
|
||||
async (ele) => {
|
||||
const { sorter } = ele;
|
||||
if (typeof sorter === 'function') {
|
||||
return await sorter();
|
||||
const sorterss = await Promise.all(
|
||||
this.sorters.map(
|
||||
async (ele) => {
|
||||
const { sorter } = ele;
|
||||
if (typeof sorter === 'function') {
|
||||
return await sorter();
|
||||
}
|
||||
else {
|
||||
return sorter;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return sorter;
|
||||
}
|
||||
}
|
||||
));
|
||||
)
|
||||
);
|
||||
const projection = typeof this.projection === 'function' ? await this.projection() : this.projection;
|
||||
const value = await this.cache.get(this.entity, {
|
||||
data: projection as any,
|
||||
|
|
@ -200,6 +207,10 @@ class ListNode<ED extends EntityDict,
|
|||
}
|
||||
}
|
||||
|
||||
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'],
|
||||
|
|
@ -337,11 +348,23 @@ class ListNode<ED extends EntityDict,
|
|||
}
|
||||
}
|
||||
|
||||
getValue(): SelectRowShape<ED[T]['Schema'], ED[T]['Selection']['data']>[] {
|
||||
getFreshValue(): SelectRowShape<ED[T]['Schema'], ED[T]['Selection']['data']>[] {
|
||||
const value = this.children.map(
|
||||
ele => ele.getValue()
|
||||
ele => ele.getFreshValue()
|
||||
);
|
||||
return value;
|
||||
if (this.isDirty()) {
|
||||
const action = this.action || 'update';
|
||||
|
||||
if (action === 'remove') {
|
||||
return []; // 这个可能跑到吗?
|
||||
}
|
||||
return value.map(
|
||||
ele => assign({}, ele, this.updateData)
|
||||
);
|
||||
}
|
||||
else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
getAction() {
|
||||
|
|
@ -459,6 +482,7 @@ class SingleNode<ED extends EntityDict,
|
|||
AD extends Record<string, Aspect<ED, Cxt>>> extends Node<ED, T, Cxt, AD> {
|
||||
private id?: string;
|
||||
private value?: SelectRowShape<ED[T]['OpSchema'], ED[T]['Selection']['data']>;
|
||||
private freshValue?: SelectRowShape<ED[T]['OpSchema'], ED[T]['Selection']['data']>;
|
||||
|
||||
private children: {
|
||||
[K: string]: SingleNode<ED, keyof ED, Cxt, AD> | ListNode<ED, keyof ED, Cxt, AD>;
|
||||
|
|
@ -523,7 +547,7 @@ class SingleNode<ED extends EntityDict,
|
|||
id: this.id,
|
||||
}
|
||||
} as any, 'onCacheSync');
|
||||
this.updateValue(value);
|
||||
this.setValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -606,6 +630,21 @@ class SingleNode<ED extends EntityDict,
|
|||
unset(this.children, path);
|
||||
}
|
||||
|
||||
refreshValue() {
|
||||
const action = this.action || (this.isDirty() ? 'update' : '');
|
||||
if (!action) {
|
||||
this.freshValue = this.value;
|
||||
}
|
||||
else {
|
||||
if (action === 'remove') {
|
||||
this.freshValue = undefined;
|
||||
}
|
||||
else {
|
||||
this.freshValue = assign({}, this.value, this.updateData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setValue(value: SelectRowShape<ED[T]['OpSchema'], ED[T]['Selection']['data']>) {
|
||||
for (const attr in this.children) {
|
||||
const node = this.children[attr];
|
||||
|
|
@ -630,27 +669,19 @@ class SingleNode<ED extends EntityDict,
|
|||
}
|
||||
this.id = value.id as string;
|
||||
this.value = value;
|
||||
this.refreshValue();
|
||||
}
|
||||
|
||||
updateValue(value: SelectRowShape<ED[T]['Schema'], ED[T]['Selection']['data']>) {
|
||||
if (!this.value) {
|
||||
this.value = {} as SelectRowShape<ED[T]['Schema'], ED[T]['Selection']['data']>;
|
||||
}
|
||||
assign(this.value, value);
|
||||
|
||||
// todo,可能的一对多和多对一的子结点上的处理
|
||||
}
|
||||
|
||||
getValue(): SelectRowShape<ED[T]['Schema'], ED[T]['Selection']['data']> {
|
||||
const value = this.value ? cloneDeep(this.value) : {} as SelectRowShape<ED[T]['Schema'], ED[T]['Selection']['data']>;
|
||||
getFreshValue(): SelectRowShape<ED[T]['Schema'], ED[T]['Selection']['data']> {
|
||||
const freshValue = this.freshValue ? cloneDeep(this.freshValue) : {} as SelectRowShape<ED[T]['Schema'], ED[T]['Selection']['data']>;
|
||||
|
||||
for (const k in this.children) {
|
||||
assign(value, {
|
||||
[k]: this.children[k].getValue(),
|
||||
assign(freshValue, {
|
||||
[k]: this.children[k].getFreshValue(),
|
||||
});
|
||||
}
|
||||
|
||||
return value;
|
||||
return freshValue;
|
||||
}
|
||||
|
||||
getAction() {
|
||||
|
|
@ -708,6 +739,38 @@ class SingleNode<ED extends EntityDict,
|
|||
for (const attr in this.children) {
|
||||
this.children[attr].resetUpdateData();
|
||||
}
|
||||
this.refreshValue();
|
||||
}
|
||||
|
||||
async setForeignKey(attr: string, id: string) {
|
||||
const rel = this.judgeRelation(attr);
|
||||
|
||||
let subEntity: string;
|
||||
if (rel === 2) {
|
||||
this.setMultiUpdateData({
|
||||
entity: attr,
|
||||
entityId: id,
|
||||
} as any);
|
||||
subEntity = attr;
|
||||
}
|
||||
else {
|
||||
assert(typeof rel === 'string');
|
||||
this.setUpdateData(`${attr}Id`, id);
|
||||
subEntity = rel;
|
||||
}
|
||||
|
||||
// 如果修改了外键且对应的外键上有子结点,在这里把子结点的value更新掉
|
||||
if (this.children[attr]) {
|
||||
const proj = typeof this.projection === 'function' ? await this.projection() : this.projection;
|
||||
const subProj = proj[attr];
|
||||
const [value] = await this.cache.get(subEntity, {
|
||||
data: subProj,
|
||||
filter: {
|
||||
id,
|
||||
} as any,
|
||||
}, 'SingleNode:setForeignKey');
|
||||
(<SingleNode<ED, keyof ED, Cxt, AD>>this.children[attr]).setValue(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -981,20 +1044,11 @@ export class RunningTree<ED extends EntityDict, Cxt extends Context<ED>, AD exte
|
|||
}
|
||||
}
|
||||
|
||||
async getValue(path: string) {
|
||||
async getFreshValue(path: string) {
|
||||
const node = this.findNode(path);
|
||||
if (node) {
|
||||
let value: ReturnType<typeof node.getValue> | undefined = node.getValue();
|
||||
let value = node.getFreshValue();
|
||||
|
||||
if (node.isDirty()) {
|
||||
const operation = await node.composeOperation();
|
||||
const projection = await node.getProjection();
|
||||
value = (await this.applyOperation(node.getEntity(), cloneDeep(value), operation!, projection, path));
|
||||
}
|
||||
|
||||
return value instanceof Array ? value : [value];
|
||||
}
|
||||
return [];
|
||||
return value instanceof Array ? value : [value];
|
||||
}
|
||||
|
||||
isDirty(path: string) {
|
||||
|
|
@ -1034,21 +1088,11 @@ export class RunningTree<ED extends EntityDict, Cxt extends Context<ED>, AD exte
|
|||
}
|
||||
|
||||
@Action
|
||||
async setForeignKey(path: string, id: string) {
|
||||
throw new Error('method not implemented');
|
||||
const node = this.findNode(path);
|
||||
const parent = node.getParent()!;
|
||||
const attr = path.slice(path.lastIndexOf('.') + 1);
|
||||
const rel = judgeRelation(this.schema!, parent.getEntity(), attr);
|
||||
async setForeignKey(parent: string, attr: string, id: string) {
|
||||
const parentNode = this.findNode(parent);
|
||||
assert (parentNode instanceof SingleNode);
|
||||
|
||||
if (rel === 2) {
|
||||
parent.setUpdateData('entity', node.getEntity());
|
||||
parent.setUpdateData('entityId', id);
|
||||
}
|
||||
else {
|
||||
assert(typeof rel === 'string');
|
||||
parent.setUpdateData(`${attr}Id`, id);
|
||||
}
|
||||
parentNode.setForeignKey(attr, id);
|
||||
}
|
||||
|
||||
@Action
|
||||
|
|
@ -1234,7 +1278,7 @@ export class RunningTree<ED extends EntityDict, Cxt extends Context<ED>, AD exte
|
|||
|
||||
const node = parentNode.getChild(path);
|
||||
assert(parentNode instanceof ListNode && node instanceof SingleNode); // 现在应该不可能remove一个list吧,未来对list的处理还要细化
|
||||
if (node.getValue().id) {
|
||||
if (node.getFreshValue().id) {
|
||||
// 如果有id,说明是删除数据
|
||||
await this.getAspectProxy().operate({
|
||||
entity: node.getEntity() as string,
|
||||
|
|
@ -1242,7 +1286,7 @@ export class RunningTree<ED extends EntityDict, Cxt extends Context<ED>, AD exte
|
|||
action: 'remove',
|
||||
data: {},
|
||||
filter: {
|
||||
id: node.getValue().id,
|
||||
id: node.getFreshValue().id,
|
||||
},
|
||||
}
|
||||
}, parent);
|
||||
|
|
|
|||
|
|
@ -225,7 +225,7 @@ function createPageOptions<ED extends EntityDict,
|
|||
methods: {
|
||||
async reRender(extra) {
|
||||
if (this.data.oakFullpath) {
|
||||
const $rows = await features.runningTree.getValue(this.data.oakFullpath);
|
||||
const $rows = await features.runningTree.getFreshValue(this.data.oakFullpath);
|
||||
const data = await formData.call(this, $rows as any, features);
|
||||
for (const k in data) {
|
||||
if (data[k] === undefined) {
|
||||
|
|
@ -573,9 +573,9 @@ function createPageOptions<ED extends EntityDict,
|
|||
}
|
||||
));
|
||||
}
|
||||
const path2 = oakParent ? `${oakParent}:${oakPath || options.path}` : oakPath || options.path;
|
||||
const node = await features.runningTree.createNode({
|
||||
path: oakPath || options.path,
|
||||
parent: oakParent,
|
||||
path: path2,
|
||||
entity: (oakEntity || options.entity) as T,
|
||||
isList,
|
||||
isPicker: oakIsPicker,
|
||||
|
|
@ -585,10 +585,10 @@ function createPageOptions<ED extends EntityDict,
|
|||
sorters,
|
||||
id: oakId,
|
||||
});
|
||||
const oakFullpath = oakParent ? `${oakParent}.${oakPath || options.path}` : oakPath || options.path;
|
||||
// const oakFullpath = oakParent ? `${oakParent}.${oakPath || options.path}` : oakPath || options.path;
|
||||
this.setData({
|
||||
oakEntity: node.getEntity(),
|
||||
oakFullpath,
|
||||
oakFullpath: path2,
|
||||
oakFrom,
|
||||
newOakActions: oakActions && JSON.parse(oakActions).length > 0 ? JSON.parse(oakActions) : options.actions || [],
|
||||
});
|
||||
|
|
@ -684,7 +684,7 @@ function createComponentOptions<ED extends EntityDict,
|
|||
|
||||
async reRender(extra) {
|
||||
if (this.data.oakFullpath) {
|
||||
const $rows = await features.runningTree.getValue(this.data.oakFullpath);
|
||||
const $rows = await features.runningTree.getFreshValue(this.data.oakFullpath);
|
||||
const data = await formData.call(this, $rows as any, features);
|
||||
for (const k in data) {
|
||||
if (data[k] === undefined) {
|
||||
|
|
|
|||
|
|
@ -5,10 +5,3 @@ type A = {
|
|||
areaId: string;
|
||||
area?: number;
|
||||
}
|
||||
|
||||
const a: A = {
|
||||
areaId: 'ddd',
|
||||
area: {
|
||||
bb: 1,
|
||||
},
|
||||
}
|
||||
Loading…
Reference in New Issue