<template>
|
<view class="page">
|
<!-- 顶部显示当前系统采集生产数,打码报工数和不良数 -->
|
<view class="status-section">
|
<!-- 整体标题和刷新按钮 -->
|
<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 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="status-box">
|
<text>开工时工单已报工数:</text>
|
<input v-model="kgQty" 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="status-row">
|
<view class="status-box">
|
<text>手报不良数:</text>
|
<input v-model="defectiveCount" class="highlight" disabled />
|
</view>
|
<view class="status-box">
|
<text>未打印条码数:</text>
|
<input v-model="bqty" class="highlight" disabled />
|
</view>
|
</view>
|
<!-- 第一行 -->
|
<!-- <view class="status-row">
|
<view class="status-box result-box">
|
<text>当前采集数:</text>
|
<input v-model="calculatedCurrentCount" class="highlight" disabled />
|
</view>
|
<view class="operator-box">=</view>
|
<view class="status-box">
|
<text>机台面板数:</text>
|
<input v-model="productionCount" class="highlight" disabled />
|
</view>
|
<view class="operator-box">-</view>
|
<view class="status-box">
|
<text>初始值:</text>
|
<input v-model="initialValue" class="highlight" disabled />
|
</view>
|
</view> -->
|
<!-- 第二行 -->
|
<!-- <view class="status-row">
|
<view class="status-box result-box">
|
<text>已生产数:</text>
|
<input v-model="calculatedTotalProduction" class="highlight" disabled />
|
</view>
|
<view class="operator-box">=</view>
|
<view class="status-box">
|
<text>开工时工单已报工数:</text>
|
<input v-model="kgQty" class="highlight" disabled />
|
</view>
|
<view class="operator-box">+</view>
|
<view class="status-box">
|
<text>当前采集数:</text>
|
<input v-model="calculatedCurrentCount" class="highlight" disabled />
|
</view>
|
</view> -->
|
<!-- 第三行 -->
|
<!-- <view class="status-row">
|
<view class="status-box result-box">
|
<text>不良数:</text>
|
<input v-model="calculatedDefectiveCount" class="highlight" disabled />
|
</view>
|
<view class="operator-box">=</view>
|
<view class="status-box">
|
<text>已生产数:</text>
|
<input v-model="calculatedTotalProduction" class="highlight" disabled />
|
</view>
|
<view class="operator-box">-</view>
|
<view class="status-box">
|
<text>良品数:</text>
|
<input v-model="sQuantity" class="highlight" disabled />
|
</view>
|
<view class="status-box standalone-box">
|
<text>已打印条码数:</text>
|
<input v-model="sQuantity" class="highlight" disabled />
|
</view>
|
</view> -->
|
|
<view>
|
<view style="display: flex; flex-direction: column; flex-wrap: nowrap; align-content: flex-start;">
|
<view class="form-row">
|
<view class="form-item">
|
<label>产品编码:</label>
|
<input class="inp" type="text" v-model="order.daa002" disabled="true" />
|
</view>
|
<view class="form-item">
|
<label>产品名称:</label>
|
<!-- <input class="inp" type="text" v-model="order.daa003" disabled="true" /> -->
|
<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="true" />
|
</view>
|
</view>
|
<view class="form-row">
|
<view class="form-item">
|
<label>图 号:</label>
|
<input class="inp" type="text" v-model="order.engineeringNo" disabled="true" />
|
</view>
|
<view class="form-item">
|
<label>材 质:</label>
|
<input class="inp" type="text" v-model="order.material" disabled="true" />
|
</view>
|
<view class="form-item">
|
<label>颜 色:</label>
|
<input class="inp" type="text" v-model="order.colorName" disabled="true" />
|
</view>
|
</view>
|
</view>
|
</view>
|
|
<!-- 条码打印部分 - 中部元素在一条线上 -->
|
<view class="print-section">
|
<view class="barcode-info">
|
<view class="user-select">
|
<text style="display: inline-block;float:left;margin-left: -11px;">打印条码张数:</text>
|
<input v-model="icount" class="inp"
|
style="width: 20%; height: 70px; border: 3px solid #808080; font-size: 40px; text-align: center; margin-top: 5px;" />
|
</view>
|
|
<text style="margin-left:-280px;">每张条码数量:</text>
|
<input class="inp"
|
style="width: 19%; height: 70px; border: 3px solid #808080; font-size: 40px; text-align: center; margin-top: 5px; margin-left: -38px;"
|
v-model="barcodeAmount" placeholder="条码数量(装箱数)" />
|
|
<view class="user-select">
|
<button class="print-btn" @click="showPrint" :disabled="isGeneratingBarcode || printLoading"
|
:style="(isGeneratingBarcode || printLoading) ? 'background-color: #ccc; cursor: not-allowed;' : ''">
|
{{ isGeneratingBarcode ? '生成中...' : (printLoading ? '打印中...' : '打印条码') }}
|
</button>
|
<button class="details-btn" @click="showBarcode">条码明细</button>
|
</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="(reason, index) in badReasons" :key="index"
|
:class="{'reason-btn': true, 'selected': selectedReasons.includes(reason)}"
|
@click="toggleReason(reason)" v-text="reason"></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="barcode-info">
|
<!-- <view class="user-select">
|
<text>已打印条码数:</text>
|
<input v-model="sQuantity" class="highlight" disabled />
|
</view>
|
<view class="user-select">
|
<text>未打印条码数:</text>
|
<input v-model="bqty" class="highlight" disabled />
|
</view> -->
|
|
<view class="user-select1">
|
<text style="float: left; display: inline-block;">打印条码张数:</text>
|
<input v-model="icount" class="inp5" disabled="true" />
|
</view>
|
<view class="user-select2">
|
<text style="float: left;">每张条码数量:</text>
|
<input class="inp6" disabled="true" v-model="barcodeAmount" placeholder="条码数量(装箱数)" />
|
</view>
|
|
<view class="form-row">
|
<!--<kk-printer defaultText="打印条码" class="print-btn" ref="kkprinter" :user="staffNo"
|
:bufferData="bufferData" @onPrint="onPrint" @onPrintSuccess="onPrintSuccess"
|
@onPrintFail="onPrintFail">
|
</kk-printer>-->
|
</view>
|
</view>
|
<view class="bottom-section1">
|
<!-- <button class="clean-btn" type="primary" @click="cleanUser">关闭</button> -->
|
<button class="clean-btn" type="warn" @click="deleteBarcode">取消打印</button>
|
<button class="print-btn"
|
style="width: 48%; padding: 1.5vh; color: white; font-size: 1.5vw; border: none; text-align: center; cursor: pointer; border-radius: 0.5vw;"
|
@click="printTest" :loading="printLoading" :disabled="printLoading || isGeneratingBarcode"
|
:style="(printLoading || isGeneratingBarcode) ? 'background-color: #ccc; cursor: not-allowed;' : ''">
|
{{ isGeneratingBarcode ? '生成中...' : (printLoading ? '打印中...' : '打印条码') }}
|
</button>
|
</view>
|
<view class="reason-section">
|
<text>报工人:</text>
|
<view class="reason-buttons">
|
<button v-for="(reason, index) in users" :key="index"
|
:class="{'reason-btn': true, 'selected': user === reason}" @click="toggleUser(reason)"
|
v-text="reason"></button>
|
</view>
|
</view>
|
</view>
|
</view>
|
|
<!-- 展示条码明细 -->
|
<view v-if="barcodeIsShow" class="overlay">
|
<view class="popup">
|
<!-- <view class="barcode-info"> -->
|
<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> -->
|
<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: {},
|
badReasons: [], // 不良原因
|
itemsNgname: [],
|
selectedReasons: [], // 存储选中的不良原因
|
productionCount: 0, // 当前系统采集生产数
|
printedCount: 0, // 当前已打码报工数
|
defectiveCount: 0, // 不良数
|
order: {},
|
icount: 1, // 默认为1,避免为0或null
|
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 // 当前生成请求的唯一ID
|
};
|
},
|
computed: {
|
// 计算当前采集数,确保不会出现NaN或undefined
|
calculatedCurrentCount() {
|
const production = this.productionCount || 0;
|
const initial = this.initialValue || 0;
|
return production - initial;
|
},
|
// 计算已生产总数
|
calculatedTotalProduction() {
|
const kgQty = this.kgQty || 0;
|
const currentCount = this.calculatedCurrentCount;
|
// 当开工时工单已报工数为0时,直接使用当前采集数的值
|
//return kgQty === 0 ? currentCount : kgQty + currentCount;
|
return kgQty + currentCount
|
},
|
// 计算不良数
|
calculatedDefectiveCount() {
|
const totalProduction = this.calculatedTotalProduction;
|
// const totalProduction = this.productionCount;
|
const goodCount = this.sQuantity || 0;
|
return totalProduction - goodCount;
|
}
|
},
|
components: {},
|
mounted() {
|
// this.fetchData(false); // Initial fetch
|
// this.timer = setInterval(this.fetchData, 180000); // Call fetchData every 5 minutes
|
},
|
created() {
|
// 初始化数据,确保所有数值型变量有默认值
|
this.initializeData();
|
this.fetchData(true);
|
this.init();
|
},
|
methods: {
|
// 初始化所有数值型变量,避免null或undefined
|
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;
|
console.log("已手动重置条码生成状态");
|
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("同步失败");
|
}
|
});
|
|
},
|
printTest() {
|
if (!this.staffNo) {
|
this.$showMessage("请选择报工人");
|
return;
|
}
|
|
try {
|
// 在调用onPrint前清空数据
|
// 这样可以确保每次打印都是从零开始
|
this.dataToPrint = [];
|
this.bufferData = '';
|
this.onPrint();
|
|
this.$showMessage('正在打印,请稍等!');
|
this.printLoading = true;
|
|
this.printNum = 1;
|
setTimeout(() => {
|
this.doPrint();
|
this.printLoading = false;
|
console.log("调用打印");
|
}, 2000);
|
} catch (e) {
|
this.onPrintFail();
|
console.log(e);
|
}
|
|
},
|
doPrint() { //printNum:打印次数
|
var mac_address = uni.getStorageSync('printMac');
|
console.log("打印机地址" + mac_address);
|
console.log('打印开始');
|
console.log("打印参数" + this.bufferData);
|
|
if (!mac_address) {
|
this.$showMessage('请选择蓝牙打印机');
|
this.printLoading = false;
|
return false;
|
}
|
|
// 检查Android版本并使用对应的打印方法
|
// const androidVersion = this.getAndroidVersion();
|
// console.log('Android版本:', androidVersion);
|
|
// if (androidVersion >= 12) {
|
// return this.doPrintForAndroid12Plus(mac_address);
|
// } else {
|
return this.doPrintForAndroidLegacy(mac_address);
|
// }
|
},
|
|
// Android 12+ 版本的蓝牙打印方法
|
doPrintForAndroid12Plus(mac_address) {
|
try {
|
console.log('使用Android 12+兼容的蓝牙打印方法');
|
|
// 检查蓝牙权限
|
if (!this.checkBluetoothPermissions()) {
|
this.$showMessage('蓝牙权限不足,请检查应用权限设置');
|
this.printLoading = false;
|
return false;
|
}
|
|
var main = plus.android.runtimeMainActivity();
|
var BluetoothManager = plus.android.importClass("android.bluetooth.BluetoothManager");
|
var Context = plus.android.importClass("android.content.Context");
|
|
// 获取BluetoothManager
|
var bluetoothManager = main.getSystemService(Context.BLUETOOTH_SERVICE);
|
var bluetoothAdapter = bluetoothManager.getAdapter();
|
|
if (!bluetoothAdapter) {
|
this.$showMessage('设备不支持蓝牙');
|
this.printLoading = false;
|
return false;
|
}
|
|
if (!bluetoothAdapter.isEnabled()) {
|
this.$showMessage('请先开启蓝牙');
|
this.printLoading = false;
|
return false;
|
}
|
|
// 获取配对设备
|
var pairedDevices = bluetoothAdapter.getBondedDevices();
|
var targetDevice = null;
|
|
// 查找目标设备
|
var iterator = pairedDevices.iterator();
|
while (iterator.hasNext()) {
|
var device = iterator.next();
|
if (device.getAddress().equals(mac_address)) {
|
targetDevice = device;
|
break;
|
}
|
}
|
|
if (!targetDevice) {
|
this.$showMessage('未找到配对的打印机设备');
|
this.printLoading = false;
|
return false;
|
}
|
|
// 创建蓝牙连接
|
var UUID = plus.android.importClass("java.util.UUID");
|
var uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
|
var bluetoothSocket = targetDevice.createRfcommSocketToServiceRecord(uuid);
|
|
// 连接设备
|
try {
|
bluetoothSocket.connect();
|
console.log('蓝牙连接成功');
|
|
// 发送打印数据
|
var outputStream = bluetoothSocket.getOutputStream();
|
var bytes = plus.android.invoke(this.bufferData, 'getBytes', 'gbk');
|
outputStream.write(bytes);
|
outputStream.flush();
|
|
// 关闭连接
|
outputStream.close();
|
bluetoothSocket.close();
|
|
console.log("打印成功");
|
this.cleanUser();
|
this.onPrintSuccess();
|
return true;
|
|
} catch (connectError) {
|
console.error('蓝牙连接失败:', connectError);
|
|
// 尝试fallback方法
|
try {
|
bluetoothSocket.close();
|
// 使用反射获取hidden方法
|
var createRfcommSocket = targetDevice.getClass().getMethod("createRfcommSocket",
|
plus.android.importClass("java.lang.Integer").TYPE);
|
bluetoothSocket = createRfcommSocket.invoke(targetDevice, 1);
|
|
bluetoothSocket.connect();
|
console.log('使用fallback方法连接成功');
|
|
var outputStream = bluetoothSocket.getOutputStream();
|
var bytes = plus.android.invoke(this.bufferData, 'getBytes', 'gbk');
|
outputStream.write(bytes);
|
outputStream.flush();
|
|
outputStream.close();
|
bluetoothSocket.close();
|
|
this.cleanUser();
|
this.onPrintSuccess();
|
return true;
|
|
} catch (fallbackError) {
|
console.error('Fallback方法也失败:', fallbackError);
|
this.$showMessage('蓝牙连接失败,请检查打印机状态');
|
this.printLoading = false;
|
return false;
|
}
|
}
|
|
} catch (error) {
|
console.error('Android 12+ 蓝牙打印错误:', error);
|
this.$showMessage('打印失败: ' + error.message);
|
this.printLoading = false;
|
return false;
|
}
|
},
|
|
// Android 11及以下版本的蓝牙打印方法(保持原有逻辑)
|
doPrintForAndroidLegacy(mac_address) {
|
try {
|
console.log('使用传统蓝牙打印方法');
|
|
var device = null,
|
BAdapter = null,
|
BluetoothAdapter = null,
|
uuid = null,
|
main = null,
|
bluetoothSocket = null;
|
|
main = plus.android.runtimeMainActivity();
|
BluetoothAdapter = plus.android.importClass("android.bluetooth.BluetoothAdapter");
|
let UUID = plus.android.importClass("java.util.UUID");
|
uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
|
BAdapter = BluetoothAdapter.getDefaultAdapter();
|
|
if (!BAdapter) {
|
this.$showMessage('设备不支持蓝牙');
|
this.printLoading = false;
|
return false;
|
}
|
|
device = BAdapter.getRemoteDevice(mac_address);
|
plus.android.importClass(device);
|
bluetoothSocket = device.createInsecureRfcommSocketToServiceRecord(uuid);
|
plus.android.importClass(bluetoothSocket);
|
|
if (!bluetoothSocket.isConnected()) {
|
console.log('检测到设备未连接,尝试连接....');
|
bluetoothSocket.connect();
|
}
|
|
console.log('设备已连接');
|
if (bluetoothSocket.isConnected()) {
|
var outputStream = bluetoothSocket.getOutputStream();
|
plus.android.importClass(outputStream);
|
var bytes = plus.android.invoke(this.bufferData, 'getBytes', 'gbk');
|
outputStream.write(bytes);
|
outputStream.flush();
|
device = null //这里关键
|
bluetoothSocket.close(); //必须关闭蓝牙连接否则意外断开的话打印错误
|
console.log("打印机连接状态:111");
|
this.cleanUser();
|
this.onPrintSuccess();
|
return true;
|
} else {
|
console.log("打印机连接状态:222");
|
this.printLoading = false;
|
return false;
|
}
|
} catch (error) {
|
console.error('传统蓝牙打印错误:', error);
|
this.$showMessage('打印失败: ' + error.message);
|
this.printLoading = false;
|
return false;
|
}
|
},
|
|
// 获取Android版本号
|
getAndroidVersion() {
|
try {
|
var Build = plus.android.importClass("android.os.Build");
|
return Build.VERSION.SDK_INT;
|
} catch (error) {
|
console.error('获取Android版本失败:', error);
|
return 30; // 默认返回Android 11的API Level
|
}
|
},
|
|
// 检查蓝牙权限(Android 12+需要)
|
checkBluetoothPermissions() {
|
try {
|
const androidVersion = this.getAndroidVersion();
|
|
// Android 12以下版本不需要新权限
|
if (androidVersion < 31) { // Android 12 = API 31
|
return true;
|
}
|
|
var main = plus.android.runtimeMainActivity();
|
var PackageManager = plus.android.importClass("android.content.pm.PackageManager");
|
var ContextCompat = plus.android.importClass("androidx.core.content.ContextCompat");
|
|
// Android 12+ 需要的权限
|
var permissions = [
|
"android.permission.BLUETOOTH_CONNECT",
|
"android.permission.BLUETOOTH_SCAN"
|
];
|
|
var missingPermissions = [];
|
for (var i = 0; i < permissions.length; i++) {
|
var permission = permissions[i];
|
var granted = ContextCompat.checkSelfPermission(main, permission);
|
if (granted !== PackageManager.PERMISSION_GRANTED) {
|
console.log('权限未授予:', permission);
|
missingPermissions.push(permission);
|
}
|
}
|
|
if (missingPermissions.length > 0) {
|
// 尝试请求权限
|
this.requestBluetoothPermissions(missingPermissions);
|
return false;
|
}
|
|
return true;
|
} catch (error) {
|
console.error('权限检查失败:', error);
|
// 如果检查失败,假设权限已授予(可能是老版本Android)
|
return true;
|
}
|
},
|
|
// 请求蓝牙权限
|
requestBluetoothPermissions(permissions) {
|
try {
|
var main = plus.android.runtimeMainActivity();
|
var ActivityCompat = plus.android.importClass("androidx.core.app.ActivityCompat");
|
|
console.log('请求蓝牙权限:', permissions);
|
|
// 将JavaScript数组转换为Java数组
|
var javaPermissions = plus.android.newObject("java.lang.String", permissions.length);
|
for (var i = 0; i < permissions.length; i++) {
|
javaPermissions[i] = permissions[i];
|
}
|
|
// 请求权限
|
ActivityCompat.requestPermissions(main, javaPermissions, 1001);
|
|
// 显示提示信息
|
this.$showMessage('正在请求蓝牙权限,请在系统弹窗中允许权限后重试');
|
|
} catch (error) {
|
console.error('请求权限失败:', error);
|
this.$showMessage('无法请求蓝牙权限,请手动在设置中开启应用的蓝牙权限');
|
}
|
},
|
init() {
|
console.log("设置蓝牙");
|
try {
|
// 检查Android版本并使用对应的初始化方法
|
const androidVersion = this.getAndroidVersion();
|
|
if (androidVersion >= 12) {
|
this.initForAndroid12Plus();
|
} else {
|
this.initForAndroidLegacy();
|
}
|
} catch (err) {
|
console.error("蓝牙初始化异常!", err);
|
}
|
},
|
|
// Android 12+ 版本的蓝牙初始化
|
initForAndroid12Plus() {
|
try {
|
console.log("使用Android 12+兼容的蓝牙初始化");
|
|
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");
|
|
// 获取BluetoothManager和Adapter
|
var bluetoothManager = main.getSystemService(Context.BLUETOOTH_SERVICE);
|
var bluetoothAdapter = bluetoothManager.getAdapter();
|
|
if (bluetoothAdapter && bluetoothAdapter.isDiscovering()) {
|
bluetoothAdapter.cancelDiscovery(); // 停止扫描
|
}
|
|
let printMac1 = uni.getStorageSync('printMac');
|
this.printMac = printMac1;
|
console.log("打印机地址" + this.printMac);
|
|
var address_mac = this.printMac ? this.printMac : "DC:1D:30:91:06:52";
|
console.log("status:" + address_mac);
|
|
if (bluetoothAdapter) {
|
this.device = bluetoothAdapter.getRemoteDevice(address_mac);
|
plus.android.importClass(this.device);
|
console.log("Android 12+ 蓝牙初始化成功");
|
}
|
|
} catch (err) {
|
console.error("Android 12+ 蓝牙初始化失败:", err);
|
// 如果失败,尝试使用传统方法
|
this.initForAndroidLegacy();
|
}
|
},
|
|
// Android 11及以下版本的蓝牙初始化(保持原有逻辑)
|
initForAndroidLegacy() {
|
try {
|
console.log("使用传统蓝牙初始化方法");
|
|
var main = plus.android.runtimeMainActivity();
|
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(); // 停止扫描
|
}
|
|
let printMac1 = uni.getStorageSync('printMac');
|
this.printMac = printMac1;
|
console.log("打印机地址" + this.printMac);
|
|
var address_mac = this.printMac ? this.printMac : "DC:1D:30:91:06:52";
|
console.log("status:" + address_mac);
|
|
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);
|
console.log("传统蓝牙初始化成功");
|
}
|
|
} catch (err) {
|
console.error("传统蓝牙初始化失败:", err);
|
}
|
},
|
|
onDaa003Change(event) {
|
|
let orde = this.lineList[this.DAA003List.indexOf(event)];
|
|
this.orderId = orde.id;
|
this.orderNo = orde.daa001;
|
|
//切换为新的id
|
uni.setStorageSync('machine', this.machineNo);
|
uni.setStorageSync('orderId', this.orderId);
|
uni.setStorageSync('orderNo', this.orderNo);
|
uni.setStorageSync('engineeringNo', this.order.engineeringNo);
|
|
this.fetchData(false);
|
},
|
fetchData(flag) {
|
// let machine = uni.getStorageSync('machine');
|
// let orderId = uni.getStorageSync('orderId');
|
// let orderNo = uni.getStorageSync('orderNo');
|
|
// if (orderId) {
|
// this.orderId = orderId;
|
// } else {
|
// if (!this.orderId) {
|
// this.orderId = uni.getStorageSync('id');
|
// }
|
|
// }
|
|
// if (orderNo) {
|
// this.orderNo = orderNo;
|
// } else {
|
// if (!this.orderNo) {
|
// this.orderNo = uni.getStorageSync('daa001');
|
// }
|
// }
|
|
// if (machine) {
|
// this.machineNo = machine;
|
// } else {
|
// if (!this.machineNo) {
|
// this.machineNo = uni.getStorageSync('machineNo');
|
// }
|
// }
|
|
if (!this.orderId && !this.orderNo) {
|
return;
|
}
|
|
this.getOrderById();
|
this.getMesItemsNgname();
|
|
this.getWomdaaPrintById();
|
this.findByOrderId();
|
|
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);
|
})
|
}
|
|
},
|
formatDate(date) {
|
if (!date) return '';
|
|
try {
|
let year = date.getFullYear(); // 获取年份
|
let month = String(date.getMonth() + 1).padStart(2, '0'); // 获取月份并补零
|
let day = String(date.getDate()).padStart(2, '0'); // 获取日期并补零
|
return `${year}-${month}-${day}`; // 返回格式化后的字符串
|
} catch (error) {
|
console.error("日期格式化错误:", error);
|
return '';
|
}
|
},
|
// 切换选中的不良原因
|
toggleReason(reason) {
|
if (!reason) return;
|
|
if (this.selectedReasons.includes(reason)) {
|
this.selectedReasons = this.selectedReasons.filter(r => r !== reason);
|
} else {
|
this.selectedReasons.push(reason);
|
}
|
},
|
toggleUser(user) {
|
if (!user) return;
|
|
this.user = this.user === user ? null : user;
|
this.staffNo = user;
|
},
|
showPrint() {
|
// 防重复点击检查 - 生成中或打印中都不允许
|
if (this.isGeneratingBarcode) {
|
this.$showMessage('正在生成条码,请稍等...');
|
return;
|
}
|
|
if (this.printLoading) {
|
this.$showMessage('正在打印条码,请稍等...');
|
return;
|
}
|
|
// 防抖检查:2秒内不允许重复操作
|
const currentTime = Date.now();
|
if (currentTime - this.lastGenerateTime < 2000) {
|
this.$showMessage('操作过于频繁,请稍等再试');
|
return;
|
}
|
|
if (this.icount > 6) {
|
this.$showMessage('条码数量不能超过6张');
|
return;
|
}
|
|
this.isShow = true;
|
|
//this.printBarcode();
|
this.getXS0101();
|
|
this.user = "";
|
|
this.staffNo = null;
|
},
|
showBarcode() {
|
|
|
this.$post({
|
url: "/MesStaff/GetMesReportingList",
|
data: {
|
orderNo: this.orderNo,
|
}
|
}).then(res => {
|
this.reportingList = res.data.tbBillList;
|
this.barcodeIsShow = true;
|
});
|
},
|
// 打印条码报工
|
printBarcode() {
|
// 防重复请求检查
|
if (this.isGeneratingBarcode) {
|
this.$showMessage('正在生成条码,请稍等...');
|
return;
|
}
|
|
if (!this.barcodeAmount) {
|
this.isShow = false;
|
this.$showMessage('请输入条码数量');
|
return;
|
}
|
|
if (this.bqty == 0) {
|
this.isShow = false;
|
this.$showMessage('可打印数量为0');
|
return;
|
}
|
|
if (this.bqty < this.barcodeAmount) {
|
this.isShow = false;
|
this.$showMessage('打印数量不能大于可打印数量');
|
return;
|
}
|
|
if (this.icount * this.barcodeAmount > this.bqty) {
|
this.isShow = false;
|
this.$showMessage('打印总数超过可打印总数');
|
return;
|
}
|
|
// 设置生成状态锁定
|
this.isGeneratingBarcode = true;
|
this.lastGenerateTime = Date.now();
|
|
// 生成唯一请求ID,用于防重
|
this.generateRequestId = `${this.orderNo}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
console.log('开始生成条码,请求ID:', this.generateRequestId);
|
|
// 添加超时机制:15秒后自动释放锁定
|
const timeoutId = setTimeout(() => {
|
if (this.isGeneratingBarcode) {
|
console.log('条码生成超时,释放锁定');
|
this.isGeneratingBarcode = false;
|
this.$showMessage('生成条码超时,请重试');
|
}
|
}, 15000);
|
|
this.$post({
|
url: "/MesInvItemBarcodes/AddItemToBarcodes",
|
data: {
|
printQty: this.barcodeAmount,
|
orderNo: this.orderNo,
|
orderId: this.orderId,
|
user: this.user,
|
count: this.icount,
|
requestId: this.generateRequestId // 传递请求ID到后端用于防重
|
},
|
showLoading: true,
|
showLoadingTitle: "正在生成条码..."
|
}).then(res => {
|
// 清除超时定时器
|
clearTimeout(timeoutId);
|
|
// 注意:这里不立即释放 isGeneratingBarcode,要等到打印完成才释放
|
// this.isGeneratingBarcode = false; // 移除这行,在 cleanUser() 中重置
|
|
if (res.status == 1) {
|
this.$showMessage(res.message);
|
this.isShow = false;
|
// 如果生成失败,重置状态
|
this.isGeneratingBarcode = false;
|
this.generateRequestId = null;
|
return;
|
}
|
this.dataToPrint = res.data.tbBillList;
|
// this.getXS0101();
|
|
let printCommands = [];
|
|
console.log("接口返回的条数" + this.dataToPrint.length);
|
|
let user = this.staffNo;
|
|
for (let i = 0; i < this.dataToPrint.length; i++) {
|
let _printData = {
|
strp1: this.dataToPrint[i].out12,
|
strp2: this.dataToPrint[i].out2,
|
strp3: this.dataToPrint[i].out6,
|
strp4: this.dataToPrint[i].out1,
|
strp5: this.dataToPrint[i].out11,
|
strp6: this.dataToPrint[i].out8,
|
strp7: this.dataToPrint[i].out9,
|
strp8: this.dataToPrint[i].out12,
|
strp9: this.dataToPrint[i].out7,
|
strp10: user,
|
}
|
let printCmd = printTemplate3(_printData);
|
printCommands.push(printCmd);
|
}
|
this.bufferData = printCommands.join('\n');
|
|
console.log('条码生成成功,请求ID:', this.generateRequestId);
|
}).catch(error => {
|
// 网络错误时也要释放锁定
|
clearTimeout(timeoutId);
|
this.isGeneratingBarcode = false;
|
this.generateRequestId = null;
|
|
console.error('条码生成失败:', error);
|
this.$showMessage('网络异常,条码生成失败,请重试');
|
});
|
},
|
onPrint() {
|
|
this.printBarcode();
|
},
|
|
onPrintSuccess() {
|
this.getOrderById();
|
this.findByOrderId();
|
// this.updateBarcodeAmount();
|
this.getWomdaaPrintById();
|
|
// 清空打印数据
|
this.bufferData = '';
|
this.dataToPrint = [];
|
|
// 清空报工人数据
|
this.staffNo = null;
|
this.user = '';
|
|
// 重置防重复状态(打印成功后完全重置)
|
this.isGeneratingBarcode = false;
|
this.generateRequestId = null;
|
|
console.log("打印成功,已重置防重复状态");
|
},
|
onPrintFail() {
|
console.log("重连失败");
|
this.printLoading = false;
|
|
// 重置防重复状态(打印失败后也要重置)
|
this.isGeneratingBarcode = false;
|
this.generateRequestId = null;
|
|
console.log("打印失败,已重置防重复状态");
|
},
|
|
updateBarcodeAmount() {
|
if (this.dataToPrint.length == 0) {
|
return;
|
}
|
|
let barcodes = this.dataToPrint.map(s => s.out12);
|
|
this.$post({
|
url: "/MesInvItemBarcodes/UpdateBarcodeAmount",
|
data: {
|
barcodes: barcodes,
|
user: this.staffNo
|
}
|
}).then(res => {
|
console.log("更新条码数量成功");
|
})
|
},
|
|
deleteBarcode() {
|
|
// 关闭弹窗
|
this.isShow = false;
|
|
// 取消打印时完全重置防重复状态
|
this.isGeneratingBarcode = false;
|
this.generateRequestId = null;
|
|
// 清空打印数据
|
this.bufferData = '';
|
this.dataToPrint = [];
|
|
// 清空报工人相关数据
|
this.staffNo = null;
|
this.user = '';
|
|
// 重置打印条码数据
|
this.barcodeAmount = '';
|
this.icount = 1;
|
|
// 清空staff数据
|
this.staff = null;
|
|
console.log("已清空报工人和打印数据,重置防重复状态");
|
|
if (this.dataToPrint.length == 0) {
|
return;
|
}
|
|
|
|
// let barcodes = this.dataToPrint.map(s => s.out12);
|
// this.$post({
|
// url: "/MesInvItemBarcodes/DeleteBarcode",
|
// data: {
|
// barcodes: barcodes,
|
// }
|
// }).then(res => {
|
// console.log("删除条码成功");
|
// })
|
},
|
cleanUser() {
|
this.isShow = false;
|
|
this.printLoading = false;
|
|
// 打印结束后重置生成状态,允许下次生成
|
this.isGeneratingBarcode = false;
|
this.generateRequestId = null;
|
|
console.log("打印结束,已重置生成状态");
|
},
|
// 保存操作
|
save() {
|
console.log('保存成功');
|
let ids = [];
|
|
this.selectedReasons.forEach(s => {
|
let id = this.itemsNgname[this.badReasons.indexOf(s)].id;
|
ids.push(id);
|
});
|
|
if (ids.length <= 0) {
|
return
|
}
|
|
let ngids = ids.join(",");
|
|
//MesOrderSta
|
this.$post({
|
url: "/MesOrderSta/UpdateNg",
|
data: {
|
ngId: ngids,
|
staId: this.ngStaid
|
}
|
}).then(res => {
|
if (res.data.tbBillList) {
|
uni.showToast({
|
title: '保存成功',
|
icon: 'success',
|
});
|
this.getOrderById();
|
this.getWomdaaPrintById();
|
this.findByOrderId();
|
}
|
});
|
|
},
|
// 取消操作
|
cancel() {
|
console.log('取消操作');
|
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;
|
|
if (!this.order.todayOutput) {
|
this.productionCount = 0;
|
}
|
|
if (!this.defectiveCount) {
|
this.defectiveCount = 0;
|
}
|
|
if (!this.printedCount) {
|
this.printedCount = 0;
|
}
|
|
//this.defectiveCount = this.productionCount - this.sQuantity;
|
})
|
},
|
getMesItemsNgname() {
|
this.$post({
|
url: "/MesItemsNgname/GetMesItemsNgname",
|
}).then(res => {
|
this.itemsNgname = res.data.tbBillList;
|
this.badReasons = this.itemsNgname.map(s => s.ngName);
|
});
|
},
|
getXS0101() {
|
this.$post({
|
url: "/MesStaff/GetAllXS0101",
|
}).then(res => {
|
this.staff = res.data.tbBillList;
|
this.users = this.staff.map(s => s.staffNo + ":" + s.staffName);
|
});
|
},
|
getWomdaaPrintById() {
|
// 添加错误处理和数据校验
|
try {
|
this.$post({
|
url: "/Womdaa/GetWomdaaPrintById",
|
data: {
|
orderId: this.orderId
|
}
|
}).then(res => {
|
// 检查响应数据是否存在且格式正确
|
if (!res || !res.data || !res.data.tbBillList) {
|
console.error('获取打印数据失败: 响应数据格式错误');
|
return;
|
}
|
|
const data = res.data.tbBillList;
|
|
// 直接赋值bqty,不使用默认值
|
this.bqty = data.bqty;
|
this.icount = 1; // 固定为1
|
this.sQuantity = data.sQuantity || 0;
|
this.initialValue = data.initialValue || 0;
|
this.kgQty = data.kgQty || 0;
|
this.barcodeAmount = data.qqty || 0;
|
|
// 只有当bqty不为null且不为undefined且等于0时才执行Completed
|
if (this.bqty !== null && this.bqty !== undefined && this.bqty === 0) {
|
console.log('数量为0,执行完成操作');
|
this.Completed();
|
}
|
|
}).catch(err => {
|
console.error('获取打印数据失败:', err);
|
});
|
} catch (error) {
|
console.error('执行getWomdaaPrintById时发生错误:', error);
|
}
|
},
|
Completed() {
|
this.$post({
|
url: "/MesOrderSta/Completed",
|
data: {
|
orderId: this.orderId,
|
orderNo: this.orderNo
|
}
|
}).then(res1 => {
|
|
})
|
},
|
findByOrderId() {
|
this.$post({
|
url: "/MesOrderSta/FindByOrderNo",
|
data: {
|
orderId: this.orderId,
|
orderNo: this.orderNo
|
}
|
}).then(res => {
|
|
// 从接口获取的已选择原因
|
let str = res.data.tbBillList.ngId;
|
|
this.ngStaid = res.data.tbBillList.id;
|
|
if (!str) {
|
return;
|
}
|
|
let ids = str.split(",");
|
|
// 使用 map 和 filter 提取对应的 ngName
|
let preSelectedReasons = ids.map(id => {
|
// 查找对应的对象
|
let matchedItem = this.itemsNgname.find(item => item.id == id);
|
return matchedItem ? matchedItem.ngName : null; // 如果找到,返回 ngName;否则返回 null
|
}).filter(ngName => ngName !== null); // 过滤掉 null 值
|
|
// 设置已选中的不良原因
|
this.selectedReasons = this.badReasons.filter(reason => preSelectedReasons.includes(reason));
|
});
|
},
|
confirmCustomAmount() {
|
// 检查输入是否为有效数字
|
if (!this.customAmount || isNaN(Number(this.customAmount))) {
|
this.$showMessage('请输入有效的数量');
|
return;
|
}
|
|
// 将自定义数量应用到系统中
|
let amount = Number(this.customAmount);
|
console.log('应用自定义数量:', amount);
|
|
// 这里可以根据需要调用API或更新相关数据
|
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(err => {
|
console.error('报废数量填写失败:', err);
|
this.$showMessage('报废数量填写失败,请重试');
|
});
|
}
|
}
|
};
|
</script>
|
|
<style scoped>
|
/* 页面样式 */
|
.page {
|
padding: 2vh;
|
display: flex;
|
flex-direction: column;
|
justify-content: space-between;
|
box-sizing: border-box;
|
}
|
|
.top-right {
|
position: absolute;
|
top: -25px;
|
right: 50px;
|
z-index: 1000;
|
}
|
|
.refresh-btn {
|
/* padding: 10px; */
|
float: right;
|
background-color: #00A2E9;
|
color: white;
|
border: none;
|
font-size: 32px;
|
border-radius: 15px;
|
margin-top: -23px;
|
padding-left: 25px;
|
padding-right: 25px;
|
margin-top: -32px;
|
margin-bottom: 49px;
|
}
|
|
/* 状态行样式 */
|
.status-section {
|
display: flex;
|
flex-direction: column;
|
margin-bottom: 3vh;
|
padding-top: 14px;
|
}
|
|
.status-row {
|
display: flex;
|
justify-content: space-around;
|
margin-bottom: 20px;
|
}
|
|
.status-box {
|
display: flex;
|
align-items: center;
|
}
|
|
.refresh-container {
|
display: flex;
|
flex-direction: column;
|
align-items: flex-end;
|
}
|
|
input.highlight {
|
width: 10vw;
|
font-weight: 700;
|
border: none;
|
background-color: #FFD700;
|
text-align: center;
|
font-size: 1.5vw;
|
}
|
|
.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;
|
flex-direction: row;
|
align-content: stretch;
|
justify-content: flex-start;
|
}
|
|
.barcode-info {
|
display: flex;
|
align-items: flex-start;
|
gap: 2vw;
|
flex-direction: row;
|
flex-wrap: nowrap;
|
align-content: flex-start;
|
justify-content: flex-start;
|
}
|
|
.inp {
|
width: 65%;
|
padding: 1vh;
|
margin-top: -13px;
|
font-size: 1.3vw;
|
border: 1px solid #808080;
|
border-radius: 0.5vw;
|
box-sizing: border-box;
|
}
|
|
.barcode-info text {
|
font-size: 2.5vw
|
}
|
|
input {
|
padding: 1vh;
|
font-size: 1.5vw;
|
width: 10vw;
|
border-radius: 0.5vw;
|
height: 2.4em;
|
}
|
|
.print-btn {
|
display: inline-block;
|
padding: 1.5vh;
|
background-color: #e93c00eb;
|
color: white;
|
font-size: 1.5vw;
|
border: none;
|
cursor: pointer;
|
border-radius: 1vw;
|
margin-left: 30px;
|
}
|
|
.details-btn {
|
display: inline-block;
|
padding: 1.5vh;
|
background-color: #00a2e9;
|
color: white;
|
font-size: 1.5vw;
|
border: none;
|
cursor: pointer;
|
border-radius: 1vw;
|
margin-left: 50px;
|
}
|
|
/* 不良原因选择 */
|
.reason-section {
|
margin-bottom: 3vh;
|
}
|
|
.reason-buttons {
|
display: grid;
|
grid-template-columns: repeat(5, 1fr);
|
gap: 1vw;
|
}
|
|
.reason-btn {
|
padding: 0.5vh;
|
background-color: #808080;
|
color: white;
|
font-size: 1.3vw;
|
border: none;
|
border-radius: 0.5vw;
|
cursor: pointer;
|
}
|
|
.reason-btn.selected {
|
background-color: #FFD700;
|
color: black;
|
}
|
|
/* 底部保存和取消按钮 */
|
.bottom-section {
|
display: flex;
|
justify-content: space-between;
|
margin-top: 2vh;
|
}
|
|
.bottom-section1 {
|
display: flex;
|
justify-content: space-around;
|
margin-bottom: 2vh;
|
padding: 2vh 1vw;
|
}
|
|
.save-btn,
|
.cancel-btn {
|
width: 48%;
|
padding: 1.5vh;
|
background-color: #00A2E9;
|
color: white;
|
font-size: 1.5vw;
|
border: none;
|
text-align: center;
|
cursor: pointer;
|
border-radius: 0.5vw;
|
}
|
|
.clean-btn {
|
width: 48%;
|
padding: 1.5vh;
|
color: white;
|
font-size: 1.5vw;
|
border: none;
|
text-align: center;
|
cursor: pointer;
|
border-radius: 0.5vw;
|
background-color: #007aff;
|
}
|
|
.user-select1 {
|
float: left;
|
display: inline-block;
|
margin-top: 17px;
|
}
|
|
.user-select2 {
|
margin-top: 17px;
|
margin-left: -10px;
|
}
|
|
.user-select {
|
/* margin-right: 2vw; */
|
font-size: 1.5vw;
|
}
|
|
.form-item label {
|
float: left;
|
margin-top: -5px;
|
font-size: 1.5vw;
|
/* Larger font for labels */
|
display: inline-block;
|
margin-bottom: 0.5vh;
|
color: #333;
|
}
|
|
.overlay {
|
position: fixed;
|
top: 0;
|
left: 0;
|
width: 100%;
|
height: 100%;
|
background-color: rgba(0, 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, 0.1);
|
width: 70vw;
|
height: 70vh;
|
font-size: 1.6vw;
|
/* 设置弹框的最大高度 */
|
max-height: 80vh;
|
/* 启用纵向滚动条 */
|
overflow-y: auto;
|
/* 设置弹框的外观 */
|
border-radius: 8px;
|
/* Increased font size within popups */
|
}
|
|
.inp5 {
|
float: left;
|
margin-top: 0px;
|
width: 20%;
|
text-align: center;
|
font-size: 45px;
|
border: 0px;
|
border-radius: 1.5vw;
|
background-color: #e5d3a0;
|
}
|
|
.inp6 {
|
float: left;
|
width: 22%;
|
text-align: center;
|
font-size: 45px;
|
border: 0px;
|
border-radius: 1.5vw;
|
background-color: #e5d3a0;
|
display: inline-block;
|
}
|
|
.table1 {
|
width: 100%;
|
border-spacing: 3px;
|
}
|
|
.table2 {
|
background-color: bisque;
|
|
}
|
|
.top-refresh-container {
|
display: flex;
|
justify-content: flex-end;
|
align-items: center;
|
margin-bottom: 15px;
|
}
|
|
.version-info-top {
|
text-align: right;
|
font-size: 13px;
|
color: #000;
|
margin-right: 10px;
|
}
|
|
.operator-box {
|
display: flex;
|
justify-content: center;
|
align-items: center;
|
font-size: 36px;
|
font-weight: bold;
|
margin: 0 10px;
|
color: #333;
|
}
|
|
.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, 0.1);
|
}
|
|
.header-title {
|
font-size: 24px;
|
font-weight: bold;
|
color: #333;
|
}
|
|
.header-right {
|
display: flex;
|
align-items: center;
|
}
|
|
.top-refresh-container {
|
display: flex;
|
justify-content: flex-end;
|
align-items: center;
|
margin-bottom: 15px;
|
}
|
|
.version-info-top {
|
text-align: right;
|
font-size: 13px;
|
color: #666;
|
margin-right: 10px;
|
}
|
|
.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, 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, 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;
|
line-height: 40px;
|
text-align: center;
|
}
|
|
.refresh-btn {
|
background-color: #007aff;
|
color: white;
|
border: none;
|
font-size: 18px;
|
border-radius: 6px;
|
padding: 8px 20px;
|
transition: background-color 0.3s;
|
}
|
|
.refresh-btn:active {
|
background-color: #0062cc;
|
}
|
|
.reset-btn {
|
background-color: #ff6b6b;
|
color: white;
|
border: none;
|
font-size: 18px;
|
border-radius: 6px;
|
padding: 8px 15px;
|
margin-left: 10px;
|
transition: background-color 0.3s;
|
}
|
|
.reset-btn:active {
|
background-color: #e55555;
|
}
|
|
.non-calc-row {
|
border-top: 1px dashed #ccc;
|
margin-top: 30px;
|
padding-top: 20px;
|
position: relative;
|
}
|
|
.divider-label {
|
position: absolute;
|
top: -12px;
|
left: 30px;
|
background-color: #fff;
|
padding: 0 15px;
|
font-size: 16px;
|
color: #777;
|
}
|
|
.standalone-box {
|
background-color: #f5f5f5;
|
padding: 8px 15px;
|
border-radius: 6px;
|
margin-right: 20px;
|
}
|
|
.confirm-row {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
margin-top: 10px;
|
}
|
|
.input-group {
|
display: flex;
|
align-items: center;
|
}
|
|
.custom-input {
|
width: 60%;
|
padding: 1vh;
|
font-size: 1.5vw;
|
border: 1px solid #808080;
|
border-radius: 0.5vw;
|
}
|
|
.confirm-btn {
|
padding: 1.5vh;
|
background-color: #00A2E9;
|
color: white;
|
font-size: 1.5vw;
|
border: none;
|
cursor: pointer;
|
border-radius: 0.5vw;
|
}
|
|
.custom-amount-section {
|
margin-top: 20px;
|
}
|
|
.custom-amount-container {
|
display: flex;
|
align-items: center;
|
}
|
|
.custom-amount-label {
|
margin-right: 10px;
|
font-size: 1.5vw;
|
}
|
|
.custom-amount-input {
|
width: 60%;
|
padding: 1vh;
|
font-size: 1.5vw;
|
border: 1px solid #808080;
|
border-radius: 0.5vw;
|
}
|
|
.custom-amount-row {
|
margin-top: 20px;
|
}
|
</style>
|