Files
school-developer/src/views/stuwork/classleaveapply/form.vue
2026-01-16 18:24:09 +08:00

472 lines
13 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<el-dialog
title="批量新增"
v-model="visible"
:close-on-click-modal="false"
draggable
width="900px">
<el-form
ref="dataFormRef"
:model="form"
:rules="dataRules"
label-width="120px"
v-loading="loading">
<el-row :gutter="24">
<el-col :span="12" class="mb20">
<el-form-item label="学年" prop="schoolYear">
<el-select
v-model="form.schoolYear"
placeholder="请选择学年"
clearable
filterable
style="width: 100%">
<el-option
v-for="item in schoolYearList"
:key="item.year"
:label="item.year"
:value="item.year">
</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="学期" prop="schoolTerm">
<el-select
v-model="form.schoolTerm"
placeholder="请选择学期"
clearable
style="width: 100%">
<el-option
v-for="item in schoolTermList"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="班号" prop="classCode">
<el-select
v-model="form.classCode"
placeholder="请选择班号"
clearable
filterable
style="width: 100%">
<el-option
v-for="item in classList"
:key="item.classCode"
:label="item.classNo"
:value="item.classCode">
</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="请假类型" prop="leaveType">
<el-select
v-model="form.leaveType"
placeholder="请选择请假类型"
clearable
style="width: 100%">
<el-option
v-for="item in leaveTypeList"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="24" class="mb20">
<el-form-item label="请假时间" prop="leaveTime">
<el-date-picker
v-model="form.leaveTime"
type="datetimerange"
range-separator=""
start-placeholder="开始时间"
end-placeholder="结束时间"
format="YYYY-MM-DD HH:mm"
value-format="YYYY-MM-DD HH:mm:ss"
style="width: 100%" />
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="是否住宿" prop="stayDorm">
<el-select
v-model="form.stayDorm"
placeholder="请选择是否住宿"
clearable
style="width: 100%">
<el-option
v-for="item in yesNoList"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="时段请假" prop="isSegment">
<el-switch
v-model="form.isSegment"
active-value="1"
inactive-value="0"
active-text=""
inactive-text=""
@change="handleSegmentChange" />
</el-form-item>
</el-col>
<template v-if="form.isSegment === '1'">
<el-col :span="12" class="mb20">
<el-form-item label="时段开始时间" prop="segmentStartTime">
<el-time-picker
v-model="form.segmentStartTime"
placeholder="请选择时段开始时间"
format="HH:mm"
value-format="HH:mm"
style="width: 100%" />
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="时段结束时间" prop="segmentEndTime">
<el-time-picker
v-model="form.segmentEndTime"
placeholder="请选择时段结束时间"
format="HH:mm"
value-format="HH:mm"
style="width: 100%" />
</el-form-item>
</el-col>
</template>
<el-col :span="12" class="mb20">
<el-form-item label="校门" prop="schoolDoor">
<el-select
v-model="form.schoolDoor"
placeholder="请选择校门"
clearable
style="width: 100%">
<el-option
v-for="item in schoolDoorList"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="24" class="mb20">
<el-form-item label="请假事由" prop="reason">
<el-input
v-model="form.reason"
type="textarea"
:rows="4"
placeholder="请输入请假事由" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="visible = false"> </el-button>
<el-button type="primary" @click="onSubmit" :disabled="loading"> </el-button>
</span>
</template>
</el-dialog>
</template>
<script setup lang="ts" name="ClassLeaveApplyFormDialog">
import { ref, reactive, nextTick, onMounted, computed } from 'vue'
import { useMessage } from '/@/hooks/message'
import { addObj } from '/@/api/stuwork/classleaveapply'
import { queryAllSchoolYear } from '/@/api/basic/basicyear'
import { getDicts } from '/@/api/admin/dict'
import { getClassListByRole } from '/@/api/basic/basicclass'
const emit = defineEmits(['refresh'])
// 定义变量内容
const dataFormRef = ref()
const visible = ref(false)
const loading = ref(false)
const schoolYearList = ref<any[]>([])
const schoolTermList = ref<any[]>([])
const classList = ref<any[]>([])
const leaveTypeList = ref<any[]>([])
const yesNoList = ref<any[]>([])
const schoolDoorList = ref<any[]>([])
// 校门列表
const schoolDoorListData = [
{ label: '校门东', value: '0' },
{ label: '校门南', value: '1' },
{ label: '校门西', value: '2' }
]
// 提交表单数据
const form = reactive({
schoolYear: '',
schoolTerm: '',
classCode: '',
leaveTime: null as [string, string] | null,
leaveType: '',
reason: '',
stayDorm: '',
isSegment: '0',
segmentStartTime: '',
segmentEndTime: '',
schoolDoor: ''
})
// 定义校验规则
const dataRules = {
schoolYear: [
{ required: true, message: '请选择学年', trigger: 'change' }
],
schoolTerm: [
{ required: true, message: '请选择学期', trigger: 'change' }
],
classCode: [
{ required: true, message: '请选择班号', trigger: 'change' }
],
leaveTime: [
{ required: true, message: '请选择请假时间', trigger: 'change' }
],
leaveType: [
{ required: true, message: '请选择请假类型', trigger: 'change' }
],
reason: [
{ required: true, message: '请输入请假事由', trigger: 'blur' }
],
segmentStartTime: [
{
validator: (rule: any, value: any, callback: any) => {
if (form.isSegment === '1' && !value) {
callback(new Error('请选择时段开始时间'))
} else {
callback()
}
},
trigger: 'change'
}
],
segmentEndTime: [
{
validator: (rule: any, value: any, callback: any) => {
if (form.isSegment === '1' && !value) {
callback(new Error('请选择时段结束时间'))
} else {
callback()
}
},
trigger: 'change'
}
]
}
// 打开弹窗
const openDialog = () => {
visible.value = true
resetForm()
nextTick(() => {
dataFormRef.value?.resetFields()
})
}
// 重置表单
const resetForm = () => {
form.schoolYear = ''
form.schoolTerm = ''
form.classCode = ''
form.leaveTime = null
form.leaveType = ''
form.reason = ''
form.stayDorm = ''
form.isSegment = '0'
form.segmentStartTime = ''
form.segmentEndTime = ''
form.schoolDoor = ''
}
// 时段请假变化
const handleSegmentChange = () => {
if (form.isSegment !== '1') {
form.segmentStartTime = ''
form.segmentEndTime = ''
}
}
// 提交表单
const onSubmit = async () => {
if (!dataFormRef.value) return
await dataFormRef.value.validate(async (valid: boolean) => {
if (!valid) return
// 验证请假时间范围
if (!form.leaveTime || form.leaveTime.length !== 2) {
useMessage().error('请选择请假时间范围')
return
}
const [startTime, endTime] = form.leaveTime
const start = new Date(startTime)
const end = new Date(endTime)
if (end <= start) {
useMessage().error('请假结束时间必须大于开始时间')
return
}
// 验证时段时间(如果开启了时段请假)
if (form.isSegment === '1') {
if (!form.segmentStartTime || !form.segmentEndTime) {
useMessage().error('请选择时段开始时间和结束时间')
return
}
// 简单的时段验证(可以更复杂)
if (form.segmentEndTime <= form.segmentStartTime) {
useMessage().error('时段结束时间必须大于开始时间')
return
}
}
loading.value = true
try {
// 构建时段JSON如果开启了时段请假
let segmentJson = ''
if (form.isSegment === '1' && form.segmentStartTime && form.segmentEndTime) {
segmentJson = JSON.stringify({
startTime: form.segmentStartTime,
endTime: form.segmentEndTime
})
}
await addObj({
schoolYear: form.schoolYear,
schoolTerm: form.schoolTerm,
classCode: form.classCode,
startTime: startTime,
endTime: endTime,
leaveType: form.leaveType,
reason: form.reason,
stayDorm: form.stayDorm,
isSegment: form.isSegment,
segmentJson: segmentJson,
schoolDoor: form.schoolDoor
})
useMessage().success('新增成功')
visible.value = false
emit('refresh')
} catch (err: any) {
useMessage().error(err.msg || '新增失败')
} finally {
loading.value = false
}
})
}
// 获取学年列表
const getSchoolYearListData = async () => {
try {
const res = await queryAllSchoolYear()
if (res.data) {
schoolYearList.value = Array.isArray(res.data) ? res.data : []
}
} catch (err) {
console.error('获取学年列表失败', err)
schoolYearList.value = []
}
}
// 获取学期字典
const getSchoolTermDict = async () => {
try {
const res = await getDicts('school_term')
if (res.data) {
schoolTermList.value = Array.isArray(res.data) ? res.data.map((item: any) => ({
label: item.label || item.dictLabel || item.name,
value: item.value || item.dictValue || item.code
})) : []
}
} catch (err) {
console.error('获取学期字典失败', err)
schoolTermList.value = []
}
}
// 获取班级列表
const getClassListData = async () => {
try {
const res = await getClassListByRole()
if (res.data) {
classList.value = Array.isArray(res.data) ? res.data : []
}
} catch (err) {
console.error('获取班级列表失败', err)
classList.value = []
}
}
// 获取请假类型字典
const getLeaveTypeDict = async () => {
try {
const res = await getDicts('leave_type')
if (res.data) {
leaveTypeList.value = Array.isArray(res.data) ? res.data.map((item: any) => ({
label: item.label || item.dictLabel || item.name,
value: item.value || item.dictValue || item.code
})) : []
}
} catch (err) {
console.error('获取请假类型字典失败', err)
leaveTypeList.value = []
}
}
// 获取是否字典
const getYesNoDict = async () => {
try {
const res = await getDicts('yes_no')
if (res.data) {
yesNoList.value = Array.isArray(res.data) ? res.data.map((item: any) => ({
label: item.label || item.dictLabel || item.name,
value: item.value || item.dictValue || item.code
})) : []
}
} catch (err) {
console.error('获取是否字典失败', err)
yesNoList.value = []
}
}
// 初始化
onMounted(() => {
schoolDoorList.value = schoolDoorListData
getSchoolYearListData()
getSchoolTermDict()
getClassListData()
getLeaveTypeDict()
getYesNoDict()
})
// 暴露方法
defineExpose({
openDialog
})
</script>
<style scoped lang="scss">
</style>