feat(frontend): 增强问卷模块功能,优化囚犯选择器
This commit is contained in:
parent
ec0ff8dc90
commit
11e3ef148b
@ -89,10 +89,18 @@ export const PrisonerApi = {
|
|||||||
getPage: (params: PageParam) => {
|
getPage: (params: PageParam) => {
|
||||||
return request.get({ url: '/prison/prisoner/page', params })
|
return request.get({ url: '/prison/prisoner/page', params })
|
||||||
},
|
},
|
||||||
|
// 分页查询(别名,用于选择犯人弹窗)
|
||||||
|
getPrisonerPage: (params: PageParam) => {
|
||||||
|
return request.get({ url: '/prison/prisoner/page', params })
|
||||||
|
},
|
||||||
// 获取详情
|
// 获取详情
|
||||||
get: (id: number) => {
|
get: (id: number) => {
|
||||||
return request.get({ url: '/prison/prisoner/get', params: { id } })
|
return request.get({ url: '/prison/prisoner/get', params: { id } })
|
||||||
},
|
},
|
||||||
|
// 获取详情(别名,与其他模块保持一致)
|
||||||
|
getPrisoner: (id: number) => {
|
||||||
|
return request.get({ url: '/prison/prisoner/get', params: { id } })
|
||||||
|
},
|
||||||
// 创建
|
// 创建
|
||||||
create: (data: PrisonerCreateVO) => {
|
create: (data: PrisonerCreateVO) => {
|
||||||
return request.post({ url: '/prison/prisoner/create', data })
|
return request.post({ url: '/prison/prisoner/create', data })
|
||||||
|
|||||||
@ -271,7 +271,7 @@
|
|||||||
{{ scope.row.finishTime ? formatDateTime(scope.row.finishTime) : '-' }}
|
{{ scope.row.finishTime ? formatDateTime(scope.row.finishTime) : '-' }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="操作" align="center" width="320" fixed="right">
|
<el-table-column label="操作" align="center" width="400" fixed="right">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-button
|
<el-button
|
||||||
v-if="scope.row.status === 3"
|
v-if="scope.row.status === 3"
|
||||||
@ -310,6 +310,15 @@
|
|||||||
>
|
>
|
||||||
重置
|
重置
|
||||||
</el-button>
|
</el-button>
|
||||||
|
<el-button
|
||||||
|
link
|
||||||
|
type="primary"
|
||||||
|
size="small"
|
||||||
|
@click="handleViewPrisoner(scope.row)"
|
||||||
|
v-hasPermi="['prison:prisoner:query']"
|
||||||
|
>
|
||||||
|
详情
|
||||||
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
@ -328,6 +337,9 @@
|
|||||||
|
|
||||||
<!-- 代填弹窗 -->
|
<!-- 代填弹窗 -->
|
||||||
<AgentFillDialog ref="agentFillDialogRef" @success="loadPrisonerProgress" />
|
<AgentFillDialog ref="agentFillDialogRef" @success="loadPrisonerProgress" />
|
||||||
|
|
||||||
|
<!-- 服刑人员详情弹窗 -->
|
||||||
|
<PrisonerDetail ref="prisonerDetailRef" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
@ -336,6 +348,7 @@ import { ElMessage, ElMessageBox } from 'element-plus'
|
|||||||
import { formatDateTime } from '@/utils/formatTime'
|
import { formatDateTime } from '@/utils/formatTime'
|
||||||
import AnswerDetailDialog from '@/views/prison/questionnairerecord/AnswerDetailDialog.vue'
|
import AnswerDetailDialog from '@/views/prison/questionnairerecord/AnswerDetailDialog.vue'
|
||||||
import AgentFillDialog from './AgentFillDialog.vue'
|
import AgentFillDialog from './AgentFillDialog.vue'
|
||||||
|
import PrisonerDetail from '@/views/prison/prisoner/PrisonerDetail.vue'
|
||||||
import { QuestionnaireTaskApi } from '@/api/prison/questionnaire-task'
|
import { QuestionnaireTaskApi } from '@/api/prison/questionnaire-task'
|
||||||
|
|
||||||
defineOptions({ name: 'TaskDetailDialog' })
|
defineOptions({ name: 'TaskDetailDialog' })
|
||||||
@ -353,6 +366,9 @@ const answerDetailDialogRef = ref()
|
|||||||
// 代填弹窗
|
// 代填弹窗
|
||||||
const agentFillDialogRef = ref()
|
const agentFillDialogRef = ref()
|
||||||
|
|
||||||
|
// 服刑人员详情弹窗
|
||||||
|
const prisonerDetailRef = ref()
|
||||||
|
|
||||||
// 任务详情
|
// 任务详情
|
||||||
const taskDetail = ref<any>(null)
|
const taskDetail = ref<any>(null)
|
||||||
|
|
||||||
@ -573,6 +589,11 @@ const handleAgentFill = (row: any) => {
|
|||||||
agentFillDialogRef.value?.open(row)
|
agentFillDialogRef.value?.open(row)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 查看服刑人员详情 */
|
||||||
|
const handleViewPrisoner = (row: any) => {
|
||||||
|
prisonerDetailRef.value?.open(row.prisonerId)
|
||||||
|
}
|
||||||
|
|
||||||
/** 提醒未完成人员 */
|
/** 提醒未完成人员 */
|
||||||
const handleRemind = async () => {
|
const handleRemind = async () => {
|
||||||
if (!taskId.value) return
|
if (!taskId.value) return
|
||||||
|
|||||||
@ -117,29 +117,35 @@ const open = async (type: string, id?: number) => {
|
|||||||
}
|
}
|
||||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||||
|
|
||||||
/** 提交表单 */
|
/** 提交表单 */
|
||||||
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
||||||
const submitForm = async () => {
|
const submitForm = async () => {
|
||||||
// 校验表单
|
// 校验表单
|
||||||
await formRef.value.validate()
|
await formRef.value.validate()
|
||||||
// 提交请求
|
// 提交请求:将 coverImage 数组转换为字符串(取第一个元素或null)
|
||||||
formLoading.value = true
|
formLoading.value = true
|
||||||
try {
|
try {
|
||||||
const data = formData.value as unknown as Questionnaire
|
const data = { ...formData.value } as unknown as Questionnaire
|
||||||
if (formType.value === 'create') {
|
// 处理 coverImage 数组转换为字符串
|
||||||
await QuestionnaireApi.createQuestionnaire(data)
|
if (Array.isArray(data.coverImage) && data.coverImage.length > 0) {
|
||||||
message.success(t('common.createSuccess'))
|
data.coverImage = data.coverImage[0] as unknown as string
|
||||||
} else {
|
} else {
|
||||||
await QuestionnaireApi.updateQuestionnaire(data)
|
data.coverImage = undefined as unknown as string
|
||||||
message.success(t('common.updateSuccess'))
|
}
|
||||||
|
if (formType.value === 'create') {
|
||||||
|
await QuestionnaireApi.createQuestionnaire(data)
|
||||||
|
message.success(t('common.createSuccess'))
|
||||||
|
} else {
|
||||||
|
await QuestionnaireApi.updateQuestionnaire(data)
|
||||||
|
message.success(t('common.updateSuccess'))
|
||||||
|
}
|
||||||
|
dialogVisible.value = false
|
||||||
|
// 发送操作成功的事件
|
||||||
|
emit('success')
|
||||||
|
} finally {
|
||||||
|
formLoading.value = false
|
||||||
}
|
}
|
||||||
dialogVisible.value = false
|
|
||||||
// 发送操作成功的事件
|
|
||||||
emit('success')
|
|
||||||
} finally {
|
|
||||||
formLoading.value = false
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/** 重置表单 */
|
/** 重置表单 */
|
||||||
const resetForm = () => {
|
const resetForm = () => {
|
||||||
|
|||||||
@ -192,13 +192,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
|
||||||
<el-button type="primary" plain :icon="Plus" @click="addPartition" v-hasPermi="['prison:question:create', 'prison:questionnaire:update']">添加分区</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
</el-form>
|
</el-form>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<el-button @click="savePartitions" type="primary" v-hasPermi="['prison:question:update', 'prison:questionnaire:update']">保存设置</el-button>
|
<el-button @click="savePartitions" type="primary" v-hasPermi="['prison:question:update', 'prison:questionnaire:update']">保存设置</el-button>
|
||||||
<el-button @click="partDialogVisible = false">取消</el-button>
|
<el-button @click="partDialogVisible = false">关闭</el-button>
|
||||||
</template>
|
</template>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
</template>
|
</template>
|
||||||
@ -486,26 +483,39 @@ const savePartitions = async () => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 收集所有需要更新的问题
|
// 收集所有需要更新的问题(包括默认分区)
|
||||||
const updates: Array<{ id: number; partName?: string; partSort?: number; sort?: number }> = []
|
const updates: Array<{ id: number; partName?: string; partSort?: number; sort?: number }> = []
|
||||||
for (let i = 0; i < allPartList.value.length; i++) {
|
for (let i = 0; i < allPartList.value.length; i++) {
|
||||||
const part = allPartList.value[i]
|
const part = allPartList.value[i]
|
||||||
if (!part.isDefault && part.name) {
|
for (const p of partitions.value) {
|
||||||
for (const p of partitions.value) {
|
// 匹配分区:两个 name 相等,或者两个都是空(默认分区)
|
||||||
if (p.name === part.name) {
|
if ((p.name === part.name) || (p.name === '' && part.name === '')) {
|
||||||
p.questions.forEach((q, sortIndex) => {
|
p.questions.forEach((q, sortIndex) => {
|
||||||
updates.push({
|
updates.push({
|
||||||
id: q.id!,
|
id: q.id!,
|
||||||
partName: part.name,
|
partName: part.name || undefined,
|
||||||
partSort: i,
|
partSort: i,
|
||||||
sort: sortIndex
|
sort: sortIndex
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 没有需要更新的问题(可能是添加了空分区)
|
||||||
|
if (updates.length === 0) {
|
||||||
|
// 检查是否有新建的空分区
|
||||||
|
const hasNewPartition = allPartList.value.some(p => !p.isDefault && p.id?.toString().startsWith('part_'))
|
||||||
|
if (hasNewPartition) {
|
||||||
|
message.error('请先在该分区下添加问题后再保存')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 如果确实没有变化,直接关闭弹窗
|
||||||
|
partDialogVisible.value = false
|
||||||
|
message.success('保存成功')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// 批量更新
|
// 批量更新
|
||||||
await QuestionApi.batchUpdate({ questions: updates })
|
await QuestionApi.batchUpdate({ questions: updates })
|
||||||
await getList()
|
await getList()
|
||||||
@ -518,20 +528,22 @@ const savePartitions = async () => {
|
|||||||
|
|
||||||
/** 分区拖拽排序完成 */
|
/** 分区拖拽排序完成 */
|
||||||
const onPartitionDragEnd = async () => {
|
const onPartitionDragEnd = async () => {
|
||||||
// 收集所有需要更新的问题
|
// 收集所有需要更新的问题(包括默认分区)
|
||||||
const updates: Array<{ id: number; partName?: string; partSort?: number; sort?: number }> = []
|
const updates: Array<{ id: number; partName?: string; partSort?: number; sort?: number }> = []
|
||||||
for (let i = 0; i < partitions.value.length; i++) {
|
for (let i = 0; i < partitions.value.length; i++) {
|
||||||
const part = partitions.value[i]
|
const part = partitions.value[i]
|
||||||
if (part.name) {
|
part.questions.forEach((q, sortIndex) => {
|
||||||
part.questions.forEach((q, sortIndex) => {
|
updates.push({
|
||||||
updates.push({
|
id: q.id!,
|
||||||
id: q.id!,
|
partName: part.name || undefined,
|
||||||
partName: part.name,
|
partSort: i,
|
||||||
partSort: i,
|
sort: sortIndex
|
||||||
sort: sortIndex
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
})
|
||||||
|
}
|
||||||
|
// 空数组无需调用后端
|
||||||
|
if (updates.length === 0) {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
// 批量更新
|
// 批量更新
|
||||||
await QuestionApi.batchUpdate({ questions: updates })
|
await QuestionApi.batchUpdate({ questions: updates })
|
||||||
|
|||||||
@ -101,7 +101,11 @@
|
|||||||
<dict-tag :type="DICT_TYPE.PRISON_QUESTIONNAIRE_TYPE" :value="scope.row.type" />
|
<dict-tag :type="DICT_TYPE.PRISON_QUESTIONNAIRE_TYPE" :value="scope.row.type" />
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="问卷说明" align="center" prop="description" width="200" />
|
<el-table-column label="问卷说明" align="center" prop="description" width="200">
|
||||||
|
<template #default="scope">
|
||||||
|
<div v-html="scope.row.description"></div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column label="总分" align="center" prop="totalScore" width="80" />
|
<el-table-column label="总分" align="center" prop="totalScore" width="80" />
|
||||||
<el-table-column label="及格分" align="center" prop="passScore" width="80" />
|
<el-table-column label="及格分" align="center" prop="passScore" width="80" />
|
||||||
<el-table-column label="状态" align="center" prop="status" width="100">
|
<el-table-column label="状态" align="center" prop="status" width="100">
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user