|
@@ -1,7 +1,8 @@
|
|
-import { forwardRef, memo, useImperativeHandle, useState } from 'react'
|
|
|
|
|
|
+import { forwardRef, memo, useEffect, useImperativeHandle, useState } from 'react'
|
|
import { cloneDeep } from 'lodash-es'
|
|
import { cloneDeep } from 'lodash-es'
|
|
import { getTenantApply, ITenantApplyInfo } from '@/api/services/riskcontrol/declare'
|
|
import { getTenantApply, ITenantApplyInfo } from '@/api/services/riskcontrol/declare'
|
|
import { orderStateMap } from './constants/orderState'
|
|
import { orderStateMap } from './constants/orderState'
|
|
|
|
+import DynamicForm from './components/DynamicForm'
|
|
|
|
|
|
export interface FormParseRef {}
|
|
export interface FormParseRef {}
|
|
|
|
|
|
@@ -14,6 +15,8 @@ interface FormParseProps {
|
|
expiry?: string
|
|
expiry?: string
|
|
isExpiry?: boolean
|
|
isExpiry?: boolean
|
|
className?: string
|
|
className?: string
|
|
|
|
+ onFormDataChange: (data: Record<string, any>) => void
|
|
|
|
+ onFormRuleChange: (rule: any) => void
|
|
}
|
|
}
|
|
|
|
|
|
const checkStateMap = {
|
|
const checkStateMap = {
|
|
@@ -24,7 +27,20 @@ const checkStateMap = {
|
|
|
|
|
|
const FormParse = memo(
|
|
const FormParse = memo(
|
|
forwardRef<FormParseRef, FormParseProps>(
|
|
forwardRef<FormParseRef, FormParseProps>(
|
|
- ({ declFormData, formData, formRule, disabled, state, expiry, isExpiry }, ref) => {
|
|
|
|
|
|
+ (
|
|
|
|
+ {
|
|
|
|
+ declFormData,
|
|
|
|
+ formData,
|
|
|
|
+ formRule,
|
|
|
|
+ disabled,
|
|
|
|
+ state,
|
|
|
|
+ expiry,
|
|
|
|
+ isExpiry,
|
|
|
|
+ onFormDataChange,
|
|
|
|
+ onFormRuleChange
|
|
|
|
+ },
|
|
|
|
+ ref
|
|
|
|
+ ) => {
|
|
console.log(formData)
|
|
console.log(formData)
|
|
console.log(formRule)
|
|
console.log(formRule)
|
|
console.log(disabled)
|
|
console.log(disabled)
|
|
@@ -68,6 +84,253 @@ const FormParse = memo(
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ const [isInited, setIsInited] = useState(false)
|
|
|
|
+ const initFn = () => {
|
|
|
|
+ console.log('init')
|
|
|
|
+ // 初始化表单
|
|
|
|
+ formItemsCopy?.forEach((item) => {
|
|
|
|
+ // 初始化数据
|
|
|
|
+ if (item.itemStruct?.type === 'FILE_PICKER') {
|
|
|
|
+ onFormDataChange((prev: Record<string, any>) => ({
|
|
|
|
+ ...prev,
|
|
|
|
+ [item.itemStruct!.widgetId!]: item.itemDeli?.length
|
|
|
|
+ ? item.itemDeli.map((deli) => ({
|
|
|
|
+ fileName: deli.value.fileName, // 用来回显
|
|
|
|
+ original: deli.value.fileName, // 文件原始名称, 后续保存提交此参数
|
|
|
|
+ name: deli.value.fileName, // 用来回显
|
|
|
|
+ url: deli.value.ossLink, // 用来回显
|
|
|
|
+ viewUrl: deli.value.ossLink, // 用来图片放大器回显
|
|
|
|
+ originUrl: deli.value.url, // 用来保存原始url, 后续保存提交此参数
|
|
|
|
+ state: 'old' // 旧数据
|
|
|
|
+ }))
|
|
|
|
+ : []
|
|
|
|
+ }))
|
|
|
|
+ } else if (item.itemStruct?.type === 'INVOICE_PICKER') {
|
|
|
|
+ onFormDataChange((prev: Record<string, any>) => ({
|
|
|
|
+ ...prev,
|
|
|
|
+ [item.itemStruct!.widgetId!]: item.itemDeli?.length
|
|
|
|
+ ? item.itemDeli.map((deli) => ({
|
|
|
|
+ fileName: deli.value.fileName, // 用来回显
|
|
|
|
+ original: deli.value.fileName, // 文件原始名称, 后续保存提交此参数
|
|
|
|
+ name: deli.value.fileName, // 用来回显
|
|
|
|
+ url: deli.value.ossLink, // 用来回显
|
|
|
|
+ viewUrl: deli.value.ossLink, // 用来图片放大器回显
|
|
|
|
+ originUrl: deli.value.url, // 用来保存原始url, 后续保存提交此参数
|
|
|
|
+ state: 'old' // 旧数据
|
|
|
|
+ }))
|
|
|
|
+ : []
|
|
|
|
+ }))
|
|
|
|
+ } else if (item.itemStruct?.type === 'FINANCE_PICKER') {
|
|
|
|
+ onFormDataChange((prev: Record<string, any>) => ({
|
|
|
|
+ ...prev,
|
|
|
|
+ [item.itemStruct!.widgetId!]: item.itemDeli?.length
|
|
|
|
+ ? item.itemDeli.map((deli) => ({
|
|
|
|
+ fileName: deli.value.fileName, // 用来回显
|
|
|
|
+ original: deli.value.fileName, // 文件原始名称, 后续保存提交此参数
|
|
|
|
+ name: deli.value.fileName, // 用来回显
|
|
|
|
+ url: deli.value.ossLink, // 用来回显
|
|
|
|
+ viewUrl: deli.value.ossLink, // 用来图片放大器回显
|
|
|
|
+ originUrl: deli.value.url, // 用来保存原始url, 后续保存提交此参数
|
|
|
|
+ state: 'old' // 旧数据
|
|
|
|
+ }))
|
|
|
|
+ : []
|
|
|
|
+ }))
|
|
|
|
+ } else if (item.itemStruct?.type === 'INPUT') {
|
|
|
|
+ onFormDataChange((prev: Record<string, any>) => ({
|
|
|
|
+ ...prev,
|
|
|
|
+ [item.itemStruct!.widgetId!]: item.itemDeli?.length ? item.itemDeli[0].value : ''
|
|
|
|
+ }))
|
|
|
|
+ } else if (item.itemStruct?.type === 'NUMBER_INPUT') {
|
|
|
|
+ onFormDataChange((prev: Record<string, any>) => ({
|
|
|
|
+ ...prev,
|
|
|
|
+ [item.itemStruct!.widgetId!]: item.itemDeli?.length ? item.itemDeli[0].value : ''
|
|
|
|
+ }))
|
|
|
|
+ } else if (item.itemStruct?.type === 'AMOUNT_INPUT') {
|
|
|
|
+ onFormDataChange((prev: Record<string, any>) => ({
|
|
|
|
+ ...prev,
|
|
|
|
+ [item.itemStruct!.widgetId!]: item.itemDeli?.length ? item.itemDeli[0].value : ''
|
|
|
|
+ }))
|
|
|
|
+ } else if (item.itemStruct?.type === 'RADIO') {
|
|
|
|
+ onFormDataChange((prev: Record<string, any>) => ({
|
|
|
|
+ ...prev,
|
|
|
|
+ [item.itemStruct!.widgetId!]: item.itemDeli?.length ? item.itemDeli[0].value : ''
|
|
|
|
+ }))
|
|
|
|
+ } else if (item.itemStruct?.type === 'SELECT') {
|
|
|
|
+ onFormDataChange((prev: Record<string, any>) => ({
|
|
|
|
+ ...prev,
|
|
|
|
+ [item.itemStruct!.widgetId!]: item.itemDeli?.length
|
|
|
|
+ ? item.itemDeli[0].value
|
|
|
|
+ : (item.itemStruct?.expand as API.FD_COM['SELECT']).multiple
|
|
|
|
+ ? []
|
|
|
|
+ : ''
|
|
|
|
+ }))
|
|
|
|
+ } else if (item.itemStruct?.type === 'DATETIME_PICKER') {
|
|
|
|
+ const isRangeType = ['DATERANGE', 'DATETIMERANGE'].includes(
|
|
|
|
+ (item.itemStruct.expand as API.FD_COM['DATETIME_PICKER']).dateType
|
|
|
|
+ )
|
|
|
|
+ onFormDataChange((prev: Record<string, any>) => ({
|
|
|
|
+ ...prev,
|
|
|
|
+ [item.itemStruct!.widgetId!]: item.itemDeli?.length
|
|
|
|
+ ? item.itemDeli[0].value
|
|
|
|
+ : isRangeType
|
|
|
|
+ ? []
|
|
|
|
+ : ''
|
|
|
|
+ }))
|
|
|
|
+ }
|
|
|
|
+ // 初始化rules
|
|
|
|
+ if (formRule) {
|
|
|
|
+ const rules: any[] = []
|
|
|
|
+ if (item.itemStruct!.required) {
|
|
|
|
+ const tipMap = {
|
|
|
|
+ INPUT: '请输入',
|
|
|
|
+ FILE_PICKER: '请上传',
|
|
|
|
+ INVOICE_PICKER: '请上传',
|
|
|
|
+ NUMBER_INPUT: '请输入数值',
|
|
|
|
+ AMOUNT_INPUT: '请输入金额',
|
|
|
|
+ FINANCIAL_PICKER: '请上传',
|
|
|
|
+ DATETIME_PICKER: '请选择',
|
|
|
|
+ SELECT: '请选择'
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ const tipText = tipMap[item.itemStruct?.type as keyof typeof tipMap] ?? '请输入'
|
|
|
|
+ rules.push({
|
|
|
|
+ required: true,
|
|
|
|
+ message:
|
|
|
|
+ item.itemStruct?.type === 'SELECT' &&
|
|
|
|
+ (item.itemStruct.expand as API.FD_COM['SELECT']).multiple
|
|
|
|
+ ? '请至少选择一个选项'
|
|
|
|
+ : `${tipText}${item.itemStruct?.label.text}`,
|
|
|
|
+ trigger: 'blur'
|
|
|
|
+ })
|
|
|
|
+ // requireLimit
|
|
|
|
+ if ((item.itemStruct!.expand as API.FD_COM['FILE_PICKER'])?.requiredLimit) {
|
|
|
|
+ rules.push({
|
|
|
|
+ validator: (_rule: any, value: any, callback: any) => {
|
|
|
|
+ if (
|
|
|
|
+ value.length <
|
|
|
|
+ (item.itemStruct!.expand as API.FD_COM['FILE_PICKER'])!.requiredLimit!
|
|
|
|
+ ) {
|
|
|
|
+ callback(
|
|
|
|
+ new Error(
|
|
|
|
+ `至少上传${(item.itemStruct!.expand as API.FD_COM['FILE_PICKER'])!
|
|
|
|
+ .requiredLimit!}个文件`
|
|
|
|
+ )
|
|
|
|
+ )
|
|
|
|
+ } else {
|
|
|
|
+ callback()
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ trigger: 'blur'
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ if (
|
|
|
|
+ (item.itemStruct!.expand as API.FD_COM_ENHANCE['INVOICE_PICKER'])?.requiredLimit
|
|
|
|
+ ) {
|
|
|
|
+ rules.push({
|
|
|
|
+ validator: (_rule: any, value: any, callback: any) => {
|
|
|
|
+ if (
|
|
|
|
+ value.length <
|
|
|
|
+ (item.itemStruct!.expand as API.FD_COM_ENHANCE['INVOICE_PICKER'])!
|
|
|
|
+ .requiredLimit!
|
|
|
|
+ ) {
|
|
|
|
+ callback(
|
|
|
|
+ new Error(
|
|
|
|
+ `至少上传${(item.itemStruct!
|
|
|
|
+ .expand as API.FD_COM_ENHANCE['INVOICE_PICKER'])!.requiredLimit!}个文件`
|
|
|
|
+ )
|
|
|
|
+ )
|
|
|
|
+ } else {
|
|
|
|
+ callback()
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ trigger: 'blur'
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ if (
|
|
|
|
+ (item.itemStruct!.expand as API.FD_COM_ENHANCE['FINANCE_PICKER'])?.requiredLimit
|
|
|
|
+ ) {
|
|
|
|
+ rules.push({
|
|
|
|
+ validator: (_rule: any, value: any, callback: any) => {
|
|
|
|
+ if (
|
|
|
|
+ value.length <
|
|
|
|
+ (item.itemStruct!.expand as API.FD_COM_ENHANCE['FINANCE_PICKER'])!
|
|
|
|
+ .requiredLimit!
|
|
|
|
+ ) {
|
|
|
|
+ callback(
|
|
|
|
+ new Error(
|
|
|
|
+ `至少上传${(item.itemStruct!
|
|
|
|
+ .expand as API.FD_COM_ENHANCE['FINANCE_PICKER'])!.requiredLimit!}个文件`
|
|
|
|
+ )
|
|
|
|
+ )
|
|
|
|
+ } else {
|
|
|
|
+ callback()
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ trigger: 'blur'
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if ((item.itemStruct!.expand as API.FD_COM['INPUT'])?.maxChars) {
|
|
|
|
+ rules.push({
|
|
|
|
+ max: parseInt((item.itemStruct!.expand as API.FD_COM['INPUT'])?.maxChars),
|
|
|
|
+ message: `最多输入${(item.itemStruct!.expand as API.FD_COM['INPUT'])?.maxChars}个字符`,
|
|
|
|
+ trigger: 'blur'
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ if ((item.itemStruct!.expand as API.FD_COM['NUMBER_INPUT'])?.maxChars) {
|
|
|
|
+ rules.push({
|
|
|
|
+ max: parseInt((item.itemStruct!.expand as API.FD_COM['NUMBER_INPUT'])?.maxChars),
|
|
|
|
+ message: `最多输入${
|
|
|
|
+ (item.itemStruct!.expand as API.FD_COM['NUMBER_INPUT'])?.maxChars
|
|
|
|
+ }个字符`,
|
|
|
|
+ trigger: 'blur'
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ if ((item.itemStruct!.expand as API.FD_COM['AMOUNT_INPUT'])?.maxChars) {
|
|
|
|
+ rules.push({
|
|
|
|
+ max: parseInt((item.itemStruct!.expand as API.FD_COM['AMOUNT_INPUT'])?.maxChars),
|
|
|
|
+ message: `最多输入${
|
|
|
|
+ (item.itemStruct!.expand as API.FD_COM['AMOUNT_INPUT'])?.maxChars
|
|
|
|
+ }个字符`,
|
|
|
|
+ trigger: 'blur'
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ // 这里可以根据需要添加其他规则
|
|
|
|
+ item.itemStruct!.valid?.forEach((validItem) => {
|
|
|
|
+ rules.push({
|
|
|
|
+ validator: (_rule: any, value: any, callback: any) => {
|
|
|
|
+ const reg = new RegExp(validItem.expression.body, validItem.expression.modifier)
|
|
|
|
+ if (!reg.test(value)) {
|
|
|
|
+ callback(new Error(validItem.message))
|
|
|
|
+ } else {
|
|
|
|
+ callback()
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ trigger: 'blur'
|
|
|
|
+ })
|
|
|
|
+ })
|
|
|
|
+ if (Array.isArray(formRule![item.itemStruct!.widgetId!]) && disabled) {
|
|
|
|
+ onFormRuleChange((prev: any) => ({
|
|
|
|
+ ...prev,
|
|
|
|
+ [item.itemStruct!.widgetId!]: [
|
|
|
|
+ ...((formRule![item.itemStruct!.widgetId!] as []) || [])
|
|
|
|
+ ]
|
|
|
|
+ }))
|
|
|
|
+ } else {
|
|
|
|
+ onFormRuleChange((prev: any) => ({
|
|
|
|
+ ...prev,
|
|
|
|
+ [item.itemStruct!.widgetId!]: rules as any
|
|
|
|
+ }))
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ setIsInited(true)
|
|
|
|
+ }
|
|
|
|
+ useEffect(() => {
|
|
|
|
+ initFn()
|
|
|
|
+ }, [])
|
|
|
|
+
|
|
return (
|
|
return (
|
|
<div>
|
|
<div>
|
|
{state && (
|
|
{state && (
|
|
@@ -126,6 +389,8 @@ const FormParse = memo(
|
|
<span className='ml-20'>审核意见:{declFormData?.checkMsg || '-'}</span>
|
|
<span className='ml-20'>审核意见:{declFormData?.checkMsg || '-'}</span>
|
|
<span className='ml-20 break-all'>原因说明:{declFormData?.remarks || '-'}</span>
|
|
<span className='ml-20 break-all'>原因说明:{declFormData?.remarks || '-'}</span>
|
|
</div>
|
|
</div>
|
|
|
|
+ {/* 动态生成表单 */}
|
|
|
|
+ {isInited && <DynamicForm formItems={formItemsCopy} />}
|
|
</div>
|
|
</div>
|
|
)
|
|
)
|
|
}
|
|
}
|