| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255 |
- /**
- * 项目阶段截止时间工具函数
- */
- /**
- * 默认工期配置(天数)
- */
- const DEFAULT_PHASE_DURATIONS = {
- modeling: 1, // 建模默认1天
- softDecor: 1, // 软装默认1天
- rendering: 1, // 渲染默认1天
- postProcessing: 1 // 后期默认1天
- };
- /**
- * 生成项目阶段截止时间
- * @param {Date} projectStartDate - 项目开始日期(可选)
- * @param {Date} projectDeadline - 项目截止日期(必填)
- * @param {Object} customDurations - 自定义工期(可选)
- * @returns {Object} phaseDeadlines对象
- */
- function generatePhaseDeadlines(projectStartDate, projectDeadline, customDurations = {}) {
- if (!projectDeadline) {
- throw new Error("项目截止日期(projectDeadline)是必填参数");
- }
-
- // 合并默认工期和自定义工期
- const durations = {
- ...DEFAULT_PHASE_DURATIONS,
- ...customDurations
- };
-
- const deadlineTime = projectDeadline.getTime();
-
- // 从后往前计算各阶段截止时间
- const postProcessingDeadline = new Date(deadlineTime);
- const renderingDeadline = new Date(deadlineTime - durations.postProcessing * 24 * 60 * 60 * 1000);
- const softDecorDeadline = new Date(deadlineTime - (durations.postProcessing + durations.rendering) * 24 * 60 * 60 * 1000);
- const modelingDeadline = new Date(deadlineTime - (durations.postProcessing + durations.rendering + durations.softDecor) * 24 * 60 * 60 * 1000);
-
- // 如果提供了开始日期,使用它作为建模阶段的开始时间
- const modelingStartDate = projectStartDate || new Date(deadlineTime - (durations.modeling + durations.softDecor + durations.rendering + durations.postProcessing) * 24 * 60 * 60 * 1000);
-
- // 构建阶段截止时间对象
- return {
- modeling: {
- startDate: modelingStartDate,
- deadline: modelingDeadline,
- estimatedDays: durations.modeling,
- status: "in_progress", // 默认第一个阶段为进行中
- priority: "medium"
- },
- softDecor: {
- startDate: modelingDeadline,
- deadline: softDecorDeadline,
- estimatedDays: durations.softDecor,
- status: "not_started",
- priority: "medium"
- },
- rendering: {
- startDate: softDecorDeadline,
- deadline: renderingDeadline,
- estimatedDays: durations.rendering,
- status: "not_started",
- priority: "medium"
- },
- postProcessing: {
- startDate: renderingDeadline,
- deadline: postProcessingDeadline,
- estimatedDays: durations.postProcessing,
- status: "not_started",
- priority: "medium"
- }
- };
- }
- /**
- * 从公司配置获取工期设置
- * @param {String} companyId - 公司ID
- * @returns {Promise<Object>} 工期配置
- */
- async function getCompanyPhaseDurations(companyId) {
- try {
- const companyQuery = new Parse.Query("Company");
- const company = await companyQuery.get(companyId, { useMasterKey: true });
-
- const companyData = company.get("data") || {};
- return companyData.phaseDefaultDurations || DEFAULT_PHASE_DURATIONS;
- } catch (error) {
- console.warn(`获取公司${companyId}的工期配置失败,使用默认配置:`, error.message);
- return DEFAULT_PHASE_DURATIONS;
- }
- }
- /**
- * 更新阶段状态
- * @param {String} projectId - 项目ID
- * @param {String} phaseName - 阶段名称 (modeling/softDecor/rendering/postProcessing)
- * @param {String} status - 新状态 (not_started/in_progress/completed/delayed)
- * @param {Object} additionalData - 额外数据(如completedAt)
- * @returns {Promise<Object>} 更新后的项目对象
- */
- async function updatePhaseStatus(projectId, phaseName, status, additionalData = {}) {
- const validPhases = ['modeling', 'softDecor', 'rendering', 'postProcessing'];
- const validStatuses = ['not_started', 'in_progress', 'completed', 'delayed'];
-
- if (!validPhases.includes(phaseName)) {
- throw new Error(`无效的阶段名称: ${phaseName}`);
- }
-
- if (!validStatuses.includes(status)) {
- throw new Error(`无效的状态: ${status}`);
- }
-
- const projectQuery = new Parse.Query("Project");
- const project = await projectQuery.get(projectId, { useMasterKey: true });
-
- const data = project.get("data") || {};
- const phaseDeadlines = data.phaseDeadlines || {};
-
- if (!phaseDeadlines[phaseName]) {
- throw new Error(`项目${projectId}没有${phaseName}阶段信息`);
- }
-
- // 更新阶段状态
- phaseDeadlines[phaseName].status = status;
-
- // 如果是完成状态,记录完成时间
- if (status === 'completed' && !phaseDeadlines[phaseName].completedAt) {
- phaseDeadlines[phaseName].completedAt = new Date();
- }
-
- // 合并额外数据
- Object.assign(phaseDeadlines[phaseName], additionalData);
-
- data.phaseDeadlines = phaseDeadlines;
- project.set("data", data);
-
- await project.save(null, { useMasterKey: true });
-
- return project;
- }
- /**
- * 获取项目当前阶段
- * @param {Object} phaseDeadlines - 阶段截止时间对象
- * @returns {String} 当前阶段名称
- */
- function getCurrentPhase(phaseDeadlines) {
- if (!phaseDeadlines) {
- return null;
- }
-
- const phases = ['modeling', 'softDecor', 'rendering', 'postProcessing'];
-
- // 找到第一个未完成的阶段
- for (const phase of phases) {
- const phaseInfo = phaseDeadlines[phase];
- if (phaseInfo && phaseInfo.status !== 'completed') {
- return phase;
- }
- }
-
- // 所有阶段都完成了,返回最后一个阶段
- return 'postProcessing';
- }
- /**
- * 检查阶段是否延期
- * @param {Object} phaseInfo - 阶段信息
- * @returns {Boolean} 是否延期
- */
- function isPhaseDelayed(phaseInfo) {
- if (!phaseInfo || !phaseInfo.deadline) {
- return false;
- }
-
- // 已完成的阶段不算延期
- if (phaseInfo.status === 'completed') {
- return false;
- }
-
- const deadline = new Date(phaseInfo.deadline);
- const now = new Date();
-
- return now > deadline;
- }
- /**
- * 获取阶段剩余天数
- * @param {Object} phaseInfo - 阶段信息
- * @returns {Number} 剩余天数(负数表示已逾期)
- */
- function getPhaseDaysRemaining(phaseInfo) {
- if (!phaseInfo || !phaseInfo.deadline) {
- return 0;
- }
-
- const deadline = new Date(phaseInfo.deadline);
- const now = new Date();
- const diff = deadline.getTime() - now.getTime();
-
- return Math.ceil(diff / (24 * 60 * 60 * 1000));
- }
- // 导出函数
- module.exports = {
- DEFAULT_PHASE_DURATIONS,
- generatePhaseDeadlines,
- getCompanyPhaseDurations,
- updatePhaseStatus,
- getCurrentPhase,
- isPhaseDelayed,
- getPhaseDaysRemaining
- };
- // Parse Cloud Code函数注册
- Parse.Cloud.define("generateProjectPhaseDeadlines", async (request) => {
- const { projectStartDate, projectDeadline, companyId, customDurations } = request.params;
-
- if (!projectDeadline) {
- throw new Error("缺少projectDeadline参数");
- }
-
- // 如果提供了companyId,获取公司的默认工期配置
- let durations = customDurations || {};
- if (companyId) {
- const companyDurations = await getCompanyPhaseDurations(companyId);
- durations = { ...companyDurations, ...customDurations };
- }
-
- const startDate = projectStartDate ? new Date(projectStartDate) : null;
- const deadline = new Date(projectDeadline);
-
- return generatePhaseDeadlines(startDate, deadline, durations);
- });
- Parse.Cloud.define("updateProjectPhaseStatus", async (request) => {
- const { projectId, phaseName, status, additionalData } = request.params;
-
- if (!projectId) {
- throw new Error("缺少projectId参数");
- }
-
- if (!phaseName) {
- throw new Error("缺少phaseName参数");
- }
-
- if (!status) {
- throw new Error("缺少status参数");
- }
-
- return await updatePhaseStatus(projectId, phaseName, status, additionalData);
- });
|