154 lines
5.7 KiB
Vue
154 lines
5.7 KiB
Vue
<template>
|
||
<scroll-view scroll-y class="page">
|
||
<!-- 加载骨架屏 -->
|
||
<view v-if="loading" class="skeleton-list">
|
||
<view class="card skeleton" v-for="n in 3" :key="n">
|
||
<view class="skeleton-line w-70"></view>
|
||
<view class="skeleton-line w-40"></view>
|
||
<view class="skeleton-line w-90"></view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 列表内容 -->
|
||
<view v-else>
|
||
<view v-if="inventoryPlanList.length === 0" class="empty">暂无数据</view>
|
||
|
||
<view class="inventory-list">
|
||
<view class="card inventory-item" v-for="item in inventoryPlanList" :key="item.inventoryId || item.id" @tap="gotoPlanDetail(item)">
|
||
<!-- 卡片头部:标题 + 状态 -->
|
||
<view class="card-header">
|
||
<text class="title ellipsis-1">📋 盘点计划</text>
|
||
<text class="status-badge" :class="statusClass(item.status)">{{ item.status || '未知' }}</text>
|
||
</view>
|
||
|
||
<!-- 关键指标:开始/结束日期 -->
|
||
<view class="key-meta">
|
||
<view class="meta-block">
|
||
<text class="meta-label">开始日期</text>
|
||
<text class="meta-value">{{ item.checkStartDate || '-' }}</text>
|
||
</view>
|
||
<view class="meta-block">
|
||
<text class="meta-label">结束日期</text>
|
||
<text class="meta-value">{{ item.checkEndDate || '-' }}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 详情信息 -->
|
||
<view class="detail">
|
||
<view class="detail-row">
|
||
<text class="label">创建人</text>
|
||
<text class="value ellipsis-1">{{ item.createByName || '-' }}</text>
|
||
</view>
|
||
<view class="detail-row">
|
||
<text class="label">计划ID</text>
|
||
<text class="value">{{ item.id || item.inventoryId }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="load-status" v-if="noMore && inventoryPlanList.length > 0">没有更多数据了</view>
|
||
</view>
|
||
</scroll-view>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { ref } from 'vue'
|
||
import { onLoad, onReachBottom } from '@dcloudio/uni-app'
|
||
// @ts-ignore JS模块无类型声明
|
||
import { getConsumpationPlan } from '@/pages/api/fixedAssets.js'
|
||
|
||
type Plan = Record<string, any>
|
||
|
||
const page = ref(1)
|
||
const pageSize = ref(10)
|
||
const loading = ref(false)
|
||
const noMore = ref(false)
|
||
const inventoryPlanList = ref<Plan[]>([])
|
||
|
||
function statusClass(status?: string) {
|
||
if (status === '已结束') return 'ended'
|
||
if (status === '正在进行') return 'running'
|
||
return 'unknown'
|
||
}
|
||
|
||
async function fetchInventoryList() {
|
||
if (loading.value || noMore.value) return
|
||
loading.value = true
|
||
try {
|
||
const res = await getConsumpationPlan(page.value, pageSize.value)
|
||
const list: any[] = (res?.data?.list) || (res?.data?.records) || (Array.isArray(res?.data) ? res.data : []) || []
|
||
inventoryPlanList.value = inventoryPlanList.value.concat(list)
|
||
if (list.length < pageSize.value) noMore.value = true
|
||
} catch (e) {
|
||
console.error('获取易耗品盘点计划失败', e)
|
||
uni.showToast({ title: '加载失败', icon: 'none' })
|
||
} finally {
|
||
loading.value = false
|
||
}
|
||
}
|
||
|
||
function gotoPlanDetail(item: any) {
|
||
const planId = item?.id || item?.inventoryId
|
||
if (!planId && planId !== 0) {
|
||
uni.showToast({ title: '缺少计划ID', icon: 'none' })
|
||
return
|
||
}
|
||
if (item.status === '已结束') {
|
||
uni.navigateTo({ url: `/pages/consumables/inventory-end?planId=${planId}` })
|
||
} else {
|
||
uni.navigateTo({ url: `/pages/consumables/inventory-ing?planId=${planId}` })
|
||
}
|
||
}
|
||
|
||
onLoad(() => {
|
||
fetchInventoryList()
|
||
})
|
||
|
||
onReachBottom(() => {
|
||
if (!loading.value && !noMore.value) {
|
||
page.value += 1
|
||
fetchInventoryList()
|
||
}
|
||
})
|
||
</script>
|
||
|
||
<style scoped>
|
||
.page { min-height: 100vh; background: #f5f7fb; padding: 24rpx; box-sizing: border-box; }
|
||
.empty { color: #9a9aa0; text-align: center; padding: 24rpx 0; }
|
||
.inventory-list { display: flex; flex-direction: column; gap: 16rpx; }
|
||
|
||
.card { background: #fff; border-radius: 16rpx; padding: 20rpx; box-shadow: 0 6rpx 16rpx rgba(0,0,0,0.06); }
|
||
.card-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12rpx; }
|
||
.title { font-size: 32rpx; color: #222; font-weight: 600; }
|
||
|
||
.status-badge { font-size: 24rpx; padding: 4rpx 12rpx; border-radius: 999rpx; }
|
||
.status-badge.running { color: #1e88e5; background: #e3f2fd; }
|
||
.status-badge.ended { color: #2e7d32; background: #e8f5e9; }
|
||
.status-badge.unknown { color: #757575; background: #eeeeee; }
|
||
|
||
.key-meta { display: grid; grid-template-columns: 1fr 1fr; gap: 16rpx; margin: 8rpx 0 12rpx; }
|
||
.meta-block { background: #f7f9ff; border-radius: 12rpx; padding: 16rpx; }
|
||
.meta-label { display: block; color: #8a8f99; font-size: 22rpx; margin-bottom: 6rpx; }
|
||
.meta-value { color: #333; font-size: 28rpx; }
|
||
|
||
.detail { margin-top: 8rpx; }
|
||
.detail-row { display: flex; align-items: flex-start; margin: 8rpx 0; }
|
||
.label { color: #888; min-width: 140rpx; }
|
||
.value { color: #333; }
|
||
|
||
.ellipsis-1 { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||
|
||
.load-status { text-align: center; color: #9a9aa0; padding: 20rpx 0; }
|
||
|
||
/* 骨架屏样式 */
|
||
.skeleton-list .card { overflow: hidden; }
|
||
.skeleton { position: relative; }
|
||
.skeleton::after { content: ''; position: absolute; left: 0; top: 0; width: 100%; height: 100%; background: linear-gradient(90deg, rgba(0,0,0,0) 0%, rgba(0,0,0,0.04) 50%, rgba(0,0,0,0) 100%); animation: shimmer 1.2s infinite; }
|
||
.skeleton-line { height: 28rpx; background: #f0f2f5; border-radius: 8rpx; margin: 14rpx 0; }
|
||
.skeleton-line.w-70 { width: 70%; }
|
||
.skeleton-line.w-40 { width: 40%; }
|
||
.skeleton-line.w-90 { width: 90%; }
|
||
@keyframes shimmer { 0% { transform: translateX(-100%);} 100% { transform: translateX(100%);} }
|
||
</style>
|