| 
					
				 | 
			
			
				@@ -4,13 +4,12 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     <!-- 筛选条件 --> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     <div class="d-flex justify-space-between mt-8 mb-10"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       <div class="d-flex align-center"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        <!-- <span class="mx-3 color-666 font-size-14">院系</span> --> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        <Autocomplete class="mr-3" v-model="query.schoolDepartmentName" :item="schoolDepartmentItem"></Autocomplete> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        <TextInput class="mr-3" v-model="query.studentName" :item="studentNameItem" @enter="handleSearch()"></TextInput> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        <Autocomplete class="mr-3" v-model="query.schoolDeptId" :item="schoolDepartmentItem"></Autocomplete> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        <TextInput class="mr-3" v-model="query.name" :item="studentNameItem" @enter="handleSearch()"></TextInput> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         <v-btn color="primary" class="half-button ml-3" @click="handleSearch()">查 询</v-btn> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         <v-btn class="half-button ml-3" prepend-icon="mdi-refresh" variant="outlined" color="primary" @click="handleSearch(true)">刷 新</v-btn> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       </div> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      <v-btn :loading="exportLoading" prepend-icon="mdi-export-variant" color="primary" variant="tonal" class="ml-3" @click="null">导出</v-btn> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      <!-- <v-btn :loading="exportLoading" prepend-icon="mdi-export-variant" color="primary" variant="tonal" class="ml-3" @click="null">导出</v-btn> --> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     </div> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     <!-- 列表 --> 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -34,31 +33,54 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           </div> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         </template> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         <template #actions="{ item }"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          <v-btn v-if="!item?.recommendationLetter" color="primary" variant="text" @click="previewFile(item.recommendationLetter)">推荐信</v-btn> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          <v-btn v-if="!item?.evaluate" color="#00897B" variant="text" @click="previewFile(item.evaluate)">实习证书</v-btn> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          <v-btn color="primary" variant="text" @click="studentDetails(item.id)">详情</v-btn> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          <v-btn color="primary" variant="text" @click="handleReport(item)">实习报告</v-btn> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         </template> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       </CtTable> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      <!-- <Loading :visible="loading"></Loading> --> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     </div> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  </v-card > 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    <v-navigation-drawer v-model="showDetail" absolute location="right" rounded temporary width="700" class="pa-5"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    <div class="resume-header" style="height: 50px;"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      <div class="resume-title">{{ itemData?.person?.name }} - 实习报告</div> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      <Autocomplete v-model="enterpriseId" :item="enterpriseItem" @change="handleEnterprise"></Autocomplete> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    </div> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    <div v-if="report && report.length > 0" class="mt-5"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      <div v-for="item in report" :key="item.date" class="mb-3"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        <div class="color-666">日期:{{ item.date }}</div> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        <div class="d-flex flex-wrap"> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          <img  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            v-for="(src, index) in item.arr"  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            :key="index"  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            :src="src"  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            @click="handlePreview(item.arr, index)"  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            class="cursor-pointer"  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            style="width: 200px; height: 250px;" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          /> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        </div> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      </div> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    </div> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    <Empty v-else :elevation="false" :message="!enterpriseId ? '请选择要查看的实习企业' : '暂无实习报告'" /> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	</v-navigation-drawer> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  </v-card> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  <PreviewImage v-if="showPreview" :initialIndex="initialIndex" :urlList="urlsList" @close="handleClosePreview" /> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 </template> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 <script setup> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 defineOptions({name: 'studentList-index'}) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import { ref } from 'vue' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import { ref, onMounted } from 'vue' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import Snackbar from '@/plugins/snackbar' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import { formatName } from '@/utils/getText' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import { getUserAvatar } from '@/utils/avatar' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import { studentList, getSchoolOrganizationList } from '@/api/school' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// import { useRouter } from 'vue-router'; const router = useRouter() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import { previewFile } from '@/utils' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import { studentList, getSchoolOrganizationList, getStudentPracticeReportById, getStudentPracticeCompanyList } from '@/api/school' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import { formatName } from '@/utils/getText' 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const loading = ref(false) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const query = ref({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  pageSize: 20, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  pageSize: 10, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   pageNo: 1, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  schoolDepartmentName: null, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  studentName: null, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  schoolId: JSON.parse(localStorage.getItem('schoolInfo'))?.schoolId, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  name: null, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  schoolDeptId: null 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 }) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const studentNameItem = ref({ 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -68,27 +90,35 @@ const studentNameItem = ref({ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   clearable: true, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   hideDetails: true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 }) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const enterpriseId = ref(null) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const enterpriseItem = ref({  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  width: 300,  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  items: [],  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  clearable: true, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  hideDetails: true,  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  label: '请选择实习企业',  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  itemText: 'name',  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  itemValue: 'id'  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const headers = [ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   { title: '学生姓名', key: 'studentName', sortable: false }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  { title: '学生学号', key: 'test', sortable: false }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  { title: '所属专业', key: 'test', sortable: false }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  { title: '录用企业', key: 'test', sortable: false, value: item => formatName(item.test) }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  { title: '录用部门', key: 'test', sortable: false, value: item => formatName(item.test) }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  { title: '录用岗位', key: 'test', sortable: false, value: item => formatName(item.test) }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  { title: '所属院系', key: 'schoolDept.name', sortable: false }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  { title: '所属专业', key: 'major.nameCn', sortable: false }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  { title: '所在班级', key: 'schoolClass.name', sortable: false }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  { title: '学号', key: 'studentNo', sortable: false }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  { title: '紧急联系人', key: 'emergencyContactName', sortable: false }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  { title: '紧急联系人电话', key: 'emergencyContactPhone', sortable: false }, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   { title: '操作', key: 'actions', sortable: false } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 ] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// 数据列表 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 学生列表 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const tableData = ref([]); const total = ref(0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const getData = async (isRefresh = false) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (!query.value?.schoolDepartmentName) return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  const { data, total: number } = await studentList(query.value) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  tableData.value = data?.records?.length && data.records.map(item=>{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    const { enterpeiseName, enterpriseRecruitJobName, jobDept } = item 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    return { ...item.student, enterpeiseName, enterpriseRecruitJobName, jobDept } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  }) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  total.value = number 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const result = await studentList(query.value) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  tableData.value = result.list || [] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  total.value = result.total 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (isRefresh) Snackbar.success('刷新成功') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -107,29 +137,67 @@ const handleSearch = (refresh = false) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const schoolInfo = ref(localStorage.getItem('schoolInfo') ? JSON.parse(localStorage.getItem('schoolInfo')) : {}) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const schoolDepartmentItem = ref({ width: 300, items: [], clearable: false, hideDetails: true, label: '请选择院系', itemText: 'name', itemValue: 'id' }) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// 列表 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-const getYuanXiItem = async () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 院系列表 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const getSchoolDepartment = async () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   const schoolId = schoolInfo.value?.schoolId || null 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (!schoolId) return Snackbar.warning('获取学校信息失败!') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				    
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   const data = await getSchoolOrganizationList({ schoolId, type: 0 }) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   schoolDepartmentItem.value.items = data || [] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  // if (schoolDepartmentItem.value.items?.length) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  //   query.value.schoolDepartmentName = schoolDepartmentItem.value.items[0].value 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  //   getData() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  // } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-getYuanXiItem() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+onMounted(() => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  getSchoolDepartment() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  getData() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 const studentDetails = (id) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (id) window.open(`/recruit/teacher/studentList/detail/${id}`) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-// 导出 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-const exportLoading = ref(false) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 实习报告 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const showDetail = ref(false) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const report = ref([]) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const itemData = ref({}) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const handleReport = async (item) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  enterpriseId.value = null 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  report.value = [] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  itemData.value = item 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  enterpriseItem.value.items = [] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const data = await getStudentPracticeCompanyList({ userId: item.userId }) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  enterpriseItem.value.items = data ? data.map(e => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return { name: formatName(e.anotherName || e.name), id: e.id } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  }) : [] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  showDetail.value = true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const handleEnterprise = async (id) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  report.value = [] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (!id) return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const data = await getStudentPracticeReportById({ enterpriseId: id, userId: itemData.value.userId }) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (!data || !Object.keys(data).length) return 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	for (let item in data) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		report.value.push({ date: item, arr: data[item].map(e => e.url) }) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 图片预览 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const showPreview = ref(false) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const initialIndex = ref(0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const urlsList = ref([]) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const handlePreview = (arr, index) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  urlsList.value = arr 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  initialIndex.value = index 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  showPreview.value = true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+const handleClosePreview = () => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  showPreview.value = false 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  initialIndex.value = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  urlsList.value = [] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 </script> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 <style lang="scss" scoped> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 .title { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   color: var(--color-333); 
			 |