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
48ac1217
Commit
48ac1217
authored
Dec 22, 2022
by
陈龙
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: 提交报表代码
parent
e7a194d1
Hide whitespace changes
Inline
Side-by-side
Showing
34 changed files
with
6185 additions
and
0 deletions
+6185
-0
CHANGELOG.md
packages/base-components/BasicReport/CHANGELOG.md
+113
-0
package.json
packages/base-components/BasicReport/package.json
+38
-0
BasicReport.md
packages/base-components/BasicReport/src/BasicReport.md
+3
-0
Control.js
...nents/BasicReport/src/ReportsManage/Components/Control.js
+152
-0
CustomerColorPicker.js
...age/Components/customerColorPicker/CustomerColorPicker.js
+30
-0
CustomerColorPicker.less
...e/Components/customerColorPicker/CustomerColorPicker.less
+26
-0
fileUpload.js
...ort/src/ReportsManage/Components/fileUpload/fileUpload.js
+221
-0
fileUpload.less
...t/src/ReportsManage/Components/fileUpload/fileUpload.less
+25
-0
ReportEditForm.js
...omponents/BasicReport/src/ReportsManage/ReportEditForm.js
+237
-0
ReportEditForm.less
...ponents/BasicReport/src/ReportsManage/ReportEditForm.less
+90
-0
ReportsDataSourceSetting.js
...BasicReport/src/ReportsManage/ReportsDataSourceSetting.js
+469
-0
ReportsDataSourceSetting.less
...sicReport/src/ReportsManage/ReportsDataSourceSetting.less
+85
-0
ReportsManage.js
...components/BasicReport/src/ReportsManage/ReportsManage.js
+1400
-0
ReportsManage.less
...mponents/BasicReport/src/ReportsManage/ReportsManage.less
+139
-0
ReportsPermissionDelete.js
.../BasicReport/src/ReportsManage/ReportsPermissionDelete.js
+5
-0
ReportsPermissionScan.js
...ts/BasicReport/src/ReportsManage/ReportsPermissionScan.js
+5
-0
ReportsSetting.js
...omponents/BasicReport/src/ReportsManage/ReportsSetting.js
+1982
-0
ReportsSetting.less
...ponents/BasicReport/src/ReportsManage/ReportsSetting.less
+119
-0
mysql.png
...components/BasicReport/src/ReportsManage/assets/mysql.png
+0
-0
pic.webp
...-components/BasicReport/src/ReportsManage/assets/pic.webp
+0
-0
sqlserver.png
...onents/BasicReport/src/ReportsManage/assets/sqlserver.png
+0
-0
webapi.png
...omponents/BasicReport/src/ReportsManage/assets/webapi.png
+0
-0
detailsComponent.js
...s/BasicReport/src/ReportsManage/extra/detailsComponent.js
+14
-0
extraComponents.js
...ts/BasicReport/src/ReportsManage/extra/extraComponents.js
+13
-0
constant.js
...omponents/BasicReport/src/ReportsManage/utils/constant.js
+32
-0
handlers.js
...omponents/BasicReport/src/ReportsManage/utils/handlers.js
+274
-0
utils.js
...e-components/BasicReport/src/ReportsManage/utils/utils.js
+159
-0
constants.js
packages/base-components/BasicReport/src/api/constants.js
+36
-0
index.js
packages/base-components/BasicReport/src/api/index.js
+63
-0
report.js
...ges/base-components/BasicReport/src/api/service/report.js
+229
-0
workflow.js
...s/base-components/BasicReport/src/api/service/workflow.js
+3
-0
index.js
...nents/BasicReport/src/components/DatePickerGroup/index.js
+198
-0
Basic.tsx
packages/base-components/BasicReport/src/demos/Basic.tsx
+19
-0
index.js
packages/base-components/BasicReport/src/index.js
+6
-0
No files found.
packages/base-components/BasicReport/CHANGELOG.md
0 → 100644
View file @
48ac1217
# Change Log
All notable changes to this project will be documented in this file. See
[
Conventional Commits
](
https://conventionalcommits.org
)
for commit guidelines.
## [1.8.2](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/basicreport@1.8.0...@wisdom-components/basicreport@1.8.2) (2022-12-13)
### Bug Fixes
-
修复函数未引用导致的 bug (
[
3f3eb57
](
https://g.civnet.cn:8443/ReactWeb5/wisdom-components/commits/3f3eb57d01d9d97a0e1c5b836cef09e93d1193b1
)
)
-
修复函数未引用导致的 bug (
[
07038a2
](
https://g.civnet.cn:8443/ReactWeb5/wisdom-components/commits/07038a22afd57b8935ea6cdb6c3fd761f14f3ff0
)
)
## [1.8.1](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/basicreport@1.8.0...@wisdom-components/basicreport@1.8.1) (2022-12-13)
### Bug Fixes
-
修复函数未引用导致的 bug (
[
07038a2
](
https://g.civnet.cn:8443/ReactWeb5/wisdom-components/commits/07038a22afd57b8935ea6cdb6c3fd761f14f3ff0
)
)
# [1.8.0](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/basicreport@1.7.0...@wisdom-components/basicreport@1.8.0) (2022-12-07)
### Features
-
更新轻量化报表 (
[
3985ad9
](
https://g.civnet.cn:8443/ReactWeb5/wisdom-components/commits/3985ad9af1a9d3130ad07eab0cb959a820a73fad
)
)
# [1.7.0](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/basicreport@1.6.0...@wisdom-components/basicreport@1.7.0) (2022-12-07)
### Features
-
更新轻量化报表功能 (
[
d73f0e6
](
https://g.civnet.cn:8443/ReactWeb5/wisdom-components/commits/d73f0e6c84d5633af7cfe3d4bf3c234bcaa8f2c9
)
)
# [1.6.0](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/basicreport@1.5.0...@wisdom-components/basicreport@1.6.0) (2022-09-13)
### Features
-
更新 baiscreport 版本 (
[
fa63f24
](
https://g.civnet.cn:8443/ReactWeb5/wisdom-components/commits/fa63f244ddcc23f4fe11dd78acd8d9fcc8b3cc8a
)
)
-
优化默认筛选值的逻辑,现在可以配置多个筛选值 (
[
62f7fed
](
https://g.civnet.cn:8443/ReactWeb5/wisdom-components/commits/62f7fed834d31526b8fb33868fad905bf45de4fc
)
)
# [1.5.0](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/basicreport@1.4.0...@wisdom-components/basicreport@1.5.0) (2022-09-13)
### Features
-
实现选择器 (
[
9df6ec8
](
https://g.civnet.cn:8443/ReactWeb5/wisdom-components/commits/9df6ec87a429fe9c8d321a6f7bc4a5677b852b7f
)
)
# [1.4.0](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/basicreport@1.3.1...@wisdom-components/basicreport@1.4.0) (2022-09-07)
### Bug Fixes
-
修复组件引入错误 (
[
31facdf
](
https://g.civnet.cn:8443/ReactWeb5/wisdom-components/commits/31facdf92b6200c3ceac31fb549a77faa4a68434
)
)
### Features
-
新增 demo (
[
0ffab69
](
https://g.civnet.cn:8443/ReactWeb5/wisdom-components/commits/0ffab69ab677d377ce861e1ab9205ab8b78464a4
)
)
## [1.3.1](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/basicreport@1.3.0...@wisdom-components/basicreport@1.3.1) (2022-09-06)
### Bug Fixes
-
修复路径错误 (
[
c7d8fa8
](
https://g.civnet.cn:8443/ReactWeb5/wisdom-components/commits/c7d8fa8230f1f47478010e8e1263b1aa46703311
)
)
# [1.3.0](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/basicreport@1.2.3...@wisdom-components/basicreport@1.3.0) (2022-09-05)
### Features
-
新增大量功能 (
[
437dd7c
](
https://g.civnet.cn:8443/ReactWeb5/wisdom-components/commits/437dd7ca8cb83552b88e11585bb9b7040ee6b07e
)
)
## [1.2.3](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/basicreport@1.2.2...@wisdom-components/basicreport@1.2.3) (2022-08-29)
### Bug Fixes
-
兼容日期为 null 的情况 (
[
0ef2dfb
](
https://g.civnet.cn:8443/ReactWeb5/wisdom-components/commits/0ef2dfb65a938134d8ecea589479ccc99c7c7b93
)
)
## [1.2.2](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/basicreport@1.2.1...@wisdom-components/basicreport@1.2.2) (2022-08-18)
### Bug Fixes
-
fix (
[
bc49887
](
https://g.civnet.cn:8443/ReactWeb5/wisdom-components/commits/bc498875cbd3deb3104ff5d61c99cb3c318ba355
)
)
## [1.2.1](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/basicreport@1.2.0...@wisdom-components/basicreport@1.2.1) (2022-08-18)
### Bug Fixes
-
修复数据格式导致的报错;修复路径引入导致的报错 (
[
6014c40
](
https://g.civnet.cn:8443/ReactWeb5/wisdom-components/commits/6014c40b6b19f9060b69e95ce729dcdfc2935521
)
)
# [1.2.0](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/basicreport@1.1.3...@wisdom-components/basicreport@1.2.0) (2022-08-18)
### Features
-
重新处理报表逻辑 (
[
3ebe719
](
https://g.civnet.cn:8443/ReactWeb5/wisdom-components/commits/3ebe71907d0b60988a53c7b641189f748490826b
)
)
## [1.1.3](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/basicreport@1.1.2...@wisdom-components/basicreport@1.1.3) (2022-08-17)
### Bug Fixes
-
重新发布 (
[
2776cf9
](
https://g.civnet.cn:8443/ReactWeb5/wisdom-components/commits/2776cf9dd8f7520a84c00fad5500da38ec42dc8f
)
)
## [1.1.2](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/basicreport@1.1.1...@wisdom-components/basicreport@1.1.2) (2022-08-17)
### Bug Fixes
-
删除无效引用 (
[
372c06f
](
https://g.civnet.cn:8443/ReactWeb5/wisdom-components/commits/372c06f3233ab5e48d6b104addfb6ba95e43d847
)
)
## [1.1.1](https://g.civnet.cn:8443/ReactWeb5/wisdom-components/compare/@wisdom-components/basicreport@1.1.0...@wisdom-components/basicreport@1.1.1) (2022-08-17)
### Bug Fixes
-
修复文件引用错误 (
[
7e486a8
](
https://g.civnet.cn:8443/ReactWeb5/wisdom-components/commits/7e486a8a6c321fd36d89e78975c4e65002f7eaa2
)
)
# 1.1.0 (2022-08-17)
### Features
-
新增报表组件 (
[
561f975
](
https://g.civnet.cn:8443/ReactWeb5/wisdom-components/commits/561f975db85081d678854c94e859406903f71438
)
)
-
新增 BasicReport (
[
fb2e80f
](
https://g.civnet.cn:8443/ReactWeb5/wisdom-components/commits/fb2e80f00b130f48e743de5dd4781913e7ff4c01
)
)
-
增加 package.json (
[
e10973a
](
https://g.civnet.cn:8443/ReactWeb5/wisdom-components/commits/e10973a31059ceab4b2e01dda56fdd54ade270bc
)
)
packages/base-components/BasicReport/package.json
0 → 100644
View file @
48ac1217
{
"name"
:
"@wisdom-components/basicreport"
,
"version"
:
"1.8.2"
,
"description"
:
"> TODO: description"
,
"author"
:
"chenlong <857265978@163.com>"
,
"homepage"
:
""
,
"license"
:
"ISC"
,
"sideEffects"
:
[
"*.less"
],
"module"
:
"es/index.js"
,
"main"
:
"es/index.js"
,
"files"
:
[
"lib"
,
"es"
,
"dist"
],
"directories"
:
{
"lib"
:
"lib"
,
"es"
:
"es"
,
"dist"
:
"dist"
,
"test"
:
"__tests__"
},
"publishConfig"
:
{
"registry"
:
"https://g.civnet.cn:4873/"
},
"repository"
:
{
"type"
:
"git"
,
"url"
:
"https://g.civnet.cn:8443/ReactWeb5/wisdom-components.git"
},
"scripts"
:
{
"test"
:
"echo
\"
Error: run tests from root
\"
&& exit 1"
},
"dependencies"
:
{
"@babel/runtime"
:
"^7.17.9"
,
"@wisdom-components/basictable"
:
"^1.5.25"
}
}
packages/base-components/BasicReport/src/BasicReport.md
0 → 100644
View file @
48ac1217
#### 常规使用
<code
src=
"./demos/Basic.tsx"
>
packages/base-components/BasicReport/src/ReportsManage/Components/Control.js
0 → 100644
View file @
48ac1217
// 文本/下拉/多选/时间
/**
* @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
USER_ID
=
window
.
globalConfig
.
userInfo
.
OID
;
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
,
filterFields
,
filterValues
,
filterObject
,
})
=>
{
const
[
value
,
setValue
]
=
useState
(
''
);
const
[
options
,
setOptions
]
=
useState
([]);
const
defaultConfigs
=
returnDefaultValueOrConfigs
(
configItems
,
[
'defaultValue'
]);
const
{
defaultValue
}
=
defaultConfigs
;
const
getData
=
()
=>
{
reportService
.
getReportFilterValues
({
fieldAlias
,
...
filterObject
,
})
.
then
((
res
)
=>
{
if
(
res
.
code
===
0
)
{
let
_options
=
res
.
data
.
find
((
item
)
=>
item
.
fieldAlias
===
fieldAlias
)
.
filterValues
.
filter
((
item
)
=>
item
.
filterValue
);
if
(
filterValues
&&
filterFields
)
{
let
_filterFields
=
filterFields
.
split
(
'|'
);
let
_filterValues
=
filterValues
.
split
(
'|'
);
let
_index
=
_filterFields
.
findIndex
((
item
)
=>
item
===
fieldAlias
);
if
(
_index
>
-
1
)
{
let
_needToFilterValues
=
_filterValues
[
_index
]?.
split
(
','
)
||
[];
_options
=
_options
.
filter
((
item
)
=>
_needToFilterValues
.
includes
(
item
.
filterValue
));
}
}
setOptions
(
_options
);
}
})
.
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
?
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
,
filterValues
,
filterFields
,
filterObject
,
})
=>
{
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
}
filterFields
=
{
filterFields
}
filterValues
=
{
filterValues
}
filterObject
=
{
filterObject
}
/
>
);
break
;
default
:
break
;
}
return
_component
;
};
export
default
ReturnControlComponent
;
packages/base-components/BasicReport/src/ReportsManage/Components/customerColorPicker/CustomerColorPicker.js
0 → 100644
View file @
48ac1217
/*
** 自定义取色板
** create by ChenLong on 2022/8/23
** 功能路径:src\pages\product\ReportsManage\Components\CustomerColorPicker.js
** 菜单参数列表:*变量名*(变量说明,数据类型,是否必填,取值范围)
**/
import
React
from
'react'
;
import
style
from
'./CustomerColorPicker.less'
;
import
{
tagColors
,
tagBackgroundColors
}
from
'../../utils/constant'
;
import
classnames
from
'classnames'
;
const
CustomerColorPicker
=
(
props
)
=>
{
return
(
<
div
className
=
{
style
.
colorPickerWrapper
}
>
{
tagColors
.
map
((
color
,
index
)
=>
(
<
div
className
=
{
classnames
(
style
.
colorCard
)}
onClick
=
{()
=>
props
.
clickColorPicker
(
tagBackgroundColors
[
index
])}
style
=
{{
color
:
color
,
backgroundColor
:
tagBackgroundColors
[
index
],
}}
>
A
<
/div
>
))}
<
/div
>
);
};
export
default
CustomerColorPicker
;
packages/base-components/BasicReport/src/ReportsManage/Components/customerColorPicker/CustomerColorPicker.less
0 → 100644
View file @
48ac1217
@import '~antd/es/style/themes/default.less';
.colorPickerWrapper {
display: flex;
gap: 5px;
width: 330px;
//height: 40px;
padding: 10px;
background: #ffffff;
border: 1px solid rgba(200, 200, 200, 0.85);
border-radius: 4px;
.colorCard {
display: flex;
flex: 0 0 30px;
align-items: center;
justify-content: center;
height: 30px;
font-size: 14px;
&:hover {
font-weight: bold;
font-size: 16px;
box-shadow: #1685ff;
cursor: pointer;
}
}
}
packages/base-components/BasicReport/src/ReportsManage/Components/fileUpload/fileUpload.js
0 → 100644
View file @
48ac1217
/** @tips: 约定:该控件,获取文件路径字符串或上传了文件(即对应编辑时从接口获取的文件链接和新增时获取的对象),都会将符合要求的对象(上传的文件数据或自行拼接的,必须包含status、type、uid等必要字段)转化为字符串 */
/**
* @description: 合并老版的文件、可预览文件、录音、视频
* @params: 接收参数 renderTo: Recording/Video/File
* @return: {Object} 文件类型返回需要另外处理
* @date: 2021/12/1
* @author: ChenLong
* @待解决问题: 为什么list不直接返回url,而要把file对象变成对象字符串?
*/
/** @tips: 上传业务为:1.通过上传接口,上传文件,获取上传的链接;2.将文件链接存储到服务器,获取存储的地址;3.提交地址 */
/**
* @description: 完成 1.文件名校验;2.编辑界面的文件加载及显示的能力;3.不同类型文件的判断
* @date: 2021/12/2
*/
/**
* @description: 合并图片/可预览图片到文件上传中
* @date: 2021/12/6
*/
/**
* @description: 文件类型单独处理。文件类型返回的是文件对象的字符串,使用JSON.parse解析之后,取url值即可,拼成用逗号分割的字符串即可。这部分修改在入口文件内
* @description: 需要判断值是文件对象的字符串,约定:文件类必须会有 status: 'done'
* @date: 2021/12/8
*/
/** @tips: 裁剪功能在前端框架内无法正常工作,暂不提供裁剪功能 */
// 自定义Form Render组件
import
React
,
{
useState
,
useEffect
}
from
'react'
;
import
{
Upload
,
Button
,
Modal
,
message
}
from
'antd'
;
import
{
UploadOutlined
,
DownloadOutlined
}
from
'@ant-design/icons'
;
import
'./fileUpload.less'
;
import
{
downloadFunc
,
filenameVerification
}
from
'../../utils/utils'
;
import
{
uploadFileUrl
,
downloadFileUrl
}
from
'../../../api/service/workflow'
;
const
videoTypeArray
=
[
'.mp4'
];
const
audioTypeArray
=
[
'.mp4'
];
const
fileTypeArray
=
[];
const
imageTypeArray
=
[
'.bmp'
,
'.gif'
,
'.jpeg'
,
'tiff'
,
'.png'
,
'.svg'
,
'.jpg'
];
const
FileUpload
=
({
value
,
onChange
,
schema
})
=>
{
const
_isRecordingOrVideo
=
[
'Recording'
,
'Video'
,
'Image'
].
includes
(
schema
.
renderTo
);
const
_isVideo
=
schema
.
renderTo
===
'Video'
;
const
_isAudio
=
schema
.
renderTo
===
'Recording'
;
const
_isImage
=
schema
.
renderTo
===
'Image'
;
const
[
previewTitle
,
setPreviewTitle
]
=
useState
(
''
);
const
[
previewVisible
,
setPreviewVisible
]
=
useState
(
false
);
const
[
previewUrl
,
setPreviewUrl
]
=
useState
(
''
);
const
[
showList
,
setShowList
]
=
useState
(
''
);
const
file
=
value
||
schema
.
default
;
const
option
=
{
name
:
'file'
,
action
:
`
${
window
.
location
.
origin
}${
uploadFileUrl
}
`
,
listType
:
_isRecordingOrVideo
?
'picture-card'
:
'picture'
,
withCredentials
:
true
,
beforeUpload
(
file
,
fileList
)
{
/** @tips: 解决提交文件中存在特殊字符的问题 */
let
_continueUpload
=
true
;
let
_msg
=
{
type
:
'success'
,
content
:
'上传成功!'
,
};
fileList
.
forEach
((
item
)
=>
{
let
_msgObject
=
filenameVerification
(
item
);
if
(
_msgObject
.
type
===
'error'
)
{
_continueUpload
=
false
;
_msg
=
{
type
:
'error'
,
content
:
'上传失败!文件名不符合规则!'
,
};
}
});
_msg
.
type
===
'error'
?
message
[
_msg
.
type
](
_msg
.
content
)
:
''
;
return
_continueUpload
;
},
onChange
:
({
file
,
fileList
,
event
})
=>
{
// 检验名字,名字不通过不允许显示
if
(
filenameVerification
(
file
).
type
===
'error'
)
return
false
;
// 返回的链接在file.response内;不设置url,预览图表不可点击
if
(
file
.
status
===
'done'
&&
file
.
response
.
code
===
0
)
{
file
.
url
=
`
${
downloadFileUrl
}
?filePath=
${
file
.
response
.
data
}
`
;
file
.
sourcePath
=
file
.
response
.
data
;
message
.
success
(
'上传成功!'
);
}
else
if
(
file
.
status
===
'done'
&&
file
.
response
.
code
!==
0
)
{
file
.
status
=
'error'
;
message
.
error
(
'上传失败!'
);
}
onChange
((
fileList
&&
fileList
.
length
&&
JSON
.
stringify
(
fileList
))
||
''
);
setShowList
(
JSON
.
stringify
(
fileList
));
},
onPreview
(
file
)
{
if
(
_isRecordingOrVideo
)
{
setPreviewVisible
(
true
);
setPreviewUrl
(
file
.
url
);
}
},
previewFile
(
file
)
{},
onDownload
(
file
)
{
downloadFunc
(
file
.
url
,
file
.
name
,
'_self'
);
},
};
const
handleCancel
=
()
=>
{
setPreviewVisible
(
false
);
setPreviewTitle
(
''
);
};
/**
* @description: 返回文件类型限定值
* @params: {Array} typeArray: Video | Recording | File
* @date: 2021/12/2
* @author: ChenLong
*/
const
returnFileTypeString
=
(
type
)
=>
{
let
_obj
=
{
Video
:
videoTypeArray
,
Recording
:
audioTypeArray
,
File
:
fileTypeArray
,
Image
:
imageTypeArray
,
};
return
_obj
[
type
].
join
(
','
);
};
useEffect
(()
=>
{
let
fileList
=
[];
(
file
||
''
).
split
(
','
).
forEach
((
item
,
index
)
=>
{
if
(
item
&&
filenameVerification
({
name
:
item
},
true
).
type
!==
'error'
)
{
// @Tips: 直接过滤掉名字中有异常字符的文件
let
_obj
=
{
uid
:
index
+
'_'
+
Math
.
random
(),
value
:
item
,
name
:
item
.
split
(
'
\
\'
).reverse()[0],
type: schema.renderTo === '
Image
' ? '
image
' : '
file
',
status: '
done
',
url: `${downloadFileUrl}?filePath=${item}`,
sourcePath: item,
};
if (schema.renderTo === '
Image
') _obj.thumbUrl = `${downloadFileUrl}?filePath=${item}`;
fileList.push(_obj);
}
});
// onChange(fileList.length && JSON.stringify(fileList) || '');
setShowList(JSON.stringify(fileList));
}, []);
useEffect(() => {
if (value) {
let fileList = [];
(file || '').split('
,
').forEach((item, index) => {
if (item && filenameVerification({ name: item }, true).type !== '
error
') {
// @Tips: 直接过滤掉名字中有异常字符的文件
let _obj = {
uid: index + '
_
' + Math.random(),
value: item,
name: item.split('
\\
').reverse()[0],
type: schema.renderTo === '
Image
' ? '
image
' : '
file
',
status: '
done
',
url: `${downloadFileUrl}?filePath=${item}`,
sourcePath: item,
};
if (schema.renderTo === '
Image
') _obj.thumbUrl = `${downloadFileUrl}?filePath=${item}`;
fileList.push(_obj);
}
});
// onChange(fileList.length && JSON.stringify(fileList) || '');
setShowList(JSON.stringify(fileList));
}
}, [value]);
return (
<>
{/** @tips: 裁剪功能无法正常工作,暂不提供 */}
{/* <ImgCrop beforeCrop={(file) => {
let _returnObj = filenameVerification(file);
if (_returnObj.type === '
error
') {
message.error(_returnObj.content);
return false;
}
return schema.renderTo === '
Image
';
}} rotate locale={'
zh
-
cn
'} modalTitle={'
编辑图片
'} modalOk={'
确定
'}
modalCancel={'
取消
'}>*/}
<Upload
disabled={schema.disabled}
{...option}
fileList={showList ? JSON.parse(showList) : []}
multiple
style={{ width: '
100
%
' }}
className={_isRecordingOrVideo ? '
formUploadVideoOrRecording
' : '
formUpload
'}
showUploadList={{
showPreviewIcon: _isRecordingOrVideo,
showDownloadIcon: true,
downloadIcon: <DownloadOutlined />,
}}
accept={returnFileTypeString(schema.renderTo)}
>
{!_isRecordingOrVideo ? (
<Button disabled={schema.disabled} icon={<UploadOutlined />}>
Upload
</Button>
) : (
'
+
Upload
'
)}
</Upload>
{/* </ImgCrop>*/}
<Modal
style={{ width: '
30
%
' }}
bodyStyle={{ textAlign: '
center
' }}
visible={previewVisible}
title={previewTitle}
footer={null}
onCancel={handleCancel}
>
{_isVideo ? (
<video width={'
100
%
'} height={'
100
%
'} controls autoPlay src={previewUrl} />
) : (
''
)}
{_isAudio ? <audio controls autoPlay src={previewUrl} /> : ''}
{_isImage ? <img width={'
100
%
'} height={'
100
%
'} src={previewUrl} alt="缩略图" /> : ''}
</Modal>
</>
);
};
export default FileUpload;
packages/base-components/BasicReport/src/ReportsManage/Components/fileUpload/fileUpload.less
0 → 100644
View file @
48ac1217
@import '~antd/es/style/themes/default.less';
@parse-form-prefix-cls: ~'@{ant-prefix}-parse-form';
.@{parse-form-prefix-cls} {
.formUpload {
width: 100%;
.@{ant-prefix}-upload-list-item {
float: left;
width: 49%;
max-width: 300px; // 增加了最大宽度,防止样式失效导致布局错误的问题
margin-right: 1%;
}
}
.@{ant-prefix}-animate {
}
.formUploadVideoOrRecording {
width: 100%;
.@{ant-prefix}-upload-list-item {
float: left;
width: 99%;
margin-right: 1%;
}
}
}
packages/base-components/BasicReport/src/ReportsManage/ReportEditForm.js
0 → 100644
View file @
48ac1217
/*
** 报表的编辑、新增表单
** create by ChenLong on 2022/8/10
** 功能路径:src\pages\product\ReportsManage\ReportEditForm.js
** 菜单参数列表:*变量名*(变量说明,数据类型,是否必填,取值范围)
**/
import
React
,
{
useEffect
,
useState
,
useContext
}
from
'react'
;
import
{
Form
,
Input
,
DatePicker
,
InputNumber
,
Row
,
Col
,
Button
,
message
,
Select
,
ConfigProvider
,
}
from
'antd'
;
import
moment
from
'moment'
;
import
{
submitReportData
}
from
'../api/service/report'
;
import
FileUpload
from
'./Components/fileUpload/fileUpload'
;
import
{
reportService
}
from
'../api'
;
import
{
isSelect
,
returnOptions
,
returnRows
,
returnCols
}
from
'./utils/utils'
;
import
style
from
'./ReportEditForm.less'
;
const
{
Option
}
=
Select
;
const
{
TextArea
}
=
Input
;
// 类型
const
USER_ID
=
window
.
globalConfig
.
userInfo
.
OID
;
const
TEXT_ARRAY
=
[
'文本'
,
'标签'
];
const
TEXTAREA_ARRAY
=
[
'多行文本'
];
const
DATE_PICKER_ARRAY
=
[
'日期'
];
const
DATE_TIME_PICKER_ARRAY
=
[
'日期时刻'
];
const
DATE_TYPE
=
[
'日期'
,
'日期时刻'
];
// 用来匹配是否需要转为日期对象;
const
NUMBER_ARRAY
=
[
'数值'
,
'数值标签'
];
const
FILE_ARRAY
=
[
'附件'
];
// 形态对应组件
// 对应关系
/**
* @description: 函数描述
* @date: 2022/8/10
* @author: ChenLong
* @params: reportDetails 各个字段的配置列表
* data 与reportDetails对应的值
*/
const
ReportEditForm
=
({
reportDetails
,
reportData
,
onCancel
,
reportName
,
modalType
})
=>
{
// if (!reportData || Object.keys(reportData).length === 0) return <>未传递表单数据</>;
const
[
fileAlias
,
setFileAlias
]
=
useState
([]);
// 附件需要单独处理提交的数据
const
[
form
]
=
Form
.
useForm
();
const
{
getPrefixCls
}
=
useContext
(
ConfigProvider
.
ConfigContext
);
const
prefixCls
=
getPrefixCls
();
/* 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
]
=
data
[
item
.
fieldAlias
]
?
moment
(
data
[
item
.
fieldAlias
])
:
moment
();
}
});
return
_data
;
};
const
componentMap
=
(
config
)
=>
{
if
(
DATE_TIME_PICKER_ARRAY
.
includes
(
config
.
type
))
{
return
<
DatePicker
showTime
readonly
=
{
config
.
isReadOnly
}
/>
;
}
else
if
(
DATE_PICKER_ARRAY
.
includes
(
config
.
type
))
{
return
<
DatePicker
disabled
=
{
config
.
isReadOnly
}
/>
;
}
else
if
(
NUMBER_ARRAY
.
includes
(
config
.
type
))
{
return
<
InputNumber
disabled
=
{
config
.
isReadOnly
}
/>
;
}
else
if
(
FILE_ARRAY
.
includes
(
config
.
type
))
{
return
<
FileUpload
schema
=
{{
renderTo
:
'File'
}}
disabled
=
{
config
.
isReadOnly
}
/>
;
}
else
if
(
TEXTAREA_ARRAY
.
includes
(
config
.
type
))
{
let
_rows
=
returnRows
(
config
.
configItems
);
return
<
TextArea
rows
=
{
_rows
}
disabled
=
{
config
.
isReadOnly
}
/>
;
}
else
{
if
(
isSelect
(
config
.
configItems
))
{
let
options
=
returnOptions
(
config
.
configItems
);
if
(
options
)
{
return
(
<
Select
disabled
=
{
config
.
isReadOnly
}
>
{
options
.
map
((
item
)
=>
(
<
Option
value
=
{
item
}
>
{
item
}
<
/Option
>
))}
<
/Select
>
);
}
}
return
<
Input
disabled
=
{
config
.
isReadOnly
}
/>
;
}
};
const
submitReportForm
=
()
=>
{
form
.
validateFields
().
then
((
values
)
=>
{
let
_data
=
values
;
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
)
{
if
(
fileAlias
.
includes
(
key
))
{
_value
=
_value
?
JSON
.
parse
(
_value
)
.
reduce
((
final
,
curr
)
=>
{
final
.
push
(
curr
.
sourcePath
);
return
final
;
},
[])
.
join
(
','
)
:
''
;
}
let
_finalData
=
{
fieldAlias
:
key
,
fieldValue
:
_value
,
};
if
(
modalType
===
'编辑'
)
{
_finalData
.
key
=
reportData
.
Key
;
}
final
.
push
(
_finalData
);
}
});
if
(
modalType
===
'新增'
)
{
reportService
.
addReportData
({
reportName
:
reportName
,
userId
:
USER_ID
,
reportDatas
:
final
,
})
.
then
((
res
)
=>
{
if
(
res
.
code
===
0
)
{
message
.
success
(
'保存成功!'
);
onCancel
();
}
else
if
(
res
.
code
===
-
1
)
{
message
.
error
(
res
.
msg
);
}
else
if
(
res
.
code
===
-
2
)
{
message
.
error
(
'系统故障,请找管理员查看故障!'
);
}
});
}
if
(
modalType
===
'编辑'
)
{
submitReportData
(
{},
{
editDatas
:
final
,
reportName
:
reportName
,
userId
:
USER_ID
,
},
).
then
((
res
)
=>
{
if
(
res
.
code
===
0
)
{
message
.
success
(
'保存成功!'
);
onCancel
();
}
else
if
(
res
.
code
===
-
1
)
{
message
.
error
(
res
.
msg
);
}
else
if
(
res
.
code
===
-
2
)
{
message
.
error
(
'系统故障,请找管理员查看故障!'
);
}
});
}
});
};
useEffect
(()
=>
{
if
(
reportDetails
&&
reportDetails
.
length
)
{
let
_fileAlias
=
[...
fileAlias
];
reportDetails
.
forEach
((
item
)
=>
{
if
(
item
.
type
===
'附件'
)
_fileAlias
.
push
(
item
.
fieldAlias
);
});
setFileAlias
(
_fileAlias
);
}
},
[
reportDetails
]);
useEffect
(()
=>
{
if
(
reportData
&&
Object
.
keys
(
reportData
).
length
)
form
.
setFieldsValue
(
handleDate
(
reportDetails
,
reportData
));
},
[
reportData
]);
return
(
<
div
className
=
{
style
.
reportEditForm
}
style
=
{{
position
:
'relative'
}}
>
<
div
>
<
Form
form
=
{
form
}
>
<
Row
style
=
{{
overflowY
:
'scroll'
,
maxHeight
:
'calc(100vh - 300px)'
}}
>
{
reportDetails
&&
reportDetails
.
filter
((
config
)
=>
{
if
(
modalType
===
'新增'
&&
config
.
isReadOnly
)
return
false
;
return
config
;
})
.
map
((
config
)
=>
{
// return <Col span={returnCols(config.configItems) * 8} key={config.fieldAlias}>
return
(
<
div
style
=
{{
width
:
`
${
returnCols
(
config
.
configItems
)
*
33.3
}
%`
}}
key
=
{
config
.
fieldAlias
}
>
<
Form
.
Item
label
=
{
config
.
fieldAlias
}
name
=
{
config
.
fieldAlias
}
rules
=
{[
{
required
:
config
.
isRequired
,
message
:
`
${
config
.
fieldAlias
}
必填`
,
},
]}
>
{
componentMap
(
config
)}
<
/Form.Item
>
<
/div
>
);
})}
<
/Row
>
<
Row
>
<
Col
span
=
{
24
}
style
=
{{
textAlign
:
'right'
}}
>
{
/*<Form.Item style={{textAlign:'right'}}>*/
}
<
Button
style
=
{{
position
:
'sticky'
,
bottom
:
0
}}
type
=
{
'primary'
}
onClick
=
{
submitReportForm
}
>
提交
<
/Button
>
{
/*</Form.Item>*/
}
<
/Col
>
<
/Row
>
<
/Form
>
<
/div
>
<
/div
>
);
};
export
default
ReportEditForm
;
packages/base-components/BasicReport/src/ReportsManage/ReportEditForm.less
0 → 100644
View file @
48ac1217
@import '~antd/es/style/themes/default.less';
.reportEditForm {
:global {
.@{ant-prefix}-form-item-label {
width: 120px !important;
}
input[disabled] {
background-color: rgb(250, 250, 250);
cursor: default;
}
// 多行文本框
.@{ant-prefix}-input[disabled] {
color: rgba(0, 0, 0, 0.85);
background-color: rgb(250, 250, 250);
border-color: #d9d9d9;
box-shadow: none;
cursor: default;
opacity: 1;
}
// 时间选择器的disabled样式
.@{ant-prefix}-picker-disabled {
color: rgba(0, 0, 0, 0.85);
background-color: rgb(250, 250, 250);
cursor: default;
& + span {
cursor: default;
}
}
// radio的disabled样式
.@{ant-prefix}-radio-disabled {
cursor: default;
& + span {
cursor: default;
}
.@{ant-prefix}-radio-inner {
cursor: default;
}
}
// 下拉选已选的disabled样式
.@{ant-prefix}-cascader-picker-disabled {
color: rgba(0, 0, 0, 0.85);
background-color: rgb(250, 250, 250);
cursor: default;
}
// 按钮的disabled样式
.@{ant-prefix}-btn[disabled] {
text-shadow: none;
background: #ffffff;
border-color: #d9d9d9;
box-shadow: none;
cursor: default;
&:hover,
&:focus,
&:active {
color: rgba(0, 0, 0, 0.25);
text-shadow: none;
background: #ffffff;
border-color: #d9d9d9;
box-shadow: none;
}
}
// 多选下的tag的disabled样式
.@{ant-prefix}-select-disabled.@{ant-prefix}-select-multiple {
.@{ant-prefix}-select-selection-item {
color: #bfbfbf;
border-color: #d9d9d9;
cursor: default;
}
}
.@{ant-prefix}-select-disabled.@{ant-prefix}-select:not(.@{ant-prefix}-select-customize-input) {
.@{ant-prefix}-select-selector input {
cursor: default;
}
}
// 时间选择框
.@{ant-prefix}-picker-input > input[disabled] {
color: rgba(0, 0, 0, 0.85);
}
}
}
packages/base-components/BasicReport/src/ReportsManage/ReportsDataSourceSetting.js
0 → 100644
View file @
48ac1217
import
React
,
{
useEffect
,
useState
}
from
'react'
;
import
style
from
'./ReportsDataSourceSetting.less'
;
import
{
Row
,
Space
,
Form
,
Button
,
Card
,
Input
,
Avatar
,
Modal
,
Select
,
InputNumber
,
Spin
,
message
,
}
from
'antd'
;
import
{
sourceIconMap
}
from
'./utils/constant'
;
import
{
EditOutlined
,
DeleteOutlined
,
EyeTwoTone
,
EyeInvisibleOutlined
}
from
'@ant-design/icons'
;
import
{
reportService
}
from
'../api'
;
import
classnames
from
'classnames'
;
const
{
Search
,
TextArea
}
=
Input
;
const
{
Option
}
=
Select
;
const
{
Meta
}
=
Card
;
const
ReportsDataSourceSetting
=
()
=>
{
const
[
sourceList
,
setSourceList
]
=
useState
([]);
const
[
modalVisible
,
setModalVisible
]
=
useState
(
false
);
const
[
currentData
,
setCurrentData
]
=
useState
(
null
);
const
[
type
,
setType
]
=
useState
(
''
);
const
[
dataSourceType
,
setDataSourceType
]
=
useState
(
'sqlserver'
);
const
[
searchStr
,
setSearchStr
]
=
useState
(
null
);
const
[
form
]
=
Form
.
useForm
();
const
[
dbList
,
setDBList
]
=
useState
([]);
const
[
listLoading
,
setListLoading
]
=
useState
(
false
);
const
[
testLoading
,
setTestLoading
]
=
useState
(
false
);
const
[
submitLoading
,
setSubmitLoading
]
=
useState
(
false
);
const
initValues
=
{
db_sourcesname
:
''
,
db_type
:
'sqlserver'
,
db_url
:
''
,
db_username
:
''
,
db_password
:
''
,
db_port
:
1433
,
db_name
:
''
,
webapiRType
:
''
,
webapiRParam
:
''
,
};
const
getSourceList
=
()
=>
{
setListLoading
(
true
);
let
_temp
=
searchStr
?
{
sourceName
:
searchStr
}
:
{};
reportService
.
getDataSources
(
_temp
)
.
then
((
res
)
=>
{
if
(
res
.
code
===
0
)
{
setSourceList
(
res
.
data
);
}
else
{
setSourceList
([]);
}
setListLoading
(
false
);
})
.
catch
((
err
)
=>
{
setListLoading
(
false
);
});
};
const
cancelVisible
=
()
=>
{
setCurrentData
(
null
);
setModalVisible
(
false
);
form
.
resetFields
();
setDataSourceType
(
'sqlserver'
);
};
const
checkCard
=
(
data
)
=>
{
setModalVisible
(
true
);
setCurrentData
(
data
);
setType
(
'detail'
);
};
const
editCard
=
(
data
)
=>
{
setModalVisible
(
true
);
setCurrentData
(
data
);
setType
(
'edit'
);
form
.
setFieldsValue
(
data
);
setDataSourceType
(
data
.
db_type
);
};
const
addCard
=
()
=>
{
setModalVisible
(
true
);
setCurrentData
(
null
);
form
.
resetFields
();
};
const
deleteCard
=
(
source
)
=>
{
Modal
.
confirm
({
title
:
`当前有
${
source
.
db_name
}
正在使用该数据源,删除后会导致该报表无法使用。请确认,是否删除【
${
source
.
db_sourcesname
}
】数据源配置?`
,
onOk
:
()
=>
{
setSubmitLoading
(
true
);
reportService
.
deleteDbConnection
({
sourcesId
:
source
.
id
})
.
then
((
res
)
=>
{
if
(
res
.
code
===
0
)
{
message
.
success
(
'删除成功!'
);
getSourceList
();
}
else
{
message
.
error
(
`删除失败!
${
res
.
msg
}
`
);
}
setSubmitLoading
(
false
);
})
.
catch
((
err
)
=>
{
console
.
log
(
err
);
setSubmitLoading
(
false
);
});
},
});
};
const
selectType
=
(
e
)
=>
{
setDataSourceType
(
e
);
if
(
e
===
'mysql'
)
form
.
setFieldsValue
({
db_port
:
3306
});
if
(
e
===
'sqlserver'
)
form
.
setFieldsValue
({
db_port
:
1433
});
};
const
onSearch
=
(
e
)
=>
{
setSearchStr
(
e
);
};
const
getLoginInfo
=
()
=>
{
let
list
=
form
.
getFieldsValue
([
'db_url'
,
'db_username'
,
'db_password'
,
'db_port'
,
'db_sourcesname'
,
'db_type'
,
]);
let
_final
=
Object
.
values
(
list
).
reduce
((
final
,
curr
)
=>
{
if
(
curr
===
undefined
)
final
=
false
;
return
final
;
},
true
);
return
_final
?
list
:
false
;
};
const
getDBList
=
()
=>
{
let
info
=
getLoginInfo
();
if
(
info
)
{
let
{
db_url
,
db_username
,
db_password
,
db_port
,
db_sourcesname
,
db_type
}
=
info
;
reportService
.
getDbSources
({
db_url
,
db_username
,
db_password
,
db_port
,
db_sourcesname
,
db_type
,
})
.
then
((
res
)
=>
{
if
(
res
.
code
===
0
)
{
setDBList
(
res
.
data
);
}
else
{
setDBList
([]);
message
.
error
(
res
.
msg
);
}
});
}
else
{
message
.
error
(
`请完善名称、IP、端口、账号、密码`
);
}
};
const
test
=
()
=>
{
form
.
validateFields
().
then
((
value
)
=>
{
setTestLoading
(
true
);
let
_value
=
!
currentData
?
value
:
{
...
value
,
id
:
currentData
.
id
};
reportService
.
testConnection
(
_value
)
.
then
((
res
)
=>
{
if
(
res
.
code
===
0
)
{
message
.
success
(
'测试通过!'
);
}
else
{
message
.
error
(
res
.
msg
);
}
setTestLoading
(
false
);
})
.
catch
((
err
)
=>
{
setTestLoading
(
false
);
});
});
};
const
submit
=
()
=>
{
form
.
validateFields
().
then
((
value
)
=>
{
setSubmitLoading
(
true
);
let
_value
=
!
currentData
?
value
:
{
...
value
,
id
:
currentData
.
id
};
reportService
.
addDbConnection
(
_value
)
.
then
((
res
)
=>
{
if
(
res
.
code
===
0
)
{
message
.
success
(
'保存成功!'
);
setModalVisible
(
false
);
getSourceList
();
}
else
{
message
.
error
(
res
.
msg
);
}
setSubmitLoading
(
false
);
})
.
catch
((
err
)
=>
{
setSubmitLoading
(
false
);
});
});
};
useEffect
(()
=>
{
getSourceList
();
},
[]);
useEffect
(()
=>
{
if
(
searchStr
!==
null
)
getSourceList
();
},
[
searchStr
]);
return
(
<
div
className
=
{
style
.
reportsDataSourceSetting
}
>
<
div
className
=
{
style
.
contentWrapper
}
>
<
Row
className
=
{
style
.
controlRow
}
>
<
Space
>
{
/*控制栏左侧部分*/
}
<
Form
.
Item
>
<
Search
onSearch
=
{
onSearch
}
/
>
<
/Form.Item
>
<
Form
.
Item
>
<
Button
onClick
=
{
addCard
}
type
=
{
'primary'
}
>
添加
<
/Button
>
<
/Form.Item
>
<
/Space
>
<
div
>
{
/* 控制栏右侧部分 */
}
<
/div
>
<
/Row
>
<
div
className
=
{
style
.
content
}
>
<
Spin
style
=
{{
width
:
'100%'
,
height
:
'100%'
,
position
:
'absolute'
,
display
:
'flex'
,
justifyContent
:
'center'
,
alignItems
:
'center'
,
background
:
'rgba(255,255,255,0.2)'
,
}}
spinning
=
{
listLoading
}
/
>
{
sourceList
.
filter
((
item
)
=>
{
return
!
searchStr
?
true
:
item
.
db_sourcesname
.
includes
(
searchStr
);
})
.
map
((
item
)
=>
{
return
(
<
Card
className
=
{
style
.
card
}
actions
=
{[
// <SettingOutlined onClick={checkCard} key='setting' />,
<
EditOutlined
onClick
=
{()
=>
editCard
(
item
)}
key
=
"edit"
/>
,
<
DeleteOutlined
onClick
=
{()
=>
deleteCard
(
item
)}
key
=
"delete"
/>
,
]}
>
<
Meta
avatar
=
{
<
Avatar
src
=
{
sourceIconMap
[
item
.
db_type
]}
/>
}
title
=
{
item
.
db_sourcesname
}
/
>
<
div
className
=
{
style
.
cardInfo
}
>
<
p
className
=
{
style
.
cardInfoItem
}
>
类型
:{
' '
}
<
span
className
=
{
classnames
(
style
.
item
,
style
.
blue
)}
>
{
item
.
db_type
||
'无'
}
<
/span
>
<
/p
>
{
item
.
db_type
===
'webapi'
?
(
<
p
className
=
{
style
.
cardInfoItem
}
>
请求类型
:{
' '
}
<
span
className
=
{
style
.
item
}
>
{
item
.
webapiRType
===
'post'
?
'POST'
:
'GET'
}
<
/span
>
<
/p
>
)
:
(
<
p
className
=
{
style
.
cardInfoItem
}
>
数据库
:
<
span
className
=
{
style
.
item
}
>
{
item
.
db_name
||
'无'
}
<
/span
>
<
/p
>
)}
<
p
className
=
{
style
.
cardInfoItem
}
>
请求地址
:{
' '
}
<
span
title
=
{
item
.
db_url
}
className
=
{
classnames
(
style
.
item
,
style
.
ellipsis
)}
>
{
item
.
db_url
}
<
/span
>
<
/p
>
<
/div
>
<
/Card
>
);
})}
<
/div
>
<
/div
>
<
Modal
title
=
{
currentData
?.
id
?
'编辑'
:
'新增'
}
visible
=
{
modalVisible
}
onCancel
=
{
cancelVisible
}
footer
=
{
null
}
width
=
{
600
}
destroyOnClose
>
<
Form
autocomplete
=
{
'off'
}
form
=
{
form
}
initialValues
=
{
initValues
}
labelCol
=
{{
span
:
6
,
}}
wrapperCol
=
{{
span
:
16
,
}}
>
<
Form
.
Item
label
=
{
'名称'
}
name
=
{
'db_sourcesname'
}
rules
=
{[
{
required
:
true
,
message
:
'名称必填'
,
},
]}
>
<
Input
placeholder
=
{
'请输入数据源名称'
}
/
>
<
/Form.Item
>
<
Form
.
Item
label
=
{
'类型'
}
name
=
{
'db_type'
}
rules
=
{[
{
required
:
true
,
message
:
'名称必填'
,
},
]}
>
<
Select
onChange
=
{
selectType
}
disabled
=
{
!!
currentData
?.
id
}
>
<
Option
value
=
"mysql"
>
MySQL
<
/Option
>
<
Option
value
=
"sqlserver"
>
SQLServer
<
/Option
>
<
Option
value
=
"webapi"
>
WebAPI
<
/Option
>
<
/Select
>
<
/Form.Item
>
<
Form
.
Item
label
=
{[
'mysql'
,
'sqlserver'
].
includes
(
dataSourceType
)
?
'IP'
:
'请求地址'
}
name
=
{
'db_url'
}
rules
=
{[
{
required
:
true
,
message
:
'名称必填'
,
},
]}
>
{[
'mysql'
,
'sqlserver'
].
includes
(
dataSourceType
)
?
(
<
Input
placeholder
=
{
'请输入要链接的服务器IP'
}
/
>
)
:
(
<
TextArea
placeholder
=
{
'请输入API链接'
}
rows
=
{
3
}
/
>
)}
<
/Form.Item
>
{[
'mysql'
,
'sqlserver'
].
includes
(
dataSourceType
)
?
(
<>
<
Form
.
Item
label
=
{
'账号'
}
name
=
{
'db_username'
}
rules
=
{[
{
required
:
true
,
message
:
'名称必填'
,
},
]}
>
<
Input
placeholder
=
{
'请输入链接账号'
}
/
>
<
/Form.Item
>
<
Form
.
Item
label
=
{
'密码'
}
name
=
{
'db_password'
}
rules
=
{[
{
required
:
true
,
message
:
'名称必填'
,
},
]}
>
<
Input
.
Password
placeholder
=
"请输入密码"
iconRender
=
{(
visible
)
=>
(
visible
?
<
EyeTwoTone
/>
:
<
EyeInvisibleOutlined
/>
)}
/
>
<
/Form.Item
>
<
Form
.
Item
label
=
{
'端口'
}
name
=
{
'db_port'
}
rules
=
{[
{
required
:
true
,
message
:
'名称必填'
,
},
]}
>
<
InputNumber
min
=
{
0
}
max
=
{
65535
}
step
=
{
1
}
/
>
<
/Form.Item
>
<
Form
.
Item
label
=
{
'数据库'
}
name
=
{
'db_name'
}
rules
=
{[
{
required
:
true
,
message
:
'请选择要连接的数据库'
,
},
]}
>
<
Select
onFocus
=
{
getDBList
}
filterOption
=
{(
input
,
option
)
=>
option
.
children
.
includes
(
input
)}
showSearch
>
{
dbList
.
map
((
item
)
=>
{
return
<
Option
value
=
{
item
}
>
{
item
}
<
/Option>
;
})}
<
/Select
>
<
/Form.Item
>
<
/
>
)
:
(
''
)}
{
// webapiRType
// webapiRParam
[
'webapi'
].
includes
(
dataSourceType
)
?
(
<>
<
Form
.
Item
label
=
{
'请求方式'
}
name
=
{
'webapiRType'
}
rules
=
{[
{
required
:
true
,
message
:
'请选择请求方式'
,
},
]}
>
<
Select
>
<
Option
value
=
{
'post'
}
>
POST
<
/Option
>
<
Option
value
=
{
'get'
}
>
GET
<
/Option
>
<
/Select
>
<
/Form.Item
>
<
Form
.
Item
label
=
{
'请求头参数'
}
name
=
{
'requestHeader'
}
>
<
TextArea
rows
=
{
3
}
placeholder
=
{
'请配置请求头参数'
}
/
>
<
/Form.Item
>
<
Form
.
Item
label
=
{
'请求参数'
}
name
=
{
'webapiRParam'
}
>
<
TextArea
rows
=
{
3
}
placeholder
=
{
'请填写请求参数,使用&拼接,例:id=0&type=二供泵房'
}
/
>
<
/Form.Item
>
<
Form
.
Item
name
=
{
'webapiDataNode'
}
label
=
{
'数据路径'
}
rules
=
{[{
required
:
true
,
message
:
'数据路径必填!'
}]}
>
<
Input
placeholder
=
{
'仅获取该层级数据'
}
/
>
<
/Form.Item
>
<
/
>
)
:
(
''
)
}
<
Form
.
Item
label
=
{
' '
}
colon
=
{
false
}
>
<
Space
>
<
Button
onClick
=
{
test
}
loading
=
{
testLoading
}
>
测试链接
<
/Button
>
<
Button
onClick
=
{
cancelVisible
}
>
取消
<
/Button
>
<
Button
onClick
=
{
submit
}
type
=
{
'primary'
}
loading
=
{
submitLoading
}
>
确定
<
/Button
>
<
/Space
>
<
/Form.Item
>
<
/Form
>
<
/Modal
>
<
/div
>
);
};
export
default
ReportsDataSourceSetting
;
packages/base-components/BasicReport/src/ReportsManage/ReportsDataSourceSetting.less
0 → 100644
View file @
48ac1217
@import '~antd/es/style/themes/default.less';
.reportsDataSourceSetting {
height: 100%;
overflow: hidden;
.contentWrapper {
display: flex;
flex-direction: column;
height: calc(100% - 16px);
margin: 8px;
@media screen and (min-width: 1680px) {
.content {
grid-template-columns: repeat(5, 1fr);
}
}
@media screen and (max-width: 1680px) {
.content {
grid-template-columns: repeat(4, 1fr);
}
}
@media screen and (max-width: 1320px) {
.content {
grid-template-columns: repeat(3, 1fr);
}
}
@media screen and (max-width: 960px) {
.content {
grid-template-columns: repeat(2, 1fr);
}
}
.controlRow {
display: flex;
flex-direction: column;
margin-bottom: 8px;
padding: 8px;
background: #ffffff;
:global {
.@{ant-prefix}-form-item {
margin-bottom: 0;
}
}
}
.content {
display: grid;
grid-gap: 10px;
padding-bottom: 8px;
overflow: scroll;
.card {
height: 198px;
.cardInfo {
padding-left: 48px;
.cardInfoItem {
margin-bottom: 4px;
color: rgb(100, 100, 100, 0.65);
.item {
color: rgba(58, 58, 58, 0.55);
font-weight: bold;
}
.blue {
color: rgba(23, 130, 252, 0.65);
}
.ellipsis {
display: inline-block;
max-width: 120px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
vertical-align: top;
}
}
}
}
}
}
}
packages/base-components/BasicReport/src/ReportsManage/ReportsManage.js
0 → 100644
View file @
48ac1217
/**
* * 轻量化报表通用配置页面 * 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/filterValues多用于以组件的形式嵌入,将需要过滤的条件传入********************
*
*
*
* filterFields: 需要默认加载的过滤条件的field,用|分割,与filterValues一一对应;
* filterValues:
*
*
* 需要默认加载的过滤条件的value,用|分割,与filterFields一一对应;当某个字段的filterValues为多个时,控件必须配置成多选才可生效;
*
*
*
* *************************************************************************************************
*
*
*
* state: delete|edit|scan 各种权限;
* customerState:
*
*
* ['filters','sortBtn','exportBtn','editBtn','deleteBtn','pagination'];
*
* sortFields:
*
* '排序字段1,排序字段2,排序字段3'
*
*
*
* ---------------------------------------权限过滤-----------------------------------------
*
*
*
* permissionType: 部门|站点|用户
* permissionField: 【字段名】
*
*
*
* ---------------------------------------------------------------------------------------
* @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
,
Popconfirm
,
Tooltip
,
}
from
'antd'
;
import
{
SortAscendingOutlined
,
MinusCircleOutlined
,
ExportOutlined
,
FormOutlined
,
PlusOutlined
,
DeleteOutlined
,
QuestionCircleOutlined
,
HeartTwoTone
,
HeartOutlined
,
DownOutlined
,
}
from
'@ant-design/icons'
;
import
BasicTable
from
'@wisdom-components/basictable'
;
import
ReturnControlComponent
from
'./Components/Control'
;
import
{
reportService
}
from
'../api/index'
;
import
style
from
'./ReportsManage.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
,
handleNumberTag
,
}
from
'./utils/handlers'
;
import
{
hasMoney
,
isArray
,
isNumber
,
isString
,
returnHandledNumber
}
from
'./utils/utils'
;
import
{
connect
}
from
'react-redux'
;
import
ReportEditForm
from
'./ReportEditForm'
;
import
{
exportJPG
}
from
'../api/service/report'
;
const
ControlsType
=
[
'下拉'
,
'多选'
,
'日期'
];
const
fieldSplitStr
=
'-'
;
// fieldGroup用来分割
const
{
Option
}
=
Select
;
const
dateFormat
=
'YYYY-MM-DD'
;
// 日期格式化
const
initDateModel
=
'all'
;
let
timer
=
null
;
const
PERMISSION
=
{
delete
:
[
'addBtn'
,
'filters'
,
'pagination'
,
// 操作条按钮
'sortBtn'
,
'exportBtn'
,
// 操作列
'editBtn'
,
'deleteBtn'
,
],
edit
:
[
'addBtn'
,
'filters'
,
'pagination'
,
'sortBtn'
,
'exportBtn'
,
// 操作列
'editBtn'
,
],
scan
:
[
'filters'
,
'pagination'
,
'sortBtn'
],
};
const
USER_ID
=
window
.
globalConfig
.
userInfo
.
OID
;
const
MODEL
=
[
'all'
,
'year'
,
'quarter'
,
'month'
,
'week'
,
'day'
];
const
ReportsManage
=
(
props
)
=>
{
const
{
reportName
,
pageSize
,
filterFields
,
filterValues
,
state
,
customState
,
sortFields
,
permissionType
,
permissionField
,
}
=
props
.
params
;
const
handleCustomerState
=
(
customState
)
=>
{
if
(
isArray
(
customState
))
{
return
customState
;
}
else
if
(
isString
(
customState
))
{
return
customState
.
split
(
','
);
}
};
const
permission
=
customState
?
handleCustomerState
(
customState
)
:
PERMISSION
[
state
||
'delete'
];
const
tableWrapperRef
=
useRef
();
const
controlRef
=
useRef
();
if
(
!
reportName
)
return
(
<
div
className
=
{
style
.
lackParams
}
>
未配置
reportName
,请完善配置并重新登陆后查看页面!
<
/div
>
);
const
[
isInit
,
setIsInit
]
=
useState
(
true
);
const
[
firstToGetData
,
setFirstToGetData
]
=
useState
(
false
);
const
[
tableStruct
,
setTableStruct
]
=
useState
([]);
// 临时使用,看后续是否需要保留
const
[
columns
,
setColumns
]
=
useState
([]);
// 表头设置
const
[
tableData
,
setTableData
]
=
useState
([]);
// 表数据
const
[
reportConfigs
,
setReportConfigs
]
=
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
(
_pagination
);
},
onChange
:
(
current
,
size
)
=>
{
let
_pagination
=
{
...
pagination
};
_pagination
.
current
=
current
;
_pagination
.
pageSize
=
size
;
setPagination
(
_pagination
);
getData
(
_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
[
detailsComponentVisible
,
setDetailsComponentVisible
]
=
useState
(
false
);
// 是否显示详情组件
const
[
modalType
,
setModalType
]
=
useState
(
''
);
const
[
currentData
,
setCurrentData
]
=
useState
({});
// 设置当前编辑数据
const
[
sorterObject
,
setSorterObject
]
=
useState
({});
const
[
detailConfig
,
setDetailConfig
]
=
useState
({
url
:
''
,
type
:
''
,
params
:
{}
});
const
[
controlsHeight
,
setControlsHeight
]
=
useState
(
44
);
const
[
getNewData
,
setGetNewData
]
=
useState
(
false
);
const
[
isLocalDataSource
,
setIsLocalDataSource
]
=
useState
(
0
);
// 如果是本地数据源,那么值为0;反之,则是外部数据源
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'
,
},
{
label
:
(
<
Button
size
=
"middle"
loading
=
{
exportLoading
}
type
=
"text"
onClick
=
{()
=>
exportImage
()}
icon
=
{
<
ExportOutlined
/>
}
>
导出
JPG
<
/Button
>
),
key
:
'excelPdf'
,
},
];
return
<
Menu
items
=
{
_item
}
/>
;
};
const
exportModule
=
(
type
,
extension
)
=>
{
setExportLoading
(
true
);
let
_data
=
addFilterAndSearchParams
({
reportName
,
pageIndex
:
0
,
pageSize
:
0
,
userId
:
USER_ID
,
});
exportAccountData
({
responseType
:
'blob'
},
{
exportType
:
type
},
_data
)
.
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
exportImage
=
()
=>
{
let
_data
=
addFilterAndSearchParams
({
reportName
,
pageIndex
:
0
,
pageSize
:
0
,
userId
:
USER_ID
,
});
exportJPG
({
responseType
:
'blob'
},
_data
).
then
((
res
)
=>
{
if
(
res
&&
res
.
code
===
-
1
)
return
message
.
error
(
res
.
msg
);
const
url
=
window
.
URL
.
createObjectURL
(
new
Blob
([
res
],
{
type
:
'application/zip;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
(
'-'
,
''
)}
.zip`
;
a
.
click
();
a
.
remove
();
setExportLoading
(
false
);
});
};
const
searchData
=
(
e
)
=>
{
getData
(
pagination
);
};
const
controlSelectChange
=
(
fieldAlias
,
e
)
=>
{
let
_filterArray
=
{
...
filterObject
};
_filterArray
[
fieldAlias
]
=
e
;
setFilterObject
(
_filterArray
);
};
const
searchInputChange
=
(
e
)
=>
{
setSearchContent
(
e
.
target
.
value
);
};
const
setConfig
=
(
config
)
=>
{
getControlsBarConfig
(
config
);
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
&&
!
_filters
.
find
((
item
)
=>
item
.
fieldAlias
===
filterFields
))
{
let
_customerFilterArray
=
filterFields
.
split
(
'|'
);
let
_customerValueArray
=
filterValues
.
split
(
'|'
);
_customerFilterArray
.
forEach
((
item
,
index
)
=>
{
_filters
.
push
({
fieldAlias
:
item
,
fieldValue
:
_customerValueArray
[
index
]
||
''
,
});
});
}
// 表格上的自定义排序的按钮
if
(
sorterObject
&&
sorterObject
.
order
)
{
_data
.
sortFields
=
`
${
sorterObject
.
columnKey
}
${
sorterObject
.
order
===
'ascend'
?
'asc'
:
'desc'
}
`
;
}
// 增加权限过滤的参数
if
(
permissionType
&&
permissionField
)
{
_data
.
filterType
=
permissionType
;
_data
.
filterField
=
permissionField
;
}
// 并入 _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
handleData
=
()
=>
{};
const
getData
=
(
pagination
)
=>
{
setTableLoading
(
true
);
const
{
pageSize
,
current
}
=
pagination
;
// 搜索条件附加到params
let
_data
=
addFilterAndSearchParams
({
reportName
:
reportName
,
pageIndex
:
current
,
pageSize
:
pageSize
,
userId
:
USER_ID
,
});
// sortFields
reportService
.
getReportInfo
(
_data
)
.
then
((
res
)
=>
{
if
(
res
.
code
===
0
)
{
let
_reportDetails
=
res
.
data
?.
reportDetails
;
let
_statisticalValues
=
res
.
data
?.
statisticalValues
;
// webAPIData 存在值时使用webAPIData,否则使用原始数据
let
_tableData
=
res
.
data
.
webAPIData
?.
webAPIData
?
JSON
.
parse
(
res
.
data
.
webAPIData
.
webAPIData
)
:
res
.
data
?.
data
?.
list
.
map
((
item
)
=>
{
if
(
Object
.
prototype
.
toString
.
call
(
item
)
===
'[object String]'
)
{
return
JSON
.
parse
(
item
);
}
return
item
;
})
||
[];
let
_sortString
=
res
.
data
.
sortString
;
if
(
isInit
)
{
setIsInit
(
false
);
}
setIsLocalDataSource
(
res
.
data
.
sourcesId
);
getTableSummaryConfig
(
_reportDetails
,
_statisticalValues
);
getTableHeaderConfig
(
_reportDetails
,
_tableData
);
let
_pagination
=
{
...
pagination
};
_pagination
.
total
=
res
.
data
.
webAPIData
?.
webAPIData
?
res
.
data
.
webAPIData
.
totalCount
:
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
([]);
}
if
(
isInit
)
setIsInit
(
false
);
setTableLoading
(
false
);
})
.
catch
((
err
)
=>
{
console
.
log
(
err
);
setTableLoading
(
false
);
});
};
const
getConfigs
=
()
=>
{
reportService
.
getReportDetails
({
reportName
}).
then
((
res
)
=>
{
if
(
res
.
code
===
0
)
{
setReportConfigs
(
res
.
data
);
setConfig
(
res
.
data
);
setColumns
(
returnColumn
(
res
.
data
));
setTableStruct
(
res
.
data
);
setFirstToGetData
(
true
);
}
else
{
message
.
error
(
res
.
msg
);
}
});
};
/** @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
);
handleControls
(
_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
,
多行文本
:
handleText
,
数值
:
handleNumber
,
数值标签
:
handleNumberTag
,
标签
:
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
=
data
?
handleDataToGetRowSpanArray
(
_config
,
data
)
:
false
;
// 需要向下合并的字段
_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
&&
_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
,
[
undefined
,
null
].
includes
(
value
)
?
''
:
value
,
record
,
...
rest
,
);
},
};
_item
.
width
=
(
!
isNaN
(
Number
(
item
.
columnWidth
))
&&
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
:
'操作'
,
align
:
'center'
,
width
:
permission
.
reduce
((
final
,
curr
)
=>
{
if
([
'editBtn'
,
'deleteBtn'
].
includes
(
curr
))
{
final
+=
30
;
}
return
final
;
},
30
),
fixed
:
'right'
,
render
:
(
text
,
record
)
=>
{
return
(
<
Space
className
=
{
style
.
handleColumnWrapper
}
>
{
record
.
IsAllow
?
(
<
Popconfirm
placement
=
"topRight"
title
=
{
'确认取消关注吗'
}
icon
=
{
<
QuestionCircleOutlined
/>
}
onConfirm
=
{()
=>
focusProject
(
record
)}
>
<
Tooltip
title
=
{
'点击取消关注'
}
>
<
HeartTwoTone
twoToneColor
=
"#eb2f96"
/>
<
/Tooltip
>
<
/Popconfirm
>
)
:
(
<
Popconfirm
placement
=
"topRight"
title
=
{
'确认关注项目吗'
}
icon
=
{
<
QuestionCircleOutlined
/>
}
onConfirm
=
{()
=>
focusProject
(
record
)}
>
<
Tooltip
title
=
{
'点击添加关注'
}
>
<
HeartOutlined
/>
<
/Tooltip
>
<
/Popconfirm
>
)}
{
permission
.
includes
(
'editBtn'
)
&&
!
isLocalDataSource
?
(
<
FormOutlined
className
=
{
style
.
editButton
}
onClick
=
{()
=>
{
// setEditComponentVisible(true);
setModalType
(
'编辑'
);
setCurrentData
(
record
);
}}
/
>
)
:
(
''
)}
{
permission
.
includes
(
'deleteBtn'
)
&&
!
isLocalDataSource
?
(
<
DeleteOutlined
disabled
className
=
{
style
.
deleteButton
}
onClick
=
{()
=>
{
Modal
.
confirm
({
content
:
'你确定要删除该数据吗?'
,
onOk
:
()
=>
{
reportService
.
delReportData
({
reportName
:
reportName
,
userId
:
USER_ID
,
key
:
record
.
Key
,
})
.
then
((
res
)
=>
{
if
(
res
.
code
===
0
)
{
message
.
success
(
'删除成功!'
);
setGetNewData
(
!
getNewData
);
// getData(pagination); // 在onOk的回调函数内,打包后的代码会形成闭包
}
});
},
});
}}
/
>
)
:
(
''
)}
<
/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
handleControls
=
(
controls
)
=>
{
// 过滤出非日期的字段,存储默认值
let
_controls
=
controls
.
filter
((
item
)
=>
item
.
type
!==
'日期'
);
_controls
.
forEach
((
item
)
=>
{
let
_configItems
=
item
.
configItems
.
split
(
'|'
);
_configItems
.
forEach
((
str
)
=>
{
if
(
str
.
includes
(
'defaultValue='
))
{
controlSelectChange
(
item
.
fieldAlias
,
str
.
replace
(
'defaultValue='
,
''
));
}
});
});
};
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
(
','
);
let
_defaultModel
=
_configItems
.
find
((
item
)
=>
item
.
includes
(
'defaultModel='
))?.
replace
(
'defaultModel='
,
''
)
||
'year'
;
_defaultDate
=
MODEL
.
includes
(
_defaultModel
)
?
_defaultDate
:
'year'
;
// 确保值符合要求
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
()
};
}
// 给定默认值,初始化时可以加载
changeDate
(
{
dateFrom
:
_defaultDate
?.
dateFrom
.
clone
().
startOf
(
_defaultModel
).
format
(
dateFormat
),
dateTo
:
_defaultDate
?.
dateTo
.
clone
().
endOf
(
_defaultModel
).
format
(
dateFormat
),
},
_defaultModel
,
);
setDefaultDateConfig
({
defaultDate
:
_defaultDate
?.
dateFrom
,
defaultModel
:
_defaultModel
,
});
};
const
focusProject
=
(
record
)
=>
{
reportService
.
setReportAllow
({
userId
:
USER_ID
,
reportName
:
reportName
,
reportKey
:
record
.
Key
,
})
.
then
((
res
)
=>
{
if
(
res
.
code
===
0
)
{
message
.
success
(
`
${
record
.
IsAllow
?
'取消'
:
'关注'
}
成功!`
);
getData
(
pagination
);
}
else
{
message
.
error
(
`
${
record
.
IsAllow
?
'取消'
:
'关注'
}
失败!`
);
}
});
};
function
getRefHeight
()
{
if
(
timer
)
clearTimeout
(
timer
);
timer
=
setTimeout
(()
=>
{
let
_height
=
controlRef
?.
current
.
clientHeight
;
setControlsHeight
(
_height
);
},
100
);
}
useEffect
(()
=>
{
getConfigs
();
},
[]);
useEffect
(()
=>
{
if
(
firstToGetData
)
getData
(
pagination
);
getRefHeight
();
},
[
firstToGetData
]);
useEffect
(()
=>
{
if
(
tableHeaderLevel
)
setTableHeight
();
},
[
tableHeaderLevel
]);
useEffect
(()
=>
{
if
(
!
isInit
)
getData
(
pagination
);
},
[
timeFrom
,
timeTo
,
sorterObject
,
filterObject
,
getNewData
]);
useEffect
(()
=>
{
window
.
addEventListener
(
'resize'
,
getRefHeight
);
return
()
=>
window
.
removeEventListener
(
'resize'
,
getRefHeight
);
});
return
(
<
div
className
=
{
style
.
reportManage
}
ref
=
{
tableWrapperRef
}
>
{
/* 预留容器,提供给点击后的功能显示 */
}
{
detailsComponentVisible
?
(
<
div
className
=
{
style
.
contentWrapper
}
style
=
{{
position
:
'absolute'
,
zIndex
:
100
,
width
:
'calc(100% - 16px)'
,
height
:
'calc(100% - 16px)'
,
}}
>
<
DetailsComponent
url
=
{
detailConfig
.
url
}
params
=
{
detailConfig
.
params
}
onCancel
=
{()
=>
setDetailsComponentVisible
(
false
)}
/
>
<
/div
>
)
:
(
''
)}
{
/* 为方便阅读,分开两部分代码 */
}
<
div
className
=
{
style
.
contentWrapper
}
style
=
{{
zIndex
:
detailsComponentVisible
?
-
1
:
'auto'
}}
>
<
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
)}
filterFields
=
{
filterFields
}
filterValues
=
{
filterValues
}
filterObject
=
{
addFilterAndSearchParams
({
reportName
:
reportName
,
userId
:
USER_ID
,
})}
/
>
<
/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'
)
||
permission
.
includes
(
'exportBtn'
)
||
permission
.
includes
(
'addBtn'
)
?
(
<
div
style
=
{{
width
:
270
,
textAlign
:
'end'
}}
>
<
Space
size
=
{
8
}
nowrap
>
{
permission
.
includes
(
'addBtn'
)
&&
!
isLocalDataSource
?
(
<
Form
.
Item
>
<
Button
type
=
{
'primary'
}
title
=
{
'自定义排序'
}
icon
=
{
<
PlusOutlined
/>
}
onClick
=
{()
=>
{
setModalType
(
'新增'
);
setCurrentData
({});
}}
>
添加
<
/Button
>
<
/Form.Item
>
)
:
(
''
)}
{
sortModalVisible
&&
permission
.
includes
(
'sortBtn'
)
?
(
<
Form
.
Item
>
<
Button
type
=
{
'primary'
}
title
=
{
'自定义排序'
}
icon
=
{
<
SortAscendingOutlined
/>
}
onClick
=
{()
=>
setModalVisible
(
true
)}
>
排序
<
/Button
>
<
/Form.Item
>
)
:
(
''
)}
{
permission
.
includes
(
'exportBtn'
)
?
(
<
Form
.
Item
>
<
Dropdown
style
=
{{
float
:
'right'
}}
overlay
=
{
menu
}
>
<
Button
>
<
Space
>
导出
<
DownOutlined
/>
<
/Space
>
<
/Button
>
<
/Dropdown
>
<
/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
)
=>
{
setSorterObject
(
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
[
'单页'
],
true
)}
<
/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
[
'全部'
],
true
)}
<
/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
(
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
=
{
`
${
modalType
}
报表信息`
}
visible
=
{
!!
modalType
}
width
=
{
'80%'
}
footer
=
{
null
}
// visible={true}
destroyOnClose
onCancel
=
{()
=>
setModalType
(
''
)}
>
<
ReportEditForm
modalType
=
{
modalType
}
reportDetails
=
{
tableStruct
}
reportData
=
{
currentData
}
onCancel
=
{()
=>
{
setModalType
(
''
);
getData
(
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
)(
ReportsManage
);
packages/base-components/BasicReport/src/ReportsManage/ReportsManage.less
0 → 100644
View file @
48ac1217
@import '~antd/es/style/themes/default.less';
.lackParams {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
}
.reportManage {
display: flex;
flex-direction: column;
height: 100%;
padding: 8px;
.contentWrapper {
display: flex;
flex-direction: column;
height: 100%;
.controlRow {
display: flex;
flex-direction: row;
margin-bottom: 4px;
padding: 6px;
background: #ffffff;
border-radius: 4px;
}
.tableContent {
flex: 1;
padding: 6px;
background: #ffffff;
.handleColumnWrapper {
display: flex;
justify-content: space-around;
.editButton {
cursor: pointer;
&:hover {
color: rgb(24, 144, 255);
}
}
.deleteButton {
color: rgb(255, 0, 0);
cursor: pointer;
&:hover {
//color: rgb(24, 144, 255);
}
}
}
.spinWrapper {
display: flex;
align-items: center;
justify-content: center;
width: 100vw;
height: 60vh;
}
:global {
.@{ant-prefix}-table-container {
height: 100%;
& > .@{ant-prefix}-table-body {
border-right: 1px solid #dbe7fb;
border-bottom: 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, 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 {
background: #dcdcdc;
border-radius: 5px;
}
}
}
packages/base-components/BasicReport/src/ReportsManage/ReportsPermissionDelete.js
0 → 100644
View file @
48ac1217
import
React
from
'react'
;
import
ReportsManage
from
'./ReportsManage'
;
const
ReportsPermissionDelete
=
(
props
)
=>
<
ReportsManage
{...
props
}
state
=
"delete"
/>
;
export
default
ReportsPermissionDelete
;
packages/base-components/BasicReport/src/ReportsManage/ReportsPermissionScan.js
0 → 100644
View file @
48ac1217
import
React
from
'react'
;
import
ReportsManage
from
'./ReportsManage'
;
const
ReportsPermissionScan
=
(
props
)
=>
<
ReportsManage
{...
props
}
state
=
"scan"
/>
;
export
default
ReportsPermissionScan
;
packages/base-components/BasicReport/src/ReportsManage/ReportsSetting.js
0 → 100644
View file @
48ac1217
/**
* * 报表设置列表 * create by ChenLong on 2022/6/28 *
* 功能路径:src\pages\product\ReportsManage\Components\ReportsSetting.js *
* 菜单参数列表:*变量名*(变量说明,数据类型,是否必填,取值范围) * @changelog: edit by ChenLong 2022年7月7日
* 增加日期类型的过滤,可以配置日期选择器,只允许存在一个日期类型的过滤;在表单提交时做校验 edit by ChenLong 2022年7月8日 表单的使用方式需要变更,需求为:1.
* 动态表单控件需要封装成组件; 2. 动态列表需要使用Form.List替换】 待执行 edit by ChenLong 2022年7月8日 变更单页、全部统计的规则
*/
import
React
,
{
useEffect
,
useRef
,
useState
}
from
'react'
;
import
{
DeleteOutlined
,
FormOutlined
,
MinusCircleOutlined
,
PlusOutlined
,
MenuOutlined
,
SettingOutlined
,
LeftOutlined
,
ExportOutlined
,
ImportOutlined
,
}
from
'@ant-design/icons'
;
import
{
Button
,
Checkbox
,
Divider
,
Form
,
Input
,
InputNumber
,
message
,
Modal
,
Row
,
Select
,
Space
,
Switch
,
Tooltip
,
Table
,
Upload
,
}
from
'antd'
;
import
{
SketchPicker
}
from
'react-color'
;
import
{
arrayMoveImmutable
}
from
'array-move'
;
import
BasicTable
from
'@wisdom-components/basictable'
;
import
{
reportService
}
from
'../api'
;
import
style
from
'./ReportsSetting.less'
;
import
classname
from
'classnames'
;
import
{
SortableContainer
,
SortableElement
,
SortableHandle
}
from
'react-sortable-hoc'
;
import
{
addReportDetailInfoIndex
,
API
,
exportReportConfig
,
importReportConfig
,
}
from
'../api/service/report'
;
import
{
isNumber
,
isString
}
from
'./utils/utils'
;
import
moment
from
'moment'
;
import
CustomerColorPicker
from
'./Components/customerColorPicker/CustomerColorPicker'
;
const
{
Option
}
=
Select
;
const
{
TextArea
}
=
Input
;
const
{
Search
}
=
Input
;
const
typeArray
=
[
'文本'
,
'标签'
,
'数值'
,
'链接'
,
'功能'
,
'弹窗'
,
'日期'
,
'日期时间'
,
'附件'
];
const
filterRule
=
[
'文本'
,
'下拉'
,
'多选'
,
'日期'
];
const
publicSplit
=
'&split;'
;
const
USER_ID
=
window
.
globalConfig
.
userInfo
.
OID
;
const
ReportsSetting
=
()
=>
{
// 报表列表
const
layout
=
{
labelCol
:
{
span
:
4
},
wrapperCol
:
{
span
:
20
},
};
const
[
form
]
=
Form
.
useForm
();
const
[
createMainTableForm
]
=
Form
.
useForm
();
const
[
patchSubTableForm
]
=
Form
.
useForm
();
const
[
editDetailForm
]
=
Form
.
useForm
();
const
watchType
=
Form
.
useWatch
(
'type'
,
form
);
const
showFilter
=
Form
.
useWatch
(
'isFilter'
,
form
);
const
fieldGroupLevel
=
Form
.
useWatch
(
'level'
,
form
);
const
isStatistics
=
Form
.
useWatch
(
'isStatistics'
,
form
);
const
[
isCreatingMainTable
,
setIsCreatingMainTable
]
=
useState
(
false
);
const
colorPicker
=
useRef
();
const
reportDetails
=
useRef
();
const
[
tableData
,
setTableData
]
=
useState
([]);
// 常规使用的数据
const
[
tableLoading
,
setTableLoading
]
=
useState
(
false
);
const
[
detailTableVisible
,
setDetailTableVisible
]
=
useState
(
false
);
const
columns
=
[
{
title
:
'报表名称'
,
dataIndex
:
'reportName'
,
key
:
'reportName'
,
},
{
title
:
'主表名称'
,
dataIndex
:
'tableName'
,
key
:
'tableName'
,
},
{
title
:
'报表字段'
,
dataIndex
:
'reportFields'
,
key
:
'reportFields'
,
// ellipsis:true,
render
:
(
text
)
=>
(
<
Tooltip
title
=
{
text
}
>
{
/* 自动折叠内容时,如果使用Tooltip,Tooltip会无法正确定位;建议手动设置内容折叠 */
}
<
span
className
=
{
style
.
reportFiled
}
>
{
text
}
<
/span
>
<
/Tooltip
>
),
},
{
title
:
'创建时间'
,
dataIndex
:
'createTime'
,
key
:
'createTime'
,
},
{
title
:
'创建人'
,
dataIndex
:
'creator'
,
key
:
'creator'
,
},
{
title
:
'操作'
,
width
:
120
,
render
:
(
text
,
record
)
=>
{
return
(
<
div
style
=
{{
display
:
'flex'
,
justifyContent
:
'space-around'
}}
>
<
FormOutlined
title
=
{
'编辑字段'
}
onClick
=
{()
=>
editReport
(
record
)}
style
=
{{
color
:
'#1685FF'
}}
/
>
<
SettingOutlined
title
=
{
'设置'
}
style
=
{{
color
:
'rgba(0,0,0,.55)'
}}
onClick
=
{()
=>
{
setCurrentReport
(
record
);
clickReport
(
record
.
id
);
}}
/
>
<
ExportOutlined
title
=
{
'导出配置'
}
onClick
=
{()
=>
exportConfigs
(
record
)}
/
>
<
DeleteOutlined
title
=
{
'删除报表'
}
style
=
{{
color
:
'red'
}}
onClick
=
{()
=>
deleteReport
(
record
.
id
)}
/
>
<
/div
>
);
},
},
];
// 详情表
const
[
detailData
,
setDetailData
]
=
useState
([]);
// 详情表的数据
const
[
tempDetailData
,
setTempDetailData
]
=
useState
([]);
// 备份数据
const
[
detailVisible
,
setDetailVisible
]
=
useState
(
false
);
const
[
backgroundColor
,
setBackgroundColor
]
=
useState
(
'rgba(0,0,0,.85)'
);
const
[
showSketchPicker
,
setShowSketchPicker
]
=
useState
(
false
);
const
[
createModalVisible
,
setCreateModalVisible
]
=
useState
(
false
);
const
[
activeID
,
setActiveID
]
=
useState
(
null
);
const
[
currentField
,
setCurrentField
]
=
useState
(
null
);
const
[
patchFieldVisible
,
setPatchFieldVisible
]
=
useState
(
false
);
const
[
subTableList
,
setSubTableList
]
=
useState
([]);
const
[
allTableList
,
setAllTableList
]
=
useState
([]);
// 数据库表
const
[
allFields
,
setAllFields
]
=
useState
([]);
// 新增主表时的选择的表字段
const
[
allSubFields
,
setAllSubFields
]
=
useState
([]);
// 新增子表字段
const
[
createBtnLoading
,
setCreateBtnLoading
]
=
useState
(
false
);
const
[
currentReport
,
setCurrentReport
]
=
useState
({});
const
[
colorCardPosition
,
setColorCardPosition
]
=
useState
({});
const
[
labelColorPickerArray
,
setLabelColorPickerArray
]
=
useState
([]);
// 标签色板
const
[
numberColorPickerArray
,
setNumberColorPickerArray
]
=
useState
([]);
// 数值色板
const
[
currentColorPicker
,
setCurrentColorPicker
]
=
useState
({
// 因为使用单例,需要记录是哪一个色板触发了
data
:
[],
callback
:
()
=>
{},
index
:
0
,
key
:
'init'
,
// init 初始化时的key,用来解决初始化报错的问题;wordColor 用来区分是那部分的色板
});
// 记录需要修改的对象
const
[
submitFieldLoading
,
setSubmitFieldLoading
]
=
useState
(
false
);
const
[
relationship
,
setRelationship
]
=
useState
([]);
const
[
patchSubTableBtnLoading
,
setPatchSubTableBtnLoading
]
=
useState
(
false
);
const
[
isEditing
,
setIsEditing
]
=
useState
(
true
);
const
[
detailTableLoading
,
setDetailTableLoading
]
=
useState
(
false
);
const
[
selectedRowKeys
,
setSelectedRowKeys
]
=
useState
([]);
const
[
selectedRows
,
setSelectedRows
]
=
useState
([]);
const
SortableItem
=
SortableElement
((
props
)
=>
<
tr
{...
props
}
/>
)
;
const
SortableBody
=
SortableContainer
((
props
)
=>
<
tbody
{...
props
}
/>
)
;
// 导入配置
const
uploadProps
=
{
action
:
`
${
window
.
location
.
origin
}${
API
.
IMPORT_REPORT_DATA
}
`
,
multiple
:
false
,
showUploadList
:
false
,
headers
:
{
'Content-Type'
:
'multipart/form-data'
,
},
withCredentials
:
true
,
customRequest
({
action
,
file
,
headers
,
withCredentials
})
{
const
formData
=
new
FormData
();
formData
.
append
(
'file'
,
file
);
const
_data
=
{
userId
:
USER_ID
};
importReportConfig
(
{
headers
:
{
'Content-Type'
:
'multipart/form-data'
,
},
},
{
...
_data
},
formData
,
).
then
((
res
)
=>
{
if
(
res
.
code
===
0
)
{
message
.
success
(
'导入成功!'
);
getData
();
}
else
{
message
.
info
(
res
.
msg
);
}
});
},
};
const
onSortEnd
=
({
oldIndex
,
newIndex
})
=>
{
if
(
oldIndex
!==
newIndex
)
{
const
newData
=
arrayMoveImmutable
(
detailData
.
slice
(),
oldIndex
,
newIndex
).
filter
(
(
el
)
=>
!!
el
,
);
console
.
log
(
'Sorted items: '
,
newData
);
setDetailData
(
newData
);
setTempDetailData
(
newData
);
editDetailForm
.
setFieldsValue
(
newData
);
saveOrder
(
newData
);
}
};
const
DraggableContainer
=
(
props
)
=>
(
<
SortableBody
useDragHandle
disableAutoscroll
helperClass
=
"row-dragging"
onSortEnd
=
{
onSortEnd
}
{...
props
}
/
>
);
const
DraggableBodyRow
=
({
className
,
style
,
...
restProps
})
=>
{
const
index
=
detailData
.
findIndex
((
x
)
=>
x
.
id
===
restProps
[
'data-row-key'
]);
return
<
SortableItem
index
=
{
index
}
{...
restProps
}
/>
;
};
const
returnEqual
=
(
index
,
key
)
=>
{
// return detailData !== tempDetailData || detailData[index] !== tempDetailData[index] || (detailData[index] && tempDetailData[index] && detailData[index][key] !== tempDetailData[index][key]);
return
(
(
detailData
[
index
]
&&
!
tempDetailData
[
index
])
||
(
detailData
[
index
]
&&
tempDetailData
[
index
]
&&
detailData
[
index
][
key
]
!==
tempDetailData
[
index
][
key
])
);
};
const
detailColumns
=
[
{
title
:
''
,
dataIndex
:
'sort'
,
width
:
isEditing
?
0
:
30
,
className
:
'drag-visible'
,
render
:
()
=>
<
DragHandle
/>
,
},
{
title
:
'表名'
,
dataIndex
:
'tableName'
,
className
:
'drag-visible'
,
key
:
'tableName'
,
},
{
title
:
'字段名'
,
dataIndex
:
'fieldName'
,
key
:
'fieldName'
,
},
/* {
title: '别名',
dataIndex: 'fieldAlias',
key: 'fieldAlias',
render: (text, record, index) => {
return isEditing ? <Form.Item name={[index, 'fieldAlias']} rules={[{
required: true,
message: '请输入字段别名',
}]}><Input key={`fieldAlias_${index}`} value={record?.fieldAlias}
className={returnEqual(index, 'fieldAlias') ? style.boxShadow : ''}
onChange={(e) => modifyDetailData('fieldAlias', e.target.value, record, index)} /></Form.Item> : text;
},
}, */
{
title
:
'字段组'
,
dataIndex
:
'fieldGroup'
,
key
:
'fieldGroup'
,
},
{
title
:
'形态'
,
dataIndex
:
'type'
,
key
:
'type'
,
width
:
60
,
},
{
title
:
'列宽'
,
dataIndex
:
'columnWidth'
,
key
:
'columnWidth'
,
width
:
120
,
render
:
(
text
,
record
,
index
)
=>
{
return
isEditing
?
(
<
Form
.
Item
name
=
{[
index
,
'columnWidth'
]}
rules
=
{[
{
required
:
true
,
message
:
'列宽不能为空'
,
},
]}
>
<
InputNumber
value
=
{
record
?.
columnWidth
}
className
=
{
returnEqual
(
index
,
'columnWidth'
)
?
style
.
boxShadow
:
''
}
onChange
=
{(
e
)
=>
modifyDetailData
(
'columnWidth'
,
e
,
record
,
index
)}
/
>
<
/Form.Item
>
)
:
(
`
${
text
}
px`
);
},
},
{
title
:
'对齐方式'
,
dataIndex
:
'alignType'
,
key
:
'alignType'
,
width
:
80
,
render
:
(
text
,
record
,
index
)
=>
{
const
_map
=
{
left
:
'左'
,
right
:
'右'
,
center
:
'中'
,
};
return
isEditing
?
(
<
Form
.
Item
name
=
{[
index
,
'alignType'
]}
>
<
Select
onChange
=
{(
e
)
=>
modifyDetailData
(
'alignType'
,
e
,
record
,
index
)}
className
=
{
returnEqual
(
index
,
'alignType'
)
?
style
.
boxShadowOfSelect
:
''
}
>
<
Option
value
=
{
text
?
'left'
:
''
}
>
左
<
/Option
>
<
Option
value
=
{
'center'
}
>
中
<
/Option
>
<
Option
value
=
{
'right'
}
>
右
<
/Option
>
<
/Select
>
<
/Form.Item
>
)
:
(
_map
[
text
]
||
'左'
);
},
},
{
title
:
'是否固定'
,
dataIndex
:
'fixedColumn'
,
key
:
'fixedColumn'
,
width
:
120
,
render
:
(
text
,
record
,
index
)
=>
{
const
_map
=
{
left
:
'左'
,
right
:
'右'
,
};
return
isEditing
?
(
<
Form
.
Item
name
=
{[
index
,
'fixedColumn'
]}
>
<
Select
onChange
=
{(
e
)
=>
modifyDetailData
(
'fixedColumn'
,
e
,
record
,
index
)}
className
=
{
returnEqual
(
index
,
'fixedColumn'
)
?
style
.
boxShadowOfSelect
:
''
}
>
<
Option
value
=
{
''
}
>
不固定
<
/Option
>
<
Option
value
=
{
'left'
}
>
左
<
/Option
>
<
Option
value
=
{
'right'
}
>
右
<
/Option
>
<
/Select
>
<
/Form.Item
>
)
:
(
_map
[
text
]
||
'不固定'
);
},
},
{
title
:
'是否显示'
,
dataIndex
:
'isShow'
,
key
:
'isShow'
,
width
:
100
,
render
:
(
text
,
record
,
index
)
=>
{
return
isEditing
?
(
<
Form
.
Item
name
=
{[
index
,
'isShow'
]}
valuePropName
=
"checked"
>
<
Switch
onChange
=
{(
e
)
=>
modifyDetailData
(
'isShow'
,
e
,
record
,
index
)}
checkedChildren
=
"显示"
unCheckedChildren
=
"不显示"
defaultChecked
=
{
false
}
className
=
{
returnEqual
(
index
,
'isShow'
)
?
style
.
boxShadowOfSwitch
:
''
}
/
>
<
/Form.Item
>
)
:
text
?
(
'是'
)
:
(
'否'
);
},
},
{
title
:
'是否过滤'
,
dataIndex
:
'isFilter'
,
key
:
'isFilter'
,
width
:
120
,
render
:
(
text
,
record
,
index
)
=>
{
return
isEditing
?
(
<
Form
.
Item
name
=
{[
index
,
'isFilter'
]}
valuePropName
=
"checked"
>
<
Switch
onChange
=
{(
e
)
=>
modifyDetailData
(
'isFilter'
,
e
,
record
,
index
)}
checkedChildren
=
"开启"
unCheckedChildren
=
"关闭"
defaultChecked
=
{
false
}
className
=
{
returnEqual
(
index
,
'isFilter'
)
?
style
.
boxShadowOfSwitch
:
''
}
/
>
<
/Form.Item
>
)
:
text
?
(
'是'
)
:
(
'否'
);
},
},
{
title
:
'过滤类型'
,
dataIndex
:
'filterRule'
,
key
:
'filterRule'
,
width
:
120
,
render
:
(
text
,
record
,
index
)
=>
{
return
isEditing
?
(
<
Form
.
Item
name
=
{[
index
,
'filterRule'
]}
>
<
Select
disabled
=
{
!
record
.
isFilter
}
onChange
=
{(
e
)
=>
modifyDetailData
(
'filterRule'
,
e
,
record
,
index
)}
className
=
{
returnEqual
(
index
,
'filterRule'
)
?
style
.
boxShadowOfSelect
:
''
}
>
<
Option
value
=
{
''
}
>
不过滤
<
/Option
>
{
filterRule
.
map
((
item
)
=>
(
<
Option
value
=
{
item
}
>
{
item
}
<
/Option
>
))}
<
/Select
>
<
/Form.Item
>
)
:
(
text
);
},
},
{
title
:
'向下合并'
,
dataIndex
:
'isMerge'
,
key
:
'isMerge'
,
width
:
120
,
render
:
(
text
,
record
,
index
)
=>
{
return
isEditing
?
(
<
Form
.
Item
name
=
{[
index
,
'isMerge'
]}
valuePropName
=
"checked"
>
<
Switch
onChange
=
{(
e
)
=>
modifyDetailData
(
'isMerge'
,
e
,
record
,
index
)}
checkedChildren
=
"开启"
unCheckedChildren
=
"关闭"
defaultChecked
=
{
false
}
className
=
{
returnEqual
(
index
,
'isMerge'
)
?
style
.
boxShadowOfSwitch
:
''
}
/
>
<
/Form.Item
>
)
:
text
?
(
'合并'
)
:
(
'不合并'
);
},
},
{
title
:
'是否必填'
,
dataIndex
:
'isRequired'
,
key
:
'isRequired'
,
width
:
100
,
render
:
(
text
,
record
,
index
)
=>
{
return
isEditing
?
(
<
Form
.
Item
name
=
{[
index
,
'isRequired'
]}
valuePropName
=
"checked"
>
<
Switch
onChange
=
{(
e
)
=>
modifyDetailData
(
'isRequired'
,
e
,
record
,
index
)}
checkedChildren
=
"是"
unCheckedChildren
=
"否"
defaultChecked
=
{
false
}
className
=
{
returnEqual
(
index
,
'isRequired'
)
?
style
.
boxShadowOfSwitch
:
''
}
/
>
<
/Form.Item
>
)
:
text
?
(
'是'
)
:
(
'否'
);
},
},
{
title
:
'操作'
,
width
:
80
,
render
:
(
text
,
record
)
=>
{
return
(
<
div
style
=
{{
display
:
'flex'
,
justifyContent
:
'space-around'
}}
>
<
FormOutlined
onClick
=
{()
=>
{
setActiveID
(
record
.
id
);
if
(
record
.
color
)
setBackgroundColor
(
record
.
color
);
form
.
setFieldsValue
(
setDefaultValue
(
record
));
setCurrentField
(
setDefaultValue
(
record
));
setDetailVisible
(
true
);
}}
/
>
<
DeleteOutlined
onClick
=
{()
=>
deleteReportDetail
(
record
.
id
)}
style
=
{{
color
:
'red'
}}
/
>
<
/div
>
);
},
},
];
const
rowSelection
=
{
onChange
:
(
selectedRowKeys
,
selectedRows
)
=>
{
setSelectedRowKeys
(
selectedRowKeys
);
setSelectedRows
(
selectedRows
);
},
};
const
wordInputWidth
=
300
;
const
numberInputWidth
=
120
;
const
rangeWidth
=
500
;
const
tagWidth
=
400
;
const
getData
=
()
=>
{
setTableLoading
(
true
);
reportService
.
getReportConfigList
()
.
then
((
res
)
=>
{
if
(
res
.
code
===
0
)
{
// 增加visible属性,后续搜索时需要
let
_data
=
res
.
data
.
map
((
item
)
=>
{
let
_item
=
{
...
item
};
_item
.
visible
=
true
;
return
_item
;
});
setTableData
(
_data
);
}
else
{
message
.
error
(
res
.
msg
);
}
setTableLoading
(
false
);
})
.
catch
((
err
)
=>
{
setTableLoading
(
false
);
});
};
const
clickReport
=
(
reportId
)
=>
{
setTableLoading
(
true
);
reportService
.
getReportDetailsInfo
({
reportId
})
.
then
((
res
)
=>
{
if
(
res
.
code
===
0
)
{
setTableLoading
(
false
);
setDetailTableVisible
(
true
);
// 增加visible属性,方便后续检索的属性变更
let
_final
=
res
.
data
.
details
.
map
((
item
)
=>
{
let
_item
=
{
...
item
};
_item
.
visible
=
true
;
return
_item
;
});
editDetailForm
.
setFieldsValue
(
_final
);
setDetailData
(
_final
);
setTempDetailData
(
_final
);
// 存储关联关系
setRelationship
(
res
.
data
.
child
);
}
})
.
catch
((
err
)
=>
{
setTableLoading
(
false
);
});
};
const
restCreateReportForm
=
()
=>
{
createMainTableForm
.
resetFields
();
setAllFields
([]);
};
const
createReport
=
()
=>
{
setCreateBtnLoading
(
true
);
createMainTableForm
.
validateFields
()
.
then
((
values
)
=>
{
let
_data
=
{
reportName
:
values
.
reportName
,
tableName
:
values
.
tableName
,
reportFields
:
values
.
reportFields
.
join
(
','
),
creator
:
String
(
globalConfig
.
userInfo
.
OID
),
};
if
(
currentReport
&&
currentReport
.
id
)
{
_data
.
id
=
currentReport
.
id
;
return
editReportOrSubTable
({
rM_ReportInfo
:
[
_data
]
},
()
=>
{
setCreateBtnLoading
(
false
);
setCreateModalVisible
(
false
);
getData
();
restCreateReportForm
();
});
}
addReportOrPatchSubTable
({
rM_ReportInfo
:
[
_data
]
},
()
=>
{
setCreateBtnLoading
(
false
);
setCreateModalVisible
(
false
);
getData
();
restCreateReportForm
();
});
})
.
catch
((
err
)
=>
{
setCreateBtnLoading
(
false
);
});
};
const
deleteReport
=
(
reportId
)
=>
{
Modal
.
confirm
({
title
:
'请确认'
,
content
:
'是否删除该报表?'
,
onOk
:
()
=>
{
reportService
.
deleteReportInfo
({
reportId
}).
then
((
res
)
=>
{
if
(
res
.
code
===
0
)
{
message
.
success
(
'删除成功!'
);
getData
();
}
});
},
});
};
const
deleteReportDetail
=
(
reportDetailId
)
=>
{
Modal
.
confirm
({
title
:
'请确认'
,
content
:
'是否删除该参数?'
,
onOk
:
()
=>
{
reportService
.
deleteReportDetailInfo
({
reportDetailId
}).
then
((
res
)
=>
{
if
(
res
.
code
===
0
)
{
clickReport
(
currentReport
.
id
);
message
.
success
(
'删除成功!'
);
}
else
{
message
.
error
(
res
.
code
);
}
});
},
});
};
const
deleteField
=
()
=>
{};
const
editReport
=
(
record
)
=>
{
openCreateModal
();
setCurrentReport
(
record
);
setIsCreatingMainTable
(
false
);
createMainTableForm
.
setFieldsValue
({
tableName
:
record
.
tableName
,
reportName
:
record
.
reportName
,
reportFields
:
record
.
reportFields
.
split
(
','
),
});
getFieldsFromTable
(
record
.
tableName
,
'mainTable'
);
};
const
addReportOrPatchSubTable
=
(
data
,
callback
)
=>
{
reportService
.
addReportInfo
(
data
).
then
((
res
)
=>
{
if
(
res
.
code
===
0
)
{
message
.
success
(
'提交成功!'
);
}
else
{
message
.
error
(
res
.
msg
);
}
if
(
callback
)
callback
();
});
};
const
editReportOrSubTable
=
(
data
,
callback
)
=>
{
reportService
.
editReportInfo
(
data
).
then
((
res
)
=>
{
if
(
res
.
code
===
0
)
{
message
.
success
(
'提交成功!'
);
}
else
{
message
.
error
(
res
.
msg
);
}
if
(
callback
)
callback
();
});
};
// 切换字段的同时,如果数据有修改,那需要保存之前的数据 edit by ChenLong 2022年8月29日
const
changeField
=
(
record
)
=>
{
// submitReportDetails('changeField').then(res => {
setActiveID
(
record
.
id
);
form
.
setFieldsValue
(
setDefaultValue
(
record
));
// 手动设置文字的颜色
setBackgroundColor
(
record
.
color
);
// 手动设置labelConfig和number的设置
setNumberColorPickerArray
(
record
.
numericalConfigs
);
setLabelColorPickerArray
(
record
.
labelConfigs
);
setCurrentField
(
setDefaultValue
(
record
));
// 为了确保前后数据统一
// });
};
const
setDefaultValue
=
(
record
)
=>
{
if
(
!
record
)
return
{};
let
_record
=
{
...
record
};
if
(
!
_record
.
type
)
_record
.
type
=
'文本'
;
if
(
isString
(
_record
.
fieldGroup
))
{
_record
.
fieldGroup
=
_record
.
fieldGroup
.
split
(
'-'
).
reduce
((
final
,
curr
,
index
)
=>
{
final
[
`fieldGroup_
${
record
.
fieldAlias
}
_
${
index
}
`
]
=
curr
;
return
final
;
},
{});
}
if
(
!
_record
.
filterRule
)
_record
.
filterRule
=
'下拉'
;
if
(
!
_record
.
statisticsRule
)
_record
.
statisticsRule
=
'求和'
;
// 统计规则变更
if
(
isString
(
_record
.
statisticsData
))
_record
.
statisticsData
=
{
单页
:
_record
.
statisticsData
.
includes
(
'单页'
),
全部
:
_record
.
statisticsData
.
includes
(
'全部'
),
};
// 对齐方式设置默认值
if
(
!
_record
.
alignType
)
_record
.
alignType
=
'left'
;
return
_record
;
};
// @params: {type:String} 不传入type,默认提交表单、关闭表单;传入type时
const
submitReportDetails
=
(
type
)
=>
{
// 1.表单内的值;2.标签值
return
form
.
validateFields
().
then
((
value
)
=>
{
// 需要将表单内带索引的fieldGroup_[number]处理成后端需要的fieldGroups: a-b-c-d;
value
.
fieldGroup
=
Object
.
values
(
value
.
fieldGroup
).
join
(
'-'
);
let
_value
=
Object
.
assign
(
currentField
,
value
);
// 处理数值颜色和标签颜色
// 后端需求:labelConfig和numberConfig里面都需要设置默认configId并且id设置为0;
if
(
numberColorPickerArray
.
length
)
_value
.
numericalConfigs
=
numberColorPickerArray
.
map
((
item
)
=>
{
let
_item
=
{
...
item
};
Object
.
keys
(
_item
).
forEach
((
key
)
=>
{
if
(
_item
[
key
]
===
''
)
_item
[
key
]
=
null
;
});
_item
.
configId
=
_value
.
id
;
_item
.
id
=
0
;
return
_item
;
});
if
(
labelColorPickerArray
.
length
)
_value
.
labelConfigs
=
labelColorPickerArray
.
map
((
item
)
=>
{
let
_item
=
{
...
item
};
_item
.
configId
=
_value
.
id
;
_item
.
id
=
0
;
return
_item
;
});
// 文字的颜色
if
(
backgroundColor
)
{
_value
.
color
=
backgroundColor
;
}
// 过滤规则的设置,需要确保日期类型的过滤规则字段是唯一的
let
_isDateArray
=
detailData
.
filter
((
item
)
=>
item
.
filterRule
===
'日期'
);
if
(
_isDateArray
.
length
>
1
||
(
_isDateArray
.
length
===
1
&&
_value
.
filterRule
===
'日期'
&&
_isDateArray
[
0
].
fieldName
!==
_value
.
fieldName
)
)
return
message
.
error
(
'已存在日期类型的过滤,请确保日期类型的过滤规则只存在一个!'
);
// 统计规则的提交变更
let
_statisticsData
=
_value
.
statisticsData
;
_value
.
statisticsData
=
Object
.
keys
(
_statisticsData
)
.
filter
((
key
)
=>
_statisticsData
[
key
])
.
join
(
','
);
// 提交请求
setSubmitFieldLoading
(
true
);
reportService
.
addReportDetailInfo
({
reportDetails
:
[
_value
]
}).
then
((
res
)
=>
{
if
(
res
.
code
===
0
)
{
message
.
success
(
'提交成功!'
);
}
else
{
message
.
error
(
res
.
msg
);
}
setSubmitFieldLoading
(
false
);
if
(
!
type
)
{
setDetailVisible
(
false
);
}
clickReport
(
currentReport
.
id
);
});
});
};
const
searchReportList
=
(
e
)
=>
{
let
_data
=
[...
tableData
];
let
final
=
_data
.
map
((
item
)
=>
{
let
_item
=
{
...
item
};
if
(
!
e
)
{
_item
.
visible
=
true
;
}
else
{
_item
.
visible
=
_item
.
reportName
.
includes
(
e
);
}
return
_item
;
});
setTableData
(
final
);
};
const
openCreateModal
=
(
callback
)
=>
{
if
(
callback
)
callback
();
getTableFromDB
((
data
)
=>
{
setAllTableList
(
data
);
setCreateModalVisible
(
true
);
});
};
const
getTableFromDB
=
(
callback
)
=>
{
reportService
.
getTables
().
then
((
res
)
=>
{
if
(
res
.
code
===
0
)
{
callback
(
res
.
data
);
}
else
{
message
.
error
(
res
.
msg
);
}
});
};
const
getFieldsFromTable
=
(
tableName
,
type
)
=>
{
let
_data
=
tableName
.
split
(
','
).
map
((
name
)
=>
({
name
:
name
}));
reportService
.
getTableFields
({
tableName
:
_data
}).
then
((
res
)
=>
{
if
(
res
.
code
===
0
)
{
if
(
type
===
'mainTable'
)
{
setAllFields
(
res
.
data
[
0
].
fieldName
);
}
if
(
type
===
'subTable'
)
{
// setTable
setAllSubFields
(
res
.
data
);
}
}
});
};
const
showPatchSubModal
=
()
=>
{
getTableFromDB
((
data
)
=>
{
setSubTableList
(
data
.
filter
((
item
)
=>
item
.
name
!==
currentReport
.
tableName
));
});
setPatchFieldVisible
(
true
);
getFieldsFromTable
(
currentReport
.
tableName
,
'mainTable'
);
let
subTableName
=
relationship
.
map
((
item
)
=>
item
.
tableName
);
if
(
subTableName
&&
subTableName
.
length
)
getFieldsFromTable
(
subTableName
.
join
(
','
),
'subTable'
);
let
_relationshipObject
=
{};
relationship
.
forEach
((
item
)
=>
{
let
_arr
=
item
.
relation
.
split
(
'='
);
_relationshipObject
[
item
.
tableName
+
publicSplit
+
'mainTable'
]
=
_arr
[
0
];
_relationshipObject
[
item
.
tableName
+
publicSplit
+
'subTable'
]
=
_arr
[
1
];
});
patchSubTableForm
.
setFieldsValue
({
subTableName
,
subTableFields
:
detailData
.
map
((
item
)
=>
item
.
tableName
+
publicSplit
+
item
.
fieldName
),
...
_relationshipObject
,
});
};
const
addVirtualColumn
=
()
=>
{
// 添加虚拟列;1. 增加字段;2.保存
const
_detailData
=
[...
detailData
];
const
_temp
=
{
...
_detailData
[
0
]
};
delete
_temp
.
id
;
// delete _temp.tableName;
_temp
.
index
=
_detailData
.
length
-
1
;
_temp
.
isVirtualColumn
=
true
;
//fieldAlias: "软件开票"
// fieldGroup: "软件开票"
// fieldName: "软件开票"
_temp
.
fieldAlias
=
_temp
.
fieldGroup
=
_temp
.
fieldName
=
`虚拟字段
${
moment
().
format
(
'YYYY-MM-DD-HH-mm-ss'
).
replace
(
/-/g
,
''
)}
`
;
_detailData
.
push
(
_temp
);
setDetailData
(
_detailData
);
// setTempDetailData(_detailData);
editDetailForm
.
setFieldsValue
(
_detailData
);
// submitDetailFromTable();
};
const
editDetailInTable
=
()
=>
{
// setIsEditing(true);
};
const
submitDetailFromTable
=
()
=>
{
setDetailTableLoading
(
true
);
editDetailForm
.
validateFields
().
then
((
res
)
=>
{
// 去除掉标签、数字区间内的id
let
_detailData
=
detailData
.
map
((
item
)
=>
{
let
_item
=
{
...
item
};
_item
.
numericalConfigs
=
_item
.
numericalConfigs
.
map
((
obj
)
=>
{
let
_obj
=
{
...
obj
};
_obj
.
id
=
0
;
return
_obj
;
});
_item
.
labelConfigs
=
_item
.
labelConfigs
.
map
((
obj
)
=>
{
let
_obj
=
{
...
obj
};
_obj
.
id
=
0
;
return
_obj
;
});
return
_item
;
});
reportService
.
addReportDetailInfo
({
reportDetails
:
_detailData
})
.
then
((
res
)
=>
{
if
(
res
.
code
===
0
)
{
message
.
success
(
'提交成功!'
);
}
else
{
message
.
error
(
res
.
msg
);
}
setDetailTableLoading
(
false
);
setSubmitFieldLoading
(
false
);
setDetailVisible
(
false
);
clickReport
(
currentReport
.
id
);
})
.
catch
((
err
)
=>
{
setDetailTableLoading
(
false
);
});
});
};
const
patchSubTable2MainTable
=
()
=>
{
patchSubTableForm
.
validateFields
().
then
(
async
(
value
)
=>
{
setPatchSubTableBtnLoading
(
true
);
// 由于是动态表单数据,导致表单对象无法正常监听数据,要过滤掉未能监听的数据。
let
_tempArray
=
value
.
subTableFields
.
filter
((
item
)
=>
value
.
subTableName
.
includes
(
item
.
split
(
publicSplit
)[
0
]))
.
map
((
item
)
=>
item
.
split
(
publicSplit
));
let
_tempObject
=
{};
_tempArray
.
forEach
((
item
)
=>
{
if
(
_tempObject
[
item
[
0
]])
{
_tempObject
[
item
[
0
]].
push
(
item
[
1
]);
}
else
{
_tempObject
[
item
[
0
]]
=
[
item
[
1
]];
}
});
let
rM_ReportInfo
=
Object
.
keys
(
_tempObject
).
map
((
key
)
=>
{
return
{
parentId
:
currentReport
.
id
,
tableName
:
key
,
reportFields
:
_tempObject
[
key
].
join
(
','
),
relation
:
`
${
value
[
key
+
`
${
publicSplit
}
mainTable`
]}
=
${
value
[
key
+
`
${
publicSplit
}
subTable`
]
}
`
,
};
});
await
reportService
.
addReportInfo
({
rM_ReportInfo
,
})
.
then
((
res
)
=>
{
if
(
res
.
code
===
0
)
{
message
.
success
(
'保存成功!'
);
setPatchFieldVisible
(
false
);
}
else
{
message
.
error
(
res
.
msg
);
}
})
.
catch
((
err
)
=>
{
message
.
error
(
'保存失败!'
);
setPatchSubTableBtnLoading
(
false
);
});
setPatchSubTableBtnLoading
(
false
);
clickReport
(
currentReport
.
id
);
});
};
const
clickColorCard
=
(
e
)
=>
{
let
_cardPosition
=
e
.
target
.
getBoundingClientRect
();
let
_wrapperPosition
=
reportDetails
.
current
.
getBoundingClientRect
();
let
_colorPicker
=
colorPicker
.
current
.
getBoundingClientRect
();
// 减去最外层的边距之后,还需要减去色块的高度+外边白边的高度+1px的边框+1px间隙 + 8px的最外层容器的padding
let
_cardLeft
=
_cardPosition
.
left
-
_wrapperPosition
.
left
-
4
-
8
;
let
_cardTop
=
_cardPosition
.
top
-
_wrapperPosition
.
top
+
14
+
4
+
1
+
1
-
8
;
// 需要考虑超出边距的问题,如果超出边界,则向上,向左平移
let
isOuterOfBottom
=
_cardTop
+
_colorPicker
.
height
-
_wrapperPosition
.
height
;
// let isOuterOfRight = (_colorPicker.left + _colorPicker.width) - (_wrapperPosition.top + _wrapperPosition.height);
if
(
isOuterOfBottom
>
0
)
{
_cardTop
-=
isOuterOfBottom
+
10
;
// 向上平移,10px保证显示效果
_cardLeft
-=
_colorPicker
.
width
+
5
;
// 向左平移,5px保证显示效果
}
setColorCardPosition
({
left
:
_cardLeft
,
top
:
_cardTop
,
});
setShowSketchPicker
(
true
);
};
const
addColorPicker
=
(
data
,
callback
,
init
)
=>
{
let
_labels
=
[...
data
];
_labels
.
push
(
init
);
callback
(
_labels
);
};
const
removeColorPicker
=
(
data
,
callback
,
index
)
=>
{
let
_labels
=
[...
data
];
_labels
.
splice
(
index
,
1
);
callback
(
_labels
);
};
const
changeColorLabel
=
(
e
,
data
,
callback
,
key
,
index
)
=>
{
// 接口需要id全部为 0
let
_labels
=
[...
data
];
_labels
[
index
][
key
]
=
isNumber
(
e
)
?
e
:
e
.
target
.
value
;
// e为数值时是InputNumber,e为对象时是Input
callback
(
_labels
);
};
const
changeBackgroundColor
=
(
e
)
=>
{
// 改变当前的
let
_rgb
=
e
.
rgb
;
if
(
currentColorPicker
.
key
===
'wordColor'
)
{
setBackgroundColor
(
`rgba(
${
_rgb
.
r
}
,
${
_rgb
.
g
}
,
${
_rgb
.
b
}
,
${
_rgb
.
a
}
)`
);
return
;
}
let
{
data
,
callback
,
index
,
key
}
=
currentColorPicker
;
let
_data
=
[...
data
];
if
(
currentColorPicker
.
key
===
'tagColor'
)
{
_data
[
index
].
color
=
e
;
}
else
{
_data
[
index
][
key
]
=
`rgba(
${
_rgb
.
r
}
,
${
_rgb
.
g
}
,
${
_rgb
.
b
}
,
${
_rgb
.
a
}
)`
;
}
callback
(
_data
);
};
const
returnCurrentColor
=
()
=>
{
let
{
data
,
index
,
key
}
=
currentColorPicker
;
if
(
key
===
'init'
)
return
'rgba(0,0,0,.65)'
;
return
data
[
index
][
key
];
};
// 拖拽
const
DragHandle
=
SortableHandle
(()
=>
(
<
MenuOutlined
style
=
{{
cursor
:
'grab'
,
color
:
'#999'
,
}}
/
>
));
const
saveOrder
=
(
data
)
=>
{
let
_data
=
data
.
map
((
item
,
index
)
=>
{
let
_item
=
{};
_item
.
index
=
index
;
_item
.
id
=
item
.
id
;
return
_item
;
});
addReportDetailInfoIndex
(
_data
).
then
((
res
)
=>
{
if
(
res
.
code
!==
0
)
{
message
.
error
(
res
.
msg
);
}
else
{
clickReport
(
currentReport
.
id
);
}
});
};
const
submitDetail
=
(
data
)
=>
{
reportService
.
addReportDetailInfo
({
reportDetails
:
data
}).
then
((
res
)
=>
{
if
(
res
.
code
===
0
)
{
message
.
success
(
'提交成功!'
);
}
else
{
message
.
error
(
res
.
msg
);
}
setSubmitFieldLoading
(
false
);
clickReport
(
currentReport
.
id
);
});
};
const
modifyDetailData
=
(
key
,
value
,
record
,
index
,
data
=
detailData
)
=>
{
let
_data
=
[...
data
];
let
_record
=
{
...
record
};
_record
[
key
]
=
value
;
_data
.
splice
(
index
,
1
,
_record
);
setDetailData
(
_data
);
};
const
batchModify
=
(
key
,
value
)
=>
{
console
.
log
(
key
,
':'
,
value
);
// 1.取出勾选的字段;2.批量修改值
if
(
selectedRowKeys
.
length
===
0
)
return
message
.
info
(
'未勾选任何字段'
);
let
_detailData
=
detailData
.
map
((
item
)
=>
{
let
_item
=
{
...
item
};
if
(
selectedRowKeys
.
includes
(
_item
.
id
))
{
_item
[
key
]
=
value
;
}
return
_item
;
});
setDetailData
(
_detailData
);
editDetailForm
.
setFieldsValue
(
_detailData
);
};
const
exportConfigs
=
(
record
)
=>
{
setTableLoading
(
true
);
exportReportConfig
(
{
responseType
:
'blob'
},
{
reportId
:
record
.
id
,
},
).
then
((
res
)
=>
{
setTableLoading
(
false
);
if
(
res
&&
res
.
code
===
-
1
)
return
message
.
error
(
res
.
msg
);
const
url
=
window
.
URL
.
createObjectURL
(
new
Blob
([
res
],
{
type
:
'application/json;charset=UTF-8'
}),
);
const
a
=
document
.
createElement
(
'a'
);
a
.
href
=
url
;
a
.
target
=
'_blank'
;
a
.
download
=
`
${
record
.
reportName
}
.json`
;
a
.
click
();
a
.
remove
();
});
};
useEffect
(()
=>
{
getData
();
},
[]);
useEffect
(()
=>
{
let
numericalConfigs
=
currentField
?
currentField
.
numericalConfigs
:
[];
let
labelConfigs
=
currentField
?
currentField
.
labelConfigs
:
[];
setNumberColorPickerArray
(
numericalConfigs
);
setLabelColorPickerArray
(
labelConfigs
);
},
[
watchType
]);
return
(
<
div
className
=
{
style
.
reportSettings
}
>
{
detailTableVisible
?
(
<
div
ref
=
{
reportDetails
}
className
=
{
style
.
reportDetails
}
>
{
/* 色板容器 */
}
<
div
onClick
=
{(
e
)
=>
{
if
(
e
.
target
.
className
.
includes
(
'colorSketch'
))
{
setShowSketchPicker
(
false
);
}
}}
style
=
{{
visibility
:
showSketchPicker
?
'visible'
:
'hidden'
,
}}
className
=
{
style
.
colorSketch
}
>
<
div
ref
=
{
colorPicker
}
style
=
{{
position
:
'absolute'
,
left
:
colorCardPosition
.
left
,
top
:
colorCardPosition
.
top
,
}}
>
{
currentColorPicker
.
key
===
'tagColor'
?
(
<
CustomerColorPicker
clickColorPicker
=
{(
backgroundColor
)
=>
{
changeBackgroundColor
(
backgroundColor
);
}}
/
>
)
:
(
<
SketchPicker
width
=
{
240
}
presetColors
=
{[
'rgb(129, 134, 143)'
,
'rgb(41, 114, 244)'
,
'rgb(0, 163, 245)'
,
'rgb(69, 176, 118)'
,
'rgb(222, 60, 54)'
,
'rgb(248, 136, 37)'
,
'rgb(216,180,255)'
,
'rgb(154, 56, 215)'
,
'rgb(221, 64, 151)'
,
]}
color
=
{
currentColorPicker
.
key
===
'wordColor'
?
backgroundColor
:
returnCurrentColor
()
}
onChange
=
{(
e
)
=>
changeBackgroundColor
(
e
)}
/
>
)}
<
/div
>
<
/div
>
<
Modal
title
=
{
'附加子表'
}
width
=
{
600
}
visible
=
{
patchFieldVisible
}
onCancel
=
{()
=>
{
setPatchFieldVisible
(
false
);
setAllFields
([]);
setAllSubFields
([]);
}}
onOk
=
{
patchSubTable2MainTable
}
okButtonProps
=
{{
loading
:
patchSubTableBtnLoading
,
}}
>
<
Form
form
=
{
patchSubTableForm
}
{...
layout
}
>
<
Form
.
Item
label
=
{
'子表'
}
rules
=
{[
{
required
:
true
,
message
:
'请选择需要附加的子表'
,
},
]}
name
=
{
'subTableName'
}
>
<
Select
placeholder
=
{
'请选择子表'
}
maxTagCount
=
{
2
}
style
=
{{
width
:
'100%'
}}
mode
=
{
'multiple'
}
onChange
=
{(
value
)
=>
{
console
.
log
(
value
);
getFieldsFromTable
(
value
.
join
(
','
),
'subTable'
);
}}
>
{
subTableList
.
map
((
item
)
=>
(
<
Option
value
=
{
item
.
name
}
>
{
item
.
name
}
<
/Option
>
))}
<
/Select
>
<
/Form.Item
>
{
allSubFields
&&
allSubFields
.
length
?
(
<
Form
.
Item
label
=
{
'子表字段'
}
rules
=
{[
{
required
:
true
,
message
:
'请选择字段'
,
},
]}
name
=
{
'subTableFields'
}
>
<
Checkbox
.
Group
style
=
{{
height
:
400
,
overflowY
:
'scroll'
}}
>
{
allSubFields
.
map
((
item
,
index
)
=>
{
return
(
<
div
>
<
Divider
orientation
=
"left"
>
{
item
.
tableName
}
<
/Divider
>
<
Row
style
=
{{
display
:
'flex'
}}
>
<
Form
.
Item
label
=
{
'主表'
}
name
=
{
`
${
item
.
tableName
}${
publicSplit
}
mainTable`
}
rules
=
{[
{
required
:
true
,
message
:
'请选择对应字段'
,
},
]}
>
<
Select
style
=
{{
width
:
150
}}
placeholder
=
{
'主表对应字段'
}
>
{
allFields
.
map
((
field
)
=>
(
<
Option
value
=
{
`
${
currentReport
.
tableName
}
.
${
field
.
name
}
`
}
>
{
field
.
name
}
<
/Option
>
))}
<
/Select
>
<
/Form.Item
>
<
Form
.
Item
label
=
{
'子表'
}
name
=
{
`
${
item
.
tableName
}${
publicSplit
}
subTable`
}
rules
=
{[
{
required
:
true
,
message
:
'请选择对应字段'
,
},
]}
>
<
Select
style
=
{{
width
:
150
}}
placeholder
=
{
'子表关联字段'
}
>
{
item
.
fieldName
.
map
((
field
)
=>
(
<
Option
value
=
{
`
${
item
.
tableName
}
.
${
field
.
name
}
`
}
>
{
field
.
name
}
<
/Option
>
))}
<
/Select
>
<
/Form.Item
>
<
/Row
>
{
item
.
fieldName
.
map
((
field
)
=>
{
return
(
<
Row
>
<
Checkbox
value
=
{
`
${
item
.
tableName
}${
publicSplit
}${
field
.
name
}
`
}
>
{
field
.
name
}
<
/Checkbox
>
<
/Row
>
);
})}
<
/div
>
);
})}
<
/Checkbox.Group
>
<
/Form.Item
>
)
:
(
''
)}
<
/Form
>
<
/Modal
>
<
Modal
title
=
{
'编辑字段属性'
}
width
=
{
920
}
visible
=
{
detailVisible
}
onCancel
=
{()
=>
setDetailVisible
(
false
)}
destroyOnClose
footer
=
{
null
}
onClick
=
{()
=>
setShowSketchPicker
(
false
)}
>
<
div
style
=
{{
display
:
'flex'
}}
>
<
div
style
=
{{
width
:
200
}}
>
{
detailData
?
(
<
ul
>
{
detailData
.
map
((
item
,
index
)
=>
(
<
li
onClick
=
{()
=>
changeField
(
item
)}
className
=
{
classname
(
style
.
fieldList
,
activeID
===
item
.
id
?
style
.
active
:
''
,
)}
key
=
{
item
.
id
}
>
{
item
.
fieldAlias
}
<
/li
>
))}
<
/ul
>
)
:
(
''
)}
<
/div
>
<
div
style
=
{{
flex
:
1
,
}}
>
{
/*<Form {...layout} form={form} initialValues={setDefaultValue(currentField)}*/
}
<
Form
{...
layout
}
form
=
{
form
}
onFinish
=
{
submitReportDetails
}
>
<
div
style
=
{{
height
:
500
,
overflowY
:
'scroll'
}}
>
<
Form
.
Item
disabled
label
=
{
'字段'
}
name
=
{
'fieldName'
}
rules
=
{[
{
required
:
true
,
message
:
'编码名称必填'
,
},
]}
>
<
Input
disabled
style
=
{{
width
:
wordInputWidth
}}
/
>
<
/Form.Item
>
<
Form
.
Item
label
=
{
'别名'
}
name
=
{
'fieldAlias'
}
rules
=
{[
{
required
:
true
,
message
:
'别名必填且不可重复'
,
},
]}
>
<
Input
style
=
{{
width
:
wordInputWidth
}}
/
>
<
/Form.Item
>
<
Form
.
Item
label
=
{
'表头级数'
}
name
=
{
'level'
}
rules
=
{[
{
required
:
true
,
message
:
'别名必填且不可重复'
,
},
]}
>
<
InputNumber
min
=
{
1
}
/
>
<
/Form.Item
>
{
fieldGroupLevel
?
(
<
Form
.
Item
style
=
{{
marginBottom
:
0
}}
label
=
{
'分组'
}
>
<
Input
.
Group
compact
>
{
new
Array
(
Number
(
fieldGroupLevel
)
*
2
-
1
).
fill
(
1
).
map
((
item
,
index
)
=>
{
if
(
index
%
2
===
0
)
{
return
(
<
Form
.
Item
key
=
{
`fieldGroup_
${
index
/
2
}
`
}
style
=
{{
width
:
160
}}
name
=
{[
'fieldGroup'
,
`fieldGroup_
${
currentField
.
fieldAlias
}
_
${
index
/
2
}
`
,
]}
rules
=
{[
{
required
:
true
,
message
:
'分组名称必填'
,
},
]}
>
<
Input
/>
<
/Form.Item
>
);
}
else
{
return
(
<
span
style
=
{{
color
:
'rgba(0,0,0,.25)'
}}
>
&
nbsp
;
_
&
nbsp
;
<
/span
>
);
}
})}
<
/Input.Group
>
<
/Form.Item
>
)
:
(
''
)}
<
Form
.
Item
label
=
{
'形态'
}
name
=
{
'type'
}
>
<
Select
style
=
{{
width
:
wordInputWidth
}}
>
{
typeArray
.
map
((
item
)
=>
(
<
Option
value
=
{
item
}
>
{
item
}
<
/Option
>
))}
<
/Select
>
<
/Form.Item
>
<
Form
.
Item
label
=
{
'字体颜色'
}
name
=
{
'color'
}
>
<
div
style
=
{{
padding
:
4
,
display
:
'inline-flex'
,
borderRadius
:
'2px'
,
border
:
'1px solid rgba(0,0,0,.35)'
,
}}
>
<
div
style
=
{{
width
:
'36px'
,
height
:
'14px'
,
borderRadius
:
'2px'
,
border
:
'1px solid rgba(0,0,0,.35)'
,
backgroundColor
:
backgroundColor
,
}}
onClick
=
{(
e
)
=>
{
clickColorCard
(
e
);
setCurrentColorPicker
({
key
:
'wordColor'
,
});
}}
/
>
<
/div
>
<
/Form.Item
>
{
watchType
===
'数值'
?
(
<
Form
.
Item
label
=
{
'区间设置'
}
>
{
numberColorPickerArray
.
map
((
item
,
index
)
=>
{
return
(
<
Space
key
=
{
item
.
key
}
style
=
{{
display
:
'flex'
,
marginBottom
:
8
,
width
:
rangeWidth
,
}}
align
=
"baseline"
>
<
Form
.
Item
label
=
{
'最小值'
}
>
<
InputNumber
value
=
{
item
.
minValue
}
onChange
=
{(
e
)
=>
changeColorLabel
(
e
,
numberColorPickerArray
,
setNumberColorPickerArray
,
'minValue'
,
index
,
)
}
/
>
<
/Form.Item
>
<
Form
.
Item
label
=
{
'最大值'
}
>
<
InputNumber
value
=
{
item
.
maxValue
}
onChange
=
{(
e
)
=>
changeColorLabel
(
e
,
numberColorPickerArray
,
setNumberColorPickerArray
,
'maxValue'
,
index
,
)
}
/
>
<
/Form.Item
>
<
Form
.
Item
label
=
{
'颜色'
}
>
<
div
style
=
{{
padding
:
4
,
display
:
'inline-flex'
,
borderRadius
:
'2px'
,
border
:
'1px solid rgba(0,0,0,.35)'
,
}}
>
<
div
style
=
{{
width
:
'36px'
,
height
:
'14px'
,
borderRadius
:
'2px'
,
border
:
'1px solid rgba(0,0,0,.35)'
,
backgroundColor
:
item
.
color
,
}}
onClick
=
{(
e
)
=>
{
clickColorCard
(
e
);
setCurrentColorPicker
({
data
:
numberColorPickerArray
,
callback
:
setNumberColorPickerArray
,
index
,
key
:
'color'
,
});
}}
/
>
<
/div
>
<
/Form.Item
>
<
MinusCircleOutlined
onClick
=
{()
=>
removeColorPicker
(
numberColorPickerArray
,
setNumberColorPickerArray
,
index
,
)
}
/
>
<
/Space
>
);
})}
<
Form
.
Item
>
<
Button
type
=
"dashed"
onClick
=
{()
=>
addColorPicker
(
numberColorPickerArray
,
setNumberColorPickerArray
,
{
maxValue
:
''
,
minValue
:
''
,
color
:
'rgba(0,0,0,.65)'
,
})
}
block
icon
=
{
<
PlusOutlined
/>
}
>
增加区间
<
/Button
>
<
/Form.Item
>
<
/Form.Item
>
)
:
(
''
)}
{
watchType
===
'数值'
?
(
<
Form
.
Item
label
=
{
'统计规则'
}
style
=
{{
display
:
'flex'
}}
>
<
Space
style
=
{{
display
:
'flex'
,
marginBottom
:
8
,
}}
>
<
Form
.
Item
style
=
{{
marginBottom
:
0
}}
name
=
{
'isStatistics'
}
valuePropName
=
{
'checked'
}
>
<
Switch
checkedChildren
=
"开启"
unCheckedChildren
=
"关闭"
defaultChecked
=
{
false
}
/
>
<
/Form.Item
>
{
isStatistics
?
(
<>
<
Form
.
Item
label
=
{
'统计规则'
}
rules
=
{[
{
required
:
true
,
message
:
'请选择统计规则'
,
},
]}
style
=
{{
marginBottom
:
0
}}
name
=
{
'statisticsRule'
}
>
<
Select
style
=
{{
width
:
120
}}
>
<
Option
value
=
{
'求和'
}
>
求和
<
/Option
>
<
Option
value
=
{
'求平均'
}
>
求平均
<
/Option
>
<
Option
value
=
{
'求方差'
}
>
求方差
<
/Option
>
<
/Select
>
<
/Form.Item
>
<
Form
.
Item
name
=
{[
'statisticsData'
,
'单页'
]}
style
=
{{
marginBottom
:
0
}}
label
=
{
'单页统计'
}
valuePropName
=
{
'checked'
}
>
<
Switch
checkedChildren
=
"开启"
unCheckedChildren
=
"关闭"
/>
<
/Form.Item
>
<
Form
.
Item
name
=
{[
'statisticsData'
,
'全部'
]}
style
=
{{
marginBottom
:
0
}}
label
=
{
'全部统计'
}
valuePropName
=
{
'checked'
}
>
<
Switch
checkedChildren
=
"开启"
unCheckedChildren
=
"关闭"
/>
<
/Form.Item
>
<
/
>
)
:
(
''
)}
<
/Space
>
<
/Form.Item
>
)
:
(
''
)}
{
watchType
===
'标签'
?
(
<
Form
.
Item
label
=
{
'标签设置'
}
>
{
labelColorPickerArray
.
map
((
item
,
index
)
=>
{
return
(
<
Space
key
=
{
item
.
key
}
style
=
{{
display
:
'flex'
,
marginBottom
:
8
,
}}
align
=
"baseline"
>
<
Form
.
Item
label
=
{
'标签'
}
>
<
Input
value
=
{
item
.
labelValue
}
onChange
=
{(
e
)
=>
changeColorLabel
(
e
,
labelColorPickerArray
,
setLabelColorPickerArray
,
'labelValue'
,
index
,
)
}
/
>
<
/Form.Item
>
<
Form
.
Item
label
=
{
'颜色'
}
>
<
div
style
=
{{
padding
:
4
,
display
:
'inline-flex'
,
borderRadius
:
'2px'
,
border
:
'1px solid rgba(0,0,0,.35)'
,
}}
>
<
div
style
=
{{
width
:
'36px'
,
height
:
'14px'
,
borderRadius
:
'2px'
,
border
:
'1px solid rgba(0,0,0,.35)'
,
backgroundColor
:
item
.
color
,
}}
onClick
=
{(
e
)
=>
{
clickColorCard
(
e
);
setCurrentColorPicker
({
data
:
labelColorPickerArray
,
callback
:
setLabelColorPickerArray
,
index
,
key
:
'tagColor'
,
});
}}
/
>
<
/div
>
<
/Form.Item
>
<
MinusCircleOutlined
onClick
=
{()
=>
removeColorPicker
(
labelColorPickerArray
,
setLabelColorPickerArray
,
index
,
)
}
/
>
<
/Space
>
);
})}
<
Form
.
Item
>
<
Button
type
=
"dashed"
onClick
=
{()
=>
addColorPicker
(
labelColorPickerArray
,
setLabelColorPickerArray
,
{
color
:
'rgba(0,0,0,.65)'
,
labelValue
:
''
,
})
}
block
icon
=
{
<
PlusOutlined
/>
}
>
增加区间
<
/Button
>
<
/Form.Item
>
<
/Form.Item
>
)
:
(
''
)}
<
Form
.
Item
label
=
{
'配置'
}
name
=
{
'configItems'
}
>
<
TextArea
rows
=
{
6
}
/
>
<
/Form.Item
>
<
/div
>
<
Form
.
Item
label
=
{
' '
}
colon
=
{
false
}
style
=
{{
marginTop
:
10
}}
>
<
Button
onClick
=
{()
=>
setDetailVisible
(
false
)}
>
取消
<
/Button
>
<
Button
loading
=
{
submitFieldLoading
}
style
=
{{
marginLeft
:
8
}}
type
=
"primary"
htmlType
=
"submit"
>
提交
<
/Button
>
<
/Form.Item
>
<
/Form
>
<
/div
>
<
/div
>
<
/Modal
>
<
div
className
=
{
style
.
tableWrapper
}
>
<
Row
className
=
{
style
.
controlRow
}
>
<
LeftOutlined
className
=
{
style
.
leftBtn
}
onClick
=
{()
=>
{
setDetailTableVisible
(
false
);
}}
/
>
<
Form
layout
=
{
'inline'
}
style
=
{{
display
:
'flex'
,
flex
:
1
,
justifyContent
:
'space-between'
}}
>
<
div
style
=
{{
display
:
'flex'
}}
>
<
Form
.
Item
label
=
{
'快速索引'
}
>
<
Search
onSearch
=
{(
e
)
=>
{
let
_detailData
=
detailData
.
map
((
item
)
=>
{
let
_item
=
{
...
item
};
if
(
e
)
{
_item
.
visible
=
item
.
fieldName
.
includes
(
e
)
||
item
.
fieldAlias
.
includes
(
e
);
}
else
{
_item
.
visible
=
true
;
}
return
_item
;
});
setDetailData
(
_detailData
);
setTempDetailData
(
_detailData
);
}}
/
>
<
/Form.Item
>
<
Form
.
Item
>
<
Button
style
=
{{
marginRight
:
8
}}
onClick
=
{
showPatchSubModal
}
>
附加子表
<
/Button
>
<
Button
onClick
=
{
addVirtualColumn
}
>
添加虚拟字段
<
/Button
>
<
/Form.Item
>
<
/div
>
<
Form
.
Item
style
=
{{
marginRight
:
0
}}
>
{
isEditing
?
(
<>
<
Button
style
=
{{
marginRight
:
8
}}
onClick
=
{()
=>
{
setDetailData
(
tempDetailData
);
editDetailForm
.
setFieldsValue
(
tempDetailData
);
}}
>
重置
<
/Button
>
<
Button
type
=
{
'primary'
}
loading
=
{
detailTableLoading
}
style
=
{{
marginRight
:
8
}}
onClick
=
{
submitDetailFromTable
}
>
保存字段
<
/Button
>
<
/
>
)
:
(
''
)}
{
isEditing
?
(
<
Button
type
=
{
'primary'
}
onClick
=
{()
=>
setIsEditing
(
false
)}
>
拖动排序
<
/Button
>
)
:
(
<
Button
type
=
{
'primary'
}
onClick
=
{()
=>
setIsEditing
(
true
)}
>
关闭排序
<
/Button
>
)}
<
/Form.Item
>
<
/Form
>
<
/Row
>
<
div
className
=
{
style
.
tableContent
}
>
<
Form
className
=
{
style
.
tableForm
}
form
=
{
editDetailForm
}
>
<
BasicTable
loading
=
{
detailTableLoading
}
pagination
=
{
false
}
bordered
scroll
=
{{
y
:
`calc(100% -
${
selectedRowKeys
.
length
?
90
:
40
}
px)`
}}
// 需要考虑总结栏的高度
rowKey
=
{
'id'
}
columns
=
{
detailColumns
}
rowSelection
=
{
isEditing
?
{
type
:
'checkbox'
,
...
rowSelection
,
}
:
null
}
dataSource
=
{
detailData
.
filter
((
item
)
=>
item
.
visible
)}
summary
=
{(
pageData
)
=>
{
if
(
detailData
&&
detailData
.
length
>
1
&&
isEditing
&&
selectedRows
.
length
)
{
return
(
<
Table
.
Summary
fixed
>
<
Table
.
Summary
.
Row
>
<
Table
.
Summary
.
Cell
colSpan
=
{
7
}
>
批量操作
<
/Table.Summary.Cell
>
<
Table
.
Summary
.
Cell
>
<
Form
.
Item
>
<
InputNumber
onChange
=
{(
e
)
=>
batchModify
(
'columnWidth'
,
e
)}
/
>
<
/Form.Item
>
<
/Table.Summary.Cell
>
<
Table
.
Summary
.
Cell
>
<
Form
.
Item
>
<
Select
onChange
=
{(
e
)
=>
batchModify
(
'alignType'
,
e
)}
>
<
Option
value
=
{
'left'
}
>
左
<
/Option
>
<
Option
value
=
{
'center'
}
>
中
<
/Option
>
<
Option
value
=
{
'right'
}
>
右
<
/Option
>
<
/Select
>
<
/Form.Item
>
<
/Table.Summary.Cell
>
<
Table
.
Summary
.
Cell
>
<
Form
.
Item
>
<
Select
onChange
=
{(
e
)
=>
batchModify
(
'fixedColumn'
,
e
)}
>
<
Option
value
=
{
''
}
>
不固定
<
/Option
>
<
Option
value
=
{
'left'
}
>
左
<
/Option
>
<
Option
value
=
{
'right'
}
>
右
<
/Option
>
<
/Select
>
<
/Form.Item
>
<
/Table.Summary.Cell
>
<
Table
.
Summary
.
Cell
>
<
Form
.
Item
>
<
Switch
checkedChildren
=
"显示"
unCheckedChildren
=
"不显示"
defaultChecked
=
{
false
}
onChange
=
{(
e
)
=>
batchModify
(
'isShow'
,
e
)}
/
>
<
/Form.Item
>
<
/Table.Summary.Cell
>
<
Table
.
Summary
.
Cell
>
<
Form
.
Item
>
<
Switch
checkedChildren
=
"开启"
unCheckedChildren
=
"关闭"
defaultChecked
=
{
false
}
onChange
=
{(
e
)
=>
batchModify
(
'isFilter'
,
e
)}
/
>
<
/Form.Item
>
<
/Table.Summary.Cell
>
<
Table
.
Summary
.
Cell
>
<
Form
.
Item
>
<
Select
onChange
=
{(
e
)
=>
batchModify
(
'isFilter'
,
e
)}
>
<
Option
value
=
{
''
}
>
不过滤
<
/Option
>
<
Option
value
=
{
'文本'
}
>
文本
<
/Option
>
<
Option
value
=
{
'下拉'
}
>
下拉
<
/Option
>
<
Option
value
=
{
'多选'
}
>
多选
<
/Option
>
<
Option
value
=
{
'日期'
}
>
日期
<
/Option
>
<
/Select
>
<
/Form.Item
>
<
/Table.Summary.Cell
>
<
Table
.
Summary
.
Cell
>
<
Form
.
Item
>
<
Switch
checkedChildren
=
"开启"
unCheckedChildren
=
"关闭"
defaultChecked
=
{
false
}
onChange
=
{(
e
)
=>
batchModify
(
'isMerge'
,
e
)}
/
>
<
/Form.Item
>
<
/Table.Summary.Cell
>
<
Table
.
Summary
.
Cell
>
<
Form
.
Item
>
<
DeleteOutlined
onClick
=
{()
=>
batchModify
(
'delete'
)}
title
=
{
'批量删除'
}
style
=
{{
color
:
'red'
}}
/
>
<
/Form.Item
>
<
/Table.Summary.Cell
>
<
/Table.Summary.Row
>
<
/Table.Summary
>
);
}
}}
components
=
{
isEditing
?
''
:
{
body
:
{
wrapper
:
DraggableContainer
,
row
:
DraggableBodyRow
,
},
}
}
onRow
=
{(
record
)
=>
{
return
{
onDoubleClick
:
(
e
)
=>
{
return
false
;
if
(
e
.
target
.
cellIndex
===
detailColumns
.
length
-
1
||
e
.
target
.
cellIndex
===
void
0
)
return
false
;
setActiveID
(
record
.
id
);
if
(
record
.
color
)
setBackgroundColor
(
record
.
color
);
form
.
setFieldsValue
(
setDefaultValue
(
record
));
setCurrentField
(
setDefaultValue
(
record
));
setDetailVisible
(
true
);
},
};
}}
/
>
<
/Form
>
<
/div
>
<
/div
>
<
/div
>
)
:
(
<
div
className
=
{
style
.
reportDetails
}
>
<
Modal
onCancel
=
{()
=>
setCreateModalVisible
(
false
)}
closable
=
{
false
}
visible
=
{
createModalVisible
}
footer
=
{
null
}
destroyOnClose
>
<
Form
form
=
{
createMainTableForm
}
{...
layout
}
onFinish
=
{
createReport
}
>
<
Form
.
Item
label
=
{
'主表'
}
name
=
{
'tableName'
}
rules
=
{[
{
required
:
true
,
message
:
'请选择一张主表'
,
},
]}
>
<
Select
disabled
=
{
!
isCreatingMainTable
}
placeholder
=
{
'选择一张表作为主表'
}
showSearch
optionFilterProp
=
"children"
filterOption
=
{(
input
,
option
)
=>
option
.
children
.
includes
(
input
)}
onChange
=
{(
e
)
=>
{
getFieldsFromTable
(
e
,
'mainTable'
);
createMainTableForm
.
setFields
([{
reportFields
:
[]
}]);
}}
>
{
allTableList
.
map
((
item
)
=>
(
<
Option
value
=
{
item
.
name
}
>
{
item
.
name
}
<
/Option
>
))}
<
/Select
>
<
/Form.Item
>
<
Form
.
Item
label
=
{
'报表名称'
}
name
=
{
'reportName'
}
rules
=
{[
{
required
:
true
,
message
:
'请输入报表名称'
,
},
]}
>
<
Input
placeholder
=
{
'请输入报表名称'
}
/
>
<
/Form.Item
>
{
allFields
.
length
?
(
<
Form
.
Item
label
=
{
'报表字段'
}
name
=
{
'reportFields'
}
rules
=
{[{
required
:
true
,
message
:
'请选择需要绑定的字段!'
}]}
>
<
Checkbox
.
Group
style
=
{{
maxHeight
:
400
,
overflowY
:
'scroll'
}}
>
{
allFields
.
map
((
item
)
=>
(
<
Row
>
<
Checkbox
value
=
{
item
.
name
}
>
{
item
.
name
}
<
/Checkbox
>
<
/Row
>
))}
<
/Checkbox.Group
>
<
/Form.Item
>
)
:
(
''
)}
<
Form
.
Item
label
=
{
' '
}
colon
=
{
false
}
>
<
Button
onClick
=
{()
=>
setCreateModalVisible
(
false
)}
>
取消
<
/Button
>
<
Button
loading
=
{
createBtnLoading
}
style
=
{{
marginLeft
:
8
}}
type
=
{
'primary'
}
htmlType
=
{
'submit'
}
>
提交
<
/Button
>
<
/Form.Item
>
<
/Form
>
<
/Modal
>
<
div
className
=
{
style
.
tableWrapper
}
>
<
Row
className
=
{
style
.
controlRow
}
>
<
Form
layout
=
{
'inline'
}
>
<
Form
.
Item
label
=
{
'快速索引'
}
>
<
Search
onSearch
=
{(
e
)
=>
searchReportList
(
e
)}
/
>
<
/Form.Item
>
<
Form
.
Item
>
<
Button
type
=
{
'primary'
}
style
=
{{
marginRight
:
8
}}
onClick
=
{()
=>
openCreateModal
(()
=>
{
setCurrentReport
({});
setAllFields
([]);
setIsCreatingMainTable
(
true
);
createMainTableForm
.
setFieldsValue
({
tableName
:
''
,
reportName
:
''
,
reportFields
:
[],
});
})
}
>
新增
<
/Button
>
<
Upload
{...
uploadProps
}
>
<
Button
size
=
"middle"
icon
=
{
<
ImportOutlined
/>
}
>
导入
<
/Button
>
<
/Upload
>
<
/Form.Item
>
<
/Form
>
<
/Row
>
<
div
className
=
{
style
.
tableContent
}
>
<
BasicTable
pagination
=
{
false
}
bordered
loading
=
{
tableLoading
}
rowKey
=
{
'id'
}
columns
=
{
columns
}
dataSource
=
{
tableData
.
filter
((
item
)
=>
item
.
visible
)}
/
>
<
/div
>
<
/div
>
<
/div
>
)}
<
/div
>
);
};
export
default
ReportsSetting
;
packages/base-components/BasicReport/src/ReportsManage/ReportsSetting.less
0 → 100644
View file @
48ac1217
@import '~antd/es/style/themes/default.less';
.reportSettings {
//width: 100%;
height: 100%;
.reportFiled {
display: inline-block;
width: 100%;
overflow: hidden;
line-height: 1;
white-space: nowrap;
text-overflow: ellipsis;
&:hover {
color: #1685ff;
}
}
.reportDetails {
position: relative;
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
padding: 8px;
.colorSketch {
position: absolute;
z-index: 1001;
width: 100%;
height: 100%;
}
:global {
.@{ant-prefix}-form-item {
margin-bottom: 0 !important;
}
}
.tableWrapper {
display: flex;
flex: 1;
flex-direction: column;
overflow: hidden;
.controlRow {
display: flex;
flex: 0 0 44px;
//justify-content: space-between;
align-items: center;
height: 44px;
margin-bottom: 4px;
padding: 6px;
background: #ffffff;
.leftBtn {
margin-right: 10px;
font-weight: bold;
font-size: 18px;
cursor: pointer;
&:hover {
color: #1685ff;
opacity: 0.8;
}
}
}
.tableContent {
flex: 1;
width: 100%;
max-height: calc(100% - 44px);
padding: 6px;
overflow: hidden;
background: #ffffff;
.tableForm {
height: 100%;
}
}
}
}
}
.boxShadow {
border-color: #40a9ff;
border-right-width: 1px;
outline: 0;
box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
}
.boxShadowOfSwitch {
border-right-width: 1px;
outline: 0;
box-shadow: 0 0 4px 2px rgba(24, 144, 255, 0.6);
}
.boxShadowOfSelect {
border-right-width: 1px;
outline: 0;
box-shadow: 0 0 2px 2px rgba(24, 144, 255, 0.2);
:global {
.@{ant-prefix}-select-selector {
border-color: #40a9ff !important;
}
}
}
.fieldList {
cursor: pointer !important;
&:hover {
color: #1685ff;
}
&.active {
color: #1685ff;
}
}
packages/base-components/BasicReport/src/ReportsManage/assets/mysql.png
0 → 100644
View file @
48ac1217
18 KB
packages/base-components/BasicReport/src/ReportsManage/assets/pic.webp
0 → 100644
View file @
48ac1217
File added
packages/base-components/BasicReport/src/ReportsManage/assets/sqlserver.png
0 → 100644
View file @
48ac1217
33.9 KB
packages/base-components/BasicReport/src/ReportsManage/assets/webapi.png
0 → 100644
View file @
48ac1217
13.7 KB
packages/base-components/BasicReport/src/ReportsManage/extra/detailsComponent.js
0 → 100644
View file @
48ac1217
/**
* * 用来动态加载配置的组件功能函数 * 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} />;*/
return
<
div
>
弹窗组件在组件中未实现
<
/div>
;
};
export
default
DetailsComponent
;
packages/base-components/BasicReport/src/ReportsManage/extra/extraComponents.js
0 → 100644
View file @
48ac1217
// import AccountPermissionScan from '../../AccountManage/AccountPermissionScan';
import
React
from
'react'
;
import
pic
from
'../assets/pic.webp'
;
const
extraComponents
=
{
renderAccount
:
(
props
)
=>
{
return
<
div
>
台账组件
<
/div>
;
},
returnImage
:
(
data
)
=>
{
return
<
img
width
=
{
200
}
height
=
{
200
}
src
=
{
pic
}
alt
=
{
data
.
alt
}
/>
;
},
default
:
()
=>
<
span
>
若需要使用弹窗功能,请开发或配置功能函数
<
/span>
,
};
export
default
extraComponents
;
packages/base-components/BasicReport/src/ReportsManage/utils/constant.js
0 → 100644
View file @
48ac1217
import
MySQLIcon
from
'../assets/mysql.png'
;
import
SQLServerIcon
from
'../assets/sqlserver.png'
;
import
WebAPIIcon
from
'../assets/webapi.png'
;
const
tagColors
=
[
'rgb(129, 134, 143)'
,
'rgb(41, 114, 244)'
,
'rgb(0, 163, 245)'
,
'rgb(69, 176, 118)'
,
'rgb(222, 60, 54)'
,
'rgb(248, 136, 37)'
,
'rgb(189, 160, 20)'
,
'rgb(154, 56, 215)'
,
'rgb(221, 64, 151)'
,
];
const
tagBackgroundColors
=
[
'rgb(220, 223, 228)'
,
'rgb(214, 229, 255)'
,
'rgb(214, 241, 255)'
,
'rgb(211, 243, 226)'
,
'rgb(255, 220, 219)'
,
'rgb(255, 236, 219)'
,
'rgb(255, 245, 204)'
,
'rgb(251, 219, 255)'
,
'rgb(255, 219, 234)'
,
];
const
sourceIconMap
=
{
mysql
:
MySQLIcon
,
sqlserver
:
SQLServerIcon
,
webapi
:
WebAPIIcon
,
};
export
{
tagColors
,
tagBackgroundColors
,
sourceIconMap
};
packages/base-components/BasicReport/src/ReportsManage/utils/handlers.js
0 → 100644
View file @
48ac1217
import
style
from
'../ReportsManage.less'
;
import
extraComponents
from
'../extra/extraComponents'
;
import
moment
from
'moment'
;
import
{
Tag
}
from
'antd'
;
import
{
hasMoney
,
isNumber
,
returnHandledNumber
}
from
'./utils'
;
import
{
tagColors
,
tagBackgroundColors
}
from
'./constant'
;
/**
* @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
=
''
;
let
_number
;
if
(
number
)
_number
=
Number
(
number
);
// 当设置精度后,会被转成字符串
if
(
config
.
type
===
'数值'
&&
config
.
numericalConfigs
&&
config
.
numericalConfigs
.
length
)
{
config
.
numericalConfigs
.
forEach
((
item
)
=>
{
// 接口对于数值类型的返回为null
if
(
!
_color
)
{
let
_max
=
isNumber
(
item
.
maxValue
)
?
item
.
maxValue
:
''
;
let
_min
=
isNumber
(
item
.
minValue
)
?
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
.
type
===
'数值标签'
&&
config
.
labelConfigs
&&
config
.
labelConfigs
.
length
)
{
console
.
log
(
'数值标签'
);
_color
=
'red'
;
}
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'
,
}}
>
{
returnHandledNumber
(
config
.
configItems
,
number
)}
<
/span
>
<
span
className
=
{
style
.
prefixOrSuffix
}
style
=
{{
color
:
_color
}}
>
{
config
.
suffix
||
''
}
<
/span
>
<
/span
>
)
:
(
'-'
);
};
export
const
handleNumberTag
=
(
config
,
number
)
=>
{
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>);
// let a = 'abc' a.split(undefined); a = ['abc']
return
(
<
Tag
style
=
{{
background
:
mapTag
(
_map
,
number
)
||
_color
,
border
:
`1px solid
${
mapTag
(
_map
,
number
)
||
_color
}
`
,
borderRadius
:
2
,
color
:
mapTag
(
_map
,
number
)
?
tagColors
[
tagBackgroundColors
.
findIndex
((
c
)
=>
c
===
mapTag
(
_map
,
number
))]
:
`rgba(0, 0, 0, .65)`
,
}}
>
{(
config
.
prefix
||
''
)
+
returnHandledNumber
(
config
.
configItems
,
number
)
+
(
config
.
suffix
||
''
)}
<
/Tag
>
);
};
/** @params: 标签形态的configRule,[{标签值:'字符串',颜色: '#AAAAAA'}]; */
/* 支持正则配置 RegExp */
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>);
// let a = 'abc' a.split(undefined); a = ['abc']
return
String
(
text
)
.
split
(
_configMap
[
'分隔符'
])
.
map
((
item
)
=>
(
<
Tag
style
=
{{
background
:
mapTag
(
_map
,
item
)
||
_color
,
border
:
`1px solid
${
mapTag
(
_map
,
item
)
||
_color
}
`
,
borderRadius
:
2
,
color
:
mapTag
(
_map
,
item
)
?
tagColors
[
tagBackgroundColors
.
findIndex
((
c
)
=>
c
===
mapTag
(
_map
,
item
))]
:
`rgba(0, 0, 0, .65)`
,
}}
>
{
item
}
<
/Tag
>
));
};
const
mapTag
=
(
map
,
key
)
=>
{
if
(
map
[
key
])
{
return
map
[
key
];
}
else
{
let
_keys
=
Object
.
keys
(
map
);
return
_keys
.
reduce
((
final
,
_key
)
=>
{
let
isRegExp
=
_key
.
includes
(
'RegExp='
);
let
reg
=
new
RegExp
(
_key
.
replace
(
'RegExp='
,
''
));
if
(
isRegExp
&&
reg
.
test
(
key
))
{
final
=
map
[
_key
];
}
return
final
;
},
''
);
}
};
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/ReportsManage/utils/utils.js
0 → 100644
View file @
48ac1217
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
===
'金额'
);
};
const
isSelect
=
(
configItems
)
=>
{
if
(
!
configItems
)
return
false
;
let
_items
=
configItems
.
split
(
'|'
);
return
!!
_items
.
find
((
item
)
=>
item
===
'renderAsSelect'
);
};
// options=name1[.value1],name2[.value2],name3[.value3];
const
returnOptions
=
(
configItems
)
=>
{
if
(
!
configItems
)
return
false
;
let
_items
=
configItems
.
split
(
'|'
);
let
_options
=
_items
.
find
((
item
)
=>
item
.
includes
(
'options='
));
if
(
!
_options
)
return
false
;
return
_options
.
replace
(
'options='
,
''
).
split
(
','
);
};
const
returnRows
=
(
configItems
)
=>
{
if
(
!
configItems
)
return
3
;
let
_items
=
configItems
.
split
(
'|'
);
let
_options
=
_items
.
find
((
item
)
=>
item
.
includes
(
'rows='
));
if
(
!
_options
)
return
3
;
let
_rows
=
Number
(
_options
.
replace
(
'rows='
,
''
));
return
!
isNaN
(
_rows
)
&&
_rows
>=
1
?
_rows
:
3
;
};
const
returnCols
=
(
configItems
)
=>
{
if
(
!
configItems
)
return
1
;
let
_items
=
configItems
.
split
(
'|'
);
let
_options
=
_items
.
find
((
item
)
=>
item
.
includes
(
'cols='
));
if
(
!
_options
)
return
1
;
let
_cols
=
Number
(
_options
.
replace
(
'cols='
,
''
));
return
!
isNaN
(
_cols
)
&&
_cols
<=
3
&&
_cols
>=
0
?
_cols
:
1
;
};
/**
* @description: 用来在summary中处理数值的配置
* @params: 参数描述
* @date: 2022/8/10
* @author: ChenLong
*/
const
returnHandledNumber
=
(
configItems
,
num
,
isSummary
)
=>
{
// 精度、前缀、后缀、倍率
// $_d|_d%|_d*0.0001|金额|0.00
if
(
isNaN
(
num
))
return
'-'
;
if
(
!
configItems
)
return
num
;
num
=
Number
(
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
&&
isSummary
?
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
)).
toLocaleString
();
return
template
.
replace
(
/_d/
,
isString
(
final
)
?
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
;
};
function
downloadFunc
(
url
,
name
,
target
=
'_self'
)
{
const
a
=
document
.
createElement
(
'a'
);
a
.
href
=
url
;
a
.
target
=
target
;
a
.
download
=
name
;
a
.
click
();
a
.
remove
();
}
/**
* @description: 校验文件的名称是否包含特殊字符
* @params: {Object: File} file file对象 { special:Boolean } 是否去除/的匹配
* @date: 2021/12/8
* @author: ChenLong
* @returns {Object} {type: error | success ,content: 提示...}
*/
function
filenameVerification
(
file
,
special
)
{
// 文件名含有特殊字符 提示不能上传 {+,:/?#[]@!$&\\*+;=}
// 规则对象(flag)
var
flag
=
!
special
?
new
RegExp
(
"[`~!@#$^&*=|{}':;',
\\
[
\\
]/?~!@#¥&*——|{}【】‘;:”“'。,、?]"
)
:
new
RegExp
(
"[`~!@#$^&*=|{}':;',[
\\
]?~!@#¥&*——|{}【】‘;:”“'。,、?]"
);
if
(
flag
.
test
(
file
.
name
))
{
return
{
type
:
'error'
,
content
:
`文件名格式错误,请检查文件名是否含有特殊字符
${
"~!@#$^&*=|{}':;',
\\
[
\\
]/?~!@#¥&*——|{}【】‘;:”“'。,、?"
}
`
,
};
}
return
{
type
:
'success'
,
content
:
`上传成功!`
,
};
}
export
{
isObject
,
isString
,
isNumber
,
hasMoney
,
isArray
,
returnHandledNumber
,
returnDefaultValueOrConfigs
,
downloadFunc
,
filenameVerification
,
isSelect
,
returnOptions
,
returnRows
,
returnCols
,
};
packages/base-components/BasicReport/src/api/constants.js
0 → 100644
View file @
48ac1217
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'
;
packages/base-components/BasicReport/src/api/index.js
0 → 100644
View file @
48ac1217
import
{
Modal
,
notification
}
from
'antd'
;
import
{
instanceRequest
,
service
}
from
'@wisdom-utils/utils'
;
import
ReportService
from
'./service/report'
;
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
reportService
=
service
(
ReportService
);
export
{
reportService
};
packages/base-components/BasicReport/src/api/service/report.js
0 → 100644
View file @
48ac1217
/*
** 轻量化报表平台接口
** 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_FILTER_VALUES
:
`
${
BASEURL
}
/GetReportFilterValues`
,
// 获取过滤字段的值的枚举
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`
,
// 更新报表数据
GET_REPORT_DETAILS
:
`
${
BASEURL
}
/GetReportDetails`
,
// 获取报表配置
DEL_REPORT_DATA
:
`
${
BASEURL
}
/DelReportData`
,
// 删除报表数据
SET_REPORT_ALLOW
:
`
${
BASEURL
}
/SetReportAllow`
,
// 设置关注
ADD_REPORT_DATA
:
`
${
BASEURL
}
/AddReportData`
,
// 添加报表数据
EXPORT_JPG
:
`
${
BASEURL
}
/ExportJPGAccountData`
,
EXPORT_REPORT_CONFIG
:
`
${
BASEURL
}
/ExportReportConfig`
,
IMPORT_REPORT_CONFIG
:
`
${
BASEURL
}
/ImportReportConfig`
,
// 多数据源
GET_DATA_SOURCES
:
`
${
BASEURL
}
/GetDataSources`
,
// 获取数据源列表
ADD_DB_CONNECTION
:
`
${
BASEURL
}
/AddDbConnection`
,
// 新增/编辑数据源
DELETE_DB_CONNECTION
:
`
${
BASEURL
}
/DeleteDbConnection`
,
// 删除数据源
GET_DB_SOURCES
:
`
${
BASEURL
}
/GetDBSources`
,
// 获取数据库
TEST_CONNECTION
:
`
${
BASEURL
}
/TestConnection`
,
// 测试链接
DEL_REPORT_CHILD
:
`
${
BASEURL
}
/DelReportChlid`
,
// 删除挂接关系
};
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
,
},
getReportFilterValues
:
{
url
:
API
.
GET_REPORT_FILTER_VALUES
,
method
:
constants
.
REQUEST_METHOD_POST
,
type
:
constants
.
REQUEST_METHOD_POST
,
},
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
,
},
getReportDetails
:
{
url
:
API
.
GET_REPORT_DETAILS
,
method
:
constants
.
REQUEST_METHOD_GET
,
type
:
constants
.
REQUEST_METHOD_GET
,
},
delReportData
:
{
url
:
API
.
DEL_REPORT_DATA
,
method
:
constants
.
REQUEST_METHOD_POST
,
type
:
constants
.
REQUEST_METHOD_POST
,
},
setReportAllow
:
{
url
:
API
.
SET_REPORT_ALLOW
,
method
:
constants
.
REQUEST_METHOD_POST
,
type
:
constants
.
REQUEST_METHOD_POST
,
},
addReportData
:
{
url
:
API
.
ADD_REPORT_DATA
,
method
:
constants
.
REQUEST_METHOD_POST
,
type
:
constants
.
REQUEST_METHOD_POST
,
},
exportJPG
:
{
url
:
API
.
EXPORT_JPG
,
method
:
constants
.
REQUEST_METHOD_POST
,
type
:
constants
.
REQUEST_METHOD_POST
,
},
exportConfig
:
{
url
:
API
.
EXPORT_REPORT_CONFIG
,
method
:
constants
.
REQUEST_METHOD_GET
,
type
:
constants
.
REQUEST_METHOD_GET
,
},
importConfig
:
{
url
:
API
.
IMPORT_REPORT_CONFIG
,
method
:
constants
.
REQUEST_METHOD_POST
,
type
:
constants
.
REQUEST_METHOD_POST
,
},
getDataSources
:
{
url
:
API
.
GET_DATA_SOURCES
,
method
:
constants
.
REQUEST_METHOD_GET
,
type
:
constants
.
REQUEST_METHOD_GET
,
},
addDbConnection
:
{
url
:
API
.
ADD_DB_CONNECTION
,
method
:
constants
.
REQUEST_METHOD_POST
,
type
:
constants
.
REQUEST_METHOD_POST
,
},
deleteDbConnection
:
{
url
:
API
.
DELETE_DB_CONNECTION
,
method
:
constants
.
REQUEST_METHOD_GET
,
type
:
constants
.
REQUEST_METHOD_GET
,
},
getDbSources
:
{
url
:
API
.
GET_DB_SOURCES
,
method
:
constants
.
REQUEST_METHOD_POST
,
type
:
constants
.
REQUEST_METHOD_POST
,
},
testConnection
:
{
url
:
API
.
TEST_CONNECTION
,
method
:
constants
.
REQUEST_METHOD_POST
,
type
:
constants
.
REQUEST_METHOD_POST
,
},
delReportChild
:
{
url
:
API
.
DEL_REPORT_CHILD
,
method
:
constants
.
REQUEST_METHOD_GET
,
type
:
constants
.
REQUEST_METHOD_GET
,
},
};
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
exportJPG
=
(
options
,
data
)
=>
{
return
request
({
url
:
API
.
EXPORT_JPG
,
method
:
'post'
,
...
options
,
data
,
});
};
export
const
addReportDetailInfoIndex
=
(
data
)
=>
request
({
url
:
API
.
ADD_REPORT_DETAIL_INFO_INDEX
,
method
:
'post'
,
data
,
});
export
const
importReportConfig
=
(
options
,
params
,
data
)
=>
request
({
url
:
API
.
IMPORT_REPORT_CONFIG
,
method
:
'post'
,
...
options
,
params
,
data
,
});
export
const
exportReportConfig
=
(
options
,
params
)
=>
request
({
url
:
API
.
EXPORT_REPORT_CONFIG
,
method
:
'get'
,
...
options
,
params
,
});
export
default
reportService
;
packages/base-components/BasicReport/src/api/service/workflow.js
0 → 100644
View file @
48ac1217
const
AccountBaseURL
=
'/PandaWorkFlow/WorkFlow/AccountManage'
;
export
const
uploadFileUrl
=
`
${
AccountBaseURL
}
/UploaderFiles`
;
// 上传文件链接
export
const
downloadFileUrl
=
`
${
AccountBaseURL
}
/DownloadFiles`
;
// 下载/播放文件链接
packages/base-components/BasicReport/src/components/DatePickerGroup/index.js
0 → 100644
View file @
48ac1217
/**
* 时间组选择:支持 全部,日,月,年,自定义 类型 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/demos/Basic.tsx
0 → 100644
View file @
48ac1217
import
React
from
'react'
;
import
BasicReport
from
'../index'
;
const
Demo
=
()
=>
{
return
(
<
div
>
<
h3
>
报表
</
h3
>
<
div
style=
{
{
height
:
'600px'
}
}
>
<
BasicReport
params=
{
{
reportName
:
'订单合同'
,
}
}
/>
</
div
>
</
div
>
);
};
export
default
Demo
;
packages/base-components/BasicReport/src/index.js
0 → 100644
View file @
48ac1217
import
React
from
'react'
;
import
ReportsManage
from
'./ReportsManage/ReportsManage'
;
const
BasicReport
=
(
props
)
=>
{
return
<
ReportsManage
{...
props
}
/>
;
};
export
default
BasicReport
;
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