🎉 1.1.0.RELEASE

saber
ssc 5 years ago
parent 9ee7dc2e8a
commit 0299e62c25
  1. 54
      public/cdn/wf-design/index.umd.min.js
  2. 1
      public/index.html
  3. 61
      src/api/plugin/workflow/condition.js
  4. 39
      src/api/plugin/workflow/process.js
  5. 2
      src/main.js
  6. 264
      src/views/plugin/workflow/design/condition.vue
  7. 13
      src/views/plugin/workflow/design/index.vue
  8. 2
      src/views/plugin/workflow/process/components/detail.vue
  9. 47
      src/views/plugin/workflow/process/components/flow.vue
  10. 361
      src/views/plugin/workflow/process/components/user-select.vue

File diff suppressed because one or more lines are too long

@ -104,6 +104,7 @@
<!-- built files will be auto injected -->
<script src="<%= BASE_URL %>util/aes.js" charset="utf-8"></script>
<script src="<%= BASE_URL %>cdn/vue/2.6.10/vue.min.js" charset="utf-8"></script>
<!-- <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script> -->
<script src="<%= BASE_URL %>cdn/vuex/3.1.1/vuex.min.js" charset="utf-8"></script>
<script src="<%= BASE_URL %>cdn/vue-router/3.0.1/vue-router.min.js" charset="utf-8"></script>
<script src="<%= BASE_URL %>cdn/axios/1.0.0/axios.min.js" charset="utf-8"></script>

@ -0,0 +1,61 @@
import request from '@/router/axios';
const prefix = '/api/blade-workflow/design/condition'
export const getList = (current, size, params) => {
return request({
url: `${prefix}/list`,
method: 'get',
params: {
...params,
current,
size,
}
})
}
export const listType = (params) => {
return request({
url: `${prefix}/listType`,
method: 'get',
params
})
}
export const getDetail = (id) => {
return request({
url: `${prefix}/detail`,
method: 'get',
params: {
id
}
})
}
export const remove = (ids) => {
return request({
url: `${prefix}/remove`,
method: 'post',
params: {
ids,
}
})
}
export const add = (row) => {
return request({
url: `${prefix}/submit`,
method: 'post',
data: row
})
}
export const update = (row) => {
return request({
url: `${prefix}/submit`,
method: 'post',
data: row
})
}

@ -222,7 +222,44 @@ export const terminateProcess = (data) => {
*/
export const userList = (current, size, params) => {
return request({
url: `/api/blade-user/user-search`,
url: `/api/blade-user/search/user`,
method: 'get',
params: {
...params,
current,
size,
}
})
}
/**
* 角色列表
*/
export const roleList = (params) => {
return request({
url: `/api/blade-system/search/role`,
method: 'get',
params
})
}
/**
* 部门列表
*/
export const deptList = (params) => {
return request({
url: `/api/blade-system/search/dept`,
method: 'get',
params
})
}
/**
* 岗位列表
*/
export const postList = (current, size, params) => {
return request({
url: `/api/blade-system/search/post`,
method: 'get',
params: {
...params,

@ -40,7 +40,7 @@ Vue.use(window.AVUE, {
Vue.component('basicContainer', basicContainer);
Vue.component('basicBlock', basicBlock);
Vue.component('thirdRegister', thirdRegister);
Vue.component('avueUeditor', avueUeditor);
Vue.use(avueUeditor);
// 加载相关url地址
Object.keys(urls).forEach(key => {
Vue.prototype[key] = urls[key];

@ -0,0 +1,264 @@
<template>
<basic-container>
<avue-crud :option="option"
:table-loading="loading"
:data="data"
:page.sync="page"
:permission="permissionList"
:before-open="beforeOpen"
v-model="form"
ref="crud"
@row-update="rowUpdate"
@row-save="rowSave"
@row-del="rowDel"
@search-change="searchChange"
@search-reset="searchReset"
@selection-change="selectionChange"
@current-change="currentChange"
@size-change="sizeChange"
@refresh-change="refreshChange"
@on-load="onLoad">
<template slot="menuLeft">
<el-button type="danger"
size="mini"
icon="el-icon-delete"
plain
v-if="permission.wf_condition_delete"
@click="handleDelete">
</el-button>
<el-tag type="warning"
effect="dark"
size="medium"><i class="el-icon-warning"></i> 此配置只做快捷选择用具体逻辑请自行实现具体实现方法请查看使用文档</el-tag>
</template>
</avue-crud>
</basic-container>
</template>
<script>
import { getList, getDetail, add, update, remove } from "@/api/plugin/workflow/condition";
import { mapGetters } from "vuex";
export default {
data() {
return {
form: {},
query: {},
loading: true,
page: {
pageSize: 10,
currentPage: 1,
total: 0
},
selectionList: [],
option: {
dialogType: 'drawer',
size: 'mini',
align: 'center',
height: 'auto',
calcHeight: 30,
tip: false,
searchShow: true,
searchMenuSpan: 6,
searchSize: 'mini',
border: true,
index: true,
viewBtn: true,
selection: true,
dialogClickModal: false,
column: [
{
label: "名称",
prop: "name",
rules: [{
required: true,
message: "请输入名称",
trigger: "blur"
}],
search: true
},
{
label: "表达式",
prop: "expression",
rules: [{
required: true,
message: "请输入表达式",
trigger: "blur"
}]
},
{
label: "类型",
prop: "type",
rules: [{
required: true,
message: "请选择类型",
trigger: "change"
}],
type: 'select',
dicData: [{
label: '人员配置',
value: 'user'
}, {
label: '流转条件',
value: 'flow'
}],
search: true
},
{
label: '状态',
prop: 'status',
type: 'select',
rules: [{
required: true,
message: "请选择状态",
trigger: "change"
}],
dicData: [{
label: '可用',
value: 1
}, {
label: '禁用',
value: 2
}],
search: true
}
]
},
data: []
};
},
computed: {
...mapGetters(["permission"]),
permissionList() {
return {
addBtn: this.vaildData(this.permission.wf_condition_add, false),
viewBtn: this.vaildData(this.permission.wf_condition_view, false),
delBtn: this.vaildData(this.permission.wf_condition_delete, false),
editBtn: this.vaildData(this.permission.wf_condition_edit, false)
};
},
ids() {
let ids = [];
this.selectionList.forEach(ele => {
ids.push(ele.id);
});
return ids.join(",");
}
},
methods: {
rowSave(row, done, loading) {
add(row).then(() => {
this.onLoad(this.page);
this.$message({
type: "success",
message: "操作成功!"
});
done();
}, error => {
loading();
window.console.log(error);
});
},
rowUpdate(row, index, done, loading) {
update(row).then(() => {
this.onLoad(this.page);
this.$message({
type: "success",
message: "操作成功!"
});
done();
}, error => {
loading();
console.log(error);
});
},
rowDel(row) {
this.$confirm("确定将选择数据删除?", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(() => {
return remove(row.id);
})
.then(() => {
this.onLoad(this.page);
this.$message({
type: "success",
message: "操作成功!"
});
});
},
handleDelete() {
if (this.selectionList.length === 0) {
this.$message.warning("请选择至少一条数据");
return;
}
this.$confirm("确定将选择数据删除?", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(() => {
return remove(this.ids);
})
.then(() => {
this.onLoad(this.page);
this.$message({
type: "success",
message: "操作成功!"
});
this.$refs.crud.toggleSelection();
});
},
beforeOpen(done, type) {
if (["edit", "view"].includes(type)) {
getDetail(this.form.id).then(res => {
this.form = res.data.data;
});
} else {
this.$set(this.form, 'status', 1)
}
done();
},
searchReset() {
this.query = {};
this.onLoad(this.page);
},
searchChange(params, done) {
this.query = params;
this.page.currentPage = 1;
this.onLoad(this.page, params);
done();
},
selectionChange(list) {
this.selectionList = list;
},
selectionClear() {
this.selectionList = [];
this.$refs.crud.toggleSelection();
},
currentChange(currentPage) {
this.page.currentPage = currentPage;
},
sizeChange(pageSize) {
this.page.pageSize = pageSize;
},
refreshChange() {
this.onLoad(this.page, this.query);
},
onLoad(page, params = {}) {
this.loading = true;
getList(page.currentPage, page.pageSize, Object.assign(params, this.query)).then(res => {
const data = res.data.data;
this.page.total = data.total;
this.data = data.records;
this.loading = false;
this.selectionClear();
});
}
}
};
</script>
<style>
</style>

@ -268,7 +268,8 @@ export default {
},
mounted() {
this.getButtonList()
this.getUserList()
// this.getUserList()
this.getUserListV2()
},
methods: {
handleNextStep() {
@ -391,6 +392,16 @@ export default {
this.$set(this.step2.option, 'user', userConfig)
})
},
getUserListV2() {
this.$set(this.step2.option, 'user', {
version: 'v2',
userUrl: '/api/blade-user/search/user',
roleUrl: '/api/blade-system/search/role',
deptUrl: '/api/blade-system/search/dept',
postUrl: '/api/blade-system/search/post',
customUrl: '/api/blade-workflow/design/condition/list'
})
},
handleFullScreen() {
fullscreenToggel()
this.$store.commit('SET_COLLAPSE')

@ -132,7 +132,7 @@ export default {
} else {
const columnFilter = this.filterAvueColumn(column, taskForm)
const columnArr = columnFilter.column
let vars = columnFilter.vars
let vars = columnFilter.vars || []
const groupArr = []
if (group && group.length > 0) { // group

@ -7,13 +7,34 @@
:timestamp="item.endTime || item.createTime"
placement="top">
<el-card shadow="never">
<p>{{item.assigneeName}} [{{item.createTime}}] 开始处理 [{{item.historyActivityName}}] 环节</p>
<p>{{item.assigneeName}} [{{item.createTime}}] 开始处理 [{{item.historyActivityType == 'endEvent'? '结束': (item.historyActivityName || '未命名')}}] 环节</p>
<p v-if="item.historyActivityDurationTime">任务历时 [{{item.historyActivityDurationTime}}]</p>
<p v-if="item.commentObj && item.commentObj.type == 'transferComment'">转办意见: [{{item.comment}}]</p>
<p v-if="item.commentObj && item.commentObj.type == 'delegateComment'">委托意见: [{{item.comment}}]</p>
<p v-if="item.commentObj && item.commentObj.type == 'rollbackComment'">驳回意见: [{{item.comment}}]</p>
<p v-if="item.commentObj && item.commentObj.type == 'terminateComment'">终止意见: [{{item.comment}}]</p>
<p v-if="item.commentObj && item.commentObj.type == 'comment'">审批意见: [{{item.comment}}]</p>
<template v-if="item.comments">
<p v-for="(comment, index) in item.comments"
:key="index">
<template v-if="index < 1">
<span v-if="comment.type == 'transferComment'">转办: [{{comment.fullMessage}}]</span>
<span v-if="comment.type == 'delegateComment'">委托: [{{comment.fullMessage}}]</span>
<span v-if="comment.type == 'rollbackComment'">驳回意见: [{{comment.fullMessage}}]</span>
<span v-if="comment.type == 'terminateComment'">终止意见: [{{comment.fullMessage}}]</span>
<span v-if="comment.type == 'comment'">审批意见: [{{comment.fullMessage}}]</span>
<span style="color: #1989fa; float: right;"
v-if="item.comments.length > 1"
@click="handleClick">{{toggleText}} <i :class="[isFlag ? 'el-icon-arrow-up' : 'el-icon-arrow-down']"></i> </span>
<p style="color: gray; font-size: 12px;"
v-if="comment.time">{{comment.time}}</p>
</template>
<template v-if="index > 0 && isFlag">
<span v-if="comment.type == 'transferComment'">转办: [{{comment.fullMessage}}]</span>
<span v-if="comment.type == 'delegateComment'">委托: [{{comment.fullMessage}}]</span>
<span v-if="comment.type == 'rollbackComment'">驳回意见: [{{comment.fullMessage}}]</span>
<span v-if="comment.type == 'terminateComment'">终止意见: [{{comment.fullMessage}}]</span>
<span v-if="comment.type == 'comment'">审批意见: [{{comment.fullMessage}}]</span>
<p style="color: gray; font-size: 12px;"
v-if="comment.time">{{comment.time}}</p>
</template>
</p>
</template>
<p v-if="item.endTime">结束时间: [{{item.endTime}}]</p>
</el-card>
</el-timeline-item>
@ -32,7 +53,19 @@ export default {
return []
}
}
}
},
data() {
return {
isFlag: false,
toggleText: '展开',
}
},
methods: {
handleClick() {
this.isFlag = !this.isFlag
this.toggleText = this.isFlag ? '收起' : '展开'
}
},
}
</script>

@ -1,152 +1,64 @@
<template>
<div class="select-user">
<el-dialog title="选择人员"
:visible.sync="visible"
width="900px"
top="5vh"
:before-close="handleClose"
append-to-body>
<template v-if="visible">
<!-- 搜索栏 -->
<el-row :gutter=8>
<el-col :xs="12"
:sm="6"
:md="6">
<el-input placeholder="请输入用户名"
v-model="query.realName"
clearable
size="mini"></el-input>
</el-col>
<el-col :xs="12"
:sm="6"
:md="6">
<el-input placeholder="请输入部门"
v-model="query.deptName"
clearable
size="mini"></el-input>
</el-col>
<el-col :xs="12"
:sm="6"
:md="6">
<el-input placeholder="请输入职位"
v-model="query.postName"
clearable
size="mini"></el-input>
</el-col>
<el-col :xs="24"
:sm="6"
:md="6">
<el-button type="primary"
icon="el-icon-search"
size="mini"
@click="onLoad">搜索</el-button>
<el-button icon="el-icon-delete"
size="mini"
@click="handleRefresh">清空</el-button>
</el-col>
</el-row>
<!-- table -->
<el-table ref="table"
style="width: 100%; margin-top: 40px"
size="mini"
tooltip-effect="dark"
class='avue-crud'
border
:data="userList"
@current-change="handleRadio"
@selection-change="handleCheckbox">
<template v-if="checkType == 'checkbox'">
<el-table-column type="selection"
width="55"
align="center">
</el-table-column>
</template>
<template v-else>
<el-table-column align="center"
width="55">
<template slot-scope="scope">
<el-radio v-model="tableRadio"
:label="scope.row.id">
<i></i>
</el-radio>
</template>
</el-table-column>
</template>
<el-table-column prop="avatar"
label="头像"
align="center"
width="60">
<template slot-scope="scope">
<el-avatar fit="cover"
:size="35"
:src="scope.row.avatar"></el-avatar>
</template>
</el-table-column>
<el-table-column prop="realName"
label="姓名"
align="center">
</el-table-column>
<el-table-column prop="deptName"
label="部门"
align="center">
</el-table-column>
<el-table-column prop="postName"
label="职位"
align="center">
</el-table-column>
</el-table>
<!-- 分页 -->
<div class="pagination">
<el-pagination background
layout="total, sizes, prev, pager, next, jumper"
@current-change="currentChange"
@size-change="sizeChange"
:current-page="page.currentPage"
:page-size="page.pageSize"
:total="page.total">
</el-pagination>
</div>
<span slot="footer"
class="dialog-footer">
<el-button @click="handleClose"
size="mini"> </el-button>
<el-button type="primary"
@click="handleConfirm"
size="mini"> </el-button>
</span>
<el-dialog ref="wf-dialog"
custom-class="wf-dialog"
:visible.sync="visible"
title="人员选择"
width="60%"
:before-close="handleClose"
append-to-body>
<avue-crud :option="crudOption"
:table-loading="loading"
:data="data"
:page.sync="page"
v-model="form"
ref="crud"
@search-change="searchChange"
@search-reset="searchReset"
@selection-change="selectionList=$event"
@current-change="page.currentPage=$event"
@size-change="page.pageSize=$event"
@row-click="rowClick"
@on-load="onLoad">
<template v-if="checkType == 'radio'"
#radio="{row}">
<el-radio v-model="form.radio"
:label="row.id"><i></i></el-radio>
</template>
</el-dialog>
</div>
</avue-crud>
<span slot="footer"
class="dialog-footer">
<el-button @click="handleClose"
size="mini"> </el-button>
<el-button type="primary"
@click="handleConfirm"
size="mini"> </el-button>
</span>
</el-dialog>
</template>
<script>
import { userList as getList } from "@/api/plugin/workflow/process";
export default {
name: 'userSelect',
props: {
checkType: {
type: String,
default: () => {
return 'checkbox'
},
},
return 'radio'
}
}
},
data() {
return {
visible: false,
page: {
currentPage: 1,
pageSize: 10,
total: 0
watch: {
checkType: {
handler(val) {
if (val == 'radio') {
this.$set(this.crudOption, 'selection', false)
this.findObject(this.crudOption.column, 'radio').hide = false
} else {
this.$set(this.crudOption, 'selection', true)
this.findObject(this.crudOption.column, 'radio').hide = true
}
},
query: {},
treeDeptId: '',
userList: [],
selectionList: [],
tableRadio: '',
immediate: true
}
},
computed: {
@ -165,88 +77,123 @@ export default {
return names.join(",");
}
},
created() {
this.onLoad()
data() {
return {
visible: false,
form: {},
query: {},
loading: false,
page: {
pageSize: 10,
currentPage: 1,
total: 0
},
selectionList: [],
data: [],
crudOption: {
size: 'mini',
searchSize: 'mini',
align: 'center',
menu: false,
addBtn: false,
header: false,
border: true,
tip: false,
reserveSelection: true,
highlightCurrentRow: true,
gutter: 5,
searchMenuSpan: 6,
selection: true,
column: [{
label: '',
prop: 'radio',
type: 'radio',
width: 55,
hide: true
}, {
label: '头像',
prop: 'avatar',
type: 'upload',
width: 90
}, {
label: '姓名',
prop: 'name',
overHidden: true,
search: true
}, {
label: '部门',
prop: 'deptName',
overHidden: true,
search: true
}, {
label: '职位',
prop: 'postName',
overHidden: true,
search: true
}]
}
}
},
methods: {
handleClose() { //
handleConfirm() {
if (this.selectionList.length === 0) {
this.$message.warning("请选择至少一条数据")
return
}
this.$emit('onConfirm', this.ids, this.names)
},
handleClose() {
if (this.checkType == 'checkbox') this.$refs.crud.toggleSelection()
this.$set(this, 'selectionList', [])
this.$set(this, 'tableRadio', '')
this.$set(this, 'form', { radio: '' })
this.visible = false
this.$emit('onClose')
},
handleConfirm() { //
if (this.checkType == 'checkbox') {
if (this.selectionList.length === 0) {
this.$message.warning("请选择至少一条数据");
return;
}
this.$emit('onConfirm', this.ids, this.names)
} else {
if (!this.tableRadio) {
this.$message.warning("请选择至少一条数据");
return;
}
this.$emit('onConfirm', this.tableRadio, this.tableRadioName)
}
},
handleRefresh() { //
searchReset() {
this.query = {}
this.page = {
currentPage: 1,
pageSize: 10,
}
this.onLoad();
},
currentChange(val) { //
this.page.currentPage = val;
this.onLoad()
},
sizeChange(val) { //
this.page.pageSize = val;
this.onLoad()
},
onLoad() { //
const params = {}
getList(this.page.currentPage, this.page.pageSize, Object.assign(params, this.query), this.treeDeptId).then(res => {
const data = res.data.data;
this.page.total = data.total;
this.userList = data.records;
this.selectionClear();
});
this.onLoad(this.page)
},
selectionClear() { //
this.selectionList = [];
// this.$refs.table.clearSelection();
searchChange(params, done) {
this.query = params
this.page.currentPage = 1
this.onLoad(this.page, params)
done()
},
handleCheckbox(val) { //
this.selectionList = val;
selectionClear() {
this.selectionList = []
this.$refs.crud.toggleSelection()
},
handleRadio(val) { //
this.tableRadio = val.id
this.tableRadioName = val.realName
rowClick(row) {
if (this.checkType == 'radio') {
this.selectionList = [row]
this.$set(this.form, 'radio', row.id)
} else this.$refs.crud.toggleSelection([row])
},
},
onLoad(page, params = {}) {
this.loading = true;
getList(page.currentPage, page.pageSize, Object.assign(params, this.query)).then(res => {
const data = res.data.data
this.page.total = data.total * 3
this.data = data.records
this.loading = false
})
}
}
}
</script>
<style lang="scss" scped>
.pagination {
padding: 30px 0;
<style lang="scss">
.wf-dialog {
display: flex;
justify-content: flex-end;
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 lang="scss">
// .select-user {
// position: relative;
// .el-dialog {
// position: absolute;
// top: 50%;
// left: 50%;
// margin: 0 !important;
// -webkit-transform: translate(-50%, -50%);
// transform: translate(-50%, -50%);
// }
// }
</style>
Loading…
Cancel
Save