提交
This commit is contained in:
1 parent
f89d747952
commit
4c63668c19
10 files changed
+1608
-24
No files matched your search
@@ -150,6 +150,15 @@ page {
|
||||
border-color: #007dfb !important;
|
||||
}
|
||||
|
||||
/* Tabs组件主题色覆盖 - 全局统一底部方块颜色 */
|
||||
.u-tabs__wrapper__nav__line {
|
||||
background-color: #0051d9 !important;
|
||||
}
|
||||
|
||||
.u-tabs .u-tabs__wrapper__nav__line {
|
||||
background: #0051d9 !important;
|
||||
}
|
||||
|
||||
/* ========== 全局温暖商务风格样式 ========== */
|
||||
|
||||
/* 全局页面背景 */
|
||||
|
||||
@@ -73,18 +73,36 @@
|
||||
<!-- 办理人信息 -->
|
||||
<view class="approver-section">
|
||||
<text class="section-label">办理人:</text>
|
||||
<view class="approver-tags">
|
||||
<template v-if="record.approveName">
|
||||
<u-tag
|
||||
v-for="(name, nameIndex) in record.approveName.split(
|
||||
',',
|
||||
)"
|
||||
:key="nameIndex"
|
||||
:text="name.trim()"
|
||||
:type="getApproverType()"
|
||||
size="mini"
|
||||
class="approver-tag"
|
||||
/>
|
||||
<view class="approver-info-list">
|
||||
<template
|
||||
v-if="record.approverList && record.approverList.length > 0"
|
||||
>
|
||||
<view
|
||||
v-for="(approver, approverIndex) in record.approverList"
|
||||
:key="approverIndex"
|
||||
class="approver-info-item"
|
||||
>
|
||||
<u-tag
|
||||
:text="approver.name"
|
||||
:type="getApproverType()"
|
||||
size="mini"
|
||||
class="approver-tag"
|
||||
/>
|
||||
<view
|
||||
v-if="approver.phone"
|
||||
class="approver-phone-wrapper"
|
||||
@click="handleCallPhone(approver.phone)"
|
||||
>
|
||||
<u-icon
|
||||
name="phone-fill"
|
||||
size="28"
|
||||
color="#1989fa"
|
||||
/>
|
||||
<text class="approver-phone">
|
||||
{{ approver.phone }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<u-tag
|
||||
v-else
|
||||
@@ -253,10 +271,43 @@ export default {
|
||||
console.log('实例ID:', this.insId);
|
||||
console.log('记录数量:', this.historyList.length);
|
||||
|
||||
// 处理附件信息(与web端保持一致)
|
||||
// 处理附件信息和审批人信息(与web端保持一致)
|
||||
if (this.historyList.length > 0) {
|
||||
console.log('开始处理附件信息...');
|
||||
console.log('开始处理附件信息和审批人信息...');
|
||||
|
||||
// 收集所有审批人ID
|
||||
const allApproverIds = new Set();
|
||||
for (const item of this.historyList) {
|
||||
if (item.approver) {
|
||||
// approver字段可能包含多个ID,用逗号分隔
|
||||
const ids = item.approver
|
||||
.split(',')
|
||||
.map((id) => id.trim())
|
||||
.filter((id) => id);
|
||||
ids.forEach((id) => allApproverIds.add(id));
|
||||
}
|
||||
}
|
||||
|
||||
// 批量查询审批人信息(包含手机号码)
|
||||
let userInfoMap = {};
|
||||
if (allApproverIds.size > 0) {
|
||||
console.log(
|
||||
'开始批量查询审批人信息,ID列表:',
|
||||
Array.from(allApproverIds),
|
||||
);
|
||||
try {
|
||||
userInfoMap = await this.getUserInfoByIds(
|
||||
Array.from(allApproverIds),
|
||||
);
|
||||
console.log('审批人信息查询完成:', userInfoMap);
|
||||
} catch (error) {
|
||||
console.error('批量查询审批人信息失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// 处理每条审批记录
|
||||
for (const item of this.historyList) {
|
||||
// 处理附件信息
|
||||
if (item.ext) {
|
||||
try {
|
||||
const attachmentRes = await this.getAttachmentsByIds(item.ext);
|
||||
@@ -268,8 +319,31 @@ export default {
|
||||
} else {
|
||||
item.attachmentList = [];
|
||||
}
|
||||
|
||||
// 处理审批人信息(包含姓名和手机号)
|
||||
if (item.approver && item.approveName) {
|
||||
const approverIds = item.approver
|
||||
.split(',')
|
||||
.map((id) => id.trim())
|
||||
.filter((id) => id);
|
||||
const approverNames = item.approveName
|
||||
.split(',')
|
||||
.map((name) => name.trim())
|
||||
.filter((name) => name);
|
||||
|
||||
item.approverList = approverIds.map((id, index) => {
|
||||
const userInfo = userInfoMap[id];
|
||||
return {
|
||||
id: id,
|
||||
name: approverNames[index] || '未知',
|
||||
phone: userInfo ? userInfo.phonenumber : null,
|
||||
};
|
||||
});
|
||||
} else {
|
||||
item.approverList = [];
|
||||
}
|
||||
}
|
||||
console.log('附件信息处理完成');
|
||||
console.log('附件信息和审批人信息处理完成');
|
||||
}
|
||||
} else {
|
||||
console.error('API响应异常:', response);
|
||||
@@ -300,6 +374,67 @@ export default {
|
||||
return response;
|
||||
},
|
||||
|
||||
// 批量查询用户信息(包含手机号码)
|
||||
async getUserInfoByIds(userIds) {
|
||||
try {
|
||||
const response = await request({
|
||||
url: '/system/user/optionselect',
|
||||
method: 'GET',
|
||||
params: {
|
||||
userIds: userIds.join(','),
|
||||
},
|
||||
});
|
||||
|
||||
if (response.code === 200 && response.data) {
|
||||
// 将数组转换为以userId为key的Map,方便后续查找
|
||||
const userMap = {};
|
||||
response.data.forEach((user) => {
|
||||
userMap[user.userId] = user;
|
||||
});
|
||||
return userMap;
|
||||
} else {
|
||||
console.error('查询用户信息失败:', response.msg);
|
||||
return {};
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('批量查询用户信息异常:', error);
|
||||
return {};
|
||||
}
|
||||
},
|
||||
|
||||
// 拨打电话
|
||||
handleCallPhone(phoneNumber) {
|
||||
if (!phoneNumber) {
|
||||
uni.showToast({
|
||||
title: '手机号码为空',
|
||||
icon: 'none',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
uni.showModal({
|
||||
title: '拨打电话',
|
||||
content: `确定要拨打 ${phoneNumber} 吗?`,
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
uni.makePhoneCall({
|
||||
phoneNumber: phoneNumber,
|
||||
success: () => {
|
||||
console.log('拨打电话成功');
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error('拨打电话失败:', err);
|
||||
uni.showToast({
|
||||
title: '拨打电话失败',
|
||||
icon: 'none',
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
// 获取状态样式类(使用字典方式)
|
||||
getStatusClass(flowStatus) {
|
||||
console.log('flowStatus:', flowStatus);
|
||||
@@ -670,16 +805,44 @@ export default {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.approver-tags {
|
||||
.approver-info-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12rpx;
|
||||
}
|
||||
|
||||
.approver-info-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12rpx;
|
||||
flex-wrap: wrap;
|
||||
gap: 8rpx;
|
||||
}
|
||||
|
||||
.approver-tag {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.approver-phone-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6rpx;
|
||||
padding: 4rpx 8rpx;
|
||||
border-radius: 8rpx;
|
||||
transition: all 0.3s;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.approver-phone-wrapper:active {
|
||||
background-color: #e6f7ff;
|
||||
transform: scale(0.98);
|
||||
}
|
||||
|
||||
.approver-phone {
|
||||
font-size: 26rpx;
|
||||
color: #1989fa;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.comment-text {
|
||||
font-size: 26rpx;
|
||||
color: #333;
|
||||
|
||||
@@ -333,6 +333,14 @@
|
||||
"navigationBarBackgroundColor": "#0051d9",
|
||||
"navigationBarTextStyle": "white"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path": "pages/xg/studentDynamics/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "学生动向信息",
|
||||
"navigationBarBackgroundColor": "#0051d9",
|
||||
"navigationBarTextStyle": "white"
|
||||
}
|
||||
}
|
||||
],
|
||||
"globalStyle": {
|
||||
|
||||
@@ -221,6 +221,20 @@
|
||||
</template>
|
||||
</ServiceItem>
|
||||
|
||||
<ServiceItem
|
||||
v-if="hasPermi(['student:dynamics:list'])"
|
||||
title="学生动向信息(宿管)"
|
||||
@click="gotoStudentDynamics"
|
||||
>
|
||||
<template #icon>
|
||||
<image
|
||||
src="/static/0011.png"
|
||||
mode="aspectFit"
|
||||
style="width: 24px; height: 24px"
|
||||
/>
|
||||
</template>
|
||||
</ServiceItem>
|
||||
|
||||
<ServiceItem
|
||||
v-if="hasPermi(['student:workstudy:list'])"
|
||||
title="勤工俭学"
|
||||
@@ -722,6 +736,7 @@ export default {
|
||||
this.hasPermi(['student:dormviolation:listapp']) ||
|
||||
this.hasPermi(['student:visit:list']) ||
|
||||
this.hasPermi(['student:dormhygiene:listapp']) ||
|
||||
this.hasPermi(['student:dynamics:list']) ||
|
||||
this.hasPermi(['student:workstudy:list']) ||
|
||||
this.hasPermi(['student:violation:listapp']) ||
|
||||
this.hasPermi(['student:assessment:applyapp']) ||
|
||||
@@ -988,6 +1003,13 @@ export default {
|
||||
});
|
||||
},
|
||||
|
||||
// 跳转到学生动向信息(宿管)页面
|
||||
gotoStudentDynamics() {
|
||||
uni.navigateTo({
|
||||
url: '/pages/xg/studentDynamics/index',
|
||||
});
|
||||
},
|
||||
|
||||
// 跳转到修改密码页面
|
||||
gotoResetPassword() {
|
||||
uni.navigateTo({
|
||||
|
||||
@@ -0,0 +1,432 @@
|
||||
<template>
|
||||
<view class="dorm-application-tab">
|
||||
<!-- 搜索区域 -->
|
||||
<view class="search-container">
|
||||
<u-search
|
||||
v-model="searchKeyword"
|
||||
placeholder="请输入姓名或学号"
|
||||
:show-action="true"
|
||||
action-text="搜索"
|
||||
:animation="true"
|
||||
@search="handleQuery"
|
||||
@custom="handleQuery"
|
||||
@clear="handleClear"
|
||||
></u-search>
|
||||
</view>
|
||||
|
||||
<!-- 加载状态 -->
|
||||
<u-loading-page
|
||||
:loading="loading && dataList.length === 0"
|
||||
loading-text="加载中..."
|
||||
></u-loading-page>
|
||||
|
||||
<!-- 列表内容 -->
|
||||
<view v-if="!loading || dataList.length > 0" class="content-wrapper">
|
||||
<!-- 空状态 -->
|
||||
<view v-if="dataList.length === 0" class="empty-container">
|
||||
<u-empty text="暂无调宿/退宿申请记录" mode="data"></u-empty>
|
||||
</view>
|
||||
|
||||
<!-- 列表 -->
|
||||
<scroll-view
|
||||
v-else
|
||||
scroll-y
|
||||
class="scroll-view"
|
||||
:lower-threshold="50"
|
||||
@scrolltolower="handleLoadMore"
|
||||
>
|
||||
<view class="list-container">
|
||||
<view
|
||||
v-for="(item, index) in dataList"
|
||||
:key="item.id || index"
|
||||
class="list-card"
|
||||
>
|
||||
<!-- 卡片头部 -->
|
||||
<view class="card-header">
|
||||
<view class="student-info">
|
||||
<text class="student-name">{{ item.studentName || '-' }}</text>
|
||||
<text class="student-no">{{ item.studentNo || '-' }}</text>
|
||||
</view>
|
||||
<u-tag
|
||||
:text="getApplicationTypeText(item.applicationType)"
|
||||
:type="getApplicationTypeTagType(item.applicationType)"
|
||||
size="mini"
|
||||
></u-tag>
|
||||
</view>
|
||||
|
||||
<!-- 卡片内容 -->
|
||||
<view class="card-content">
|
||||
<view class="info-row">
|
||||
<text class="label">学院:</text>
|
||||
<text class="value">{{ item.collegeName || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<text class="label">专业:</text>
|
||||
<text class="value">{{ item.majorName || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<text class="label">班级:</text>
|
||||
<text class="value">{{ item.className || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<text class="label">当前宿舍:</text>
|
||||
<text class="value">
|
||||
{{ item.currentBuildingName }}{{ item.currentRoomNo
|
||||
}}{{ item.currentBedNo }}
|
||||
</text>
|
||||
</view>
|
||||
<view v-if="item.applicationType === '1'" class="info-row">
|
||||
<text class="label">目标宿舍:</text>
|
||||
<text class="value">
|
||||
{{ item.targetBuildingName }}{{ item.targetRoomNo
|
||||
}}{{ item.targetBedNo }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<text class="label">审批状态:</text>
|
||||
<u-tag
|
||||
:text="getApprovalStatusText(item.applicationStatus)"
|
||||
:type="getApprovalStatusTagType(item.applicationStatus)"
|
||||
size="mini"
|
||||
></u-tag>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<text class="label">申请时间:</text>
|
||||
<text class="value">{{ formatTime(item.applyTime) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<view class="card-actions">
|
||||
<u-button
|
||||
type="primary"
|
||||
size="small"
|
||||
plain
|
||||
@click="handleViewApproval(item)"
|
||||
>
|
||||
<u-icon
|
||||
name="list"
|
||||
size="16"
|
||||
color="#fff"
|
||||
style="margin-right: 4px"
|
||||
></u-icon>
|
||||
审批记录
|
||||
</u-button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 加载更多提示 -->
|
||||
<view class="load-more-wrapper">
|
||||
<u-loadmore :status="loadMoreStatus" :load-text="loadMoreText" />
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
|
||||
<!-- 审批记录组件 -->
|
||||
<approval-record ref="approvalRecordRef"></approval-record>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { request } from '@/common/request.js';
|
||||
import { getDict, getDictLabel, getDictTagType } from '@/common/dict.js';
|
||||
import ApprovalRecord from '@/components/Process/approvalRecord.vue';
|
||||
|
||||
export default {
|
||||
name: 'DormApplicationTab',
|
||||
components: {
|
||||
ApprovalRecord,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
dataList: [],
|
||||
total: 0,
|
||||
searchKeyword: '', // 搜索关键字(姓名或学号)
|
||||
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
studentName: '',
|
||||
studentNo: '',
|
||||
},
|
||||
|
||||
// 加载更多状态
|
||||
loadMoreStatus: 'loadmore',
|
||||
loadMoreText: {
|
||||
loadmore: '点击加载更多',
|
||||
loading: '正在加载...',
|
||||
nomore: '没有更多了',
|
||||
},
|
||||
|
||||
// 字典数据
|
||||
dictApplicationType: [],
|
||||
dictApprovalStatus: [],
|
||||
};
|
||||
},
|
||||
|
||||
async created() {
|
||||
await this.loadDictData();
|
||||
await this.getList();
|
||||
},
|
||||
|
||||
methods: {
|
||||
// 加载字典数据
|
||||
async loadDictData() {
|
||||
try {
|
||||
this.dictApplicationType = await getDict('dorm_application_type');
|
||||
this.dictApprovalStatus = await getDict('student_leave_approval_status');
|
||||
} catch (error) {
|
||||
console.error('加载字典数据失败:', error);
|
||||
}
|
||||
},
|
||||
|
||||
// 获取列表数据
|
||||
async getList() {
|
||||
this.loading = true;
|
||||
try {
|
||||
// 根据搜索关键字设置查询参数
|
||||
const params = {
|
||||
...this.queryParams,
|
||||
studentName: this.searchKeyword,
|
||||
studentNo: this.searchKeyword,
|
||||
};
|
||||
|
||||
const res = await request({
|
||||
url: '/studentDynamics/dormApplicationList',
|
||||
method: 'GET',
|
||||
params: params,
|
||||
});
|
||||
|
||||
if (res && res.code === 200) {
|
||||
if (this.queryParams.pageNum === 1) {
|
||||
this.dataList = res.rows || [];
|
||||
} else {
|
||||
this.dataList = [...this.dataList, ...(res.rows || [])];
|
||||
}
|
||||
this.total = res.total || 0;
|
||||
|
||||
// 更新加载更多状态
|
||||
if (this.dataList.length >= this.total) {
|
||||
this.loadMoreStatus = 'nomore';
|
||||
} else {
|
||||
this.loadMoreStatus = 'loadmore';
|
||||
}
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: res?.msg || '获取数据失败',
|
||||
icon: 'none',
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取调宿退宿申请列表失败:', error);
|
||||
uni.showToast({
|
||||
title: '获取数据失败',
|
||||
icon: 'none',
|
||||
});
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
|
||||
// 加载更多
|
||||
handleLoadMore() {
|
||||
if (this.loadMoreStatus === 'nomore' || this.loadMoreStatus === 'loading') {
|
||||
return;
|
||||
}
|
||||
|
||||
this.loadMoreStatus = 'loading';
|
||||
this.queryParams.pageNum++;
|
||||
this.getList();
|
||||
},
|
||||
|
||||
// 搜索操作
|
||||
handleQuery() {
|
||||
this.queryParams.pageNum = 1;
|
||||
this.dataList = [];
|
||||
this.getList();
|
||||
},
|
||||
|
||||
// 清空搜索
|
||||
handleClear() {
|
||||
this.searchKeyword = '';
|
||||
this.handleQuery();
|
||||
},
|
||||
|
||||
// 格式化时间
|
||||
formatTime(timeStr) {
|
||||
if (!timeStr) return '-';
|
||||
try {
|
||||
const date = new Date(timeStr);
|
||||
if (isNaN(date.getTime())) return timeStr;
|
||||
|
||||
const year = date.getFullYear();
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(date.getDate()).padStart(2, '0');
|
||||
const hours = String(date.getHours()).padStart(2, '0');
|
||||
const minutes = String(date.getMinutes()).padStart(2, '0');
|
||||
const seconds = String(date.getSeconds()).padStart(2, '0');
|
||||
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
||||
} catch (error) {
|
||||
console.error('时间格式化失败:', error);
|
||||
return timeStr;
|
||||
}
|
||||
},
|
||||
|
||||
// 获取申请类型文本
|
||||
getApplicationTypeText(value) {
|
||||
return getDictLabel(this.dictApplicationType, value) || '-';
|
||||
},
|
||||
|
||||
// 获取申请类型标签类型
|
||||
getApplicationTypeTagType(value) {
|
||||
const fallbackMap = {
|
||||
1: 'primary', // 调宿
|
||||
2: 'warning', // 退宿
|
||||
};
|
||||
return getDictTagType(this.dictApplicationType, value, fallbackMap);
|
||||
},
|
||||
|
||||
// 获取审批状态文本
|
||||
getApprovalStatusText(value) {
|
||||
return getDictLabel(this.dictApprovalStatus, value) || '-';
|
||||
},
|
||||
|
||||
// 获取审批状态标签类型
|
||||
getApprovalStatusTagType(value) {
|
||||
const fallbackMap = {
|
||||
0: 'warning', // 待审批
|
||||
1: 'success', // 已通过
|
||||
2: 'error', // 已驳回
|
||||
};
|
||||
return getDictTagType(this.dictApprovalStatus, value, fallbackMap);
|
||||
},
|
||||
|
||||
// 查看审批记录
|
||||
handleViewApproval(item) {
|
||||
console.log('查看审批记录:', item);
|
||||
if (!item.id) {
|
||||
uni.showToast({
|
||||
title: '数据异常,无法查看审批记录',
|
||||
icon: 'none',
|
||||
});
|
||||
return;
|
||||
}
|
||||
// 调用审批记录组件,传入业务ID
|
||||
this.$refs.approvalRecordRef.init(item.id);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.dorm-application-tab {
|
||||
background-color: #f5f6fa;
|
||||
min-height: calc(100vh - 176rpx);
|
||||
}
|
||||
|
||||
.search-container {
|
||||
padding: 20rpx;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.content-wrapper {
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
.empty-container {
|
||||
padding: 100rpx 20rpx;
|
||||
}
|
||||
|
||||
.scroll-view {
|
||||
height: calc(100vh - 176rpx - 88rpx); // 减去搜索栏高度
|
||||
}
|
||||
|
||||
.list-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20rpx;
|
||||
padding-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.list-card {
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 24rpx;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.student-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.student-name {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.student-no {
|
||||
font-size: 26rpx;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.card-content {
|
||||
padding: 24rpx;
|
||||
}
|
||||
|
||||
.info-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 16rpx;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.label {
|
||||
font-size: 28rpx;
|
||||
color: #606266;
|
||||
min-width: 140rpx;
|
||||
margin-right: 16rpx;
|
||||
}
|
||||
|
||||
.value {
|
||||
font-size: 28rpx;
|
||||
color: #303133;
|
||||
flex: 1;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.card-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
padding: 20rpx 24rpx;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.load-more-wrapper {
|
||||
padding: 20rpx 0;
|
||||
}
|
||||
|
||||
// uview组件样式调整
|
||||
::v-deep .u-search {
|
||||
background-color: #f5f6fa;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,392 @@
|
||||
<template>
|
||||
<view class="holiday-stay-tab">
|
||||
<!-- 搜索区域 -->
|
||||
<view class="search-container">
|
||||
<u-search
|
||||
v-model="searchKeyword"
|
||||
placeholder="请输入姓名或学号"
|
||||
:show-action="true"
|
||||
action-text="搜索"
|
||||
:animation="true"
|
||||
@search="handleQuery"
|
||||
@custom="handleQuery"
|
||||
@clear="handleClear"
|
||||
></u-search>
|
||||
</view>
|
||||
|
||||
<!-- 加载状态 -->
|
||||
<u-loading-page
|
||||
:loading="loading && dataList.length === 0"
|
||||
loading-text="加载中..."
|
||||
></u-loading-page>
|
||||
|
||||
<!-- 列表内容 -->
|
||||
<view v-if="!loading || dataList.length > 0" class="content-wrapper">
|
||||
<!-- 空状态 -->
|
||||
<view v-if="dataList.length === 0" class="empty-container">
|
||||
<u-empty text="暂无假期留宿记录" mode="data"></u-empty>
|
||||
</view>
|
||||
|
||||
<!-- 列表 -->
|
||||
<scroll-view
|
||||
v-else
|
||||
scroll-y
|
||||
class="scroll-view"
|
||||
:lower-threshold="50"
|
||||
@scrolltolower="handleLoadMore"
|
||||
>
|
||||
<view class="list-container">
|
||||
<view
|
||||
v-for="(item, index) in dataList"
|
||||
:key="item.id || index"
|
||||
class="list-card"
|
||||
>
|
||||
<!-- 卡片头部 -->
|
||||
<view class="card-header">
|
||||
<view class="student-info">
|
||||
<text class="student-name">{{ item.studentName || '-' }}</text>
|
||||
<text class="student-no">{{ item.studentNo || '-' }}</text>
|
||||
</view>
|
||||
<u-tag
|
||||
:text="getHolidayTypeText(item.holidayType)"
|
||||
:type="getHolidayTypeTagType(item.holidayType)"
|
||||
size="mini"
|
||||
></u-tag>
|
||||
</view>
|
||||
|
||||
<!-- 卡片内容 -->
|
||||
<view class="card-content">
|
||||
<view class="info-row">
|
||||
<text class="label">学院:</text>
|
||||
<text class="value">{{ item.collegeName || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<text class="label">专业:</text>
|
||||
<text class="value">{{ item.majorName || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<text class="label">班级:</text>
|
||||
<text class="value">{{ item.className || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<text class="label">宿舍信息:</text>
|
||||
<text class="value">
|
||||
{{ item.buildingName }}{{ item.roomName }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<text class="label">留宿时间:</text>
|
||||
<text class="value">
|
||||
{{ item.applyStartDate }} 至 {{ item.applyEndDate }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<text class="label">留宿原因:</text>
|
||||
<u-tag
|
||||
:text="getStayReasonTypeText(item.stayReasonType)"
|
||||
:type="getStayReasonTypeTagType(item.stayReasonType)"
|
||||
size="mini"
|
||||
></u-tag>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<text class="label">联系电话:</text>
|
||||
<text class="value">{{ item.studentPhone || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<text class="label">紧急联系人:</text>
|
||||
<text class="value">{{ item.emergencyContact || '-' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 操作按钮 - 暂不开发
|
||||
<view class="card-actions">
|
||||
<u-button
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="handleView(item)"
|
||||
>查看</u-button>
|
||||
</view>
|
||||
-->
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 加载更多提示 -->
|
||||
<view class="load-more-wrapper">
|
||||
<u-loadmore :status="loadMoreStatus" :load-text="loadMoreText" />
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { request } from '@/common/request.js';
|
||||
import { getDict, getDictLabel, getDictTagType } from '@/common/dict.js';
|
||||
|
||||
export default {
|
||||
name: 'HolidayStayTab',
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
dataList: [],
|
||||
total: 0,
|
||||
searchKeyword: '', // 搜索关键字(姓名或学号)
|
||||
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
studentName: '',
|
||||
studentNo: '',
|
||||
},
|
||||
|
||||
// 加载更多状态
|
||||
loadMoreStatus: 'loadmore',
|
||||
loadMoreText: {
|
||||
loadmore: '点击加载更多',
|
||||
loading: '正在加载...',
|
||||
nomore: '没有更多了',
|
||||
},
|
||||
|
||||
// 字典数据
|
||||
dictHolidayType: [],
|
||||
dictStayReasonType: [],
|
||||
};
|
||||
},
|
||||
|
||||
async created() {
|
||||
await this.loadDictData();
|
||||
await this.getList();
|
||||
},
|
||||
|
||||
methods: {
|
||||
// 加载字典数据
|
||||
async loadDictData() {
|
||||
try {
|
||||
this.dictHolidayType = await getDict('xg_holiday_type');
|
||||
this.dictStayReasonType = await getDict('xg_stay_reason_type');
|
||||
} catch (error) {
|
||||
console.error('加载字典数据失败:', error);
|
||||
}
|
||||
},
|
||||
|
||||
// 获取列表数据
|
||||
async getList() {
|
||||
this.loading = true;
|
||||
try {
|
||||
// 根据搜索关键字设置查询参数
|
||||
const params = {
|
||||
...this.queryParams,
|
||||
studentName: this.searchKeyword,
|
||||
studentNo: this.searchKeyword,
|
||||
};
|
||||
|
||||
const res = await request({
|
||||
url: '/studentDynamics/holidayStayList',
|
||||
method: 'GET',
|
||||
params: params,
|
||||
});
|
||||
|
||||
if (res && res.code === 200) {
|
||||
if (this.queryParams.pageNum === 1) {
|
||||
this.dataList = res.rows || [];
|
||||
} else {
|
||||
this.dataList = [...this.dataList, ...(res.rows || [])];
|
||||
}
|
||||
this.total = res.total || 0;
|
||||
|
||||
// 更新加载更多状态
|
||||
if (this.dataList.length >= this.total) {
|
||||
this.loadMoreStatus = 'nomore';
|
||||
} else {
|
||||
this.loadMoreStatus = 'loadmore';
|
||||
}
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: res?.msg || '获取数据失败',
|
||||
icon: 'none',
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取假期留宿信息列表失败:', error);
|
||||
uni.showToast({
|
||||
title: '获取数据失败',
|
||||
icon: 'none',
|
||||
});
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
|
||||
// 加载更多
|
||||
handleLoadMore() {
|
||||
if (this.loadMoreStatus === 'nomore' || this.loadMoreStatus === 'loading') {
|
||||
return;
|
||||
}
|
||||
|
||||
this.loadMoreStatus = 'loading';
|
||||
this.queryParams.pageNum++;
|
||||
this.getList();
|
||||
},
|
||||
|
||||
// 搜索操作
|
||||
handleQuery() {
|
||||
this.queryParams.pageNum = 1;
|
||||
this.dataList = [];
|
||||
this.getList();
|
||||
},
|
||||
|
||||
// 清空搜索
|
||||
handleClear() {
|
||||
this.searchKeyword = '';
|
||||
this.handleQuery();
|
||||
},
|
||||
|
||||
// 获取假期类型文本
|
||||
getHolidayTypeText(value) {
|
||||
return getDictLabel(this.dictHolidayType, value) || '-';
|
||||
},
|
||||
|
||||
// 获取假期类型标签类型
|
||||
getHolidayTypeTagType(value) {
|
||||
const fallbackMap = {
|
||||
1: 'primary', // 寒假
|
||||
2: 'warning', // 暑假
|
||||
3: 'success', // 国庆
|
||||
4: 'info', // 其他
|
||||
};
|
||||
return getDictTagType(this.dictHolidayType, value, fallbackMap);
|
||||
},
|
||||
|
||||
// 获取留宿原因类型文本
|
||||
getStayReasonTypeText(value) {
|
||||
return getDictLabel(this.dictStayReasonType, value) || '-';
|
||||
},
|
||||
|
||||
// 获取留宿原因类型标签类型
|
||||
getStayReasonTypeTagType(value) {
|
||||
const fallbackMap = {
|
||||
1: 'primary', // 学习
|
||||
2: 'warning', // 实习
|
||||
3: 'success', // 工作
|
||||
4: 'info', // 其他
|
||||
};
|
||||
return getDictTagType(this.dictStayReasonType, value, fallbackMap);
|
||||
},
|
||||
|
||||
// 查看详情 - 暂不开发
|
||||
// handleView(row) {
|
||||
// console.log('查看详情:', row);
|
||||
// },
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.holiday-stay-tab {
|
||||
background-color: #f5f6fa;
|
||||
min-height: calc(100vh - 176rpx);
|
||||
}
|
||||
|
||||
.search-container {
|
||||
padding: 20rpx;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.content-wrapper {
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
.empty-container {
|
||||
padding: 100rpx 20rpx;
|
||||
}
|
||||
|
||||
.scroll-view {
|
||||
height: calc(100vh - 176rpx - 88rpx); // 减去搜索栏高度
|
||||
}
|
||||
|
||||
.list-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20rpx;
|
||||
padding-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.list-card {
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 24rpx;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.student-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.student-name {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.student-no {
|
||||
font-size: 26rpx;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.card-content {
|
||||
padding: 24rpx;
|
||||
}
|
||||
|
||||
.info-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 16rpx;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.label {
|
||||
font-size: 28rpx;
|
||||
color: #606266;
|
||||
min-width: 140rpx;
|
||||
margin-right: 16rpx;
|
||||
}
|
||||
|
||||
.value {
|
||||
font-size: 28rpx;
|
||||
color: #303133;
|
||||
flex: 1;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.card-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
padding: 20rpx 24rpx;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.load-more-wrapper {
|
||||
padding: 20rpx 0;
|
||||
}
|
||||
|
||||
// uview组件样式调整
|
||||
::v-deep .u-search {
|
||||
background-color: #f5f6fa;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,435 @@
|
||||
<template>
|
||||
<view class="student-leave-tab">
|
||||
<!-- 搜索区域 -->
|
||||
<view class="search-container">
|
||||
<u-search
|
||||
v-model="searchKeyword"
|
||||
placeholder="请输入姓名或学号"
|
||||
:show-action="true"
|
||||
action-text="搜索"
|
||||
:animation="true"
|
||||
@search="handleQuery"
|
||||
@custom="handleQuery"
|
||||
@clear="handleClear"
|
||||
></u-search>
|
||||
</view>
|
||||
|
||||
<!-- 加载状态 -->
|
||||
<u-loading-page
|
||||
:loading="loading && dataList.length === 0"
|
||||
loading-text="加载中..."
|
||||
></u-loading-page>
|
||||
|
||||
<!-- 列表内容 -->
|
||||
<view v-if="!loading || dataList.length > 0" class="content-wrapper">
|
||||
<!-- 空状态 -->
|
||||
<view v-if="dataList.length === 0" class="empty-container">
|
||||
<u-empty text="暂无学生请假记录" mode="data"></u-empty>
|
||||
</view>
|
||||
|
||||
<!-- 列表 -->
|
||||
<scroll-view
|
||||
v-else
|
||||
scroll-y
|
||||
class="scroll-view"
|
||||
:lower-threshold="50"
|
||||
@scrolltolower="handleLoadMore"
|
||||
>
|
||||
<view class="list-container">
|
||||
<view
|
||||
v-for="(item, index) in dataList"
|
||||
:key="item.id || index"
|
||||
class="list-card"
|
||||
>
|
||||
<!-- 卡片头部 -->
|
||||
<view class="card-header">
|
||||
<view class="student-info">
|
||||
<text class="student-name">{{ item.studentName || '-' }}</text>
|
||||
<text class="student-no">{{ item.studentNo || '-' }}</text>
|
||||
</view>
|
||||
<u-tag
|
||||
:text="item.leaveTypeName || '-'"
|
||||
type="primary"
|
||||
size="mini"
|
||||
></u-tag>
|
||||
</view>
|
||||
|
||||
<!-- 卡片内容 -->
|
||||
<view class="card-content">
|
||||
<view class="info-row">
|
||||
<text class="label">学院:</text>
|
||||
<text class="value">{{ item.collegeName || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<text class="label">专业:</text>
|
||||
<text class="value">{{ item.majorName || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<text class="label">班级:</text>
|
||||
<text class="value">{{ item.className || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<text class="label">请假时间:</text>
|
||||
<text class="value">
|
||||
{{ item.startTime }} 至 {{ item.endTime }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<text class="label">请假时长:</text>
|
||||
<text class="value">{{ item.leaveDuration || 0 }}天</text>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<text class="label">是否离校:</text>
|
||||
<u-tag
|
||||
:text="getIsLeaveSchoolText(item.isLeaveSchool)"
|
||||
:type="getIsLeaveSchoolTagType(item.isLeaveSchool)"
|
||||
size="mini"
|
||||
></u-tag>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<text class="label">审批状态:</text>
|
||||
<u-tag
|
||||
:text="getApprovalStatusText(item.approvalStatus)"
|
||||
:type="getApprovalStatusTagType(item.approvalStatus)"
|
||||
size="mini"
|
||||
></u-tag>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<text class="label">销假状态:</text>
|
||||
<u-tag
|
||||
:text="getCancelStatusText(item.cancelStatus)"
|
||||
:type="getCancelStatusTagType(item.cancelStatus)"
|
||||
size="mini"
|
||||
></u-tag>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<view class="card-actions">
|
||||
<u-button
|
||||
type="primary"
|
||||
size="small"
|
||||
plain
|
||||
@click="handleViewApproval(item)"
|
||||
>
|
||||
<u-icon
|
||||
name="list"
|
||||
size="16"
|
||||
color="#fff"
|
||||
style="margin-right: 4px"
|
||||
></u-icon>
|
||||
审批记录
|
||||
</u-button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 加载更多提示 -->
|
||||
<view class="load-more-wrapper">
|
||||
<u-loadmore :status="loadMoreStatus" :load-text="loadMoreText" />
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
|
||||
<!-- 审批记录组件 -->
|
||||
<approval-record ref="approvalRecordRef"></approval-record>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { request } from '@/common/request.js';
|
||||
import { getDict, getDictLabel, getDictTagType } from '@/common/dict.js';
|
||||
import ApprovalRecord from '@/components/Process/approvalRecord.vue';
|
||||
|
||||
export default {
|
||||
name: 'StudentLeaveTab',
|
||||
components: {
|
||||
ApprovalRecord,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
dataList: [],
|
||||
total: 0,
|
||||
searchKeyword: '', // 搜索关键字(姓名或学号)
|
||||
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
studentName: '',
|
||||
studentNo: '',
|
||||
},
|
||||
|
||||
// 加载更多状态
|
||||
loadMoreStatus: 'loadmore',
|
||||
loadMoreText: {
|
||||
loadmore: '点击加载更多',
|
||||
loading: '正在加载...',
|
||||
nomore: '没有更多了',
|
||||
},
|
||||
|
||||
// 字典数据
|
||||
dictYesNo: [],
|
||||
dictApprovalStatus: [],
|
||||
dictCancelStatus: [],
|
||||
};
|
||||
},
|
||||
|
||||
async created() {
|
||||
await this.loadDictData();
|
||||
await this.getList();
|
||||
},
|
||||
|
||||
methods: {
|
||||
// 加载字典数据
|
||||
async loadDictData() {
|
||||
try {
|
||||
this.dictYesNo = await getDict('sys_yesno');
|
||||
this.dictApprovalStatus = await getDict('student_leave_approval_status');
|
||||
this.dictCancelStatus = await getDict('xg_xsqj_cancel_status');
|
||||
} catch (error) {
|
||||
console.error('加载字典数据失败:', error);
|
||||
}
|
||||
},
|
||||
|
||||
// 获取列表数据
|
||||
async getList() {
|
||||
this.loading = true;
|
||||
try {
|
||||
// 根据搜索关键字设置查询参数
|
||||
const params = {
|
||||
...this.queryParams,
|
||||
studentName: this.searchKeyword,
|
||||
studentNo: this.searchKeyword,
|
||||
};
|
||||
|
||||
const res = await request({
|
||||
url: '/studentDynamics/studentLeaveList',
|
||||
method: 'GET',
|
||||
params: params,
|
||||
});
|
||||
|
||||
if (res && res.code === 200) {
|
||||
if (this.queryParams.pageNum === 1) {
|
||||
this.dataList = res.rows || [];
|
||||
} else {
|
||||
this.dataList = [...this.dataList, ...(res.rows || [])];
|
||||
}
|
||||
this.total = res.total || 0;
|
||||
|
||||
// 更新加载更多状态
|
||||
if (this.dataList.length >= this.total) {
|
||||
this.loadMoreStatus = 'nomore';
|
||||
} else {
|
||||
this.loadMoreStatus = 'loadmore';
|
||||
}
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: res?.msg || '获取数据失败',
|
||||
icon: 'none',
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取学生请假信息列表失败:', error);
|
||||
uni.showToast({
|
||||
title: '获取数据失败',
|
||||
icon: 'none',
|
||||
});
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
|
||||
// 加载更多
|
||||
handleLoadMore() {
|
||||
if (this.loadMoreStatus === 'nomore' || this.loadMoreStatus === 'loading') {
|
||||
return;
|
||||
}
|
||||
|
||||
this.loadMoreStatus = 'loading';
|
||||
this.queryParams.pageNum++;
|
||||
this.getList();
|
||||
},
|
||||
|
||||
// 搜索操作
|
||||
handleQuery() {
|
||||
this.queryParams.pageNum = 1;
|
||||
this.dataList = [];
|
||||
this.getList();
|
||||
},
|
||||
|
||||
// 清空搜索
|
||||
handleClear() {
|
||||
this.searchKeyword = '';
|
||||
this.handleQuery();
|
||||
},
|
||||
|
||||
// 获取是否离校文本
|
||||
getIsLeaveSchoolText(value) {
|
||||
return getDictLabel(this.dictYesNo, value) || '-';
|
||||
},
|
||||
|
||||
// 获取是否离校标签类型
|
||||
getIsLeaveSchoolTagType(value) {
|
||||
const fallbackMap = {
|
||||
Y: 'warning', // 是
|
||||
N: 'info', // 否
|
||||
};
|
||||
return getDictTagType(this.dictYesNo, value, fallbackMap);
|
||||
},
|
||||
|
||||
// 获取审批状态文本
|
||||
getApprovalStatusText(value) {
|
||||
return getDictLabel(this.dictApprovalStatus, value) || '-';
|
||||
},
|
||||
|
||||
// 获取审批状态标签类型
|
||||
getApprovalStatusTagType(value) {
|
||||
const fallbackMap = {
|
||||
0: 'warning', // 待审批
|
||||
1: 'success', // 已通过
|
||||
2: 'error', // 已驳回
|
||||
};
|
||||
return getDictTagType(this.dictApprovalStatus, value, fallbackMap);
|
||||
},
|
||||
|
||||
// 获取销假状态文本
|
||||
getCancelStatusText(value) {
|
||||
return getDictLabel(this.dictCancelStatus, value) || '-';
|
||||
},
|
||||
|
||||
// 获取销假状态标签类型
|
||||
getCancelStatusTagType(value) {
|
||||
const fallbackMap = {
|
||||
0: 'warning', // 未销假
|
||||
1: 'success', // 已销假
|
||||
};
|
||||
return getDictTagType(this.dictCancelStatus, value, fallbackMap);
|
||||
},
|
||||
|
||||
// 查看审批记录
|
||||
handleViewApproval(item) {
|
||||
console.log('查看审批记录:', item);
|
||||
if (!item.id) {
|
||||
uni.showToast({
|
||||
title: '数据异常,无法查看审批记录',
|
||||
icon: 'none',
|
||||
});
|
||||
return;
|
||||
}
|
||||
// 调用审批记录组件,传入业务ID
|
||||
this.$refs.approvalRecordRef.init(item.id);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.student-leave-tab {
|
||||
background-color: #f5f6fa;
|
||||
min-height: calc(100vh - 176rpx);
|
||||
}
|
||||
|
||||
.search-container {
|
||||
padding: 20rpx;
|
||||
background-color: #fff;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.content-wrapper {
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
.empty-container {
|
||||
padding: 100rpx 20rpx;
|
||||
}
|
||||
|
||||
.scroll-view {
|
||||
height: calc(100vh - 176rpx - 88rpx); // 减去搜索栏高度
|
||||
}
|
||||
|
||||
.list-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20rpx;
|
||||
padding-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.list-card {
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 24rpx;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.student-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.student-name {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.student-no {
|
||||
font-size: 26rpx;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.card-content {
|
||||
padding: 24rpx;
|
||||
}
|
||||
|
||||
.info-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 16rpx;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.label {
|
||||
font-size: 28rpx;
|
||||
color: #606266;
|
||||
min-width: 140rpx;
|
||||
margin-right: 16rpx;
|
||||
}
|
||||
|
||||
.value {
|
||||
font-size: 28rpx;
|
||||
color: #303133;
|
||||
flex: 1;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.card-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
padding: 20rpx 24rpx;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.load-more-wrapper {
|
||||
padding: 20rpx 0;
|
||||
}
|
||||
|
||||
// uview组件样式调整
|
||||
::v-deep .u-search {
|
||||
background-color: #f5f6fa;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,99 @@
|
||||
<template>
|
||||
<view class="student-dynamics-container">
|
||||
<!-- 顶部导航 -->
|
||||
<u-navbar title="学生动向信息" :border-bottom="false" bg-color="#0051d9" title-color="#fff">
|
||||
<view slot="left" @click="goBack">
|
||||
<u-icon name="arrow-left" color="#fff" size="22"></u-icon>
|
||||
</view>
|
||||
</u-navbar>
|
||||
|
||||
<!-- Tab切换 -->
|
||||
<u-tabs
|
||||
:list="tabList"
|
||||
:current="currentTab"
|
||||
@change="handleTabChange"
|
||||
active-color="#0051d9"
|
||||
inactive-color="#606266"
|
||||
line-color="#0051d9"
|
||||
:line-width="60"
|
||||
:line-height="4"
|
||||
:scrollable="false"
|
||||
></u-tabs>
|
||||
|
||||
<!-- Tab内容区域 -->
|
||||
<view class="tab-content">
|
||||
<!-- 调宿/退宿信息 -->
|
||||
<view v-show="currentTab === 0" class="tab-pane">
|
||||
<dorm-application-tab ref="dormApplicationTabRef"></dorm-application-tab>
|
||||
</view>
|
||||
|
||||
<!-- 假期留宿信息 -->
|
||||
<view v-show="currentTab === 1" class="tab-pane">
|
||||
<holiday-stay-tab ref="holidayStayTabRef"></holiday-stay-tab>
|
||||
</view>
|
||||
|
||||
<!-- 学生请假信息 -->
|
||||
<view v-show="currentTab === 2" class="tab-pane">
|
||||
<student-leave-tab ref="studentLeaveTabRef"></student-leave-tab>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import DormApplicationTab from './components/DormApplicationTab.vue';
|
||||
import HolidayStayTab from './components/HolidayStayTab.vue';
|
||||
import StudentLeaveTab from './components/StudentLeaveTab.vue';
|
||||
|
||||
export default {
|
||||
name: 'StudentDynamics',
|
||||
components: {
|
||||
DormApplicationTab,
|
||||
HolidayStayTab,
|
||||
StudentLeaveTab,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// Tab列表
|
||||
tabList: [
|
||||
{ name: '调宿/退宿信息' },
|
||||
{ name: '假期留宿信息' },
|
||||
{ name: '学生请假信息' },
|
||||
],
|
||||
// 当前激活的Tab
|
||||
currentTab: 0,
|
||||
};
|
||||
},
|
||||
onLoad() {
|
||||
console.log('学生动向信息管理页面已加载');
|
||||
},
|
||||
methods: {
|
||||
// 返回上一页
|
||||
goBack() {
|
||||
uni.navigateBack();
|
||||
},
|
||||
|
||||
// Tab切换处理
|
||||
handleTabChange(item) {
|
||||
console.log('切换到Tab页:', item);
|
||||
// uview的@change事件返回的是对象,需要提取index属性
|
||||
this.currentTab = item.index;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.student-dynamics-container {
|
||||
background-color: #f5f6fa;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.tab-content {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.tab-pane {
|
||||
min-height: calc(100vh - 88rpx - 88rpx); // 减去navbar和tabs的高度
|
||||
}
|
||||
</style>
|
||||
@@ -17,7 +17,7 @@
|
||||
:list="tabList"
|
||||
:current="safeCurrentTab"
|
||||
@click="handleTabClick"
|
||||
active-color="#3c9cff"
|
||||
active-color="#0051d9"
|
||||
inactive-color="#606266"
|
||||
:font-size="32"
|
||||
:bar-width="60"
|
||||
|
||||
Reference in new issue
Block a user