From 776c4730543f521995c824fff3922f17cd78327e Mon Sep 17 00:00:00 2001 From: catchonme Date: Tue, 14 Jan 2020 19:11:01 +0800 Subject: [PATCH 01/42] =?UTF-8?q?api=E5=A2=9E=E5=8A=A0replaceData?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/renderers/Form/Table.tsx | 6 +++--- src/renderers/Tasks.tsx | 6 ++++-- src/store/crud.ts | 15 ++++++++------- src/store/form.ts | 10 +++++----- src/store/iRenderer.ts | 8 ++++---- src/store/service.ts | 30 ++++++++++++++++-------------- src/types.ts | 1 + 7 files changed, 41 insertions(+), 35 deletions(-) diff --git a/src/renderers/Form/Table.tsx b/src/renderers/Form/Table.tsx index e132a1629..9c1a84e1d 100644 --- a/src/renderers/Form/Table.tsx +++ b/src/renderers/Form/Table.tsx @@ -2,8 +2,8 @@ import React from "react"; 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 {createObject, isObject, isObjectShallowModified} from '../../utils/helper'; +import {RendererData, Action, Api, Payload, ApiObject} from '../../types'; import { isEffectiveApi } from "../../utils/api"; import { filter } from "../../utils/tpl"; import omit = require("lodash/omit"); @@ -253,7 +253,7 @@ export default class FormTable extends React.Component { return; } else if (remote && remote.ok) { item = { - ...item, + ...(isObject(updateApi) && (updateApi as ApiObject).replaceData ? {} : item), ...remote.data }; } diff --git a/src/renderers/Tasks.tsx b/src/renderers/Tasks.tsx index 9fa48918b..62638566a 100644 --- a/src/renderers/Tasks.tsx +++ b/src/renderers/Tasks.tsx @@ -3,10 +3,11 @@ 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 = require('react-addons-update'); import {isEffectiveApi, isApiOutdated} from '../utils/api'; import {ScopedContext, IScopedContext} from '../Scoped'; +import {isObject} from '../utils/helper'; export interface TaskProps extends RendererProps { className?: string; @@ -210,8 +211,9 @@ export default class Task extends React.Component { if (Array.isArray(ret.data)) { this.handleLoaded(ret); } else { + let replace = isObject(api) && (api as ApiObject).replaceData; const items = this.state.items.map(item => - item.key === ret.data.key + (item.key === ret.data.key && !replace) ? { ...item, ...ret.data diff --git a/src/store/crud.ts b/src/store/crud.ts index 39f6f560a..0d94cbfe8 100644 --- a/src/store/crud.ts +++ b/src/store/crud.ts @@ -7,9 +7,10 @@ import { isObjectShallowModified, sortArray, isEmpty, - qsstringify + qsstringify, + isObject } from '../utils/helper'; -import {Api, Payload, fetchOptions, Action} from '../types'; +import {Api, Payload, fetchOptions, Action, ApiObject} from '../types'; import qs from 'qs'; import pick = require('lodash/pick'); import {resolveVariableAndFilter} from '../utils/tpl-builtin'; @@ -116,7 +117,7 @@ export const CRUDStore = ServiceStore.named('CRUDStore') syncResponse2Query?: boolean; } ) => Promise = flow(function* getInitData( - api: string, + api: Api, data: object, options: fetchOptions & { forceReload?: boolean; @@ -263,7 +264,7 @@ export const CRUDStore = ServiceStore.named('CRUDStore') } const data = { - ...self.pristine, + ...(isObject(api) && (api as ApiObject).replaceData ? {} : self.pristine), items: rowsData, count: count, total: total, @@ -286,7 +287,7 @@ export const CRUDStore = ServiceStore.named('CRUDStore') } self.items.replace(rowsData); - self.reInitData(data); + self.reInitData(data, isObject(api) && (api as ApiObject).replaceData); options.syncResponse2Query !== false && updateQuery( pick(rest, Object.keys(self.query)), @@ -348,7 +349,7 @@ export const CRUDStore = ServiceStore.named('CRUDStore') data?: object, options?: fetchOptions ) => Promise = flow(function* saveRemote( - api: string, + api: Api, data: object, options: fetchOptions = {} ) { @@ -369,7 +370,7 @@ export const CRUDStore = ServiceStore.named('CRUDStore') if (!isEmpty(json.data) || json.ok) { self.updateData(json.data, { __saved: Date.now() - }); + }, isObject(api) && (api as ApiObject).replaceData); self.updatedAt = Date.now(); } diff --git a/src/store/form.ts b/src/store/form.ts index d29f7a933..308560af5 100644 --- a/src/store/form.ts +++ b/src/store/form.ts @@ -2,7 +2,7 @@ import {types, getEnv, flow, getRoot, detach} from 'mobx-state-tree'; import debounce = require('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, @@ -81,8 +81,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 +198,7 @@ export const FormStore = ServiceStore.named('FormStore') data?: object, options?: fetchOptions ) => Promise = flow(function* saveRemote( - api: string, + api: Api, data: object, options: fetchOptions = {} ) { @@ -231,7 +231,7 @@ export const FormStore = ServiceStore.named('FormStore') if (!isEmpty(json.data) || json.ok) { setValues(json.data, { __saved: Date.now() - }); + }, isObject(api) && (api as ApiObject).replaceData); self.updatedAt = Date.now(); } diff --git a/src/store/iRenderer.ts b/src/store/iRenderer.ts index b420f42f3..9b72b992c 100644 --- a/src/store/iRenderer.ts +++ b/src/store/iRenderer.ts @@ -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); + let proto = createObject(!replace && (self.data as any).__super || null, tag); newData = createObject(proto, { - ...self.data, + ...(replace ? {} : self.data), ...data }); } else { - newData = extendObject(self.data, data); + newData = replace ? data : extendObject(self.data, data); } Object.defineProperty(newData, '__prev', { diff --git a/src/store/service.ts b/src/store/service.ts index 4631438a3..418ffb134 100644 --- a/src/store/service.ts +++ b/src/store/service.ts @@ -39,8 +39,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 = replace ? data : extendObject(self.pristine, data); self.data = self.pristine = newData; } @@ -58,7 +58,7 @@ export const ServiceStore = iRendererStore data?: object, options?: fetchOptions ) => Promise = flow(function* getInitData( - api: string, + api: Api, data: object, options?: fetchOptions ) { @@ -97,10 +97,12 @@ export const ServiceStore = iRendererStore : undefined ); } else { - reInitData({ - ...self.data, + let replaceData = isObject(api) && (api as ApiObject).replaceData; + let data = { + ...(replaceData ? {} : self.data), ...json.data - }); + }; + reInitData(data, replaceData); self.updatedAt = Date.now(); self.hasRemoteData = true; if (options && options.onSuccess) { @@ -143,7 +145,7 @@ export const ServiceStore = iRendererStore data?: object, options?: fetchOptions ) => Promise = flow(function* getInitData( - api: string, + api: Api, data: object, options?: fetchOptions ) { @@ -168,7 +170,7 @@ 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, isObject(api) && (api as ApiObject).replaceData); self.updatedAt = Date.now(); self.hasRemoteData = true; } @@ -226,7 +228,7 @@ export const ServiceStore = iRendererStore data?: object, options?: fetchOptions ) => Promise = flow(function* saveRemote( - api: string, + api: Api, data: object, options: fetchOptions = {} ) { @@ -248,7 +250,7 @@ export const ServiceStore = iRendererStore ); if (!isEmpty(json.data) || json.ok) { - json.data && self.updateData(json.data); + json.data && self.updateData(json.data, undefined, isObject(api) && (api as ApiObject).replaceData); self.updatedAt = Date.now(); } @@ -302,7 +304,7 @@ export const ServiceStore = iRendererStore data?: object, options?: fetchOptions ) => Promise = flow(function* fetchSchema( - api: string, + api: Api, data: object, options: fetchOptions = {} ) { @@ -363,7 +365,7 @@ 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, isObject(api) && (api as ApiObject).replaceData); } updateMessage(json.msg || (options && options.successMessage)); @@ -397,7 +399,7 @@ export const ServiceStore = iRendererStore data?: object, options?: fetchOptions ) => Promise = flow(function* checkRemote( - api: string, + api: Api, data: object, options?: fetchOptions ) { @@ -412,7 +414,7 @@ export const ServiceStore = iRendererStore data, options ); - json.ok && self.updateData(json.data); + json.ok && self.updateData(json.data, undefined, isObject(api) && (api as ApiObject).replaceData); if (!json.ok) { throw new Error(json.msg); diff --git a/src/types.ts b/src/types.ts index 500965bf5..9a4b81bfc 100644 --- a/src/types.ts +++ b/src/types.ts @@ -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; From dcd345fa3c215c6bd18f9ca16db678503933cf5c Mon Sep 17 00:00:00 2001 From: catchonme Date: Tue, 14 Jan 2020 20:30:36 +0800 Subject: [PATCH 02/42] =?UTF-8?q?replaceData=E6=97=B6=E6=8B=BF=E5=88=B0?= =?UTF-8?q?=E7=88=B6=E7=BA=A7value?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/renderers/Types.md | 1 + src/renderers/Form/Table.tsx | 2 +- src/renderers/Tasks.tsx | 2 +- src/store/crud.ts | 6 +++--- src/store/form.ts | 2 +- src/store/iRenderer.ts | 4 ++-- src/store/service.ts | 16 ++++++++-------- src/utils/helper.ts | 8 ++++---- 8 files changed, 21 insertions(+), 20 deletions(-) diff --git a/docs/renderers/Types.md b/docs/renderers/Types.md index 0f0f57f65..743f69af0 100644 --- a/docs/renderers/Types.md +++ b/docs/renderers/Types.md @@ -65,6 +65,7 @@ Api 类型可以是字符串或者对象。API 中可以直接设置数据发送 - `headers` 头部,配置方式和 data 配置一样,下面不详讲。如果要使用,请前往群组系统配置中,添加允许。 - `sendOn` 可以配置发送条件比如: `this.id` 表示当存在 id 值时才发送这个请求。 - `cache` 通过配置此属性开启缓存,单位是 ms,比如设置 3000 的话,当前接口在3s内请求,只要传参一致就会走缓存。 + - `replaceData` boolean; 返回的数据是否替换掉当前的数据,默认为 false - `requestAdaptor` (api) => api; 发送适配器,支持字符串串格式,或者直接就是函数如: ``` diff --git a/src/renderers/Form/Table.tsx b/src/renderers/Form/Table.tsx index 9c1a84e1d..6a2f97bf4 100644 --- a/src/renderers/Form/Table.tsx +++ b/src/renderers/Form/Table.tsx @@ -253,7 +253,7 @@ export default class FormTable extends React.Component { return; } else if (remote && remote.ok) { item = { - ...(isObject(updateApi) && (updateApi as ApiObject).replaceData ? {} : item), + ...(updateApi && (updateApi as ApiObject).replaceData ? {} : item), ...remote.data }; } diff --git a/src/renderers/Tasks.tsx b/src/renderers/Tasks.tsx index 62638566a..d4a25a1cf 100644 --- a/src/renderers/Tasks.tsx +++ b/src/renderers/Tasks.tsx @@ -211,7 +211,7 @@ export default class Task extends React.Component { if (Array.isArray(ret.data)) { this.handleLoaded(ret); } else { - let replace = isObject(api) && (api as ApiObject).replaceData; + let replace = api && (api as ApiObject).replaceData; const items = this.state.items.map(item => (item.key === ret.data.key && !replace) ? { diff --git a/src/store/crud.ts b/src/store/crud.ts index 0d94cbfe8..b4e183dda 100644 --- a/src/store/crud.ts +++ b/src/store/crud.ts @@ -264,7 +264,7 @@ export const CRUDStore = ServiceStore.named('CRUDStore') } const data = { - ...(isObject(api) && (api as ApiObject).replaceData ? {} : self.pristine), + ...(api && (api as ApiObject).replaceData ? {} : self.pristine), items: rowsData, count: count, total: total, @@ -287,7 +287,7 @@ export const CRUDStore = ServiceStore.named('CRUDStore') } self.items.replace(rowsData); - self.reInitData(data, isObject(api) && (api as ApiObject).replaceData); + self.reInitData(data, !!api && (api as ApiObject).replaceData); options.syncResponse2Query !== false && updateQuery( pick(rest, Object.keys(self.query)), @@ -370,7 +370,7 @@ export const CRUDStore = ServiceStore.named('CRUDStore') if (!isEmpty(json.data) || json.ok) { self.updateData(json.data, { __saved: Date.now() - }, isObject(api) && (api as ApiObject).replaceData); + }, !!api && (api as ApiObject).replaceData); self.updatedAt = Date.now(); } diff --git a/src/store/form.ts b/src/store/form.ts index 308560af5..b11683674 100644 --- a/src/store/form.ts +++ b/src/store/form.ts @@ -231,7 +231,7 @@ export const FormStore = ServiceStore.named('FormStore') if (!isEmpty(json.data) || json.ok) { setValues(json.data, { __saved: Date.now() - }, isObject(api) && (api as ApiObject).replaceData); + }, !!api && (api as ApiObject).replaceData); self.updatedAt = Date.now(); } diff --git a/src/store/iRenderer.ts b/src/store/iRenderer.ts index 9b72b992c..b0796de69 100644 --- a/src/store/iRenderer.ts +++ b/src/store/iRenderer.ts @@ -66,13 +66,13 @@ export const iRendererStore = types const prev = self.data; let newData; if (tag) { - let proto = createObject(!replace && (self.data as any).__super || null, tag); + let proto = createObject((self.data as any).__super || null, tag); newData = createObject(proto, { ...(replace ? {} : self.data), ...data }); } else { - newData = replace ? data : extendObject(self.data, data); + newData = extendObject(self.data, data, !replace); } Object.defineProperty(newData, '__prev', { diff --git a/src/store/service.ts b/src/store/service.ts index 418ffb134..d20cafe46 100644 --- a/src/store/service.ts +++ b/src/store/service.ts @@ -40,7 +40,7 @@ export const ServiceStore = iRendererStore } function reInitData(data: object | undefined, replace: boolean = false) { - const newData = replace ? data : extendObject(self.pristine, data); + const newData = extendObject(self.pristine, data, !replace); self.data = self.pristine = newData; } @@ -97,12 +97,12 @@ export const ServiceStore = iRendererStore : undefined ); } else { - let replaceData = isObject(api) && (api as ApiObject).replaceData; + let replace = !!api && (api as ApiObject).replaceData; let data = { - ...(replaceData ? {} : self.data), + ...(replace ? {} : self.data), ...json.data }; - reInitData(data, replaceData); + reInitData(data, replace); self.updatedAt = Date.now(); self.hasRemoteData = true; if (options && options.onSuccess) { @@ -170,7 +170,7 @@ export const ServiceStore = iRendererStore fetchCancel = null; if (!isEmpty(json.data) || json.ok) { - json.data && self.updateData(json.data, undefined, isObject(api) && (api as ApiObject).replaceData); + json.data && self.updateData(json.data, undefined, !!api && (api as ApiObject).replaceData); self.updatedAt = Date.now(); self.hasRemoteData = true; } @@ -250,7 +250,7 @@ export const ServiceStore = iRendererStore ); if (!isEmpty(json.data) || json.ok) { - json.data && self.updateData(json.data, undefined, isObject(api) && (api as ApiObject).replaceData); + json.data && self.updateData(json.data, undefined, !!api && (api as ApiObject).replaceData); self.updatedAt = Date.now(); } @@ -365,7 +365,7 @@ export const ServiceStore = iRendererStore if (json.data) { self.schema = json.data; self.schemaKey = '' + Date.now(); - isObject(json.data.data) && self.updateData(json.data.data, undefined, isObject(api) && (api as ApiObject).replaceData); + isObject(json.data.data) && self.updateData(json.data.data, undefined, !!api && (api as ApiObject).replaceData); } updateMessage(json.msg || (options && options.successMessage)); @@ -414,7 +414,7 @@ export const ServiceStore = iRendererStore data, options ); - json.ok && self.updateData(json.data, undefined, isObject(api) && (api as ApiObject).replaceData); + json.ok && self.updateData(json.data, undefined, !!api && (api as ApiObject).replaceData); if (!json.ok) { throw new Error(json.msg); diff --git a/src/utils/helper.ts b/src/utils/helper.ts index c4d719fae..50da317c1 100644 --- a/src/utils/helper.ts +++ b/src/utils/helper.ts @@ -38,7 +38,7 @@ export function createObject( return obj; } -export function cloneObject(from: any) { +export function cloneObject(from: any, cloneOwnValue: boolean = true) { const obj = from && from.__super ? Object.create(from.__super, { @@ -49,12 +49,12 @@ export function cloneObject(from: any) { } }) : Object.create(Object.prototype); - from && Object.keys(from).forEach(key => (obj[key] = from[key])); + cloneOwnValue && from && Object.keys(from).forEach(key => (obj[key] = from[key])); return obj; } -export function extendObject(to: any, from?: any) { - const obj = cloneObject(to); +export function extendObject(to: any, from?: any, cloneTosValue?: boolean) { + const obj = cloneObject(to, cloneTosValue); from && Object.keys(from).forEach(key => (obj[key] = from[key])); return obj; } From 4cda10d2411dd3b392fd91e76fb5613c54071f4b Mon Sep 17 00:00:00 2001 From: catchonme Date: Tue, 14 Jan 2020 20:35:56 +0800 Subject: [PATCH 03/42] =?UTF-8?q?=E5=8E=BB=E9=99=A4=E6=97=A0=E6=95=88?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/renderers/Form/Table.tsx | 2 +- src/renderers/Tasks.tsx | 1 - src/store/crud.ts | 3 +-- src/store/form.ts | 1 - 4 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/renderers/Form/Table.tsx b/src/renderers/Form/Table.tsx index 6a2f97bf4..03f4d09ac 100644 --- a/src/renderers/Form/Table.tsx +++ b/src/renderers/Form/Table.tsx @@ -2,7 +2,7 @@ import React from "react"; import { FormItem, FormControlProps } from "./Item"; import cx from "classnames"; import Button from "../../components/Button"; -import {createObject, isObject, isObjectShallowModified} from '../../utils/helper'; +import {createObject, isObjectShallowModified} from '../../utils/helper'; import {RendererData, Action, Api, Payload, ApiObject} from '../../types'; import { isEffectiveApi } from "../../utils/api"; import { filter } from "../../utils/tpl"; diff --git a/src/renderers/Tasks.tsx b/src/renderers/Tasks.tsx index d4a25a1cf..720d3db01 100644 --- a/src/renderers/Tasks.tsx +++ b/src/renderers/Tasks.tsx @@ -7,7 +7,6 @@ import {Api, ApiObject, Payload} from '../types'; import update = require('react-addons-update'); import {isEffectiveApi, isApiOutdated} from '../utils/api'; import {ScopedContext, IScopedContext} from '../Scoped'; -import {isObject} from '../utils/helper'; export interface TaskProps extends RendererProps { className?: string; diff --git a/src/store/crud.ts b/src/store/crud.ts index b4e183dda..8c065b461 100644 --- a/src/store/crud.ts +++ b/src/store/crud.ts @@ -7,8 +7,7 @@ import { isObjectShallowModified, sortArray, isEmpty, - qsstringify, - isObject + qsstringify } from '../utils/helper'; import {Api, Payload, fetchOptions, Action, ApiObject} from '../types'; import qs from 'qs'; diff --git a/src/store/form.ts b/src/store/form.ts index b11683674..bfb479394 100644 --- a/src/store/form.ts +++ b/src/store/form.ts @@ -12,7 +12,6 @@ import { createObject, difference, guid, - isObject, isEmpty, mapObject } from '../utils/helper'; From 24177ecdb77ddc2f25f7abcc1d115471bca3de06 Mon Sep 17 00:00:00 2001 From: catchonme Date: Wed, 15 Jan 2020 10:15:22 +0800 Subject: [PATCH 04/42] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=91=BD=E5=90=8D?= =?UTF-8?q?=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/helper.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/utils/helper.ts b/src/utils/helper.ts index 50da317c1..f1f14c0a5 100644 --- a/src/utils/helper.ts +++ b/src/utils/helper.ts @@ -38,24 +38,24 @@ export function createObject( return obj; } -export function cloneObject(from: any, cloneOwnValue: boolean = true) { +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); - cloneOwnValue && 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, cloneTosValue?: boolean) { - const obj = cloneObject(to, cloneTosValue); - from && Object.keys(from).forEach(key => (obj[key] = from[key])); +export function extendObject(target: any, src?: any, persistOwnProps?: boolean) { + const obj = cloneObject(target, persistOwnProps); + src && Object.keys(src).forEach(key => (obj[key] = src[key])); return obj; } From eeb52e0dfcaa90f7648750644fc859ceeaeffdae Mon Sep 17 00:00:00 2001 From: catchonme Date: Wed, 15 Jan 2020 10:20:56 +0800 Subject: [PATCH 05/42] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=8F=8F=E8=BF=B0?= =?UTF-8?q?=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/renderers/Types.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/renderers/Types.md b/docs/renderers/Types.md index 743f69af0..46d1f444a 100644 --- a/docs/renderers/Types.md +++ b/docs/renderers/Types.md @@ -65,7 +65,7 @@ Api 类型可以是字符串或者对象。API 中可以直接设置数据发送 - `headers` 头部,配置方式和 data 配置一样,下面不详讲。如果要使用,请前往群组系统配置中,添加允许。 - `sendOn` 可以配置发送条件比如: `this.id` 表示当存在 id 值时才发送这个请求。 - `cache` 通过配置此属性开启缓存,单位是 ms,比如设置 3000 的话,当前接口在3s内请求,只要传参一致就会走缓存。 - - `replaceData` boolean; 返回的数据是否替换掉当前的数据,默认为 false + - `replaceData` boolean; 返回的数据是否替换掉当前的数据,默认为 false,即:追加。 - `requestAdaptor` (api) => api; 发送适配器,支持字符串串格式,或者直接就是函数如: ``` From 6d3fc4f661a656483ec27f694418d9190ce198d5 Mon Sep 17 00:00:00 2001 From: catchonme Date: Wed, 15 Jan 2020 10:41:14 +0800 Subject: [PATCH 06/42] =?UTF-8?q?=E4=BF=AE=E6=AD=A3tasks=E4=B8=ADreplaceDa?= =?UTF-8?q?ta=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/renderers/Form/Table.tsx | 18 +++++++++--------- src/renderers/Tasks.tsx | 14 +++++++++----- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/src/renderers/Form/Table.tsx b/src/renderers/Form/Table.tsx index aa2745af1..db20028ab 100644 --- a/src/renderers/Form/Table.tsx +++ b/src/renderers/Form/Table.tsx @@ -1,14 +1,14 @@ -import React from "react"; -import {FormItem, FormControlProps} from "./Item"; -import cx from "classnames"; -import Button from "../../components/Button"; +import React from 'react'; +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, ApiObject} from '../../types'; -import {isEffectiveApi} from "../../utils/api"; -import {filter} from "../../utils/tpl"; -import omit = require("lodash/omit"); -import {dataMapping} from "../../utils/tpl-builtin"; -import findIndex = require("lodash/findIndex"); +import {isEffectiveApi} from '../../utils/api'; +import {filter} from '../../utils/tpl'; +import omit = require('lodash/omit'); +import {dataMapping} from '../../utils/tpl-builtin'; +import findIndex = require('lodash/findIndex'); import memoize = require('lodash/memoize'); export interface TableProps extends FormControlProps { diff --git a/src/renderers/Tasks.tsx b/src/renderers/Tasks.tsx index 720d3db01..5b0eb377f 100644 --- a/src/renderers/Tasks.tsx +++ b/src/renderers/Tasks.tsx @@ -212,11 +212,15 @@ export default class Task extends React.Component { } else { let replace = api && (api as ApiObject).replaceData; const items = this.state.items.map(item => - (item.key === ret.data.key && !replace) - ? { - ...item, - ...ret.data - } + item.key === ret.data.key + ? ( + !replace + ? { + ...item, + ...ret.data + } + : {...ret.data} + ) : item ); this.handleLoaded({ From 02f349629ee9176f4722ebbb80b0601f3e65165f Mon Sep 17 00:00:00 2001 From: catchonme Date: Wed, 15 Jan 2020 11:56:18 +0800 Subject: [PATCH 07/42] =?UTF-8?q?=E5=A2=9E=E5=8A=A0replaceData=E4=BD=BF?= =?UTF-8?q?=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/renderers/Form/Matrix.tsx | 14 +++++++++----- src/renderers/Form/Select.tsx | 5 +++-- src/renderers/Form/TreeSelect.tsx | 5 +++-- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/renderers/Form/Matrix.tsx b/src/renderers/Form/Matrix.tsx index 7a6db5090..45853de7a 100644 --- a/src/renderers/Form/Matrix.tsx +++ b/src/renderers/Form/Matrix.tsx @@ -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; @@ -170,13 +171,16 @@ export default class MatrixCheckbox extends React.Component< columns: (ret.data as any).columns || [] }, () => { + let replace = source && (source as ApiObject).replaceData; let value = (ret.data as any).value; if (value) { - value = mergeValue( - value, - this.state.columns, - this.state.rows - ); + value = replace + ? value + : mergeValue( + value, + this.state.columns, + this.state.rows + ); onChange(value); } resolve(); diff --git a/src/renderers/Form/Select.tsx b/src/renderers/Form/Select.tsx index c798d85d5..c86336ece 100644 --- a/src/renderers/Form/Select.tsx +++ b/src/renderers/Form/Select.tsx @@ -4,7 +4,7 @@ import {OptionsControl, OptionsControlProps, Option} from './Options'; import Select from '../../components/Select'; import find = require('lodash/find'); import debouce = require('lodash/debounce'); -import {Api} from '../../types'; +import {Api, ApiObject} from '../../types'; import {isEffectiveApi} from '../../utils/api'; import {isEmpty, createObject} from '../../utils/helper'; import {dataMapping} from '../../utils/tpl-builtin'; @@ -147,7 +147,8 @@ export default class SelectControl extends React.Component { .fetcher(autoComplete, ctx) .then(ret => { let options = (ret.data && (ret.data as any).options) || ret.data || []; - let combinedOptions = this.mergeOptions(options); + let replace = autoComplete && (autoComplete as ApiObject).replaceData; + let combinedOptions = replace ? options : this.mergeOptions(options); setOptions(combinedOptions); return { diff --git a/src/renderers/Form/TreeSelect.tsx b/src/renderers/Form/TreeSelect.tsx index c51b9645e..0b0bb6e28 100644 --- a/src/renderers/Form/TreeSelect.tsx +++ b/src/renderers/Form/TreeSelect.tsx @@ -10,7 +10,7 @@ import TreeSelector from '../../components/Tree'; import matchSorter from 'match-sorter'; import debouce = require('lodash/debounce'); import find = require('lodash/find'); -import {Api} from '../../types'; +import {Api, ApiObject} from '../../types'; import {isEffectiveApi} from '../../utils/api'; export interface TreeSelectProps extends OptionsControlProps { @@ -278,7 +278,8 @@ export default class TreeSelectControl extends React.Component< .then(ret => { let options = (ret.data && (ret.data as any).options) || ret.data || []; this.cache[input] = options; - let combinedOptions = this.mergeOptions(options); + let replace = autoComplete && (autoComplete as ApiObject).replaceData; + let combinedOptions = replace ? options : this.mergeOptions(options); setOptions(combinedOptions); return Promise.resolve({ From 2bcdb91ef0404aa34b8497f91288dc9eaa87a434 Mon Sep 17 00:00:00 2001 From: catchonme Date: Wed, 15 Jan 2020 12:48:16 +0800 Subject: [PATCH 08/42] =?UTF-8?q?=E4=BF=AE=E6=94=B9tasks=E4=B8=ADreplaceDa?= =?UTF-8?q?ta?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/renderers/Form/Select.tsx | 5 ++--- src/renderers/Form/TreeSelect.tsx | 5 ++--- src/renderers/Tasks.tsx | 12 ++++-------- 3 files changed, 8 insertions(+), 14 deletions(-) diff --git a/src/renderers/Form/Select.tsx b/src/renderers/Form/Select.tsx index c86336ece..c798d85d5 100644 --- a/src/renderers/Form/Select.tsx +++ b/src/renderers/Form/Select.tsx @@ -4,7 +4,7 @@ import {OptionsControl, OptionsControlProps, Option} from './Options'; import Select from '../../components/Select'; import find = require('lodash/find'); import debouce = require('lodash/debounce'); -import {Api, ApiObject} from '../../types'; +import {Api} from '../../types'; import {isEffectiveApi} from '../../utils/api'; import {isEmpty, createObject} from '../../utils/helper'; import {dataMapping} from '../../utils/tpl-builtin'; @@ -147,8 +147,7 @@ export default class SelectControl extends React.Component { .fetcher(autoComplete, ctx) .then(ret => { let options = (ret.data && (ret.data as any).options) || ret.data || []; - let replace = autoComplete && (autoComplete as ApiObject).replaceData; - let combinedOptions = replace ? options : this.mergeOptions(options); + let combinedOptions = this.mergeOptions(options); setOptions(combinedOptions); return { diff --git a/src/renderers/Form/TreeSelect.tsx b/src/renderers/Form/TreeSelect.tsx index 0b0bb6e28..c51b9645e 100644 --- a/src/renderers/Form/TreeSelect.tsx +++ b/src/renderers/Form/TreeSelect.tsx @@ -10,7 +10,7 @@ import TreeSelector from '../../components/Tree'; import matchSorter from 'match-sorter'; import debouce = require('lodash/debounce'); import find = require('lodash/find'); -import {Api, ApiObject} from '../../types'; +import {Api} from '../../types'; import {isEffectiveApi} from '../../utils/api'; export interface TreeSelectProps extends OptionsControlProps { @@ -278,8 +278,7 @@ export default class TreeSelectControl extends React.Component< .then(ret => { let options = (ret.data && (ret.data as any).options) || ret.data || []; this.cache[input] = options; - let replace = autoComplete && (autoComplete as ApiObject).replaceData; - let combinedOptions = replace ? options : this.mergeOptions(options); + let combinedOptions = this.mergeOptions(options); setOptions(combinedOptions); return Promise.resolve({ diff --git a/src/renderers/Tasks.tsx b/src/renderers/Tasks.tsx index 5b0eb377f..f2a1b4b8c 100644 --- a/src/renderers/Tasks.tsx +++ b/src/renderers/Tasks.tsx @@ -213,14 +213,10 @@ export default class Task extends React.Component { let replace = api && (api as ApiObject).replaceData; const items = this.state.items.map(item => item.key === ret.data.key - ? ( - !replace - ? { - ...item, - ...ret.data - } - : {...ret.data} - ) + ? { + ...(replace ? {} : item), + ...ret.data + } : item ); this.handleLoaded({ From eea00f0a83ac8df51e5b8b7109afb85347582330 Mon Sep 17 00:00:00 2001 From: catchonme Date: Thu, 16 Jan 2020 14:37:38 +0800 Subject: [PATCH 09/42] =?UTF-8?q?=E4=BF=AE=E5=A4=8Dimage=E5=86=8D=E6=AC=A1?= =?UTF-8?q?=E7=BC=96=E8=BE=91=E5=87=BA=E9=94=99=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/renderers/Form/Image.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/renderers/Form/Image.tsx b/src/renderers/Form/Image.tsx index e40fe0e95..7d4f1dad3 100644 --- a/src/renderers/Form/Image.tsx +++ b/src/renderers/Form/Image.tsx @@ -493,7 +493,7 @@ export default class ImageControl extends React.Component< this.setState({ cropFile: { - preview: files[index].url as string, + preview: files[index].preview as string, state: 'init' } }); From 25ede26879df2ee8a05580e25e9d2b211c7c99e5 Mon Sep 17 00:00:00 2001 From: catchonme Date: Thu, 16 Jan 2020 15:16:01 +0800 Subject: [PATCH 10/42] =?UTF-8?q?image=E5=A2=9E=E5=8A=A0=E5=88=9D=E5=A7=8B?= =?UTF-8?q?=E5=80=BC=E6=97=B6=E7=BC=96=E8=BE=91=E6=83=85=E5=86=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/renderers/Form/Image.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/renderers/Form/Image.tsx b/src/renderers/Form/Image.tsx index 7d4f1dad3..66f24dc0a 100644 --- a/src/renderers/Form/Image.tsx +++ b/src/renderers/Form/Image.tsx @@ -487,13 +487,11 @@ export default class ImageControl extends React.Component< } editImage(index: number) { - const {multiple} = this.props; - const files = this.files; this.setState({ cropFile: { - preview: files[index].preview as string, + preview: files[index].preview || files[index].url as string, state: 'init' } }); From da510f73f204ae295adb208b1e12706684d8178a Mon Sep 17 00:00:00 2001 From: 2betop <2betop.cn@gmail.com> Date: Thu, 27 Feb 2020 19:57:30 +0800 Subject: [PATCH 11/42] =?UTF-8?q?=E8=A1=A5=E5=85=85filter=20=E7=94=A8?= =?UTF-8?q?=E6=B3=95=E7=9A=84=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/renderers/Tpl.md | 102 +++++++++++++++++++++++------------------- 1 file changed, 55 insertions(+), 47 deletions(-) diff --git a/docs/renderers/Tpl.md b/docs/renderers/Tpl.md index 5f0f3a0d4..b90b214b4 100644 --- a/docs/renderers/Tpl.md +++ b/docs/renderers/Tpl.md @@ -28,24 +28,24 @@ tpl 类型的渲染器支持用 JS 模板引擎来组织输出,采用的 lodas 仔细看示例不难发现,语法跟 ejs 很像,`<% 这里面是 js 语句 %>`,所以只要会写 js,做页面渲染没有什么问题。另外以下是一些可用 js 方法。 -- `formatDate(value, format='LLL', inputFormat='')` 格式化时间格式,关于 format 请前往 [moment](http://momentjs.com/) 文档页面。 -- `formatTimeStamp(value, format='LLL')` 格式化时间戳为字符串。 -- `formatNumber(number)` 格式化数字格式,加上千分位。 -- `countDown(value)` 倒计时,显示离指定时间还剩下多少天,只支持时间戳。 -- 下面 filters 中的方法也可以使用如: `<%= date(data.xxx, 'YYYY-MM-DD')%>` -- 可以联系我们添加更多公用方法。 +- `formatDate(value, format='LLL', inputFormat='')` 格式化时间格式,关于 format 请前往 [moment](http://momentjs.com/) 文档页面。 +- `formatTimeStamp(value, format='LLL')` 格式化时间戳为字符串。 +- `formatNumber(number)` 格式化数字格式,加上千分位。 +- `countDown(value)` 倒计时,显示离指定时间还剩下多少天,只支持时间戳。 +- 下面 filters 中的方法也可以使用如: `<%= date(data.xxx, 'YYYY-MM-DD')%>` +- 可以联系我们添加更多公用方法。 如: ```json { - "data": { - "user": "no one" - }, - "body": { - "type": "tpl", - "tpl": "User: <%= formatDate(data.time, 'YYYY-MM-DD') %>" - } + "data": { + "user": "no one" + }, + "body": { + "type": "tpl", + "tpl": "User: <%= formatDate(data.time, 'YYYY-MM-DD') %>" + } } ``` @@ -65,51 +65,59 @@ tpl 类型的渲染器支持用 JS 模板引擎来组织输出,采用的 lodas `注意:$xxx 与 <%= data.xxx %> 这两种语法不能同时使用,只有一种有效,所以不要交叉使用。` -通过 `$xxx` 取到的值,默认是会做 html 转义的,也就是说 `$xxx` 完全等价于 `${xxx | html}`, 如果你想什么都不做,那么请这么写 `${xxx | raw}`。 +通过 `$xxx` 取到的值,默认是会做 html 转义的,也就是说 `$xxx` 完全等价于 `${xxx | html}`, 如果你想什么都不做,那么请这么写 `${xxx | raw}`。 从上面的语法可以看出来,取值时是支持指定 filter 的,那么有哪些 filter 呢? -- `html` 转义 html 如:`${xxx|html}`。 -- `json` json stringify。 -- `raw` 表示不转换, 原样输出。 -- `date` 做日期转换如: `${xxx | date:YYYY-MM-DD}` -- `number` 自动给数字加千分位。`${xxx | number}` `9999` => `9,999` -- `trim` 把前后多余的空格去掉。 -- `percent` 格式化成百分比。`${xxx | percent}` `0.8232343` => `82.32%` -- `round` 四舍五入取整。 -- `truncate` 切除, 当超出 200 个字符时,后面的部分直接显示 ...。 `${desc | truncate:500:...}` -- `url_encode` 做 url encode 转换。 -- `url_decode` 做 url decode 转换。 -- `default` 当值为空时,显示其他值代替。 `${xxx | default:-}` 当为空时显示 `-` -- `join` 当值是 array 时,可以把内容连起来。\${xxx | join:,} -- `first` 获取数组的第一个成员。 -- `last` 获取数组的最后一个成员。 -- `pick` 如果是对象则从当前值中再次查找值如: `${xxx|pick:yyy}` 等价于 `${xxx.yyy}`。如果是数组,则做 map 操作,操作完后还是数组,不过成员已经变成了你选择的东西。如: `${xxx|pick:bbb}` 如果 xxx 的值为 `[{aaa: 1, bbb: 2}]` 经过处理后就是 `[2]`。更复杂的用法: `${xxx|pick:a~aaa,b~bbb}` 经过处理就是 `[{a:1, b: 2}]` -- `split` 可以将字符传通过分隔符分离成数组,默认分隔符为 `,` 如: `${ids|split|last}` 即取一段用逗号分割的数值中的最后一个。 -- `nth` 取数组中的第 n 个成员。如: `${ids|split|nth:1}` -- `str2date` 请参考 [date](./Date.md) 中日期默认值的设置格式。 -- `duration` 格式化成时间端如:`2` -=> `2秒` `67` => `1分7秒` `1111111` => `13天21时39分31秒` -- `asArray` 将数据包成数组如: `a` => `[a]` -- `lowerCase` 转小写 -- `upperCase` 转大写 -- `base64Encode` base64 转码 -- `base64Decode` base64 解码 -- `filter` 过滤数组,操作对象为数组,当目标对象不是数组时将无效。使用语法 ${xxx | filter: 参与过滤的字段集合:指令:取值变量名}。比如: `${xxx|filter:readonly:isTrue}` 将xxx 数组中 readonly 为 true 的成员提取出来。再来个栗子:`${xxx|filter:a,b:match:keywords}` 将 xxx 数组中成员变量 a 或者 b 的值与环境中 keywords 的值相匹配的提取出来。如果不需要取变量,也可以写固定值如:`${xxx|filter:a,b:match:'123'}` +- `html` 转义 html 如:`${xxx|html}`。 +- `json` json stringify。 +- `raw` 表示不转换, 原样输出。 +- `date` 做日期转换如: `${xxx | date:YYYY-MM-DD}` +- `number` 自动给数字加千分位。`${xxx | number}` `9999` => `9,999` +- `trim` 把前后多余的空格去掉。 +- `percent` 格式化成百分比。`${xxx | percent}` `0.8232343` => `82.32%` +- `round` 四舍五入取整。 +- `truncate` 切除, 当超出 200 个字符时,后面的部分直接显示 ...。 `${desc | truncate:500:...}` +- `url_encode` 做 url encode 转换。 +- `url_decode` 做 url decode 转换。 +- `default` 当值为空时,显示其他值代替。 `${xxx | default:-}` 当为空时显示 `-` +- `join` 当值是 array 时,可以把内容连起来。\${xxx | join:,} +- `first` 获取数组的第一个成员。 +- `last` 获取数组的最后一个成员。 +- `pick` 如果是对象则从当前值中再次查找值如: `${xxx|pick:yyy}` 等价于 `${xxx.yyy}`。如果是数组,则做 map 操作,操作完后还是数组,不过成员已经变成了你选择的东西。如: `${xxx|pick:bbb}` 如果 xxx 的值为 `[{aaa: 1, bbb: 2}]` 经过处理后就是 `[2]`。更复杂的用法: `${xxx|pick:a~aaa,b~bbb}` 经过处理就是 `[{a:1, b: 2}]` +- `split` 可以将字符传通过分隔符分离成数组,默认分隔符为 `,` 如: `${ids|split|last}` 即取一段用逗号分割的数值中的最后一个。 +- `nth` 取数组中的第 n 个成员。如: `${ids|split|nth:1}` +- `str2date` 请参考 [date](./Date.md) 中日期默认值的设置格式。 +- `duration` 格式化成时间端如:`2` -=> `2秒` `67` => `1分7秒` `1111111` => `13天21时39分31秒` +- `asArray` 将数据包成数组如: `a` => `[a]` +- `lowerCase` 转小写 +- `upperCase` 转大写 +- `base64Encode` base64 转码 +- `base64Decode` base64 解码 +- `filter` 过滤数组,操作对象为数组,当目标对象不是数组时将无效。使用语法 \${xxx | filter: 参与过滤的字段集合:指令:取值变量名}。 + + 比如: `${xxx|filter:readonly:isTrue}` 将 xxx 数组中 readonly 为 true 的成员提取出来。 + 再来个栗子:`${xxx|filter:a,b:match:keywords}` 将 xxx 数组中成员变量 a 或者 b 的值与环境中 keywords 的值相匹配的提取出来。如果不需要取变量,也可以写固定值如:`${xxx|filter:a,b:match:'123'}` + + 指令类型: + + - `isTrue` 目标值为真通过筛选。 + - `isFalse` 目标值为假时通过筛选。 + - `match` 模糊匹配后面的参数。`${xxx|filter:a,b:match:keywords}` 表示 xxx 里面的成员,如果字段 a 或者 字段 b 模糊匹配 keywords 变量的值,则通过筛选。 + - `equals` 相对于模糊匹配,这个就是时相对精确匹配了,用法跟 `match` 一样。 组合使用。 -- `${&|json|html}` 把当前可用的数据全部打印出来。`$&` 取当前值,json 做 json stringify,然后 html 转义。 -- `${rows|first|pick:id}` 把 rows 中的第一条数据中的 id 取到。 -- `${rows|pick:id|join:,}` - +- `${&|json|html}` 把当前可用的数据全部打印出来。`$&` 取当前值,json 做 json stringify,然后 html 转义。 +- `${rows|first|pick:id}` 把 rows 中的第一条数据中的 id 取到。 +- `${rows|pick:id|join:,}` 没有找到合适的?可以自定义 filter。如果是 AMIS 平台用户,可以将以下代码加入到自定义组件中,如果不是请想办法插入以下代码。 - ```js import {registerFilter} from 'amis'; -registerFilter('my-filter', (input:string) => `${input}Boom`); +registerFilter('my-filter', (input: string) => `${input}Boom`); ``` -加入成功后就可以这样使用了 `${xxx | my-filter}`。 如果 `xxx` 的值是 `abc` 那么输出将会是 `abcBoom`。 \ No newline at end of file +加入成功后就可以这样使用了 `${xxx | my-filter}`。 如果 `xxx` 的值是 `abc` 那么输出将会是 `abcBoom`。 From e98c746ce5ee1aa952c5d7d2a9acab884f7e03bb Mon Sep 17 00:00:00 2001 From: 2betop <2betop.cn@gmail.com> Date: Thu, 27 Feb 2020 20:24:35 +0800 Subject: [PATCH 12/42] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/renderers/Tpl.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/renderers/Tpl.md b/docs/renderers/Tpl.md index b90b214b4..d7bab960c 100644 --- a/docs/renderers/Tpl.md +++ b/docs/renderers/Tpl.md @@ -117,7 +117,7 @@ tpl 类型的渲染器支持用 JS 模板引擎来组织输出,采用的 lodas ```js import {registerFilter} from 'amis'; -registerFilter('my-filter', (input: string) => `${input}Boom`); +registerFilter('myfilter', (input: string) => `${input}Boom`); ``` -加入成功后就可以这样使用了 `${xxx | my-filter}`。 如果 `xxx` 的值是 `abc` 那么输出将会是 `abcBoom`。 +加入成功后就可以这样使用了 `${xxx | myfilter}`。 如果 `xxx` 的值是 `abc` 那么输出将会是 `abcBoom`。 From 39f58bf64fa19e45bc94cd4f140d171248da47ba Mon Sep 17 00:00:00 2001 From: 2betop <2betop.cn@gmail.com> Date: Thu, 27 Feb 2020 20:24:57 +0800 Subject: [PATCH 13/42] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/renderers/Tpl.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/renderers/Tpl.md b/docs/renderers/Tpl.md index d7bab960c..75d967676 100644 --- a/docs/renderers/Tpl.md +++ b/docs/renderers/Tpl.md @@ -104,7 +104,7 @@ tpl 类型的渲染器支持用 JS 模板引擎来组织输出,采用的 lodas - `isTrue` 目标值为真通过筛选。 - `isFalse` 目标值为假时通过筛选。 - `match` 模糊匹配后面的参数。`${xxx|filter:a,b:match:keywords}` 表示 xxx 里面的成员,如果字段 a 或者 字段 b 模糊匹配 keywords 变量的值,则通过筛选。 - - `equals` 相对于模糊匹配,这个就是时相对精确匹配了,用法跟 `match` 一样。 + - `equals` 相对于模糊匹配,这个就相对精确匹配了,用法跟 `match` 一样。 组合使用。 From 48dd654ce742a1af88ef06b5124e5b6c7f2f84fd Mon Sep 17 00:00:00 2001 From: 2betop <2betop.cn@gmail.com> Date: Fri, 28 Feb 2020 12:39:53 +0800 Subject: [PATCH 14/42] =?UTF-8?q?=E5=9B=BE=E7=89=87=E5=9C=A8=E8=A3=81?= =?UTF-8?q?=E5=89=AA=E4=B8=AD=E8=A1=A8=E5=8D=95=E6=8F=90=E4=BA=A4,?= =?UTF-8?q?=E5=88=99=E8=87=AA=E5=8A=A8=E6=8A=8A=E5=86=85=E5=AE=B9=E8=A3=81?= =?UTF-8?q?=E5=89=AA=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/renderers/Form/Image.tsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/renderers/Form/Image.tsx b/src/renderers/Form/Image.tsx index 8a49344a5..255e618b5 100644 --- a/src/renderers/Form/Image.tsx +++ b/src/renderers/Form/Image.tsx @@ -569,8 +569,6 @@ export default class ImageControl extends React.Component< } return this.setState({ - locked: true, - lockedReason: '请选择放弃或者应用', cropFile: file }); } @@ -853,6 +851,11 @@ export default class ImageControl extends React.Component< validate(): any { if (this.state.locked && this.state.lockedReason) { return this.state.lockedReason; + } else if (this.state.cropFile) { + return new Promise(resolve => { + this.resolve = resolve; + this.handleCrop(); + }); } else if ( this.state.uploading || this.files.some(item => item.state === 'pending') From 7c90a2afd5775d6049eed24c98c419b941de86c2 Mon Sep 17 00:00:00 2001 From: 2betop <2betop.cn@gmail.com> Date: Fri, 28 Feb 2020 13:23:17 +0800 Subject: [PATCH 15/42] =?UTF-8?q?Tree=20=E6=A0=B7=E5=BC=8F=E4=BC=98?= =?UTF-8?q?=E5=8C=96,=E5=A2=9E=E5=A4=A7=E7=82=B9=E5=87=BB=E9=80=89?= =?UTF-8?q?=E4=B8=AD=E8=8C=83=E5=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scss/components/form/_tree.scss | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scss/components/form/_tree.scss b/scss/components/form/_tree.scss index 9f9295fe9..8d0b946ad 100644 --- a/scss/components/form/_tree.scss +++ b/scss/components/form/_tree.scss @@ -62,6 +62,7 @@ } &-itemLabel { + display: flex; &:hover { background: $Tree-item-onHover-bg; } @@ -223,6 +224,7 @@ &-itemText { cursor: pointer; + flex: 1 auto; } &-placeholder { From 1908233ed78f4ab9bf9f0f5b7ad1ff1d5de42f40 Mon Sep 17 00:00:00 2001 From: 2betop <2betop.cn@gmail.com> Date: Fri, 28 Feb 2020 16:22:23 +0800 Subject: [PATCH 16/42] =?UTF-8?q?=E6=96=87=E6=A1=88=E6=95=B4=E4=BD=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/renderers/Form/Select.md | 45 +++++++++++++++++------------------ 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/docs/renderers/Form/Select.md b/docs/renderers/Form/Select.md index 585fbcc84..775549b17 100644 --- a/docs/renderers/Form/Select.md +++ b/docs/renderers/Form/Select.md @@ -2,27 +2,27 @@ 选项表单。 -- `type` 请设置成 `select` -- `options` 选项配置,类型为数组,成员格式如下。 - - `label` 文字 - - `value` 值 -- `value` 设置默认值,如果想要默认选中某个,请设置默认值。 -- `source` Api 地址,如果选项不固定,可以通过配置 `source` 动态拉取。另外也可以用 `$xxxx` 来获取当前作用域中的变量。 -- `autoComplete` 跟 source 不同的是,每次用户输入都会去接口获取提示。 -- `multiple` 默认为 `false`, 设置成 `true` 表示可多选。 -- `joinValues` 默认为 `true` -- 单选模式:当用户选中某个选项时,选项中的 value 将被作为该表单项的值提交,否则,整个选项对象都会作为该表单项的值提交。 -- 多选模式:选中的多个选项的 `value` 会通过 `delimiter` 连接起来,否则直接将以数组的形式提交值。 -- `extractValue` 默认为 `false`, `joinValues`设置为`false`时生效, 开启后将选中的选项 `value` 的值封装为数组,作为当前表单项的值。 -- `delimiter` 默认为 `,` -- `clearable` 默认为 `false`, 当设置为 `true` 时,已选中的选项右侧会有个小 `X` 用来取消设置。 -- `searchable` 默认为 `false`,表示可以通过输入部分内容检索出选项。 -- `checkAll` 默认为 `false` 开启后支持全选 -- `checkAllLabel` 默认为 `全选`, 全选的文字 -- `defaultCheckAll` 是否默认全选,默认为`false` -- `autoFill` 将当前已选中的选项的某个字段的值自动填充到表单中某个表单项中,只在单选时有效 - - `autoFill`的格式为`{address: "${label}"}`,表示将选中项中的`label`的值,自动填充到当前表单项中`name` 为`address` 中 -- **还有更多通用配置请参考** [FormItem](./FormItem.md) +- `type` 请设置成 `select` +- `options` 选项配置,类型为数组,成员格式如下。 + - `label` 文字 + - `value` 值 +- `value` 设置默认值,如果想要默认选中某个,请设置默认值。 +- `source` Api 地址,如果选项不固定,可以通过配置 `source` 动态拉取。另外也可以用 `$xxxx` 来获取当前作用域中的变量。 +- `autoComplete` 跟 source 不同的是,每次用户输入都会去接口获取提示。 +- `multiple` 默认为 `false`, 设置成 `true` 表示可多选。 +- `joinValues` 默认为 `true` +- 单选模式:当用户选中某个选项时,选项中的 value 将被作为该表单项的值提交,否则,整个选项对象都会作为该表单项的值提交。 +- 多选模式:选中的多个选项的 `value` 会通过 `delimiter` 连接起来,否则直接将以数组的形式提交值。 +- `extractValue` 默认为 `false`, `joinValues`设置为`false`时生效, 开启后将选中的选项 `value` 的值封装为数组,作为当前表单项的值。 +- `delimiter` 默认为 `,` +- `clearable` 默认为 `false`, 当设置为 `true` 时,已选中的选项右侧会有个小 `X` 用来取消设置。 +- `searchable` 默认为 `false`,当设置为 `true` 时表示可以通过输入部分内容检索出选项。 +- `checkAll` 默认为 `false` 开启后支持全选 +- `checkAllLabel` 默认为 `全选`, 全选的文字 +- `defaultCheckAll` 是否默认全选,默认为`false` +- `autoFill` 将当前已选中的选项的某个字段的值自动填充到表单中某个表单项中,只在单选时有效 + - `autoFill`的格式为`{address: "${label}"}`,表示将选中项中的`label`的值,自动填充到当前表单项中`name` 为`address` 中 +- **还有更多通用配置请参考** [FormItem](./FormItem.md) 单选 @@ -91,7 +91,6 @@ ] ``` - ### 接口说明 开始之前请你先阅读[整体要求](../api.md)。 @@ -126,4 +125,4 @@ "value": "值" // 默认值,可以获取列表的同时设置默认值。 } } -``` \ No newline at end of file +``` From d01e0753a31bda1b848153565a0165fa4ec5f06f Mon Sep 17 00:00:00 2001 From: chen Date: Sat, 29 Feb 2020 09:59:17 +0800 Subject: [PATCH 17/42] =?UTF-8?q?import=20require=20=E6=94=B9=E6=88=90=20i?= =?UTF-8?q?mport=20from?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Scoped.tsx | 4 ++-- src/components/Checkboxes.tsx | 8 ++++---- src/components/Collapse.tsx | 2 +- src/components/ColorPicker.tsx | 2 +- src/components/DateRangePicker.tsx | 4 ++-- src/components/LazyComponent.tsx | 2 +- src/components/Radios.tsx | 4 ++-- src/components/Range.tsx | 2 +- src/components/Select.tsx | 8 ++++---- src/components/TooltipWrapper.tsx | 4 ++-- src/factory.tsx | 10 +++++----- src/renderers/Action.tsx | 2 +- src/renderers/Alert.tsx | 2 +- src/renderers/Audio.tsx | 2 +- src/renderers/CRUD.tsx | 8 ++++---- src/renderers/Cards.tsx | 4 ++-- src/renderers/Copyable.tsx | 2 +- src/renderers/Dialog.tsx | 2 +- src/renderers/Drawer.tsx | 2 +- src/renderers/Form/Checkboxes.tsx | 2 +- src/renderers/Form/Combo.tsx | 4 ++-- src/renderers/Form/Control.tsx | 2 +- src/renderers/Form/DiffEditor.tsx | 2 +- src/renderers/Form/Editor.tsx | 2 +- src/renderers/Form/File.tsx | 4 ++-- src/renderers/Form/Grid.tsx | 2 +- src/renderers/Form/Image.tsx | 2 +- src/renderers/Form/Item.tsx | 2 +- src/renderers/Form/NestedSelect.tsx | 4 ++-- src/renderers/Form/Picker.tsx | 4 ++-- src/renderers/Form/Range.tsx | 6 +++--- src/renderers/Form/Select.tsx | 4 ++-- src/renderers/Form/SubForm.tsx | 4 ++-- src/renderers/Form/Table.tsx | 6 +++--- src/renderers/Form/Tag.tsx | 4 ++-- src/renderers/Form/Text.tsx | 4 ++-- src/renderers/Form/TreeSelect.tsx | 4 ++-- src/renderers/Form/index.tsx | 8 ++++---- src/renderers/Grid.tsx | 2 +- src/renderers/List.tsx | 2 +- src/renderers/PopOver.tsx | 2 +- src/renderers/QRCode.tsx | 2 +- src/renderers/QuickEdit.tsx | 8 ++++---- src/renderers/Table.tsx | 12 ++++++------ src/renderers/Tabs.tsx | 4 ++-- src/renderers/Tasks.tsx | 2 +- src/store/crud.ts | 2 +- src/store/form.ts | 4 ++-- src/store/formItem.ts | 6 +++--- src/store/list.ts | 4 ++-- src/store/table.ts | 4 ++-- src/theme.tsx | 2 +- src/utils/SimpleMap.ts | 4 ++-- src/utils/dom.tsx | 12 ++++++------ src/utils/helper.ts | 10 +++++----- src/utils/tpl-builtin.ts | 2 +- src/utils/tpl-lodash.ts | 2 +- 57 files changed, 115 insertions(+), 115 deletions(-) diff --git a/src/Scoped.tsx b/src/Scoped.tsx index 3d458424c..e28a2a6b0 100644 --- a/src/Scoped.tsx +++ b/src/Scoped.tsx @@ -4,9 +4,9 @@ */ import React from 'react'; -import find = require('lodash/find'); +import find from 'lodash/find'; import PropTypes from 'prop-types'; -import hoistNonReactStatic = require('hoist-non-react-statics'); +import hoistNonReactStatic from 'hoist-non-react-statics'; import qs from 'qs'; import {dataMapping} from './utils/tpl-builtin'; import {RendererEnv, RendererProps} from './factory'; diff --git a/src/components/Checkboxes.tsx b/src/components/Checkboxes.tsx index 44a9dc1c2..67dd47b7b 100644 --- a/src/components/Checkboxes.tsx +++ b/src/components/Checkboxes.tsx @@ -5,14 +5,14 @@ */ import React from "react"; -import uncontrollable = require("uncontrollable"); +import uncontrollable from "uncontrollable"; import Checkbox from "./Checkbox"; -import find = require("lodash/find"); -import chunk = require("lodash/chunk"); +import find from "lodash/find"; +import chunk from "lodash/chunk"; import { flattenTree, isObject } from "../utils/helper"; import { ClassNamesFn, themeable } from "../theme"; import { optionValueCompare } from "./Select"; -// import isPlainObject = require('lodash/isPlainObject'); +// import isPlainObject from 'lodash/isPlainObject'; export interface Option { label?: string; diff --git a/src/components/Collapse.tsx b/src/components/Collapse.tsx index 09e9880f8..ff9a6adf5 100644 --- a/src/components/Collapse.tsx +++ b/src/components/Collapse.tsx @@ -5,7 +5,7 @@ */ import React from 'react'; -import css = require('dom-helpers/style/index'); +import css from 'dom-helpers/style/index'; import {ClassNamesFn, themeable} from '../theme'; import Transition, { EXITED, diff --git a/src/components/ColorPicker.tsx b/src/components/ColorPicker.tsx index a35b4750b..cc1eb4bc3 100644 --- a/src/components/ColorPicker.tsx +++ b/src/components/ColorPicker.tsx @@ -10,7 +10,7 @@ import {findDOMNode} from 'react-dom'; import {SketchPicker, GithubPicker, ColorResult} from 'react-color'; import {Icon} from './icons'; import Overlay from './Overlay'; -import uncontrollable = require('uncontrollable'); +import uncontrollable from 'uncontrollable'; import PopOver from './PopOver'; import {ClassNamesFn, themeable} from '../theme'; import {autobind} from '../utils/helper'; diff --git a/src/components/DateRangePicker.tsx b/src/components/DateRangePicker.tsx index 124fd34fd..8e1346ffb 100644 --- a/src/components/DateRangePicker.tsx +++ b/src/components/DateRangePicker.tsx @@ -4,8 +4,8 @@ * @author fex */ -import React = require('react'); -import moment = require('moment'); +import React from 'react'; +import moment from 'moment'; import {findDOMNode} from 'react-dom'; import cx from 'classnames'; import {Icon} from './icons'; diff --git a/src/components/LazyComponent.tsx b/src/components/LazyComponent.tsx index b60641742..b88102895 100644 --- a/src/components/LazyComponent.tsx +++ b/src/components/LazyComponent.tsx @@ -5,7 +5,7 @@ */ import React from 'react'; -import VisibilitySensor = require('react-visibility-sensor'); +import VisibilitySensor from 'react-visibility-sensor'; import Spinner from './Spinner'; export interface LazyComponentProps { diff --git a/src/components/Radios.tsx b/src/components/Radios.tsx index 79dc5ee2e..d77564798 100644 --- a/src/components/Radios.tsx +++ b/src/components/Radios.tsx @@ -14,10 +14,10 @@ */ import React from 'react'; -import uncontrollable = require('uncontrollable'); +import uncontrollable from 'uncontrollable'; import Checkbox from './Checkbox'; import {value2array, OptionProps, Option} from './Checkboxes'; -import chunk = require('lodash/chunk'); +import chunk from 'lodash/chunk'; import {ClassNamesFn, themeable} from '../theme'; interface RadioProps extends OptionProps { diff --git a/src/components/Range.tsx b/src/components/Range.tsx index 1e54c9a10..9d79c1fa5 100644 --- a/src/components/Range.tsx +++ b/src/components/Range.tsx @@ -6,7 +6,7 @@ import React from 'react'; import InputRange from 'react-input-range'; -import uncontrollable = require('uncontrollable'); +import uncontrollable from 'uncontrollable'; import cx from 'classnames'; import {RendererProps} from '../factory'; import {ClassNamesFn, themeable} from '../theme'; diff --git a/src/components/Select.tsx b/src/components/Select.tsx index 884dd6485..b142eb633 100644 --- a/src/components/Select.tsx +++ b/src/components/Select.tsx @@ -5,7 +5,7 @@ * @date 2017-11-07 */ -import uncontrollable = require('uncontrollable'); +import uncontrollable from 'uncontrollable'; import React from 'react'; import 'react-datetime/css/react-datetime.css'; import Overlay from './Overlay'; @@ -15,9 +15,9 @@ import {closeIcon, Icon} from './icons'; // @ts-ignore import matchSorter from 'match-sorter'; import {noop, isObject} from '../utils/helper'; -import find = require('lodash/find'); -import isPlainObject = require('lodash/isPlainObject'); -import union = require('lodash/union'); +import find from 'lodash/find'; +import isPlainObject from 'lodash/isPlainObject'; +import union from 'lodash/union'; import {highlight} from '../renderers/Form/Options'; import {findDOMNode} from 'react-dom'; import {ClassNamesFn, themeable} from '../theme'; diff --git a/src/components/TooltipWrapper.tsx b/src/components/TooltipWrapper.tsx index 76a605198..185f84368 100644 --- a/src/components/TooltipWrapper.tsx +++ b/src/components/TooltipWrapper.tsx @@ -4,9 +4,9 @@ * @author fex */ -import React = require('react'); +import React from 'react'; import Html from './Html'; -import uncontrollable = require('uncontrollable'); +import uncontrollable from 'uncontrollable'; import {findDOMNode} from 'react-dom'; import Tooltip from './Tooltip'; import {ClassNamesFn, themeable} from '../theme'; diff --git a/src/factory.tsx b/src/factory.tsx index a353319c9..22000979c 100644 --- a/src/factory.tsx +++ b/src/factory.tsx @@ -29,13 +29,13 @@ import { } from './types'; import {observer} from 'mobx-react'; import getExprProperties from './utils/filter-schema'; -import hoistNonReactStatic = require('hoist-non-react-statics'); -import omit = require('lodash/omit'); -import difference = require('lodash/difference'); -import isPlainObject = require('lodash/isPlainObject'); +import hoistNonReactStatic from 'hoist-non-react-statics'; +import omit from 'lodash/omit'; +import difference from 'lodash/difference'; +import isPlainObject from 'lodash/isPlainObject'; import Scoped from './Scoped'; import {getTheme, ThemeInstance, ClassNamesFn, ThemeContext} from './theme'; -import find = require('lodash/find'); +import find from 'lodash/find'; import Alert from './components/Alert2'; import {LazyComponent} from './components'; import ImageGallery from './components/ImageGallery'; diff --git a/src/renderers/Action.tsx b/src/renderers/Action.tsx index 5dd3ae810..f9b4ba920 100644 --- a/src/renderers/Action.tsx +++ b/src/renderers/Action.tsx @@ -2,7 +2,7 @@ import React from 'react'; import {Renderer, RendererProps} from '../factory'; import {filter} from '../utils/tpl'; import Button from '../components/Button'; -import pick = require('lodash/pick'); +import pick from 'lodash/pick'; const ActionProps = [ 'dialog', 'drawer', diff --git a/src/renderers/Alert.tsx b/src/renderers/Alert.tsx index 6d5f7c9cf..f1ddbb004 100644 --- a/src/renderers/Alert.tsx +++ b/src/renderers/Alert.tsx @@ -1,5 +1,5 @@ import {Renderer, RendererProps} from '../factory'; -import React = require('react'); +import React from 'react'; import Alert, {AlertProps} from '../components/Alert2'; @Renderer({ diff --git a/src/renderers/Audio.tsx b/src/renderers/Audio.tsx index dd7e78c8b..7332c5f91 100644 --- a/src/renderers/Audio.tsx +++ b/src/renderers/Audio.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import upperFirst = require('lodash/upperFirst'); +import upperFirst from 'lodash/upperFirst'; import {Renderer, RendererProps} from '../factory'; import {autobind} from '../utils/helper'; import {Icon} from '../components/icons'; diff --git a/src/renderers/CRUD.tsx b/src/renderers/CRUD.tsx index cde1b09bf..7f235da9f 100644 --- a/src/renderers/CRUD.tsx +++ b/src/renderers/CRUD.tsx @@ -14,18 +14,18 @@ import { qsstringify } from '../utils/helper'; import {observer} from 'mobx-react'; -import partition = require('lodash/partition'); +import partition from 'lodash/partition'; import Scoped, {ScopedContext, IScopedContext} from '../Scoped'; import Button from '../components/Button'; import Select from '../components/Select'; import getExprProperties from '../utils/filter-schema'; -import pick = require('lodash/pick'); +import pick from 'lodash/pick'; import qs from 'qs'; import {findDOMNode} from 'react-dom'; import {evalExpression, filter} from '../utils/tpl'; import {isValidApi, buildApi, isEffectiveApi} from '../utils/api'; -import omit = require('lodash/omit'); -import find = require('lodash/find'); +import omit from 'lodash/omit'; +import find from 'lodash/find'; import Html from '../components/Html'; import {Spinner} from '../components'; diff --git a/src/renderers/Cards.tsx b/src/renderers/Cards.tsx index 33dd126ee..d265aa197 100644 --- a/src/renderers/Cards.tsx +++ b/src/renderers/Cards.tsx @@ -13,9 +13,9 @@ import { ucFirst } from '../utils/helper'; import {resolveVariable} from '../utils/tpl-builtin'; -import Sortable = require('sortablejs'); +import Sortable from 'sortablejs'; import {filter} from '../utils/tpl'; -import debounce = require('lodash/debounce'); +import debounce from 'lodash/debounce'; import {resizeSensor} from '../utils/resize-sensor'; export interface Column { diff --git a/src/renderers/Copyable.tsx b/src/renderers/Copyable.tsx index d84f91338..c06950ae3 100644 --- a/src/renderers/Copyable.tsx +++ b/src/renderers/Copyable.tsx @@ -6,7 +6,7 @@ import React from 'react'; import {RendererProps} from '../factory'; import cx from 'classnames'; -import hoistNonReactStatic = require('hoist-non-react-statics'); +import hoistNonReactStatic from 'hoist-non-react-statics'; import Button from '../components/Button'; import {filter} from '../utils/tpl'; diff --git a/src/renderers/Dialog.tsx b/src/renderers/Dialog.tsx index a79798a29..dbc145a68 100644 --- a/src/renderers/Dialog.tsx +++ b/src/renderers/Dialog.tsx @@ -4,7 +4,7 @@ import {Renderer, RendererProps} from '../factory'; import {SchemaNode, Schema, Action} from '../types'; import {filter} from '../utils/tpl'; import Modal from '../components/Modal'; -import findLast = require('lodash/findLast'); +import findLast from 'lodash/findLast'; import {guid, isVisible} from '../utils/helper'; import {reaction} from 'mobx'; import {Icon} from '../components/icons'; diff --git a/src/renderers/Drawer.tsx b/src/renderers/Drawer.tsx index e1b868837..bf1c73870 100644 --- a/src/renderers/Drawer.tsx +++ b/src/renderers/Drawer.tsx @@ -3,7 +3,7 @@ import {ScopedContext, IScopedContext} from '../Scoped'; import {Renderer, RendererProps} from '../factory'; import {SchemaNode, Schema, Action} from '../types'; import {default as DrawerContainer} from '../components/Drawer'; -import findLast = require('lodash/findLast'); +import findLast from 'lodash/findLast'; import {guid, isVisible} from '../utils/helper'; import {reaction} from 'mobx'; import {findDOMNode} from 'react-dom'; diff --git a/src/renderers/Form/Checkboxes.tsx b/src/renderers/Form/Checkboxes.tsx index 71970ae60..57c461466 100644 --- a/src/renderers/Form/Checkboxes.tsx +++ b/src/renderers/Form/Checkboxes.tsx @@ -2,7 +2,7 @@ import React from 'react'; import {OptionsControl, OptionsControlProps, Option} from './Options'; import cx from 'classnames'; import Checkbox from '../../components/Checkbox'; -import chunk = require('lodash/chunk'); +import chunk from 'lodash/chunk'; export interface CheckboxesProps extends OptionsControlProps { placeholder?: any; diff --git a/src/renderers/Form/Combo.tsx b/src/renderers/Form/Combo.tsx index da7a61f39..309386b42 100644 --- a/src/renderers/Form/Combo.tsx +++ b/src/renderers/Form/Combo.tsx @@ -14,9 +14,9 @@ import { autobind, isObjectShallowModified } from '../../utils/helper'; -import Sortable = require('sortablejs'); +import Sortable from 'sortablejs'; import {evalExpression, filter} from '../../utils/tpl'; -import find = require('lodash/find'); +import find from 'lodash/find'; import Select from '../../components/Select'; import {dataMapping, resolveVariable} from '../../utils/tpl-builtin'; import {isEffectiveApi} from '../../utils/api'; diff --git a/src/renderers/Form/Control.tsx b/src/renderers/Form/Control.tsx index 64d62bcf4..c6781bad8 100644 --- a/src/renderers/Form/Control.tsx +++ b/src/renderers/Form/Control.tsx @@ -1,6 +1,6 @@ import React from 'react'; import {IFormStore, IFormItemStore} from '../../store/form'; -import debouce = require('lodash/debounce'); +import debouce from 'lodash/debounce'; import {RendererProps, Renderer} from '../../factory'; import {ComboStore, IComboStore, IUniqueGroup} from '../../store/combo'; diff --git a/src/renderers/Form/DiffEditor.tsx b/src/renderers/Form/DiffEditor.tsx index b475fb616..3563dda8d 100644 --- a/src/renderers/Form/DiffEditor.tsx +++ b/src/renderers/Form/DiffEditor.tsx @@ -4,7 +4,7 @@ import {FormItem, FormControlProps} from './Item'; import {filter} from '../../utils/tpl'; import cx from 'classnames'; import LazyComponent from '../../components/LazyComponent'; -import debouce = require('lodash/debounce'); +import debouce from 'lodash/debounce'; import {isPureVariable} from '../../utils/tpl-builtin'; function loadComponent(): Promise { diff --git a/src/renderers/Form/Editor.tsx b/src/renderers/Form/Editor.tsx index 934534b4a..8fc92d4f2 100644 --- a/src/renderers/Form/Editor.tsx +++ b/src/renderers/Form/Editor.tsx @@ -1,7 +1,7 @@ import React from 'react'; import {FormItem, FormControlProps} from './Item'; import LazyComponent from '../../components/LazyComponent'; -import debouce = require('lodash/debounce'); +import debouce from 'lodash/debounce'; import Editor from '../../components/Editor'; export interface EditorProps extends FormControlProps { diff --git a/src/renderers/Form/File.tsx b/src/renderers/Form/File.tsx index 38f54e623..100ac7683 100644 --- a/src/renderers/Form/File.tsx +++ b/src/renderers/Form/File.tsx @@ -2,8 +2,8 @@ import React from 'react'; import {FormItem, FormControlProps} from './Item'; import cx from 'classnames'; import qs from 'qs'; -import find = require('lodash/find'); -import isPlainObject = require('lodash/isPlainObject'); +import find from 'lodash/find'; +import isPlainObject from 'lodash/isPlainObject'; import {mapLimit} from 'async'; import ImageControl from './Image'; import {Payload, ApiObject, ApiString} from '../../types'; diff --git a/src/renderers/Form/Grid.tsx b/src/renderers/Form/Grid.tsx index 913064126..15d88556b 100644 --- a/src/renderers/Form/Grid.tsx +++ b/src/renderers/Form/Grid.tsx @@ -3,7 +3,7 @@ import Grid, {ColumnNode, Column, ColProps, ColumnArray} from '../Grid'; import {Schema} from '../../types'; import {FormItem, FormControlProps} from './Item'; -import pick = require('lodash/pick'); +import pick from 'lodash/pick'; import React from 'react'; import cx from 'classnames'; diff --git a/src/renderers/Form/Image.tsx b/src/renderers/Form/Image.tsx index 8a49344a5..7a1cc81bc 100644 --- a/src/renderers/Form/Image.tsx +++ b/src/renderers/Form/Image.tsx @@ -4,7 +4,7 @@ import {FormItem, FormControlProps} from './Item'; import Cropper from 'react-cropper'; import DropZone from 'react-dropzone'; import 'blueimp-canvastoblob'; -import find = require('lodash/find'); +import find from 'lodash/find'; import qs from 'qs'; import {Payload} from '../../types'; import {buildApi} from '../../utils/api'; diff --git a/src/renderers/Form/Item.tsx b/src/renderers/Form/Item.tsx index 64a7e29b4..f1d5bf9a5 100644 --- a/src/renderers/Form/Item.tsx +++ b/src/renderers/Form/Item.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import hoistNonReactStatic = require('hoist-non-react-statics'); +import hoistNonReactStatic from 'hoist-non-react-statics'; import {IFormItemStore, IFormStore} from '../../store/form'; import {reaction} from 'mobx'; diff --git a/src/renderers/Form/NestedSelect.tsx b/src/renderers/Form/NestedSelect.tsx index 9ebb1c5fa..07e38f3d8 100644 --- a/src/renderers/Form/NestedSelect.tsx +++ b/src/renderers/Form/NestedSelect.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import xorBy = require('lodash/xorBy'); -import unionBy = require('lodash/unionBy'); +import xorBy from 'lodash/xorBy'; +import unionBy from 'lodash/unionBy'; import Overlay from '../../components/Overlay'; import Checkbox from '../../components/Checkbox'; import PopOver from '../../components/PopOver'; diff --git a/src/renderers/Form/Picker.tsx b/src/renderers/Form/Picker.tsx index ae957857b..ba9794664 100644 --- a/src/renderers/Form/Picker.tsx +++ b/src/renderers/Form/Picker.tsx @@ -3,7 +3,7 @@ import {OptionsControl, OptionsControlProps, Option} from './Options'; import cx from 'classnames'; import Button from '../../components/Button'; import {SchemaNode, Schema, Action} from '../../types'; -import find = require('lodash/find'); +import find from 'lodash/find'; import { anyChanged, autobind, @@ -11,7 +11,7 @@ import { noop, createObject } from '../../utils/helper'; -import findIndex = require('lodash/findIndex'); +import findIndex from 'lodash/findIndex'; import Html from '../../components/Html'; import {filter} from '../../utils/tpl'; import {Icon} from '../../components/icons'; diff --git a/src/renderers/Form/Range.tsx b/src/renderers/Form/Range.tsx index 2b7485893..e067646b1 100644 --- a/src/renderers/Form/Range.tsx +++ b/src/renderers/Form/Range.tsx @@ -1,7 +1,7 @@ import React from 'react'; -import isNumber = require('lodash/isNumber'); -import isObject = require('lodash/isObject'); -import isEqual = require('lodash/isEqual'); +import isNumber from 'lodash/isNumber'; +import isObject from 'lodash/isObject'; +import isEqual from 'lodash/isEqual'; import {FormItem, FormControlProps} from './Item'; import cx from 'classnames'; import InputRange from '../../components/Range'; diff --git a/src/renderers/Form/Select.tsx b/src/renderers/Form/Select.tsx index c798d85d5..4c3def1f3 100644 --- a/src/renderers/Form/Select.tsx +++ b/src/renderers/Form/Select.tsx @@ -2,8 +2,8 @@ import React from 'react'; import cx from 'classnames'; import {OptionsControl, OptionsControlProps, Option} from './Options'; import Select from '../../components/Select'; -import find = require('lodash/find'); -import debouce = require('lodash/debounce'); +import find from 'lodash/find'; +import debouce from 'lodash/debounce'; import {Api} from '../../types'; import {isEffectiveApi} from '../../utils/api'; import {isEmpty, createObject} from '../../utils/helper'; diff --git a/src/renderers/Form/SubForm.tsx b/src/renderers/Form/SubForm.tsx index aa14a3b88..4f4cc9ae5 100644 --- a/src/renderers/Form/SubForm.tsx +++ b/src/renderers/Form/SubForm.tsx @@ -1,8 +1,8 @@ import React from 'react'; import {FormItem, FormControlProps} from './Item'; import cx from 'classnames'; -import omit = require('lodash/omit'); -import pick = require('lodash/pick'); +import omit from 'lodash/omit'; +import pick from 'lodash/pick'; import {createObject} from '../../utils/helper'; export interface SubFormProps extends FormControlProps { diff --git a/src/renderers/Form/Table.tsx b/src/renderers/Form/Table.tsx index abee1172f..3bece2067 100644 --- a/src/renderers/Form/Table.tsx +++ b/src/renderers/Form/Table.tsx @@ -6,10 +6,10 @@ import {createObject, isObjectShallowModified} from '../../utils/helper'; import {RendererData, Action, Api, Payload} from '../../types'; import {isEffectiveApi} from '../../utils/api'; import {filter} from '../../utils/tpl'; -import omit = require('lodash/omit'); +import omit from 'lodash/omit'; import {dataMapping} from '../../utils/tpl-builtin'; -import findIndex = require('lodash/findIndex'); -import memoize = require('lodash/memoize'); +import findIndex from 'lodash/findIndex'; +import memoize from 'lodash/memoize'; export interface TableProps extends FormControlProps { placeholder?: string; diff --git a/src/renderers/Form/Tag.tsx b/src/renderers/Form/Tag.tsx index f909a09df..2dc0b2b42 100644 --- a/src/renderers/Form/Tag.tsx +++ b/src/renderers/Form/Tag.tsx @@ -4,8 +4,8 @@ import cx from 'classnames'; import {Action} from '../../types'; import Downshift from 'downshift'; import matchSorter from 'match-sorter'; -import debouce = require('lodash/debounce'); -import find = require('lodash/find'); +import debouce from 'lodash/debounce'; +import find from 'lodash/find'; import {Icon} from '../../components/icons'; import {Portal} from 'react-overlays'; import {findDOMNode} from 'react-dom'; diff --git a/src/renderers/Form/Text.tsx b/src/renderers/Form/Text.tsx index 2f0c4c8c3..769be3e6e 100644 --- a/src/renderers/Form/Text.tsx +++ b/src/renderers/Form/Text.tsx @@ -5,9 +5,9 @@ import {Action} from '../../types'; import Downshift, {StateChangeOptions} from 'downshift'; // @ts-ignore import matchSorter from 'match-sorter'; -import debouce = require('lodash/debounce'); +import debouce from 'lodash/debounce'; import {filter} from '../../utils/tpl'; -import find = require('lodash/find'); +import find from 'lodash/find'; import {Icon} from '../../components/icons'; import Input from '../../components/Input'; import {autobind, createObject, setVariable} from '../../utils/helper'; diff --git a/src/renderers/Form/TreeSelect.tsx b/src/renderers/Form/TreeSelect.tsx index c51b9645e..81636dabe 100644 --- a/src/renderers/Form/TreeSelect.tsx +++ b/src/renderers/Form/TreeSelect.tsx @@ -8,8 +8,8 @@ import {Icon} from '../../components/icons'; import TreeSelector from '../../components/Tree'; // @ts-ignore import matchSorter from 'match-sorter'; -import debouce = require('lodash/debounce'); -import find = require('lodash/find'); +import debouce from 'lodash/debounce'; +import find from 'lodash/find'; import {Api} from '../../types'; import {isEffectiveApi} from '../../utils/api'; diff --git a/src/renderers/Form/index.tsx b/src/renderers/Form/index.tsx index 7be8ee04f..88c2e9565 100644 --- a/src/renderers/Form/index.tsx +++ b/src/renderers/Form/index.tsx @@ -16,16 +16,16 @@ import { isVisible, cloneObject } from '../../utils/helper'; -import debouce = require('lodash/debounce'); -import flatten = require('lodash/flatten'); -import find = require('lodash/find'); +import debouce from 'lodash/debounce'; +import flatten from 'lodash/flatten'; +import find from 'lodash/find'; import Scoped, { ScopedContext, IScopedContext, ScopedComponentType } from '../../Scoped'; import {IComboStore} from '../../store/combo'; -import qs = require('qs'); +import qs from 'qs'; import {dataMapping} from '../../utils/tpl-builtin'; import {isApiOutdated, isEffectiveApi} from '../../utils/api'; import Spinner from '../../components/Spinner'; diff --git a/src/renderers/Grid.tsx b/src/renderers/Grid.tsx index 854434b49..4b132a308 100644 --- a/src/renderers/Grid.tsx +++ b/src/renderers/Grid.tsx @@ -2,7 +2,7 @@ import React from 'react'; import {Renderer, RendererProps} from '../factory'; import {Schema} from '../types'; import cx from 'classnames'; -import pick = require('lodash/pick'); +import pick from 'lodash/pick'; export const ColProps = ['lg', 'md', 'sm', 'xs']; diff --git a/src/renderers/List.tsx b/src/renderers/List.tsx index be2270981..dbb826321 100644 --- a/src/renderers/List.tsx +++ b/src/renderers/List.tsx @@ -19,7 +19,7 @@ import { import {resolveVariable} from '../utils/tpl-builtin'; import QuickEdit from './QuickEdit'; import PopOver from './PopOver'; -import Sortable = require('sortablejs'); +import Sortable from 'sortablejs'; import {TableCell} from './Table'; import Copyable from './Copyable'; diff --git a/src/renderers/PopOver.tsx b/src/renderers/PopOver.tsx index fb3308c33..201862e17 100644 --- a/src/renderers/PopOver.tsx +++ b/src/renderers/PopOver.tsx @@ -7,7 +7,7 @@ import React from 'react'; import {findDOMNode} from 'react-dom'; import {RendererProps} from '../factory'; import cx from 'classnames'; -import hoistNonReactStatic = require('hoist-non-react-statics'); +import hoistNonReactStatic from 'hoist-non-react-statics'; import {RootCloseWrapper} from 'react-overlays'; import PopOver, {Offset} from '../components/PopOver'; import Overlay from '../components/Overlay'; diff --git a/src/renderers/QRCode.tsx b/src/renderers/QRCode.tsx index 8cebbc856..596a07136 100644 --- a/src/renderers/QRCode.tsx +++ b/src/renderers/QRCode.tsx @@ -3,7 +3,7 @@ import cx from 'classnames'; import {Renderer, RendererProps} from '../factory'; import {FormItem, FormControlProps} from './Form/Item'; import {filter} from '../utils/tpl'; -import QrCode = require('qrcode.react'); +import QrCode from 'qrcode.react'; export interface QRCodeProps extends FormControlProps { codeSize?: number; diff --git a/src/renderers/QuickEdit.tsx b/src/renderers/QuickEdit.tsx index a2e98f5e6..1768340aa 100644 --- a/src/renderers/QuickEdit.tsx +++ b/src/renderers/QuickEdit.tsx @@ -5,16 +5,16 @@ import React from 'react'; import {findDOMNode} from 'react-dom'; -import find = require('lodash/find'); +import find from 'lodash/find'; import PropTypes from 'prop-types'; -import isPlainObject = require('lodash/isPlainObject'); +import isPlainObject from 'lodash/isPlainObject'; import {RendererProps} from '../factory'; import cx from 'classnames'; -import hoistNonReactStatic = require('hoist-non-react-statics'); +import hoistNonReactStatic from 'hoist-non-react-statics'; import onClickOutside from 'react-onclickoutside'; import {Action} from '../types'; import keycode from 'keycode'; -import matches = require('dom-helpers/query/matches'); +import matches from 'dom-helpers/query/matches'; import Overlay from '../components/Overlay'; import PopOver from '../components/PopOver'; diff --git a/src/renderers/Table.tsx b/src/renderers/Table.tsx index e5217a569..fdfe12309 100644 --- a/src/renderers/Table.tsx +++ b/src/renderers/Table.tsx @@ -2,7 +2,7 @@ import React from 'react'; import {findDOMNode} from 'react-dom'; import {Renderer, RendererProps} from '../factory'; import {SchemaNode, Action, Schema, Api, ApiObject} from '../types'; -import forEach = require('lodash/forEach'); +import forEach from 'lodash/forEach'; import {filter} from '../utils/tpl'; import cx from 'classnames'; import DropDownButton from './DropDownButton'; @@ -25,15 +25,15 @@ import { buildApi, normalizeApi } from '../utils/api'; -import debounce = require('lodash/debounce'); -import xor = require('lodash/xor'); +import debounce from 'lodash/debounce'; +import xor from 'lodash/xor'; import QuickEdit from './QuickEdit'; import PopOver from '../components/PopOver'; import Copyable from './Copyable'; -import Sortable = require('sortablejs'); -import flatMap = require('lodash/flatMap'); +import Sortable from 'sortablejs'; +import flatMap from 'lodash/flatMap'; import {resizeSensor} from '../utils/resize-sensor'; -import find = require('lodash/find'); +import find from 'lodash/find'; import Overlay from '../components/Overlay'; import PopOverable from './PopOver'; diff --git a/src/renderers/Tabs.tsx b/src/renderers/Tabs.tsx index 16c6d310c..f1aabfb2d 100644 --- a/src/renderers/Tabs.tsx +++ b/src/renderers/Tabs.tsx @@ -1,9 +1,9 @@ import React from 'react'; import {Renderer, RendererProps} from '../factory'; import {Action, Schema, SchemaNode} from '../types'; -import find = require('lodash/find'); +import find from 'lodash/find'; import {isVisible, autobind, isDisabled} from '../utils/helper'; -import findIndex = require('lodash/findIndex'); +import findIndex from 'lodash/findIndex'; import {Tabs as CTabs, Tab} from '../components/Tabs'; import {ClassNamesFn} from '../theme'; diff --git a/src/renderers/Tasks.tsx b/src/renderers/Tasks.tsx index 9fa48918b..74f18da43 100644 --- a/src/renderers/Tasks.tsx +++ b/src/renderers/Tasks.tsx @@ -4,7 +4,7 @@ import {ServiceStore, IServiceStore} from '../store/service'; import cx from 'classnames'; import getExprProperties from '../utils/filter-schema'; import {Api, Payload} from '../types'; -import update = require('react-addons-update'); +import update from 'react-addons-update'; import {isEffectiveApi, isApiOutdated} from '../utils/api'; import {ScopedContext, IScopedContext} from '../Scoped'; diff --git a/src/store/crud.ts b/src/store/crud.ts index 5b99c3713..ac8e8b688 100644 --- a/src/store/crud.ts +++ b/src/store/crud.ts @@ -18,7 +18,7 @@ import { } from '../utils/helper'; import {Api, Payload, fetchOptions, Action} from '../types'; import qs from 'qs'; -import pick = require('lodash/pick'); +import pick from 'lodash/pick'; import {resolveVariableAndFilter} from '../utils/tpl-builtin'; class ServerError extends Error { diff --git a/src/store/form.ts b/src/store/form.ts index d29f7a933..61f8373d1 100644 --- a/src/store/form.ts +++ b/src/store/form.ts @@ -1,5 +1,5 @@ import {types, getEnv, flow, getRoot, detach} from 'mobx-state-tree'; -import debounce = require('lodash/debounce'); +import debounce from 'lodash/debounce'; import {ServiceStore} from './service'; import {FormItemStore, IFormItemStore, SFormItemStore} from './formItem'; import {Api, fetchOptions, Payload} from '../types'; @@ -17,7 +17,7 @@ import { mapObject } from '../utils/helper'; import {IComboStore} from './combo'; -import isEqual = require('lodash/isEqual'); +import isEqual from 'lodash/isEqual'; import {IRendererStore} from '.'; export const FormStore = ServiceStore.named('FormStore') diff --git a/src/store/formItem.ts b/src/store/formItem.ts index 98e400399..103e7f83e 100644 --- a/src/store/formItem.ts +++ b/src/store/formItem.ts @@ -11,7 +11,7 @@ import {str2rules, validate as doValidate} from '../utils/validations'; import {Api, Payload, fetchOptions} from '../types'; import {ComboStore, IComboStore, IUniqueGroup} from './combo'; import {evalExpression} from '../utils/tpl'; -import findIndex = require('lodash/findIndex'); +import findIndex from 'lodash/findIndex'; import { isArrayChildrenModified, isObject, @@ -22,9 +22,9 @@ import { import {flattenTree} from '../utils/helper'; import {IRendererStore} from '.'; import {normalizeOptions, optionValueCompare} from '../components/Select'; -import find = require('lodash/find'); +import find from 'lodash/find'; import {SimpleMap} from '../utils/SimpleMap'; -import memoize = require('lodash/memoize'); +import memoize from 'lodash/memoize'; interface IOption { value?: string | number | null; diff --git a/src/store/list.ts b/src/store/list.ts index cb034f7b3..67c611214 100644 --- a/src/store/list.ts +++ b/src/store/list.ts @@ -7,8 +7,8 @@ import { getRoot } from 'mobx-state-tree'; import {iRendererStore} from './iRenderer'; -import isEqual = require('lodash/isEqual'); -import find = require('lodash/find'); +import isEqual from 'lodash/isEqual'; +import find from 'lodash/find'; import {createObject, isObject, guid} from '../utils/helper'; import {evalExpression} from '../utils/tpl'; diff --git a/src/store/table.ts b/src/store/table.ts index b7246b69c..52770cc97 100644 --- a/src/store/table.ts +++ b/src/store/table.ts @@ -10,8 +10,8 @@ import { } from 'mobx-state-tree'; import {iRendererStore} from './iRenderer'; import {resolveVariable} from '../utils/tpl-builtin'; -import isEqual = require('lodash/isEqual'); -import find = require('lodash/find'); +import isEqual from 'lodash/isEqual'; +import find from 'lodash/find'; import { isBreakpoint, createObject, diff --git a/src/theme.tsx b/src/theme.tsx index a21f84730..9e70e2833 100644 --- a/src/theme.tsx +++ b/src/theme.tsx @@ -1,7 +1,7 @@ // 主题管理 import cx from 'classnames'; import React from 'react'; -import hoistNonReactStatic = require('hoist-non-react-statics'); +import hoistNonReactStatic from 'hoist-non-react-statics'; import {ExtractProps, Omit} from './types'; export type ClassValue = diff --git a/src/utils/SimpleMap.ts b/src/utils/SimpleMap.ts index 84a279acd..214514575 100644 --- a/src/utils/SimpleMap.ts +++ b/src/utils/SimpleMap.ts @@ -1,5 +1,5 @@ -import find = require('lodash/find'); -import findIndex = require('lodash/findIndex'); +import find from 'lodash/find'; +import findIndex from 'lodash/findIndex'; export class SimpleMap { private readonly list: Array<{ diff --git a/src/utils/dom.tsx b/src/utils/dom.tsx index 10ff12c65..66dd6027b 100644 --- a/src/utils/dom.tsx +++ b/src/utils/dom.tsx @@ -1,11 +1,11 @@ import React from 'react'; import ReactDOM from 'react-dom'; -import hoistNonReactStatic = require('hoist-non-react-statics'); -import domOwnerDocument = require('dom-helpers/ownerDocument'); -import css = require('dom-helpers/style/index'); -import getOffset = require('dom-helpers/query/offset'); -import getPosition = require('dom-helpers/query/position'); -import getScrollTop = require('dom-helpers/query/scrollTop'); +import hoistNonReactStatic from 'hoist-non-react-statics'; +import domOwnerDocument from 'dom-helpers/ownerDocument'; +import css from 'dom-helpers/style/index'; +import getOffset from 'dom-helpers/query/offset'; +import getPosition from 'dom-helpers/query/position'; +import getScrollTop from 'dom-helpers/query/scrollTop'; const bsMapping: { [propName: string]: string; diff --git a/src/utils/helper.ts b/src/utils/helper.ts index c4d719fae..772c98956 100644 --- a/src/utils/helper.ts +++ b/src/utils/helper.ts @@ -1,8 +1,8 @@ -import isPlainObject = require('lodash/isPlainObject'); -import transform = require('lodash/transform'); -import isEqual = require('lodash/isEqual'); -import lodashIsObject = require('lodash/isObject'); -import uniq = require('lodash/uniq'); +import isPlainObject from 'lodash/isPlainObject'; +import transform from 'lodash/transform'; +import isEqual from 'lodash/isEqual'; +import lodashIsObject from 'lodash/isObject'; +import uniq from 'lodash/uniq'; import {Schema, PlainObject, FunctionPropertyNames} from '../types'; import {evalExpression} from './tpl'; import {boundMethod} from 'autobind-decorator'; diff --git a/src/utils/tpl-builtin.ts b/src/utils/tpl-builtin.ts index 659eb9ea7..86a6a0fb0 100644 --- a/src/utils/tpl-builtin.ts +++ b/src/utils/tpl-builtin.ts @@ -1,7 +1,7 @@ import {reigsterTplEnginer, filter} from './tpl'; import moment from 'moment'; import {PlainObject} from '../types'; -import isPlainObject = require('lodash/isPlainObject'); +import isPlainObject from 'lodash/isPlainObject'; import {createObject, isObject, setVariable, qsstringify} from './helper'; const UNITS = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']; diff --git a/src/utils/tpl-lodash.ts b/src/utils/tpl-lodash.ts index 7748c9df5..4cd20b835 100644 --- a/src/utils/tpl-lodash.ts +++ b/src/utils/tpl-lodash.ts @@ -1,5 +1,5 @@ import {reigsterTplEnginer, filter} from './tpl'; -import template = require('lodash/template'); +import template from 'lodash/template'; import {getFilters} from './tpl-builtin'; import React from 'react'; import moment from 'moment'; From d357f714b32220c2f4b65cf1019d542cdfb35536 Mon Sep 17 00:00:00 2001 From: 2betop <2betop.cn@gmail.com> Date: Mon, 2 Mar 2020 12:52:00 +0800 Subject: [PATCH 18/42] =?UTF-8?q?wizard=20=E6=B7=BB=E5=8A=A0=20reset=20?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/renderers/Wizard.tsx | 52 +++++++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/src/renderers/Wizard.tsx b/src/renderers/Wizard.tsx index 5a28d745d..ffc30c523 100644 --- a/src/renderers/Wizard.tsx +++ b/src/renderers/Wizard.tsx @@ -67,23 +67,13 @@ export default class Wizard extends React.Component { unSensor: Function; affixDom: React.RefObject = React.createRef(); footerDom: React.RefObject = React.createRef(); + initalValues: { + [propName: string]: any; + } = {}; - constructor(props: WizardProps) { - super(props); - - this.state = { - currentStep: -1 // init 完后会设置成 1 - }; - - this.handleAction = this.handleAction.bind(this); - this.handleChange = this.handleChange.bind(this); - this.handleSubmit = this.handleSubmit.bind(this); - this.handleDialogConfirm = this.handleDialogConfirm.bind(this); - this.handleDialogClose = this.handleDialogClose.bind(this); - this.formRef = this.formRef.bind(this); - this.domRef = this.domRef.bind(this); - this.getPopOverContainer = this.getPopOverContainer.bind(this); - } + state = { + currentStep: -1 // init 完后会设置成 1 + }; componentDidMount() { const { @@ -227,6 +217,7 @@ export default class Wizard extends React.Component { }); } + @autobind formRef(ref: any) { if (ref) { while (ref && ref.getWrappedInstance) { @@ -316,10 +307,12 @@ export default class Wizard extends React.Component { this.reload(); } + @autobind domRef(ref: any) { this.dom = ref; } + @autobind getPopOverContainer() { return this.dom; } @@ -357,6 +350,7 @@ export default class Wizard extends React.Component { }); } + @autobind handleAction( e: React.UIEvent | void, action: Action, @@ -425,13 +419,35 @@ export default class Wizard extends React.Component { }); } + @autobind handleChange(values: object) { const {store} = this.props; store.updateData(values); } + @autobind + handleInit(values: any) { + const step = this.state.currentStep; + this.initalValues[step] = values; + } + + @autobind + handleReset(values: any) { + const {store} = this.props; + const initalValue = this.initalValues[this.state.currentStep]; + const reseted: any = {}; + Object.keys(values).forEach(key => { + reseted[key] = initalValue.hasOwnProperty(key) + ? initalValue[key] + : undefined; + }); + + store.updateData(reseted); + } + // 接管里面 form 的提交,不能直接让 form 提交,因为 wizard 自己需要知道进度。 + @autobind handleSubmit(values: object, action: Action) { const { store, @@ -556,6 +572,7 @@ export default class Wizard extends React.Component { return false; } + @autobind handleDialogConfirm(values: object[], action: Action, targets: Array) { const {store} = this.props; @@ -571,6 +588,7 @@ export default class Wizard extends React.Component { store.closeDialog(); } + @autobind handleDialogClose() { const {store} = this.props; store.closeDialog(); @@ -768,6 +786,8 @@ export default class Wizard extends React.Component { { key: this.state.currentStep, ref: this.formRef, + onInit: this.handleInit, + onReset: this.handleReset, onSubmit: this.handleSubmit, onAction: this.handleAction, disabled: store.loading, From 90e528bfa5d3b0ae3fb980683c054cf33fad1960 Mon Sep 17 00:00:00 2001 From: 2betop <2betop.cn@gmail.com> Date: Mon, 2 Mar 2020 14:08:24 +0800 Subject: [PATCH 19/42] =?UTF-8?q?=E5=8F=AA=E8=AE=B0=E5=BD=95=E7=AC=AC?= =?UTF-8?q?=E4=B8=80=E6=AC=A1=E7=9A=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/renderers/Wizard.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/renderers/Wizard.tsx b/src/renderers/Wizard.tsx index ffc30c523..a46f068eb 100644 --- a/src/renderers/Wizard.tsx +++ b/src/renderers/Wizard.tsx @@ -429,7 +429,7 @@ export default class Wizard extends React.Component { @autobind handleInit(values: any) { const step = this.state.currentStep; - this.initalValues[step] = values; + this.initalValues[step] = this.initalValues[step] || values; } @autobind From d7f765b697c76a5c8b5c3147a80e3fc0cb131454 Mon Sep 17 00:00:00 2001 From: 2betop <2betop.cn@gmail.com> Date: Mon, 2 Mar 2020 14:18:59 +0800 Subject: [PATCH 20/42] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20requiredOn=20?= =?UTF-8?q?=E5=9C=A8=20group=20=E4=B8=AD=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/renderers/Form/Group.tsx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/renderers/Form/Group.tsx b/src/renderers/Form/Group.tsx index 3f8f9e953..cda2a4021 100644 --- a/src/renderers/Form/Group.tsx +++ b/src/renderers/Form/Group.tsx @@ -8,6 +8,7 @@ import { } from '../../utils/helper'; import cx from 'classnames'; import {FormItemWrap} from './Item'; +import getExprProperties from '../../utils/filter-schema'; export interface InputGroupProps extends RendererProps { formMode?: string; @@ -27,7 +28,7 @@ export class ControlGroupRenderer extends React.Component { } renderControl(control: any, index: any, otherProps?: any) { - const {render, disabled} = this.props; + const {render, disabled, data} = this.props; if (!control) { return null; @@ -43,6 +44,12 @@ export class ControlGroupRenderer extends React.Component { if (subSchema.control) { let control = subSchema.control as Schema; + + control = subSchema.control = { + ...control, + ...getExprProperties(control, data) + }; + control.hiddenOn && (subSchema.hiddenOn = control.hiddenOn); control.visibleOn && (subSchema.visibleOn = control.visibleOn); } From 841eb9dce1cc171f1fad991d51b6041ac49d39e2 Mon Sep 17 00:00:00 2001 From: 2betop <2betop.cn@gmail.com> Date: Mon, 2 Mar 2020 15:40:05 +0800 Subject: [PATCH 21/42] =?UTF-8?q?=E4=BC=98=E5=8C=96=20icon-picker?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scss/_variables.scss | 5 ++-- scss/components/form/_icon-picker.scss | 27 +++++++++--------- src/renderers/Form/IconPicker.tsx | 39 +++++++++----------------- 3 files changed, 29 insertions(+), 42 deletions(-) diff --git a/scss/_variables.scss b/scss/_variables.scss index 0bd7b0450..b294441a6 100644 --- a/scss/_variables.scss +++ b/scss/_variables.scss @@ -1399,13 +1399,12 @@ $Tree-inputHeight: $Form-input-height * 0.85 !default; // IconPicker $IconPicker-tabs-bg: #f0f3f4 !default; -$IconPicker-tab-padding: 0 px2rem(5px) !default; +$IconPicker-tab-padding: 0 px2rem(10px) !default; $IconPicker-tab-height: px2rem(30px) !default; $IconPicker-tab-lineHeight: px2rem(30px) !default; $IconPicker-tab-onActive-bg: $white !default; $IconPicker-content-maxHeight: px2rem(350px) !default; -$IconPicker-singleVendor-padding: px2rem(5px) 0 px2rem(5px) px2rem(13px) !default; -$IconPicker-multiVendor-padding: px2rem(35px) 0 px2rem(5px) px2rem(13px) !default; +$IconPicker-padding: px2rem(5px) !default; $IconPicker-sugItem-width: px2rem(28px) !default; $IconPicker-sugItem-height: px2rem(28px) !default; $IconPicker-sugItem-lineHeight: px2rem(28px) !default; diff --git a/scss/components/form/_icon-picker.scss b/scss/components/form/_icon-picker.scss index 1e914883b..a13a22624 100644 --- a/scss/components/form/_icon-picker.scss +++ b/scss/components/form/_icon-picker.scss @@ -45,11 +45,6 @@ } &-tabs { - position: absolute; - top: 0; - left: 0; - right: 0; - z-index: 11; background: $IconPicker-tabs-bg; } @@ -60,24 +55,19 @@ line-height: $IconPicker-tab-lineHeight; cursor: pointer; text-align: center; + font-size: $fontSizeSm; + user-select: none; &.active { background: $IconPicker-tab-onActive-bg; } } - &-singleVendor { - padding: $IconPicker-singleVendor-padding; - } - - &-multiVendor { - padding: $IconPicker-multiVendor-padding; - } - &-sugs { position: relative; + padding: $IconPicker-padding; max-height: $IconPicker-content-maxHeight; - overflow-y: scroll; + overflow-y: auto; } &-sugItem { @@ -87,6 +77,15 @@ text-align: center; line-height: $IconPicker-sugItem-lineHeight; cursor: pointer; + + &:hover { + background-color: $Form-select-menu-onHover-bg; + } + + &.is-active { + color: $white; + background-color: $Form-select-menu-onActive-color; + } } &-value { diff --git a/src/renderers/Form/IconPicker.tsx b/src/renderers/Form/IconPicker.tsx index 3689c66e9..040a7bd95 100644 --- a/src/renderers/Form/IconPicker.tsx +++ b/src/renderers/Form/IconPicker.tsx @@ -204,17 +204,10 @@ export default class IconPickerControl extends React.PureComponent< classnames: cx, name, value, - noDataTip, - formItem + noDataTip } = this.props; const options = this.formatOptions(); const vendors = this.getVendors(); - const selectedOptions = - formItem && formItem.selectedOptions.length - ? formItem.selectedOptions - : value - ? [{label: value, value: value}] - : []; return ( option['value'])} + selectedItem={[value]} > - {({getInputProps, getItemProps, isOpen, inputValue, selectedItem}) => { + {({getInputProps, getItemProps, isOpen, inputValue}) => { let filteredOptions = inputValue && isOpen ? matchSorter(options, inputValue, {keys: ['label', 'value']}) : options; - filteredOptions = filteredOptions.filter( - (option: any) => !~selectedItem.indexOf(option.value) - ); return (
- {placeholder && - !selectedOptions.length && - !this.state.inputValue ? ( + {placeholder && !value && !this.state.inputValue ? (
{placeholder}
) : null} - {selectedOptions.map((option: Option, index: number) => - inputValue && isOpen ? null : ( -
- - {option.label} -
- ) + {!value || (inputValue && isOpen) ? null : ( +
+ + {value} +
)} @@ -305,7 +292,9 @@ export default class IconPickerControl extends React.PureComponent<
From 70f936bcb941b5ef60187d5519da409921dd880a Mon Sep 17 00:00:00 2001 From: 2betop <2betop.cn@gmail.com> Date: Mon, 2 Mar 2020 16:01:49 +0800 Subject: [PATCH 22/42] =?UTF-8?q?contextmenu=20=E5=8F=AF=E4=BB=A5=E6=94=BE?= =?UTF-8?q?=E5=9C=A8=E9=9D=9E=E9=A1=B6=E7=BA=A7=E5=AE=B9=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scss/components/_context-menu.scss | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scss/components/_context-menu.scss b/scss/components/_context-menu.scss index c1076f4bd..a14bdc59f 100644 --- a/scss/components/_context-menu.scss +++ b/scss/components/_context-menu.scss @@ -26,6 +26,11 @@ } .#{$ns}ContextMenu { + position: fixed; + left: 0; + top: 0; + // pointer-events: none; + &-menu { position: absolute; z-index: $zindex-contextmenu; From 5dedf50a792f6179e6e68ad6d72ee2208b49b71a Mon Sep 17 00:00:00 2001 From: 2betop <2betop.cn@gmail.com> Date: Tue, 3 Mar 2020 15:59:31 +0800 Subject: [PATCH 23/42] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20picker=20=E8=AF=BB?= =?UTF-8?q?=E5=8F=96=E9=80=89=E9=A1=B9=E6=8E=A5=E5=8F=A3=E4=B8=8D=E6=89=A7?= =?UTF-8?q?=E8=A1=8C=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scss/components/_context-menu.scss | 1 + src/renderers/Form/Picker.tsx | 8 +++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/scss/components/_context-menu.scss b/scss/components/_context-menu.scss index a14bdc59f..951490190 100644 --- a/scss/components/_context-menu.scss +++ b/scss/components/_context-menu.scss @@ -26,6 +26,7 @@ } .#{$ns}ContextMenu { + z-index: $zindex-contextmenu; position: fixed; left: 0; top: 0; diff --git a/src/renderers/Form/Picker.tsx b/src/renderers/Form/Picker.tsx index ba9794664..2470b3a5c 100644 --- a/src/renderers/Form/Picker.tsx +++ b/src/renderers/Form/Picker.tsx @@ -92,13 +92,15 @@ export default class PickerControl extends React.PureComponent< fetchOptions() { const {value, formItem, valueField, labelField, source, data} = this.props; + let selectedOptions: any; if ( !source || !formItem || - !formItem.selectedOptions.length || - formItem.selectedOptions[0][valueField || 'value'] !== - formItem.selectedOptions[0][labelField || 'label'] + ((selectedOptions = formItem.getSelectedOptions(value)) && + (!selectedOptions.length || + selectedOptions[0][valueField || 'value'] !== + selectedOptions[0][labelField || 'label'])) ) { return; } From 53044ac090c6fc9b12b615a818ecdcedea9cc5db Mon Sep 17 00:00:00 2001 From: 2betop <2betop.cn@gmail.com> Date: Tue, 3 Mar 2020 16:56:18 +0800 Subject: [PATCH 24/42] =?UTF-8?q?dialog=20=E4=B8=AD=20affixTop=20=E7=9A=84?= =?UTF-8?q?=E5=81=8F=E7=A7=BB=E9=87=8F=E8=AE=BE=E7=BD=AE=E4=B8=BA0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/renderers/Dialog.tsx | 3 ++- src/renderers/Table.tsx | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/renderers/Dialog.tsx b/src/renderers/Dialog.tsx index dbc145a68..9dee4adbf 100644 --- a/src/renderers/Dialog.tsx +++ b/src/renderers/Dialog.tsx @@ -300,7 +300,8 @@ export default class Dialog extends React.Component { key, disabled: (body && (body as any).disabled) || store.loading, onAction: this.handleAction, - onFinished: this.handleChildFinished + onFinished: this.handleChildFinished, + affixOffsetTop: 0 }; if (!(body as Schema).type) { diff --git a/src/renderers/Table.tsx b/src/renderers/Table.tsx index fdfe12309..0db4f989b 100644 --- a/src/renderers/Table.tsx +++ b/src/renderers/Table.tsx @@ -524,7 +524,8 @@ export default class Table extends React.Component { const ns = this.props.classPrefix; const dom = findDOMNode(this) as HTMLElement; const clip = (this.table as HTMLElement).getBoundingClientRect(); - const offsetY = this.props.env.affixOffsetTop || 0; + const offsetY = + this.props.affixOffsetTop ?? this.props.env.affixOffsetTop ?? 0; const affixed = clip.top < offsetY && clip.top + clip.height - 40 > offsetY; const affixedDom = dom.querySelector(`.${ns}Table-fixedTop`) as HTMLElement; From 5220eef98f944c0070c49eb2846291d9c38368d5 Mon Sep 17 00:00:00 2001 From: 2betop <2betop.cn@gmail.com> Date: Tue, 3 Mar 2020 19:30:35 +0800 Subject: [PATCH 25/42] =?UTF-8?q?contextmenu=20=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/ContextMenu.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/ContextMenu.tsx b/src/components/ContextMenu.tsx index 8301bc2d1..e241aa0e6 100644 --- a/src/components/ContextMenu.tsx +++ b/src/components/ContextMenu.tsx @@ -68,7 +68,9 @@ export class ContextMenu extends React.Component< }; menuRef: React.RefObject = React.createRef(); + originInstance: this | null; componentWillMount() { + this.originInstance = ContextMenu.instance; ContextMenu.instance = this; } @@ -78,9 +80,10 @@ export class ContextMenu extends React.Component< } componentWillUnmount() { - ContextMenu.instance = null; + ContextMenu.instance = this.originInstance; // document.body.removeEventListener('click', this.handleOutClick, true); document.removeEventListener('keydown', this.handleKeyDown); + delete this.originInstance; } @autobind From 2cb260429bc4b2ba21b5e392bae6757ec1036b6d Mon Sep 17 00:00:00 2001 From: 2betop <2betop.cn@gmail.com> Date: Tue, 3 Mar 2020 19:38:14 +0800 Subject: [PATCH 26/42] =?UTF-8?q?=E6=96=87=E6=A1=88=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/renderers/Form/FormItem.md | 130 ++++++++++++++++---------------- 1 file changed, 65 insertions(+), 65 deletions(-) diff --git a/docs/renderers/Form/FormItem.md b/docs/renderers/Form/FormItem.md index e23a5ba93..3f886b382 100644 --- a/docs/renderers/Form/FormItem.md +++ b/docs/renderers/Form/FormItem.md @@ -2,74 +2,74 @@ Form 中主要是由各种 FormItem 组成。FormItem 中主要包含这些字段。 -- `name` 字段名,表单提交时的 key。 -- `value` 值,可以通过它设置默认值。 -- `label` 描述标题,当表单为水平布局时,左边即便是不设置 label 为了保持对齐也会留空,如果想要去掉空白,请设置成 `false`。 -- `description` 描述内容。 -- `placeholder` 占位内容。 -- `type` 指定表单类型,如: `text`、`textarea`、`date`、`email`等等 -- `inline` 是否为 inline 模式。 -- `submitOnChange` 是否该表单项值发生变化时就提交当前表单。 -- `className` 表单最外层类名。 -- `disabled` 当前表单项是否是禁用状态。 -- `disabledOn` 通过[表达式](../Types.md#表达式)来配置当前表单项的禁用状态。 -- `visible` 是否可见。 -- `visibleOn` 通过[表达式](../Types.md#表达式)来配置当前表单项是否显示。 -- `hidden` 是否隐藏,不要跟 `visible` `visibleOn` 同时配置 -- `hiddenOn` 通过[表达式](../Types.md#表达式)来配置当前表单项是否隐藏。 -- `inputClassName` 表单控制器类名。 -- `labelClassName` label 的类名。 -- `required` 是否为必填。 -- `requiredOn` 通过[表达式](../Types.md#表达式)来配置当前表单项是否为必填。 -- `validations` 格式验证,支持设置多个,多个规则用英文逗号隔开。 +- `name` 字段名,表单提交时的 key。 +- `value` 值,可以通过它设置默认值。 +- `label` 描述标题,当表单为水平布局时,左边即便是不设置 label 为了保持对齐也会留空,如果想要去掉空白,请设置成 `false`。 +- `description` 描述内容。 +- `placeholder` 占位内容。 +- `type` 指定表单类型,如: `text`、`textarea`、`date`、`email`等等 +- `inline` 是否为 inline 模式。 +- `submitOnChange` 是否该表单项值发生变化时就提交当前表单。 +- `className` 表单最外层类名。 +- `disabled` 当前表单项是否是禁用状态。 +- `disabledOn` 通过[表达式](../Types.md#表达式)来配置当前表单项的禁用状态。 +- `visible` 是否可见。 +- `visibleOn` 通过[表达式](../Types.md#表达式)来配置当前表单项是否显示。 +- `hidden` 是否隐藏,不要跟 `visible` `visibleOn` 同时配置 +- `hiddenOn` 通过[表达式](../Types.md#表达式)来配置当前表单项是否隐藏。 +- `inputClassName` 表单控制器类名。 +- `labelClassName` label 的类名。 +- `required` 是否为必填。 +- `requiredOn` 通过[表达式](../Types.md#表达式)来配置当前表单项是否为必填。 +- `validations` 格式验证,支持设置多个,多个规则用英文逗号隔开。 - - `isEmptyString` 必须是空白字符。 - - `isEmail` 必须是 Email。 - - `isUrl` 必须是 Url。 - - `isNumeric` 必须是 数值。 - - `isAlpha` 必须是 字母。 - - `isAlphanumeric` 必须是 字母或者数字。 - - `isInt` 必须是 整形。 - - `isFloat` 必须是 浮点形。 - - `isLength:length` 是否长度正好等于设定值。 - - `minLength:length` 最小长度。 - - `maxLength:length` 最大长度。 - - `maximum:length` 最大值。 - - `minimum:length` 最小值。 - - `equals:xxx` 当前值必须完全等于 xxx。 - - `equalsField:xxx` 当前值必须与 xxx 变量值一致。 - - `isJson` 是否是合法的 Json 字符串。 - - `notEmptyString` 要求输入内容不是空白。 - - `isUrlPath` 是 url 路径。 - - `matchRegexp:/foo/` 必须命中某个正则。 - - `matchRegexp1:/foo/` 必须命中某个正则。 - - `matchRegexp2:/foo/` 必须命中某个正则。 - - `matchRegexp3:/foo/` 必须命中某个正则。 - - `matchRegexp4:/foo/` 必须命中某个正则。 - 如: - - ```js - { - "validations": "isNumeric,minimum:10", - - // 或者对象配置方式, 推荐 - "validations": { - "isNumeric": true, - "minimum": 10 - } - } - ``` - -- `validationErrors` 自定义错误提示, 配置为对象, key 为规则名, value 为错误提示字符串(提示:其中`$1`表示输入) + - `isEmptyString` 必须是空白字符。 + - `isEmail` 必须是 Email。 + - `isUrl` 必须是 Url。 + - `isNumeric` 必须是 数值。 + - `isAlpha` 必须是 字母。 + - `isAlphanumeric` 必须是 字母或者数字。 + - `isInt` 必须是 整形。 + - `isFloat` 必须是 浮点形。 + - `isLength:length` 是否长度正好等于设定值。 + - `minLength:length` 最小长度。 + - `maxLength:length` 最大长度。 + - `maximum:number` 最大值。 + - `minimum:number` 最小值。 + - `equals:xxx` 当前值必须完全等于 xxx。 + - `equalsField:xxx` 当前值必须与 xxx 变量值一致。 + - `isJson` 是否是合法的 Json 字符串。 + - `notEmptyString` 要求输入内容不是空白。 + - `isUrlPath` 是 url 路径。 + - `matchRegexp:/foo/` 必须命中某个正则。 + - `matchRegexp1:/foo/` 必须命中某个正则。 + - `matchRegexp2:/foo/` 必须命中某个正则。 + - `matchRegexp3:/foo/` 必须命中某个正则。 + - `matchRegexp4:/foo/` 必须命中某个正则。 如: - ```json - { - "validationErrors": { - "isEmail": "请输入正确的邮箱地址" - } + + ```js + { + "validations": "isNumeric,minimum:10", + + // 或者对象配置方式, 推荐 + "validations": { + "isNumeric": true, + "minimum": 10 } - ``` -- `validateOnChange` 是否修改就验证数值,默认当表单提交过就会每次修改验证,如果要关闭请设置为 `false`,即便是关了,表单提交前还是会验证的。 + } + ``` + +- `validationErrors` 自定义错误提示, 配置为对象, key 为规则名, value 为错误提示字符串(提示:其中`$1`表示输入) + 如: + ```json + { + "validationErrors": { + "isEmail": "请输入正确的邮箱地址" + } + } + ``` +- `validateOnChange` 是否修改就验证数值,默认当表单提交过就会每次修改验证,如果要关闭请设置为 `false`,即便是关了,表单提交前还是会验证的。 ```schema:height="200" scope="form-item" { From 51b4e655123ce7001451e062ed69e15e9e77472b Mon Sep 17 00:00:00 2001 From: 2betop <2betop.cn@gmail.com> Date: Wed, 4 Mar 2020 13:50:43 +0800 Subject: [PATCH 27/42] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=BC=B9=E6=A1=86?= =?UTF-8?q?=E4=BD=8D=E7=BD=AE=E6=A3=80=E6=B5=8B=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/dom.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/dom.tsx b/src/utils/dom.tsx index 66dd6027b..b8c5dabf0 100644 --- a/src/utils/dom.tsx +++ b/src/utils/dom.tsx @@ -198,8 +198,8 @@ export function calculatePosition( // 如果还有其他可选项,则做位置判断,是否在可视区域,不完全在则继续看其他定位情况。 if (tests.length) { const transformed = { - x: clip.x + positionLeft / scale - childOffset.left, - y: clip.y + positionTop / scale - childOffset.top, + x: clip.x + positionLeft / scale, + y: clip.y + positionTop / scale, width: overlayWidth, height: overlayHeight }; From 5d1a9318ec1fbd2532d6fd52fb0b5a90cbf19864 Mon Sep 17 00:00:00 2001 From: 2betop <2betop.cn@gmail.com> Date: Wed, 4 Mar 2020 16:42:09 +0800 Subject: [PATCH 28/42] =?UTF-8?q?=E5=BC=B9=E5=87=BA=E4=BD=8D=E7=BD=AE?= =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/ColorPicker.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/components/ColorPicker.tsx b/src/components/ColorPicker.tsx index cc1eb4bc3..8c214e39a 100644 --- a/src/components/ColorPicker.tsx +++ b/src/components/ColorPicker.tsx @@ -264,9 +264,7 @@ export class ColorControl extends React.PureComponent< {isOpened ? ( findDOMNode(this)} onHide={this.close} container={popOverContainer || (() => findDOMNode(this))} From 2357a53caa30f45c06de46ce100ad670a9c50898 Mon Sep 17 00:00:00 2001 From: 2betop <2betop.cn@gmail.com> Date: Wed, 4 Mar 2020 17:52:08 +0800 Subject: [PATCH 29/42] =?UTF-8?q?confirm=20=E6=94=AF=E6=8C=81=E6=8C=87?= =?UTF-8?q?=E5=AE=9A=E7=A1=AE=E8=AE=A4=E6=96=87=E5=AD=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Alert.tsx | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/components/Alert.tsx b/src/components/Alert.tsx index 7e061a5c1..f959f61a1 100644 --- a/src/components/Alert.tsx +++ b/src/components/Alert.tsx @@ -26,6 +26,7 @@ export interface AlertState { title?: string; content: string; confirm: boolean; + confirmText?: string; } export class Alert extends React.Component { @@ -115,12 +116,13 @@ export class Alert extends React.Component { }); } - confirm(content: string, title?: string) { + confirm(content: string, title?: string, confirmText?: string) { this.setState({ title, content, show: true, - confirm: true + confirm: true, + confirmText }); return new Promise(resolve => { @@ -169,7 +171,7 @@ export class Alert extends React.Component { level={this.state.confirm ? confirmBtnLevel : alertBtnLevel} onClick={this.handleConfirm} > - {confirmText} + {this.state.confirm || confirmText}
@@ -181,9 +183,11 @@ export const alert: (content: string, title?: string) => void = ( content, title ) => Alert.getInstance().alert(content, title); -export const confirm: (content: string, title?: string) => Promise = ( - content, - title -) => Alert.getInstance().confirm(content, title); +export const confirm: ( + content: string, + title?: string, + confirmText?: string +) => Promise = (content, title) => + Alert.getInstance().confirm(content, title, confirmText); export const ThemedAlert = themeable(Alert); export default ThemedAlert; From 9eba9c4d96d4ca8424fe9d77a923e6ecec65a948 Mon Sep 17 00:00:00 2001 From: 2betop <2betop.cn@gmail.com> Date: Wed, 4 Mar 2020 17:56:56 +0800 Subject: [PATCH 30/42] =?UTF-8?q?confirm=20=E6=94=AF=E6=8C=81=E6=8C=87?= =?UTF-8?q?=E5=AE=9A=E7=A1=AE=E8=AE=A4=E6=96=87=E5=AD=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Alert.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Alert.tsx b/src/components/Alert.tsx index f959f61a1..faa7a5b70 100644 --- a/src/components/Alert.tsx +++ b/src/components/Alert.tsx @@ -187,7 +187,7 @@ export const confirm: ( content: string, title?: string, confirmText?: string -) => Promise = (content, title) => +) => Promise = (content, title, confirmText) => Alert.getInstance().confirm(content, title, confirmText); export const ThemedAlert = themeable(Alert); export default ThemedAlert; From 363814e0b4b35fd53a8f916364afaa9791b504ff Mon Sep 17 00:00:00 2001 From: 2betop <2betop.cn@gmail.com> Date: Wed, 4 Mar 2020 17:58:12 +0800 Subject: [PATCH 31/42] =?UTF-8?q?confirm=20=E6=94=AF=E6=8C=81=E6=8C=87?= =?UTF-8?q?=E5=AE=9A=E7=A1=AE=E8=AE=A4=E6=96=87=E5=AD=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/Alert.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Alert.tsx b/src/components/Alert.tsx index faa7a5b70..958efd428 100644 --- a/src/components/Alert.tsx +++ b/src/components/Alert.tsx @@ -171,7 +171,7 @@ export class Alert extends React.Component { level={this.state.confirm ? confirmBtnLevel : alertBtnLevel} onClick={this.handleConfirm} > - {this.state.confirm || confirmText} + {this.state.confirmText || confirmText}
From d212362e6e9129d7380f1f2e8c5d90b6fd348a45 Mon Sep 17 00:00:00 2001 From: 2betop <2betop.cn@gmail.com> Date: Wed, 4 Mar 2020 20:37:18 +0800 Subject: [PATCH 32/42] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E8=87=AA=E5=AE=9A?= =?UTF-8?q?=E4=B9=89=20dataFilter?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/renderers/Chart.tsx | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/renderers/Chart.tsx b/src/renderers/Chart.tsx index a55db2dd6..9805a3843 100644 --- a/src/renderers/Chart.tsx +++ b/src/renderers/Chart.tsx @@ -14,6 +14,7 @@ import {ScopedContext, IScopedContext} from '../Scoped'; export interface ChartProps extends RendererProps { chartRef?: (echart: any) => void; onDataFilter?: (config: any) => any; + dataFilter?: string; api?: Api; source?: string; config?: object; @@ -193,13 +194,22 @@ export class Chart extends React.Component { if (!this.echarts) { return; } - const onDataFilter = this.props.onDataFilter; + let onDataFilter = this.props.onDataFilter; + const dataFilter = this.props.dataFilter; + + if (!onDataFilter && typeof dataFilter === 'string') { + onDataFilter = new Function('config', 'echarts', dataFilter) as any; + } config = config || this.pending; if (typeof config === 'string') { config = new Function('return ' + config)(); } - onDataFilter && (config = onDataFilter(config) || config); + try { + onDataFilter && (config = onDataFilter(config) || config); + } catch (e) { + console.warn(e); + } if (config) { try { From 26b4f63fe0fd79e9f563e1f57435d2db8ce7edda Mon Sep 17 00:00:00 2001 From: 2betop <2betop.cn@gmail.com> Date: Wed, 4 Mar 2020 20:38:08 +0800 Subject: [PATCH 33/42] =?UTF-8?q?=E5=BF=98=E4=BA=86=E4=BC=A0=20echarts=20?= =?UTF-8?q?=E5=AF=B9=E8=B1=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/renderers/Chart.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/renderers/Chart.tsx b/src/renderers/Chart.tsx index 9805a3843..b23556557 100644 --- a/src/renderers/Chart.tsx +++ b/src/renderers/Chart.tsx @@ -206,7 +206,7 @@ export class Chart extends React.Component { config = new Function('return ' + config)(); } try { - onDataFilter && (config = onDataFilter(config) || config); + onDataFilter && (config = onDataFilter(config, this.echarts) || config); } catch (e) { console.warn(e); } From 904864cb47ee34602f1a4efcdfc9e70603fa3236 Mon Sep 17 00:00:00 2001 From: 2betop <2betop.cn@gmail.com> Date: Wed, 4 Mar 2020 20:41:19 +0800 Subject: [PATCH 34/42] =?UTF-8?q?=E8=A1=A5=E5=85=85=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/renderers/Chart.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/renderers/Chart.tsx b/src/renderers/Chart.tsx index b23556557..55c446bce 100644 --- a/src/renderers/Chart.tsx +++ b/src/renderers/Chart.tsx @@ -13,7 +13,7 @@ import {ScopedContext, IScopedContext} from '../Scoped'; export interface ChartProps extends RendererProps { chartRef?: (echart: any) => void; - onDataFilter?: (config: any) => any; + onDataFilter?: (config: any, echarts: any) => any; dataFilter?: string; api?: Api; source?: string; From 96cfb18c9fc26ecb0b0091a6fa7afeffbafe7905 Mon Sep 17 00:00:00 2001 From: 2betop <2betop.cn@gmail.com> Date: Thu, 5 Mar 2020 14:57:16 +0800 Subject: [PATCH 35/42] =?UTF-8?q?store=20=E6=8A=A5=E9=94=99=E5=A4=84?= =?UTF-8?q?=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/renderers/Form/File.tsx | 1 + src/renderers/Form/index.tsx | 9 ++++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/renderers/Form/File.tsx b/src/renderers/Form/File.tsx index 100ac7683..c2769d3c0 100644 --- a/src/renderers/Form/File.tsx +++ b/src/renderers/Form/File.tsx @@ -424,6 +424,7 @@ export default class FileControl extends React.Component { newFile.error = error; } else { newFile = obj as FileValue; + newFile.name = newFile.name || file!.name; } files.splice(idx, 1, newFile); this.current = null; diff --git a/src/renderers/Form/index.tsx b/src/renderers/Form/index.tsx index 88c2e9565..361c5be51 100644 --- a/src/renderers/Form/index.tsx +++ b/src/renderers/Form/index.tsx @@ -328,6 +328,9 @@ export default class Form extends React.Component { async onInit() { const {onInit, store, submitOnInit} = this.props; + if (!isAlive(store)) { + return; + } // 先拿出来数据,主要担心 form 被什么东西篡改了,然后又应用出去了 // 之前遇到过问题,所以拿出来了。但是 options loadOptions 默认值失效了。 @@ -339,7 +342,11 @@ export default class Form extends React.Component { const hooks: Array<(data: any) => Promise> = this.hooks['init'] || []; await Promise.all(hooks.map(hook => hook(data))); - if (isAlive(store) && store.initedAt !== initedAt) { + if (!isAlive(store)) { + return; + } + + if (store.initedAt !== initedAt) { // 说明,之前的数据已经失效了。 // 比如 combo 一开始设置了初始值,然后 form 的 initApi 又返回了新的值。 // 这个时候 store 的数据应该已经 init 了新的值。但是 data 还是老的,这个时候 From b4c98198ca5b33b5d8eaab513047d2331dba0dd8 Mon Sep 17 00:00:00 2001 From: 2betop <2betop.cn@gmail.com> Date: Thu, 5 Mar 2020 18:36:58 +0800 Subject: [PATCH 36/42] =?UTF-8?q?=E4=BC=A0=E9=94=99=E4=BA=86=E5=AF=B9?= =?UTF-8?q?=E8=B1=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/renderers/Chart.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/renderers/Chart.tsx b/src/renderers/Chart.tsx index 55c446bce..ebea5a814 100644 --- a/src/renderers/Chart.tsx +++ b/src/renderers/Chart.tsx @@ -206,7 +206,8 @@ export class Chart extends React.Component { config = new Function('return ' + config)(); } try { - onDataFilter && (config = onDataFilter(config, this.echarts) || config); + onDataFilter && + (config = onDataFilter(config, (window as any).echarts) || config); } catch (e) { console.warn(e); } From 965296f9c3714ec6368f55c8406d539f70f7c467 Mon Sep 17 00:00:00 2001 From: 2betop <2betop.cn@gmail.com> Date: Thu, 5 Mar 2020 20:12:42 +0800 Subject: [PATCH 37/42] =?UTF-8?q?=E6=8D=A2=E6=88=90=20svg=20icon?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scss/components/_alert.scss | 2 -- src/components/Alert2.tsx | 3 ++- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/scss/components/_alert.scss b/scss/components/_alert.scss index 0c0fdb8a3..ca46f5cc2 100644 --- a/scss/components/_alert.scss +++ b/scss/components/_alert.scss @@ -13,8 +13,6 @@ background: transparent; border: 0; float: right; - font-size: 21px; - font-weight: 700; line-height: 1; color: #000; text-shadow: 0 1px 0 #fff; diff --git a/src/components/Alert2.tsx b/src/components/Alert2.tsx index 1b3025d63..f028067e3 100644 --- a/src/components/Alert2.tsx +++ b/src/components/Alert2.tsx @@ -5,6 +5,7 @@ import React from 'react'; import {ClassNamesFn, themeable} from '../theme'; +import {Icon} from './icons'; export interface AlertProps { level: 'danger' | 'info' | 'success' | 'warning'; @@ -70,7 +71,7 @@ export class Alert extends React.Component { onClick={this.handleClick} type="button" > - × + ) : null} {children} From 7cfea508978004446236e7e5ed887145bcabe92d Mon Sep 17 00:00:00 2001 From: 2betop <2betop.cn@gmail.com> Date: Thu, 5 Mar 2020 20:36:07 +0800 Subject: [PATCH 38/42] =?UTF-8?q?card=20=E6=94=AF=E6=8C=81=20avtarText?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scss/components/_card.scss | 15 +++++++++++++++ src/renderers/Card.tsx | 18 +++++++++++++++--- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/scss/components/_card.scss b/scss/components/_card.scss index 68b8377e5..fd2ad89aa 100644 --- a/scss/components/_card.scss +++ b/scss/components/_card.scss @@ -66,6 +66,21 @@ } } + &-avtarText { + background-color: $primary; + color: $white; + width: 50px; + height: 50px; + line-height: 50px; + text-align: center; + vertical-align: middle; + border-radius: 500px; + float: left; + margin-right: $gap-base; + font-size: $fontSizeXl; + text-transform: uppercase(); + } + &-meta { display: block; height: 100%; diff --git a/src/renderers/Card.tsx b/src/renderers/Card.tsx index 703495fdd..ca7774da8 100644 --- a/src/renderers/Card.tsx +++ b/src/renderers/Card.tsx @@ -280,9 +280,12 @@ export class Card extends React.Component { subTitleClassName, descClassName, checkOnItemClick, + avatarClassName, checkable, classnames: cx, - classPrefix: ns + classPrefix: ns, + imageClassName, + avatarTextClassName } = this.props; let heading = null; @@ -291,8 +294,7 @@ export class Card extends React.Component { const { highlight: highlightTpl, avatar: avatarTpl, - avatarClassName, - imageClassName, + avatarText: avatarTextTpl, title: titleTpl, subTitle: subTitleTpl, subTitlePlaceholder, @@ -302,6 +304,7 @@ export class Card extends React.Component { const highlight = !!evalExpression(highlightTpl, data as object); const avatar = filter(avatarTpl, data); + const avatarText = filter(avatarTextTpl, data); const title = filter(titleTpl, data); const subTitle = filter(subTitleTpl, data); const desc = filter(descTpl, data); @@ -323,6 +326,15 @@ export class Card extends React.Component { src={avatar} /> + ) : avatarText ? ( + + {avatarText} + ) : null}
{highlight ? ( From 2d6c92446451ee3a10237ba00927c5198cbc8eba Mon Sep 17 00:00:00 2001 From: 2betop <2betop.cn@gmail.com> Date: Fri, 6 Mar 2020 12:40:08 +0800 Subject: [PATCH 39/42] Merge remote-tracking branch 'baidu/master' --- docs/renderers/Types.md | 9 ++++--- src/renderers/Form/Image.tsx | 2 -- src/renderers/Form/Matrix.tsx | 9 +++---- src/renderers/Form/Table.tsx | 4 +-- src/renderers/Tasks.tsx | 4 +-- src/store/crud.ts | 20 ++++++++------ src/store/form.ts | 21 ++++++++------- src/store/iRenderer.ts | 6 ++--- src/store/service.ts | 50 +++++++++++++++++++++++++---------- src/types.ts | 1 + src/utils/helper.ts | 22 +++++++++------ 11 files changed, 91 insertions(+), 57 deletions(-) diff --git a/docs/renderers/Types.md b/docs/renderers/Types.md index 16bdd87db..ebca16ed2 100644 --- a/docs/renderers/Types.md +++ b/docs/renderers/Types.md @@ -49,11 +49,11 @@ Api 类型可以是字符串或者对象。API 中可以直接设置数据发送 - `` 可以是: `get`、`post`、`put`、`delete`或者`raw` - `` 即 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; 发送适配器,支持字符串串格式,或者直接就是函数如: ``` diff --git a/src/renderers/Form/Image.tsx b/src/renderers/Form/Image.tsx index 0f42ac8ed..4f52859b2 100644 --- a/src/renderers/Form/Image.tsx +++ b/src/renderers/Form/Image.tsx @@ -487,8 +487,6 @@ export default class ImageControl extends React.Component< } editImage(index: number) { - const {multiple} = this.props; - const files = this.files; this.setState({ diff --git a/src/renderers/Form/Matrix.tsx b/src/renderers/Form/Matrix.tsx index 7a6db5090..e363b8de3 100644 --- a/src/renderers/Form/Matrix.tsx +++ b/src/renderers/Form/Matrix.tsx @@ -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(); diff --git a/src/renderers/Form/Table.tsx b/src/renderers/Form/Table.tsx index 3bece2067..d4b91087e 100644 --- a/src/renderers/Form/Table.tsx +++ b/src/renderers/Form/Table.tsx @@ -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 { return; } else if (remote && remote.ok) { item = { - ...item, + ...((isNew ? addApi : updateApi) as ApiObject).replaceData ? {} : item, ...remote.data }; } diff --git a/src/renderers/Tasks.tsx b/src/renderers/Tasks.tsx index 74f18da43..38efedaa2 100644 --- a/src/renderers/Tasks.tsx +++ b/src/renderers/Tasks.tsx @@ -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 { const items = this.state.items.map(item => item.key === ret.data.key ? { - ...item, + ...((api as ApiObject).replaceData ? {} : item), ...ret.data } : item diff --git a/src/store/crud.ts b/src/store/crud.ts index ac8e8b688..a1a4ed7f4 100644 --- a/src/store/crud.ts +++ b/src/store/crud.ts @@ -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 = 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 = 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(); } diff --git a/src/store/form.ts b/src/store/form.ts index 61f8373d1..e4ab987f3 100644 --- a/src/store/form.ts +++ b/src/store/form.ts @@ -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 = 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(); } diff --git a/src/store/iRenderer.ts b/src/store/iRenderer.ts index b420f42f3..b0796de69 100644 --- a/src/store/iRenderer.ts +++ b/src/store/iRenderer.ts @@ -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', { diff --git a/src/store/service.ts b/src/store/service.ts index afd8c6773..2e01c82b3 100644 --- a/src/store/service.ts +++ b/src/store/service.ts @@ -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 = 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 = 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 = 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 = 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 = 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); diff --git a/src/types.ts b/src/types.ts index 500965bf5..9a4b81bfc 100644 --- a/src/types.ts +++ b/src/types.ts @@ -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; diff --git a/src/utils/helper.ts b/src/utils/helper.ts index 772c98956..eccd28a17 100644 --- a/src/utils/helper.ts +++ b/src/utils/helper.ts @@ -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; } From bf75028e61cdf1ef9142f3f7c0bf440a83779969 Mon Sep 17 00:00:00 2001 From: 2betop <2betop.cn@gmail.com> Date: Fri, 6 Mar 2020 14:37:26 +0800 Subject: [PATCH 40/42] =?UTF-8?q?=E5=9B=BE=E7=89=87=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E6=98=AF=E5=90=A6=E9=87=8D=E6=96=B0=E8=A3=81=E5=89=AA=E7=9A=84?= =?UTF-8?q?=E5=BC=80=E5=85=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scss/components/_images.scss | 2 +- src/renderers/Form/Image.tsx | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/scss/components/_images.scss b/scss/components/_images.scss index 607769ee9..3a00e5e44 100644 --- a/scss/components/_images.scss +++ b/scss/components/_images.scss @@ -26,7 +26,7 @@ position: absolute; left: 50%; top: 50%; - height: 100%; + max-height: 100%; width: auto; transform: translate(-50%, -50%); } diff --git a/src/renderers/Form/Image.tsx b/src/renderers/Form/Image.tsx index 4f52859b2..2a4b6fa61 100644 --- a/src/renderers/Form/Image.tsx +++ b/src/renderers/Form/Image.tsx @@ -31,6 +31,7 @@ export interface ImageProps extends FormControlProps { aspectRatio?: number; aspectRatioLabel?: string; }; + reCropable: boolean; crop?: | boolean | { @@ -879,7 +880,8 @@ export default class ImageControl extends React.Component< autoUpload, hideUploadButton, thumbMode, - thumbRatio + thumbRatio, + reCropable } = this.props; const {files, error, crop, uploading, cropFile} = this.state; @@ -1072,7 +1074,9 @@ export default class ImageControl extends React.Component< - {!!crop && !disabled ? ( + {!!crop && + reCropable !== false && + !disabled ? ( Date: Fri, 6 Mar 2020 17:43:52 +0800 Subject: [PATCH 41/42] =?UTF-8?q?equals=20=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/tpl-builtin.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/utils/tpl-builtin.ts b/src/utils/tpl-builtin.ts index 86a6a0fb0..901a90c61 100644 --- a/src/utils/tpl-builtin.ts +++ b/src/utils/tpl-builtin.ts @@ -244,11 +244,10 @@ export const filters: { ? RegExp.$2 : resolveVariable(arg1, this as any) : ''; - // 比对的值是空时直接返回。 - if (!arg1) { + if (arg1 !== undefined && arg1 !== null) { return input; } - fn = value => arg1 == value; + fn = value => arg1 === value; } else { if (directive !== 'match') { directive = 'match'; From 01a8b8293a87655cfeabdeb16eb8d8e2f8bc4336 Mon Sep 17 00:00:00 2001 From: 2betop <2betop.cn@gmail.com> Date: Fri, 6 Mar 2020 17:49:12 +0800 Subject: [PATCH 42/42] =?UTF-8?q?=E4=BC=98=E5=8C=96=20equals=20=E7=9A=84?= =?UTF-8?q?=E5=88=A4=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/tpl-builtin.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/utils/tpl-builtin.ts b/src/utils/tpl-builtin.ts index 901a90c61..bef7f9302 100644 --- a/src/utils/tpl-builtin.ts +++ b/src/utils/tpl-builtin.ts @@ -244,10 +244,7 @@ export const filters: { ? RegExp.$2 : resolveVariable(arg1, this as any) : ''; - if (arg1 !== undefined && arg1 !== null) { - return input; - } - fn = value => arg1 === value; + fn = value => arg1 == value; } else { if (directive !== 'match') { directive = 'match';