Merge branch 'dev' into release
This commit is contained in:
commit
22baf22456
|
|
@ -1,9 +1,9 @@
|
|||
export default OakComponent({
|
||||
isList: false,
|
||||
data: {
|
||||
slideWidth: 0,
|
||||
slideLeft: 0,
|
||||
slideShow: false,
|
||||
slideWidth: 0, //小程序使用
|
||||
slideLeft: 0, //小程序使用
|
||||
slideShow: false, //小程序使用
|
||||
commonAction: [
|
||||
'create',
|
||||
'update',
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ export default OakComponent({
|
|||
let currentUrl = event.currentTarget.dataset.src;
|
||||
let urlList = event.currentTarget.dataset.list;
|
||||
wx.previewImage({
|
||||
current: currentUrl,
|
||||
current: currentUrl, // 当前显示图片的http链接
|
||||
urls: urlList, // 需要预览的图片http链接列表
|
||||
});
|
||||
},
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ export default OakComponent({
|
|||
code: '',
|
||||
title: '',
|
||||
desc: '',
|
||||
icon: '',
|
||||
icon: '', //web独有
|
||||
imagePath: '', //小程序独有
|
||||
},
|
||||
lifetimes: {
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ export default OakComponent({
|
|||
attribute: {},
|
||||
options: [],
|
||||
inputType: '',
|
||||
timeStartStr: '',
|
||||
timeStartStr: '', // 小程序选择时间显示
|
||||
timeEndStr: '',
|
||||
selectedLabel: '',
|
||||
minDateMp: new Date(1980, 1, 1).getTime(),
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ type ToolBarProps = {
|
|||
title?: React.ReactNode;
|
||||
buttonGroup?: buttonProps[];
|
||||
extraContent?: React.ReactNode;
|
||||
reload: () => void;
|
||||
reload?: () => void;
|
||||
};
|
||||
declare function ToolBar(props: ToolBarProps): React.JSX.Element;
|
||||
export default ToolBar;
|
||||
|
|
|
|||
|
|
@ -14,13 +14,14 @@ function ToolBar(props) {
|
|||
<Space align='center'>
|
||||
{extraContent}
|
||||
{buttonGroup && buttonGroup.length > 0 && (<ButtonGroup items={buttonGroup}/>)}
|
||||
<Tooltip title={features.locales.t('reload')}>
|
||||
<div className={Style.reloadIconBox} onClick={() => {
|
||||
reload();
|
||||
}}>
|
||||
<ReloadOutlined />
|
||||
</div>
|
||||
</Tooltip>
|
||||
{reload &&
|
||||
<Tooltip title={features.locales.t('reload')}>
|
||||
<div className={Style.reloadIconBox} onClick={() => {
|
||||
reload();
|
||||
}}>
|
||||
<ReloadOutlined />
|
||||
</div>
|
||||
</Tooltip>}
|
||||
<ColumnSetting />
|
||||
</Space>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -68,9 +68,7 @@ const ProList = (props) => {
|
|||
},
|
||||
}}>
|
||||
<div className={Style.container}>
|
||||
{!isMobile && !hideDefaultButtons && (<ToolBar title={title} extraContent={extraContent} buttonGroup={buttonGroup} reload={() => {
|
||||
onReload && onReload();
|
||||
}}/>)}
|
||||
{!isMobile && !hideDefaultButtons && (<ToolBar title={title} extraContent={extraContent} buttonGroup={buttonGroup} reload={onReload}/>)}
|
||||
{isMobile && <ButtonGroup items={buttonGroup}/>}
|
||||
<List entity={entity} extraActions={extraActions} onAction={onAction} disabledOp={disabledOp} attributes={attributes} data={!disableSerialNumber
|
||||
? data?.map((ele, index) => {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ export default OakComponent({
|
|||
multiple: false,
|
||||
entityId: '',
|
||||
entityIds: [],
|
||||
pickerRender: {},
|
||||
pickerRender: {}, // OakAbsRefAttrPickerRender
|
||||
onChange: (() => undefined),
|
||||
},
|
||||
formData() {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ export default OakComponent({
|
|||
return this.props.entity;
|
||||
},
|
||||
properties: {
|
||||
helps: {},
|
||||
helps: {}, // Record<string, string>;
|
||||
entity: '',
|
||||
attributes: [],
|
||||
layout: 'horizontal',
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ export declare abstract class BackendRuntimeContext<ED extends EntityDict & Base
|
|||
getSubscriberId(): string | undefined;
|
||||
getBriefEnvironment(): BriefEnv | undefined;
|
||||
protected getSerializedData(): Promise<SerializedData>;
|
||||
initialize(data?: SerializedData): Promise<void>;
|
||||
initialize(data?: SerializedData, later?: boolean): Promise<void>;
|
||||
/**
|
||||
* 未来可以支持在event中带id的占位符,到saveOpRecord时再动态注入 by Xc
|
||||
* @param operationId
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ export class BackendRuntimeContext extends AsyncContext {
|
|||
ns: this.ns,
|
||||
};
|
||||
}
|
||||
async initialize(data) {
|
||||
async initialize(data, later) {
|
||||
if (data?.sid) {
|
||||
this.subscriberId = data.sid;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -321,7 +321,7 @@ export class Cache extends Feature {
|
|||
opers.forEach((oper) => {
|
||||
const { entity, operation } = oper;
|
||||
this.cacheStore.operate(entity, operation, this.context, {
|
||||
checkerTypes: ['logical'],
|
||||
checkerTypes: ['logical'], // 这里不能检查data,不然在数据没填完前会有大量异常
|
||||
dontCollect: true,
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import { Environment } from './environment';
|
|||
import { SyncContext } from 'oak-domain/lib/store/SyncRowStore';
|
||||
import { Scope, TranslateOptions } from 'i18n-js';
|
||||
export declare class Locales<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED>, FrontCxt extends SyncContext<ED>, AD extends CommonAspectDict<ED, Cxt>> extends Feature {
|
||||
static MINIMAL_LOADING_GAP: number;
|
||||
static REFRESH_STALE_INTERVAL: number;
|
||||
private cache;
|
||||
private localStorage;
|
||||
private environment;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { assert } from 'oak-domain/lib/utils/assert';
|
|||
import { I18n } from 'i18n-js';
|
||||
import { LOCAL_STORAGE_KEYS } from '../constant/constant';
|
||||
export class Locales extends Feature {
|
||||
static MINIMAL_LOADING_GAP = 600 * 10000; // 最小加载间歇
|
||||
static REFRESH_STALE_INTERVAL = 30 * 24 * 3600 * 1000; // 正式环境下的主动刷新缓存策略
|
||||
cache;
|
||||
localStorage;
|
||||
environment;
|
||||
|
|
@ -61,6 +61,7 @@ export class Locales extends Feature {
|
|||
data: 1,
|
||||
namespace: 1,
|
||||
language: 1,
|
||||
$$updateAt$$: 1,
|
||||
},
|
||||
});
|
||||
const dataset = {};
|
||||
|
|
@ -76,10 +77,23 @@ export class Locales extends Feature {
|
|||
});
|
||||
this.i18n.store(dataset);
|
||||
if (i18ns.length > 0) {
|
||||
// 启动时刷新数据策略
|
||||
// 先不处理了,这样似乎会导致如果key不miss就不会更新,所以i18n的更新要确保这点
|
||||
/* const nss = i18ns.map(ele => ele.namespace!);
|
||||
await this.loadServerData(nss); */
|
||||
/**
|
||||
* 前台启动时的数据刷新策略:
|
||||
* dev环境无条件刷新,production环境只会主动刷新超过REFRESH_STALE_INTERVAL(30天)的i18n数据,
|
||||
* 这样会导致在此期间内,如果不发生key miss,数据不会更新
|
||||
* 程序员要谨慎对待这一特性,对于重要的i18n,在版本间尽量不要更新原有的key值。
|
||||
*/
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
const nss = i18ns.map(ele => ele.namespace);
|
||||
await this.loadServerData(nss);
|
||||
}
|
||||
else {
|
||||
const now = Date.now();
|
||||
const nss = i18ns.filter(ele => now - ele.$$updateAt$$ > Locales.REFRESH_STALE_INTERVAL).map(ele => ele.namespace);
|
||||
if (nss.length > 0) {
|
||||
await this.loadServerData(nss);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
async loadServerData(nss) {
|
||||
|
|
|
|||
|
|
@ -168,6 +168,7 @@ declare class SingleNode<ED extends EntityDict & BaseEntityDict, T extends keyof
|
|||
addChild(path: string, node: SingleNode<ED, keyof ED, Cxt, FrontCxt, AD> | ListNode<ED, keyof ED, Cxt, FrontCxt, AD>): void;
|
||||
removeChild(path: string): void;
|
||||
getFreshValue(inModi?: boolean): Partial<ED[T]['Schema']> | undefined;
|
||||
private refreshListChildren;
|
||||
create(data: Partial<Omit<ED[T]['CreateSingle']['data'], 'id'>>): void;
|
||||
update(data: ED[T]['Update']['data'], action?: ED[T]['Action']): void;
|
||||
remove(): void;
|
||||
|
|
|
|||
|
|
@ -787,6 +787,7 @@ class ListNode extends Node {
|
|||
}
|
||||
else {
|
||||
// 不刷新也publish一下,触发页面reRender,不然有可能导致页面不进入formData
|
||||
this.sr = {};
|
||||
this.publish();
|
||||
}
|
||||
}
|
||||
|
|
@ -913,12 +914,14 @@ class SingleNode extends Node {
|
|||
}
|
||||
assert(!this.dirty, 'setId时结点是dirty,在setId之前应当处理掉原有的update');
|
||||
this.id = id;
|
||||
this.refreshListChildren();
|
||||
this.publish();
|
||||
}
|
||||
}
|
||||
unsetId() {
|
||||
if (this.id) {
|
||||
this.id = undefined;
|
||||
this.refreshListChildren();
|
||||
this.publish();
|
||||
}
|
||||
}
|
||||
|
|
@ -963,6 +966,15 @@ class SingleNode extends Node {
|
|||
return result[0];
|
||||
}
|
||||
}
|
||||
// 当node的id重置时,其一对多的儿子结点都应当刷新数据(条件已经改变)
|
||||
refreshListChildren() {
|
||||
for (const k in this.children) {
|
||||
const child = this.children[k];
|
||||
if (child instanceof ListNode) {
|
||||
child.refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
create(data) {
|
||||
const id = generateNewId();
|
||||
assert(!this.id && !this.dirty, 'create前要保证singleNode为空');
|
||||
|
|
@ -979,6 +991,7 @@ class SingleNode extends Node {
|
|||
action: 'create',
|
||||
data: Object.assign({}, data, { id }),
|
||||
};
|
||||
this.refreshListChildren();
|
||||
this.setDirty();
|
||||
}
|
||||
update(data, action) {
|
||||
|
|
@ -1294,7 +1307,7 @@ class SingleNode extends Node {
|
|||
*/
|
||||
getParentFilter(childNode, ignoreNewParent) {
|
||||
const value = this.getFreshValue();
|
||||
if (value && value.$$createAt$$ === 1 && ignoreNewParent) {
|
||||
if (!value || (value && value.$$createAt$$ === 1 && ignoreNewParent)) {
|
||||
return;
|
||||
}
|
||||
for (const key in this.children) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import React from 'react';
|
||||
export const keys = ['xs', 'sm', 'md', 'lg', 'xl', 'xxl'];
|
||||
export const values = {
|
||||
xs: 576,
|
||||
xs: 576, //小于576
|
||||
sm: 576,
|
||||
md: 768,
|
||||
lg: 992,
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ export declare abstract class BackendRuntimeContext<ED extends EntityDict & Base
|
|||
getSubscriberId(): string | undefined;
|
||||
getBriefEnvironment(): BriefEnv | undefined;
|
||||
protected getSerializedData(): Promise<SerializedData>;
|
||||
initialize(data?: SerializedData): Promise<void>;
|
||||
initialize(data?: SerializedData, later?: boolean): Promise<void>;
|
||||
/**
|
||||
* 未来可以支持在event中带id的占位符,到saveOpRecord时再动态注入 by Xc
|
||||
* @param operationId
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ class BackendRuntimeContext extends AsyncRowStore_1.AsyncContext {
|
|||
ns: this.ns,
|
||||
};
|
||||
}
|
||||
async initialize(data) {
|
||||
async initialize(data, later) {
|
||||
if (data?.sid) {
|
||||
this.subscriberId = data.sid;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -324,7 +324,7 @@ class Cache extends Feature_1.Feature {
|
|||
opers.forEach((oper) => {
|
||||
const { entity, operation } = oper;
|
||||
this.cacheStore.operate(entity, operation, this.context, {
|
||||
checkerTypes: ['logical'],
|
||||
checkerTypes: ['logical'], // 这里不能检查data,不然在数据没填完前会有大量异常
|
||||
dontCollect: true,
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import { Environment } from './environment';
|
|||
import { SyncContext } from 'oak-domain/lib/store/SyncRowStore';
|
||||
import { Scope, TranslateOptions } from 'i18n-js';
|
||||
export declare class Locales<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED>, FrontCxt extends SyncContext<ED>, AD extends CommonAspectDict<ED, Cxt>> extends Feature {
|
||||
static MINIMAL_LOADING_GAP: number;
|
||||
static REFRESH_STALE_INTERVAL: number;
|
||||
private cache;
|
||||
private localStorage;
|
||||
private environment;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ const assert_1 = require("oak-domain/lib/utils/assert");
|
|||
const i18n_js_1 = require("i18n-js");
|
||||
const constant_1 = require("../constant/constant");
|
||||
class Locales extends Feature_1.Feature {
|
||||
static MINIMAL_LOADING_GAP = 600 * 10000; // 最小加载间歇
|
||||
static REFRESH_STALE_INTERVAL = 30 * 24 * 3600 * 1000; // 正式环境下的主动刷新缓存策略
|
||||
cache;
|
||||
localStorage;
|
||||
environment;
|
||||
|
|
@ -64,6 +64,7 @@ class Locales extends Feature_1.Feature {
|
|||
data: 1,
|
||||
namespace: 1,
|
||||
language: 1,
|
||||
$$updateAt$$: 1,
|
||||
},
|
||||
});
|
||||
const dataset = {};
|
||||
|
|
@ -79,10 +80,23 @@ class Locales extends Feature_1.Feature {
|
|||
});
|
||||
this.i18n.store(dataset);
|
||||
if (i18ns.length > 0) {
|
||||
// 启动时刷新数据策略
|
||||
// 先不处理了,这样似乎会导致如果key不miss就不会更新,所以i18n的更新要确保这点
|
||||
/* const nss = i18ns.map(ele => ele.namespace!);
|
||||
await this.loadServerData(nss); */
|
||||
/**
|
||||
* 前台启动时的数据刷新策略:
|
||||
* dev环境无条件刷新,production环境只会主动刷新超过REFRESH_STALE_INTERVAL(30天)的i18n数据,
|
||||
* 这样会导致在此期间内,如果不发生key miss,数据不会更新
|
||||
* 程序员要谨慎对待这一特性,对于重要的i18n,在版本间尽量不要更新原有的key值。
|
||||
*/
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
const nss = i18ns.map(ele => ele.namespace);
|
||||
await this.loadServerData(nss);
|
||||
}
|
||||
else {
|
||||
const now = Date.now();
|
||||
const nss = i18ns.filter(ele => now - ele.$$updateAt$$ > Locales.REFRESH_STALE_INTERVAL).map(ele => ele.namespace);
|
||||
if (nss.length > 0) {
|
||||
await this.loadServerData(nss);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
async loadServerData(nss) {
|
||||
|
|
|
|||
|
|
@ -168,6 +168,7 @@ declare class SingleNode<ED extends EntityDict & BaseEntityDict, T extends keyof
|
|||
addChild(path: string, node: SingleNode<ED, keyof ED, Cxt, FrontCxt, AD> | ListNode<ED, keyof ED, Cxt, FrontCxt, AD>): void;
|
||||
removeChild(path: string): void;
|
||||
getFreshValue(inModi?: boolean): Partial<ED[T]['Schema']> | undefined;
|
||||
private refreshListChildren;
|
||||
create(data: Partial<Omit<ED[T]['CreateSingle']['data'], 'id'>>): void;
|
||||
update(data: ED[T]['Update']['data'], action?: ED[T]['Action']): void;
|
||||
remove(): void;
|
||||
|
|
|
|||
|
|
@ -790,6 +790,7 @@ class ListNode extends Node {
|
|||
}
|
||||
else {
|
||||
// 不刷新也publish一下,触发页面reRender,不然有可能导致页面不进入formData
|
||||
this.sr = {};
|
||||
this.publish();
|
||||
}
|
||||
}
|
||||
|
|
@ -916,12 +917,14 @@ class SingleNode extends Node {
|
|||
}
|
||||
(0, assert_1.assert)(!this.dirty, 'setId时结点是dirty,在setId之前应当处理掉原有的update');
|
||||
this.id = id;
|
||||
this.refreshListChildren();
|
||||
this.publish();
|
||||
}
|
||||
}
|
||||
unsetId() {
|
||||
if (this.id) {
|
||||
this.id = undefined;
|
||||
this.refreshListChildren();
|
||||
this.publish();
|
||||
}
|
||||
}
|
||||
|
|
@ -966,6 +969,15 @@ class SingleNode extends Node {
|
|||
return result[0];
|
||||
}
|
||||
}
|
||||
// 当node的id重置时,其一对多的儿子结点都应当刷新数据(条件已经改变)
|
||||
refreshListChildren() {
|
||||
for (const k in this.children) {
|
||||
const child = this.children[k];
|
||||
if (child instanceof ListNode) {
|
||||
child.refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
create(data) {
|
||||
const id = (0, uuid_1.generateNewId)();
|
||||
(0, assert_1.assert)(!this.id && !this.dirty, 'create前要保证singleNode为空');
|
||||
|
|
@ -982,6 +994,7 @@ class SingleNode extends Node {
|
|||
action: 'create',
|
||||
data: Object.assign({}, data, { id }),
|
||||
};
|
||||
this.refreshListChildren();
|
||||
this.setDirty();
|
||||
}
|
||||
update(data, action) {
|
||||
|
|
@ -1297,7 +1310,7 @@ class SingleNode extends Node {
|
|||
*/
|
||||
getParentFilter(childNode, ignoreNewParent) {
|
||||
const value = this.getFreshValue();
|
||||
if (value && value.$$createAt$$ === 1 && ignoreNewParent) {
|
||||
if (!value || (value && value.$$createAt$$ === 1 && ignoreNewParent)) {
|
||||
return;
|
||||
}
|
||||
for (const key in this.children) {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ const tslib_1 = require("tslib");
|
|||
const react_1 = tslib_1.__importDefault(require("react"));
|
||||
exports.keys = ['xs', 'sm', 'md', 'lg', 'xl', 'xxl'];
|
||||
exports.values = {
|
||||
xs: 576,
|
||||
xs: 576, //小于576
|
||||
sm: 576,
|
||||
md: 768,
|
||||
lg: 992,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "oak-frontend-base",
|
||||
"version": "4.2.6",
|
||||
"version": "4.2.7",
|
||||
"description": "oak框架中前端与业务逻辑无关的平台部分",
|
||||
"author": {
|
||||
"name": "XuChang"
|
||||
|
|
@ -22,8 +22,8 @@
|
|||
"i18n-js": "^4.3.0",
|
||||
"node-schedule": "^2.1.1",
|
||||
"oak-common-aspect": "^2.2.5",
|
||||
"oak-domain": "^4.2.4",
|
||||
"oak-memory-tree-store": "^3.1.4",
|
||||
"oak-domain": "^4.2.8",
|
||||
"oak-memory-tree-store": "^3.1.5",
|
||||
"ol": "^7.3.0",
|
||||
"react-native-device-info": "^10.12.0",
|
||||
"react-native-localize": "^3.0.4",
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import React from 'react';
|
||||
import { Space, Tooltip, ButtonProps } from 'antd';
|
||||
import {
|
||||
ReloadOutlined
|
||||
ReloadOutlined
|
||||
} from '@ant-design/icons';
|
||||
import ButtonGroup from '../buttonGroup';
|
||||
import ColumnSetting from '../columnSetting';
|
||||
|
|
@ -13,13 +13,13 @@ type buttonProps = {
|
|||
label: string;
|
||||
type?: ButtonProps['type'];
|
||||
onClick: () => void;
|
||||
}
|
||||
}
|
||||
|
||||
type ToolBarProps = {
|
||||
title?: React.ReactNode;
|
||||
buttonGroup?: buttonProps[];
|
||||
extraContent?: React.ReactNode;
|
||||
reload: () => void;
|
||||
reload?: () => void;
|
||||
}
|
||||
|
||||
function ToolBar(props: ToolBarProps) {
|
||||
|
|
@ -35,16 +35,17 @@ function ToolBar(props: ToolBarProps) {
|
|||
{buttonGroup && buttonGroup.length > 0 && (
|
||||
<ButtonGroup items={buttonGroup} />
|
||||
)}
|
||||
<Tooltip title={features.locales.t('reload')}>
|
||||
<div
|
||||
className={Style.reloadIconBox}
|
||||
onClick={() => {
|
||||
reload();
|
||||
}}
|
||||
>
|
||||
<ReloadOutlined />
|
||||
</div>
|
||||
</Tooltip>
|
||||
{reload &&
|
||||
<Tooltip title={features.locales.t('reload')}>
|
||||
<div
|
||||
className={Style.reloadIconBox}
|
||||
onClick={() => {
|
||||
reload!();
|
||||
}}
|
||||
>
|
||||
<ReloadOutlined />
|
||||
</div>
|
||||
</Tooltip>}
|
||||
<ColumnSetting />
|
||||
</Space>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -162,9 +162,7 @@ const ProList = <ED2 extends ED, T extends keyof ED2>(props: Props<ED2, T>) => {
|
|||
title={title}
|
||||
extraContent={extraContent}
|
||||
buttonGroup={buttonGroup}
|
||||
reload={() => {
|
||||
onReload && onReload();
|
||||
}}
|
||||
reload={onReload}
|
||||
/>
|
||||
)}
|
||||
{isMobile && <ButtonGroup items={buttonGroup} />}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ export abstract class BackendRuntimeContext<ED extends EntityDict & BaseEntityDi
|
|||
}
|
||||
}
|
||||
|
||||
async initialize(data?: SerializedData) {
|
||||
async initialize(data?: SerializedData, later?: boolean) {
|
||||
if (data?.sid) {
|
||||
this.subscriberId = data.sid;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import { I18n, Scope, TranslateOptions } from 'i18n-js';
|
|||
import { LOCAL_STORAGE_KEYS } from '../constant/constant';
|
||||
|
||||
export class Locales<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncContext<ED>, FrontCxt extends SyncContext<ED>, AD extends CommonAspectDict<ED, Cxt>> extends Feature {
|
||||
static MINIMAL_LOADING_GAP = 600 * 10000; // 最小加载间歇
|
||||
static REFRESH_STALE_INTERVAL = 30 * 24 * 3600 * 1000; // 正式环境下的主动刷新缓存策略
|
||||
private cache: Cache<ED, Cxt, FrontCxt, AD>;
|
||||
private localStorage: LocalStorage;
|
||||
private environment: Environment;
|
||||
|
|
@ -83,6 +83,7 @@ export class Locales<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncCo
|
|||
data: 1,
|
||||
namespace: 1,
|
||||
language: 1,
|
||||
$$updateAt$$: 1,
|
||||
},
|
||||
});
|
||||
const dataset: Record<string, any> = {};
|
||||
|
|
@ -101,10 +102,25 @@ export class Locales<ED extends EntityDict & BaseEntityDict, Cxt extends AsyncCo
|
|||
this.i18n.store(dataset);
|
||||
|
||||
if (i18ns.length > 0) {
|
||||
// 启动时刷新数据策略
|
||||
// 先不处理了,这样似乎会导致如果key不miss就不会更新,所以i18n的更新要确保这点
|
||||
/* const nss = i18ns.map(ele => ele.namespace!);
|
||||
await this.loadServerData(nss); */
|
||||
/**
|
||||
* 前台启动时的数据刷新策略:
|
||||
* dev环境无条件刷新,production环境只会主动刷新超过REFRESH_STALE_INTERVAL(30天)的i18n数据,
|
||||
* 这样会导致在此期间内,如果不发生key miss,数据不会更新
|
||||
* 程序员要谨慎对待这一特性,对于重要的i18n,在版本间尽量不要更新原有的key值。
|
||||
*/
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
const nss = i18ns.map(ele => ele.namespace!);
|
||||
await this.loadServerData(nss);
|
||||
}
|
||||
else {
|
||||
const now = Date.now();
|
||||
const nss = i18ns.filter(
|
||||
ele => now - (ele.$$updateAt$$ as number) > Locales.REFRESH_STALE_INTERVAL
|
||||
).map(ele => ele.namespace!);
|
||||
if (nss.length > 0) {
|
||||
await this.loadServerData(nss);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -971,6 +971,7 @@ class ListNode<
|
|||
}
|
||||
else {
|
||||
// 不刷新也publish一下,触发页面reRender,不然有可能导致页面不进入formData
|
||||
this.sr = {};
|
||||
this.publish();
|
||||
}
|
||||
}
|
||||
|
|
@ -1130,6 +1131,7 @@ class SingleNode<ED extends EntityDict & BaseEntityDict,
|
|||
}
|
||||
assert(!this.dirty, 'setId时结点是dirty,在setId之前应当处理掉原有的update');
|
||||
this.id = id;
|
||||
this.refreshListChildren();
|
||||
this.publish();
|
||||
}
|
||||
}
|
||||
|
|
@ -1137,6 +1139,7 @@ class SingleNode<ED extends EntityDict & BaseEntityDict,
|
|||
unsetId() {
|
||||
if (this.id) {
|
||||
this.id = undefined;
|
||||
this.refreshListChildren();
|
||||
this.publish();
|
||||
}
|
||||
}
|
||||
|
|
@ -1187,6 +1190,16 @@ class SingleNode<ED extends EntityDict & BaseEntityDict,
|
|||
}
|
||||
}
|
||||
|
||||
// 当node的id重置时,其一对多的儿子结点都应当刷新数据(条件已经改变)
|
||||
private refreshListChildren() {
|
||||
for (const k in this.children) {
|
||||
const child = this.children[k];
|
||||
if (child instanceof ListNode) {
|
||||
child.refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
create(data: Partial<Omit<ED[T]['CreateSingle']['data'], 'id'>>) {
|
||||
const id = generateNewId();
|
||||
assert(!this.id && !this.dirty, 'create前要保证singleNode为空');
|
||||
|
|
@ -1203,6 +1216,7 @@ class SingleNode<ED extends EntityDict & BaseEntityDict,
|
|||
action: 'create',
|
||||
data: Object.assign({}, data, { id }),
|
||||
};
|
||||
this.refreshListChildren();
|
||||
this.setDirty();
|
||||
}
|
||||
|
||||
|
|
@ -1544,7 +1558,7 @@ class SingleNode<ED extends EntityDict & BaseEntityDict,
|
|||
getParentFilter<T2 extends keyof ED>(childNode: ListNode<ED, keyof ED, Cxt, FrontCxt, AD>, ignoreNewParent?: boolean): ED[T2]['Selection']['filter'] | undefined {
|
||||
const value = this.getFreshValue();
|
||||
|
||||
if (value && value.$$createAt$$ === 1 && ignoreNewParent) {
|
||||
if (!value || (value && value.$$createAt$$ === 1 && ignoreNewParent)) {
|
||||
return;
|
||||
}
|
||||
for (const key in this.children) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue