diff --git a/src/api/mes/taskManagement.js b/src/api/mes/taskManagement.js
index 94b4d89..3e9210c 100644
--- a/src/api/mes/taskManagement.js
+++ b/src/api/mes/taskManagement.js
@@ -15,3 +15,20 @@ export function createTaskManagementTicket(id) {
params: { id }
})
}
+
+
+export function getPlanMaintenancePage(params = {}) {
+ return request({
+ url: '/admin-api/mes/plan-maintenance/page',
+ method: 'get',
+ params
+ })
+}
+
+export function getPlanMaintenanceSubjectList(id) {
+ return request({
+ url: '/admin-api/mes/plan-maintenance/getSubjectList',
+ method: 'get',
+ params: { id }
+ })
+}
diff --git a/src/locales/en-US.js b/src/locales/en-US.js
index 4130779..991503e 100644
--- a/src/locales/en-US.js
+++ b/src/locales/en-US.js
@@ -526,7 +526,21 @@ export default {
empty: 'No equipment inspection tasks',
createTicketSuccess: 'Work order created successfully',
createTicketFail: 'Work order creation failed',
- lineFilter: 'Line',
},
+ lineFilter: 'Line',
moreFilter: 'More Filters',
+ filterScope: 'Filter Scope',
+ placeholderProjectForm: 'Select inspection template',
+ placeholderDeviceList: 'Select equipment',
+ selectedCount: '{count} selected',
+ noPlanData: 'No inspection templates',
+ noDeviceData: 'No equipment data',
+ confirmCreateTicketContent: 'Create a work order from \"{name}\"?',
+ subjectListTitle: 'Template Items',
+ noSubjectData: 'No template items',
+ subjectCode: 'Item Code',
+ subjectName: 'Item Name',
+ inspectionMethod: 'Inspection Method',
+ judgmentCriteria: 'Criteria',
+ },
equipmentInspectionRecord: {
moduleName: 'Equipment Inspection Records',
subTitle: 'Equipment inspection record list',
diff --git a/src/locales/zh-CN.js b/src/locales/zh-CN.js
index b877cbb..238e22a 100644
--- a/src/locales/zh-CN.js
+++ b/src/locales/zh-CN.js
@@ -526,7 +526,21 @@ export default {
empty: '暂无设备点检任务数据',
createTicketSuccess: '工单创建成功',
createTicketFail: '工单创建失败',
- lineFilter: '产线',
},
+ lineFilter: '产线',
moreFilter: '更多筛选',
+ filterScope: '筛选范围',
+ placeholderProjectForm: '请选择点检模板',
+ placeholderDeviceList: '请选择设备',
+ selectedCount: '已选择 {count} 项',
+ noPlanData: '暂无点检模板',
+ noDeviceData: '暂无设备数据',
+ confirmCreateTicketContent: '确认根据\"{name}\"新增工单吗?',
+ subjectListTitle: '模板项目',
+ noSubjectData: '暂无模板项目',
+ subjectCode: '项目编码',
+ subjectName: '项目名称',
+ inspectionMethod: '点检方式',
+ judgmentCriteria: '判定标准',
+ },
equipmentInspectionRecord: {
moduleName: '设备点检记录',
subTitle: '设备点检记录查询',
diff --git a/src/pages_function/pages/equipmentInspectionTasks/detail.vue b/src/pages_function/pages/equipmentInspectionTasks/detail.vue
index bc49eee..6e0659f 100644
--- a/src/pages_function/pages/equipmentInspectionTasks/detail.vue
+++ b/src/pages_function/pages/equipmentInspectionTasks/detail.vue
@@ -53,6 +53,35 @@
{{ formatDateTime(detailData.updateTime) }}
+
+
+ {{ t('equipmentInspectionTasks.subjectListTitle') }}
+ {{ t('functionCommon.loading') }}
+ {{ t('equipmentInspectionTasks.noSubjectData') }}
+
+
+ {{ index + 1 }}
+
+
+ {{ t('equipmentInspectionTasks.subjectCode') }}
+ {{ textValue(item.subjectCode) }}
+
+
+ {{ t('equipmentInspectionTasks.subjectName') }}
+ {{ textValue(item.subjectName) }}
+
+
+ {{ t('equipmentInspectionTasks.inspectionMethod') }}
+ {{ inspectionMethodText(item.inspectionMethod) }}
+
+
+ {{ t('equipmentInspectionTasks.judgmentCriteria') }}
+ {{ textValue(item.judgmentCriteria) }}
+
+
+
+
+
@@ -69,13 +98,16 @@ import { computed, reactive, ref } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import { useI18n } from 'vue-i18n'
import NavBar from '@/components/common/NavBar.vue'
-import { createTaskManagementTicket } from '@/api/mes/taskManagement'
+import { createTaskManagementTicket, getPlanMaintenanceSubjectList } from '@/api/mes/taskManagement'
import { getDeviceLedgerList } from '@/api/mes/deviceLedger'
+import { DICT_TYPE, getDictLabel, initAllDict } from '@/utils/dict'
const { t } = useI18n()
const detailData = reactive({})
const ticketLoading = ref(false)
const deviceOptions = ref([])
+const subjectList = ref([])
+const subjectLoading = ref(false)
const taskTypeText = computed(() => {
const normalized = Number(detailData.taskType)
if (normalized === 1) return t('equipmentInspectionTasks.taskTypeInspect')
@@ -120,6 +152,38 @@ function parseIdsValue(value) {
return String(value).split(',').map((item) => item.trim()).filter(Boolean)
}
+function firstIdValue(value) {
+ return parseIdsValue(value)[0] || ''
+}
+
+function inspectionMethodText(value) {
+ return getDictLabel(DICT_TYPE.INSPECTION_METHOD, value, textValue(value))
+}
+
+function normalizeListData(res) {
+ const root = res && res.data !== undefined ? res.data : res
+ const data = Array.isArray(root) ? root : (root?.list || root?.data?.list || root?.records || root?.data || [])
+ return Array.isArray(data) ? data : []
+}
+
+async function loadSubjectList() {
+ const planId = firstIdValue(detailData.projectForm)
+ if (!planId) {
+ subjectList.value = []
+ return
+ }
+ subjectLoading.value = true
+ try {
+ const res = await getPlanMaintenanceSubjectList(planId)
+ subjectList.value = normalizeListData(res)
+ } catch (error) {
+ subjectList.value = []
+ uni.showToast({ title: t('functionCommon.loadFailed'), icon: 'none' })
+ } finally {
+ subjectLoading.value = false
+ }
+}
+
onLoad(async () => {
try {
const cached = uni.getStorageSync('equipmentInspectionTasksDetail')
@@ -127,22 +191,30 @@ onLoad(async () => {
Object.assign(detailData, JSON.parse(cached))
uni.removeStorageSync('equipmentInspectionTasksDetail')
}
- await Promise.all([ensureDeviceOptionsLoaded()])
+ await initAllDict()
+ await Promise.all([ensureDeviceOptionsLoaded(), loadSubjectList()])
} catch (error) {
}
})
async function handleCreateTicket() {
if (!detailData.id || ticketLoading.value) return
- ticketLoading.value = true
- try {
- await createTaskManagementTicket(detailData.id)
- uni.showToast({ title: t('equipmentInspectionTasks.createTicketSuccess'), icon: 'success' })
- } catch (error) {
- uni.showToast({ title: t('equipmentInspectionTasks.createTicketFail'), icon: 'none' })
- } finally {
- ticketLoading.value = false
- }
+ uni.showModal({
+ title: t('functionCommon.confirmTitle'),
+ content: t('equipmentInspectionTasks.confirmCreateTicketContent', { name: textValue(detailData.name) }),
+ success: async (res) => {
+ if (!res.confirm) return
+ ticketLoading.value = true
+ try {
+ await createTaskManagementTicket(detailData.id)
+ uni.showToast({ title: t('equipmentInspectionTasks.createTicketSuccess'), icon: 'success' })
+ } catch (error) {
+ uni.showToast({ title: t('equipmentInspectionTasks.createTicketFail'), icon: 'none' })
+ } finally {
+ ticketLoading.value = false
+ }
+ }
+ })
}
function isEnabled(value) {
@@ -219,4 +291,12 @@ function formatDateTime(value) {
.action-btn-disabled {
background: #94a3b8;
}
+.hint { text-align: center; color: #909399; padding: 24rpx 0; font-size: 26rpx; }
+.subject-list { display: flex; flex-direction: column; gap: 16rpx; }
+.subject-card { display: flex; background: #f7f9fc; border-radius: 14rpx; padding: 20rpx; gap: 16rpx; }
+.subject-index { min-width: 48rpx; height: 48rpx; border-radius: 10rpx; background: #1a3a5c; color: #fff; display: flex; align-items: center; justify-content: center; font-size: 24rpx; font-weight: 700; }
+.subject-body { flex: 1; display: flex; flex-direction: column; gap: 8rpx; }
+.subject-row { display: flex; justify-content: space-between; align-items: center; }
+.subject-label { font-size: 24rpx; color: #8a9099; }
+.subject-value { font-size: 26rpx; color: #30363d; max-width: 60%; text-align: right; }
diff --git a/src/pages_function/pages/equipmentInspectionTasks/index.vue b/src/pages_function/pages/equipmentInspectionTasks/index.vue
index cab54c0..64dfa73 100644
--- a/src/pages_function/pages/equipmentInspectionTasks/index.vue
+++ b/src/pages_function/pages/equipmentInspectionTasks/index.vue
@@ -3,28 +3,37 @@
-
- {{ selectedLineLabel }}
-
-
-
-
+
+
+ {{ selectedLineLabel }}
+
+
+
+
+ {{ currentTaskTypeLabel }}
+
+
+
-
-
- {{ currentTaskTypeLabel }}
-
+
+
+
+
+
+
+
+
+
-
- {{ t('functionCommon.reset') }}
+
@@ -63,6 +72,60 @@
+
+
+
{
let searchTimer = null
const taskTypeOptions = computed(() => [
- { label: t('functionCommon.all'), value: '' },
{ label: t('equipmentInspectionTasks.taskTypeInspect'), value: '1' },
{ label: t('equipmentInspectionTasks.taskTypeMaintain'), value: '2' }
])
@@ -141,13 +209,28 @@ const taskTypeIndex = computed(() => {
return index >= 0 ? index : 0
})
const currentTaskTypeLabel = computed(() => {
+ if (selectedTaskType.value === '') return t('equipmentInspectionTasks.taskType')
const current = taskTypeOptions.value.find((item) => item.value === selectedTaskType.value)
- return current ? current.label : t('functionCommon.all')
+ return current ? current.label : t('equipmentInspectionTasks.taskType')
})
+const drawerPlanOptions = computed(() => planOptions.value.map((item) => ({
+ id: String(item.id),
+ name: item.planName || item.name || String(item.id || '')
+})))
+
+const drawerDeviceOptions = computed(() => deviceOptions.value.map((item) => ({
+ id: String(item.id),
+ label: item.label || item.deviceName || String(item.id || '')
+})))
+
+const selectedPlanLabel = computed(() => formatSelectedSummary(selectedPlanIds.value, drawerPlanOptions.value, 'name', t('equipmentInspectionTasks.placeholderProjectForm')))
+const selectedDeviceLabel = computed(() => formatSelectedSummary(selectedDeviceIds.value, drawerDeviceOptions.value, 'label', t('equipmentInspectionTasks.placeholderDeviceList')))
+
onLoad(async () => {
activateKeywordFocus()
- await Promise.all([loadLineTree(), ensureDeviceOptionsLoaded(), fetchList(true)])
+ await Promise.all([loadLineTree(), ensurePlanOptionsLoaded(), ensureDeviceOptionsLoaded()])
+ await fetchList(true)
})
onShow(() => {
@@ -168,6 +251,17 @@ onReachBottom(() => {
loadMore()
})
+async function ensurePlanOptionsLoaded() {
+ try {
+ const res = await getPlanMaintenancePage({ pageNo: 1, pageSize: 100 })
+ const root = res && res.data !== undefined ? res.data : res
+ const data = Array.isArray(root) ? root : (root?.list || root?.data?.list || root?.records || [])
+ planOptions.value = (Array.isArray(data) ? data : []).filter((item) => item && item.id !== undefined && item.id !== null)
+ } catch (error) {
+ planOptions.value = []
+ }
+}
+
async function ensureDeviceOptionsLoaded() {
try {
const res = await getDeviceLedgerList()
@@ -205,8 +299,9 @@ async function fetchList(reset) {
pageNo: pageNo.value,
pageSize: pageSize.value,
name: deviceId ? undefined : keyword || undefined,
- deviceIds: deviceId ? [deviceId] : undefined,
+ deviceIds: selectedDeviceIds.value.length ? selectedDeviceIds.value.join(',') : (deviceId ? [deviceId] : undefined),
taskType: selectedTaskType.value || undefined,
+ projectForm: selectedPlanIds.value.length ? selectedPlanIds.value.join(',') : undefined,
deviceLineId: selectedLineId.value || undefined
}
const res = await getTaskManagementPage(params)
@@ -307,6 +402,56 @@ function normalizePageData(res) {
}
}
+function openFilterDrawer() {
+ filterPopupRef.value?.open()
+}
+
+function closeFilterDrawer() {
+ filterPopupRef.value?.close()
+}
+
+async function confirmFilterDrawer() {
+ planPanelOpen.value = false
+ devicePanelOpen.value = false
+ closeFilterDrawer()
+ await fetchList(true)
+}
+
+function togglePlanPanel() {
+ planPanelOpen.value = !planPanelOpen.value
+ devicePanelOpen.value = false
+}
+
+function toggleDevicePanel() {
+ devicePanelOpen.value = !devicePanelOpen.value
+ planPanelOpen.value = false
+}
+
+function togglePlanOption(option) {
+ toggleStringSelection(selectedPlanIds, option?.id)
+}
+
+function toggleDeviceOption(option) {
+ toggleStringSelection(selectedDeviceIds, option?.id)
+}
+
+function toggleStringSelection(targetRef, value) {
+ const id = String(value ?? '')
+ if (!id) return
+ const current = targetRef.value.map((item) => String(item))
+ targetRef.value = current.includes(id) ? current.filter((item) => item !== id) : [...current, id]
+}
+
+function formatSelectedSummary(ids, options, labelKey, placeholder) {
+ const selected = Array.isArray(ids) ? ids : []
+ if (!selected.length) return placeholder
+ if (selected.length === 1) {
+ const found = options.find((item) => String(item.id) === String(selected[0]))
+ return found?.[labelKey] || placeholder
+ }
+ return t('equipmentInspectionTasks.selectedCount', { count: selected.length })
+}
+
function handleSearch() {
clearSearchTimer()
uni.hideKeyboard()
@@ -324,6 +469,11 @@ async function resetFilters() {
clearSearchTimer()
searchKeyword.value = ''
selectedTaskType.value = ''
+ selectedPlanIds.value = []
+ selectedDeviceIds.value = []
+ planPanelOpen.value = false
+ devicePanelOpen.value = false
+ closeFilterDrawer()
resetLineFilter()
activateKeywordFocus()
await nextTick()
@@ -355,15 +505,22 @@ function openDetail(item) {
async function handleCreateTicket(item) {
if (!item?.id || ticketLoadingId.value) return
- ticketLoadingId.value = item.id
- try {
- await createTaskManagementTicket(item.id)
- uni.showToast({ title: t('equipmentInspectionTasks.createTicketSuccess'), icon: 'success' })
- } catch (error) {
- uni.showToast({ title: t('equipmentInspectionTasks.createTicketFail'), icon: 'none' })
- } finally {
- ticketLoadingId.value = null
- }
+ uni.showModal({
+ title: t('functionCommon.confirmTitle'),
+ content: t('equipmentInspectionTasks.confirmCreateTicketContent', { name: textValue(item.name) }),
+ success: async (res) => {
+ if (!res.confirm) return
+ ticketLoadingId.value = item.id
+ try {
+ await createTaskManagementTicket(item.id)
+ uni.showToast({ title: t('equipmentInspectionTasks.createTicketSuccess'), icon: 'success' })
+ } catch (error) {
+ uni.showToast({ title: t('equipmentInspectionTasks.createTicketFail'), icon: 'none' })
+ } finally {
+ ticketLoadingId.value = null
+ }
+ }
+ })
}
function onScroll(event) {
@@ -446,65 +603,50 @@ function formatDate(value) {