Merge pull request 'feat: 添加汇总的提供请求链接地址' (#347) from fix_groupBlock4 into @hera/dev
Reviewed-on: daoyoucloud/tachycode#347 Reviewed-by: sealday <zhanglin@daoyoucloud.com>
This commit is contained in:
		
						commit
						0e8d02cc1e
					
				| @ -1,16 +1,30 @@ | |||||||
| import { useField, useFieldSchema } from '@formily/react'; | import { useField, useFieldSchema } from '@formily/react'; | ||||||
| import { useDesignable, useFieldNames } from '@nocobase/client'; | import { useDesignable, useFieldNames, useFilterBlock } from '@nocobase/client'; | ||||||
| import { App, Button, Flex, Modal, Select } from 'antd'; | import { App, Button, Flex, Input, Modal, Select } from 'antd'; | ||||||
| import React, { useContext, useEffect, useState } from 'react'; | import React, { useContext, useEffect, useState } from 'react'; | ||||||
| import { useTranslation } from '../../locale'; | import { useTranslation } from '../../locale'; | ||||||
| import { GroupBlockContext } from '../../schema-initializer/GroupBlockInitializer'; | import { GroupBlockContext } from '../../schema-initializer/GroupBlockInitializer'; | ||||||
| import { transformers } from './transformers'; | import { transformers } from './transformers'; | ||||||
| import { DeleteOutlined } from '@ant-design/icons'; | import { DeleteOutlined, PullRequestOutlined } from '@ant-design/icons'; | ||||||
|  | import { uid } from '@formily/shared'; | ||||||
| 
 | 
 | ||||||
| export type SelectedField = { | export type SelectedField = { | ||||||
|   field: string | string[]; |   field: string | string[]; | ||||||
|   alias?: string; |   alias?: string; | ||||||
| }; | }; | ||||||
|  | export type fieldOptionType = { | ||||||
|  |   label: string; | ||||||
|  |   fieldFormat: { | ||||||
|  |     fieldValue: string; | ||||||
|  |     option: string; | ||||||
|  |     type: string; | ||||||
|  |     decimal?: string; | ||||||
|  |     requestUrl?: string; | ||||||
|  |   }; | ||||||
|  |   aggregation?: string; | ||||||
|  |   field?: [string]; | ||||||
|  |   display?: boolean; | ||||||
|  | }; | ||||||
| 
 | 
 | ||||||
| export const GroupConfigure = (props) => { | export const GroupConfigure = (props) => { | ||||||
|   const { visible, setVisible } = useContext(GroupBlockContext); |   const { visible, setVisible } = useContext(GroupBlockContext); | ||||||
| @ -18,16 +32,36 @@ export const GroupConfigure = (props) => { | |||||||
|   const { dn } = useDesignable(); |   const { dn } = useDesignable(); | ||||||
|   const { modal } = App.useApp(); |   const { modal } = App.useApp(); | ||||||
|   const fieldSchema = useFieldSchema(); |   const fieldSchema = useFieldSchema(); | ||||||
|   const measure = fieldSchema['x-decorator-props']?.params?.measures; |   const measures = fieldSchema['x-decorator-props']?.params?.measures; | ||||||
|   const [fieldOption, setFieldOption] = useState( |   const option: fieldOptionType[] = []; | ||||||
|     JSON.parse(JSON.stringify(measure.filter((item) => item.fieldFormat))), |   const params = fieldSchema['x-decorator-props']?.params; | ||||||
|   ); |   if (params['config']) { | ||||||
|   const valueOption = measure.map((item) => { |     if (params['config']['measures']) { | ||||||
|  |       option.push(...params['config']['measures']); | ||||||
|  |     } | ||||||
|  |     if (params['config']['request']) { | ||||||
|  |       option.push(...params['config']['request']); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   const [fieldOption, setFieldOption] = useState(JSON.parse(JSON.stringify(option))); | ||||||
|  |   const fieldType = [ | ||||||
|  |     { | ||||||
|  |       label: '字段配置', | ||||||
|  |       value: 'field', | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |       label: '请求配置', | ||||||
|  |       value: 'custom', | ||||||
|  |     }, | ||||||
|  |   ]; | ||||||
|  |   const valueOption = measures.map((item) => { | ||||||
|     return { |     return { | ||||||
|       label: item.label, |       label: item.label, | ||||||
|       value: item.field[0], |       value: item.field[0], | ||||||
|     }; |     }; | ||||||
|   }); |   }); | ||||||
|  | 
 | ||||||
|   const decimal = transformers.option.filter((item) => item.value === 'decimal')[0].childrens; |   const decimal = transformers.option.filter((item) => item.value === 'decimal')[0].childrens; | ||||||
|   useEffect(() => { |   useEffect(() => { | ||||||
|     if (!visible) { |     if (!visible) { | ||||||
| @ -39,16 +73,31 @@ export const GroupConfigure = (props) => { | |||||||
|       title={t('Configure Group')} |       title={t('Configure Group')} | ||||||
|       open={visible} |       open={visible} | ||||||
|       onOk={() => { |       onOk={() => { | ||||||
|         measure.forEach((measureItem) => { |         const request = []; | ||||||
|           delete measureItem['fieldFormat']; |         const configMeasures = []; | ||||||
|         fieldOption.forEach((fieldOptionItem) => { |         fieldOption.forEach((fieldOptionItem) => { | ||||||
|  |           if (fieldOptionItem.fieldFormat.type === 'field') { | ||||||
|  |             const { measureItem, index } = measures | ||||||
|  |               .map((measureItem, index) => { | ||||||
|                 if (measureItem.field[0] === fieldOptionItem?.fieldFormat?.fieldValue) { |                 if (measureItem.field[0] === fieldOptionItem?.fieldFormat?.fieldValue) { | ||||||
|  |                   return { measureItem, index }; | ||||||
|  |                 } else { | ||||||
|  |                   return {}; | ||||||
|  |                 } | ||||||
|  |               }) | ||||||
|  |               .filter((value) => value.measureItem)[0]; | ||||||
|  |             if (measureItem) { | ||||||
|               measureItem['fieldFormat'] = { ...fieldOptionItem.fieldFormat }; |               measureItem['fieldFormat'] = { ...fieldOptionItem.fieldFormat }; | ||||||
|  |               configMeasures.push(measureItem); | ||||||
|  |             } | ||||||
|  |           } else if (fieldOptionItem.fieldFormat.type === 'custom') { | ||||||
|  |             request.push({ ...fieldOptionItem, label: '自定义请求', field: [uid()] }); | ||||||
|           } |           } | ||||||
|         }); |         }); | ||||||
|         }); |         fieldSchema['x-decorator-props']['params']['config'] = { | ||||||
| 
 |           measures: configMeasures, | ||||||
|         fieldSchema['x-decorator-props']['params'].measures = measure; |           request, | ||||||
|  |         }; | ||||||
|         dn.emit('patch', { |         dn.emit('patch', { | ||||||
|           schema: fieldSchema, |           schema: fieldSchema, | ||||||
|         }); |         }); | ||||||
| @ -73,6 +122,16 @@ export const GroupConfigure = (props) => { | |||||||
|         {fieldOption.map((item, index) => { |         {fieldOption.map((item, index) => { | ||||||
|           return ( |           return ( | ||||||
|             <div style={{ marginBottom: '7px' }} key={index}> |             <div style={{ marginBottom: '7px' }} key={index}> | ||||||
|  |               <Select | ||||||
|  |                 options={fieldType} | ||||||
|  |                 placeholder="Type" | ||||||
|  |                 style={{ marginRight: '5px' }} | ||||||
|  |                 value={item?.fieldFormat?.type ? item?.fieldFormat?.type : undefined} | ||||||
|  |                 onChange={(v) => { | ||||||
|  |                   fieldConfig('type', fieldOption, setFieldOption, index, v); | ||||||
|  |                 }} | ||||||
|  |               /> | ||||||
|  |               {item?.fieldFormat?.type === 'field' ? ( | ||||||
|                 <Select |                 <Select | ||||||
|                   options={valueOption} |                   options={valueOption} | ||||||
|                   placeholder="Field" |                   placeholder="Field" | ||||||
| @ -82,6 +141,19 @@ export const GroupConfigure = (props) => { | |||||||
|                     fieldConfig('field', fieldOption, setFieldOption, index, v); |                     fieldConfig('field', fieldOption, setFieldOption, index, v); | ||||||
|                   }} |                   }} | ||||||
|                 /> |                 /> | ||||||
|  |               ) : null} | ||||||
|  |               {item?.fieldFormat?.type === 'custom' ? ( | ||||||
|  |                 <Input | ||||||
|  |                   addonBefore={<PullRequestOutlined />} | ||||||
|  |                   placeholder="RequestUrl" | ||||||
|  |                   allowClear | ||||||
|  |                   style={{ marginRight: '5px', marginTop: '5px', marginBottom: '5px' }} | ||||||
|  |                   defaultValue={item?.fieldFormat?.requestUrl ? item?.fieldFormat?.requestUrl : undefined} | ||||||
|  |                   onChange={(v) => { | ||||||
|  |                     fieldConfig('url', fieldOption, setFieldOption, index, v.currentTarget.value); | ||||||
|  |                   }} | ||||||
|  |                 /> | ||||||
|  |               ) : null} | ||||||
|               <Select |               <Select | ||||||
|                 options={transformers.option} |                 options={transformers.option} | ||||||
|                 placeholder="Format" |                 placeholder="Format" | ||||||
| @ -129,6 +201,16 @@ const fieldConfig = (type, fieldOption, setFieldOption, index?, record?) => { | |||||||
|     option.push({}); |     option.push({}); | ||||||
|   } else if (type === 'del') { |   } else if (type === 'del') { | ||||||
|     option.splice(index, 1); |     option.splice(index, 1); | ||||||
|  |   } else if (type === 'type') { | ||||||
|  |     option[index]['fieldFormat'] = { | ||||||
|  |       ...option[index]['fieldFormat'], | ||||||
|  |       type: record, | ||||||
|  |     }; | ||||||
|  |   } else if (type === 'url') { | ||||||
|  |     option[index]['fieldFormat'] = { | ||||||
|  |       ...option[index]['fieldFormat'], | ||||||
|  |       requestUrl: record, | ||||||
|  |     }; | ||||||
|   } else if (type === 'field') { |   } else if (type === 'field') { | ||||||
|     option[index]['fieldFormat'] = { |     option[index]['fieldFormat'] = { | ||||||
|       ...option[index]['fieldFormat'], |       ...option[index]['fieldFormat'], | ||||||
|  | |||||||
| @ -1,40 +1,73 @@ | |||||||
| import { useField, useFieldSchema } from '@formily/react'; | import { useField, useFieldSchema } from '@formily/react'; | ||||||
| import { useBlockRequestContext } from '@nocobase/client'; | import { findFilterTargets, useAPIClient, useBlockRequestContext, useFilterBlock } from '@nocobase/client'; | ||||||
| import { Descriptions, DescriptionsProps, Spin } from 'antd'; | import { Descriptions, DescriptionsProps, Spin } from 'antd'; | ||||||
| import { transformers } from '../components/GroupBlockConfigure/transformers'; | import { transformers } from '../components/GroupBlockConfigure/transformers'; | ||||||
| import React from 'react'; | import React, { useEffect, useState } from 'react'; | ||||||
|  | import { useAsyncEffect } from 'ahooks'; | ||||||
|  | 
 | ||||||
|  | type DataItem = { | ||||||
|  |   labels: string[]; | ||||||
|  |   values: number[]; | ||||||
|  | }; | ||||||
|  | type requestData = { | ||||||
|  |   label: string; | ||||||
|  |   value: number | DataItem; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| export const GroupBlock = (props) => { | export const GroupBlock = (props) => { | ||||||
|   const field = useField<any>(); |   const field = useField<any>(); | ||||||
|   const fieldSchema = useFieldSchema(); |   const fieldSchema = useFieldSchema(); | ||||||
|   const measures = fieldSchema.parent['x-decorator-props'].params?.measures; |   const params = fieldSchema.parent['x-decorator-props'].params; | ||||||
|   const { resource, service } = useBlockRequestContext(); |   const { resource, service } = useBlockRequestContext(); | ||||||
|  |   const { getDataBlocks } = useFilterBlock(); | ||||||
|  |   const { targets = [], uid } = findFilterTargets(fieldSchema); | ||||||
|  |   const api = useAPIClient(); | ||||||
|  |   const [result, setResult] = useState([]); | ||||||
|  |   const items: DescriptionsProps['items'] = []; | ||||||
|  |   const Blocks = getDataBlocks(); | ||||||
|  |   if (!service.params.length) { | ||||||
|  |     getDataBlocks().map((block) => { | ||||||
|  |       if (Object.keys(block.defaultFilter).length) { | ||||||
|  |         getDataBlocks().forEach((getblock) => { | ||||||
|  |           if (getblock.uid !== block.uid && getblock.collection.name === block.collection.name) { | ||||||
|  |             service.params = block.defaultFilter; | ||||||
|  |           } | ||||||
|  |         }); | ||||||
|  |       } | ||||||
|  |     }); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   useAsyncEffect(async () => { | ||||||
|  |     const filter = service?.params[0] ? service.params[0].filter : service?.params; | ||||||
|  |     setResult( | ||||||
|  |       await Promise.all( | ||||||
|  |         params?.config?.request?.map(async (requeatItem) => { | ||||||
|  |           return [ | ||||||
|  |             await api.request({ | ||||||
|  |               url: requeatItem.fieldFormat.requestUrl, | ||||||
|  |               params: { | ||||||
|  |                 filter: { ...filter }, | ||||||
|  |               }, | ||||||
|  |             }), | ||||||
|  |             requeatItem, | ||||||
|  |           ]; | ||||||
|  |         }), | ||||||
|  |       ), | ||||||
|  |     ); | ||||||
|  |   }, [Blocks, service.params, service.params[0]]); | ||||||
|  | 
 | ||||||
|   if (service.loading && !field.loaded) { |   if (service.loading && !field.loaded) { | ||||||
|     return <Spin />; |     return <Spin />; | ||||||
|   } |   } | ||||||
|   const data = service.data?.data[0] ?? {}; |   const data = service.data?.data[0] ?? {}; | ||||||
|   const { option: tOption } = transformers; | 
 | ||||||
|   measures.forEach((measuresItem) => { |   params?.config?.measures?.forEach((measuresItem) => { | ||||||
|     if (measuresItem.fieldFormat) { |  | ||||||
|     const value = measuresItem.fieldFormat.fieldValue; |     const value = measuresItem.fieldFormat.fieldValue; | ||||||
|       const option = measuresItem.fieldFormat.option; |     data[value] = fieldTransformers(measuresItem, data[value]); | ||||||
|       const decimal = measuresItem.fieldFormat.decimal; |  | ||||||
|       if (option && option !== 'decimal') { |  | ||||||
|         const component = tOption.filter((tValue) => tValue.value === option)[0].component; |  | ||||||
|         data[value] = String(data[value]).includes(',') ? String(data[value]).replace(/,/g, '') : data[value]; |  | ||||||
|         data[value] = component(data[value]); |  | ||||||
|       } else if (option && option === 'decimal') { |  | ||||||
|         const component = tOption |  | ||||||
|           .filter((tValue) => tValue.value === 'decimal')[0] |  | ||||||
|           .childrens.filter((decimalOption) => decimalOption.value === decimal)[0].component; |  | ||||||
|         data[value] = String(data[value]).includes(',') ? String(data[value]).replace(/,/g, '') : data[value]; |  | ||||||
|         data[value] = component(data[value]); |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   }); |   }); | ||||||
| 
 | 
 | ||||||
|   const items: DescriptionsProps['items'] = []; |  | ||||||
|   for (const key in data) { |   for (const key in data) { | ||||||
|     measures?.forEach((value) => { |     params?.config?.measures?.forEach((value) => { | ||||||
|       if (value.field[0] === key) { |       if (value.field[0] === key) { | ||||||
|         if (value.display) { |         if (value.display) { | ||||||
|           items.push({ |           items.push({ | ||||||
| @ -47,5 +80,38 @@ export const GroupBlock = (props) => { | |||||||
|     }); |     }); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   result.forEach(([data, requeatItem]) => { | ||||||
|  |     data?.data?.data?.forEach((requestData: requestData) => { | ||||||
|  |       const dataItem = { key: requestData.label, label: requestData.label, children: '' }; | ||||||
|  |       if (typeof requestData.value === 'object') { | ||||||
|  |         requestData.value.labels.forEach((labelItem, index) => { | ||||||
|  |           dataItem.children = | ||||||
|  |             dataItem.children + `  ${labelItem} ${fieldTransformers(requeatItem, requestData.value['values'][index])}`; | ||||||
|  |         }); | ||||||
|  |       } else { | ||||||
|  |         dataItem.children = fieldTransformers(requeatItem, requestData.value.toString()); | ||||||
|  |       } | ||||||
|  |       items.push(dataItem); | ||||||
|  |     }); | ||||||
|  |   }); | ||||||
|   return <Descriptions title="汇总:" items={items} />; |   return <Descriptions title="汇总:" items={items} />; | ||||||
| }; | }; | ||||||
|  | 
 | ||||||
|  | const fieldTransformers = (item, data) => { | ||||||
|  |   const { option: tOption } = transformers; | ||||||
|  |   if (item.fieldFormat) { | ||||||
|  |     const option = item.fieldFormat.option; | ||||||
|  |     const decimal = item.fieldFormat.decimal; | ||||||
|  |     if (option && option !== 'decimal') { | ||||||
|  |       const component = tOption.filter((tValue) => tValue.value === option)[0].component; | ||||||
|  |       data = String(data).includes(',') ? String(data).replace(/,/g, '') : data; | ||||||
|  |       return component(data); | ||||||
|  |     } else if (option && option === 'decimal') { | ||||||
|  |       const component = tOption | ||||||
|  |         .filter((tValue) => tValue.value === 'decimal')[0] | ||||||
|  |         .childrens.filter((decimalOption) => decimalOption.value === decimal)[0].component; | ||||||
|  |       data = String(data).includes(',') ? String(data).replace(/,/g, '') : data; | ||||||
|  |       return component(data); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  | |||||||
| @ -121,38 +121,6 @@ export const GroupBlockInitializer = () => { | |||||||
| export const groupBlockSettings = new SchemaSettings({ | export const groupBlockSettings = new SchemaSettings({ | ||||||
|   name: 'groupBlockSettings', |   name: 'groupBlockSettings', | ||||||
|   items: [ |   items: [ | ||||||
|     { |  | ||||||
|       type: 'itemGroup', |  | ||||||
|       name: 'displayFields', |  | ||||||
|       componentProps: { title: 'display Fields' }, |  | ||||||
|       useChildren() { |  | ||||||
|         const item = []; |  | ||||||
|         const { dn } = useDesignable(); |  | ||||||
|         const fieldSchema = useFieldSchema(); |  | ||||||
|         const measures = fieldSchema['x-decorator-props'].params?.measures; |  | ||||||
|         if (measures && measures.length) { |  | ||||||
|           measures.forEach((value) => { |  | ||||||
|             item.push({ |  | ||||||
|               type: 'item', |  | ||||||
|               Component: () => ( |  | ||||||
|                 <SchemaSettingsSwitchItem |  | ||||||
|                   title={value.label} |  | ||||||
|                   checked={value.display} |  | ||||||
|                   onChange={(chang) => { |  | ||||||
|                     value.display = chang; |  | ||||||
|                     dn.emit('patch', { |  | ||||||
|                       schema: fieldSchema, |  | ||||||
|                     }); |  | ||||||
|                     dn.refresh(); |  | ||||||
|                   }} |  | ||||||
|                 /> |  | ||||||
|               ), |  | ||||||
|             }); |  | ||||||
|           }); |  | ||||||
|         } |  | ||||||
|         return item; |  | ||||||
|       }, |  | ||||||
|     }, |  | ||||||
|     { |     { | ||||||
|       name: 'Configure', |       name: 'Configure', | ||||||
|       Component: GroupBlockConfigure, |       Component: GroupBlockConfigure, | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user