|
|
|
|
@ -1633,3 +1633,50 @@ export function validateSupplierEvaluationStepThree(payload) {
|
|
|
|
|
headers: { repeatSubmit: false },
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function validateBusinessFeasibilityStepOneDemo(payload) {
|
|
|
|
|
const value = payload || {}; const overview = value.projectOverview || {};
|
|
|
|
|
const requiredOverview = ["projectBackground", "productPositioning", "projectGoals", "macroEnvironmentConclusion", "competitiveLandscapeConclusion"];
|
|
|
|
|
if (requiredOverview.some((key) => !String(overview[key] || "").trim())) throw new Error("请完整填写项目概述");
|
|
|
|
|
const market = value.marketAnalysis || {}; const numericFields = ["annualMarketSize", "monthlyGrowthRate", "topBrandMarketShare", "marketConcentrationCr3"];
|
|
|
|
|
if (numericFields.some((key) => !Number.isFinite(Number(market[key])) || Number(market[key]) < 0) || !String(market.competitorsPriceRange || "").trim()) throw new Error("请完整填写市场规模与竞争格局分析");
|
|
|
|
|
const users = Array.isArray(value.targetUsers) ? value.targetUsers : [];
|
|
|
|
|
if (users.length !== 3 || users.some((user) => !String(user?.userGroup || "").trim() || !String(user?.scenario || "").trim() || !String(user?.coreNeed || "").trim() || !String(user?.spendingPower || "").trim())) throw new Error("请完整填写 3 类目标用户群体分析");
|
|
|
|
|
const models = Array.isArray(value.businessModels) ? value.businessModels : [];
|
|
|
|
|
if (models.length !== 2 || models.some((model) => !String(model?.module || "").trim() || !String(model?.strategy || "").trim() || !String(model?.explanation || "").trim())) throw new Error("请完整填写商业模式梳理");
|
|
|
|
|
const costIds = ["hardware-bom", "manufacturing", "rd-amortization", "channel-marketing", "logistics-warehouse"]; const costs = Array.isArray(value.costs) ? value.costs : [];
|
|
|
|
|
if (costs.length !== costIds.length || costIds.some((id) => !costs.some((cost) => cost?.id === id && Number.isFinite(Number(cost?.amount)) && Number(cost.amount) >= 0))) throw new Error("请填写全部成本项目");
|
|
|
|
|
const totalCost = costs.reduce((total, cost) => total + Number(cost.amount), 0);
|
|
|
|
|
if (totalCost <= 0 || !Number.isFinite(Number(value.targetPrice)) || Number(value.targetPrice) < totalCost) throw new Error("目标售价需不低于单位总成本,且单位总成本必须大于 0");
|
|
|
|
|
const riskTypes = ["技术风险", "市场风险", "供应链风险", "资金风险"]; const risks = Array.isArray(value.risks) ? value.risks : [];
|
|
|
|
|
if (risks.length !== riskTypes.length || riskTypes.some((type) => !risks.some((risk) => risk?.type === type && String(risk?.description || "").trim() && ["高", "中", "低"].includes(risk?.impact) && String(risk?.response || "").trim()))) throw new Error("请完整填写风险描述、影响程度和应对措施");
|
|
|
|
|
const unitGrossProfit = Number(value.targetPrice) - totalCost;
|
|
|
|
|
return { valid: true, message: "校验通过", unitTotalCost: totalCost.toFixed(2), unitGrossProfit: unitGrossProfit.toFixed(2), grossMargin: (unitGrossProfit / totalCost * 100).toFixed(2) };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function checkBusinessFeasibilityStepOne(payload) {
|
|
|
|
|
if (isStudentDemo()) { try { return Promise.resolve({ code: 200, data: validateBusinessFeasibilityStepOneDemo(payload) }); } catch (error) { return Promise.reject(error); } }
|
|
|
|
|
return request({ url: "/api/student-training-answers/business-feasibility/step-1/validate", method: "post", data: payload, headers: { repeatSubmit: false } });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function checkBusinessFeasibilityStepTwo(payload) {
|
|
|
|
|
const value = payload || {};
|
|
|
|
|
if (isStudentDemo()) {
|
|
|
|
|
const decisions = ["highly-feasible", "feasible-after-optimization", "observe", "not-feasible"]; const priorities = ["hardware-cost-control", "content-ecosystem", "channel-expansion", "brand-differentiation", "supply-chain-management", "capital-planning"]; const selected = Array.isArray(value.priorities) ? value.priorities : [];
|
|
|
|
|
if (!decisions.includes(value.decision)) return Promise.reject(new Error("请选择项目商业可行性总体评估"));
|
|
|
|
|
if (selected.some((item) => !priorities.includes(item)) || new Set(selected).size !== selected.length) return Promise.reject(new Error("优先问题包含无效或重复项"));
|
|
|
|
|
if (value.decision === "not-feasible" && selected.length) return Promise.reject(new Error("选择不可行时无需勾选优先问题"));
|
|
|
|
|
if (value.decision !== "not-feasible" && selected.length !== 3) return Promise.reject(new Error("请且仅选择 3 个需要优先解决的关键问题"));
|
|
|
|
|
return Promise.resolve({ code: 200, data: { valid: true, message: "校验通过" } });
|
|
|
|
|
}
|
|
|
|
|
return request({ url: "/api/student-training-answers/business-feasibility/step-2/validate", method: "post", data: value, headers: { repeatSubmit: false } });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function checkBusinessFeasibilityStepThree(payload) {
|
|
|
|
|
const reportUrl = String(payload?.reportUrl || "").trim(); const reportName = String(payload?.reportName || "").trim(); const supported = /\.(pdf|docx?|png|jpe?g)(?:\?|$)/i;
|
|
|
|
|
if (isStudentDemo()) {
|
|
|
|
|
if (!reportUrl || !supported.test(reportUrl) && !supported.test(reportName)) return Promise.reject(new Error("请上传 PDF、Word、PNG 或 JPG 格式的可行性论证报告"));
|
|
|
|
|
return Promise.resolve({ code: 200, data: { valid: true, message: "校验通过" } });
|
|
|
|
|
}
|
|
|
|
|
return request({ url: "/api/student-training-answers/business-feasibility/step-3/validate", method: "post", data: { reportUrl, reportName }, headers: { repeatSubmit: false } });
|
|
|
|
|
}
|
|
|
|
|
|