Commit 7e486a8a authored by 陈龙's avatar 陈龙

fix: 修复文件引用错误

parent ab5be8e3
export const RESTART_ON_REMOUNT = '@@saga-injector/restart-on-remount';
export const DAEMON = '@@saga-injector/daemon';
export const ONCE_TILL_UNMOUNT = '@@saga-injector/once-till-unmount';
export const FILTER_FOLER_REG =
/(configs|configuration|framework|iframe|Product|product|productex|project|qrcode|threedimensional|video|widgetconfigs)/;
export const FILTER_FOLER_WEB5 = /(pages)/;
export const SERVICE_APP_GET_UI_META = 'app.getUIMeta';
export const SERVICE_APP_LOGIN_MODE = {
password: 'password',
dingding: 'dingding',
weixin: 'weixin',
phone: 'phone',
};
export const LOGIN_DISPLAY = {
Account: 'Account',
WeChart: 'WeChart',
Mobile: 'Mobile',
};
export const LOGIN_WAY = {
Account: 'pdw',
WeChart: 'iotWechat',
Mobile: 'iotPhone',
};
export const WX_REDIRECT_URI = 'https://panda-water.com/civbase/user/login';
export const SERVICE_INTERFACE_SUCCESS_CODE = 0;
export const SERVICE_INTERFACE_PARAMS_EXCEPTION_CODE = -1; // 服务参数异常
export const SERVICE_INTERFACE_HANDLE_EXCEPTION_CODE = -2; // 服务处理异常
export const SERVICE_APP_CLOSE_ALL_TABS = 'app.close.tabs';
export const REQUEST_HTTP = 'http';
export const REQUEST_POP = 'pop';
export const REQUEST_METHOD_GET = 'get';
export const REQUEST_METHOD_POST = 'post';
export const REQUEST_METHOD_PUT = 'put';
export const REQUEST_METHOD_DELETE = 'delete';
export const RESPONSE_TYPE = 'blob';
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
** 菜单参数列表:*变量名*(变量说明,数据类型,是否必填,取值范围) ** 菜单参数列表:*变量名*(变量说明,数据类型,是否必填,取值范围)
**/ **/
import { request } from '@wisdom-utils/utils'; import { request } from '@wisdom-utils/utils';
import * as constants from '../../constants'; import * as constants from '../constants';
const BASEURL = '/PandaAssets/Assets/ReportManager'; const BASEURL = '/PandaAssets/Assets/ReportManager';
export const API = { export const API = {
...@@ -97,12 +97,13 @@ const reportService = { ...@@ -97,12 +97,13 @@ const reportService = {
type: constants.REQUEST_METHOD_POST, type: constants.REQUEST_METHOD_POST,
}, },
}; };
export const submitReportData = (params, data) => request({ export const submitReportData = (params, data) =>
url: API.UPDATE_REPORT_DATA, request({
method: 'post', url: API.UPDATE_REPORT_DATA,
params, method: 'post',
data, params,
}); data,
});
export const exportAccountData = (options, params, data) => export const exportAccountData = (options, params, data) =>
request({ request({
url: API.EXPORT_ACCOUNT_DATA, url: API.EXPORT_ACCOUNT_DATA,
...@@ -111,9 +112,10 @@ export const exportAccountData = (options, params, data) => ...@@ -111,9 +112,10 @@ export const exportAccountData = (options, params, data) =>
params, params,
data, data,
}); });
export const addReportDetailInfoIndex = (data) => request({ export const addReportDetailInfoIndex = (data) =>
url: API.ADD_REPORT_DETAIL_INFO_INDEX, request({
method: 'post', url: API.ADD_REPORT_DETAIL_INFO_INDEX,
data, method: 'post',
}); data,
});
export default reportService; export default reportService;
/** /**
* 时间组选择:支持 全部,日,月,年,自定义 类型 * 时间组选择:支持 全部,日,月,年,自定义 类型 props:
* props: * onChange: ({dateFrom, dateTo}, model) => {}。切换时间类型或时间会触发onChange,并传递选择的时间范围和类型。
* onChange: ({dateFrom, dateTo}, model) => {}。切换时间类型或时间会触发onChange,并传递选择的时间范围和类型。 * 注:dateFrom和dateTo都是格式化后的字符串
* 注:dateFrom和dateTo都是格式化后的字符串 * format: 格式化字符串格式,默认"YYYY-MM-DD HH:mm:ss",参看moment格式化支持的
* format: 格式化字符串格式,默认"YYYY-MM-DD HH:mm:ss",参看moment格式化支持的
*/ */
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { Radio, Space, DatePicker } from 'antd'; import { Radio, Space, DatePicker } from 'antd';
import moment from 'moment'; import moment from 'moment';
const dateForModel = (model, date = moment()) => { const dateForModel = (model, date = moment()) => {
if (!date) { if (!date) {
result = { dateFrom: null, dateTo: null }; result = { dateFrom: null, dateTo: null };
return result;
}
let result = { dateFrom: null, dateTo: null };
switch (model) {
case 'day':
result = { dateFrom: date.clone().startOf('day'), dateTo: date.clone().endOf('day') };
break;
case 'week':
result = { dateFrom: date.clone().startOf('week'), dateTo: date.clone().endOf('week') };
break;
case 'month':
result = { dateFrom: date.clone().startOf('month'), dateTo: date.clone().endOf('month') };
break;
case 'quarter':
result = { dateFrom: date.clone().startOf('quarter'), dateTo: date.clone().endOf('quarter') };
break;
case 'year':
result = { dateFrom: date.clone().startOf('year'), dateTo: date.clone().endOf('year') };
break;
case 'all':
default:
result = { dateFrom: null, dateTo: null };
break;
}
return result; return result;
}
let result = { dateFrom: null, dateTo: null };
switch (model) {
case 'day':
result = { dateFrom: date.clone().startOf('day'), dateTo: date.clone().endOf('day') };
break;
case 'week':
result = { dateFrom: date.clone().startOf('week'), dateTo: date.clone().endOf('week') };
break;
case 'month':
result = { dateFrom: date.clone().startOf('month'), dateTo: date.clone().endOf('month') };
break;
case 'quarter':
result = { dateFrom: date.clone().startOf('quarter'), dateTo: date.clone().endOf('quarter') };
break;
case 'year':
result = { dateFrom: date.clone().startOf('year'), dateTo: date.clone().endOf('year') };
break;
case 'all':
default:
result = { dateFrom: null, dateTo: null };
break;
}
return result;
}; };
const textForModel = model => { const textForModel = (model) => {
switch (model) { switch (model) {
case 'day': case 'day':
return '日'; return '日';
case 'week': case 'week':
return '周'; return '周';
case 'month': case 'month':
return '月'; return '月';
case 'quarter': case 'quarter':
return '季度'; return '季度';
case 'year': case 'year':
return '年'; return '年';
case 'all': case 'all':
return '全部'; return '全部';
case 'custom': case 'custom':
return '自定义'; return '自定义';
default: default:
return model; return model;
} }
}; };
const useDataGroup = (defaultValue = { dateFrom: null, dateTo: null }, defaultModel = 'all') => { const useDataGroup = (defaultValue = { dateFrom: null, dateTo: null }, defaultModel = 'all') => {
const [model, setModel] = useState(defaultModel); const [model, setModel] = useState(defaultModel);
const [value, setValue] = useState(defaultValue); const [value, setValue] = useState(defaultValue);
const updateValeu = (_value, _model) => { const updateValeu = (_value, _model) => {
setModel(_model); setModel(_model);
setValue(_value); setValue(_value);
}; };
return [value, model, updateValeu]; return [value, model, updateValeu];
}; };
const defaultFormat = 'YYYY-MM-DD HH:mm:ss'; const defaultFormat = 'YYYY-MM-DD HH:mm:ss';
const defaultShowModels = ['all', 'week', 'month', 'quarter', 'year', 'custom']; const defaultShowModels = ['all', 'week', 'month', 'quarter', 'year', 'custom'];
const DatePickerGroup = ({ const DatePickerGroup = ({
onChange, onChange,
format = defaultFormat, format = defaultFormat,
showModels = defaultShowModels, showModels = defaultShowModels,
defaultModel = 'all', defaultModel = 'all',
defaultDate, defaultDate,
value, value,
dateModel, dateModel,
}) => { }) => {
const [model, setModel] = useState(defaultModel); const [model, setModel] = useState(defaultModel);
const [dateValue, setDateValue] = useState(() => dateForModel(defaultModel, defaultDate)); const [dateValue, setDateValue] = useState(() => dateForModel(defaultModel, defaultDate));
useEffect(() => { useEffect(() => {
if (value || dateModel) { if (value || dateModel) {
setModel(dateModel); setModel(dateModel);
setDateValue(value); setDateValue(value);
} }
}, [value, dateModel]); }, [value, dateModel]);
// 切换类型 // 切换类型
const changeModel = e => { const changeModel = (e) => {
const _model = e.target.value; const _model = e.target.value;
const _dateValue = dateForModel(_model); const _dateValue = dateForModel(_model);
if (!value && !dateModel) { if (!value && !dateModel) {
setModel(_model); setModel(_model);
setDateValue(_dateValue); setDateValue(_dateValue);
if (_model === 'custom') return; if (_model === 'custom') return;
} }
const _dateFrom = _dateValue && _dateValue.dateFrom ? _dateValue.dateFrom.format(format) : ''; const _dateFrom = _dateValue && _dateValue.dateFrom ? _dateValue.dateFrom.format(format) : '';
const _dateTo = _dateValue && _dateValue.dateTo ? _dateValue.dateTo.format(format) : ''; const _dateTo = _dateValue && _dateValue.dateTo ? _dateValue.dateTo.format(format) : '';
onChange && onChange &&
onChange( onChange(
{ {
dateFrom: _dateFrom, dateFrom: _dateFrom,
dateTo: _dateTo, dateTo: _dateTo,
}, },
_model, _model,
); );
}; };
// 切换时间 // 切换时间
const changeDate = (date, dateString) => { const changeDate = (date, dateString) => {
const _dateValue = dateForModel(model, date); const _dateValue = dateForModel(model, date);
const _dateFrom = _dateValue && _dateValue.dateFrom ? _dateValue.dateFrom.format(format) : ''; const _dateFrom = _dateValue && _dateValue.dateFrom ? _dateValue.dateFrom.format(format) : '';
const _dateTo = _dateValue && _dateValue.dateTo ? _dateValue.dateTo.format(format) : ''; const _dateTo = _dateValue && _dateValue.dateTo ? _dateValue.dateTo.format(format) : '';
if (!value && !dateModel) { if (!value && !dateModel) {
setDateValue(_dateValue); setDateValue(_dateValue);
} }
onChange && onChange &&
onChange( onChange(
{ {
dateFrom: _dateFrom, dateFrom: _dateFrom,
dateTo: _dateTo, dateTo: _dateTo,
}, },
model, model,
); );
}; };
// 切换范围时间 // 切换范围时间
const changeRangeDate = (dates, dateStrings) => { const changeRangeDate = (dates, dateStrings) => {
const _dateValue = { dateFrom: dates?.[0], dateTo: dates?.[1] }; const _dateValue = { dateFrom: dates?.[0], dateTo: dates?.[1] };
const _dateFrom = _dateValue && _dateValue.dateFrom ? _dateValue.dateFrom.format(format) : ''; const _dateFrom = _dateValue && _dateValue.dateFrom ? _dateValue.dateFrom.format(format) : '';
const _dateTo = _dateValue && _dateValue.dateTo ? _dateValue.dateTo.format(format) : ''; const _dateTo = _dateValue && _dateValue.dateTo ? _dateValue.dateTo.format(format) : '';
if (!value && !dateModel) { if (!value && !dateModel) {
setDateValue(_dateValue); setDateValue(_dateValue);
} }
onChange && onChange &&
onChange( onChange(
{ {
dateFrom: _dateFrom, dateFrom: _dateFrom,
dateTo: _dateTo, dateTo: _dateTo,
}, },
model, model,
); );
}; };
// 渲染时间选择器 // 渲染时间选择器
const renderDatePicker = () => { const renderDatePicker = () => {
let _result = null; let _result = null;
switch (model) { switch (model) {
case 'day': case 'day':
_result = <DatePicker onChange={changeDate} value={dateValue.dateFrom} />; _result = <DatePicker onChange={changeDate} value={dateValue.dateFrom} />;
break; break;
case 'week': case 'week':
_result = <DatePicker picker="week" onChange={changeDate} value={dateValue.dateFrom} />; _result = <DatePicker picker="week" onChange={changeDate} value={dateValue.dateFrom} />;
break; break;
case 'month': case 'month':
_result = <DatePicker picker="month" onChange={changeDate} value={dateValue.dateFrom} />; _result = <DatePicker picker="month" onChange={changeDate} value={dateValue.dateFrom} />;
break; break;
case 'quarter': case 'quarter':
_result = <DatePicker picker="quarter" onChange={changeDate} value={dateValue.dateFrom} />; _result = <DatePicker picker="quarter" onChange={changeDate} value={dateValue.dateFrom} />;
break; break;
case 'year': case 'year':
_result = <DatePicker picker="year" onChange={changeDate} value={dateValue.dateFrom} />; _result = <DatePicker picker="year" onChange={changeDate} value={dateValue.dateFrom} />;
break; break;
case 'custom': case 'custom':
_result = ( _result = (
<DatePicker.RangePicker onChange={changeRangeDate} value={[dateValue.dateFrom, dateValue.dateTo]} /> <DatePicker.RangePicker
); onChange={changeRangeDate}
break; value={[dateValue.dateFrom, dateValue.dateTo]}
case 'all': />
default: );
_result = null; break;
break; case 'all':
} default:
return _result; _result = null;
}; break;
}
return _result;
};
return ( return (
<Space size={8}> <Space size={8}>
<Radio.Group value={model} onChange={changeModel} style={{ whiteSpace: 'nowrap' }}> <Radio.Group value={model} onChange={changeModel} style={{ whiteSpace: 'nowrap' }}>
{showModels.map(item => ( {showModels.map((item) => (
<Radio.Button value={item} key={item}> <Radio.Button value={item} key={item}>
{textForModel(item)} {textForModel(item)}
</Radio.Button> </Radio.Button>
))} ))}
</Radio.Group> </Radio.Group>
{renderDatePicker()} {renderDatePicker()}
</Space> </Space>
); );
}; };
export { useDataGroup }; export { useDataGroup };
export default DatePickerGroup; export default DatePickerGroup;
...@@ -7,6 +7,6 @@ const extraComponents = { ...@@ -7,6 +7,6 @@ const extraComponents = {
returnImage: (data) => { returnImage: (data) => {
return <img width={200} height={200} src={pic} alt={data.alt} />; return <img width={200} height={200} src={pic} alt={data.alt} />;
}, },
default: () => <span>若需要使用弹窗功能,请开发或配置功能函数</span> default: () => <span>若需要使用弹窗功能,请开发或配置功能函数</span>,
}; };
export default extraComponents; export default extraComponents;
/** /**
** 轻量化报表通用配置页面 * * 轻量化报表通用配置页面 * create by ChenLong on 2022/6/22 *
** create by ChenLong on 2022/6/22 * 功能路径:src\pages\product\ReportsManage\ReportsManage.js * 菜单参数列表:*变量名*(变量说明,数据类型,是否必填,取值范围)
** 功能路径:src\pages\product\ReportsManage\ReportsManage.js
** 菜单参数列表:*变量名*(变量说明,数据类型,是否必填,取值范围)
* @Changelog:
* editComponentVisible && detailsComponentVisible 共同作用组件的显示
* *
**/ * @changelog:
* editComponentVisible && detailsComponentVisible 共同作用组件的显示
*/
/** /**
* @Description: 功能描述:参考台账概念,重新定义 * @description: 功能描述:参考台账概念,重新定义
* @Tips: 1. 如果需要对字段进行处理,增加功能之类的。需要提前确定返回值的类型. * @tips: 1. 如果需要对字段进行处理,增加功能之类的。需要提前确定返回值的类型.
* 2. 如果要用customerState来控制页面按钮等,需要按照给定的权限值进行配置 * 2. 如果要用customerState来控制页面按钮等,需要按照给定的权限值进行配置
* @Params: <ReportManage params={{reportName,pageSize,filterFields,filterValues,state,customerState}}> * @params: <ReportManage
* reportName: 报表名称; * params={{reportName,pageSize,filterFields,filterValues,state,customerState}}>
*
* reportName: 报表名称;
* pageSize: 按需配置,默认加载100; * pageSize: 按需配置,默认加载100;
* filterFields: 需要默认加载的过滤条件的field,英文逗号分割,与filterValues一一对应; * filterFields:
* filterValues: 需要默认加载的过滤条件的value,英文逗号分割,与filterFields一一对应; * 需要默认加载的过滤条件的field,英文逗号分割,与filterValues一一对应;
* filterValues:
* 需要默认加载的过滤条件的value,英文逗号分割,与filterFields一一对应;
* state: delete|edit|scan 各种权限; * state: delete|edit|scan 各种权限;
* customerState: ['filters','sortBtn','exportBtn','editBtn','deleteBtn','pagination']; *
* sortFields: '排序字段1,排序字段2,排序字段3' * customerState: ['filters','sortBtn','exportBtn','editBtn','deleteBtn','pagination'];
* @Config: *
* sortFields: '排序字段1,排序字段2,排序字段3'
* @config:
* 【数值】 [prefix]_d%|0.00|_d%[suffix]|金额 = 前缀|精度|后缀|金额类的数据(千分位),可分别设置。 * 【数值】 [prefix]_d%|0.00|_d%[suffix]|金额 = 前缀|精度|后缀|金额类的数据(千分位),可分别设置。
* 【标签】 split=, 分隔符。 * 【标签】 split=, 分隔符。
* 【功能】 功能配置框内,配置需要跳转功能所需参数,type、url是必须功能,需要type判断类型,需要通过url去解析加载组件。 *
* @Type: * 【功能】 功能配置框内,配置需要跳转功能所需参数,type、url是必须功能,需要type判断类型,需要通过url去解析加载组件。
* @type:
* 【文本】普通文本 * 【文本】普通文本
* 【数值】数值类型的文本 * 【数值】数值类型的文本
* 【标签】文本渲染成标签,具有不同颜色; * 【标签】文本渲染成标签,具有不同颜色;
* 【功能】“功能”会在当前页内去展示,会卸载掉列表页,加载功能组件。配置 type + url + 自定义字段 的配置项,自行解析加载即可; * 【功能】“功能”会在当前页内去展示,会卸载掉列表页,加载功能组件。配置 type +
* url + 自定义字段 的配置项,自行解析加载即可;
* -------------------- 待需求提出后开发 ----------------- * -------------------- 待需求提出后开发 -----------------
* 【链接】内链外链,点击可跳转;配置规则:配置链接即可; *
* 【链接】内链外链,点击可跳转;配置规则:配置链接即可;
* 【弹窗】modal弹窗弹出,弹窗内的具体业务自行配置;配置规则:[function_name];[...params]; * 【弹窗】modal弹窗弹出,弹窗内的具体业务自行配置;配置规则:[function_name];[...params];
* ------------------------------------------------------ *
* @Table: * ------------------------------------------------------
* @table:
* 表头:表头需要支持多级表头、合并; * 表头:表头需要支持多级表头、合并;
* 列:列支持设置筛选; * 列:列支持设置筛选;
* 固定行、固定列:可根据配置生成固定行、列; * 固定行、固定列:可根据配置生成固定行、列;
* @Control: * @control:
* 固定筛选:拥有固定筛选框,根据配置显示可搜索字段; * 固定筛选:拥有固定筛选框,根据配置显示可搜索字段;
* 可配置筛选框:根据字段配置,将字段设置成筛选条件,枚举出该字段所有值,提供用户进行选择,然后进行筛选;筛选框具体形态可根据配置字段来渲染; *
* 可配置筛选框:根据字段配置,将字段设置成筛选条件,枚举出该字段所有值,提供用户进行选择,然后进行筛选;筛选框具体形态可根据配置字段来渲染;
* 导出功能:各类导出功能按钮; * 导出功能:各类导出功能按钮;
* 时间筛选框:单表唯一;需要变更,支持多时间参数的筛选 *
* @State: 参考台账权限 * 时间筛选框:单表唯一;需要变更,支持多时间参数的筛选
* delete 全部权限 * @state: 参考台账权限 delete 全部权限
* edit 除删除外的权限 * edit 除删除外的权限
* scan 查看权限 * scan 查看权限
* */ */
import React, { useState, useEffect, useRef } from 'react'; import React, { useState, useEffect, useRef } from 'react';
import { Row, Button, Tag, message, Form, Space, Modal, Select, Table, Dropdown, Menu, Spin } from 'antd';
import { import {
SortAscendingOutlined, MinusCircleOutlined, ExportOutlined, FormOutlined, Row,
Button,
Tag,
message,
Form,
Space,
Modal,
Select,
Table,
Dropdown,
Menu,
Spin,
} from 'antd';
import {
SortAscendingOutlined,
MinusCircleOutlined,
ExportOutlined,
FormOutlined,
} from '@ant-design/icons'; } from '@ant-design/icons';
import BasicTable from '@wisdom-components/basictable'; import BasicTable from '@wisdom-components/basictable';
import ReturnControlComponent from './components/Control'; import ReturnControlComponent from './components/Control';
import { reportService } from './api/index'; import { reportService } from './api/index';
import style from './index.less'; import style from './index.less';
import { exportAccountData } from './api/service/report'; import { exportAccountData } from './api/service/report';
import extraComponents from './extra/extraComponents';
import DatePickerGroup from './components/DatePickerGroup'; import DatePickerGroup from './components/DatePickerGroup';
import moment from 'moment'; import moment from 'moment';
import DetailsComponent from './extra/detailsComponent'; import DetailsComponent from './extra/detailsComponent';
...@@ -68,7 +92,9 @@ import { ...@@ -68,7 +92,9 @@ import {
handleWidget, handleWidget,
handleModal, handleModal,
handleDateString, handleDateString,
handleDateTimeString, handlePageSize, handleSortFields, handleDateTimeString,
handlePageSize,
handleSortFields,
} from './utils/handlers'; } from './utils/handlers';
import { hasMoney, isArray, isNumber, isString, returnHandledNumber } from './utils/utils'; import { hasMoney, isArray, isNumber, isString, returnHandledNumber } from './utils/utils';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
...@@ -99,19 +125,19 @@ const PERMISSION = { ...@@ -99,19 +125,19 @@ const PERMISSION = {
// 操作列 // 操作列
'editBtn', 'editBtn',
], ],
scan: [ scan: ['filters', 'pagination'],
'filters',
'pagination',
],
}; };
const BasicReport = (props) => { const BasicReport = (props) => {
const { reportName, pageSize, filterFields, filterValues, state, customerState, sortFields } = props.params; const { reportName, pageSize, filterFields, filterValues, state, customerState, sortFields } =
const permission = customerState && isArray(customerState) ? customerState : PERMISSION[(state || 'delete')]; props.params;
const permission =
customerState && isArray(customerState) ? customerState : PERMISSION[state || 'delete'];
const tableWrapperRef = useRef(); const tableWrapperRef = useRef();
const controlRef = useRef(); const controlRef = useRef();
if (!reportName) return <div className={style.lackParams}> if (!reportName)
未配置reportName,请完善配置并重新登陆后查看页面! return (
</div>; <div className={style.lackParams}>未配置reportName,请完善配置并重新登陆后查看页面!</div>
);
const [tableStruct, setTableStruct] = useState([]); // 临时使用,看后续是否需要保留 const [tableStruct, setTableStruct] = useState([]); // 临时使用,看后续是否需要保留
const [columns, setColumns] = useState([]); // 表头设置 const [columns, setColumns] = useState([]); // 表头设置
const [tableData, setTableData] = useState([]); // 表数据 const [tableData, setTableData] = useState([]); // 表数据
...@@ -119,7 +145,9 @@ const BasicReport = (props) => { ...@@ -119,7 +145,9 @@ const BasicReport = (props) => {
current: 1, current: 1,
total: 0, total: 0,
pageSize: handlePageSize(pageSize) || 100, pageSize: handlePageSize(pageSize) || 100,
pageSizeOptions: [...new Set([20, 50, 100].concat(handlePageSize(pageSize)))].filter(item => Number(item)).sort((a, b) => Number(a) - Number(b)), pageSizeOptions: [...new Set([20, 50, 100].concat(handlePageSize(pageSize)))]
.filter((item) => Number(item))
.sort((a, b) => Number(a) - Number(b)),
showQuickJumper: true, showQuickJumper: true,
showSizeChanger: true, showSizeChanger: true,
onShowSizeChange: (current, size) => { onShowSizeChange: (current, size) => {
...@@ -143,11 +171,13 @@ const BasicReport = (props) => { ...@@ -143,11 +171,13 @@ const BasicReport = (props) => {
const [filterObject, setFilterObject] = useState({}); // 存控制条中,选了筛选条件的值 const [filterObject, setFilterObject] = useState({}); // 存控制条中,选了筛选条件的值
const [modalVisible, setModalVisible] = useState(false); const [modalVisible, setModalVisible] = useState(false);
const [allSortFields, setAllSortFields] = useState([]); // 设置所有列表 const [allSortFields, setAllSortFields] = useState([]); // 设置所有列表
const [selectedSortFields, setSelectedSortFields] = useState([{ const [selectedSortFields, setSelectedSortFields] = useState([
label: '主要排序', {
value: '', label: '主要排序',
sort: 'asc', value: '',
}]); sort: 'asc',
},
]);
const [summaryArray, setSummaryArray] = useState([]); // 总结栏,包括小计、总计 const [summaryArray, setSummaryArray] = useState([]); // 总结栏,包括小计、总计
const [tableY, setTableY] = useState(500); const [tableY, setTableY] = useState(500);
const [tableX, setTableX] = useState(1820); const [tableX, setTableX] = useState(1820);
...@@ -160,16 +190,8 @@ const BasicReport = (props) => { ...@@ -160,16 +190,8 @@ const BasicReport = (props) => {
const [tableLoading, setTableLoading] = useState(false); const [tableLoading, setTableLoading] = useState(false);
const [mergeObject, setMergeObject] = useState({}); const [mergeObject, setMergeObject] = useState({});
// const // const
const [timeFrom, setTimeFrom] = useState( const [timeFrom, setTimeFrom] = useState(moment().startOf(initDateModel).format(dateFormat));
moment() const [timeTo, setTimeTo] = useState(moment().endOf(initDateModel).format(dateFormat));
.startOf(initDateModel)
.format(dateFormat),
);
const [timeTo, setTimeTo] = useState(
moment()
.endOf(initDateModel)
.format(dateFormat),
);
const [extra, setExtra] = useState(<></>); const [extra, setExtra] = useState(<></>);
const [sortModalVisible, setSortModalVisible] = useState(false); const [sortModalVisible, setSortModalVisible] = useState(false);
const [currentReportId, setCurrentReportId] = useState(null); const [currentReportId, setCurrentReportId] = useState(null);
...@@ -191,9 +213,9 @@ const BasicReport = (props) => { ...@@ -191,9 +213,9 @@ const BasicReport = (props) => {
{ {
label: ( label: (
<Button <Button
size='middle' size="middle"
loading={exportLoading} loading={exportLoading}
type='text' type="text"
onClick={() => exportModule('pdf', 'pdf')} onClick={() => exportModule('pdf', 'pdf')}
icon={<ExportOutlined />} icon={<ExportOutlined />}
> >
...@@ -205,9 +227,9 @@ const BasicReport = (props) => { ...@@ -205,9 +227,9 @@ const BasicReport = (props) => {
{ {
label: ( label: (
<Button <Button
size='middle' size="middle"
loading={exportLoading} loading={exportLoading}
type='text' type="text"
onClick={() => exportModule('excel', 'xls')} onClick={() => exportModule('excel', 'xls')}
icon={<ExportOutlined />} icon={<ExportOutlined />}
> >
...@@ -221,20 +243,24 @@ const BasicReport = (props) => { ...@@ -221,20 +243,24 @@ const BasicReport = (props) => {
}; };
const exportModule = (type, extension) => { const exportModule = (type, extension) => {
setExportLoading(true); setExportLoading(true);
exportAccountData({ responseType: 'blob' }, { exportType: type }, { exportAccountData(
reportName, { responseType: 'blob' },
pageIndex: 0, { exportType: type },
pageSize: 0, {
sortFields: '', reportName,
content: '', pageIndex: 0,
filters: [ pageSize: 0,
{ sortFields: '',
fieldAlias: '', content: '',
fieldValue: '', filters: [
}, {
], fieldAlias: '',
}) fieldValue: '',
.then(res => { },
],
},
)
.then((res) => {
if (res && res.code === -1) return message.error(res.msg); if (res && res.code === -1) return message.error(res.msg);
const url = window.URL.createObjectURL( const url = window.URL.createObjectURL(
new Blob([res], { type: 'application/octet-stream;charset=UTF-8' }), new Blob([res], { type: 'application/octet-stream;charset=UTF-8' }),
...@@ -242,12 +268,13 @@ const BasicReport = (props) => { ...@@ -242,12 +268,13 @@ const BasicReport = (props) => {
const a = document.createElement('a'); const a = document.createElement('a');
a.href = url; a.href = url;
a.target = '_blank'; a.target = '_blank';
a.download = `${reportName}${moment().format('YYYY-MM-DD-HH-mm-ss').replaceAll('-', '')}.` + extension; a.download =
`${reportName}${moment().format('YYYY-MM-DD-HH-mm-ss').replaceAll('-', '')}.` + extension;
a.click(); a.click();
a.remove(); a.remove();
setExportLoading(false); setExportLoading(false);
}) })
.catch(err => { .catch((err) => {
setExportLoading(false); setExportLoading(false);
}); });
}; };
...@@ -272,21 +299,25 @@ const BasicReport = (props) => { ...@@ -272,21 +299,25 @@ const BasicReport = (props) => {
// 搜索框是否有值 // 搜索框是否有值
if (searchContent) _data.content = searchContent; if (searchContent) _data.content = searchContent;
// filterObject是存起来的控制栏的过滤条件 // filterObject是存起来的控制栏的过滤条件
let _filters = Object.keys(filterObject).filter(key => { let _filters = Object.keys(filterObject)
let _value = filterObject[key]; .filter((key) => {
return (isString(_value) && _value) || (isArray(_value) && _value.length); let _value = filterObject[key];
}).map(key => { return (isString(_value) && _value) || (isArray(_value) && _value.length);
let _value = filterObject[key]; })
if (isString(_value) && _value) return { .map((key) => {
fieldAlias: key, let _value = filterObject[key];
fieldValue: _value, if (isString(_value) && _value)
}; return {
if (isArray(_value) && _value.length) return { fieldAlias: key,
fieldAlias: key, fieldValue: _value,
fieldValue: _value.join(','), };
}; if (isArray(_value) && _value.length)
return false; return {
}); fieldAlias: key,
fieldValue: _value.join(','),
};
return false;
});
// 加上时间过滤参数 // 加上时间过滤参数
if (dateModel !== 'all' && hasDatePicker && timeFrom && timeTo) { if (dateModel !== 'all' && hasDatePicker && timeFrom && timeTo) {
_filters.push({ _filters.push({
...@@ -330,20 +361,16 @@ const BasicReport = (props) => { ...@@ -330,20 +361,16 @@ const BasicReport = (props) => {
}); });
setSelectedSortFields(_sortStringArray); setSelectedSortFields(_sortStringArray);
}; };
/** /** @description: 根据是否向下合并处理数据,返回合并的key的数组 */
* @Description: 根据是否向下合并处理数据,返回合并的key的数组
* */
const returnMergeArray = (config) => { const returnMergeArray = (config) => {
return config.filter(item => item.isMerge).map(item => item.fieldAlias); return config.filter((item) => item.isMerge).map((item) => item.fieldAlias);
}; };
/** /** @description: 根据配置和数据,计算出该合并的字段和每一行是否合并 */
* @Description: 根据配置和数据,计算出该合并的字段和每一行是否合并
* */
const handleDataToGetRowSpanArray = (config, data) => { const handleDataToGetRowSpanArray = (config, data) => {
let _arr = returnMergeArray(config); let _arr = returnMergeArray(config);
let _merge = {}; let _merge = {};
// _merge:{爱好:[[0,3],[3,5]]} // _merge:{爱好:[[0,3],[3,5]]}
_arr.forEach(key => { _arr.forEach((key) => {
_merge[key] = {}; _merge[key] = {};
let _currentIndex = 0; let _currentIndex = 0;
data.forEach((item, index) => { data.forEach((item, index) => {
...@@ -372,54 +399,57 @@ const BasicReport = (props) => { ...@@ -372,54 +399,57 @@ const BasicReport = (props) => {
pageSize: pageSize, pageSize: pageSize,
}); });
// sortFields // sortFields
reportService.getReportInfo(_data).then(res => { reportService
if (res.code === 0) { .getReportInfo(_data)
let _reportDetails = res.data.reportDetails; .then((res) => {
let _statisticalValues = res.data.statisticalValues; if (res.code === 0) {
let _tableData = res.data.data.list; let _reportDetails = res.data.reportDetails;
let _sortString = res.data.sortString; let _statisticalValues = res.data.statisticalValues;
if (isInit) { let _tableData = res.data.data.list;
setConfig(_reportDetails, _statisticalValues, _tableData); let _sortString = res.data.sortString;
} if (isInit) {
getTableHeaderConfig(_reportDetails, _tableData); setConfig(_reportDetails, _statisticalValues, _tableData);
let _pagination = { ...pagination }; }
_pagination.total = res.data.data.totalCount; getTableHeaderConfig(_reportDetails, _tableData);
setPagination(_pagination); let _pagination = { ...pagination };
setTableData(_tableData); _pagination.total = res.data.data.totalCount;
// 处理排序字段 setPagination(_pagination);
handleSortString(_sortString); setTableData(_tableData);
if (_tableData) { // 处理排序字段
setSortModalVisible(true); handleSortString(_sortString);
setCurrentReportId(_reportDetails[0]?.reportId); if (_tableData) {
setSortModalVisible(true);
setCurrentReportId(_reportDetails[0]?.reportId);
} else {
setSortModalVisible(false);
setCurrentReportId(null);
}
} else { } else {
setSortModalVisible(false); setSortModalVisible(false);
setCurrentReportId(null); setCurrentReportId(null);
message.error('未能查询到报表数据!');
let _pagination = { ...pagination };
_pagination.total = 0;
_pagination.current = 1;
setPagination(_pagination);
setTableData([]);
} }
} else { setTableLoading(false);
setSortModalVisible(false); })
setCurrentReportId(null); .catch((err) => {
message.error('未能查询到报表数据!'); console.log(err);
let _pagination = { ...pagination }; setTableLoading(false);
_pagination.total = 0; });
_pagination.current = 1;
setPagination(_pagination);
setTableData([]);
}
setTableLoading(false);
}).catch(err => {
console.log(err);
setTableLoading(false);
});
}; };
/** /** @description: 在配置项中,isFilter: true 用来渲染控制框;filterRule: 下拉/文本/多选 */
* @Description: 在配置项中,isFilter: true 用来渲染控制框;filterRule: 下拉/文本/多选
* */
const getControlsBarConfig = (config) => { const getControlsBarConfig = (config) => {
let _data = config.filter(item => item.isFilter); let _data = config.filter((item) => item.isFilter);
let _searchPlaceholder = []; let _searchPlaceholder = [];
_data.filter(item => item.filterRule === '文本').forEach(item => _searchPlaceholder.push(item.fieldAlias)); _data
.filter((item) => item.filterRule === '文本')
.forEach((item) => _searchPlaceholder.push(item.fieldAlias));
setSearchPlaceholder(_searchPlaceholder); setSearchPlaceholder(_searchPlaceholder);
let _controls = _data.filter(item => ControlsType.includes(item.filterRule)); let _controls = _data.filter((item) => ControlsType.includes(item.filterRule));
setControls(_controls); setControls(_controls);
handleDate(_controls); handleDate(_controls);
}; };
...@@ -438,32 +468,34 @@ const BasicReport = (props) => { ...@@ -438,32 +468,34 @@ const BasicReport = (props) => {
// 合并列 // 合并列
let _colSpan = -1; let _colSpan = -1;
let _index = 0; let _index = 0;
config.filter(item => item.isShow).forEach((item, index) => { config
if (item.isStatistics) { .filter((item) => item.isShow)
_index += 1; .forEach((item, index) => {
_colSpan = -1; if (item.isStatistics) {
_summaryConfig[item.fieldAlias] = { _index += 1;
fieldName: item.fieldAlias, _colSpan = -1;
index, _summaryConfig[item.fieldAlias] = {
alignType: item.alignType, fieldName: item.fieldAlias,
type: item.statisticsRule, index,
isMoney: item.type === '数值' && !!hasMoney(item.configItems), alignType: item.alignType,
configItems: item.configItems, type: item.statisticsRule,
}; isMoney: item.type === '数值' && !!hasMoney(item.configItems),
} else { configItems: item.configItems,
let _name = `空值行${_index}`; };
if (_colSpan === -1) {
_colSpan = 1;
} else { } else {
_colSpan += 1; let _name = `空值行${_index}`;
if (_colSpan === -1) {
_colSpan = 1;
} else {
_colSpan += 1;
}
_summaryConfig[_name] = {
fieldName: _name,
colSpan: _colSpan,
};
} }
_summaryConfig[_name] = { });
fieldName: _name, summary.forEach((item) => {
colSpan: _colSpan,
};
}
});
summary.forEach(item => {
switch (item.totalType) { switch (item.totalType) {
case '全部': case '全部':
setHasTotal(true); setHasTotal(true);
...@@ -480,11 +512,12 @@ const BasicReport = (props) => { ...@@ -480,11 +512,12 @@ const BasicReport = (props) => {
}); });
// 增加操作列,总结栏最后一个单元格需要延伸一格 // 增加操作列,总结栏最后一个单元格需要延伸一格
let _sumArr = Object.values(_summaryConfig); let _sumArr = Object.values(_summaryConfig);
if (_sumArr && _sumArr.length) _sumArr = _sumArr.map((item, index) => { if (_sumArr && _sumArr.length)
let _item = { ...item }; _sumArr = _sumArr.map((item, index) => {
if (index === _sumArr.length - 1) _item.colSpan += 1; let _item = { ...item };
return _item; if (index === _sumArr.length - 1) _item.colSpan += 1;
}); return _item;
});
setSummaryArray(_sumArr); setSummaryArray(_sumArr);
}; };
...@@ -508,7 +541,7 @@ const BasicReport = (props) => { ...@@ -508,7 +541,7 @@ const BasicReport = (props) => {
return _map[type] || _map['文本']; return _map[type] || _map['文本'];
}; };
const returnSortFields = (data) => { const returnSortFields = (data) => {
return data.map(item => item.fieldAlias); return data.map((item) => item.fieldAlias);
}; };
// 处理表格数据,生成表头 // 处理表格数据,生成表头
const returnColumn = (config, data) => { const returnColumn = (config, data) => {
...@@ -516,7 +549,7 @@ const BasicReport = (props) => { ...@@ -516,7 +549,7 @@ const BasicReport = (props) => {
//1. 合并表头; //1. 合并表头;
//2. 四类形态的渲染处理; //2. 四类形态的渲染处理;
//3. 多列表头排序;剔除掉原有图标,需要自己实现排序的按钮 //3. 多列表头排序;剔除掉原有图标,需要自己实现排序的按钮
let _config = [...config].filter(item => item.isShow); let _config = [...config].filter((item) => item.isShow);
function dataStruct(keyArray, dataIndex, obj, dataObj) { function dataStruct(keyArray, dataIndex, obj, dataObj) {
if (dataIndex < keyArray.length - 1) { if (dataIndex < keyArray.length - 1) {
...@@ -532,7 +565,7 @@ const BasicReport = (props) => { ...@@ -532,7 +565,7 @@ const BasicReport = (props) => {
let _tempObj = {}; let _tempObj = {};
let _fieldAliasArray = handleDataToGetRowSpanArray(_config, data); // 需要向下合并的字段 let _fieldAliasArray = handleDataToGetRowSpanArray(_config, data); // 需要向下合并的字段
_config.forEach(item => { _config.forEach((item) => {
let _item = { let _item = {
title: item.fieldAlias, title: item.fieldAlias,
dataIndex: item.fieldAlias, dataIndex: item.fieldAlias,
...@@ -610,15 +643,20 @@ const BasicReport = (props) => { ...@@ -610,15 +643,20 @@ const BasicReport = (props) => {
width: 60, width: 60,
fixed: 'right', fixed: 'right',
render: (text, record) => { render: (text, record) => {
return <Space className={style.handleColumnWrapper}> return (
{ <Space className={style.handleColumnWrapper}>
permission.includes('editBtn') ? {permission.includes('editBtn') ? (
<FormOutlined className={style.editButton} onClick={() => { <FormOutlined
setEditComponentVisible(true); className={style.editButton}
setCurrentData(record); onClick={() => {
}} /> : '' setEditComponentVisible(true);
} setCurrentData(record);
{/* { }}
/>
) : (
''
)}
{/* {
permission.includes('deleteBtn') ? permission.includes('deleteBtn') ?
<DeleteOutlined disabled className={style.deleteButton} onClick={() => { <DeleteOutlined disabled className={style.deleteButton} onClick={() => {
Modal.confirm({ Modal.confirm({
...@@ -627,13 +665,14 @@ const BasicReport = (props) => { ...@@ -627,13 +665,14 @@ const BasicReport = (props) => {
}); });
}} /> : '' }} /> : ''
}*/} }*/}
</Space>; </Space>
);
}, },
}); });
} }
// 统计宽度 // 统计宽度
let _x = _tempArray.reduce((final, curr) => { let _x = _tempArray.reduce((final, curr) => {
return final += curr.width; return (final += curr.width);
}, 0); }, 0);
setTableX(_x); setTableX(_x);
return _tempArray; return _tempArray;
...@@ -665,40 +704,47 @@ const BasicReport = (props) => { ...@@ -665,40 +704,47 @@ const BasicReport = (props) => {
const paginationHeight = 75; // 分页部分的高度 const paginationHeight = 75; // 分页部分的高度
const tableHeaderHeight = tableHeaderLevel * 40; // 表头高度 const tableHeaderHeight = tableHeaderLevel * 40; // 表头高度
const summaryHeight = summaryArray.length ? 40 * (Number(hasTotal) + Number(hasSinglePage)) : 0; // 总结栏的高度 const summaryHeight = summaryArray.length ? 40 * (Number(hasTotal) + Number(hasSinglePage)) : 0; // 总结栏的高度
const _minus = clientHeight - _height - 16 - 4 - tableHeaderHeight - paginationHeight - summaryHeight - 10; const _minus =
clientHeight - _height - 16 - 4 - tableHeaderHeight - paginationHeight - summaryHeight - 10;
setListHeight(clientHeight - _height - paginationHeight - 4 - 6 - 16 - 2); setListHeight(clientHeight - _height - paginationHeight - 4 - 6 - 16 - 2);
setTableY(_minus); setTableY(_minus);
}; };
const getTableLevel = (config) => { const getTableLevel = (config) => {
let _level = config.reduce((final, curr) => { let _level =
return final = curr.level > final ? curr.level : final; config.reduce((final, curr) => {
}, 1) || 1; return (final = curr.level > final ? curr.level : final);
}, 1) || 1;
setTableHeaderLevel(_level); setTableHeaderLevel(_level);
}; };
const saveReportListSortFields = (callback) => { const saveReportListSortFields = (callback) => {
reportService.saveReportListSortFields({ reportService
reportId: currentReportId, .saveReportListSortFields({
sortFields: selectedSortFields.filter(item => item.value).map(item => ({ reportId: currentReportId,
fieldAlias: item.value, sortFields: selectedSortFields
sortType: item.sort, .filter((item) => item.value)
})), .map((item) => ({
}).then(res => { fieldAlias: item.value,
if (res.code === 0) { sortType: item.sort,
message.success('排序保存成功!'); })),
callback(); })
} else { .then((res) => {
message.error(res.msg); if (res.code === 0) {
} message.success('排序保存成功!');
}); callback();
} else {
message.error(res.msg);
}
});
}; };
/** /** @description: 判断是否存在【时间】类型的选择,并返回组件 */
* @Description: 判断是否存在【时间】类型的选择,并返回组件
* */
const handleDate = (obj) => { const handleDate = (obj) => {
let _typeObj = obj.find(item => item.filterRule === '日期'); let _typeObj = obj.find((item) => item.filterRule === '日期');
setHasDatePicker(_typeObj ? _typeObj.fieldAlias : ''); setHasDatePicker(_typeObj ? _typeObj.fieldAlias : '');
const _configItems = _typeObj.configItems.split('|'); const _configItems = _typeObj.configItems.split('|');
let _defaultDate = _configItems.find(item => item.includes('defaultDate='))?.replace('defaultDate=', '')?.split(','); let _defaultDate = _configItems
.find((item) => item.includes('defaultDate='))
?.replace('defaultDate=', '')
?.split(',');
if (_defaultDate && _defaultDate.length > 1) { if (_defaultDate && _defaultDate.length > 1) {
_defaultDate = { dateFrom: moment(_defaultDate[0]), dateTo: moment(_defaultDate[1]) }; _defaultDate = { dateFrom: moment(_defaultDate[0]), dateTo: moment(_defaultDate[1]) };
} else if (_defaultDate && _defaultDate.length === 1) { } else if (_defaultDate && _defaultDate.length === 1) {
...@@ -708,7 +754,9 @@ const BasicReport = (props) => { ...@@ -708,7 +754,9 @@ const BasicReport = (props) => {
} }
setDefaultDateConfig({ setDefaultDateConfig({
defaultDate: _defaultDate?.dateFrom, defaultDate: _defaultDate?.dateFrom,
defaultModel: _configItems.find(item => item.includes('defaultModel='))?.replace('defaultModel=', '') || 'year', defaultModel:
_configItems.find((item) => item.includes('defaultModel='))?.replace('defaultModel=', '') ||
'year',
}); });
}; };
useEffect(() => { useEffect(() => {
...@@ -732,219 +780,327 @@ const BasicReport = (props) => { ...@@ -732,219 +780,327 @@ const BasicReport = (props) => {
window.addEventListener('resize', getRefHeight); window.addEventListener('resize', getRefHeight);
return () => window.removeEventListener('resize', getRefHeight); return () => window.removeEventListener('resize', getRefHeight);
}); });
return <div className={style.reportManage} ref={tableWrapperRef}> return (
{/* 预留容器,提供给点击后的功能显示 */} <div className={style.reportManage} ref={tableWrapperRef}>
{ {/* 预留容器,提供给点击后的功能显示 */}
detailsComponentVisible ? <DetailsComponent url={detailConfig.url} params={detailConfig.params} {detailsComponentVisible ? (
onCancel={() => setDetailsComponentVisible(false)} /> : '' <DetailsComponent
} url={detailConfig.url}
{/* 为方便阅读,分开两部分代码 */} params={detailConfig.params}
{ onCancel={() => setDetailsComponentVisible(false)}
!detailsComponentVisible ? <div className={style.contentWrapper}> />
{ ) : (
state !== 'scan' ? <Row className={style.controlRow} ref={controlRef}> ''
)}
<Space style={{ flex: 1 }} size={8} wrap={true}> {/* 为方便阅读,分开两部分代码 */}
{/*时间搜索控件,确保时间搜索控件在第一个,单独匹配*/} {!detailsComponentVisible ? (
{ <div className={style.contentWrapper}>
hasDatePicker && defaultDateConfig.defaultDate !== null && permission.includes('filters') ? {state !== 'scan' ? (
<Row className={style.controlRow} ref={controlRef}>
<Space style={{ flex: 1 }} size={8} wrap={true}>
{/*时间搜索控件,确保时间搜索控件在第一个,单独匹配*/}
{hasDatePicker &&
defaultDateConfig.defaultDate !== null &&
permission.includes('filters') ? (
<DatePickerGroup <DatePickerGroup
showModels={['all', 'month', 'quarter', 'year', 'custom']} showModels={['all', 'month', 'quarter', 'year', 'custom']}
onChange={changeDate} onChange={changeDate}
format={dateFormat} format={dateFormat}
defaultModel={defaultDateConfig.defaultModel} defaultModel={defaultDateConfig.defaultModel}
defaultDate={defaultDateConfig.defaultDate} defaultDate={defaultDateConfig.defaultDate}
/> : '' />
} ) : (
{ ''
controls && controls.length && permission.includes('filters') ? )}
controls.filter(control => ['下拉', '多选'].includes(control.filterRule)).map(control => { {controls && controls.length && permission.includes('filters')
return <Form.Item label={control.fieldAlias} key={control.fieldAlias}> ? controls
<ReturnControlComponent style={{ width: 240 }} type={control.filterRule} reportName={reportName} .filter((control) => ['下拉', '多选'].includes(control.filterRule))
fieldAlias={control.fieldAlias} .map((control) => {
configItems={control.configItems} return (
onChange={(e) => controlSelectChange(control.fieldAlias, e)} /> <Form.Item label={control.fieldAlias} key={control.fieldAlias}>
</Form.Item>; <ReturnControlComponent
}) : '' style={{ width: 240 }}
} type={control.filterRule}
{ reportName={reportName}
permission.includes('filters') ? <Form.Item label='快速索引' key={'快速搜索控件'}> fieldAlias={control.fieldAlias}
<ReturnControlComponent configItems={control.configItems}
placeholder={`请输入${searchPlaceholder.length ? searchPlaceholder.join(',') : '关键字'}搜索`} onChange={(e) => controlSelectChange(control.fieldAlias, e)}
style={{ width: 240 }} type={'文本'} onChange={(e) => { />
searchInputChange(e); </Form.Item>
}} onSearch={searchData} /> );
</Form.Item> : '' })
} : ''}
</Space> {permission.includes('filters') ? (
{ <Form.Item label="快速索引" key={'快速搜索控件'}>
permission.includes('sortBtn') ? <div style={{ width: 200, textAlign: 'end' }}> <ReturnControlComponent
<Space size={8} nowrap={true}> placeholder={`请输入${
{ searchPlaceholder.length ? searchPlaceholder.join(',') : '关键字'
sortModalVisible && permission.includes('sortBtn') ? <Form.Item> }搜索`}
<Button type={'primary'} title={'自定义排序'} icon={<SortAscendingOutlined />} style={{ width: 240 }}
onClick={() => setModalVisible(true)}>排序</Button> type={'文本'}
</Form.Item> : '' onChange={(e) => {
} searchInputChange(e);
{ }}
permission.includes('exportBtn') ? <Form.Item> onSearch={searchData}
<Dropdown.Button style={{ float: 'right' }} overlay={menu}>导出</Dropdown.Button> />
</Form.Item> : '' </Form.Item>
} ) : (
</Space> ''
</div> : '' )}
} </Space>
</Row> : '' {permission.includes('sortBtn') ? (
} <div style={{ width: 200, textAlign: 'end' }}>
<div className={style.tableContent} <Space size={8} nowrap={true}>
style={{ height: `calc(100% - ${controlsHeight || 0}px)` }}> {sortModalVisible && permission.includes('sortBtn') ? (
{ <Form.Item>
columns && columns.length ? <BasicTable <Button
rowKey={'Key'} type={'primary'}
bordered title={'自定义排序'}
loading={tableLoading} icon={<SortAscendingOutlined />}
dataSource={tableData} onClick={() => setModalVisible(true)}
columns={columns} >
onChange={(pagination, filters, sorter, extra)=>{ 排序
console.log(sorter) </Button>
}} </Form.Item>
pagination={permission.includes('pagination') ? pagination : false} ) : (
// 237是内置图片高度 ''
scroll={{ y: (tableData && tableData.length) ? `calc(100% - 44px)` : 237, x: tableX }} )}
summary={(pageData) => { {permission.includes('exportBtn') ? (
if (summaryArray.length && tableData && tableData.length) return <Table.Summary fixed> <Form.Item>
<Table.Summary.Row> <Dropdown.Button style={{ float: 'right' }} overlay={menu}>
{ 导出
hasSinglePage ? </Dropdown.Button>
summaryArray.map((item, index) => { </Form.Item>
if (item.fieldName === '空值行0') { ) : (
return <Table.Summary.Cell key={`summary_${index}`} index={0} ''
colSpan={item.colSpan + 1}><span )}
style={{ </Space>
display: 'inline-block', </div>
width: '100%', ) : (
textAlign: 'center', ''
}}>小计</span></Table.Summary.Cell>; )}
} else if (item.fieldName.includes('空值行')) { </Row>
return <Table.Summary.Cell key={`summary_${index}`} index={0} colSpan={item.colSpan} />; ) : (
} else { ''
return <Table.Summary.Cell key={`summary_${index}`} index={0}><span style={{ )}
display: 'inline-block', <div
width: '100%', className={style.tableContent}
textAlign: item.alignType, style={{ height: `calc(100% - ${controlsHeight || 0}px)` }}
}}>{item.type.replace('求', '')}: {returnHandledNumber(item.configItems, item['单页'])}</span></Table.Summary.Cell>; >
} {columns && columns.length ? (
}) : '' <BasicTable
} rowKey={'Key'}
</Table.Summary.Row> bordered
<Table.Summary.Row> loading={tableLoading}
{ dataSource={tableData}
hasTotal ? columns={columns}
summaryArray.map(item => { onChange={(pagination, filters, sorter, extra) => {
if (item.fieldName === '空值行0') { console.log(sorter);
return <Table.Summary.Cell index={0} colSpan={item.colSpan + 1}><span style={{ }}
display: 'inline-block', pagination={permission.includes('pagination') ? pagination : false}
width: '100%', // 237是内置图片高度
textAlign: 'center', scroll={{ y: tableData && tableData.length ? `calc(100% - 44px)` : 237, x: tableX }}
}}>总计</span></Table.Summary.Cell>; summary={(pageData) => {
} else if (item.fieldName.includes('空值行')) { if (summaryArray.length && tableData && tableData.length)
return <Table.Summary.Cell index={0} colSpan={item.colSpan} />; return (
} else { <Table.Summary fixed>
return <Table.Summary.Cell index={0}><span style={{ <Table.Summary.Row>
display: 'inline-block', {hasSinglePage
width: '100%', ? summaryArray.map((item, index) => {
textAlign: item.alignType, if (item.fieldName === '空值行0') {
}}>{item.type.replace('求', '')}: {returnHandledNumber(item.configItems, item['全部'])}</span></Table.Summary.Cell>; return (
} <Table.Summary.Cell
}) : '' key={`summary_${index}`}
} index={0}
</Table.Summary.Row> colSpan={item.colSpan + 1}
</Table.Summary>; >
}} <span
/> : <div className={style.spinWrapper}> style={{
<Spin /> display: 'inline-block',
</div> width: '100%',
} textAlign: 'center',
</div> }}
</div> : '' >
} 小计
<Modal </span>
title={'自定义排序字段'} </Table.Summary.Cell>
visible={modalVisible} );
onCancel={() => setModalVisible(false)} } else if (item.fieldName.includes('空值行')) {
footer={ return (
<div style={{ display: 'flex', justifyContent: 'space-between' }}> <Table.Summary.Cell
<div> key={`summary_${index}`}
<Button type={'link'} onClick={() => addOtherSortFields()}>增加次要排序</Button> index={0}
</div> colSpan={item.colSpan}
<div> />
<Button onClick={() => setModalVisible(false)}>取消</Button> );
<Button type={'primary'} onClick={() => { } else {
saveReportListSortFields(() => getData(false, pagination)); return (
setModalVisible(false); <Table.Summary.Cell key={`summary_${index}`} index={0}>
}}>确认</Button> <span
style={{
display: 'inline-block',
width: '100%',
textAlign: item.alignType,
}}
>
{item.type.replace('求', '')}:{' '}
{returnHandledNumber(item.configItems, item['单页'])}
</span>
</Table.Summary.Cell>
);
}
})
: ''}
</Table.Summary.Row>
<Table.Summary.Row>
{hasTotal
? summaryArray.map((item) => {
if (item.fieldName === '空值行0') {
return (
<Table.Summary.Cell index={0} colSpan={item.colSpan + 1}>
<span
style={{
display: 'inline-block',
width: '100%',
textAlign: 'center',
}}
>
总计
</span>
</Table.Summary.Cell>
);
} else if (item.fieldName.includes('空值行')) {
return <Table.Summary.Cell index={0} colSpan={item.colSpan} />;
} else {
return (
<Table.Summary.Cell index={0}>
<span
style={{
display: 'inline-block',
width: '100%',
textAlign: item.alignType,
}}
>
{item.type.replace('求', '')}:{' '}
{returnHandledNumber(item.configItems, item['全部'])}
</span>
</Table.Summary.Cell>
);
}
})
: ''}
</Table.Summary.Row>
</Table.Summary>
);
}}
/>
) : (
<div className={style.spinWrapper}>
<Spin />
</div>
)}
</div> </div>
</div> </div>
} ) : (
> ''
{ )}
selectedSortFields.map((item, index) => <Row key={'label'} className={style.controlRow}> <Modal
<Space size={8} wrap={true}> title={'自定义排序字段'}
<Form.Item label={item.label}> visible={modalVisible}
<Select style={{ width: 240 }} defaultValue={item.value} value={item.value} onCancel={() => setModalVisible(false)}
onChange={(e) => changeSortField(e, index, 'value')}> footer={
<Option value=''>未选择</Option> <div style={{ display: 'flex', justifyContent: 'space-between' }}>
{ <div>
allSortFields.map(item => <Option value={item}>{item}</Option>) <Button type={'link'} onClick={() => addOtherSortFields()}>
} 增加次要排序
</Select> </Button>
</Form.Item> </div>
<Form.Item> <div>
<Select style={{ width: 120 }} defaultValue={item.sort} value={item.sort} <Button onClick={() => setModalVisible(false)}>取消</Button>
onChange={(e) => changeSortField(e, index, 'sort')}> <Button
<Option value={'asc'}>升序</Option> type={'primary'}
<Option value={'desc'}>降序</Option> onClick={() => {
</Select> saveReportListSortFields(() => getData(false, pagination));
</Form.Item> setModalVisible(false);
{ }}
index !== 0 ? >
确认
</Button>
</div>
</div>
}
>
{selectedSortFields.map((item, index) => (
<Row key={'label'} className={style.controlRow}>
<Space size={8} wrap={true}>
<Form.Item label={item.label}>
<Select
style={{ width: 240 }}
defaultValue={item.value}
value={item.value}
onChange={(e) => changeSortField(e, index, 'value')}
>
<Option value="">未选择</Option>
{allSortFields.map((item) => (
<Option value={item}>{item}</Option>
))}
</Select>
</Form.Item>
<Form.Item>
<Select
style={{ width: 120 }}
defaultValue={item.sort}
value={item.sort}
onChange={(e) => changeSortField(e, index, 'sort')}
>
<Option value={'asc'}>升序</Option>
<Option value={'desc'}>降序</Option>
</Select>
</Form.Item>
{index !== 0 ? (
<Form.Item> <Form.Item>
<MinusCircleOutlined style={{ color: 'rgba(0,0,0,.65)' }} onClick={() => deleteSortField(index)} /> <MinusCircleOutlined
</Form.Item> : '' style={{ color: 'rgba(0,0,0,.65)' }}
} onClick={() => deleteSortField(index)}
</Space> />
</Row>) </Form.Item>
} ) : (
</Modal> ''
<Modal )}
visible={extraModal} </Space>
onCancel={() => setExtraModal(false)} </Row>
destroyOnClose ))}
width={800} </Modal>
> <Modal visible={extraModal} onCancel={() => setExtraModal(false)} destroyOnClose width={800}>
{extra} {extra}
</Modal> </Modal>
{/* 编辑表单 */} {/* 编辑表单 */}
<Modal <Modal
title={'编辑报表信息'} title={'编辑报表信息'}
visible={editComponentVisible} visible={editComponentVisible}
width={'80%'} width={'80%'}
footer={null} footer={null}
// visible={true} // visible={true}
onCancel={() => setEditComponentVisible(false)} onCancel={() => setEditComponentVisible(false)}
> >
<ReportEditForm reportDetails={tableStruct} reportData={currentData} onCancel={() => { <ReportEditForm
setEditComponentVisible(false); reportDetails={tableStruct}
getData(false, pagination); reportData={currentData}
}} reportName={reportName} /> onCancel={() => {
</Modal> setEditComponentVisible(false);
</div>; getData(false, pagination);
}}
reportName={reportName}
/>
</Modal>
</div>
);
}; };
const mapStateToProps = state => { const mapStateToProps = (state) => {
const allWidgets = state.getIn(['global', 'globalConfig', 'allWidgets']); const allWidgets = state.getIn(['global', 'globalConfig', 'allWidgets']);
let _flatWidgets = []; let _flatWidgets = [];
const flatWidgets = (arr) => { const flatWidgets = (arr) => {
arr.forEach(item => { arr.forEach((item) => {
if (item.widgets && item.widgets.length) { if (item.widgets && item.widgets.length) {
flatWidgets(item.widgets); flatWidgets(item.widgets);
} else { } else {
......
@import "~antd/es/style/themes/default.less"; @import '~antd/es/style/themes/default.less';
.lackParams { .lackParams {
width: 100%;
height: 100%;
display: flex; display: flex;
justify-content: center;
align-items: center; align-items: center;
justify-content: center;
width: 100%;
height: 100%;
} }
.reportManage { .reportManage {
padding: 8px;
height: 100%;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
height: 100%;
padding: 8px;
.contentWrapper { .contentWrapper {
display: flex; display: flex;
...@@ -20,12 +20,12 @@ ...@@ -20,12 +20,12 @@
height: 100%; height: 100%;
.controlRow { .controlRow {
background: #ffffff;
padding: 6px;
border-radius: 4px;
margin-bottom: 4px;
display: flex; display: flex;
flex-direction: row; flex-direction: row;
margin-bottom: 4px;
padding: 6px;
background: #ffffff;
border-radius: 4px;
} }
.tableContent { .tableContent {
...@@ -46,8 +46,8 @@ ...@@ -46,8 +46,8 @@
} }
.deleteButton { .deleteButton {
cursor: pointer;
color: rgb(255, 0, 0); color: rgb(255, 0, 0);
cursor: pointer;
&:hover { &:hover {
//color: rgb(24, 144, 255); //color: rgb(24, 144, 255);
...@@ -56,25 +56,24 @@ ...@@ -56,25 +56,24 @@
} }
.spinWrapper { .spinWrapper {
width: 100vw;
height: 60vh;
display: flex; display: flex;
align-items: center;
justify-content: center; justify-content: center;
align-items: center width: 100vw;
height: 60vh;
} }
:global { :global {
.@{ant-prefix}-table-container { .@{ant-prefix}-table-container {
height: 100%; height: 100%;
& > .@{ant-prefix}-table-body { & > .@{ant-prefix}-table-body {
border-bottom: 1px solid #dbe7fb;
border-right: 1px solid #dbe7fb; border-right: 1px solid #dbe7fb;
border-bottom: 1px solid #dbe7fb;
} }
.@{ant-prefix}-table-body { .@{ant-prefix}-table-body {
flex: 1 flex: 1;
} }
.@{ant-prefix}-table-summary > table > tfoot > tr > td { .@{ant-prefix}-table-summary > table > tfoot > tr > td {
...@@ -97,7 +96,6 @@ ...@@ -97,7 +96,6 @@
} }
} }
.link { .link {
cursor: pointer; cursor: pointer;
...@@ -115,7 +113,7 @@ ...@@ -115,7 +113,7 @@
} }
.prefixOrSuffix { .prefixOrSuffix {
color: rgba(0, 0, 0, .65); color: rgba(0, 0, 0, 0.65);
font-size: 10px; font-size: 10px;
} }
...@@ -128,14 +126,14 @@ ...@@ -128,14 +126,14 @@
::-webkit-scrollbar-track, ::-webkit-scrollbar-track,
*::-webkit-scrollbar-track { *::-webkit-scrollbar-track {
background: #F2F2F2; background: #f2f2f2;
border-radius: 10px; border-radius: 10px;
} }
::-webkit-scrollbar-thumb, ::-webkit-scrollbar-thumb,
*::-webkit-scrollbar-thumb { *::-webkit-scrollbar-thumb {
background: #dcdcdc;
border-radius: 5px; border-radius: 5px;
background: #DCDCDC;
} }
} }
} }
...@@ -13,14 +13,14 @@ const isArray = (arr) => { ...@@ -13,14 +13,14 @@ const isArray = (arr) => {
const hasMoney = (configItems) => { const hasMoney = (configItems) => {
if (!configItems) return false; if (!configItems) return false;
let _items = configItems.split('|'); let _items = configItems.split('|');
return !!_items.find(item => item === '金额'); return !!_items.find((item) => item === '金额');
}; };
/** /**
* @Description: 用来在summary中处理数值的配置 * @description: 用来在summary中处理数值的配置
* @Params: 参数描述 * @params: 参数描述
* @Date: 2022/8/10 * @date: 2022/8/10
* @Author: ChenLong * @author: ChenLong
* */ */
const returnHandledNumber = (configItems, num) => { const returnHandledNumber = (configItems, num) => {
// 精度、前缀、后缀、倍率 // 精度、前缀、后缀、倍率
// $_d|_d%|_d*0.0001|金额|0.00 // $_d|_d%|_d*0.0001|金额|0.00
...@@ -31,7 +31,7 @@ const returnHandledNumber = (configItems, num) => { ...@@ -31,7 +31,7 @@ const returnHandledNumber = (configItems, num) => {
let template = '_d'; let template = '_d';
let precision = 0; let precision = 0;
let rate = 1; let rate = 1;
_items.forEach(item => { _items.forEach((item) => {
let _arr = []; let _arr = [];
if (item.match(/_d[^\*]/)) { if (item.match(/_d[^\*]/)) {
// 后缀 // 后缀
...@@ -46,30 +46,40 @@ const returnHandledNumber = (configItems, num) => { ...@@ -46,30 +46,40 @@ const returnHandledNumber = (configItems, num) => {
} }
}); });
// 可能存在NaN的问题 // 可能存在NaN的问题
let final = _items.includes('金额') ? Number((num * rate).toFixed(precision)).toLocaleString() : Number((num * rate).toFixed(precision)); let final = _items.includes('金额')
? Number((num * rate).toFixed(precision)).toLocaleString()
: Number((num * rate).toFixed(precision));
return template.replace(/_d/, final); return template.replace(/_d/, final);
}; };
/** /**
* @Description: 返回configItems内配置的默认值、默认模式等等 * @description: 返回configItems内配置的默认值、默认模式等等
* @Params: 参数描述 * @params: 参数描述
* @Date: 2022/8/12 * @date: 2022/8/12
* @Author: ChenLong * @author: ChenLong
* @params: * @params:
* configItems 报表字段的配置 例如 defaultValue=智慧水务 defaultDateModel=customer|defaultDateValue=2022-01-01,2022-12-31; * configItems 报表字段的配置 例如 defaultValue=智慧水务
* keysArray 所需要返回的值的key的集合,比如你需要获取configItems中的’defaultValue‘,那么keysArray=['defaultValue']; * defaultDateModel=customer|defaultDateValue=2022-01-01,2022-12-31;
* @Returns: * keysArray
* defaultValue 通用参数 默认值 * 所需要返回的值的key的集合,比如你需要获取configItems中的’defaultValue‘,那么keysArray=['defaultValue'];
* @returns:
* defaultValue 通用参数 默认值
* defaultDateModel 时间参数 默认模式 * defaultDateModel 时间参数 默认模式
* defaultDateValue 时间参数 默认时间 * defaultDateValue 时间参数 默认时间
* */ */
const returnDefaultValueOrConfigs = (configItems = '', keysArray = []) => { const returnDefaultValueOrConfigs = (configItems = '', keysArray = []) => {
let _map = {}; let _map = {};
let _configItemsArray = configItems.split('|'); let _configItemsArray = configItems.split('|');
keysArray.forEach(key => { keysArray.forEach((key) => {
_map[key] = _configItemsArray.find(item => item.includes(`${key}=`))?.replace(`${key}=`, ''); _map[key] = _configItemsArray.find((item) => item.includes(`${key}=`))?.replace(`${key}=`, '');
}); });
return _map; return _map;
}; };
export { export {
isObject, isString, isNumber, hasMoney, isArray, returnHandledNumber, returnDefaultValueOrConfigs, isObject,
isString,
isNumber,
hasMoney,
isArray,
returnHandledNumber,
returnDefaultValueOrConfigs,
}; };
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