From ce78df6f54ad55f7e4fe4640239cee6a3d49640c Mon Sep 17 00:00:00 2001
From: liutao <790864623@qq.com>
Date: Fri, 5 Jun 2026 16:19:22 +0800
Subject: [PATCH] =?UTF-8?q?app=E7=AB=AF=E7=82=B9=E6=A3=80=E4=BB=BB?=
=?UTF-8?q?=E5=8A=A1=E5=8F=8A=E7=82=B9=E6=A3=80=E8=AE=B0=E5=BD=95=E5=A2=9E?=
=?UTF-8?q?=E5=8A=A0=E6=9F=A5=E8=AF=A2=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 | 6 +-
src/locales/zh-CN.js | 6 +-
.../pages/equipmentInspectionRecord/index.vue | 172 +++++++++++++++++-
.../pages/equipmentInspectionTasks/index.vue | 139 +++++++++++++-
4 files changed, 306 insertions(+), 17 deletions(-)
diff --git a/src/locales/en-US.js b/src/locales/en-US.js
index 04f1f87..5590b17 100644
--- a/src/locales/en-US.js
+++ b/src/locales/en-US.js
@@ -474,7 +474,8 @@ export default {
searchPlaceholder: 'Enter task name',
empty: 'No equipment inspection tasks',
createTicketSuccess: 'Work order created successfully',
- createTicketFail: 'Work order creation failed'
+ createTicketFail: 'Work order creation failed',
+ lineFilter: 'Line',
},
equipmentInspectionRecord: {
moduleName: 'Equipment Inspection Records',
@@ -515,7 +516,8 @@ export default {
images: 'Images',
maxUploadCount: 'You can upload up to 9 images',
selectAllDecisionError: 'Please choose a result for all pending items',
- noResultData: 'No inspection items'
+ noResultData: 'No inspection items',
+ lineFilter: 'Line',
},
moldWorkOrder: {
moduleName: 'Inspection Records',
diff --git a/src/locales/zh-CN.js b/src/locales/zh-CN.js
index 91f0e4d..a1250c2 100644
--- a/src/locales/zh-CN.js
+++ b/src/locales/zh-CN.js
@@ -474,7 +474,8 @@ export default {
searchPlaceholder: '请输入任务名称',
empty: '暂无设备点检任务数据',
createTicketSuccess: '工单创建成功',
- createTicketFail: '工单创建失败'
+ createTicketFail: '工单创建失败',
+ lineFilter: '产线',
},
equipmentInspectionRecord: {
moduleName: '设备点检记录',
@@ -515,7 +516,8 @@ export default {
images: '图片',
maxUploadCount: '最多上传 9 张图片',
selectAllDecisionError: '请为所有待检项选择结果',
- noResultData: '暂无点检项数据'
+ noResultData: '暂无点检项数据',
+ lineFilter: '产线',
},
moldWorkOrder: {
moduleName: '点检记录',
diff --git a/src/pages_function/pages/equipmentInspectionRecord/index.vue b/src/pages_function/pages/equipmentInspectionRecord/index.vue
index 0f090b8..832da54 100644
--- a/src/pages_function/pages/equipmentInspectionRecord/index.vue
+++ b/src/pages_function/pages/equipmentInspectionRecord/index.vue
@@ -3,6 +3,10 @@
+
+ {{ selectedLineLabel }}
+
+
+
+
+
@@ -81,10 +100,21 @@ import { onLoad, onReachBottom, onShow, onUnload } from '@dcloudio/uni-app'
import { useI18n } from 'vue-i18n'
import NavBar from '@/components/common/NavBar.vue'
import { getEquipmentInspectionRecordPage } from '@/api/mes/equipmentInspectionRecord'
+import { getDeviceLineTree } from '@/api/mes/deviceLine'
import { DICT_TYPE, getDictLabel, initAllDict } from '@/utils/dict'
const { t } = useI18n()
+const selectedLineId = ref('')
+const lineTree = ref([])
+const lineCascaderShow = ref(false)
+const lineCascaderValue = ref([])
+const lineCascaderKey = ref(0)
+const lineCascaderOptions = computed(() => [
+ { label: t('functionCommon.all'), value: '' },
+ ...normalizeLineTreeForCascader(lineTree.value)
+])
+
const searchKeyword = ref('')
const selectedTaskType = ref('')
const selectedJobStatus = ref('')
@@ -100,6 +130,11 @@ const keywordFocus = ref(false)
let searchTimer = null
+const selectedLineLabel = computed(() => {
+ if (selectedLineId.value === '') return t('equipmentInspectionRecord.lineFilter')
+ const found = lineOptions.value.find(item => String(item.id) === String(selectedLineId.value))
+ return found?.name || t('equipmentInspectionRecord.lineFilter')
+})
const taskTypeOptions = computed(() => [
{ label: t('functionCommon.all'), value: '' },
{ label: t('equipmentInspectionRecord.taskTypeInspect'), value: '1' },
@@ -135,19 +170,114 @@ const currentJobStatusLabel = computed(() => {
})
onLoad(async () => {
- activateKeywordFocus()
await initAllDict()
+ await loadLineTree()
await fetchList(true)
})
+
onShow(() => {
activateKeywordFocus()
+ if (!lineTree.value.length) loadLineTree()
})
onUnload(() => {
clearSearchTimer()
})
+async function loadLineTree() {
+ 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 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 resetLineFilter() {
+ selectedLineId.value = ''
+ lineCascaderValue.value = []
+ lineCascaderShow.value = false
+ lineCascaderKey.value += 1
+}
+
+
+const lineOptions = computed(() => {
+ return flattenLineTree(lineTree.value, 1)
+})
+
+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 normalizeLineTree(nodes) {
+ return (Array.isArray(nodes) ? nodes : []).map((node) => {
+ const children = normalizeLineTree(node.children)
+ const item = {
+ ...node,
+ id: String(node.id ?? ''),
+ children
+ }
+ if (!children.length) delete item.children
+ return item
+ })
+}
+
+function normalizeListData(res) {
+ const root = res && res.data !== undefined ? res.data : res
+ if (Array.isArray(root)) return root
+ if (Array.isArray(res)) return res
+ if (root?.list && Array.isArray(root.list)) return root.list
+ if (root?.rows && Array.isArray(root.rows)) return root.rows
+ if (root?.records && Array.isArray(root.records)) return root.records
+ if (root?.data?.list && Array.isArray(root.data.list)) return root.data.list
+ if (root?.data?.rows && Array.isArray(root.data.rows)) return root.data.rows
+ if (root?.data?.records && Array.isArray(root.data.records)) return root.data.records
+ if (Array.isArray(root?.children)) return root.children
+ if (Array.isArray(root?.data)) return root.data
+ const keys = root ? Object.keys(root) : []
+ for (let i = 0; i < keys.length; i++) {
+ if (Array.isArray(root[keys[i]])) return root[keys[i]]
+ }
+ return []
+}
+
onReachBottom(() => {
loadMore()
})
@@ -168,9 +298,10 @@ async function fetchList(reset) {
const params = {
pageNo: pageNo.value,
pageSize: pageSize.value,
- planNo: searchKeyword.value.trim() || undefined,
+ planNo: searchKeyword.value.trim() || undefined,
planType: selectedTaskType.value || undefined,
- jobStatus: selectedJobStatus.value || undefined
+ jobStatus: selectedJobStatus.value || undefined,
+ deviceLineId: selectedLineId.value || undefined
}
const res = await getEquipmentInspectionRecordPage(params)
const page = normalizePageData(res)
@@ -213,6 +344,7 @@ async function resetFilters() {
searchKeyword.value = ''
selectedTaskType.value = ''
selectedJobStatus.value = ''
+ resetLineFilter()
activateKeywordFocus()
await nextTick()
await fetchList(true)
@@ -329,23 +461,45 @@ function formatDateTime(value) {
.page-container { min-height: 100vh; background: #f4f5f7; }
.filter-bar {
display: grid;
- grid-template-columns: minmax(0, 0.9fr) 136rpx 136rpx 88rpx;
+ grid-template-columns: minmax(0, 1fr) 136rpx 136rpx 88rpx;
align-items: center;
gap: 10rpx;
- padding: 18rpx 20rpx 20rpx;
+ padding: 18rpx 4rpx 0rpx;
}
+.line-filter,
.keyword-box,
.status-box,
.reset-filter-btn {
- height: 64rpx;
+ height: 66rpx;
background: #ffffff;
border: 1rpx solid #d9dde5;
box-sizing: border-box;
display: flex;
align-items: center;
}
+
+.line-filter {
+ grid-column: 1 / -1;
+ justify-content: space-between;
+ padding: 0 28rpx;
+ 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 16rpx;
+ padding: 0 28rpx;
}
.keyword-input {
width: 100%;
@@ -354,7 +508,7 @@ function formatDateTime(value) {
}
.status-box {
justify-content: space-between;
- padding: 0 14rpx;
+ padding: 0 28rpx;
}
.status-box-text {
font-size: 24rpx;
@@ -370,7 +524,7 @@ function formatDateTime(value) {
color: #4b5563;
}
.list-scroll { height: calc(100vh - 194rpx); }
-.list-wrap { padding: 0 24rpx 32rpx; }
+.list-wrap { padding: 0 4rpx 32rpx; }
.task-card { position: relative; margin-top: 20rpx; padding: 28rpx; background: #fff; border-radius: 22rpx; box-shadow: 0 8rpx 28rpx rgba(15, 23, 42, 0.06); }
.card-header { margin-bottom: 18rpx; }
.header-main { display: flex; align-items: center; justify-content: space-between; gap: 16rpx; }
diff --git a/src/pages_function/pages/equipmentInspectionTasks/index.vue b/src/pages_function/pages/equipmentInspectionTasks/index.vue
index 88236ec..ba726ed 100644
--- a/src/pages_function/pages/equipmentInspectionTasks/index.vue
+++ b/src/pages_function/pages/equipmentInspectionTasks/index.vue
@@ -3,6 +3,10 @@
+
+ {{ selectedLineLabel }}
+
+
+
@@ -69,6 +86,7 @@ import { onLoad, onReachBottom, onShow, onUnload } from '@dcloudio/uni-app'
import { useI18n } from 'vue-i18n'
import NavBar from '@/components/common/NavBar.vue'
import { getTaskManagementPage, createTaskManagementTicket } from '@/api/mes/taskManagement'
+import { getDeviceLineTree } from '@/api/mes/deviceLine'
import { getDeviceLedgerList } from '@/api/mes/deviceLedger'
const { t } = useI18n()
@@ -86,6 +104,26 @@ const showGoTop = ref(false)
const ticketLoadingId = ref(null)
const deviceOptions = ref([])
const keywordFocus = ref(false)
+const selectedLineId = ref('')
+const lineTree = ref([])
+const lineCascaderShow = ref(false)
+const lineCascaderValue = ref([])
+const lineCascaderKey = ref(0)
+
+const lineCascaderOptions = computed(() => [
+ { label: t('functionCommon.all'), value: '' },
+ ...normalizeLineTreeForCascader(lineTree.value)
+])
+
+const selectedLineLabel = computed(() => {
+ if (selectedLineId.value === '') return t('equipmentInspectionTasks.lineFilter')
+ const found = lineOptions.value.find(item => String(item.id) === String(selectedLineId.value))
+ return found?.name || t('equipmentInspectionTasks.lineFilter')
+})
+
+const lineOptions = computed(() => {
+ return flattenLineTree(lineTree.value, 1)
+})
let searchTimer = null
@@ -107,7 +145,7 @@ const currentTaskTypeLabel = computed(() => {
onLoad(async () => {
activateKeywordFocus()
- await Promise.all([ensureDeviceOptionsLoaded(), fetchList(true)])
+ await Promise.all([loadLineTree(), ensureDeviceOptionsLoaded(), fetchList(true)])
})
onShow(() => {
@@ -157,7 +195,8 @@ async function fetchList(reset) {
pageNo: pageNo.value,
pageSize: pageSize.value,
name: searchKeyword.value.trim() || undefined,
- taskType: selectedTaskType.value || undefined
+ taskType: selectedTaskType.value || undefined,
+ deviceLineId: selectedLineId.value || undefined
}
const res = await getTaskManagementPage(params)
const page = normalizePageData(res)
@@ -172,6 +211,76 @@ async function fetchList(reset) {
}
}
+async function loadLineTree() {
+ 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 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 resetLineFilter() {
+ selectedLineId.value = ''
+ lineCascaderValue.value = []
+ lineCascaderShow.value = false
+ lineCascaderKey.value += 1
+}
+
+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 normalizeLineTree(nodes) {
+ return (Array.isArray(nodes) ? nodes : []).map((node) => {
+ const children = normalizeLineTree(node.children)
+ const item = {
+ ...node,
+ id: String(node.id ?? ''),
+ children
+ }
+ if (!children.length) delete item.children
+ return item
+ })
+}
+
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 || []
@@ -199,6 +308,7 @@ async function resetFilters() {
clearSearchTimer()
searchKeyword.value = ''
selectedTaskType.value = ''
+ resetLineFilter()
activateKeywordFocus()
await nextTick()
await fetchList(true)
@@ -320,8 +430,9 @@ function formatDate(value) {
grid-template-columns: minmax(0, 1fr) 150rpx 96rpx;
align-items: center;
gap: 14rpx;
- padding: 18rpx 28rpx 20rpx;
+ padding: 18rpx 4rpx 0rpx;
}
+.line-filter,
.keyword-box,
.status-box,
.reset-filter-btn {
@@ -332,6 +443,26 @@ function formatDate(value) {
display: flex;
align-items: center;
}
+.line-filter {
+ grid-column: 1 / -1;
+ justify-content: space-between;
+ padding: 0 28rpx;
+ 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;
}
@@ -354,7 +485,7 @@ function formatDate(value) {
color: #4b5563;
}
.list-scroll { height: calc(100vh - 194rpx); }
-.list-wrap { padding: 0 24rpx 32rpx; }
+.list-wrap { padding: 0 4rpx 32rpx; }
.task-card { position: relative; margin-top: 20rpx; padding: 28rpx; background: #fff; border-radius: 22rpx; box-shadow: 0 8rpx 28rpx rgba(15, 23, 42, 0.06); }
.card-header { margin-bottom: 18rpx; }
.header-main { display: flex; align-items: center; justify-content: space-between; gap: 16rpx; }