提交代码
This commit is contained in:
1 parent
eb51f1645c
commit
c164d1feb4
21 files changed
+1721
-381
No files matched your search
@@ -50,7 +50,7 @@
|
||||
<!-- 流程列表 -->
|
||||
<view v-else class="process-list">
|
||||
<view
|
||||
v-for="item in processInstanceList"
|
||||
v-for="(item, index) in processInstanceList"
|
||||
:key="item.id"
|
||||
class="process-item"
|
||||
@click="handleView(item)"
|
||||
@@ -58,6 +58,7 @@
|
||||
<!-- 流程信息 -->
|
||||
<view class="process-header">
|
||||
<view class="process-title-row">
|
||||
<text class="title-index">{{ index + 1 }}.</text>
|
||||
<text class="process-name">{{ item.flowName }}</text>
|
||||
<u-tag
|
||||
:text="getStatusText(item.flowStatus)"
|
||||
@@ -751,6 +752,12 @@ export default {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.title-index {
|
||||
color: #000000;
|
||||
font-weight: bold;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.process-name {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
|
||||
@@ -43,7 +43,10 @@
|
||||
<view v-for="(item, index) in taskList" :key="item.id || index" class="task-card">
|
||||
<!-- 卡片头部 -->
|
||||
<view class="card-header">
|
||||
<view class="flow-name">{{ item.flowName || '-' }}</view>
|
||||
<view class="flow-name">
|
||||
<text class="title-index">{{ index + 1 }}.</text>
|
||||
{{ item.flowName || '-' }}
|
||||
</view>
|
||||
<view class="flow-status">
|
||||
<u-tag
|
||||
:text="getFlowStatusText(item.flowStatus)"
|
||||
@@ -458,6 +461,12 @@ export default {
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.title-index {
|
||||
color: #000000;
|
||||
font-weight: bold;
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
|
||||
.flow-name {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
|
||||
@@ -73,7 +73,10 @@
|
||||
>
|
||||
<!-- 卡片头部 -->
|
||||
<view class="card-header">
|
||||
<view class="task-title">{{ item.flowName || '-' }}</view>
|
||||
<view class="task-title">
|
||||
<text class="title-index">{{ index + 1 }}.</text>
|
||||
{{ item.flowName || '-' }}
|
||||
</view>
|
||||
<view class="task-status">
|
||||
<u-tag
|
||||
:text="getFlowStatusText(item.flowStatus)"
|
||||
@@ -842,6 +845,12 @@ export default {
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.title-index {
|
||||
color: #000000;
|
||||
font-weight: bold;
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
|
||||
.task-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
|
||||
@@ -53,92 +53,110 @@
|
||||
<u-empty text="暂无待办任务" mode="data"></u-empty>
|
||||
</view>
|
||||
|
||||
<!-- 任务卡片列表 -->
|
||||
<view v-else class="task-list">
|
||||
<view v-for="(item, index) in taskList" :key="item.id || index" class="task-card">
|
||||
<!-- 卡片头部 -->
|
||||
<view class="card-header">
|
||||
<view class="task-title">{{ item.flowName || '-' }}</view>
|
||||
<view class="task-status">
|
||||
<u-tag
|
||||
:text="getFlowStatusText(item.flowStatus)"
|
||||
:type="getFlowStatusType(item.flowStatus)"
|
||||
size="mini"
|
||||
></u-tag>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 卡片内容 -->
|
||||
<view class="card-content">
|
||||
<view class="info-item">
|
||||
<text class="label">流程名称:</text>
|
||||
<text class="value">{{ item.flowName || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">流程分类:</text>
|
||||
<text class="value">{{ item.categoryName || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">任务名称:</text>
|
||||
<text class="value">{{ item.nodeName || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">申请人:</text>
|
||||
<text class="value">{{ item.createByName || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">办理人:</text>
|
||||
<view class="assignee-tags">
|
||||
<template v-if="item.assigneeNames">
|
||||
<u-tag
|
||||
v-for="(name, idx) in item.assigneeNames.split(',')"
|
||||
:key="idx"
|
||||
:text="name"
|
||||
type="success"
|
||||
size="mini"
|
||||
style="margin-right: 8rpx; margin-bottom: 8rpx"
|
||||
></u-tag>
|
||||
</template>
|
||||
<u-tag v-else text="无" type="info" size="mini"></u-tag>
|
||||
<!-- 任务卡片列表 - 滚动加载 -->
|
||||
<scroll-view
|
||||
v-else
|
||||
scroll-y
|
||||
class="task-scroll-list"
|
||||
@scrolltolower="loadMore"
|
||||
:scroll-top="scrollTop"
|
||||
refresher-enabled="true"
|
||||
:refresher-triggered="refreshing"
|
||||
@refresherrefresh="onRefresh"
|
||||
>
|
||||
<view class="task-list">
|
||||
<view
|
||||
v-for="(item, index) in taskList"
|
||||
:key="item.id || index"
|
||||
class="task-card"
|
||||
>
|
||||
<!-- 卡片头部 -->
|
||||
<view class="card-header">
|
||||
<view class="task-title">
|
||||
<text class="title-index">{{ index + 1 }}.</text>
|
||||
{{ item.flowName || '-' }}
|
||||
</view>
|
||||
<view class="task-status">
|
||||
<u-tag
|
||||
:text="getFlowStatusText(item.flowStatus)"
|
||||
:type="getFlowStatusType(item.flowStatus)"
|
||||
size="mini"
|
||||
></u-tag>
|
||||
</view>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">创建时间:</text>
|
||||
<text class="value">{{ formatTime(item.createTime) }}</text>
|
||||
|
||||
<!-- 卡片内容 -->
|
||||
<view class="card-content">
|
||||
<view class="info-item">
|
||||
<text class="label">流程名称:</text>
|
||||
<text class="value">{{ item.flowName || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">流程分类:</text>
|
||||
<text class="value">{{ item.categoryName || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">任务名称:</text>
|
||||
<text class="value">{{ item.nodeName || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">申请人:</text>
|
||||
<text class="value">{{ item.createByName || '-' }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">办理人:</text>
|
||||
<view class="assignee-tags">
|
||||
<template v-if="item.assigneeNames">
|
||||
<u-tag
|
||||
v-for="(name, idx) in item.assigneeNames.split(',')"
|
||||
:key="idx"
|
||||
:text="name"
|
||||
type="success"
|
||||
size="mini"
|
||||
style="margin-right: 8rpx; margin-bottom: 8rpx"
|
||||
></u-tag>
|
||||
</template>
|
||||
<u-tag v-else text="无" type="info" size="mini"></u-tag>
|
||||
</view>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="label">创建时间:</text>
|
||||
<text class="value">{{ formatTime(item.createTime) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<view class="card-actions">
|
||||
<u-button
|
||||
@click="handleApproval(item)"
|
||||
type="primary"
|
||||
size="small"
|
||||
shape="circle"
|
||||
>
|
||||
<u-icon
|
||||
name="edit-pen"
|
||||
size="16"
|
||||
color="#fff"
|
||||
style="margin-right: 8rpx"
|
||||
></u-icon>
|
||||
办理
|
||||
</u-button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<view class="card-actions">
|
||||
<u-button
|
||||
@click="handleApproval(item)"
|
||||
type="primary"
|
||||
size="small"
|
||||
shape="circle"
|
||||
>
|
||||
<u-icon
|
||||
name="edit-pen"
|
||||
size="16"
|
||||
color="#fff"
|
||||
style="margin-right: 8rpx"
|
||||
></u-icon>
|
||||
办理
|
||||
</u-button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 滚动加载更多 -->
|
||||
<u-loadmore
|
||||
v-if="taskList.length > 0"
|
||||
:status="loadmoreStatus"
|
||||
:load-text="{
|
||||
loadmore: '轻轻上拉',
|
||||
loading: '努力加载中',
|
||||
nomore: '没有更多了',
|
||||
}"
|
||||
@loadmore="loadMore"
|
||||
></u-loadmore>
|
||||
<!-- 滚动加载更多状态 -->
|
||||
<view v-if="taskList.length > 0" class="loadmore-status">
|
||||
<u-loadmore
|
||||
:status="loadmoreStatus"
|
||||
:load-text="{
|
||||
loadmore: '轻轻上拉加载更多',
|
||||
loading: '努力加载中...',
|
||||
nomore: '没有更多数据了',
|
||||
}"
|
||||
></u-loadmore>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
|
||||
<!-- 申请人选择弹窗 -->
|
||||
@@ -229,6 +247,10 @@ export default {
|
||||
total: 0,
|
||||
loadmoreStatus: 'loadmore', // loadmore, loading, nomore
|
||||
|
||||
// 滚动相关
|
||||
scrollTop: 0,
|
||||
refreshing: false,
|
||||
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
pageNum: 1,
|
||||
@@ -262,6 +284,8 @@ export default {
|
||||
|
||||
async created() {
|
||||
await this.loadFlowStatusDict();
|
||||
// 重置滚动位置
|
||||
this.scrollTop = 0;
|
||||
await this.getList();
|
||||
},
|
||||
|
||||
@@ -320,6 +344,8 @@ export default {
|
||||
if (!isLoadMore) {
|
||||
this.loading = true;
|
||||
this.queryParams.pageNum = 1;
|
||||
// 非加载更多时重置滚动位置
|
||||
this.scrollTop = 0;
|
||||
} else {
|
||||
this.loadmoreStatus = 'loading';
|
||||
}
|
||||
@@ -400,6 +426,8 @@ export default {
|
||||
|
||||
// 搜索操作
|
||||
handleQuery() {
|
||||
// 重置滚动位置
|
||||
this.scrollTop = 0;
|
||||
this.getList();
|
||||
},
|
||||
|
||||
@@ -413,6 +441,35 @@ export default {
|
||||
this.getList(true);
|
||||
},
|
||||
|
||||
// 下拉刷新
|
||||
async onRefresh() {
|
||||
this.refreshing = true;
|
||||
try {
|
||||
// 重置分页参数
|
||||
this.queryParams.pageNum = 1;
|
||||
this.loadmoreStatus = 'loadmore';
|
||||
|
||||
// 重新加载数据
|
||||
await this.getList();
|
||||
|
||||
// 显示刷新成功提示
|
||||
uni.showToast({
|
||||
title: '刷新成功',
|
||||
icon: 'success',
|
||||
duration: 1500,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('下拉刷新失败:', error);
|
||||
uni.showToast({
|
||||
title: '刷新失败',
|
||||
icon: 'none',
|
||||
duration: 1500,
|
||||
});
|
||||
} finally {
|
||||
this.refreshing = false;
|
||||
}
|
||||
},
|
||||
|
||||
// 格式化时间
|
||||
formatTime(timeStr) {
|
||||
if (!timeStr) return '-';
|
||||
@@ -536,6 +593,8 @@ export default {
|
||||
}
|
||||
|
||||
this.userSelectDialog.visible = false;
|
||||
// 重置滚动位置并查询
|
||||
this.scrollTop = 0;
|
||||
this.handleQuery();
|
||||
},
|
||||
|
||||
@@ -717,6 +776,12 @@ export default {
|
||||
|
||||
.content-wrapper {
|
||||
padding: 20rpx;
|
||||
height: calc(100vh - 200rpx); /* 减去导航栏和搜索区域的高度 */
|
||||
}
|
||||
|
||||
.task-scroll-list {
|
||||
height: 100%;
|
||||
padding: 0 20rpx;
|
||||
}
|
||||
|
||||
.empty-container {
|
||||
@@ -744,6 +809,12 @@ export default {
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.title-index {
|
||||
color: #000000;
|
||||
font-weight: bold;
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
|
||||
.task-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
@@ -923,4 +994,9 @@ export default {
|
||||
::v-deep .u-loadmore {
|
||||
padding: 40rpx 0;
|
||||
}
|
||||
|
||||
.loadmore-status {
|
||||
padding: 20rpx 0;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
@@ -92,6 +92,12 @@
|
||||
<!-- 请假记录卡片列表 -->
|
||||
<view v-else class="leave-list">
|
||||
<view v-for="(item, index) in leaveList" :key="item.id || index" class="leave-card">
|
||||
<!-- 序号标识 -->
|
||||
<view class="card-index">
|
||||
<text class="index-text">
|
||||
{{ getItemIndex(index) }}
|
||||
</text>
|
||||
</view>
|
||||
<!-- 卡片头部 -->
|
||||
<view class="card-header">
|
||||
<view class="leave-info">
|
||||
@@ -478,7 +484,11 @@ export default {
|
||||
本次加载: newData.length,
|
||||
总数: this.total,
|
||||
列表长度: this.leaveList.length,
|
||||
分页状态: this.loadStatus,
|
||||
});
|
||||
|
||||
// 验证序号连续性
|
||||
this.validateIndexContinuity();
|
||||
} else {
|
||||
console.warn('获取请假记录失败:', res?.msg);
|
||||
uni.showToast({
|
||||
@@ -518,7 +528,12 @@ export default {
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('📄 开始加载更多数据...');
|
||||
console.log('📄 开始加载更多数据...', {
|
||||
当前页码: this.queryParams.pageNum,
|
||||
当前列表长度: this.leaveList.length,
|
||||
总数: this.total,
|
||||
});
|
||||
|
||||
this.queryParams.pageNum += 1;
|
||||
await this.loadLeaveList(false);
|
||||
},
|
||||
@@ -604,11 +619,17 @@ export default {
|
||||
// 搜索操作
|
||||
handleQuery() {
|
||||
console.log('🔍 执行搜索:', this.queryParams);
|
||||
|
||||
// 搜索时重置分页状态
|
||||
this.queryParams.pageNum = 1;
|
||||
this.loadStatus = 'loadmore';
|
||||
|
||||
this.loadLeaveList();
|
||||
},
|
||||
|
||||
// 重置搜索
|
||||
resetQuery() {
|
||||
console.log('🔄 重置搜索条件...');
|
||||
this.queryParams.startTime = '';
|
||||
this.queryParams.endTime = '';
|
||||
this.queryParams.approvalStatus = '';
|
||||
@@ -616,6 +637,12 @@ export default {
|
||||
this.endTimeDisplay = '';
|
||||
this.startTimeValue = '';
|
||||
this.endTimeValue = '';
|
||||
|
||||
// 重置分页状态
|
||||
this.queryParams.pageNum = 1;
|
||||
this.loadStatus = 'loadmore';
|
||||
|
||||
console.log('🔄 重置完成,开始加载数据...');
|
||||
this.loadLeaveList();
|
||||
},
|
||||
|
||||
@@ -703,6 +730,60 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
// 计算列表项序号
|
||||
getItemIndex(index) {
|
||||
// 序号应该基于数据在列表中的实际位置,而不是基于当前请求的页码
|
||||
// 直接使用 index + 1,因为数据已经按顺序合并到 leaveList 中
|
||||
const finalIndex = index + 1;
|
||||
|
||||
// 调试信息
|
||||
console.log('🔢 序号计算:', {
|
||||
当前项索引: index,
|
||||
最终序号: finalIndex,
|
||||
列表总长度: this.leaveList.length,
|
||||
});
|
||||
|
||||
return finalIndex;
|
||||
},
|
||||
|
||||
// 验证序号连续性
|
||||
validateIndexContinuity() {
|
||||
if (this.leaveList.length === 0) return;
|
||||
|
||||
console.log('🔍 验证序号连续性...');
|
||||
const expectedIndices = [];
|
||||
|
||||
for (let i = 0; i < this.leaveList.length; i++) {
|
||||
const expectedIndex = i + 1;
|
||||
const actualIndex = this.getItemIndex(i);
|
||||
expectedIndices.push({ position: i, expected: expectedIndex, actual: actualIndex });
|
||||
}
|
||||
|
||||
console.log('🔍 序号验证结果:', expectedIndices);
|
||||
|
||||
// 检查是否有不连续的序号
|
||||
const hasDiscontinuity = expectedIndices.some((item, index) => {
|
||||
if (index === 0) return false;
|
||||
return item.expected !== expectedIndices[index - 1].expected + 1;
|
||||
});
|
||||
|
||||
if (hasDiscontinuity) {
|
||||
console.warn('⚠️ 发现序号不连续:', expectedIndices);
|
||||
} else {
|
||||
console.log('✅ 序号连续性验证通过');
|
||||
}
|
||||
|
||||
// 额外验证:检查序号范围
|
||||
const minIndex = Math.min(...expectedIndices.map((item) => item.actual));
|
||||
const maxIndex = Math.max(...expectedIndices.map((item) => item.actual));
|
||||
console.log('🔍 序号范围验证:', {
|
||||
最小序号: minIndex,
|
||||
最大序号: maxIndex,
|
||||
期望范围: `1-${this.leaveList.length}`,
|
||||
是否正常: minIndex === 1 && maxIndex === this.leaveList.length,
|
||||
});
|
||||
},
|
||||
|
||||
// 查看详情
|
||||
handleViewDetail(item) {
|
||||
const detailInfo = [
|
||||
@@ -863,6 +944,26 @@ export default {
|
||||
border-radius: 16rpx;
|
||||
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08);
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
// 序号标识
|
||||
.card-index {
|
||||
position: absolute;
|
||||
top: 8rpx;
|
||||
left: 8rpx;
|
||||
background-color: #f5f6fa;
|
||||
padding: 6rpx 12rpx;
|
||||
border-radius: 8rpx;
|
||||
z-index: 1;
|
||||
min-width: 32rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.index-text {
|
||||
font-size: 24rpx;
|
||||
color: #909399;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
// 卡片头部
|
||||
@@ -871,6 +972,7 @@ export default {
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
padding: 24rpx;
|
||||
padding-left: 80rpx; // 为序号预留左边空间
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
background: linear-gradient(135deg, #f8f9fa 0%, #ffffff 100%);
|
||||
}
|
||||
@@ -928,6 +1030,7 @@ export default {
|
||||
// 卡片内容
|
||||
.card-content {
|
||||
padding: 24rpx;
|
||||
padding-left: 80rpx; // 与头部对齐
|
||||
}
|
||||
|
||||
.info-section {
|
||||
@@ -1021,6 +1124,7 @@ export default {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
padding: 20rpx;
|
||||
padding-left: 80rpx; // 与头部对齐
|
||||
border-top: 1px solid #f0f0f0;
|
||||
gap: 16rpx;
|
||||
}
|
||||
@@ -1080,8 +1184,21 @@ export default {
|
||||
}
|
||||
|
||||
.card-header,
|
||||
.card-content {
|
||||
.card-content,
|
||||
.card-actions {
|
||||
padding: 20rpx;
|
||||
padding-left: 70rpx; // 小屏幕下为序号预留左边空间
|
||||
}
|
||||
|
||||
.card-index {
|
||||
top: 6rpx;
|
||||
left: 6rpx;
|
||||
padding: 4rpx 8rpx;
|
||||
min-width: 28rpx;
|
||||
}
|
||||
|
||||
.index-text {
|
||||
font-size: 22rpx;
|
||||
}
|
||||
|
||||
.fab-button {
|
||||
|
||||
@@ -39,7 +39,10 @@
|
||||
>
|
||||
<!-- 卡片头部 -->
|
||||
<view class="card-header">
|
||||
<view class="batch-title">{{ item.batchName || '-' }}</view>
|
||||
<view class="batch-title">
|
||||
<text class="batch-number">{{ index + 1 }}.</text>
|
||||
<text>{{ item.batchName || '-' }}</text>
|
||||
</view>
|
||||
<view class="batch-status">
|
||||
<u-tag
|
||||
:text="item.status === '0' ? '正常' : '停用'"
|
||||
@@ -90,7 +93,12 @@
|
||||
></u-icon>
|
||||
信息完善
|
||||
</u-button>
|
||||
<u-button type="info" shape="round" size="small" @click="handleViewHistory(item)">
|
||||
<u-button
|
||||
type="info"
|
||||
shape="round"
|
||||
size="small"
|
||||
@click="handleViewHistory(item)"
|
||||
>
|
||||
<u-icon
|
||||
name="clock"
|
||||
size="14"
|
||||
@@ -450,6 +458,13 @@ export default {
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.batch-number {
|
||||
color: #000000;
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
|
||||
.batch-status {
|
||||
|
||||
@@ -50,12 +50,15 @@
|
||||
</view>
|
||||
|
||||
<!-- 加载状态 -->
|
||||
<u-loading-page :loading="loading" loading-text="加载中..."></u-loading-page>
|
||||
<u-loading-page
|
||||
:loading="loading && queryParams.pageNum === 1"
|
||||
loading-text="加载中..."
|
||||
></u-loading-page>
|
||||
|
||||
<!-- 列表内容 -->
|
||||
<view v-if="!loading" class="content-wrapper">
|
||||
<view v-if="!loading || queryParams.pageNum > 1" class="content-wrapper">
|
||||
<!-- 空状态 -->
|
||||
<view v-if="dormViolationList.length === 0" class="empty-container">
|
||||
<view v-if="dormViolationList.length === 0 && !loading" class="empty-container">
|
||||
<u-empty text="暂无违纪记录" mode="data"></u-empty>
|
||||
</view>
|
||||
|
||||
@@ -66,6 +69,13 @@
|
||||
:key="item.id || index"
|
||||
class="violation-card"
|
||||
>
|
||||
<!-- 序号标识 -->
|
||||
<view class="card-index">
|
||||
<text class="index-text">
|
||||
{{ index + 1 }}
|
||||
</text>
|
||||
</view>
|
||||
|
||||
<!-- 卡片头部 -->
|
||||
<view class="card-header">
|
||||
<view class="student-info">
|
||||
@@ -178,15 +188,18 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 加载更多 -->
|
||||
<view v-if="hasMore" class="load-more">
|
||||
<u-loadmore
|
||||
:status="loadMoreStatus"
|
||||
@loadmore="loadMore"
|
||||
:loading-text="loadingText"
|
||||
:loadmore-text="loadMoreText"
|
||||
:nomore-text="noMoreText"
|
||||
></u-loadmore>
|
||||
<!-- 底部加载状态提示 -->
|
||||
<view v-if="dormViolationList.length > 0" class="load-status">
|
||||
<view v-if="loading && queryParams.pageNum > 1" class="loading-tip">
|
||||
<u-loading-icon mode="circle" size="32"></u-loading-icon>
|
||||
<text class="loading-text">加载中...</text>
|
||||
</view>
|
||||
<view v-else-if="!hasMore" class="no-more-tip">
|
||||
<text class="no-more-text">没有更多数据了</text>
|
||||
</view>
|
||||
<view v-else-if="dormViolationList.length >= 10" class="pull-tip">
|
||||
<text class="pull-text">上拉加载更多</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -205,10 +218,6 @@ export default {
|
||||
dormViolationList: [],
|
||||
total: 0,
|
||||
hasMore: true,
|
||||
loadMoreStatus: 'loadmore',
|
||||
loadingText: '努力加载中...',
|
||||
loadMoreText: '点击或上拉加载更多',
|
||||
noMoreText: '没有更多了',
|
||||
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
@@ -253,6 +262,16 @@ export default {
|
||||
await this.initData();
|
||||
},
|
||||
|
||||
// 监听页面触底事件
|
||||
onReachBottom() {
|
||||
this.loadMore();
|
||||
},
|
||||
|
||||
// 监听下拉刷新事件
|
||||
onPullDownRefresh() {
|
||||
this.refreshData();
|
||||
},
|
||||
|
||||
methods: {
|
||||
// 返回上一页
|
||||
goBack() {
|
||||
@@ -296,10 +315,19 @@ export default {
|
||||
|
||||
// 获取违纪记录列表
|
||||
async getList(isLoadMore = false) {
|
||||
if (this.loading) return;
|
||||
// 防止重复加载
|
||||
if (this.loading) {
|
||||
console.log('正在加载中,跳过本次请求');
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果没有更多数据且是加载更多操作,直接返回
|
||||
if (isLoadMore && !this.hasMore) {
|
||||
console.log('没有更多数据,跳过加载更多');
|
||||
return;
|
||||
}
|
||||
|
||||
this.loading = true;
|
||||
this.loadMoreStatus = 'loading';
|
||||
|
||||
try {
|
||||
// 获取当前登录用户信息
|
||||
@@ -326,24 +354,52 @@ export default {
|
||||
if (res && res.code === 200) {
|
||||
const { rows, total } = res;
|
||||
|
||||
// 确保 rows 是数组
|
||||
const newData = Array.isArray(rows) ? rows : [];
|
||||
|
||||
console.log('API返回数据:', {
|
||||
isLoadMore: isLoadMore,
|
||||
pageNum: this.queryParams.pageNum,
|
||||
apiReturnedCount: newData.length,
|
||||
currentListLength: this.dormViolationList.length,
|
||||
total: total,
|
||||
});
|
||||
|
||||
if (isLoadMore) {
|
||||
this.dormViolationList = [...this.dormViolationList, ...rows];
|
||||
// 加载更多时,追加数据(去重处理)
|
||||
const existingIds = new Set(this.dormViolationList.map((item) => item.id));
|
||||
const uniqueNewData = newData.filter((item) => !existingIds.has(item.id));
|
||||
|
||||
console.log('加载更多去重处理:', {
|
||||
existingCount: this.dormViolationList.length,
|
||||
newDataCount: newData.length,
|
||||
uniqueNewDataCount: uniqueNewData.length,
|
||||
duplicateCount: newData.length - uniqueNewData.length,
|
||||
});
|
||||
|
||||
this.dormViolationList = [...this.dormViolationList, ...uniqueNewData];
|
||||
} else {
|
||||
this.dormViolationList = rows;
|
||||
// 首次加载或搜索时,替换数据
|
||||
this.dormViolationList = newData;
|
||||
}
|
||||
|
||||
this.total = total;
|
||||
|
||||
// 更新是否还有更多数据的状态
|
||||
this.hasMore = this.dormViolationList.length < total;
|
||||
|
||||
console.log('获取违纪记录成功:', {
|
||||
current: this.dormViolationList.length,
|
||||
finalListLength: this.dormViolationList.length,
|
||||
total: total,
|
||||
hasMore: this.hasMore,
|
||||
isLoadMore: isLoadMore,
|
||||
pageNum: this.queryParams.pageNum,
|
||||
});
|
||||
} else {
|
||||
if (!isLoadMore) {
|
||||
this.dormViolationList = [];
|
||||
this.total = 0;
|
||||
this.hasMore = false;
|
||||
}
|
||||
uni.showToast({
|
||||
title: res?.msg || '获取数据失败',
|
||||
@@ -355,6 +411,7 @@ export default {
|
||||
if (!isLoadMore) {
|
||||
this.dormViolationList = [];
|
||||
this.total = 0;
|
||||
this.hasMore = false;
|
||||
}
|
||||
uni.showToast({
|
||||
title: '获取数据失败',
|
||||
@@ -362,13 +419,17 @@ export default {
|
||||
});
|
||||
} finally {
|
||||
this.loading = false;
|
||||
this.loadMoreStatus = this.hasMore ? 'loadmore' : 'nomore';
|
||||
// 结束下拉刷新
|
||||
if (!isLoadMore) {
|
||||
uni.stopPullDownRefresh();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// 搜索操作
|
||||
handleQuery() {
|
||||
this.queryParams.pageNum = 1;
|
||||
this.hasMore = true;
|
||||
this.getList();
|
||||
},
|
||||
|
||||
@@ -379,10 +440,18 @@ export default {
|
||||
pageSize: 10,
|
||||
violationTime: '',
|
||||
};
|
||||
this.hasMore = true;
|
||||
this.getList();
|
||||
},
|
||||
|
||||
// 加载更多
|
||||
// 下拉刷新
|
||||
refreshData() {
|
||||
this.queryParams.pageNum = 1;
|
||||
this.hasMore = true;
|
||||
this.getList();
|
||||
},
|
||||
|
||||
// 加载更多(滚动到底部触发)
|
||||
loadMore() {
|
||||
if (this.hasMore && !this.loading) {
|
||||
this.queryParams.pageNum++;
|
||||
@@ -554,13 +623,34 @@ export default {
|
||||
border-radius: 16rpx;
|
||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.card-index {
|
||||
position: absolute;
|
||||
top: 12rpx;
|
||||
left: 12rpx;
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
background-color: rgba(162, 161, 161, 0.8);
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.index-text {
|
||||
font-size: 22rpx;
|
||||
font-weight: bold;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 24rpx;
|
||||
padding: 24rpx 24rpx 24rpx 70rpx;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
@@ -673,10 +763,42 @@ export default {
|
||||
border-top: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.load-more {
|
||||
// 底部加载状态样式
|
||||
.load-status {
|
||||
padding: 30rpx 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.loading-tip {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.loading-text {
|
||||
font-size: 26rpx;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.no-more-tip {
|
||||
padding: 20rpx 0;
|
||||
}
|
||||
|
||||
.no-more-text {
|
||||
font-size: 26rpx;
|
||||
color: #c0c4cc;
|
||||
}
|
||||
|
||||
.pull-tip {
|
||||
padding: 20rpx 0;
|
||||
}
|
||||
|
||||
.pull-text {
|
||||
font-size: 26rpx;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
// uview组件样式调整
|
||||
::v-deep .u-tag {
|
||||
margin: 0;
|
||||
@@ -684,13 +806,11 @@ export default {
|
||||
|
||||
::v-deep .u-button {
|
||||
flex: 1;
|
||||
// max-width: 200rpx;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
|
||||
// 搜索按钮样式
|
||||
::v-deep .search-btn {
|
||||
// background: linear-gradient(135deg, #007aff, #0051d9) !important;
|
||||
border: none !important;
|
||||
box-shadow: 0 4px 16px rgba(0, 122, 255, 0.3) !important;
|
||||
transition: all 0.3s ease !important;
|
||||
|
||||
@@ -48,7 +48,10 @@
|
||||
<view class="card-header">
|
||||
<!-- 第一行:标题和卫生等级 -->
|
||||
<view class="header-row">
|
||||
<view class="check-title">{{ item.checkTitle || '-' }}</view>
|
||||
<view class="check-title">
|
||||
<text class="title-index">{{ index + 1 }}.</text>
|
||||
{{ item.checkTitle || '-' }}
|
||||
</view>
|
||||
<view class="grade-section">
|
||||
<u-tag
|
||||
:text="$getDictLabel(xg_dorm_hygiene_grade, item.hygieneGrade)"
|
||||
@@ -151,22 +154,37 @@
|
||||
<!-- 操作按钮 -->
|
||||
<view class="card-actions">
|
||||
<!-- 查看按钮 -->
|
||||
<view class="action-btn primary-btn" @click="handleView(item)">
|
||||
<u-icon name="eye" size="16" color="#19be6b"></u-icon>
|
||||
<text class="btn-text">查看</text>
|
||||
</view>
|
||||
<u-button
|
||||
type="info"
|
||||
size="small"
|
||||
class="action-btn"
|
||||
@click="handleView(item)"
|
||||
>
|
||||
<u-icon name="eye" size="16" color="#323233"></u-icon>
|
||||
<text>查看</text>
|
||||
</u-button>
|
||||
|
||||
<!-- 修改按钮 -->
|
||||
<view class="action-btn info-btn" @click="handleUpdate(item)">
|
||||
<u-icon name="edit-pen" size="16" color="#3c9cff"></u-icon>
|
||||
<u-button
|
||||
type="primary"
|
||||
size="small"
|
||||
class="action-btn"
|
||||
@click="handleUpdate(item)"
|
||||
>
|
||||
<u-icon name="edit-pen" size="16" color="#ffffff"></u-icon>
|
||||
<text class="btn-text">修改</text>
|
||||
</view>
|
||||
</u-button>
|
||||
|
||||
<!-- 删除按钮 -->
|
||||
<view class="action-btn danger-btn" @click="handleDelete(item)">
|
||||
<u-icon name="trash" size="16" color="#f56c6c"></u-icon>
|
||||
<u-button
|
||||
type="error"
|
||||
size="small"
|
||||
class="action-btn"
|
||||
@click="handleDelete(item)"
|
||||
>
|
||||
<u-icon name="trash" size="16" color="#ffffff"></u-icon>
|
||||
<text class="btn-text">删除</text>
|
||||
</view>
|
||||
</u-button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -608,6 +626,12 @@ export default {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.title-index {
|
||||
color: #000000;
|
||||
font-weight: bold;
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
|
||||
.check-level {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
@@ -733,37 +757,26 @@ export default {
|
||||
|
||||
.action-btn {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 16rpx 20rpx;
|
||||
border-radius: 12rpx;
|
||||
min-width: 120rpx;
|
||||
transition: all 0.3s ease;
|
||||
background-color: transparent;
|
||||
border-radius: 20rpx;
|
||||
|
||||
&:active {
|
||||
transform: scale(0.95);
|
||||
opacity: 0.8;
|
||||
::v-deep .u-button {
|
||||
border-radius: 20rpx;
|
||||
padding: 16rpx 20rpx;
|
||||
min-width: 120rpx;
|
||||
height: auto;
|
||||
line-height: 1.2;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-text {
|
||||
font-size: 24rpx;
|
||||
margin-top: 8rpx;
|
||||
margin-left: 8rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.primary-btn .btn-text {
|
||||
color: #19be6b;
|
||||
}
|
||||
|
||||
.info-btn .btn-text {
|
||||
color: #3c9cff;
|
||||
}
|
||||
|
||||
.danger-btn .btn-text {
|
||||
color: #f56c6c;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
// 分页容器
|
||||
|
||||
@@ -60,7 +60,10 @@
|
||||
<view class="card-header">
|
||||
<!-- 第一行:标题和卫生等级 -->
|
||||
<view class="header-row">
|
||||
<view class="check-title">{{ item.checkTitle || '-' }}</view>
|
||||
<view class="check-title">
|
||||
<text class="check-index">{{ index + 1 }}.</text>
|
||||
<text>{{ item.checkTitle || '-' }}</text>
|
||||
</view>
|
||||
<view class="grade-section">
|
||||
<u-tag
|
||||
:text="$getDictLabel(xg_dorm_hygiene_grade, item.hygieneGrade)"
|
||||
@@ -189,8 +192,8 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 分页加载(已废弃,因为接口返回完整列表) -->
|
||||
<!-- <view v-if="checkList.length > 0" class="pagination-container">
|
||||
<!-- 分页加载 -->
|
||||
<view v-if="checkList.length > 0" class="pagination-container">
|
||||
<u-loadmore
|
||||
:status="loadStatus"
|
||||
@loadmore="loadMore"
|
||||
@@ -198,7 +201,7 @@
|
||||
loading-text="正在加载..."
|
||||
no-more-text="没有更多数据了"
|
||||
/>
|
||||
</view> -->
|
||||
</view>
|
||||
|
||||
<!-- 悬浮添加按钮 -->
|
||||
<!-- <view class="fab-button" @click="handleAdd">
|
||||
@@ -227,7 +230,6 @@ export default {
|
||||
|
||||
// 检查记录列表
|
||||
checkList: [],
|
||||
originalCheckList: [], // 原始数据,用于前端过滤
|
||||
total: 0,
|
||||
|
||||
// 分页加载状态
|
||||
@@ -260,11 +262,11 @@ export default {
|
||||
uni.$off('refreshCheckList', this.handleRefreshEvent);
|
||||
},
|
||||
|
||||
// 页面滚动到底部事件(已废弃,因为接口返回完整列表)
|
||||
// onReachBottom() {
|
||||
// console.log('🔄 触发滚动到底部事件,开始加载更多...');
|
||||
// this.loadMore();
|
||||
// },
|
||||
// 页面滚动到底部事件
|
||||
onReachBottom() {
|
||||
console.log('🔄 触发滚动到底部事件,开始加载更多...');
|
||||
this.loadMore();
|
||||
},
|
||||
|
||||
methods: {
|
||||
// 处理刷新事件
|
||||
@@ -313,7 +315,11 @@ export default {
|
||||
this.loading = true;
|
||||
this.queryParams.pageNum = 1;
|
||||
this.checkList = [];
|
||||
this.loadStatus = 'loadmore';
|
||||
} else {
|
||||
if (this.loadStatus === 'loading' || this.loadStatus === 'nomore') {
|
||||
return;
|
||||
}
|
||||
this.loadStatus = 'loading';
|
||||
}
|
||||
|
||||
@@ -331,35 +337,50 @@ export default {
|
||||
console.log('📋 开始加载当前学生的宿舍卫生检查记录...', {
|
||||
学生ID: currentUser.userId,
|
||||
查询参数: this.queryParams,
|
||||
是否刷新: isRefresh,
|
||||
});
|
||||
|
||||
// 调用根据学生ID查询卫生检查记录的接口
|
||||
// 构建请求参数
|
||||
const params = {
|
||||
pageNum: this.queryParams.pageNum,
|
||||
pageSize: this.queryParams.pageSize,
|
||||
};
|
||||
|
||||
// 添加搜索条件
|
||||
if (this.queryParams.checkTitle && this.queryParams.checkTitle.trim()) {
|
||||
params.checkTitle = this.queryParams.checkTitle.trim();
|
||||
}
|
||||
|
||||
// 调用分页接口
|
||||
const res = await request({
|
||||
url: `/dormHygieneCheck/dormHygieneCheck/student/${currentUser.userId}`,
|
||||
url: `/dormHygieneCheck/dormHygieneCheck/student/${currentUser.userId}/page`,
|
||||
method: 'GET',
|
||||
params: params,
|
||||
});
|
||||
|
||||
if (res && res.code === 200) {
|
||||
const newData = res.data || [];
|
||||
const newData = res.rows || [];
|
||||
const total = res.total || 0;
|
||||
|
||||
if (isRefresh) {
|
||||
this.originalCheckList = newData; // 保存原始数据
|
||||
this.checkList = newData;
|
||||
} else {
|
||||
this.originalCheckList = [...this.originalCheckList, ...newData];
|
||||
this.checkList = [...this.checkList, ...newData];
|
||||
}
|
||||
|
||||
this.total = newData.length;
|
||||
this.total = total;
|
||||
|
||||
// 由于getHygieneChecksByStudentId返回的是完整列表,不需要分页加载
|
||||
this.loadStatus = 'nomore';
|
||||
// 判断是否还有更多数据
|
||||
const hasMore = this.queryParams.pageNum * this.queryParams.pageSize < total;
|
||||
this.loadStatus = hasMore ? 'loadmore' : 'nomore';
|
||||
|
||||
console.log('✅ 学生宿舍卫生检查记录加载成功:', {
|
||||
学生ID: currentUser.userId,
|
||||
当前页码: this.queryParams.pageNum,
|
||||
本次加载: newData.length,
|
||||
总数: this.total,
|
||||
总数: total,
|
||||
列表长度: this.checkList.length,
|
||||
是否还有更多: hasMore,
|
||||
});
|
||||
} else {
|
||||
console.warn('获取学生宿舍卫生检查记录失败:', res?.msg);
|
||||
@@ -368,9 +389,7 @@ export default {
|
||||
icon: 'none',
|
||||
});
|
||||
|
||||
if (!isRefresh) {
|
||||
this.loadStatus = 'loadmore';
|
||||
}
|
||||
this.loadStatus = isRefresh ? 'loadmore' : 'loadmore';
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('❌ 加载学生宿舍卫生检查记录失败:', error);
|
||||
@@ -379,9 +398,7 @@ export default {
|
||||
icon: 'none',
|
||||
});
|
||||
|
||||
if (!isRefresh) {
|
||||
this.loadStatus = 'loadmore';
|
||||
}
|
||||
this.loadStatus = isRefresh ? 'loadmore' : 'loadmore';
|
||||
} finally {
|
||||
if (isRefresh) {
|
||||
this.loading = false;
|
||||
@@ -389,51 +406,35 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
// 加载更多(已废弃,因为getHygieneChecksByStudentId返回完整列表)
|
||||
// 加载更多
|
||||
async loadMore() {
|
||||
console.log('📄 当前接口返回完整列表,无需分页加载');
|
||||
// 由于getHygieneChecksByStudentId返回的是完整列表,不需要分页加载
|
||||
this.loadStatus = 'nomore';
|
||||
console.log('📄 触发加载更多,当前状态:', this.loadStatus);
|
||||
|
||||
if (this.loadStatus !== 'loadmore') {
|
||||
console.log('📄 当前状态不允许加载更多:', this.loadStatus);
|
||||
return;
|
||||
}
|
||||
|
||||
// 增加页码,加载下一页数据
|
||||
this.queryParams.pageNum += 1;
|
||||
console.log('📄 加载第', this.queryParams.pageNum, '页数据');
|
||||
|
||||
await this.loadCheckList(false);
|
||||
},
|
||||
|
||||
// 搜索操作(前端过滤)
|
||||
// 搜索操作(后端过滤)
|
||||
handleQuery() {
|
||||
console.log('🔍 执行前端搜索过滤:', this.queryParams);
|
||||
// 由于接口返回完整列表,在前端进行过滤
|
||||
this.filterCheckList();
|
||||
console.log('🔍 执行搜索查询:', this.queryParams);
|
||||
// 重新从第一页开始搜索
|
||||
this.loadCheckList(true);
|
||||
},
|
||||
|
||||
// 重置搜索
|
||||
resetQuery() {
|
||||
this.queryParams.checkTitle = '';
|
||||
this.filterCheckList();
|
||||
},
|
||||
|
||||
// 前端过滤检查记录列表
|
||||
filterCheckList() {
|
||||
if (!this.originalCheckList || this.originalCheckList.length === 0) {
|
||||
this.checkList = [];
|
||||
return;
|
||||
}
|
||||
|
||||
let filteredList = [...this.originalCheckList];
|
||||
|
||||
// 按检查标题过滤
|
||||
if (this.queryParams.checkTitle && this.queryParams.checkTitle.trim()) {
|
||||
const searchTerm = this.queryParams.checkTitle.trim().toLowerCase();
|
||||
filteredList = filteredList.filter(
|
||||
(item) => item.checkTitle && item.checkTitle.toLowerCase().includes(searchTerm),
|
||||
);
|
||||
}
|
||||
|
||||
this.checkList = filteredList;
|
||||
this.total = filteredList.length;
|
||||
|
||||
console.log('✅ 前端过滤完成:', {
|
||||
原始数据: this.originalCheckList.length,
|
||||
过滤后: this.checkList.length,
|
||||
搜索条件: this.queryParams.checkTitle,
|
||||
});
|
||||
console.log('🔄 重置搜索条件');
|
||||
// 重新加载数据
|
||||
this.loadCheckList(true);
|
||||
},
|
||||
|
||||
// 获取检查级别类型
|
||||
@@ -655,6 +656,14 @@ export default {
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
}
|
||||
|
||||
.check-index {
|
||||
color: #000000;
|
||||
font-weight: bold;
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
|
||||
.check-level {
|
||||
@@ -815,10 +824,10 @@ export default {
|
||||
color: #f56c6c;
|
||||
}
|
||||
|
||||
// 分页容器(已废弃)
|
||||
// .pagination-container {
|
||||
// padding: 20rpx;
|
||||
// }
|
||||
// 分页容器
|
||||
.pagination-container {
|
||||
padding: 20rpx;
|
||||
}
|
||||
|
||||
// 搜索按钮样式
|
||||
::v-deep .search-btn {
|
||||
|
||||
+206
-119
@@ -17,101 +17,126 @@
|
||||
<u-empty text="暂无可申请的考核计划" mode="data"></u-empty>
|
||||
</view>
|
||||
|
||||
<!-- 考核计划列表 -->
|
||||
<view v-else class="schedule-list">
|
||||
<view
|
||||
v-for="(item, index) in assessmentScheduleList"
|
||||
:key="item.id || index"
|
||||
class="schedule-card"
|
||||
>
|
||||
<!-- 卡片头部 -->
|
||||
<view class="card-header">
|
||||
<view class="schedule-info">
|
||||
<text class="schedule-name">{{ item.scheduleName || '暂无' }}</text>
|
||||
<view class="schedule-meta">
|
||||
<text class="academic-info">
|
||||
{{ item.academicYear || '暂无' }}
|
||||
{{ getSemesterText(item.semester) }}
|
||||
<!-- 考核计划列表 - 滚动加载 -->
|
||||
<scroll-view
|
||||
v-else
|
||||
class="schedule-scroll-view"
|
||||
scroll-y
|
||||
@scrolltolower="handleScrollToLower"
|
||||
:lower-threshold="100"
|
||||
>
|
||||
<view class="schedule-list">
|
||||
<view
|
||||
v-for="(item, index) in assessmentScheduleList"
|
||||
:key="item.id || index"
|
||||
class="schedule-card"
|
||||
>
|
||||
<!-- 卡片头部 -->
|
||||
<view class="card-header">
|
||||
<view class="schedule-info">
|
||||
<view class="schedule-name-wrapper">
|
||||
<text class="schedule-index">{{ index + 1 }}.</text>
|
||||
<text class="schedule-name">
|
||||
{{ item.scheduleName || '暂无' }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="schedule-meta">
|
||||
<text class="academic-info">
|
||||
{{ item.academicYear || '暂无' }}
|
||||
{{ getSemesterText(item.semester) }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="status-info">
|
||||
<u-tag
|
||||
:text="getStatusText(item.status)"
|
||||
:type="getStatusTagType(item.status)"
|
||||
size="mini"
|
||||
></u-tag>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 卡片内容 -->
|
||||
<view class="card-content">
|
||||
<view class="schedule-description">
|
||||
<text class="description-text">
|
||||
{{ item.description || '暂无说明' }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="time-info">
|
||||
<view class="time-item">
|
||||
<text class="time-label">开始时间:</text>
|
||||
<text class="time-value">{{ formatTime(item.startTime) }}</text>
|
||||
</view>
|
||||
<view class="time-item">
|
||||
<text class="time-label">结束时间:</text>
|
||||
<text class="time-value">{{ formatTime(item.endTime) }}</text>
|
||||
</view>
|
||||
<view class="time-item">
|
||||
<text class="time-label">数据统计开始时间:</text>
|
||||
<text class="time-value">
|
||||
{{ formatTime(item.dataStartTime) }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="time-item">
|
||||
<text class="time-label">数据统计结束时间:</text>
|
||||
<text class="time-value">
|
||||
{{ formatTime(item.dataEndTime) }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="plan-info">
|
||||
<text class="plan-name">
|
||||
考核方案: {{ item.planName || '暂无' }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="status-info">
|
||||
<u-tag
|
||||
:text="getStatusText(item.status)"
|
||||
:type="getStatusTagType(item.status)"
|
||||
size="mini"
|
||||
></u-tag>
|
||||
|
||||
<!-- 卡片操作按钮 -->
|
||||
<view class="card-actions">
|
||||
<u-button
|
||||
type="info"
|
||||
size="small"
|
||||
icon="eye"
|
||||
shape="round"
|
||||
@click="handleViewSchedule(item)"
|
||||
>
|
||||
查看计划
|
||||
</u-button>
|
||||
<u-button
|
||||
v-if="canSubmitApplication(item)"
|
||||
type="primary"
|
||||
size="small"
|
||||
icon="edit-pen"
|
||||
shape="round"
|
||||
@click="handleSubmitApplication(item)"
|
||||
>
|
||||
提交申请
|
||||
</u-button>
|
||||
<u-button
|
||||
type="warning"
|
||||
size="small"
|
||||
icon="file-text"
|
||||
shape="round"
|
||||
@click="handleViewApplication(item)"
|
||||
>
|
||||
查看申请
|
||||
</u-button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 卡片内容 -->
|
||||
<view class="card-content">
|
||||
<view class="schedule-description">
|
||||
<text class="description-text">
|
||||
{{ item.description || '暂无说明' }}
|
||||
</text>
|
||||
<!-- 加载更多状态提示 -->
|
||||
<view v-if="assessmentScheduleList.length > 0" class="load-more">
|
||||
<view v-if="loadingMore" class="loading-more">
|
||||
<u-loading-icon mode="circle" size="16"></u-loading-icon>
|
||||
<text class="loading-text">正在加载更多...</text>
|
||||
</view>
|
||||
<view class="time-info">
|
||||
<view class="time-item">
|
||||
<text class="time-label">开始时间:</text>
|
||||
<text class="time-value">{{ formatTime(item.startTime) }}</text>
|
||||
</view>
|
||||
<view class="time-item">
|
||||
<text class="time-label">结束时间:</text>
|
||||
<text class="time-value">{{ formatTime(item.endTime) }}</text>
|
||||
</view>
|
||||
<view class="time-item">
|
||||
<text class="time-label">数据统计开始时间:</text>
|
||||
<text class="time-value">{{ formatTime(item.dataStartTime) }}</text>
|
||||
</view>
|
||||
<view class="time-item">
|
||||
<text class="time-label">数据统计结束时间:</text>
|
||||
<text class="time-value">{{ formatTime(item.dataEndTime) }}</text>
|
||||
</view>
|
||||
<view v-else class="load-complete-text">
|
||||
{{ getNoMoreText() }}
|
||||
</view>
|
||||
<view class="plan-info">
|
||||
<text class="plan-name">考核方案: {{ item.planName || '暂无' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 卡片操作按钮 -->
|
||||
<view class="card-actions">
|
||||
<u-button
|
||||
type="info"
|
||||
size="small"
|
||||
icon="eye"
|
||||
shape="round"
|
||||
@click="handleViewSchedule(item)"
|
||||
>
|
||||
查看计划
|
||||
</u-button>
|
||||
<u-button
|
||||
v-if="canSubmitApplication(item)"
|
||||
type="primary"
|
||||
size="small"
|
||||
icon="edit-pen"
|
||||
shape="round"
|
||||
@click="handleSubmitApplication(item)"
|
||||
>
|
||||
提交申请
|
||||
</u-button>
|
||||
<u-button
|
||||
type="warning"
|
||||
size="small"
|
||||
icon="file-text"
|
||||
shape="round"
|
||||
@click="handleViewApplication(item)"
|
||||
>
|
||||
查看申请
|
||||
</u-button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 分页加载 -->
|
||||
<view v-if="hasMore && assessmentScheduleList.length > 0" class="load-more">
|
||||
<u-loadmore :status="loadStatus" @loadmore="loadMore"></u-loadmore>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
|
||||
<!-- 查看计划详情弹窗 -->
|
||||
@@ -231,6 +256,7 @@ export default {
|
||||
total: 0,
|
||||
hasMore: true,
|
||||
loadStatus: 'loadmore',
|
||||
loadingMore: false,
|
||||
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
@@ -276,9 +302,14 @@ export default {
|
||||
},
|
||||
|
||||
// 获取考核计划列表
|
||||
async getList(loadMore = false) {
|
||||
if (!loadMore) {
|
||||
async getList(isLoadMore = false) {
|
||||
if (isLoadMore) {
|
||||
this.loadingMore = true;
|
||||
} else {
|
||||
this.loading = true;
|
||||
// 重置分页参数
|
||||
this.queryParams.pageNum = 1;
|
||||
this.assessmentScheduleList = [];
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -290,38 +321,49 @@ export default {
|
||||
|
||||
if (res && res.code === 200) {
|
||||
const rows = res.rows || [];
|
||||
const total = res.total || 0;
|
||||
|
||||
if (loadMore) {
|
||||
this.assessmentScheduleList = this.assessmentScheduleList.concat(rows);
|
||||
if (isLoadMore) {
|
||||
// 加载更多时追加数据
|
||||
this.assessmentScheduleList = [...this.assessmentScheduleList, ...rows];
|
||||
} else {
|
||||
// 首次加载时直接设置数据
|
||||
this.assessmentScheduleList = rows;
|
||||
}
|
||||
|
||||
this.total = res.total || 0;
|
||||
this.total = total;
|
||||
|
||||
if (rows.length < this.queryParams.pageSize) {
|
||||
this.hasMore = false;
|
||||
this.loadStatus = 'nomore';
|
||||
} else {
|
||||
this.hasMore = true;
|
||||
this.loadStatus = 'loadmore';
|
||||
}
|
||||
// 判断是否还有更多数据
|
||||
const currentTotal = this.assessmentScheduleList.length;
|
||||
this.hasMore = currentTotal < total;
|
||||
this.loadStatus = this.hasMore ? 'loadmore' : 'nomore';
|
||||
|
||||
console.log('获取考核计划数据成功:', {
|
||||
当前页: this.queryParams.pageNum,
|
||||
返回条数: rows.length,
|
||||
累计条数: currentTotal,
|
||||
总数量: total,
|
||||
是否还有更多: this.hasMore,
|
||||
});
|
||||
} else {
|
||||
this.handleRequestError(res?.msg || '获取数据失败', loadMore);
|
||||
this.handleRequestError(res?.msg || '获取数据失败');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取数据失败:', error);
|
||||
this.handleRequestError('获取数据失败', loadMore);
|
||||
this.handleRequestError('获取数据失败');
|
||||
} finally {
|
||||
if (!loadMore) {
|
||||
if (isLoadMore) {
|
||||
this.loadingMore = false;
|
||||
} else {
|
||||
this.loading = false;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// 错误处理
|
||||
handleRequestError(message, isLoadMore = false) {
|
||||
if (!isLoadMore) {
|
||||
handleRequestError(message) {
|
||||
if (this.queryParams.pageNum === 1) {
|
||||
// 首次加载失败,清空数据
|
||||
this.assessmentScheduleList = [];
|
||||
this.total = 0;
|
||||
}
|
||||
@@ -334,22 +376,22 @@ export default {
|
||||
});
|
||||
},
|
||||
|
||||
// 加载更多
|
||||
async loadMore() {
|
||||
if (!this.hasMore || this.loadStatus !== 'loadmore') {
|
||||
// 滚动到底部触发加载更多
|
||||
async handleScrollToLower() {
|
||||
if (!this.hasMore || this.loadingMore || this.loading) {
|
||||
console.log('无需加载更多数据:', {
|
||||
hasMore: this.hasMore,
|
||||
loadingMore: this.loadingMore,
|
||||
loading: this.loading,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
this.loadStatus = 'loading';
|
||||
this.queryParams.pageNum += 1;
|
||||
console.log('滚动到底部,开始加载更多数据');
|
||||
|
||||
try {
|
||||
await this.getList(true);
|
||||
} catch (error) {
|
||||
console.error('加载更多数据失败:', error);
|
||||
this.queryParams.pageNum -= 1;
|
||||
this.loadStatus = 'loadmore';
|
||||
}
|
||||
// 页码加1,加载下一页
|
||||
this.queryParams.pageNum += 1;
|
||||
await this.getList(true);
|
||||
},
|
||||
|
||||
// 查看考核计划信息
|
||||
@@ -466,9 +508,6 @@ export default {
|
||||
|
||||
// 提交成功回调
|
||||
handleSuccess() {
|
||||
this.queryParams.pageNum = 1;
|
||||
this.hasMore = true;
|
||||
this.loadStatus = 'loadmore';
|
||||
this.getList();
|
||||
},
|
||||
|
||||
@@ -514,6 +553,16 @@ export default {
|
||||
};
|
||||
return getDictTagType(this.assessmentScheduleStatus, status, fallbackMap);
|
||||
},
|
||||
|
||||
// 获取没有更多数据文本
|
||||
getNoMoreText() {
|
||||
if (this.hasMore) {
|
||||
return `已加载${this.assessmentScheduleList.length}条,共${this.total}条`;
|
||||
} else if (this.total > 0) {
|
||||
return `已全部加载完毕,共${this.total}条考核计划`;
|
||||
}
|
||||
return '暂无数据';
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -526,6 +575,11 @@ export default {
|
||||
|
||||
.content-wrapper {
|
||||
padding: 20rpx;
|
||||
height: calc(100vh - 88rpx); /* 减去导航栏高度 */
|
||||
}
|
||||
|
||||
.schedule-scroll-view {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.empty-container {
|
||||
@@ -558,12 +612,25 @@ export default {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.schedule-name-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
|
||||
.schedule-index {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #000000;
|
||||
margin-right: 8rpx;
|
||||
min-width: 40rpx;
|
||||
}
|
||||
|
||||
.schedule-name {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
display: block;
|
||||
margin-bottom: 12rpx;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.schedule-meta {
|
||||
@@ -640,6 +707,26 @@ export default {
|
||||
padding: 20rpx 0;
|
||||
}
|
||||
|
||||
.loading-more {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 20rpx 0;
|
||||
gap: 12rpx;
|
||||
}
|
||||
|
||||
.loading-text {
|
||||
font-size: 24rpx;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.load-complete-text {
|
||||
text-align: center;
|
||||
font-size: 24rpx;
|
||||
color: #909399;
|
||||
padding: 20rpx 0;
|
||||
}
|
||||
|
||||
/* 弹窗样式 */
|
||||
.schedule-detail-popup {
|
||||
background-color: #fff;
|
||||
|
||||
@@ -26,7 +26,10 @@
|
||||
>
|
||||
<!-- 卡片头部 -->
|
||||
<view class="card-header">
|
||||
<view class="record-title">{{ item.disciplineTypeName || '-' }}</view>
|
||||
<view class="record-title">
|
||||
<text class="record-number">{{ index + 1 }}.</text>
|
||||
{{ item.disciplineTypeName || '-' }}
|
||||
</view>
|
||||
<view class="record-status">
|
||||
<u-tag
|
||||
:text="getDictLabel(studentDisciplineStatus, item.status)"
|
||||
@@ -114,9 +117,15 @@
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 滚动加载提示 -->
|
||||
<view v-if="hasMore && disciplineRecordList.length > 0" class="load-more">
|
||||
<u-loadmore :status="loadStatus" @loadmore="loadMore"></u-loadmore>
|
||||
<!-- 底部加载状态提示 -->
|
||||
<view v-if="disciplineRecordList.length > 0" class="load-status">
|
||||
<view v-if="loadingMore" class="loading-tip">
|
||||
<u-loading-icon></u-loading-icon>
|
||||
<text class="loading-text">加载中...</text>
|
||||
</view>
|
||||
<view v-else-if="!hasMore" class="no-more-tip">
|
||||
<text>已加载全部数据</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -143,10 +152,10 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
loadingMore: false, // 加载更多状态
|
||||
disciplineRecordList: [],
|
||||
total: 0,
|
||||
hasMore: true,
|
||||
loadStatus: 'loadmore',
|
||||
|
||||
// 查询参数
|
||||
queryParams: {
|
||||
@@ -172,6 +181,16 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
// 滚动到底部时自动加载更多
|
||||
onReachBottom() {
|
||||
this.loadMore();
|
||||
},
|
||||
|
||||
// 下拉刷新
|
||||
onPullDownRefresh() {
|
||||
this.handleRefresh();
|
||||
},
|
||||
|
||||
methods: {
|
||||
// 返回上一页
|
||||
goBack() {
|
||||
@@ -205,6 +224,8 @@ export default {
|
||||
async getList(loadMore = false) {
|
||||
if (!loadMore) {
|
||||
this.loading = true;
|
||||
} else {
|
||||
this.loadingMore = true;
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -230,10 +251,8 @@ export default {
|
||||
// 判断是否还有更多数据
|
||||
if (rows.length < this.queryParams.pageSize) {
|
||||
this.hasMore = false;
|
||||
this.loadStatus = 'nomore';
|
||||
} else {
|
||||
this.hasMore = true;
|
||||
this.loadStatus = 'loadmore';
|
||||
}
|
||||
} else {
|
||||
if (!loadMore) {
|
||||
@@ -241,7 +260,6 @@ export default {
|
||||
this.total = 0;
|
||||
}
|
||||
this.hasMore = false;
|
||||
this.loadStatus = 'nomore';
|
||||
|
||||
uni.showToast({
|
||||
title: res?.msg || '获取数据失败',
|
||||
@@ -256,7 +274,6 @@ export default {
|
||||
this.total = 0;
|
||||
}
|
||||
this.hasMore = false;
|
||||
this.loadStatus = 'nomore';
|
||||
|
||||
uni.showToast({
|
||||
title: '获取数据失败',
|
||||
@@ -265,17 +282,19 @@ export default {
|
||||
} finally {
|
||||
if (!loadMore) {
|
||||
this.loading = false;
|
||||
} else {
|
||||
this.loadingMore = false;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// 加载更多数据
|
||||
async loadMore() {
|
||||
if (!this.hasMore || this.loadStatus !== 'loadmore') {
|
||||
// 防止重复加载
|
||||
if (!this.hasMore || this.loadingMore || this.loading) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.loadStatus = 'loading';
|
||||
this.queryParams.pageNum += 1;
|
||||
|
||||
try {
|
||||
@@ -283,7 +302,25 @@ export default {
|
||||
} catch (error) {
|
||||
console.error('加载更多数据失败:', error);
|
||||
this.queryParams.pageNum -= 1; // 回退页码
|
||||
this.loadStatus = 'loadmore';
|
||||
|
||||
uni.showToast({
|
||||
title: '加载失败,请重试',
|
||||
icon: 'none',
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// 下拉刷新处理
|
||||
async handleRefresh() {
|
||||
this.queryParams.pageNum = 1;
|
||||
this.hasMore = true;
|
||||
|
||||
try {
|
||||
await this.getList();
|
||||
} catch (error) {
|
||||
console.error('刷新数据失败:', error);
|
||||
} finally {
|
||||
uni.stopPullDownRefresh();
|
||||
}
|
||||
},
|
||||
|
||||
@@ -318,7 +355,6 @@ export default {
|
||||
// 重新加载列表
|
||||
this.queryParams.pageNum = 1;
|
||||
this.hasMore = true;
|
||||
this.loadStatus = 'loadmore';
|
||||
this.getList();
|
||||
},
|
||||
|
||||
@@ -354,6 +390,7 @@ export default {
|
||||
|
||||
.content-wrapper {
|
||||
padding: 20rpx;
|
||||
padding-bottom: 40rpx; // 增加底部间距
|
||||
}
|
||||
|
||||
.empty-container {
|
||||
@@ -386,6 +423,15 @@ export default {
|
||||
font-weight: bold;
|
||||
color: #303133;
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.record-number {
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
margin-right: 8rpx;
|
||||
min-width: 40rpx;
|
||||
}
|
||||
|
||||
.record-status {
|
||||
@@ -434,12 +480,42 @@ export default {
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.load-more {
|
||||
// 底部加载状态样式
|
||||
.load-status {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 40rpx 20rpx;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
|
||||
.loading-tip {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 16rpx;
|
||||
|
||||
.loading-text {
|
||||
font-size: 28rpx;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
.no-more-tip {
|
||||
text {
|
||||
font-size: 28rpx;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
// uview组件样式调整
|
||||
::v-deep .u-tag {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
// 加载图标样式调整
|
||||
::v-deep .u-loading-icon {
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
}
|
||||
</style>
|
||||
Reference in new issue
Block a user