黄伟杰 14 hours ago
commit c655469801

@ -71,27 +71,21 @@
</view>
<view class="warehouse-area-row">
<text class="warehouse-area-label">库区</text>
<view class="warehouse-area-dropdown" @click="toggleAreaDropdown">
<view class="dropdown-input">
<text :class="['dropdown-value', { placeholder: !selectedArea }]">
{{ selectedArea ? selectedArea.label : (loadingAreas ? '加载中...' : '请选择') }}
</text>
<text class="dropdown-arrow"></text>
</view>
<view v-if="showAreaDropdown" class="dropdown-panel">
<view class="dropdown-scroll">
<view
v-for="item in areaOptions"
:key="item.value"
class="dropdown-item"
:class="{ active: selectedArea?.value === item.value }"
@click.stop="handleSelectArea(item)"
>
<text class="dropdown-item-text">{{ item.label }}</text>
<text v-if="selectedArea?.value === item.value" class="dropdown-check"></text>
<view class="warehouse-area-dropdown">
<view class="product-search-row">
<input
v-model="areaScanInput"
class="scan-input"
type="text"
placeholder="扫码或输入库区码"
confirm-type="done"
@confirm="onAreaScanConfirm"
/>
<picker mode="selector" :range="areaOptions" range-key="label" :value="getAreaIndex(selectedArea, areaOptions)" @change="onAreaChange">
<view class="area-select-btn">
<text class="select-btn-text">选择</text>
</view>
<view v-if="!areaOptions.length" class="dropdown-empty"></view>
</view>
</picker>
</view>
</view>
</view>
@ -161,11 +155,11 @@ const inboundQty = ref(null)
const warehouseOptions = ref([])
const selectedWarehouse = ref(null)
//
//
const areaOptions = ref([])
const selectedArea = ref(null)
const showAreaDropdown = ref(false)
const loadingAreas = ref(false)
const areaScanInput = ref('')
const materialImage = computed(() => {
const images = material.value.images
@ -295,17 +289,41 @@ async function loadWarehouses() {
}
//
function toggleAreaDropdown() {
if (!selectedWarehouse.value) {
uni.showToast({ title: '请先选择仓库', icon: 'none' })
return
function getAreaIndex(selected, options) {
if (!selected) return -1
const index = options.findIndex((item) => String(item.value) === String(selected.value))
return index >= 0 ? index : -1
}
function onAreaChange(event) {
const index = Number(event.detail.value)
if (index >= 0 && index < areaOptions.value.length) {
selectedArea.value = areaOptions.value[index]
areaScanInput.value = selectedArea.value.label
}
showAreaDropdown.value = !showAreaDropdown.value
}
function handleSelectArea(item) {
selectedArea.value = item
showAreaDropdown.value = false
function getAreaScanId(value) {
const text = String(value || '').trim()
if (!text) return ''
const match = text.match(/WAREHOUSE_AREA[-_:](\d+)/i)
if (match) return match[1]
const tail = text.match(/(\d+)$/)
return tail ? tail[1] : text
}
async function onAreaScanConfirm() {
const areaId = getAreaScanId(areaScanInput.value)
if (!areaId) return
const area = areaOptions.value.find((item) => String(item.value) === String(areaId))
if (!area) {
uni.showToast({ title: '未找到该库区', icon: 'none' })
return
}
selectedArea.value = area
areaScanInput.value = area.label
}
async function loadAreas(warehouseId) {
if (!warehouseId) return
loadingAreas.value = true
@ -363,9 +381,7 @@ async function loadStockCount() {
}
}
onHide(() => {
showAreaDropdown.value = false
})
onHide(() => {})
</script>
<style lang="scss" scoped>
@ -446,6 +462,11 @@ onHide(() => {
.warehouse-area-label { width: 80rpx; font-size: 26rpx; color: #6b7280; flex-shrink: 0; }
.warehouse-area-dropdown { flex: 1; min-width: 0; position: relative; }
.product-search-row { display: flex; align-items: center; gap: 16rpx; }
.scan-input { flex: 1; min-width: 0; height: 64rpx; padding: 0 20rpx; background: #f8fafc; border: 1rpx solid #e5e7eb; border-radius: 10rpx; box-sizing: border-box; font-size: 27rpx; color: #333; }
.area-select-btn { flex-shrink: 0; width: 160rpx; min-height: 64rpx; padding: 0 18rpx; background: #1f4b79; border-radius: 10rpx; box-sizing: border-box; display: flex; align-items: center; justify-content: center; }
.select-btn-text { color: #ffffff; font-size: 26rpx; font-weight: 600; }
.dropdown-input { display: flex; align-items: center; min-height: 64rpx !important; height: 64rpx !important; padding: 0 20rpx; border: 1rpx solid #e0e0e0; border-radius: 10rpx; background: #f9fafb; }
.dropdown-value { flex: 1; font-size: 27rpx; color: #333; &.placeholder { color: #bbb; } }
.dropdown-arrow { font-size: 20rpx; color: #999; flex-shrink: 0; }

@ -45,18 +45,21 @@
</view>
<view class="warehouse-area-row">
<text class="warehouse-area-label">库区</text>
<view class="warehouse-area-dropdown" @click="toggleAreaDropdown">
<view class="dropdown-input">
<text :class="['dropdown-value', { placeholder: !selectedArea }]">{{ selectedArea ? selectedArea.label : (loadingAreas ? '加载中...' : '请选择') }}</text>
<text class="dropdown-arrow"></text>
</view>
<view v-if="showAreaDropdown" class="dropdown-panel">
<view class="dropdown-scroll">
<view v-for="item in areaOptions" :key="item.value" class="dropdown-item" :class="{ active: selectedArea?.value === item.value }" @click.stop="handleSelectArea(item)">
<text class="dropdown-item-text">{{ item.label }}</text>
<text v-if="selectedArea?.value === item.value" class="dropdown-check"></text>
<view class="warehouse-area-dropdown">
<view class="product-search-row">
<input
v-model="areaScanInput"
class="scan-input"
type="text"
placeholder="扫码或输入库区码"
confirm-type="done"
@confirm="onAreaScanConfirm"
/>
<picker mode="selector" :range="areaOptions" range-key="label" :value="getAreaIndex(selectedArea, areaOptions)" @change="onAreaChange">
<view class="area-select-btn">
<text class="select-btn-text">选择</text>
</view>
</view>
</picker>
</view>
</view>
</view>
@ -125,8 +128,8 @@ const warehouseOptions = ref([])
const selectedWarehouse = ref(null)
const areaOptions = ref([])
const selectedArea = ref(null)
const showAreaDropdown = ref(false)
const loadingAreas = ref(false)
const areaScanInput = ref('')
const materialImage = computed(() => {
const images = material.value.images
@ -262,8 +265,42 @@ async function loadWarehouses() {
} catch (e) {}
}
function toggleAreaDropdown() { if (!selectedWarehouse.value) { uni.showToast({ title: '请先选择仓库', icon: 'none' }); return }; showAreaDropdown.value = !showAreaDropdown.value }
function handleSelectArea(item) { selectedArea.value = item; showAreaDropdown.value = false; loadStockCount() }
function getAreaIndex(selected, options) {
if (!selected) return -1
const index = options.findIndex((item) => String(item.value) === String(selected.value))
return index >= 0 ? index : -1
}
function onAreaChange(event) {
const index = Number(event.detail.value)
if (index >= 0 && index < areaOptions.value.length) {
selectedArea.value = areaOptions.value[index]
areaScanInput.value = selectedArea.value.label
loadStockCount()
}
}
function getAreaScanId(value) {
const text = String(value || '').trim()
if (!text) return ''
const match = text.match(/WAREHOUSE_AREA[-_:](\d+)/i)
if (match) return match[1]
const tail = text.match(/(\d+)$/)
return tail ? tail[1] : text
}
async function onAreaScanConfirm() {
const areaId = getAreaScanId(areaScanInput.value)
if (!areaId) return
const area = areaOptions.value.find((item) => String(item.value) === String(areaId))
if (!area) {
uni.showToast({ title: '未找到该库区', icon: 'none' })
return
}
selectedArea.value = area
areaScanInput.value = area.label
loadStockCount()
}
async function loadAreas(warehouseId) {
if (!warehouseId) return
loadingAreas.value = true
@ -320,7 +357,7 @@ async function loadStockCount() {
} catch (e) { warehouseAreaStockCount.value = 0 }
}
onHide(() => { showAreaDropdown.value = false })
onHide(() => {})
</script>
<style lang="scss" scoped>
@ -375,6 +412,12 @@ onHide(() => { showAreaDropdown.value = false })
.warehouse-area-dropdown { flex: 1; min-width: 0; position: relative;
.dropdown-panel { position: absolute; top: 100%; left: 0; right: 0; z-index: 200; margin-top: 4rpx; background: #fff; border: 1rpx solid #e0e0e0; border-radius: 12rpx; box-shadow: 0 8rpx 30rpx rgba(0,0,0,0.15); overflow: hidden; }
}
.product-search-row { display: flex; align-items: center; gap: 16rpx; }
.scan-input { flex: 1; min-width: 0; height: 64rpx; padding: 0 20rpx; background: #f8fafc; border: 1rpx solid #e5e7eb; border-radius: 10rpx; box-sizing: border-box; font-size: 27rpx; color: #333; }
.area-select-btn { flex-shrink: 0; width: 160rpx; min-height: 64rpx; padding: 0 18rpx; background: #1f4b79; border-radius: 10rpx; box-sizing: border-box; display: flex; align-items: center; justify-content: center; }
.select-btn-text { color: #ffffff; font-size: 26rpx; font-weight: 600; }
.dropdown-input { display: flex; align-items: center; min-height: 64rpx !important; height: 64rpx !important; padding: 0 20rpx; border: 1rpx solid #e0e0e0; border-radius: 10rpx; background: #f9fafb; }
.dropdown-value { flex: 1; font-size: 27rpx; color: #333; &.placeholder { color: #bbb; } }
.dropdown-arrow { font-size: 20rpx; color: #999; flex-shrink: 0; }

@ -72,27 +72,21 @@
</view>
<view class="warehouse-area-row">
<text class="warehouse-area-label">库区</text>
<view class="warehouse-area-dropdown" @click="toggleAreaDropdown">
<view class="dropdown-input">
<text :class="['dropdown-value', { placeholder: !selectedArea }]">
{{ selectedArea ? selectedArea.label : (loadingAreas ? '加载中...' : '请选择') }}
</text>
<text class="dropdown-arrow"></text>
</view>
<view v-if="showAreaDropdown" class="dropdown-panel">
<view class="dropdown-scroll">
<view
v-for="item in areaOptions"
:key="item.value"
class="dropdown-item"
:class="{ active: selectedArea?.value === item.value }"
@click.stop="handleSelectArea(item)"
>
<text class="dropdown-item-text">{{ item.label }}</text>
<text v-if="selectedArea?.value === item.value" class="dropdown-check"></text>
<view class="warehouse-area-dropdown">
<view class="product-search-row">
<input
v-model="areaScanInput"
class="scan-input"
type="text"
placeholder="扫码或输入库区码"
confirm-type="done"
@confirm="onAreaScanConfirm"
/>
<picker mode="selector" :range="areaOptions" range-key="label" :value="getAreaIndex(selectedArea, areaOptions)" @change="onAreaChange">
<view class="area-select-btn">
<text class="select-btn-text">选择</text>
</view>
<view v-if="!areaOptions.length" class="dropdown-empty"></view>
</view>
</picker>
</view>
</view>
</view>
@ -164,11 +158,11 @@ const supplierName = ref('')
const warehouseOptions = ref([])
const selectedWarehouse = ref(null)
//
//
const areaOptions = ref([])
const selectedArea = ref(null)
const showAreaDropdown = ref(false)
const loadingAreas = ref(false)
const areaScanInput = ref('')
const sparepartImage = computed(() => {
const images = sparepart.value.images
@ -309,17 +303,41 @@ async function loadWarehouses() {
}
//
function toggleAreaDropdown() {
if (!selectedWarehouse.value) {
uni.showToast({ title: '请先选择仓库', icon: 'none' })
return
function getAreaIndex(selected, options) {
if (!selected) return -1
const index = options.findIndex((item) => String(item.value) === String(selected.value))
return index >= 0 ? index : -1
}
function onAreaChange(event) {
const index = Number(event.detail.value)
if (index >= 0 && index < areaOptions.value.length) {
selectedArea.value = areaOptions.value[index]
areaScanInput.value = selectedArea.value.label
}
showAreaDropdown.value = !showAreaDropdown.value
}
function handleSelectArea(item) {
selectedArea.value = item
showAreaDropdown.value = false
function getAreaScanId(value) {
const text = String(value || '').trim()
if (!text) return ''
const match = text.match(/WAREHOUSE_AREA[-_:](\d+)/i)
if (match) return match[1]
const tail = text.match(/(\d+)$/)
return tail ? tail[1] : text
}
async function onAreaScanConfirm() {
const areaId = getAreaScanId(areaScanInput.value)
if (!areaId) return
const area = areaOptions.value.find((item) => String(item.value) === String(areaId))
if (!area) {
uni.showToast({ title: '未找到该库区', icon: 'none' })
return
}
selectedArea.value = area
areaScanInput.value = area.label
}
async function loadAreas(warehouseId) {
if (!warehouseId) return
loadingAreas.value = true
@ -379,9 +397,7 @@ async function loadStockCount() {
}
}
onHide(() => {
showAreaDropdown.value = false
})
onHide(() => {})
</script>
<style lang="scss" scoped>
@ -449,11 +465,6 @@ onHide(() => {
box-shadow: 0 4rpx 16rpx rgba(15, 23, 42, 0.04);
min-height: 0 !important;
height: auto !important;
.dropdown-panel {
position: absolute; top: 100%; left: 0; right: 0; z-index: 200; margin-top: 4rpx;
background: #fff; border: 1rpx solid #e0e0e0; border-radius: 12rpx;
box-shadow: 0 8rpx 30rpx rgba(0, 0, 0, 0.1); overflow: hidden;
}
}
.full-dropdown { display: flex; align-items: center; justify-content: space-between; width: 100%; font-size: 28rpx; color: #374151;
@ -465,26 +476,18 @@ onHide(() => {
.warehouse-area-rows { width: 100%; display: flex; flex-direction: column; gap: 16rpx; }
.warehouse-area-row { display: flex; align-items: center; }
.warehouse-area-label { width: 80rpx; font-size: 26rpx; color: #6b7280; flex-shrink: 0; }
.warehouse-area-dropdown { flex: 1; min-width: 0; position: relative;
.dropdown-panel {
position: absolute; top: 100%; left: 0; right: 0; z-index: 100; margin-top: 4rpx;
background: #fff; border: 1rpx solid #e0e0e0; border-radius: 12rpx;
box-shadow: 0 8rpx 30rpx rgba(0, 0, 0, 0.1); overflow: hidden;
}
}
.warehouse-area-dropdown { flex: 1; min-width: 0; }
.dropdown-input { display: flex; align-items: center; min-height: 64rpx !important; height: 64rpx !important; padding: 0 20rpx; border: 1rpx solid #e0e0e0; border-radius: 10rpx; background: #f9fafb; }
.dropdown-value { flex: 1; font-size: 27rpx; color: #333; &.placeholder { color: #bbb; } }
.dropdown-arrow { font-size: 20rpx; color: #999; flex-shrink: 0; }
.dropdown-panel { position: absolute; top: 68rpx; left: 0; right: 0; z-index: 200; background: #fff; border: 1rpx solid #e0e0e0; border-radius: 12rpx; box-shadow: 0 8rpx 30rpx rgba(0, 0, 0, 0.1); overflow: hidden; }
.dropdown-scroll { max-height: 360rpx; overflow-y: auto; }
.dropdown-item { display: flex; align-items: center; justify-content: space-between; padding: 20rpx 24rpx; border-bottom: 1rpx solid #f0f0f0;
&:last-child { border-bottom: 0; }
&.active { background: #f0f5ff; }
}
.dropdown-item-text { font-size: 27rpx; color: #333; }
.dropdown-check { font-size: 28rpx; color: #2563eb; font-weight: 700; }
.dropdown-empty { padding: 32rpx; text-align: center; color: #999; font-size: 26rpx; }
.dropdown-value { flex: 1; font-size: 27rpx; color: #333; }
.product-search-row { display: flex; align-items: center; gap: 16rpx; }
.scan-input { flex: 1; min-width: 0; height: 70rpx; padding: 0 22rpx; background: #f8fafc; border: 1rpx solid #e5e7eb; border-radius: 14rpx; box-sizing: border-box; font-size: 28rpx; color: #1f2937; }
.area-select-btn { flex-shrink: 0; width: 160rpx; min-height: 70rpx; padding: 0 18rpx; background: #1f4b79; border-radius: 14rpx; box-sizing: border-box; display: flex; align-items: center; justify-content: center; }
.select-btn-text { color: #ffffff; font-size: 26rpx; font-weight: 600; }
.selected-tip { margin-top: 10rpx; padding: 14rpx 18rpx; border-radius: 12rpx; background: #f8fafc; color: #334155; font-size: 24rpx; }
.bottom-actions {
position: fixed; left: 0; right: 0; bottom: 0; display: flex; gap: 18rpx;

@ -56,39 +56,24 @@
<view class="warehouse-area-rows">
<view class="warehouse-area-row">
<text class="warehouse-area-label">关联设备</text>
<view class="warehouse-area-dropdown" @click="toggleDeviceDropdown">
<view class="dropdown-input">
<text :class="['dropdown-value', { placeholder: !selectedDevice }]">{{ selectedDevice ? selectedDevice.label : '请选择' }}</text>
<text class="dropdown-arrow"></text>
</view>
<view v-if="showDeviceDropdown" class="dropdown-panel">
<view class="dropdown-scroll">
<view v-for="item in filteredDeviceOptions" :key="item.value" class="dropdown-item" :class="{ active: selectedDevice?.value === item.value }" @click.stop="handleSelectDevice(item)">
<text class="dropdown-item-text">{{ item.label }}</text>
<text v-if="selectedDevice?.value === item.value" class="dropdown-check"></text>
</view>
<view v-if="deviceLoading" class="dropdown-empty">...</view>
<view v-else-if="!filteredDeviceOptions.length" class="dropdown-empty">{{ selectedPurpose === 'maintain' ? '暂无保养设备' : '暂无设备数据' }}</view>
<view class="warehouse-area-dropdown">
<picker mode="selector" :range="filteredDeviceOptions" range-key="label" :value="getDeviceIndex(selectedDevice, filteredDeviceOptions)" @change="onDeviceChange">
<view class="dropdown-input">
<text :class="['dropdown-value', { placeholder: !selectedDevice }]">{{ selectedDevice ? selectedDevice.label : '请选择' }}</text>
<text class="dropdown-arrow"></text>
</view>
</view>
</picker>
</view>
</view>
<view class="warehouse-area-row">
<text class="warehouse-area-label">{{ selectedPurpose === 'repair' ? '维修单号' : '保养单号' }}</text>
<view class="warehouse-area-dropdown" @click="toggleOrderDropdown">
<view class="dropdown-input">
<text :class="['dropdown-value', { placeholder: !currentOrder }]">{{ currentOrder ? currentOrder.label : '请选择' }}</text>
<text class="dropdown-arrow"></text>
</view>
<view v-if="showOrderDropdown" class="dropdown-panel">
<view class="dropdown-scroll">
<view v-for="item in currentOrderOptions" :key="item.value" class="dropdown-item" :class="{ active: currentOrder?.value === item.value }" @click.stop="handleSelectOrder(item)">
<text class="dropdown-item-text">{{ item.label }}</text>
<text v-if="currentOrder?.value === item.value" class="dropdown-check"></text>
</view>
<view v-if="!currentOrderOptions.length" class="dropdown-empty">{{ selectedPurpose === 'repair' ? '' : '' }}</view>
<view class="warehouse-area-dropdown">
<picker mode="selector" :range="currentOrderOptions" range-key="label" :value="getOrderIndex(currentOrder, currentOrderOptions)" :disabled="!currentOrderOptions.length" @change="onOrderChange">
<view class="dropdown-input">
<text :class="['dropdown-value', { placeholder: !currentOrder }]">{{ currentOrder ? currentOrder.label : '请选择' }}</text>
<text class="dropdown-arrow"></text>
</view>
</view>
</picker>
</view>
</view>
</view>
@ -111,18 +96,21 @@
</view>
<view class="warehouse-area-row">
<text class="warehouse-area-label">库区</text>
<view class="warehouse-area-dropdown" @click="toggleAreaDropdown">
<view class="dropdown-input">
<text :class="['dropdown-value', { placeholder: !selectedArea }]">{{ selectedArea ? selectedArea.label : (loadingAreas ? '加载中...' : '请选择') }}</text>
<text class="dropdown-arrow"></text>
</view>
<view v-if="showAreaDropdown" class="dropdown-panel">
<view class="dropdown-scroll">
<view v-for="item in areaOptions" :key="item.value" class="dropdown-item" :class="{ active: selectedArea?.value === item.value }" @click.stop="handleSelectArea(item)">
<text class="dropdown-item-text">{{ item.label }}</text>
<text v-if="selectedArea?.value === item.value" class="dropdown-check"></text>
<view class="warehouse-area-dropdown">
<view class="product-search-row">
<input
v-model="areaScanInput"
class="scan-input"
type="text"
placeholder="扫码或输入库区码"
confirm-type="done"
@confirm="onAreaScanConfirm"
/>
<picker mode="selector" :range="areaOptions" range-key="label" :value="getAreaIndex(selectedArea, areaOptions)" @change="onAreaChange">
<view class="area-select-btn">
<text class="select-btn-text">选择</text>
</view>
</view>
</picker>
</view>
</view>
</view>
@ -198,23 +186,25 @@ function setPurpose(value) {
selectedMaintainOrder.value = null
repairOrderOptions.value = []
maintainOrderOptions.value = []
if (value === 'repair') loadRepairDeviceIds()
if (value === 'maintain') loadMaintainDeviceIds()
}
const deviceOptions = ref([])
const selectedDevice = ref(null)
const showDeviceDropdown = ref(false)
const repairOrderOptions = ref([])
const selectedRepairOrder = ref(null)
const maintainOrderOptions = ref([])
const selectedMaintainOrder = ref(null)
const maintainDeviceIds = ref(new Set())
const repairDeviceIds = ref(new Set())
const deviceLoading = ref(false)
const filteredDeviceOptions = computed(() => {
if (selectedPurpose.value === 'maintain') return deviceOptions.value.filter(d => maintainDeviceIds.value.has(d.value))
if (selectedPurpose.value === 'repair') return deviceOptions.value.filter(d => repairDeviceIds.value.has(d.value))
return deviceOptions.value
})
const showOrderDropdown = ref(false)
const currentOrder = computed(() => selectedPurpose.value === 'repair' ? selectedRepairOrder.value : selectedMaintainOrder.value)
const currentOrderOptions = computed(() => selectedPurpose.value === 'repair' ? repairOrderOptions.value : maintainOrderOptions.value)
@ -222,8 +212,8 @@ const warehouseOptions = ref([])
const selectedWarehouse = ref(null)
const areaOptions = ref([])
const selectedArea = ref(null)
const showAreaDropdown = ref(false)
const loadingAreas = ref(false)
const areaScanInput = ref('')
const sparepartImage = computed(() => {
const images = sparepart.value.images
@ -355,12 +345,39 @@ function handleConfirm() {
}, 800)
}
function toggleDeviceDropdown() {
showDeviceDropdown.value = !showDeviceDropdown.value
if (showDeviceDropdown.value && selectedPurpose.value === 'maintain' && maintainDeviceIds.value.size === 0) {
loadMaintainDeviceIds()
function getDeviceIndex(selected, options) {
if (!selected) return -1
const index = options.findIndex((item) => String(item.value) === String(selected.value))
return index >= 0 ? index : -1
}
function getOrderIndex(selected, options) {
if (!selected) return -1
const index = options.findIndex((item) => String(item.value) === String(selected.value))
return index >= 0 ? index : -1
}
async function onDeviceChange(event) {
const index = Number(event.detail.value)
if (index >= 0 && index < filteredDeviceOptions.value.length) {
const item = filteredDeviceOptions.value[index]
selectedDevice.value = item
selectedRepairOrder.value = null; selectedMaintainOrder.value = null
repairOrderOptions.value = []; maintainOrderOptions.value = []
if (selectedPurpose.value === 'repair') loadRepairOrders(item.deviceCode)
else loadMaintainOrders(item.deviceCode)
}
}
function onOrderChange(event) {
const index = Number(event.detail.value)
if (index >= 0 && index < currentOrderOptions.value.length) {
const item = currentOrderOptions.value[index]
if (selectedPurpose.value === 'repair') selectedRepairOrder.value = item
else selectedMaintainOrder.value = item
}
}
async function loadMaintainDeviceIds() {
deviceLoading.value = true
try {
@ -376,12 +393,27 @@ async function loadMaintainDeviceIds() {
} catch (e) { console.error('loadMaintainDeviceIds error', e) }
finally { deviceLoading.value = false }
}
async function handleSelectDevice(item) {
selectedDevice.value = item; showDeviceDropdown.value = false
selectedRepairOrder.value = null; selectedMaintainOrder.value = null
repairOrderOptions.value = []; maintainOrderOptions.value = []
if (selectedPurpose.value === 'repair') loadRepairOrders(item.deviceCode)
else loadMaintainOrders(item.deviceCode)
async function loadRepairDeviceIds() {
deviceLoading.value = true
try {
// 100
const allRecords = []
for (let page = 1; page <= 5; page++) {
const res = await getDvRepairPage({ pageNo: page, pageSize: 100 })
const data = res && res.data !== undefined ? res.data : res
const records = Array.isArray(data) ? data : (data?.list || data?.records || [])
allRecords.push(...records)
if (records.length < 100) break
}
const deviceCodes = new Set(allRecords.map(r => r.machineryCode || r.deviceCode || r.deviceName).filter(Boolean))
const ids = new Set()
for (const d of deviceOptions.value) {
if (deviceCodes.has(d.deviceCode) || deviceCodes.has(d.label) || deviceCodes.has(d.deviceName)) ids.add(d.value)
}
repairDeviceIds.value = ids
console.log('[loadRepairDeviceIds] 维修单设备编码:', [...deviceCodes], '匹配到的设备数:', ids.size)
} catch (e) { console.error('loadRepairDeviceIds error', e) }
finally { deviceLoading.value = false }
}
async function loadDevices() {
try {
@ -401,12 +433,6 @@ async function loadDevices() {
}))
} catch (e) { console.error('loadDevices error', e) }
}
function toggleOrderDropdown() { if (!selectedDevice.value) return; showOrderDropdown.value = !showOrderDropdown.value }
function handleSelectOrder(item) {
if (selectedPurpose.value === 'repair') selectedRepairOrder.value = item
else selectedMaintainOrder.value = item
showOrderDropdown.value = false
}
async function loadMaintainOrders(deviceCode) {
const deviceId = selectedDevice.value?.value
if (deviceId) await loadMaintainOrdersById(deviceId)
@ -462,8 +488,43 @@ async function loadWarehouses() {
} catch (e) {}
}
function toggleAreaDropdown() { if (!selectedWarehouse.value) { uni.showToast({ title: '请先选择仓库', icon: 'none' }); return }; showAreaDropdown.value = !showAreaDropdown.value }
function handleSelectArea(item) { selectedArea.value = item; showAreaDropdown.value = false; loadStockCount() }
function getAreaIndex(selected, options) {
if (!selected) return -1
const index = options.findIndex((item) => String(item.value) === String(selected.value))
return index >= 0 ? index : -1
}
function onAreaChange(event) {
const index = Number(event.detail.value)
if (index >= 0 && index < areaOptions.value.length) {
selectedArea.value = areaOptions.value[index]
areaScanInput.value = selectedArea.value.label
loadStockCount()
}
}
function getAreaScanId(value) {
const text = String(value || '').trim()
if (!text) return ''
const match = text.match(/WAREHOUSE_AREA[-_:](\d+)/i)
if (match) return match[1]
const tail = text.match(/(\d+)$/)
return tail ? tail[1] : text
}
async function onAreaScanConfirm() {
const areaId = getAreaScanId(areaScanInput.value)
if (!areaId) return
const area = areaOptions.value.find((item) => String(item.value) === String(areaId))
if (!area) {
uni.showToast({ title: '未找到该库区', icon: 'none' })
return
}
selectedArea.value = area
areaScanInput.value = area.label
loadStockCount()
}
async function loadAreas(warehouseId) {
if (!warehouseId) return
loadingAreas.value = true
@ -489,7 +550,8 @@ onShow(async () => {
} catch (e) { console.error('获取备件详情失败:', e) }
}
}
loadDevices()
await loadDevices()
loadRepairDeviceIds()
loadWarehouses()
})
@ -521,7 +583,7 @@ async function loadStockCount() {
} catch (e) { warehouseAreaStockCount.value = 0 }
}
onHide(() => { showDeviceDropdown.value = false; showOrderDropdown.value = false })
onHide(() => {})
</script>
<style lang="scss" scoped>
@ -592,6 +654,11 @@ onHide(() => { showDeviceDropdown.value = false; showOrderDropdown.value = false
.dropdown-check { font-size: 28rpx; color: #2563eb; font-weight: 700; }
.dropdown-empty { padding: 32rpx; text-align: center; color: #999; font-size: 26rpx; }
.product-search-row { display: flex; align-items: center; gap: 16rpx; }
.scan-input { flex: 1; min-width: 0; height: 70rpx; padding: 0 22rpx; background: #f8fafc; border: 1rpx solid #e5e7eb; border-radius: 14rpx; box-sizing: border-box; font-size: 28rpx; color: #1f2937; }
.area-select-btn { flex-shrink: 0; width: 160rpx; min-height: 70rpx; padding: 0 18rpx; background: #1f4b79; border-radius: 14rpx; box-sizing: border-box; display: flex; align-items: center; justify-content: center; }
.select-btn-text { color: #ffffff; font-size: 26rpx; font-weight: 600; }
.bottom-actions { position: fixed; left: 0; right: 0; bottom: 0; display: flex; gap: 18rpx; padding: 18rpx 24rpx calc(18rpx + env(safe-area-inset-bottom)); background: #fff; box-shadow: 0 -8rpx 24rpx rgba(15,23,42,0.06); z-index: 99; }
.bottom-btn { flex: 1; height: 84rpx; line-height: 84rpx; text-align: center; border-radius: 16rpx; font-size: 30rpx; font-weight: 600; &:active { opacity: 0.85; } }
.cancel-btn { background: #eef2f7; color: #475569; }

Loading…
Cancel
Save