Files
zhxg_app/pages/finance/aid/index.vue

794 lines
20 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="financialaid">
<!-- 头部导航 -->
<!-- <uni-nav-bar left-icon="back" title="助学金" :border="false"></uni-nav-bar> -->
<view class="app-container">
<!-- 数据列表滚动容器 -->
<scroll-view class="list-container" id="list-container" scroll-y @scrolltolower="handleLoadMore"
lower-threshold="50" enhanced :show-scrollbar="false">
<!-- 初始加载状态 -->
<uni-load-more :status="loading ? 'loading' : 'done'" v-if="loading" class="loading-wrap"></uni-load-more>
<!-- 空数据状态 -->
<view class="empty-state" v-if="!loading && !hasData">
<uni-icons type="empty" size="80" color="#c0c4cc"></uni-icons>
<text class="empty-text">暂无助学金申请数据</text>
<text class="empty-tip" v-if="roleGroup.includes('学生')">点击右下角"+"按钮提交新申请</text>
</view>
<!-- 数据列表 -->
<view class="card-list" v-if="!loading && hasData">
<view class="apply-card" v-for="(item, index) in validDataList" :key="index" hover-class="card-hover"
:hover-stop-propagation="true">
<!-- 卡片头部 -->
<view class="card-header">
<view class="apply-no">
<text class="label-text">学年</text>
<text class="no-text">{{ getSafeValue(item, 'applyYear', '无') }}</text>
</view>
<view class="status-wrap">
<view class="status-label" :class="getStatusClass(item)">
{{ getStatusText(item) }}
</view>
<view class="status-label" :class="getReviewClass(item)">
{{ getReviewText(item) }}
</view>
</view>
</view>
<!-- 卡片主体折叠面板 -->
<uni-collapse accordion v-model="item.activeCollapse">
<uni-collapse-item title="基本信息" name="basic" class="collapse-item">
<view class="info-grid">
<view class="info-item"><text class="label">学号</text><text
class="value">{{ getSafeValue(item, 'xh', '-') }}</text></view>
<view class="info-item"><text class="label">姓名</text><text
class="value">{{ getSafeValue(item, 'xm', '-') }}</text></view>
<view class="info-item"><text class="label">性别</text><text
class="value">{{ getSafeValue(item, 'xb', '-') }}</text></view>
<view class="info-item"><text class="label">民族</text><text
class="value">{{ getSafeValue(item, 'mz', '-') }}</text></view>
<view class="info-item"><text class="label">出生年月</text><text
class="value">{{ parseTime(getSafeValue(item, 'csny')) || '-' }}</text>
</view>
<view class="info-item"><text class="label">学院</text><text
class="value">{{ getSafeValue(item, 'xy', '-') }}</text></view>
<view class="info-item"><text class="label">专业</text><text
class="value">{{ getSafeValue(item, 'zy', '-') }}</text></view>
<view class="info-item"><text class="label">班级</text><text
class="value">{{ getSafeValue(item, 'bj', '-') }}</text></view>
<view class="info-item"><text class="label">处分是否解除</text><text
class="value">{{ (parseInt(getSafeValue(item, 'penaltyStatus0')) === 1) ? '否' : ((parseInt(getSafeValue(item, 'penaltyStatus1')) === 1) ? '是' : '无处分记录') }}</text></view>
</view>
</uni-collapse-item>
<uni-collapse-item title="审核意见" name="approval" class="collapse-item">
<view class="approval-list">
<view class="approval-item">
<text class="approval-node">辅导员审核意见</text>
<text class="approval-result" :class="getReviewClass(item, 'fdyqm')">
{{ getReviewDetailText(item, 'fdyqm') }}
</text>
</view>
<view class="approval-item">
<text class="approval-node">二级学院审核意见</text>
<text class="approval-result" :class="getReviewClass(item, 'ejxyldqm')">
{{ getReviewDetailText(item, 'ejxyldqm') }}
</text>
</view>
<view class="approval-item">
<text class="approval-node">学校意见</text>
<text class="approval-result" :class="getReviewClass(item, 'zzdj')">
{{ getReviewDetailText(item, 'zzdj') }}
</text>
</view>
</view>
</uni-collapse-item>
</uni-collapse>
<!-- 卡片操作区 -->
<view class="card-actions">
<view>
<uni-button type="text" size="mini" @click="detail(item, '修改')"
v-if="item.step == 0 || isRejected(item)">
<uni-icons type="eye-filled" size="14" class="mr-5"></uni-icons>修改
</uni-button>
<uni-button type="text" size="mini" @click="handleRevoke(item)"
v-if="(item.fdyqm == null || item.fdyqm == '') && (item.step == 1 || item.step == 2 || item.step == 3)">
<uni-icons type="back" size="14" class="mr-5"></uni-icons>撤回
</uni-button>
<uni-button type="text" size="mini" @click="handleDelete(item)"
v-if="item.step == 0">
<uni-icons type="trash" size="14" class="mr-5"></uni-icons>删除
</uni-button>
</view>
<view>
<uni-button type="text" size="mini" @click="detail(item, '详情')" class="detail-btn"
:disabled="!getSafeValue(item, 'id')">
<uni-icons type="info" size="14" class="mr-5"></uni-icons>查看详情
</uni-button>
</view>
</view>
</view>
</view>
<!-- 加载更多状态 -->
<view class="load-more-wrap" v-if="hasData">
<uni-load-more :status="loadingMore ? 'loading' : (hasMore ? 'more' : 'nomore')"
:content-text="loadMoreText"></uni-load-more>
</view>
</scroll-view>
</view>
<!-- 添加申请按钮 -->
<view class="add" @click="applyFinancialaid" v-if="roleGroup.includes('学生')">+</view>
</view>
</template>
<script>
// 导入API接口
import { listOwn, delApply, revoke, getYearByTag, isPoor } from '@/api/finance/financialaid';
import { getUserProfile } from '@/api/system/user';
export default {
name: "FinancialaidApplyList",
data() {
return {
// 加载状态
loading: true,
loadingMore: false,
hasMore: true,
// 总数据量
totalCount: 0,
// 原始数据
financialaidApplyList: [],
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 5
},
// 用户角色
roleGroup: '',
user: {},
// 加载更多文本
loadMoreText: {
contentdown: '上拉加载更多',
contentrefresh: '正在加载...',
contentnomore: '没有更多数据了'
},
// 学年信息
yearInfoList: [],
stuYearId: '',
currentYear: ''
};
},
computed: {
// 过滤后的有效数据列表
validDataList() {
return this.financialaidApplyList.filter(item => {
return item !== null && item !== undefined && typeof item === 'object';
}).map(item => {
if (!item.hasOwnProperty('activeCollapse')) {
item.activeCollapse = 'basic';
}
return item;
});
},
// 是否有有效数据
hasData() {
return this.validDataList.length > 0;
}
},
onShow() {
this.getUser();
},
methods: {
/** 安全取值方法 */
getSafeValue(obj, key, defaultValue = '') {
if (!obj || typeof obj !== 'object') return defaultValue;
return obj[key] !== undefined && obj[key] !== null ? obj[key] : defaultValue;
},
/** 获取状态样式类 */
getStatusClass(item) {
// 如果学校已经审核完成(zzdj有值),直接返回审核通过样式
if (this.getSafeValue(item, 'zzdj')) {
return 'status-success';
}
const status = this.getSafeValue(item, 'step');
const statusNum = Number(status);
const typeMap = {
'-1': 'status-error',
'0': 'status-info',
'1': 'status-info',
'2': 'status-warning',
'3': 'status-warning',
'4': 'status-success',
'5': 'status-success',
'6': 'status-error',
'7': 'status-error'
};
return typeMap[statusNum.toString()] || 'status-default';
},
/** 获取状态文本 */
getStatusText(item) {
// 如果学校已经审核完成(zzdj有值),直接显示审核通过
if (this.getSafeValue(item, 'zzdj')) {
return '审核通过';
}
// 如果状态为拒绝或驳回,直接显示相应状态
const status = this.getSafeValue(item, 'step');
const statusNum = Number(status);
if (statusNum === -1 || statusNum === 6) {
return '已拒绝';
}
if (statusNum === 7) {
return '已驳回';
}
// 根据step值显示对应状态
const statusMap = {
'0': '待提交',
'1': '待辅导员审核',
'2': '待二级学院审核',
'3': '待学校审核',
'4': '审核完成',
'5': '审核通过'
};
return statusMap[statusNum.toString()] || '未知状态';
},
/** 获取审核意见样式类 */
getReviewClass(item, type = 'fdyqm') {
let reviewResult;
let signField;
if (type === 'fdyqm') {
reviewResult = this.getSafeValue(item, 'bjyjdj');
signField = 'fdyqm';
} else if (type === 'ejxyldqm') {
reviewResult = this.getSafeValue(item, 'ejxyyjdj');
signField = 'ejxyldqm';
} else if (type === 'zzdj') {
reviewResult = this.getSafeValue(item, 'zzdj');
signField = 'xxqm';
} else {
reviewResult = this.getSafeValue(item, type);
signField = type;
}
// 根据签名字段是否有值来判断是否显示审核结果的样式与PC页面保持一致
const signValue = this.getSafeValue(item, signField);
const hasSign = signValue !== null && signValue !== undefined && signValue !== '';
if (!hasSign) return 'status-default';
if (!reviewResult) return 'status-default';
// 助学金等级1-3都使用绿色背景不困难4使用红色背景
const typeMap = {
'1': 'status-success',
'2': 'status-success',
'3': 'status-success',
'4': 'status-error'
};
return typeMap[reviewResult] || 'status-success';
},
/** 获取审核意见文本 */
getReviewText(item) {
if (this.getSafeValue(item, 'zzdj')) {
return this.getReviewDetailText(item, 'zzdj');
} else if (this.getSafeValue(item, 'ejxyyjdj')) {
return this.getReviewDetailText(item, 'ejxyldqm');
} else if (this.getSafeValue(item, 'bjyjdj')) {
return this.getReviewDetailText(item, 'fdyqm');
} else {
return '未审核';
}
},
/** 获取详细审核意见文本 */
getReviewDetailText(item, type = 'fdyqm') {
let reviewResult;
let statusField;
let signField;
if (type === 'fdyqm') {
reviewResult = this.getSafeValue(item, 'bjyjdj');
statusField = 'status1';
signField = 'fdyqm';
} else if (type === 'ejxyldqm') {
reviewResult = this.getSafeValue(item, 'ejxyyjdj');
statusField = 'status2';
signField = 'ejxyldqm';
} else if (type === 'zzdj') {
reviewResult = this.getSafeValue(item, 'zzdj');
statusField = 'status3';
signField = 'xxqm';
} else {
reviewResult = this.getSafeValue(item, type);
statusField = 'status1';
signField = type;
}
// 根据签名字段是否有值来判断是否显示审核结果与PC页面保持一致
const signValue = this.getSafeValue(item, signField);
const hasSign = signValue !== null && signValue !== undefined && signValue !== '';
if (!hasSign) {
const statusText = this.getSafeValue(item, statusField);
return statusText || '未审核';
}
if (!reviewResult) return '未审核';
const reviewMap = {
'1': '一等国家助学金',
'2': '二等国家助学金',
'3': '三等国家助学金',
'4': '不困难'
};
return reviewMap[reviewResult] || '未知审核结果';
},
/** 时间格式化 */
parseTime(time, format = '{y}-{m}-{d}') {
if (!time) return '';
try {
const date = new Date(time);
if (isNaN(date.getTime())) return '';
const year = date.getFullYear();
const month = (date.getMonth() + 1).toString().padStart(2, '0');
const day = date.getDate().toString().padStart(2, '0');
return format.replace('{y}', year).replace('{m}', month).replace('{d}', day);
} catch (error) {
return '';
}
},
/** 查询数据 */
getList(isRefresh = false) {
if (isRefresh) {
this.loading = true;
this.hasMore = true;
this.queryParams.pageNum = 1;
this.financialaidApplyList = [];
} else {
this.loadingMore = true;
}
// 使用实际的API调用
listOwn(this.queryParams).then(response => {
const res = response || {};
const newData = Array.isArray(res.rows) ? res.rows : [];
this.totalCount = Number(res.total) || 0;
if (isRefresh) {
this.financialaidApplyList = newData;
} else {
this.financialaidApplyList = [...this.financialaidApplyList, ...newData];
}
// 更新状态
this.loading = false;
this.loadingMore = false;
this.hasMore = this.financialaidApplyList.length < this.totalCount;
}).catch((error) => {
console.error('数据加载失败:', error);
this.loading = false;
this.loadingMore = false;
uni.showToast({
title: '数据加载失败',
icon: 'none'
});
});
},
/** 获取用户信息 */
getUser() {
// 使用实际的API调用
getUserProfile().then(response => {
const res = response || {};
this.user = res.data || {};
this.roleGroup = res.roleGroup || '';
// 获取学年信息
this.getYearInfo();
}).catch((error) => {
console.error('用户信息获取失败:', error);
this.loading = false;
uni.showToast({
title: '用户信息加载失败',
icon: 'none'
});
});
},
/** 获取助学金学年信息 */
getYearInfo() {
// 使用实际的API调用根据PC端代码助学金的标签值应该是'ZXJ'
getYearByTag('ZXJ').then(response => {
const res = response || {};
if (res.code === 200 && res.data && res.data.length > 0) {
this.yearInfoList = res.data;
// 默认使用第一个学年
this.stuYearId = res.data[0].id;
this.currentYear = res.data[0].stuYearName;
}
this.getList(true);
}).catch((error) => {
console.error('学年信息获取失败:', error);
this.loading = false;
uni.showToast({
title: '学年信息加载失败',
icon: 'none'
});
});
},
/** 加载更多 */
handleLoadMore() {
if (this.loadingMore || !this.hasMore) return;
this.queryParams.pageNum += 1;
this.getList(false);
},
/** 查看详情 */
detail(item, text) {
const id = this.getSafeValue(item, 'id');
if (!id) {
uni.showToast({
title: '数据异常,无法查看详情',
icon: 'none'
});
return;
}
if (text == '详情') {
uni.navigateTo({
url: `/pages/finance/aid/apply?id=${id}&type=detail`
});
} else {
uni.navigateTo({
url: `/pages/finance/aid/apply?id=${id}`
});
}
},
/** 撤回申请 */
handleRevoke(item) {
uni.showModal({
title: '确认撤回',
content: '确定要撤回该申请吗?',
success: (res) => {
if (res.confirm) {
// 直接传递item对象与PC端保持一致
revoke(item).then(response => {
console.log('撤回申请响应:', response);
if (response.code === 200 || response.code === 0) {
uni.showToast({
title: '撤回成功',
icon: 'success'
});
this.getList(true);
} else {
uni.showToast({
title: response.msg || '撤回失败',
icon: 'none'
});
}
}).catch(error => {
console.error('撤回申请失败:', error);
uni.showToast({
title: error.response?.data?.msg || error.message || '撤回失败',
icon: 'none'
});
});
}
}
});
},
/** 删除申请 */
handleDelete(item) {
uni.showModal({
title: '确认删除',
content: '确定要删除该申请吗?',
success: (res) => {
if (res.confirm) {
// 传递item.id与PC端保持一致
delApply(item.id).then(() => {
uni.showToast({
title: '删除成功',
icon: 'success'
});
this.getList(true);
}).catch(() => {
uni.showToast({
title: '删除失败',
icon: 'none'
});
});
}
}
});
},
// 跳转到申请页面
applyFinancialaid() {
// 校验申请资格
uni.showLoading({
title: '校验资格中...'
});
// 检查是不是贫困生
isPoor({ stuYearId: this.stuYearId }).then(poorRes => {
uni.hideLoading();
const poorData = poorRes.data || {};
console.log('贫困生检查响应:', poorRes);
// 检查是否为贫困生
if (!poorData.isPoor) {
uni.showToast({
title: poorData.message || '非贫困生,无法申请助学金',
icon: 'none'
});
return;
}
// 只要isPoor为true就直接跳转到申请页面不展示message
uni.navigateTo({
url: `/pages/finance/aid/apply?stuYearId=${this.stuYearId}&yearName=${this.currentYear}`
});
}).catch(error => {
uni.hideLoading();
console.error('申请资格校验失败:', error);
uni.showToast({
title: '申请资格校验失败',
icon: 'none'
});
});
},
// 判断是否被拒绝
isRejected(item) {
const stepNum = Number(item.step);
return stepNum === -1 || stepNum === 6 || stepNum === 7;
}
}
}
</script>
<style scoped>
.financialaid {
background-color: #F3F4F6;
min-height: 100vh;
}
.app-container {
padding-bottom: 10rpx;
}
.list-container {
width: 100%;
min-height: calc(100vh - 88rpx);
}
.loading-wrap {
padding: 20rpx;
text-align: center;
}
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 100rpx 0;
color: #c0c4cc;
}
.empty-text {
margin-top: 20rpx;
font-size: 28rpx;
}
.empty-tip {
margin-top: 10rpx;
font-size: 24rpx;
color: #909399;
}
.card-list {
width: 100%;
padding: 5px 15px 0px;
}
.apply-card {
background-color: white;
margin-bottom: 10px;
border-radius: 10px;
overflow: hidden;
}
.card-hover {
opacity: 0.8;
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20rpx 24rpx;
border-bottom: 1px solid #f0f0f0;
}
.apply-no {
display: flex;
align-items: center;
}
.label-text {
font-size: 26rpx;
color: #606266;
margin-right: 10rpx;
}
.no-text {
font-size: 28rpx;
color: #303133;
font-weight: 500;
}
.status-wrap {
display: flex;
align-items: center;
gap: 10rpx;
}
.status-label {
padding: 4rpx 12rpx;
border-radius: 10rpx;
font-size: 22rpx;
color: white;
}
.status-info {
background-color: #909399;
}
.status-warning {
background-color: #e6a23c;
}
.status-success {
background-color: #67c23a;
}
.status-error {
background-color: #f56c6c;
}
.status-default {
background-color: #909399;
}
.collapse-item {
padding: 0;
}
.info-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 15rpx;
padding: 20rpx 24rpx;
}
.info-item {
display: flex;
align-items: center;
}
.info-item .label {
font-size: 26rpx;
color: #606266;
width: 100rpx;
}
.info-item .value {
font-size: 26rpx;
color: #303133;
flex: 1;
}
.info-form {
padding: 20rpx 24rpx;
}
.form-item {
display: flex;
align-items: flex-start;
margin-bottom: 15rpx;
}
.form-item .label {
font-size: 26rpx;
color: #606266;
width: 140rpx;
padding-top: 5rpx;
}
.form-item .value {
font-size: 26rpx;
color: #303133;
flex: 1;
word-break: break-word;
}
.split-text {
margin: 0 10rpx;
color: #909399;
}
.approval-list {
padding: 20rpx 24rpx;
}
.approval-item {
margin-bottom: 15rpx;
}
.approval-item:last-child {
margin-bottom: 0;
}
.approval-node {
font-size: 26rpx;
color: #606266;
margin-right: 10rpx;
}
.approval-result {
font-size: 26rpx;
padding: 4rpx 12rpx;
border-radius: 10rpx;
color: white;
}
.card-actions {
display: flex;
justify-content: space-between;
align-items: center;
padding: 16rpx 24rpx;
border-top: 1px solid #f0f0f0;
}
.mr-5 {
margin-right: 5rpx;
}
.detail-btn {
color: #409eff;
}
.load-more-wrap {
padding: 20rpx;
text-align: center;
}
.add {
position: fixed;
bottom: 40rpx;
right: 40rpx;
width: 80rpx;
height: 80rpx;
border-radius: 50%;
background-color: #409eff;
color: white;
font-size: 60rpx;
text-align: center;
line-height: 80rpx;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}
</style>