feat: 部分bpm页面

This commit is contained in:
xingyu 2022-07-28 19:10:45 +08:00
parent e16f8abc3a
commit 607f6e4bb5
8 changed files with 516 additions and 20 deletions

View File

@ -2,20 +2,20 @@ import { useAxios } from '@/hooks/web/useAxios'
import { ModelVO } from './types' import { ModelVO } from './types'
const request = useAxios() const request = useAxios()
export const getModelPage = async (params) => { export const getModelPageApi = async (params) => {
return await request.get({ url: '/bpm/model/page', params }) return await request.get({ url: '/bpm/model/page', params })
} }
export const getModel = async (id: number) => { export const getModelApi = async (id: number) => {
return await request.get({ url: '/bpm/model/get?id=' + id }) return await request.get({ url: '/bpm/model/get?id=' + id })
} }
export const updateModel = async (data: ModelVO) => { export const updateModelApi = async (data: ModelVO) => {
return await request.put({ url: '/bpm/model/update', data: data }) return await request.put({ url: '/bpm/model/update', data: data })
} }
// 任务状态修改 // 任务状态修改
export const updateModelState = async (id: number, state: string) => { export const updateModelStateApi = async (id: number, state: number) => {
const data = { const data = {
id: id, id: id,
state: state state: state
@ -23,14 +23,14 @@ export const updateModelState = async (id: number, state: string) => {
return await request.put({ url: '/bpm/model/update-state', data: data }) return await request.put({ url: '/bpm/model/update-state', data: data })
} }
export const createModel = async (data: ModelVO) => { export const createModelApi = async (data: ModelVO) => {
return await request.post({ url: '/bpm/model/create', data: data }) return await request.post({ url: '/bpm/model/create', data: data })
} }
export const deleteModel = async (id: number) => { export const deleteModelApi = async (id: number) => {
return await request.delete({ url: '/bpm/model/delete?id=' + id }) return await request.delete({ url: '/bpm/model/delete?id=' + id })
} }
export const deployModel = async (id: number) => { export const deployModelApi = async (id: number) => {
return await request.post({ url: '/bpm/model/deploy?id=' + id }) return await request.post({ url: '/bpm/model/deploy?id=' + id })
} }

View File

@ -1,3 +1,10 @@
export type ProcessDefinitionVO = {
id: string
version: number
deploymentTIme: string
suspensionState: number
}
export type ModelVO = { export type ModelVO = {
id: number id: number
formName: string formName: string
@ -9,6 +16,7 @@ export type ModelVO = {
formId: number formId: number
formCustomCreatePath: string formCustomCreatePath: string
formCustomViewPath: string formCustomViewPath: string
processDefinition: ProcessDefinitionVO
status: number status: number
remark: string remark: string
createTime: string createTime: string

View File

@ -2,15 +2,15 @@ import { useAxios } from '@/hooks/web/useAxios'
import { ProcessInstanceVO } from './types' import { ProcessInstanceVO } from './types'
const request = useAxios() const request = useAxios()
export const getMyProcessInstancePage = async (params) => { export const getMyProcessInstancePageApi = async (params) => {
return await request.get({ url: '/bpm/process-instance/my-page', params }) return await request.get({ url: '/bpm/process-instance/my-page', params })
} }
export const createProcessInstance = async (data: ProcessInstanceVO) => { export const createProcessInstanceApi = async (data: ProcessInstanceVO) => {
return await request.post({ url: '/bpm/process-instance/create', data: data }) return await request.post({ url: '/bpm/process-instance/create', data: data })
} }
export const cancelProcessInstance = async (id: number, reason: string) => { export const cancelProcessInstanceApi = async (id: number, reason: string) => {
const data = { const data = {
id: id, id: id,
reason: reason reason: reason
@ -18,6 +18,6 @@ export const cancelProcessInstance = async (id: number, reason: string) => {
return await request.delete({ url: '/bpm/process-instance/cancel', data: data }) return await request.delete({ url: '/bpm/process-instance/cancel', data: data })
} }
export const getProcessInstance = async (id: number) => { export const getProcessInstanceApi = async (id: number) => {
return await request.get({ url: '/bpm/process-instance/get?id=' + id }) return await request.get({ url: '/bpm/process-instance/get?id=' + id })
} }

View File

@ -72,7 +72,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
children: [ children: [
{ {
path: 'edit', path: 'edit',
component: () => import('@/views/infra/codegen/components/EditTable.vue'), component: () => import('@/views/infra/codegen/EditTable.vue'),
name: 'EditTable', name: 'EditTable',
meta: { meta: {
noCache: true, noCache: true,

View File

@ -1,7 +1,216 @@
<script setup lang="ts"></script> <script setup lang="ts">
import { ref, unref } from 'vue'
import dayjs from 'dayjs'
import { ElTableColumn, ElTag, ElSwitch } from 'element-plus'
import { DICT_TYPE } from '@/utils/dict'
import { useTable } from '@/hooks/web/useTable'
import { useI18n } from '@/hooks/web/useI18n'
import { FormExpose } from '@/components/Form'
import type { ModelVO } from '@/api/bpm/model/types'
import { rules, allSchemas } from './model.data'
import * as ModelApi from '@/api/bpm/model'
import { useMessage } from '@/hooks/web/useMessage'
const message = useMessage()
const { t } = useI18n() //
// ========== ==========
const { register, tableObject, methods } = useTable<ModelVO>({
getListApi: ModelApi.getModelPageApi,
delListApi: ModelApi.deleteModelApi
})
const { getList, setSearchParams, delList } = methods
// ========== CRUD ==========
const actionLoading = ref(false) //
const actionType = ref('') //
const dialogVisible = ref(false) //
const dialogTitle = ref('edit') //
const formRef = ref<FormExpose>() // Ref
//
const setDialogTile = (type: string) => {
dialogTitle.value = t('action.' + type)
actionType.value = type
dialogVisible.value = true
}
//
const handleCreate = () => {
setDialogTile('create')
//
unref(formRef)?.getElFormRef()?.resetFields()
}
//
const handleUpdate = async (row: ModelVO) => {
setDialogTile('update')
//
const res = await ModelApi.getModelApi(row.id)
unref(formRef)?.setValues(res)
}
//
const submitForm = async () => {
actionLoading.value = true
//
try {
const data = unref(formRef)?.formModel as ModelVO
if (actionType.value === 'create') {
await ModelApi.createModelApi(data)
message.success(t('common.createSuccess'))
} else {
await ModelApi.updateModelApi(data)
message.success(t('common.updateSuccess'))
}
//
dialogVisible.value = false
await getList()
} finally {
actionLoading.value = false
}
}
/** 流程表单的详情按钮操作 */
const handleChangeState = async (row: ModelVO) => {
const state = row.processDefinition.suspensionState
const statusState = state === 1 ? '激活' : '挂起'
message
.confirm(
'是否确认' + statusState + '流程名字为"' + row.name + '"的数据项?',
t('common.reminder')
)
.then(async () => {
ModelApi.updateModelStateApi(row.id, state).then(() => {
message.success(t('common.updateSuccess'))
getList()
})
})
.catch(() => {})
}
// ========== ==========
const detailRef = ref() // Ref
//
const handleDetail = async (row: ModelVO) => {
//
detailRef.value = row
setDialogTile('detail')
}
// ========== ==========
getList()
</script>
<template> <template>
<div>index</div> <!-- 搜索工作区 -->
</template> <ContentWrap>
<Search :schema="allSchemas.searchSchema" @search="setSearchParams" @reset="setSearchParams" />
</ContentWrap>
<ContentWrap>
<!-- 操作工具栏 -->
<div class="mb-10px">
<el-button type="primary" v-hasPermi="['bpm:model:create']" @click="handleCreate">
<Icon icon="ep:zoom-in" class="mr-5px" /> {{ t('action.add') }}
</el-button>
</div>
<!-- 列表 -->
<Table
:columns="allSchemas.tableColumns"
:selection="false"
:data="tableObject.tableList"
:loading="tableObject.loading"
:pagination="{
total: tableObject.total
}"
v-model:pageSize="tableObject.pageSize"
v-model:currentPage="tableObject.currentPage"
@register="register"
>
<template #category="{ row }">
<DictTag :type="DICT_TYPE.BPM_MODEL_CATEGORY" :value="row.category" />
</template>
<template #formId="{ row }">
<span>{{ row.formName }}</span>
</template>
<template #processDefinition>
<el-table-column label="流程版本" prop="processDefinition.version">
<template #default="{ row }">
<el-tag v-if="row.processDefinition">
{{ 'v' + row.processDefinition.version }}
</el-tag>
<el-tag type="warning" v-else>未部署</el-tag>
</template>
</el-table-column>
<el-table-column label="激活状态" prop="processDefinition.suspensionState">
<template #default="{ row }">
<el-switch
v-if="row.processDefinition"
v-model="row.processDefinition.suspensionState"
:active-value="1"
:inactive-value="2"
@change="handleChangeState(row)"
/>
</template>
</el-table-column>
<el-table-column label="部署时间" prop="processDefinition.deploymentTime">
<template #default="{ row }">
<span>
{{ dayjs(row.processDefinition.deploymentTime).format('YYYY-MM-DD HH:mm:ss') }}
</span>
</template>
</el-table-column>
</template>
<template #createTime="{ row }">
<span>{{ dayjs(row.createTime).format('YYYY-MM-DD HH:mm:ss') }}</span>
</template>
<template #action="{ row }">
<el-button link type="primary" v-hasPermi="['bpm:model:update']" @click="handleUpdate(row)">
<Icon icon="ep:edit" class="mr-1px" /> {{ t('action.edit') }}
</el-button>
<el-button link type="primary" v-hasPermi="['bpm:model:update']" @click="handleDetail(row)">
<Icon icon="ep:view" class="mr-1px" /> {{ t('action.detail') }}
</el-button>
<el-button
link
type="primary"
v-hasPermi="['bpm:model:delete']"
@click="delList(row.id, false)"
>
<Icon icon="ep:delete" class="mr-1px" /> {{ t('action.del') }}
</el-button>
</template>
</Table>
</ContentWrap>
<style scoped></style> <Dialog v-model="dialogVisible" :title="dialogTitle">
<!-- 对话框(添加 / 修改) -->
<Form
v-if="['create', 'update'].includes(actionType)"
:schema="allSchemas.formSchema"
:rules="rules"
ref="formRef"
/>
<!-- 对话框(详情) -->
<Descriptions
v-if="actionType === 'detail'"
:schema="allSchemas.detailSchema"
:data="detailRef"
>
<template #createTime="{ row }">
<span>{{ dayjs(row.createTime).format('YYYY-MM-DD HH:mm:ss') }}</span>
</template>
</Descriptions>
<!-- 操作按钮 -->
<template #footer>
<el-button
v-if="['create', 'update'].includes(actionType)"
type="primary"
:loading="actionLoading"
@click="submitForm"
>
{{ t('action.save') }}
</el-button>
<el-button @click="dialogVisible = false">{{ t('dialog.close') }}</el-button>
</template>
</Dialog>
</template>

View File

@ -0,0 +1,81 @@
import { reactive } from 'vue'
import { useI18n } from '@/hooks/web/useI18n'
import { required } from '@/utils/formRules'
import { CrudSchema, useCrudSchemas } from '@/hooks/web/useCrudSchemas'
import { DICT_TYPE } from '@/utils/dict'
const { t } = useI18n() // 国际化
// 表单校验
export const rules = reactive({
name: [required]
})
// CrudSchema
const crudSchemas = reactive<CrudSchema[]>([
{
label: t('common.index'),
field: 'id',
type: 'index',
form: {
show: false
},
detail: {
show: false
}
},
{
label: '流程标识',
field: 'key',
search: {
show: true
}
},
{
label: '流程名称',
field: 'name',
search: {
show: true
}
},
{
label: '流程分类',
field: 'category',
dictType: DICT_TYPE.BPM_MODEL_CATEGORY,
search: {
show: true
}
},
{
label: '表单信息',
field: 'formId'
},
{
label: '最新部署的流程定义',
field: 'processDefinition',
form: {
show: false
},
detail: {
show: false
}
},
{
label: t('common.createTime'),
field: 'createTime',
form: {
show: false
}
},
{
label: t('table.action'),
field: 'action',
width: '240px',
form: {
show: false
},
detail: {
show: false
}
}
])
export const { allSchemas } = useCrudSchemas(crudSchemas)

View File

@ -1,7 +1,121 @@
<script setup lang="ts"></script> <script setup lang="ts">
import { ref } from 'vue'
import dayjs from 'dayjs'
import { DICT_TYPE } from '@/utils/dict'
import { useTable } from '@/hooks/web/useTable'
import { useI18n } from '@/hooks/web/useI18n'
import type { ProcessInstanceVO } from '@/api/bpm/processInstance/types'
import { allSchemas } from './process.data'
import * as ProcessInstanceApi from '@/api/bpm/processInstance'
import { ElMessage, ElMessageBox } from 'element-plus'
const { t } = useI18n() //
// ========== ==========
const { register, tableObject, methods } = useTable<ProcessInstanceVO>({
getListApi: ProcessInstanceApi.getMyProcessInstancePageApi
})
const { getList, setSearchParams } = methods
// ========== CRUD ==========
const dialogVisible = ref(false) //
//
const handleAdd = () => {
console.info('add')
}
//
const handleCancel = (row: ProcessInstanceVO) => {
ElMessageBox.prompt('请输入取消原因?', '取消流程', {
confirmButtonText: t('common.ok'),
cancelButtonText: t('common.cancel'),
type: 'warning',
inputPattern: /^[\s\S]*.*[^\s][\s\S]*$/, //
inputErrorMessage: '取消原因不能为空'
}).then(async ({ value }) => {
await ProcessInstanceApi.cancelProcessInstanceApi(row.id, value)
ElMessage.success('取消成功')
getList()
})
}
// ========== ==========
const detailRef = ref() // Ref
//
const handleDetail = async (row: ProcessInstanceVO) => {
//
detailRef.value = row
dialogVisible.value = true
}
// ========== ==========
getList()
</script>
<template> <template>
<div>index</div> <!-- 搜索工作区 -->
</template> <ContentWrap>
<Search :schema="allSchemas.searchSchema" @search="setSearchParams" @reset="setSearchParams" />
</ContentWrap>
<ContentWrap>
<!-- 操作工具栏 -->
<div class="mb-10px">
<el-button type="primary" v-hasPermi="['bpm:process-instance:query']" @click="handleAdd">
<Icon icon="ep:zoom-in" class="mr-5px" /> {{ t('action.add') }}
</el-button>
</div>
<!-- 列表 -->
<Table
:columns="allSchemas.tableColumns"
:selection="false"
:data="tableObject.tableList"
:loading="tableObject.loading"
:pagination="{
total: tableObject.total
}"
v-model:pageSize="tableObject.pageSize"
v-model:currentPage="tableObject.currentPage"
@register="register"
>
<template #status="{ row }">
<DictTag :type="DICT_TYPE.COMMON_STATUS" :value="row.status" />
</template>
<template #createTime="{ row }">
<span>{{ dayjs(row.createTime).format('YYYY-MM-DD HH:mm:ss') }}</span>
</template>
<template #action="{ row }">
<el-button
link
type="primary"
v-hasPermi="['bpm:process-instance:query']"
@click="handleDetail(row)"
>
<Icon icon="ep:view" class="mr-1px" /> {{ t('action.detail') }}
</el-button>
<el-button
link
type="primary"
v-hasPermi="['bpm:process-instance:cancel']"
@click="handleCancel(row)"
>
<Icon icon="ep:delete" class="mr-1px" /> {{ t('action.del') }}
</el-button>
</template>
</Table>
</ContentWrap>
<style scoped></style> <Dialog v-model="dialogVisible" :title="t('action.detail')">
<!-- 对话框(详情) -->
<Descriptions :schema="allSchemas.detailSchema" :data="detailRef">
<template #status="{ row }">
<DictTag :type="DICT_TYPE.COMMON_STATUS" :value="row.status" />
</template>
<template #createTime="{ row }">
<span>{{ dayjs(row.createTime).format('YYYY-MM-DD HH:mm:ss') }}</span>
</template>
</Descriptions>
<!-- 操作按钮 -->
<template #footer>
<el-button @click="dialogVisible = false">{{ t('dialog.close') }}</el-button>
</template>
</Dialog>
</template>

View File

@ -0,0 +1,84 @@
import { reactive } from 'vue'
import { useI18n } from '@/hooks/web/useI18n'
import { CrudSchema, useCrudSchemas } from '@/hooks/web/useCrudSchemas'
import { DICT_TYPE } from '@/utils/dict'
const { t } = useI18n() // 国际化
// CrudSchema
const crudSchemas = reactive<CrudSchema[]>([
{
label: t('common.index'),
field: 'id',
type: 'index',
form: {
show: false
},
detail: {
show: false
}
},
{
label: '流程名',
field: 'name',
search: {
show: true
}
},
{
label: '流程分类',
field: 'category',
dictType: DICT_TYPE.BPM_MODEL_CATEGORY,
search: {
show: true
}
},
{
label: '当前审批任务',
field: 'tasks'
},
{
label: t('common.status'),
field: 'status',
dictType: DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS,
search: {
show: true
}
},
{
label: '结果',
field: 'result',
dictType: DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT,
search: {
show: true
}
},
{
label: '提交时间',
field: 'createTime',
form: {
show: false
},
search: {
show: true
}
},
{
label: '结束时间',
field: 'endTime',
form: {
show: false
}
},
{
label: t('table.action'),
field: 'action',
width: '240px',
form: {
show: false
},
detail: {
show: false
}
}
])
export const { allSchemas } = useCrudSchemas(crudSchemas)