Files
school-developer/src/views/recruit/recruitstudentsignup/list.vue
guochunsi 0063894c8e a
2026-01-19 18:01:21 +08:00

443 lines
13 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div>
<!-- 搜索表单 -->
<el-form :model="queryForm" inline ref="searchFormRef">
<el-form-item label="招生计划" prop="groupId">
<el-select v-model="queryForm.groupId" filterable clearable placeholder="请选择招生计划">
<el-option
v-for="item in planList"
:key="item.id"
:label="item.groupName"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="学院" prop="deptCode">
<el-select v-model="queryForm.deptCode" filterable clearable placeholder="请选择学院">
<el-option
v-for="item in deptList"
:key="item.deptCode"
:label="item.deptName"
:value="item.deptCode"
/>
</el-select>
</el-form-item>
<el-form-item label="录取专业" prop="confirmedMajor">
<el-select v-model="queryForm.confirmedMajor" filterable clearable placeholder="请选择录取专业">
<el-option
v-for="item in planMajorList"
:key="item.majorCode"
:label="item.majorName + '(' + item.learnYear + '年制)'"
:value="item.majorCode"
/>
</el-select>
</el-form-item>
<el-form-item label="唯一号/姓名/身份证号" prop="search">
<el-input v-model="queryForm.search" clearable placeholder="唯一号/姓名/身份证号" />
</el-form-item>
<el-form-item label="住宿范围" prop="isOutFw">
<el-select v-model="queryForm.isOutFw" filterable clearable placeholder="请选择住宿范围">
<el-option
v-for="item in isOutFwList"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item label="是否发送短信" prop="isSend">
<el-select v-model="queryForm.isSend" filterable clearable placeholder="请选择是否发送短信">
<el-option
v-for="item in isSendList"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item label="性别" prop="gender">
<el-select v-model="queryForm.gender" filterable clearable placeholder="请选择性别">
<el-option
v-for="item in sexy"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="getDataList">查询</el-button>
<el-button icon="Refresh" class="ml10" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<!-- 操作按钮 -->
<div class="mb15">
<el-button
v-if="permissions.recruitStuDorm"
icon="Setting"
@click="setDormFW"
>
设置住宿范围
</el-button>
<el-button
v-if="permissions.recruitStuDorm"
type="danger"
plain
icon="Location"
class="ml10"
@click="yjOut"
>
一键判断住宿范围
</el-button>
<el-button
v-if="permissions.recruitStuDormMess"
type="danger"
plain
icon="Message"
class="ml10"
@click="yjSend"
>
批量发送短信
</el-button>
<el-button
type="warning"
plain
icon="Download"
class="ml10"
@click="handleExport"
>
名单导出
</el-button>
</div>
<!-- 表格 -->
<el-table
ref="tableRef"
:data="state.dataList"
v-loading="state.loading"
border
stripe
:cell-style="tableStyle.cellStyle"
:header-cell-style="tableStyle.headerCellStyle"
>
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="serialNumber" label="唯一号" width="100" align="center" show-overflow-tooltip />
<el-table-column prop="name" label="姓名" width="100" align="center" show-overflow-tooltip />
<el-table-column prop="gender" label="性别" width="80" align="center" show-overflow-tooltip>
<template #default="scope">
<GenderTag :sex="scope.row.gender" />
</template>
</el-table-column>
<el-table-column prop="idNumber" label="身份证号" width="180" align="center" show-overflow-tooltip />
<el-table-column prop="deptCode" label="学院" width="120" align="center" show-overflow-tooltip>
<template #default="scope">
{{ getDeptName(scope.row.deptCode) }}
</template>
</el-table-column>
<el-table-column prop="homeAddressDetail" label="家庭地址" align="center" show-overflow-tooltip />
<el-table-column prop="isOutFw" label="范围" width="100" align="center" show-overflow-tooltip>
<template #default="scope">
<span v-if="scope.row.isOutFw == 0">待确认</span>
<span v-if="scope.row.isOutFw == 1">范围内</span>
<span v-if="scope.row.isOutFw == 2">范围外</span>
</template>
</el-table-column>
<el-table-column prop="isSd" label="手动设置" width="100" align="center" show-overflow-tooltip>
<template #default="scope">
<span v-if="scope.row.isSd == 0">未设置</span>
<span v-if="scope.row.isSd == 1">已设置</span>
</template>
</el-table-column>
<el-table-column prop="isSend" label="发送短信" width="100" align="center" show-overflow-tooltip>
<template #default="scope">
<span v-if="scope.row.isSend == 0">未发送</span>
<span v-if="scope.row.isSend == 1">已发送</span>
</template>
</el-table-column>
<el-table-column label="操作" width="300" align="center" fixed="right">
<template #default="scope">
<el-button
v-if="permissions.recruitStuDormSd && scope.row.isOutFw != '1'"
type="primary"
link
icon="CircleCheck"
@click="setFw(scope.row, 1)"
>
设为范围内
</el-button>
<el-button
v-if="permissions.recruitStuDormSd && scope.row.isOutFw != '2'"
type="primary"
link
icon="Close"
@click="setFw(scope.row, 2)"
>
设为范围外
</el-button>
<el-button
type="primary"
link
icon="Location"
@click="baiduMap(scope.row)"
>
家庭地址
</el-button>
<el-button
v-if="permissions.recruitStuDormDel"
type="danger"
link
icon="Delete"
@click="deleteHandle(scope.row.id)"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<pagination
v-bind="state.pagination"
@current-change="currentChangeHandle"
@size-change="sizeChangeHandle"
/>
<DormFW ref="dormFWRef" />
<ShowMap ref="baiduMapRef" />
</div>
</template>
<script setup lang="ts" name="recruitstudentsignupList">
import { ref, reactive, computed, onMounted, nextTick, defineAsyncComponent } from 'vue'
import { storeToRefs } from 'pinia'
import { useUserInfo } from '/@/stores/userInfo'
import { BasicTableProps, useTable } from '/@/hooks/table'
import { useMessage, useMessageBox } from '/@/hooks/message'
import { useDict } from '/@/hooks/dict'
import { getLabelValue } from '/@/utils/dictLabel'
import { getList } from '/@/api/recruit/recruitstudentplangroup'
import { fetchListStuDorm, yjOut as yjOutApi, setFw as setFwApi, delFw, yjSend as yjSendApi } from '/@/api/recruit/recruitstudentsignup'
import { getDeptList } from '/@/api/basic/basicclass'
const GenderTag = defineAsyncComponent(() => import('/@/components/GenderTag/index.vue'))
const DormFW = defineAsyncComponent(() => import('./dormFW.vue'))
const ShowMap = defineAsyncComponent(() => import('./showMap.vue'))
// 使用 Pinia store
const userInfoStore = useUserInfo()
const { userInfos } = storeToRefs(userInfoStore)
// 创建权限对象
const permissions = computed(() => {
const perms: Record<string, boolean> = {}
userInfos.value.authBtnList.forEach((perm: string) => {
perms[perm] = true
})
return perms
})
// 消息提示 hooks
const message = useMessage()
const messageBox = useMessageBox()
// 字典数据
const { sexy } = useDict('sexy')
// 表格引用
const tableRef = ref()
const searchFormRef = ref()
const dormFWRef = ref()
const baiduMapRef = ref()
// 数据
const planList = ref<any[]>([])
const planMajorList = ref<any[]>([])
const deptList = ref<any[]>([])
const isOutFwList = ref([{ label: '待确认', value: '0' }, { label: '范围内', value: '1' }, { label: '范围外', value: '2' }])
const isSendList = ref([{ label: '未发送', value: 0 }, { label: '已发送', value: 1 }])
// 查询表单
const queryForm = reactive({
groupId: '',
deptCode: '',
confirmedMajor: '',
search: '',
isOutFw: '',
isSend: null,
gender: ''
})
// 弹窗状态DormFW 和 ShowMap 组件内部自己管理显示状态)
// 获取学院名称
const getDeptName = (deptCode: string) => {
const item = deptList.value.find(item => item.deptCode === deptCode)
return item ? item.deptName : ''
}
// 表格状态
const state: BasicTableProps = reactive<BasicTableProps>({
queryForm: queryForm,
pageList: async (params: any) => {
const response = await fetchListStuDorm(params)
return {
data: {
records: response.data.records,
total: response.data.total
}
}
},
createdIsNeed: false,
dataList: [],
loading: false,
pagination: {
current: 1,
size: 10,
total: 0,
pageSizes: [1, 10, 20, 50, 100, 200],
layout: 'total, sizes, prev, pager, next, jumper'
}
})
// 使用 table hook
const { getDataList, currentChangeHandle, sizeChangeHandle, tableStyle, downBlobFile } = useTable(state)
// 初始化
const init = async () => {
try {
// 查询二级学院信息
const deptData = await getDeptList()
deptList.value = deptData.data || []
// 获取招生计划列表
const planData = await getList()
planList.value = planData.data || []
if (planList.value.length > 0) {
queryForm.groupId = planList.value[0].id
}
getDataList()
} catch (error) {
message.error('初始化失败')
}
}
// 设置住宿范围
const setFw = async (row: any, type: number) => {
const title = type == 1 ? '范围内' : '范围外'
try {
await messageBox.confirm(`是否确认设置${title}?请谨慎操作`)
await setFwApi({ id: row.id, isOutFw: type })
message.success('操作成功')
getDataList()
} catch {
// 用户取消
}
}
// 设置住宿范围窗口
const setDormFW = () => {
nextTick(() => {
dormFWRef.value?.init()
})
}
// 一键判断住宿范围
const yjOut = async () => {
if (!queryForm.groupId) {
message.warning('招生计划不能为空')
return
}
try {
await messageBox.confirm('是否确认一键判断是否超出住宿范围?请谨慎操作')
await yjOutApi({ groupId: queryForm.groupId })
message.success('操作成功')
getDataList()
} catch {
// 用户取消
}
}
// 批量发送短信
const yjSend = async () => {
if (!queryForm.groupId) {
message.warning('招生计划不能为空')
return
}
try {
await messageBox.confirm('是否确认批量发送短信通知?请谨慎操作')
await yjSendApi({ groupId: queryForm.groupId })
message.success('操作成功')
getDataList()
} catch {
// 用户取消
}
}
// 百度地图
const baiduMap = (row: any) => {
nextTick(() => {
baiduMapRef.value?.init(row)
})
}
// 导出
const handleExport = async () => {
if (!queryForm.groupId) {
message.warning('招生计划不能为空')
return
}
try {
await downBlobFile(
'/recruit/recruitstudentsignup/stuDormExport',
queryForm,
'新生住宿名单导出.xls'
)
} catch (error: any) {
message.error(error.msg || '导出失败')
}
}
// 重置查询
const resetQuery = () => {
searchFormRef.value?.resetFields()
queryForm.groupId = ''
queryForm.deptCode = ''
queryForm.confirmedMajor = ''
queryForm.search = ''
queryForm.isOutFw = ''
queryForm.isSend = null
queryForm.gender = ''
if (planList.value.length > 0) {
queryForm.groupId = planList.value[0].id
}
getDataList()
}
// 删除
const deleteHandle = async (id: string) => {
try {
await messageBox.confirm('是否确认删除本条数据?请谨慎操作')
await delFw(id)
message.success('删除成功')
getDataList()
} catch {
// 用户取消
}
}
onMounted(() => {
init()
})
</script>
<style lang="scss" scoped>
</style>