Bladeren bron

Merge branch 'master' of gitee.com:xiaopubao/aizuda-web-vue3

xlsea 1 jaar geleden
bovenliggende
commit
55ed7d0c2b

+ 43 - 2
src/api/flow/processTask.ts

@@ -14,7 +14,11 @@ const api = {
 	reviewTask: '/v1/process-task/comment', // 评论审批
 	approvalInfo: '/v1/process-task/approval-info', // 审批详情
 	appendNode: '/v1/process-task/append-node', // 加签审批
-	transfer: '/v1/process-task/transfer' // 转交任务
+	transfer: '/v1/process-task/transfer', // 转交任务
+	claimProcess: '/v1/process-task/claim', // 认领任务
+	withDrawProcess: '/v1/process-task/withdraw', // 撤回任务
+	previousNodeName: '/v1/process-task/previous-node-names', // 以前节点名称列表
+	processTaskJump: '/v1/process-task/jump' // 跳到指定节点任务
 }
 
 // 待认领任务分页列表
@@ -131,6 +135,39 @@ export function processTaskApprovalInfo(taskId: string): AxiosPromise {
 	})
 }
 
+// 认领任务
+export function processClaimTaskApi(taskId: string): AxiosPromise {
+	return request({
+		url: `${api.claimProcess}-${taskId}`,
+		method: 'post'
+	})
+}
+
+// 认领任务
+export function processWithDrawTaskApi(taskId: string): AxiosPromise {
+	return request({
+		url: `${api.withDrawProcess}-${taskId}`,
+		method: 'post'
+	})
+}
+
+// 以前节点名称列表
+export function processPreviousNodeNameApi(taskId: string): AxiosPromise {
+	return request({
+		url: `${api.previousNodeName}/${taskId}`,
+		method: 'post'
+	})
+}
+
+// 跳到指定节点任务
+export function processTaskJumpApi(data: string): AxiosPromise {
+	return request({
+		url: `${api.processTaskJump}`,
+		method: 'post',
+		data
+	})
+}
+
 export default {
 	processTaskPageMyApplicationApi,
 	processTaskPageApprovedApi,
@@ -141,5 +178,9 @@ export default {
 	processApprovalInfoApi,
 	processTaskApprovalInfo,
 	processAppendNodeApi,
-	processTransferApi
+	processTransferApi,
+	processClaimTaskApi,
+	processWithDrawTaskApi,
+	processPreviousNodeNameApi,
+	processTaskJumpApi
 }

+ 0 - 1
src/components/Flow/FlowStatusStamp.vue

@@ -29,7 +29,6 @@ const style = computed(() => {
 	img {
 		overflow: hidden;
 		background-color: transparent;
-		z-index: 999;
 	}
 }
 </style>

+ 1 - 1
src/components/FormConfig/hooks/useForm.tsx

@@ -11,7 +11,7 @@ import { LeFormItem, ObjectOpts, SlotOption } from '@/components/FormConfig/form
 import { get_formSlots, getOptions, renderOption } from '@/components/FormConfig/utils.ts'
 // import { LeTableOptions, LeTableProps } from '@/components/Table'
 // import { SearchFormProps } from '@/components/SearchForm'
-// import { FormConfigProps } from '../index1.vue'
+// import { FormConfigProps } from '../index-old.vue'
 import { useI18n } from 'vue-i18n'
 import { OptionItemProps } from '@/components/Select/select.types.ts'
 export type FormType = 'FormConfig' | 'SearchForm'

+ 1 - 1
src/components/SearchForm.vue

@@ -107,7 +107,7 @@ export const SearchForm = defineComponent({
 		// render渲染
 		return () => {
 			const { searchData, formConfig = {}, triggerSearchAuto } = props
-			let warpClass = 'le-search-form-container labelStyle'
+			let warpClass = 'le-search-form-container' // labelStyle
 			const getItemStyle = (itemStyle, defaultWidth) => {
 				return itemStyle + ((/width\:/g).test(itemStyle) ? '' : `;width:${defaultWidth}`)
 			}

+ 1 - 1
src/layout/index.vue

@@ -7,7 +7,7 @@
 import { computed, type Component } from 'vue'
 import { LayoutType } from '@/store/interface'
 import useStore from '@/store'
-// import RightPanel from '@/components/RightPanel/index1.vue'
+// import RightPanel from '@/components/RightPanel/index-old.vue'
 import LayoutLeft from './LayoutLeft/index.vue'
 import LayoutLeftMix from './LayoutLeftMix/index.vue'
 import LayoutTop from './LayoutTop/index.vue'

+ 1 - 1
src/router/index.ts

@@ -404,7 +404,7 @@ export const constantRoutes: AppRouteRecordRaw[] = [
 			},
 			{
 				path: 'componentCommunication',
-				component: () => import('@/views/test/componentCommunication/index1.vue'),
+				component: () => import('@/views/test/componentCommunication/index.vue'),
 				name: 'componentCommunication',
 				meta: { title: '组件通信方式' }
 			}

+ 8 - 8
src/router/test_routes.ts

@@ -28,49 +28,49 @@ const routers = [
 		children: [
 			{
 				path: 'group1',
-				// component: () => import('@/views/flow/group/index1.vue'),
-				component: 'flow/group/index1',
+				// component: () => import('@/views/flow/group/index.vue'),
+				component: 'flow/group/index',
 				name: 'flow_group1',
 				meta: { title: '流程组', icon: '' }
 			},
 			{
 				path: 'group',
-				// component: () => import('@/views/flow/group/index1.vue'),
+				// component: () => import('@/views/flow/group/index.vue'),
 				component: 'flow/group/index',
 				name: 'flow_group',
 				meta: { title: '流程组 - ui调整', icon: '' }
 			},
 			{
 				path: 'form',
-				// component: () => import('@/views/flow/form/index1.vue'),
+				// component: () => import('@/views/flow/form/index.vue'),
 				component: 'flow/form/index',
 				name: 'flow_form',
 				meta: { title: '流程表单', icon: '' }
 			},
 			{
 				path: 'create',
-				// component: () => import('@/views/flow/create/index1.vue'),
+				// component: () => import('@/views/flow/create/index.vue'),
 				component: 'flow/create/index',
 				name: 'flow_create',
 				meta: { title: '创建流程', icon: '' }
 			},
 			{
 				path: 'task',
-				// component: () => import('@/views/flow/task/index1.vue'),
+				// component: () => import('@/views/flow/task/index.vue'),
 				component: 'flow/task/index',
 				name: 'flow_task',
 				meta: { title: '流程任务', icon: '' }
 			},
 			{
 				path: 'instance',
-				// component: () => import('@/views/flow/instance/index1.vue'),
+				// component: () => import('@/views/flow/instance/index.vue'),
 				component: 'flow/instance/index',
 				name: 'flow_instance',
 				meta: { title: '流程实例', icon: '' }
 			},
 			{
 				path: 'modal',
-				// component: () => import('@/views/flow/modal/index1.vue'),
+				// component: () => import('@/views/flow/modal/index.vue'),
 				component: 'flow/modal/index',
 				name: 'flow_modal',
 				meta: { title: '流程模型', icon: '' }

+ 1 - 1
src/store/modules/permission.ts

@@ -139,7 +139,7 @@ const usePermissionStore = defineStore({
 				{
 					path: 'dashboard',
 					// path: HOME_URL,
-					component: () => import('@/views/dashboard/index1.vue'),
+					component: () => import('@/views/dashboard/index-old.vue'),
 					name: 'dashboard',
 					meta: { title: 'dashboard', icon: 'icon-homepage', affix: true }
 				}

+ 18 - 0
src/styles/project_normal.scss

@@ -52,3 +52,21 @@ body {
 ::-webkit-scrollbar-thumb{border-radius:6px;background-color:rgba(0,0,0,0.1);box-shadow:0 0 0 #fff inset,0 0 0 #fff inset,0 0 0 rgba(255,255,255,0.9) inset,0 0 0 rgba(255,255,255,0.9) inset}
 ::-webkit-scrollbar-thumb:hover{background-color:rgba(0,0,0,0.4)}
 ::-webkit-scrollbar-thumb:active{background:rgba(0,0,0,0.6)}
+
+// 审批公用样式
+.flex-column-page-wrap.flex-wrap {
+	flex-direction: row;
+	background-color: #f2f3f5;
+	padding: 10px 10px 0 10px;
+}
+
+.warp-left {
+	width: 330px; /*固定宽度*/
+	overflow: auto; /*超出部分滚动*/
+	background-color: var(--el-bg-color);
+	margin-right: 10px;
+}
+
+.warp-right {
+	flex: 1; /*这里设置为占比1,填充满剩余空间*/
+}

+ 0 - 187
src/views/approve/await/index.vue

@@ -1,187 +0,0 @@
-<script setup lang="ts"></script>
-
-<template>
-	<div class="content-container">
-		<section class="flow-approve-box">
-			<!-- 需要抽成组件 -->
-			<div class="flow-content">
-				<!-- 搜索框 -->
-				<div class="search-box">
-					<div class="search-segment" style="flex: 1 1 0%"></div>
-					<div class="search-segment"></div>
-					<div class="search-segment"></div>
-				</div>
-
-				<!-- 列表值 -->
-				<div class="flow-list-box">
-					<div class="item-box">
-						<div class="flow-card-box flow-card-box-hoverable">
-							<div class="header">
-								<span class="typography name">请假</span>
-								<div class="status"><el-button type="success" plain size="small">审核中</el-button></div>
-							</div>
-							<div class="summary-list">
-								<div class="summary-item">
-									<div class="label">假期类型:</div>
-									<div class="value">事假</div>
-								</div>
-								<div class="summary-item">
-									<div class="label">假期时间:</div>
-									<div class="value">2023</div>
-								</div>
-							</div>
-							<div class="footer">
-								<div class="initiator">
-									<div class="avatar" style="height: 28px; border-radius: 14px; padding: 4px">
-										<div class="icon" style="width: 20px; height: 20px; font-size: 10px"></div>
-										<div class="name" style="font-size: 11px">123</div>
-									</div>
-								</div>
-								<div class="begin-time">提交时间:1233-34-56</div>
-							</div>
-						</div>
-					</div>
-				</div>
-			</div>
-			<div class="flow-detail-content"></div>
-		</section>
-	</div>
-</template>
-
-<style scoped lang="scss">
-.content-container {
-	height: calc(100% - 45px);
-	.flow-approve-box {
-		width: 100%;
-		height: calc(100vh - 105px);
-		overflow: hidden;
-		padding: 0 12px;
-		display: flex;
-		gap: 12px;
-
-		.flow-content {
-			width: 330px;
-			min-width: 330px;
-			height: 100%;
-			overflow: hidden;
-			//background: #fff;
-			border-radius: 6px;
-			background: #0d84ff;
-			.search-box {
-				display: flex;
-				align-items: center;
-				height: 56px;
-				padding: 0 12px;
-				.search-segment {
-					margin-left: 4px;
-				}
-			}
-		}
-
-		// 列表
-		.flow-list-box {
-			background-color: #fff;
-			padding: 0 12px;
-			height: calc(100vh - 161px);
-			overflow: hidden auto;
-			scroll-snap-type: y mandatory;
-			will-change: scroll-position;
-			.item-box {
-				margin-bottom: 12px;
-			}
-		}
-
-		// 列表的卡片样式
-		.flow-card-box {
-			-webkit-user-select: none;
-			user-select: none;
-			border-radius: 6px;
-			overflow: hidden;
-			border: 1px solid #e9ebef;
-			padding: 10px 12px;
-			cursor: pointer;
-			transition: box-shadow 0.2s cubic-bezier(0, 0, 1, 1);
-			.header {
-				display: flex;
-				align-items: center;
-				justify-content: space-between;
-				.typography {
-					//color: var(--color-text-1); todo
-					line-height: 1.5715;
-					white-space: normal;
-					overflow-wrap: anywhere;
-				}
-				.name {
-					font-size: 15px;
-				}
-			}
-
-			.summary-list {
-				margin-top: 10px;
-				.summary-item {
-					display: flex;
-					min-height: 20px;
-					.label {
-						color: #9ba5b3;
-						overflow: hidden;
-						white-space: nowrap;
-						flex-shrink: 0;
-					}
-					.value {
-						color: #232730;
-						overflow: hidden;
-						text-overflow: ellipsis;
-						white-space: nowrap;
-					}
-				}
-			}
-
-			.footer {
-				margin-top: 10px;
-				display: flex;
-				align-items: center;
-				justify-content: space-between;
-				font-size: 13px;
-				.avatar {
-					background: #f2f4f5;
-					display: flex;
-					align-items: center;
-					width: fit-content;
-					.icon {
-						overflow: hidden;
-						flex-shrink: 0;
-						border-radius: 50%;
-					}
-					.name {
-						-webkit-user-select: none;
-						user-select: none;
-						font-family: PingFangSC-Regular, PingFang SC;
-						color: #34383e;
-						margin: 0 4px;
-						overflow: hidden;
-						white-space: nowrap;
-						text-overflow: ellipsis;
-						max-width: 64px;
-					}
-				}
-				.initiator {
-					display: flex;
-					align-items: center;
-				}
-				.begin-time {
-					//color: #9ba5b3; todo
-				}
-			}
-		}
-
-		.flow-detail-content {
-			height: 100%;
-			overflow: hidden;
-			//background: #fff;
-			border-radius: 6px;
-			flex: auto;
-			background: #0934ff;
-		}
-	}
-}
-</style>

+ 30 - 0
src/views/approve/components/approvalIndex.vue

@@ -0,0 +1,30 @@
+<template>
+	<div class="flex-column-page-wrap flex-wrap">
+		<div class="warp-left">
+			<ApprovedItem :current-task-type="currentTaskType" />
+		</div>
+
+		<div class="warp-right">
+			<ApprovedContent :current-task-type="currentTaskType" />
+		</div>
+	</div>
+</template>
+
+<script setup>
+import ApprovedItem from '../components/approvedItem.vue'
+import ApprovedContent from '../components/approvedContent.vue'
+
+const props = defineProps({
+	/**
+	 * pendingApproval 待审批
+	 * myApplication 我的申请
+	 * myReceived 我收到的
+	 * pendingClaim 认领任务
+	 * approved 已审批
+	 */
+	currentTaskType: {
+		type: String,
+		default: ''
+	}
+})
+</script>

+ 110 - 51
src/views/approve/components/approvedContent.vue

@@ -67,33 +67,55 @@
 				</div>
 
 				<!-- 3、底部操作按钮 -->
+				<!--
+            1、已审批的任务不显示操作按钮
+            2、我的申请显示撤回按钮
+            3、认领任务显示认领按钮
+            4、我收到的任务显示评论
+            -->
 				<div class="flow-actions">
 					<el-button :icon="ChatLineSquare" @click="openComment('reviewVisible')">评论</el-button>
-					<el-button :icon="Check" type="success" @click="openComment('consentOrRefuseVisible', 'agree')">同意</el-button>
-					<el-button :icon="Close" type="danger" @click="openComment('consentOrRefuseVisible', 'reject')">拒绝</el-button>
-					<el-dropdown style="margin-left: 12px">
-						<el-button :icon="More">更多</el-button>
-						<template #dropdown>
-							<el-dropdown-menu>
-								<el-dropdown-item @click.native="openComment('deliverToReviewVisible')">
-									<el-icon><DArrowLeft /></el-icon>
-									转交
-								</el-dropdown-item>
-								<el-dropdown-item @click.native="openComment('rollbackVisible')">
-									<el-icon><Switch /></el-icon>
-									回退
-								</el-dropdown-item>
-								<el-dropdown-item @click.native="openComment('addSignVisible')">
-									<el-icon><Plus /></el-icon>
-									加签
-								</el-dropdown-item>
-								<el-dropdown-item @click.native="openComment('loseSignVisible')">
-									<el-icon><Minus /></el-icon>
-									减签
-								</el-dropdown-item>
-							</el-dropdown-menu>
-						</template>
-					</el-dropdown>
+					<template v-if="currentTaskType !== 'myReceived' || currentTaskType !== 'approved'">
+						<el-button
+							v-if="currentTaskType === 'pendingApproval'"
+							:icon="Check"
+							type="primary"
+							@click="openComment('consentOrRefuseVisible', 'agree')"
+							>同意</el-button
+						>
+						<el-button
+							v-if="currentTaskType === 'pendingApproval'"
+							:icon="Close"
+							type="danger"
+							@click="openComment('consentOrRefuseVisible', 'reject')"
+							>拒绝</el-button
+						>
+						<el-button v-if="currentTaskType === 'myApplication'" :icon="Close" @click="withDrawTaskEv">撤回</el-button>
+						<el-button v-if="currentTaskType === 'pendingClaim'" :icon="Close" @click="claimTaskEv">认领</el-button>
+						<el-dropdown v-if="currentTaskType === 'pendingApproval'" style="margin-left: 12px">
+							<el-button :icon="More">更多</el-button>
+							<template #dropdown>
+								<el-dropdown-menu>
+									<el-dropdown-item @click.native="openComment('deliverToReviewVisible')">
+										<el-icon><DArrowLeft /></el-icon>
+										转交
+									</el-dropdown-item>
+									<el-dropdown-item @click.native="openComment('rollbackVisible')">
+										<el-icon><Switch /></el-icon>
+										回退
+									</el-dropdown-item>
+									<el-dropdown-item @click.native="openComment('addSignVisible')">
+										<el-icon><Plus /></el-icon>
+										加签
+									</el-dropdown-item>
+									<el-dropdown-item @click.native="openComment('loseSignVisible')">
+										<el-icon><Minus /></el-icon>
+										减签
+									</el-dropdown-item>
+								</el-dropdown-menu>
+							</template>
+						</el-dropdown>
+					</template>
 				</div>
 			</template>
 		</div>
@@ -109,7 +131,8 @@
 			v-if="consentOrRefuseVisible"
 			v-model="consentOrRefuseVisible"
 			:task-id="taskId"
-			:current-type="currentDialog"
+			:current-type="currentType"
+			:form-data="currentFormData"
 			@success-cb="closeDetailEv"
 		></consent-or-refuse-dialog>
 
@@ -137,7 +160,7 @@ import FlowStatusTag from '@/components/Flow/FlowStatusTag.vue'
 import FlowNodeAvatar from '@/components/Flow/FlowNodeAvatar.vue'
 import FlowTypeDot from '@/components/Flow/FlowTypeDot.vue'
 import { ChatLineSquare, Check, Close, Switch, DArrowLeft, Plus, Minus, More } from '@element-plus/icons-vue'
-import { processApprovalInfoApi, processTaskApprovalInfo } from '@/api/flow/processTask'
+import { processApprovalInfoApi, processTaskApprovalInfo, processClaimTaskApi, processWithDrawTaskApi } from '@/api/flow/processTask'
 import { formatTimestamp } from '@/utils/datetime'
 import ReviewDialog from './reviewDialog'
 import AddSignDialog from './addSignDialog'
@@ -148,6 +171,20 @@ import RollbackDialog from './rollbackDialog'
 import viewForm from '@/utils/form'
 import { storeToRefs } from 'pinia'
 
+const props = defineProps({
+	/**
+	 * pendingApproval 待审批
+	 * myApplication 我的申请
+	 * myReceived 我收到的
+	 * pendingClaim 认领任务
+	 * approved 已审批
+	 */
+	currentTaskType: {
+		type: String,
+		default: ''
+	}
+})
+
 // store值
 const taskProcessInfo = useTaskProcessStore()
 const { currentTaskRow } = storeToRefs(taskProcessInfo)
@@ -161,8 +198,10 @@ const loseSignVisible = ref(false)
 const rollbackVisible = ref(false)
 // 各种操作弹窗显示隐藏 end
 const activeData = ref([])
-const currentDialog = ref(null)
-
+const currentType = ref(null)
+const currentFormData = ref({})
+// 当前form 表单数据字符串
+let cur_processForm_str = '[]'
 const taskId = computed(() => {
 	return currentTaskRow.value.taskId || ''
 })
@@ -183,31 +222,16 @@ const validateForm = ref({
 const closeDetailEv = () => {
 	// 存储表单 todo.....
 	// 如果这里有表单,是否要把所有表单的内容进行存储,存储完毕后,才能关闭这个详情,刷新左侧的列表 todo
-	// return todo
-	debugger
 	taskProcessInfo.refresh = true
-	taskProcessInfo.setCurrentTaskRow({})
+	// taskProcessInfo.setCurrentTaskRow({})
 }
 
 /**
  * 详情按钮各个操作弹窗
- * @param type 评论 拒绝 同意等
+ * @param visibleType 评论 拒绝 同意等
  */
-const openComment = (type, item) => {
-	// 验证表单 todo...
-	const api = validateForm.value.api
-	api.validate((valid, fail) => {
-		if (valid) {
-			const values = api.formData()
-			console.warn(values, 'values')
-			//todo 表单验证通过
-		} else {
-			//todo 表单验证未通过
-		}
-	})
-	// return
-
-	switch (type) {
+const openComment = async (visibleType, item) => {
+	switch (visibleType) {
 		case 'reviewVisible':
 			reviewVisible.value = !reviewVisible.value
 			break
@@ -215,7 +239,28 @@ const openComment = (type, item) => {
 			addSignVisible.value = !addSignVisible.value
 			break
 		case 'consentOrRefuseVisible':
-			currentDialog.value = item
+			currentFormData.value = {}
+			// 点击同意
+			let bool = true
+			if (item === 'agree') {
+				const api = validateForm.value.api
+				bool = await api.validate((valid, fail) => {
+					if (valid) {
+						// 表单验证通过
+						const values = api.formData()
+						const processForm = JSON.parse(cur_processForm_str)
+						processForm.forEach(v => {
+							// 填写的数据存储(local_: 本地数据处理标识)
+							v.local_value = values[v.field]
+						})
+						console.warn(processForm, 'processForm')
+						// 流程表单JSON内容 & local_value 保存
+						currentFormData.value = { processForm: JSON.stringify(processForm) }
+					}
+				})
+			}
+			if (!bool) return
+			currentType.value = item
 			consentOrRefuseVisible.value = !consentOrRefuseVisible.value
 			break
 		case 'deliverToReviewVisible':
@@ -267,6 +312,7 @@ const getTaskDetail = () => {
 					}
 				})*/
 				const forms = JSON.parse(data.formContent)
+				cur_processForm_str = data.formContent
 				if (Array.isArray(forms)) {
 					validateForm.value.rule = forms
 					const api = validateForm.value.api
@@ -292,6 +338,18 @@ const getTaskDetail = () => {
 		})
 }
 
+/** 认领任务 **/
+const claimTaskEv = async () => {
+	const res = await processClaimTaskApi(currentTaskRow.value.taskId)
+	console.log(res, 'res====')
+}
+
+/** 撤回审批 **/
+const withDrawTaskEv = async () => {
+	const res = await processWithDrawTaskApi(currentTaskRow.value.taskId)
+	console.log(res)
+}
+
 /**
  * 监听同级子组件的taskId的值变化
  * 1、监听taskId的值变化,如果值有变化,则重新获取审批详情
@@ -326,6 +384,7 @@ watch(
 		position: absolute;
 		right: 30px;
 		top: 30px;
+		z-index: 999;
 	}
 
 	// 头部
@@ -390,7 +449,7 @@ watch(
 		.area-divider {
 			border-bottom: 1px solid rgba(229, 230, 235, 1);
 			margin: 20px 0;
-			position: relative;
+			//position: relative;
 		}
 	}
 
@@ -401,7 +460,7 @@ watch(
 		justify-content: flex-end;
 		height: 52px;
 		//border-top: 1px solid var(--color-neutral-3);
-		border-top: 1px solid black;
+		border-top: 1px solid #e5e6ec;
 		padding: 0 20px;
 	}
 }

+ 51 - 6
src/views/approve/components/approvedItem.vue

@@ -32,7 +32,17 @@
 					<!--头部-->
 					<div class="header">
 						<el-text tag="b">{{ i.processName }}</el-text>
-						<el-tag type="primary">待审核</el-tag>
+						<el-tag v-if="currentTaskType === 'pendingApproval'">待审批</el-tag>
+						<template v-else>
+							<el-tag>
+								<template v-if="i.instanceState === 0">审批中</template>
+								<template v-if="i.instanceState === 1">审批通过</template>
+								<template v-if="i.instanceState === 2">审批拒绝</template>
+								<template v-if="i.instanceState === 3">撤销审批</template>
+								<template v-if="i.instanceState === 4">超时结束</template>
+								<template v-if="i.instanceState === 5">强制终止</template>
+							</el-tag>
+						</template>
 					</div>
 					<!--操作类容-->
 					<div class="summary-list"></div>
@@ -58,7 +68,27 @@ import useTaskProcessStore from '@/store/modules/taskProcess'
 import FlowNodeAvatar from '@/components/Flow/FlowNodeAvatar.vue'
 import { Search, Filter, Refresh } from '@element-plus/icons-vue'
 import { computed, onMounted, reactive, ref, watch } from 'vue'
-import { processTaskPagePendingApprovalApi } from '@/api/flow/processTask'
+import {
+	processTaskPagePendingApprovalApi,
+	processTaskPageMyApplicationApi,
+	processTaskPagePendingClaimApi,
+	processTaskPageApprovedApi,
+	processTaskPageMyReceivedApi
+} from '@/api/flow/processTask'
+
+const props = defineProps({
+	/**
+	 * pendingApproval 待审批
+	 * myApplication 我的申请
+	 * myReceived 我收到的
+	 * pendingClaim 认领任务
+	 * approved 已审批
+	 */
+	currentTaskType: {
+		type: String,
+		default: ''
+	}
+})
 
 // store值
 const taskProcessInfo = useTaskProcessStore()
@@ -85,10 +115,12 @@ const init = () => {
 	totalPages.value = 0
 	taskProcessInfo.refresh = false
 	taskProcessInfo.setCurrentTaskRow({})
+	load()
 }
 
 // 分页获取数据
 const load = () => {
+	if (loading.value) return false
 	loading.value = true
 	getPagedSatellites()
 }
@@ -96,7 +128,20 @@ const load = () => {
 // 获取分页数据
 const getPagedSatellites = async () => {
 	try {
-		const { records, total, pages } = await processTaskPagePendingApprovalApi(condition)
+		let responseData = {}
+		const { currentTaskType } = props
+		if (currentTaskType === 'pendingApproval') {
+			responseData = await processTaskPagePendingApprovalApi(condition)
+		} else if (currentTaskType === 'myApplication') {
+			responseData = await processTaskPageMyApplicationApi(condition)
+		} else if (currentTaskType === 'myReceived') {
+			responseData = await processTaskPageMyReceivedApi(condition)
+		} else if (currentTaskType === 'pendingClaim') {
+			responseData = await processTaskPagePendingClaimApi(condition)
+		} else if (currentTaskType === 'approved') {
+			responseData = await processTaskPageApprovedApi(condition)
+		}
+		const { records, total, pages } = responseData
 		records.forEach(item => {
 			satelliteList.value.push(item)
 		})
@@ -118,9 +163,9 @@ const getTaskDetail = item => {
 	taskProcessInfo.setCurrentTaskRow(item)
 }
 
-onMounted(() => {
+/*onMounted(() => {
 	init()
-})
+})*/
 
 /**
  * 监听同级子组件通知
@@ -170,7 +215,7 @@ const disabledInfinite = computed(() => noMore.value)
 	.flow-list-box {
 		background-color: #fff;
 		padding: 0 12px;
-		height: calc(100vh - 161px);
+		height: calc(100vh - 192px);
 		overflow: hidden auto;
 		scroll-snap-type: y mandatory;
 		will-change: scroll-position;

+ 13 - 3
src/views/approve/components/consentOrRefuseDialog.vue

@@ -31,6 +31,7 @@
 import { computed, reactive, ref } from 'vue'
 import FileUpload from '@/components/FileUpload.vue'
 import { processConsentTaskApi, processRejectionTaskApi } from '@/api/flow/processTask'
+import { ElMessage } from 'element-plus'
 
 const props = defineProps({
 	// 弹窗是否显示
@@ -47,11 +48,16 @@ const props = defineProps({
 	currentType: {
 		type: String,
 		default: 'agree'
+	},
+	// 额外 表单数据
+	formData: {
+		type: Object,
+		default: () => ({})
 	}
 })
 const btnDisabled = ref(false)
 const form = reactive({
-	content: '',
+	content: ''
 	// attachment: []
 })
 const formRef = ref(null)
@@ -61,14 +67,18 @@ const $myEmit = defineEmits(['update:modelValue', 'successCb'])
 
 const submitForm = () => {
 	btnDisabled.value = true
-	const formData = { ...form, taskId: props.taskId }
+	const formData = { taskId: props.taskId, ...props.formData, ...form }
 	formRef.value
 		.validate()
 		.then(async valid => {
 			if (valid) {
-				if (currentTip.value) {
+				const isAgree = props.currentType === 'agree'
+				if (isAgree) {
+					// 同意
 					await processConsentTaskApi(formData)
+					ElMessage.success('执行成功')
 				} else {
+					// 拒绝
 					await processRejectionTaskApi(formData)
 				}
 				closeDialog()

+ 27 - 36
src/views/approve/components/rollbackDialog.vue

@@ -2,15 +2,15 @@
 	<!-- 回退审批弹窗 -->
 	<el-dialog v-model="reviewVisibleDialog" title="回退审批" width="700" destroy-on-close>
 		<el-form ref="formRef" v-loading="uploadLoading" label-position="top" element-loading-text="图片上传中..." :model="form" label-width="80px">
-			<el-form-item label="回退到" prop="review" :rules="[{ required: true, message: '请选择回退节点' }]">
-				<el-select v-model="form.deliverTo" placeholder="请选择回退节点">
-					<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
+			<el-form-item label="回退到" prop="nodeName" :rules="[{ required: true, message: '请选择回退节点' }]">
+				<el-select v-model="form.nodeName" placeholder="请选择回退节点">
+					<el-option v-for="item in rollbackOptions" :key="item" :label="item" :value="item" />
 				</el-select>
 			</el-form-item>
-			<el-form-item label="回退原因" prop="review">
-				<el-input v-model="form.review" type="textarea" placeholder="请输入回退原因" maxlength="64" show-word-limit> </el-input>
+			<el-form-item label="回退原因" prop="content">
+				<el-input v-model="form.content" type="textarea" placeholder="请输入回退原因" maxlength="64" show-word-limit> </el-input>
 			</el-form-item>
-			<el-form-item prop="attachment" label="附件" class="example-img-box">
+			<el-form-item v-if="false" prop="attachment" label="附件" class="example-img-box">
 				<!--'.docx', '.doc', '.pptx', '.ppt', '.xlsx', '.xls', '.zip', '.csv', '.pdf', '.png', '.jpg'  因前端不支持图片以外格式,所以注释 -->
 				<FileUpload
 					v-model="form.attachment"
@@ -33,8 +33,9 @@
 </template>
 
 <script setup>
-import { computed, reactive, ref } from 'vue'
+import { computed, onMounted, reactive, ref } from 'vue'
 import FileUpload from '@/components/FileUpload.vue'
+import { processPreviousNodeNameApi, processTaskJumpApi } from '@/api/flow/processTask'
 
 const props = defineProps({
 	modelValue: {
@@ -48,49 +49,35 @@ const props = defineProps({
 })
 const btnDisabled = ref(false)
 const form = reactive({
-	deliverTo: '',
-	review: '',
-	attachment: []
+	nodeName: '',
+	content: ''
+	// attachment: []
 })
 const formRef = ref(null)
 const uploadLoading = ref(false)
-const options = [
-	{
-		value: 'Option1',
-		label: 'Option1'
-	},
-	{
-		value: 'Option2',
-		label: 'Option2'
-	},
-	{
-		value: 'Option3',
-		label: 'Option3'
-	},
-	{
-		value: 'Option4',
-		label: 'Option4'
-	},
-	{
-		value: 'Option5',
-		label: 'Option5'
-	}
-]
+const rollbackOptions = ref([])
 
 const $myEmit = defineEmits(['update:modelValue', 'successCb'])
 
+// 回退节点列表
+const getProcessPreviousNodeNameApi = async () => {
+	const res = await processPreviousNodeNameApi(props.taskId)
+	rollbackOptions.value = res || []
+}
+
 const submitForm = () => {
 	btnDisabled.value = true
-	const formData = { ...form }
+	const formData = { ...form, taskId: props.taskId }
 	formRef.value
 		.validate()
-		.then(valid => {
+		.then(async valid => {
 			if (valid) {
+				await processTaskJumpApi(formData)
+				closeDialog()
 				btnDisabled.value = false
 			}
 		})
 		.catch(err => {
-			console.error('挂起订单表单拦截', err)
 			btnDisabled.value = false
 		})
 }
@@ -100,6 +87,8 @@ const closeDialog = () => {
 	$myEmit('update:modelValue', false)
 }
 
+const clearValidate = () => {}
+
 const reviewVisibleDialog = computed({
 	get() {
 		return props.modelValue
@@ -109,7 +98,9 @@ const reviewVisibleDialog = computed({
 	}
 })
 
-const clearValidate = () => {}
+onMounted(() => {
+	getProcessPreviousNodeNameApi()
+})
 </script>
 
 <style scoped>

+ 229 - 0
src/views/approve/myApplication/index-old.vue

@@ -0,0 +1,229 @@
+<template>
+	<div class="pageWrap flex-column-page-wrap">
+		<div class="flex-column-page-wrap">
+			<!-- 公用搜索组件 -->
+			<LeSearchForm ref="searchForm" v-model:searchData="searchData" :forms="forms" :loading="tableOpts.options.loading"> </LeSearchForm>
+
+			<!--  LeTable 组件使用  -->
+			<LeTable
+				ref="tableRef"
+				v-model:searchParams="tableOpts.searchParams"
+				v-bind="tableOpts"
+				v-model:curRow="tableOpts.curRow"
+				v-model:checked-options="checkedColumns"
+				:columns="activeColumns"
+			>
+				<template #toolLeft>
+					<el-button type="primary">操作我申请的</el-button>
+				</template>
+
+				<template #currentNodeSlot="scope">
+					<div v-if="scope.row.currentNode === 'complete'">-</div>
+					<div v-else>{{ scope.row.currentNode }}</div>
+				</template>
+
+				<template #instanceStateSlot="scope">
+					<el-tag v-if="scope.row.instanceState === 0" size="small" effect="plain">审批中</el-tag>
+					<el-tag v-if="scope.row.instanceState === 1" size="small" type="info" effect="plain">审批通过</el-tag>
+					<el-tag v-if="scope.row.instanceState === 2" size="small" type="warning" effect="plain">审批拒绝</el-tag>
+					<el-tag v-if="scope.row.instanceState === 3" size="small" type="warning" effect="plain">撤销审批</el-tag>
+					<el-tag v-if="scope.row.instanceState === 4" size="small" type="warning" effect="plain">超时结束</el-tag>
+					<el-tag v-if="scope.row.instanceState === 5" size="small" type="warning" effect="plain">强制终止</el-tag>
+				</template>
+
+				<template #durationSlot="scope">
+					<div>{{ format_milliseconds(scope.row.duration) }}</div>
+				</template>
+
+				<template #actionSlot="scope">
+					<el-tooltip content="查看" placement="bottom" effect="light">
+						<el-icon class="ibt0" @click="openDetail(scope.row)">
+							<View />
+						</el-icon>
+					</el-tooltip>
+				</template>
+			</LeTable>
+		</div>
+
+		<message-detail v-if="visibleDetail" v-model="visibleDetail" :message-id="currentId" @closed="visibleDetail = false"> </message-detail>
+	</div>
+</template>
+<script lang="tsx" setup>
+import { processTaskPageMyApplicationApi } from '@/api/flow/processTask'
+import { nextTick, ref, watch } from 'vue'
+import { useTablePage } from '@/hooks/useTablePage'
+import { format_milliseconds } from '@/utils'
+import MessageDetail from './detail.vue'
+import { useRoute } from 'vue-router'
+const route = useRoute()
+
+const visibleDetail = ref(false) // 权限设置弹窗显示隐藏
+const currentId = ref(null)
+
+// 表格搜索条件
+const forms = ref([
+	{
+		prop: 'processName',
+		label: '流程名称:',
+		itemType: 'input',
+		placeholder: '请输入流程名称'
+	},
+	{
+		prop: 'createBy',
+		label: '发布人:',
+		itemType: 'input',
+		placeholder: '请输入发布人'
+	}
+])
+
+// table列表数据请求
+const queryList = async () => {
+	const { options, searchParams } = tableOpts
+	options.loading = true
+	try {
+		const { records: list, total } = await processTaskPageMyApplicationApi(searchParams)
+		tableOpts.total = total
+		tableOpts.list = list
+	} catch {
+		console.log('获取列表数据失败')
+		tableOpts.total = 0
+		tableOpts.list = []
+		options.loading = false // 更改加载中的 loading值
+	} finally {
+		options.loading = false
+	}
+}
+
+// table 参数
+const columns = [
+	{
+		prop: 'processName',
+		label: '流程名称',
+		minWidth: 80
+	},
+	{
+		prop: 'currentNode',
+		label: '当前所在节点',
+		minWidth: 80,
+		slots: {
+			default: 'currentNodeSlot'
+		}
+	},
+	{
+		prop: 'instanceState',
+		label: '流程状态',
+		minWidth: 100,
+		slots: {
+			default: 'instanceStateSlot'
+		}
+	},
+	{
+		prop: 'createBy',
+		label: '发起人',
+		minWidth: 100
+	},
+	{
+		prop: 'createTime',
+		label: '发起时间',
+		minWidth: 126
+	},
+	{
+		prop: 'endTime',
+		label: '结束时间',
+		minWidth: 126
+	},
+	{
+		prop: 'duration',
+		label: '处理耗时',
+		minWidth: 100,
+		slots: {
+			default: 'durationSlot'
+		}
+	},
+	{
+		prop: 'expireTime',
+		label: '期望完成时间',
+		minWidth: 126
+	},
+	{
+		prop: 'action',
+		label: '操作',
+		width: 100,
+		fixed: 'right',
+		slots: {
+			default: 'actionSlot'
+		}
+	}
+]
+
+const { searchData, tableOpts, checkedColumns, activeColumns } = useTablePage(
+	{
+		options: {
+			showIndex: false
+		},
+		// 需要展示的列
+		columns,
+		// 控制列配置
+		columnsConfig: {
+			columns
+		}
+	},
+	{
+		queryList,
+		fetchImmediate: false
+	}
+)
+
+const openDetail = (row: any) => {
+	currentId.value = row.id
+	visibleDetail.value = true
+}
+
+nextTick(() => {
+	queryList()
+})
+
+watch(
+	() => route.query,
+	(newPath, oldPath) => {
+		if (JSON.stringify(newPath) !== '{}') {
+			nextTick(() => {
+				openDetail(newPath)
+			})
+		}
+	},
+	{ immediate: true }
+)
+</script>
+<style scoped lang="scss">
+.pageWrap {
+	flex: 1;
+	display: flex;
+	height: 100%;
+	min-height: 0;
+	//background-color: #fafafa;
+	background-color: var(--el-fill-color-lighter);
+	//background: #fff;
+}
+// 单独自己写的
+/*:deep(.box-card) {
+	height: 100%;
+	.el-card__body {
+		padding: 0;
+	}
+}*/
+
+// 应用的树结构样式
+:deep(.menu-tree) {
+	.el-tree-node__content {
+		height: 36px;
+	}
+	.el-tree-node__content .el-tree-node__label .icon {
+		margin-right: 5px;
+	}
+}
+
+.nopadding {
+	padding: 0px;
+}
+</style>

+ 12 - 225
src/views/approve/myApplication/index.vue

@@ -1,229 +1,16 @@
 <template>
-	<div class="pageWrap flex-column-page-wrap">
-		<div class="flex-column-page-wrap">
-			<!-- 公用搜索组件 -->
-			<LeSearchForm ref="searchForm" v-model:searchData="searchData" :forms="forms" :loading="tableOpts.options.loading"> </LeSearchForm>
-
-			<!--  LeTable 组件使用  -->
-			<LeTable
-				ref="tableRef"
-				v-model:searchParams="tableOpts.searchParams"
-				v-bind="tableOpts"
-				v-model:curRow="tableOpts.curRow"
-				v-model:checked-options="checkedColumns"
-				:columns="activeColumns"
-			>
-				<template #toolLeft>
-					<el-button type="primary">操作我申请的</el-button>
-				</template>
-
-				<template #currentNodeSlot="scope">
-					<div v-if="scope.row.currentNode === 'complete'">-</div>
-					<div v-else>{{ scope.row.currentNode }}</div>
-				</template>
-
-				<template #instanceStateSlot="scope">
-					<el-tag v-if="scope.row.instanceState === 0" size="small" effect="plain">审批中</el-tag>
-					<el-tag v-if="scope.row.instanceState === 1" size="small" type="info" effect="plain">审批通过</el-tag>
-					<el-tag v-if="scope.row.instanceState === 2" size="small" type="warning" effect="plain">审批拒绝</el-tag>
-					<el-tag v-if="scope.row.instanceState === 3" size="small" type="warning" effect="plain">撤销审批</el-tag>
-					<el-tag v-if="scope.row.instanceState === 4" size="small" type="warning" effect="plain">超时结束</el-tag>
-					<el-tag v-if="scope.row.instanceState === 5" size="small" type="warning" effect="plain">强制终止</el-tag>
-				</template>
-
-				<template #durationSlot="scope">
-					<div>{{ format_milliseconds(scope.row.duration) }}</div>
-				</template>
-
-				<template #actionSlot="scope">
-					<el-tooltip content="查看" placement="bottom" effect="light">
-						<el-icon class="ibt0" @click="openDetail(scope.row)">
-							<View />
-						</el-icon>
-					</el-tooltip>
-				</template>
-			</LeTable>
-		</div>
-
-		<message-detail v-if="visibleDetail" v-model="visibleDetail" :message-id="currentId" @closed="visibleDetail = false"> </message-detail>
-	</div>
+	<ApprovalIndex ref="myApplication" :current-task-type="taskType"></ApprovalIndex>
 </template>
-<script lang="tsx" setup>
-import { processTaskPageMyApplicationApi } from '@/api/flow/processTask'
-import { nextTick, ref, watch } from 'vue'
-import { useTablePage } from '@/hooks/useTablePage'
-import { format_milliseconds } from '@/utils'
-import MessageDetail from './detail.vue'
-import { useRoute } from 'vue-router'
-const route = useRoute()
-
-const visibleDetail = ref(false) // 权限设置弹窗显示隐藏
-const currentId = ref(null)
-
-// 表格搜索条件
-const forms = ref([
-	{
-		prop: 'processName',
-		label: '流程名称:',
-		itemType: 'input',
-		placeholder: '请输入流程名称'
-	},
-	{
-		prop: 'createBy',
-		label: '发布人:',
-		itemType: 'input',
-		placeholder: '请输入发布人'
-	}
-])
 
-// table列表数据请求
-const queryList = async () => {
-	const { options, searchParams } = tableOpts
-	options.loading = true
-	try {
-		const { records: list, total } = await processTaskPageMyApplicationApi(searchParams)
-		tableOpts.total = total
-		tableOpts.list = list
-	} catch {
-		console.log('获取列表数据失败')
-		tableOpts.total = 0
-		tableOpts.list = []
-		options.loading = false // 更改加载中的 loading值
-	} finally {
-		options.loading = false
-	}
-}
-
-// table 参数
-const columns = [
-	{
-		prop: 'processName',
-		label: '流程名称',
-		minWidth: 80
-	},
-	{
-		prop: 'currentNode',
-		label: '当前所在节点',
-		minWidth: 80,
-		slots: {
-			default: 'currentNodeSlot'
-		}
-	},
-	{
-		prop: 'instanceState',
-		label: '流程状态',
-		minWidth: 100,
-		slots: {
-			default: 'instanceStateSlot'
-		}
-	},
-	{
-		prop: 'createBy',
-		label: '发起人',
-		minWidth: 100
-	},
-	{
-		prop: 'createTime',
-		label: '发起时间',
-		minWidth: 126
-	},
-	{
-		prop: 'endTime',
-		label: '结束时间',
-		minWidth: 126
-	},
-	{
-		prop: 'duration',
-		label: '处理耗时',
-		minWidth: 100,
-		slots: {
-			default: 'durationSlot'
-		}
-	},
-	{
-		prop: 'expireTime',
-		label: '期望完成时间',
-		minWidth: 126
-	},
-	{
-		prop: 'action',
-		label: '操作',
-		width: 100,
-		fixed: 'right',
-		slots: {
-			default: 'actionSlot'
-		}
-	}
-]
-
-const { searchData, tableOpts, checkedColumns, activeColumns } = useTablePage(
-	{
-		options: {
-			showIndex: false
-		},
-		// 需要展示的列
-		columns,
-		// 控制列配置
-		columnsConfig: {
-			columns
-		}
-	},
-	{
-		queryList,
-		fetchImmediate: false
-	}
-)
-
-const openDetail = (row: any) => {
-	currentId.value = row.id
-	visibleDetail.value = true
-}
-
-nextTick(() => {
-	queryList()
-})
-
-watch(
-	() => route.query,
-	(newPath, oldPath) => {
-		if (JSON.stringify(newPath) !== '{}') {
-			nextTick(() => {
-				openDetail(newPath)
-			})
-		}
-	},
-	{ immediate: true }
-)
+<script setup>
+import ApprovalIndex from '../components/approvalIndex.vue'
+import { ref } from 'vue'
+/**
+ * pendingApproval 待审批
+ * myApplication 我的申请
+ * myReceived 我收到的
+ * pendingClaim 认领任务
+ * approved 已审批
+ */
+const taskType = ref('myApplication')
 </script>
-<style scoped lang="scss">
-.pageWrap {
-	flex: 1;
-	display: flex;
-	height: 100%;
-	min-height: 0;
-	//background-color: #fafafa;
-	background-color: var(--el-fill-color-lighter);
-	//background: #fff;
-}
-// 单独自己写的
-/*:deep(.box-card) {
-	height: 100%;
-	.el-card__body {
-		padding: 0;
-	}
-}*/
-
-// 应用的树结构样式
-:deep(.menu-tree) {
-	.el-tree-node__content {
-		height: 36px;
-	}
-	.el-tree-node__content .el-tree-node__label .icon {
-		margin-right: 5px;
-	}
-}
-
-.nopadding {
-	padding: 0px;
-}
-</style>

+ 1 - 0
src/views/approve/pendingApproval/detail.vue

@@ -1,3 +1,4 @@
+<!-- todo 无用页面 可以删除了-->
 <template>
 	<div>
 		<el-drawer v-model="visibleDialog" class="custom-adrawer" direction="rtl" size="900" @close="handleCancel">

+ 6 - 7
src/views/approve/pendingClaim/index1.vue → src/views/approve/pendingApproval/index-old.vue

@@ -14,7 +14,7 @@
 				:columns="activeColumns"
 			>
 				<template #toolLeft>
-					<el-button type="primary">操作认领任务</el-button>
+					<el-button type="primary">操作待审批</el-button>
 				</template>
 
 				<template #taskTypeSlot="scope">
@@ -36,20 +36,19 @@
 			</LeTable>
 		</div>
 
-		<message-detail v-if="visibleDetail" v-model="visibleDetail" :message-id="currentId" @closed="visibleDetail = false"> </message-detail>
+		<message-detail v-if="visibleDetail" v-model="visibleDetail" :task-obj="taskRow" @closed="visibleDetail = false"> </message-detail>
 	</div>
 </template>
 <script lang="tsx" setup>
-import { processTaskPagePendingClaimApi } from '@/api/flow/processTask'
+import { processTaskPagePendingApprovalApi } from '@/api/flow/processTask'
 import { nextTick, ref, watch } from 'vue'
 import { useTablePage } from '@/hooks/useTablePage'
 import MessageDetail from './detail.vue'
 import { useRoute } from 'vue-router'
-import InstanceDetail from "@/views/flow/instance/instance-detail.vue";
 const route = useRoute()
 
 const visibleDetail = ref(false) // 权限设置弹窗显示隐藏
-const currentId = ref(null)
+const taskRow = ref({}) // 当前这条数据详情
 
 // 表格搜索条件
 const forms = ref([
@@ -72,7 +71,7 @@ const queryList = async () => {
 	const { options, searchParams } = tableOpts
 	options.loading = true
 	try {
-		const { records: list, total } = await processTaskPagePendingClaimApi(searchParams)
+		const { records: list, total } = await processTaskPagePendingApprovalApi(searchParams)
 		tableOpts.total = total
 		tableOpts.list = list
 	} catch {
@@ -155,7 +154,7 @@ const { searchData, tableOpts, checkedColumns, activeColumns } = useTablePage(
 )
 
 const openDetail = (row: any) => {
-	currentId.value = row.id
+	taskRow.value = row || {}
 	visibleDetail.value = true
 }
 

+ 12 - 204
src/views/approve/pendingApproval/index.vue

@@ -1,208 +1,16 @@
 <template>
-	<div class="pageWrap flex-column-page-wrap">
-		<div class="flex-column-page-wrap">
-			<!-- 公用搜索组件 -->
-			<LeSearchForm ref="searchForm" v-model:searchData="searchData" :forms="forms" :loading="tableOpts.options.loading"> </LeSearchForm>
-
-			<!--  LeTable 组件使用  -->
-			<LeTable
-				ref="tableRef"
-				v-model:searchParams="tableOpts.searchParams"
-				v-bind="tableOpts"
-				v-model:curRow="tableOpts.curRow"
-				v-model:checked-options="checkedColumns"
-				:columns="activeColumns"
-			>
-				<template #toolLeft>
-					<el-button type="primary">操作待审批</el-button>
-				</template>
-
-				<template #taskTypeSlot="scope">
-					<el-tag v-if="scope.row.taskType === 0" effect="plain">主办</el-tag>
-					<el-tag v-if="scope.row.taskType === 1" type="success" effect="plain">转办</el-tag>
-					<el-tag v-if="scope.row.taskType === 2" type="info" effect="plain">委派</el-tag>
-					<el-tag v-if="scope.row.taskType === 3 && scope.row.performType === 1" type="info" effect="plain">会签</el-tag>
-					<el-tag v-if="scope.row.taskType === 3 && scope.row.performType === 2" type="warning" effect="plain">或签</el-tag>
-					<el-tag v-if="scope.row.taskType === 3 && scope.row.performType === 2" type="danger" effect="plain">票签</el-tag>
-				</template>
-
-				<template #actionSlot="scope">
-					<el-tooltip content="查看" placement="bottom" effect="light">
-						<el-icon class="ibt0" @click="openDetail(scope.row)">
-							<View />
-						</el-icon>
-					</el-tooltip>
-				</template>
-			</LeTable>
-		</div>
-
-		<message-detail v-if="visibleDetail" v-model="visibleDetail" :task-obj="taskRow" @closed="visibleDetail = false"> </message-detail>
-	</div>
+	<ApprovalIndex ref="pendingApproval" :current-task-type="taskType"></ApprovalIndex>
 </template>
-<script lang="tsx" setup>
-import { processTaskPagePendingApprovalApi } from '@/api/flow/processTask'
-import { nextTick, ref, watch } from 'vue'
-import { useTablePage } from '@/hooks/useTablePage'
-import MessageDetail from './detail.vue'
-import { useRoute } from 'vue-router'
-const route = useRoute()
-
-const visibleDetail = ref(false) // 权限设置弹窗显示隐藏
-const taskRow = ref({}) // 当前这条数据详情
-
-// 表格搜索条件
-const forms = ref([
-	{
-		prop: 'processName',
-		label: '流程名称:',
-		itemType: 'input',
-		placeholder: '请输入流程名称'
-	},
-	{
-		prop: 'createBy',
-		label: '发布人:',
-		itemType: 'input',
-		placeholder: '请输入发布人'
-	}
-])
-
-// table列表数据请求
-const queryList = async () => {
-	const { options, searchParams } = tableOpts
-	options.loading = true
-	try {
-		const { records: list, total } = await processTaskPagePendingApprovalApi(searchParams)
-		tableOpts.total = total
-		tableOpts.list = list
-	} catch {
-		console.log('获取列表数据失败')
-		tableOpts.total = 0
-		tableOpts.list = []
-		options.loading = false // 更改加载中的 loading值
-	} finally {
-		options.loading = false
-	}
-}
 
-// table 参数
-const columns = [
-	{
-		prop: 'processName',
-		label: '流程名称',
-		minWidth: 150
-	},
-	{
-		prop: 'launchBy',
-		label: '发起人',
-		minWidth: 100
-	},
-	{
-		prop: 'launchTime',
-		label: '发起时间',
-		minWidth: 150
-	},
-	{
-		prop: 'taskName',
-		label: '当前任务名称',
-		minWidth: 150
-	},
-	{
-		prop: 'taskType',
-		label: '任务类型',
-		minWidth: 100,
-		slots: {
-			default: 'taskTypeSlot'
-		}
-	},
-	{
-		prop: 'expireTime',
-		label: '期望任务完成时间',
-		minWidth: 150
-	},
-	{
-		prop: 'createTime',
-		label: '任务开始时间',
-		minWidth: 150
-	},
-	{
-		prop: 'action',
-		label: '操作',
-		width: 100,
-		fixed: 'right',
-		slots: {
-			default: 'actionSlot'
-		}
-	}
-]
-
-const { searchData, tableOpts, checkedColumns, activeColumns } = useTablePage(
-	{
-		options: {
-			showIndex: false
-		},
-		// 需要展示的列
-		columns,
-		// 控制列配置
-		columnsConfig: {
-			columns
-		}
-	},
-	{
-		queryList,
-		fetchImmediate: false
-	}
-)
-
-const openDetail = (row: any) => {
-	taskRow.value = row || {}
-	visibleDetail.value = true
-}
-
-nextTick(() => {
-	queryList()
-})
-
-watch(
-	() => route.query,
-	(newPath, oldPath) => {
-		if (JSON.stringify(newPath) !== '{}') {
-			nextTick(() => {
-				openDetail(newPath)
-			})
-		}
-	},
-	{ immediate: true }
-)
+<script setup>
+import ApprovalIndex from '../components/approvalIndex.vue'
+import { ref } from 'vue'
+/**
+ * pendingApproval 待审批
+ * myApplication 我的申请
+ * myReceived 我收到的
+ * pendingClaim 认领任务
+ * approved 已审批
+ */
+const taskType = ref('pendingApproval')
 </script>
-<style scoped lang="scss">
-.pageWrap {
-	flex: 1;
-	display: flex;
-	height: 100%;
-	min-height: 0;
-	//background-color: #fafafa;
-	background-color: var(--el-fill-color-lighter);
-	//background: #fff;
-}
-// 单独自己写的
-/*:deep(.box-card) {
-	height: 100%;
-	.el-card__body {
-		padding: 0;
-	}
-}*/
-
-// 应用的树结构样式
-:deep(.menu-tree) {
-	.el-tree-node__content {
-		height: 36px;
-	}
-	.el-tree-node__content .el-tree-node__label .icon {
-		margin-right: 5px;
-	}
-}
-
-.nopadding {
-	padding: 0px;
-}
-</style>

+ 195 - 22
src/views/approve/pendingClaim/index.vue

@@ -1,36 +1,209 @@
 <template>
-	<div class="flex-column-page-wrap flex-wrap">
-		<div class="warp-left">
-			<ApprovedItem />
-		</div>
+	<div class="pageWrap flex-column-page-wrap">
+		<div class="flex-column-page-wrap">
+			<!-- 公用搜索组件 -->
+			<LeSearchForm ref="searchForm" v-model:searchData="searchData" :forms="forms" :loading="tableOpts.options.loading"> </LeSearchForm>
+
+			<!--  LeTable 组件使用  -->
+			<LeTable
+				ref="tableRef"
+				v-model:searchParams="tableOpts.searchParams"
+				v-bind="tableOpts"
+				v-model:curRow="tableOpts.curRow"
+				v-model:checked-options="checkedColumns"
+				:columns="activeColumns"
+			>
+				<template #toolLeft>
+					<el-button type="primary">操作认领任务</el-button>
+				</template>
 
-		<div class="warp-right">
-			<ApprovedContent />
+				<template #taskTypeSlot="scope">
+					<el-tag v-if="scope.row.taskType === 0" effect="plain">主办</el-tag>
+					<el-tag v-if="scope.row.taskType === 1" type="success" effect="plain">转办</el-tag>
+					<el-tag v-if="scope.row.taskType === 2" type="info" effect="plain">委派</el-tag>
+					<el-tag v-if="scope.row.taskType === 3 && scope.row.performType === 1" type="info" effect="plain">会签</el-tag>
+					<el-tag v-if="scope.row.taskType === 3 && scope.row.performType === 2" type="warning" effect="plain">或签</el-tag>
+					<el-tag v-if="scope.row.taskType === 3 && scope.row.performType === 2" type="danger" effect="plain">票签</el-tag>
+				</template>
+
+				<template #actionSlot="scope">
+					<el-tooltip content="查看" placement="bottom" effect="light">
+						<el-icon class="ibt0" @click="openDetail(scope.row)">
+							<View />
+						</el-icon>
+					</el-tooltip>
+				</template>
+			</LeTable>
 		</div>
+
+		<message-detail v-if="visibleDetail" v-model="visibleDetail" :message-id="currentId" @closed="visibleDetail = false"> </message-detail>
 	</div>
 </template>
+<script lang="tsx" setup>
+import { processTaskPagePendingClaimApi } from '@/api/flow/processTask'
+import { nextTick, ref, watch } from 'vue'
+import { useTablePage } from '@/hooks/useTablePage'
+import MessageDetail from './detail.vue'
+import { useRoute } from 'vue-router'
+import InstanceDetail from "@/views/flow/instance/instance-detail.vue";
+const route = useRoute()
 
-<script setup>
-import ApprovedItem from '../components/approvedItem.vue'
-import ApprovedContent from '../components/approvedContent.vue'
-</script>
+const visibleDetail = ref(false) // 权限设置弹窗显示隐藏
+const currentId = ref(null)
+
+// 表格搜索条件
+const forms = ref([
+	{
+		prop: 'processName',
+		label: '流程名称:',
+		itemType: 'input',
+		placeholder: '请输入流程名称'
+	},
+	{
+		prop: 'createBy',
+		label: '发布人:',
+		itemType: 'input',
+		placeholder: '请输入发布人'
+	}
+])
+
+// table列表数据请求
+const queryList = async () => {
+	const { options, searchParams } = tableOpts
+	options.loading = true
+	try {
+		const { records: list, total } = await processTaskPagePendingClaimApi(searchParams)
+		tableOpts.total = total
+		tableOpts.list = list
+	} catch {
+		console.log('获取列表数据失败')
+		tableOpts.total = 0
+		tableOpts.list = []
+		options.loading = false // 更改加载中的 loading值
+	} finally {
+		options.loading = false
+	}
+}
+
+// table 参数
+const columns = [
+	{
+		prop: 'processName',
+		label: '流程名称',
+		minWidth: 150
+	},
+	{
+		prop: 'launchBy',
+		label: '发起人',
+		minWidth: 100
+	},
+	{
+		prop: 'launchTime',
+		label: '发起时间',
+		minWidth: 150
+	},
+	{
+		prop: 'taskName',
+		label: '当前任务名称',
+		minWidth: 150
+	},
+	{
+		prop: 'taskType',
+		label: '任务类型',
+		minWidth: 100,
+		slots: {
+			default: 'taskTypeSlot'
+		}
+	},
+	{
+		prop: 'expireTime',
+		label: '期望任务完成时间',
+		minWidth: 150
+	},
+	{
+		prop: 'createTime',
+		label: '任务开始时间',
+		minWidth: 150
+	},
+	{
+		prop: 'action',
+		label: '操作',
+		width: 100,
+		fixed: 'right',
+		slots: {
+			default: 'actionSlot'
+		}
+	}
+]
 
+const { searchData, tableOpts, checkedColumns, activeColumns } = useTablePage(
+	{
+		options: {
+			showIndex: false
+		},
+		// 需要展示的列
+		columns,
+		// 控制列配置
+		columnsConfig: {
+			columns
+		}
+	},
+	{
+		queryList,
+		fetchImmediate: false
+	}
+)
+
+const openDetail = (row: any) => {
+	currentId.value = row.id
+	visibleDetail.value = true
+}
+
+nextTick(() => {
+	queryList()
+})
+
+watch(
+	() => route.query,
+	(newPath, oldPath) => {
+		if (JSON.stringify(newPath) !== '{}') {
+			nextTick(() => {
+				openDetail(newPath)
+			})
+		}
+	},
+	{ immediate: true }
+)
+</script>
 <style scoped lang="scss">
-.flex-column-page-wrap.flex-wrap {
-	flex-direction: row;
-	background-color: #f2f3f5;
-	padding: 10px 10px 0 10px;
+.pageWrap {
+	flex: 1;
+	display: flex;
+	height: 100%;
+	min-height: 0;
+	//background-color: #fafafa;
+	background-color: var(--el-fill-color-lighter);
+	//background: #fff;
 }
+// 单独自己写的
+/*:deep(.box-card) {
+	height: 100%;
+	.el-card__body {
+		padding: 0;
+	}
+}*/
 
-.warp-left {
-	width: 330px; /*固定宽度*/
-	overflow: auto; /*超出部分滚动*/
-	background-color: var(--el-bg-color);
-	margin-right: 10px;
+// 应用的树结构样式
+:deep(.menu-tree) {
+	.el-tree-node__content {
+		height: 36px;
+	}
+	.el-tree-node__content .el-tree-node__label .icon {
+		margin-right: 5px;
+	}
 }
 
-.warp-right {
-	flex: 1; /*这里设置为占比1,填充满剩余空间*/
-	//border: 1px solid #ff4400;
+.nopadding {
+	padding: 0px;
 }
 </style>

+ 6 - 3
src/views/flow/group/components/listGroup.vue

@@ -51,8 +51,8 @@
 										<div class="group_itemIntro">{{ element.title }}</div>
 									</div>
 									<div class="group_itemSeeable">
-										<el-button type="primary" round>V{{ element.processVersion }}</el-button>
-										<el-button v-if="element.processState === 0" type="danger" round>已停用</el-button>
+										<el-tag type="primary" round>V{{ element.processVersion }}</el-tag>
+										<el-tag v-if="element.processState === 0" type="danger" round>已停用</el-tag>
 									</div>
 									<div class="group_itemSeeable">{{ element.processKey }}</div>
 									<div class="group_itemOperations">
@@ -305,7 +305,7 @@ defineExpose({
 		}
 		.group_item {
 			justify-content: flex-start;
-			padding: 12px;
+			padding: 8px 12px;
 			&:not(.group_item-disabled):hover {
 				background-color: var(--el-fill-color-lighter);
 			}
@@ -335,6 +335,9 @@ defineExpose({
 				text-overflow: ellipsis;
 				white-space: nowrap;
 				flex: 1 1;
+				.el-tag + .el-tag {
+					margin-left: 4px;
+				}
 			}
 			.group_itemOperations {
 				max-width: 350px;