Merge branch 'dev' into release
This commit is contained in:
commit
0452132b2b
|
|
@ -10,8 +10,7 @@
|
|||
}
|
||||
|
||||
.block--bottom {
|
||||
width: 100vw;
|
||||
height: 35vh;
|
||||
width: 100%;
|
||||
border-top-left-radius: 16rpx;
|
||||
border-top-right-radius: 16rpx;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -179,7 +179,7 @@ declare class ListNode<ED extends EntityDict & BaseEntityDict, T extends keyof E
|
|||
* 存留查询结果
|
||||
*/
|
||||
saveRefreshResult(sr: Awaited<ReturnType<CommonAspectDict<ED>['select']>>, append?: boolean, currentPage?: number): void;
|
||||
refresh(pageNumber?: number, append?: boolean, resetTotal?: number): Promise<void>;
|
||||
refresh(pageNumber?: number, append?: boolean, resetTotal?: boolean): Promise<void>;
|
||||
loadMore(): Promise<void>;
|
||||
setCurrentPage(currentPage: number): void;
|
||||
clean(lsn?: number, dontPublish?: true): void;
|
||||
|
|
@ -313,7 +313,7 @@ export declare class RunningTree<ED extends EntityDict & BaseEntityDict> extends
|
|||
isLoading(path: string): boolean | undefined;
|
||||
isLoadingMore(path: string): boolean | undefined;
|
||||
isExecuting(path: string): boolean;
|
||||
isListDescandentOrStaleBranch(path: string): boolean;
|
||||
isListDescandentOrStale(path: string): boolean;
|
||||
private isInModiNextBranch;
|
||||
refresh(path: string, pageNumber?: number): Promise<void>;
|
||||
loadMore(path: string): Promise<void>;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { assert } from 'oak-domain/lib/utils/assert';
|
||||
import { cloneDeep, unset, uniq } from "oak-domain/lib/utils/lodash";
|
||||
import { cloneDeep, difference, unset, uniq, intersection } from "oak-domain/lib/utils/lodash";
|
||||
import { combineFilters, getRelevantIds } from "oak-domain/lib/store/filter";
|
||||
import { createOperationsFromModies } from 'oak-domain/lib/store/modi';
|
||||
import { judgeRelation } from "oak-domain/lib/store/relation";
|
||||
|
|
@ -417,8 +417,7 @@ class ListNode extends EntityNode {
|
|||
}
|
||||
}
|
||||
onCacheSync(records) {
|
||||
// 只需要处理当listNode为首页且插入/删除项满足条件的情况
|
||||
if (this.loading || this.pagination.currentPage !== 0) {
|
||||
if (this.loading) {
|
||||
return;
|
||||
}
|
||||
// let hasUpdated = false;
|
||||
|
|
@ -507,6 +506,50 @@ class ListNode extends EntityNode {
|
|||
}
|
||||
case 'u':
|
||||
default: {
|
||||
// 更新可能会引起本行不再满足条件
|
||||
const { e, d, f } = record;
|
||||
if (e === this.entity) {
|
||||
const { id } = f;
|
||||
const ids = typeof id === 'string' ? [id] : id.$in;
|
||||
const currentIds = Object.keys(this.sr);
|
||||
const intersected = intersection(ids, currentIds);
|
||||
const diffed = difference(ids, currentIds);
|
||||
/** 检查原本就在的,现在还在不在,
|
||||
* 以及原本不在的,现在是不是满足条件了
|
||||
* (后一种情况也可能原本就满足但不在当前的ids中,这时是判断不出来的,total+1可能不对,但是应该是较少的case)*/
|
||||
const filter = this.constructFilters(true, true, true);
|
||||
if (intersected.length) {
|
||||
const rows = this.cache.get(this.entity, {
|
||||
data: {
|
||||
id: 1,
|
||||
},
|
||||
filter: combineFilters(this.entity, this.schema, [
|
||||
...filter,
|
||||
{
|
||||
id: {
|
||||
$in: intersected,
|
||||
}
|
||||
}
|
||||
])
|
||||
});
|
||||
const rowIds = rows.map(ele => ele.id);
|
||||
const missed = difference(intersected, rowIds);
|
||||
missed.forEach((id) => {
|
||||
unset(this.sr, id);
|
||||
if (this.pagination.total) {
|
||||
this.pagination.total--;
|
||||
}
|
||||
});
|
||||
}
|
||||
if (diffed.length) {
|
||||
diffed.forEach((ele) => {
|
||||
this.sr[ele] = {};
|
||||
if (this.pagination.total) {
|
||||
this.pagination.total++;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
// hasUpdated = true;
|
||||
break;
|
||||
}
|
||||
|
|
@ -630,6 +673,7 @@ class ListNode extends EntityNode {
|
|||
if (fIndex >= 0) {
|
||||
this.filters.splice(fIndex, 1);
|
||||
}
|
||||
this.pagination.total = undefined;
|
||||
if (refresh) {
|
||||
this.refresh(0, false);
|
||||
}
|
||||
|
|
@ -643,6 +687,7 @@ class ListNode extends EntityNode {
|
|||
if (fIndex >= 0) {
|
||||
this.filters.splice(fIndex, 1);
|
||||
}
|
||||
this.pagination.total = undefined;
|
||||
if (refresh) {
|
||||
this.refresh(0, false);
|
||||
}
|
||||
|
|
@ -722,10 +767,10 @@ class ListNode extends EntityNode {
|
|||
* 在非modi状态下,所取数据是在ids2中满足filter的部分(自身对象和其它对象的更新可能会影响这些行不再满足条件)
|
||||
*/
|
||||
const filter2 = inModiNextBranch ? filter : (ids2.length > 0 ? combineFilters(this.entity, this.cache.getSchema(), [filter, {
|
||||
id: {
|
||||
$in: ids2,
|
||||
}
|
||||
}]) : undefined);
|
||||
id: {
|
||||
$in: ids2,
|
||||
}
|
||||
}]) : undefined);
|
||||
if (filter2 && data) {
|
||||
const result = this.cache.get(this.entity, {
|
||||
data,
|
||||
|
|
@ -1182,11 +1227,15 @@ class SingleNode extends EntityNode {
|
|||
const operations = this.ulManager.makeOperations();
|
||||
assert(operations.length <= 1);
|
||||
const [operation] = operations;
|
||||
// 如果本身是create, 这里无视就行(因为框架原因会调用一次)
|
||||
if (operation?.action === 'create') {
|
||||
if (operation.data.id === id) {
|
||||
// 如果本身是create, 这里无视就行(因为框架原因会调用一次)
|
||||
return;
|
||||
}
|
||||
else {
|
||||
// 这种情况是oakId属性没有初始化完成
|
||||
this.clean(0, true);
|
||||
}
|
||||
}
|
||||
assert(!this.dirty, 'setId时结点是dirty,在setId之前应当处理掉原有的update');
|
||||
this.id = id;
|
||||
|
|
@ -1918,7 +1967,7 @@ export class RunningTree extends Feature {
|
|||
}
|
||||
else {
|
||||
node = new SingleNode(entity, this.schema, this.cache, path, projection, parentNode, // 过编译
|
||||
id, filters, stale);
|
||||
id, filters, stale);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
@ -1934,7 +1983,10 @@ export class RunningTree extends Feature {
|
|||
});
|
||||
}
|
||||
node.increaseCount();
|
||||
node.setZombie(zombie);
|
||||
if (zombie) {
|
||||
// 像Pagination, FilterPanel, ExtrafileCommit这种要和某个Component共用路径的,按要求都应该是后创建,不能影响原来的zombie
|
||||
node.setZombie(zombie);
|
||||
}
|
||||
if (node instanceof SingleNode && !node.getId()) {
|
||||
node.create(this.logSerailNumber, {});
|
||||
}
|
||||
|
|
@ -2085,11 +2137,14 @@ export class RunningTree extends Feature {
|
|||
const node = this.findNode(path);
|
||||
return node ? node.isExecuting() : false;
|
||||
}
|
||||
isListDescandentOrStaleBranch(path) {
|
||||
isListDescandentOrStale(path) {
|
||||
const node = this.findNode(path);
|
||||
if (node?.isStale()) {
|
||||
return true;
|
||||
}
|
||||
let parent = node?.getParent();
|
||||
while (parent) {
|
||||
if (parent instanceof ListNode || parent.isStale()) {
|
||||
if (parent instanceof ListNode) {
|
||||
return true;
|
||||
}
|
||||
parent = parent.getParent();
|
||||
|
|
@ -2361,19 +2416,19 @@ export class RunningTree extends Feature {
|
|||
const result = await this.cache.operate(entities[0], operations
|
||||
.filter((ele) => !!ele)
|
||||
.map((ele) => ele.operation), undefined, () => {
|
||||
// 清空缓存
|
||||
this.clean(path, undefined, true);
|
||||
if (node instanceof SingleNode) {
|
||||
assert(operations.length === 1);
|
||||
// 这逻辑有点扯,页面自己决定后续逻辑 by Xc 20231108
|
||||
// if (operations[0].operation.action === 'create') {
|
||||
// // 如果是create动作,给结点赋上id,以保证页面数据的完整性
|
||||
// const { id } = operations[0].operation.data as ED[keyof ED]['CreateSingle']['data'];
|
||||
// node.setId(id);
|
||||
// }
|
||||
}
|
||||
node.setExecuting(false);
|
||||
});
|
||||
// 清空缓存
|
||||
this.clean(path, undefined, true);
|
||||
if (node instanceof SingleNode) {
|
||||
assert(operations.length === 1);
|
||||
// 这逻辑有点扯,页面自己决定后续逻辑 by Xc 20231108
|
||||
// if (operations[0].operation.action === 'create') {
|
||||
// // 如果是create动作,给结点赋上id,以保证页面数据的完整性
|
||||
// const { id } = operations[0].operation.data as ED[keyof ED]['CreateSingle']['data'];
|
||||
// node.setId(id);
|
||||
// }
|
||||
}
|
||||
node.setExecuting(false);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
this.clean(path, undefined, true);
|
||||
|
|
|
|||
|
|
@ -442,10 +442,10 @@ export function reRender(option, extra) {
|
|||
const entity = this.features.runningTree.getEntity(this.state.oakFullpath);
|
||||
if (origin) {
|
||||
if (rows instanceof Array) {
|
||||
modified = compareRows(schema, entity, rows, origin);
|
||||
modified = !compareRows(schema, entity, rows, origin);
|
||||
}
|
||||
else {
|
||||
modified = compareRow(schema, entity, rows, origin);
|
||||
modified = !compareRow(schema, entity, rows, origin);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
|
|||
|
|
@ -197,7 +197,7 @@ const oakBehavior = Behavior({
|
|||
? `${this.state.oakFullpath}.${path}`
|
||||
: this.state.oakFullpath;
|
||||
const operations = this.features.runningTree.getOperations(path2);
|
||||
if (operations) {
|
||||
if (operations?.length) {
|
||||
for (const oper of operations) {
|
||||
const { entity, operation } = oper;
|
||||
const operation2 = action ? {
|
||||
|
|
@ -485,7 +485,7 @@ const oakBehavior = Behavior({
|
|||
this.oakOption.lifetimes?.ready &&
|
||||
this.oakOption.lifetimes?.ready.call(this);
|
||||
const { oakFullpath } = this.state;
|
||||
if (oakFullpath && !this.features.runningTree.isListDescandentOrStaleBranch(oakFullpath)) {
|
||||
if (oakFullpath && !this.features.runningTree.isListDescandentOrStale(oakFullpath)) {
|
||||
this.refresh();
|
||||
}
|
||||
else {
|
||||
|
|
@ -788,7 +788,7 @@ export function createComponent(option, features) {
|
|||
return;
|
||||
}
|
||||
const { oakFullpath } = this.state;
|
||||
if (oakFullpath && !this.features.runningTree.isListDescandentOrStaleBranch(oakFullpath)) {
|
||||
if (oakFullpath && !this.features.runningTree.isListDescandentOrStale(oakFullpath)) {
|
||||
try {
|
||||
await this.refresh();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -187,7 +187,7 @@ class OakComponentBase extends React.PureComponent {
|
|||
? `${this.state.oakFullpath}.${path}`
|
||||
: this.state.oakFullpath;
|
||||
const operations = this.features.runningTree.getOperations(path2);
|
||||
if (operations) {
|
||||
if (operations?.length) {
|
||||
for (const oper of operations) {
|
||||
const { entity, operation } = oper;
|
||||
const operation2 = action ? {
|
||||
|
|
@ -646,7 +646,7 @@ export function createComponent(option, features) {
|
|||
}
|
||||
try {
|
||||
const { oakFullpath } = this.state;
|
||||
if (oakFullpath && !this.features.runningTree.isListDescandentOrStaleBranch(oakFullpath)) {
|
||||
if (oakFullpath && !this.features.runningTree.isListDescandentOrStale(oakFullpath)) {
|
||||
await this.refresh();
|
||||
}
|
||||
else {
|
||||
|
|
@ -704,7 +704,7 @@ export function createComponent(option, features) {
|
|||
lifetimes?.show && lifetimes.show.call(this);
|
||||
}
|
||||
const { oakFullpath } = this.state;
|
||||
if (oakFullpath && !this.features.runningTree.isListDescandentOrStaleBranch(oakFullpath)) {
|
||||
if (oakFullpath && !this.features.runningTree.isListDescandentOrStale(oakFullpath)) {
|
||||
this.refresh();
|
||||
}
|
||||
else {
|
||||
|
|
|
|||
|
|
@ -179,7 +179,7 @@ declare class ListNode<ED extends EntityDict & BaseEntityDict, T extends keyof E
|
|||
* 存留查询结果
|
||||
*/
|
||||
saveRefreshResult(sr: Awaited<ReturnType<CommonAspectDict<ED>['select']>>, append?: boolean, currentPage?: number): void;
|
||||
refresh(pageNumber?: number, append?: boolean, resetTotal?: number): Promise<void>;
|
||||
refresh(pageNumber?: number, append?: boolean, resetTotal?: boolean): Promise<void>;
|
||||
loadMore(): Promise<void>;
|
||||
setCurrentPage(currentPage: number): void;
|
||||
clean(lsn?: number, dontPublish?: true): void;
|
||||
|
|
@ -313,7 +313,7 @@ export declare class RunningTree<ED extends EntityDict & BaseEntityDict> extends
|
|||
isLoading(path: string): boolean | undefined;
|
||||
isLoadingMore(path: string): boolean | undefined;
|
||||
isExecuting(path: string): boolean;
|
||||
isListDescandentOrStaleBranch(path: string): boolean;
|
||||
isListDescandentOrStale(path: string): boolean;
|
||||
private isInModiNextBranch;
|
||||
refresh(path: string, pageNumber?: number): Promise<void>;
|
||||
loadMore(path: string): Promise<void>;
|
||||
|
|
|
|||
|
|
@ -420,8 +420,7 @@ class ListNode extends EntityNode {
|
|||
}
|
||||
}
|
||||
onCacheSync(records) {
|
||||
// 只需要处理当listNode为首页且插入/删除项满足条件的情况
|
||||
if (this.loading || this.pagination.currentPage !== 0) {
|
||||
if (this.loading) {
|
||||
return;
|
||||
}
|
||||
// let hasUpdated = false;
|
||||
|
|
@ -510,6 +509,50 @@ class ListNode extends EntityNode {
|
|||
}
|
||||
case 'u':
|
||||
default: {
|
||||
// 更新可能会引起本行不再满足条件
|
||||
const { e, d, f } = record;
|
||||
if (e === this.entity) {
|
||||
const { id } = f;
|
||||
const ids = typeof id === 'string' ? [id] : id.$in;
|
||||
const currentIds = Object.keys(this.sr);
|
||||
const intersected = (0, lodash_1.intersection)(ids, currentIds);
|
||||
const diffed = (0, lodash_1.difference)(ids, currentIds);
|
||||
/** 检查原本就在的,现在还在不在,
|
||||
* 以及原本不在的,现在是不是满足条件了
|
||||
* (后一种情况也可能原本就满足但不在当前的ids中,这时是判断不出来的,total+1可能不对,但是应该是较少的case)*/
|
||||
const filter = this.constructFilters(true, true, true);
|
||||
if (intersected.length) {
|
||||
const rows = this.cache.get(this.entity, {
|
||||
data: {
|
||||
id: 1,
|
||||
},
|
||||
filter: (0, filter_1.combineFilters)(this.entity, this.schema, [
|
||||
...filter,
|
||||
{
|
||||
id: {
|
||||
$in: intersected,
|
||||
}
|
||||
}
|
||||
])
|
||||
});
|
||||
const rowIds = rows.map(ele => ele.id);
|
||||
const missed = (0, lodash_1.difference)(intersected, rowIds);
|
||||
missed.forEach((id) => {
|
||||
(0, lodash_1.unset)(this.sr, id);
|
||||
if (this.pagination.total) {
|
||||
this.pagination.total--;
|
||||
}
|
||||
});
|
||||
}
|
||||
if (diffed.length) {
|
||||
diffed.forEach((ele) => {
|
||||
this.sr[ele] = {};
|
||||
if (this.pagination.total) {
|
||||
this.pagination.total++;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
// hasUpdated = true;
|
||||
break;
|
||||
}
|
||||
|
|
@ -633,6 +676,7 @@ class ListNode extends EntityNode {
|
|||
if (fIndex >= 0) {
|
||||
this.filters.splice(fIndex, 1);
|
||||
}
|
||||
this.pagination.total = undefined;
|
||||
if (refresh) {
|
||||
this.refresh(0, false);
|
||||
}
|
||||
|
|
@ -646,6 +690,7 @@ class ListNode extends EntityNode {
|
|||
if (fIndex >= 0) {
|
||||
this.filters.splice(fIndex, 1);
|
||||
}
|
||||
this.pagination.total = undefined;
|
||||
if (refresh) {
|
||||
this.refresh(0, false);
|
||||
}
|
||||
|
|
@ -1185,11 +1230,15 @@ class SingleNode extends EntityNode {
|
|||
const operations = this.ulManager.makeOperations();
|
||||
(0, assert_1.assert)(operations.length <= 1);
|
||||
const [operation] = operations;
|
||||
// 如果本身是create, 这里无视就行(因为框架原因会调用一次)
|
||||
if (operation?.action === 'create') {
|
||||
if (operation.data.id === id) {
|
||||
// 如果本身是create, 这里无视就行(因为框架原因会调用一次)
|
||||
return;
|
||||
}
|
||||
else {
|
||||
// 这种情况是oakId属性没有初始化完成
|
||||
this.clean(0, true);
|
||||
}
|
||||
}
|
||||
(0, assert_1.assert)(!this.dirty, 'setId时结点是dirty,在setId之前应当处理掉原有的update');
|
||||
this.id = id;
|
||||
|
|
@ -1937,7 +1986,10 @@ class RunningTree extends Feature_1.Feature {
|
|||
});
|
||||
}
|
||||
node.increaseCount();
|
||||
node.setZombie(zombie);
|
||||
if (zombie) {
|
||||
// 像Pagination, FilterPanel, ExtrafileCommit这种要和某个Component共用路径的,按要求都应该是后创建,不能影响原来的zombie
|
||||
node.setZombie(zombie);
|
||||
}
|
||||
if (node instanceof SingleNode && !node.getId()) {
|
||||
node.create(this.logSerailNumber, {});
|
||||
}
|
||||
|
|
@ -2088,11 +2140,14 @@ class RunningTree extends Feature_1.Feature {
|
|||
const node = this.findNode(path);
|
||||
return node ? node.isExecuting() : false;
|
||||
}
|
||||
isListDescandentOrStaleBranch(path) {
|
||||
isListDescandentOrStale(path) {
|
||||
const node = this.findNode(path);
|
||||
if (node?.isStale()) {
|
||||
return true;
|
||||
}
|
||||
let parent = node?.getParent();
|
||||
while (parent) {
|
||||
if (parent instanceof ListNode || parent.isStale()) {
|
||||
if (parent instanceof ListNode) {
|
||||
return true;
|
||||
}
|
||||
parent = parent.getParent();
|
||||
|
|
|
|||
|
|
@ -446,10 +446,10 @@ function reRender(option, extra) {
|
|||
const entity = this.features.runningTree.getEntity(this.state.oakFullpath);
|
||||
if (origin) {
|
||||
if (rows instanceof Array) {
|
||||
modified = (0, row_1.compareRows)(schema, entity, rows, origin);
|
||||
modified = !(0, row_1.compareRows)(schema, entity, rows, origin);
|
||||
}
|
||||
else {
|
||||
modified = (0, row_1.compareRow)(schema, entity, rows, origin);
|
||||
modified = !(0, row_1.compareRow)(schema, entity, rows, origin);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
|
|||
|
|
@ -200,7 +200,7 @@ const oakBehavior = Behavior({
|
|||
? `${this.state.oakFullpath}.${path}`
|
||||
: this.state.oakFullpath;
|
||||
const operations = this.features.runningTree.getOperations(path2);
|
||||
if (operations) {
|
||||
if (operations?.length) {
|
||||
for (const oper of operations) {
|
||||
const { entity, operation } = oper;
|
||||
const operation2 = action ? {
|
||||
|
|
@ -488,7 +488,7 @@ const oakBehavior = Behavior({
|
|||
this.oakOption.lifetimes?.ready &&
|
||||
this.oakOption.lifetimes?.ready.call(this);
|
||||
const { oakFullpath } = this.state;
|
||||
if (oakFullpath && !this.features.runningTree.isListDescandentOrStaleBranch(oakFullpath)) {
|
||||
if (oakFullpath && !this.features.runningTree.isListDescandentOrStale(oakFullpath)) {
|
||||
this.refresh();
|
||||
}
|
||||
else {
|
||||
|
|
@ -791,7 +791,7 @@ function createComponent(option, features) {
|
|||
return;
|
||||
}
|
||||
const { oakFullpath } = this.state;
|
||||
if (oakFullpath && !this.features.runningTree.isListDescandentOrStaleBranch(oakFullpath)) {
|
||||
if (oakFullpath && !this.features.runningTree.isListDescandentOrStale(oakFullpath)) {
|
||||
try {
|
||||
await this.refresh();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -192,7 +192,7 @@ class OakComponentBase extends react_1.default.PureComponent {
|
|||
? `${this.state.oakFullpath}.${path}`
|
||||
: this.state.oakFullpath;
|
||||
const operations = this.features.runningTree.getOperations(path2);
|
||||
if (operations) {
|
||||
if (operations?.length) {
|
||||
for (const oper of operations) {
|
||||
const { entity, operation } = oper;
|
||||
const operation2 = action ? {
|
||||
|
|
@ -651,7 +651,7 @@ function createComponent(option, features) {
|
|||
}
|
||||
try {
|
||||
const { oakFullpath } = this.state;
|
||||
if (oakFullpath && !this.features.runningTree.isListDescandentOrStaleBranch(oakFullpath)) {
|
||||
if (oakFullpath && !this.features.runningTree.isListDescandentOrStale(oakFullpath)) {
|
||||
await this.refresh();
|
||||
}
|
||||
else {
|
||||
|
|
@ -709,7 +709,7 @@ function createComponent(option, features) {
|
|||
lifetimes?.show && lifetimes.show.call(this);
|
||||
}
|
||||
const { oakFullpath } = this.state;
|
||||
if (oakFullpath && !this.features.runningTree.isListDescandentOrStaleBranch(oakFullpath)) {
|
||||
if (oakFullpath && !this.features.runningTree.isListDescandentOrStale(oakFullpath)) {
|
||||
this.refresh();
|
||||
}
|
||||
else {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "oak-frontend-base",
|
||||
"version": "5.3.23",
|
||||
"version": "5.3.24",
|
||||
"description": "oak框架中前端与业务逻辑无关的平台部分",
|
||||
"author": {
|
||||
"name": "XuChang"
|
||||
|
|
@ -23,8 +23,8 @@
|
|||
"node-schedule": "^2.1.1",
|
||||
"nprogress": "^0.2.0",
|
||||
"oak-common-aspect": "^3.0.5",
|
||||
"oak-domain": "^5.1.15",
|
||||
"oak-memory-tree-store": "^3.3.8",
|
||||
"oak-domain": "^5.1.16",
|
||||
"oak-memory-tree-store": "^3.3.9",
|
||||
"ol": "^7.3.0",
|
||||
"rc-pagination": "^4.3.0",
|
||||
"react-activation": "^0.12.4",
|
||||
|
|
@ -64,7 +64,7 @@
|
|||
"@types/node": "^20.7.0",
|
||||
"@types/node-schedule": "^2.1.0",
|
||||
"@types/nprogress": "^0.2.3",
|
||||
"@types/react": "^18.3.17",
|
||||
"@types/react": "^18.3.18",
|
||||
"@types/react-dom": "^18.2.14",
|
||||
"@types/react-native": "^0.72.8",
|
||||
"@types/uuid": "^9.0.6",
|
||||
|
|
|
|||
|
|
@ -10,8 +10,7 @@
|
|||
}
|
||||
|
||||
.block--bottom {
|
||||
width: 100vw;
|
||||
height: 35vh;
|
||||
width: 100%;
|
||||
border-top-left-radius: 16rpx;
|
||||
border-top-right-radius: 16rpx;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { assert } from 'oak-domain/lib/utils/assert';
|
||||
import { cloneDeep, difference, unset, merge, uniq, omit } from "oak-domain/lib/utils/lodash";
|
||||
import { cloneDeep, difference, unset, merge, uniq, omit, intersection } from "oak-domain/lib/utils/lodash";
|
||||
import { combineFilters, getRelevantIds } from "oak-domain/lib/store/filter";
|
||||
import { createOperationsFromModies } from 'oak-domain/lib/store/modi';
|
||||
import { judgeRelation } from "oak-domain/lib/store/relation";
|
||||
|
|
@ -534,8 +534,7 @@ class ListNode<
|
|||
}
|
||||
|
||||
onCacheSync(records: OpRecord<ED>[]) {
|
||||
// 只需要处理当listNode为首页且插入/删除项满足条件的情况
|
||||
if (this.loading || this.pagination.currentPage !== 0) {
|
||||
if (this.loading) {
|
||||
return;
|
||||
}
|
||||
// let hasUpdated = false;
|
||||
|
|
@ -628,6 +627,56 @@ class ListNode<
|
|||
}
|
||||
case 'u':
|
||||
default: {
|
||||
// 更新可能会引起本行不再满足条件
|
||||
const { e, d, f } = record as UpdateOpResult<ED, keyof ED>;
|
||||
if (e === this.entity) {
|
||||
const { id } = f!;
|
||||
const ids: string[] = typeof id === 'string' ? [id] : id.$in;
|
||||
const currentIds = Object.keys(this.sr);
|
||||
|
||||
const intersected = intersection(ids, currentIds);
|
||||
const diffed = difference(ids, currentIds);
|
||||
|
||||
/** 检查原本就在的,现在还在不在,
|
||||
* 以及原本不在的,现在是不是满足条件了
|
||||
* (后一种情况也可能原本就满足但不在当前的ids中,这时是判断不出来的,total+1可能不对,但是应该是较少的case)*/
|
||||
const filter = this.constructFilters(true, true, true);
|
||||
if (intersected.length) {
|
||||
const rows = this.cache.get(this.entity, {
|
||||
data: {
|
||||
id: 1,
|
||||
},
|
||||
filter: combineFilters(this.entity, this.schema, [
|
||||
...filter!,
|
||||
{
|
||||
id: {
|
||||
$in: intersected,
|
||||
}
|
||||
}
|
||||
])
|
||||
});
|
||||
const rowIds = rows.map(ele => ele.id!);
|
||||
const missed = difference(intersected, rowIds);
|
||||
missed.forEach(
|
||||
(id) => {
|
||||
unset(this.sr, id);
|
||||
if (this.pagination.total) {
|
||||
this.pagination.total --;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
if (diffed.length) {
|
||||
diffed.forEach(
|
||||
(ele) => {
|
||||
this.sr[ele] = {};
|
||||
if (this.pagination.total) {
|
||||
this.pagination.total ++;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
// hasUpdated = true;
|
||||
break;
|
||||
}
|
||||
|
|
@ -784,6 +833,7 @@ class ListNode<
|
|||
if (fIndex >= 0) {
|
||||
this.filters.splice(fIndex, 1);
|
||||
}
|
||||
this.pagination.total = undefined;
|
||||
if (refresh) {
|
||||
this.refresh(0, false);
|
||||
} else {
|
||||
|
|
@ -797,6 +847,7 @@ class ListNode<
|
|||
if (fIndex >= 0) {
|
||||
this.filters.splice(fIndex, 1);
|
||||
}
|
||||
this.pagination.total = undefined;
|
||||
if (refresh) {
|
||||
this.refresh(0, false);
|
||||
} else {
|
||||
|
|
@ -1208,7 +1259,7 @@ class ListNode<
|
|||
// this.publish();
|
||||
}
|
||||
|
||||
async refresh(pageNumber?: number, append?: boolean, resetTotal?: number) {
|
||||
async refresh(pageNumber?: number, append?: boolean, resetTotal?: boolean) {
|
||||
if (resetTotal) {
|
||||
// 清空之前查询计算的total值,目前只有父结点id改变会这样调用
|
||||
this.pagination.total = undefined;
|
||||
|
|
@ -1466,11 +1517,15 @@ class SingleNode<ED extends EntityDict & BaseEntityDict,
|
|||
const operations = this.ulManager.makeOperations();
|
||||
assert(operations.length <= 1);
|
||||
const [operation] = operations;
|
||||
// 如果本身是create, 这里无视就行(因为框架原因会调用一次)
|
||||
if (operation?.action === 'create') {
|
||||
if (operation.data.id === id) {
|
||||
// 如果本身是create, 这里无视就行(因为框架原因会调用一次)
|
||||
return;
|
||||
}
|
||||
else {
|
||||
// 这种情况是oakId属性没有初始化完成
|
||||
this.clean(0, true);
|
||||
}
|
||||
}
|
||||
assert(!this.dirty, 'setId时结点是dirty,在setId之前应当处理掉原有的update');
|
||||
this.id = id;
|
||||
|
|
@ -2352,7 +2407,10 @@ export class RunningTree<ED extends EntityDict & BaseEntityDict> extends Feature
|
|||
}
|
||||
|
||||
node.increaseCount();
|
||||
node.setZombie(zombie);
|
||||
if (zombie) {
|
||||
// 像Pagination, FilterPanel, ExtrafileCommit这种要和某个Component共用路径的,按要求都应该是后创建,不能影响原来的zombie
|
||||
node.setZombie(zombie);
|
||||
}
|
||||
if (node instanceof SingleNode && !node.getId()) {
|
||||
node.create(this.logSerailNumber, {});
|
||||
}
|
||||
|
|
@ -2545,11 +2603,14 @@ export class RunningTree<ED extends EntityDict & BaseEntityDict> extends Feature
|
|||
return node ? node.isExecuting() : false;
|
||||
}
|
||||
|
||||
isListDescandentOrStaleBranch(path: string) {
|
||||
isListDescandentOrStale(path: string) {
|
||||
const node = this.findNode(path);
|
||||
if (node?.isStale()) {
|
||||
return true;
|
||||
}
|
||||
let parent = node?.getParent();
|
||||
while (parent) {
|
||||
if (parent instanceof ListNode || parent.isStale()) {
|
||||
if (parent instanceof ListNode) {
|
||||
return true;
|
||||
}
|
||||
parent = parent.getParent();
|
||||
|
|
|
|||
|
|
@ -547,10 +547,10 @@ export function reRender<
|
|||
const entity = this.features.runningTree.getEntity(this.state.oakFullpath);
|
||||
if (origin) {
|
||||
if (rows instanceof Array) {
|
||||
modified = compareRows(schema, entity, rows, origin as typeof rows);
|
||||
modified = !compareRows(schema, entity, rows, origin as typeof rows);
|
||||
}
|
||||
else {
|
||||
modified = compareRow(schema, entity, rows!, origin as NonNullable<typeof rows>);
|
||||
modified = !compareRow(schema, entity, rows!, origin as NonNullable<typeof rows>);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
|
|||
|
|
@ -332,7 +332,7 @@ const oakBehavior = Behavior<
|
|||
? `${this.state.oakFullpath}.${path}`
|
||||
: this.state.oakFullpath;
|
||||
const operations = this.features.runningTree.getOperations(path2);
|
||||
if (operations) {
|
||||
if (operations?.length) {
|
||||
for (const oper of operations) {
|
||||
const { entity, operation } = oper;
|
||||
const operation2 = action ? {
|
||||
|
|
@ -709,7 +709,7 @@ const oakBehavior = Behavior<
|
|||
this.oakOption.lifetimes?.ready.call(this);
|
||||
|
||||
const { oakFullpath } = this.state;
|
||||
if (oakFullpath && !this.features.runningTree.isListDescandentOrStaleBranch(oakFullpath)) {
|
||||
if (oakFullpath && !this.features.runningTree.isListDescandentOrStale(oakFullpath)) {
|
||||
this.refresh();
|
||||
} else {
|
||||
this.reRender();
|
||||
|
|
@ -1113,7 +1113,7 @@ export function createComponent<
|
|||
return;
|
||||
}
|
||||
const { oakFullpath } = this.state;
|
||||
if (oakFullpath && !this.features.runningTree.isListDescandentOrStaleBranch(oakFullpath)) {
|
||||
if (oakFullpath && !this.features.runningTree.isListDescandentOrStale(oakFullpath)) {
|
||||
try {
|
||||
await this.refresh();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -368,7 +368,7 @@ abstract class OakComponentBase<
|
|||
? `${this.state.oakFullpath}.${path}`
|
||||
: this.state.oakFullpath;
|
||||
const operations = this.features.runningTree.getOperations(path2);
|
||||
if (operations) {
|
||||
if (operations?.length) {
|
||||
for (const oper of operations) {
|
||||
const { entity, operation } = oper;
|
||||
const operation2 = action ? {
|
||||
|
|
@ -979,7 +979,7 @@ export function createComponent<
|
|||
|
||||
try {
|
||||
const { oakFullpath } = this.state;
|
||||
if (oakFullpath && !this.features.runningTree.isListDescandentOrStaleBranch(oakFullpath)) {
|
||||
if (oakFullpath && !this.features.runningTree.isListDescandentOrStale(oakFullpath)) {
|
||||
await this.refresh();
|
||||
}
|
||||
else {
|
||||
|
|
@ -1047,7 +1047,7 @@ export function createComponent<
|
|||
lifetimes?.show && lifetimes.show.call(this);
|
||||
}
|
||||
const { oakFullpath } = this.state;
|
||||
if (oakFullpath && !this.features.runningTree.isListDescandentOrStaleBranch(oakFullpath)) {
|
||||
if (oakFullpath && !this.features.runningTree.isListDescandentOrStale(oakFullpath)) {
|
||||
this.refresh();
|
||||
}
|
||||
else {
|
||||
|
|
|
|||
Loading…
Reference in New Issue