UNPKG

@bos-alpha/progress

Version:

进度管理

698 lines (697 loc) 33.2 kB
var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) { if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; } return cooked; }; var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); }; import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import { useEffect, useState } from 'react'; import { Button, message, Row, Col } from 'antd'; import dayjs from 'dayjs'; import styled from '@emotion/styled'; import { Icon, cookieToken, Modal } from '@bos-alpha/common'; import * as api from '@bos-alpha/common/lib/services'; import { ImportModal } from '../import-modal'; import { Gantt } from '../gantt'; import { EditableTable } from '../editable-table'; import { TagLink } from '../tag-link'; // 获取指定层级以内的数据 export function getListBeyondLevel(list, level) { return list.map(function (item) { if (item.children) { return __assign(__assign({}, item), { children: parseInt(item.level) <= level ? getListBeyondLevel(item.children, level) : null }); } return item; }); } // 获取指定key的数据项 export function loopQuery(allList, key) { var curItem = {}; var loop = function (list) { list.forEach(function (item) { if (item.key === key) { curItem = item; } else if (item.children) { loop(item.children); } }); }; loop(allList); return curItem; } // 返回数据里所有的key 支持筛选指定层级数据 export var getAllKeys = function (data, level) { var allKeys = []; data.forEach(function (item) { if (typeof level !== 'undefined') { if (parseInt(item.level) === level) { allKeys.push(item.key); } } else { allKeys.push(item.key); } if (item.children) allKeys.push.apply(allKeys, getAllKeys(item.children, level)); }); return allKeys; }; // 进度管理 - 可编辑进度表格 + 表格顶部操作按钮 + 甘特图 export var Manage = function (_a) { var isLoading = _a.isLoading, tableData = _a.tableData, onRefresh = _a.onRefresh; // 勾选的任务项 var _b = useState([]), selectedRows = _b[0], setSelectedRows = _b[1]; // 勾选的任务key var selectedRowKeys = selectedRows.map(function (_a) { var key = _a.key; return key; }); // 展开的key var _c = useState([]), expandedRowKeys = _c[0], setExpandedRowKeys = _c[1]; // 所有任务key var _d = useState([]), allKeys = _d[0], setAllKeys = _d[1]; // 当前可见的表格任务数据 前端分页 var _e = useState([]), taskList = _e[0], setTaskList = _e[1]; // 物项管理弹窗显隐 var _f = useState(false), tagLinkVisible = _f[0], setTagLinkVisible = _f[1]; // 新增关联还是编辑关联 var _g = useState('add'), tagLinkType = _g[0], setTagLinkType = _g[1]; // 物项管理或查看任务关联的物项 之 当前任务key var _h = useState(''), wbsKey = _h[0], setWbsKey = _h[1]; // 导入进度文件弹窗 var _j = useState(false), importModalVisible = _j[0], setImportModalVisible = _j[1]; // 如果有勾选一行 刷新勾选数据 useEffect(function () { var allKeys = getAllKeys(tableData); // 任务数超过1000才特殊处理 if (allKeys.length > 1000) { var list = getListBeyondLevel(tableData, 1); var level0Keys = list.map(function (item) { return item.key; }); setTaskList(list); setExpandedRowKeys(level0Keys); } else { setTaskList(tableData); setExpandedRowKeys(allKeys); } setAllKeys(allKeys); if (setSelectedRows.length === 1) { var loopQuery_1 = function (list) { list.forEach(function (item) { var _a; if (item.key === ((_a = selectedRows[0]) === null || _a === void 0 ? void 0 : _a.key)) { setSelectedRows([item]); } if (item.children) { loopQuery_1(item.children); } }); }; loopQuery_1(tableData); } }, [tableData]); // eslint-disable-line react-hooks/exhaustive-deps // 展开树 var onExpand = function (expanded, record) { // 总任务数小于1000时,不作特殊处理 if (allKeys.length < 1000) { var keys_1 = expanded ? __spreadArray(__spreadArray([], expandedRowKeys, true), [record.key], false) : expandedRowKeys.filter(function (key) { return record.key !== key; }); setExpandedRowKeys(keys_1); return; } // 收集所有被关闭的子节点key var closedKeys = []; if (!expanded && record.children) { var loop_1 = function (list) { return list.forEach(function (item) { if (item.children) { closedKeys.push(item.key); loop_1(item.children); } }); }; closedKeys.push(record.key); loop_1(record.children); } // 展开时,关闭同级节点 // 关闭时,关闭所有子节点树 var keys = []; if (expanded) { keys = __spreadArray(__spreadArray([], expandedRowKeys, true), [record.key], false); var curLevel = parseInt(record.level); if (curLevel > 0) { // 兄弟同级keys var sameLevelKeys_1 = getAllKeys(tableData, curLevel).filter(function (key) { return key !== record.key; }); keys = keys.filter(function (key) { return sameLevelKeys_1.indexOf(key) < 0; }); } } else { keys = expandedRowKeys.filter(function (key) { return closedKeys.indexOf(key) < 0; }); } // 只获取下两级节点 var curItem = loopQuery(tableData, record.key); var loop = function (list) { return list.map(function (el) { if (el.key === record.key) { return __assign(__assign({}, el), { children: getListBeyondLevel(curItem === null || curItem === void 0 ? void 0 : curItem.children, parseInt(curItem.level) + (expanded ? 1 : 0)) }); } if (el.children) { return __assign(__assign({}, el), { children: loop(el.children) }); } return el; }); }; setTaskList(loop(taskList)); setExpandedRowKeys(keys); }; // 勾选行数 针对不同按钮禁用的条件 var selectedLen = selectedRows.length; // 未勾选 var nullRow = selectedLen === 0; // 只勾选一行 var onlyOneRow = selectedLen === 1; // 是否可以升降级 var isCanUpgrade = false; var isCanDowngrade = false; // 是否可以上下移 var isCanUp = false; var isCanDown = false; // 是否是叶子节点 var isLeaf = false; // 是否已关联物项 var wbsHasTag = false; if (onlyOneRow) { var _k = selectedRows[0], gIndex_1 = _k.gIndex, level = _k.level, key_1 = _k.key, parentId_1 = _k.parentId, leaf = _k.leaf, hasTags = _k.hasTags; isLeaf = leaf; wbsHasTag = hasTags; // 层级大于1可以升级(升级后与父级同级) isCanUpgrade = level > 1; // 不是第一个都可以降级(降级到前一个任务) isCanDowngrade = gIndex_1 > 1; // 序号大于1可以上移 isCanUp = gIndex_1 > 1; // 不是最后一条数据(注意子任务)都可以下移 // 找到当前勾选项的父级 获取兄弟元素个数 var loopQuery_2 = function (list) { list.forEach(function (item) { // 一级或子级 if (parentId_1 === null || item.key === key_1) { isCanDown = gIndex_1 < list.length; } // 有子级 继续查找 if (item.children) { loopQuery_2(item.children); } }); }; loopQuery_2(tableData); } var time2date = function (time) { return time ? dayjs(Number(time)).format('YYYY/MM/DD') : '点此修改'; }; // 天数计算 工期的决定机制统一为:结束时间 - 开始时间 + 1 var daysCalc = function (diff) { return "".concat(Math.ceil(diff / 86400000) + 1, "\u5929"); }; // 表格操作按钮 var tableOptBtns = [ { name: '新增任务', disabled: !(nullRow || onlyOneRow) || wbsHasTag, action: function () { return __awaiter(void 0, void 0, void 0, function () { var now, data, _a, key, code, planStartTime, planEndTime, res; return __generator(this, function (_b) { switch (_b.label) { case 0: now = dayjs(dayjs().format('YYYY-MM-DD 00:00:00')).valueOf(); data = { bosclass: 'wbses', parentId: null, code: "".concat(233333 + Math.round(Math.random() * 1000000)), name: "\u65B0\u4EFB\u52A1".concat(Date.now() % Math.pow(10, 10)), planStartTime: now, planEndTime: now + 86400000 }; // 新增子任务 if (selectedRows.length === 1) { _a = selectedRows[0], key = _a.key, code = _a.code, planStartTime = _a.planStartTime, planEndTime = _a.planEndTime; data.parentId = key; data.code = "".concat(code).concat(data.code); data.planStartTime = planStartTime; data.planEndTime = planEndTime; } return [4 /*yield*/, api.addEntity('wbses', { data: data }, { noErrorHandle: true })]; case 1: res = _b.sent(); if (res.code === 'SUCCESS') { onRefresh && onRefresh(); } else if (res.code === 'CLASS_WRITEPERMISSION_REQUIRED') { message.error('缺少实体类wbses的编辑权限'); } else { message.error(_jsxs("div", { children: [_jsx("h4", { children: "\u65B0\u589E\u4EFB\u52A1\u5931\u8D25" }, void 0), _jsx("p", { children: res.message }, void 0)] }, void 0), 3); } return [2 /*return*/]; } }); }); } }, { name: '删除任务', disabled: nullRow, action: function () { // @ts-ignore Modal.confirm({ title: '是否删除任务', onOk: function () { var delKeys = selectedRowKeys.length === allKeys.length ? ['all'] : selectedRowKeys; // 批量删除 返回结果是数组 api.wbsesBatch({ data: delKeys }, { noErrorHandle: true }).then(function (ress) { if (!Array.isArray(ress)) { if (ress.code !== 'SUCCESS') { if (ress.code === 'CLASS_DELETEPERMISSION_REQUIRED') { message.error('缺少实体类wbses的删除权限'); } else { message.error('删除任务失败'); } } else { // 已删除的任务 取消勾选 setSelectedRows([]); // 刷新数据 onRefresh && onRefresh(); } } else { var errors = ress .filter(function (res) { return res.code !== 'SUCCESS'; }) .map(function (res) { if (res.code === 'CLASS_WRITEPERMISSION_REQUIRED') { return '缺少实体类wbses的删除权限'; } return res.message; }); if (errors.length) { message.error(_jsxs("div", { children: [_jsx("h4", { children: "\u5220\u9664\u4EFB\u52A1\u5931\u8D25" }, void 0), errors.map(function (err, index) { return (_jsx("p", { children: err }, index)); })] }, void 0)); } // 已删除的任务 取消勾选 setSelectedRows([]); // 刷新数据 onRefresh && onRefresh(); } }); } }); } }, { name: '升级任务', disabled: !(onlyOneRow && isCanUpgrade), action: function () { return __awaiter(void 0, void 0, void 0, function () { var key, err_1; return __generator(this, function (_a) { switch (_a.label) { case 0: _a.trys.push([0, 2, , 3]); key = selectedRows[0].key; return [4 /*yield*/, api.updateWbsLevel(key, { params: { type: 'up' } })]; case 1: _a.sent(); onRefresh && onRefresh(); return [3 /*break*/, 3]; case 2: err_1 = _a.sent(); return [3 /*break*/, 3]; case 3: return [2 /*return*/]; } }); }); } }, { name: '降级任务', disabled: !(onlyOneRow && isCanDowngrade), action: function () { return __awaiter(void 0, void 0, void 0, function () { var key, err_2; return __generator(this, function (_a) { switch (_a.label) { case 0: _a.trys.push([0, 2, , 3]); key = selectedRows[0].key; return [4 /*yield*/, api.updateWbsLevel(key, { params: { type: 'down' } })]; case 1: _a.sent(); onRefresh && onRefresh(); return [3 /*break*/, 3]; case 2: err_2 = _a.sent(); return [3 /*break*/, 3]; case 3: return [2 /*return*/]; } }); }); } }, { name: '上移任务', disabled: !(onlyOneRow && isCanUp), action: function () { return __awaiter(void 0, void 0, void 0, function () { var key, err_3; return __generator(this, function (_a) { switch (_a.label) { case 0: _a.trys.push([0, 2, , 3]); key = selectedRows[0].key; return [4 /*yield*/, api.wbsSequence(key, { params: { type: 'up' } })]; case 1: _a.sent(); onRefresh && onRefresh(); return [3 /*break*/, 3]; case 2: err_3 = _a.sent(); return [3 /*break*/, 3]; case 3: return [2 /*return*/]; } }); }); } }, { name: '下移任务', disabled: !(onlyOneRow && isCanDown), action: function () { return __awaiter(void 0, void 0, void 0, function () { var key, err_4; return __generator(this, function (_a) { switch (_a.label) { case 0: _a.trys.push([0, 2, , 3]); key = selectedRows[0].key; return [4 /*yield*/, api.wbsSequence(key, { params: { type: 'down' } })]; case 1: _a.sent(); onRefresh && onRefresh(); return [3 /*break*/, 3]; case 2: err_4 = _a.sent(); return [3 /*break*/, 3]; case 3: return [2 /*return*/]; } }); }); } }, { name: '物项管理', disabled: !(onlyOneRow && isLeaf), action: function () { var key = selectedRows[0].key; setWbsKey(key); setTagLinkType('add'); setTagLinkVisible(true); } }, { name: '导入进度文件', icon: 'iconicon_download', disabled: false, action: function () { return setImportModalVisible(true); } }, { name: '导出进度文件', icon: 'iconicon_upload', disabled: tableData.length === 0, action: function () { return __awaiter(void 0, void 0, void 0, function () { var res, blobURL, tempLink; return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, api.downloadWbsFile({ params: { type: 'excel', access_token: cookieToken() } }, { noErrorHandle: true })]; case 1: res = _a.sent(); console.log(res); if (res.data) { blobURL = window.URL.createObjectURL(res.data); tempLink = document.createElement('a'); tempLink.style.display = 'none'; tempLink.href = blobURL; tempLink.setAttribute('download', '进度.xls'); document.body.appendChild(tempLink); tempLink.click(); document.body.removeChild(tempLink); window.URL.revokeObjectURL(blobURL); } return [2 /*return*/]; } }); }); } } ]; var columns = [ { title: '任务名称', dataIndex: 'name', inputType: 'input', editable: true, rules: [ { required: true, message: "\u4EFB\u52A1\u540D\u79F0\u662F\u5FC5\u586B\u9879\u76EE" } ] }, { title: '编号', dataIndex: 'code', inputType: 'input', editable: true, rules: [ { required: true, message: "\u7F16\u53F7\u662F\u5FC5\u586B\u9879\u76EE" } ] }, { title: '完成进度', dataIndex: 'progress', inputType: 'input', editable: true, render: function (progress) { return (progress ? progress : '暂无进度'); } }, { title: '计划开始时间', dataIndex: 'planStartTime', inputType: 'datePicker', editable: true, rules: [ { required: true, message: "\u8BF7\u8F93\u5165\u65F6\u95F4" } ], render: function (time) { return time2date(time); } }, { title: '计划结束时间', dataIndex: 'planEndTime', inputType: 'datePicker', editable: true, rules: [ { required: true, message: "\u8BF7\u8F93\u5165\u65F6\u95F4" } ], render: function (time) { return time2date(time); } }, { title: '计划工期', dataIndex: '', render: function (_, record) { if (!record.planEndTime || !record.planStartTime) return ''; return daysCalc(record.planEndTime - record.planStartTime); } }, { title: '实际开始时间', dataIndex: 'startTime', inputType: 'datePicker', editable: true, render: function (time) { return time2date(time); } }, { title: '实际结束时间', dataIndex: 'endTime', inputType: 'datePicker', editable: true, render: function (time) { return time2date(time); } }, { title: '实际工期', dataIndex: '', render: function (_, record) { if (!record.endTime || !record.startTime) return ''; return daysCalc(record.endTime - record.startTime); } }, { title: '物项信息', dataIndex: 'hasTags', render: function (hasTags, record) { if (hasTags) { return (_jsx(CustomIcon, { type: "iconicon_questionmarktips", title: "\u6709\u5173\u8054\u7269\u9879", onClick: function () { setTagLinkType('remove'); setWbsKey(record.key); setTagLinkVisible(true); } }, void 0)); } else { return ''; } } } ].map(function (col) { if (!col.editable) return col; return __assign(__assign({}, col), { onCell: function (record) { // record就是表格数据 // console.log('record', record, col); return __assign(__assign({}, col), { editable: col.editable && !([ 'planStartTime', 'planEndTime', 'startTime', 'endTime' ].indexOf(col.dataIndex) >= 0 && record.children) && !(col.dataIndex === 'progress' && record.children), record: record, onSave: function (vals) { return __awaiter(void 0, void 0, void 0, function () { var err_5; return __generator(this, function (_a) { switch (_a.label) { case 0: if (Object.values(vals).filter(function (item) { return typeof item !== 'undefined'; }).length === 0) { return [2 /*return*/]; } _a.label = 1; case 1: _a.trys.push([1, 3, , 4]); return [4 /*yield*/, api.editEntity('wbses', record.key, { data: vals })]; case 2: _a.sent(); onRefresh && onRefresh(); return [3 /*break*/, 4]; case 3: err_5 = _a.sent(); return [2 /*return*/, message.error(err_5.message)]; case 4: return [2 /*return*/]; } }); }); } }); } }); }); return (_jsxs("div", { children: [_jsxs(Row, { children: [_jsxs(Col, __assign({ span: 16 }, { children: [_jsx(TableOptionBtns, { children: tableOptBtns.map(function (_a) { var name = _a.name, icon = _a.icon, disabled = _a.disabled, action = _a.action; return (_jsx(Button, __assign({ className: "btn" }, (icon ? { icon: (_jsx(Icon, { className: "iconfont", type: icon, title: name }, void 0)) } : {}), { disabled: disabled, onClick: action }, { children: name }), name)); }) }, void 0), _jsx(EditableTable, { rowKey: "key", size: "small", bordered: true, columns: columns, rowSelection: { selectedRowKeys: selectedRowKeys, onChange: function (_, rows) { return setSelectedRows(rows); } }, loading: isLoading, dataSource: taskList, expandable: { expandedRowKeys: expandedRowKeys, onExpand: onExpand }, pagination: false }, void 0)] }), void 0), _jsx(Col, __assign({ span: 8 }, { children: _jsx(Gantt, { pageMode: "manage", tableData: tableData }, void 0) }), void 0)] }, void 0), _jsx(TagLink, { visible: tagLinkVisible, type: tagLinkType, wbsKey: wbsKey, onClose: function () { return setTagLinkVisible(false); }, onAddOk: function () { setTagLinkVisible(false); onRefresh && onRefresh(); } }, void 0), _jsx(ImportModal, { visible: importModalVisible, onCancel: function () { return setImportModalVisible(false); }, onOk: function () { setImportModalVisible(false); onRefresh && onRefresh(); } }, void 0)] }, void 0)); }; var CustomIcon = styled(Icon)(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n color: inherit;\n font-size: 16px;\n cursor: pointer;\n"], ["\n color: inherit;\n font-size: 16px;\n cursor: pointer;\n"]))); var TableOptionBtns = styled.div(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n padding-bottom: 20px;\n white-space: nowrap;\n .btn {\n color: rgba(0, 0, 0, 0.65);\n background-color: #fff;\n border-radius: 16px;\n border: 1px solid #d9d9d9;\n margin-right: 10px;\n &:hover {\n border-color: #68a0ff;\n color: #68a0ff;\n }\n &[disabled] {\n color: rgba(0, 0, 0, 0.25);\n background-color: #f5f5f5;\n border-color: #d9d9d9;\n text-shadow: none;\n -webkit-box-shadow: none;\n box-shadow: none;\n }\n }\n .iconfont {\n display: inline-block;\n color: inherit;\n font-size: 14px;\n }\n"], ["\n padding-bottom: 20px;\n white-space: nowrap;\n .btn {\n color: rgba(0, 0, 0, 0.65);\n background-color: #fff;\n border-radius: 16px;\n border: 1px solid #d9d9d9;\n margin-right: 10px;\n &:hover {\n border-color: #68a0ff;\n color: #68a0ff;\n }\n &[disabled] {\n color: rgba(0, 0, 0, 0.25);\n background-color: #f5f5f5;\n border-color: #d9d9d9;\n text-shadow: none;\n -webkit-box-shadow: none;\n box-shadow: none;\n }\n }\n .iconfont {\n display: inline-block;\n color: inherit;\n font-size: 14px;\n }\n"]))); var templateObject_1, templateObject_2;