|
|
|
|
@ -0,0 +1,264 @@
|
|
|
|
|
<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">{{ categoryLabel }}</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">{{ statusLabel }}</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 productId = 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 categoryLabel = computed(() => {
|
|
|
|
|
const d = detailData.value
|
|
|
|
|
if (!d) return '-'
|
|
|
|
|
const v = d.subCategoryName || d.categoryName
|
|
|
|
|
return detailValue(v)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const statusLabel = computed(() => {
|
|
|
|
|
const d = detailData.value
|
|
|
|
|
const status = d ? d.status : undefined
|
|
|
|
|
if (status === 0 || status === '0') return '启用'
|
|
|
|
|
if (status === 1 || status === '1') return '禁用'
|
|
|
|
|
return detailValue(status)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
async function fetchAll() {
|
|
|
|
|
if (!productId.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: productId.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)) : ''
|
|
|
|
|
productId.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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.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;
|
|
|
|
|
text-align: right;
|
|
|
|
|
max-width: 65%;
|
|
|
|
|
}
|
|
|
|
|
</style>
|