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
3ebe7190
Commit
3ebe7190
authored
Aug 18, 2022
by
陈龙
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: 重新处理报表逻辑
parent
b8b2275c
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
3116 additions
and
1137 deletions
+3116
-1137
package.json
packages/base-components/BasicReport/package.json
+1
-1
Control.js
...nents/BasicReport/src/ReportsManage/Components/Control.js
+1
-1
ReportEditForm.js
...omponents/BasicReport/src/ReportsManage/ReportEditForm.js
+1
-1
ReportsManage.js
...components/BasicReport/src/ReportsManage/ReportsManage.js
+1120
-0
ReportsManage.less
...mponents/BasicReport/src/ReportsManage/ReportsManage.less
+0
-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
+1831
-0
ReportsSetting.less
...ponents/BasicReport/src/ReportsManage/ReportsSetting.less
+119
-0
pic.webp
...-components/BasicReport/src/ReportsManage/assets/pic.webp
+0
-0
detailsComponent.js
...s/BasicReport/src/ReportsManage/extra/detailsComponent.js
+14
-0
extraComponents.js
...ts/BasicReport/src/ReportsManage/extra/extraComponents.js
+13
-0
handlers.js
...omponents/BasicReport/src/ReportsManage/utils/handlers.js
+2
-2
utils.js
...e-components/BasicReport/src/ReportsManage/utils/utils.js
+0
-0
constants.js
packages/base-components/BasicReport/src/api/constants.js
+0
-8
index.js
...nents/BasicReport/src/components/DatePickerGroup/index.js
+0
-0
index.js
packages/base-components/BasicReport/src/index.js
+4
-1124
No files found.
packages/base-components/BasicReport/package.json
View file @
3ebe7190
...
...
@@ -9,7 +9,7 @@
"*.less"
],
"module"
:
"es/index.js"
,
"main"
:
"
lib
/index.js"
,
"main"
:
"
es
/index.js"
,
"files"
:
[
"lib"
,
"es"
,
...
...
packages/base-components/BasicReport/src/
c
omponents/Control.js
→
packages/base-components/BasicReport/src/
ReportsManage/C
omponents/Control.js
View file @
3ebe7190
...
...
@@ -6,7 +6,7 @@
*/
import
React
,
{
useEffect
,
useState
}
from
'react'
;
import
{
Input
,
Select
}
from
'antd'
;
import
{
reportService
}
from
'
..
/api'
;
import
{
reportService
}
from
'
@
/api'
;
import
{
returnDefaultValueOrConfigs
}
from
'../utils/utils'
;
const
{
Option
}
=
Select
;
...
...
packages/base-components/BasicReport/src/ReportEditForm.js
→
packages/base-components/BasicReport/src/Report
sManage/Report
EditForm.js
View file @
3ebe7190
...
...
@@ -7,7 +7,7 @@
import
React
,
{
useEffect
,
useState
}
from
'react'
;
import
{
Form
,
Input
,
DatePicker
,
InputNumber
,
Space
,
Row
,
Col
,
Button
,
message
}
from
'antd'
;
import
moment
from
'moment'
;
import
{
submitReportData
}
from
'./api/service/report'
;
import
{
submitReportData
}
from
'.
.
/api/service/report'
;
// 类型
const
DATE_PICKER_ARRAY
=
[
'日期'
];
const
DATE_TIME_PICKER_ARRAY
=
[
'日期时刻'
];
...
...
packages/base-components/BasicReport/src/ReportsManage/ReportsManage.js
0 → 100644
View file @
3ebe7190
/**
* * 轻量化报表通用配置页面 * create by ChenLong on 2022/6/22 *
* 功能路径:src\pages\product\ReportsManage\ReportsManage.js * 菜单参数列表:*变量名*(变量说明,数据类型,是否必填,取值范围)
*
* @changelog:
* editComponentVisible && detailsComponentVisible 共同作用组件的显示
*/
/**
* @description: 功能描述:参考台账概念,重新定义
* @tips: 1. 如果需要对字段进行处理,增加功能之类的。需要提前确定返回值的类型.
* 2. 如果要用customerState来控制页面按钮等,需要按照给定的权限值进行配置
* @params: <ReportManage
* params={{reportName,pageSize,filterFields,filterValues,state,customerState}}>
*
* reportName: 报表名称;
* pageSize: 按需配置,默认加载100;
* filterFields:
* 需要默认加载的过滤条件的field,英文逗号分割,与filterValues一一对应;
* filterValues:
* 需要默认加载的过滤条件的value,英文逗号分割,与filterFields一一对应;
* state: delete|edit|scan 各种权限;
*
* customerState: ['filters','sortBtn','exportBtn','editBtn','deleteBtn','pagination'];
*
* sortFields: '排序字段1,排序字段2,排序字段3'
* @config:
* 【数值】 [prefix]_d%|0.00|_d%[suffix]|金额 = 前缀|精度|后缀|金额类的数据(千分位),可分别设置。
* 【标签】 split=, 分隔符。
*
* 【功能】 功能配置框内,配置需要跳转功能所需参数,type、url是必须功能,需要type判断类型,需要通过url去解析加载组件。
* @type:
* 【文本】普通文本
* 【数值】数值类型的文本
* 【标签】文本渲染成标签,具有不同颜色;
* 【功能】“功能”会在当前页内去展示,会卸载掉列表页,加载功能组件。配置 type +
* url + 自定义字段 的配置项,自行解析加载即可;
* -------------------- 待需求提出后开发 -----------------
*
* 【链接】内链外链,点击可跳转;配置规则:配置链接即可;
* 【弹窗】modal弹窗弹出,弹窗内的具体业务自行配置;配置规则:[function_name];[...params];
*
* ------------------------------------------------------
* @table:
* 表头:表头需要支持多级表头、合并;
* 列:列支持设置筛选;
* 固定行、固定列:可根据配置生成固定行、列;
* @control:
* 固定筛选:拥有固定筛选框,根据配置显示可搜索字段;
*
* 可配置筛选框:根据字段配置,将字段设置成筛选条件,枚举出该字段所有值,提供用户进行选择,然后进行筛选;筛选框具体形态可根据配置字段来渲染;
* 导出功能:各类导出功能按钮;
*
* 时间筛选框:单表唯一;需要变更,支持多时间参数的筛选
* @state: 参考台账权限 delete 全部权限
* edit 除删除外的权限
* scan 查看权限
*/
import
React
,
{
useState
,
useEffect
,
useRef
}
from
'react'
;
import
{
Row
,
Button
,
Tag
,
message
,
Form
,
Space
,
Modal
,
Select
,
Table
,
Dropdown
,
Menu
,
Spin
,
}
from
'antd'
;
import
{
SortAscendingOutlined
,
MinusCircleOutlined
,
ExportOutlined
,
FormOutlined
,
DeleteOutlined
,
}
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
,
}
from
'./utils/handlers'
;
import
{
hasMoney
,
isArray
,
isNumber
,
isString
,
returnHandledNumber
}
from
'./utils/utils'
;
import
{
connect
}
from
'react-redux'
;
import
ReportEditForm
from
'./ReportEditForm'
;
const
ControlsType
=
[
'下拉'
,
'多选'
,
'日期'
];
const
fieldSplitStr
=
'-'
;
// fieldGroup用来分割
const
{
Option
}
=
Select
;
const
dateFormat
=
'YYYY-MM-DD'
;
// 日期格式化
const
initDateModel
=
'all'
;
let
timer
=
null
;
const
PERMISSION
=
{
delete
:
[
'filters'
,
'pagination'
,
// 操作条按钮
'sortBtn'
,
'exportBtn'
,
// 操作列
'editBtn'
,
'deleteBtn'
,
],
edit
:
[
'filters'
,
'pagination'
,
'sortBtn'
,
'exportBtn'
,
// 操作列
'editBtn'
,
],
scan
:
[
'filters'
,
'pagination'
],
};
const
ReportsManage
=
(
props
)
=>
{
const
{
reportName
,
pageSize
,
filterFields
,
filterValues
,
state
,
customerState
,
sortFields
}
=
props
.
params
;
const
permission
=
customerState
&&
isArray
(
customerState
)
?
customerState
:
PERMISSION
[
state
||
'delete'
];
const
tableWrapperRef
=
useRef
();
const
controlRef
=
useRef
();
if
(
!
reportName
)
return
(
<
div
className
=
{
style
.
lackParams
}
>
未配置
reportName
,请完善配置并重新登陆后查看页面!
<
/div
>
);
const
[
tableStruct
,
setTableStruct
]
=
useState
([]);
// 临时使用,看后续是否需要保留
const
[
columns
,
setColumns
]
=
useState
([]);
// 表头设置
const
[
tableData
,
setTableData
]
=
useState
([]);
// 表数据
const
[
pagination
,
setPagination
]
=
useState
({
current
:
1
,
total
:
0
,
pageSize
:
handlePageSize
(
pageSize
)
||
100
,
pageSizeOptions
:
[...
new
Set
([
20
,
50
,
100
].
concat
(
handlePageSize
(
pageSize
)))]
.
filter
((
item
)
=>
Number
(
item
))
.
sort
((
a
,
b
)
=>
Number
(
a
)
-
Number
(
b
)),
showQuickJumper
:
true
,
showSizeChanger
:
true
,
onShowSizeChange
:
(
current
,
size
)
=>
{
let
_pagination
=
{
...
pagination
};
_pagination
.
current
=
current
;
_pagination
.
pageSize
=
size
;
setPagination
(
_pagination
);
getData
(
false
,
_pagination
);
},
onChange
:
(
current
,
size
)
=>
{
let
_pagination
=
{
...
pagination
};
_pagination
.
current
=
current
;
_pagination
.
pageSize
=
size
;
setPagination
(
_pagination
);
getData
(
false
,
_pagination
);
},
});
const
[
controls
,
setControls
]
=
useState
([]);
// 用来存储操作控件
const
[
searchContent
,
setSearchContent
]
=
useState
(
''
);
// 搜索框内的值
const
[
searchPlaceholder
,
setSearchPlaceholder
]
=
useState
([]);
// 搜索框的placeholder
const
[
filterObject
,
setFilterObject
]
=
useState
({});
// 存控制条中,选了筛选条件的值
const
[
modalVisible
,
setModalVisible
]
=
useState
(
false
);
const
[
allSortFields
,
setAllSortFields
]
=
useState
([]);
// 设置所有列表
const
[
selectedSortFields
,
setSelectedSortFields
]
=
useState
([
{
label
:
'主要排序'
,
value
:
''
,
sort
:
'asc'
,
},
]);
const
[
summaryArray
,
setSummaryArray
]
=
useState
([]);
// 总结栏,包括小计、总计
const
[
tableY
,
setTableY
]
=
useState
(
500
);
const
[
tableX
,
setTableX
]
=
useState
(
1820
);
const
[
listHeight
,
setListHeight
]
=
useState
(
0
);
const
[
tableHeaderLevel
,
setTableHeaderLevel
]
=
useState
(
null
);
const
[
exportLoading
,
setExportLoading
]
=
useState
(
false
);
const
[
extraModal
,
setExtraModal
]
=
useState
(
false
);
const
[
hasTotal
,
setHasTotal
]
=
useState
(
false
);
const
[
hasSinglePage
,
setHasSinglePage
]
=
useState
(
false
);
const
[
tableLoading
,
setTableLoading
]
=
useState
(
false
);
const
[
mergeObject
,
setMergeObject
]
=
useState
({});
// const
const
[
timeFrom
,
setTimeFrom
]
=
useState
(
moment
().
startOf
(
initDateModel
).
format
(
dateFormat
));
const
[
timeTo
,
setTimeTo
]
=
useState
(
moment
().
endOf
(
initDateModel
).
format
(
dateFormat
));
const
[
extra
,
setExtra
]
=
useState
(
<><
/>
)
;
const
[
sortModalVisible
,
setSortModalVisible
]
=
useState
(
false
);
const
[
currentReportId
,
setCurrentReportId
]
=
useState
(
null
);
const
[
hasDatePicker
,
setHasDatePicker
]
=
useState
(
''
);
const
[
defaultDateConfig
,
setDefaultDateConfig
]
=
useState
({
defaultModel
:
'year'
,
defaultDate
:
null
,
});
const
[
dateModel
,
setDateMode
]
=
useState
(
'all'
);
// const [detailsComponent, setDetailsComponent] = useState(<></>); // 详情组件
const
[
detailsComponentVisible
,
setDetailsComponentVisible
]
=
useState
(
false
);
// 是否显示详情组件
const
[
editComponentVisible
,
setEditComponentVisible
]
=
useState
(
false
);
// 是否显示编辑组件
const
[
currentData
,
setCurrentData
]
=
useState
({});
// 设置当前编辑数据
const
[
sroter
,
setSorter
]
=
useState
({});
const
[
detailConfig
,
setDetailConfig
]
=
useState
({
url
:
''
,
type
:
''
,
params
:
{}
});
const
[
controlsHeight
,
setControlsHeight
]
=
useState
(
44
);
const
menu
=
()
=>
{
const
_item
=
[
{
label
:
(
<
Button
size
=
"middle"
loading
=
{
exportLoading
}
type
=
"text"
onClick
=
{()
=>
exportModule
(
'pdf'
,
'pdf'
)}
icon
=
{
<
ExportOutlined
/>
}
>
导出
pdf
<
/Button
>
),
key
:
'exportPdf'
,
},
{
label
:
(
<
Button
size
=
"middle"
loading
=
{
exportLoading
}
type
=
"text"
onClick
=
{()
=>
exportModule
(
'excel'
,
'xls'
)}
icon
=
{
<
ExportOutlined
/>
}
>
导出
Excel
<
/Button
>
),
key
:
'exportExcel'
,
},
];
return
<
Menu
items
=
{
_item
}
/>
;
};
const
exportModule
=
(
type
,
extension
)
=>
{
setExportLoading
(
true
);
exportAccountData
(
{
responseType
:
'blob'
},
{
exportType
:
type
},
{
reportName
,
pageIndex
:
0
,
pageSize
:
0
,
sortFields
:
''
,
content
:
''
,
filters
:
[
{
fieldAlias
:
''
,
fieldValue
:
''
,
},
],
},
)
.
then
((
res
)
=>
{
if
(
res
&&
res
.
code
===
-
1
)
return
message
.
error
(
res
.
msg
);
const
url
=
window
.
URL
.
createObjectURL
(
new
Blob
([
res
],
{
type
:
'application/octet-stream;charset=UTF-8'
}),
);
const
a
=
document
.
createElement
(
'a'
);
a
.
href
=
url
;
a
.
target
=
'_blank'
;
a
.
download
=
`
${
reportName
}${
moment
().
format
(
'YYYY-MM-DD-HH-mm-ss'
).
replaceAll
(
'-'
,
''
)}
.`
+
extension
;
a
.
click
();
a
.
remove
();
setExportLoading
(
false
);
})
.
catch
((
err
)
=>
{
setExportLoading
(
false
);
});
};
const
searchData
=
(
e
)
=>
{
getData
(
false
,
pagination
);
};
const
controlSelectChange
=
(
fieldAlias
,
e
)
=>
{
let
_filterArray
=
{
...
filterObject
};
_filterArray
[
fieldAlias
]
=
e
;
setFilterObject
(
_filterArray
);
};
const
searchInputChange
=
(
e
)
=>
{
setSearchContent
(
e
.
target
.
value
);
};
const
setConfig
=
(
config
,
summary
,
data
)
=>
{
getControlsBarConfig
(
config
);
getTableSummaryConfig
(
config
,
summary
);
getTableLevel
(
config
);
};
const
addFilterAndSearchParams
=
(
data
)
=>
{
let
_data
=
{
...
data
};
// 搜索框是否有值
if
(
searchContent
)
_data
.
content
=
searchContent
;
// filterObject是存起来的控制栏的过滤条件
let
_filters
=
Object
.
keys
(
filterObject
)
.
filter
((
key
)
=>
{
let
_value
=
filterObject
[
key
];
return
(
isString
(
_value
)
&&
_value
)
||
(
isArray
(
_value
)
&&
_value
.
length
);
})
.
map
((
key
)
=>
{
let
_value
=
filterObject
[
key
];
if
(
isString
(
_value
)
&&
_value
)
return
{
fieldAlias
:
key
,
fieldValue
:
_value
,
};
if
(
isArray
(
_value
)
&&
_value
.
length
)
return
{
fieldAlias
:
key
,
fieldValue
:
_value
.
join
(
','
),
};
return
false
;
});
// 加上时间过滤参数
if
(
dateModel
!==
'all'
&&
hasDatePicker
&&
timeFrom
&&
timeTo
)
{
_filters
.
push
({
fieldAlias
:
hasDatePicker
,
fieldValue
:
`
${
timeFrom
}
00:00:00,
${
timeTo
}
23:59:59`
,
});
}
// 合并手动传入的filters
if
(
filterFields
)
{
let
_customerFilterArray
=
filterFields
.
split
(
','
);
let
_customerValueArray
=
filterValues
.
split
(
','
);
_customerFilterArray
.
forEach
((
item
,
index
)
=>
{
_filters
.
push
({
fieldAlias
:
item
,
fieldValue
:
_customerValueArray
[
index
]
||
''
,
});
});
}
// 并入 _data
if
(
_filters
.
length
)
_data
.
filters
=
_filters
;
return
_data
;
};
// 排序字符串处理成数组
const
handleSortString
=
(
sortString
)
=>
{
// selectedSortFields
let
_sortStringArray
=
sortString
.
split
(
','
).
map
((
item
,
index
)
=>
{
let
_item
=
item
.
split
(
' '
);
if
(
index
===
0
)
{
return
{
label
:
'主要排序'
,
value
:
_item
[
0
].
replace
(
/
\[
|
\]
/g
,
''
),
sort
:
_item
[
1
],
};
}
else
{
return
{
label
:
'次要排序'
,
value
:
_item
[
0
].
replace
(
/
\[
|
\]
/g
,
''
),
sort
:
_item
[
1
],
};
}
});
setSelectedSortFields
(
_sortStringArray
);
};
/** @description: 根据是否向下合并处理数据,返回合并的key的数组 */
const
returnMergeArray
=
(
config
)
=>
{
return
config
.
filter
((
item
)
=>
item
.
isMerge
).
map
((
item
)
=>
item
.
fieldAlias
);
};
/** @description: 根据配置和数据,计算出该合并的字段和每一行是否合并 */
const
handleDataToGetRowSpanArray
=
(
config
,
data
)
=>
{
let
_arr
=
returnMergeArray
(
config
);
let
_merge
=
{};
// _merge:{爱好:[[0,3],[3,5]]}
_arr
.
forEach
((
key
)
=>
{
_merge
[
key
]
=
{};
let
_currentIndex
=
0
;
data
.
forEach
((
item
,
index
)
=>
{
if
(
index
>
0
)
{
if
(
item
[
key
]
===
data
[
index
-
1
][
key
])
{
_merge
[
key
][
_currentIndex
]
+=
1
;
_merge
[
key
][
index
]
=
0
;
}
else
{
_currentIndex
=
index
;
_merge
[
key
][
index
]
=
1
;
}
}
else
{
_merge
[
key
][
0
]
=
1
;
}
});
});
return
_merge
;
};
const
getData
=
(
isInit
,
pagination
)
=>
{
setTableLoading
(
true
);
const
{
pageSize
,
current
}
=
pagination
;
// 搜索条件附加到params
let
_data
=
addFilterAndSearchParams
({
reportName
:
reportName
,
pageIndex
:
current
,
pageSize
:
pageSize
,
});
// sortFields
reportService
.
getReportInfo
(
_data
)
.
then
((
res
)
=>
{
if
(
res
.
code
===
0
)
{
let
_reportDetails
=
res
.
data
.
reportDetails
;
let
_statisticalValues
=
res
.
data
.
statisticalValues
;
let
_tableData
=
res
.
data
.
data
.
list
;
let
_sortString
=
res
.
data
.
sortString
;
if
(
isInit
)
{
setConfig
(
_reportDetails
,
_statisticalValues
,
_tableData
);
}
getTableHeaderConfig
(
_reportDetails
,
_tableData
);
let
_pagination
=
{
...
pagination
};
_pagination
.
total
=
res
.
data
.
data
.
totalCount
;
setPagination
(
_pagination
);
setTableData
(
_tableData
);
// 处理排序字段
handleSortString
(
_sortString
);
if
(
_tableData
)
{
setSortModalVisible
(
true
);
setCurrentReportId
(
_reportDetails
[
0
]?.
reportId
);
}
else
{
setSortModalVisible
(
false
);
setCurrentReportId
(
null
);
}
}
else
{
setSortModalVisible
(
false
);
setCurrentReportId
(
null
);
message
.
error
(
'未能查询到报表数据!'
);
let
_pagination
=
{
...
pagination
};
_pagination
.
total
=
0
;
_pagination
.
current
=
1
;
setPagination
(
_pagination
);
setTableData
([]);
}
setTableLoading
(
false
);
})
.
catch
((
err
)
=>
{
console
.
log
(
err
);
setTableLoading
(
false
);
});
};
/** @description: 在配置项中,isFilter: true 用来渲染控制框;filterRule: 下拉/文本/多选 */
const
getControlsBarConfig
=
(
config
)
=>
{
let
_data
=
config
.
filter
((
item
)
=>
item
.
isFilter
);
let
_searchPlaceholder
=
[];
_data
.
filter
((
item
)
=>
item
.
filterRule
===
'文本'
)
.
forEach
((
item
)
=>
_searchPlaceholder
.
push
(
item
.
fieldAlias
));
setSearchPlaceholder
(
_searchPlaceholder
);
let
_controls
=
_data
.
filter
((
item
)
=>
ControlsType
.
includes
(
item
.
filterRule
));
setControls
(
_controls
);
handleDate
(
_controls
);
};
const
getTableHeaderConfig
=
(
config
,
data
)
=>
{
setTableStruct
(
config
);
setColumns
(
returnColumn
(
config
,
data
));
setAllSortFields
(
returnSortFields
(
config
));
};
const
getTableSummaryConfig
=
(
config
,
summary
)
=>
{
if
(
summary
.
length
===
0
)
{
setSummaryArray
([]);
return
false
;
}
let
_summaryConfig
=
{};
let
_configLength
=
config
.
length
;
// 需要判断
// 合并列
let
_colSpan
=
-
1
;
let
_index
=
0
;
config
.
filter
((
item
)
=>
item
.
isShow
)
.
forEach
((
item
,
index
)
=>
{
if
(
item
.
isStatistics
)
{
_index
+=
1
;
_colSpan
=
-
1
;
_summaryConfig
[
item
.
fieldAlias
]
=
{
fieldName
:
item
.
fieldAlias
,
index
,
alignType
:
item
.
alignType
,
type
:
item
.
statisticsRule
,
isMoney
:
item
.
type
===
'数值'
&&
!!
hasMoney
(
item
.
configItems
),
configItems
:
item
.
configItems
,
};
}
else
{
let
_name
=
`空值行
${
_index
}
`
;
if
(
_colSpan
===
-
1
)
{
_colSpan
=
1
;
}
else
{
_colSpan
+=
1
;
}
_summaryConfig
[
_name
]
=
{
fieldName
:
_name
,
colSpan
:
_colSpan
,
};
}
});
summary
.
forEach
((
item
)
=>
{
switch
(
item
.
totalType
)
{
case
'全部'
:
setHasTotal
(
true
);
break
;
case
'单页'
:
setHasSinglePage
(
true
);
break
;
default
:
break
;
}
if
(
_summaryConfig
[
item
.
fieldName
])
{
_summaryConfig
[
item
.
fieldName
][
item
.
totalType
]
=
item
.
fieldValue
;
}
});
// 增加操作列,总结栏最后一个单元格需要延伸一格
let
_sumArr
=
Object
.
values
(
_summaryConfig
);
if
(
_sumArr
&&
_sumArr
.
length
)
_sumArr
=
_sumArr
.
map
((
item
,
index
)
=>
{
let
_item
=
{
...
item
};
if
(
index
===
_sumArr
.
length
-
1
)
_item
.
colSpan
+=
1
;
return
_item
;
});
setSummaryArray
(
_sumArr
);
};
const
changeDate
=
({
dateFrom
,
dateTo
},
mode
)
=>
{
setTimeFrom
(
dateFrom
);
setTimeTo
(
dateTo
);
setDateMode
(
mode
);
};
const
mapHandleType
=
(
type
)
=>
{
const
_map
=
{
文本
:
handleText
,
数值
:
handleNumber
,
标签
:
handleTag
,
链接
:
handleLink
,
功能
:
handleWidget
,
弹窗
:
handleModal
,
日期
:
handleDateString
,
日期时间
:
handleDateTimeString
,
};
return
_map
[
type
]
||
_map
[
'文本'
];
};
const
returnSortFields
=
(
data
)
=>
{
return
data
.
map
((
item
)
=>
item
.
fieldAlias
);
};
// 处理表格数据,生成表头
const
returnColumn
=
(
config
,
data
)
=>
{
//0. 常规数据
//1. 合并表头;
//2. 四类形态的渲染处理;
//3. 多列表头排序;剔除掉原有图标,需要自己实现排序的按钮
let
_config
=
[...
config
].
filter
((
item
)
=>
item
.
isShow
);
function
dataStruct
(
keyArray
,
dataIndex
,
obj
,
dataObj
)
{
if
(
dataIndex
<
keyArray
.
length
-
1
)
{
if
(
!
obj
[
keyArray
[
dataIndex
]])
{
obj
[
keyArray
[
dataIndex
]]
=
{};
}
let
_dataIndex
=
dataIndex
+
1
;
dataStruct
(
keyArray
,
_dataIndex
,
obj
[
keyArray
[
dataIndex
]],
dataObj
);
}
else
if
(
dataIndex
===
keyArray
.
length
-
1
)
{
obj
[
keyArray
[
dataIndex
]]
=
dataObj
;
}
}
let
_tempObj
=
{};
let
_fieldAliasArray
=
handleDataToGetRowSpanArray
(
_config
,
data
);
// 需要向下合并的字段
_config
.
forEach
((
item
)
=>
{
let
_item
=
{
title
:
item
.
fieldAlias
,
dataIndex
:
item
.
fieldAlias
,
key
:
item
.
fieldAlias
,
ellipsis
:
true
,
onCell
:
(
record
,
rowIndex
)
=>
{
// console.log('Record: ', record); // record是这条记录,index是rowIndex
// 1. 如果该字段是需要向下合并的,则进入判断
let
_obj
=
{};
if
(
_fieldAliasArray
[
item
.
fieldAlias
])
{
_obj
.
rowSpan
=
_fieldAliasArray
[
item
.
fieldAlias
][
rowIndex
];
}
return
_obj
;
},
render
:
(
value
,
record
)
=>
{
// 文本、标签、链接、数值
// @params: item 当前的config数据,提供该字段的各类配置
// value 当前单元格的值
// record 点击单元格的整行数据
let
rest
=
[];
if
(
item
.
type
===
'功能'
)
{
/* rest = {
showComponent: setDetailsComponentVisible,
setDetailsConfig: setDetailConfig,
}; */
rest
=
[
setDetailsComponentVisible
,
setDetailConfig
];
}
else
if
(
item
.
type
===
'弹窗'
)
{
/* rest = {
showModal: setModalVisible,
setExtra: setExtra,
};*/
rest
=
[
setModalVisible
,
setExtra
];
}
return
mapHandleType
(
item
.
type
)(
item
,
value
||
''
,
record
,
...
rest
);
},
};
_item
.
width
=
item
.
columnWidth
||
200
;
// 列宽,不设置时默认给200;
if
(
item
.
fixedColumn
)
_item
.
fixed
=
item
.
fixedColumn
;
// 固定位置
_item
.
align
=
item
.
alignType
||
'left'
;
// 单元格内对齐方式
let
_keyArray
=
(
item
.
fieldGroup
||
item
.
fieldAlias
||
item
.
fieldName
).
split
(
fieldSplitStr
);
// 自定义排序
let
_sortFields
=
handleSortFields
(
sortFields
);
if
(
_sortFields
.
includes
(
item
.
fieldAlias
))
{
_item
.
sorter
=
true
;
}
dataStruct
(
_keyArray
,
0
,
_tempObj
,
_item
);
return
_item
;
});
let
_tempArray
=
[];
function
handleObject2Array
(
obj
,
arr
)
{
Object
.
keys
(
obj
).
forEach
((
key
,
index
)
=>
{
if
(
obj
[
key
].
title
&&
obj
[
key
].
title
===
key
)
{
arr
.
push
(
obj
[
key
]);
}
else
{
arr
.
push
({
title
:
key
,
children
:
[]
});
handleObject2Array
(
obj
[
key
],
arr
[
index
].
children
);
}
});
}
handleObject2Array
(
_tempObj
,
_tempArray
);
// 增加序号
_tempArray
.
unshift
({
title
:
'序号'
,
dataIndex
:
'r'
,
key
:
'r'
,
width
:
60
,
fixed
:
'left'
,
});
// 增加操作列
if
(
permission
.
includes
(
'editBtn'
)
||
permission
.
includes
(
'deleteBtn'
))
{
_tempArray
.
push
({
title
:
'操作'
,
width
:
60
,
fixed
:
'right'
,
render
:
(
text
,
record
)
=>
{
return
(
<
Space
className
=
{
style
.
handleColumnWrapper
}
>
{
permission
.
includes
(
'editBtn'
)
?
(
<
FormOutlined
className
=
{
style
.
editButton
}
onClick
=
{()
=>
{
setEditComponentVisible
(
true
);
setCurrentData
(
record
);
}}
/
>
)
:
(
''
)}
{
/* {
permission.includes('deleteBtn') ?
<DeleteOutlined disabled className={style.deleteButton} onClick={() => {
Modal.confirm({
content: '你确定要删除改数据吗?',
onOK: () => message.error('您无法删除数据!'),
});
}} /> : ''
}*/
}
<
/Space
>
);
},
});
}
// 统计宽度
let
_x
=
_tempArray
.
reduce
((
final
,
curr
)
=>
{
return
(
final
+=
curr
.
width
);
},
0
);
setTableX
(
_x
);
return
_tempArray
;
};
const
changeSortField
=
(
value
,
index
,
key
)
=>
{
let
_selectedSortFields
=
[...
selectedSortFields
];
_selectedSortFields
[
index
][
key
]
=
value
;
setSelectedSortFields
(
_selectedSortFields
);
};
const
addOtherSortFields
=
()
=>
{
let
_selectedSortFields
=
[...
selectedSortFields
];
_selectedSortFields
.
push
({
label
:
'次要排序'
,
value
:
''
,
sort
:
'asc'
,
});
setSelectedSortFields
(
_selectedSortFields
);
};
const
deleteSortField
=
(
index
)
=>
{
let
_selectedSortFields
=
[...
selectedSortFields
];
_selectedSortFields
.
splice
(
index
,
1
);
setSelectedSortFields
(
_selectedSortFields
);
};
const
setTableHeight
=
()
=>
{
if
(
!
tableWrapperRef
.
current
)
return
;
const
clientHeight
=
tableWrapperRef
.
current
?.
clientHeight
||
0
;
const
clientWidth
=
tableWrapperRef
.
current
?.
clientWidth
||
0
;
const
_height
=
controlRef
.
current
?.
clientHeight
;
// 控制条的高度
const
paginationHeight
=
75
;
// 分页部分的高度
const
tableHeaderHeight
=
tableHeaderLevel
*
40
;
// 表头高度
const
summaryHeight
=
summaryArray
.
length
?
40
*
(
Number
(
hasTotal
)
+
Number
(
hasSinglePage
))
:
0
;
// 总结栏的高度
const
_minus
=
clientHeight
-
_height
-
16
-
4
-
tableHeaderHeight
-
paginationHeight
-
summaryHeight
-
10
;
setListHeight
(
clientHeight
-
_height
-
paginationHeight
-
4
-
6
-
16
-
2
);
setTableY
(
_minus
);
};
const
getTableLevel
=
(
config
)
=>
{
let
_level
=
config
.
reduce
((
final
,
curr
)
=>
{
return
(
final
=
curr
.
level
>
final
?
curr
.
level
:
final
);
},
1
)
||
1
;
setTableHeaderLevel
(
_level
);
};
const
saveReportListSortFields
=
(
callback
)
=>
{
reportService
.
saveReportListSortFields
({
reportId
:
currentReportId
,
sortFields
:
selectedSortFields
.
filter
((
item
)
=>
item
.
value
)
.
map
((
item
)
=>
({
fieldAlias
:
item
.
value
,
sortType
:
item
.
sort
,
})),
})
.
then
((
res
)
=>
{
if
(
res
.
code
===
0
)
{
message
.
success
(
'排序保存成功!'
);
callback
();
}
else
{
message
.
error
(
res
.
msg
);
}
});
};
/** @description: 判断是否存在【时间】类型的选择,并返回组件 */
const
handleDate
=
(
obj
)
=>
{
let
_typeObj
=
obj
.
find
((
item
)
=>
item
.
filterRule
===
'日期'
);
setHasDatePicker
(
_typeObj
?
_typeObj
.
fieldAlias
:
''
);
const
_configItems
=
_typeObj
?.
configItems
.
split
(
'|'
)
||
''
;
let
_defaultDate
=
_configItems
.
find
((
item
)
=>
item
.
includes
(
'defaultDate='
))
?.
replace
(
'defaultDate='
,
''
)
?.
split
(
','
);
if
(
_defaultDate
&&
_defaultDate
.
length
>
1
)
{
_defaultDate
=
{
dateFrom
:
moment
(
_defaultDate
[
0
]),
dateTo
:
moment
(
_defaultDate
[
1
])
};
}
else
if
(
_defaultDate
&&
_defaultDate
.
length
===
1
)
{
_defaultDate
=
{
dateFrom
:
moment
(
_defaultDate
[
0
]),
dateTo
:
moment
(
_defaultDate
[
0
])
};
}
else
{
_defaultDate
=
{
dateFrom
:
moment
(),
dateTo
:
moment
()
};
}
setDefaultDateConfig
({
defaultDate
:
_defaultDate
?.
dateFrom
,
defaultModel
:
_configItems
.
find
((
item
)
=>
item
.
includes
(
'defaultModel='
))?.
replace
(
'defaultModel='
,
''
)
||
'year'
,
});
};
useEffect
(()
=>
{
getData
(
true
,
pagination
);
},
[]);
useEffect
(()
=>
{
if
(
tableHeaderLevel
)
setTableHeight
();
},
[
tableHeaderLevel
]);
useEffect
(()
=>
{
getData
(
false
,
pagination
);
},
[
timeFrom
,
timeTo
,
filterObject
]);
useEffect
(()
=>
{
function
getRefHeight
()
{
if
(
timer
)
clearTimeout
(
timer
);
timer
=
setTimeout
(()
=>
{
let
_height
=
controlRef
?.
current
.
clientHeight
;
setControlsHeight
(
_height
);
},
100
);
}
window
.
addEventListener
(
'resize'
,
getRefHeight
);
return
()
=>
window
.
removeEventListener
(
'resize'
,
getRefHeight
);
});
return
(
<
div
className
=
{
style
.
reportManage
}
ref
=
{
tableWrapperRef
}
>
{
/* 预留容器,提供给点击后的功能显示 */
}
{
detailsComponentVisible
?
(
<
DetailsComponent
url
=
{
detailConfig
.
url
}
params
=
{
detailConfig
.
params
}
onCancel
=
{()
=>
setDetailsComponentVisible
(
false
)}
/
>
)
:
(
''
)}
{
/* 为方便阅读,分开两部分代码 */
}
{
!
detailsComponentVisible
?
(
<
div
className
=
{
style
.
contentWrapper
}
>
{
state
!==
'scan'
?
(
<
Row
className
=
{
style
.
controlRow
}
ref
=
{
controlRef
}
>
<
Space
style
=
{{
flex
:
1
}}
size
=
{
8
}
wrap
=
{
true
}
>
{
/*时间搜索控件,确保时间搜索控件在第一个,单独匹配*/
}
{
hasDatePicker
&&
defaultDateConfig
.
defaultDate
!==
null
&&
permission
.
includes
(
'filters'
)
?
(
<
DatePickerGroup
showModels
=
{[
'all'
,
'month'
,
'quarter'
,
'year'
,
'custom'
]}
onChange
=
{
changeDate
}
format
=
{
dateFormat
}
defaultModel
=
{
defaultDateConfig
.
defaultModel
}
defaultDate
=
{
defaultDateConfig
.
defaultDate
}
/
>
)
:
(
''
)}
{
controls
&&
controls
.
length
&&
permission
.
includes
(
'filters'
)
?
controls
.
filter
((
control
)
=>
[
'下拉'
,
'多选'
].
includes
(
control
.
filterRule
))
.
map
((
control
)
=>
{
return
(
<
Form
.
Item
label
=
{
control
.
fieldAlias
}
key
=
{
control
.
fieldAlias
}
>
<
ReturnControlComponent
style
=
{{
width
:
240
}}
type
=
{
control
.
filterRule
}
reportName
=
{
reportName
}
fieldAlias
=
{
control
.
fieldAlias
}
configItems
=
{
control
.
configItems
}
onChange
=
{(
e
)
=>
controlSelectChange
(
control
.
fieldAlias
,
e
)}
/
>
<
/Form.Item
>
);
})
:
''
}
{
permission
.
includes
(
'filters'
)
?
(
<
Form
.
Item
label
=
"快速索引"
key
=
{
'快速搜索控件'
}
>
<
ReturnControlComponent
placeholder
=
{
`请输入
${
searchPlaceholder
.
length
?
searchPlaceholder
.
join
(
','
)
:
'关键字'
}
搜索`
}
style
=
{{
width
:
240
}}
type
=
{
'文本'
}
onChange
=
{(
e
)
=>
{
searchInputChange
(
e
);
}}
onSearch
=
{
searchData
}
/
>
<
/Form.Item
>
)
:
(
''
)}
<
/Space
>
{
permission
.
includes
(
'sortBtn'
)
?
(
<
div
style
=
{{
width
:
200
,
textAlign
:
'end'
}}
>
<
Space
size
=
{
8
}
nowrap
=
{
true
}
>
{
sortModalVisible
&&
permission
.
includes
(
'sortBtn'
)
?
(
<
Form
.
Item
>
<
Button
type
=
{
'primary'
}
title
=
{
'自定义排序'
}
icon
=
{
<
SortAscendingOutlined
/>
}
onClick
=
{()
=>
setModalVisible
(
true
)}
>
排序
<
/Button
>
<
/Form.Item
>
)
:
(
''
)}
{
permission
.
includes
(
'exportBtn'
)
?
(
<
Form
.
Item
>
<
Dropdown
.
Button
style
=
{{
float
:
'right'
}}
overlay
=
{
menu
}
>
导出
<
/Dropdown.Button
>
<
/Form.Item
>
)
:
(
''
)}
<
/Space
>
<
/div
>
)
:
(
''
)}
<
/Row
>
)
:
(
''
)}
<
div
className
=
{
style
.
tableContent
}
style
=
{{
height
:
`calc(100% -
${
controlsHeight
||
0
}
px)`
}}
>
{
columns
&&
columns
.
length
?
(
<
BasicTable
rowKey
=
{
'Key'
}
bordered
loading
=
{
tableLoading
}
dataSource
=
{
tableData
}
columns
=
{
columns
}
onChange
=
{(
pagination
,
filters
,
sorter
,
extra
)
=>
{
console
.
log
(
sorter
);
setSorter
(
sorter
);
}}
pagination
=
{
permission
.
includes
(
'pagination'
)
?
pagination
:
false
}
// 237是内置图片高度
scroll
=
{{
y
:
tableData
&&
tableData
.
length
?
`calc(100% - 44px)`
:
237
,
x
:
tableX
}}
summary
=
{(
pageData
)
=>
{
if
(
summaryArray
.
length
&&
tableData
&&
tableData
.
length
)
return
(
<
Table
.
Summary
fixed
>
<
Table
.
Summary
.
Row
>
{
hasSinglePage
?
summaryArray
.
map
((
item
,
index
)
=>
{
if
(
item
.
fieldName
===
'空值行0'
)
{
return
(
<
Table
.
Summary
.
Cell
key
=
{
`summary_
${
index
}
`
}
index
=
{
0
}
colSpan
=
{
item
.
colSpan
+
1
}
>
<
span
style
=
{{
display
:
'inline-block'
,
width
:
'100%'
,
textAlign
:
'center'
,
}}
>
小计
<
/span
>
<
/Table.Summary.Cell
>
);
}
else
if
(
item
.
fieldName
.
includes
(
'空值行'
))
{
return
(
<
Table
.
Summary
.
Cell
key
=
{
`summary_
${
index
}
`
}
index
=
{
0
}
colSpan
=
{
item
.
colSpan
}
/
>
);
}
else
{
return
(
<
Table
.
Summary
.
Cell
key
=
{
`summary_
${
index
}
`
}
index
=
{
0
}
>
<
span
style
=
{{
display
:
'inline-block'
,
width
:
'100%'
,
textAlign
:
item
.
alignType
,
}}
>
{
item
.
type
.
replace
(
'求'
,
''
)}:{
' '
}
{
returnHandledNumber
(
item
.
configItems
,
item
[
'单页'
])}
<
/span
>
<
/Table.Summary.Cell
>
);
}
})
:
''
}
<
/Table.Summary.Row
>
<
Table
.
Summary
.
Row
>
{
hasTotal
?
summaryArray
.
map
((
item
)
=>
{
if
(
item
.
fieldName
===
'空值行0'
)
{
return
(
<
Table
.
Summary
.
Cell
index
=
{
0
}
colSpan
=
{
item
.
colSpan
+
1
}
>
<
span
style
=
{{
display
:
'inline-block'
,
width
:
'100%'
,
textAlign
:
'center'
,
}}
>
总计
<
/span
>
<
/Table.Summary.Cell
>
);
}
else
if
(
item
.
fieldName
.
includes
(
'空值行'
))
{
return
<
Table
.
Summary
.
Cell
index
=
{
0
}
colSpan
=
{
item
.
colSpan
}
/>
;
}
else
{
return
(
<
Table
.
Summary
.
Cell
index
=
{
0
}
>
<
span
style
=
{{
display
:
'inline-block'
,
width
:
'100%'
,
textAlign
:
item
.
alignType
,
}}
>
{
item
.
type
.
replace
(
'求'
,
''
)}:{
' '
}
{
returnHandledNumber
(
item
.
configItems
,
item
[
'全部'
])}
<
/span
>
<
/Table.Summary.Cell
>
);
}
})
:
''
}
<
/Table.Summary.Row
>
<
/Table.Summary
>
);
}}
/
>
)
:
(
<
div
className
=
{
style
.
spinWrapper
}
>
<
Spin
/>
<
/div
>
)}
<
/div
>
<
/div
>
)
:
(
''
)}
<
Modal
title
=
{
'自定义排序字段'
}
visible
=
{
modalVisible
}
onCancel
=
{()
=>
setModalVisible
(
false
)}
footer
=
{
<
div
style
=
{{
display
:
'flex'
,
justifyContent
:
'space-between'
}}
>
<
div
>
<
Button
type
=
{
'link'
}
onClick
=
{()
=>
addOtherSortFields
()}
>
增加次要排序
<
/Button
>
<
/div
>
<
div
>
<
Button
onClick
=
{()
=>
setModalVisible
(
false
)}
>
取消
<
/Button
>
<
Button
type
=
{
'primary'
}
onClick
=
{()
=>
{
saveReportListSortFields
(()
=>
getData
(
false
,
pagination
));
setModalVisible
(
false
);
}}
>
确认
<
/Button
>
<
/div
>
<
/div
>
}
>
{
selectedSortFields
.
map
((
item
,
index
)
=>
(
<
Row
key
=
{
'label'
}
className
=
{
style
.
controlRow
}
>
<
Space
size
=
{
8
}
wrap
=
{
true
}
>
<
Form
.
Item
label
=
{
item
.
label
}
>
<
Select
style
=
{{
width
:
240
}}
defaultValue
=
{
item
.
value
}
value
=
{
item
.
value
}
onChange
=
{(
e
)
=>
changeSortField
(
e
,
index
,
'value'
)}
>
<
Option
value
=
""
>
未选择
<
/Option
>
{
allSortFields
.
map
((
item
)
=>
(
<
Option
value
=
{
item
}
>
{
item
}
<
/Option
>
))}
<
/Select
>
<
/Form.Item
>
<
Form
.
Item
>
<
Select
style
=
{{
width
:
120
}}
defaultValue
=
{
item
.
sort
}
value
=
{
item
.
sort
}
onChange
=
{(
e
)
=>
changeSortField
(
e
,
index
,
'sort'
)}
>
<
Option
value
=
{
'asc'
}
>
升序
<
/Option
>
<
Option
value
=
{
'desc'
}
>
降序
<
/Option
>
<
/Select
>
<
/Form.Item
>
{
index
!==
0
?
(
<
Form
.
Item
>
<
MinusCircleOutlined
style
=
{{
color
:
'rgba(0,0,0,.65)'
}}
onClick
=
{()
=>
deleteSortField
(
index
)}
/
>
<
/Form.Item
>
)
:
(
''
)}
<
/Space
>
<
/Row
>
))}
<
/Modal
>
<
Modal
visible
=
{
extraModal
}
onCancel
=
{()
=>
setExtraModal
(
false
)}
destroyOnClose
width
=
{
800
}
>
{
extra
}
<
/Modal
>
{
/* 编辑表单 */
}
<
Modal
title
=
{
'编辑报表信息'
}
visible
=
{
editComponentVisible
}
width
=
{
'80%'
}
footer
=
{
null
}
// visible={true}
onCancel
=
{()
=>
setEditComponentVisible
(
false
)}
>
<
ReportEditForm
reportDetails
=
{
tableStruct
}
reportData
=
{
currentData
}
onCancel
=
{()
=>
{
setEditComponentVisible
(
false
);
getData
(
false
,
pagination
);
}}
reportName
=
{
reportName
}
/
>
<
/Modal
>
<
/div
>
);
};
const
mapStateToProps
=
(
state
)
=>
{
const
allWidgets
=
state
.
getIn
([
'global'
,
'globalConfig'
,
'allWidgets'
]);
let
_flatWidgets
=
[];
const
flatWidgets
=
(
arr
)
=>
{
arr
.
forEach
((
item
)
=>
{
if
(
item
.
widgets
&&
item
.
widgets
.
length
)
{
flatWidgets
(
item
.
widgets
);
}
else
{
_flatWidgets
.
push
(
item
);
}
});
};
flatWidgets
(
allWidgets
);
return
{
allWidgets
:
_flatWidgets
,
};
};
export
default
connect
(
mapStateToProps
,
null
)(
ReportsManage
);
packages/base-components/BasicReport/src/
index
.less
→
packages/base-components/BasicReport/src/
ReportsManage/ReportsManage
.less
View file @
3ebe7190
File moved
packages/base-components/BasicReport/src/ReportsManage/ReportsPermissionDelete.js
0 → 100644
View file @
3ebe7190
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 @
3ebe7190
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 @
3ebe7190
/**
* * 报表设置列表 * 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
,
}
from
'@ant-design/icons'
;
import
{
Button
,
Checkbox
,
Divider
,
Form
,
Input
,
InputNumber
,
message
,
Modal
,
Row
,
Select
,
Space
,
Switch
,
Tooltip
,
}
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
}
from
'../api/service/report'
;
import
{
isNumber
,
isString
}
from
'./utils/utils'
;
import
moment
from
'moment'
;
const
{
Option
}
=
Select
;
const
{
TextArea
}
=
Input
;
const
{
Search
}
=
Input
;
const
typeArray
=
[
'文本'
,
'标签'
,
'数值'
,
'链接'
,
'功能'
,
'弹窗'
,
'日期'
,
'日期时间'
];
const
filterRule
=
[
'文本'
,
'下拉'
,
'多选'
,
'日期'
];
const
publicSplit
=
'&split;'
;
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
);
}}
/
>
<
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
SortableItem
=
SortableElement
((
props
)
=>
<
tr
{...
props
}
/>
)
;
const
SortableBody
=
SortableContainer
((
props
)
=>
<
tbody
{...
props
}
/>
)
;
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
:
'操作'
,
width
:
100
,
render
:
(
text
,
record
)
=>
{
return
(
<
DeleteOutlined
onClick
=
{()
=>
deleteReportDetail
(
record
.
id
)}
style
=
{{
color
:
'red'
}}
/
>
);
},
},
];
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
();
});
};
const
changeField
=
(
record
)
=>
{
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
;
};
const
submitReportDetails
=
()
=>
{
// 1.表单内的值;2.标签值
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
);
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
=
()
=>
{
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
(
'提交成功!'
);
// setIsEditing(false);
}
else
{
message
.
error
(
res
.
msg
);
}
setSubmitFieldLoading
(
false
);
setDetailVisible
(
false
);
clickReport
(
currentReport
.
id
);
});
});
};
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
];
_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
];
};
// 颜色卡片组件
//[
// "rgb(255, 255, 255)",
// "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)",
// "rgb(220, 223, 228)",
// "rgb(173, 203, 255)",
// "rgb(173, 228, 255)",
// "rgb(172, 226, 197)",
// "rgb(255, 181, 179)",
// "rgb(255, 206, 163)",
// "rgb(255, 234, 153)",
// "rgb(231, 180, 255)",
// "rgb(255, 179, 220)",
// "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(231, 180, 255)",
// "rgb(154, 56, 215)",
// "rgb(221, 64, 151)"
// ]
const
ColorBoard
=
({
value
,
onChange
})
=>
{
return
(
<>
<
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
:
value
||
'rgba(0,0,0,.65)'
,
}}
onClick
=
{(
e
)
=>
{
clickColorCard
(
e
);
setCurrentColorPicker
({
key
:
'wordColor'
,
callback
:
onChange
,
});
}}
/
>
<
/div
>
<
/
>
);
};
// 拖拽
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
);
};
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
,
}}
>
<
SketchPicker
width
=
{
240
}
presetColors
=
{[
'rgb(255, 255, 255)'
,
'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)'
,
'rgb(220, 223, 228)'
,
'rgb(173, 203, 255)'
,
'rgb(173, 228, 255)'
,
'rgb(172, 226, 197)'
,
'rgb(255, 181, 179)'
,
'rgb(255, 206, 163)'
,
'rgb(255, 234, 153)'
,
'rgb(231, 180, 255)'
,
'rgb(255, 179, 220)'
,
'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
.
fieldName
}
<
/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
>
{
/* <Form.Item label={'对齐方式'} name={'alignType'}>
<Radio.Group>
<Radio value={'left'}>左</Radio>
<Radio value={'center'}>中</Radio>
<Radio value={'right'}>右</Radio>
</Radio.Group>
</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
:
'color'
,
});
}}
/
>
<
/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
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'
}
style
=
{{
marginRight
:
8
}}
onClick
=
{
submitDetailFromTable
}
>
保存字段
<
/Button
>
<
/
>
)
:
(
''
)}
{
isEditing
?
(
<
Button
type
=
{
'primary'
}
onClick
=
{()
=>
setIsEditing
(
false
)}
>
拖动排序
<
/Button
>
)
:
(
<
Button
type
=
{
'primary'
}
onClick
=
{()
=>
setIsEditing
(
true
)}
>
关闭排序
<
/Button
>
)}
<
/Form.Item
>
<
/Form
>
{
/* <Button type={'primary'} onClick={() => {
setDetailTableVisible(false);
// setIsEditing(false);
}}>返回</Button>*/
}
<
/Row
>
<
div
className
=
{
style
.
tableContent
}
>
<
Form
className
=
{
style
.
tableForm
}
form
=
{
editDetailForm
}
>
<
BasicTable
loading
=
{
detailTableLoading
}
pagination
=
{
false
}
bordered
scroll
=
{{
y
:
'calc(100% - 40px)'
}}
rowKey
=
{
'id'
}
columns
=
{
detailColumns
}
dataSource
=
{
detailData
.
filter
((
item
)
=>
item
.
visible
)}
components
=
{
isEditing
?
''
:
{
body
:
{
wrapper
:
DraggableContainer
,
row
:
DraggableBodyRow
,
},
}
}
onRow
=
{(
record
)
=>
{
return
{
onDoubleClick
:
(
e
)
=>
{
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'
}
onClick
=
{()
=>
openCreateModal
(()
=>
{
setCurrentReport
({});
setAllFields
([]);
setIsCreatingMainTable
(
true
);
createMainTableForm
.
setFieldsValue
({
tableName
:
''
,
reportName
:
''
,
reportFields
:
[],
});
})
}
>
新增
<
/Button
>
<
/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 @
3ebe7190
@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/assets/pic.webp
→
packages/base-components/BasicReport/src/
ReportsManage/
assets/pic.webp
View file @
3ebe7190
File moved
packages/base-components/BasicReport/src/ReportsManage/extra/detailsComponent.js
0 → 100644
View file @
3ebe7190
/**
* * 用来动态加载配置的组件功能函数 * 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 @
3ebe7190
// 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/utils/handlers.js
→
packages/base-components/BasicReport/src/
ReportsManage/
utils/handlers.js
View file @
3ebe7190
import
style
from
'../
index
.less'
;
import
style
from
'../
ReportsManage
.less'
;
import
extraComponents
from
'../extra/extraComponents'
;
import
moment
from
'moment'
;
import
{
Tag
}
from
'antd'
;
...
...
@@ -206,5 +206,5 @@ export const handlePageSize = (numStr) => {
};
// 处理默认排序
export
const
handleSortFields
=
(
sortFields
)
=>
{
return
sortFields
&&
sortFields
.
split
(
','
)
;
return
(
sortFields
&&
sortFields
.
split
(
','
))
||
[]
;
};
packages/base-components/BasicReport/src/utils/utils.js
→
packages/base-components/BasicReport/src/
ReportsManage/
utils/utils.js
View file @
3ebe7190
File moved
packages/base-components/BasicReport/src/api/constants.js
View file @
3ebe7190
export
const
RESTART_ON_REMOUNT
=
'@@saga-injector/restart-on-remount'
;
export
const
DAEMON
=
'@@saga-injector/daemon'
;
export
const
ONCE_TILL_UNMOUNT
=
'@@saga-injector/once-till-unmount'
;
export
const
FILTER_FOLER_REG
=
/
(
configs|configuration|framework|iframe|Product|product|productex|project|qrcode|threedimensional|video|widgetconfigs
)
/
;
export
const
FILTER_FOLER_WEB5
=
/
(
pages
)
/
;
export
const
SERVICE_APP_GET_UI_META
=
'app.getUIMeta'
;
export
const
SERVICE_APP_LOGIN_MODE
=
{
...
...
packages/base-components/BasicReport/src/components/DatePickerGroup.js
→
packages/base-components/BasicReport/src/components/DatePickerGroup
/index
.js
View file @
3ebe7190
File moved
packages/base-components/BasicReport/src/index.js
View file @
3ebe7190
/**
* * 轻量化报表通用配置页面 * create by ChenLong on 2022/6/22 *
* 功能路径:src\pages\product\ReportsManage\ReportsManage.js * 菜单参数列 表:*变量名*(变量说明,数据类型,是否必填,取值范围)
*
* @changelog:
* editComponentVisible && detailsComponentVisible 共同作用组件的显示
*/
/**
* @description: 功能描述:参考台账概念,重新定义
* @tips: 1. 如果需要对字段进行处理,增加功能之类的。需要提前确定返回值的类型.
* 2. 如果要用customerState来控制页面按钮等,需要按照给定的权限值进行配置
* @params: <ReportManage
* params={{reportName,pageSize,filterFields,filterValues,state,customerState}}>
*
*
*
* reportName: 报表名称;
* pageSize: 按需配置,默认加载100;
* filterFields:
*
*
* 需要默认加载的过滤条件的field,英文逗号分割,与filterValues一一对应;
* filterValues:
*
*
* 需要默认加载的过滤条件的value,英文逗号分割,与filterFields一一对应;
* state: delete|edit|scan 各种权限;
*
*
*
* customerState: ['filters','sortBtn','exportBtn','editBtn','deleteBtn','pagination'];
*
*
*
* sortFields: '排序字段1,排序字段2,排序字段3'
* @config:
* 【数值】 [prefix]_d%|0.00|_d%[suffix]|金额 = 前缀|精度|后缀|金额类的数据(千分位),可分别设置。
* 【标签】 split=,
*
* 分隔符。
*
* 【功能】 功能配置框内,配置需要跳转功能所需参数,type、url是必须功能,需要type判断类型,需要通过url去解析加载组件。
* @type:
* 【文本】普通文本
* 【数值】数值类型的文本
* 【标签】文本渲染成标签,具有不同颜色;
* 【功能】“功能”会在当前页内去展示,会卸载掉列表页,加载功能组件。配置 type +
*
*
* url + 自定义字段 的配置项,自行解析加载即可;
* -------------------- 待需求提出后开发 -----------------
*
*
*
* 【链接】内链外链,点击可跳转;配置规则:配置链接即可;
* 【弹窗】modal弹窗弹出,弹窗内的具体业务自行配置;配置规则:[function_name];[...params];
*
*
*
* ------------------------------------------------------
* @table:
* 表头:表头需要支持多级表头、合并;
* 列:列支持设置筛选;
* 固定行、固定列:可根据配置生成固定行、列;
* @control:
* 固定筛选:拥有固定筛选框,根据配置显示可搜索字段;
*
*
*
* 可配置筛选框:根据字段配置,将字段设置成筛选条件,枚举出该字段所有值,提供用户进行选择,然后进行筛选;筛选框具体形态可根据配置字段来渲染;
* 导出功能:各类导出功能按钮;
*
*
*
* 时间筛选框:单表唯一;需要变更,支持多时间参数的筛选
* @state: 参考台账权限 delete 全部权限
* edit 除删除外的权限
* scan 查看权限
*/
import
React
,
{
useState
,
useEffect
,
useRef
}
from
'react'
;
import
{
Row
,
Button
,
Tag
,
message
,
Form
,
Space
,
Modal
,
Select
,
Table
,
Dropdown
,
Menu
,
Spin
,
}
from
'antd'
;
import
{
SortAscendingOutlined
,
MinusCircleOutlined
,
ExportOutlined
,
FormOutlined
,
}
from
'@ant-design/icons'
;
import
BasicTable
from
'@wisdom-components/basictable'
;
import
ReturnControlComponent
from
'./components/Control'
;
import
{
reportService
}
from
'./api/index'
;
import
style
from
'./index.less'
;
import
{
exportAccountData
}
from
'./api/service/report'
;
import
DatePickerGroup
from
'./components/DatePickerGroup'
;
import
moment
from
'moment'
;
import
{
handleNumber
,
handleTag
,
handleText
,
handleLink
,
handleWidget
,
handleModal
,
handleDateString
,
handleDateTimeString
,
handlePageSize
,
handleSortFields
,
}
from
'./utils/handlers'
;
import
{
hasMoney
,
isArray
,
isNumber
,
isString
,
returnHandledNumber
}
from
'./utils/utils'
;
import
{
connect
}
from
'react-redux'
;
import
ReportEditForm
from
'./ReportEditForm'
;
import
React
from
'react'
;
import
ReportsManage
from
'./ReportsManage/ReportsManage'
;
const
ControlsType
=
[
'下拉'
,
'多选'
,
'日期'
];
const
fieldSplitStr
=
'-'
;
// fieldGroup用来分割
const
{
Option
}
=
Select
;
const
dateFormat
=
'YYYY-MM-DD'
;
// 日期格式化
const
initDateModel
=
'all'
;
let
timer
=
null
;
const
PERMISSION
=
{
delete
:
[
'filters'
,
'pagination'
,
// 操作条按钮
'sortBtn'
,
'exportBtn'
,
// 操作列
'editBtn'
,
'deleteBtn'
,
],
edit
:
[
'filters'
,
'pagination'
,
'sortBtn'
,
'exportBtn'
,
// 操作列
'editBtn'
,
],
scan
:
[
'filters'
,
'pagination'
],
};
const
BasicReport
=
(
props
)
=>
{
const
{
reportName
,
pageSize
,
filterFields
,
filterValues
,
state
,
customerState
,
sortFields
}
=
props
.
params
;
const
permission
=
customerState
&&
isArray
(
customerState
)
?
customerState
:
PERMISSION
[
state
||
'delete'
];
const
tableWrapperRef
=
useRef
();
const
controlRef
=
useRef
();
if
(
!
reportName
)
return
(
<
div
className
=
{
style
.
lackParams
}
>
未配置
reportName
,请完善配置并重新登陆后查看页面!
<
/div
>
);
const
[
tableStruct
,
setTableStruct
]
=
useState
([]);
// 临时使用,看后续是否需要保留
const
[
columns
,
setColumns
]
=
useState
([]);
// 表头设置
const
[
tableData
,
setTableData
]
=
useState
([]);
// 表数据
const
[
pagination
,
setPagination
]
=
useState
({
current
:
1
,
total
:
0
,
pageSize
:
handlePageSize
(
pageSize
)
||
100
,
pageSizeOptions
:
[...
new
Set
([
20
,
50
,
100
].
concat
(
handlePageSize
(
pageSize
)))]
.
filter
((
item
)
=>
Number
(
item
))
.
sort
((
a
,
b
)
=>
Number
(
a
)
-
Number
(
b
)),
showQuickJumper
:
true
,
showSizeChanger
:
true
,
onShowSizeChange
:
(
current
,
size
)
=>
{
let
_pagination
=
{
...
pagination
};
_pagination
.
current
=
current
;
_pagination
.
pageSize
=
size
;
setPagination
(
_pagination
);
getData
(
false
,
_pagination
);
},
onChange
:
(
current
,
size
)
=>
{
let
_pagination
=
{
...
pagination
};
_pagination
.
current
=
current
;
_pagination
.
pageSize
=
size
;
setPagination
(
_pagination
);
getData
(
false
,
_pagination
);
},
});
const
[
controls
,
setControls
]
=
useState
([]);
// 用来存储操作控件
const
[
searchContent
,
setSearchContent
]
=
useState
(
''
);
// 搜索框内的值
const
[
searchPlaceholder
,
setSearchPlaceholder
]
=
useState
([]);
// 搜索框的placeholder
const
[
filterObject
,
setFilterObject
]
=
useState
({});
// 存控制条中,选了筛选条件的值
const
[
modalVisible
,
setModalVisible
]
=
useState
(
false
);
const
[
allSortFields
,
setAllSortFields
]
=
useState
([]);
// 设置所有列表
const
[
selectedSortFields
,
setSelectedSortFields
]
=
useState
([
{
label
:
'主要排序'
,
value
:
''
,
sort
:
'asc'
,
},
]);
const
[
summaryArray
,
setSummaryArray
]
=
useState
([]);
// 总结栏,包括小计、总计
const
[
tableY
,
setTableY
]
=
useState
(
500
);
const
[
tableX
,
setTableX
]
=
useState
(
1820
);
const
[
listHeight
,
setListHeight
]
=
useState
(
0
);
const
[
tableHeaderLevel
,
setTableHeaderLevel
]
=
useState
(
null
);
const
[
exportLoading
,
setExportLoading
]
=
useState
(
false
);
const
[
extraModal
,
setExtraModal
]
=
useState
(
false
);
const
[
hasTotal
,
setHasTotal
]
=
useState
(
false
);
const
[
hasSinglePage
,
setHasSinglePage
]
=
useState
(
false
);
const
[
tableLoading
,
setTableLoading
]
=
useState
(
false
);
const
[
mergeObject
,
setMergeObject
]
=
useState
({});
// const
const
[
timeFrom
,
setTimeFrom
]
=
useState
(
moment
().
startOf
(
initDateModel
).
format
(
dateFormat
));
const
[
timeTo
,
setTimeTo
]
=
useState
(
moment
().
endOf
(
initDateModel
).
format
(
dateFormat
));
const
[
extra
,
setExtra
]
=
useState
(
<><
/>
)
;
const
[
sortModalVisible
,
setSortModalVisible
]
=
useState
(
false
);
const
[
currentReportId
,
setCurrentReportId
]
=
useState
(
null
);
const
[
hasDatePicker
,
setHasDatePicker
]
=
useState
(
''
);
const
[
defaultDateConfig
,
setDefaultDateConfig
]
=
useState
({
defaultModel
:
'year'
,
defaultDate
:
null
,
});
const
[
dateModel
,
setDateMode
]
=
useState
(
'all'
);
// const [detailsComponent, setDetailsComponent] = useState(<></>); // 详情组件
const
[
detailsComponentVisible
,
setDetailsComponentVisible
]
=
useState
(
false
);
// 是否显示详情组件
const
[
editComponentVisible
,
setEditComponentVisible
]
=
useState
(
false
);
// 是否显示编辑组件
const
[
currentData
,
setCurrentData
]
=
useState
({});
const
[
detailConfig
,
setDetailConfig
]
=
useState
({
url
:
''
,
type
:
''
,
params
:
{}
});
const
[
controlsHeight
,
setControlsHeight
]
=
useState
(
44
);
const
menu
=
()
=>
{
const
_item
=
[
{
label
:
(
<
Button
size
=
"middle"
loading
=
{
exportLoading
}
type
=
"text"
onClick
=
{()
=>
exportModule
(
'pdf'
,
'pdf'
)}
icon
=
{
<
ExportOutlined
/>
}
>
导出
pdf
<
/Button
>
),
key
:
'exportPdf'
,
},
{
label
:
(
<
Button
size
=
"middle"
loading
=
{
exportLoading
}
type
=
"text"
onClick
=
{()
=>
exportModule
(
'excel'
,
'xls'
)}
icon
=
{
<
ExportOutlined
/>
}
>
导出
Excel
<
/Button
>
),
key
:
'exportExcel'
,
},
];
return
<
Menu
items
=
{
_item
}
/>
;
};
const
exportModule
=
(
type
,
extension
)
=>
{
setExportLoading
(
true
);
exportAccountData
(
{
responseType
:
'blob'
},
{
exportType
:
type
},
{
reportName
,
pageIndex
:
0
,
pageSize
:
0
,
sortFields
:
''
,
content
:
''
,
filters
:
[
{
fieldAlias
:
''
,
fieldValue
:
''
,
},
],
},
)
.
then
((
res
)
=>
{
if
(
res
&&
res
.
code
===
-
1
)
return
message
.
error
(
res
.
msg
);
const
url
=
window
.
URL
.
createObjectURL
(
new
Blob
([
res
],
{
type
:
'application/octet-stream;charset=UTF-8'
}),
);
const
a
=
document
.
createElement
(
'a'
);
a
.
href
=
url
;
a
.
target
=
'_blank'
;
a
.
download
=
`
${
reportName
}${
moment
().
format
(
'YYYY-MM-DD-HH-mm-ss'
).
replaceAll
(
'-'
,
''
)}
.`
+
extension
;
a
.
click
();
a
.
remove
();
setExportLoading
(
false
);
})
.
catch
((
err
)
=>
{
setExportLoading
(
false
);
});
};
const
searchData
=
(
e
)
=>
{
getData
(
false
,
pagination
);
};
const
controlSelectChange
=
(
fieldAlias
,
e
)
=>
{
let
_filterArray
=
{
...
filterObject
};
_filterArray
[
fieldAlias
]
=
e
;
setFilterObject
(
_filterArray
);
};
const
searchInputChange
=
(
e
)
=>
{
setSearchContent
(
e
.
target
.
value
);
};
const
setConfig
=
(
config
,
summary
,
data
)
=>
{
getControlsBarConfig
(
config
);
getTableSummaryConfig
(
config
,
summary
);
getTableLevel
(
config
);
};
const
addFilterAndSearchParams
=
(
data
)
=>
{
let
_data
=
{
...
data
};
// 搜索框是否有值
if
(
searchContent
)
_data
.
content
=
searchContent
;
// filterObject是存起来的控制栏的过滤条件
let
_filters
=
Object
.
keys
(
filterObject
)
.
filter
((
key
)
=>
{
let
_value
=
filterObject
[
key
];
return
(
isString
(
_value
)
&&
_value
)
||
(
isArray
(
_value
)
&&
_value
.
length
);
})
.
map
((
key
)
=>
{
let
_value
=
filterObject
[
key
];
if
(
isString
(
_value
)
&&
_value
)
return
{
fieldAlias
:
key
,
fieldValue
:
_value
,
};
if
(
isArray
(
_value
)
&&
_value
.
length
)
return
{
fieldAlias
:
key
,
fieldValue
:
_value
.
join
(
','
),
};
return
false
;
});
// 加上时间过滤参数
if
(
dateModel
!==
'all'
&&
hasDatePicker
&&
timeFrom
&&
timeTo
)
{
_filters
.
push
({
fieldAlias
:
hasDatePicker
,
fieldValue
:
`
${
timeFrom
}
00:00:00,
${
timeTo
}
23:59:59`
,
});
}
// 合并手动传入的filters
if
(
filterFields
)
{
let
_customerFilterArray
=
filterFields
.
split
(
','
);
let
_customerValueArray
=
filterValues
.
split
(
','
);
_customerFilterArray
.
forEach
((
item
,
index
)
=>
{
_filters
.
push
({
fieldAlias
:
item
,
fieldValue
:
_customerValueArray
[
index
]
||
''
,
});
});
}
// 并入 _data
if
(
_filters
.
length
)
_data
.
filters
=
_filters
;
return
_data
;
};
// 排序字符串处理成数组
const
handleSortString
=
(
sortString
)
=>
{
// selectedSortFields
let
_sortStringArray
=
sortString
.
split
(
','
).
map
((
item
,
index
)
=>
{
let
_item
=
item
.
split
(
' '
);
if
(
index
===
0
)
{
return
{
label
:
'主要排序'
,
value
:
_item
[
0
].
replace
(
/
\[
|
\]
/g
,
''
),
sort
:
_item
[
1
],
};
}
else
{
return
{
label
:
'次要排序'
,
value
:
_item
[
0
].
replace
(
/
\[
|
\]
/g
,
''
),
sort
:
_item
[
1
],
};
}
});
setSelectedSortFields
(
_sortStringArray
);
};
/** @description: 根据是否向下合并处理数据,返回合并的key的数组 */
const
returnMergeArray
=
(
config
)
=>
{
return
config
.
filter
((
item
)
=>
item
.
isMerge
).
map
((
item
)
=>
item
.
fieldAlias
);
};
/** @description: 根据配置和数据,计算出该合并的字段和每一行是否合并 */
const
handleDataToGetRowSpanArray
=
(
config
,
data
)
=>
{
let
_arr
=
returnMergeArray
(
config
);
let
_merge
=
{};
// _merge:{爱好:[[0,3],[3,5]]}
_arr
.
forEach
((
key
)
=>
{
_merge
[
key
]
=
{};
let
_currentIndex
=
0
;
data
.
forEach
((
item
,
index
)
=>
{
if
(
index
>
0
)
{
if
(
item
[
key
]
===
data
[
index
-
1
][
key
])
{
_merge
[
key
][
_currentIndex
]
+=
1
;
_merge
[
key
][
index
]
=
0
;
}
else
{
_currentIndex
=
index
;
_merge
[
key
][
index
]
=
1
;
}
}
else
{
_merge
[
key
][
0
]
=
1
;
}
});
});
return
_merge
;
};
const
getData
=
(
isInit
,
pagination
)
=>
{
setTableLoading
(
true
);
const
{
pageSize
,
current
}
=
pagination
;
// 搜索条件附加到params
let
_data
=
addFilterAndSearchParams
({
reportName
:
reportName
,
pageIndex
:
current
,
pageSize
:
pageSize
,
});
// sortFields
reportService
.
getReportInfo
(
_data
)
.
then
((
res
)
=>
{
if
(
res
.
code
===
0
)
{
let
_reportDetails
=
res
.
data
.
reportDetails
;
let
_statisticalValues
=
res
.
data
.
statisticalValues
;
let
_tableData
=
res
.
data
.
data
.
list
;
let
_sortString
=
res
.
data
.
sortString
;
if
(
isInit
)
{
setConfig
(
_reportDetails
,
_statisticalValues
,
_tableData
);
}
getTableHeaderConfig
(
_reportDetails
,
_tableData
);
let
_pagination
=
{
...
pagination
};
_pagination
.
total
=
res
.
data
.
data
.
totalCount
;
setPagination
(
_pagination
);
setTableData
(
_tableData
);
// 处理排序字段
handleSortString
(
_sortString
);
if
(
_tableData
)
{
setSortModalVisible
(
true
);
setCurrentReportId
(
_reportDetails
[
0
]?.
reportId
);
}
else
{
setSortModalVisible
(
false
);
setCurrentReportId
(
null
);
}
}
else
{
setSortModalVisible
(
false
);
setCurrentReportId
(
null
);
message
.
error
(
'未能查询到报表数据!'
);
let
_pagination
=
{
...
pagination
};
_pagination
.
total
=
0
;
_pagination
.
current
=
1
;
setPagination
(
_pagination
);
setTableData
([]);
}
setTableLoading
(
false
);
})
.
catch
((
err
)
=>
{
console
.
log
(
err
);
setTableLoading
(
false
);
});
};
/** @description: 在配置项中,isFilter: true 用来渲染控制框;filterRule: 下拉/文本/多选 */
const
getControlsBarConfig
=
(
config
)
=>
{
let
_data
=
config
.
filter
((
item
)
=>
item
.
isFilter
);
let
_searchPlaceholder
=
[];
_data
.
filter
((
item
)
=>
item
.
filterRule
===
'文本'
)
.
forEach
((
item
)
=>
_searchPlaceholder
.
push
(
item
.
fieldAlias
));
setSearchPlaceholder
(
_searchPlaceholder
);
let
_controls
=
_data
.
filter
((
item
)
=>
ControlsType
.
includes
(
item
.
filterRule
));
setControls
(
_controls
);
handleDate
(
_controls
);
};
const
getTableHeaderConfig
=
(
config
,
data
)
=>
{
setTableStruct
(
config
);
setColumns
(
returnColumn
(
config
,
data
));
setAllSortFields
(
returnSortFields
(
config
));
};
const
getTableSummaryConfig
=
(
config
,
summary
)
=>
{
if
(
summary
.
length
===
0
)
{
setSummaryArray
([]);
return
false
;
}
let
_summaryConfig
=
{};
let
_configLength
=
config
.
length
;
// 需要判断
// 合并列
let
_colSpan
=
-
1
;
let
_index
=
0
;
config
.
filter
((
item
)
=>
item
.
isShow
)
.
forEach
((
item
,
index
)
=>
{
if
(
item
.
isStatistics
)
{
_index
+=
1
;
_colSpan
=
-
1
;
_summaryConfig
[
item
.
fieldAlias
]
=
{
fieldName
:
item
.
fieldAlias
,
index
,
alignType
:
item
.
alignType
,
type
:
item
.
statisticsRule
,
isMoney
:
item
.
type
===
'数值'
&&
!!
hasMoney
(
item
.
configItems
),
configItems
:
item
.
configItems
,
};
}
else
{
let
_name
=
`空值行
${
_index
}
`
;
if
(
_colSpan
===
-
1
)
{
_colSpan
=
1
;
}
else
{
_colSpan
+=
1
;
}
_summaryConfig
[
_name
]
=
{
fieldName
:
_name
,
colSpan
:
_colSpan
,
};
}
});
summary
.
forEach
((
item
)
=>
{
switch
(
item
.
totalType
)
{
case
'全部'
:
setHasTotal
(
true
);
break
;
case
'单页'
:
setHasSinglePage
(
true
);
break
;
default
:
break
;
}
if
(
_summaryConfig
[
item
.
fieldName
])
{
_summaryConfig
[
item
.
fieldName
][
item
.
totalType
]
=
item
.
fieldValue
;
}
});
// 增加操作列,总结栏最后一个单元格需要延伸一格
let
_sumArr
=
Object
.
values
(
_summaryConfig
);
if
(
_sumArr
&&
_sumArr
.
length
)
_sumArr
=
_sumArr
.
map
((
item
,
index
)
=>
{
let
_item
=
{
...
item
};
if
(
index
===
_sumArr
.
length
-
1
)
_item
.
colSpan
+=
1
;
return
_item
;
});
setSummaryArray
(
_sumArr
);
};
const
changeDate
=
({
dateFrom
,
dateTo
},
mode
)
=>
{
setTimeFrom
(
dateFrom
);
setTimeTo
(
dateTo
);
setDateMode
(
mode
);
};
const
mapHandleType
=
(
type
)
=>
{
const
_map
=
{
文本
:
handleText
,
数值
:
handleNumber
,
标签
:
handleTag
,
链接
:
handleLink
,
功能
:
handleWidget
,
弹窗
:
handleModal
,
日期
:
handleDateString
,
日期时间
:
handleDateTimeString
,
};
return
_map
[
type
]
||
_map
[
'文本'
];
};
const
returnSortFields
=
(
data
)
=>
{
return
data
.
map
((
item
)
=>
item
.
fieldAlias
);
};
// 处理表格数据,生成表头
const
returnColumn
=
(
config
,
data
)
=>
{
//0. 常规数据
//1. 合并表头;
//2. 四类形态的渲染处理;
//3. 多列表头排序;剔除掉原有图标,需要自己实现排序的按钮
let
_config
=
[...
config
].
filter
((
item
)
=>
item
.
isShow
);
function
dataStruct
(
keyArray
,
dataIndex
,
obj
,
dataObj
)
{
if
(
dataIndex
<
keyArray
.
length
-
1
)
{
if
(
!
obj
[
keyArray
[
dataIndex
]])
{
obj
[
keyArray
[
dataIndex
]]
=
{};
}
let
_dataIndex
=
dataIndex
+
1
;
dataStruct
(
keyArray
,
_dataIndex
,
obj
[
keyArray
[
dataIndex
]],
dataObj
);
}
else
if
(
dataIndex
===
keyArray
.
length
-
1
)
{
obj
[
keyArray
[
dataIndex
]]
=
dataObj
;
}
}
let
_tempObj
=
{};
let
_fieldAliasArray
=
handleDataToGetRowSpanArray
(
_config
,
data
);
// 需要向下合并的字段
_config
.
forEach
((
item
)
=>
{
let
_item
=
{
title
:
item
.
fieldAlias
,
dataIndex
:
item
.
fieldAlias
,
key
:
item
.
fieldAlias
,
ellipsis
:
true
,
onCell
:
(
record
,
rowIndex
)
=>
{
// console.log('Record: ', record); // record是这条记录,index是rowIndex
// 1. 如果该字段是需要向下合并的,则进入判断
let
_obj
=
{};
if
(
_fieldAliasArray
[
item
.
fieldAlias
])
{
_obj
.
rowSpan
=
_fieldAliasArray
[
item
.
fieldAlias
][
rowIndex
];
}
return
_obj
;
},
render
:
(
value
,
record
)
=>
{
// 文本、标签、链接、数值
// @params: item 当前的config数据,提供该字段的各类配置
// value 当前单元格的值
// record 点击单元格的整行数据
let
rest
=
[];
if
(
item
.
type
===
'功能'
)
{
/* rest = {
showComponent: setDetailsComponentVisible,
setDetailsConfig: setDetailConfig,
}; */
rest
=
[
setDetailsComponentVisible
,
setDetailConfig
];
}
else
if
(
item
.
type
===
'弹窗'
)
{
/* rest = {
showModal: setModalVisible,
setExtra: setExtra,
};*/
rest
=
[
setModalVisible
,
setExtra
];
}
return
mapHandleType
(
item
.
type
)(
item
,
value
||
''
,
record
,
...
rest
);
},
};
_item
.
width
=
item
.
columnWidth
||
200
;
// 列宽,不设置时默认给200;
if
(
item
.
fixedColumn
)
_item
.
fixed
=
item
.
fixedColumn
;
// 固定位置
_item
.
align
=
item
.
alignType
||
'left'
;
// 单元格内对齐方式
let
_keyArray
=
(
item
.
fieldGroup
||
item
.
fieldAlias
||
item
.
fieldName
).
split
(
fieldSplitStr
);
// 自定义排序
let
_sortFields
=
handleSortFields
(
sortFields
);
if
(
_sortFields
.
includes
(
item
.
fieldAlias
))
{
_item
.
sorter
=
true
;
}
dataStruct
(
_keyArray
,
0
,
_tempObj
,
_item
);
return
_item
;
});
let
_tempArray
=
[];
function
handleObject2Array
(
obj
,
arr
)
{
Object
.
keys
(
obj
).
forEach
((
key
,
index
)
=>
{
if
(
obj
[
key
].
title
&&
obj
[
key
].
title
===
key
)
{
arr
.
push
(
obj
[
key
]);
}
else
{
arr
.
push
({
title
:
key
,
children
:
[]
});
handleObject2Array
(
obj
[
key
],
arr
[
index
].
children
);
}
});
}
handleObject2Array
(
_tempObj
,
_tempArray
);
// 增加序号
_tempArray
.
unshift
({
title
:
'序号'
,
dataIndex
:
'r'
,
key
:
'r'
,
width
:
60
,
fixed
:
'left'
,
});
// 增加操作列
if
(
permission
.
includes
(
'editBtn'
)
||
permission
.
includes
(
'deleteBtn'
))
{
_tempArray
.
push
({
title
:
'操作'
,
width
:
60
,
fixed
:
'right'
,
render
:
(
text
,
record
)
=>
{
return
(
<
Space
className
=
{
style
.
handleColumnWrapper
}
>
{
permission
.
includes
(
'editBtn'
)
?
(
<
FormOutlined
className
=
{
style
.
editButton
}
onClick
=
{()
=>
{
setEditComponentVisible
(
true
);
setCurrentData
(
record
);
}}
/
>
)
:
(
''
)}
{
/* {
permission.includes('deleteBtn') ?
<DeleteOutlined disabled className={style.deleteButton} onClick={() => {
Modal.confirm({
content: '你确定要删除改数据吗?',
onOK: () => message.error('您无法删除数据!'),
});
}} /> : ''
}*/
}
<
/Space
>
);
},
});
}
// 统计宽度
let
_x
=
_tempArray
.
reduce
((
final
,
curr
)
=>
{
return
(
final
+=
curr
.
width
);
},
0
);
setTableX
(
_x
);
return
_tempArray
;
};
const
changeSortField
=
(
value
,
index
,
key
)
=>
{
let
_selectedSortFields
=
[...
selectedSortFields
];
_selectedSortFields
[
index
][
key
]
=
value
;
setSelectedSortFields
(
_selectedSortFields
);
};
const
addOtherSortFields
=
()
=>
{
let
_selectedSortFields
=
[...
selectedSortFields
];
_selectedSortFields
.
push
({
label
:
'次要排序'
,
value
:
''
,
sort
:
'asc'
,
});
setSelectedSortFields
(
_selectedSortFields
);
};
const
deleteSortField
=
(
index
)
=>
{
let
_selectedSortFields
=
[...
selectedSortFields
];
_selectedSortFields
.
splice
(
index
,
1
);
setSelectedSortFields
(
_selectedSortFields
);
};
const
setTableHeight
=
()
=>
{
if
(
!
tableWrapperRef
.
current
)
return
;
const
clientHeight
=
tableWrapperRef
.
current
?.
clientHeight
||
0
;
const
clientWidth
=
tableWrapperRef
.
current
?.
clientWidth
||
0
;
const
_height
=
controlRef
.
current
?.
clientHeight
;
// 控制条的高度
const
paginationHeight
=
75
;
// 分页部分的高度
const
tableHeaderHeight
=
tableHeaderLevel
*
40
;
// 表头高度
const
summaryHeight
=
summaryArray
.
length
?
40
*
(
Number
(
hasTotal
)
+
Number
(
hasSinglePage
))
:
0
;
// 总结栏的高度
const
_minus
=
clientHeight
-
_height
-
16
-
4
-
tableHeaderHeight
-
paginationHeight
-
summaryHeight
-
10
;
setListHeight
(
clientHeight
-
_height
-
paginationHeight
-
4
-
6
-
16
-
2
);
setTableY
(
_minus
);
};
const
getTableLevel
=
(
config
)
=>
{
let
_level
=
config
.
reduce
((
final
,
curr
)
=>
{
return
(
final
=
curr
.
level
>
final
?
curr
.
level
:
final
);
},
1
)
||
1
;
setTableHeaderLevel
(
_level
);
};
const
saveReportListSortFields
=
(
callback
)
=>
{
reportService
.
saveReportListSortFields
({
reportId
:
currentReportId
,
sortFields
:
selectedSortFields
.
filter
((
item
)
=>
item
.
value
)
.
map
((
item
)
=>
({
fieldAlias
:
item
.
value
,
sortType
:
item
.
sort
,
})),
})
.
then
((
res
)
=>
{
if
(
res
.
code
===
0
)
{
message
.
success
(
'排序保存成功!'
);
callback
();
}
else
{
message
.
error
(
res
.
msg
);
}
});
};
/** @description: 判断是否存在【时间】类型的选择,并返回组件 */
const
handleDate
=
(
obj
)
=>
{
let
_typeObj
=
obj
.
find
((
item
)
=>
item
.
filterRule
===
'日期'
);
setHasDatePicker
(
_typeObj
?
_typeObj
.
fieldAlias
:
''
);
const
_configItems
=
_typeObj
.
configItems
.
split
(
'|'
);
let
_defaultDate
=
_configItems
.
find
((
item
)
=>
item
.
includes
(
'defaultDate='
))
?.
replace
(
'defaultDate='
,
''
)
?.
split
(
','
);
if
(
_defaultDate
&&
_defaultDate
.
length
>
1
)
{
_defaultDate
=
{
dateFrom
:
moment
(
_defaultDate
[
0
]),
dateTo
:
moment
(
_defaultDate
[
1
])
};
}
else
if
(
_defaultDate
&&
_defaultDate
.
length
===
1
)
{
_defaultDate
=
{
dateFrom
:
moment
(
_defaultDate
[
0
]),
dateTo
:
moment
(
_defaultDate
[
0
])
};
}
else
{
_defaultDate
=
{
dateFrom
:
moment
(),
dateTo
:
moment
()
};
}
setDefaultDateConfig
({
defaultDate
:
_defaultDate
?.
dateFrom
,
defaultModel
:
_configItems
.
find
((
item
)
=>
item
.
includes
(
'defaultModel='
))?.
replace
(
'defaultModel='
,
''
)
||
'year'
,
});
};
useEffect
(()
=>
{
getData
(
true
,
pagination
);
},
[]);
useEffect
(()
=>
{
if
(
tableHeaderLevel
)
setTableHeight
();
},
[
tableHeaderLevel
]);
useEffect
(()
=>
{
getData
(
false
,
pagination
);
},
[
timeFrom
,
timeTo
,
filterObject
]);
useEffect
(()
=>
{
function
getRefHeight
()
{
if
(
timer
)
clearTimeout
(
timer
);
timer
=
setTimeout
(()
=>
{
let
_height
=
controlRef
?.
current
.
clientHeight
;
setControlsHeight
(
_height
);
},
100
);
}
window
.
addEventListener
(
'resize'
,
getRefHeight
);
return
()
=>
window
.
removeEventListener
(
'resize'
,
getRefHeight
);
});
return
(
<
div
className
=
{
style
.
reportManage
}
ref
=
{
tableWrapperRef
}
>
{
/* 为方便阅读,分开两部分代码 */
}
{
!
detailsComponentVisible
?
(
<
div
className
=
{
style
.
contentWrapper
}
>
{
state
!==
'scan'
?
(
<
Row
className
=
{
style
.
controlRow
}
ref
=
{
controlRef
}
>
<
Space
style
=
{{
flex
:
1
}}
size
=
{
8
}
wrap
=
{
true
}
>
{
/*时间搜索控件,确保时间搜索控件在第一个,单独匹配*/
}
{
hasDatePicker
&&
defaultDateConfig
.
defaultDate
!==
null
&&
permission
.
includes
(
'filters'
)
?
(
<
DatePickerGroup
showModels
=
{[
'all'
,
'month'
,
'quarter'
,
'year'
,
'custom'
]}
onChange
=
{
changeDate
}
format
=
{
dateFormat
}
defaultModel
=
{
defaultDateConfig
.
defaultModel
}
defaultDate
=
{
defaultDateConfig
.
defaultDate
}
/
>
)
:
(
''
)}
{
controls
&&
controls
.
length
&&
permission
.
includes
(
'filters'
)
?
controls
.
filter
((
control
)
=>
[
'下拉'
,
'多选'
].
includes
(
control
.
filterRule
))
.
map
((
control
)
=>
{
return
(
<
Form
.
Item
label
=
{
control
.
fieldAlias
}
key
=
{
control
.
fieldAlias
}
>
<
ReturnControlComponent
style
=
{{
width
:
240
}}
type
=
{
control
.
filterRule
}
reportName
=
{
reportName
}
fieldAlias
=
{
control
.
fieldAlias
}
configItems
=
{
control
.
configItems
}
onChange
=
{(
e
)
=>
controlSelectChange
(
control
.
fieldAlias
,
e
)}
/
>
<
/Form.Item
>
);
})
:
''
}
{
permission
.
includes
(
'filters'
)
?
(
<
Form
.
Item
label
=
"快速索引"
key
=
{
'快速搜索控件'
}
>
<
ReturnControlComponent
placeholder
=
{
`请输入
${
searchPlaceholder
.
length
?
searchPlaceholder
.
join
(
','
)
:
'关键字'
}
搜索`
}
style
=
{{
width
:
240
}}
type
=
{
'文本'
}
onChange
=
{(
e
)
=>
{
searchInputChange
(
e
);
}}
onSearch
=
{
searchData
}
/
>
<
/Form.Item
>
)
:
(
''
)}
<
/Space
>
{
permission
.
includes
(
'sortBtn'
)
?
(
<
div
style
=
{{
width
:
200
,
textAlign
:
'end'
}}
>
<
Space
size
=
{
8
}
nowrap
=
{
true
}
>
{
sortModalVisible
&&
permission
.
includes
(
'sortBtn'
)
?
(
<
Form
.
Item
>
<
Button
type
=
{
'primary'
}
title
=
{
'自定义排序'
}
icon
=
{
<
SortAscendingOutlined
/>
}
onClick
=
{()
=>
setModalVisible
(
true
)}
>
排序
<
/Button
>
<
/Form.Item
>
)
:
(
''
)}
{
permission
.
includes
(
'exportBtn'
)
?
(
<
Form
.
Item
>
<
Dropdown
.
Button
style
=
{{
float
:
'right'
}}
overlay
=
{
menu
}
>
导出
<
/Dropdown.Button
>
<
/Form.Item
>
)
:
(
''
)}
<
/Space
>
<
/div
>
)
:
(
''
)}
<
/Row
>
)
:
(
''
)}
<
div
className
=
{
style
.
tableContent
}
style
=
{{
height
:
`calc(100% -
${
controlsHeight
||
0
}
px)`
}}
>
{
columns
&&
columns
.
length
?
(
<
BasicTable
rowKey
=
{
'Key'
}
bordered
loading
=
{
tableLoading
}
dataSource
=
{
tableData
}
columns
=
{
columns
}
onChange
=
{(
pagination
,
filters
,
sorter
,
extra
)
=>
{
console
.
log
(
sorter
);
}}
pagination
=
{
permission
.
includes
(
'pagination'
)
?
pagination
:
false
}
// 237是内置图片高度
scroll
=
{{
y
:
tableData
&&
tableData
.
length
?
`calc(100% - 44px)`
:
237
,
x
:
tableX
}}
summary
=
{(
pageData
)
=>
{
if
(
summaryArray
.
length
&&
tableData
&&
tableData
.
length
)
return
(
<
Table
.
Summary
fixed
>
<
Table
.
Summary
.
Row
>
{
hasSinglePage
?
summaryArray
.
map
((
item
,
index
)
=>
{
if
(
item
.
fieldName
===
'空值行0'
)
{
return
(
<
Table
.
Summary
.
Cell
key
=
{
`summary_
${
index
}
`
}
index
=
{
0
}
colSpan
=
{
item
.
colSpan
+
1
}
>
<
span
style
=
{{
display
:
'inline-block'
,
width
:
'100%'
,
textAlign
:
'center'
,
}}
>
小计
<
/span
>
<
/Table.Summary.Cell
>
);
}
else
if
(
item
.
fieldName
.
includes
(
'空值行'
))
{
return
(
<
Table
.
Summary
.
Cell
key
=
{
`summary_
${
index
}
`
}
index
=
{
0
}
colSpan
=
{
item
.
colSpan
}
/
>
);
}
else
{
return
(
<
Table
.
Summary
.
Cell
key
=
{
`summary_
${
index
}
`
}
index
=
{
0
}
>
<
span
style
=
{{
display
:
'inline-block'
,
width
:
'100%'
,
textAlign
:
item
.
alignType
,
}}
>
{
item
.
type
.
replace
(
'求'
,
''
)}:{
' '
}
{
returnHandledNumber
(
item
.
configItems
,
item
[
'单页'
])}
<
/span
>
<
/Table.Summary.Cell
>
);
}
})
:
''
}
<
/Table.Summary.Row
>
<
Table
.
Summary
.
Row
>
{
hasTotal
?
summaryArray
.
map
((
item
)
=>
{
if
(
item
.
fieldName
===
'空值行0'
)
{
return
(
<
Table
.
Summary
.
Cell
index
=
{
0
}
colSpan
=
{
item
.
colSpan
+
1
}
>
<
span
style
=
{{
display
:
'inline-block'
,
width
:
'100%'
,
textAlign
:
'center'
,
}}
>
总计
<
/span
>
<
/Table.Summary.Cell
>
);
}
else
if
(
item
.
fieldName
.
includes
(
'空值行'
))
{
return
<
Table
.
Summary
.
Cell
index
=
{
0
}
colSpan
=
{
item
.
colSpan
}
/>
;
}
else
{
return
(
<
Table
.
Summary
.
Cell
index
=
{
0
}
>
<
span
style
=
{{
display
:
'inline-block'
,
width
:
'100%'
,
textAlign
:
item
.
alignType
,
}}
>
{
item
.
type
.
replace
(
'求'
,
''
)}:{
' '
}
{
returnHandledNumber
(
item
.
configItems
,
item
[
'全部'
])}
<
/span
>
<
/Table.Summary.Cell
>
);
}
})
:
''
}
<
/Table.Summary.Row
>
<
/Table.Summary
>
);
}}
/
>
)
:
(
<
div
className
=
{
style
.
spinWrapper
}
>
<
Spin
/>
<
/div
>
)}
<
/div
>
<
/div
>
)
:
(
''
)}
<
Modal
title
=
{
'自定义排序字段'
}
visible
=
{
modalVisible
}
onCancel
=
{()
=>
setModalVisible
(
false
)}
footer
=
{
<
div
style
=
{{
display
:
'flex'
,
justifyContent
:
'space-between'
}}
>
<
div
>
<
Button
type
=
{
'link'
}
onClick
=
{()
=>
addOtherSortFields
()}
>
增加次要排序
<
/Button
>
<
/div
>
<
div
>
<
Button
onClick
=
{()
=>
setModalVisible
(
false
)}
>
取消
<
/Button
>
<
Button
type
=
{
'primary'
}
onClick
=
{()
=>
{
saveReportListSortFields
(()
=>
getData
(
false
,
pagination
));
setModalVisible
(
false
);
}}
>
确认
<
/Button
>
<
/div
>
<
/div
>
}
>
{
selectedSortFields
.
map
((
item
,
index
)
=>
(
<
Row
key
=
{
'label'
}
className
=
{
style
.
controlRow
}
>
<
Space
size
=
{
8
}
wrap
=
{
true
}
>
<
Form
.
Item
label
=
{
item
.
label
}
>
<
Select
style
=
{{
width
:
240
}}
defaultValue
=
{
item
.
value
}
value
=
{
item
.
value
}
onChange
=
{(
e
)
=>
changeSortField
(
e
,
index
,
'value'
)}
>
<
Option
value
=
""
>
未选择
<
/Option
>
{
allSortFields
.
map
((
item
)
=>
(
<
Option
value
=
{
item
}
>
{
item
}
<
/Option
>
))}
<
/Select
>
<
/Form.Item
>
<
Form
.
Item
>
<
Select
style
=
{{
width
:
120
}}
defaultValue
=
{
item
.
sort
}
value
=
{
item
.
sort
}
onChange
=
{(
e
)
=>
changeSortField
(
e
,
index
,
'sort'
)}
>
<
Option
value
=
{
'asc'
}
>
升序
<
/Option
>
<
Option
value
=
{
'desc'
}
>
降序
<
/Option
>
<
/Select
>
<
/Form.Item
>
{
index
!==
0
?
(
<
Form
.
Item
>
<
MinusCircleOutlined
style
=
{{
color
:
'rgba(0,0,0,.65)'
}}
onClick
=
{()
=>
deleteSortField
(
index
)}
/
>
<
/Form.Item
>
)
:
(
''
)}
<
/Space
>
<
/Row
>
))}
<
/Modal
>
<
Modal
visible
=
{
extraModal
}
onCancel
=
{()
=>
setExtraModal
(
false
)}
destroyOnClose
width
=
{
800
}
>
{
extra
}
<
/Modal
>
{
/* 编辑表单 */
}
<
Modal
title
=
{
'编辑报表信息'
}
visible
=
{
editComponentVisible
}
width
=
{
'80%'
}
footer
=
{
null
}
// visible={true}
onCancel
=
{()
=>
setEditComponentVisible
(
false
)}
>
<
ReportEditForm
reportDetails
=
{
tableStruct
}
reportData
=
{
currentData
}
onCancel
=
{()
=>
{
setEditComponentVisible
(
false
);
getData
(
false
,
pagination
);
}}
reportName
=
{
reportName
}
/
>
<
/Modal
>
<
/div
>
);
};
const
mapStateToProps
=
(
state
)
=>
{
const
allWidgets
=
state
.
getIn
([
'global'
,
'globalConfig'
,
'allWidgets'
]);
let
_flatWidgets
=
[];
const
flatWidgets
=
(
arr
)
=>
{
arr
.
forEach
((
item
)
=>
{
if
(
item
.
widgets
&&
item
.
widgets
.
length
)
{
flatWidgets
(
item
.
widgets
);
}
else
{
_flatWidgets
.
push
(
item
);
}
});
};
flatWidgets
(
allWidgets
);
return
{
allWidgets
:
_flatWidgets
,
};
return
<
ReportsManage
{...
props
}
/>
;
};
export
default
connect
(
mapStateToProps
,
null
)(
BasicReport
)
;
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