@ -104,6 +104,20 @@
< div class = "task-actions" > < button type = "button" class = "btn-nav btn-submit" :disabled ="saving" @click ="saveAndGoToStepThree" > 保 存 并 进 入 第 3 步 < / button > < button type = "button" class = "btn-nav" :disabled ="saving" @click ="resetTraining" > < el -icon > < RefreshLeft / > < / e l - i c o n > 清 空 填 写 < / b u t t o n > < / d i v >
< / template >
< template v -else -if = " currentStep = = = 2 " >
< p class = "factor-intro" > 商业化及市场反馈角度分析 , 填写下表 : < / p >
< div class = "training-table-wrap" > < table class = "factor-table" > < thead > < tr > < th class = "dimension-col" > 维度 < / th > < th class = "criteria-col" > 评估项 < / th > < th > 成功产品 < / th > < th > 失败产品 < / th > < / tr > < / thead > < tbody >
< tr v-for ="row in stepThreeRows" :key="row.dimension"><td class="dimension-cell">{{ row.dimension }}</td><td class="criteria-cell" > {{ row.criteria }} < / td > < td > < textarea v -model = " row.successAnalysis " class = "table-textarea" placeholder = "填写成功产品在该维度的分析" / > < / td > < td > < textarea v -model = " row.failedAnalysis " class = "table-textarea" placeholder = "填写失败产品在该维度的分析" / > < / td > < / tr >
< / tbody > < / table > < / div >
< div class = "task-actions" > < button type = "button" class = "btn-nav btn-submit" :disabled ="saving" @click ="saveAndGoToStepFour" > 保 存 并 进 入 第 4 步 < / button > < button type = "button" class = "btn-nav" :disabled ="saving" @click ="resetTraining" > < el -icon > < RefreshLeft / > < / e l - i c o n > 清 空 填 写 < / b u t t o n > < / d i v >
< / template >
< template v -else -if = " currentStep = = = 3 " >
< p class = "factor-intro" > 结合案例信息及前述步骤 , 分析案例资料中产品一成功的关键因素是什么 , 产品二失败的关键因素是什么 。 < / p >
< label class = "factor-intro" > 产品成功的关键因素 : < / label > < textarea v -model = " stepFourForm.successFactors " class = "table-textarea summary-textarea" / >
< label class = "factor-intro" > 产品失败的关键因素 : < / label > < textarea v -model = " stepFourForm.failedFactors " class = "table-textarea summary-textarea" / >
< div class = "task-actions" > < button type = "button" class = "btn-nav btn-submit" :disabled ="saving" @click ="submitTraining" > 提 交 任 务 < / button > < button type = "button" class = "btn-nav" :disabled ="saving" @click ="resetTraining" > 清 空 填 写 < / button > < / div >
< / template >
< div v -else class = "step-placeholder" >
< p > 第 { { currentStep + 1 } } 步内容待配置 < / p >
< span > 已保存的分析可从上方步骤栏返回查看 。 < / span >
@ -125,7 +139,7 @@
< script setup >
import { Download , Operation , RefreshLeft } from "@element-plus/icons-vue" ;
import { getTrainingTaskByKey } from "@/api/trainingTask" ;
import { checkProductDevelopmentFactorsStepOne , checkProductDevelopmentFactorsStepTwo , getStudentTrainingAnswer, saveStudentTrainingAnswer } from "@/api/studentTrainingAnswer" ;
import { checkProductDevelopmentFactorsStepOne , checkProductDevelopmentFactorsStepTwo , checkProductDevelopmentFactorsStepThree, checkProductDevelopmentFactorsStepFour , getStudentTrainingAnswer, saveStudentTrainingAnswer } from "@/api/studentTrainingAnswer" ;
import useUserStore from "@/store/modules/user" ;
import TrainingAiSidebar from "@/views/components/TrainingAiSidebar.vue" ;
import TrainingMaterialButton from "@/views/components/TrainingMaterialButton.vue" ;
@ -182,6 +196,11 @@ const STEP_TWO_FACTOR_ROWS = [
{ dimension : "技术应用" , criteria : "核心技术是否已成熟、可量产?避免使用实验室级原型(如未验证的 AI 模型)" } ,
{ dimension : "合规与认证" , criteria : "是否通过目标市场强制认证? 目标市场要求的产品资质、检测报告等中国: CCC; 美国: FCC; 欧盟: CE; 出口需符合 RoHS、REACH。是否规避专利与知识产权风险? " } ,
] ;
const STEP _THREE _FACTOR _ROWS = [
{ dimension : "供应链与成本控制" , criteria : "产品成本是否可控? 是否支持规模化? 是否具备备选供应链? 关键元器件( 如芯片、传感器) 有≥2家可替换供应商" } ,
{ dimension : "商业模式" , criteria : "盈利模式是否清晰? 硬件销售毛利率≥50%, 或有订阅服务( 如云存储、AI 功能包)。是否构建“数据 - 反馈 - 迭代”闭环?产品使用数据可回传,驱动功能优化与新版本开发" } ,
{ dimension : "市场反馈" , criteria : "是否处于需求上升期?功能、设计、服务、品牌是否有差异化壁垒?用户是否高留存、高互动、低退货?" } ,
] ;
const createStepOneRows = ( ) => STEP _ONE _FACTOR _ROWS . map ( ( row ) => ( {
... row ,
@ -189,8 +208,11 @@ const createStepOneRows = () => STEP_ONE_FACTOR_ROWS.map((row) => ({
failedAnalysis : "" ,
} ) ) ;
const createStepTwoRows = ( ) => STEP _TWO _FACTOR _ROWS . map ( ( row ) => ( { ... row , successAnalysis : "" , failedAnalysis : "" } ) ) ;
const createStepThreeRows = ( ) => STEP _THREE _FACTOR _ROWS . map ( ( row ) => ( { ... row , successAnalysis : "" , failedAnalysis : "" } ) ) ;
const stepOneRows = ref ( createStepOneRows ( ) ) ;
const stepTwoRows = ref ( createStepTwoRows ( ) ) ;
const stepThreeRows = ref ( createStepThreeRows ( ) ) ;
const stepFourForm = ref ( { successFactors : "" , failedFactors : "" } ) ;
const progressItems = [
{ text : "进行中:成功/失败产品对比" , status : "doing" } ,
@ -230,6 +252,8 @@ async function loadSavedAnswer() {
clearDraft ( ) ;
}
if ( answer ? . step2Answer ) stepTwoRows . value = restoreRows ( answer . step2Answer , createStepTwoRows ) ;
if ( answer ? . step3Answer ) stepThreeRows . value = restoreRows ( answer . step3Answer , createStepThreeRows ) ;
if ( answer ? . step4Answer ) stepFourForm . value = { ... stepFourForm . value , ... parseSavedAnswer ( answer . step4Answer ) } ;
restoreCurrentStep ( answer ? . currentStep ) ;
} catch ( error ) {
/ / K e e p l o c a l d r a f t w h e n t h e b a c k e n d a n s w e r c a n n o t b e l o a d e d .
@ -310,6 +334,8 @@ function loadDraft() {
if ( draft ? . stepOne ) stepOneRows . value = restoreRows ( draft . stepOne , createStepOneRows ) ;
else stepOneRows . value = restoreRows ( raw , createStepOneRows ) ;
if ( draft ? . stepTwo ) stepTwoRows . value = restoreRows ( draft . stepTwo , createStepTwoRows ) ;
if ( draft ? . stepThree ) stepThreeRows . value = restoreRows ( draft . stepThree , createStepThreeRows ) ;
if ( draft ? . stepFour ) stepFourForm . value = { ... stepFourForm . value , ... draft . stepFour } ;
}
} catch ( error ) {
clearDraft ( ) ;
@ -336,7 +362,9 @@ function buildStepOneOutcome() {
} ;
}
function buildStepTwoOutcome ( ) { return { title : taskTitle . value , factors : stepTwoRows . value . map ( ( row ) => ( { dimension : row . dimension , criteria : row . criteria , successAnalysis : row . successAnalysis , failedAnalysis : row . failedAnalysis } ) ) } ; }
function buildDraft ( ) { return { stepOne : buildStepOneOutcome ( ) , stepTwo : buildStepTwoOutcome ( ) , currentStep : currentStep . value + 1 } ; }
function buildStepThreeOutcome ( ) { return { title : taskTitle . value , factors : stepThreeRows . value . map ( ( row ) => ( { dimension : row . dimension , criteria : row . criteria , successAnalysis : row . successAnalysis , failedAnalysis : row . failedAnalysis } ) ) } ; }
function buildStepFourOutcome ( ) { return { successFactors : stepFourForm . value . successFactors , failedFactors : stepFourForm . value . failedFactors } ; }
function buildDraft ( ) { return { stepOne : buildStepOneOutcome ( ) , stepTwo : buildStepTwoOutcome ( ) , stepThree : buildStepThreeOutcome ( ) , stepFour : buildStepFourOutcome ( ) , currentStep : currentStep . value + 1 } ; }
function buildStepOneValidationPayload ( ) {
return {
@ -358,6 +386,10 @@ function buildStepOneAnswerPayload(saveAction = "SAVE", persistedStep = currentS
}
function buildStepTwoValidationPayload ( ) { return { factors : stepTwoRows . value . map ( ( { dimension , successAnalysis , failedAnalysis } ) => ( { dimension , successAnalysis , failedAnalysis } ) ) } ; }
function buildStepTwoAnswerPayload ( saveAction = "SAVE" , persistedStep = currentStep . value + 1 ) { return { step2Answer : JSON . stringify ( buildStepTwoOutcome ( ) ) , currentStep : persistedStep , submitted : false , saveAction } ; }
function buildStepThreeValidationPayload ( ) { return { factors : stepThreeRows . value . map ( ( { dimension , successAnalysis , failedAnalysis } ) => ( { dimension , successAnalysis , failedAnalysis } ) ) } ; }
function buildStepThreeAnswerPayload ( saveAction = "SAVE" , persistedStep = currentStep . value + 1 ) { return { step3Answer : JSON . stringify ( buildStepThreeOutcome ( ) ) , currentStep : persistedStep , submitted : false , saveAction } ; }
function buildStepFourValidationPayload ( ) { return buildStepFourOutcome ( ) ; }
function buildStepFourAnswerPayload ( saveAction = "SUBMIT" , persistedStep = 4 ) { return { step4Answer : JSON . stringify ( buildStepFourOutcome ( ) ) , currentStep : persistedStep , submitted : true , saveAction } ; }
async function saveAndGoToStepTwo ( ) {
if ( saving . value ) return ;
@ -392,9 +424,25 @@ async function saveAndGoToStepThree() {
} catch ( error ) { proxy ? . $modal ? . msgError ? . ( error ? . message || "请完成技术应用和合规与认证分析" ) ; } finally { saving . value = false ; }
}
async function saveAndGoToStepFour ( ) {
if ( saving . value ) return ;
saving . value = true ;
try {
await checkProductDevelopmentFactorsStepThree ( buildStepThreeValidationPayload ( ) ) ;
await saveStudentTrainingAnswer ( TASK _KEY , buildStepThreeAnswerPayload ( "SAVE" , 4 ) ) ;
clearDraft ( ) ;
if ( trainingSteps . value . length < 4 ) { proxy ? . $modal ? . msgSuccess ( "已保存,当前任务尚未配置第 4 步" ) ; return ; }
currentStep . value = 3 ;
proxy ? . $modal ? . msgSuccess ( "已保存,已进入第 4 步" ) ;
} catch ( error ) { proxy ? . $modal ? . msgError ? . ( error ? . message || "请完成供应链与成本控制、商业模式和市场反馈分析" ) ; } finally { saving . value = false ; }
}
async function submitTraining ( ) { if ( saving . value ) return ; saving . value = true ; try { await checkProductDevelopmentFactorsStepFour ( buildStepFourValidationPayload ( ) ) ; await saveStudentTrainingAnswer ( TASK _KEY , buildStepFourAnswerPayload ( "SUBMIT" , 4 ) ) ; clearDraft ( ) ; proxy ? . $modal ? . msgSuccess ( "任务提交成功" ) ; } catch ( error ) { proxy ? . $modal ? . msgError ? . ( error ? . message || "请完成关键因素分析" ) ; } finally { saving . value = false ; } }
async function resetTraining ( ) {
stepOneRows . value = createStepOneRows ( ) ;
stepTwoRows . value = createStepTwoRows ( ) ;
stepThreeRows . value = createStepThreeRows ( ) ;
stepFourForm . value = { successFactors : "" , failedFactors : "" } ;
currentStep . value = 0 ;
clearDraft ( ) ;
try {