47 2 weeks ago
parent
commit
6fe5ac4b75

+ 11 - 0
src/api/system/studentSelectionProject/index.ts

@@ -47,4 +47,15 @@ export const studentSelectionProjectApi = {
   getAllProject: async () => {
     return await request.get({ url: `/system/student-selection-project/getAllProject`})
   },
+
+  // 获取当前项目的导师 
+  getProjectSupervisors: async (projectId: number) => {
+    return await request.get({ url: `/system/student-selection-project/getProjectSupervisors`, params: { projectId: projectId }})
+  },
+
+  // /withdrawRecord
+  withdrawRecord: async (id: number) => {
+    return await request.delete({ url: `/system/student-selection-project/withdrawRecord?id=` + id })
+  },
+
 }

BIN
src/assets/imgs/GLUT.png


+ 0 - 50
src/views/Home/Index.vue

@@ -1,53 +1,3 @@
-
-  <!-- <div>
-                                                                  <el-card shadow="never">
-                                                                    <el-skeleton :loading="loading" animated>
-                                                                      <el-row :gutter="16" justify="space-between">
-                                                                        <el-col :xl="12" :lg="12" :md="12" :sm="24" :xs="24">
-                                                                          <div class="flex items-center">
-                                                                            <el-avatar :src="avatar" :size="70" class="mr-16px">
-                                                                              <img src="@/assets/imgs/avatar.gif" alt="" />
-                                                                            </el-avatar>
-                                                                            <div>
-                                                                              <div class="text-20px">
-                                                                                {{ t('workplace.welcome') }} {{ username }} {{ t('workplace.happyDay') }}
-                                                                              </div>
-                                                                              <div class="mt-10px text-14px text-gray-500">
-                                                                                {{ t('workplace.toady') }},20℃ - 32℃!
-                                                                              </div>
-                                                                            </div>
-                                                                          </div>
-                                                                        </el-col>
-                                                                        <el-col :xl="12" :lg="12" :md="12" :sm="24" :xs="24">
-                                                                          <div class="h-70px flex items-center justify-end lt-sm:mt-10px">
-                                                                            <div class="px-8px text-right">
-                                                                              <div class="mb-16px text-14px text-gray-400">{{ t('workplace.project') }}</div>
-                                                                              <CountTo class="text-20px" :start-val="0" :end-val="totalSate.project" :duration="2600" />
-                                                                            </div>
-                                                                            <el-divider direction="vertical" />
-                                                                            <div class="px-8px text-right">
-                                                                              <div class="mb-16px text-14px text-gray-400">{{ t('workplace.toDo') }}</div>
-                                                                              <CountTo class="text-20px" :start-val="0" :end-val="totalSate.todo" :duration="2600" />
-                                                                            </div>
-                                                                            <el-divider direction="vertical" border-style="dashed" />
-                                                                            <div class="px-8px text-right">
-                                                                              <div class="mb-16px text-14px text-gray-400">{{ t('workplace.access') }}</div>
-                                                                              <CountTo class="text-20px" :start-val="0" :end-val="totalSate.access" :duration="2600" />
-                                                                            </div>
-                                                                          </div>
-                                                                        </el-col>
-                                                                      </el-row>
-                                                                    </el-skeleton>
-                                                                  </el-card>
-                                                                </div> -->
-  <!-- 日期
-                                                                                                  <div class="mt-16px text-12px text-gray-400">
-                                                                                                    {{ formatTime(item.date, 'yyyy-MM-dd') }}
-                                                                                                  </div> -->
-  <!-- 更多<el-link type="primary" :underline="false" href="https://github.com/yudaocode" target="_blank"> {{
-                                                    t('action.more') }}
-                                                  </el-link> -->
-
 <template>
   <el-skeleton :loading="loading" animated>
     <el-row :gutter="8">

+ 91 - 46
src/views/system/Home/Index.vue

@@ -13,20 +13,21 @@
 
             <el-row style="flex-wrap: wrap; ">
               <el-col
-v-for="(item, index) in projects" :key="`card-${index}`" :xs="24" :sm="8"
-                      :md="8" :lg="8" :xl="8">
+                v-for="(item, index) in projects" :key="`card-${index}`" :xs="24" :sm="8"
+                :md="8" :lg="8" :xl="8">
                 <el-card
-class="mr-10px mt-5px  ml-10px "
-                         :style="{ backgroundColor: item.cardBgColor }">
+                  class="mr-10px mt-5px  ml-10px "
+                  :style="{ backgroundColor: item.cardBgColor }">
                   <div class="flex items-center h-120px ">
                     <!-- <Icon :icon="item.icon" :size="25" class="mr-8px" /> -->
                     <Icon
-:icon="item.icon" :size="80"
-                          :style="{ backgroundColor: item.iconBgColor, color: item. iconColor, borderRadius: '50%' }"
-                          class="circle-icon"/>
+                      :icon="item.icon" :size="80"
+                      :style="{ backgroundColor: item.iconBgColor, color: item. iconColor, borderRadius: '50%' }"
+                      class="circle-icon"/>
                     <span class="text-30px c-black ">{{ item.name }}</span>
                   </div>
-                  <div class="mb-18px text-40px c-#233B59FF ml-20px text-center">{{
+                  <div class="mb-18px text-40px c-#233B59FF ml-20px text-center">
+                    {{
                       t(item.message)
                     }}
                   </div>
@@ -309,6 +310,7 @@ v-if="list1.length == 0"
 
     </el-row>
   </el-skeleton>
+  <teacher ref="teacherFormRef" @success="getUserInfo"/>
 </template>
 
 <script lang="ts" setup>
@@ -325,6 +327,9 @@ import * as UserApi from '@/api/system/user'
 import * as  DeptApi from '@/api/system/dept'
 import {StudentAttendanceApi} from '@/api/system/studentAttendance'
 import * as echarts from 'echarts';
+import {PopDo,getIsPop} from '@/api/system/user/pop';
+import { getUserProfile, ProfileVO } from '@/api/system/user/profile';
+import teacher from '../userDetail/teacher.vue';
 
 defineOptions({name: 'SystemHome'})
 
@@ -336,6 +341,39 @@ const avatar = userStore.getUser.avatar
 const username = userStore.getUser.nickname
 const chartRef = ref(null)
 const chartInstance = ref(null)
+// 教师是否弹窗
+const teacherFormRef = ref();
+const isPop  = ref();
+const userInfo = ref({} as ProfileVO);
+const getPopDataFunction = async () => {
+  console.log('getPopDataFunction 被调用');
+  try {
+    isPop.value = await getIsPop();
+    console.log(isPop.value, '弹窗值');
+  } catch (error) {
+    console.error('获取弹窗状态失败:', error);
+  }
+};
+
+const teacherForm = () => {
+  if (teacherFormRef.value) {
+    teacherFormRef.value.open('update', userInfo.value.id);
+  } else {
+    console.error('Teacher form component is not mounted yet!');
+  }
+};
+const getUserInfo = async () => {
+  try {
+    loading.value = true;
+    const users = await getUserProfile();
+    userInfo.value = users;
+    // console.log('获取用户信息成功:', userInfo.value);
+  } catch (error) {
+    console.error('获取用户信息失败:', error);
+  } finally {
+    loading.value = false;
+  }
+};
 
 /*基本信息*/
 const detail = reactive({
@@ -345,7 +383,7 @@ const detail = reactive({
 })
 const getDetail = async () => {
   const data = await UserApi.getDetail()
-  console.log("基本信息", data);
+  // console.log("基本信息", data);
   detail.deptNum = data.deptNum
   detail.teacherNum = data.teacherNum
   detail.studentNum = data.studentNum
@@ -396,7 +434,7 @@ let totalSate = reactive<WorkplaceTotal>({
 })
 const getCount = async () => {
   const data = await StudentAttendanceApi.getDayAttendance()
-  console.log("实时出勤统计", data);
+  // console.log("实时出勤统计", data);
   totalSate = Object.assign(totalSate, data)
 }
 
@@ -407,7 +445,7 @@ const getCount = async () => {
 let pieOptionsData = reactive<EChartsOption>(pieOptions) as EChartsOption
 const getGraduateCount = async () => {
   const data = await UserApi.getGraduateCount()
-  console.log("毕业达成统计", data);
+  // console.log("毕业达成统计", data);
   const studentNum = data.studentNum;
   const graduateNum = data.graduateNum;
   const options = {
@@ -514,30 +552,11 @@ const getGraduateCount = async () => {
     chartInstance.value.setOption(pieOptionsData, true);
   }
 };
-  //图表自动适应容器尺寸变化
-onMounted(() => {
-  nextTick(()=>{
-    if (chartRef.value) {
-      chartInstance.value = echarts.init(chartRef.value);
-      chartInstance.value.setOption(pieOptionsData);
-
-      window.addEventListener('resize', resizeChart);
-      resizeChart();
-    }
-  })
-});
-
-onUnmounted(() => {
-  if (chartInstance.value) {
-    window.removeEventListener('resize', resizeChart);
-    chartInstance.value.dispose();
-  }
-});
 
 const resizeChart = () => {
-  console.log(chartRef.value,"eee")
+  // console.log(chartRef.value,"eee")
   if (chartInstance.value && chartRef.value) {
-    console.log(chartRef.value,"eee")
+    // console.log(chartRef.value,"eee")
     const width = chartRef.value.offsetWidth;
     // 根据容器宽度计算内外径比例
     const innerRadius = width > 600 ? '50%' : '20%';
@@ -562,7 +581,7 @@ barOptionsData.textStyle = {
 };
 const getWeekend = async () => {
   const data = await StudentAttendanceApi.getWeekendAttendance();
-  console.log("周出勤情况", data);
+  // console.log("周出勤情况", data);
   const normalData = data.dailyNormalList
   const errorData = data.dailyErrorList;
   const excuseData = data.dailyExcuseList;
@@ -575,7 +594,7 @@ const getWeekend = async () => {
 let list2 = reactive([]);
 const getStudentAttendanceError = async () => {
   const data = await StudentAttendanceApi.getDayStudentErrorAttendance()
-  console.log("缺勤列表", data);
+  // console.log("缺勤列表", data);
   list2.splice(0, list2.length, ...data);
 }
 const class2Options = reactive({
@@ -589,7 +608,7 @@ const class2Options = reactive({
 const list = reactive([]);
 const getStudentAttendance = async () => {
   const data = await StudentAttendanceApi.getDayStudentAttendance()
-  console.log("打卡列表", data);
+  // console.log("打卡列表", data);
   list.splice(0, list.length, ...data);
 }
 const classOptions = reactive({
@@ -603,7 +622,7 @@ const classOptions = reactive({
 const list1 = reactive([]);
 const getGraduationSource = async () => {
   const data = await DeptApi.getGraduationSource()
-  console.log("毕业条件达成率", data);
+  // console.log("毕业条件达成率", data);
   list1.splice(0, list1.length, ...data);
 }
 const list1Options = reactive({
@@ -612,16 +631,42 @@ const list1Options = reactive({
   direction: 1,//方向: 0 往下 1 往上 2 向左 3 向右。
 });
 
-onMounted(() => {
-  getDetail()
-  getWeekend()
-  getProject()
-  getCount()
-  getStudentAttendanceError()
-  getStudentAttendance()
-  getGraduationSource()
-  getGraduateCount()
-})
+  //图表自动适应容器尺寸变化
+  onMounted(async () => {
+    getDetail()
+    getWeekend()
+    getProject()
+    getCount()
+    getStudentAttendanceError()
+    getStudentAttendance()
+    getGraduationSource()
+    getGraduateCount()
+    // 别删我,球球了
+    await getUserInfo()
+    if (userInfo.value.userType === '3' || userInfo.value.userType === '5') {
+      await getPopDataFunction();
+      if (isPop.value) {
+        await nextTick();
+        teacherForm();
+      }
+    }
+    nextTick(()=>{
+      if (chartRef.value) {
+        chartInstance.value = echarts.init(chartRef.value);
+        chartInstance.value.setOption(pieOptionsData);
+
+        window.addEventListener('resize', resizeChart);
+        resizeChart();
+      }
+    })
+});
+
+onUnmounted(() => {
+  if (chartInstance.value) {
+    window.removeEventListener('resize', resizeChart);
+    chartInstance.value.dispose();
+  }
+});
 
 const getAllApi = async () => {
   await Promise.all([

+ 5 - 5
src/views/system/selfAchievement/index.vue

@@ -135,11 +135,11 @@
         </template>
       </el-table-column>
 
-          <el-table-column label="是否达成毕业条件" align="center" prop="isGraduate">
-            <template #default="scope">
-              <dict-tag :type="DICT_TYPE.SYSTEM_STUDENT_GRADUATE_STATUS" :value="scope.row.isGraduate" />  
-            </template>
-          </el-table-column>
+      <el-table-column label="是否达成毕业条件" align="center" prop="isGraduate">
+        <template #default="scope">
+          <dict-tag :type="DICT_TYPE.SYSTEM_STUDENT_GRADUATE_STATUS" :value="scope.row.isGraduate" />  
+        </template>
+      </el-table-column>
 
       <!-- <el-table-column
         label="创建时间"

+ 19 - 19
src/views/system/studentSelectSupervisorRecord/index.vue

@@ -190,7 +190,7 @@
             退回
           </el-button>
 
-          <el-button
+          <!-- <el-button
             link
             type="primary"
             @click="handelPrint(scope.row.id)"
@@ -198,25 +198,25 @@
             v-if="userInfo?.userType === '4' &&scope.row.selectType ==2"
           >
             信息
+          </el-button> -->
+
+          <!-- <el-button
+           link
+           type="primary"
+           @click="openForm('update', scope.row.id)"
+           v-hasPermi="['system:student-select-supervisor-record:update']"
+          >
+           编辑
           </el-button>
 
-<!--          <el-button-->
-<!--            link-->
-<!--            type="primary"-->
-<!--            @click="openForm('update', scope.row.id)"-->
-<!--            v-hasPermi="['system:student-select-supervisor-record:update']"-->
-<!--          >-->
-<!--            编辑-->
-<!--          </el-button>-->
-
-<!--          <el-button-->
-<!--            link-->
-<!--            type="danger"-->
-<!--            @click="handleDelete(scope.row.id)"-->
-<!--            v-hasPermi="['system:student-select-supervisor-record:delete']"-->
-<!--          >-->
-<!--            删除-->
-<!--          </el-button>-->
+          <el-button
+           link
+           type="danger"
+           @click="handleDelete(scope.row.id)"
+           v-hasPermi="['system:student-select-supervisor-record:delete']"
+          >
+           删除
+          </el-button> -->
         </template>
       </el-table-column>
     </el-table>
@@ -379,7 +379,7 @@ const agreeOpenForm = (type: string, projectId?: number,supervisorId? :number,id
 
 const handelRefuse = async (id:number) => {
   try {
-    await message.confirm()
+    await message.confirm("是否确定退回申请?")
     formData.value.id=id
     const data =formData.value as unknown as studentSelectSupervisorRecordVO
     await studentSelectSupervisorRecordApi.refuseStudentSelectSupervisorRecord(data)

+ 48 - 17
src/views/system/studentSelectSupervisorRecord/record.vue

@@ -1,13 +1,14 @@
 <template>
    <!-- <el-loading :loading="isLoading" text="加载中..."> -->
       <!-- 搜索工作栏 -->
-      <ContentWrap v-if="userInfo.userType==='4'">
+      <ContentWrap v-if="userInfo.userType ==='4' || userInfo.userType === '1'">
         <el-form
           class="-mb-15px"
           :model="queryParams"
           ref="queryFormRef"
           :inline="true"
           label-width="100px"
+          v-if="userInfo.userType==='4'"
         >
           <el-form-item label="参与导师" prop="supervisorIds">
             <el-select
@@ -103,6 +104,7 @@
             <el-button type="primary" @click="exportWordTemplate" :loading="exportLoading">批量导出互选表</el-button>
           </el-form-item>
         </el-form>
+        <el-button type="primary" @click="exportWordTemplate" :loading="exportLoading" v-if="userInfo.userType==='1'">导出互选表</el-button>
       </ContentWrap>
     
       <ContentWrap v-if="userInfo.userType==='1' ||userInfo.userType==='4'" >
@@ -162,24 +164,34 @@
             :formatter="dateFormatter"
             width="180px"
           />
-          <el-table-column label="操作" align="center" min-width="120px"   v-if="userInfo.userType==='4'">
+          <el-table-column label="操作" align="center" min-width="120px"   v-if="userInfo.userType==='4' || userInfo.userType==='1'">
             <template #default="scope">
               <el-button
                 link
                 type="primary"
                 @click="openForm('update',  scope.row.projectId,scope.row.supervisorId,scope.row.id,scope.row.studentId)"
                 v-hasPermi="['system:student-select-supervisor-record:update']"
+                v-if="userInfo.userType==='4'"
               >
                 志愿编辑
               </el-button>
               <el-button
                 link
                 type="primary"
-                v-if="scope.row.selectType === 2"
+                v-if="scope.row.selectType === 2 && userInfo.userType==='4'"
                 @click="openForm('end',  scope.row.projectId,scope.row.supervisorId,scope.row.id,scope.row.studentId)"
               >
                 详情
               </el-button>
+              <el-button
+                link
+                type="primary"
+                @click="handelWithdraw( scope.row.supervisorId)"
+                v-hasPermi="['system:student-select-supervisor-record:withdraw']"
+                v-if="userInfo?.userType === '1'&& scope.row.selectType === 1"
+              >
+                撤回
+              </el-button>
             </template>
           </el-table-column>
       </el-table>
@@ -273,6 +285,17 @@ const openForm = (type: string, projectId?: number,supervisorId? :number,id?:num
   formRef.value.open(type, projectId,supervisorId,id,studentId)
 }
 
+const handelWithdraw = async (supervisorId:number) => {
+  try {
+    await message.confirm('是否确定撤回申请?')
+    recordData.value.supervisorId = supervisorId
+    const data =recordData.value as unknown as studentSelectSupervisorRecordVO
+    await studentSelectSupervisorRecordApi.withdrawStudentSelectSupervisorRecord(data)
+    message.success("撤回了申请")
+    await getList()
+  } catch {}
+}
+
 // 添加一个响应式的变量来保存选中的行
 const selectedRows = ref([]);
 const selectableRows = (row) => {
@@ -294,22 +317,30 @@ const exportWordTemplate = async () => {
     message.error('请先选择需要导出的数据!');
     return;
   }
+  const formatDate = (date) => {
+    if (!date) return '无'; // 处理不存在日期的情况
+    const d = new Date(date);
+    const year = String(d.getFullYear()).slice(-2);
+    const month = String(d.getMonth() + 1).padStart(2, '0');
+    const day = String(d.getDate()).padStart(2, '0');
+    return `${year}.${month}.${day}`;
+  };
   const dataList = await Promise.all(selectedRows.value.map(async (row) => {
     // 获取每一行的详细信息
     const selectionBook = await selectionBookApi.getSelectionBook(row.id);
     console.log(selectionBook);
     return {
-      studentName: selectionBook.studentName,
-      userNumber: selectionBook.studentNumber,
-      major: selectionBook.major,
-      mobile: selectionBook.studentMobile,
-      nickname: selectionBook.supervisor,
-      title: selectionBook.supervisor,
-      studentAchievementRequirement: selectionBook.studentAchievementRequirement,
-      studentSignDate: new Date(selectionBook.studentSignDate).toLocaleDateString(),
-      supervisorSignDate: new Date(selectionBook.supervisorSignDate).toLocaleDateString(),
-      supervisorSignature: "/logo.png",
-      studentSignature: "/logo.png"
+      studentName: selectionBook.studentName || '无',
+      userNumber: selectionBook.studentNumber || '无',
+      major: selectionBook.major || '无',
+      mobile: selectionBook.studentMobile || '无',
+      nickname: selectionBook.supervisor || '无',
+      title: selectionBook.supervisor || '无',
+      studentAchievementRequirement: selectionBook.studentAchievementRequirement || '无',
+      studentSignDate: formatDate(selectionBook.studentSignDate) || '无',
+      supervisorSignDate: formatDate(selectionBook.supervisorSignDate) || '无',
+      supervisorSignature: selectionBook.supervisorSignature || '/none.png',
+      studentSignature: selectionBook.supervisorSignature || '/none.png'
     };
   }));
   console.log("导出的数据对象:", dataList);
@@ -329,16 +360,16 @@ const exportWordTemplate = async () => {
       // 使用 await 确保每个 Word 文件生成并下载前才继续执行
       await _word.initWord((_this) => {
         const out = _this.addDownloadFile(); // 获取文件的 Blob
-        console.log(`document_${i + 1}.docx 文件已生成`);
+        console.log(`${data.studentName}_.docx 文件已生成`);
 
         // 将生成的 .docx 文件添加到 zip 压缩包中
-        zip.file(`document_${i + 1}.docx`, out);
+        zip.file(`${data.studentName}_.docx`, out);
       });
     }
 
     // 生成 zip 文件并保存
     const zipBlob = await zip.generateAsync({ type: 'blob' });
-    saveAs(zipBlob, "导出文件.zip");
+    saveAs(zipBlob, "师生互选表.zip");
   } catch (error) {
     console.error('导出文档失败:', error);
   }

+ 36 - 22
src/views/system/studentSelectSupervisorRecord/studentSelectSupervisorRecordForm.vue

@@ -122,7 +122,7 @@
       <div class="section" v-if="userInfo.userType==='4' && formType === 'update'">
         <el-form-item label="参与导师" prop="supervisorId">
           <el-select
-            v-model="supervisors.supervisorId"
+            v-model="formData.supervisorId"
             placeholder="请选择参与导师"
             clearable
             filterable
@@ -130,7 +130,7 @@
             @change="handleSupervisorChange"
           >
             <el-option
-              v-for="supervisor in supervisors"
+              v-for="supervisor in supervisorsin"
               :key="supervisor.id"
               :label="supervisor.nickname"
               :value="supervisor.id"
@@ -155,6 +155,7 @@ import { defineOptions, defineExpose, ref, reactive, nextTick, onMounted, comput
 import { getUserProfile, ProfileVO } from '@/api/system/user/profile'
 import {supervisorSelectionSettingApi} from '@/api/system/supervisorSelectionSetting'
 import { htmlPdf } from "@/utils/htmlToPDF.js"  
+import { studentSelectionProjectApi, studentSelectionProjectVO } from '@/api/system/studentSelectionProject'
 
 
 /** 师生互选记录 表单 */
@@ -245,9 +246,8 @@ const getSupervisor= async () => {
 }
 
 const showPrintButton = ref(false); // 控制打印按钮的显示
-
 /** 打开弹窗 */
-const open = async (type: string, projectId?: number ,supervisorId?:number, id?:number,studentId?:number) => {
+const open = async (type: string, projectId?: number, supervisorId?:number, id?:number, studentId?:number) => {
   dialogVisible.value = true;
   if (type === 'create'){
     dialogTitle.value = '志愿填报'
@@ -308,28 +308,30 @@ const open = async (type: string, projectId?: number ,supervisorId?:number, id?:
       formLoading.value = true
       try {
         formData.value = await studentSelectSupervisorRecordApi.getStudentSelectSupervisorRecord(id)
+        // console.log(formData.value,'formData.value');
+        
       } finally {
         formLoading.value = false
       }
     }
-    if (supervisorId) {
-      formLoading.value = true
-      try {
-        console.log(supervisorId)
-        console.log(projectId)
-        const supervisor = await supervisorSelectionSettingApi.getSupervisorInfo(supervisorId,projectId);
-        //需要传的
-        formData.value.supervisorId =supervisorId;
-        formData.value.projectId = projectId;
-        //显示的
-        supervisorData.value.nickname = supervisor.supervisorName;
-        supervisorData.value.title =supervisor.title;
-        supervisorData.value.studentAchievementRequirement = supervisor.studentAchievementRequirement;
-        supervisorData.value.major = supervisor.major;
-      } finally {
-        formLoading.value = false
-      }
-    }
+    // if (supervisorId) {
+    //   formLoading.value = true
+    //   try {
+    //     console.log(supervisorId)
+    //     console.log(projectId)
+    //     const supervisor = await supervisorSelectionSettingApi.getSupervisorInfo(supervisorId,projectId);
+    //     //需要传的
+    //     formData.value.supervisorId =supervisorId;
+    //     formData.value.projectId = projectId;
+    //     //显示的
+    //     supervisorData.value.nickname = supervisor.supervisorName;
+    //     supervisorData.value.title =supervisor.title;
+    //     supervisorData.value.studentAchievementRequirement = supervisor.studentAchievementRequirement;
+    //     supervisorData.value.major = supervisor.major;
+    //   } finally {
+    //     formLoading.value = false
+    //   }
+    // }
     if (studentId) {
       formLoading.value = true
       try {
@@ -350,6 +352,9 @@ const open = async (type: string, projectId?: number ,supervisorId?:number, id?:
         formLoading.value = false
       }
     }
+    
+    await getProjectSupervisors(projectId)
+    
   }
   if (type === 'end'){
     dialogTitle.value = '详情'
@@ -396,6 +401,15 @@ const open = async (type: string, projectId?: number ,supervisorId?:number, id?:
   }
 }
 
+// 获取当前项目的导师
+const supervisorsin = ref()
+const getProjectSupervisors = async (projectId: number) => {
+  console.log('请求的项目ID:', projectId);
+  const result = await studentSelectionProjectApi.getProjectSupervisors(projectId);
+  console.log(result,'获取到的导师信息');
+  supervisorsin.value = result
+}
+
 const handleExport = (row) => {
   var fileName = '师生互选表';
   const formElement = document.querySelector('.form-container'); 

+ 13 - 11
src/views/system/studentSelectionProject/index.vue

@@ -4,12 +4,12 @@
     class="switch-form"
     :inline="true"
     label-width="200px"
+    v-if="userInfo?.userType === '4' "
   >
-    <el-form-item label="是否开启导师弹窗"  v-if="userInfo?.userType === '4' ">
+    <el-form-item label="是否开启导师弹窗">
       <el-switch v-model="popData.isSupervisor" :active-value="1" :inactive-value="0" @change="(val) => handleSwitchChange(popData.id, 'isSupervisor', val)" />
     </el-form-item>
-
-    <el-form-item label="是否开启学生弹窗"  v-if="userInfo?.userType === '4'">
+    <el-form-item label="是否开启学生弹窗">
       <el-switch v-model="popData.isStudent" :active-value="1" :inactive-value="0" @change="(val) => handleSwitchChange(popData.id, 'isStudent', val)" />
     </el-form-item>
   </el-form>
@@ -132,13 +132,13 @@
 
       <el-table-column label="操作" align="center" min-width="120px">
         <template #default="scope">
-<!--          校内导师查看项目详情,互选记录-->
-          <el-button type="text" v-if="userInfo?.userType === '3'" @click="openStudentSelectSupervisorRecord(scope.row.id)" v-hasPermi="['system:student-select-supervisor-record:query']">
-          <Icon icon="ep:bell" />
-           详情
+          <!--校内导师查看项目详情,互选记录-->
+          <el-button type="text" v-if="userInfo?.userType === '3' || userInfo?.userType === '5'" @click="openStudentSelectSupervisorRecord(scope.row.id)" v-hasPermi="['system:student-select-supervisor-record:query']">
+            <Icon icon="ep:bell" />
+            详情
           </el-button>
 
-<!--          学院或者学生查看详情,导师名额设置页面-->
+          <!--学院或者学生查看详情,导师名额设置页面-->
           <el-button type="text"  v-if="userInfo?.userType === '4' || userInfo?.userType === '1'" @click="openSupervisorSelectionSetting(scope.row.id)" v-hasPermi="['system:supervisor-selection-setting:query']" >
             <Icon icon="ep:bell" />
             详情
@@ -220,6 +220,8 @@ const getList = async () => {
   try {
     const data = await studentSelectionProjectApi.getStudentSelectionProjectPage(queryParams)
     list.value = data.list
+    console.log(data.list);
+    
     total.value = data.total
   } finally {
     loading.value = false
@@ -249,8 +251,8 @@ const resetQuery = () => {
 
 /** 添加/修改操作 */
 const formRef = ref()
-const openForm = (type: string, id?: number) => {
-  formRef.value.open(type, id)
+const openForm = (type: string, id?: number, projectId?: number) => {
+  formRef.value.open(type, id, projectId)
 }
 
 /** 删除按钮操作 */
@@ -340,7 +342,7 @@ onMounted(async () => {
   background-color: white; /* 设置白色背景 */
   padding: 10px; /* 根据需要添加内边距 */
   border-radius: 4px; /* 根据需要添加边框圆角 */
-  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); /* 根据需要添加阴影 */
+  /* box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); 根据需要添加阴影 */
   font-size: 16px; /* 增大字体大小 */
   margin-bottom: 10px; /* 增加元素之间的间距 */
 }

+ 7 - 4
src/views/system/studentSelectionProject/studentSelectionProjectForm.vue

@@ -4,7 +4,7 @@
       ref="formRef"
       :model="formData"
       :rules="formRules"
-      label-width="100px"
+      label-width="130px"
       v-loading="formLoading"
     >
       <el-form-item label="项目名称" prop="projectName">
@@ -16,6 +16,7 @@
           type="datetime"
           value-format="x"
           placeholder="选择学生开始时间"
+          class="!w-full"
         />
       </el-form-item>
       <el-form-item label="导师截止时间" prop="supervisorConfirmDeadline">
@@ -24,6 +25,7 @@
           type="datetime"
           value-format="x"
           placeholder="选择导师截止时间"
+          class="!w-full"
         />
       </el-form-item>
 
@@ -35,7 +37,7 @@
           clearable
           filterable
           multiple
-          class="!w-240px"
+          class="!w-full"
         >
           <el-option
             v-for="supervisor in supervisors"
@@ -46,7 +48,7 @@
         </el-select>
       </el-form-item>
 
-      <el-form-item label="年级">
+      <el-form-item label="年级" prop="studentGrade">
         <el-select v-model="formData.studentGrade" placeholder="请选择年级" >
           <el-option
             v-for="year in gradeOptions"
@@ -93,11 +95,12 @@ const formRules = reactive({
   studentStartTime: [{ required: true, message: '学生开始时间不能为空', trigger: 'blur' }],
   supervisorConfirmDeadline: [{ required: true, message: '导师截止时间不能为空', trigger: 'blur' }],
   studentGrade: [{ required: true, message: '学生年级不能为空', trigger: 'blur' }],
+  supervisorIds: [{ required: true, message: '请选择参与导师', trigger: 'change' }],
 })
 const formRef = ref() // 表单 Ref
 
 /** 打开弹窗 */
-const open = async (type: string, id?: number) => {
+const open = async (type: string, id?: number, projectId?: number) => {
   dialogVisible.value = true
   dialogTitle.value = t('action.' + type)
   formType.value = type

+ 9 - 0
src/views/system/studentSelf/SForm.vue

@@ -59,6 +59,14 @@
         </el-col>
       </el-row>
 
+      <el-row>
+        <el-col :span="24">
+          <el-form-item label="个人简历" prop="introduction">
+            <upload-file v-model="formData.introduction" />
+          </el-form-item>
+        </el-col>
+      </el-row>
+
       <el-row>
         <el-col :span="24">
           <el-form-item label="简介" prop="remark">
@@ -110,6 +118,7 @@ const formData = ref({
   userNumber: '',
   dept: undefined,
   deptId: undefined,
+  introduction : '',
 })
 const formRules = reactive<FormRules>({
   username: [{ required: true, message: '账号不能为空', trigger: 'blur' }],

+ 46 - 1
src/views/system/studentSelf/index.vue

@@ -49,6 +49,14 @@
             </li>
           </div>
 
+          <div class="info-row">
+            <li class="info-item">
+              <Icon class="mr-5px" icon="ep:user" />
+              <span class="info-label">个人简历:</span>
+              <!-- <span class="pull-right"> {{ userInfo.introduction }}</span> -->
+              <el-button class="pull-right" type="text" @click="downloadPDF">预览PDF</el-button>
+            </li>
+          </div>
         </ul>
         <div class="info-remark">
           <div style="display: flex; align-items: center;">
@@ -116,6 +124,43 @@ const getUserInfo = async () => {
   }
 };
 
+const downloadPDF = () => {
+  const url = userInfo.value.introduction
+  if (!url) {
+    message.error('没有简历文件!');
+    return;
+  }
+  // 先预览
+  const link = document.createElement('a'); // 创建一个链接元素
+  link.href = url; // 设置链接地址
+  link.download = '下载文件.pdf'; // 设置下载文件的名称
+  document.body.appendChild(link); // 将链接添加到文档中
+  link.click(); // 触发下载
+  document.body.removeChild(link); // 下载后移除链接
+  // 直接下载
+  // // 创建一个下载链接
+  // fetch(url)
+  //   .then(response => {
+  //     if (!response.ok) {
+  //       throw new Error('网络错误');
+  //     }
+  //     return response.blob(); // 将响应转换为 Blob 对象
+  //   })
+  //   .then(blob => {
+  //     const link = document.createElement('a');
+  //     const blobUrl = URL.createObjectURL(blob); // 创建 Blob URL
+  //     link.href = blobUrl;
+  //     link.download = '下载文件.pdf'; // 设置下载文件的名称
+  //     document.body.appendChild(link);
+  //     link.click(); // 触发下载
+  //     document.body.removeChild(link); // 下载后移除链接
+  //     URL.revokeObjectURL(blobUrl); // 释放 Blob URL
+  //   })
+  //   .catch(error => {
+  //     console.error('下载失败:', error);
+  //   });
+}
+
 const openDialog = () => {
   dialogVisible.value = true;
   formRef.value.open();
@@ -149,7 +194,7 @@ const fetchImageUrls = async () => {
 };
 
 const getPopDataFunction =(async ()=>{
-  isPop.value = await  getIsPop();
+  isPop.value = await getIsPop();
   console.log(isPop.value)
 })
 

+ 33 - 26
src/views/system/supervisorSelectionSetting/index.vue

@@ -47,7 +47,7 @@
       <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
           plain
           type="primary"
@@ -56,7 +56,7 @@
           v-if="userInfo?.userType === '1'"
         >
           志愿编辑
-        </el-button>
+        </el-button> -->
 <!--        <el-button-->
 <!--          type="primary"-->
 <!--          plain-->
@@ -81,7 +81,7 @@
   <!-- 列表 -->
   <ContentWrap>
     <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
-      <el-table-column type="index" width="50" />
+      <el-table-column type="index" />
 <!--      <el-table-column label="项目名称" align="center" prop="projectId" />-->
       <el-table-column label="导师姓名" align="center" prop="supervisorName" />
       <el-table-column
@@ -98,7 +98,7 @@
 <!--      <el-table-column label="学硕名额" align="center" prop="academicSlots" />-->
 <!--      <el-table-column label="专硕名额" align="center" prop="professionalSlots" />-->
 
-      <el-table-column label="已招生名额" align="center">
+      <el-table-column label="已招生名额" align="center" min-width="90px">
         <template #default="scope">
           <span>
             <span v-if="scope.row.occupiedAcademicSlots">
@@ -113,7 +113,7 @@
           </span>
         </template>
       </el-table-column>
-      <el-table-column label="剩余名额" align="center">
+      <el-table-column label="剩余名额" align="center" min-width="100px">
         <template #default="scope">
           学硕/{{ scope.row.academicSlots -scope.row.occupiedAcademicSlots }} 专硕/{{ scope.row.professionalSlots-scope.row.occupiedProfessionalSlots }}
         </template>
@@ -126,13 +126,13 @@
         width="180px"
       />
 
-      <el-table-column label="导师详情" align="center" min-width="120px"  v-if="userInfo?.userType === '4' || userInfo?.userType === '1'">
+      <el-table-column label="导师详情" align="center" v-if="userInfo?.userType === '4' || userInfo?.userType === '1'">
         <template #default="scope">
           <el-button
-link
-                      type="primary"
-                      @click="openTeacherRequireForm( scope.row.supervisorId)"
-                      v-hasPermi="['system:user:query']"
+            link
+            type="primary"
+            @click="openTeacherRequireForm( scope.row.supervisorId, scope.row.userType)"
+            v-hasPermi="['system:user:query']"
           >
             <Icon icon="ep:bell" />
             查看
@@ -159,13 +159,17 @@ link
 
       <el-table-column label="操作" align="center" min-width="120px">
         <template #default="scope">
-<!--          学院查看招生详情-->
-          <el-button type="text"  v-if="userInfo?.userType === '4'" @click="openStudentSelectSupervisorRecord(scope.row.projectId,scope.row.supervisorId)" v-hasPermi="['system:student-select-supervisor-record:query']"
-                     >
+          <!--学院查看招生详情-->
+          <el-button 
+            type="text"  
+            v-if="userInfo?.userType === '4'" 
+            @click="openStudentSelectSupervisorRecord(scope.row.projectId,scope.row.supervisorId)" 
+            v-hasPermi="['system:student-select-supervisor-record:query']"
+          >
             <Icon icon="ep:bell" />
             招生详情
           </el-button>
-<!--       志愿填报修改-->
+          <!--志愿填报修改-->
           <el-button
             link
             type="primary"
@@ -207,7 +211,7 @@ link
   </ContentWrap>
 
   <!--  是学生-->
-  <ContentWrap v-if="userInfo.userType==='1' ||userInfo.userType==='4'" >
+  <!-- <ContentWrap v-if="userInfo.userType==='1' ||userInfo.userType==='4'" >
       <el-table
         v-loading="loading"
         :data="selectionList"
@@ -229,17 +233,17 @@ link
           :formatter="userTypeFormatter"
         />
 
-<!--      <el-table-column label="专业" align="center" prop="major" />-->
+     <el-table-column label="专业" align="center" prop="major" />
 
-<!--      <el-table-column label="简历" align="center" prop="introduction" />-->
+     <el-table-column label="简历" align="center" prop="introduction" />
 
       <el-table-column label="申请状态" align="center" prop="selectType" >
         <template #default="scope">
           <dict-tag :type="DICT_TYPE.SYSTEM_STUDENT_SELECT_RECORD_SELECT_TYPE" :value="scope.row.selectType" />
         </template>
       </el-table-column>
-<!--      <el-table-column label="学生电子签名" align="center" prop="studentSignature" />-->
-<!--      <el-table-column label="导师电子签名" align="center" prop="supervisorSignature" />-->
+     <el-table-column label="学生电子签名" align="center" prop="studentSignature" />
+     <el-table-column label="导师电子签名" align="center" prop="supervisorSignature" />
       <el-table-column
         label="提交时间"
         align="center"
@@ -255,7 +259,7 @@ link
         width="180px"
       />
     </el-table>
-  </ContentWrap>
+  </ContentWrap> -->
 
   <!-- 表单弹窗:添加/修改 -->
   <supervisorSelectionSettingForm ref="formRef" @success="getList" />
@@ -280,21 +284,24 @@ import {
   studentSelectSupervisorRecordVO
 } from "@/api/system/studentSelectSupervisorRecord";
 import {DICT_TYPE} from "@/utils/dict";
+import { useRoute, useRouter } from 'vue-router';
+
 
 /** 导师学硕专硕名额设置 列表 */
 defineOptions({ name: 'SupervisorSelectionSetting' })
 
+const route = useRoute()
+const projectId = ref(route.query.projectId);
+
 const message = useMessage() // 消息弹窗
 const { t } = useI18n() // 国际化
-
 const loading = ref(true) // 列表的加载中
 const list = ref<supervisorSelectionSettingVO[]>([]) // 列表的数据
-
 const total = ref(0) // 列表的总页数
 const queryParams = reactive({
   pageNo: 1,
   pageSize: 10,
-  projectId: undefined,
+  projectId: projectId.value,
   supervisorId: undefined,
   academicSlots: undefined,
   professionalSlots: undefined,
@@ -306,7 +313,7 @@ const queryFormRef = ref() // 搜索的表单
 const exportLoading = ref(false) // 导出的加载中
 
 //记录页面
-const router = useRouter()
+const router = useRouter();
 const openStudentSelectSupervisorRecord = (projectId,supervisorId) => {
   router.push({ name: 'studentSelectSupervisorRecord', query: { projectId: projectId ,supervisorId :supervisorId} });
 }
@@ -401,8 +408,8 @@ const getSupervisor= async () => {
 //传supervisorId给formData.supervisorId
 
 const teacherRequireFormRef = ref()
-const openTeacherRequireForm = (supervisorId?: number) => {
-  teacherRequireFormRef.value.open("detail",supervisorId)
+const openTeacherRequireForm = (supervisorId?: number, userType?: string) => {
+  teacherRequireFormRef.value.open("detail",supervisorId,userType)
 }
 
 //志愿填报弹窗

+ 3 - 3
src/views/system/userDetail/student.vue

@@ -1,4 +1,3 @@
-
 <template>
   <Dialog v-model="dialogVisible" :title="dialogTitle">
     <el-form
@@ -91,10 +90,11 @@ const userInfo = ref({} as ProfileVO)
 const getUserInfo = async () => {
   const users = await getUserProfile()
   userInfo.value = users
+  // console.log(users,'00');
 }
 const isStudent = computed(() => userInfo.value.userType === "1");
 
-  const open = async () => {
+const open = async () => {
   dialogVisible.value = true
   dialogTitle.value = '信息填写'
   formType.value = '' //
@@ -103,11 +103,11 @@ const isStudent = computed(() => userInfo.value.userType === "1");
     formLoading.value = true
     try {
       const user = await UserApi.getUser(userInfo.value.id)
+      // console.log(user,'11');
       formData.value = user;
     } finally {
       formLoading.value = false
     }
-
 }
 
   defineExpose({ open }) // 提供 open 方法,用于打开弹窗

+ 13 - 12
src/views/system/userDetail/teacher.vue

@@ -21,7 +21,7 @@
         </el-form-item>
       </el-col>
     </el-row>
-    <el-row v-if="userInfo.userType==='5'">
+    <el-row v-if="TUsertype === '5' || userInfo.userType==='5'">
       <el-col :span="24" >
         <el-form-item label="外聘导师" style="font-weight: 550;">
           <p></p>
@@ -33,7 +33,7 @@
         </el-form-item>
       </el-col>
     </el-row>
-    <el-row v-if="userInfo.userType==='5'">
+    <el-row v-if="TUsertype ==='5' || userInfo.userType==='5'">
       <el-col :span="24">
         <el-form-item label="合作的校内导师" prop="supervisor">
           <el-input v-model="formData.supervisor" placeholder="自动链接" :disabled="!isSupervisor"/>
@@ -49,7 +49,7 @@
     </el-row>
       <el-row >
         <!--        导师上传-->
-        <el-col :span="24" v-if="userInfo.userType==='3'&&formType==='update'">
+        <el-col :span="24" v-if="userInfo.userType==='3'&& formType==='update' || userInfo.userType==='5' && formType==='update'">
           <el-form-item label="个人简历上传" prop="introduction">
             <!-- <upload-file v-model="formData.introduction" /> -->
             <Editor v-model="formData.introduction" ref="editorRef" class="full-width-editor"/>
@@ -80,8 +80,8 @@
     </el-row>
     </el-form>
     <template #footer>
-      <el-button :disabled="formLoading" type="primary" @click="submitForm" v-if="userInfo.userType==='3'">确 定</el-button>
-      <el-button @click="dialogVisible = false" v-if="userInfo.userType==='3'" >取 消</el-button>
+      <el-button :disabled="formLoading" type="primary" @click="submitForm" v-if="userInfo.userType==='3' || userInfo.userType==='5'">确 定</el-button>
+      <el-button @click="dialogVisible = false" v-if="userInfo.userType==='3' || userInfo.userType==='5'" >取 消</el-button>
     </template>
   </Dialog>
 </template>
@@ -105,9 +105,9 @@ const dialogTitle = ref('') // 弹窗的标题
 const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
 const formType = ref('') // 表单的类型:create - 新增;update - 修改
 const formData = ref({
-  id: undefined,
-  sex: undefined,
-  supervisorId:undefined,
+  id: null,
+  sex: null,
+  supervisorId: null,
   nickname: '',
   title: '',//职称
   status: CommonStatusEnum.ENABLE,
@@ -126,13 +126,14 @@ const deptList = ref<Tree[]>([]) // 树形结构
 const userInfo = ref({} as ProfileVO)
 const getUserInfo = async () => {
   const users = await getUserProfile()
-  userInfo.value = users
+  userInfo.value = users  
 }
 // const isStudent = computed(() => userInfo.value.userType === "1");
-
-  const open = async (type:string,supervisorId: number) => {
+const TUsertype = ref<string | undefined>(undefined);
+const open = async (type: string, supervisorId: number, userType?: string) => {
   dialogVisible.value = true
-    formType.value=type
+  formType.value=type
+  TUsertype.value = userType; 
   if (formType.value == 'detail'){
     dialogTitle.value = '查看详情'
     resetForm()

+ 10 - 0
src/views/system/workroomTeacher/TeacherSelf/TForm.vue

@@ -59,6 +59,14 @@
         </el-col>
       </el-row>
 
+<!--  <el-row>
+        <el-col :span="24">
+          <el-form-item label="个人简历" prop="introduction">
+            <upload-file v-model="formData.introduction" />
+          </el-form-item>
+        </el-col>
+      </el-row> -->
+
       <el-row>
         <el-col :span="24">
           <el-form-item label="简介" prop="remark">
@@ -110,6 +118,7 @@ const formData = ref({
   userNumber: '',
   dept: undefined,
   deptId: undefined,
+  introduction: '',
 })
 const formRules = reactive<FormRules>({
   username: [{ required: true, message: '账号不能为空', trigger: 'blur' }],
@@ -141,6 +150,7 @@ const postList = ref([] as PostApi.PostVO[]) // 岗位列表
 //用户类型
 const userTypes = [
   { value: '3', label: '导师' },
+  { value: '5', label: '外聘导师' },
 ]
 
 /** 打开弹窗 */

+ 39 - 0
src/views/system/workroomTeacher/TeacherSelf/index.vue

@@ -124,8 +124,46 @@ const getUserInfo = async () => {
 
 const userTypeMapping = {
   '3': '导师',
+  '5': '外聘导师',
 };
 
+const downloadPDF = () => {
+  const url = userInfo.value.introduction
+  if (!url) {
+    message.error('没有简历文件!');
+    return;
+  }
+  // 先预览
+  const link = document.createElement('a'); // 创建一个链接元素
+  link.href = url; // 设置链接地址
+  link.download = '下载文件.pdf'; // 设置下载文件的名称
+  document.body.appendChild(link); // 将链接添加到文档中
+  link.click(); // 触发下载
+  document.body.removeChild(link); // 下载后移除链接
+  // 直接下载
+  // // 创建一个下载链接
+  // fetch(url)
+  //   .then(response => {
+  //     if (!response.ok) {
+  //       throw new Error('网络错误');
+  //     }
+  //     return response.blob(); // 将响应转换为 Blob 对象
+  //   })
+  //   .then(blob => {
+  //     const link = document.createElement('a');
+  //     const blobUrl = URL.createObjectURL(blob); // 创建 Blob URL
+  //     link.href = blobUrl;
+  //     link.download = '下载文件.pdf'; // 设置下载文件的名称
+  //     document.body.appendChild(link);
+  //     link.click(); // 触发下载
+  //     document.body.removeChild(link); // 下载后移除链接
+  //     URL.revokeObjectURL(blobUrl); // 释放 Blob URL
+  //   })
+  //   .catch(error => {
+  //     console.error('下载失败:', error);
+  //   });
+}
+
 const openDialog = () => {
   loading.value = true; // 显示加载中
   dialogVisible.value = true;
@@ -216,6 +254,7 @@ const fetchImageUrls = async () => {
       extractedImageUrls,
       cleanedremark,
       userTypeMapping,
+      downloadPDF,
     };
   }
 });