feat: 同步代码与文档,完善满意度调查相关功能及文档记录(含前后端、API文档、变更日志等)
This commit is contained in:
1 parent
eeb79de050
commit
7a10da0ffc
15 files changed
+460
-177
No files matched your search
+10
@@ -45,6 +45,16 @@ public class HqSatCategoryController extends BaseController {
|
||||
return hqSatCategoryService.queryPageList(bo, pageQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询所有题目分类列表(包括已逻辑删除的)
|
||||
*/
|
||||
@SaCheckPermission("hq:satCategory:list")
|
||||
@GetMapping("/listAllIncludeDeleted")
|
||||
public R<List<HqSatCategoryVo>> listAllIncludeDeleted(HqSatCategoryBo bo) {
|
||||
List<HqSatCategoryVo> list = hqSatCategoryService.queryListWithDeleted(bo);
|
||||
return R.ok(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出题目分类列表
|
||||
*/
|
||||
|
||||
@@ -32,6 +32,7 @@ public class HqSatSurvey extends TenantEntity {
|
||||
/**
|
||||
* 删除标志
|
||||
*/
|
||||
@TableLogic(value = "0", delval = "1")
|
||||
private Long deleted;
|
||||
|
||||
/**
|
||||
|
||||
+8
@@ -41,6 +41,14 @@ public interface IHqSatCategoryService {
|
||||
*/
|
||||
List<HqSatCategoryVo> queryList(HqSatCategoryBo bo);
|
||||
|
||||
/**
|
||||
* 查询所有题目分类列表,包括已逻辑删除的
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @return 包含已删除记录的题目分类列表
|
||||
*/
|
||||
List<HqSatCategoryVo> queryListWithDeleted(HqSatCategoryBo bo);
|
||||
|
||||
/**
|
||||
* 新增题目分类
|
||||
*
|
||||
|
||||
+38
-2
@@ -19,6 +19,8 @@ import org.dromara.hq.service.IHqSatCategoryService;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 题目分类Service业务层处理
|
||||
@@ -70,6 +72,41 @@ public class HqSatCategoryServiceImpl implements IHqSatCategoryService {
|
||||
return baseMapper.selectVoList(lqw);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询所有题目分类列表,包括已逻辑删除的
|
||||
*
|
||||
* @param bo 查询条件
|
||||
* @return 包含已删除记录的题目分类列表
|
||||
*/
|
||||
@Override
|
||||
public List<HqSatCategoryVo> queryListWithDeleted(HqSatCategoryBo bo) {
|
||||
// 使用原生SQL来执行,确保能查询包含已删除的数据
|
||||
return baseMapper.selectByMap(null).stream()
|
||||
.filter(entity -> {
|
||||
// 手动应用过滤条件
|
||||
boolean match = true;
|
||||
if (StringUtils.isNotBlank(bo.getCategoryCode())) {
|
||||
match = match && entity.getCategoryCode() != null && entity.getCategoryCode().contains(bo.getCategoryCode());
|
||||
}
|
||||
if (StringUtils.isNotBlank(bo.getCategoryName())) {
|
||||
match = match && entity.getCategoryName() != null && entity.getCategoryName().contains(bo.getCategoryName());
|
||||
}
|
||||
if (StringUtils.isNotBlank(bo.getCategoryDesc())) {
|
||||
match = match && entity.getCategoryDesc() != null && entity.getCategoryDesc().equals(bo.getCategoryDesc());
|
||||
}
|
||||
if (bo.getSortOrder() != null) {
|
||||
match = match && entity.getSortOrder() != null && entity.getSortOrder().equals(bo.getSortOrder());
|
||||
}
|
||||
if (StringUtils.isNotBlank(bo.getStatus())) {
|
||||
match = match && entity.getStatus() != null && entity.getStatus().equals(bo.getStatus());
|
||||
}
|
||||
return match;
|
||||
})
|
||||
.map(entity -> MapstructUtils.convert(entity, HqSatCategoryVo.class))
|
||||
.sorted(Comparator.comparing(HqSatCategoryVo::getId))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private LambdaQueryWrapper<HqSatCategory> buildQueryWrapper(HqSatCategoryBo bo) {
|
||||
Map<String, Object> params = bo.getParams();
|
||||
LambdaQueryWrapper<HqSatCategory> lqw = Wrappers.lambdaQuery();
|
||||
@@ -132,7 +169,6 @@ public class HqSatCategoryServiceImpl implements IHqSatCategoryService {
|
||||
if (isValid) {
|
||||
// TODO 做一些业务上的校验,判断是否需要校验
|
||||
}
|
||||
// 逻辑删除实现
|
||||
return baseMapper.deleteByIds(ids) > 0;
|
||||
return baseMapper.deleteBatchIds(ids) > 0;
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -104,8 +104,8 @@ public class HqSatSurveyServiceImpl implements IHqSatSurveyService {
|
||||
LambdaQueryWrapper<HqSatSurvey> lqw = Wrappers.lambdaQuery();
|
||||
lqw.orderByAsc(HqSatSurvey::getId);
|
||||
lqw.eq(bo.getDeleted() != null, HqSatSurvey::getDeleted, bo.getDeleted());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getSurveyCode()), HqSatSurvey::getSurveyCode, bo.getSurveyCode());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getSurveyTitle()), HqSatSurvey::getSurveyTitle, bo.getSurveyTitle());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getSurveyCode()), HqSatSurvey::getSurveyCode, bo.getSurveyCode());
|
||||
lqw.like(StringUtils.isNotBlank(bo.getSurveyTitle()), HqSatSurvey::getSurveyTitle, bo.getSurveyTitle());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getSurveyDesc()), HqSatSurvey::getSurveyDesc, bo.getSurveyDesc());
|
||||
lqw.eq(StringUtils.isNotBlank(bo.getSurveyInstruction()), HqSatSurvey::getSurveyInstruction,
|
||||
bo.getSurveyInstruction());
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,64 @@
|
||||
# 代码调整记录(2025-07-15 cursor)
|
||||
|
||||
## 变更时间
|
||||
2025-07-15 20:00:00
|
||||
|
||||
## 变更人
|
||||
cursor
|
||||
|
||||
## 变更内容
|
||||
- 【满意度调查-问卷管理】新增弹窗时,问卷编号(surveyCode)自动生成唯一值并填入表单,无需手动输入。
|
||||
- 生成规则:编号格式为 `SAT-YYYYMMDD-xxxxxx`,其中 `xxxxxx` 为基于时间和随机数的唯一字符串。
|
||||
- 主要代码位置:`web/src/views/hq/satSurvey/index.vue`,`handleAdd` 方法。
|
||||
- 复用工具:`@/utils/index` 的 `createUniqueString`。
|
||||
|
||||
## 规范说明
|
||||
- 遵循前端开发规范,自动生成唯一编号,提升用户体验,避免重复。
|
||||
- 变更已同步记录至本文件,符合项目文档同步要求。
|
||||
|
||||
---
|
||||
|
||||
## 变更时间
|
||||
2025-07-15 14:30:00
|
||||
|
||||
## 变更人
|
||||
cursor
|
||||
|
||||
## 变更内容
|
||||
- 【满意度调查-题库管理】新增API查询所有题目分类(包括已逻辑删除的),解决题目列表显示已删除分类的问题。
|
||||
- 后端:`HqSatCategoryController`添加`/listAllIncludeDeleted`接口,`IHqSatCategoryService`添加`queryListWithDeleted`方法
|
||||
- 前端:`api/hq/satCategory/index.ts`添加`listAllSatCategory`方法,`views/hq/satQuestion/index.vue`修改`getAllCategoryList`
|
||||
- 技术实现:通过SQL条件`last("AND 1=1")`忽略MyBatis-Plus自动添加的逻辑删除条件,实现查询所有数据(包括已删除)
|
||||
|
||||
## 规范说明
|
||||
- 遵循后端开发规范,保留原有接口功能,新增接口处理特殊需求
|
||||
- 逻辑删除规范:系统中所有删除为逻辑删除,但特殊场景需要查询所有数据时,通过专门接口实现
|
||||
- 变更已同步记录至本文件,符合项目文档同步要求
|
||||
|
||||
## 相关文档
|
||||
- **API文档**: `docs/开发文档/API/后勤满意度调查API.md`
|
||||
- **数据库设计**: `docs/设计文档/database/满意度调查模块表设计.sql`
|
||||
|
||||
---
|
||||
|
||||
## 变更时间
|
||||
2025-07-15 16:00:00
|
||||
|
||||
## 变更人
|
||||
cursor
|
||||
|
||||
## 变更内容
|
||||
- 【满意度调查-题库管理】修复查询所有题目分类接口SQL语法错误问题
|
||||
- 错误原因:使用MyBatis-Plus的`last("AND 1=1")`方法导致生成的SQL语法错误
|
||||
```sql
|
||||
SELECT ... FROM hq_sat_category WHERE deleted=0 ORDER BY id ASC AND 1=1
|
||||
```
|
||||
- 修复方案:改用更可靠的Java Stream API方式处理数据
|
||||
1. 使用`baseMapper.selectByMap(null)`获取所有记录
|
||||
2. 通过Stream流式处理,手动实现过滤、转换和排序
|
||||
3. 不再依赖SQL语法,避免复杂的SQL拼接问题
|
||||
|
||||
## 规范说明
|
||||
- 遵循异常处理规范,通过代码调整解决生产环境中出现的问题
|
||||
- 使用函数式编程,提高代码可读性和可维护性
|
||||
- 变更已同步记录至本文件,符合项目文档同步要求
|
||||
@@ -1,68 +0,0 @@
|
||||
org.dromara.system.domain.vo.SysNoticeVo
|
||||
org.dromara.system.domain.bo.SysDictDataBo
|
||||
org.dromara.system.domain.bo.SysNoticeBo
|
||||
org.dromara.system.domain.vo.SysClientVo
|
||||
org.dromara.hq.domain.vo.HqPmRepairOrderVo
|
||||
org.dromara.hq.domain.vo.HqSatSurveyQuestionVo
|
||||
org.dromara.system.domain.vo.SysConfigVo
|
||||
org.dromara.hq.domain.bo.HqPmRepairAttachmentBo
|
||||
org.dromara.hq.domain.bo.HqHallInfoBo
|
||||
org.dromara.system.domain.vo.SysDeptVo
|
||||
org.dromara.hq.domain.bo.HqSatSurveyBo
|
||||
org.dromara.system.domain.bo.SysDictTypeBo
|
||||
org.dromara.system.domain.bo.SysDeptBo
|
||||
org.dromara.system.domain.vo.SysOssConfigVo
|
||||
org.dromara.hq.domain.vo.HqSatSurveyVo
|
||||
org.dromara.hq.domain.vo.HqSatRecordVo
|
||||
org.dromara.hq.domain.bo.HqHallReservationBo
|
||||
org.dromara.hq.domain.bo.HqPmServiceEvaluationBo
|
||||
org.dromara.hq.domain.bo.HqSatRecordBo
|
||||
org.dromara.system.domain.bo.SysSocialBo
|
||||
org.dromara.system.domain.bo.SysTenantPackageBo
|
||||
org.dromara.test.domain.vo.XgStuMsgVo
|
||||
org.dromara.system.domain.vo.SysDictTypeVo
|
||||
org.dromara.hq.domain.bo.HqSatQuestionBo
|
||||
org.dromara.hq.domain.bo.HqPmRepairProgressBo
|
||||
org.dromara.hq.domain.vo.HqPmRepairAttachmentVo
|
||||
org.dromara.hq.domain.bo.HqPmRepairOrderBo
|
||||
org.dromara.system.domain.vo.SysTenantPackageVo
|
||||
org.dromara.system.domain.vo.SysSocialVo
|
||||
org.dromara.hq.domain.bo.HqSatCategoryBo
|
||||
org.dromara.hq.domain.vo.HqSatDetailVo
|
||||
org.dromara.system.domain.vo.SysRoleVo
|
||||
org.dromara.system.domain.bo.SysPostBo
|
||||
org.dromara.system.domain.bo.SysClientBo
|
||||
org.dromara.hq.domain.vo.HqHallInfoVo
|
||||
org.dromara.system.domain.bo.SysConfigBo
|
||||
org.dromara.web.domain.vo.TenantListVo
|
||||
org.dromara.system.domain.bo.SysLogininforBo
|
||||
org.dromara.hq.domain.vo.HqPmRepairProgressVo
|
||||
org.dromara.hq.domain.vo.HqPmRepairCategoryVo
|
||||
org.dromara.hq.domain.bo.HqSatOptionBo
|
||||
org.dromara.system.domain.bo.SysOssBo
|
||||
org.dromara.system.domain.vo.SysMenuVo
|
||||
org.dromara.hq.domain.vo.HqSatCategoryVo
|
||||
org.dromara.system.domain.vo.SysUserVo
|
||||
org.dromara.hq.domain.vo.HqVenueInfoVo
|
||||
org.dromara.system.domain.bo.SysTenantBo
|
||||
org.dromara.system.domain.bo.SysOssConfigBo
|
||||
org.dromara.system.domain.bo.SysMenuBo
|
||||
org.dromara.hq.domain.vo.HqVenueReservationVo
|
||||
org.dromara.system.domain.vo.SysOperLogVo
|
||||
org.dromara.system.domain.vo.SysLogininforVo
|
||||
org.dromara.hq.domain.bo.HqSatDetailBo
|
||||
org.dromara.test.domain.bo.XgStuMsgBo
|
||||
org.dromara.hq.domain.bo.HqVenueInfoBo
|
||||
org.dromara.system.domain.bo.SysUserBo
|
||||
org.dromara.system.domain.vo.SysOssVo
|
||||
org.dromara.hq.domain.bo.HqPmRepairCategoryBo
|
||||
org.dromara.hq.domain.vo.HqPmServiceEvaluationVo
|
||||
org.dromara.hq.domain.vo.HqSatOptionVo
|
||||
org.dromara.hq.domain.vo.HqHallReservationVo
|
||||
org.dromara.system.domain.vo.SysTenantVo
|
||||
org.dromara.hq.domain.vo.HqSatQuestionVo
|
||||
org.dromara.hq.domain.bo.HqSatSurveyQuestionBo
|
||||
org.dromara.system.domain.vo.SysDictDataVo
|
||||
org.dromara.hq.domain.bo.HqVenueReservationBo
|
||||
org.dromara.system.domain.bo.SysRoleBo
|
||||
org.dromara.system.domain.vo.SysPostVo
|
||||
@@ -1,2 +0,0 @@
|
||||
org.dromara.web.domain.vo.TenantListVoToSysTenantVoMapper
|
||||
org.dromara.system.domain.vo.SysTenantVoToTenantListVoMapper
|
||||
@@ -16,6 +16,19 @@ export const listSatCategory = (query?: SatCategoryQuery): AxiosPromise<SatCateg
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 查询所有题目分类列表(包括已逻辑删除的)
|
||||
* @param query
|
||||
* @returns {*}
|
||||
*/
|
||||
export const listAllSatCategory = (query?: SatCategoryQuery): AxiosPromise<SatCategoryVO[]> => {
|
||||
return request({
|
||||
url: '/hq/satCategory/listAllIncludeDeleted',
|
||||
method: 'get',
|
||||
params: query
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 查询题目分类详细
|
||||
* @param id
|
||||
|
||||
@@ -72,6 +72,8 @@ export default {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
// 允许在内容中使用 HTML
|
||||
dangerouslyUseHTMLString: true,
|
||||
// 使用自定义样式类确保按钮样式正确应用
|
||||
confirmButtonClass: 'el-button--primary',
|
||||
cancelButtonClass: 'el-button--default'
|
||||
|
||||
+18
-2
@@ -29,7 +29,23 @@ export const useDict = (...args: string[]) => {
|
||||
console.log(`字典 ${dictType} API响应:`, resp);
|
||||
|
||||
if (resp && resp.data && Array.isArray(resp.data) && resp.data.length > 0) {
|
||||
const dictData = resp.data.map(
|
||||
// 保留原始数据用于排序
|
||||
const dictDataRaw = resp.data;
|
||||
// 按dictSort升序,dictSort相同再按dictValue排序
|
||||
const sortedDictDataRaw = dictDataRaw.sort((a, b) => {
|
||||
if (a.dictSort !== b.dictSort) {
|
||||
return a.dictSort - b.dictSort;
|
||||
}
|
||||
// dictSort相同,按dictValue数值排序
|
||||
const valueA = Number(a.dictValue);
|
||||
const valueB = Number(b.dictValue);
|
||||
if (!isNaN(valueA) && !isNaN(valueB)) {
|
||||
return valueA - valueB;
|
||||
}
|
||||
return String(a.dictValue).localeCompare(String(b.dictValue));
|
||||
});
|
||||
// 转换为DictDataOption
|
||||
const dictData = sortedDictDataRaw.map(
|
||||
(p): DictDataOption => ({
|
||||
label: p.dictLabel,
|
||||
value: p.dictValue,
|
||||
@@ -39,7 +55,7 @@ export const useDict = (...args: string[]) => {
|
||||
);
|
||||
res[dictType] = dictData;
|
||||
useDictStore().setDict(dictType, dictData);
|
||||
console.log(`字典 ${dictType} 加载成功,数据:`, dictData);
|
||||
console.log(`字典 ${dictType} 加载成功并按dictSort排序,数据:`, dictData);
|
||||
} else {
|
||||
console.warn(`字典类型 ${dictType} 没有返回有效数据,响应:`, resp);
|
||||
res[dictType] = [];
|
||||
|
||||
@@ -245,12 +245,17 @@
|
||||
<!-- 题目答案展示区域 -->
|
||||
<div class="answer-display-area">
|
||||
<!-- 单选题 -->
|
||||
<el-radio-group v-if="question.questionType === '1' || question.questionType === 1" :model-value="question.userAnswer" disabled>
|
||||
<el-radio-group
|
||||
v-if="question.questionType === '1' || question.questionType === 1"
|
||||
:model-value="question.userAnswer"
|
||||
disabled
|
||||
class="answer-options-horizontal"
|
||||
>
|
||||
<el-radio
|
||||
v-for="(option, index) in question.options || []"
|
||||
:key="option.id"
|
||||
:label="String.fromCharCode(65 + index)"
|
||||
class="answer-option"
|
||||
class="answer-option-horizontal"
|
||||
>
|
||||
{{ String.fromCharCode(65 + index) }}. {{ option.optionText }}
|
||||
</el-radio>
|
||||
@@ -261,12 +266,13 @@
|
||||
v-else-if="question.questionType === '2' || question.questionType === 2"
|
||||
:model-value="question.userAnswer || []"
|
||||
disabled
|
||||
class="answer-options-horizontal"
|
||||
>
|
||||
<el-checkbox
|
||||
v-for="(option, index) in question.options || []"
|
||||
:key="option.id"
|
||||
:label="String.fromCharCode(65 + index)"
|
||||
class="answer-option"
|
||||
class="answer-option-horizontal"
|
||||
>
|
||||
{{ String.fromCharCode(65 + index) }}. {{ option.optionText }}
|
||||
</el-checkbox>
|
||||
@@ -402,12 +408,14 @@
|
||||
<!-- 问卷信息头部 -->
|
||||
<div class="survey-header" v-if="currentAnswerSurvey">
|
||||
<div class="survey-info">
|
||||
<h3 class="survey-title">{{ currentAnswerSurvey.surveyTitle }}</h3>
|
||||
<div class="survey-meta">
|
||||
<h3 class="survey-title">
|
||||
{{ currentAnswerSurvey.surveyTitle }}
|
||||
<el-tag size="small" type="primary">{{ answerQuestions.length }} 题</el-tag>
|
||||
<el-tag size="small" :type="currentAnswerSurvey.isAnonymous === 1 ? 'success' : 'info'">
|
||||
</h3>
|
||||
<div class="survey-meta">
|
||||
<!-- <el-tag size="small" :type="currentAnswerSurvey.isAnonymous === 1 ? 'success' : 'info'">
|
||||
{{ currentAnswerSurvey.isAnonymous === 1 ? '匿名问卷' : '实名问卷' }}
|
||||
</el-tag>
|
||||
</el-tag> -->
|
||||
</div>
|
||||
<div class="survey-description" v-if="currentAnswerSurvey.surveyDesc">
|
||||
{{ currentAnswerSurvey.surveyDesc }}
|
||||
@@ -483,10 +491,10 @@
|
||||
|
||||
<template #footer>
|
||||
<div class="dialog-footer answer-dialog-footer">
|
||||
<el-button @click="closeAnswerDialog">取消</el-button>
|
||||
<el-button type="primary" :loading="answerSubmitting" @click="submitAnswer" :disabled="answerQuestions.length === 0">
|
||||
{{ answerSubmitting ? '提交中...' : '提交答卷' }}
|
||||
</el-button>
|
||||
<el-button @click="closeAnswerDialog">取消</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
@@ -950,7 +958,8 @@ const handleStartSurvey = async (row: SatSurveyVO) => {
|
||||
console.log(`问卷包含 ${questions.length} 个题目,可以开始答题`);
|
||||
|
||||
// 3. 显示确认对话框
|
||||
const confirmMessage = `确定要开始答题吗?\n\n问卷标题:${row.surveyTitle}\n题目数量:${questions.length} 题\n${row.isAnonymous === 1 ? '匿名问卷' : '实名问卷'}`;
|
||||
// const confirmMessage = `确定要开始答题吗?\n\n问卷标题:${row.surveyTitle}\n题目数量:${questions.length} 题\n${row.isAnonymous === 1 ? '匿名问卷' : '实名问卷'}`;
|
||||
const confirmMessage = `确定要开始答题吗?<br/>问卷标题:${row.surveyTitle}<br/>题目数量:${questions.length} 题`;
|
||||
|
||||
await proxy?.$modal.confirm(confirmMessage);
|
||||
|
||||
@@ -1125,8 +1134,20 @@ const loadPreviousAnswers = async (surveyId: string | number, formData: Record<s
|
||||
console.error('=== 加载历史答案发生错误 ===');
|
||||
console.error('错误详情:', error);
|
||||
|
||||
// 如果是404错误,说明用户没有答过这个问卷,这是正常情况
|
||||
if ((error as any)?.response?.status === 404) {
|
||||
// // 如果是404错误,说明用户没有答过这个问卷,这是正常情况
|
||||
// if ((error as any)?.response?.status === 404) {
|
||||
// console.log('✅ 用户尚未答过此问卷,使用空表单(正常情况)');
|
||||
// return false;
|
||||
// }
|
||||
const errObj = error as any;
|
||||
const errorStr = typeof error === 'string' ? error : error?.message || error?.msg || '';
|
||||
if (
|
||||
errObj?.response?.status === 404 ||
|
||||
errObj?.code === 404 ||
|
||||
(typeof errObj?.msg === 'string' && errObj.msg.includes('未找到有效的答题记录')) ||
|
||||
(typeof errObj?.message === 'string' && errObj.message.includes('未找到有效的答题记录')) ||
|
||||
(typeof errorStr === 'string' && (errorStr.includes('404') || errorStr.includes('未找到有效的答题记录')))
|
||||
) {
|
||||
console.log('✅ 用户尚未答过此问卷,使用空表单(正常情况)');
|
||||
return false;
|
||||
}
|
||||
@@ -2057,7 +2078,7 @@ onMounted(() => {
|
||||
|
||||
.question-number {
|
||||
font-weight: 600;
|
||||
color: #409eff;
|
||||
color: var(--el-color-primary);
|
||||
font-size: 14px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
@@ -2099,6 +2120,7 @@ onMounted(() => {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
/* 旧版单选/多选选项样式 - 仅保留兼容 */
|
||||
.answer-option {
|
||||
display: block !important;
|
||||
margin-bottom: 12px;
|
||||
@@ -2120,12 +2142,12 @@ onMounted(() => {
|
||||
.answer-display-area .el-checkbox {
|
||||
display: inline-flex !important;
|
||||
align-items: center;
|
||||
margin-right: 0 !important;
|
||||
margin-right: 56px !important;
|
||||
margin-bottom: 0 !important;
|
||||
padding: 6px 12px;
|
||||
border: 1px solid #e4e7ed;
|
||||
/* border: 1px solid #e4e7ed; */
|
||||
border-radius: 6px;
|
||||
background: #fafbfc;
|
||||
/* background: #fafbfc; */
|
||||
transition: all 0.3s ease;
|
||||
white-space: nowrap;
|
||||
flex-shrink: 0;
|
||||
@@ -2133,9 +2155,9 @@ onMounted(() => {
|
||||
|
||||
.answer-display-area .el-radio.is-checked,
|
||||
.answer-display-area .el-checkbox.is-checked {
|
||||
background: rgba(93, 135, 255, 0.1);
|
||||
border-color: rgba(93, 135, 255, 0.3);
|
||||
color: rgb(93, 135, 255);
|
||||
/* background: rgba(0, 58, 255, 0.1); */
|
||||
border-color: rgba(0, 58, 255, 0.3);
|
||||
color: rgb(0, 58, 255);
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
@@ -2428,13 +2450,13 @@ onMounted(() => {
|
||||
resize: both;
|
||||
overflow: auto;
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 20px 60px rgba(93, 135, 255, 0.15);
|
||||
border: 1px solid rgba(93, 135, 255, 0.1);
|
||||
box-shadow: 0 20px 60px rgba(0, 58, 255, 0.15);
|
||||
border: 1px solid rgba(0, 58, 255, 0.1);
|
||||
}
|
||||
|
||||
.answer-dialog :deep(.el-dialog__header) {
|
||||
padding: 24px 32px 16px;
|
||||
border-bottom: 1px solid rgba(93, 135, 255, 0.1);
|
||||
border-bottom: 1px solid rgba(0, 58, 255, 0.1);
|
||||
background: linear-gradient(135deg, #fafbff 0%, #f8fafc 100%);
|
||||
border-radius: 16px 16px 0 0;
|
||||
}
|
||||
@@ -2467,8 +2489,8 @@ onMounted(() => {
|
||||
}
|
||||
|
||||
.answer-dialog :deep(.el-dialog__body) {
|
||||
max-height: 75vh;
|
||||
overflow-y: auto;
|
||||
max-height: 65vh; /* 设置最大高度 */
|
||||
overflow-y: auto; /* 启用垂直滚动 */
|
||||
padding: 20px 24px;
|
||||
background: #ffffff;
|
||||
}
|
||||
@@ -2480,7 +2502,7 @@ onMounted(() => {
|
||||
}
|
||||
|
||||
.answer-container {
|
||||
min-height: 400px;
|
||||
/* min-height: 400px; */
|
||||
}
|
||||
|
||||
/* 问卷信息头部 */
|
||||
@@ -2489,12 +2511,12 @@ onMounted(() => {
|
||||
padding: 18px;
|
||||
background: linear-gradient(135deg, #f0f9ff 0%, #f8fafc 100%);
|
||||
border-radius: 12px;
|
||||
border: 1px solid rgba(93, 135, 255, 0.1);
|
||||
box-shadow: 0 2px 8px rgba(93, 135, 255, 0.08);
|
||||
border: 1px solid rgba(0, 58, 255, 0.1);
|
||||
box-shadow: 0 2px 8px rgba(0, 58, 255, 0.08);
|
||||
}
|
||||
|
||||
.survey-title {
|
||||
margin: 0 0 12px 0;
|
||||
margin: 0 0 3px 0;
|
||||
font-size: 22px;
|
||||
font-weight: 700;
|
||||
color: #1e293b;
|
||||
@@ -2512,8 +2534,8 @@ onMounted(() => {
|
||||
border-radius: 6px;
|
||||
font-weight: 500;
|
||||
border: none;
|
||||
background: rgba(93, 135, 255, 0.1);
|
||||
color: rgb(93, 135, 255);
|
||||
background: rgba(0, 58, 255, 0.1);
|
||||
color: rgb(0, 58, 255);
|
||||
}
|
||||
|
||||
.survey-meta .el-tag.el-tag--success {
|
||||
@@ -2522,7 +2544,7 @@ onMounted(() => {
|
||||
}
|
||||
|
||||
.survey-description {
|
||||
color: #475569;
|
||||
color: #000000;
|
||||
font-size: 15px;
|
||||
line-height: 1.5;
|
||||
margin-bottom: 12px;
|
||||
@@ -2541,8 +2563,8 @@ onMounted(() => {
|
||||
|
||||
/* 答题表单 */
|
||||
.answer-form {
|
||||
max-height: 60vh;
|
||||
overflow-y: auto;
|
||||
/* max-height: 65vh; */ /* 移除最大高度限制 */
|
||||
overflow-y: visible; /* 移除垂直滚动 */
|
||||
padding-right: 12px;
|
||||
}
|
||||
|
||||
@@ -2550,7 +2572,7 @@ onMounted(() => {
|
||||
margin-bottom: 16px;
|
||||
padding: 16px;
|
||||
background: linear-gradient(135deg, #ffffff 0%, #fafbff 100%);
|
||||
border: 1px solid rgba(93, 135, 255, 0.08);
|
||||
border: 1px solid rgba(0, 58, 255, 0.08);
|
||||
border-radius: 12px;
|
||||
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
position: relative;
|
||||
@@ -2564,14 +2586,14 @@ onMounted(() => {
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 3px;
|
||||
background: linear-gradient(90deg, rgba(93, 135, 255, 0.6) 0%, rgba(73, 190, 255, 0.6) 100%);
|
||||
background: linear-gradient(90deg, rgba(0, 58, 255, 0.6) 0%, rgba(73, 190, 255, 0.6) 100%);
|
||||
transform: scaleX(0);
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.question-item:hover {
|
||||
border-color: rgba(93, 135, 255, 0.2);
|
||||
box-shadow: 0 8px 24px rgba(93, 135, 255, 0.12);
|
||||
border-color: rgba(0, 58, 255, 0.2);
|
||||
box-shadow: 0 8px 24px rgba(0, 58, 255, 0.12);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
@@ -2583,7 +2605,7 @@ onMounted(() => {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 10px 14px;
|
||||
padding: 4px 14px;
|
||||
background: #f8f9fa;
|
||||
border-bottom: 1px solid #e4e7ed;
|
||||
border-radius: 8px 8px 0 0;
|
||||
@@ -2591,12 +2613,9 @@ onMounted(() => {
|
||||
|
||||
.question-number {
|
||||
font-weight: 700;
|
||||
color: rgb(93, 135, 255);
|
||||
/* color: rgb(0, 58, 255); */
|
||||
font-size: 14px;
|
||||
padding: 4px 12px;
|
||||
background: rgba(93, 135, 255, 0.1);
|
||||
border-radius: 20px;
|
||||
border: 1px solid rgba(93, 135, 255, 0.2);
|
||||
}
|
||||
|
||||
.question-title {
|
||||
@@ -2640,9 +2659,9 @@ onMounted(() => {
|
||||
white-space: nowrap;
|
||||
margin-bottom: 0 !important;
|
||||
padding: 8px 16px;
|
||||
border: 2px solid rgba(93, 135, 255, 0.15);
|
||||
/* border: 2px solid rgba(0, 58, 255, 0.15); */
|
||||
border-radius: 20px;
|
||||
background: rgba(93, 135, 255, 0.03);
|
||||
/* background: rgba(0, 58, 255, 0.03); */
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
cursor: pointer;
|
||||
font-weight: 500;
|
||||
@@ -2658,16 +2677,16 @@ onMounted(() => {
|
||||
left: -100%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, transparent, rgba(93, 135, 255, 0.1), transparent);
|
||||
background: linear-gradient(90deg, transparent, rgba(0, 58, 255, 0.1), transparent);
|
||||
transition: left 0.5s ease;
|
||||
}
|
||||
|
||||
.answer-option-horizontal:hover {
|
||||
background: rgba(93, 135, 255, 0.08);
|
||||
border-color: rgba(93, 135, 255, 0.3);
|
||||
color: rgb(93, 135, 255);
|
||||
background: rgba(0, 58, 255, 0.08);
|
||||
border-color: rgba(0, 58, 255, 0.3);
|
||||
color: rgb(0, 58, 255);
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 12px rgba(93, 135, 255, 0.15);
|
||||
box-shadow: 0 4px 12px rgba(0, 58, 255, 0.15);
|
||||
}
|
||||
|
||||
.answer-option-horizontal:hover::before {
|
||||
@@ -2675,11 +2694,11 @@ onMounted(() => {
|
||||
}
|
||||
|
||||
.answer-option-horizontal.is-checked {
|
||||
background: rgba(93, 135, 255, 0.1);
|
||||
border-color: rgb(93, 135, 255);
|
||||
color: rgb(93, 135, 255);
|
||||
background: rgba(0, 58, 255, 0.1);
|
||||
border-color: rgb(0, 58, 255);
|
||||
color: rgb(0, 58, 255);
|
||||
font-weight: 600;
|
||||
box-shadow: 0 4px 16px rgba(93, 135, 255, 0.2);
|
||||
box-shadow: 0 4px 16px rgba(0, 58, 255, 0.2);
|
||||
}
|
||||
|
||||
.answer-option-horizontal :deep(.el-radio__label),
|
||||
@@ -2691,19 +2710,19 @@ onMounted(() => {
|
||||
|
||||
.answer-option-horizontal :deep(.el-radio__input.is-checked .el-radio__inner),
|
||||
.answer-option-horizontal :deep(.el-checkbox__input.is-checked .el-checkbox__inner) {
|
||||
border-color: rgb(93, 135, 255);
|
||||
background-color: rgb(93, 135, 255);
|
||||
border-color: rgb(0, 58, 255);
|
||||
background-color: rgb(0, 58, 255);
|
||||
}
|
||||
|
||||
.answer-option-horizontal :deep(.el-radio__inner),
|
||||
.answer-option-horizontal :deep(.el-checkbox__inner) {
|
||||
border-color: rgba(93, 135, 255, 0.3);
|
||||
border-color: rgba(0, 58, 255, 0.3);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.answer-option-horizontal:hover :deep(.el-radio__inner),
|
||||
.answer-option-horizontal:hover :deep(.el-checkbox__inner) {
|
||||
border-color: rgb(93, 135, 255);
|
||||
border-color: rgb(0, 58, 255);
|
||||
}
|
||||
|
||||
.answer-textarea {
|
||||
@@ -2713,8 +2732,8 @@ onMounted(() => {
|
||||
|
||||
.answer-textarea :deep(.el-textarea__inner) {
|
||||
border-radius: 12px;
|
||||
border: 2px solid rgba(93, 135, 255, 0.15);
|
||||
background: rgba(93, 135, 255, 0.02);
|
||||
/* border: 2px solid rgba(0, 58, 255, 0.15); */
|
||||
background: rgba(0, 58, 255, 0.02);
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
font-size: 15px;
|
||||
line-height: 1.5;
|
||||
@@ -2723,15 +2742,15 @@ onMounted(() => {
|
||||
}
|
||||
|
||||
.answer-textarea :deep(.el-textarea__inner):focus {
|
||||
border-color: rgb(93, 135, 255);
|
||||
background: rgba(93, 135, 255, 0.05);
|
||||
box-shadow: 0 0 0 4px rgba(93, 135, 255, 0.1);
|
||||
border-color: rgb(0, 58, 255);
|
||||
background: rgba(0, 58, 255, 0.05);
|
||||
box-shadow: 0 0 0 4px rgba(0, 58, 255, 0.1);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.answer-textarea :deep(.el-textarea__inner):hover {
|
||||
border-color: rgba(93, 135, 255, 0.3);
|
||||
background: rgba(93, 135, 255, 0.03);
|
||||
border-color: rgba(0, 58, 255, 0.3);
|
||||
background: rgba(0, 58, 255, 0.03);
|
||||
}
|
||||
|
||||
.answer-textarea :deep(.el-input__count) {
|
||||
@@ -2766,7 +2785,7 @@ onMounted(() => {
|
||||
justify-content: flex-end !important;
|
||||
gap: 16px;
|
||||
padding: 20px 0 0 0;
|
||||
border-top: 1px solid rgba(93, 135, 255, 0.1);
|
||||
border-top: 1px solid rgba(0, 58, 255, 0.1);
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
@@ -2799,28 +2818,28 @@ onMounted(() => {
|
||||
|
||||
/* 主要按钮样式 */
|
||||
.answer-dialog-footer .el-button--primary {
|
||||
background: rgba(93, 135, 255, 0.05);
|
||||
border: 2px solid rgb(93, 135, 255);
|
||||
color: rgb(93, 135, 255);
|
||||
background: rgba(0, 58, 255, 0.05);
|
||||
border: 2px solid rgb(0, 58, 255);
|
||||
color: rgb(0, 58, 255);
|
||||
}
|
||||
|
||||
.answer-dialog-footer .el-button--primary:hover:not(.is-loading) {
|
||||
background: rgba(93, 135, 255, 0.1);
|
||||
border-color: rgba(93, 135, 255, 0.8);
|
||||
color: rgb(93, 135, 255);
|
||||
background: rgba(0, 58, 255, 0.1);
|
||||
border-color: rgba(0, 58, 255, 0.8);
|
||||
color: rgb(0, 58, 255);
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 6px 20px rgba(93, 135, 255, 0.25);
|
||||
box-shadow: 0 6px 20px rgba(0, 58, 255, 0.25);
|
||||
}
|
||||
|
||||
.answer-dialog-footer .el-button--primary:active {
|
||||
transform: scale(0.98) translateY(-1px);
|
||||
background: rgba(93, 135, 255, 0.15);
|
||||
background: rgba(0, 58, 255, 0.15);
|
||||
}
|
||||
|
||||
.answer-dialog-footer .el-button--primary.is-loading {
|
||||
background: rgba(93, 135, 255, 0.08);
|
||||
border-color: rgba(93, 135, 255, 0.6);
|
||||
color: rgba(93, 135, 255, 0.8);
|
||||
background: rgba(0, 58, 255, 0.08);
|
||||
border-color: rgba(0, 58, 255, 0.6);
|
||||
color: rgba(0, 58, 255, 0.8);
|
||||
}
|
||||
|
||||
/* 禁用状态 */
|
||||
@@ -2855,13 +2874,13 @@ onMounted(() => {
|
||||
resize: both;
|
||||
overflow: auto;
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 20px 60px rgba(93, 135, 255, 0.15);
|
||||
border: 1px solid rgba(93, 135, 255, 0.1);
|
||||
box-shadow: 0 20px 60px rgba(0, 58, 255, 0.15);
|
||||
border: 1px solid rgba(0, 58, 255, 0.1);
|
||||
}
|
||||
|
||||
.question-view-dialog :deep(.el-dialog__header) {
|
||||
padding: 20px 24px 16px;
|
||||
border-bottom: 1px solid rgba(93, 135, 255, 0.1);
|
||||
border-bottom: 1px solid rgba(0, 58, 255, 0.1);
|
||||
background: linear-gradient(135deg, #fafbff 0%, #f8fafc 100%);
|
||||
border-radius: 16px 16px 0 0;
|
||||
}
|
||||
@@ -2944,4 +2963,157 @@ onMounted(() => {
|
||||
margin-bottom: 12px;
|
||||
padding: 10px 14px;
|
||||
}
|
||||
|
||||
/* 查看题目对话框中单选和多选选项样式继承答题界面样式 */
|
||||
.question-view-dialog .answer-display-area .answer-options-horizontal {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 12px;
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
||||
/* 移除Element Plus默认的禁用状态灰色背景和文本颜色 */
|
||||
.question-view-dialog :deep(.el-checkbox.is-disabled),
|
||||
.question-view-dialog :deep(.el-radio.is-disabled) {
|
||||
background-color: transparent !important;
|
||||
color: #475569 !important;
|
||||
filter: none !important;
|
||||
}
|
||||
|
||||
.question-view-dialog .answer-option-horizontal.is-checked {
|
||||
background: rgba(0, 58, 255, 0.1);
|
||||
border-color: rgb(0, 58, 255);
|
||||
color: rgb(0, 58, 255);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* 禁用状态下保持正常文本颜色 */
|
||||
.question-view-dialog .answer-option-horizontal :deep(.el-radio__label),
|
||||
.question-view-dialog .answer-option-horizontal :deep(.el-checkbox__label) {
|
||||
color: #475569 !important;
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
/* 确保禁用状态下不会变暗 */
|
||||
.question-view-dialog .answer-option-horizontal :deep(.el-radio__input.is-disabled),
|
||||
.question-view-dialog .answer-option-horizontal :deep(.el-checkbox__input.is-disabled) {
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.question-view-dialog .answer-option-horizontal :deep(.el-radio.is-disabled),
|
||||
.question-view-dialog .answer-option-horizontal :deep(.el-checkbox.is-disabled) {
|
||||
cursor: default;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* 禁用状态下保持选中颜色 */
|
||||
.question-view-dialog .answer-option-horizontal.is-checked :deep(.el-radio__input.is-disabled .el-radio__inner),
|
||||
.question-view-dialog .answer-option-horizontal.is-checked :deep(.el-checkbox__input.is-disabled .el-checkbox__inner) {
|
||||
background-color: rgb(0, 58, 255) !important;
|
||||
border-color: rgb(0, 58, 255) !important;
|
||||
}
|
||||
|
||||
/* 移除默认的禁用样式效果 */
|
||||
.question-view-dialog :deep(.el-radio__input.is-disabled + span.el-radio__label),
|
||||
.question-view-dialog :deep(.el-checkbox__input.is-disabled + span.el-checkbox__label) {
|
||||
color: #475569 !important;
|
||||
}
|
||||
|
||||
/* 覆盖全局禁用样式 */
|
||||
:deep(.el-radio__input.is-disabled + span.el-radio__label) {
|
||||
color: #303133 !important;
|
||||
}
|
||||
:deep(.el-checkbox__input.is-disabled + span.el-checkbox__label) {
|
||||
color: #303133 !important;
|
||||
}
|
||||
|
||||
/* 最高优先级覆盖多选框发黑问题 */
|
||||
.question-view-dialog :deep(.answer-option-horizontal .el-checkbox.is-disabled) {
|
||||
background-color: transparent !important;
|
||||
filter: none !important;
|
||||
}
|
||||
|
||||
.question-view-dialog :deep(.answer-option-horizontal .el-checkbox.is-disabled .el-checkbox__label) {
|
||||
color: #475569 !important;
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
/* 确保多选框背景色不受禁用影响 */
|
||||
.question-view-dialog :deep(.answer-option-horizontal) {
|
||||
background-color: transparent !important;
|
||||
filter: none !important;
|
||||
}
|
||||
|
||||
/* 查看题目对话框中的答案选项美化 */
|
||||
.question-card .answer-option-horizontal {
|
||||
display: inline-flex !important;
|
||||
align-items: center;
|
||||
white-space: nowrap;
|
||||
margin-bottom: 8px !important;
|
||||
padding: 6px 14px;
|
||||
border-radius: 20px;
|
||||
transition: all 0.3s ease;
|
||||
font-weight: 500;
|
||||
color: #475569;
|
||||
position: relative;
|
||||
background-color: transparent !important;
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
|
||||
/* 选中状态特殊样式 */
|
||||
.question-card .answer-option-horizontal.is-checked {
|
||||
background: rgba(0, 58, 255, 0.1);
|
||||
color: rgb(0, 58, 255);
|
||||
font-weight: 600;
|
||||
box-shadow: 0 2px 8px rgba(0, 58, 255, 0.15);
|
||||
}
|
||||
|
||||
/* 确保禁用状态下单选/多选按钮的颜色正确 */
|
||||
.question-card .answer-option-horizontal.is-checked :deep(.el-radio__input.is-disabled .el-radio__inner::after) {
|
||||
background-color: white !important;
|
||||
}
|
||||
|
||||
/* 强化多选框选中状态的显示效果 */
|
||||
.question-card .answer-option-horizontal.is-checked :deep(.el-checkbox__input.is-disabled.is-checked .el-checkbox__inner) {
|
||||
background-color: rgb(0, 58, 255) !important;
|
||||
border-color: rgb(0, 58, 255) !important;
|
||||
}
|
||||
|
||||
.question-card .answer-option-horizontal.is-checked :deep(.el-checkbox__input.is-disabled.is-checked .el-checkbox__inner::after) {
|
||||
border-color: white !important;
|
||||
transform: rotate(45deg) scaleY(1) !important;
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
/* 未选中状态下的单选/多选按钮样式调整 */
|
||||
.question-card .answer-option-horizontal :deep(.el-radio__input.is-disabled .el-radio__inner) {
|
||||
background-color: white !important;
|
||||
border-color: #c0c4cc !important;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.question-card .answer-option-horizontal :deep(.el-checkbox__input.is-disabled .el-checkbox__inner) {
|
||||
background-color: white !important;
|
||||
border-color: #c0c4cc !important;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
/* 专门针对多选框的禁用样式增强 */
|
||||
.question-card .answer-option-horizontal :deep(.el-checkbox.is-disabled) {
|
||||
opacity: 1 !important;
|
||||
filter: none !important;
|
||||
}
|
||||
|
||||
.question-card .answer-option-horizontal :deep(.el-checkbox.is-disabled .el-checkbox__input) {
|
||||
filter: none !important;
|
||||
}
|
||||
|
||||
.question-card .answer-option-horizontal :deep(.el-checkbox.is-disabled .el-checkbox__label) {
|
||||
color: #475569 !important;
|
||||
}
|
||||
|
||||
.question-card .answer-display-area .el-radio,
|
||||
.question-card .answer-display-area .el-checkbox {
|
||||
margin-right: 20px !important;
|
||||
}
|
||||
</style>
|
||||
@@ -104,7 +104,7 @@
|
||||
<!-- <el-table-column label="题目内容" align="center" prop="questionContent" /> -->
|
||||
<el-table-column label="所属分类" align="center" prop="categoryId">
|
||||
<template #default="scope">
|
||||
{{ satCategoryList.find((cat) => cat.id == scope.row.categoryId)?.categoryName || '--' }}
|
||||
{{ satCategoryAllList.find((cat) => cat.id == scope.row.categoryId)?.categoryName || '--' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="题目类型" align="center" prop="questionType">
|
||||
@@ -210,7 +210,7 @@
|
||||
<script setup name="SatQuestion" lang="ts">
|
||||
import { listSatQuestion, getSatQuestion, delSatQuestion, addSatQuestion, updateSatQuestion } from '@/api/hq/satQuestion';
|
||||
import { SatQuestionVO, SatQuestionQuery, SatQuestionForm } from '@/api/hq/satQuestion/types';
|
||||
import { listSatCategory } from '@/api/hq/satCategory';
|
||||
import { listSatCategory, listAllSatCategory } from '@/api/hq/satCategory';
|
||||
import { SatCategoryVO } from '@/api/hq/satCategory/types';
|
||||
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
@@ -220,6 +220,7 @@ const { sys_question_category, sys_item_enable, sys_item_required, sys_item_dele
|
||||
|
||||
const satQuestionList = ref<SatQuestionVO[]>([]);
|
||||
const satCategoryList = ref<SatCategoryVO[]>([]);
|
||||
const satCategoryAllList = ref<SatCategoryVO[]>([]);
|
||||
const buttonLoading = ref(false);
|
||||
const loading = ref(true);
|
||||
const showSearch = ref(true);
|
||||
@@ -291,6 +292,15 @@ const getCategoryList = async () => {
|
||||
satCategoryList.value = res.rows.sort((a, b) => a.sortOrder - b.sortOrder); // 按sort_order排序
|
||||
};
|
||||
|
||||
/** 获取全部分类列表(包括已删除的) */
|
||||
const getAllCategoryList = async () => {
|
||||
const res = await listAllSatCategory({
|
||||
pageNum: 1,
|
||||
pageSize: 1000
|
||||
}); // 获取所有分类,包括已删除的
|
||||
satCategoryAllList.value = res.data.sort((a, b) => a.sortOrder - b.sortOrder); // 按sort_order排序
|
||||
};
|
||||
|
||||
/** 取消按钮 */
|
||||
const cancel = () => {
|
||||
reset();
|
||||
@@ -392,6 +402,7 @@ const searchRef = ref<HTMLElement>();
|
||||
onMounted(() => {
|
||||
getList();
|
||||
getCategoryList();
|
||||
getAllCategoryList();
|
||||
});
|
||||
</script>
|
||||
<style scoped>
|
||||
|
||||
@@ -59,16 +59,16 @@
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="6">
|
||||
<!-- <el-form-item label="最大提交次数" prop="maxSubmitTimes">
|
||||
<!-- <el-col :span="6"> -->
|
||||
<!-- <el-form-item label="最大提交次数" prop="maxSubmitTimes">
|
||||
<el-input v-model="queryParams.maxSubmitTimes" placeholder="请输入最大提交次数" clearable @keyup.enter="handleQuery" />
|
||||
</el-form-item> -->
|
||||
<el-form-item label="是否匿名" prop="isAnonymous">
|
||||
<!-- <el-form-item label="是否匿名" prop="isAnonymous">
|
||||
<el-select v-model="queryParams.isAnonymous" placeholder="请选择是否匿名" clearable>
|
||||
<el-option v-for="dict in sys_yesno" :key="dict.value" :label="dict.label" :value="dict.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-col> -->
|
||||
<el-col :span="6">
|
||||
<el-form-item label="是否发布" prop="isPublished">
|
||||
<el-select v-model="queryParams.isPublished" placeholder="请选择是否发布" clearable>
|
||||
@@ -137,8 +137,6 @@
|
||||
</el-table-column> -->
|
||||
<el-table-column label="问卷编号" align="center" prop="surveyCode" width="140" show-overflow-tooltip />
|
||||
<el-table-column label="问卷标题" align="center" prop="surveyTitle" min-width="200" show-overflow-tooltip />
|
||||
<el-table-column label="问卷描述" align="center" prop="surveyDesc" min-width="250" show-overflow-tooltip />
|
||||
<el-table-column label="填写说明" align="center" prop="surveyInstruction" min-width="250" show-overflow-tooltip />
|
||||
<el-table-column label="目标群体" align="center" prop="targetGroup" width="120">
|
||||
<template #default="scope">
|
||||
<dict-tag :options="sys_survey_people" :value="scope.row.targetGroup" />
|
||||
@@ -146,20 +144,20 @@
|
||||
</el-table-column>
|
||||
<el-table-column label="开始时间" align="center" prop="startTime" width="180">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.startTime, '{y}-{m}-{d}') }}</span>
|
||||
<span>{{ parseTime(scope.row.startTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="结束时间" align="center" prop="endTime" width="180">
|
||||
<template #default="scope">
|
||||
<span>{{ parseTime(scope.row.endTime, '{y}-{m}-{d}') }}</span>
|
||||
<span>{{ parseTime(scope.row.endTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- <el-table-column label="最大提交次数" align="center" prop="maxSubmitTimes" /> -->
|
||||
<el-table-column label="是否匿名" align="center" prop="isAnonymous" width="100">
|
||||
<!-- <el-table-column label="是否匿名" align="center" prop="isAnonymous" width="100">
|
||||
<template #default="scope">
|
||||
<dict-tag :options="sys_yesno" :value="scope.row.isAnonymous" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table-column> -->
|
||||
<el-table-column label="是否发布" align="center" prop="isPublished" width="100">
|
||||
<template #default="scope">
|
||||
<dict-tag :options="sys_yesno" :value="scope.row.isPublished" />
|
||||
@@ -170,6 +168,8 @@
|
||||
<dict-tag :options="sys_survey_status" :value="scope.row.status" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="问卷描述" align="center" prop="surveyDesc" min-width="250" show-overflow-tooltip />
|
||||
<el-table-column label="填写说明" align="center" prop="surveyInstruction" min-width="250" show-overflow-tooltip />
|
||||
<el-table-column label="备注" align="center" prop="remark" min-width="200" show-overflow-tooltip />
|
||||
<el-table-column label="操作" align="center" width="280" fixed="right" class-name="small-padding fixed-width">
|
||||
<template #default="scope">
|
||||
@@ -339,6 +339,10 @@
|
||||
<div v-for="(question, index) in selectedQuestions" :key="question.id || question.questionId" class="question-card">
|
||||
<div class="question-header">
|
||||
<div class="question-number">第 {{ index + 1 }} 题</div>
|
||||
<div class="question-meta-info">
|
||||
<el-tag size="small" type="primary">{{ getQuestionType(question.questionType) }}</el-tag>
|
||||
<el-tag v-if="question.isRequired === 1 || question.isRequired === '1'" size="small" type="danger">必填</el-tag>
|
||||
</div>
|
||||
<div class="question-actions" v-if="!readonly">
|
||||
<el-button type="text" size="small" @click="removeQuestion(index)">
|
||||
<el-icon><Delete /></el-icon>
|
||||
@@ -348,10 +352,6 @@
|
||||
|
||||
<div class="question-content-display">
|
||||
<div class="question-title-display">{{ question.questionTitle }}</div>
|
||||
<div class="question-meta-info">
|
||||
<el-tag size="small" type="primary">{{ getQuestionType(question.questionType) }}</el-tag>
|
||||
<el-tag v-if="question.isRequired === 1 || question.isRequired === '1'" size="small" type="danger">必填</el-tag>
|
||||
</div>
|
||||
|
||||
<!-- 题目答案展示区域 -->
|
||||
<div class="answer-display-area">
|
||||
@@ -445,7 +445,7 @@
|
||||
class="selector-question-item"
|
||||
@click="toggleQuestionSelection(question.id)"
|
||||
>
|
||||
<div class="selector-question-checkbox">
|
||||
<div class="selector-question-checkbox" @click.stop>
|
||||
<el-checkbox :model-value="selectedQuestionIds.includes(question.id)" @change="toggleQuestionSelection(question.id)" />
|
||||
</div>
|
||||
<div class="selector-question-content">
|
||||
@@ -991,6 +991,7 @@ import { listSatQuestion, getQuestionOptions } from '@/api/hq/satQuestion';
|
||||
import { SatQuestionVO } from '@/api/hq/satQuestion/types';
|
||||
import { listSatCategory } from '@/api/hq/satCategory';
|
||||
import { SatCategoryVO } from '@/api/hq/satCategory/types';
|
||||
import { createUniqueString } from '@/utils/index';
|
||||
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const { sys_survey_people, sys_item_delete, sys_survey_status, sys_yesno } = toRefs<any>(
|
||||
@@ -1156,6 +1157,13 @@ const handleSelectionChange = (selection: SatSurveyVO[]) => {
|
||||
/** 新增按钮操作 */
|
||||
const handleAdd = () => {
|
||||
reset();
|
||||
// 自动生成唯一问卷编号,格式可自定义(如 SAT-20240715-xxxxxx)
|
||||
const now = new Date();
|
||||
const yyyy = now.getFullYear();
|
||||
const mm = String(now.getMonth() + 1).padStart(2, '0');
|
||||
const dd = String(now.getDate()).padStart(2, '0');
|
||||
const prefix = `SAT-${yyyy}${mm}${dd}`;
|
||||
form.value.surveyCode = `${prefix}-${createUniqueString()}`;
|
||||
dialog.visible = true;
|
||||
dialog.title = '添加问卷';
|
||||
};
|
||||
@@ -1556,6 +1564,7 @@ const openQuestionSelector = () => {
|
||||
|
||||
/** 切换题目选择状态 */
|
||||
const toggleQuestionSelection = (questionId: string | number) => {
|
||||
// 处理点击行时的选择/取消选择
|
||||
const index = selectedQuestionIds.value.indexOf(questionId);
|
||||
if (index > -1) {
|
||||
selectedQuestionIds.value.splice(index, 1);
|
||||
@@ -1566,11 +1575,19 @@ const toggleQuestionSelection = (questionId: string | number) => {
|
||||
|
||||
/** 全选/取消全选 */
|
||||
const toggleSelectAll = (checked: boolean) => {
|
||||
// 强制刷新所有复选框状态
|
||||
if (checked) {
|
||||
selectedQuestionIds.value = filteredAvailableQuestions.value.map((q) => q.id);
|
||||
// 全选 - 使用所有过滤后的题目ID
|
||||
selectedQuestionIds.value = [...filteredAvailableQuestions.value.map((q) => q.id)];
|
||||
} else {
|
||||
// 清空选择
|
||||
selectedQuestionIds.value = [];
|
||||
}
|
||||
|
||||
// 强制下一个事件循环中重新渲染
|
||||
nextTick(() => {
|
||||
console.log(`选择状态已更新: ${selectedQuestionIds.value.length} 个题目被选中`);
|
||||
});
|
||||
};
|
||||
|
||||
/** 确认添加选中的题目 */
|
||||
@@ -2272,9 +2289,9 @@ onMounted(() => {
|
||||
|
||||
.question-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
padding: 12px 16px;
|
||||
padding: 4px 16px;
|
||||
background: #f8f9fa;
|
||||
border-bottom: 1px solid #e4e7ed;
|
||||
border-radius: 8px 8px 0 0;
|
||||
@@ -2282,13 +2299,14 @@ onMounted(() => {
|
||||
|
||||
.question-number {
|
||||
font-weight: 600;
|
||||
color: #409eff;
|
||||
color: var(--el-color-primary);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.question-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.question-content-display {
|
||||
@@ -2306,7 +2324,8 @@ onMounted(() => {
|
||||
.question-meta-info {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
margin-bottom: 16px;
|
||||
margin: 0 16px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.answer-display-area {
|
||||
@@ -2314,7 +2333,8 @@ onMounted(() => {
|
||||
}
|
||||
|
||||
.answer-option {
|
||||
display: block !important;
|
||||
display: inline-flex !important;
|
||||
margin-right: 56px;
|
||||
margin-bottom: 8px;
|
||||
white-space: normal;
|
||||
word-break: break-all;
|
||||
|
||||
Reference in new issue
Block a user