提交代码
No files matched your search
|
After Width: | Height: | Size: 529 KiB |
|
After Width: | Height: | Size: 1.9 MiB |
|
After Width: | Height: | Size: 1.9 MiB |
|
After Width: | Height: | Size: 25 MiB |
|
After Width: | Height: | Size: 3.9 MiB |
|
After Width: | Height: | Size: 2.3 MiB |
|
After Width: | Height: | Size: 564 KiB |
|
After Width: | Height: | Size: 1.5 MiB |
|
After Width: | Height: | Size: 529 KiB |
|
After Width: | Height: | Size: 1.9 MiB |
|
After Width: | Height: | Size: 1.9 MiB |
@@ -429,7 +429,7 @@ const auditorList = ref<any[]>([]);
|
||||
/** 获取具有审核权限的人员列表 */
|
||||
const getAuditorList = async () => {
|
||||
try {
|
||||
const res = await listUsersByPermission('hq:hallAudit:list');
|
||||
const res = await listUsersByPermission('hq:hallAudit:hallAudit');
|
||||
auditorList.value = res.data || [];
|
||||
console.log('审核人员列表:', auditorList.value);
|
||||
} catch (error) {
|
||||
|
||||
@@ -174,6 +174,8 @@ const data = reactive<PageData<SatCategoryForm, SatCategoryQuery>>({
|
||||
categoryDesc: undefined,
|
||||
sortOrder: undefined,
|
||||
status: undefined,
|
||||
orderByColumn: 'createTime',
|
||||
isAsc: 'desc',
|
||||
params: {}
|
||||
},
|
||||
rules: {
|
||||
@@ -215,6 +217,9 @@ const handleQuery = () => {
|
||||
/** 重置按钮操作 */
|
||||
const resetQuery = () => {
|
||||
queryFormRef.value?.resetFields();
|
||||
// 保持排序设置
|
||||
queryParams.value.orderByColumn = 'createTime';
|
||||
queryParams.value.isAsc = 'desc';
|
||||
handleQuery();
|
||||
};
|
||||
|
||||
|
||||
@@ -319,7 +319,10 @@ const data = reactive<PageData<SatQuestionForm, SatQuestionQuery>>({
|
||||
isRequired: undefined,
|
||||
sortOrder: undefined,
|
||||
status: undefined,
|
||||
params: {}
|
||||
params: {
|
||||
orderByColumn: 'createTime',
|
||||
isAsc: 'desc'
|
||||
}
|
||||
},
|
||||
rules: {
|
||||
id: [{ required: true, message: '主键ID不能为空', trigger: 'blur' }],
|
||||
|
||||
@@ -1,5 +1,21 @@
|
||||
<template>
|
||||
<div class="app-container home">
|
||||
<!-- 上半部分:校园风景图片轮播 -->
|
||||
<div class="carousel-section">
|
||||
<el-carousel :interval="4000" type="card" height="400px" indicator-position="outside" arrow="always" class="campus-carousel">
|
||||
<el-carousel-item v-for="(image, index) in campusImages" :key="index">
|
||||
<div class="carousel-item">
|
||||
<img :src="image.url" :alt="image.title" class="carousel-image" />
|
||||
<div class="carousel-overlay">
|
||||
<h3 class="carousel-title">{{ image.title }}</h3>
|
||||
<p class="carousel-description">{{ image.description }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</el-carousel-item>
|
||||
</el-carousel>
|
||||
</div>
|
||||
|
||||
<!-- 下半部分:原有内容 -->
|
||||
<div class="construction-container">
|
||||
<div class="construction-content">
|
||||
<!-- 系统标题 -->
|
||||
@@ -58,8 +74,28 @@
|
||||
</template>
|
||||
|
||||
<script setup name="Index" lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import { Tools, Calendar, Service, Phone, Message } from '@element-plus/icons-vue';
|
||||
|
||||
// 校园风景图片数据
|
||||
const campusImages = [
|
||||
{
|
||||
url: '/assets/images/01.jpg',
|
||||
title: '校园正门',
|
||||
description: '绿意盎然的校园入口,展现学院的自然之美'
|
||||
},
|
||||
{
|
||||
url: '/assets/images/02.jpg',
|
||||
title: '校园风光',
|
||||
description: '现代化的校园建筑与自然景观的完美融合'
|
||||
},
|
||||
{
|
||||
url: '/assets/images/03.jpg',
|
||||
title: '校园全景',
|
||||
description: '鸟瞰校园全景,展现学院的整体风貌'
|
||||
}
|
||||
];
|
||||
|
||||
// 计算预计完成时间(当前时间后30天)
|
||||
const expectedDate = computed(() => {
|
||||
const date = new Date();
|
||||
@@ -75,16 +111,79 @@ const expectedDate = computed(() => {
|
||||
<style lang="scss" scoped>
|
||||
.home {
|
||||
min-height: calc(100vh - 200px);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
|
||||
}
|
||||
|
||||
// 上半部分:轮播图样式
|
||||
.carousel-section {
|
||||
padding: 40px 20px;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
backdrop-filter: blur(5px);
|
||||
}
|
||||
|
||||
.campus-carousel {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
border-radius: 16px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
|
||||
|
||||
:deep(.el-carousel__item) {
|
||||
border-radius: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.carousel-item {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
border-radius: 16px;
|
||||
}
|
||||
|
||||
.carousel-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.carousel-item:hover .carousel-image {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.carousel-overlay {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background: linear-gradient(transparent, rgba(0, 0, 0, 0.7));
|
||||
color: white;
|
||||
padding: 40px 30px 30px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.carousel-title {
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
margin: 0 0 10px 0;
|
||||
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.carousel-description {
|
||||
font-size: 16px;
|
||||
margin: 0;
|
||||
opacity: 0.9;
|
||||
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
// 下半部分:原有样式
|
||||
.construction-container {
|
||||
width: 100%;
|
||||
max-width: 800px;
|
||||
padding: 40px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.construction-content {
|
||||
@@ -212,6 +311,26 @@ const expectedDate = computed(() => {
|
||||
|
||||
// 响应式设计
|
||||
@media (max-width: 768px) {
|
||||
.carousel-section {
|
||||
padding: 20px 10px;
|
||||
}
|
||||
|
||||
.campus-carousel {
|
||||
height: 300px !important;
|
||||
}
|
||||
|
||||
.carousel-overlay {
|
||||
padding: 30px 20px 20px;
|
||||
}
|
||||
|
||||
.carousel-title {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.carousel-description {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.construction-container {
|
||||
padding: 20px;
|
||||
}
|
||||
@@ -237,6 +356,10 @@ const expectedDate = computed(() => {
|
||||
|
||||
// 深色主题适配
|
||||
html.dark {
|
||||
.carousel-section {
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.construction-content {
|
||||
background: rgba(30, 30, 30, 0.95);
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
|
||||
@@ -10,12 +10,12 @@
|
||||
<h3 class="title">{{ title }}</h3>
|
||||
<!-- <lang-select /> -->
|
||||
</div>
|
||||
<el-form-item v-if="tenantEnabled" prop="tenantId" class="el_select_coopr">
|
||||
<!-- <el-form-item v-if="tenantEnabled" prop="tenantId" class="el_select_coopr">
|
||||
<el-select v-model="loginForm.tenantId" filterable :placeholder="proxy.$t('login.selectPlaceholder')" style="width: 100%">
|
||||
<el-option v-for="item in tenantList" :key="item.tenantId" :label="item.companyName" :value="item.tenantId"></el-option>
|
||||
<template #prefix><svg-icon icon-class="company" class="el-input__icon input-icon" /></template>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form-item> -->
|
||||
<el-form-item prop="username">
|
||||
<el-input v-model="loginForm.username" type="text" auto-complete="off" :placeholder="proxy.$t('login.username')">
|
||||
<template #prefix><svg-icon icon-class="user" class="el-input__icon input-icon" /></template>
|
||||
|
||||
@@ -123,7 +123,7 @@
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
|
||||
<!-- 分页组件已移除,因为列表接口不支持分页 -->
|
||||
</el-card>
|
||||
<!-- 添加或修改学生信息收集批次对话框 -->
|
||||
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
|
||||
@@ -313,7 +313,6 @@ const showSearch = ref(true);
|
||||
const ids = ref<Array<string | number>>([]);
|
||||
const single = ref(true);
|
||||
const multiple = ref(true);
|
||||
const total = ref(0);
|
||||
|
||||
const queryFormRef = ref<ElFormInstance>();
|
||||
const stuColBatchFormRef = ref<ElFormInstance>();
|
||||
@@ -384,8 +383,6 @@ const initFormData: StuColBatchForm = {
|
||||
const data = reactive<PageData<StuColBatchForm, StuColBatchQuery>>({
|
||||
form: { ...initFormData },
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
batchName: undefined,
|
||||
status: undefined,
|
||||
collectionType: undefined,
|
||||
@@ -419,16 +416,13 @@ const getList = async () => {
|
||||
if (res && res.code === 200) {
|
||||
// 将返回的数据转换为表格需要的格式
|
||||
stuColBatchList.value = res.data || [];
|
||||
total.value = res.data ? res.data.length : 0;
|
||||
} else {
|
||||
stuColBatchList.value = [];
|
||||
total.value = 0;
|
||||
proxy?.$modal.msgError(res?.msg || '获取数据失败');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取学生可参与批次信息失败:', error);
|
||||
stuColBatchList.value = [];
|
||||
total.value = 0;
|
||||
proxy?.$modal.msgError('获取数据失败');
|
||||
} finally {
|
||||
loading.value = false;
|
||||
@@ -449,7 +443,6 @@ const reset = () => {
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
const handleQuery = () => {
|
||||
queryParams.value.pageNum = 1;
|
||||
getList();
|
||||
};
|
||||
|
||||
|
||||
@@ -145,6 +145,12 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<!-- <el-table-column v-if="columns[9].visible" label="宿舍房间" align="center" prop="dormitoryRoom" width="120">
|
||||
<template #default="scope">
|
||||
<span>{{ getRoomDisplayName(scope.row.dormitoryRoom) }}</span>
|
||||
</template>
|
||||
</el-table-column> -->
|
||||
|
||||
<el-table-column label="操作" fixed="right" width="240" class-name="small-padding fixed-width">
|
||||
<template #default="scope">
|
||||
<el-tooltip content="修改" placement="top">
|
||||
@@ -826,8 +832,13 @@
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="宿舍房间号" prop="dormitoryRoom">
|
||||
<el-input disabled v-model="form.dormitoryRoom" placeholder="请输入宿舍房间号" maxlength="20" />
|
||||
<el-form-item label="宿舍房间" prop="dormitoryRoom">
|
||||
<el-input disabled :value="getRoomDisplayName(form.dormitoryRoom)" placeholder="宿舍房间" maxlength="20" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="床位" prop="extField1">
|
||||
<el-input disabled :value="getBedDisplayName(form.extField1)" placeholder="床位" maxlength="20" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
@@ -1389,8 +1400,13 @@
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="宿舍房间号">
|
||||
<span class="form-value">{{ detailForm.dormitoryRoom }}</span>
|
||||
<el-form-item label="宿舍房间">
|
||||
<span class="form-value">{{ getRoomDisplayName(detailForm.dormitoryRoom) }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="床位">
|
||||
<span class="form-value">{{ getBedDisplayName(detailForm.extField1) }}</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
@@ -1603,6 +1619,8 @@ const classOptions = ref([]);
|
||||
const regionOptions = ref([]); // 行政区划选项
|
||||
const dormBuildingOptions = ref([]); // 宿舍楼栋选项
|
||||
const currentSelectedNode = ref<any>(null); // 当前选中的部门节点
|
||||
const roomCache = ref<Map<string | number, string>>(new Map()); // 房间名称缓存
|
||||
const bedCache = ref<Map<string | number, string>>(new Map()); // 床位名称缓存
|
||||
|
||||
// 计算属性:判断是否显示新增按钮(只有班级节点才显示)
|
||||
const showAddButton = computed(() => {
|
||||
@@ -1623,7 +1641,8 @@ const columns = ref([
|
||||
{ key: 5, label: `班级`, visible: true },
|
||||
{ key: 6, label: `手机号码`, visible: true },
|
||||
{ key: 7, label: `状态`, visible: true },
|
||||
{ key: 8, label: `创建时间`, visible: true }
|
||||
{ key: 8, label: `创建时间`, visible: true },
|
||||
{ key: 9, label: `宿舍房间`, visible: true }
|
||||
]);
|
||||
|
||||
const deptTreeRef = ref<any>();
|
||||
@@ -1686,7 +1705,7 @@ const initFormData: StudentMsgForm = {
|
||||
photoUrl: '',
|
||||
photoPath: '',
|
||||
phone: '',
|
||||
isBoarder: 0,
|
||||
isBoarder: '0',
|
||||
|
||||
// // 扩展信息字段
|
||||
educationLevel: '2',
|
||||
@@ -1700,14 +1719,14 @@ const initFormData: StudentMsgForm = {
|
||||
emergencyContactName: '',
|
||||
emergencyContactPhone: '',
|
||||
emergencyContactRelation: '',
|
||||
isPoorStudent: 0,
|
||||
isMinority: 0,
|
||||
isDisabled: 0,
|
||||
isOrphan: 0,
|
||||
isLeftBehindChild: 0,
|
||||
isSingleChild: 0,
|
||||
isLowIncome: 0,
|
||||
hasLoan: 0,
|
||||
isPoorStudent: '0',
|
||||
isMinority: '0',
|
||||
isDisabled: '0',
|
||||
isOrphan: '0',
|
||||
isLeftBehindChild: '0',
|
||||
isSingleChild: '0',
|
||||
isLowIncome: '0',
|
||||
hasLoan: '0',
|
||||
loanAmount: undefined,
|
||||
specialties: '',
|
||||
awards: '',
|
||||
@@ -1762,6 +1781,7 @@ const initFormData: StudentMsgForm = {
|
||||
classTeacherName: '',
|
||||
dormitoryBuilding: '',
|
||||
dormitoryRoom: '',
|
||||
extField1: '', // 床位ID
|
||||
|
||||
// // 银行卡信息字段
|
||||
bankCardNo: '',
|
||||
@@ -1873,6 +1893,152 @@ const getDormBuildingName = (id: string | number) => {
|
||||
return findBuildingName(dormBuildingOptions.value, id) || String(id);
|
||||
};
|
||||
|
||||
/** 根据房间ID获取房间名称 */
|
||||
const getRoomName = async (roomId: string | number): Promise<string> => {
|
||||
if (!roomId) return '';
|
||||
|
||||
// 检查缓存
|
||||
if (roomCache.value.has(roomId)) {
|
||||
return roomCache.value.get(roomId) || '';
|
||||
}
|
||||
|
||||
try {
|
||||
// 调用房间信息接口
|
||||
const res = await service.get(`/xgss/dormRoom/${roomId}`);
|
||||
if (res && res.code === 200 && res.data) {
|
||||
const roomName = res.data.roomName || res.data.roomCode || String(roomId);
|
||||
// 缓存结果
|
||||
roomCache.value.set(roomId, roomName);
|
||||
return roomName;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取房间信息失败:', error);
|
||||
}
|
||||
|
||||
// 如果获取失败,返回ID并缓存
|
||||
roomCache.value.set(roomId, String(roomId));
|
||||
return String(roomId);
|
||||
};
|
||||
|
||||
/** 根据床位ID获取床位名称 */
|
||||
const getBedName = async (bedId: string | number): Promise<string> => {
|
||||
if (!bedId) return '';
|
||||
|
||||
// 检查缓存
|
||||
if (bedCache.value.has(bedId)) {
|
||||
return bedCache.value.get(bedId) || '';
|
||||
}
|
||||
|
||||
try {
|
||||
// 调用床位信息接口
|
||||
const res = await service.get(`/dormbed/dormBed/${bedId}`);
|
||||
if (res && res.code === 200 && res.data) {
|
||||
const bedName = res.data.bedName || res.data.bedCode || String(bedId);
|
||||
// 缓存结果
|
||||
bedCache.value.set(bedId, bedName);
|
||||
return bedName;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取床位信息失败:', error);
|
||||
}
|
||||
|
||||
// 如果获取失败,返回ID并缓存
|
||||
bedCache.value.set(bedId, String(bedId));
|
||||
return String(bedId);
|
||||
};
|
||||
|
||||
/** 获取房间显示名称(同步方法,用于弹窗显示) */
|
||||
const getRoomDisplayName = (roomId: string | number): string => {
|
||||
if (!roomId) return '-';
|
||||
|
||||
// 优先从缓存中获取
|
||||
if (roomCache.value.has(roomId)) {
|
||||
return roomCache.value.get(roomId) || String(roomId);
|
||||
}
|
||||
|
||||
// 如果缓存中没有,返回ID,并异步加载
|
||||
setTimeout(() => {
|
||||
getRoomName(roomId);
|
||||
}, 0);
|
||||
|
||||
return String(roomId);
|
||||
};
|
||||
|
||||
/** 获取床位显示名称(同步方法,用于弹窗显示) */
|
||||
const getBedDisplayName = (bedId: string | number): string => {
|
||||
if (!bedId) return '-';
|
||||
|
||||
// 优先从缓存中获取
|
||||
if (bedCache.value.has(bedId)) {
|
||||
return bedCache.value.get(bedId) || String(bedId);
|
||||
}
|
||||
|
||||
// 如果缓存中没有,返回ID,并异步加载
|
||||
setTimeout(() => {
|
||||
getBedName(bedId);
|
||||
}, 0);
|
||||
|
||||
return String(bedId);
|
||||
};
|
||||
|
||||
/** 预加载房间信息 */
|
||||
const preloadRoomInfo = async () => {
|
||||
if (!studentList.value || studentList.value.length === 0) return;
|
||||
|
||||
// 收集所有需要查询的房间ID(兼容不同的字段名)
|
||||
const roomIds = studentList.value
|
||||
.map((student) => (student as any).dormitoryRoom || (student as any).dormitory_room)
|
||||
.filter((roomId) => roomId && !roomCache.value.has(roomId));
|
||||
|
||||
if (roomIds.length === 0) return;
|
||||
|
||||
// 批量查询房间信息
|
||||
const uniqueRoomIds = [...new Set(roomIds)];
|
||||
|
||||
for (const roomId of uniqueRoomIds) {
|
||||
try {
|
||||
const res = await service.get(`/xgss/dormRoom/${roomId}`);
|
||||
if (res && res.code === 200 && res.data) {
|
||||
const roomName = res.data.roomName || res.data.roomCode || String(roomId);
|
||||
roomCache.value.set(roomId, roomName);
|
||||
} else {
|
||||
roomCache.value.set(roomId, String(roomId));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`获取房间信息失败,房间ID: ${roomId}`, error);
|
||||
roomCache.value.set(roomId, String(roomId));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/** 预加载床位信息 */
|
||||
const preloadBedInfo = async () => {
|
||||
if (!studentList.value || studentList.value.length === 0) return;
|
||||
|
||||
// 收集所有需要查询的床位ID(从extField1字段获取)
|
||||
const bedIds = studentList.value.map((student) => (student as any).extField1).filter((bedId) => bedId && !bedCache.value.has(bedId));
|
||||
|
||||
if (bedIds.length === 0) return;
|
||||
|
||||
// 批量查询床位信息
|
||||
const uniqueBedIds = [...new Set(bedIds)];
|
||||
|
||||
for (const bedId of uniqueBedIds) {
|
||||
try {
|
||||
const res = await service.get(`/dormbed/dormBed/${bedId}`);
|
||||
if (res && res.code === 200 && res.data) {
|
||||
const bedName = res.data.bedName || res.data.bedCode || String(bedId);
|
||||
bedCache.value.set(bedId, bedName);
|
||||
} else {
|
||||
bedCache.value.set(bedId, String(bedId));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`获取床位信息失败,床位ID: ${bedId}`, error);
|
||||
bedCache.value.set(bedId, String(bedId));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/** 根据行政区划代码获取完整路径(省/市/区) */
|
||||
const getRegionFullPath = (code: string): string => {
|
||||
if (!code || !regionOptions.value) return code || '';
|
||||
@@ -1940,6 +2106,11 @@ const getList = async () => {
|
||||
if (res && res.code === 200) {
|
||||
studentList.value = res.rows || [];
|
||||
total.value = res.total || 0;
|
||||
|
||||
// 预加载房间信息
|
||||
await preloadRoomInfo();
|
||||
// 预加载床位信息
|
||||
await preloadBedInfo();
|
||||
} else {
|
||||
ElMessage.error(res?.msg || '查询学生列表失败');
|
||||
studentList.value = [];
|
||||
|
||||