This commit is contained in:
yaojian
2026-03-13 18:36:27 +08:00
parent c611c3e720
commit ff1d38752d
6 changed files with 498 additions and 53 deletions

View File

@@ -98,11 +98,22 @@
{{ formatStudentStatus(scope.row.stuStatus) }}
</el-tag>
</template>
<!-- 考勤类型列特殊模板 -->
<!-- 考勤类型列 - 可编辑下拉框 -->
<template v-else-if="col.prop === 'attendanceType'" #default="scope">
<el-tag size="small" type="warning" effect="plain" round>
{{ formatAttendanceType(scope.row.attendanceType) }}
</el-tag>
<el-select
v-model="scope.row.attendanceType"
placeholder="请选择"
size="small"
style="width: 100%"
:disabled="!scope.row.canChangeAttendType"
>
<el-option
v-for="item in attendanceTypeList"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</template>
<!-- 是否住宿列特殊模板 -->
<template v-else-if="col.prop === 'isRoom'" #default="scope">
@@ -123,27 +134,72 @@
</template>
</el-table-column>
</template>
<el-table-column label="操作" width="100" align="center" fixed="right">
<template #header>
<el-icon><Setting /></el-icon>
<span style="margin-left: 4px">操作</span>
</template>
<template #default="scope">
<el-button icon="EditPen" link type="primary" @click="handleEdit(scope.row)"> 编辑 </el-button>
</template>
</el-table-column>
<template #empty>
<el-empty description="暂无数据" :image-size="120"> </el-empty>
</template>
</el-table>
<!-- 提交考勤区域 -->
<div class="submit-attendance" v-if="dataList.length > 0">
<el-divider />
<el-form :model="submitForm" label-width="100px" class="submit-form">
<el-row :gutter="24">
<el-col :span="8">
<el-form-item label="考勤照片">
<el-upload
class="photo-uploader"
:action="uploadUrl"
:show-file-list="false"
:on-success="handlePhotoSuccess"
:before-upload="beforePhotoUpload"
accept="image/*"
>
<el-image
v-if="submitForm.photo"
:src="submitForm.photo"
class="photo-preview"
fit="cover"
/>
<el-icon v-else class="photo-uploader-icon"><Plus /></el-icon>
</el-upload>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="班级">
<el-input :value="selectedClassName" disabled />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="点名类型">
<el-input :value="selectedOrderTypeName" disabled />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24" style="text-align: center">
<el-button
type="primary"
size="large"
:loading="submitLoading"
:disabled="!canSubmit"
@click="handleSubmit"
>
<el-icon><CircleCheck /></el-icon>
提交考勤
</el-button>
</el-col>
</el-row>
</el-form>
</div>
</el-card>
</div>
</div>
</template>
<script setup lang="ts" name="ClassAttendance">
import { reactive, ref, onMounted } from 'vue';
import { fetchList, queryMyClassList } from '/@/api/stuwork/classattendance';
import { reactive, ref, onMounted, computed } from 'vue';
import { fetchList, saveDataBatch } from '/@/api/stuwork/classattendance';
import { getClassListByRole } from '/@/api/basic/basicclass';
import { getDicts } from '/@/api/admin/dict';
import { useMessage } from '/@/hooks/message';
import TableColumnControl from '/@/components/TableColumnControl/index.vue';
@@ -156,11 +212,10 @@ import {
Collection,
House,
Camera,
Setting,
Menu,
Search,
Document,
EditPen,
Plus,
} from '@element-plus/icons-vue';
import { useTableColumnControl } from '/@/hooks/tableColumn';
import { defineAsyncComponent } from 'vue';
@@ -171,12 +226,40 @@ const searchFormRef = ref();
const columnControlRef = ref();
const showSearch = ref(true);
const loading = ref(false);
const submitLoading = ref(false);
const dataList = ref<any[]>([]);
const classList = ref<any[]>([]);
const orderTypeList = ref<any[]>([]);
const studentStatusList = ref<any[]>([]);
const attendanceTypeList = ref<any[]>([]);
// 上传地址
const uploadUrl = ref('/admin/sys-file/upload');
// 提交表单
const submitForm = reactive({
photo: '',
});
// 选中的班级名称
const selectedClassName = computed(() => {
if (!searchForm.classCode) return '';
const classItem = classList.value.find((item: any) => item.classCode === searchForm.classCode);
return classItem ? classItem.classNo : '';
});
// 选中的点名类型名称
const selectedOrderTypeName = computed(() => {
if (!searchForm.orderType) return '';
const orderItem = orderTypeList.value.find((item: any) => item.value === searchForm.orderType);
return orderItem ? orderItem.label : '';
});
// 是否可以提交
const canSubmit = computed(() => {
return searchForm.classCode && searchForm.orderType && dataList.value.length > 0;
});
// 表格列配置
const tableColumns = [
{ prop: 'stuNo', label: '学号', icon: CreditCard },
@@ -185,7 +268,7 @@ const tableColumns = [
{ prop: 'parentPhoneA', label: '家长联系电话1', icon: Phone },
{ prop: 'parentPhoneB', label: '家长联系电话2', icon: Phone },
{ prop: 'stuStatus', label: '学生状态', icon: CircleCheck },
{ prop: 'attendanceType', label: '考勤类型', icon: Collection },
{ prop: 'attendanceType', label: '考勤类型', icon: Collection, width: 150 },
{ prop: 'isRoom', label: '是否住宿', icon: House },
{ prop: 'roomNo', label: '宿舍号', icon: House },
{ prop: 'isDeviceIn', label: '是否扫脸', icon: Camera },
@@ -234,21 +317,21 @@ const handleReset = () => {
searchFormRef.value?.resetFields();
searchForm.classCode = '';
searchForm.orderType = '';
getDataList();
};
// 编辑
const handleEdit = (row: any) => {
useMessage().info('编辑功能待实现');
dataList.value = [];
submitForm.photo = '';
};
// 获取数据列表
const getDataList = async () => {
if (!searchForm.classCode || !searchForm.orderType) {
useMessage().warning('请先选择班级和点名类型');
return;
}
loading.value = true;
try {
const params: any = {
classCode: searchForm.classCode || undefined,
orderType: searchForm.orderType || undefined,
classCode: searchForm.classCode,
orderType: searchForm.orderType,
};
const res = await fetchList(params);
@@ -265,16 +348,92 @@ const getDataList = async () => {
}
};
// 图片上传成功
const handlePhotoSuccess = (response: any) => {
if (response.code === 0 && response.data) {
submitForm.photo = response.data.url;
useMessage().success('图片上传成功');
} else {
useMessage().error(response.msg || '图片上传失败');
}
};
// 图片上传前验证
const beforePhotoUpload = (file: File) => {
const isImage = file.type.startsWith('image/');
const isLt5M = file.size / 1024 / 1024 < 5;
if (!isImage) {
useMessage().error('只能上传图片文件!');
return false;
}
if (!isLt5M) {
useMessage().error('图片大小不能超过 5MB!');
return false;
}
return true;
};
// 提交考勤
const handleSubmit = async () => {
if (!searchForm.classCode || !searchForm.orderType) {
useMessage().warning('请先选择班级和点名类型');
return;
}
submitLoading.value = true;
try {
const submitData = {
photo: submitForm.photo,
classCode: searchForm.classCode,
orderType: searchForm.orderType,
list: dataList.value.map((item: any) => ({
stuNo: item.stuNo,
realName: item.realName,
attendanceType: item.attendanceType,
roomNo: item.roomNo,
stayDorm: item.stayDorm,
leaveReason: item.leaveReason,
leaveStartTime: item.leaveStartTime,
leaveEndTime: item.leaveEndTime,
bedNo: item.bedNo,
dealContent: item.dealContent,
parentPhoneA: item.parentPhoneA,
parentPhoneB: item.parentPhoneB,
phone: item.phone,
stuStatus: item.stuStatus,
isRoom: item.isRoom,
canChangeAttendType: item.canChangeAttendType,
classCode: item.classCode,
truancyNums: item.truancyNums,
outContactNums: item.outContactNums,
isDeviceIn: item.isDeviceIn,
})),
};
await saveDataBatch(submitData);
useMessage().success('考勤提交成功');
// 清空数据
dataList.value = [];
submitForm.photo = '';
} catch (err: any) {
useMessage().error(err.msg || '考勤提交失败');
} finally {
submitLoading.value = false;
}
};
// 获取班级列表
const getClassListData = async () => {
try {
const res = await queryMyClassList();
if (res.data && Array.isArray(res.data)) {
classList.value = res.data;
const res = await getClassListByRole();
if (res.data) {
classList.value = Array.isArray(res.data) ? res.data : [];
} else {
classList.value = [];
}
} catch (err) {
console.error('获取班级列表失败', err);
classList.value = [];
}
};
@@ -282,13 +441,17 @@ const getClassListData = async () => {
// 获取点名类型字典
const getOrderTypeDict = async () => {
try {
orderTypeList.value = [
{ label: '早读', value: '1' },
{ label: '上午', value: '2' },
{ label: '下午', value: '3' },
{ label: '晚自习', value: '4' },
];
const res = await getDicts('call_type');
if (res.data && Array.isArray(res.data)) {
orderTypeList.value = res.data.map((item: any) => ({
label: item.label || item.dictLabel || item.name,
value: item.value || item.dictValue || item.code,
}));
} else {
orderTypeList.value = [];
}
} catch (err) {
console.error('获取点名类型字典失败', err);
orderTypeList.value = [];
}
};
@@ -338,4 +501,44 @@ onMounted(() => {
<style scoped lang="scss">
@import '/@/assets/styles/modern-page.scss';
</style>
.submit-attendance {
margin-top: 20px;
padding: 20px;
background: #f5f7fa;
border-radius: 8px;
.submit-form {
max-width: 100%;
}
}
.photo-uploader {
:deep(.el-upload) {
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
width: 120px;
height: 120px;
display: flex;
align-items: center;
justify-content: center;
&:hover {
border-color: #409eff;
}
}
.photo-preview {
width: 120px;
height: 120px;
}
.photo-uploader-icon {
font-size: 28px;
color: #8c939d;
}
}
</style>

View File

@@ -54,6 +54,11 @@
<el-option v-for="item in classList" :key="item.classCode" :label="item.classNo" :value="item.classCode"> </el-option>
</el-select>
</el-form-item>
<el-form-item label="审核状态" prop="auditStatus">
<el-select v-model="searchForm.auditStatus" placeholder="请选择审核状态" clearable style="width: 200px">
<el-option v-for="item in auditStatusList" :key="item.value" :label="item.label" :value="item.value"> </el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" plain icon="Search" @click="handleSearch">查询</el-button>
<el-button icon="Refresh" @click="handleReset">重置</el-button>
@@ -71,6 +76,8 @@
</span>
<div class="header-actions">
<el-button icon="FolderAdd" type="primary" @click="formDialogRef.openDialog()"> </el-button>
<el-button icon="Check" type="success" @click="handleBatchAudit('2')" :disabled="selectedRows.length === 0"> 批量通过 </el-button>
<el-button icon="Close" type="danger" @click="handleBatchAudit('3')" :disabled="selectedRows.length === 0"> 批量不通过 </el-button>
<el-button icon="Download" type="success" class="ml10" @click="handleExport"> </el-button>
<right-toolbar v-model:showSearch="showSearch" class="ml10" @queryTable="getDataList">
<TableColumnControl
@@ -100,10 +107,12 @@
:data="state.dataList"
v-loading="state.loading"
stripe
@selection-change="handleSelectionChange"
:cell-style="tableStyle.cellStyle"
:header-cell-style="tableStyle.headerCellStyle"
class="modern-table"
>
<el-table-column type="selection" width="55" align="center" :selectable="checkSelectable" />
<el-table-column type="index" label="序号" width="70" align="center">
<template #header>
<el-icon><List /></el-icon>
@@ -135,16 +144,20 @@
<span>{{ formatLiveType(scope.row.liveType) }}</span>
</template>
<template #default="scope" v-else-if="col.prop === 'auditStatus'">
<span>{{ formatAuditStatus(scope.row.auditStatus) }}</span>
<el-tag :type="getAuditStatusType(scope.row.auditStatus)" size="small" effect="plain">
{{ formatAuditStatus(scope.row.auditStatus) }}
</el-tag>
</template>
</el-table-column>
</template>
<el-table-column label="操作" width="150" align="center" fixed="right">
<el-table-column label="操作" width="250" align="center" fixed="right">
<template #header>
<el-icon><Setting /></el-icon>
<span style="margin-left: 4px">操作</span>
</template>
<template #default="scope">
<el-button v-if="scope.row.auditStatus === '1'" icon="Check" link type="success" @click="handleAudit(scope.row, '2')"> 通过 </el-button>
<el-button v-if="scope.row.auditStatus === '1'" icon="Close" link type="danger" @click="handleAudit(scope.row, '3')"> 不通过 </el-button>
<el-button icon="Edit" link type="primary" @click="handleEdit(scope.row)"> 编辑 </el-button>
<el-button icon="Delete" link type="danger" @click="handleDelete(scope.row)"> 删除 </el-button>
</template>
@@ -163,13 +176,31 @@
<!-- 新增/编辑表单弹窗 -->
<form-dialog ref="formDialogRef" @refresh="getDataList" />
<!-- 审批弹窗 -->
<el-dialog v-model="auditDialogVisible" :title="auditForm.auditStatus === '2' ? '审批通过' : '审批不通过'" width="500" :close-on-click-modal="false" draggable>
<el-form :model="auditForm" label-width="80px">
<el-form-item label="审核结果">
<el-tag :type="auditForm.auditStatus === '2' ? 'success' : 'danger'" size="large">
{{ auditForm.auditStatus === '2' ? '通过' : '不通过' }}
</el-tag>
</el-form-item>
<el-form-item label="审核备注">
<el-input v-model="auditForm.auditRemark" type="textarea" :rows="3" placeholder="请输入审核备注(选填)" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="auditDialogVisible = false"> </el-button>
<el-button type="primary" @click="submitAudit" :loading="auditLoading"> </el-button>
</template>
</el-dialog>
</div>
</template>
<script setup lang="ts" name="DormLiveApply">
import { reactive, ref, onMounted } from 'vue';
import { BasicTableProps, useTable } from '/@/hooks/table';
import { fetchList, delObj, exportData } from '/@/api/stuwork/dormliveapply';
import { fetchList, delObj, exportData, auditApply, batchAuditApply } from '/@/api/stuwork/dormliveapply';
import { queryAllSchoolYear } from '/@/api/basic/basicyear';
import { getDicts } from '/@/api/admin/dict';
import { getBuildingList } from '/@/api/stuwork/dormbuilding';
@@ -177,7 +208,7 @@ import { getClassListByRole } from '/@/api/basic/basicclass';
import { useMessage, useMessageBox } from '/@/hooks/message';
import TableColumnControl from '/@/components/TableColumnControl/index.vue';
import FormDialog from './form.vue';
import { List, Calendar, Clock, OfficeBuilding, Grid, Menu, Search, Document, Setting, User } from '@element-plus/icons-vue';
import { List, Calendar, Clock, OfficeBuilding, Grid, Menu, Search, Document, Setting, User, Check, Close } from '@element-plus/icons-vue';
import { useTableColumnControl } from '/@/hooks/tableColumn';
// 定义变量内容
@@ -191,6 +222,16 @@ const classList = ref<any[]>([]);
const liveTypeList = ref<any[]>([]);
const auditStatusList = ref<any[]>([]);
const formDialogRef = ref();
const selectedRows = ref<any[]>([]);
const auditDialogVisible = ref(false);
const auditLoading = ref(false);
const auditForm = reactive({
id: '',
auditStatus: '',
auditRemark: '',
isBatch: false,
ids: [] as string[],
});
// 表格列配置
const tableColumns = [
@@ -216,6 +257,7 @@ const searchForm = reactive({
startTime: '',
endTime: '',
classCode: '',
auditStatus: '',
});
// 配置 useTable
@@ -255,6 +297,20 @@ const formatAuditStatus = (value: string) => {
return item ? item.label : value;
};
// 获取审核状态标签类型
const getAuditStatusType = (value: string) => {
switch (value) {
case '1':
return 'warning';
case '2':
return 'success';
case '3':
return 'danger';
default:
return 'info';
}
};
// 查询
const handleSearch = () => {
getDataList();
@@ -269,6 +325,7 @@ const handleReset = () => {
searchForm.startTime = '';
searchForm.endTime = '';
searchForm.classCode = '';
searchForm.auditStatus = '';
getDataList();
};
@@ -311,6 +368,59 @@ const handleExport = async () => {
}
};
// 选择变化
const handleSelectionChange = (rows: any[]) => {
selectedRows.value = rows;
};
// 判断是否可选(只有待审核状态可选)
const checkSelectable = (row: any) => {
return row.auditStatus === '1';
};
// 单个审批
const handleAudit = (row: any, auditStatus: string) => {
auditForm.id = row.id;
auditForm.auditStatus = auditStatus;
auditForm.auditRemark = '';
auditForm.isBatch = false;
auditForm.ids = [];
auditDialogVisible.value = true;
};
// 批量审批
const handleBatchAudit = (auditStatus: string) => {
if (selectedRows.value.length === 0) {
useMessage().warning('请选择要审批的记录');
return;
}
auditForm.id = '';
auditForm.auditStatus = auditStatus;
auditForm.auditRemark = '';
auditForm.isBatch = true;
auditForm.ids = selectedRows.value.map((row) => row.id);
auditDialogVisible.value = true;
};
// 提交审批
const submitAudit = async () => {
auditLoading.value = true;
try {
if (auditForm.isBatch) {
await batchAuditApply(auditForm.ids, auditForm.auditStatus, auditForm.auditRemark);
} else {
await auditApply(auditForm.id, auditForm.auditStatus, auditForm.auditRemark);
}
useMessage().success('审批成功');
auditDialogVisible.value = false;
getDataList();
} catch (err: any) {
useMessage().error(err.msg || '审批失败');
} finally {
auditLoading.value = false;
}
};
// 获取学年列表
const getSchoolYearList = async () => {
try {

View File

@@ -104,11 +104,29 @@
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="校门" prop="schoolDoor">
<el-select
v-model="form.schoolDoor"
placeholder="请选择校门"
clearable
filterable
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"
<el-input
v-model="form.reason"
type="textarea"
:rows="4"
placeholder="请输入请假事由" />
</el-form-item>
@@ -139,8 +157,9 @@ import { ref, reactive, nextTick, onMounted } from 'vue'
import { useMessage } from '/@/hooks/message'
import { addObj } from '/@/api/stuwork/stutemleaveapply'
import { getDeptListByLevelTwo } from '/@/api/basic/basicdept'
import { list as getClassList } from '/@/api/basic/basicclass'
import { queryStudentListByClass } from '/@/api/basic/basicstudent'
import { getClassListByRole } from '/@/api/basic/basicclass'
import { queryStudentListByClass, queryAllStudentByClassCode } from '/@/api/basic/basicstudent'
import { listAll as getSchoolDoorList } from '/@/api/safety/clouddeviceposition'
const emit = defineEmits(['refresh'])
@@ -149,8 +168,10 @@ const dataFormRef = ref()
const visible = ref(false)
const loading = ref(false)
const deptList = ref<any[]>([])
const classList = ref<any[]>([])
const allClassList = ref<any[]>([]) // 保存所有班级数据
const classList = ref<any[]>([]) // 显示的班级数据(筛选后)
const studentList = ref<any[]>([])
const schoolDoorList = ref<any[]>([])
// 提交表单数据
const form = reactive({
@@ -160,6 +181,7 @@ const form = reactive({
realName: '',
startTime: '',
endTime: '',
schoolDoor: '',
reason: '',
remarks: ''
})
@@ -203,9 +225,12 @@ const resetForm = () => {
form.realName = ''
form.startTime = ''
form.endTime = ''
form.schoolDoor = ''
form.reason = ''
form.remarks = ''
studentList.value = []
// 重置班级列表为全部
classList.value = allClassList.value
}
// 系部变化
@@ -216,9 +241,9 @@ const handleDeptChange = () => {
studentList.value = []
// 根据系部筛选班级
if (form.deptCode) {
classList.value = classList.value.filter((item: any) => item.deptCode === form.deptCode)
classList.value = allClassList.value.filter((item: any) => item.deptCode === form.deptCode)
} else {
getClassListData()
classList.value = allClassList.value
}
}
@@ -267,6 +292,7 @@ const onSubmit = async () => {
stuNo: form.stuNo,
startTime: form.startTime,
endTime: form.endTime,
schoolDoor: form.schoolDoor,
reason: form.reason,
remarks: form.remarks
})
@@ -296,37 +322,70 @@ const getDeptListData = async () => {
// 获取班级列表
const getClassListData = async () => {
try {
const res = await getClassList()
const res = await getClassListByRole()
if (res.data) {
classList.value = Array.isArray(res.data) ? res.data : []
const list = Array.isArray(res.data) ? res.data : []
allClassList.value = list
classList.value = list
}
} catch (err) {
allClassList.value = []
classList.value = []
}
}
// 获取学生列表接口文档GET 仅 classCode返回 data 为数组)
// 获取学生列表
const getStudentListData = async () => {
if (!form.classCode) return
try {
const res = await queryStudentListByClass({ classCode: form.classCode })
const data = res?.data
// 先尝试 queryStudentListByClass 接口
let res = await queryStudentListByClass({ classCode: form.classCode })
let data = res?.data
// 如果数据为空或不是数组,尝试 queryAllStudentByClassCode 接口
if (!data || (Array.isArray(data) && data.length === 0)) {
res = await queryAllStudentByClassCode(form.classCode)
data = res?.data
}
if (Array.isArray(data)) {
studentList.value = data
} else if (data?.records && Array.isArray(data.records)) {
studentList.value = data.records
} else if (data && typeof data === 'object') {
// 可能返回的是单个对象或包装对象
studentList.value = [data]
} else {
studentList.value = []
}
} catch (err) {
console.error('获取学生列表失败', err)
studentList.value = []
}
}
// 获取校门列表
const getSchoolDoorData = async () => {
try {
const res = await getSchoolDoorList()
if (res.data) {
schoolDoorList.value = Array.isArray(res.data)
? res.data.map((item: any) => ({
label: item.positionName || item.name,
value: item.id || item.positionCode
}))
: []
}
} catch (err) {
schoolDoorList.value = []
}
}
// 初始化
onMounted(() => {
getDeptListData()
getClassListData()
getSchoolDoorData()
})
// 暴露方法

View File

@@ -136,6 +136,9 @@
</template>
<template #default="scope" v-else-if="col.prop === 'endTime'">
<span>{{ scope.row.endTime ? formatDateTime(scope.row.endTime) : '-' }}</span>
</template>
<template #default="scope" v-else-if="col.prop === 'schoolDoor'">
<span>{{ formatSchoolDoor(scope.row.schoolDoor) }}</span>
</template>
</el-table-column>
</template>
@@ -179,6 +182,7 @@ import { fetchList, delObj } from "/@/api/stuwork/stutemleaveapply";
import { getDicts } from "/@/api/admin/dict";
import { getDeptListByLevelTwo } from "/@/api/basic/basicdept";
import { getClassListByRole } from "/@/api/basic/basicclass";
import { listAll as getSchoolDoorListApi } from "/@/api/safety/clouddeviceposition";
import { useMessage, useMessageBox } from "/@/hooks/message";
import TableColumnControl from '/@/components/TableColumnControl/index.vue'
import FormDialog from './form.vue'
@@ -194,6 +198,7 @@ const showSearch = ref(true)
const deptList = ref<any[]>([])
const classList = ref<any[]>([])
const schoolTermList = ref<any[]>([])
const schoolDoorList = ref<any[]>([])
const formDialogRef = ref()
// 表格列配置
@@ -206,6 +211,7 @@ const tableColumns = [
{ prop: 'realName', label: '姓名', icon: Avatar },
{ prop: 'startTime', label: '请假开始时间', icon: Calendar, width: 180 },
{ prop: 'endTime', label: '请假结束时间', icon: Calendar, width: 180 },
{ prop: 'schoolDoor', label: '校门', icon: OfficeBuilding, width: 100 },
{ prop: 'reason', label: '请假事由', icon: Document, minWidth: 150 },
{ prop: 'classTeach', label: '班主任', icon: UserFilled },
{ prop: 'stuPhote', label: '联系方式', icon: Phone },
@@ -256,6 +262,15 @@ const formatSchoolTerm = (value: string | number) => {
return dictItem ? dictItem.label : value
}
// 格式化校门
const formatSchoolDoor = (value: string) => {
if (value === null || value === undefined || value === '') {
return '-'
}
const dictItem = schoolDoorList.value.find(item => item.value === value)
return dictItem ? dictItem.label : value
}
// 格式化日期时间
const formatDateTime = (dateTime: string) => {
if (!dateTime) return '-'
@@ -331,11 +346,29 @@ const getSchoolTermDict = async () => {
}
}
// 获取校门列表
const getSchoolDoorData = async () => {
try {
const res = await getSchoolDoorListApi()
if (res.data) {
schoolDoorList.value = Array.isArray(res.data)
? res.data.map((item: any) => ({
label: item.positionName || item.name,
value: item.id || item.positionCode
}))
: []
}
} catch (err) {
schoolDoorList.value = []
}
}
// 初始化
onMounted(() => {
getDeptListData()
getClassListData()
getSchoolTermDict()
getSchoolDoorData()
})
</script>