337 lines
9.3 KiB
Vue
337 lines
9.3 KiB
Vue
<template>
|
||
<el-dialog
|
||
v-model="dialogVisible"
|
||
:title="isEdit ? '编辑任务' : '创建问卷任务'"
|
||
width="600px"
|
||
:close-on-click-modal="false"
|
||
>
|
||
<el-form
|
||
ref="formRef"
|
||
:model="formData"
|
||
:rules="formRules"
|
||
label-width="100px"
|
||
>
|
||
<!-- 基本信息 -->
|
||
<el-divider content-position="left">基本信息</el-divider>
|
||
|
||
<el-form-item label="任务名称" prop="taskName">
|
||
<el-input v-model="formData.taskName" placeholder="请输入任务名称" maxlength="100" show-word-limit />
|
||
</el-form-item>
|
||
|
||
<el-form-item label="选择问卷" prop="questionnaireId">
|
||
<el-select
|
||
v-model="formData.questionnaireId"
|
||
placeholder="请选择问卷"
|
||
filterable
|
||
style="width: calc(100% - 90px)"
|
||
>
|
||
<el-option
|
||
v-for="item in questionnaireList"
|
||
:key="item.id"
|
||
:label="item.title"
|
||
:value="item.id"
|
||
/>
|
||
</el-select>
|
||
<el-button
|
||
type="primary"
|
||
link
|
||
:disabled="!formData.questionnaireId"
|
||
@click="handlePreviewQuestionnaire"
|
||
>
|
||
<Icon icon="ep:view" class="mr-3px" />预览
|
||
</el-button>
|
||
</el-form-item>
|
||
|
||
<!-- 目标范围 -->
|
||
<el-divider content-position="left">目标范围</el-divider>
|
||
|
||
<el-form-item label="目标类型" prop="targetType">
|
||
<el-radio-group v-model="formData.targetType">
|
||
<el-radio :value="1">指定犯人</el-radio>
|
||
<el-radio :value="2">指定监区</el-radio>
|
||
<el-radio :value="3">全部犯人</el-radio>
|
||
</el-radio-group>
|
||
</el-form-item>
|
||
|
||
<!-- 指定犯人 -->
|
||
<el-form-item v-if="formData.targetType === 1" label="选择犯人" prop="prisonerIds">
|
||
<el-button type="primary" plain @click="openPrisonerSelector">
|
||
<Icon icon="ep:user" class="mr-5px" />
|
||
选择犯人(已选 {{ formData.prisonerIds.length }} 人)
|
||
</el-button>
|
||
</el-form-item>
|
||
|
||
<!-- 指定监区 -->
|
||
<el-form-item v-if="formData.targetType === 2" label="选择监区" prop="areaId">
|
||
<el-select
|
||
v-model="formData.areaId"
|
||
placeholder="请选择监区"
|
||
filterable
|
||
style="width: 100%"
|
||
>
|
||
<el-option
|
||
v-for="item in areaList"
|
||
:key="item.id"
|
||
:label="item.name"
|
||
:value="item.id"
|
||
/>
|
||
</el-select>
|
||
</el-form-item>
|
||
|
||
<!-- 时间设置 -->
|
||
<el-divider content-position="left">时间设置</el-divider>
|
||
|
||
<el-form-item label="开始时间" prop="startTime">
|
||
<el-date-picker
|
||
v-model="formData.startTime"
|
||
type="datetime"
|
||
placeholder="选择开始时间"
|
||
style="width: 100%"
|
||
value-format="YYYY-MM-DD HH:mm:ss"
|
||
/>
|
||
</el-form-item>
|
||
|
||
<el-form-item label="截止时间" prop="deadline">
|
||
<el-date-picker
|
||
v-model="formData.deadline"
|
||
type="datetime"
|
||
placeholder="选择截止时间"
|
||
style="width: 100%"
|
||
value-format="YYYY-MM-DD HH:mm:ss"
|
||
/>
|
||
</el-form-item>
|
||
|
||
<!-- 备注 -->
|
||
<el-divider content-position="left">备注</el-divider>
|
||
|
||
<el-form-item label="备注" prop="remark">
|
||
<el-input
|
||
v-model="formData.remark"
|
||
type="textarea"
|
||
:rows="3"
|
||
placeholder="请输入备注信息"
|
||
maxlength="500"
|
||
show-word-limit
|
||
/>
|
||
</el-form-item>
|
||
</el-form>
|
||
|
||
<!-- 犯人选择器弹窗 -->
|
||
<PrisonerSelectorDialog
|
||
ref="prisonerSelectorRef"
|
||
:selected-ids="formData.prisonerIds"
|
||
@confirm="handlePrisonerSelect"
|
||
/>
|
||
|
||
<!-- 问卷预览弹窗 -->
|
||
<el-dialog
|
||
v-model="previewVisible"
|
||
title="问卷预览"
|
||
width="800px"
|
||
destroy-on-close
|
||
>
|
||
<QuestionnairePreview :id="previewQuestionnaireId" />
|
||
<template #footer>
|
||
<el-button @click="previewVisible = false">关闭</el-button>
|
||
</template>
|
||
</el-dialog>
|
||
|
||
<template #footer>
|
||
<el-button @click="dialogVisible = false">取消</el-button>
|
||
<el-button type="primary" :loading="submitLoading" @click="handleSubmit">
|
||
确定
|
||
</el-button>
|
||
</template>
|
||
</el-dialog>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { ref, reactive, watch } from 'vue'
|
||
import { ElMessage } from 'element-plus'
|
||
import PrisonerSelectorDialog from './PrisonerSelectorDialog.vue'
|
||
import QuestionnairePreview from '@/views/prison/questionnaire/components/QuestionnairePreview.vue'
|
||
import { QuestionnaireTaskApi } from '@/api/prison/questionnaire-task'
|
||
import { QuestionnaireApi } from '@/api/prison/questionnaire'
|
||
import { AreaApi } from '@/api/prison/area'
|
||
|
||
defineOptions({ name: 'CreateTaskDialog' })
|
||
|
||
const emit = defineEmits(['success'])
|
||
|
||
const dialogVisible = ref(false)
|
||
const submitLoading = ref(false)
|
||
const isEdit = ref(false)
|
||
const formRef = ref()
|
||
|
||
// 预览相关
|
||
const previewVisible = ref(false)
|
||
const previewQuestionnaireId = ref<number>()
|
||
|
||
// 表单数据
|
||
const formData = reactive({
|
||
id: undefined,
|
||
taskName: '',
|
||
questionnaireId: undefined as number | undefined,
|
||
targetType: 2, // 默认指定监区
|
||
prisonerIds: [] as number[],
|
||
areaId: undefined as number | undefined,
|
||
startTime: '',
|
||
deadline: '',
|
||
remark: ''
|
||
})
|
||
|
||
// 表单校验规则
|
||
const formRules = {
|
||
taskName: [{ required: true, message: '请输入任务名称', trigger: 'blur' }],
|
||
questionnaireId: [{ required: true, message: '请选择问卷', trigger: 'change' }],
|
||
targetType: [{ required: true, message: '请选择目标类型', trigger: 'change' }],
|
||
deadline: [{ required: true, message: '请选择截止时间', trigger: 'change' }]
|
||
}
|
||
|
||
// 数据列表
|
||
const questionnaireList = ref<any[]>([])
|
||
const areaList = ref<any[]>([])
|
||
const prisonerSelectorRef = ref()
|
||
|
||
/** 打开弹窗 */
|
||
const open = async (row?: any) => {
|
||
dialogVisible.value = true
|
||
isEdit.value = !!row
|
||
|
||
if (row) {
|
||
// 编辑模式
|
||
formData.id = row.id
|
||
formData.taskName = row.taskName
|
||
formData.questionnaireId = row.questionnaireId
|
||
formData.targetType = row.targetType
|
||
formData.areaId = row.areaId
|
||
formData.startTime = row.startTime || ''
|
||
formData.deadline = row.deadline || ''
|
||
formData.remark = row.remark || ''
|
||
} else {
|
||
// 重置表单
|
||
formData.id = undefined
|
||
formData.taskName = ''
|
||
formData.questionnaireId = undefined
|
||
formData.targetType = 2
|
||
formData.prisonerIds = []
|
||
formData.areaId = undefined
|
||
formData.startTime = ''
|
||
formData.deadline = ''
|
||
formData.remark = ''
|
||
}
|
||
|
||
// 加载数据
|
||
await Promise.all([getQuestionnaires(), getAreas()])
|
||
}
|
||
|
||
/** 获取问卷列表 */
|
||
const getQuestionnaires = async () => {
|
||
try {
|
||
const data = await QuestionnaireApi.getQuestionnairePage({
|
||
pageNo: 1,
|
||
pageSize: 100,
|
||
status: 2
|
||
})
|
||
questionnaireList.value = data.list || []
|
||
} catch (e) {
|
||
console.error('获取问卷列表失败', e)
|
||
}
|
||
}
|
||
|
||
/** 获取监区列表 */
|
||
const getAreas = async () => {
|
||
try {
|
||
const data = await AreaApi.getAreaTree({})
|
||
// 提取所有监区用于下拉选择
|
||
const extractAreas = (nodes: any[]): any[] => {
|
||
const result: any[] = []
|
||
nodes.forEach(node => {
|
||
result.push({ id: node.id, name: node.name })
|
||
if (node.children && node.children.length > 0) {
|
||
result.push(...extractAreas(node.children))
|
||
}
|
||
})
|
||
return result
|
||
}
|
||
areaList.value = extractAreas(data || [])
|
||
} catch (e) {
|
||
console.error('获取监区列表失败', e)
|
||
}
|
||
}
|
||
|
||
/** 打开犯人选择器 */
|
||
const openPrisonerSelector = () => {
|
||
prisonerSelectorRef.value?.open(formData.prisonerIds)
|
||
}
|
||
|
||
/** 预览问卷 */
|
||
const handlePreviewQuestionnaire = () => {
|
||
if (!formData.questionnaireId) {
|
||
ElMessage.warning('请先选择问卷')
|
||
return
|
||
}
|
||
previewQuestionnaireId.value = formData.questionnaireId
|
||
previewVisible.value = true
|
||
}
|
||
|
||
/** 犯人选择确认 */
|
||
const handlePrisonerSelect = (selectedIds: number[]) => {
|
||
formData.prisonerIds = selectedIds
|
||
}
|
||
|
||
/** 提交 */
|
||
const handleSubmit = async () => {
|
||
try {
|
||
await formRef.value?.validate()
|
||
} catch (e) {
|
||
return
|
||
}
|
||
|
||
submitLoading.value = true
|
||
try {
|
||
const data = {
|
||
taskName: formData.taskName,
|
||
questionnaireId: formData.questionnaireId,
|
||
targetType: formData.targetType,
|
||
prisonerIds: formData.targetType === 1 ? formData.prisonerIds : undefined,
|
||
areaId: formData.targetType === 2 ? formData.areaId : undefined,
|
||
startTime: formData.startTime || undefined,
|
||
deadline: formData.deadline,
|
||
remark: formData.remark || undefined
|
||
}
|
||
|
||
if (isEdit.value) {
|
||
await QuestionnaireTaskApi.updateQuestionnaireTask({
|
||
id: formData.id,
|
||
taskName: formData.taskName,
|
||
deadline: formData.deadline,
|
||
remark: formData.remark
|
||
})
|
||
ElMessage.success('修改成功')
|
||
} else {
|
||
await QuestionnaireTaskApi.createQuestionnaireTask(data)
|
||
ElMessage.success('创建成功')
|
||
}
|
||
|
||
dialogVisible.value = false
|
||
emit('success')
|
||
} catch (e) {
|
||
console.error('提交失败', e)
|
||
} finally {
|
||
submitLoading.value = false
|
||
}
|
||
}
|
||
|
||
// 监听目标类型变化,重置相关字段
|
||
watch(() => formData.targetType, (val) => {
|
||
if (val === 1) {
|
||
formData.areaId = undefined
|
||
} else if (val === 2) {
|
||
formData.prisonerIds = []
|
||
}
|
||
})
|
||
|
||
defineExpose({ open })
|
||
</script>
|