Merge remote-tracking branch 'baidu/master'

This commit is contained in:
2betop 2020-03-06 12:40:08 +08:00
parent 6bc230120e
commit 927ef02ec2
11 changed files with 91 additions and 57 deletions

View File

@ -49,11 +49,11 @@ Api 类型可以是字符串或者对象。API 中可以直接设置数据发送
- `<type>` 可以是: `get`、`post`、`put`、`delete`或者`raw`
- `<url>` 即 api 地址,支持通过 `$key` 取变量。
如:
如:
* `get:http://imis.tieba.baidu.com/yule/list?start=$startTime&end=$endTime`
* `get:http://imis.tieba.baidu.com/yule/list?$$` 拿所有可用数据。
* `get:http://imis.tieba.baidu.com/yule/list?data=$$` 拿所有可用数据。
* `get:http://imis.tieba.baidu.com/yule/list?start=$startTime&end=$endTime`
* `get:http://imis.tieba.baidu.com/yule/list?$$` 拿所有可用数据。
* `get:http://imis.tieba.baidu.com/yule/list?data=$$` 拿所有可用数据。
- `Object`
@ -65,6 +65,7 @@ Api 类型可以是字符串或者对象。API 中可以直接设置数据发送
- `headers` 头部,配置方式和 data 配置一样,下面不详讲。如果要使用,请前往群组系统配置中,添加允许。
- `sendOn` 可以配置发送条件比如: `this.id` 表示当存在 id 值时才发送这个请求。
- `cache` 通过配置此属性开启缓存,单位是 ms比如设置 3000 的话,当前接口在 3s 内请求,只要传参一致就会走缓存。
- `replaceData` boolean; 返回的数据是否替换掉当前的数据,默认为 false追加设置成 true 就是完全替换。
- `requestAdaptor` (api) => api; 发送适配器,支持字符串串格式,或者直接就是函数如:
```

View File

@ -487,8 +487,6 @@ export default class ImageControl extends React.Component<
}
editImage(index: number) {
const {multiple} = this.props;
const files = this.files;
this.setState({

View File

@ -9,6 +9,7 @@ import {FormControlProps, FormItem} from './Item';
import {buildApi, isValidApi, isEffectiveApi} from '../../utils/api';
import {Checkbox, Spinner} from '../../components';
import {autobind, setVariable} from '../../utils/helper';
import {ApiObject} from '../../types';
export interface Column {
label: string;
@ -172,11 +173,9 @@ export default class MatrixCheckbox extends React.Component<
() => {
let value = (ret.data as any).value;
if (value) {
value = mergeValue(
value,
this.state.columns,
this.state.rows
);
value = (source as ApiObject).replaceData
? value
: mergeValue(value, this.state.columns, this.state.rows);
onChange(value);
}
resolve();

View File

@ -3,7 +3,7 @@ import {FormItem, FormControlProps} from './Item';
import cx from 'classnames';
import Button from '../../components/Button';
import {createObject, isObjectShallowModified} from '../../utils/helper';
import {RendererData, Action, Api, Payload} from '../../types';
import {RendererData, Action, Api, Payload, ApiObject} from '../../types';
import {isEffectiveApi} from '../../utils/api';
import {filter} from '../../utils/tpl';
import omit from 'lodash/omit';
@ -255,7 +255,7 @@ export default class FormTable extends React.Component<TableProps, TableState> {
return;
} else if (remote && remote.ok) {
item = {
...item,
...((isNew ? addApi : updateApi) as ApiObject).replaceData ? {} : item,
...remote.data
};
}

View File

@ -3,7 +3,7 @@ import {Renderer, RendererProps} from '../factory';
import {ServiceStore, IServiceStore} from '../store/service';
import cx from 'classnames';
import getExprProperties from '../utils/filter-schema';
import {Api, Payload} from '../types';
import {Api, ApiObject, Payload} from '../types';
import update from 'react-addons-update';
import {isEffectiveApi, isApiOutdated} from '../utils/api';
import {ScopedContext, IScopedContext} from '../Scoped';
@ -213,7 +213,7 @@ export default class Task extends React.Component<TaskProps, TaskState> {
const items = this.state.items.map(item =>
item.key === ret.data.key
? {
...item,
...((api as ApiObject).replaceData ? {} : item),
...ret.data
}
: item

View File

@ -16,7 +16,7 @@ import {
isEmpty,
qsstringify
} from '../utils/helper';
import {Api, Payload, fetchOptions, Action} from '../types';
import {Api, Payload, fetchOptions, Action, ApiObject} from '../types';
import qs from 'qs';
import pick from 'lodash/pick';
import {resolveVariableAndFilter} from '../utils/tpl-builtin';
@ -123,7 +123,7 @@ export const CRUDStore = ServiceStore.named('CRUDStore')
syncResponse2Query?: boolean;
}
) => Promise<any> = flow(function* getInitData(
api: string,
api: Api,
data: object,
options: fetchOptions & {
forceReload?: boolean;
@ -265,7 +265,7 @@ export const CRUDStore = ServiceStore.named('CRUDStore')
}
const data = {
...self.pristine,
...((api as ApiObject).replaceData ? {} : self.pristine),
items: rowsData,
count: count,
total: total,
@ -288,7 +288,7 @@ export const CRUDStore = ServiceStore.named('CRUDStore')
}
self.items.replace(rowsData);
self.reInitData(data);
self.reInitData(data, !!(api && (api as ApiObject).replaceData));
options.syncResponse2Query !== false &&
updateQuery(
pick(rest, Object.keys(self.query)),
@ -350,7 +350,7 @@ export const CRUDStore = ServiceStore.named('CRUDStore')
data?: object,
options?: fetchOptions
) => Promise<any> = flow(function* saveRemote(
api: string,
api: Api,
data: object,
options: fetchOptions = {}
) {
@ -369,9 +369,13 @@ export const CRUDStore = ServiceStore.named('CRUDStore')
self.markSaving(false);
if (!isEmpty(json.data) || json.ok) {
self.updateData(json.data, {
__saved: Date.now()
});
self.updateData(
json.data,
{
__saved: Date.now()
},
!!api && (api as ApiObject).replaceData
);
self.updatedAt = Date.now();
}

View File

@ -2,7 +2,7 @@ import {types, getEnv, flow, getRoot, detach} from 'mobx-state-tree';
import debounce from 'lodash/debounce';
import {ServiceStore} from './service';
import {FormItemStore, IFormItemStore, SFormItemStore} from './formItem';
import {Api, fetchOptions, Payload} from '../types';
import {Api, ApiObject, fetchOptions, Payload} from '../types';
import {ServerError} from '../utils/errors';
import {
getVariable,
@ -12,7 +12,6 @@ import {
createObject,
difference,
guid,
isObject,
isEmpty,
mapObject
} from '../utils/helper';
@ -81,8 +80,8 @@ export const FormStore = ServiceStore.named('FormStore')
}
}))
.actions(self => {
function setValues(values: object, tag?: object) {
self.updateData(values, tag);
function setValues(values: object, tag?: object, replace?: boolean) {
self.updateData(values, tag, replace);
// 同步 options
syncOptions();
@ -198,7 +197,7 @@ export const FormStore = ServiceStore.named('FormStore')
data?: object,
options?: fetchOptions
) => Promise<any> = flow(function* saveRemote(
api: string,
api: Api,
data: object,
options: fetchOptions = {}
) {
@ -227,11 +226,15 @@ export const FormStore = ServiceStore.named('FormStore')
options
);
// 失败也同样 merge,如果有数据的话。
// 失败也同样修改数据,如果有数据的话。
if (!isEmpty(json.data) || json.ok) {
setValues(json.data, {
__saved: Date.now()
});
setValues(
json.data,
{
__saved: Date.now()
},
!!(api && (api as ApiObject).replaceData)
);
self.updatedAt = Date.now();
}

View File

@ -62,17 +62,17 @@ export const iRendererStore = types
self.data = self.pristine;
},
updateData(data: object = {}, tag?: object) {
updateData(data: object = {}, tag?: object, replace?:boolean) {
const prev = self.data;
let newData;
if (tag) {
let proto = createObject((self.data as any).__super || null, tag);
newData = createObject(proto, {
...self.data,
...(replace ? {} : self.data),
...data
});
} else {
newData = extendObject(self.data, data);
newData = extendObject(self.data, data, !replace);
}
Object.defineProperty(newData, '__prev', {

View File

@ -46,8 +46,8 @@ export const ServiceStore = iRendererStore
self.busying = busying;
}
function reInitData(data: object | undefined) {
const newData = extendObject(self.pristine, data);
function reInitData(data: object | undefined, replace: boolean = false) {
const newData = extendObject(self.pristine, data, !replace);
self.data = self.pristine = newData;
}
@ -65,7 +65,7 @@ export const ServiceStore = iRendererStore
data?: object,
options?: fetchOptions
) => Promise<any> = flow(function* getInitData(
api: string,
api: Api,
data: object,
options?: fetchOptions
) {
@ -104,10 +104,12 @@ export const ServiceStore = iRendererStore
: undefined
);
} else {
reInitData({
...self.data,
let replace = !!(api as ApiObject).replaceData;
let data = {
...(replace ? {} : self.data),
...json.data
});
};
reInitData(data, replace);
self.updatedAt = Date.now();
self.hasRemoteData = true;
if (options && options.onSuccess) {
@ -150,7 +152,7 @@ export const ServiceStore = iRendererStore
data?: object,
options?: fetchOptions
) => Promise<any> = flow(function* getInitData(
api: string,
api: Api,
data: object,
options?: fetchOptions
) {
@ -175,7 +177,12 @@ export const ServiceStore = iRendererStore
fetchCancel = null;
if (!isEmpty(json.data) || json.ok) {
json.data && self.updateData(json.data);
json.data &&
self.updateData(
json.data,
undefined,
!!(api as ApiObject).replaceData
);
self.updatedAt = Date.now();
self.hasRemoteData = true;
}
@ -233,7 +240,7 @@ export const ServiceStore = iRendererStore
data?: object,
options?: fetchOptions
) => Promise<any> = flow(function* saveRemote(
api: string,
api: Api,
data: object,
options: fetchOptions = {}
) {
@ -255,7 +262,12 @@ export const ServiceStore = iRendererStore
);
if (!isEmpty(json.data) || json.ok) {
json.data && self.updateData(json.data);
json.data &&
self.updateData(
json.data,
undefined,
!!(api as ApiObject).replaceData
);
self.updatedAt = Date.now();
}
@ -309,7 +321,7 @@ export const ServiceStore = iRendererStore
data?: object,
options?: fetchOptions
) => Promise<any> = flow(function* fetchSchema(
api: string,
api: Api,
data: object,
options: fetchOptions = {}
) {
@ -370,7 +382,12 @@ export const ServiceStore = iRendererStore
if (json.data) {
self.schema = json.data;
self.schemaKey = '' + Date.now();
isObject(json.data.data) && self.updateData(json.data.data);
isObject(json.data.data) &&
self.updateData(
json.data.data,
undefined,
!!(api as ApiObject).replaceData
);
}
updateMessage(json.msg || (options && options.successMessage));
@ -404,7 +421,7 @@ export const ServiceStore = iRendererStore
data?: object,
options?: fetchOptions
) => Promise<any> = flow(function* checkRemote(
api: string,
api: Api,
data: object,
options?: fetchOptions
) {
@ -419,7 +436,12 @@ export const ServiceStore = iRendererStore
data,
options
);
json.ok && self.updateData(json.data);
json.ok &&
self.updateData(
json.data,
undefined,
!!(api as ApiObject).replaceData
);
if (!json.ok) {
throw new Error(json.msg);

View File

@ -14,6 +14,7 @@ export interface ApiObject {
cache?: number;
qsOptions?: any;
dataType?: 'json' | 'form-data' | 'form';
replaceData?: boolean;
}
export type ApiString = string;
export type Api = ApiString | ApiObject;

View File

@ -38,24 +38,30 @@ export function createObject(
return obj;
}
export function cloneObject(from: any) {
export function cloneObject(target: any, persistOwnProps: boolean = true) {
const obj =
from && from.__super
? Object.create(from.__super, {
target && target.__super
? Object.create(target.__super, {
__super: {
value: from.__super,
value: target.__super,
writable: false,
enumerable: false
}
})
: Object.create(Object.prototype);
from && Object.keys(from).forEach(key => (obj[key] = from[key]));
persistOwnProps &&
target &&
Object.keys(target).forEach(key => (obj[key] = target[key]));
return obj;
}
export function extendObject(to: any, from?: any) {
const obj = cloneObject(to);
from && Object.keys(from).forEach(key => (obj[key] = from[key]));
export function extendObject(
target: any,
src?: any,
persistOwnProps: boolean = true
) {
const obj = cloneObject(target, persistOwnProps);
src && Object.keys(src).forEach(key => (obj[key] = src[key]));
return obj;
}