import React, {Component} from 'react'
|
import PropTypes from 'prop-types'
|
import moment from 'moment'
|
import {connect} from 'react-redux'
|
import { is, fromJS } from 'immutable'
|
import { Button, Modal, notification, message } from 'antd'
|
import * as XLSX from 'xlsx'
|
|
import Utils from '@/utils/utils.js'
|
import options from '@/store/options.js'
|
import Api from '@/api'
|
import zhCN from '@/locales/zh-CN/main.js'
|
import enUS from '@/locales/en-US/main.js'
|
import './index.scss'
|
|
class ExcelOutButton extends Component {
|
static propTpyes = {
|
BID: PropTypes.string, // 主表ID
|
show: PropTypes.any, // 显示样式
|
Tab: PropTypes.any, // 如果当前元素为标签时,tab为标签信息
|
btn: PropTypes.object, // 按钮
|
setting: PropTypes.any, // 页面通用设置
|
updateStatus: PropTypes.func, // 按钮状态更新
|
getexceloutparam: PropTypes.func, // 获取表格中参数
|
triggerBtn: PropTypes.any,
|
}
|
|
state = {
|
dict: sessionStorage.getItem('lang') !== 'en-US' ? zhCN : enUS,
|
excelName: '',
|
search: '', // 搜索条件
|
loading: false
|
}
|
|
/**
|
* @description 外部触发按钮点击
|
*/
|
UNSAFE_componentWillReceiveProps(nextProps) {
|
if (nextProps.triggerBtn && !is(fromJS(this.props.triggerBtn), fromJS(nextProps.triggerBtn)) && nextProps.triggerBtn.button.uuid === this.props.btn.uuid) {
|
this.actionTrigger()
|
}
|
}
|
|
shouldComponentUpdate (nextProps, nextState) {
|
return !is(fromJS(this.props), fromJS(nextProps)) || !is(fromJS(this.state), fromJS(nextState))
|
}
|
|
/**
|
* @description 按钮状态改变
|
*/
|
updateStatus = (type, name) => {
|
if (type === 'start') {
|
this.setState({
|
loading: true,
|
excelName: name
|
})
|
this.props.updateStatus('start')
|
} else if (type === 'over') {
|
this.setState({
|
loading: false
|
})
|
this.props.updateStatus('over')
|
}
|
}
|
|
/**
|
* @description 触发按钮操作
|
*/
|
actionTrigger = () => {
|
const { setting, Tab, BID, btn } = this.props
|
|
if (Tab && Tab.supMenu && !BID) {
|
notification.warning({
|
top: 92,
|
message: '需要上级主键值!',
|
duration: 5
|
})
|
return
|
}
|
|
if (
|
btn.intertype === 'inner' && !btn.innerFunc &&
|
((setting.interType === 'inner' && setting.innerFunc) || setting.interType === 'outer')
|
) {
|
notification.warning({
|
top: 92,
|
message: '导出按钮配置错误!',
|
duration: 5
|
})
|
return
|
} else if (!btn.verify || !btn.verify.columns || btn.verify.columns.length === 0) {
|
notification.warning({
|
top: 92,
|
message: '请设置导出列!',
|
duration: 5
|
})
|
return
|
}
|
|
this.triggerExcelout()
|
}
|
|
/**
|
* @description Excel 导出
|
*/
|
triggerExcelout = () => {
|
const { btn } = this.props
|
let viewParam = this.props.getexceloutparam()
|
let name = `${viewParam.menuName}${moment().format('YYYYMMDDHHmmss')}.xlsx`
|
let pageSize = 1000
|
|
if (btn.search === 'true' && viewParam.search && viewParam.search.length > 0) {
|
let valid = false
|
viewParam.search.forEach(item => {
|
if (Array.isArray(item.value) && item.value.length > 0) {
|
valid = true
|
} else if (item.value || item.value === 0) {
|
valid = true
|
}
|
})
|
|
if (!valid) {
|
notification.warning({
|
top: 92,
|
message: '搜索条件不可为空!',
|
duration: 5
|
})
|
return
|
}
|
}
|
|
if (btn.intertype === 'inner' && !btn.innerFunc && !viewParam.arr_field) { // 使用系统函数
|
notification.warning({
|
top: 92,
|
message: '未设置显示列!',
|
duration: 5
|
})
|
return
|
} else if (btn.intertype === 'inner' && !btn.innerFunc && btn.verify && btn.verify.enable === 'true') {
|
this.setState({search: fromJS(viewParam.search).toJS()})
|
}
|
|
this.updateStatus('start', name)
|
|
if (btn.pagination !== 'true') {
|
if (btn.intertype === 'inner' && !btn.innerFunc) { // 使用系统函数
|
let param = this.getExcelDefaultParam(viewParam.arr_field, viewParam.orderBy, viewParam.search)
|
|
Api.genericInterface(param).then(result => {
|
if (result.status) {
|
this.exportExcel(result.data)
|
} else {
|
this.execError(result)
|
}
|
}, () => {
|
this.execError({})
|
})
|
} else if (btn.intertype === 'inner' && btn.innerFunc) { // 使用内部函数
|
let param = this.getExcelCustomParam(viewParam.orderBy, viewParam.search)
|
param.func = btn.innerFunc
|
|
Api.genericInterface(param).then(result => {
|
if (result.status) {
|
this.exportExcel(result.data)
|
} else {
|
this.execError(result)
|
}
|
}, () => {
|
this.execError({})
|
})
|
} else if (btn.intertype === 'outer' && !btn.innerFunc) { // 使用外部函数
|
let param = this.getExcelCustomParam(viewParam.orderBy, viewParam.search)
|
|
if (this.props.menuType === 'HS') {
|
if (btn.sysInterface === 'true' && options.cloudServiceApi) {
|
param.rduri = options.cloudServiceApi
|
} else if (btn.sysInterface !== 'true') {
|
param.rduri = btn.interface
|
}
|
} else {
|
if (btn.sysInterface === 'true' && window.GLOB.mainSystemApi) {
|
param.rduri = window.GLOB.mainSystemApi
|
} else if (btn.sysInterface !== 'true') {
|
param.rduri = btn.interface
|
}
|
}
|
|
if (btn.outerFunc) {
|
param.func = btn.outerFunc
|
}
|
|
Api.genericInterface(param).then(result => {
|
if (result.status) {
|
this.exportExcel(result.data)
|
} else {
|
this.execError(result)
|
}
|
}, () => {
|
this.execError({})
|
})
|
} else if (btn.intertype === 'outer' && btn.innerFunc) {
|
let param = this.getExcelCustomParam(viewParam.orderBy, viewParam.search)
|
param.func = btn.innerFunc
|
|
Api.genericInterface(param).then(res => {
|
if (res.status) {
|
delete res.ErrCode
|
delete res.ErrMesg
|
delete res.message
|
delete res.status
|
|
if (this.props.menuType === 'HS') {
|
if (btn.sysInterface === 'true' && options.cloudServiceApi) {
|
res.rduri = options.cloudServiceApi
|
} else if (btn.sysInterface !== 'true') {
|
res.rduri = btn.interface
|
}
|
} else {
|
if (btn.sysInterface === 'true' && window.GLOB.mainSystemApi) {
|
res.rduri = window.GLOB.mainSystemApi
|
} else if (btn.sysInterface !== 'true') {
|
res.rduri = btn.interface
|
}
|
}
|
|
if (btn.outerFunc) {
|
res.func = btn.outerFunc
|
}
|
|
Api.genericInterface(res).then(result => {
|
if (result.status) {
|
this.exportExcel(result.data)
|
} else {
|
this.execError(result)
|
}
|
})
|
} else {
|
this.execError(res)
|
}
|
}, () => {
|
this.execError({})
|
})
|
} else {
|
notification.warning({
|
top: 92,
|
message: '导出按钮设置错误!',
|
duration: 5
|
})
|
this.updateStatus('over')
|
}
|
} else if (btn.intertype === 'outer' && btn.innerFunc) { // 分页,且两步请求
|
this.getExcelOutDoubleData(viewParam, 1, pageSize, [])
|
} else { // 分页,一步请求
|
this.getExcelOutData(viewParam, 1, pageSize, [])
|
}
|
}
|
|
/**
|
* @description 两步分页请求
|
*/
|
getExcelOutDoubleData = (viewParam, pageIndex, pageSize, data) => {
|
const { btn } = this.props
|
let param = this.getExcelCustomParam(viewParam.orderBy, viewParam.search, true, pageIndex, pageSize)
|
param.func = btn.innerFunc
|
|
Api.genericInterface(param).then(res => {
|
if (res.status) {
|
delete res.ErrCode
|
delete res.ErrMesg
|
delete res.message
|
delete res.status
|
|
if (this.props.menuType === 'HS') {
|
if (btn.sysInterface === 'true' && options.cloudServiceApi) {
|
res.rduri = options.cloudServiceApi
|
} else if (btn.sysInterface !== 'true') {
|
res.rduri = btn.interface
|
}
|
} else {
|
if (btn.sysInterface === 'true' && window.GLOB.mainSystemApi) {
|
res.rduri = window.GLOB.mainSystemApi
|
} else if (btn.sysInterface !== 'true') {
|
res.rduri = btn.interface
|
}
|
}
|
|
if (btn.outerFunc) {
|
res.func = btn.outerFunc
|
}
|
|
Api.genericInterface(res).then(result => {
|
if (result.status) {
|
if (!result.data) {
|
this.execError({ErrCode: 'N', message: '未获取到数据信息!'})
|
} else if (result.data.length >= pageSize) {
|
data = data.concat(result.data)
|
pageIndex++
|
this.getExcelOutDoubleData(viewParam, pageIndex, pageSize, data)
|
} else {
|
data = data.concat(result.data)
|
this.exportExcel(data)
|
}
|
} else {
|
this.execError(result)
|
}
|
}, () => {
|
this.execError({})
|
})
|
} else {
|
this.execError(res)
|
}
|
}, () => {
|
this.execError({})
|
})
|
}
|
|
/**
|
* @description 一步分页请求
|
*/
|
getExcelOutData = (viewParam, pageIndex, pageSize, data) => {
|
const { btn } = this.props
|
let param = null
|
if (btn.intertype === 'inner' && !btn.innerFunc) { // 使用系统函数
|
if (!viewParam.arr_field) {
|
this.execError({ErrCode: 'N', message: '未设置显示列!'})
|
return
|
}
|
|
param = this.getExcelDefaultParam(viewParam.arr_field, viewParam.orderBy, viewParam.search, true, pageIndex, pageSize)
|
} else if (btn.intertype === 'inner' && btn.innerFunc) { // 使用内部函数
|
param = this.getExcelCustomParam(viewParam.orderBy, viewParam.search, true, pageIndex, pageSize)
|
param.func = btn.innerFunc
|
|
} else if (btn.intertype === 'outer' && !btn.innerFunc) { // 使用外部函数
|
param = this.getExcelCustomParam(viewParam.orderBy, viewParam.search, true, pageIndex, pageSize)
|
|
if (this.props.menuType === 'HS') {
|
if (btn.sysInterface === 'true' && options.cloudServiceApi) {
|
param.rduri = options.cloudServiceApi
|
} else if (btn.sysInterface !== 'true') {
|
param.rduri = btn.interface
|
}
|
} else {
|
if (btn.sysInterface === 'true' && window.GLOB.mainSystemApi) {
|
param.rduri = window.GLOB.mainSystemApi
|
} else if (btn.sysInterface !== 'true') {
|
param.rduri = btn.interface
|
}
|
}
|
|
if (btn.outerFunc) {
|
param.func = btn.outerFunc
|
}
|
}
|
|
Api.genericInterface(param).then(result => {
|
if (result.status) {
|
if (!result.data) {
|
this.execError({ErrCode: 'N', message: '未获取到数据信息!'})
|
} else if (result.data.length >= pageSize) {
|
data = data.concat(result.data)
|
pageIndex++
|
this.getExcelOutData(viewParam, pageIndex, pageSize, data)
|
} else {
|
data = data.concat(result.data)
|
this.exportExcel(data)
|
}
|
} else {
|
this.execError(result)
|
}
|
}, () => {
|
this.execError({})
|
})
|
}
|
|
/**
|
* @description Excel 生成
|
*/
|
exportExcel = (data) => {
|
const { btn } = this.props
|
|
try {
|
let _header = []
|
let _topRow = {}
|
let colwidth = []
|
|
btn.verify.columns.forEach(col => {
|
if (_topRow[col.Column]) return
|
|
_header.push(col.Column)
|
_topRow[col.Column] = col.Text
|
|
colwidth.push({width: col.Width || 20})
|
})
|
|
let table = []
|
|
table.push(_topRow)
|
|
data && data.forEach(item => {
|
let _row = {}
|
_header.forEach(field => {
|
_row[field] = item[field]
|
})
|
|
table.push(_row)
|
})
|
|
const ws = XLSX.utils.json_to_sheet(table, {header: _header, skipHeader: true})
|
|
ws['!cols'] = colwidth
|
|
const wb = XLSX.utils.book_new()
|
XLSX.utils.book_append_sheet(wb, ws, 'Sheet1')
|
|
XLSX.writeFile(wb, this.state.excelName)
|
|
if (btn.verify && btn.verify.enable === 'true' && btn.verify.script) {
|
this.execCustomScript()
|
} else {
|
this.execSuccess({ErrCode: 'S', ErrMesg: '导出成功!'})
|
}
|
} catch {
|
this.execError({ErrCode: 'N', message: 'Excel生成失败!'})
|
}
|
}
|
|
/**
|
* @description 执行自定义脚本
|
*/
|
execCustomScript = () => {
|
const { btn } = this.props
|
const { search } = this.state
|
let script = btn.verify.script
|
|
if (this.props.dataManager) { // 数据权限
|
script = script.replace(/\$@/ig, '/*')
|
script = script.replace(/@\$/ig, '*/')
|
} else {
|
script = script.replace(/@\$|\$@/ig, '')
|
}
|
|
let allSearch = Utils.getAllSearchOptions(search)
|
let regoptions = allSearch.map(item => {
|
return {
|
reg: new RegExp('@' + item.key + '@', 'ig'),
|
value: `'${item.value}'`
|
}
|
})
|
|
regoptions.forEach(item => {
|
script = script.replace(item.reg, item.value)
|
})
|
|
let param = {
|
func: 'sPC_TableData_InUpDe'
|
}
|
|
if (this.props.BID) {
|
param.BID = this.props.BID
|
}
|
|
let { LText, LText1, LText2 } = Utils.sPCInUpDeFormatOptions(script)
|
|
param.LText2 = LText2
|
param.LText1 = LText1
|
param.LText = LText
|
|
param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
|
param.secretkey = Utils.encrypt(param.LText, param.timestamp)
|
|
if (this.props.menuType === 'HS') { // 函数 sPC_TableData_InUpDe 云端验证
|
param.open_key = Utils.encrypt(param.secretkey, param.timestamp, true)
|
}
|
|
Api.genericInterface(param).then((res) => {
|
if (res.status) {
|
this.execSuccess({ErrCode: 'S', ErrMesg: '导出成功!'})
|
} else {
|
this.execError(res)
|
}
|
}, () => {
|
this.updateStatus('over')
|
})
|
}
|
|
/**
|
* @description 获取用户自定义存储过程传参
|
*/
|
getExcelCustomParam = (orderBy, search, pagination = false, pageIndex = 1, pageSize = 100) => {
|
let _search = Utils.formatCustomMainSearch(search)
|
|
let param = {
|
OrderCol: orderBy,
|
..._search
|
}
|
|
// 数据管理权限
|
if (this.props.dataManager) {
|
param.dataM = 'Y'
|
}
|
|
if (this.props.BID) {
|
param.BID = this.props.BID
|
}
|
|
if (pagination) {
|
param.PageIndex = pageIndex
|
param.PageSize = pageSize
|
}
|
|
return param
|
}
|
|
/**
|
* @description 获取默认存储过程请求参数
|
*/
|
getExcelDefaultParam = (arr_field, orderBy, search, pagination = false, pageIndex = 1, pageSize = 100) => {
|
const { setting } = this.props
|
|
let _search = Utils.joinMainSearchkey(search)
|
|
_search = _search ? 'where ' + _search : ''
|
|
let param = {
|
func: 'sPC_Get_TableData',
|
obj_name: 'data',
|
arr_field: arr_field,
|
custom_script: setting.customScript || '',
|
default_sql: setting.default || 'true'
|
}
|
|
// 数据管理权限
|
if (this.props.dataManager) {
|
param.dataM = 'Y'
|
}
|
|
if (this.props.BID) {
|
param.BID = this.props.BID
|
}
|
|
let _dataresource = setting.dataresource
|
|
if (/\s/.test(_dataresource)) {
|
_dataresource = '(' + _dataresource + ') tb'
|
}
|
|
if (this.props.dataManager) { // 数据权限
|
_dataresource = _dataresource.replace(/\$@/ig, '/*')
|
_dataresource = _dataresource.replace(/@\$/ig, '*/')
|
param.custom_script = param.custom_script.replace(/\$@/ig, '/*')
|
param.custom_script = param.custom_script.replace(/@\$/ig, '*/')
|
} else {
|
_dataresource = _dataresource.replace(/@\$|\$@/ig, '')
|
param.custom_script = param.custom_script.replace(/@\$|\$@/ig, '')
|
}
|
|
let regoptions = null
|
if (setting.queryType === 'statistics' || param.custom_script) {
|
let allSearch = Utils.getAllSearchOptions(search)
|
|
regoptions = allSearch.map(item => {
|
return {
|
reg: new RegExp('@' + item.key + '@', 'ig'),
|
value: `'${item.value}'`
|
}
|
})
|
|
regoptions.push({
|
reg: new RegExp('@orderBy@', 'ig'),
|
value: orderBy
|
}, {
|
reg: new RegExp('@pageSize@', 'ig'),
|
value: pageSize
|
}, {
|
reg: new RegExp('@pageIndex@', 'ig'),
|
value: pageIndex
|
})
|
}
|
|
if (setting.queryType === 'statistics') { // 统计数据源,内容替换
|
regoptions.forEach(item => {
|
_dataresource = _dataresource.replace(item.reg, item.value)
|
})
|
_search = ''
|
}
|
|
let LText = ''
|
|
if (setting.default !== 'false' && !pagination) {
|
LText = ` select ${arr_field} from (select ${arr_field} ,ROW_NUMBER() over(order by ${orderBy}) as rows from ${_dataresource} ${_search}) tmptable order by tmptable.rows `
|
} else if (setting.default !== 'false') {
|
LText = ` select top ${pageSize} ${arr_field} from (select ${arr_field} ,ROW_NUMBER() over(order by ${orderBy}) as rows from ${_dataresource} ${_search}) tmptable where rows > ${pageSize * (pageIndex - 1)} order by tmptable.rows `
|
}
|
|
if (param.custom_script) {
|
regoptions.forEach(item => {
|
param.custom_script = param.custom_script.replace(item.reg, item.value)
|
})
|
|
if (LText) {
|
LText += `
|
aaa:
|
if @ErrorCode!=''
|
insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg,@UserID@
|
`
|
} else {
|
param.custom_script += `
|
aaa:
|
if @ErrorCode!=''
|
insert into tmp_err_retmsg (ID, ErrorCode, retmsg, CreateUserID) select @time_id@,@ErrorCode, @retmsg,@UserID@
|
`
|
}
|
|
param.custom_script = Utils.formatOptions(param.custom_script)
|
}
|
|
param.LText = Utils.formatOptions(LText)
|
param.timestamp = moment().format('YYYY-MM-DD HH:mm:ss') + '.000'
|
param.secretkey = Utils.encrypt(param.LText, param.timestamp)
|
param.DateCount = ''
|
|
if (this.props.menuType === 'HS') { // 云端数据验证
|
param.open_key = Utils.encrypt(param.secretkey, param.timestamp, true)
|
}
|
|
return param
|
}
|
|
/**
|
* @description 操作成功后处理
|
* 1、excel导出,成功后取消导出按钮加载中状态
|
* 2、状态码为 S 时,显示成功信息后系统默认信息
|
* 3、状态码为 -1 时,不显示任何信息
|
* 4、模态框执行成功后是否关闭
|
* 5、通知主列表刷新
|
*/
|
execSuccess = (res) => {
|
const { btn } = this.props
|
|
if (res && res.ErrCode === 'S') { // 执行成功
|
notification.success({
|
top: 92,
|
message: res.ErrMesg || this.state.dict['main.action.confirm.success'],
|
duration: btn.verify && btn.verify.stime ? btn.verify.stime : 2
|
})
|
} else if (res && res.ErrCode === 'Y') { // 执行成功
|
Modal.success({
|
title: res.ErrMesg || this.state.dict['main.action.confirm.success']
|
})
|
} else if (res && res.ErrCode === '-1') { // 完成后不提示
|
|
}
|
|
this.setState({
|
loading: false
|
})
|
|
this.props.updateStatus('refresh', btn.execSuccess)
|
}
|
|
/**
|
* @description 操作失败后处理
|
* 1、状态码为 E、N、F、NM 时,显示相应提示信息
|
* 2、excel导出,失败后取消导出按钮加载中状态
|
* 3、通知主列表刷新
|
*/
|
execError = (res) => {
|
const { btn } = this.props
|
|
if (res.ErrCode === 'E') {
|
Modal.error({
|
title: res.message || res.ErrMesg,
|
})
|
} else if (res.ErrCode === 'N') {
|
notification.error({
|
top: 92,
|
message: res.message || res.ErrMesg,
|
duration: btn.verify && btn.verify.ntime ? btn.verify.ntime : 10
|
})
|
} else if (res.ErrCode === 'F') {
|
notification.error({
|
className: 'notification-custom-error',
|
top: 92,
|
message: res.message || res.ErrMesg,
|
duration: btn.verify && btn.verify.ftime ? btn.verify.ftime : 10
|
})
|
} else if (res.ErrCode === 'NM') {
|
message.error(res.message || res.ErrMesg)
|
}
|
|
this.setState({
|
loading: false
|
})
|
|
this.props.updateStatus('refresh', btn.execError)
|
}
|
|
render() {
|
const { btn, show } = this.props
|
const { loading } = this.state
|
|
return (
|
<div className="mk-btn-wrap">
|
{!show ? <Button
|
className={'mk-btn mk-' + btn.class}
|
icon={btn.icon}
|
onClick={() => {this.actionTrigger()}}
|
loading={loading}
|
>{btn.label}</Button> : null}
|
{show === 'icon' ? <Button
|
className="export-icon"
|
icon="download"
|
onClick={() => {this.actionTrigger()}}
|
loading={loading}
|
title={btn.label}
|
></Button> : null}
|
</div>
|
)
|
}
|
}
|
|
const mapStateToProps = (state) => {
|
return {
|
menuType: state.editLevel,
|
dataManager: state.dataManager
|
}
|
}
|
|
const mapDispatchToProps = () => {
|
return {}
|
}
|
|
export default connect(mapStateToProps, mapDispatchToProps)(ExcelOutButton)
|