Commit 561f975d authored by 陈龙's avatar 陈龙

feat: 新增报表组件

parent fb2e80f0
...@@ -147,7 +147,6 @@ ...@@ -147,7 +147,6 @@
"@wisdom-components/basictable": "^1.5.14", "@wisdom-components/basictable": "^1.5.14",
"@wisdom-components/empty": "^1.3.9", "@wisdom-components/empty": "^1.3.9",
"@wisdom-components/exportexcel": "^1.1.2", "@wisdom-components/exportexcel": "^1.1.2",
"@wisdom-components/rich": "file:packages/base-components/rich",
"@wisdom-components/timerangepicker": "^1.3.4", "@wisdom-components/timerangepicker": "^1.3.4",
"@wisdom-utils/utils": "0.0.46", "@wisdom-utils/utils": "0.0.46",
"classnames": "^2.2.6", "classnames": "^2.2.6",
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { Form, Input, DatePicker, InputNumber, Space, Row, Col, Button, message } from 'antd'; import { Form, Input, DatePicker, InputNumber, Space, Row, Col, Button, message } from 'antd';
import moment from 'moment'; import moment from 'moment';
import { submitReportData } from '../../../api/service/report'; import { submitReportData } from './api/service/report';
// 类型 // 类型
const DATE_PICKER_ARRAY = ['日期']; const DATE_PICKER_ARRAY = ['日期'];
const DATE_TIME_PICKER_ARRAY = ['日期时刻']; const DATE_TIME_PICKER_ARRAY = ['日期时刻'];
...@@ -18,12 +18,12 @@ const NUMBER_ARRAY = ['数值', '金额']; ...@@ -18,12 +18,12 @@ const NUMBER_ARRAY = ['数值', '金额'];
// 对应关系 // 对应关系
/** /**
* @Description: 函数描述 * @description: 函数描述
* @Date: 2022/8/10 * @date: 2022/8/10
* @Author: ChenLong * @author: ChenLong
* @Params: reportDetails 各个字段的配置列表 * @params: reportDetails 各个字段的配置列表
* data 与reportDetails对应的值 * data 与reportDetails对应的值
* */ */
const ReportEditForm = ({ reportDetails, reportData, onCancel, reportName }) => { const ReportEditForm = ({ reportDetails, reportData, onCancel, reportName }) => {
if (!reportData || Object.keys(reportData).length === 0) return <>未传递表单数据</>; if (!reportData || Object.keys(reportData).length === 0) return <>未传递表单数据</>;
const [form] = Form.useForm(); const [form] = Form.useForm();
...@@ -37,7 +37,7 @@ const ReportEditForm = ({ reportDetails, reportData, onCancel, reportName }) => ...@@ -37,7 +37,7 @@ const ReportEditForm = ({ reportDetails, reportData, onCancel, reportName }) =>
}; };
const handleDate = (reportDetails, data) => { const handleDate = (reportDetails, data) => {
let _data = { ...data }; let _data = { ...data };
reportDetails.forEach(item => { reportDetails.forEach((item) => {
if (DATE_TYPE.includes(item.type)) { if (DATE_TYPE.includes(item.type)) {
_data[item.fieldAlias] = moment(data[item.fieldAlias]); _data[item.fieldAlias] = moment(data[item.fieldAlias]);
} }
...@@ -64,7 +64,7 @@ const ReportEditForm = ({ reportDetails, reportData, onCancel, reportName }) => ...@@ -64,7 +64,7 @@ const ReportEditForm = ({ reportDetails, reportData, onCancel, reportName }) =>
// "fieldValue": "string" // "fieldValue": "string"
// } // }
let final = []; let final = [];
Object.keys(_data).forEach(key => { Object.keys(_data).forEach((key) => {
let value = reportData[key]; let value = reportData[key];
let _value = _data[key]; let _value = _data[key];
if (moment.isMoment(_data[key])) { if (moment.isMoment(_data[key])) {
...@@ -80,10 +80,13 @@ const ReportEditForm = ({ reportDetails, reportData, onCancel, reportName }) => ...@@ -80,10 +80,13 @@ const ReportEditForm = ({ reportDetails, reportData, onCancel, reportName }) =>
}); });
console.log(final); console.log(final);
// reportService.updateReportData() // reportService.updateReportData()
submitReportData({ submitReportData(
reportName: reportName, {
userId: window.globalConfig.userInfo.OID, reportName: reportName,
}, final).then(res => { userId: window.globalConfig.userInfo.OID,
},
final,
).then((res) => {
if (res.code === 0) { if (res.code === 0) {
message.success('保存成功!'); message.success('保存成功!');
onCancel(); onCancel();
...@@ -91,26 +94,30 @@ const ReportEditForm = ({ reportDetails, reportData, onCancel, reportName }) => ...@@ -91,26 +94,30 @@ const ReportEditForm = ({ reportDetails, reportData, onCancel, reportName }) =>
}); });
}; };
useEffect(() => { useEffect(() => {
if (reportData && Object.keys(reportData).length) form.setFieldsValue(handleDate(reportDetails, reportData)); if (reportData && Object.keys(reportData).length)
form.setFieldsValue(handleDate(reportDetails, reportData));
}, [reportData]); }, [reportData]);
return ( return (
<div> <div>
<Form {...formItemLayout} form={form}> <Form {...formItemLayout} form={form}>
<Row> <Row>
{ {reportDetails &&
reportDetails && reportDetails.map(config => { reportDetails.map((config) => {
return <Col span={8}> return (
<Form.Item label={config.fieldAlias} name={config.fieldAlias}> <Col span={8}>
{componentMap(config)} <Form.Item label={config.fieldAlias} name={config.fieldAlias}>
</Form.Item> {componentMap(config)}
</Col>; </Form.Item>
}) </Col>
} );
})}
</Row> </Row>
<Row> <Row>
<Col span={24} style={{textAlign:'right'}}> <Col span={24} style={{ textAlign: 'right' }}>
{/*<Form.Item style={{textAlign:'right'}}>*/} {/*<Form.Item style={{textAlign:'right'}}>*/}
<Button type={'primary'} onClick={submitReportForm}>提交</Button> <Button type={'primary'} onClick={submitReportForm}>
提交
</Button>
{/*</Form.Item>*/} {/*</Form.Item>*/}
</Col> </Col>
</Row> </Row>
......
...@@ -2,12 +2,7 @@ import { Modal, notification } from 'antd'; ...@@ -2,12 +2,7 @@ import { Modal, notification } from 'antd';
import { instanceRequest, service } from '@wisdom-utils/utils'; import { instanceRequest, service } from '@wisdom-utils/utils';
import AppService from './service/base';
import notificationService from './service/notification';
import AccountService from './service/account';
import AssetService from './service/asset';
import ReportService from './service/report'; import ReportService from './service/report';
// import WorkflowService from './service/workflow';
const { warning } = Modal; const { warning } = Modal;
// eslint-disable-next-line no-return-await // eslint-disable-next-line no-return-await
...@@ -32,7 +27,7 @@ const codeMessage = { ...@@ -32,7 +27,7 @@ const codeMessage = {
}; };
let instance = null; let instance = null;
instanceRequest.setErrorHandler(error => { instanceRequest.setErrorHandler((error) => {
const { response } = error; const { response } = error;
if (response && response.status) { if (response && response.status) {
const errorText = codeMessage[response.status] || response.statusText; const errorText = codeMessage[response.status] || response.statusText;
...@@ -44,9 +39,7 @@ instanceRequest.setErrorHandler(error => { ...@@ -44,9 +39,7 @@ instanceRequest.setErrorHandler(error => {
content: `${codeMessage[status]}`, content: `${codeMessage[status]}`,
centered: true, centered: true,
onOk(close) { onOk(close) {
window.share && window.share && window.share.event && window.share.event.emit('triggerLoginout');
window.share.event &&
window.share.event.emit('triggerLoginout');
close(); close();
}, },
}); });
...@@ -66,18 +59,5 @@ instanceRequest.setErrorHandler(error => { ...@@ -66,18 +59,5 @@ instanceRequest.setErrorHandler(error => {
return response; return response;
}); });
const appService = service(AppService);
const noticeService = service(notificationService);
const accountService = service(AccountService);
const assetService = service(AssetService);
// const workflowService = service(WorkflowService);
const reportService = service(ReportService); const reportService = service(ReportService);
export { export { reportService };
appService,
noticeService,
accountService,
assetService,
// workflowService
reportService
};
// 文本/下拉/多选/时间 // 文本/下拉/多选/时间
/** /**
* @Description: * @description:
* @Params: * @params:
* onChange: 需要传入onChange,接收值的变更 * onChange: 需要传入onChange,接收值的变更
* */ */
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { Input, Select } from 'antd'; import { Input, Select } from 'antd';
import { reportService } from '@/api'; import { reportService } from '../api';
import { returnDefaultValueOrConfigs } from '../utils/utils'; import { returnDefaultValueOrConfigs } from '../utils/utils';
const { Option } = Select; const { Option } = Select;
const { Search } = Input; const { Search } = Input;
const TextSearchComponent = ({ onChange, style, onSearch, placeholder }) => { const TextSearchComponent = ({ onChange, style, onSearch, placeholder }) => {
return <Search title={placeholder} style={style} placeholder={placeholder} onChange={onChange} onSearch={onSearch} />; return (
<Search
title={placeholder}
style={style}
placeholder={placeholder}
onChange={onChange}
onSearch={onSearch}
/>
);
}; };
/** /**
* data = ['选项1','选项2'...] * Data = ['选项1','选项2'...]
* @Props:
* 正常选项:武汉
* 附带统计数值: 武汉 (20)
* *
* */ * @props:
const SelectSearchComponent = ({ onChange, style, data, mode, reportName, fieldAlias, configItems }) => { * 正常选项:武汉
const [value,setValue] = useState(''); * 附带统计数值: 武汉 (20)
*/
const SelectSearchComponent = ({
onChange,
style,
data,
mode,
reportName,
fieldAlias,
configItems,
}) => {
const [value, setValue] = useState('');
const [options, setOptions] = useState([]); const [options, setOptions] = useState([]);
const defaultConfigs = returnDefaultValueOrConfigs(configItems, ['defaultValue']); const defaultConfigs = returnDefaultValueOrConfigs(configItems, ['defaultValue']);
const { defaultValue } = defaultConfigs; const { defaultValue } = defaultConfigs;
const getData = () => { const getData = () => {
reportService.getReportFilterValue({ reportService
reportName, .getReportFilterValue({
fieldAlias, reportName,
}).then(res => { fieldAlias,
if (res.code === 0) { })
setOptions(res.data); .then((res) => {
} if (res.code === 0) {
}).catch(err => { setOptions(res.data);
console.log(err); }
}); })
.catch((err) => {
console.log(err);
});
}; };
useEffect(() => { useEffect(() => {
getData(); getData();
setValue(defaultValue) setValue(defaultValue);
}, []); }, []);
return <Select return (
value={value} <Select
style={style} value={value}
onChange={(e) => { style={style}
onChange(e); onChange={(e) => {
setValue(e); onChange(e);
}} setValue(e);
mode={mode} }}
defaultValue={mode === 'multiple' ? defaultValue.split(',') : defaultValue} mode={mode}
allowClear defaultValue={mode === 'multiple' ? defaultValue.split(',') : defaultValue}
maxTagCount={1} allowClear
placeholder={`请选择${fieldAlias}`} maxTagCount={1}
> placeholder={`请选择${fieldAlias}`}
{ >
options && options.length ? {options && options.length
options.map( ? options.map((item) => (
item => <Option key={item.filterValue} value={item.filterValue}>{item.filterValue} <span <Option key={item.filterValue} value={item.filterValue}>
style={{ color: 'rgba(0,0,0,.65)' }}>({item.count})</span></Option>, {item.filterValue} <span style={{ color: 'rgba(0,0,0,.65)' }}>({item.count})</span>
) : '' </Option>
} ))
</Select>; : ''}
</Select>
);
}; };
const ReturnControlComponent = ({ const ReturnControlComponent = ({
type, type,
onChange, onChange,
style, style,
data, data,
onSearch, onSearch,
reportName, reportName,
fieldAlias, fieldAlias,
placeholder, placeholder,
configItems, configItems,
}) => { }) => {
let _component = ''; let _component = '';
switch (type) { switch (type) {
case '文本': case '文本':
_component = _component = (
<TextSearchComponent style={style} onChange={onChange} onSearch={onSearch} placeholder={placeholder} <TextSearchComponent
configItems={configItems} />; style={style}
onChange={onChange}
onSearch={onSearch}
placeholder={placeholder}
configItems={configItems}
/>
);
break; break;
case '下拉': case '下拉':
case '多选': case '多选':
_component = _component = (
<SelectSearchComponent mode={type === '多选' ? 'multiple' : ''} style={style} onChange={onChange} <SelectSearchComponent
reportName={reportName} fieldAlias={fieldAlias} configItems={configItems} />; mode={type === '多选' ? 'multiple' : ''}
style={style}
onChange={onChange}
reportName={reportName}
fieldAlias={fieldAlias}
configItems={configItems}
/>
);
break; break;
default: default:
break; break;
......
import style from '../ReportsManage.less'; import style from '../index.less';
import extraComponents from '../extra/extraComponents'; import extraComponents from '../extra/extraComponents';
import moment from 'moment'; import moment from 'moment';
import { Tag } from 'antd'; import { Tag } from 'antd';
import { hasMoney, isNumber } from './utils'; import { hasMoney, isNumber } from './utils';
/** /**
* @Params: config下的数值的configRule结构如下,[{最大值: 10,最小值: 0,颜色:'#AAAAAA'}]; * @params: config下的数值的configRule结构如下,[{最大值: 10,最小值: 0,颜色:'#AAAAAA'}];
* @business: configRule有值,则按照configRule设置;没有,按照color设置; * @business: configRule有值,则按照configRule设置;没有,按照color设置; 有最大值,无最小值;['', 1]
* 有最大值,无最小值;['', 1] * 有最大值,有最小值;[2,
* 有最大值,有最小值;[2, 10] * 10]
* 有最小值,无最大值;[11,''] * 有最小值,无最大值;[11,'']
* */ */
// 链接 功能 弹窗功能待提出需求 // 链接 功能 弹窗功能待提出需求
// 函数名、属性、... // 函数名、属性、...
const clickLink = (config) => { const clickLink = (config) => {
return window.open(config.configItems, '_blank'); return window.open(config.configItems, '_blank');
}; };
const handleUrl = (allWidgets, config) => { const handleUrl = (allWidgets, config) => {};
};
const handleConfigUrl = (config, record) => { const handleConfigUrl = (config, record) => {
let _configs = config.configItems.split('|'); let _configs = config.configItems.split('|');
// type = 替换|跳转; // type = 替换|跳转;
let _type = ''; let _type = '';
//url=project/pandawork/contractDetails/index?ageSize=100&accountName=软件订单台账|contractCode=${订单编号}|company=${分公司} //url=project/pandawork/contractDetails/index?ageSize=100&accountName=软件订单台账|contractCode=${订单编号}|company=${分公司}
let _url = ''; let _url = '';
let _params = {}; let _params = {};
_configs.forEach(item => { _configs.forEach((item) => {
if (item.includes('type=')) _type = item.replace('type=', ''); if (item.includes('type=')) _type = item.replace('type=', '');
if (item.includes('url=')) { if (item.includes('url=')) {
let _tempUrl = item.replace('url=', ''); let _tempUrl = item.replace('url=', '');
let _urlArray = _tempUrl.split('?'); let _urlArray = _tempUrl.split('?');
if (_urlArray[1]) { if (_urlArray[1]) {
_urlArray[1].split('&').forEach(param => { _urlArray[1].split('&').forEach((param) => {
let _paramArr = param.split('='); let _paramArr = param.split('=');
if (_paramArr[1] && _paramArr[1].includes('${') && _paramArr[1].includes('}')) { if (_paramArr[1] && _paramArr[1].includes('${') && _paramArr[1].includes('}')) {
let _key = _paramArr[1].replace(/\$\{|\}/g, ''); let _key = _paramArr[1].replace(/\$\{|\}/g, '');
...@@ -62,7 +60,7 @@ const clickModal = (config, showModal, setExtra) => { ...@@ -62,7 +60,7 @@ const clickModal = (config, showModal, setExtra) => {
let _fn = _splitArr[0] || 'default'; let _fn = _splitArr[0] || 'default';
_splitArr.splice(0, 1); _splitArr.splice(0, 1);
let _data = {}; let _data = {};
_splitArr.forEach(item => { _splitArr.forEach((item) => {
let _item = item.split('='); let _item = item.split('=');
_data[_item[0]] = _item[1]; _data[_item[0]] = _item[1];
}); });
...@@ -80,7 +78,8 @@ export const handleNumber = (config, number) => { ...@@ -80,7 +78,8 @@ export const handleNumber = (config, number) => {
let _color = ''; let _color = '';
if (number) number = Number(number); // 当设置精度后,会被转成字符串 if (number) number = Number(number); // 当设置精度后,会被转成字符串
if (config.numericalConfigs && config.numericalConfigs.length) { if (config.numericalConfigs && config.numericalConfigs.length) {
config.numericalConfigs.forEach(item => { // 接口对于数值类型的返回为null config.numericalConfigs.forEach((item) => {
// 接口对于数值类型的返回为null
if (!_color) { if (!_color) {
let _max = item.maxValue || ''; let _max = item.maxValue || '';
let _min = item.minValue || ''; let _min = item.minValue || '';
...@@ -96,39 +95,58 @@ export const handleNumber = (config, number) => { ...@@ -96,39 +95,58 @@ export const handleNumber = (config, number) => {
} else if (config.color) { } else if (config.color) {
_color = config.color; _color = config.color;
} }
return number ? <span> return number ? (
<span className={style.prefixOrSuffix} style={{ <span>
color: _color, <span
}}>{config.prefix || ''}</span> className={style.prefixOrSuffix}
<span style={{ style={{
color: _color, color: _color,
margin: '0 5px', }}
}}>{hasMoney(config?.configItems) ? (number ? Number(number)?.toLocaleString() : number) : number}</span> >
<span className={style.prefixOrSuffix} style={{ color: _color }}>{config.suffix || ''}</span> {config.prefix || ''}
</span> : '-'; </span>
<span
style={{
color: _color,
margin: '0 5px',
}}
>
{hasMoney(config?.configItems)
? number
? Number(number)?.toLocaleString()
: number
: number}
</span>
<span className={style.prefixOrSuffix} style={{ color: _color }}>
{config.suffix || ''}
</span>
</span>
) : (
'-'
);
}; };
/** /** @params: 标签形态的configRule,[{标签值:'字符串',颜色: '#AAAAAA'}]; */
* @Params: 标签形态的configRule,[{标签值:'字符串',颜色: '#AAAAAA'}];
* */
export const handleTag = (config, text) => { export const handleTag = (config, text) => {
let _color = ''; let _color = '';
let _map = {}; let _map = {};
// 标签需要设置分隔符 2022年7月13日 ChenLong // 标签需要设置分隔符 2022年7月13日 ChenLong
let _configItems = config.configItems.split('|'); let _configItems = config.configItems.split('|');
let _configMap = {}; let _configMap = {};
_configItems.forEach(item => { _configItems.forEach((item) => {
let _arr = item.split('='); let _arr = item.split('=');
_configMap[_arr[0]] = _arr[1]; _configMap[_arr[0]] = _arr[1];
}); });
// 处理label的颜色 // 处理label的颜色
if (config.labelConfigs && config.labelConfigs.length) { if (config.labelConfigs && config.labelConfigs.length) {
config.labelConfigs.forEach(item => { config.labelConfigs.forEach((item) => {
_map[item.labelValue] = item.color; _map[item.labelValue] = item.color;
}); });
} }
_color = config.color || 'rgba(0,0,0,.85)'; _color = config.color || 'rgba(0,0,0,.85)';
// String(text)为了解决可能存在数值类型的数据需要设置成标签的需求 // String(text)为了解决可能存在数值类型的数据需要设置成标签的需求
return String(text).split(_configMap['分隔符']).map(item => <Tag color={_map[item]}>{item}</Tag>); return String(text)
.split(_configMap['分隔符'])
.map((item) => <Tag color={_map[item]}>{item}</Tag>);
/* return String(text).split(_configMap['分隔符']).map(item => <Tag style={{ /* return String(text).split(_configMap['分隔符']).map(item => <Tag style={{
background: _map[item] || _color, background: _map[item] || _color,
border: `1px solid ${_map[item]}`, border: `1px solid ${_map[item]}`,
...@@ -140,17 +158,39 @@ export const handleText = (config, text) => { ...@@ -140,17 +158,39 @@ export const handleText = (config, text) => {
return <span style={{ color: config.color || 'rgba(0,0,0,.85)' }}>{text}</span>; return <span style={{ color: config.color || 'rgba(0,0,0,.85)' }}>{text}</span>;
}; };
export const handleLink = (config, text) => { export const handleLink = (config, text) => {
return <span className={style.link} style={{ return (
color: config.color || 'rgba(0,0,0,.85)', <span
}} onClick={() => clickLink(config)}>{text}</span>; className={style.link}
style={{
color: config.color || 'rgba(0,0,0,.85)',
}}
onClick={() => clickLink(config)}
>
{text}
</span>
);
}; };
export const handleWidget = (config, text, record, showComponents, setDetailsConfig) => { export const handleWidget = (config, text, record, showComponents, setDetailsConfig) => {
return <span style={{ color: config.color }} className={style.link} return (
onClick={() => clickWidget(config, text, record, showComponents, setDetailsConfig)}>{text}</span>; <span
style={{ color: config.color }}
className={style.link}
onClick={() => clickWidget(config, text, record, showComponents, setDetailsConfig)}
>
{text}
</span>
);
}; };
export const handleModal = (config, text, showModal, setExtra) => { export const handleModal = (config, text, showModal, setExtra) => {
return <span className={style.link} style={{ color: config.color || 'rgba(0,0,0,.85)' }} return (
onClick={() => clickModal(config, showModal, setExtra)}>{text}</span>; <span
className={style.link}
style={{ color: config.color || 'rgba(0,0,0,.85)' }}
onClick={() => clickModal(config, showModal, setExtra)}
>
{text}
</span>
);
}; };
// 日期 // 日期
export const handleDateString = (config, text) => { export const handleDateString = (config, text) => {
...@@ -166,5 +206,5 @@ export const handlePageSize = (numStr) => { ...@@ -166,5 +206,5 @@ export const handlePageSize = (numStr) => {
}; };
// 处理默认排序 // 处理默认排序
export const handleSortFields = (sortFields) => { export const handleSortFields = (sortFields) => {
return sortFields && sortFields.split(',') return sortFields && sortFields.split(',');
} };
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment