feat: add market opportunity selection steps five and six

dev-QQq^2
chenyuan 5 days ago
parent 822cb61bc1
commit 18dfd1ca09

@ -628,7 +628,7 @@ export function checkRequirementsDocumentStepOne(payload) {
export function checkMarketOpportunitySelectionStepOne(items) { export function checkMarketOpportunitySelectionStepOne(items) {
const expected = { const expected = {
"search-count": "市场规模", "demand-supply-ratio": "竞争强度", "transaction-amount": "市场规模", "transaction-growth": "市场潜力", "search-count": "市场规模", "demand-supply-ratio": "竞争强度", "transaction-amount": "市场规模", "transaction-growth": "市场潜力",
"category-transaction-growth": "市场潜力", "online-products": "竞争强度", "online-merchants": "竞争强度", "organic-traffic-ratio": "运营难度", "category-transaction-growth": "市场潜力", "online-products": "竞争强度", "online-merchants": "竞争强度", "organic-traffic-ratio": "运营难度", "return-rate": "运营难度",
}; };
if (isStudentDemo()) { if (isStudentDemo()) {
const list = Array.isArray(items) ? items : []; const list = Array.isArray(items) ? items : [];
@ -640,17 +640,23 @@ export function checkMarketOpportunitySelectionStepOne(items) {
} }
export function checkMarketOpportunitySelectionStepTwo(payload) { export function checkMarketOpportunitySelectionStepTwo(payload) {
const weights = Array.isArray(payload?.weights) ? payload.weights : []; const primaryWeights = Array.isArray(payload?.primaryWeights) ? payload.primaryWeights : [];
const expectedIds = ["search-count", "transaction-amount", "transaction-growth", "category-transaction-growth", "demand-supply-ratio", "online-products", "online-merchants", "organic-traffic-ratio"]; const dimensionWeights = Array.isArray(payload?.dimensionWeights) ? payload.dimensionWeights : [];
if (isStudentDemo()) { const groups = ["市场规模", "市场潜力", "竞争强度", "运营难度"];
const ids = new Set(weights.map((item) => item?.id)); const expectedIds = ["search-count", "demand-supply-ratio", "transaction-amount", "transaction-growth", "category-transaction-growth", "online-products", "online-merchants", "organic-traffic-ratio", "return-rate"];
const total = weights.reduce((sum, item) => sum + Number(item?.weight || 0), 0); if (isStudentDemo()) {
if (weights.length !== expectedIds.length || expectedIds.some((id) => !ids.has(id)) || weights.some((item) => !Number.isInteger(Number(item?.weight)) || Number(item.weight) < 1 || Number(item.weight) > 100) || total !== 100) { const primaryMap = Object.fromEntries(primaryWeights.map((item) => [item?.group, Number(item?.weight)]));
return Promise.reject(new Error("二级指标权重需为 1 至 100 的整数,且合计必须为 100%")); const dimensionMap = Object.fromEntries(dimensionWeights.map((item) => [item?.id, Number(item?.weight)]));
const groupsByIndicator = { "search-count": "市场规模", "transaction-amount": "市场规模", "transaction-growth": "市场潜力", "category-transaction-growth": "市场潜力", "demand-supply-ratio": "竞争强度", "online-products": "竞争强度", "online-merchants": "竞争强度", "organic-traffic-ratio": "运营难度", "return-rate": "运营难度" };
const isWeight = (value) => Number.isInteger(value) && value >= 1 && value <= 100;
const validPrimary = primaryWeights.length === groups.length && groups.every((group) => isWeight(primaryMap[group])) && groups.reduce((sum, group) => sum + primaryMap[group], 0) === 100;
const validDimensions = dimensionWeights.length === expectedIds.length && expectedIds.every((id) => isWeight(dimensionMap[id])) && groups.every((group) => expectedIds.filter((id) => groupsByIndicator[id] === group).reduce((sum, id) => sum + dimensionMap[id], 0) === 100);
if (!validPrimary || !validDimensions) {
return Promise.reject(new Error("一级指标权重合计和各类维度内权重合计均须为 100%"));
} }
return Promise.resolve({ code: 200, data: { valid: true, message: "校验通过" } }); return Promise.resolve({ code: 200, data: { valid: true, message: "校验通过" } });
} }
return request({ url: "/api/student-training-answers/market-opportunity-selection/step-2/validate", method: "post", data: { weights }, headers: { repeatSubmit: false } }); return request({ url: "/api/student-training-answers/market-opportunity-selection/step-2/validate", method: "post", data: { primaryWeights, dimensionWeights }, headers: { repeatSubmit: false } });
} }
export function checkMarketOpportunitySelectionStepThree(payload) { export function checkMarketOpportunitySelectionStepThree(payload) {
@ -658,8 +664,9 @@ export function checkMarketOpportunitySelectionStepThree(payload) {
const expectedIds = ["smart-fitness-mirror", "smart-bathroom-mirror", "smart-beauty-mirror"]; const expectedIds = ["smart-fitness-mirror", "smart-bathroom-mirror", "smart-beauty-mirror"];
if (isStudentDemo()) { if (isStudentDemo()) {
const ids = new Set(scores.map((item) => item?.id)); const ids = new Set(scores.map((item) => item?.id));
if (scores.length !== expectedIds.length || expectedIds.some((id) => !ids.has(id)) || scores.some((item) => !Number.isFinite(Number(item?.score)) || Number(item.score) < 0 || Number(item.score) > 100)) { const isScore = (value) => Number.isFinite(Number(value)) && Number(value) >= 0 && Number(value) <= 100 && Math.round(Number(value) * 100) === Number(value) * 100;
return Promise.reject(new Error("请为三类产品填写 0 至 100 分的综合得分")); if (scores.length !== expectedIds.length || expectedIds.some((id) => !ids.has(id)) || scores.some((item) => !isScore(item?.score))) {
return Promise.reject(new Error("请为三类产品填写 0 至 100 分、最多保留两位小数的综合得分"));
} }
return Promise.resolve({ code: 200, data: { valid: true, message: "校验通过" } }); return Promise.resolve({ code: 200, data: { valid: true, message: "校验通过" } });
} }
@ -675,6 +682,30 @@ export function checkMarketOpportunitySelectionStepFour(payload) {
return request({ url: "/api/student-training-answers/market-opportunity-selection/step-4/validate", method: "post", data: { visualizationUrl }, headers: { repeatSubmit: false } }); return request({ url: "/api/student-training-answers/market-opportunity-selection/step-4/validate", method: "post", data: { visualizationUrl }, headers: { repeatSubmit: false } });
} }
export function checkMarketOpportunitySelectionStepFive(payload) {
const insights = Array.isArray(payload?.insights) ? payload.insights : [];
const expectedIds = ["smart-fitness-mirror", "smart-bathroom-mirror", "smart-beauty-mirror"];
const isRate = (value) => Number.isFinite(Number(value)) && Number(value) >= 0 && Number(value) <= 100 && Math.round(Number(value) * 100) === Number(value) * 100;
const isFilled = (value) => String(value || "").trim().length > 0;
if (isStudentDemo()) {
const ids = new Set(insights.map((item) => item?.productId));
if (insights.length !== expectedIds.length || expectedIds.some((id) => !ids.has(id)) || insights.some((item) => !isRate(item?.favorableRate) || !isFilled(item?.painPoint) || !isFilled(item?.unmetNeed))) {
return Promise.reject(new Error("请完整填写三类产品的好评率、用户痛点和未被满足的需求;好评率为 0 至 100最多保留两位小数"));
}
return Promise.resolve({ code: 200, data: { valid: true, message: "校验通过" } });
}
return request({ url: "/api/student-training-answers/market-opportunity-selection/step-5/validate", method: "post", data: { insights }, headers: { repeatSubmit: false } });
}
export function checkMarketOpportunitySelectionStepSix(payload) {
const developmentConclusion = String(payload?.developmentConclusion || "").trim();
if (isStudentDemo()) {
if (!developmentConclusion) return Promise.reject(new Error("请填写建议开发的产品及具体原因"));
return Promise.resolve({ code: 200, data: { valid: true, message: "校验通过" } });
}
return request({ url: "/api/student-training-answers/market-opportunity-selection/step-6/validate", method: "post", data: { developmentConclusion }, headers: { repeatSubmit: false } });
}
export function checkProductDevelopmentProcessStepOne(items) { export function checkProductDevelopmentProcessStepOne(items) {
if (isStudentDemo()) { if (isStudentDemo()) {
const results = Array.isArray(items) const results = Array.isArray(items)

File diff suppressed because one or more lines are too long
Loading…
Cancel
Save