Commit f9560ad6 authored by 邓超's avatar 邓超

fix: 流程模块

parent 18196eb1
Pipeline #34140 passed with stages
in 27 minutes 8 seconds
import React, { useEffect, useState } from 'react';
import { useHistory } from 'react-router-dom';
import { reloadFlows, removeFlowExtend } from '@/services/platform/flow';
import {
Card,
Space,
Table,
Popconfirm,
Spin,
Tooltip,
notification,
message,
Button,
} from 'antd';
import {
RightOutlined,
DoubleLeftOutlined,
DoubleRightOutlined,
EditTwoTone,
ApartmentOutlined,
DeleteOutlined,
OrderedListOutlined,
} from '@ant-design/icons';
import classnames from 'classnames';
import PageContainer from '@/components/BasePageContainer';
import ProcessConfig from './flowComponents/ProcessConfig';
import Order from './flowComponents/Order';
import styles from './flow.less';
const Flow = () => {
const history = useHistory();
const [tableData, setTableData] = useState([]); // 流程对应的回显的表格
const [processData, setProcessData] = useState([]); // 流程列表总
const [dataSource, setDataSource] = useState(''); // 是否是返回获取数据
const [processMsg, setProcessMsg] = useState({}); // 流程配置回显信息
const [treeLoading, setTreeLoading] = useState(false);
const [treeVisible, setTreeVisible] = useState(true);
const [pickItemIndex, setPickItemIndex] = useState(0); // 选中流程索引
const [visible, setVisible] = useState({
processConfig: false,
order: false,
}); // 弹窗显示
// 初始化
useEffect(() => {
// 初始化流程列表
getProcessData();
if (history.location.state && history.location.state.pickItemIndex) {
setDataSource('back');
}
}, []);
// 表格数据改变后处理
useEffect(() => {
// 判断是否是返回回来的页面
if (processData.length === 0) {
return;
}
if (dataSource === 'back') {
setPickItemIndex(history.location.state.pickItemIndex);
setTableData(processData[history.location.state.pickItemIndex].root);
} else {
setTableData(processData[pickItemIndex].root);
}
}, [processData]);
// 弹窗显示控制
const showModal = (key, value) => {
setVisible({ ...visible, [key]: value });
};
// 初始化流程列表
const getProcessData = () => {
setTreeLoading(true);
reloadFlows()
.then(res => {
setTreeLoading(false);
if (res.code === 0) {
setProcessData(res.data);
} else {
notification.error({
message: '提示',
duration: 3,
description: res.msg,
});
}
})
.catch(() => {
setTreeLoading(false);
notification.error({
message: '提示',
duration: 3,
description: '网络异常',
});
});
};
// 删除流程
const delProcess = val => {
removeFlowExtend({ flowIDs: val.extendID })
.then(res => {
if (res.code === 0) {
setDataSource('current');
getProcessData();
notification.success({
message: '提示',
duration: 3,
description: '删除成功',
});
} else {
notification.error({
message: '提示',
duration: 3,
description: res.msg,
});
}
})
.catch(() => {
notification.error({
message: '提示',
duration: 3,
description: '网络异常',
});
});
};
// 跳转到对应的流程节点
const toNode = flowName => {
history.push({
pathname: '/platformCenter/bsmanger/flowNode',
state: { flowName, pickItemIndex },
});
};
// 定义表格
const columns = [
{ title: '名称', dataIndex: 'name', width: 150, align: 'center' },
{
title: '前端样式',
dataIndex: 'extendWebPage',
align: 'center',
render: text => (
// eslint-disable-next-line react/no-danger
<span dangerouslySetInnerHTML={{ __html: text }} />
),
},
{
title: '手持样式',
dataIndex: 'extendMobilePage',
align: 'center',
render: text => (
// eslint-disable-next-line react/no-danger
<span dangerouslySetInnerHTML={{ __html: text }} />
),
},
{
title: '辅助试图',
dataIndex: 'extendPageCount',
align: 'center',
render: text => (
// eslint-disable-next-line react/no-danger
<span dangerouslySetInnerHTML={{ __html: text }} />
),
},
{
title: '流程结束后',
dataIndex: 'flowEndBehavior',
align: 'center',
render: text => (
// eslint-disable-next-line react/no-danger
<span dangerouslySetInnerHTML={{ __html: text }} />
),
},
{
title: '12位编码',
dataIndex: 'useFixedCodingRule',
width: 80,
align: 'center',
},
{
title: '异常节点',
dataIndex: 'errorNodes',
align: 'center',
render: text => (
// eslint-disable-next-line react/no-danger
<span dangerouslySetInnerHTML={{ __html: text }} />
),
},
{
title: '接口配置',
dataIndex: 'interfaceConfig',
align: 'center',
render: text => (
// eslint-disable-next-line react/no-danger
<span dangerouslySetInnerHTML={{ __html: text }} />
),
},
{
title: '操作',
align: 'center',
ellipsis: true,
render: record => (
<>
<Space>
<Tooltip title="流程配置">
<EditTwoTone
onClick={() => {
showModal('processConfig', true);
setProcessMsg(record);
}}
style={{ fontSize: '16px', color: '#1890FF' }}
/>
</Tooltip>
<Tooltip title="节点配置">
<ApartmentOutlined
onClick={() => toNode(record.name)}
style={{ fontSize: '16px', color: '#1890FF' }}
/>
</Tooltip>
<Tooltip title="清除流程配置">
<Popconfirm
title="是否清除该流程配置?"
onConfirm={() => delProcess(record)}
onCancel={() => message.error('取消清除')}
okText="是"
cancelText="否"
>
<DeleteOutlined
style={{ fontSize: '16px', color: '#e86060' }}
/>
</Popconfirm>
</Tooltip>
</Space>
</>
),
},
];
return (
<PageContainer>
<div className={styles.flowContainer}>
{/* 左侧事件树 */}
<Spin spinning={treeLoading} tip="loading...">
<Card
className={classnames({
[styles.orgContainer]: true,
[styles.orgContainerHide]: !treeVisible,
})}
>
{treeVisible ? (
<>
<span className={styles.processTitle}>流程列表</span>
<hr className={styles.splitLine} />
{/* 流程列表 */}
{processData.length > 0 &&
processData.map((item, index) => (
<div
className={classnames({
[styles.listItem]: true,
[styles.pickItem]: index === pickItemIndex,
})}
onClick={() => {
setPickItemIndex(index);
setTableData(item.root);
}}
key={item.goupName}
>
{item.goupName}{item.count ? item.count : ''}
{index === pickItemIndex ? <RightOutlined /> : ''}
</div>
))}
</>
) : (
''
)}
<div className={styles.switcher}>
{treeVisible && (
<Tooltip title="隐藏流程列表">
<DoubleLeftOutlined onClick={() => setTreeVisible(false)} />
</Tooltip>
)}
{!treeVisible && (
<Tooltip title="显示流程列表">
<DoubleRightOutlined onClick={() => setTreeVisible(true)} />
</Tooltip>
)}
</div>
</Card>
</Spin>
{/* 右侧流程表 */}
<div className={styles.processContainer}>
<div className={styles.buttonList}>
<Button
onClick={() => {
showModal('order', true);
}}
>
<OrderedListOutlined />
排序
</Button>
</div>
<Table
dataSource={tableData}
columns={columns}
rowKey={record => record.ID}
bordered
size="small"
scroll={{ x: 'max-content', y: '100vh-150px' }}
onRow={record => ({
onDoubleClick: () => {
toNode(record.name);
},
})}
pagination={{
showTotal: (total, range) =>
`第${range[0]}-${range[1]} 条/共 ${total} 条`,
pageSizeOptions: [10, 20, 50, 100],
defaultPageSize: 10,
showQuickJumper: true,
showSizeChanger: true,
}}
/>
</div>
</div>
{/* 流程配置弹窗 */}
<ProcessConfig
visible={visible.processConfig}
processMsg={processMsg}
handleCancel={() => showModal('processConfig', false)}
onSubumit={() => {
showModal('processConfig', false);
setDataSource('current');
getProcessData();
}}
/>
{/* 排序弹窗 */}
<Order
visible={visible.order}
tableData={tableData}
handleCancel={() => showModal('order', false)}
submitCallBack={() => {
showModal('order', false);
setDataSource('current');
getProcessData();
}}
/>
</PageContainer>
);
};
export default Flow;
.flowContainer {
display: flex;
width: 100%;
position: relative;
.orgContainer {
position: relative;
left: 0;
top: 0;
height: calc(100vh - 74px);
width: 280px;
margin-right: 10px;
overflow-x: hidden;
transition-property: width, left;
transition-duration: 0.5s;
white-space: nowrap;
.processTitle {
font-size: 15px;
font-weight: bold;
color: #333e51;
padding-left: 14px;
}
.splitLine {
width: 100%;
color: #eeecec;
}
.listItem {
display: flex;
justify-content: space-between;
align-items: center;
padding: 8px 14px;
line-height: 28px;
font-size: 14px;
font-weight: 400;
color: #414e65;
cursor: pointer;
}
.pickItem {
background-color: #f5f6f9;
}
.switcher {
display: block;
position: absolute;
font-size: 18px;
color: #1890ff !important;
top: 50%;
right: 2px;
transform: translate(0%, -50%);
z-index: 1;
}
}
.orgContainerHide {
left: 0px;
top: 0;
width: 26px;
}
.processContainer {
position: relative;
width: 100%;
height: calc(100vh - 74px);
min-width: 800px;
background: white;
.buttonList {
display: flex;
justify-content: flex-end;
margin: 10px 10px 10px 0;
.ant-btn {
vertical-align: middle;
line-height: 2px;
}
}
.ant-table-pagination {
padding-right: 12px;
background: white;
margin: 1px 0;
padding: 8px;
padding-right: 20px;
}
.ant-table-thead tr th {
font-weight: 600;
color: rgba(0, 0, 0, 0.85);
}
.ant-table-cell {
text-align: center;
overflow: hidden;
white-space: nowrap;
}
.ant-table-body {
height: calc(100vh - 210px);
border-right: white;
overflow: auto !important;
}
.ant-pagination {
z-index: 999;
border-top: 1px solid #f0eded;
}
}
}
.ant-radio-wrapper {
min-width: 150px;
margin-bottom: 2px;
}
.doctorTable {
margin-bottom: 16px;
table {
width: 100%;
td {
padding: 6px;
border: 1px solid #e8e8e8;
}
thead {
tr {
font-weight: 600;
background: #fafafa;
}
td {
width: 12rem;
}
}
tbody {
tr:hover {
background-color: #ededed;
}
}
}
}
import React, { useState, useEffect } from 'react';
import { flowReOrder } from '@/services/platform/flow';
import Sortable from 'sortablejs';
import { Modal, notification } from 'antd';
import styles from '../flow.less';
const Order = props => {
const { visible, handleCancel, tableData, submitCallBack } = props;
const [orderTable, setOrderTable] = useState([]);
const [flowIDs, setFlowIDs] = useState('');
// 页面弹出的时候初始化拖拽
let dragTimer = null;
useEffect(() => {
if (visible) {
setOrderTable(() => {
let table;
table = tableData.filter(item => item.extendID !== -1);
return table;
});
dragTimer = setTimeout(() => {
dragSort();
}, 0);
}
return () => {
clearTimeout(dragTimer);
};
}, [visible]);
// 根据orderTable初始化flowIDs
useEffect(() => {
let ids;
orderTable.forEach((item, index) => {
if (index === orderTable.length - 1) {
ids += `${item.extendID}`;
} else {
ids += `${item.extendID},`;
}
});
setFlowIDs(ids);
}, [orderTable]);
// 初始化排序
const dragSort = () => {
let el = document.getElementById('doctor-drag-items');
if (el) {
Sortable.create(el, {
animation: 100, // 动画参数
onEnd(evt) {
// 拖拽完毕之后发生,只需关注该事件
let ids = '';
let drg = evt.from.children;
drg.forEach((item, index) => {
if (index === drg.length - 1) {
ids += `${item.getAttribute('drag-id')}`;
} else {
ids += `${item.getAttribute('drag-id')},`;
}
});
setFlowIDs(ids);
},
});
}
};
// 提交表单
const onSubmit = () => {
flowReOrder({ flowIDs }).then(res => {
if (res.code === 0) {
notification.success({
message: '提示',
duration: 3,
description: '保存成功',
});
submitCallBack();
} else {
notification.error({
message: '提示',
duration: 3,
description: res.msg,
});
}
});
};
return (
<Modal
title="调整顺序"
visible={visible}
onOk={onSubmit}
onCancel={handleCancel}
maskClosable={false}
destroyOnClose
>
<div className={styles.doctorTable}>
<table>
<tbody id="doctor-drag-items">
{orderTable && orderTable.length > 0 ? (
orderTable.map(item => (
<tr
drag-id={item.extendID}
key={item.extendID}
style={{ cursor: 'move' }}
>
<td>
<span title={item.name}>{item.name}</span>
</td>
</tr>
))
) : (
<tr>
<td colSpan="10" style={{ textAlign: 'center' }}>
暂无数据
</td>
</tr>
)}
</tbody>
</table>
</div>
</Modal>
);
};
export default Order;
import React, { useEffect } from 'react';
import { CMFlowGet, CMFlowPost } from '@/services/platform/flow';
import { Form, Modal, Input, Radio, Select, notification } from 'antd';
const { Option } = Select;
const { TextArea } = Input;
const ProcessConfig = props => {
const { onSubumit, handleCancel, visible, processMsg } = props;
const [form] = Form.useForm();
useEffect(() => {
if (visible) {
getFormData();
}
}, [visible]);
// 获取表单回显
const getFormData = () => {
CMFlowGet({ flowId: processMsg.ID }).then(res => {
if (res.code === 0) {
form.setFieldsValue(res.data);
}
});
};
// 提交表单
const onFinish = () => {
form.validateFields().then(validate => {
if (validate) {
console.log(validate);
CMFlowPost({ ...validate, flowId: processMsg.ID })
.then(res => {
if (res.code === 0) {
notification.success({
message: '提示',
duration: 3,
description: '编辑成功',
});
onSubumit();
} else {
notification.error({
message: '提示',
duration: 3,
description: res.msg,
});
}
})
.catch(() => {
notification.error({
message: '提示',
duration: 3,
description: '网络异常',
});
});
}
});
};
return (
<Modal
title="流程配置"
visible={visible}
onOk={onFinish}
onCancel={handleCancel}
maskClosable={false}
>
<Form
form={form}
labelCol={{ span: 5 }}
wrapperCol={{ span: 18 }}
initialValues={{ remember: true }}
>
<Form.Item label="流程名称" name="name">
<Input disabled />
</Form.Item>
<Form.Item label="流程结束" name="flowEndBehavior">
<Radio.Group>
<Radio value={0}>不做任何事情</Radio>
<Radio value={1}>直接关闭事件</Radio>
<Radio value={2}>事件转为待审核</Radio>
<Radio value={3}>重新处理事件</Radio>
</Radio.Group>
</Form.Item>
<Form.Item label="前端页面" name="webPage">
<Select>
<Option value="多表显示">多表显示</Option>
<Option value="多表在办显示">多表在办显示</Option>
<Option value="表堆叠显示">表堆叠显示</Option>
<Option value="分派节点显示">分派节点显示</Option>
</Select>
</Form.Item>
<Form.Item label="编码样式" name="coding12Checked">
<Radio.Group>
<Radio value={false}>GIS-2021-0000001 (前缀长度 + 13 位)</Radio>
<Radio value>GIS000000001 (始终 12 位)</Radio>
</Radio.Group>
</Form.Item>
<Form.Item label="接口配置" name="interfaceConfig">
<TextArea />
</Form.Item>
</Form>
</Modal>
);
};
export default ProcessConfig;
import React, { useEffect, useState } from 'react';
import { useHistory } from 'react-router-dom';
import {
reloadFlowNodes,
removeFlowNodeExtend,
} from '@/services/platform/flow';
import {
Space,
Table,
Popconfirm,
Tooltip,
notification,
message,
Button,
} from 'antd';
import {
RollbackOutlined,
EditTwoTone,
FontColorsOutlined,
DeleteOutlined,
} from '@ant-design/icons';
import NodeEdit from './flowNodeComponents/NodeEdit';
import styles from './flowNode.less';
const FlowNode = () => {
const history = useHistory();
const { flowName, pickItemIndex } = history.location.state;
const [visible, setVisible] = useState({
nodeEdit: false,
}); // 弹窗显示
const [tableData, setTableData] = useState([]); // 流程对应的回显的表格
const [expandedRowKeys, setExpandedRowKeys] = useState([]); // 开开的表格的key
const [nodeMsg, setNodeMsg] = useState(); // 保存节点信息
useEffect(() => {
getData();
}, []);
// 弹窗显示控制
const showModal = (key, value) => {
setVisible({ ...visible, [key]: value });
};
// 获取数据
const getData = () => {
reloadFlowNodes({ flowName }).then(res => {
if (res.code === 0) {
setTableData(res.data);
// 存入需要展开得节点
setExpandedRowKeys(res.data.map(item => item.GroupName));
}
});
};
// 清除节点
const delNode = record => {
removeFlowNodeExtend({ flowNodeExtendID: record.flowID })
.then(res => {
if (res.code === 0) {
notification.success({
message: '提示',
duration: 3,
description: '清除成功',
});
} else {
notification.error({
message: '提示',
duration: 3,
description: res.msg,
});
}
})
.catch(() => {
notification.error({
message: '提示',
duration: 3,
description: '网络异常',
});
});
};
// 控制表格的展开跟收起
const onUnfold = (expanded, record) => {
const data = [...expandedRowKeys];
let index = data.indexOf(record);
if (expanded) {
data.push(record.GroupName);
} else {
data.splice(index, 1);
}
setExpandedRowKeys(data);
};
// 定义展开的表格
const createUnfoldTable = itemTable => {
const columns = [
{
title: '节点名称',
dataIndex: 'name',
width: 149,
align: 'left',
render: text => (
<div
style={{ paddingLeft: 60 }}
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{ __html: text }}
/>
),
},
{
title: '节点别名',
dataIndex: 'NodeAliasName',
align: 'center',
width: 80,
render: text => (
// eslint-disable-next-line react/no-danger
<span dangerouslySetInnerHTML={{ __html: text }} />
),
},
{
title: '移交方式',
dataIndex: 'extendHandover',
align: 'center',
width: 80,
render: text => (
// eslint-disable-next-line react/no-danger
<span dangerouslySetInnerHTML={{ __html: text }} />
),
},
{
title: '节点类型',
dataIndex: 'extendNodeType',
align: 'center',
width: 80,
render: text => (
// eslint-disable-next-line react/no-danger
<span dangerouslySetInnerHTML={{ __html: text }} />
),
},
{
title: '工单主表',
dataIndex: 'extendTableName',
width: 150,
align: 'center',
render: text => (
// eslint-disable-next-line react/no-danger
<span dangerouslySetInnerHTML={{ __html: text }} />
),
},
{
title: '查看字段',
dataIndex: 'extendSeeFields',
align: 'center',
width: 80,
},
{
title: '字段',
dataIndex: 'extendFields',
align: 'center',
width: 80,
render: text => (
// eslint-disable-next-line react/no-danger
<span dangerouslySetInnerHTML={{ __html: text }} />
),
},
{
title: '补正',
dataIndex: 'extendEditableLater',
align: 'center',
width: 80,
render: text => (
// eslint-disable-next-line react/no-danger
<span dangerouslySetInnerHTML={{ __html: text }} />
),
},
{
title: '可退',
dataIndex: 'extendRollbackable',
align: 'center',
width: 80,
render: text => (
// eslint-disable-next-line react/no-danger
<span dangerouslySetInnerHTML={{ __html: text }} />
),
},
{
title: '退至',
dataIndex: 'extendRollbackNode',
align: 'center',
width: 80,
render: text => (
// eslint-disable-next-line react/no-danger
<span dangerouslySetInnerHTML={{ __html: text }} />
),
},
{
title: '评级移交',
dataIndex: 'tranferable',
align: 'center',
width: 80,
render: text => (
// eslint-disable-next-line react/no-danger
<span dangerouslySetInnerHTML={{ __html: text }} />
),
},
{
title: '显示事件信息',
dataIndex: 'eventInformation',
align: 'center',
width: 80,
render: text => (
// eslint-disable-next-line react/no-danger
<span dangerouslySetInnerHTML={{ __html: text }} />
),
},
{
title: '操作',
align: 'center',
ellipsis: true,
width: 150,
render: record => (
<>
<Space>
<Tooltip title="修改节点">
<EditTwoTone
onClick={() => {
showModal('nodeEdit', true);
setNodeMsg(record);
}}
style={{ fontSize: '16px', color: '#1890FF' }}
/>
</Tooltip>
<Tooltip title="节点辅助视图">
<FontColorsOutlined
// onClick={() => toNode(record.name)}
style={{ fontSize: '16px', color: '#1890FF' }}
/>
</Tooltip>
<Tooltip title="清除节点配置">
<Popconfirm
title="是否清除该节点配置?"
onConfirm={() => delNode(record)}
onCancel={() => message.error('取消清除')}
okText="是"
cancelText="否"
>
<DeleteOutlined
style={{ fontSize: '16px', color: '#e86060' }}
/>
</Popconfirm>
</Tooltip>
</Space>
</>
),
},
];
return (
<Table
className={styles.unfoldTable}
rowKey={record => record.ID}
columns={columns}
bordered
size="small"
showHeader={false}
dataSource={itemTable}
pagination={false}
onRow={record => ({
onDoubleClick: () => {
showModal('nodeEdit', true);
setNodeMsg(record);
},
})}
/>
);
};
// 返回
const backFlow = () => {
history.push({
pathname: '/platformCenter/bsmanger/flow',
state: { pickItemIndex },
});
};
// 定义表格
const columns = [
{
title: '节点名称',
dataIndex: 'GroupName',
width: 100,
align: 'left',
render: (text, record) => (
<a style={{ fontWeight: 'bold' }}>
{text}({record.Items.length ? record.Items.length : 0}个)
</a>
),
},
{
title: '节点别名',
align: 'center',
width: 80,
},
{
title: '移交方式',
align: 'center',
width: 80,
},
{
title: '节点类型',
align: 'center',
width: 80,
},
{
title: '工单主表',
align: 'center',
width: 150,
},
{
title: '查看字段',
width: 80,
align: 'center',
},
{
title: '字段',
align: 'center',
width: 80,
},
{
title: '补正',
align: 'center',
width: 80,
},
{
title: '可退',
align: 'center',
width: 80,
},
{
title: '退至',
align: 'center',
width: 80,
},
{
title: '评级移交',
align: 'center',
width: 80,
},
{
title: '显示事件信息',
align: 'center',
width: 80,
},
{
title: '操作',
align: 'center',
width: 150,
},
];
return (
<div className={styles.NodeContent}>
<div className={styles.header}>
<div className={styles.nodeTitle}>{flowName}</div>
<div className={styles.buttonBox}>
<Button type="primary" onClick={() => backFlow()}>
<RollbackOutlined />
返回
</Button>
</div>
</div>
<Table
dataSource={tableData}
columns={columns}
rowKey={record => record.GroupName}
size="small"
showHeader
scroll={{ y: '100vh-150px' }}
expandable={{
expandedRowRender: record => createUnfoldTable(record.Items),
}}
expandedRowKeys={expandedRowKeys}
onExpand={onUnfold}
pagination={false}
/>
<NodeEdit
visible={visible.nodeEdit}
msg={nodeMsg}
handleCancel={() => showModal('nodeEdit', false)}
onSubumit={() => {
showModal('nodeEdit', false);
getData();
}}
/>
</div>
);
};
export default FlowNode;
// 节点配置
.NodeContent {
position: relative;
width: 100%;
height: calc(100vh - 74px);
min-width: 800px;
background: white;
.header {
display: flex;
justify-content: space-between;
height: 50px;
line-height: 50px;
.nodeTitle {
font-size: 18px;
color: #0072ff;
font-weight: bold;
margin-left: 10px;
}
.buttonBox {
margin-right: 10px;
.ant-btn {
vertical-align: middle;
line-height: 1px;
}
}
}
.ant-table-pagination {
padding-right: 12px;
background: white;
margin: 1px 0;
padding: 8px;
padding-right: 20px;
}
.ant-table-thead tr th {
font-weight: 600;
color: rgba(0, 0, 0, 0.85);
}
.ant-table-cell {
// text-align: center;
overflow: hidden;
white-space: nowrap;
}
.ant-table-body {
height: calc(100vh - 160px);
border-right: white;
overflow: auto !important;
}
.ant-pagination {
z-index: 999;
border-top: 1px solid #f0eded;
}
.unfoldTable {
.ant-table {
margin-left: -9px !important;
}
}
}
// 编辑节点表单
.formData {
height: 32rem;
overflow-y: scroll;
.filedListItem {
display: flex;
flex-wrap: nowrap;
justify-content: space-between;
width: 100%;
.ant-btn-icon-only {
display: flex;
align-items: center;
justify-content: center;
width: 82px;
margin-left: 10px;
}
}
}
// 字段集选择
.fieldContent {
display: flex;
.willSelectBox {
width: 50%;
height: 600px;
overflow-y: scroll;
padding: 8px;
border-right: 1px solid rgb(153, 187, 232);
box-sizing: border-box;
.cardContent {
height: 530px;
overflow-y: scroll;
.cardBox {
padding: 10px;
margin-bottom: 10px;
border: 1px solid #b5b8c8;
box-sizing: border-box;
}
}
}
.hasSelectBox {
width: 50%;
height: 600px;
overflow-y: scroll;
padding: 8px 8px 8px 12px;
box-sizing: border-box;
.doctorTable {
margin-bottom: 16px;
table {
width: 100%;
td {
padding: 6px;
border: 1px solid #e8e8e8;
}
thead {
tr {
font-weight: 600;
background: #fafafa;
}
td {
width: 12rem;
}
}
tbody {
tr:hover {
background-color: #ededed;
}
}
}
}
}
.header {
margin: 0px 0px 10px;
background-color: rgb(223, 232, 246);
.headDivider {
margin-bottom: 10px;
background-color: #dfe8f6;
}
}
.cardDivider {
margin-bottom: 10px;
font-weight: 700;
color: #15428b;
border-top-color: #99bbe8;
}
}
import React, { useEffect, useState } from 'react';
import {
getFlowNode,
loadRollbackNodes,
loadEventTypeTable,
loadEventFields,
loadFeedbackType,
editFlowNodeExtend,
} from '@/services/platform/flow';
import {
Form,
Modal,
Input,
Radio,
Select,
notification,
Checkbox,
Button,
} from 'antd';
import { PlusOutlined } from '@ant-design/icons';
import Fieldselection from './nodeEditComponents/Fieldselection';
import styles from '../flowNode.less';
const { Option } = Select;
const NodeEdit = props => {
const { onSubumit, handleCancel, visible, msg } = props;
const [fieldList, setFieldList] = useState([]); // 当前选择库字段列表
const [showField, setShowField] = useState(false); // 选择字段弹窗
const [fieldName, setFieldName] = useState(); // 编辑的字段
const [backNodes, setBackNodes] = useState([]); // 允许返回的节点
const [backType, setBackType] = useState([]); // 反馈类型
const [eventTable, setEventTable] = useState([]); // 表名
const [isDisable, setIsDisable] = useState(); // 允许回退是否可选择
const [form] = Form.useForm();
useEffect(() => {
if (visible) {
// 获取表单回显
getFormData();
// 获取返回步骤
rollBackNodes();
// 获取表名
getTableName();
// 获取反馈类型
getFeedbackName();
}
}, [visible]);
// 获取表单回显
const getFormData = () => {
getFlowNode({ flowNodeId: msg.ID }).then(res => {
if (res.code === 0) {
let obj = {
...res.data.Extend,
FlowName: res.data.FlowName,
};
if (res.data.Extend.Rollbackable) {
setIsDisable(false);
} else {
setIsDisable(true);
}
form.setFieldsValue(obj);
}
});
};
// 获取反馈类型
const getFeedbackName = () => {
loadFeedbackType().then(res => {
if (res.code === 0) {
setBackType(res.data);
}
});
};
// 获取表名
const getTableName = () => {
loadEventTypeTable({ flowNodeId: msg.ID }).then(res => {
if (res.code === 0) {
setEventTable(res.data);
}
});
};
// 加载修改流程节点配置允许退回列表
const rollBackNodes = () => {
loadRollbackNodes({ flowNodeId: msg.ID }).then(res => {
if (res.code === 0) {
setBackNodes(res.data);
}
});
};
// 字段配置
const deployField = val => {
setFieldName(val);
form.validateFields().then(value => {
loadEventFields({ eventTableName: value.TableName }).then(res => {
if (res.code === 0) {
let defaultCheckedList = value[val].split(',');
// 处理数据为树形结构
let keylist = new Set();
let list = new Map();
res.data.forEach(item => {
keylist.add(item.group);
if (keylist.has(item.group)) {
let listItem = list.get(item.group);
// 存入check得选项,是否全选,选中的选项'
if (listItem) {
list.set(item.group, {
plainOptions: [...listItem.plainOptions, item.fieldName],
defaultCheckedList: [],
});
} else {
list.set(item.group, {
plainOptions: [item.fieldName],
defaultCheckedList: [],
});
}
}
});
let checkList = [...list];
defaultCheckedList.forEach(item => {
checkList.forEach(element => {
// 当前得模块是否有当前字段
let indeterminate = element[1].plainOptions.some(
checkName => checkName === item,
);
// 处理已选中的字段
if (indeterminate) {
element[1].defaultCheckedList.push(item);
}
if (
element[1].defaultCheckedList.length > 0 &&
element[1].defaultCheckedList.length <
element[1].plainOptions.length
) {
element[1].indeterminate = true;
} else {
element[1].indeterminate = false;
}
// 处理是否全选字段
if (
element[1].defaultCheckedList.length ===
element[1].plainOptions.length
) {
element[1].checkAll = true;
} else {
element[1].checkAll = false;
}
});
});
setFieldList(checkList);
setTimeout(() => {
setShowField(true);
}, 0);
}
});
});
};
// 字段修改后回调函数
const setFiled = val => {
let Fields = '';
val.forEach((item, index) => {
if (index === val.length - 1) {
Fields = `${Fields + item}`;
} else {
Fields = `${Fields + item},`;
}
});
let obj = {};
obj[fieldName] = Fields;
form.setFieldsValue(obj);
setShowField(false);
};
// 提交表单
const onFinish = () => {
form.validateFields().then(validate => {
if (validate) {
editFlowNodeExtend({ ...validate, flowNodeId: msg.ID })
.then(res => {
if (res.code === 0) {
notification.success({
message: '提示',
duration: 3,
description: '编辑成功',
});
onSubumit();
} else {
notification.error({
message: '提示',
duration: 3,
description: res.msg,
});
}
})
.catch(() => {
notification.error({
message: '提示',
duration: 3,
description: '网络异常',
});
});
}
});
};
// 表单监听
const onValuesChange = val => {
if (Object.keys(val)[0] === 'Rollbackable') {
if (val.Rollbackable) {
setIsDisable(false);
} else {
setIsDisable(true);
}
}
};
return (
<Modal
title="流程节点配置"
visible={visible}
onOk={onFinish}
width="800px"
onCancel={handleCancel}
maskClosable={false}
centered
>
<Form
form={form}
labelCol={{ span: 5 }}
wrapperCol={{ span: 18 }}
initialValues={{ remember: true }}
className={styles.formData}
onValuesChange={onValuesChange}
>
<Form.Item label="流程节点" name="FlowName">
<Input disabled />
</Form.Item>
<Form.Item label="节点别名" name="NodeAliasName">
<Input />
</Form.Item>
<Form.Item label="节点类型">
<Form.Item name="NodeType" style={{ marginBottom: '10px' }}>
<Select>
<Option value="办理">办理</Option>
<Option value="上报">上报</Option>
<Option value="分派">分派</Option>
<Option value="审核">审核</Option>
<Option value="办理关单">办理关单</Option>
</Select>
</Form.Item>
<Form.Item
name="EditableLater"
valuePropName="checked"
style={{ marginBottom: 0 }}
>
<Checkbox>允许补正(事后修改)</Checkbox>
</Form.Item>
<div style={{ display: 'flex' }}>
<Form.Item
name="Rollbackable"
valuePropName="checked"
style={{ marginBottom: 0, width: '150px' }}
>
<Checkbox>允许回退至</Checkbox>
</Form.Item>
<Form.Item
name="RollbackNode"
style={{ marginBottom: 0, width: '100%' }}
>
<Select disabled={isDisable}>
{backNodes.map(item => (
<Option value={item.Name} key={item.ID}>
{item.Name}
</Option>
))}
</Select>
</Form.Item>
</div>
</Form.Item>
<Form.Item label="移交方式" name="Handover">
<Select>
<Option value="移交选择人">移交选择人</Option>
<Option value="自处理">自处理</Option>
<Option value="自处理或者移交选择人">自处理或者移交选择人</Option>
<Option value="移交默认人">移交默认人</Option>
<Option value="跨站移交">跨站移交</Option>
<Option value="处理站点移交">处理站点移交</Option>
<Option value="本人站点移交">本人站点移交</Option>
<Option value="移交上报人">移交上报人</Option>
</Select>
</Form.Item>
<Form.Item label="平级移交" name="Transferable">
<Radio.Group>
<Radio value="0"></Radio>
<Radio value="1"></Radio>
</Radio.Group>
</Form.Item>
<Form.Item label="显示事件信息" name="EventsInformation">
<Radio.Group>
<Radio value="0"></Radio>
<Radio value="1"></Radio>
</Radio.Group>
</Form.Item>
<Form.Item label="工单主表" name="TableName">
<Select>
{eventTable.map(item => (
<Option value={item.Name} key={item.ID}>
{item.Name}
</Option>
))}
</Select>
</Form.Item>
<Form.Item label="字段编辑">
<div className={styles.filedListItem}>
<Form.Item name="Fields" style={{ marginBottom: 0, width: '100%' }}>
<Input placeholder="请选编辑字段" />
</Form.Item>
<Button
type="dashed"
icon={<PlusOutlined />}
onClick={() => {
deployField('Fields');
}}
/>
</div>
</Form.Item>
<Form.Item label="查看字段(工程模型)">
<div className={styles.filedListItem}>
<Form.Item
name="SeeFields"
style={{ marginBottom: 0, width: '100%' }}
>
<Input placeholder="请选择查看字段" />
</Form.Item>
<Button
type="dashed"
icon={<PlusOutlined />}
onClick={() => {
deployField('SeeFields');
}}
/>
</div>
</Form.Item>
<Form.Item label="前端视图" name="webPage">
<Input placeholder="请配置前端视图" />
</Form.Item>
<Form.Item label="手持视图" name="MobilePage">
<Input placeholder="请配置手持视图" />
</Form.Item>
<Form.Item label="视图参数" name="PageParam">
<Input placeholder="请配置视图参数" />
</Form.Item>
<Form.Item label="反馈类型" name="FeedbackName">
<Select>
{backType.map(item => (
<Option value={item.value} key={item.value}>
{item.value}
</Option>
))}
</Select>
</Form.Item>
<Form.Item
name="FeedbackToEvent"
valuePropName="checked"
wrapperCol={{ offset: 5, span: 18 }}
>
<Checkbox>将反馈信息显示到事件级别</Checkbox>
</Form.Item>
</Form>
{/* 字段集选择 */}
<Fieldselection
visible={showField}
handleCancel={() => setShowField(false)}
fieldList={fieldList}
onSubumit={val => setFiled(val)}
/>
</Modal>
);
};
export default NodeEdit;
import React, { useEffect, useState } from 'react';
import Sortable from 'sortablejs';
import { Modal, Divider, Checkbox } from 'antd';
import styles from '../../flowNode.less';
const CheckboxGroup = Checkbox.Group;
const Fieldselection = props => {
const { onSubumit, handleCancel, visible, fieldList } = props;
const [checkList, setCheckList] = useState([]);
const [selectList, setSelectList] = useState([]); // 选中字段列表
useEffect(() => {
if (visible) {
setCheckList(fieldList);
}
}, [visible]);
useEffect(() => {
let arr = [];
if (checkList.length < 0) {
return;
}
checkList.forEach(element => {
arr = [...arr, ...element[1].defaultCheckedList];
});
setSelectList(arr);
// 初始化拖拽
setTimeout(() => {
dragSort();
}, 0);
console.log(arr);
}, [checkList]);
// 提交表单
const onFinish = () => {
console.log(selectList, '子组件');
onSubumit(selectList);
};
// 复选框
const onChange = (list, index) => {
setCheckList(value => {
const chooseList = JSON.parse(JSON.stringify(value));
chooseList[index][1].defaultCheckedList = list;
chooseList[index][1].indeterminate =
!!list.length && list.length < chooseList[index][1].plainOptions.length;
chooseList[index][1].checkAll =
list.length === chooseList[index][1].plainOptions.length;
return chooseList;
});
};
// 全选
const onCheckAllChange = (e, index) => {
console.log(e, 'eeeee');
setCheckList(value => {
const chooseList = JSON.parse(JSON.stringify(value));
chooseList[index][1].defaultCheckedList = e.target.checked
? chooseList[index][1].plainOptions
: [];
chooseList[index][1].indeterminate = false;
chooseList[index][1].checkAll = e.target.checked;
return chooseList;
});
};
// 初始化排序
const dragSort = () => {
let el = document.getElementById('doctor-drag-items');
if (el) {
Sortable.create(el, {
animation: 100, // 动画参数
onEnd(evt) {
// 拖拽完毕之后发生,只需关注该事件
let arr = [];
let len = evt.from.children;
len.forEach(item => {
arr.push(item.getAttribute('drag-id'));
});
setSelectList(arr);
},
});
}
};
return (
<Modal
title="流程节点配置"
visible={visible}
onOk={onFinish}
width="700px"
onCancel={handleCancel}
maskClosable={false}
destroyOnClose
centered
>
<div className={styles.fieldContent}>
{/* 待选字段列表 */}
<div className={styles.willSelectBox}>
<div className={styles.header}>
<Divider orientation="left" className={styles.headDivider}>
待选字段列表
</Divider>
</div>
<div className={styles.cardContent}>
{checkList.map((item, index) => (
<div className={styles.cardBox} key={index}>
<div className={styles.title}>
<Divider orientation="left" className={styles.cardDivider}>
<span style={{ marginRight: '10px' }}>{item[0]}</span>
<Checkbox
indeterminate={item[1].indeterminate}
onChange={e => onCheckAllChange(e, index)}
checked={item[1].checkAll}
/>
</Divider>
</div>
<div className={styles.filedList}>
<CheckboxGroup
key={index}
options={item[1].plainOptions}
value={item[1].defaultCheckedList}
onChange={list => onChange(list, index)}
/>
</div>
</div>
))}
</div>
</div>
{/* 已选字段列表 */}
<div className={styles.hasSelectBox}>
<div className={styles.header}>
<Divider orientation="left" className={styles.headDivider}>
已选字段列表
</Divider>
</div>
<div className={styles.doctorTable}>
<table>
<thead>
<tr>
<td>字段名</td>
</tr>
</thead>
<tbody id="doctor-drag-items">
{selectList && selectList.length > 0 ? (
selectList.map((item, index) => (
<tr drag-id={item} key={index} style={{ cursor: 'move' }}>
<td>
<span title={item}>{item}</span>
</td>
</tr>
))
) : (
<tr>
<td colSpan="10" style={{ textAlign: 'center' }}>
暂无数据
</td>
</tr>
)}
</tbody>
</table>
</div>
</div>
</div>
</Modal>
);
};
export default Fieldselection;
......@@ -47,11 +47,12 @@ import DimensionsConfig from '@/pages/platformCenter/dimensionsConfig/dimensions
import TaskScheduling from '@/pages/artificial/taskScheduling/taskScheduling';
import PoliciesIssued from '@/pages/artificial/policiesIssued/policiesIssued';
import AuthControl from '@/pages/authcontrol';
import TableManager from '@/pages/platformCenter/bsmanager/tablemanager'
import StandingBook from '@/pages/platformCenter/standingBook/standingBook'
import FiledConfig from '@/pages/platformCenter/filedConfig/filedConfig'
import TableManager from '@/pages/platformCenter/bsmanager/tablemanager';
import StandingBook from '@/pages/platformCenter/standingBook/standingBook';
import FiledConfig from '@/pages/platformCenter/filedConfig/filedConfig';
import Incident from '@/pages/platformCenter/bsmanager/workOrder/incident';
import Flow from '@/pages/platformCenter/bsmanager/workOrder/flow';
import Flow from '@/pages/platformCenter/bsmanager/workFlow/flow';
import FlowNode from '@/pages/platformCenter/bsmanager/workFlow/flowNode/flowNode';
// import ColConen from '@/components/Colophon/colContent';
const iconStyle = { verticalAlign: '0.125em' };
......@@ -288,12 +289,17 @@ export default {
name: '事件',
component: Incident,
},
{
path: '/platformCenter/bsmanger/flow',
name: '流程',
component: Flow,
},
{
path: '/platformCenter/bsmanger/flowNode',
name: '流程节点',
hideMenu: true,
component: FlowNode,
},
// {
// path: '/platformCenter/bsmanger/standbookmanager',
// name: '台账配置',
......@@ -305,7 +311,7 @@ export default {
path: '/platformCenter/video',
name: '视频平台',
component: VideoManager,
}
},
],
},
{
......@@ -346,7 +352,7 @@ export default {
path: '/dataCenter/dictionary1',
name: '数据字典',
component: Dictionary1,
}
},
// {
// path: '/dataCenter/video',
// name: '视频管理',
......
import { get, post, PUBLISH_SERVICE } from '@/services/index';
// 工单流程列表查询
export const reloadFlows = param =>
get(`${PUBLISH_SERVICE}/WorkOrderCenter/CM_Flow_ReloadFlows`, param);
// 流程信息查询
export const CMFlowGet = param =>
get(`${PUBLISH_SERVICE}/WorkOrderCenter/CM_Flow/${param.flowId}`);
// 流程信息查询
export const CMFlowPost = param =>
post(`${PUBLISH_SERVICE}/WorkOrderCenter/CM_Flow/${param.flowId}`, param);
// 工单流程组内调序
export const flowReOrder = param =>
post(
`${PUBLISH_SERVICE}/WorkOrderCenter/CM_Flow_ReOrder?flowIDs=${
param.flowIDs
}`,
);
// 工单流程组内调序
export const removeFlowExtend = param =>
post(
`${PUBLISH_SERVICE}/WorkOrderCenter/CM_Flow_RemoveFlowExtend?flowIDs=${
param.flowIDs
}`,
);
// 流程节点列表查询
export const reloadFlowNodes = param =>
get(
`${PUBLISH_SERVICE}/WorkOrderCenter/CM_Event_ReloadFlowNodes?flowName=${
param.flowName
}`,
);
// 清除节点配置
export const removeFlowNodeExtend = param =>
get(
`${PUBLISH_SERVICE}/WorkOrderCenter/CM_Event_RemoveFlowNodeExtend?flowNodeExtendID=${
param.flowNodeExtendID
}`,
);
// 流程节点详情
export const getFlowNode = param =>
get(
`${PUBLISH_SERVICE}/WorkOrderCenter/CM_Event_GetFlowNode?flowNodeId=${
param.flowNodeId
}`,
);
// 流程节点详情
export const loadRollbackNodes = param =>
get(
`${PUBLISH_SERVICE}/WorkOrderCenter/CM_Event_LoadRollbackNodes?flowNodeId=${
param.flowNodeId
}`,
);
// 加载事件主表
export const loadEventTypeTable = query =>
get(`${PUBLISH_SERVICE}/WorkOrderCenter/CM_Event_LoadTables`, query);
// 根据触发事件加载字段
export const loadEventFields = query =>
get(`${PUBLISH_SERVICE}/WorkOrderCenter/CM_Feedback_LoadEventFields`, query);
// 加载反馈类型
export const loadFeedbackType = query =>
get(`${PUBLISH_SERVICE}/WorkOrderCenter/CM_Feedback_LoadFeedbackType`, query);
// 加载反馈类型
export const editFlowNodeExtend = query =>
post(`${PUBLISH_SERVICE}/WorkOrderCenter/CM_Event_EditFlowNodeExtend`, query);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment