yuhdemo/yh-app/pages/yys/ToolManagement/index.vue

477 lines
16 KiB
Vue
Raw Normal View History

2026-01-30 14:02:18 +08:00
<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>