diff --git a/src/api/studentTrainingAnswer.js b/src/api/studentTrainingAnswer.js index 4be51d4..681cf8d 100644 --- a/src/api/studentTrainingAnswer.js +++ b/src/api/studentTrainingAnswer.js @@ -335,3 +335,32 @@ export function checkProductDevelopmentFactorsStepFour(payload) { } return request({ url: "/api/student-training-answers/product-development-factors/step-4/validate", method: "post", data: 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 } }); +} diff --git a/src/router/index.js b/src/router/index.js index 1a2dbf7..51be56e 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -250,7 +250,7 @@ export const dynamicRoutes = [ }, { path: "business-feasibility", - component: () => import("@/views/training/GenericTrainingPage.vue"), + component: () => import("@/views/demand/business-feasibility.vue"), name: "BusinessFeasibility", meta: { title: "商业可行性论证", icon: "需求挖掘", affix: true, pageKey: "business-feasibility" }, }, diff --git a/src/views/demand/business-feasibility.vue b/src/views/demand/business-feasibility.vue new file mode 100644 index 0000000..75b656e --- /dev/null +++ b/src/views/demand/business-feasibility.vue @@ -0,0 +1,127 @@ +