smart-delivery/src/pages/consumables/inventory-plan.vue
2025-09-30 17:02:05 +08:00

154 lines
5.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>
<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>