Эх сурвалжийг харах

Merge branch 'feature/审批样式'

# Conflicts:
#	src/api/flow/processTask.ts
luoyali 1 жил өмнө
parent
commit
67562e8772

+ 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 '../index.vue'
+// import { FormConfigProps } from '../index1.vue'
 import { useI18n } from 'vue-i18n'
 import { OptionItemProps } from '@/components/Select/select.types.ts'
 export type FormType = 'FormConfig' | 'SearchForm'

+ 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/index.vue'
+// import RightPanel from '@/components/RightPanel/index1.vue'
 import LayoutLeft from './LayoutLeft/index.vue'
 import LayoutLeftMix from './LayoutLeftMix/index.vue'
 import LayoutTop from './LayoutTop/index.vue'

+ 15 - 15
src/router/index.ts

@@ -404,7 +404,7 @@ export const constantRoutes: AppRouteRecordRaw[] = [
 			},
 			{
 				path: 'componentCommunication',
-				component: () => import('@/views/test/componentCommunication/index.vue'),
+				component: () => import('@/views/test/componentCommunication/index1.vue'),
 				name: 'componentCommunication',
 				meta: { title: '组件通信方式' }
 			}
@@ -429,28 +429,28 @@ export const local_permissionsMenuList: Array<AppRouteRecordRaw> = [
 		children: [
 			{
 				path: 'user',
-				// component: () => import('@/views/setting/user/index.vue'),
+				// component: () => import('@/views/setting/user/index1.vue'),
 				component: 'setting/user/index',
 				name: 'user',
 				meta: { title: '用户管理', icon: 'icon-logo' } // 本地icon
 			},
 			{
 				path: 'role',
-				// component: () => import('@/views/setting/role/index.vue'),
+				// component: () => import('@/views/setting/role/index1.vue'),
 				component: 'setting/role/index',
 				name: 'role',
 				meta: { title: '角色管理', icon: 'le-amazon' } // le-iconfont
 			},
 			{
 				path: 'post',
-				// component: () => import('@/views/setting/post/index.vue'),
+				// component: () => import('@/views/setting/post/index1.vue'),
 				component: 'setting/post/index',
 				name: 'post',
 				meta: { title: '岗位管理', icon: '' }
 			},
 			{
 				path: 'app',
-				// component: () => import('@/views/setting/app/index.vue'),
+				// component: () => import('@/views/setting/app/index1.vue'),
 				component: 'setting/app/index',
 				name: 'app',
 				meta: { title: '应用管理', icon: '' }
@@ -458,28 +458,28 @@ export const local_permissionsMenuList: Array<AppRouteRecordRaw> = [
 
 			{
 				path: 'department',
-				// component: () => import('@/views/setting/department/index.vue'),
+				// component: () => import('@/views/setting/department/index1.vue'),
 				component: 'setting/department/index',
 				name: 'department',
 				meta: { title: '部门管理', icon: '' }
 			},
 			{
 				path: 'region',
-				// component: () => import('@/views/setting/region/index.vue'),
+				// component: () => import('@/views/setting/region/index1.vue'),
 				component: 'setting/region/index',
 				name: 'region',
 				meta: { title: '行政区域', icon: '' }
 			},
 			{
 				path: 'configure',
-				// component: () => import('@/views/setting/configure/index.vue'),
+				// component: () => import('@/views/setting/configure/index1.vue'),
 				component: 'setting/configure/index',
 				name: 'configure',
 				meta: { title: '扩展配置', icon: '' }
 			},
 			{
 				path: 'dict',
-				// component: () => import('@/views/setting/dict/index.vue'),
+				// component: () => import('@/views/setting/dict/index1.vue'),
 				component: 'setting/dict/index',
 				name: 'dict',
 				meta: { title: '字典管理', icon: '' }
@@ -510,42 +510,42 @@ export const local_permissionsMenuList: Array<AppRouteRecordRaw> = [
 			},
 			{
 				path: 'group',
-				// component: () => import('@/views/flow/group/index.vue'),
+				// component: () => import('@/views/flow/group/index1.vue'),
 				component: 'flow/group/index',
 				name: 'flow_group',
 				meta: { title: '流程组 - ui调整', icon: '' }
 			},
 			{
 				path: 'form',
-				// component: () => import('@/views/flow/form/index.vue'),
+				// component: () => import('@/views/flow/form/index1.vue'),
 				component: 'flow/form/index',
 				name: 'flow_form',
 				meta: { title: '流程表单', icon: '' }
 			},
 			{
 				path: 'create',
-				// component: () => import('@/views/flow/create/index.vue'),
+				// component: () => import('@/views/flow/create/index1.vue'),
 				component: 'flow/create/index',
 				name: 'flow_create',
 				meta: { title: '创建流程', icon: '' }
 			},
 			{
 				path: 'task',
-				// component: () => import('@/views/flow/task/index.vue'),
+				// component: () => import('@/views/flow/task/index1.vue'),
 				component: 'flow/task/index',
 				name: 'flow_task',
 				meta: { title: '流程任务', icon: '' }
 			},
 			{
 				path: 'instance',
-				// component: () => import('@/views/flow/instance/index.vue'),
+				// component: () => import('@/views/flow/instance/index1.vue'),
 				component: 'flow/instance/index',
 				name: 'flow_instance',
 				meta: { title: '流程实例', icon: '' }
 			},
 			{
 				path: 'modal',
-				// component: () => import('@/views/flow/modal/index.vue'),
+				// component: () => import('@/views/flow/modal/index1.vue'),
 				component: 'flow/modal/index',
 				name: 'flow_modal',
 				meta: { title: '流程模型', icon: '' }

+ 6 - 6
src/router/test_routes.ts

@@ -35,42 +35,42 @@ const routers = [
 			},
 			{
 				path: 'group',
-				// component: () => import('@/views/flow/group/index.vue'),
+				// component: () => import('@/views/flow/group/index1.vue'),
 				component: 'flow/group/index',
 				name: 'flow_group',
 				meta: { title: '流程组 - ui调整', icon: '' }
 			},
 			{
 				path: 'form',
-				// component: () => import('@/views/flow/form/index.vue'),
+				// component: () => import('@/views/flow/form/index1.vue'),
 				component: 'flow/form/index',
 				name: 'flow_form',
 				meta: { title: '流程表单', icon: '' }
 			},
 			{
 				path: 'create',
-				// component: () => import('@/views/flow/create/index.vue'),
+				// component: () => import('@/views/flow/create/index1.vue'),
 				component: 'flow/create/index',
 				name: 'flow_create',
 				meta: { title: '创建流程', icon: '' }
 			},
 			{
 				path: 'task',
-				// component: () => import('@/views/flow/task/index.vue'),
+				// component: () => import('@/views/flow/task/index1.vue'),
 				component: 'flow/task/index',
 				name: 'flow_task',
 				meta: { title: '流程任务', icon: '' }
 			},
 			{
 				path: 'instance',
-				// component: () => import('@/views/flow/instance/index.vue'),
+				// component: () => import('@/views/flow/instance/index1.vue'),
 				component: 'flow/instance/index',
 				name: 'flow_instance',
 				meta: { title: '流程实例', icon: '' }
 			},
 			{
 				path: 'modal',
-				// component: () => import('@/views/flow/modal/index.vue'),
+				// component: () => import('@/views/flow/modal/index1.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/index.vue'),
+					component: () => import('@/views/dashboard/index1.vue'),
 					name: 'dashboard',
 					meta: { title: 'dashboard', icon: 'icon-homepage', affix: true }
 				}

+ 395 - 0
src/views/approve/components/approvedContent.vue

@@ -0,0 +1,395 @@
+<template>
+	<div class="flow-detail-content">
+		<div class="flow-detail-container">
+			<!-- 值为空 -->
+			<div v-if="false" class="flow-empty-detail-box">
+				<el-empty description="暂无数据" />
+			</div>
+
+			<!-- 值不为空 -->
+			<template v-if="true">
+				<!-- 1、头部信息 -->
+				<div class="flow-status-stamp">
+					<div class="flow-stamp-container">
+						<FlowStatusStamp :status="0" />
+					</div>
+				</div>
+
+				<div class="flow-header-box">
+					<div class="flow-no">编号:1759387444983226369</div>
+					<div class="action-area">
+						<div class="action-item"></div>
+					</div>
+				</div>
+				<!-- 2、内容体 -->
+				<div class="flow-detail-box">
+					<!--头部-->
+					<div class="header-box">
+						<div class="summary-info">
+							<div class="title">{{ taskObj.processName }}</div>
+							<FlowStatusTag :status="0" />
+						</div>
+						<div class="initiator-info">
+							<FlowNodeAvatar id="1" />
+							<div class="begin-time">{{ taskObj.createTime }} 提交</div>
+						</div>
+					</div>
+					<div class="area-divider"></div>
+
+					<!-- 表单 -->
+					<div v-loading="validateForm.loading" class="form-wrap">
+						<FormCreate v-show="validateForm.rule.length" v-model:api="validateForm.api" :option="validateForm.option" :rule="validateForm.rule" />
+						<LeNoData v-if="!validateForm.rule.length" message="表单无数据" />
+					</div>
+
+					<div class="area-divider"></div>
+
+					<!--审批流-->
+					<el-timeline style="margin-left: 50px">
+						<el-timeline-item v-for="active in activeData" :key="active.id" hollow :timestamp="active.taskName" placement="top">
+							<template #dot>
+								<FlowTypeDot :status="active.taskState" :type="active.taskType" />
+							</template>
+
+							<div class="timeline-box flex-1">
+								<div class="flex flex-align-center">
+									<div class="timeline-box-user flex-1">
+										<FlowNodeAvatar id="1" />
+										<div class="comment">
+											<div class="comment-content">{{ active.duration }}</div>
+										</div>
+									</div>
+									<span class="timeline-box-date">{{ formatTimestamp(active.finishTime) }}</span>
+								</div>
+							</div>
+						</el-timeline-item>
+					</el-timeline>
+				</div>
+
+				<!-- 3、底部操作按钮 -->
+				<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>
+									<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>
+				</div>
+			</template>
+		</div>
+
+		<!-- 评论弹窗-->
+		<review-dialog v-if="reviewVisible" v-model="reviewVisible" :task-id="taskId"></review-dialog>
+
+		<!-- 加签弹窗 -->
+		<add-sign-dialog v-if="addSignVisible" v-model="addSignVisible" :task-id="taskId"></add-sign-dialog>
+
+		<!-- 同意或拒绝弹窗 -->
+		<consent-or-refuse-dialog
+			v-if="consentOrRefuseVisible"
+			v-model="consentOrRefuseVisible"
+			:task-id="taskId"
+			:current-type="currentDialog"
+		></consent-or-refuse-dialog>
+
+		<!-- 转交审批弹窗 -->
+		<deliver-to-review-dialog v-if="deliverToReviewVisible" v-model="deliverToReviewVisible" :task-id="taskId"></deliver-to-review-dialog>
+
+		<!-- 减签弹窗 -->
+		<lose-sign-dialog v-if="loseSignVisible" v-model="loseSignVisible" :task-id="taskId"></lose-sign-dialog>
+
+		<!-- 回退弹窗 -->
+		<rollback-dialog v-if="rollbackVisible" v-model="rollbackVisible" :task-id="taskId"></rollback-dialog>
+	</div>
+</template>
+
+<script setup>
+import { computed, ref, onMounted, nextTick } from 'vue'
+import FlowStatusStamp from '@/components/Flow/FlowStatusStamp.vue'
+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 { formatTimestamp } from '@/utils/datetime'
+import ReviewDialog from './reviewDialog'
+import AddSignDialog from './addSignDialog'
+import ConsentOrRefuseDialog from './consentOrRefuseDialog'
+import DeliverToReviewDialog from './deliverToReviewDialog'
+import LoseSignDialog from './loseSignDialog'
+import RollbackDialog from './rollbackDialog'
+import viewForm from '@/utils/form'
+
+const props = defineProps({
+	modelValue: {
+		type: Boolean,
+		default: false
+	},
+	taskObj: {
+		type: Object,
+		default: () => ({})
+	}
+})
+const emit = defineEmits(['update:modelValue', 'successFn'])
+
+// 各种操作弹窗显示隐藏 start
+const reviewVisible = ref(false)
+const addSignVisible = ref(false)
+const consentOrRefuseVisible = ref(false)
+const deliverToReviewVisible = ref(false)
+const loseSignVisible = ref(false)
+const rollbackVisible = ref(false)
+// 各种操作弹窗显示隐藏 end
+const activeData = ref([])
+const currentDialog = ref(null)
+
+const visibleDialog = computed({
+	get() {
+		return props.modelValue
+	},
+	set(val) {
+		emit('update:modelValue', val)
+	}
+})
+
+const taskId = computed(() => {
+	return props.taskObj.taskId || ''
+})
+const FormCreate = viewForm.$form()
+const validateForm = ref({
+	api: {},
+	option: {
+		submitBtn: false
+	},
+	rule: [],
+	loading: false
+})
+
+// 关闭按钮
+const closeDrawer = () => {
+	emit('successFn')
+	emit('update:modelValue', false)
+}
+
+const handleCancel = () => {
+	closeDrawer()
+}
+
+// 操作按钮
+const openComment = (type, item) => {
+	switch (type) {
+		case 'reviewVisible':
+			reviewVisible.value = !reviewVisible.value
+			break
+		case 'addSignVisible':
+			addSignVisible.value = !addSignVisible.value
+			break
+		case 'consentOrRefuseVisible':
+			// 点击同意
+			if (item === 'agree') {
+				debugger
+				// 验证表单 todo...
+				const api = validateForm.value.api
+				api.validate((valid, fail) => {
+					if (valid) {
+						const values = api.formData()
+						console.warn(values, 'values')
+						//todo 表单验证通过
+					} else {
+						//todo 表单验证未通过
+					}
+				})
+				// return
+			}
+			currentDialog.value = item
+			consentOrRefuseVisible.value = !consentOrRefuseVisible.value
+			break
+		case 'deliverToReviewVisible':
+			deliverToReviewVisible.value = !deliverToReviewVisible.value
+			break
+		case 'loseSignVisible':
+			loseSignVisible.value = !loseSignVisible.value
+			break
+		case 'rollbackVisible':
+			rollbackVisible.value = !rollbackVisible.value
+			break
+	}
+}
+
+nextTick(() => {
+	const cur = props.taskObj || {}
+	processApprovalInfoApi(cur.taskId).then(data => {
+		// console.log(JSON.stringify(data))
+		activeData.value = data
+	})
+	// 提交的表单 数据展示
+	validateForm.value.loading = true
+	processTaskApprovalInfo(cur.taskId)
+		.then(data => {
+			console.log(data, 'data.......')
+			// validateForm.value.origin = data
+			try {
+				/*descItemsData.value.list = JSON.parse(data.formContent).map(item => {
+					const showLabel = item.title
+					let showValue = item.local_value
+					const options = item.options
+					if (Array.isArray(options) && showValue !== undefined) {
+						if (Array.isArray(showValue)) {
+							showValue = showValue.reduce(val => {
+								const cur = options.find(option => option.value === val)
+								return cur?.label || val
+							}, [])
+						} else {
+							const cur = options.find(option => option.value === showValue)
+							showValue = cur?.label || showValue
+						}
+					}
+					return {
+						showLabel,
+						showValue
+					}
+				})*/
+				const forms = JSON.parse(data.formContent)
+				if (Array.isArray(forms)) {
+					validateForm.value.rule = forms
+					const api = validateForm.value.api
+					api.setValue(
+						forms.reduce((obj, item) => {
+							obj[item.field] = item.local_value
+							return obj
+						}, {})
+					)
+					api.nextTick(() => {
+						// 是否有编辑权限 操作
+						api.disabled(false /*true*/)
+					})
+				}
+			} catch (e) {
+				console.error('解析 descItems 数据出现问题', e)
+				// descItemsData.value.list = []
+				validateForm.value.rule = []
+			}
+		})
+		.finally(() => {
+			validateForm.value.loading = false
+		})
+})
+</script>
+
+<style scoped lang="scss">
+.flow-detail-content {
+	height: 100%;
+	overflow: hidden;
+	background: #fff;
+	border-radius: 6px;
+	flex: auto;
+	.flow-detail-container {
+		height: 100%;
+		overflow: hidden;
+		position: relative;
+	}
+
+	// 通过、不通过样式
+	.flow-status-stamp {
+		position: absolute;
+		right: 30px;
+		top: 30px;
+	}
+
+	// 头部
+	.flow-header-box {
+		font-weight: 400;
+		font-size: 13px;
+		border-bottom: 1px solid #e5e6ec;
+		padding: 0 20px;
+		height: 39px;
+		display: flex;
+		align-items: center;
+		justify-content: space-between;
+		color: #86909c;
+		.action-area {
+			display: flex;
+			gap: 4px;
+			.action-item {
+				cursor: pointer;
+				padding: 4px;
+				border-radius: 6px;
+				width: fit-content;
+				height: fit-content;
+			}
+		}
+	}
+
+	// 内容体
+	.flow-detail-box {
+		height: calc(100% - 92px);
+		overflow: hidden;
+		overflow-y: auto;
+		padding: 0 20px;
+
+		.header-box {
+			display: flex;
+			flex-direction: column;
+			justify-content: center;
+			// padding-top: 20px;
+			.summary-info {
+				display: flex;
+				align-items: center;
+				.title {
+					font-size: 24px;
+					font-family: PingFangSC-Semibold, PingFang SC;
+					color: #1d2129;
+				}
+			}
+			.initiator-info {
+				display: flex;
+				align-items: center;
+				margin-top: 16px;
+				.begin-time {
+					margin-left: 16px;
+					font-weight: 350;
+					color: #86909c;
+					font-size: 13px;
+					-webkit-user-select: none;
+					user-select: none;
+				}
+			}
+		}
+		.area-divider {
+			border-bottom: 1px solid rgba(229, 230, 235, 1);
+			margin: 20px 0;
+			position: relative;
+		}
+	}
+
+	// 底部
+	.flow-actions {
+		display: flex;
+		align-items: center;
+		justify-content: end;
+		height: 52px;
+		border-top: 1px solid var(--color-neutral-3);
+		padding: 0 20px;
+	}
+}
+</style>

+ 142 - 0
src/views/approve/components/approvedItem.vue

@@ -0,0 +1,142 @@
+<template>
+	<!-- 左侧列表 -->
+	<div class="flow-content">
+		<!-- 搜索条件 -->
+		<div class="search-box">
+			<div class="search-segment" style="flex: 1 1 0%">
+				<el-input v-model="input3" placeholder="流程名称">
+					<template #append>
+						<el-button :icon="Search" />
+					</template>
+				</el-input>
+			</div>
+			<div class="search-segment">
+				<el-tooltip effect="dark" content="重置" placement="top">
+					<el-button :icon="Refresh" />
+				</el-tooltip>
+			</div>
+			<div class="search-segment">
+				<el-button :icon="Filter" />
+			</div>
+		</div>
+		<!-- 内容值 -->
+		<div v-infinite-scroll="load" class="flow-list-box">
+			<div v-for="i in count" :key="i" class="item-box" :class="[i === 2 ? 'item-box-choosed' : '']">
+				<div class="flow-card-box flow-card-box-hoverable">
+					<!--头部-->
+					<div class="header">
+						<el-text tag="b">我是Bold {{ i }}</el-text>
+						<el-tag type="primary">待审核</el-tag>
+					</div>
+					<!--操作类容-->
+					<div class="summary-list"></div>
+					<!--底部-->
+					<div class="footer">
+						<!-- 头像 -->
+						<div class="initiator">
+							<FlowNodeAvatar id="1" />
+						</div>
+						<!-- 时间 -->
+						<div class="begin-time">提交于 2024-02-29 15:30:23</div>
+					</div>
+				</div>
+			</div>
+		</div>
+	</div>
+</template>
+
+<script setup>
+import FlowNodeAvatar from '@/components/Flow/FlowNodeAvatar.vue'
+import { Search, Filter, Refresh } from '@element-plus/icons-vue'
+
+import { ref } from 'vue'
+const count = ref(0)
+const load = () => {
+	count.value += 2
+}
+</script>
+
+<style scoped lang="scss">
+.flow-content {
+	width: 330px;
+	min-width: 330px;
+	height: 100%;
+	overflow: hidden;
+	background: var(--el-bg-color);
+	border-radius: 6px;
+
+	// 搜搜条件
+	.search-box {
+		display: flex;
+		align-items: center;
+		height: 56px;
+		padding: 0 12px;
+
+		.search-segment + .search-segment {
+			margin-left: 4px;
+		}
+		//> .el-button {
+		//	padding: 0;
+		//	width: 32px;
+		//	background-color: var(--el-fill-color-light);
+		//}
+	}
+
+	.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;
+			&.item-box-choosed {
+				.flow-card-box {
+					border-color: var(--el-color-primary);
+				}
+			}
+		}
+		.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);
+
+			&.flow-card-box-hoverable {
+				&:hover {
+					box-shadow: 4px 4px 12px rgb(229, 230, 235);
+				}
+			}
+
+			// 头部
+			.header {
+				display: flex;
+				align-items: center;
+				justify-content: space-between;
+			}
+
+			// 操作类容
+			.summary-list {
+				margin-top: 10px;
+			}
+
+			// 底部
+			.footer {
+				margin-top: 10px;
+				display: flex;
+				align-items: center;
+				justify-content: space-between;
+				font-size: 13px;
+				.begin-time {
+					color: var(--el-text-color-regular);
+				}
+			}
+		}
+	}
+}
+</style>

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

@@ -1,209 +1,36 @@
 <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 class="flex-column-page-wrap flex-wrap">
+		<div class="warp-left">
+			<ApprovedItem />
 		</div>
 
-		<message-detail v-if="visibleDetail" v-model="visibleDetail" :message-id="currentId" @closed="visibleDetail = false"> </message-detail>
+		<div class="warp-right">
+			<ApprovedContent />
+		</div>
 	</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()
-
-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 setup>
+import ApprovedItem from '../components/approvedItem.vue'
+import ApprovedContent from '../components/approvedContent.vue'
 </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;
+.flex-column-page-wrap.flex-wrap {
+	flex-direction: row;
+	background-color: #f2f3f5;
+	padding: 10px 10px 0 10px;
 }
-// 单独自己写的
-/*: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;
-	}
+.warp-left {
+	width: 330px; /*固定宽度*/
+	overflow: auto; /*超出部分滚动*/
+	background-color: var(--el-bg-color);
+	margin-right: 10px;
 }
 
-.nopadding {
-	padding: 0px;
+.warp-right {
+	flex: 1; /*这里设置为占比1,填充满剩余空间*/
+	//border: 1px solid #ff4400;
 }
 </style>

+ 209 - 0
src/views/approve/pendingClaim/index1.vue

@@ -0,0 +1,209 @@
+<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" :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()
+
+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">
+.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>