🎉 1.2.8.RELEASE

saber
ssc 4 years ago
parent 8c14a375ca
commit 71d7781e31
  1. 10
      public/cdn/avue-form-design/index.umd.min.js
  2. 2
      public/cdn/wf-design/index.umd.min.js
  3. 11
      src/store/modules/tags.js
  4. 18
      src/views/plugin/workflow/mixins/ex-form.js
  5. 27
      src/views/plugin/workflow/mixins/theme.js
  6. 7
      src/views/plugin/workflow/process/claim.vue
  7. 74
      src/views/plugin/workflow/process/components/button.vue
  8. 59
      src/views/plugin/workflow/process/components/detail.vue
  9. 2
      src/views/plugin/workflow/process/components/form.vue
  10. 6
      src/views/plugin/workflow/process/copy.vue
  11. 9
      src/views/plugin/workflow/process/done.vue
  12. 165
      src/views/plugin/workflow/process/external/Leave/detail.vue
  13. 142
      src/views/plugin/workflow/process/external/Leave/start.vue
  14. 127
      src/views/plugin/workflow/process/external/template/detail.vue
  15. 95
      src/views/plugin/workflow/process/external/template/start.vue
  16. 9
      src/views/plugin/workflow/process/my-done.vue
  17. 6
      src/views/plugin/workflow/process/send.vue
  18. 23
      src/views/plugin/workflow/process/todo.vue
  19. 41
      src/views/plugin/workflow/styles/theme/border.scss
  20. 128
      src/views/plugin/workflow/styles/theme/default.scss

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -1,5 +1,5 @@
import {setStore, getStore} from '@/util/store' import {setStore, getStore} from '@/util/store'
import {diff} from '@/util/util' import {diff, deepClone} from '@/util/util'
import website from '@/config/website' import website from '@/config/website'
const isFirstPage = website.isFirstPage; const isFirstPage = website.isFirstPage;
@ -40,7 +40,14 @@ const navs = {
ADD_TAG: (state, action) => { ADD_TAG: (state, action) => {
state.tag = action; state.tag = action;
setStore({name: 'tag', content: state.tag}) setStore({name: 'tag', content: state.tag})
if (state.tagList.some(ele => diff(ele, action))) return
// 去除对象中的label,防止修改了tag的label后重复添加
const tagList = deepClone(state.tagList)
tagList.forEach(t => delete t.label)
const tag = deepClone(action)
delete tag.label
if (tagList.some(ele => diff(ele, tag))) return
state.tagList.push(action) state.tagList.push(action)
setFistTag(state.tagList); setFistTag(state.tagList);
setStore({name: 'tagList', content: state.tagList}) setStore({name: 'tagList', content: state.tagList})

@ -76,10 +76,17 @@ export default {
column.forEach(col => { column.forEach(col => {
let c = taskForm.find(s => s.id == col[props.prop]) let c = taskForm.find(s => s.id == col[props.prop])
if (c && c.readable) { if (c && c.readable) {
let event = ['change', 'blur', 'click', 'focus']
if (c.writable) { // 可写,记录需要提交的字段、处理字段默认值 if (c.writable) { // 可写,记录需要提交的字段、处理字段默认值
vars.push(col[props.prop]) vars.push(col[props.prop])
if (col.value) col.value = _this.getDefaultValues(col.value) if (col.value) col.value = _this.getDefaultValues(col.value)
} else { // 不可写,清除校验与默认值
// 处理事件
event.forEach(e => {
if (col[e]) col[e] = eval((col[e] + '').replace(/this/g, '_this'))
})
if (col.event) Object.keys(col.event).forEach(key => col.event[key] = eval((col.event[key] + '').replace(/this/g, '_this')))
} else { // 不可写,清除校验、默认值、事件
if (col.type == 'dynamic') { if (col.type == 'dynamic') {
col.children.addBtn = false col.children.addBtn = false
col.children.delBtn = false col.children.delBtn = false
@ -89,6 +96,8 @@ export default {
} }
delete col.rules delete col.rules
delete col.value delete col.value
delete col.event
event.forEach(e => delete col[e])
} }
if (col.type == 'dynamic') { // 处理子表单 if (col.type == 'dynamic') { // 处理子表单
col.children.column = _this.filterAvueColumn(col.children.column, taskForm).column col.children.column = _this.filterAvueColumn(col.children.column, taskForm).column
@ -99,13 +108,6 @@ export default {
}) })
} }
// 处理事件
let event = ['change', 'blur', 'click', 'focus']
event.forEach(e => {
if (col[e]) col[e] = eval((col[e] + '').replace(/this/g, '_this'))
})
if (col.event) Object.keys(col.event).forEach(key => col.event[key] = eval((col.event[key] + '').replace(/this/g, '_this')))
values.push(col) values.push(col)
} }
}) })

@ -0,0 +1,27 @@
import { getStore, setStore } from '@/util/store'
export default {
data() {
return {
theme: '',
themeList: [{
label: '默认',
value: 'default'
}, {
label: '边框',
value: 'border'
}]
}
},
created() {
const theme = getStore({ name: 'wf-theme' })
if (theme || theme == '') this.theme = theme
},
watch: {
theme(val) {
if (val) {
import(`../styles/theme/${val}.scss`)
}
setStore({ name: 'wf-theme', content: val })
}
},
}

@ -31,10 +31,11 @@
<el-dialog :visible.sync="bpmnVisible" <el-dialog :visible.sync="bpmnVisible"
append-to-body append-to-body
destroy-on-close destroy-on-close
title="流程图"> title="流程图"
width="70%"
custom-class="wf-dialog">
<wf-design ref="bpmn" <wf-design ref="bpmn"
style="height: 500px;" style="height: 60vh;"
access-key="OFdH37<Bs9[8A74vp)5B59Fu3c1I7{N:"
:options="bpmnOption"></wf-design> :options="bpmnOption"></wf-design>
</el-dialog> </el-dialog>
</basic-container> </basic-container>

@ -1,49 +1,51 @@
<template> <template>
<div> <div v-if="process.status == 'todo' || (process.status == 'done' && buttonList.find(b => b.buttonKey == 'wf_print'))">
<div style="height: 120px;"></div> <div style="height: 120px;"></div>
<el-row class="foot-item avue-affix" <el-row class="foot-item avue-affix"
:style="{width: isCollapse? 'calc(100% - 80px)': 'calc(100% - 260px)' }" :style="{width: isCollapse? 'calc(100% - 80px)': 'calc(100% - 260px)' }"
id="avue-view"> id="avue-view">
<el-button v-if="buttonList.find(b => b.buttonKey == 'wf_pass')" <template v-if="process.status == 'todo'">
type="success" <el-button v-if="buttonList.find(b => b.buttonKey == 'wf_pass')"
size="medium" type="success"
v-loading="loading" size="medium"
@click="$emit('examine', true)">通过</el-button> v-loading="loading"
<el-button v-if="buttonList.find(b => b.buttonKey == 'wf_reject')" @click="$emit('examine', true)">通过</el-button>
type="danger" <el-button v-if="buttonList.find(b => b.buttonKey == 'wf_reject')"
size="medium" type="danger"
v-loading="loading" size="medium"
@click="$emit('examine', false)">驳回</el-button> v-loading="loading"
<el-button v-if="buttonList.find(b => b.buttonKey == 'wf_transfer')" @click="$emit('examine', false)">驳回</el-button>
type="primary" <el-button v-if="buttonList.find(b => b.buttonKey == 'wf_transfer')"
size="medium" type="primary"
v-loading="loading" size="medium"
@click="$emit('user-select', {type: 'transfer', checkType: 'radio'})">转办</el-button> v-loading="loading"
<el-button v-if="buttonList.find(b => b.buttonKey == 'wf_delegate')" @click="$emit('user-select', {type: 'transfer', checkType: 'radio'})">转办</el-button>
type="warning" <el-button v-if="buttonList.find(b => b.buttonKey == 'wf_delegate')"
size="medium" type="warning"
v-loading="loading" size="medium"
@click="$emit('user-select', {type: 'delegate', checkType: 'radio'})">委托</el-button> v-loading="loading"
@click="$emit('user-select', {type: 'delegate', checkType: 'radio'})">委托</el-button>
<el-button v-if="buttonList.find(b => b.buttonKey == 'wf_rollback')"
type="success"
size="medium"
v-loading="loading"
@click="handleRollback">指定回退</el-button>
<el-button v-if="buttonList.find(b => b.buttonKey == 'wf_terminate')"
type="danger"
size="medium"
v-loading="loading"
@click="$emit('terminate')">终止</el-button>
<el-button v-if="process.isMultiInstance && buttonList.find(b => b.buttonKey == 'wf_add_instance')"
type="primary"
size="medium"
v-loading="loading"
@click="$emit('user-select', {type: 'addInstance', checkType: 'checkbox'})">加签</el-button>
</template>
<el-button v-if="buttonList.find(b => b.buttonKey == 'wf_print')" <el-button v-if="buttonList.find(b => b.buttonKey == 'wf_print')"
type="info" type="info"
size="medium" size="medium"
v-loading="loading" v-loading="loading"
@click="$emit('print')">打印</el-button> @click="$emit('print')">打印</el-button>
<el-button v-if="buttonList.find(b => b.buttonKey == 'wf_rollback')"
type="success"
size="medium"
v-loading="loading"
@click="handleRollback">指定回退</el-button>
<el-button v-if="buttonList.find(b => b.buttonKey == 'wf_terminate')"
type="danger"
size="medium"
v-loading="loading"
@click="$emit('terminate')">终止</el-button>
<el-button v-if="process.isMultiInstance && buttonList.find(b => b.buttonKey == 'wf_add_instance')"
type="primary"
size="medium"
v-loading="loading"
@click="$emit('user-select', {type: 'addInstance', checkType: 'checkbox'})">加签</el-button>
</el-row> </el-row>
<el-dialog :visible.sync="nodeVisible" <el-dialog :visible.sync="nodeVisible"
append-to-body append-to-body

@ -4,16 +4,23 @@
avatar avatar
:rows="8"> :rows="8">
<avue-affix id="avue-view" <avue-affix id="avue-view"
:offset-top="116"> :offset-top="114">
<div class="header"> <div class="header">
<avue-title :value="process.processDefinitionName"></avue-title> <avue-title :value="process.processDefinitionName"></avue-title>
<div v-if="process.status != 'todo'">
主题<avue-select v-model="theme"
size="mini"
:clearable="false"
:dic="themeList"></avue-select>
</div>
</div> </div>
</avue-affix> </avue-affix>
<el-tabs v-model="activeName"> <el-tabs v-model="activeName">
<el-tab-pane label="申请信息" <el-tab-pane label="申请信息"
name="first"> name="first">
<el-card shadow="never"> <el-card shadow="never">
<div ref="printBody"> <div ref="printBody"
:class="process.status != 'todo' ? `wf-theme-${theme}`: ''">
<avue-form v-if="option && ((option.column && option.column.length > 0) || (option.group && option.group.length > 0))" <avue-form v-if="option && ((option.column && option.column.length > 0) || (option.group && option.group.length > 0))"
v-model="form" v-model="form"
ref="form" ref="form"
@ -54,17 +61,15 @@
</avue-skeleton> </avue-skeleton>
<!-- 底部按钮 --> <!-- 底部按钮 -->
<template v-if="process.status == 'todo'"> <wf-button :loading="submitLoading"
<wf-button :loading="submitLoading" :button-list="buttonList"
:button-list="buttonList" :process="process"
:process="process" :comment="comment"
:comment="comment" @examine="handleExamine"
@examine="handleExamine" @user-select="handleUserSelect"
@user-select="handleUserSelect" @print="handlePrint"
@print="handlePrint" @rollback="handleRollbackTask"
@rollback="handleRollbackTask" @terminate="handleTerminateProcess"></wf-button>
@terminate="handleTerminateProcess"></wf-button>
</template>
<!-- 人员选择弹窗 --> <!-- 人员选择弹窗 -->
<user-select ref="user-select" <user-select ref="user-select"
:check-type="checkType" :check-type="checkType"
@ -80,9 +85,10 @@ import WfFlow from './flow.vue'
import userSelect from './user-select' import userSelect from './user-select'
import exForm from '../../mixins/ex-form' import exForm from '../../mixins/ex-form'
import theme from '../../mixins/theme'
export default { export default {
mixins: [exForm], mixins: [exForm, theme],
components: { userSelect, WfExamineForm, WfButton, WfFlow }, components: { userSelect, WfExamineForm, WfButton, WfFlow },
watch: { watch: {
'$route.params.params': { '$route.params.params': {
@ -119,11 +125,20 @@ export default {
option.menuBtn = false option.menuBtn = false
const { column, group } = option const { column, group } = option
if (status != 'todo') { // if (status != 'todo') { //
let event = ['change', 'blur', 'click', 'focus']
option.detail = true option.detail = true
if (column && column.length > 0) { // column if (column && column.length > 0) { // column
column.forEach(col => { column.forEach(col => {
if (col.type == 'dynamic') col.children.column.forEach(cc => delete cc.value) if (col.type == 'dynamic') col.children.column.forEach(cc => {
else delete col.value delete cc.value
delete cc.event
event.forEach(e => delete cc[e])
})
else {
delete col.value
delete col.event
event.forEach(e => delete col[e])
}
}) })
} }
@ -131,8 +146,16 @@ export default {
group.forEach(gro => { group.forEach(gro => {
if (gro.column && gro.column.length > 0) { if (gro.column && gro.column.length > 0) {
gro.column.forEach(col => { gro.column.forEach(col => {
if (col.type == 'dynamic') col.children.column.forEach(cc => delete cc.value) if (col.type == 'dynamic') col.children.column.forEach(cc => {
else delete col.value delete cc.value
delete cc.event
event.forEach(e => delete cc[e])
})
else {
delete col.value
delete col.event
event.forEach(e => delete col[e])
}
}) })
} }
}) })

@ -113,8 +113,6 @@ export default {
option.group = groupArr option.group = groupArr
this.option = option this.option = option
this.tag.label = '发起流程 - ' + process.name
if (this.permission.wf_process_draft) { if (this.permission.wf_process_draft) {
// 稿 // 稿
this.initDraft(process.id).then(data => { this.initDraft(process.id).then(data => {

@ -29,9 +29,11 @@
<el-dialog :visible.sync="bpmnVisible" <el-dialog :visible.sync="bpmnVisible"
append-to-body append-to-body
destroy-on-close destroy-on-close
title="流程图"> title="流程图"
width="70%"
custom-class="wf-dialog">
<wf-design ref="bpmn" <wf-design ref="bpmn"
style="height: 500px;" style="height: 60vh;"
:options="bpmnOption"></wf-design> :options="bpmnOption"></wf-design>
</el-dialog> </el-dialog>
</basic-container> </basic-container>

@ -31,11 +31,12 @@
<el-dialog :visible.sync="bpmnVisible" <el-dialog :visible.sync="bpmnVisible"
append-to-body append-to-body
destroy-on-close destroy-on-close
title="流程图"> title="流程图"
width="70%"
custom-class="wf-dialog">
<wf-design ref="bpmn" <wf-design ref="bpmn"
style="height: 500px;" style="height: 60vh;"
access-key="OFdH37<Bs9[8A74vp)5B59Fu3c1I7{N:" :options="bpmnOption"></wf-design>
:options="bpmnOption"></wf-design>
</el-dialog> </el-dialog>
</basic-container> </basic-container>
</template> </template>

@ -1,75 +1,80 @@
<template> <template>
<basic-container> <basic-container>
<avue-affix id="avue-view" <avue-skeleton :loading="waiting"
:offset-top="116"> avatar
<div class="header"> :rows="8">
<avue-title :value="process.processDefinitionName"></avue-title> <avue-affix id="avue-view"
</div> :offset-top="114">
</avue-affix> <div class="header">
<el-tabs v-model="activeName"> <avue-title :value="process.processDefinitionName"></avue-title>
<el-tab-pane label="申请信息" <div v-if="process.status != 'todo'">
name="first"> 主题<avue-select v-model="theme"
<el-card shadow="never"> size="mini"
<div ref="printBody"> :clearable="false"
<avue-form v-if="showForm" :dic="themeList"></avue-select>
v-model="form"
ref="form"
:option="option">
</avue-form>
</div> </div>
</el-card> </div>
<el-card shadow="never" </avue-affix>
style="margin-top: 20px" <el-tabs v-model="activeName">
v-if="process.status == 'todo'"> <el-tab-pane label="申请信息"
<wf-examine-form ref="examineForm" name="first">
:comment.sync="comment" <el-card shadow="never">
@user-select="handleUserSelect"></wf-examine-form> <div ref="printBody"
</el-card> :class="process.status != 'todo' ? `wf-theme-${theme}`: ''">
</el-tab-pane> <avue-form v-if="option && ((option.column && option.column.length > 0) || (option.group && option.group.length > 0))"
<el-tab-pane label="流转信息" v-model="form"
name="second"> ref="form"
<el-card shadow="never" :defaults.sync="defaults"
style="margin-top: 5px;"> :option="option"
<wf-flow :flow="flow"></wf-flow> :upload-preview="handleUploadPreview">
</el-card> </avue-form>
</el-tab-pane> </div>
<el-tab-pane label="流程跟踪" </el-card>
name="third"> <el-card shadow="never"
<template v-if="activeName == 'third'"> style="margin-top: 20px"
v-if="process.status == 'todo'">
<wf-examine-form ref="examineForm"
:comment.sync="comment"
:process="process"
@user-select="handleUserSelect"></wf-examine-form>
</el-card>
</el-tab-pane>
<el-tab-pane label="流转信息"
name="second">
<el-card shadow="never" <el-card shadow="never"
style="margin-top: 5px;"> style="margin-top: 5px;">
<wf-design ref="bpmn" <wf-flow :flow="flow"></wf-flow>
style="height: 500px;"
:options="bpmnOption"></wf-design>
</el-card> </el-card>
</template> </el-tab-pane>
</el-tab-pane> <el-tab-pane label="流程跟踪"
</el-tabs> name="third">
<template v-if="activeName == 'third'">
<el-card shadow="never"
style="margin-top: 5px;">
<wf-design ref="bpmn"
style="height: 500px;"
:options="bpmnOption"></wf-design>
</el-card>
</template>
</el-tab-pane>
</el-tabs>
</avue-skeleton>
<!-- 底部按钮 --> <!-- 底部按钮 -->
<template v-if="process.status == 'todo'"> <wf-button :loading="submitLoading"
<wf-button :loading="submitLoading" :button-list="buttonList"
:button-list="buttonList" :process="process"
:process="process" :comment="comment"
:comment="comment" @examine="handleExamine"
@examine="handleExamine" @user-select="handleUserSelect"
@user-select="handleUserSelect" @print="handlePrint"
@print="handlePrint" @rollback="handleRollbackTask"
@rollback="handleRollbackTask" @terminate="handleTerminateProcess"></wf-button>
@terminate="handleTerminateProcess"></wf-button>
</template>
<!-- 人员选择弹窗 --> <!-- 人员选择弹窗 -->
<user-select ref="user-select" <user-select ref="user-select"
:check-type="checkType" :check-type="checkType"
:default-checked="defaultChecked"
@onConfirm="handleUserSelectConfirm"></user-select> @onConfirm="handleUserSelectConfirm"></user-select>
<!-- 选择回退节点弹窗 -->
<el-dialog :visible.sync="nodeVisible"
append-to-body
title="选择回退节点">
<avue-form v-model="nodeForm"
:option="nodeOption"
@submit="handleNodeSubmit"></avue-form>
</el-dialog>
</basic-container> </basic-container>
</template> </template>
@ -80,9 +85,10 @@ import WfFlow from '@/views/plugin/workflow/process/components/flow.vue'
import userSelect from '@/views/plugin/workflow/process/components/user-select' import userSelect from '@/views/plugin/workflow/process/components/user-select'
import exForm from '@/views/plugin/workflow/mixins/ex-form' import exForm from '@/views/plugin/workflow/mixins/ex-form'
import theme from '@/views/plugin/workflow/mixins/theme'
export default { export default {
mixins: [exForm], mixins: [exForm, theme],
components: { userSelect, WfExamineForm, WfButton, WfFlow }, components: { userSelect, WfExamineForm, WfButton, WfFlow },
watch: { watch: {
'$route.query.p': { '$route.query.p': {
@ -99,7 +105,7 @@ export default {
data() { data() {
return { return {
activeName: 'first', activeName: 'first',
showForm: false, defaults: {},
form: {}, form: {},
option: { option: {
column: [{ column: [{
@ -138,11 +144,20 @@ export default {
option.menuBtn = false option.menuBtn = false
const { column, group } = option const { column, group } = option
if (status != 'todo') { // if (status != 'todo') { //
let event = ['change', 'blur', 'click', 'focus']
option.detail = true option.detail = true
if (column && column.length > 0) { // column if (column && column.length > 0) { // column
column.forEach(col => { column.forEach(col => {
if (col.type == 'dynamic') col.children.column.forEach(cc => delete cc.value) if (col.type == 'dynamic') col.children.column.forEach(cc => {
else delete col.value delete cc.value
delete cc.event
event.forEach(e => delete cc[e])
})
else {
delete col.value
delete col.event
event.forEach(e => delete col[e])
}
}) })
} }
@ -150,8 +165,16 @@ export default {
group.forEach(gro => { group.forEach(gro => {
if (gro.column && gro.column.length > 0) { if (gro.column && gro.column.length > 0) {
gro.column.forEach(col => { gro.column.forEach(col => {
if (col.type == 'dynamic') col.children.column.forEach(cc => delete cc.value) if (col.type == 'dynamic') col.children.column.forEach(cc => {
else delete col.value delete cc.value
delete cc.event
event.forEach(e => delete cc[e])
})
else {
delete col.value
delete col.event
event.forEach(e => delete col[e])
}
}) })
} }
}) })
@ -159,14 +182,14 @@ export default {
} else { } else {
const columnFilter = this.filterAvueColumn(column, taskForm) const columnFilter = this.filterAvueColumn(column, taskForm)
const columnArr = columnFilter.column const columnArr = columnFilter.column
let vars = columnFilter.vars let vars = columnFilter.vars || []
const groupArr = [] const groupArr = []
if (group && group.length > 0) { // group if (group && group.length > 0) { // group
group.forEach(gro => { group.forEach(gro => {
const groupFilter = this.filterAvueColumn(gro.column, taskForm) const groupFilter = this.filterAvueColumn(gro.column, taskForm)
gro.column = groupFilter.column gro.column = groupFilter.column
vars = vars.conact(groupFilter.vars) vars = vars.concat(groupFilter.vars)
if (gro.column.length > 0) groupArr.push(gro) if (gro.column.length > 0) groupArr.push(gro)
}) })
} }
@ -189,13 +212,13 @@ export default {
this.option = option this.option = option
this.form = variables this.form = variables
this.showForm = true this.waiting = false
}) })
}, },
// //
handleExamine(pass) { handleExamine(pass) {
this.submitLoading = true this.submitLoading = true
this.$refs.form.validate((valid) => { this.$refs.form.validate((valid, done) => {
if (valid) { if (valid) {
const variables = {} const variables = {}
this.vars.forEach(v => { this.vars.forEach(v => {
@ -206,9 +229,11 @@ export default {
this.$message.success("处理成功") this.$message.success("处理成功")
this.handleCloseTag('/plugin/workflow/process/todo') this.handleCloseTag('/plugin/workflow/process/todo')
}).catch(() => { }).catch(() => {
done()
this.submitLoading = false this.submitLoading = false
}) })
} else { } else {
done()
this.submitLoading = false this.submitLoading = false
} }
}) })

@ -1,24 +1,72 @@
<template> <template>
<basic-container> <basic-container>
<avue-title style="margin-bottom: 20px; " <avue-skeleton :loading="waiting"
:styles="{fontSize: '20px'}" avatar
:value="process.name"></avue-title> :rows="8">
<!-- 自定义表单区域 --> <avue-title style="margin-bottom: 20px; "
<avue-form v-if="option && ((option.column && option.column.length > 0) || (option.group && option.group.length > 0))" :styles="{fontSize: '20px'}"
v-model="form" :value="process.name"></avue-title>
ref="form" <el-card shadow="never"
:option="option" style="margin-top: 20px">
@submit="handleSubmit"> <!-- 自定义表单区域 -->
</avue-form> <avue-form v-if="option && ((option.column && option.column.length > 0) || (option.group && option.group.length > 0))"
<!-- 自定义表单区域 --> v-model="form"
ref="form"
:option="option"
:defaults.sync="defaults"
@submit="handleSubmit"
@error="loading = false"
:upload-preview="handleUploadPreview">
</avue-form>
<!-- 自定义表单区域 -->
</el-card>
<el-card shadow="never"
style="margin-top: 20px"
v-if="showExamForm">
<wf-examine-form ref="examineForm"
:process="process"
@user-select="handleUserSelect"></wf-examine-form>
</el-card>
<div style="height: 120px;"></div>
<el-row class="foot-item avue-affix"
:style="{width: isCollapse? 'calc(100% - 80px)': 'calc(100% - 260px)' }"
id="avue-view">
<el-button type="primary"
size="medium"
v-loading="loading"
@click="() => {
loading = true;
$refs.form.submit()
}">发起</el-button>
<el-button v-if="permission.wf_process_draft"
type="success"
size="medium"
v-loading="loading"
@click="handleDraft(process.id, process.formKey, form)">存为草稿</el-button>
</el-row>
</avue-skeleton>
<!-- 人员选择弹窗 -->
<wf-user-select ref="user-select"
:check-type="checkType"
:default-checked="defaultChecked"
@onConfirm="handleUserSelectConfirm"></wf-user-select>
</basic-container> </basic-container>
</template> </template>
<script> <script>
import WfExamineForm from '@/views/plugin/workflow/process/components/examForm.vue'
import WfUserSelect from '@/views/plugin/workflow/process/components/user-select'
import exForm from '@/views/plugin/workflow/mixins/ex-form' import exForm from '@/views/plugin/workflow/mixins/ex-form'
import draft from '@/views/plugin/workflow/mixins/draft'
export default { export default {
mixins: [exForm], components: {
WfUserSelect, WfExamineForm
},
mixins: [exForm, draft],
watch: { watch: {
'$route.query.p': { '$route.query.p': {
handler(val) { handler(val) {
@ -31,10 +79,18 @@ export default {
immediate: true immediate: true
} }
}, },
computed: {
showExamForm() {
const { hideComment, hideCopy, hideExamine } = this.process
return !hideComment || !hideCopy || !hideExamine
}
},
data() { data() {
return { return {
defaults: {},
form: {}, form: {},
option: { option: {
menuBtn: false,
column: [{ column: [{
label: '请假时间', label: '请假时间',
prop: 'datetime', prop: 'datetime',
@ -55,33 +111,42 @@ export default {
rules: [{ required: true, message: '请输入请假理由' }] rules: [{ required: true, message: '请输入请假理由' }]
}] }]
}, },
process: {} process: {},
loading: false
} }
}, },
methods: { methods: {
getForm(processId) { getForm(processId) {
this.getStartForm(processId).then(res => { this.getStartForm(processId).then(res => {
let { process, startForm } = res let { process, startForm } = res
this.process = process
this.form.processId = process.id this.form.processId = process.id
const option = this.option
const { column, group } = option
if (startForm && startForm.length > 0) { const groupArr = []
const option = this.option const columnArr = this.filterAvueColumn(column, startForm).column
const { column, group } = option if (group && group.length > 0) { // group
group.forEach(gro => {
gro.column = this.filterAvueColumn(gro.column, startForm).column
if (gro.column.length > 0) groupArr.push(gro)
})
}
const groupArr = [] option.column = columnArr
const columnArr = this.filterAvueColumn(column, startForm).column option.group = groupArr
if (group && group.length > 0) { // group this.option = option
group.forEach(gro => {
gro.column = this.filterAvueColumn(gro.column, startForm).column
if (gro.column.length > 0) groupArr.push(gro)
})
}
option.column = columnArr if (this.permission.wf_process_draft) {
option.group = groupArr // 稿
this.option = option this.initDraft(process.id).then(data => {
this.$confirm('是否恢复之前保存的草稿?', '提示', {
}).then(() => {
this.form = JSON.parse(data)
}).catch(() => {
})
})
} }
this.waiting = false
}) })
}, },
handleSubmit(form, done) { handleSubmit(form, done) {
@ -89,11 +154,30 @@ export default {
this.$message.success("发起成功") this.$message.success("发起成功")
done() done()
this.handleCloseTag('/plugin/workflow/process/send') this.handleCloseTag('/plugin/workflow/process/send')
}).catch(() => {
this.loading = false
done()
}) })
}, },
} }
} }
</script> </script>
<style> <style lang="scss" scoped>
.foot-item {
position: fixed;
bottom: 0;
margin-left: -20px;
// right: 0;
z-index: 101;
height: 66px;
background-color: #fff;
display: flex;
justify-content: center;
align-items: center;
-webkit-transition: 0.3s;
transition: 0.3s;
-webkit-box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}
</style> </style>

@ -1,67 +1,78 @@
<template> <template>
<basic-container> <basic-container>
<avue-affix id="avue-view" <avue-skeleton :loading="waiting"
:offset-top="116"> avatar
<div class="header"> :rows="8">
<avue-title :value="process.processDefinitionName"></avue-title> <avue-affix id="avue-view"
</div> :offset-top="114">
</avue-affix> <div class="header">
<el-tabs v-model="activeName"> <avue-title :value="process.processDefinitionName"></avue-title>
<el-tab-pane label="申请信息" <div v-if="process.status != 'todo'">
name="first"> 主题<avue-select v-model="theme"
<el-card shadow="never"> size="mini"
<div ref="printBody"> :clearable="false"
<!-- 自定义表单区域 --> :dic="themeList"></avue-select>
<!-- 自定义表单区域 -->
</div> </div>
</el-card> </div>
<!-- 审批意见表单 --> </avue-affix>
<el-card shadow="never" <el-tabs v-model="activeName">
style="margin-top: 20px" <el-tab-pane label="申请信息"
v-if="process.status == 'todo'"> name="first">
<wf-examine-form ref="examineForm" <el-card shadow="never">
:comment.sync="comment" <div ref="printBody"
@user-select="handleUserSelect"></wf-examine-form> :class="process.status != 'todo' ? `wf-theme-${theme}`: ''">
</el-card> <!-- 自定义表单区域 -->
</el-tab-pane>
<!-- 流转信息 --> <!-- 自定义表单区域 -->
<el-tab-pane label="流转信息" </div>
name="second"> </el-card>
<el-card shadow="never" <!-- 审批意见表单 -->
style="margin-top: 5px;"> <el-card shadow="never"
<wf-flow :flow="flow"></wf-flow> style="margin-top: 20px"
</el-card> v-if="process.status == 'todo'">
</el-tab-pane> <wf-examine-form ref="examineForm"
<!-- 流程图 --> :comment.sync="comment"
<el-tab-pane label="流程跟踪" :process="process"
name="third"> @user-select="handleUserSelect"></wf-examine-form>
<template v-if="activeName == 'third'"> </el-card>
</el-tab-pane>
<!-- 流转信息 -->
<el-tab-pane label="流转信息"
name="second">
<el-card shadow="never" <el-card shadow="never"
style="margin-top: 5px;"> style="margin-top: 5px;">
<wf-design ref="bpmn" <wf-flow :flow="flow"></wf-flow>
style="height: 500px;"
:options="bpmnOption"></wf-design>
</el-card> </el-card>
</template> </el-tab-pane>
</el-tab-pane> <!-- 流程图 -->
</el-tabs> <el-tab-pane label="流程跟踪"
name="third">
<template v-if="activeName == 'third'">
<el-card shadow="never"
style="margin-top: 5px;">
<wf-design ref="bpmn"
style="height: 500px;"
:options="bpmnOption"></wf-design>
</el-card>
</template>
</el-tab-pane>
</el-tabs>
</avue-skeleton>
<!-- 底部按钮 --> <!-- 底部按钮 -->
<template v-if="process.status == 'todo'"> <wf-button :loading="submitLoading"
<wf-button :loading="submitLoading" :button-list="buttonList"
:button-list="buttonList" :process="process"
:process="process" :comment="comment"
:comment="comment" @examine="handleExamine"
@examine="handleExamine" @user-select="handleUserSelect"
@user-select="handleUserSelect" @print="handlePrint"
@print="handlePrint" @rollback="handleRollbackTask"
@rollback="handleRollbackTask" @terminate="handleTerminateProcess"></wf-button>
@terminate="handleTerminateProcess"></wf-button>
</template>
<!-- 人员选择弹窗 --> <!-- 人员选择弹窗 -->
<user-select ref="user-select" <user-select ref="user-select"
:check-type="checkType" :check-type="checkType"
:default-checked="defaultChecked"
@onConfirm="handleUserSelectConfirm"></user-select> @onConfirm="handleUserSelectConfirm"></user-select>
</basic-container> </basic-container>
</template> </template>
@ -73,9 +84,10 @@ import WfFlow from '@/views/plugin/workflow/process/components/flow.vue'
import userSelect from '@/views/plugin/workflow/process/components/user-select' import userSelect from '@/views/plugin/workflow/process/components/user-select'
import exForm from '@/views/plugin/workflow/mixins/ex-form' import exForm from '@/views/plugin/workflow/mixins/ex-form'
import theme from '@/views/plugin/workflow/mixins/theme'
export default { export default {
mixins: [exForm], mixins: [exForm, theme],
components: { userSelect, WfExamineForm, WfButton, WfFlow }, components: { userSelect, WfExamineForm, WfButton, WfFlow },
watch: { watch: {
'$route.query.p': { '$route.query.p': {
@ -92,6 +104,7 @@ export default {
data() { data() {
return { return {
activeName: 'first', activeName: 'first',
defaults: {},
form: {}, form: {},
option: {}, // option: {}, //
vars: [], // vars: [], //
@ -112,12 +125,14 @@ export default {
console.log("status", status) // todo done console.log("status", status) // todo done
// //
this.waiting = false //
}) })
}, },
// //
handleExamine(pass) { handleExamine(pass) {
this.submitLoading = true this.submitLoading = true
this.$refs.form.validate((valid) => { this.$refs.form.validate((valid, done) => {
if (valid) { if (valid) {
const variables = {} const variables = {}
this.vars.forEach(v => { this.vars.forEach(v => {
@ -128,9 +143,11 @@ export default {
this.$message.success("处理成功") this.$message.success("处理成功")
this.handleCloseTag('/plugin/workflow/process/todo') this.handleCloseTag('/plugin/workflow/process/todo')
}).catch(() => { }).catch(() => {
done()
this.submitLoading = false this.submitLoading = false
}) })
} else { } else {
done()
this.submitLoading = false this.submitLoading = false
} }
}) })

@ -1,20 +1,66 @@
<template> <template>
<basic-container> <basic-container>
<avue-title style="margin-bottom: 20px; " <avue-skeleton :loading="waiting"
:styles="{fontSize: '20px'}" avatar
:value="process.name"></avue-title> :rows="8">
<!-- 自定义表单区域 --> <avue-title style="margin-bottom: 20px; "
:styles="{fontSize: '20px'}"
:value="process.name"></avue-title>
<el-card shadow="never"
style="margin-top: 20px">
<!-- 自定义表单区域 -->
<!-- 自定义表单区域 -->
<!-- 自定义表单区域 -->
</el-card>
<el-card shadow="never"
style="margin-top: 20px"
v-if="showExamForm">
<wf-examine-form ref="examineForm"
:process="process"
@user-select="handleUserSelect"></wf-examine-form>
</el-card>
<div style="height: 120px;"></div>
<el-row class="foot-item avue-affix"
:style="{width: isCollapse? 'calc(100% - 80px)': 'calc(100% - 260px)' }"
id="avue-view">
<el-button type="primary"
size="medium"
v-loading="loading"
@click="() => {
loading = true;
$refs.form.submit()
}">发起</el-button>
<el-button v-if="permission.wf_process_draft"
type="success"
size="medium"
v-loading="loading"
@click="handleDraft(process.id, process.formKey, form)">存为草稿</el-button>
</el-row>
</avue-skeleton>
<!-- 人员选择弹窗 -->
<wf-user-select ref="user-select"
:check-type="checkType"
:default-checked="defaultChecked"
@onConfirm="handleUserSelectConfirm"></wf-user-select>
</basic-container> </basic-container>
</template> </template>
<script> <script>
import WfExamineForm from '@/views/plugin/workflow/process/components/examForm.vue'
import WfUserSelect from '@/views/plugin/workflow/process/components/user-select'
import exForm from '@/views/plugin/workflow/mixins/ex-form' import exForm from '@/views/plugin/workflow/mixins/ex-form'
import draft from '@/views/plugin/workflow/mixins/draft'
export default { export default {
mixins: [exForm], components: {
WfUserSelect, WfExamineForm
},
mixins: [exForm, draft],
watch: { watch: {
'$route.query.p': { '$route.query.p': {
handler(val) { handler(val) {
@ -27,11 +73,22 @@ export default {
immediate: true immediate: true
} }
}, },
computed: {
showExamForm() {
const { hideComment, hideCopy, hideExamine } = this.process
return !hideComment || !hideCopy || !hideExamine
}
},
data() { data() {
return { return {
defaults: {},
form: {}, form: {},
option: {}, option: {
process: {} menuBtn: false,
column: []
},
process: {},
loading: false
} }
}, },
methods: { methods: {
@ -41,6 +98,7 @@ export default {
console.log("process", process) console.log("process", process)
console.log("startForm", startForm) console.log("startForm", startForm)
// //
this.waiting = false
}) })
}, },
handleSubmit(form, done) { handleSubmit(form, done) {
@ -48,11 +106,30 @@ export default {
this.$message.success("发起成功") this.$message.success("发起成功")
done() done()
this.handleCloseTag('/plugin/workflow/process/send') this.handleCloseTag('/plugin/workflow/process/send')
}).catch(() => {
this.loading = false
done()
}) })
}, },
} }
} }
</script> </script>
<style> <style lang="scss" scoped>
.foot-item {
position: fixed;
bottom: 0;
margin-left: -20px;
// right: 0;
z-index: 101;
height: 66px;
background-color: #fff;
display: flex;
justify-content: center;
align-items: center;
-webkit-transition: 0.3s;
transition: 0.3s;
-webkit-box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}
</style> </style>

@ -28,11 +28,12 @@
<el-dialog :visible.sync="bpmnVisible" <el-dialog :visible.sync="bpmnVisible"
append-to-body append-to-body
destroy-on-close destroy-on-close
title="流程图"> title="流程图"
width="70%"
custom-class="wf-dialog">
<wf-design ref="bpmn" <wf-design ref="bpmn"
style="height: 500px;" style="height: 60vh;"
access-key="OFdH37<Bs9[8A74vp)5B59Fu3c1I7{N:" :options="bpmnOption"></wf-design>
:options="bpmnOption"></wf-design>
</el-dialog> </el-dialog>
</basic-container> </basic-container>
</template> </template>

@ -31,9 +31,11 @@
<el-dialog :visible.sync="bpmnVisible" <el-dialog :visible.sync="bpmnVisible"
append-to-body append-to-body
destroy-on-close destroy-on-close
title="流程图"> title="流程图"
width="70%"
custom-class="wf-dialog">
<wf-design ref="bpmn" <wf-design ref="bpmn"
style="height: 500px;" style="height: 60vh;"
:options="bpmnOption"></wf-design> :options="bpmnOption"></wf-design>
</el-dialog> </el-dialog>
</basic-container> </basic-container>

@ -31,9 +31,11 @@
<el-dialog :visible.sync="bpmnVisible" <el-dialog :visible.sync="bpmnVisible"
append-to-body append-to-body
destroy-on-close destroy-on-close
title="流程图"> title="流程图"
width="70%"
custom-class="wf-dialog">
<wf-design ref="bpmn" <wf-design ref="bpmn"
style="height: 500px;" style="height: 60vh;"
:options="bpmnOption"></wf-design> :options="bpmnOption"></wf-design>
</el-dialog> </el-dialog>
</basic-container> </basic-container>
@ -198,5 +200,20 @@ export default {
}; };
</script> </script>
<style> <style lang="scss">
.wf-dialog {
display: flex;
flex-direction: column;
margin: 0 !important;
position: absolute;
top: 40%;
left: 50%;
transform: translate(-50%, -40%);
max-height: calc(100% - 30px);
max-width: calc(100% - 30px);
.el-dialog__body {
flex: 1;
overflow: auto;
}
}
</style> </style>

@ -0,0 +1,41 @@
// form - border
.wf-theme-border {
.avue--detail {
.avue-form__group,
.avue-form__row {
border: 1px solid #333 !important;
}
.el-form-item > .el-form-item__content {
border-left: 2px solid #333 !important;
}
.el-table__row .el-form-item__content {
border-left: none !important;
}
.avue-form__row {
margin-bottom: 0px !important;
}
.el-form-item {
margin-bottom: 0px !important;
}
.el-form-item__label {
text-align: center !important;
}
.el-input.is-disabled .el-input__inner,
.el-range-editor.is-disabled,
.el-textarea.is-disabled .el-textarea__inner {
border: 1px solid transparent;
background: #fff;
background-color: #fff;
}
.el-input-number.is-disabled .el-input-number__decrease,
.el-input-number.is-disabled .el-input-number__increase {
display: none;
}
}
}

@ -0,0 +1,128 @@
.wf-theme-default {
.avue--detail {
.el-col {
margin-bottom: 0 !important;
}
.hover-row td {
background-color: #fff !important;
}
.avue-group__header {
padding-left: 10px;
}
.el-collapse-item__header {
margin-bottom: 0;
}
.el-input.is-disabled .el-input__inner,
.el-textarea.is-disabled .el-textarea__inner,
.el-range-editor.is-disabled,
.el-range-editor.is-disabled input {
color: #606266;
background-color: #fff;
padding-left: 0;
cursor: default;
}
.el-input-number__decrease,
.el-input-number__increase {
display: none;
}
.el-input-group__append,
.el-input-group__prepend {
background-color: transparent;
border: none;
}
.el-input__suffix {
display: none;
}
.el-input__inner,
.el-textarea__inner {
border: none;
&::-webkit-input-placeholder {
color: transparent !important;
}
&::-moz-placeholder {
color: transparent !important;
}
&::-moz-placeholder {
color: transparent !important;
}
&::-ms-input-placeholder {
color: transparent !important;
}
&::-ms-input-placeholder {
color: transparent !important;
}
}
.avue-checkbox__all {
display: none;
}
.el-checkbox__input.is-disabled.is-checked .el-checkbox__inner {
background-color: #409eff;
border-color: #409eff;
}
.el-checkbox__input.is-disabled.is-checked .el-checkbox__inner::after {
border-color: #fff;
}
.el-radio__input.is-disabled.is-checked .el-radio__inner {
background-color: #409eff;
border-color: #409eff;
}
.el-radio__input.is-disabled.is-checked .el-radio__inner::after {
background-color: #fff;
}
.el-checkbox__input.is-disabled + span.el-checkbox__label,
.el-radio__input.is-disabled + span.el-radio__label {
color: #606266;
}
.el-form-item.is-required:not(.is-no-asterisk)
.el-form-item__label-wrap
> .el-form-item__label:before,
.el-form-item.is-required:not(.is-no-asterisk)
> .el-form-item__label:before {
display: none;
}
.el-row {
border-top: 1px solid #ebeef5;
border-left: 1px solid #ebeef5;
}
.el-col {
padding: 0 !important;
border-bottom: 1px solid #ebeef5;
border-right: 1px solid #ebeef5;
}
.el-form-item {
margin: 0;
background: #fafafa;
}
.el-form-item__label,
.el-form-item__content {
padding: 2px 0;
}
.el-form-item__label {
padding: 0 10px;
color: #909399;
box-sizing: border-box;
}
.el-tag {
margin-left: 0 !important;
margin-right: 6px !important;
}
.el-form-item__content {
border-left: 1px solid #ebeef5;
padding-left: 20px;
box-sizing: border-box;
background-color: #fff;
}
&__column {
.el-form-item {
background-color: #fff;
}
.el-form-item__label {
padding-right: 12px;
}
.el-form-item__content {
padding-left: 0;
border-left: none;
}
}
}
}
Loading…
Cancel
Save