levelRecord.vue 8.2 KB
<template>
	<view class="page-container">
		<!-- 加载状态 -->
		<view v-if="loading" class="loading-container">
			<uni-load-more status="loading"></uni-load-more>
		</view>

		<!-- 列表内容 -->
		<view v-else class="list-content">
			<view class="record-card" v-for="(item, index) in levelRecords" :key="index">
				<!-- <view class="card-header">
					<text class="card-index">{{ index + 1 }}</text>
					<text class="card-level">{{ szToHz(item.level) }}</text>
				</view> -->
				<view class="card-body">
					<view class="card-row">
						<text class="row-label">  {{ pageType==0?'级位':'段位' }}</text>
						<text class="row-value">{{ szToHz(item.level)}}{{ pageType==0?'级':'段' }}</text>
					</view>
					<view class="card-row">
						<text class="row-label">{{ pageType==0?'级位号':'段位号' }}</text>
						<text class="row-value">{{ item.certCode || '-' }}</text>
					</view>
					<view class="card-row">
						<text class="row-label">获得证书时间</text>
						<text class="row-value">{{ item.createTime ? item.createTime.substring(0, 10) : '-' }}</text>
					</view>
					<view class="card-row" v-if="item.remark?.length > 0">
						<text class="row-label">变更记录</text>
						<text class="row-value link" @click="showChangeRecord(item)">查看详情</text>
					</view>
				</view>
			</view>

			<!-- 空状态 -->
			<view v-if="levelRecords.length === 0 && !loading" class="empty">
				<image class="empty-img" mode="aspectFit" :src="config.baseUrl_api + '/fs/static/nodata.png'"></image>
				<view class="empty-text">暂无级位记录</view>
			</view>
		</view>

		<!-- 变更记录弹窗 -->
		<uni-popup ref="changeRecordPopup" type="center">
			<view class="popup-content">
				<view class="popup-header">
					<view class="popup-title">级位变更</view>
					<view class="popup-close" @click="closeChangeRecord">
						<uni-icons type="close" size="24" color="#fff" />
					</view>
				</view>
				<view class="popup-body">
					<view v-if="currentChangeRecord" class="change-details">
						<view class="change-item">
							<view class="change-label">变更名称:{{ currentChangeRecord.modName || '等级变更' }}</view>
						</view>
						<view class="change-item">
							<view class="change-label">考级级别:{{ szToHz(currentChangeRecord.oldJi) }}</view>
						</view>
						<view class="change-item">
							<view class="change-label">变更后级位:{{ szToHz(currentChangeRecord.newJi) }}</view>
						</view>
						<view class="change-item">
							<view class="change-label">变更时间:{{ parseTime(currentChangeRecord.modTime) }}</view>
						</view>
					</view>
					<view v-else class="empty">
						<uni-icons type="empty" size="60" color="#ccc" />
						<image class="empty-img" mode="aspectFit" :src="config.baseUrl_api + '/fs/static/nodata.png'"></image>
						<view class="empty-text">暂无变更记录</view>
					</view>
				</view>
			</view>
		</uni-popup>
	</view>
</template>

<script setup>
	import { ref, onMounted } from 'vue';
	import { onLoad } from '@dcloudio/uni-app';
		
	import { useUserStore } from '../store/modules/user';
	import { getAssoPers } from '@/common/api.js';
	import { getPersonTecDetails } from '@/common/api.js';
	import config from '@/config.js';

	// 级位记录数据
	const levelRecords = ref([]);
	const loading = ref(false);
	const perId = ref('');
	const userStore = useUserStore();

	// 变更记录相关
	const changeRecordPopup = ref(null);
	const currentChangeRecord = ref(null);
	const pageType = ref('');

	// 返回上一页
	const goBack = () => {
		uni.navigateBack();
	};
	onLoad((option) => {
		if (option.type) {
			pageType.value = option.type;
			if (pageType.value == '0') {
				uni.setNavigationBarTitle({ title: '级位记录' })
			} else if (pageType.value == '1') {
				uni.setNavigationBarTitle({ title: '段位记录' })
			}
		}
	});
// 显示变更记录
	const showChangeRecord = (item) => {
		// remark已经在getLevelRecords中解析过了,直接使用
		if (item.remark) {
			currentChangeRecord.value = Array.isArray(item.remark) ? item.remark[0] : item.remark;
		} else {
			currentChangeRecord.value = null;
		}
		changeRecordPopup.value.open();
	};

	// 关闭变更记录
	const closeChangeRecord = () => {
		changeRecordPopup.value.close();
	};

	// 获取级位记录数据
	const getLevelRecords = async () => {
		loading.value = true;
		try {
			const res = await getPersonTecDetails(pageType.value, perId.value); // 0表示级位
			levelRecords.value = res.data || [];
			// 处理数据
			levelRecords.value.forEach(item => {
				item.level = item.level * 1;
				if (item.remark) {
					try {
						item.remark = JSON.parse(item.remark);
					} catch (e) {
						console.error('解析remark失败:', e);
					}
				}
			});
		} catch (error) {
			console.error('获取级位记录失败:', error);
			uni.showToast({
				title: '获取级位记录失败',
				icon: 'none'
			});
		} finally {
			loading.value = false;
		}
	};

	// 数字转汉字
	const szToHz = (num) => {
		const arr = ['', '一', '二', '三', '四', '五', '六', '七', '八', '九'];
		return arr[num] || num;
	};

	// 时间格式化
	const parseTime = (time) => {
		if (!time) return '--';
		const date = new Date(time);
		return date.getFullYear() + '-' + 
			String(date.getMonth() + 1).padStart(2, '0') + '-' + 
			String(date.getDate()).padStart(2, '0');
	};

	onMounted(async () => {
		// 获取perId
		const userInfo = userStore.user;
		if (userInfo && userInfo.perId) {
			perId.value = userInfo.perId;
			getLevelRecords();
		} else {
			// 如果userInfo中没有perId,尝试通过getAssoPers获取
			try {
				const res = await getAssoPers(userInfo?.id || '');
				perId.value = res.data[10] || '';
				if (perId.value) {
					getLevelRecords();
				} else {
					uni.showToast({
						title: '获取用户信息失败',
						icon: 'none'
					});
				}
			} catch (error) {
				console.error('获取perId失败:', error);
				uni.showToast({
					title: '获取用户信息失败',
					icon: 'none'
				});
			}
		}
	});
</script>

<style lang="scss" scoped>
	.page-container {
		min-height: 100vh;
		background: #f5f5f5;
		padding: 20rpx;
	}

	/* 加载状态 */
	.loading-container {
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: center;
		height: 500rpx;
	}

	/* 列表内容 */
	.list-content {
		padding-bottom: 20rpx;
	}

	/* 卡片 */
	.record-card {
		background: #fff;
		border-radius: 16rpx;
		margin-bottom: 20rpx;
		overflow: hidden;
		box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
	}

	.card-header {
		display: flex;
		align-items: center;
		padding: 24rpx 30rpx;
		background: linear-gradient(135deg, #ff6b6b, #ff9f43);

		.card-index {
			width: 44rpx;
			height: 44rpx;
			background: rgba(255, 255, 255, 0.3);
			border-radius: 50%;
			display: flex;
			align-items: center;
			justify-content: center;
			font-size: 24rpx;
			color: #fff;
			margin-right: 16rpx;
		}

		.card-level {
			font-size: 32rpx;
			font-weight: 600;
			color: #fff;
		}
	}

	.card-body {
		padding: 8rpx 24rpx 24rpx;
	}

	.card-row {
		display: flex;
		justify-content: space-between;
		align-items: center;
		padding: 20rpx 0;
		border-bottom: 1rpx solid #f5f5f5;

		&:last-child {
			border-bottom: none;
		}

		.row-label {
			font-size: 26rpx;
			color: #999;
			flex-shrink: 0;
		}

		.row-value {
			font-size: 26rpx;
			color: #333;
			text-align: right;
			flex: 1;
			margin-left: 20rpx;
			word-break: break-all;

			&.link {
				color: #1890ff;
			}
		}
	}

	/* 空状态 */





	/* 弹窗 */
	.popup-content {
		width: 600rpx;
		background: #ffffff;
		border-radius: 20rpx;
		overflow: hidden;
	}

	.popup-header {
		display: flex;
		align-items: center;
		justify-content: space-between;
		padding: 30rpx;
		background: linear-gradient(135deg, #ff6b6b, #ff9f43);
	}

	.popup-title {
		font-size: 32rpx;
		font-weight: 500;
		color: #ffffff;
	}

	.popup-close {
		width: 44rpx;
		height: 44rpx;
		display: flex;
		align-items: center;
		justify-content: center;
		background: rgba(255, 255, 255, 0.2);
		border-radius: 50%;
	}

	.popup-body {
		padding: 40rpx;
	}

	.change-details {
		width: 100%;
	}

	.change-item {
		margin-bottom: 30rpx;

		&:last-child {
			margin-bottom: 0;
		}
	}

	.change-label {
		font-size: 26rpx;
		color: #666;
		font-weight: 500;
	}
</style>