feat: 修改问题跳转逻辑,使用第4题的选择结果来决定跳转,移除后端工作领域判断逻辑

This commit is contained in:
胡海星 2025-02-23 15:30:26 +08:00
parent 480008777b
commit 67a6a13b1d
32 changed files with 426 additions and 347 deletions

View File

@ -20,6 +20,8 @@
- WAR包目录`$DOCKER_DATA_DIR/tomcat/webapps` - WAR包目录`$DOCKER_DATA_DIR/tomcat/webapps`
- 应用上下文路径:`/llm-survey-api` - 应用上下文路径:`/llm-survey-api`
- 复制文件时,使用 `command cp` 命令 - 复制文件时,使用 `command cp` 命令
- 查看日志始终只查看应用的业务日志
- 部署完成后应该稍等几秒查看下业务日志看看发布有没有错误
## 4. 数据库规则 ## 4. 数据库规则
- 数据库名称:`llm_survey` - 数据库名称:`llm_survey`

View File

@ -3,7 +3,6 @@ package ltd.qubit.survey.dao;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import ltd.qubit.survey.model.Question; import ltd.qubit.survey.model.Question;
import ltd.qubit.survey.model.WorkArea;
/** /**
* 问题DAO接口 * 问题DAO接口
@ -17,14 +16,6 @@ public interface QuestionDao extends BaseDao<Question, Long> {
*/ */
Optional<Question> findByQuestionNumber(Integer questionNumber); Optional<Question> findByQuestionNumber(Integer questionNumber);
/**
* 根据工作领域查询问题列表
*
* @param workArea 工作领域
* @return 问题列表
*/
List<Question> findByWorkArea(WorkArea workArea);
/** /**
* 查询通用问题列表不针对特定工作领域 * 查询通用问题列表不针对特定工作领域
* *

View File

@ -16,12 +16,4 @@ public interface UserDao extends BaseDao<User, Long> {
* @return 用户对象 * @return 用户对象
*/ */
Optional<User> findByPhone(String phone); Optional<User> findByPhone(String phone);
/**
* 根据工作领域查询用户列表
*
* @param workArea 工作领域
* @return 用户列表
*/
List<User> findByWorkArea(WorkArea workArea);
} }

View File

@ -1 +0,0 @@
<result property="selectedOptions" column="selected_options" typeHandler="ltd.qubit.survey.common.mybatis.JsonTypeHandler"/>

View File

@ -1,6 +1,7 @@
package ltd.qubit.survey.model; package ltd.qubit.survey.model;
import java.time.Instant; import java.time.Instant;
import java.util.Map;
import lombok.Data; import lombok.Data;
/** /**
@ -41,7 +42,12 @@ public class Question {
/** /**
* 跳转逻辑JSON格式 * 跳转逻辑JSON格式
*/ */
private String next; private Map<String, Integer> next;
/**
* 是否是最后一题
*/
private Boolean isLast;
/** /**
* 创建时间 * 创建时间

View File

@ -3,7 +3,6 @@ package ltd.qubit.survey.service;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import ltd.qubit.survey.model.Question; import ltd.qubit.survey.model.Question;
import ltd.qubit.survey.model.WorkArea;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
/** /**
@ -19,14 +18,6 @@ public interface QuestionService extends BaseService<Question, Long> {
*/ */
Optional<Question> findByQuestionNumber(Integer questionNumber); Optional<Question> findByQuestionNumber(Integer questionNumber);
/**
* 根据工作领域查询问题列表
*
* @param workArea 工作领域
* @return 问题列表
*/
List<Question> findByWorkArea(WorkArea workArea);
/** /**
* 查询通用问题列表不针对特定工作领域 * 查询通用问题列表不针对特定工作领域
* *

View File

@ -3,7 +3,6 @@ package ltd.qubit.survey.service;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import ltd.qubit.survey.model.User; import ltd.qubit.survey.model.User;
import ltd.qubit.survey.model.WorkArea;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
/** /**
@ -19,14 +18,6 @@ public interface UserService extends BaseService<User, Long> {
*/ */
Optional<User> findByPhone(String phone); Optional<User> findByPhone(String phone);
/**
* 根据工作领域查询用户列表
*
* @param workArea 工作领域
* @return 用户列表
*/
List<User> findByWorkArea(WorkArea workArea);
/** /**
* 用户注册 * 用户注册
* *

View File

@ -11,7 +11,6 @@ import lombok.RequiredArgsConstructor;
import ltd.qubit.survey.dao.QuestionDao; import ltd.qubit.survey.dao.QuestionDao;
import ltd.qubit.survey.model.Question; import ltd.qubit.survey.model.Question;
import ltd.qubit.survey.model.User; import ltd.qubit.survey.model.User;
import ltd.qubit.survey.model.WorkArea;
import ltd.qubit.survey.service.QuestionService; import ltd.qubit.survey.service.QuestionService;
import ltd.qubit.survey.service.UserService; import ltd.qubit.survey.service.UserService;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -29,8 +28,8 @@ public class QuestionServiceImpl implements QuestionService {
@Override @Override
public Question create(Question question) { public Question create(Question question) {
// 如果没有指定问题序号则自动生成 // 如果没有指定问题序号则自动生成
if (question.getQuestionNumber() == null) { if (question.getNumber() == null) {
question.setQuestionNumber(questionDao.getNextQuestionNumber()); question.setNumber(questionDao.getNextQuestionNumber());
} }
question.setCreatedAt(Instant.now()); question.setCreatedAt(Instant.now());
questionDao.insert(question); questionDao.insert(question);
@ -63,11 +62,6 @@ public class QuestionServiceImpl implements QuestionService {
return questionDao.findByQuestionNumber(questionNumber); return questionDao.findByQuestionNumber(questionNumber);
} }
@Override
public List<Question> findByWorkArea(WorkArea workArea) {
return questionDao.findByWorkArea(workArea);
}
@Override @Override
public List<Question> findCommonQuestions() { public List<Question> findCommonQuestions() {
return questionDao.findCommonQuestions(); return questionDao.findCommonQuestions();
@ -75,6 +69,11 @@ public class QuestionServiceImpl implements QuestionService {
@Override @Override
public Optional<Question> getNextQuestion(Long userId, Integer currentQuestionNumber, List<String> selectedOptions) { public Optional<Question> getNextQuestion(Long userId, Integer currentQuestionNumber, List<String> selectedOptions) {
// 如果当前问题序号为0返回第一个问题
if (currentQuestionNumber == 0) {
return findByQuestionNumber(1);
}
// 获取当前问题 // 获取当前问题
Optional<Question> currentQuestion = findByQuestionNumber(currentQuestionNumber); Optional<Question> currentQuestion = findByQuestionNumber(currentQuestionNumber);
if (currentQuestion.isEmpty()) { if (currentQuestion.isEmpty()) {
@ -82,21 +81,17 @@ public class QuestionServiceImpl implements QuestionService {
} }
// 如果当前问题有跳转逻辑则根据选项判断下一个问题 // 如果当前问题有跳转逻辑则根据选项判断下一个问题
String nextQuestionLogic = currentQuestion.get().getNextQuestionLogic(); Map<String, Integer> next = currentQuestion.get().getNext();
if (nextQuestionLogic != null && !nextQuestionLogic.isEmpty()) { if (next != null && !next.isEmpty() && selectedOptions != null && !selectedOptions.isEmpty()) {
try { // 根据选项确定下一个问题序号
// 解析跳转逻辑JSON for (String option : selectedOptions) {
Map<String, Integer> logic = objectMapper.readValue(nextQuestionLogic, if (next.containsKey(option)) {
new TypeReference<Map<String, Integer>>() {}); return findByQuestionNumber(next.get(option));
// 根据选项确定下一个问题序号
for (String option : selectedOptions) {
if (logic.containsKey(option)) {
return findByQuestionNumber(logic.get(option));
}
} }
} catch (Exception e) { }
// JSON解析错误继续使用默认的下一个问题 // 如果有通配符跳转规则
if (next.containsKey("*")) {
return findByQuestionNumber(next.get("*"));
} }
} }
@ -115,13 +110,10 @@ public class QuestionServiceImpl implements QuestionService {
} }
// 添加通用问题 // 添加通用问题
questions.addAll(findCommonQuestions()); questions.addAll(findAll());
// 添加针对用户工作领域的问题
questions.addAll(findByWorkArea(user.get().getWorkArea()));
// 按问题序号排序 // 按问题序号排序
questions.sort((q1, q2) -> q1.getQuestionNumber().compareTo(q2.getQuestionNumber())); questions.sort((q1, q2) -> q1.getNumber().compareTo(q2.getNumber()));
return questions; return questions;
} }

View File

@ -89,7 +89,7 @@ public class SurveyResponseServiceImpl implements SurveyResponseService {
.anyMatch(response -> response.getQuestionId().equals(question.getId())); .anyMatch(response -> response.getQuestionId().equals(question.getId()));
if (!answered) { if (!answered) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
String.format("问题 %d 为必答题,请填写答案", question.getQuestionNumber())); String.format("问题 %d 为必答题,请填写答案", question.getNumber()));
} }
} }
} }

View File

@ -6,7 +6,6 @@ import java.util.Optional;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import ltd.qubit.survey.dao.UserDao; import ltd.qubit.survey.dao.UserDao;
import ltd.qubit.survey.model.User; import ltd.qubit.survey.model.User;
import ltd.qubit.survey.model.WorkArea;
import ltd.qubit.survey.service.UserService; import ltd.qubit.survey.service.UserService;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -51,11 +50,6 @@ public class UserServiceImpl implements UserService {
return userDao.findByPhone(phone); return userDao.findByPhone(phone);
} }
@Override
public List<User> findByWorkArea(WorkArea workArea) {
return userDao.findByWorkArea(workArea);
}
@Override @Override
public User register(User user) { public User register(User user) {
// 检查手机号是否已注册 // 检查手机号是否已注册

View File

@ -7,22 +7,23 @@
<result property="number" column="number"/> <result property="number" column="number"/>
<result property="content" column="content"/> <result property="content" column="content"/>
<result property="type" column="type"/> <result property="type" column="type"/>
<result property="workArea" column="work_area"/>
<result property="isRequired" column="is_required"/> <result property="isRequired" column="is_required"/>
<result property="next" column="next" typeHandler="ltd.qubit.survey.common.mybatis.JsonTypeHandler"/> <result property="next" column="next" typeHandler="ltd.qubit.survey.common.mybatis.JsonTypeHandler"/>
<result property="isLast" column="is_last"/>
<result property="createdAt" column="created_at"/> <result property="createdAt" column="created_at"/>
</resultMap> </resultMap>
<!-- 基础列 --> <!-- 基础列 -->
<sql id="baseColumns"> <sql id="baseColumns">
`id`, `number`, `content`, `type`, `work_area`, `is_required`, `next`, `created_at` `id`, `number`, `content`, `type`, `is_required`, `next`, `is_last`, `created_at`
</sql> </sql>
<!-- 插入 --> <!-- 插入 -->
<insert id="insert" parameterType="ltd.qubit.survey.model.Question" useGeneratedKeys="true" keyProperty="id"> <insert id="insert" parameterType="ltd.qubit.survey.model.Question" useGeneratedKeys="true" keyProperty="id">
INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`, `next`) INSERT INTO `question` (`number`, `content`, `type`, `is_required`, `next`, `is_last`)
VALUES (#{number}, #{content}, #{type}, #{workArea}, #{isRequired}, VALUES (#{number}, #{content}, #{type}, #{isRequired},
#{next,typeHandler=ltd.qubit.survey.common.mybatis.JsonTypeHandler}) #{next,typeHandler=ltd.qubit.survey.common.mybatis.JsonTypeHandler},
#{isLast})
</insert> </insert>
<!-- 更新 --> <!-- 更新 -->
@ -31,9 +32,9 @@
SET `number` = #{number}, SET `number` = #{number},
`content` = #{content}, `content` = #{content},
`type` = #{type}, `type` = #{type},
`work_area` = #{workArea},
`is_required` = #{isRequired}, `is_required` = #{isRequired},
`next` = #{next,typeHandler=ltd.qubit.survey.common.mybatis.JsonTypeHandler} `next` = #{next,typeHandler=ltd.qubit.survey.common.mybatis.JsonTypeHandler},
`is_last` = #{isLast}
WHERE `id` = #{id} WHERE `id` = #{id}
</update> </update>
@ -63,19 +64,10 @@
WHERE `number` = #{number} WHERE `number` = #{number}
</select> </select>
<!-- 根据工作领域查询 -->
<select id="findByWorkArea" parameterType="string" resultMap="questionMap">
SELECT <include refid="baseColumns"/>
FROM `question`
WHERE `work_area` = #{workArea}
ORDER BY `number`
</select>
<!-- 查询通用问题 --> <!-- 查询通用问题 -->
<select id="findCommonQuestions" resultMap="questionMap"> <select id="findCommonQuestions" resultMap="questionMap">
SELECT <include refid="baseColumns"/> SELECT <include refid="baseColumns"/>
FROM `question` FROM `question`
WHERE `work_area` IS NULL
ORDER BY `number` ORDER BY `number`
</select> </select>

View File

@ -55,12 +55,4 @@
FROM `user` FROM `user`
WHERE `phone` = #{phone} WHERE `phone` = #{phone}
</select> </select>
<!-- 根据工作领域查询 -->
<select id="findByWorkArea" parameterType="string" resultMap="userMap">
SELECT <include refid="baseColumns"/>
FROM `user`
WHERE `work_area` = #{workArea}
ORDER BY `id`
</select>
</mapper> </mapper>

View File

@ -2,7 +2,7 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="ltd.qubit.survey.dao.OptionDao"> <mapper namespace="ltd.qubit.survey.dao.OptionDao">
<!-- 结果映射 --> <!-- 结果映射 -->
<resultMap id="baseOptionMap" type="ltd.qubit.survey.model.Option"> <resultMap id="optionMap" type="ltd.qubit.survey.model.Option">
<id property="id" column="id"/> <id property="id" column="id"/>
<result property="questionId" column="question_id"/> <result property="questionId" column="question_id"/>
<result property="optionCode" column="option_code"/> <result property="optionCode" column="option_code"/>
@ -13,18 +13,18 @@
<!-- 基础列 --> <!-- 基础列 -->
<sql id="baseColumns"> <sql id="baseColumns">
id, question_id, option_code, content, requires_text, created_at `id`, `question_id`, `option_code`, `content`, `requires_text`, `created_at`
</sql> </sql>
<!-- 插入 --> <!-- 插入 -->
<insert id="insert" parameterType="ltd.qubit.survey.model.Option" useGeneratedKeys="true" keyProperty="id"> <insert id="insert" parameterType="ltd.qubit.survey.model.Option" useGeneratedKeys="true" keyProperty="id">
INSERT INTO options (question_id, option_code, content, requires_text) INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`)
VALUES (#{questionId}, #{optionCode}, #{content}, #{requiresText}) VALUES (#{questionId}, #{optionCode}, #{content}, #{requiresText})
</insert> </insert>
<!-- 批量插入 --> <!-- 批量插入 -->
<insert id="batchInsert" parameterType="java.util.List"> <insert id="batchInsert" parameterType="java.util.List">
INSERT INTO options (question_id, option_code, content, requires_text) INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`)
VALUES VALUES
<foreach collection="list" item="item" separator=","> <foreach collection="list" item="item" separator=",">
(#{item.questionId}, #{item.optionCode}, #{item.content}, #{item.requiresText}) (#{item.questionId}, #{item.optionCode}, #{item.content}, #{item.requiresText})
@ -33,51 +33,51 @@
<!-- 更新 --> <!-- 更新 -->
<update id="update" parameterType="ltd.qubit.survey.model.Option"> <update id="update" parameterType="ltd.qubit.survey.model.Option">
UPDATE options UPDATE `option`
SET question_id = #{questionId}, SET `question_id` = #{questionId},
option_code = #{optionCode}, `option_code` = #{optionCode},
content = #{content}, `content` = #{content},
requires_text = #{requiresText} `requires_text` = #{requiresText}
WHERE id = #{id} WHERE `id` = #{id}
</update> </update>
<!-- 删除 --> <!-- 删除 -->
<delete id="deleteById" parameterType="long"> <delete id="deleteById" parameterType="long">
DELETE FROM options WHERE id = #{id} DELETE FROM `option` WHERE `id` = #{id}
</delete> </delete>
<!-- 根据问题ID删除 --> <!-- 根据问题ID删除 -->
<delete id="deleteByQuestionId" parameterType="long"> <delete id="deleteByQuestionId" parameterType="long">
DELETE FROM options WHERE question_id = #{questionId} DELETE FROM `option` WHERE `question_id` = #{questionId}
</delete> </delete>
<!-- 根据ID查询 --> <!-- 根据ID查询 -->
<select id="findById" parameterType="long" resultMap="baseOptionMap"> <select id="findById" parameterType="long" resultMap="optionMap">
SELECT <include refid="baseColumns"/> SELECT <include refid="baseColumns"/>
FROM options FROM `option`
WHERE id = #{id} WHERE `id` = #{id}
</select> </select>
<!-- 查询所有 --> <!-- 查询所有 -->
<select id="findAll" resultMap="baseOptionMap"> <select id="findAll" resultMap="optionMap">
SELECT <include refid="baseColumns"/> SELECT <include refid="baseColumns"/>
FROM options FROM `option`
ORDER BY question_id, option_code ORDER BY `question_id`, `option_code`
</select> </select>
<!-- 根据问题ID查询 --> <!-- 根据问题ID查询 -->
<select id="findByQuestionId" parameterType="long" resultMap="baseOptionMap"> <select id="findByQuestionId" parameterType="long" resultMap="optionMap">
SELECT <include refid="baseColumns"/> SELECT <include refid="baseColumns"/>
FROM options FROM `option`
WHERE question_id = #{questionId} WHERE `question_id` = #{questionId}
ORDER BY option_code ORDER BY `option_code`
</select> </select>
<!-- 根据问题ID和选项代码查询 --> <!-- 根据问题ID和选项代码查询 -->
<select id="findByQuestionIdAndCode" resultMap="baseOptionMap"> <select id="findByQuestionIdAndOptionCode" resultMap="optionMap">
SELECT <include refid="baseColumns"/> SELECT <include refid="baseColumns"/>
FROM options FROM `option`
WHERE question_id = #{questionId} WHERE `question_id` = #{questionId}
AND option_code = #{optionCode} AND `option_code` = #{optionCode}
</select> </select>
</mapper> </mapper>

View File

@ -4,83 +4,76 @@
<!-- 结果映射 --> <!-- 结果映射 -->
<resultMap id="questionMap" type="ltd.qubit.survey.model.Question"> <resultMap id="questionMap" type="ltd.qubit.survey.model.Question">
<id property="id" column="id"/> <id property="id" column="id"/>
<result property="questionNumber" column="question_number"/> <result property="number" column="number"/>
<result property="content" column="content"/> <result property="content" column="content"/>
<result property="questionType" column="question_type"/> <result property="type" column="type"/>
<result property="workArea" column="work_area"/>
<result property="isRequired" column="is_required"/> <result property="isRequired" column="is_required"/>
<result property="nextQuestionLogic" column="next_question_logic"/> <result property="next" column="next" typeHandler="ltd.qubit.survey.common.mybatis.JsonTypeHandler"/>
<result property="isLast" column="is_last"/>
<result property="createdAt" column="created_at"/> <result property="createdAt" column="created_at"/>
</resultMap> </resultMap>
<!-- 基础列 --> <!-- 基础列 -->
<sql id="baseColumns"> <sql id="baseColumns">
id, question_number, content, question_type, work_area, is_required, next_question_logic, created_at `id`, `number`, `content`, `type`, `is_required`, `next`, `is_last`, `created_at`
</sql> </sql>
<!-- 插入 --> <!-- 插入 -->
<insert id="insert" parameterType="ltd.qubit.survey.model.Question" useGeneratedKeys="true" keyProperty="id"> <insert id="insert" parameterType="ltd.qubit.survey.model.Question" useGeneratedKeys="true" keyProperty="id">
INSERT INTO questions (question_number, content, question_type, work_area, is_required, next_question_logic) INSERT INTO `question` (`number`, `content`, `type`, `is_required`, `next`, `is_last`)
VALUES (#{questionNumber}, #{content}, #{questionType}, #{workArea}, #{isRequired}, #{nextQuestionLogic}) VALUES (#{number}, #{content}, #{type}, #{isRequired},
#{next,typeHandler=ltd.qubit.survey.common.mybatis.JsonTypeHandler},
#{isLast})
</insert> </insert>
<!-- 更新 --> <!-- 更新 -->
<update id="update" parameterType="ltd.qubit.survey.model.Question"> <update id="update" parameterType="ltd.qubit.survey.model.Question">
UPDATE questions UPDATE `question`
SET question_number = #{questionNumber}, SET `number` = #{number},
content = #{content}, `content` = #{content},
question_type = #{questionType}, `type` = #{type},
work_area = #{workArea}, `is_required` = #{isRequired},
is_required = #{isRequired}, `next` = #{next,typeHandler=ltd.qubit.survey.common.mybatis.JsonTypeHandler},
next_question_logic = #{nextQuestionLogic} `is_last` = #{isLast}
WHERE id = #{id} WHERE `id` = #{id}
</update> </update>
<!-- 删除 --> <!-- 删除 -->
<delete id="deleteById" parameterType="long"> <delete id="deleteById" parameterType="long">
DELETE FROM questions WHERE id = #{id} DELETE FROM `question` WHERE `id` = #{id}
</delete> </delete>
<!-- 根据ID查询 --> <!-- 根据ID查询 -->
<select id="findById" parameterType="long" resultMap="questionMap"> <select id="findById" parameterType="long" resultMap="questionMap">
SELECT <include refid="baseColumns"/> SELECT <include refid="baseColumns"/>
FROM questions FROM `question`
WHERE id = #{id} WHERE `id` = #{id}
</select> </select>
<!-- 查询所有 --> <!-- 查询所有 -->
<select id="findAll" resultMap="questionMap"> <select id="findAll" resultMap="questionMap">
SELECT <include refid="baseColumns"/> SELECT <include refid="baseColumns"/>
FROM questions FROM `question`
ORDER BY question_number ORDER BY `number`
</select> </select>
<!-- 根据问题序号查询 --> <!-- 根据问题序号查询 -->
<select id="findByQuestionNumber" parameterType="int" resultMap="questionMap"> <select id="findByQuestionNumber" parameterType="int" resultMap="questionMap">
SELECT <include refid="baseColumns"/> SELECT <include refid="baseColumns"/>
FROM questions FROM `question`
WHERE question_number = #{questionNumber} WHERE `number` = #{number}
</select>
<!-- 根据工作领域查询 -->
<select id="findByWorkArea" parameterType="string" resultMap="questionMap">
SELECT <include refid="baseColumns"/>
FROM questions
WHERE work_area = #{workArea}
ORDER BY question_number
</select> </select>
<!-- 查询通用问题 --> <!-- 查询通用问题 -->
<select id="findCommonQuestions" resultMap="questionMap"> <select id="findCommonQuestions" resultMap="questionMap">
SELECT <include refid="baseColumns"/> SELECT <include refid="baseColumns"/>
FROM questions FROM `question`
WHERE work_area IS NULL ORDER BY `number`
ORDER BY question_number
</select> </select>
<!-- 获取下一个问题序号 --> <!-- 获取下一个问题序号 -->
<select id="getNextQuestionNumber" resultType="int"> <select id="getNextQuestionNumber" resultType="int">
SELECT COALESCE(MAX(question_number) + 1, 1) SELECT COALESCE(MAX(`number`) + 1, 1)
FROM questions FROM `question`
</select> </select>
</mapper> </mapper>

View File

@ -13,18 +13,18 @@
<!-- 基础列 --> <!-- 基础列 -->
<sql id="baseColumns"> <sql id="baseColumns">
id, user_id, question_id, selected_options, text_answer, created_at `id`, `user_id`, `question_id`, `selected_options`, `text_answer`, `created_at`
</sql> </sql>
<!-- 插入 --> <!-- 插入 -->
<insert id="insert" parameterType="ltd.qubit.survey.model.SurveyResponse" useGeneratedKeys="true" keyProperty="id"> <insert id="insert" parameterType="ltd.qubit.survey.model.SurveyResponse" useGeneratedKeys="true" keyProperty="id">
INSERT INTO survey_responses (user_id, question_id, selected_options, text_answer) 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> </insert>
<!-- 批量插入 --> <!-- 批量插入 -->
<insert id="batchInsert" parameterType="java.util.List"> <insert id="batchInsert" parameterType="java.util.List">
INSERT INTO survey_responses (user_id, question_id, selected_options, text_answer) INSERT INTO `survey_response` (`user_id`, `question_id`, `selected_options`, `text_answer`)
VALUES VALUES
<foreach collection="list" item="item" separator=","> <foreach collection="list" item="item" separator=",">
(#{item.userId}, #{item.questionId}, (#{item.userId}, #{item.questionId},
@ -35,59 +35,59 @@
<!-- 更新 --> <!-- 更新 -->
<update id="update" parameterType="ltd.qubit.survey.model.SurveyResponse"> <update id="update" parameterType="ltd.qubit.survey.model.SurveyResponse">
UPDATE survey_responses UPDATE `survey_response`
SET user_id = #{userId}, SET `user_id` = #{userId},
question_id = #{questionId}, `question_id` = #{questionId},
selected_options = #{selectedOptions,typeHandler=ltd.qubit.survey.common.mybatis.JsonTypeHandler}, `selected_options` = #{selectedOptions,typeHandler=ltd.qubit.survey.common.mybatis.JsonTypeHandler},
text_answer = #{textAnswer} `text_answer` = #{textAnswer}
WHERE id = #{id} WHERE `id` = #{id}
</update> </update>
<!-- 删除 --> <!-- 删除 -->
<delete id="deleteById" parameterType="long"> <delete id="deleteById" parameterType="long">
DELETE FROM survey_responses WHERE id = #{id} DELETE FROM `survey_response` WHERE `id` = #{id}
</delete> </delete>
<!-- 根据用户ID删除 --> <!-- 根据用户ID删除 -->
<delete id="deleteByUserId" parameterType="long"> <delete id="deleteByUserId" parameterType="long">
DELETE FROM survey_responses WHERE user_id = #{userId} DELETE FROM `survey_response` WHERE `user_id` = #{userId}
</delete> </delete>
<!-- 根据ID查询 --> <!-- 根据ID查询 -->
<select id="findById" parameterType="long" resultMap="responseMap"> <select id="findById" parameterType="long" resultMap="responseMap">
SELECT <include refid="baseColumns"/> SELECT <include refid="baseColumns"/>
FROM survey_responses FROM `survey_response`
WHERE id = #{id} WHERE `id` = #{id}
</select> </select>
<!-- 查询所有 --> <!-- 查询所有 -->
<select id="findAll" resultMap="responseMap"> <select id="findAll" resultMap="responseMap">
SELECT <include refid="baseColumns"/> SELECT <include refid="baseColumns"/>
FROM survey_responses FROM `survey_response`
ORDER BY user_id, question_id ORDER BY `user_id`, `question_id`
</select> </select>
<!-- 根据用户ID查询 --> <!-- 根据用户ID查询 -->
<select id="findByUserId" parameterType="long" resultMap="responseMap"> <select id="findByUserId" parameterType="long" resultMap="responseMap">
SELECT <include refid="baseColumns"/> SELECT <include refid="baseColumns"/>
FROM survey_responses FROM `survey_response`
WHERE user_id = #{userId} WHERE `user_id` = #{userId}
ORDER BY question_id ORDER BY `question_id`
</select> </select>
<!-- 根据问题ID查询 --> <!-- 根据问题ID查询 -->
<select id="findByQuestionId" parameterType="long" resultMap="responseMap"> <select id="findByQuestionId" parameterType="long" resultMap="responseMap">
SELECT <include refid="baseColumns"/> SELECT <include refid="baseColumns"/>
FROM survey_responses FROM `survey_response`
WHERE question_id = #{questionId} WHERE `question_id` = #{questionId}
ORDER BY user_id ORDER BY `user_id`
</select> </select>
<!-- 根据用户ID和问题ID查询 --> <!-- 根据用户ID和问题ID查询 -->
<select id="findByUserIdAndQuestionId" resultMap="responseMap"> <select id="findByUserIdAndQuestionId" resultMap="responseMap">
SELECT <include refid="baseColumns"/> SELECT <include refid="baseColumns"/>
FROM survey_responses FROM `survey_response`
WHERE user_id = #{userId} WHERE `user_id` = #{userId}
AND question_id = #{questionId} AND `question_id` = #{questionId}
</select> </select>
</mapper> </mapper>

View File

@ -6,63 +6,53 @@
<id property="id" column="id"/> <id property="id" column="id"/>
<result property="name" column="name"/> <result property="name" column="name"/>
<result property="phone" column="phone"/> <result property="phone" column="phone"/>
<result property="workArea" column="work_area"/>
<result property="positionType" column="position_type"/> <result property="positionType" column="position_type"/>
<result property="createdAt" column="created_at"/> <result property="createdAt" column="created_at"/>
</resultMap> </resultMap>
<!-- 基础列 --> <!-- 基础列 -->
<sql id="baseColumns"> <sql id="baseColumns">
id, name, phone, work_area, position_type, created_at `id`, `name`, `phone`, `position_type`, `created_at`
</sql> </sql>
<!-- 插入 --> <!-- 插入 -->
<insert id="insert" parameterType="ltd.qubit.survey.model.User" useGeneratedKeys="true" keyProperty="id"> <insert id="insert" parameterType="ltd.qubit.survey.model.User" useGeneratedKeys="true" keyProperty="id">
INSERT INTO users (name, phone, work_area, position_type) INSERT INTO `user` (`name`, `phone`, `position_type`)
VALUES (#{name}, #{phone}, #{workArea}, #{positionType}) VALUES (#{name}, #{phone}, #{positionType})
</insert> </insert>
<!-- 更新 --> <!-- 更新 -->
<update id="update" parameterType="ltd.qubit.survey.model.User"> <update id="update" parameterType="ltd.qubit.survey.model.User">
UPDATE users UPDATE `user`
SET name = #{name}, SET `name` = #{name},
phone = #{phone}, `phone` = #{phone},
work_area = #{workArea}, `position_type` = #{positionType}
position_type = #{positionType} WHERE `id` = #{id}
WHERE id = #{id}
</update> </update>
<!-- 删除 --> <!-- 删除 -->
<delete id="deleteById" parameterType="long"> <delete id="deleteById" parameterType="long">
DELETE FROM users WHERE id = #{id} DELETE FROM `user` WHERE `id` = #{id}
</delete> </delete>
<!-- 根据ID查询 --> <!-- 根据ID查询 -->
<select id="findById" parameterType="long" resultMap="userMap"> <select id="findById" parameterType="long" resultMap="userMap">
SELECT <include refid="baseColumns"/> SELECT <include refid="baseColumns"/>
FROM users FROM `user`
WHERE id = #{id} WHERE `id` = #{id}
</select> </select>
<!-- 查询所有 --> <!-- 查询所有 -->
<select id="findAll" resultMap="userMap"> <select id="findAll" resultMap="userMap">
SELECT <include refid="baseColumns"/> SELECT <include refid="baseColumns"/>
FROM users FROM `user`
ORDER BY id ORDER BY `id`
</select> </select>
<!-- 根据手机号查询 --> <!-- 根据手机号查询 -->
<select id="findByPhone" parameterType="string" resultMap="userMap"> <select id="findByPhone" parameterType="string" resultMap="userMap">
SELECT <include refid="baseColumns"/> SELECT <include refid="baseColumns"/>
FROM users FROM `user`
WHERE phone = #{phone} WHERE `phone` = #{phone}
</select>
<!-- 根据工作领域查询 -->
<select id="findByWorkArea" parameterType="string" resultMap="userMap">
SELECT <include refid="baseColumns"/>
FROM users
WHERE work_area = #{workArea}
ORDER BY id
</select> </select>
</mapper> </mapper>

View File

@ -15,7 +15,6 @@ ltd/qubit/survey/utils/CustomObjectMapper.class
ltd/qubit/survey/model/User.class ltd/qubit/survey/model/User.class
ltd/qubit/survey/service/QuestionService.class ltd/qubit/survey/service/QuestionService.class
ltd/qubit/survey/common/mybatis/JsonTypeHandler.class ltd/qubit/survey/common/mybatis/JsonTypeHandler.class
ltd/qubit/survey/service/impl/QuestionServiceImpl$1.class
ltd/qubit/survey/service/UserService.class ltd/qubit/survey/service/UserService.class
ltd/qubit/survey/dao/BaseDao.class ltd/qubit/survey/dao/BaseDao.class
ltd/qubit/survey/service/impl/OptionServiceImpl.class ltd/qubit/survey/service/impl/OptionServiceImpl.class

View File

@ -3,6 +3,12 @@ CREATE DATABASE IF NOT EXISTS `llm_survey` DEFAULT CHARACTER SET utf8mb4 COLLATE
USE `llm_survey`; USE `llm_survey`;
-- 删除旧表(如果存在)
DROP TABLE IF EXISTS `survey_response`;
DROP TABLE IF EXISTS `option`;
DROP TABLE IF EXISTS `question`;
DROP TABLE IF EXISTS `user`;
-- 创建用户表 -- 创建用户表
CREATE TABLE IF NOT EXISTS `user` ( CREATE TABLE IF NOT EXISTS `user` (
`id` BIGINT PRIMARY KEY AUTO_INCREMENT, `id` BIGINT PRIMARY KEY AUTO_INCREMENT,
@ -22,6 +28,7 @@ CREATE TABLE IF NOT EXISTS `question` (
`work_area` VARCHAR(20) DEFAULT NULL COMMENT '针对的工作领域', `work_area` VARCHAR(20) DEFAULT NULL COMMENT '针对的工作领域',
`is_required` BOOLEAN NOT NULL DEFAULT TRUE COMMENT '是否必答', `is_required` BOOLEAN NOT NULL DEFAULT TRUE COMMENT '是否必答',
`next` JSON DEFAULT NULL COMMENT '跳转逻辑', `next` JSON DEFAULT NULL COMMENT '跳转逻辑',
`is_last` BOOLEAN NOT NULL DEFAULT FALSE COMMENT '是否是最后一题',
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
UNIQUE KEY `uk_number` (`number`) UNIQUE KEY `uk_number` (`number`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='问题表'; ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='问题表';
@ -59,8 +66,8 @@ TRUNCATE TABLE `user`;
SET FOREIGN_KEY_CHECKS = 1; SET FOREIGN_KEY_CHECKS = 1;
-- 插入通用认知问题 -- 插入通用认知问题
INSERT INTO `question` (`number`, `content`, `type`, `is_required`) INSERT INTO `question` (`number`, `content`, `type`, `is_required`, `is_last`)
VALUES (1, '您对大模型如ChatGPT、通义千问、DeepSeek的了解程度', 'SINGLE_CHOICE', TRUE); VALUES (1, '您对大模型如ChatGPT、通义千问、DeepSeek的了解程度', 'SINGLE_CHOICE', TRUE, FALSE);
INSERT INTO `option` (`question_id`, `option_code`, `content`) VALUES INSERT INTO `option` (`question_id`, `option_code`, `content`) VALUES
(LAST_INSERT_ID(), 'A', '从未接触过'), (LAST_INSERT_ID(), 'A', '从未接触过'),
@ -68,8 +75,8 @@ INSERT INTO `option` (`question_id`, `option_code`, `content`) VALUES
(LAST_INSERT_ID(), 'C', '在工作中尝试过基础应用'), (LAST_INSERT_ID(), 'C', '在工作中尝试过基础应用'),
(LAST_INSERT_ID(), 'D', '深度研究过技术原理'); (LAST_INSERT_ID(), 'D', '深度研究过技术原理');
INSERT INTO `question` (`number`, `content`, `type`, `is_required`) INSERT INTO `question` (`number`, `content`, `type`, `is_required`, `is_last`)
VALUES (2, '您觉得大模型可以做到下面哪些事?', 'MULTIPLE_CHOICE', TRUE); VALUES (2, '您觉得大模型可以做到下面哪些事?', 'MULTIPLE_CHOICE', TRUE, FALSE);
INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES
(LAST_INSERT_ID(), 'A', '精准知识问答', FALSE), (LAST_INSERT_ID(), 'A', '精准知识问答', FALSE),
@ -80,8 +87,8 @@ INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`)
(LAST_INSERT_ID(), 'F', '流程自动化', FALSE), (LAST_INSERT_ID(), 'F', '流程自动化', FALSE),
(LAST_INSERT_ID(), 'G', '其他', TRUE); (LAST_INSERT_ID(), 'G', '其他', TRUE);
INSERT INTO `question` (`number`, `content`, `type`, `is_required`) INSERT INTO `question` (`number`, `content`, `type`, `is_required`, `is_last`)
VALUES (3, '您最关注大模型应用的哪些风险?', 'MULTIPLE_CHOICE', TRUE); VALUES (3, '您最关注大模型应用的哪些风险?', 'MULTIPLE_CHOICE', TRUE, FALSE);
INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES
(LAST_INSERT_ID(), 'A', '数据隐私泄露', FALSE), (LAST_INSERT_ID(), 'A', '数据隐私泄露', FALSE),
@ -90,8 +97,8 @@ INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`)
(LAST_INSERT_ID(), 'D', '技术使用门槛高', FALSE), (LAST_INSERT_ID(), 'D', '技术使用门槛高', FALSE),
(LAST_INSERT_ID(), 'E', '其他', TRUE); (LAST_INSERT_ID(), 'E', '其他', TRUE);
INSERT INTO `question` (`number`, `content`, `type`, `is_required`) INSERT INTO `question` (`number`, `content`, `type`, `is_required`, `is_last`)
VALUES (4, '您的主要工作内容是:', 'SINGLE_CHOICE', TRUE); VALUES (4, '您的主要工作内容是:', 'SINGLE_CHOICE', TRUE, FALSE);
INSERT INTO `option` (`question_id`, `option_code`, `content`) VALUES INSERT INTO `option` (`question_id`, `option_code`, `content`) VALUES
(LAST_INSERT_ID(), 'A', '研发(产品、开发、算法、测试、运维等)'), (LAST_INSERT_ID(), 'A', '研发(产品、开发、算法、测试、运维等)'),
@ -106,8 +113,8 @@ INSERT INTO `option` (`question_id`, `option_code`, `content`) VALUES
(LAST_INSERT_ID(), 'J', '公司高管(战略规划、组织架构、制度建设等)'); (LAST_INSERT_ID(), 'J', '公司高管(战略规划、组织架构、制度建设等)');
-- 研发部门专属问题 -- 研发部门专属问题
INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`) INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`, `is_last`)
VALUES (5, '您在开发过程中最耗时的重复性工作:', 'MULTIPLE_CHOICE', 'RD', TRUE); VALUES (5, '您在开发过程中最耗时的重复性工作:', 'MULTIPLE_CHOICE', 'RD', TRUE, FALSE);
INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES
(LAST_INSERT_ID(), 'A', '文档编写(如需求文档、技术文档等)', FALSE), (LAST_INSERT_ID(), 'A', '文档编写(如需求文档、技术文档等)', FALSE),
@ -117,8 +124,8 @@ INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`)
(LAST_INSERT_ID(), 'E', '系统监控与维护', FALSE), (LAST_INSERT_ID(), 'E', '系统监控与维护', FALSE),
(LAST_INSERT_ID(), 'F', '其他', TRUE); (LAST_INSERT_ID(), 'F', '其他', TRUE);
INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`) INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`, `is_last`)
VALUES (6, '您希望大模型如何与现有系统集成:', 'MULTIPLE_CHOICE', 'RD', TRUE); VALUES (6, '您希望大模型如何与现有系统集成:', 'MULTIPLE_CHOICE', 'RD', TRUE, FALSE);
INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES
(LAST_INSERT_ID(), 'A', '回答技术问题', FALSE), (LAST_INSERT_ID(), 'A', '回答技术问题', FALSE),
@ -131,8 +138,8 @@ INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`)
(LAST_INSERT_ID(), 'H', '其他', TRUE); (LAST_INSERT_ID(), 'H', '其他', TRUE);
-- 项目管理专属问题 -- 项目管理专属问题
INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`) INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`, `is_last`)
VALUES (7, '项目管理中最常遇到的挑战是:', 'MULTIPLE_CHOICE', 'PROJECT', TRUE); VALUES (7, '项目管理中最常遇到的挑战是:', 'MULTIPLE_CHOICE', 'PROJECT', TRUE, FALSE);
INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES
(LAST_INSERT_ID(), 'A', '项目进度跟踪与更新', FALSE), (LAST_INSERT_ID(), 'A', '项目进度跟踪与更新', FALSE),
@ -140,8 +147,8 @@ INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`)
(LAST_INSERT_ID(), 'C', '项目报告生成', FALSE), (LAST_INSERT_ID(), 'C', '项目报告生成', FALSE),
(LAST_INSERT_ID(), 'D', '其他', TRUE); (LAST_INSERT_ID(), 'D', '其他', TRUE);
INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`) INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`, `is_last`)
VALUES (8, '您希望如何利用大模型提升项目管理效率:', 'MULTIPLE_CHOICE', 'PROJECT', TRUE); VALUES (8, '您希望如何利用大模型提升项目管理效率:', 'MULTIPLE_CHOICE', 'PROJECT', TRUE, FALSE);
INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES
(LAST_INSERT_ID(), 'A', '自动生成立项报告、进度报告、总结报告等', FALSE), (LAST_INSERT_ID(), 'A', '自动生成立项报告、进度报告、总结报告等', FALSE),
@ -151,8 +158,8 @@ INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`)
(LAST_INSERT_ID(), 'E', '其他', TRUE); (LAST_INSERT_ID(), 'E', '其他', TRUE);
-- 保险专属问题 -- 保险专属问题
INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`) INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`, `is_last`)
VALUES (9, '理赔处理中的主要瓶颈是:', 'MULTIPLE_CHOICE', 'INSURANCE', TRUE); VALUES (9, '理赔处理中的主要瓶颈是:', 'MULTIPLE_CHOICE', 'INSURANCE', TRUE, FALSE);
INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES
(LAST_INSERT_ID(), 'A', '理赔文档处理', FALSE), (LAST_INSERT_ID(), 'A', '理赔文档处理', FALSE),
@ -161,8 +168,8 @@ INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`)
(LAST_INSERT_ID(), 'D', '理赔规则理解与应用', FALSE), (LAST_INSERT_ID(), 'D', '理赔规则理解与应用', FALSE),
(LAST_INSERT_ID(), 'E', '其他', TRUE); (LAST_INSERT_ID(), 'E', '其他', TRUE);
INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`) INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`, `is_last`)
VALUES (10, '大模型可以优化哪些保险工作环节:', 'MULTIPLE_CHOICE', 'INSURANCE', TRUE); VALUES (10, '大模型可以优化哪些保险工作环节:', 'MULTIPLE_CHOICE', 'INSURANCE', TRUE, FALSE);
INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES
(LAST_INSERT_ID(), 'A', '新员工入职培训', FALSE), (LAST_INSERT_ID(), 'A', '新员工入职培训', FALSE),
@ -173,8 +180,8 @@ INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`)
(LAST_INSERT_ID(), 'F', '其他', TRUE); (LAST_INSERT_ID(), 'F', '其他', TRUE);
-- 财务专属问题 -- 财务专属问题
INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`) INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`, `is_last`)
VALUES (11, '日常工作中最重复的任务是:', 'MULTIPLE_CHOICE', 'FINANCE', TRUE); VALUES (11, '日常工作中最重复的任务是:', 'MULTIPLE_CHOICE', 'FINANCE', TRUE, FALSE);
INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES
(LAST_INSERT_ID(), 'A', '财务数据整理与报表生成', FALSE), (LAST_INSERT_ID(), 'A', '财务数据整理与报表生成', FALSE),
@ -182,8 +189,8 @@ INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`)
(LAST_INSERT_ID(), 'C', '财务审计与合规检查', FALSE), (LAST_INSERT_ID(), 'C', '财务审计与合规检查', FALSE),
(LAST_INSERT_ID(), 'D', '其他', TRUE); (LAST_INSERT_ID(), 'D', '其他', TRUE);
INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`) INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`, `is_last`)
VALUES (12, '大模型能如何协助提升财务工作效率:', 'MULTIPLE_CHOICE', 'FINANCE', TRUE); VALUES (12, '大模型能如何协助提升财务工作效率:', 'MULTIPLE_CHOICE', 'FINANCE', TRUE, FALSE);
INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES
(LAST_INSERT_ID(), 'A', '各种报表格式的自动转换', FALSE), (LAST_INSERT_ID(), 'A', '各种报表格式的自动转换', FALSE),
@ -193,8 +200,8 @@ INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`)
(LAST_INSERT_ID(), 'E', '其他', TRUE); (LAST_INSERT_ID(), 'E', '其他', TRUE);
-- 客服专属问题 -- 客服专属问题
INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`) INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`, `is_last`)
VALUES (13, '客户咨询中最常遇到的重复性问题:', 'MULTIPLE_CHOICE', 'CUSTOMER_SERVICE', TRUE); VALUES (13, '客户咨询中最常遇到的重复性问题:', 'MULTIPLE_CHOICE', 'CUSTOMER_SERVICE', TRUE, FALSE);
INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES
(LAST_INSERT_ID(), 'A', '参保资格咨询', FALSE), (LAST_INSERT_ID(), 'A', '参保资格咨询', FALSE),
@ -202,8 +209,8 @@ INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`)
(LAST_INSERT_ID(), 'C', '材料补交通知', FALSE), (LAST_INSERT_ID(), 'C', '材料补交通知', FALSE),
(LAST_INSERT_ID(), 'D', '其他', TRUE); (LAST_INSERT_ID(), 'D', '其他', TRUE);
INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`) INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`, `is_last`)
VALUES (14, '您希望大模型如何辅助客服工作:', 'MULTIPLE_CHOICE', 'CUSTOMER_SERVICE', TRUE); VALUES (14, '您希望大模型如何辅助客服工作:', 'MULTIPLE_CHOICE', 'CUSTOMER_SERVICE', TRUE, FALSE);
INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES
(LAST_INSERT_ID(), 'A', '自动生成客户回复模板', FALSE), (LAST_INSERT_ID(), 'A', '自动生成客户回复模板', FALSE),
@ -212,8 +219,8 @@ INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`)
(LAST_INSERT_ID(), 'D', '其他', TRUE); (LAST_INSERT_ID(), 'D', '其他', TRUE);
-- 运营专属问题 -- 运营专属问题
INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`) INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`, `is_last`)
VALUES (15, '在运营工作中,最需要自动化支持的任务是:', 'MULTIPLE_CHOICE', 'OPERATION', TRUE); VALUES (15, '在运营工作中,最需要自动化支持的任务是:', 'MULTIPLE_CHOICE', 'OPERATION', TRUE, FALSE);
INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES
(LAST_INSERT_ID(), 'A', '热点讯息的获取和跟踪', FALSE), (LAST_INSERT_ID(), 'A', '热点讯息的获取和跟踪', FALSE),
@ -222,8 +229,8 @@ INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`)
(LAST_INSERT_ID(), 'D', '活动效果评估与预测', FALSE), (LAST_INSERT_ID(), 'D', '活动效果评估与预测', FALSE),
(LAST_INSERT_ID(), 'E', '其他', TRUE); (LAST_INSERT_ID(), 'E', '其他', TRUE);
INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`) INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`, `is_last`)
VALUES (16, '大模型可以如何帮助提升运营效率:', 'MULTIPLE_CHOICE', 'OPERATION', TRUE); VALUES (16, '大模型可以如何帮助提升运营效率:', 'MULTIPLE_CHOICE', 'OPERATION', TRUE, FALSE);
INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES
(LAST_INSERT_ID(), 'A', '自动抓取热点讯息', FALSE), (LAST_INSERT_ID(), 'A', '自动抓取热点讯息', FALSE),
@ -233,8 +240,8 @@ INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`)
(LAST_INSERT_ID(), 'E', '其他', TRUE); (LAST_INSERT_ID(), 'E', '其他', TRUE);
-- 市场拓展专属问题 -- 市场拓展专属问题
INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`) INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`, `is_last`)
VALUES (17, '在市场拓展和商务沟通中,您最常遇到的挑战是:', 'MULTIPLE_CHOICE', 'MARKET', TRUE); VALUES (17, '在市场拓展和商务沟通中,您最常遇到的挑战是:', 'MULTIPLE_CHOICE', 'MARKET', TRUE, FALSE);
INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES
(LAST_INSERT_ID(), 'A', '市场分析和竞争对手跟踪', FALSE), (LAST_INSERT_ID(), 'A', '市场分析和竞争对手跟踪', FALSE),
@ -242,8 +249,8 @@ INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`)
(LAST_INSERT_ID(), 'C', '商务沟通中的信息处理与反馈跟踪', FALSE), (LAST_INSERT_ID(), 'C', '商务沟通中的信息处理与反馈跟踪', FALSE),
(LAST_INSERT_ID(), 'D', '其他', TRUE); (LAST_INSERT_ID(), 'D', '其他', TRUE);
INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`) INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`, `is_last`)
VALUES (18, '您希望大模型如何帮助提升市场拓展效率:', 'MULTIPLE_CHOICE', 'MARKET', TRUE); VALUES (18, '您希望大模型如何帮助提升市场拓展效率:', 'MULTIPLE_CHOICE', 'MARKET', TRUE, FALSE);
INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES
(LAST_INSERT_ID(), 'A', '自动生成市场分析报告与趋势预测', FALSE), (LAST_INSERT_ID(), 'A', '自动生成市场分析报告与趋势预测', FALSE),
@ -252,8 +259,8 @@ INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`)
(LAST_INSERT_ID(), 'D', '其他', TRUE); (LAST_INSERT_ID(), 'D', '其他', TRUE);
-- 人力资源专属问题 -- 人力资源专属问题
INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`) INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`, `is_last`)
VALUES (19, '人事部门最耗时的日常任务是:', 'MULTIPLE_CHOICE', 'HR', TRUE); VALUES (19, '人事部门最耗时的日常任务是:', 'MULTIPLE_CHOICE', 'HR', TRUE, FALSE);
INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES
(LAST_INSERT_ID(), 'A', '招聘简历筛选与面试安排', FALSE), (LAST_INSERT_ID(), 'A', '招聘简历筛选与面试安排', FALSE),
@ -261,8 +268,8 @@ INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`)
(LAST_INSERT_ID(), 'C', '绩效评估与报告生成', FALSE), (LAST_INSERT_ID(), 'C', '绩效评估与报告生成', FALSE),
(LAST_INSERT_ID(), 'D', '其他', TRUE); (LAST_INSERT_ID(), 'D', '其他', TRUE);
INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`) INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`, `is_last`)
VALUES (20, '您希望大模型如何协助提升人事工作效率:', 'MULTIPLE_CHOICE', 'HR', TRUE); VALUES (20, '您希望大模型如何协助提升人事工作效率:', 'MULTIPLE_CHOICE', 'HR', TRUE, FALSE);
INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES
(LAST_INSERT_ID(), 'A', '自动筛选招聘简历并推荐候选人', FALSE), (LAST_INSERT_ID(), 'A', '自动筛选招聘简历并推荐候选人', FALSE),
@ -271,8 +278,8 @@ INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`)
(LAST_INSERT_ID(), 'D', '其他', TRUE); (LAST_INSERT_ID(), 'D', '其他', TRUE);
-- 综合管理专属问题 -- 综合管理专属问题
INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`) INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`, `is_last`)
VALUES (21, '在行政工作中,最耗时的任务是:', 'MULTIPLE_CHOICE', 'ADMIN', TRUE); VALUES (21, '在行政工作中,最耗时的任务是:', 'MULTIPLE_CHOICE', 'ADMIN', TRUE, FALSE);
INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES
(LAST_INSERT_ID(), 'A', '合同审查与管理', FALSE), (LAST_INSERT_ID(), 'A', '合同审查与管理', FALSE),
@ -280,8 +287,8 @@ INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`)
(LAST_INSERT_ID(), 'C', '文档管理与更新', FALSE), (LAST_INSERT_ID(), 'C', '文档管理与更新', FALSE),
(LAST_INSERT_ID(), 'D', '其他', TRUE); (LAST_INSERT_ID(), 'D', '其他', TRUE);
INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`) INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`, `is_last`)
VALUES (22, '您希望大模型如何协助提升行政工作效率:', 'MULTIPLE_CHOICE', 'ADMIN', TRUE); VALUES (22, '您希望大模型如何协助提升行政工作效率:', 'MULTIPLE_CHOICE', 'ADMIN', TRUE, FALSE);
INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES
(LAST_INSERT_ID(), 'A', '自动生成合同和协议模板', FALSE), (LAST_INSERT_ID(), 'A', '自动生成合同和协议模板', FALSE),
@ -290,8 +297,8 @@ INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`)
(LAST_INSERT_ID(), 'D', '其他', TRUE); (LAST_INSERT_ID(), 'D', '其他', TRUE);
-- 公司高管专属问题 -- 公司高管专属问题
INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`) INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`, `is_last`)
VALUES (23, '您认为大模型在哪些战略层面的决策中可以发挥作用?', 'MULTIPLE_CHOICE', 'EXECUTIVE', TRUE); VALUES (23, '您认为大模型在哪些战略层面的决策中可以发挥作用?', 'MULTIPLE_CHOICE', 'EXECUTIVE', TRUE, FALSE);
INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES
(LAST_INSERT_ID(), 'A', '市场趋势预测与分析', FALSE), (LAST_INSERT_ID(), 'A', '市场趋势预测与分析', FALSE),
@ -299,8 +306,8 @@ INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`)
(LAST_INSERT_ID(), 'C', '业务流程优化与重组', FALSE), (LAST_INSERT_ID(), 'C', '业务流程优化与重组', FALSE),
(LAST_INSERT_ID(), 'D', '其他', TRUE); (LAST_INSERT_ID(), 'D', '其他', TRUE);
INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`) INSERT INTO `question` (`number`, `content`, `type`, `work_area`, `is_required`, `is_last`)
VALUES (24, '在公司管理工作中,您最希望大模型协助哪些任务?', 'MULTIPLE_CHOICE', 'EXECUTIVE', TRUE); VALUES (24, '在公司管理工作中,您最希望大模型协助哪些任务?', 'MULTIPLE_CHOICE', 'EXECUTIVE', TRUE, FALSE);
INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`) VALUES
(LAST_INSERT_ID(), 'A', '数据分析与报告自动生成', FALSE), (LAST_INSERT_ID(), 'A', '数据分析与报告自动生成', FALSE),
@ -309,11 +316,11 @@ INSERT INTO `option` (`question_id`, `option_code`, `content`, `requires_text`)
(LAST_INSERT_ID(), 'D', '其他', TRUE); (LAST_INSERT_ID(), 'D', '其他', TRUE);
-- 开放建议问题 -- 开放建议问题
INSERT INTO `question` (`number`, `content`, `type`, `is_required`) INSERT INTO `question` (`number`, `content`, `type`, `is_required`, `is_last`)
VALUES (25, '您对大模型培训的具体期待:', 'TEXT', FALSE); VALUES (25, '您对大模型培训的具体期待:', 'TEXT', FALSE, FALSE);
INSERT INTO `question` (`number`, `content`, `type`, `is_required`) INSERT INTO `question` (`number`, `content`, `type`, `is_required`, `is_last`)
VALUES (26, '您认为公司引入AI需提前防范的风险', 'TEXT', FALSE); VALUES (26, '您认为公司引入AI需提前防范的风险', 'TEXT', FALSE, TRUE);
-- 设置问题跳转逻辑 -- 设置问题跳转逻辑
UPDATE `question` UPDATE `question`
@ -364,3 +371,6 @@ UPDATE `question` SET `next` = JSON_OBJECT('*', 25) WHERE `number` = 24;
-- 第一个开放性问题跳转到第二个 -- 第一个开放性问题跳转到第二个
UPDATE `question` SET `next` = JSON_OBJECT('*', 26) WHERE `number` = 25; UPDATE `question` SET `next` = JSON_OBJECT('*', 26) WHERE `number` = 25;
-- 设置最后一题标记
UPDATE `question` SET `is_last` = TRUE WHERE `number` = 26;

View File

@ -17,15 +17,24 @@ export function getQuestionOptions(questionId) {
} }
// 获取下一个问题 // 获取下一个问题
export function getNextQuestion(userId, currentQuestionNumber, selectedOptions) { export function getNextQuestion(userId, selectedOptions, currentQuestionNumber) {
console.log('API调用参数:', { userId, selectedOptions, currentQuestionNumber });
const params = {
userId
};
// 只有在不是第一次请求时才添加这些参数
if (selectedOptions) {
params.selectedOptions = selectedOptions.join(',');
}
if (currentQuestionNumber !== undefined) {
params.currentQuestionNumber = currentQuestionNumber;
}
return request({ return request({
url: '/question/next', url: '/question/next',
method: 'get', method: 'get',
params: { params
userId,
currentQuestionNumber,
selectedOptions,
},
}); });
} }

View File

@ -13,14 +13,15 @@ export const useSurveyStore = defineStore('survey', () => {
const currentQuestion = ref(null); const currentQuestion = ref(null);
const questionOptions = ref([]); const questionOptions = ref([]);
const userResponses = ref([]); const userResponses = ref([]);
const currentQuestionNumber = ref(0); const currentQuestionNumber = ref(null);
const currentOptions = ref([]);
const isCompleted = ref(false); const isCompleted = ref(false);
// 获取用户的问题列表 // 获取用户的问题列表
async function fetchUserQuestions(userId) { async function fetchUserQuestions(userId) {
try { try {
const response = await getUserQuestions(userId); const response = await getUserQuestions(userId);
return response.data; return response;
} catch (error) { } catch (error) {
showToast('获取问题列表失败:' + error.message); showToast('获取问题列表失败:' + error.message);
throw error; throw error;
@ -30,10 +31,13 @@ export const useSurveyStore = defineStore('survey', () => {
// 获取问题的选项列表 // 获取问题的选项列表
async function fetchQuestionOptions(questionId) { async function fetchQuestionOptions(questionId) {
try { try {
const response = await getQuestionOptions(questionId); console.log('获取问题选项问题ID:', questionId);
questionOptions.value = response.data; const options = await getQuestionOptions(questionId);
return response.data; console.log('获取到的选项:', options);
currentOptions.value = options;
return options;
} catch (error) { } catch (error) {
console.error('获取问题选项失败:', error);
showToast('获取问题选项失败:' + error.message); showToast('获取问题选项失败:' + error.message);
throw error; throw error;
} }
@ -42,19 +46,35 @@ export const useSurveyStore = defineStore('survey', () => {
// 获取下一个问题 // 获取下一个问题
async function fetchNextQuestion(userId, selectedOptions) { async function fetchNextQuestion(userId, selectedOptions) {
try { try {
// 如果是初始化currentQuestionNumber为0则从第3题开始 console.log('获取下一个问题,参数:', { userId, selectedOptions, currentQuestionNumber: currentQuestionNumber.value });
const questionNumber = currentQuestionNumber.value === 0 ? 3 : currentQuestionNumber.value;
const response = await getNextQuestion(userId, questionNumber, selectedOptions); // 如果没有当前问题号,说明是新开始的问卷
if (response) { const isNewSurvey = !currentQuestionNumber.value;
currentQuestion.value = response;
currentQuestionNumber.value = response.questionNumber; const question = await getNextQuestion(
await fetchQuestionOptions(response.id); userId,
selectedOptions,
isNewSurvey ? undefined : currentQuestionNumber.value
);
console.log('获取到的问题:', question);
if (question) {
currentQuestion.value = question;
currentQuestionNumber.value = question.number;
// 获取问题的选项
console.log('开始获取问题选项');
const options = await getQuestionOptions(question.id);
console.log('获取到的选项:', options);
currentOptions.value = options;
} else { } else {
console.log('没有更多问题了');
isCompleted.value = true; isCompleted.value = true;
} }
return response;
return question;
} catch (error) { } catch (error) {
showToast('获取下一个问题失败:' + error.message); console.error('获取下一个问题失败:', error);
throw error; throw error;
} }
} }
@ -64,7 +84,7 @@ export const useSurveyStore = defineStore('survey', () => {
try { try {
const response = await submitSurvey(userId, responses); const response = await submitSurvey(userId, responses);
userResponses.value = responses; userResponses.value = responses;
return response.data; return response;
} catch (error) { } catch (error) {
showToast('提交问卷失败:' + error.message); showToast('提交问卷失败:' + error.message);
throw error; throw error;
@ -75,8 +95,8 @@ export const useSurveyStore = defineStore('survey', () => {
async function fetchUserResponses(userId) { async function fetchUserResponses(userId) {
try { try {
const response = await getUserResponses(userId); const response = await getUserResponses(userId);
userResponses.value = response.data; userResponses.value = response;
return response.data; return response;
} catch (error) { } catch (error) {
showToast('获取问卷答案失败:' + error.message); showToast('获取问卷答案失败:' + error.message);
throw error; throw error;
@ -87,8 +107,13 @@ export const useSurveyStore = defineStore('survey', () => {
function resetSurvey() { function resetSurvey() {
currentQuestion.value = null; currentQuestion.value = null;
questionOptions.value = []; questionOptions.value = [];
currentQuestionNumber.value = 0; userResponses.value = [];
currentQuestionNumber.value = null;
currentOptions.value = [];
isCompleted.value = false; isCompleted.value = false;
// 清除本地存储中的问卷相关数据
localStorage.removeItem('surveyProgress');
localStorage.removeItem('surveyResponses');
} }
return { return {
@ -96,6 +121,7 @@ export const useSurveyStore = defineStore('survey', () => {
questionOptions, questionOptions,
userResponses, userResponses,
currentQuestionNumber, currentQuestionNumber,
currentOptions,
isCompleted, isCompleted,
fetchUserQuestions, fetchUserQuestions,
fetchQuestionOptions, fetchQuestionOptions,

View File

@ -2,6 +2,7 @@ import { defineStore } from 'pinia';
import { ref } from 'vue'; import { ref } from 'vue';
import { register, checkPhone, getUserInfo } from '@/api/user'; import { register, checkPhone, getUserInfo } from '@/api/user';
import { showToast } from 'vant'; import { showToast } from 'vant';
import { useSurveyStore } from './survey';
export const useUserStore = defineStore('user', () => { export const useUserStore = defineStore('user', () => {
const userId = ref(localStorage.getItem('userId') || ''); const userId = ref(localStorage.getItem('userId') || '');
@ -87,10 +88,10 @@ export const useUserStore = defineStore('user', () => {
// 退出登录 // 退出登录
function logout() { function logout() {
userId.value = ''; const surveyStore = useSurveyStore();
userInfo.value = null; userId.value = null;
localStorage.removeItem('userId'); localStorage.removeItem('userId');
console.log('用户已登出'); surveyStore.resetSurvey();
} }
return { return {

View File

@ -8,41 +8,66 @@
/> />
<div v-if="!surveyStore.isCompleted" class="survey-content"> <div v-if="!surveyStore.isCompleted" class="survey-content">
<div v-if="surveyStore.currentQuestion" class="question-card"> <div v-if="surveyStore.currentQuestion" class="question-container">
<van-cell-group inset> <h2 class="question-title">
<van-cell> {{ surveyStore.currentQuestionNumber }}. {{ surveyStore.currentQuestion.content }}
<template #title> <span v-if="surveyStore.currentQuestion.type === 'MULTIPLE_CHOICE'" class="question-type">(多选)</span>
<div class="question-title"> </h2>
{{ surveyStore.currentQuestionNumber }}. {{ surveyStore.currentQuestion.content }} <van-checkbox-group v-if="surveyStore.currentQuestion.type === 'MULTIPLE_CHOICE'" v-model="selectedOptions" class="options-container">
</div> <van-cell-group inset>
</template> <van-cell
</van-cell> v-for="option in surveyStore.currentOptions"
:key="option.optionCode"
<van-radio-group v-model="selectedOption"> clickable
<van-cell-group> @click="toggleOption(option.optionCode)"
<van-cell >
v-for="option in surveyStore.questionOptions" <template #title>
:key="option.id" <span>{{ option.optionCode }}. {{ option.content }}</span>
clickable </template>
@click="selectedOption = option.id" <template #right-icon>
> <van-checkbox
<template #title> :name="option.optionCode"
<van-radio :name="option.id">{{ option.content }}</van-radio> @click.stop
</template> />
</van-cell> </template>
</van-cell-group> </van-cell>
</van-radio-group> </van-cell-group>
</van-cell-group> </van-checkbox-group>
<van-radio-group v-else-if="surveyStore.currentQuestion.type === 'SINGLE_CHOICE'" v-model="selectedOption" class="options-container">
<div class="action-buttons"> <van-cell-group inset>
<van-cell
v-for="option in surveyStore.currentOptions"
:key="option.optionCode"
clickable
@click="selectedOption = option.optionCode"
>
<template #title>
<span>{{ option.optionCode }}. {{ option.content }}</span>
</template>
<template #right-icon>
<van-radio :name="option.optionCode" />
</template>
</van-cell>
</van-cell-group>
</van-radio-group>
<div v-else-if="surveyStore.currentQuestion.type === 'TEXT'" class="text-input-container">
<van-field
v-model="textAnswer"
type="textarea"
rows="4"
autosize
placeholder="请输入您的答案"
:rules="[{ required: surveyStore.currentQuestion.isRequired, message: '请输入答案' }]"
/>
</div>
<div class="button-container">
<van-button <van-button
round
block
type="primary" type="primary"
:disabled="!selectedOption" block
:disabled="!isValidSelection"
@click="onNextQuestion" @click="onNextQuestion"
> >
下一题 {{ surveyStore.currentQuestion?.isLast ? '完成' : '下一题' }}
</van-button> </van-button>
</div> </div>
</div> </div>
@ -51,25 +76,29 @@
</div> </div>
<div v-else class="survey-completed"> <div v-else class="survey-completed">
<van-empty description="问卷已完成"> <van-empty description="感谢您完成问卷调查!">
<template #image> <template #image>
<van-icon name="success" size="64" color="#07c160" /> <van-icon name="success" size="64" color="#07c160" />
</template> </template>
<div class="completion-message">
<p>您的反馈对我们非常重要</p>
<p>我们将根据调查结果持续改进和优化</p>
</div>
</van-empty> </van-empty>
<van-button <van-button
round round
type="primary" type="primary"
class="restart-button" class="home-button"
@click="onRestartSurvey" @click="router.replace('/')"
> >
重新开始 返回首页
</van-button> </van-button>
</div> </div>
</div> </div>
</template> </template>
<script setup> <script setup>
import { ref, onMounted } from 'vue'; import { ref, onMounted, computed } from 'vue';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { useUserStore } from '@/stores/user'; import { useUserStore } from '@/stores/user';
import { useSurveyStore } from '@/stores/survey'; import { useSurveyStore } from '@/stores/survey';
@ -80,8 +109,33 @@ const userStore = useUserStore();
const surveyStore = useSurveyStore(); const surveyStore = useSurveyStore();
const selectedOption = ref(''); const selectedOption = ref('');
const selectedOptions = ref([]);
const textAnswer = ref('');
const responses = ref([]); const responses = ref([]);
//
const isValidSelection = computed(() => {
const questionType = surveyStore.currentQuestion?.type;
if (questionType === 'MULTIPLE_CHOICE') {
return selectedOptions.value.length > 0;
} else if (questionType === 'SINGLE_CHOICE') {
return selectedOption.value !== '';
} else if (questionType === 'TEXT') {
return textAnswer.value.trim() !== '';
}
return false;
});
//
function toggleOption(optionCode) {
const index = selectedOptions.value.indexOf(optionCode);
if (index === -1) {
selectedOptions.value.push(optionCode);
} else {
selectedOptions.value.splice(index, 1);
}
}
// //
function onBack() { function onBack() {
router.back(); router.back();
@ -89,47 +143,71 @@ function onBack() {
// //
async function onNextQuestion() { async function onNextQuestion() {
if (!selectedOption.value) { const questionType = surveyStore.currentQuestion.type;
if (questionType === 'MULTIPLE_CHOICE' && selectedOptions.value.length === 0) {
showToast('请至少选择一个选项');
return;
} else if (questionType === 'SINGLE_CHOICE' && !selectedOption.value) {
showToast('请选择一个选项'); showToast('请选择一个选项');
return; return;
} else if (questionType === 'TEXT' && !textAnswer.value.trim()) {
showToast('请输入答案');
return;
} }
try { try {
let currentSelection = [];
if (questionType === 'MULTIPLE_CHOICE') {
currentSelection = selectedOptions.value;
} else if (questionType === 'SINGLE_CHOICE') {
currentSelection = [selectedOption.value];
}
// //
responses.value.push({ responses.value.push({
questionId: surveyStore.currentQuestion.id, questionId: surveyStore.currentQuestion.id,
optionId: selectedOption.value, selectedOptions: currentSelection,
textAnswer: questionType === 'TEXT' ? textAnswer.value.trim() : null
}); });
// //
const nextQuestion = await surveyStore.fetchNextQuestion( if (surveyStore.currentQuestion.isLast) {
userStore.userId, try {
selectedOption.value await surveyStore.submitSurveyResponses(userStore.userId, responses.value);
); showToast('问卷提交成功');
surveyStore.isCompleted.value = true;
// return;
if (!nextQuestion) { } catch (error) {
await surveyStore.submitSurveyResponses(userStore.userId, responses.value); console.error('提交问卷失败:', error);
showToast('问卷提交成功'); showToast(error.response?.data?.message || '提交失败,请重试');
return;
}
} }
// //
selectedOption.value = ''; try {
await surveyStore.fetchNextQuestion(userStore.userId, currentSelection);
//
selectedOption.value = '';
selectedOptions.value = [];
textAnswer.value = '';
} catch (error) {
console.error('获取下一题失败:', error);
showToast(error.response?.data?.message || '获取下一题失败,请重试');
}
} catch (error) { } catch (error) {
console.error('获取下一个问题失败:', error); console.error('问卷处理失败:', error);
showToast(error.response?.data?.message || '操作失败,请重试');
} }
} }
//
function onRestartSurvey() {
surveyStore.resetSurvey();
responses.value = [];
initSurvey();
}
// //
async function initSurvey() { async function initSurvey() {
try { try {
surveyStore.resetSurvey(); //
responses.value = [];
//
await surveyStore.fetchNextQuestion(userStore.userId); await surveyStore.fetchNextQuestion(userStore.userId);
} catch (error) { } catch (error) {
console.error('初始化问卷失败:', error); console.error('初始化问卷失败:', error);
@ -157,20 +235,27 @@ onMounted(() => {
padding: 20px; padding: 20px;
} }
.question-card { .question-container {
margin-bottom: 20px; margin-bottom: 20px;
} }
.question-title { .question-title {
font-size: 16px; font-size: 18px;
font-weight: bold; font-weight: bold;
line-height: 1.5; line-height: 1.5;
margin-bottom: 16px;
padding: 0 16px;
} }
.action-buttons { .options-container {
margin-top: 20px; margin-top: 20px;
} }
.button-container {
margin-top: 24px;
padding: 0 16px;
}
.survey-completed { .survey-completed {
padding: 40px 20px; padding: 40px 20px;
text-align: center; text-align: center;
@ -180,4 +265,28 @@ onMounted(() => {
margin-top: 20px; margin-top: 20px;
width: 80%; width: 80%;
} }
.question-type {
font-size: 14px;
color: #666;
margin-left: 8px;
}
.text-input-container {
padding: 16px;
background-color: #fff;
border-radius: 8px;
margin: 0 16px;
}
.completion-message {
margin: 16px 0;
color: #666;
line-height: 1.6;
}
.home-button {
margin-top: 24px;
width: 80%;
}
</style> </style>