<template>
|
<view class="container">
|
<uni-transition :duration="duration" :mode-class="homeMode" :show="homeViewShow">
|
<view class="home-view">
|
<view class="head">
|
<text>智能大屏显示系统</text>
|
</view>
|
<!-- 日历 -->
|
<view class="time-tools">{{ calendar }}</view>
|
<view class="version">V:{{ version }}</view>
|
<view class="button-left" @click="ejected()"></view>
|
<view class="button-right" @click="ejected()"></view>
|
<!-- 主视图 -->
|
<view class="main">
|
<view class="main-item">
|
<view class="main-item-box">
|
<y-box>
|
<view class="box-item">
|
<text class="item-title">智能大屏显示系统</text>
|
<text class="item-subTitle">Intelligent LargeScreen Display System</text>
|
</view>
|
<view class="box-item">
|
<text class="item-title">仓库数据</text>
|
<text class="item-subTitle">warehouse data</text>
|
<view class="img-box">
|
<view class="data-row" v-for="(item, i) in locList" :key="i">
|
<view class="data-cell data-text">物料码: {{ item.matnr }}</view>
|
<view class="data-cell data-text-lg">数量: {{ item.matnrCount }}</view>
|
</view>
|
</view>
|
</view>
|
<view class="box-item">
|
<view class="flex-row" style="width: 100%">
|
<!-- 左侧 -->
|
<view class="flex-col" style="align-items: flex-start; justify-content: flex-start">
|
<text class="item-title">库位使用率</text>
|
<text class="item-subTitle">EQUIPMENT USAGE THIS MONTH</text>
|
</view>
|
<!-- 右侧 -->
|
<view style="margin-left: auto">
|
<!-- 百分比 -->
|
<view class="flex-col" style="align-items: flex-end; justify-content: flex-end">
|
<!-- style="justify-content: flex-end;position: absolute;top: 0;right: 1vw;text-align: right;" -->
|
<text class="item-title">{{ baseInfo.usedPr }}%</text>
|
<!-- <text class="item-subTitle">同比上月 + 5%</text> -->
|
</view>
|
</view>
|
</view>
|
<view class="flex-col" style="width: 100%; align-items: flex-start; position: relative; font-size: 1vw">
|
<!-- 进度条 -->
|
<view class="flex-row" style="width: 100%; position: relative; margin-top: 5%">
|
<view class="progressBar" style="width: 80%; height: 2vw">
|
<view class="progress" :style="'width:' + baseInfo.usedPr + '%'"></view>
|
</view>
|
<view style="position: absolute; bottom: 0; right: 0; font-size: 2.5vw; color: #ff5722">
|
{{ baseInfo.used }}
|
</view>
|
</view>
|
</view>
|
</view>
|
</y-box>
|
</view>
|
</view>
|
<view class="main-item">
|
<view class="main-item-box">
|
<view style="width: 100%; height: 100%">
|
<view style="height: 35%">
|
<!-- 折线图 -->
|
<y-box>
|
<view class="box-item">
|
<view class="flex-row" style="width: 100%">
|
<!-- 左侧 -->
|
<view class="flex-col" style="align-items: flex-start; justify-content: flex-start">
|
<text class="item-title">入出库统计</text>
|
<text class="item-subTitle">ORDER STATISTICS</text>
|
</view>
|
<!-- 右侧 -->
|
<view style="margin-left: auto">
|
<!-- 百分比 -->
|
<view class="flex-col" style="align-items: flex-end; justify-content: flex-end"></view>
|
</view>
|
</view>
|
<view class="charts-box">
|
<qiun-data-charts type="line" :chartData="chartsDataLine1" :echartsH5="true" :echartsApp="true" />
|
</view>
|
</view>
|
</y-box>
|
</view>
|
<view style="height: 2%"></view>
|
<view style="height: 43%">
|
<y-box>
|
<view class="box-item">
|
<view class="flex-row" style="width: 100%">
|
<view class="flex-col" style="align-items: flex-start; justify-content: flex-start">
|
<text class="item-title">库存类型</text>
|
<text class="item-subTitle">INCOME DATE</text>
|
</view>
|
<view style="margin-left: auto">
|
<view class="flex-col" style="align-items: flex-end; justify-content: flex-end">
|
<text class="item-title">今天</text>
|
<text class="item-subTitle">Today</text>
|
</view>
|
</view>
|
</view>
|
<view class="flex-row" style="width: 100%">
|
<view class="charts-box-ring">
|
<qiun-data-charts
|
type="ring"
|
:opts="{ legend: { position: 'bottom' } }"
|
:eopts="ringOpts"
|
:chartData="chartsDataPie2"
|
:echartsH5="true"
|
:echartsApp="true"
|
/>
|
</view>
|
<view class="stat-panel">
|
<view class="flex-row sub-info">
|
<image src="../../static/g1.png" mode="aspectFit"></image>
|
<view class="stat-label">在库</view>
|
<view class="stat-label data-text-lg">{{ baseInfo.stockCount }}</view>
|
</view>
|
<view class="flex-row sub-info">
|
<image src="../../static/f1.png" mode="aspectFit"></image>
|
<view class="stat-label">空库</view>
|
<view class="stat-label data-text-lg">{{ baseInfo.emptyCount }}</view>
|
</view>
|
<view class="flex-row sub-info">
|
<image src="../../static/e1.png" mode="aspectFit"></image>
|
<view class="stat-label">锁定</view>
|
<view class="stat-label data-text-lg">{{ baseInfo.noneCount }}</view>
|
</view>
|
</view>
|
</view>
|
</view>
|
</y-box>
|
</view>
|
<view style="height: 2%"></view>
|
<view style="height: 18%; display: flex; justify-content: space-around; align-items: center">
|
<view style="height: 50%">
|
<image style="height: 100%; opacity: 0;" src="../../static/img/logo-bai.png" mode="aspectFit"></image>
|
</view>
|
</view>
|
</view>
|
</view>
|
</view>
|
</view>
|
</view>
|
</uni-transition>
|
<!-- 全板/拣料信息 -->
|
<uni-transition :duration="duration" :mode-class="infoMode" :show="infoViewShow">
|
<view class="home-view">
|
<view class="head">
|
<text>{{ infoText.title }}</text>
|
</view>
|
<!-- 日历 -->
|
<view class="time-tools">{{ calendar }}</view>
|
<view class="button-left" @click="ejected()"></view>
|
<view class="button-right" @click="ejected()"></view>
|
<!-- 主体 -->
|
<view class="info-main">
|
<view class="info-box">
|
<y-box>
|
<!-- 文本容器 -->
|
<view class="text-content">
|
<!-- head -->
|
<view class="swiper-head">
|
<view style="width: 30%">托盘码: {{ infoText.barcode }}</view>
|
<view style="width: 20%">工作号: {{ infoText.workNo }}</view>
|
<view style="width: 30%">源库位: {{ infoText.sourceLocNo }}</view>
|
<view style="width: 20%">目标站: {{ infoText.staNo }}</view>
|
</view>
|
<!-- body -->
|
<view class="swiper-body">
|
<swiper class="swiper-body-main" vertical="true" display-multiple-items="1" circular="true" :autoplay="true" :interval="3000" :duration="2000">
|
<swiper-item class="swiper-item" v-for="(item, i) in swiperList" :key="i">
|
<view style="width: 100%">{{ i + 1 }} / {{ swiperList.length }}</view>
|
<view style="width: 50%; font-size: 3vw">物料编码: {{ item.matnr }}</view>
|
<view style="width: 50%; font-size: 3vw">名称: {{ item.maknx }}</view>
|
<view style="width: 50%; font-size: 3vw">规格: {{ item.specs }}</view>
|
<!-- <view style="width: 50%; font-size: 3vw">批次: {{ item.batch }}</view> -->
|
<view style="width: 50%; font-size: 3vw">供应商代码: {{ item.orderNo }}</view>
|
<!-- <view style="width: 50%; font-size: 3vw">客户名称: {{ item.customer }}</view> -->
|
<view style="width: 33%; font-size: 3vw">数量: {{ item.count }}</view>
|
</swiper-item>
|
</swiper>
|
</view>
|
</view>
|
</y-box>
|
</view>
|
</view>
|
</view>
|
</uni-transition>
|
<!-- 异常信息 -->
|
<uni-transition :duration="duration" :mode-class="errorInfoMode" :show="errorInfoViewShow">
|
<view class="error-info-view">
|
<view class="head">
|
<text>{{ infoText.title }}</text>
|
</view>
|
<!-- 日历 -->
|
<view class="time-tools">{{ calendar }}</view>
|
<view class="button-left"></view>
|
<view class="button-right"></view>
|
<!-- 主体 -->
|
<view class="info-main">
|
<view class="info-box">
|
<y-box>
|
<view class="info-box-text">
|
<view class="flex-col info-box-text-item">{{ infoText.error }}</view>
|
</view>
|
</y-box>
|
</view>
|
</view>
|
</view>
|
</uni-transition>
|
<!-- 自定义弹出层 -->
|
<view class="eject-mask" v-show="ejectShow">
|
<view class="eject">
|
<view class="eject-title">修改 / 配置</view>
|
<scroll-view scroll-y class="eject-input">
|
<view class="item">
|
<view class="desc">ip:</view>
|
<view class="input">
|
<input type="text" v-model="baseIP" />
|
</view>
|
</view>
|
<view class="item">
|
<view class="desc">port:</view>
|
<view class="input">
|
<input type="text" v-model="basePort" />
|
</view>
|
</view>
|
<view class="item">
|
<view class="desc">Url:</view>
|
<view class="input">
|
<input type="text" v-model="baseUrl" />
|
</view>
|
</view>
|
<view class="item">
|
<view class="desc">ledId:</view>
|
<view class="input">
|
<input type="text" v-model="baseLedId" />
|
</view>
|
</view>
|
</scroll-view>
|
<!-- button -->
|
<view class="eject-button">
|
<view class="button-item" @click="ejectClose">取 消</view>
|
<view class="button-item" @click="ejectConfirm">确 认</view>
|
</view>
|
</view>
|
</view>
|
<view>
|
<!-- 提示窗示例 -->
|
<uni-popup ref="upVersion" type="dialog">
|
<uni-popup-dialog :type="msgType" title="通知" :content="dialogContent" @confirm="dialogConfirm" @close="dialogClose"></uni-popup-dialog>
|
</uni-popup>
|
</view>
|
<view style="color: #fff; position: fixed; bottom: 10px; left: 10px" v-show="timeOut">连接超时,正在重新建立链接:: {{ times }}</view>
|
</view>
|
</template>
|
<script>
|
import WebSocketUtil from './uniWebSocket';
|
|
// 任务类型常量映射
|
const IO_TYPE_MAP = {
|
101: '全板出库',
|
103: '拣料出库',
|
107: '盘点出库',
|
1: '入库',
|
10: '空托入库',
|
110: '空托出库',
|
104: '并板出库',
|
54: '并板入库'
|
};
|
|
export default {
|
data() {
|
return {
|
// 视图状态
|
homeViewShow: true,
|
infoViewShow: false,
|
errorInfoViewShow: false,
|
homeMode: [],
|
infoMode: [],
|
errorInfoMode: [],
|
|
// 基础信息
|
baseInfo: {
|
xDistance: 1,
|
yDistance: 2,
|
xDuration: 3,
|
yDuration: 4,
|
usedPr: 50,
|
used: 3537,
|
stockCount: '',
|
emptyCount: '',
|
noneCount: ''
|
},
|
|
// 图表数据
|
chartsData: {
|
Line: { categories: [], series: [] },
|
Pie: { series: [{ data: [] }] }
|
},
|
|
// 动画与图表
|
duration: 300,
|
calendar: '',
|
ringOpts: {},
|
chartsDataLine1: {},
|
chartsDataPie2: {},
|
|
// 配置弹窗
|
ejectShow: false,
|
|
// 服务器配置
|
baseIP: '',
|
basePort: '',
|
baseLedId: '',
|
baseUrl: '',
|
wmsUrl: '',
|
wmsPort: '',
|
getConfigUrl: 'http://127.0.0.1:8088/wcs/monitor/getIpConfig',
|
|
// 任务信息
|
infoType: 0,
|
infoText: {
|
title: '',
|
staNo: '',
|
matnr: '',
|
maknx: '',
|
specs: '',
|
count: '',
|
error: '',
|
barcode: ''
|
},
|
swiperList: [],
|
|
// 连接状态
|
timeOut: false,
|
times: 0,
|
socketClient: null,
|
socketUrl: '',
|
|
// 日期时间
|
currDate: '',
|
locList: [],
|
oldHours: '',
|
oldMin: '',
|
|
// 版本更新
|
version: '',
|
msgType: 'success',
|
filename: '',
|
dialogContent: '',
|
|
// 视图切换控制
|
switchDebounceTimer: null,
|
viewSwitchInProgress: false,
|
|
// 定时器ID(用于清理)
|
refreshTimerId: null,
|
restartTimerId: null,
|
gcTimerId: null
|
};
|
},
|
onShow() {
|
// 隐藏时间,电量,信号等
|
// #ifdef APP-PLUS
|
plus.navigator.setFullscreen(true);
|
// #endif
|
this.getVersion();
|
},
|
|
mounted() {
|
// 使用统一的配置初始化方法
|
this.initConfig();
|
},
|
|
created() {
|
// 初始化配置并建立连接
|
this.initConfig();
|
this.getIPConfig();
|
this.uniWebSocket();
|
},
|
|
onLoad() {
|
// 数据刷新定时器(每秒)
|
this.refreshTimerId = setInterval(() => {
|
this.getServerData();
|
this.controller();
|
}, 1000);
|
|
// 应用重启定时器(每4小时)
|
this.restartTimerId = setInterval(() => {
|
setTimeout(() => {
|
plus.runtime.restart();
|
}, 100);
|
}, 1000 * 60 * 60 * 4);
|
|
// 垃圾回收定时器(每5分钟)
|
this.gcTimerId = setInterval(() => {
|
// #ifdef APP-PLUS
|
if (plus.os.name.toLowerCase() === 'android') {
|
plus.android.importClass('java.lang.System');
|
plus.android.invoke('java.lang.System', 'gc');
|
console.log('手动触发 GC');
|
}
|
// #endif
|
// 清理大型数据对象
|
if (this.oldData && this.oldData.length > 100) {
|
this.oldData = [];
|
}
|
}, 30000 * 10);
|
},
|
|
// 组件卸载时清理资源
|
onUnload() {
|
// 清理所有定时器
|
if (this.refreshTimerId) {
|
clearInterval(this.refreshTimerId);
|
this.refreshTimerId = null;
|
}
|
if (this.restartTimerId) {
|
clearInterval(this.restartTimerId);
|
this.restartTimerId = null;
|
}
|
if (this.gcTimerId) {
|
clearInterval(this.gcTimerId);
|
this.gcTimerId = null;
|
}
|
if (this.switchDebounceTimer) {
|
clearTimeout(this.switchDebounceTimer);
|
this.switchDebounceTimer = null;
|
}
|
|
// 关闭 WebSocket 连接
|
if (this.socketClient) {
|
this.socketClient.close();
|
this.socketClient = null;
|
}
|
},
|
|
methods: {
|
// 统一的配置初始化方法
|
initConfig() {
|
this.baseIP = uni.getStorageSync('BaseIp') || '';
|
this.baseLedId = uni.getStorageSync('BaseLedId') || '';
|
this.basePort = uni.getStorageSync('BasePort') || '';
|
this.baseCrnId = uni.getStorageSync('BaseCrnId') || '';
|
this.baseUrl = uni.getStorageSync('UPROJ') || '';
|
this.wmsUrl = uni.getStorageSync('wmsUrl') || '';
|
this.wmsPort = uni.getStorageSync('wmsPort') || '';
|
},
|
|
// 获取IP配置(带错误处理)
|
getIPConfig() {
|
const that = this;
|
uni.request({
|
url: that.getConfigUrl,
|
method: 'GET',
|
timeout: 5000,
|
success(result) {
|
if (result.data && result.data.data) {
|
const configData = result.data.data;
|
uni.setStorageSync('BaseIp', configData.ledIp || '');
|
uni.setStorageSync('BaseLedId', configData.ledId || '');
|
uni.setStorageSync('BasePort', configData.ledPort || '');
|
uni.setStorageSync('UPROJ', configData.ledUrl || '');
|
console.log('IP配置获取成功');
|
}
|
},
|
fail(err) {
|
console.error('获取IP配置失败:', err);
|
// 使用本地存储的配置作为后备
|
}
|
});
|
},
|
uniWebSocket() {
|
let that = this;
|
that.commonUrl = that.baseIP + ':' + that.basePort + '/' + that.baseUrl;
|
that.socketUrl = 'ws://' + that.commonUrl + '/led/' + that.baseLedId;
|
// 创建WebSocket实例
|
that.socketClient = new WebSocketUtil(that.socketUrl, {
|
// 心跳间隔,默认30秒
|
heartbeatInterval: 30000,
|
// 重连间隔,默认3秒
|
reconnectInterval: 3000,
|
// 最大重连次数,-1表示无限重连
|
maxReconnectAttempts: -1,
|
// 消息回调
|
onMessage: (res) => {
|
try {
|
const data = JSON.parse(res.data);
|
that.showDate(data);
|
// 处理消息...
|
} catch (e) {
|
console.error('解析消息失败', e);
|
}
|
},
|
// 连接打开回调
|
onOpen: (res) => {
|
that.timeOut = false;
|
that.times = 0;
|
console.log('WebSocket已连接', res);
|
},
|
// 连接错误回调
|
onError: (error) => {
|
console.error('WebSocket错误', error);
|
},
|
// 连接关闭回调
|
onClose: (res) => {
|
that.timeOut = true;
|
that.times = that.times + 1;
|
that.infoType = 0;
|
console.log('WebSocket已关闭', res);
|
},
|
// 重连回调
|
onReconnect: (info) => {
|
console.log(`WebSocket重连(${info.attempts}/${info.maxAttempts})`);
|
}
|
});
|
|
// 建立连接
|
that.socketClient.connect();
|
},
|
showDate(data) {
|
const that = this;
|
if (data.type === 'default') {
|
that.chartsData.Pie.series[0].data = data.pie;
|
that.baseInfo.stockCount = data.stockCunt;
|
that.baseInfo.emptyCount = data.emptyCount;
|
that.baseInfo.noneCount = data.noneCount;
|
that.baseInfo.used = data.used;
|
that.baseInfo.usedPr = data.usedPr;
|
|
that.chartsData.Line.categories = that.generateDateCategories(-11, 0);
|
that.chartsData.Line.series = data.rows;
|
that.calendar = data.year + '年' + data.month + '月' + data.day + '日 ' + data.hour + ':' + data.minute + ':' + data.second + ' ' + data.week;
|
that.currDate = data.year + '/' + data.month + '/' + data.day;
|
that.locList = data.inventoryData;
|
that.oldHours = data.hour;
|
that.oldMin = data.minute;
|
} else if (data.type === 'error') {
|
if (data.errMsg && data.errMsg !== '') {
|
var errorInfo = data.errMsg;
|
if (that.infoType == 1) {
|
that.infoType = 3;
|
that.infoText.title = '其他信息';
|
// that.infoText.title = "异常"
|
that.infoText.error = errorInfo;
|
return;
|
}
|
that.infoType = 2;
|
that.infoText.title = '其他信息';
|
// that.infoText.title = "异常"
|
that.infoText.error = errorInfo;
|
} else {
|
if (that.infoType == 1) {
|
return;
|
}
|
that.infoType = 0;
|
}
|
} else if (data.type === 'task') {
|
this.handleTaskData(data);
|
} else if (data.type === 'NoData') {
|
that.infoType = 0;
|
}
|
},
|
|
// 处理任务数据(使用常量映射简化逻辑)
|
handleTaskData(data) {
|
// 无任务列表时
|
if (!data.taskList || data.taskList.length === 0) {
|
// 异常信息优先级更高,不切换
|
if (this.infoType === 2 || this.infoType === 3) {
|
return;
|
}
|
this.infoType = 0;
|
return;
|
}
|
|
// 异常信息优先级更高,不切换到任务视图
|
if (this.infoType === 2 || this.infoType === 3) {
|
return;
|
}
|
|
const task = data.taskList[0];
|
this.infoType = 1;
|
|
// 使用常量映射获取任务类型名称
|
this.infoText.title = IO_TYPE_MAP[task.ioType] || task.title || '任务';
|
this.infoText.barcode = task.barcode || '';
|
this.infoText.workNo = task.workNo || '';
|
this.infoText.sourceLocNo = task.sourceLocNo || '';
|
this.infoText.staNo = task.staNo || '';
|
this.swiperList = task.matDtos || [];
|
},
|
|
// 生成日期分类数组(性能优化)
|
generateDateCategories(startOffset, endOffset) {
|
const categories = [];
|
const baseDate = new Date(this.currDate);
|
for (let i = startOffset; i <= endOffset; i++) {
|
const date = new Date(baseDate);
|
date.setDate(date.getDate() + i);
|
categories.push(`${date.getMonth() + 1}-${date.getDate()}`);
|
}
|
return categories;
|
},
|
|
getDateFormat(value) {
|
const date = new Date(this.currDate);
|
date.setDate(date.getDate() + value);
|
return `${date.getMonth() + 1}-${date.getDate()}`;
|
},
|
|
getServerData() {
|
// 使用展开运算符浅拷贝(性能优于 JSON 深拷贝)
|
this.chartsDataLine1 = { ...this.chartsData.Line };
|
this.chartsDataPie2 = { ...this.chartsData.Pie };
|
},
|
// 控制器
|
controller() {
|
// 防抖处理,避免频繁切换
|
if (this.switchDebounceTimer) {
|
clearTimeout(this.switchDebounceTimer);
|
}
|
this.switchDebounceTimer = setTimeout(() => {
|
this.performViewSwitch();
|
}, 100);
|
},
|
|
performViewSwitch() {
|
// 使用状态机模式简化视图切换
|
const viewStates = {
|
0: () => this.showHomeView(),
|
1: () => this.showInfoView(),
|
2: () => this.showErrorView(),
|
3: () => this.showErrorView()
|
};
|
const switchAction = viewStates[this.infoType];
|
if (switchAction && !this.viewSwitchInProgress) {
|
this.viewSwitchInProgress = true;
|
switchAction();
|
// 统一的切换完成处理
|
setTimeout(() => {
|
this.viewSwitchInProgress = false;
|
}, this.duration + 100);
|
}
|
},
|
|
// 统一的视图切换方法
|
switchToView(viewType) {
|
const transitionMode = ['fade', 'slide-bottom'];
|
|
// 根据目标视图隐藏其他视图
|
if (viewType !== 'home') {
|
this.homeViewShow = false;
|
this.homeMode = transitionMode;
|
}
|
if (viewType !== 'info') {
|
this.infoViewShow = false;
|
this.infoMode = transitionMode;
|
}
|
if (viewType !== 'error') {
|
this.errorInfoViewShow = false;
|
this.errorInfoMode = transitionMode;
|
}
|
|
// 延迟显示目标视图
|
setTimeout(() => {
|
switch(viewType) {
|
case 'home':
|
this.homeViewShow = true;
|
this.homeMode = transitionMode;
|
break;
|
case 'info':
|
this.infoViewShow = true;
|
this.infoMode = transitionMode;
|
break;
|
case 'error':
|
this.errorInfoViewShow = true;
|
this.errorInfoMode = transitionMode;
|
break;
|
}
|
}, this.duration);
|
},
|
|
showHomeView() {
|
this.switchToView('home');
|
},
|
|
showInfoView() {
|
this.switchToView('info');
|
},
|
|
showErrorView() {
|
this.switchToView('error');
|
},
|
// 配置
|
ejected() {
|
this.ejectShow = true;
|
},
|
// 取消配置
|
ejectClose() {
|
this.ejectShow = false;
|
},
|
// 确认配置
|
ejectConfirm() {
|
uni.setStorageSync('BaseIp', this.baseIP);
|
uni.setStorageSync('BaseLedId', this.baseLedId);
|
uni.setStorageSync('BasePort', this.basePort);
|
uni.setStorageSync('BaseCrnId', this.baseCrnId);
|
uni.setStorageSync('UPROJ', this.baseUrl);
|
uni.setStorageSync('wmsUrl', this.wmsUrl);
|
uni.setStorageSync('wmsPort', this.wmsPort);
|
|
this.ejectShow = false;
|
},
|
//检测当前平台,如果是安卓则启动安卓更新
|
getVersion() {
|
let that = this;
|
uni.getSystemInfo({
|
success: (res) => {
|
if (res.platform == 'android') {
|
that.AndroidCheckUpdate();
|
}
|
}
|
});
|
},
|
// 获取当前版本号
|
AndroidCheckUpdate() {
|
let that = this;
|
plus.runtime.getProperty(plus.runtime.appid, (wgtinfo) => {
|
that.version = wgtinfo.version; //客户端版本号
|
});
|
setTimeout(() => {
|
that.getUpdateVersion();
|
}, 100);
|
},
|
// 校验版本(增强错误处理)
|
getUpdateVersion() {
|
const that = this;
|
const type = 1;
|
|
// 配置验证
|
if (!that.baseIP || !that.wmsPort || !that.wmsUrl) {
|
console.log('版本检查跳过:配置不完整');
|
return;
|
}
|
|
const wmsBaseUrl = `http://${that.baseIP}:${that.wmsPort}/${that.wmsUrl}`;
|
const url = `${wmsBaseUrl}/appVersion/checkUpdate/${that.version}/${type}`;
|
|
uni.request({
|
url: url,
|
method: 'GET',
|
timeout: 10000,
|
success(result) {
|
const res = result.data;
|
if (res && res.data) {
|
that.filename = res.data.path;
|
that.dialogContent = `发现新版本: ${res.data.version}, 是否立即更新`;
|
that.$refs.upVersion.open();
|
}
|
},
|
fail(err) {
|
console.error('版本检查失败:', err);
|
}
|
});
|
},
|
dialogConfirm() {
|
this.$refs.upVersion.close();
|
this.downWgt();
|
},
|
dialogClose() {
|
this.$refs.upVersion.close();
|
},
|
downWgt() {
|
let that = this;
|
const wms = 'http://' + that.baseIP + ':' + that.wmsPort + '/' + that.wmsUrl;
|
const downloadUrl = wms + '/appVersion/downloadApp/' + that.filename;
|
uni.showLoading({
|
title: '更新中……'
|
});
|
const downloadTask = uni.downloadFile({
|
//执行下载
|
url: downloadUrl, //下载地址
|
timeout: 1000 * 30, //30秒超时时间
|
success: (downloadResult) => {
|
//下载成功
|
console.log(downloadResult);
|
that.showdownLine = false;
|
uni.hideLoading();
|
if (downloadResult.statusCode == 200) {
|
uni.showModal({
|
title: '',
|
content: '更新成功,确定现在重启吗?',
|
confirmText: '重启',
|
confirmColor: '#EE8F57',
|
success: function (res) {
|
if (res.confirm == true) {
|
plus.runtime.install(
|
//安装
|
downloadResult.tempFilePath,
|
{
|
force: true
|
},
|
function (res) {
|
utils.showToast('更新成功,重启中');
|
plus.runtime.restart();
|
}
|
);
|
}
|
}
|
});
|
} else {
|
uni.hideLoading();
|
that.showdownLine = false;
|
uni.showToast({
|
title: '请先上传安装包',
|
icon: 'error'
|
});
|
}
|
},
|
fail: (err) => {
|
uni.hideLoading();
|
that.showdownLine = false;
|
that.$u.toast(downloadResult.errMsg);
|
},
|
complete: (com) => {
|
console.log(com);
|
}
|
});
|
|
// 下载进度
|
downloadTask.onProgressUpdate((res) => {
|
that.downloadNum = res.progress;
|
console.log('下载进度' + that.downloadNum);
|
});
|
}
|
}
|
};
|
</script>
|
|
<style>
|
@import url('home.css');
|
|
/* ========== 工具类 ========== */
|
.flex-col {
|
display: flex;
|
flex-direction: column;
|
}
|
|
.flex-row {
|
display: flex;
|
flex-direction: row;
|
}
|
|
.flex-full {
|
width: 100%;
|
display: flex;
|
}
|
|
.flex-center {
|
display: flex;
|
justify-content: center;
|
align-items: center;
|
}
|
|
/* 数据文本样式 */
|
.data-text {
|
font-size: 1.3vw;
|
color: rgba(255, 255, 255, 0.9);
|
}
|
|
.data-text-lg {
|
font-size: 2vw;
|
font-weight: 600;
|
color: #00d4ff;
|
}
|
|
.data-text-xl {
|
font-size: 3vw;
|
font-weight: 700;
|
}
|
|
.stat-label {
|
width: 8vw;
|
height: 4vw;
|
line-height: 4vw;
|
}
|
|
/* 数据行列表 */
|
.data-row {
|
width: 100%;
|
display: flex;
|
padding: 0.5vw 0;
|
border-bottom: 1px solid rgba(0, 212, 255, 0.1);
|
transition: background 0.2s ease;
|
}
|
|
.data-row:hover {
|
background: rgba(0, 212, 255, 0.05);
|
}
|
|
.data-cell {
|
display: flex;
|
justify-content: center;
|
align-items: center;
|
width: 48%;
|
}
|
|
/* 统计面板 */
|
.stat-panel {
|
display: flex;
|
flex-direction: column;
|
gap: 1.5vh;
|
}
|
|
/* ========== 容器 ========== */
|
.container {
|
width: 100vw;
|
min-height: 100vh;
|
background: linear-gradient(135deg, #00163e 0%, #001a4d 50%, #00163e 100%);
|
color: #fff;
|
text-align: center;
|
}
|
|
/* ========== 主视图 ========== */
|
.home-view {
|
width: 100vw;
|
min-height: 100vh;
|
background-image: url(../../static/background.png);
|
background-size: 100vw 100vh;
|
background-position: center;
|
}
|
|
.home-right {
|
width: 50vw;
|
height: 89vh;
|
}
|
|
.home-right-box {
|
width: 98%;
|
height: 98%;
|
}
|
|
/* ========== 头部标题 ========== */
|
.head {
|
width: 100vw;
|
height: 11vh;
|
font-size: 4vw;
|
font-weight: 700;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
transform: scale(0.7);
|
background: linear-gradient(180deg, rgba(0, 212, 255, 0.1) 0%, transparent 100%);
|
text-shadow: 0 0 20px rgba(0, 212, 255, 0.5);
|
letter-spacing: 0.5vw;
|
}
|
|
/* ========== 时间工具栏 ========== */
|
.time-tools {
|
position: absolute;
|
right: 2%;
|
top: 2%;
|
font-size: 1vw;
|
transform: scale(0.8);
|
color: rgba(255, 255, 255, 0.8);
|
text-shadow: 0 0 10px rgba(0, 212, 255, 0.3);
|
}
|
|
/* ========== 装饰按钮 ========== */
|
.button-left {
|
position: absolute;
|
background-image: url(../../static/right.png);
|
background-size: 100% 100%;
|
top: 1.8%;
|
left: 21.3%;
|
width: 13.5%;
|
height: 8.5%;
|
transform: scaleX(-1);
|
opacity: 0.9;
|
transition: opacity 0.3s ease;
|
}
|
|
.button-left:hover,
|
.button-right:hover {
|
opacity: 1;
|
}
|
|
.button-right {
|
position: absolute;
|
background-image: url(../../static/right.png);
|
background-size: 100% 100%;
|
top: 1.8%;
|
left: 65%;
|
width: 13.5%;
|
height: 8.5%;
|
opacity: 0.9;
|
transition: opacity 0.3s ease;
|
}
|
|
/* ========== 仓库数据列表 ========== */
|
.img-box {
|
height: 23vw;
|
width: 100%;
|
display: flex;
|
flex-direction: row;
|
justify-content: flex-start;
|
flex-wrap: wrap;
|
font-size: 1vw;
|
overflow-y: auto;
|
padding: 0.5vw;
|
}
|
|
.img-box::-webkit-scrollbar {
|
width: 4px;
|
}
|
|
.img-box::-webkit-scrollbar-thumb {
|
background: rgba(0, 212, 255, 0.5);
|
border-radius: 2px;
|
}
|
|
.item-img {
|
width: 50%;
|
margin-top: 5%;
|
display: flex;
|
flex-direction: row;
|
justify-content: flex-start;
|
align-items: flex-start;
|
}
|
|
.distance {
|
}
|
|
.item-img image {
|
height: 5vw;
|
width: 5vw;
|
}
|
|
/* ========== 进度条(增强版)========== */
|
.progressBar {
|
margin-top: 9%;
|
height: 20%;
|
background: linear-gradient(90deg, #233751 0%, #1a2a3d 100%);
|
border-radius: 5vw;
|
overflow: hidden;
|
box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.3);
|
position: relative;
|
}
|
|
.progress {
|
height: 100%;
|
max-width: 100%;
|
background: linear-gradient(90deg, #ff9800 0%, #ff5722 50%, #f44336 100%);
|
border-radius: 5vw;
|
transition: width 0.5s ease-out;
|
position: relative;
|
}
|
|
.progress::after {
|
content: '';
|
position: absolute;
|
top: 0;
|
left: 0;
|
right: 0;
|
bottom: 0;
|
background: linear-gradient(180deg, rgba(255, 255, 255, 0.3) 0%, transparent 50%);
|
border-radius: 5vw;
|
}
|
|
/* ========== 图表区域 ========== */
|
.charts-box {
|
width: 80%;
|
height: 24vh;
|
margin-left: 10%;
|
}
|
|
.charts-box-ring {
|
width: 60%;
|
height: 24vh;
|
}
|
|
/* ========== 库存统计信息 ========== */
|
.sub-info {
|
font-size: 1.5vw;
|
padding: 0.5vw 1vw;
|
border-radius: 0.5vw;
|
background: rgba(0, 212, 255, 0.05);
|
transition: background 0.3s ease;
|
}
|
|
.sub-info:hover {
|
background: rgba(0, 212, 255, 0.1);
|
}
|
|
.sub-info image {
|
width: 3.5vw;
|
height: 3.5vw;
|
margin-right: 0.5vw;
|
}
|
|
/* ========== 共用 ========== */
|
.main {
|
width: 100vw;
|
height: 88vh;
|
margin-top: 1vh;
|
display: flex;
|
}
|
|
.main-item {
|
width: 50%;
|
height: 100%;
|
display: flex;
|
flex-direction: column;
|
align-items: center;
|
justify-content: center;
|
}
|
|
.main-item-box {
|
width: 98%;
|
height: 98%;
|
}
|
|
.box-item {
|
width: 100%;
|
margin-top: 4%;
|
display: flex;
|
flex-direction: column;
|
align-items: flex-start;
|
justify-content: flex-start;
|
}
|
|
.item-title {
|
font-size: 1.5vw;
|
font-weight: 700;
|
}
|
|
.version {
|
position: absolute;
|
left: 1%;
|
top: 1%;
|
font-size: 1vw;
|
transform: scale(0.8);
|
}
|
|
.item-subTitle {
|
font-size: 0.5vw;
|
text-indent: 0em;
|
}
|
|
.item-text {
|
font-size: 1vw;
|
text-indent: 2em;
|
letter-spacing: 1px;
|
line-height: 3vh;
|
}
|
|
/* 全板/拣料信息 */
|
.info-view {
|
width: 100vw;
|
min-height: 100vh;
|
background-image: url(../../static/background.png);
|
background-size: 100vw 100vh;
|
}
|
|
.info-main {
|
width: 100vw;
|
height: 88vh;
|
display: flex;
|
justify-content: center;
|
align-items: center;
|
}
|
|
.info-box {
|
width: 98%;
|
height: 98%;
|
}
|
|
/* 异常信息 */
|
.error-info-view {
|
width: 100vw;
|
min-height: 100vh;
|
background-image: url(../../static/background.png);
|
background-size: 100vw 100vh;
|
}
|
|
/* 弹出:配置区域 */
|
.eject-mask {
|
width: 100%;
|
height: 100%;
|
background-color: rgba(0, 0, 0, 0.5);
|
position: fixed;
|
top: 0;
|
left: 0;
|
z-index: 999;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
}
|
|
.eject {
|
position: relative;
|
width: 45vw;
|
height: 45vh;
|
background-color: #fff;
|
border-radius: 2rem;
|
}
|
|
.eject-title {
|
width: 100%;
|
height: 5vh;
|
line-height: 6vh;
|
font-size: 3vh;
|
font-weight: 700;
|
color: #606266;
|
text-align: center;
|
}
|
|
.eject-input {
|
margin-top: 2vh;
|
height: 25vh;
|
|
/* background-color: #00163E; */
|
::-webkit-scrollbar {
|
display: none;
|
}
|
}
|
|
.item {
|
display: flex;
|
align-items: center;
|
margin: 1vh 0 0 0;
|
font-size: 1.5vw;
|
color: #363636;
|
}
|
|
.desc {
|
display: inline-block;
|
width: 40%;
|
text-align: right;
|
color: #606266;
|
}
|
|
.input {
|
display: flex;
|
align-items: center;
|
padding-left: 5px;
|
padding-right: 5px;
|
width: 100%;
|
height: 3vh;
|
border: 0.1vh solid #cfd4dc;
|
margin-right: 20%;
|
text-align: start;
|
}
|
|
.eject-input input {
|
width: 100%;
|
height: 3vh;
|
font-size: 1vw;
|
}
|
|
.eject-button {
|
display: flex;
|
align-items: center;
|
position: absolute;
|
bottom: 0;
|
height: 6vh;
|
line-height: 6vh;
|
width: 100%;
|
border-top: 1px solid #ccc;
|
}
|
|
.button-item {
|
width: 50%;
|
height: 100%;
|
font-size: 1.5vw;
|
font-weight: bold;
|
text-align: center;
|
color: #909399;
|
}
|
|
.button-item:last-child {
|
color: #67c23a;
|
|
border-left: 1px solid #ccc;
|
}
|
|
.info-box-text {
|
width: 100%;
|
height: 100%;
|
display: flex;
|
flex-direction: column;
|
align-items: center;
|
justify-content: center;
|
}
|
|
.info-box-text-item {
|
height: 20%;
|
font-size: 8vh;
|
justify-content: center;
|
}
|
</style>
|