feat: 汇总区块添加表格样式及配置项排序 (#536)
Reviewed-on: daoyoucloud/tachycode#536 Co-authored-by: wjh <wwwjh0710@163.com> Co-committed-by: wjh <wwwjh0710@163.com>
This commit is contained in:
parent
dc7c6a5052
commit
1675b39d0e
@ -1,9 +1,10 @@
|
|||||||
import { useField, useFieldSchema } from '@formily/react';
|
import { useField, useFieldSchema } from '@formily/react';
|
||||||
import { findFilterTargets, useAPIClient, useBlockRequestContext, useFilterBlock } from '@nocobase/client';
|
import { findFilterTargets, useAPIClient, useBlockRequestContext, useFilterBlock } from '@nocobase/client';
|
||||||
import { Descriptions, DescriptionsProps, Spin } from 'antd';
|
import { Descriptions, DescriptionsProps, Space, Spin } from 'antd';
|
||||||
import { transformers } from './GroupBlockConfigure/transformers';
|
import { transformers } from './GroupBlockConfigure/transformers';
|
||||||
import React, { useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { useAsyncEffect } from 'ahooks';
|
import { useAsyncEffect } from 'ahooks';
|
||||||
|
import { GroupConfigure } from './GroupBlockConfigure/GroupConfigure';
|
||||||
|
|
||||||
type DataItem = {
|
type DataItem = {
|
||||||
labels: string[];
|
labels: string[];
|
||||||
@ -20,11 +21,8 @@ export const GroupBlock = (props) => {
|
|||||||
const params = fieldSchema.parent['x-decorator-props'].params;
|
const params = fieldSchema.parent['x-decorator-props'].params;
|
||||||
const { resource, service } = useBlockRequestContext();
|
const { resource, service } = useBlockRequestContext();
|
||||||
const { getDataBlocks } = useFilterBlock();
|
const { getDataBlocks } = useFilterBlock();
|
||||||
const { targets = [], uid } = findFilterTargets(fieldSchema);
|
|
||||||
const api = useAPIClient();
|
|
||||||
const [result, setResult] = useState([]);
|
|
||||||
const items: DescriptionsProps['items'] = [];
|
|
||||||
const Blocks = getDataBlocks();
|
const Blocks = getDataBlocks();
|
||||||
|
const [group, setGroup] = useState([]);
|
||||||
if (!service.params.length) {
|
if (!service.params.length) {
|
||||||
getDataBlocks().map((block) => {
|
getDataBlocks().map((block) => {
|
||||||
if (Object.keys(block.defaultFilter).length) {
|
if (Object.keys(block.defaultFilter).length) {
|
||||||
@ -37,84 +35,35 @@ export const GroupBlock = (props) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
|
||||||
method: 'POST',
|
|
||||||
data: {
|
|
||||||
filter: { ...filter },
|
|
||||||
collection: params.collection,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
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] ? { ...service.data?.data[0] } : {};
|
return (
|
||||||
|
<>
|
||||||
params?.config?.measures?.forEach((measuresItem) => {
|
<p style={{ fontWeight: 600 }}>汇总:</p>
|
||||||
const value = measuresItem.fieldFormat.fieldValue;
|
{params?.config.map((configItem, index) => {
|
||||||
if (!data[value]) data[value] = 0;
|
if (configItem) {
|
||||||
data[value] = fieldTransformers(measuresItem, data[value], api);
|
return <GroupConfigure {...props} configItem={configItem} service={service} key={index} />;
|
||||||
});
|
|
||||||
|
|
||||||
for (const key in data) {
|
|
||||||
params?.config?.measures?.forEach((value) => {
|
|
||||||
if (value.field[0] === key) {
|
|
||||||
if (value.display) {
|
|
||||||
items.push({
|
|
||||||
key: key,
|
|
||||||
label: value.label,
|
|
||||||
children: data[key],
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
})}
|
||||||
});
|
</>
|
||||||
}
|
);
|
||||||
|
|
||||||
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], api)}`;
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
dataItem.children = fieldTransformers(requeatItem, requestData.value.toString(), api);
|
|
||||||
}
|
|
||||||
items.push(dataItem);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return <Descriptions title="汇总:" items={items} />;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const fieldTransformers = (item, data, api) => {
|
export const fieldTransformers = (item, data, api) => {
|
||||||
const { option: tOption } = transformers;
|
const { option: tOption } = transformers;
|
||||||
const locale = api.auth.getLocale();
|
const locale = api.auth.getLocale();
|
||||||
if (item.fieldFormat) {
|
if (item) {
|
||||||
const option = item.fieldFormat.option;
|
const format = item.format;
|
||||||
const decimal = item.fieldFormat.decimal;
|
const digits = item?.digits;
|
||||||
if (option && option !== 'decimal') {
|
if (format && format !== 'decimal') {
|
||||||
const component = tOption.filter((tValue) => tValue.value === option)[0].component;
|
const component = tOption.find((tValue) => tValue.value === format).component;
|
||||||
data = String(data).includes(',') ? String(data).replace(/,/g, '') : data;
|
data = String(data).includes(',') ? String(data).replace(/,/g, '') : data;
|
||||||
return component(data, locale);
|
return component(data, locale);
|
||||||
} else if (option && option === 'decimal') {
|
} else if (format && format === 'decimal' && digits) {
|
||||||
const component = tOption
|
const component = tOption
|
||||||
.filter((tValue) => tValue.value === 'decimal')[0]
|
.filter((tValue) => tValue.value === 'decimal')[0]
|
||||||
.childrens.filter((decimalOption) => decimalOption.value === decimal)[0].component;
|
.childrens.filter((decimalOption) => decimalOption.value === digits)[0].component;
|
||||||
data = String(data).includes(',') ? String(data).replace(/,/g, '') : data;
|
data = String(data).includes(',') ? String(data).replace(/,/g, '') : data;
|
||||||
return component(data);
|
return component(data);
|
||||||
}
|
}
|
||||||
|
@ -1,21 +1,205 @@
|
|||||||
import { SchemaSettingsItem } from '@nocobase/client';
|
import {
|
||||||
|
SchemaComponentOptions,
|
||||||
|
SchemaSettingsItem,
|
||||||
|
SchemaSettingsModalItem,
|
||||||
|
useBlockRequestContext,
|
||||||
|
useDesignable,
|
||||||
|
} from '@nocobase/client';
|
||||||
import React, { useContext } from 'react';
|
import React, { useContext } from 'react';
|
||||||
import { useTranslation } from '../../../locale';
|
import { useTranslation } from '../../../locale';
|
||||||
import { Modal } from 'antd';
|
|
||||||
import { GroupBlockContext } from '../../../schema-initializer/blocks/GroupBlockInitializer';
|
import { GroupBlockContext } from '../../../schema-initializer/blocks/GroupBlockInitializer';
|
||||||
|
import { transformers } from './transformers';
|
||||||
|
import { ISchema, connect, useFieldSchema } from '@formily/react';
|
||||||
|
import { ArrayItems, FormItem, Space } from '@formily/antd-v5';
|
||||||
|
import { PullRequestOutlined } from '@ant-design/icons';
|
||||||
|
|
||||||
export const GroupBlockConfigure = (props) => {
|
export const GroupBlockConfigure = connect((props) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { setVisible, visible } = useContext(GroupBlockContext);
|
const fieldSchema = useFieldSchema();
|
||||||
|
const { dn } = useDesignable();
|
||||||
|
const { service } = useBlockRequestContext();
|
||||||
|
|
||||||
|
const params = fieldSchema['x-decorator-props']?.params;
|
||||||
|
const measures = params?.measures;
|
||||||
|
const decimal = transformers.option.filter((item) => item.value === 'decimal')[0].childrens;
|
||||||
|
const valueOption = measures.map((item) => {
|
||||||
|
return {
|
||||||
|
label: item.label,
|
||||||
|
value: item.field[0],
|
||||||
|
};
|
||||||
|
});
|
||||||
|
const { scope } = useContext(GroupBlockContext);
|
||||||
|
const schema = modalSchema(t, params, valueOption, decimal);
|
||||||
return (
|
return (
|
||||||
<SchemaSettingsItem
|
<SchemaComponentOptions scope={{ ...scope }} components={{ ArrayItems, FormItem, Space, PullRequestOutlined }}>
|
||||||
|
<SchemaSettingsModalItem
|
||||||
title="Configure"
|
title="Configure"
|
||||||
key="configure"
|
key="configure"
|
||||||
onClick={async () => {
|
onSubmit={(fieldOptionItem) => {
|
||||||
setVisible(true);
|
fieldSchema['x-decorator-props'].params['config'] = [...fieldOptionItem.configField];
|
||||||
|
dn.emit('patch', {
|
||||||
|
schema: {
|
||||||
|
'x-uid': fieldSchema['x-uid'],
|
||||||
|
'x-decorator-props': fieldSchema['x-decorator-props'],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
dn.refresh();
|
||||||
|
service?.refresh();
|
||||||
}}
|
}}
|
||||||
>
|
schema={schema as ISchema}
|
||||||
{t('Configure')}
|
/>
|
||||||
</SchemaSettingsItem>
|
</SchemaComponentOptions>
|
||||||
);
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
const fieldType = [
|
||||||
|
{
|
||||||
|
label: '字段配置',
|
||||||
|
value: 'field',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '请求配置',
|
||||||
|
value: 'custom',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const styleOption = [
|
||||||
|
{
|
||||||
|
label: '描述',
|
||||||
|
value: 'describe',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '表格',
|
||||||
|
value: 'table',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const modalSchema = (t, params, valueOption, decimal) => {
|
||||||
|
const schema = {
|
||||||
|
title: t('Configure Group'),
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
configField: {
|
||||||
|
title: 'Config Field',
|
||||||
|
type: 'array',
|
||||||
|
'x-decorator': 'FormItem',
|
||||||
|
'x-component': 'ArrayItems',
|
||||||
|
default: params.config,
|
||||||
|
items: {
|
||||||
|
type: 'object',
|
||||||
|
'x-decorator': 'ArrayItems.Item',
|
||||||
|
properties: {
|
||||||
|
space: {
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'Space',
|
||||||
|
properties: {
|
||||||
|
sort: {
|
||||||
|
type: 'void',
|
||||||
|
'x-decorator': 'FormItem',
|
||||||
|
'x-component': 'ArrayItems.SortHandle',
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
type: 'string',
|
||||||
|
'x-decorator': 'FormItem',
|
||||||
|
'x-component': 'Select',
|
||||||
|
'x-component-props': {
|
||||||
|
placeholder: '{{t("type")}}',
|
||||||
|
},
|
||||||
|
enum: fieldType,
|
||||||
|
require: true,
|
||||||
|
},
|
||||||
|
field: {
|
||||||
|
type: 'string',
|
||||||
|
'x-decorator': 'FormItem',
|
||||||
|
'x-component': 'Select',
|
||||||
|
'x-component-props': {
|
||||||
|
placeholder: '{{t("field")}}',
|
||||||
|
},
|
||||||
|
'x-visbile': false,
|
||||||
|
enum: valueOption,
|
||||||
|
'x-reactions': {
|
||||||
|
dependencies: ['.type'],
|
||||||
|
fulfill: {
|
||||||
|
schema: {
|
||||||
|
'x-visible': "{{$deps[0]==='field'}}",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
reqUrl: {
|
||||||
|
type: 'string',
|
||||||
|
'x-decorator': 'FormItem',
|
||||||
|
'x-component': 'Input',
|
||||||
|
'x-component-props': {
|
||||||
|
placeholder: '{{t("reqUrl")}}',
|
||||||
|
addonBefore: <PullRequestOutlined />,
|
||||||
|
},
|
||||||
|
'x-visible': false,
|
||||||
|
'x-reactions': {
|
||||||
|
dependencies: ['.type'],
|
||||||
|
fulfill: {
|
||||||
|
schema: {
|
||||||
|
'x-visible': "{{$deps[0]==='custom'}}",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
format: {
|
||||||
|
type: 'string',
|
||||||
|
'x-decorator': 'FormItem',
|
||||||
|
'x-component': 'Select',
|
||||||
|
'x-component-props': {
|
||||||
|
placeholder: '{{t("format")}}',
|
||||||
|
},
|
||||||
|
enum: transformers.option,
|
||||||
|
require: true,
|
||||||
|
},
|
||||||
|
digits: {
|
||||||
|
type: 'string',
|
||||||
|
'x-decorator': 'FormItem',
|
||||||
|
'x-component': 'Select',
|
||||||
|
'x-component-props': {
|
||||||
|
placeholder: '{{t("digits")}}',
|
||||||
|
},
|
||||||
|
enum: decimal,
|
||||||
|
'x-visible': false,
|
||||||
|
'x-reactions': {
|
||||||
|
dependencies: ['.format'],
|
||||||
|
fulfill: {
|
||||||
|
schema: {
|
||||||
|
'x-visible': "{{$deps[0]==='decimal'}}",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
style: {
|
||||||
|
type: 'string',
|
||||||
|
'x-decorator': 'FormItem',
|
||||||
|
'x-component': 'Select',
|
||||||
|
'x-component-props': {
|
||||||
|
placeholder: '{{t("style")}}',
|
||||||
|
},
|
||||||
|
enum: styleOption,
|
||||||
|
require: true,
|
||||||
|
},
|
||||||
|
remove: {
|
||||||
|
type: 'void',
|
||||||
|
'x-decorator': 'FormItem',
|
||||||
|
'x-component': 'ArrayItems.Remove',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
properties: {
|
||||||
|
add: {
|
||||||
|
type: 'void',
|
||||||
|
title: 'Add',
|
||||||
|
'x-component': 'ArrayItems.Addition',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return schema;
|
||||||
};
|
};
|
||||||
|
@ -1,231 +1,132 @@
|
|||||||
import { useField, useFieldSchema } from '@formily/react';
|
import { useField, useFieldSchema } from '@formily/react';
|
||||||
import { useDesignable, useFieldNames, useFilterBlock } from '@nocobase/client';
|
import { useAPIClient, useFilterBlock, useRequest } from '@nocobase/client';
|
||||||
import { App, Button, Flex, Input, Modal, Select } from 'antd';
|
import { Descriptions, DescriptionsProps, Spin, Table } from 'antd';
|
||||||
import React, { useContext, useEffect, useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { useTranslation } from '../../../locale';
|
import { useAsyncEffect } from 'ahooks';
|
||||||
import { GroupBlockContext } from '../../../schema-initializer/blocks/GroupBlockInitializer';
|
import { fieldTransformers } from '../GroupBlock';
|
||||||
import { transformers } from './transformers';
|
|
||||||
import { DeleteOutlined, PullRequestOutlined } from '@ant-design/icons';
|
|
||||||
import { uid } from '@formily/shared';
|
|
||||||
|
|
||||||
export type SelectedField = {
|
type reqData = {
|
||||||
field: string | string[];
|
labels: any[];
|
||||||
alias?: string;
|
values: any[];
|
||||||
};
|
|
||||||
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 { configItem, service } = props;
|
||||||
const { t } = useTranslation();
|
|
||||||
const { dn } = useDesignable();
|
|
||||||
const { modal } = App.useApp();
|
|
||||||
const fieldSchema = useFieldSchema();
|
const fieldSchema = useFieldSchema();
|
||||||
const measures = fieldSchema['x-decorator-props']?.params?.measures;
|
const field = useField<any>();
|
||||||
const option: fieldOptionType[] = [];
|
const params = fieldSchema.parent['x-decorator-props'].params;
|
||||||
const params = fieldSchema['x-decorator-props']?.params;
|
const [result, setResult] = useState({});
|
||||||
if (params['config']) {
|
const { getDataBlocks } = useFilterBlock();
|
||||||
if (params['config']['measures']) {
|
const Blocks = getDataBlocks();
|
||||||
option.push(...params['config']['measures']);
|
const api = useAPIClient();
|
||||||
}
|
useAsyncEffect(async () => {
|
||||||
if (params['config']['request']) {
|
const filter = service?.params[0] ? service.params[0].filter : service?.params;
|
||||||
option.push(...params['config']['request']);
|
if (configItem.reqUrl) {
|
||||||
}
|
setResult(
|
||||||
}
|
(await api.request({
|
||||||
|
url: configItem.reqUrl,
|
||||||
const [fieldOption, setFieldOption] = useState(JSON.parse(JSON.stringify(option)));
|
method: 'POST',
|
||||||
const fieldType = [
|
data: {
|
||||||
{
|
filter: { ...filter },
|
||||||
label: '字段配置',
|
collection: params.collection,
|
||||||
value: 'field',
|
|
||||||
},
|
},
|
||||||
{
|
})) ?? {},
|
||||||
label: '请求配置',
|
|
||||||
value: 'custom',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
const valueOption = measures.map((item) => {
|
|
||||||
return {
|
|
||||||
label: item.label,
|
|
||||||
value: item.field[0],
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
const decimal = transformers.option.filter((item) => item.value === 'decimal')[0].childrens;
|
|
||||||
useEffect(() => {
|
|
||||||
if (!visible) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}, [visible]);
|
|
||||||
return (
|
|
||||||
<Modal
|
|
||||||
title={t('Configure Group')}
|
|
||||||
open={visible}
|
|
||||||
onOk={() => {
|
|
||||||
const request = [];
|
|
||||||
const configMeasures = [];
|
|
||||||
fieldOption.forEach((fieldOptionItem) => {
|
|
||||||
if (fieldOptionItem.fieldFormat.type === 'field') {
|
|
||||||
const { measureItem, index } = measures
|
|
||||||
.map((measureItem, index) => {
|
|
||||||
if (measureItem.field[0] === fieldOptionItem?.fieldFormat?.fieldValue) {
|
|
||||||
return { measureItem, index };
|
|
||||||
} else {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.filter((value) => value.measureItem)[0];
|
|
||||||
if (measureItem) {
|
|
||||||
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,
|
|
||||||
request,
|
|
||||||
};
|
|
||||||
dn.emit('patch', {
|
|
||||||
schema: fieldSchema,
|
|
||||||
});
|
|
||||||
setVisible(false);
|
|
||||||
dn.refresh();
|
|
||||||
}}
|
|
||||||
onCancel={() => {
|
|
||||||
modal.confirm({
|
|
||||||
title: t('Are you sure to cancel?'),
|
|
||||||
content: t('You changes are not saved. If you click OK, your changes will be lost.'),
|
|
||||||
okButtonProps: {
|
|
||||||
danger: true,
|
|
||||||
},
|
|
||||||
onOk: () => {
|
|
||||||
setVisible(false);
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
width={'30%'}
|
|
||||||
>
|
|
||||||
<div style={{ display: 'flex', marginBottom: '10px', marginTop: '10px', flexDirection: 'column' }}>
|
|
||||||
{fieldOption.map((item, index) => {
|
|
||||||
return (
|
|
||||||
<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
|
|
||||||
options={valueOption}
|
|
||||||
placeholder="Field"
|
|
||||||
style={{ marginRight: '5px' }}
|
|
||||||
value={item?.fieldFormat?.fieldValue ? item?.fieldFormat?.fieldValue : undefined}
|
|
||||||
onChange={(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
|
|
||||||
options={transformers.option}
|
|
||||||
placeholder="Format"
|
|
||||||
style={{ marginRight: '5px' }}
|
|
||||||
value={item?.fieldFormat?.option ? item?.fieldFormat?.option : undefined}
|
|
||||||
onChange={(v) => {
|
|
||||||
fieldConfig('format', fieldOption, setFieldOption, index, v);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
{item?.fieldFormat?.option === 'decimal' ? (
|
|
||||||
<Select
|
|
||||||
options={decimal}
|
|
||||||
placeholder="Digits"
|
|
||||||
style={{ marginRight: '5px' }}
|
|
||||||
value={item.fieldFormat.decimal}
|
|
||||||
onChange={(v) => fieldConfig('decimal', fieldOption, setFieldOption, index, v)}
|
|
||||||
/>
|
|
||||||
) : null}
|
|
||||||
<DeleteOutlined
|
|
||||||
style={{ fontSize: '14px' }}
|
|
||||||
onClick={() => {
|
|
||||||
fieldConfig('del', fieldOption, setFieldOption, index);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
<Button
|
|
||||||
type="dashed"
|
|
||||||
style={{ borderRadius: '0', width: '30%' }}
|
|
||||||
onClick={() => {
|
|
||||||
fieldConfig('add', fieldOption, setFieldOption);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
+ Add Field
|
|
||||||
</Button>
|
|
||||||
</Modal>
|
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
}, [Blocks, service.params, service.params[0]]);
|
||||||
|
if (configItem.style === 'describe') {
|
||||||
|
const item: DescriptionsProps['items'] = describeItem(configItem, result, service, params, api);
|
||||||
|
return <Descriptions style={{ marginBottom: '10px' }} items={item} />;
|
||||||
|
} else if (configItem.style === 'table') {
|
||||||
|
const { columns, options } = tableItem(configItem, result, service, params, api);
|
||||||
|
return <Table style={{ marginBottom: '10px' }} columns={columns} dataSource={options} pagination={false} />;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const fieldConfig = (type, fieldOption, setFieldOption, index?, record?) => {
|
const describeItem = (configItem, result, service, params, api) => {
|
||||||
const option = [...fieldOption];
|
const item = [];
|
||||||
if (type === 'add') {
|
if (configItem.type === 'field') {
|
||||||
option.push({});
|
const measuresData = service.data?.data;
|
||||||
} else if (type === 'del') {
|
if (measuresData) {
|
||||||
option.splice(index, 1);
|
let data = measuresData.map((value) => {
|
||||||
} else if (type === 'type') {
|
return value[configItem.field];
|
||||||
option[index]['fieldFormat'] = {
|
})[0];
|
||||||
...option[index]['fieldFormat'],
|
data = fieldTransformers(configItem, data, api);
|
||||||
type: record,
|
const label = params.measures.find((value) => value.field[0] === configItem.field).label;
|
||||||
};
|
item.push({
|
||||||
} else if (type === 'url') {
|
key: configItem.field,
|
||||||
option[index]['fieldFormat'] = {
|
label,
|
||||||
...option[index]['fieldFormat'],
|
children: data,
|
||||||
requestUrl: record,
|
});
|
||||||
};
|
|
||||||
} else if (type === 'field') {
|
|
||||||
option[index]['fieldFormat'] = {
|
|
||||||
...option[index]['fieldFormat'],
|
|
||||||
fieldValue: record,
|
|
||||||
};
|
|
||||||
} else if (type === 'format') {
|
|
||||||
option[index]['fieldFormat'] = {
|
|
||||||
...option[index]['fieldFormat'],
|
|
||||||
option: record,
|
|
||||||
};
|
|
||||||
} else if (type === 'decimal') {
|
|
||||||
option[index]['fieldFormat'] = {
|
|
||||||
...option[index]['fieldFormat'],
|
|
||||||
decimal: record,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
setFieldOption(option);
|
} else if (configItem.type === 'custom') {
|
||||||
|
if (Object.keys(result).length && result?.['data']?.data) {
|
||||||
|
const data: reqData = { ...result?.['data']?.data };
|
||||||
|
const label = data.labels;
|
||||||
|
data.values.forEach((valueItem, index) => {
|
||||||
|
let childrenText = '';
|
||||||
|
label.forEach((value, index) => {
|
||||||
|
if (index === 0) return;
|
||||||
|
childrenText += `${value}${fieldTransformers(configItem, valueItem[index], api)} `;
|
||||||
|
});
|
||||||
|
item.push({
|
||||||
|
key: index,
|
||||||
|
label: valueItem[0],
|
||||||
|
children: childrenText,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return item;
|
||||||
|
};
|
||||||
|
|
||||||
|
const tableItem = (configItem, result, service, params, api) => {
|
||||||
|
const columns = [];
|
||||||
|
const options = [];
|
||||||
|
if (configItem.type === 'custom') {
|
||||||
|
if (Object.keys(result).length && result?.['data']?.data) {
|
||||||
|
const data: reqData = { ...result?.['data']?.data };
|
||||||
|
data.labels.forEach((value, index) => {
|
||||||
|
columns.push({ title: value, dataIndex: 'value' + index, key: index });
|
||||||
|
});
|
||||||
|
data.values.forEach((value, index) => {
|
||||||
|
const item = {
|
||||||
|
key: index,
|
||||||
|
};
|
||||||
|
columns.forEach((colItem, index) => {
|
||||||
|
const data = isNaN(value[index]) ? value[index] : fieldTransformers(configItem, value[index], api);
|
||||||
|
item[colItem.dataIndex] = data;
|
||||||
|
});
|
||||||
|
options.push(item);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else if (configItem.type === 'field') {
|
||||||
|
const measuresData = service.data?.data;
|
||||||
|
if (measuresData) {
|
||||||
|
let data = measuresData.map((value) => {
|
||||||
|
return value[configItem.field];
|
||||||
|
})[0];
|
||||||
|
data = fieldTransformers(configItem, data, api);
|
||||||
|
const label = params.measures.find((value) => value.field[0] === configItem.field).label;
|
||||||
|
columns.push(
|
||||||
|
{
|
||||||
|
title: '名称',
|
||||||
|
dataIndex: 'name',
|
||||||
|
key: 'name',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '数量',
|
||||||
|
dataIndex: 'number',
|
||||||
|
key: 'number',
|
||||||
|
},
|
||||||
|
);
|
||||||
|
options.push({
|
||||||
|
key: label,
|
||||||
|
name: label,
|
||||||
|
number: data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { columns, options };
|
||||||
};
|
};
|
||||||
|
@ -17,7 +17,6 @@ import React, { createContext, useState } from 'react';
|
|||||||
import { uid } from '@nocobase/utils/client';
|
import { uid } from '@nocobase/utils/client';
|
||||||
import { Checkbox, Spin } from 'antd';
|
import { Checkbox, Spin } from 'antd';
|
||||||
import { GroupBlockConfigure } from '../../schema-components/blocks/GroupBlockConfigure/GroupBlockConfigure';
|
import { GroupBlockConfigure } from '../../schema-components/blocks/GroupBlockConfigure/GroupBlockConfigure';
|
||||||
import { GroupConfigure } from '../../schema-components/blocks/GroupBlockConfigure/GroupConfigure';
|
|
||||||
|
|
||||||
export const GroupBlockContext = createContext<any>({});
|
export const GroupBlockContext = createContext<any>({});
|
||||||
|
|
||||||
@ -43,7 +42,6 @@ const InternalGroupBlockProvider = (props) => {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{props.children}
|
{props.children}
|
||||||
<GroupConfigure />
|
|
||||||
</GroupBlockContext.Provider>
|
</GroupBlockContext.Provider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -80,15 +80,14 @@ export class RecordPreviewController {
|
|||||||
items[product.name].total -= count;
|
items[product.name].total -= count;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
ctx.body = _.toArray(items)
|
const result = {
|
||||||
|
labels: ['名称', '出库数量', '入库数量', '小计'],
|
||||||
|
values: [],
|
||||||
|
};
|
||||||
|
_.toArray(items)
|
||||||
.sort((a, b) => a.sort - b.sort)
|
.sort((a, b) => a.sort - b.sort)
|
||||||
.map((item) => ({
|
.forEach((item) => result.values.push([item.name, item.out, item.in, item.total]));
|
||||||
label: item.name,
|
ctx.body = { ...result };
|
||||||
value: {
|
|
||||||
labels: ['出库数量', '入库数量', '小计'],
|
|
||||||
values: [item.out, item.in, item.total],
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@Action('allweight')
|
@Action('allweight')
|
||||||
@ -106,15 +105,10 @@ export class RecordPreviewController {
|
|||||||
|
|
||||||
const inNum = records.find((item) => item.movement === Movement.in)?.weight ?? 0;
|
const inNum = records.find((item) => item.movement === Movement.in)?.weight ?? 0;
|
||||||
const outNum = records.find((item) => item.movement === Movement.out)?.weight ?? 0;
|
const outNum = records.find((item) => item.movement === Movement.out)?.weight ?? 0;
|
||||||
const data = [
|
const data = {
|
||||||
{
|
labels: ['名称', '出库数量(吨)', '入库数量(吨)', '小计(吨)'],
|
||||||
label: '实际重量(吨)',
|
values: [['实际重量(吨)', outNum, inNum, inNum - outNum]],
|
||||||
value: {
|
};
|
||||||
labels: ['出库数量(吨)', '入库数量(吨)', '小计(吨)'],
|
|
||||||
values: [outNum, inNum, inNum - outNum],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
];
|
|
||||||
ctx.body = data;
|
ctx.body = data;
|
||||||
}
|
}
|
||||||
@Action('allprice')
|
@Action('allprice')
|
||||||
@ -132,15 +126,10 @@ export class RecordPreviewController {
|
|||||||
|
|
||||||
const inNum = records.find((item) => item.movement === Movement.in)?.all_price ?? 0;
|
const inNum = records.find((item) => item.movement === Movement.in)?.all_price ?? 0;
|
||||||
const outNum = records.find((item) => item.movement === Movement.out)?.all_price ?? 0;
|
const outNum = records.find((item) => item.movement === Movement.out)?.all_price ?? 0;
|
||||||
const data = [
|
const data = {
|
||||||
{
|
labels: ['名称', '收入', '支出', '小计'],
|
||||||
label: '总金额',
|
values: [['总金额', outNum, inNum, outNum - inNum]],
|
||||||
value: {
|
};
|
||||||
labels: ['收入', '支出', '小计'],
|
|
||||||
values: [outNum, inNum, outNum - inNum],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
];
|
|
||||||
ctx.body = data;
|
ctx.body = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user