import React, { useEffect, useState, useRef, useMemo } from 'react';
import { UnorderedListOutlined, PlusOutlined } from '@ant-design/icons';
import { Button, Modal, message, Alert, Avatar, Spin, Select, Menu, Dropdown } from 'antd';
import { connect } from 'dva';
import styles from './Index.less';
import LuckySheet from './LuckySheet';
import router from 'umi/router';
import AuditModal from './AuditModal';
// import CommentDrawer from './CommentDrawer';
import RightDrawer from './RightDrawer';
import CommitModal from './CommitModal';
import CompareModal from './CompareModal';
import ExportModal from './ExportModal';
import FlowModal from './FlowModal';
import HistoryModal from './HistoryModal';
import TimeNode from './TimeNode';
import FilesModal from './FilesModal';
import VersionModal from './VersionModal';
import CommitAuditModal from './CommitAuditModal';
import CommentContent from '@/components/CommentContent';
import MergeModal from './MergeModal';
import { GetTokenFromUrl, getToken } from '@/utils/utils';
import { queryDetail } from '@/services/boom';
const LocalData = localStorage.luckysheet;
const { Option } = Select;
function Detail(props) {
const {
// flow,
dispatch,
comment,
history,
loading,
currentUser,
fileList,
roleList,
template,
versionList,
auditList,
flowDetail,
match: { params },
} = props;
// const audit_status = 0
const [commentVisible, setCommentVisible] = useState(false);
const [mergeVisible, setMergeVisible] = useState(false);
const [compareVisible, setCompareVisible] = useState(false);
const [exportVisible, setExportVisible] = useState(false);
const [commitVisible, setCommitVisible] = useState(false);
const [auditVisible, setAuditVisible] = useState(false);
const [flowVisible, setFlowVisible] = useState(false);
const [versionVisible, setVersionVisible] = useState(false);
const [commitAuditVisible, setCommitAuditVisible] = useState(false);
const [sheet, setSheet] = useState({});
const [compareList, setCompareList] = useState([]);
const [edit, setEdit] = useState(false);
const [isMerge, setIsMerge] = useState(false);
const [version, setVersion] = useState({});
const [user, setUser] = useState([]);
const [updateCount, setUpdateCount] = useState({
diff: 0,
add: 0,
});
const [fileVisible, setFileVisible] = useState(false);
const [exportDate, setExportData] = useState([]);
// const [dataSource, setDataSource] = useState(DataSource);
// const [lastCommit, setLastCommit] = useState({ data: [] });
const sheetRef = useRef();
const sheetRef2 = useRef();
const sheetRef3 = useRef();
const fileRef = useRef();
const statusRef = useRef({
edit: false,
compare: false,
});
const cellPosition = useRef({});
// const [excelId, setExcelId] = useState(parseInt(params.excelId));
// const excelId = parseInt(params.excelId);
const projectId = parseInt(params.projectId);
const templateId = parseInt(params.templateId);
const flow = useMemo(() => {
let data = {
active: 0,
active_id: null,
current: 0,
currentNode: {},
list: {
FlowNodes: [],
},
};
if (version?.flow_id && auditList?.length > 0) {
let item = auditList.find(item => item.list.id == version.flow_id);
if (!item) return data;
// 合并同审批级别项
let nodes = {};
item.list.FlowNodes.map(item => {
if (!nodes[item.seq]) nodes[item.seq] = { ...item, user: [] };
nodes[item.seq].user.push(item.AuditorUser);
});
item.list.FlowNodes = Object.values(nodes);
// 查询当前节点
let current = item.list.FlowNodes.findIndex(node => node.seq == item.active);
item.current = current == -1 ? 0 : current;
// 保存当前所处节点
item.currentNode = item.list.FlowNodes[item.current];
data = item;
}
return data;
}, [auditList, version]);
const audit_status = flow.active_audit;
const isAuditor = useMemo(() => {
const getUserRole = () => {
let item = flow.currentNode?.user?.find?.(item => item.ID == currentUser.ID);
if (item) return true;
return false;
};
return audit_status == 1 && getUserRole();
}, [audit_status, flow, currentUser]);
// const audit_status = 1;
const onSave = () => {
let sheet1 = compareList[0];
Modal.confirm({
title: '提示',
content: `是否确认保存【${sheet1.version_name || sheet1.name}】`,
okText: '确定',
cancelText: '取消',
onOk() {
let sheetData = sheetRef3.current.getSheetJson().data;
sheetData.forEach(sheet => {
delete sheet.data;
});
let params = {
...sheet1,
data: JSON.stringify(sheetData),
};
dispatch({
type: 'detail/commitSheet',
payload: params,
callback: () => {
onCompare(false);
},
});
},
});
};
const onCompare = async checkSheets => {
if (checkSheets) {
const [sheet1, sheet2] = checkSheets;
if (!sheet1.data) {
sheet1.data = (
await queryDetail({
excel_id: sheet1.id,
})
).data;
}
if (!sheet2.data) {
sheet2.data = (
await queryDetail({
excel_id: sheet2.id,
})
).data;
}
setCompareList(checkSheets);
statusRef.current.compare = true;
} else {
let index = compareList.findIndex(item => item.id == sheet.id);
// 退出比对模式
if (index == 0) {
sheetRef3.current.toggleCompare(false);
} else if (index == 1) {
sheetRef2.current.toggleCompare(false);
}
setIsMerge(false);
setCompareList([]);
setSheet({
...sheet,
});
setUpdateCount({
diff: 0,
add: 0,
});
statusRef.current.compare = false;
}
setCommentVisible(false);
};
// const exportSheet = async item => {
// console.log(item);
// var sheets = await queryHistoryDetail(item);
// sheets.id = sheets.sheet_id;
// setSheet({
// ...item,
// name: item.version_name,
// data: sheets,
// });
// };
const renderSheetDom = (item, index) => {
return (
{item?.name}
{item.version_name && `(${item.version_name})`}
);
};
const onClickCell = (cell, position, s) => {
console.log(cell);
if (cell?.cid && !statusRef.current.edit) {
let payload = {
sheet_id: s.order || '0',
excel_id: version.id,
cid: cell.cid,
};
dispatch({
type: 'detail/queryComment',
payload,
});
cellPosition.current = {
...payload,
sheet_index: (s.seq || 0) + '',
};
// setCommentVisible(true);
}
// 比对模式下双excl同步选中
// if (statusRef.current.compare) {
// sheetRef3.current.selectCell(position.r, position.c, s.order);
// sheetRef2.current.selectCell(position.r, position.c, s.order);
// }
};
const onCommit = (values, id) => {
let currentData = sheetRef.current.getSheetJson().data;
let sheets = JSON.parse(JSON.stringify(currentData));
sheets.forEach(item => {
delete item.data;
});
console.log(sheets);
let params = {
...values,
id: id,
project_id: version.project_id,
name: version.name,
guid: version.guid,
audit_status: version.audit_status,
template_id: version.template_id,
template_node_id: version.template_node_id,
flow_id: version.flow_id,
node_id: version.node_id,
new_version: '0',
data: JSON.stringify(sheets),
};
dispatch({
type: 'detail/commitSheet',
payload: params,
callback: sheets => {
onCompare(false);
setCommitVisible(false);
setVersionVisible(false);
// setSheet(sheets);
// localStorage.luckysheet = JSON.stringify(sheets);
},
});
};
const onUpdate = () => {
let currentData = sheetRef.current.getSheetJson().data;
let sheets = JSON.parse(JSON.stringify(currentData));
sheets.forEach(item => {
delete item.data;
});
console.log(sheets);
let params = {
...version,
data: JSON.stringify(sheets),
};
dispatch({
type: 'detail/saveSheet',
payload: params,
});
};
// const onCommit = values => {
// var flowNode = flow.currentNode;
// // 获取最新sheet页信息
// dispatch({
// type: 'detail/querySheet',
// payload: {
// project_id: projectId,
// flow_id: flowNode.flow_id,
// node_id: flowNode.id,
// },
// callback: sheets => {
// let currentData = sheetRef.current.getSheetJson().data;
// currentData.forEach((item, index) => {
// // 使用最新的sheetId 防止多次创建sheet
// item.id = sheets.data[index]?.id;
// console.log(item.data.celldata);
// });
// let newSheet = {
// ...values,
// data: JSON.stringify(currentData),
// id: excelId,
// flow_id: flowNode.flow_id,
// node_id: flowNode.id,
// project_id: projectId,
// };
// dispatch({
// type: 'detail/commitSheet',
// payload: newSheet,
// callback: sheets => {
// onCompare(false);
// setCommitVisible(false);
// setSheet(sheets);
// localStorage.luckysheet = JSON.stringify(sheets);
// },
// });
// },
// });
// };
const onAudit = ({ audit_comment }) => {
var flowNode = flow.currentNode;
dispatch({
type: 'detail/approve',
payload: {
id: version.id,
project_id: projectId,
audit_status: 2,
flow_id: flowNode.flow_id,
node_id: flowNode.seq,
audit_comment,
},
callback: () => {
setAuditVisible(false);
},
});
};
const onSubmitAudit = () => {
Modal.confirm({
title: '提示',
content: '是否确认提交审批。',
okText: '确定',
cancelText: '取消',
onOk() {
var flowNode = flow.currentNode;
dispatch({
type: 'detail/submitAudit',
payload: {
id: version.id,
flow_id: flowNode.flow_id,
node_id: flowNode.id,
projectId,
},
});
},
});
};
const onApprove = flag => {
if (!flag) {
setAuditVisible(true);
return;
}
Modal.confirm({
title: '提示',
content: `是否${flag ? '通过' : '拒绝'}审批。`,
okText: '确定',
cancelText: '取消',
onOk: () => {
var flowNode = flow.currentNode;
dispatch({
type: 'detail/approve',
payload: {
id: flow.active_id,
project_id: projectId,
audit_status: flag ? 3 : 2,
flow_id: flowNode.flow_id,
node_id: flowNode.seq,
},
callback: newVersion => {
// 更新flow流程图
dispatch({
type: 'xflow/queryBoomFlowDetail',
payload: {
id: templateId,
},
});
if (flow.current == flow.list.FlowNodes.length - 1) {
// 最后一个审核节点通过后 需要更新version id
localStorage.excelId = newVersion.id;
setVersion({
...version,
id: newVersion.id,
});
}
},
});
},
});
};
const onMerge = () => {
const [sheet1, sheet2] = compareList;
Modal.confirm({
title: '提示',
content: `是否确认将【${sheet2.version_name}】改动的内容同步至【${sheet1.version_name ||
sheet1.name}】`,
okText: '确定',
cancelText: '取消',
onOk() {
// let sheet2Data = sheetRef2.current.getSheetJson()
sheetRef3.current.mergeExcl(sheetRef2.current.updateCell);
// setCompareList([...compareList]);
// let currentData = sheetRef3.current.getSheetJson()
// // 更新后重新比对
// sheetRef2.current.toggleCompare(false);
// sheetRef2.current.toggleCompare(true, currentData);
},
});
};
const onMergeVersion = async sheet2 => {
// const [sheet1, sheet2] = checkSheets;
const sheet1 = version;
if (!sheet1.data) {
sheet1.data = (
await queryDetail({
excel_id: sheet1.id,
})
).data;
}
if (!sheet2.data) {
sheet2.data = (
await queryDetail({
excel_id: sheet2.id,
})
).data;
}
setIsMerge(true);
setCompareList([sheet1, sheet2]);
// setTimeout(() => {
// sheetRef3.current.mergeExcl(sheet.data);
// }, 400);
};
// const handleClickCommit = async () => {
// const { list } = await queryHistory();
// let lastCommit = list[0];
// // 判断当前版本是否为最新版本
// if (lastCommit && sheet.guid != lastCommit.guid) {
// Modal.confirm({
// title: '提示',
// content: '当前版本与最新版本不匹配,将进入比对模式确认版本差异。',
// okText: '比对',
// cancelText: '返回',
// onOk() {
// dispatch({
// type: 'detail/queryHistoryDetail',
// payload: {
// excel_id: lastCommit.excel_id,
// history_id: lastCommit.id,
// },
// callback: sheets => {
// setIsMerge(true);
// let currentSheet = {
// ...sheet,
// name: '当前版本',
// };
// let lastSheet = {
// ...lastCommit,
// name: `线上最新版本(${lastCommit.version_name})`,
// data: sheets,
// };
// onCompare([currentSheet, lastSheet]);
// },
// });
// },
// });
// } else {
// setCommitVisible(true);
// }
// setCommentVisible(false);
// };
// const handleEdit = status => {
// if (!status) {
// // 还原数据
// sheetRef.current.renderSheet(sheet.data);
// }
// setCommentVisible(false);
// setEdit(status);
// statusRef.current.edit = status;
// sheetRef.current.toggleEdit(status);
// };
const handleClickFile = () => {
fileRef.current.click();
};
const handleMenuClick = e => {
console.log('click', e);
switch (e.key) {
case 'back':
// 返回
router.push(`/home`);
break;
// case 'version':
// // 版本
// queryHistory();
// setCommentVisible(false);
// setHistoryVisible(true);
// break;
case 'bomDetail':
// 版本
setCommentVisible(true);
break;
case 'export':
// 导出
handleExportClick();
break;
case 'commitAudit':
// 提交流转
setCommitAuditVisible(true);
break;
case 'flow':
// 查看流程
setFlowVisible(true);
break;
case 'compare':
// 比对
setCompareVisible(true);
break;
case 'template':
// 模板
handleClickFile();
break;
// case 'auditSuccess':
// // 审核通过
// onApprove(true);
// break;
// case 'auditFailed':
// // 审核拒绝
// onApprove(false);
// break;
// case 'edit':
// // 编辑
// handleEdit(true);
case 'merge':
// 同步版本
setMergeVisible(true);
break;
case 'commit':
// 提交
// handleClickCommit();
setCommitVisible(true);
setCommentVisible(false);
break;
case 'approval':
// 申请审批
onSubmitAudit();
break;
case 'attachment':
// 附件
setFileVisible(true);
queryFiles();
break;
}
};
const renderBtns = () => {
// if (edit) {
// return (
// <>
//
//
// >
// );
// }
// 判断是否为比对模式
if (compareList.length == 2) {
// 判断是否为同步最新版本的比对
if (isMerge) {
return (
<>
{/* */}
>
);
} else {
return ;
}
}
const menuList = [
返回,
详情,
导出,
提交流转,
查看流程,
比对,
附件,
];
// if (audit_status != 1) {
// menuList.push(历史提交);
// // menuList.push(模板);
// }
if (!isAuditor && canEdit()) {
// menuList.push(编辑);
menuList.push(同步);
// menuList.push(提交);
// if (history.list.length > 0) {
// menuList.push(申请审批);
// }
}
return (
<>
{menuList}}>
{/* */}
>
);
};
const canEdit = () => {
if (flow.list.FlowNodes.length - 1 == flow.current && audit_status == 3) return false;
return audit_status != 1;
};
const renderAlert = () => {
const audit_comment = history.list[0]?.audit_comment;
let item = '';
switch (audit_status) {
case 0:
return;
case 1:
item = ;
break;
case 2:
item = (
);
break;
case 3:
item = ;
break;
}
return {item}
;
};
const exportExcl = files => {
sheetRef.current.uploadExcel(files, () => {
fileRef.current.value = null;
});
};
const getRowOneList = () => {
const obj = sheetRef.current.getSheetJson();
console.log(obj);
const list = [];
obj.data.forEach(item => {
list.push(item.data[0]);
});
return list;
};
//点击导出弹出选择导出列弹框
const handleExportClick = () => {
setExportData(sheetRef.current.getSheetJson());
setExportVisible(true);
};
const downloadExcel = checkValue => {
sheetRef.current.downloadExcel(checkValue);
setExportVisible(false);
};
const queryHistory = id => {
return new Promise(reslove => {
dispatch({
type: 'detail/queryHistory',
payload: {
// excel_id: id || excelId,
project_id: projectId,
},
callback: reslove,
});
});
};
const queryFiles = () => {
dispatch({
type: 'detail/queryFiles',
payload: {
// excel_id: id || excelId,
excel_id: version.id,
},
});
};
const getUploadProps = () => {
const token = getToken() || GetTokenFromUrl();
const uploadProps = {
name: 'file',
showUploadList: false,
action: `/api/v1/purchase/attachment/${version.id}`,
headers: {
'JWT-TOKEN': token,
},
onChange(info) {
if (info.file.status !== 'uploading') {
console.log(info.file, info.fileList);
}
if (info.file.status === 'done') {
message.success(`${info.file.name} 文件上传成功`);
queryFiles();
} else if (info.file.status === 'error') {
message.error(`${info.file.name} 文件上传失败`);
}
},
};
return uploadProps;
};
const deleteFile = id => {
dispatch({
type: 'detail/deleteFiles',
id: id,
callback: () => {
queryFiles();
},
});
};
const queryHistoryDetail = async item => {
return new Promise(resolve => {
dispatch({
type: 'detail/queryHistoryDetail',
payload: {
excel_id: item.excel_id,
history_id: item.id,
},
callback: sheet => {
resolve(sheet);
},
});
});
};
const getLoading = () => {
let effects = loading.effects;
return !loading.effects['detail/queryComment'] && loading.models.detail;
};
const getFilesLoading = () => {
let effects = loading.effects;
return loading.effects['detail/queryFiles'];
};
const downloadFile = record => {
window.location.href = `${record.url}`;
};
const changeVersion = id => {
let version = versionList.find(item => item.id == id);
if (!version) return;
localStorage.excelId = id;
setVersion(version);
// 查询excel内容
// dispatch({
// type: 'detail/queryRecord',
// payload: {
// project_id: projectId,
// template_id: version.template_id,
// template_node_id: version.template_node_id,
// version_id: version.id,
// },
// callback: sheets => {
// console.log(sheets);
// setSheet(sheets);
// // sheetRef.current.renderSheet(sheets.data);
// },
// });
// // 查询历史修改
// dispatch({
// type: 'detail/queryHistoryList',
// payload: {
// version_id: version.id,
// },
// });
// 判断是否审批节点
if (version.flow_id) {
dispatch({
type: 'detail/queryAuditList',
payload: {
template_id: version.template_id,
template_node_id: version.template_node_id,
flow_id: version.flow_id,
version_id: version.id,
},
});
}
};
const onSubmitNextNode = values => {
dispatch({
type: 'detail/submitNextNode',
payload: values,
callback: () => {
setCommitAuditVisible(false);
},
});
};
const getUser = user => {
setUser(user);
};
const renderNode = () => {
const nodeId = version.template_node_id;
if (!flowDetail?.nodes || !nodeId) return;
const node = flowDetail.nodes.find(item => item.Id == nodeId);
return `当前节点:${node?.label || '-'}`;
};
const handleSubmitCell = (value, callback) => {
if (!value) return;
dispatch({
type: 'detail/addComment',
payload: {
...cellPosition.current,
comment: value,
},
callback,
});
};
useEffect(() => {
dispatch({
type: 'detail/queryProjectRecord',
payload: {
project_id: projectId,
},
});
dispatch({
type: 'xflow/queryBoomFlowDetail',
payload: {
id: templateId,
},
});
dispatch({
type: 'user/fetchUserList',
});
// 审批流程
// dispatch({
// type: 'detail/queryAuditList',
// });
// 查询节点
// dispatch({
// type: 'detail/queryFlowInfo',
// payload: {
// projectId,
// },
// callback: async ({ currentNode }, sheets) => {
// if (sheets.id != excelId) {
// // 更新excel id
// router.push(`/home/detail/${sheets.id}/${projectId}`);
// }
// let { list } = await queryHistory(sheets.id);
// let sheet = JSON.parse(LocalData || '{}');
// if (
// LocalData &&
// sheet.excel_id == sheets.id &&
// currentNode.id == sheet.node_id &&
// list[0]?.audit_status != 1
// ) {
// // 显示缓存数据
// setSheet(sheet);
// } else {
// sheets.excel_id = sheets.id;
// sheets.name = sheets.version_name;
// delete sheets.id;
// setSheet(sheets);
// }
// sheetRef.current.renderSheet(sheets.data);
// },
// });
// dispatch({
// type: 'detail/getRoleList',
// payload: {
// ID: projectId,
// },
// });
}, []);
useEffect(() => {
if (compareList.length == 2) {
const callback = ({ diff, add }) => {
setUpdateCount(updateCount => {
return {
diff: diff.length,
add: updateCount.add + add.length,
};
});
};
var update1 = sheetRef3.current.toggleCompare(true, compareList[1].data, callback);
var update2 = sheetRef2.current.toggleCompare(true, compareList[0].data, callback);
}
}, [compareList]);
useEffect(() => {
if (versionList.length == 0) return;
if (!version.id) {
const excelId = localStorage.excelId;
changeVersion(excelId);
} else {
changeVersion(version.id);
}
// else if (version.id != params.excelId) {
// changeVersion(version.id);
// }
}, [versionList]);
return (
{/* */}
{/* 当前节点: {version.template_node_id}
当前状态:{version.audit_status} */}
{flow?.active == 0 && (
}
onClick={() => setVersionVisible(true)}
>
)}
{renderNode()}
{user.map(item => (
{item.Name}
))}
{renderBtns()}
exportExcl(e.target.files)}
/>
{renderAlert()}
{/* 判断是否为比对模式 */}
{compareList.length == 2 ? (
<>
{compareList.map(renderSheetDom)}
>
) : (
{version.id && (
)}
)}
setCommentVisible(false)}
/>
{/* setHistoryVisible(false)}
onSelect={item => exportSheet(item)}
/> */}
setCompareVisible(false)}
onOk={onCompare}
/>
setMergeVisible(false)}
onOk={onMergeVersion}
/>
setExportVisible(false)}
onOk={downloadExcel}
/>
{/* setCommitVisible(false)}
onOk={values => onCommit(values, version.id)}
/> */}
setFlowVisible(false)}
version={version}
// onOk={onCommit}
onChangeVersion={version => changeVersion(version.id)}
/>
setAuditVisible(false)}
onOk={onAudit}
/>
setFileVisible(false)}
uploadProps={getUploadProps()}
DeleteFile={deleteFile}
downloadFile={downloadFile}
data={fileList}
/>
setVersionVisible(false)}
onOk={values => onCommit(values)}
/>
setCommitAuditVisible(false)}
onOk={onSubmitNextNode}
/>
);
}
export default connect(({ detail, user, xflow, loading }) => ({
flow: detail.flow,
flowDetail: xflow.flowDetail,
auditList: detail.auditList,
fileList: detail.fileList,
history: detail.history,
comment: detail.comment,
currentUser: user.currentUser,
roleList: detail.roleList,
versionList: detail.versionList,
loading,
}))(Detail);