264 lines
7.7 KiB
TypeScript
264 lines
7.7 KiB
TypeScript
import request from '@/config/axios'
|
||
import axios from 'axios'
|
||
import * as FileApi from '@/api/infra/file'
|
||
|
||
// ============================================================
|
||
// 类型定义
|
||
// ============================================================
|
||
|
||
export interface ReviewMeetingProjectRespVO {
|
||
id: number
|
||
reviewMeetingId: number
|
||
seqNo: number
|
||
startTime: string
|
||
endTime: string
|
||
agendaCategory: string
|
||
projectTitle: string
|
||
reporter: string
|
||
reporterUnit: string
|
||
host?: string
|
||
reviewDate?: string
|
||
reviewResult?: 'PASS' | 'REJECT'
|
||
preMeetingMaterialsComplete?: boolean
|
||
postMeetingMaterialsComplete?: boolean
|
||
aiSummaryStatus?: number
|
||
aiSummaryUpdatedTime?: string
|
||
}
|
||
|
||
export const REVIEW_AGENDA_CATEGORY_OPTIONS = ['项目立项', '预验收', '项目终验'] as const
|
||
export type ReviewAgendaCategory = (typeof REVIEW_AGENDA_CATEGORY_OPTIONS)[number]
|
||
|
||
export interface ReviewMeetingProjectSeqUpdateReqVO {
|
||
id: number
|
||
seqNo: number
|
||
}
|
||
|
||
export interface ReviewMeetingProjectPageReqVO {
|
||
pageNo?: number
|
||
pageSize?: number
|
||
reviewMeetingId: number
|
||
projectTitle?: string
|
||
agendaCategory?: string
|
||
reporter?: string
|
||
reviewResult?: 'PASS' | 'REJECT'
|
||
reviewDate?: string
|
||
}
|
||
|
||
/** 独立项目列表查询(meetingId 可选,用于独立菜单页) */
|
||
export interface ReviewProjectPageReqVO {
|
||
pageNo?: number
|
||
pageSize?: number
|
||
reviewMeetingId?: number
|
||
projectTitle?: string
|
||
agendaCategory?: string
|
||
reporter?: string
|
||
reporterUnit?: string
|
||
reviewResult?: 'PASS' | 'REJECT'
|
||
reviewDate?: string
|
||
}
|
||
|
||
export interface ReviewMeetingFileRespVO {
|
||
id: number
|
||
reviewMeetingId: number
|
||
reviewMeetingProjectId: number
|
||
materialCode?: string
|
||
materialNameSnapshot?: string
|
||
agendaTypeSnapshot?: string
|
||
version?: number
|
||
fileName: string
|
||
fileUrl: string
|
||
fileSize: number
|
||
fileType: string
|
||
aiBuildStatus?: number
|
||
aiBuildStatusName?: string
|
||
aiBuildErrorMessage?: string
|
||
aiBuildTime?: string
|
||
creator: string
|
||
createTime: string
|
||
}
|
||
|
||
export interface ReviewMeetingFileRegisterReqVO {
|
||
reviewMeetingId: number
|
||
reviewMeetingProjectId: number
|
||
fileName: string
|
||
fileUrl: string
|
||
fileSize: number
|
||
fileType?: string
|
||
}
|
||
|
||
export interface ReviewMeetingMaterialItemRespVO {
|
||
materialCode: string
|
||
materialName: string
|
||
required: boolean
|
||
acceptExts: string
|
||
tabletVisible: boolean
|
||
latestFile?: ReviewMeetingFileRespVO
|
||
}
|
||
|
||
export interface ReviewMeetingMaterialSummaryRespVO {
|
||
agendaType: string
|
||
templateAvailable: boolean
|
||
materials: ReviewMeetingMaterialItemRespVO[]
|
||
}
|
||
|
||
export interface ReviewMeetingMaterialHistoryRespVO {
|
||
materialCode: string
|
||
materialName: string
|
||
file: ReviewMeetingFileRespVO
|
||
}
|
||
|
||
export interface ReviewMeetingMaterialUploadReqVO {
|
||
reviewMeetingId: number
|
||
reviewMeetingProjectId: number
|
||
materialCode: string
|
||
fileName: string
|
||
fileUrl: string
|
||
fileSize: number
|
||
fileType?: string
|
||
}
|
||
|
||
// ============================================================
|
||
// API 调用
|
||
// ============================================================
|
||
|
||
/** 分页查询评审项目列表(需要 meetingId) */
|
||
export const getReviewProjectPage = (params: ReviewMeetingProjectPageReqVO) =>
|
||
request.get({ url: '/project/review-project/page', params })
|
||
|
||
/** 独立分页查询评审项目列表(meetingId 可选) */
|
||
export const getReviewProjectPageStandalone = (params: ReviewProjectPageReqVO) =>
|
||
request.get({ url: '/project/review-project/page', params })
|
||
|
||
/** 创建评审项目 */
|
||
export const createReviewProject = (data: Partial<ReviewMeetingProjectRespVO>) =>
|
||
request.post({ url: '/project/review-project/create', data })
|
||
|
||
/** 更新评审项目信息 */
|
||
export const updateReviewProject = (data: Partial<ReviewMeetingProjectRespVO>) =>
|
||
request.put({ url: '/project/review-project/update', data })
|
||
|
||
/** 批量更新会中序号 */
|
||
export const updateReviewProjectSeqBatch = (data: ReviewMeetingProjectSeqUpdateReqVO[]) =>
|
||
request.put({ url: '/project/review-project/update-seq-batch', data })
|
||
|
||
/** 删除评审项目 */
|
||
export const deleteReviewProject = (ids: number[]) =>
|
||
request.delete({ url: '/project/review-project/delete', params: { ids: ids.join(',') } })
|
||
|
||
/** 更新评审项目主持人 */
|
||
export const updateProjectHost = (projectId: number, host: string) =>
|
||
request.put({ url: '/project/review-project/update-host', params: { projectId, host } })
|
||
|
||
/** 上传会议文件 */
|
||
export const uploadMeetingFile = (
|
||
reviewMeetingId: number,
|
||
reviewMeetingProjectId: number,
|
||
file: File
|
||
) => {
|
||
return uploadMeetingFileByPresignedUrl(reviewMeetingId, reviewMeetingProjectId, file)
|
||
}
|
||
|
||
/** 登记会议文件 */
|
||
export const registerMeetingFile = (data: ReviewMeetingFileRegisterReqVO) =>
|
||
request.post<ReviewMeetingFileRespVO>({ url: '/project/review-project/register-file', data })
|
||
|
||
/** 获取项目文件列表 */
|
||
export const getMeetingFileList = (reviewMeetingProjectId: number) =>
|
||
request.get({
|
||
url: '/project/review-project/file-list',
|
||
params: { reviewMeetingProjectId }
|
||
})
|
||
|
||
/** 删除会议文件 */
|
||
export const deleteMeetingFile = (id: number) =>
|
||
request.delete({ url: '/project/review-project/delete-file', params: { id } })
|
||
|
||
/** 获取结构化材料汇总 */
|
||
export const getProjectMaterialSummary = (reviewMeetingProjectId: number) =>
|
||
request.get<ReviewMeetingMaterialSummaryRespVO>({
|
||
url: '/project/review-project/material-summary',
|
||
params: { reviewMeetingProjectId }
|
||
})
|
||
|
||
/** 获取材料历史版本 */
|
||
export const getProjectMaterialHistory = (reviewMeetingProjectId: number, materialCode: string) =>
|
||
request.get<ReviewMeetingMaterialHistoryRespVO[]>({
|
||
url: '/project/review-project/material-history',
|
||
params: { reviewMeetingProjectId, materialCode }
|
||
})
|
||
|
||
/** 下载当前议程分类模板包 */
|
||
export const downloadProjectTemplateBundle = (agendaType: string) =>
|
||
request.download({
|
||
url: '/project/review-project/download-template-bundle',
|
||
params: { agendaType }
|
||
})
|
||
|
||
/** 上传结构化材料(预签名直传) */
|
||
export const uploadProjectMaterial = async (
|
||
reviewMeetingId: number,
|
||
reviewMeetingProjectId: number,
|
||
materialCode: string,
|
||
file: File
|
||
) => {
|
||
const presignedInfo = await FileApi.getFilePresignedUrl(file.name, 'review-meeting')
|
||
await axios.put(presignedInfo.uploadUrl, file, {
|
||
headers: {
|
||
'Content-Type': file.type || 'application/octet-stream'
|
||
}
|
||
})
|
||
|
||
await FileApi.createFile({
|
||
configId: presignedInfo.configId,
|
||
url: presignedInfo.url,
|
||
path: presignedInfo.path,
|
||
name: file.name,
|
||
type: file.type || 'application/octet-stream',
|
||
size: file.size
|
||
})
|
||
|
||
return request.post<ReviewMeetingFileRespVO>({
|
||
url: '/project/review-project/upload-material',
|
||
data: {
|
||
reviewMeetingId,
|
||
reviewMeetingProjectId,
|
||
materialCode,
|
||
fileName: file.name,
|
||
fileUrl: presignedInfo.url,
|
||
fileSize: file.size,
|
||
fileType: file.name.includes('.') ? file.name.split('.').pop()?.toLowerCase() : ''
|
||
} satisfies ReviewMeetingMaterialUploadReqVO
|
||
})
|
||
}
|
||
|
||
const uploadMeetingFileByPresignedUrl = async (
|
||
reviewMeetingId: number,
|
||
reviewMeetingProjectId: number,
|
||
file: File
|
||
) => {
|
||
const presignedInfo = await FileApi.getFilePresignedUrl(file.name, 'review-meeting')
|
||
await axios.put(presignedInfo.uploadUrl, file, {
|
||
headers: {
|
||
'Content-Type': file.type || 'application/octet-stream'
|
||
}
|
||
})
|
||
|
||
await FileApi.createFile({
|
||
configId: presignedInfo.configId,
|
||
url: presignedInfo.url,
|
||
path: presignedInfo.path,
|
||
name: file.name,
|
||
type: file.type || 'application/octet-stream',
|
||
size: file.size
|
||
})
|
||
|
||
return registerMeetingFile({
|
||
reviewMeetingId,
|
||
reviewMeetingProjectId,
|
||
fileName: file.name,
|
||
fileUrl: presignedInfo.url,
|
||
fileSize: file.size,
|
||
fileType: file.name.includes('.') ? file.name.split('.').pop()?.toLowerCase() : ''
|
||
})
|
||
}
|