You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

332 lines
6.9 KiB
Vue

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<view class="page-container">
<view class="header-section">
<view class="back-btn" @click="goBack">
<text class="back-icon"></text>
<text class="back-text">返回</text>
</view>
<view class="header-content">
<text class="header-title">备件详情</text>
</view>
</view>
<view class="content-section">
<view class="info-card">
<view class="card-title">基本信息</view>
<view class="info-list">
<view class="info-row">
<text class="info-label">备件编码</text>
<text class="info-value">{{ getField('barCode') }}</text>
</view>
<view class="info-row">
<text class="info-label">备件名称</text>
<text class="info-value">{{ getField('name') }}</text>
</view>
<view class="info-row">
<text class="info-label">单位</text>
<text class="info-value">{{ unitLabel }}</text>
</view>
<view class="info-row">
<text class="info-label">规格</text>
<text class="info-value">{{ getField('standard') }}</text>
</view>
<view class="info-row">
<text class="info-label">预警库存</text>
<text class="info-value">{{ getField('safetyNumber') }}</text>
</view>
<view class="info-row">
<text class="info-label">备注</text>
<text class="info-value">{{ getField('remark') }}</text>
</view>
<view class="info-row">
<text class="info-label">创建时间</text>
<text class="info-value">{{ createTimeLabel }}</text>
</view>
</view>
</view>
</view>
</view>
</template>
<script setup>
import { ref, computed } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import request from '@/utils/request'
const spareId = ref(undefined)
const loading = ref(false)
const detailData = ref(null)
const unitList = ref([])
function goBack() {
uni.navigateBack();
}
function detailValue(v) {
if (v === 0) return '0'
if (v === false) return '否'
if (v === true) return '是'
if (v === null || v === undefined) return '-'
const s = String(v).trim()
return s ? s : '-'
}
function getField(field) {
const d = detailData.value
return detailValue(d ? d[field] : undefined)
}
function pad2(v) {
return String(v).padStart(2, '0')
}
function formatDateTime(v) {
if (v === null || v === undefined || v === '') return '-'
const d = new Date(typeof v === 'number' ? v : String(v))
if (Number.isNaN(d.getTime())) return '-'
const yyyy = d.getFullYear()
const mm = pad2(d.getMonth() + 1)
const dd = pad2(d.getDate())
const hh = pad2(d.getHours())
const mi = pad2(d.getMinutes())
const ss = pad2(d.getSeconds())
return `${yyyy}-${mm}-${dd} ${hh}:${mi}:${ss}`
}
const createTimeLabel = computed(() => {
const d = detailData.value
return formatDateTime(d ? d.createTime : undefined)
})
const unitLabel = computed(() => {
const d = detailData.value
const explicit = d ? d.unitName : undefined
if (explicit) return detailValue(explicit)
const unitId = d ? d.unitId : undefined
const list = unitList.value
const matched = Array.isArray(list) ? list.find(u => u && u.id === unitId) : undefined
return detailValue(matched ? matched.name : undefined)
})
async function fetchAll() {
if (!spareId.value) {
uni.showToast({ title: '缺少备件ID', icon: 'none' })
return
}
loading.value = true
try {
const [detailRes, unitRes] = await Promise.all([
request({
url: '/admin-api/erp/product/get',
method: 'get',
params: { id: spareId.value },
showLoading: false
}),
request({
url: '/admin-api/erp/product-unit/simple-list',
method: 'get',
showLoading: false
})
])
detailData.value = detailRes ? detailRes.data : null
unitList.value = unitRes ? unitRes.data : []
} catch (e) {
uni.showToast({ title: '加载失败', icon: 'none' })
} finally {
loading.value = false
}
}
onLoad((query) => {
const rawId = query && (query.id !== undefined ? query.id : query.code)
const decoded = rawId ? decodeURIComponent(String(rawId)) : ''
spareId.value = decoded ? decoded : undefined
fetchAll()
})
</script>
<style lang="scss" scoped>
.page-container {
min-height: 100vh;
background-color: #f0f2f5;
}
.header-section {
background: linear-gradient(135deg, #1a3a5c 0%, #2d5a87 100%);
padding: 40rpx 30rpx 80rpx;
position: relative;
}
.back-btn {
display: flex;
align-items: center;
margin-bottom: 20rpx;
&:active {
opacity: 0.7;
}
.back-icon {
font-size: 48rpx;
color: #ffffff;
margin-right: 8rpx;
}
.back-text {
font-size: 28rpx;
color: #ffffff;
}
}
.header-content {
.header-title {
display: block;
font-size: 44rpx;
font-weight: bold;
color: #ffffff;
margin-bottom: 16rpx;
}
.header-code {
display: block;
font-size: 28rpx;
color: rgba(255, 255, 255, 0.7);
}
}
.status-badge {
position: absolute;
top: 60rpx;
right: 30rpx;
padding: 12rpx 24rpx;
border-radius: 24rpx;
font-size: 24rpx;
}
.status-normal {
background: rgba(24, 188, 55, 0.2);
color: #18bc37;
}
.status-low {
background: rgba(255, 140, 0, 0.2);
color: #ff8c00;
}
.status-empty {
background: rgba(255, 77, 79, 0.2);
color: #ff4d4f;
}
.content-section {
padding: 0 30rpx 30rpx;
margin-top: 40rpx;
}
.info-card {
background: #ffffff;
border-radius: 20rpx;
padding: 30rpx;
margin-bottom: 24rpx;
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.05);
}
.card-title {
font-size: 32rpx;
font-weight: 600;
color: #1a3a5c;
margin-bottom: 24rpx;
padding-bottom: 20rpx;
border-bottom: 2rpx solid #f0f2f5;
}
.info-list {
display: flex;
flex-direction: column;
}
.info-row {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20rpx 0;
border-bottom: 1rpx solid #f5f7fa;
&:last-child {
border-bottom: none;
}
}
.info-label {
font-size: 28rpx;
color: #999999;
}
.info-value {
font-size: 28rpx;
color: #333333;
&.highlight {
font-weight: 600;
color: #1a3a5c;
}
}
.record-list {
display: flex;
flex-direction: column;
}
.record-item {
display: flex;
align-items: center;
padding: 24rpx 0;
border-bottom: 1rpx solid #f5f7fa;
&:last-child {
border-bottom: none;
}
}
.record-dot {
width: 16rpx;
height: 16rpx;
border-radius: 50%;
background: #1a3a5c;
margin-right: 20rpx;
}
.record-content {
flex: 1;
.record-title {
display: block;
font-size: 28rpx;
color: #333333;
margin-bottom: 8rpx;
}
.record-time {
display: block;
font-size: 24rpx;
color: #999999;
}
}
.record-type {
padding: 8rpx 16rpx;
border-radius: 8rpx;
font-size: 22rpx;
}
.type-in {
background: rgba(24, 188, 55, 0.1);
color: #18bc37;
}
.type-out {
background: rgba(255, 77, 79, 0.1);
color: #ff4d4f;
}
</style>