|
|
@@ -1,171 +1,442 @@
|
|
|
<template>
|
|
|
- <div>
|
|
|
- <el-form :model="form" ref="form" label-width="100px" class="demo-ruleForm" label-position="top">
|
|
|
-
|
|
|
- <el-col :span="24">
|
|
|
- <el-form-item label="G(目标导向):" class="cust-label">
|
|
|
- <div v-html="question.gOriented" style="font-weight: 700;font-size: 16px;"></div>
|
|
|
- </el-form-item>
|
|
|
- </el-col>
|
|
|
-
|
|
|
- <el-steps :active="active" finish-status="success" simple style="margin-top: 20px">
|
|
|
- <el-step>
|
|
|
- <div slot="title" style="border-radius: 10px;">
|
|
|
- <div style="display: flex;flex-direction: row;justify-content: center;align-items: center;">
|
|
|
- <span>P</span>
|
|
|
- <span>(问题定义)</span>
|
|
|
- </div>
|
|
|
+ <div class="gpsren-container">
|
|
|
+ <el-form :model="form" ref="form" class="gpsren-form">
|
|
|
+ <!-- 目标导向卡片 -->
|
|
|
+ <div class="goal-card">
|
|
|
+ <div class="goal-header">
|
|
|
+ <i class="el-icon-aim"></i>
|
|
|
+ <span class="goal-title">学习目标</span>
|
|
|
+ </div>
|
|
|
+ <div class="goal-content" v-html="question.gOriented"></div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 进度步骤条 -->
|
|
|
+ <div class="steps-wrapper">
|
|
|
+ <div class="steps-header">
|
|
|
+ <div class="progress-info">
|
|
|
+ <span class="current-step">当前步骤:{{['P - 问题定义', 'S - 系统拆解', 'R - 结果整合', 'E - 结果评估', 'N - 总结新知识'][active]}}</span>
|
|
|
+ <span class="progress-text">{{active + 1}}/5</span>
|
|
|
</div>
|
|
|
- </el-step>
|
|
|
- <el-step>
|
|
|
- <div slot="title" style="border-radius: 10px;">
|
|
|
- <div style="display: flex;flex-direction: row;justify-content: center;align-items: center;">
|
|
|
- <span>S</span>
|
|
|
- <span>(系统拆解)</span>
|
|
|
- </div>
|
|
|
+ <div class="score-summary" v-if="active < 4">
|
|
|
+ <span class="label">已获得分数:</span>
|
|
|
+ <span class="value">{{totalScore}}</span>
|
|
|
+ <span class="total">/{{totalMaxScore}}</span>
|
|
|
</div>
|
|
|
- </el-step>
|
|
|
- <el-step>
|
|
|
- <div slot="title" style="border-radius: 10px;">
|
|
|
- <div style="display: flex;flex-direction: row;justify-content: center;align-items: center;">
|
|
|
- <span>R</span>
|
|
|
- <span>(结果整合)</span>
|
|
|
+ </div>
|
|
|
+ <el-steps :active="active" finish-status="success" align-center class="custom-steps">
|
|
|
+ <el-step>
|
|
|
+ <div slot="title" class="step-title">
|
|
|
+ <div class="step-badge" :class="{'active': active === 0, 'finished': active > 0}">P</div>
|
|
|
+ <span class="step-name">问题定义</span>
|
|
|
+ <div class="step-score" v-if="saveForm.pScore !== undefined">
|
|
|
+ {{saveForm.pScore}}/{{stepscore.P}}
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- </div>
|
|
|
- </el-step>
|
|
|
- <el-step>
|
|
|
- <div slot="title" style="border-radius: 10px;">
|
|
|
- <div style="display: flex;flex-direction: row;justify-content: center;align-items: center;">
|
|
|
- <span>E</span>
|
|
|
- <span>(结果评估)</span>
|
|
|
+ </el-step>
|
|
|
+ <el-step>
|
|
|
+ <div slot="title" class="step-title">
|
|
|
+ <div class="step-badge" :class="{'active': active === 1, 'finished': active > 1}">S</div>
|
|
|
+ <span class="step-name">系统拆解</span>
|
|
|
+ <div class="step-score" v-if="saveForm.sScore !== undefined">
|
|
|
+ {{saveForm.sScore}}/{{stepscore.S}}
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- </div>
|
|
|
- </el-step>
|
|
|
- <el-step>
|
|
|
- <div slot="title" style="border-radius: 10px;">
|
|
|
- <div style="display: flex;flex-direction: row;justify-content: center;align-items: center;">
|
|
|
- <span>N</span>
|
|
|
- <span>(总结新知识)</span>
|
|
|
+ </el-step>
|
|
|
+ <el-step>
|
|
|
+ <div slot="title" class="step-title">
|
|
|
+ <div class="step-badge" :class="{'active': active === 2, 'finished': active > 2}">R</div>
|
|
|
+ <span class="step-name">结果整合</span>
|
|
|
+ <div class="step-score" v-if="saveForm.rScore !== undefined">
|
|
|
+ {{saveForm.rScore}}/{{stepscore.R}}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-step>
|
|
|
+ <el-step>
|
|
|
+ <div slot="title" class="step-title">
|
|
|
+ <div class="step-badge" :class="{'active': active === 3, 'finished': active > 3}">E</div>
|
|
|
+ <span class="step-name">结果评估</span>
|
|
|
+ <div class="step-score" v-if="saveForm.eScore !== undefined">
|
|
|
+ {{saveForm.eScore}}/{{stepscore.E}}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-step>
|
|
|
+ <el-step>
|
|
|
+ <div slot="title" class="step-title">
|
|
|
+ <div class="step-badge" :class="{'active': active === 4}">N</div>
|
|
|
+ <span class="step-name">总结新知识</span>
|
|
|
+ </div>
|
|
|
+ </el-step>
|
|
|
+ </el-steps>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 答题区域 -->
|
|
|
+ <div class="answer-section">
|
|
|
+ <!-- P阶段 -->
|
|
|
+ <div class="answer-card" v-if="active==0">
|
|
|
+ <div class="answer-header">
|
|
|
+ <div class="answer-title">
|
|
|
+ <span class="phase-badge phase-p">P</span>
|
|
|
+ <div class="title-content">
|
|
|
+ <span class="main-title">问题定义 Problem</span>
|
|
|
+ <span class="sub-title">准确描述问题,明确目标与需求</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="score-display" v-if="saveForm.pScore !== undefined">
|
|
|
+ <div class="score-content">
|
|
|
+ <span class="score-value">{{saveForm.pScore}}</span>
|
|
|
+ <span class="score-divider">/</span>
|
|
|
+ <span class="score-total">{{stepscore.P}}</span>
|
|
|
+ </div>
|
|
|
+ <span class="score-label">分</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
- </el-step>
|
|
|
- </el-steps>
|
|
|
- <!-- <div>
|
|
|
- <el-button icon="el-icon-discover" size="small" type="success">AI助手</el-button>
|
|
|
- </div> -->
|
|
|
- <br />
|
|
|
- <el-col :span="24" >
|
|
|
- <div class="test-area" v-if="active==0">
|
|
|
- <el-form-item class="test-form cust-label">
|
|
|
-
|
|
|
- <el-input type="textarea" class="custom-height" v-model="form.p" :placeholder="stepmodel.P"></el-input>
|
|
|
- </el-form-item>
|
|
|
- <div class="test-form ai-evaluate">
|
|
|
- <div v-if="showAIEvaluate"><i class="el-icon-loading"></i></div>
|
|
|
- <div v-else >
|
|
|
- <p v-html="resp"></p>
|
|
|
+ <div class="answer-content">
|
|
|
+ <div class="input-area">
|
|
|
+ <div class="input-header">
|
|
|
+ <span class="input-label">你的答案</span>
|
|
|
+ <span class="char-count">{{form.p ? form.p.length : 0}} 字</span>
|
|
|
+ </div>
|
|
|
+ <el-input
|
|
|
+ type="textarea"
|
|
|
+ v-model="form.p"
|
|
|
+ :placeholder="stepmodel.P"
|
|
|
+ :autosize="{ minRows: 12, maxRows: 20 }"
|
|
|
+ class="answer-textarea">
|
|
|
+ </el-input>
|
|
|
+ </div>
|
|
|
+ <div class="ai-feedback-area">
|
|
|
+ <div class="feedback-header">
|
|
|
+ <div class="header-left">
|
|
|
+ <i class="el-icon-chat-dot-round"></i>
|
|
|
+ <span>AI 智能评估</span>
|
|
|
+ </div>
|
|
|
+ <el-tag v-if="saveForm.pScore !== undefined" size="small" :type="getScoreType(saveForm.pScore, stepscore.P)">
|
|
|
+ {{getScoreLevel(saveForm.pScore, stepscore.P)}}
|
|
|
+ </el-tag>
|
|
|
+ </div>
|
|
|
+ <div class="feedback-content">
|
|
|
+ <div v-if="showAIEvaluate" class="loading-state">
|
|
|
+ <div class="loading-animation">
|
|
|
+ <i class="el-icon-loading"></i>
|
|
|
+ </div>
|
|
|
+ <span>AI正在分析您的答案,请稍候...</span>
|
|
|
+ </div>
|
|
|
+ <div v-else-if="!aiResponseContent.P" class="empty-state">
|
|
|
+ <i class="el-icon-info"></i>
|
|
|
+ <span>点击"提交AI测评"按钮获取智能评估反馈</span>
|
|
|
+ </div>
|
|
|
+ <div ref="aiResponseP" class="ai-response" v-html="aiResponseContent.P"></div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
- <div class="test-area" v-if="active==1">
|
|
|
- <el-form-item class="test-form cust-label">
|
|
|
- <el-input type="textarea" class="custom-height" v-model="form.s" :placeholder="stepmodel.S"></el-input>
|
|
|
- </el-form-item>
|
|
|
- <div class="test-form ai-evaluate">
|
|
|
- <div v-if="showAIEvaluate"><i class="el-icon-loading"></i></div>
|
|
|
- <div v-else >
|
|
|
- <p v-html="resp"></p>
|
|
|
+ <!-- S阶段 -->
|
|
|
+ <div class="answer-card" v-if="active==1">
|
|
|
+ <div class="answer-header">
|
|
|
+ <div class="answer-title">
|
|
|
+ <span class="phase-badge phase-s">S</span>
|
|
|
+ <div class="title-content">
|
|
|
+ <span class="main-title">系统拆解 Systematic</span>
|
|
|
+ <span class="sub-title">将复杂问题分解为可管理的子问题</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="score-display" v-if="saveForm.sScore !== undefined">
|
|
|
+ <div class="score-content">
|
|
|
+ <span class="score-value">{{saveForm.sScore}}</span>
|
|
|
+ <span class="score-divider">/</span>
|
|
|
+ <span class="score-total">{{stepscore.S}}</span>
|
|
|
+ </div>
|
|
|
+ <span class="score-label">分</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <div class="test-area" v-if="active==2">
|
|
|
- <el-form-item class="test-form cust-label">
|
|
|
- <el-input type="textarea" class="custom-height" v-model="form.r" :placeholder="stepmodel.R"></el-input>
|
|
|
- </el-form-item>
|
|
|
- <div class="test-form ai-evaluate">
|
|
|
- <div v-if="showAIEvaluate"><i class="el-icon-loading"></i></div>
|
|
|
- <div v-else >
|
|
|
- <p v-html="resp"></p>
|
|
|
+ <div class="answer-content">
|
|
|
+ <div class="input-area">
|
|
|
+ <div class="input-header">
|
|
|
+ <span class="input-label">你的答案</span>
|
|
|
+ <span class="char-count">{{form.s ? form.s.length : 0}} 字</span>
|
|
|
+ </div>
|
|
|
+ <el-input
|
|
|
+ type="textarea"
|
|
|
+ v-model="form.s"
|
|
|
+ :placeholder="stepmodel.S"
|
|
|
+ :autosize="{ minRows: 12, maxRows: 20 }"
|
|
|
+ class="answer-textarea">
|
|
|
+ </el-input>
|
|
|
+ </div>
|
|
|
+ <div class="ai-feedback-area">
|
|
|
+ <div class="feedback-header">
|
|
|
+ <div class="header-left">
|
|
|
+ <i class="el-icon-chat-dot-round"></i>
|
|
|
+ <span>AI 智能评估</span>
|
|
|
+ </div>
|
|
|
+ <el-tag v-if="saveForm.sScore !== undefined" size="small" :type="getScoreType(saveForm.sScore, stepscore.S)">
|
|
|
+ {{getScoreLevel(saveForm.sScore, stepscore.S)}}
|
|
|
+ </el-tag>
|
|
|
+ </div>
|
|
|
+ <div class="feedback-content">
|
|
|
+ <div v-if="showAIEvaluate" class="loading-state">
|
|
|
+ <div class="loading-animation">
|
|
|
+ <i class="el-icon-loading"></i>
|
|
|
+ </div>
|
|
|
+ <span>AI正在分析您的答案,请稍候...</span>
|
|
|
+ </div>
|
|
|
+ <div v-else-if="!aiResponseContent.S" class="empty-state">
|
|
|
+ <i class="el-icon-info"></i>
|
|
|
+ <span>点击"提交AI测评"按钮获取智能评估反馈</span>
|
|
|
+ </div>
|
|
|
+ <div ref="aiResponseS" class="ai-response" v-html="aiResponseContent.S"></div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
- <div class="test-area" v-if="active==3">
|
|
|
- <el-form-item class="test-form cust-label">
|
|
|
- <el-input type="textarea" class="custom-height" v-model="form.e" :placeholder="stepmodel.E"></el-input>
|
|
|
- </el-form-item>
|
|
|
- <div class="test-form ai-evaluate">
|
|
|
- <div v-if="showAIEvaluate"><i class="el-icon-loading"></i></div>
|
|
|
- <div v-else >
|
|
|
- <p v-html="resp"></p>
|
|
|
+ <!-- R阶段 -->
|
|
|
+ <div class="answer-card" v-if="active==2">
|
|
|
+ <div class="answer-header">
|
|
|
+ <div class="answer-title">
|
|
|
+ <span class="phase-badge phase-r">R</span>
|
|
|
+ <div class="title-content">
|
|
|
+ <span class="main-title">结果整合 Result</span>
|
|
|
+ <span class="sub-title">整合各部分解决方案,形成完整答案</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="score-display" v-if="saveForm.rScore !== undefined">
|
|
|
+ <div class="score-content">
|
|
|
+ <span class="score-value">{{saveForm.rScore}}</span>
|
|
|
+ <span class="score-divider">/</span>
|
|
|
+ <span class="score-total">{{stepscore.R}}</span>
|
|
|
+ </div>
|
|
|
+ <span class="score-label">分</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
- </div>
|
|
|
-
|
|
|
- <div class="test-area" v-if="active==4">
|
|
|
- <el-form-item class="test-form cust-label" style="width:100%;">
|
|
|
- <el-input type="textarea" class="custom-height" v-model="form.n" :placeholder="stepmodel.N"></el-input>
|
|
|
- </el-form-item>
|
|
|
- <!-- <div class="test-form ai-evaluate">
|
|
|
- <div v-if="showAIEvaluate"><i class="el-icon-loading"></i></div>
|
|
|
- <div v-else >
|
|
|
- <p v-html="resp"></p>
|
|
|
+ <div class="answer-content">
|
|
|
+ <div class="input-area">
|
|
|
+ <div class="input-header">
|
|
|
+ <span class="input-label">你的答案</span>
|
|
|
+ <span class="char-count">{{form.r ? form.r.length : 0}} 字</span>
|
|
|
+ </div>
|
|
|
+ <el-input
|
|
|
+ type="textarea"
|
|
|
+ v-model="form.r"
|
|
|
+ :placeholder="stepmodel.R"
|
|
|
+ :autosize="{ minRows: 12, maxRows: 20 }"
|
|
|
+ class="answer-textarea">
|
|
|
+ </el-input>
|
|
|
+ </div>
|
|
|
+ <div class="ai-feedback-area">
|
|
|
+ <div class="feedback-header">
|
|
|
+ <div class="header-left">
|
|
|
+ <i class="el-icon-chat-dot-round"></i>
|
|
|
+ <span>AI 智能评估</span>
|
|
|
+ </div>
|
|
|
+ <el-tag v-if="saveForm.rScore !== undefined" size="small" :type="getScoreType(saveForm.rScore, stepscore.R)">
|
|
|
+ {{getScoreLevel(saveForm.rScore, stepscore.R)}}
|
|
|
+ </el-tag>
|
|
|
+ </div>
|
|
|
+ <div class="feedback-content">
|
|
|
+ <div v-if="showAIEvaluate" class="loading-state">
|
|
|
+ <div class="loading-animation">
|
|
|
+ <i class="el-icon-loading"></i>
|
|
|
+ </div>
|
|
|
+ <span>AI正在分析您的答案,请稍候...</span>
|
|
|
+ </div>
|
|
|
+ <div v-else-if="!aiResponseContent.R" class="empty-state">
|
|
|
+ <i class="el-icon-info"></i>
|
|
|
+ <span>点击"提交AI测评"按钮获取智能评估反馈</span>
|
|
|
+ </div>
|
|
|
+ <div ref="aiResponseR" class="ai-response" v-html="aiResponseContent.R"></div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- </div> -->
|
|
|
+ </div>
|
|
|
</div>
|
|
|
|
|
|
- <div class="opt-area" v-if="active <4">
|
|
|
- <div class="opt-left">
|
|
|
- <el-button :disabled="showAIEvaluate" :icon="showAIEvaluate?'el-icon-loading':'el-icon-arrow-right'" style="width: 100%;" size="small" type="primary" plain @click="onAIEvaluate">提交AI测评</el-button>
|
|
|
+ <!-- E阶段 -->
|
|
|
+ <div class="answer-card" v-if="active==3">
|
|
|
+ <div class="answer-header">
|
|
|
+ <div class="answer-title">
|
|
|
+ <span class="phase-badge phase-e">E</span>
|
|
|
+ <div class="title-content">
|
|
|
+ <span class="main-title">结果评估 Evaluation</span>
|
|
|
+ <span class="sub-title">验证解决方案的正确性与完整性</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="score-display" v-if="saveForm.eScore !== undefined">
|
|
|
+ <div class="score-content">
|
|
|
+ <span class="score-value">{{saveForm.eScore}}</span>
|
|
|
+ <span class="score-divider">/</span>
|
|
|
+ <span class="score-total">{{stepscore.E}}</span>
|
|
|
+ </div>
|
|
|
+ <span class="score-label">分</span>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- <div class="opt-left">
|
|
|
- <el-button :disabled="showAIEvaluate" icon="el-icon-check" v-if="active<4" style="width: 100%;" size="small" type="success" plain @click="onNext">下一步</el-button>
|
|
|
+ <div class="answer-content">
|
|
|
+ <div class="input-area">
|
|
|
+ <div class="input-header">
|
|
|
+ <span class="input-label">你的答案</span>
|
|
|
+ <span class="char-count">{{form.e ? form.e.length : 0}} 字</span>
|
|
|
+ </div>
|
|
|
+ <el-input
|
|
|
+ type="textarea"
|
|
|
+ v-model="form.e"
|
|
|
+ :placeholder="stepmodel.E"
|
|
|
+ :autosize="{ minRows: 12, maxRows: 20 }"
|
|
|
+ class="answer-textarea">
|
|
|
+ </el-input>
|
|
|
+ </div>
|
|
|
+ <div class="ai-feedback-area">
|
|
|
+ <div class="feedback-header">
|
|
|
+ <div class="header-left">
|
|
|
+ <i class="el-icon-chat-dot-round"></i>
|
|
|
+ <span>AI 智能评估</span>
|
|
|
+ </div>
|
|
|
+ <el-tag v-if="saveForm.eScore !== undefined" size="small" :type="getScoreType(saveForm.eScore, stepscore.E)">
|
|
|
+ {{getScoreLevel(saveForm.eScore, stepscore.E)}}
|
|
|
+ </el-tag>
|
|
|
+ </div>
|
|
|
+ <div class="feedback-content">
|
|
|
+ <div v-if="showAIEvaluate" class="loading-state">
|
|
|
+ <div class="loading-animation">
|
|
|
+ <i class="el-icon-loading"></i>
|
|
|
+ </div>
|
|
|
+ <span>AI正在分析您的答案,请稍候...</span>
|
|
|
+ </div>
|
|
|
+ <div v-else-if="!aiResponseContent.E" class="empty-state">
|
|
|
+ <i class="el-icon-info"></i>
|
|
|
+ <span>点击"提交AI测评"按钮获取智能评估反馈</span>
|
|
|
+ </div>
|
|
|
+ <div ref="aiResponseE" class="ai-response" v-html="aiResponseContent.E"></div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
- <div v-else class="opt-area" >
|
|
|
- <el-button :disabled="showAIEvaluate" icon="el-icon-check" style="width: 100%;" size="small" type="success" plain @click="onFinish">完成</el-button>
|
|
|
- </div>
|
|
|
- </el-col>
|
|
|
-
|
|
|
- </el-form>
|
|
|
|
|
|
-
|
|
|
-
|
|
|
- <!-- <template>
|
|
|
- <el-dialog :visible.sync="dialogResultVisible" width="50%" top="0" custom-class="GPSREN" :modal="false"
|
|
|
- :modal-append-to-body="false">
|
|
|
- <div slot="title" class="cust-title">
|
|
|
- AI评价 <i :class="aiTestClass"></i>
|
|
|
+ <!-- N阶段 -->
|
|
|
+ <div class="answer-card summary-card" v-if="active==4">
|
|
|
+ <div class="answer-header">
|
|
|
+ <div class="answer-title">
|
|
|
+ <span class="phase-badge phase-n">N</span>
|
|
|
+ <div class="title-content">
|
|
|
+ <span class="main-title">总结新知识 New Knowledge</span>
|
|
|
+ <span class="sub-title">反思学习过程,提炼关键知识点</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="total-score">
|
|
|
+ <div class="total-content">
|
|
|
+ <span class="total-label">总分</span>
|
|
|
+ <div class="total-value-wrapper">
|
|
|
+ <span class="total-value">{{totalScore}}</span>
|
|
|
+ <span class="total-divider">/</span>
|
|
|
+ <span class="total-max">{{totalMaxScore}}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="answer-content single-column">
|
|
|
+ <div class="input-area">
|
|
|
+ <div class="input-header">
|
|
|
+ <span class="input-label">你的总结</span>
|
|
|
+ <span class="char-count">{{form.n ? form.n.length : 0}} 字</span>
|
|
|
+ </div>
|
|
|
+ <el-input
|
|
|
+ type="textarea"
|
|
|
+ v-model="form.n"
|
|
|
+ :placeholder="stepmodel.N"
|
|
|
+ :autosize="{ minRows: 15, maxRows: 25 }"
|
|
|
+ class="answer-textarea">
|
|
|
+ </el-input>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
|
|
|
- <div class="block">
|
|
|
- <div v-html="resp"></div>
|
|
|
+ <!-- 操作按钮 -->
|
|
|
+ <div class="action-buttons">
|
|
|
+ <template v-if="active < 4">
|
|
|
+ <div class="button-group">
|
|
|
+ <el-button
|
|
|
+ v-if="active > 0"
|
|
|
+ type="info"
|
|
|
+ size="medium"
|
|
|
+ @click="onPrev"
|
|
|
+ class="action-btn">
|
|
|
+ <i class="el-icon-left"></i>
|
|
|
+ 上一步
|
|
|
+ </el-button>
|
|
|
+ <el-button
|
|
|
+ :disabled="showAIEvaluate"
|
|
|
+ :loading="showAIEvaluate"
|
|
|
+ type="primary"
|
|
|
+ size="medium"
|
|
|
+ @click="onAIEvaluate"
|
|
|
+ class="action-btn primary-btn">
|
|
|
+ <i class="el-icon-cpu" v-if="!showAIEvaluate"></i>
|
|
|
+ {{showAIEvaluate ? 'AI评估中...' : '提交AI测评'}}
|
|
|
+ </el-button>
|
|
|
+ <el-button
|
|
|
+ :disabled="showAIEvaluate"
|
|
|
+ type="success"
|
|
|
+ size="medium"
|
|
|
+ @click="onNext"
|
|
|
+ class="action-btn success-btn">
|
|
|
+ 下一步
|
|
|
+ <i class="el-icon-right"></i>
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
+ <div class="tips-text">
|
|
|
+ <i class="el-icon-info"></i>
|
|
|
+ 建议先提交AI测评获取反馈后再进入下一步
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <template v-else>
|
|
|
+ <div class="finish-section">
|
|
|
+ <div class="finish-summary">
|
|
|
+ <div class="summary-item">
|
|
|
+ <span class="label">完成步骤</span>
|
|
|
+ <span class="value">4/4</span>
|
|
|
+ </div>
|
|
|
+ <div class="summary-item">
|
|
|
+ <span class="label">总得分</span>
|
|
|
+ <span class="value highlight">{{totalScore}}/{{totalMaxScore}}</span>
|
|
|
+ </div>
|
|
|
+ <div class="summary-item">
|
|
|
+ <span class="label">得分率</span>
|
|
|
+ <span class="value">{{totalMaxScore > 0 ? Math.round((totalScore/totalMaxScore)*100) : 0}}%</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="button-group">
|
|
|
+ <el-button
|
|
|
+ type="info"
|
|
|
+ size="medium"
|
|
|
+ @click="onPrev"
|
|
|
+ class="action-btn">
|
|
|
+ <i class="el-icon-left"></i>
|
|
|
+ 上一步
|
|
|
+ </el-button>
|
|
|
+ <el-button
|
|
|
+ :disabled="showAIEvaluate"
|
|
|
+ type="success"
|
|
|
+ size="large"
|
|
|
+ @click="onFinish"
|
|
|
+ class="action-btn finish-btn">
|
|
|
+ <i class="el-icon-circle-check"></i>
|
|
|
+ 提交并完成学习
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
</div>
|
|
|
-
|
|
|
- <span slot="footer" class="dialog-footer" v-if="aiTestClass=='el-icon-reading'">
|
|
|
- <el-button icon="el-icon-arrow-right" size="small" type="primary" plain v-if="active<4"
|
|
|
- @click="()=>{active++;dialogResultVisible = false;}">AI评测</el-button>
|
|
|
- <el-button type="primary" @click="()=>{dialogResultVisible = false;dialogVisible = false}"
|
|
|
- size="small" v-else-if="active==4">提交</el-button>
|
|
|
- <el-button @click="dialogResultVisible = false" size="small">修改</el-button>
|
|
|
- <el-button @click="()=>{dialogResultVisible = false; active=0;}" size="small">重新答题</el-button>
|
|
|
- </span>
|
|
|
- </el-dialog>
|
|
|
- </template> -->
|
|
|
+ </div>
|
|
|
+ </el-form>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
import Axios from 'axios';
|
|
|
import { getDictValueByType } from '../api/dict'
|
|
|
-
|
|
|
import { mockAI, steps ,tips} from '../mock/gpsren';
|
|
|
+import {askAI, postGPSREN, getStepModel, getGpsrenSession} from '../api/ai'
|
|
|
|
|
|
-import {askAI,postGPSREN,getStepModel} from '../api/ai'
|
|
|
let thisPage = null
|
|
|
-
|
|
|
let stepMapToCnt = {}
|
|
|
|
|
|
export default {
|
|
|
@@ -193,7 +464,16 @@ export default {
|
|
|
uploadAction: this.$httpApi.httpUrl('/api/upload/2'),
|
|
|
dialogVisible: false,
|
|
|
form: {},
|
|
|
- saveForm:{},
|
|
|
+ saveForm:{
|
|
|
+ pScore: undefined,
|
|
|
+ sScore: undefined,
|
|
|
+ rScore: undefined,
|
|
|
+ eScore: undefined,
|
|
|
+ pAnswer: '',
|
|
|
+ sAnswer: '',
|
|
|
+ rAnswer: '',
|
|
|
+ eAnswer: ''
|
|
|
+ },
|
|
|
config: {
|
|
|
zIndex: 0
|
|
|
},
|
|
|
@@ -202,18 +482,26 @@ export default {
|
|
|
aiTestItem: [],
|
|
|
aiTestClass: "el-icon-reading",
|
|
|
resp:'',
|
|
|
+ aiResponseContent: {
|
|
|
+ P: '',
|
|
|
+ S: '',
|
|
|
+ R: '',
|
|
|
+ E: ''
|
|
|
+ },
|
|
|
stepmodel: {
|
|
|
- "P": "",
|
|
|
- "S":"",
|
|
|
- "R":"",
|
|
|
- "E":""
|
|
|
- },
|
|
|
+ "P": "",
|
|
|
+ "S":"",
|
|
|
+ "R":"",
|
|
|
+ "E":"",
|
|
|
+ "N":""
|
|
|
+ },
|
|
|
stepscore: {
|
|
|
- "P": 0,
|
|
|
- "S":0,
|
|
|
- "R":0,
|
|
|
- "E":0
|
|
|
- },
|
|
|
+ "P": 0,
|
|
|
+ "S":0,
|
|
|
+ "R":0,
|
|
|
+ "E":0
|
|
|
+ },
|
|
|
+ abortController: null
|
|
|
}
|
|
|
},
|
|
|
|
|
|
@@ -233,17 +521,14 @@ export default {
|
|
|
"P":"",
|
|
|
"S":"",
|
|
|
"R":"",
|
|
|
- "E":""
|
|
|
- }
|
|
|
- console.log("this.stepmodel===> ",this.stepmodel)
|
|
|
+ "E":"",
|
|
|
+ "N":""
|
|
|
+ }
|
|
|
|
|
|
- //todo
|
|
|
- getStepModel().then(resp=>{
|
|
|
- console.log(resp)
|
|
|
+ getStepModel().then(resp=>{
|
|
|
if(resp.status == 200) {
|
|
|
let res = resp.data
|
|
|
if(res.code == 1) {
|
|
|
-
|
|
|
let stepModels = res.data.dataList
|
|
|
for(let n =0 ;n<stepModels.length;n++) {
|
|
|
let m = stepModels[n]
|
|
|
@@ -252,22 +537,121 @@ export default {
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- }).finally(d=>{
|
|
|
- console.log("this.stepmodel",this.stepmodel)
|
|
|
+ }).then(() => {
|
|
|
+ // 尝试恢复之前的答题进度
|
|
|
+ const studentId = JSON.parse(localStorage.getItem('userInfo')).id
|
|
|
+ const goalId = this.$props.question.id
|
|
|
+ return getGpsrenSession(goalId, studentId).then(resp => {
|
|
|
+ if (resp.status === 200 && resp.data.code === 1 && resp.data.data) {
|
|
|
+ this.restoreSession(resp.data.data)
|
|
|
+ }
|
|
|
+ }).catch(() => {
|
|
|
+ // 读取失败不影响正常答题
|
|
|
+ })
|
|
|
+ }).finally(() => {
|
|
|
loading.close()
|
|
|
})
|
|
|
})
|
|
|
-
|
|
|
},
|
|
|
|
|
|
+ computed: {
|
|
|
+ totalScore() {
|
|
|
+ let total = 0
|
|
|
+ console.log('计算总分 - saveForm:', JSON.stringify(this.saveForm));
|
|
|
+ if (this.saveForm.pScore !== undefined) {
|
|
|
+ total += this.saveForm.pScore
|
|
|
+ console.log('P分数:', this.saveForm.pScore);
|
|
|
+ }
|
|
|
+ if (this.saveForm.sScore !== undefined) {
|
|
|
+ total += this.saveForm.sScore
|
|
|
+ console.log('S分数:', this.saveForm.sScore);
|
|
|
+ }
|
|
|
+ if (this.saveForm.rScore !== undefined) {
|
|
|
+ total += this.saveForm.rScore
|
|
|
+ console.log('R分数:', this.saveForm.rScore);
|
|
|
+ }
|
|
|
+ if (this.saveForm.eScore !== undefined) {
|
|
|
+ total += this.saveForm.eScore
|
|
|
+ console.log('E分数:', this.saveForm.eScore);
|
|
|
+ }
|
|
|
+ console.log('计算得出总分:', total);
|
|
|
+ return total
|
|
|
+ },
|
|
|
+ totalMaxScore() {
|
|
|
+ const maxScore = (this.stepscore.P || 0) + (this.stepscore.S || 0) +
|
|
|
+ (this.stepscore.R || 0) + (this.stepscore.E || 0);
|
|
|
+ console.log('总满分:', maxScore, 'stepscore:', JSON.stringify(this.stepscore));
|
|
|
+ return maxScore;
|
|
|
+ }
|
|
|
+ },
|
|
|
|
|
|
methods: {
|
|
|
+ // 恢复 Redis 中的答题进度
|
|
|
+ restoreSession(session) {
|
|
|
+ const stepOrder = ['P', 'S', 'R', 'E']
|
|
|
+ const steps = session.steps || {}
|
|
|
+ let lastCompletedIndex = -1
|
|
|
+
|
|
|
+ stepOrder.forEach((step, index) => {
|
|
|
+ const record = steps[step]
|
|
|
+ if (!record) return
|
|
|
+
|
|
|
+ // 恢复答案输入框
|
|
|
+ this.form[step.toLowerCase()] = record.studentAnswer || ''
|
|
|
+
|
|
|
+ // 恢复 saveForm(分数 + 答案)
|
|
|
+ const newSaveForm = { ...this.saveForm }
|
|
|
+ newSaveForm[`${step.toLowerCase()}Answer`] = record.studentAnswer || ''
|
|
|
+ if (record.score !== undefined && record.score !== null) {
|
|
|
+ newSaveForm[`${step.toLowerCase()}Score`] = record.score
|
|
|
+ }
|
|
|
+ this.saveForm = newSaveForm
|
|
|
+
|
|
|
+ // 恢复 AI 回复展示
|
|
|
+ this.aiResponseContent[step] = record.aiResponse || ''
|
|
|
+
|
|
|
+ lastCompletedIndex = index
|
|
|
+ })
|
|
|
+
|
|
|
+ // 恢复 N 阶段总结
|
|
|
+ if (steps['N'] && steps['N'].studentAnswer) {
|
|
|
+ this.form.n = steps['N'].studentAnswer
|
|
|
+ }
|
|
|
+
|
|
|
+ // 跳到最后完成阶段(停在该阶段,允许继续或回看)
|
|
|
+ if (lastCompletedIndex >= 0) {
|
|
|
+ this.active = lastCompletedIndex
|
|
|
+ this.$nextTick(() => {
|
|
|
+ const step = stepOrder[lastCompletedIndex]
|
|
|
+ const el = this.$refs[`aiResponse${step}`]
|
|
|
+ if (el) el.innerHTML = this.aiResponseContent[step]
|
|
|
+ })
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 获取分数等级
|
|
|
+ getScoreLevel(score, maxScore) {
|
|
|
+ const percentage = (score / maxScore) * 100
|
|
|
+ if (percentage >= 90) return '优秀'
|
|
|
+ if (percentage >= 80) return '良好'
|
|
|
+ if (percentage >= 70) return '中等'
|
|
|
+ if (percentage >= 60) return '及格'
|
|
|
+ return '待提高'
|
|
|
+ },
|
|
|
+
|
|
|
+ // 获取分数类型(用于tag颜色)
|
|
|
+ getScoreType(score, maxScore) {
|
|
|
+ const percentage = (score / maxScore) * 100
|
|
|
+ if (percentage >= 90) return 'success'
|
|
|
+ if (percentage >= 70) return ''
|
|
|
+ if (percentage >= 60) return 'warning'
|
|
|
+ return 'danger'
|
|
|
+ },
|
|
|
|
|
|
//提交测评
|
|
|
onAIEvaluate() {
|
|
|
let step = steps[this.active]
|
|
|
if(!!!this.form[`${step.toLowerCase()}`]) {
|
|
|
- //没有学生答案
|
|
|
this.$message({
|
|
|
type: 'warning',
|
|
|
message: '请输入答案',
|
|
|
@@ -277,63 +661,175 @@ export default {
|
|
|
}
|
|
|
this.showAIEvaluate = true
|
|
|
let run = () => {
|
|
|
- return this.remoteAskAI(this.$props.question.courseName ,
|
|
|
- step,
|
|
|
- this.$props.question.gOriented,
|
|
|
- this.$props.question[`${step.toLowerCase()}ScoreStd`] + ' '+ this.stepmodel[step],
|
|
|
- this.form[`${step.toLowerCase()}`],
|
|
|
- this.stepscore[step]
|
|
|
- )
|
|
|
+ return this.remoteAskAI(
|
|
|
+ this.$props.question.courseName,
|
|
|
+ step,
|
|
|
+ this.$props.question.gOriented,
|
|
|
+ this.$props.question[`${step.toLowerCase()}ScoreStd`] + ' '+ this.stepmodel[step],
|
|
|
+ this.form[`${step.toLowerCase()}`],
|
|
|
+ this.stepscore[step]
|
|
|
+ )
|
|
|
}
|
|
|
run().finally(f=>{ this.showAIEvaluate = false; })
|
|
|
},
|
|
|
|
|
|
- //
|
|
|
- remoteAskAI(cn, sn, g,sa,ssa,_s) {
|
|
|
- console.log(cn,sn,g,sa,ssa)
|
|
|
+ extractScoreFromHtml(content) {
|
|
|
+ const match = content.match(/\[\[SCORE:(\d+)\]\]/g);
|
|
|
+ if (match) {
|
|
|
+ // 取最后一个(末尾)
|
|
|
+ const last = match[match.length - 1];
|
|
|
+ const score = parseInt(last.match(/\[\[SCORE:(\d+)\]\]/)[1]);
|
|
|
+ console.log('提取到的分数:', score);
|
|
|
+ return score;
|
|
|
+ }
|
|
|
+ console.log('未找到分数标记,原文片段:', content.substring(0, 200));
|
|
|
+ return 0;
|
|
|
+ },
|
|
|
+
|
|
|
+ // 去掉评分标记,返回纯展示 HTML
|
|
|
+ stripScoreTag(content) {
|
|
|
+ return content.replace(/\[\[SCORE:\d+\]\]/g, '').trim();
|
|
|
+ },
|
|
|
+
|
|
|
+ async remoteAskAI(cn, sn, g, sa, ssa, _s) {
|
|
|
this.resp = ''
|
|
|
- return askAI({
|
|
|
- memoryId:1,
|
|
|
- courseName:cn,
|
|
|
- stepName:sn,
|
|
|
- goal:g,
|
|
|
- standardAnswer:sa,
|
|
|
- studentAnswer:ssa,
|
|
|
- score:_s
|
|
|
- }).then(r=>{
|
|
|
- if(r.status == 200) {
|
|
|
- let res = r.data
|
|
|
- if(res.code == 1) {
|
|
|
- console.log(res.data)
|
|
|
- try{
|
|
|
- let jData = JSON.parse(res.data)
|
|
|
- this.resp = jData.text
|
|
|
- this.score = jData.score
|
|
|
- }catch(e){
|
|
|
- console.log(e)
|
|
|
- this.resp = "AI返回值不符合格式要求"
|
|
|
+ this.score = 0
|
|
|
+ this.abortController = new AbortController()
|
|
|
+
|
|
|
+ const step = steps[this.active]
|
|
|
+ const refName = `aiResponse${step}`;
|
|
|
+ this.aiResponseContent[step] = '';
|
|
|
+
|
|
|
+ await this.$nextTick()
|
|
|
+ const el = this.$refs[refName]
|
|
|
+ if (el) {
|
|
|
+ el.innerHTML = '';
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ const requestData = {
|
|
|
+ goalId: this.$props.question.id,
|
|
|
+ studentId: JSON.parse(localStorage.getItem('userInfo')).id,
|
|
|
+ courseName: cn,
|
|
|
+ stepName: sn,
|
|
|
+ goal: g,
|
|
|
+ studentAnswer: ssa,
|
|
|
+ score: _s
|
|
|
+ }
|
|
|
+
|
|
|
+ const apiUrl = this.$httpApi.aiUrl('/api/psrenEvalution')
|
|
|
+
|
|
|
+ const response = await fetch(apiUrl, {
|
|
|
+ method: 'POST',
|
|
|
+ headers: {
|
|
|
+ 'Content-Type': 'application/json',
|
|
|
+ 'Authorization': localStorage.getItem('token'),
|
|
|
+ 'Platform': 'educationStudent'
|
|
|
+ },
|
|
|
+ body: JSON.stringify(requestData),
|
|
|
+ signal: this.abortController.signal
|
|
|
+ })
|
|
|
+
|
|
|
+ if (!response.ok) throw new Error('评估请求失败')
|
|
|
+
|
|
|
+ const reader = response.body.getReader()
|
|
|
+ const decoder = new TextDecoder()
|
|
|
+ let buffer = ''
|
|
|
+ let fullContent = ''
|
|
|
+
|
|
|
+ while (true) {
|
|
|
+ const { done, value } = await reader.read()
|
|
|
+ if (done) break
|
|
|
+
|
|
|
+ buffer += decoder.decode(value, { stream: true })
|
|
|
+
|
|
|
+ const lines = buffer.split('\n')
|
|
|
+ buffer = lines.pop() || ''
|
|
|
+
|
|
|
+ for (const line of lines) {
|
|
|
+ if (line.startsWith('data:')) {
|
|
|
+ const content = line.substring(5).trim()
|
|
|
+ if (content) {
|
|
|
+ fullContent += content
|
|
|
+ this.resp += content
|
|
|
+
|
|
|
+ // 渲染时去掉评分标记,避免显示在页面上
|
|
|
+ const displayHtml = this.stripScoreTag(fullContent);
|
|
|
+ this.aiResponseContent[step] = displayHtml;
|
|
|
+
|
|
|
+ const el = this.$refs[refName]
|
|
|
+ if (el) {
|
|
|
+ el.innerHTML = displayHtml;
|
|
|
+ await new Promise(resolve => setTimeout(resolve, 30))
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (buffer.trim() && buffer.startsWith('data:')) {
|
|
|
+ const content = buffer.substring(5).trim()
|
|
|
+ if (content) {
|
|
|
+ fullContent += content
|
|
|
+ this.resp += content
|
|
|
+ const displayHtml = this.stripScoreTag(fullContent);
|
|
|
+ this.aiResponseContent[step] = displayHtml;
|
|
|
+
|
|
|
+ const el = this.$refs[refName]
|
|
|
+ if (el) {
|
|
|
+ el.innerHTML = displayHtml;
|
|
|
}
|
|
|
- } else {
|
|
|
- this.resp = res.message
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ this.score = this.extractScoreFromHtml(fullContent);
|
|
|
+
|
|
|
+ return this.resp
|
|
|
+
|
|
|
+ } catch (error) {
|
|
|
+ if (error.name === 'AbortError') {
|
|
|
+ this.resp = '评估已取消'
|
|
|
+ this.aiResponseContent[step] = '评估已取消';
|
|
|
+ const el = this.$refs[refName]
|
|
|
+ if (el) {
|
|
|
+ el.innerHTML = '评估已取消';
|
|
|
}
|
|
|
} else {
|
|
|
- this.resp = "AI超时"
|
|
|
+ console.error('AI评估错误:', error)
|
|
|
+ this.resp = "服务故障,请重试"
|
|
|
+ this.aiResponseContent[step] = "服务故障,请重试";
|
|
|
+ const el = this.$refs[refName]
|
|
|
+ if (el) {
|
|
|
+ el.innerHTML = "服务故障,请重试";
|
|
|
+ }
|
|
|
}
|
|
|
-
|
|
|
return this.resp
|
|
|
- }).catch(c=>{
|
|
|
- this.resp = "服务故障,请重试"
|
|
|
- }).finally(()=>{
|
|
|
- //记录本地
|
|
|
- this.saveForm[`${sn.toLowerCase()}Answer`] = ssa
|
|
|
- this.saveForm[`${sn.toLowerCase()}Score`] = this.score
|
|
|
+ } finally {
|
|
|
+ // 创建新的 saveForm 对象来触发响应式更新
|
|
|
+ const newSaveForm = { ...this.saveForm }
|
|
|
+ newSaveForm[`${sn.toLowerCase()}Answer`] = ssa
|
|
|
+ newSaveForm[`${sn.toLowerCase()}Score`] = this.score
|
|
|
+ this.saveForm = newSaveForm
|
|
|
+
|
|
|
+ console.log('保存分数:', `${sn.toLowerCase()}Score`, '=', this.score);
|
|
|
+ console.log('当前saveForm:', JSON.stringify(this.saveForm));
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ onPrev() {
|
|
|
+ if (this.active <= 0) return
|
|
|
+ this.active--
|
|
|
+ this.showAIEvaluate = false
|
|
|
+ // 恢复该阶段的 AI 回复到 DOM
|
|
|
+ this.$nextTick(() => {
|
|
|
+ const step = ['P', 'S', 'R', 'E', 'N'][this.active]
|
|
|
+ const el = this.$refs[`aiResponse${step}`]
|
|
|
+ if (el) el.innerHTML = this.aiResponseContent[step] || ''
|
|
|
})
|
|
|
},
|
|
|
|
|
|
onNext() {
|
|
|
- //保存答案
|
|
|
let step = steps[this.active]
|
|
|
-
|
|
|
let a = this.saveForm[`${step.toLowerCase()}Answer`]
|
|
|
|
|
|
if(!!!a) {
|
|
|
@@ -345,255 +841,743 @@ export default {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
- //进入到下一个步骤
|
|
|
+ console.log('进入下一步前 - 当前步骤:', step, '当前saveForm:', JSON.stringify(this.saveForm));
|
|
|
this.active ++
|
|
|
+ console.log('进入下一步后 - 新步骤:', this.active, '总分应该是:', this.totalScore);
|
|
|
|
|
|
this.resp = ''
|
|
|
this.showAIEvaluate = false
|
|
|
this.score = 0
|
|
|
-
|
|
|
+
|
|
|
+ this.$nextTick(() => {
|
|
|
+ const nextStep = steps[this.active]
|
|
|
+ if (nextStep && this.aiResponseContent[nextStep] !== undefined) {
|
|
|
+ this.aiResponseContent[nextStep] = '';
|
|
|
+ }
|
|
|
+ const refName = `aiResponse${nextStep}`
|
|
|
+ const el = this.$refs[refName]
|
|
|
+ if (el) {
|
|
|
+ el.innerHTML = '';
|
|
|
+ }
|
|
|
+ })
|
|
|
},
|
|
|
|
|
|
onFinish() {
|
|
|
- //保存
|
|
|
-
|
|
|
- let params = {
|
|
|
+ let params = {
|
|
|
goalInfoId: this.$props.question.id,
|
|
|
- nAnswer:this.form.n
|
|
|
- }
|
|
|
- let p = Object.assign(params,this.saveForm)
|
|
|
+ nAnswer: this.form.n
|
|
|
+ }
|
|
|
+ let p = Object.assign(params, this.saveForm)
|
|
|
|
|
|
- postGPSREN(p).then(d=>{
|
|
|
+ postGPSREN(p).then(d=>{
|
|
|
console.log("postGPSREN",d)
|
|
|
if(d.status == 200) {
|
|
|
- let dt = d.data || {}
|
|
|
- if(dt.code == 1) {
|
|
|
- this.$props.finish && this.$props.finish()
|
|
|
- }
|
|
|
+ let dt = d.data || {}
|
|
|
+ if(dt.code == 1) {
|
|
|
+ this.$props.finish && this.$props.finish()
|
|
|
+ }
|
|
|
}
|
|
|
- })
|
|
|
-
|
|
|
+ })
|
|
|
},
|
|
|
-
|
|
|
},
|
|
|
|
|
|
filters: {
|
|
|
getStepModelTips(s) {
|
|
|
let cs = this.stepmodel[s]
|
|
|
- console.log("dddd==>",cs)
|
|
|
if(!!cs) {
|
|
|
- return cs['requires'] || ""
|
|
|
+ return cs['requires'] || ""
|
|
|
}
|
|
|
return ""
|
|
|
},
|
|
|
},
|
|
|
-
|
|
|
}
|
|
|
</script>
|
|
|
|
|
|
-<style lang="scss">
|
|
|
-.el-dialog__header {
|
|
|
- background-color: #477efa !important;
|
|
|
- color: aliceblue !important;
|
|
|
+<style lang="scss" scoped>
|
|
|
+
|
|
|
+
|
|
|
+.gpsren-container {
|
|
|
+ max-width: 1400px;
|
|
|
+ margin: 0 auto;
|
|
|
+ padding: 24px;
|
|
|
+ background: #f5f7fa;
|
|
|
+ min-height: 100vh;
|
|
|
}
|
|
|
|
|
|
-.el-dialog__close {
|
|
|
- color: aliceblue !important;
|
|
|
+.gpsren-form {
|
|
|
+ width: 100%;
|
|
|
}
|
|
|
|
|
|
-.GPSREN {
|
|
|
- margin-bottom: 0px !important;
|
|
|
+/* 目标卡片 */
|
|
|
+.goal-card {
|
|
|
+ background: #ffffff;
|
|
|
+ border-radius: 8px;
|
|
|
+ padding: 20px 24px;
|
|
|
+ margin-bottom: 24px;
|
|
|
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
|
|
|
+ border-left: 3px solid #409EFF;
|
|
|
|
|
|
- .cust-title {
|
|
|
- text-align: center;
|
|
|
- font-size: 20px;
|
|
|
+ .goal-header {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ margin-bottom: 12px;
|
|
|
+
|
|
|
+ i {
|
|
|
+ font-size: 20px;
|
|
|
+ color: #409EFF;
|
|
|
+ margin-right: 10px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .goal-title {
|
|
|
+ font-size: 16px;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #303133;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- .test-area{
|
|
|
+ .goal-content {
|
|
|
+ font-size: 15px;
|
|
|
+ line-height: 1.6;
|
|
|
+ color: #606266;
|
|
|
+ padding-left: 30px;
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
+/* 步骤条 */
|
|
|
+.steps-wrapper {
|
|
|
+ background: #ffffff;
|
|
|
+ border-radius: 8px;
|
|
|
+ padding: 20px 24px;
|
|
|
+ margin-bottom: 24px;
|
|
|
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
|
|
|
+
|
|
|
+ .steps-header {
|
|
|
display: flex;
|
|
|
- align-items:flex-start;
|
|
|
justify-content: space-between;
|
|
|
- gap: 10px;
|
|
|
- height: 350px;
|
|
|
+ align-items: center;
|
|
|
+ margin-bottom: 20px;
|
|
|
+ padding-bottom: 16px;
|
|
|
+ border-bottom: 1px solid #EBEEF5;
|
|
|
+
|
|
|
+ .progress-info {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 16px;
|
|
|
+
|
|
|
+ .current-step {
|
|
|
+ font-size: 16px;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #303133;
|
|
|
+ }
|
|
|
|
|
|
- .test-form{
|
|
|
- width:50%;
|
|
|
+ .progress-text {
|
|
|
+ font-size: 14px;
|
|
|
+ color: #909399;
|
|
|
+ background: #F5F7FA;
|
|
|
+ padding: 4px 12px;
|
|
|
+ border-radius: 12px;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- .ai-evaluate{
|
|
|
- color:#333;
|
|
|
- background-color: #eee;
|
|
|
- border: solid 1px #eee;
|
|
|
- height: calc(100%);
|
|
|
- overflow: auto;
|
|
|
+ .score-summary {
|
|
|
+ display: flex;
|
|
|
+ align-items: baseline;
|
|
|
+ gap: 6px;
|
|
|
+
|
|
|
+ .label {
|
|
|
+ font-size: 13px;
|
|
|
+ color: #606266;
|
|
|
+ }
|
|
|
+
|
|
|
+ .value {
|
|
|
+ font-size: 24px;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #409EFF;
|
|
|
+ }
|
|
|
+
|
|
|
+ .total {
|
|
|
+ font-size: 14px;
|
|
|
+ color: #909399;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- .cust-label {
|
|
|
- font-weight: bold;
|
|
|
+ ::v-deep .custom-steps {
|
|
|
+ .el-step__head {
|
|
|
+ &.is-process {
|
|
|
+ color: #409EFF;
|
|
|
+ border-color: #409EFF;
|
|
|
+ }
|
|
|
|
|
|
- .el-form-item__label {
|
|
|
- color: #67C23A !important;
|
|
|
+ &.is-finish {
|
|
|
+ color: #67C23A;
|
|
|
+ border-color: #67C23A;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
+ .el-step__line {
|
|
|
+ background-color: #E4E7ED;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- .custom-height .el-textarea__inner {
|
|
|
- height: 350px;
|
|
|
- /* 设置你想要的高度 */
|
|
|
- }
|
|
|
-
|
|
|
- .opt-area{
|
|
|
- // background-color: #67C23A;
|
|
|
- color:#eee;
|
|
|
+ .step-title {
|
|
|
display: flex;
|
|
|
- align-items:center;
|
|
|
- justify-content: space-between;
|
|
|
- gap: 10px;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: center;
|
|
|
+ gap: 8px;
|
|
|
+
|
|
|
+ .step-badge {
|
|
|
+ width: 44px;
|
|
|
+ height: 44px;
|
|
|
+ border-radius: 50%;
|
|
|
+ background: #E4E7ED;
|
|
|
+ color: #909399;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ font-size: 18px;
|
|
|
+ font-weight: 600;
|
|
|
+ transition: all 0.3s;
|
|
|
+
|
|
|
+ &.active {
|
|
|
+ background: #409EFF;
|
|
|
+ color: white;
|
|
|
+ box-shadow: 0 0 0 4px rgba(64, 158, 255, 0.2);
|
|
|
+ }
|
|
|
+
|
|
|
+ &.finished {
|
|
|
+ background: #67C23A;
|
|
|
+ color: white;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- .opt-left{
|
|
|
- width: 50%;
|
|
|
- height: 100%;
|
|
|
+ .step-name {
|
|
|
+ font-size: 13px;
|
|
|
+ color: #606266;
|
|
|
+ font-weight: 500;
|
|
|
+ }
|
|
|
+
|
|
|
+ .step-score {
|
|
|
+ font-size: 12px;
|
|
|
+ color: #F56C6C;
|
|
|
+ font-weight: 600;
|
|
|
+ background: #FEF0F0;
|
|
|
+ padding: 3px 10px;
|
|
|
+ border-radius: 10px;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-.testbox p {
|
|
|
- display: inline-block;
|
|
|
-}
|
|
|
+/* 答题区域 */
|
|
|
+.answer-section {
|
|
|
+ .answer-card {
|
|
|
+ background: #ffffff;
|
|
|
+ border-radius: 8px;
|
|
|
+ padding: 24px;
|
|
|
+ margin-bottom: 20px;
|
|
|
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
|
|
|
+
|
|
|
+ .answer-header {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ margin-bottom: 20px;
|
|
|
+ padding-bottom: 12px;
|
|
|
+ border-bottom: 1px solid #EBEEF5;
|
|
|
+
|
|
|
+ .answer-title {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 14px;
|
|
|
+
|
|
|
+ .phase-badge {
|
|
|
+ width: 48px;
|
|
|
+ height: 48px;
|
|
|
+ border-radius: 8px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ font-size: 20px;
|
|
|
+ font-weight: 600;
|
|
|
+ color: white;
|
|
|
+ flex-shrink: 0;
|
|
|
+
|
|
|
+ &.phase-p {
|
|
|
+ background: #409EFF;
|
|
|
+ }
|
|
|
|
|
|
+ &.phase-s {
|
|
|
+ background: #67C23A;
|
|
|
+ }
|
|
|
|
|
|
-/*.el-upload--picture-card {*/
|
|
|
-/* width: 100px !important;*/
|
|
|
-/* height: 90px !important;*/
|
|
|
-/* line-height: 100px !important;*/
|
|
|
-/* vertical-align: top;*/
|
|
|
-/*}*/
|
|
|
-.tops {
|
|
|
- display: inline-block;
|
|
|
- text-align: center;
|
|
|
- width: 100px;
|
|
|
- height: 40px;
|
|
|
- line-height: 40px;
|
|
|
- border-radius: 40px;
|
|
|
- background-color: #FAD303;
|
|
|
- box-shadow: 3px 2px 0 0 rgba(250, 213, 3, 0.445);
|
|
|
-}
|
|
|
+ &.phase-r {
|
|
|
+ background: #E6A23C;
|
|
|
+ }
|
|
|
|
|
|
-.el-pagination {
|
|
|
- margin-top: 15px;
|
|
|
- text-align: center;
|
|
|
-}
|
|
|
+ &.phase-e {
|
|
|
+ background: #F56C6C;
|
|
|
+ }
|
|
|
|
|
|
-.title3 .count {
|
|
|
- position: relative;
|
|
|
- overflow: overlay;
|
|
|
- display: inline-block;
|
|
|
- font-weight: bolder;
|
|
|
- left: 86px;
|
|
|
- color: red;
|
|
|
- font-size: 45px;
|
|
|
-}
|
|
|
+ &.phase-n {
|
|
|
+ background: #909399;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
-.title3 .mark {
|
|
|
- width: 205px;
|
|
|
- top: 85px;
|
|
|
- left: 57%;
|
|
|
- height: 64px;
|
|
|
- position: absolute;
|
|
|
-}
|
|
|
+ .title-content {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 4px;
|
|
|
|
|
|
-.el-radio-button__inner,
|
|
|
-.el-radio-group {
|
|
|
- padding-top: 20px !important;
|
|
|
- display: block !important;
|
|
|
-}
|
|
|
+ .main-title {
|
|
|
+ font-size: 18px;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #303133;
|
|
|
+ line-height: 1.2;
|
|
|
+ }
|
|
|
|
|
|
-.testinfo {
|
|
|
- padding-left: 30px;
|
|
|
- padding-top: 22px;
|
|
|
-}
|
|
|
+ .sub-title {
|
|
|
+ font-size: 13px;
|
|
|
+ color: #909399;
|
|
|
+ line-height: 1.2;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
-.title3 {
|
|
|
- width: 100%;
|
|
|
- height: 30px;
|
|
|
- text-align: center;
|
|
|
-}
|
|
|
+ .score-display {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 8px;
|
|
|
+ background: #F5F7FA;
|
|
|
+ padding: 8px 16px;
|
|
|
+ border-radius: 6px;
|
|
|
+ border: 2px solid #409EFF;
|
|
|
+
|
|
|
+ .score-content {
|
|
|
+ display: flex;
|
|
|
+ align-items: baseline;
|
|
|
+ gap: 2px;
|
|
|
+
|
|
|
+ .score-value {
|
|
|
+ font-size: 28px;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #409EFF;
|
|
|
+ line-height: 1;
|
|
|
+ }
|
|
|
|
|
|
-.subbtnbox {
|
|
|
- width: 100%;
|
|
|
- text-align: center;
|
|
|
- padding: 20px;
|
|
|
+ .score-divider {
|
|
|
+ font-size: 18px;
|
|
|
+ color: #DCDFE6;
|
|
|
+ margin: 0 2px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .score-total {
|
|
|
+ font-size: 16px;
|
|
|
+ color: #909399;
|
|
|
+ line-height: 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- .btn {
|
|
|
- width: 100px;
|
|
|
- background-color: red;
|
|
|
+ .score-label {
|
|
|
+ font-size: 13px;
|
|
|
+ color: #606266;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .total-score {
|
|
|
+ background: #F0F9FF;
|
|
|
+ padding: 10px 20px;
|
|
|
+ border-radius: 6px;
|
|
|
+ border: 2px solid #67C23A;
|
|
|
+
|
|
|
+ .total-content {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: center;
|
|
|
+ gap: 4px;
|
|
|
+
|
|
|
+ .total-label {
|
|
|
+ font-size: 12px;
|
|
|
+ color: #606266;
|
|
|
+ }
|
|
|
+
|
|
|
+ .total-value-wrapper {
|
|
|
+ display: flex;
|
|
|
+ align-items: baseline;
|
|
|
+ gap: 2px;
|
|
|
+
|
|
|
+ .total-value {
|
|
|
+ font-size: 32px;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #67C23A;
|
|
|
+ line-height: 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ .total-divider {
|
|
|
+ font-size: 20px;
|
|
|
+ color: #DCDFE6;
|
|
|
+ margin: 0 2px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .total-max {
|
|
|
+ font-size: 18px;
|
|
|
+ color: #909399;
|
|
|
+ line-height: 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .answer-content {
|
|
|
+ display: grid;
|
|
|
+ grid-template-columns: 1fr 1fr;
|
|
|
+ gap: 20px;
|
|
|
+
|
|
|
+ &.single-column {
|
|
|
+ grid-template-columns: 1fr;
|
|
|
+ }
|
|
|
+
|
|
|
+ .input-area {
|
|
|
+ .input-header {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ margin-bottom: 8px;
|
|
|
+
|
|
|
+ .input-label {
|
|
|
+ font-size: 14px;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #303133;
|
|
|
+ }
|
|
|
+
|
|
|
+ .char-count {
|
|
|
+ font-size: 12px;
|
|
|
+ color: #909399;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ ::v-deep .answer-textarea {
|
|
|
+ .el-textarea__inner {
|
|
|
+ border: 1px solid #DCDFE6;
|
|
|
+ border-radius: 4px;
|
|
|
+ padding: 12px;
|
|
|
+ font-size: 14px;
|
|
|
+ line-height: 1.6;
|
|
|
+ transition: border-color 0.2s;
|
|
|
+
|
|
|
+ &:focus {
|
|
|
+ border-color: #409EFF;
|
|
|
+ }
|
|
|
+
|
|
|
+ &::placeholder {
|
|
|
+ color: #C0C4CC;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .ai-feedback-area {
|
|
|
+ background: #F5F7FA;
|
|
|
+ border-radius: 4px;
|
|
|
+ padding: 16px;
|
|
|
+ border: 1px solid #E4E7ED;
|
|
|
+
|
|
|
+ .feedback-header {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ margin-bottom: 12px;
|
|
|
+ padding-bottom: 10px;
|
|
|
+ border-bottom: 1px solid #DCDFE6;
|
|
|
+
|
|
|
+ .header-left {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 6px;
|
|
|
+
|
|
|
+ i {
|
|
|
+ font-size: 16px;
|
|
|
+ color: #409EFF;
|
|
|
+ }
|
|
|
+
|
|
|
+ span {
|
|
|
+ font-size: 14px;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #303133;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .feedback-content {
|
|
|
+ min-height: 200px;
|
|
|
+ max-height: 500px;
|
|
|
+ overflow-y: auto;
|
|
|
+
|
|
|
+ .loading-state {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ padding: 50px 20px;
|
|
|
+ color: #606266;
|
|
|
+
|
|
|
+ .loading-animation {
|
|
|
+ width: 48px;
|
|
|
+ height: 48px;
|
|
|
+ border-radius: 50%;
|
|
|
+ background: #ECF5FF;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ margin-bottom: 16px;
|
|
|
+
|
|
|
+ i {
|
|
|
+ font-size: 24px;
|
|
|
+ color: #409EFF;
|
|
|
+ animation: rotate 1.5s linear infinite;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ span {
|
|
|
+ font-size: 13px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .empty-state {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ padding: 50px 20px;
|
|
|
+ color: #909399;
|
|
|
+
|
|
|
+ i {
|
|
|
+ font-size: 48px;
|
|
|
+ margin-bottom: 12px;
|
|
|
+ opacity: 0.5;
|
|
|
+ }
|
|
|
+
|
|
|
+ span {
|
|
|
+ font-size: 13px;
|
|
|
+ text-align: center;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .ai-response {
|
|
|
+ font-size: 14px;
|
|
|
+ line-height: 1.7;
|
|
|
+ color: #606266;
|
|
|
+ white-space: pre-wrap;
|
|
|
+ word-wrap: break-word;
|
|
|
+
|
|
|
+ ::v-deep {
|
|
|
+ h1, h2, h3, h4, h5, h6 {
|
|
|
+ margin: 14px 0 10px;
|
|
|
+ color: #303133;
|
|
|
+ font-weight: 600;
|
|
|
+ }
|
|
|
+
|
|
|
+ p {
|
|
|
+ margin: 6px 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ ul, ol {
|
|
|
+ padding-left: 20px;
|
|
|
+ margin: 10px 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ li {
|
|
|
+ margin: 4px 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ strong {
|
|
|
+ color: #303133;
|
|
|
+ font-weight: 600;
|
|
|
+ }
|
|
|
+
|
|
|
+ code {
|
|
|
+ background: #FDF6EC;
|
|
|
+ padding: 2px 6px;
|
|
|
+ border-radius: 3px;
|
|
|
+ font-family: 'Courier New', monospace;
|
|
|
+ color: #E6A23C;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
-}
|
|
|
|
|
|
-.testbox {
|
|
|
- display: inline-block;
|
|
|
- margin-top: 20px
|
|
|
+ .summary-card {
|
|
|
+ border: 2px solid #67C23A;
|
|
|
+ background: linear-gradient(to bottom, #ffffff 0%, #f0f9ff 100%);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-.btnbox {
|
|
|
- display: flex;
|
|
|
- display: -webkit-flex;
|
|
|
- justify-content: space-around;
|
|
|
- padding-left: 100px;
|
|
|
- margin-top: 30px;
|
|
|
- padding-right: 100px;
|
|
|
-}
|
|
|
+/* 操作按钮 */
|
|
|
+.action-buttons {
|
|
|
+ margin-top: 24px;
|
|
|
|
|
|
-.play {
|
|
|
- display: inline-block;
|
|
|
- height: 30px;
|
|
|
- line-height: 30px;
|
|
|
- padding-left: 10px;
|
|
|
- color: red;
|
|
|
- cursor: pointer;
|
|
|
-
|
|
|
- .cp {
|
|
|
- font-size: 20px;
|
|
|
- vertical-align: middle;
|
|
|
+ .button-group {
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ gap: 16px;
|
|
|
+ margin-bottom: 12px;
|
|
|
}
|
|
|
|
|
|
- .ai-ana {
|
|
|
- color: skyblue;
|
|
|
+ .tips-text {
|
|
|
+ text-align: center;
|
|
|
+ font-size: 13px;
|
|
|
+ color: #909399;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ gap: 4px;
|
|
|
+
|
|
|
+ i {
|
|
|
+ font-size: 14px;
|
|
|
+ }
|
|
|
}
|
|
|
-}
|
|
|
|
|
|
+ .action-btn {
|
|
|
+ min-width: 140px;
|
|
|
+ height: 40px;
|
|
|
+ font-size: 15px;
|
|
|
+ font-weight: 500;
|
|
|
+ border-radius: 4px;
|
|
|
+
|
|
|
+ i {
|
|
|
+ font-size: 16px;
|
|
|
+ }
|
|
|
+
|
|
|
+ &.primary-btn {
|
|
|
+ background: #409EFF;
|
|
|
+ border-color: #409EFF;
|
|
|
+
|
|
|
+ &:hover:not(:disabled) {
|
|
|
+ background: #66b1ff;
|
|
|
+ border-color: #66b1ff;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ &.success-btn {
|
|
|
+ background: #67C23A;
|
|
|
+ border-color: #67C23A;
|
|
|
|
|
|
-.typing-effect {
|
|
|
- overflow: hidden;
|
|
|
- /* 确保超出部分的内容不显示 */
|
|
|
- border-right: .15em solid orange;
|
|
|
- /* 光标效果 */
|
|
|
- white-space: nowrap;
|
|
|
- /* 防止文本换行 */
|
|
|
- animation: typing 3s steps(20, end), blink-caret .75s step-end infinite;
|
|
|
+ &:hover:not(:disabled) {
|
|
|
+ background: #85ce61;
|
|
|
+ border-color: #85ce61;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ &.finish-btn {
|
|
|
+ background: #67C23A;
|
|
|
+ border-color: #67C23A;
|
|
|
+ min-width: 200px;
|
|
|
+ height: 48px;
|
|
|
+ font-size: 16px;
|
|
|
+
|
|
|
+ &:hover:not(:disabled) {
|
|
|
+ background: #85ce61;
|
|
|
+ border-color: #85ce61;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .finish-section {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: center;
|
|
|
+ gap: 20px;
|
|
|
+
|
|
|
+ .finish-summary {
|
|
|
+ display: flex;
|
|
|
+ gap: 32px;
|
|
|
+ padding: 16px 32px;
|
|
|
+ background: #F5F7FA;
|
|
|
+ border-radius: 8px;
|
|
|
+ border: 1px solid #E4E7ED;
|
|
|
+
|
|
|
+ .summary-item {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ align-items: center;
|
|
|
+ gap: 6px;
|
|
|
+
|
|
|
+ .label {
|
|
|
+ font-size: 13px;
|
|
|
+ color: #909399;
|
|
|
+ }
|
|
|
+
|
|
|
+ .value {
|
|
|
+ font-size: 20px;
|
|
|
+ font-weight: 600;
|
|
|
+ color: #303133;
|
|
|
+
|
|
|
+ &.highlight {
|
|
|
+ color: #67C23A;
|
|
|
+ font-size: 24px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-@keyframes typing {
|
|
|
+/* 动画 */
|
|
|
+@keyframes rotate {
|
|
|
from {
|
|
|
- width: 0
|
|
|
+ transform: rotate(0deg);
|
|
|
}
|
|
|
-
|
|
|
to {
|
|
|
- width: 100%
|
|
|
+ transform: rotate(360deg);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-@keyframes blink-caret {
|
|
|
+/* 滚动条样式 */
|
|
|
+.feedback-content::-webkit-scrollbar {
|
|
|
+ width: 8px;
|
|
|
+}
|
|
|
|
|
|
- from,
|
|
|
- to {
|
|
|
- border-color: transparent
|
|
|
+.feedback-content::-webkit-scrollbar-track {
|
|
|
+ background: #f1f1f1;
|
|
|
+ border-radius: 4px;
|
|
|
+}
|
|
|
+
|
|
|
+.feedback-content::-webkit-scrollbar-thumb {
|
|
|
+ background: #c1c1c1;
|
|
|
+ border-radius: 4px;
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ background: #a8a8a8;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/* 响应式设计 */
|
|
|
+@media (max-width: 1200px) {
|
|
|
+ .answer-content {
|
|
|
+ grid-template-columns: 1fr !important;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+@media (max-width: 768px) {
|
|
|
+ .gpsren-container {
|
|
|
+ padding: 16px;
|
|
|
}
|
|
|
|
|
|
- 50% {
|
|
|
- border-color: orange
|
|
|
+ .goal-card,
|
|
|
+ .steps-wrapper,
|
|
|
+ .answer-card {
|
|
|
+ padding: 20px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .action-buttons {
|
|
|
+ flex-direction: column;
|
|
|
+
|
|
|
+ .action-btn {
|
|
|
+ width: 100%;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
</style>
|