feat: 优化问卷完成流程 - 添加完成页面,优化样式和交互,简化后端代码
This commit is contained in:
parent
67a6a13b1d
commit
083f263d09
@ -20,10 +20,10 @@ public interface OptionDao extends BaseDao<Option, Long> {
|
||||
* 根据问题ID和选项代码查询
|
||||
*
|
||||
* @param questionId 问题ID
|
||||
* @param optionCode 选项代码
|
||||
* @param code 选项代码
|
||||
* @return 选项对象
|
||||
*/
|
||||
Optional<Option> findByQuestionIdAndCode(Long questionId, String optionCode);
|
||||
Optional<Option> findByQuestionIdAndCode(Long questionId, String code);
|
||||
|
||||
/**
|
||||
* 批量插入选项
|
||||
|
||||
@ -21,7 +21,7 @@ public class Option {
|
||||
/**
|
||||
* 选项代码(如A、B、C)
|
||||
*/
|
||||
private String optionCode;
|
||||
private String code;
|
||||
|
||||
/**
|
||||
* 选项内容
|
||||
|
||||
@ -30,7 +30,7 @@ public class SurveyResponse {
|
||||
private List<String> selectedOptions;
|
||||
|
||||
/**
|
||||
* 文本答案
|
||||
* 文本答案(用于文本题或需要填写文本的选项)
|
||||
*/
|
||||
private String textAnswer;
|
||||
|
||||
|
||||
@ -81,19 +81,6 @@ public class SurveyResponseServiceImpl implements SurveyResponseService {
|
||||
|
||||
@Override
|
||||
public List<SurveyResponse> submitSurvey(Long userId, List<SurveyResponse> responses) {
|
||||
// 验证所有必答题是否已回答
|
||||
List<Question> questions = questionService.getUserQuestions(userId);
|
||||
for (Question question : questions) {
|
||||
if (question.getIsRequired()) {
|
||||
boolean answered = responses.stream()
|
||||
.anyMatch(response -> response.getQuestionId().equals(question.getId()));
|
||||
if (!answered) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("问题 %d 为必答题,请填写答案", question.getNumber()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 删除用户之前的答案
|
||||
deleteByUserId(userId);
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
<resultMap id="optionMap" type="ltd.qubit.survey.model.Option">
|
||||
<id property="id" column="id"/>
|
||||
<result property="questionId" column="question_id"/>
|
||||
<result property="optionCode" column="option_code"/>
|
||||
<result property="code" column="code"/>
|
||||
<result property="content" column="content"/>
|
||||
<result property="requiresText" column="requires_text"/>
|
||||
<result property="createdAt" column="created_at"/>
|
||||
@ -13,21 +13,21 @@
|
||||
|
||||
<!-- 基础列 -->
|
||||
<sql id="baseColumns">
|
||||
`id`, `question_id`, `option_code`, `content`, `requires_text`, `created_at`
|
||||
`id`, `question_id`, `code`, `content`, `requires_text`, `created_at`
|
||||
</sql>
|
||||
|
||||
<!-- 插入 -->
|
||||
<insert id="insert" parameterType="ltd.qubit.survey.model.Option" useGeneratedKeys="true" keyProperty="id">
|
||||
INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`)
|
||||
VALUES (#{questionId}, #{optionCode}, #{content}, #{requiresText})
|
||||
INSERT INTO `option` (`question_id`, `code`, `content`, `requires_text`)
|
||||
VALUES (#{questionId}, #{code}, #{content}, #{requiresText})
|
||||
</insert>
|
||||
|
||||
<!-- 批量插入 -->
|
||||
<insert id="batchInsert" parameterType="java.util.List">
|
||||
INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`)
|
||||
INSERT INTO `option` (`question_id`, `code`, `content`, `requires_text`)
|
||||
VALUES
|
||||
<foreach collection="list" item="item" separator=",">
|
||||
(#{item.questionId}, #{item.optionCode}, #{item.content}, #{item.requiresText})
|
||||
(#{item.questionId}, #{item.code}, #{item.content}, #{item.requiresText})
|
||||
</foreach>
|
||||
</insert>
|
||||
|
||||
@ -35,7 +35,7 @@
|
||||
<update id="update" parameterType="ltd.qubit.survey.model.Option">
|
||||
UPDATE `option`
|
||||
SET `question_id` = #{questionId},
|
||||
`option_code` = #{optionCode},
|
||||
`code` = #{code},
|
||||
`content` = #{content},
|
||||
`requires_text` = #{requiresText}
|
||||
WHERE `id` = #{id}
|
||||
@ -62,7 +62,7 @@
|
||||
<select id="findAll" resultMap="optionMap">
|
||||
SELECT <include refid="baseColumns"/>
|
||||
FROM `option`
|
||||
ORDER BY `question_id`, `option_code`
|
||||
ORDER BY `question_id`, `code`
|
||||
</select>
|
||||
|
||||
<!-- 根据问题ID查询 -->
|
||||
@ -70,14 +70,14 @@
|
||||
SELECT <include refid="baseColumns"/>
|
||||
FROM `option`
|
||||
WHERE `question_id` = #{questionId}
|
||||
ORDER BY `option_code`
|
||||
ORDER BY `code`
|
||||
</select>
|
||||
|
||||
<!-- 根据问题ID和选项代码查询 -->
|
||||
<select id="findByQuestionIdAndOptionCode" resultMap="optionMap">
|
||||
<select id="findByQuestionIdAndCode" resultMap="optionMap">
|
||||
SELECT <include refid="baseColumns"/>
|
||||
FROM `option`
|
||||
WHERE `question_id` = #{questionId}
|
||||
AND `option_code` = #{optionCode}
|
||||
AND `code` = #{code}
|
||||
</select>
|
||||
</mapper>
|
||||
@ -19,7 +19,9 @@
|
||||
<!-- 插入 -->
|
||||
<insert id="insert" parameterType="ltd.qubit.survey.model.SurveyResponse" useGeneratedKeys="true" keyProperty="id">
|
||||
INSERT INTO `survey_response` (`user_id`, `question_id`, `selected_options`, `text_answer`)
|
||||
VALUES (#{userId}, #{questionId}, #{selectedOptions,typeHandler=ltd.qubit.survey.common.mybatis.JsonTypeHandler}, #{textAnswer})
|
||||
VALUES (#{userId}, #{questionId},
|
||||
#{selectedOptions,typeHandler=ltd.qubit.survey.common.mybatis.JsonTypeHandler},
|
||||
#{textAnswer})
|
||||
</insert>
|
||||
|
||||
<!-- 批量插入 -->
|
||||
|
||||
@ -36,14 +36,14 @@ CREATE TABLE IF NOT EXISTS `question` (
|
||||
-- 创建选项表
|
||||
CREATE TABLE IF NOT EXISTS `option` (
|
||||
`id` BIGINT PRIMARY KEY AUTO_INCREMENT,
|
||||
`question_id` BIGINT NOT NULL COMMENT '问题ID',
|
||||
`option_code` VARCHAR(10) NOT NULL COMMENT '选项代码',
|
||||
`question_id` BIGINT NOT NULL COMMENT '关联的问题ID',
|
||||
`code` VARCHAR(10) NOT NULL COMMENT '选项代码',
|
||||
`content` TEXT NOT NULL COMMENT '选项内容',
|
||||
`requires_text` BOOLEAN NOT NULL DEFAULT FALSE COMMENT '是否需要填写文本',
|
||||
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
FOREIGN KEY (`question_id`) REFERENCES `question` (`id`),
|
||||
UNIQUE KEY `uk_question_option` (`question_id`, `option_code`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='选项表';
|
||||
UNIQUE KEY `uk_question_code` (`question_id`, `code`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='问题选项表';
|
||||
|
||||
-- 创建问卷答案表
|
||||
CREATE TABLE IF NOT EXISTS `survey_response` (
|
||||
@ -51,7 +51,7 @@ CREATE TABLE IF NOT EXISTS `survey_response` (
|
||||
`user_id` BIGINT NOT NULL COMMENT '用户ID',
|
||||
`question_id` BIGINT NOT NULL COMMENT '问题ID',
|
||||
`selected_options` JSON DEFAULT NULL COMMENT '选中的选项代码列表',
|
||||
`text_answer` TEXT DEFAULT NULL COMMENT '文本答案',
|
||||
`text_answer` TEXT DEFAULT NULL COMMENT '文本答案(用于文本题或需要填写文本的选项)',
|
||||
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||||
FOREIGN KEY (`user_id`) REFERENCES `user` (`id`),
|
||||
FOREIGN KEY (`question_id`) REFERENCES `question` (`id`)
|
||||
@ -69,7 +69,7 @@ SET FOREIGN_KEY_CHECKS = 1;
|
||||
INSERT INTO `question` (`number`, `content`, `type`, `is_required`, `is_last`)
|
||||
VALUES (1, '您对大模型(如ChatGPT、通义千问、DeepSeek)的了解程度:', 'SINGLE_CHOICE', TRUE, FALSE);
|
||||
|
||||
INSERT INTO `option` (`question_id`, `option_code`, `content`) VALUES
|
||||
INSERT INTO `option` (`question_id`, `code`, `content`) VALUES
|
||||
(LAST_INSERT_ID(), 'A', '从未接触过'),
|
||||
(LAST_INSERT_ID(), 'B', '仅在日常简单使用过通用功能(如问答)'),
|
||||
(LAST_INSERT_ID(), 'C', '在工作中尝试过基础应用'),
|
||||
@ -78,7 +78,7 @@ INSERT INTO `option` (`question_id`, `option_code`, `content`) VALUES
|
||||
INSERT INTO `question` (`number`, `content`, `type`, `is_required`, `is_last`)
|
||||
VALUES (2, '您觉得大模型可以做到下面哪些事?', 'MULTIPLE_CHOICE', TRUE, FALSE);
|
||||
|
||||
INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES
|
||||
INSERT INTO `option` (`question_id`, `code`, `content`, `requires_text`) VALUES
|
||||
(LAST_INSERT_ID(), 'A', '精准知识问答', FALSE),
|
||||
(LAST_INSERT_ID(), 'B', '文档撰写/报告生成/代码编写/图片视频生成等', FALSE),
|
||||
(LAST_INSERT_ID(), 'C', '数据清洗与分析', FALSE),
|
||||
@ -90,7 +90,7 @@ INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`)
|
||||
INSERT INTO `question` (`number`, `content`, `type`, `is_required`, `is_last`)
|
||||
VALUES (3, '您最关注大模型应用的哪些风险?', 'MULTIPLE_CHOICE', TRUE, FALSE);
|
||||
|
||||
INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES
|
||||
INSERT INTO `option` (`question_id`, `code`, `content`, `requires_text`) VALUES
|
||||
(LAST_INSERT_ID(), 'A', '数据隐私泄露', FALSE),
|
||||
(LAST_INSERT_ID(), 'B', '生成内容不准确', FALSE),
|
||||
(LAST_INSERT_ID(), 'C', '合规审查风险', FALSE),
|
||||
@ -100,7 +100,7 @@ INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`)
|
||||
INSERT INTO `question` (`number`, `content`, `type`, `is_required`, `is_last`)
|
||||
VALUES (4, '您的主要工作内容是:', 'SINGLE_CHOICE', TRUE, FALSE);
|
||||
|
||||
INSERT INTO `option` (`question_id`, `option_code`, `content`) VALUES
|
||||
INSERT INTO `option` (`question_id`, `code`, `content`) VALUES
|
||||
(LAST_INSERT_ID(), 'A', '研发(产品、开发、算法、测试、运维等)'),
|
||||
(LAST_INSERT_ID(), 'B', '项目管理(项目立项、进度跟踪、风险管理等)'),
|
||||
(LAST_INSERT_ID(), 'C', '保险(产品、核保、理赔、精算等)'),
|
||||
@ -116,7 +116,7 @@ INSERT INTO `option` (`question_id`, `option_code`, `content`) VALUES
|
||||
INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`, `is_last`)
|
||||
VALUES (5, '您在开发过程中最耗时的重复性工作:', 'MULTIPLE_CHOICE', 'RD', TRUE, FALSE);
|
||||
|
||||
INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES
|
||||
INSERT INTO `option` (`question_id`, `code`, `content`, `requires_text`) VALUES
|
||||
(LAST_INSERT_ID(), 'A', '文档编写(如需求文档、技术文档等)', FALSE),
|
||||
(LAST_INSERT_ID(), 'B', '产品原型、界面设计(如使用图片生成模型自动生成等)', FALSE),
|
||||
(LAST_INSERT_ID(), 'C', '代码编写', FALSE),
|
||||
@ -127,7 +127,7 @@ INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`)
|
||||
INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`, `is_last`)
|
||||
VALUES (6, '您希望大模型如何与现有系统集成:', 'MULTIPLE_CHOICE', 'RD', TRUE, FALSE);
|
||||
|
||||
INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES
|
||||
INSERT INTO `option` (`question_id`, `code`, `content`, `requires_text`) VALUES
|
||||
(LAST_INSERT_ID(), 'A', '回答技术问题', FALSE),
|
||||
(LAST_INSERT_ID(), 'B', '自动生成代码片段(如 Github Copilot等)', FALSE),
|
||||
(LAST_INSERT_ID(), 'C', '智能测试用例生成', FALSE),
|
||||
@ -141,7 +141,7 @@ INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`)
|
||||
INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`, `is_last`)
|
||||
VALUES (7, '项目管理中最常遇到的挑战是:', 'MULTIPLE_CHOICE', 'PROJECT', TRUE, FALSE);
|
||||
|
||||
INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES
|
||||
INSERT INTO `option` (`question_id`, `code`, `content`, `requires_text`) VALUES
|
||||
(LAST_INSERT_ID(), 'A', '项目进度跟踪与更新', FALSE),
|
||||
(LAST_INSERT_ID(), 'B', '风险评估与管控', FALSE),
|
||||
(LAST_INSERT_ID(), 'C', '项目报告生成', FALSE),
|
||||
@ -150,7 +150,7 @@ INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`)
|
||||
INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`, `is_last`)
|
||||
VALUES (8, '您希望如何利用大模型提升项目管理效率:', 'MULTIPLE_CHOICE', 'PROJECT', TRUE, FALSE);
|
||||
|
||||
INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES
|
||||
INSERT INTO `option` (`question_id`, `code`, `content`, `requires_text`) VALUES
|
||||
(LAST_INSERT_ID(), 'A', '自动生成立项报告、进度报告、总结报告等', FALSE),
|
||||
(LAST_INSERT_ID(), 'B', '风险预测与预警', FALSE),
|
||||
(LAST_INSERT_ID(), 'C', '项目资料自动化整理', FALSE),
|
||||
@ -161,7 +161,7 @@ INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`)
|
||||
INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`, `is_last`)
|
||||
VALUES (9, '理赔处理中的主要瓶颈是:', 'MULTIPLE_CHOICE', 'INSURANCE', TRUE, FALSE);
|
||||
|
||||
INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES
|
||||
INSERT INTO `option` (`question_id`, `code`, `content`, `requires_text`) VALUES
|
||||
(LAST_INSERT_ID(), 'A', '理赔文档处理', FALSE),
|
||||
(LAST_INSERT_ID(), 'B', '医疗票据审核与核对', FALSE),
|
||||
(LAST_INSERT_ID(), 'C', '客户资料信息录入与处理', FALSE),
|
||||
@ -171,7 +171,7 @@ INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`)
|
||||
INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`, `is_last`)
|
||||
VALUES (10, '大模型可以优化哪些保险工作环节:', 'MULTIPLE_CHOICE', 'INSURANCE', TRUE, FALSE);
|
||||
|
||||
INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES
|
||||
INSERT INTO `option` (`question_id`, `code`, `content`, `requires_text`) VALUES
|
||||
(LAST_INSERT_ID(), 'A', '新员工入职培训', FALSE),
|
||||
(LAST_INSERT_ID(), 'B', '保险产品设计的优化', FALSE),
|
||||
(LAST_INSERT_ID(), 'C', '自动生成理赔报告与告知书', FALSE),
|
||||
@ -183,7 +183,7 @@ INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`)
|
||||
INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`, `is_last`)
|
||||
VALUES (11, '日常工作中最重复的任务是:', 'MULTIPLE_CHOICE', 'FINANCE', TRUE, FALSE);
|
||||
|
||||
INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES
|
||||
INSERT INTO `option` (`question_id`, `code`, `content`, `requires_text`) VALUES
|
||||
(LAST_INSERT_ID(), 'A', '财务数据整理与报表生成', FALSE),
|
||||
(LAST_INSERT_ID(), 'B', '发票和报销单审核', FALSE),
|
||||
(LAST_INSERT_ID(), 'C', '财务审计与合规检查', FALSE),
|
||||
@ -192,7 +192,7 @@ INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`)
|
||||
INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`, `is_last`)
|
||||
VALUES (12, '大模型能如何协助提升财务工作效率:', 'MULTIPLE_CHOICE', 'FINANCE', TRUE, FALSE);
|
||||
|
||||
INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES
|
||||
INSERT INTO `option` (`question_id`, `code`, `content`, `requires_text`) VALUES
|
||||
(LAST_INSERT_ID(), 'A', '各种报表格式的自动转换', FALSE),
|
||||
(LAST_INSERT_ID(), 'B', '自动生成财务报表与分析摘要', FALSE),
|
||||
(LAST_INSERT_ID(), 'C', '自动化审计和合规检查', FALSE),
|
||||
@ -203,7 +203,7 @@ INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`)
|
||||
INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`, `is_last`)
|
||||
VALUES (13, '客户咨询中最常遇到的重复性问题:', 'MULTIPLE_CHOICE', 'CUSTOMER_SERVICE', TRUE, FALSE);
|
||||
|
||||
INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES
|
||||
INSERT INTO `option` (`question_id`, `code`, `content`, `requires_text`) VALUES
|
||||
(LAST_INSERT_ID(), 'A', '参保资格咨询', FALSE),
|
||||
(LAST_INSERT_ID(), 'B', '理赔进度查询', FALSE),
|
||||
(LAST_INSERT_ID(), 'C', '材料补交通知', FALSE),
|
||||
@ -212,7 +212,7 @@ INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`)
|
||||
INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`, `is_last`)
|
||||
VALUES (14, '您希望大模型如何辅助客服工作:', 'MULTIPLE_CHOICE', 'CUSTOMER_SERVICE', TRUE, FALSE);
|
||||
|
||||
INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES
|
||||
INSERT INTO `option` (`question_id`, `code`, `content`, `requires_text`) VALUES
|
||||
(LAST_INSERT_ID(), 'A', '自动生成客户回复模板', FALSE),
|
||||
(LAST_INSERT_ID(), 'B', '客户咨询自动分类与转接', FALSE),
|
||||
(LAST_INSERT_ID(), 'C', '智能分析客户情绪与需求', FALSE),
|
||||
@ -222,7 +222,7 @@ INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`)
|
||||
INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`, `is_last`)
|
||||
VALUES (15, '在运营工作中,最需要自动化支持的任务是:', 'MULTIPLE_CHOICE', 'OPERATION', TRUE, FALSE);
|
||||
|
||||
INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES
|
||||
INSERT INTO `option` (`question_id`, `code`, `content`, `requires_text`) VALUES
|
||||
(LAST_INSERT_ID(), 'A', '热点讯息的获取和跟踪', FALSE),
|
||||
(LAST_INSERT_ID(), 'B', '数据分析与报告生成', FALSE),
|
||||
(LAST_INSERT_ID(), 'C', '社交媒体内容创作', FALSE),
|
||||
@ -232,7 +232,7 @@ INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`)
|
||||
INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`, `is_last`)
|
||||
VALUES (16, '大模型可以如何帮助提升运营效率:', 'MULTIPLE_CHOICE', 'OPERATION', TRUE, FALSE);
|
||||
|
||||
INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES
|
||||
INSERT INTO `option` (`question_id`, `code`, `content`, `requires_text`) VALUES
|
||||
(LAST_INSERT_ID(), 'A', '自动抓取热点讯息', FALSE),
|
||||
(LAST_INSERT_ID(), 'B', '自动生成社交媒体内容', FALSE),
|
||||
(LAST_INSERT_ID(), 'C', '用户评论分析与舆情监测', FALSE),
|
||||
@ -243,7 +243,7 @@ INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`)
|
||||
INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`, `is_last`)
|
||||
VALUES (17, '在市场拓展和商务沟通中,您最常遇到的挑战是:', 'MULTIPLE_CHOICE', 'MARKET', TRUE, FALSE);
|
||||
|
||||
INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES
|
||||
INSERT INTO `option` (`question_id`, `code`, `content`, `requires_text`) VALUES
|
||||
(LAST_INSERT_ID(), 'A', '市场分析和竞争对手跟踪', FALSE),
|
||||
(LAST_INSERT_ID(), 'B', '渠道拓展计划的自动化和优化', FALSE),
|
||||
(LAST_INSERT_ID(), 'C', '商务沟通中的信息处理与反馈跟踪', FALSE),
|
||||
@ -252,7 +252,7 @@ INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`)
|
||||
INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`, `is_last`)
|
||||
VALUES (18, '您希望大模型如何帮助提升市场拓展效率:', 'MULTIPLE_CHOICE', 'MARKET', TRUE, FALSE);
|
||||
|
||||
INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES
|
||||
INSERT INTO `option` (`question_id`, `code`, `content`, `requires_text`) VALUES
|
||||
(LAST_INSERT_ID(), 'A', '自动生成市场分析报告与趋势预测', FALSE),
|
||||
(LAST_INSERT_ID(), 'B', '根据目标客户数据生成个性化营销策略', FALSE),
|
||||
(LAST_INSERT_ID(), 'C', '自动化生成商务沟通邮件和提案文档', FALSE),
|
||||
@ -262,7 +262,7 @@ INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`)
|
||||
INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`, `is_last`)
|
||||
VALUES (19, '人事部门最耗时的日常任务是:', 'MULTIPLE_CHOICE', 'HR', TRUE, FALSE);
|
||||
|
||||
INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES
|
||||
INSERT INTO `option` (`question_id`, `code`, `content`, `requires_text`) VALUES
|
||||
(LAST_INSERT_ID(), 'A', '招聘简历筛选与面试安排', FALSE),
|
||||
(LAST_INSERT_ID(), 'B', '员工培训与学习进度管理', FALSE),
|
||||
(LAST_INSERT_ID(), 'C', '绩效评估与报告生成', FALSE),
|
||||
@ -271,7 +271,7 @@ INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`)
|
||||
INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`, `is_last`)
|
||||
VALUES (20, '您希望大模型如何协助提升人事工作效率:', 'MULTIPLE_CHOICE', 'HR', TRUE, FALSE);
|
||||
|
||||
INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES
|
||||
INSERT INTO `option` (`question_id`, `code`, `content`, `requires_text`) VALUES
|
||||
(LAST_INSERT_ID(), 'A', '自动筛选招聘简历并推荐候选人', FALSE),
|
||||
(LAST_INSERT_ID(), 'B', '自动化培训内容推送与学习路径规划', FALSE),
|
||||
(LAST_INSERT_ID(), 'C', '绩效评估与员工反馈的自动化分析', FALSE),
|
||||
@ -281,7 +281,7 @@ INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`)
|
||||
INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`, `is_last`)
|
||||
VALUES (21, '在行政工作中,最耗时的任务是:', 'MULTIPLE_CHOICE', 'ADMIN', TRUE, FALSE);
|
||||
|
||||
INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES
|
||||
INSERT INTO `option` (`question_id`, `code`, `content`, `requires_text`) VALUES
|
||||
(LAST_INSERT_ID(), 'A', '合同审查与管理', FALSE),
|
||||
(LAST_INSERT_ID(), 'B', '会议纪要整理', FALSE),
|
||||
(LAST_INSERT_ID(), 'C', '文档管理与更新', FALSE),
|
||||
@ -290,7 +290,7 @@ INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`)
|
||||
INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`, `is_last`)
|
||||
VALUES (22, '您希望大模型如何协助提升行政工作效率:', 'MULTIPLE_CHOICE', 'ADMIN', TRUE, FALSE);
|
||||
|
||||
INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES
|
||||
INSERT INTO `option` (`question_id`, `code`, `content`, `requires_text`) VALUES
|
||||
(LAST_INSERT_ID(), 'A', '自动生成合同和协议模板', FALSE),
|
||||
(LAST_INSERT_ID(), 'B', '自动化会议纪要整理与分发', FALSE),
|
||||
(LAST_INSERT_ID(), 'C', '自动化文档归档与管理', FALSE),
|
||||
@ -300,7 +300,7 @@ INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`)
|
||||
INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`, `is_last`)
|
||||
VALUES (23, '您认为大模型在哪些战略层面的决策中可以发挥作用?', 'MULTIPLE_CHOICE', 'EXECUTIVE', TRUE, FALSE);
|
||||
|
||||
INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES
|
||||
INSERT INTO `option` (`question_id`, `code`, `content`, `requires_text`) VALUES
|
||||
(LAST_INSERT_ID(), 'A', '市场趋势预测与分析', FALSE),
|
||||
(LAST_INSERT_ID(), 'B', '组织结构优化与调整', FALSE),
|
||||
(LAST_INSERT_ID(), 'C', '业务流程优化与重组', FALSE),
|
||||
@ -309,7 +309,7 @@ INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`)
|
||||
INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`, `is_last`)
|
||||
VALUES (24, '在公司管理工作中,您最希望大模型协助哪些任务?', 'MULTIPLE_CHOICE', 'EXECUTIVE', TRUE, FALSE);
|
||||
|
||||
INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES
|
||||
INSERT INTO `option` (`question_id`, `code`, `content`, `requires_text`) VALUES
|
||||
(LAST_INSERT_ID(), 'A', '数据分析与报告自动生成', FALSE),
|
||||
(LAST_INSERT_ID(), 'B', '战略规划与方案优化', FALSE),
|
||||
(LAST_INSERT_ID(), 'C', '业务协同与跨部门信息流通', FALSE),
|
||||
|
||||
44
deploy-local.sh
Executable file
44
deploy-local.sh
Executable file
@ -0,0 +1,44 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 获取脚本所在目录的绝对路径
|
||||
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
|
||||
# 设置Docker数据目录
|
||||
DOCKER_DATA_DIR="/Volumes/working/docker"
|
||||
TOMCAT_WEBAPPS_DIR="$DOCKER_DATA_DIR/tomcat/webapps"
|
||||
TOMCAT_LOGS_DIR="$DOCKER_DATA_DIR/tomcat/logs/llm-survey-api"
|
||||
|
||||
echo "=== 开始部署 ==="
|
||||
|
||||
# 1. 进入后端项目目录
|
||||
cd "$SCRIPT_DIR/backend" || exit 1
|
||||
echo "✓ 已切换到后端项目目录"
|
||||
|
||||
# 2. 清理并打包项目
|
||||
echo "正在打包后端项目..."
|
||||
mvn clean package -DskipTests
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "✗ Maven打包失败"
|
||||
exit 1
|
||||
fi
|
||||
echo "✓ Maven打包成功"
|
||||
|
||||
# 3. 复制WAR包到Tomcat的webapps目录
|
||||
echo "正在复制WAR包到Tomcat..."
|
||||
cp target/llm-survey-api.war "$TOMCAT_WEBAPPS_DIR/"
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "✗ WAR包复制失败"
|
||||
exit 1
|
||||
fi
|
||||
echo "✓ WAR包复制成功"
|
||||
|
||||
# 4. 等待部署完成
|
||||
echo "等待应用部署完成..."
|
||||
sleep 5
|
||||
|
||||
# 5. 检查部署日志
|
||||
echo "检查业务日志..."
|
||||
tail "$TOMCAT_LOGS_DIR/app.log"
|
||||
|
||||
echo "=== 部署完成 ==="
|
||||
echo "请访问 http://localhost:18080/llm-survey-api 验证部署结果"
|
||||
@ -19,6 +19,12 @@ const router = createRouter({
|
||||
component: () => import('@/views/SurveyView.vue'),
|
||||
meta: { requiresAuth: true },
|
||||
},
|
||||
{
|
||||
path: '/completed',
|
||||
name: 'completed',
|
||||
component: () => import('@/views/CompletedView.vue'),
|
||||
meta: { requiresAuth: true },
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
|
||||
@ -44,18 +44,20 @@ export const useSurveyStore = defineStore('survey', () => {
|
||||
}
|
||||
|
||||
// 获取下一个问题
|
||||
async function fetchNextQuestion(userId, selectedOptions) {
|
||||
async function fetchNextQuestion(userId, selectedOptions, targetQuestionNumber) {
|
||||
try {
|
||||
console.log('获取下一个问题,参数:', { userId, selectedOptions, currentQuestionNumber: currentQuestionNumber.value });
|
||||
console.log('获取问题,参数:', { userId, selectedOptions, targetQuestionNumber, currentQuestionNumber: currentQuestionNumber.value });
|
||||
|
||||
// 如果没有当前问题号,说明是新开始的问卷
|
||||
const isNewSurvey = !currentQuestionNumber.value;
|
||||
let question;
|
||||
if (targetQuestionNumber) {
|
||||
// 如果指定了目标问题号,直接获取该问题
|
||||
const questions = await getUserQuestions(userId);
|
||||
question = questions.find(q => q.number === targetQuestionNumber);
|
||||
} else {
|
||||
// 否则获取下一题
|
||||
question = await getNextQuestion(userId, selectedOptions, currentQuestionNumber.value);
|
||||
}
|
||||
|
||||
const question = await getNextQuestion(
|
||||
userId,
|
||||
selectedOptions,
|
||||
isNewSurvey ? undefined : currentQuestionNumber.value
|
||||
);
|
||||
console.log('获取到的问题:', question);
|
||||
|
||||
if (question) {
|
||||
@ -74,7 +76,7 @@ export const useSurveyStore = defineStore('survey', () => {
|
||||
|
||||
return question;
|
||||
} catch (error) {
|
||||
console.error('获取下一个问题失败:', error);
|
||||
console.error('获取问题失败:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
88
frontend/src/views/CompletedView.vue
Normal file
88
frontend/src/views/CompletedView.vue
Normal file
@ -0,0 +1,88 @@
|
||||
<template>
|
||||
<div class="completed-view">
|
||||
<van-nav-bar title="问卷完成" />
|
||||
|
||||
<div class="content">
|
||||
<van-empty description="感谢您完成问卷调查!">
|
||||
<template #image>
|
||||
<van-icon name="success" size="64" color="#ffffff" />
|
||||
</template>
|
||||
<div class="completion-message">
|
||||
<p>您的反馈对我们非常重要</p>
|
||||
<p>我们将根据调查结果持续改进和优化</p>
|
||||
</div>
|
||||
</van-empty>
|
||||
<van-button
|
||||
round
|
||||
type="primary"
|
||||
class="home-button"
|
||||
@click="router.replace('/')"
|
||||
>
|
||||
返回首页
|
||||
</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
const router = useRouter();
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.completed-view {
|
||||
min-height: 100vh;
|
||||
background-color: #f7f8fa;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 40px 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.completion-message {
|
||||
margin: 24px 0;
|
||||
color: #666;
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
.completion-message p:first-child {
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
color: #323233;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.completion-message p {
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
.home-button {
|
||||
margin-top: 32px;
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
/* 自定义图标样式 */
|
||||
:deep(.van-empty__image) {
|
||||
width: 120px !important;
|
||||
height: 120px !important;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
:deep(.van-icon) {
|
||||
background-color: #07c160;
|
||||
border-radius: 50%;
|
||||
padding: 16px;
|
||||
box-shadow: 0 4px 12px rgba(7, 193, 96, 0.3);
|
||||
}
|
||||
|
||||
:deep(.van-empty__description) {
|
||||
color: #323233;
|
||||
font-size: 22px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 8px;
|
||||
white-space: nowrap;
|
||||
padding: 0 20px;
|
||||
}
|
||||
</style>
|
||||
@ -13,7 +13,13 @@
|
||||
|
||||
<h1 class="title">欢迎参与 LLM 问卷调查</h1>
|
||||
<p class="description">
|
||||
本问卷旨在了解您对大语言模型(LLM)的使用体验和看法。您的反馈对我们非常重要。
|
||||
本问卷旨在了解智慧医疗员工对大语言模型的使用体验和看法。您的反馈对我们非常重要。
|
||||
</p>
|
||||
<p class="description">
|
||||
此应用使用Cursor生成。所有代码,包括数据库脚本、前后端代码、配置文件等均通过提示词指挥AI生成;git提交、测试、代码打包发布等操作也是通过提示词指挥AI完成。
|
||||
</p>
|
||||
<p class="description">
|
||||
此项目开发到上线共计耗时1人5小时,传统开发方式需要产品、前端、后端、测试4人1~2天工作量。
|
||||
</p>
|
||||
|
||||
<div class="action-buttons">
|
||||
@ -32,9 +38,9 @@
|
||||
round
|
||||
block
|
||||
type="primary"
|
||||
@click="router.push('/survey')"
|
||||
@click="surveyStore.isCompleted ? startNewSurvey() : router.push('/survey')"
|
||||
>
|
||||
继续答题
|
||||
{{ surveyStore.isCompleted ? '重新答题' : '继续答题' }}
|
||||
</van-button>
|
||||
|
||||
<van-button
|
||||
@ -55,15 +61,23 @@
|
||||
<script setup>
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useUserStore } from '@/stores/user';
|
||||
import { useSurveyStore } from '@/stores/survey';
|
||||
import { showToast } from 'vant';
|
||||
|
||||
const router = useRouter();
|
||||
const userStore = useUserStore();
|
||||
const surveyStore = useSurveyStore();
|
||||
|
||||
function onLogout() {
|
||||
userStore.logout();
|
||||
showToast('已退出登录');
|
||||
}
|
||||
|
||||
// 开始新的问卷
|
||||
function startNewSurvey() {
|
||||
surveyStore.resetSurvey();
|
||||
router.push('/survey');
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@ -92,7 +106,8 @@ function onLogout() {
|
||||
font-size: 16px;
|
||||
color: #666;
|
||||
line-height: 1.5;
|
||||
margin-bottom: 40px;
|
||||
margin-bottom: 20px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.action-buttons {
|
||||
|
||||
@ -86,7 +86,6 @@ async function onPhoneBlur() {
|
||||
const isRegistered = await userStore.checkPhoneNumber(formData.phone);
|
||||
if (isRegistered) {
|
||||
showToast('该手机号已注册');
|
||||
formData.phone = '';
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('检查手机号失败:', error);
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
@click-left="onBack"
|
||||
/>
|
||||
|
||||
<div v-if="!surveyStore.isCompleted" class="survey-content">
|
||||
<div class="survey-content">
|
||||
<div v-if="surveyStore.currentQuestion" class="question-container">
|
||||
<h2 class="question-title">
|
||||
{{ surveyStore.currentQuestionNumber }}. {{ surveyStore.currentQuestion.content }}
|
||||
@ -17,16 +17,25 @@
|
||||
<van-cell-group inset>
|
||||
<van-cell
|
||||
v-for="option in surveyStore.currentOptions"
|
||||
:key="option.optionCode"
|
||||
:key="option.code"
|
||||
clickable
|
||||
@click="toggleOption(option.optionCode)"
|
||||
@click="toggleOption(option.code)"
|
||||
>
|
||||
<template #title>
|
||||
<span>{{ option.optionCode }}. {{ option.content }}</span>
|
||||
<span>{{ option.code }}. {{ option.content }}</span>
|
||||
<template v-if="option.requiresText && selectedOptions.includes(option.code)">
|
||||
<van-field
|
||||
v-model="textAnswer"
|
||||
type="text"
|
||||
placeholder="请输入具体内容"
|
||||
class="option-text-input"
|
||||
@click.stop
|
||||
/>
|
||||
</template>
|
||||
</template>
|
||||
<template #right-icon>
|
||||
<van-checkbox
|
||||
:name="option.optionCode"
|
||||
:name="option.code"
|
||||
@click.stop
|
||||
/>
|
||||
</template>
|
||||
@ -37,15 +46,24 @@
|
||||
<van-cell-group inset>
|
||||
<van-cell
|
||||
v-for="option in surveyStore.currentOptions"
|
||||
:key="option.optionCode"
|
||||
:key="option.code"
|
||||
clickable
|
||||
@click="selectedOption = option.optionCode"
|
||||
@click="selectedOption = option.code"
|
||||
>
|
||||
<template #title>
|
||||
<span>{{ option.optionCode }}. {{ option.content }}</span>
|
||||
<span>{{ option.code }}. {{ option.content }}</span>
|
||||
<template v-if="option.requiresText && selectedOption === option.code">
|
||||
<van-field
|
||||
v-model="textAnswer"
|
||||
type="text"
|
||||
placeholder="请输入具体内容"
|
||||
class="option-text-input"
|
||||
@click.stop
|
||||
/>
|
||||
</template>
|
||||
</template>
|
||||
<template #right-icon>
|
||||
<van-radio :name="option.optionCode" />
|
||||
<van-radio :name="option.code" />
|
||||
</template>
|
||||
</van-cell>
|
||||
</van-cell-group>
|
||||
@ -57,7 +75,6 @@
|
||||
rows="4"
|
||||
autosize
|
||||
placeholder="请输入您的答案"
|
||||
:rules="[{ required: surveyStore.currentQuestion.isRequired, message: '请输入答案' }]"
|
||||
/>
|
||||
</div>
|
||||
<div class="button-container">
|
||||
@ -74,26 +91,6 @@
|
||||
|
||||
<van-empty v-else description="加载中..." />
|
||||
</div>
|
||||
|
||||
<div v-else class="survey-completed">
|
||||
<van-empty description="感谢您完成问卷调查!">
|
||||
<template #image>
|
||||
<van-icon name="success" size="64" color="#07c160" />
|
||||
</template>
|
||||
<div class="completion-message">
|
||||
<p>您的反馈对我们非常重要</p>
|
||||
<p>我们将根据调查结果持续改进和优化</p>
|
||||
</div>
|
||||
</van-empty>
|
||||
<van-button
|
||||
round
|
||||
type="primary"
|
||||
class="home-button"
|
||||
@click="router.replace('/')"
|
||||
>
|
||||
返回首页
|
||||
</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -116,21 +113,30 @@ const responses = ref([]);
|
||||
// 计算当前选择是否有效
|
||||
const isValidSelection = computed(() => {
|
||||
const questionType = surveyStore.currentQuestion?.type;
|
||||
if (!questionType) return false;
|
||||
|
||||
if (questionType === 'MULTIPLE_CHOICE') {
|
||||
return selectedOptions.value.length > 0;
|
||||
// 检查是否有选中的选项需要填写文本
|
||||
const needsText = selectedOptions.value.some(code => {
|
||||
const option = surveyStore.currentOptions.find(opt => opt.code === code);
|
||||
return option?.requiresText;
|
||||
});
|
||||
return selectedOptions.value.length > 0 && (!needsText || (textAnswer.value?.trim() || '').length > 0);
|
||||
} else if (questionType === 'SINGLE_CHOICE') {
|
||||
return selectedOption.value !== '';
|
||||
// 检查单选的选项是否需要文本且已填写
|
||||
const selectedOpt = surveyStore.currentOptions.find(opt => opt.code === selectedOption.value);
|
||||
return selectedOption.value && (!selectedOpt?.requiresText || (textAnswer.value?.trim() || '').length > 0);
|
||||
} else if (questionType === 'TEXT') {
|
||||
return textAnswer.value.trim() !== '';
|
||||
return (textAnswer.value?.trim() || '').length > 0;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
// 切换多选选项
|
||||
function toggleOption(optionCode) {
|
||||
const index = selectedOptions.value.indexOf(optionCode);
|
||||
function toggleOption(code) {
|
||||
const index = selectedOptions.value.indexOf(code);
|
||||
if (index === -1) {
|
||||
selectedOptions.value.push(optionCode);
|
||||
selectedOptions.value.push(code);
|
||||
} else {
|
||||
selectedOptions.value.splice(index, 1);
|
||||
}
|
||||
@ -144,20 +150,9 @@ function onBack() {
|
||||
// 获取下一个问题
|
||||
async function onNextQuestion() {
|
||||
const questionType = surveyStore.currentQuestion.type;
|
||||
|
||||
if (questionType === 'MULTIPLE_CHOICE' && selectedOptions.value.length === 0) {
|
||||
showToast('请至少选择一个选项');
|
||||
return;
|
||||
} else if (questionType === 'SINGLE_CHOICE' && !selectedOption.value) {
|
||||
showToast('请选择一个选项');
|
||||
return;
|
||||
} else if (questionType === 'TEXT' && !textAnswer.value.trim()) {
|
||||
showToast('请输入答案');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
let currentSelection = [];
|
||||
|
||||
if (questionType === 'MULTIPLE_CHOICE') {
|
||||
currentSelection = selectedOptions.value;
|
||||
} else if (questionType === 'SINGLE_CHOICE') {
|
||||
@ -165,18 +160,36 @@ async function onNextQuestion() {
|
||||
}
|
||||
|
||||
// 保存当前答案
|
||||
responses.value.push({
|
||||
const currentResponse = {
|
||||
questionId: surveyStore.currentQuestion.id,
|
||||
selectedOptions: currentSelection,
|
||||
textAnswer: questionType === 'TEXT' ? textAnswer.value.trim() : null
|
||||
});
|
||||
textAnswer: textAnswer.value?.trim() || null
|
||||
};
|
||||
|
||||
// 更新或添加当前答案
|
||||
const existingIndex = responses.value.findIndex(r => r.questionId === currentResponse.questionId);
|
||||
if (existingIndex !== -1) {
|
||||
responses.value[existingIndex] = currentResponse;
|
||||
} else {
|
||||
responses.value.push(currentResponse);
|
||||
}
|
||||
|
||||
// 保存答题进度到本地存储
|
||||
localStorage.setItem('surveyProgress', JSON.stringify({
|
||||
currentQuestionNumber: surveyStore.currentQuestionNumber,
|
||||
responses: responses.value
|
||||
}));
|
||||
|
||||
// 如果是最后一题,直接提交答案
|
||||
if (surveyStore.currentQuestion.isLast) {
|
||||
try {
|
||||
await surveyStore.submitSurveyResponses(userStore.userId, responses.value);
|
||||
showToast('问卷提交成功');
|
||||
surveyStore.isCompleted.value = true;
|
||||
surveyStore.isCompleted = true;
|
||||
// 清除本地存储的进度
|
||||
localStorage.removeItem('surveyProgress');
|
||||
// 跳转到完成页面
|
||||
router.replace('/completed');
|
||||
return;
|
||||
} catch (error) {
|
||||
console.error('提交问卷失败:', error);
|
||||
@ -205,10 +218,45 @@ async function onNextQuestion() {
|
||||
// 初始化问卷
|
||||
async function initSurvey() {
|
||||
try {
|
||||
// 检查是否有保存的进度
|
||||
const savedProgress = localStorage.getItem('surveyProgress');
|
||||
if (savedProgress) {
|
||||
const progress = JSON.parse(savedProgress);
|
||||
responses.value = progress.responses || [];
|
||||
|
||||
// 恢复当前题目的选项状态
|
||||
const lastResponse = responses.value[responses.value.length - 1];
|
||||
if (lastResponse) {
|
||||
if (lastResponse.selectedOptions.length === 1) {
|
||||
selectedOption.value = lastResponse.selectedOptions[0];
|
||||
} else {
|
||||
selectedOptions.value = lastResponse.selectedOptions;
|
||||
}
|
||||
textAnswer.value = lastResponse.textAnswer || '';
|
||||
}
|
||||
|
||||
// 获取当前问题
|
||||
const nextQuestionNumber = progress.currentQuestionNumber + 1;
|
||||
await surveyStore.fetchNextQuestion(
|
||||
userStore.userId,
|
||||
[],
|
||||
nextQuestionNumber
|
||||
);
|
||||
|
||||
// 如果获取失败(可能是最后一题),尝试获取当前题目
|
||||
if (!surveyStore.currentQuestion) {
|
||||
await surveyStore.fetchNextQuestion(
|
||||
userStore.userId,
|
||||
[],
|
||||
progress.currentQuestionNumber
|
||||
);
|
||||
}
|
||||
} else {
|
||||
surveyStore.resetSurvey(); // 确保重置所有状态
|
||||
responses.value = [];
|
||||
// 初始化时不传递任何选项
|
||||
await surveyStore.fetchNextQuestion(userStore.userId);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('初始化问卷失败:', error);
|
||||
showToast('初始化问卷失败,请重试');
|
||||
@ -289,4 +337,10 @@ onMounted(() => {
|
||||
margin-top: 24px;
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
.option-text-input {
|
||||
margin-top: 8px;
|
||||
background-color: #f8f8f8;
|
||||
border-radius: 4px;
|
||||
}
|
||||
</style>
|
||||
Loading…
Reference in New Issue
Block a user