123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219 |
- <!-- 学生列表 -->
- <template>
- <v-card class="px-3">
- <!-- 筛选条件 -->
- <div class="d-flex justify-space-between mt-8 mb-10">
- <div class="d-flex align-center">
- <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="handleReset">重 置</v-btn>
- <v-btn class="half-button ml-3" prepend-icon="mdi-refresh" variant="outlined" color="warning" @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> -->
- </div>
-
- <!-- 列表 -->
- <div class="mt-5" style="min-height: 500px;">
- <CtTable
- :items="tableData"
- :headers="headers"
- :loading="loading"
- :elevation="0"
- :is-tools="false"
- :showPage="true"
- :total="total"
- :page-info="query"
- itemKey="id"
- @pageHandleChange="handleChangePage"
- >
- <template #studentName="{ item }">
- <div class="d-flex align-center defaultLink" @click="studentDetails(item.id)">
- <v-avatar size="40" :image="getUserAvatar(item?.person?.avatar, item?.person?.sex)"></v-avatar>
- <span class="ml-3">{{ item?.person?.name }}</span>
- </div>
- </template>
- <template #actions="{ item }">
- <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>
- </div>
- <v-navigation-drawer v-model="showDetail" absolute location="right" rounded temporary width="700" class="pa-5">
- <div class="resume-header" style="height: 60px;">
- <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, onMounted } from 'vue'
- import Snackbar from '@/plugins/snackbar'
- import { getUserAvatar } from '@/utils/avatar'
- import { studentList, getSchoolOrganizationList, getStudentPracticeReportById, getStudentPracticeCompanyList } from '@/api/school'
- import { formatName } from '@/utils/getText'
- const loading = ref(false)
- const query = ref({
- pageSize: 10,
- pageNo: 1,
- schoolId: JSON.parse(localStorage.getItem('schoolInfo'))?.schoolId,
- name: null,
- schoolDeptId: null
- })
- const studentNameItem = ref({
- type: 'text',
- width: 300,
- label: '请输入学生姓名搜索',
- clearable: false,
- 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: '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) => {
- const result = await studentList(query.value)
- tableData.value = result.list || []
- total.value = result.total
- if (isRefresh) Snackbar.success('刷新成功')
- }
- // 分页
- const handleChangePage = (val) => {
- query.value.pageNo = val
- getData()
- }
- // 查询
- const handleSearch = (refresh = false) => {
- query.value.pageNo = 1
- getData(refresh)
- }
- // 重置
- const handleReset = () => {
- query.value.pageNo = 1
- query.value.name = null
- query.value.schoolDeptId = null
- getData()
- }
- 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 getSchoolDepartment = async () => {
- const schoolId = schoolInfo.value?.schoolId || null
- if (!schoolId) return Snackbar.warning('获取学校信息失败!')
-
- const data = await getSchoolOrganizationList({ schoolId, type: 0 })
- schoolDepartmentItem.value.items = data || []
- }
- onMounted(() => {
- getSchoolDepartment()
- getData()
- })
- const studentDetails = (id) => {
- if (id) window.open(`/recruit/teacher/studentList/detail/${id}`)
- }
- // 实习报告
- 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);
- font-weight: 600;
- font-size: 16px;
- }
- .left {
- min-width: 200px;
- }
- </style>
|