优化 types 问题

This commit is contained in:
liaoxuezhi 2019-11-07 00:07:26 +08:00
parent f5c65fa004
commit ea8370e6b0
7 changed files with 121 additions and 43 deletions

View File

@ -13,7 +13,8 @@ import {RendererEnv, RendererProps} from './factory';
import {noop, autobind, qsstringify} from './utils/helper'; import {noop, autobind, qsstringify} from './utils/helper';
import {RendererData, Action} from './types'; import {RendererData, Action} from './types';
interface ScopedComponentType extends React.Component<RendererProps> { export interface ScopedComponentType extends React.Component<RendererProps> {
focus?: () =>void;
doAction?: (action: Action, data: RendererData, throwErrors?: boolean) => void; doAction?: (action: Action, data: RendererData, throwErrors?: boolean) => void;
receive?: (values: RendererData, subPath?: string) => void; receive?: (values: RendererData, subPath?: string) => void;
reload?: (subPath?: string, query?: RendererData | null, ctx?: RendererData) => void; reload?: (subPath?: string, query?: RendererData | null, ctx?: RendererData) => void;

View File

@ -156,6 +156,7 @@ interface SelectProps {
checkAllLabel?: string; checkAllLabel?: string;
defaultCheckAll?: boolean; defaultCheckAll?: boolean;
simpleValue?: boolean; simpleValue?: boolean;
} }
interface SelectState { interface SelectState {

View File

@ -10,7 +10,7 @@ import {Schema} from '../../types';
import {IIRendererStore} from '../../store'; import {IIRendererStore} from '../../store';
import {ScopedContext, IScopedContext} from '../../Scoped'; import {ScopedContext, IScopedContext} from '../../Scoped';
export interface FormControlProps extends RendererProps { export interface ControlProps extends RendererProps {
control: { control: {
id?: string; id?: string;
name?: string; name?: string;
@ -36,13 +36,13 @@ export interface FormControlProps extends RendererProps {
removeHook: (fn: () => any) => void; removeHook: (fn: () => any) => void;
} }
export default class FormControl extends React.Component<FormControlProps, any> { export default class FormControl extends React.Component<ControlProps> {
public model: IFormItemStore | undefined; public model: IFormItemStore | undefined;
control: any; control: any;
hook?: () => any; hook?: () => any;
hook2?: () => any; hook2?: () => any;
static defaultProps: Partial<FormControlProps> = {}; static defaultProps: Partial<ControlProps> = {};
lazyValidate: Function; lazyValidate: Function;
componentWillMount() { componentWillMount() {
@ -134,7 +134,7 @@ export default class FormControl extends React.Component<FormControlProps, any>
} }
} }
componentWillReceiveProps(nextProps: FormControlProps) { componentWillReceiveProps(nextProps: ControlProps) {
const props = this.props; const props = this.props;
const form = nextProps.formStore; const form = nextProps.formStore;
@ -204,7 +204,7 @@ export default class FormControl extends React.Component<FormControlProps, any>
} }
} }
componentDidUpdate(prevProps: FormControlProps) { componentDidUpdate(prevProps: ControlProps) {
const { const {
store, store,
formStore: form, formStore: form,

View File

@ -1,11 +1,12 @@
import React from 'react'; import React from 'react';
import hoistNonReactStatic = require('hoist-non-react-statics'); import hoistNonReactStatic = require('hoist-non-react-statics');
import {IFormItemStore} from '../../store/form'; import {IFormItemStore, IFormStore} from '../../store/form';
import {reaction} from 'mobx'; import {reaction} from 'mobx';
import {RendererProps, registerRenderer, TestFunc, RendererConfig, HocStoreFactory} from '../../factory'; import {RendererProps, registerRenderer, TestFunc, RendererConfig, HocStoreFactory} from '../../factory';
import {anyChanged, ucFirst, getWidthRate} from '../../utils/helper'; import {anyChanged, ucFirst, getWidthRate} from '../../utils/helper';
import {observer} from 'mobx-react'; import {observer} from 'mobx-react';
import {FormHorizontal, FormSchema} from '.';
export interface FormItemBasicConfig extends Partial<RendererConfig> { export interface FormItemBasicConfig extends Partial<RendererConfig> {
type?: string; type?: string;
@ -26,28 +27,40 @@ export interface FormItemBasicConfig extends Partial<RendererConfig> {
validate?: (values: any, value: any) => string | boolean; validate?: (values: any, value: any) => string | boolean;
} }
export interface FormControlProps extends RendererProps { export interface FormItemState {
// error string isFocused: boolean;
error?: string; }
inputOnly?: boolean;
// error 详情
errors?: {
[propName: string]: string;
};
export interface FormItemProps extends RendererProps {
name?: string;
formStore?: IFormStore;
formInited: boolean;
formMode: 'normal' | 'horizontal' | 'inline' | 'row' | 'default';
formHorizontal: FormHorizontal;
defaultSize?: 'xs' | 'sm' | 'md' | 'lg' | 'full';
size?: 'xs' | 'sm' | 'md' | 'lg' | 'full';
disabled: boolean;
btnDisabled: boolean;
defaultValue: any; defaultValue: any;
value: any; value: any;
onChange: (value: any, submitOnChange?: boolean) => void;
onBulkChange: (values: any, submitOnChange?: boolean) => void;
prinstine: any; prinstine: any;
setPrinstineValue: (value: any) => void; setPrinstineValue: (value: any) => void;
formMode?: 'default' | 'inline' | 'horizontal' | 'row'; onChange: (value: any, submitOnChange?: boolean) => void;
formItem?: IFormItemStore; onBulkChange: (values: {[propName: string]: any}, submitOnChange?: boolean) => void;
strictMode?: boolean; addHook: (fn: Function, mode?: 'validate' | 'init') => void;
removeHook: (fn: Function, mode?: 'validate' | 'init') => void;
renderFormItems: (schema: FormSchema, region: string, props: any) => JSX.Element;
onFocus: (e: any) => void;
onBlur: (e: any) => void;
renderControl?: (props: RendererProps) => JSX.Element; formItemValue: any; // 不建议使用 为了兼容 v1
getValue: () => any; // 不建议使用 为了兼容 v1
setValue: (value: any, key: string) => void; // 不建议使用 为了兼容 v1
inputClassName?: string;
renderControl?: (props: FormControlProps) => JSX.Element;
inputOnly?: boolean;
renderLabel?: boolean; renderLabel?: boolean;
renderDescription?: boolean; renderDescription?: boolean;
sizeMutable?: boolean; sizeMutable?: boolean;
@ -55,23 +68,43 @@ export interface FormControlProps extends RendererProps {
hint?: string; hint?: string;
description?: string; description?: string;
descriptionClassName?: string; descriptionClassName?: string;
// error 详情
errors?: {
[propName: string]: string;
};
// error string
error?: string;
} }
export interface FormControlState { export type FormControlProps = RendererProps &
isFocused: boolean; Exclude<
} FormItemProps,
| 'inputClassName'
| 'renderControl'
| 'defaultSize'
| 'size'
| 'error'
| 'errors'
| 'hint'
| 'descriptionClassName'
| 'inputOnly'
| 'renderLabel'
| 'renderDescription'
| 'sizeMutable'
| 'wrap'
>;
export type FormItemComponent = React.ComponentType<FormControlProps>; export type FormItemComponent = React.ComponentType<FormItemProps>;
export type FormControlComponent = React.ComponentType<FormControlProps>; export type FormControlComponent = React.ComponentType<FormControlProps>;
export interface FormItemConfig extends FormItemBasicConfig { export interface FormItemConfig extends FormItemBasicConfig {
component: FormControlComponent; component: FormControlComponent;
} }
export class FormItemWrap extends React.Component<FormControlProps, FormControlState> { export class FormItemWrap extends React.Component<FormItemProps, FormItemState> {
reaction: any; reaction: any;
constructor(props: FormControlProps) { constructor(props: FormItemProps) {
super(props); super(props);
this.state = { this.state = {
@ -603,7 +636,7 @@ export function registerFormItem(config: FormItemConfig): RendererConfig {
ref: any; ref: any;
constructor(props: FormControlProps) { constructor(props: FormItemProps) {
super(props); super(props);
this.refFn = this.refFn.bind(this); this.refFn = this.refFn.bind(this);
} }

View File

@ -1,4 +1,4 @@
import {Api} from '../../types'; import {Api, Schema} from '../../types';
import {buildApi, isEffectiveApi, isValidApi, isApiOutdated} from '../../utils/api'; import {buildApi, isEffectiveApi, isValidApi, isApiOutdated} from '../../utils/api';
import {anyChanged} from '../../utils/helper'; import {anyChanged} from '../../utils/helper';
import {reaction} from 'mobx'; import {reaction} from 'mobx';
@ -30,15 +30,33 @@ export interface OptionsControlProps extends FormControlProps, OptionProps {
setOptions: (value: Array<any>) => void; setOptions: (value: Array<any>) => void;
setLoading: (value: boolean) => void; setLoading: (value: boolean) => void;
reloadOptions: () => void; reloadOptions: () => void;
addable?: boolean;
onAdd?: () => void;
editable?: boolean;
onEdit?: (value: Option) => void;
removable?: boolean;
onDelete?: (value: Option) => void;
}
export interface OptionsProps extends FormControlProps, OptionProps {
sourcce?: Api;
addApi?: Api;
addMode?: 'dialog' | 'normal';
addDialog?: Schema;
editApi?: Api;
editMode?: 'dialog' | 'normal';
editDialog?: Schema;
deleteApi?: Api;
deleteConfirmText?: string;
} }
export function registerOptionsControl(config: OptionsConfig) { export function registerOptionsControl(config: OptionsConfig) {
const Control = config.component; const Control = config.component;
// @observer // @observer
class FormOptionsItem extends React.Component<FormControlProps, any> { class FormOptionsItem extends React.Component<OptionsProps, any> {
static displayName = `OptionsControl(${config.type})`; static displayName = `OptionsControl(${config.type})`;
static defaultProps: Partial<FormControlProps> = { static defaultProps = {
delimiter: ',', delimiter: ',',
labelField: 'label', labelField: 'label',
valueField: 'value', valueField: 'value',
@ -55,7 +73,7 @@ export function registerOptionsControl(config: OptionsConfig) {
reaction: any; reaction: any;
input: any; input: any;
constructor(props: FormControlProps) { constructor(props: OptionsProps) {
super(props); super(props);
const formItem = props.formItem as IFormItemStore; const formItem = props.formItem as IFormItemStore;
@ -114,7 +132,7 @@ export function registerOptionsControl(config: OptionsConfig) {
this.normalizeValue(); this.normalizeValue();
} }
shouldComponentUpdate(nextProps: FormControlProps) { shouldComponentUpdate(nextProps: OptionsProps) {
if (config.strictMode === false || nextProps.strictMode === false) { if (config.strictMode === false || nextProps.strictMode === false) {
return true; return true;
} }
@ -156,7 +174,7 @@ export function registerOptionsControl(config: OptionsConfig) {
return false; return false;
} }
componentWillReceiveProps(nextProps: OptionsControlProps) { componentWillReceiveProps(nextProps: OptionsProps) {
const props = this.props; const props = this.props;
const formItem = nextProps.formItem as IFormItemStore; const formItem = nextProps.formItem as IFormItemStore;

View File

@ -11,7 +11,7 @@ import {promisify, difference, until, noop, isObject, isVisible} from '../../uti
import debouce = require('lodash/debounce'); import debouce = require('lodash/debounce');
import flatten = require('lodash/flatten'); import flatten = require('lodash/flatten');
import find = require('lodash/find'); import find = require('lodash/find');
import Scoped, {ScopedContext, IScopedContext} from '../../Scoped'; import Scoped, {ScopedContext, IScopedContext, ScopedComponentType} from '../../Scoped';
import {IComboStore} from '../../store/combo'; import {IComboStore} from '../../store/combo';
import qs = require('qs'); import qs = require('qs');
import {dataMapping} from '../../utils/tpl-builtin'; import {dataMapping} from '../../utils/tpl-builtin';
@ -145,7 +145,7 @@ export default class Form extends React.Component<FormProps, object> {
asyncCancel: () => void; asyncCancel: () => void;
disposeOnValidate: () => void; disposeOnValidate: () => void;
shouldLoadInitApi: boolean = false; shouldLoadInitApi: boolean = false;
timer: number; timer: NodeJS.Timeout;
mounted: boolean; mounted: boolean;
constructor(props: FormProps) { constructor(props: FormProps) {
super(props); super(props);
@ -940,8 +940,8 @@ export class FormRenderer extends Form {
if (this.props.autoFocus) { if (this.props.autoFocus) {
const scoped = this.context as IScopedContext; const scoped = this.context as IScopedContext;
const inputs = scoped.getComponents(); const inputs = scoped.getComponents();
let focuableInput = find(inputs, (input: any) => input.focus); let focuableInput = find(inputs, input => input.focus) as ScopedComponentType;
focuableInput && setTimeout(() => focuableInput.focus(), 200); focuableInput && setTimeout(() => focuableInput.focus!(), 200);
} }
} }

View File

@ -5,7 +5,7 @@ import {Api, Payload, fetchOptions} from '../types';
import {ComboStore, IComboStore, IUniqueGroup} from './combo'; import {ComboStore, IComboStore, IUniqueGroup} from './combo';
import {evalExpression} from '../utils/tpl'; import {evalExpression} from '../utils/tpl';
import findIndex = require('lodash/findIndex'); import findIndex = require('lodash/findIndex');
import {isArrayChilrenModified, hasOwnProperty, isObject} from '../utils/helper'; import {isArrayChilrenModified, hasOwnProperty, isObject, createObject} from '../utils/helper';
import {flattenTree} from '../utils/helper'; import {flattenTree} from '../utils/helper';
import {IRendererStore} from '.'; import {IRendererStore} from '.';
import {normalizeOptions} from '../components/Select'; import {normalizeOptions} from '../components/Select';
@ -50,7 +50,10 @@ export const FormItemStore = types
options: types.optional(types.array(types.frozen()), []), options: types.optional(types.array(types.frozen()), []),
expressionsInOptions: false, expressionsInOptions: false,
selectedOptions: types.optional(types.frozen(), []), selectedOptions: types.optional(types.frozen(), []),
filteredOptions: types.optional(types.frozen(), []) filteredOptions: types.optional(types.frozen(), []),
dialogSchema: types.frozen(),
dialogOpen: false,
dialogData: types.frozen(),
}) })
.views(self => { .views(self => {
function getForm(): any { function getForm(): any {
@ -532,6 +535,26 @@ export const FormItemStore = types
clearError(); clearError();
} }
function openDialog(schema: any, ctx: any, additonal?: object) {
let proto = ctx.__super ? ctx.__super : self.form.data;
if (additonal) {
proto = createObject(proto, additonal);
}
const data = createObject(proto, {
...ctx
});
self.dialogSchema = schema;
self.dialogData = data;
self.dialogOpen = true;
}
function closeDialog() {
self.dialogOpen = false;
}
return { return {
config, config,
changeValue, changeValue,
@ -544,7 +567,9 @@ export const FormItemStore = types
syncOptions, syncOptions,
setLoading, setLoading,
setSubStore, setSubStore,
reset reset,
openDialog,
closeDialog
}; };
}); });