Commit ce948e14 authored by jingnan's avatar jingnan 👀

批量签审功能开发

parent faaecadc
import BaseRenderer from 'diagram-js/lib/draw/BaseRenderer'
import { append as svgAppend, create as svgCreate } from 'tiny-svg'
import notify from '@/assets/notify.png'
const HIGH_PRIORITY = 1500
const customConfig = {
notify: {
url: notify,
attr: { x: 0, y: 0, width: 100, height: 80 }
}
}
const customElements = ['bpmn:ServiceTask']
export default class CustomRenderer extends BaseRenderer {
constructor(eventBus, bpmnRenderer) {
super(eventBus, HIGH_PRIORITY)
this.bpmnRenderer = bpmnRenderer
}
canRender(element) {
return !element.labelTarget
}
drawShape(parentNode, element) {
const type = element.type // 获取到类型
// 所有节点都会走这个函数,所以此时只限制,需要自定义的才去自定义,否则仍显示bpmn默认图标
let custom = null
if (element.type === 'bpmn:ServiceTask') {
const extensionElements = element.businessObject.extensionElements
if (extensionElements) {
const property = extensionElements.values
if (property && property.length) {
property.forEach(el => {
if (el.$children && el.$children.length) {
custom = el.$children.find((item) => {
return item.name === 'custom'
})
}
})
}
}
}
if (customElements.includes(type) && custom && custom.value === 'msgTask') {
const { url, attr } = customConfig['notify']
const customIcon = svgCreate('image', { ...attr, href: url })
element['width'] = attr.width
element['height'] = attr.height
svgAppend(parentNode, customIcon)
// 下方为更改节点名称位置(防止图片遮盖节点的文字)
if (element.businessObject.name) {
const text = svgCreate('text', {
class: 'djs-label-custom',
'font-size': '12px',
'font-family': 'Arial, sans-serif',
'font-weight': 'normal',
fill: 'black',
x: attr.x + 20,
y: attr.y + 50 // 位置可以随意调,我理解此时的attr.y 是此时元素的左上角纵坐标
})
const nameStr = element.businessObject.name
let str = ''
for (let i = 0; i < nameStr.length / 6; i++) {
const temp = nameStr.substring(i, i + 6)
const x = attr.x + 20
const y = attr.y + 50 + i * 15
str += `<tspan x=${x} y=${y}>${temp}</tspan>`
}
text.innerHTML = str
svgAppend(parentNode, text)
}
// 结束
return customIcon
}
const shape = this.bpmnRenderer.drawShape(parentNode, element)
return shape
}
getShapePath(shape) {
return this.bpmnRenderer.getShapePath(shape)
}
}
CustomRenderer.$inject = ['eventBus', 'bpmnRenderer']
import customRenderer from './customRenderer' // 自定义元素在canvas的渲染,否则渲染进去还是Task形状
export default {
__init__: ['customRenderer'],
customRenderer: ['type', customRenderer]
}
{
"name": "YondeNotify",
"uri": "http://yond-e.com/schema/bpmn/notify",
"prefix": "notify",
"xml": {
"tagAlias": "lowerCase"
},
"types": [
{
"name": "NotifyNode",
"extends": [
"bpmn:FlowNode"
],
"properties": [
{
"name": "description",
"isAttr": true,
"type": "String"
}
]
},
{
"name": "NotifyDetails",
"superClass": [ "NotifyNode" ],
"properties": [
{
"name": "sendConfig",
"isAttr": true,
"type": "SendConfig"
}
]
},
{
"name": "SendConfig",
"properties": [
{
"name": "notifyType",
"isAttr": true,
"type": "String"
},
{
"name": "mailServer",
"isAttr": true,
"type": "String"
},
{
"name": "notifyScopes",
"isMany": true,
"type": "NotifyScope"
}
]
},
{
"name": "NotifyScope",
"properties": [
{
"name": "type",
"isAttr": true,
"type": "String"
},
{
"name": "values",
"isAttr": true,
"type": "String"
}
]
}
],
"emumerations": [],
"associations": []
}
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg class="icon" width="48px" height="48.00px" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M0 424.3456m87.6544 0l848.6912 0q87.6544 0 87.6544 87.6544l0-0.2048q0 87.6544-87.6544 87.6544l-848.6912 0q-87.6544 0-87.6544-87.6544l0 0.2048q0-87.6544 87.6544-87.6544ZM424.3456 1024m0-87.6544l0-848.6912q0-87.6544 87.6544-87.6544l-0.2048 0q87.6544 0 87.6544 87.6544l0 848.6912q0 87.6544-87.6544 87.6544l0.2048 0q-87.6544 0-87.6544-87.6544Z" /></svg>
\ No newline at end of file
import translations from './translationsGerman'
export default function customTranslate(template, replacements) {
replacements = replacements || {}
// Translate
template = translations[template] || template
// Replace
return template.replace(/{([^}]+)}/g, function(_, key) {
return replacements[key] || '{' + key + '}'
})
}
export default {
// Labels
'Activate the global connect tool': '激活全局连接工具',
'Append {type}': '添加 {type}',
'Add Lane above': '在上面添加道',
'Divide into two Lanes': '分割成两个道',
'Divide into three Lanes': '分割成三个道',
'Add Lane below': '在下面添加道',
'Append compensation activity': '追加补偿活动',
'Change type': '修改类型',
'Connect using Association': '使用关联连接',
'Connect using Sequence/MessageFlow or Association': '使用顺序/消息流或者关联连接',
'Connect using DataInputAssociation': '使用数据输入关联连接',
'Remove': '移除',
'Activate the hand tool': '激活抓手工具',
'Activate the lasso tool': '激活套索工具',
'Activate the create/remove space tool': '激活创建/删除空间工具',
'Create expanded SubProcess': '创建扩展子过程',
'Create IntermediateThrowEvent/BoundaryEvent': '创建中间抛出事件/边界事件',
'Create Pool/Participant': '创建池/参与者',
'Parallel Multi Instance': '并行多重事件',
'Sequential Multi Instance': '时序多重事件',
'DataObjectReference': '数据对象参考',
'DataStoreReference': '数据存储参考',
'Loop': '循环',
'Ad-hoc': '即席',
'Create {type}': '创建 {type}',
'Task': '任务',
'Send Task': '发送任务',
'Receive Task': '接收任务',
'User Task': '用户任务',
'Manual Task': '手工任务',
'Business Rule Task': '业务规则任务',
'Service Task': '服务任务',
'Script Task': '脚本任务',
'Call Activity': '调用活动',
'Sub Process (collapsed)': '子流程(折叠的)',
'Sub Process (expanded)': '子流程(展开的)',
'Start Event': '开始事件',
'StartEvent': '开始事件',
'Intermediate Throw Event': '中间事件',
'End Event': '结束事件',
'EndEvent': '结束事件',
'Create Gateway': '创建网关',
'Create Intermediate/Boundary Event': '创建中间/边界事件',
'Message Start Event': '消息开始事件',
'Timer Start Event': '定时开始事件',
'Conditional Start Event': '条件开始事件',
'Signal Start Event': '信号开始事件',
'Error Start Event': '错误开始事件',
'Escalation Start Event': '升级开始事件',
'Compensation Start Event': '补偿开始事件',
'Message Start Event (non-interrupting)': '消息开始事件(非中断)',
'Timer Start Event (non-interrupting)': '定时开始事件(非中断)',
'Conditional Start Event (non-interrupting)': '条件开始事件(非中断)',
'Signal Start Event (non-interrupting)': '信号开始事件(非中断)',
'Escalation Start Event (non-interrupting)': '升级开始事件(非中断)',
'Message Intermediate Catch Event': '消息中间捕获事件',
'Message Intermediate Throw Event': '消息中间抛出事件',
'Timer Intermediate Catch Event': '定时中间捕获事件',
'Escalation Intermediate Throw Event': '升级中间抛出事件',
'Conditional Intermediate Catch Event': '条件中间捕获事件',
'Link Intermediate Catch Event': '链接中间捕获事件',
'Link Intermediate Throw Event': '链接中间抛出事件',
'Compensation Intermediate Throw Event': '补偿中间抛出事件',
'Signal Intermediate Catch Event': '信号中间捕获事件',
'Signal Intermediate Throw Event': '信号中间抛出事件',
'Message End Event': '消息结束事件',
'Escalation End Event': '定时结束事件',
'Error End Event': '错误结束事件',
'Cancel End Event': '取消结束事件',
'Compensation End Event': '补偿结束事件',
'Signal End Event': '信号结束事件',
'Terminate End Event': '终止结束事件',
'Message Boundary Event': '消息边界事件',
'Message Boundary Event (non-interrupting)': '消息边界事件(非中断)',
'Timer Boundary Event': '定时边界事件',
'Timer Boundary Event (non-interrupting)': '定时边界事件(非中断)',
'Escalation Boundary Event': '升级边界事件',
'Escalation Boundary Event (non-interrupting)': '升级边界事件(非中断)',
'Conditional Boundary Event': '条件边界事件',
'Conditional Boundary Event (non-interrupting)': '条件边界事件(非中断)',
'Error Boundary Event': '错误边界事件',
'Cancel Boundary Event': '取消边界事件',
'Signal Boundary Event': '信号边界事件',
'Signal Boundary Event (non-interrupting)': '信号边界事件(非中断)',
'Compensation Boundary Event': '补偿边界事件',
'Exclusive Gateway': '互斥网关',
'Parallel Gateway': '并行网关',
'Inclusive Gateway': '相容网关',
'Complex Gateway': '复杂网关',
'Event based Gateway': '事件网关',
'Transaction': '事务子流程',
'Sub Process': '子流程',
'Event Sub Process': '事件子流程',
'Collapsed Pool': '折叠池',
'Expanded Pool': '展开池',
'Create StartEvent': '创建开始事件',
'Create EndEvent': '创建结束事件',
'Create Task': '创建任务',
'Append EndEvent': '插入结束事件',
'Append Gateway': '插入网关',
'Append MessageIntermediateCatchEvent': '插入信号中间捕获事件',
'Append TimerIntermediateCatchEvent': '插入时间中间捕获事件',
'Append ConditionIntermediateCatchEvent': '插入条件中间捕获事件',
'Append SignalIntermediateCatchEvent': '插入信号中间捕获事件',
'Append Task': '插入任务',
'Append Intermediate/Boundary Event': '插入中间/边界事件',
'Append TextAnnotation': '文本注释',
// Errors
'no parent for {element} in {parent}': '在{parent}里,{element}没有父类',
'no shape type specified': '没有指定的形状类型',
'flow elements must be children of pools/participants': '流元素必须是池/参与者的子类',
'out of bounds release': 'out of bounds release',
'more than {count} child lanes': '子道大于{count} ',
'element required': '元素不能为空',
'diagram not part of bpmn:Definitions': '流程图不符合bpmn规范',
'no diagram to display': '没有可展示的流程图',
'no process or collaboration to display': '没有可展示的流程/协作',
'element {element} referenced by {referenced}#{property} not yet drawn': '由{referenced}#{property}引用的{element}元素仍未绘制',
'already rendered {element}': '{element} 已被渲染',
'failed to import {element}': '导入{element}失败',
// 属性面板的参数
'Id': '编号',
'Name': '名称',
'General': '常规',
'Details': '详情',
'Message Name': '消息名称',
'Message': '消息',
'Initiator': '创建者',
'Asynchronous Continuations': '持续异步',
'Asynchronous Before': '异步前',
'Asynchronous After': '异步后',
'Job Configuration': '工作配置',
'Exclusive': '排除',
'Job Priority': '工作优先级',
'Retry Time Cycle': '重试时间周期',
'Documentation': '文档',
'Element Documentation': '元素文档',
'History Configuration': '历史配置',
'History Time To Live': '历史的生存时间',
'Forms': '表单',
'Form Key': '表单key',
'Form Fields': '表单字段',
'Business Key': '业务key',
'Form Field': '表单字段',
'ID': '编号',
'Type': '类型',
'Label': '名称',
'Default Value': '默认值',
'Validation': '校验',
'Add Constraint': '添加约束',
'Config': '配置',
'Properties': '属性',
'Add Property': '添加属性',
'Value': '值',
'Listeners': '监听器',
'Execution Listener': '执行监听',
'Event Type': '事件类型',
'Listener Type': '监听器类型',
'Java Class': 'Java类',
'Expression': '表达式',
'Must provide a value': '必须提供一个值',
'Delegate Expression': '代理表达式',
'Script': '脚本',
'Script Format': '脚本格式',
'Script Type': '脚本类型',
'Inline Script': '内联脚本',
'External Script': '外部脚本',
'Resource': '资源',
'Field Injection': '字段注入',
'Extensions': '扩展',
'Input/Output': '输入/输出',
'Input Parameters': '输入参数',
'Output Parameters': '输出参数',
'Parameters': '参数',
'Output Parameter': '输出参数',
'Timer Definition Type': '定时器定义类型',
'Timer Definition': '定时器定义',
'Date': '日期',
'Duration': '持续',
'Cycle': '循环',
'Signal': '信号',
'Signal Name': '信号名称',
'Escalation': '升级',
'Error': '错误',
'Link Name': '链接名称',
'Condition': '条件名称',
'Variable Name': '变量名称',
'Variable Event': '变量事件',
'Specify more than one variable change event as a comma separated list.': '多个变量事件以逗号隔开',
'Wait for Completion': '等待完成',
'Activity Ref': '活动参考',
'Version Tag': '版本标签',
'Executable': '可执行文件',
'External Task Configuration': '扩展任务配置',
'Task Priority': '任务优先级',
'External': '外部',
'Connector': '连接器',
'Must configure Connector': '必须配置连接器',
'Connector Id': '连接器编号',
'Implementation': '实现方式',
'Field Injections': '字段注入',
'Fields': '字段',
'Result Variable': '结果变量',
'Topic': '主题',
'Configure Connector': '配置连接器',
'Input Parameter': '输入参数',
'Assignee': '代理人',
'Candidate Users': '候选用户',
'Candidate Groups': '候选组',
'Due Date': '到期时间',
'Follow Up Date': '跟踪日期',
'Priority': '优先级',
'The follow up date as an EL expression (e.g. ${someDate} or an ISO date (e.g. 2015-06-26T09:54:00)': '跟踪日期必须符合EL表达式,如: ${someDate} ,或者一个ISO标准日期,如:2015-06-26T09:54:00',
'The due date as an EL expression (e.g. ${someDate} or an ISO date (e.g. 2015-06-26T09:54:00)': '跟踪日期必须符合EL表达式,如: ${someDate} ,或者一个ISO标准日期,如:2015-06-26T09:54:00',
'Variables': '变量'
}
<!--
* @Author: gjn
* @Date: 2023-08-02 10:03:15
* @Description:流程跟踪
-->
<template>
<div class="process-tracking-com">
<div class="controller-controller">
<svg-icon class-name="fangda" icon-class="fangda" @click="zoomOut" />
<svg-icon class-name="suoxiao" icon-class="suoxiao" @click="zoomIn" />
</div>
<div class="containers-wrap">
<div ref="bpnmDiv" class="containers" :style="{width: 100 * scale + '%',height: 100 * scale + '%'}" />
</div>
<div class="fb mt20 mb4">处理人信息</div>
<dee-up-table
:columns="colums"
:data="tableData"
/>
</div>
</template>
<script>
import { panZoom } from './moveAndZoom'
// 引入相关的依赖
import BpmnViewer from 'bpmn-js'
import customRender from './bpmn/custom-render'
import { getInsXml, getHistoryParticipantInfo, getCurrentParticipantInfo } from '@/api/workflow/userSettings.js'
export default {
name: 'ProcessTracking',
components: { },
props: {
// processInstanceId: {
// type: String,
// default: null
// },
parentTableData: {
type: Object,
default: null
}
},
data() {
return {
// bpmn建模器
BpmnViewer: null,
container: null,
canvas: null,
scale: 1,
xmlData: null,
tableData: [],
colums: [
{
title: '处理人', key: 'assigneeName', align: 'center', minWidth: 180,
component: {
render: (h, row) => {
return h('DeeUserProfile', {
props: {
value: {
userId: row.assignee,
userName: row.assigneeName
}
}
})
}
}
},
{ title: '处理时间', key: 'endTime', align: 'center', minWidth: 180 },
{ title: '处理结果', key: 'result', align: 'center', minWidth: 180 },
{ title: '备注', key: 'comments', align: 'center', minWidth: 180, formatter: function(row, column) {
return row.comments ? row.comments.join('\n') : ''
} }
]
}
},
computed: {
processInstanceId() {
return this.parentTableData ? this.parentTableData.processInstanceId : ''
}
},
watch: {
processInstanceId: {
handler: function(val) {
val && this.getXml(val)
},
immediate: true
}
},
created() {
},
mounted() {
},
methods: {
/**
* @description 放大画布
*/
zoomOut() {
const x = this.bpmnViewer.mainContainerWrap.clientWidth / 2
const y = this.bpmnViewer.mainContainerWrap.clientHeight / 2
this.bpmnViewer.pan.smoothZoom(x, y, 1.2)
},
// /**
// * @description 缩小画布
// */
zoomIn() {
const x = this.bpmnViewer.mainContainerWrap.clientWidth / 2
const y = this.bpmnViewer.mainContainerWrap.clientHeight / 2
this.bpmnViewer.pan.smoothZoom(x, y, 0.8)
},
drawXml(data) {
this.$nextTick(() => {
this.createNewDiagram(data.xml, data.activeActivities, data.historyActivities)
})
},
createNewDiagram(bpmnXmlStr, arr, historyArr) {
this.bpmnViewer && this.bpmnViewer.destroy()
this.bpmnViewer = new BpmnViewer({
container: this.$refs.bpnmDiv,
additionalModules: [
// 自定义
customRender
]
})
panZoom(this.bpmnViewer)
this.bpmnViewer.importXML(bpmnXmlStr, (err) => {
if (err) { console.error(err) }
const bpmnCanvas = this.bpmnViewer.get('canvas')
// 兼容chrome49svg字体无法缩小
const svgDOM = bpmnCanvas._container.querySelector('svg[data-element-id=SupervisionAndInspection]')
if (svgDOM) {
svgDOM.setAttribute('text-rendering', 'geometricPrecision')
}
bpmnCanvas.zoom('fit-viewport', 'auto')
if (arr && arr.length) {
const activeArr = this.uniq(arr)
activeArr.forEach((item) => {
bpmnCanvas.addMarker(item.taskKey, 'highlight')
})
getHistoryParticipantInfo(this.processInstanceId, arr[0].taskKey).then(res => {
this.tableData = res.items.content
})
}
if (historyArr && historyArr.length) {
const historyActivities = this.array_diff(this.uniq(historyArr), arr)
historyActivities.forEach((item) => {
bpmnCanvas.addMarker(item.taskKey, 'lowlight')
})
}
this.addModelerListener(arr, historyArr)
})
},
addModelerListener(arr, historyArr) {
const eventBus = this.bpmnViewer.get('eventBus')
const eventTypes = ['element.click', 'element.changed']
eventTypes.forEach((eventType) => {
eventBus.on(eventType, (e) => {
if (!e || !e.element) {
return
}
if (eventType === 'element.click' && e.element.type === 'bpmn:UserTask') {
const curNodeItem = arr.find(r => r.taskKey === e.element.id)
const historyNodeItem = historyArr.find(r => r.taskKey === e.element.id)
const fun = curNodeItem || historyNodeItem ? getHistoryParticipantInfo : getCurrentParticipantInfo
fun(this.processInstanceId, e.element.id).then(res => {
this.tableData = res.items.content
})
}
})
})
},
array_diff(a, b) {
a.forEach((m, x) => {
b.forEach((n) => {
if (m.taskKey === n.taskKey) {
a.splice(x, 1)
}
})
})
return a
},
uniq(array) {
var temp = []
var l = array.length
for (var i = 0; i < l; i++) {
for (var j = i + 1; j < l; j++) {
if (array[i].taskKey === array[j].taskKey) {
i++
j = i
}
}
temp.push(array[i])
}
return temp
},
handleClose() {
this.$emit('handleCloseFlow')
},
getXml(id) {
getInsXml(id).then(res => {
this.xmlData = res.items
this.drawXml(res.items)
})
}
}
}
</script>
<style lang="scss">
/*左边工具栏以及编辑节点的样式*/
@import "../../../../node_modules/bpmn-js/dist/assets/diagram-js.css";
@import "../../../../node_modules/bpmn-js/dist/assets/bpmn-font/css/bpmn.css";
@import "../../../../node_modules/bpmn-js/dist/assets/bpmn-font/css/bpmn-codes.css";
@import "../../../../node_modules/bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css";
.process-tracking-com {
// padding: 20px;
width: 100%;
height: 100%;
overflow: scroll;
background: #fff;
.fb{
font-weight: bold;
}
.mt20{
margin-top: 20px;
}
.mb4{
margin-bottom: 4px;
}
.containers-wrap {
width: 100%;
height: 600px;
background: #f8f8f8;
overflow: hidden;
}
.canvas {
width: 100%;
height: 100%;
}
.panel {
position: absolute;
right: 0;
top: 0;
width: 300px;
}
.djs-palette {
display: none;
}
.djs-element.djs-shape > .djs-visual > rect {
stroke: #666666!important;
}
.djs-element.djs-shape > .djs-visual > .djs-label {
font-size: 14px !important;
font-weight: bold !important;
}
.highlight:not(.djs-connection) .djs-visual > :nth-child(1) {
fill: #59a35d !important;
stroke:#388f3d!important;
// opacity: .4;
pointer-events: none;
}
.highlight:not(.djs-connection) .djs-visual > :nth-child(2) {
fill: white !important;
}
.lowlight:not(.djs-connection) .djs-visual > :nth-child(1) {
fill: #d9e0e9 !important;
stroke: #b9c3cf !important;
// opacity: .4;
pointer-events: none;
}
.controller-controller{
position: absolute;
right: 32px;
top: 50px;
width: 80px;
padding: 8px;
text-align: right;
font-size: 20px;
z-index: 1;
cursor: pointer;
.suoxiao,.fangda{
padding: 8px;
}
}
}
</style>
const panzoom = require('panzoom')
// 初始化panzoom插件
export function panZoom(instance) {
const mainContainer = instance._container
const mainContainerWrap = mainContainer.parentNode
const pan = panzoom(mainContainer, {
smoothScroll: false,
bounds: true,
// autocenter: true,
zoomDoubleClickSpeed: 1,
minZoom: 0.5,
maxZoom: 100
})
instance.mainContainerWrap = mainContainerWrap
instance.pan = pan
// 缩放时设置jsPlumb的缩放比率
pan.on('zoom', (e) => {
const { scale } = e.getTransform()
instance.get('canvas').zoom(scale)
instance.get('canvas').zoom('fit-viewport', 'auto')
})
// 平移时设置鼠标样式
mainContainerWrap.style.cursor = 'grab'
mainContainerWrap.addEventListener('mousedown', function wrapMousedown() {
this.style.cursor = 'grabbing'
// mainContainerWrap.addEventListener('mouseout', function wrapMouseout() {
// this.style.cursor = 'grab'
// })
})
mainContainerWrap.addEventListener('mouseup', function wrapMouseup() {
this.style.cursor = 'grab'
})
}
export default {
panZoom
}
<!--
* @Author: gjn
* @Date: 2023-08-02 10:51:11
* @Description:签审历史记录
-->
<template>
<div v-dee-loading="loading" class="task-detail-process-common-com">
<div class="name">
<div class="message-popper-flow">
<div>
<div
v-for="(pitem, id) in historyInfo"
:key="id"
class="program-item"
>
<div class="program-left">
<!-- <div class="program-left-content">
<div>{{ pitem.completed?'已完成':'待完成' }}</div>
</div> -->
<div v-show="pitem.endTime" class="program-circle-finished" />
<div v-show="!pitem.endTime" class="program-circle-unfinished" />
</div>
<div class="program-right">
<div style="padding: 2px 0">{{ pitem.aliasName || pitem.name }}</div>
<div>
<span class="p-r-title">{{ pitem.vote && pitem.vote.indexOf('null')>-1?'':pitem.vote }}</span>
{{ pitem.assigneeName }}
</div>
<div style="padding: 2px 0">
{{ pitem.startTime || '' }} {{ pitem.startTime && pitem.endTime ? '~' : '' }} {{ pitem.endTime || '' }}
<span v-if="pitem.restDay!==''">持续 {{ calculateDay(pitem) }}</span>
</div>
<div v-if="pitem.result" style="padding: 2px 0">
处理结果:{{ pitem.result }}
</div>
<!-- <div v-if="pitem.comments.length" style="padding: 2px 0">备注:{{ pitem.comments ? pitem.comments.join('\n') : '' }}</div> -->
</div>
</div>
</div>
<!-- <div v-else style="line-height: 88px;text-align: center">暂无数据</div> -->
</div>
</div>
</div>
</template>
<script>
import moment from 'moment'
import { getInstanceHistory } from '@/api/workflow/userSettings.js'
export default {
name: 'TaskDetailProcess',
components: {},
props: {
parentTableData: {
type: Object,
default: null
}
},
data() {
return {
loading: true,
item: {},
historyInfo: [],
businessObject: null,
basicData: {}
}
},
computed: {
processInstanceId() {
return this.parentTableData ? this.parentTableData.processInstanceId : ''
}
},
watch: {
basicData: {
handler: function(val) {
// this.businessObject = val.businessObject
this.historyInfo = val.historyInfo || []
},
immediate: true
},
processInstanceId: {
handler: function(val) {
this.$nextTick(function() {
this.getDetail(val)
})
},
immediate: true
}
},
created() {
// this.getDetail('678df986-9c26-11eb-9fc3-fa163ee7db6d')
},
methods: {
handleClose() {
this.$emit('handleClose')
},
// 获取任务详情
getDetail(instanceId) {
this.loading = true
// 获取流程历史记录
getInstanceHistory(instanceId).then(res => {
this.$set(this.basicData, 'historyInfo', res.items.content || [])
}).catch(err => console.log(err)).finally(() => {
this.loading = false
})
},
calculateDay(item) {
//
let restDay = ''
if (item.endTime && item.startTime) {
restDay = moment(new Date(item.endTime).getTime()).diff(moment(new Date(item.startTime).getTime()), 'day')
} else if (!item.endTime && item.startTime) {
restDay = moment().diff(moment(new Date(item.startTime).getTime()), 'day')
}
return restDay
},
loadProcess(item) {
}
}
}
</script>
<style lang="scss">
// @import "../../styles/mixin";
// @import "../../styles/variables";
.task-detail-process-common-com{
height: 100%;
padding-bottom: 8px;
.name {
max-height: 800px;
line-height: 24px;
font-size: 14px;
overflow: auto;
}
.select-header{
display:flex;
justify-content: flex-start;
width: 100%;
height: 35px;
background: linear-gradient(90deg, #2F70A4 0%, #4E85A3 64%, #55A781 100%);
.select-name{
width: 152px;
height: 13px;
font-size: 13px;
font-family: Microsoft YaHei;
font-weight: 400;
color: #FEFEFE;
line-height: 76px;
margin: -20px 0px -17px 10px;
}
.close-pic{
display: block;
width: 7px;
height: 7px;
background-image: url('/icons/settledlcons/more.png');
background-size: cover;
margin: 11px 15px 11px 15px;
padding: 5px;
}
}
.message-popper-flow {
padding: 0 !important;
background: #f5f5f5 !important;
border: 1px solid #d4d4d4 !important;
width: 698px !important;
height: 100%;;
overflow: auto;
box-shadow: #dadada 0 0 15px !important;
.program-item {
// height: 88px;
width: 100%;
display: flex;
padding: 8px;
box-sizing: border-box;
cursor: pointer;
&:hover {
background: #e7eef8;
}
.program-left {
width: 24px;
height: 100%;
box-sizing: border-box;
// padding-right: 15px;
text-align: right;
display: flex;
margin-top: 6px;
.program-left-content {
flex: 1;
}
.program-circle-finished {
display: inline-block;
margin-left: 15px;
width: 8px;
height: 8px;
border-radius: 100%;
background-color: #d9d9d9;
box-sizing: border-box;
position: relative;
&:after {
content: "";
position: absolute;
width: 1px;
height: 56px;
// background: rgba(217, 217, 217, 1);
top: 16px;
left: 3px;
}
}
.program-circle-unfinished {
display: inline-block;
margin-left: 15px;
width: 8px;
height: 8px;
border-radius: 100%;
background: #2A75CE;
// @include color(background-color);
box-sizing: border-box;
position: relative;
&:after {
content: "";
position: absolute;
width: 1px;
height: 56px;
// background: rgba(217, 217, 217, 1);
top: 16px;
left: 3px;
}
}
}
.program-right {
flex: 1;
padding-left: 15px;
flex-direction: column-reverse;
.p-r-title {
color: #212121;
}
}
}
}
}
</style>
......@@ -33,7 +33,7 @@ export default {
icon: '/images/common/batchEdit.png'
}
],
activeName: '批量签审'
activeName: '单个签审'
}
},
methods: {
......
......@@ -10,8 +10,7 @@
<module-task-list ref="moduleTaskList" @goModuleTaskDetail="goModuleTaskDetail" />
</div>
<div slot="right" class="right-box">
<!-- <module-task-detail v-if="selectData && selectData.subType" :select-data="selectData" /> -->
<module-task-detail :select-data="selectData" />
<module-task-detail v-if="selectData && selectData.taskKey" :select-data="selectData" />
</div>
</right-to-left>
</div>
......
<template>
<div class="MyPlanTaskPage">
<div v-if="loadComponents" class="TaskComponentView" :class="{'height_class':heightClass}">
<compnent :is="tabPosition" :sub-type="subType" :def-state="state" />
<div class="TaskComponentView" :class="{'height_class':heightClass}">
<compnent is="WarehouseApply" :select-data="selectData" :sub-type="subType" :def-state="state" />
</div>
</div>
</template>
......@@ -9,11 +9,12 @@
<script>
export default {
components: {
WarehouseApply: () => import('./warehouseApply')
},
props: {
selectData: {
type: Object,
default: () => null
default: () => {}
}
},
data() {
......@@ -26,54 +27,14 @@ export default {
}
},
watch: {
selectData(newVal, oldVal) {
if (oldVal) {
if (newVal.state !== oldVal.state || newVal.subType !== oldVal.subType) {
this.loadComponents = false
this.subType = newVal.subType
this.state = newVal.state
this.tabPosition = this.getComponentName()
this.$nextTick(() => {
this.loadComponents = true
})
}
} else if (newVal) {
this.subType = newVal.subType
this.state = newVal.state
this.tabPosition = this.getComponentName()
}
}
},
created() {
// this.tabPosition = this.getComponentName()
},
mounted() {
// const radioHeight = document.getElementsByClassName('task_list')[0].offsetHeight
// if (radioHeight > 40) {
// this.heightClass = true
// }
},
methods: {
getComponentName() {
// const { subType } = this.$route.query
const subType = this.subType
let componentName = ''
const childCompsObj = this.childComps.find(eve => eve.subType === subType)
if (childCompsObj) {
componentName = childCompsObj.compName
}
return componentName
},
onTabChange(compName) {
this.loadComponents = false
// 通过路由跳转,实现参数同步反映在URL上,页面按钮切换导致查询参数不正确
const item = this.childComps.find(c => c.compName === compName)
this.subType = item.subType
this.state = ''
this.$nextTick(() => {
this.loadComponents = true
})
}
}
}
</script>
......
<!--
* @Author: gjn
* @Date: 2023-08-01 10:28:07
* @Description:验收入库申请
-->
<template>
<div class="warehouseApply">
<dee-as-com
ref="search"
:lay-config="{ typeName: 'InStorageRequestItem', layKey: 'warehouse_search'}"
:basic-data="defaultData"
@searchEvent="searchEvent"
/>
<!-- tab页签 -->
<el-tabs v-model="active" type="border-card" class="detailTabs">
<el-tab-pane :label="'器材验收单(' + totals.MaterialTotal + ')'" name="Material">
<dee-as-com
ref="MaterialTable"
class="list-table"
:basic-data=" { selectData: selectData }"
:lay-config="{ typeName: 'InStorageRequestItem', layKey: 'material_table'}"
/>
</el-tab-pane>
<el-tab-pane :label="'机载系统设备验收单(' + totals.AirEquipmentTotal + ')'" name="AirEquipment">
<dee-as-com
ref="AirEquipmentTable"
class="list-table"
:lay-config="{ typeName: 'InStorageRequestItem', layKey: 'airEquipment_table'}"
:basic-data=" { selectData: selectData }"
/>
</el-tab-pane>
<el-tab-pane :label="'外包产品验收单(' + totals.OutSourceTotal + ')'" name="OutSource">
<dee-as-com
ref="OutSourceTable"
class="list-table"
:lay-config="{ typeName: 'InStorageRequestItem', layKey: 'outSource_table'}"
:basic-data=" { selectData: selectData }"
/>
</el-tab-pane>
</el-tabs>
</div>
</template>
<script>
export default {
name: 'WarehouseApply',
components: {},
props: {
selectData: {
type: Object,
default: () => {}
}
},
data() {
return {
active: 'Material',
defaultData: {},
totals: {
MaterialTotal: 0,
AirEquipmentTotal: 0,
OutSourceTotal: 0
},
billTypeList: [],
searchItems: [],
tabNames: [
'Material',
'AirEquipment',
'OutSource'
]
}
},
computed: {
},
watch: {
selectData: {
immediate: true,
deep: true,
handler(val) {
if (val && val.taskKey) {
this.$nextTick(() => {
this.getTableData()
})
}
}
}
},
created() {
// this.getDict()
},
mounted() {
// 获取total在界面渲染 临时渲染数据, 待修改
setTimeout(() => {
this.tabNames.forEach(item => {
const el = this.$refs[item + 'Table']
this.$set(this.totals, item + 'Total', el.$refs.asCom.pagination.total)
})
}, 2000)
},
// 组件方法
methods: {
getTableData() {
this.tabNames.forEach(item => {
const el = this.$refs[item + 'Table']
if (el && el.$refs.asCom) {
el.$refs.asCom.getData(this.searchItems)
setTimeout(() => {
this.$set(this.totals, item + 'Total', el.$refs.asCom.pagination.total)
}, 1000) // 临时渲染数据, 待修改
}
})
},
searchEvent(val) {
this.searchItems = val.items
this.getTableData()
}
}
}
</script>
<style lang='scss'>
.warehouseApply{
width: 100%;
height: 100%;
box-sizing: border-box;
padding:0 4px;
.search-form-box-com .search-box-col{
width: 100%!important;
}
.detailTabs {
height: calc(100% - 40px);
border: 0;
.dee-table-header{
padding: 0px 10px;
.dee-tools{
margin: 4px 0;
}
}
}
.el-tabs--border-card > .el-tabs__content {
padding: 0px;
height: calc(100% - 70px);
.el-tab-pane{
height: 100%;
}
}
.el-tabs--border-card > .el-tabs__header {
.el-tabs__nav-wrap {
margin: 0px;
}
.el-tabs__item.is-active {
color: #409eff;
}
}
}
</style>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment