提交 5e75fe20 authored 作者: 钟是志's avatar 钟是志

将流程详情页面搬入iframe

上级 d7644a83
/**
* @file 加签人列表展示
*/
import React, { Component } from 'react';
import styles from './styles.less';
import { Tag } from 'antd';
export default class ChildTaskModel extends Component {
constructor(props) {
super(props);
this.state = {
isShow: false,
};
}
/**
* @function 加签展开状态
* @event click
*/
onStatusClick = () => {
this.setState({
isShow: !this.state.isShow,
});
};
render() {
const { isShow } = this.state;
const { data } = this.props;
return (
<>
<div className={styles.title_div}>
<span className={styles.left_title_span}>加签人:</span>
<a onClick={this.onStatusClick} className={styles.right_title_span}>
{isShow ? '收起' : '展开'}
</a>
</div>
{isShow && data && Array.isArray(data) ? (
<div className={styles.ani_div}>
{data.map((item, index) => {
return (
<div className={styles.card_div} key={index}>
<div>
加签人: <Tag color="#f50">{item.assignee}</Tag>
</div>
<div>审批状态: {item.status}</div>
{item.taskVariable && item.taskVariable.reason && (
<div>审批原因: {item.taskVariable.reason}</div>
)}
</div>
);
})}
</div>
) : null}
</>
);
}
}
/**
* 徐立
* 2019年9月19日
* 查看详情页面
*/
import React, { Component, Fragment } from 'react';
import {
Row,
Col,
Timeline,
Icon,
Form,
Button,
Spin,
Radio,
Popconfirm,
Checkbox,
Switch,
InputNumber,
message,
} from 'antd';
import Card from './components/Card';
import { getToken } from '@/webPublic/one_stop_public/utils/token';
import { connect } from 'dva';
import { isEmpty } from 'lodash';
import { openToast } from './components/Notification';
import PortalFlowExamineModal from '@/pages/Portal/components/FlowExamineModal';
import BtnOk from '@/webPublic/one_stop_public/AffairButton/AuditButton/userTable';
import ZdyTable from '@/webPublic/one_stop_public/Table';
import moment from 'moment';
import SVG from './components/SVG';
import TrunToModel from './components/trunToModel';
import router from 'umi/router';
import { permRequest } from '@/webPublic/one_stop_public/utils/request';
import styles from './styles.less';
import TrunToDetail from './trunToDetail';
import Countersign from './components/Countersign';
import ChildTaskModel from './ChildTaskModel';
import { checkNeedFormValidateFieldsAndScroll, must, submitValues } from './splitDetailSplit';
import { queryApiVersion, queryApiActionPath } from '@/webPublic/one_stop_public/utils/queryConfig';
import { isJSON } from '@/webPublic/zyd_public/utils/utils';
@Form.create()
@connect()
export default class GetDetail extends Component {
constructor() {
super();
this.state = {
isTakeFlow: false,
data: {}, // 详情数据
stepFlow: [],
items: [],
obj: {},
isSecond: false, // 如果为true,表示重新发起
selects: new Map(),
left: 0,
top: 0,
max: 4,
width: 100,
taskId: '', // 模型id
appId: '', // 事务id
code: '', // 事务code 当前表单唯一值
isHandle: false, // 判断用户是否有权限
id: '', // 表单id
btns: [], // 自定义按钮
taskFormKey: '', // 多表单显示的key
itemsOK: [], // 多表单显示的表单
hisTaskFormKeys: {}, // 历史任务相关
isLoading: false, // 请求状态
formColor: '', // 流程紧急度颜色
formLevel: '', // 流程文本
btnList: [], // 紧急度按钮返回数据
radiovalue: '', // 单选id
isEnd: false, // 是否结束
isShowTitle: true, // 是否展示流程步骤几个字
isSumbitLoading: false, // 发起时触发
isOpenTrunToModel: false, // 用户转办,回收弹框控制变量
trunToStatus: '转办', // 当前节点存在状态
trunData: '', // 转办当前选中数据
isCloseUserDetail: false, // 是否展示用户基础详细信息
checkedConfimList: [], // 用户选择打印元素
checkListOptions: [], // 历史表单复选框存放值
isShowTitleTwo: true, // 历史表单展示状态
paddingBottom: 0,
isSign: false, // 是否使用签名
userInfo: '', // 得到用户数据
setData: '', // 配置的数据
countersignModal: '', // 开启加签弹框函数
nextAuditInfo: {}, // 最新的节点的审核人信息
isAllPrint: false,
};
window.callbackSubmitInfoZhiYong = undefined;
}
/**
* @function 同步加签函数
* @param { function } func 打开加签弹框函数
*/
updateCountersignModal = func => {
this.setState({
countersignModal: func,
});
};
/**
* 关闭转办,回收弹框
*/
handleTrunToModel = () => {
this.setState({
isOpenTrunToModel: false,
trunData: '',
trunToStatus: '',
});
};
/**
* 打开转办,回收弹框
* @param { string } text 当前按钮状态
*/
showTrunToModel = (text, record) => {
this.setState({
isOpenTrunToModel: true,
trunToStatus: text,
trunData: record,
});
};
examineFlow = (...ags) => {
this.flowExamineModal.showModal(...ags);
};
componentDidMount() {
this.getInit();
if (this.props.onRef) {
this.props.onRef(this);
}
}
/**
* @function 默认请求
*/
getInit = handleUser => {
const { dispatch } = this.props;
const id = this.props.history.location.state && this.props.history.location.state.id;
const code = this.props.history.location.state && this.props.history.location.state.code;
const queryId = this.props.history.location.query && this.props.history.location.query.id;
const taskId = this.props.history.location.state && this.props.history.location.state.taskId;
if (!id) {
if (queryId) {
} else {
openToast('error', '数据已过期', '当前页面数据已过期,请重新进入');
router.push('/portal/home');
return;
}
}
dispatch({
type: 'affair/getIdFormDetail',
payload: {
id: queryId ? queryId : id, // 审批表Id
code: code || null, // 表单值
handleUser: handleUser || null, // 处理人
taskId, // 多任务流程会使用到,后续改为必须传入
},
callback: val => {
if (this.props.changeData) {
this.props.changeData(val);
}
const checkListOptions = [];
const checkedConfimList = [];
if (val.hisTaskForm.formKeys) {
val.hisTaskForm.formKeys.map(item => {
checkListOptions.push({
label: item.taskName,
value: item.formKey,
});
// checkedConfimList.push(item.formKey);
});
}
if (val.code) {
permRequest('/UnifiedAppFormApi/getAll', {
keyWords: val.code,
pageNo: 1,
pageSize: 10,
})
.then(res => {
if (res && res.rows && res.rows.length) {
let thisAuditData = res.rows[0];
if (thisAuditData?.nextUsers?.endsWith(',')) {
thisAuditData.nextUsers = thisAuditData.nextUsers.slice(0, -1);
}
this.setState({
nextAuditInfo: thisAuditData,
});
}
});
}
this.setState(
{
data: val,
stepFlow: val.taskInfo,
obj: JSON.parse(val.content),
code: val.code,
taskId: val.taskId,
isSecond: val.isSecond ? val.isSecond : false,
appId: val.appId,
code: val.code,
isHandle: val.isHandle,
id,
btns: val.btns,
taskFormKey: val.taskFormKey,
hisTaskFormKeys: val.hisTaskForm,
isLoading: true,
formColor: val.formColor,
formLevel: val.formLevel,
isEnd: val.isEnd,
checkListOptions,
checkedConfimList,
},
() => {
if (val.isSecond) {
this.props.dispatch({
type: 'urge/GetMyBtn',
payload: {},
callback: arr => {
this.setState({
btnList: arr,
radiovalue: val.formLevelId ? val.formLevelId : arr[arr.length - 1].id,
}, () => {
this.giveMessageTop();
});
},
});
} else {
this.giveMessageTop();
}
},
);
},
});
dispatch({
type: 'emailorphone/GetLogo',
payload: {
configKeys: ['isCloseUserDetail', 'isCloseFlowPath', 'isAllPrint'],
},
callback: val => {
this.setState({
isCloseUserDetail: !!(val[0] && val[0].configValue === 'true'),
});
if (val[1]?.configValue) {
sessionStorage.setItem(
'isCloseFlowPath',
val[1]?.configValue === 'true' ? JSON.stringify(true) : JSON.stringify(false),
);
}
if (val[2]?.configValue === 'true') {
this.setState({
isAllPrint: true,
});
}
},
});
if (getToken()) {
const user = localStorage.getItem('user');
if(user && isJSON(user)){
this.setState({
userInfo: JSON.parse(user),
});
}
}
/**
* 获取设置的数据
*/
this.props.dispatch({
type: 'UserSetCenterApi/queryUserSet',
payload: {},
callback: val => {
this.setState({
setData: val,
});
},
});
};
giveMessageTop = () => {
const isCg = this.props.history.location.state && this.props.history.location.state.isCg;
const fromIframe =
this.props.history.location.state && this.props.history.location.state.fromIframe;
if (fromIframe) {
const ifrmeTimeOut = setTimeout(() => {
const dom = document.getElementById('detailInfoDiv');
if (typeof dom.scrollHeight !== 'undefined') {
window.top.postMessage(`iframeDetailHeight-${dom.scrollHeight}`, '*');
}
clearTimeout(ifrmeTimeOut);
}, 2500);
}
};
/**
* @function 用户点击确认执行相应操作
* @description: 注意 用户点击状态时在点击动态配置按钮时进行了保存,并在该函数中最终提交给后端
* @param { string } oldkey 按钮状态
* @param { string } btnValue 按钮选中状态
* @param { string } value 审批理由
* @param { boolean } checked 加签状态
* @param { function } callback 回调函数
*/
affairOk = (oldkey, btnValue, value, checked, callback) => {
const { dispatch } = this.props;
const {
radiovalue,
isSecond,
userInfo,
setData,
data,
btns,
taskId,
code,
} = this.state;
const { handleUser } = this.props.history.location.state;
const isCloseFlowPath = sessionStorage.getItem('isCloseFlowPath')
? JSON.parse(sessionStorage.getItem('isCloseFlowPath'))
: false;
if (callback) {
callback();
}
let checkSumbitInfo = checkNeedFormValidateFieldsAndScroll({
btns,
btnValue,
});
const argumentsSubmitValue = {
isCloseFlowPath,
radiovalue,
isSecond,
taskId,
code,
btnValue,
oldkey,
value,
checked,
setData,
data,
userInfo,
btns,
dispatch,
that: this,
handleUser,
};
if (!checkSumbitInfo) {
const values = this.props.form.getFieldsValue();
argumentsSubmitValue.values = values;
submitValues(argumentsSubmitValue);
} else {
this.props.form.validateFieldsAndScroll((err, values) => {
if (!err) {
argumentsSubmitValue.values = values;
submitValues(argumentsSubmitValue);
}
});
}
};
onChange = e => {
this.setState({
radiovalue: e.target.value,
});
};
/**
* @function 复选框状态函数
* @event change
*/
onCheckChange = checkedValues => {
this.setState({
checkedConfimList: checkedValues,
});
};
/**
* @function 加签点击函数
* @event click
*/
onClickCountersign = () => {
const { countersignModal } = this.state;
countersignModal();
};
/**
* @function 通过用户复选框选择拼装为对应打印页面
*/
changeTake = checked => {
this.setState({ isTakeFlow: checked });
};
changePadding = value => {
this.setState({ paddingBottom: value });
};
/**
* @function 历史表单展示
* @description: 历史表单二次封装,独立form主要防止新表单进行输入时会同步刷新历史表单问题
* @param {string} key 模板key值
* @param { any } postData 参数
* @param { any } obj 默认值
* @param { any } form form控件
* @param { any } routerState 路由参数
* @return: 渲染组件
*/
OldFromZdy = Form.create()(function name({
key,
postData,
obj,
taskId,
form,
formKey,
routerState,
}) {
return (
<ZdyTable
key={key}
get='web'
postData={postData}
taskId={taskId}
obj={obj}
form={form}
formKey={formKey}
routerState={routerState}
/>
);
});
render() {
const {
stepFlow,
isHandle,
hisTaskFormKeys,
id,
appId,
code,
steps,
data,
btns,
isSecond,
isLoading,
formColor,
formLevel,
btnList,
radiovalue,
isEnd,
isShowTitle,
isSumbitLoading,
isOpenTrunToModel,
trunToStatus,
trunData,
isCloseUserDetail,
checkListOptions,
checkedConfimList,
isTakeFlow,
paddingBottom,
setData,
isSign,
nextAuditInfo,
isAllPrint,
} = this.state;
const { showPrint } = this.props;
const isCloseFlowPath = sessionStorage.getItem('isCloseFlowPath')
? JSON.parse(sessionStorage.getItem('isCloseFlowPath'))
: false;
const isTrunTo = sessionStorage.getItem('isTrunTo')
? JSON.parse(sessionStorage.getItem('isTrunTo'))
: false;
const domainName = sessionStorage.getItem('domainName')
? sessionStorage.getItem('domainName')
: '';
const routerState = {
history: this.props?.history,
location: this.props?.location,
match: this.props?.match,
computedMatch: this.props?.computedMatch,
route: this.props?.route,
};
return (
<Fragment>
<div
style={{
width: '100%',
display: 'flex',
justifyContent: 'center',
}}
>
<div style={{ width: 1200 }}>
<div
className={styles.header}
style={{
position: 'relative',
}}
>
{isCloseFlowPath ? null : ( // 关闭流程紧急度显示
<span
style={{
position: 'absolute',
left: 0,
top: '30%',
}}
>
{isSecond ? (
<>
<span style={{ marginRight: 12 }}>{must}流程紧急度</span>
<Radio.Group onChange={this.onChange} value={radiovalue}>
{btnList.length > 0
? btnList.map(item => (
<Radio key={item.id + Math.random()} value={item.id}>
<span style={{ color: item.color }}>{item.name}</span>
</Radio>
))
: ''}
</Radio.Group>
</>
) : (
<>
紧急程度:
<span
style={{
color: formColor || '',
marginLeft: 21,
}}
>
{formLevel || '暂无'}
</span>
</>
)}
</span>
)}
{data.appName ? data.appName : '当前表单'}
{isEnd || isAllPrint || showPrint ? (
<>
<Popconfirm
onConfirm={() => {
if (!checkedConfimList || !checkedConfimList.length) {
message.warning('请选择需要打印的表单');
return false;
}
if (domainName) {
window.open(
`${domainName}/protal/printRouter?id=${data.id}&list=${JSON.stringify(
checkedConfimList,
)}&padding=${paddingBottom}&isTakeFlow=${isTakeFlow}&token=${getToken()}`,
);
} else {
openToast('warning', '未配置域名地址,请联系管理员');
}
}}
title={
<div>
<div>
是否带流程:
<Switch checked={isTakeFlow} onChange={this.changeTake} />
</div>
<div>
表单间距:
<InputNumber
min={0}
size='small'
value={paddingBottom}
onChange={this.changePadding}
/>
</div>
<div className={styles.history_form_title}>请选择需要打印的表单</div>
<div className={styles.history_form_body_div}>
<Checkbox.Group
options={checkListOptions}
onChange={this.onCheckChange}
defaultValue={checkedConfimList}
/>
</div>
</div>
}
okText='确定'
cancelText='取消'
>
{data.isPrint == null || data.isPrint || isAllPrint || showPrint ? (
<Button
style={{
position: 'absolute',
right: 200,
top: '30%',
}}
type='primary'
>
打印预览
</Button>
) : (
''
)}
</Popconfirm>
</>
) : (
''
)}
</div>
</div>
</div>
{isLoading ? (
<>
<Card>
{!isCloseUserDetail && (
<div className={styles.body_hea}>
<h3>发起人信息</h3>
{data &&
(data.createTime ||
data.code ||
data.userName ||
data.userPosition ||
data.userPhone ||
data.userSchool) && (
<Row className={styles.row}>
{data && data.code && (
<Col
style={{
marginBottom: 12,
}}
span={8}
>
<span className={styles.hea_title}>单号</span>
<span className={styles.hew_content}>{data.code}</span>
</Col>
)}
{data && data.userName && (
<Col
style={{
marginBottom: 12,
}}
span={8}
>
<span className={styles.hea_title}>用户姓名</span>
<span className={styles.hew_content}>{data.userName}</span>
</Col>
)}
{data && data.userPosition && (
<Col
style={{
marginBottom: 12,
}}
span={8}
>
<span className={styles.hea_title}>职位</span>
<span className={styles.hew_content}>{data.userPosition}</span>
</Col>
)}
{data && data.userSchool && (
<Col
span={8}
style={{
marginBottom: 12,
}}
>
<span className={styles.hea_title}>学院/单位</span>
<span className={styles.hew_content}>{data.userSchool}</span>
</Col>
)}
{data && data.userPhone && (
<Col
span={8}
style={{
marginBottom: 12,
}}
>
<span className={styles.hea_title}>联系电话</span>
<span className={styles.hew_content}>{data.userPhone}</span>
</Col>
)}
{data && data.createTime && (
<Col
style={{
marginBottom: 12,
}}
span={8}
>
<span className={styles.hea_title}>申请时间</span>
<span className={styles.hew_content}>
{moment(data.createTime)
.format('YYYY-MM-DD HH:mm')}
</span>
</Col>
)}
</Row>
)}
</div>
)}
<div
id='card_table'
ref={el => (this.componentRef = el)}
style={{ padding: !isShowTitle ? '50px' : '' }}
>
{hisTaskFormKeys.formKeys && hisTaskFormKeys.formKeys.length > 0
? hisTaskFormKeys.formKeys.map((item, index) => (
<Fragment key={item.taskName}>
{isShowTitle ? (
<h3
style={{
display: 'flex',
alignItems: 'center',
}}
>
<SVG name='vertical' color='#999999' height='24' />
{item?.taskName ?? '历史流程表单'}
</h3>
) : (
''
)}
{!data ? (
<div
style={{
width: '100%',
height: 200,
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
}}
>
<Spin size='large' />
</div>
) : (
/* <div>
123临时注释
</div>*/
<this.OldFromZdy
key={item.formKey}
get='web'
taskId={data.taskId}
postData={data}
obj={data && data.isMultiple ? item.taskForm : hisTaskFormKeys.formData}
formKey={item.formKey}
routerState={routerState}
/>
)}
</Fragment>
))
: ''}
{isHandle === true && !!data.taskFormKey ? (
<>
{isShowTitle ? (
<h3
style={{
display: 'flex',
alignItems: 'center',
}}
>
<SVG name='vertical' color='#999999' height='24' />
当前流程
</h3>
) : (
''
)}
{isEmpty(data) === false ? (
<ZdyTable
key={data.taskFormKey}
postData={data}
get='web'
obj={hisTaskFormKeys.formData}
table='new'
form={this.props.form}
routerState={routerState}
/>
) : (
''
)}
</>
) : (
''
)}
</div>
</Card>
<Card>
<div className={styles.body_content} style={{ minHeight: '300px' }}>
<div id={'btnsModalMountDiv'}></div>
<h3>
审批状态 <span onClick={this.examineFlow}>查看流程图</span>
</h3>
<div
ref={el => (this.componentTwoRef = el)}
style={{
padding: !isShowTitle ? '0 50px 50px 50px' : '',
}}
>
<Timeline>
{stepFlow !== '' && steps !== ''
? stepFlow.map((item, index) => {
if (index === stepFlow.length - 1) {
// 最后一步流程
return (
<Timeline.Item
color={['处理中', '待处理'].includes(item.status) ? 'red' : '#ccc'}
dot={
<Icon
type={
['处理中', '待处理'].includes(item.status) ? 'clock-circle-o' : 'check-circle'
}
style={{ fontSize: '16px' }}
/>
}
className={styles.steps_step}
key={item.id}
>
<p className={styles.steps_title}>
{item.assignee}
<span>
{item.endTime
? moment(item.endTime)
.format('YYYY-MM-DD HH:mm')
: '处理中'}
</span>
</p>
{
queryApiVersion() === '2.0' && ['处理中', '待处理'].includes(item.status) && !!data.nextUsers && (
<p>审批人员: {data.nextUsers}</p>
)
}
{queryApiVersion() !== '2.0' && ['处理中', '待处理'].includes(item.status) && !!nextAuditInfo.nextUsers && (
<p>审批人员: {nextAuditInfo.nextUsers}</p>
)}
<p>审批流程:{item.name}</p>
<p className={styles.steps_body}>审批状态:{item.status}</p>
{item.taskVariable?.reason ? (
<p>审批原因:{item.taskVariable?.reason}</p>
) : (
''
)}
{item.childTaskModel && item.childTaskModel.length > 0 && (
<ChildTaskModel data={item.childTaskModel} />
)}
{isSign || item.taskVariable?.sign ? (
<img
style={{
position: 'absolute',
top: '50%',
left: 200,
height: 50,
marginTop: -25,
border: item.taskVariable?.sign ? '1px solid #ccc' : '',
}}
src={
item.taskVariable?.sign
? queryApiActionPath() + item.taskVariable?.sign
: ''
}
alt=''
/>
) : (
''
)}
{isTrunTo && +item.commentCount > 0 ? (
<TrunToDetail data={data} item={item} />
) : null}
</Timeline.Item>
);
}
return (
<Timeline.Item
color={item.status === 0 ? 'gray' : 'green'}
dot={
item.status === 0 ? (
''
) : (
<Icon
type='check-circle'
theme='twoTone'
twoToneColor='#52c41a'
/>
)
}
className={styles.steps_step}
key={item.id}
>
<p className={styles.steps_title}>
{item.assignee}
<span>
{item.endTime
? moment(item.endTime)
.format('YYYY-MM-DD HH:mm')
: null}
</span>
</p>
<p>审批流程:{item.name}</p>
<p className={styles.steps_body}>审批状态:{item.status}</p>
{item.taskVariable?.reason ? (
<p>审批原因:{item.taskVariable.reason}</p>
) : (
''
)}
{item.childTaskModel && item.childTaskModel.length > 0 && (
<ChildTaskModel data={item.childTaskModel} />
)}
{item.taskVariable?.sign ? (
<img
style={{
position: 'absolute',
top: '50%',
left: 200,
height: 50,
marginTop: -25,
border: item.taskVariable?.sign ? '1px solid #ccc' : '',
}}
src={
item.taskVariable?.sign
? queryApiActionPath() + item.taskVariable?.sign
: ''
}
alt=''
/>
) : (
''
)}
{isTrunTo && +item.commentCount > 0 ? (
<TrunToDetail data={data} item={item} />
) : null}
</Timeline.Item>
);
})
: ''}
</Timeline>
</div>
</div>
</Card>
<div className={styles.buttonList}>
{isHandle === true ? (
<>
<BtnOk
Sign={!!setData?.userSign}
isSumbitLoading={isSumbitLoading}
isSecond={isSecond}
affairOk={this.affairOk}
btns={btns}
addition={
<>
{isTrunTo && data.isSecond !== true && isHandle ? (
<Button
style={{
marginLeft: 16,
minHeight: 32,
minWidth: 90,
}}
onClick={() => {
this.showTrunToModel(
data.isHandle && data.isOwner
? '转办'
: !data.isHandle && data.isOwner
? '撤回'
: '回退',
data,
);
}}
type='primary'
>
{data.isHandle && data.isOwner
? '转办'
: !data.isHandle && data.isOwner
? '撤回'
: data.isHandle && !data.isOwner
? '回退'
: null}
</Button>
) : null}
{data.isCanSign && (
<Button
style={{
marginLeft: 16,
minHeight: 32,
minWidth: 90,
}}
onClick={this.onClickCountersign}
type='primary'
>
加签
</Button>
)}
</>
}
/>
</>
) : (
''
)}
{isTrunTo && data.isSecond !== true && !data.isHandle && data.isOwner && (
<div
style={{
width: '100%',
textAlign: 'center',
}}
>
<Button
style={{
minHeight: 32,
minWidth: 90,
margin: '0 auto',
}}
onClick={() => {
this.showTrunToModel('撤回', data);
}}
type='primary'
>
撤回
</Button>
</div>
)}
</div>
</>
) : (
<div
style={{
width: '100%',
height: 200,
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
}}
>
<Spin size='large' />
</div>
)}
<PortalFlowExamineModal
ref={node => (this.flowExamineModal = node)}
affairId={id}
id={appId}
code={code}
/>
<TrunToModel
visible={isOpenTrunToModel}
handleCancel={this.handleTrunToModel}
status={trunToStatus}
value={trunData}
init={this.getInit}
/>
{data?.appName && (
<Countersign
taskId={data.taskId}
data={data}
getInit={this.getInit}
updateCountersignModal={this.updateCountersignModal}
/>
)}
</Fragment>
);
}
}
/**
* 钟是志
* 2019年12月11日 17:30:41
* 查看详情页面的iframe嵌套到中医大里面
*/
import React, {Component} from 'react';
import { setToken } from '@/webPublic/one_stop_public/utils/token';
import {getUrlInfo} from './utils';
import DetailSplit from './DetailSplit';
import styles from './styles.less';
import {getOneStopConfigList} from '@/webPublic/one_stop_public/publicServices';
export default class GetDetail extends Component {
constructor(props) {
super(props);
const token = getUrlInfo().token;
if(token && token.length > 10){
setToken(token);
}
getOneStopConfigList();
this.state = {
id: getUrlInfo().id || props.id,
};
}
componentDidMount() {
}
/***
* 需要加入跳转功能;
* 钟是志
* 在iframe中打开时 直接返回一个postMessage;
* */
render() {
const {id} = this.state;
let {location} = this.props.history;
location = {
...location,
state: {
id,
fromIframe: true,
},
};
return (
<div className={styles.detail_div}
id={'detailInfoDiv'}
style={{
backgroundColor: '#FFFFFF',
// overflow: isFromIframe() ? 'hidden' : 'unset',
overflow: 'auto',
height: '100%',
}}
>
<DetailSplit history={{...this.props.history, location}}
showPrint={getUrlInfo().showPrint === 'true'}
/>
</div>
);
}
}
/**
* 徐立
* 2019年9月19日
* 查看详情底层模板,内容不做添加
*/
import React, { Component } from 'react'
import styles from './index.less'
export default class Card extends Component {
render() {
return (
<div className={styles.div}>
<div className={styles.card}>
{this.props.children}
</div>
</div>
)
}
}
.div{
.card{
position: relative;
left: 50%;
transform: translateX(-50%);
width: 1200px;
min-height: 319px;
margin-bottom: 16px;
padding:36px 35px 24px 24px;
background-color: #fff;
border-top: 4px solid #0F91FF;
}
}
\ No newline at end of file
/**
* @file 加签功能
*/
import React, { Component } from 'react';
import { Modal, Input, Table, Row, Col, Tooltip, Spin, Tag } from 'antd';
import styles from './style.less';
import { openToast } from '../Notification';
import { connect } from 'dva';
const { Search } = Input;
@connect()
export default class Countersign extends Component {
constructor(props) {
super(props);
this.state = {
data: [], // 表格参数
textAreaValue: '', // 用户转发理由
current: 1, // 当前页数
pageSize: 10, // 每页条数
total: 0, // 数据总数
realname: '', // 姓名输入框输入值
username: '', // 账号输入框输入值
isLoading: false, // 请求状态
visible: false,
selectUserData: [],
btnLoading: false, // 提交状态
};
this.columns = [
{
title: '用户名',
fixed: 'left',
dataIndex: 'realname',
width: 170,
},
{
title: '工号',
dataIndex: 'stuNo',
width: 170,
},
{
title: '邮箱',
dataIndex: 'email',
width: 200,
render: text => {
return (
<Tooltip title={text}>
<div className={styles.table_post_name}>{text}</div>
</Tooltip>
);
},
},
{
title: '职位',
dataIndex: 'mainPostName',
render: text => {
return (
<Tooltip title={text}>
<div className={styles.table_post_name}>{text}</div>
</Tooltip>
);
},
},
{
title: '操作',
key: '操作',
fixed: 'right',
render: record => {
return (
<a
onClick={() => {
this.addUserSelect(record);
}}
>
选择
</a>
);
},
},
];
}
componentDidMount() {
this.props.updateCountersignModal(this.showModal);
this.setState(
{
isLoading: true,
},
() => {
this.getInit();
},
);
}
/**
* @function 进行用户添加
* @event click
*/
addUserSelect = val => {
const { selectUserData } = this.state;
let array = selectUserData.filter(item => item.id === val.id);
if (array.length > 0) {
openToast('warning', '请勿重复添加用户');
return;
}
let ary = [
...selectUserData,
{
id: val.id,
name: val.realname,
},
];
this.setState({
selectUserData: ary,
});
};
/**
* @function 进行用户删除
* @param { string } id 需要删除的ID
*/
removeUserSelect = id => {
const { selectUserData } = this.state;
let ary = selectUserData.filter(item => item.id !== id);
this.setState({
selectUserData: ary,
});
};
getInit = async () => {
const {
dispatch,
data: {
addSignSql,
id,
},
} = this.props;
// 用户名列表
this.getData();
await this.setState({
isLoading: false,
});
};
getData = async (params = {
pageNo: 1,
pageSize: 5,
}) => {
const {
dispatch,
data,
} = this.props;
await dispatch({
type: 'uaa_User/fetch',
payload: {
...params,
},
callback: val => {
this.setState({
data: val.rows,
current: val.pageNo,
total: val.totalPage,
pageSize: val.pageSize,
});
},
});
};
userPaginationChange = value => {
const { dispatch } = this.props;
const {
realname,
username,
} = this.state;
this.getData({
pageNo: value,
pageSize: 5,
realname,
username,
});
};
/**
* 根据名字查询
* @param { string } value 用户输入值
*/
searchNameChange = value => {
const { dispatch } = this.props;
this.getData({
realname: value,
pageNo: 1,
pageSize: 5,
});
};
/**
* 名字输入事件
* @param { stirng } e 用户输入事件
*/
onNameChange = e => {
this.setState({
realname: e.target.value,
username: '',
});
};
/**
* 根据账号查询
* @param { stirng } value 用户输入值
*/
serachStuNoChange = value => {
const { dispatch } = this.props;
this.setState({
username: value,
});
this.getData({
username: value,
pageNo: 1,
pageSize: 5,
});
};
/**
* 账号输入数据
* @param { stirng } e 用户输入事件
*/
onStuNoChange = e => {
this.setState({
username: e.target.value,
realname: '',
});
};
showModal = () => {
this.setState({
visible: true,
});
};
handleOk = e => {
const { selectUserData } = this.state;
const { dispatch } = this.props;
let ary = [];
selectUserData.map(item => {
ary.push(item.id);
});
if (ary.length === 0) {
openToast('info', '并未选择加签用户,请选择');
return;
}
this.setState(
{
btnLoading: true,
},
() => {
dispatch({
type: 'countersign/countersignHandle',
payload: {
taskId: this.props.taskId,
userIds: ary,
},
callback: () => {
openToast('success', '加签成功');
this.props.getInit();
this.setState({
visible: false,
btnLoading: false,
});
},
});
},
);
};
handleCancel = e => {
this.setState({
visible: false,
});
};
render() {
const {
data,
current,
total,
pageSize,
realname,
username,
isLoading,
selectUserData,
btnLoading,
} = this.state;
let allWidth = 0;
// 计算滑动总长度
if (Array.isArray(this.columns)) {
this.columns.map((item, index) => {
if (this.columns.length - 1 === index) {
// 为最后一个元素时跳过
allWidth += 270; // 自适应200宽度
return item;
}
if (item.width) {
// 存在默认宽度
allWidth += item.width;
} else {
// 不存在
allWidth += 170;
}
return item;
});
}
return (
<Modal
title='加签'
visible={this.state.visible}
onOk={this.handleOk}
onCancel={this.handleCancel}
width={800}
confirmLoading={btnLoading}
destroyOnClose
>
{!isLoading ? (
<>
<Row>
<Col span={12}>
<Row>
<Col
span={4}
style={{
minHeight: 32,
textAlign: 'right',
lineHeight: '32px',
}}
>
姓名 &nbsp;
</Col>
<Col span={20}>
<Search
placeholder='姓名'
value={realname}
onSearch={this.searchNameChange}
onChange={this.onNameChange}
enterButton
/>
</Col>
</Row>
</Col>
<Col span={12}>
<Col
span={4}
style={{
minHeight: 32,
textAlign: 'right',
lineHeight: '32px',
}}
>
账号 &nbsp;
</Col>
<Col span={20}>
<Search
placeholder='账号'
value={username}
onSearch={this.serachStuNoChange}
onChange={this.onStuNoChange}
enterButton
/>
</Col>
</Col>
</Row>
<div id='trun_to_table' className={styles.trun_to_table_div}>
<Table
columns={this.columns}
dataSource={data}
scroll={{ x: allWidth }}
pagination={{
hideOnSinglePage: true,
pageSize,
total,
current,
onChange: this.userPaginationChange,
}}
/>
</div>
<div className={styles.title_name_div}>已选择加签人</div>
<div className={styles.tag_div}>
{selectUserData &&
Array.isArray(selectUserData) &&
selectUserData.length > 0 &&
selectUserData.map(item => {
return (
<Tag
color='#108ee9'
onClose={() => {
this.removeUserSelect(item.id);
}}
closable
key={item.id}
>
{item.name}
</Tag>
);
})}
</div>
</>
) : (
<div className={styles.spin_div}>
<Spin />
</div>
)}
</Modal>
);
}
}
.table_post_name {
cursor: initial;
width: 200px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.trun_to_table_div {
margin-top: 12px;
}
.spin_div {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.title_name_div {
font-size: 16px;
font-weight: bold;
color: #333333;
}
.tag_div {
width: 100%;
min-height: 80px;
}
:global {
#trun_to_table .ant-table-thead tr th {
background-color: #fff;
}
}
import React from 'react';
import { Col, Row } from 'antd';
import classNames from 'classnames/bind';
import PortalFlowExamineModalImage from './Image';
import { connect } from 'dva';
import { queryApiActionPath } from '@/webPublic/one_stop_public/utils/queryConfig';
const names = classNames.bind(require('./style.less'));
const Body = ({
className,
...props
}) => <div className={names('body', className)} {...props} />;
@connect()
export default class PortalFlowExamineModalContent extends React.Component {
constructor() {
super();
this.state = {
data: {}, // 事务所有数据
arr: [], // 事务流程
};
}
render() {
let {
id,
affairId,
code,
} = this.props;
return (
<Row className={names('warp')}>
<Col span={24}>
<Body>
{id % 2 === 1 ? (
<PortalFlowExamineModalImage
appid={id}
code={code}
src={
!!affairId
? `${queryApiActionPath()}/UnifiedAppFormApi/getProcessImg?appId=${id}&id=${affairId}`
: `${queryApiActionPath()}/UnifiedAppFormApi/getProcessImg?appId=${id}`
}
/>
) : (
<PortalFlowExamineModalImage
appid={id}
code={code}
src={
!!affairId
? `${queryApiActionPath()}/UnifiedAppFormApi/getProcessImg?appId=${id}&id=${affairId}`
: `${queryApiActionPath()}/UnifiedAppFormApi/getProcessImg?appId=${id}`
}
/>
)}
</Body>
</Col>
</Row>
);
}
}
import React from 'react';
import Loading from '../loadThree';
import { Slider, Row, Col } from 'antd';
import { connect } from 'dva';
import classNames from 'classnames/bind';
const names = classNames.bind(require('./style.less'));
let width;
let sliNum = 0;
const GetEditor = () => {
const GgEditor = require('../ggEditor');
return GgEditor;
}
@connect()
export default class PortalFlowExamineModalImage extends React.Component {
state = {
visible: true,
slider: 0,
isImgLoading: true,
canvasIMg: '', // canvas转换的图片
configValue: false, // 配置信息
flowInfo: '', // 获取流程图的信息
};
handleCancel = () => this.setState({ visible: false });
handlePreview = () => {
// const {width} = this.img;
// this.setState({visible: true, width})
};
sliderChange = num => {
if (sliNum === 0) {
width = document.querySelector('.img').width;
// console.log(document.querySelector('.img').width)
}
sliNum++;
if (num == 0 && sliNum != 0) {
document.querySelector('.img').width = width;
return;
}
if (num > 0) {
document.querySelector('.img').width = width * `${1}.${num}`;
} else {
document.querySelector('.img').width = width * `${0}.${Math.abs(num + 10)}`;
}
};
getCanvasImg = imgSrc => {
this.setState(
{
canvasIMg: imgSrc,
},
() => {
this.setState({
visible: false,
});
},
);
};
componentDidMount = () => {
const { appid, code } = this.props;
this.props.dispatch({
// 获取配置信息
type: 'DataGgEditor/getNewProcessImg',
payload: {
appid,
code,
},
callback: val => {
this.setState({
flowInfo: val,
});
},
});
this.props.dispatch({
// 获取配置信息
type: 'emailorphone/GetLogo',
payload: {
configKeys: 'IsOldFlow',
},
callback: val => {
this.setState({
configValue: val[0].configValue == 'true',
});
},
});
};
onLoad = () => {
this.setState({
isImgLoading: false,
visible: false,
});
};
render() {
const { src, appid } = this.props;
const { visible, width, isImgLoading, canvasIMg, configValue, flowInfo } = this.state;
return (
<>
{configValue ? (
<div
className={names('image-warp')}
style={{ overflow: 'hidden', width: '1300px', height: '630px' }}
>
{flowInfo?.model?.id ? (
<>
<div
style={{
width: '100%',
height: '630px',
textAlign: 'center',
overflow: 'auto',
}}
>
<img onLoad={this.onLoad} src={canvasIMg}></img>
</div>
{flowInfo?.model?.id && isImgLoading ? (
<div
style={{
width: '1600px',
height: '670px',
visibility: 'hidden',
position: 'relative',
}}
>
<GetEditor
flowModelId={flowInfo.model.id}
taskKeys={flowInfo.taskKeys}
getCanvasImg={this.getCanvasImg}
isShow={false}
/>
</div>
) : null}
</>
) : (
<div style={{ marginTop: '350px' }}>
{' '}
<Loading />
</div>
)}
</div>
) : (
<div className={names('image-warp')}>
<Row>
<Col span={6} style={{ paddingLeft: 24, lineHeight: '36px' }}>
图片展示比例:
</Col>
<Col span={6}>
<Slider defaultValue={0} max={5} min={-5} onChange={this.sliderChange} />
</Col>
</Row>
<div
style={{
display: isImgLoading ? 'none' : 'block',
}}
>
<img
onLoad={this.onLoad}
className="img"
src={src}
style={{ overflow: 'auto', transition: 'all 0.5s', position: 'relative' }}
ref={node => (this.img = node)}
alt=""
onClick={this.handlePreview}
/>
</div>
{isImgLoading ? (
<div
style={{
width: '90%',
height: '610px',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
paddingLeft: '10%',
}}
>
<Loading />
</div>
) : null}
{/* <Modal
width={width >= 1200 ? 1200 : width}
wrapClassName={names("image-modal-warp")}
visible={visible} footer={null}
onCancel={this.handleCancel}
destroyOnClose
>
<img alt="example" style={{ width: '100%' }} src={src} />
</Modal> */}
</div>
)}
</>
);
}
}
import React from 'react';
import { Modal } from 'antd';
import classNames from 'classnames/bind';
import PortalFlowExamineModalContent from './Content';
const names = classNames.bind(require('./style.less'));
export default class PortalFlowExamineModal extends React.Component {
state = { visible: false };
showModal = () => {
this.setState({ visible: true });
};
handleCancel = () => {
this.setState({ visible: false });
};
render() {
const { visible } = this.state;
const { isShow, id, affairId } = this.props;
const code = this.props?.code ? this.props?.code : '';
// console.log(this.props)
return (
<Modal
title="事务流程"
visible={visible}
onCancel={this.handleCancel}
footer={null}
width={1300}
wrapClassName={names('modal-warp')}
destroyOnClose
>
<PortalFlowExamineModalContent affairId={affairId} id={id} code={code} isShow={isShow} />
</Modal>
);
}
}
.warp {
position: relative;
&:before {
display: block;
height: 100%;
width: 1px;
background: #e8e8e8;
position: absolute;
top: 0;
left: 50%;
}
.title {
font-weight: bold;
color: #333333;
margin-bottom: 16px;
}
.body {
max-width: 100%;
min-height: 480px;
overflow: auto;
background-color: #fff;
}
.step {
background: #F5F5F5;
padding: 16px 16px 16px 80px;
.step-title {
font-weight: normal;
.name {
color: #0F91FF;
}
.date {
font-size: 12px;
color: #999999;
display: inline-block;
float: right;
margin-top: 2px;
}
}
.description {
font-size: 12px;
line-height: 20px;
.date {
font-size: 12px;
color: #999999;
display: inline-block;
margin-top: 2px;
}
}
:global {
.ant-steps-item-content {
//width: unset;
}
.ant-steps-item-title {
display: block;
font-size: 14px;
}
.ant-steps-dot .ant-steps-item-icon {
width: 12px;
height: 12px;
}
.ant-steps-item-finish .ant-steps-item-icon > .ant-steps-icon .ant-steps-icon-dot {
background: -moz-linear-gradient(to right, #1C89E0 0%, #B53CED 100%);
background: -webkit-gradient(to right, #1C89E0 0%, #B53CED 100%);
background: -webkit-linear-gradient(to right, #1C89E0 0%, #B53CED 100%);
background: -o-linear-gradient(to right, #1C89E0 0%, #B53CED 100%);
background: -ms-linear-gradient(to right, #1C89E0 0%, #B53CED 100%);
background: linear-gradient(to left, #1C89E0 0%, #B53CED 100%);
}
.ant-steps-item-icon > .ant-steps-icon {
right: 2px;
}
}
}
}
.modal-warp {
:global {
.ant-modal-header {
background: #EAF5FF;
}
.ant-modal-body{
padding-left: 0;
padding-right: 0;
}
}
}
.image-warp{
text-align: center;
position: relative;
}
.image-modal-warp {
img {
max-width: 100%;
}
}
/**
* 徐立
* 2019年9月11日
* 通知提醒框二次封装
*/
import React from 'react'
import { notification,Modal } from 'antd';
/**
*
* @param {string} type 'success 成功 info 注意 warning 警告 error 错误'
* @param {string} title '提示标题'
* @param {string} content '主要内容'
* @param {string} placement '弹出位置 topLeft topRight bottomLeft bottomRight'
* @param {pbject} style '使用style 自定义弹出框样式
*/
export const openToast = (type:string,title:string,content:string,placement?:string,style?:object):void => {
notification[type]({
message: title,
description:content,
placement,
style
});
};
/**
* 点击提示,执行信息展示,只提供一个按钮用于关闭
* @param {string} title 成功提示信息标题
* @param {any} content 成功提示信息内容(可为html标签)
* @param {Function} handleOk 点击确定回调
*/
export const success = (title:string,content:any,handleOk:()=>{}):void => {
Modal.success({
title: title,
content: (
<div>
{content}
</div>),
onOk:handleOk,
});
}
/**
* 点击提示,执行信息展示,只提供一个按钮用于关闭
* @param {string} title 错误提示信息标题
* @param {any} content 错误提示信息内容(可为html标签)
* @param {Function} handleOk 点击确定回调
*/
export const error = (title:string,content:any,handleOk:()=>{}):void => {
Modal.error({
title: title,
content: (
<div>
{content}
</div>),
onOk:handleOk,
});
}
/**
* 点击提示,执行信息展示,只提供一个按钮用于关闭
* @param {string} title 普通提示信息标题
* @param {any} content 普通提示信息内容(可为html标签)
* @param {Function} handleOk 点击确定回调
*/
export const info = (title:string,content:any,handleOk:()=>{}):void => {
Modal.info({
title: title,
content: (
<div>
{content}
</div>
),
onOk:handleOk,
});
}
/**
* 点击提示,执行信息展示,只提供一个按钮用于关闭
* @param {string} title 警告提示信息标题
* @param {any} content 警告提示信息内容(可为html标签)
* @param {Function} handleOk 点击确定回调
*/
export const warning = (title:string,content:any,handleOk:()=>{}):void => {
Modal.warning({
title: title,
content: (
<div>
{content}
</div>),
onOk:handleOk,
});
}
/**
* 含有确认取消按钮的消息确认框
* @param {string} title 消息提示框标题
* @param {any} content 消息提示框内容
* @param {Function} handleOk 点击确认回调
* @param {Function} handleCancel 点击取消回调
* @param {string} okText 确定按钮文本内容默认确定
* @param {string} cancelText 取消按钮文本内容默认取消
*/
export const confirm = (title:string,content:any,handleOk:()=>{},handleCancel:()=>{},okText:string='确定',cancelText:string='取消'):void => {
Modal.confirm({
title: title,
content: content,
okText:okText,
cancelText:cancelText,
onOk:handleOk,
onCancel:handleCancel,
});
}
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
.icon{
cursor: pointer;
}
\ No newline at end of file
## 一站式通用SVG库
##依赖环境
>```
>react
>```
## 使用示例
```jsx
import SVG from '@/SVG';
<SVG
name='leftArrows' // svg注册名
width={20} // 宽度 20||"20"
height={20} // 高度 20 || "20"
mouseColor='blue' // 鼠标移入改变颜色,不传默认显示color颜色
color='#888888' // 默认展示颜色
/>
```
## 注册新svg说明
前往iconfont网站选择图标
https://www.iconfont.cn/
选中图标后点击复制SVG
获取到以下代码
```html
<svg
t="1585207472508"
class="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="2142"
width="16"
height="16">
<path
d="M1024 384 640 384 783.53 240.47C711 167.944 614.57 128 512 128 409.43 128 313 167.944 240.47 240.47 167.944 313 128 409.43 128 512 128 614.57 167.944 711 240.47 783.53 313 856.056 409.43 896 512 896 614.57 896 711 856.056 783.528 783.528 789.584 777.474 795.388 771.236 800.984 764.86L897.304 849.142C803.458 956.308 665.64 1024 512 1024 229.23 1024 0 794.77 0 512 0 229.23 229.23 0 512 0 653.386 0 781.368 57.326 874.016 149.984L1024 0 1024 384Z"
p-id="2143">
</path>
</svg>
```
修改为以下代码后复制入SVG下index中进行注册
```jsx
<svg
t="1585207472508"
class="icon"
viewBox="0 0 1024 1024"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
p-id="2142"
width={width?width:"16"} // 动态配置宽度
height={height?height:"16"} // 动态配置高度
onMouseEnter={mouseEnterColor} // 移入方法
onMouseLeave={mouseLeaveColor} // 移出方法
style={{'cursor':'pointer'}} // 复制就行
>
<path
d="M1024 384 640 384 783.53 240.47C711 167.944 614.57 128 512 128 409.43 128 313 167.944 240.47 240.47 167.944 313 128 409.43 128 512 128 614.57 167.944 711 240.47 783.53 313 856.056 409.43 896 512 896 614.57 896 711 856.056 783.528 783.528 789.584 777.474 795.388 771.236 800.984 764.86L897.304 849.142C803.458 956.308 665.64 1024 512 1024 229.23 1024 0 794.77 0 512 0 229.23 229.23 0 512 0 653.386 0 781.368 57.326 874.016 149.984L1024 0 1024 384Z"
fill={ // 预先展示移入颜色,判断是否传入数组进行下标值分开获取,非数组直接展示
showColor?
Array.isArray(showColor)?
showColor[0]
:showColor
:Array.isArray(color)?
color[0]
:color}
p-id="2143">
</path>
</svg>
```
\ No newline at end of file
.editor {
display: flex;
flex: 1;
flex-direction: column;
width: 100%;
height: 100%;
background: #fff;
position: relative;
border: 1px solid #e6e9ed;
.saveDate{
position: absolute;
top: 6px;
left: 94%;
}
.inputValue{
width:400px;
position: absolute;
top: 6px;
left: 45%;
}
}
.editorHd {
padding: 8px;
border: 1px solid #e6e9ed;
}
.editorBd {
flex: 1;
}
.editorSidebar,
.editorContent {
display: flex;
flex-direction: column;
}
.editorSidebar {
background: #fafafa;
&:first-child {
border-right: 1px solid #e6e9ed;
}
&:last-child {
border-left: 1px solid #e6e9ed;
}
}
.ant-collapse-content > .ant-collapse-content-box {
padding: 0px !important;
}
.flow {
flex: 1;
// https://github.com/philipwalton/flexbugs/issues/197#issuecomment-378908438
height: 0;
z-index: 2;
}
import { Icon } from 'antd';
const IconFont = Icon.createFromIconfontCN({
scriptUrl: 'https://at.alicdn.com/t/font_1101588_01zniftxm9yp.js',
});
export default IconFont;
import React from 'react';
import { NodeMenu, EdgeMenu, GroupMenu, MultiMenu, CanvasMenu, ContextMenu } from 'gg-editor';
import MenuItem from './MenuItem';
import styles from './index.less';
const FlowContextMenu = (isDelete) => {
return (
<ContextMenu className={styles.contextMenu}>
<NodeMenu>
<MenuItem command="copy" />
<MenuItem command="delete" isDelete={isDelete} />
</NodeMenu>
<EdgeMenu>
<MenuItem command="delete" isDelete={isDelete} />
</EdgeMenu>
<GroupMenu>
<MenuItem command="copy" />
<MenuItem command="delete" isDelete={isDelete} />
<MenuItem command="unGroup" icon="ungroup" text="Ungroup" />
</GroupMenu>
<MultiMenu>
<MenuItem command="copy" />
<MenuItem command="paste" />
<MenuItem command="addGroup" icon="group" text="Add Group" />
<MenuItem command="delete" />
</MultiMenu>
<CanvasMenu>
<MenuItem command="undo" />
<MenuItem command="redo" />
<MenuItem command="pasteHere" icon="paste" text="Paste Here" />
</CanvasMenu>
</ContextMenu>
);
};
export default FlowContextMenu;
import React from 'react';
import { Command } from 'gg-editor';
import upperFirst from 'lodash/upperFirst';
import IconFont from '../../common/IconFont';
import styles from './index.less';
const getIsDelete = (props) => {
if (props.command == 'delete') {
// props.isDelete(true)
props.isDelete.isDelete(true)
}
}
const MenuItem = (props) => {
const { command, icon, text, isDelete } = props;
return (
<Command name={command} >
<div onClick={() => { getIsDelete(props) }} className={styles.item}>
<IconFont type={`icon-${icon || command}`} />
<span>{text || upperFirst(command)}</span>
</div>
</Command>
);
};
export default MenuItem;
import FlowContextMenu from './FlowContextMenu';
export { FlowContextMenu };
.contextMenu {
display: none;
overflow: hidden;
background: #fff;
border-radius: 4px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
.item {
display: flex;
align-items: center;
padding: 5px 12px;
cursor: pointer;
transition: all 0.3s;
user-select: none;
&:hover {
background: #e6f7ff;
}
i {
margin-right: 8px;
}
}
:global {
.disable {
:local {
.item {
color: rgba(0, 0, 0, 0.25);
cursor: auto;
&:hover {
background: #fff;
}
}
}
}
}
}
import React, { Fragment } from 'react';
import { Card, Form, Input, Select, Switch, Modal, Button, Checkbox, Col, Row, Icon, Tooltip } from 'antd';
import { connect } from 'dva';
import { withPropsAPI } from 'gg-editor';
import upperFirst from 'lodash/upperFirst';
import GetDetail from '../GetDetail'
import styles from './index.less';
import textImg from '@/assets/down.png'
import { node } from 'prop-types';
import copySymbolsIn from '@/components/copy/deepclone/copySymbolsIn';
const { Item } = Form;
const { Option } = Select;
const options = [
{
id: 'static',
name: '流程发起人'
},
{
id: 'dynamicAllocation',
name: '动态分配'
},
{
id: 'idm',
name: '候选人'
},
{
id: 'group',
name: '分组'
},
]
let golbalInfo = {}//获取信息
const inlineFormItemLayout = {
labelCol: {
sm: { span: 8 },
},
wrapperCol: {
sm: { span: 16 },
},
};
@connect()
class DetailForm extends React.Component {
constructor(props) {
super(props)
// console.log(69554154, this.props.type)
this.state = {
values: {},
checked: true,//判断是否打开监听器
judge: true,//判断条件
initialFp: false,//初始分配人
visible: false,
optionValue: 'static',//分配人初始值
idm: [],
group: [],
searchList: [],//候选人列表数据
searchGroupList: [],//分组列表数据
dynamicAllocation: [],
candidateUsers: [],
openModel: false,
activity: true,
expand: false,//监听器下展开点击控制
idRender: true,//是否再次渲染
isCancel: false,//是否取消添加
IsADD: false,//是否有另外的新增
isAddlisner: false,//是否新增监听器
}
}
get item() {
const { propsAPI } = this.props;
return propsAPI.getSelected()[0];//获取当前选中图形
}
//表单提交函数
handleSubmit = (e) => {
if (e && e.preventDefault) {
e.preventDefault();
}
const { form, propsAPI } = this.props;
const { getSelected, executeCommand, update } = propsAPI;
setTimeout(() => {
form.validateFieldsAndScroll((err, values) => {
if (err) {
return;
}
values = {
...values,
static: values.s
}
this.valueDistriBution = values.distriBution
this.setState({
values: values
}, () => {
console.log(this.state.values)
this.setallmasg(this.state.values)
})
const item = getSelected()[0];
if (!item) {
return;
}
executeCommand(() => {
update(item, {
...values,
});
});
});
}, 0);
};
// 修改属性
setallmasg = (values) => {
let data = this.props.data
let flag = true//判断是否修改的是最外层的数据
data.model.childShapes = data.model.childShapes.map(item => {
//判断节点
if (item.resourceId == values.id) {
//判断是否是线条
if (item.stencil.id === 'SequenceFlow') {
item.properties.overrideid = values.overrideid
item.properties.name = values.label
if (values.conditions !== '') {
// console.log(values.conditions)
item.properties.conditionsequenceflow = {
expression: {
"type": "static",
staticValue: values.conditions
}
}
}
flag = false
} else {
if (!item?.properties) {
item.properties = {
"overrideid": "",
"name": '',
"documentation": "",
"executionlisteners": "",
"initiator": "userId",
"formkeydefinition": "",
"formreference": "",
"formproperties": ""
}
}
item.properties.overrideid = values.overrideid
item.properties.name = values.label
flag = false
//判断是否设置监听器
if (values.listener && this.state.isAddlisner) {
// console.log('设置监听器')
this.handleFormReset()
if (item.properties.executionlisteners.executionListeners == undefined) {
item.properties.executionlisteners = { executionListeners: [] }
}
item.properties.executionlisteners.executionListeners.push({//添加监听者到数组
"event": values.things,
"implementation": values.expression !== '' ? values.expression : values.category !== '' ? values.category : '',
"className": values.category,
"expression": values.expression,
})
this.setState({
isAddlisner: false
})
} else if (values.listener && !this.state.isAddlisner) {
console.log('监听器个数不变')
} else {
// console.log('没有监听器')
item.properties.executionlisteners = ''
}
//判断是否设置分配人
if (this.state.isCancel && this.state.openModel == true) {
item.properties.usertaskassignment = ''
if (values.distriBution == 'static') {
item.properties.usertaskassignment = {
assignment: {
type: this.state.optionValue,
assignee: '${ userId }'
}
}
} else if (values.distriBution == 'idm') {
if (this.state.idm.length > 0) {
item.properties.usertaskassignment = {
assignment: {
type: this.state.optionValue,
idm: {
type: "users",
candidateUsers: this.state.idm
}
}
}
} else {
item.properties.usertaskassignment = ''
}
} else if (values.distriBution == 'group') {
console.log(this.state.group)
if (this.state.group.length > 0) {
item.properties.usertaskassignment = {
assignment: {
type: this.state.optionValue,
idm: {
type: "groups",
candidateGroups: this.state.group
}
}
}
} else {
item.properties.usertaskassignment = ''
}
} else if (values.distriBution == 'dynamicAllocation') {
console.log(values.dynamicAllocation)
if (!!values.dynamicAllocation.length) {
item.properties.usertaskassignment = {
assignment: {
type: 'static',
candidateUsers: [{
value: values.dynamicAllocation,
$$hashKey: ""
}]
}
}
} else {
item.properties.usertaskassignment = ''
}
}
} else {
console.log('发起者确定或者没有修改')
}
//判断定时器时间
if (values.activity !== undefined) {
item.properties.timerdatedefinition = values.timer
item.properties.cancelactivity = values.activity
}
//添加表单键
item.properties.formkeydefinition = values.formkey
return item
}
}
return item
})
if (flag) {
data.name = values.name
data.key = values.key
data.model.modelid = this.props.data.modelId
data.model.properties.process_id = values.key
data.model.properties.name = values.name
data.model.properties.process_author = values.author
data.model.properties.process_namespace = values.namespace
}
// console.log(data)
const newData = this.newData = this.deformation(data)//把新的数据转换为能展示的数据
// console.log(newData)
// newData.edges[8].controlPoints = [{ x: 3000, y: 1000 }]
const type = 'masg'
this.props.getprocess(data, newData, type);
}
//把线和节点重新构建
getNewMap = (itemMap, id) => {
let data = this.props.data
//初始化所有节点
let nodes = itemMap._nodes.map((item) => {
if (item.model.shape === 'flow-circle' || item.model.shape === 'EndNoneEvent') {
item = {
"resourceId": item.model.id,
"properties": {
"overrideid": "",
"name": item.model.label,
"documentation": "",
"executionlisteners": "",
"initiator": "userId",
"formkeydefinition": "",
"formreference": "",
"formproperties": ""
},
"stencil": {
"id": item.model.shape
},
"childShapes": [],
"outgoing": [],
"bounds": {
"lowerRight": {
"x": Number(item.model.x) + Number(item.model.size.split("*")[0]),
"y": Number(item.model.y) + Number(item.model.size.split("*")[1])
},
"upperLeft": {
"x": Number(item.model.x),
"y": Number(item.model.y)
}
},
"dockers": []
}
} else if (item.model.shape === 'UserTask') {
item = {
"resourceId": item.model.id,
"properties": {
"overrideid": "",
"name": item.model.label,
"documentation": "",
"asynchronousdefinition": "false",
"exclusivedefinition": "false",
"executionlisteners": "",
"multiinstance_type": "None",
"multiinstance_cardinality": "",
"multiinstance_collection": "",
"multiinstance_variable": "",
"multiinstance_condition": "",
"isforcompensation": "false",
"usertaskassignment": '',
"formkeydefinition": "",
"formreference": "",
"duedatedefinition": "",
"prioritydefinition": "",
"formproperties": "",
"tasklisteners": "",
"skipexpression": "",
"nodetype": "",
"iseditdata": ""
},
"stencil": {
"id": item.model.shape
},
"childShapes": [],
"outgoing": [],
"bounds": {
"lowerRight": {
"x": Number(item.model.x) + Number(item.model.size.split("*")[0]),
"y": Number(item.model.y) + Number(item.model.size.split("*")[1])
},
"upperLeft": {
"x": Number(item.model.x),
"y": Number(item.model.y)
}
},
"dockers": []
}
} else if (item.model.shape === 'StartNoneEvent') {
item = {
"resourceId": item.model.id,
"properties": {
"overrideid": "",
"name": item.model.label,
"documentation": "",
"executionlisteners": "",
"initiator": "userId",
"formkeydefinition": "",
"formreference": "",
"formproperties": ""
},
"stencil": {
"id": item.model.shape
},
"childShapes": [],
"outgoing": [],
"bounds": {
"lowerRight": {
"x": Number(item.model.x) + Number(item.model.size.split("*")[0]),
"y": Number(item.model.y) + Number(item.model.size.split("*")[1])
},
"upperLeft": {
"x": Number(item.model.x),
"y": Number(item.model.y)
}
},
"dockers": []
}
} else if (item.model.shape === 'BoundaryTimerEvent') {
// this.bindTimer(data)
item = {
"resourceId": item.model.id,
"properties": {
"overrideid": "",
"name": item.model.label,
"documentation": "",
"timercycledefinition": "",
"timerdatedefinition": "",
"timerdurationdefinition": "",
"timerenddatedefinition": "",
"cancelactivity": true
},
"stencil": {
"id": item.model.shape
},
"childShapes": [],
"outgoing": [],
"bounds": {
"lowerRight": {
"x": Number(item.model.x) + Number(item.model.size.split("*")[0]),
"y": Number(item.model.y) + Number(item.model.size.split("*")[1])
},
"upperLeft": {
"x": Number(item.model.x),
"y": Number(item.model.y)
}
},
"dockers": []
}
} else if (item.model.shape === 'ExclusiveGateway') {
item = {
"resourceId": item.model.id,
"properties": {
"overrideid": "",
"name": item.model.label,
"documentation": "",
"asynchronousdefinition": "false",
"exclusivedefinition": "false",
"sequencefloworder": ""
},
"stencil": {
"id": item.model.shape
},
"childShapes": [],
"outgoing": [],
"bounds": {
"lowerRight": {
"x": Number(item.model.x) + Number(item.model.size.split("*")[0]),
"y": Number(item.model.y) + Number(item.model.size.split("*")[1])
},
"upperLeft": {
"x": Number(item.model.x),
"y": Number(item.model.y)
}
},
"dockers": []
}
}
return item
})
//把已经有的节点重新赋值
data.model.childShapes.map(node => {
nodes = nodes.map((item) => {
if (item.resourceId === node.resourceId) {
let flag = true
//获取节点是的outgoing是否有定时器节点的id
node.outgoing.map(timerId => {
data.model.childShapes.map(timer => {
if (timer.stencil.id === 'BoundaryTimerEvent' && timerId.resourceId === timer.resourceId) {
// console.log(timerId, node.outgoing)
node.outgoing = []
node.outgoing.push(timerId)
flag = false
}
})
})
if (flag) {
node.outgoing = []
}
//清空节点定的bounds的值
node.bounds = item.bounds
return item = node
}
return item
})
})
let edges = itemMap._edges.map((item) => {
let conditions = ''
if (!!item.model.conditions) {
conditions = {
expression: {
"type": "static",
staticValue: item.model.conditions
}
}
}
return item = {
"resourceId": item.id,
"properties": {
"overrideid": item.model.overrideid,
"name": item.model.label,
"documentation": "",
"conditionsequenceflow": conditions,
"executionlisteners": "",
"defaultflow": "false",
"skipexpression": "",
"sequence_flow_text_x": "",
"targetAnchor": item.model.targetAnchor !== undefined ? item.model.targetAnchor : '',
"sourceAnchor": item.model.sourceAnchor !== undefined ? item.model.sourceAnchor : ''
},
"stencil": {
"id": "SequenceFlow"
},
"childShapes": [],
"outgoing": [
{
"resourceId": item.model.target
}
],
"bounds": {
"lowerRight": item.model.source,
"upperLeft": item.model.target
},
"dockers": [{ x: item.model.sourceAnchor * 50, y: item.model.sourceAnchor * 40 }, { x: item.model.targetAnchor * 50, y: item.model.targetAnchor * 40 }],
"target": {
"resourceId": item.model.target
}
}
})
//把已有的线重新赋值
data.model.childShapes.map(edge => {
edges = edges.map((item) => {
if (item.resourceId === edge.resourceId) {
if (item.resourceId == id) {
// console.log(item)
return item
}
return item = edge
}
return item
})
})
data.model.childShapes = edges
if (itemMap._edges.length == 0) {
data.model.childShapes = nodes
this.props.getprocess(data);
} else {
this.summary(nodes, itemMap._edges)
}
}
//结合线把nodes的指向完善
summary = (nodes, edges) => {
const { id } = this.item.getModel();
let stencil = ''
//得到节点的stencil
nodes.map(item => {
if (item.resourceId === id) {
stencil = item.stencil.id
}
})
if (edges.length > 0 && nodes.length > 0) {
//绑定线和节点
edges.map(item => {
nodes = nodes.map(node => {
if (node.resourceId === item.model.source) {
node.outgoing.push({ resourceId: item.id })
return node
} else {
return node
}
})
})
//是否移出定时器
if (stencil === 'BoundaryTimerEvent') {
// console.log(this.myNode, nodes)
nodes.map(item => {
item.outgoing = item.outgoing.filter(delItem => {
if (!!this.myNode && delItem.resourceId !== this.myNode.resourceId) {
return delItem
}
})
})
}
//是否绑定定时器到节点上
if (stencil === 'BoundaryTimerEvent') {
nodes.map(item => {
if (item.stencil.id === 'UserTask') {
nodes.map(timer => {
if (timer.stencil.id === 'BoundaryTimerEvent') {
const w = item.bounds.upperLeft.x + 50 - timer.bounds.upperLeft.x - 36
const h = item.bounds.upperLeft.y + 40 - timer.bounds.upperLeft.y - 36
if (-40 < w && w < 60 && -40 < h && h < 50) {
console.log(w, h, item.properties.name)
item.outgoing.push({ resourceId: timer.resourceId })
timer.dockers = [{
x: w,
y: h
}]
}
}
})
}
})
}
let data = this.props.data
data.model.childShapes = [...data.model.childShapes, ...nodes]
let type = 'node'
//判断是否是一个新边
if (this.newEdge) {
type = 'newEdge'
}
//判断是否移动的带有定时器的节点
let flag = false
if (this.stencil == 'UserTask') {
data.model.childShapes.map(item => {
this.myNode.outgoing.map(outgoingitem => {
if (item.resourceId == outgoingitem.resourceId && item.stencil.id == 'BoundaryTimerEvent') {
flag = true
}
})
})
}
// console.log(flag)
const isGetEvent = !!this.props.getEvent
if (this.stencil == 'UserTask' && flag && !isGetEvent) {
type = 'stencilNode'
// console.log(12566)
}
const newData = this.deformation(data)//把新的数据转换为能展示的数据
// console.log(data, newData)
this.props.getprocess(data, newData, type);
}
}
//把新的数据转换为能展示的数据
deformation = (data) => {
// console.log(data)
const arr = {
nodes: [],
edges: []
}
data.model.childShapes.map(item => {
if (item.stencil.id == "StartNoneEvent") {
const obj = {
type: 'node',
size: '55*55',
shape: 'StartNoneEvent',
label: item?.properties?.name ? item.properties.name : '',
x: item.bounds.upperLeft.x,
y: item.bounds.upperLeft.y,
id: item.resourceId,
}
// console.log(obj)
arr.nodes.push(obj)
} else if (item.stencil.id == "UserTask") {
const obj = {
type: 'node',
size: '60*48',
shape: 'UserTask',
// color: '#578586',
label: item.properties.name,
x: item.bounds.upperLeft.x,
y: item.bounds.upperLeft.y,
id: item.resourceId,
}
// console.log(obj)
arr.nodes.push(obj)
} else if (item.stencil.id == "SequenceFlow") {
data.model.childShapes.map(edge => {
if (edge.outgoing.length > 0) {
edge.outgoing.map(dome => {
if (dome.resourceId == item.resourceId) {
let staticValue = item?.properties?.conditionsequenceflow?.expression?.staticValue
const obj = {
source: edge.resourceId,
target: item.target.resourceId,
label: item.properties.name,
index: 1,
style: {
lineWidth: 4,
},
id: item.resourceId,
shape: "flow-polyline",
overrideid: item.properties.overrideid,
conditions: staticValue ? staticValue : '',
static: '',
controlPoints: [],
targetAnchor: item.properties.targetAnchor !== undefined ? item.properties.targetAnchor : '',
sourceAnchor: item.properties.sourceAnchor !== undefined ? item.properties.sourceAnchor : ''
}
arr.edges.push(obj)
}
})
}
})
} else if (item.stencil.id == "EndNoneEvent") {
const obj = {
type: 'node',
size: '55*55',
shape: 'EndNoneEvent',
label: item.properties.name,
x: item.bounds.upperLeft.x,
y: item.bounds.upperLeft.y,
id: item.resourceId,
}
// console.log(obj)
arr.nodes.push(obj)
} else if (item.stencil.id == "ExclusiveGateway") {
const obj = {
type: 'node',
size: '55*55',
shape: 'ExclusiveGateway',
label: '选择',
x: item.bounds.upperLeft.x,
y: item.bounds.upperLeft.y,
id: item.resourceId,
}
// console.log(obj)
arr.nodes.push(obj)
} else if (item.stencil.id == "BoundaryTimerEvent") {
let obj = {
type: 'node',
size: '55*55',
shape: 'BoundaryTimerEvent',
label: '计时器',
x: item.bounds.upperLeft.x,
y: item.bounds.upperLeft.y,
id: item.resourceId,
}
data.model.childShapes.map(node => {
if (node.outgoing.length > 0) {
node.outgoing.map(timer => {
if (timer.resourceId === item.resourceId) {
item.bounds.upperLeft = {
x: node.bounds.upperLeft.x + 45,
y: node.bounds.upperLeft.y + 39,
}
item.bounds.lowerRight = {
x: node.bounds.lowerRight.x - 10,
y: node.bounds.lowerRight.y - 16,
}
obj = {
type: 'node',
size: '55*55',
shape: 'BoundaryTimerEvent',
label: '计时器',
x: node.bounds.upperLeft.x + 45,
y: node.bounds.upperLeft.y + 39,
id: item.resourceId,
}
// console.log(obj)
}
})
}
})
arr.nodes.push(obj)
}
})
return arr
}
//固定定时器的位子
bindTimer = (nodes) => {
nodes.map(item => {
if (item.outgoing.length > 0) {
item.outgoing.map(outgoingid => {
nodes.map(timer => {
// { timer.stencil.id === 'BoundaryTimerEvent' ? console.log(outgoingid["resourceId "], timer.resourceId, 32555585) : 3655855 }
if (timer.stencil.id === 'BoundaryTimerEvent' && outgoingid["resourceId "] === timer.resourceId) {
const w = item.bounds.upperLeft.x + 50 - timer.bounds.upperLeft.x - 18
const h = item.bounds.upperLeft.y + 40 - timer.bounds.upperLeft.y - 18
console.log(w, h, item.properties.name)
timer.bounds.upperLeft = {
x: item.bounds.upperLeft.x - w,
y: item.bounds.upperLeft.y - h
}
// console.log(timer.bounds.upperLeft)
}
})
})
}
})
}
//是否打开监听器
onChange = (checked) => {
// console.log('change事件')
this.checked = checked
this.setState({
checked: checked,
judge: false
})
if (!checked) {
// console.log(!checked)
this.handleSubmit()
}
}
//监听器的下拉选项
listenerSelect = () => {
return (
<Select style={{ width: '160px' }}>
<Option value="start">开始</Option>
<Option value="end">结束</Option>
<Option value="take">任务中</Option>
</Select>
)
}
//监听器开关
switch = () => {
let numlisners = this.myNode?.properties?.executionlisteners?.executionListeners?.length
return (<>
<Switch checkedChildren="开" unCheckedChildren="关" defaultChecked={this.checked ? true : false} onChange={this.onChange} />
{numlisners ? numlisners + '个监听器' : ''}
</>
)
}
//展开点击事件
toggleForm = () => {
const { expand } = this.state;
this.setState({ expand: !expand });
}
//重置表单
handleFormReset = () => {
const { form } = this.props;
form.resetFields();
}
//删除表单
deleteLiseen = (index) => {
this?.myNode?.properties?.executionlisteners?.executionListeners?.splice(index, 1);
this.setState({
idRender: true
})
}
//监听器的box
renderSimpleForm = (golbalInfo) => {
const {
form: { getFieldDecorator },
} = this.props;
// console.log(558565, this.myNode)
const { label, id, detail, shape, userId, listener, timer, activity, category, things, expression } = golbalInfo
return (
// <Form onSubmit={this.handleSearch} layout="inline">
<Row className={styles.myRow} gutter={{ md: 8, lg: 24, xl: 48 }} >
<Item label="事件" {...inlineFormItemLayout}>
{getFieldDecorator('things', {
initialValue: things,
})(this.listenerSelect())}
</Item>
<Item label="类" {...inlineFormItemLayout}>
{getFieldDecorator('category', {
initialValue: category,
})(<Input />)}
</Item>
<Item label="表达式" {...inlineFormItemLayout}>
{getFieldDecorator('expression', {
initialValue: expression,
})(<Input />)}
</Item>
<Col md={8} sm={24} className={styles.myCol} style={{ paddingLeft: '24px', paddingRight: '10px' }}>
<span className={styles.submitButtons}>
<Button type="primary" htmlType="submit" onClick={() => { this.IsLisenner() }}>
保存
</Button>
<Button style={{ marginLeft: 8 }} onClick={this.handleFormReset}>
重置
</Button>
<a style={{ marginLeft: 8 }} onClick={this.toggleForm}>
{this.state.expand ? <span>关闭</span> : <span>展开</span>}
<Icon type={this.state.expand ? 'down' : 'right'} />
</a>
</span>
{this.state.expand ?
<div>
{this?.myNode?.properties?.executionlisteners?.executionListeners?.map((item, index) => {
return <div key={index}>
事件 : <span className={styles.mySpen}>{item.event}</span>
{item.expression.length > 0 || item.className.length > 0 ?
<Tooltip title={item.expression.length > 0 ? item.expression : item.className}>
<span
style={{ display: "inline-block", width: '83px', overflow: 'hidden', whiteSpace: 'nowrap', textOverflow: 'ellipsis', verticalAlign: 'bottom' }}>实现
: {item.expression.length > 0 ? item.expression : item.className}
</span>
</Tooltip>
: ''}
<Button type="danger" size="small" style={{ marginLeft: 3 }} onClick={() => { this.deleteLiseen(index) }}> 删除</Button>
</div>
}
)}
</div> : ''}
</Col>
</Row>
// </Form>
);
}
//判断是否添加监听器
IsLisenner = () => {
this.setState({
isAddlisner: true
}, () => {
if (this.state.isAddlisner) {
this.handleSubmit()
}
})
}
//分配人模态框
modal = () => {
// console.log(this.myNode)
const { form } = this.props;
const { initialFp, IsADD } = this.state
const type = this.myNode?.properties?.usertaskassignment?.assignment?.type
// console.log(type)
let num2 = ''//流程发起人的判断
//确定展示的分配人选项
let optionValue = '' //确定是类别
//个数判断
//候选人个数
let num = this.usertaskassignment?.assignment?.idm?.candidateUsers ? this.usertaskassignment.assignment.idm.candidateUsers.length : ''
if (this.state.idm.length > 0 || this.state.isCancel) {
num = this.state.idm.length
}
//动态分配个数
let num1 = this.usertaskassignment?.assignment?.candidateUsers ? this.usertaskassignment.assignment.candidateUsers.length : ''
if (this.state.dynamicAllocation.length > 0 || this.state.isCancel) {
num1 = 1
dynamicAllocation = this.state.dynamicAllocation[0]?.value
}
//分组个数
let num3 = this.usertaskassignment?.assignment?.idm?.candidateGroups ? this.usertaskassignment.assignment.idm.candidateGroups.length : ''
if (this.state.group.length > 0 || this.state.isCancel) {
num3 = this.state.group.length
}
//当动态分配时获取值
let dynamicAllocation = ''
if (!!num1) {
dynamicAllocation = this.state.dynamicAllocation[0]?.value
}
//类型判断
if (!initialFp && type) {
optionValue = type ? type : this.state.optionValue
if (optionValue == 'static' && this.myNode?.properties?.usertaskassignment?.assignment?.candidateUsers) {//做动态分配人的逻辑
optionValue = 'dynamicAllocation'
if (!this.myNode?.properties?.usertaskassignment?.assignment?.candidateUsers) {
optionValue = 'static'
}
} else if (optionValue == 'idm' && this.myNode?.properties?.usertaskassignment?.assignment?.idm?.candidateUsers) {//做候选人的逻辑
optionValue = 'idm'
if (!this.myNode?.properties?.usertaskassignment?.assignment?.idm?.candidateUsers) {
optionValue = 'static'
}
} else if (optionValue == 'static' && this.myNode?.properties?.usertaskassignment?.assignment?.assignee) {
optionValue = 'static'
//流程发起人
num2 = '流程发起人'
} else if (optionValue == 'idm' && this.myNode?.properties?.usertaskassignment?.assignment?.idm?.candidateGroups) {
optionValue = 'group'
}
} else {
// console.log(2)
// console.log(initialFp, this.valueDistriBution)
//清空个数
if (IsADD) {
num = num1 = num2 = num3 = ''
}
//判断转化类型和个数
if (!initialFp && !type) {//当初始进来和type没有的时候进入的判断
optionValue = 'static'
} else if (initialFp && this.valueDistriBution == 'static') {
optionValue = 'static'
this.valueDistriBution = ''
//流程发起人
num2 = '流程发起人'
num = num1 = num3 = ''
} else if (initialFp && this.valueDistriBution == 'dynamicAllocation') {
optionValue = 'dynamicAllocation'
// this.valueDistriBution = ''
if (this.state.dynamicAllocation.length > 0 || this.state.isCancel) {
num1 = 1
console.log(this.state.dynamicAllocation[0]?.value)
dynamicAllocation = this.state.dynamicAllocation[0]?.value
}
num2 = num = num3 = ''
} else if (initialFp && this.valueDistriBution == 'idm') {
optionValue = 'idm'
// this.valueDistriBution = ''
if (this.state.idm.length > 0 || this.state.isCancel) {
num = this.state.idm.length
}
num2 = num1 = num3 = ''
} else if (initialFp && this.valueDistriBution == 'group') {
optionValue = 'group'
// this.valueDistriBution = ''
if (this.state.group.length > 0 || this.state.isCancel) {
num3 = this.state.group.length
}
num2 = num1 = num = ''
} else {
optionValue = this.state.optionValue
}
}
//参数配置
const search = ''
const defaultperson = 'userId'
// console.log(optionValue)
return (
<div>
<Button type="primary" onClick={() => { this.showModal(optionValue) }}>分配</Button>
{!!num ? num + '个候选人' : ''}
{!!num1 ? num1 + '动态分配' : ''}
{!!num2 ? num2 : ''}
{!!num3 ? num3 + '个分组' : ''}
<Modal
title="分配"
visible={this.state.visible}
onOk={this.handleOk}
onCancel={this.handleCancel}
maskClosable={false}
destroyOnClose={true}
>
{form.getFieldDecorator('distriBution', {
initialValue: optionValue,
})(this.personSlect(optionValue))}
{optionValue == 'static' ?
<Item label="" {...inlineFormItemLayout}>
{form.getFieldDecorator('static', {
initialValue: defaultperson,
})(<div></div>)}
</Item> : ''}
{optionValue == 'dynamicAllocation' ?
<Item label="动态分配" {...inlineFormItemLayout}>
{form.getFieldDecorator('dynamicAllocation', {
initialValue: dynamicAllocation,
})(<Input onBlur={this.handleSubmit} />)}
</Item> : ''}
{optionValue == 'idm' ?
<Fragment>
<Item label="分配" {...inlineFormItemLayout}>
{form.getFieldDecorator('idm', {
initialValue: optionValue,
})(this.renderIdm())}
</Item>
<Item label="搜索" {...inlineFormItemLayout}>
{form.getFieldDecorator('search', {
initialValue: search,
})(this.searchList())}
</Item>
</Fragment>
: ''}
{optionValue == 'group' ?
<Fragment>
<Item label="分配" {...inlineFormItemLayout}>
{form.getFieldDecorator('group', {
initialValue: optionValue,
})(this.renderGroup())}
</Item>
<Item label="搜索" {...inlineFormItemLayout}>
{form.getFieldDecorator('search', {
initialValue: search,
})(this.searchGroupList())}
</Item>
</Fragment>
: ''}
</Modal>
</div>
)
}
//分配人下拉框
personSlect = (optionValue) => {
return (<Select onSelect={this.onSelect}>
<Option value="static">流程发起人</Option>
<Option value="dynamicAllocation">动态分配</Option>
<Option value="idm">候选人</Option>
<Option value="group">分组</Option>
</Select>)
}
//修改候选人分类
onSelect = (value) => {
// console.log(value);
this.valueDistriBution = ''
this.setState({
optionValue: value,
initialFp: true
})
}
//显示弹框
showModal = (optionValue) => {
// console.log(this.myNode)
let dynamicAllocation = []
let idm = []
let group = []
if (optionValue == 'idm') {
idm = this.myNode?.properties?.usertaskassignment?.assignment?.idm?.candidateUsers ?
this.myNode.properties.usertaskassignment.assignment.idm.candidateUsers : []
// console.log(idm)
}
if (optionValue == 'dynamicAllocation') {
dynamicAllocation = this.myNode?.properties?.usertaskassignment?.assignment?.candidateUsers ?
this.myNode.properties.usertaskassignment.assignment.candidateUsers : []
}
if (optionValue == 'group') {
group = this.myNode?.properties?.usertaskassignment?.assignment?.idm?.candidateGroups ?
this.myNode.properties.usertaskassignment.assignment.idm.candidateGroups : []
// console.log(group)
}
this.setState({
visible: true,
idm: idm,
group: group,
dynamicAllocation: dynamicAllocation,
optionValue: optionValue,
});
};
//得到动态分配人列表
getdtList = () => {
const person = 'person'
const { form } = this.props
let { dynamicAllocation } = this.state
const value = ''
return (
<Fragment>
{form.getFieldDecorator('addDynamicAlDlocation', {
initialValue: value,
})(<Input placeholder='请输入' />)}
<Button type="primary" onClick={this.addDynamicAlDlocation}>添加</Button>
{dynamicAllocation.map((item, index) => {
return (
<div key={index} className={styles.deleteDynamicAlDlocationBox}>
<span>{item.value}</span>
<Button className={styles.deleteDynamicAlDlocation} type="primary" onClick={() => { this.deleteDynamicAlDlocation(item.value) }}>删除</Button>
</div>
)
})}
</Fragment>
)
}
//添加动态分配
addDynamicAlDlocation = () => {
let dynamicAllocation = this.state.dynamicAllocation
const { form, dispatch } = this.props
let values = {}
setTimeout(() => {
values = form.getFieldsValue()
if (values.addDynamicAlDlocation !== '') {
const obj = {
"value": values.addDynamicAlDlocation,
"$$hashKey": ""
}
form.setFields({ "addDynamicAlDlocation": "" })
dynamicAllocation.push(obj)
// console.log(values, dynamicAllocation)
this.setState({
dynamicAllocation: values.dynamicAllocation,
IsADD: true
})
}
})
}
//删除不要的分配人
deleteDynamicAlDlocation = (value) => {
// console.log(value)
this.myStr = this.state.dynamicAllocation.filter(item => item.value !== value)
this.setState({
dynamicAllocation: this.myStr,
isCancel: true
})
}
//确定
handleOk = e => {
this.handleSubmit()
this.setState({
visible: false,
idm: this.state.idm,
dynamicAllocation: this.state.dynamicAllocation,
openModel: true,
isCancel: true,
});
};
//取消
handleCancel = e => {
this.setState({
visible: false,
isCancel: false,
IsLisenner: false,
initialFp: false,
});
};
//分组列表
renderGroup = () => {
return (
<div className={styles.personList}>
{this.state.group.map((item, index) => {
return <div key={index}>
<img src={textImg}></img>
<span>{item.name}</span>
<img className={styles.idmRemove} src={textImg} onClick={() => (this.removeGroup(item.id))}></img>
</div>
})}
</div>
)
}
//搜索分组数据
searchGroupList = () => {
return (
<div >
<Input onChange={() => { this.getServerGroupList() }} />
<div className={styles.searchList}>
{this.state.searchGroupList.map((item, index) => {
return <div key={index} onClick={() => (this.addGroup(item))}>
<img src={textImg}></img>
<span>{item.name}</span>
<img className={styles.idmRemove} src={textImg} ></img>
</div>
})}
</div>
</div>
)
}
//获取搜索数据
getServerGroupList = () => {
const { form, dispatch } = this.props
let values = {}
setTimeout(() => {
values = form.getFieldsValue()
if (values.search !== '') {
dispatch({
type: 'DataGgEditor/getGroupList',
payload: values.search,
callback: (response) => {
this.setState({
searchGroupList: response.data
})
}
})
} else {
this.setState({
searchGroupList: []
})
}
})
}
//添加分组人
addGroup = (person) => {
let flag = true
let group = this.state.group
this.state.group.map(item => {
if (item.id == person.id) {
flag = false
}
})
if (flag) {
group.push(person)
}
this.setState({
group: group,
IsADD: true
})
}
//删除分组人
removeGroup = (id) => {
let group = this.state.group.filter(item => {
if (item.id !== id) {
return item
}
})
this.setState({
group: group,
isCancel: true
})
}
//选定的候选人列表
renderIdm = (id) => {
return (
<div className={styles.personList}>
{this.state.idm.map((item, index) => {
return <div key={index}>
<img src={textImg}></img>
<span>{item.firstName}</span>
<img className={styles.idmRemove} src={textImg} onClick={() => (this.removeIdm(item.id))}></img>
</div>
})}
</div>
)
}
//搜索候选人列表
searchList = () => {
return (
<div >
<Input onChange={() => { this.getServerList() }} />
<div className={styles.searchList}>
{this.state.searchList.map((item, index) => {
return <div key={index} onClick={() => (this.addIdm(item))}>
<img src={textImg}></img>
<span>{item.firstName}</span>
<img className={styles.idmRemove} src={textImg} ></img>
</div>
})}
</div>
</div>
)
}
//获取搜索的数据
getServerList = () => {
const { form, dispatch } = this.props
let values = {}
setTimeout(() => {
values = form.getFieldsValue()
if (values.search !== '') {
dispatch({
type: 'DataGgEditor/getDistriBution',
payload: values.search,
callback: (response) => {
this.setState({
searchList: response.data
})
}
})
} else {
this.setState({
searchList: []
})
}
})
}
//删除不要的候选人
removeIdm = (id) => {
let idm = this.state.idm.filter(item => {
if (item.id !== id) {
return item
}
})
this.setState({
idm: idm,
isCancel: true
})
}
//添加候选人
addIdm = (person) => {
let flag = true
let idm = this.state.idm
this.state.idm.map(item => {
if (item.id == person.id) {
flag = false
}
})
if (flag) {
idm.push(person)
}
this.setState({
idm: idm,
IsADD: true
})
}
//activity多选框的函数
changeCheckBox = () => {
this.setState({
activity: !this.state.activity
})
}
//得到当前node
getNeedNode = (id) => {
const detail = this.props.data.model.childShapes.filter(item => {
if (item.resourceId === id) {
if (item.stencil.id == 'UserTask' || item.stencil.id == 'StartNoneEvent' || item.stencil.id == 'EndNoneEvent') {//判断是否是有监听器的节点
if (this.state.judge) {//判断是否开启监听器
const executionlisteners = item?.properties?.executionlisteners?.executionListeners?.length
this.checked = executionlisteners ? true : false
} else {
this.checked = this.state.checked
}
} else {
this.checked = this.state.checked
}
return item
}
})
if (detail.length == 0) return
this.myNode = detail[0]
//获取分配人
if (detail[0]?.properties?.usertaskassignment) {
this.usertaskassignment = detail[0].properties.usertaskassignment
this.distriBution = this.usertaskassignment.assignment ? this.usertaskassignment.assignment.type : 'static'
}
if (detail[0]?.properties?.cancelactivity) {
this.cancelactivity = detail[0].properties.cancelactivity
this.timerdatedefinition = detail[0].properties.timerdatedefinition
}
this.stencil = detail[0].stencil.id
//获取定时器
if (detail[0]?.properties?.executionlisteners) {
this.detail = detail[0].properties.executionlisteners.executionlisteners
return detail[0].properties.executionlisteners.executionListeners !== undefined ?
detail[0].properties.executionlisteners.executionListeners : this.detail
}
}
//获取需要的线
getNeededge = (id) => {
this.myedge = ''
this.props.data.model.childShapes.filter(item => {
if (item.resourceId === id) {
this.myedge = item
return item
}
})
}
//节点的具体数据
aginRender = () => {
const { form, getDrag, getEvent } = this.props;
let { id, shape } = !!getEvent ?
getEvent.item.model : !!getDrag.currentItem ?
getDrag.currentItem.model : this.MyE.model
this.getNeedNode(id)
console.log(this.myNode)
const label = this.myNode?.properties?.name ? this.myNode.properties.name : ''
let formkey = this.myNode?.properties?.formkeydefinition
const overrideid = this.myNode?.properties?.overrideid ? this.myNode.properties.overrideid : ''
const userId = 'userId'
const listener = this.checked
const timer = this.timerdatedefinition !== undefined ? this.timerdatedefinition : ''
const activity = this.cancelactivity
const category = ''
const things = 'start'
const expression = ''
// console.log(id, shape, label)
switch (shape) {
case 'StartNoneEvent':
case 'EndNoneEvent':
return <Fragment>
<Item label="标签名" {...inlineFormItemLayout}>
{form.getFieldDecorator('label', {
initialValue: label,
})(<Input onBlur={this.handleSubmit} />)}
</Item>
<Item style={{ display: 'none' }} label="" {...inlineFormItemLayout}>
{form.getFieldDecorator('id', {
initialValue: id,
})(<Input onBlur={this.handleSubmit} />)}
</Item>
<Item label="编号" {...inlineFormItemLayout}>
{form.getFieldDecorator('overrideid', {
initialValue: overrideid,
})(<Input onBlur={this.handleSubmit} />)}
</Item>
<Item label="监听器" {...inlineFormItemLayout}>
{form.getFieldDecorator('listener', {
initialValue: listener,
})(this.switch())}
</Item>
{this.state.checked && this.checked ?
<div>
{this.renderSimpleForm(golbalInfo)}
</div> : ''
}
</Fragment>
case 'UserTask':
return <Fragment>
<Item label="标签名" {...inlineFormItemLayout}>
{form.getFieldDecorator('label', {
initialValue: label,
})(<Input onBlur={this.handleSubmit} />)}
</Item>
<Item style={{ display: 'none' }} label="" {...inlineFormItemLayout}>
{form.getFieldDecorator('id', {
initialValue: id,
})(<Input onBlur={this.handleSubmit} />)}
</Item>
<Item label="表单键(key)" {...inlineFormItemLayout}>
{form.getFieldDecorator('formkey', {
initialValue: formkey,
})(<Input onBlur={this.handleSubmit} />)}
</Item>
<Item label="编号" {...inlineFormItemLayout}>
{form.getFieldDecorator('overrideid', {
initialValue: overrideid,
})(<Input onBlur={this.handleSubmit} />)}
</Item>
<Item label="分配人" {...inlineFormItemLayout}>
{form.getFieldDecorator('userId', {
initialValue: userId,
})(this.modal())}
</Item>
<Item label="监听器" {...inlineFormItemLayout}>
{form.getFieldDecorator('listener', {
initialValue: listener,
})(this.switch())}
</Item>
{this.state.checked && this.checked ?
<div>
{this.renderSimpleForm(golbalInfo)}
</div> : ''
}
</Fragment>
case 'BoundaryTimerEvent':
return <Fragment>
<Item label="标签名" {...inlineFormItemLayout}>
{form.getFieldDecorator('label', {
initialValue: label,
})(<Input onBlur={this.handleSubmit} />)}
</Item>
<Item style={{ display: 'none' }} label="" {...inlineFormItemLayout}>
{form.getFieldDecorator('id', {
initialValue: id,
})(<Input onBlur={this.handleSubmit} />)}
</Item>
<Item label="编号" {...inlineFormItemLayout}>
{form.getFieldDecorator('overrideid', {
initialValue: overrideid,
})(<Input onBlur={this.handleSubmit} />)}
</Item>
<Item label="开启时间" {...inlineFormItemLayout}>
{form.getFieldDecorator('timer', {
initialValue: timer,
})(<Input onBlur={this.handleSubmit} />)}
</Item>
<Item label="Activity" {...inlineFormItemLayout}>
{form.getFieldDecorator('activity', {
initialValue: activity,
})(<Checkbox defaultChecked={activity} onClick={this.changeCheckBox, this.handleSubmit}></Checkbox>)}
</Item>
</Fragment>
case 'ExclusiveGateway':
return <Fragment>
<Item label="标签名" {...inlineFormItemLayout}>
{form.getFieldDecorator('label', {
initialValue: label,
})(<Input onBlur={this.handleSubmit} />)}
</Item>
<Item style={{ display: 'none' }} label="" {...inlineFormItemLayout}>
{form.getFieldDecorator('id', {
initialValue: id,
})(<Input onBlur={this.handleSubmit} />)}
</Item>
<Item label="编号" {...inlineFormItemLayout}>
{form.getFieldDecorator('overrideid', {
initialValue: overrideid,
})(<Input onBlur={this.handleSubmit} />)}
</Item>
</Fragment>
default:
return <span>缺乏匹配项</span>
}
}
//线的参数
aginRenderEdge = () => {
const { form, getEvent } = this.props;
const { label, id, shape, overrideid, conditions } = getEvent.item.model
// const label = this.MyE.model.label,
// shape = this.MyE.model.shape,
// id = this.MyE.model.id,
// overrideid = this.MyE.model.overrideid,
// conditions = this.MyE.model.conditions
return (
<Fragment>
<Item label="标签名" {...inlineFormItemLayout}>
{form.getFieldDecorator('label', {
initialValue: label,
})(<Input onBlur={this.handleSubmit} />)}
</Item>
<Item label="Shape" style={{ display: 'none' }} {...inlineFormItemLayout}>
{form.getFieldDecorator('shape', {
initialValue: shape,
})(this.renderEdgeShapeSelect())}
</Item>
<Item style={{ display: 'none' }} label="" {...inlineFormItemLayout}>
{form.getFieldDecorator('id', {
initialValue: id,
})(<Input onBlur={this.handleSubmit} />)}
</Item>
<Item label="编号" {...inlineFormItemLayout}>
{form.getFieldDecorator('overrideid', {
initialValue: overrideid,
})(<Input onBlur={this.handleSubmit} />)}
</Item>
<Item label="流条件" {...inlineFormItemLayout}>
{form.getFieldDecorator('conditions', {
initialValue: conditions,
})(<Input onBlur={this.handleSubmit} />)}
</Item>
</Fragment>
);
}
//canvas的参数
aginRendercanvas = () => {
const { form, data } = this.props;
const name = Object.keys(this.state.values).length > 0 ? this.state.values.name : data.name,
key = Object.keys(this.state.values).length > 0 ? this.state.values.key : data.key
let author = '', namespace = ''
data.model !== undefined ?
author = Object.keys(this.state.values).length > 0 ?
this.state.values.author : data.model.properties.process_author : ''
data.model !== undefined ?
namespace = Object.keys(this.state.values).length > 0 ?
this.state.values.namespace : data.model.properties.process_namespace : ''
return (
<Fragment>
<Item label="name" {...inlineFormItemLayout}>
{form.getFieldDecorator('name', {
initialValue: name,
})(<Input onBlur={this.handleSubmit} />)}
</Item>
<Item label="key" {...inlineFormItemLayout}>
{form.getFieldDecorator('key', {
initialValue: key,
})(<Input onBlur={this.handleSubmit} />)}
</Item>
<Item label="author" {...inlineFormItemLayout}>
{form.getFieldDecorator('author', {
initialValue: author,
})(<Input onBlur={this.handleSubmit} />)}
</Item>
<Item label="namespace" {...inlineFormItemLayout}>
{form.getFieldDecorator('namespace', {
initialValue: namespace,
})(<Input onBlur={this.handleSubmit} />)}
</Item>
</Fragment>
);
}
//线的显示样式
renderEdgeShapeSelect = () => {
return (
<Select onChange={this.handleSubmit}>
<Option value="flow-smooth">Smooth</Option>
<Option value="flow-polyline">Polyline</Option>
<Option value="flow-polyline-round">Polyline Round</Option>
</Select>
);
};
//跟新数据调用的函数
towRender = () => {
// console.log(golbalInfo)
const { getDrag, getEvent, getDragEnd } = this.props;
console.log('第二次点击', this.MyE)
// console.log(getDrag, getEvent)
const isGetEvent = !!getEvent
const isGetDrag = !!getDrag
let type = ''
if (isGetEvent && !isGetDrag) {
type = !!getEvent.item ? getEvent.item.type : 'canvas'
// console.log(getEvent)
if (getEvent.item) {
if (!getEvent.item.model.shape && !!getDragEnd) {
type = 'canvas'
}
}
} else if (!isGetEvent && isGetDrag) {
type = !!getDrag.currentItem ? getDrag.currentItem.type : 'canvas'
}
// console.log(type)
// let type = !!getEvent ? getEvent.item.type : !!getDrag.currentItem ? getDrag.currentItem.type : 'canvas'
return (
<Card type="inner" size="small" title={type} bordered={false}>
<Form onSubmit={this.handleSubmit}>
{type === 'node' && this.aginRender()}
{type === 'edge' && this.aginRenderEdge()}
{type === 'canvas' && this.aginRendercanvas()}
</Form>
</Card>
);
}
//移动节点是改变定时器的位子
moveTimer = (item) => {
item.itemMap._nodes.map(timer => {
if (timer.model.shape == "BoundaryTimerEvent") {
console.log(1236)
timer.model.x = 900
}
})
}
renderNodeDetail = () => {
const { form, propsAPI } = this.props;
const { getSelected } = propsAPI;
const { label, id } = this.item.getModel();
const item = getSelected()[0];
this.MyE = this.item//在更新视图后保留住this.item
console.log(this.item)
console.log(this.myNode)
const detail = this.getNeedNode(id)
this.getNewMap(item.itemMap)
this.getNeedNode(id)
this.isAddEdge(this.item)
let overrideid = this.myNode?.properties?.overrideid
overrideid = overrideid ? overrideid : ''
let formkey = this.myNode?.properties?.formkeydefinition
const shape = item.model.shape
const userId = 'userId'
const listener = this.checked
const timer = this.timerdatedefinition !== undefined ? this.timerdatedefinition : ''
const activity = this.cancelactivity
const category = ''
const things = 'start'
const expression = ''
golbalInfo = { label, id, overrideid, detail, shape, userId, listener, timer, activity, category, things, expression, type: 'node' }
switch (shape) {
case 'StartNoneEvent':
case 'EndNoneEvent':
return <Fragment>
<Item label="标签名" {...inlineFormItemLayout}>
{form.getFieldDecorator('label', {
initialValue: label,
})(<Input onBlur={this.handleSubmit} />)}
</Item>
<Item style={{ display: 'none' }} label="" {...inlineFormItemLayout}>
{form.getFieldDecorator('id', {
initialValue: id,
})(<Input onBlur={this.handleSubmit} />)}
</Item>
<Item label="编号" {...inlineFormItemLayout}>
{form.getFieldDecorator('overrideid', {
initialValue: overrideid,
})(<Input onBlur={this.handleSubmit} />)}
</Item>
<Item label="监听器" {...inlineFormItemLayout}>
{form.getFieldDecorator('listener', {
initialValue: listener,
})(this.switch())}
</Item>
{this.state.checked && this.checked ?
<div>
{this.renderSimpleForm(golbalInfo)}
</div> : ''
}
</Fragment>
case 'UserTask':
return <Fragment>
<Item label="标签名" {...inlineFormItemLayout}>
{form.getFieldDecorator('label', {
initialValue: label,
})(<Input onBlur={this.handleSubmit} />)}
</Item>
<Item style={{ display: 'none' }} label="" {...inlineFormItemLayout}>
{form.getFieldDecorator('id', {
initialValue: id,
})(<Input onBlur={this.handleSubmit} />)}
</Item>
<Item label="表单键(key)" {...inlineFormItemLayout}>
{form.getFieldDecorator('formkey', {
initialValue: formkey,
})(<Input onBlur={this.handleSubmit} />)}
</Item>
<Item label="编号" {...inlineFormItemLayout}>
{form.getFieldDecorator('overrideid', {
initialValue: overrideid,
})(<Input onBlur={this.handleSubmit} />)}
</Item>
<Item label="分配人" {...inlineFormItemLayout}>
{form.getFieldDecorator('userId', {
initialValue: userId,
})(this.modal())}
</Item>
<Item label="监听器" {...inlineFormItemLayout}>
{form.getFieldDecorator('listener', {
initialValue: listener,
})(this.switch())}
</Item>
{this.state.checked && this.checked ?
<div>
{this.renderSimpleForm(golbalInfo)}
</div> : ''
}
</Fragment>
case 'BoundaryTimerEvent':
return <Fragment>
<Item label="标签名" {...inlineFormItemLayout}>
{form.getFieldDecorator('label', {
initialValue: label,
})(<Input onBlur={this.handleSubmit} />)}
</Item>
<Item style={{ display: 'none' }} label="" {...inlineFormItemLayout}>
{form.getFieldDecorator('id', {
initialValue: id,
})(<Input onBlur={this.handleSubmit} />)}
</Item>
<Item label="编号" {...inlineFormItemLayout}>
{form.getFieldDecorator('overrideid', {
initialValue: overrideid,
})(<Input onBlur={this.handleSubmit} />)}
</Item>
<Item label="开启时间" {...inlineFormItemLayout}>
{form.getFieldDecorator('timer', {
initialValue: timer,
})(<Input onBlur={this.handleSubmit} />)}
</Item>
<Item label="Activity" {...inlineFormItemLayout}>
{form.getFieldDecorator('activity', {
initialValue: activity,
})(<Checkbox defaultChecked={activity} onClick={this.changeCheckBox, this.handleSubmit}></Checkbox>)}
</Item>
</Fragment>
case 'ExclusiveGateway':
return <Fragment>
<Item label="标签名" {...inlineFormItemLayout}>
{form.getFieldDecorator('label', {
initialValue: label,
})(<Input onBlur={this.handleSubmit} />)}
</Item>
<Item style={{ display: 'none' }} label="" {...inlineFormItemLayout}>
{form.getFieldDecorator('id', {
initialValue: id,
})(<Input onBlur={this.handleSubmit} />)}
</Item>
<Item label="编号" {...inlineFormItemLayout}>
{form.getFieldDecorator('overrideid', {
initialValue: overrideid,
})(<Input onBlur={this.handleSubmit} />)}
</Item>
</Fragment>
default:
return <span>缺乏匹配项</span>
}
};
//判断是否有新赠线条
isAddEdge = (item) => {
let flag = false
this.newEdge = false
item.itemMap._edges.filter(edge => {
if (edge.model.style == undefined) {
// console.log(2155688)
this.newEdge = true
flag = true
return edge
}
})
if (flag) {
this.getNewMap(item.itemMap, item.id)
}
}
renderEdgeDetail = () => {
const { form, propsAPI } = this.props;
const { label = '', shape = 'flow-polyline', id } = this.item.getModel();
console.log(this.item)
this.MyE = this.item//在更新视图后保留住this.item
// this.item.keyShape._attrs.lineWidth = 20//修改选中后的样式
this.getNeededge(id)
this.sourceAnchor = this.item.model.sourceAnchor !== undefined ? this.item.model.sourceAnchor : ''
this.targetAnchor = this.item.model.targetAnchor !== undefined ? this.item.model.targetAnchor : ''
let overrideid = ''
let conditions = ''
console.log(this.myedge)
this.isAddEdge(this.item)
if (!!this.myedge) {//判断是否有这个边
overrideid = this.myedge.properties.overrideid
let value = this.myedge?.properties?.conditionsequenceflow?.expression?.staticValue
// console.log(value)
conditions = value ? value : ''
// console.log(conditions)
}
this.getNewMap(this.item.itemMap, id)
golbalInfo = { label, shape, id, overrideid, conditions, type: 'edge' }
return (
<Fragment>
<Item label="标签名" {...inlineFormItemLayout}>
{form.getFieldDecorator('label', {
initialValue: label,
})(<Input onBlur={this.handleSubmit} />)}
</Item>
<Item label="Shape" style={{ display: 'none' }} {...inlineFormItemLayout}>
{form.getFieldDecorator('shape', {
initialValue: shape,
})(this.renderEdgeShapeSelect())}
</Item>
<Item style={{ display: 'none' }} label="" {...inlineFormItemLayout}>
{form.getFieldDecorator('id', {
initialValue: id,
})(<Input onBlur={this.handleSubmit} />)}
</Item>
<Item label="编号" {...inlineFormItemLayout}>
{form.getFieldDecorator('overrideid', {
initialValue: overrideid,
})(<Input onBlur={this.handleSubmit} />)}
</Item>
<Item label="流条件" {...inlineFormItemLayout}>
{form.getFieldDecorator('conditions', {
initialValue: conditions,
})(<Input onBlur={this.handleSubmit} />)}
</Item>
</Fragment>
);
};
renderGroupDetail = () => {
const { form } = this.props;
const { label = '新建分组' } = this.item.getModel();
return (
<Item label="Label" {...inlineFormItemLayout}>
{form.getFieldDecorator('label', {
initialValue: label,
})(<Input onBlur={this.handleSubmit} />)}
</Item>
);
};
renderCanvasDetail = () => {
const { form, data } = this.props;
const name = Object.keys(this.state.values).length > 0 ? this.state.values.name : data.name,
key = Object.keys(this.state.values).length > 0 ? this.state.values.key : data.key
let author = '', namespace = ''
data.model !== undefined ?
author = Object.keys(this.state.values).length > 0 ?
this.state.values.author : data.model.properties.process_author : ''
data.model !== undefined ?
namespace = Object.keys(this.state.values).length > 0 ?
this.state.values.namespace : data.model.properties.process_namespace : ''
return (
<Card type="inner" size="small" title="Canvas" bordered={false}>
<Fragment>
<Item label="name" {...inlineFormItemLayout}>
{form.getFieldDecorator('name', {
initialValue: name,
})(<Input onBlur={this.handleSubmit} />)}
</Item>
<Item label="key" {...inlineFormItemLayout}>
{form.getFieldDecorator('key', {
initialValue: key,
})(<Input onBlur={this.handleSubmit} />)}
</Item>
<Item label="author" {...inlineFormItemLayout}>
{form.getFieldDecorator('author', {
initialValue: author,
})(<Input onBlur={this.handleSubmit} />)}
</Item>
<Item label="namespace" {...inlineFormItemLayout}>
{form.getFieldDecorator('namespace', {
initialValue: namespace,
})(<Input onBlur={this.handleSubmit} />)}
</Item>
</Fragment>
</Card>
);
}
render() {
const { type } = this.props;
// console.log(this.props)
if (type === 'canvas' || this.props.isDelete == true) {
return this.renderCanvasDetail()
}
// console.log('再次执行render', this.item)
if (!this.item) {
// console.log(545544)
return this.towRender();
}
return (
<Card type="inner" size="small" title={upperFirst(type)} bordered={false}>
<Form onSubmit={this.handleSubmit}>
{type === 'node' && this.renderNodeDetail()}
{type === 'edge' && this.renderEdgeDetail()}
{type === 'group' && this.renderGroupDetail()}
</Form>
</Card>
);
}
}
export default Form.create()(withPropsAPI(DetailForm));
import React from 'react';
import { Card } from 'antd';
import { NodePanel, EdgePanel, GroupPanel, MultiPanel, CanvasPanel, DetailPanel } from 'gg-editor';
import DetailForm from './DetailForm';
import styles from './index.less';
import GetDetail from '../GetDetail'
const FlowDetailPanel = ({ getDrag, getDragEnd, getprocess, data, getEvent, isDelete }) => {
// console.log(getEvent)
return (
<DetailPanel className={styles.detailPanel}>
<NodePanel>
<DetailForm
type="node"
getDragEnd={getDragEnd}
getDrag={getDrag}
getEvent={getEvent}
data={data} getprocess={getprocess}
isDelete={isDelete}
/>
{/* <GetDetail type="node" getprocess={getprocess} /> */}
</NodePanel>
<EdgePanel>
<DetailForm type="edge"
getDragEnd={getDragEnd}
getEvent={getEvent}
data={data}
getprocess={getprocess}
isDelete={isDelete}
/>
{/* <GetDetail type="edge" getprocess={getprocess} /> */}
</EdgePanel>
<GroupPanel>
<DetailForm type="group"
getEvent={getEvent} data={data}
getprocess={getprocess}
/>
{/* <GetDetail type="group" getprocess={getprocess} /> */}
</GroupPanel>
<MultiPanel>
<Card type="inner" size="small" title="Multi Select" bordered={false} />
</MultiPanel>
<CanvasPanel>
{/* <Card type="inner" size="small" title="Canvas" bordered={false} /> */}
<DetailForm type="canvas"
getEvent={getEvent}
data={data}
getprocess={getprocess}
/>
{/* <GetDetail type="canvas" getprocess={getprocess} /> */}
</CanvasPanel>
</DetailPanel>
);
};
export default FlowDetailPanel;
import FlowDetailPanel from './FlowDetailPanel';
export { FlowDetailPanel };
.detailPanel {
flex: 1;
background: #fafafa;
:global {
.ant-card {
background: #fafafa;
.ant-form-item{
margin:0;
input{
width: 160px;
}
}
}
}
.myRow{
margin:0!important;
div{
display: block;
}
.myCol{
width: 100%;
padding-left:20px!important;
margin-top: 10px;
Button {
margin-right: 10px;
}
}
.mySpen{
margin-right: 5px;
}
}
}
.idmRemove{
float: right;
margin-top: 10px;
}
.searchList{
height: 200px;
overflow: auto;
cursor:pointer;
}
.personList{
max-height: 200px;
overflow: auto;
}
.deleteDynamicAlDlocationBox{
border-bottom: 1px solid #cccccc;
.deleteDynamicAlDlocation{
float:right;
margin-top: 5px;
}
}
import React from 'react';
import { Card, Collapse, Icon } from 'antd';
import { ItemPanel, Item, RegisterNode } from 'gg-editor';
import styles from './index.less';
import textImg from '@/assets/down.png'
import UserTaskImg from '@/assets/UserTaskImg.png'
import StartNoneEvent from '@/assets/StartNoneEvent.png'
import EndNoneEvent from '@/assets/EndNoneEvent.png'
import BoundaryTimerEvent from '@/assets/BoundaryTimerEvent.png'
import ExclusiveGateway from '@/assets/ExclusiveGateway.png'
const { Panel } = Collapse;
const FlowItemPanel = (props) => {
let { maxX, minY } = props
return (
// {/* 画板中的节点样式由 model 控制,而节点预览样式由 CSS 或者图片控制, */}
// {/* model: {
// color: '#333', // 节点主题色(选中颜色、激活颜色基于该值)
// size: [10, 10], // [x, y] 节点尺寸
// shape: 'cirle', // 图形:圆形 circle | 圆角矩形 rect | 菱形 rhombus | 椭圆矩形 capsule
// style: { // 关键形样式(可覆盖color的普通样式,但激活、选中依然无效,坑!)
// fill: 'red', // 填充背景
// stroke: 'blue' // 形状描边
// },
// label: { // 节点标签
// text: '开始节点', // 文本内容
// fill: 'green' // 文本颜色
// },
// index: 1 // 渲染层级
// } */}
//
<Collapse accordion className={styles.itemPanelBox}>
<Panel header="启动事件" key="2">
<ItemPanel className={styles.itemPanel}>
<Card bordered={false}>
<Item
type="node"
size="20*20"
shape="StartNoneEvent"
model={{
label: '开始',
}}
// src={StartNoneEvent}
/>
<img src={StartNoneEvent}></img>
<span>开始事件</span>
</Card>
</ItemPanel>
<ItemPanel className={styles.itemPanel}>
<Card bordered={false}>
<Item
type="node"
size="20*20"
shape="EndNoneEvent"
model={{
label: '结束',
}}
// src={EndNoneEvent}
/>
<img src={EndNoneEvent}></img>
<span>结束事件</span>
</Card>
</ItemPanel>
</Panel>
<Panel header="任务" key="3">
<ItemPanel className={styles.itemPanel}>
<Card bordered={false}>
<Item
type="node"
size="80*48"
shape="UserTask"
model={{
label: '',
}}
// src={UserTaskImg}
/>
<img src={UserTaskImg}></img>
<span>任务</span>
</Card>
</ItemPanel>
</Panel>
<Panel header="定时器" key="4">
<ItemPanel className={styles.itemPanel}>
<Card bordered={false}>
<Item
type="node"
size="20*20"
shape="BoundaryTimerEvent"
model={{
color: '#578586',
label: '定时器',
}}
src={BoundaryTimerEvent}
/>
<img src={BoundaryTimerEvent}></img>
<span>定时器</span>
</Card>
</ItemPanel>
</Panel>
<Panel header="网关" key="5">
<ItemPanel className={styles.itemPanel}>
<Card bordered={false}>
<Item
type="node"
size="20*20"
shape="ExclusiveGateway"
model={{
color: '#578586',
label: '网关',
}}
// src={ExclusiveGateway}
/>
<img src={ExclusiveGateway}></img>
<span>网关</span>
</Card>
</ItemPanel>
</Panel>
{maxX !== 0 && minY !== 0 ?
<div id={styles.more} className={styles.more} style={{ left: maxX + 274 + "px", top: minY + 'px' }}>
<ItemPanel className={styles.myItemPanel}>
<Card bordered={false} className='myCard'>
<Item
type="node"
size="20*20"
shape="StartNoneEvent"
model={{
label: '开始',
}}
/>
<img src={StartNoneEvent}></img>
</Card>
<Card bordered={false} className='myCard'>
<Item
type="node"
size="80*48"
shape="UserTask"
model={{
label: '',
}}
/>
<img src={UserTaskImg}></img>
</Card>
<Card bordered={false} className='myCard'>
<Item
type="node"
size="20*20"
shape="EndNoneEvent"
model={{
label: '结束',
}}
/>
<img src={EndNoneEvent}></img>
</Card>
</ItemPanel>
</div> : ''}
</Collapse>
);
};
export default FlowItemPanel;
import FlowItemPanel from './FlowItemPanel';
export { FlowItemPanel };
.itemPanelBox{
position: relative;
:global{
.ant-collapse-content > .ant-collapse-content-box {
padding: 0;
}
}
.itemPanel {
flex: 1;
background: #fafafa;
user-select:none;
:global{
.ant-card {
background: #fafafa;
}
.ant-card-body {
display: flex;
flex-direction: column;
align-items: center;
padding:5px;
position: relative;
div{
height: 20px;
width: 60%;
z-index: 2;
}
span{
position: absolute;
left: 29%;
top: 7px;
}
img{
position: absolute;
left: 58px;
top: 11px;
height: 14px;
width: 14px;
}
}
}
}
#more{
position: absolute;
opacity: 0.5;
z-index: 10;
.myItemPanel{
display: flex;
user-select:none;
background: #cccccc;
}
:global{
.myCard{
background:#cccccc;
padding:2px;
.ant-card-body {
display: flex;
flex-direction: column;
align-items: center;
padding:5px;
position: relative;
div{
height: 20px;
width: 20px;
z-index: 2;
}
img{
position: absolute;
left: 7px;
top: 6px;
height: 16px;
width: 16px;
}
}
}
}
}
}
import React from 'react';
import { Card } from 'antd';
import { Minimap } from 'gg-editor';
const EditorMinimap = () => {
return (
<div>
<div
style={{ fontSize: 14, borderTop: '1px solid #CCCCCC', borderBottom: '1px solid #CCCCCC', padding: 10, fontWeight: "bold" }}>小地图
</div>
<Minimap height={200} />
</div>
);
};
export default EditorMinimap;
import React from 'react';
import { Divider } from 'antd';
import { Toolbar } from 'gg-editor';
import ToolbarButton from './ToolbarButton';
import styles from './index.less';
const FlowToolbar = () => {
return (
<Toolbar className={styles.toolbar}>
<ToolbarButton command="undo" />
<ToolbarButton command="redo" />
<Divider type="vertical" />
<ToolbarButton command="copy" />
<ToolbarButton command="paste" />
<ToolbarButton command="delete" />
<Divider type="vertical" />
<ToolbarButton command="zoomIn" icon="zoom-in" text="Zoom In" />
<ToolbarButton command="zoomOut" icon="zoom-out" text="Zoom Out" />
<ToolbarButton command="autoZoom" icon="fit-map" text="Fit Map" />
<ToolbarButton command="resetZoom" icon="actual-size" text="Actual Size" />
<Divider type="vertical" />
<ToolbarButton command="toBack" icon="to-back" text="To Back" />
<ToolbarButton command="toFront" icon="to-front" text="To Front" />
<Divider type="vertical" />
<ToolbarButton command="multiSelect" icon="multi-select" text="Multi Select" />
<ToolbarButton command="addGroup" icon="group" text="Add Group" />
<ToolbarButton command="unGroup" icon="ungroup" text="Ungroup" />
</Toolbar>
);
};
export default FlowToolbar;
import React from 'react';
import { Tooltip } from 'antd';
import { Command } from 'gg-editor';
import upperFirst from 'lodash/upperFirst';
import IconFont from '../../common/IconFont';
import styles from './index.less';
const ToolbarButton = (props) => {
const { command, icon, text } = props;
return (
<Command name={command}>
<Tooltip
title={text || upperFirst(command)}
placement="bottom"
overlayClassName={styles.tooltip}
>
<IconFont type={`icon-${icon || command}`} />
</Tooltip>
</Command>
);
};
export default ToolbarButton;
import FlowToolbar from './FlowToolbar';
export { FlowToolbar };
.toolbar {
display: flex;
align-items: center;
:global {
.command i {
display: inline-block;
width: 27px;
height: 27px;
margin: 0 6px;
padding-top: 6px;
text-align: center;
border: 1px solid #fff;
cursor: pointer;
&:hover {
border: 1px solid #e6e9ed;
}
}
.disable i {
color: rgba(0, 0, 0, 0.25);
cursor: auto;
&:hover {
border: 1px solid #fff;
}
}
}
}
.tooltip {
:global {
.ant-tooltip-inner {
font-size: 12px;
border-radius: 0;
}
}
}
import React from 'react';
import { withPropsAPI } from 'gg-editor';
import { Card } from 'antd';
var allmasg = {
"modelId": "85ca0dfc-26bc-11ea-b653-02424e738a18",
"name": "流程名称zy1209659076275863552",
"key": "zy1209659076275863552",
"description": "",
"lastUpdated": 1577695506731,
"lastUpdatedBy": "admin",
"model": {
"modelId": "85ca0dfc-26bc-11ea-b653-02424e738a18",
"bounds": {
"lowerRight": {
"x": 0,
"y": 0
},
"upperLeft": {
"x": 0,
"y": 0
}
},
"properties": {
"process_id": "zy1209659076275863552",
"name": "流程名称zy1209659076275863552",
"documentation": "",
"process_author": "",
"process_version": "",
"process_namespace": "http://www.flowable.org/processdef",
"process_historylevel": "",
"isexecutable": true,
"dataproperties": "",
"executionlisteners": "",
"eventlisteners": "",
"signaldefinitions": "",
"messagedefinitions": "",
"process_potentialstarteruser": "",
"process_potentialstartergroup": "",
"iseagerexecutionfetch": "false"
},
"childShapes": [],
"stencil": {
"id": "BPMNDiagram"
},
"stencilset": {
"namespace": "http://b3mn.org/stencilset/bpmn2.0#",
"url": "../editor/stencilsets/bpmn2.0/bpmn2.0.json"
},
"modelType": "model"
}
}//结合节点和线
class GetDetail extends React.Component {
get item() {
const { propsAPI } = this.props;
return propsAPI.getSelected()[0];
}
summary = (nodes, edges) => {//把节点和线结合起来
if (edges.length > 0 && nodes.length > 0) {
edges.map(item => {
nodes = nodes.map(node => {
if (node.resourceId === item.source) {
node.outgoing.push({ "resourceId ": item.target })
return node
} else {
return node
}
})
})
allmasg.model.childShapes = nodes
this.props.getprocess(allmasg);
}
}
allnodes = (itemMap) => {//把canvas中的信息分类
// console.log(itemMap._nodes)
const nodes = itemMap._nodes.map((item) => {
// console.log(item.model)
return item = {
"resourceId": item.model.id,//组件的id
"properties": {//组件的属性
"overrideid": "jd1",
"name": item.model.label,
"documentation": "",
"executionlisteners": "",
"initiator": "userId",
"formkeydefinition": "",
"formreference": "",
"formproperties": ""
},
"stencil": {
"id": item.model.shape
},
"childShapes": {//子类的组件
},
"outgoing": [],//要去的组件
"bounds": {//组件的大小
"lowerRight": {//右下角
"x": Number(item.model.x) + Number(item.model.size.split("*")[0]),
"y": Number(item.model.y) + Number(item.model.size.split("*")[1])
},
"upperLeft": {//左上角
"x": Number(item.model.x),
"y": Number(item.model.y)
}
},
"dockers": []
}
})
// console.log(nodes)
//结合线条和节点
if (itemMap._edges.length == 0) {
allmasg.model.childShapes = nodes
// console.log(allmasg)
} else {
this.summary(nodes, itemMap._edges)
}
}
getNodeDetail = () => {
const { form, propsAPI } = this.props;
const { getSelected } = propsAPI;
const { label } = this.item.getModel();
const item = getSelected()[0];
// console.log(item)
this.allnodes(item.itemMap)//信息分类
// this.getDetail(item)
}
getEdgeDetail = () => {
this.edgeInfo = this.item.getModel()
// console.log(this.item)
// this.addEdges(this.edgeInfo)
this.allnodes(this.item.itemMap)//信息分类
};
getGroupDetail = () => {
const { form } = this.props;
const { label = '新建分组' } = this.item.getModel();
console.log('group', this.item)
};
getCanvasDetail = () => {//点击canvas时运行的方法
// console.log(1)
}
render() {
const { type } = this.props;
return (
<Card type="inner" size="small" bordered={false}>
{type === 'node' && this.getNodeDetail()}
{type === 'edge' && this.getEdgeDetail()}
{type === 'group' && this.getGroupDetail()}
{type === 'canvas' && this.getCanvasDetail()}
</Card>
);
}
}
export default withPropsAPI(GetDetail);
import React, { Component } from 'react'
import { connect } from 'dva';
import { Input } from 'antd'
import styles from '../../Flow/index.less'
//引入dispath
@connect(({ DataGgEditor, loading }) => ({
DataGgEditor,
loading: loading.models.DataGgEditor,
}))
export default class GetProcess extends Component {
constructor(props) {
super(props)
this.state = {
data: {},
value: this.props.value
}
}
//请求自己需要的模板
uplodeValueId = () => {
if (event && event.target && event.target.value) {
let value = event.target.value;
this.setState(() => ({ value: value }), () => { this.getData() })
}
}
getData = () => {//获取服务器的数据
const { dispatch, value } = this.props;
const valueId = this.state.value
dispatch({
type: 'DataGgEditor/fetch',
payload: !!value ? value : '54791413-1c94-11ea-930a-525400e1d4cc',
callback: (data) => {
console.log(data)
this.clearPrefix(data)
}
});
}
//清除前缀
clearPrefix = (data) => {
data.model.childShapes = data.model.childShapes.map(item => {
if (item.resourceId.substring(0, 7) !== 'zysoft_') {
return item
}
item.resourceId = item.resourceId.substring(7)
if (item.outgoing.length > 0) {
item.outgoing.map(goItem => {
goItem.resourceId = goItem.resourceId.substring(7)
return goItem
})
}
if (item?.target) {
item.target.resourceId = item?.target?.resourceId ? item?.target?.resourceId.substring(7) : ''
}
return item
})
this.deformation(data)
}
deformation = (data) => {//把服务器的数据转换为能展示的数据
// console.log(data)
const arr = {
nodes: [],
edges: []
}
data.model.childShapes.map(item => {
if (item.stencil.id == "StartNoneEvent") {
const obj = {
type: 'node',
size: '20*20',
shape: 'StartNoneEvent',
// color: '#FA8C16',
label: item?.properties?.name ? item.properties.name : '',
x: item.bounds.upperLeft.x,
y: item.bounds.upperLeft.y,
id: item.resourceId,
}
// console.log(obj)
arr.nodes.push(obj)
} else if (item.stencil.id == "UserTask") {
let obj = ''
if (!!this.props.taskKeys && this.props.taskKeys.length > 0) {//判断是否有流程标记
this.props.taskKeys.map(taskItem => {
if (taskItem.substring(7) == item.resourceId) {
obj = {
type: 'node',
size: '60*48',
shape: 'UserTask',
// color: "#ffeae6",
tag: true,
label: item.properties.name,
x: item.bounds.upperLeft.x,
y: item.bounds.upperLeft.y,
id: item.resourceId,
}
} else {
obj = {
type: 'node',
size: '60*48',
shape: 'UserTask',
tag: false,
// color: "#ffeae6",
label: item.properties.name,
x: item.bounds.upperLeft.x,
y: item.bounds.upperLeft.y,
id: item.resourceId,
}
}
})
} else {
obj = {
type: 'node',
size: '60*48',
shape: 'UserTask',
// color: "#ffeae6",
label: item.properties.name,
x: item.bounds.upperLeft.x,
y: item.bounds.upperLeft.y,
id: item.resourceId,
}
}
// console.log(obj)
arr.nodes.push(obj)
} else if (item.stencil.id == "SequenceFlow") {
data.model.childShapes.map(edge => {
edge.outgoing.map(dome => {
if (dome.resourceId == item.resourceId) {
// console.log(item.target.resourceId)
let staticValue = item?.properties?.conditionsequenceflow?.expression?.staticValue
const obj = {
source: edge.resourceId,
target: item.target.resourceId,
label: item.properties.name,
index: 1,
id: item.resourceId,
shape: "flow-polyline",
overrideid: item.properties.overrideid,
conditions: staticValue ? staticValue : '',
style: {
lineWidth: 4,//连线的宽度
// stroke: '#DDDDDD'//定义边的颜色
},
static: undefined,
controlPoints: [],
targetAnchor: item.properties.targetAnchor !== undefined ? item.properties.targetAnchor : '',
sourceAnchor: item.properties.sourceAnchor !== undefined ? item.properties.sourceAnchor : ''
}
arr.edges.push(obj)
}
})
})
} else if (item.stencil.id == "EndNoneEvent") {
const obj = {
type: 'node',
size: '20*20',
shape: 'EndNoneEvent',
// color: '#FA8C16',
label: item.properties.name,
x: item.bounds.upperLeft.x,
y: item.bounds.upperLeft.y,
id: item.resourceId,
}
// console.log(obj)
arr.nodes.push(obj)
} else if (item.stencil.id == "ExclusiveGateway") {
const obj = {
type: 'node',
size: '20*20',
shape: 'ExclusiveGateway',
// color: 'blue',
label: item.properties.name,
x: item.bounds.upperLeft.x,
y: item.bounds.upperLeft.y,
id: item.resourceId,
}
// console.log(obj)
arr.nodes.push(obj)
} else if (item.stencil.id == "BoundaryTimerEvent") {
const obj = {
type: 'node',
size: '20*20',
shape: 'BoundaryTimerEvent',
// color: '#FA8C16',
label: item.properties.name,
x: item.bounds.upperLeft.x,
y: item.bounds.upperLeft.y,
id: item.resourceId,
}
// console.log(obj)
arr.nodes.push(obj)
}
})
this.setState({
data: arr,
}, () => {
// console.log(this.state.data, data)
// console.log(this.props)
// const obj = {
// source: "startEvent1",
// target: "sid-6EE74761-4EAD-43E9-84CC-4CD5478A47F1",
// label: "第二步",
// index: 1,
// id: "fdgdsgdg",
// shape: "MyEdge",
// overrideid: "",
// conditions: "",
// style: { lineWidth: 4 },
// static: undefined,
// controlPoints: [{ x: 200, y: 600 }],
// targetAnchor: 1,
// sourceAnchor: 1,
// }
// arr.edges.push(obj)
// console.log(arr)
this.props.getServerData(this.state.data, data)
})
}
componentDidMount() {
this.getData()
}
render() {
return <></>
}
}
import React, { Component } from 'react'
import { RegisterNode, RegisterEdge } from 'gg-editor';
class NewItem extends React.Component {
render() {
const config = {
draw(item) {
const group = item.getGraphicGroup();
const model = item.getModel();
const width = 100;//展示宽度
const height = 80;//展示高度
// console.log(65856852)
const x = -width / 2;
const y = -height / 2;
const borderRadius = 10;//圆角
const keyShape = group.addShape('rect', {
attrs: {
x,
y,
width,
height,
radius: borderRadius,
fill: 'white',//默认填充色
stroke: model?.tag ? 'red' : '#CED4D9',//默认边框颜色
lineWidth: 2,
}
});
// // 左侧色条
// group.addShape('path', {
// attrs: {
// path: [//绘制图形
// ['M', x, y + borderRadius],
// ['L', x, y + height - borderRadius],
// ['A', borderRadius, borderRadius, 0, 0, 0, x + borderRadius, y + height],
// ['L', x + borderRadius, y],
// ['A', borderRadius, borderRadius, 0, 0, 0, x, y + borderRadius],
// ],
// fill: 'black',
// },
// });
// 类型 logo
// group.addShape('image', {
// attrs: {
// img: textImg,//放入到框架的图片
// x: x + 16,
// y: y + 12,
// width: 20,
// height: 16,
// },
// });
// 名称文本
let label = model.label ? model.label : this.label;
if (label?.length > 5 && label?.length <= 10) {
label = label.slice(0, 5) + '\n' + label.slice(5)
console.log(label)
} else if (label?.length > 10) {
label = label.slice(0, 5) + '\n' + label.slice(5, 10) + '\n' + label.slice(10)
console.log(label)
}
group.addShape('text', {
attrs: {
text: label,
x: x - x / 2,
y: y - y / 2,
textAlign: 'start',//文本对齐方式
textBaseline: 'top',//文本的基线对齐
fill: 'rgba(0,0,0,0.65)',
},
});
return keyShape;//draw方法返回的图形
},
// 设置锚点
anchor: [
[0.5, 0], // 上面边的中点
[0.5, 1], // 下边边的中点
[0, 0.5],
[1, 0.5]
],
}
return (
<RegisterNode name="UserTask" config={config} />
);
}
}
class BPMN extends React.Component {
render() {
const config = {
draw(item) {
const group = item.getGraphicGroup();
const model = item.getModel();
const width = 500;//展示宽度
const height = 500;//展示高度
const x = -width / 2;
const y = -height / 2;
const borderRadius = 10;//圆角
const keyShape = group.addShape('rect', {
attrs: {
x,
y,
width,
height,
radius: borderRadius,
fill: 'white',
stroke: '#CED4D9',
},
});
// 左侧色条
group.addShape('path', {
attrs: {
path: [//绘制图形
['M', x, y + borderRadius],
['L', x, y + height - borderRadius],
['A', borderRadius, borderRadius, 0, 0, 0, x + borderRadius, y + height],
['L', x + borderRadius, y],
['A', borderRadius, borderRadius, 0, 0, 0, x, y + borderRadius],
],
fill: 'black',
},
});
return keyShape;//draw方法返回的图形
},
}
return (
<RegisterNode name="BPMN" config={config} />
);
}
}
class StartNoneEvent extends React.Component {
render() {
const config = {
draw(item) {
console.log(7523)
const group = item.getGraphicGroup();
const model = item.getModel();
// console.log(65856852)
const x = 5;
const y = 5;
const r = 20;//圆角
const keyShape = group.addShape('circle', {
attrs: {
x,
y,
r,
fill: 'white',
stroke: '#CED4D9',
lineWidth: 2
},
});
const label = model.label ? model.label : this.label;
//文字
group.addShape('text', {
attrs: {
text: label,
x: -10,
y: -5,
textAlign: 'start',//文本对齐方式
textBaseline: 'top',//文本的基线对齐
fill: 'rgba(0,0,0,0.65)',
},
});
return keyShape;//draw方法返回的图形
},
anchor: [
[0.5, 0], // 上面边的中点
[0.5, 1], // 下边边的中点
[0, 0.5],
[1, 0.5]
],
}
return (
<RegisterNode name="StartNoneEvent" config={config} />
);
}
}
class EndNoneEvent extends React.Component {
render() {
const config = {
draw(item) {
const group = item.getGraphicGroup();
const model = item.getModel();
// console.log(4578574)
const x = 0;
const y = 0;
const r = 20;//圆角
const keyShape = group.addShape('circle', {
attrs: {
x,
y,
r,
fill: 'white',
stroke: '#CED4D9',
lineWidth: 3
},
});
const label = model.label ? model.label : this.label;
//文字
group.addShape('text', {
attrs: {
text: label,
x: -10,
y: -5,
textAlign: 'start',//文本对齐方式
textBaseline: 'top',//文本的基线对齐
fill: 'rgba(0,0,0,0.65)',
},
});
return keyShape;//draw方法返回的图形
},
anchor: [
[0.5, 0], // 上面边的中点
[0.5, 1], // 下边边的中点
[0, 0.5],
[1, 0.5]
],
}
return (
<RegisterNode name="EndNoneEvent" config={config} />
);
}
}
class BoundaryTimerEvent extends React.Component {
render() {
const config = {
draw(item) {
const group = item.getGraphicGroup();
const model = item.getModel();
// model.x = model.x - 42
// model.y = model.y - 42
// console.log(15465)
const x = 0;
const y = 0;
const r = 20;//圆角
const keyShape = group.addShape('circle', {
attrs: {
x,
y,
r,
fill: 'white',
stroke: '#CED4D9',
lineWidth: 2
},
});
const label = model.label ? model.label : this.label;
//文字
group.addShape('text', {
attrs: {
text: label,
x: -10,
y: -5,
textAlign: 'start',//文本对齐方式
textBaseline: 'top',//文本的基线对齐
fill: 'rgba(0,0,0,0.65)',
},
});
return keyShape;//draw方法返回的图形
},
anchor: [
[0.5, 0], // 上面边的中点
[0.5, 1], // 下边边的中点
[0, 0.5],
[1, 0.5]
],
}
return (
<RegisterNode name="BoundaryTimerEvent" config={config} />
);
}
}
class Erroy extends React.Component {
render() {
const config = {
draw(item) {
const group = item.getGraphicGroup();
const model = item.getModel();
const x = 40;
const y = 40;
const r = 20;//圆角
const keyShape = group.addShape('circle', {
attrs: {
x,
y,
r,
fill: 'blue',
},
});
return keyShape;//draw方法返回的图形
},
anchor: [
[0.5, 0], // 上面边的中点
[0.5, 1], // 下边边的中点
[0, 0.5],
[1, 0.5]
],
}
return (
<RegisterNode name="erroy" config={config} />
);
}
}
//网关
class ExclusiveGateway extends React.Component {
render() {
const config = {
draw(item) {
const group = item.getGraphicGroup()
const model = item.getModel();
// model.x = model.x - 30
// model.y = model.y - 30
const keyShape = group.addShape('polygon', {
attrs: {
points: [
[30, 0],
[60, 30],
[30, 60],
[0, 30]
],
symbol: 'diamond',
fill: '#cccccc'
},
});
const label = model.label ? model.label : this.label;
//文字
group.addShape('text', {
attrs: {
text: label,
x: 15,
y: 22,
textAlign: 'start',//文本对齐方式
textBaseline: 'top',//文本的基线对齐
fill: 'rgba(0,0,0,0.65)',
},
});
return keyShape;
},
anchor: [
[0.5, 0], // 上面边的中点
[0.5, 1], // 下边边的中点
[0, 0.5],
[1, 0.5]
],
}
return <RegisterNode name="ExclusiveGateway" config={config} />
}
}
//自定义线
class MyEdge extends React.Component {
render() {
const config = {
draw(item) {
const group = item.getGraphicGroup()
const model = item.getModel();
// console.log('我的边', item)
const label = model.label ? model.label : this.label;
let startX = ''
let startY = ''
let endX = ''
let endY = ''
let sourceAnchor = model.sourceAnchor
let targetAnchor = model.targetAnchor
if (model?.source?.x && model?.target?.x) {
console.log(1)
startX = model.source.x
startY = model.source.y
endX = model.target.x
endY = model.target.y
} else if (!model?.source?.x && !model?.target?.x) {
console.log(2)
item.itemMap._nodes.map(item => {
if (item.id == model.source) {
startX = item._anchorPoints[sourceAnchor].x
startY = item._anchorPoints[sourceAnchor].y
}
if (item.id == model.target) {
endX = item._anchorPoints[targetAnchor].x
endY = item._anchorPoints[targetAnchor].y
}
})
} else if (!model?.source?.x && model?.target?.x) {
endX = model.target.x
endY = model.target.y
item.itemMap._nodes.map(item => {
if (item.id == model.source) {
startX = item._anchorPoints[sourceAnchor].x
startY = item._anchorPoints[sourceAnchor].y
}
})
} else if (model?.source?.x && !model?.target?.x) {
startX = model.source.x
startY = model.source.y
item.itemMap._nodes.map(item => {
if (item.id == model.target) {
endX = item._anchorPoints[targetAnchor].x
endY = item._anchorPoints[targetAnchor].y
}
})
}
// console.log(startX)
const keyShape = group.addShape('path', {
attrs: {
lineWidth: 4,
startArrow: false,
endArrow: {
path: 'M 0,0 L 12,6 L 9,0 L 12,-6 Z',
fill: '#F6BD16',
},
stroke: "#A3B1BF",
strokeStyle: "#A3B1BF",
path: [
["M", startX, startY],
["L", model.controlPoints[0].x, model.controlPoints[0].y],
["L", endX, endY],
],
},
});
//文字
group.addShape('text', {
attrs: {
text: label,
x: model.controlPoints[0].x,
y: model.controlPoints[0].y,
textAlign: 'start',//文本对齐方式
textBaseline: 'top',//文本的基线对齐
fill: 'black',
},
});
return keyShape;
}
}
return <RegisterEdge name="MyEdge" config={config} />
}
}
export {
NewItem,
BPMN,
StartNoneEvent,
EndNoneEvent,
BoundaryTimerEvent,
ExclusiveGateway,
Erroy,
MyEdge
};
import React, { PureComponent } from 'react'
import { Row, Col, Button,} from 'antd';
import { openToast } from '../Notification'
import GGEditor, { Flow } from 'gg-editor';
import EditorMinimap from './components/EditorMinimap';
import { FlowContextMenu } from './components/EditorContextMenu';
import { FlowToolbar } from './components/EditorToolbar';
import { FlowItemPanel } from './components/EditorItemPanel';
import { FlowDetailPanel } from './components/EditorDetailPanel';
import styles from './Flow/index.less';
import { NewItem, BPMN, StartNoneEvent, EndNoneEvent, BoundaryTimerEvent, ExclusiveGateway, MyEdge } from './components/NewItem'
import { connect } from 'dva';
import GetServerData from './components/GetServerData'
var updata = {}
@connect()
class FlowPage extends PureComponent {
constructor(props) {
super(props)
this.state = {
serverData: {},
perfectData: {},
lowerRightX: 0,
lowerRightY: 0,
upload: {},
maxX: 0,
minY: 0,
getEvent: '',
getDrag: '',
getDragEnd: '',
getMouseUp: '',
isDelete: false,//是否点击了删除按钮
nodeId: '',//点击的节点id
isNode: '',//判断删除的是否为节点
canvasImg: '',//canvas转换的图片
isShow: true,//是否展示
}
}
//把canvas转化为图片
convertCanvasToImage(canvas) {
// console.log(canvas)
var image = new Image();
image.src = canvas.toDataURL("image/png");
// console.log(image)
this.setState({
canvasImg: canvas.toDataURL("image/png")
}, () => {
if (this?.props?.getCanvasImg) {
this.props.getCanvasImg(this.state.canvasImg)
this.setState({
isShow: this.props.isShow
})
}
})
return image;
}
//获取服务器的数据
getServerData = (serverData, perfectData) => {
this.setState({
serverData: serverData,
perfectData: perfectData
}, () => {
let myCavas = document.querySelector('.graph-container canvas')//获取canvas的外层
// console.log(myCavas)
setTimeout(() => {
this.convertCanvasToImage(myCavas)
}, 100);
})
}
//子传父的方法data数据
getprocess = (data, newData, type) => {//获取上传json
updata = data
//修改perfectData会报错
let myCavas = document.querySelector('.graph-container canvas')//获取canvas的外层
// console.log(myCavas)
setTimeout(() => {
this.convertCanvasToImage(myCavas)
}, 100);
this.type = type
if (type == 'masg') {//修改属性
this.setState({
perfectData: data
})
} else if (type == 'node') {//修改节点
this.setState({
perfectData: data
})
} else if (type == 'stencilNode') {//修改带有定时器的节点
this.setState({
perfectData: data,
serverData: newData
})
} else if (type == 'newEdge') {//新增线条
this.setState({
perfectData: data,
serverData: newData
})
}
}
//子传父的方法是否删除
isDelete = (isDelete) => {
this.setState({
isDelete: isDelete
}, () => {
this.deleteNode()
})
}
//删除节点和线
deleteNode = () => {
// console.log(this.state.nodeId)
const { nodeId, isNode } = this.state
let data = this.state.perfectData
if (isNode == 'node') {
data.model.childShapes = data.model.childShapes.filter(item => {
if ((item.resourceId !== nodeId && !item?.target?.resourceId)
|| (item.stencil.id == 'SequenceFlow' && item?.target?.resourceId !== nodeId)
) {
return item
}
})
} else if (isNode == 'edge') {
data.model.childShapes = data.model.childShapes.filter(item => {
if (item.resourceId !== nodeId) {
return item
}
})
}
}
//上传方法
upData = (updata) => {
const { dispatch } = this.props;
let timestamp = new Date().getTime();
const user = JSON.parse(localStorage.getItem('user'))
updata.lastUpdated = timestamp//修改上传时间
updata.lastUpdatedBy = !!user.currentAuthority ? user.currentAuthority : 'admin'//确定上传者
console.log(updata)
if (updata.model === undefined) {
console.log('没有修改')
openToast('info', '保存流程图', '没有修改,不用上传', 'topRight')
} else {
this.addPrefix(updata)
dispatch({
type: 'DataGgEditor/upData',
payload: updata,
callback: (data) => {
openToast('success', '保存流程图', '上传成功', 'topRight')
dispatch({
type: 'DataGgEditor/fetch',
payload: this.props.flowModelId,
callback: (data) => {
console.log(data)
this.clearPrefix(data)
}
});
}
});
}
}
//清除前缀
clearPrefix = (data) => {
data.model.childShapes = data.model.childShapes.map(item => {
if (item.resourceId.substring(0, 7) !== 'zysoft_') {
return item
}
item.resourceId = item.resourceId.substring(7)
if (item.outgoing.length > 0) {
item.outgoing.map(goItem => {
goItem.resourceId = goItem.resourceId.substring(7)
return goItem
})
}
if (item?.target) {
item.target.resourceId = item?.target?.resourceId ? item?.target?.resourceId.substring(7) : ''
}
return item
})
this.deformation(data)
}
deformation = (data) => {//把服务器的数据转换为能展示的数据
// console.log(data)
const arr = {
nodes: [],
edges: []
}
data.model.childShapes.map(item => {
if (item.stencil.id == "StartNoneEvent") {
const obj = {
type: 'node',
size: '55*55',
shape: 'StartNoneEvent',
// color: '#FA8C16',
label: item?.properties?.name ? item.properties.name : '',
x: item.bounds.upperLeft.x,
y: item.bounds.upperLeft.y,
id: item.resourceId,
}
// console.log(obj)
arr.nodes.push(obj)
} else if (item.stencil.id == "UserTask") {
const obj = {
type: 'node',
size: '60*48',
shape: 'UserTask',
// color: "#ffeae6",
label: item.properties.name,
x: item.bounds.upperLeft.x,
y: item.bounds.upperLeft.y,
id: item.resourceId,
}
// console.log(obj)
arr.nodes.push(obj)
} else if (item.stencil.id == "SequenceFlow") {
data.model.childShapes.map(edge => {
edge.outgoing.map(dome => {
if (dome.resourceId == item.resourceId) {
// console.log(item.target.resourceId)
let staticValue = item?.properties?.conditionsequenceflow?.expression?.staticValue
const obj = {
source: edge.resourceId,
target: item.target.resourceId,
label: item.properties.name,
index: 1,
id: item.resourceId,
shape: "flow-polyline",
overrideid: item.properties.overrideid,
conditions: staticValue ? staticValue : '',
style: {
lineWidth: 4,//连线的宽度
},
static: undefined,
controlPoints: [],
targetAnchor: item.properties.targetAnchor !== undefined ? item.properties.targetAnchor : '',
sourceAnchor: item.properties.sourceAnchor !== undefined ? item.properties.sourceAnchor : ''
}
arr.edges.push(obj)
}
})
})
} else if (item.stencil.id == "EndNoneEvent") {
const obj = {
type: 'node',
size: '55*55',
shape: 'EndNoneEvent',
// color: '#FA8C16',
label: item.properties.name,
x: item.bounds.upperLeft.x,
y: item.bounds.upperLeft.y,
id: item.resourceId,
}
// console.log(obj)
arr.nodes.push(obj)
} else if (item.stencil.id == "ExclusiveGateway") {
const obj = {
type: 'node',
size: '55*55',
shape: 'ExclusiveGateway',
// color: 'blue',
label: item.properties.name,
x: item.bounds.upperLeft.x,
y: item.bounds.upperLeft.y,
id: item.resourceId,
}
// console.log(obj)
arr.nodes.push(obj)
} else if (item.stencil.id == "BoundaryTimerEvent") {
const obj = {
type: 'node',
size: '55*55',
shape: 'BoundaryTimerEvent',
// color: '#FA8C16',
label: item.properties.name,
x: item.bounds.upperLeft.x,
y: item.bounds.upperLeft.y,
id: item.resourceId,
}
// console.log(obj)
arr.nodes.push(obj)
}
})
this.setState({
serverData: arr,
perfectData: data
})
}
//上传添加前缀
addPrefix = (data) => {
data.model.childShapes = data.model.childShapes.map(item => {
if (item.resourceId.substring(0, 7) === 'zysoft_') {
return item
}
item.resourceId = 'zysoft_' + item.resourceId
if (item.outgoing.length > 0) {
item.outgoing.map(goItem => {
goItem.resourceId = 'zysoft_' + goItem.resourceId
return goItem
})
}
if (item?.target) {
item.target.resourceId = item?.target?.resourceId ? 'zysoft_' + item?.target?.resourceId : ''
}
return item
})
}
getlowerRight = (e) => {//获取canvas的大小
// console.log(e, '点击')
this.setState({
getEvent: e,
getDrag: '',
isDelete: false
})
this.selectedId = ''
if (e.item == null) {
this.setState({
lowerRightX: e?.domEvent?.toElement?.width,
lowerRightY: e?.domEvent?.toElement?.height,
maxX: 0,
minY: 0
}, () => {
if (Object.keys(updata).length > 0 && updata.model?.bounds) {
updata.model.bounds.lowerRight.x = this.state.lowerRightX
updata.model.bounds.lowerRight.y = this.state.lowerRightY
}
})
} else if (e.item.bbox !== undefined) {
//获取点击的位子在节点的中的坐标
const width = e.item.bbox.maxX - e.x
const height = e.item.bbox.minY - e.y
if (e.item.model.shape == 'EndNoneEvent') {
this.setState({
maxX: 0,
minY: 0
})
return
}
this.setState({
maxX: e.domX + width,
minY: e.domY + height
})
} else if (e.item.type == 'edge') {
this.setState({
maxX: 0,
minY: 0
})
}
}
//更新跟过选择框
more = (e) => {
// console.log('拖动结束', e)
this.setState({
maxX: 0,
minY: 0,
getDragEnd: e
})
}
//清除点击事件,拖动事件
clearClick = (e) => {
// console.log('拖动', e)
this.setState({
getEvent: '',
getDrag: e,
getDragEnd: '',
maxX: 0,
minY: 0,
isDelete: false,
})
}
//鼠标抬起事件函数
mouseUp = (e) => {
// console.log('抬起', e)
this.setState({
getMouseUp: e
})
}
//鼠标移入事件
mouseEnter = (e) => {
// console.log(e, '移入')
if (e.item && e.item.type == 'node') {
// console.log(12121455)
e.item.keyShape._cfg.attrs.lineWidth = 5
}
}
//鼠标移出事件
mouseLeave = (e) => {
// console.log(e, '移出')
if (e.item && e.item.type == 'node' && this.selectedId !== e.item.id && e.item?.keyShape?._cfg.attrs?.fillStyle) {
// e.item.keyShape._cfg.attrs.fillStyle = '#ffffff'
// e.item.keyShape._cfg.attrs.strokeStyle = '#CED4D9'
e.item.keyShape._cfg.attrs.lineWidth = 2
}
}
//选中节点后
afterItemSelected = (e) => {
// console.log(e, '选中')
if (e.item && e.item.type == 'node') {
this.selectedId = e.item.id
// console.log(32566555)
e.item.keyShape._cfg.attrs.fillStyle = '#cccccc'
e.item.keyShape._cfg.attrs.strokeStyle = '#1890ff'
// e.item.keyShape._cfg.attrs.lineWidth = 5
}
if (e.item && e.item.type == 'edge') {
//线
this.selectedId = e.item.id
e.item.keyShape._cfg.attrs.strokeStyle = '#A3B1BF'
e.item.endArrow._cfg.attrs.fillStyle = '#A3B1BF'
e.item.endArrow._cfg.attrs.fill = '#A3B1BF'
}
}
//取消选中后
afterItemUnselected = (e) => {
if (e.item && e.item.type == 'node') {
this.selectedId = ''
e.item.keyShape._cfg.attrs.fillStyle = '#ffffff'
e.item.keyShape._cfg.attrs.strokeStyle = '#CED4D9'
// e.item.keyShape._cfg.attrs.lineWidth = 2
}
}
//鼠标右键事件
mouseRight = (e) => {
// console.log(e)
this.setState({
maxX: 0,
minY: 0,
nodeId: e?.item?.id,
isNode: e?.item?.type
})
}
//激活节点
AfterItemInactivated = (e) => {
// console.log(e, '激活后')
if (e.item && e.item.type == 'edge' && this.selectedId == e.item.id) {
//线
e.item.keyShape._cfg.attrs.strokeStyle = '#A3B1BF'
e.item.endArrow._cfg.attrs.fillStyle = '#A3B1BF'
e.item.endArrow._cfg.attrs.fill = '#A3B1BF'
e.item.keyShape._attrs.lineWidth = 2
}
}
//数据变化后
AfterChange = (e) => {
console.log(e, '数据变化后')
if (e.item && e.item.type == 'node' && this.selectedId == e.item.id) {
// console.log(32566555)
e.item.keyShape._cfg.attrs.fillStyle = '#cccccc'
e.item.keyShape._cfg.attrs.strokeStyle = '#1890ff'
// e.item.keyShape._cfg.attrs.lineWidth = 5
}
if (e.item && e.item.type == 'edge' && this.selectedId == e.item.id && e.item?.keyShape?._cfg?.attrs?.stroke) {
//线
e.item.keyShape._cfg.attrs.stroke = '#A3B1BF'
e.item.keyShape._cfg.attrs.strokeStyle = '#A3B1BF'
e.item.endArrow._cfg.attrs.fillStyle = '#A3B1BF'
e.item.endArrow._cfg.attrs.fill = '#A3B1BF'
}
}
render() {
let { isDelete, maxX, minY } = this.state
// console.log(this.props.flowModelId)
return (<>
<GGEditor id='editor' className={styles.editor} >
<Row type="flex" className={styles.editorHd}>
<Col span={24}>
<FlowToolbar />
</Col>
</Row>
<Row type="flex" className={styles.editorBd}>
<Col span={4} className={styles.editorSidebar}>
{/* 选择需要的框的类型*/}
<FlowItemPanel minY={minY} maxX={maxX} />
<NewItem></NewItem>
<BPMN></BPMN>
<StartNoneEvent></StartNoneEvent>
<EndNoneEvent></EndNoneEvent>
<BoundaryTimerEvent></BoundaryTimerEvent>
<ExclusiveGateway></ExclusiveGateway>
<MyEdge></MyEdge>
</Col>
<Col span={16} className={styles.editorContent}>
<Flow className={styles.flow}
data={this.state.serverData}//渲染data数据
onDragEnd={(e) => { this.more(e) }}//拖动结束事件
onClick={(e) => { this.getlowerRight(e) }}//点击事件
onDrag={(e) => { this.clearClick(e) }}//拖动事件
onMouseUp={(e) => { this.mouseUp(e) }}//鼠标抬起事件
// onMouseEnter={(e) => { this.mouseEnter(e) }}//鼠标移入事件
// onMouseLeave={(e) => { this.mouseLeave(e) }}//鼠标移出事件
onAfterItemSelected={(e) => { this.afterItemSelected(e) }}//选中节点事件
// onAfterItemUnselected={(e) => { this.afterItemUnselected(e) }}//取消选中后
onContextMenu={(e) => { this.mouseRight(e) }}//鼠标右键事件
// onAfterItemInactivated={(e) => { this.AfterItemInactivated(e) }}//激活节点和线
// onAfterChange={(e) => { this.AfterChange(e) }}//数据变化后
/>
</Col>
<Col span={4} className={styles.editorSidebar} >
<FlowDetailPanel
getEvent={this.state.getEvent}//传送e事件
data={this.state.perfectData}//数据
getprocess={this.getprocess}//字串传父的函数
getDrag={this.state.getDrag}//拖动事件数据
getDragEnd={this.state.getDragEnd}//拖动结束事件
isDelete={isDelete}//是否删除
/>
<EditorMinimap />
</Col>
</Row>
<FlowContextMenu
isDelete={this.isDelete}
/>
<Button
className={styles.saveDate}
onClick={() => { this.upData(updata) }}>保存
</Button>
<GetServerData
value={this.props.flowModelId}
getServerData={this.getServerData}
taskKeys={this.props?.taskKeys ? this.props?.taskKeys : ''}
></GetServerData>
</GGEditor>
{/* <img src={this.state.canvasImg}></img> */}
</>
)
}
}
export default FlowPage;
/**
* 预加载动画
* 小球跳动加载(页面级)
* 徐立
* 2020.2.18
*/
import React from 'react'
import styles from './style.less';
export default function LoadThree() {
return (
<div className={styles.ani6}>
<div className={[`${styles.wrap_preload}`,`${styles.circle_ball}`].join(' ')}>
<div className={styles.overlay}></div>
<div className={styles.wrap_content}>
<div className={styles.wrap_circle_ball}>
<div className={styles.wrap_ball}>
<div className={[`${styles.ball}`,`${styles.ball_top}`].join(' ')}></div>
<div className={[`${styles.ball}`,`${styles.ball_top}`].join(' ')}></div>
</div>
<div className={styles.wrap_ball}>
<div className={[`${styles.ball}`,`${styles.ball_bot}`].join(' ')}></div>
<div className={[`${styles.ball}`,`${styles.ball_bot}`].join(' ')}></div>
</div>
<div className={styles.wrap_effect}>
<div className={styles.wrap_circle}>
<div className={[`${styles.circle_effect}`,`${styles.left}`].join(' ')}></div>
<div className={[`${styles.circle_effect}`,`${styles.left}`].join(' ')}></div>
</div>
<div className={styles.wrap_circle}>
<div className={[`${styles.circle_effect}`,`${styles.right}`].join(' ')}></div>
<div className={[`${styles.circle_effect}`,`${styles.right}`].join(' ')}></div>
</div>
</div>
</div>
</div>
</div>
</div>
)
}
/**
* 转办+回收弹框
* 徐立
* 2020.4.8
* @param { boolean } visible model层显示控制变量
* @param { Function } handleCancel model层关闭控制函数
* @param { string } status 状态栏 存在以下状态 撤回 转办 回退
* @param { any } value 当前表单数据
* @param { Function } init 重置提交后数据源
*/
import React, { Component } from 'react';
import { Modal } from 'antd';
import TrunTo from './trunTo';
import Recycle from './recycle';
import styles from './style.less';
import { confirm,openToast } from '../Notification';
import { connect } from 'dva';
@connect()
export default class TurnToModel extends Component {
constructor(props){
super(props)
this.state = {
reason : '', // 用户相关原因同步,
user: '', // 用户选择移交人数据
loading: false, // 提交状态
}
}
/**
* 同步用户选择移交用户数据
* @param { any } user 选中用户
*/
asyncUser = (user) => {
this.setState({
user
})
}
/**
* 同步用户移交理由
* @param { string } value 输入值
*/
asyncReasion = (value) => {
this.setState({
reason: value
})
}
/**
* 用于不同状态提交
*/
handleOk = async () => {
const { status,dispatch,value } = this.props
const { reason } = this.state
await this.setState({
loading: true
})
if(status === '转办'){ // 发起转办提交处理
const { user } = this.state
if(user){
dispatch({
type:'trunTo/turnsProcess',
payload: {
taskIds:[value.taskId],
reason,
turnsUserCode: user.stuNo
},
callback: (val) => {
openToast('success', '成功','当前流程已成功移交')
this.props.init()
this.setState({
loading: false
})
}
})
} else {
openToast('info','错误','请选择移交人员')
}
} else if(status === '回退') { // 发起回退提交处理
dispatch({
type: 'trunTo/refuseProcess',
payload: {
taskIds:[value.taskId],
reason
},
callback: (val) => {
openToast('success', '回退','当前流程已成功回退')
this.props.init()
this.setState({
loading: false
})
}
})
} else {
console.log('缺乏匹配字段提交方法')
}
this.props.handleCancel()
}
recallConfim = () => {
const { status,dispatch,value } = this.props
confirm('撤回','是否撤回当前转办流程',()=>{
dispatch({
type:'trunTo/resetProcess',
payload:{
taskIds:[value.taskId],
},
callback:(val) => {
openToast('success','成功','该转办流程已成功撤回')
this.props.init()
}
})
this.props.handleCancel()
},()=>{
this.props.handleCancel()
})
}
render() {
const {
visible,
handleCancel,
status,
value,
} = this.props
const {
loading
} = this.state
if(visible){
switch (status) {
case '撤回':
this.recallConfim()
return <></>
case '转办':
return <Modal
title={status}
visible={visible}
onOk={this.handleOk}
onCancel={handleCancel}
width={800}
loading={loading}
>
<div
className={styles.model_div}
>
<TrunTo
asyncReasion={this.asyncReasion}
asyncUser={this.asyncUser}
value={value}
/>
</div>
</Modal>
case '回退':
return <Modal
title={status}
visible={visible}
onOk={this.handleOk}
onCancel={handleCancel}
width={800}
loading={loading}
>
<div
className={styles.model_div}
>
<Recycle
asyncReasion={this.asyncReasion}
value={value}
/>
</div>
</Modal>
default:
console.log('缺乏匹配项')
return <></>
}
} else {
return <></>
}
}
}
/**
* 回收组件
* 徐立
* 2020.4.8
* @param { Function } asyncReasion 转交理由同步参数
*/
import React, { Component } from 'react'
import styles from '../style.less';
import { Row, Col,Input,Spin } from 'antd';
import { connect } from 'dva';
const { TextArea } = Input;
@connect()
export default class index extends Component {
constructor(props){
super(props)
this.state = {
textAreaValue: '',
data:'',
isLoading: false,
}
}
async componentDidMount(){ // 请求当前
const { value, dispatch } = this.props
this.setState({
isLoading: true
})
await dispatch({
type: 'trunTo/detailProcess',
payload: {
taskId:value.taskId,
},
callback: (val) => {
this.setState({
data:Array.isArray(val)&&val?.length>0?val[val.length-1]:'',
isLoading: false,
})
}
})
}
/**
* 多行文本输入
*/
textAreaChange = (e) => {
this.setState({
textAreaValue: e.target.value
})
this.props.asyncReasion(e.target.value)
}
render() {
const { data,isLoading } = this.state
return (
<div
className={styles.show_recall_user_div}
>
{
!isLoading?
<>
<Row
gutter={16}
>
<Col
span={4}
style={{
textAlign:'right'
}}
>
转发人:
</Col>
<Col
span={20}
>
{data?.sendUserName}
</Col>
</Row>
<Row
gutter={16}
>
<Col
span={4}
style={{
textAlign:'right'
}}
>
转发理由:
</Col>
<Col
span={20}
>
{data?.massage??'暂无'}
</Col>
</Row>
<Row
gutter={16}
style={{
marginTop:12
}}
>
<Col
span={4}
style={{
textAlign:'right'
}}
>
回退原因:
</Col>
<Col
span={20}
>
<TextArea
rows={4}
style={{
resize:'none'
}}
onChange={
this.textAreaChange
}
/>
</Col>
</Row>
</>
:<div
className={styles.spin_div}
>
<Spin />
</div>
}
</div>
)
}
}
.trun_to_table_div{
margin-top: 12px;
}
.show_checked_user_div{
border: 1px solid #e8e8e8;
animation: ani .5s;
padding: 12px 12px;
width: 752px;
}
.show_recall_user_div{
animation: ani .5s;
padding: 12px 12px;
width: 752px;
}
.table_post_name{
cursor: initial;
width: 200px;
overflow: hidden;
text-overflow:ellipsis;
white-space: nowrap;
}
@keyframes ani {
0%{
opacity: 0;
}
100%{
opacity: 1;
}
}
:global{
#trun_to_table .ant-table-thead tr th{
background-color: #fff;
}
}
.spin_div{
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
\ No newline at end of file
/**
* 转办组件
* 徐立
* 2020.4.8
* @param { Function } asyncUser 选择用户同步函数
* @param { Function } asyncReasion 转交理由同步参数
*/
import React, { Component } from 'react';
import { Input, Table, Row, Col, Tooltip, Spin } from 'antd';
import styles from '../style.less';
import { connect } from 'dva';
const { Search } = Input;
const { TextArea } = Input;
@connect()
export default class index extends Component {
constructor(props) {
super(props);
this.state = {
data: [], // 表格参数
checkedUser: '', // 用户选择参数
textAreaValue: '', // 用户转发理由
current: 1, // 当前页数
pageSize: 10, // 每页条数
total: 0, // 数据总数
realname: '', // 姓名输入框输入值
username: '', // 账号输入框输入值
userData: '', // 回退数据
isLoading: false, // 请求状态
};
this.columns = [
{
title: '工号',
dataIndex: 'stuNo',
width: 170,
},
{
title: '用户名',
dataIndex: 'realname',
width: 170,
},
{
title: '邮箱',
dataIndex: 'email',
width: 200,
render: text => {
return (
<Tooltip title={text}>
<div className={styles.table_post_name}>{text}</div>
</Tooltip>
);
},
},
{
title: '职位',
dataIndex: 'mainPostName',
render: text => {
return (
<Tooltip title={text}>
<div className={styles.table_post_name}>{text}</div>
</Tooltip>
);
},
},
];
}
componentDidMount() {
this.setState(
{
isLoading: true,
},
() => {
this.getInit();
},
);
}
getInit = async () => {
const { dispatch, value } = this.props;
// 用户名列表
await dispatch({
type: 'uaa_User/fetch',
payload: {
pageNo: 1,
pageSize: 5,
},
callback: val => {
this.setState({
data: val.rows,
current: val.pageNo,
total: val.totalPage,
pageSize: val.pageSize,
});
},
});
await dispatch({
type: 'trunTo/detailProcess',
payload: {
taskId: value.taskId,
},
callback: val => {
this.setState({
userData: Array.isArray(val) && val?.length > 0 ? val[val.length - 1] : '',
});
},
});
await this.setState({
isLoading: false,
});
};
userPaginationChange = value => {
const { dispatch } = this.props;
const { realname, username } = this.state;
// 用户名列表
dispatch({
type: 'uaa_User/fetch',
payload: {
pageNo: value,
pageSize: 5,
realname,
username,
},
callback: val => {
this.setState({
data: val.rows,
current: val.pageNo,
total: val.totalPage,
pageSize: val.pageSize,
});
},
});
};
/**
* 根据名字查询
* @param { string } value 用户输入值
*/
searchNameChange = value => {
const { dispatch } = this.props;
dispatch({
type: 'uaa_User/fetch',
payload: {
pageNo: 1,
pageSize: 5,
realname: value,
},
callback: val => {
this.setState({
data: val.rows,
current: val.pageNo,
total: val.totalPage,
pageSize: val.pageSize,
});
},
});
};
/**
* 名字输入事件
* @param { stirng } e 用户输入事件
*/
onNameChange = e => {
this.setState({
realname: e.target.value,
username: '',
});
};
/**
* 根据账号查询
* @param { stirng } value 用户输入值
*/
serachStuNoChange = value => {
const { dispatch } = this.props;
this.setState({
username: value,
});
dispatch({
type: 'uaa_User/fetch',
payload: {
pageNo: 1,
pageSize: 5,
username: value,
},
callback: val => {
this.setState({
data: val.rows,
current: val.pageNo,
total: val.totalPage,
pageSize: val.pageSize,
});
},
});
};
/**
* 账号输入数据
* @param { stirng } e 用户输入事件
*/
onStuNoChange = e => {
this.setState({
username: e.target.value,
realname: '',
});
};
/**
* 表格选择事件
*/
tableChange = (selectedRowKeys, selectedRows) => {
this.setState(
{
checkedUser: selectedRows?.[0] ?? '',
},
() => {
this.props.asyncUser(this.state.checkedUser);
},
);
};
/**
* 表格默认选择配置
*/
getCheckboxProps = record => {
return {
disabled: record.name === 'Disabled User', // Column configuration not to be checked
name: record.name,
};
};
/**
* 多行文本输入
*/
textAreaChange = e => {
this.setState({
textAreaValue: e.target.value,
});
this.props.asyncReasion(e.target.value);
};
render() {
const {
data,
checkedUser,
current,
total,
pageSize,
realname,
username,
userData,
isLoading,
} = this.state;
const rowSelection = {
onChange: this.tableChange,
type: 'radio',
fixed: true,
// getCheckboxProps: this.getCheckboxProps,
};
let allWidth = 0;
// 计算滑动总长度
if (Array.isArray(this.columns)) {
this.columns.map((item, index) => {
if (this.columns.length - 1 === index) {
// 为最后一个元素时跳过
allWidth += 270; // 自适应200宽度
return item;
}
if (item.width) {
// 存在默认宽度
allWidth += item.width;
} else {
// 不存在
allWidth += 170;
}
return item;
});
}
return (
<>
{!isLoading ? (
<>
<Row>
<Col span={12}>
<Row>
<Col
span={4}
style={{
minHeight: 32,
textAlign: 'right',
lineHeight: '32px',
}}
>
姓名 &nbsp;
</Col>
<Col span={20}>
<Search
placeholder="姓名"
value={realname}
onSearch={this.searchNameChange}
onChange={this.onNameChange}
enterButton
/>
</Col>
</Row>
</Col>
<Col span={12}>
<Col
span={4}
style={{
minHeight: 32,
textAlign: 'right',
lineHeight: '32px',
}}
>
账号 &nbsp;
</Col>
<Col span={20}>
<Search
placeholder="账号"
value={username}
onSearch={this.serachStuNoChange}
onChange={this.onStuNoChange}
enterButton
/>
</Col>
</Col>
</Row>
<div id="trun_to_table" className={styles.trun_to_table_div}>
<Table
rowSelection={rowSelection}
columns={this.columns}
dataSource={data}
scroll={{ x: allWidth }}
pagination={{
hideOnSinglePage: true,
pageSize,
total,
current,
onChange: this.userPaginationChange,
}}
/>
</div>
{checkedUser ? (
<div className={styles.show_checked_user_div}>
<Row gutter={16}>
<Col
span={4}
style={{
textAlign: 'right',
}}
>
转发人:
</Col>
<Col span={20}>{checkedUser.realname}</Col>
</Row>
<Row
gutter={16}
style={{
marginTop: 12,
}}
>
<Col
span={4}
style={{
textAlign: 'right',
}}
>
转发原因:
</Col>
<Col span={20}>
<TextArea
rows={4}
style={{
resize: 'none',
}}
onChange={this.textAreaChange}
/>
</Col>
</Row>
</div>
) : null}
{userData && (
<div
className={styles.show_checked_user_div}
style={{
marginTop: 12,
}}
>
<Row gutter={16}>
<Col
span={4}
style={{
textAlign: 'right',
}}
>
回退人:
</Col>
<Col span={20}>
{userData?.receiveUserName ?? '暂无'}
{/* {checkedUser.realname} */}
</Col>
</Row>
<Row
gutter={16}
style={{
marginTop: 12,
}}
>
<Col
span={4}
style={{
textAlign: 'right',
}}
>
回退原因:
</Col>
<Col span={20}>{userData?.massage}</Col>
</Row>
</div>
)}
</>
) : (
<div className={styles.spin_div}>
<Spin />
</div>
)}
</>
);
}
}
import React from 'react';
import { openToast } from './components/Notification';
import { preHandle } from '@/webPublic/one_stop_public/utils/myutils';
import { getToken } from '@/webPublic/one_stop_public/utils/token';
import { callbackSubmitData } from '@/webPublic/one_stop_public/models/callbackExamineProcess';
import { getModal } from '@/webPublic/one_stop_public/utils/utils';
const Modal = getModal();
const must = (
<span
style={{
color: '#FF5350',
marginLeft: 5,
marginRight: 5,
}}
>
*
</span>
);
// 检查是否启用表单校验
const checkNeedFormValidateFieldsAndScroll = ({
btns,
btnValue,
}) => {
let btnInfo = btns.find(g => g.value + '' === btnValue + '');
let checkSumbitInfo = true;
if (btnInfo && btnInfo.isValidateForm === false) {
checkSumbitInfo = false; // 23425 学生事务/学生违纪管理/违纪上报/审核,2013010255 学生处干事选择驳回 这些字段不用填
}
return checkSumbitInfo;
};
const submitValues = ({
values,
isCloseFlowPath,
radiovalue,
isSecond,
taskId,
code,
btnValue,
oldkey,
value,
checked,
setData,
data,
userInfo,
btns,
dispatch,
that,
handleUser,
}) => {
if (isCloseFlowPath) {
} else if (!radiovalue && isSecond) {
openToast('success', '请选择紧急度');
return;
}
that.setState(
{
isSumbitLoading: true,
},
() => {
preHandle(values); // 引入 import {preHandle} from '@/webPublic/one_stop_public/utils/myutils.js'
// console.log(JSON.stringify(values));
// return ;
let payload = {
taskIds: [taskId], // 接口里面的taskId 任务Id
// taskIds: [this.state.taskId], // 接口里面的taskId 任务Id
level: radiovalue && isSecond ? radiovalue : '', // 流程紧急度 可不传
// code: this.state.code, // 接口里面的code 为表单编号
code: code, // 接口里面的code 为表单编号
// 所有审核内容都在这里面
examineMap: JSON.stringify({
// 接口里面的btns数组, key值和value没有值问题后期已修复
// 是否同意 0同意 1拒绝
[oldkey]: btnValue, // 每个配置按钮对应的对象内容 oldkey = 接口中 key btnValue = 接口中 value
reason: value, // 审批理由
// code: this.state.code, // 接口里面的code 为表单编号
code: code, // 接口里面的code 为表单编号
sign: checked ? setData?.userSign : '', // 加签
}),
taskForm: JSON.stringify(values), // 审批表单的参数值
handleUser, // 表单处理人
apiData: data,
taskFormKey: data.taskFormKey,
userNowInfo: userInfo,
buttonInfo: btns && btns.length ? btns.find(x => x.value === btnValue) : {},
token: getToken(),
};
payload = callbackSubmitData(payload);
dispatch({
type: 'affair/getExamineProcess',
payload,
callback: val => {
if (val) {
that.getInit();
that.setState({
isHandle: false,
isSumbitLoading: false,
isSign: checked,
});
Modal.success({
title: '操作成功',
content: (
<div>
<p>操作成功,点击确认刷新页面!</p>
</div>
),
onOk: () => {
that.getInit();
},
okText: '确认',
});
} else {
openToast('error', '失败', '请稍后重试');
}
},
});
},
);
};
export { must, checkNeedFormValidateFieldsAndScroll, submitValues };
/*查看详情样式*/
.detail_div {
padding: 0 24px 20px;
:global(.antd-pro-web-public-one_stop_public-detail-for-audit-components-card-index-card) {
width: 100% !important;
}
.header {
width: 100%;
text-align: center;
font-size: 20px;
font-weight: bold;
color: #333333;
padding: 32px 0 32px 0;
position: relative;
}
.body_hea {
h3 {
font-weight: bold;
color: #333333;
font-size: 16px;
margin-bottom: 28px;
}
.hea_title {
font-size: 14px;
color: #666666;
margin-left: 41px;
}
.hew_content {
color: #333333;
font-size: 14px;
margin-left: 23px;
}
/*事项理由样式*/
.title {
text-align: right;
font-size: 14px;
color: #666666;
}
.body {
padding-left: 24px;
color: #333333;
font-size: 14px;
}
/*附件样式*/
.file {
margin-bottom: 16px;
img {
width: 14px;
height: 16px;
margin-right: 9px;
margin-top: -5px;
}
}
}
/*审批样式*/
.body_content {
h3 {
font-weight: bold;
margin-top: 20px;
color: #333333;
font-size: 16px;
margin-bottom: 28px;
span {
float: right;
font-size: 14px;
color: #0f91ff;
font-weight: normal;
}
}
/* 流程样式 */
.steps_step {
position: relative;
font-size: 14px;
color: #333333;
.steps_title {
font-size: 14px;
color: #333333;
font-weight: bold;
span {
float: right;
font-size: 12px;
color: #cccccc;
}
}
.steps_body {
margin: 10px 0;
}
}
:global {
.ant-timeline-item-last > .ant-timeline-item-content {
position: relative;
}
}
}
}
.row {
margin-bottom: 28px;
}
.steps_span {
margin-left: 12px;
color: #1890ff;
cursor: pointer;
display: flex;
align-items: center;
}
.ani_css {
animation: ani 0.3s;
}
@keyframes ani {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
.history_form_title {
width: 200px;
height: 20px;
font-size: 14px;
font-weight: bold;
color: #000;
}
.history_form_body_div {
width: 200px;
}
// 加签组件样式
.title_div {
width: 100%;
.left_title_span {
margin-right: 20px;
font-weight: bold;
margin-bottom: 12px;
}
}
.ani_div {
margin-left: 12px;
animation: opacity 0.5s;
display: flex;
flex-wrap: wrap;
.card_div {
min-width: 250px;
min-height: 50px;
padding: 5px;
border: 1px solid #e8e8e8;
border-radius: 5px;
margin: 5px;
}
}
@keyframes opacity {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
.buttonList {
margin-top: 24px;
margin-bottom: 24px;
min-height: 50px;
}
/**
* 转办详情卡片
* 徐立
* 2020-4-14
* @param { any } data 当前表单数据
* @param { any } item 当前节点数据
*/
import React, { Component } from 'react';
import styles from './styles.less';
import SVG from './components/SVG';
import { Spin, Timeline,Icon } from 'antd';
import { connect } from 'dva';
import moment from 'moment';
@connect()
export default class trunToDetail extends Component {
constructor(props){
super(props)
this.state = {
trunToData: '',
isUnfold: false,
isLoading: false,
}
}
/**
* 切换状态函数
*/
updateUnfold = () => {
this.setState({
isUnfold:!this.state.isUnfold,
},async () => {
const { isUnfold } = this.state
const { dispatch,item } = this.props
if(isUnfold){ // 判断当前是否为展开状态
await this.setState({
isLoading: true,
})
// 发起请求获取数据
dispatch({
type: 'trunTo/detailProcess',
payload: {
taskId: item.id,
},
callback: (val) => {
this.setState({
isLoading: false,
trunToData: val
})
}
})
} else { // 为关闭状态清空数据
this.setState({
trunToData: ''
})
}
})
}
render() {
const {
trunToData,
isUnfold,
isLoading,
} = this.state
// console.log(import.meta)
return (
<>
<div
className={styles.steps_body}
style={{
display:'flex'
}}
>
转办流程
<span
className={styles.steps_span}
onClick={this.updateUnfold}
>
{
isUnfold?
<>
收起
<SVG
name='packUp'
color='#1890FF'
/>
</>
:<>
展开
<SVG
name='unfold'
color='#1890FF'
/>
</>
}
</span>
</div>
{
isUnfold?
isLoading?
<div
style={{
textAlign:'center'
}}
>
<Spin />
</div>
:<div
className={styles.ani_css}
style={{
marginTop:32
}}
>
<Timeline>
{trunToData !== ''
? trunToData.map((item, index) => {
if (index == trunToData.length - 1) {
return (
<Timeline.Item
color={"#ccc"}
dot={<Icon type={"clock-circle-o"}
style={{ fontSize: '16px' }} />}
className={styles.steps_step}
key={item.id}
>
<p>
转办人:{item?.sendUserName??'暂无'}
</p>
<p className={styles.steps_body}>
转办时间:{item?.createTime?moment(+item.createTime).format('YYYY-MM-DD HH:MM'):'暂无'}
</p>
<p>
接办人:{item?.receiveUserName??'暂无'}
</p>
<p className={styles.steps_body}>
移交理由:{item?.receiveUserName??'暂无'}
</p>
</Timeline.Item>
);
}
return (
<Timeline.Item
color={'green'}
dot={<Icon type="check-circle" theme="twoTone" twoToneColor="#52c41a" />
}
className={styles.steps_step}
key={item.id}
>
<p>
转办人:{item?.sendUserName??'暂无'}
</p>
<p className={styles.steps_body}>
转办时间:{item?.createTime?moment(+item.createTime).format('YYYY-MM-DD HH:MM'):'暂无'}
</p>
<p>
接办人:{item?.receiveUserName??'暂无'}
</p>
<p className={styles.steps_body}>
移交理由:{item?.massage??'暂无'}
</p>
</Timeline.Item>
);
})
: ''}
</Timeline>
</div>
:null
}
</>
)
}
}
export function getUrlInfo(){
let url = window.document.location.href.toString();
let u = url.split("?");
if (typeof(u[1]) == "string") {
u = u[1].split("&");
let get = {};
for (let i in u) {
let j = u[i].split("=");
get[j[0]] = decodeURIComponent(j[1]);
}
return get;
} else {
return {};
}
}
import { uaaRequest } from '../utils/request';
const api = '/UnifiedAppFormApi';
const myCollect = {
namespace: 'countersign', // 加签
state: {
user: {}, // 用户数据
},
effects: {
/**
* 转办流程
* @param { string|Array } taskId 需要转交流程ID
* @param { Array } userIds 加签人id
*/
*countersignHandle({ payload, callback }, { call, put }) {
const response = yield call(uaaRequest, `${api}/addSigns`, {
...payload,
});
if (response == null) {
yield put({ type: 'nom' });
return;
}
if (callback) {
callback(response);
}
},
/**
* 介入(改派流程)
* @param { string } taskId 表Id
* @param { string } userId 用户Id
*/
*involvedHandle({ payload, callback }, { call, put }) {
const response = yield call(uaaRequest, `${api}/reassignmentProcess`, {
...payload,
});
if (response == null) {
yield put({ type: 'nom' });
return;
}
if (callback) {
callback(response);
}
},
},
reducers: {
nom(state) {
return { ...state };
},
},
};
export default myCollect;
import { apiRequest, getRequest } from '../utils/request';
const api = '/DataGgEditorApi'
export default {
namespace: 'DataGgEditor',
state: {
data: {
allmasg: {}
},
},
// 6c64c3f8-1c91-11ea-930a-525400e1d4cc/editor
effects: {
* fetch({ callback, payload }, { call, put }) {//获取数据
const response = yield call(getRequest, `/app/rest/models/${payload}/editor/json`);
if (response == null) {
yield put({ type: 'nom' });
return
}
yield put({
type: 'allmasg',
payload: response,
});
if (callback) callback(response);
},
* getNewProcessImg({ callback, payload }, { call, put }) {//获取数据
const response = yield call(getRequest, `/UnifiedAppFormApi/getNewProcessImg?appId=${payload.appid}&code=${payload.code}`);
if (response == null) {
yield put({ type: 'nom' });
return
}
yield put({
type: 'allmasg',
payload: response,
});
if (callback) callback(response);
},
* getDistriBution({ callback, payload }, { call, put }) {
const response = yield call(getRequest, `/demo/rest/editor-users?filter=${payload}`);
if (response == null) {
yield put({ type: 'nom' });
return
}
yield put({
type: 'allmasg',
payload: response,
});
if (callback) callback(response);
},
*getGroupList({ payload, callback }, { call, put }) {
const response = yield call(getRequest, `/demo/rest/editor-groups?filter=${payload}`)
if (response == null) {
yield put({ type: 'nom' });
return
}
yield put({
type: 'allmasg',
payload: response,
});
if (callback) callback(response);
},
*upData({ payload, callback }, { call, put }) {//上传数据
const newPayload = JSON.parse(JSON.stringify(payload))//数据转换
newPayload.json_xml = JSON.stringify(newPayload.model)//转换model中的数据为字符串
newPayload.newversion = true //是否定义新版本
// console.log(newPayload)
const response = yield call(apiRequest, `/app/rest/models/${payload.modelId}/editor/json`, newPayload);
if (response == null) {
yield put({ type: 'nom' });
return
}
yield put({
type: 'allmasg',
payload: response,
});
if (callback) callback(response);
},
},
reducers: {
allmasg(state, { payload }) {
return {
...state,
data: {
allmasg: payload
}
};
},
nom(state, action) {
return {
...state,
status: 'ok'
};
},
},
};
import { uaaRequest } from '../utils/request';
const api = '/ActCommentApi';
const myCollect = {
namespace: 'trunTo',
state: {
user: {}, // 用户数据
},
effects: {
/**
* 转办流程
* @param { string|Array } taskIds 需要转交流程ID
* @param { string } turnsUserCode 移交人账号
* @param { string } reason 转交理由
*/
* turnsProcess({
payload,
callback,
}, {
call,
put,
}) {
const response = yield call(uaaRequest, `${api}/turnsProcess`, {
...payload,
});
if (response == null) {
yield put({ type: 'nom' });
return;
}
if (callback) {
callback(response);
}
},
/**
* 撤回移交流程
* @param { string|Array } taskIds 需要转交流程ID
*/
* resetProcess({
payload,
callback,
}, {
call,
put,
}) {
const response = yield call(uaaRequest, `${api}/resetProcess`, {
...payload,
});
if (response == null) {
yield put({ type: 'nom' });
return;
}
if (callback) {
callback(response);
}
},
/**
* 回退移交流程
* @param { string|Array } taskIds 需要转交流程ID
* @param { string } reason 转交理由
*/
* refuseProcess({
payload,
callback,
}, {
call,
put,
}) {
const response = yield call(uaaRequest, `${api}/refuseProcess`, {
...payload,
});
if (response == null) {
yield put({ type: 'nom' });
return;
}
if (callback) {
callback(response);
}
},
/**
* 查询单个转交流程数据
* @param { string|Array } taskId 需要转交流程ID
*/
* detailProcess({
payload,
callback,
}, {
call,
put,
}) {
const response = yield call(uaaRequest, `${api}/getList`, {
...payload,
});
if (response == null) {
yield put({ type: 'nom' });
return;
}
if (callback) {
callback(response);
}
},
},
reducers: {
nom(state) {
return { ...state };
},
},
};
export default myCollect;
/**
* 徐立
* 2019年11月8日
* 绑定邮箱手机相关请求
*/
import { uaaRequest } from '../utils/request';
import { setToken } from '@/webPublic/one_stop_public/utils/token';
const api: string = '/UserApi';
const api2: string = '/ConfigApi';
const api3: string = '/UserApi';
interface getPayload {
email?: string;
}
interface fuc {
(response: any, isNull?: boolean): void,
}
const myCollect = {
namespace: 'emailorphone',
state: {
user: {}, // 用户数据
deaImg: '', // 全局背景图
},
effects: {
/**
* 发送邮箱验证码
* @params {email} 邮箱
*/
* GetSysCodeEmail({
payload,
callback,
}: { payload: getPayload, callback: fuc },
{
call,
put,
}: { call: any, put: any }) {
const response = yield call(uaaRequest, `${api}/sendResetCode`, {
...payload,
});
if (response == null) {
yield put({ type: 'nom' });
return;
}
if (callback) {
callback(response);
}
},
/**
* 发送绑定手机验证码
* @param {phone} 手机号
*/
* GetSysCodePhone({
payload,
callback,
}: { payload: getPayload, callback: fuc },
{
call,
put,
}: { call: any, put: any }) {
const response = yield call(uaaRequest, `${api}/sendResetCodePhone`, {
...payload,
});
if (response == null) {
yield put({ type: 'nom' });
return;
}
if (callback) {
callback(response);
}
},
/**
* 获得验证码后重置邮箱
* @params { verifyCode } 验证码
* @params {email} 邮箱
*/
* GetResteEmail({
payload,
callback,
}: { payload: getPayload, callback: fuc },
{
call,
put,
}: { call: any, put: any }) {
const response = yield call(uaaRequest, `${api}/changeEmail`, {
...payload,
});
if (response == null) {
yield put({ type: 'nom' });
if (callback) {
callback(response, true);
}
return;
}
if (callback) {
callback(response);
}
},
/**
* 获得验证码后重置手机
* @params {verifyCode } 验证码
* @params {phone} 手机
*/
* GetRestePhone({
payload,
callback,
}: { payload: getPayload, callback: fuc },
{
call,
put,
}: { call: any, put: any }) {
const response = yield call(uaaRequest, `${api}/changePhone`, {
...payload,
});
if (response == null) {
yield put({ type: 'nom' });
if (callback) {
callback(response, true);
}
return;
}
if (callback) {
callback(response);
}
},
/**
* 游客注册接口
* @params { username } 用户名
* @params { password } 密码
*/
* GetRegister({
payload,
callback,
}: { payload: getPayload, callback: fuc },
{
call,
put,
}: { call: any, put: any }) {
const response = yield call(uaaRequest, `${api}/register`, {
...payload,
});
if (response == null) {
yield put({ type: 'nom' });
return;
}
if (callback) {
callback(response);
}
},
/**
* 手机重置密码
* @params {verifyCode } 验证码
* @params {phone} 手机
*/
* GetPhonePassword({
payload,
callback,
}: { payload: getPayload, callback: fuc },
{
call,
put,
}: { call: any, put: any }) {
const response = yield call(uaaRequest, `${api}/changePhonePwd`, {
...payload,
});
if (response == null) {
yield put({ type: 'nom' });
return;
}
setToken(response.token);
if (callback) {
callback(response);
}
},
/**
* logo相关配置接口
* @parmas {configKey} 配置项
*/
* GetLogo({
payload,
callback,
}: {
payload: getPayload,
callback: fuc,
},
{
call,
put,
}: { call: any, put: any }) {
const response = yield call(uaaRequest, `${api2}/getDetails`, {
...payload,
});
if (response == null) {
yield put({ type: 'nom' });
return;
}
if (callback) {
callback(response);
}
},
/**
* 通过传入用户名直接拿取用户信息
*/
* GetUserData({
payload,
callback,
}: { payload: getPayload, callback: fuc },
{
call,
put,
}: { call: any, put: any }) {
const response = yield call(uaaRequest, `${api3}/loginByCount`, {
...payload,
});
if (response == null) {
yield put({ type: 'nom' });
return;
}
if (callback) {
callback(response);
}
},
/**
* 获取背景图并转存到modal中
*/
* GetDeaImg({
payload,
callback,
}: { payload: getPayload, callback: fuc },
{
call,
put,
}: { call: any, put: any }) {
const response = yield call(uaaRequest, `${api2}/getDetails`, {
...payload,
});
if (response == null) {
yield put({ type: 'nom' });
return;
}
if (callback) {
callback(response);
}
yield put({
type: 'setImg',
payload: response,
});
},
},
reducers: {
setImg(state: any, action: any) {
return {
...state,
deaImg: action.payload,
};
},
nom(state: any, action: any) {
return { ...state };
},
},
};
export default myCollect;
import { permRequest } from '../utils/request';
export default {
namespace: 'uaa_User',
state: {
data: {
list: [],
pagination: {},
},
data2: {
list: [],
pagination: {},
},
},
effects: {
*savePost({ payload, callback }, { call, put }) {
const response = yield call(permRequest, '/UserApi/savePost', payload);
if (!response) {
yield put({ type: 'nom' });
return;
}
yield put({
type: 'nom',
payload: response,
});
if (callback) callback(response);
},
*fetch2({ payload, callback }, { call, put }) {
const response = yield call(permRequest, '/UserApi/newGetPage', payload);
if (response == null) {
yield put({ type: 'nom' });
return;
}
yield put({
type: 'list2',
payload: response,
});
},
*getMyApp({ payload, callback }, { call, put }) {
const response = yield call(permRequest, '/UserApi/getMyApp', payload);
if (!response) {
yield put({ type: 'nom' });
return;
}
yield put({
type: 'nom',
payload: response,
});
if (callback) callback(response);
},
*findUser({ payload, callback }, { call, put }) {
const response = yield call(permRequest, '/UserApi/findUser', payload);
if (!response) {
yield put({ type: 'nom' });
return;
}
yield put({
type: 'nom',
payload: response,
});
if (callback) callback(response);
},
*isOpen({ payload, callback }, { call, put }) {
const response = yield call(permRequest, '/UserApi/isOpen', payload);
if (!response) {
yield put({ type: 'nom' });
return;
}
yield put({
type: 'nom',
payload: response,
});
if (callback) callback(response);
},
*add({ payload, callback }, { call, put }) {
const response = yield call(permRequest, '/UserApi/add', payload);
if (!response) {
yield put({ type: 'nom' });
return;
}
yield put({
type: 'nom',
payload: response,
});
if (callback) callback({ suc: true });
},
*changeAppIds({ payload, callback }, { call, put }) {
const response = yield call(permRequest, '/UserApi/changeAppIds', payload);
if (!response) {
yield put({ type: 'nom' });
return;
}
yield put({
type: 'nom',
payload: response,
});
if (callback) callback(response);
},
*getAppIds({ payload, callback }, { call, put }) {
const response = yield call(permRequest, '/UserApi/getAppIds', payload);
if (!response) {
yield put({ type: 'nom' });
return;
}
yield put({
type: 'nom',
payload: response,
});
if (callback) callback(response);
},
*changeUser({ payload, callback }, { call, put }) {
const response = yield call(permRequest, '/UserApi/changeUser', payload);
if (!response) {
yield put({ type: 'nom' });
return;
}
yield put({
type: 'nom',
payload: response,
});
if (callback) callback(response);
},
*getMy({ payload, callback }, { call, put }) {
const response = yield call(permRequest, '/UserApi/getMy', payload);
if (!response) {
yield put({ type: 'nom' });
return;
}
yield put({
type: 'nom',
payload: response,
});
if (callback) callback(response);
},
*changePassword({ payload, callback }, { call, put }) {
const response = yield call(permRequest, '/UserApi/changePassword', payload);
if (!response) {
yield put({ type: 'nom' });
return;
}
yield put({
type: 'nom',
payload: response,
});
if (callback) callback(response);
},
*fetch({ payload, callback }, { call, put }) {
const response = yield call(permRequest, '/UserApi/getPage', payload);
if (!response) {
yield put({ type: 'nom' });
return;
}
yield put({
type: 'list2',
payload: response,
});
if (callback) callback(response);
},
*remove({ payload, callback }, { call, put }) {
const response = yield call(permRequest, '/UserApi/remove', payload);
if (!response) {
yield put({ type: 'nom' });
return;
}
yield put({
type: 'nom',
payload: response,
});
if (callback) callback(response);
},
},
reducers: {
list(state, { payload }) {
return {
...state,
data: {
list: payload.rows,
pagination: {
current: payload.pageNo,
pageSize: payload.pageSize,
total: payload.total,
},
},
};
},
list2(state, { payload }) {
return {
...state,
data2: {
list: payload.rows,
pagination: {
current: payload.pageNo,
pageSize: payload.pageSize,
total: payload.total,
},
},
};
},
nom(state) {
return { ...state };
},
},
};
/**
* 徐立
* 2019年11月27日
* 个人申请新增按钮接口
*/
import { uaaRequest } from '../utils/request';
const api: string = "/UnifiedAppFormApi"
const myCollect = {
namespace: 'urge',
state: {
user: {}, // 用户数据
deaImg: '', // 全局背景图
},
effects: {
/**
* 催促办理请求
* @param {需要催办的数组id} taskIds
*/
* GetUrge({payload, callback}: { payload: any, callback: any },
{call, put}: { call: any, put: any }) {
const response = yield call(uaaRequest, `${api}/urgeProcess`, {
...payload,
});
if (response == null) {
yield put({type: 'nom'});
return
}
if (callback) {
callback(response)
}
},
/**
* 撤回已发起流程
* @param {撤回函数} taskIds
*/
* GetRecall({payload, callback}: { payload: any, callback: any },
{call, put}: { call: any, put: any }) {
const response = yield call(uaaRequest, `${api}/regressionProcess`, {
...payload,
});
if (response == null) {
yield put({type: 'nom'});
return
}
if (callback) {
callback(response)
}
},
/**
* 获取用户权限
*/
* GetMyPath({payload, callback}: { payload: any, callback: any },
{call, put}: { call: any, put: any }) {
const response = yield call(uaaRequest, `/UserApi/myPath`, {
...payload,
});
if (response == null) {
yield put({type: 'nom'});
return
}
if (callback) {
callback(response)
}
},
/**
* 紧急度动态按钮请求
*/
* GetMyBtn({payload, callback}: { payload: any, callback: any },
{call, put}: { call: any, put: any }) {
const response = yield call(uaaRequest, `/UnifiedAppFormLevelApi/getAll`, {
...payload,
});
if (response == null) {
yield put({type: 'nom'});
return
}
if (callback) {
callback(response)
}
},
},
reducers: {
setImg(state: any, action: any) {
return {
...state,
deaImg: action.payload,
};
},
nom(state: any, action: any) {
return {...state};
},
},
};
export default myCollect;
// import config from '@/webPublic/one_stop_public/config';
import { apiRequest } from '../utils/request';
const api = '/UserSetCenterApi';
const Search = {
namespace: 'UserSetCenterApi',
state: {
result: [], // 初始请求,默认条件为全选
options: {}, // 初始化请求条件
},
effects: {
// 新增或则修改1
*addOrUpdate({ payload, callback }, { call, put }) {
const response = yield call(apiRequest, `${api}/addOrUpdate`, payload);
if (response == null) {
yield put({ type: 'nom' });
return;
}
yield put({
type: 'nom',
payload: response,
});
if (callback) callback(response);
},
// 查询
*queryUserSet({ payload, callback }, { call, put }) {
const response = yield call(apiRequest, `${api}/queryUserSet`, payload);
if (response == null) {
yield put({ type: 'nom' });
return;
}
yield put({
type: 'nom',
payload: response,
});
if (callback) callback(response);
},
},
reducers: {
nom(state, action) {
return { ...state };
},
},
};
export default Search;
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论