赵正易 a8dbe84e25 feat: 新增油漆件叫料与收料功能及相关页面
refactor: 优化首页菜单图标显示方式

fix: 修复SignalR连接初始化问题

style: 更新manifest.json版本号至2.0.0

chore: 新增多个SVG图标资源

perf: 为登录接口添加超时处理

docs: 更新API接口文档

test: 添加油漆件叫料相关测试用例

build: 更新依赖版本
2025-08-06 10:25:23 +08:00

362 lines
9.5 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>
<view class="container">
<!-- 筛选查询区域 -->
<view class="filter-section">
<uni-forms ref="filterForm" :modelValue="filterData" validateTrigger="bind">
<view class="form-row">
<uni-forms-item label="线别选择" label-width="80" name="lineCode" required class="form-item">
<uni-data-select :localdata="lineOptions" v-model="filterData.lineCode" placeholder="请选择线体" @change="getMRPList"></uni-data-select>
</uni-forms-item>
<uni-forms-item label="选择日期" label-width="80" name="workOrderDate" required class="form-item">
<uni-datetime-picker type="date" v-model="filterData.workOrderDate" format="yyyy-MM-dd" placeholder="请选择日期"></uni-datetime-picker>
</uni-forms-item>
</view>
<view class="btn-search">
<button type="primary" @click="getMRPList">查询</button>
</view>
</uni-forms>
</view>
<!-- 清单展示区域 -->
<view class="list-section">
<view class="list-header">
<text>MRP叫料清单</text>
</view>
<scroll-view scroll-y class="list-container">
<view v-if="mrpList.length === 0" class="empty-tip">
暂无叫料数据
</view>
<view v-for="(item, index) in mrpList" :key="index" class="list-item">
<view class="item-info">
<view class="info-row">
<text class="label">物料名称:</text>
<text class="value">{{ item.materialName }}</text>
</view>
<view class="info-row">
<text class="label">物料号:</text>
<text class="value">{{ item.materialCode }}</text>
</view>
<view class="info-row">
<text class="label">数量:</text>
<text class="value">{{ item.quantity }}</text>
</view>
</view>
<view class="item-action">
<button type="primary" size="mini" @click="callMaterial(item)">叫料</button>
</view>
</view>
</scroll-view>
</view>
<!-- 叫料弹窗 -->
<uni-popup ref="popup" mode="center">
<view class="popup-content">
<view class="popup-header">
<text class="title">叫料确认</text>
</view>
<view class="popup-body">
<view v-if="currentMaterial" class="info-item">
<text class="label">物料名称:</text>
<text class="value">{{ currentMaterial.materialName }}</text>
</view>
<view v-if="currentMaterial" class="info-item">
<text class="label">物料号:</text>
<text class="value">{{ currentMaterial.materialCode }}</text>
</view>
<view v-if="currentMaterial" class="info-item">
<text class="label">可叫数量:</text>
<text class="value">{{ currentMaterial.quantity }}</text>
</view>
<view class="info-item">
<text class="label">叫料数量:</text>
<input type="number" v-model="callQuantity" placeholder="请输入叫料数量" class="input" />
</view>
</view>
<view class="popup-footer">
<button type="default" size="mini" @click="cancelCall">取消</button>
<button type="primary" size="mini" @click="confirmCall">确认</button>
</view>
</view>
</uni-popup>
</view>
</template>
<script>
import { queryCallMaterialMRP,getLineOptions,doLineCallMaterial } from '@/api/mmcall';
export default {
data() {
return {
filterData: {
lineCode: '',
workOrderDate: new Date()
},
lineOptions: [],
mrpList: [],
currentMaterial: null,
callQuantity: 0
};
},
onLoad() {
// 默认选择当前日期
this.filterData.workOrderDate = new Date();
// 获取线体数据
this.getLineOptions();
},
methods: {
// 获取线体数据
getLineOptions() {
getLineOptions().then(res => {
if (res.code === 200 && res.data) {
// 格式化线体数据为uni-data-select需要的格式
this.lineOptions = res.data.map(item => ({
text: item.groupName, // 显示名称
value: item.groupCode // 实际值
}));
} else {
this.$modal.showToast('获取线体数据失败');
}
}).catch(err => {
console.error('获取线体数据失败', err);
this.$modal.showToast('获取线体数据失败');
});
},
// 获取MRP叫料清单
getMRPList() {
if (!this.filterData.lineCode) {
this.$modal.showToast('请先选择线体');
return;
}
// 准备请求参数
const params = {
pageNum: 1,
pageSize: 100,
lineCode: this.filterData.lineCode,
workOrderDate: this.$dayjs(this.filterData.workOrderDate).format('YYYY-MM-DD')
};
// 显示加载中提示
uni.showLoading({
title: '加载中...'
});
// 调用API获取MRP清单
queryCallMaterialMRP(params).then(res => {
uni.hideLoading();
if (res.code === 200 && res.data) {
this.mrpList = res.data.result;
console.log('MRP数据:', res.data.result);
} else {
this.mrpList = [];
this.$modal.showToast(res.message || '获取MRP数据失败');
}
}).catch(err => {
uni.hideLoading();
console.error('获取MRP数据失败', err);
this.mrpList = [];
this.$modal.showToast('获取MRP数据失败');
});
},
// 叫料操作
callMaterial(item) {
// 设置当前操作的物料和初始叫料数量
this.currentMaterial = item;
this.callQuantity = item.quantity;
// 显示自定义弹窗
this.$refs.popup.open();
},
// 确认叫料
confirmCall() {
if (!this.currentMaterial) return;
// 验证叫料数量
const quantity = parseInt(this.callQuantity);
if (isNaN(quantity) || quantity <= 0 || quantity > this.currentMaterial.quantity) {
this.$modal.showToast('请输入有效的叫料数量(大于0且不超过可叫数量)');
return;
}
// 准备叫料参数
const params = {
id: this.currentMaterial.id, // 物料ID
quantity: quantity, // 叫料数量
lineCode: this.filterData.lineCode, // 线体代码
workOrderDate: this.$dayjs(this.filterData.workOrderDate).format('YYYY-MM-DD') // 日期
};
// 显示加载中提示
uni.showLoading({
title: '叫料中...'
});
// 调用叫料API
doLineCallMaterial(params).then(res => {
uni.hideLoading();
if (res.code === 200) {
this.$modal.showToast(`成功叫料 ${quantity}${this.currentMaterial.materialName}`);
// 更新物料数量
this.currentMaterial.quantity -= quantity;
// 如果数量为0从列表中移除
if (this.currentMaterial.quantity <= 0) {
this.mrpList = this.mrpList.filter(m => m.id !== this.currentMaterial.id);
}
// 关闭弹窗
this.$refs.popup.close();
} else {
this.$modal.showToast(res.message || '叫料失败');
}
}).catch(err => {
uni.hideLoading();
console.error('叫料失败', err);
this.$modal.showToast('叫料失败');
});
},
// 取消叫料
cancelCall() {
this.$refs.popup.close();
}
}
};
</script>
<style scoped>
.container {
padding: 20rpx;
}
.header {
text-align: center;
padding: 20rpx 0;
margin-bottom: 20rpx;
}
.title {
font-size: 36rpx;
font-weight: bold;
}
.filter-section {
background-color: #fff;
border-radius: 16rpx;
padding: 20rpx;
margin-bottom: 20rpx;
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1);
}
.form-row {
display: flex;
flex-direction: column;
gap: 20rpx;
padding: 10rpx 0;
}
.form-item {
width: 100%;
}
.uni-forms-item__label {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.btn-search {
margin-top: 20rpx;
}
.list-section {
background-color: #fff;
border-radius: 16rpx;
padding: 20rpx;
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1);
}
.list-header {
padding: 10rpx 0;
border-bottom: 1rpx solid #eee;
margin-bottom: 10rpx;
}
.list-header text {
font-size: 32rpx;
font-weight: bold;
}
.list-container {
height: 500rpx;
}
.list-item {
display: flex;
justify-content: space-between;
padding: 20rpx 0;
border-bottom: 1rpx solid #eee;
}
.item-info {
flex: 1;
}
.info-row {
display: flex;
margin-bottom: 10rpx;
}
.label {
width: 120rpx;
color: #999;
}
.value {
flex: 1;
}
.item-action {
display: flex;
align-items: center;
}
.empty-tip {
text-align: center;
padding: 40rpx 0;
color: #999;
}
/* 弹窗样式 */
.popup-content {
width: 80%;
background-color: #fff;
border-radius: 16rpx;
padding: 20rpx;
}
.popup-header {
padding: 10rpx 0;
border-bottom: 1rpx solid #eee;
margin-bottom: 20rpx;
}
.popup-header .title {
font-size: 32rpx;
font-weight: bold;
}
.popup-body {
padding: 10rpx 0;
}
.info-item {
display: flex;
margin-bottom: 20rpx;
align-items: center;
}
.info-item .label {
width: 120rpx;
color: #999;
}
.info-item .value {
flex: 1;
}
.info-item .input {
flex: 1;
border: 1rpx solid #ccc;
padding: 10rpx;
border-radius: 8rpx;
}
.popup-footer {
display: flex;
justify-content: space-around;
margin-top: 20rpx;
}
.popup-footer button {
width: 35%;
}
</style>