|
@@ -0,0 +1,508 @@
|
|
|
+<template>
|
|
|
+ <div class="mainOfficeCenter">
|
|
|
+ <div class="header">
|
|
|
+ <el-popover placement="bottom-start" title="" trigger="hover" width="auto">
|
|
|
+ <template #reference>
|
|
|
+ <el-button type="danger">新建流程</el-button>
|
|
|
+ </template>
|
|
|
+ <ul class="flowTemplateBox">
|
|
|
+ <li v-for="(item, index) in flowTemplateTree" :key="index">
|
|
|
+ <span class="title">{{ item['name'] }}</span>
|
|
|
+ <ul v-for="(cItem, cIndex) in item['children']" :key="cIndex">
|
|
|
+ <li
|
|
|
+ @click="addTProcessHandle(cItem)"
|
|
|
+ v-if="
|
|
|
+ [
|
|
|
+ '开票申请',
|
|
|
+ '分包申请',
|
|
|
+ '外包申请',
|
|
|
+ '合同签订',
|
|
|
+ '项目验收',
|
|
|
+ '项目结项',
|
|
|
+ '分包合同签订',
|
|
|
+ '外包合同签订'
|
|
|
+ ].indexOf(cItem['name']) === -1
|
|
|
+ "
|
|
|
+ >{{ cItem['name'] }}</li
|
|
|
+ >
|
|
|
+ </ul>
|
|
|
+ </li>
|
|
|
+ </ul>
|
|
|
+ </el-popover>
|
|
|
+ <ul class="tabs">
|
|
|
+ <li
|
|
|
+ v-for="item in tabList"
|
|
|
+ :key="item['key']"
|
|
|
+ :class="{ active: currentTab === item['key'] }"
|
|
|
+ @click="switchTabHandle(item)"
|
|
|
+ >
|
|
|
+ {{ item['name'] }}({{ item['value'] }})
|
|
|
+ </li>
|
|
|
+ </ul>
|
|
|
+ <div class="search">
|
|
|
+ <el-form :inline="true" :model="searchForm" class="demo-form-inline">
|
|
|
+ <el-form-item label="流程名称">
|
|
|
+ <el-tree-select
|
|
|
+ :data="flowTemplates"
|
|
|
+ :props="defaultProps"
|
|
|
+ :render-after-expand="false"
|
|
|
+ ref="treeRef"
|
|
|
+ style="width: 240px"
|
|
|
+ default-expand-all
|
|
|
+ show-checkbox
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="">
|
|
|
+ <el-input
|
|
|
+ type="text"
|
|
|
+ style="width: 280px"
|
|
|
+ v-model="sendData['searchVal']"
|
|
|
+ placeholder="业务编号/流程描述/流程名称"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item>
|
|
|
+ <el-button type="primary" @click="searchHandle">查询</el-button>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="table_box">
|
|
|
+ <div class="table" ref="tableRef">
|
|
|
+ <el-table
|
|
|
+ :data="tableData"
|
|
|
+ :style="{ width: '100%', height: tableHeight + 'px' }"
|
|
|
+ stripe
|
|
|
+ :header-cell-style="{
|
|
|
+ background: '#E5F0FB',
|
|
|
+ color: '#233755',
|
|
|
+ height: '50px'
|
|
|
+ }"
|
|
|
+ :cell-class-name="cellClassNameHandle"
|
|
|
+ @row-dblclick="(item) => openFlowHandle(item)"
|
|
|
+ >
|
|
|
+ <el-table-column
|
|
|
+ v-for="(item, index) in currentColumn"
|
|
|
+ :key="index"
|
|
|
+ :label="item['label']"
|
|
|
+ :prop="item['name']"
|
|
|
+ :width="item['width']"
|
|
|
+ :min-width="item['minWidth']"
|
|
|
+ :fixed="item['fixed']"
|
|
|
+ :formatter="item['formatter']"
|
|
|
+ >
|
|
|
+ <template v-if="item['name'] === 'statusVal'" #default="scope">
|
|
|
+ <span v-html="scope.row[item['name']]"></span>
|
|
|
+ </template>
|
|
|
+ <template v-else-if="item['name'] === 'action'" #default="scope">
|
|
|
+ <template v-if="currentTab === '1'">
|
|
|
+ <el-dropdown
|
|
|
+ split-button
|
|
|
+ type="primary"
|
|
|
+ @click="flowApplyHandle(scope.row)"
|
|
|
+ @command="
|
|
|
+ (name) => {
|
|
|
+ commandHandle(name, scope.row)
|
|
|
+ }
|
|
|
+ "
|
|
|
+ >
|
|
|
+ 办理
|
|
|
+ <template #dropdown>
|
|
|
+ <el-dropdown-menu>
|
|
|
+ <el-dropdown-item
|
|
|
+ v-for="(bItem, bIndex) in scope.row.btnArrJson"
|
|
|
+ :key="bIndex"
|
|
|
+ :disabled="!bItem['iEnable']"
|
|
|
+ :command="bItem['value']"
|
|
|
+ >{{ bItem['value'] }}</el-dropdown-item
|
|
|
+ >
|
|
|
+ </el-dropdown-menu>
|
|
|
+ </template>
|
|
|
+ </el-dropdown>
|
|
|
+ </template>
|
|
|
+ <template v-else-if="currentTab === '90'">
|
|
|
+ <el-button type="primary" icon="Search" @click="openFlowHandle(scope.row)">
|
|
|
+ 查看
|
|
|
+ </el-button>
|
|
|
+ <el-popconfirm title="是否确定追回?" @confirm="recoverActivityHandle(scope.row)">
|
|
|
+ <template #reference>
|
|
|
+ <el-button type="warning" icon="RefreshRight"> 追回 </el-button>
|
|
|
+ </template>
|
|
|
+ </el-popconfirm>
|
|
|
+ </template>
|
|
|
+ <template v-else-if="currentTab === '40'">
|
|
|
+ <el-button type="primary" icon="Search" @click="openFlowHandle(scope.row)">
|
|
|
+ 查看
|
|
|
+ </el-button>
|
|
|
+ </template>
|
|
|
+ <template v-else-if="currentTab === '20'">
|
|
|
+ <el-button type="primary" icon="Search" @click="openFlowHandle(scope.row)">
|
|
|
+ 查看
|
|
|
+ </el-button>
|
|
|
+ <el-popconfirm title="是否确定解挂?" @confirm="addIHangUpHandle(scope.row)">
|
|
|
+ <template #reference>
|
|
|
+ <el-button type="warning" icon="RefreshRight"> 解挂 </el-button>
|
|
|
+ </template>
|
|
|
+ </el-popconfirm>
|
|
|
+ </template>
|
|
|
+ <template v-else-if="currentTab === '160'">
|
|
|
+ <el-button type="primary" icon="Search" @click="openFlowHandle(scope.row, '160')">
|
|
|
+ 查看
|
|
|
+ </el-button>
|
|
|
+ <el-button
|
|
|
+ type="warning"
|
|
|
+ icon="RefreshRight"
|
|
|
+ @click="recoverINullyApplyHandle(scope.row)"
|
|
|
+ >
|
|
|
+ 恢复
|
|
|
+ </el-button>
|
|
|
+ <el-popconfirm
|
|
|
+ title="是否确定彻底作废?"
|
|
|
+ @confirm="completelyVoidINullyApplyHandle(scope.row)"
|
|
|
+ >
|
|
|
+ <template #reference>
|
|
|
+ <el-button type="warning" icon="RefreshRight"> 彻底作废 </el-button>
|
|
|
+ </template>
|
|
|
+ </el-popconfirm>
|
|
|
+ </template>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+ </div>
|
|
|
+ <div class="pageBox">
|
|
|
+ <el-pagination
|
|
|
+ v-model:current-page="sendData.page"
|
|
|
+ :page-size="sendData.rows"
|
|
|
+ background
|
|
|
+ layout="total, prev, pager, next, jumper"
|
|
|
+ :total="records"
|
|
|
+ @current-change="handleCurrentChange"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <!-- 作废表单Dialog -->
|
|
|
+ <el-dialog v-model="nullyApplyVisible" :title="nullyApplyTitle" width="40%">
|
|
|
+ <el-form v-model="inullyApplyForm" label-width="100px">
|
|
|
+ <el-row :gutter="20">
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="申请人:">
|
|
|
+ <el-input v-model="inullyApplyForm.nickname" disabled />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item label="申请时间:">
|
|
|
+ <el-input v-model="inullyApplyForm.nullyApplyTime" disabled />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ <el-row>
|
|
|
+ <el-col :span="24">
|
|
|
+ <el-form-item label="申请原因:">
|
|
|
+ <el-input
|
|
|
+ type="textarea"
|
|
|
+ rows="5"
|
|
|
+ style="width: 100%"
|
|
|
+ v-model="inullyApplyForm.nullyReason"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ </el-form>
|
|
|
+ <template #footer>
|
|
|
+ <div class="dialog-footer">
|
|
|
+ <el-button @click="nullyApplyVisible = false">关闭</el-button>
|
|
|
+ <el-button type="primary" @click="nullyApplySubmit">提交</el-button>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-dialog>
|
|
|
+ <!-- 退回表单Dialog -->
|
|
|
+ <el-dialog v-model="callbackVisible" title="退回" width="40%">
|
|
|
+ <el-form v-model="callbackForm" label-width="100px">
|
|
|
+ <div class="callback_header">
|
|
|
+ <span class="title">{{ callbackTitle }}</span>
|
|
|
+ <ul class="callback_process">
|
|
|
+ <li
|
|
|
+ v-for="(item, index) in callbacks"
|
|
|
+ :key="index"
|
|
|
+ :class="{ active: index === 0 }"
|
|
|
+ :icon="Edit"
|
|
|
+ >
|
|
|
+ <el-icon style="margin-right: 2px">
|
|
|
+ <DArrowRight />
|
|
|
+ </el-icon>
|
|
|
+ <span>{{ item['name'] }}</span>
|
|
|
+ </li>
|
|
|
+ </ul>
|
|
|
+ </div>
|
|
|
+ <div class="callback_header">
|
|
|
+ <span class="title">请填写退回原因</span>
|
|
|
+ <el-input
|
|
|
+ type="textarea"
|
|
|
+ rows="5"
|
|
|
+ style="width: 100%"
|
|
|
+ v-model="callbackForm.callbackRemark"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </el-form>
|
|
|
+ <template #footer>
|
|
|
+ <div class="dialog-footer">
|
|
|
+ <el-button @click="callbackVisible = false">关闭</el-button>
|
|
|
+ <el-button type="primary" @click="callbackSumbit">提交</el-button>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-dialog>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup lang="ts">
|
|
|
+import { Edit } from '@element-plus/icons-vue'
|
|
|
+import { defaultProps, handleTree } from '@/utils/tree'
|
|
|
+import {
|
|
|
+ getHandlerCaseCenterList,
|
|
|
+ getHandlerCaseCenterCount,
|
|
|
+ getFlowTemplateTreeDataByUser,
|
|
|
+ getFlowTemplateTree,
|
|
|
+ recoverActivity,
|
|
|
+ officeCenterModule,
|
|
|
+ addIHangUp
|
|
|
+} from '@/api/oa/workflow'
|
|
|
+import subscribe from '@/utils/Subscribe'
|
|
|
+import { TabColumns } from './common'
|
|
|
+import { InullyApplyEnum, InullyApplyEnumType } from './inullyApply'
|
|
|
+import useLookAndApplyFlow from './lookAndApplyFlow'
|
|
|
+import useInullyApply from './inullyApply'
|
|
|
+import useCallback from './callback'
|
|
|
+
|
|
|
+defineOptions({
|
|
|
+ name: 'MainOfficeCenter2'
|
|
|
+})
|
|
|
+const message = useMessage()
|
|
|
+const currentTab = ref<string>()
|
|
|
+const currentColumn = ref<any[]>()
|
|
|
+const tableData = ref<any[]>([])
|
|
|
+const records = ref<number>(0)
|
|
|
+const sendData = reactive({
|
|
|
+ _search: false,
|
|
|
+ status: 1,
|
|
|
+ flowTemIds: [],
|
|
|
+ searchVal: '',
|
|
|
+ isMobile: false,
|
|
|
+ queryMethod: 0,
|
|
|
+ toSystemId: '',
|
|
|
+ excludedSystemId: '',
|
|
|
+ page: 1,
|
|
|
+ rows: 18
|
|
|
+})
|
|
|
+const cellClassNameHandle = (item) => {
|
|
|
+ if (sendData['status'] !== 1) return 'rowClass'
|
|
|
+ if (!item.row['RECEIVE_TIME']) {
|
|
|
+ return 'fontWeight'
|
|
|
+ }
|
|
|
+ return 'rowClass'
|
|
|
+}
|
|
|
+/**
|
|
|
+ * 初始化流程列表
|
|
|
+ */
|
|
|
+const isLoading = ref<boolean>(false)
|
|
|
+const queryHandlerCaseCenterList = () => {
|
|
|
+ isLoading.value = true
|
|
|
+ getHandlerCaseCenterList(sendData).then((result: any) => {
|
|
|
+ if (result.rows && result.rows.length > 0) {
|
|
|
+ result.rows.forEach((item) => {
|
|
|
+ item['btnArrJson'] = item['btnArrJson'] ? JSON.parse(item['btnArrJson']) : []
|
|
|
+ })
|
|
|
+ }
|
|
|
+ isLoading.value = false
|
|
|
+ tableData.value = result.rows
|
|
|
+ records.value = result.records
|
|
|
+ })
|
|
|
+}
|
|
|
+queryHandlerCaseCenterList()
|
|
|
+const handleCurrentChange = (pageNo: number) => {
|
|
|
+ sendData['page'] = pageNo
|
|
|
+ queryHandlerCaseCenterList()
|
|
|
+}
|
|
|
+/**
|
|
|
+ * tab初始化和角标汇总统计
|
|
|
+ */
|
|
|
+const keyValMap = {
|
|
|
+ '1': 'NORMAL',
|
|
|
+ '90': 'FINISH',
|
|
|
+ '40': 'CALLBACK',
|
|
|
+ '20': 'HANG_UP',
|
|
|
+ '160': 'OBSOLETE'
|
|
|
+}
|
|
|
+type TabType = {
|
|
|
+ name: string
|
|
|
+ key: string
|
|
|
+ value: number
|
|
|
+}
|
|
|
+const tabList = ref<TabType[]>([])
|
|
|
+const queryOfficeCenterModule = async () => {
|
|
|
+ const result = await officeCenterModule()
|
|
|
+ const moduleList = result['moduleList']
|
|
|
+ if (moduleList && moduleList.length > 0) {
|
|
|
+ currentTab.value = moduleList[0]['status']
|
|
|
+ currentColumn.value = TabColumns[moduleList[0]['status']]
|
|
|
+ tabList.value = moduleList.map((item) => {
|
|
|
+ return {
|
|
|
+ name: item['name'],
|
|
|
+ key: item['status'],
|
|
|
+ value: 0
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+}
|
|
|
+const queryHandlerCaseCenterCount = async () => {
|
|
|
+ await queryOfficeCenterModule()
|
|
|
+ const formData = new FormData()
|
|
|
+ const keys = Object.keys(sendData)
|
|
|
+ for (let key of keys) {
|
|
|
+ formData.set(key, sendData[key])
|
|
|
+ }
|
|
|
+ getHandlerCaseCenterCount(formData).then((result) => {
|
|
|
+ tabList.value.forEach((item) => {
|
|
|
+ item['value'] = result[keyValMap[item['key']]]
|
|
|
+ })
|
|
|
+ })
|
|
|
+}
|
|
|
+queryHandlerCaseCenterCount()
|
|
|
+//切换tab流程状态选项卡
|
|
|
+const switchTabHandle = (item) => {
|
|
|
+ currentTab.value = item['key']
|
|
|
+ currentColumn.value = TabColumns[currentTab.value]
|
|
|
+ queryFlowTemplateTreeDataByUser(item['key'])
|
|
|
+ sendData['status'] = item['key']
|
|
|
+ sendData['page'] = 1
|
|
|
+ queryHandlerCaseCenterList()
|
|
|
+}
|
|
|
+
|
|
|
+const initHandleCaseCenterData = () => {
|
|
|
+ queryHandlerCaseCenterCount()
|
|
|
+ queryHandlerCaseCenterList()
|
|
|
+}
|
|
|
+
|
|
|
+subscribe.on('updateHandleCenterEvent', () => {
|
|
|
+ //同步更新办件中心角标
|
|
|
+ initHandleCaseCenterData()
|
|
|
+})
|
|
|
+/**
|
|
|
+ * 初始化新建流程中流程模板Tree
|
|
|
+ */
|
|
|
+const flowTemplateTree = ref<any>()
|
|
|
+const initFlowTemplateTree = () => {
|
|
|
+ getFlowTemplateTree().then((result) => {
|
|
|
+ flowTemplateTree.value = result.data[0]['children']
|
|
|
+ })
|
|
|
+}
|
|
|
+initFlowTemplateTree()
|
|
|
+
|
|
|
+/**
|
|
|
+ * 初始化搜索条件中流程名称Tree结构数据
|
|
|
+ */
|
|
|
+const flowTemplates = ref<any[]>([])
|
|
|
+const queryFlowTemplateTreeDataByUser = (officeStatus = '1') => {
|
|
|
+ const formData = new FormData()
|
|
|
+ formData.append('isRight', '0')
|
|
|
+ formData.append('toSystemId', '') //后台获取
|
|
|
+ formData.append('excludedSystemId', '') //后台获取
|
|
|
+ formData.append('officeStatus', officeStatus)
|
|
|
+ getFlowTemplateTreeDataByUser(formData).then((result: any) => {
|
|
|
+ flowTemplates.value = handleTree(result, 'id', 'pid')
|
|
|
+ })
|
|
|
+}
|
|
|
+queryFlowTemplateTreeDataByUser()
|
|
|
+const searchForm = ref({
|
|
|
+ name: ''
|
|
|
+})
|
|
|
+const treeRef = ref()
|
|
|
+const searchHandle = () => {
|
|
|
+ sendData.flowTemIds = treeRef.value.getCheckedNodes(false).map((item) => item['id'])
|
|
|
+ handleCurrentChange(1)
|
|
|
+}
|
|
|
+const { addTProcessHandle, openFlowHandle, flowApplyHandle } = useLookAndApplyFlow()
|
|
|
+
|
|
|
+const commandHandle = (name, item) => {
|
|
|
+ if (name === '作废') {
|
|
|
+ cancelFlow(item)
|
|
|
+ } else if (name === '退回') {
|
|
|
+ callbackActivity(item)
|
|
|
+ }
|
|
|
+ return
|
|
|
+}
|
|
|
+/**
|
|
|
+ * 初始化作废Hook
|
|
|
+ */
|
|
|
+const {
|
|
|
+ nullyApplyTitle,
|
|
|
+ nullyApplyVisible,
|
|
|
+ inullyApplyForm,
|
|
|
+ cancelFlow,
|
|
|
+ nullyApplySubmit,
|
|
|
+ recoverINullyApplyHandle,
|
|
|
+ completelyVoidINullyApplyHandle
|
|
|
+} = useInullyApply({
|
|
|
+ success: (type: InullyApplyEnumType) => {
|
|
|
+ message.success(
|
|
|
+ type === InullyApplyEnum.Recover
|
|
|
+ ? '恢复作废成功!'
|
|
|
+ : type === InullyApplyEnum.Nully
|
|
|
+ ? '作废成功!'
|
|
|
+ : '彻底作废成功!'
|
|
|
+ )
|
|
|
+ initHandleCaseCenterData()
|
|
|
+ }
|
|
|
+})
|
|
|
+/**
|
|
|
+ * 初始化退回Hook
|
|
|
+ */
|
|
|
+const {
|
|
|
+ callbackVisible,
|
|
|
+ callbackTitle,
|
|
|
+ callbacks,
|
|
|
+ callbackForm,
|
|
|
+ callbackActivity,
|
|
|
+ callbackSumbit
|
|
|
+} = useCallback({
|
|
|
+ success: (msg: string) => {
|
|
|
+ message.success(msg)
|
|
|
+ initHandleCaseCenterData()
|
|
|
+ }
|
|
|
+})
|
|
|
+/***
|
|
|
+ * 追回
|
|
|
+ */
|
|
|
+const recoverActivityHandle = (item: any) => {
|
|
|
+ recoverActivity({
|
|
|
+ activityInstanceId: item['ACTIVITYINSID'],
|
|
|
+ participantId: item['PARTICIPANTID']
|
|
|
+ }).then((res) => {
|
|
|
+ if (res) {
|
|
|
+ message.success('追回成功!')
|
|
|
+ initHandleCaseCenterData()
|
|
|
+ }
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+/***
|
|
|
+ * 解挂
|
|
|
+ */
|
|
|
+const addIHangUpHandle = (item: any) => {
|
|
|
+ addIHangUp({
|
|
|
+ activityInstanceId: item['ACTIVITYINSID'],
|
|
|
+ isRecover: 1
|
|
|
+ }).then((res) => {
|
|
|
+ if (res) {
|
|
|
+ message.success('解挂成功!')
|
|
|
+ }
|
|
|
+ })
|
|
|
+}
|
|
|
+const tableRef: any = ref(null)
|
|
|
+const tableHeight: any = ref(0)
|
|
|
+onMounted(() => {
|
|
|
+ tableHeight.value = tableRef.value.clientHeight
|
|
|
+})
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+@import './index.scss';
|
|
|
+</style>
|