Jelajahi Sumber

学生列表、学生详情

Xiao_123 2 bulan lalu
induk
melakukan
15ec4a0670

+ 36 - 4
src/api/school.js

@@ -16,10 +16,18 @@ export const schoolRegister = async (data) => {
 }
 
 // 学生列表
-export const studentList = async (data) => {
-	return await request.post({
-		url: '/app-api/flames/student/list',
-		data
+export const studentList = async (params) => {
+	return await request.get({
+		url: '/app-api/menduner/system/teacher/school/student/page',
+		params
+	})
+}
+
+// 学生详情
+export const getStudentDetailsById = async (params) => {
+	return await request.get({
+		url: '/app-api/menduner/system/teacher/school/student/get',
+		params
 	})
 }
 
@@ -141,3 +149,27 @@ export const deleteOrganization = async (id) => {
 		url: '/app-api/menduner/system/teacher/school/delete?id=' + id
 	})
 }
+
+// 根据id获取学生实习情况
+export const getInternshipById = async (params) => {
+	return await request.get({
+		url: '/app-api/menduner/system/teacher/school/student/practice/record/get',
+		params
+	})
+}
+
+// 根据id获取学生实习报告
+export const getStudentPracticeReportById = async (params) => {
+	return await request.get({
+		url: '/app-api/menduner/system/teacher/school/student/report/get',
+		params
+	})
+}
+
+// 获取学生实习的企业列表
+export const getStudentPracticeCompanyList = async (params) => {
+	return await request.get({
+		url: '/app-api/menduner/system/teacher/school/student/practice/record-enterprise/list',
+		params
+	})
+}

+ 20 - 20
src/router/modules/components/recruit/teacher.js

@@ -56,26 +56,26 @@ const teacher = [
       },
     ]
   },
-  {
-    path: '/recruit/teacher/internshipReport',
-    component: Layout,
-    name: '实习报告',
-    icon: 'mdi-file-document-multiple-outline',
-    meta: {
-      enName: 'Internship Report'
-    },
-    children: [
-      {
-        path: 'index',
-        name: '实习报告',
-        meta: {
-          enName: 'Internship Report',
-        },
-        show: true,
-        component: () => import('@/views/recruit/teacher/internshipReport/index.vue')
-      },
-    ]
-  },
+  // {
+  //   path: '/recruit/teacher/internshipReport',
+  //   component: Layout,
+  //   name: '实习报告',
+  //   icon: 'mdi-file-document-multiple-outline',
+  //   meta: {
+  //     enName: 'Internship Report'
+  //   },
+  //   children: [
+  //     {
+  //       path: 'index',
+  //       name: '实习报告',
+  //       meta: {
+  //         enName: 'Internship Report',
+  //       },
+  //       show: true,
+  //       component: () => import('@/views/recruit/teacher/internshipReport/index.vue')
+  //     },
+  //   ]
+  // },
   // {
   //   path: '/recruit/teacher/internshipCompany',
   //   component: Layout,

+ 11 - 11
src/views/recruit/teacher/studentList/components/baseInfo.vue

@@ -4,25 +4,25 @@
     <!-- 头像 -->
     <div class="avatarsBox">
       <v-badge
-        v-if="info?.sex === '1' || info?.sex === '2'"
+        v-if="info?.person?.sex === '1' || info?.person?.sex === '2'"
         bordered 
         offset-x="-25" 
         offset-y="33" 
-        :color="info?.sex ? (info?.sex === '1' ? '#1867c0' : 'error') : 'error'" 
-        :icon="info?.sex ? (info?.sex === '1' ? 'mdi-gender-male' : 'mdi-gender-female') : 'mdi-gender-female'">
-        <v-avatar size=80 :image="getUserAvatar(info?.avatar, info?.sex)"></v-avatar>
+        :color="info?.person?.sex ? (info?.person?.sex === '1' ? '#1867c0' : 'error') : 'error'" 
+        :icon="info?.person?.sex ? (info?.person?.sex === '1' ? 'mdi-gender-male' : 'mdi-gender-female') : 'mdi-gender-female'">
+        <v-avatar size=80 :image="getUserAvatar(info?.person?.avatar, info?.person?.sex)"></v-avatar>
       </v-badge>
-      <v-avatar v-else size=80 :image="getUserAvatar(info?.student?.studentHeadImg, info?.sex)"></v-avatar>
+      <v-avatar v-else size="80" :image="getUserAvatar(info?.person?.avatar, info?.person?.sex)"></v-avatar>
     </div>
     <!-- 信息 -->
     <div style="flex: 1;">
-      <span style="font-size: 20px; font-weight: 600;color: var(--color-666);">{{ info?.student?.studentName }}</span>
+      <span style="font-size: 20px; font-weight: 600;color: var(--color-666);">{{ info?.person?.name }}</span>
       <div class="d-flex mt-2 listBox">
-        <span>{{ info?.student?.schoolDepartmentName }}</span>
-        <span v-if="info?.student?.schoolDepartmentName && info?.student?.majorName" class="mx-3">|</span>
-        <span>{{ info?.student?.majorName }}</span>
+        <span>{{ info?.schoolDept?.name }}</span>
+        <span v-if="info?.schoolDept?.name && info?.major?.nameCn" class="mx-3">|</span>
+        <span>{{ info?.major?.nameCn }}</span>
       </div>
-      <view class="mt-2 listBox">{{ info?.student?.schoolClassName }}</view>
+      <view class="mt-2 listBox">{{ info?.schoolClass?.name }}</view>
     </div>
   </div>
 </template>
@@ -38,7 +38,7 @@ const props = defineProps({
 const info = ref({})
 if (props.data && Object.keys(props.data).length) {
   info.value = props.data
-  info.value.sex = info.value?.student?.studentSex === '男' ? '1' : info.value?.student?.studentSex === '女' ? '2' : info.value?.student?.sex || null
+  info.value.sex = info.value?.person?.sex === '男' ? '1' : info.value?.person?.sex === '女' ? '2' : info.value?.person?.sex || null
 }
 </script>
 

+ 9 - 59
src/views/recruit/teacher/studentList/components/other.vue

@@ -4,84 +4,34 @@
     <div class="boxMy">
       <div class="title-text">基本信息</div>
       <div class="my">
-        <span>出生年月:</span>
-        <span class="ml">{{ info?.student?.studentBirthday ? info?.student?.studentBirthday.slice(0, 10) : '' }}</span>
-      </div>
-      <div class="my">
-        <span>联系电话:</span>
-        <span class="ml">{{ info?.student?.phone }}</span>
-      </div>
-      <div class="my">
-        <span>就读院系:</span>
-        <span class="ml">{{ info?.schoolDepartment?.departmentTitle }}</span>
-      </div>
-      <div class="my">
-        <span>就读专业:</span>
-        <span class="ml">{{ info?.major?.majorName }}</span>
+        <span>学号:</span>
+        <span class="ml">{{ info?.studentNo }}</span>
       </div>
       <div class="my">
-        <span>所在班级:</span>
-        <span class="ml">{{ info?.schoolClass?.title }}</span>
+        <span>出生年月:</span>
+        <span class="ml">{{ info?.person?.birthday ? timesTampChange(info?.person?.birthday, 'Y-M-D') : '' }}</span>
       </div>
       <div class="my">
-        <span>学号:</span>
-        <span class="ml">{{ info?.student?.studentNo }}</span>
+        <span>联系电话:</span>
+        <span class="ml">{{ info?.person?.phone }}</span>
       </div>
       <div class="my">
         <span>紧急联系人:</span>
-        <span class="ml">{{ info?.student?.emergencyContactName }}</span>
+        <span class="ml">{{ info?.emergencyContactName }}</span>
       </div>
       <div class="my">
         <span>紧急联系人电话:</span>
-        <span class="ml">{{ info?.student?.emergencyContactPhone }}</span>
-      </div>
-      <div class="my" style="display: flex;align-items: center;">
-        <span>学生简历:</span>
-        <img v-if="checkIsImage(info?.studentBiographicalNotes?.fileUrl)" :src="info?.studentBiographicalNotes?.fileUrl" style="height: 100px;" />
-      </div>
-      <div class="my">
-        <span>录用企业:</span>
-        <span class="ml">{{ info?.student?.enterpeiseName }}</span>
-      </div>
-      <div class="my">
-        <span>录用部门:</span>
-        <span class="ml">{{ info?.student?.jobDept }}</span>
-      </div>
-      <div class="my">
-        <span>录用岗位:</span>
-        <span class="ml">{{ info?.student?.enterpriseRecruitJobName }}</span>
+        <span class="ml">{{ info?.emergencyContactPhone }}</span>
       </div>
     </div>
 
-    <div class="boxMy">
-      <div class="title-text">实习证书</div>
-      <div class="my" style="display: flex;">
-        <span>点评:</span>
-        <span class="ml">{{ info?.certificate?.comment }}</span>
-      </div>
-      <div class="my">
-        <span>证书:</span>
-        <span v-if="info?.certificate?.comment" class="ml link-text" @click="viewCertificate">点击查看</span>
-      </div>
-      <div class="my">
-        <span>附件:</span>
-        <span v-if="info?.certificate?.fileUrl" class="ml link-text" @click="handlePreview(info?.certificate?.fileUrl)">在线预览</span>
-      </div>
-    </div>
-    <div class="boxMy">
-      <div class="title-text">企业推荐信</div>
-      <div class="my">
-        <span>附件:</span>
-        <span v-if="info?.commendation?.fileUrl" class="ml link-text" @click="handlePreview(info?.commendation?.fileUrl)">在线预览</span>
-      </div>
-    </div>
   </div>
 </template>
 
 <script setup>
 defineOptions({name: 'studentList-student-details-baseInfoOther'})
 import { ref } from 'vue'
-import { checkIsImage } from '@/utils'
+import { timesTampChange } from '@/utils/date'
 
 const props = defineProps({
   data: Object

+ 108 - 40
src/views/recruit/teacher/studentList/index.vue

@@ -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);

+ 77 - 77
src/views/recruit/teacher/studentList/studentDetails.vue

@@ -1,26 +1,42 @@
 <!-- 学生详情 -->
 <template>
-  <div v-if="Object.keys(info).length" class="d-flex justify-center mb-8">
-    <div style="width: 940px;background: #fff;" class="px-8 pb-12 pt-3 my-n3 mr-3">
-      <!-- 基本信息 -->
+  <div v-if="Object.keys(info).length" class="d-flex justify-center flex-column align-center mb-8">
+    <v-card class="pa-8">
+      <!-- 头像院系 -->
       <baseInfo class="mt-5" :data="info"></baseInfo>
       <!-- 基本信息 -->
       <other :data="info"></other>
-    </div>
-    <div class="operate pa-3">
-      <v-list>
-        <v-list-subheader class="title">操作</v-list-subheader>
-        <v-list-item
-          v-for="(item, i) in operateItems" :key="'操作' + i"
-          color="primary"
-          :prepend-icon="item.icon"
-          :title="item.text"
-          @click="handleClick(item)"
-        >
-        </v-list-item>
-      </v-list>
-    </div>
+    </v-card>
+
+    <!-- 实习情况 -->
+    <v-card class="my-3 pa-5">
+      <div class="resume-header">
+        <div class="resume-title">实习情况</div>
+      </div>
+      <CtTable
+        class="mt-3"
+        :items="practice"
+        :headers="headers"
+        :elevation="0"
+        :loading="false"
+        :is-tools="false"
+        :items-per-page="-1"
+        :showPage="false"
+        itemKey="id"
+      >
+        <template #enterpriseName="{ item }">
+          <div class="d-flex align-center defaultLink" @click="handleEnterprise(item.enterpriseId)">
+            <v-avatar size="40" :image="item.enterprise.logoUrl || 'https://minio.citupro.com/dev/menduner/company-avatar.png'"></v-avatar>
+            <span class="ml-3">{{ formatName(item.enterprise.anotherName || item.enterprise.name) }}</span>
+          </div>
+        </template>
+        <template #status="{ item }">
+          {{ statusList.find(e => e.value === item.status)?.label }}
+        </template>
+      </CtTable>
+    </v-card>
   </div>
+
   <Loading :visible="loading"></Loading>
 </template>
 
@@ -28,35 +44,38 @@
 defineOptions({name: 'studentList-student-details'})
 import baseInfo from './components/baseInfo.vue'
 import other from './components/other.vue'
-import { ref } from 'vue'
-import { stuDetail, certificateList, recommendationList } from '@/api/school'
+import { ref, onMounted } from 'vue'
+import { getStudentDetailsById, getInternshipById } from '@/api/school'
 import Snackbar from '@/plugins/snackbar'
-import { useRoute } from 'vue-router'; const route = useRoute()
+import { useRoute } from 'vue-router';
+import { formatName } from '@/utils/getText'
+import { timesTampChange } from '@/utils/date'
+import { getDict } from '@/hooks/web/useDictionaries'
 
-const operateItems = [
-  { text: '上传推荐信', key:'letter', icon: 'mdi-circle-medium' },
-  { text: '颁发实习证书', key:'certificate', icon: 'mdi-circle-medium' },
-]
+const route = useRoute()
 
 // 获取人才详情
-const info = ref({
-  student: {
-    studentName: '莫秋妮',
-    studentSex: '男',
-    studentBirthday: '2000-01-01 00:00:00',
-    schoolDepartmentName: '上海交通大学',
-    majorName: '野生动物与自然保护区管理',
-    schoolClassName: '1班',
-  },
-  studentBiographicalNotes: {
-    fileUrl: 'https://minio.huomiaoer.com/dev/data/a613722d-f0cc-404b-88b7-4f92dbed5264/ba9e680f-6bba-4fb9-8df6-1fd723b286ed.jpg',
-  }
-})
+const info = ref({})
 const loading = ref(false)
-const { id: studentId } = route.params
+const { id } = route.params
+
+const headers = [
+  { title: '实习企业', key: 'enterpriseName', sortable: false },
+  { title: '投递职位', key: 'jobName', sortable: false, value: item =>  formatName(item?.job?.name) },
+  { title: '实习状态', key: 'status', sortable: false },
+  { title: '开始时间', key: 'startTime', sortable: false, value: item => timesTampChange(item.startTime, 'Y-M-D') },
+  { title: '结束时间', key: 'endTime', sortable: false, value: item => timesTampChange(item.startTime, 'Y-M-D') },
+]
+
+// 获取学生实习情况
+const practice = ref([])
+const getPracticeRecord = async (userId) => {
+  const data = await getInternshipById({ userId })
+  practice.value = data || []
+}
 
 const getCvDetail = async () => {
-  if (!studentId) {
+  if (!id) {
     Snackbar.warning('缺少学生id')
     setTimeout(() => {
       window.close()
@@ -64,51 +83,32 @@ const getCvDetail = async () => {
     return
   }
   loading.value = true
-  const data = await stuDetail({ studentId })
-  info.value = data
-  await getInternshipCertificate()
-  await getRecommendation()
+  const data = await getStudentDetailsById({ id })
+  info.value = data || {}
   loading.value = false
-}
-getCvDetail()
 
-// 实习证书
-const getInternshipCertificate = async () => {
-  const query = {
-    size: 999,
-    current: 1,
-    studentId
-  }
-  const data = await certificateList(query)
-  info.value.certificate = data.records.length > 0 ? data.records.reverse()[0].studentInternshipCertificate : {}
-  loading.value = false
+  // 实习情况
+  getPracticeRecord(data.userId)
 }
 
-// 学生推荐信
-const getRecommendation = async () => {
-  const query = {
-    page: {
-      size: 9999,
-      current: 1
-    },
-    entity: {
-      studentId
-    }
-  }
-  const data = await recommendationList(query)
-  info.value.commendation = data.records.length > 0 ? data.records.reverse()[0].entity : {}
-}
+const statusList = ref([])
+onMounted(async () => {
+  // 状态字典
+  const { data } = await getDict('student_practice_status')
+  statusList.value = data || []
 
-const handleClick = (item) => {
-  console.log('handleClick->item:', item)
-}
+  getCvDetail()
+})
 
+// 跳转企业详情
+const handleEnterprise = (enterpriseId) => {
+  if (!enterpriseId) return
+  window.open(`/recruit/personal/company/details/${enterpriseId}?key=briefIntroduction`)
+}
 </script>
+
 <style lang="scss" scoped>
-.operate {
-  width: 240px;
-  height: 500px; // 272px
-  position: sticky;
-  top: 60px;
+.v-card {
+  width: 940px;
 }
 </style>