学生、本校老师新增数据,批量分配饭卡、多增几条外校老师查询条件

This commit is contained in:
Qi 2025-06-04 16:48:09 +08:00
parent 205d11df74
commit 3d7b36df1c
6 changed files with 208 additions and 23 deletions

View File

@ -136,6 +136,22 @@ export const formSchema: FormSchema[] = [
return [{ required: true, message: '请输入手机号!' }]; return [{ required: true, message: '请输入手机号!' }];
}, },
}, },
{
label: '学科',
field: 'majorId',
component: 'Select',
componentProps: {
options: [
{ label: '语文', value: 1 },
{ label: '地理', value: 4 },
{ label: '历史', value: 7 },
{ label: '政治', value: 8 },
],
},
dynamicRules: ({ model, schema }) => {
return [{ required: true, message: '请选择学科!' }];
},
},
{ {
label: '所属分组', label: '所属分组',
field: 'groupId', field: 'groupId',
@ -157,7 +173,7 @@ export const formSchema: FormSchema[] = [
//}, //},
{ {
label: '是否第一次阅卷', label: '是否第一次阅卷',
field: 'status', field: 'checked',
component: 'RadioGroup', component: 'RadioGroup',
componentProps: { componentProps: {
options: [ options: [
@ -165,9 +181,9 @@ export const formSchema: FormSchema[] = [
{ label: '否', value: 1 }, { label: '否', value: 1 },
], ],
}, },
//dynamicRules: ({ model, schema }) => { dynamicRules: ({ model, schema }) => {
// return [{ required: true, message: '请选择是否第一次阅卷!' }]; return [{ required: true, message: '请选择是否第一次阅卷!' }];
//}, },
}, },
// TODO 主键隐藏字段目前写死为ID // TODO 主键隐藏字段目前写死为ID
{ {

View File

@ -159,9 +159,9 @@ export const formSchema: FormSchema[] = [
{ label: '否', value: 0 }, { label: '否', value: 0 },
], ],
}, },
//dynamicRules: ({ model, schema }) => { dynamicRules: ({ model, schema }) => {
// return [{ required: true, message: '请选择是否第一次阅卷!' }]; return [{ required: true, message: '请选择是否第一次阅卷!' }];
//}, },
}, },
{ {
label: '所属分组', label: '所属分组',

View File

@ -16,6 +16,7 @@ enum Api {
cancelCheckIn = '/cees/ceesWaiTeacher/cancelCheckIn', cancelCheckIn = '/cees/ceesWaiTeacher/cancelCheckIn',
confirmCheckIn = '/cees/ceesWaiTeacher/confirmCheckIn', confirmCheckIn = '/cees/ceesWaiTeacher/confirmCheckIn',
batchGroup = '/cees/ceesWaiTeacher/batchGroup', batchGroup = '/cees/ceesWaiTeacher/batchGroup',
batchMealCard = '/cees/ceesWaiTeacher/batchMealCard',
} }
export const updateDormitory = (id, dormitory) => defHttp.get({ url: Api.updateDormitory, params: { id, dormitory } }); // ✅ 将参数包装为独立的对象 }); export const updateDormitory = (id, dormitory) => defHttp.get({ url: Api.updateDormitory, params: { id, dormitory } }); // ✅ 将参数包装为独立的对象 });
@ -29,6 +30,11 @@ export const getGroup = () =>
defHttp.get({ url: '/cees/ceesGroup/list' }).then((res) => { defHttp.get({ url: '/cees/ceesGroup/list' }).then((res) => {
return res.records; return res.records;
}); });
//获取宿舍
export const getDormitory = () =>
defHttp.get({ url: '/CEES/ceesDormitoryInfo/list' }).then((res) => {
return res.records;
});
/** /**
* api * api
* @param params * @param params
@ -89,6 +95,25 @@ export const batchGroup = (params, handleSuccess) => {
}, },
}); });
}; };
/**
*
* @param params
*/
export const batchMealCard = (params, handleSuccess) => {
console.log('params', params);
createConfirm({
iconType: 'warning',
title: '确认分配饭卡',
content: '是否分配饭卡选中数据',
okText: '确认',
cancelText: '取消',
onOk: () => {
return defHttp.post({ url: Api.batchMealCard, data: params }).then(() => {
handleSuccess();
});
},
});
};
//更新分组中间表 //更新分组中间表
export const updateGroupUser = (params) => { export const updateGroupUser = (params) => {

View File

@ -2,18 +2,27 @@ import { BasicColumn } from '/@/components/Table';
import { FormSchema } from '/@/components/Table'; import { FormSchema } from '/@/components/Table';
import { rules } from '/@/utils/helper/validator'; import { rules } from '/@/utils/helper/validator';
import { render } from '/@/utils/common/renderUtils'; import { render } from '/@/utils/common/renderUtils';
import { ref, onMounted, reactive } from 'vue'; import { ref, computed, onMounted, reactive } from 'vue';
import { usePermission } from '/@/hooks/web/usePermission'; import { usePermission } from '/@/hooks/web/usePermission';
const { hasPermission } = usePermission(); const { hasPermission } = usePermission();
const groupOptions = ref(); //const groupOptions = ref();
export const groupOptions = ref<{ label: string; value: number }[]>([]);
// 创建一个简单的事件总线 // 创建一个简单的事件总线
export const updateGroupOptions = reactive({ export const updateGroupOptions = reactive({
updateGroupOptions(newOptions: any) { updateGroupOptions(newOptions: { label: string; value: number }[]) {
groupOptions.value = newOptions; groupOptions.value = newOptions;
}, },
}); });
export const dormitoryOptions = ref<{ label: string; value: number }[]>([]);
// 创建一个简单的事件总线
export const updatedormitoryOptions = reactive({
updatedormitoryOptions(newOptions: { label: string; value: number }[]) {
dormitoryOptions.value = newOptions;
},
});
// 计算年龄的函数 // 计算年龄的函数
function calculateAge(birthday: string) { function calculateAge(birthday: string) {
@ -246,17 +255,17 @@ export const columns: BasicColumn[] = [
]; ];
//查询数据 //查询数据
export const searchFormSchema: FormSchema[] = [ export const searchFormSchema: FormSchema[] = [
//{ {
// label: '学科', label: '用户身份码',
// field: 'majorId', component: 'Input',
// component: 'JRangeNumber', field: 'userId',
// //colProps: {span: 6}, colProps: { span: 6 },
//}, },
{ {
label: '姓名', label: '姓名',
field: 'userName', field: 'userName',
component: 'Input', component: 'Input',
//colProps: {span: 6}, colProps: { span: 6 },
}, },
{ {
label: '学科', label: '学科',
@ -274,6 +283,34 @@ export const searchFormSchema: FormSchema[] = [
return hasPermission('waiTeacher:majorId:select'); return hasPermission('waiTeacher:majorId:select');
}, },
}, },
{
label: '手机号',
field: 'phone',
component: 'Input',
},
{
label: '所属分组',
component: 'Select',
field: 'groupId',
colProps: { span: 6 },
componentProps: {
placeholder: '请选择分组',
options: computed(() => groupOptions.value), // ✅ 变成响应式
showSearch: true,
filterOption: (input, option) => option.label.toLowerCase().includes(input.toLowerCase()),
},
},
{
label: '住宿信息',
field: 'dormitoryId',
component: 'Select',
componentProps: {
placeholder: '请选择住宿信息',
options: computed(() => dormitoryOptions.value), // ✅ 变成响应式
showSearch: true,
filterOption: (input, option) => option.label.toLowerCase().includes(input.toLowerCase()),
},
},
]; ];
//表单数据 //表单数据
export const formSchema: FormSchema[] = [ export const formSchema: FormSchema[] = [

View File

@ -22,6 +22,11 @@
<Icon icon="ant-design:usergroup-add-outlined" /> <Icon icon="ant-design:usergroup-add-outlined" />
分组 分组
</a-menu-item> </a-menu-item>
<TransactionOutlined />
<a-menu-item key="1" @click="batchHandleMealCard">
<Icon icon="ant-design:transaction-outlined" />
分配饭卡
</a-menu-item>
<a-menu-item key="1" @click="batchHandleDelete" v-if="hasPermission('waiTeacher:batchDelete')"> <a-menu-item key="1" @click="batchHandleDelete" v-if="hasPermission('waiTeacher:batchDelete')">
<Icon icon="ant-design:delete-outlined" /> <Icon icon="ant-design:delete-outlined" />
删除 删除
@ -96,6 +101,7 @@
<!-- 表单区域 --> <!-- 表单区域 -->
<CeesWaiTeacherModal @register="registerModal" @success="handleSuccess" /> <CeesWaiTeacherModal @register="registerModal" @success="handleSuccess" />
<GroupSelectModal ref="groupModalRef" @register="registerGroupModal" @success="handleGroupSuccess" /> <GroupSelectModal ref="groupModalRef" @register="registerGroupModal" @success="handleGroupSuccess" />
<MealCardModal ref="mealCardModalRef" @register="registerMealCardModal" @success="handleMealCardSuccess" />
</div> </div>
</template> </template>
@ -104,9 +110,10 @@
import { BasicTable, useTable, TableAction } from '/@/components/Table'; import { BasicTable, useTable, TableAction } from '/@/components/Table';
import { useModal } from '/@/components/Modal'; import { useModal } from '/@/components/Modal';
import GroupSelectModal from './components/GroupSelectModal.vue'; import GroupSelectModal from './components/GroupSelectModal.vue';
import MealCardModal from './components/MealCardSelectModal.vue';
import { useListPage } from '/@/hooks/system/useListPage'; import { useListPage } from '/@/hooks/system/useListPage';
import CeesWaiTeacherModal from './components/CeesWaiTeacherModal.vue'; import CeesWaiTeacherModal from './components/CeesWaiTeacherModal.vue';
import { columns, searchFormSchema, superQuerySchema, updateGroupOptions } from './CeesWaiTeacher.data'; import { columns, searchFormSchema, superQuerySchema, updateGroupOptions, updatedormitoryOptions } from './CeesWaiTeacher.data';
import { import {
list, list,
deleteOne, deleteOne,
@ -114,10 +121,12 @@
getImportUrl, getImportUrl,
getExportUrl, getExportUrl,
getGroup, getGroup,
getDormitory,
updateDormitory, updateDormitory,
cancelCheckIn, cancelCheckIn,
confirmCheckIn, confirmCheckIn,
batchGroup, batchGroup,
batchMealCard,
} from './CeesWaiTeacher.api'; } from './CeesWaiTeacher.api';
import { selectBySex } from '/@/views/cees/dormitory/CeesDormitoryInfo.api'; import { selectBySex } from '/@/views/cees/dormitory/CeesDormitoryInfo.api';
import { downloadFile } from '/@/utils/common/renderUtils'; import { downloadFile } from '/@/utils/common/renderUtils';
@ -136,7 +145,10 @@
//model //model
const [registerModal, { openModal }] = useModal(); const [registerModal, { openModal }] = useModal();
const [registerGroupModal, { openModal: openGroupModal }] = useModal(); const [registerGroupModal, { openModal: openGroupModal }] = useModal();
const [registerMealCardModal, { openModal: openMealCardModal }] = useModal();
const groupModalRef = ref<any>(null); const groupModalRef = ref<any>(null);
const mealCardModalRef = ref<any>(null);
//table //table
const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({ const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({
tableProps: { tableProps: {
@ -201,18 +213,27 @@
// //
const groupOptions = ref<{ label: string; value: number }[]>([]); const groupOptions = ref<{ label: string; value: number }[]>([]);
const dormitoryOptions = ref<{ label: string; value: number }[]>([]);
onMounted(async () => { onMounted(async () => {
console.log('组件已加载'); console.log('组件已加载');
try { try {
const res = await getGroup(); const resGroup = await getGroup();
console.log('获取分组数据成功:', res); console.log('获取分组数据成功:', resGroup);
groupOptions.value = res.map((group) => ({ groupOptions.value = resGroup.map((group) => ({
label: group.name, // name label: group.name, // name
value: group.id, // ID id value: group.id, // ID id
})); }));
console.log('分组数据:', groupOptions.value);
updateGroupOptions.updateGroupOptions(groupOptions.value); updateGroupOptions.updateGroupOptions(groupOptions.value);
const resDormitory = await getDormitory();
console.log('获取宿舍数据成功:', resDormitory);
dormitoryOptions.value = resDormitory.map((item) => ({
label: item.dormitory, // name
value: item.id, // ID id
}));
updatedormitoryOptions.updatedormitoryOptions(dormitoryOptions.value);
console.log('分组数据:', groupOptions.value);
console.log('宿舍数据:', dormitoryOptions.value);
} catch (error) { } catch (error) {
console.error('获取分组数据失败:', error); console.error('获取分组数据失败:', error);
} }
@ -287,6 +308,16 @@
groupModalRef.value?.setGroupOptions(groupOptions.value); groupModalRef.value?.setGroupOptions(groupOptions.value);
openGroupModal(true); openGroupModal(true);
} }
/**
* 批量设置饭卡事件
*/
async function batchHandleMealCard() {
if (selectedRowKeys.value.length < 1) {
message.warning('请至少选择一个用户!');
return;
}
openMealCardModal(true);
}
/** /**
* 分组选好后的确认事件 * 分组选好后的确认事件
*/ */
@ -299,6 +330,21 @@
console.error('批量分组失败:', error); console.error('批量分组失败:', error);
} }
} }
/**
* 设置饭卡后的确认事件
*/
async function handleMealCardSuccess({ min, max }) {
try {
if (min == null || max == null || min > max) {
message.warning('无效的饭卡范围');
return;
}
await batchMealCard({ ids: selectedRowKeys.value, min, max }, handleSuccess); //
} catch (e) {
console.error(e);
message.error('添加失败');
}
}
/** /**
* 成功回调 * 成功回调
*/ */
@ -405,7 +451,7 @@
<Descriptions.Item label="车牌号">{record.carNumber}</Descriptions.Item> <Descriptions.Item label="车牌号">{record.carNumber}</Descriptions.Item>
<Descriptions.Item label="饭卡">{record.mealCard}</Descriptions.Item> <Descriptions.Item label="饭卡">{record.mealCard}</Descriptions.Item>
<Descriptions.Item label="所属分组">{record.groupId}</Descriptions.Item> <Descriptions.Item label="所属分组">{record.groupName}</Descriptions.Item>
<Descriptions.Item label="住宿信息"> <Descriptions.Item label="住宿信息">
<div className="custom-select-wrapper"> <div className="custom-select-wrapper">
<select <select

View File

@ -0,0 +1,61 @@
<template>
<BasicModal v-bind="$attrs" @register="registerModal" title="设置饭卡范围" @ok="handleOk" :canFullscreen="false">
<div class="meal-card-modal">
<div class="form-wrapper">
<a-form :model="formState" layout="vertical">
<a-form-item label="饭卡最小值" required>
<a-input v-model:value="formState.min" placeholder="请输入最小值" />
</a-form-item>
<a-form-item label="饭卡最大值" required>
<a-input v-model:value="formState.max" placeholder="请输入最大值" />
</a-form-item>
</a-form>
</div>
</div>
</BasicModal>
</template>
<script lang="ts" setup>
import { ref } from 'vue';
import { BasicModal, useModalInner } from '/@/components/Modal';
import { message } from 'ant-design-vue';
const emit = defineEmits(['register', 'success']);
const formState = ref({
min: null,
max: null,
});
const [registerModal, { closeModal }] = useModalInner(() => {
formState.value.min = null;
formState.value.max = null;
});
function handleOk() {
const { min, max } = formState.value;
if (min == null || max == null || min > max) {
message.warning('请输入有效的饭卡最小值和最大值');
return;
}
emit('success', { min, max });
closeModal();
}
</script>
<style lang="less" scoped>
.meal-card-modal {
padding: 20px 24px;
.form-wrapper {
display: flex;
justify-content: center;
align-items: center;
}
.select-width {
width: 200px;
}
}
</style>