memberAuditRecord.vue 6.07 KB
<template>
	<view class="member-audit-record">
		<!-- Tab切换 -->
		<view class="tab-bar">
			<view
				v-for="tab in tabs"
				:key="tab.value"
				class="tab-item"
				:class="{ active: currentTab === tab.value }"
				@click="onTabChange(tab.value)"
			>
				{{ tab.label }}
			</view>
		</view>

		<!-- 列表 -->
		<view class="list-content">
			<view v-if="list.length === 0 && !loading" class="empty-tip">
				<text>暂无数据</text>
			</view>

			<view
				v-for="(item, index) in list"
				:key="index"
				class="list-item"
				:class="{ 'success-row': item.approveStatus == 2 }"
			>
				<view class="item-header">
					<text class="item-name">{{ item.name }}</text>
					<text class="item-status" :class="getStatusClass(item.approveStatus)">
						{{ getStatusText(item.approveStatus) }}
					</text>
				</view>

				<view class="item-row">
					<text class="item-label">证件类型</text>
					<text class="item-value">{{ getIdcTypeText(item.idcType) }}</text>
				</view>

				<view class="item-row">
					<text class="item-label">证件号</text>
					<text class="item-value">{{ item.idcCode || '-' }}</text>
				</view>

				<view class="item-row">
					<text class="item-label">提交单位</text>
					<text class="item-value">{{ item.memName || '-' }}</text>
				</view>

				<view class="item-row">
					<text class="item-label">提交时间</text>
					<text class="item-value">{{ formatDate(item.commitTime) }}</text>
				</view>

				<view class="item-row">
					<text class="item-label">审核时间</text>
					<text class="item-value">{{ formatDate(item.approveTime) }}</text>
				</view>

				<view v-if="item.msg" class="item-row">
					<text class="item-label">备注</text>
					<text class="item-value">{{ item.msg }}</text>
				</view>

				<view v-if="item.fileUrl" class="item-row">
					<text class="item-label">附件</text>
					<image
						class="item-image"
						:src="fillImgUrl(item.fileUrl)"
						mode="aspectFill"
						@click="previewImage(item.fileUrl)"
					></image>
				</view>
			</view>

			<view v-if="loading" class="loading-tip">
				<text>加载中...</text>
			</view>

			<view v-if="noMore && list.length > 0" class="no-more-tip">
				<text>没有更多了</text>
			</view>
		</view>
	</view>
</template>

<script setup>
import { ref } from 'vue'
import { onLoad, onReachBottom } from '@dcloudio/uni-app'
import { memberAuditList } from '@/common/api'
import config from '@/config'

const tabs = [
	{ label: '全部', value: '' },
	{ label: '审核中', value: '1' },
	{ label: '审核通过', value: '2' },
	{ label: '审核拒绝', value: '3' }
]

const currentTab = ref('')
const list = ref([])
const loading = ref(false)
const noMore = ref(false)
const pageNum = ref(1)
const pageSize = ref(10)

function onTabChange(value) {
	currentTab.value = value
	list.value = []
	pageNum.value = 1
	noMore.value = false
	loadData()
}

function loadData() {
	if (loading.value) return
	loading.value = true

	memberAuditList({
		pageNum: pageNum.value,
		pageSize: pageSize.value,
		approveStatus: currentTab.value
	}).then(res => {
		if (res.rows) {
			if (pageNum.value === 1) {
				list.value = res.rows
			} else {
				list.value = [...list.value, ...res.rows]
			}

			if (res.rows.length < pageSize.value) {
				noMore.value = true
			}
		} else {
			if (pageNum.value === 1) {
				list.value = []
			}
			noMore.value = true
		}
	}).finally(() => {
		loading.value = false
	})
}

// 上划加载
onReachBottom(() => {
	if (!noMore.value) {
		pageNum.value++
		loadData()
	}
})

onLoad(() => {
	loadData()
})

function getStatusText(status) {
	const map = { 1: '审核中', 2: '审核通过', 3: '审核拒绝' }
	return map[status] || '-'
}

function getStatusClass(status) {
	return {
		'status-1': status == 1,
		'status-2': status == 2,
		'status-3': status == 3
	}
}

function getIdcTypeText(type) {
	const map = {
		1: '身份证',
		2: '护照',
		3: '军官证',
		4: '港澳通行证',
		5: '台湾通行证'
	}
	return map[type] || '-'
}

function formatDate(dateStr) {
	if (!dateStr) return '-'
	const date = new Date(dateStr)
	const year = date.getFullYear()
	const month = String(date.getMonth() + 1).padStart(2, '0')
	const day = String(date.getDate()).padStart(2, '0')
	return `${year}-${month}-${day}`
}

function fillImgUrl(url) {
	if (!url) return ''
	if (url.startsWith('http')) return url
	return config.baseUrl + url
}

function previewImage(url) {
	uni.previewImage({
		urls: [fillImgUrl(url)],
		current: fillImgUrl(url)
	})
}
</script>

<style lang="scss" scoped>
.member-audit-record {
	min-height: 100vh;
	background: #f5f5f5;
}

.tab-bar {
	display: flex;
	background: #fff;
	padding: 0 20rpx;
	border-bottom: 1rpx solid #eee;
}

.tab-item {
	flex: 1;
	height: 88rpx;
	line-height: 88rpx;
	text-align: center;
	font-size: 28rpx;
	color: #666;
	position: relative;
}

.tab-item.active {
	color: #e64329;
	font-weight: 600;
}

.tab-item.active::after {
	content: '';
	position: absolute;
	bottom: 0;
	left: 50%;
	transform: translateX(-50%);
	width: 48rpx;
	height: 4rpx;
	background: #e64329;
	border-radius: 2rpx;
}

.list-content {
	padding: 20rpx;
}

.empty-tip,
.loading-tip,
.no-more-tip {
	text-align: center;
	padding: 60rpx 0;
	color: #999;
	font-size: 26rpx;
}

.list-item {
	background: #fff;
	border-radius: 16rpx;
	padding: 24rpx;
	margin-bottom: 20rpx;
}

.list-item.success-row {
	border-left: 6rpx solid #19be6b;
}

.item-header {
	display: flex;
	justify-content: space-between;
	align-items: center;
	margin-bottom: 20rpx;
	padding-bottom: 20rpx;
	border-bottom: 1rpx solid #f0f0f0;
}

.item-name {
	font-size: 32rpx;
	font-weight: 600;
	color: #333;
}

.item-status {
	font-size: 26rpx;
	padding: 4rpx 16rpx;
	border-radius: 20rpx;
}

.status-1 {
	background: #fff7e6;
	color: #fa8c16;
}

.status-2 {
	background: #e6fff7;
	color: #52c41a;
}

.status-3 {
	background: #fff1f0;
	color: #ff4d4f;
}

.item-row {
	display: flex;
	margin-bottom: 16rpx;
}

.item-label {
	width: 140rpx;
	font-size: 26rpx;
	color: #999;
}

.item-value {
	flex: 1;
	font-size: 26rpx;
	color: #333;
	word-break: break-all;
}

.item-image {
	width: 120rpx;
	height: 120rpx;
	border-radius: 8rpx;
	margin-top: 8rpx;
}
</style>