Prechádzať zdrojové kódy

Merge remote-tracking branch 'origin/master'

lipenghui 2 mesiacov pred
rodič
commit
c4d5c5c304

+ 2 - 0
src/api/pms/iotmainworkorderbom/index.ts

@@ -8,6 +8,8 @@ export interface IotMainWorkOrderBomVO {
   workOrderId: number // 保养工单id
   deviceCategoryId: number // 所属设备分类
   deviceId: number // 设备id
+  deviceCode: string  // 设备编码
+  deviceName: string  // 设备名称
   rule: string // 保养规则(量程 运行时间 自然日期) 可多选
   mileageRule: number // 保养规则-里程(0启用 1停用)
   naturalDateRule: number // 保养规则-自然日期(0启用 1停用)

+ 1 - 1
src/config/axios/service.ts

@@ -182,7 +182,7 @@ service.interceptors.response.use(
       // 判断是否包含rq/iot路径
       if (requestUrl.includes('rq/')||requestUrl.includes('system/dict')||requestUrl.includes('system/auth/get-permission-info')||requestUrl.includes('system/dept/list')
         ||requestUrl.includes('system/menu/simple-list')||requestUrl.includes('system/menu/list')||requestUrl.includes('system/dept/simple-list')
-        ||requestUrl.includes('pms/')||requestUrl.includes('system/user/page')||requestUrl.includes('supplier/base/page')) {
+        ||requestUrl.includes('pms/')||requestUrl.includes('system/user/page')||requestUrl.includes('supplier/base/page')||requestUrl.includes('system/dept/get')) {
         const localeStore = useLocaleStore()
         const lang = localeStore.getCurrentLocale.lang
         if (data&& data.data) {

+ 50 - 0
src/locales/en.ts

@@ -498,6 +498,7 @@ export default {
     view:'View',
     fill:'Fill',
     all:'All',
+    clear:'Clear'
   },
   operationFillForm:{
     team:'Team',
@@ -1010,4 +1011,53 @@ export default {
     selProcess:'Please select process ',
     InitiationTime:'InitiationTime',
   },
+  map:{
+    amplify:'Amplify',
+    reduce:'Reduce',
+    SwitchMapType:'SwitchMapType'
+  },
+  rem:{
+    DeviceAttrTemplateModel:'DeviceAttrTemplateModel',
+    AttributeInformationDetails:'AttributeInformationDetails',
+    AddProjectInformation:'AddProjectInformation',
+    TaskAllocation:'TaskAllocation',
+    FillInInformation:'FillInInformation',
+    detail:'Detail',
+    AddEquipment:'AddEquipment',
+    EquipmentEditing:'EquipmentEditing',
+    EquipmentDetails:'EquipmentDetails',
+    MonitoringDetails:'MonitoringDetails',
+    UploadFile:'UploadFile',
+    EquipmentBOM:'EquipmentBOM',
+    EquipmentResponsiblePerson:'EquipmentResponsiblePerson',
+    EquipmentStatusAdjustment:'EquipmentStatusAdjustment',
+    EquipmentAllocation:'EquipmentAllocation',
+    LocalStock:'LocalStock',
+    ManualWarehousing:'ManualWarehousing',
+    EditingWarehousing:'EditingWarehousing',
+    SAPStock:'SAPStock',
+    ConfigureSafetyStock:'ConfigureSafetyStock',
+    MaintenancePlan:'MaintenancePlan',
+    AddMaintenancePlan:'AddMaintenancePlan',
+    EditMaintenancePlan:'EditMaintenancePlan',
+    MaintenancePlanDetail:'MaintenancePlanDetail',
+    MaintenanceOrder:'MaintenanceOrder',
+    FillMaintenanceOrder:'FillMaintenanceOrder',
+    AddMaintenanceOrder:'AddMaintenanceOrder',
+    MaintenanceOrderDetail:"MaintenanceOrderDetail",
+    MaterialRequisition:'MaterialRequisition',
+    MaterialRequisitionAdd:'MaterialRequisitionAdd',
+    CollectionFormDetails:'CollectionFormDetails',
+    MaintainCalendar:'MaintainCalendar',
+    RepairOrderAdd:'RepairOrderAdd',
+    RepairOrderEdit:'RepairOrderEdit',
+    RepairOrderDetail:'RepairOrderDetail',
+    InspectionRouteAdd:'InspectionRouteAdd',
+    InspectionRouteEdit:"InspectionRouteEdit",
+    InspectOrderAdd:'InspectOrderAdd',
+    InspectPlanAdd:'InspectPlanAdd',
+    InspectPlanEdit:'InspectPlanEdit',
+    InspectOrderDetail:'InspectOrderDetail',
+    FailureDetail:'FailureDetail',
+  },
 }

+ 53 - 0
src/locales/zh-CN.ts

@@ -493,6 +493,7 @@ export default {
     view:'查看',
     fill:'填写',
     all:'全部',
+    clear:'清空'
   },
   operationFillForm:{
     team:'所属队伍',
@@ -1003,6 +1004,58 @@ export default {
     belongProcess:'所属流程',
     selProcess:'请选择流程定义 ',
     InitiationTime:'发起时间',
+  },
+  map:{
+    amplify:'放大',
+    reduce:'缩小',
+    SwitchMapType:'切换地图类型'
+  },
+  rem:{
+    DeviceAttrTemplateModel:'设备属性详情',
+    AttributeInformationDetails:'属性信息详情',
+    AddProjectInformation:'添加项目信息',
+    TaskAllocation:'任务分配',
+    FillInInformation:'填写信息',
+    detail:'详情',
+    AddEquipment:'设备添加',
+    EquipmentEditing:'设备编辑',
+    EquipmentDetails:'设备详情',
+    MonitoringDetails:'监控详情',
+    UploadFile:'资料上传',
+    EquipmentBOM:'设备BOM',
+    EquipmentResponsiblePerson:'设备责任人',
+    EquipmentStatusAdjustment:'设备状态调整',
+    EquipmentAllocation:'设备调拨',
+    LocalStock:'本地库存',
+    ManualWarehousing:'手工入库',
+    EditingWarehousing:'修改入库',
+    SAPStock:'SAP库存',
+    ConfigureSafetyStock:'配置安全库存',
+    MaintenancePlan:'保养计划',
+    AddMaintenancePlan:'新增保养计划',
+    EditMaintenancePlan:'修改保养计划',
+    MaintenancePlanDetail:'保养计划详情',
+    MaintenanceOrder:'保养工单',
+    FillMaintenanceOrder:'填写保养工单',
+    AddMaintenanceOrder:'新增保养工单',
+    MaintenanceOrderDetail:"保养工单详情",
+    MaterialRequisition:'物料领用',
+    MaterialRequisitionAdd:'物料领用',
+    CollectionFormDetails:'领用单详情',
+    MaintainCalendar:'保养台历',
+    RepairOrderAdd:'维修工单添加',
+    RepairOrderEdit:'维修工单编辑',
+    RepairOrderDetail:'维修工单详情',
+    InspectionRouteAdd:'巡检路线添加',
+    InspectionRouteEdit:"巡检路线编辑",
+    InspectOrderAdd:'巡检工单填写',
+    InspectPlanAdd:'巡检计划添加',
+    InspectPlanEdit:'巡检计划编辑',
+    InspectOrderDetail:'巡检工单详情',
+    FailureDetail:'查看故障详情',
+
+
+
   },
 
   'OAuth 2.0': 'OAuth 2.0' // 避免菜单名是 OAuth 2.0 时,一直 warn 报错

+ 47 - 47
src/router/modules/remaining.ts

@@ -90,7 +90,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
         component: () => import('@/views/pms/devicetemplate/detail/attrsModel/index.vue'),
         name: 'DeviceAttrTemplateModel',
         meta: {
-          title: '设备属性模板详情',
+          title: t('rem.DeviceAttrTemplateModel'),
           noCache: false,
           hidden: true,
           canTo: true,
@@ -112,7 +112,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
         component: () => import('@/views/pms/modeltemplate/detail/attrsModel/index.vue'),
         name: 'ModelAttrTemplate',
         meta: {
-          title: '属性信息详情',
+          title: t('rem.AttributeInformationDetails'),
           noCache: false,
           hidden: true,
           canTo: true,
@@ -134,7 +134,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
         component: () => import('@/views/pms/iotprojectinfo/IotProjectInfoForm.vue'),
         name: 'IotProjectInfo',
         meta: {
-          title: '添加项目信息',
+          title: t('rem.AddProjectInformation'),
           noCache: false,
           hidden: true,
           canTo: true,
@@ -156,7 +156,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
         component: () => import('@/views/pms/iotprojecttask/IotProjectTaskForm.vue'),
         name: 'IotProjectTaskInfo',
         meta: {
-          title: '拆分',
+          title: t('rem.TaskAllocation'),
           noCache: false,
           hidden: true,
           canTo: true,
@@ -178,7 +178,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
         component: () => import('@/views/pms/iotopeationfill/index1.vue'),
         name: 'FillOrderInfo',
         meta: {
-          title: '填写信息详情',
+          title: t('rem.FillInInformation'),
           noCache: false,
           hidden: true,
           canTo: true,
@@ -190,7 +190,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
         component: () => import('@/views/pms/device/record/RecordInfo.vue'),
         name: 'FillOrderInfoDevice',
         meta: {
-          title: '详情',
+          title: t('rem.detail'),
           noCache: false,
           hidden: true,
           canTo: true,
@@ -216,7 +216,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
           hidden: true,
           canTo: true,
           icon: 'ep:add',
-          title: '设备台账添加',
+          title: t('rem.AddEquipment'),
           activeMenu: '/device/base'
         }
       },
@@ -229,7 +229,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
           hidden: true,
           canTo: true,
           icon: 'ep:add',
-          title: '设备台账添加',
+          title:  t('rem.AddEquipment'),
           activeMenu: '/device/base'
         }
       },
@@ -242,7 +242,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
           hidden: true,
           canTo: true,
           icon: 'ep:edit',
-          title: '设备台账编辑',
+          title: t('rem.EquipmentEditing'),
           activeMenu: '/device/base'
         }
       },{
@@ -254,7 +254,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
           hidden: true,
           canTo: true,
           icon: 'ep:info',
-          title: '设备台账详情',
+          title: t('rem.EquipmentDetails'),
           activeMenu: '/device/info'
         }
       },{
@@ -266,7 +266,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
           hidden: true,
           canTo: true,
           icon: 'ep:info',
-          title: '监控详情',
+          title: t('rem.MonitoringDetails'),
           activeMenu: '/device/info'
         }
       },{
@@ -278,7 +278,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
           hidden: true,
           canTo: true,
           icon: 'ep:info',
-          title: '设备台账资料上传',
+          title: t('rem.UploadFile'),
           activeMenu: '/device/upload'
         }
       },{
@@ -290,7 +290,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
           hidden: true,
           canTo: true,
           icon: 'ep:info',
-          title: '设备BOM',
+          title: t('rem.EquipmentBOM'),
           activeMenu: '/device/bom'
         }
       },
@@ -303,7 +303,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
           hidden: true,
           canTo: true,
           icon: 'ep:add',
-          title: '设备责任人',
+          title: t('rem.EquipmentResponsiblePerson'),
           activeMenu: '/device/person'
         }
       },
@@ -316,7 +316,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
           hidden: true,
           canTo: true,
           icon: 'ep:add',
-          title: '调整设备状态',
+          title: t('rem.EquipmentStatusAdjustment'),
           activeMenu: '/device/status'
         }
       },
@@ -329,7 +329,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
           hidden: true,
           canTo: true,
           icon: 'ep:add',
-          title: '设备调拨',
+          title: t('rem.EquipmentAllocation'),
           activeMenu: '/device/allot'
         }
       }
@@ -353,7 +353,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
           hidden: true,
           canTo: true,
           icon: 'ep:menu',
-          title: '本地库存',
+          title: t('rem.LocalStock'),
           activeMenu: '/lockstock/index'
         }
       },
@@ -366,7 +366,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
           hidden: true,
           canTo: true,
           icon: 'ep:add',
-          title: '手工入库',
+          title: t('rem.ManualWarehousing'),
           activeMenu: '/lockstock/add'
         }
       },
@@ -379,7 +379,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
           hidden: true,
           canTo: true,
           icon: 'ep:edit',
-          title: '修改入库',
+          title: t('rem.EditingWarehousing'),
           activeMenu: '/lockstock/edit'
         }
       }
@@ -403,7 +403,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
           hidden: true,
           canTo: true,
           icon: 'ep:menu',
-          title: 'SAP库存',
+          title: t('rem.SAPStock'),
           activeMenu: '/sapstock/index'
         }
       },
@@ -416,7 +416,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
           hidden: true,
           canTo: true,
           icon: 'ep:add',
-          title: '配置安全库存',
+          title: t('rem.ConfigureSafetyStock'),
           activeMenu: '/sapstock/config'
         }
       },
@@ -429,7 +429,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
           hidden: true,
           canTo: true,
           icon: 'ep:add',
-          title: '配置安全库存',
+          title: t('rem.ConfigureSafetyStock'),
           activeMenu: '/sapstock/safe'
         }
       },
@@ -453,7 +453,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
           hidden: true,
           canTo: true,
           icon: 'ep:menu',
-          title: '保养计划',
+          title: t('rem.MaintenancePlan'),
           activeMenu: '/maintenanceplan/index'
         }
       },
@@ -466,7 +466,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
           hidden: true,
           canTo: true,
           icon: 'ep:add',
-          title: '新增保养计划',
+          title: t('rem.AddMaintenancePlan'),
           activeMenu: '/maintenanceplan/add'
         }
       },
@@ -479,7 +479,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
           hidden: true,
           canTo: true,
           icon: 'ep:edit',
-          title: '修改保养计划',
+          title: t('rem.EditMaintenancePlan'),
           activeMenu: '/maintenanceplan/edit'
         }
       },
@@ -492,7 +492,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
           hidden: true,
           canTo: true,
           icon: 'ep:edit',
-          title: '保养计划详情',
+          title: t('rem.MaintenancePlanDetail'),
           activeMenu: '/maintenanceplan/detail'
         }
       }
@@ -516,7 +516,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
           hidden: true,
           canTo: true,
           icon: 'ep:menu',
-          title: '保养工单',
+          title: t('rem.MaintenanceOrder'),
           activeMenu: '/mainworkorder/index'
         }
       },
@@ -529,7 +529,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
           hidden: true,
           canTo: true,
           icon: 'ep:add',
-          title: '填报保养工单',
+          title: t('rem.FillMaintenanceOrder'),
           activeMenu: '/mainworkorder/bom'
         }
       },
@@ -542,7 +542,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
           hidden: true,
           canTo: true,
           icon: 'ep:add',
-          title: '新增保养工单',
+          title: t('rem.AddMaintenanceOrder'),
           activeMenu: '/mainworkorder/add'
         }
       },
@@ -555,7 +555,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
           hidden: true,
           canTo: true,
           icon: 'ep:add',
-          title: '保养工单详情',
+          title: t('rem.MaintenanceOrderDetail'),
           activeMenu: '/mainworkorder/detail'
         }
       },
@@ -568,7 +568,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
           hidden: true,
           canTo: true,
           icon: 'ep:add',
-          title: '保养工单详情',
+          title: t('rem.MaintenanceOrderDetail'),
           activeMenu: '/mainworkorder/detail'
         }
       }
@@ -592,7 +592,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
           hidden: true,
           canTo: true,
           icon: 'ep:menu',
-          title: '物料领用',
+          title: t('rem.MaterialRequisition'),
           activeMenu: '/materialreq/index'
         }
       },
@@ -605,7 +605,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
           hidden: true,
           canTo: true,
           icon: 'ep:add',
-          title: '新增物料领用',
+          title: t('rem.MaterialRequisitionAdd'),
           activeMenu: '/materialreq/add'
         }
       },
@@ -618,7 +618,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
           hidden: true,
           canTo: true,
           icon: 'ep:view',
-          title: '领用单详情',
+          title: t('rem.CollectionFormDetails'),
           activeMenu: '/materialreq/detail'
         }
       },
@@ -642,7 +642,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
           hidden: true,
           canTo: true,
           icon: 'ep:menu',
-          title: '保养台历',
+          title: t('rem.MaintainCalendar'),
           activeMenu: '/maintenancecalendar/index'
         }
       }
@@ -665,7 +665,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
           hidden: true,
           canTo: true,
           icon: 'ep:add',
-          title: '维修工单添加',
+          title: t('rem.RepairOrderAdd'),
           activeMenu: '/maintain/add'
         }
       },
@@ -678,7 +678,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
           hidden: true,
           canTo: true,
           icon: 'ep:edit',
-          title: '维修工单编辑',
+          title: t('rem.RepairOrderEdit'),
           activeMenu: '/maintain/edit'
         }
       },{
@@ -690,7 +690,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
           hidden: true,
           canTo: true,
           icon: 'ep:add',
-          title: '维修工单详情',
+          title: t('rem.RepairOrderDetail'),
           activeMenu: '/maintain/detail'
         }
       },
@@ -713,7 +713,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
           hidden: true,
           canTo: true,
           icon: 'ep:add',
-          title: '巡检路线添加',
+          title: t('rem.InspectionRouteAdd'),
           activeMenu: '/route/add'
         }
       },
@@ -726,7 +726,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
           hidden: true,
           canTo: true,
           icon: 'ep:edit',
-          title: '巡检路线编辑',
+          title: t('rem.InspectionRouteEdit'),
           activeMenu: '/route/edit'
         }
       // }
@@ -763,7 +763,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
           hidden: true,
           canTo: true,
           icon: 'ep:add',
-          title: '巡检计划添加',
+          title: t('rem.InspectPlanAdd'),
           activeMenu: '/inspect/plan/add'
         }
       },
@@ -776,7 +776,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
           hidden: true,
           canTo: true,
           icon: 'ep:edit',
-          title: '巡检计划编辑',
+          title: t('rem.InspectPlanEdit'),
           activeMenu: '/inspect/plan/edit'
         }
         // }
@@ -812,7 +812,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
           hidden: true,
           canTo: true,
           icon: 'ep:add',
-          title: '巡检工单填写',
+          title: t('rem.InspectOrderAdd'),
           activeMenu: '/inspect/order/add'
         }
       },
@@ -825,7 +825,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
           hidden: true,
           canTo: true,
           icon: 'ep:edit',
-          title: '巡检计划编辑',
+          title: t('rem.InspectPlanEdit'),
           activeMenu: '/inspect/order/edit'
         }
         }
@@ -838,7 +838,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
             hidden: true,
             canTo: true,
             icon: 'ep:add',
-            title: '巡检工单详情',
+            title: t('rem.InspectOrderDetail'),
             activeMenu: '/inspect/order/detail'
           }
       },{
@@ -850,7 +850,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
           hidden: true,
           canTo: true,
           icon: 'ep:add',
-          title: '巡检工单填写',
+          title: t('rem.InspectOrderAdd'),
           activeMenu: '/inspect/order/write'
         }
       }
@@ -872,7 +872,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
           noCache: true,
           hidden: true,
           canTo: true,
-          title: '查看故障详情',
+          title: t('rem.FailureDetail'),
           activeMenu: '/failure/detail'
         }
       }

+ 61 - 0
src/views/pms/iotlockstock/index.vue

@@ -93,6 +93,22 @@
     </el-form>
   </ContentWrap>
 
+  <!-- ========== 统计信息卡片 ========== -->
+  <ContentWrap style="margin-bottom: 16px">
+    <el-card shadow="never" class="stat-card">
+      <div class="stat-container">
+        <div class="stat-item">
+          <span class="stat-label">{{ t('stock.totalQuantity') }}:</span>
+          <span class="stat-value">{{ totalQuantity.toLocaleString() }}</span>
+        </div>
+        <div class="stat-item">
+          <span class="stat-label">{{ t('stock.totalAmount') }}:</span>
+          <span class="stat-value">¥ {{ totalAmount.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 }) }}</span>
+        </div>
+      </div>
+    </el-card>
+  </ContentWrap>
+
   <!-- 列表 -->
   <ContentWrap>
     <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
@@ -190,6 +206,10 @@ const factoryList = ref([] as SapOrgVO[])   // 工厂列表
 const storageLocationList = ref([] as SapOrgVO[]) // 库存地点列表
 const costCenterList = ref([] as SapOrgVO[]) // SAP成本中心列表
 
+// 新增统计变量
+const totalQuantity = ref(0)   // 总数量
+const totalAmount = ref(0)     // 总金额
+
 const selectedFactoryReqVO = ref({
   type: 0, // 类型(1工厂 2成本中心 3库位)
   factoryCodes: [] // 已经选择的SAP工厂code 列表
@@ -202,6 +222,16 @@ const getList = async () => {
     const data = await IotLockStockApi.getIotLockStockPage(queryParams)
     list.value = data.list
     total.value = data.total
+    // 从第一条记录中提取统计值
+    if (data.list && data.list.length > 0) {
+      // 确保取到有效的数值(第一条记录中的统计值代表整个查询结果)
+      totalQuantity.value = Number(data.list[0].totalQuantity) || 0
+      totalAmount.value = Number(data.list[0].totalAmount) || 0
+    } else {
+      // 没有数据时重置为0
+      totalQuantity.value = 0
+      totalAmount.value = 0
+    }
   } finally {
     loading.value = false
   }
@@ -287,3 +317,34 @@ onMounted(() => {
   getList()
 })
 </script>
+
+<style scoped>
+/* 统计卡片样式 */
+.stat-card {
+  border-radius: 4px;
+  border: 1px solid #ebeef5;
+}
+
+.stat-container {
+  display: flex;
+  padding: 1px;
+}
+
+.stat-item {
+  display: flex;
+  align-items: center;
+  margin-right: 40px; /* 控制项间距 */
+}
+
+.stat-label {
+  font-weight: bold;
+  color: #606266;
+  margin-right: 8px;
+}
+
+.stat-value {
+  font-size: 18px;
+  font-weight: bold;
+  color: #409EFF;
+}
+</style>

+ 56 - 34
src/views/pms/iotmainworkorder/IotMainWorkOrder.vue

@@ -897,59 +897,81 @@ const configFormRules = reactive({
 
 /** 校验表格数据 */
 const validateTableData = (): boolean => {
-  let isValid = true
-  const errorMessages: string[] = []
-  let shouldBreak = false;
-  const materialRequiredErrors: string[] = []  // 物料必填错误
+  let isValid = true;
+  const errorMessages: string[] = []; // 通用错误集合
+  const materialRequiredErrors: string[] = []; // 物料缺失专用错误集合
 
+  // 1. 基础校验:工单明细是否存在
   if (list.value.length === 0) {
-    errorMessages.push('工单明细不存在')
-    isValid = false
-    // 直接返回无需后续校验
-    message.error('工单明细不存在')
-    return isValid
+    message.error('工单明细不存在');
+    return false;
   }
 
-  // 新增物料必填校验(仅在非委外模式下检查)
-  if (formData.value.outsourcingFlag !== 1) { // 非委外模式
+  // 2. 校验设备状态
+  list.value.forEach((row, index) => {
+    const rowNumber = index + 1;
+    if (row.deviceCode === null || row.deviceName === null) {
+      errorMessages.push(`第${rowNumber}行设备状态错误`);
+      isValid = false;
+    }
+  });
+
+  // 3. 校验物料必填(仅在非委外模式下)
+  if (formData.value.outsourcingFlag !== 1) {
     list.value.forEach((row, index) => {
-      const rowNumber = index + 1
-      const deviceIdentifier = `${row.deviceCode}-${row.name}`
+      const rowNumber = index + 1;
+      const deviceIdentifier = `${row.deviceCode}-${row.name}`;
 
       // 检查是否设置了推迟保养
       const hasDelay =
         (row.delayKilometers || 0) > 0 ||
         (row.delayNaturalDate || 0) > 0 ||
-        (row.delayDuration || 0) > 0
+        (row.delayDuration || 0) > 0;
 
       // 未设置推迟保养且未选择物料
       if (!hasDelay && getMaterialCount(row.bomNodeId) === 0) {
-        materialRequiredErrors.push(`第${rowNumber}行【${deviceIdentifier}】必须选择物料`)
-        isValid = false
+        materialRequiredErrors.push(`第${rowNumber}行【${deviceIdentifier}】未添加物料`);
+        isValid = false;
       }
-    })
+    });
   }
 
-  list.value.forEach((row, index) => {
-    if (shouldBreak) return;
-    const rowNumber = index + 1 // 用户可见的行号从1开始
-    // const deviceIdentifier = `${row.deviceCode}-${row.name}` // 设备标识
-    if(row.deviceCode === null || row.deviceName === null){
-      errorMessages.push('设备状态错误')
-      isValid = false
+  // 4. 智能错误提示
+  if (!isValid) {
+    // 构建错误消息HTML
+    let errorHtml = '';
+
+    // 添加通用错误
+    if (errorMessages.length > 0) {
+      errorHtml += errorMessages.join('<br>');
+    }
+
+    // 添加物料错误(带智能截断)
+    if (materialRequiredErrors.length > 0) {
+      if (errorHtml) errorHtml += '<br>'; // 添加换行分隔
+
+      if (materialRequiredErrors.length > 3) {
+        errorHtml += materialRequiredErrors.slice(0, 3).join('<br>');
+        errorHtml += `<br>...等共 ${materialRequiredErrors.length} 个保养项未添加物料`;
+      } else {
+        errorHtml += materialRequiredErrors.join('<br>');
+      }
     }
-  })
-  if (errorMessages.length > 0) {
-    message.error('设备状态错误')
-  }
-  // 合并错误信息
-  if (materialRequiredErrors.length > 0) {
-    message.error(materialRequiredErrors.join('\n'))
-  }
-  return isValid
-}
 
+    // 添加标题
+    const title = "<span style='font-weight:bold;color:#f56c6c'></span>";
+    errorHtml = title + errorHtml;
+
+    // 显示带格式的错误消息
+    message.error({
+      message: errorHtml,
+      dangerouslyUseHTMLString: true,
+      duration: 8000  // 延长显示时间
+    });
+  }
 
+  return isValid;
+};
 
 /** 重置表单 */
 const resetForm = () => {

+ 48 - 1
src/views/pms/iotmainworkorder/IotMainWorkOrderAdd.vue

@@ -726,7 +726,7 @@ const saveConfig = () => {
     // 强制校验逻辑
     if (configDialog.current.naturalDateRule === 0) {
       if (!configDialog.form.lastNaturalDate) {
-        message.error('必须选择自然日期')
+        message.error('必须选择 上次保养自然日期')
         return
       }
 
@@ -836,6 +836,11 @@ const submitForm = async () => {
   // 校验表格数据
   const isValid = validateTableData()
   if (!isValid) return
+
+  // 新增:校验物料选择
+  const hasMaterial = validateMaterialSelection();
+  if (!hasMaterial) return;
+
   // 提交请求
   formLoading.value = true
   try {
@@ -904,6 +909,48 @@ const validateTableData = (): boolean => {
   return isValid
 }
 
+/** 检查每个保养项是否都有物料 */
+const validateMaterialSelection = (): boolean => {
+  let isValid = true;
+  const errorMessages: string[] = [];
+
+  // 遍历所有保养项
+  list.value.forEach(item => {
+    const hasMaterial = materialList.value.some(
+      material => material.bomNodeId === item.bomNodeId
+    );
+
+    if (!hasMaterial) {
+      isValid = false;
+      errorMessages.push(
+        `设备 ${item.deviceCode}-${item.deviceName} 的保养项【${item.name}】未添加物料`
+      );
+    }
+  });
+
+  // 显示错误信息
+  if (!isValid) {
+    let displayMessage;
+
+    if (errorMessages.length > 3) {
+      // 超过3条错误时显示前3条+总结
+      const firstThree = errorMessages.slice(0, 3);
+      displayMessage = firstThree.join('<br/>') +
+        `<br/>...等共 ${errorMessages.length} 个保养项未添加物料`;
+    } else {
+      // 3条及以内直接显示全部
+      displayMessage = errorMessages.join('<br/>');
+    }
+
+    message.error({
+      message: displayMessage,
+      dangerouslyUseHTMLString: true
+    });
+  }
+
+  return isValid;
+};
+
 /** 重置表单 */
 const resetForm = () => {
   formData.value = {

+ 2 - 2
src/views/pms/iotopeationfill/index1.vue

@@ -34,7 +34,7 @@
                   >
                     <el-form-item :label='item.name' class="custom-label1">
                   <span style="text-decoration: underline;">
-                  {{item.totalRunTime}}h
+                  {{item.totalRunTime}}
                   </span>
                     </el-form-item>
                   </el-col>
@@ -65,7 +65,7 @@
             </div>
             <el-form-item>
               <el-button type="primary" @click="getFillInfo" v-show="showStatus">{{t('operationFillForm.confirm')}}</el-button>
-              <el-button type="info" @click="deleteFillInfo" v-show="showStatus">{{t('operationFillForm.cancel')}}</el-button>
+              <el-button type="info" @click="deleteFillInfo" v-show="showStatus">{{t('operationFill.clear')}}</el-button>
             </el-form-item>
           </el-form>
         </div>

+ 1 - 1
src/views/pms/iotsapstock/index.vue

@@ -336,7 +336,7 @@ onMounted(() => {
 
 .stat-container {
   display: flex;
-  padding: 8px;
+  padding: 1px;
 }
 
 .stat-item {

+ 17 - 4
src/views/pms/maintenance/IotMaintenancePlan.vue

@@ -160,6 +160,7 @@
     v-model="configDialog.visible"
     :title="`设备 ${configDialog.current?.deviceCode+'-'+configDialog.current?.name} 保养配置`"
     width="600px"
+    :close-on-click-modal="false"
   >
     <!-- 使用header插槽自定义标题 -->
     <template #header>
@@ -432,7 +433,10 @@ const openConfigDialog = (row: IotMaintenanceBomVO) => {
   configDialog.form = {
     lastRunningKilometers: row.lastRunningKilometers || 0,
     lastRunningTime: row.lastRunningTime || 0,
-    lastNaturalDate: initialDate,
+    // 时间戳 -> Date对象(用于日期选择器)
+    lastNaturalDate: row.lastNaturalDate
+      ? dayjs(row.lastNaturalDate).format('YYYY-MM-DD')
+      : null,
     // 保养规则 周期值
     nextRunningKilometers: row.nextRunningKilometers || 0,
     nextRunningTime: row.nextRunningTime || 0,
@@ -495,7 +499,8 @@ const saveConfig = () => {
     // 更新当前行的数据
     Object.assign(configDialog.current, {
       ...configDialog.form,
-      lastNaturalDate: finalDate
+      // Date对象 -> 时间戳
+      lastNaturalDate: finalDate,
     })
     configDialog.visible = false
   })
@@ -629,9 +634,17 @@ const submitForm = async () => {
   // 提交请求
   formLoading.value = true
   try {
+    // 转换日期格式
+    const convertedList = list.value.map(item => ({
+      ...item,
+      lastNaturalDate: typeof item.lastNaturalDate === 'number'
+        ? item.lastNaturalDate
+        : (item.lastNaturalDate ? dayjs(item.lastNaturalDate).valueOf() : null)
+    }));
+
     const data = {
       mainPlan: formData.value,
-      mainPlanBom: list.value
+      mainPlanBom: convertedList
     }
     if (formType.value === 'create') {
       await IotMaintenancePlanApi.createIotMaintenancePlan(data)
@@ -811,7 +824,7 @@ onMounted(async () => {
       list.value = data.map(item => ({
         ...item,
         // 这里可以添加必要的字段转换(如果有日期等需要格式化的字段)
-        lastNaturalDate: item.lastNaturalDate ? dayjs(item.lastNaturalDate).format('YYYY-MM-DD') : null
+        lastNaturalDate: item.lastNaturalDate
       }))
       // 同时查询所有设备的责任人
       // await getDevicePersons();

+ 7 - 7
src/views/pms/map/DeviceMonitorDrawer.vue

@@ -1,6 +1,6 @@
 <template>
   <el-drawer
-    title="设备运行监控"
+    :title="t('rem.MonitoringDetails')"
     :append-to-body="true"
     :model-value="modelValue"
     @update:model-value="$emit('update:modelValue', $event)"
@@ -16,7 +16,7 @@
               <el-col :span="8">
                 <el-form-item prop="deviceCode">
                   <template #label>
-                    <span class="custom-label">资产编码:</span>
+                    <span class="custom-label">{{ t('chooseMaintain.deviceCode') }}:</span>
                   </template>
                   <span class="custom-label">{{ formData.deviceCode }}</span>
                 </el-form-item>
@@ -24,7 +24,7 @@
               <el-col :span="8">
                 <el-form-item prop="deviceName">
                   <template #label>
-                    <span class="custom-label">设备类别:</span>
+                    <span class="custom-label">{{ t('deviceForm.category') }}:</span>
                   </template>
                   <span class="custom-label">{{ formData.deviceName }}</span>
                 </el-form-item>
@@ -32,7 +32,7 @@
               <el-col :span="8">
                 <el-form-item prop="dept">
                   <template #label>
-                    <span class="custom-label">所在部门:</span>
+                    <span class="custom-label">{{ t('devicePerson.dept') }}:</span>
                   </template>
                   <span class="custom-label">{{ formData.dept }}</span>
                 </el-form-item>
@@ -40,7 +40,7 @@
               <el-col :span="8">
                 <el-form-item prop="ifInline">
                   <template #label>
-                    <span class="custom-label">是否在线:</span>
+                    <span class="custom-label">{{ t('monitor.online') }}:</span>
                   </template>
                   <template #default>
                     <dict-tag :type="DICT_TYPE.IOT_DEVICE_STATUS" :value="formData.ifInline" />
@@ -50,7 +50,7 @@
               <el-col :span="8">
                 <el-form-item prop="lastInlineTime">
                   <template #label>
-                    <span class="custom-label">最后数据时间:</span>
+                    <span class="custom-label">{{ t('monitor.latestDataTime') }}:</span>
                   </template>
                   <span class="custom-label">{{ formData.lastInlineTime }}</span>
                 </el-form-item>
@@ -94,7 +94,7 @@ import {IotStatApi} from "@/api/pms/stat";
 import * as echarts from "echarts";
 import {IotDeviceApi} from "@/api/pms/device";
 import {propTypes} from "@/utils/propTypes";
-
+const { t } = useI18n() // 国际化
 const drawerVisible = ref<boolean>(false)
 const emit = defineEmits(['update:modelValue', 'add', 'delete'])
 

+ 12 - 12
src/views/pms/map/Map.vue

@@ -2,10 +2,10 @@
   <div class="map-container">
     <div id="baidu-map" ref="mapContainer"></div>
     <div class="map-controls">
-      <button @click="zoomIn">放大</button>
-      <button @click="zoomOut">缩小</button>
+      <button @click="zoomIn">{{t('map.amplify')}}</button>
+      <button @click="zoomOut">{{t('map.reduce')}}</button>
       <button @click="toggleMapType"
-      >切换地图类型({{ mapType === 'BMAP_NORMAL_MAP' ? '地图' : '卫星' }})</button>
+      >{{t('map.SwitchMapType')}}({{ mapType === 'BMAP_NORMAL_MAP' ? '地图' : '卫星' }})</button>
     </div>
   </div>
   <DeviceMonitorDrawer :model-value="drawerVisible" @update:model-value="(val) => (drawerVisible = val)" :id="deviceId" :deviceName="deviceName" :lastLineTime="lastLineTime"
@@ -41,7 +41,7 @@ const lastLineTime = ref('')
 const ifLine = ref()
 const dept = ref('')
 const deviceCode = ref('')
-
+const { t } = useI18n() // 国际化
 // 设备数据示例
 const devices = ref<IotDeviceVO[]>()
 
@@ -250,13 +250,13 @@ const showDeviceInfoWindow = (device: IotDeviceVO, point: any) => {
     const content = `
 <div style="display: flex;flex-direction: column;justify-content: center;border: 1px solid #ccc;">
         <div style="margin-top: 1px;padding: 8px">
-          <p><strong>设备编码:</strong> ${device.deviceCode}</p>
-          <p><strong>设备名称:</strong> ${device.deviceName}</p>
-          <p><strong>所在部门:</strong> ${res.name}</p>
-          <p><strong>位置:</strong> ${device.location?device.location.replaceAll('"',''):''}</p>
-          <p><strong>状态:</strong> ${getDictLabel(DICT_TYPE.PMS_DEVICE_STATUS, device.deviceStatus)}</p>
-          <p><strong>是否在线:</strong> ${getDictLabel(DICT_TYPE.IOT_DEVICE_STATUS, device.ifInline)}</p>
-          <p><strong>最后在线时间:</strong> ${device.lastInlineTime}</p>
+          <p><strong>${t('iotDevice.code')}:</strong> ${device.deviceCode}</p>
+          <p><strong>${t('iotDevice.name')}:</strong> ${device.deviceName}</p>
+          <p><strong>${t('iotDevice.dept')}:</strong> ${res.name}</p>
+          <p><strong>${t('form.position')}:</strong> ${device.location?device.location.replaceAll('"',''):''}</p>
+          <p><strong>${t('dict.status')}:</strong> ${getDictLabel(DICT_TYPE.PMS_DEVICE_STATUS, device.deviceStatus)}</p>
+          <p><strong>${t('monitor.online')}:</strong> ${getDictLabel(DICT_TYPE.IOT_DEVICE_STATUS, device.ifInline)}</p>
+          <p><strong>${t('monitor.latestDataTime')}:</strong> ${device.lastInlineTime}</p>
         </div>
         <div style="margin-bottom: 5px;padding: 8px">
             <button id="device-detail-btn" style=" background-color: #2196f3;
@@ -265,7 +265,7 @@ const showDeviceInfoWindow = (device: IotDeviceVO, point: any) => {
               padding: 8px 16px;
               border-radius: 4px;
 
-              cursor: pointer;">查看</button>
+              cursor: pointer;">${t('fault.view')}</button>
         </div>
         </div>
       `