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