赵正易 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

356 lines
8.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">
<!-- 轮播图 -->
<uni-swiper-dot class="uni-swiper-dot-box" :info="bannerList" :current="current" field="content">
<swiper class="swiper-box" :current="swiperDotIndex" @change="changeSwiper">
<swiper-item v-for="(item, index) in bannerList" :key="index">
<view class="swiper-item" @click="clickBannerItem(item)">
<image :src="item.image" mode="aspectFill" :draggable="false" />
</view>
</swiper-item>
</swiper>
</uni-swiper-dot>
<!-- 宫格组件 -->
<uni-section title="产线管理" type="line"></uni-section>
<view class="grid-body">
<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">
<image :src="item.iconPath" mode="aspectFit" class="menu-icon"></image>
<text class="text">{{ item.name }}</text>
</view>
</uni-grid-item>
</uni-grid>
</view>
<uni-section title="物料管理" type="line"></uni-section>
<view class="grid-body">
<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">
<image :src="item.iconPath" mode="aspectFit" class="menu-icon"></image>
<text class="text">{{ item.name }}</text>
</view>
</uni-grid-item>
</uni-grid>
</view>
<view ref="socketRef"></view>
</view>
</template>
<script>
import { getBaseUrl } from '@/utils/baseUrl';
export default {
onShow() {
uni.hideLoading();
},
data() {
return {
socketRef: null,
current: 0,
swiperDotIndex: 0,
bannerList: [
{
image: '/static/images/door/1.jpg'
},
{
image: '/static/images/door/2.jpg'
},
{
image: '/static/images/door/3.jpg'
}
],
// 生产模块
produceOptions: [
{
name: '产线报工(通用)',
iconPath: '/static/images/index_menu_icon/work_report_common.svg',
url: '/pages/produceManagement/workorder/workorder'
},
{
name: '产线报工\n(U16线U17线)',
iconPath: '/static/images/index_menu_icon/work_report_u16u17.svg',
url: '/pages/produceManagement/workorder/workorder02'
},
{
name: '产线报工\n(U03线U05线)',
iconPath: '/static/images/index_menu_icon/work_report_u03u05.svg',
url: '/pages/produceManagement/workorder/workorder03'
},
{
name: '安灯报警',
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: '产线备料',
iconPath: '/static/images/index_menu_icon/material_preparation.svg',
url: '/pages/materialManagement/preparationByPlan/index'
}
// {
// name: '工单备料',
// icon: 'upload-filled',
// url: '/pages/materialManagement/materialPreparation/index'
// }
]
};
},
methods: {
clickBannerItem(item) {
console.info(item);
},
changeSwiper(e) {
this.current = e.detail.current;
},
// 产线功能
changeProduceGrid(e) {
const _url = this.produceOptions[e.detail.index].url;
uni.navigateTo({
url: _url,
fail: () => {
this.$modal.showToast('模块建设中~');
}
});
},
// 物料功能
changeMaterialGrid(e) {
const _url = this.materialOptions[e.detail.index].url;
uni.navigateTo({
url: _url,
fail: () => {
this.$modal.showToast('模块建设中~');
}
});
},
// 处理来自 renderjs 的获取存储数据请求
handleGetStorage() {
const value = getBaseUrl();
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();
}
}
};
</script>
<!-- SignalR的使用 -->
<script module="socketRef" lang="renderjs">
import SignalRUtil from '@/utils/signalrUtil';
export default {
data() {
return {
baseUrl:"",
signalRUtil: null,
isSignalRConnected: false
}
},
methods: {
initSignalR() {
this.requestStorageValue();
},
stopSignalRConnection() {
if (this.isSignalRConnected && this.signalRUtil) {
this.signalRUtil
.stopConnection()
.then(() => {
this.isSignalRConnected = false;
console.log('SignalR 连接已停止');
})
.catch((error) => {
console.error('停止 SignalR 连接失败:', error);
});
}
},
// 示例:发送系统通知并震动
showSystemAlertAndVibrate(obj) {
// 发送系统通知
this.sendNativeNotification(obj);
},
// 在需要发送通知的地方调用
sendNativeNotification(obj) {
const {lineCode,askPerson,faultDict,faultContext} = obj;
// #ifdef APP-PLUS
let content = `线别:${lineCode} 报警人:${askPerson}\n报警类别:${faultDict}\n报警内容:${faultContext}`;
let options = {
cover: false,
when: new Date(),
title: '产线Andon报警'
};
let body = {
id: 'id',
key: 'key'
};
let payload = JSON.stringify(body);
plus.push.createMessage(content, payload, options);
if (plus && plus.vibration) {
plus.vibration.vibrate(3000);
} else {
console.error('震动功能不可用');
}
// #endif
},
// 向逻辑层请求存储数据
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() {
// 确保组件已经挂载完成再初始化
setTimeout(() => {
this.initSignalR();
}, 100);
},
}
</script>
<style lang="scss">
/* #ifndef APP-NVUE */
page {
display: flex;
flex-direction: column;
box-sizing: border-box;
background-color: #fff;
min-height: 100%;
height: auto;
}
view {
font-size: 14px;
line-height: inherit;
}
/* #endif */
.text {
text-align: center;
font-size: 26rpx;
margin-top: 10rpx;
}
.menu-icon {
width: 60rpx;
height: 60rpx;
margin-bottom: 8rpx;
}
.grid-item-box {
flex: 1;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: column;
align-items: center;
justify-content: center;
padding: 15px 0;
}
.uni-margin-wrap {
width: 690rpx;
width: 100%;
}
.swiper {
height: 300rpx;
}
.swiper-box {
height: 150px;
}
.swiper-item {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: column;
justify-content: center;
align-items: center;
color: #fff;
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;
/* #ifndef APP-NVUE */
margin: 0 auto;
/* #endif */
margin-top: 8px;
}
.image {
width: 100%;
}
}
</style>