yuhdemo/yh-app/pages/yys/ToolManagement/index.vue
2026-01-30 14:02:18 +08:00

477 lines
16 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">
<!-- 搜索框区域 -->
<view class="search-box">
<view class="input-box">
<input type="text" v-model="searchCode" placeholder="请输入或扫码" placeholder-class="placeholder"
@confirm="getToolInfo" />
<view class="scan-btn" @tap="openScan">
<u-icon name="scan" size="40" color="#333"></u-icon>
</view>
</view>
</view>
<!-- 设备信息展示区域 -->
<view class="tool-list">
<view v-for="(tool, index) in toolList" :key="index" class="tool-info">
<view class="title">设备信息</view>
<view class="divider"></view>
<view class="info-item">
<text class="label">设备编号:</text>
<text class="value">{{ tool.eqmtNo }}</text>
</view>
<view class="info-item">
<text class="label">设备名称:</text>
<text class="value">{{ tool.eqmtName }}</text>
</view>
<view class="info-item">
<text class="label">设备型号:</text>
<text class="value">{{ tool.specName }}</text>
</view>
<view class="info-item">
<text class="label">磨刀次数:</text>
<text class="value">{{ tool.shareNum }}</text>
</view>
<view class="info-item">
<text class="label">使用时间:</text>
<text class="value">{{ tool.useDtime }}H</text>
</view>
<view class="info-item status-row">
<view class="status-wrapper">
<text class="label">当前状态:</text>
<text class="value">{{ statusMapping[tool.status] }}</text>
</view>
<u-button type="primary" size="mini" @click="handleOperate(tool)">操作</u-button>
</view>
</view>
</view>
<!-- 底部弹出窗体 -->
<u-popup v-model="showPopup" mode="bottom" :border-radius="10" :closeable="true" @close="closePopup"
height="800rpx">
<view class="popup-content">
<view class="popup-title">操作</view>
<!-- 表单内容 -->
<u-form :model="formData" :rules="rules" ref="formData" label-width="200rpx">
<u-form-item label="当前状态" prop="status">
<text>{{ currentTool && statusMapping[currentTool.status] }}</text>
</u-form-item>
<u-form-item label="确认去向" prop="status" required>
<text @click="show = true">{{ currentTool && statusMapping[formData.status] || '请选择去向' }}</text>
<u-select v-model="show" :list="getStatusOptions" placeholder="请选择去向" @confirm="confirm"
@cancel="show = false" confirm-text="确定" cancel-text="取消"></u-select>
</u-form-item>
<template v-if="currentTool && statusMapping[currentTool.status] === '上机'">
<u-form-item label="切片数量" prop="cutNum" required>
<u-input v-model="formData.cutNum" type="number" placeholder="请输入切片数量"></u-input>
</u-form-item>
<u-form-item label="下机时间" prop="downDtime" required>
<jnpf-date-time type="datetime" v-model="formData.downDtime"></jnpf-date-time>
</u-form-item>
<u-form-item label="使用时间(h)" prop="useDtime">
<!-- 强制数值化,默认/回退为 0 -->
<u-input v-model="formData.useDtime" type="number" placeholder="使用时间"
@input="onUseDtimeInput"></u-input>
</u-form-item>
</template>
</u-form>
<!-- 底部按钮 -->
<view class="popup-footer">
<u-button @click="showPopup = false" :custom-style="{ marginRight: '20rpx' }">取消</u-button>
<u-button type="primary" @click="saveOperation">保存</u-button>
</view>
</view>
</u-popup>
</view>
</template>
<script>
import {
getEqmtBaseList,
saveEqmtBase
} from '@/api/yys/EqmtBase.js';
export default {
data() {
return {
showPopup: false, // 控制弹出层显示
searchCode: '',
toolList: [], // 替换原来的 toolInfo
currentTool: null, // 当前操作的设备
showTimePicker: false, // 控制时间选择器显示
formData: {
status: "",
cutNum: 0,
downDtime: "",
useDtime: 0, // 默认数字 0
},
go: {
'上机': ['下机', '磨光', '入库'],
'下机': ['上机', '磨光', '入库'],
'磨光': ['上机', '入库'],
'入库': ['上机', '磨光']
},
statusMapping: {
10: "上机",
11: "下机",
20: "磨光",
30: "入库",
50: "报废"
},
show: false, // 控制状态选择弹出层
rules: {
targetStatus: [{
required: true,
message: '请选择确认去向',
trigger: 'change'
}],
sliceCount: [{
required: true,
message: '请输入切片数量',
trigger: 'blur'
}],
offTime: [{
required: true,
message: '请选择下机时间',
trigger: 'change'
}]
},
}
},
computed: {
getStatusOptions() {
const currentStatus = this.currentTool?.status || '';
const currentStatusText = this.statusMapping[currentStatus] || "";
console.log('options:', currentStatusText, this.go[currentStatusText]);
return this.go[currentStatusText] && this.go[currentStatusText].map(item => ({
label: item,
value: this.getStatusKey(item)
})) || [];
}
},
methods: {
// 打开扫码
openScan() {
uni.scanCode({
scanType: ['qrCode', 'barCode'],
success: (res) => {
this.searchCode = res.result;
this.getToolInfo();
}
});
},
// 获取设备信息
async getToolInfo() {
try {
const params = {
eqmtNo: this.searchCode,
currentPage: 1,
pageSize: 10
};
const res = await getEqmtBaseList(params);
console.log('设备信息:', res);
if (res.code === 200 && res.data.list.length > 0) {
this.toolList = res.data.list;
console.log('设备列表:', this.toolList);
} else {
uni.showToast({
title: '未找到设备信息',
icon: 'none'
});
}
} catch (error) {
console.error('获取设备信息失败:', error);
uni.showToast({
title: '获取设备信息失败',
icon: 'none'
});
}
},
isOnMachine() {
const raw = this.currentTool?.status;
const text = this.statusMapping[raw];
return text === '上机';
},
// 操作按钮点击
handleOperate(tool) {
this.$set(this, 'currentTool', tool);
this.showPopup = true;
if (this.isOnMachine()) {
// 下机时间默认当前时间戳
this.formData.downDtime = Date.now();
// 使用时间按上机时间计算(小时,向下取整),不可解析则回退为 0 取整
const upTime = Number(this.currentTool.upDtime);
const downTime = Number(this.formData.downDtime);
const hours = (downTime - upTime) / (1000 * 60 * 60);
this.formData.useDtime = Number.isFinite(hours) ? Math.floor(hours) : 0;
}
},
closePopup() {
if (this.isClosing) return;
this.isClosing = true;
this.showPopup = false;
this.resetForm();
this.currentTool = null;
// 统一在关闭时刷新一次列表(保存成功、手动关闭都走这里)
this.getToolInfo();
this.$nextTick(() => {
this.isClosing = false;
});
},
statusConfirm(value) {
this.formData.targetStatus = value;
},
timeConfirm(value) {
this.formData.offTime = value;
},
resetForm() {
this.formData = {
status: "",
cutNum: "",
downDtime: "",
useDtime: 0, // 重置为数字 0
};
// 移除这里的查询,避免重复
},
getStatusKey(label) {
const entry = Object.entries(this.statusMapping).find(([key, val]) => val === label);
return entry ? Number(entry[0]) : null;
},
confirm(value) {
// u-select 返回的数组,取首个选中项
const selected = value[0]?.value;
// 若是文本,转换为数值 key若已是数值直接使用
this.formData.status = typeof selected === 'number' ? selected : this.getStatusKey(selected);
this.show = false;
console.log('value:', value, 'selected status key:', this.formData.status);
},
formatDate(dateString) {
if (!dateString) return "";
const date = new Date(dateString);
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
const seconds = String(date.getSeconds()).padStart(2, '0');
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
},
// 保存操作
async saveOperation() {
try {
if(!this.formData.status) {
uni.showToast({
title: '请选择去向',
icon: 'none'
});
return;
}
// await this.$refs.formData.validate();
// 构造保存参数
const params = {
id: this.currentTool.id,
status: this.formData.status, // 去向
useDtime: this.formData.useDtime,
cutNum: this.formData.cutNum,
downDtime: this.formData.downDtime,//当前为时间戳
eqmtNo: this.currentTool.eqmtNo
};
console.log('保存参数:', params);
const res = await saveEqmtBase(params);
if (res.code === 200) {
uni.showToast({
title: res.msg || '保存成功',
icon: 'success'
});
// 仅关闭弹窗,查询在 @close -> closePopup 中统一触发一次
this.showPopup = false;
} else {
uni.showToast({
title: res.msg || '保存失败',
icon: 'error'
});
}
} catch (error) {
console.error('保存操作失败:', error);
// uni.showToast({
// title: '保存失败',
// icon: 'none'
// });
}
}
},
async mounted() {
// 页面加载时可以初始化数据
},
watch: {
'formData.downDtime'(newVal) {
if (this.isOnMachine()) {
// 使用时间按上机时间计算(小时,向下取整),不可解析则回退为 0 取整
const upTime = Number(this.currentTool.upDtime);
const downTime = Number(this.formData.downDtime);
const hours = (downTime - upTime) / (1000 * 60 * 60);
this.formData.useDtime = Number.isFinite(hours) ? Math.floor(hours) : 0;
}
}
}
}
</script>
<style lang="scss" scoped>
.container {
padding: 20rpx;
background-color: #F8F8F8;
min-height: 100vh;
}
.search-box {
padding: 20rpx;
background-color: #fff;
border-radius: 8rpx;
.input-box {
display: flex;
align-items: center;
background-color: #F5F5F5;
padding: 10rpx 20rpx;
border-radius: 8rpx;
input {
flex: 1;
height: 60rpx;
font-size: 28rpx;
}
.scan-btn {
padding-left: 20rpx;
display: flex;
align-items: center;
}
}
}
.tool-list {
.tool-info {
margin-bottom: 20rpx;
background-color: #fff;
border-radius: 8rpx;
padding: 30rpx;
.title {
font-size: 32rpx;
font-weight: bold;
margin-bottom: 20rpx;
}
.info-item {
display: flex;
align-items: center;
margin-bottom: 16rpx;
font-size: 28rpx;
.label {
color: #666;
width: 160rpx;
}
.value {
color: #333;
flex: 1;
}
&.status-row {
justify-content: space-between;
align-items: center;
.status-wrapper {
display: flex;
align-items: center;
}
.u-button {
margin-left: 20rpx;
width: 140rpx;
}
}
}
}
}
.placeholder {
color: #999;
font-size: 28rpx;
}
.popup-content {
padding: 30rpx;
max-height: 80vh;
overflow-y: auto;
.popup-title {
font-size: 32rpx;
font-weight: bold;
text-align: center;
margin-bottom: 30rpx;
}
.time-trigger {
width: 100%;
height: 70rpx;
line-height: 70rpx;
padding: 0 20rpx;
background-color: #F5F5F5;
border-radius: 4rpx;
font-size: 28rpx;
color: #333;
}
.popup-footer {
display: flex;
justify-content: space-between;
margin-top: 40rpx;
padding-bottom: env(safe-area-inset-bottom);
.u-button {
flex: 1;
}
}
}
// 调整单选框组样式
/deep/ .u-radio-group {
display: flex;
flex-wrap: wrap;
.u-radio {
margin-right: 30rpx;
margin-bottom: 10rpx;
}
}
</style>