设备维修选择设备优化

master
liutao 2 weeks ago
parent 1bda98f6f9
commit ca6bb6e21b

@ -1003,6 +1003,8 @@ export default {
validatorFaultLevelRequired: 'Please select the failure level',
validatorIsShutdownRequired: 'Please select whether shutdown is required',
validatorFaultPhenomenonRequired: 'Please enter the fault phenomenon',
selectDevice: 'Select Device',
searchDevicePlaceholder: 'Search device name or code',
lineFilter: 'Line',
validatorRepairStatusRequired: 'Please select the repair result',
validatorFinishDateRequired: 'Please select the completion date',

@ -1006,6 +1006,8 @@ export default {
validatorFaultLevelRequired: '请选择故障等级',
validatorIsShutdownRequired: '请选择是否停机',
validatorFaultPhenomenonRequired: '请输入故障现象',
selectDevice: '选择设备',
searchDevicePlaceholder: '搜索设备名称或编码',
lineFilter: '产线',
validatorRepairStatusRequired: '请选择维修结果',
validatorFinishDateRequired: '请选择完成日期',

@ -108,9 +108,13 @@
<u-icon name="scan" size="18" color="#1f4b79"></u-icon>
</view>
</view>
<picker :range="deviceLabels" :value="deviceIndex" :disabled="readonlyBase" @change="onDeviceChange">
<view :class="['picker-field', !formData.deviceId ? 'is-placeholder' : '']">{{ selectedDeviceLabel }}</view>
</picker>
<view :class="['device-select-trigger', formData.deviceId ? 'selected' : '']" @click="openDevicePicker">
<view class="device-select-trigger-content">
<text :class="formData.deviceId ? 'device-select-value' : 'device-select-placeholder'">{{ selectedDeviceLabel || t('equipmentMaintenance.placeholderDevice') }}</text>
<text v-if="formData.deviceId" class="device-select-subtext">{{ deviceCodeText }}</text>
</view>
<uni-icons type="right" size="18" color="#9ca3af"></uni-icons>
</view>
</view>
<view v-if="showComponentSelect" class="form-item">
@ -232,6 +236,29 @@
<view class="footer-btn cancel" @click="goBack">{{ t('dashboard.back') }}</view>
<view v-if="!isReadonly" class="footer-btn confirm" @click="submitForm">{{ submitButtonText }}</view>
</view>
<!-- 设备选择弹窗 -->
<view v-if="showDevicePicker" class="picker-mask" @click="showDevicePicker = false">
<view class="picker-popup" @click.stop>
<view class="picker-header">
<text class="picker-title">{{ t('equipmentMaintenance.selectDevice') }}</text>
<view class="picker-close" @click="showDevicePicker = false">
<uni-icons type="close" size="24" color="#6b7280"></uni-icons>
</view>
</view>
<view class="picker-search">
<input v-model="deviceSearchKeyword" class="picker-search-input" type="text" :placeholder="t('equipmentMaintenance.searchDevicePlaceholder')" confirm-type="search" @input="onDeviceSearchInput" />
</view>
<scroll-view scroll-y class="picker-content">
<view v-for="(item, index) in filteredDeviceOptions" :key="item.value" :class="['picker-item', String(item.value) === String(formData.deviceId) ? 'picker-item-active' : '']" @click="selectDeviceFromPicker(item)">
<view class="picker-item-main">
<text class="picker-item-name">{{ item.raw?.deviceName || '-' }}</text>
<text class="picker-item-code">{{ item.raw?.deviceCode || '-' }}</text>
</view>
</view>
<view v-if="!filteredDeviceOptions.length" class="picker-empty">{{ t('functionCommon.noData') }}</view>
</scroll-view>
</view>
</view>
</view>
</template>
@ -259,6 +286,9 @@ const mode = ref('create')
const repairId = ref('')
const users = ref([])
const deviceOptions = ref([])
const showDevicePicker = ref(false)
const deviceSearchKeyword = ref('')
let deviceSearchTimer = null
const componentOptions = ref([])
const loading = ref(false)
@ -341,6 +371,21 @@ const selectedDeviceLabel = computed(() => {
const current = deviceOptions.value.find((item) => String(item.value) === String(formData.deviceId || ''))
return current?.label || t('equipmentMaintenance.placeholderDevice')
})
const deviceCodeText = computed(() => {
const current = deviceOptions.value.find((item) => String(item.value) === String(formData.deviceId || ''))
return current?.raw?.deviceCode || ''
})
const filteredDeviceOptions = computed(() => {
const keyword = deviceSearchKeyword.value.trim().toLowerCase()
if (!keyword) return deviceOptions.value
return deviceOptions.value.filter((item) => {
const code = String(item.raw?.deviceCode || '').toLowerCase()
const name = String(item.raw?.deviceName || '').toLowerCase()
return code.includes(keyword) || name.includes(keyword)
})
})
const filteredComponentOptions = computed(() => {
const source = Array.isArray(componentOptions.value) ? componentOptions.value : []
const currentDeviceId = String(formData.deviceId || '').trim()
@ -547,6 +592,24 @@ function onMachineryTypeChange(event) {
selectMachineryType(event?.detail?.value)
}
function openDevicePicker() {
if (readonlyBase.value) return
deviceSearchKeyword.value = ''
showDevicePicker.value = true
}
function selectDeviceFromPicker(item) {
if (!item) return
applyDeviceOption(item)
showDevicePicker.value = false
}
function onDeviceSearchInput() {
if (deviceSearchTimer) clearTimeout(deviceSearchTimer)
deviceSearchTimer = setTimeout(() => {}, 200)
}
async function handleDeviceScan() {
try {
const res = await uni.scanCode({ scanType: ['qrCode', 'barCode'] })
@ -1164,4 +1227,54 @@ function goBack() {
background: #1f4b79;
color: #ffffff;
}
.device-select-trigger {
display: flex;
align-items: center;
justify-content: space-between;
padding: 24rpx 20rpx;
background: #f7f9fc;
border-radius: 12rpx;
min-height: 88rpx;
}
.device-select-trigger.selected {
background: #eef2ff;
border: 1rpx solid #c7d2fe;
}
.device-select-trigger-content {
flex: 1;
display: flex;
flex-direction: column;
gap: 6rpx;
min-width: 0;
}
.device-select-value {
font-size: 28rpx;
color: #1f2937;
font-weight: 500;
}
.device-select-placeholder {
font-size: 28rpx;
color: #9ca3af;
}
.device-select-subtext {
font-size: 22rpx;
color: #6b7280;
}
.picker-mask { position: fixed; left: 0; right: 0; top: 0; bottom: 0; background: rgba(0, 0, 0, 0.5); z-index: 100; display: flex; align-items: flex-end; }
.picker-popup { width: 100%; background: #ffffff; border-radius: 24rpx 24rpx 0 0; padding-bottom: env(safe-area-inset-bottom); }
.picker-header { display: flex; align-items: center; justify-content: space-between; padding: 28rpx 32rpx; border-bottom: 1rpx solid #e5e7eb; }
.picker-title { font-size: 34rpx; font-weight: 600; color: #1f2937; }
.picker-close { width: 48rpx; height: 48rpx; display: flex; align-items: center; justify-content: center; }
.picker-search { padding: 16rpx 32rpx; }
.picker-search-input { width: 100%; height: 72rpx; padding: 0 20rpx; background: #f3f4f6; border-radius: 12rpx; font-size: 26rpx; box-sizing: border-box; }
.picker-content { max-height: 60vh; }
.picker-item { padding: 24rpx 32rpx; border-bottom: 1rpx solid #f3f4f6; }
.picker-item-main { display: flex; align-items: center; justify-content: space-between; gap: 16rpx; }
.picker-item-name { font-size: 28rpx; color: #374151; flex: 1; min-width: 0; }
.picker-item-code { font-size: 24rpx; color: #9ca3af; flex-shrink: 0; }
.picker-item-active { background: #eff6ff; }
.picker-item-active .picker-item-name { color: #1f7cff; font-weight: 600; }
.picker-empty { padding: 48rpx; text-align: center; color: #9ca3af; font-size: 26rpx; }
</style>

Loading…
Cancel
Save