Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wisdom-components
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
ReactWeb5
wisdom-components
Commits
fb2e80f0
Commit
fb2e80f0
authored
Aug 17, 2022
by
陈龙
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: 新增BasicReport
parent
8b5c5f14
Pipeline
#57933
failed with stages
in 13 seconds
Changes
12
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
1990 additions
and
0 deletions
+1990
-0
ReportEditForm.js
packages/base-components/BasicReport/src/ReportEditForm.js
+121
-0
index.js
packages/base-components/BasicReport/src/api/index.js
+83
-0
report.js
...ges/base-components/BasicReport/src/api/service/report.js
+119
-0
pic.webp
packages/base-components/BasicReport/src/assets/pic.webp
+0
-0
Control.js
...ges/base-components/BasicReport/src/components/Control.js
+96
-0
DatePickerGroup.js
...-components/BasicReport/src/components/DatePickerGroup.js
+196
-0
detailsComponent.js
...base-components/BasicReport/src/extra/detailsComponent.js
+17
-0
extraComponents.js
.../base-components/BasicReport/src/extra/extraComponents.js
+12
-0
index.js
packages/base-components/BasicReport/src/index.js
+960
-0
index.less
packages/base-components/BasicReport/src/index.less
+141
-0
handlers.js
packages/base-components/BasicReport/src/utils/handlers.js
+170
-0
utils.js
packages/base-components/BasicReport/src/utils/utils.js
+75
-0
No files found.
packages/base-components/BasicReport/src/ReportEditForm.js
0 → 100644
View file @
fb2e80f0
/*
** 报表的编辑、新增表单
** create by ChenLong on 2022/8/10
** 功能路径:src\pages\product\ReportsManage\ReportEditForm.js
** 菜单参数列表:*变量名*(变量说明,数据类型,是否必填,取值范围)
**/
import
React
,
{
useEffect
,
useState
}
from
'react'
;
import
{
Form
,
Input
,
DatePicker
,
InputNumber
,
Space
,
Row
,
Col
,
Button
,
message
}
from
'antd'
;
import
moment
from
'moment'
;
import
{
submitReportData
}
from
'../../../api/service/report'
;
// 类型
const
DATE_PICKER_ARRAY
=
[
'日期'
];
const
DATE_TIME_PICKER_ARRAY
=
[
'日期时刻'
];
const
DATE_TYPE
=
[
'日期'
,
'日期时刻'
];
// 用来匹配是否需要转为日期对象;
const
NUMBER_ARRAY
=
[
'数值'
,
'金额'
];
// 形态对应组件
// 对应关系
/**
* @Description: 函数描述
* @Date: 2022/8/10
* @Author: ChenLong
* @Params: reportDetails 各个字段的配置列表
* data 与reportDetails对应的值
* */
const
ReportEditForm
=
({
reportDetails
,
reportData
,
onCancel
,
reportName
})
=>
{
if
(
!
reportData
||
Object
.
keys
(
reportData
).
length
===
0
)
return
<>
未传递表单数据
<
/>
;
const
[
form
]
=
Form
.
useForm
();
const
formItemLayout
=
{
labelCol
:
{
span
:
8
,
},
wrapperCol
:
{
span
:
16
,
},
};
const
handleDate
=
(
reportDetails
,
data
)
=>
{
let
_data
=
{
...
data
};
reportDetails
.
forEach
(
item
=>
{
if
(
DATE_TYPE
.
includes
(
item
.
type
))
{
_data
[
item
.
fieldAlias
]
=
moment
(
data
[
item
.
fieldAlias
]);
}
});
return
_data
;
};
const
componentMap
=
(
config
)
=>
{
if
(
DATE_TIME_PICKER_ARRAY
.
includes
(
config
.
type
))
{
return
<
DatePicker
showTime
/>
;
}
else
if
(
DATE_PICKER_ARRAY
.
includes
(
config
.
type
))
{
return
<
DatePicker
/>
;
}
else
if
(
NUMBER_ARRAY
.
includes
(
config
.
type
))
{
return
<
InputNumber
/>
;
}
else
{
return
<
Input
/>
;
}
};
const
submitReportForm
=
()
=>
{
let
_data
=
form
.
getFieldsValue
();
console
.
log
(
_data
);
// {
// "key": "string",
// "fieldName": "string",
// "fieldValue": "string"
// }
let
final
=
[];
Object
.
keys
(
_data
).
forEach
(
key
=>
{
let
value
=
reportData
[
key
];
let
_value
=
_data
[
key
];
if
(
moment
.
isMoment
(
_data
[
key
]))
{
_value
=
moment
(
_data
[
key
]).
format
(
'YYYY-MM-DD HH:mm:ss'
);
}
if
(
value
!==
_value
)
{
final
.
push
({
key
:
reportData
.
Key
,
fieldName
:
key
,
fieldValue
:
_value
,
});
}
});
console
.
log
(
final
);
// reportService.updateReportData()
submitReportData
({
reportName
:
reportName
,
userId
:
window
.
globalConfig
.
userInfo
.
OID
,
},
final
).
then
(
res
=>
{
if
(
res
.
code
===
0
)
{
message
.
success
(
'保存成功!'
);
onCancel
();
}
});
};
useEffect
(()
=>
{
if
(
reportData
&&
Object
.
keys
(
reportData
).
length
)
form
.
setFieldsValue
(
handleDate
(
reportDetails
,
reportData
));
},
[
reportData
]);
return
(
<
div
>
<
Form
{...
formItemLayout
}
form
=
{
form
}
>
<
Row
>
{
reportDetails
&&
reportDetails
.
map
(
config
=>
{
return
<
Col
span
=
{
8
}
>
<
Form
.
Item
label
=
{
config
.
fieldAlias
}
name
=
{
config
.
fieldAlias
}
>
{
componentMap
(
config
)}
<
/Form.Item
>
<
/Col>
;
})
}
<
/Row
>
<
Row
>
<
Col
span
=
{
24
}
style
=
{{
textAlign
:
'right'
}}
>
{
/*<Form.Item style={{textAlign:'right'}}>*/
}
<
Button
type
=
{
'primary'
}
onClick
=
{
submitReportForm
}
>
提交
<
/Button
>
{
/*</Form.Item>*/
}
<
/Col
>
<
/Row
>
<
/Form
>
<
/div
>
);
};
export
default
ReportEditForm
;
packages/base-components/BasicReport/src/api/index.js
0 → 100644
View file @
fb2e80f0
import
{
Modal
,
notification
}
from
'antd'
;
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 WorkflowService from './service/workflow';
const
{
warning
}
=
Modal
;
// eslint-disable-next-line no-return-await
instanceRequest
.
reportCodeError
=
true
;
const
codeMessage
=
{
200
:
'服务器成功返回请求的数据。'
,
201
:
'新建或修改数据成功。'
,
202
:
'一个请求已经进入后台排队(异步任务)。'
,
204
:
'删除数据成功。'
,
400
:
'发出的请求有错误,服务器没有进行新建或修改数据的操作。'
,
401
:
'用户没有权限(令牌、用户名、密码错误), 或当前的会话已超时,请重新登录'
,
403
:
'用户得到授权,但是访问是被禁止的。'
,
404
:
'发出的请求针对的是不存在的记录,服务器没有进行操作。'
,
406
:
'请求的格式不可得。'
,
410
:
'请求的资源被永久删除,且不会再得到的。'
,
422
:
'当创建一个对象时,发生一个验证错误。'
,
500
:
'服务器发生错误,请检查服务器。'
,
502
:
'网关错误。'
,
503
:
'服务不可用,服务器暂时过载或维护。'
,
504
:
'网关超时。'
,
};
let
instance
=
null
;
instanceRequest
.
setErrorHandler
(
error
=>
{
const
{
response
}
=
error
;
if
(
response
&&
response
.
status
)
{
const
errorText
=
codeMessage
[
response
.
status
]
||
response
.
statusText
;
const
{
status
,
config
}
=
response
;
if
(
status
===
401
)
{
if
(
!
instance
)
{
instance
=
warning
({
title
:
'错误信息'
,
content
:
`
${
codeMessage
[
status
]}
`
,
centered
:
true
,
onOk
(
close
)
{
window
.
share
&&
window
.
share
.
event
&&
window
.
share
.
event
.
emit
(
'triggerLoginout'
);
close
();
},
});
}
}
else
{
notification
.
error
({
message
:
`请求错误
${
status
}
:
${
config
.
url
}
`
,
description
:
errorText
,
});
}
}
else
if
(
!
response
)
{
notification
.
error
({
description
:
'您的网络发生异常,无法连接服务器'
,
message
:
'网络异常'
,
});
}
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
);
export
{
appService
,
noticeService
,
accountService
,
assetService
,
// workflowService
reportService
};
packages/base-components/BasicReport/src/api/service/report.js
0 → 100644
View file @
fb2e80f0
/*
** 轻量化报表平台接口
** create by ChenLong on 2022/6/24
** 功能路径:src\api\service\report.js
** 菜单参数列表:*变量名*(变量说明,数据类型,是否必填,取值范围)
**/
import
{
request
}
from
'@wisdom-utils/utils'
;
import
*
as
constants
from
'../../constants'
;
const
BASEURL
=
'/PandaAssets/Assets/ReportManager'
;
export
const
API
=
{
GET_REPORT_INFO
:
`
${
BASEURL
}
/GetReportInfo`
,
// 获取报表信息
GET_REPORT_FILTER_VALUE
:
`
${
BASEURL
}
/GetReportFilterValue`
,
// 获取过滤字段的值的枚举
GET_REPORT_CONFIG_LIST
:
`
${
BASEURL
}
/GetReportConfigList`
,
// 获取配置列表
GET_REPORT_DETAILS_INFO
:
`
${
BASEURL
}
/GetReportDetailsInfo`
,
// 获取配置详情
GET_TABLES
:
`
${
BASEURL
}
/GetTables`
,
// 查询表
GET_TABLE_FIELDS
:
`
${
BASEURL
}
/GetTableFields`
,
// 查询表内的字段
ADD_REPORT_INFO
:
`
${
BASEURL
}
/AddReportInfo`
,
// 创建报表主表、关联报表子表
EDIT_REPORT_INFO
:
`
${
BASEURL
}
/AddReportInfo`
,
ADD_REPORT_DETAIL_INFO
:
`
${
BASEURL
}
/AddReportDetailInfo`
,
// 附加子表字段到主表
DELETE_REPORT_INFO
:
`
${
BASEURL
}
/DeleteReportInfo`
,
// 删除报表
DELETE_REPORT_DETAIL_INFO
:
`
${
BASEURL
}
/DeleteReportDetailInfo`
,
// 删除字段
EXPORT_ACCOUNT_DATA
:
`
${
BASEURL
}
/ExportAccountData`
,
// 导出数据
SAVE_REPORT_LIST_SORT_FIELDS
:
`
${
BASEURL
}
/SaveReportListSortFields`
,
// 保存排序
ADD_REPORT_DETAIL_INFO_INDEX
:
`
${
BASEURL
}
/AddReportDetailInfoIndex`
,
// 变更接口顺序
UPDATE_REPORT_DATA
:
`
${
BASEURL
}
/UpdateReportData`
,
// 更新报表数据
};
const
reportService
=
{
getReportInfo
:
{
url
:
API
.
GET_REPORT_INFO
,
method
:
constants
.
REQUEST_METHOD_POST
,
type
:
constants
.
REQUEST_METHOD_POST
,
},
getReportFilterValue
:
{
url
:
API
.
GET_REPORT_FILTER_VALUE
,
method
:
constants
.
REQUEST_METHOD_GET
,
type
:
constants
.
REQUEST_METHOD_GET
,
},
getReportConfigList
:
{
url
:
API
.
GET_REPORT_CONFIG_LIST
,
method
:
constants
.
REQUEST_METHOD_GET
,
type
:
constants
.
REQUEST_METHOD_GET
,
},
getReportDetailsInfo
:
{
url
:
API
.
GET_REPORT_DETAILS_INFO
,
method
:
constants
.
REQUEST_METHOD_GET
,
type
:
constants
.
REQUEST_METHOD_GET
,
},
getTables
:
{
url
:
API
.
GET_TABLES
,
method
:
constants
.
REQUEST_METHOD_GET
,
type
:
constants
.
REQUEST_METHOD_GET
,
},
getTableFields
:
{
url
:
API
.
GET_TABLE_FIELDS
,
method
:
constants
.
REQUEST_METHOD_POST
,
type
:
constants
.
REQUEST_METHOD_POST
,
},
addReportInfo
:
{
url
:
API
.
ADD_REPORT_INFO
,
method
:
constants
.
REQUEST_METHOD_POST
,
type
:
constants
.
REQUEST_METHOD_POST
,
},
editReportInfo
:
{
url
:
API
.
EDIT_REPORT_INFO
,
method
:
constants
.
REQUEST_METHOD_POST
,
type
:
constants
.
REQUEST_METHOD_POST
,
},
addReportDetailInfo
:
{
url
:
API
.
ADD_REPORT_DETAIL_INFO
,
method
:
constants
.
REQUEST_METHOD_POST
,
type
:
constants
.
REQUEST_METHOD_POST
,
},
deleteReportInfo
:
{
url
:
API
.
DELETE_REPORT_INFO
,
method
:
constants
.
REQUEST_METHOD_GET
,
type
:
constants
.
REQUEST_METHOD_GET
,
},
deleteReportDetailInfo
:
{
url
:
API
.
DELETE_REPORT_DETAIL_INFO
,
method
:
constants
.
REQUEST_METHOD_GET
,
type
:
constants
.
REQUEST_METHOD_GET
,
},
saveReportListSortFields
:
{
url
:
API
.
SAVE_REPORT_LIST_SORT_FIELDS
,
method
:
constants
.
REQUEST_METHOD_POST
,
type
:
constants
.
REQUEST_METHOD_POST
,
},
addReportDetailInfoIndex
:
{
url
:
API
.
ADD_REPORT_DETAIL_INFO_INDEX
,
method
:
constants
.
REQUEST_METHOD_POST
,
type
:
constants
.
REQUEST_METHOD_POST
,
},
updateReportData
:
{
url
:
API
.
UPDATE_REPORT_DATA
,
method
:
constants
.
REQUEST_METHOD_POST
,
type
:
constants
.
REQUEST_METHOD_POST
,
},
};
export
const
submitReportData
=
(
params
,
data
)
=>
request
({
url
:
API
.
UPDATE_REPORT_DATA
,
method
:
'post'
,
params
,
data
,
});
export
const
exportAccountData
=
(
options
,
params
,
data
)
=>
request
({
url
:
API
.
EXPORT_ACCOUNT_DATA
,
method
:
'post'
,
...
options
,
params
,
data
,
});
export
const
addReportDetailInfoIndex
=
(
data
)
=>
request
({
url
:
API
.
ADD_REPORT_DETAIL_INFO_INDEX
,
method
:
'post'
,
data
,
});
export
default
reportService
;
packages/base-components/BasicReport/src/assets/pic.webp
0 → 100644
View file @
fb2e80f0
File added
packages/base-components/BasicReport/src/components/Control.js
0 → 100644
View file @
fb2e80f0
// 文本/下拉/多选/时间
/**
* @Description:
* @Params:
* onChange: 需要传入onChange,接收值的变更
* */
import
React
,
{
useEffect
,
useState
}
from
'react'
;
import
{
Input
,
Select
}
from
'antd'
;
import
{
reportService
}
from
'@/api'
;
import
{
returnDefaultValueOrConfigs
}
from
'../utils/utils'
;
const
{
Option
}
=
Select
;
const
{
Search
}
=
Input
;
const
TextSearchComponent
=
({
onChange
,
style
,
onSearch
,
placeholder
})
=>
{
return
<
Search
title
=
{
placeholder
}
style
=
{
style
}
placeholder
=
{
placeholder
}
onChange
=
{
onChange
}
onSearch
=
{
onSearch
}
/>
;
};
/**
* data = ['选项1','选项2'...]
* @Props:
* 正常选项:武汉
* 附带统计数值: 武汉 (20)
*
* */
const
SelectSearchComponent
=
({
onChange
,
style
,
data
,
mode
,
reportName
,
fieldAlias
,
configItems
})
=>
{
const
[
value
,
setValue
]
=
useState
(
''
);
const
[
options
,
setOptions
]
=
useState
([]);
const
defaultConfigs
=
returnDefaultValueOrConfigs
(
configItems
,
[
'defaultValue'
]);
const
{
defaultValue
}
=
defaultConfigs
;
const
getData
=
()
=>
{
reportService
.
getReportFilterValue
({
reportName
,
fieldAlias
,
}).
then
(
res
=>
{
if
(
res
.
code
===
0
)
{
setOptions
(
res
.
data
);
}
}).
catch
(
err
=>
{
console
.
log
(
err
);
});
};
useEffect
(()
=>
{
getData
();
setValue
(
defaultValue
)
},
[]);
return
<
Select
value
=
{
value
}
style
=
{
style
}
onChange
=
{(
e
)
=>
{
onChange
(
e
);
setValue
(
e
);
}}
mode
=
{
mode
}
defaultValue
=
{
mode
===
'multiple'
?
defaultValue
.
split
(
','
)
:
defaultValue
}
allowClear
maxTagCount
=
{
1
}
placeholder
=
{
`请选择
${
fieldAlias
}
`
}
>
{
options
&&
options
.
length
?
options
.
map
(
item
=>
<
Option
key
=
{
item
.
filterValue
}
value
=
{
item
.
filterValue
}
>
{
item
.
filterValue
}
<
span
style
=
{{
color
:
'rgba(0,0,0,.65)'
}}
>
({
item
.
count
})
<
/span></
Option
>
,
)
:
''
}
<
/Select>
;
};
const
ReturnControlComponent
=
({
type
,
onChange
,
style
,
data
,
onSearch
,
reportName
,
fieldAlias
,
placeholder
,
configItems
,
})
=>
{
let
_component
=
''
;
switch
(
type
)
{
case
'文本'
:
_component
=
<
TextSearchComponent
style
=
{
style
}
onChange
=
{
onChange
}
onSearch
=
{
onSearch
}
placeholder
=
{
placeholder
}
configItems
=
{
configItems
}
/>
;
break
;
case
'下拉'
:
case
'多选'
:
_component
=
<
SelectSearchComponent
mode
=
{
type
===
'多选'
?
'multiple'
:
''
}
style
=
{
style
}
onChange
=
{
onChange
}
reportName
=
{
reportName
}
fieldAlias
=
{
fieldAlias
}
configItems
=
{
configItems
}
/>
;
break
;
default
:
break
;
}
return
_component
;
};
export
default
ReturnControlComponent
;
packages/base-components/BasicReport/src/components/DatePickerGroup.js
0 → 100644
View file @
fb2e80f0
/**
* 时间组选择:支持 全部,日,月,年,自定义 类型
* props:
* onChange: ({dateFrom, dateTo}, model) => {}。切换时间类型或时间会触发onChange,并传递选择的时间范围和类型。
* 注:dateFrom和dateTo都是格式化后的字符串
* format: 格式化字符串格式,默认"YYYY-MM-DD HH:mm:ss",参看moment格式化支持的
*/
import
React
,
{
useState
,
useEffect
}
from
'react'
;
import
{
Radio
,
Space
,
DatePicker
}
from
'antd'
;
import
moment
from
'moment'
;
const
dateForModel
=
(
model
,
date
=
moment
())
=>
{
if
(
!
date
)
{
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
;
};
const
textForModel
=
model
=>
{
switch
(
model
)
{
case
'day'
:
return
'日'
;
case
'week'
:
return
'周'
;
case
'month'
:
return
'月'
;
case
'quarter'
:
return
'季度'
;
case
'year'
:
return
'年'
;
case
'all'
:
return
'全部'
;
case
'custom'
:
return
'自定义'
;
default
:
return
model
;
}
};
const
useDataGroup
=
(
defaultValue
=
{
dateFrom
:
null
,
dateTo
:
null
},
defaultModel
=
'all'
)
=>
{
const
[
model
,
setModel
]
=
useState
(
defaultModel
);
const
[
value
,
setValue
]
=
useState
(
defaultValue
);
const
updateValeu
=
(
_value
,
_model
)
=>
{
setModel
(
_model
);
setValue
(
_value
);
};
return
[
value
,
model
,
updateValeu
];
};
const
defaultFormat
=
'YYYY-MM-DD HH:mm:ss'
;
const
defaultShowModels
=
[
'all'
,
'week'
,
'month'
,
'quarter'
,
'year'
,
'custom'
];
const
DatePickerGroup
=
({
onChange
,
format
=
defaultFormat
,
showModels
=
defaultShowModels
,
defaultModel
=
'all'
,
defaultDate
,
value
,
dateModel
,
})
=>
{
const
[
model
,
setModel
]
=
useState
(
defaultModel
);
const
[
dateValue
,
setDateValue
]
=
useState
(()
=>
dateForModel
(
defaultModel
,
defaultDate
));
useEffect
(()
=>
{
if
(
value
||
dateModel
)
{
setModel
(
dateModel
);
setDateValue
(
value
);
}
},
[
value
,
dateModel
]);
// 切换类型
const
changeModel
=
e
=>
{
const
_model
=
e
.
target
.
value
;
const
_dateValue
=
dateForModel
(
_model
);
if
(
!
value
&&
!
dateModel
)
{
setModel
(
_model
);
setDateValue
(
_dateValue
);
if
(
_model
===
'custom'
)
return
;
}
const
_dateFrom
=
_dateValue
&&
_dateValue
.
dateFrom
?
_dateValue
.
dateFrom
.
format
(
format
)
:
''
;
const
_dateTo
=
_dateValue
&&
_dateValue
.
dateTo
?
_dateValue
.
dateTo
.
format
(
format
)
:
''
;
onChange
&&
onChange
(
{
dateFrom
:
_dateFrom
,
dateTo
:
_dateTo
,
},
_model
,
);
};
// 切换时间
const
changeDate
=
(
date
,
dateString
)
=>
{
const
_dateValue
=
dateForModel
(
model
,
date
);
const
_dateFrom
=
_dateValue
&&
_dateValue
.
dateFrom
?
_dateValue
.
dateFrom
.
format
(
format
)
:
''
;
const
_dateTo
=
_dateValue
&&
_dateValue
.
dateTo
?
_dateValue
.
dateTo
.
format
(
format
)
:
''
;
if
(
!
value
&&
!
dateModel
)
{
setDateValue
(
_dateValue
);
}
onChange
&&
onChange
(
{
dateFrom
:
_dateFrom
,
dateTo
:
_dateTo
,
},
model
,
);
};
// 切换范围时间
const
changeRangeDate
=
(
dates
,
dateStrings
)
=>
{
const
_dateValue
=
{
dateFrom
:
dates
?.[
0
],
dateTo
:
dates
?.[
1
]
};
const
_dateFrom
=
_dateValue
&&
_dateValue
.
dateFrom
?
_dateValue
.
dateFrom
.
format
(
format
)
:
''
;
const
_dateTo
=
_dateValue
&&
_dateValue
.
dateTo
?
_dateValue
.
dateTo
.
format
(
format
)
:
''
;
if
(
!
value
&&
!
dateModel
)
{
setDateValue
(
_dateValue
);
}
onChange
&&
onChange
(
{
dateFrom
:
_dateFrom
,
dateTo
:
_dateTo
,
},
model
,
);
};
// 渲染时间选择器
const
renderDatePicker
=
()
=>
{
let
_result
=
null
;
switch
(
model
)
{
case
'day'
:
_result
=
<
DatePicker
onChange
=
{
changeDate
}
value
=
{
dateValue
.
dateFrom
}
/>
;
break
;
case
'week'
:
_result
=
<
DatePicker
picker
=
"week"
onChange
=
{
changeDate
}
value
=
{
dateValue
.
dateFrom
}
/>
;
break
;
case
'month'
:
_result
=
<
DatePicker
picker
=
"month"
onChange
=
{
changeDate
}
value
=
{
dateValue
.
dateFrom
}
/>
;
break
;
case
'quarter'
:
_result
=
<
DatePicker
picker
=
"quarter"
onChange
=
{
changeDate
}
value
=
{
dateValue
.
dateFrom
}
/>
;
break
;
case
'year'
:
_result
=
<
DatePicker
picker
=
"year"
onChange
=
{
changeDate
}
value
=
{
dateValue
.
dateFrom
}
/>
;
break
;
case
'custom'
:
_result
=
(
<
DatePicker
.
RangePicker
onChange
=
{
changeRangeDate
}
value
=
{[
dateValue
.
dateFrom
,
dateValue
.
dateTo
]}
/
>
);
break
;
case
'all'
:
default
:
_result
=
null
;
break
;
}
return
_result
;
};
return
(
<
Space
size
=
{
8
}
>
<
Radio
.
Group
value
=
{
model
}
onChange
=
{
changeModel
}
style
=
{{
whiteSpace
:
'nowrap'
}}
>
{
showModels
.
map
(
item
=>
(
<
Radio
.
Button
value
=
{
item
}
key
=
{
item
}
>
{
textForModel
(
item
)}
<
/Radio.Button
>
))}
<
/Radio.Group
>
{
renderDatePicker
()}
<
/Space
>
);
};
export
{
useDataGroup
};
export
default
DatePickerGroup
;
packages/base-components/BasicReport/src/extra/detailsComponent.js
0 → 100644
View file @
fb2e80f0
/**
** 用来动态加载配置的组件功能函数
** create by ChenLong on 2022/7/28
** @Params: url 功能路径,加载需要的业务组件
** onCancel 从详情组件回到当前功能的函数
** params 其他的必要参数
** 功能路径:src\pages\product\ReportsManage\extra\detailsComponent.js
** 菜单参数列表:*变量名*(变量说明,数据类型,是否必填,取值范围)
**/
import
React
from
'react'
;
import
{
Button
}
from
'antd'
;
const
DetailsComponent
=
({
url
,
onCancel
,
params
})
=>
{
const
BusinessComponent
=
React
.
lazy
(()
=>
import
(
`@/pages/
${
url
}
`
));
return
<
BusinessComponent
onCancel
=
{
onCancel
}
{...
params
}
/>
;
};
export
default
DetailsComponent
;
packages/base-components/BasicReport/src/extra/extraComponents.js
0 → 100644
View file @
fb2e80f0
import
AccountPermissionScan
from
'../../AccountManage/AccountPermissionScan'
;
import
pic
from
'../assets/pic.webp'
;
const
extraComponents
=
{
renderAccount
:
(
props
)
=>
{
return
<
AccountPermissionScan
accountName
=
{
props
.
accountName
}
/>
;
},
returnImage
:
(
data
)
=>
{
return
<
img
width
=
{
200
}
height
=
{
200
}
src
=
{
pic
}
alt
=
{
data
.
alt
}
/>
;
},
default
:
()
=>
<
span
>
若需要使用弹窗功能,请开发或配置功能函数
<
/span
>
};
export
default
extraComponents
;
packages/base-components/BasicReport/src/index.js
0 → 100644
View file @
fb2e80f0
/**
** 轻量化报表通用配置页面
** create by ChenLong on 2022/6/22
** 功能路径:src\pages\product\ReportsManage\ReportsManage.js
** 菜单参数列表:*变量名*(变量说明,数据类型,是否必填,取值范围)
* @Changelog:
* editComponentVisible && detailsComponentVisible 共同作用组件的显示
*
**/
/**
* @Description: 功能描述:参考台账概念,重新定义
* @Tips: 1. 如果需要对字段进行处理,增加功能之类的。需要提前确定返回值的类型.
* 2. 如果要用customerState来控制页面按钮等,需要按照给定的权限值进行配置
* @Params: <ReportManage params={{reportName,pageSize,filterFields,filterValues,state,customerState}}>
* reportName: 报表名称;
* pageSize: 按需配置,默认加载100;
* filterFields: 需要默认加载的过滤条件的field,英文逗号分割,与filterValues一一对应;
* filterValues: 需要默认加载的过滤条件的value,英文逗号分割,与filterFields一一对应;
* state: delete|edit|scan 各种权限;
* customerState: ['filters','sortBtn','exportBtn','editBtn','deleteBtn','pagination'];
* sortFields: '排序字段1,排序字段2,排序字段3'
* @Config:
* 【数值】 [prefix]_d%|0.00|_d%[suffix]|金额 = 前缀|精度|后缀|金额类的数据(千分位),可分别设置。
* 【标签】 split=, 分隔符。
* 【功能】 功能配置框内,配置需要跳转功能所需参数,type、url是必须功能,需要type判断类型,需要通过url去解析加载组件。
* @Type:
* 【文本】普通文本
* 【数值】数值类型的文本
* 【标签】文本渲染成标签,具有不同颜色;
* 【功能】“功能”会在当前页内去展示,会卸载掉列表页,加载功能组件。配置 type + url + 自定义字段 的配置项,自行解析加载即可;
* -------------------- 待需求提出后开发 -----------------
* 【链接】内链外链,点击可跳转;配置规则:配置链接即可;
* 【弹窗】modal弹窗弹出,弹窗内的具体业务自行配置;配置规则:[function_name];[...params];
* ------------------------------------------------------
* @Table:
* 表头:表头需要支持多级表头、合并;
* 列:列支持设置筛选;
* 固定行、固定列:可根据配置生成固定行、列;
* @Control:
* 固定筛选:拥有固定筛选框,根据配置显示可搜索字段;
* 可配置筛选框:根据字段配置,将字段设置成筛选条件,枚举出该字段所有值,提供用户进行选择,然后进行筛选;筛选框具体形态可根据配置字段来渲染;
* 导出功能:各类导出功能按钮;
* 时间筛选框:单表唯一;需要变更,支持多时间参数的筛选
* @State: 参考台账权限
* delete 全部权限
* edit 除删除外的权限
* scan 查看权限
* */
import
React
,
{
useState
,
useEffect
,
useRef
}
from
'react'
;
import
{
Row
,
Button
,
Tag
,
message
,
Form
,
Space
,
Modal
,
Select
,
Table
,
Dropdown
,
Menu
,
Spin
}
from
'antd'
;
import
{
SortAscendingOutlined
,
MinusCircleOutlined
,
ExportOutlined
,
FormOutlined
,
}
from
'@ant-design/icons'
;
import
BasicTable
from
'@wisdom-components/basictable'
;
import
ReturnControlComponent
from
'./components/Control'
;
import
{
reportService
}
from
'./api/index'
;
import
style
from
'./index.less'
;
import
{
exportAccountData
}
from
'./api/service/report'
;
import
extraComponents
from
'./extra/extraComponents'
;
import
DatePickerGroup
from
'./components/DatePickerGroup'
;
import
moment
from
'moment'
;
import
DetailsComponent
from
'./extra/detailsComponent'
;
import
{
handleNumber
,
handleTag
,
handleText
,
handleLink
,
handleWidget
,
handleModal
,
handleDateString
,
handleDateTimeString
,
handlePageSize
,
handleSortFields
,
}
from
'./utils/handlers'
;
import
{
hasMoney
,
isArray
,
isNumber
,
isString
,
returnHandledNumber
}
from
'./utils/utils'
;
import
{
connect
}
from
'react-redux'
;
import
ReportEditForm
from
'./ReportEditForm'
;
const
ControlsType
=
[
'下拉'
,
'多选'
,
'日期'
];
const
fieldSplitStr
=
'-'
;
// fieldGroup用来分割
const
{
Option
}
=
Select
;
const
dateFormat
=
'YYYY-MM-DD'
;
// 日期格式化
const
initDateModel
=
'all'
;
let
timer
=
null
;
const
PERMISSION
=
{
delete
:
[
'filters'
,
'pagination'
,
// 操作条按钮
'sortBtn'
,
'exportBtn'
,
// 操作列
'editBtn'
,
'deleteBtn'
,
],
edit
:
[
'filters'
,
'pagination'
,
'sortBtn'
,
'exportBtn'
,
// 操作列
'editBtn'
,
],
scan
:
[
'filters'
,
'pagination'
,
],
};
const
BasicReport
=
(
props
)
=>
{
const
{
reportName
,
pageSize
,
filterFields
,
filterValues
,
state
,
customerState
,
sortFields
}
=
props
.
params
;
const
permission
=
customerState
&&
isArray
(
customerState
)
?
customerState
:
PERMISSION
[(
state
||
'delete'
)];
const
tableWrapperRef
=
useRef
();
const
controlRef
=
useRef
();
if
(
!
reportName
)
return
<
div
className
=
{
style
.
lackParams
}
>
未配置
reportName
,请完善配置并重新登陆后查看页面!
<
/div>
;
const
[
tableStruct
,
setTableStruct
]
=
useState
([]);
// 临时使用,看后续是否需要保留
const
[
columns
,
setColumns
]
=
useState
([]);
// 表头设置
const
[
tableData
,
setTableData
]
=
useState
([]);
// 表数据
const
[
pagination
,
setPagination
]
=
useState
({
current
:
1
,
total
:
0
,
pageSize
:
handlePageSize
(
pageSize
)
||
100
,
pageSizeOptions
:
[...
new
Set
([
20
,
50
,
100
].
concat
(
handlePageSize
(
pageSize
)))].
filter
(
item
=>
Number
(
item
)).
sort
((
a
,
b
)
=>
Number
(
a
)
-
Number
(
b
)),
showQuickJumper
:
true
,
showSizeChanger
:
true
,
onShowSizeChange
:
(
current
,
size
)
=>
{
let
_pagination
=
{
...
pagination
};
_pagination
.
current
=
current
;
_pagination
.
pageSize
=
size
;
setPagination
(
_pagination
);
getData
(
false
,
_pagination
);
},
onChange
:
(
current
,
size
)
=>
{
let
_pagination
=
{
...
pagination
};
_pagination
.
current
=
current
;
_pagination
.
pageSize
=
size
;
setPagination
(
_pagination
);
getData
(
false
,
_pagination
);
},
});
const
[
controls
,
setControls
]
=
useState
([]);
// 用来存储操作控件
const
[
searchContent
,
setSearchContent
]
=
useState
(
''
);
// 搜索框内的值
const
[
searchPlaceholder
,
setSearchPlaceholder
]
=
useState
([]);
// 搜索框的placeholder
const
[
filterObject
,
setFilterObject
]
=
useState
({});
// 存控制条中,选了筛选条件的值
const
[
modalVisible
,
setModalVisible
]
=
useState
(
false
);
const
[
allSortFields
,
setAllSortFields
]
=
useState
([]);
// 设置所有列表
const
[
selectedSortFields
,
setSelectedSortFields
]
=
useState
([{
label
:
'主要排序'
,
value
:
''
,
sort
:
'asc'
,
}]);
const
[
summaryArray
,
setSummaryArray
]
=
useState
([]);
// 总结栏,包括小计、总计
const
[
tableY
,
setTableY
]
=
useState
(
500
);
const
[
tableX
,
setTableX
]
=
useState
(
1820
);
const
[
listHeight
,
setListHeight
]
=
useState
(
0
);
const
[
tableHeaderLevel
,
setTableHeaderLevel
]
=
useState
(
null
);
const
[
exportLoading
,
setExportLoading
]
=
useState
(
false
);
const
[
extraModal
,
setExtraModal
]
=
useState
(
false
);
const
[
hasTotal
,
setHasTotal
]
=
useState
(
false
);
const
[
hasSinglePage
,
setHasSinglePage
]
=
useState
(
false
);
const
[
tableLoading
,
setTableLoading
]
=
useState
(
false
);
const
[
mergeObject
,
setMergeObject
]
=
useState
({});
// const
const
[
timeFrom
,
setTimeFrom
]
=
useState
(
moment
()
.
startOf
(
initDateModel
)
.
format
(
dateFormat
),
);
const
[
timeTo
,
setTimeTo
]
=
useState
(
moment
()
.
endOf
(
initDateModel
)
.
format
(
dateFormat
),
);
const
[
extra
,
setExtra
]
=
useState
(
<><
/>
)
;
const
[
sortModalVisible
,
setSortModalVisible
]
=
useState
(
false
);
const
[
currentReportId
,
setCurrentReportId
]
=
useState
(
null
);
const
[
hasDatePicker
,
setHasDatePicker
]
=
useState
(
''
);
const
[
defaultDateConfig
,
setDefaultDateConfig
]
=
useState
({
defaultModel
:
'year'
,
defaultDate
:
null
,
});
const
[
dateModel
,
setDateMode
]
=
useState
(
'all'
);
// const [detailsComponent, setDetailsComponent] = useState(<></>); // 详情组件
const
[
detailsComponentVisible
,
setDetailsComponentVisible
]
=
useState
(
false
);
// 是否显示详情组件
const
[
editComponentVisible
,
setEditComponentVisible
]
=
useState
(
false
);
// 是否显示编辑组件
const
[
currentData
,
setCurrentData
]
=
useState
({});
const
[
detailConfig
,
setDetailConfig
]
=
useState
({
url
:
''
,
type
:
''
,
params
:
{}
});
const
[
controlsHeight
,
setControlsHeight
]
=
useState
(
44
);
const
menu
=
()
=>
{
const
_item
=
[
{
label
:
(
<
Button
size
=
'middle'
loading
=
{
exportLoading
}
type
=
'text'
onClick
=
{()
=>
exportModule
(
'pdf'
,
'pdf'
)}
icon
=
{
<
ExportOutlined
/>
}
>
导出
pdf
<
/Button
>
),
key
:
'exportPdf'
,
},
{
label
:
(
<
Button
size
=
'middle'
loading
=
{
exportLoading
}
type
=
'text'
onClick
=
{()
=>
exportModule
(
'excel'
,
'xls'
)}
icon
=
{
<
ExportOutlined
/>
}
>
导出
Excel
<
/Button
>
),
key
:
'exportExcel'
,
},
];
return
<
Menu
items
=
{
_item
}
/>
;
};
const
exportModule
=
(
type
,
extension
)
=>
{
setExportLoading
(
true
);
exportAccountData
({
responseType
:
'blob'
},
{
exportType
:
type
},
{
reportName
,
pageIndex
:
0
,
pageSize
:
0
,
sortFields
:
''
,
content
:
''
,
filters
:
[
{
fieldAlias
:
''
,
fieldValue
:
''
,
},
],
})
.
then
(
res
=>
{
if
(
res
&&
res
.
code
===
-
1
)
return
message
.
error
(
res
.
msg
);
const
url
=
window
.
URL
.
createObjectURL
(
new
Blob
([
res
],
{
type
:
'application/octet-stream;charset=UTF-8'
}),
);
const
a
=
document
.
createElement
(
'a'
);
a
.
href
=
url
;
a
.
target
=
'_blank'
;
a
.
download
=
`
${
reportName
}${
moment
().
format
(
'YYYY-MM-DD-HH-mm-ss'
).
replaceAll
(
'-'
,
''
)}
.`
+
extension
;
a
.
click
();
a
.
remove
();
setExportLoading
(
false
);
})
.
catch
(
err
=>
{
setExportLoading
(
false
);
});
};
const
searchData
=
(
e
)
=>
{
getData
(
false
,
pagination
);
};
const
controlSelectChange
=
(
fieldAlias
,
e
)
=>
{
let
_filterArray
=
{
...
filterObject
};
_filterArray
[
fieldAlias
]
=
e
;
setFilterObject
(
_filterArray
);
};
const
searchInputChange
=
(
e
)
=>
{
setSearchContent
(
e
.
target
.
value
);
};
const
setConfig
=
(
config
,
summary
,
data
)
=>
{
getControlsBarConfig
(
config
);
getTableSummaryConfig
(
config
,
summary
);
getTableLevel
(
config
);
};
const
addFilterAndSearchParams
=
(
data
)
=>
{
let
_data
=
{
...
data
};
// 搜索框是否有值
if
(
searchContent
)
_data
.
content
=
searchContent
;
// filterObject是存起来的控制栏的过滤条件
let
_filters
=
Object
.
keys
(
filterObject
).
filter
(
key
=>
{
let
_value
=
filterObject
[
key
];
return
(
isString
(
_value
)
&&
_value
)
||
(
isArray
(
_value
)
&&
_value
.
length
);
}).
map
(
key
=>
{
let
_value
=
filterObject
[
key
];
if
(
isString
(
_value
)
&&
_value
)
return
{
fieldAlias
:
key
,
fieldValue
:
_value
,
};
if
(
isArray
(
_value
)
&&
_value
.
length
)
return
{
fieldAlias
:
key
,
fieldValue
:
_value
.
join
(
','
),
};
return
false
;
});
// 加上时间过滤参数
if
(
dateModel
!==
'all'
&&
hasDatePicker
&&
timeFrom
&&
timeTo
)
{
_filters
.
push
({
fieldAlias
:
hasDatePicker
,
fieldValue
:
`
${
timeFrom
}
00:00:00,
${
timeTo
}
23:59:59`
,
});
}
// 合并手动传入的filters
if
(
filterFields
)
{
let
_customerFilterArray
=
filterFields
.
split
(
','
);
let
_customerValueArray
=
filterValues
.
split
(
','
);
_customerFilterArray
.
forEach
((
item
,
index
)
=>
{
_filters
.
push
({
fieldAlias
:
item
,
fieldValue
:
_customerValueArray
[
index
]
||
''
,
});
});
}
// 并入 _data
if
(
_filters
.
length
)
_data
.
filters
=
_filters
;
return
_data
;
};
// 排序字符串处理成数组
const
handleSortString
=
(
sortString
)
=>
{
// selectedSortFields
let
_sortStringArray
=
sortString
.
split
(
','
).
map
((
item
,
index
)
=>
{
let
_item
=
item
.
split
(
' '
);
if
(
index
===
0
)
{
return
{
label
:
'主要排序'
,
value
:
_item
[
0
].
replace
(
/
\[
|
\]
/g
,
''
),
sort
:
_item
[
1
],
};
}
else
{
return
{
label
:
'次要排序'
,
value
:
_item
[
0
].
replace
(
/
\[
|
\]
/g
,
''
),
sort
:
_item
[
1
],
};
}
});
setSelectedSortFields
(
_sortStringArray
);
};
/**
* @Description: 根据是否向下合并处理数据,返回合并的key的数组
* */
const
returnMergeArray
=
(
config
)
=>
{
return
config
.
filter
(
item
=>
item
.
isMerge
).
map
(
item
=>
item
.
fieldAlias
);
};
/**
* @Description: 根据配置和数据,计算出该合并的字段和每一行是否合并
* */
const
handleDataToGetRowSpanArray
=
(
config
,
data
)
=>
{
let
_arr
=
returnMergeArray
(
config
);
let
_merge
=
{};
// _merge:{爱好:[[0,3],[3,5]]}
_arr
.
forEach
(
key
=>
{
_merge
[
key
]
=
{};
let
_currentIndex
=
0
;
data
.
forEach
((
item
,
index
)
=>
{
if
(
index
>
0
)
{
if
(
item
[
key
]
===
data
[
index
-
1
][
key
])
{
_merge
[
key
][
_currentIndex
]
+=
1
;
_merge
[
key
][
index
]
=
0
;
}
else
{
_currentIndex
=
index
;
_merge
[
key
][
index
]
=
1
;
}
}
else
{
_merge
[
key
][
0
]
=
1
;
}
});
});
return
_merge
;
};
const
getData
=
(
isInit
,
pagination
)
=>
{
setTableLoading
(
true
);
const
{
pageSize
,
current
}
=
pagination
;
// 搜索条件附加到params
let
_data
=
addFilterAndSearchParams
({
reportName
:
reportName
,
pageIndex
:
current
,
pageSize
:
pageSize
,
});
// sortFields
reportService
.
getReportInfo
(
_data
).
then
(
res
=>
{
if
(
res
.
code
===
0
)
{
let
_reportDetails
=
res
.
data
.
reportDetails
;
let
_statisticalValues
=
res
.
data
.
statisticalValues
;
let
_tableData
=
res
.
data
.
data
.
list
;
let
_sortString
=
res
.
data
.
sortString
;
if
(
isInit
)
{
setConfig
(
_reportDetails
,
_statisticalValues
,
_tableData
);
}
getTableHeaderConfig
(
_reportDetails
,
_tableData
);
let
_pagination
=
{
...
pagination
};
_pagination
.
total
=
res
.
data
.
data
.
totalCount
;
setPagination
(
_pagination
);
setTableData
(
_tableData
);
// 处理排序字段
handleSortString
(
_sortString
);
if
(
_tableData
)
{
setSortModalVisible
(
true
);
setCurrentReportId
(
_reportDetails
[
0
]?.
reportId
);
}
else
{
setSortModalVisible
(
false
);
setCurrentReportId
(
null
);
}
}
else
{
setSortModalVisible
(
false
);
setCurrentReportId
(
null
);
message
.
error
(
'未能查询到报表数据!'
);
let
_pagination
=
{
...
pagination
};
_pagination
.
total
=
0
;
_pagination
.
current
=
1
;
setPagination
(
_pagination
);
setTableData
([]);
}
setTableLoading
(
false
);
}).
catch
(
err
=>
{
console
.
log
(
err
);
setTableLoading
(
false
);
});
};
/**
* @Description: 在配置项中,isFilter: true 用来渲染控制框;filterRule: 下拉/文本/多选
* */
const
getControlsBarConfig
=
(
config
)
=>
{
let
_data
=
config
.
filter
(
item
=>
item
.
isFilter
);
let
_searchPlaceholder
=
[];
_data
.
filter
(
item
=>
item
.
filterRule
===
'文本'
).
forEach
(
item
=>
_searchPlaceholder
.
push
(
item
.
fieldAlias
));
setSearchPlaceholder
(
_searchPlaceholder
);
let
_controls
=
_data
.
filter
(
item
=>
ControlsType
.
includes
(
item
.
filterRule
));
setControls
(
_controls
);
handleDate
(
_controls
);
};
const
getTableHeaderConfig
=
(
config
,
data
)
=>
{
setTableStruct
(
config
);
setColumns
(
returnColumn
(
config
,
data
));
setAllSortFields
(
returnSortFields
(
config
));
};
const
getTableSummaryConfig
=
(
config
,
summary
)
=>
{
if
(
summary
.
length
===
0
)
{
setSummaryArray
([]);
return
false
;
}
let
_summaryConfig
=
{};
let
_configLength
=
config
.
length
;
// 需要判断
// 合并列
let
_colSpan
=
-
1
;
let
_index
=
0
;
config
.
filter
(
item
=>
item
.
isShow
).
forEach
((
item
,
index
)
=>
{
if
(
item
.
isStatistics
)
{
_index
+=
1
;
_colSpan
=
-
1
;
_summaryConfig
[
item
.
fieldAlias
]
=
{
fieldName
:
item
.
fieldAlias
,
index
,
alignType
:
item
.
alignType
,
type
:
item
.
statisticsRule
,
isMoney
:
item
.
type
===
'数值'
&&
!!
hasMoney
(
item
.
configItems
),
configItems
:
item
.
configItems
,
};
}
else
{
let
_name
=
`空值行
${
_index
}
`
;
if
(
_colSpan
===
-
1
)
{
_colSpan
=
1
;
}
else
{
_colSpan
+=
1
;
}
_summaryConfig
[
_name
]
=
{
fieldName
:
_name
,
colSpan
:
_colSpan
,
};
}
});
summary
.
forEach
(
item
=>
{
switch
(
item
.
totalType
)
{
case
'全部'
:
setHasTotal
(
true
);
break
;
case
'单页'
:
setHasSinglePage
(
true
);
break
;
default
:
break
;
}
if
(
_summaryConfig
[
item
.
fieldName
])
{
_summaryConfig
[
item
.
fieldName
][
item
.
totalType
]
=
item
.
fieldValue
;
}
});
// 增加操作列,总结栏最后一个单元格需要延伸一格
let
_sumArr
=
Object
.
values
(
_summaryConfig
);
if
(
_sumArr
&&
_sumArr
.
length
)
_sumArr
=
_sumArr
.
map
((
item
,
index
)
=>
{
let
_item
=
{
...
item
};
if
(
index
===
_sumArr
.
length
-
1
)
_item
.
colSpan
+=
1
;
return
_item
;
});
setSummaryArray
(
_sumArr
);
};
const
changeDate
=
({
dateFrom
,
dateTo
},
mode
)
=>
{
setTimeFrom
(
dateFrom
);
setTimeTo
(
dateTo
);
setDateMode
(
mode
);
};
const
mapHandleType
=
(
type
)
=>
{
const
_map
=
{
文本
:
handleText
,
数值
:
handleNumber
,
标签
:
handleTag
,
链接
:
handleLink
,
功能
:
handleWidget
,
弹窗
:
handleModal
,
日期
:
handleDateString
,
日期时间
:
handleDateTimeString
,
};
return
_map
[
type
]
||
_map
[
'文本'
];
};
const
returnSortFields
=
(
data
)
=>
{
return
data
.
map
(
item
=>
item
.
fieldAlias
);
};
// 处理表格数据,生成表头
const
returnColumn
=
(
config
,
data
)
=>
{
//0. 常规数据
//1. 合并表头;
//2. 四类形态的渲染处理;
//3. 多列表头排序;剔除掉原有图标,需要自己实现排序的按钮
let
_config
=
[...
config
].
filter
(
item
=>
item
.
isShow
);
function
dataStruct
(
keyArray
,
dataIndex
,
obj
,
dataObj
)
{
if
(
dataIndex
<
keyArray
.
length
-
1
)
{
if
(
!
obj
[
keyArray
[
dataIndex
]])
{
obj
[
keyArray
[
dataIndex
]]
=
{};
}
let
_dataIndex
=
dataIndex
+
1
;
dataStruct
(
keyArray
,
_dataIndex
,
obj
[
keyArray
[
dataIndex
]],
dataObj
);
}
else
if
(
dataIndex
===
keyArray
.
length
-
1
)
{
obj
[
keyArray
[
dataIndex
]]
=
dataObj
;
}
}
let
_tempObj
=
{};
let
_fieldAliasArray
=
handleDataToGetRowSpanArray
(
_config
,
data
);
// 需要向下合并的字段
_config
.
forEach
(
item
=>
{
let
_item
=
{
title
:
item
.
fieldAlias
,
dataIndex
:
item
.
fieldAlias
,
key
:
item
.
fieldAlias
,
ellipsis
:
true
,
onCell
:
(
record
,
rowIndex
)
=>
{
// console.log('Record: ', record); // record是这条记录,index是rowIndex
// 1. 如果该字段是需要向下合并的,则进入判断
let
_obj
=
{};
if
(
_fieldAliasArray
[
item
.
fieldAlias
])
{
_obj
.
rowSpan
=
_fieldAliasArray
[
item
.
fieldAlias
][
rowIndex
];
}
return
_obj
;
},
render
:
(
value
,
record
)
=>
{
// 文本、标签、链接、数值
// @params: item 当前的config数据,提供该字段的各类配置
// value 当前单元格的值
// record 点击单元格的整行数据
let
rest
=
[];
if
(
item
.
type
===
'功能'
)
{
/* rest = {
showComponent: setDetailsComponentVisible,
setDetailsConfig: setDetailConfig,
}; */
rest
=
[
setDetailsComponentVisible
,
setDetailConfig
];
}
else
if
(
item
.
type
===
'弹窗'
)
{
/* rest = {
showModal: setModalVisible,
setExtra: setExtra,
};*/
rest
=
[
setModalVisible
,
setExtra
];
}
return
mapHandleType
(
item
.
type
)(
item
,
value
||
''
,
record
,
...
rest
);
},
};
_item
.
width
=
item
.
columnWidth
||
200
;
// 列宽,不设置时默认给200;
if
(
item
.
fixedColumn
)
_item
.
fixed
=
item
.
fixedColumn
;
// 固定位置
_item
.
align
=
item
.
alignType
||
'left'
;
// 单元格内对齐方式
let
_keyArray
=
(
item
.
fieldGroup
||
item
.
fieldAlias
||
item
.
fieldName
).
split
(
fieldSplitStr
);
// 自定义排序
let
_sortFields
=
handleSortFields
(
sortFields
);
if
(
_sortFields
.
includes
(
item
.
fieldAlias
))
{
_item
.
sorter
=
true
;
}
dataStruct
(
_keyArray
,
0
,
_tempObj
,
_item
);
return
_item
;
});
let
_tempArray
=
[];
function
handleObject2Array
(
obj
,
arr
)
{
Object
.
keys
(
obj
).
forEach
((
key
,
index
)
=>
{
if
(
obj
[
key
].
title
&&
obj
[
key
].
title
===
key
)
{
arr
.
push
(
obj
[
key
]);
}
else
{
arr
.
push
({
title
:
key
,
children
:
[]
});
handleObject2Array
(
obj
[
key
],
arr
[
index
].
children
);
}
});
}
handleObject2Array
(
_tempObj
,
_tempArray
);
// 增加序号
_tempArray
.
unshift
({
title
:
'序号'
,
dataIndex
:
'r'
,
key
:
'r'
,
width
:
60
,
fixed
:
'left'
,
});
// 增加操作列
if
(
permission
.
includes
(
'editBtn'
)
||
permission
.
includes
(
'deleteBtn'
))
{
_tempArray
.
push
({
title
:
'操作'
,
width
:
60
,
fixed
:
'right'
,
render
:
(
text
,
record
)
=>
{
return
<
Space
className
=
{
style
.
handleColumnWrapper
}
>
{
permission
.
includes
(
'editBtn'
)
?
<
FormOutlined
className
=
{
style
.
editButton
}
onClick
=
{()
=>
{
setEditComponentVisible
(
true
);
setCurrentData
(
record
);
}}
/> : '
'
}
{
/* {
permission.includes('deleteBtn') ?
<DeleteOutlined disabled className={style.deleteButton} onClick={() => {
Modal.confirm({
content: '你确定要删除改数据吗?',
onOK: () => message.error('您无法删除数据!'),
});
}} /> : ''
}*/
}
<
/Space>
;
},
});
}
// 统计宽度
let
_x
=
_tempArray
.
reduce
((
final
,
curr
)
=>
{
return
final
+=
curr
.
width
;
},
0
);
setTableX
(
_x
);
return
_tempArray
;
};
const
changeSortField
=
(
value
,
index
,
key
)
=>
{
let
_selectedSortFields
=
[...
selectedSortFields
];
_selectedSortFields
[
index
][
key
]
=
value
;
setSelectedSortFields
(
_selectedSortFields
);
};
const
addOtherSortFields
=
()
=>
{
let
_selectedSortFields
=
[...
selectedSortFields
];
_selectedSortFields
.
push
({
label
:
'次要排序'
,
value
:
''
,
sort
:
'asc'
,
});
setSelectedSortFields
(
_selectedSortFields
);
};
const
deleteSortField
=
(
index
)
=>
{
let
_selectedSortFields
=
[...
selectedSortFields
];
_selectedSortFields
.
splice
(
index
,
1
);
setSelectedSortFields
(
_selectedSortFields
);
};
const
setTableHeight
=
()
=>
{
if
(
!
tableWrapperRef
.
current
)
return
;
const
clientHeight
=
tableWrapperRef
.
current
?.
clientHeight
||
0
;
const
clientWidth
=
tableWrapperRef
.
current
?.
clientWidth
||
0
;
const
_height
=
controlRef
.
current
?.
clientHeight
;
// 控制条的高度
const
paginationHeight
=
75
;
// 分页部分的高度
const
tableHeaderHeight
=
tableHeaderLevel
*
40
;
// 表头高度
const
summaryHeight
=
summaryArray
.
length
?
40
*
(
Number
(
hasTotal
)
+
Number
(
hasSinglePage
))
:
0
;
// 总结栏的高度
const
_minus
=
clientHeight
-
_height
-
16
-
4
-
tableHeaderHeight
-
paginationHeight
-
summaryHeight
-
10
;
setListHeight
(
clientHeight
-
_height
-
paginationHeight
-
4
-
6
-
16
-
2
);
setTableY
(
_minus
);
};
const
getTableLevel
=
(
config
)
=>
{
let
_level
=
config
.
reduce
((
final
,
curr
)
=>
{
return
final
=
curr
.
level
>
final
?
curr
.
level
:
final
;
},
1
)
||
1
;
setTableHeaderLevel
(
_level
);
};
const
saveReportListSortFields
=
(
callback
)
=>
{
reportService
.
saveReportListSortFields
({
reportId
:
currentReportId
,
sortFields
:
selectedSortFields
.
filter
(
item
=>
item
.
value
).
map
(
item
=>
({
fieldAlias
:
item
.
value
,
sortType
:
item
.
sort
,
})),
}).
then
(
res
=>
{
if
(
res
.
code
===
0
)
{
message
.
success
(
'排序保存成功!'
);
callback
();
}
else
{
message
.
error
(
res
.
msg
);
}
});
};
/**
* @Description: 判断是否存在【时间】类型的选择,并返回组件
* */
const
handleDate
=
(
obj
)
=>
{
let
_typeObj
=
obj
.
find
(
item
=>
item
.
filterRule
===
'日期'
);
setHasDatePicker
(
_typeObj
?
_typeObj
.
fieldAlias
:
''
);
const
_configItems
=
_typeObj
.
configItems
.
split
(
'|'
);
let
_defaultDate
=
_configItems
.
find
(
item
=>
item
.
includes
(
'defaultDate='
))?.
replace
(
'defaultDate='
,
''
)?.
split
(
','
);
if
(
_defaultDate
&&
_defaultDate
.
length
>
1
)
{
_defaultDate
=
{
dateFrom
:
moment
(
_defaultDate
[
0
]),
dateTo
:
moment
(
_defaultDate
[
1
])
};
}
else
if
(
_defaultDate
&&
_defaultDate
.
length
===
1
)
{
_defaultDate
=
{
dateFrom
:
moment
(
_defaultDate
[
0
]),
dateTo
:
moment
(
_defaultDate
[
0
])
};
}
else
{
_defaultDate
=
{
dateFrom
:
moment
(),
dateTo
:
moment
()
};
}
setDefaultDateConfig
({
defaultDate
:
_defaultDate
?.
dateFrom
,
defaultModel
:
_configItems
.
find
(
item
=>
item
.
includes
(
'defaultModel='
))?.
replace
(
'defaultModel='
,
''
)
||
'year'
,
});
};
useEffect
(()
=>
{
getData
(
true
,
pagination
);
},
[]);
useEffect
(()
=>
{
if
(
tableHeaderLevel
)
setTableHeight
();
},
[
tableHeaderLevel
]);
useEffect
(()
=>
{
getData
(
false
,
pagination
);
},
[
timeFrom
,
timeTo
,
filterObject
]);
useEffect
(()
=>
{
function
getRefHeight
()
{
if
(
timer
)
clearTimeout
(
timer
);
timer
=
setTimeout
(()
=>
{
let
_height
=
controlRef
?.
current
.
clientHeight
;
setControlsHeight
(
_height
);
},
100
);
}
window
.
addEventListener
(
'resize'
,
getRefHeight
);
return
()
=>
window
.
removeEventListener
(
'resize'
,
getRefHeight
);
});
return
<
div
className
=
{
style
.
reportManage
}
ref
=
{
tableWrapperRef
}
>
{
/* 预留容器,提供给点击后的功能显示 */
}
{
detailsComponentVisible
?
<
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
}
>
{
/*时间搜索控件,确保时间搜索控件在第一个,单独匹配*/
}
{
hasDatePicker
&&
defaultDateConfig
.
defaultDate
!==
null
&&
permission
.
includes
(
'filters'
)
?
<
DatePickerGroup
showModels
=
{[
'all'
,
'month'
,
'quarter'
,
'year'
,
'custom'
]}
onChange
=
{
changeDate
}
format
=
{
dateFormat
}
defaultModel
=
{
defaultDateConfig
.
defaultModel
}
defaultDate
=
{
defaultDateConfig
.
defaultDate
}
/> : '
'
}
{
controls
&&
controls
.
length
&&
permission
.
includes
(
'filters'
)
?
controls
.
filter
(
control
=>
[
'下拉'
,
'多选'
].
includes
(
control
.
filterRule
)).
map
(
control
=>
{
return
<
Form
.
Item
label
=
{
control
.
fieldAlias
}
key
=
{
control
.
fieldAlias
}
>
<
ReturnControlComponent
style
=
{{
width
:
240
}}
type
=
{
control
.
filterRule
}
reportName
=
{
reportName
}
fieldAlias
=
{
control
.
fieldAlias
}
configItems
=
{
control
.
configItems
}
onChange
=
{(
e
)
=>
controlSelectChange
(
control
.
fieldAlias
,
e
)}
/
>
<
/Form.Item>
;
})
:
''
}
{
permission
.
includes
(
'filters'
)
?
<
Form
.
Item
label
=
'快速索引'
key
=
{
'快速搜索控件'
}
>
<
ReturnControlComponent
placeholder
=
{
`请输入
${
searchPlaceholder
.
length
?
searchPlaceholder
.
join
(
','
)
:
'关键字'
}
搜索`
}
style
=
{{
width
:
240
}}
type
=
{
'文本'
}
onChange
=
{(
e
)
=>
{
searchInputChange
(
e
);
}}
onSearch
=
{
searchData
}
/
>
<
/Form.Item> : '
'
}
<
/Space
>
{
permission
.
includes
(
'sortBtn'
)
?
<
div
style
=
{{
width
:
200
,
textAlign
:
'end'
}}
>
<
Space
size
=
{
8
}
nowrap
=
{
true
}
>
{
sortModalVisible
&&
permission
.
includes
(
'sortBtn'
)
?
<
Form
.
Item
>
<
Button
type
=
{
'primary'
}
title
=
{
'自定义排序'
}
icon
=
{
<
SortAscendingOutlined
/>
}
onClick
=
{()
=>
setModalVisible
(
true
)}
>
排序
<
/Button
>
<
/Form.Item> : '
'
}
{
permission
.
includes
(
'exportBtn'
)
?
<
Form
.
Item
>
<
Dropdown
.
Button
style
=
{{
float
:
'right'
}}
overlay
=
{
menu
}
>
导出
<
/Dropdown.Button
>
<
/Form.Item> : '
'
}
<
/Space
>
<
/div> : '
'
}
<
/Row> : '
'
}
<
div
className
=
{
style
.
tableContent
}
style
=
{{
height
:
`calc(100% -
${
controlsHeight
||
0
}
px)`
}}
>
{
columns
&&
columns
.
length
?
<
BasicTable
rowKey
=
{
'Key'
}
bordered
loading
=
{
tableLoading
}
dataSource
=
{
tableData
}
columns
=
{
columns
}
onChange
=
{(
pagination
,
filters
,
sorter
,
extra
)
=>
{
console
.
log
(
sorter
)
}}
pagination
=
{
permission
.
includes
(
'pagination'
)
?
pagination
:
false
}
// 237是内置图片高度
scroll
=
{{
y
:
(
tableData
&&
tableData
.
length
)
?
`calc(100% - 44px)`
:
237
,
x
:
tableX
}}
summary
=
{(
pageData
)
=>
{
if
(
summaryArray
.
length
&&
tableData
&&
tableData
.
length
)
return
<
Table
.
Summary
fixed
>
<
Table
.
Summary
.
Row
>
{
hasSinglePage
?
summaryArray
.
map
((
item
,
index
)
=>
{
if
(
item
.
fieldName
===
'空值行0'
)
{
return
<
Table
.
Summary
.
Cell
key
=
{
`summary_
${
index
}
`
}
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
key
=
{
`summary_
${
index
}
`
}
index
=
{
0
}
colSpan
=
{
item
.
colSpan
}
/>
;
}
else
{
return
<
Table
.
Summary
.
Cell
key
=
{
`summary_
${
index
}
`
}
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
.
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> : '
'
}
<
Modal
title
=
{
'自定义排序字段'
}
visible
=
{
modalVisible
}
onCancel
=
{()
=>
setModalVisible
(
false
)}
footer
=
{
<
div
style
=
{{
display
:
'flex'
,
justifyContent
:
'space-between'
}}
>
<
div
>
<
Button
type
=
{
'link'
}
onClick
=
{()
=>
addOtherSortFields
()}
>
增加次要排序
<
/Button
>
<
/div
>
<
div
>
<
Button
onClick
=
{()
=>
setModalVisible
(
false
)}
>
取消
<
/Button
>
<
Button
type
=
{
'primary'
}
onClick
=
{()
=>
{
saveReportListSortFields
(()
=>
getData
(
false
,
pagination
));
setModalVisible
(
false
);
}}
>
确认
<
/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
>
<
MinusCircleOutlined
style
=
{{
color
:
'rgba(0,0,0,.65)'
}}
onClick
=
{()
=>
deleteSortField
(
index
)}
/
>
<
/Form.Item> : '
'
}
<
/Space
>
<
/Row>
)
}
<
/Modal
>
<
Modal
visible
=
{
extraModal
}
onCancel
=
{()
=>
setExtraModal
(
false
)}
destroyOnClose
width
=
{
800
}
>
{
extra
}
<
/Modal
>
{
/* 编辑表单 */
}
<
Modal
title
=
{
'编辑报表信息'
}
visible
=
{
editComponentVisible
}
width
=
{
'80%'
}
footer
=
{
null
}
// visible={true}
onCancel
=
{()
=>
setEditComponentVisible
(
false
)}
>
<
ReportEditForm
reportDetails
=
{
tableStruct
}
reportData
=
{
currentData
}
onCancel
=
{()
=>
{
setEditComponentVisible
(
false
);
getData
(
false
,
pagination
);
}}
reportName
=
{
reportName
}
/
>
<
/Modal
>
<
/div>
;
};
const
mapStateToProps
=
state
=>
{
const
allWidgets
=
state
.
getIn
([
'global'
,
'globalConfig'
,
'allWidgets'
]);
let
_flatWidgets
=
[];
const
flatWidgets
=
(
arr
)
=>
{
arr
.
forEach
(
item
=>
{
if
(
item
.
widgets
&&
item
.
widgets
.
length
)
{
flatWidgets
(
item
.
widgets
);
}
else
{
_flatWidgets
.
push
(
item
);
}
});
};
flatWidgets
(
allWidgets
);
return
{
allWidgets
:
_flatWidgets
,
};
};
export
default
connect
(
mapStateToProps
,
null
)(
BasicReport
);
packages/base-components/BasicReport/src/index.less
0 → 100644
View file @
fb2e80f0
@import "~antd/es/style/themes/default.less";
.lackParams {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.reportManage {
padding: 8px;
height: 100%;
display: flex;
flex-direction: column;
.contentWrapper {
display: flex;
flex-direction: column;
height: 100%;
.controlRow {
background: #ffffff;
padding: 6px;
border-radius: 4px;
margin-bottom: 4px;
display: flex;
flex-direction: row;
}
.tableContent {
flex: 1;
padding: 6px;
background: #ffffff;
.handleColumnWrapper {
display: flex;
justify-content: space-around;
.editButton {
cursor: pointer;
&:hover {
color: rgb(24, 144, 255);
}
}
.deleteButton {
cursor: pointer;
color: rgb(255, 0, 0);
&:hover {
//color: rgb(24, 144, 255);
}
}
}
.spinWrapper {
width: 100vw;
height: 60vh;
display: flex;
justify-content: center;
align-items: center
}
:global {
.@{ant-prefix}-table-container {
height: 100%;
& > .@{ant-prefix}-table-body {
border-bottom: 1px solid #dbe7fb;
border-right: 1px solid #dbe7fb;
}
.@{ant-prefix}-table-body {
flex: 1
}
.@{ant-prefix}-table-summary > table > tfoot > tr > td {
border-right: none;
}
.@{ant-prefix}-table-summary > table > tfoot > tr:not(:last-child) > td {
border-bottom: none;
}
.@{ant-prefix}-table-summary > table > tfoot > tr:last-child > td {
border-bottom: 1px solid #dbe7fb;
}
}
.@{ant-prefix}-basic-table .@{ant-prefix}-pagination {
border-top: none;
}
}
}
}
.link {
cursor: pointer;
&:hover {
//color: #1685FF;
font-weight: bold;
text-decoration: underline;
}
}
:global {
.@{ant-prefix}-form-item {
margin-bottom: 0 !important;
}
}
.prefixOrSuffix {
color: rgba(0, 0, 0, .65);
font-size: 10px;
}
:global {
::-webkit-scrollbar,
*::-webkit-scrollbar {
width: 0px;
height: 6px;
}
::-webkit-scrollbar-track,
*::-webkit-scrollbar-track {
background: #F2F2F2;
border-radius: 10px;
}
::-webkit-scrollbar-thumb,
*::-webkit-scrollbar-thumb {
border-radius: 5px;
background: #DCDCDC;
}
}
}
packages/base-components/BasicReport/src/utils/handlers.js
0 → 100644
View file @
fb2e80f0
import
style
from
'../ReportsManage.less'
;
import
extraComponents
from
'../extra/extraComponents'
;
import
moment
from
'moment'
;
import
{
Tag
}
from
'antd'
;
import
{
hasMoney
,
isNumber
}
from
'./utils'
;
/**
* @Params: config下的数值的configRule结构如下,[{最大值: 10,最小值: 0,颜色:'#AAAAAA'}];
* @business: configRule有值,则按照configRule设置;没有,按照color设置;
* 有最大值,无最小值;['', 1]
* 有最大值,有最小值;[2, 10]
* 有最小值,无最大值;[11,'']
* */
// 链接 功能 弹窗功能待提出需求
// 函数名、属性、...
const
clickLink
=
(
config
)
=>
{
return
window
.
open
(
config
.
configItems
,
'_blank'
);
};
const
handleUrl
=
(
allWidgets
,
config
)
=>
{
};
const
handleConfigUrl
=
(
config
,
record
)
=>
{
let
_configs
=
config
.
configItems
.
split
(
'|'
);
// type = 替换|跳转;
let
_type
=
''
;
//url=project/pandawork/contractDetails/index?ageSize=100&accountName=软件订单台账|contractCode=${订单编号}|company=${分公司}
let
_url
=
''
;
let
_params
=
{};
_configs
.
forEach
(
item
=>
{
if
(
item
.
includes
(
'type='
))
_type
=
item
.
replace
(
'type='
,
''
);
if
(
item
.
includes
(
'url='
))
{
let
_tempUrl
=
item
.
replace
(
'url='
,
''
);
let
_urlArray
=
_tempUrl
.
split
(
'?'
);
if
(
_urlArray
[
1
])
{
_urlArray
[
1
].
split
(
'&'
).
forEach
(
param
=>
{
let
_paramArr
=
param
.
split
(
'='
);
if
(
_paramArr
[
1
]
&&
_paramArr
[
1
].
includes
(
'${'
)
&&
_paramArr
[
1
].
includes
(
'}'
))
{
let
_key
=
_paramArr
[
1
].
replace
(
/
\$\{
|
\}
/g
,
''
);
_params
[
_paramArr
[
0
]]
=
record
[
_key
];
}
else
{
_params
[
_paramArr
[
0
]]
=
_paramArr
[
1
];
}
});
}
_url
=
_urlArray
[
0
];
}
});
return
{
url
:
_url
,
type
:
_type
,
params
:
_params
};
};
const
clickWidget
=
(
config
,
text
,
record
,
showComponents
,
setDetailsConfig
)
=>
{
// 功能跳转接口
// type=替换|url=product/ReportsManage/ReportsSetting?accountName=${ID}&pageSize=100&title=${name}
if
(
!
config
.
configItems
)
return
message
.
error
(
'未配置跳转信息'
);
// setDetailsComponentVisible(true);
showComponents
(
true
);
let
urlConfig
=
handleConfigUrl
(
config
,
record
);
// setDetailConfig(urlConfig);
setDetailsConfig
(
urlConfig
);
};
const
clickModal
=
(
config
,
showModal
,
setExtra
)
=>
{
let
_splitArr
=
config
.
configItems
.
split
(
'&'
);
let
_fn
=
_splitArr
[
0
]
||
'default'
;
_splitArr
.
splice
(
0
,
1
);
let
_data
=
{};
_splitArr
.
forEach
(
item
=>
{
let
_item
=
item
.
split
(
'='
);
_data
[
_item
[
0
]]
=
_item
[
1
];
});
// setExtraModal(true);
showModal
(
true
);
return
setExtra
(
extraComponents
[
_fn
](
_data
));
};
const
returnOpacity
=
(
rgba
)
=>
{
if
(
!
rgba
)
rgba
=
'rgba(0,0,0,.65)'
;
let
_str
=
rgba
.
replace
(
'rgba('
,
''
).
replace
(
')'
,
''
);
let
_splitStr
=
_str
.
split
(
','
);
return
`rgba(
${
_splitStr
[
0
]}
,
${
_splitStr
[
1
]}
,
${
_splitStr
[
2
]}
,.25)`
;
};
export
const
handleNumber
=
(
config
,
number
)
=>
{
let
_color
=
''
;
if
(
number
)
number
=
Number
(
number
);
// 当设置精度后,会被转成字符串
if
(
config
.
numericalConfigs
&&
config
.
numericalConfigs
.
length
)
{
config
.
numericalConfigs
.
forEach
(
item
=>
{
// 接口对于数值类型的返回为null
if
(
!
_color
)
{
let
_max
=
item
.
maxValue
||
''
;
let
_min
=
item
.
minValue
||
''
;
if
(
_max
!==
''
&&
_min
===
''
)
{
_color
=
number
<=
Number
(
_max
)
?
''
:
item
.
color
;
}
else
if
(
_min
!==
''
&&
_max
===
''
)
{
_color
=
number
>
Number
(
_min
)
?
item
.
color
:
''
;
}
else
{
_color
=
number
>
Number
(
_min
)
&&
number
<=
Number
(
_max
)
?
item
.
color
:
''
;
}
}
});
}
else
if
(
config
.
color
)
{
_color
=
config
.
color
;
}
return
number
?
<
span
>
<
span
className
=
{
style
.
prefixOrSuffix
}
style
=
{{
color
:
_color
,
}}
>
{
config
.
prefix
||
''
}
<
/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'}];
* */
export
const
handleTag
=
(
config
,
text
)
=>
{
let
_color
=
''
;
let
_map
=
{};
// 标签需要设置分隔符 2022年7月13日 ChenLong
let
_configItems
=
config
.
configItems
.
split
(
'|'
);
let
_configMap
=
{};
_configItems
.
forEach
(
item
=>
{
let
_arr
=
item
.
split
(
'='
);
_configMap
[
_arr
[
0
]]
=
_arr
[
1
];
});
// 处理label的颜色
if
(
config
.
labelConfigs
&&
config
.
labelConfigs
.
length
)
{
config
.
labelConfigs
.
forEach
(
item
=>
{
_map
[
item
.
labelValue
]
=
item
.
color
;
});
}
_color
=
config
.
color
||
'rgba(0,0,0,.85)'
;
// String(text)为了解决可能存在数值类型的数据需要设置成标签的需求
return
String
(
text
).
split
(
_configMap
[
'分隔符'
]).
map
(
item
=>
<
Tag
color
=
{
_map
[
item
]}
>
{
item
}
<
/Tag>
)
;
/* return String(text).split(_configMap['分隔符']).map(item => <Tag style={{
background: _map[item] || _color,
border: `1px solid ${_map[item]}`,
borderRadius: 4,
color: `rgba(0, 0, 0, .65)`,
}}>{item}</Tag>);*/
};
export
const
handleText
=
(
config
,
text
)
=>
{
return
<
span
style
=
{{
color
:
config
.
color
||
'rgba(0,0,0,.85)'
}}
>
{
text
}
<
/span>
;
};
export
const
handleLink
=
(
config
,
text
)
=>
{
return
<
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
)
=>
{
return
<
span
style
=
{{
color
:
config
.
color
}}
className
=
{
style
.
link
}
onClick
=
{()
=>
clickWidget
(
config
,
text
,
record
,
showComponents
,
setDetailsConfig
)}
>
{
text
}
<
/span>
;
};
export
const
handleModal
=
(
config
,
text
,
showModal
,
setExtra
)
=>
{
return
<
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
)
=>
{
return
text
?
moment
(
text
).
format
(
'YYYY-MM-DD'
)
:
'-'
;
};
// 时刻
export
const
handleDateTimeString
=
(
config
,
text
)
=>
{
return
text
?
moment
(
text
).
format
(
'YYYY-MM-DD HH:mm:ss'
)
:
'-'
;
};
// 处理pageSize
export
const
handlePageSize
=
(
numStr
)
=>
{
return
numStr
&&
isNumber
(
Number
(
numStr
))
?
Number
(
numStr
)
:
false
;
};
// 处理默认排序
export
const
handleSortFields
=
(
sortFields
)
=>
{
return
sortFields
&&
sortFields
.
split
(
','
)
}
packages/base-components/BasicReport/src/utils/utils.js
0 → 100644
View file @
fb2e80f0
const
isObject
=
(
obj
)
=>
{
return
Object
.
prototype
.
toString
.
call
(
obj
)
===
'[object Object]'
;
};
const
isString
=
(
obj
)
=>
{
return
Object
.
prototype
.
toString
.
call
(
obj
)
===
'[object String]'
;
};
const
isNumber
=
(
num
)
=>
{
return
Object
.
prototype
.
toString
.
call
(
num
)
===
'[object Number]'
;
};
const
isArray
=
(
arr
)
=>
{
return
Object
.
prototype
.
toString
.
call
(
arr
)
===
'[object Array]'
;
};
const
hasMoney
=
(
configItems
)
=>
{
if
(
!
configItems
)
return
false
;
let
_items
=
configItems
.
split
(
'|'
);
return
!!
_items
.
find
(
item
=>
item
===
'金额'
);
};
/**
* @Description: 用来在summary中处理数值的配置
* @Params: 参数描述
* @Date: 2022/8/10
* @Author: ChenLong
* */
const
returnHandledNumber
=
(
configItems
,
num
)
=>
{
// 精度、前缀、后缀、倍率
// $_d|_d%|_d*0.0001|金额|0.00
if
(
!
configItems
)
return
num
;
let
_items
=
configItems
.
split
(
'|'
);
/* let prefix = '';
let suffix = '';*/
let
template
=
'_d'
;
let
precision
=
0
;
let
rate
=
1
;
_items
.
forEach
(
item
=>
{
let
_arr
=
[];
if
(
item
.
match
(
/_d
[^\*]
/
))
{
// 后缀
template
=
item
;
}
else
if
(
item
.
match
(
/^_d
\*
/
))
{
// 倍率
let
_rate
=
item
.
replace
(
/_d
\*
/
,
''
);
rate
=
_rate
?
Number
(
_rate
)
:
1
;
}
else
if
(
item
.
match
(
/^0
\.
/
))
{
// 精度
precision
=
item
.
replace
(
'0.'
,
''
).
length
;
}
});
// 可能存在NaN的问题
let
final
=
_items
.
includes
(
'金额'
)
?
Number
((
num
*
rate
).
toFixed
(
precision
)).
toLocaleString
()
:
Number
((
num
*
rate
).
toFixed
(
precision
));
return
template
.
replace
(
/_d/
,
final
);
};
/**
* @Description: 返回configItems内配置的默认值、默认模式等等
* @Params: 参数描述
* @Date: 2022/8/12
* @Author: ChenLong
* @params:
* configItems 报表字段的配置 例如 defaultValue=智慧水务 defaultDateModel=customer|defaultDateValue=2022-01-01,2022-12-31;
* keysArray 所需要返回的值的key的集合,比如你需要获取configItems中的’defaultValue‘,那么keysArray=['defaultValue'];
* @Returns:
* defaultValue 通用参数 默认值
* defaultDateModel 时间参数 默认模式
* defaultDateValue 时间参数 默认时间
* */
const
returnDefaultValueOrConfigs
=
(
configItems
=
''
,
keysArray
=
[])
=>
{
let
_map
=
{};
let
_configItemsArray
=
configItems
.
split
(
'|'
);
keysArray
.
forEach
(
key
=>
{
_map
[
key
]
=
_configItemsArray
.
find
(
item
=>
item
.
includes
(
`
${
key
}
=`
))?.
replace
(
`
${
key
}
=`
,
''
);
});
return
_map
;
};
export
{
isObject
,
isString
,
isNumber
,
hasMoney
,
isArray
,
returnHandledNumber
,
returnDefaultValueOrConfigs
,
};
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment