饭卡、外校、宿舍

This commit is contained in:
Qi 2025-06-06 18:50:31 +08:00
parent 819800bef2
commit e0eae6fa1c
6 changed files with 204 additions and 23 deletions

View File

@ -12,6 +12,7 @@ enum Api {
importExcel = '/CEES/ceesDormitoryInfo/importExcel', importExcel = '/CEES/ceesDormitoryInfo/importExcel',
exportXls = '/CEES/ceesDormitoryInfo/exportXls', exportXls = '/CEES/ceesDormitoryInfo/exportXls',
selectBySex = '/CEES/ceesDormitoryInfo/selectBySex', selectBySex = '/CEES/ceesDormitoryInfo/selectBySex',
setDormAndSubjectBatch = '/CEES/ceesDormitoryInfo/setDormAndSubjectBatch',
} }
/** /**
* 宿 * 宿
@ -61,6 +62,47 @@ export const batchDelete = (params, handleSuccess) => {
}, },
}); });
}; };
/**
*
* @param params
*/
export const setDormAndSubject = (params, handleSuccess) => {
console.log(params);
// 学科选项映射
const subjectOptions = [
{ label: '语文', value: 1 },
{ label: '地理', value: 4 },
{ label: '历史', value: 7 },
{ label: '政治', value: 8 },
];
// 获取当前选中的学科名称
const selectedSubject = subjectOptions.find((item) => item.value === params.majorId)?.label || '';
const redSubject = `<span style="color: red">${selectedSubject}</span>`;
createConfirm({
iconType: 'warning',
title: `设置学科`,
content: `是否为选中宿舍数据设置为${redSubject}学科宿舍`,
okText: '确认',
cancelText: '取消',
onOk: () => {
return defHttp
.post(
{
url: Api.setDormAndSubjectBatch,
data: params,
},
{ joinParamsToUrl: true }
)
.then(() => {
handleSuccess();
});
},
});
};
/** /**
* *
* @param params * @param params

View File

@ -48,7 +48,7 @@ export const searchFormSchema: FormSchema[] = [
{ {
label: '宿舍信息', label: '宿舍信息',
field: 'dormitory', field: 'dormitory',
component: 'Input', component: 'JInput',
}, },
{ {
label: '所属学科', label: '所属学科',
@ -58,6 +58,8 @@ export const searchFormSchema: FormSchema[] = [
options: [ options: [
{ label: '语文', value: 1 }, { label: '语文', value: 1 },
{ label: '地理', value: 4 }, { label: '地理', value: 4 },
{ label: '历史', value: 7 },
{ label: '政治', value: 8 },
], ],
}, },
ifShow: ({ values }) => { ifShow: ({ values }) => {
@ -85,6 +87,7 @@ export const formSchema: FormSchema[] = [
{ label: '女', value: 1 }, { label: '女', value: 1 },
], ],
}, },
defaultValue: 1,
dynamicRules: ({ model, schema }) => { dynamicRules: ({ model, schema }) => {
return [{ required: true, message: '请选择男/女!' }]; return [{ required: true, message: '请选择男/女!' }];
}, },
@ -93,6 +96,7 @@ export const formSchema: FormSchema[] = [
label: '宿舍人数', label: '宿舍人数',
field: 'dormitoryNum', field: 'dormitoryNum',
component: 'InputNumber', component: 'InputNumber',
defaultValue: 4,
dynamicRules: ({ model, schema }) => { dynamicRules: ({ model, schema }) => {
return [{ required: true, message: '请输入宿舍人数!' }]; return [{ required: true, message: '请输入宿舍人数!' }];
}, },
@ -108,6 +112,7 @@ export const formSchema: FormSchema[] = [
{ label: '已满', value: 1 }, { label: '已满', value: 1 },
], ],
}, },
defaultValue: 0,
dynamicRules: ({ model, schema }) => { dynamicRules: ({ model, schema }) => {
return [{ required: true, message: '请选择宿舍状态' }]; return [{ required: true, message: '请选择宿舍状态' }];
}, },
@ -124,9 +129,9 @@ export const formSchema: FormSchema[] = [
{ label: '政治', value: 8 }, { label: '政治', value: 8 },
], ],
}, },
dynamicRules: ({ model, schema }) => { //dynamicRules: ({ model, schema }) => {
return [{ required: true, message: '请选择所属学科!' }]; // return [{ required: true, message: '请选择所属学科!' }];
}, //},
}, },
// TODO 主键隐藏字段目前写死为ID // TODO 主键隐藏字段目前写死为ID
{ {

View File

@ -7,9 +7,37 @@
<a-button type="primary" @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增</a-button> <a-button type="primary" @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增</a-button>
<a-button type="primary" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button> <a-button type="primary" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
<j-upload-button type="primary" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button> <j-upload-button type="primary" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
<a-button type="primary" @click="batchHandleDelete" v-if="hasPermission('dormitory:batchDelete')" <a-dropdown>
>批量删除 <template #overlay>
</a-button> <a-menu>
<a-menu-item key="1" @click="openModalSubject">
<Icon icon="ant-design:usergroup-add-outlined" />
批量设置宿舍学科
</a-menu-item>
<a-modal title="批量设置宿舍学科" v-model:visible="visible" @ok="handleOk" @cancel="handleCancel" width="400">
<a-form :model="form" :label-col="{ span: 6 }" :wrapper-col="{ span: 16 }" label-align="left">
<a-form-item label="所属学科" name="majorId" :rules="[{ required: true, message: '请选择学科' }]">
<a-select v-model:value="form.majorId" placeholder="请选择学科" style="width: 100%">
<a-select-option v-for="item in options" :key="item.value" :value="item.value">
{{ item.label }}
</a-select-option>
</a-select>
</a-form-item>
</a-form>
</a-modal>
<a-menu-item key="1" @click="batchHandleDelete" v-if="hasPermission('dormitory:batchDelete')">
<Icon icon="ant-design:delete-outlined" />
批量删除
</a-menu-item>
</a-menu>
</template>
<a-button
>批量操作
<Icon icon="mdi:chevron-down" />
</a-button>
</a-dropdown>
<!--<a-button type="primary" @click="batchHandleDelete" v-if="hasPermission('dormitory:batchDelete')">批量删除 </a-button>-->
<!-- 高级查询 --> <!-- 高级查询 -->
<super-query :config="superQueryConfig" @search="handleSuperQuery" /> <super-query :config="superQueryConfig" @search="handleSuperQuery" />
</template> </template>
@ -44,7 +72,7 @@
import { useListPage } from '/@/hooks/system/useListPage'; import { useListPage } from '/@/hooks/system/useListPage';
import CeesDormitoryInfoModal from './components/CeesDormitoryInfoModal.vue'; import CeesDormitoryInfoModal from './components/CeesDormitoryInfoModal.vue';
import { columns, searchFormSchema, superQuerySchema } from './CeesDormitoryInfo.data'; import { columns, searchFormSchema, superQuerySchema } from './CeesDormitoryInfo.data';
import { list, deleteOne, batchDelete, getImportUrl, getExportUrl } from './CeesDormitoryInfo.api'; import { list, deleteOne, batchDelete, getImportUrl, getExportUrl, setDormAndSubject } from './CeesDormitoryInfo.api';
import { downloadFile } from '/@/utils/common/renderUtils'; import { downloadFile } from '/@/utils/common/renderUtils';
import { useUserStore } from '/@/store/modules/user'; import { useUserStore } from '/@/store/modules/user';
import { usePermission } from '/@/hooks/web/usePermission'; import { usePermission } from '/@/hooks/web/usePermission';
@ -88,6 +116,37 @@
success: handleSuccess, success: handleSuccess,
}, },
}); });
const visible = ref(false);
const form = reactive({
majorId: null,
});
const options = [
{ label: '语文', value: 1 },
{ label: '地理', value: 4 },
{ label: '历史', value: 7 },
{ label: '政治', value: 8 },
];
const openModalSubject = () => {
visible.value = true;
};
const handleCancel = () => {
visible.value = false;
};
const handleOk = async () => {
if (!form.majorId) {
message.warning('请选择学科');
return;
}
console.log('选择的学科 ID', form.majorId);
//
await setDormAndSubject({ ids: selectedRowKeys.value, majorId: form.majorId }, handleSuccess);
visible.value = false;
};
const [registerTable, { reload }, { rowSelection, selectedRowKeys }] = tableContext; const [registerTable, { reload }, { rowSelection, selectedRowKeys }] = tableContext;

View File

@ -17,6 +17,7 @@ enum Api {
confirmCheckIn = '/cees/ceesWaiTeacher/confirmCheckIn', confirmCheckIn = '/cees/ceesWaiTeacher/confirmCheckIn',
batchGroup = '/cees/ceesWaiTeacher/batchGroup', batchGroup = '/cees/ceesWaiTeacher/batchGroup',
batchMealCard = '/cees/ceesWaiTeacher/batchMealCard', batchMealCard = '/cees/ceesWaiTeacher/batchMealCard',
clearMealCardData = '/cees/ceesWaiTeacher/clearMealCardData',
} }
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 } }); // ✅ 将参数包装为独立的对象 });
@ -115,6 +116,26 @@ export const batchMealCard = (params, handleSuccess) => {
}); });
}; };
/**
*
* @param params
*/
export const clearMealCardData = (params, handleSuccess) => {
console.log('params', params);
createConfirm({
iconType: 'warning',
title: '确认清空饭卡数据',
content: '是否清空选中的饭卡数据',
okText: '确认',
cancelText: '取消',
onOk: () => {
return defHttp.post({ url: Api.clearMealCardData, data: params }).then(() => {
handleSuccess();
});
},
});
};
//更新分组中间表 //更新分组中间表
export const updateGroupUser = (params) => { export const updateGroupUser = (params) => {
return defHttp.post({ url: Api.updateGroupUser, params }); return defHttp.post({ url: Api.updateGroupUser, params });

View File

@ -22,11 +22,14 @@
<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"> <a-menu-item key="1" @click="batchHandleMealCard">
<Icon icon="ant-design:transaction-outlined" /> <Icon icon="ant-design:transaction-outlined" />
分配饭卡 分配饭卡
</a-menu-item> </a-menu-item>
<a-menu-item key="1" @click="batchClearMealCardData">
<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" />
删除 删除
@ -127,6 +130,7 @@
confirmCheckIn, confirmCheckIn,
batchGroup, batchGroup,
batchMealCard, batchMealCard,
clearMealCardData,
} 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';
@ -335,7 +339,14 @@
*/ */
async function handleMealCardSuccess({ min, max }) { async function handleMealCardSuccess({ min, max }) {
try { try {
if (min == null || max == null || min > max) { const minVal = Number(min);
const maxVal = Number(max);
console.log(minVal, maxVal);
console.log(minVal > maxVal);
if (isNaN(minVal) || isNaN(maxVal) || minVal > maxVal) {
console.log('111');
message.warning('无效的饭卡范围'); message.warning('无效的饭卡范围');
return; return;
} }
@ -345,6 +356,17 @@
message.error('添加失败'); message.error('添加失败');
} }
} }
/**
* 清空饭卡
*/
async function batchClearMealCardData() {
try {
await clearMealCardData({ ids: selectedRowKeys.value }, handleSuccess); //
} catch (e) {
console.error(e);
message.error('添加失败');
}
}
/** /**
* 成功回调 * 成功回调
*/ */
@ -378,16 +400,27 @@
const handleConfirm = (actionType) => { const handleConfirm = (actionType) => {
const isConfirmAction = actionType === 'confirm'; const isConfirmAction = actionType === 'confirm';
// 宿
let selectedDorm = record.dormitoryName;
Modal.confirm({ Modal.confirm({
title: isConfirmAction ? '请核对信息!!!' : '', title: isConfirmAction ? '请核对信息!!!' : '',
content: <ConfirmContent record={record} />, content: (
<ConfirmContent
record={record}
selectedDorm={selectedDorm}
onDormChange={(val) => (selectedDorm = val)} // 宿
/>
),
okText: isConfirmAction ? '确认报到' : '取消报到', okText: isConfirmAction ? '确认报到' : '取消报到',
cancelText: isConfirmAction ? '取消' : '关闭', cancelText: isConfirmAction ? '取消' : '关闭',
width: 800, width: 800,
onOk: () => { onOk: async () => {
if (isConfirmAction) { if (isConfirmAction) {
updateStatus(record.id); await updateStatus(record.id);
// 宿宿
if (selectedDorm !== record.dormitoryName) {
await updateDormitory(record.userId, selectedDorm);
}
} else { } else {
updateStatus(record.id, 'un'); updateStatus(record.id, 'un');
} }
@ -422,7 +455,7 @@
return actions; return actions;
} }
const ConfirmContent = ({ record }) => ( const ConfirmContent = ({ record, selectedDorm, onDormChange }) => (
<Descriptions <Descriptions
bordered bordered
size="small" size="small"
@ -455,11 +488,13 @@
<Descriptions.Item label="住宿信息"> <Descriptions.Item label="住宿信息">
<div className="custom-select-wrapper"> <div className="custom-select-wrapper">
<select <select
style={{ width: '100%' }}
className="custom-select" className="custom-select"
value={record.dormitoryName} value={selectedDorm}
disabled={record.dormitoryStatus === 0} // status disabled={record.dormitoryStatus === 0} // status
onFocus={() => record.dormitoryStatus !== 0 && handleFocus(record)} // focus onFocus={() => record.dormitoryStatus !== 0 && handleFocus(record)} // focus
onChange={(e) => handleChange(record.userId, e.target.value, record)} onChange={(e) => onDormChange(e.target.value)}
/*onChange={(e) => handleChange(record.userId, e.target.value, record)}*/
> >
{/* 禁用状态显示提示 */} {/* 禁用状态显示提示 */}
{record.dormitoryStatus === 0 ? ( {record.dormitoryStatus === 0 ? (
@ -550,10 +585,23 @@
// console.log(' :', dormitory.sysOrgCode); // console.log(' :', dormitory.sysOrgCode);
// console.log(' 宿:', dormitory.dormitoryNum); // console.log(' 宿:', dormitory.dormitoryNum);
//}); //});
dormOptions.value = response.map((dormitory) => ({ //dormOptions.value = response.map((dormitory) => ({
label: dormitory.dormitory, // label: `${dormitory.dormitory} ${dormitory.dormitoryNum}`,
value: dormitory.id, // value: dormitory.id,
})); //}));
dormOptions.value = [
//
{
label: '不分配宿舍',
value: null, // ''
disabled: false, //
},
// 宿
...response.map((dormitory) => ({
label: `${dormitory.dormitory} 剩余人数:${dormitory.dormitoryNum}`,
value: dormitory.id,
})),
];
} else { } else {
console.error('预期的响应应该是一个数组。'); console.error('预期的响应应该是一个数组。');
} }

View File

@ -34,11 +34,17 @@
function handleOk() { function handleOk() {
const { min, max } = formState.value; const { min, max } = formState.value;
if (min == null || max == null || min > max) { const minVal = Number(min);
const maxVal = Number(max);
console.log(minVal, maxVal);
console.log(minVal > maxVal);
if (isNaN(minVal) || isNaN(maxVal) || minVal > maxVal) {
console.log('111');
message.warning('请输入有效的饭卡最小值和最大值'); message.warning('请输入有效的饭卡最小值和最大值');
return; return;
} }
emit('success', { min, max }); emit('success', { min, max });
closeModal(); closeModal();
} }