import React, {Component} from 'react'
|
import PropTypes from 'prop-types'
|
import { is, fromJS } from 'immutable'
|
import { Button, Modal, notification, message, Progress } from 'antd'
|
import CryptoJS from 'crypto-js'
|
import moment from 'moment'
|
|
import NApi from '@/api'
|
import Utils from '@/utils/utils.js'
|
import Api from '@/api/direct.js'
|
import MKEmitter from '@/utils/events.js'
|
import MkIcon from '@/components/mk-icon'
|
|
// import { mockdata } from './mock'
|
|
import './index.scss'
|
|
class FuncButton extends Component {
|
static propTpyes = {
|
btn: PropTypes.object, // 按钮
|
disabled: PropTypes.any, // 行按钮禁用
|
}
|
|
state = {
|
loading: false,
|
disabled: false,
|
loadingNumber: '',
|
loadingTotal: '',
|
hidden: false,
|
IpList: [],
|
lines: [],
|
selectIp: {},
|
visible: false
|
}
|
|
UNSAFE_componentWillMount () {
|
const { btn, selectedData, BData, disabled } = this.props
|
|
if (btn.controlField) {
|
this.setStatus(btn, selectedData || [], BData, disabled)
|
} else if (disabled) {
|
this.setState({disabled: true})
|
}
|
}
|
|
componentDidMount () {
|
MKEmitter.addListener('triggerBtnId', this.actionTrigger)
|
}
|
|
UNSAFE_componentWillReceiveProps (nextProps) {
|
const { btn } = this.props
|
|
if (btn.controlField) {
|
this.setStatus(btn, nextProps.selectedData || [], nextProps.BData, nextProps.disabled)
|
} else {
|
this.setState({disabled: nextProps.disabled === true})
|
}
|
}
|
|
shouldComponentUpdate (nextProps, nextState) {
|
return !is(fromJS(this.state), fromJS(nextState))
|
}
|
|
componentWillUnmount () {
|
this.setState = () => {
|
return
|
}
|
MKEmitter.removeListener('triggerBtnId', this.actionTrigger)
|
}
|
|
setStatus = (btn, data, BData, disprop) => {
|
let disabled = false
|
let hidden = false
|
|
if (btn.control !== 'parent') {
|
if (data.length > 0) {
|
data.forEach(item => {
|
let s = item[btn.controlField] !== undefined ? item[btn.controlField] + '' : ''
|
if (btn.controlVals.includes(s)) {
|
disabled = true
|
}
|
})
|
} else if (btn.controlVals.includes('')) {
|
disabled = true
|
}
|
} else {
|
if (!BData || !BData.hasOwnProperty(btn.controlField)) {
|
hidden = true
|
} else {
|
let s = BData[btn.controlField] + ''
|
if (btn.controlVals.includes(s)) {
|
hidden = true
|
}
|
}
|
}
|
|
if (disabled && btn.control === 'hidden') {
|
hidden = true
|
}
|
|
if (disprop) {
|
disabled = true
|
}
|
|
this.setState({hidden, disabled})
|
}
|
|
/**
|
* @description 触发按钮操作
|
*/
|
actionTrigger = (triggerId, record, type, lid) => {
|
const { BID, btn, selectedData, setting, LID } = this.props
|
const { loading, disabled } = this.state
|
|
if (loading || disabled) return
|
if (triggerId && btn.uuid !== triggerId) return
|
if (type === 'linkbtn' && !btn.$toolbtn && LID !== lid) return
|
|
let data = record || selectedData || []
|
// let data = fromJS(mockdata.data).toJS()
|
|
if (setting.supModule && !BID) {
|
notification.warning({
|
top: 92,
|
message: setting.supModTip || '需要上级主键值!',
|
duration: 5
|
})
|
} else if (data.length === 0) {
|
// 需要选择行时,校验数据
|
notification.warning({
|
top: 92,
|
message: '请选择行!',
|
duration: 5
|
})
|
} else {
|
this.setState({
|
loading: true,
|
lines: data
|
})
|
this.getIpList()
|
}
|
}
|
|
getIpList = () => {
|
let _scriptSql = `select ID,data_code,data_name,Remark,face_ip,face_uname,face_pwd from bd_data where typecharone='face_device' and deleted=0`
|
|
let _sParam = {
|
func: 'sPC_Get_SelectedList',
|
obj_name: 'data',
|
arr_field: 'ID,data_code,data_name,Remark,face_ip,face_uname,face_pwd'
|
}
|
|
if (window.GLOB.execType === 'x') {
|
_sParam.exec_type = 'x'
|
}
|
|
_sParam.LText = Utils.formatOptions(_scriptSql, _sParam.exec_type)
|
_sParam.timestamp = moment().format('YYYY-MM-DD HH:mm:ss')
|
_sParam.secretkey = Utils.encrypt(window.GLOB.execType === 'x' ? '' : _sParam.LText, _sParam.timestamp)
|
|
NApi.getSystemCacheConfig(_sParam).then(res => {
|
if (res.status) {
|
let IpList = res.data || []
|
|
if (IpList.length === 0) {
|
notification.warning({
|
top: 92,
|
message: '未获取到设备信息!',
|
duration: 5
|
})
|
this.setState({
|
loading: false
|
})
|
} else {
|
this.setState({
|
IpList: IpList.map(item => {
|
if (item.face_ip) {
|
if (!/^http:/.test(item.face_ip)) {
|
item.face_ip = 'http://' + item.face_ip
|
}
|
if (!/:\d{2,4}$/.test(item.face_ip)) {
|
item.face_ip = item.face_ip + ':80'
|
}
|
}
|
return item
|
}),
|
selectIp: {},
|
visible: true
|
})
|
}
|
} else {
|
notification.warning({
|
top: 92,
|
message: res.message,
|
duration: 5
|
})
|
}
|
})
|
}
|
|
loginDevice = () => {
|
const { btn } = this.props
|
const { lines, selectIp } = this.state
|
|
// 上报接口设置:工程模式-场景模式-开放接口设置-数据上报设置-数据上报服务器地址(开启服务器二次鉴权)
|
// let ip = 'http://localhost:3001'
|
let ip = selectIp.face_ip
|
|
Api.w4kLogin(ip, selectIp.face_uname, selectIp.face_pwd).then(result => {
|
if (result.errors) {
|
this.execPreError(result)
|
return
|
}
|
|
document.cookie = 'sessionID=' + result.session_id
|
|
Api.w4kQueryUsers(ip).then(res => {
|
if (res.errors) {
|
this.execPreError(res)
|
return
|
}
|
|
let persons = {}
|
res.data.forEach(item => {
|
persons[item.id] = true
|
})
|
|
let data = lines.map(cell => {
|
let item = {}
|
Object.keys(cell).forEach(key => {
|
item[key.toLowerCase()] = cell[key]
|
})
|
|
return {
|
deleted: persons[item.id] || false,
|
recognition_type: item.recognition_type || 'staff',
|
is_admin: item.is_admin === 'true',
|
person_name: item.person_name || '',
|
id: item.id || '',
|
card_number: item.card_number || '',
|
person_code: item.person_code || '',
|
group_list: item.group_list ? item.group_list.split(',') : [1],
|
password: item.password || '',
|
id_number: item.id_number || '',
|
face_list: [{
|
idx: item.face_idx || 0,
|
data: item.face_data ? item.face_data.replace(/^data:image\/(jpeg|png|jpg|gif);base64,/, '') : '',
|
}]
|
}
|
})
|
|
if (data.length > 1 && btn.progress === 'progressbar') {
|
this.setState({
|
loadingTotal: data.length
|
})
|
}
|
|
this.addUser(ip, data, result.session_id)
|
})
|
}, err => {
|
this.execPreError(err)
|
})
|
}
|
|
addUser = (ip, datas, sessionId) => {
|
let data = datas.shift()
|
|
this.setState({
|
loadingNumber: datas.length
|
})
|
|
let error = ''
|
if (!data.person_name) {
|
error = '人员名称不可为空'
|
} else if (!data.id) {
|
error = '人员id不可为空'
|
} else if (!data.face_list[0].data) {
|
error = '人员图片不可为空'
|
} else if (data.password) {
|
if (/^\d{6}$/.test(data.password)) {
|
let key = CryptoJS.enc.Utf8.parse(sessionId)
|
let srcs = CryptoJS.enc.Utf8.parse(data.password)
|
let encrypted = CryptoJS.AES.encrypt(srcs, key, {mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7})
|
|
data.password = CryptoJS.enc.Base64.stringify(encrypted.ciphertext)
|
} else {
|
error = '密码使用6位数字'
|
}
|
}
|
|
if (error) {
|
this.execError({ErrCode: 'E', message: error})
|
return
|
}
|
|
if (data.id_number) {
|
let key = CryptoJS.enc.Utf8.parse(sessionId)
|
let srcs = CryptoJS.enc.Utf8.parse(data.id_number)
|
let encrypted = CryptoJS.AES.encrypt(srcs, key, {mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7})
|
|
data.id_number = CryptoJS.enc.Base64.stringify(encrypted.ciphertext)
|
}
|
|
Api.w4kAddUsers(ip, data).then(res => {
|
if (res.errors) {
|
this.execPreError(res, data)
|
return
|
}
|
if (datas.length > 0) {
|
this.addUser(ip, datas, sessionId)
|
} else {
|
this.execSuccess({ErrCode: 'S', message: '执行成功。'})
|
}
|
}, (err) => {
|
this.execPreError(err, data)
|
})
|
}
|
|
/**
|
* @description 操作成功后处理
|
* 1、excel导出,成功后取消导出按钮加载中状态
|
* 2、状态码为 S 时,显示成功信息后系统默认信息
|
* 3、状态码为 -1 时,不显示任何信息
|
* 4、模态框执行成功后是否关闭
|
* 5、通知主列表刷新
|
*/
|
execSuccess = (res = {}) => {
|
const { btn } = this.props
|
|
if (res.ErrCode === 'S' || !res.ErrCode) { // 执行成功
|
notification.success({
|
top: 92,
|
message: res.message || '执行成功',
|
duration: btn.verify && btn.verify.stime ? btn.verify.stime : 2
|
})
|
} else if (res && res.ErrCode === 'Y') { // 执行成功
|
Modal.success({
|
title: res.message || '执行成功'
|
})
|
} else if (res && res.ErrCode === '-1') { // 完成后不提示
|
|
}
|
|
this.setState({
|
loading: false,
|
loadingNumber: '',
|
loadingTotal: ''
|
})
|
|
// if (btn.execSuccess !== 'never') {
|
// MKEmitter.emit('refreshByButtonResult', btn.$menuId, btn.execSuccess, btn)
|
// }
|
}
|
|
execPreError = (err, data) => {
|
if (err.data && err.data.errors && err.data.errors[0]) {
|
let error = err.data.errors[0]
|
let message = error.detail
|
if (error.source.pointer === '/api/persons/item' && error.error_code) {
|
let list = [
|
{val: 1, msg: '图片格式错误'},
|
{val: 2, msg: '图片大小超出限制'},
|
{val: 3, msg: '图片分辨率超出限制'},
|
{val: 16, msg: '人脸无特征值'},
|
{val: 17, msg: '入库无图片'},
|
{val: 18, msg: '未检测到人脸'},
|
{val: 19, msg: '检测到多个人脸'},
|
{val: 20, msg: '人脸太小'},
|
{val: 21, msg: '图片太亮'},
|
{val: 22, msg: '图片太暗'},
|
{val: 23, msg: '人脸太模糊'},
|
{val: 24, msg: '人脸方向错误'},
|
{val: 32, msg: '数据库满'},
|
{val: 33, msg: '人脸图片重复'},
|
{val: 34, msg: '人员编号重复'},
|
{val: 35, msg: '卡号重复'},
|
{val: 48, msg: '人员名称重复'},
|
{val: -1, msg: '未知错误'},
|
{val: -2141716476, msg: '系统参数错误,有可能是人员组不存在。'},
|
]
|
|
list.forEach(item => {
|
if (item.val === error.error_code) {
|
message = (data ? data.person_name + ' - ' : '') + item.msg
|
}
|
})
|
}
|
|
this.execError({
|
ErrCode: 'E',
|
message: message
|
})
|
} else {
|
this.execError({
|
ErrCode: 'E',
|
message: '请检查设备状态!'
|
})
|
}
|
}
|
|
/**
|
* @description 操作失败后处理
|
*/
|
execError = (res) => {
|
const { btn } = this.props
|
|
if (res.ErrCode === 'E') {
|
Modal.error({
|
title: res.message || '执行失败!',
|
})
|
} else if (res.ErrCode === 'N') {
|
notification.error({
|
top: 92,
|
message: res.message || '执行失败!',
|
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 || '执行失败!',
|
duration: btn.verify && btn.verify.ftime ? btn.verify.ftime : 10
|
})
|
} else if (res.ErrCode === 'NM') {
|
message.error(res.message || '执行失败!')
|
}
|
|
this.setState({
|
loading: false,
|
loadingNumber: '',
|
loadingTotal: ''
|
})
|
|
// if (btn.execError !== 'never') {
|
// MKEmitter.emit('refreshByButtonResult', btn.$menuId, btn.execError, btn)
|
// }
|
}
|
|
handleOk = () => {
|
const { selectIp } = this.state
|
|
if (!selectIp.ID) {
|
notification.warning({
|
top: 92,
|
message: '请选择面板机!',
|
duration: 5
|
})
|
return
|
} else if (!selectIp.face_ip) {
|
notification.warning({
|
top: 92,
|
message: '面板机IP缺失!',
|
duration: 5
|
})
|
return
|
} else if (!selectIp.face_uname) {
|
notification.warning({
|
top: 92,
|
message: '面板机用户名缺失!',
|
duration: 5
|
})
|
return
|
} else if (!selectIp.face_pwd) {
|
notification.warning({
|
top: 92,
|
message: '面板机密码缺失!',
|
duration: 5
|
})
|
return
|
}
|
|
this.setState({
|
visible: false
|
})
|
|
this.loginDevice()
|
}
|
|
getModels = () => {
|
const { IpList, visible, selectIp } = this.state
|
|
return (
|
<Modal
|
title="请选择面板机"
|
maskClosable={false}
|
getContainer={document.body}
|
wrapClassName='ip-list-modal'
|
visible={visible}
|
width={700}
|
onOk={this.handleOk}
|
onCancel={() => this.setState({visible: false, loading: false})}
|
destroyOnClose
|
>
|
{IpList.map(item => {
|
return <div className={'ip-item' + (selectIp.ID === item.ID ? ' active' : '')} key={item.ID} onClick={() => {this.setState({selectIp: item})}}>
|
<div className="ip">IP:{item.face_ip}</div>
|
<div className="user">用户:{item.face_uname}</div>
|
<div className="remark">备注:{item.Remark}</div>
|
</div>
|
})}
|
</Modal>
|
)
|
}
|
|
render() {
|
const { btn } = this.props
|
const { loading, disabled, hidden, loadingNumber, loadingTotal } = this.state
|
|
if (hidden) return null
|
|
let label = ''
|
|
if (btn.show === 'link') {
|
label = <span>{btn.label}{btn.icon ? <MkIcon style={{marginLeft: '8px'}} type={btn.icon} /> : ''}</span>
|
} else if (btn.show === 'icon') {
|
label = !loading ? <MkIcon type={btn.icon} /> : null
|
} else if (btn.$toolbtn) {
|
label = <span>{!loading && btn.icon ? <MkIcon style={{marginRight: '8px'}} type={btn.icon} /> : ''}{loadingNumber && !loadingTotal ? `(${loadingNumber})` : ''}{btn.label}</span>
|
} else {
|
label = <span>{!loading && btn.icon ? <MkIcon style={{marginRight: '8px'}} type={btn.icon} /> : ''}{btn.label}</span>
|
}
|
|
return (
|
<>
|
<Button
|
type="link"
|
title={disabled ? (btn.reason || '') : (btn.show === 'icon' ? btn.label : '')}
|
loading={loading}
|
disabled={disabled}
|
style={btn.style}
|
className={btn.hover || ''}
|
onClick={(e) => {e.stopPropagation(); this.actionTrigger()}}
|
>{label}</Button>
|
{this.getModels()}
|
{loadingTotal ? <Progress className="mk-button-progress" percent={(loadingTotal - loadingNumber) / loadingTotal * 100} size="small" showInfo={false} /> : null}
|
</>
|
)
|
}
|
}
|
|
export default FuncButton
|