47 7 ماه پیش
والد
کامیت
4553f11cbb

+ 8 - 2
src/api/system/studentAttendance/index.ts

@@ -10,7 +10,7 @@ export interface StudentAttendanceVO {
   clockInStatus: string // 打卡状态 0正常,1迟到、2早退、3缺勤、4请假
   remark: string // 备注原因
   studentName: string // 学生名称
-  importStatus: string // 导入状态 0未导入,1已导入
+  
 }
 
 // 学生考勤记录 API
@@ -19,12 +19,12 @@ export const StudentAttendanceApi = {
   getStudentAttendancePage: async (params: any) => {
     return await request.get({ url: `/system/student-attendance/page`, params })
   },
+
   // 查询学生考勤记录分页
   getStudentAttendanceErrorPage: async (params: any) => {
     return await request.get({ url: `/system/student-attendance/errorPage`, params })
   },
 
-
   // 查询学生考勤记录详情
   getStudentAttendance: async (id: number) => {
     return await request.get({ url: `/system/student-attendance/get?id=` + id })
@@ -45,6 +45,12 @@ export const StudentAttendanceApi = {
     return await request.delete({ url: `/system/student-attendance/delete?id=` + id })
   },
 
+  // 查询学生个人考勤信息
+  getStudentAttendanceSelfPage: async (id: number) => {
+    return await request.get({ url: `/system/student-attendance /selfPage`, id })
+  },
+  
+
   // 导出学生考勤记录 Excel
   exportStudentAttendance: async (params) => {
     return await request.download({ url: `/system/student-attendance/export-excel`, params })

+ 15 - 2
src/api/system/user/index.ts

@@ -16,6 +16,9 @@ export interface UserVO {
   loginDate: Date
   createTime: Date
   userType: string
+  importStatus: string// 导入状态
+  photoUrl: string// 学生照片
+  userNumber: string// 学号
 }
 
 // 查询用户管理列表
@@ -32,7 +35,6 @@ export const getStudentPage = (params: PageParam) => {
   return request.get({ url: '/system/user/page1', params })
 }
 
-
 // 查询当前工作间下老师管理列表
 export const getDeptTeacherPage = (params: PageParam) => {
   return request.get({ url: '/system/user/DeptTeacherPage', params })
@@ -42,6 +44,14 @@ export const getDeptTeacherPage = (params: PageParam) => {
 export const getDeptStudentPage = (params: PageParam) => {
   return request.get({ url: '/system/user/DeptStudentPage', params })
 }
+const params = {
+  // 这里填写你的参数,例如:
+  pageNo: 1,
+  pageSize: 10,
+}
+const response = await getDeptStudentPage(params);
+console.log(response);
+
 // 查询当前工作间下用户
 export const getDeptUser = () => {
   return request.get({ url: '/system/user/DeptUser'})
@@ -62,7 +72,10 @@ export const getSupervisor = () => {
   return request.get({ url: '/system/user/supervisor'})
 }
 
-
+// 教师更新学生图片
+export const updateStudentImg = (employeeNo: string, photoUrl: string) => {
+  return request.post({ url: `/md/acs/teacher-updateUserImage?employeeNo=${employeeNo}&photoUrl=${photoUrl}` })
+}
 
 
 // 查询所有用户列表

+ 0 - 131
src/views/system/studentAttendanceManage/studentFaceManage/StudentAttendanceForm.vue

@@ -1,131 +0,0 @@
-<template>
-  <Dialog :title="dialogTitle" v-model="dialogVisible">
-    <el-form
-      ref="formRef"
-      :model="formData"
-      :rules="formRules"
-      label-width="100px"
-      v-loading="formLoading"
-    >
-      <el-form-item label="学生id" prop="studentId">
-        <el-input v-model="formData.studentId" placeholder="请输入学生id" />
-      </el-form-item>
-      <el-form-item label="工作间id" prop="deptId">
-        <el-input v-model="formData.deptId" placeholder="请输入工作间id" />
-      </el-form-item>
-      <el-form-item label="日期" prop="date">
-        <el-date-picker
-          v-model="formData.date"
-          type="date"
-          value-format="x"
-          placeholder="选择日期"
-        />
-      </el-form-item>
-      <el-form-item label="打卡时间" prop="clockInTime">
-        <el-date-picker
-          v-model="formData.clockInTime"
-          type="date"
-          value-format="x"
-          placeholder="选择打卡时间"
-        />
-      </el-form-item>
-      <el-form-item label="打卡状态 0正常,1迟到、2早退、3缺勤、4请假" prop="clockInStatus">
-        <el-radio-group v-model="formData.clockInStatus">
-          <el-radio label="1">请选择字典生成</el-radio>
-        </el-radio-group>
-      </el-form-item>
-      <el-form-item label="备注原因" prop="remark">
-        <el-input v-model="formData.remark" placeholder="请输入备注原因" />
-      </el-form-item>
-    </el-form>
-    <template #footer>
-      <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
-      <el-button @click="dialogVisible = false">取 消</el-button>
-    </template>
-  </Dialog>
-</template>
-<script setup lang="ts">
-import { StudentAttendanceApi, StudentAttendanceVO } from '@/api/system/studentAttendance'
-
-/** 学生考勤记录 表单 */
-defineOptions({ name: 'StudentAttendanceForm' })
-
-const { t } = useI18n() // 国际化
-const message = useMessage() // 消息弹窗
-
-const dialogVisible = ref(false) // 弹窗的是否展示
-const dialogTitle = ref('') // 弹窗的标题
-const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
-const formType = ref('') // 表单的类型:create - 新增;update - 修改
-const formData = ref({
-  id: undefined,
-  studentId: undefined,
-  deptId: undefined,
-  date: undefined,
-  clockInTime: undefined,
-  clockInStatus: undefined,
-  remark: undefined,
-})
-const formRules = reactive({
-  studentId: [{ required: true, message: '学生id不能为空', trigger: 'blur' }],
-  deptId: [{ required: true, message: '工作间id不能为空', trigger: 'blur' }],
-  date: [{ required: true, message: '日期不能为空', trigger: 'blur' }],
-})
-const formRef = ref() // 表单 Ref
-
-/** 打开弹窗 */
-const open = async (type: string, id?: number) => {
-  dialogVisible.value = true
-  dialogTitle.value = t('action.' + type)
-  formType.value = type
-  resetForm()
-  // 修改时,设置数据
-  if (id) {
-    formLoading.value = true
-    try {
-      formData.value = await StudentAttendanceApi.getStudentAttendance(id)
-    } finally {
-      formLoading.value = false
-    }
-  }
-}
-defineExpose({ open }) // 提供 open 方法,用于打开弹窗
-
-/** 提交表单 */
-const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
-const submitForm = async () => {
-  // 校验表单
-  await formRef.value.validate()
-  // 提交请求
-  formLoading.value = true
-  try {
-    const data = formData.value as unknown as StudentAttendanceVO
-    if (formType.value === 'create') {
-      await StudentAttendanceApi.createStudentAttendance(data)
-      message.success(t('common.createSuccess'))
-    } else {
-      await StudentAttendanceApi.updateStudentAttendance(data)
-      message.success(t('common.updateSuccess'))
-    }
-    dialogVisible.value = false
-    // 发送操作成功的事件
-    emit('success')
-  } finally {
-    formLoading.value = false
-  }
-}
-
-/** 重置表单 */
-const resetForm = () => {
-  formData.value = {
-    id: undefined,
-    studentId: undefined,
-    deptId: undefined,
-    date: undefined,
-    clockInTime: undefined,
-    clockInStatus: undefined,
-    remark: undefined,
-  }
-  formRef.value?.resetFields()
-}
-</script>

+ 89 - 164
src/views/system/studentAttendanceManage/studentFaceManage/StudentFaceForm.vue

@@ -1,194 +1,119 @@
 <template>
-  <Dialog v-model="dialogVisible" title="用户批量导入" width="400">
-    <el-upload
-      ref="uploadRef"
-      v-model:file-list="fileList"
-      :action="importUrl + '?updateSupport=' + updateSupport"
-      :auto-upload="false"
-      :disabled="formLoading"
-      :headers="uploadHeaders"
-      :on-error="submitFormError"
-      :on-success="submitFormSuccess"
-      accept=".xlsx, .xls"
-      drag
+  <Dialog :title="dialogTitle" v-model="dialogVisible">
+    <el-form
+      ref="formRef"
+      :model="formData"
+      label-width="100px"
+      v-loading="formLoading"
     >
-      <Icon icon="ep:upload" />
-      <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
-      <template #tip>
-        <div class="el-upload__tip text-center">
-          <!-- <div class="el-upload__tip">
-            <el-checkbox v-model="updateSupport" />
-            是否更新已经存在的用户数据
-          </div> -->
-          <span>仅允许导入 xlsx, xls 格式文件。</span>
-          <el-link
-            :underline="false"
-            style="font-size: 12px; vertical-align: baseline"
-            type="primary"
-            @click="importTemplate"
-          >
-            下载模板
-          </el-link>
-        </div>
-      </template>
-    </el-upload>
-    <el-upload
-      ref="uploadZipRef"
-      v-model:file-list="zipList"
-      drag
-      :action="importZipUrl + '?updateSupport=' + updateSupport"
-      :on-success="submitZipSuccess"
-      :auto-upload="false"
-      :disabled="formLoading"
-      :headers="uploadHeaders"
-      :on-error="submitFormError"
-      :http-request="httpRequest"
-      accept=".zip,.rar"
-    >
-      <Icon icon="ep:upload" />
-      <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
-      <template #tip>
-        <div class="el-upload__tip text-center">
-          <span>仅允许导入 zip、rar 格式压缩包。</span>
-          <div class="el-upload__tip">
-            <el-checkbox v-model="updateSupport" />
-            是否更新已经存在的用户数据
-          </div>
-        </div>
-      </template>
-    </el-upload>
+      <el-form-item label="照片详情url" prop="photoUrl">
+        <UploadImg v-model="formData.photoUrl" />
+      </el-form-item>
+    </el-form>
     <template #footer>
-      <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button>
+      <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
       <el-button @click="dialogVisible = false">取 消</el-button>
     </template>
   </Dialog>
 </template>
-<script lang="ts" setup>
-// import * as faceApi from '@/api/system/face'
+<script setup lang="ts">
+// import { UserAchievementApi, UserAchievementVO } from '@/api/system/userAchievement'
 import * as UserApi from '@/api/system/user'
-import { getAccessToken, getTenantId } from '@/utils/auth'
-import download from '@/utils/download'
-import {useUpload} from "@/components/UploadFile/src/useUpload";
-defineOptions({ name: 'SystemUserImportForm' })
+import { UserVO } from '@/api/system/user'
+
 
+/** 成果 表单 */
+defineOptions({ name: 'UserAchievementForm' })
+
+const { t } = useI18n() // 国际化
 const message = useMessage() // 消息弹窗
-const {  httpRequest } = useUpload()
-const dialogVisible = ref(false) // 弹窗的是否展示
-const formLoading = ref(false) // 表单的加载中
-const uploadRef = ref()
-const uploadZipRef = ref()
-const importUrl =
-  import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + '/md/acs/import-data'
-const importZipUrl =
-  import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + '/md/acs/import-data'
-const uploadHeaders = ref() // 上传 Header 头
-const fileList = ref([]) // 文件列表
-const updateSupport = ref(0) // 是否更新已经存在的用户数据
 
-const zipList = ref([]) // 压缩文件列表
+const dialogVisible = ref(false) // 弹窗的是否展示
+const dialogTitle = ref('') // 弹窗的标题
+const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
+const formType = ref('') // 表单的类型:create - 新增;update - 修改
+const formData = ref({
+  userNumber : '',
+  photoUrl: '',
+})
+// const formRules = reactive({
+//   userId: [{ required: true, message: '用户id不能为空', trigger: 'blur' }],
+//   achievementName: [{ required: true, message: '成果名称不能为空', trigger: 'blur' }],
+//   achievementType: [{ required: true, message: '成果类型不能为空', trigger: 'change' }],
+//   userName: [{ required: true, message: '用户名称不能为空', trigger: 'blur' }],
+// })
+const formRef = ref() // 表单 Ref
 
+// /** 获取用户列表 */
+// const users = ref();
+// const getDeptUser = async () => {
+//     try {
+//         const response = await UserApi.getDeptUser();
+//         console.log(response);
+//         users.value = response;
+//     } catch (error) {
+//         console.error("Error fetching user data:", error);
+//     }
+// };
 
 /** 打开弹窗 */
-const open = () => {
+const open = async (type: string, id?: number) => {
   dialogVisible.value = true
-  updateSupport.value = 0
-  fileList.value = []
+  dialogTitle.value = t('action.' + type)
+  formType.value = type
   resetForm()
-  zipList.value = [] // 压缩文件列表
+  // 修改时,设置数据
+  if (id) {
+    formLoading.value = true
+    try {
+      formData.value = await UserApi.getUser(id)
+    } finally {
+      formLoading.value = false
+    }
+  }
 }
 defineExpose({ open }) // 提供 open 方法,用于打开弹窗
 
+/** 用户id更新 */
+// const handleUserChange = (selectedNickname: string) => {
+//   const selectedUser = users.value.find((user: any) => user.nickname === selectedNickname);
+//   formData.value.userId = selectedUser? selectedUser.id : undefined;
+// };
+
 /** 提交表单 */
+const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
 const submitForm = async () => {
-  // if (fileList.value.length == 0) {
-  //   message.error('请上传文件')
-  //   return
-  // }
-
-  // if (zipList.value.length === 0) {
-  //   message.error('请上传压缩包')
-  //   return
-  // }
-  if (fileList.value.length == 0 && zipList.value.length === 0) {
-    message.error('请上传文件或压缩包')
-    return
-  }
-
+  // 校验表单
+  // await formRef.value.validate()
   // 提交请求
-  uploadHeaders.value = {
-    Authorization: 'Bearer ' + getAccessToken(),
-    'tenant-id': getTenantId()
-  }
   formLoading.value = true
-  uploadRef.value!.submit()
-  uploadZipRef.value!.submit()
-}
-console.log(fileList,'fileList');
-
-
-/** 文件上传成功 */
-const emits = defineEmits(['success'])
-const submitFormSuccess = (response: any) => {
-  if (response.code !== 0) {
-    message.error(response.msg)
-    formLoading.value = false
-    return
-  }
-  // 拼接提示语
-  const data = response.data;
-  console.log(response.data,'123');
-  let text = '上传成功数量:' + data.createUsernames.length + ';'
-  for (let username of data.createUsernames) {
-    text += '< ' + username + ' >'
-  }
-  text += '更新成功数量:' + data.updateUsernames.length + ';'
-  for (const username of data.updateUsernames) {
-    text += '< ' + username + ' >'
-  }
-  text += '更新失败数量:' + Object.keys(data.failureUsernames).length + ';'
-  for (const username in data.failureUsernames) {
-    text += '< ' + username + ': ' + data.failureUsernames[username] + ' >'
-  }
-  message.alert(text)
-  formLoading.value = false
-  dialogVisible.value = false
-  // 发送操作成功的事件
-  emits('success')
-}
-
-const submitZipSuccess = (response: any) => {
-  if (response.code !== 0) {
-    message.error(response.msg)
+  try {
+    const data = formData.value as unknown as UserVO
+      console.log(data,'data');
+      // const message = await UserApi.updateStudentImg(data.userNumber, data.photoUrl)
+      await UserApi.updateStudentImg(data.userNumber, data.photoUrl)
+      message.success('修改成功')
+    
+    dialogVisible.value = false
+    // 发送操作成功的事件
+    emit('success')
+    // 通知父组件重新加载数据
+    
+  } finally {
     formLoading.value = false
-    return
   }
-  // 处理上传成功的逻辑,例如解压压缩包,处理里面的文件等
-  message.success('压缩包上传成功')
-  formLoading.value = false
-  dialogVisible.value = false
-  // 发送操作成功的事件
-  emits('success')
-}
-
-/** 上传错误提示 */
-const submitFormError = (): void => {
-  message.error('上传失败,请您重新上传!')
-  formLoading.value = false
 }
 
 /** 重置表单 */
-const resetForm = async (): Promise<void> => {
-  // 重置上传状态和文件
-  formLoading.value = false
-  await nextTick()
-  uploadRef.value?.clearFiles()
-  uploadZipRef.value?.clearFiles()
+const resetForm = () => {
+  formData.value = {
+    userNumber: '',
+    photoUrl: '',
+  }
+  formRef.value?.resetFields()
 }
 
-/** 下载模板操作 */
-const importTemplate = async () => {
-  const res = await UserApi.getAttendanceTemplate()
-  console.log(res,'111');
-  download.excel(res, '用户导入模版.xls')
-}
-</script>
+onMounted(() => {
+ 
+})
+</script>

+ 197 - 0
src/views/system/studentAttendanceManage/studentFaceManage/StudentFaceImport.vue

@@ -0,0 +1,197 @@
+<template>
+  <Dialog v-model="dialogVisible" title="用户批量导入" width="400">
+    <el-upload
+      ref="uploadRef"
+      v-model:file-list="fileList"
+      :action="importUrl + '?updateSupport=' + updateSupport"
+      :auto-upload="false"
+      :disabled="formLoading"
+      :headers="uploadHeaders"
+      :on-error="submitFormError"
+      :on-success="submitFormSuccess"
+      accept=".xlsx, .xls"
+      drag
+    >
+      <Icon icon="ep:upload" />
+      <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
+      <template #tip>
+        <div class="el-upload__tip text-center">
+          <!-- <div class="el-upload__tip">
+            <el-checkbox v-model="updateSupport" />
+            是否更新已经存在的用户数据
+          </div> -->
+          <span>仅允许导入 xlsx, xls 格式文件。</span>
+          <el-link
+            :underline="false"
+            style="font-size: 12px; vertical-align: baseline"
+            type="primary"
+            @click="importTemplate"
+          >
+            下载模板
+          </el-link>
+        </div>
+      </template>
+    </el-upload>
+    <el-upload
+      ref="uploadZipRef"
+      v-model:file-list="zipList"
+      drag
+      :action="importZipUrl + '?updateSupport=' + updateSupport"
+      :on-success="submitZipSuccess"
+      :auto-upload="false"
+      :disabled="formLoading"
+      :headers="uploadHeaders"
+      :on-error="submitFormError"
+      :http-request="httpRequest"
+      accept=".zip,.rar"
+    >
+      <Icon icon="ep:upload" />
+      <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
+      <template #tip>
+        <div class="el-upload__tip text-center">
+          <span>仅允许导入 zip、rar 格式压缩包。</span>
+          <div class="el-upload__tip">
+            <el-checkbox v-model="updateSupport" />
+            是否更新已经存在的用户数据
+          </div>
+        </div>
+      </template>
+    </el-upload>
+    <template #footer>
+      <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button>
+      <el-button @click="dialogVisible = false">取 消</el-button>
+    </template>
+  </Dialog>
+</template>
+<script lang="ts" setup>
+// import * as faceApi from '@/api/system/face'
+import * as UserApi from '@/api/system/user'
+import { getAccessToken, getTenantId } from '@/utils/auth'
+import download from '@/utils/download'
+import {useUpload} from "@/components/UploadFile/src/useUpload";
+defineOptions({ name: 'StudentFaceImport' })
+
+const message = useMessage() // 消息弹窗
+const {  httpRequest } = useUpload()
+const dialogVisible = ref(false) // 弹窗的是否展示
+const formLoading = ref(false) // 表单的加载中
+const uploadRef = ref()
+const uploadZipRef = ref()
+const importUrl =
+  import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + '/md/acs/import-data'
+const importZipUrl =
+  import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + '/md/acs/import-data'
+const uploadHeaders = ref() // 上传 Header 头
+const fileList = ref([]) // 文件列表
+const updateSupport = ref(0) // 是否更新已经存在的用户数据
+
+const zipList = ref([]) // 压缩文件列表
+
+
+/** 打开弹窗 */
+const open = () => {
+  dialogVisible.value = true
+  updateSupport.value = 0
+  fileList.value = []
+  resetForm()
+  zipList.value = [] // 压缩文件列表
+}
+defineExpose({ open }) // 提供 open 方法,用于打开弹窗
+
+/** 提交表单 */
+const submitForm = async () => {
+  // if (fileList.value.length == 0) {
+  //   message.error('请上传文件')
+  //   return
+  // }
+
+  // if (zipList.value.length === 0) {
+  //   message.error('请上传压缩包')
+  //   return
+  // }
+  if (fileList.value.length == 0 && zipList.value.length === 0) {
+    message.error('请上传文件或压缩包')
+    return
+  }
+
+  // 提交请求
+  uploadHeaders.value = {
+    Authorization: 'Bearer ' + getAccessToken(),
+    'tenant-id': getTenantId()
+  }
+  formLoading.value = true
+  uploadRef.value!.submit()
+  uploadZipRef.value!.submit()
+}
+console.log(fileList,'fileList');
+
+
+/** 文件上传成功 */
+const emits = defineEmits(['success'])
+const submitFormSuccess = (response: any) => {
+  if (response.data.code !== 0) {
+    console.log(response.data.code,'code');
+    
+    message.error(response.msg)
+    formLoading.value = false
+    return
+  }
+  // 拼接提示语
+  const data = response.data.data;
+  console.log(data,'123');
+  let text = data.msg;
+  // let text = '上传成功数量:' + data.createUsernames.length + ';'
+  // for (let username of data.createUsernames) {
+  //   text += '< ' + username + ' >'
+  // }
+  // text += '更新成功数量:' + data.updateUsernames.length + ';'
+  // for (const username of data.updateUsernames) {
+  //   text += '< ' + username + ' >'
+  // }
+  // text += '更新失败数量:' + Object.keys(data.failureUsernames).length + ';'
+  // for (const username in data.failureUsernames) {
+  //   text += '< ' + username + ': ' + data.failureUsernames[username] + ' >'
+  // }
+  message.alert(text)
+  formLoading.value = false
+  dialogVisible.value = false
+  // 发送操作成功的事件
+  emits('success')
+}
+
+const submitZipSuccess = (response: any) => {
+  if (response.data.code !== 0) {
+    message.error(response.msg)
+    formLoading.value = false
+    return
+  }
+  // 处理上传成功的逻辑,例如解压压缩包,处理里面的文件等
+  message.success('压缩包上传成功')
+  formLoading.value = false
+  dialogVisible.value = false
+  // 发送操作成功的事件
+  emits('success')
+}
+
+/** 上传错误提示 */
+const submitFormError = (): void => {
+  message.error('上传失败,请您重新上传!')
+  formLoading.value = false
+}
+
+/** 重置表单 */
+const resetForm = async (): Promise<void> => {
+  // 重置上传状态和文件
+  formLoading.value = false
+  await nextTick()
+  uploadRef.value?.clearFiles()
+  uploadZipRef.value?.clearFiles()
+}
+
+/** 下载模板操作 */
+const importTemplate = async () => {
+  const res = await UserApi.getAttendanceTemplate()
+  console.log(res,'111');
+  download.excel(res, '用户导入模版.xls')
+}
+</script>

+ 73 - 82
src/views/system/studentAttendanceManage/studentFaceManage/index.vue

@@ -8,41 +8,24 @@
       :inline="true"
       label-width="68px"
     >
-      <el-form-item label="用户昵称" prop="studentName">
+      <el-form-item label="用户昵称" prop="nickName">
             <el-input
               placeholder="请输入用户昵称 "
-              v-model="queryParams.studentName"
+              v-model="queryParams.nickName"
               clearable
                @keyup.enter="handleQuery"
               class="!w-240px"
             />
       </el-form-item>
 
-      <!-- <el-form-item label="创建时间" prop="createTime">
+      <el-form-item label="导入时间" prop="createTime">
             <el-date-picker
               v-model="queryParams.createTime"
               value-format="YYYY-MM-DD HH:mm:ss"
-              type="datetimerange"
-              start-placeholder="开始日期"
-              end-placeholder="结束日期"
+              type="datetime"
               class="!w-240px"
             />
-      </el-form-item> -->
-
-      <!-- <el-form-item label="打卡状态 " prop="clockInStatus">
-        <el-select
-          v-model="queryParams.clockInStatus"
-          placeholder="请选择打卡状态 "
-          clearable
-          class="!w-240px"
-        >
-          <el-option :label="'正常'" :value="0" />
-          <el-option :label="'迟到'" :value="1" />
-          <el-option :label="'早退'" :value="2" />
-          <el-option :label="'缺勤'" :value="3" />
-          <el-option :label="'请假'" :value="4" />
-        </el-select>
-      </el-form-item> -->
+      </el-form-item>
 
       <el-form-item label="导入状态" prop="importStatus">
         <el-select
@@ -59,14 +42,14 @@
       <el-form-item>
         <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
         <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
-        <el-button
+        <!-- <el-button
           type="primary"
           plain
           @click="openForm('create')"
           v-hasPermi="['system:student-attendance:query']"
         >
           <Icon icon="ep:plus" class="mr-5px" /> 新增
-        </el-button>
+        </el-button> -->
         <el-button
           type="success"
           plain
@@ -92,17 +75,15 @@
   <ContentWrap>
     <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
       <el-table-column label="Id" align="center" prop="id" />
-      <!-- <el-table-column label="学生id" align="center" prop="studentId" /> -->
-      <el-table-column label="学生名称" align="center" prop="studentName" />
-      <!-- <el-table-column label="工作间id" align="center" prop="deptId" /> -->
-      <!-- <el-table-column label="日期" align="center" prop="date" /> -->
-      <!-- <el-table-column
-        label="打卡时间"
+      <el-table-column label="学生名称" align="center" prop="nickName" />
+      <el-table-column
+        label="导入时间"
         align="center"
-        prop="clockInTime"
+        prop="createTime"
         :formatter="dateFormatter"
         width="180px"
-      /> -->
+      />
+      
       <el-table-column label="导入状态" align="center" prop="importStatus" width="180px">
         <template #default="rowData">
           <!-- <span v-if="rowData.row.importStatus === 0">未导入</span>
@@ -117,53 +98,43 @@
             }}
           </span>
         </template>
-      </el-table-column>
-      <!-- <el-table-column label="打卡状态 " align="center" prop="clockInStatus" >
-        <template #default="rowData">
-          <span :class="getStatusClass(rowData.row.clockInStatus)">
-            {{
-              rowData.row.clockInStatus == 0
-               ? '正常'
-                : rowData.row.clockInStatus ==1
-               ? '迟到'
-                : rowData.row.clockInStatus == 2
-               ? '早退'
-                : rowData.row.clockInStatus == 3
-               ? '缺勤'
-                : rowData.row.clockInStatus == 4
-               ? '请假'
-                : '未知类型'
-            }}
-          </span>
-        </template>
-      </el-table-column> -->
-      <!-- <el-table-column
-        label="创建时间"
-        align="center"
-        prop="createTime"
-        :formatter="dateFormatter"
-        width="180px"
-      /> -->
+      </el-table-column> 
       <el-table-column label="备注原因" align="center" prop="remark" />
-      <el-table-column label="详情" align="center" prop="detail" />
+      <el-table-column label="详情" align="center" prop="photoUrl">
+        <template #default="scope">
+          <el-image
+            lazy
+            class="h-80px w-80px"
+            :src="scope.row.photoUrl"
+            :preview-src-list="[scope.row.photoUrl]"
+            preview-teleported
+            :zoom-rate="1.2"
+            :max-scale="7"
+            :min-scale="0.2"
+            :initial-index="4"
+            fit="cover"
+          />
+          <!-- <img :src="scope.row.photoUrl" alt="详情图片" style="width: 50px; height: 50px;" /> -->
+        </template>
+      </el-table-column>
       <el-table-column label="操作" align="center" min-width="120px">
         <template #default="scope">
           <el-button
             link
             type="primary"
             @click="openForm('update', scope.row.id)"
-            v-hasPermi="['system:student-attendance:query']"
+            v-hasPermi="['system:teacher-user-image:update']"
           >
             编辑
           </el-button>
-          <el-button
+          <!-- <el-button
             link
             type="danger"
             @click="handleDelete(scope.row.id)"
             v-hasPermi="['system:student-attendance:query']"
           >
             删除
-          </el-button>
+          </el-button> -->
         </template>
       </el-table-column>
     </el-table>
@@ -176,45 +147,41 @@
     />
   </ContentWrap>
 
-  <!-- 表单弹窗:添加/修改 -->
-  <StudentAttendanceForm ref="formRef" @success="getList" />
+  <!-- 表单弹窗:修改 -->
+  <StudentFaceForm ref="formRef" @success="getList" />
   <!-- 导出弹窗 -->
   <!--批量导入弹窗-->
-  <StudentFaceForm ref="importFormzipRef" @success="getList" />
+  <StudentFaceImport ref="importFormzipRef" @success="getList" />
 </template>
 
 <script setup lang="ts">
-// import { dateFormatter } from '@/utils/formatTime'
+import * as UserApi from '@/api/system/user'
+import { UserVO } from '@/api/system/user'
+import { dateFormatter } from '@/utils/formatTime'
 import download from '@/utils/download'
-import { StudentAttendanceApi, StudentAttendanceVO } from '@/api/system/studentAttendance'
-import StudentAttendanceForm from './StudentAttendanceForm.vue'
 import StudentFaceForm from './StudentFaceForm.vue'
+import StudentFaceImport from './StudentFaceImport.vue'
 import { useI18n } from 'vue-i18n'
 import { ref, reactive, onMounted } from 'vue'
 
 
 /** 学生考勤记录 列表 */
-defineOptions({ name: 'studentFaceManage' })
+defineOptions({ name: 'StudentFaceManage' })
 
 const message = useMessage() // 消息弹窗
 const { t } = useI18n() // 国际化
 
 const loading = ref(true) // 列表的加载中
-const list = ref<StudentAttendanceVO[]>([]) // 列表的数据
+const list = ref<UserVO[]>([]) // 列表的数据
 const total = ref(0) // 列表的总页数
 const queryParams = reactive({
   pageNo: 1,
   pageSize: 10,
-  studentId: undefined,
-  studentName: undefined,
-  deptId: undefined,
-  date: [],
-  clockInTime: [],
-  clockInTimeRange: [],
-  clockInStatus: undefined,
+  id: undefined,
+  nickName: undefined,
   createTime: [],
-  remark: undefined,
   importStatus: undefined,
+  remark: undefined,
 })
 const queryFormRef = ref() // 搜索的表单
 const exportLoading = ref(false) // 导出的加载中
@@ -223,9 +190,13 @@ const exportLoading = ref(false) // 导出的加载中
 const getList = async () => {
   loading.value = true
   try {
-    const data = await StudentAttendanceApi.getStudentAttendancePage(queryParams)
+    const data = await UserApi.getDeptStudentPage(queryParams)
     list.value = data.list
     total.value = data.total
+    console.log(data,'查询列表');
+    console.log(list.value,'列表数据');
+    
+    // await loadStudentData({}); 
   } finally {
     loading.value = false
   }
@@ -255,7 +226,7 @@ const handleDelete = async (id: number) => {
     // 删除的二次确认
     await message.delConfirm()
     // 发起删除
-    await StudentAttendanceApi.deleteStudentAttendance(id)
+    await UserApi.deleteUser(id)
     message.success(t('common.delSuccess'))
     // 刷新列表
     await getList()
@@ -269,7 +240,7 @@ const handleExport = async () => {
     await message.exportConfirm()
     // 发起导出
     exportLoading.value = true
-    const data = await StudentAttendanceApi.exportStudentAttendance(queryParams)
+    const data = await UserApi.exportUser(queryParams)
     download.excel(data, '学生考勤记录.xls')
   } catch {
   } finally {
@@ -295,6 +266,26 @@ const getStatusClass = (status) => {
   }
 };
 
+// 获取学生列表并处理 photoUrl
+// const loadStudentData = async (params) => {
+//   try {
+//     const response = await UserApi.getDeptStudentPage(params);
+//     const students = response.list;
+//     const studentPhotoMap = {};
+//     students.forEach(student => {
+//       studentPhotoMap[student.userNumber] = student.photoUrl;
+//     });
+//     // 更新考勤记录时,附加每条记录的 photoUrl
+//     list.value = list.value.map(attendance => ({
+//       ...attendance,
+//       photoUrl: studentPhotoMap[attendance.userNumber] // 根据学生 id 附加照片链接
+//     }));
+//     console.log('更新后的考勤记录:', list.value);
+//   } catch (error) {
+//     console.error('获取学生列表失败:', error);
+//   }
+// };
+
 /** 初始化 **/
 onMounted(() => {
   getList()

+ 284 - 0
src/views/system/studentSelfAttendance/index.vue

@@ -0,0 +1,284 @@
+<template>
+  <ContentWrap>
+    <!-- 搜索工作栏 -->
+    <el-form
+      class="-mb-15px"
+      :model="queryParams"
+      ref="queryFormRef"
+      :inline="true"
+      label-width="68px"
+    >
+      <el-form-item label="用户昵称" prop="studentName">
+            <el-input
+              placeholder="请输入用户昵称 "
+              v-model="queryParams.studentName"
+              clearable
+               @keyup.enter="handleQuery"
+              class="!w-240px"
+            />
+          </el-form-item>
+
+      <el-form-item label="创建时间" prop="createTime">
+            <el-date-picker
+              v-model="queryParams.createTime"
+              value-format="YYYY-MM-DD HH:mm:ss"
+              type="datetimerange"
+              start-placeholder="开始日期"
+              end-placeholder="结束日期"
+              class="!w-240px"
+            />
+          </el-form-item>
+
+      <el-form-item label="打卡状态 " prop="clockInStatus">
+        <el-select
+          v-model="queryParams.clockInStatus"
+          placeholder="请选择打卡状态 "
+          clearable
+          class="!w-240px"
+        >
+          <el-option :label="'正常'" :value="0" />
+          <el-option :label="'迟到'" :value="1" />
+          <el-option :label="'早退'" :value="2" />
+          <el-option :label="'缺勤'" :value="3" />
+          <el-option :label="'请假'" :value="4" />
+        </el-select>
+      </el-form-item>
+
+      <el-form-item>
+        <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
+        <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
+        <el-button
+          type="primary"
+          plain
+          @click="openForm('create')"
+          v-hasPermi="['system:student-attendance:create']"
+        >
+          <Icon icon="ep:plus" class="mr-5px" /> 新增
+        </el-button>
+        <el-button
+          type="success"
+          plain
+          @click="handleExport"
+          :loading="exportLoading"
+          v-hasPermi="['system:student-attendance:export']"
+        >
+          <Icon icon="ep:download" class="mr-5px" /> 导出
+        </el-button>
+      </el-form-item>
+    </el-form>
+  </ContentWrap>
+
+  <!-- 列表 -->
+  <ContentWrap>
+    <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
+      <el-table-column label="Id" align="center" prop="id" />
+      <!-- <el-table-column label="学生id" align="center" prop="studentId" /> -->
+      <el-table-column label="学生名称" align="center" prop="studentName" />
+      <!-- <el-table-column label="工作间id" align="center" prop="deptId" /> -->
+      <!-- <el-table-column label="日期" align="center" prop="date" /> -->
+      <el-table-column
+        label="打卡时间"
+        align="center"
+        prop="clockInTime"
+        :formatter="dateFormatter"
+        width="180px"
+      />
+      <el-table-column label="打卡状态 " align="center" prop="clockInStatus" >
+        <template #default="rowData">
+          <span :class="getStatusClass(rowData.row.clockInStatus)">
+            {{
+              rowData.row.clockInStatus == 0
+               ? '正常'
+                : rowData.row.clockInStatus ==1
+               ? '迟到'
+                : rowData.row.clockInStatus == 2
+               ? '早退'
+                : rowData.row.clockInStatus == 3
+               ? '缺勤'
+                : rowData.row.clockInStatus == 4
+               ? '请假'
+                : '未知类型'
+            }}
+          </span>
+        </template>
+      </el-table-column>
+      <!-- <el-table-column
+        label="创建时间"
+        align="center"
+        prop="createTime"
+        :formatter="dateFormatter"
+        width="180px"
+      /> -->
+      <el-table-column label="备注原因" align="center" prop="remark" />
+      <el-table-column label="操作" align="center" min-width="120px">
+        <template #default="scope">
+          <el-button
+            link
+            type="primary"
+            @click="openForm('update', scope.row.id)"
+            v-hasPermi="['system:student-attendance:update']"
+          >
+            编辑
+          </el-button>
+          <el-button
+            link
+            type="danger"
+            @click="handleDelete(scope.row.id)"
+            v-hasPermi="['system:student-attendance:delete']"
+          >
+            删除
+          </el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    <!-- 分页 -->
+    <Pagination
+      :total="total"
+      v-model:page="queryParams.pageNo"
+      v-model:limit="queryParams.pageSize"
+      @pagination="getList"
+    />
+  </ContentWrap>
+
+  <!-- 表单弹窗:添加/修改 -->
+  <StudentAttendanceForm ref="formRef" @success="getList" />
+</template>
+
+<script setup lang="ts">
+import { dateFormatter } from '@/utils/formatTime'
+import download from '@/utils/download'
+import { StudentAttendanceApi, StudentAttendanceVO } from '@/api/system/studentAttendance'
+import StudentAttendanceForm from './StudentAttendanceForm.vue'
+
+/** 学生考勤记录 列表 */
+defineOptions({ name: 'StudentAttendance' })
+
+const message = useMessage() // 消息弹窗
+const { t } = useI18n() // 国际化
+
+const loading = ref(true) // 列表的加载中
+const list = ref<StudentAttendanceVO[]>([]) // 列表的数据
+const total = ref(0) // 列表的总页数
+const queryParams = reactive({
+  pageNo: 1,
+  pageSize: 10,
+  studentId: undefined,
+  studentName: undefined,
+  deptId: undefined,
+  date: [],
+  clockInTime: [],
+  clockInTimeRange: [],
+  clockInStatus: undefined,
+  createTime: [],
+  remark: undefined,
+})
+const queryFormRef = ref() // 搜索的表单
+const exportLoading = ref(false) // 导出的加载中
+
+/** 查询列表 */
+const getList = async () => {
+  loading.value = true
+  try {
+    const data = await StudentAttendanceApi.getStudentAttendancePage(queryParams)
+    list.value = data.list
+    total.value = data.total
+  } finally {
+    loading.value = false
+  }
+}
+
+/** 搜索按钮操作 */
+const handleQuery = () => {
+  queryParams.pageNo = 1
+  getList()
+}
+
+/** 重置按钮操作 */
+const resetQuery = () => {
+  queryFormRef.value.resetFields()
+  handleQuery()
+}
+
+/** 添加/修改操作 */
+const formRef = ref()
+const openForm = (type: string, id?: number) => {
+  formRef.value.open(type, id)
+}
+
+/** 删除按钮操作 */
+const handleDelete = async (id: number) => {
+  try {
+    // 删除的二次确认
+    await message.delConfirm()
+    // 发起删除
+    await StudentAttendanceApi.deleteStudentAttendance(id)
+    message.success(t('common.delSuccess'))
+    // 刷新列表
+    await getList()
+  } catch {}
+}
+
+/** 导出按钮操作 */
+const handleExport = async () => {
+  try {
+    // 导出的二次确认
+    await message.exportConfirm()
+    // 发起导出
+    exportLoading.value = true
+    const data = await StudentAttendanceApi.exportStudentAttendance(queryParams)
+    download.excel(data, '学生考勤记录.xls')
+  } catch {
+  } finally {
+    exportLoading.value = false
+  }
+}
+
+// 状态颜色显示
+const getStatusClass = (status) => {
+  switch (status) {
+    case "0":
+      return 'status-normal';
+    case "1":
+      return 'status-late';
+    case "2":
+      return 'status-early';
+    case "3":
+      return 'status-absent';
+    case "4":
+      return 'status-leave';
+    default:
+      return 'status-unknown';
+  }
+};
+
+/** 初始化 **/
+onMounted(() => {
+  getList()
+})
+</script>
+
+<style scoped>
+.status-normal {
+  color: green;
+}
+
+.status-late {
+  color: orange;
+}
+
+.status-early {
+  color: blue;
+}
+
+.status-absent {
+  color: red;
+}
+
+.status-leave {
+  color: purple;
+}
+
+.status-unknown {
+  color: gray;
+}
+</style>

+ 3 - 1
src/views/system/workroomCollege/user/UserImportForm.vue

@@ -80,7 +80,7 @@ const submitForm = async () => {
   }
   formLoading.value = true
   uploadRef.value!.submit()
-  console.log('67890',uploadHeaders.value);
+  // console.log('67890',uploadHeaders.value);
 }
 
 /** 文件上传成功 */
@@ -91,8 +91,10 @@ const submitFormSuccess = (response: any) => {
     formLoading.value = false
     return
   }
+
   // 拼接提示语
   const data = response.data
+  console.log(data,'data');
   let text = '上传成功数量:' + data.createUsernames.length + ';'
   for (let username of data.createUsernames) {
     text += '< ' + username + ' >'

+ 34 - 27
src/views/system/workroomCollege/user/UserImportFormzip.vue

@@ -81,11 +81,9 @@ const uploadRef = ref()
 const uploadZipRef = ref()
 const importUrl =
   import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL + '/md/acs/import-data'
-
 const uploadHeaders = ref() // 上传 Header 头
 const fileList = ref([]) // 文件列表
 const updateSupport = ref(0) // 是否更新已经存在的用户数据
-
 const zipList = ref([]) // 压缩文件列表
 
 
@@ -105,15 +103,14 @@ const submitForm = async () => {
   //   message.error('请上传文件')
   //   return
   // }
-
   // if (zipList.value.length === 0) {
   //   message.error('请上传压缩包')
   //   return
   // }
-  if (fileList.value.length == 0 && zipList.value.length === 0) {
-    message.error('请上传文件或压缩包')
-    return
-  }
+  // if (fileList.value.length == 0 && zipList.value.length === 0) {
+  //   message.error('请上传文件或压缩包')
+  //   return
+  // }
   const formData = new FormData();
 
   if (fileList.value.length > 0) {
@@ -124,16 +121,25 @@ const submitForm = async () => {
     formData.append('imageFile', zipList.value[0].raw); // 确保是 .raw
   }
 
-  formData.append('updateSupport', updateSupport.value);
+  formData.append('updateSupport',updateSupport.value.toString());
 
-  await axios.post(importUrl, formData, {
+  let response = await axios.post(importUrl, formData, {
     headers: {
       'Content-Type': 'multipart/form-data',
       Authorization: 'Bearer ' + getAccessToken(),
       'tenant-id': getTenantId()
     }
   });
-
+  console.log(response,'response');
+  submitFormSuccess(response)
+  // // 提交请求
+  // uploadHeaders.value = {
+  //   Authorization: 'Bearer ' + getAccessToken(),
+  //   'tenant-id': getTenantId()
+  // }
+  // formLoading.value = true
+  // uploadRef.value!.submit()
+  // uploadZipRef.value!.submit()
 }
 
 
@@ -141,27 +147,28 @@ const submitForm = async () => {
 /** 文件上传成功 */
 const emits = defineEmits(['success'])
 const submitFormSuccess = (response: any) => {
-  if (response.code !== 0) {
+  if (response.data.code !== 0) {
+    console.log(response.data.code,'code');   
     message.error(response.msg)
     formLoading.value = false
-    console.log(response.code,'12345');
     return
   }
   // 拼接提示语
-  const data = response.data;
-  console.log(response.data,'123');
-  let text = '上传成功数量:' + data.createUsernames.length + ';'
-  for (let username of data.createUsernames) {
-    text += '< ' + username + ' >'
-  }
-  text += '更新成功数量:' + data.updateUsernames.length + ';'
-  for (const username of data.updateUsernames) {
-    text += '< ' + username + ' >'
-  }
-  text += '更新失败数量:' + Object.keys(data.failureUsernames).length + ';'
-  for (const username in data.failureUsernames) {
-    text += '< ' + username + ': ' + data.failureUsernames[username] + ' >'
-  }
+  const data = response.data.data;
+  console.log(data,'data');
+  let text = data;
+  // let text = '上传成功数量:' + data.createUsernames.length + ';'
+  // for (let username of data.createUsernames) {
+  //   text += '< ' + username + ' >'
+  // }
+  // text += '更新成功数量:' + data.updateUsernames.length + ';'
+  // for (const username of data.updateUsernames) {
+  //   text += '< ' + username + ' >'
+  // }
+  // text += '更新失败数量:' + Object.keys(data.failureUsernames).length + ';'
+  // for (const username in data.failureUsernames) {
+  //   text += '< ' + username + ': ' + data.failureUsernames[username] + ' >'
+  // }
   message.alert(text)
   formLoading.value = false
   dialogVisible.value = false
@@ -170,7 +177,7 @@ const submitFormSuccess = (response: any) => {
 }
 
 const submitZipSuccess = (response: any) => {
-  if (response.code !== 0) {
+  if (response.data.code !== 0) {
     message.error(response.msg)
     formLoading.value = false
     return