Bläddra i källkod

新增流程任务列表

hubin 1 år sedan
förälder
incheckning
5c38b1895a

+ 61 - 0
src/api/flow/processTask.ts

@@ -0,0 +1,61 @@
+import request from '@/utils/request'
+import { AxiosPromise } from 'axios'
+
+// apiUrl
+const api = {
+	pagePendingClaim: '/v1/process-task/page-pending-claim',
+	pagePendingApproval: '/v1/process-task/page-pending-approval',
+	pageMyReceived: '/v1/process-task/page-my-received',
+	pageMyApplication: '/v1/process-task/page-my-application',
+	pageApproved: '/v1/process-task/page-approved'
+}
+
+// 待认领任务分页列表
+export function processTaskPagePendingClaimApi(data: any): AxiosPromise {
+	return request({
+		url: api.pagePendingClaim,
+		method: 'post',
+		data
+	})
+}
+
+// 待审批任务分页列表
+export function processTaskPagePendingApprovalApi(data: any): AxiosPromise {
+	return request({
+		url: api.pagePendingApproval,
+		method: 'post',
+		data
+	})
+}
+
+// 我收到的任务分页列表
+export function processTaskPageMyReceivedApi(data: any): AxiosPromise {
+	return request({
+		url: api.pageMyReceived,
+		method: 'post',
+		data
+	})
+}
+
+// 我的申请任务分页列表
+export function processTaskPageMyApplicationApi(data: any): AxiosPromise {
+	return request({
+		url: api.pageMyApplication,
+		method: 'post',
+		data
+	})
+}
+
+// 已审批任务分页列表
+export function processTaskPageApprovedApi(data: any): AxiosPromise {
+	return request({
+		url: api.pageApproved,
+		method: 'post',
+		data
+	})
+}
+
+export default {
+	processTaskPageMyApplicationApi,
+	processTaskPageApprovedApi
+}

+ 79 - 0
src/views/approve/approved/detail.vue

@@ -0,0 +1,79 @@
+<template>
+	<el-dialog class="le-dialog" v-model="visibleDialog" title="查看详情" @close="handleCancel">
+		<div>
+			<!--title-->
+			<div>
+				<div class="content-title">{{ formOptions.title }}</div>
+				<span>发布人:{{ formOptions.createBy }} 发布时间: {{ formOptions.createTime }}</span>
+
+				<div class="content-title mbt20">
+					<el-tag v-if="formOptions.category === 0" size="small" effect="plain">通知公告</el-tag>
+					<el-tag v-if="formOptions.category === 1" size="small" type="info" effect="plain">系统消息</el-tag>
+					<el-tag v-if="formOptions.category === 2" size="small" type="warning" effect="plain">待办通知</el-tag>
+				</div>
+				<span>通知时间: - </span>
+				<br />
+				<br />
+				<span>通知内容:{{ formOptions.content }}</span>
+			</div>
+			<!--content-->
+		</div>
+	</el-dialog>
+</template>
+
+<script setup>
+import { computed, ref } from 'vue'
+import { getMessageInfoById } from '@/api/system/message'
+
+// 同步值
+const $myEmit = defineEmits(['update:modelValue'])
+
+const myProps = defineProps({
+	modelValue: {
+		type: Boolean,
+		default: false
+	},
+	messageId: {
+		type: String,
+		default: null
+	}
+})
+
+const formOptions = ref({})
+const handleCancel = () => {
+	$myEmit('update:modelValue', false)
+}
+
+const getMessageInfoDetail = async () => {
+	const { messageId } = myProps
+	const res = await getMessageInfoById(messageId)
+	formOptions.value = res
+}
+
+getMessageInfoDetail()
+
+// computed
+const visibleDialog = computed({
+	get() {
+		return myProps.modelValue
+	},
+	set(val) {
+		$myEmit('update:modelValue', val)
+	}
+})
+</script>
+
+<style scoped lang="scss">
+.content-title {
+	overflow: hidden;
+	color: #000000d9;
+	font-weight: 500;
+	font-size: 16px;
+	white-space: nowrap;
+	text-overflow: ellipsis;
+	margin-bottom: 20px;
+	&.mbt20 {
+		margin-top: 20px;
+	}
+}
+</style>

+ 189 - 0
src/views/approve/approved/index.vue

@@ -0,0 +1,189 @@
+<template>
+	<div class="pageWrap">
+		<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 #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 === 2" size="small" type="warning" 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 === 2" size="small" type="warning" effect="plain">强制终止</el-tag>
+				</template>
+
+				<template #actionSlot="scope">
+					<el-link type="primary" @click="openDetail(scope.row)">查看</el-link>
+				</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 { processTaskPageApprovedApi } 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 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 processTaskPageApprovedApi(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: 'instanceState',
+		label: '流程状态',
+		minWidth: 100,
+		slots: {
+			default: 'instanceStateSlot'
+		}
+	},
+	{
+		prop: 'createBy',
+		label: '发布人',
+		minWidth: 100
+	},
+	{
+		prop: 'createTime',
+		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>

+ 79 - 0
src/views/approve/myApplication/detail.vue

@@ -0,0 +1,79 @@
+<template>
+	<el-dialog class="le-dialog" v-model="visibleDialog" title="查看详情" @close="handleCancel">
+		<div>
+			<!--title-->
+			<div>
+				<div class="content-title">{{ formOptions.title }}</div>
+				<span>发布人:{{ formOptions.createBy }} 发布时间: {{ formOptions.createTime }}</span>
+
+				<div class="content-title mbt20">
+					<el-tag v-if="formOptions.category === 0" size="small" effect="plain">通知公告</el-tag>
+					<el-tag v-if="formOptions.category === 1" size="small" type="info" effect="plain">系统消息</el-tag>
+					<el-tag v-if="formOptions.category === 2" size="small" type="warning" effect="plain">待办通知</el-tag>
+				</div>
+				<span>通知时间: - </span>
+				<br />
+				<br />
+				<span>通知内容:{{ formOptions.content }}</span>
+			</div>
+			<!--content-->
+		</div>
+	</el-dialog>
+</template>
+
+<script setup>
+import { computed, ref } from 'vue'
+import { getMessageInfoById } from '@/api/system/message'
+
+// 同步值
+const $myEmit = defineEmits(['update:modelValue'])
+
+const myProps = defineProps({
+	modelValue: {
+		type: Boolean,
+		default: false
+	},
+	messageId: {
+		type: String,
+		default: null
+	}
+})
+
+const formOptions = ref({})
+const handleCancel = () => {
+	$myEmit('update:modelValue', false)
+}
+
+const getMessageInfoDetail = async () => {
+	const { messageId } = myProps
+	const res = await getMessageInfoById(messageId)
+	formOptions.value = res
+}
+
+getMessageInfoDetail()
+
+// computed
+const visibleDialog = computed({
+	get() {
+		return myProps.modelValue
+	},
+	set(val) {
+		$myEmit('update:modelValue', val)
+	}
+})
+</script>
+
+<style scoped lang="scss">
+.content-title {
+	overflow: hidden;
+	color: #000000d9;
+	font-weight: 500;
+	font-size: 16px;
+	white-space: nowrap;
+	text-overflow: ellipsis;
+	margin-bottom: 20px;
+	&.mbt20 {
+		margin-top: 20px;
+	}
+}
+</style>

+ 189 - 0
src/views/approve/myApplication/index.vue

@@ -0,0 +1,189 @@
+<template>
+	<div class="pageWrap">
+		<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 #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 === 2" size="small" type="warning" 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 === 2" size="small" type="warning" effect="plain">强制终止</el-tag>
+				</template>
+
+				<template #actionSlot="scope">
+					<el-link type="primary" @click="openDetail(scope.row)">查看</el-link>
+				</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 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: 'instanceState',
+		label: '流程状态',
+		minWidth: 100,
+		slots: {
+			default: 'instanceStateSlot'
+		}
+	},
+	{
+		prop: 'createBy',
+		label: '发布人',
+		minWidth: 100
+	},
+	{
+		prop: 'createTime',
+		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>

+ 79 - 0
src/views/approve/myReceived/detail.vue

@@ -0,0 +1,79 @@
+<template>
+	<el-dialog class="le-dialog" v-model="visibleDialog" title="查看详情" @close="handleCancel">
+		<div>
+			<!--title-->
+			<div>
+				<div class="content-title">{{ formOptions.title }}</div>
+				<span>发布人:{{ formOptions.createBy }} 发布时间: {{ formOptions.createTime }}</span>
+
+				<div class="content-title mbt20">
+					<el-tag v-if="formOptions.category === 0" size="small" effect="plain">通知公告</el-tag>
+					<el-tag v-if="formOptions.category === 1" size="small" type="info" effect="plain">系统消息</el-tag>
+					<el-tag v-if="formOptions.category === 2" size="small" type="warning" effect="plain">待办通知</el-tag>
+				</div>
+				<span>通知时间: - </span>
+				<br />
+				<br />
+				<span>通知内容:{{ formOptions.content }}</span>
+			</div>
+			<!--content-->
+		</div>
+	</el-dialog>
+</template>
+
+<script setup>
+import { computed, ref } from 'vue'
+import { getMessageInfoById } from '@/api/system/message'
+
+// 同步值
+const $myEmit = defineEmits(['update:modelValue'])
+
+const myProps = defineProps({
+	modelValue: {
+		type: Boolean,
+		default: false
+	},
+	messageId: {
+		type: String,
+		default: null
+	}
+})
+
+const formOptions = ref({})
+const handleCancel = () => {
+	$myEmit('update:modelValue', false)
+}
+
+const getMessageInfoDetail = async () => {
+	const { messageId } = myProps
+	const res = await getMessageInfoById(messageId)
+	formOptions.value = res
+}
+
+getMessageInfoDetail()
+
+// computed
+const visibleDialog = computed({
+	get() {
+		return myProps.modelValue
+	},
+	set(val) {
+		$myEmit('update:modelValue', val)
+	}
+})
+</script>
+
+<style scoped lang="scss">
+.content-title {
+	overflow: hidden;
+	color: #000000d9;
+	font-weight: 500;
+	font-size: 16px;
+	white-space: nowrap;
+	text-overflow: ellipsis;
+	margin-bottom: 20px;
+	&.mbt20 {
+		margin-top: 20px;
+	}
+}
+</style>

+ 189 - 0
src/views/approve/myReceived/index.vue

@@ -0,0 +1,189 @@
+<template>
+	<div class="pageWrap">
+		<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 #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 === 2" size="small" type="warning" 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 === 2" size="small" type="warning" effect="plain">强制终止</el-tag>
+				</template>
+
+				<template #actionSlot="scope">
+					<el-link type="primary" @click="openDetail(scope.row)">查看</el-link>
+				</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 { processTaskPageMyReceivedApi } 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 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 processTaskPageMyReceivedApi(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: 'instanceState',
+		label: '流程状态',
+		minWidth: 100,
+		slots: {
+			default: 'instanceStateSlot'
+		}
+	},
+	{
+		prop: 'createBy',
+		label: '发布人',
+		minWidth: 100
+	},
+	{
+		prop: 'createTime',
+		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>

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

@@ -0,0 +1,79 @@
+<template>
+	<el-dialog class="le-dialog" v-model="visibleDialog" title="查看详情" @close="handleCancel">
+		<div>
+			<!--title-->
+			<div>
+				<div class="content-title">{{ formOptions.title }}</div>
+				<span>发布人:{{ formOptions.createBy }} 发布时间: {{ formOptions.createTime }}</span>
+
+				<div class="content-title mbt20">
+					<el-tag v-if="formOptions.category === 0" size="small" effect="plain">通知公告</el-tag>
+					<el-tag v-if="formOptions.category === 1" size="small" type="info" effect="plain">系统消息</el-tag>
+					<el-tag v-if="formOptions.category === 2" size="small" type="warning" effect="plain">待办通知</el-tag>
+				</div>
+				<span>通知时间: - </span>
+				<br />
+				<br />
+				<span>通知内容:{{ formOptions.content }}</span>
+			</div>
+			<!--content-->
+		</div>
+	</el-dialog>
+</template>
+
+<script setup>
+import { computed, ref } from 'vue'
+import { getMessageInfoById } from '@/api/system/message'
+
+// 同步值
+const $myEmit = defineEmits(['update:modelValue'])
+
+const myProps = defineProps({
+	modelValue: {
+		type: Boolean,
+		default: false
+	},
+	messageId: {
+		type: String,
+		default: null
+	}
+})
+
+const formOptions = ref({})
+const handleCancel = () => {
+	$myEmit('update:modelValue', false)
+}
+
+const getMessageInfoDetail = async () => {
+	const { messageId } = myProps
+	const res = await getMessageInfoById(messageId)
+	formOptions.value = res
+}
+
+getMessageInfoDetail()
+
+// computed
+const visibleDialog = computed({
+	get() {
+		return myProps.modelValue
+	},
+	set(val) {
+		$myEmit('update:modelValue', val)
+	}
+})
+</script>
+
+<style scoped lang="scss">
+.content-title {
+	overflow: hidden;
+	color: #000000d9;
+	font-weight: 500;
+	font-size: 16px;
+	white-space: nowrap;
+	text-overflow: ellipsis;
+	margin-bottom: 20px;
+	&.mbt20 {
+		margin-top: 20px;
+	}
+}
+</style>

+ 189 - 0
src/views/approve/pendingApproval/index.vue

@@ -0,0 +1,189 @@
+<template>
+	<div class="pageWrap">
+		<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 #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 === 2" size="small" type="warning" 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 === 2" size="small" type="warning" effect="plain">强制终止</el-tag>
+				</template>
+
+				<template #actionSlot="scope">
+					<el-link type="primary" @click="openDetail(scope.row)">查看</el-link>
+				</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 { 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 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 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: 80
+	},
+	{
+		prop: 'instanceState',
+		label: '流程状态',
+		minWidth: 100,
+		slots: {
+			default: 'instanceStateSlot'
+		}
+	},
+	{
+		prop: 'createBy',
+		label: '发布人',
+		minWidth: 100
+	},
+	{
+		prop: 'createTime',
+		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>

+ 79 - 0
src/views/approve/pendingClaim/detail.vue

@@ -0,0 +1,79 @@
+<template>
+	<el-dialog class="le-dialog" v-model="visibleDialog" title="查看详情" @close="handleCancel">
+		<div>
+			<!--title-->
+			<div>
+				<div class="content-title">{{ formOptions.title }}</div>
+				<span>发布人:{{ formOptions.createBy }} 发布时间: {{ formOptions.createTime }}</span>
+
+				<div class="content-title mbt20">
+					<el-tag v-if="formOptions.category === 0" size="small" effect="plain">通知公告</el-tag>
+					<el-tag v-if="formOptions.category === 1" size="small" type="info" effect="plain">系统消息</el-tag>
+					<el-tag v-if="formOptions.category === 2" size="small" type="warning" effect="plain">待办通知</el-tag>
+				</div>
+				<span>通知时间: - </span>
+				<br />
+				<br />
+				<span>通知内容:{{ formOptions.content }}</span>
+			</div>
+			<!--content-->
+		</div>
+	</el-dialog>
+</template>
+
+<script setup>
+import { computed, ref } from 'vue'
+import { getMessageInfoById } from '@/api/system/message'
+
+// 同步值
+const $myEmit = defineEmits(['update:modelValue'])
+
+const myProps = defineProps({
+	modelValue: {
+		type: Boolean,
+		default: false
+	},
+	messageId: {
+		type: String,
+		default: null
+	}
+})
+
+const formOptions = ref({})
+const handleCancel = () => {
+	$myEmit('update:modelValue', false)
+}
+
+const getMessageInfoDetail = async () => {
+	const { messageId } = myProps
+	const res = await getMessageInfoById(messageId)
+	formOptions.value = res
+}
+
+getMessageInfoDetail()
+
+// computed
+const visibleDialog = computed({
+	get() {
+		return myProps.modelValue
+	},
+	set(val) {
+		$myEmit('update:modelValue', val)
+	}
+})
+</script>
+
+<style scoped lang="scss">
+.content-title {
+	overflow: hidden;
+	color: #000000d9;
+	font-weight: 500;
+	font-size: 16px;
+	white-space: nowrap;
+	text-overflow: ellipsis;
+	margin-bottom: 20px;
+	&.mbt20 {
+		margin-top: 20px;
+	}
+}
+</style>

+ 189 - 0
src/views/approve/pendingClaim/index.vue

@@ -0,0 +1,189 @@
+<template>
+	<div class="pageWrap">
+		<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 #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 === 2" size="small" type="warning" 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 === 2" size="small" type="warning" effect="plain">强制终止</el-tag>
+				</template>
+
+				<template #actionSlot="scope">
+					<el-link type="primary" @click="openDetail(scope.row)">查看</el-link>
+				</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'
+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: 80
+	},
+	{
+		prop: 'instanceState',
+		label: '流程状态',
+		minWidth: 100,
+		slots: {
+			default: 'instanceStateSlot'
+		}
+	},
+	{
+		prop: 'createBy',
+		label: '发布人',
+		minWidth: 100
+	},
+	{
+		prop: 'createTime',
+		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>

+ 186 - 0
src/views/message/list/my.vue

@@ -0,0 +1,186 @@
+<template>
+	<div class="pageWrap">
+		<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 #categorySlot="scope">
+					<el-tag v-if="scope.row.category === 0" size="small" effect="plain">通知公告</el-tag>
+					<el-tag v-if="scope.row.category === 1" size="small" type="info" effect="plain">系统消息</el-tag>
+					<el-tag v-if="scope.row.category === 2" size="small" type="warning" effect="plain">待办通知</el-tag>
+				</template>
+
+				<template #actionSlot="scope">
+					<el-link type="primary" @click="openDetail(scope.row)">查看</el-link>
+				</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 { getMessageInfo } from '@/api/system/message'
+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 currentId = ref(null)
+
+// 表格搜索条件
+const forms = ref([
+	{
+		prop: 'title',
+		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 getMessageInfo(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: 'title',
+		label: '标题',
+		minWidth: 80
+	},
+	{
+		prop: 'category',
+		label: '消息类型',
+		minWidth: 100,
+		slots: {
+			default: 'categorySlot'
+		}
+	},
+	{
+		prop: 'createBy',
+		label: '发布人',
+		minWidth: 100
+	},
+	{
+		prop: 'createTime',
+		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>