<template>
|
<view class="page">
|
<view class="status-section">
|
<!-- 报工记录表 -->
|
<view class="report-table-wrapper">
|
<view class="report-title">报工记录表</view>
|
<table class="report-table">
|
<thead>
|
<tr>
|
<th>时间</th>
|
<th>报工人</th>
|
<th>工单号</th>
|
<th>产品名称</th>
|
<th>计划生产数</th>
|
<th>机台号</th>
|
<th>初始采集数</th>
|
<th>报工时采集数</th>
|
<th>报工数(计算)</th>
|
<th>不良数</th>
|
<th>良品数(计算)</th>
|
</tr>
|
</thead>
|
<tbody>
|
<tr>
|
<td>{{ nowTime }}</td>
|
<td>{{ staffNo || '-' }}</td>
|
<td>{{ orderNo || '-' }}</td>
|
<td>{{ order.daa003 || '-' }}</td>
|
<td>{{ planQtyDisplay }}</td>
|
<td>{{ machineNo || '-' }}</td>
|
<td>{{ initialValue }}</td>
|
<td>{{ productionCount }}</td>
|
<td>{{ calculatedTotalProduction }}</td>
|
<td>{{ calculatedDefectiveCount }}</td>
|
<td>{{ sQuantity }}</td>
|
</tr>
|
</tbody>
|
</table>
|
</view>
|
|
<!-- 顶部状态(保留原第一行) -->
|
<view class="status-row">
|
<view class="status-box">
|
<text>机台面板数:</text>
|
<input v-model="productionCount" class="highlight" disabled />
|
</view>
|
<view class="status-box">
|
<text>当前采集数:</text>
|
<input v-model="calculatedCurrentCount" class="highlight" disabled />
|
</view>
|
<view class="operator-box">-</view>
|
<view class="status-box standalone-box">
|
<text>已打印条码数:</text>
|
<input v-model="sQuantity" class="highlight" disabled />
|
</view>
|
<view class="operator-box">=</view>
|
<view class="status-box">
|
<text>机采不良数:</text>
|
<input v-model="calculatedDefectiveCount" class="highlight" disabled />
|
</view>
|
<view class="status-box result-box">
|
<text>已生产数:</text>
|
<input v-model="calculatedTotalProduction" class="highlight" disabled />
|
</view>
|
</view>
|
|
<!-- 头部 -->
|
<view class="header-container">
|
<view class="header-title">
|
<text>生产数据统计</text>
|
</view>
|
<view class="header-right">
|
<view class="version-info-top">
|
<text>v1.0.6</text>
|
</view>
|
<button class="refresh-btn" @click="refresh">刷新</button>
|
<button v-if="isGeneratingBarcode" class="reset-btn" @click="resetGenerateState">重置</button>
|
</view>
|
</view>
|
|
<!-- 基础信息(移除 图号 / 材质 / 颜色 行) -->
|
<view>
|
<view style="display:flex;flex-direction:column;">
|
<view class="form-row">
|
<view class="form-item">
|
<label>产品编码:</label>
|
<input class="inp" type="text" v-model="order.daa002" disabled />
|
</view>
|
<view class="form-item">
|
<label>产品名称:</label>
|
<superwei-combox :candidates="DAA003List" v-model="order.daa003"
|
@select="onDaa003Change" class="inp"></superwei-combox>
|
</view>
|
<view class="form-item">
|
<label>产品规格:</label>
|
<input class="inp" type="text" v-model="order.daa004" disabled />
|
</view>
|
</view>
|
</view>
|
</view>
|
|
<!-- 不良数量 -->
|
<view class="print-section" style="margin-top:20px;">
|
<view class="barcode-info">
|
<view class="user-select">
|
<text style="display:inline-block;float:left;margin-left:-11px;">不良数量:</text>
|
<input v-model="customAmount" class="inp"
|
style="width:55%;height:70px;border:3px solid #808080;font-size:40px;text-align:center;margin-top:5px;"
|
placeholder="请输入数量" />
|
</view>
|
<view class="user-select" style="margin-left:30px;">
|
<button class="details-btn" @click="confirmCustomAmount">确认提交</button>
|
</view>
|
</view>
|
</view>
|
|
<!-- 报工人选择 -->
|
<view>
|
<view class="reason-section" style="margin-bottom:-16px">
|
<text>报工人:</text>
|
<view class="reason-buttons" style="font-size:23px;">
|
<button v-for="(u,index) in users" :key="index"
|
:class="{'reason-btn':true,'selected': staffNo===u}"
|
@click="toggleUser(u)" v-text="u"></button>
|
</view>
|
</view>
|
</view>
|
|
<!-- 底部按钮 -->
|
<view class="bottom-section">
|
<button class="save-btn" @click="save">保存并生效</button>
|
<button class="cancel-btn" @click="cancel">取消</button>
|
</view>
|
|
<!-- 下面弹窗逻辑保留(如不需要可再删除) -->
|
<view v-if="isShow" class="overlay">
|
<view class="popup">
|
<view class="bottom-section1">
|
<button class="clean-btn" type="warn" @click="deleteBarcode">关闭</button>
|
</view>
|
<view class="reason-section">
|
<text>报工人:</text>
|
<view class="reason-buttons">
|
<button v-for="(u,index) in users" :key="index"
|
:class="{'reason-btn':true,'selected': user===u}"
|
@click="toggleUser(u)" v-text="u"></button>
|
</view>
|
</view>
|
</view>
|
</view>
|
|
<view v-if="barcodeIsShow" class="overlay">
|
<view class="popup">
|
<uni-table ref="table" border stripe emptyText="暂无更多数据" class="table1">
|
<uni-tr>
|
<uni-th align="center" style="font-size:40px;">生成时间</uni-th>
|
<uni-th align="center" style="width:39%;font-size:40px;">条码</uni-th>
|
<uni-th align="center" style="font-size:40px;">报工人</uni-th>
|
<uni-th align="center" style="font-size:40px;">报工数量</uni-th>
|
</uni-tr>
|
<uni-tr v-for="(item,index) in reportingList" :key="index">
|
<uni-td align="center">
|
<input type="text" v-model="item.bgDate" style="width:26vh;" />
|
</uni-td>
|
<uni-td align="center">
|
<input v-model="item.itemNoCade" style="width:40vh;" />
|
</uni-td>
|
<uni-td align="center">
|
<input v-model="item.staffName" />
|
</uni-td>
|
<uni-td align="center">
|
<input v-model="item.okQty" />
|
</uni-td>
|
</uni-tr>
|
</uni-table>
|
<view>
|
<button class="clean-btn" type="warn" @click="barcodeIsShow=false">关闭</button>
|
</view>
|
</view>
|
</view>
|
</view>
|
</view>
|
</template>
|
|
<script>
|
import { printTemplate3 } from "../utils/printTemplate";
|
|
export default {
|
props: {
|
orderNo: String,
|
orderId: Number,
|
machineNo: String
|
},
|
data() {
|
return {
|
currentUser: '',
|
barcodeAmount: '',
|
users: [],
|
userForm: [],
|
staff: [],
|
user: {},
|
productionCount: 0,
|
printedCount: 0,
|
defectiveCount: 0,
|
order: {},
|
icount: 1,
|
bqty: 0,
|
sQuantity: 0,
|
kgQty: 0,
|
initialValue: 0,
|
qqty: 0,
|
ngStaid: 0,
|
bufferData: '',
|
dataToPrint: [],
|
isLoading: false,
|
but: false,
|
DAA003List: [],
|
lineList: [],
|
isShow: false,
|
barcodeIsShow: false,
|
barcodeList: [],
|
staffNo: '',
|
printStr: '',
|
printMac: '',
|
bluetoothSocket: {},
|
device: '',
|
uuid: '',
|
printNum: 1,
|
reportingList: [],
|
printLoading: false,
|
customAmount: '',
|
isGeneratingBarcode: false,
|
lastGenerateTime: 0,
|
generateRequestId: null,
|
nowTimeTimer: null,
|
nowTime: ''
|
};
|
},
|
computed: {
|
calculatedCurrentCount() {
|
const production = this.productionCount || 0;
|
const initial = this.initialValue || 0;
|
return production - initial;
|
},
|
calculatedTotalProduction() {
|
const kgQty = this.kgQty || 0;
|
const currentCount = this.calculatedCurrentCount;
|
return kgQty + currentCount;
|
},
|
calculatedDefectiveCount() {
|
const totalProduction = this.calculatedTotalProduction;
|
const goodCount = this.sQuantity || 0;
|
return totalProduction - goodCount;
|
},
|
planQtyDisplay() {
|
// 计划生产数字段不确定时兜底
|
return this.order.planQty || this.order.planQuantity || this.order.daa007 || this.order.daa010 || 0;
|
}
|
},
|
created() {
|
this.initializeData();
|
this.fetchData(true);
|
this.init();
|
this.getXS0101();
|
this.updateNowTime();
|
this.nowTimeTimer = setInterval(this.updateNowTime, 60000);
|
},
|
beforeDestroy() {
|
if (this.nowTimeTimer) clearInterval(this.nowTimeTimer);
|
},
|
methods: {
|
updateNowTime() {
|
const d = new Date();
|
const pad = n => (n < 10 ? '0' + n : n);
|
this.nowTime = `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`;
|
},
|
initializeData() {
|
this.productionCount = 0;
|
this.printedCount = 0;
|
this.defectiveCount = 0;
|
this.icount = 1;
|
this.bqty = 0;
|
this.sQuantity = 0;
|
this.kgQty = 0;
|
this.initialValue = 0;
|
this.qqty = 0;
|
this.isGeneratingBarcode = false;
|
this.lastGenerateTime = 0;
|
this.generateRequestId = null;
|
},
|
resetGenerateState() {
|
this.isGeneratingBarcode = false;
|
this.generateRequestId = null;
|
this.lastGenerateTime = 0;
|
this.$showMessage("已重置条码生成状态");
|
},
|
refresh() {
|
this.$sendPostRequest({
|
url: "http://192.168.0.94:9095/Numerical/RefreshDev",
|
data: { machineNo: this.order.machineNo },
|
contentType: "application/json"
|
}).then(res1 => {
|
if (res1.code == 200) {
|
this.fetchData(true);
|
} else {
|
this.$showMessage("同步失败");
|
}
|
});
|
},
|
onDaa003Change(event) {
|
let orde = this.lineList[this.DAA003List.indexOf(event)];
|
this.orderId = orde.id;
|
this.orderNo = orde.daa001;
|
uni.setStorageSync('machine', this.machineNo);
|
uni.setStorageSync('orderId', this.orderId);
|
uni.setStorageSync('orderNo', this.orderNo);
|
this.fetchData(false);
|
},
|
fetchData(flag) {
|
if (!this.orderId && !this.orderNo) return;
|
this.getOrderById();
|
this.getWomdaaPrintById();
|
if (flag) {
|
this.$post({
|
url: "/Womdaa/GetWomdaasByShow",
|
data: { machineNo: this.machineNo }
|
}).then(res => {
|
this.lineList = res.data.tbBillList;
|
this.DAA003List = res.data.tbBillList.map(item => item.daa003);
|
});
|
}
|
},
|
toggleUser(user) {
|
if (!user) return;
|
this.user = this.user === user ? null : user;
|
this.staffNo = this.user;
|
},
|
confirmCustomAmount() {
|
if (!this.customAmount || isNaN(Number(this.customAmount))) {
|
this.$showMessage('请输入有效的数量');
|
return;
|
}
|
let amount = Number(this.customAmount);
|
this.$post({
|
url: "/MesInvItemBarcodes/AddBFToBarcodes",
|
data: {
|
orderNo: this.orderNo,
|
orderId: this.orderId,
|
bf: amount
|
}
|
}).then(res => {
|
if (res.status == 1) {
|
this.$showMessage(res.message);
|
return;
|
}
|
this.$showMessage('报废数量填写成功');
|
this.fetchData(true);
|
this.customAmount = '';
|
}).catch(() => {
|
this.$showMessage('报废数量填写失败,请重试');
|
});
|
},
|
save() {
|
if (!this.staffNo) {
|
this.$showMessage('请选择报工人');
|
return;
|
}
|
uni.showToast({ title: '保存成功', icon: 'success' });
|
},
|
cancel() {
|
uni.showToast({ title: '取消操作', icon: 'none' });
|
},
|
getOrderById() {
|
this.$post({
|
url: "/Womdaa/GetWomdaaById",
|
data: { orderId: this.orderId, orderNo: this.orderNo }
|
}).then(res => {
|
this.order = res.data.tbBillList;
|
this.printedCount = res.data.tbBillList.bgqty;
|
this.defectiveCount = res.data.tbBillList.blQty;
|
this.productionCount = this.order.todayOutput || 0;
|
this.defectiveCount = this.defectiveCount || 0;
|
this.printedCount = this.printedCount || 0;
|
});
|
},
|
getXS0101() {
|
this.$post({ url: "/MesStaff/GetAllXS0101" }).then(res => {
|
this.staff = res.data.tbBillList;
|
this.users = this.staff.map(s => s.staffNo + ":" + s.staffName);
|
});
|
},
|
getWomdaaPrintById() {
|
this.$post({
|
url: "/Womdaa/GetWomdaaPrintById",
|
data: { orderId: this.orderId }
|
}).then(res => {
|
if (!res || !res.data || !res.data.tbBillList) return;
|
const data = res.data.tbBillList;
|
this.bqty = data.bqty;
|
this.icount = 1;
|
this.sQuantity = data.sQuantity || 0;
|
this.initialValue = data.initialValue || 0;
|
this.kgQty = data.kgQty || 0;
|
this.barcodeAmount = data.qqty || 0;
|
if (this.bqty === 0) this.Completed();
|
}).catch(() => { });
|
},
|
Completed() {
|
this.$post({
|
url: "/MesOrderSta/Completed",
|
data: { orderId: this.orderId, orderNo: this.orderNo }
|
});
|
},
|
init() {
|
try {
|
const androidVersion = this.getAndroidVersion();
|
if (androidVersion >= 12) this.initForAndroid12Plus(); else this.initForAndroidLegacy();
|
} catch (e) { console.error(e); }
|
},
|
getAndroidVersion() {
|
try {
|
var Build = plus.android.importClass("android.os.Build");
|
return Build.VERSION.SDK_INT;
|
} catch { return 30; }
|
},
|
initForAndroid12Plus() {
|
try {
|
var main = plus.android.runtimeMainActivity();
|
var BluetoothManager = plus.android.importClass("android.bluetooth.BluetoothManager");
|
var Context = plus.android.importClass("android.content.Context");
|
var UUID = plus.android.importClass("java.util.UUID");
|
this.uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
|
var bluetoothManager = main.getSystemService(Context.BLUETOOTH_SERVICE);
|
var bluetoothAdapter = bluetoothManager.getAdapter();
|
if (bluetoothAdapter && bluetoothAdapter.isDiscovering()) bluetoothAdapter.cancelDiscovery();
|
this.printMac = uni.getStorageSync('printMac');
|
var address_mac = this.printMac ? this.printMac : "DC:1D:30:91:06:52";
|
if (bluetoothAdapter) {
|
this.device = bluetoothAdapter.getRemoteDevice(address_mac);
|
plus.android.importClass(this.device);
|
}
|
} catch (e) {
|
this.initForAndroidLegacy();
|
}
|
},
|
initForAndroidLegacy() {
|
try {
|
var BluetoothAdapter = plus.android.importClass("android.bluetooth.BluetoothAdapter");
|
var UUID = plus.android.importClass("java.util.UUID");
|
this.uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
|
var BAdapter = BluetoothAdapter.getDefaultAdapter();
|
if (BAdapter) BAdapter.cancelDiscovery();
|
this.printMac = uni.getStorageSync('printMac');
|
var address_mac = this.printMac ? this.printMac : "DC:1D:30:91:06:52";
|
if (BAdapter) {
|
this.device = BAdapter.getRemoteDevice(address_mac);
|
plus.android.importClass(this.device);
|
this.bluetoothSocket = this.device.createInsecureRfcommSocketToServiceRecord(this.uuid);
|
plus.android.importClass(this.bluetoothSocket);
|
}
|
} catch (e) { }
|
},
|
deleteBarcode() {
|
this.isShow = false;
|
this.isGeneratingBarcode = false;
|
this.generateRequestId = null;
|
this.bufferData = '';
|
this.dataToPrint = [];
|
this.staffNo = null;
|
this.user = '';
|
this.barcodeAmount = '';
|
this.icount = 1;
|
this.staff = null;
|
}
|
}
|
};
|
</script>
|
|
<style scoped>
|
.page {
|
padding: 2vh;
|
display: flex;
|
flex-direction: column;
|
justify-content: space-between;
|
box-sizing: border-box;
|
}
|
|
.report-table-wrapper {
|
margin-bottom: 20px;
|
}
|
|
.report-title {
|
font-size: 26px;
|
font-weight: 600;
|
text-align: center;
|
margin-bottom: 10px;
|
}
|
|
.report-table {
|
width: 100%;
|
border-collapse: collapse;
|
font-size: 14px;
|
background: #fff;
|
}
|
|
.report-table th, .report-table td {
|
border: 1px solid #555;
|
padding: 6px;
|
text-align: center;
|
white-space: nowrap;
|
}
|
|
.refresh-btn {
|
float: right;
|
background-color: #00A2E9;
|
color: #fff;
|
border: none;
|
font-size: 32px;
|
border-radius: 15px;
|
margin-top: -32px;
|
margin-bottom: 49px;
|
padding: 0 25px;
|
}
|
|
.status-section {
|
display: flex;
|
flex-direction: column;
|
margin-bottom: 3vh;
|
padding-top: 14px;
|
}
|
|
.status-row {
|
display: flex;
|
justify-content: flex-start;
|
align-items: center;
|
margin-bottom: 20px;
|
background-color: #f9f9f9;
|
padding: 15px;
|
border-radius: 8px;
|
box-shadow: 0 1px 3px rgba(0,0,0,.05);
|
}
|
|
.status-box {
|
display: flex;
|
align-items: center;
|
padding: 0 10px;
|
}
|
|
.result-box {
|
background-color: #f0f8ff;
|
padding: 5px 15px;
|
border-radius: 6px;
|
border-left: 4px solid #007aff;
|
}
|
|
input.highlight {
|
width: 10vw;
|
font-weight: 700;
|
border: none;
|
background-color: #fff;
|
text-align: center;
|
font-size: 1.5vw;
|
padding: 8px;
|
border-radius: 4px;
|
box-shadow: inset 0 1px 3px rgba(0,0,0,.1);
|
}
|
|
.operator-box {
|
display: flex;
|
justify-content: center;
|
align-items: center;
|
font-size: 36px;
|
font-weight: bold;
|
margin: 0 15px;
|
color: #007aff;
|
width: 40px;
|
height: 40px;
|
}
|
|
.header-container {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
margin-bottom: 20px;
|
padding: 10px 15px;
|
background-color: #f2f2f2;
|
border-radius: 10px;
|
box-shadow: 0 2px 5px rgba(0,0,0,.1);
|
}
|
|
.header-title {
|
font-size: 24px;
|
font-weight: bold;
|
color: #333;
|
}
|
|
.version-info-top {
|
font-size: 13px;
|
color: #666;
|
margin-right: 10px;
|
}
|
|
.inp {
|
width: 65%;
|
padding: 1vh;
|
margin-top: -13px;
|
font-size: 1.3vw;
|
border: 1px solid #808080;
|
border-radius: .5vw;
|
box-sizing: border-box;
|
}
|
|
.form-row {
|
display: flex;
|
justify-content: space-between;
|
margin-bottom: 3vh;
|
flex-wrap: nowrap;
|
}
|
|
.form-item {
|
width: 30%;
|
}
|
|
.print-section {
|
padding: 1vh;
|
border-radius: 1vw;
|
margin-bottom: 2vh;
|
display: flex;
|
flex-wrap: wrap;
|
align-items: center;
|
}
|
|
.barcode-info {
|
display: flex;
|
align-items: flex-start;
|
gap: 2vw;
|
}
|
|
.details-btn {
|
display: inline-block;
|
padding: 1.5vh;
|
background-color: #00a2e9;
|
color: #fff;
|
font-size: 1.5vw;
|
border: none;
|
cursor: pointer;
|
border-radius: 1vw;
|
}
|
|
.reason-section {
|
margin-bottom: 3vh;
|
}
|
|
.reason-buttons {
|
display: grid;
|
grid-template-columns: repeat(5,1fr);
|
gap: 1vw;
|
}
|
|
.reason-btn {
|
padding: .5vh;
|
background-color: #808080;
|
color: #fff;
|
font-size: 1.3vw;
|
border: none;
|
border-radius: .5vw;
|
cursor: pointer;
|
}
|
|
.reason-btn.selected {
|
background-color: #FFD700;
|
color: #000;
|
}
|
|
.bottom-section {
|
display: flex;
|
justify-content: space-between;
|
margin-top: 2vh;
|
}
|
|
.save-btn, .cancel-btn {
|
width: 48%;
|
padding: 1.5vh;
|
background-color: #00A2E9;
|
color: #fff;
|
font-size: 1.5vw;
|
border: none;
|
text-align: center;
|
cursor: pointer;
|
border-radius: .5vw;
|
}
|
|
.overlay {
|
position: fixed;
|
top: 0;
|
left: 0;
|
width: 100%;
|
height: 100%;
|
background-color: rgba(0,0,0,.5);
|
display: flex;
|
justify-content: center;
|
align-items: center;
|
}
|
|
.popup {
|
background-color: #fff;
|
padding: 2vh;
|
border: 1px solid #ccc;
|
box-shadow: 0 0 10px rgba(0,0,0,.1);
|
width: 70vw;
|
height: 70vh;
|
font-size: 1.6vw;
|
max-height: 80vh;
|
overflow-y: auto;
|
border-radius: 8px;
|
}
|
|
.clean-btn {
|
width: 48%;
|
padding: 1.5vh;
|
color: #fff;
|
font-size: 1.5vw;
|
border: none;
|
text-align: center;
|
cursor: pointer;
|
border-radius: .5vw;
|
background-color: #007aff;
|
}
|
|
.table1 {
|
width: 100%;
|
border-spacing: 3px;
|
}
|
|
.reset-btn {
|
background-color: #ff6b6b;
|
color: #fff;
|
border: none;
|
font-size: 18px;
|
border-radius: 6px;
|
padding: 8px 15px;
|
margin-left: 10px;
|
}
|
</style>
|