Browse Source

feat: 部分bpm页面

xingyu 2 years ago
parent
commit
607f6e4bb5

+ 7 - 7
yudao-ui-admin-vue3/src/api/bpm/model/index.ts

@@ -2,20 +2,20 @@ import { useAxios } from '@/hooks/web/useAxios'
 import { ModelVO } from './types'
 const request = useAxios()
 
-export const getModelPage = async (params) => {
+export const getModelPageApi = async (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 })
 }
 
-export const updateModel = async (data: ModelVO) => {
+export const updateModelApi = async (data: ModelVO) => {
   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 = {
     id: id,
     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 })
 }
 
-export const createModel = async (data: ModelVO) => {
+export const createModelApi = async (data: ModelVO) => {
   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 })
 }
 
-export const deployModel = async (id: number) => {
+export const deployModelApi = async (id: number) => {
   return await request.post({ url: '/bpm/model/deploy?id=' + id })
 }

+ 8 - 0
yudao-ui-admin-vue3/src/api/bpm/model/types.ts

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

+ 4 - 4
yudao-ui-admin-vue3/src/api/bpm/processInstance/index.ts

@@ -2,15 +2,15 @@ import { useAxios } from '@/hooks/web/useAxios'
 import { ProcessInstanceVO } from './types'
 const request = useAxios()
 
-export const getMyProcessInstancePage = async (params) => {
+export const getMyProcessInstancePageApi = async (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 })
 }
 
-export const cancelProcessInstance = async (id: number, reason: string) => {
+export const cancelProcessInstanceApi = async (id: number, reason: string) => {
   const data = {
     id: id,
     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 })
 }
 
-export const getProcessInstance = async (id: number) => {
+export const getProcessInstanceApi = async (id: number) => {
   return await request.get({ url: '/bpm/process-instance/get?id=' + id })
 }

+ 1 - 1
yudao-ui-admin-vue3/src/router/modules/remaining.ts

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

+ 213 - 4
yudao-ui-admin-vue3/src/views/bpm/model/index.vue

@@ -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>
-  <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>

+ 81 - 0
yudao-ui-admin-vue3/src/views/bpm/model/model.data.ts

@@ -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)

+ 118 - 4
yudao-ui-admin-vue3/src/views/bpm/processInstance/index.vue

@@ -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>
-  <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>

+ 84 - 0
yudao-ui-admin-vue3/src/views/bpm/processInstance/process.data.ts

@@ -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)