diff --git a/src/components/formFields/any/index.tsx b/src/components/formFields/any/index.tsx index b0f9666c86cd2e1fac2b1e91939a9c0dedd0751a..ad029b2c1164e02244fddb265657abd0659dd836 100644 --- a/src/components/formFields/any/index.tsx +++ b/src/components/formFields/any/index.tsx @@ -93,6 +93,7 @@ export default class AnyField extends Field : ( @@ -109,6 +110,7 @@ export default class AnyField extends Field : diff --git a/src/components/formFields/common.tsx b/src/components/formFields/common.tsx index b5c5c7e5a90ea7fd81a91cbb25677987bd6d8131..4d6814e5e4081257869a0c2e98719a1994d0e192 100644 --- a/src/components/formFields/common.tsx +++ b/src/components/formFields/common.tsx @@ -92,6 +92,8 @@ export interface FieldProps { onValueListAppend: (path: string, value: any, validation: true | FieldError[]) => Promise // 事件:修改值 - 列表 - 删除 onValueListSplice: (path: string, index: number, count: number, validation: true | FieldError[]) => Promise + // 事件:修改值 - 列表 - 修改顺序 + onValueListSort: (path: string, index: number, sortType: 'up' | 'down', validation: true | FieldError[]) => Promise baseRoute: string, loadDomain: (domain: string) => Promise } diff --git a/src/components/formFields/form/index.tsx b/src/components/formFields/form/index.tsx index d57ede7d03d740d0332260f80d07f74aa8c0b171..ca01bb30cef4d42c69960a20e7c6a711c155d08c 100644 --- a/src/components/formFields/form/index.tsx +++ b/src/components/formFields/form/index.tsx @@ -1,7 +1,7 @@ import React from 'react' import { Field, FieldConfig, FieldConfigs, FieldError, FieldProps, IField } from '../common' import getALLComponents from '../' -import { getValue } from '../../../util/value' +import { getValue, listItemMove } from '../../../util/value' import { cloneDeep } from 'lodash' import ConditionHelper from '../../../util/condition' @@ -14,19 +14,27 @@ export interface FormFieldConfig extends FieldConfig { initialValues?: any // 新增子项时的默认值 mode?: 'show' // 子项仅显示列表 modeValue?: string + canInsert?: boolean + canRemove?: boolean + canSort?: boolean + canCollapse?: boolean // 是否用Collapse折叠展示 } export interface IFormField { insertText: string - onInsert: () => Promise + onInsert?: () => Promise + canCollapse?: boolean children: React.ReactNode[] } export interface IFormFieldItem { index: number + isLastIndex: boolean title: string removeText: string - onRemove: () => Promise + onRemove?: () => Promise + onSort?: (sortType: 'up' | 'down') => Promise + canCollapse?: boolean children: React.ReactNode[] } @@ -204,6 +212,15 @@ export default class FormField extends Field { + const formDataList = listItemMove(cloneDeep(this.state.formDataList), index, sortType) + this.setState({ + formDataList + }) + this.formFieldsMountedList = listItemMove(this.formFieldsMountedList, index, sortType) + await this.props.onValueListSort('', index, sortType, true) + } handleChange = async (index: number, formFieldIndex: number, value: any) => { // const formField = this.formItemsList[index][formFieldIndex] @@ -308,6 +325,24 @@ export default class FormField extends Field { + const formFieldConfig = (this.props.config.fields || [])[formFieldIndex] + if (formFieldConfig) { + const fullPath = formFieldConfig.field === '' || path === '' ? `${formFieldConfig.field}${path}` : `${formFieldConfig.field}.${path}` + await this.props.onValueListSort(`[${index}]${fullPath}`, _index, sortType, true) + + const formDataList = cloneDeep(this.state.formDataList) + if (validation === true) { + formDataList[index][formFieldIndex] = { status: 'normal' } + } else { + formDataList[index][formFieldIndex] = { status: 'error', message: validation[0].message } + } + + this.setState({ + formDataList + }) + } + } /** * 用于展示子表单组件中的每一子项中的每一个子表单项组件 @@ -353,7 +388,11 @@ export default class FormField extends Field await this.handleInsert(), + onInsert: canInsert? async () => await this.handleInsert(): undefined, + canCollapse, children: ( (Array.isArray(value) ? value : []).map((itemValue: any, index: number) => { return {this.renderItemComponent({ index, + isLastIndex: value.length - 1 === index? true: false, title: primaryField !== undefined ? getValue(itemValue, primaryField) : index.toString(), removeText: removeText === undefined ? `删除 ${label}` : removeText, - onRemove: async () => await this.handleRemove(index), + onRemove: canRemove? async () => await this.handleRemove(index): undefined, + onSort: canSort? async (sortType: 'up' | 'down') => await this.handleSort(index, sortType): undefined, + canCollapse, children: (fields || []).map((formFieldConfig, fieldIndex) => { if (!ConditionHelper(formFieldConfig.condition, { record: itemValue, data: this.props.data, step: this.props.step })) { return null @@ -408,6 +451,7 @@ export default class FormField extends Field this.handleValueUnset(index, fieldIndex, path, validation)} onValueListAppend={async (path, value, validation) => this.handleValueListAppend(index, fieldIndex, path, value, validation)} onValueListSplice={async (path, _index, count, validation) => this.handleValueListSplice(index, fieldIndex, path, _index, count, validation)} + onValueListSort={async (path, _index, sortType, validation) => await this.handleValueListSort(index, fieldIndex, path, _index, sortType, validation)} baseRoute={this.props.baseRoute} loadDomain={async (domain: string) => await this.props.loadDomain(domain)} /> diff --git a/src/components/formFields/group/index.tsx b/src/components/formFields/group/index.tsx index 1826dcbbed806b702f780287526523070f2e8849..03c50eec96db9e9c025001b6f6e39e51284e7ebd 100644 --- a/src/components/formFields/group/index.tsx +++ b/src/components/formFields/group/index.tsx @@ -228,6 +228,25 @@ export default class GroupField extends Field { + const formFieldConfig = (this.props.config.fields || [])[formFieldIndex] + if (formFieldConfig) { + const fullPath = formFieldConfig.field === '' || path === '' ? `${formFieldConfig.field}${path}` : `${formFieldConfig.field}.${path}` + await this.props.onValueListSort(fullPath, index, sortType, true) + + const formData = cloneDeep(this.state.formData) + if (validation === true) { + formData[formFieldIndex] = { status: 'normal' } + } else { + formData[formFieldIndex] = { status: 'error', message: validation[0].message } + } + + this.setState({ + formData + }) + } + } + renderComponent = (props: IGroupField) => { return 您当前使用的UI版本没有实现GroupField组件。 @@ -305,6 +324,7 @@ export default class GroupField extends Field this.handleValueUnset(formFieldIndex, path, validation)} onValueListAppend={async (path, value, validation) => this.handleValueListAppend(formFieldIndex, path, value, validation)} onValueListSplice={async (path, index, count, validation) => this.handleValueListSplice(formFieldIndex, path, index, count, validation)} + onValueListSort={async (path, index, sortType, validation) => this.handleValueListSort(formFieldIndex, path, index, sortType, validation)} baseRoute={this.props.baseRoute} loadDomain={async (domain: string) => await this.props.loadDomain(domain)} /> diff --git a/src/components/formFields/importSubform/index.tsx b/src/components/formFields/importSubform/index.tsx index f211cd3b5b89f7597964d57af64744128aaedece..0a446a0c97872d3d50407b331bd59034333c335d 100644 --- a/src/components/formFields/importSubform/index.tsx +++ b/src/components/formFields/importSubform/index.tsx @@ -246,7 +246,24 @@ export default class ImportSubformField extends Field { + const formFieldConfig = (this.state.fields || [])[formFieldIndex] + if (formFieldConfig) { + const fullPath = formFieldConfig.field === '' || path === '' ? `${formFieldConfig.field}${path}` : `${formFieldConfig.field}.${path}` + await this.props.onValueListSort(fullPath, index, sortType, true) + + const formData = cloneDeep(this.state.formData) + if (validation === true) { + formData[formFieldIndex] = { status: 'normal' } + } else { + formData[formFieldIndex] = { status: 'error', message: validation[0].message } + } + this.setState({ + formData + }) + } + } renderComponent = (props: IImportSubformField) => { return 您当前使用的UI版本没有实现ImportSubformField组件。 @@ -340,6 +357,7 @@ export default class ImportSubformField extends Field this.handleValueUnset(formFieldIndex, path, validation)} onValueListAppend={async (path, value, validation) => this.handleValueListAppend(formFieldIndex, path, value, validation)} onValueListSplice={async (path, index, count, validation) => this.handleValueListSplice(formFieldIndex, path, index, count, validation)} + onValueListSort={async (path, index, sortType, validation) => this.handleValueListSort(formFieldIndex, path, index, sortType, validation)} baseRoute={this.props.baseRoute} loadDomain={async (domain: string) => await this.props.loadDomain(domain)} /> diff --git a/src/components/formFields/object/index.tsx b/src/components/formFields/object/index.tsx index 42179c946e864979bdf5c3a000b792aad6e45d00..e9ad5c3403eafdd824c598584c05d0b5d9f30b69 100644 --- a/src/components/formFields/object/index.tsx +++ b/src/components/formFields/object/index.tsx @@ -320,6 +320,25 @@ export default class ObjectField extends Field { + const formFieldConfig = (this.props.config.fields || [])[formFieldIndex] + if (formFieldConfig) { + const fullPath = formFieldConfig.field === '' || path === '' ? `${formFieldConfig.field}${path}` : `${formFieldConfig.field}.${path}` + await this.props.onValueListSort(fullPath === '' ? key : `${key}.${fullPath}`, _index, sortType, true) + + const formDataList = cloneDeep(this.state.formDataList) + if (validation === true) { + formDataList[key][formFieldIndex] = { status: 'normal' } + } else { + formDataList[key][formFieldIndex] = { status: 'error', message: validation[0].message } + } + + this.setState({ + formDataList + }) + } + } + /** * 用于展示子表单组件 * @param _props @@ -428,6 +447,7 @@ export default class ObjectField extends Field this.handleValueUnset(key, formFieldIndex, path, validation)} onValueListAppend={async (path, value, validation) => this.handleValueListAppend(key, formFieldIndex, path, value, validation)} onValueListSplice={async (path, _index, count, validation) => this.handleValueListSplice(key, formFieldIndex, path, _index, count, validation)} + onValueListSort={async (path, _index, sortType, validation) => this.handleValueListSort(key, formFieldIndex, path, _index, sortType, validation)} baseRoute={this.props.baseRoute} loadDomain={async (domain: string) => this.props.loadDomain(domain)} /> diff --git a/src/components/formFields/tabs/index.tsx b/src/components/formFields/tabs/index.tsx index dee32136d5dc6af1d68d19be4081b4c280f10be5..21615d57c366a123554f7999669be65433471a57 100644 --- a/src/components/formFields/tabs/index.tsx +++ b/src/components/formFields/tabs/index.tsx @@ -282,6 +282,29 @@ export default class TabsField extends Field { + const tab = (this.props.config.tabs || [])[index] + + const fields = this.props.config.mode === 'same' ? (this.props.config.fields || []) : (((this.props.config.tabs || [])[index] || {}).fields || []) + const formFieldConfig = fields[formFieldIndex] + if (formFieldConfig) { + const fieldPath = formFieldConfig.field === '' || path === '' ? `${formFieldConfig.field}${path}` : `${formFieldConfig.field}.${path}` + const fullPath = tab.field === '' || fieldPath === '' ? `${tab.field}${fieldPath}` : `${tab.field}.${fieldPath}` + await this.props.onValueListSort(fullPath, _index, sortType, true) + + const formDataList = cloneDeep(this.state.formDataList) + if (!formDataList[index]) formDataList[index] = [] + if (validation === true) { + formDataList[index][formFieldIndex] = { status: 'normal' } + } else { + formDataList[index][formFieldIndex] = { status: 'error', message: validation[0].message } + } + + this.setState({ + formDataList + }) + } + } /** * 用于展示子表单组件 @@ -385,6 +408,7 @@ export default class TabsField extends Field this.handleValueUnset(index, formFieldIndex, path, validation)} onValueListAppend={async (path, value, validation) => this.handleValueListAppend(index, formFieldIndex, path, value, validation)} onValueListSplice={async (path, _index, count, validation) => this.handleValueListSplice(index, formFieldIndex, path, _index, count, validation)} + onValueListSort={async (path, _index, sortType, validation) => this.handleValueListSort(index, formFieldIndex, path, _index, sortType, validation)} baseRoute={this.props.baseRoute} loadDomain={async (domain: string) => await this.props.loadDomain(domain)} /> diff --git a/src/steps/filter/index.tsx b/src/steps/filter/index.tsx index 05bc4f677c96a51181cdef419e15657707286243..c6cd09cbee7587ffce9eadd63d422c9e9c6d712f 100644 --- a/src/steps/filter/index.tsx +++ b/src/steps/filter/index.tsx @@ -6,7 +6,7 @@ import { ParamConfig } from '../../interface' import ParamHelper from '../../util/param' import { cloneDeep, get, set, unset } from 'lodash' import ConditionHelper from '../../util/condition' -import { getValue, setValue } from '../../util/value' +import { getValue, setValue, listItemMove } from '../../util/value' /** * 表单步骤配置文件格式定义 @@ -381,6 +381,31 @@ export default class FilterStep extends Step { }) } } + handleValueListSort = async (formFieldIndex: number, path: string, index: number, sortType: 'up' | 'down', validation: true | FieldError[]) => { + const formFieldConfig = (this.props.config.fields || [])[formFieldIndex] + if (formFieldConfig) { + const fullPath = formFieldConfig.field === '' || path === '' ? `${formFieldConfig.field}${path}` : `${formFieldConfig.field}.${path}` + + const list = listItemMove(get(this.formValue, fullPath, []), index, sortType) + set(this.formValue, fullPath, list) + this.setState({ + formValue: this.formValue + }) + if (this.props.onChange) { + this.props.onChange(this.formValue) + } + + if (validation === true) { + this.formData[formFieldIndex] = { status: 'normal' } + } else { + this.formData[formFieldIndex] = { status: 'error', message: validation[0].message } + } + + await this.setState({ + formData: cloneDeep(this.formData) + }) + } + } /** * 表单步骤组件 - UI渲染方法 @@ -472,6 +497,7 @@ export default class FilterStep extends Step { onValueUnset={async (path, validation) => await this.handleValueUnset(formFieldIndex, path, validation)} onValueListAppend={async (path, value, validation) => await this.handleValueListAppend(formFieldIndex, path, value, validation)} onValueListSplice={async (path, index, count, validation) => await this.handleValueListSplice(formFieldIndex, path, index, count, validation)} + onValueListSort={async (path, index, sortType, validation) => await this.handleValueListSort(formFieldIndex, path, index, sortType, validation)} baseRoute={this.props.baseRoute} loadDomain={async (domain: string) => await this.props.loadDomain(domain)} /> diff --git a/src/steps/form/index.tsx b/src/steps/form/index.tsx index 8eeb22380f3b02df082f4ee49e77f7c60d834b5f..320cfc2f4f8e77b2e8c44911766cc4da117486c6 100644 --- a/src/steps/form/index.tsx +++ b/src/steps/form/index.tsx @@ -2,7 +2,7 @@ import React from 'react' import { Field, FieldConfigs, FieldError } from '../../components/formFields/common' import Step, { StepConfig, StepProps } from '../common' import getALLComponents from '../../components/formFields' -import { getValue, setValue } from '../../util/value' +import { getValue, setValue, listItemMove } from '../../util/value' import { ParamConfig } from '../../interface' import ParamHelper from '../../util/param' import { cloneDeep, get, set, unset } from 'lodash' @@ -318,7 +318,8 @@ export default class FormStep extends Step { if (formFieldConfig) { const fullPath = formFieldConfig.field === '' || path === '' ? `${formFieldConfig.field}${path}` : `${formFieldConfig.field}.${path}` - const list = get(this.formValue, fullPath, []) + let list = get(this.formValue, fullPath, []) + if (!Array.isArray(list)) list = [] list.push(value) set(this.formValue, fullPath, list) this.setState({ @@ -366,6 +367,31 @@ export default class FormStep extends Step { }) } } + handleValueListSort = async (formFieldIndex: number, path: string, index: number, sortType: 'up' | 'down', validation: true | FieldError[]) => { + const formFieldConfig = (this.props.config.fields || [])[formFieldIndex] + if (formFieldConfig) { + const fullPath = formFieldConfig.field === '' || path === '' ? `${formFieldConfig.field}${path}` : `${formFieldConfig.field}.${path}` + + const list = listItemMove(get(this.formValue, fullPath, []), index, sortType) + set(this.formValue, fullPath, list) + this.setState({ + formValue: this.formValue + }) + if (this.props.onChange) { + this.props.onChange(this.formValue) + } + + if (validation === true) { + this.formData[formFieldIndex] = { status: 'normal', name: formFieldConfig.label } + } else { + this.formData[formFieldIndex] = { status: 'error', message: validation[0].message, name: formFieldConfig.label } + } + + await this.setState({ + formData: cloneDeep(this.formData) + }) + } + } /** * 表单步骤组件 - UI渲染方法 @@ -470,6 +496,7 @@ export default class FormStep extends Step { onValueUnset={async (path, validation) => await this.handleValueUnset(formFieldIndex, path, validation)} onValueListAppend={async (path, value, validation) => await this.handleValueListAppend(formFieldIndex, path, value, validation)} onValueListSplice={async (path, index, count, validation) => await this.handleValueListSplice(formFieldIndex, path, index, count, validation)} + onValueListSort={async (path, index, sortType, validation) => await this.handleValueListSort(formFieldIndex, path, index, sortType, validation)} baseRoute={this.props.baseRoute} loadDomain={async (domain: string) => await this.props.loadDomain(domain)} /> diff --git a/src/util/value.ts b/src/util/value.ts index 8588af3c471e75f0ee8abc1138e1f918e6b50a35..f10cbd719e3f65a78f8dcf5b619e7f2cc8f5c9ee 100644 --- a/src/util/value.ts +++ b/src/util/value.ts @@ -13,15 +13,15 @@ export const getValue = (obj: any, path: string = '', defaultValue: any = undefi } const merge = (a: any, b: any): any => { - return assignInWith(a, b, (a,b) => { + return assignInWith(a, b, (a, b) => { if (isUndefined(a) && isArray(b)) { a = [] } if (isObject(b)) { if (isArray(a)) { - return merge(a,b).filter((i: any) => i !== undefined) + return merge(a, b).filter((i: any) => i !== undefined) } else { - return merge(a,b) + return merge(a, b) } } }) @@ -103,3 +103,21 @@ export const getBoolean = (value: any) => { } return false } + +/** + * 处理list元素上移、下移 + * @param list list + * @param currentIndex 当前操作元素在list索引 + * @param sortType up或down + */ +export const listItemMove = (list: any[], currentIndex: number, sortType: 'up' | 'down') => { + switch (sortType) { + case 'up': + currentIndex !== 0 && (list[currentIndex] = list.splice(currentIndex - 1, 1, list[currentIndex])[0]) + break; + case 'down': + currentIndex < list.length - 1 && (list[currentIndex] = list.splice(currentIndex + 1, 1, list[currentIndex])[0]) + break; + } + return list +}