Files
pj_mini_app_cloud/src/pages/integrated/lostAndFound/index.vue
T
dzc 653b4688cd fix:图片访问
fix:权限修改
2026-10-29 14:25:46 +08:00

232 lines
4.7 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>
<crud-layout mainIsScroll title="失物招领" :bg="$fileUrl(filePath(SERVICE_IMAGE.blueBg))">
<scroll-view scroll-y class="scroll-view" @scrolltolower="onLoadMore" refresher-enabled
:refresher-triggered="refreshing" @refresherrefresh="onRefresh">
<view v-if="list.length > 0">
<view v-for="item in list" :key="item.id" class="item-card" @tap="viewDetail(item)">
<view class="item-title">{{ item.title }}</view>
<view class="item-description" v-html="$fileHtml(item.description)"></view>
<view class="item-info">
<text>地点:{{ item.location }}</text>
<text>时间:{{ formatDate(item.dateFound) }}</text>
</view>
<view :class="['status-tag', item.status === '0' ? 'status-pending' : 'status-claimed']">
{{ item.status === '0' ? '待认领' : '已认领' }}
</view>
</view>
</view>
<view v-else class="empty-box">
<text class="empty-text">暂无失物招领信息</text>
</view>
<view v-if="loading" class="loading">加载中...</view>
<view v-if="!hasMore && list.length > 0" class="no-more">没有更多了</view>
</scroll-view>
</crud-layout>
</template>
<script lang="ts" setup>
import { ref, onMounted } from 'vue'
import dayjs from 'dayjs'
import lostAndFoundApi from '@/sheep/api/lost-and-found'
import { filePath } from "@@/utils/file"
import { SERVICE_IMAGE } from "@@/constant/index"
interface LostAndFoundItem {
id: string
title: string
picUrl: string | null
description: string
dateFound: string
location: string
status: string
}
interface ApiResponse {
code: number
data: {
records: LostAndFoundItem[]
pages: number
}
}
const list = ref<LostAndFoundItem[]>([])
const current = ref(1)
const hasMore = ref(true)
const loading = ref(false)
const refreshing = ref(false)
const fetchData = async (page: number = 1) => {
try {
loading.value = true
const response = await lostAndFoundApi.getList({
current: page,
size: 10,
}) as unknown as ApiResponse
if (response.code === 0 && response.data) {
if (page === 1) {
list.value = response.data.records
} else {
list.value = [...list.value, ...response.data.records]
}
hasMore.value = page < response.data.pages
current.value = page
}
} catch (error) {
console.error('Failed to fetch lost and found items:', error)
} finally {
loading.value = false
refreshing.value = false
}
}
const onLoadMore = () => {
if (!loading.value && hasMore.value) {
fetchData(current.value + 1)
}
}
const onRefresh = async () => {
refreshing.value = true
await fetchData(1)
}
const viewDetail = (item: LostAndFoundItem) => {
if (!item?.id) return
uni.navigateTo({
url: `/pages/integrated/lostAndFound/detail?id=${item.id}`,
success: (res) => {
res.eventChannel.emit('initDetail', item)
},
})
}
const formatDate = (date: string) => {
return dayjs(date).format('YYYY-MM-DD')
}
const goBack = () => {
uni.navigateBack()
}
onMounted(() => {
fetchData()
})
</script>
<style lang="scss" scoped>
.container {
min-height: 100vh;
background-color: #f5f5f5;
}
.custom-nav {
position: fixed;
top: 0;
left: 0;
right: 0;
height: 88rpx;
background-color: #1777FF;
display: flex;
align-items: center;
padding: 0 30rpx;
z-index: 100;
}
.nav-back {
width: 60rpx;
height: 60rpx;
display: flex;
align-items: center;
justify-content: center;
}
.back-arrow {
color: #fff;
font-size: 40rpx;
font-weight: bold;
}
.nav-title {
flex: 1;
text-align: center;
color: #fff;
font-size: 32rpx;
font-weight: 500;
margin-right: 60rpx; // 为了保持标题居中,抵消返回按钮的宽度
}
.scroll-view {
height: calc(100vh - 30rpx);
margin-top: 30rpx;
box-sizing: border-box;
}
.item-card {
margin: 12px 0 0 0;
padding: 16px;
background-color: #fff;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
}
.item-title {
font-size: 16px;
font-weight: 500;
color: #333;
margin-bottom: 8px;
}
.item-description {
font-size: 14px;
color: #666;
margin-bottom: 8px;
}
.item-info {
display: flex;
gap: 16px;
color: #999;
font-size: 12px;
margin-bottom: 8px;
}
.status-tag {
display: inline-block;
padding: 2px 8px;
border-radius: 4px;
font-size: 12px;
}
.status-pending {
background-color: #e6f7ff;
color: #1890ff;
}
.status-claimed {
background-color: #f6ffed;
color: #52c41a;
}
.empty-box {
display: flex;
justify-content: center;
align-items: center;
height: 200px;
}
.empty-text {
color: #999;
font-size: 14px;
}
.loading,
.no-more {
text-align: center;
padding: 12px;
color: #999;
font-size: 12px;
}
</style>