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);
|
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;
|
private Long deleted;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
+8
@@ -41,6 +41,14 @@ public interface IHqSatCategoryService {
|
|||||||
*/
|
*/
|
||||||
List<HqSatCategoryVo> queryList(HqSatCategoryBo bo);
|
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.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 题目分类Service业务层处理
|
* 题目分类Service业务层处理
|
||||||
@@ -70,6 +72,41 @@ public class HqSatCategoryServiceImpl implements IHqSatCategoryService {
|
|||||||
return baseMapper.selectVoList(lqw);
|
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) {
|
private LambdaQueryWrapper<HqSatCategory> buildQueryWrapper(HqSatCategoryBo bo) {
|
||||||
Map<String, Object> params = bo.getParams();
|
Map<String, Object> params = bo.getParams();
|
||||||
LambdaQueryWrapper<HqSatCategory> lqw = Wrappers.lambdaQuery();
|
LambdaQueryWrapper<HqSatCategory> lqw = Wrappers.lambdaQuery();
|
||||||
@@ -132,7 +169,6 @@ public class HqSatCategoryServiceImpl implements IHqSatCategoryService {
|
|||||||
if (isValid) {
|
if (isValid) {
|
||||||
// TODO 做一些业务上的校验,判断是否需要校验
|
// TODO 做一些业务上的校验,判断是否需要校验
|
||||||
}
|
}
|
||||||
// 逻辑删除实现
|
return baseMapper.deleteBatchIds(ids) > 0;
|
||||||
return baseMapper.deleteByIds(ids) > 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+2
-2
@@ -104,8 +104,8 @@ public class HqSatSurveyServiceImpl implements IHqSatSurveyService {
|
|||||||
LambdaQueryWrapper<HqSatSurvey> lqw = Wrappers.lambdaQuery();
|
LambdaQueryWrapper<HqSatSurvey> lqw = Wrappers.lambdaQuery();
|
||||||
lqw.orderByAsc(HqSatSurvey::getId);
|
lqw.orderByAsc(HqSatSurvey::getId);
|
||||||
lqw.eq(bo.getDeleted() != null, HqSatSurvey::getDeleted, bo.getDeleted());
|
lqw.eq(bo.getDeleted() != null, HqSatSurvey::getDeleted, bo.getDeleted());
|
||||||
lqw.eq(StringUtils.isNotBlank(bo.getSurveyCode()), HqSatSurvey::getSurveyCode, bo.getSurveyCode());
|
lqw.like(StringUtils.isNotBlank(bo.getSurveyCode()), HqSatSurvey::getSurveyCode, bo.getSurveyCode());
|
||||||
lqw.eq(StringUtils.isNotBlank(bo.getSurveyTitle()), HqSatSurvey::getSurveyTitle, bo.getSurveyTitle());
|
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.getSurveyDesc()), HqSatSurvey::getSurveyDesc, bo.getSurveyDesc());
|
||||||
lqw.eq(StringUtils.isNotBlank(bo.getSurveyInstruction()), HqSatSurvey::getSurveyInstruction,
|
lqw.eq(StringUtils.isNotBlank(bo.getSurveyInstruction()), HqSatSurvey::getSurveyInstruction,
|
||||||
bo.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
|
* @param id
|
||||||
|
|||||||
@@ -72,6 +72,8 @@ export default {
|
|||||||
confirmButtonText: '确定',
|
confirmButtonText: '确定',
|
||||||
cancelButtonText: '取消',
|
cancelButtonText: '取消',
|
||||||
type: 'warning',
|
type: 'warning',
|
||||||
|
// 允许在内容中使用 HTML
|
||||||
|
dangerouslyUseHTMLString: true,
|
||||||
// 使用自定义样式类确保按钮样式正确应用
|
// 使用自定义样式类确保按钮样式正确应用
|
||||||
confirmButtonClass: 'el-button--primary',
|
confirmButtonClass: 'el-button--primary',
|
||||||
cancelButtonClass: 'el-button--default'
|
cancelButtonClass: 'el-button--default'
|
||||||
|
|||||||
+18
-2
@@ -29,7 +29,23 @@ export const useDict = (...args: string[]) => {
|
|||||||
console.log(`字典 ${dictType} API响应:`, resp);
|
console.log(`字典 ${dictType} API响应:`, resp);
|
||||||
|
|
||||||
if (resp && resp.data && Array.isArray(resp.data) && resp.data.length > 0) {
|
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 => ({
|
(p): DictDataOption => ({
|
||||||
label: p.dictLabel,
|
label: p.dictLabel,
|
||||||
value: p.dictValue,
|
value: p.dictValue,
|
||||||
@@ -39,7 +55,7 @@ export const useDict = (...args: string[]) => {
|
|||||||
);
|
);
|
||||||
res[dictType] = dictData;
|
res[dictType] = dictData;
|
||||||
useDictStore().setDict(dictType, dictData);
|
useDictStore().setDict(dictType, dictData);
|
||||||
console.log(`字典 ${dictType} 加载成功,数据:`, dictData);
|
console.log(`字典 ${dictType} 加载成功并按dictSort排序,数据:`, dictData);
|
||||||
} else {
|
} else {
|
||||||
console.warn(`字典类型 ${dictType} 没有返回有效数据,响应:`, resp);
|
console.warn(`字典类型 ${dictType} 没有返回有效数据,响应:`, resp);
|
||||||
res[dictType] = [];
|
res[dictType] = [];
|
||||||
|
|||||||
@@ -245,12 +245,17 @@
|
|||||||
<!-- 题目答案展示区域 -->
|
<!-- 题目答案展示区域 -->
|
||||||
<div class="answer-display-area">
|
<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
|
<el-radio
|
||||||
v-for="(option, index) in question.options || []"
|
v-for="(option, index) in question.options || []"
|
||||||
:key="option.id"
|
:key="option.id"
|
||||||
:label="String.fromCharCode(65 + index)"
|
:label="String.fromCharCode(65 + index)"
|
||||||
class="answer-option"
|
class="answer-option-horizontal"
|
||||||
>
|
>
|
||||||
{{ String.fromCharCode(65 + index) }}. {{ option.optionText }}
|
{{ String.fromCharCode(65 + index) }}. {{ option.optionText }}
|
||||||
</el-radio>
|
</el-radio>
|
||||||
@@ -261,12 +266,13 @@
|
|||||||
v-else-if="question.questionType === '2' || question.questionType === 2"
|
v-else-if="question.questionType === '2' || question.questionType === 2"
|
||||||
:model-value="question.userAnswer || []"
|
:model-value="question.userAnswer || []"
|
||||||
disabled
|
disabled
|
||||||
|
class="answer-options-horizontal"
|
||||||
>
|
>
|
||||||
<el-checkbox
|
<el-checkbox
|
||||||
v-for="(option, index) in question.options || []"
|
v-for="(option, index) in question.options || []"
|
||||||
:key="option.id"
|
:key="option.id"
|
||||||
:label="String.fromCharCode(65 + index)"
|
:label="String.fromCharCode(65 + index)"
|
||||||
class="answer-option"
|
class="answer-option-horizontal"
|
||||||
>
|
>
|
||||||
{{ String.fromCharCode(65 + index) }}. {{ option.optionText }}
|
{{ String.fromCharCode(65 + index) }}. {{ option.optionText }}
|
||||||
</el-checkbox>
|
</el-checkbox>
|
||||||
@@ -402,12 +408,14 @@
|
|||||||
<!-- 问卷信息头部 -->
|
<!-- 问卷信息头部 -->
|
||||||
<div class="survey-header" v-if="currentAnswerSurvey">
|
<div class="survey-header" v-if="currentAnswerSurvey">
|
||||||
<div class="survey-info">
|
<div class="survey-info">
|
||||||
<h3 class="survey-title">{{ currentAnswerSurvey.surveyTitle }}</h3>
|
<h3 class="survey-title">
|
||||||
<div class="survey-meta">
|
{{ currentAnswerSurvey.surveyTitle }}
|
||||||
<el-tag size="small" type="primary">{{ answerQuestions.length }} 题</el-tag>
|
<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 ? '匿名问卷' : '实名问卷' }}
|
{{ currentAnswerSurvey.isAnonymous === 1 ? '匿名问卷' : '实名问卷' }}
|
||||||
</el-tag>
|
</el-tag> -->
|
||||||
</div>
|
</div>
|
||||||
<div class="survey-description" v-if="currentAnswerSurvey.surveyDesc">
|
<div class="survey-description" v-if="currentAnswerSurvey.surveyDesc">
|
||||||
{{ currentAnswerSurvey.surveyDesc }}
|
{{ currentAnswerSurvey.surveyDesc }}
|
||||||
@@ -483,10 +491,10 @@
|
|||||||
|
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<div class="dialog-footer answer-dialog-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">
|
<el-button type="primary" :loading="answerSubmitting" @click="submitAnswer" :disabled="answerQuestions.length === 0">
|
||||||
{{ answerSubmitting ? '提交中...' : '提交答卷' }}
|
{{ answerSubmitting ? '提交中...' : '提交答卷' }}
|
||||||
</el-button>
|
</el-button>
|
||||||
|
<el-button @click="closeAnswerDialog">取消</el-button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
@@ -950,7 +958,8 @@ const handleStartSurvey = async (row: SatSurveyVO) => {
|
|||||||
console.log(`问卷包含 ${questions.length} 个题目,可以开始答题`);
|
console.log(`问卷包含 ${questions.length} 个题目,可以开始答题`);
|
||||||
|
|
||||||
// 3. 显示确认对话框
|
// 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);
|
await proxy?.$modal.confirm(confirmMessage);
|
||||||
|
|
||||||
@@ -1125,8 +1134,20 @@ const loadPreviousAnswers = async (surveyId: string | number, formData: Record<s
|
|||||||
console.error('=== 加载历史答案发生错误 ===');
|
console.error('=== 加载历史答案发生错误 ===');
|
||||||
console.error('错误详情:', error);
|
console.error('错误详情:', error);
|
||||||
|
|
||||||
// 如果是404错误,说明用户没有答过这个问卷,这是正常情况
|
// // 如果是404错误,说明用户没有答过这个问卷,这是正常情况
|
||||||
if ((error as any)?.response?.status === 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('✅ 用户尚未答过此问卷,使用空表单(正常情况)');
|
console.log('✅ 用户尚未答过此问卷,使用空表单(正常情况)');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -2057,7 +2078,7 @@ onMounted(() => {
|
|||||||
|
|
||||||
.question-number {
|
.question-number {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: #409eff;
|
color: var(--el-color-primary);
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
@@ -2099,6 +2120,7 @@ onMounted(() => {
|
|||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 旧版单选/多选选项样式 - 仅保留兼容 */
|
||||||
.answer-option {
|
.answer-option {
|
||||||
display: block !important;
|
display: block !important;
|
||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
@@ -2120,12 +2142,12 @@ onMounted(() => {
|
|||||||
.answer-display-area .el-checkbox {
|
.answer-display-area .el-checkbox {
|
||||||
display: inline-flex !important;
|
display: inline-flex !important;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-right: 0 !important;
|
margin-right: 56px !important;
|
||||||
margin-bottom: 0 !important;
|
margin-bottom: 0 !important;
|
||||||
padding: 6px 12px;
|
padding: 6px 12px;
|
||||||
border: 1px solid #e4e7ed;
|
/* border: 1px solid #e4e7ed; */
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
background: #fafbfc;
|
/* background: #fafbfc; */
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
@@ -2133,9 +2155,9 @@ onMounted(() => {
|
|||||||
|
|
||||||
.answer-display-area .el-radio.is-checked,
|
.answer-display-area .el-radio.is-checked,
|
||||||
.answer-display-area .el-checkbox.is-checked {
|
.answer-display-area .el-checkbox.is-checked {
|
||||||
background: rgba(93, 135, 255, 0.1);
|
/* background: rgba(0, 58, 255, 0.1); */
|
||||||
border-color: rgba(93, 135, 255, 0.3);
|
border-color: rgba(0, 58, 255, 0.3);
|
||||||
color: rgb(93, 135, 255);
|
color: rgb(0, 58, 255);
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2428,13 +2450,13 @@ onMounted(() => {
|
|||||||
resize: both;
|
resize: both;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
border-radius: 16px;
|
border-radius: 16px;
|
||||||
box-shadow: 0 20px 60px rgba(93, 135, 255, 0.15);
|
box-shadow: 0 20px 60px rgba(0, 58, 255, 0.15);
|
||||||
border: 1px solid rgba(93, 135, 255, 0.1);
|
border: 1px solid rgba(0, 58, 255, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.answer-dialog :deep(.el-dialog__header) {
|
.answer-dialog :deep(.el-dialog__header) {
|
||||||
padding: 24px 32px 16px;
|
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%);
|
background: linear-gradient(135deg, #fafbff 0%, #f8fafc 100%);
|
||||||
border-radius: 16px 16px 0 0;
|
border-radius: 16px 16px 0 0;
|
||||||
}
|
}
|
||||||
@@ -2467,8 +2489,8 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.answer-dialog :deep(.el-dialog__body) {
|
.answer-dialog :deep(.el-dialog__body) {
|
||||||
max-height: 75vh;
|
max-height: 65vh; /* 设置最大高度 */
|
||||||
overflow-y: auto;
|
overflow-y: auto; /* 启用垂直滚动 */
|
||||||
padding: 20px 24px;
|
padding: 20px 24px;
|
||||||
background: #ffffff;
|
background: #ffffff;
|
||||||
}
|
}
|
||||||
@@ -2480,7 +2502,7 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.answer-container {
|
.answer-container {
|
||||||
min-height: 400px;
|
/* min-height: 400px; */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 问卷信息头部 */
|
/* 问卷信息头部 */
|
||||||
@@ -2489,12 +2511,12 @@ onMounted(() => {
|
|||||||
padding: 18px;
|
padding: 18px;
|
||||||
background: linear-gradient(135deg, #f0f9ff 0%, #f8fafc 100%);
|
background: linear-gradient(135deg, #f0f9ff 0%, #f8fafc 100%);
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
border: 1px solid rgba(93, 135, 255, 0.1);
|
border: 1px solid rgba(0, 58, 255, 0.1);
|
||||||
box-shadow: 0 2px 8px rgba(93, 135, 255, 0.08);
|
box-shadow: 0 2px 8px rgba(0, 58, 255, 0.08);
|
||||||
}
|
}
|
||||||
|
|
||||||
.survey-title {
|
.survey-title {
|
||||||
margin: 0 0 12px 0;
|
margin: 0 0 3px 0;
|
||||||
font-size: 22px;
|
font-size: 22px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: #1e293b;
|
color: #1e293b;
|
||||||
@@ -2512,8 +2534,8 @@ onMounted(() => {
|
|||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
border: none;
|
border: none;
|
||||||
background: rgba(93, 135, 255, 0.1);
|
background: rgba(0, 58, 255, 0.1);
|
||||||
color: rgb(93, 135, 255);
|
color: rgb(0, 58, 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
.survey-meta .el-tag.el-tag--success {
|
.survey-meta .el-tag.el-tag--success {
|
||||||
@@ -2522,7 +2544,7 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.survey-description {
|
.survey-description {
|
||||||
color: #475569;
|
color: #000000;
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
@@ -2541,8 +2563,8 @@ onMounted(() => {
|
|||||||
|
|
||||||
/* 答题表单 */
|
/* 答题表单 */
|
||||||
.answer-form {
|
.answer-form {
|
||||||
max-height: 60vh;
|
/* max-height: 65vh; */ /* 移除最大高度限制 */
|
||||||
overflow-y: auto;
|
overflow-y: visible; /* 移除垂直滚动 */
|
||||||
padding-right: 12px;
|
padding-right: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2550,7 +2572,7 @@ onMounted(() => {
|
|||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
background: linear-gradient(135deg, #ffffff 0%, #fafbff 100%);
|
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;
|
border-radius: 12px;
|
||||||
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
|
transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
position: relative;
|
position: relative;
|
||||||
@@ -2564,14 +2586,14 @@ onMounted(() => {
|
|||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
height: 3px;
|
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);
|
transform: scaleX(0);
|
||||||
transition: transform 0.3s ease;
|
transition: transform 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.question-item:hover {
|
.question-item:hover {
|
||||||
border-color: rgba(93, 135, 255, 0.2);
|
border-color: rgba(0, 58, 255, 0.2);
|
||||||
box-shadow: 0 8px 24px rgba(93, 135, 255, 0.12);
|
box-shadow: 0 8px 24px rgba(0, 58, 255, 0.12);
|
||||||
transform: translateY(-2px);
|
transform: translateY(-2px);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2583,7 +2605,7 @@ onMounted(() => {
|
|||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 10px 14px;
|
padding: 4px 14px;
|
||||||
background: #f8f9fa;
|
background: #f8f9fa;
|
||||||
border-bottom: 1px solid #e4e7ed;
|
border-bottom: 1px solid #e4e7ed;
|
||||||
border-radius: 8px 8px 0 0;
|
border-radius: 8px 8px 0 0;
|
||||||
@@ -2591,12 +2613,9 @@ onMounted(() => {
|
|||||||
|
|
||||||
.question-number {
|
.question-number {
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: rgb(93, 135, 255);
|
/* color: rgb(0, 58, 255); */
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
padding: 4px 12px;
|
padding: 4px 12px;
|
||||||
background: rgba(93, 135, 255, 0.1);
|
|
||||||
border-radius: 20px;
|
|
||||||
border: 1px solid rgba(93, 135, 255, 0.2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.question-title {
|
.question-title {
|
||||||
@@ -2640,9 +2659,9 @@ onMounted(() => {
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
margin-bottom: 0 !important;
|
margin-bottom: 0 !important;
|
||||||
padding: 8px 16px;
|
padding: 8px 16px;
|
||||||
border: 2px solid rgba(93, 135, 255, 0.15);
|
/* border: 2px solid rgba(0, 58, 255, 0.15); */
|
||||||
border-radius: 20px;
|
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);
|
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
@@ -2658,16 +2677,16 @@ onMounted(() => {
|
|||||||
left: -100%;
|
left: -100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 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;
|
transition: left 0.5s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.answer-option-horizontal:hover {
|
.answer-option-horizontal:hover {
|
||||||
background: rgba(93, 135, 255, 0.08);
|
background: rgba(0, 58, 255, 0.08);
|
||||||
border-color: rgba(93, 135, 255, 0.3);
|
border-color: rgba(0, 58, 255, 0.3);
|
||||||
color: rgb(93, 135, 255);
|
color: rgb(0, 58, 255);
|
||||||
transform: translateY(-1px);
|
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 {
|
.answer-option-horizontal:hover::before {
|
||||||
@@ -2675,11 +2694,11 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.answer-option-horizontal.is-checked {
|
.answer-option-horizontal.is-checked {
|
||||||
background: rgba(93, 135, 255, 0.1);
|
background: rgba(0, 58, 255, 0.1);
|
||||||
border-color: rgb(93, 135, 255);
|
border-color: rgb(0, 58, 255);
|
||||||
color: rgb(93, 135, 255);
|
color: rgb(0, 58, 255);
|
||||||
font-weight: 600;
|
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),
|
.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-radio__input.is-checked .el-radio__inner),
|
||||||
.answer-option-horizontal :deep(.el-checkbox__input.is-checked .el-checkbox__inner) {
|
.answer-option-horizontal :deep(.el-checkbox__input.is-checked .el-checkbox__inner) {
|
||||||
border-color: rgb(93, 135, 255);
|
border-color: rgb(0, 58, 255);
|
||||||
background-color: rgb(93, 135, 255);
|
background-color: rgb(0, 58, 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
.answer-option-horizontal :deep(.el-radio__inner),
|
.answer-option-horizontal :deep(.el-radio__inner),
|
||||||
.answer-option-horizontal :deep(.el-checkbox__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;
|
transition: all 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.answer-option-horizontal:hover :deep(.el-radio__inner),
|
.answer-option-horizontal:hover :deep(.el-radio__inner),
|
||||||
.answer-option-horizontal:hover :deep(.el-checkbox__inner) {
|
.answer-option-horizontal:hover :deep(.el-checkbox__inner) {
|
||||||
border-color: rgb(93, 135, 255);
|
border-color: rgb(0, 58, 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
.answer-textarea {
|
.answer-textarea {
|
||||||
@@ -2713,8 +2732,8 @@ onMounted(() => {
|
|||||||
|
|
||||||
.answer-textarea :deep(.el-textarea__inner) {
|
.answer-textarea :deep(.el-textarea__inner) {
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
border: 2px solid rgba(93, 135, 255, 0.15);
|
/* border: 2px solid rgba(0, 58, 255, 0.15); */
|
||||||
background: rgba(93, 135, 255, 0.02);
|
background: rgba(0, 58, 255, 0.02);
|
||||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
@@ -2723,15 +2742,15 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.answer-textarea :deep(.el-textarea__inner):focus {
|
.answer-textarea :deep(.el-textarea__inner):focus {
|
||||||
border-color: rgb(93, 135, 255);
|
border-color: rgb(0, 58, 255);
|
||||||
background: rgba(93, 135, 255, 0.05);
|
background: rgba(0, 58, 255, 0.05);
|
||||||
box-shadow: 0 0 0 4px rgba(93, 135, 255, 0.1);
|
box-shadow: 0 0 0 4px rgba(0, 58, 255, 0.1);
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.answer-textarea :deep(.el-textarea__inner):hover {
|
.answer-textarea :deep(.el-textarea__inner):hover {
|
||||||
border-color: rgba(93, 135, 255, 0.3);
|
border-color: rgba(0, 58, 255, 0.3);
|
||||||
background: rgba(93, 135, 255, 0.03);
|
background: rgba(0, 58, 255, 0.03);
|
||||||
}
|
}
|
||||||
|
|
||||||
.answer-textarea :deep(.el-input__count) {
|
.answer-textarea :deep(.el-input__count) {
|
||||||
@@ -2766,7 +2785,7 @@ onMounted(() => {
|
|||||||
justify-content: flex-end !important;
|
justify-content: flex-end !important;
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
padding: 20px 0 0 0;
|
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;
|
margin-top: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2799,28 +2818,28 @@ onMounted(() => {
|
|||||||
|
|
||||||
/* 主要按钮样式 */
|
/* 主要按钮样式 */
|
||||||
.answer-dialog-footer .el-button--primary {
|
.answer-dialog-footer .el-button--primary {
|
||||||
background: rgba(93, 135, 255, 0.05);
|
background: rgba(0, 58, 255, 0.05);
|
||||||
border: 2px solid rgb(93, 135, 255);
|
border: 2px solid rgb(0, 58, 255);
|
||||||
color: rgb(93, 135, 255);
|
color: rgb(0, 58, 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
.answer-dialog-footer .el-button--primary:hover:not(.is-loading) {
|
.answer-dialog-footer .el-button--primary:hover:not(.is-loading) {
|
||||||
background: rgba(93, 135, 255, 0.1);
|
background: rgba(0, 58, 255, 0.1);
|
||||||
border-color: rgba(93, 135, 255, 0.8);
|
border-color: rgba(0, 58, 255, 0.8);
|
||||||
color: rgb(93, 135, 255);
|
color: rgb(0, 58, 255);
|
||||||
transform: translateY(-1px);
|
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 {
|
.answer-dialog-footer .el-button--primary:active {
|
||||||
transform: scale(0.98) translateY(-1px);
|
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 {
|
.answer-dialog-footer .el-button--primary.is-loading {
|
||||||
background: rgba(93, 135, 255, 0.08);
|
background: rgba(0, 58, 255, 0.08);
|
||||||
border-color: rgba(93, 135, 255, 0.6);
|
border-color: rgba(0, 58, 255, 0.6);
|
||||||
color: rgba(93, 135, 255, 0.8);
|
color: rgba(0, 58, 255, 0.8);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 禁用状态 */
|
/* 禁用状态 */
|
||||||
@@ -2855,13 +2874,13 @@ onMounted(() => {
|
|||||||
resize: both;
|
resize: both;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
border-radius: 16px;
|
border-radius: 16px;
|
||||||
box-shadow: 0 20px 60px rgba(93, 135, 255, 0.15);
|
box-shadow: 0 20px 60px rgba(0, 58, 255, 0.15);
|
||||||
border: 1px solid rgba(93, 135, 255, 0.1);
|
border: 1px solid rgba(0, 58, 255, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.question-view-dialog :deep(.el-dialog__header) {
|
.question-view-dialog :deep(.el-dialog__header) {
|
||||||
padding: 20px 24px 16px;
|
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%);
|
background: linear-gradient(135deg, #fafbff 0%, #f8fafc 100%);
|
||||||
border-radius: 16px 16px 0 0;
|
border-radius: 16px 16px 0 0;
|
||||||
}
|
}
|
||||||
@@ -2944,4 +2963,157 @@ onMounted(() => {
|
|||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
padding: 10px 14px;
|
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>
|
</style>
|
||||||
@@ -104,7 +104,7 @@
|
|||||||
<!-- <el-table-column label="题目内容" align="center" prop="questionContent" /> -->
|
<!-- <el-table-column label="题目内容" align="center" prop="questionContent" /> -->
|
||||||
<el-table-column label="所属分类" align="center" prop="categoryId">
|
<el-table-column label="所属分类" align="center" prop="categoryId">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
{{ satCategoryList.find((cat) => cat.id == scope.row.categoryId)?.categoryName || '--' }}
|
{{ satCategoryAllList.find((cat) => cat.id == scope.row.categoryId)?.categoryName || '--' }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="题目类型" align="center" prop="questionType">
|
<el-table-column label="题目类型" align="center" prop="questionType">
|
||||||
@@ -210,7 +210,7 @@
|
|||||||
<script setup name="SatQuestion" lang="ts">
|
<script setup name="SatQuestion" lang="ts">
|
||||||
import { listSatQuestion, getSatQuestion, delSatQuestion, addSatQuestion, updateSatQuestion } from '@/api/hq/satQuestion';
|
import { listSatQuestion, getSatQuestion, delSatQuestion, addSatQuestion, updateSatQuestion } from '@/api/hq/satQuestion';
|
||||||
import { SatQuestionVO, SatQuestionQuery, SatQuestionForm } from '@/api/hq/satQuestion/types';
|
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';
|
import { SatCategoryVO } from '@/api/hq/satCategory/types';
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
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 satQuestionList = ref<SatQuestionVO[]>([]);
|
||||||
const satCategoryList = ref<SatCategoryVO[]>([]);
|
const satCategoryList = ref<SatCategoryVO[]>([]);
|
||||||
|
const satCategoryAllList = ref<SatCategoryVO[]>([]);
|
||||||
const buttonLoading = ref(false);
|
const buttonLoading = ref(false);
|
||||||
const loading = ref(true);
|
const loading = ref(true);
|
||||||
const showSearch = 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排序
|
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 = () => {
|
const cancel = () => {
|
||||||
reset();
|
reset();
|
||||||
@@ -392,6 +402,7 @@ const searchRef = ref<HTMLElement>();
|
|||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getList();
|
getList();
|
||||||
getCategoryList();
|
getCategoryList();
|
||||||
|
getAllCategoryList();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|||||||
@@ -59,16 +59,16 @@
|
|||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="6">
|
<!-- <el-col :span="6"> -->
|
||||||
<!-- <el-form-item label="最大提交次数" prop="maxSubmitTimes">
|
<!-- <el-form-item label="最大提交次数" prop="maxSubmitTimes">
|
||||||
<el-input v-model="queryParams.maxSubmitTimes" placeholder="请输入最大提交次数" clearable @keyup.enter="handleQuery" />
|
<el-input v-model="queryParams.maxSubmitTimes" placeholder="请输入最大提交次数" clearable @keyup.enter="handleQuery" />
|
||||||
</el-form-item> -->
|
</el-form-item> -->
|
||||||
<el-form-item label="是否匿名" prop="isAnonymous">
|
<!-- <el-form-item label="是否匿名" prop="isAnonymous">
|
||||||
<el-select v-model="queryParams.isAnonymous" placeholder="请选择是否匿名" clearable>
|
<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-option v-for="dict in sys_yesno" :key="dict.value" :label="dict.label" :value="dict.value" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col> -->
|
||||||
<el-col :span="6">
|
<el-col :span="6">
|
||||||
<el-form-item label="是否发布" prop="isPublished">
|
<el-form-item label="是否发布" prop="isPublished">
|
||||||
<el-select v-model="queryParams.isPublished" placeholder="请选择是否发布" clearable>
|
<el-select v-model="queryParams.isPublished" placeholder="请选择是否发布" clearable>
|
||||||
@@ -137,8 +137,6 @@
|
|||||||
</el-table-column> -->
|
</el-table-column> -->
|
||||||
<el-table-column label="问卷编号" align="center" prop="surveyCode" width="140" show-overflow-tooltip />
|
<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="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">
|
<el-table-column label="目标群体" align="center" prop="targetGroup" width="120">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<dict-tag :options="sys_survey_people" :value="scope.row.targetGroup" />
|
<dict-tag :options="sys_survey_people" :value="scope.row.targetGroup" />
|
||||||
@@ -146,20 +144,20 @@
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="开始时间" align="center" prop="startTime" width="180">
|
<el-table-column label="开始时间" align="center" prop="startTime" width="180">
|
||||||
<template #default="scope">
|
<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>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="结束时间" align="center" prop="endTime" width="180">
|
<el-table-column label="结束时间" align="center" prop="endTime" width="180">
|
||||||
<template #default="scope">
|
<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>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<!-- <el-table-column label="最大提交次数" align="center" prop="maxSubmitTimes" /> -->
|
<!-- <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">
|
<template #default="scope">
|
||||||
<dict-tag :options="sys_yesno" :value="scope.row.isAnonymous" />
|
<dict-tag :options="sys_yesno" :value="scope.row.isAnonymous" />
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column> -->
|
||||||
<el-table-column label="是否发布" align="center" prop="isPublished" width="100">
|
<el-table-column label="是否发布" align="center" prop="isPublished" width="100">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<dict-tag :options="sys_yesno" :value="scope.row.isPublished" />
|
<dict-tag :options="sys_yesno" :value="scope.row.isPublished" />
|
||||||
@@ -170,6 +168,8 @@
|
|||||||
<dict-tag :options="sys_survey_status" :value="scope.row.status" />
|
<dict-tag :options="sys_survey_status" :value="scope.row.status" />
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</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" prop="remark" min-width="200" show-overflow-tooltip />
|
||||||
<el-table-column label="操作" align="center" width="280" fixed="right" class-name="small-padding fixed-width">
|
<el-table-column label="操作" align="center" width="280" fixed="right" class-name="small-padding fixed-width">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
@@ -339,6 +339,10 @@
|
|||||||
<div v-for="(question, index) in selectedQuestions" :key="question.id || question.questionId" class="question-card">
|
<div v-for="(question, index) in selectedQuestions" :key="question.id || question.questionId" class="question-card">
|
||||||
<div class="question-header">
|
<div class="question-header">
|
||||||
<div class="question-number">第 {{ index + 1 }} 题</div>
|
<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">
|
<div class="question-actions" v-if="!readonly">
|
||||||
<el-button type="text" size="small" @click="removeQuestion(index)">
|
<el-button type="text" size="small" @click="removeQuestion(index)">
|
||||||
<el-icon><Delete /></el-icon>
|
<el-icon><Delete /></el-icon>
|
||||||
@@ -348,10 +352,6 @@
|
|||||||
|
|
||||||
<div class="question-content-display">
|
<div class="question-content-display">
|
||||||
<div class="question-title-display">{{ question.questionTitle }}</div>
|
<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">
|
<div class="answer-display-area">
|
||||||
@@ -445,7 +445,7 @@
|
|||||||
class="selector-question-item"
|
class="selector-question-item"
|
||||||
@click="toggleQuestionSelection(question.id)"
|
@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)" />
|
<el-checkbox :model-value="selectedQuestionIds.includes(question.id)" @change="toggleQuestionSelection(question.id)" />
|
||||||
</div>
|
</div>
|
||||||
<div class="selector-question-content">
|
<div class="selector-question-content">
|
||||||
@@ -991,6 +991,7 @@ import { listSatQuestion, getQuestionOptions } from '@/api/hq/satQuestion';
|
|||||||
import { SatQuestionVO } from '@/api/hq/satQuestion/types';
|
import { SatQuestionVO } from '@/api/hq/satQuestion/types';
|
||||||
import { listSatCategory } from '@/api/hq/satCategory';
|
import { listSatCategory } from '@/api/hq/satCategory';
|
||||||
import { SatCategoryVO } from '@/api/hq/satCategory/types';
|
import { SatCategoryVO } from '@/api/hq/satCategory/types';
|
||||||
|
import { createUniqueString } from '@/utils/index';
|
||||||
|
|
||||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||||
const { sys_survey_people, sys_item_delete, sys_survey_status, sys_yesno } = toRefs<any>(
|
const { sys_survey_people, sys_item_delete, sys_survey_status, sys_yesno } = toRefs<any>(
|
||||||
@@ -1156,6 +1157,13 @@ const handleSelectionChange = (selection: SatSurveyVO[]) => {
|
|||||||
/** 新增按钮操作 */
|
/** 新增按钮操作 */
|
||||||
const handleAdd = () => {
|
const handleAdd = () => {
|
||||||
reset();
|
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.visible = true;
|
||||||
dialog.title = '添加问卷';
|
dialog.title = '添加问卷';
|
||||||
};
|
};
|
||||||
@@ -1556,6 +1564,7 @@ const openQuestionSelector = () => {
|
|||||||
|
|
||||||
/** 切换题目选择状态 */
|
/** 切换题目选择状态 */
|
||||||
const toggleQuestionSelection = (questionId: string | number) => {
|
const toggleQuestionSelection = (questionId: string | number) => {
|
||||||
|
// 处理点击行时的选择/取消选择
|
||||||
const index = selectedQuestionIds.value.indexOf(questionId);
|
const index = selectedQuestionIds.value.indexOf(questionId);
|
||||||
if (index > -1) {
|
if (index > -1) {
|
||||||
selectedQuestionIds.value.splice(index, 1);
|
selectedQuestionIds.value.splice(index, 1);
|
||||||
@@ -1566,11 +1575,19 @@ const toggleQuestionSelection = (questionId: string | number) => {
|
|||||||
|
|
||||||
/** 全选/取消全选 */
|
/** 全选/取消全选 */
|
||||||
const toggleSelectAll = (checked: boolean) => {
|
const toggleSelectAll = (checked: boolean) => {
|
||||||
|
// 强制刷新所有复选框状态
|
||||||
if (checked) {
|
if (checked) {
|
||||||
selectedQuestionIds.value = filteredAvailableQuestions.value.map((q) => q.id);
|
// 全选 - 使用所有过滤后的题目ID
|
||||||
|
selectedQuestionIds.value = [...filteredAvailableQuestions.value.map((q) => q.id)];
|
||||||
} else {
|
} else {
|
||||||
|
// 清空选择
|
||||||
selectedQuestionIds.value = [];
|
selectedQuestionIds.value = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 强制下一个事件循环中重新渲染
|
||||||
|
nextTick(() => {
|
||||||
|
console.log(`选择状态已更新: ${selectedQuestionIds.value.length} 个题目被选中`);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/** 确认添加选中的题目 */
|
/** 确认添加选中的题目 */
|
||||||
@@ -2272,9 +2289,9 @@ onMounted(() => {
|
|||||||
|
|
||||||
.question-header {
|
.question-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: flex-start;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 12px 16px;
|
padding: 4px 16px;
|
||||||
background: #f8f9fa;
|
background: #f8f9fa;
|
||||||
border-bottom: 1px solid #e4e7ed;
|
border-bottom: 1px solid #e4e7ed;
|
||||||
border-radius: 8px 8px 0 0;
|
border-radius: 8px 8px 0 0;
|
||||||
@@ -2282,13 +2299,14 @@ onMounted(() => {
|
|||||||
|
|
||||||
.question-number {
|
.question-number {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: #409eff;
|
color: var(--el-color-primary);
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.question-actions {
|
.question-actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
|
margin-left: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.question-content-display {
|
.question-content-display {
|
||||||
@@ -2306,7 +2324,8 @@ onMounted(() => {
|
|||||||
.question-meta-info {
|
.question-meta-info {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
margin-bottom: 16px;
|
margin: 0 16px;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.answer-display-area {
|
.answer-display-area {
|
||||||
@@ -2314,7 +2333,8 @@ onMounted(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.answer-option {
|
.answer-option {
|
||||||
display: block !important;
|
display: inline-flex !important;
|
||||||
|
margin-right: 56px;
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
white-space: normal;
|
white-space: normal;
|
||||||
word-break: break-all;
|
word-break: break-all;
|
||||||
|
|||||||
Reference in new issue
Block a user