From 818f7737e7396142378dd0c881a4b81950f69a8a Mon Sep 17 00:00:00 2001 From: liutao <790864623@qq.com> Date: Thu, 4 Jun 2026 14:48:38 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=AE=BE=E5=A4=87=E7=BB=B4?= =?UTF-8?q?=E4=BF=AE=E5=A2=9E=E5=8A=A0=E6=9D=A1=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/locales/en-US.js | 1 + src/locales/zh-CN.js | 1 + .../pages/equipmentMaintenance/index.vue | 299 +++++++++++------- 3 files changed, 195 insertions(+), 106 deletions(-) diff --git a/src/locales/en-US.js b/src/locales/en-US.js index bde9954..04f1f87 100644 --- a/src/locales/en-US.js +++ b/src/locales/en-US.js @@ -951,6 +951,7 @@ export default { validatorFaultLevelRequired: 'Please select the failure level', validatorIsShutdownRequired: 'Please select whether shutdown is required', validatorFaultPhenomenonRequired: 'Please enter the fault phenomenon', + lineFilter: 'Line', validatorRepairStatusRequired: 'Please select the repair result', validatorFinishDateRequired: 'Please select the completion date', validatorConfirmDateRequired: 'Please select the acceptance date' diff --git a/src/locales/zh-CN.js b/src/locales/zh-CN.js index d67bf32..91f0e4d 100644 --- a/src/locales/zh-CN.js +++ b/src/locales/zh-CN.js @@ -954,6 +954,7 @@ export default { validatorFaultLevelRequired: '请选择故障等级', validatorIsShutdownRequired: '请选择是否停机', validatorFaultPhenomenonRequired: '请输入故障现象', + lineFilter: '产线', validatorRepairStatusRequired: '请选择维修结果', validatorFinishDateRequired: '请选择完成日期', validatorConfirmDateRequired: '请选择验收日期' diff --git a/src/pages_function/pages/equipmentMaintenance/index.vue b/src/pages_function/pages/equipmentMaintenance/index.vue index 4943ba0..624d7f4 100644 --- a/src/pages_function/pages/equipmentMaintenance/index.vue +++ b/src/pages_function/pages/equipmentMaintenance/index.vue @@ -3,6 +3,10 @@ + + {{ selectedLineLabel }} + + {{ t('functionCommon.reset') }} - - - + + + @@ -93,10 +108,16 @@ import { deleteDvRepair, getDvRepairPage } from '@/api/mes/dvrepair' +import { getDeviceLineTree } from '@/api/mes/deviceLine' const { t } = useI18n() const searchKeyword = ref('') const selectedStatus = ref('') +const selectedLineId = ref('') +const lineTree = ref([]) +const lineCascaderShow = ref(false) +const lineCascaderValue = ref([]) +const lineCascaderKey = ref(0) const list = ref([]) const loading = ref(false) const loadingMore = ref(false) @@ -108,7 +129,6 @@ const initialized = ref(false) const scrollTop = ref(0) const showGoTop = ref(false) const keywordFocus = ref(false) -const selectedMachineryId = ref('') const statusOptions = computed(() => [ { label: t('functionCommon.all'), value: '' }, @@ -127,21 +147,86 @@ const selectedStatusLabel = computed(() => { return current ? current.label : t('functionCommon.all') }) -onLoad(async () => { - initialized.value = true - activateKeywordFocus() - await fetchList(true) +const selectedLineLabel = computed(() => { + if (selectedLineId.value === '') return t('equipmentMaintenance.lineFilter') + const found = lineOptions.value.find(item => String(item.id) === String(selectedLineId.value)) + return found?.name || t('equipmentMaintenance.lineFilter') }) -onShow(async () => { - activateKeywordFocus() - if (!initialized.value) return - await fetchList(true) +const lineOptions = computed(() => { + return flattenLineTree(lineTree.value, 1) }) -onReachBottom(() => { - loadMore() -}) +const lineCascaderOptions = computed(() => [ + { label: t('functionCommon.all'), value: '' }, + ...normalizeLineTreeForCascader(lineTree.value) +]) + +function flattenLineTree(nodes, level) { + const result = [] + ;(Array.isArray(nodes) ? nodes : []).forEach((node) => { + result.push({ + id: node.id, + name: node.name || node.label || String(node.id || ''), + level + }) + if (Array.isArray(node.children) && node.children.length) { + result.push(...flattenLineTree(node.children, level + 1)) + } + }) + return result +} + +function normalizeLineTreeForCascader(nodes) { + return (Array.isArray(nodes) ? nodes : []).map((node) => { + const children = normalizeLineTreeForCascader(node.children) + const item = { + label: node.name || node.label || String(node.id || ''), + value: String(node.id ?? '') + } + if (children.length) item.children = children + return item + }) +} + +function findLinePath(nodes, id, parents = []) { + const target = String(id) + for (const node of Array.isArray(nodes) ? nodes : []) { + const currentPath = [...parents, String(node.id ?? '')] + if (String(node.id) === target) return currentPath + const childPath = findLinePath(node.children, id, currentPath) + if (childPath.length) return childPath + } + return [] +} + +async function fetchDeviceLineTree() { + try { + const res = await getDeviceLineTree() + const root = res && res.data !== undefined ? res.data : res + const treeData = Array.isArray(root) ? root : (Array.isArray(root?.data) ? root.data : []) + lineTree.value = normalizeLineTree(treeData) + } catch (_) { + lineTree.value = [] + } +} + +function normalizeLineTree(nodes) { + return (Array.isArray(nodes) ? nodes : []).map((node) => { + const children = normalizeLineTree(node.children) + const item = { + ...node, + id: String(node.id ?? ''), + name: node.name || node.label || String(node.id || '') + } + if (children.length) { + item.children = children + } else { + delete item.children + } + return item + }) +} async function fetchList(reset) { if (reset) { @@ -162,35 +247,50 @@ async function fetchList(reset) { pageSize: pageSize.value, repairCode: keyword || undefined, machineryCode: keyword || undefined, - machineryId: selectedMachineryId.value || undefined, + deviceLine: selectedLineId.value === '' ? undefined : selectedLineId.value, repairStatus: selectedStatus.value === '' ? undefined : selectedStatus.value } const res = await getDvRepairPage(params) - const page = normalizePageData(res) - total.value = page.total - list.value = reset ? page.list : [...list.value, ...page.list] - finished.value = list.value.length >= total.value || page.list.length < pageSize.value - } catch (error) { - if (!reset) { - pageNo.value = Math.max(1, pageNo.value - 1) - } - uni.showToast({ title: t('functionCommon.loadFailed'), icon: 'none' }) + const root = res && res.data !== undefined ? res.data : res + const candidateList = root?.list || root?.rows || root?.records || root?.data?.list || root?.data?.rows || root?.data?.records || [] + const candidateTotal = root?.total ?? root?.data?.total ?? (Array.isArray(candidateList) ? candidateList.length : 0) + onFetchResult({ list: Array.isArray(candidateList) ? candidateList : [], total: Number(candidateTotal || 0) }) + } catch (e) { + onFetchResult({ list: [], total: 0 }) + if (!reset) pageNo.value = Math.max(1, pageNo.value - 1) } finally { loading.value = false loadingMore.value = false } } -function normalizePageData(res) { - const root = res && res.data !== undefined ? res.data : res - const candidateList = root?.list || root?.rows || root?.records || root?.data?.list || root?.data?.rows || root?.data?.records || [] - const candidateTotal = root?.total ?? root?.data?.total ?? (Array.isArray(candidateList) ? candidateList.length : 0) - return { - list: Array.isArray(candidateList) ? candidateList : [], - total: Number(candidateTotal || 0) +function onFetchResult(result) { + const data = result || { list: [], total: 0 } + if (pageNo.value === 1) { + list.value = data.list + } else { + list.value = list.value.concat(data.list) } + total.value = data.total + const loadedCount = list.value.length + finished.value = loadedCount >= total.value || data.list.length < pageSize.value } +onLoad(async () => { + initialized.value = true + await fetchDeviceLineTree() + await fetchList(true) +}) + +onShow(async () => { + if (!initialized.value) return + await fetchList(true) +}) + +onReachBottom(() => { + loadMore() +}) + function activateKeywordFocus() { keywordFocus.value = false nextTick(() => { @@ -203,10 +303,25 @@ function handleSearch() { fetchList(true) } +function openLineCascader() { + lineCascaderShow.value = true +} + +function onLineCascaderConfirm(values) { + const selectedValues = Array.isArray(values) ? values : [] + const nextValue = selectedValues[selectedValues.length - 1] ?? '' + selectedLineId.value = nextValue === '' ? '' : String(nextValue) + lineCascaderValue.value = nextValue === '' ? [] : selectedValues.map(item => String(item)) + fetchList(true) +} + async function resetFilters() { searchKeyword.value = '' selectedStatus.value = '' - selectedMachineryId.value = '' + selectedLineId.value = '' + lineCascaderValue.value = [] + lineCascaderShow.value = false + lineCascaderKey.value += 1 activateKeywordFocus() await fetchList(true) } @@ -217,51 +332,6 @@ function onStatusFilterChange(event) { fetchList(true) } -async function handleScan() { - try { - const res = await uni.scanCode({ scanType: ['qrCode', 'barCode'] }) - const result = String(res?.result || '').trim() - if (!result) { - uni.showToast({ title: t('equipmentMaintenance.scanUnrecognized'), icon: 'none' }) - return - } - const scan = parseEquipmentScanResult(result) - if (!scan.id) { - uni.showToast({ title: t('equipmentMaintenance.scanEquipmentRequired'), icon: 'none' }) - return - } - selectedMachineryId.value = scan.id - searchKeyword.value = '' - await fetchList(true) - } catch (error) { - const message = String(error?.errMsg || '') - if (message.includes('cancel')) return - uni.showToast({ title: t('equipmentMaintenance.scanFailed'), icon: 'none' }) - } -} - -function parseEquipmentScanResult(result) { - const text = String(result || '').trim() - const directMatch = text.match(/^([A-Z_]+)-(\d+)$/i) - if (directMatch) { - return { - type: directMatch[1].toUpperCase(), - id: directMatch[1].toUpperCase() === 'EQUIPMENT' ? directMatch[2] : '' - } - } - try { - const parsed = JSON.parse(text) - const type = String(parsed?.type || parsed?.bizType || parsed?.codeType || '').toUpperCase() - const id = String(parsed?.id || parsed?.machineryId || parsed?.deviceId || '').trim() - return { - type, - id: type === 'EQUIPMENT' && id ? id : '' - } - } catch { - return { type: '', id: '' } - } -} - function canEdit(item) { return !isProcessedRepair(item?.repairStatus) } @@ -410,16 +480,16 @@ function textValue(value) { .filter-bar { display: grid; - grid-template-columns: minmax(0, 1fr) 150rpx 96rpx 64rpx; + grid-template-columns: minmax(0, 1fr) 150rpx 110rpx; align-items: center; gap: 14rpx; - padding: 18rpx 4rpx 20rpx; + padding: 18rpx 4rpx 16rpx; } +.line-filter, .keyword-box, .status-box, -.reset-filter-btn, -.scan-btn { +.reset-filter-btn { height: 66rpx; background: #ffffff; border: 1rpx solid #d9dde5; @@ -428,6 +498,26 @@ function textValue(value) { align-items: center; } +.line-filter { + grid-column: 1 / -1; + justify-content: space-between; + padding: 0 18rpx; + border-radius: 8rpx; +} + +.line-filter-text { + font-size: 26rpx; + color: #374151; + max-width: 85%; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.line-filter-text.placeholder { + color: #a8adb7; +} + .keyword-box { padding: 0 20rpx; } @@ -456,19 +546,14 @@ function textValue(value) { color: #a8adb7; } -.scan-btn { - display: flex; - align-items: center; - justify-content: center; - background: #ffffff; -} - .reset-filter-btn { display: flex; align-items: center; justify-content: center; font-size: 24rpx; color: #4b5563; + border-radius: 8rpx; + cursor: pointer; } .list-scroll { @@ -480,15 +565,15 @@ function textValue(value) { } .repair-card { - margin-bottom: 18rpx; - border-radius: 12rpx; + margin-bottom: 20rpx; + border-radius: 16rpx; background: #ffffff; - box-shadow: none; + box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.06); overflow: hidden; } .card-main { - padding: 24rpx; + padding: 28rpx 24rpx; } .card-top, @@ -500,9 +585,9 @@ function textValue(value) { } .repair-code { - max-width: 420rpx; - font-size: 36rpx; - line-height: 44rpx; + max-width: 460rpx; + font-size: 32rpx; + line-height: 42rpx; color: #24456b; font-weight: 700; } @@ -514,9 +599,9 @@ function textValue(value) { } .repair-status-tag { - padding: 8rpx 18rpx; + padding: 6rpx 20rpx; border-radius: 999rpx; - font-size: 24rpx; + font-size: 22rpx; font-weight: 600; line-height: 1.2; } @@ -537,21 +622,22 @@ function textValue(value) { align-items: center; justify-content: space-between; gap: 20rpx; - margin-top: 14rpx; + margin-top: 16rpx; } .equipment-label { - font-size: 28rpx; + font-size: 26rpx; color: #9ca3af; - font-weight: 600; + font-weight: 500; flex-shrink: 0; } .equipment-value { flex: 1; text-align: right; - font-size: 30rpx; + font-size: 28rpx; color: #9ca3af; + font-weight: 500; } .text-warning { @@ -605,8 +691,8 @@ function textValue(value) { } .card-actions { - padding: 18rpx 24rpx; - border-top: 1rpx solid #f1f5f9; + padding: 16rpx 24rpx; + border-top: 1rpx solid #f0f2f5; justify-content: flex-end; gap: 28rpx; } @@ -627,7 +713,7 @@ function textValue(value) { } .state-text.empty { - padding-top: 160rpx; + padding-top: 200rpx; } .add-btn, @@ -647,6 +733,7 @@ function textValue(value) { right: 28rpx; bottom: calc(56rpx + env(safe-area-inset-bottom)); background: #1f4b79; + box-shadow: 0 8rpx 24rpx rgba(31, 75, 121, 0.35); } .go-top-btn { @@ -660,4 +747,4 @@ function textValue(value) { line-height: 1; margin-top: -4rpx; } - \ No newline at end of file +