!90 【重构】Vue3 管理后台:[流程管理 -> 已办任务] 使用 Element Plus 原生实现
Merge pull request !90 from Chika/devpull/91/head
						commit
						68564b77e9
					
				| 
						 | 
				
			
			@ -1,5 +1,9 @@
 | 
			
		|||
import request from '@/config/axios'
 | 
			
		||||
 | 
			
		||||
export type TaskVO = {
 | 
			
		||||
  id: number
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const getTodoTaskPage = async (params) => {
 | 
			
		||||
  return await request.get({ url: '/bpm/task/todo-page', params })
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -32,3 +36,8 @@ export const getTaskListByProcessInstanceId = async (processInstanceId) => {
 | 
			
		|||
    url: '/bpm/task/list-by-process-instance-id?processInstanceId=' + processInstanceId
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 导出任务
 | 
			
		||||
export const exportTask = async (params) => {
 | 
			
		||||
  return await request.download({ url: '/bpm/task/export', params })
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -317,6 +317,18 @@ const remainingRouter: AppRouteRecordRaw[] = [
 | 
			
		|||
          title: '查看 OA 请假',
 | 
			
		||||
          activeMenu: 'bpm/oa/leave/detail'
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      {
 | 
			
		||||
        path: '/bpm/task/done',
 | 
			
		||||
        component: () => import('@/views/bpm/task/done/index.vue'),
 | 
			
		||||
        name: 'TaskDone',
 | 
			
		||||
        meta: {
 | 
			
		||||
          noCache: true,
 | 
			
		||||
          hidden: true,
 | 
			
		||||
          canTo: true,
 | 
			
		||||
          title: '已办任务',
 | 
			
		||||
          activeMenu: 'bpm/task/done/index'
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    ]
 | 
			
		||||
  },
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,47 @@
 | 
			
		|||
<template>
 | 
			
		||||
  <Dialog title="详情" v-model="dialogVisible" :scroll="true" :max-height="500" width="800">
 | 
			
		||||
    <el-descriptions border :column="1">
 | 
			
		||||
      <el-descriptions-item label="任务编号" min-width="120">
 | 
			
		||||
        {{ detailData.id }}
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="任务名称">
 | 
			
		||||
        {{ detailData.name }}
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="所属流程">
 | 
			
		||||
        {{ detailData.processInstance.name }}
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="流程发起人">
 | 
			
		||||
        {{ detailData.processInstance.startUserNickname }}
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="状态">
 | 
			
		||||
        {{ detailData.result }}
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="原因">
 | 
			
		||||
        {{ detailData.reason }}
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
      <el-descriptions-item label="创建时间">
 | 
			
		||||
        {{ formatDate(detailData.createTime) }}
 | 
			
		||||
      </el-descriptions-item>
 | 
			
		||||
    </el-descriptions>
 | 
			
		||||
  </Dialog>
 | 
			
		||||
</template>
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
import { formatDate } from '@/utils/formatTime'
 | 
			
		||||
import * as TaskApi from '@/api/bpm/task'
 | 
			
		||||
const dialogVisible = ref(false) // 弹窗的是否展示
 | 
			
		||||
const detailLoading = ref(false) // 表单的加载中
 | 
			
		||||
const detailData = ref() // 详情数据
 | 
			
		||||
 | 
			
		||||
/** 打开弹窗 */
 | 
			
		||||
const openModal = async (data: TaskApi.TaskVO) => {
 | 
			
		||||
  dialogVisible.value = true
 | 
			
		||||
  // 设置数据
 | 
			
		||||
  detailLoading.value = true
 | 
			
		||||
  try {
 | 
			
		||||
    detailData.value = data
 | 
			
		||||
  } finally {
 | 
			
		||||
    detailLoading.value = false
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
defineExpose({ openModal }) // 提供 openModal 方法,用于打开弹窗
 | 
			
		||||
</script>
 | 
			
		||||
| 
						 | 
				
			
			@ -1,52 +0,0 @@
 | 
			
		|||
import type { VxeCrudSchema } from '@/hooks/web/useVxeCrudSchemas'
 | 
			
		||||
 | 
			
		||||
const { t } = useI18n() // 国际化
 | 
			
		||||
 | 
			
		||||
// crudSchemas
 | 
			
		||||
const crudSchemas = reactive<VxeCrudSchema>({
 | 
			
		||||
  primaryKey: 'id',
 | 
			
		||||
  primaryType: null,
 | 
			
		||||
  action: true,
 | 
			
		||||
  columns: [
 | 
			
		||||
    {
 | 
			
		||||
      title: '任务编号',
 | 
			
		||||
      field: 'id',
 | 
			
		||||
      table: {
 | 
			
		||||
        width: 320
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '任务名称',
 | 
			
		||||
      field: 'name',
 | 
			
		||||
      isSearch: true
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '所属流程',
 | 
			
		||||
      field: 'processInstance.name'
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '流程发起人',
 | 
			
		||||
      field: 'processInstance.startUserNickname'
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: t('common.status'),
 | 
			
		||||
      field: 'result',
 | 
			
		||||
      dictType: DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT,
 | 
			
		||||
      dictClass: 'number',
 | 
			
		||||
      isSearch: true
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: '原因',
 | 
			
		||||
      field: 'reason'
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      title: t('common.createTime'),
 | 
			
		||||
      field: 'createTime',
 | 
			
		||||
      formatter: 'formatDate',
 | 
			
		||||
      table: {
 | 
			
		||||
        width: 180
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  ]
 | 
			
		||||
})
 | 
			
		||||
export const { allSchemas } = useVxeCrudSchemas(crudSchemas)
 | 
			
		||||
| 
						 | 
				
			
			@ -1,30 +1,147 @@
 | 
			
		|||
<template>
 | 
			
		||||
  <ContentWrap>
 | 
			
		||||
    <XTable @register="registerTable">
 | 
			
		||||
      <template #suspensionState_default="{ row }">
 | 
			
		||||
        <el-tag type="success" v-if="row.suspensionState === 1">激活</el-tag>
 | 
			
		||||
        <el-tag type="warning" v-if="row.suspensionState === 2">挂起</el-tag>
 | 
			
		||||
      </template>
 | 
			
		||||
      <template #actionbtns_default="{ row }">
 | 
			
		||||
        <!-- 操作: 审批进度 -->
 | 
			
		||||
        <XTextButton preIcon="ep:view" title="详情" @click="handleAudit(row)" />
 | 
			
		||||
      </template>
 | 
			
		||||
    </XTable>
 | 
			
		||||
    <!-- 搜索工作栏 -->
 | 
			
		||||
    <el-form
 | 
			
		||||
      class="-mb-15px"
 | 
			
		||||
      :model="queryParams"
 | 
			
		||||
      ref="queryFormRef"
 | 
			
		||||
      :inline="true"
 | 
			
		||||
      label-width="68px"
 | 
			
		||||
    >
 | 
			
		||||
      <el-form-item label="任务名称" prop="name">
 | 
			
		||||
        <el-input
 | 
			
		||||
          v-model="queryParams.name"
 | 
			
		||||
          placeholder="请输入任务名称"
 | 
			
		||||
          clearable
 | 
			
		||||
          @keyup.enter="handleQuery"
 | 
			
		||||
        />
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="状态" prop="status">
 | 
			
		||||
        <el-select v-model="queryParams.status" placeholder="请选择状态" clearable>
 | 
			
		||||
          <el-option
 | 
			
		||||
            v-for="dict in getIntDictOptions(DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT)"
 | 
			
		||||
            :key="dict.value"
 | 
			
		||||
            :label="dict.label"
 | 
			
		||||
            :value="dict.value"
 | 
			
		||||
          />
 | 
			
		||||
        </el-select>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item>
 | 
			
		||||
        <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
 | 
			
		||||
        <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
 | 
			
		||||
        <el-button
 | 
			
		||||
          type="success"
 | 
			
		||||
          plain
 | 
			
		||||
          @click="handleExport"
 | 
			
		||||
          :loading="exportLoading"
 | 
			
		||||
          v-hasPermi="['bpm:task:done:export']"
 | 
			
		||||
        >
 | 
			
		||||
          <Icon icon="ep:download" class="mr-5px" /> 导出
 | 
			
		||||
        </el-button>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
    </el-form>
 | 
			
		||||
  </ContentWrap>
 | 
			
		||||
  <!-- 列表 -->
 | 
			
		||||
  <ContentWrap>
 | 
			
		||||
    <el-table v-loading="loading" :data="list" align="center">
 | 
			
		||||
      <el-table-column label="任务编号" align="center" prop="id" width="300px" />
 | 
			
		||||
      <el-table-column label="任务名称" align="center" prop="name" />
 | 
			
		||||
      <el-table-column label="所属流程" align="center" prop="processInstance.name" />
 | 
			
		||||
      <el-table-column label="流程发起人" align="center" prop="processInstance.startUserNickname" />
 | 
			
		||||
      <el-table-column label="状态" align="center" prop="result">
 | 
			
		||||
        <template #default="scope">
 | 
			
		||||
          <dict-tag :type="DICT_TYPE.BPM_PROCESS_INSTANCE_RESULT" :value="scope.row.result" />
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
      <el-table-column label="原因" align="center" prop="reason" />
 | 
			
		||||
      <el-table-column
 | 
			
		||||
        label="创建时间"
 | 
			
		||||
        align="center"
 | 
			
		||||
        prop="createTime"
 | 
			
		||||
        width="180"
 | 
			
		||||
        :formatter="dateFormatter"
 | 
			
		||||
      />
 | 
			
		||||
      <el-table-column label="操作" align="center">
 | 
			
		||||
        <template #default="scope">
 | 
			
		||||
          <el-button link type="primary" @click="openModal(scope.row)"> 流程信息 </el-button>
 | 
			
		||||
          <el-button link type="primary" @click="handleAudit(scope.row)"> 流程详情 </el-button>
 | 
			
		||||
        </template>
 | 
			
		||||
      </el-table-column>
 | 
			
		||||
    </el-table>
 | 
			
		||||
    <!-- 分页 -->
 | 
			
		||||
    <Pagination
 | 
			
		||||
      :total="total"
 | 
			
		||||
      v-model:page="queryParams.pageNo"
 | 
			
		||||
      v-model:limit="queryParams.pageSize"
 | 
			
		||||
      @pagination="getList"
 | 
			
		||||
    />
 | 
			
		||||
  </ContentWrap>
 | 
			
		||||
  <!-- 表单弹窗:详情 -->
 | 
			
		||||
  <TaskDoneDetail ref="modalRef" @success="getList" />
 | 
			
		||||
</template>
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
// 业务相关的 import
 | 
			
		||||
import { allSchemas } from './done.data'
 | 
			
		||||
<script setup lang="tsx">
 | 
			
		||||
import { dateFormatter } from '@/utils/formatTime'
 | 
			
		||||
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
 | 
			
		||||
import * as TaskApi from '@/api/bpm/task'
 | 
			
		||||
import download from '@/utils/download'
 | 
			
		||||
import TaskDoneDetail from './Taskdetail.vue'
 | 
			
		||||
 | 
			
		||||
const { push } = useRouter() // 路由
 | 
			
		||||
 | 
			
		||||
const [registerTable] = useXTable({
 | 
			
		||||
  allSchemas: allSchemas,
 | 
			
		||||
  topActionSlots: false,
 | 
			
		||||
  getListApi: TaskApi.getDoneTaskPage
 | 
			
		||||
const loading = ref(true) // 列表的加载中
 | 
			
		||||
const total = ref(0) // 列表的总页数
 | 
			
		||||
const list = ref([]) // 列表的数据
 | 
			
		||||
const message = useMessage() // 消息弹窗
 | 
			
		||||
const exportLoading = ref(false) // 导出的加载中
 | 
			
		||||
const queryFormRef = ref() // 搜索的表单
 | 
			
		||||
const queryParams = reactive({
 | 
			
		||||
  pageNo: 1,
 | 
			
		||||
  pageSize: 10,
 | 
			
		||||
  name: '',
 | 
			
		||||
  status: undefined,
 | 
			
		||||
  createTime: []
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
/** 搜索按钮操作 */
 | 
			
		||||
const handleQuery = () => {
 | 
			
		||||
  queryParams.pageNo = 1
 | 
			
		||||
  getList()
 | 
			
		||||
}
 | 
			
		||||
/** 详情操作 */
 | 
			
		||||
const modalRef = ref()
 | 
			
		||||
const openModal = (data: TaskApi.TaskVO) => {
 | 
			
		||||
  modalRef.value.openModal(data)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** 重置按钮操作 */
 | 
			
		||||
const resetQuery = () => {
 | 
			
		||||
  queryFormRef.value.resetFields()
 | 
			
		||||
  handleQuery()
 | 
			
		||||
}
 | 
			
		||||
/** 查询任务列表 */
 | 
			
		||||
const getList = async () => {
 | 
			
		||||
  loading.value = true
 | 
			
		||||
  try {
 | 
			
		||||
    const data = await TaskApi.getDoneTaskPage(queryParams)
 | 
			
		||||
    list.value = data.list
 | 
			
		||||
    total.value = data.total
 | 
			
		||||
  } finally {
 | 
			
		||||
    loading.value = false
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
/** 导出按钮操作 */
 | 
			
		||||
const handleExport = async () => {
 | 
			
		||||
  try {
 | 
			
		||||
    // 导出的二次确认
 | 
			
		||||
    await message.exportConfirm()
 | 
			
		||||
    // 发起导出
 | 
			
		||||
    exportLoading.value = true
 | 
			
		||||
    const data = await TaskApi.exportTask(queryParams)
 | 
			
		||||
    download.excel(data, '任务列表.xls')
 | 
			
		||||
  } catch {
 | 
			
		||||
  } finally {
 | 
			
		||||
    exportLoading.value = false
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
const { push } = useRouter() // 路由
 | 
			
		||||
// 处理审批按钮
 | 
			
		||||
const handleAudit = (row) => {
 | 
			
		||||
  push({
 | 
			
		||||
| 
						 | 
				
			
			@ -34,4 +151,8 @@ const handleAudit = (row) => {
 | 
			
		|||
    }
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
/** 初始化 **/
 | 
			
		||||
onMounted(() => {
 | 
			
		||||
  getList()
 | 
			
		||||
})
 | 
			
		||||
</script>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue