From c59f37569f9cd48de4a8719ed1e2456d93b0f645 Mon Sep 17 00:00:00 2001 From: lh Date: Fri, 19 Dec 2025 14:37:17 +0800 Subject: [PATCH] =?UTF-8?q?=E9=A1=B9=E7=9B=AE=E5=91=A8=E6=8A=A5=E5=AE=8C?= =?UTF-8?q?=E5=96=84=E3=80=81=E6=9C=BA=E7=A5=A8=E9=A2=84=E5=AE=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/oa/crm/flightBooking/index.ts | 76 ++ src/api/oa/crm/flightBooking/types.ts | 201 +++++ src/views/oa/crm/flightBooking/edit.vue | 974 +++++++++++++++++++++++ src/views/oa/crm/flightBooking/index.vue | 334 ++++++++ src/views/oa/erp/projectReport/edit.vue | 293 ++++--- 5 files changed, 1771 insertions(+), 107 deletions(-) create mode 100644 src/api/oa/crm/flightBooking/index.ts create mode 100644 src/api/oa/crm/flightBooking/types.ts create mode 100644 src/views/oa/crm/flightBooking/edit.vue create mode 100644 src/views/oa/crm/flightBooking/index.vue diff --git a/src/api/oa/crm/flightBooking/index.ts b/src/api/oa/crm/flightBooking/index.ts new file mode 100644 index 0000000..02deea7 --- /dev/null +++ b/src/api/oa/crm/flightBooking/index.ts @@ -0,0 +1,76 @@ +import request from '@/utils/request'; +import { AxiosPromise } from 'axios'; +import { FlightBookingVO, FlightBookingForm, FlightBookingQuery } from '@/api/oa/flightBooking/types'; + +/** + * 查询机票预订列表 + * @param query + * @returns {*} + */ + +export const listFlightBooking = (query?: FlightBookingQuery): AxiosPromise => { + return request({ + url: '/oa/crm/flightBooking/list', + method: 'get', + params: query + }); +}; + +/** + * 查询机票预订详细 + * @param bookingId + */ +export const getFlightBooking = (bookingId: string | number): AxiosPromise => { + return request({ + url: '/oa/crm/flightBooking/' + bookingId, + method: 'get' + }); +}; + +/** + * 新增机票预订 + * @param data + */ +export const addFlightBooking = (data: FlightBookingForm) => { + return request({ + url: '/oa//crm/flightBooking', + method: 'post', + data: data + }); +}; + +/** + * 修改机票预订 + * @param data + */ +export const updateFlightBooking = (data: FlightBookingForm) => { + return request({ + url: '/oa//crm/flightBooking', + method: 'put', + data: data + }); +}; + +/** + * 删除机票预订 + * @param bookingId + */ +export const delFlightBooking = (bookingId: string | number | Array) => { + return request({ + url: '/oa//crm/flightBooking/' + bookingId, + method: 'delete' + }); +}; + +/** + * 下拉框查询机票预订列表 + * @param query + * @returns {*} + */ +export function getCrmFlightBookingList(query) { + return request({ + url: '/oa//crm/flightBooking/getCrmFlightBookingList', + method: 'get', + params: query + }); +} diff --git a/src/api/oa/crm/flightBooking/types.ts b/src/api/oa/crm/flightBooking/types.ts new file mode 100644 index 0000000..bd704f8 --- /dev/null +++ b/src/api/oa/crm/flightBooking/types.ts @@ -0,0 +1,201 @@ +export interface FlightBookingVO { + /** + * 机票预订ID + */ + bookingId: string | number; + + /** + * 机票预订编号 + */ + applyCode: string; + + /** + * 乘机人ID + */ + passengerId: string | number; + + /** + * 乘机人姓名 + */ + passengerName: string; + + /** + * 出行日期 + */ + travelDate: string; + + /** + * 出发地点(出差地点) + */ + departureLocation: string; + + /** + * 到达地点 + */ + arrivalLocation: string; + + /** + * 机票折扣(1:5折及以下 2:5~8折 3:8折及以上 4:退改签) + */ + flightDiscount: string; + + /** + * 机票金额(元) + */ + flightAmount: number; + + /** + * 附件ID(支持多个,逗号分隔) + */ + ossId: string | number; + + /** + * 申请状态(1暂存 2审批中 3已审批 4作废) + */ + bookingStatus: string; + + /** + * 流程状态 + */ + flowStatus: string; + + /** + * 备注 + */ + remark: string; + +} + +export interface FlightBookingForm extends BaseEntity { + /** + * 机票预订ID + */ + bookingId?: string | number; + + /** + * 机票预订编号 + */ + applyCode?: string; + + /** + * 乘机人ID + */ + passengerId?: string | number; + + /** + * 乘机人姓名 + */ + passengerName?: string; + + /** + * 出行日期 + */ + travelDate?: string; + + /** + * 出发地点(出差地点) + */ + departureLocation?: string; + + /** + * 到达地点 + */ + arrivalLocation?: string; + + /** + * 机票折扣(1:5折及以下 2:5~8折 3:8折及以上 4:退改签) + */ + flightDiscount?: string; + + /** + * 机票金额(元) + */ + flightAmount?: number; + + /** + * 附件ID(支持多个,逗号分隔) + */ + ossId?: string | number; + + /** + * 申请状态(1暂存 2审批中 3已审批 4作废) + */ + bookingStatus?: string; + + /** + * 流程状态 + */ + flowStatus?: string; + + /** + * 备注 + */ + remark?: string; + +} + +export interface FlightBookingQuery extends PageQuery { + + /** + * 机票预订编号 + */ + applyCode?: string; + + /** + * 乘机人ID + */ + passengerId?: string | number; + + /** + * 乘机人姓名 + */ + passengerName?: string; + + /** + * 出行日期 + */ + travelDate?: string; + + /** + * 出发地点(出差地点) + */ + departureLocation?: string; + + /** + * 到达地点 + */ + arrivalLocation?: string; + + /** + * 机票折扣(1:5折及以下 2:5~8折 3:8折及以上 4:退改签) + */ + flightDiscount?: string; + + /** + * 机票金额(元) + */ + flightAmount?: number; + + /** + * 附件ID(支持多个,逗号分隔) + */ + ossId?: string | number; + + /** + * 申请状态(1暂存 2审批中 3已审批 4作废) + */ + bookingStatus?: string; + + /** + * 流程状态 + */ + flowStatus?: string; + + /** + * 日期范围参数 + */ + params?: any; +} + + + diff --git a/src/views/oa/crm/flightBooking/edit.vue b/src/views/oa/crm/flightBooking/edit.vue new file mode 100644 index 0000000..c58df9f --- /dev/null +++ b/src/views/oa/crm/flightBooking/edit.vue @@ -0,0 +1,974 @@ + + + diff --git a/src/views/oa/crm/flightBooking/index.vue b/src/views/oa/crm/flightBooking/index.vue new file mode 100644 index 0000000..4e65ea3 --- /dev/null +++ b/src/views/oa/crm/flightBooking/index.vue @@ -0,0 +1,334 @@ + + + diff --git a/src/views/oa/erp/projectReport/edit.vue b/src/views/oa/erp/projectReport/edit.vue index f3b36eb..b3593c4 100644 --- a/src/views/oa/erp/projectReport/edit.vue +++ b/src/views/oa/erp/projectReport/edit.vue @@ -207,11 +207,12 @@ - - + + { //根据项目名称回调项目信息 const projectInfoSelectCallBack = async (data: any) => { if (data.length > 0) { + proxy?.$modal.loading('正在导出数据,请稍后...'); const res = await getErpProjectReportList({ projectId: data[0].projectId }); // console.log(res.data); if (res.data.length > 0) { if (res.data[0].status === '0') { projectFormRef.value?.resetFields(); projectReportDetailFormRef.value?.resetFields(); + proxy?.$modal.closeLoading(); proxy?.$modal.notifyError('该项目周报记录已存在,请在项目周报信息界面维护!'); } else { projectFormRef.value?.resetFields(); projectReportDetailFormRef.value?.resetFields(); + proxy?.$modal.closeLoading(); proxy?.$modal.notifyError('已存在暂存记录,请在项目周报信息界面维护!'); } } else { + proxy?.$modal.closeLoading(); proxy?.$modal.msgSuccess('选择成功'); Object.assign(form.value, data[0]); } } else { projectFormRef.value?.resetFields(); projectReportDetailFormRef.value?.resetFields(); + proxy?.$modal.closeLoading(); proxy?.$modal.msgWarning('请选择项目信息'); } }; @@ -1113,119 +1119,116 @@ const submitProjectReportForm = () => { }; // 添加响应式变量来存储日期部分 const datePart = ref(''); // 日期部分(YYYY-MM-DD) - -// 工作周计算函数 - 包含星期几 -const getWorkWeek = (dateString) => { - if (!dateString) return ''; - - const date = new Date(dateString); - if (isNaN(date.getTime())) { - return ''; - } - - const year = date.getFullYear(); - const firstDayOfYear = new Date(year, 0, 1); - - // 使用时间戳计算天数差 - const timeDiff = date.getTime() - firstDayOfYear.getTime(); - const days = Math.floor(timeDiff / (24 * 60 * 60 * 1000)) + 1; - - // 计算周数 - const firstDayWeek = firstDayOfYear.getDay(); - const isoFirstDayWeek = firstDayWeek === 0 ? 7 : firstDayWeek; - const weekNumber = Math.ceil((days + isoFirstDayWeek - 1) / 7); - - // 获取星期几(0-周日,1-周一,...,6-周六) - const weekday = date.getDay(); - const weekdays = ['周日', '周一', '周二', '周三', '周四', '周五', '周六']; - - return `${weekdays[weekday]}`; -}; -// 初始化默认日期 -const initDefaultDate = () => { - if (routeParams.value.type === 'add') { - // 设置日期部分和 fillTime +// 统一处理日期时间格式的函数 +const formatDateTime = (dateStr?: string, includeTime: boolean = true): string => { + if (!dateStr) { const now = new Date(); - - // 格式化日期为 YYYY-MM-DD const year = now.getFullYear(); const month = String(now.getMonth() + 1).padStart(2, '0'); const day = String(now.getDate()).padStart(2, '0'); - const dateStr = `${year}-${month}-${day}`; - // 格式化时间为 HH:mm:ss(用于保存) - const hours = String(now.getHours()).padStart(2, '0'); - const minutes = String(now.getMinutes()).padStart(2, '0'); - const seconds = String(now.getSeconds()).padStart(2, '0'); - const timeStr = `${hours}:${minutes}:${seconds}`; - - // 设置日期部分 - datePart.value = dateStr; - - // 组合成完整的日期时间字符串(带当前时间) - // 如果已有 fillTime(从缓存或传入数据),使用已有的,否则设置新的 - if (!projectReportForm.value.fillTime) { - projectReportForm.value.fillTime = `${dateStr} ${timeStr}`; - } else { - // 确保 fillTime 是 DateTime 格式,如果只有日期部分,添加时间部分 - if (projectReportForm.value.fillTime && !projectReportForm.value.fillTime.includes(' ')) { - projectReportForm.value.fillTime = `${projectReportForm.value.fillTime} ${timeStr}`; - } + if (includeTime) { + const hours = String(now.getHours()).padStart(2, '0'); + const minutes = String(now.getMinutes()).padStart(2, '0'); + const seconds = String(now.getSeconds()).padStart(2, '0'); + return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; } - - // 计算工作周 - projectReportForm.value.currentWorkWeek = getWorkWeek(dateStr); + return `${year}-${month}-${day}`; } -}; -// 处理日期变化 -const handleDateChange = (selectedDate) => { - if (selectedDate) { - // 获取当前时间(用户提交流程的时间) + // 如果传入的日期字符串已经包含时间,直接返回 + if (dateStr.includes(' ')) { + return dateStr; + } + + // 如果只有日期,添加默认时间 + if (includeTime) { const now = new Date(); const hours = String(now.getHours()).padStart(2, '0'); const minutes = String(now.getMinutes()).padStart(2, '0'); const seconds = String(now.getSeconds()).padStart(2, '0'); - const timeStr = `${hours}:${minutes}:${seconds}`; + return `${dateStr} ${hours}:${minutes}:${seconds}`; + } - // 组合成完整的日期时间字符串(日期为用户选择的,时间为当前时间) - projectReportForm.value.fillTime = `${selectedDate} ${timeStr}`; + return dateStr; +}; - // 计算工作周 - projectReportForm.value.currentWorkWeek = getWorkWeek(selectedDate); - } else { - // 如果清空了日期 - projectReportForm.value.fillTime = ''; - projectReportForm.value.currentWorkWeek = ''; +// 解析日期时间,提取日期部分 +const parseDatePart = (dateTimeStr?: string): string => { + if (!dateTimeStr) return ''; + + const [date] = dateTimeStr.split(' '); + return date || ''; +}; + +// 工作周计算函数 - 包含星期几 +const getWorkWeek = (dateString: string): string => { + if (!dateString) return ''; + + try { + // 处理可能包含时间的字符串 + const [datePart] = dateString.split(' '); + const date = new Date(datePart); + + if (isNaN(date.getTime())) { + console.warn('无效的日期格式:', dateString); + return ''; + } + + const year = date.getFullYear(); + const firstDayOfYear = new Date(year, 0, 1); + + // 使用时间戳计算天数差 + const timeDiff = date.getTime() - firstDayOfYear.getTime(); + const days = Math.floor(timeDiff / (24 * 60 * 60 * 1000)) + 1; + + // 计算周数 + const firstDayWeek = firstDayOfYear.getDay(); + const isoFirstDayWeek = firstDayWeek === 0 ? 7 : firstDayWeek; + const weekNumber = Math.ceil((days + isoFirstDayWeek - 1) / 7); + + // 获取星期几(0-周日,1-周一,...,6-周六) + const weekday = date.getDay(); + const weekdays = ['周日', '周一', '周二', '周三', '周四', '周五', '周六']; + + return `${weekdays[weekday]}`; + } catch (error) { + console.error('计算工作周失败:', error); + return ''; } }; -// 监听 fillTime 变化,当从后端获取数据时设置日期部分 -watch( - () => projectReportForm.value.fillTime, - (newValue) => { - if (newValue && (routeParams.value.type === 'update' || routeParams.value.type === 'view' || routeParams.value.type === 'approval')) { - // 解析日期时间字符串,只取日期部分 - const [date] = newValue.split(' '); - if (date) { - datePart.value = date; - } +// 初始化默认日期 +const initDefaultDate = () => { + if (routeParams.value.type === 'add') { + // 确保 fillTime 有完整的日期时间格式 + if (!projectReportForm.value.fillTime) { + projectReportForm.value.fillTime = formatDateTime(); + } else { + // 确保已有的 fillTime 是完整的格式 + projectReportForm.value.fillTime = formatDateTime(projectReportForm.value.fillTime, true); } - }, - { immediate: true } -); -// 添加修改对话框的日期部分变量 -const modifyDatePart = ref(''); -// 处理修改对话框日期变化 -const handleModifyDateChange = (selectedDate) => { + // 从 fillTime 中提取日期部分设置到 datePart + datePart.value = parseDatePart(projectReportForm.value.fillTime); + + // 计算工作周 + if (datePart.value) { + projectReportForm.value.currentWorkWeek = getWorkWeek(datePart.value); + } + } +}; + +// 处理日期变化 - 优化版本 +const handleDateChange = (selectedDate: string) => { if (selectedDate) { - // 获取当前时间(保持原有时间或使用当前时间) - let timeStr = ''; - if (detailForm.value.fillTime && detailForm.value.fillTime.includes(' ')) { - const [, time] = detailForm.value.fillTime.split(' '); - if (time) { - timeStr = time; + // 获取当前的时间部分,如果已有 fillTime 则保留原时间,否则使用当前时间 + let timeStr = '00:00:00'; // 默认时间 + + if (projectReportForm.value.fillTime && projectReportForm.value.fillTime.includes(' ')) { + const [, existingTime] = projectReportForm.value.fillTime.split(' '); + if (existingTime) { + timeStr = existingTime; } else { const now = new Date(); const hours = String(now.getHours()).padStart(2, '0'); @@ -1240,8 +1243,50 @@ const handleModifyDateChange = (selectedDate) => { const seconds = String(now.getSeconds()).padStart(2, '0'); timeStr = `${hours}:${minutes}:${seconds}`; } + + // 组合成完整的日期时间字符串 + projectReportForm.value.fillTime = `${selectedDate} ${timeStr}`; + + // 计算工作周 + projectReportForm.value.currentWorkWeek = getWorkWeek(selectedDate); + } else { + // 如果清空了日期 + projectReportForm.value.fillTime = ''; + projectReportForm.value.currentWorkWeek = ''; + } +}; + +// 添加修改对话框的日期部分变量 +const modifyDatePart = ref(''); + +// 处理修改对话框日期变化 +const handleModifyDateChange = (selectedDate: string) => { + if (selectedDate) { + // 获取当前的时间部分,如果已有 fillTime 则保留原时间 + let timeStr = '00:00:00'; // 默认时间 + + if (detailForm.value.fillTime && detailForm.value.fillTime.includes(' ')) { + const [, existingTime] = detailForm.value.fillTime.split(' '); + if (existingTime) { + timeStr = existingTime; + } else { + const now = new Date(); + const hours = String(now.getHours()).padStart(2, '0'); + const minutes = String(now.getMinutes()).padStart(2, '0'); + const seconds = String(now.getSeconds()).padStart(2, '0'); + timeStr = `${hours}:${minutes}:${seconds}`; + } + } else { + const now = new Date(); + const hours = String(now.getHours()).padStart(2, '0'); + const minutes = String(now.getMinutes()).padStart(2, '0'); + const seconds = String(now.getSeconds()).padStart(2, '0'); + timeStr = `${hours}:${minutes}:${seconds}`; + } + // 组合成完整的日期时间字符串 detailForm.value.fillTime = `${selectedDate} ${timeStr}`; + // 计算工作周 detailForm.value.currentWorkWeek = getWorkWeek(selectedDate); } else { @@ -1250,9 +1295,14 @@ const handleModifyDateChange = (selectedDate) => { detailForm.value.currentWorkWeek = ''; } }; + // 审批记录 -const handleApprovalRecord = () => { - approvalRecordRef.value.init(projectReportForm.value.reportDetailId); +const handleApprovalRecord = (row?: ProjectReportDetailVO) => { + if (row) { + approvalRecordRef.value.init(row?.reportDetailId); + } else { + approvalRecordRef.value.init(projectReportForm.value.reportDetailId); + } }; // 提交回调 @@ -1290,6 +1340,11 @@ const getProjectDetail = async () => { reportId: form.value.reportId }); projectReportDetailList.value = res.rows; + // 确保每条数据的 fillTime 都有完整格式 + projectReportDetailList.value = res.rows.map((item) => ({ + ...item, + fillTime: formatDateTime(item.fillTime, true) + })); total.value = res.total; loading.value = false; }; @@ -1307,6 +1362,7 @@ const shouldCheckApprovalData = computed(() => { return (routeParams.value.type === 'add' || routeParams.value.type === 'update') && routeParams.value.reportData; }); // 查询是否存在审批中的数据 +// 在 checkApprovalData 函数中确保日期格式 const checkApprovalData = async () => { try { if (!shouldCheckApprovalData.value) return; @@ -1328,14 +1384,17 @@ const checkApprovalData = async () => { if (res.rows && res.rows.length > 0) { hasApprovalData.value = true; // 填充第一条审批中的数据 - Object.assign(projectReportForm.value, res.rows[0]); + const approvalData = res.rows[0]; + Object.assign(projectReportForm.value, approvalData); + + // 确保 fillTime 有完整格式 + projectReportForm.value.fillTime = formatDateTime(approvalData.fillTime, true); + // 设置日期部分 - if (projectReportForm.value.fillTime) { - const [date] = projectReportForm.value.fillTime.split(' '); - if (date) { - datePart.value = date; - } - } + datePart.value = parseDatePart(projectReportForm.value.fillTime); + + // 确保 flowStatus 被正确设置为 'waiting' + projectReportForm.value.flowStatus = 'waiting'; } else { hasApprovalData.value = false; } @@ -1482,6 +1541,9 @@ onMounted(async () => { await checkApprovalData(); } else { Object.assign(projectReportForm.value, reportData); + // 确保项目周报表单的日期格式正确 + projectReportForm.value.fillTime = formatDateTime(projectReportForm.value.fillTime, true); + datePart.value = parseDatePart(projectReportForm.value.fillTime); projectReportForm.value.informationNote = undefined; projectReportForm.value.remark = undefined; projectReportForm.value.ossId = undefined; @@ -1497,6 +1559,13 @@ onMounted(async () => { } else { const reportId = routeParams.value.id; const res = await listProjectReportDetail({ pageNum: 1, pageSize: 10, reportId: reportId }); + if (res.rows && res.rows.length > 0) { + const detailData = res.rows[0]; + // 确保日期格式正确 + detailData.fillTime = formatDateTime(detailData.fillTime, true); + Object.assign(projectReportForm.value, detailData); + datePart.value = parseDatePart(projectReportForm.value.fillTime); + } Object.assign(projectReportForm.value, res.rows[0]); } proxy?.$modal.closeLoading(); @@ -1513,13 +1582,23 @@ onMounted(async () => { if (reportId && routeParams.value.type === 'view') { const reportRes = await getProjectReport(reportId); Object.assign(form.value, reportRes.data); + // 确保日期格式正确 + reportDetailRes.data.fillTime = formatDateTime(reportDetailRes.data.fillTime, true); Object.assign(projectReportForm.value, reportDetailRes.data); + + // 设置日期部分 + datePart.value = parseDatePart(projectReportForm.value.fillTime); projectReportDetailList.value = [reportDetailRes.data]; } if (reportId && routeParams.value.type === 'approval') { const reportRes = await getProjectReport(reportId); Object.assign(form.value, reportRes.data); + // 确保日期格式正确 + reportDetailRes.data.fillTime = formatDateTime(reportDetailRes.data.fillTime, true); Object.assign(projectReportForm.value, reportDetailRes.data); + + // 设置日期部分 + datePart.value = parseDatePart(projectReportForm.value.fillTime); } proxy?.$modal.closeLoading(); }