443 lines
13 KiB
Vue
443 lines
13 KiB
Vue
<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>
|