chore: 保存盘点开发前改动
This commit is contained in:
@@ -1,82 +1,170 @@
|
||||
<template>
|
||||
<view class="page-container">
|
||||
<view class="module-header">
|
||||
<uni-icons type="bars" size="22" color="#722ed1"></uni-icons>
|
||||
<text class="header-title">库存统计</text>
|
||||
<view class="query-card">
|
||||
<view class="section-header">
|
||||
<text class="section-title">库存查询</text>
|
||||
<text class="section-subtitle">托盘码</text>
|
||||
</view>
|
||||
|
||||
<view class="input-row">
|
||||
<input
|
||||
class="tray-input"
|
||||
v-model="trayCode"
|
||||
placeholder="请扫描或输入托盘码"
|
||||
confirm-type="search"
|
||||
@confirm="queryStock"
|
||||
/>
|
||||
<button class="icon-button" @click="scanTray">
|
||||
<uni-icons type="scan" size="22" color="#1890ff"></uni-icons>
|
||||
</button>
|
||||
</view>
|
||||
|
||||
<button class="primary-button" :disabled="loading" @click="queryStock">
|
||||
{{ loading ? '查询中...' : '查询库存' }}
|
||||
</button>
|
||||
</view>
|
||||
|
||||
<!-- 库存概览卡片 -->
|
||||
<view class="summary-section">
|
||||
<view class="summary-card">
|
||||
<view class="summary-row">
|
||||
<view class="summary-item">
|
||||
<text class="summary-value">--</text>
|
||||
<text class="summary-label">库存总量</text>
|
||||
<view v-if="searched" class="result-section">
|
||||
<view v-if="materialList.length > 0">
|
||||
<view class="summary-card">
|
||||
<view class="summary-main">
|
||||
<text class="summary-tray">{{ currentTrayCode }}</text>
|
||||
<text class="summary-location">{{ warehouseName }} / {{ cargoSpaceName }}</text>
|
||||
</view>
|
||||
<view class="summary-divider"></view>
|
||||
<view class="summary-item">
|
||||
<text class="summary-value">--</text>
|
||||
<text class="summary-label">物料种类</text>
|
||||
<view class="summary-grid">
|
||||
<view class="summary-item">
|
||||
<text class="summary-value">{{ materialCount }}</text>
|
||||
<text class="summary-label">物料种类</text>
|
||||
</view>
|
||||
<view class="summary-divider"></view>
|
||||
<view class="summary-item">
|
||||
<text class="summary-value">{{ totalQuantity }}</text>
|
||||
<text class="summary-label">库存总量</text>
|
||||
</view>
|
||||
<view class="summary-divider"></view>
|
||||
<view class="summary-item">
|
||||
<text class="summary-value">{{ availableQuantity }}</text>
|
||||
<text class="summary-label">可用库存</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="summary-row">
|
||||
<view class="summary-item">
|
||||
<text class="summary-value">--</text>
|
||||
<text class="summary-label">今日入库</text>
|
||||
</view>
|
||||
<view class="summary-divider"></view>
|
||||
<view class="summary-item">
|
||||
<text class="summary-value">--</text>
|
||||
<text class="summary-label">今日出库</text>
|
||||
|
||||
<view class="material-list">
|
||||
<view class="material-card" v-for="(item, index) in materialList" :key="item.stockDetailId || index">
|
||||
<view class="material-header">
|
||||
<text class="material-name">{{ formatValue(item.materialName || item.productName) }}</text>
|
||||
<text class="material-code">{{ formatValue(item.materialCode || item.productId) }}</text>
|
||||
</view>
|
||||
<view class="material-body">
|
||||
<view class="info-item">
|
||||
<text class="info-label">批次</text>
|
||||
<text class="info-value">{{ formatValue(item.lotNo) }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">库存数量</text>
|
||||
<text class="info-value">{{ formatNumber(item.quantity) }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">占用数量</text>
|
||||
<text class="info-value">{{ formatNumber(item.outQuantity) }}</text>
|
||||
</view>
|
||||
<view class="info-item">
|
||||
<text class="info-label">可用数量</text>
|
||||
<text class="info-value strong">{{ formatNumber(item.availableQuantity) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="feature-list">
|
||||
<view class="feature-card" @click="$modal.showToast('功能开发中')">
|
||||
<view class="feature-left">
|
||||
<uni-icons type="search" size="20" color="#1890ff"></uni-icons>
|
||||
<text class="feature-name">库存查询</text>
|
||||
</view>
|
||||
<uni-icons type="right" size="16" color="#ccc"></uni-icons>
|
||||
<view v-else class="empty-state">
|
||||
<uni-icons type="info" size="30" color="#bfbfbf"></uni-icons>
|
||||
<text class="empty-text">未查询到托盘库存</text>
|
||||
</view>
|
||||
|
||||
<view class="feature-card" @click="$modal.showToast('功能开发中')">
|
||||
<view class="feature-left">
|
||||
<uni-icons type="location" size="20" color="#fa8c16"></uni-icons>
|
||||
<text class="feature-name">库位分布</text>
|
||||
</view>
|
||||
<uni-icons type="right" size="16" color="#ccc"></uni-icons>
|
||||
</view>
|
||||
|
||||
<view class="feature-card" @click="$modal.showToast('功能开发中')">
|
||||
<view class="feature-left">
|
||||
<uni-icons type="pie-chart" size="20" color="#52c41a"></uni-icons>
|
||||
<text class="feature-name">库存报表</text>
|
||||
</view>
|
||||
<uni-icons type="right" size="16" color="#ccc"></uni-icons>
|
||||
</view>
|
||||
|
||||
<view class="feature-card" @click="$modal.showToast('功能开发中')">
|
||||
<view class="feature-left">
|
||||
<uni-icons type="alert" size="20" color="#f5222d"></uni-icons>
|
||||
<text class="feature-name">库存预警</text>
|
||||
</view>
|
||||
<uni-icons type="right" size="16" color="#ccc"></uni-icons>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="empty-tip">
|
||||
<text class="tip-text">库存统计模块正在开发中,敬请期待</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getTrayStock } from '@/api/warehouse/stock'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {}
|
||||
return {
|
||||
trayCode: '',
|
||||
currentTrayCode: '',
|
||||
loading: false,
|
||||
searched: false,
|
||||
materialList: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
materialCount() {
|
||||
var map = {}
|
||||
this.materialList.forEach(item => {
|
||||
var key = item.materialCode || item.productId || item.stockDetailId
|
||||
if (key) map[key] = true
|
||||
})
|
||||
return Object.keys(map).length
|
||||
},
|
||||
totalQuantity() {
|
||||
return this.sumBy('quantity')
|
||||
},
|
||||
availableQuantity() {
|
||||
return this.sumBy('availableQuantity')
|
||||
},
|
||||
warehouseName() {
|
||||
return this.formatValue(this.materialList[0] && this.materialList[0].warehouseName)
|
||||
},
|
||||
cargoSpaceName() {
|
||||
return this.formatValue(this.materialList[0] && this.materialList[0].cargoSpaceName)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
scanTray() {
|
||||
uni.scanCode({
|
||||
success: res => {
|
||||
this.trayCode = res.result || ''
|
||||
this.queryStock()
|
||||
}
|
||||
})
|
||||
},
|
||||
queryStock() {
|
||||
var code = (this.trayCode || '').trim()
|
||||
if (!code) {
|
||||
this.$modal.msg('请扫描或输入托盘码')
|
||||
return
|
||||
}
|
||||
this.loading = true
|
||||
getTrayStock(code).then(res => {
|
||||
this.currentTrayCode = code
|
||||
this.materialList = res.data || []
|
||||
this.searched = true
|
||||
}).catch(() => {
|
||||
this.materialList = []
|
||||
this.searched = true
|
||||
}).then(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
sumBy(field) {
|
||||
var total = 0
|
||||
this.materialList.forEach(item => {
|
||||
total += this.toNumber(item[field])
|
||||
})
|
||||
return this.formatNumber(total)
|
||||
},
|
||||
toNumber(value) {
|
||||
var number = Number(value)
|
||||
return isNaN(number) ? 0 : number
|
||||
},
|
||||
formatNumber(value) {
|
||||
var number = this.toNumber(value)
|
||||
return Number.isInteger(number) ? String(number) : String(Number(number.toFixed(3)))
|
||||
},
|
||||
formatValue(value) {
|
||||
return value === undefined || value === null || value === '' ? '-' : value
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -91,101 +179,210 @@
|
||||
padding: 24rpx;
|
||||
}
|
||||
|
||||
.module-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 24rpx 0;
|
||||
margin-bottom: 20rpx;
|
||||
.query-card,
|
||||
.summary-card,
|
||||
.material-card,
|
||||
.empty-state {
|
||||
background: #fff;
|
||||
border-radius: 16rpx;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
|
||||
}
|
||||
|
||||
.header-title {
|
||||
.query-card {
|
||||
padding: 28rpx;
|
||||
margin-bottom: 28rpx;
|
||||
}
|
||||
|
||||
.section-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 22rpx;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
margin-left: 12rpx;
|
||||
}
|
||||
|
||||
.summary-section {
|
||||
margin-bottom: 32rpx;
|
||||
.section-subtitle {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.input-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.tray-input {
|
||||
flex: 1;
|
||||
height: 82rpx;
|
||||
padding: 0 24rpx;
|
||||
border: 1rpx solid #e5e6eb;
|
||||
border-radius: 12rpx;
|
||||
background: #fafafa;
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.icon-button {
|
||||
width: 82rpx;
|
||||
height: 82rpx;
|
||||
padding: 0;
|
||||
margin-left: 18rpx;
|
||||
border-radius: 12rpx;
|
||||
background: #e6f7ff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.icon-button::after,
|
||||
.primary-button::after {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.primary-button {
|
||||
height: 84rpx;
|
||||
line-height: 84rpx;
|
||||
border-radius: 12rpx;
|
||||
background: #1890ff;
|
||||
color: #fff;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
|
||||
.primary-button[disabled] {
|
||||
background: #91caff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.result-section {
|
||||
margin-bottom: 28rpx;
|
||||
}
|
||||
|
||||
.summary-card {
|
||||
background: linear-gradient(135deg, #1890ff, #096dd9);
|
||||
border-radius: 16rpx;
|
||||
padding: 40rpx 28rpx;
|
||||
padding: 30rpx 28rpx;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.summary-row {
|
||||
.summary-main {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding-bottom: 24rpx;
|
||||
margin-bottom: 24rpx;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
.summary-tray {
|
||||
font-size: 34rpx;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.summary-location {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.summary-grid {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
.summary-row:first-child {
|
||||
margin-bottom: 32rpx;
|
||||
}
|
||||
|
||||
.summary-divider {
|
||||
width: 1rpx;
|
||||
height: 60rpx;
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.summary-item {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.summary-divider {
|
||||
width: 1rpx;
|
||||
height: 54rpx;
|
||||
background: #f0f0f0;
|
||||
}
|
||||
|
||||
.summary-value {
|
||||
font-size: 40rpx;
|
||||
font-weight: 500;
|
||||
color: #fff;
|
||||
margin-bottom: 8rpx;
|
||||
font-size: 36rpx;
|
||||
font-weight: 600;
|
||||
color: #1890ff;
|
||||
margin-bottom: 6rpx;
|
||||
}
|
||||
|
||||
.summary-label {
|
||||
font-size: 24rpx;
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
font-size: 22rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.feature-list {
|
||||
background: #fff;
|
||||
border-radius: 16rpx;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
|
||||
.material-card {
|
||||
padding: 28rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.feature-card {
|
||||
.material-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 32rpx 28rpx;
|
||||
border-bottom: 1rpx solid #f5f5f5;
|
||||
align-items: flex-start;
|
||||
padding-bottom: 18rpx;
|
||||
margin-bottom: 16rpx;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
}
|
||||
|
||||
.feature-card:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.feature-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.feature-name {
|
||||
font-size: 28rpx;
|
||||
.material-name {
|
||||
flex: 1;
|
||||
font-size: 30rpx;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
margin-left: 16rpx;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
.empty-tip {
|
||||
padding: 60rpx 0;
|
||||
text-align: center;
|
||||
.material-code {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.tip-text {
|
||||
.material-body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.info-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 9rpx 0;
|
||||
}
|
||||
|
||||
.info-label {
|
||||
font-size: 26rpx;
|
||||
color: #ccc;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.info-value {
|
||||
font-size: 26rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.info-value.strong {
|
||||
color: #1890ff;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.empty-state {
|
||||
padding: 86rpx 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
font-size: 28rpx;
|
||||
color: #999;
|
||||
margin-top: 16rpx;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user