From 362162d897b67712be885dadd5d2bf6ec23f2a89 Mon Sep 17 00:00:00 2001 From: zhenjintao Date: Thu, 20 Jan 2022 19:22:08 +0800 Subject: [PATCH 01/23] =?UTF-8?q?feat:=20hidden=E3=80=81group=E3=80=81form?= =?UTF-8?q?=E3=80=81tabs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/detail/importSubform/index.tsx | 27 +- src/components/formFields/form/display.tsx | 344 +++++++++++++++++ src/components/formFields/group/display.tsx | 277 ++++++++++++++ src/components/formFields/hidden/display.tsx | 5 + .../formFields/importSubform/display.tsx | 272 +++++++++++++ src/components/formFields/index.tsx | 12 +- src/components/formFields/tabs/display.tsx | 362 ++++++++++++++++++ src/index.tsx | 5 + 8 files changed, 1295 insertions(+), 9 deletions(-) create mode 100644 src/components/formFields/form/display.tsx create mode 100644 src/components/formFields/group/display.tsx create mode 100644 src/components/formFields/hidden/display.tsx create mode 100644 src/components/formFields/importSubform/display.tsx create mode 100644 src/components/formFields/tabs/display.tsx diff --git a/src/components/detail/importSubform/index.tsx b/src/components/detail/importSubform/index.tsx index d56f6ab..5b0e44f 100644 --- a/src/components/detail/importSubform/index.tsx +++ b/src/components/detail/importSubform/index.tsx @@ -151,16 +151,11 @@ export default class ImportSubformField extends DetailField } - render = () => { + getConfigData=() => { const { config, - formLayout, - value, - record, - data, - step + value } = this.props - if (config.configFrom && config.configFrom.type === 'interface' && config.configFrom.interface) { this.interfaceHelper.request( config.configFrom.interface, @@ -187,7 +182,6 @@ export default class ImportSubformField extends DetailField { + const { + config, + formLayout, + value, + record, + data, + step + } = this.props + + const fields = this.state.fields if (!fields || !Array.isArray(fields) || fields.length === 0) { return } else { diff --git a/src/components/formFields/form/display.tsx b/src/components/formFields/form/display.tsx new file mode 100644 index 0000000..f6a861a --- /dev/null +++ b/src/components/formFields/form/display.tsx @@ -0,0 +1,344 @@ +import React from 'react' +import { display as getALLComponents } from '../' +import { FormFieldConfig } from '.' +import { Display, FieldConfigs, FieldError, FieldProps } from '../common' +import { getValue, setValue } from '../../../util/value' +import { cloneDeep } from 'lodash' +import ConditionHelper from '../../../util/condition' + +export interface IFormField { + canCollapse?: boolean + children: React.ReactNode[] +} + +export interface IFormFieldItem { + index: number + title: string + canCollapse?: boolean + children: React.ReactNode[] +} + +export interface IFormFieldItemField { + index: number + label: string + fieldType: string + children: React.ReactNode +} + +interface FormState { + didMount: boolean + formDataList: { status: 'normal' | 'error' | 'loading', message?: string }[][] + showItem: boolean + showIndex: number +} + +export default class FormField extends Display, FormState> { + getALLComponents = (type: any): typeof Display => getALLComponents[type] + + formFieldsList: Array | null>> = [] + formFieldsMountedList: Array> = [] + + constructor (props: FieldProps) { + super(props) + + this.state = { + didMount: false, + formDataList: [], + showItem: false, + showIndex: 0 + } + } + + didMount = async () => { + await this.setState({ + didMount: true + }) + } + + set = async (value: any) => { + if (this.props.config.unstringify && this.props.config.unstringify.length > 0 && Array.isArray(value)) { + for (let index = 0; index < value.length; index++) { + if (value[index]) { + for (const field of this.props.config.unstringify) { + const info = getValue(value[index], field) + try { + value[index] = setValue(value[index], field, JSON.parse(info)) + } catch (e) {} + } + } + } + } + + return value + } + + get = async () => { + const data: any[] = [] + + for (let index = 0; index < this.formFieldsList.length; index++) { + if (this.formFieldsList[index]) { + let item: any = {} + + if (Array.isArray(this.props.config.fields)) { + for (const formFieldIndex in this.props.config.fields) { + const formFieldConfig = this.props.config.fields[formFieldIndex] + if (!ConditionHelper(formFieldConfig.condition, { record: this.props.value[index], data: this.props.data, step: this.props.step })) { + continue + } + const formField = this.formFieldsList[index] && this.formFieldsList[index][formFieldIndex] + if (formField) { + const value = await formField.get() + item = setValue(item, formFieldConfig.field, value) + } + } + } + + if (this.props.config.stringify) { + for (const field of this.props.config.stringify) { + const info = getValue(item, field) + item = setValue(item, field, JSON.stringify(info)) + } + } + + data[index] = item + } + } + + return data + } + + handleMount = async (index: number, formFieldIndex: number) => { + if (!this.formFieldsMountedList[index]) { + this.formFieldsMountedList[index] = [] + } + if (this.formFieldsMountedList[index][formFieldIndex]) { + return true + } + this.formFieldsMountedList[index][formFieldIndex] = true + + const formDataList = cloneDeep(this.state.formDataList) + if (!formDataList[index]) formDataList[index] = [] + + if (this.formFieldsList[index] && this.formFieldsList[index][formFieldIndex]) { + const formField = this.formFieldsList[index][formFieldIndex] + if (formField) { + const formFieldConfig = (this.props.config.fields || [])[formFieldIndex] + + let value = getValue(this.props.value[index] === undefined ? {} : this.props.value[index], formFieldConfig.field) + const source = value + if ((formFieldConfig.defaultValue) && value === undefined) { + value = await formField.reset() + } + value = await formField.set(value) + if (source !== value) { + this.props.onValueSet(`[${index}]${formFieldConfig.field}`, value, true) + } + + if (value !== undefined) { + formDataList[index][formFieldIndex] = { status: 'normal' } + } + + await formField.didMount() + } + } + + await this.setState({ + formDataList + }) + } + + handleValueSet = async (index: number, formFieldIndex: number, path: string, value: any, validation: true | FieldError[]) => { + const formFieldConfig = (this.props.config.fields || [])[formFieldIndex] + if (formFieldConfig) { + const fullPath = formFieldConfig.field === '' || path === '' ? `${formFieldConfig.field}${path}` : `${formFieldConfig.field}.${path}` + await this.props.onValueSet(`[${index}]${fullPath}`, value, 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 + }) + } + } + + handleValueUnset = async (index: number, formFieldIndex: number, path: string, validation: true | FieldError[]) => { + const formFieldConfig = (this.props.config.fields || [])[formFieldIndex] + if (formFieldConfig) { + const fullPath = formFieldConfig.field === '' || path === '' ? `${formFieldConfig.field}${path}` : `${formFieldConfig.field}.${path}` + await this.props.onValueUnset(`[${index}]${fullPath}`, 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 + }) + } + } + + handleValueListAppend = async (index: number, formFieldIndex: number, path: string, value: any, validation: true | FieldError[]) => { + const formFieldConfig = (this.props.config.fields || [])[formFieldIndex] + if (formFieldConfig) { + const fullPath = formFieldConfig.field === '' || path === '' ? `${formFieldConfig.field}${path}` : `${formFieldConfig.field}.${path}` + await this.props.onValueListAppend(`[${index}]${fullPath}`, value, 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 + }) + } + } + + handleValueListSplice = async (index: number, formFieldIndex: number, path: string, _index: number, count: number, validation: true | FieldError[]) => { + const formFieldConfig = (this.props.config.fields || [])[formFieldIndex] + if (formFieldConfig) { + const fullPath = formFieldConfig.field === '' || path === '' ? `${formFieldConfig.field}${path}` : `${formFieldConfig.field}.${path}` + await this.props.onValueListSplice(`[${index}]${fullPath}`, _index, count, 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 + }) + } + } + + /** + * 用于展示子表单组件中的每一子项中的每一个子表单项组件 + * @param props + * @returns + */ + renderItemFieldComponent = (props: IFormFieldItemField) => { + return + 您当前使用的UI版本没有实现FormField组件的renderItemFieldComponent方法。 + + } + + /** + * 用于展示子表单组件中的每一个子项 + * @param props + * @returns + */ + renderItemComponent = (props: IFormFieldItem) => { + return + 您当前使用的UI版本没有实现FormField组件的renderItemComponent方法。 + + } + + /** + * 用于展示子表单组件 + * @param _props + * @returns + */ + renderComponent = (_props: IFormField) => { + return + 您当前使用的UI版本没有实现FormField组件。 + + } + + render = () => { + const { + value = [], + data, + step, + config: { + fields, + primaryField, + canCollapse + } + } = this.props + + return ( + + { + this.renderComponent({ + canCollapse, + children: ( + this.state.didMount + ? (Array.isArray(value) ? value : []).map((itemValue: any, index: number) => { + return + {this.renderItemComponent({ + index, + title: primaryField !== undefined ? getValue(itemValue, primaryField, '').toString() : index.toString(), + canCollapse, + children: (fields || []).map((formFieldConfig, fieldIndex) => { + if (!ConditionHelper(formFieldConfig.condition, { record: itemValue, data: this.props.data, step: this.props.step })) { + if (!this.formFieldsMountedList[index]) this.formFieldsMountedList[index] = [] + this.formFieldsMountedList[index][fieldIndex] = false + return null + } + const FormField = this.getALLComponents(formFieldConfig.type) || Display + + let status = ((this.state.formDataList[index] || [])[fieldIndex] || {}).status || 'normal' + + if (['group', 'import_subform', 'object', 'tabs', 'form'].some((type) => type === formFieldConfig.type)) { + status = 'normal' + } + // 渲染表单项容器 + return ( +
+ { + this.renderItemFieldComponent({ + index: fieldIndex, + label: formFieldConfig.label, + fieldType: formFieldConfig.type, + children: ( + | null) => { + if (fieldRef) { + if (!this.formFieldsList[index]) this.formFieldsList[index] = [] + this.formFieldsList[index][fieldIndex] = fieldRef + this.handleMount(index, fieldIndex) + } + }} + value={getValue(value[index], formFieldConfig.field)} + record={value[index]} + data={cloneDeep(data)} + step={step} + config={formFieldConfig} + onValueSet={async (path, value, validation) => this.handleValueSet(index, fieldIndex, path, value, validation)} + onValueUnset={async (path, validation) => 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)} + baseRoute={this.props.baseRoute} + loadDomain={async (domain: string) => await this.props.loadDomain(domain)} + /> + ) + }) + } +
+ ) + }) + }) + } +
+ } + ) + : [] + ) + }) + } +
+ ) + } +} diff --git a/src/components/formFields/group/display.tsx b/src/components/formFields/group/display.tsx new file mode 100644 index 0000000..fc9a131 --- /dev/null +++ b/src/components/formFields/group/display.tsx @@ -0,0 +1,277 @@ +import React from 'react' +import { display as getALLComponents, FieldConfigs } from '../' +import { GroupFieldConfig, IGroupField } from '.' +import { setValue, getValue, getBoolean } from '../../../util/value' +import { Display, FieldError, FieldProps } from '../common' +import { IFormItem } from '../../../steps/form' +import { cloneDeep } from 'lodash' +import ConditionHelper from '../../../util/condition' +import StatementHelper from '../../../util/statement' + +interface IGroupFieldState { + didMount: boolean + formData: { status: 'normal' | 'error' | 'loading', message?: string, name?: string }[] +} + +export default class GroupField extends Display { + // 各表单项对应的类型所使用的UI组件的类 + getALLComponents = (type: any): typeof Display => getALLComponents[type] + + formFields: Array | null> = [] + formFieldsMounted: Array = [] + + constructor (props: FieldProps) { + super(props) + + this.state = { + didMount: false, + formData: [] + } + } + + didMount = async () => { + await this.setState({ + didMount: true + }) + } + + get = async () => { + let data: any = {} + + if (Array.isArray(this.props.config.fields)) { + for (let formFieldIndex = 0; formFieldIndex < this.props.config.fields.length; formFieldIndex++) { + const formFieldConfig = this.props.config.fields[formFieldIndex] + if (!ConditionHelper(formFieldConfig.condition, { record: this.props.value, data: this.props.data, step: this.props.step })) { + continue + } + const formField = this.formFields[formFieldIndex] + if (formField) { + const value = await formField.get() + data = setValue(data, formFieldConfig.field, value) + } + } + } + return data + } + + handleMount = async (formFieldIndex: number) => { + if (this.formFieldsMounted[formFieldIndex]) { + return true + } + this.formFieldsMounted[formFieldIndex] = true + + if (this.formFields[formFieldIndex]) { + const formField = this.formFields[formFieldIndex] + if (formField) { + const formFieldConfig = this.props.config.fields[formFieldIndex] + + let value = getValue(this.props.value, formFieldConfig.field) + const source = value + if ((formFieldConfig.defaultValue) && value === undefined) { + value = await formField.reset() + } + value = await formField.set(value) + if (source !== value) { + this.props.onValueSet(formFieldConfig.field, value, true) + } + + if (value !== undefined) { + this.setState(({ formData }) => { + formData[formFieldIndex] = { status: 'normal', name: formFieldConfig.label } + return { formData: cloneDeep(formData) } + }) + } + await formField.didMount() + } + } + } + + handleValueSet = async (formFieldIndex: number, path: string, value: any, validation: true | FieldError[]) => { + const formFieldConfig = (this.props.config.fields || [])[formFieldIndex] + if (formFieldConfig) { + const fullPath = formFieldConfig.field === '' || path === '' ? `${formFieldConfig.field}${path}` : `${formFieldConfig.field}.${path}` + await this.props.onValueSet(fullPath, value, 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 + }) + } + } + + handleValueUnset = async (formFieldIndex: number, path: string, validation: true | FieldError[]) => { + const formFieldConfig = (this.props.config.fields || [])[formFieldIndex] + if (formFieldConfig) { + const fullPath = formFieldConfig.field === '' || path === '' ? `${formFieldConfig.field}${path}` : `${formFieldConfig.field}.${path}` + await this.props.onValueUnset(fullPath, 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 + }) + } + } + + handleValueListAppend = async (formFieldIndex: number, path: string, value: any, validation: true | FieldError[]) => { + const formFieldConfig = (this.props.config.fields || [])[formFieldIndex] + if (formFieldConfig) { + const fullPath = formFieldConfig.field === '' || path === '' ? `${formFieldConfig.field}${path}` : `${formFieldConfig.field}.${path}` + await this.props.onValueListAppend(fullPath, value, 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 + }) + } + } + + handleValueListSplice = async (formFieldIndex: number, path: string, index: number, count: number, validation: true | FieldError[]) => { + const formFieldConfig = (this.props.config.fields || [])[formFieldIndex] + if (formFieldConfig) { + const fullPath = formFieldConfig.field === '' || path === '' ? `${formFieldConfig.field}${path}` : `${formFieldConfig.field}.${path}` + await this.props.onValueListSplice(fullPath, index, count, 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 + }) + } + } + + handleValueListSort = async (formFieldIndex: number, path: string, index: number, sortType: 'up' | 'down', validation: true | FieldError[]) => { + const formFieldConfig = (this.props.config.fields || [])[formFieldIndex] + if (formFieldConfig) { + 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组件。 + + } + + /** + * 表单项组件 - UI渲染方法 + * 各UI库需重写该方法 + * @param props + */ + renderItemComponent = (props: IFormItem) => { + return + 您当前使用的UI版本没有实现FormItem组件。 + + } + + render = () => { + const { + value, + record, + data, + step + } = this.props + + return ( + + {this.renderComponent({ + children: this.state.didMount + ? (this.props.config.fields || []).map((formFieldConfig, formFieldIndex) => { + if (!ConditionHelper(formFieldConfig.condition, { record: value, data: this.props.data, step: this.props.step })) { + this.formFieldsMounted[formFieldIndex] = false + return null + } + let hidden: boolean = true + let display: boolean = true + + if (formFieldConfig.type === 'hidden') { + hidden = true + display = false + } + + if (formFieldConfig.display === 'none') { + hidden = true + display = false + } + + const FormField = this.getALLComponents(formFieldConfig.type) || Display + + let status = (this.state.formData[formFieldIndex] || {}).status || 'normal' + + if (['group', 'import_subform', 'object', 'tabs', 'form'].some((type) => type === formFieldConfig.type)) { + status = 'normal' + } + + const renderData = { + key: formFieldIndex, + label: formFieldConfig.label, + status, + layout: 'horizontal' as 'horizontal', + message: (this.state.formData[formFieldIndex] || {}).message || '', + extra: StatementHelper(formFieldConfig.extra, { record: this.props.record, data: this.props.data, step: this.props.step }), + required: getBoolean(formFieldConfig.required), + visitable: display, + fieldType: formFieldConfig.type, + children: ( + | null) => { + if (formField) { + this.formFields[formFieldIndex] = formField + this.handleMount(formFieldIndex) + } + }} + value={getValue(value, formFieldConfig.field)} + record={record} + data={cloneDeep(data)} + step={step} + config={formFieldConfig} + onValueSet={async (path, value, validation) => this.handleValueSet(formFieldIndex, path, value, validation)} + onValueUnset={async (path, validation) => 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)} + baseRoute={this.props.baseRoute} + loadDomain={async (domain: string) => await this.props.loadDomain(domain)} + /> + ) + } + // 渲染表单项容器 + return ( + hidden + ? this.renderItemComponent(renderData) + : + ) + }) + : [] + })} + + ) + } +} diff --git a/src/components/formFields/hidden/display.tsx b/src/components/formFields/hidden/display.tsx new file mode 100644 index 0000000..0ff145f --- /dev/null +++ b/src/components/formFields/hidden/display.tsx @@ -0,0 +1,5 @@ +import { HiddenFieldConfig } from '.' +import { Display } from '../common' + +export default class HiddenField extends Display { +} diff --git a/src/components/formFields/importSubform/display.tsx b/src/components/formFields/importSubform/display.tsx new file mode 100644 index 0000000..98e797e --- /dev/null +++ b/src/components/formFields/importSubform/display.tsx @@ -0,0 +1,272 @@ +import React from 'react' +import { getValue } from '../../../util/value' + +import { DetailField, DetailFieldConfig, DetailFieldProps, IDetailField } from '../../detail/common' +import { Display } from '../../formFields/common' +import { display as getALLComponents, FieldConfigs } from '../../formFields' +import { IDetailItem } from '../../../steps/detail' +import { cloneDeep, isEqual } from 'lodash' +import ConditionHelper from '../../../util/condition' +import InterfaceHelper, { InterfaceConfig } from '../../../util/interface' +/** + * 子表单配置项 + * - withConfig: 拓展配置 + * - * - enable: 是否开启 + * - * - dataField: (序列化)数据 + * - * - configField: (序列化)配置 + */ +export interface ImportSubformFieldConfig extends DetailFieldConfig { + type: 'import_subform', + configFrom?: ImportSubformConfigFromData | ImportSubformConfigFromInterface +} + +interface ImportSubformConfigFromData { + type: 'data' + dataField?: string + configField?: string +} + +interface ImportSubformConfigFromInterface { + type: 'interface' + interface?: InterfaceConfig +} + +export interface IImportSubformField { + children: React.ReactNode[] +} + +interface IImportSubformFieldState { + didMount: boolean + fields: FieldConfigs[] + formData: { status: 'normal' | 'error' | 'loading', message?: string }[] +} + +export default class ImportSubformFieldDisplay extends DetailField implements IDetailField { + // 各表单项对应的类型所使用的UI组件的类 + getALLComponents = (type: any): typeof Display => getALLComponents[type] + + // 用于请求防频的判断条件 + requestConfig: string = '' + value: string = '' + + formFields: Array | null> = [] + formFieldsMounted: Array = [] + + interfaceHelper = new InterfaceHelper() + + constructor (props: DetailFieldProps) { + super(props) + + this.state = { + didMount: false, + fields: [], + formData: [] + } + } + + getFullpath + (field: string, path: string = '') { + const withConfigPath = this.props.config.configFrom?.type === 'data' && this.props.config.configFrom.dataField ? `${this.props.config.configFrom.dataField}` : '' + const _fullPath = `${withConfigPath}.${field}.${path}.` + const fullPath = _fullPath.replace(/(^\.*)|(\.*$)|(\.){2,}/g, '$3') + return fullPath + } + + didMount = async () => { + await this.setState({ + didMount: true + }) + } + + set: (value: any) => Promise = async (value) => { + return value + }; + + handleMount = async (formFieldIndex: number) => { + if (this.formFieldsMounted[formFieldIndex]) { + return true + } + this.formFieldsMounted[formFieldIndex] = true + if (this.formFields[formFieldIndex]) { + const formField = this.formFields[formFieldIndex] + if (formField) { + const formFieldConfig = this.state.fields[formFieldIndex] + + let value = getValue(this.props.value, this.getFullpath(formFieldConfig.field)) + const source = value + if ((formFieldConfig.defaultValue) && value === undefined) { + value = await formField.reset() + } + value = await formField.set(value) + if (source !== value) { + this.props.onValueSet(this.getFullpath(formFieldConfig.field), value, true) + } + await formField.didMount() + } + } + } + + getConfigData= () => { + const { + config, + value + } = this.props + if (config.configFrom && config.configFrom.type === 'interface' && config.configFrom.interface) { + this.interfaceHelper.request( + config.configFrom.interface, + {}, + { record: this.props.record, data: this.props.data, step: this.props.step }, + { loadDomain: this.props.loadDomain } + ).then((data: any) => { + let dataToUnstringfy = data + let dataToStringfy = JSON.stringify(data) + if (Object.prototype.toString.call(data) === '[object String]') { + try { + dataToStringfy = data + dataToUnstringfy = JSON.parse(data) + } catch (e) { + console.error('当前动态子表单接口响应数据格式不是合格的json字符串') + dataToUnstringfy = [] + dataToStringfy = '[]' + } + } + if (dataToStringfy !== JSON.stringify(this.state.fields)) { + this.setState({ + fields: dataToUnstringfy + }) + } + }) + } + let fields = this.state.fields + if (config.configFrom && config.configFrom.type === 'data') { + fields = config.configFrom.configField ? getValue(value, config.configFrom.configField) : [] + if (!isEqual(fields, this.state.fields)) { + this.setState({ + fields + }) + } + } + } + + componentDidMount () { + this.getConfigData() + } + + handleValueSet = async (formFieldIndex: number, path: string, value: any) => { + const formFieldConfig = (this.state.fields || [])[formFieldIndex] + if (formFieldConfig) { + const fullPath = this.getFullpath(formFieldConfig.field, path) + await this.props.onValueSet(fullPath, value, true) + } + } + + handleValueUnset = async (formFieldIndex: number, path: string) => { + const formFieldConfig = (this.state.fields || [])[formFieldIndex] + if (formFieldConfig) { + const fullPath = this.getFullpath(formFieldConfig.field, path) + await this.props.onValueUnset(fullPath, true) + } + } + + handleValueListAppend = async (formFieldIndex: number, path: string, value: any) => { + const formFieldConfig = (this.state.fields || [])[formFieldIndex] + if (formFieldConfig) { + const fullPath = this.getFullpath(formFieldConfig.field, path) + await this.props.onValueListAppend(fullPath, value, true) + } + } + + handleValueListSplice = async (formFieldIndex: number, path: string, index: number, count: number) => { + const formFieldConfig = (this.state.fields || [])[formFieldIndex] + if (formFieldConfig) { + const fullPath = this.getFullpath(formFieldConfig.field, path) + await this.props.onValueListSplice(fullPath, index, count, true) + } + } + + renderComponent = (props: IImportSubformField) => { + return + 您当前使用的UI版本没有实现ImportSubformField组件。 + + } + + /** + * 表单项组件 - UI渲染方法 + * 各UI库需重写该方法 + * @param props + */ + renderItemComponent = (props: IDetailItem) => { + return + 您当前使用的UI版本没有实现FormItem组件。 + + } + + render = () => { + const { + config, + value, + record, + data, + step + } = this.props + const fields = this.state.fields + + if (!fields || !Array.isArray(fields) || fields.length === 0) { + return + } else { + return ( + + {this.renderComponent({ + children: this.state.didMount + ? fields.map((formFieldConfig, formFieldIndex) => { + if (!ConditionHelper(formFieldConfig.condition, { record: value, data, step })) { + this.formFieldsMounted[formFieldIndex] = false + return null + } + let display: boolean = true + + if (formFieldConfig.type === 'hidden' || formFieldConfig.display === 'none') { + display = false + } + + const FormField = this.getALLComponents(formFieldConfig.type) || Display + + const renderData: IDetailItem = { + key: formFieldIndex, + label: formFieldConfig.label, + visitable: display, + fieldType: formFieldConfig.type, + layout: 'horizontal' as 'horizontal', + children: ( + | null) => { + if (formField) { + this.formFields[formFieldIndex] = formField + this.handleMount(formFieldIndex) + } + }} + value={getValue(value, this.getFullpath(formFieldConfig.field))} + record={record} + data={cloneDeep(data)} + step={step} + config={formFieldConfig} + onValueSet={async (path, value) => this.handleValueSet(formFieldIndex, path, value)} + onValueUnset={async (path) => this.handleValueUnset(formFieldIndex, path)} + onValueListAppend={async (path, value) => this.handleValueListAppend(formFieldIndex, path, value)} + onValueListSplice={async (path, index, count) => this.handleValueListSplice(formFieldIndex, path, index, count)} + baseRoute={this.props.baseRoute} + loadDomain={async (domain: string) => await this.props.loadDomain(domain)} + /> + ) + } + // 渲染表单项容器 + return this.renderItemComponent(renderData) + }) + : [] + })} + + ) + } + } +} diff --git a/src/components/formFields/index.tsx b/src/components/formFields/index.tsx index e7735a6..3fbf89a 100644 --- a/src/components/formFields/index.tsx +++ b/src/components/formFields/index.tsx @@ -25,6 +25,7 @@ import MultipleTextField, { MultipleTextFieldConfig } from './multipleText' import CustomField, { CustomFieldConfig } from './custom' import TextDisplay from './text/display' +import FormDisplay from './form/display' import RadioDisplay from './radio/display' import ColorDisplay from './color/display' import UploadDisplay from './upload/display' @@ -34,8 +35,12 @@ import DatetimeDisplay from './datetime/display' import DatetimeRangeDisplay from './datetimeRange/display' import SelectSingleDisplay from './select/single/display' import SelectMultipleDisplay from './select/multiple/display' +import ImportSubformDisplay from './importSubform/display' +import GroupDisplay from './group/display' import SwitchDisplay from './switch/display' +import TabsDisplay from './tabs/display' import MultipleTextDisplay from './multipleText/display' +import HiddenDisplay from './hidden/display' export interface HiddenFieldConfig extends FieldConfig { type: 'hidden' | 'none' @@ -124,14 +129,19 @@ export default { export const display = { text: TextDisplay, longtext: LongtextDisplay, + form: FormDisplay, radio: RadioDisplay, color: ColorDisplay, upload: UploadDisplay, + import_subform: ImportSubformDisplay, + group: GroupDisplay, number: NumberDisplay, datetime: DatetimeDisplay, datetimeRange: DatetimeRangeDisplay, select_single: SelectSingleDisplay, select_multiple: SelectMultipleDisplay, switch: SwitchDisplay, - multiple_text: MultipleTextDisplay + tabs: TabsDisplay, + multiple_text: MultipleTextDisplay, + hidden: HiddenDisplay } diff --git a/src/components/formFields/tabs/display.tsx b/src/components/formFields/tabs/display.tsx new file mode 100644 index 0000000..c7ba0d4 --- /dev/null +++ b/src/components/formFields/tabs/display.tsx @@ -0,0 +1,362 @@ +import React from 'react' +import { display as getALLComponents } from '../' +import { TabsFieldConfig, TabsFieldState } from '.' +import { Display, FieldConfigs, DisplayProps, FieldError } from '../common' +import ConditionHelper from '../../../util/condition' +import { getValue, setValue, getBoolean } from '../../../util/value' +import { cloneDeep } from 'lodash' + +export interface ITabsField { + children: React.ReactNode[] +} + +export interface ITabsFieldItem { + key: string + label: string + children: React.ReactNode[] +} + +export interface ITabsFieldItemField { + index: number + label: string + required: boolean + status: 'normal' | 'error' | 'loading' + description?: string + message?: string + extra?: string + fieldType: string + children: React.ReactNode +} + +export default class TabsField extends Display> { + // 各表单项对应的类型所使用的UI组件的类 + getALLComponents = (type: any): typeof Display => getALLComponents[type] + + formFieldsList: Array | null>> = [] + formFieldsMountedList: Array> = [] + + constructor (props: DisplayProps) { + super(props) + + this.state = { + didMount: false, + formDataList: [] + } + } + + didMount = async () => { + await this.setState({ + didMount: true + }) + } + + get = async () => { + let data: any = {} + + for (let index = 0; index < (this.props.config.tabs || []).length; index++) { + const tab = (this.props.config.tabs || [])[index] + const fields = this.props.config.mode === 'same' ? (this.props.config.fields || []) : (((this.props.config.tabs || [])[index] || {}).fields || []) + + for (let formFieldIndex = 0; formFieldIndex < fields.length; formFieldIndex++) { + const formFieldConfig = fields[formFieldIndex] + if (!ConditionHelper(formFieldConfig.condition, { record: getValue(this.props.value, tab.field), data: this.props.data, step: this.props.step })) { + continue + } + const formField = this.formFieldsList[index] && this.formFieldsList[index][formFieldIndex] + if (formField) { + const value = await formField.get() + const fullPath = tab.field === '' || formFieldConfig.field === '' ? `${tab.field}${formFieldConfig.field}` : `${tab.field}.${formFieldConfig.field}` + data = setValue(data, fullPath, value) + } + } + } + + return data + } + + handleMount = async (index: number, formFieldIndex: number) => { + if (!this.formFieldsMountedList[index]) { + this.formFieldsMountedList[index] = [] + } + if (this.formFieldsMountedList[index][formFieldIndex]) { + return true + } + this.formFieldsMountedList[index][formFieldIndex] = true + + const tab = (this.props.config.tabs || [])[index] + + if (this.formFieldsList[index] && this.formFieldsList[index][formFieldIndex]) { + const formField = this.formFieldsList[index][formFieldIndex] + if (formField) { + const fields = this.props.config.mode === 'same' ? (this.props.config.fields || []) : (((this.props.config.tabs || [])[index] || {}).fields || []) + const formFieldConfig = fields[formFieldIndex] + + const fullPath = tab.field === '' || formFieldConfig.field === '' ? `${tab.field}${formFieldConfig.field}` : `${tab.field}.${formFieldConfig.field}` + + let value = getValue(this.props.value, fullPath) + const source = value + if ((formFieldConfig.defaultValue) && value === undefined) { + value = await formField.reset() + } + value = await formField.set(value) + if (source !== value) { + this.props.onValueSet(fullPath, value, true) + } + + if (value !== undefined) { + this.setState(({ formDataList }) => { + if (!formDataList[index]) formDataList[index] = [] + formDataList[index][formFieldIndex] = { status: 'normal' } + return { formDataList: cloneDeep(formDataList) } + }) + } + await formField.didMount() + } + } + } + + handleChange = async (index: number, formFieldIndex: number, value: any) => { + } + + handleValueSet = async (index: number, formFieldIndex: number, path: string, value: any, validation: true | FieldError[]) => { + 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.onValueSet(fullPath, value, 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 + }) + } + } + + handleValueUnset = async (index: number, formFieldIndex: number, path: string, validation: true | FieldError[]) => { + 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.onValueUnset(fullPath, 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 + }) + } + } + + handleValueListAppend = async (index: number, formFieldIndex: number, path: string, value: any, validation: true | FieldError[]) => { + 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.onValueListAppend(fullPath, value, 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 + }) + } + } + + handleValueListSplice = async (index: number, formFieldIndex: number, path: string, _index: number, count: number, validation: true | FieldError[]) => { + 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.onValueListSplice(fullPath, _index, count, 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 + }) + } + } + + handleValueListSort = async (index: number, formFieldIndex: number, path: string, _index: number, sortType: 'up' | 'down', validation: true | FieldError[]) => { + const fields = this.props.config.mode === 'same' ? (this.props.config.fields || []) : (((this.props.config.tabs || [])[index] || {}).fields || []) + const formFieldConfig = fields[formFieldIndex] + if (formFieldConfig) { + 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 + }) + } + } + + /** + * 用于展示子表单组件 + * @param _props + * @returns + */ + renderComponent = (_props: ITabsField) => { + return + 您当前使用的UI版本没有实现FormField组件。 + + } + + /** + * 用于展示子表单组件中的每一个子项 + * @param props + * @returns + */ + renderItemComponent = (props: ITabsFieldItem) => { + return + 您当前使用的UI版本没有实现FormField组件的renderItemComponent方法。 + + } + + /** + * 用于展示子表单组件中的每一子项中的每一个子表单项组件 + * @param props + * @returns + */ + renderItemFieldComponent = (props: ITabsFieldItemField) => { + return + 您当前使用的UI版本没有实现FormField组件的renderItemFieldComponent方法。 + + } + + render = () => { + const { + value = {} + } = this.props + + return ( + + { + this.renderComponent({ + children: ( + this.state.didMount + ? (this.props.config.tabs || []).map((tab: any, index: number) => { + const fields = this.props.config.mode === 'same' ? (this.props.config.fields || []) : (((this.props.config.tabs || [])[index] || {}).fields || []) + return ( + + {this.renderItemComponent({ + key: index.toString(), + label: tab.label, + children: fields.map((formFieldConfig, formFieldIndex) => { + if (!ConditionHelper(formFieldConfig.condition, { record: this.props.record, data: this.props.data, step: this.props.step })) { + if (!this.formFieldsMountedList[index]) this.formFieldsMountedList[index] = [] + this.formFieldsMountedList[index][formFieldIndex] = false + return null + } + let hidden: boolean = true + let display: boolean = true + + if (formFieldConfig.type === 'hidden') { + hidden = true + display = false + } + + if (formFieldConfig.display === 'none') { + hidden = true + display = false + } + + const FormField = this.getALLComponents(formFieldConfig.type) || Display + + let status = ((this.state.formDataList[index] || [])[formFieldIndex] || {}).status || 'normal' + + if (['group', 'import_subform', 'object', 'tabs', 'form'].some((type) => type === formFieldConfig.type)) { + status = 'normal' + } + // 渲染表单项容器 + if (hidden) { + return ( +
+ {this.renderItemFieldComponent({ + index: formFieldIndex, + label: formFieldConfig.label, + status, + message: ((this.state.formDataList[index] || [])[formFieldIndex] || {}).message || '', + required: getBoolean(formFieldConfig.required), + fieldType: formFieldConfig.type, + children: ( + | null) => { + if (!this.formFieldsList[index]) this.formFieldsList[index] = [] + this.formFieldsList[index][formFieldIndex] = formField + this.handleMount(index, formFieldIndex) + }} + value={getValue(getValue(value, tab.field), formFieldConfig.field)} + record={getValue(value, tab.field)} + data={cloneDeep(this.props.data)} + step={this.props.step} + config={formFieldConfig} + onValueSet={async (path, value, validation) => this.handleValueSet(index, formFieldIndex, path, value, validation)} + onValueUnset={async (path, validation) => 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)} + baseRoute={this.props.baseRoute} + loadDomain={async (domain: string) => await this.props.loadDomain(domain)} + /> + ) + })} +
+ ) + } else { + return + } + }) + })} + + ) + }) + : [] + ) + }) + } +
+ ) + } +} diff --git a/src/index.tsx b/src/index.tsx index c8abdd5..d911d62 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -28,6 +28,7 @@ export { default as MultipleTextField } from './components/formFields/multipleTe export { default as CustomField } from './components/formFields/custom' export { default as TextDisplay } from './components/formFields/text/display' +export { default as FormDisplay } from './components/formFields/form/display' export { default as LongTextDisplay } from './components/formFields/longtext/display' export { default as RadioDisplay } from './components/formFields/radio/display' export { default as ColorDisplay } from './components/formFields/color/display' @@ -38,7 +39,11 @@ export { default as DatetimeDisplay } from './components/formFields/datetime/dis export { default as DatetimeRangeDisplay } from './components/formFields/datetimeRange/display' export { default as SelectSingleDisplay } from './components/formFields/select/single/display' export { default as SelectMultipleDisplay } from './components/formFields/select/multiple/display' +export { default as ImportSubformDisplay } from './components/formFields/importSubform/display' +export { default as GroupDisplay } from './components/formFields/group/display' +export { default as TabsDisplay } from './components/formFields/tabs/display' export { default as MultipleTextDisplay } from './components/formFields/multipleText/display' +export { default as HiddenDisplay } from './components/formFields/hidden/display' export { default as TableStep } from './steps/table' export { default as TextColumn } from './components/tableColumns/text' -- Gitee From 458e47aead80a854a2f38e088e9572e33ba21ed8 Mon Sep 17 00:00:00 2001 From: wangailin Date: Fri, 21 Jan 2022 19:19:07 +0800 Subject: [PATCH 02/23] =?UTF-8?q?feat:=20=E8=AF=A6=E6=83=85=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0image=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/detail/enum/index.tsx | 5 +- src/components/detail/image/index.tsx | 66 +++++++++++++++++++++++++++ src/components/detail/index.tsx | 4 ++ src/index.tsx | 1 + 4 files changed, 73 insertions(+), 3 deletions(-) create mode 100644 src/components/detail/image/index.tsx diff --git a/src/components/detail/enum/index.tsx b/src/components/detail/enum/index.tsx index c79b2cf..ac2517b 100644 --- a/src/components/detail/enum/index.tsx +++ b/src/components/detail/enum/index.tsx @@ -1,6 +1,5 @@ -import { config } from 'process' import React from 'react' -import { DetailField, DetailFieldConfig, DetailFieldError, DetailFieldProps, IDetailField } from '../common' +import { DetailField, DetailFieldConfig, IDetailField } from '../common' export interface EnumDetailConfig extends DetailFieldConfig { type: 'detail_enum' @@ -58,7 +57,7 @@ export default class EnumDetail extends DetailField implements IDetailField { + renderComponent = (props: IImageDetail) => { + return + 您当前使用的UI版本没有实现Image组件。 +
+
+
+ } + + getValue = () => { + const { + value, + config: { + url, + defaultValue + } + } = this.props + if (value === undefined || value === null || value === '') { + if (url) { + return url + } + return defaultValue !== undefined ? defaultValue : '' + } + return value + } + + render = () => { + const { + config: { + height, + width, + preview + } + } = this.props + const props: any = { + height, + width, + preview, + value: this.getValue() + } + + return ( + + {this.renderComponent(props)} + + ) + } +} diff --git a/src/components/detail/index.tsx b/src/components/detail/index.tsx index 24ae057..a88014b 100644 --- a/src/components/detail/index.tsx +++ b/src/components/detail/index.tsx @@ -2,6 +2,7 @@ import TextField, { TextFieldConfig } from './text' import EnumDetail, { EnumDetailConfig } from './enum' import StatementDetail, { StatementDetailConfig } from './statement' +import ImageDetail, { ImageDetailConfig } from './image' import GroupField, { GroupFieldConfig } from './group' import ImportSubformField, { ImportSubformFieldConfig } from './importSubform' @@ -13,6 +14,7 @@ export type DetailFieldConfigs = TextFieldConfig | EnumDetailConfig | StatementDetailConfig | + ImageDetailConfig | GroupFieldConfig | ImportSubformFieldConfig @@ -21,6 +23,7 @@ export type componentType = 'group' | 'detail_enum' | 'statement' | + 'image' | 'import_subform' export default { @@ -28,5 +31,6 @@ export default { text: TextField, import_subform: ImportSubformField, detail_enum: EnumDetail, + image: ImageDetail, statement: StatementDetail } diff --git a/src/index.tsx b/src/index.tsx index c3b11cf..849fd0e 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -61,6 +61,7 @@ export { default as DetailStep } from './steps/detail' export { default as DetailGroupField } from './components/detail/group' export { default as DetailEunmField } from './components/detail/enum' export { default as DetailStatementField } from './components/detail/statement' +export { default as DetailImageField } from './components/detail/image' export { default as DetailTextField } from './components/detail/text' export { default as DetailImportSubformField } from './components/detail/importSubform' -- Gitee From cada06d915791eb2fe7e568d08c53d7c4470364f Mon Sep 17 00:00:00 2001 From: zhenjintao Date: Fri, 21 Jan 2022 22:32:46 +0800 Subject: [PATCH 03/23] =?UTF-8?q?feat:=20group=E3=80=81importSubform?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=88=86=E6=A0=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/detail/importSubform/index.tsx | 12 ++++++++++++ src/components/formFields/common.tsx | 1 + src/components/formFields/form/display.tsx | 5 +++++ src/components/formFields/group/display.tsx | 17 +++++++++++++++-- .../formFields/importSubform/display.tsx | 18 +++++++++++++++++- src/components/formFields/tabs/display.tsx | 3 +++ 6 files changed, 53 insertions(+), 3 deletions(-) diff --git a/src/components/detail/importSubform/index.tsx b/src/components/detail/importSubform/index.tsx index f70c3ee..3c124a8 100644 --- a/src/components/detail/importSubform/index.tsx +++ b/src/components/detail/importSubform/index.tsx @@ -20,6 +20,7 @@ import { ColumnsConfig } from '../../../interface' export interface ImportSubformFieldConfig extends DetailFieldConfig { type: 'import_subform', configFrom?: ImportSubformConfigFromData | ImportSubformConfigFromInterface + childColumns?: ColumnsConfig } interface ImportSubformConfigFromData { @@ -216,6 +217,7 @@ export default class ImportSubformField extends DetailField {this.renderComponent({ + columns: config?.columns?.enable ? config.columns : undefined, children: this.state.didMount ? fields.map((formFieldConfig, formFieldIndex) => { if (!ConditionHelper(formFieldConfig.condition, { record: value, data, step })) { @@ -233,11 +235,21 @@ export default class ImportSubformField extends DetailField | null) => { if (formField) { diff --git a/src/components/formFields/common.tsx b/src/components/formFields/common.tsx index 9539759..f930b1a 100644 --- a/src/components/formFields/common.tsx +++ b/src/components/formFields/common.tsx @@ -181,6 +181,7 @@ export class Field extends React.Component< } export interface DisplayProps { + formLayout: 'horizontal' | 'vertical' | 'inline' value: T, record: { [field: string]: any }, data: any[], diff --git a/src/components/formFields/form/display.tsx b/src/components/formFields/form/display.tsx index f6a861a..6cdb1e0 100644 --- a/src/components/formFields/form/display.tsx +++ b/src/components/formFields/form/display.tsx @@ -21,6 +21,7 @@ export interface IFormFieldItem { export interface IFormFieldItemField { index: number label: string + layout: 'horizontal' | 'vertical' | 'inline' fieldType: string children: React.ReactNode } @@ -261,6 +262,7 @@ export default class FormField extends Display | null) => { if (fieldRef) { if (!this.formFieldsList[index]) this.formFieldsList[index] = [] @@ -311,6 +315,7 @@ export default class FormField extends Display { @@ -193,7 +193,9 @@ export default class GroupField extends Display { const { + config, value, + formLayout, record, data, step @@ -202,6 +204,7 @@ export default class GroupField extends Display {this.renderComponent({ + columns: config?.columns?.enable ? config.columns : undefined, children: this.state.didMount ? (this.props.config.fields || []).map((formFieldConfig, formFieldIndex) => { if (!ConditionHelper(formFieldConfig.condition, { record: value, data: this.props.data, step: this.props.step })) { @@ -232,11 +235,20 @@ export default class GroupField extends Display { const { config, + formLayout, value, record, data, @@ -217,6 +222,7 @@ export default class ImportSubformFieldDisplay extends DetailField {this.renderComponent({ + columns: config?.columns?.enable ? config.columns : undefined, children: this.state.didMount ? fields.map((formFieldConfig, formFieldIndex) => { if (!ConditionHelper(formFieldConfig.condition, { record: value, data, step })) { @@ -234,11 +240,21 @@ export default class ImportSubformFieldDisplay extends DetailField | null) => { if (formField) { diff --git a/src/components/formFields/tabs/display.tsx b/src/components/formFields/tabs/display.tsx index c7ba0d4..1029f88 100644 --- a/src/components/formFields/tabs/display.tsx +++ b/src/components/formFields/tabs/display.tsx @@ -24,6 +24,7 @@ export interface ITabsFieldItemField { description?: string message?: string extra?: string + layout: 'horizontal' | 'vertical' | 'inline' fieldType: string children: React.ReactNode } @@ -319,6 +320,7 @@ export default class TabsField extends Display extends Display Date: Fri, 11 Feb 2022 19:26:10 +0800 Subject: [PATCH 04/23] build: use rollup --- .babelrc | 24 ++++++++++++ .eslintrc | 31 +++++++++++++++ .eslintrc.js | 27 ------------- .fatherrc.js | 21 ----------- package.json | 98 ++++++++++++++++++++++++------------------------ rollup.config.js | 41 ++++++++++++++++++++ tsconfig.json | 34 ++++++++++------- 7 files changed, 164 insertions(+), 112 deletions(-) create mode 100644 .babelrc create mode 100644 .eslintrc delete mode 100644 .eslintrc.js delete mode 100644 .fatherrc.js create mode 100644 rollup.config.js diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..0792683 --- /dev/null +++ b/.babelrc @@ -0,0 +1,24 @@ +{ + "sourceMaps": true, + "presets": [ + [ + "@babel/preset-typescript", + { + "isTSX": true, + "allExtensions": true + } + ], + "@babel/preset-react", + [ + "@babel/preset-env", + { + "targets": { + "node": "10.13.0" + }, + // "modules": false + //将 ES6 module 转换为其他模块规范,可选 "adm" | "umd" | "systemjs" | "commonjs" | "cjs" | false,默认为 false + // 否则 Babel 会在 Rollup 有机会做处理之前,将我们的模块转成 CommonJS ,导致 Rollup 的一些处理失败。 + } + ] + ] +} \ No newline at end of file diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..e88f05d --- /dev/null +++ b/.eslintrc @@ -0,0 +1,31 @@ +{ + "env": { + "browser": true, + "es2021": true, + "jest": true, + "node": true, + "commonjs": true, + "es6": true + }, + "parser": "@typescript-eslint/parser", + "plugins": [ + "react", + "@typescript-eslint" + ], + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "standard" + ], + "parserOptions": { + "ecmaFeatures": { + "jsx": true + }, + "ecmaVersion": 12, + "sourceType": "module" + }, + "rules": { + "no-use-before-define": "off", + "react/display-name": 0 + } +} \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index 797152f..0000000 --- a/.eslintrc.js +++ /dev/null @@ -1,27 +0,0 @@ -module.exports = { - env: { - browser: true, - es2021: true, - jest: true - }, - extends: [ - 'plugin:react/recommended', - 'standard' - ], - parser: '@typescript-eslint/parser', - parserOptions: { - ecmaFeatures: { - jsx: true - }, - ecmaVersion: 12, - sourceType: 'module' - }, - plugins: [ - 'react', - '@typescript-eslint' - ], - rules: { - 'no-use-before-define': 'off', - 'react/display-name': 0 - } -} diff --git a/.fatherrc.js b/.fatherrc.js deleted file mode 100644 index c9b7c09..0000000 --- a/.fatherrc.js +++ /dev/null @@ -1,21 +0,0 @@ -export default { - entry: 'src/index.tsx', - esm: "rollup", - cjs: { - type: "babel", - lazy: true - }, - cssModules: true, - injectCSS: true, - lessInBabelMode: true, - doc: { - typescript: true - }, - extraBabelPlugins: [ - ['babel-plugin-import', { - libraryName: 'antd', - libraryDirectory: 'es', - style: true, - }], - ] -} \ No newline at end of file diff --git a/package.json b/package.json index 91472ce..27772ca 100644 --- a/package.json +++ b/package.json @@ -10,76 +10,74 @@ "dist" ], "scripts": { - "build": "father build", - "dev": "father doc dev", - "lint-init": "eslint --init", - "lint": "eslint src --ext .ts", + "dev": "npm-watch build", + "build": "npm run clear && npm run build:rollup && npm run build:babel", + "build:rollup": "rollup -c", + "build:babel": "babel src -d lib -s -x '.ts,.tsx'", + "clear": "rm -rf dist && rm -rf lib", "test": "jest", - "test:u": "npm test -- -u" + "test:u": "npm test -- -u", + "lint": "eslint src/** --fix" }, + "keywords": [ + "ccms" + ], "author": "niuweb", "license": "MIT", + "dependencies": { + "@types/react": "^16.9.46", + "@types/react-router-dom": "^5.1.5", + "axios": "^0.20.0", + "lodash": "^4.17.21", + "marked": "^1.2.5", + "moment": "^2.29.0", + "qiankun": "^2.5.1", + "query-string": "^6.13.8", + "rc-table": "^7.9.10", + "react-loadable": "^5.5.0" + }, "devDependencies": { - "@babel/core": "^7.11.4", + "@babel/cli": "^7.16.8", + "@babel/core": "^7.16.12", "@babel/plugin-proposal-class-properties": "^7.10.4", "@babel/plugin-proposal-decorators": "^7.10.5", "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-transform-runtime": "^7.11.0", - "@babel/preset-env": "^7.11.0", - "@babel/preset-react": "^7.10.4", + "@babel/preset-env": "^7.16.11", + "@babel/preset-react": "^7.16.7", + "@babel/preset-typescript": "^7.16.7", + "@rollup/plugin-babel": "^5.3.0", + "@rollup/plugin-commonjs": "^21.0.1", + "@rollup/plugin-json": "^4.1.0", + "@rollup/plugin-node-resolve": "^13.1.3", "@testing-library/react": "^11.0.4", - "@types/jest": "^26.0.14", - "@types/lodash": "^4.14.172", + "@types/jest": "^27.4.0", + "@types/lodash": "^4.14.178", "@types/marked": "^1.2.0", "@types/node": "^14.11.2", "@types/react-dom": "^16.9.8", "@types/react-loadable": "^5.5.3", "@types/react-test-renderer": "^16.9.3", - "@typescript-eslint/eslint-plugin": "^4.12.0", - "@typescript-eslint/parser": "^4.12.0", + "@typescript-eslint/eslint-plugin": "^5.10.1", + "@typescript-eslint/parser": "^5.10.1", "awesome-typescript-loader": "^5.2.1", "babel-jest": "^26.3.0", - "babel-loader": "^8.1.0", "babel-plugin-import": "^1.13.0", - "css-loader": "^4.3.0", - "eslint": "^7.17.0", - "eslint-config-standard": "^16.0.2", - "eslint-plugin-import": "^2.22.1", + "eslint": "^7.32.0", + "eslint-config-standard": "^16.0.3", + "eslint-plugin-import": "^2.25.4", "eslint-plugin-node": "^11.1.0", - "eslint-plugin-promise": "^4.2.1", - "eslint-plugin-react": "^7.22.0", - "express": "^4.17.1", - "father": "^2.29.11", - "html-webpack-plugin": "^4.5.0", - "identity-obj-proxy": "^3.0.0", - "jest": "^26.4.2", - "less": "^3.12.2", - "less-loader": "^7.0.1", - "loadsh": "0.0.4", - "react-docgen": "^5.3.1", - "react-scripts": "^4.0.1", - "react-test-renderer": "^16.13.1", - "style-loader": "^1.2.1", - "ts-jest": "^26.4.0", - "typedoc": "^0.19.2", - "typescript": "^4.0.2", - "webpack": "^4.44.2", - "webpack-bundle-analyzer": "^3.9.0", - "webpack-cli": "^3.3.12", - "webpack-dev-server": "^3.11.0", - "webpack-merge": "^5.1.4" - }, - "dependencies": { - "@types/react": "^16.9.46", - "@types/react-router-dom": "^5.1.5", - "axios": "^0.20.0", + "eslint-plugin-promise": "^4.3.1", + "eslint-plugin-react": "^7.28.0", + "execa": "^4.1.0", + "jest": "^27.4.7", "lodash": "^4.17.21", - "marked": "^1.2.5", - "moment": "^2.29.0", - "qiankun": "^2.5.1", - "query-string": "^6.13.8", - "rc-table": "^7.9.10", - "react-loadable": "^5.5.0" + "npm-watch": "^0.11.0", + "rollup": "^2.66.0", + "rollup-plugin-eslint": "^7.0.0", + "rollup-plugin-typescript2": "^0.31.1", + "ts-jest": "^27.1.3", + "typescript": "^4.5.5" }, "peerDependencies": { "react": "^16.13.1", diff --git a/rollup.config.js b/rollup.config.js new file mode 100644 index 0000000..b2a1bc4 --- /dev/null +++ b/rollup.config.js @@ -0,0 +1,41 @@ +import path from 'path' +import ts from 'rollup-plugin-typescript2' +import { nodeResolve } from '@rollup/plugin-node-resolve' +import { babel } from '@rollup/plugin-babel' +import commonjs from '@rollup/plugin-commonjs' +import { eslint } from 'rollup-plugin-eslint' +import json from '@rollup/plugin-json' + +export default { + input: 'src/index.tsx', + output: [ + { + format: 'esm', + file: path.resolve('dist/index.esm.js'), // 输出的文件路径 + sourcemap: true + } + ], + plugins: [ + json(), + // eslint({ + // throwOnError: true, + // exclude: ['node_modules/**', 'es/**', 'dist/**'] + // }), + ts({ + tsconfig: path.resolve(__dirname, 'tsconfig.json') + }), + babel({ + babelHelpers: 'runtime', + exclude: 'node_modules/**' // 只编译我们的源代码 + }), + commonjs(), + nodeResolve({ + extensions: ['.js', '.ts', '.tsx'] + }) + ], + external: ['react', 'react-dom'], + // external: id => /lodash/.test(id), // lodash 现在将被视为外部的(externals),不会与你的库打包在一起 + watch: { + include: 'src/**' + } +} diff --git a/tsconfig.json b/tsconfig.json index 95deb7c..8123d1b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,32 +1,38 @@ { "compilerOptions": { - "target": "es6", - "module": "esnext", - "jsx": "react", - "sourceMap": true, - "outDir": "./lib/", + "target": "ES6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ + "module": "ESNext", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ + "allowJs": true, /* Allow javascript files to be compiled. */ + "sourceMap": true, /* Generates corresponding '.map' file. */ + "outDir": "./lib/", //输出编译后的文件 /* Redirect output structure to the directory. */ + "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ + "esModuleInterop": true, /* 通过为所有导入创建命名空间对象,启用 CommonJS 和 ES 模块之间的发射互操作性 Implies 'allowSyntheticDefaultImports'. */ + "declaration": true, // 生成定义文件 /* Generates corresponding '.d.ts' file. */ + "jsx": "react", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ + // "declarationDir": "./ts/types", // 定义文件输出目录 + // "declarationMap": true, // 生成定义sourceMap /* Generates a sourcemap for each corresponding '.d.ts' file. */ + // "removeComments": true, // 删除注释 + // "noUnusedLocals": true, // 未使用变量报错 /* Report errors on unused locals. */ + "strict": true, - "esModuleInterop": true, - "lib": [ + "lib": [ // // 指定要包含在编译中的库文件导入库类型定义 "dom", "dom.iterable", "esnext" ], - "allowJs": true, - "skipLibCheck": true, + "skipLibCheck": true, // Skip type checking of declaration files. "allowSyntheticDefaultImports": true, - "forceConsistentCasingInFileNames": true, - "moduleResolution": "node", + "forceConsistentCasingInFileNames": true, // /* Disallow inconsistently-cased references to the same file. */ "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, "noImplicitAny": true, "strictNullChecks": true, "suppressImplicitAnyIndexErrors": true, - "types": [ + "types": [ // // 导入指定类型包 "node", "jest" ], - "experimentalDecorators": true + "experimentalDecorators": true, } -} \ No newline at end of file +} -- Gitee From 817f6e7c19145eedf20b92954874192f998051f3 Mon Sep 17 00:00:00 2001 From: zhenjintao Date: Tue, 15 Feb 2022 10:57:16 +0800 Subject: [PATCH 05/23] feat: eslint --- .eslintrc | 42 ++++++++++++++++++++++++++++++++---------- .prettierrc | 5 +++++ package.json | 14 ++++++++++++-- 3 files changed, 49 insertions(+), 12 deletions(-) create mode 100644 .prettierrc diff --git a/.eslintrc b/.eslintrc index e88f05d..4ba6db6 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,22 +1,25 @@ { + // 为我们提供运行环境,一个环境定义了一组预定义的全局变量 "env": { "browser": true, "es2021": true, "jest": true, "node": true, - "commonjs": true, - "es6": true + "commonjs": true }, - "parser": "@typescript-eslint/parser", - "plugins": [ - "react", - "@typescript-eslint" - ], + // 一个配置文件可以被基础配置中的已启用的规则继承。 "extends": [ - "eslint:recommended", - "plugin:@typescript-eslint/recommended", - "standard" + "airbnb", + "prettier", + "plugin:compat/recommended", + "plugin:jest/recommended", + "plugin:react/recommended", + "plugin:import/typescript", + "plugin:@typescript-eslint/recommended" ], + // ESLint 默认使用Espree作为其解析器,你可以在配置文件中指定一个不同的解析器 + "parser": "@typescript-eslint/parser", + // 配置解析器支持的语法 "parserOptions": { "ecmaFeatures": { "jsx": true @@ -24,8 +27,27 @@ "ecmaVersion": 12, "sourceType": "module" }, + // ESLint 支持使用第三方插件。在使用插件之前,你必须使用 npm 安装它。 + // 在配置文件里配置插件时,可以使用 plugins 关键字来存放插件名字的列表。插件名称可以省略 eslint-plugin- 前缀 + "plugins": [ + "react", + "babel", + "jest", + "react-hooks", + "@typescript-eslint" + ], + // ESLint 附带有大量的规则。你可以使用注释或配置文件修改你项目中要使用的规则。要改变一个规则设置,你必须将规则 ID 设置为下列值之一: + // "off" 或 0 - 关闭规则 + // "warn" 或 1 - 开启规则,使用警告级别的错误:warn (不会导致程序退出) + // "error" 或 2 - 开启规则,使用错误级别的错误:error (当被触发的时候,程序会退出) "rules": { "no-use-before-define": "off", "react/display-name": 0 + }, + // 指定react版本为安装的版本 + "settings": { + "react": { + "version": "16.13.1" + } } } \ No newline at end of file diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..122cf16 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,5 @@ +{ + "singleQuote": true, + "printWidth": 120, + "tabWidth": 2 +} \ No newline at end of file diff --git a/package.json b/package.json index 27772ca..77bd680 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,8 @@ "clear": "rm -rf dist && rm -rf lib", "test": "jest", "test:u": "npm test -- -u", - "lint": "eslint src/** --fix" + "lint": "eslint src/** --fix", + "prettier": "prettier -c --write **/*" }, "keywords": [ "ccms" @@ -64,15 +65,24 @@ "babel-jest": "^26.3.0", "babel-plugin-import": "^1.13.0", "eslint": "^7.32.0", - "eslint-config-standard": "^16.0.3", + "eslint-config-airbnb": "^19.0.4", + "eslint-config-prettier": "^8.3.0", + "eslint-plugin-babel": "^5.3.1", + "eslint-plugin-compat": "^4.0.1", "eslint-plugin-import": "^2.25.4", + "eslint-plugin-jest": "^26.0.0", + "eslint-plugin-jsx-a11y": "^6.5.1", "eslint-plugin-node": "^11.1.0", "eslint-plugin-promise": "^4.3.1", "eslint-plugin-react": "^7.28.0", + "eslint-plugin-react-hooks": "^4.3.0", "execa": "^4.1.0", + "husky": "^7.0.4", "jest": "^27.4.7", + "lint-staged": "^12.3.3", "lodash": "^4.17.21", "npm-watch": "^0.11.0", + "prettier": "^2.5.1", "rollup": "^2.66.0", "rollup-plugin-eslint": "^7.0.0", "rollup-plugin-typescript2": "^0.31.1", -- Gitee From d1acea5d9897f8fdded0fd2e8b63c2fb6dbc2038 Mon Sep 17 00:00:00 2001 From: zhenjintao Date: Tue, 15 Feb 2022 17:30:08 +0800 Subject: [PATCH 06/23] feat: commitlint --- .commitlintrc.js | 32 +++++++++++++++++++++++++++++++ .editorconfig | 9 +++++++++ .eslintrc | 5 +++-- .prettierrc | 8 ++++---- package.json | 31 +++++++++++++++++++++++++++--- src/util/param.ts | 48 ++++++++++++++++++++++------------------------- 6 files changed, 98 insertions(+), 35 deletions(-) create mode 100644 .commitlintrc.js create mode 100644 .editorconfig diff --git a/.commitlintrc.js b/.commitlintrc.js new file mode 100644 index 0000000..1449c0f --- /dev/null +++ b/.commitlintrc.js @@ -0,0 +1,32 @@ +/** + * @file commitlint 配置 + * commit message: (注意冒号后面有空格) + * + */ +module.exports = { + extends: ['@commitlint/config-conventional'], + rules: { + 'type-enum': [ + 2, + 'always', + [ + 'init', // 初始提交 + 'feat', // 新功能(feature) + 'perf', // 优化 + 'fix', // 修补bug + 'docs', // 文档(documentation) + 'style', // 格式(不影响代码运行的变动) + 'refactor', // 重构(即不是新增功能,也不是修改bug的代码变动) + 'build', // 编译构建 + 'test', // 增加测试 + 'revert', // 回滚 + 'config', // 构建过程或辅助工具的变动 + 'chore', // 其他改动 + ], + ], + 'type-empty': [2, 'never'], // 提交不符合规范时,也可以提交,但是会有警告 + 'subject-empty': [2, 'never'], // 提交不符合规范时,也可以提交,但是会有警告 + 'subject-full-stop': [0, 'never'], + 'subject-case': [0, 'never'], + }, +}; diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..c6c8b36 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,9 @@ +root = true + +[*] +indent_style = space +indent_size = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true diff --git a/.eslintrc b/.eslintrc index 4ba6db6..04b963d 100644 --- a/.eslintrc +++ b/.eslintrc @@ -42,7 +42,8 @@ // "error" 或 2 - 开启规则,使用错误级别的错误:error (当被触发的时候,程序会退出) "rules": { "no-use-before-define": "off", - "react/display-name": 0 + "react/display-name": 0, + "import/extensions": 0 }, // 指定react版本为安装的版本 "settings": { @@ -50,4 +51,4 @@ "version": "16.13.1" } } -} \ No newline at end of file +} diff --git a/.prettierrc b/.prettierrc index 122cf16..d0ed5e8 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,5 +1,5 @@ { - "singleQuote": true, - "printWidth": 120, - "tabWidth": 2 -} \ No newline at end of file + "singleQuote": true, + "printWidth": 120, + "tabWidth": 2 +} diff --git a/package.json b/package.json index 77bd680..07f6e2c 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,28 @@ "test": "jest", "test:u": "npm test -- -u", "lint": "eslint src/** --fix", - "prettier": "prettier -c --write **/*" + "prettier": "prettier -c --write **/*", + "commit": "git-cz" + }, + "husky": { + "hooks": { + "commit-msg": "commitlint --env HUSKY_GIT_PARAMS", + "pre-commit": "lint-staged" + } + }, + "lint-staged": { + "src/*.{js, jsx, ts, tsx}": [ + "npm run prettier", + "npm run lint" + ], + "src/*.{css,scss,less,json,html,md,markdown}": [ + "npm run prettier" + ] + }, + "config": { + "commitizen": { + "path": "./node_modules/cz-conventional-changelog" + } }, "keywords": [ "ccms" @@ -38,6 +59,9 @@ "react-loadable": "^5.5.0" }, "devDependencies": { + "@commitlint/cli": "^9.0.1", + "@commitlint/config-conventional": "^9.0.1", + "commitizen": "^4.2.4", "@babel/cli": "^7.16.8", "@babel/core": "^7.16.12", "@babel/plugin-proposal-class-properties": "^7.10.4", @@ -77,9 +101,10 @@ "eslint-plugin-react": "^7.28.0", "eslint-plugin-react-hooks": "^4.3.0", "execa": "^4.1.0", - "husky": "^7.0.4", + "husky": "^4.2.5", + "cz-conventional-changelog": "^3.3.0", "jest": "^27.4.7", - "lint-staged": "^12.3.3", + "lint-staged": "^10.2.11", "lodash": "^4.17.21", "npm-watch": "^0.11.0", "prettier": "^2.5.1", diff --git a/src/util/param.ts b/src/util/param.ts index 0742e6b..f86401f 100644 --- a/src/util/param.ts +++ b/src/util/param.ts @@ -1,53 +1,49 @@ -import { get, set } from "lodash" -import qs from "query-string" -import { ParamConfig } from "../interface"; +import { get, set } from 'lodash'; +import qs from 'query-string'; +import { ParamConfig } from '../interface'; -export default function ParamHelper ( config: ParamConfig, datas: { record?: object, data: object[], step: number }) { +export default function ParamHelper(config: ParamConfig, datas: { record?: object; data: object[]; step: number }) { switch (config.source) { case 'record': if (datas.record) { if (config.field === '') { - return datas.record - } else { - return get(datas.record, config.field) + return datas.record; } + return get(datas.record, config.field); } - break + break; case 'data': if (datas.data[datas.step]) { if (config.field === '') { - return datas.data[datas.step] - } else { - return get(datas.data[datas.step], config.field) + return datas.data[datas.step]; } + return get(datas.data[datas.step], config.field); } - break + break; case 'source': if (datas.data[0]) { if (config.field === '') { - return datas.data[0] - } else { - return get(datas.data[0], config.field) + return datas.data[0]; } + return get(datas.data[0], config.field); } - break + break; case 'step': if (datas.data[config.step]) { if (config.field === '') { - return datas.data[config.step] - } else { - return get(datas.data[config.step], config.field) + return datas.data[config.step]; } + return get(datas.data[config.step], config.field); } - break + break; case 'url': if (config.field === '') { - return qs.parse(window.location.search, { arrayFormat: 'bracket' }) - } else { - return get(qs.parse(window.location.search, { arrayFormat: 'bracket' }), config.field) + return qs.parse(window.location.search, { arrayFormat: 'bracket' }); } + return get(qs.parse(window.location.search, { arrayFormat: 'bracket' }), config.field); + case 'static': - return config.value + return config.value; } - return undefined -} \ No newline at end of file + return undefined; +} -- Gitee From 5871d8bb7efc4603b1eae0a2d7b04c84ec73f1a3 Mon Sep 17 00:00:00 2001 From: zhenjintao Date: Thu, 17 Feb 2022 21:49:54 +0800 Subject: [PATCH 07/23] feat: commitlint --- .commitlintrc.js | 1 - package.json | 23 ++++++++++++----------- rollup.config.js | 36 +++++++++++++++++++----------------- tsconfig.json | 19 +++++++++---------- 4 files changed, 40 insertions(+), 39 deletions(-) diff --git a/.commitlintrc.js b/.commitlintrc.js index 1449c0f..ccc051b 100644 --- a/.commitlintrc.js +++ b/.commitlintrc.js @@ -20,7 +20,6 @@ module.exports = { 'build', // 编译构建 'test', // 增加测试 'revert', // 回滚 - 'config', // 构建过程或辅助工具的变动 'chore', // 其他改动 ], ], diff --git a/package.json b/package.json index 07f6e2c..97bba4d 100644 --- a/package.json +++ b/package.json @@ -49,19 +49,10 @@ "dependencies": { "@types/react": "^16.9.46", "@types/react-router-dom": "^5.1.5", - "axios": "^0.20.0", - "lodash": "^4.17.21", - "marked": "^1.2.5", - "moment": "^2.29.0", - "qiankun": "^2.5.1", - "query-string": "^6.13.8", "rc-table": "^7.9.10", "react-loadable": "^5.5.0" }, "devDependencies": { - "@commitlint/cli": "^9.0.1", - "@commitlint/config-conventional": "^9.0.1", - "commitizen": "^4.2.4", "@babel/cli": "^7.16.8", "@babel/core": "^7.16.12", "@babel/plugin-proposal-class-properties": "^7.10.4", @@ -71,6 +62,8 @@ "@babel/preset-env": "^7.16.11", "@babel/preset-react": "^7.16.7", "@babel/preset-typescript": "^7.16.7", + "@commitlint/cli": "^9.0.1", + "@commitlint/config-conventional": "^9.0.1", "@rollup/plugin-babel": "^5.3.0", "@rollup/plugin-commonjs": "^21.0.1", "@rollup/plugin-json": "^4.1.0", @@ -88,6 +81,8 @@ "awesome-typescript-loader": "^5.2.1", "babel-jest": "^26.3.0", "babel-plugin-import": "^1.13.0", + "commitizen": "^4.2.4", + "cz-conventional-changelog": "^3.3.0", "eslint": "^7.32.0", "eslint-config-airbnb": "^19.0.4", "eslint-config-prettier": "^8.3.0", @@ -102,7 +97,6 @@ "eslint-plugin-react-hooks": "^4.3.0", "execa": "^4.1.0", "husky": "^4.2.5", - "cz-conventional-changelog": "^3.3.0", "jest": "^27.4.7", "lint-staged": "^10.2.11", "lodash": "^4.17.21", @@ -110,12 +104,19 @@ "prettier": "^2.5.1", "rollup": "^2.66.0", "rollup-plugin-eslint": "^7.0.0", + "rollup-plugin-terser": "^7.0.2", "rollup-plugin-typescript2": "^0.31.1", "ts-jest": "^27.1.3", "typescript": "^4.5.5" }, "peerDependencies": { + "axios": "^0.20.0", + "lodash": "^4.17.21", + "marked": "^1.2.5", "react": "^16.13.1", - "react-dom": "^16.13.1" + "react-dom": "^16.13.1", + "query-string": "^6.13.8", + "moment": "^2.29.0", + "qiankun": "^2.5.1" } } diff --git a/rollup.config.js b/rollup.config.js index b2a1bc4..523ba5a 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -1,10 +1,11 @@ -import path from 'path' -import ts from 'rollup-plugin-typescript2' -import { nodeResolve } from '@rollup/plugin-node-resolve' -import { babel } from '@rollup/plugin-babel' -import commonjs from '@rollup/plugin-commonjs' -import { eslint } from 'rollup-plugin-eslint' -import json from '@rollup/plugin-json' +import path from 'path'; +import ts from 'rollup-plugin-typescript2'; +import { nodeResolve } from '@rollup/plugin-node-resolve'; +import { babel } from '@rollup/plugin-babel'; +import commonjs from '@rollup/plugin-commonjs'; +import { eslint } from 'rollup-plugin-eslint'; +import json from '@rollup/plugin-json'; +import { terser } from 'rollup-plugin-terser'; export default { input: 'src/index.tsx', @@ -12,8 +13,8 @@ export default { { format: 'esm', file: path.resolve('dist/index.esm.js'), // 输出的文件路径 - sourcemap: true - } + // sourcemap: true, + }, ], plugins: [ json(), @@ -22,20 +23,21 @@ export default { // exclude: ['node_modules/**', 'es/**', 'dist/**'] // }), ts({ - tsconfig: path.resolve(__dirname, 'tsconfig.json') + tsconfig: path.resolve(__dirname, 'tsconfig.json'), }), babel({ babelHelpers: 'runtime', - exclude: 'node_modules/**' // 只编译我们的源代码 + exclude: 'node_modules/**', // 只编译我们的源代码 }), commonjs(), nodeResolve({ - extensions: ['.js', '.ts', '.tsx'] - }) + extensions: ['.js', '.ts', '.tsx'], + }), + terser(), ], - external: ['react', 'react-dom'], + external: ['react', 'react-dom', 'marked', 'lodash', 'axios', 'query-string', 'moment', 'qiankun'], // external: id => /lodash/.test(id), // lodash 现在将被视为外部的(externals),不会与你的库打包在一起 watch: { - include: 'src/**' - } -} + include: 'src/**', + }, +}; diff --git a/tsconfig.json b/tsconfig.json index 8123d1b..1e93bd0 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,19 +1,18 @@ { "compilerOptions": { - "target": "ES6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ - "module": "ESNext", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ - "allowJs": true, /* Allow javascript files to be compiled. */ - "sourceMap": true, /* Generates corresponding '.map' file. */ - "outDir": "./lib/", //输出编译后的文件 /* Redirect output structure to the directory. */ - "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ - "esModuleInterop": true, /* 通过为所有导入创建命名空间对象,启用 CommonJS 和 ES 模块之间的发射互操作性 Implies 'allowSyntheticDefaultImports'. */ - "declaration": true, // 生成定义文件 /* Generates corresponding '.d.ts' file. */ - "jsx": "react", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ + "target": "ES6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ + "module": "ESNext", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ + "allowJs": true, /* Allow javascript files to be compiled. */ + "sourceMap": true, /* Generates corresponding '.map' file. */ + "outDir": "./lib/", //输出编译后的文件 /* Redirect output structure to the directory. */ + "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ + "esModuleInterop": true, /* 通过为所有导入创建命名空间对象,启用 CommonJS 和 ES 模块之间的发射互操作性 Implies 'allowSyntheticDefaultImports'. */ + "declaration": true, // 生成定义文件 /* Generates corresponding '.d.ts' file. */ + "jsx": "react", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ // "declarationDir": "./ts/types", // 定义文件输出目录 // "declarationMap": true, // 生成定义sourceMap /* Generates a sourcemap for each corresponding '.d.ts' file. */ // "removeComments": true, // 删除注释 // "noUnusedLocals": true, // 未使用变量报错 /* Report errors on unused locals. */ - "strict": true, "lib": [ // // 指定要包含在编译中的库文件导入库类型定义 "dom", -- Gitee From 7520577fa5ea4721ad2355396e400cacd7853c16 Mon Sep 17 00:00:00 2001 From: zjt Date: Mon, 21 Feb 2022 14:38:47 +0800 Subject: [PATCH 08/23] chore: package.json --- package.json | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 97bba4d..00c1bd6 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,12 @@ "dependencies": { "@types/react": "^16.9.46", "@types/react-router-dom": "^5.1.5", + "axios": "^0.20.0", + "lodash": "^4.17.21", + "marked": "^1.2.5", + "moment": "^2.29.0", + "qiankun": "^2.5.1", + "query-string": "^6.13.8", "rc-table": "^7.9.10", "react-loadable": "^5.5.0" }, @@ -99,7 +105,6 @@ "husky": "^4.2.5", "jest": "^27.4.7", "lint-staged": "^10.2.11", - "lodash": "^4.17.21", "npm-watch": "^0.11.0", "prettier": "^2.5.1", "rollup": "^2.66.0", @@ -110,13 +115,7 @@ "typescript": "^4.5.5" }, "peerDependencies": { - "axios": "^0.20.0", - "lodash": "^4.17.21", - "marked": "^1.2.5", "react": "^16.13.1", - "react-dom": "^16.13.1", - "query-string": "^6.13.8", - "moment": "^2.29.0", - "qiankun": "^2.5.1" + "react-dom": "^16.13.1" } } -- Gitee From 13054ae60ab6e6965191b7c0e23a3e31074cbdb0 Mon Sep 17 00:00:00 2001 From: zjt Date: Wed, 2 Mar 2022 10:42:25 +0800 Subject: [PATCH 09/23] 1.2.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 00c1bd6..9d3a91d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ccms", - "version": "1.2.0", + "version": "1.2.1", "description": "ConfigableCMS", "main": "lib/index.js", "module": "dist/index.js", -- Gitee From 07bf310402465db2a7ca3bd5f7ef7e702439c122 Mon Sep 17 00:00:00 2001 From: zjt Date: Wed, 2 Mar 2022 10:42:28 +0800 Subject: [PATCH 10/23] 1.2.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9d3a91d..3111d61 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ccms", - "version": "1.2.1", + "version": "1.2.2", "description": "ConfigableCMS", "main": "lib/index.js", "module": "dist/index.js", -- Gitee From 6e99401ada937dc7868c55e1455901af59f0d3bc Mon Sep 17 00:00:00 2001 From: zjt Date: Wed, 2 Mar 2022 10:45:23 +0800 Subject: [PATCH 11/23] 1.2.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3111d61..3a68709 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ccms", - "version": "1.2.2", + "version": "1.2.3", "description": "ConfigableCMS", "main": "lib/index.js", "module": "dist/index.js", -- Gitee From 0deb94fa53ebb9aca7a17c6844b58c29dd7b1d6d Mon Sep 17 00:00:00 2001 From: zjt Date: Wed, 2 Mar 2022 17:58:13 +0800 Subject: [PATCH 12/23] docs: commit&eslint --- .commitlintrc.js | 26 ++++++++++++++------------ .cz-config.js | 30 ++++++++++++++++++++++++++++++ .eslintrc | 48 ++++++++++++++++++++++-------------------------- .prettierrc | 5 ++++- package.json | 9 ++++++--- rollup.config.js | 19 +++++++++---------- tsconfig.json | 41 +++++++++++++++-------------------------- 7 files changed, 100 insertions(+), 78 deletions(-) create mode 100644 .cz-config.js diff --git a/.commitlintrc.js b/.commitlintrc.js index ccc051b..72120c1 100644 --- a/.commitlintrc.js +++ b/.commitlintrc.js @@ -1,7 +1,9 @@ /** * @file commitlint 配置 - * commit message: (注意冒号后面有空格) - * + * commit message: (): (注意冒号后面有空格) + * type 标识commit类别 + * scope 标识commit影响范围 + * subject 本次修改的简单描述 */ module.exports = { extends: ['@commitlint/config-conventional'], @@ -14,18 +16,18 @@ module.exports = { 'feat', // 新功能(feature) 'perf', // 优化 'fix', // 修补bug - 'docs', // 文档(documentation) - 'style', // 格式(不影响代码运行的变动) - 'refactor', // 重构(即不是新增功能,也不是修改bug的代码变动) + 'docs', // 文档 + 'style', // 格式 + 'refactor', // 重构 'build', // 编译构建 'test', // 增加测试 'revert', // 回滚 - 'chore', // 其他改动 - ], + 'chore' // 其他改动 + ] ], - 'type-empty': [2, 'never'], // 提交不符合规范时,也可以提交,但是会有警告 - 'subject-empty': [2, 'never'], // 提交不符合规范时,也可以提交,但是会有警告 + 'type-empty': [2, 'never'], + 'subject-empty': [2, 'never'], 'subject-full-stop': [0, 'never'], - 'subject-case': [0, 'never'], - }, -}; + 'subject-case': [0, 'never'] + } +} diff --git a/.cz-config.js b/.cz-config.js new file mode 100644 index 0000000..ac77282 --- /dev/null +++ b/.cz-config.js @@ -0,0 +1,30 @@ +'use strict' +module.exports = { + types: [ + { value: 'init', name: '初始化' }, + { value: 'feat', name: '新增: 新功能' }, + { value: 'fix', name: '修复: 修复一个Bug' }, + { value: 'docs', name: '文档: 变更的只有文档' }, + { value: 'style', name: '格式: 空格, 分号等格式修复' }, + { value: 'refactor', name: '重构: 代码重构,注意和特性、修复区分开' }, + { value: 'perf', name: '性能: 提升性能' }, + { value: 'test', name: '测试: 添加一个测试' }, + { value: 'build', name: '工具: 开发工具变动(构建、脚手架工具等)' }, + { value: 'revert', name: '回滚: 代码回退' }, + { value: 'chore', name: '其他' } + ], + scopes: [{ name: 'javascript' }, { name: 'typescript' }, { name: 'React' }, { name: 'node' }], + messages: { + type: '选择一种你的提交类型:', + scope: '选择一个scope (可选):', + customScope: 'Denote the SCOPE of this change:', + subject: '短说明:\n', + body: '长说明,使用"|"换行(可选):\n', + breaking: '非兼容性说明 (可选):\n', + footer: '关联关闭的issue,例如:#31, #34(可选):\n', + confirmCommit: '确定提交说明?(yes/no)' + }, + allowCustomScopes: true, + allowBreakingChanges: ['特性', '修复'], + subjectLimit: 100 +} diff --git a/.eslintrc b/.eslintrc index 04b963d..23b421f 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,5 +1,4 @@ { - // 为我们提供运行环境,一个环境定义了一组预定义的全局变量 "env": { "browser": true, "es2021": true, @@ -7,19 +6,17 @@ "node": true, "commonjs": true }, - // 一个配置文件可以被基础配置中的已启用的规则继承。 "extends": [ "airbnb", - "prettier", "plugin:compat/recommended", "plugin:jest/recommended", "plugin:react/recommended", "plugin:import/typescript", - "plugin:@typescript-eslint/recommended" + "plugin:@typescript-eslint/recommended", + "prettier", + "plugin:prettier/recommended" ], - // ESLint 默认使用Espree作为其解析器,你可以在配置文件中指定一个不同的解析器 "parser": "@typescript-eslint/parser", - // 配置解析器支持的语法 "parserOptions": { "ecmaFeatures": { "jsx": true @@ -27,28 +24,27 @@ "ecmaVersion": 12, "sourceType": "module" }, - // ESLint 支持使用第三方插件。在使用插件之前,你必须使用 npm 安装它。 - // 在配置文件里配置插件时,可以使用 plugins 关键字来存放插件名字的列表。插件名称可以省略 eslint-plugin- 前缀 - "plugins": [ - "react", - "babel", - "jest", - "react-hooks", - "@typescript-eslint" - ], - // ESLint 附带有大量的规则。你可以使用注释或配置文件修改你项目中要使用的规则。要改变一个规则设置,你必须将规则 ID 设置为下列值之一: - // "off" 或 0 - 关闭规则 - // "warn" 或 1 - 开启规则,使用警告级别的错误:warn (不会导致程序退出) - // "error" 或 2 - 开启规则,使用错误级别的错误:error (当被触发的时候,程序会退出) - "rules": { - "no-use-before-define": "off", - "react/display-name": 0, - "import/extensions": 0 - }, - // 指定react版本为安装的版本 + "plugins": ["react", "babel", "jest", "react-hooks", "@typescript-eslint"], "settings": { "react": { "version": "16.13.1" - } + }, + "polyfills": ["Promise"] + }, + "rules": { + "prettier/prettier": "error", + "arrow-body-style": "off", + "prefer-arrow-callback": "off", + "no-use-before-define": "off", + "react/display-name": 0, + "import/extensions": 0, + "comma-dangle": ["error", "never"], + "space-before-function-paren": [0, "always"], + "react/jsx-filename-extension": [ + 2, + { + "extensions": [".js", ".jsx", ".ts", ".tsx"] + } + ] } } diff --git a/.prettierrc b/.prettierrc index d0ed5e8..51fdad2 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,5 +1,8 @@ { "singleQuote": true, "printWidth": 120, - "tabWidth": 2 + "useTabs": false, + "tabWidth": 2, + "semi": false, + "trailingComma": "none" } diff --git a/package.json b/package.json index 3a68709..723ebea 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ }, "config": { "commitizen": { - "path": "./node_modules/cz-conventional-changelog" + "path": "./node_modules/cz-customizable" } }, "keywords": [ @@ -56,7 +56,8 @@ "qiankun": "^2.5.1", "query-string": "^6.13.8", "rc-table": "^7.9.10", - "react-loadable": "^5.5.0" + "react-loadable": "^5.5.0", + "tslib": "^2.3.1" }, "devDependencies": { "@babel/cli": "^7.16.8", @@ -88,7 +89,8 @@ "babel-jest": "^26.3.0", "babel-plugin-import": "^1.13.0", "commitizen": "^4.2.4", - "cz-conventional-changelog": "^3.3.0", + "commitlint-config-cz": "^0.13.2", + "cz-customizable": "^6.3.0", "eslint": "^7.32.0", "eslint-config-airbnb": "^19.0.4", "eslint-config-prettier": "^8.3.0", @@ -98,6 +100,7 @@ "eslint-plugin-jest": "^26.0.0", "eslint-plugin-jsx-a11y": "^6.5.1", "eslint-plugin-node": "^11.1.0", + "eslint-plugin-prettier": "^4.0.0", "eslint-plugin-promise": "^4.3.1", "eslint-plugin-react": "^7.28.0", "eslint-plugin-react-hooks": "^4.3.0", diff --git a/rollup.config.js b/rollup.config.js index 523ba5a..6b20707 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -12,9 +12,8 @@ export default { output: [ { format: 'esm', - file: path.resolve('dist/index.esm.js'), // 输出的文件路径 - // sourcemap: true, - }, + file: path.resolve('dist/index.esm.js') + } ], plugins: [ json(), @@ -23,21 +22,21 @@ export default { // exclude: ['node_modules/**', 'es/**', 'dist/**'] // }), ts({ - tsconfig: path.resolve(__dirname, 'tsconfig.json'), + tsconfig: path.resolve(__dirname, 'tsconfig.json') }), babel({ babelHelpers: 'runtime', - exclude: 'node_modules/**', // 只编译我们的源代码 + exclude: 'node_modules/**' }), + commonjs(), nodeResolve({ - extensions: ['.js', '.ts', '.tsx'], + extensions: ['.js', '.ts', '.tsx'] }), - terser(), + terser() ], external: ['react', 'react-dom', 'marked', 'lodash', 'axios', 'query-string', 'moment', 'qiankun'], - // external: id => /lodash/.test(id), // lodash 现在将被视为外部的(externals),不会与你的库打包在一起 watch: { - include: 'src/**', - }, + include: 'src/**' + } }; diff --git a/tsconfig.json b/tsconfig.json index 1e93bd0..8231895 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,37 +1,26 @@ { "compilerOptions": { - "target": "ES6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ - "module": "ESNext", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ - "allowJs": true, /* Allow javascript files to be compiled. */ - "sourceMap": true, /* Generates corresponding '.map' file. */ - "outDir": "./lib/", //输出编译后的文件 /* Redirect output structure to the directory. */ - "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ - "esModuleInterop": true, /* 通过为所有导入创建命名空间对象,启用 CommonJS 和 ES 模块之间的发射互操作性 Implies 'allowSyntheticDefaultImports'. */ - "declaration": true, // 生成定义文件 /* Generates corresponding '.d.ts' file. */ - "jsx": "react", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ - // "declarationDir": "./ts/types", // 定义文件输出目录 - // "declarationMap": true, // 生成定义sourceMap /* Generates a sourcemap for each corresponding '.d.ts' file. */ - // "removeComments": true, // 删除注释 - // "noUnusedLocals": true, // 未使用变量报错 /* Report errors on unused locals. */ + "target": "ES6", + "module": "ESNext", + "allowJs": true, + "sourceMap": true, + "outDir": "./lib/", + "moduleResolution": "node", + "esModuleInterop": true, + "declaration": true, + "jsx": "react", "strict": true, - "lib": [ // // 指定要包含在编译中的库文件导入库类型定义 - "dom", - "dom.iterable", - "esnext" - ], - "skipLibCheck": true, // Skip type checking of declaration files. + "lib": ["dom", "dom.iterable", "esnext"], + "skipLibCheck": true, "allowSyntheticDefaultImports": true, - "forceConsistentCasingInFileNames": true, // /* Disallow inconsistently-cased references to the same file. */ + "forceConsistentCasingInFileNames": true, "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, - "noImplicitAny": true, + "noImplicitAny": false, "strictNullChecks": true, "suppressImplicitAnyIndexErrors": true, - "types": [ // // 导入指定类型包 - "node", - "jest" - ], - "experimentalDecorators": true, + "types": ["node", "jest"], + "experimentalDecorators": true } } -- Gitee From 4cd8f0218b4e7f902ec4d443648853478ec39388 Mon Sep 17 00:00:00 2001 From: zjt Date: Thu, 3 Mar 2022 10:43:07 +0800 Subject: [PATCH 13/23] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=E8=A7=84?= =?UTF-8?q?=E5=88=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .babelrc | 7 ++----- .eslintrc | 5 +---- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/.babelrc b/.babelrc index 0792683..5e1194f 100644 --- a/.babelrc +++ b/.babelrc @@ -14,11 +14,8 @@ { "targets": { "node": "10.13.0" - }, - // "modules": false - //将 ES6 module 转换为其他模块规范,可选 "adm" | "umd" | "systemjs" | "commonjs" | "cjs" | false,默认为 false - // 否则 Babel 会在 Rollup 有机会做处理之前,将我们的模块转成 CommonJS ,导致 Rollup 的一些处理失败。 + } } ] ] -} \ No newline at end of file +} diff --git a/.eslintrc b/.eslintrc index 23b421f..fc8dbf2 100644 --- a/.eslintrc +++ b/.eslintrc @@ -13,7 +13,6 @@ "plugin:react/recommended", "plugin:import/typescript", "plugin:@typescript-eslint/recommended", - "prettier", "plugin:prettier/recommended" ], "parser": "@typescript-eslint/parser", @@ -32,9 +31,7 @@ "polyfills": ["Promise"] }, "rules": { - "prettier/prettier": "error", - "arrow-body-style": "off", - "prefer-arrow-callback": "off", + "react/jsx-props-no-spreading": 0, "no-use-before-define": "off", "react/display-name": 0, "import/extensions": 0, -- Gitee From 4c42a15d5a18809d2369079673767a839405ed6b Mon Sep 17 00:00:00 2001 From: cuiwenlong7 Date: Tue, 19 Apr 2022 18:01:49 +0800 Subject: [PATCH 14/23] =?UTF-8?q?fix:=20=E7=BB=93=E5=90=88noPathCombinatio?= =?UTF-8?q?n=E4=BF=AE=E6=94=B9=E8=A1=A8=E5=8D=95=E9=A1=B9form=E4=B8=8Bdisp?= =?UTF-8?q?lay=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/formFields/form/display.tsx | 100 ++++----------------- 1 file changed, 19 insertions(+), 81 deletions(-) diff --git a/src/components/formFields/form/display.tsx b/src/components/formFields/form/display.tsx index f6a861a..0999d80 100644 --- a/src/components/formFields/form/display.tsx +++ b/src/components/formFields/form/display.tsx @@ -1,7 +1,7 @@ import React from 'react' import { display as getALLComponents } from '../' import { FormFieldConfig } from '.' -import { Display, FieldConfigs, FieldError, FieldProps } from '../common' +import { Display, FieldConfigs, DisplayProps } from '../common' import { getValue, setValue } from '../../../util/value' import { cloneDeep } from 'lodash' import ConditionHelper from '../../../util/condition' @@ -27,7 +27,6 @@ export interface IFormFieldItemField { interface FormState { didMount: boolean - formDataList: { status: 'normal' | 'error' | 'loading', message?: string }[][] showItem: boolean showIndex: number } @@ -38,12 +37,11 @@ export default class FormField extends Display | null>> = [] formFieldsMountedList: Array> = [] - constructor (props: FieldProps) { + constructor (props: DisplayProps) { super(props) this.state = { didMount: false, - formDataList: [], showItem: false, showIndex: 0 } @@ -116,9 +114,6 @@ export default class FormField extends Display { + handleValueSet = async (index: number, formFieldIndex: number, path: string, value: any, options?: { noPathCombination?: boolean }) => { const formFieldConfig = (this.props.config.fields || [])[formFieldIndex] if (formFieldConfig) { - const fullPath = formFieldConfig.field === '' || path === '' ? `${formFieldConfig.field}${path}` : `${formFieldConfig.field}.${path}` - await this.props.onValueSet(`[${index}]${fullPath}`, value, 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 - }) + const fullPath = options && options.noPathCombination ? path : (formFieldConfig.field === '' || path === '' ? `${formFieldConfig.field}${path}` : `${formFieldConfig.field}.${path}`) + await this.props.onValueSet(`[${index}]${fullPath}`, value) } } - handleValueUnset = async (index: number, formFieldIndex: number, path: string, validation: true | FieldError[]) => { + handleValueUnset = async (index: number, formFieldIndex: number, path: string, options?: { noPathCombination?: boolean }) => { const formFieldConfig = (this.props.config.fields || [])[formFieldIndex] if (formFieldConfig) { - const fullPath = formFieldConfig.field === '' || path === '' ? `${formFieldConfig.field}${path}` : `${formFieldConfig.field}.${path}` - await this.props.onValueUnset(`[${index}]${fullPath}`, 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 - }) + const fullPath = options && options.noPathCombination ? path : (formFieldConfig.field === '' || path === '' ? `${formFieldConfig.field}${path}` : `${formFieldConfig.field}.${path}`) + await this.props.onValueUnset(`[${index}]${fullPath}`) } } - handleValueListAppend = async (index: number, formFieldIndex: number, path: string, value: any, validation: true | FieldError[]) => { + handleValueListAppend = async (index: number, formFieldIndex: number, path: string, value: any, options?: { noPathCombination?: boolean }) => { const formFieldConfig = (this.props.config.fields || [])[formFieldIndex] if (formFieldConfig) { - const fullPath = formFieldConfig.field === '' || path === '' ? `${formFieldConfig.field}${path}` : `${formFieldConfig.field}.${path}` - await this.props.onValueListAppend(`[${index}]${fullPath}`, value, 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 - }) + const fullPath = options && options.noPathCombination ? path : (formFieldConfig.field === '' || path === '' ? `${formFieldConfig.field}${path}` : `${formFieldConfig.field}.${path}`) + await this.props.onValueListAppend(`[${index}]${fullPath}`, value) } } - handleValueListSplice = async (index: number, formFieldIndex: number, path: string, _index: number, count: number, validation: true | FieldError[]) => { + handleValueListSplice = async (index: number, formFieldIndex: number, path: string, _index: number, count: number, options?: { noPathCombination?: boolean }) => { const formFieldConfig = (this.props.config.fields || [])[formFieldIndex] if (formFieldConfig) { - const fullPath = formFieldConfig.field === '' || path === '' ? `${formFieldConfig.field}${path}` : `${formFieldConfig.field}.${path}` - await this.props.onValueListSplice(`[${index}]${fullPath}`, _index, count, 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 - }) + const fullPath = options && options.noPathCombination ? path : (formFieldConfig.field === '' || path === '' ? `${formFieldConfig.field}${path}` : `${formFieldConfig.field}.${path}`) + await this.props.onValueListSplice(`[${index}]${fullPath}`, _index, count) } } @@ -289,11 +232,6 @@ export default class FormField extends Display type === formFieldConfig.type)) { - status = 'normal' - } // 渲染表单项容器 return (
@@ -316,10 +254,10 @@ export default class FormField extends Display this.handleValueSet(index, fieldIndex, path, value, validation)} - onValueUnset={async (path, validation) => 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)} + onValueSet={async (path, value, options) => this.handleValueSet(index, fieldIndex, path, value, options)} + onValueUnset={async (path, options) => this.handleValueUnset(index, fieldIndex, path, options)} + onValueListAppend={async (path, value, options) => this.handleValueListAppend(index, fieldIndex, path, value, options)} + onValueListSplice={async (path, _index, count, options) => this.handleValueListSplice(index, fieldIndex, path, _index, count, options)} baseRoute={this.props.baseRoute} loadDomain={async (domain: string) => await this.props.loadDomain(domain)} /> -- Gitee From 53e4689253c99218b2fe3b5b7b90503ef659b6e7 Mon Sep 17 00:00:00 2001 From: zjt Date: Tue, 19 Apr 2022 20:26:14 +0800 Subject: [PATCH 15/23] =?UTF-8?q?fix:=20=E7=BB=93=E5=90=88noPathCombinatio?= =?UTF-8?q?n=E4=BF=AE=E6=94=B9display?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/formFields/group/display.tsx | 218 ++++------ .../formFields/importSubform/display.tsx | 18 +- src/components/formFields/tabs/display.tsx | 379 +++++++----------- 3 files changed, 235 insertions(+), 380 deletions(-) diff --git a/src/components/formFields/group/display.tsx b/src/components/formFields/group/display.tsx index fc9a131..48f71a3 100644 --- a/src/components/formFields/group/display.tsx +++ b/src/components/formFields/group/display.tsx @@ -2,7 +2,7 @@ import React from 'react' import { display as getALLComponents, FieldConfigs } from '../' import { GroupFieldConfig, IGroupField } from '.' import { setValue, getValue, getBoolean } from '../../../util/value' -import { Display, FieldError, FieldProps } from '../common' +import { Display, DisplayProps } from '../common' import { IFormItem } from '../../../steps/form' import { cloneDeep } from 'lodash' import ConditionHelper from '../../../util/condition' @@ -10,7 +10,6 @@ import StatementHelper from '../../../util/statement' interface IGroupFieldState { didMount: boolean - formData: { status: 'normal' | 'error' | 'loading', message?: string, name?: string }[] } export default class GroupField extends Display { @@ -20,12 +19,11 @@ export default class GroupField extends Display | null> = [] formFieldsMounted: Array = [] - constructor (props: FieldProps) { + constructor(props: DisplayProps) { super(props) this.state = { - didMount: false, - formData: [] + didMount: false } } @@ -72,105 +70,43 @@ export default class GroupField extends Display { - formData[formFieldIndex] = { status: 'normal', name: formFieldConfig.label } - return { formData: cloneDeep(formData) } - }) - } await formField.didMount() } } } - handleValueSet = async (formFieldIndex: number, path: string, value: any, validation: true | FieldError[]) => { + handleValueSet = async (formFieldIndex: number, path: string, value: any, options?: { noPathCombination?: boolean }) => { const formFieldConfig = (this.props.config.fields || [])[formFieldIndex] if (formFieldConfig) { - const fullPath = formFieldConfig.field === '' || path === '' ? `${formFieldConfig.field}${path}` : `${formFieldConfig.field}.${path}` - await this.props.onValueSet(fullPath, value, 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 - }) + const fullPath = options && options.noPathCombination ? `${formFieldConfig.field}${path}` : `${formFieldConfig.field}.${path}` + await this.props.onValueSet(fullPath, value) } } - handleValueUnset = async (formFieldIndex: number, path: string, validation: true | FieldError[]) => { + handleValueUnset = async (formFieldIndex: number, path: string, options?: { noPathCombination?: boolean }) => { const formFieldConfig = (this.props.config.fields || [])[formFieldIndex] if (formFieldConfig) { - const fullPath = formFieldConfig.field === '' || path === '' ? `${formFieldConfig.field}${path}` : `${formFieldConfig.field}.${path}` - await this.props.onValueUnset(fullPath, 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 - }) - } - } - - handleValueListAppend = async (formFieldIndex: number, path: string, value: any, validation: true | FieldError[]) => { - const formFieldConfig = (this.props.config.fields || [])[formFieldIndex] - if (formFieldConfig) { - const fullPath = formFieldConfig.field === '' || path === '' ? `${formFieldConfig.field}${path}` : `${formFieldConfig.field}.${path}` - await this.props.onValueListAppend(fullPath, value, 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 - }) + const fullPath = options && options.noPathCombination ? `${formFieldConfig.field}${path}` : `${formFieldConfig.field}.${path}` + await this.props.onValueUnset(fullPath) } } - handleValueListSplice = async (formFieldIndex: number, path: string, index: number, count: number, validation: true | FieldError[]) => { + handleValueListAppend = async (formFieldIndex: number, path: string, value: any, options?: { noPathCombination?: boolean }) => { const formFieldConfig = (this.props.config.fields || [])[formFieldIndex] if (formFieldConfig) { - const fullPath = formFieldConfig.field === '' || path === '' ? `${formFieldConfig.field}${path}` : `${formFieldConfig.field}.${path}` - await this.props.onValueListSplice(fullPath, index, count, 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 - }) + const fullPath = options && options.noPathCombination ? `${formFieldConfig.field}${path}` : `${formFieldConfig.field}.${path}` + await this.props.onValueListAppend(fullPath, value) } } - handleValueListSort = async (formFieldIndex: number, path: string, index: number, sortType: 'up' | 'down', validation: true | FieldError[]) => { + handleValueListSplice = async (formFieldIndex: number, path: string, index: number, count: number, options?: { noPathCombination?: boolean }) => { const formFieldConfig = (this.props.config.fields || [])[formFieldIndex] if (formFieldConfig) { - 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 - }) + const fullPath = options && options.noPathCombination ? `${formFieldConfig.field}${path}` : `${formFieldConfig.field}.${path}` + await this.props.onValueListSplice(fullPath, index, count) } } @@ -204,71 +140,65 @@ export default class GroupField extends Display { - if (!ConditionHelper(formFieldConfig.condition, { record: value, data: this.props.data, step: this.props.step })) { - this.formFieldsMounted[formFieldIndex] = false - return null - } - let hidden: boolean = true - let display: boolean = true - - if (formFieldConfig.type === 'hidden') { - hidden = true - display = false - } - - if (formFieldConfig.display === 'none') { - hidden = true - display = false - } - - const FormField = this.getALLComponents(formFieldConfig.type) || Display - - let status = (this.state.formData[formFieldIndex] || {}).status || 'normal' - - if (['group', 'import_subform', 'object', 'tabs', 'form'].some((type) => type === formFieldConfig.type)) { - status = 'normal' - } - - const renderData = { - key: formFieldIndex, - label: formFieldConfig.label, - status, - layout: 'horizontal' as 'horizontal', - message: (this.state.formData[formFieldIndex] || {}).message || '', - extra: StatementHelper(formFieldConfig.extra, { record: this.props.record, data: this.props.data, step: this.props.step }), - required: getBoolean(formFieldConfig.required), - visitable: display, - fieldType: formFieldConfig.type, - children: ( - | null) => { - if (formField) { - this.formFields[formFieldIndex] = formField - this.handleMount(formFieldIndex) - } - }} - value={getValue(value, formFieldConfig.field)} - record={record} - data={cloneDeep(data)} - step={step} - config={formFieldConfig} - onValueSet={async (path, value, validation) => this.handleValueSet(formFieldIndex, path, value, validation)} - onValueUnset={async (path, validation) => 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)} - baseRoute={this.props.baseRoute} - loadDomain={async (domain: string) => await this.props.loadDomain(domain)} - /> - ) - } - // 渲染表单项容器 - return ( - hidden - ? this.renderItemComponent(renderData) - : + if (!ConditionHelper(formFieldConfig.condition, { record: value, data: this.props.data, step: this.props.step })) { + this.formFieldsMounted[formFieldIndex] = false + return null + } + let hidden: boolean = true + let display: boolean = true + + if (formFieldConfig.type === 'hidden') { + hidden = true + display = false + } + + if (formFieldConfig.display === 'none') { + hidden = true + display = false + } + + const FormField = this.getALLComponents(formFieldConfig.type) || Display + + let status: 'normal' = 'normal' + const renderData = { + key: formFieldIndex, + label: formFieldConfig.label, + status, + layout: 'horizontal' as 'horizontal', + extra: StatementHelper(formFieldConfig.extra, { record: this.props.record, data: this.props.data, step: this.props.step }), + required: getBoolean(formFieldConfig.required), + visitable: display, + fieldType: formFieldConfig.type, + children: ( + | null) => { + if (formField) { + this.formFields[formFieldIndex] = formField + this.handleMount(formFieldIndex) + } + }} + value={getValue(value, formFieldConfig.field)} + record={record} + data={cloneDeep(data)} + step={step} + config={formFieldConfig} + onValueSet={async (path, value, options) => this.handleValueSet(formFieldIndex, path, value, options)} + onValueUnset={async (path, options) => this.handleValueUnset(formFieldIndex, path, options)} + onValueListAppend={async (path, value, options) => this.handleValueListAppend(formFieldIndex, path, value, options)} + onValueListSplice={async (path, index, count, options) => this.handleValueListSplice(formFieldIndex, path, index, count, options)} + baseRoute={this.props.baseRoute} + loadDomain={async (domain: string) => await this.props.loadDomain(domain)} + /> ) - }) + } + // 渲染表单项容器 + return ( + hidden + ? this.renderItemComponent(renderData) + : + ) + }) : [] })} diff --git a/src/components/formFields/importSubform/display.tsx b/src/components/formFields/importSubform/display.tsx index 98e797e..52b90e5 100644 --- a/src/components/formFields/importSubform/display.tsx +++ b/src/components/formFields/importSubform/display.tsx @@ -54,7 +54,7 @@ export default class ImportSubformFieldDisplay extends DetailField) { + constructor(props: DetailFieldProps) { super(props) this.state = { @@ -65,7 +65,7 @@ export default class ImportSubformFieldDisplay extends DetailField { + getConfigData = () => { const { config, value @@ -148,7 +148,7 @@ export default class ImportSubformFieldDisplay extends DetailField { + didMount: boolean + extra?: S +} export default class TabsField extends Display> { - // 各表单项对应的类型所使用的UI组件的类 - getALLComponents = (type: any): typeof Display => getALLComponents[type] + // 各表单项对应的类型所使用的UI组件的类 + getALLComponents = (type: any): typeof Display => getALLComponents[type] - formFieldsList: Array | null>> = [] - formFieldsMountedList: Array> = [] + formFieldsList: Array | null>> = [] + formFieldsMountedList: Array> = [] - constructor (props: DisplayProps) { - super(props) + constructor(props: DisplayProps) { + super(props) - this.state = { - didMount: false, - formDataList: [] - } - } + this.state = { + didMount: false + } + } + + didMount = async () => { + await this.setState({ + didMount: true + }) + } - didMount = async () => { - await this.setState({ - didMount: true - }) + get = async () => { + let data: any = {} + + for (let index = 0; index < (this.props.config.tabs || []).length; index++) { + const tab = (this.props.config.tabs || [])[index] + const fields = this.props.config.mode === 'same' ? (this.props.config.fields || []) : (((this.props.config.tabs || [])[index] || {}).fields || []) + + for (let formFieldIndex = 0; formFieldIndex < fields.length; formFieldIndex++) { + const formFieldConfig = fields[formFieldIndex] + if (!ConditionHelper(formFieldConfig.condition, { record: getValue(this.props.value, tab.field), data: this.props.data, step: this.props.step })) { + continue + } + const formField = this.formFieldsList[index] && this.formFieldsList[index][formFieldIndex] + if (formField) { + const value = await formField.get() + const fullPath = tab.field === '' || formFieldConfig.field === '' ? `${tab.field}${formFieldConfig.field}` : `${tab.field}.${formFieldConfig.field}` + data = setValue(data, fullPath, value) + } + } } - get = async () => { - let data: any = {} - - for (let index = 0; index < (this.props.config.tabs || []).length; index++) { - const tab = (this.props.config.tabs || [])[index] - const fields = this.props.config.mode === 'same' ? (this.props.config.fields || []) : (((this.props.config.tabs || [])[index] || {}).fields || []) - - for (let formFieldIndex = 0; formFieldIndex < fields.length; formFieldIndex++) { - const formFieldConfig = fields[formFieldIndex] - if (!ConditionHelper(formFieldConfig.condition, { record: getValue(this.props.value, tab.field), data: this.props.data, step: this.props.step })) { - continue - } - const formField = this.formFieldsList[index] && this.formFieldsList[index][formFieldIndex] - if (formField) { - const value = await formField.get() - const fullPath = tab.field === '' || formFieldConfig.field === '' ? `${tab.field}${formFieldConfig.field}` : `${tab.field}.${formFieldConfig.field}` - data = setValue(data, fullPath, value) - } - } - } - - return data - } + return data + } handleMount = async (index: number, formFieldIndex: number) => { if (!this.formFieldsMountedList[index]) { @@ -100,16 +103,9 @@ export default class TabsField extends Display { - if (!formDataList[index]) formDataList[index] = [] - formDataList[index][formFieldIndex] = { status: 'normal' } - return { formDataList: cloneDeep(formDataList) } - }) - } await formField.didMount() } } @@ -118,152 +114,86 @@ export default class TabsField extends Display { } - handleValueSet = async (index: number, formFieldIndex: number, path: string, value: any, validation: true | FieldError[]) => { + handleValueSet = async (index: number, formFieldIndex: number, path: string, value: any, options?: { noPathCombination?: boolean }) => { 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 fieldPath = options && options.noPathCombination ? `${formFieldConfig.field}${path}` : `${formFieldConfig.field}.${path}` const fullPath = tab.field === '' || fieldPath === '' ? `${tab.field}${fieldPath}` : `${tab.field}.${fieldPath}` - await this.props.onValueSet(fullPath, value, 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 - }) + await this.props.onValueSet(fullPath, value) } } - handleValueUnset = async (index: number, formFieldIndex: number, path: string, validation: true | FieldError[]) => { + handleValueUnset = async (index: number, formFieldIndex: number, path: string, options?: { noPathCombination?: boolean }) => { 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 fieldPath = options && options.noPathCombination ? `${formFieldConfig.field}${path}` : `${formFieldConfig.field}.${path}` const fullPath = tab.field === '' || fieldPath === '' ? `${tab.field}${fieldPath}` : `${tab.field}.${fieldPath}` - await this.props.onValueUnset(fullPath, 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 - }) + await this.props.onValueUnset(fullPath) } } - handleValueListAppend = async (index: number, formFieldIndex: number, path: string, value: any, validation: true | FieldError[]) => { + handleValueListAppend = async (index: number, formFieldIndex: number, path: string, value: any, options?: { noPathCombination?: boolean }) => { 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 fieldPath = options && options.noPathCombination ? `${formFieldConfig.field}${path}` : `${formFieldConfig.field}.${path}` const fullPath = tab.field === '' || fieldPath === '' ? `${tab.field}${fieldPath}` : `${tab.field}.${fieldPath}` - await this.props.onValueListAppend(fullPath, value, 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 - }) + await this.props.onValueListAppend(fullPath, value) } } - handleValueListSplice = async (index: number, formFieldIndex: number, path: string, _index: number, count: number, validation: true | FieldError[]) => { + handleValueListSplice = async (index: number, formFieldIndex: number, path: string, _index: number, count: number, options?: { noPathCombination?: boolean }) => { 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 fieldPath = options && options.noPathCombination ? `${formFieldConfig.field}${path}` : `${formFieldConfig.field}.${path}` const fullPath = tab.field === '' || fieldPath === '' ? `${tab.field}${fieldPath}` : `${tab.field}.${fieldPath}` - await this.props.onValueListSplice(fullPath, _index, count, 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 - }) + await this.props.onValueListSplice(fullPath, _index, count) } } - handleValueListSort = async (index: number, formFieldIndex: number, path: string, _index: number, sortType: 'up' | 'down', validation: true | FieldError[]) => { - const fields = this.props.config.mode === 'same' ? (this.props.config.fields || []) : (((this.props.config.tabs || [])[index] || {}).fields || []) - const formFieldConfig = fields[formFieldIndex] - if (formFieldConfig) { - 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 - }) - } - } - - /** - * 用于展示子表单组件 - * @param _props - * @returns - */ - renderComponent = (_props: ITabsField) => { - return + /** + * 用于展示子表单组件 + * @param _props + * @returns + */ + renderComponent = (_props: ITabsField) => { + return 您当前使用的UI版本没有实现FormField组件。 - } - - /** - * 用于展示子表单组件中的每一个子项 - * @param props - * @returns - */ - renderItemComponent = (props: ITabsFieldItem) => { - return + } + + /** + * 用于展示子表单组件中的每一个子项 + * @param props + * @returns + */ + renderItemComponent = (props: ITabsFieldItem) => { + return 您当前使用的UI版本没有实现FormField组件的renderItemComponent方法。 - } - - /** - * 用于展示子表单组件中的每一子项中的每一个子表单项组件 - * @param props - * @returns - */ - renderItemFieldComponent = (props: ITabsFieldItemField) => { - return + } + + /** + * 用于展示子表单组件中的每一子项中的每一个子表单项组件 + * @param props + * @returns + */ + renderItemFieldComponent = (props: ITabsFieldItemField) => { + return 您当前使用的UI版本没有实现FormField组件的renderItemFieldComponent方法。 - } + } render = () => { const { @@ -277,81 +207,76 @@ export default class TabsField extends Display { - const fields = this.props.config.mode === 'same' ? (this.props.config.fields || []) : (((this.props.config.tabs || [])[index] || {}).fields || []) - return ( - - {this.renderItemComponent({ - key: index.toString(), - label: tab.label, - children: fields.map((formFieldConfig, formFieldIndex) => { - if (!ConditionHelper(formFieldConfig.condition, { record: this.props.record, data: this.props.data, step: this.props.step })) { - if (!this.formFieldsMountedList[index]) this.formFieldsMountedList[index] = [] - this.formFieldsMountedList[index][formFieldIndex] = false - return null - } - let hidden: boolean = true - let display: boolean = true - - if (formFieldConfig.type === 'hidden') { - hidden = true - display = false - } - - if (formFieldConfig.display === 'none') { - hidden = true - display = false - } - - const FormField = this.getALLComponents(formFieldConfig.type) || Display - - let status = ((this.state.formDataList[index] || [])[formFieldIndex] || {}).status || 'normal' - - if (['group', 'import_subform', 'object', 'tabs', 'form'].some((type) => type === formFieldConfig.type)) { - status = 'normal' - } - // 渲染表单项容器 - if (hidden) { - return ( -
- {this.renderItemFieldComponent({ - index: formFieldIndex, - label: formFieldConfig.label, - status, - message: ((this.state.formDataList[index] || [])[formFieldIndex] || {}).message || '', - required: getBoolean(formFieldConfig.required), - fieldType: formFieldConfig.type, - children: ( - | null) => { - if (!this.formFieldsList[index]) this.formFieldsList[index] = [] - this.formFieldsList[index][formFieldIndex] = formField - this.handleMount(index, formFieldIndex) - }} - value={getValue(getValue(value, tab.field), formFieldConfig.field)} - record={getValue(value, tab.field)} - data={cloneDeep(this.props.data)} - step={this.props.step} - config={formFieldConfig} - onValueSet={async (path, value, validation) => this.handleValueSet(index, formFieldIndex, path, value, validation)} - onValueUnset={async (path, validation) => 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)} - baseRoute={this.props.baseRoute} - loadDomain={async (domain: string) => await this.props.loadDomain(domain)} - /> - ) - })} -
- ) - } else { - return - } - }) - })} - - ) - }) + const fields = this.props.config.mode === 'same' ? (this.props.config.fields || []) : (((this.props.config.tabs || [])[index] || {}).fields || []) + return ( + + {this.renderItemComponent({ + key: index.toString(), + label: tab.label, + children: fields.map((formFieldConfig, formFieldIndex) => { + if (!ConditionHelper(formFieldConfig.condition, { record: this.props.record, data: this.props.data, step: this.props.step })) { + if (!this.formFieldsMountedList[index]) this.formFieldsMountedList[index] = [] + this.formFieldsMountedList[index][formFieldIndex] = false + return null + } + let hidden: boolean = true + let display: boolean = true + + if (formFieldConfig.type === 'hidden') { + hidden = true + display = false + } + + if (formFieldConfig.display === 'none') { + hidden = true + display = false + } + + const FormField = this.getALLComponents(formFieldConfig.type) || Display + + let status: 'normal' = 'normal' + // 渲染表单项容器 + if (hidden) { + return ( +
+ {this.renderItemFieldComponent({ + index: formFieldIndex, + label: formFieldConfig.label, + status, + required: getBoolean(formFieldConfig.required), + fieldType: formFieldConfig.type, + children: ( + | null) => { + if (!this.formFieldsList[index]) this.formFieldsList[index] = [] + this.formFieldsList[index][formFieldIndex] = formField + this.handleMount(index, formFieldIndex) + }} + value={getValue(getValue(value, tab.field), formFieldConfig.field)} + record={getValue(value, tab.field)} + data={cloneDeep(this.props.data)} + step={this.props.step} + config={formFieldConfig} + onValueSet={async (path, value, validation) => this.handleValueSet(index, formFieldIndex, path, value, validation)} + onValueUnset={async (path, validation) => 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)} + baseRoute={this.props.baseRoute} + loadDomain={async (domain: string) => await this.props.loadDomain(domain)} + /> + ) + })} +
+ ) + } else { + return + } + }) + })} + + ) + }) : [] ) }) -- Gitee From 49b62433a87d31b33be8c335208dafc9c44c8a20 Mon Sep 17 00:00:00 2001 From: zjt Date: Wed, 20 Apr 2022 18:02:47 +0800 Subject: [PATCH 16/23] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index c2edd2d..3fe0b54 100644 --- a/package.json +++ b/package.json @@ -28,12 +28,13 @@ } }, "lint-staged": { - "src/*.{js, jsx, ts, tsx}": [ - "npm run prettier", - "npm run lint" + "*.{js,jsx,ts,tsx}": [ + "eslint --fix", + "git add" ], - "src/*.{css,scss,less,json,html,md,markdown}": [ - "npm run prettier" + "*.{json,html,md,markdown}": [ + "prettier --write", + "git add -f" ] }, "config": { -- Gitee From 69c128c1ae239b56246768b82ca67c89b336cd3a Mon Sep 17 00:00:00 2001 From: zjt Date: Wed, 20 Apr 2022 21:05:34 +0800 Subject: [PATCH 17/23] =?UTF-8?q?fix:=20=E5=90=88=E5=B9=B6v1.3.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 1 + src/util/produce.tsx | 27 +++++++++++++++------------ src/util/value.ts | 4 ++-- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/package.json b/package.json index 3fe0b54..e647667 100644 --- a/package.json +++ b/package.json @@ -51,6 +51,7 @@ "@types/react": "^16.9.46", "@types/react-router-dom": "^5.1.5", "axios": "^0.20.0", + "immer": "^9.0.7", "lodash": "^4.17.21", "marked": "^1.2.5", "moment": "^2.29.0", diff --git a/src/util/produce.tsx b/src/util/produce.tsx index 2d97d10..60b9ff1 100644 --- a/src/util/produce.tsx +++ b/src/util/produce.tsx @@ -1,7 +1,6 @@ import produce, { setAutoFreeze } from 'immer' import lodash from 'lodash' -import { listItemMove } from '../util/value' - +import { listItemMove } from './value' /** * setAutoFreeze @@ -21,7 +20,8 @@ setAutoFreeze(false) export function set(current: any, path?: string, value?: any) { const target = produce(current, (draft: any) => { if (path) { - if (arguments.length === 2) { // 移除对象路径的属性 参数改动时同步修改这块 + if (arguments.length === 2) { + // 移除对象路径的属性 参数改动时同步修改这块 lodash.unset(draft, path) } else { return lodash.set(draft, path, value) @@ -38,11 +38,12 @@ export function set(current: any, path?: string, value?: any) { * @param value * @returns */ -export const push = (current: any, path: string = '', value?: any) => { +export const push = (current: any, path = '', value?: any) => { const target = produce(current, (draft: any) => { const list = lodash.get(draft, path) - if (!Array.isArray(list)) { // 如果指定路径下不是数组类型 - var tempArr = [] + if (!Array.isArray(list)) { + // 如果指定路径下不是数组类型 + const tempArr: any[] = [] tempArr.push(value) lodash.set(draft, path, tempArr) } else { @@ -60,7 +61,7 @@ export const push = (current: any, path: string = '', value?: any) => { * @param count * @returns */ -export const splice = (current: any, path: string = '', index: number, count: number) => { +export const splice = (current: any, path = '', index: number, count: number) => { const target = produce(current, (draft: any) => { const list = lodash.get(draft, path, []) list.splice(index, count) @@ -76,7 +77,7 @@ export const splice = (current: any, path: string = '', index: number, count: nu * @param sortType * @returns */ -export const sort = (current: any, path: string = '', index: number, sortType: 'up' | 'down') => { +export const sort = (current: any, path = '', index: number, sortType: 'up' | 'down') => { const target = produce(current, (draft: any) => { const list = lodash.get(draft, path, []) listItemMove(list, index, sortType) @@ -98,14 +99,13 @@ const merge = (a: any, b: any): any => { if (lodash.isObject(b)) { if (lodash.isArray(a)) { return merge(a, b).filter((i: any) => i !== undefined) - } else { - return merge(a, b) } + return merge(a, b) } }) } -export const setValue = (obj: any, path: string = '', value: any) => { +export const setValue = (obj: any, path = '', value: any) => { const target = produce(obj, (draft: any) => { if (path === '') { if (Object.prototype.toString.call(value) === '[object Object]') { @@ -115,7 +115,10 @@ export const setValue = (obj: any, path: string = '', value: any) => { } } else { const source = lodash.get(draft, path) - if (Object.prototype.toString.call(value) === '[object Object]' && Object.prototype.toString.call(source) === '[object Object]') { + if ( + Object.prototype.toString.call(value) === '[object Object]' && + Object.prototype.toString.call(source) === '[object Object]' + ) { lodash.set(draft, path, merge(source, value)) } else { lodash.set(draft, path, value) diff --git a/src/util/value.ts b/src/util/value.ts index 6a2eef4..6cf1f15 100644 --- a/src/util/value.ts +++ b/src/util/value.ts @@ -134,8 +134,8 @@ export const getChainPath = (...arg: any[]) => { * @param find 目标字符串 * @returns 返回目标字符串出现在来源字符串中所有索引 */ -function indexes (source: string, find: string) { - const result = [] +function indexes(source: string, find: string) { + const result: number[] = [] for (let i = 0; i < source.length; ++i) { if (source.substring(i, i + find.length) === find) { result.push(i) -- Gitee From ae027fcd1ad6e334fe66384f6d6d31f81c3c46e1 Mon Sep 17 00:00:00 2001 From: zhenjintao Date: Thu, 21 Apr 2022 10:47:10 +0800 Subject: [PATCH 18/23] =?UTF-8?q?fix:=20=E5=8E=BB=E9=99=A4=E5=AF=B9package?= =?UTF-8?q?-lock.json=E7=9A=84=E5=BF=BD=E7=95=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index acebde4..4c4d10b 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,3 @@ node_modules dist lib coverage -package-lock.json \ No newline at end of file -- Gitee From 424e71756fd5d5903e6963c9e6552fce9cbb639d Mon Sep 17 00:00:00 2001 From: zjt Date: Thu, 21 Apr 2022 16:17:43 +0800 Subject: [PATCH 19/23] =?UTF-8?q?doc:=20=E5=BF=BD=E7=95=A5package-lock.jso?= =?UTF-8?q?n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 4c4d10b..b3f0ce9 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ node_modules dist lib coverage +package-lock.json -- Gitee From de2b6241a7fd63fe2a86a9eab36b406f2d09af9c Mon Sep 17 00:00:00 2001 From: zjt Date: Fri, 22 Apr 2022 12:36:41 +0800 Subject: [PATCH 20/23] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9render?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/detail/importSubform/index.tsx | 257 +++++++++++------- 1 file changed, 166 insertions(+), 91 deletions(-) diff --git a/src/components/detail/importSubform/index.tsx b/src/components/detail/importSubform/index.tsx index 0832aa3..46d3a30 100644 --- a/src/components/detail/importSubform/index.tsx +++ b/src/components/detail/importSubform/index.tsx @@ -1,11 +1,11 @@ import React from 'react' -import { getValue , getChainPath} from '../../../util/value' +import { cloneDeep, isEqual } from 'lodash' +import { getValue, getChainPath } from '../../../util/value' import { DetailField, DetailFieldConfig, DetailFieldProps, IDetailField } from '../common' import { Display } from '../../formFields/common' import { display as getALLComponents, FieldConfigs } from '../../formFields' import { IDetailItem } from '../../../steps/detail' -import { cloneDeep, isEqual } from 'lodash' import ConditionHelper from '../../../util/condition' import InterfaceHelper, { InterfaceConfig } from '../../../util/interface' import { ColumnsConfig } from '../../../interface' @@ -19,7 +19,7 @@ import { ColumnsConfig } from '../../../interface' * - * - interface: 来源接口配置 // 仅type为interface时生效 */ export interface ImportSubformFieldConfig extends DetailFieldConfig { - type: 'import_subform', + type: 'import_subform' configFrom?: ImportSubformConfigFromData | ImportSubformConfigFromInterface childColumns?: ColumnsConfig } @@ -43,23 +43,28 @@ export interface IImportSubformField { interface IImportSubformFieldState { didMount: boolean fields: FieldConfigs[] - formData: { status: 'normal' | 'error' | 'loading', message?: string }[] + formData: { status: 'normal' | 'error' | 'loading'; message?: string }[] } -export default class DetailImportSubformField extends DetailField implements IDetailField { +export default class DetailImportSubformField + extends DetailField + implements IDetailField +{ // 各表单项对应的类型所使用的UI组件的类 getALLComponents = (type: any): typeof Display => getALLComponents[type] // 用于请求防频的判断条件 - requestConfig: string = '' - value: string = '' + requestConfig = '' + + value = '' formFields: Array | null> = [] + formFieldsMounted: Array = [] interfaceHelper = new InterfaceHelper() - constructor (props: DetailFieldProps) { + constructor(props: DetailFieldProps) { super(props) this.state = { @@ -69,8 +74,6 @@ export default class DetailImportSubformField extends DetailField { await this.setState({ didMount: true @@ -86,11 +89,14 @@ export default class DetailImportSubformField extends DetailField { - const withConfigPath = this.props.config.configFrom?.type === 'data' && this.props.config.configFrom.dataField ? `${this.props.config.configFrom.dataField}` : '' + handleValueSet = async ( + formFieldIndex: number, + path: string, + value: any, + options?: { noPathCombination?: boolean } + ) => { + const withConfigPath = + this.props.config.configFrom?.type === 'data' && this.props.config.configFrom.dataField + ? `${this.props.config.configFrom.dataField}` + : '' const formFieldConfig = (this.state.fields || [])[formFieldIndex] if (formFieldConfig) { - const fullPath = options && options.noPathCombination ? path : getChainPath(withConfigPath, formFieldConfig.field, path) + const fullPath = + options && options.noPathCombination ? path : getChainPath(withConfigPath, formFieldConfig.field, path) await this.props.onValueSet(fullPath, value) } } handleValueUnset = async (formFieldIndex: number, path: string, options?: { noPathCombination?: boolean }) => { - const withConfigPath = this.props.config.configFrom?.type === 'data' && this.props.config.configFrom.dataField ? `${this.props.config.configFrom.dataField}` : '' + const withConfigPath = + this.props.config.configFrom?.type === 'data' && this.props.config.configFrom.dataField + ? `${this.props.config.configFrom.dataField}` + : '' const formFieldConfig = (this.state.fields || [])[formFieldIndex] if (formFieldConfig) { - const fullPath = options && options.noPathCombination ? path : getChainPath(withConfigPath, formFieldConfig.field, path) + const fullPath = + options && options.noPathCombination ? path : getChainPath(withConfigPath, formFieldConfig.field, path) await this.props.onValueUnset(fullPath) } } - handleValueListAppend = async (formFieldIndex: number, path: string, value: any, options?: { noPathCombination?: boolean }) => { - const withConfigPath = this.props.config.configFrom?.type === 'data' && this.props.config.configFrom.dataField ? `${this.props.config.configFrom.dataField}` : '' + handleValueListAppend = async ( + formFieldIndex: number, + path: string, + value: any, + options?: { noPathCombination?: boolean } + ) => { + const withConfigPath = + this.props.config.configFrom?.type === 'data' && this.props.config.configFrom.dataField + ? `${this.props.config.configFrom.dataField}` + : '' const formFieldConfig = (this.state.fields || [])[formFieldIndex] if (formFieldConfig) { - const fullPath = options && options.noPathCombination ? path : getChainPath(withConfigPath, formFieldConfig.field, path) + const fullPath = + options && options.noPathCombination ? path : getChainPath(withConfigPath, formFieldConfig.field, path) await this.props.onValueListAppend(fullPath, value) } } - handleValueListSplice = async (formFieldIndex: number, path: string, index: number, count: number, options?: { noPathCombination?: boolean }) => { - const withConfigPath = this.props.config.configFrom?.type === 'data' && this.props.config.configFrom.dataField ? `${this.props.config.configFrom.dataField}` : '' + handleValueListSplice = async ( + formFieldIndex: number, + path: string, + index: number, + count: number, + options?: { noPathCombination?: boolean } + ) => { + const withConfigPath = + this.props.config.configFrom?.type === 'data' && this.props.config.configFrom.dataField + ? `${this.props.config.configFrom.dataField}` + : '' const formFieldConfig = (this.state.fields || [])[formFieldIndex] if (formFieldConfig) { - const fullPath = options && options.noPathCombination ? path : getChainPath(withConfigPath, formFieldConfig.field, path) + const fullPath = + options && options.noPathCombination ? path : getChainPath(withConfigPath, formFieldConfig.field, path) await this.props.onValueListSplice(fullPath, index, count) } } renderComponent = (props: IImportSubformField) => { - return - 您当前使用的UI版本没有实现ImportSubformField组件。 - + return <>您当前使用的UI版本没有实现ImportSubformField组件。 } /** @@ -150,83 +186,117 @@ export default class DetailImportSubformField extends DetailField { - return - 您当前使用的UI版本没有实现FormItem组件。 - + return <>您当前使用的UI版本没有实现FormItem组件。 + } + + /** + * 处理data 兼容非法json的情况 + * @param {any} data 待处理数据 + * @returns 返回data反序列化形式 + */ + handleDataToUnstringfy = (data: any) => { + let dataToUnstringfy = data + if (Object.prototype.toString.call(data) === '[object String]') { + try { + dataToUnstringfy = JSON.parse(data) + } catch (e) { + console.error('当前动态子表单接口响应数据格式不是合格的json字符串') + dataToUnstringfy = [] + } + } + return dataToUnstringfy } - getConfigData=() => { - const { - config, - value - } = this.props + getConfigData = () => { + const { config, value } = this.props if (config.configFrom && config.configFrom.type === 'interface' && config.configFrom.interface) { - this.interfaceHelper.request( - config.configFrom.interface, - {}, - { record: this.props.record, data: this.props.data, step: this.props.step }, - { loadDomain: this.props.loadDomain } - ).then((data: any) => { - let dataToUnstringfy = data - let dataToStringfy = JSON.stringify(data) - if (Object.prototype.toString.call(data) === '[object String]') { - try { - dataToStringfy = data - dataToUnstringfy = JSON.parse(data) - } catch (e) { - console.error('当前动态子表单接口响应数据格式不是合格的json字符串') - dataToUnstringfy = [] - dataToStringfy = '[]' + this.interfaceHelper + .request( + config.configFrom.interface, + {}, + { record: this.props.record, data: this.props.data, step: this.props.step }, + { loadDomain: this.props.loadDomain } + ) + .then((data: any) => { + const dataToUnstringfy = this.handleDataToUnstringfy(data) + if (!isEqual(dataToUnstringfy, this.state.fields)) { + this.setState({ + fields: dataToUnstringfy + }) } - } - if (dataToStringfy !== JSON.stringify(this.state.fields)) { - this.setState({ - fields: dataToUnstringfy - }) - } - }) + }) } - let fields = this.state.fields + + let { fields } = this.state if (config.configFrom && config.configFrom.type === 'data') { fields = config.configFrom.configField ? getValue(value, config.configFrom.configField) : [] - if (!isEqual(fields, this.state.fields)) { + const dataToUnstringfy = this.handleDataToUnstringfy(fields) + if (!isEqual(dataToUnstringfy, this.state.fields)) { this.setState({ - fields + fields: dataToUnstringfy }) } } } - componentDidMount () { - this.getConfigData() - } + // componentDidMount() { + // this.getConfigData() + // } + + // componentDidUpdate() { + // this.getConfigData() + // } render = () => { - const { - config, - formLayout, - value, - record, - data, - step - } = this.props - - const fields = this.state.fields + const { config, formLayout, value, record, data, step } = this.props + + let { fields } = this.state + if (config.configFrom && config.configFrom.type === 'data') { + fields = config.configFrom.configField ? getValue(value, config.configFrom.configField) : [] + const dataToUnstringfy = this.handleDataToUnstringfy(fields) + if (!isEqual(dataToUnstringfy, this.state.fields)) { + this.setState({ + fields: dataToUnstringfy + }) + } + } + + if (config.configFrom && config.configFrom.type === 'interface' && config.configFrom.interface) { + this.interfaceHelper + .request( + config.configFrom.interface, + {}, + { record: this.props.record, data: this.props.data, step: this.props.step }, + { loadDomain: this.props.loadDomain } + ) + .then((data: any) => { + const dataToUnstringfy = this.handleDataToUnstringfy(data) + if (!isEqual(dataToUnstringfy, this.state.fields)) { + this.setState({ + fields: dataToUnstringfy + }) + } + }) + } + if (!fields || !Array.isArray(fields) || fields.length === 0) { - return - } else { - const withConfigPath = this.props.config.configFrom?.type === 'data' && this.props.config.configFrom.dataField ? `${this.props.config.configFrom.dataField}` : '' - return ( - - {this.renderComponent({ - columns: config?.columns?.enable ? config.columns : undefined, - children: this.state.didMount - ? fields.map((formFieldConfig, formFieldIndex) => { + return <> + } + const withConfigPath = + this.props.config.configFrom?.type === 'data' && this.props.config.configFrom.dataField + ? `${this.props.config.configFrom.dataField}` + : '' + return ( + <> + {this.renderComponent({ + columns: config?.columns?.enable ? config.columns : undefined, + children: this.state.didMount + ? fields.map((formFieldConfig, formFieldIndex) => { if (!ConditionHelper(formFieldConfig.condition, { record: value, data, step })) { this.formFieldsMounted[formFieldIndex] = false return null } - let display: boolean = true + let display = true if (formFieldConfig.type === 'hidden' || formFieldConfig.display === 'none') { display = false @@ -263,10 +333,16 @@ export default class DetailImportSubformField extends DetailField this.handleValueSet(formFieldIndex, path, value, options)} + onValueSet={async (path, value, options) => + this.handleValueSet(formFieldIndex, path, value, options) + } onValueUnset={async (path, options) => this.handleValueUnset(formFieldIndex, path, options)} - onValueListAppend={async (path, value, options) => this.handleValueListAppend(formFieldIndex, path, value, options)} - onValueListSplice={async (path, index, count, options) => this.handleValueListSplice(formFieldIndex, path, index, count, options)} + onValueListAppend={async (path, value, options) => + this.handleValueListAppend(formFieldIndex, path, value, options) + } + onValueListSplice={async (path, index, count, options) => + this.handleValueListSplice(formFieldIndex, path, index, count, options) + } baseRoute={this.props.baseRoute} loadDomain={async (domain: string) => await this.props.loadDomain(domain)} /> @@ -275,10 +351,9 @@ export default class DetailImportSubformField extends DetailField - ) - } + : [] + })} + + ) } } -- Gitee From a10471d4d5326949122370e0a2521e6deedc928e Mon Sep 17 00:00:00 2001 From: zjt Date: Fri, 22 Apr 2022 13:37:21 +0800 Subject: [PATCH 21/23] =?UTF-8?q?fix:=20=E8=A1=A5=E5=85=85update?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/detail/importSubform/index.tsx | 42 +----- .../formFields/importSubform/display.tsx | 141 +++++++++--------- 2 files changed, 79 insertions(+), 104 deletions(-) diff --git a/src/components/detail/importSubform/index.tsx b/src/components/detail/importSubform/index.tsx index 46d3a30..a4360cd 100644 --- a/src/components/detail/importSubform/index.tsx +++ b/src/components/detail/importSubform/index.tsx @@ -1,5 +1,6 @@ import React from 'react' import { cloneDeep, isEqual } from 'lodash' +import { setTimeout } from 'timers' import { getValue, getChainPath } from '../../../util/value' import { DetailField, DetailFieldConfig, DetailFieldProps, IDetailField } from '../common' @@ -239,45 +240,18 @@ export default class DetailImportSubformField } } - // componentDidMount() { - // this.getConfigData() - // } + componentDidMount() { + this.getConfigData() + } - // componentDidUpdate() { - // this.getConfigData() - // } + componentDidUpdate() { + this.getConfigData() + } render = () => { const { config, formLayout, value, record, data, step } = this.props - let { fields } = this.state - if (config.configFrom && config.configFrom.type === 'data') { - fields = config.configFrom.configField ? getValue(value, config.configFrom.configField) : [] - const dataToUnstringfy = this.handleDataToUnstringfy(fields) - if (!isEqual(dataToUnstringfy, this.state.fields)) { - this.setState({ - fields: dataToUnstringfy - }) - } - } - - if (config.configFrom && config.configFrom.type === 'interface' && config.configFrom.interface) { - this.interfaceHelper - .request( - config.configFrom.interface, - {}, - { record: this.props.record, data: this.props.data, step: this.props.step }, - { loadDomain: this.props.loadDomain } - ) - .then((data: any) => { - const dataToUnstringfy = this.handleDataToUnstringfy(data) - if (!isEqual(dataToUnstringfy, this.state.fields)) { - this.setState({ - fields: dataToUnstringfy - }) - } - }) - } + const { fields } = this.state if (!fields || !Array.isArray(fields) || fields.length === 0) { return <> diff --git a/src/components/formFields/importSubform/display.tsx b/src/components/formFields/importSubform/display.tsx index 52b90e5..4e0eae5 100644 --- a/src/components/formFields/importSubform/display.tsx +++ b/src/components/formFields/importSubform/display.tsx @@ -1,11 +1,11 @@ import React from 'react' +import { cloneDeep, isEqual } from 'lodash' import { getValue } from '../../../util/value' import { DetailField, DetailFieldConfig, DetailFieldProps, IDetailField } from '../../detail/common' -import { Display } from '../../formFields/common' -import { display as getALLComponents, FieldConfigs } from '../../formFields' +import { Display } from '../common' +import { display as getALLComponents, FieldConfigs } from '..' import { IDetailItem } from '../../../steps/detail' -import { cloneDeep, isEqual } from 'lodash' import ConditionHelper from '../../../util/condition' import InterfaceHelper, { InterfaceConfig } from '../../../util/interface' /** @@ -16,7 +16,7 @@ import InterfaceHelper, { InterfaceConfig } from '../../../util/interface' * - * - configField: (序列化)配置 */ export interface ImportSubformFieldConfig extends DetailFieldConfig { - type: 'import_subform', + type: 'import_subform' configFrom?: ImportSubformConfigFromData | ImportSubformConfigFromInterface } @@ -38,18 +38,23 @@ export interface IImportSubformField { interface IImportSubformFieldState { didMount: boolean fields: FieldConfigs[] - formData: { status: 'normal' | 'error' | 'loading', message?: string }[] + formData: { status: 'normal' | 'error' | 'loading'; message?: string }[] } -export default class ImportSubformFieldDisplay extends DetailField implements IDetailField { +export default class ImportSubformFieldDisplay + extends DetailField + implements IDetailField +{ // 各表单项对应的类型所使用的UI组件的类 getALLComponents = (type: any): typeof Display => getALLComponents[type] // 用于请求防频的判断条件 - requestConfig: string = '' - value: string = '' + requestConfig = '' + + value = '' formFields: Array | null> = [] + formFieldsMounted: Array = [] interfaceHelper = new InterfaceHelper() @@ -64,9 +69,11 @@ export default class ImportSubformFieldDisplay extends DetailField Promise = async (value) => { return value - }; + } handleMount = async (formFieldIndex: number) => { if (this.formFieldsMounted[formFieldIndex]) { @@ -94,7 +101,7 @@ export default class ImportSubformFieldDisplay extends DetailField { - const { - config, - value - } = this.props + const { config, value } = this.props if (config.configFrom && config.configFrom.type === 'interface' && config.configFrom.interface) { - this.interfaceHelper.request( - config.configFrom.interface, - {}, - { record: this.props.record, data: this.props.data, step: this.props.step }, - { loadDomain: this.props.loadDomain } - ).then((data: any) => { - let dataToUnstringfy = data - let dataToStringfy = JSON.stringify(data) - if (Object.prototype.toString.call(data) === '[object String]') { - try { - dataToStringfy = data - dataToUnstringfy = JSON.parse(data) - } catch (e) { - console.error('当前动态子表单接口响应数据格式不是合格的json字符串') - dataToUnstringfy = [] - dataToStringfy = '[]' + this.interfaceHelper + .request( + config.configFrom.interface, + {}, + { record: this.props.record, data: this.props.data, step: this.props.step }, + { loadDomain: this.props.loadDomain } + ) + .then((data: any) => { + let dataToUnstringfy = data + let dataToStringfy = JSON.stringify(data) + if (Object.prototype.toString.call(data) === '[object String]') { + try { + dataToStringfy = data + dataToUnstringfy = JSON.parse(data) + } catch (e) { + console.error('当前动态子表单接口响应数据格式不是合格的json字符串') + dataToUnstringfy = [] + dataToStringfy = '[]' + } } - } - if (dataToStringfy !== JSON.stringify(this.state.fields)) { - this.setState({ - fields: dataToUnstringfy - }) - } - }) + if (dataToStringfy !== JSON.stringify(this.state.fields)) { + this.setState({ + fields: dataToUnstringfy + }) + } + }) } - let fields = this.state.fields + let { fields } = this.state if (config.configFrom && config.configFrom.type === 'data') { fields = config.configFrom.configField ? getValue(value, config.configFrom.configField) : [] if (!isEqual(fields, this.state.fields)) { @@ -152,6 +158,10 @@ export default class ImportSubformFieldDisplay extends DetailField { const formFieldConfig = (this.state.fields || [])[formFieldIndex] if (formFieldConfig) { @@ -185,9 +195,7 @@ export default class ImportSubformFieldDisplay extends DetailField { - return - 您当前使用的UI版本没有实现ImportSubformField组件。 - + return <>您当前使用的UI版本没有实现ImportSubformField组件。 } /** @@ -196,34 +204,26 @@ export default class ImportSubformFieldDisplay extends DetailField { - return - 您当前使用的UI版本没有实现FormItem组件。 - + return <>您当前使用的UI版本没有实现FormItem组件。 } render = () => { - const { - config, - value, - record, - data, - step - } = this.props - const fields = this.state.fields + const { config, value, record, data, step } = this.props + const { fields } = this.state if (!fields || !Array.isArray(fields) || fields.length === 0) { - return - } else { - return ( - - {this.renderComponent({ - children: this.state.didMount - ? fields.map((formFieldConfig, formFieldIndex) => { + return <> + } + return ( + <> + {this.renderComponent({ + children: this.state.didMount + ? fields.map((formFieldConfig, formFieldIndex) => { if (!ConditionHelper(formFieldConfig.condition, { record: value, data, step })) { this.formFieldsMounted[formFieldIndex] = false return null } - let display: boolean = true + let display = true if (formFieldConfig.type === 'hidden' || formFieldConfig.display === 'none') { display = false @@ -236,7 +236,7 @@ export default class ImportSubformFieldDisplay extends DetailField this.handleValueSet(formFieldIndex, path, value)} onValueUnset={async (path) => this.handleValueUnset(formFieldIndex, path)} onValueListAppend={async (path, value) => this.handleValueListAppend(formFieldIndex, path, value)} - onValueListSplice={async (path, index, count) => this.handleValueListSplice(formFieldIndex, path, index, count)} + onValueListSplice={async (path, index, count) => + this.handleValueListSplice(formFieldIndex, path, index, count) + } baseRoute={this.props.baseRoute} loadDomain={async (domain: string) => await this.props.loadDomain(domain)} /> @@ -263,10 +265,9 @@ export default class ImportSubformFieldDisplay extends DetailField - ) - } + : [] + })} + + ) } } -- Gitee From 4de1c769703445cff3e021b445e8622e18cb6543 Mon Sep 17 00:00:00 2001 From: zjt Date: Fri, 22 Apr 2022 16:35:57 +0800 Subject: [PATCH 22/23] =?UTF-8?q?fix:=20fields/importSubform=E7=9A=84rende?= =?UTF-8?q?r=E4=B8=AD=E5=8E=BB=E6=8E=89setState?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../formFields/importSubform/index.tsx | 449 +++++++++++------- 1 file changed, 281 insertions(+), 168 deletions(-) diff --git a/src/components/formFields/importSubform/index.tsx b/src/components/formFields/importSubform/index.tsx index e16aa67..f2e7fed 100644 --- a/src/components/formFields/importSubform/index.tsx +++ b/src/components/formFields/importSubform/index.tsx @@ -3,7 +3,7 @@ import { isEqual } from 'lodash' import { getValue, getBoolean, getChainPath } from '../../../util/value' import { Field, FieldConfig, FieldError, FieldProps, IField } from '../common' -import getALLComponents, { FieldConfigs } from '../' +import getALLComponents, { FieldConfigs } from '..' import { IFormItem } from '../../../steps/form' import { set, setValue } from '../../../util/produce' import ConditionHelper from '../../../util/condition' @@ -24,7 +24,7 @@ import { ColumnsConfig } from '../../../interface' * - * - configField: (序列化)配置 */ export interface ImportSubformFieldConfig extends FieldConfig { - type: 'import_subform', + type: 'import_subform' interface?: InterfaceConfig configFrom?: ImportSubformConfigFromData | ImportSubformConfigFromInterface withConfig?: { @@ -52,22 +52,28 @@ export interface IImportSubformField { interface IImportSubformFieldState { didMount: boolean fields: FieldConfigs[] - formData: { status: 'normal' | 'error' | 'loading', message?: string }[] + formData: { status: 'normal' | 'error' | 'loading'; message?: string }[] } -export default class ImportSubformField extends Field implements IField { +export default class ImportSubformField + extends Field + implements IField +{ // 各表单项对应的类型所使用的UI组件的类 getALLComponents = (type: any): typeof Field => getALLComponents[type] // 用于请求防频的判断条件 - requestConfig: string = '' - value: string = '' + requestConfig = '' + + value = '' formFields: Array | null> = [] + formFieldsMounted: Array = [] + interfaceHelper = new InterfaceHelper() - constructor (props: FieldProps) { + constructor(props: FieldProps) { super(props) this.state = { @@ -89,19 +95,37 @@ export default class ImportSubformField extends Field => { const errors: FieldError[] = [] let childrenError = 0 - const childrenErrorMsg: Array<{name:string, msg:string}> = [] + const childrenErrorMsg: Array<{ name: string; msg: string }> = [] - let formData = this.state.formData + let { formData } = this.state - for (const fieldIndex in (this.state.fields || [])) { + for (const fieldIndex in this.state.fields || []) { const formItem = this.formFields[fieldIndex] - const formConfig = this.state.fields?.[fieldIndex] - if (formItem !== null && formItem !== undefined) { - const withConfigPath = this.props.config.withConfig?.enable && this.props.config.withConfig?.dataField ? `${this.props.config.withConfig.dataField}` : '' - const validation = await formItem.validate(getValue(value, getChainPath(withConfigPath, (this.state.fields || [])[fieldIndex].field))) + const formConfig = this.state.fields?.[fieldIndex] + if (formItem !== null && formItem !== undefined) { + const withConfigPath = + this.props.config.withConfig?.enable && this.props.config.withConfig?.dataField + ? `${this.props.config.withConfig.dataField}` + : '' + const validation = await formItem.validate( + getValue(value, getChainPath(withConfigPath, (this.state.fields || [])[fieldIndex].field)) + ) if (validation === true || this.formFieldsMounted[fieldIndex] === false) { formData = set(formData, `[${fieldIndex}]`, { status: 'normal' }) @@ -154,7 +182,9 @@ export default class ImportSubformField extends Field 0) { - const errTips = `${this.props.config.label || ''}子项中错误。\n ${childrenErrorMsg.map(err => `${err.name}:${err.msg}`).join('; ')}。` + const errTips = `${this.props.config.label || ''}子项中错误。\n ${childrenErrorMsg + .map((err) => `${err.name}:${err.msg}`) + .join('; ')}。` errors.push(new FieldError(errTips)) } @@ -171,12 +201,15 @@ export default class ImportSubformField extends Field { // const formField = this.formFields[formFieldIndex] // const formFieldConfig = this.state.fields[formFieldIndex] - // const formData = cloneDeep(this.state.formData) - // if (formField && formFieldConfig) { // if (this.props.onChange) { // if (formFieldConfig.field === '') { @@ -208,14 +239,12 @@ export default class ImportSubformField extends Field { - let formData = this.state.formData + let { formData } = this.state if (validation === true) { formData = set(formData, `[${formFieldIndex}]`, { status: 'normal' }) } else { @@ -237,55 +266,106 @@ export default class ImportSubformField extends Field { + handleValueSet = async ( + formFieldIndex: number, + path: string, + value: any, + validation: true | FieldError[], + options?: { noPathCombination?: boolean } + ) => { const formFieldConfig = (this.state.fields || [])[formFieldIndex] if (formFieldConfig) { - const withConfigPath = this.props.config.withConfig?.enable && this.props.config.withConfig?.dataField ? `${this.props.config.withConfig.dataField}` : '' - const fullPath = options && options.noPathCombination ? path : getChainPath(withConfigPath, formFieldConfig.field, path) + const withConfigPath = + this.props.config.withConfig?.enable && this.props.config.withConfig?.dataField + ? `${this.props.config.withConfig.dataField}` + : '' + const fullPath = + options && options.noPathCombination ? path : getChainPath(withConfigPath, formFieldConfig.field, path) await this.props.onValueSet(fullPath, value, true) this.handleValueCallback(formFieldIndex, validation) } } - handleValueUnset = async (formFieldIndex: number, path: string, validation: true | FieldError[], options?: { noPathCombination?: boolean }) => { + handleValueUnset = async ( + formFieldIndex: number, + path: string, + validation: true | FieldError[], + options?: { noPathCombination?: boolean } + ) => { const formFieldConfig = (this.state.fields || [])[formFieldIndex] if (formFieldConfig) { - const withConfigPath = this.props.config.withConfig?.enable && this.props.config.withConfig?.dataField ? `${this.props.config.withConfig.dataField}` : '' - const fullPath = options && options.noPathCombination ? path : getChainPath(withConfigPath, formFieldConfig.field, path) + const withConfigPath = + this.props.config.withConfig?.enable && this.props.config.withConfig?.dataField + ? `${this.props.config.withConfig.dataField}` + : '' + const fullPath = + options && options.noPathCombination ? path : getChainPath(withConfigPath, formFieldConfig.field, path) await this.props.onValueUnset(fullPath, true) this.handleValueCallback(formFieldIndex, validation) } } - handleValueListAppend = async (formFieldIndex: number, path: string, value: any, validation: true | FieldError[], options?: { noPathCombination?: boolean }) => { + handleValueListAppend = async ( + formFieldIndex: number, + path: string, + value: any, + validation: true | FieldError[], + options?: { noPathCombination?: boolean } + ) => { const formFieldConfig = (this.state.fields || [])[formFieldIndex] if (formFieldConfig) { - const withConfigPath = this.props.config.withConfig?.enable && this.props.config.withConfig?.dataField ? `${this.props.config.withConfig.dataField}` : '' - const fullPath = options && options.noPathCombination ? path : getChainPath(withConfigPath, formFieldConfig.field, path) + const withConfigPath = + this.props.config.withConfig?.enable && this.props.config.withConfig?.dataField + ? `${this.props.config.withConfig.dataField}` + : '' + const fullPath = + options && options.noPathCombination ? path : getChainPath(withConfigPath, formFieldConfig.field, path) await this.props.onValueListAppend(fullPath, value, true) this.handleValueCallback(formFieldIndex, validation) } } - handleValueListSplice = async (formFieldIndex: number, path: string, index: number, count: number, validation: true | FieldError[], options?: { noPathCombination?: boolean }) => { + handleValueListSplice = async ( + formFieldIndex: number, + path: string, + index: number, + count: number, + validation: true | FieldError[], + options?: { noPathCombination?: boolean } + ) => { const formFieldConfig = (this.state.fields || [])[formFieldIndex] if (formFieldConfig) { - const withConfigPath = this.props.config.withConfig?.enable && this.props.config.withConfig?.dataField ? `${this.props.config.withConfig.dataField}` : '' - const fullPath = options && options.noPathCombination ? path : getChainPath(withConfigPath, formFieldConfig.field, path) + const withConfigPath = + this.props.config.withConfig?.enable && this.props.config.withConfig?.dataField + ? `${this.props.config.withConfig.dataField}` + : '' + const fullPath = + options && options.noPathCombination ? path : getChainPath(withConfigPath, formFieldConfig.field, path) await this.props.onValueListSplice(fullPath, index, count, true) this.handleValueCallback(formFieldIndex, validation) } } - handleValueListSort = async (formFieldIndex: number, path: string, index: number, sortType: 'up' | 'down', validation: true | FieldError[], options?: { noPathCombination?: boolean }) => { + handleValueListSort = async ( + formFieldIndex: number, + path: string, + index: number, + sortType: 'up' | 'down', + validation: true | FieldError[], + options?: { noPathCombination?: boolean } + ) => { const formFieldConfig = (this.state.fields || [])[formFieldIndex] if (formFieldConfig) { - const withConfigPath = this.props.config.withConfig?.enable && this.props.config.withConfig?.dataField ? `${this.props.config.withConfig.dataField}` : '' - const fullPath = options && options.noPathCombination ? path : getChainPath(withConfigPath, formFieldConfig.field, path) + const withConfigPath = + this.props.config.withConfig?.enable && this.props.config.withConfig?.dataField + ? `${this.props.config.withConfig.dataField}` + : '' + const fullPath = + options && options.noPathCombination ? path : getChainPath(withConfigPath, formFieldConfig.field, path) await this.props.onValueListSort(fullPath, index, sortType, true) this.handleValueCallback(formFieldIndex, validation) @@ -311,9 +391,7 @@ export default class ImportSubformField extends Field { - return - 您当前使用的UI版本没有实现ImportSubformField组件。 - + return <>您当前使用的UI版本没有实现ImportSubformField组件。 } /** @@ -321,22 +399,13 @@ export default class ImportSubformField extends Field { - return - 您当前使用的UI版本没有实现FormItem组件。 - - } + renderItemComponent = (props: IFormItem) => { + return <>您当前使用的UI版本没有实现FormItem组件。 + } - render = () => { - const { - config, - formLayout, - value, - data, - step - } = this.props - - let fields = this.state.fields + getConfigData = () => { + const { config, value } = this.props + let { fields } = this.state let interfaceConfig: InterfaceConfig | undefined if (config.configFrom) { if (config.configFrom.type === 'interface') { @@ -357,118 +426,162 @@ export default class ImportSubformField extends Field { - const dataToUnstringfy = this.handleDataToUnstringfy(data) - if (this.props.config.withConfig?.enable && this.props.config.withConfig?.configField) this.props.onValueSet(this.props.config.withConfig.configField, data, true) - if (!isEqual(dataToUnstringfy, this.state.fields)) { - this.setState({ - fields: dataToUnstringfy - }) - } - }) + this.interfaceHelper + .request( + interfaceConfig, + {}, + { record: this.props.record, data: this.props.data, step: this.props.step }, + { loadDomain: this.props.loadDomain }, + this + ) + .then((data: any) => { + const dataToUnstringfy = this.handleDataToUnstringfy(data) + if (this.props.config.withConfig?.enable && this.props.config.withConfig?.configField) + this.props.onValueSet(this.props.config.withConfig.configField, data, true) + if (!isEqual(dataToUnstringfy, this.state.fields)) { + this.setState({ + fields: dataToUnstringfy + }) + } + }) } + } + + componentDidMount() { + this.getConfigData() + } + + componentDidUpdate() { + this.getConfigData() + } + + render = () => { + const { config, formLayout, value, data, step } = this.props + + const { fields } = this.state if (!fields || !Array.isArray(fields) || fields.length === 0) { - return - } else { - const withConfigPath = this.props.config.withConfig?.enable && this.props.config.withConfig?.dataField ? `${this.props.config.withConfig.dataField}` : '' - return ( - - {this.renderComponent({ - columns: config.columns, - children: this.state.didMount - ? (Array.isArray(this.state.fields) ? this.state.fields : []).map((formFieldConfig, formFieldIndex) => { - if (!ConditionHelper(formFieldConfig.condition, { record: value, data, step, extraContainerPath: this.props.config.field }, this)) { - this.formFieldsMounted = set(this.formFieldsMounted, `[${formFieldIndex}]`, false) - this.formFields && (this.formFields[formFieldIndex] = null) - return null - } - let hidden: boolean = true - let display: boolean = true - - if (formFieldConfig.type === 'hidden') { - hidden = true - display = false - } - - if (formFieldConfig.display === 'none') { - hidden = true - display = false - } - - const FormField = this.getALLComponents(formFieldConfig.type) || Field - - let status = (this.state.formData[formFieldIndex] || {}).status || 'normal' - - if (['group', 'import_subform', 'object', 'tabs', 'form'].some((type) => type === formFieldConfig.type)) { - status = 'normal' - } - - const renderData = { - key: formFieldIndex, - label: formFieldConfig.label, - status, - columns: config.columns?.enable - ? { - type: formFieldConfig.columns?.type || config.childColumns?.type || 'span', - value: formFieldConfig.columns?.value || config.childColumns?.value || 1, - wrap: formFieldConfig.columns?.wrap || config.childColumns?.wrap || false, - gap: config.columns?.gap || 0, - rowGap: config.columns?.rowGap || 0 + return <> + } + const withConfigPath = + this.props.config.withConfig?.enable && this.props.config.withConfig?.dataField + ? `${this.props.config.withConfig.dataField}` + : '' + return ( + <> + {this.renderComponent({ + columns: config.columns, + children: this.state.didMount + ? (Array.isArray(this.state.fields) ? this.state.fields : []).map((formFieldConfig, formFieldIndex) => { + if ( + !ConditionHelper( + formFieldConfig.condition, + { record: value, data, step, extraContainerPath: this.props.config.field }, + this + ) + ) { + this.formFieldsMounted = set(this.formFieldsMounted, `[${formFieldIndex}]`, false) + this.formFields && (this.formFields[formFieldIndex] = null) + return null + } + let hidden = true + let display = true + + if (formFieldConfig.type === 'hidden') { + hidden = true + display = false + } + + if (formFieldConfig.display === 'none') { + hidden = true + display = false + } + + const FormField = this.getALLComponents(formFieldConfig.type) || Field + + let status = (this.state.formData[formFieldIndex] || {}).status || 'normal' + + if ( + ['group', 'import_subform', 'object', 'tabs', 'form'].some((type) => type === formFieldConfig.type) + ) { + status = 'normal' + } + + const renderData = { + key: formFieldIndex, + label: formFieldConfig.label, + status, + columns: config.columns?.enable + ? { + type: formFieldConfig.columns?.type || config.childColumns?.type || 'span', + value: formFieldConfig.columns?.value || config.childColumns?.value || 1, + wrap: formFieldConfig.columns?.wrap || config.childColumns?.wrap || false, + gap: config.columns?.gap || 0, + rowGap: config.columns?.rowGap || 0 + } + : undefined, + message: (this.state.formData[formFieldIndex] || {}).message || '', + extra: StatementHelper( + formFieldConfig.extra, + { + record: this.props.value, + data: this.props.data, + step: this.props.step, + extraContainerPath: this.props.config.field + }, + this + ), + required: getBoolean(formFieldConfig.required), + layout: formLayout, + visitable: display, + fieldType: formFieldConfig.type, + children: ( + | null) => { + if (formField) { + this.formFields = set(this.formFields, `[${formFieldIndex}]`, formField) + this.handleMount(formFieldIndex) } - : undefined, - message: (this.state.formData[formFieldIndex] || {}).message || '', - extra: StatementHelper(formFieldConfig.extra, { record: this.props.value, data: this.props.data, step: this.props.step, extraContainerPath: this.props.config.field }, this), - required: getBoolean(formFieldConfig.required), - layout: formLayout, - visitable: display, - fieldType: formFieldConfig.type, - children: ( - | null) => { - if (formField) { - this.formFields = set(this.formFields, `[${formFieldIndex}]`, formField) - this.handleMount(formFieldIndex) - } - }} - form={this.props.form} - formLayout={formLayout} - value={getValue(value, getChainPath(withConfigPath, formFieldConfig.field))} - record={value} - step={this.props.step} - data={data} - config={formFieldConfig} - onChange={async (value: any) => { await this.handleChange(formFieldIndex, value) }} - onValueSet={async (path, value, validation, options) => this.handleValueSet(formFieldIndex, path, value, validation, options)} - onValueUnset={async (path, validation, options) => this.handleValueUnset(formFieldIndex, path, validation, options)} - onValueListAppend={async (path, value, validation, options) => this.handleValueListAppend(formFieldIndex, path, value, validation, options)} - onValueListSplice={async (path, index, count, validation, options) => this.handleValueListSplice(formFieldIndex, path, index, count, validation, options)} - onValueListSort={async (path, index, sortType, validation, options) => this.handleValueListSort(formFieldIndex, path, index, sortType, validation, options)} - baseRoute={this.props.baseRoute} - loadDomain={async (domain: string) => await this.props.loadDomain(domain)} - containerPath={getChainPath(this.props.containerPath, this.props.config.field)} - onReportFields={async (field: string) => await this.handleReportFields(field)} - /> - ) - } - // 渲染表单项容器 - return ( - hidden - ? this.renderItemComponent(renderData) - : + }} + form={this.props.form} + formLayout={formLayout} + value={getValue(value, getChainPath(withConfigPath, formFieldConfig.field))} + record={value} + step={this.props.step} + data={data} + config={formFieldConfig} + onChange={async (value: any) => { + await this.handleChange(formFieldIndex, value) + }} + onValueSet={async (path, value, validation, options) => + this.handleValueSet(formFieldIndex, path, value, validation, options) + } + onValueUnset={async (path, validation, options) => + this.handleValueUnset(formFieldIndex, path, validation, options) + } + onValueListAppend={async (path, value, validation, options) => + this.handleValueListAppend(formFieldIndex, path, value, validation, options) + } + onValueListSplice={async (path, index, count, validation, options) => + this.handleValueListSplice(formFieldIndex, path, index, count, validation, options) + } + onValueListSort={async (path, index, sortType, validation, options) => + this.handleValueListSort(formFieldIndex, path, index, sortType, validation, options) + } + baseRoute={this.props.baseRoute} + loadDomain={async (domain: string) => await this.props.loadDomain(domain)} + containerPath={getChainPath(this.props.containerPath, this.props.config.field)} + onReportFields={async (field: string) => await this.handleReportFields(field)} + /> ) - }) - : [] - })} - - ) - } + } + // 渲染表单项容器 + return hidden ? this.renderItemComponent(renderData) : + }) + : [] + })} + + ) } } -- Gitee From bba45cd3a317bd79e49037add8348a01aa2cbe0c Mon Sep 17 00:00:00 2001 From: zjt Date: Sun, 24 Apr 2022 15:34:10 +0800 Subject: [PATCH 23/23] =?UTF-8?q?style:=20=E6=A0=BC=E5=BC=8F=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- rollup.config.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/rollup.config.js b/rollup.config.js index 6b20707..53ba1f0 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -1,11 +1,11 @@ -import path from 'path'; -import ts from 'rollup-plugin-typescript2'; -import { nodeResolve } from '@rollup/plugin-node-resolve'; -import { babel } from '@rollup/plugin-babel'; -import commonjs from '@rollup/plugin-commonjs'; -import { eslint } from 'rollup-plugin-eslint'; -import json from '@rollup/plugin-json'; -import { terser } from 'rollup-plugin-terser'; +import path from 'path' +import ts from 'rollup-plugin-typescript2' +import { nodeResolve } from '@rollup/plugin-node-resolve' +import { babel } from '@rollup/plugin-babel' +import commonjs from '@rollup/plugin-commonjs' +import { eslint } from 'rollup-plugin-eslint' +import json from '@rollup/plugin-json' +import { terser } from 'rollup-plugin-terser' export default { input: 'src/index.tsx', @@ -39,4 +39,4 @@ export default { watch: { include: 'src/**' } -}; +} -- Gitee