增加验收页面
parent
52e22970bc
commit
c66abdf33e
2
.env.dev
2
.env.dev
|
|
@ -4,7 +4,7 @@ NODE_ENV=production
|
|||
VITE_DEV=true
|
||||
|
||||
# 请求路径
|
||||
VITE_BASE_URL='http://api-dashboard.yudao.iocoder.cn'
|
||||
VITE_BASE_URL='http://127.0.0.1:48080'
|
||||
|
||||
# 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持S3服务
|
||||
VITE_UPLOAD_TYPE=server
|
||||
|
|
|
|||
13403
pnpm-lock.yaml
13403
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,161 @@
|
|||
import request from '@/config/axios'
|
||||
|
||||
// 验收实例 VO
|
||||
export interface AcceptanceVO {
|
||||
id: number
|
||||
projectId: number
|
||||
acceptanceType: string
|
||||
processInstanceId: string
|
||||
status: string
|
||||
round: number
|
||||
startTime: Date
|
||||
endTime: Date
|
||||
createTime: Date
|
||||
}
|
||||
|
||||
// 验收待办 VO
|
||||
export interface AcceptanceTodoVO {
|
||||
acceptanceId: number
|
||||
projectId: number
|
||||
projectName: string
|
||||
projectCode: string
|
||||
acceptanceType: string
|
||||
status: string
|
||||
statusDesc: string
|
||||
round: number
|
||||
taskType: string
|
||||
taskTypeDesc: string
|
||||
createTime: Date
|
||||
processInstanceId: string
|
||||
taskId: string
|
||||
taskName: string
|
||||
}
|
||||
|
||||
// 提交预验收申请请求 VO
|
||||
export interface AcceptanceSubmitPreReqVO {
|
||||
projectId: number
|
||||
serviceUserId?: number
|
||||
liaisonUserId?: number
|
||||
leaderUserId: number
|
||||
}
|
||||
|
||||
// 审核请求 VO
|
||||
export interface AcceptanceAuditReqVO {
|
||||
acceptanceId: number
|
||||
result: string
|
||||
opinion: string
|
||||
signatureUrl?: string
|
||||
}
|
||||
|
||||
// 整改审核请求 VO
|
||||
export interface AcceptanceRectifyAuditReqVO {
|
||||
acceptanceId: number
|
||||
result: string
|
||||
opinion: string
|
||||
rectifyDeadline?: Date
|
||||
signatureUrl?: string
|
||||
}
|
||||
|
||||
// 提交终验申请请求 VO
|
||||
export interface AcceptanceSubmitFinalReqVO {
|
||||
acceptanceId: number
|
||||
}
|
||||
|
||||
// ==================== 基础 CRUD ====================
|
||||
|
||||
// 查询验收实例分页
|
||||
export const getAcceptancePage = (params: any) => {
|
||||
return request.get({ url: '/project/acceptance/page', params })
|
||||
}
|
||||
|
||||
// 查询验收实例详情
|
||||
export const getAcceptance = (id: number) => {
|
||||
return request.get({ url: '/project/acceptance/get?id=' + id })
|
||||
}
|
||||
|
||||
// 新增验收实例
|
||||
export const createAcceptance = (data: AcceptanceVO) => {
|
||||
return request.post({ url: '/project/acceptance/create', data })
|
||||
}
|
||||
|
||||
// 修改验收实例
|
||||
export const updateAcceptance = (data: AcceptanceVO) => {
|
||||
return request.put({ url: '/project/acceptance/update', data })
|
||||
}
|
||||
|
||||
// 删除验收实例
|
||||
export const deleteAcceptance = (id: number) => {
|
||||
return request.delete({ url: '/project/acceptance/delete?id=' + id })
|
||||
}
|
||||
|
||||
// 批量删除验收实例
|
||||
export const deleteAcceptanceList = (ids: number[]) => {
|
||||
return request.delete({ url: '/project/acceptance/delete-list', params: { ids: ids.join(',') } })
|
||||
}
|
||||
|
||||
// 导出验收实例 Excel
|
||||
export const exportAcceptance = (params: any) => {
|
||||
return request.download({ url: '/project/acceptance/export-excel', params })
|
||||
}
|
||||
|
||||
// ==================== 业务接口 ====================
|
||||
|
||||
// 提交预验收申请
|
||||
export const submitPreAcceptance = (data: AcceptanceSubmitPreReqVO) => {
|
||||
return request.post({ url: '/project/acceptance/submit-pre', data })
|
||||
}
|
||||
|
||||
// 预验收审核(对口人/组长)
|
||||
export const auditPreAcceptance = (data: AcceptanceAuditReqVO) => {
|
||||
return request.post({ url: '/project/acceptance/audit-pre', data })
|
||||
}
|
||||
|
||||
// 提交验收材料
|
||||
export const submitMaterials = (acceptanceId: number) => {
|
||||
return request.post({ url: '/project/acceptance/submit-materials?acceptanceId=' + acceptanceId })
|
||||
}
|
||||
|
||||
// 提交预验收整改
|
||||
export const submitPreRectify = (acceptanceId: number) => {
|
||||
return request.post({ url: '/project/acceptance/submit-pre-rectify?acceptanceId=' + acceptanceId })
|
||||
}
|
||||
|
||||
// 提交终验申请
|
||||
export const submitFinalAcceptance = (data: AcceptanceSubmitFinalReqVO) => {
|
||||
return request.post({ url: '/project/acceptance/submit-final', data })
|
||||
}
|
||||
|
||||
// 终验管理员初审
|
||||
export const auditFinalAdmin = (data: AcceptanceAuditReqVO) => {
|
||||
return request.post({ url: '/project/acceptance/audit-final-admin', data })
|
||||
}
|
||||
|
||||
// 提交终验整改
|
||||
export const submitFinalRectify = (acceptanceId: number) => {
|
||||
return request.post({ url: '/project/acceptance/submit-final-rectify?acceptanceId=' + acceptanceId })
|
||||
}
|
||||
|
||||
// 整改审核
|
||||
export const auditRectify = (data: AcceptanceRectifyAuditReqVO) => {
|
||||
return request.post({ url: '/project/acceptance/audit-rectify', data })
|
||||
}
|
||||
|
||||
// 专家复核
|
||||
export const expertCheck = (data: AcceptanceAuditReqVO) => {
|
||||
return request.post({ url: '/project/acceptance/expert-check', data })
|
||||
}
|
||||
|
||||
// 强制归档
|
||||
export const forceArchive = (acceptanceId: number, reason: string) => {
|
||||
return request.post({ url: '/project/acceptance/force-archive', params: { acceptanceId, reason } })
|
||||
}
|
||||
|
||||
// 取消验收
|
||||
export const cancelAcceptance = (acceptanceId: number, reason: string) => {
|
||||
return request.post({ url: '/project/acceptance/cancel', params: { acceptanceId, reason } })
|
||||
}
|
||||
|
||||
// 查询待办任务
|
||||
export const getTodoList = () => {
|
||||
return request.get({ url: '/project/acceptance/todo' })
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
import request from '@/config/axios'
|
||||
|
||||
// 验收材料 VO
|
||||
export interface AcceptanceMaterialVO {
|
||||
id: number
|
||||
acceptanceId: number
|
||||
materialCode: string
|
||||
fileName: string
|
||||
fileUrl: string
|
||||
fileSize: number
|
||||
fileType: string
|
||||
version: number
|
||||
remark: string
|
||||
uploaderId: number
|
||||
uploadTime: Date
|
||||
createTime: Date
|
||||
}
|
||||
|
||||
// 查询验收材料分页
|
||||
export const getAcceptanceMaterialPage = (params: any) => {
|
||||
return request.get({ url: '/project/acceptance-material/page', params })
|
||||
}
|
||||
|
||||
// 根据验收ID获取材料列表
|
||||
export const getListByAcceptanceId = (acceptanceId: number) => {
|
||||
return request.get({ url: '/project/acceptance-material/list-by-acceptance-id', params: { acceptanceId } })
|
||||
}
|
||||
|
||||
// 查询验收材料详情
|
||||
export const getAcceptanceMaterial = (id: number) => {
|
||||
return request.get({ url: '/project/acceptance-material/get?id=' + id })
|
||||
}
|
||||
|
||||
// 新增验收材料
|
||||
export const createAcceptanceMaterial = (data: AcceptanceMaterialVO) => {
|
||||
return request.post({ url: '/project/acceptance-material/create', data })
|
||||
}
|
||||
|
||||
// 修改验收材料
|
||||
export const updateAcceptanceMaterial = (data: AcceptanceMaterialVO) => {
|
||||
return request.put({ url: '/project/acceptance-material/update', data })
|
||||
}
|
||||
|
||||
// 删除验收材料
|
||||
export const deleteAcceptanceMaterial = (id: number) => {
|
||||
return request.delete({ url: '/project/acceptance-material/delete?id=' + id })
|
||||
}
|
||||
|
||||
// 批量删除验收材料
|
||||
export const deleteAcceptanceMaterialList = (ids: number[]) => {
|
||||
return request.delete({ url: '/project/acceptance-material/delete-list', params: { ids: ids.join(',') } })
|
||||
}
|
||||
|
||||
// 导出验收材料 Excel
|
||||
export const exportAcceptanceMaterial = (params: any) => {
|
||||
return request.download({ url: '/project/acceptance-material/export-excel', params })
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
import request from '@/config/axios'
|
||||
|
||||
// 验收材料定义 VO
|
||||
export interface AcceptanceMaterialDefVO {
|
||||
id: number
|
||||
acceptanceType: string
|
||||
materialCode: string
|
||||
materialName: string
|
||||
requiredFlag: boolean
|
||||
uploadRole: string
|
||||
sort: number
|
||||
createTime: Date
|
||||
}
|
||||
|
||||
// 查询验收材料定义分页
|
||||
export const getAcceptanceMaterialDefPage = (params: any) => {
|
||||
return request.get({ url: '/project/acceptance-material-def/page', params })
|
||||
}
|
||||
|
||||
// 根据验收类型获取材料定义列表
|
||||
export const getListByType = (acceptanceType: string) => {
|
||||
return request.get({ url: '/project/acceptance-material-def/list-by-type', params: { acceptanceType } })
|
||||
}
|
||||
|
||||
// 查询验收材料定义详情
|
||||
export const getAcceptanceMaterialDef = (id: number) => {
|
||||
return request.get({ url: '/project/acceptance-material-def/get?id=' + id })
|
||||
}
|
||||
|
||||
// 新增验收材料定义
|
||||
export const createAcceptanceMaterialDef = (data: AcceptanceMaterialDefVO) => {
|
||||
return request.post({ url: '/project/acceptance-material-def/create', data })
|
||||
}
|
||||
|
||||
// 修改验收材料定义
|
||||
export const updateAcceptanceMaterialDef = (data: AcceptanceMaterialDefVO) => {
|
||||
return request.put({ url: '/project/acceptance-material-def/update', data })
|
||||
}
|
||||
|
||||
// 删除验收材料定义
|
||||
export const deleteAcceptanceMaterialDef = (id: number) => {
|
||||
return request.delete({ url: '/project/acceptance-material-def/delete?id=' + id })
|
||||
}
|
||||
|
||||
// 批量删除验收材料定义
|
||||
export const deleteAcceptanceMaterialDefList = (ids: number[]) => {
|
||||
return request.delete({ url: '/project/acceptance-material-def/delete-list', params: { ids: ids.join(',') } })
|
||||
}
|
||||
|
||||
// 导出验收材料定义 Excel
|
||||
export const exportAcceptanceMaterialDef = (params: any) => {
|
||||
return request.download({ url: '/project/acceptance-material-def/export-excel', params })
|
||||
}
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
import request from '@/config/axios'
|
||||
|
||||
// 验收会议 VO
|
||||
export interface AcceptanceMeetingVO {
|
||||
id: number
|
||||
meetingName: string
|
||||
meetingTime: Date
|
||||
meetingLocation: string
|
||||
meetingType: string
|
||||
meetingResult: string
|
||||
meetingOpinion: string
|
||||
minutesFileUrl: string
|
||||
signFileUrl: string
|
||||
createTime: Date
|
||||
}
|
||||
|
||||
// 批量创建会议请求 VO
|
||||
export interface AcceptanceMeetingBatchCreateReqVO {
|
||||
acceptanceIds: number[]
|
||||
meetingName: string
|
||||
meetingTime: Date
|
||||
meetingLocation?: string
|
||||
meetingType: string
|
||||
expertUserIds: number[]
|
||||
minutesFileUrl?: string
|
||||
}
|
||||
|
||||
// 批量录入会议结果请求 VO
|
||||
export interface AcceptanceMeetingBatchResultReqVO {
|
||||
meetingId: number
|
||||
results: AcceptanceMeetingResultVO[]
|
||||
}
|
||||
|
||||
// 单个会议结果 VO
|
||||
export interface AcceptanceMeetingResultVO {
|
||||
acceptanceId: number
|
||||
result: string
|
||||
opinion: string
|
||||
}
|
||||
|
||||
// ==================== 基础 CRUD ====================
|
||||
|
||||
// 查询验收会议分页
|
||||
export const getAcceptanceMeetingPage = (params: any) => {
|
||||
return request.get({ url: '/project/acceptance-meeting/page', params })
|
||||
}
|
||||
|
||||
// 查询验收会议详情
|
||||
export const getAcceptanceMeeting = (id: number) => {
|
||||
return request.get({ url: '/project/acceptance-meeting/get?id=' + id })
|
||||
}
|
||||
|
||||
// 新增验收会议
|
||||
export const createAcceptanceMeeting = (data: AcceptanceMeetingVO) => {
|
||||
return request.post({ url: '/project/acceptance-meeting/create', data })
|
||||
}
|
||||
|
||||
// 修改验收会议
|
||||
export const updateAcceptanceMeeting = (data: AcceptanceMeetingVO) => {
|
||||
return request.put({ url: '/project/acceptance-meeting/update', data })
|
||||
}
|
||||
|
||||
// 删除验收会议
|
||||
export const deleteAcceptanceMeeting = (id: number) => {
|
||||
return request.delete({ url: '/project/acceptance-meeting/delete?id=' + id })
|
||||
}
|
||||
|
||||
// 批量删除验收会议
|
||||
export const deleteAcceptanceMeetingList = (ids: number[]) => {
|
||||
return request.delete({ url: '/project/acceptance-meeting/delete-list', params: { ids: ids.join(',') } })
|
||||
}
|
||||
|
||||
// 导出验收会议 Excel
|
||||
export const exportAcceptanceMeeting = (params: any) => {
|
||||
return request.download({ url: '/project/acceptance-meeting/export-excel', params })
|
||||
}
|
||||
|
||||
// ==================== 业务接口 ====================
|
||||
|
||||
// 批量创建会议
|
||||
export const batchCreateMeeting = (data: AcceptanceMeetingBatchCreateReqVO) => {
|
||||
return request.post({ url: '/project/acceptance-meeting/batch-create', data })
|
||||
}
|
||||
|
||||
// 批量录入会议结果
|
||||
export const batchInputResult = (data: AcceptanceMeetingBatchResultReqVO) => {
|
||||
return request.post({ url: '/project/acceptance-meeting/batch-input-result', data })
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
import request from '@/config/axios'
|
||||
|
||||
// 验收会议专家关联 VO
|
||||
export interface AcceptanceMeetingExpertVO {
|
||||
id: number
|
||||
meetingId: number
|
||||
expertUserId: number
|
||||
opinion: string
|
||||
result: string
|
||||
signatureUrl: string
|
||||
createTime: Date
|
||||
}
|
||||
|
||||
// 查询验收会议专家关联分页
|
||||
export const getAcceptanceMeetingExpertPage = (params: any) => {
|
||||
return request.get({ url: '/project/acceptance-meeting-expert/page', params })
|
||||
}
|
||||
|
||||
// 查询验收会议专家关联详情
|
||||
export const getAcceptanceMeetingExpert = (id: number) => {
|
||||
return request.get({ url: '/project/acceptance-meeting-expert/get?id=' + id })
|
||||
}
|
||||
|
||||
// 新增验收会议专家关联
|
||||
export const createAcceptanceMeetingExpert = (data: AcceptanceMeetingExpertVO) => {
|
||||
return request.post({ url: '/project/acceptance-meeting-expert/create', data })
|
||||
}
|
||||
|
||||
// 修改验收会议专家关联
|
||||
export const updateAcceptanceMeetingExpert = (data: AcceptanceMeetingExpertVO) => {
|
||||
return request.put({ url: '/project/acceptance-meeting-expert/update', data })
|
||||
}
|
||||
|
||||
// 删除验收会议专家关联
|
||||
export const deleteAcceptanceMeetingExpert = (id: number) => {
|
||||
return request.delete({ url: '/project/acceptance-meeting-expert/delete?id=' + id })
|
||||
}
|
||||
|
||||
// 批量删除验收会议专家关联
|
||||
export const deleteAcceptanceMeetingExpertList = (ids: number[]) => {
|
||||
return request.delete({ url: '/project/acceptance-meeting-expert/delete-list', params: { ids: ids.join(',') } })
|
||||
}
|
||||
|
||||
// 导出验收会议专家关联 Excel
|
||||
export const exportAcceptanceMeetingExpert = (params: any) => {
|
||||
return request.download({ url: '/project/acceptance-meeting-expert/export-excel', params })
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
import request from '@/config/axios'
|
||||
|
||||
// 验收会议关联 VO
|
||||
export interface AcceptanceMeetingRelationVO {
|
||||
id: number
|
||||
meetingId: number
|
||||
acceptanceId: number
|
||||
meetingResult: string
|
||||
meetingOpinion: string
|
||||
createTime: Date
|
||||
}
|
||||
|
||||
// 查询验收会议关联分页
|
||||
export const getAcceptanceMeetingRelationPage = (params: any) => {
|
||||
return request.get({ url: '/project/acceptance-meeting-relation/page', params })
|
||||
}
|
||||
|
||||
// 查询验收会议关联详情
|
||||
export const getAcceptanceMeetingRelation = (id: number) => {
|
||||
return request.get({ url: '/project/acceptance-meeting-relation/get?id=' + id })
|
||||
}
|
||||
|
||||
// 新增验收会议关联
|
||||
export const createAcceptanceMeetingRelation = (data: AcceptanceMeetingRelationVO) => {
|
||||
return request.post({ url: '/project/acceptance-meeting-relation/create', data })
|
||||
}
|
||||
|
||||
// 修改验收会议关联
|
||||
export const updateAcceptanceMeetingRelation = (data: AcceptanceMeetingRelationVO) => {
|
||||
return request.put({ url: '/project/acceptance-meeting-relation/update', data })
|
||||
}
|
||||
|
||||
// 删除验收会议关联
|
||||
export const deleteAcceptanceMeetingRelation = (id: number) => {
|
||||
return request.delete({ url: '/project/acceptance-meeting-relation/delete?id=' + id })
|
||||
}
|
||||
|
||||
// 批量删除验收会议关联
|
||||
export const deleteAcceptanceMeetingRelationList = (ids: number[]) => {
|
||||
return request.delete({ url: '/project/acceptance-meeting-relation/delete-list', params: { ids: ids.join(',') } })
|
||||
}
|
||||
|
||||
// 导出验收会议关联 Excel
|
||||
export const exportAcceptanceMeetingRelation = (params: any) => {
|
||||
return request.download({ url: '/project/acceptance-meeting-relation/export-excel', params })
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
import request from '@/config/axios'
|
||||
|
||||
// 验收审核意见 VO
|
||||
export interface AcceptanceOpinionVO {
|
||||
id: number
|
||||
acceptanceId: number
|
||||
opinionType: string
|
||||
operatorId: number
|
||||
opinion: string
|
||||
result: string
|
||||
signatureUrl: string
|
||||
createTime: Date
|
||||
}
|
||||
|
||||
// 查询验收审核意见分页
|
||||
export const getAcceptanceOpinionPage = (params: any) => {
|
||||
return request.get({ url: '/project/acceptance-opinion/page', params })
|
||||
}
|
||||
|
||||
// 查询验收审核意见详情
|
||||
export const getAcceptanceOpinion = (id: number) => {
|
||||
return request.get({ url: '/project/acceptance-opinion/get?id=' + id })
|
||||
}
|
||||
|
||||
// 新增验收审核意见
|
||||
export const createAcceptanceOpinion = (data: AcceptanceOpinionVO) => {
|
||||
return request.post({ url: '/project/acceptance-opinion/create', data })
|
||||
}
|
||||
|
||||
// 修改验收审核意见
|
||||
export const updateAcceptanceOpinion = (data: AcceptanceOpinionVO) => {
|
||||
return request.put({ url: '/project/acceptance-opinion/update', data })
|
||||
}
|
||||
|
||||
// 删除验收审核意见
|
||||
export const deleteAcceptanceOpinion = (id: number) => {
|
||||
return request.delete({ url: '/project/acceptance-opinion/delete?id=' + id })
|
||||
}
|
||||
|
||||
// 批量删除验收审核意见
|
||||
export const deleteAcceptanceOpinionList = (ids: number[]) => {
|
||||
return request.delete({ url: '/project/acceptance-opinion/delete-list', params: { ids: ids.join(',') } })
|
||||
}
|
||||
|
||||
// 导出验收审核意见 Excel
|
||||
export const exportAcceptanceOpinion = (params: any) => {
|
||||
return request.download({ url: '/project/acceptance-opinion/export-excel', params })
|
||||
}
|
||||
|
||||
// 根据验收ID获取审核意见列表
|
||||
export const getListByAcceptanceId = (acceptanceId: number) => {
|
||||
return request.get({ url: '/project/acceptance-opinion/list-by-acceptance?acceptanceId=' + acceptanceId })
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
import request from '@/config/axios'
|
||||
|
||||
// 项目主表 VO
|
||||
export interface ProjectVO {
|
||||
id: number
|
||||
projectCode: string
|
||||
contractCode: string
|
||||
projectName: string
|
||||
applyUnit: string
|
||||
liaisonUserId: number
|
||||
principalUserId: number
|
||||
serviceUserId: number
|
||||
status: string
|
||||
currentNode: string
|
||||
createTime: Date
|
||||
}
|
||||
|
||||
// 查询项目主表分页
|
||||
export const getProjectPage = (params: any) => {
|
||||
return request.get({ url: '/project/project/page', params })
|
||||
}
|
||||
|
||||
// 查询项目主表详情
|
||||
export const getProject = (id: number) => {
|
||||
return request.get({ url: '/project/project/get?id=' + id })
|
||||
}
|
||||
|
||||
// 新增项目主表
|
||||
export const createProject = (data: ProjectVO) => {
|
||||
return request.post({ url: '/project/project/create', data })
|
||||
}
|
||||
|
||||
// 修改项目主表
|
||||
export const updateProject = (data: ProjectVO) => {
|
||||
return request.put({ url: '/project/project/update', data })
|
||||
}
|
||||
|
||||
// 删除项目主表
|
||||
export const deleteProject = (id: number) => {
|
||||
return request.delete({ url: '/project/project/delete?id=' + id })
|
||||
}
|
||||
|
||||
// 批量删除项目主表
|
||||
export const deleteProjectList = (ids: number[]) => {
|
||||
return request.delete({ url: '/project/project/delete-list', params: { ids: ids.join(',') } })
|
||||
}
|
||||
|
||||
// 导出项目主表 Excel
|
||||
export const exportProject = (params: any) => {
|
||||
return request.download({ url: '/project/project/export-excel', params })
|
||||
}
|
||||
|
|
@ -704,6 +704,28 @@ const remainingRouter: AppRouteRecordRaw[] = [
|
|||
breadcrumb: false
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/project',
|
||||
component: Layout,
|
||||
name: 'ProjectCenter',
|
||||
meta: {
|
||||
hidden: true
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: 'acceptance/detail/:id(\\d+)',
|
||||
name: 'AcceptanceDetail',
|
||||
meta: {
|
||||
title: '验收详情',
|
||||
noCache: true,
|
||||
hidden: true,
|
||||
canTo: true,
|
||||
activeMenu: '/project/acceptance'
|
||||
},
|
||||
component: () => import('@/views/project/acceptance/detail/index.vue')
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/iot',
|
||||
component: Layout,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,218 @@
|
|||
<template>
|
||||
<Dialog v-model="dialogVisible" :title="dialogTitle" width="600px">
|
||||
<el-form
|
||||
ref="formRef"
|
||||
v-loading="formLoading"
|
||||
:model="formData"
|
||||
:rules="formRules"
|
||||
label-width="100px"
|
||||
>
|
||||
<el-alert
|
||||
:title="'验收ID: ' + acceptanceInfo.id + ' | 类型: ' + getAcceptanceTypeLabel(acceptanceInfo.acceptanceType)"
|
||||
type="info"
|
||||
:closable="false"
|
||||
class="mb-4"
|
||||
/>
|
||||
<el-form-item label="审核结果" prop="result">
|
||||
<el-radio-group v-model="formData.result">
|
||||
<el-radio value="PASS">通过</el-radio>
|
||||
<el-radio value="REJECT">驳回</el-radio>
|
||||
<el-radio v-if="showRectifyOption" value="RECTIFY">需整改</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="审核意见" prop="opinion">
|
||||
<el-input
|
||||
v-model="formData.opinion"
|
||||
type="textarea"
|
||||
:rows="4"
|
||||
placeholder="请输入审核意见"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="showRectifyDeadline && formData.result === 'RECTIFY'" label="整改期限" prop="rectifyDeadline">
|
||||
<el-date-picker
|
||||
v-model="formData.rectifyDeadline"
|
||||
type="datetime"
|
||||
placeholder="请选择整改期限"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="needSignature" label="电子签名">
|
||||
<el-upload
|
||||
:action="uploadUrl"
|
||||
:headers="uploadHeaders"
|
||||
:show-file-list="false"
|
||||
:on-success="handleSignatureSuccess"
|
||||
accept="image/*"
|
||||
>
|
||||
<el-button type="primary">上传签名</el-button>
|
||||
</el-upload>
|
||||
<el-image
|
||||
v-if="formData.signatureUrl"
|
||||
:src="formData.signatureUrl"
|
||||
style="width: 200px; height: 80px; margin-top: 10px"
|
||||
fit="contain"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button :disabled="formLoading" type="primary" @click="submitForm">提交审核</el-button>
|
||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||
</template>
|
||||
</Dialog>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import * as AcceptanceApi from '@/api/project/acceptance'
|
||||
import { FormRules } from 'element-plus'
|
||||
import { getAccessToken } from '@/utils/auth'
|
||||
|
||||
defineOptions({ name: 'AcceptanceAuditForm' })
|
||||
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||
const dialogTitle = ref('审核') // 弹窗的标题
|
||||
const formLoading = ref(false) // 表单的加载中
|
||||
const auditType = ref('') // 审核类型: pre-audit, final-admin, rectify, expert-check
|
||||
const acceptanceInfo = ref({
|
||||
id: undefined as number | undefined,
|
||||
acceptanceType: '',
|
||||
status: ''
|
||||
})
|
||||
const formData = ref({
|
||||
acceptanceId: undefined as number | undefined,
|
||||
result: 'PASS',
|
||||
opinion: '',
|
||||
signatureUrl: '',
|
||||
rectifyDeadline: undefined as string | undefined
|
||||
})
|
||||
const formRules = reactive<FormRules>({
|
||||
result: [{ required: true, message: '请选择审核结果', trigger: 'change' }],
|
||||
opinion: [{ required: true, message: '请输入审核意见', trigger: 'blur' }]
|
||||
})
|
||||
const formRef = ref() // 表单 Ref
|
||||
|
||||
// 上传配置
|
||||
const uploadUrl = import.meta.env.VITE_BASE_URL + '/infra/file/upload'
|
||||
const uploadHeaders = { Authorization: 'Bearer ' + getAccessToken() }
|
||||
|
||||
// 是否显示整改选项
|
||||
const showRectifyOption = computed(() => {
|
||||
return ['pre-audit', 'final-admin', 'expert-check'].includes(auditType.value)
|
||||
})
|
||||
|
||||
// 是否显示整改期限
|
||||
const showRectifyDeadline = computed(() => {
|
||||
return auditType.value === 'rectify'
|
||||
})
|
||||
|
||||
// 是否需要签名
|
||||
const needSignature = computed(() => {
|
||||
return ['pre-audit', 'expert-check'].includes(auditType.value)
|
||||
})
|
||||
|
||||
const getAcceptanceTypeLabel = (type: string) => {
|
||||
return type === 'PRE' ? '预验收' : type === 'FINAL' ? '终验' : type
|
||||
}
|
||||
|
||||
/** 打开弹窗 */
|
||||
const open = async (row: AcceptanceApi.AcceptanceVO, type?: string) => {
|
||||
dialogVisible.value = true
|
||||
resetForm()
|
||||
acceptanceInfo.value = {
|
||||
id: row.id,
|
||||
acceptanceType: row.acceptanceType,
|
||||
status: row.status
|
||||
}
|
||||
formData.value.acceptanceId = row.id
|
||||
|
||||
// 根据状态判断审核类型
|
||||
if (type) {
|
||||
auditType.value = type
|
||||
} else {
|
||||
// 自动判断审核类型
|
||||
if (row.status === '10') {
|
||||
auditType.value = row.acceptanceType === 'PRE' ? 'pre-audit' : 'final-admin'
|
||||
} else if (row.status === '40') {
|
||||
auditType.value = 'rectify'
|
||||
} else {
|
||||
auditType.value = 'pre-audit'
|
||||
}
|
||||
}
|
||||
|
||||
dialogTitle.value = getDialogTitle()
|
||||
}
|
||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||
|
||||
const getDialogTitle = () => {
|
||||
switch (auditType.value) {
|
||||
case 'pre-audit': return '预验收审核'
|
||||
case 'final-admin': return '终验管理员初审'
|
||||
case 'rectify': return '整改审核'
|
||||
case 'expert-check': return '专家复核'
|
||||
default: return '审核'
|
||||
}
|
||||
}
|
||||
|
||||
/** 签名上传成功 */
|
||||
const handleSignatureSuccess = (response: any) => {
|
||||
if (response.code === 0) {
|
||||
formData.value.signatureUrl = response.data
|
||||
message.success('签名上传成功')
|
||||
} else {
|
||||
message.error('签名上传失败: ' + response.msg)
|
||||
}
|
||||
}
|
||||
|
||||
/** 提交表单 */
|
||||
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
||||
const submitForm = async () => {
|
||||
// 校验表单
|
||||
if (!formRef.value) return
|
||||
const valid = await formRef.value.validate()
|
||||
if (!valid) return
|
||||
// 提交请求
|
||||
formLoading.value = true
|
||||
try {
|
||||
// 根据审核类型调用不同接口
|
||||
switch (auditType.value) {
|
||||
case 'pre-audit':
|
||||
await AcceptanceApi.auditPreAcceptance(formData.value as AcceptanceApi.AcceptanceAuditReqVO)
|
||||
break
|
||||
case 'final-admin':
|
||||
await AcceptanceApi.auditFinalAdmin(formData.value as AcceptanceApi.AcceptanceAuditReqVO)
|
||||
break
|
||||
case 'rectify':
|
||||
await AcceptanceApi.auditRectify(formData.value as AcceptanceApi.AcceptanceRectifyAuditReqVO)
|
||||
break
|
||||
case 'expert-check':
|
||||
await AcceptanceApi.expertCheck(formData.value as AcceptanceApi.AcceptanceAuditReqVO)
|
||||
break
|
||||
}
|
||||
message.success('审核提交成功')
|
||||
dialogVisible.value = false
|
||||
// 发送操作成功的事件
|
||||
emit('success')
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 重置表单 */
|
||||
const resetForm = () => {
|
||||
acceptanceInfo.value = {
|
||||
id: undefined,
|
||||
acceptanceType: '',
|
||||
status: ''
|
||||
}
|
||||
formData.value = {
|
||||
acceptanceId: undefined,
|
||||
result: 'PASS',
|
||||
opinion: '',
|
||||
signatureUrl: '',
|
||||
rectifyDeadline: undefined
|
||||
}
|
||||
auditType.value = ''
|
||||
formRef.value?.resetFields()
|
||||
}
|
||||
</script>
|
||||
|
|
@ -0,0 +1,629 @@
|
|||
<template>
|
||||
<ContentWrap>
|
||||
<div v-loading="loading">
|
||||
<!-- 头部信息 -->
|
||||
<!-- 头部信息 -->
|
||||
<div class="bg-white p-5 mb-6 rounded-lg shadow-sm border border-gray-100">
|
||||
<div class="flex justify-between items-start mb-8">
|
||||
<div>
|
||||
<h2 class="text-2xl font-bold text-gray-800 flex items-center mb-3">
|
||||
{{ projectInfo.projectName || '项目验收' }}
|
||||
<el-tag v-if="acceptance.acceptanceType === 'PRE'" type="info" effect="dark" class="ml-3 rounded-full px-3">预验收</el-tag>
|
||||
<el-tag v-else-if="acceptance.acceptanceType === 'FINAL'" type="primary" effect="dark" class="ml-3 rounded-full px-3">终验</el-tag>
|
||||
</h2>
|
||||
<div class="text-gray-500 text-sm flex items-center gap-4 bg-gray-50 px-4 py-2 rounded-md">
|
||||
<span><span class="font-medium text-gray-700">项目编号:</span>{{ projectInfo.projectCode }}</span>
|
||||
<el-divider direction="vertical" />
|
||||
<span><span class="font-medium text-gray-700">验收ID:</span>{{ acceptance.id }}</span>
|
||||
<el-divider direction="vertical" />
|
||||
<span><span class="font-medium text-gray-700">轮次:</span>第 {{ acceptance.round }} 轮</span>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<el-tag :type="getStatusType(acceptance.status)" size="large" effect="plain" class="text-base px-6 py-1.5 font-bold rounded-lg border-2">
|
||||
{{ getStatusLabel(acceptance.status) }}
|
||||
</el-tag>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 流程步骤 -->
|
||||
<el-steps :active="activeStep" finish-status="success" align-center class="mb-2">
|
||||
<el-step title="提交材料" description="待提交/完善材料" />
|
||||
<el-step title="初步审核" description="对口人/组长审核" />
|
||||
<el-step title="终验申请" description="确认进入终验" />
|
||||
<el-step title="终验评审" description="会议评审与整改" />
|
||||
<el-step title="归档完成" description="流程结束" />
|
||||
</el-steps>
|
||||
</div>
|
||||
|
||||
<el-divider />
|
||||
|
||||
<el-tabs v-model="activeTab">
|
||||
<!-- 基本信息 -->
|
||||
<el-tab-pane label="基本信息" name="info">
|
||||
<el-descriptions :column="2" border>
|
||||
|
||||
<el-descriptions-item label="项目联络人">{{ liaisonUserName || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="对口人">{{ serviceUserName || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="开始时间">{{ formatDate(acceptance.startTime) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="完成时间">{{ formatDate(acceptance.endTime) || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="流程实例ID">{{ acceptance.processInstanceId || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="创建时间">{{ formatDate(acceptance.createTime) }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-tab-pane>
|
||||
|
||||
<!-- 验收材料 -->
|
||||
<el-tab-pane label="验收材料" name="materials">
|
||||
<div class="mb-6" v-if="canUploadMaterial">
|
||||
<el-alert
|
||||
title="待办任务:上传验收材料"
|
||||
type="primary"
|
||||
:closable="false"
|
||||
show-icon
|
||||
description="请完成下方所有必填材料的上传,确认无误后点击底部的【提交材料】按钮进入审核流程。"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 xl:grid-cols-3 gap-6">
|
||||
<template v-for="(item, index) in materials" :key="index">
|
||||
<el-card
|
||||
shadow="hover"
|
||||
class="relative transition-all duration-300 hover:shadow-lg hover:-translate-y-1 border-gray-200"
|
||||
:body-style="{ padding: '16px' }"
|
||||
>
|
||||
<div class="flex items-start">
|
||||
<!-- 文件图标 -->
|
||||
<div class="w-12 h-12 flex items-center justify-center rounded-lg mr-4 shrink-0"
|
||||
:class="getFileIconColor(item.fileName)">
|
||||
<Icon :icon="getFileIcon(item.fileName)" size="28" color="#fff" />
|
||||
</div>
|
||||
|
||||
<!-- 内容区域 -->
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="flex items-center justify-between mb-1">
|
||||
<span class="font-bold text-gray-800 truncate text-[15px]" :title="item.materialName">
|
||||
{{ item.materialName }}
|
||||
</span>
|
||||
<el-tag v-if="item.isRequired" type="danger" effect="plain" size="small" class="ml-2 px-1">必填</el-tag>
|
||||
<el-tag v-else type="info" effect="plain" size="small" class="ml-2 px-1">可选</el-tag>
|
||||
</div>
|
||||
|
||||
<!-- 上传状态/文件名 -->
|
||||
<div class="h-[24px] mb-3 flex items-center">
|
||||
<template v-if="item.fileUrl">
|
||||
<el-tooltip :content="item.fileName" placement="top" :show-after="500">
|
||||
<span class="text-xs text-blue-600 truncate underline cursor-pointer hover:text-blue-800"
|
||||
@click="handlePreview(item)">
|
||||
{{ item.fileName }}
|
||||
</span>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
<span v-else class="text-xs text-gray-400 italic">暂未上传文件</span>
|
||||
</div>
|
||||
|
||||
<!-- 操作按钮组 -->
|
||||
<div class="flex items-center justify-between mt-2 pt-3 border-t border-gray-100">
|
||||
<div class="flex gap-2">
|
||||
<el-button
|
||||
v-if="item.fileUrl"
|
||||
link
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="handlePreview(item)"
|
||||
>
|
||||
<Icon icon="ep:view" class="mr-1"/> 预览
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="item.fileUrl"
|
||||
link
|
||||
size="small"
|
||||
type="success"
|
||||
@click="handleDownload(item)"
|
||||
>
|
||||
<Icon icon="ep:download" class="mr-1"/> 下载
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<!-- 上传按钮 -->
|
||||
<div v-if="canUploadMaterial">
|
||||
<el-upload
|
||||
:action="uploadUrl"
|
||||
:headers="uploadHeaders"
|
||||
:show-file-list="false"
|
||||
:on-success="(res, file) => handleUploadSuccess(res, file, item)"
|
||||
>
|
||||
<el-button
|
||||
size="small"
|
||||
:type="item.fileUrl ? 'primary' : 'primary'"
|
||||
:plain="!!item.fileUrl"
|
||||
class="!rounded-md"
|
||||
>
|
||||
<Icon icon="ep:upload" class="mr-1"/>
|
||||
{{ item.fileUrl ? '重新上传' : '上传材料' }}
|
||||
</el-button>
|
||||
</el-upload>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 状态角标 -->
|
||||
<div class="absolute top-0 right-0">
|
||||
<div v-if="item.fileUrl" class="bg-green-100 text-green-600 text-[10px] px-2 py-0.5 rounded-bl-lg font-medium">已完成</div>
|
||||
<div v-else class="bg-gray-100 text-gray-500 text-[10px] px-2 py-0.5 rounded-bl-lg">待上传</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</template>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
|
||||
<!-- 审批记录 -->
|
||||
<el-tab-pane label="审批记录" name="opinions">
|
||||
<el-timeline>
|
||||
<el-timeline-item
|
||||
v-for="(opinion, index) in opinions"
|
||||
:key="index"
|
||||
:type="getOpinionType(opinion.result)"
|
||||
:timestamp="formatDate(opinion.createTime)"
|
||||
placement="top"
|
||||
>
|
||||
<el-card>
|
||||
<h4 class="mb-2">
|
||||
{{ opinion.reviewerRole || '审核人' }}:{{ opinion.reviewerName || '未知' }}
|
||||
<el-tag v-if="opinion.isLeader" type="warning" size="small" class="ml-1">组长</el-tag>
|
||||
<el-tag :type="getOpinionType(opinion.result)" size="small" class="ml-2">
|
||||
{{ getOpinionLabel(opinion.result) }}
|
||||
</el-tag>
|
||||
</h4>
|
||||
<p class="text-gray-600">{{ opinion.opinion || '无意见' }}</p>
|
||||
<el-image
|
||||
v-if="opinion.signatureUrl"
|
||||
:src="opinion.signatureUrl"
|
||||
style="width: 150px; height: 60px; margin-top: 8px"
|
||||
fit="contain"
|
||||
/>
|
||||
</el-card>
|
||||
</el-timeline-item>
|
||||
<el-empty v-if="opinions.length === 0" description="暂无审批记录" />
|
||||
</el-timeline>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<div class="mt-6 flex justify-end gap-2" v-if="showActions">
|
||||
<el-button @click="goBack">返回</el-button>
|
||||
<el-button
|
||||
v-if="canSubmitMaterial"
|
||||
type="primary"
|
||||
@click="handleSubmitMaterial"
|
||||
>
|
||||
提交材料
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="canSubmitRectify"
|
||||
type="warning"
|
||||
@click="handleSubmitRectify"
|
||||
>
|
||||
提交整改
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="canSubmitFinal"
|
||||
type="success"
|
||||
@click="handleSubmitFinal"
|
||||
>
|
||||
提交终验申请
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="canAudit"
|
||||
type="primary"
|
||||
@click="openAuditDialog"
|
||||
>
|
||||
<Icon icon="ep:check" class="mr-1" /> 审核
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 审核对话框 -->
|
||||
<el-dialog
|
||||
v-model="auditDialogVisible"
|
||||
title="验收审核"
|
||||
width="500px"
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<el-form
|
||||
ref="auditFormRef"
|
||||
:model="auditForm"
|
||||
:rules="auditFormRules"
|
||||
label-width="100px"
|
||||
>
|
||||
<el-form-item label="审核结果" prop="result">
|
||||
<el-radio-group v-model="auditForm.result">
|
||||
<el-radio-button value="PASS">
|
||||
<Icon icon="ep:check" class="mr-1" /> 通过
|
||||
</el-radio-button>
|
||||
<el-radio-button value="REJECT">
|
||||
<Icon icon="ep:close" class="mr-1" /> 驳回
|
||||
</el-radio-button>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="审核意见" prop="opinion">
|
||||
<el-input
|
||||
v-model="auditForm.opinion"
|
||||
type="textarea"
|
||||
:rows="4"
|
||||
:placeholder="auditForm.result === 'REJECT' ? '请填写驳回理由...' : '请填写审核意见...'"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="auditDialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="handleAudit">确认提交</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</ContentWrap>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { formatDate } from '@/utils/formatTime'
|
||||
import * as AcceptanceApi from '@/api/project/acceptance'
|
||||
import * as ProjectApi from '@/api/project/project'
|
||||
import * as AcceptanceMaterialApi from '@/api/project/acceptanceMaterial'
|
||||
import * as AcceptanceMaterialDefApi from '@/api/project/acceptanceMaterialDef'
|
||||
import * as AcceptanceOpinionApi from '@/api/project/acceptanceOpinion'
|
||||
import { getAccessToken } from '@/utils/auth'
|
||||
import { useUserStore } from '@/store/modules/user'
|
||||
|
||||
defineOptions({ name: 'AcceptanceDetail' })
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const message = useMessage()
|
||||
|
||||
const loading = ref(true)
|
||||
const activeTab = ref('info')
|
||||
|
||||
// 验收信息
|
||||
const acceptance = ref<AcceptanceApi.AcceptanceVO>({} as AcceptanceApi.AcceptanceVO)
|
||||
// 项目信息
|
||||
const projectInfo = ref<any>({})
|
||||
// 用户名称
|
||||
const liaisonUserName = ref('')
|
||||
const serviceUserName = ref('')
|
||||
// 验收材料
|
||||
const materials = ref<any[]>([])
|
||||
// 审批意见
|
||||
const opinions = ref<any[]>([])
|
||||
|
||||
|
||||
// 上传配置
|
||||
const uploadUrl = import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + '/infra/file/upload'
|
||||
const uploadHeaders = { Authorization: 'Bearer ' + getAccessToken() }
|
||||
|
||||
// 状态映射
|
||||
const statusMap: Record<string, { label: string; type: string }> = {
|
||||
'00': { label: '草稿', type: 'info' },
|
||||
'05': { label: '待提交材料', type: 'warning' },
|
||||
'10': { label: '对口人初审中', type: 'primary' },
|
||||
'11': { label: '待整改', type: 'danger' },
|
||||
'20': { label: '组长审核中', type: 'primary' },
|
||||
'30': { label: '待终验申请', type: 'info' },
|
||||
'40': { label: '管理员初审中', type: 'primary' }, // 对应 FINAL_ADMIN_REVIEW
|
||||
'50': { label: '待会议评审', type: 'info' }, // WAIT_MEETING
|
||||
'60': { label: '待整改', type: 'danger' }, // FINAL_RECTIFY
|
||||
'61': { label: '整改审核中', type: 'warning' }, // FINAL_RECTIFY_REVIEW
|
||||
'62': { label: '待专家复核', type: 'warning' }, // WAIT_EXPERT_CHECK
|
||||
'98': { label: '已取消', type: 'info' },
|
||||
'99': { label: '已归档', type: 'success' }
|
||||
}
|
||||
|
||||
const getStatusLabel = (status: string) => statusMap[status]?.label || status
|
||||
const getStatusType = (status: string) => statusMap[status]?.type || 'info'
|
||||
|
||||
// 审核结果映射
|
||||
const getOpinionLabel = (result: string) => {
|
||||
if (result === 'PASS') return '通过'
|
||||
if (result === 'REJECT') return '驳回'
|
||||
return result || '未知'
|
||||
}
|
||||
const getOpinionType = (result: string) => {
|
||||
if (result === 'PASS') return 'success'
|
||||
if (result === 'REJECT') return 'danger'
|
||||
return 'info'
|
||||
}
|
||||
|
||||
// 权限判断
|
||||
// 权限判断
|
||||
const canUploadMaterial = computed(() => {
|
||||
const currentUserId = useUserStore().getUser.id
|
||||
// 必须是联络人,且状态符合
|
||||
return projectInfo.value.liaisonUserId === currentUserId && ['05', '11', '60'].includes(acceptance.value.status)
|
||||
})
|
||||
|
||||
const canSubmitMaterial = computed(() => {
|
||||
const currentUserId = useUserStore().getUser.id
|
||||
return projectInfo.value.liaisonUserId === currentUserId && acceptance.value.status === '05'
|
||||
})
|
||||
|
||||
const canSubmitRectify = computed(() => {
|
||||
const currentUserId = useUserStore().getUser.id
|
||||
return projectInfo.value.liaisonUserId === currentUserId && ['11', '60'].includes(acceptance.value.status)
|
||||
})
|
||||
|
||||
const canSubmitFinal = computed(() => {
|
||||
const currentUserId = useUserStore().getUser.id
|
||||
return projectInfo.value.liaisonUserId === currentUserId && acceptance.value.status === '30' // WAIT_FINAL_APPLY
|
||||
})
|
||||
|
||||
const showActions = computed(() => {
|
||||
return canSubmitMaterial.value || canSubmitRectify.value || canSubmitFinal.value || canAudit.value
|
||||
})
|
||||
|
||||
// 是否可以审核 (对口人初审: 10, 专家组长审核: 20)
|
||||
const canAudit = computed(() => {
|
||||
const currentUserId = useUserStore().getUser.id
|
||||
const status = acceptance.value.status
|
||||
// 状态 10: 对口人初审,只有对口人可审核
|
||||
if (status === '10') {
|
||||
return projectInfo.value.serviceUserId === currentUserId
|
||||
}
|
||||
// 状态 20: 专家组长审核,显示审核按钮(后端会校验权限)
|
||||
if (status === '20') {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
// 审核对话框
|
||||
const auditDialogVisible = ref(false)
|
||||
const auditForm = ref({
|
||||
result: '',
|
||||
opinion: ''
|
||||
})
|
||||
const auditFormRef = ref()
|
||||
const auditFormRules = {
|
||||
result: [{ required: true, message: '请选择审核结果', trigger: 'change' }],
|
||||
opinion: [{ required: true, message: '请填写审核意见', trigger: 'blur' }]
|
||||
}
|
||||
|
||||
/** 打开审核对话框 */
|
||||
const openAuditDialog = () => {
|
||||
auditForm.value = { result: '', opinion: '' }
|
||||
auditDialogVisible.value = true
|
||||
}
|
||||
|
||||
/** 提交审核 */
|
||||
const handleAudit = async () => {
|
||||
if (!auditFormRef.value) return
|
||||
const valid = await auditFormRef.value.validate().catch(() => false)
|
||||
if (!valid) return
|
||||
|
||||
try {
|
||||
await AcceptanceApi.auditPreAcceptance({
|
||||
acceptanceId: acceptance.value.id,
|
||||
result: auditForm.value.result,
|
||||
opinion: auditForm.value.opinion
|
||||
})
|
||||
message.success('审核提交成功')
|
||||
auditDialogVisible.value = false
|
||||
await getDetail()
|
||||
} catch (error) {
|
||||
// Error handled by request interceptor
|
||||
}
|
||||
}
|
||||
|
||||
/** 获取验收详情 */
|
||||
const getDetail = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const id = Number(route.params.id)
|
||||
acceptance.value = await AcceptanceApi.getAcceptance(id)
|
||||
|
||||
// 获取项目信息(后端已填充用户名称)
|
||||
if (acceptance.value.projectId) {
|
||||
projectInfo.value = await ProjectApi.getProject(acceptance.value.projectId)
|
||||
// 直接使用后端返回的用户名称
|
||||
liaisonUserName.value = projectInfo.value.liaisonUserName || '-'
|
||||
serviceUserName.value = projectInfo.value.serviceUserName || '-'
|
||||
}
|
||||
|
||||
// 获取验收材料
|
||||
// 1. 获取材料定义
|
||||
const defs = await AcceptanceMaterialDefApi.getListByType(acceptance.value.acceptanceType)
|
||||
// 2. 获取已上传材料
|
||||
const uploads = await AcceptanceMaterialApi.getListByAcceptanceId(id) as unknown as any[]
|
||||
|
||||
// 3. 合并数据
|
||||
materials.value = defs.map((def: any) => {
|
||||
// 查找该材料代码对应的所有上传记录
|
||||
const allUploads = uploads.filter((u: any) => u.materialCode === def.materialCode)
|
||||
// 取最新的一条(按ID倒序,ID越大越新)
|
||||
const upload = allUploads.length > 0 ? allUploads.sort((a: any, b: any) => b.id - a.id)[0] : undefined
|
||||
|
||||
return {
|
||||
...def,
|
||||
materialType: def.requiredFlag ? '必填' : '可选',
|
||||
isRequired: def.requiredFlag, // 方便模板使用
|
||||
fileUrl: upload?.fileUrl,
|
||||
fileName: upload?.fileName,
|
||||
fileSize: upload?.fileSize,
|
||||
uploadId: upload?.id,
|
||||
acceptanceId: id
|
||||
}
|
||||
})
|
||||
|
||||
// 获取审批意见列表
|
||||
// 获取审批意见列表
|
||||
const res = await AcceptanceOpinionApi.getListByAcceptanceId(id)
|
||||
opinions.value = res.sort((a: any, b: any) => new Date(b.createTime).getTime() - new Date(a.createTime).getTime())
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
message.error('获取验收详情失败')
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 返回 */
|
||||
const goBack = () => {
|
||||
router.back()
|
||||
}
|
||||
|
||||
/** 获取文件完整URL */
|
||||
const getFileUrl = (url: string) => {
|
||||
if (!url) return ''
|
||||
if (url.startsWith('http') || url.startsWith('https')) {
|
||||
return url
|
||||
}
|
||||
// 处理相对路径,拼接后端地址
|
||||
return import.meta.env.VITE_BASE_URL + url
|
||||
}
|
||||
|
||||
/** 预览文件 */
|
||||
const handlePreview = (row: any) => {
|
||||
const url = getFileUrl(row.fileUrl)
|
||||
if (url) {
|
||||
window.open(url, '_blank')
|
||||
}
|
||||
}
|
||||
|
||||
/** 下载文件 */
|
||||
const handleDownload = (row: any) => {
|
||||
const url = getFileUrl(row.fileUrl)
|
||||
if (url) {
|
||||
const link = document.createElement('a')
|
||||
link.href = url
|
||||
link.download = row.fileName || row.materialName
|
||||
link.click()
|
||||
}
|
||||
}
|
||||
|
||||
/** 上传成功 */
|
||||
const handleUploadSuccess = async (response: any, file: any, row: any) => {
|
||||
if (response.code === 0) {
|
||||
try {
|
||||
// 调用后端保存材料信息
|
||||
await AcceptanceMaterialApi.createAcceptanceMaterial({
|
||||
acceptanceId: row.acceptanceId,
|
||||
materialCode: row.materialCode,
|
||||
fileName: file.name, // 使用原始文件名
|
||||
fileUrl: response.data,
|
||||
fileSize: file.size || 0,
|
||||
fileType: file.name.split('.').pop(),
|
||||
version: 1,
|
||||
remark: ''
|
||||
} as any)
|
||||
|
||||
message.success('上传成功')
|
||||
// 刷新列表
|
||||
getDetail()
|
||||
} catch (error) {
|
||||
message.error('保存材料记录失败')
|
||||
}
|
||||
} else {
|
||||
message.error('上传失败: ' + response.msg)
|
||||
}
|
||||
}
|
||||
|
||||
/** 提交材料 */
|
||||
const handleSubmitMaterial = async () => {
|
||||
try {
|
||||
// 校验必填项
|
||||
const missing = materials.value.filter((m: any) => m.isRequired && !m.fileUrl)
|
||||
if (missing.length > 0) {
|
||||
message.warning(`请先上传:${missing.map((m: any) => m.materialName).join('、')}`)
|
||||
return
|
||||
}
|
||||
|
||||
await message.confirm('确定提交材料吗?提交后将进入审核流程。')
|
||||
await AcceptanceApi.submitMaterials(acceptance.value.id)
|
||||
message.success('提交成功')
|
||||
await getDetail()
|
||||
} catch {}
|
||||
}
|
||||
|
||||
/** 提交整改 */
|
||||
const handleSubmitRectify = async () => {
|
||||
try {
|
||||
await message.confirm('确定提交整改吗?')
|
||||
if (acceptance.value.acceptanceType === 'PRE') {
|
||||
await AcceptanceApi.submitPreRectify(acceptance.value.id)
|
||||
} else {
|
||||
await AcceptanceApi.submitFinalRectify(acceptance.value.id)
|
||||
}
|
||||
message.success('提交成功')
|
||||
await getDetail()
|
||||
} catch {}
|
||||
}
|
||||
|
||||
/** 提交终验申请 */
|
||||
const handleSubmitFinal = async () => {
|
||||
try {
|
||||
await message.confirm('确定提交终验申请吗?')
|
||||
await AcceptanceApi.submitFinalAcceptance({ acceptanceId: acceptance.value.id })
|
||||
message.success('提交成功')
|
||||
await getDetail()
|
||||
} catch {}
|
||||
}
|
||||
|
||||
/** 流程步骤 */
|
||||
const activeStep = computed(() => {
|
||||
const status = acceptance.value.status
|
||||
if (['00', '05'].includes(status)) return 0
|
||||
if (['10', '11', '20'].includes(status)) return 1
|
||||
if (['30'].includes(status)) return 2
|
||||
if (['40', '50', '60', '61', '62'].includes(status)) return 3
|
||||
if (['99'].includes(status)) return 4
|
||||
return 0
|
||||
})
|
||||
|
||||
/** 获取文件图标 */
|
||||
const getFileIcon = (fileName?: string) => {
|
||||
if (!fileName) return 'ep:document'
|
||||
const ext = fileName.split('.').pop()?.toLowerCase()
|
||||
if (['doc', 'docx'].includes(ext)) return 'ep:document'
|
||||
if (['xls', 'xlsx'].includes(ext)) return 'ep:data-analysis'
|
||||
if (['pdf'].includes(ext)) return 'ep:document-copy'
|
||||
if (['jpg', 'jpeg', 'png', 'gif'].includes(ext)) return 'ep:picture'
|
||||
if (['zip', 'rar'].includes(ext)) return 'ep:folder'
|
||||
return 'ep:document'
|
||||
}
|
||||
|
||||
/** 获取文件图标背景色 */
|
||||
const getFileIconColor = (fileName?: string) => {
|
||||
if (!fileName) return 'bg-gray-400'
|
||||
const ext = fileName.split('.').pop()?.toLowerCase()
|
||||
if (['doc', 'docx'].includes(ext)) return 'bg-blue-500'
|
||||
if (['xls', 'xlsx'].includes(ext)) return 'bg-green-500'
|
||||
if (['pdf'].includes(ext)) return 'bg-red-500'
|
||||
if (['jpg', 'jpeg', 'png', 'gif'].includes(ext)) return 'bg-purple-500'
|
||||
if (['zip', 'rar'].includes(ext)) return 'bg-orange-500'
|
||||
return 'bg-gray-400'
|
||||
}
|
||||
|
||||
/** 初始化 */
|
||||
onMounted(() => {
|
||||
if (route.query.tab) {
|
||||
activeTab.value = route.query.tab as string
|
||||
}
|
||||
getDetail()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.inline-block {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/* 覆盖 el-steps 进行中状态的颜色为绿色 */
|
||||
:deep(.el-step__head.is-process) {
|
||||
color: #67c23a;
|
||||
border-color: #67c23a;
|
||||
}
|
||||
:deep(.el-step__title.is-process) {
|
||||
color: #67c23a;
|
||||
font-weight: bold;
|
||||
}
|
||||
:deep(.el-step__description.is-process) {
|
||||
color: #67c23a;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,303 @@
|
|||
<template>
|
||||
<ContentWrap>
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form
|
||||
class="-mb-15px"
|
||||
:model="queryParams"
|
||||
ref="queryFormRef"
|
||||
:inline="true"
|
||||
label-width="80px"
|
||||
>
|
||||
<el-form-item label="项目ID" prop="projectId">
|
||||
<el-input
|
||||
v-model="queryParams.projectId"
|
||||
placeholder="请输入项目ID"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-180px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="验收类型" prop="acceptanceType">
|
||||
<el-select
|
||||
v-model="queryParams.acceptanceType"
|
||||
placeholder="请选择验收类型"
|
||||
clearable
|
||||
class="!w-180px"
|
||||
>
|
||||
<el-option label="预验收" value="PRE" />
|
||||
<el-option label="终验" value="FINAL" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="验收状态" prop="status">
|
||||
<el-select
|
||||
v-model="queryParams.status"
|
||||
placeholder="请选择验收状态"
|
||||
clearable
|
||||
class="!w-180px"
|
||||
>
|
||||
<el-option label="待审核" value="10" />
|
||||
<el-option label="审核中" value="20" />
|
||||
<el-option label="待会议" value="30" />
|
||||
<el-option label="待整改" value="40" />
|
||||
<el-option label="已通过" value="80" />
|
||||
<el-option label="已驳回" value="90" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="轮次" prop="round">
|
||||
<el-input-number
|
||||
v-model="queryParams.round"
|
||||
:min="1"
|
||||
placeholder="轮次"
|
||||
class="!w-120px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="创建时间" prop="createTime">
|
||||
<el-date-picker
|
||||
v-model="queryParams.createTime"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
type="datetimerange"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="handleQuery"><Icon icon="ep:search" />搜索</el-button>
|
||||
<el-button @click="resetQuery"><Icon icon="ep:refresh" />重置</el-button>
|
||||
<el-button
|
||||
type="success"
|
||||
plain
|
||||
@click="handleExport"
|
||||
:loading="exportLoading"
|
||||
v-hasPermi="['project:acceptance:export']"
|
||||
>
|
||||
<Icon icon="ep:download" />导出
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 列表 -->
|
||||
<ContentWrap>
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="验收ID" align="center" prop="id" width="80" />
|
||||
<el-table-column label="项目ID" align="center" prop="projectId" width="80" />
|
||||
<el-table-column label="验收类型" align="center" prop="acceptanceType" width="100">
|
||||
<template #default="scope">
|
||||
<el-tag v-if="scope.row.acceptanceType === 'PRE'" type="info">预验收</el-tag>
|
||||
<el-tag v-else-if="scope.row.acceptanceType === 'FINAL'" type="primary">终验</el-tag>
|
||||
<el-tag v-else>{{ scope.row.acceptanceType }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" align="center" prop="status" width="100">
|
||||
<template #default="scope">
|
||||
<el-tag :type="getStatusType(scope.row.status)">{{ getStatusLabel(scope.row.status) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="轮次" align="center" prop="round" width="80" />
|
||||
<el-table-column label="流程实例ID" align="center" prop="processInstanceId" :show-overflow-tooltip="true" />
|
||||
<el-table-column
|
||||
label="启动时间"
|
||||
align="center"
|
||||
prop="startTime"
|
||||
:formatter="dateFormatter"
|
||||
width="180"
|
||||
/>
|
||||
<el-table-column
|
||||
label="完成时间"
|
||||
align="center"
|
||||
prop="endTime"
|
||||
:formatter="dateFormatter"
|
||||
width="180"
|
||||
/>
|
||||
<el-table-column
|
||||
label="创建时间"
|
||||
align="center"
|
||||
prop="createTime"
|
||||
:formatter="dateFormatter"
|
||||
width="180"
|
||||
/>
|
||||
<el-table-column label="操作" align="center" width="200" fixed="right">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
@click="handleView(scope.row)"
|
||||
>
|
||||
查看
|
||||
</el-button>
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
@click="openAuditForm(scope.row)"
|
||||
v-if="canAudit(scope.row)"
|
||||
>
|
||||
审核
|
||||
</el-button>
|
||||
<el-button
|
||||
link
|
||||
type="warning"
|
||||
@click="handleForceArchive(scope.row)"
|
||||
v-hasPermi="['project:acceptance:force-archive']"
|
||||
>
|
||||
强制归档
|
||||
</el-button>
|
||||
<el-button
|
||||
link
|
||||
type="danger"
|
||||
@click="handleCancel(scope.row)"
|
||||
v-hasPermi="['project:acceptance:cancel']"
|
||||
>
|
||||
取消
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页 -->
|
||||
<Pagination
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNo"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 审核表单弹窗 -->
|
||||
<AcceptanceAuditForm ref="auditFormRef" @success="getList" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { dateFormatter } from '@/utils/formatTime'
|
||||
import download from '@/utils/download'
|
||||
import * as AcceptanceApi from '@/api/project/acceptance'
|
||||
import AcceptanceAuditForm from './AcceptanceAuditForm.vue'
|
||||
|
||||
defineOptions({ name: 'ProjectAcceptance' })
|
||||
|
||||
const message = useMessage() // 消息弹窗
|
||||
const { t } = useI18n() // 国际化
|
||||
const router = useRouter()
|
||||
|
||||
const loading = ref(true) // 列表的加载中
|
||||
const total = ref(0) // 列表的总页数
|
||||
const list = ref([]) // 列表的数据
|
||||
const queryParams = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
projectId: undefined,
|
||||
acceptanceType: undefined,
|
||||
status: undefined,
|
||||
round: undefined,
|
||||
createTime: []
|
||||
})
|
||||
const queryFormRef = ref() // 搜索的表单
|
||||
const exportLoading = ref(false) // 导出的加载中
|
||||
|
||||
// 状态映射
|
||||
const statusMap: Record<string, { label: string; type: string }> = {
|
||||
'10': { label: '待审核', type: 'info' },
|
||||
'20': { label: '审核中', type: 'warning' },
|
||||
'30': { label: '待会议', type: '' },
|
||||
'40': { label: '待整改', type: 'danger' },
|
||||
'80': { label: '已通过', type: 'success' },
|
||||
'90': { label: '已驳回', type: 'danger' }
|
||||
}
|
||||
|
||||
const getStatusLabel = (status: string) => {
|
||||
return statusMap[status]?.label || status
|
||||
}
|
||||
|
||||
const getStatusType = (status: string) => {
|
||||
return statusMap[status]?.type || 'info'
|
||||
}
|
||||
|
||||
/** 判断是否可以审核 */
|
||||
const canAudit = (row: AcceptanceApi.AcceptanceVO) => {
|
||||
return ['10', '20', '40'].includes(row.status)
|
||||
}
|
||||
|
||||
/** 查询列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const data = await AcceptanceApi.getAcceptancePage(queryParams)
|
||||
list.value = data.list
|
||||
total.value = data.total
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
const handleQuery = () => {
|
||||
queryParams.pageNo = 1
|
||||
getList()
|
||||
}
|
||||
|
||||
/** 重置按钮操作 */
|
||||
const resetQuery = () => {
|
||||
queryFormRef.value.resetFields()
|
||||
handleQuery()
|
||||
}
|
||||
|
||||
/** 查看详情 */
|
||||
const handleView = (row: AcceptanceApi.AcceptanceVO) => {
|
||||
router.push({ path: '/project/acceptance/detail/' + row.id })
|
||||
}
|
||||
|
||||
/** 打开审核表单 */
|
||||
const auditFormRef = ref()
|
||||
const openAuditForm = (row: AcceptanceApi.AcceptanceVO) => {
|
||||
auditFormRef.value.open(row)
|
||||
}
|
||||
|
||||
/** 强制归档 */
|
||||
const handleForceArchive = async (row: AcceptanceApi.AcceptanceVO) => {
|
||||
try {
|
||||
const { value } = await ElMessageBox.prompt('请输入强制归档原因', '强制归档', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
inputPattern: /.+/,
|
||||
inputErrorMessage: '原因不能为空'
|
||||
})
|
||||
await AcceptanceApi.forceArchive(row.id, value)
|
||||
message.success('强制归档成功')
|
||||
await getList()
|
||||
} catch {}
|
||||
}
|
||||
|
||||
/** 取消验收 */
|
||||
const handleCancel = async (row: AcceptanceApi.AcceptanceVO) => {
|
||||
try {
|
||||
const { value } = await ElMessageBox.prompt('请输入取消原因', '取消验收', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
inputPattern: /.+/,
|
||||
inputErrorMessage: '原因不能为空'
|
||||
})
|
||||
await AcceptanceApi.cancelAcceptance(row.id, value)
|
||||
message.success('取消验收成功')
|
||||
await getList()
|
||||
} catch {}
|
||||
}
|
||||
|
||||
/** 导出按钮操作 */
|
||||
const handleExport = async () => {
|
||||
try {
|
||||
// 导出的二次确认
|
||||
await message.exportConfirm()
|
||||
// 发起导出
|
||||
exportLoading.value = true
|
||||
const data = await AcceptanceApi.exportAcceptance(queryParams)
|
||||
download.excel(data, '验收数据.xls')
|
||||
} catch {
|
||||
} finally {
|
||||
exportLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 初始化 **/
|
||||
onMounted(() => {
|
||||
getList()
|
||||
})
|
||||
</script>
|
||||
|
|
@ -0,0 +1,143 @@
|
|||
<template>
|
||||
<ContentWrap>
|
||||
<div class="mb-4">
|
||||
<el-alert
|
||||
title="待办任务"
|
||||
type="info"
|
||||
description="以下是您需要处理的验收任务"
|
||||
:closable="false"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<el-table v-loading="loading" :data="list" stripe>
|
||||
<el-table-column label="项目名称" align="center" prop="projectName" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="项目编号" align="center" prop="projectCode" width="150" />
|
||||
<el-table-column label="验收类型" align="center" prop="acceptanceType" width="100">
|
||||
<template #default="scope">
|
||||
<el-tag v-if="scope.row.acceptanceType === 'PRE'" type="info">预验收</el-tag>
|
||||
<el-tag v-else-if="scope.row.acceptanceType === 'FINAL'" type="primary">终验</el-tag>
|
||||
<el-tag v-else>{{ scope.row.acceptanceType }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="验收状态" align="center" prop="statusDesc" width="120" />
|
||||
<el-table-column label="轮次" align="center" prop="round" width="80" />
|
||||
<el-table-column label="任务类型" align="center" prop="taskTypeDesc" width="150" />
|
||||
<el-table-column label="任务名称" align="center" prop="taskName" :show-overflow-tooltip="true" />
|
||||
<el-table-column
|
||||
label="创建时间"
|
||||
align="center"
|
||||
prop="createTime"
|
||||
:formatter="dateFormatter"
|
||||
width="180"
|
||||
/>
|
||||
<el-table-column label="操作" align="center" width="150" fixed="right">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
@click="handleProcess(scope.row)"
|
||||
>
|
||||
<Icon icon="ep:check" /> 处理
|
||||
</el-button>
|
||||
<el-button
|
||||
link
|
||||
type="info"
|
||||
@click="handleView(scope.row)"
|
||||
>
|
||||
<Icon icon="ep:view" /> 查看
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 审核表单弹窗 -->
|
||||
<AcceptanceAuditForm ref="auditFormRef" @success="getList" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { dateFormatter } from '@/utils/formatTime'
|
||||
import * as AcceptanceApi from '@/api/project/acceptance'
|
||||
import AcceptanceAuditForm from '../AcceptanceAuditForm.vue'
|
||||
|
||||
defineOptions({ name: 'AcceptanceTodo' })
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
const loading = ref(true) // 列表的加载中
|
||||
const list = ref<AcceptanceApi.AcceptanceTodoVO[]>([]) // 列表的数据
|
||||
|
||||
/** 查询待办列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
list.value = await AcceptanceApi.getTodoList()
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 处理任务 */
|
||||
const auditFormRef = ref()
|
||||
const handleProcess = (row: AcceptanceApi.AcceptanceTodoVO) => {
|
||||
// 根据任务类型打开不同的处理界面
|
||||
const taskType = row.taskType
|
||||
if (['LIAISON_REVIEW', 'LEADER_REVIEW', 'ADMIN_REVIEW', 'EXPERT_CHECK'].includes(taskType)) {
|
||||
// 打开审核表单
|
||||
auditFormRef.value.open({
|
||||
id: row.acceptanceId,
|
||||
acceptanceType: row.acceptanceType,
|
||||
status: row.status
|
||||
}, getAuditType(taskType))
|
||||
} else if (taskType === 'RECTIFY_SUBMIT' || taskType === 'task_pre_rectify' || taskType === 'task_final_rectify') {
|
||||
// 整改任务,跳转到详情页的材料tab让用户完善材料
|
||||
router.push({ path: '/project/acceptance/detail/' + row.acceptanceId, query: { tab: 'materials' } })
|
||||
} else if (taskType === 'LIAISON_SUBMIT' || taskType === 'task_liaison_submit') {
|
||||
// 联络人提交材料,跳转到详情页的材料tab
|
||||
router.push({ path: '/project/acceptance/detail/' + row.acceptanceId, query: { tab: 'materials' } })
|
||||
} else {
|
||||
// 默认查看详情
|
||||
handleView(row)
|
||||
}
|
||||
}
|
||||
|
||||
/** 获取审核类型 */
|
||||
const getAuditType = (taskType: string) => {
|
||||
switch (taskType) {
|
||||
case 'LIAISON_REVIEW':
|
||||
case 'LEADER_REVIEW':
|
||||
return 'pre-audit'
|
||||
case 'ADMIN_REVIEW':
|
||||
return 'final-admin'
|
||||
case 'EXPERT_CHECK':
|
||||
return 'expert-check'
|
||||
default:
|
||||
return 'pre-audit'
|
||||
}
|
||||
}
|
||||
|
||||
/** 提交整改 */
|
||||
const message = useMessage()
|
||||
const handleSubmitRectify = async (row: AcceptanceApi.AcceptanceTodoVO) => {
|
||||
try {
|
||||
await message.confirm('确定提交整改吗?')
|
||||
if (row.acceptanceType === 'PRE') {
|
||||
await AcceptanceApi.submitPreRectify(row.acceptanceId)
|
||||
} else {
|
||||
await AcceptanceApi.submitFinalRectify(row.acceptanceId)
|
||||
}
|
||||
message.success('整改提交成功')
|
||||
await getList()
|
||||
} catch {}
|
||||
}
|
||||
|
||||
/** 查看详情 */
|
||||
const handleView = (row: AcceptanceApi.AcceptanceTodoVO) => {
|
||||
router.push({ path: '/project/acceptance/detail/' + row.acceptanceId, query: { tab: 'info' } })
|
||||
}
|
||||
|
||||
/** 初始化 **/
|
||||
onMounted(() => {
|
||||
getList()
|
||||
})
|
||||
</script>
|
||||
|
|
@ -0,0 +1,179 @@
|
|||
<template>
|
||||
<Dialog v-model="dialogVisible" :title="dialogTitle">
|
||||
<el-form
|
||||
ref="formRef"
|
||||
v-loading="formLoading"
|
||||
:model="formData"
|
||||
:rules="formRules"
|
||||
label-width="100px"
|
||||
>
|
||||
<el-form-item label="验收ID" prop="acceptanceId">
|
||||
<el-input v-model="formData.acceptanceId" placeholder="请输入验收ID" />
|
||||
</el-form-item>
|
||||
<el-form-item label="材料编号" prop="materialCode">
|
||||
<el-select v-model="formData.materialCode" placeholder="请选择材料类型" filterable>
|
||||
<el-option
|
||||
v-for="def in materialDefList"
|
||||
:key="def.materialCode"
|
||||
:label="def.materialName + ' (' + def.materialCode + ')'"
|
||||
:value="def.materialCode"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="上传文件" prop="fileUrl">
|
||||
<el-upload
|
||||
:action="uploadUrl"
|
||||
:headers="uploadHeaders"
|
||||
:show-file-list="false"
|
||||
:on-success="handleUploadSuccess"
|
||||
:before-upload="beforeUpload"
|
||||
>
|
||||
<el-button type="primary">选择文件</el-button>
|
||||
</el-upload>
|
||||
<div v-if="formData.fileName" class="mt-2">
|
||||
<el-tag>{{ formData.fileName }}</el-tag>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="版本号" prop="version">
|
||||
<el-input-number v-model="formData.version" :min="1" />
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input
|
||||
v-model="formData.remark"
|
||||
type="textarea"
|
||||
:rows="3"
|
||||
placeholder="请输入备注"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||
</template>
|
||||
</Dialog>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import * as AcceptanceMaterialApi from '@/api/project/acceptanceMaterial'
|
||||
import * as AcceptanceMaterialDefApi from '@/api/project/acceptanceMaterialDef'
|
||||
import { FormRules } from 'element-plus'
|
||||
import { getAccessToken } from '@/utils/auth'
|
||||
|
||||
defineOptions({ name: 'AcceptanceMaterialForm' })
|
||||
|
||||
const { t } = useI18n() // 国际化
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||
const dialogTitle = ref('') // 弹窗的标题
|
||||
const formLoading = ref(false) // 表单的加载中
|
||||
const formType = ref('') // 表单的类型:create - 新增;update - 修改
|
||||
const formData = ref({
|
||||
id: undefined,
|
||||
acceptanceId: undefined,
|
||||
materialCode: '',
|
||||
fileName: '',
|
||||
fileUrl: '',
|
||||
fileSize: 0,
|
||||
fileType: '',
|
||||
version: 1,
|
||||
remark: ''
|
||||
})
|
||||
const formRules = reactive<FormRules>({
|
||||
acceptanceId: [{ required: true, message: '验收ID不能为空', trigger: 'blur' }],
|
||||
materialCode: [{ required: true, message: '材料编号不能为空', trigger: 'change' }],
|
||||
fileUrl: [{ required: true, message: '请上传文件', trigger: 'change' }]
|
||||
})
|
||||
const formRef = ref() // 表单 Ref
|
||||
const materialDefList = ref<AcceptanceMaterialDefApi.AcceptanceMaterialDefVO[]>([]) // 材料定义列表
|
||||
|
||||
// 上传配置
|
||||
const uploadUrl = import.meta.env.VITE_BASE_URL + '/infra/file/upload'
|
||||
const uploadHeaders = { Authorization: 'Bearer ' + getAccessToken() }
|
||||
|
||||
/** 打开弹窗 */
|
||||
const open = async (type: string, id?: number) => {
|
||||
dialogVisible.value = true
|
||||
dialogTitle.value = t('action.' + type)
|
||||
formType.value = type
|
||||
resetForm()
|
||||
// 加载材料定义列表
|
||||
const defResult = await AcceptanceMaterialDefApi.getAcceptanceMaterialDefPage({ pageNo: 1, pageSize: 100 })
|
||||
materialDefList.value = defResult.list
|
||||
// 修改时,设置数据
|
||||
if (id) {
|
||||
formLoading.value = true
|
||||
try {
|
||||
formData.value = await AcceptanceMaterialApi.getAcceptanceMaterial(id)
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
}
|
||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||
|
||||
/** 上传前校验 */
|
||||
const beforeUpload = (file: File) => {
|
||||
const maxSize = 50 * 1024 * 1024 // 50MB
|
||||
if (file.size > maxSize) {
|
||||
message.error('文件大小不能超过50MB')
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
/** 上传成功 */
|
||||
const handleUploadSuccess = (response: any, file: File) => {
|
||||
if (response.code === 0) {
|
||||
formData.value.fileUrl = response.data
|
||||
formData.value.fileName = file.name
|
||||
formData.value.fileSize = file.size
|
||||
formData.value.fileType = file.name.split('.').pop() || ''
|
||||
message.success('上传成功')
|
||||
} else {
|
||||
message.error('上传失败: ' + response.msg)
|
||||
}
|
||||
}
|
||||
|
||||
/** 提交表单 */
|
||||
const emit = defineEmits(['success']) // 定义 success 事件
|
||||
const submitForm = async () => {
|
||||
// 校验表单
|
||||
if (!formRef.value) return
|
||||
const valid = await formRef.value.validate()
|
||||
if (!valid) return
|
||||
// 提交请求
|
||||
formLoading.value = true
|
||||
try {
|
||||
const data = formData.value as unknown as AcceptanceMaterialApi.AcceptanceMaterialVO
|
||||
if (formType.value === 'create') {
|
||||
await AcceptanceMaterialApi.createAcceptanceMaterial(data)
|
||||
message.success(t('common.createSuccess'))
|
||||
} else {
|
||||
await AcceptanceMaterialApi.updateAcceptanceMaterial(data)
|
||||
message.success(t('common.updateSuccess'))
|
||||
}
|
||||
dialogVisible.value = false
|
||||
// 发送操作成功的事件
|
||||
emit('success')
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 重置表单 */
|
||||
const resetForm = () => {
|
||||
formData.value = {
|
||||
id: undefined,
|
||||
acceptanceId: undefined,
|
||||
materialCode: '',
|
||||
fileName: '',
|
||||
fileUrl: '',
|
||||
fileSize: 0,
|
||||
fileType: '',
|
||||
version: 1,
|
||||
remark: ''
|
||||
}
|
||||
formRef.value?.resetFields()
|
||||
}
|
||||
</script>
|
||||
|
|
@ -0,0 +1,227 @@
|
|||
<template>
|
||||
<ContentWrap>
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form
|
||||
class="-mb-15px"
|
||||
:model="queryParams"
|
||||
ref="queryFormRef"
|
||||
:inline="true"
|
||||
label-width="80px"
|
||||
>
|
||||
<el-form-item label="验收ID" prop="acceptanceId">
|
||||
<el-input
|
||||
v-model="queryParams.acceptanceId"
|
||||
placeholder="请输入验收ID"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-180px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="材料编号" prop="materialCode">
|
||||
<el-input
|
||||
v-model="queryParams.materialCode"
|
||||
placeholder="请输入材料编号"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-180px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="文件名" prop="fileName">
|
||||
<el-input
|
||||
v-model="queryParams.fileName"
|
||||
placeholder="请输入文件名"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-180px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="handleQuery"><Icon icon="ep:search" />搜索</el-button>
|
||||
<el-button @click="resetQuery"><Icon icon="ep:refresh" />重置</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
@click="openForm('create')"
|
||||
v-hasPermi="['project:acceptance-material:create']"
|
||||
>
|
||||
<Icon icon="ep:plus" /> 新增
|
||||
</el-button>
|
||||
<el-button
|
||||
type="success"
|
||||
plain
|
||||
@click="handleExport"
|
||||
:loading="exportLoading"
|
||||
v-hasPermi="['project:acceptance-material:export']"
|
||||
>
|
||||
<Icon icon="ep:download" />导出
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 列表 -->
|
||||
<ContentWrap>
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="ID" align="center" prop="id" width="80" />
|
||||
<el-table-column label="验收ID" align="center" prop="acceptanceId" width="100" />
|
||||
<el-table-column label="材料编号" align="center" prop="materialCode" width="150" />
|
||||
<el-table-column label="文件名" align="center" prop="fileName" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="文件类型" align="center" prop="fileType" width="100" />
|
||||
<el-table-column label="文件大小" align="center" prop="fileSize" width="100">
|
||||
<template #default="scope">
|
||||
{{ formatFileSize(scope.row.fileSize) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="版本" align="center" prop="version" width="80" />
|
||||
<el-table-column
|
||||
label="上传时间"
|
||||
align="center"
|
||||
prop="uploadTime"
|
||||
:formatter="dateFormatter"
|
||||
width="180"
|
||||
/>
|
||||
<el-table-column label="操作" align="center" width="200" fixed="right">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
@click="handleDownload(scope.row)"
|
||||
>
|
||||
下载
|
||||
</el-button>
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
@click="openForm('update', scope.row.id)"
|
||||
v-hasPermi="['project:acceptance-material:update']"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button
|
||||
link
|
||||
type="danger"
|
||||
@click="handleDelete(scope.row.id)"
|
||||
v-hasPermi="['project:acceptance-material:delete']"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页 -->
|
||||
<Pagination
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNo"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 表单弹窗:添加/修改 -->
|
||||
<AcceptanceMaterialForm ref="formRef" @success="getList" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { dateFormatter } from '@/utils/formatTime'
|
||||
import download from '@/utils/download'
|
||||
import * as AcceptanceMaterialApi from '@/api/project/acceptanceMaterial'
|
||||
import AcceptanceMaterialForm from './AcceptanceMaterialForm.vue'
|
||||
|
||||
defineOptions({ name: 'AcceptanceMaterial' })
|
||||
|
||||
const message = useMessage() // 消息弹窗
|
||||
const { t } = useI18n() // 国际化
|
||||
|
||||
const loading = ref(true) // 列表的加载中
|
||||
const total = ref(0) // 列表的总页数
|
||||
const list = ref([]) // 列表的数据
|
||||
const queryParams = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
acceptanceId: undefined,
|
||||
materialCode: undefined,
|
||||
fileName: undefined
|
||||
})
|
||||
const queryFormRef = ref() // 搜索的表单
|
||||
const exportLoading = ref(false) // 导出的加载中
|
||||
|
||||
/** 格式化文件大小 */
|
||||
const formatFileSize = (size: number) => {
|
||||
if (!size) return '-'
|
||||
if (size < 1024) return size + ' B'
|
||||
if (size < 1024 * 1024) return (size / 1024).toFixed(2) + ' KB'
|
||||
return (size / 1024 / 1024).toFixed(2) + ' MB'
|
||||
}
|
||||
|
||||
/** 查询列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const data = await AcceptanceMaterialApi.getAcceptanceMaterialPage(queryParams)
|
||||
list.value = data.list
|
||||
total.value = data.total
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
const handleQuery = () => {
|
||||
queryParams.pageNo = 1
|
||||
getList()
|
||||
}
|
||||
|
||||
/** 重置按钮操作 */
|
||||
const resetQuery = () => {
|
||||
queryFormRef.value.resetFields()
|
||||
handleQuery()
|
||||
}
|
||||
|
||||
/** 添加/修改操作 */
|
||||
const formRef = ref()
|
||||
const openForm = (type: string, id?: number) => {
|
||||
formRef.value.open(type, id)
|
||||
}
|
||||
|
||||
/** 下载文件 */
|
||||
const handleDownload = (row: AcceptanceMaterialApi.AcceptanceMaterialVO) => {
|
||||
if (row.fileUrl) {
|
||||
window.open(row.fileUrl, '_blank')
|
||||
} else {
|
||||
message.warning('文件地址不存在')
|
||||
}
|
||||
}
|
||||
|
||||
/** 删除按钮操作 */
|
||||
const handleDelete = async (id: number) => {
|
||||
try {
|
||||
// 删除的二次确认
|
||||
await message.delConfirm()
|
||||
// 发起删除
|
||||
await AcceptanceMaterialApi.deleteAcceptanceMaterial(id)
|
||||
message.success(t('common.delSuccess'))
|
||||
// 刷新列表
|
||||
await getList()
|
||||
} catch {}
|
||||
}
|
||||
|
||||
/** 导出按钮操作 */
|
||||
const handleExport = async () => {
|
||||
try {
|
||||
// 导出的二次确认
|
||||
await message.exportConfirm()
|
||||
// 发起导出
|
||||
exportLoading.value = true
|
||||
const data = await AcceptanceMaterialApi.exportAcceptanceMaterial(queryParams)
|
||||
download.excel(data, '验收材料.xls')
|
||||
} catch {
|
||||
} finally {
|
||||
exportLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 初始化 **/
|
||||
onMounted(() => {
|
||||
getList()
|
||||
})
|
||||
</script>
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
<template>
|
||||
<Dialog v-model="dialogVisible" :title="dialogTitle">
|
||||
<el-form
|
||||
ref="formRef"
|
||||
v-loading="formLoading"
|
||||
:model="formData"
|
||||
:rules="formRules"
|
||||
label-width="100px"
|
||||
>
|
||||
<el-form-item label="验收类型" prop="acceptanceType">
|
||||
<el-select v-model="formData.acceptanceType" placeholder="请选择验收类型">
|
||||
<el-option label="预验收" value="PRE" />
|
||||
<el-option label="终验" value="FINAL" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="材料编码" prop="materialCode">
|
||||
<el-input v-model="formData.materialCode" placeholder="请输入材料编码" />
|
||||
</el-form-item>
|
||||
<el-form-item label="材料名称" prop="materialName">
|
||||
<el-input v-model="formData.materialName" placeholder="请输入材料名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="是否必传" prop="requiredFlag">
|
||||
<el-switch v-model="formData.requiredFlag" />
|
||||
</el-form-item>
|
||||
<el-form-item label="上传角色" prop="uploadRole">
|
||||
<el-select v-model="formData.uploadRole" placeholder="请选择上传角色" clearable>
|
||||
<el-option label="申报单位" value="APPLICANT" />
|
||||
<el-option label="网信办" value="ADMIN" />
|
||||
<el-option label="专家" value="EXPERT" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="排序" prop="sort">
|
||||
<el-input-number v-model="formData.sort" :min="0" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||
</template>
|
||||
</Dialog>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import * as AcceptanceMaterialDefApi from '@/api/project/acceptanceMaterialDef'
|
||||
import { FormRules } from 'element-plus'
|
||||
|
||||
defineOptions({ name: 'AcceptanceMaterialDefForm' })
|
||||
|
||||
const { t } = useI18n() // 国际化
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||
const dialogTitle = ref('') // 弹窗的标题
|
||||
const formLoading = ref(false) // 表单的加载中
|
||||
const formType = ref('') // 表单的类型:create - 新增;update - 修改
|
||||
const formData = ref({
|
||||
id: undefined,
|
||||
acceptanceType: 'PRE',
|
||||
materialCode: '',
|
||||
materialName: '',
|
||||
requiredFlag: false,
|
||||
uploadRole: '',
|
||||
sort: 0
|
||||
})
|
||||
const formRules = reactive<FormRules>({
|
||||
acceptanceType: [{ required: true, message: '验收类型不能为空', trigger: 'change' }],
|
||||
materialCode: [{ required: true, message: '材料编码不能为空', trigger: 'blur' }],
|
||||
materialName: [{ required: true, message: '材料名称不能为空', trigger: 'blur' }]
|
||||
})
|
||||
const formRef = ref() // 表单 Ref
|
||||
|
||||
/** 打开弹窗 */
|
||||
const open = async (type: string, id?: number) => {
|
||||
dialogVisible.value = true
|
||||
dialogTitle.value = t('action.' + type)
|
||||
formType.value = type
|
||||
resetForm()
|
||||
// 修改时,设置数据
|
||||
if (id) {
|
||||
formLoading.value = true
|
||||
try {
|
||||
formData.value = await AcceptanceMaterialDefApi.getAcceptanceMaterialDef(id)
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
}
|
||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||
|
||||
/** 提交表单 */
|
||||
const emit = defineEmits(['success']) // 定义 success 事件
|
||||
const submitForm = async () => {
|
||||
// 校验表单
|
||||
if (!formRef.value) return
|
||||
const valid = await formRef.value.validate()
|
||||
if (!valid) return
|
||||
// 提交请求
|
||||
formLoading.value = true
|
||||
try {
|
||||
const data = formData.value as unknown as AcceptanceMaterialDefApi.AcceptanceMaterialDefVO
|
||||
if (formType.value === 'create') {
|
||||
await AcceptanceMaterialDefApi.createAcceptanceMaterialDef(data)
|
||||
message.success(t('common.createSuccess'))
|
||||
} else {
|
||||
await AcceptanceMaterialDefApi.updateAcceptanceMaterialDef(data)
|
||||
message.success(t('common.updateSuccess'))
|
||||
}
|
||||
dialogVisible.value = false
|
||||
// 发送操作成功的事件
|
||||
emit('success')
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 重置表单 */
|
||||
const resetForm = () => {
|
||||
formData.value = {
|
||||
id: undefined,
|
||||
acceptanceType: 'PRE',
|
||||
materialCode: '',
|
||||
materialName: '',
|
||||
requiredFlag: false,
|
||||
uploadRole: '',
|
||||
sort: 0
|
||||
}
|
||||
formRef.value?.resetFields()
|
||||
}
|
||||
</script>
|
||||
|
|
@ -0,0 +1,212 @@
|
|||
<template>
|
||||
<ContentWrap>
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form
|
||||
class="-mb-15px"
|
||||
:model="queryParams"
|
||||
ref="queryFormRef"
|
||||
:inline="true"
|
||||
label-width="80px"
|
||||
>
|
||||
<el-form-item label="验收类型" prop="acceptanceType">
|
||||
<el-select
|
||||
v-model="queryParams.acceptanceType"
|
||||
placeholder="请选择验收类型"
|
||||
clearable
|
||||
class="!w-180px"
|
||||
>
|
||||
<el-option label="预验收" value="PRE" />
|
||||
<el-option label="终验" value="FINAL" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="材料编码" prop="materialCode">
|
||||
<el-input
|
||||
v-model="queryParams.materialCode"
|
||||
placeholder="请输入材料编码"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-180px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="材料名称" prop="materialName">
|
||||
<el-input
|
||||
v-model="queryParams.materialName"
|
||||
placeholder="请输入材料名称"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-180px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="handleQuery"><Icon icon="ep:search" />搜索</el-button>
|
||||
<el-button @click="resetQuery"><Icon icon="ep:refresh" />重置</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
@click="openForm('create')"
|
||||
v-hasPermi="['project:acceptance-material-def:create']"
|
||||
>
|
||||
<Icon icon="ep:plus" /> 新增
|
||||
</el-button>
|
||||
<el-button
|
||||
type="success"
|
||||
plain
|
||||
@click="handleExport"
|
||||
:loading="exportLoading"
|
||||
v-hasPermi="['project:acceptance-material-def:export']"
|
||||
>
|
||||
<Icon icon="ep:download" />导出
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 列表 -->
|
||||
<ContentWrap>
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="ID" align="center" prop="id" width="80" />
|
||||
<el-table-column label="验收类型" align="center" prop="acceptanceType" width="100">
|
||||
<template #default="scope">
|
||||
<el-tag v-if="scope.row.acceptanceType === 'PRE'" type="info">预验收</el-tag>
|
||||
<el-tag v-else-if="scope.row.acceptanceType === 'FINAL'" type="primary">终验</el-tag>
|
||||
<el-tag v-else>{{ scope.row.acceptanceType }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="材料编码" align="center" prop="materialCode" width="150" />
|
||||
<el-table-column label="材料名称" align="center" prop="materialName" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="是否必传" align="center" prop="requiredFlag" width="100">
|
||||
<template #default="scope">
|
||||
<el-tag v-if="scope.row.requiredFlag" type="danger">必传</el-tag>
|
||||
<el-tag v-else type="info">非必传</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="上传角色" align="center" prop="uploadRole" width="120" />
|
||||
<el-table-column label="排序" align="center" prop="sort" width="80" />
|
||||
<el-table-column
|
||||
label="创建时间"
|
||||
align="center"
|
||||
prop="createTime"
|
||||
:formatter="dateFormatter"
|
||||
width="180"
|
||||
/>
|
||||
<el-table-column label="操作" align="center" width="150" fixed="right">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
@click="openForm('update', scope.row.id)"
|
||||
v-hasPermi="['project:acceptance-material-def:update']"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button
|
||||
link
|
||||
type="danger"
|
||||
@click="handleDelete(scope.row.id)"
|
||||
v-hasPermi="['project:acceptance-material-def:delete']"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页 -->
|
||||
<Pagination
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNo"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 表单弹窗:添加/修改 -->
|
||||
<AcceptanceMaterialDefForm ref="formRef" @success="getList" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { dateFormatter } from '@/utils/formatTime'
|
||||
import download from '@/utils/download'
|
||||
import * as AcceptanceMaterialDefApi from '@/api/project/acceptanceMaterialDef'
|
||||
import AcceptanceMaterialDefForm from './AcceptanceMaterialDefForm.vue'
|
||||
|
||||
defineOptions({ name: 'AcceptanceMaterialDef' })
|
||||
|
||||
const message = useMessage() // 消息弹窗
|
||||
const { t } = useI18n() // 国际化
|
||||
|
||||
const loading = ref(true) // 列表的加载中
|
||||
const total = ref(0) // 列表的总页数
|
||||
const list = ref([]) // 列表的数据
|
||||
const queryParams = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
acceptanceType: undefined,
|
||||
materialCode: undefined,
|
||||
materialName: undefined
|
||||
})
|
||||
const queryFormRef = ref() // 搜索的表单
|
||||
const exportLoading = ref(false) // 导出的加载中
|
||||
|
||||
/** 查询列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const data = await AcceptanceMaterialDefApi.getAcceptanceMaterialDefPage(queryParams)
|
||||
list.value = data.list
|
||||
total.value = data.total
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
const handleQuery = () => {
|
||||
queryParams.pageNo = 1
|
||||
getList()
|
||||
}
|
||||
|
||||
/** 重置按钮操作 */
|
||||
const resetQuery = () => {
|
||||
queryFormRef.value.resetFields()
|
||||
handleQuery()
|
||||
}
|
||||
|
||||
/** 添加/修改操作 */
|
||||
const formRef = ref()
|
||||
const openForm = (type: string, id?: number) => {
|
||||
formRef.value.open(type, id)
|
||||
}
|
||||
|
||||
/** 删除按钮操作 */
|
||||
const handleDelete = async (id: number) => {
|
||||
try {
|
||||
// 删除的二次确认
|
||||
await message.delConfirm()
|
||||
// 发起删除
|
||||
await AcceptanceMaterialDefApi.deleteAcceptanceMaterialDef(id)
|
||||
message.success(t('common.delSuccess'))
|
||||
// 刷新列表
|
||||
await getList()
|
||||
} catch {}
|
||||
}
|
||||
|
||||
/** 导出按钮操作 */
|
||||
const handleExport = async () => {
|
||||
try {
|
||||
// 导出的二次确认
|
||||
await message.exportConfirm()
|
||||
// 发起导出
|
||||
exportLoading.value = true
|
||||
const data = await AcceptanceMaterialDefApi.exportAcceptanceMaterialDef(queryParams)
|
||||
download.excel(data, '材料定义.xls')
|
||||
} catch {
|
||||
} finally {
|
||||
exportLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 初始化 **/
|
||||
onMounted(() => {
|
||||
getList()
|
||||
})
|
||||
</script>
|
||||
|
|
@ -0,0 +1,190 @@
|
|||
<template>
|
||||
<Dialog v-model="dialogVisible" :title="dialogTitle">
|
||||
<el-form
|
||||
ref="formRef"
|
||||
v-loading="formLoading"
|
||||
:model="formData"
|
||||
:rules="formRules"
|
||||
label-width="100px"
|
||||
>
|
||||
<el-form-item label="会议名称" prop="meetingName">
|
||||
<el-input v-model="formData.meetingName" placeholder="请输入会议名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="会议时间" prop="meetingTime">
|
||||
<el-date-picker
|
||||
v-model="formData.meetingTime"
|
||||
type="datetime"
|
||||
placeholder="请选择会议时间"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="会议地点" prop="meetingLocation">
|
||||
<el-input v-model="formData.meetingLocation" placeholder="请输入会议地点" />
|
||||
</el-form-item>
|
||||
<el-form-item label="会议类型" prop="meetingType">
|
||||
<el-select v-model="formData.meetingType" placeholder="请选择会议类型">
|
||||
<el-option label="预验收" value="PRE" />
|
||||
<el-option label="终验" value="FINAL" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="会议结论" prop="meetingResult">
|
||||
<el-select v-model="formData.meetingResult" placeholder="请选择会议结论" clearable>
|
||||
<el-option label="通过" value="PASS" />
|
||||
<el-option label="不通过" value="REJECT" />
|
||||
<el-option label="需整改" value="RECTIFY" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="专家意见" prop="meetingOpinion">
|
||||
<el-input
|
||||
v-model="formData.meetingOpinion"
|
||||
type="textarea"
|
||||
:rows="3"
|
||||
placeholder="请输入专家组集体意见"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="会议纪要" prop="minutesFileUrl">
|
||||
<el-upload
|
||||
:action="uploadUrl"
|
||||
:headers="uploadHeaders"
|
||||
:show-file-list="false"
|
||||
:on-success="handleMinutesSuccess"
|
||||
>
|
||||
<el-button type="primary">上传文件</el-button>
|
||||
</el-upload>
|
||||
<el-link v-if="formData.minutesFileUrl" :href="formData.minutesFileUrl" target="_blank" class="ml-2">
|
||||
查看文件
|
||||
</el-link>
|
||||
</el-form-item>
|
||||
<el-form-item label="签字扫描件" prop="signFileUrl">
|
||||
<el-upload
|
||||
:action="uploadUrl"
|
||||
:headers="uploadHeaders"
|
||||
:show-file-list="false"
|
||||
:on-success="handleSignSuccess"
|
||||
>
|
||||
<el-button type="primary">上传文件</el-button>
|
||||
</el-upload>
|
||||
<el-link v-if="formData.signFileUrl" :href="formData.signFileUrl" target="_blank" class="ml-2">
|
||||
查看文件
|
||||
</el-link>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||
</template>
|
||||
</Dialog>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import * as AcceptanceMeetingApi from '@/api/project/acceptanceMeeting'
|
||||
import { FormRules } from 'element-plus'
|
||||
import { getAccessToken } from '@/utils/auth'
|
||||
|
||||
defineOptions({ name: 'AcceptanceMeetingForm' })
|
||||
|
||||
const { t } = useI18n() // 国际化
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||
const dialogTitle = ref('') // 弹窗的标题
|
||||
const formLoading = ref(false) // 表单的加载中
|
||||
const formType = ref('') // 表单的类型:create - 新增;update - 修改
|
||||
const formData = ref({
|
||||
id: undefined,
|
||||
meetingName: '',
|
||||
meetingTime: '',
|
||||
meetingLocation: '',
|
||||
meetingType: 'FINAL',
|
||||
meetingResult: '',
|
||||
meetingOpinion: '',
|
||||
minutesFileUrl: '',
|
||||
signFileUrl: ''
|
||||
})
|
||||
const formRules = reactive<FormRules>({
|
||||
meetingName: [{ required: true, message: '会议名称不能为空', trigger: 'blur' }],
|
||||
meetingTime: [{ required: true, message: '会议时间不能为空', trigger: 'change' }],
|
||||
meetingType: [{ required: true, message: '会议类型不能为空', trigger: 'change' }]
|
||||
})
|
||||
const formRef = ref() // 表单 Ref
|
||||
|
||||
// 上传配置
|
||||
const uploadUrl = import.meta.env.VITE_BASE_URL + '/infra/file/upload'
|
||||
const uploadHeaders = { Authorization: 'Bearer ' + getAccessToken() }
|
||||
|
||||
/** 打开弹窗 */
|
||||
const open = async (type: string, id?: number) => {
|
||||
dialogVisible.value = true
|
||||
dialogTitle.value = t('action.' + type)
|
||||
formType.value = type
|
||||
resetForm()
|
||||
// 修改时,设置数据
|
||||
if (id) {
|
||||
formLoading.value = true
|
||||
try {
|
||||
formData.value = await AcceptanceMeetingApi.getAcceptanceMeeting(id)
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
}
|
||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||
|
||||
/** 会议纪要上传成功 */
|
||||
const handleMinutesSuccess = (response: any) => {
|
||||
if (response.code === 0) {
|
||||
formData.value.minutesFileUrl = response.data
|
||||
message.success('上传成功')
|
||||
}
|
||||
}
|
||||
|
||||
/** 签字扫描件上传成功 */
|
||||
const handleSignSuccess = (response: any) => {
|
||||
if (response.code === 0) {
|
||||
formData.value.signFileUrl = response.data
|
||||
message.success('上传成功')
|
||||
}
|
||||
}
|
||||
|
||||
/** 提交表单 */
|
||||
const emit = defineEmits(['success']) // 定义 success 事件
|
||||
const submitForm = async () => {
|
||||
// 校验表单
|
||||
if (!formRef.value) return
|
||||
const valid = await formRef.value.validate()
|
||||
if (!valid) return
|
||||
// 提交请求
|
||||
formLoading.value = true
|
||||
try {
|
||||
const data = formData.value as unknown as AcceptanceMeetingApi.AcceptanceMeetingVO
|
||||
if (formType.value === 'create') {
|
||||
await AcceptanceMeetingApi.createAcceptanceMeeting(data)
|
||||
message.success(t('common.createSuccess'))
|
||||
} else {
|
||||
await AcceptanceMeetingApi.updateAcceptanceMeeting(data)
|
||||
message.success(t('common.updateSuccess'))
|
||||
}
|
||||
dialogVisible.value = false
|
||||
// 发送操作成功的事件
|
||||
emit('success')
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 重置表单 */
|
||||
const resetForm = () => {
|
||||
formData.value = {
|
||||
id: undefined,
|
||||
meetingName: '',
|
||||
meetingTime: '',
|
||||
meetingLocation: '',
|
||||
meetingType: 'FINAL',
|
||||
meetingResult: '',
|
||||
meetingOpinion: '',
|
||||
minutesFileUrl: '',
|
||||
signFileUrl: ''
|
||||
}
|
||||
formRef.value?.resetFields()
|
||||
}
|
||||
</script>
|
||||
|
|
@ -0,0 +1,174 @@
|
|||
<template>
|
||||
<Dialog v-model="dialogVisible" title="批量创建会议" width="700px">
|
||||
<el-form
|
||||
ref="formRef"
|
||||
v-loading="formLoading"
|
||||
:model="formData"
|
||||
:rules="formRules"
|
||||
label-width="100px"
|
||||
>
|
||||
<el-form-item label="选择验收" prop="acceptanceIds">
|
||||
<el-select
|
||||
v-model="formData.acceptanceIds"
|
||||
multiple
|
||||
filterable
|
||||
placeholder="请选择要加入会议的验收实例"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in acceptanceList"
|
||||
:key="item.id"
|
||||
:label="'验收ID: ' + item.id + ' - 项目ID: ' + item.projectId"
|
||||
:value="item.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="会议名称" prop="meetingName">
|
||||
<el-input v-model="formData.meetingName" placeholder="请输入会议名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="会议时间" prop="meetingTime">
|
||||
<el-date-picker
|
||||
v-model="formData.meetingTime"
|
||||
type="datetime"
|
||||
placeholder="请选择会议时间"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="会议地点" prop="meetingLocation">
|
||||
<el-input v-model="formData.meetingLocation" placeholder="请输入会议地点" />
|
||||
</el-form-item>
|
||||
<el-form-item label="会议类型" prop="meetingType">
|
||||
<el-select v-model="formData.meetingType" placeholder="请选择会议类型">
|
||||
<el-option label="预验收" value="PRE" />
|
||||
<el-option label="终验" value="FINAL" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="参会专家" prop="expertUserIds">
|
||||
<el-select
|
||||
v-model="formData.expertUserIds"
|
||||
multiple
|
||||
filterable
|
||||
placeholder="请选择参会专家"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="user in userList"
|
||||
:key="user.id"
|
||||
:label="user.nickname"
|
||||
:value="user.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="会议纪要" prop="minutesFileUrl">
|
||||
<el-upload
|
||||
:action="uploadUrl"
|
||||
:headers="uploadHeaders"
|
||||
:show-file-list="false"
|
||||
:on-success="handleUploadSuccess"
|
||||
>
|
||||
<el-button type="primary">上传文件</el-button>
|
||||
</el-upload>
|
||||
<el-link v-if="formData.minutesFileUrl" :href="formData.minutesFileUrl" target="_blank" class="ml-2">
|
||||
查看文件
|
||||
</el-link>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button :disabled="formLoading" type="primary" @click="submitForm">创建会议</el-button>
|
||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||
</template>
|
||||
</Dialog>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import * as AcceptanceMeetingApi from '@/api/project/acceptanceMeeting'
|
||||
import * as AcceptanceApi from '@/api/project/acceptance'
|
||||
import * as UserApi from '@/api/system/user'
|
||||
import { FormRules } from 'element-plus'
|
||||
import { getAccessToken } from '@/utils/auth'
|
||||
|
||||
defineOptions({ name: 'BatchCreateForm' })
|
||||
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||
const formLoading = ref(false) // 表单的加载中
|
||||
const formData = ref({
|
||||
acceptanceIds: [] as number[],
|
||||
meetingName: '',
|
||||
meetingTime: '',
|
||||
meetingLocation: '',
|
||||
meetingType: 'FINAL',
|
||||
expertUserIds: [] as number[],
|
||||
minutesFileUrl: ''
|
||||
})
|
||||
const formRules = reactive<FormRules>({
|
||||
acceptanceIds: [{ required: true, message: '请选择验收实例', trigger: 'change' }],
|
||||
meetingName: [{ required: true, message: '会议名称不能为空', trigger: 'blur' }],
|
||||
meetingTime: [{ required: true, message: '会议时间不能为空', trigger: 'change' }],
|
||||
meetingType: [{ required: true, message: '会议类型不能为空', trigger: 'change' }],
|
||||
expertUserIds: [{ required: true, message: '请选择参会专家', trigger: 'change' }]
|
||||
})
|
||||
const formRef = ref() // 表单 Ref
|
||||
const acceptanceList = ref<AcceptanceApi.AcceptanceVO[]>([]) // 验收列表
|
||||
const userList = ref<UserApi.UserVO[]>([]) // 用户列表
|
||||
|
||||
// 上传配置
|
||||
const uploadUrl = import.meta.env.VITE_BASE_URL + '/infra/file/upload'
|
||||
const uploadHeaders = { Authorization: 'Bearer ' + getAccessToken() }
|
||||
|
||||
/** 打开弹窗 */
|
||||
const open = async () => {
|
||||
dialogVisible.value = true
|
||||
resetForm()
|
||||
// 加载验收列表(待会议状态的)
|
||||
const result = await AcceptanceApi.getAcceptancePage({ pageNo: 1, pageSize: 100, status: '30' })
|
||||
acceptanceList.value = result.list
|
||||
// 加载用户列表
|
||||
userList.value = await UserApi.getSimpleUserList()
|
||||
}
|
||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||
|
||||
/** 上传成功 */
|
||||
const handleUploadSuccess = (response: any) => {
|
||||
if (response.code === 0) {
|
||||
formData.value.minutesFileUrl = response.data
|
||||
message.success('上传成功')
|
||||
}
|
||||
}
|
||||
|
||||
/** 提交表单 */
|
||||
const emit = defineEmits(['success']) // 定义 success 事件
|
||||
const submitForm = async () => {
|
||||
// 校验表单
|
||||
if (!formRef.value) return
|
||||
const valid = await formRef.value.validate()
|
||||
if (!valid) return
|
||||
// 提交请求
|
||||
formLoading.value = true
|
||||
try {
|
||||
await AcceptanceMeetingApi.batchCreateMeeting(formData.value as AcceptanceMeetingApi.AcceptanceMeetingBatchCreateReqVO)
|
||||
message.success('会议创建成功')
|
||||
dialogVisible.value = false
|
||||
// 发送操作成功的事件
|
||||
emit('success')
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 重置表单 */
|
||||
const resetForm = () => {
|
||||
formData.value = {
|
||||
acceptanceIds: [],
|
||||
meetingName: '',
|
||||
meetingTime: '',
|
||||
meetingLocation: '',
|
||||
meetingType: 'FINAL',
|
||||
expertUserIds: [],
|
||||
minutesFileUrl: ''
|
||||
}
|
||||
formRef.value?.resetFields()
|
||||
}
|
||||
</script>
|
||||
|
|
@ -0,0 +1,138 @@
|
|||
<template>
|
||||
<Dialog v-model="dialogVisible" title="录入会议结果" width="700px">
|
||||
<el-form
|
||||
ref="formRef"
|
||||
v-loading="formLoading"
|
||||
:model="formData"
|
||||
label-width="100px"
|
||||
>
|
||||
<el-alert
|
||||
:title="'会议: ' + meetingInfo.meetingName"
|
||||
type="info"
|
||||
:closable="false"
|
||||
class="mb-4"
|
||||
/>
|
||||
|
||||
<el-divider content-position="left">会议整体结论</el-divider>
|
||||
<el-form-item label="会议结论" prop="meetingResult">
|
||||
<el-select v-model="formData.overallResult" placeholder="请选择整体结论">
|
||||
<el-option label="通过" value="PASS" />
|
||||
<el-option label="不通过" value="REJECT" />
|
||||
<el-option label="需整改" value="RECTIFY" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="专家意见" prop="meetingOpinion">
|
||||
<el-input
|
||||
v-model="formData.overallOpinion"
|
||||
type="textarea"
|
||||
:rows="3"
|
||||
placeholder="请输入专家组集体意见"
|
||||
/>
|
||||
</el-form-item>
|
||||
|
||||
<el-divider content-position="left">各项目结果</el-divider>
|
||||
<el-table :data="formData.results" border>
|
||||
<el-table-column label="验收ID" align="center" prop="acceptanceId" width="100" />
|
||||
<el-table-column label="结论" align="center" width="150">
|
||||
<template #default="scope">
|
||||
<el-select v-model="scope.row.result" placeholder="请选择">
|
||||
<el-option label="通过" value="PASS" />
|
||||
<el-option label="不通过" value="REJECT" />
|
||||
<el-option label="需整改" value="RECTIFY" />
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="专家意见" align="center">
|
||||
<template #default="scope">
|
||||
<el-input v-model="scope.row.opinion" placeholder="请输入意见" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button :disabled="formLoading" type="primary" @click="submitForm">提交结果</el-button>
|
||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||
</template>
|
||||
</Dialog>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import * as AcceptanceMeetingApi from '@/api/project/acceptanceMeeting'
|
||||
import * as AcceptanceMeetingRelationApi from '@/api/project/acceptanceMeetingRelation'
|
||||
|
||||
defineOptions({ name: 'BatchResultForm' })
|
||||
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||
const formLoading = ref(false) // 表单的加载中
|
||||
const meetingInfo = ref({
|
||||
id: undefined as number | undefined,
|
||||
meetingName: ''
|
||||
})
|
||||
const formData = ref({
|
||||
meetingId: undefined as number | undefined,
|
||||
overallResult: 'PASS',
|
||||
overallOpinion: '',
|
||||
results: [] as AcceptanceMeetingApi.AcceptanceMeetingResultVO[]
|
||||
})
|
||||
const formRef = ref() // 表单 Ref
|
||||
|
||||
/** 打开弹窗 */
|
||||
const open = async (row: AcceptanceMeetingApi.AcceptanceMeetingVO) => {
|
||||
dialogVisible.value = true
|
||||
resetForm()
|
||||
meetingInfo.value = {
|
||||
id: row.id,
|
||||
meetingName: row.meetingName
|
||||
}
|
||||
formData.value.meetingId = row.id
|
||||
|
||||
// 加载会议关联的验收列表
|
||||
const result = await AcceptanceMeetingRelationApi.getAcceptanceMeetingRelationPage({
|
||||
pageNo: 1,
|
||||
pageSize: 100,
|
||||
meetingId: row.id
|
||||
})
|
||||
formData.value.results = result.list.map((item: any) => ({
|
||||
acceptanceId: item.acceptanceId,
|
||||
result: item.meetingResult || 'PASS',
|
||||
opinion: item.meetingOpinion || ''
|
||||
}))
|
||||
}
|
||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||
|
||||
/** 提交表单 */
|
||||
const emit = defineEmits(['success']) // 定义 success 事件
|
||||
const submitForm = async () => {
|
||||
// 提交请求
|
||||
formLoading.value = true
|
||||
try {
|
||||
await AcceptanceMeetingApi.batchInputResult({
|
||||
meetingId: formData.value.meetingId!,
|
||||
results: formData.value.results
|
||||
})
|
||||
message.success('结果录入成功')
|
||||
dialogVisible.value = false
|
||||
// 发送操作成功的事件
|
||||
emit('success')
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 重置表单 */
|
||||
const resetForm = () => {
|
||||
meetingInfo.value = {
|
||||
id: undefined,
|
||||
meetingName: ''
|
||||
}
|
||||
formData.value = {
|
||||
meetingId: undefined,
|
||||
overallResult: 'PASS',
|
||||
overallOpinion: '',
|
||||
results: []
|
||||
}
|
||||
formRef.value?.resetFields()
|
||||
}
|
||||
</script>
|
||||
|
|
@ -0,0 +1,260 @@
|
|||
<template>
|
||||
<ContentWrap>
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form
|
||||
class="-mb-15px"
|
||||
:model="queryParams"
|
||||
ref="queryFormRef"
|
||||
:inline="true"
|
||||
label-width="80px"
|
||||
>
|
||||
<el-form-item label="会议名称" prop="meetingName">
|
||||
<el-input
|
||||
v-model="queryParams.meetingName"
|
||||
placeholder="请输入会议名称"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="会议类型" prop="meetingType">
|
||||
<el-select
|
||||
v-model="queryParams.meetingType"
|
||||
placeholder="请选择会议类型"
|
||||
clearable
|
||||
class="!w-180px"
|
||||
>
|
||||
<el-option label="预验收" value="PRE" />
|
||||
<el-option label="终验" value="FINAL" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="会议结论" prop="meetingResult">
|
||||
<el-select
|
||||
v-model="queryParams.meetingResult"
|
||||
placeholder="请选择会议结论"
|
||||
clearable
|
||||
class="!w-180px"
|
||||
>
|
||||
<el-option label="通过" value="PASS" />
|
||||
<el-option label="不通过" value="REJECT" />
|
||||
<el-option label="需整改" value="RECTIFY" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="创建时间" prop="createTime">
|
||||
<el-date-picker
|
||||
v-model="queryParams.createTime"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
type="datetimerange"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="handleQuery"><Icon icon="ep:search" />搜索</el-button>
|
||||
<el-button @click="resetQuery"><Icon icon="ep:refresh" />重置</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
@click="openBatchCreateForm"
|
||||
v-hasPermi="['project:acceptance-meeting:batch-create']"
|
||||
>
|
||||
<Icon icon="ep:plus" /> 批量创建会议
|
||||
</el-button>
|
||||
<el-button
|
||||
type="success"
|
||||
plain
|
||||
@click="handleExport"
|
||||
:loading="exportLoading"
|
||||
v-hasPermi="['project:acceptance-meeting:export']"
|
||||
>
|
||||
<Icon icon="ep:download" />导出
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 列表 -->
|
||||
<ContentWrap>
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="会议ID" align="center" prop="id" width="80" />
|
||||
<el-table-column label="会议名称" align="center" prop="meetingName" :show-overflow-tooltip="true" />
|
||||
<el-table-column
|
||||
label="会议时间"
|
||||
align="center"
|
||||
prop="meetingTime"
|
||||
:formatter="dateFormatter"
|
||||
width="180"
|
||||
/>
|
||||
<el-table-column label="会议地点" align="center" prop="meetingLocation" width="150" />
|
||||
<el-table-column label="会议类型" align="center" prop="meetingType" width="100">
|
||||
<template #default="scope">
|
||||
<el-tag v-if="scope.row.meetingType === 'PRE'" type="info">预验收</el-tag>
|
||||
<el-tag v-else-if="scope.row.meetingType === 'FINAL'" type="primary">终验</el-tag>
|
||||
<el-tag v-else>{{ scope.row.meetingType }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="会议结论" align="center" prop="meetingResult" width="100">
|
||||
<template #default="scope">
|
||||
<el-tag v-if="scope.row.meetingResult === 'PASS'" type="success">通过</el-tag>
|
||||
<el-tag v-else-if="scope.row.meetingResult === 'REJECT'" type="danger">不通过</el-tag>
|
||||
<el-tag v-else-if="scope.row.meetingResult === 'RECTIFY'" type="warning">需整改</el-tag>
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="专家意见" align="center" prop="meetingOpinion" :show-overflow-tooltip="true" />
|
||||
<el-table-column
|
||||
label="创建时间"
|
||||
align="center"
|
||||
prop="createTime"
|
||||
:formatter="dateFormatter"
|
||||
width="180"
|
||||
/>
|
||||
<el-table-column label="操作" align="center" width="200" fixed="right">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
@click="openForm('update', scope.row.id)"
|
||||
v-hasPermi="['project:acceptance-meeting:update']"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button
|
||||
link
|
||||
type="warning"
|
||||
@click="openResultForm(scope.row)"
|
||||
v-hasPermi="['project:acceptance-meeting:batch-result']"
|
||||
>
|
||||
录入结果
|
||||
</el-button>
|
||||
<el-button
|
||||
link
|
||||
type="danger"
|
||||
@click="handleDelete(scope.row.id)"
|
||||
v-hasPermi="['project:acceptance-meeting:delete']"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页 -->
|
||||
<Pagination
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNo"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 表单弹窗:添加/修改 -->
|
||||
<AcceptanceMeetingForm ref="formRef" @success="getList" />
|
||||
<!-- 批量创建弹窗 -->
|
||||
<BatchCreateForm ref="batchCreateFormRef" @success="getList" />
|
||||
<!-- 录入结果弹窗 -->
|
||||
<BatchResultForm ref="resultFormRef" @success="getList" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { dateFormatter } from '@/utils/formatTime'
|
||||
import download from '@/utils/download'
|
||||
import * as AcceptanceMeetingApi from '@/api/project/acceptanceMeeting'
|
||||
import AcceptanceMeetingForm from './AcceptanceMeetingForm.vue'
|
||||
import BatchCreateForm from './BatchCreateForm.vue'
|
||||
import BatchResultForm from './BatchResultForm.vue'
|
||||
|
||||
defineOptions({ name: 'AcceptanceMeeting' })
|
||||
|
||||
const message = useMessage() // 消息弹窗
|
||||
const { t } = useI18n() // 国际化
|
||||
|
||||
const loading = ref(true) // 列表的加载中
|
||||
const total = ref(0) // 列表的总页数
|
||||
const list = ref([]) // 列表的数据
|
||||
const queryParams = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
meetingName: undefined,
|
||||
meetingType: undefined,
|
||||
meetingResult: undefined,
|
||||
createTime: []
|
||||
})
|
||||
const queryFormRef = ref() // 搜索的表单
|
||||
const exportLoading = ref(false) // 导出的加载中
|
||||
|
||||
/** 查询列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const data = await AcceptanceMeetingApi.getAcceptanceMeetingPage(queryParams)
|
||||
list.value = data.list
|
||||
total.value = data.total
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
const handleQuery = () => {
|
||||
queryParams.pageNo = 1
|
||||
getList()
|
||||
}
|
||||
|
||||
/** 重置按钮操作 */
|
||||
const resetQuery = () => {
|
||||
queryFormRef.value.resetFields()
|
||||
handleQuery()
|
||||
}
|
||||
|
||||
/** 添加/修改操作 */
|
||||
const formRef = ref()
|
||||
const openForm = (type: string, id?: number) => {
|
||||
formRef.value.open(type, id)
|
||||
}
|
||||
|
||||
/** 批量创建会议 */
|
||||
const batchCreateFormRef = ref()
|
||||
const openBatchCreateForm = () => {
|
||||
batchCreateFormRef.value.open()
|
||||
}
|
||||
|
||||
/** 录入会议结果 */
|
||||
const resultFormRef = ref()
|
||||
const openResultForm = (row: AcceptanceMeetingApi.AcceptanceMeetingVO) => {
|
||||
resultFormRef.value.open(row)
|
||||
}
|
||||
|
||||
/** 删除按钮操作 */
|
||||
const handleDelete = async (id: number) => {
|
||||
try {
|
||||
// 删除的二次确认
|
||||
await message.delConfirm()
|
||||
// 发起删除
|
||||
await AcceptanceMeetingApi.deleteAcceptanceMeeting(id)
|
||||
message.success(t('common.delSuccess'))
|
||||
// 刷新列表
|
||||
await getList()
|
||||
} catch {}
|
||||
}
|
||||
|
||||
/** 导出按钮操作 */
|
||||
const handleExport = async () => {
|
||||
try {
|
||||
// 导出的二次确认
|
||||
await message.exportConfirm()
|
||||
// 发起导出
|
||||
exportLoading.value = true
|
||||
const data = await AcceptanceMeetingApi.exportAcceptanceMeeting(queryParams)
|
||||
download.excel(data, '会议数据.xls')
|
||||
} catch {
|
||||
} finally {
|
||||
exportLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 初始化 **/
|
||||
onMounted(() => {
|
||||
getList()
|
||||
})
|
||||
</script>
|
||||
|
|
@ -0,0 +1,214 @@
|
|||
<template>
|
||||
<ContentWrap>
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form
|
||||
class="-mb-15px"
|
||||
:model="queryParams"
|
||||
ref="queryFormRef"
|
||||
:inline="true"
|
||||
label-width="80px"
|
||||
>
|
||||
<el-form-item label="验收ID" prop="acceptanceId">
|
||||
<el-input
|
||||
v-model="queryParams.acceptanceId"
|
||||
placeholder="请输入验收ID"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-180px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="操作人ID" prop="operatorId">
|
||||
<el-input
|
||||
v-model="queryParams.operatorId"
|
||||
placeholder="请输入操作人ID"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-180px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="审核结果" prop="result">
|
||||
<el-select
|
||||
v-model="queryParams.result"
|
||||
placeholder="请选择审核结果"
|
||||
clearable
|
||||
class="!w-180px"
|
||||
>
|
||||
<el-option label="通过" value="PASS" />
|
||||
<el-option label="驳回" value="REJECT" />
|
||||
<el-option label="需整改" value="RECTIFY" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="handleQuery"><Icon icon="ep:search" />搜索</el-button>
|
||||
<el-button @click="resetQuery"><Icon icon="ep:refresh" />重置</el-button>
|
||||
<el-button
|
||||
type="success"
|
||||
plain
|
||||
@click="handleExport"
|
||||
:loading="exportLoading"
|
||||
v-hasPermi="['project:acceptance-opinion:export']"
|
||||
>
|
||||
<Icon icon="ep:download" />导出
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 列表 -->
|
||||
<ContentWrap>
|
||||
<el-table v-loading="loading" :data="list">
|
||||
<el-table-column label="ID" align="center" prop="id" width="80" />
|
||||
<el-table-column label="验收ID" align="center" prop="acceptanceId" width="100" />
|
||||
<el-table-column label="意见类型" align="center" prop="opinionType" width="120" />
|
||||
<el-table-column label="操作人ID" align="center" prop="operatorId" width="100" />
|
||||
<el-table-column label="审核结果" align="center" prop="result" width="100">
|
||||
<template #default="scope">
|
||||
<el-tag v-if="scope.row.result === 'PASS'" type="success">通过</el-tag>
|
||||
<el-tag v-else-if="scope.row.result === 'REJECT'" type="danger">驳回</el-tag>
|
||||
<el-tag v-else-if="scope.row.result === 'RECTIFY'" type="warning">需整改</el-tag>
|
||||
<span v-else>{{ scope.row.result }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="审核意见" align="center" prop="opinion" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="签名" align="center" prop="signatureUrl" width="100">
|
||||
<template #default="scope">
|
||||
<el-image
|
||||
v-if="scope.row.signatureUrl"
|
||||
:src="scope.row.signatureUrl"
|
||||
:preview-src-list="[scope.row.signatureUrl]"
|
||||
style="width: 50px; height: 20px"
|
||||
fit="contain"
|
||||
/>
|
||||
<span v-else>-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="创建时间"
|
||||
align="center"
|
||||
prop="createTime"
|
||||
:formatter="dateFormatter"
|
||||
width="180"
|
||||
/>
|
||||
<el-table-column label="操作" align="center" width="100" fixed="right">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
@click="handleView(scope.row)"
|
||||
>
|
||||
查看详情
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页 -->
|
||||
<Pagination
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNo"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 详情弹窗 -->
|
||||
<Dialog v-model="detailVisible" title="意见详情" width="600px">
|
||||
<el-descriptions :column="1" border>
|
||||
<el-descriptions-item label="验收ID">{{ detailData.acceptanceId }}</el-descriptions-item>
|
||||
<el-descriptions-item label="意见类型">{{ detailData.opinionType }}</el-descriptions-item>
|
||||
<el-descriptions-item label="操作人ID">{{ detailData.operatorId }}</el-descriptions-item>
|
||||
<el-descriptions-item label="审核结果">
|
||||
<el-tag v-if="detailData.result === 'PASS'" type="success">通过</el-tag>
|
||||
<el-tag v-else-if="detailData.result === 'REJECT'" type="danger">驳回</el-tag>
|
||||
<el-tag v-else-if="detailData.result === 'RECTIFY'" type="warning">需整改</el-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="审核意见">{{ detailData.opinion }}</el-descriptions-item>
|
||||
<el-descriptions-item label="电子签名">
|
||||
<el-image
|
||||
v-if="detailData.signatureUrl"
|
||||
:src="detailData.signatureUrl"
|
||||
:preview-src-list="[detailData.signatureUrl]"
|
||||
style="width: 200px; height: 80px"
|
||||
fit="contain"
|
||||
/>
|
||||
<span v-else>无</span>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</Dialog>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { dateFormatter } from '@/utils/formatTime'
|
||||
import download from '@/utils/download'
|
||||
import * as AcceptanceOpinionApi from '@/api/project/acceptanceOpinion'
|
||||
|
||||
defineOptions({ name: 'AcceptanceOpinion' })
|
||||
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
const loading = ref(true) // 列表的加载中
|
||||
const total = ref(0) // 列表的总页数
|
||||
const list = ref([]) // 列表的数据
|
||||
const queryParams = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
acceptanceId: undefined,
|
||||
operatorId: undefined,
|
||||
result: undefined
|
||||
})
|
||||
const queryFormRef = ref() // 搜索的表单
|
||||
const exportLoading = ref(false) // 导出的加载中
|
||||
|
||||
// 详情弹窗
|
||||
const detailVisible = ref(false)
|
||||
const detailData = ref<AcceptanceOpinionApi.AcceptanceOpinionVO>({} as any)
|
||||
|
||||
/** 查询列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const data = await AcceptanceOpinionApi.getAcceptanceOpinionPage(queryParams)
|
||||
list.value = data.list
|
||||
total.value = data.total
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
const handleQuery = () => {
|
||||
queryParams.pageNo = 1
|
||||
getList()
|
||||
}
|
||||
|
||||
/** 重置按钮操作 */
|
||||
const resetQuery = () => {
|
||||
queryFormRef.value.resetFields()
|
||||
handleQuery()
|
||||
}
|
||||
|
||||
/** 查看详情 */
|
||||
const handleView = (row: AcceptanceOpinionApi.AcceptanceOpinionVO) => {
|
||||
detailData.value = row
|
||||
detailVisible.value = true
|
||||
}
|
||||
|
||||
/** 导出按钮操作 */
|
||||
const handleExport = async () => {
|
||||
try {
|
||||
// 导出的二次确认
|
||||
await message.exportConfirm()
|
||||
// 发起导出
|
||||
exportLoading.value = true
|
||||
const data = await AcceptanceOpinionApi.exportAcceptanceOpinion(queryParams)
|
||||
download.excel(data, '审核意见.xls')
|
||||
} catch {
|
||||
} finally {
|
||||
exportLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 初始化 **/
|
||||
onMounted(() => {
|
||||
getList()
|
||||
})
|
||||
</script>
|
||||
|
|
@ -0,0 +1,186 @@
|
|||
<template>
|
||||
<Dialog v-model="dialogVisible" :title="dialogTitle">
|
||||
<el-form
|
||||
ref="formRef"
|
||||
v-loading="formLoading"
|
||||
:model="formData"
|
||||
:rules="formRules"
|
||||
label-width="100px"
|
||||
>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="立项编号" prop="projectCode">
|
||||
<el-input v-model="formData.projectCode" placeholder="请输入立项编号" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="合同编号" prop="contractCode">
|
||||
<el-input v-model="formData.contractCode" placeholder="请输入合同编号" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="项目名称" prop="projectName">
|
||||
<el-input v-model="formData.projectName" placeholder="请输入项目名称" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="24">
|
||||
<el-form-item label="申报单位" prop="applyUnit">
|
||||
<el-input v-model="formData.applyUnit" placeholder="请输入申报单位" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="项目联络人" prop="liaisonUserId">
|
||||
<el-select v-model="formData.liaisonUserId" placeholder="请选择项目联络人" clearable filterable>
|
||||
<el-option
|
||||
v-for="user in userList"
|
||||
:key="user.id"
|
||||
:label="user.nickname"
|
||||
:value="user.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="项目负责人" prop="principalUserId">
|
||||
<el-select v-model="formData.principalUserId" placeholder="请选择项目负责人" clearable filterable>
|
||||
<el-option
|
||||
v-for="user in userList"
|
||||
:key="user.id"
|
||||
:label="user.nickname"
|
||||
:value="user.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="对口服务人" prop="serviceUserId">
|
||||
<el-select v-model="formData.serviceUserId" placeholder="请选择对口服务人" clearable filterable>
|
||||
<el-option
|
||||
v-for="user in userList"
|
||||
:key="user.id"
|
||||
:label="user.nickname"
|
||||
:value="user.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-select v-model="formData.status" placeholder="请选择状态" clearable>
|
||||
<el-option label="待验收" value="0" />
|
||||
<el-option label="验收中" value="1" />
|
||||
<el-option label="已完成" value="2" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button>
|
||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||
</template>
|
||||
</Dialog>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import * as ProjectApi from '@/api/project/project'
|
||||
import * as UserApi from '@/api/system/user'
|
||||
import { FormRules } from 'element-plus'
|
||||
|
||||
defineOptions({ name: 'ProjectForm' })
|
||||
|
||||
const { t } = useI18n() // 国际化
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||
const dialogTitle = ref('') // 弹窗的标题
|
||||
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
|
||||
const formType = ref('') // 表单的类型:create - 新增;update - 修改
|
||||
const formData = ref({
|
||||
id: undefined,
|
||||
projectCode: '',
|
||||
contractCode: '',
|
||||
projectName: '',
|
||||
applyUnit: '',
|
||||
liaisonUserId: undefined,
|
||||
principalUserId: undefined,
|
||||
serviceUserId: undefined,
|
||||
status: '0'
|
||||
})
|
||||
const formRules = reactive<FormRules>({
|
||||
projectCode: [{ required: true, message: '项目立项编号不能为空', trigger: 'blur' }],
|
||||
projectName: [{ required: true, message: '项目名称不能为空', trigger: 'blur' }]
|
||||
})
|
||||
const formRef = ref() // 表单 Ref
|
||||
const userList = ref<UserApi.UserVO[]>([]) // 用户列表
|
||||
|
||||
/** 打开弹窗 */
|
||||
const open = async (type: string, id?: number) => {
|
||||
dialogVisible.value = true
|
||||
dialogTitle.value = t('action.' + type)
|
||||
formType.value = type
|
||||
resetForm()
|
||||
// 修改时,设置数据
|
||||
if (id) {
|
||||
formLoading.value = true
|
||||
try {
|
||||
formData.value = await ProjectApi.getProject(id)
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
// 加载用户列表
|
||||
userList.value = await UserApi.getSimpleUserList()
|
||||
}
|
||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||
|
||||
/** 提交表单 */
|
||||
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
||||
const submitForm = async () => {
|
||||
// 校验表单
|
||||
if (!formRef.value) return
|
||||
const valid = await formRef.value.validate()
|
||||
if (!valid) return
|
||||
// 提交请求
|
||||
formLoading.value = true
|
||||
try {
|
||||
const data = formData.value as unknown as ProjectApi.ProjectVO
|
||||
if (formType.value === 'create') {
|
||||
await ProjectApi.createProject(data)
|
||||
message.success(t('common.createSuccess'))
|
||||
} else {
|
||||
await ProjectApi.updateProject(data)
|
||||
message.success(t('common.updateSuccess'))
|
||||
}
|
||||
dialogVisible.value = false
|
||||
// 发送操作成功的事件
|
||||
emit('success')
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 重置表单 */
|
||||
const resetForm = () => {
|
||||
formData.value = {
|
||||
id: undefined,
|
||||
projectCode: '',
|
||||
contractCode: '',
|
||||
projectName: '',
|
||||
applyUnit: '',
|
||||
liaisonUserId: undefined,
|
||||
principalUserId: undefined,
|
||||
serviceUserId: undefined,
|
||||
status: '0'
|
||||
}
|
||||
formRef.value?.resetFields()
|
||||
}
|
||||
</script>
|
||||
|
|
@ -0,0 +1,135 @@
|
|||
<template>
|
||||
<Dialog v-model="dialogVisible" title="发起预验收">
|
||||
<el-form
|
||||
ref="formRef"
|
||||
v-loading="formLoading"
|
||||
:model="formData"
|
||||
:rules="formRules"
|
||||
label-width="120px"
|
||||
>
|
||||
<el-form-item label="项目名称">
|
||||
<el-input v-model="projectInfo.projectName" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item label="项目编号">
|
||||
<el-input v-model="projectInfo.projectCode" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item label="对口服务人" prop="serviceUserId">
|
||||
<el-select v-model="formData.serviceUserId" placeholder="请选择对口服务人" clearable filterable>
|
||||
<el-option
|
||||
v-for="user in userList"
|
||||
:key="user.id"
|
||||
:label="user.nickname"
|
||||
:value="user.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="项目联络人" prop="liaisonUserId">
|
||||
<el-select v-model="formData.liaisonUserId" placeholder="请选择项目联络人" clearable filterable>
|
||||
<el-option
|
||||
v-for="user in userList"
|
||||
:key="user.id"
|
||||
:label="user.nickname"
|
||||
:value="user.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="专家组长" prop="leaderUserId">
|
||||
<el-select v-model="formData.leaderUserId" placeholder="请选择专家组长" clearable filterable>
|
||||
<el-option
|
||||
v-for="user in userList"
|
||||
:key="user.id"
|
||||
:label="user.nickname"
|
||||
:value="user.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button :disabled="formLoading" type="primary" @click="submitForm">提交申请</el-button>
|
||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||
</template>
|
||||
</Dialog>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import * as ProjectApi from '@/api/project/project'
|
||||
import * as AcceptanceApi from '@/api/project/acceptance'
|
||||
import * as UserApi from '@/api/system/user'
|
||||
import { FormRules } from 'element-plus'
|
||||
|
||||
defineOptions({ name: 'StartAcceptanceForm' })
|
||||
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||
const formLoading = ref(false) // 表单的加载中
|
||||
const projectInfo = ref({
|
||||
id: undefined,
|
||||
projectName: '',
|
||||
projectCode: ''
|
||||
})
|
||||
const formData = ref({
|
||||
projectId: undefined as number | undefined,
|
||||
serviceUserId: undefined as number | undefined,
|
||||
liaisonUserId: undefined as number | undefined,
|
||||
leaderUserId: undefined as number | undefined
|
||||
})
|
||||
const formRules = reactive<FormRules>({
|
||||
leaderUserId: [{ required: true, message: '专家组长不能为空', trigger: 'change' }]
|
||||
})
|
||||
const formRef = ref() // 表单 Ref
|
||||
const userList = ref<UserApi.UserVO[]>([]) // 用户列表
|
||||
|
||||
/** 打开弹窗 */
|
||||
const open = async (row: ProjectApi.ProjectVO) => {
|
||||
dialogVisible.value = true
|
||||
resetForm()
|
||||
projectInfo.value = {
|
||||
id: row.id,
|
||||
projectName: row.projectName,
|
||||
projectCode: row.projectCode
|
||||
}
|
||||
formData.value.projectId = row.id
|
||||
formData.value.serviceUserId = row.serviceUserId
|
||||
formData.value.liaisonUserId = row.liaisonUserId
|
||||
// 加载用户列表
|
||||
userList.value = await UserApi.getSimpleUserList()
|
||||
}
|
||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||
|
||||
/** 提交表单 */
|
||||
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
||||
const submitForm = async () => {
|
||||
// 校验表单
|
||||
if (!formRef.value) return
|
||||
const valid = await formRef.value.validate()
|
||||
if (!valid) return
|
||||
// 提交请求
|
||||
formLoading.value = true
|
||||
try {
|
||||
await AcceptanceApi.submitPreAcceptance(formData.value as AcceptanceApi.AcceptanceSubmitPreReqVO)
|
||||
message.success('预验收申请提交成功')
|
||||
dialogVisible.value = false
|
||||
// 发送操作成功的事件
|
||||
emit('success')
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 重置表单 */
|
||||
const resetForm = () => {
|
||||
projectInfo.value = {
|
||||
id: undefined,
|
||||
projectName: '',
|
||||
projectCode: ''
|
||||
}
|
||||
formData.value = {
|
||||
projectId: undefined,
|
||||
serviceUserId: undefined,
|
||||
liaisonUserId: undefined,
|
||||
leaderUserId: undefined
|
||||
}
|
||||
formRef.value?.resetFields()
|
||||
}
|
||||
</script>
|
||||
|
|
@ -0,0 +1,277 @@
|
|||
<template>
|
||||
<ContentWrap>
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form
|
||||
class="-mb-15px"
|
||||
:model="queryParams"
|
||||
ref="queryFormRef"
|
||||
:inline="true"
|
||||
label-width="68px"
|
||||
>
|
||||
<el-form-item label="项目编号" prop="projectCode">
|
||||
<el-input
|
||||
v-model="queryParams.projectCode"
|
||||
placeholder="请输入项目编号"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="项目名称" prop="projectName">
|
||||
<el-input
|
||||
v-model="queryParams.projectName"
|
||||
placeholder="请输入项目名称"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="申报单位" prop="applyUnit">
|
||||
<el-input
|
||||
v-model="queryParams.applyUnit"
|
||||
placeholder="请输入申报单位"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-select
|
||||
v-model="queryParams.status"
|
||||
placeholder="请选择状态"
|
||||
clearable
|
||||
class="!w-240px"
|
||||
>
|
||||
<el-option label="待验收" value="0" />
|
||||
<el-option label="验收中" value="1" />
|
||||
<el-option label="已完成" value="2" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="创建时间" prop="createTime">
|
||||
<el-date-picker
|
||||
v-model="queryParams.createTime"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
type="datetimerange"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="handleQuery"><Icon icon="ep:search" />搜索</el-button>
|
||||
<el-button @click="resetQuery"><Icon icon="ep:refresh" />重置</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
@click="openForm('create')"
|
||||
v-hasPermi="['project:project:create']"
|
||||
>
|
||||
<Icon icon="ep:plus" /> 新增
|
||||
</el-button>
|
||||
<el-button
|
||||
type="success"
|
||||
plain
|
||||
@click="handleExport"
|
||||
:loading="exportLoading"
|
||||
v-hasPermi="['project:project:export']"
|
||||
>
|
||||
<Icon icon="ep:download" />导出
|
||||
</el-button>
|
||||
<el-button
|
||||
type="danger"
|
||||
plain
|
||||
:disabled="checkedIds.length === 0"
|
||||
@click="handleDeleteBatch"
|
||||
v-hasPermi="['project:project:delete']"
|
||||
>
|
||||
<Icon icon="ep:delete" />批量删除
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 列表 -->
|
||||
<ContentWrap>
|
||||
<el-table v-loading="loading" :data="list" @selection-change="handleRowCheckboxChange">
|
||||
<el-table-column type="selection" width="55" />
|
||||
<el-table-column label="项目ID" align="center" prop="id" width="80" />
|
||||
<el-table-column label="立项编号" align="center" prop="projectCode" width="150" />
|
||||
<el-table-column label="合同编号" align="center" prop="contractCode" width="150" />
|
||||
<el-table-column label="项目名称" align="center" prop="projectName" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="申报单位" align="center" prop="applyUnit" :show-overflow-tooltip="true" />
|
||||
<el-table-column label="状态" align="center" prop="status" width="100">
|
||||
<template #default="scope">
|
||||
<el-tag v-if="scope.row.status === '0'" type="info">待验收</el-tag>
|
||||
<el-tag v-else-if="scope.row.status === '1'" type="warning">验收中</el-tag>
|
||||
<el-tag v-else-if="scope.row.status === '2'" type="success">已完成</el-tag>
|
||||
<el-tag v-else>{{ scope.row.status }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="当前节点" align="center" prop="currentNode" width="120" />
|
||||
<el-table-column
|
||||
label="创建时间"
|
||||
align="center"
|
||||
prop="createTime"
|
||||
:formatter="dateFormatter"
|
||||
width="180"
|
||||
/>
|
||||
<el-table-column label="操作" align="center" width="180" fixed="right">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
@click="openForm('update', scope.row.id)"
|
||||
v-hasPermi="['project:project:update']"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
@click="handleStartAcceptance(scope.row)"
|
||||
v-hasPermi="['project:acceptance:submit-pre']"
|
||||
>
|
||||
发起验收
|
||||
</el-button>
|
||||
<el-button
|
||||
link
|
||||
type="danger"
|
||||
@click="handleDelete(scope.row.id)"
|
||||
v-hasPermi="['project:project:delete']"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页 -->
|
||||
<Pagination
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNo"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 表单弹窗:添加/修改 -->
|
||||
<ProjectForm ref="formRef" @success="getList" />
|
||||
<!-- 发起验收弹窗 -->
|
||||
<StartAcceptanceForm ref="startAcceptanceFormRef" @success="getList" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { dateFormatter } from '@/utils/formatTime'
|
||||
import download from '@/utils/download'
|
||||
import * as ProjectApi from '@/api/project/project'
|
||||
import ProjectForm from './ProjectForm.vue'
|
||||
import StartAcceptanceForm from './StartAcceptanceForm.vue'
|
||||
|
||||
defineOptions({ name: 'ProjectProject' })
|
||||
|
||||
const message = useMessage() // 消息弹窗
|
||||
const { t } = useI18n() // 国际化
|
||||
|
||||
const loading = ref(true) // 列表的加载中
|
||||
const total = ref(0) // 列表的总页数
|
||||
const list = ref([]) // 列表的数据
|
||||
const queryParams = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
projectCode: undefined,
|
||||
contractCode: undefined,
|
||||
projectName: undefined,
|
||||
applyUnit: undefined,
|
||||
status: undefined,
|
||||
createTime: []
|
||||
})
|
||||
const queryFormRef = ref() // 搜索的表单
|
||||
const exportLoading = ref(false) // 导出的加载中
|
||||
|
||||
/** 查询列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const data = await ProjectApi.getProjectPage(queryParams)
|
||||
list.value = data.list
|
||||
total.value = data.total
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
const handleQuery = () => {
|
||||
queryParams.pageNo = 1
|
||||
getList()
|
||||
}
|
||||
|
||||
/** 重置按钮操作 */
|
||||
const resetQuery = () => {
|
||||
queryFormRef.value.resetFields()
|
||||
handleQuery()
|
||||
}
|
||||
|
||||
/** 添加/修改操作 */
|
||||
const formRef = ref()
|
||||
const openForm = (type: string, id?: number) => {
|
||||
formRef.value.open(type, id)
|
||||
}
|
||||
|
||||
/** 删除按钮操作 */
|
||||
const handleDelete = async (id: number) => {
|
||||
try {
|
||||
// 删除的二次确认
|
||||
await message.delConfirm()
|
||||
// 发起删除
|
||||
await ProjectApi.deleteProject(id)
|
||||
message.success(t('common.delSuccess'))
|
||||
// 刷新列表
|
||||
await getList()
|
||||
} catch {}
|
||||
}
|
||||
|
||||
/** 批量删除按钮操作 */
|
||||
const checkedIds = ref<number[]>([])
|
||||
const handleRowCheckboxChange = (rows: ProjectApi.ProjectVO[]) => {
|
||||
checkedIds.value = rows.map((row) => row.id)
|
||||
}
|
||||
|
||||
const handleDeleteBatch = async () => {
|
||||
try {
|
||||
// 删除的二次确认
|
||||
await message.delConfirm()
|
||||
// 发起批量删除
|
||||
await ProjectApi.deleteProjectList(checkedIds.value)
|
||||
checkedIds.value = []
|
||||
message.success(t('common.delSuccess'))
|
||||
// 刷新列表
|
||||
await getList()
|
||||
} catch {}
|
||||
}
|
||||
|
||||
/** 导出按钮操作 */
|
||||
const handleExport = async () => {
|
||||
try {
|
||||
// 导出的二次确认
|
||||
await message.exportConfirm()
|
||||
// 发起导出
|
||||
exportLoading.value = true
|
||||
const data = await ProjectApi.exportProject(queryParams)
|
||||
download.excel(data, '项目数据.xls')
|
||||
} catch {
|
||||
} finally {
|
||||
exportLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 发起验收操作 */
|
||||
const startAcceptanceFormRef = ref()
|
||||
const handleStartAcceptance = (row: ProjectApi.ProjectVO) => {
|
||||
startAcceptanceFormRef.value.open(row)
|
||||
}
|
||||
|
||||
/** 初始化 **/
|
||||
onMounted(() => {
|
||||
getList()
|
||||
})
|
||||
</script>
|
||||
Loading…
Reference in New Issue