feat: 新增油漆件叫料与收料功能及相关页面
refactor: 优化首页菜单图标显示方式 fix: 修复SignalR连接初始化问题 style: 更新manifest.json版本号至2.0.0 chore: 新增多个SVG图标资源 perf: 为登录接口添加超时处理 docs: 更新API接口文档 test: 添加油漆件叫料相关测试用例 build: 更新依赖版本
83
api/login.js
@ -2,60 +2,61 @@ import request from '@/utils/request'
|
||||
|
||||
// 登录方法
|
||||
export function login(username, password, code, uuid, clientId) {
|
||||
const data = {
|
||||
username,
|
||||
password,
|
||||
code,
|
||||
uuid,
|
||||
clientId
|
||||
}
|
||||
return request({
|
||||
'url': '/login',
|
||||
headers: {
|
||||
isToken: false,
|
||||
userName: username
|
||||
},
|
||||
'method': 'post',
|
||||
'data': data
|
||||
})
|
||||
const data = {
|
||||
username,
|
||||
password,
|
||||
code,
|
||||
uuid,
|
||||
clientId
|
||||
}
|
||||
return request({
|
||||
'url': '/login',
|
||||
headers: {
|
||||
isToken: false,
|
||||
userName: username
|
||||
},
|
||||
timeout: 3000,
|
||||
'method': 'post',
|
||||
'data': data
|
||||
})
|
||||
}
|
||||
|
||||
// 注册方法
|
||||
export function register(data) {
|
||||
return request({
|
||||
url: '/register',
|
||||
headers: {
|
||||
isToken: false
|
||||
},
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
return request({
|
||||
url: '/register',
|
||||
headers: {
|
||||
isToken: false
|
||||
},
|
||||
method: 'post',
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
// 获取用户详细信息
|
||||
export function getInfo() {
|
||||
return request({
|
||||
'url': '/getInfo',
|
||||
'method': 'get'
|
||||
})
|
||||
return request({
|
||||
'url': '/getInfo',
|
||||
'method': 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 退出方法
|
||||
export function logout() {
|
||||
return request({
|
||||
'url': '/logout',
|
||||
'method': 'post'
|
||||
})
|
||||
return request({
|
||||
'url': '/logout',
|
||||
'method': 'post'
|
||||
})
|
||||
}
|
||||
|
||||
// 获取验证码
|
||||
export function getCodeImg() {
|
||||
return request({
|
||||
'url': '/captchaImage',
|
||||
headers: {
|
||||
isToken: false
|
||||
},
|
||||
method: 'get',
|
||||
timeout: 20000
|
||||
})
|
||||
}
|
||||
return request({
|
||||
'url': '/captchaImage',
|
||||
headers: {
|
||||
isToken: false
|
||||
},
|
||||
method: 'get',
|
||||
timeout: 20000
|
||||
})
|
||||
}
|
||||
98
api/mmcall/index.js
Normal file
@ -0,0 +1,98 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
// 查询叫料需求表列表
|
||||
export function getMmCallList(params) {
|
||||
return request({
|
||||
url: '/mes/materialManagement/paintedparts_call/mmcall/list',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
// 查询线别MRP表
|
||||
export function queryCallMaterialMRP(params) {
|
||||
return request({
|
||||
url: '/mes/materialManagement/paintedparts_call/mmcall/QueryCallMaterialMRP',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
// 获取线清单 groupCode groupName
|
||||
export function getLineOptions(params) {
|
||||
return request({
|
||||
url: '/mes/materialManagement/paintedparts_call/mmcall/GetLineOptions',
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
// 查询叫料需求表详情
|
||||
export function getMmCallInfo(Id) {
|
||||
return request({
|
||||
url: `/mes/materialManagement/paintedparts_call/mmcall/${Id}`,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 添加叫料需求表
|
||||
export function addMmCall(data) {
|
||||
return request({
|
||||
url: '/mes/materialManagement/paintedparts_call/mmcall',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 更新叫料需求表
|
||||
export function updateMmCall(data) {
|
||||
return request({
|
||||
url: '/mes/materialManagement/paintedparts_call/mmcall',
|
||||
method: 'put',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 删除叫料需求表
|
||||
export function deleteMmCall(ids) {
|
||||
return request({
|
||||
url: `/mes/materialManagement/paintedparts_call/mmcall/${ids}`,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
// 生成产线油漆件MRP
|
||||
export function generateLineMmCallMRP(data) {
|
||||
return request({
|
||||
url: '/mes/materialManagement/paintedparts_call/mmcall/GenerateLineMmCallMRP',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 涂装油漆件产线叫料
|
||||
export function doLineCallMaterial(data) {
|
||||
return request({
|
||||
url: '/mes/materialManagement/paintedparts_call/mmcall/DoLineCallMaterial',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 涂装油漆件产线领料
|
||||
export function doLineReceiveMaterial(data) {
|
||||
return request({
|
||||
url: '/mes/materialManagement/paintedparts_call/mmcall/DoLineReceiveMaterial',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 涂装油漆件产线退料
|
||||
export function doLineReturnBackMaterial(data) {
|
||||
return request({
|
||||
url: '/mes/materialManagement/paintedparts_call/mmcall/DoLineReturnBackMaterial',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
@ -2,8 +2,8 @@
|
||||
"name": "DOAN总装车间PDA",
|
||||
"appid": "__UNI__EFA389B",
|
||||
"description": "DOAN总装车间PDA",
|
||||
"versionName": "1.5.0",
|
||||
"versionCode": 150,
|
||||
"versionName": "2.0.0",
|
||||
"versionCode": 200,
|
||||
"transformPx": false,
|
||||
"app-plus": {
|
||||
"networkTimeout": {
|
||||
|
||||
14
pages.json
@ -196,6 +196,20 @@
|
||||
{
|
||||
"navigationBarTitleText" : "U03,U05线报工"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/produceManagement/paintMaterial/paint_call",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "产线油漆件叫料"
|
||||
}
|
||||
},
|
||||
{
|
||||
"path" : "pages/produceManagement/paintMaterial/paint_receive",
|
||||
"style" :
|
||||
{
|
||||
"navigationBarTitleText" : "产线油漆件收料"
|
||||
}
|
||||
}
|
||||
],
|
||||
"tabBar": {
|
||||
|
||||
124
pages/index.vue
@ -17,7 +17,7 @@
|
||||
<uni-grid :column="4" :showBorder="false" @change="changeProduceGrid">
|
||||
<uni-grid-item v-for="(item, index) in produceOptions" :key="index" :index="index">
|
||||
<view class="grid-item-box">
|
||||
<uni-icons :type="item.icon" size="30"></uni-icons>
|
||||
<image :src="item.iconPath" mode="aspectFit" class="menu-icon"></image>
|
||||
<text class="text">{{ item.name }}</text>
|
||||
</view>
|
||||
</uni-grid-item>
|
||||
@ -28,7 +28,7 @@
|
||||
<uni-grid :column="4" :showBorder="false" @change="changeMaterialGrid">
|
||||
<uni-grid-item v-for="(item, index) in materialOptions" :key="index" :index="index">
|
||||
<view class="grid-item-box">
|
||||
<uni-icons :type="item.icon" size="30"></uni-icons>
|
||||
<image :src="item.iconPath" mode="aspectFit" class="menu-icon"></image>
|
||||
<text class="text">{{ item.name }}</text>
|
||||
</view>
|
||||
</uni-grid-item>
|
||||
@ -46,7 +46,7 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
socketRef:null,
|
||||
socketRef: null,
|
||||
current: 0,
|
||||
swiperDotIndex: 0,
|
||||
bannerList: [
|
||||
@ -64,30 +64,40 @@ export default {
|
||||
produceOptions: [
|
||||
{
|
||||
name: '产线报工(通用)',
|
||||
icon: 'folder-add-filled',
|
||||
iconPath: '/static/images/index_menu_icon/work_report_common.svg',
|
||||
url: '/pages/produceManagement/workorder/workorder'
|
||||
},
|
||||
{
|
||||
name: '产线报工\n(U16线,U17线)',
|
||||
icon: 'folder-add-filled',
|
||||
iconPath: '/static/images/index_menu_icon/work_report_u16u17.svg',
|
||||
url: '/pages/produceManagement/workorder/workorder02'
|
||||
},
|
||||
{
|
||||
name: '产线报工\n(U03线,U05线)',
|
||||
icon: 'folder-add-filled',
|
||||
iconPath: '/static/images/index_menu_icon/work_report_u03u05.svg',
|
||||
url: '/pages/produceManagement/workorder/workorder03'
|
||||
},
|
||||
{
|
||||
name: '安灯报警',
|
||||
icon: 'notification-filled',
|
||||
iconPath: '/static/images/index_menu_icon/andon_alarm.svg',
|
||||
url: '/pages/produceManagement/andon/alarm'
|
||||
},
|
||||
{
|
||||
name: '产线油漆件叫料',
|
||||
iconPath: '/static/images/index_menu_icon/paint_call.svg',
|
||||
url: '/pages/produceManagement/paintMaterial/paint_call'
|
||||
},
|
||||
{
|
||||
name: '产线油漆件收料',
|
||||
iconPath: '/static/images/index_menu_icon/paint_receive.svg',
|
||||
url: '/pages/produceManagement/paintMaterial/paint_receive'
|
||||
}
|
||||
],
|
||||
// 物料模块
|
||||
materialOptions: [
|
||||
{
|
||||
name: '产线备料',
|
||||
icon: 'upload-filled',
|
||||
iconPath: '/static/images/index_menu_icon/material_preparation.svg',
|
||||
url: '/pages/materialManagement/preparationByPlan/index'
|
||||
}
|
||||
// {
|
||||
@ -128,8 +138,28 @@ export default {
|
||||
// 处理来自 renderjs 的获取存储数据请求
|
||||
handleGetStorage() {
|
||||
const value = getBaseUrl();
|
||||
console.log('handleGetStorage', this.$refs.socketRef);
|
||||
this.$refs.socketRef.receiveStorageValue(value);
|
||||
const maxRetries = 5;
|
||||
const initialDelay = 300;
|
||||
let retries = 0;
|
||||
|
||||
const attemptCall = () => {
|
||||
console.log(`尝试调用receiveStorageValue (第${retries + 1}次)`, this.$refs.socketRef);
|
||||
if (this.$refs.socketRef && typeof this.$refs.socketRef.receiveStorageValue === 'function') {
|
||||
console.log('成功调用receiveStorageValue方法');
|
||||
this.$refs.socketRef.receiveStorageValue(value);
|
||||
} else {
|
||||
if (retries < maxRetries) {
|
||||
retries++;
|
||||
const delay = initialDelay * Math.pow(2, retries - 1); // 指数退避
|
||||
console.error(`第${retries}次尝试失败: socketRef未初始化或receiveStorageValue方法不存在,${delay}ms后重试`);
|
||||
setTimeout(attemptCall, delay);
|
||||
} else {
|
||||
console.error(`达到最大重试次数(${maxRetries}),调用receiveStorageValue方法失败`);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
attemptCall();
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -150,22 +180,6 @@ export default {
|
||||
methods: {
|
||||
initSignalR() {
|
||||
this.requestStorageValue();
|
||||
let baseUrl = this.baseUrl;
|
||||
let url = `http://${baseUrl}/pdaHub`;
|
||||
//let url = "http://192.168.50.163/pdaHub";
|
||||
this.signalRUtil = new SignalRUtil(url);
|
||||
this.signalRUtil
|
||||
.startConnection()
|
||||
.then(() => {
|
||||
this.isSignalRConnected = true;
|
||||
// 监听服务器发送的消息
|
||||
this.signalRUtil.on('Call', (message) => {
|
||||
this.showSystemAlertAndVibrate(message)
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('SignalR 连接失败:', error);
|
||||
});
|
||||
},
|
||||
stopSignalRConnection() {
|
||||
if (this.isSignalRConnected && this.signalRUtil) {
|
||||
@ -208,20 +222,42 @@ export default {
|
||||
}
|
||||
// #endif
|
||||
},
|
||||
// 向逻辑层请求存储数据
|
||||
requestStorageValue() {
|
||||
this.$ownerInstance.callMethod('handleGetStorage');
|
||||
},
|
||||
// 接收逻辑层返回的存储数据
|
||||
receiveStorageValue(value) {
|
||||
console.log('从存储中获取的值:', value);
|
||||
this.baseUrl = value;
|
||||
// 向逻辑层请求存储数据
|
||||
requestStorageValue() {
|
||||
this.$ownerInstance.callMethod('handleGetStorage');
|
||||
},
|
||||
// 接收逻辑层返回的存储数据
|
||||
receiveStorageValue(value) {
|
||||
console.log('从存储中获取的值:', value);
|
||||
this.baseUrl = value;
|
||||
|
||||
// 在这里可以进行后续处理
|
||||
}
|
||||
// 确保baseUrl不为空时才初始化SignalR
|
||||
if (this.baseUrl) {
|
||||
let url = `http://${this.baseUrl}/pdaHub`;
|
||||
console.log('SignalR 连接 URL:', url);
|
||||
this.signalRUtil = new SignalRUtil(url);
|
||||
this.signalRUtil
|
||||
.startConnection()
|
||||
.then(() => {
|
||||
this.isSignalRConnected = true;
|
||||
// 监听服务器发送的消息
|
||||
this.signalRUtil.on('Call', (message) => {
|
||||
this.showSystemAlertAndVibrate(message)
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('SignalR 连接失败:', error);
|
||||
});
|
||||
} else {
|
||||
console.error('baseUrl为空,无法初始化SignalR连接');
|
||||
}
|
||||
}
|
||||
},
|
||||
async mounted() {
|
||||
this.initSignalR()
|
||||
// 确保组件已经挂载完成再初始化
|
||||
setTimeout(() => {
|
||||
this.initSignalR();
|
||||
}, 100);
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@ -250,6 +286,12 @@ view {
|
||||
margin-top: 10rpx;
|
||||
}
|
||||
|
||||
.menu-icon {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.grid-item-box {
|
||||
flex: 1;
|
||||
/* #ifndef APP-NVUE */
|
||||
@ -285,10 +327,18 @@ view {
|
||||
height: 300rpx;
|
||||
line-height: 300rpx;
|
||||
}
|
||||
|
||||
.menu-icon {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.card-box {
|
||||
padding-bottom: 60px;
|
||||
margin-bottom: 60px;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 500px) {
|
||||
.uni-swiper-dot-box {
|
||||
width: 400px;
|
||||
|
||||
@ -128,6 +128,8 @@ export default {
|
||||
if (this.captchaEnabled) {
|
||||
this.getCode();
|
||||
}
|
||||
}).finally(()=>{
|
||||
this.$modal.closeLoading();
|
||||
});
|
||||
},
|
||||
// 登录成功后,处理函数
|
||||
|
||||
362
pages/produceManagement/paintMaterial/paint_call.vue
Normal file
@ -0,0 +1,362 @@
|
||||
<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>
|
||||
249
pages/produceManagement/paintMaterial/paint_receive.vue
Normal file
@ -0,0 +1,249 @@
|
||||
<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="getReceiveList"></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="getReceiveList">查询</button>
|
||||
</view>
|
||||
</uni-forms>
|
||||
</view>
|
||||
|
||||
<!-- 清单展示区域 -->
|
||||
<view class="list-section">
|
||||
<view class="list-header">
|
||||
<text>收料清单</text>
|
||||
</view>
|
||||
<scroll-view scroll-y class="list-container">
|
||||
<view v-if="receiveList.length === 0" class="empty-tip">
|
||||
暂无收料数据
|
||||
</view>
|
||||
<view v-for="(item, index) in receiveList" :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.supplier }}</text>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<text class="label">批次号:</text>
|
||||
<text class="value">{{ item.batchNo }}</text>
|
||||
</view>
|
||||
<view class="info-row">
|
||||
<text class="label">待收数量:</text>
|
||||
<text class="value">{{ item.waitingQuantity }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="item-actions">
|
||||
<button type="primary" size="mini" @click="receiveMaterial(item)">收料</button>
|
||||
<button type="default" size="mini" @click="returnMaterial(item)">退料</button>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { queryReceiveList } from '@/api/mmcall';
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
filterData: {
|
||||
lineCode: '',
|
||||
workOrderDate: new Date()
|
||||
},
|
||||
lineOptions: [
|
||||
{ text: 'U03线', value: 'U03' },
|
||||
{ text: 'U05线', value: 'U05' },
|
||||
{ text: 'U16线', value: 'U16' },
|
||||
{ text: 'U17线', value: 'U17' }
|
||||
],
|
||||
receiveList: []
|
||||
};
|
||||
},
|
||||
onLoad() {
|
||||
// 默认选择当前日期
|
||||
this.filterData.date = new Date();
|
||||
},
|
||||
methods: {
|
||||
// 获取收料清单
|
||||
getReceiveList() {
|
||||
if (!this.filterData.lineCode) {
|
||||
this.$modal.showToast('请先选择线体');
|
||||
return;
|
||||
}
|
||||
|
||||
// 模拟API请求获取收料清单
|
||||
setTimeout(() => {
|
||||
// 模拟数据
|
||||
this.receiveList = [
|
||||
{
|
||||
materialName: '底漆-A',
|
||||
materialCode: 'MAT001',
|
||||
supplier: '供应商1',
|
||||
batchNo: 'BATCH001',
|
||||
waitingQuantity: 100
|
||||
},
|
||||
{
|
||||
materialName: '面漆-B',
|
||||
materialCode: 'MAT002',
|
||||
supplier: '供应商2',
|
||||
batchNo: 'BATCH002',
|
||||
waitingQuantity: 150
|
||||
},
|
||||
{
|
||||
materialName: '清漆-C',
|
||||
materialCode: 'MAT003',
|
||||
supplier: '供应商3',
|
||||
batchNo: 'BATCH003',
|
||||
waitingQuantity: 80
|
||||
}
|
||||
];
|
||||
}, 500);
|
||||
},
|
||||
|
||||
// 收料操作
|
||||
receiveMaterial(item) {
|
||||
uni.showModal({
|
||||
title: '收料确认',
|
||||
content: `确定要收 ${item.materialName} (${item.materialCode}) 吗?`,
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
// 模拟收料API请求
|
||||
setTimeout(() => {
|
||||
this.$modal.showToast('收料成功');
|
||||
// 刷新收料清单
|
||||
this.getReceiveList();
|
||||
}, 500);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// 退料操作
|
||||
returnMaterial(item) {
|
||||
uni.showModal({
|
||||
title: '退料确认',
|
||||
content: `确定要退 ${item.materialName} (${item.materialCode}) 吗?`,
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
// 模拟退料API请求
|
||||
setTimeout(() => {
|
||||
this.$modal.showToast('退料成功');
|
||||
// 刷新收料清单
|
||||
this.getReceiveList();
|
||||
}, 500);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</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-actions {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10rpx;
|
||||
}
|
||||
.empty-tip {
|
||||
text-align: center;
|
||||
padding: 40rpx 0;
|
||||
color: #999;
|
||||
}
|
||||
</style>
|
||||
10
static/images/arrow-icon.svg
Normal file
@ -0,0 +1,10 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<defs>
|
||||
<linearGradient id="arrowGradient" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" style="stop-color:#4A6CF7;stop-opacity:1" />
|
||||
<stop offset="100%" style="stop-color:#1E3AFA;stop-opacity:1" />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<path d="M5 12h14" stroke="url(#arrowGradient)"/>
|
||||
<path d="m12 5 7 7-7 7" stroke="url(#arrowGradient)"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 554 B |
8
static/images/index_menu_icon/andon_alarm.svg
Normal file
@ -0,0 +1,8 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="60" height="60" viewBox="0 0 60 60" fill="none">
|
||||
<rect x="5" y="5" width="50" height="50" rx="12" fill="#F87171"/>
|
||||
<path d="M30 18C35 18 38 23 38 28C38 33 35 38 30 38C25 38 22 33 22 28C22 23 25 18 30 18Z" stroke="white" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M30 38V44" stroke="white" stroke-width="2.5" stroke-linecap="round"/>
|
||||
<path d="M25 44H35" stroke="white" stroke-width="2.5" stroke-linecap="round"/>
|
||||
<path d="M20 35L15 30" stroke="white" stroke-width="1.5" stroke-linecap="round"/>
|
||||
<path d="M40 35L45 30" stroke="white" stroke-width="1.5" stroke-linecap="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 675 B |
7
static/images/index_menu_icon/material_preparation.svg
Normal file
@ -0,0 +1,7 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="60" height="60" viewBox="0 0 60 60" fill="none">
|
||||
<rect x="5" y="5" width="50" height="50" rx="12" fill="#22C55E"/>
|
||||
<path d="M20 20H40V40H20V20Z" stroke="white" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M25 20V40" stroke="white" stroke-width="2.5" stroke-linecap="round"/>
|
||||
<path d="M20 25H40" stroke="white" stroke-width="2.5" stroke-linecap="round"/>
|
||||
<path d="M35 28L43 20" stroke="white" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 555 B |
8
static/images/index_menu_icon/paint_call.svg
Normal file
@ -0,0 +1,8 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="60" height="60" viewBox="0 0 60 60" fill="none">
|
||||
<rect x="5" y="5" width="50" height="50" rx="12" fill="#8B5CF6"/>
|
||||
<path d="M25 20L35 20V35L25 35Z" stroke="white" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M35 20L42 20" stroke="white" stroke-width="2.5" stroke-linecap="round"/>
|
||||
<path d="M35 25L42 25" stroke="white" stroke-width="2.5" stroke-linecap="round"/>
|
||||
<path d="M18 35L18 42" stroke="white" stroke-width="2.5" stroke-linecap="round"/>
|
||||
<path d="M23 42L13 42" stroke="white" stroke-width="2.5" stroke-linecap="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 624 B |
8
static/images/index_menu_icon/paint_receive.svg
Normal file
@ -0,0 +1,8 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="60" height="60" viewBox="0 0 60 60" fill="none">
|
||||
<rect x="5" y="5" width="50" height="50" rx="12" fill="#EC4899"/>
|
||||
<path d="M25 20L35 20V35L25 35Z" stroke="white" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M18 20L25 20" stroke="white" stroke-width="2.5" stroke-linecap="round"/>
|
||||
<path d="M18 25L25 25" stroke="white" stroke-width="2.5" stroke-linecap="round"/>
|
||||
<path d="M35 35L35 42" stroke="white" stroke-width="2.5" stroke-linecap="round"/>
|
||||
<path d="M28 42L42 42" stroke="white" stroke-width="2.5" stroke-linecap="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 624 B |
7
static/images/index_menu_icon/work_report_common.svg
Normal file
@ -0,0 +1,7 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="60" height="60" viewBox="0 0 60 60" fill="none">
|
||||
<rect x="5" y="5" width="50" height="50" rx="12" fill="#4A6CF7"/>
|
||||
<path d="M25 18L35 18L35 40L25 40Z" stroke="white" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M20 25L40 25" stroke="white" stroke-width="2" stroke-linecap="round"/>
|
||||
<path d="M20 30L35 30" stroke="white" stroke-width="2" stroke-linecap="round"/>
|
||||
<path d="M35 18L42 12" stroke="white" stroke-width="2.5" stroke-linecap="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 539 B |
7
static/images/index_menu_icon/work_report_u03u05.svg
Normal file
@ -0,0 +1,7 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="60" height="60" viewBox="0 0 60 60" fill="none">
|
||||
<rect x="5" y="5" width="50" height="50" rx="12" fill="#FB923C"/>
|
||||
<path d="M25 18L35 18L35 40L25 40Z" stroke="white" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M20 25L40 25" stroke="white" stroke-width="2" stroke-linecap="round"/>
|
||||
<path d="M20 30L35 30" stroke="white" stroke-width="2" stroke-linecap="round"/>
|
||||
<path d="M35 18L42 12" stroke="white" stroke-width="2.5" stroke-linecap="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 539 B |
7
static/images/index_menu_icon/work_report_u16u17.svg
Normal file
@ -0,0 +1,7 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="60" height="60" viewBox="0 0 60 60" fill="none">
|
||||
<rect x="5" y="5" width="50" height="50" rx="12" fill="#4ADE80"/>
|
||||
<path d="M25 18L35 18L35 40L25 40Z" stroke="white" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M20 25L40 25" stroke="white" stroke-width="2" stroke-linecap="round"/>
|
||||
<path d="M20 30L35 30" stroke="white" stroke-width="2" stroke-linecap="round"/>
|
||||
<path d="M35 18L42 12" stroke="white" stroke-width="2.5" stroke-linecap="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 539 B |
@ -46,6 +46,11 @@ const request = config => {
|
||||
// console.log('response',response);
|
||||
let [error, res] = response
|
||||
if (error) {
|
||||
if(error.errMsg === "request:fail abort statusCode:-1 timeout"){
|
||||
toast('接口连接超时,请检查IP地址')
|
||||
reject(error)
|
||||
return
|
||||
}
|
||||
toast('后端接口连接异常')
|
||||
reject(error)
|
||||
return
|
||||
|
||||