Sfoglia il codice sorgente

✨ feat(日报、运行记录): 非生产时间

Zimo 3 settimane fa
parent
commit
363de043ed

+ 12 - 12
config/env.dev.js

@@ -1,14 +1,14 @@
 // 开发环境配置
 export default {
-	// apiUrl: 'http://192.168.188.16:48080',
-	apiUrl: 'https://iot.deepoil.cc',
-	// apiUrl: 'https://aims.deepoil.cc', //正式
-	apiUrlSuffix: '/admin-api',
-	// 其他开发环境配置...  
-	corpId: 'dingbe7f9a7e8cffa2bd35c2f4657eb6378f', //钉钉微应用 企业的CorpID - 正式环境
-	clientId: 'dingmr9ez0ecgbmscfeb', //钉钉微应用的Client ID - 正式环境(原企业内部应用的 AppKey。原第三方企业应用的 SuiteKey。)
-	AgentId: '3687646006', //钉钉微应用的AgentID - 正式环境
-	MiniAppId: '5000000006298501', //钉钉微应用的MiniAppID - 正式环境 
-	AppKey: 'dingmr9ez0ecgbmscfeb', //钉钉微应用的AppKey - 正式环境
-	AppSecret: 'VhG_zMdTvIBwA_0Ef8FJ0foH3VYYo5T-kw0ukX_PBA8Ah1xl7AjDw5RVYCU0DTpe', //钉钉微应用的AppSecret - 正式环境
-};
+  // apiUrl: "http://192.168.188.198:48080",
+  apiUrl: "https://iot.deepoil.cc",
+  // apiUrl: 'https://aims.deepoil.cc', //正式
+  apiUrlSuffix: "/admin-api",
+  // 其他开发环境配置...
+  corpId: "dingbe7f9a7e8cffa2bd35c2f4657eb6378f", //钉钉微应用 企业的CorpID - 正式环境
+  clientId: "dingmr9ez0ecgbmscfeb", //钉钉微应用的Client ID - 正式环境(原企业内部应用的 AppKey。原第三方企业应用的 SuiteKey。)
+  AgentId: "3687646006", //钉钉微应用的AgentID - 正式环境
+  MiniAppId: "5000000006298501", //钉钉微应用的MiniAppID - 正式环境
+  AppKey: "dingmr9ez0ecgbmscfeb", //钉钉微应用的AppKey - 正式环境
+  AppSecret: "VhG_zMdTvIBwA_0Ef8FJ0foH3VYYo5T-kw0ukX_PBA8Ah1xl7AjDw5RVYCU0DTpe", //钉钉微应用的AppSecret - 正式环境
+};

+ 9 - 9
config/env.prod.js

@@ -1,14 +1,14 @@
 // 生产环境配置
 export default {
   // apiUrl: 'http://192.168.1.63:8888',
-  // apiUrl: 'https://iot.deepoil.cc', //测试
-  apiUrl: 'https://aims.deepoil.cc', //正式
-  apiUrlSuffix: '/admin-api',
+  // apiUrl: "https://iot.deepoil.cc", //测试
+  apiUrl: "https://aims.deepoil.cc", //正式
+  apiUrlSuffix: "/admin-api",
   // 其他开发环境配置...
-  corpId: 'dingbe7f9a7e8cffa2bd35c2f4657eb6378f', //钉钉微应用 企业的CorpID - 正式环境
-  clientId: 'dingmr9ez0ecgbmscfeb', //钉钉微应用的Client ID - 正式环境(原企业内部应用的 AppKey。原第三方企业应用的 SuiteKey。)
-  AgentId: '3687646006', //钉钉微应用的AgentID - 正式环境
-  MiniAppId: '5000000006298501', //钉钉微应用的MiniAppID - 正式环境
-  AppKey: 'dingmr9ez0ecgbmscfeb', //钉钉微应用的AppKey - 正式环境
-  AppSecret: 'VhG_zMdTvIBwA_0Ef8FJ0foH3VYYo5T-kw0ukX_PBA8Ah1xl7AjDw5RVYCU0DTpe', //钉钉微应用的AppSecret - 正式环境
+  corpId: "dingbe7f9a7e8cffa2bd35c2f4657eb6378f", //钉钉微应用 企业的CorpID - 正式环境
+  clientId: "dingmr9ez0ecgbmscfeb", //钉钉微应用的Client ID - 正式环境(原企业内部应用的 AppKey。原第三方企业应用的 SuiteKey。)
+  AgentId: "3687646006", //钉钉微应用的AgentID - 正式环境
+  MiniAppId: "5000000006298501", //钉钉微应用的MiniAppID - 正式环境
+  AppKey: "dingmr9ez0ecgbmscfeb", //钉钉微应用的AppKey - 正式环境
+  AppSecret: "VhG_zMdTvIBwA_0Ef8FJ0foH3VYYo5T-kw0ukX_PBA8Ah1xl7AjDw5RVYCU0DTpe", //钉钉微应用的AppSecret - 正式环境
 };

+ 1 - 0
locale/zh-Hans.json

@@ -40,6 +40,7 @@
   "operation.view": "查看",
   "operation.edit": "编辑",
   "operation.fill": "填写",
+  "operation.time": "时效",
   "operation.approve": "审批",
   "operation.submit": "提交",
   "operation.save": "保存",

+ 460 - 472
locale/zh-Hant.json

@@ -1,491 +1,479 @@
 {
-	"locale.auto": "系统",
-	"locale.en": "English",
-	"locale.zh-hans": "简体中文",
-	"locale.zh-hant": "繁体中文",
-	"locale.ru": "俄语",
-	"locale.ja": "日语",
-	"index.detail": "详情",
-	"index.language": "语言",
-	"index.languageChange": "选择语言",
-	"index.language-info": "语言信息",
-	"index.system-language": "系统语言",
-	"index.application-language": "应用语言",
-	"index.language-change-confirm": "应用此设置将重启App",
-	"api.message": "提示",
-	// -----------------------------------------------
-	"app.appName": "DeepOil",
-	"app.home": "首页",
-	"app.user": "我的",
-	// ------------------通用-----------------------------
-	"operation.cancel": "取消",
-	"operation.back": "返回",
-	"operation.confirm": "确定",
-	"operation.confirm1": "确认",
-	"operation.search": "搜索",
-	"operation.view": "查看",
-	"operation.edit": "编辑",
-	"operation.fill": "填写",
-	"operation.submit": "提交",
-	"operation.save": "保存",
-	"operation.add": "新增",
-	"operation.select": "选择",
-	"operation.delete": "删除",
-	"operation.please": "请",
-	"operation.PleaseFillIn": "请填写",
-	"operation.PleaseSelect": "请选择",
-	"operation.PleaseInput": "请输入",
-	"operation.PleaseSet": "请设置",
-	"operation.remark": "备注",
-	"operation.createTime": "创建时间",
-	"operation.updateTime": "更新时间",
-	"operation.yes": "是",
-	"operation.no": "否",
-	"operation.success": "操作成功",
-	"operation.fail": "操作失败,请重试",
-	"operation.repeat": "重复",
-	"operation.deleteConfirm": "是否删除当前所选数据?",
-	"operation.dispatchUser": "分配责任人",
-	"operation.reject": "拒绝",
-	"operation.approval": "通过",
+  "locale.auto": "系统",
+  "locale.en": "English",
+  "locale.zh-hans": "简体中文",
+  "locale.zh-hant": "繁体中文",
+  "locale.ru": "俄语",
+  "locale.ja": "日语",
+  "index.detail": "详情",
+  "index.language": "语言",
+  "index.languageChange": "选择语言",
+  "index.language-info": "语言信息",
+  "index.system-language": "系统语言",
+  "index.application-language": "应用语言",
+  "index.language-change-confirm": "应用此设置将重启App",
+  "api.message": "提示",
+  // -----------------------------------------------
+  "app.appName": "DeepOil",
+  "app.home": "首页",
+  "app.user": "我的",
+  // ------------------通用-----------------------------
+  "operation.cancel": "取消",
+  "operation.back": "返回",
+  "operation.confirm": "确定",
+  "operation.confirm1": "确认",
+  "operation.search": "搜索",
+  "operation.view": "查看",
+  "operation.edit": "编辑",
+  "operation.fill": "填写",
+  "operation.time": "时效",
+  "operation.submit": "提交",
+  "operation.save": "保存",
+  "operation.add": "新增",
+  "operation.select": "选择",
+  "operation.delete": "删除",
+  "operation.please": "请",
+  "operation.PleaseFillIn": "请填写",
+  "operation.PleaseSelect": "请选择",
+  "operation.PleaseInput": "请输入",
+  "operation.PleaseSet": "请设置",
+  "operation.remark": "备注",
+  "operation.createTime": "创建时间",
+  "operation.updateTime": "更新时间",
+  "operation.yes": "是",
+  "operation.no": "否",
+  "operation.success": "操作成功",
+  "operation.fail": "操作失败,请重试",
+  "operation.repeat": "重复",
+  "operation.deleteConfirm": "是否删除当前所选数据?",
+  "operation.dispatchUser": "分配责任人",
+  "operation.reject": "拒绝",
+  "operation.approval": "通过",
 
-	// --------------------
-	"general.picture": "图片",
-	"general.timeNotBeLater": "开始时间不能晚于结束时间",
-	"general.timeNotBeEarlier": "结束时间不能早于开始时间",
+  // --------------------
+  "general.picture": "图片",
+  "general.timeNotBeLater": "开始时间不能晚于结束时间",
+  "general.timeNotBeEarlier": "结束时间不能早于开始时间",
 
+  // -----------------------------------------------
+  "login.welcome": "您好,欢迎登录",
+  "login.login": "登录",
+  "login.loginWithDingTalk": "用钉钉登录",
+  "login.languageChange": "更换语言",
+  "login.enterUsername": "请输入用户名",
+  "login.enterPhoneNumber": "请输入手机号",
+  "login.invalidPhoneFormat": "手机号格式不正确",
+  "login.enterPassword": "请输入密码",
+  "login.passwordRule": "密码至少八位字符,且包含大小写字母、数字和特殊字符\n特殊字符包含:!@#$%^&",
+  "login.dingTalkError": "钉钉登录失败",
+  "login.logoutConfirm": "确定要退出登录吗",
 
+  "home.todo": "待办",
+  "home.remind": "提醒",
+  "home.unmaintained": "超时未保养",
+  "home.uninspected": "超时未巡检",
+  "home.unrecorded": "超时未记录",
+  "home.operationRecordFilling": "运行记录填报",
+  "home.fillDailyOperationRecord": "填报每日运行记录",
+  "home.maintenanceWorkOrder": "保养工单",
+  "home.receiveMaintenanceWorkOrderAndSubmit": "接收保养工单并提报",
+  "home.equipmentMaintenance": "设备维修",
+  "home.fillMaintenanceWorkOrder": "填报维修工单",
+  "home.inspectionWorkOrder": "巡检工单",
+  "home.receiveInspectionWorkOrderAndSubmit": "接收巡检工单并提报",
+  "home.faultReporting": "故障上报",
+  "home.fillAndReportFaultWorkOrder": "故障工单的填报及上报故障问题",
+  "home.inventoryQuery": "库存查询",
+  "home.clickToQueryInventoryData": "点击查询库存数据",
+  "home.equipmentLedger": "设备台账",
+  "home.viewEquipmentLedger": "查看设备台账",
+  "home.equipmentStatusChange": "设备状态变更",
+  "home.adjustEquipmentStatus": "调整设备状态",
+  "home.realTimeEquipmentDataMonitoring": "设备实时数据监控",
+  "home.viewRealTimeEquipmentData": "查看设备实时数据",
+  "home.statisticalAnalysis": "统计分析",
+  "home.equipmentDataStatisticalAnalysis": "设备数据统计分析",
+  // ----------------------个人中心-------------------------
+  "user.username": "用户名",
+  "user.phone": "手机号码",
+  "user.phoneHint": "请输入正确的手机号码",
+  "user.avatar": "用户头像",
+  "user.securityCenter": "安全中心",
+  "user.modifyPhoneAndPassword": "修改手机和密码",
+  "user.aboutUs": "关于我们",
+  "user.currentVersion": "当前版本",
+  "user.logout": "退出",
+  "user.userInfo": "用户信息",
+  "user.updatePassword": "修改密码",
+  "user.oldPassword": "旧密码",
+  "user.oldPasswordHint": "请输入旧密码",
+  "user.password": "新密码",
+  "user.passwordHint": "请输入新密码",
+  "user.confirmPassword": "确认密码",
+  "user.confirmPasswordHint": "请输入确认密码",
+  "user.passwordError1": "新密码与旧密码一致",
+  "user.passwordError2": "新密码与确认密码不一致",
 
+  // ---------------------运行记录--------------------------
+  "operationRecordFilling.responsiblePerson": "负责人",
+  "operationRecordFilling.workOrderName": "工单名称",
+  "operationRecordFilling.belongToTeam": "所属队伍",
+  "operationRecordFilling.totalRunningTime": "累计运行时间",
+  // ----------------------------------------------------
+  "workOrder.addDevice": "新增设备",
+  "workOrder.addMaterial": "新增物料",
+  "workOrder.selectMaterial": "选择物料",
+  "workOrder.materialDetails": "物料详情",
+  "workOrder.materialCode": "物料编码",
+  "workOrder.materialName": "物料名称",
+  "workOrder.materialCount": "物料数量",
+  "workOrder.masterData": "物料主数据",
+  "workOrder.planCode": "计划编码",
+  "workOrder.unit": "单位",
+  "workOrder.unitPrice": "单价",
+  "workOrder.inventory": "库存",
+  "workOrder.remainingInventory": "剩余库存",
+  "workOrder.inventoryShortage": "库存不足",
+  "workOrder.source": "来源",
+  "workOrder.auditStatus": "审核状态",
+  "workOrder.isSolved": "是否解决",
+  "workOrder.isHelp": "是否协助",
+  "workOrder.Needassistance": "需要协助",
+  "workOrder.workOrderSource": "工单来源",
+  "workOrder.searchPlaceholder": "输入工单编号",
+  "workOrder.workOrderStatus": "工单状态",
+  "workOrder.workOrdertype": "工单类型",
+  "workOrder.workOrderNumber": "工单编号",
+  "workOrder.workOrderName": "工单名称",
+  "workOrder.executed": "已执行",
+  "workOrder.pending": "待执行",
+  "workOrder.responsiblePerson": "负责人",
+  "workOrder.viewDetails": "查看详情",
+  "workOrder.inventoryType": "库存类型",
+  "workOrder.consumptionQuantity": "消耗数量",
+  "workOrder.yuan": "元",
+  "workOrder.specification": "规格型号",
+  "workOrder.status": "状态",
+  // -------------------状态相关---------------------------
+  "status.enable": "启用",
+  "status.disable": "停用",
+  "status.unaudited": "未审核",
+  "status.audited": "已审核",
+  "status.unfinished": "未完成",
+  "status.finished": "已完成",
+  "status.unsubmitted": "未提交",
+  "status.submitted": "已提交",
+  "status.unprocessed": "未处理",
+  "status.processed": "已处理",
+  "status.unsolved": "未解决",
+  "status.solved": "已解决",
+  "status.unfilled": "未填写",
+  "status.filled": "已填写",
+  "status.tobeFilled": "待填写",
 
-	// -----------------------------------------------
-	"login.welcome": "您好,欢迎登录",
-	"login.login": "登录",
-	"login.loginWithDingTalk": "用钉钉登录",
-	"login.languageChange": "更换语言",
-	"login.enterUsername": "请输入用户名",
-	"login.enterPhoneNumber": "请输入手机号",
-	"login.invalidPhoneFormat": "手机号格式不正确",
-	"login.enterPassword": "请输入密码",
-	"login.passwordRule": "密码至少八位字符,且包含大小写字母、数字和特殊字符\n特殊字符包含:!@#$%^&",
-	"login.dingTalkError": "钉钉登录失败",
-	"login.logoutConfirm": "确定要退出登录吗",
-	
-	"home.todo": "待办",
-	"home.remind": "提醒",
-	"home.unmaintained": "超时未保养",
-	"home.uninspected": "超时未巡检",
-	"home.unrecorded": "超时未记录",
-	"home.operationRecordFilling": "运行记录填报",
-	"home.fillDailyOperationRecord": "填报每日运行记录",
-	"home.maintenanceWorkOrder": "保养工单",
-	"home.receiveMaintenanceWorkOrderAndSubmit": "接收保养工单并提报",
-	"home.equipmentMaintenance": "设备维修",
-	"home.fillMaintenanceWorkOrder": "填报维修工单",
-	"home.inspectionWorkOrder": "巡检工单",
-	"home.receiveInspectionWorkOrderAndSubmit": "接收巡检工单并提报",
-	"home.faultReporting": "故障上报",
-	"home.fillAndReportFaultWorkOrder": "故障工单的填报及上报故障问题",
-	"home.inventoryQuery": "库存查询",
-	"home.clickToQueryInventoryData": "点击查询库存数据",
-	"home.equipmentLedger": "设备台账",
-	"home.viewEquipmentLedger": "查看设备台账",
-	"home.equipmentStatusChange": "设备状态变更",
-	"home.adjustEquipmentStatus": "调整设备状态",
-	"home.realTimeEquipmentDataMonitoring": "设备实时数据监控",
-	"home.viewRealTimeEquipmentData": "查看设备实时数据",
-	"home.statisticalAnalysis": "统计分析",
-	"home.equipmentDataStatisticalAnalysis": "设备数据统计分析",
-	// ----------------------个人中心-------------------------
-	"user.username": "用户名",
-	"user.phone": "手机号码",
-	"user.phoneHint": "请输入正确的手机号码",
-	"user.avatar": "用户头像",
-	"user.securityCenter": "安全中心",
-	"user.modifyPhoneAndPassword": "修改手机和密码",
-	"user.aboutUs": "关于我们",
-	"user.currentVersion": "当前版本",
-	"user.logout": "退出",
-	"user.userInfo": "用户信息",
-	"user.updatePassword": "修改密码",
-	"user.oldPassword": "旧密码",
-	"user.oldPasswordHint": "请输入旧密码",
-	"user.password": "新密码",
-	"user.passwordHint": "请输入新密码",
-	"user.confirmPassword": "确认密码",
-	"user.confirmPasswordHint": "请输入确认密码",
-	"user.passwordError1": "新密码与旧密码一致",
-	"user.passwordError2": "新密码与确认密码不一致",
+  // ---------------------选择设备-------------------------------
+  "device.selectDevice": "选择设备",
+  "device.assetCode": "资产编码",
+  "device.deviceCode": "设备编码",
+  "device.deviceName": "设备名称",
+  "device.department": "所在部门",
 
-	// ---------------------运行记录--------------------------
-	"operationRecordFilling.responsiblePerson": "负责人",
-	"operationRecordFilling.workOrderName": "工单名称",
-	"operationRecordFilling.belongToTeam": "所属队伍",
-	"operationRecordFilling.totalRunningTime": "累计运行时间",
-	// ----------------------------------------------------
-	"workOrder.addDevice": "新增设备",
-	"workOrder.addMaterial": "新增物料",
-	"workOrder.selectMaterial": "选择物料",
-	"workOrder.materialDetails": "物料详情",
-	"workOrder.materialCode": "物料编码",
-	"workOrder.materialName": "物料名称",
-	"workOrder.materialCount": "物料数量",
-	"workOrder.masterData": "物料主数据",
-	"workOrder.planCode": "计划编码",
-	"workOrder.unit": "单位",
-	"workOrder.unitPrice": "单价",
-	"workOrder.inventory": "库存",
-	"workOrder.remainingInventory": "剩余库存",
-	"workOrder.inventoryShortage": "库存不足",
-	"workOrder.source": "来源",
-	"workOrder.auditStatus": "审核状态",
-	"workOrder.isSolved": "是否解决",
-	"workOrder.isHelp": "是否协助",
-	"workOrder.Needassistance": "需要协助",
-	"workOrder.workOrderSource": "工单来源",
-	"workOrder.searchPlaceholder": "输入工单编号",
-	"workOrder.workOrderStatus": "工单状态",
-	"workOrder.workOrdertype": "工单类型",
-	"workOrder.workOrderNumber": "工单编号",
-	"workOrder.workOrderName": "工单名称",
-	"workOrder.executed": "已执行",
-	"workOrder.pending": "待执行",
-	"workOrder.responsiblePerson": "负责人",
-	"workOrder.viewDetails": "查看详情",
-	"workOrder.inventoryType": "库存类型",
-	"workOrder.consumptionQuantity": "消耗数量",
-	"workOrder.yuan": "元",
-	"workOrder.specification": "规格型号",
-	"workOrder.status": "状态",
-	// -------------------状态相关---------------------------
-	"status.enable": "启用",
-	"status.disable": "停用",
-	"status.unaudited": "未审核",
-	"status.audited": "已审核",
-	"status.unfinished": "未完成",
-	"status.finished": "已完成",
-	"status.unsubmitted": "未提交",
-	"status.submitted": "已提交",
-	"status.unprocessed": "未处理",
-	"status.processed": "已处理",
-	"status.unsolved": "未解决",
-	"status.solved": "已解决",
-	"status.unfilled": "未填写",
-	"status.filled": "已填写",
-	"status.tobeFilled": "待填写",
+  // -------------------保养工单----------------------------
 
+  "maintenanceWorkOrder.title": "保养工单",
+  "maintenanceWorkOrder.totalWorkOrders": "工单总数",
+  "maintenanceWorkOrder.createButton": "创建保养工单",
+  "maintenanceWorkOrder.status": "保养状态",
+  "maintenanceWorkOrder.temporaryCreation": "临时新建",
+  "maintenanceWorkOrder.planGenerator": "计划生成",
+  "maintenanceWorkOrder.actualMaintenanceStartTime": "实际保养开始时间",
+  "maintenanceWorkOrder.actualEndTime": "实际保养结束时间",
+  "maintenanceWorkOrder.timeToMaintenance": "距离保养",
+  "maintenanceWorkOrder.maintenanceButton": "去保养",
+  "maintenanceWorkOrder.isPostponed": "是否延期",
+  "maintenanceWorkOrder.createMaintenanceWorkOrder": "新建保养工单",
+  "maintenanceWorkOrder.editMaintenanceWorkOrder": "填报保养工单",
+  "maintenanceWorkOrder.viewMaintenanceWorkOrder": "查看保养工单",
+  "maintenanceWorkOrder.maintenanceType": "保养类型",
+  "maintenanceWorkOrder.maintenanceTypeIn": "内部",
+  "maintenanceWorkOrder.maintenanceTypeOut": "委外",
+  "maintenanceWorkOrder.maintenanceCost": "保养费用",
+  "maintenanceWorkOrder.otherCost": "其他费用",
+  "maintenanceWorkOrder.accumulatedRunningTime": "累计运行时间",
+  "maintenanceWorkOrder.accumulatedRunningMileage": "累计运行里数",
+  "maintenanceWorkOrder.maintenanceItems": "保养项",
+  "maintenanceWorkOrder.materialSelected": "是否已选物料",
+  "maintenanceWorkOrder.extendMaintenance": "延保",
+  "maintenanceWorkOrder.timeNotBeEarlier": "实际保养结束时间不能早于实际保养开始时间",
+  "maintenanceWorkOrder.bomEmpty": "请至少添加一条设备保养明细",
+  "maintenanceWorkOrder.materialEmpty": "请至少添加一条物料",
+  "maintenanceWorkOrder.materialUnselected": "未选择物料",
+  "maintenanceWorkOrder.equipment": "设备",
+  "maintenanceWorkOrder.maintenanceItemConfiguration": "保养项配置",
+  "maintenanceWorkOrder.noMaintenanceItems": "当前所选的设备没有保养项,请重新选择",
+  // 基础保养记录模块
+  "maintenanceWorkOrder.basicMaintenanceRecords": "基础保养记录",
+  "maintenanceWorkOrder.lastMaintenanceMileage": "上次保养里程数(KM)",
+  "maintenanceWorkOrder.delayedKilometers": "推迟公里数(KM)",
+  "maintenanceWorkOrder.lastMaintenanceRunningTime": "上次保养运行时间(H)",
+  "maintenanceWorkOrder.delayedDuration": "推迟时长(H)",
+  "maintenanceWorkOrder.lastMaintenanceNaturalDate": "上次保养自然日期",
+  "maintenanceWorkOrder.delayedNaturalDate": "推迟自然日期(D)",
+  // 运行规则配置模块(里程、时间区分)
+  "maintenanceWorkOrder.runningMileageRuleConfig": "运行里程规则配置",
+  "maintenanceWorkOrder.runningMileageCycle": "运行里程周期(KM)",
+  "maintenanceWorkOrder.runningMileageCycleLead": "运行里程周期-提前量(KM)",
+  "maintenanceWorkOrder.runningTimeRuleConfig": "运行时间规则配置",
+  "maintenanceWorkOrder.runningTimeCycle": "运行时间周期(H)",
+  "maintenanceWorkOrder.runningTimeCycleLead": "运行时间周期-提前量(H)",
+  // 自然日规则配置模块
+  "maintenanceWorkOrder.naturalDateRuleConfig": "自然日规则配置",
+  "maintenanceWorkOrder.naturalDateCycle": "自然日周期(D)",
+  "maintenanceWorkOrder.naturalDateCycleLead": "自然日周期-提前量(D)",
 
+  // -------------------设备维修-------------------
 
+  "equipmentMaintenance.title": "设备维修",
+  "equipmentMaintenance.searchHint": "请输入设备名称",
+  "equipmentMaintenance.averageResolutionTime": "平均解决时间",
+  "equipmentMaintenance.createButton": "创建维修工单",
+  "equipmentMaintenance.createWorkOrder": "新建维修工单",
+  "equipmentMaintenance.editWorkOrder": "填报维修工单",
+  "equipmentMaintenance.viewWorkOrder": "查看维修工单",
+  "equipmentMaintenance.repairCode": "维修编码",
+  "equipmentMaintenance.maintenanceStartTime": "维修开始时间",
+  "equipmentMaintenance.maintenanceEndTime": "维修结束时间",
+  "equipmentMaintenance.isStop": "是否停机",
+  "equipmentMaintenance.maintenanceType": "维修类型",
+  "equipmentMaintenance.description": "维修描述",
+  "equipmentMaintenance.cost": "维修费用",
+  "equipmentMaintenance.maintenanceItems": "维修项",
 
+  // -------------------故障------------------------
+  "fault.createButton": "创建故障工单",
+  "fault.createWorkOrder": "新建故障工单",
+  "fault.editWorkOrder": "编辑故障工单",
+  "fault.viewWorkOrder": "查看故障详情",
+  "fault.faultTotal": "故障上报总数",
+  "fault.faultCode": "故障编码",
+  "fault.faultName": "故障名称",
+  "fault.faultTime": "故障时间",
+  "fault.faultResolutionTime": "故障解决时间",
+  "fault.faultImpact": "故障影响",
+  "fault.faultSystem": "故障系统",
+  "fault.description": "故障描述",
+  "fault.solution": "解决办法",
+  "fault.timeNotBeEarlier": "故障解决时间不得早于故障时间",
 
-	// ---------------------选择设备-------------------------------
-	"device.selectDevice": "选择设备",
-	"device.assetCode": "资产编码",
-	"device.deviceCode": "设备编码",
-	"device.deviceName": "设备名称",
-	"device.department": "所在部门",
+  // ------------------巡检工单----------------------
+  "inspection.title": "巡检工单",
+  "inspection.totalWorkOrders": "巡检总数",
+  "inspection.editWorkOrder": "巡检工单填写",
+  "inspection.viewWorkOrder": "巡检工单详情",
+  "inspection.clickView": "点击查看",
+  "inspection.proj": "巡检项目",
+  "inspection.projItem": "巡检项",
+  "inspection.standard": "巡检标准",
+  "inspection.standardFile": "附件:",
+  "inspection.isAbnormal": "是否异常",
+  "inspection.abnormalDesc": "异常描述",
+  "inspection.normal": "正常",
+  "inspection.abnormal": "异常",
+  "inspection.last": "上一步",
+  "inspection.next": "下一步",
+  "inspection.finish": "完成提交",
 
+  // ------------------- 库存查询 -------------------
+  "inventory.title": "库存查询",
+  "inventory.searchHint": "请输入设备",
+  "inventory.deviceName": "设备名称:",
+  "inventory.costCenter": "库位:",
+  "inventory.quantity": "库存:",
+  "inventory.search.title": "筛选条件",
+  "inventory.search.factory": "工厂",
+  "inventory.search.storageLocation": "库存地点",
+  "inventory.search.costCenter": "成本中心",
+  "inventory.search.materialCode": "物料编码",
+  "inventory.search.materialCodeHint": "请输入物料编码",
+  "inventory.search.materialName": "物料名称",
+  "inventory.search.materialNameHint": "请输入物料名称",
+  "inventory.search.storageTime": "入库时间",
+  "inventory.search.storageTimeHint": "请选择时间",
+  "inventory.search.reset": "重置",
 
-	// -------------------保养工单----------------------------
+  // ------------------- 消息管理 -------------------
+  "message.title": "消息管理",
+  "message.tab1": "待办任务",
+  "message.tab2": "任务审批",
+  "message.tab3": "系统消息",
+  "message.id": "编号",
+  "message.processId": "工单编号: ",
+  "message.startUser": "报修人: ",
+  "message.deviceName": "设备名称: ",
+  "message.desc": "维修描述: ",
+  "message.faultTime": "报修时间: ",
+  "message.statusName": "最新进展: ",
+  "message.dispatchUser": "负责人",
+  "message.repairType": "维修类型",
+  "message.reason": "审批意见",
+  "message.reason1": "取消理由",
+  "message.cancelHint": "取消后,该审批流程将自动结束",
+  "message.form.errorHint1": "维修负责人不能为空",
+  "message.form.errorHint2": "维修类型不能为空",
+  "message.form.errorHint3": "新审批人不能为空",
+  "message.form.errorHint4": "审批意见不能为空",
+  "message.form.errorHint5": "接收人不能为空",
+  "message.form.errorHint6": "加签处理人不能为空",
+  "message.form.errorHint7": "取消理由不能为空",
+  "message.form.user3": "新审批人",
+  "message.form.user4": "接收人",
+  "message.form.user5": "加签处理人",
+  "message.form.beforeSign": "向前加签",
+  "message.form.afterSign": "向后加签",
 
-	"maintenanceWorkOrder.title": "保养工单",
-	"maintenanceWorkOrder.totalWorkOrders": "工单总数",
-	"maintenanceWorkOrder.createButton": "创建保养工单",
-	"maintenanceWorkOrder.status": "保养状态",
-	"maintenanceWorkOrder.temporaryCreation": "临时新建",
-	"maintenanceWorkOrder.planGenerator": "计划生成",
-	"maintenanceWorkOrder.actualMaintenanceStartTime": "实际保养开始时间",
-	"maintenanceWorkOrder.actualEndTime": "实际保养结束时间",
-	"maintenanceWorkOrder.timeToMaintenance": "距离保养",
-	"maintenanceWorkOrder.maintenanceButton": "去保养",
-	"maintenanceWorkOrder.isPostponed": "是否延期",
-	"maintenanceWorkOrder.createMaintenanceWorkOrder": "新建保养工单",
-	"maintenanceWorkOrder.editMaintenanceWorkOrder": "填报保养工单",
-	"maintenanceWorkOrder.viewMaintenanceWorkOrder": "查看保养工单",
-	"maintenanceWorkOrder.maintenanceType": "保养类型",
-	"maintenanceWorkOrder.maintenanceTypeIn": "内部",
-	"maintenanceWorkOrder.maintenanceTypeOut": "委外",
-	"maintenanceWorkOrder.maintenanceCost": "保养费用",
-	"maintenanceWorkOrder.otherCost": "其他费用",
-	"maintenanceWorkOrder.accumulatedRunningTime": "累计运行时间",
-	"maintenanceWorkOrder.accumulatedRunningMileage": "累计运行里数",
-	"maintenanceWorkOrder.maintenanceItems": "保养项",
-	"maintenanceWorkOrder.materialSelected": "是否已选物料",
-	"maintenanceWorkOrder.extendMaintenance": "延保",
-	"maintenanceWorkOrder.timeNotBeEarlier": "实际保养结束时间不能早于实际保养开始时间",
-	"maintenanceWorkOrder.bomEmpty": "请至少添加一条设备保养明细",
-	"maintenanceWorkOrder.materialEmpty": "请至少添加一条物料",
-	"maintenanceWorkOrder.materialUnselected": "未选择物料",
-	"maintenanceWorkOrder.equipment": "设备",
-	"maintenanceWorkOrder.maintenanceItemConfiguration": "保养项配置",
-	"maintenanceWorkOrder.noMaintenanceItems":"当前所选的设备没有保养项,请重新选择",
-	// 基础保养记录模块
-	"maintenanceWorkOrder.basicMaintenanceRecords": "基础保养记录",
-	"maintenanceWorkOrder.lastMaintenanceMileage": "上次保养里程数(KM)",
-	"maintenanceWorkOrder.delayedKilometers": "推迟公里数(KM)",
-	"maintenanceWorkOrder.lastMaintenanceRunningTime": "上次保养运行时间(H)",
-	"maintenanceWorkOrder.delayedDuration": "推迟时长(H)",
-	"maintenanceWorkOrder.lastMaintenanceNaturalDate": "上次保养自然日期",
-	"maintenanceWorkOrder.delayedNaturalDate": "推迟自然日期(D)",
-	// 运行规则配置模块(里程、时间区分)
-	"maintenanceWorkOrder.runningMileageRuleConfig": "运行里程规则配置",
-	"maintenanceWorkOrder.runningMileageCycle": "运行里程周期(KM)",
-	"maintenanceWorkOrder.runningMileageCycleLead": "运行里程周期-提前量(KM)",
-	"maintenanceWorkOrder.runningTimeRuleConfig": "运行时间规则配置",
-	"maintenanceWorkOrder.runningTimeCycle": "运行时间周期(H)",
-	"maintenanceWorkOrder.runningTimeCycleLead": "运行时间周期-提前量(H)",
-	// 自然日规则配置模块
-	"maintenanceWorkOrder.naturalDateRuleConfig": "自然日规则配置",
-	"maintenanceWorkOrder.naturalDateCycle": "自然日周期(D)",
-	"maintenanceWorkOrder.naturalDateCycleLead": "自然日周期-提前量(D)",
+  // ------------------- 状态变更 -------------------
+  "statusChange.title": "设备状态变更",
+  "statusChange.insert": "+ 新建  ",
+  "statusChange.searchHint": "请输入资产编码",
+  "statusChange.deviceName": "设备名称",
+  "statusChange.deviceCode": "设备编码",
+  "statusChange.beforeLeader": "调整前责任人",
+  "statusChange.afterLeader": "调整后责任人",
+  "statusChange.reason": "调整原因",
+  "statusChange.createUser": "调整人",
+  "statusChange.assetCode": "资产编码",
+  "statusChange.dept": "所在部门",
+  "statusChange.createDate": "创建时间",
+  "statusChange.beforeStatus": "变更前状态",
+  "statusChange.afterStatus": "变更后状态",
+  "statusChange.history": "历史",
+  "statusChange.history.title": "设备状态调整记录",
+  "statusChange.form.title": "新增设备变更",
+  "statusChange.form.device": "设备",
+  "statusChange.form.deviceHint": "请选择设备",
+  "statusChange.form.deviceError": "设备不能为空",
+  "statusChange.form.selectDevice": "选择设备",
+  "statusChange.form.status": "设备状态",
+  "statusChange.form.statusHint": "请选择设备状态",
+  "statusChange.form.statusError": "设备状态不能为空",
+  "statusChange.form.statusTitle": "变更状态",
+  "statusChange.form.reason": "调整原因",
+  "statusChange.form.reasonHint": "请输入调整原因",
+  "statusChange.form.reasonError": "调整原因不能为空",
+  "statusChange.form.searchHint": "搜索设备名称/资产编码",
+  "statusChange.form.success": "提交成功",
 
-	// -------------------设备维修-------------------
+  // ------------------- 状态变更 -------------------
+  "realTimeData.title": "设备实时数据监控",
+  "realTimeData.status.online": "在线",
+  "realTimeData.status.offline": "离线",
+  "realTimeData.number": "编号:",
+  "realTimeData.type": "类型:",
 
-	"equipmentMaintenance.title": "设备维修",
-	"equipmentMaintenance.searchHint": "请输入设备名称",
-	"equipmentMaintenance.averageResolutionTime": "平均解决时间",
-	"equipmentMaintenance.createButton": "创建维修工单",
-	"equipmentMaintenance.createWorkOrder": "新建维修工单",
-	"equipmentMaintenance.editWorkOrder": "填报维修工单",
-	"equipmentMaintenance.viewWorkOrder": "查看维修工单",
-	"equipmentMaintenance.repairCode": "维修编码",
-	"equipmentMaintenance.maintenanceStartTime": "维修开始时间",
-	"equipmentMaintenance.maintenanceEndTime": "维修结束时间",
-	"equipmentMaintenance.isStop": "是否停机",
-	"equipmentMaintenance.maintenanceType": "维修类型",
-	"equipmentMaintenance.description": "维修描述",
-	"equipmentMaintenance.cost": "维修费用",
-	"equipmentMaintenance.maintenanceItems": "维修项",
-	
+  // ------------------- 状态变更详情 -------------------
+  "realTimeData.detail.title": "设备实时数据详情",
+  "realTimeData.detail.assetCode": "资产编码:",
+  "realTimeData.detail.isOnline": "是否在线:",
+  "realTimeData.detail.deviceType": "设备类别:",
+  "realTimeData.detail.lastUpdateTime": "最后数据:",
+  "realTimeData.detail.chartTitle": "数据趋势",
 
-	// -------------------故障------------------------
-	"fault.createButton": "创建故障工单",
-	"fault.createWorkOrder": "新建故障工单",
-	"fault.editWorkOrder": "编辑故障工单",
-	"fault.viewWorkOrder": "查看故障详情",
-	"fault.faultTotal": "故障上报总数",
-	"fault.faultCode": "故障编码",
-	"fault.faultName": "故障名称",
-	"fault.faultTime": "故障时间",
-	"fault.faultResolutionTime": "故障解决时间",
-	"fault.faultImpact": "故障影响",
-	"fault.faultSystem": "故障系统",
-	"fault.description": "故障描述",
-	"fault.solution": "解决办法",
-	"fault.timeNotBeEarlier": "故障解决时间不得早于故障时间",
-	
+  // ------------------- 台账 -------------------
+  "ledger.title": "设备台账",
+  "ledger.deviceStatus": "设备状态: ",
+  "ledger.form.title": "新建台账",
+  "ledger.form.basicInfo": "基本信息:",
+  "ledger.form.deviceCode": "设备编码",
+  "ledger.form.deviceCodeError": "设备编码不能为空",
+  "ledger.form.deviceName": "设备名称",
+  "ledger.form.deviceNameError": "设备名称不能为空",
+  "ledger.form.brand": "品牌",
+  "ledger.form.brandError": "品牌不能为空",
+  "ledger.form.dept": "所在部门",
+  "ledger.form.deptError": "所在部门不能为空",
+  "ledger.form.deviceType": "设备类别",
+  "ledger.form.deviceTypeError": "设备类别不能为空",
+  "ledger.form.deviceStatus": "设备状态",
+  "ledger.form.deviceStatusError": "设备状态为空",
+  "ledger.form.assetProperty": "资产性质",
+  "ledger.form.assetPropertyError": "资产性质不能为空",
+  "ledger.form.model": "规格型号",
+  "ledger.form.image": "图片",
+  "ledger.form.remark": "备注",
+  "ledger.form.produceInfo": "制造信息:",
+  "ledger.form.manufacturer": "制造商",
+  "ledger.form.manufacturerError": "制造商不能为空",
+  "ledger.form.manDate": "生产日期",
+  "ledger.form.manDateError": "生产日期不能为空",
+  "ledger.form.supplier": "供应商",
+  "ledger.form.expires": "质保到期",
+  "ledger.form.nameplate": "铭牌信息",
+  "ledger.form.financeInfo": "财务信息:",
+  "ledger.form.plPrice": "采购价格",
+  "ledger.form.plDate": "采购日期",
+  "ledger.form.plYear": "折旧年限",
+  "ledger.form.plStartDate": "折旧开始日期",
+  "ledger.form.plMonth": "已提折旧月数",
+  "ledger.form.plAmounted": "已提折旧金额",
+  "ledger.form.remainAmount": "剩余金额",
+  "ledger.supplier.name": "客商名称",
+  "ledger.supplier.nameHint": "请输入供应商名称",
+  "ledger.supplier.code": "客商编号",
+  "ledger.supplier.type": "客商分类",
+  "ledger.supplier.status": "客商状态",
+  "ledger.supplier.time": "创建时间",
+  "ledger.supplier.status1": "草稿",
+  "ledger.supplier.status2": "活动",
+  "ledger.supplier.status3": "关闭",
+  "ledger.brand.hint": "请先选择品牌",
+  "ledger.brand.id": "字典编码",
+  "ledger.brand.label": "字典标签",
+  "ledger.brand.labelHint": "请输入品牌名称",
+  "ledger.brand.status": "状态",
+  "ledger.brand.status0": "正常",
+  "ledger.brand.status1": "关闭",
+  "ledger.model.name": "型号名称",
+  "ledger.model.standard": "符合标准",
+  "ledger.detail.title": "设备台账详情",
+  "ledger.detail.section": "设备信息详情:",
+  "ledger.detail.user": "责任人",
+  "ledger.detail.assetType": "资产类别",
 
-	// ------------------巡检工单----------------------
-	"inspection.title": "巡检工单",
-	"inspection.totalWorkOrders": "巡检总数",
-	"inspection.editWorkOrder": "巡检工单填写",
-	"inspection.viewWorkOrder": "巡检工单详情",
-	"inspection.clickView": "点击查看",
-	"inspection.proj": "巡检项目",
-	"inspection.projItem": "巡检项",
-	"inspection.standard": "巡检标准",
-	"inspection.standardFile": "附件:",
-	"inspection.isAbnormal": "是否异常",
-	"inspection.abnormalDesc": "异常描述",
-	"inspection.normal": "正常",
-	"inspection.abnormal": "异常",
-	"inspection.last": "上一步",
-	"inspection.next": "下一步",
-	"inspection.finish": "完成提交",
-
-
-
-
-	// ------------------- 库存查询 -------------------
-	"inventory.title": "库存查询",
-	"inventory.searchHint": "请输入设备",
-	"inventory.deviceName": "设备名称:",
-	"inventory.costCenter": "库位:",
-	"inventory.quantity": "库存:",
-	"inventory.search.title": "筛选条件",
-	"inventory.search.factory": "工厂",
-	"inventory.search.storageLocation": "库存地点",
-	"inventory.search.costCenter": "成本中心",
-	"inventory.search.materialCode": "物料编码",
-	"inventory.search.materialCodeHint": "请输入物料编码",
-	"inventory.search.materialName": "物料名称",
-	"inventory.search.materialNameHint": "请输入物料名称",
-	"inventory.search.storageTime": "入库时间",
-	"inventory.search.storageTimeHint": "请选择时间",
-	"inventory.search.reset": "重置",
-
-	// ------------------- 消息管理 -------------------
-	"message.title": "消息管理",
-	"message.tab1": "待办任务",
-	"message.tab2": "任务审批",
-	"message.tab3": "系统消息",
-	"message.id": "编号",
-	"message.processId": "工单编号: ",
-	"message.startUser": "报修人: ",
-	"message.deviceName": "设备名称: ",
-	"message.desc": "维修描述: ",
-	"message.faultTime": "报修时间: ",
-	"message.statusName": "最新进展: ",
-	"message.dispatchUser": "负责人",
-	"message.repairType": "维修类型",
-	"message.reason": "审批意见",
-	"message.reason1": "取消理由",
-	"message.cancelHint": "取消后,该审批流程将自动结束",
-	"message.form.errorHint1": "维修负责人不能为空",
-	"message.form.errorHint2": "维修类型不能为空",
-	"message.form.errorHint3": "新审批人不能为空",
-	"message.form.errorHint4": "审批意见不能为空",
-	"message.form.errorHint5": "接收人不能为空",
-	"message.form.errorHint6": "加签处理人不能为空",
-	"message.form.errorHint7": "取消理由不能为空",
-	"message.form.user3": "新审批人",
-	"message.form.user4": "接收人",
-	"message.form.user5": "加签处理人",
-	"message.form.beforeSign": "向前加签",
-	"message.form.afterSign": "向后加签",
-
-	// ------------------- 状态变更 -------------------
-	"statusChange.title": "设备状态变更",
-	"statusChange.insert": "+ 新建  ",
-	"statusChange.searchHint": "请输入资产编码",
-	"statusChange.deviceName": "设备名称",
-	"statusChange.deviceCode": "设备编码",
-	"statusChange.beforeLeader": "调整前责任人",
-	"statusChange.afterLeader": "调整后责任人",
-	"statusChange.reason": "调整原因",
-	"statusChange.createUser": "调整人",
-	"statusChange.assetCode": "资产编码",
-	"statusChange.dept": "所在部门",
-	"statusChange.createDate": "创建时间",
-	"statusChange.beforeStatus": "变更前状态",
-	"statusChange.afterStatus": "变更后状态",
-	"statusChange.history": "历史",
-	"statusChange.history.title": "设备状态调整记录",
-	"statusChange.form.title": "新增设备变更",
-	"statusChange.form.device": "设备",
-	"statusChange.form.deviceHint": "请选择设备",
-	"statusChange.form.deviceError": "设备不能为空",
-	"statusChange.form.selectDevice": "选择设备",
-	"statusChange.form.status": "设备状态",
-	"statusChange.form.statusHint": "请选择设备状态",
-	"statusChange.form.statusError": "设备状态不能为空",
-	"statusChange.form.statusTitle": "变更状态",
-	"statusChange.form.reason": "调整原因",
-	"statusChange.form.reasonHint": "请输入调整原因",
-	"statusChange.form.reasonError": "调整原因不能为空",
-	"statusChange.form.searchHint": "搜索设备名称/资产编码",
-	"statusChange.form.success": "提交成功",
-
-	// ------------------- 状态变更 -------------------
-	"realTimeData.title": "设备实时数据监控",
-	"realTimeData.status.online": "在线",
-	"realTimeData.status.offline": "离线",
-	"realTimeData.number": "编号:",
-	"realTimeData.type": "类型:",
-
-	// ------------------- 状态变更详情 -------------------
-	"realTimeData.detail.title": "设备实时数据详情",
-	"realTimeData.detail.assetCode": "资产编码:",
-	"realTimeData.detail.isOnline": "是否在线:",
-	"realTimeData.detail.deviceType": "设备类别:",
-	"realTimeData.detail.lastUpdateTime": "最后数据:",
-	"realTimeData.detail.chartTitle": "数据趋势",
-
-	// ------------------- 台账 -------------------
-	"ledger.title": "设备台账",
-	"ledger.deviceStatus": "设备状态: ",
-	"ledger.form.title": "新建台账",
-	"ledger.form.basicInfo": "基本信息:",
-	"ledger.form.deviceCode": "设备编码",
-	"ledger.form.deviceCodeError": "设备编码不能为空",
-	"ledger.form.deviceName": "设备名称",
-	"ledger.form.deviceNameError": "设备名称不能为空",
-	"ledger.form.brand": "品牌",
-	"ledger.form.brandError": "品牌不能为空",
-	"ledger.form.dept": "所在部门",
-	"ledger.form.deptError": "所在部门不能为空",
-	"ledger.form.deviceType": "设备类别",
-	"ledger.form.deviceTypeError": "设备类别不能为空",
-	"ledger.form.deviceStatus": "设备状态",
-	"ledger.form.deviceStatusError": "设备状态为空",
-	"ledger.form.assetProperty": "资产性质",
-	"ledger.form.assetPropertyError": "资产性质不能为空",
-	"ledger.form.model": "规格型号",
-	"ledger.form.image": "图片",
-	"ledger.form.remark": "备注",
-	"ledger.form.produceInfo": "制造信息:",
-	"ledger.form.manufacturer": "制造商",
-	"ledger.form.manufacturerError": "制造商不能为空",
-	"ledger.form.manDate": "生产日期",
-	"ledger.form.manDateError": "生产日期不能为空",
-	"ledger.form.supplier": "供应商",
-	"ledger.form.expires": "质保到期",
-	"ledger.form.nameplate": "铭牌信息",
-	"ledger.form.financeInfo": "财务信息:",
-	"ledger.form.plPrice": "采购价格",
-	"ledger.form.plDate": "采购日期",
-	"ledger.form.plYear": "折旧年限",
-	"ledger.form.plStartDate": "折旧开始日期",
-	"ledger.form.plMonth": "已提折旧月数",
-	"ledger.form.plAmounted": "已提折旧金额",
-	"ledger.form.remainAmount": "剩余金额",
-	"ledger.supplier.name": "客商名称",
-	"ledger.supplier.nameHint": "请输入供应商名称",
-	"ledger.supplier.code": "客商编号",
-	"ledger.supplier.type": "客商分类",
-	"ledger.supplier.status": "客商状态",
-	"ledger.supplier.time": "创建时间",
-	"ledger.supplier.status1": "草稿",
-	"ledger.supplier.status2": "活动",
-	"ledger.supplier.status3": "关闭",
-	"ledger.brand.hint": "请先选择品牌",
-	"ledger.brand.id": "字典编码",
-	"ledger.brand.label": "字典标签",
-	"ledger.brand.labelHint": "请输入品牌名称",
-	"ledger.brand.status": "状态",
-	"ledger.brand.status0": "正常",
-	"ledger.brand.status1": "关闭",
-	"ledger.model.name": "型号名称",
-	"ledger.model.standard": "符合标准",
-	"ledger.detail.title": "设备台账详情",
-	"ledger.detail.section": "设备信息详情:",
-	"ledger.detail.user": "责任人",
-	"ledger.detail.assetType": "资产类别",
-
-	// ------------------- 统计分析 -------------------
-	"statistic.title": "统计分析",
-	"statistic.tab1": "维修统计",
-	"statistic.tab2": "保养统计",
-	"statistic.tab3": "巡检统计",
-	"statistic.repair.resolutionTime": "平均解决时间",
-	"statistic.repair.weeklyCount": "近一周工单数量",
-	"statistic.repair.monthlyCount": "近一月工单数量",
-	"statistic.repair.totalCount": "工单总数量",
-	"statistic.repair.report": "故障上报",
-	"statistic.repair.workOrder": "维修工单",
-	"statistic.repair.failure.title": "故障上报状态统计",
-	"statistic.repair.failure.reporting": "上报中",
-	"statistic.repair.failure.finished": "处理完成",
-	"statistic.repair.failure.trans": "转工单",
-	"statistic.repair.failure.over": "工单处理完成",
-	"statistic.repair.workOrder.title": "维修工单状态统计",
-	"statistic.repair.workOrder.tx": "待填写",
-	"statistic.repair.workOrder.finished": "已完成",
-	"statistic.repair.title": "维修任务统计分析",
-	"statistic.repair.completionRate": "维修完成率",
-	"statistic.repair.repairedCount": "已维修",
-	"statistic.repair.pendingRepairCount": "待维修",
-	"statistic.maintenance.dayCount": "昨日工单数量",
-	"statistic.maintenance.count1": "总数量",
-	"statistic.maintenance.count2": "未完成",
-	"statistic.maintenance.weeklyCount": "近一周工单数量",
-	"statistic.maintenance.monthlyCount": "近一月工单数量",
-	"statistic.maintenance.totalCount": "工单数量",
-	"statistic.maintenance.workOrder.title": "保养工单状态统计",
-	"statistic.maintenance.workOrder.status1": "待执行",
-	"statistic.maintenance.workOrder.status2": "已执行",
-	"statistic.maintenance.dayWorkOrder.title": "今日工单状态统计",
-	"statistic.maintenance.orderType.title": "工单类型统计",
-	"statistic.maintenance.orderType.status1": "临时新建",
-	"statistic.maintenance.orderType.status2": "计划生成",
-	"statistic.inspection.workOrder.title": "巡检工单状态统计"
-}
+  // ------------------- 统计分析 -------------------
+  "statistic.title": "统计分析",
+  "statistic.tab1": "维修统计",
+  "statistic.tab2": "保养统计",
+  "statistic.tab3": "巡检统计",
+  "statistic.repair.resolutionTime": "平均解决时间",
+  "statistic.repair.weeklyCount": "近一周工单数量",
+  "statistic.repair.monthlyCount": "近一月工单数量",
+  "statistic.repair.totalCount": "工单总数量",
+  "statistic.repair.report": "故障上报",
+  "statistic.repair.workOrder": "维修工单",
+  "statistic.repair.failure.title": "故障上报状态统计",
+  "statistic.repair.failure.reporting": "上报中",
+  "statistic.repair.failure.finished": "处理完成",
+  "statistic.repair.failure.trans": "转工单",
+  "statistic.repair.failure.over": "工单处理完成",
+  "statistic.repair.workOrder.title": "维修工单状态统计",
+  "statistic.repair.workOrder.tx": "待填写",
+  "statistic.repair.workOrder.finished": "已完成",
+  "statistic.repair.title": "维修任务统计分析",
+  "statistic.repair.completionRate": "维修完成率",
+  "statistic.repair.repairedCount": "已维修",
+  "statistic.repair.pendingRepairCount": "待维修",
+  "statistic.maintenance.dayCount": "昨日工单数量",
+  "statistic.maintenance.count1": "总数量",
+  "statistic.maintenance.count2": "未完成",
+  "statistic.maintenance.weeklyCount": "近一周工单数量",
+  "statistic.maintenance.monthlyCount": "近一月工单数量",
+  "statistic.maintenance.totalCount": "工单数量",
+  "statistic.maintenance.workOrder.title": "保养工单状态统计",
+  "statistic.maintenance.workOrder.status1": "待执行",
+  "statistic.maintenance.workOrder.status2": "已执行",
+  "statistic.maintenance.dayWorkOrder.title": "今日工单状态统计",
+  "statistic.maintenance.orderType.title": "工单类型统计",
+  "statistic.maintenance.orderType.status1": "临时新建",
+  "statistic.maintenance.orderType.status2": "计划生成",
+  "statistic.inspection.workOrder.title": "巡检工单状态统计"
+}

+ 288 - 65
pages/recordFilling/detail.vue

@@ -4,8 +4,7 @@
     ref="paging"
     v-model="dataList"
     :loading-more-enabled="true"
-    @query="queryList"
-  >
+    @query="queryList">
     <!-- z-paging默认铺满全屏,此时页面所有view都应放在z-paging标签内,否则会被盖住 -->
     <!-- 需要固定在页面顶部的view请通过slot="top"插入,包括自定义的导航栏 -->
     <template #top>
@@ -35,6 +34,12 @@
             <span>{{ params.createTime }}</span>
           </view>
         </view>
+        <view class="item-content flex-row align-center">
+          <view class="item-title full-cell flex-row align-center">
+            <span class="item-title-width">井号:</span>
+            <span>{{ params.wellName || "" }}</span>
+          </view>
+        </view>
       </view>
     </template>
     <!-- 填报列表 -->
@@ -54,8 +59,7 @@
         </view>
         <view
           class="item-content flex-row align-center justify-between bold"
-          v-for="sum in item.sumList"
-        >
+          v-for="sum in item.sumList">
           <view class="item-title flex-row align-center word-break-all">
             <span>{{ sum.name }}:</span>
           </view>
@@ -68,20 +72,19 @@
               :value="`${sum.totalRunTime} ${
                 sum.modelAttr ? (sum.modelAttr.includes('Time') ? 'h' : '') : ''
               }`"
-              :disabled="true"
-            ></uni-easyinput>
+              :disabled="true"></uni-easyinput>
           </view>
         </view>
         <view
           class="item-content flex-col align-center justify-between"
           :class="{ 'bottom-bold': item.nonSumList.length > 0 }"
-          v-for="nosum in item.nonSumList"
-        >
+          v-for="nosum in item.nonSumList.filter(
+            nosum => !keys.includes(nosum.description)
+          )">
           <!-- isCollection为1,提示:以下数值取自PLC,如有不符请修改 -->
           <uni-notice-bar
             :text="$t('operationRecordFilling.plcNotice')"
-            v-if="nosum.isCollection == 1"
-          />
+            v-if="nosum.isCollection == 1" />
           <view class="flex-row align-center justify-between item-content">
             <view class="item-title flex-row align-center">
               <span>{{ nosum.name }}:</span>
@@ -90,8 +93,7 @@
             <!-- type为double时,输入框为数字类型 -->
             <view
               class="item-value flex-row align-center justify-end"
-              v-if="nosum.type == 'double'"
-            >
+              v-if="nosum.type == 'double'">
               <uni-easyinput
                 style="text-align: right"
                 :styles="{ disableColor: '#fff' }"
@@ -106,14 +108,12 @@
                     ? checkThreshold(nosum)
                     : checkLessThreshold(nosum)
                 "
-                @input="handleRealTimeUpdate(nosum, item)"
-              ></uni-easyinput>
+                @input="handleRealTimeUpdate(nosum, item)"></uni-easyinput>
             </view>
             <!-- type为textarea时,输入框为文本类型 -->
             <view
               class="item-value flex-row align-center justify-end"
-              v-else-if="nosum.type == 'textarea'"
-            >
+              v-else-if="nosum.type == 'textarea'">
               <uni-easyinput
                 style="text-align: right"
                 :styles="{ disableColor: '#fff' }"
@@ -124,14 +124,12 @@
                 v-model="nosum.fillContent"
                 :type="'textarea'"
                 :autoHeight="true"
-                :maxlength="-1"
-              ></uni-easyinput>
+                :maxlength="-1"></uni-easyinput>
             </view>
             <!-- type为enum时,使用下拉菜单 -->
             <view
               class="item-value select flex-row align-center justify-end"
-              v-else-if="nosum.type == 'enum' && nosum.description !== null"
-            >
+              v-else-if="nosum.type == 'enum' && nosum.description !== null">
               <uni-data-select
                 :localdata="nosum.enumList"
                 style="text-align: right"
@@ -139,8 +137,7 @@
                 :clear="false"
                 :disabled="!isView"
                 :placeholder="$t('operation.PleaseSelect')"
-                v-model="nosum.fillContent"
-              ></uni-data-select>
+                v-model="nosum.fillContent"></uni-data-select>
             </view>
             <!-- 其他类型时,输入框为文本类型 -->
             <view class="item-value flex-row align-center justify-end" v-else>
@@ -152,11 +149,51 @@
                 :placeholder="$t('operation.PleaseFillIn')"
                 :disabled="!isView"
                 v-model="nosum.fillContent"
-                :type="'text'"
-              ></uni-easyinput>
+                :type="'text'"></uni-easyinput>
             </view>
           </view>
         </view>
+        <!-- {{ nosum.name }} {{ nosum.description }} -->
+        <uni-forms
+          ref="formRef"
+          labelWidth="auto"
+          validateTrigger="submit"
+          err-show-type="toast"
+          :model="{ nonSumList: item.nonSumList }">
+          <template
+            v-for="(nosum, nosumIndex) in item.nonSumList"
+            :key="nosumIndex">
+            <uni-forms-item
+              v-if="keys.includes(nosum.description)"
+              :label="nosum.name"
+              :rules="rules[nosum.description]?.(index)"
+              :name="['nonSumList', nosumIndex, 'fillContent']">
+              <uni-easyinput
+                v-if="nosum.description !== 'otherNptReason'"
+                type="number"
+                :placeholder="$t('operation.PleaseFillIn')"
+                style="text-align: right"
+                :styles="{ disableColor: '#fff' }"
+                :inputBorder="false"
+                :clearable="false"
+                :disabled="!isView"
+                v-model.number="nosum.fillContent"
+                @input="val => onInputChange(val, nosum)" />
+              <uni-easyinput
+                v-else
+                type="textarea"
+                autoHeight
+                :placeholder="$t('operation.PleaseFillIn')"
+                style="text-align: right"
+                :styles="{ disableColor: '#fff' }"
+                :inputBorder="false"
+                :clearable="false"
+                :disabled="!isView"
+                v-model="nosum.fillContent"
+                :maxlength="1000" />
+            </uni-forms-item>
+          </template>
+        </uni-forms>
       </view>
     </view>
     <!-- 如果需要使用页脚,请使用slot="bottom"slot节点不支持通过v-if或v-show动态显示/隐藏,若需要动态控制,可将v-if添加在其子节点上 -->
@@ -166,8 +203,7 @@
         type="primary"
         @click="onSubmit()"
         :disabled="dataList.length < totalNum || isSubmitting"
-        v-if="isView"
-      >
+        v-if="isView">
         {{ isSubmitting ? "提交中" : $t("operation.save") }}
       </button>
     </template>
@@ -175,20 +211,17 @@
 </template>
 
 <script setup>
-import { ref, reactive, getCurrentInstance, watch, onMounted } from "vue";
+import { ref, reactive, getCurrentInstance, watch } from "vue";
 import { onReady, onLoad } from "@dcloudio/uni-app";
 import dayjs from "dayjs";
 import {
-  getRecordFillingDetailGetPage,
-  getRecordFillingDetailGetAttrs,
-  recordFillingDetailInsertLog,
   getRecordFillingDetail,
   recordFillingUpOperationOrder,
   recordFillingDetailGetPageAndAttrs,
   recordFillingDetailInsertDataList,
   getDeptName,
 } from "@/api/recordFilling";
-import { getUserId, reloginByUserId } from "@/utils/auth.js";
+import { reloginByUserId } from "@/utils/auth.js";
 import { useDataDictStore } from "@/store/modules/dataDict";
 // 引用全局变量$t
 const { appContext } = getCurrentInstance();
@@ -197,6 +230,128 @@ const t = appContext.config.globalProperties.$t;
 // 获取字典项
 const { getStrDictOptions, getIntDictOptions } = useDataDictStore();
 
+const NON_KEYS = [
+  "repairTime",
+  "selfStopTime",
+  "accidentTime",
+  "complexityTime",
+  "rectificationTime",
+  "waitingStopTime",
+  "partyaDesign",
+  "partyaPrepare",
+  "partyaResource",
+  "relocationTime",
+  "winterBreakTime",
+  "otherNptTime",
+];
+
+const keys = [
+  "repairTime",
+  "selfStopTime",
+  "accidentTime",
+  "complexityTime",
+  "rectificationTime",
+  "waitingStopTime",
+  "partyaDesign",
+  "partyaPrepare",
+  "partyaResource",
+  "relocationTime",
+  "winterBreakTime",
+  "otherNptTime",
+  "drillingWorkingTime",
+  "otherProductionTime",
+  "ratedProductionTime",
+  "productionTime",
+  "dailyInjectGasTime",
+  "otherNptReason",
+];
+
+const sumNonProdTimes = index => {
+  let sum = 0;
+  const { nonSumList } = dataList.value[index];
+  NON_KEYS.forEach(field => {
+    sum += Number(
+      (nonSumList || []).find(item => item.description === field)
+        ?.fillContent || 0
+    );
+  });
+  return sum;
+};
+
+const handleInputRaw = (val, item) => {
+  let num = Number(val);
+  if (val === "" || isNaN(num) || num < 0) {
+    num = 0;
+  } else if (num > 24) {
+    num = 24;
+  }
+  item.fillContent = num;
+};
+const onInputChange = debounce(handleInputRaw, 500);
+
+// 校验函数:总时间必须为 24
+const ryValidateTotalTime = index => (rule, value, data, callback) => {
+  const { nonSumList } = dataList.value[index];
+
+  const drillingTime = Number(
+    (nonSumList || []).find(item => item.description === "drillingWorkingTime")
+      ?.fillContent || 0
+  );
+
+  const otherTime = Number(
+    (nonSumList || []).find(item => item.description === "otherProductionTime")
+      ?.fillContent || 0
+  );
+
+  const nonProdSum = sumNonProdTimes(index);
+
+  let total = 0;
+  let msg = "";
+
+  total = parseFloat((drillingTime + otherTime + nonProdSum).toFixed(2));
+  msg = `进尺(${drillingTime})+其他(${otherTime})+非生产(${nonProdSum})=${total}H,必须为24H`;
+
+  if (Math.abs(total - 24) > 0.01) {
+    callback(msg);
+  }
+  return true;
+};
+
+const rhValidateTotalTime = index => (rule, value, data, callback) => {
+  const { nonSumList } = dataList.value[index];
+
+  const gasTime = Number(
+    (nonSumList || []).find(item => item.description === "dailyInjectGasTime")
+      ?.fillContent || 0
+  );
+
+  const nonProdSum = sumNonProdTimes(index);
+
+  let total = 0;
+  let msg = "";
+
+  total = parseFloat((gasTime + nonProdSum).toFixed(2));
+  msg = `运转(${gasTime})+非生产(${nonProdSum})=${total}H,必须为24H`;
+
+  console.log("total :>> ", total);
+
+  if (Math.abs(total - 24) > 0.01) {
+    callback(msg);
+  }
+  return true;
+};
+
+const rules = reactive({
+  drillingWorkingTime: index => [
+    { required: true, errorMessage: "请输入进尺工作时间" },
+    { validateFunction: ryValidateTotalTime(index) },
+  ],
+  dailyInjectGasTime: index => [
+    { required: true, errorMessage: "请输入当日运转时间" },
+    { validateFunction: rhValidateTotalTime(index) },
+  ],
+});
+
 // -------------------------------------
 const isFromMsg = ref(false);
 const params = ref({});
@@ -206,8 +361,8 @@ let deptName = ref("");
 // 累加状态对象,用于在生产日报加载前存储累加值
 const accumulatedValues = reactive({
   "当日注水量-方": 0,
-  当日用电量kWh: 0,
-  当日运转时间H: 0,
+  "当日用电量kWh": 0,
+  "当日运转时间H": 0,
   "当日注气量-方": 0,
 });
 
@@ -215,7 +370,7 @@ onReady(() => {
   console.log("onReady");
 });
 
-onLoad(async (option) => {
+onLoad(async option => {
   console.log("onLoad", option);
   await reloginByUserId(option.reloginUserId);
   isFromMsg.value = !!option.reloginUserId;
@@ -260,7 +415,7 @@ const totalNum = ref(0);
 // 监听dataList变化,初始化时计算一次总和
 watch(
   dataList,
-  (newVal) => {
+  newVal => {
     // calculateTotalRunTime();
   },
   { deep: true }
@@ -297,7 +452,7 @@ const handleFillContentChange = (nosum, deviceItem) => {
 function debounce(func, delay) {
   let timer;
   return function (...args) {
-    clearTimeout(timer);
+    if (timer) clearTimeout(timer);
     timer = setTimeout(() => func.apply(this, args), delay);
   };
 }
@@ -316,9 +471,9 @@ const debouncedApplyAccumulatedToReport = debounce(
  */
 const updateAccumulatedValue = (fieldName, deviceType) => {
   let total = 0;
-  dataList.value.forEach((item) => {
+  dataList.value.forEach(item => {
     if (item.deviceName.includes(deviceType) && item.nonSumList) {
-      item.nonSumList.forEach((nonSum) => {
+      item.nonSumList.forEach(nonSum => {
         if (
           nonSum.type === "double" &&
           nonSum.name === fieldName &&
@@ -358,7 +513,7 @@ function applyAccumulatedToReport() {
   recalculateAllAccumulatedValues();
 
   const reportItem = dataList.value.find(
-    (item) => item.deviceName === "生产日报"
+    item => item.deviceName === "生产日报"
   );
 
   if (!reportItem) {
@@ -366,9 +521,9 @@ function applyAccumulatedToReport() {
     return;
   }
 
-  Object.keys(accumulatedValues).forEach((fieldName) => {
+  Object.keys(accumulatedValues).forEach(fieldName => {
     const targetItem = reportItem.nonSumList.find(
-      (item) => item.name === fieldName
+      item => item.name === fieldName
     );
     if (targetItem) {
       console.log(
@@ -441,7 +596,7 @@ function calculateTotalRunTime(
   targetFieldName
 ) {
   const reportItem = dataList.value.find(
-    (item) => item.deviceName === "生产日报"
+    item => item.deviceName === "生产日报"
   );
 
   if (!reportItem) {
@@ -450,7 +605,7 @@ function calculateTotalRunTime(
   }
 
   const targetItem = reportItem.nonSumList.find(
-    (item) => item.name === targetFieldName
+    item => item.name === targetFieldName
   );
 
   if (!targetItem) {
@@ -460,9 +615,9 @@ function calculateTotalRunTime(
 
   let total = 0;
 
-  dataList.value.forEach((item) => {
+  dataList.value.forEach(item => {
     if (item.deviceName.includes(deviceNameToMatch) && item.nonSumList) {
-      item.nonSumList.forEach((nonSum) => {
+      item.nonSumList.forEach(nonSum => {
         if (
           nonSum.type === "double" &&
           nonSum.name === sourceFieldName &&
@@ -495,14 +650,14 @@ const queryList = (pageNo, pageSize) => {
     orderId: params.value.orderId,
     // deviceCategoryId: 1,
   })
-    .then(async (res) => {
+    .then(async res => {
       console.log("🚀 ~ res:", res);
       const { data } = res;
       const resList = [].concat(data.list);
       // 列表总数
       totalNum.value = data.total;
       // 遍历列表,处理attrsDetail
-      resList.map(async (item) => {
+      resList.map(async item => {
         const attrParams = {
           deviceCode: item.deviceCode,
           deviceName: item.deviceName,
@@ -526,14 +681,14 @@ const queryList = (pageNo, pageSize) => {
           attrParams.id = attrParams.orderId;
           delete attrParams.orderId;
           delete attrParams.deviceName;
-          resAttrs.map((rtem) => {
+          resAttrs.map(rtem => {
             // 将rtem中sumList和nonSumList两个数组中的
             // fillContent字段判断是否为null, 如果为null,则赋值为0 不为null则保留两位小数
             // 将attrParams合并到两个数组的每个对象中
             // 然后将sumList和nonSumList分别赋值给item的sumList和nonSumList
 
             if (rtem.sumList) {
-              rtem.sumList.map((sumItem) => {
+              rtem.sumList.map(sumItem => {
                 if (sumItem.fillContent == null || sumItem.fillContent == "") {
                   // console.log("🚀 ~ rtem.sumList.map ~ sumItem:", sumItem);
                   // sumItem.fillContent = 0;
@@ -553,7 +708,7 @@ const queryList = (pageNo, pageSize) => {
             }
             if (rtem.nonSumList) {
               //
-              rtem.nonSumList.map((nonSumItem) => {
+              rtem.nonSumList.map(nonSumItem => {
                 if (
                   nonSumItem.fillContent == null ||
                   nonSumItem.fillContent == ""
@@ -582,7 +737,7 @@ const queryList = (pageNo, pageSize) => {
                       ? getIntDictOptions(nonSumItem.description)
                       : getStrDictOptions(nonSumItem.description);
 
-                  nonSumItem.enumList = dictOptions.map((dict) => {
+                  nonSumItem.enumList = dictOptions.map(dict => {
                     return {
                       ...dict,
                       text: dict.label,
@@ -606,7 +761,16 @@ const queryList = (pageNo, pageSize) => {
             }
             item.sumList = rtem.sumList;
 
-            item.nonSumList = rtem.nonSumList;
+            const timeKeys = keys.filter(k => k !== "otherNptReason");
+
+            item.nonSumList = rtem.nonSumList
+              .sort((a, b) => a.modelId - b.modelId)
+              .map(item => {
+                if (timeKeys.includes(item.description)) {
+                  item.fillContent = Number(item.fillContent || 0);
+                }
+                return item;
+              });
           });
           console.log("resAttrs-modelId", resAttrs);
         }
@@ -622,12 +786,12 @@ const queryList = (pageNo, pageSize) => {
       );
 
       // 如果加载的数据中包含生产日报,应用累加值
-      const hasReport = resList.some((item) => item.deviceName === "生产日报");
+      const hasReport = resList.some(item => item.deviceName === "生产日报");
       if (hasReport) {
         applyAccumulatedToReport();
       }
     })
-    .catch((res) => {
+    .catch(res => {
       // 如果请求失败写paging.value.complete(false);
       // 注意,每次都需要在catch中写这句话很麻烦,z-paging提供了方案可以全局统一处理
       // 在底层的网络请求抛出异常时,写uni.$emit('z-paging-error-emit');即可
@@ -672,7 +836,7 @@ const checkRdThreshold = (item, totalValue, maxIncrement, itemName) => {
 };
 
 // 判断是否小于阈值 (<0)
-const checkLessThreshold = (item) => {
+const checkLessThreshold = item => {
   if (item.fillContent < 0) {
     uni.showToast({
       title:
@@ -686,7 +850,7 @@ const checkLessThreshold = (item) => {
   }
 };
 // 判断是否大于阈值
-const checkThreshold = (item) => {
+const checkThreshold = item => {
   checkLessThreshold(item);
   // 如果threshold > 0,则判断fillContent是否大于threshold,如果大于则提示用户填写小于等于threshold的值
   if (item.fillContent > item.threshold) {
@@ -703,7 +867,7 @@ const checkThreshold = (item) => {
 };
 
 // 保留两位小数
-const toFixed = (num) => {
+const toFixed = num => {
   if (num) {
     num = Number(num);
     num = num.toFixed(2);
@@ -967,7 +1131,17 @@ const isSubmitting = ref(false); // 添加提交状态
 //   submitDataWithDisable();
 // };
 
+const formRef = ref(null);
+
 const onSubmit = async () => {
+  if (!formRef.value) return;
+  try {
+    for (const item of formRef.value) {
+      await item.validate();
+    }
+  } catch (error) {
+    return;
+  }
   // 清空之前的超限记录
   rdThresholdExceededItems.value = [];
 
@@ -985,19 +1159,35 @@ const onSubmit = async () => {
     const nonSumList = Array.isArray(item.nonSumList) ? item.nonSumList : [];
 
     // 查找当日运转时间H项目
-    const runtimeItem = nonSumList.find((i) => i.name === "当日运转时间H");
+
+    const otherNptTime = nonSumList.find(i => i.name === "其他非生产时间H");
+    const runtimeItem = nonSumList.find(i => i.name === "当日运转时间H");
     const isRuntime24 =
       runtimeItem &&
       (runtimeItem.fillContent == 24 || runtimeItem.fillContent == "24");
     for (const nonSumItem of nonSumList) {
       // 增加判断条件:如果当日运转时间H等于24,则非生产原因和非生产时间H为非必填,否则为必填
+
+      if (
+        nonSumItem.name === "其他非生产时间原因" &&
+        !nonSumItem.fillContent &&
+        otherNptTime.fillContent > 0
+      ) {
+        uni.showToast({
+          title: "其他非生产时间大于 0 时,必须填写其他非生产时间原因",
+          icon: "none",
+        });
+        return;
+      }
+
       const isExemptField =
         isRuntime24 &&
         (nonSumItem.name === "非生产原因" || nonSumItem.name === "非生产时间H");
       if (
         (!item.isReport || item.isReport != 1) &&
         !isExemptField &&
-        (nonSumItem.fillContent == null || nonSumItem.fillContent === "")
+        (nonSumItem.fillContent == null || nonSumItem.fillContent === "") &&
+        nonSumItem.name !== "其他非生产时间原因"
       ) {
         uni.showToast({
           title:
@@ -1048,7 +1238,7 @@ const onSubmit = async () => {
         // 新增:针对rd公司的特殊阈值检查
         // 检查包含"累计公里数填报"的字段不能超过对应"累计公里数"字段 + 3000
         if (nonSumItem.name.includes("累计公里数填报")) {
-          const correspondingSumItem = item.sumList.find((sumItem) =>
+          const correspondingSumItem = item.sumList.find(sumItem =>
             sumItem.name.includes("累计公里数")
           );
           if (correspondingSumItem) {
@@ -1058,7 +1248,7 @@ const onSubmit = async () => {
         }
         // 检查包含"累计运转时长填报"的字段不能超过对应"累计运转时长"字段 + 100
         else if (nonSumItem.name.includes("累计运转时长填报")) {
-          const correspondingSumItem = item.sumList.find((sumItem) =>
+          const correspondingSumItem = item.sumList.find(sumItem =>
             sumItem.name.includes("累计运转时长")
           );
           if (correspondingSumItem) {
@@ -1088,7 +1278,7 @@ const onSubmit = async () => {
       showCancel: true,
       cancelText: "取消",
       confirmText: "继续",
-      success: (res) => {
+      success: res => {
         if (res.confirm) {
           // 用户选择继续,执行保存操作,此时才设置按钮禁用
           submitDataWithDisable();
@@ -1145,7 +1335,7 @@ const submitDataWithDisable = async () => {
           // 新增:针对rd公司的特殊阈值检查
           // 检查包含"累计公里数填报"的字段不能超过对应"累计公里数"字段 + 3000
           if (nonSumItem.name.includes("累计公里数填报")) {
-            const correspondingSumItem = item.sumList.find((sumItem) =>
+            const correspondingSumItem = item.sumList.find(sumItem =>
               sumItem.name.includes("累计公里数")
             );
             if (correspondingSumItem) {
@@ -1156,7 +1346,7 @@ const submitDataWithDisable = async () => {
           }
           // 检查包含"累计运转时长填报"的字段不能超过对应"累计运转时长"字段 + 100
           else if (nonSumItem.name.includes("累计运转时长填报")) {
-            const correspondingSumItem = item.sumList.find((sumItem) =>
+            const correspondingSumItem = item.sumList.find(sumItem =>
               sumItem.name.includes("累计运转时长")
             );
             if (correspondingSumItem) {
@@ -1201,7 +1391,7 @@ const submitData = async () => {
 
     console.log("处理提交用的副本数据:subDataList", subDataList);
     // 2. 处理提交数据:将nonSumList和sumList合并为新数组并赋值给deviceInfoList对象,将所有的deviceInfoList合并为submitList
-    const submitList = subDataList.map((item) => ({
+    const submitList = subDataList.map(item => ({
       deviceInfoList: [].concat(item.sumList).concat(item.nonSumList),
     }));
     console.log("提交用的数据:submitList", submitList);
@@ -1447,4 +1637,37 @@ const submitData = async () => {
   min-height: inherit;
   margin: 10px;
 }
+
+.uni-forms {
+  .uni-forms-item {
+    display: flex;
+    align-items: center;
+    flex: 1;
+    margin-bottom: 0px;
+    border-bottom: 1px dashed #cacccf;
+  }
+
+  :deep(.uni-forms-item__content) {
+    text-align: right;
+    .readOnly {
+      padding-right: 10px;
+    }
+  }
+
+  :deep(.uni-forms-item__label) {
+    height: 44px;
+    font-weight: 500;
+    font-size: 14px;
+    color: #333333 !important;
+    width: max-content !important;
+  }
+
+  :deep(.uni-easyinput__content-input) {
+    padding: 0 !important;
+  }
+}
+
+:deep(.uni-easyinput__content-textarea) {
+  margin: 0 !important;
+}
 </style>

File diff suppressed because it is too large
+ 965 - 789
pages/ruiDu/compontents/report-form.vue


+ 10 - 2
pages/ruiDu/edit.vue

@@ -15,7 +15,11 @@
       </view>
       <!-- 保养项列表 -->
       <view class="work-order-bom-list" v-show="currentTab === 1">
-        <report-form ref="reportFormEditRef" :report-id="reportId" :report-data="detailData" />
+        <report-form
+          ref="reportFormEditRef"
+          :report-id="reportId"
+          :report-data="detailData"
+          :form-disable="detailData.status !== 0" />
       </view>
       <!-- <view class="work-order-bom-list" v-if="currentTab === 2">
         <report-form-copy ref="reportFormEditRef" :report-id="reportId" :report-data="detailData" />
@@ -26,7 +30,11 @@
       <uni-row class="flex-row align-center justify-end">
         <uni-col :span="6">
           <view class="footer-btn">
-            <button class="mini-btn" type="primary" @click="save">
+            <button
+              class="mini-btn"
+              type="primary"
+              @click="save"
+              :disabled="detailData.status !== 0 && detailData.auditStatus !== 20">
               {{ t('operation.save') }}
             </button>
           </view>

+ 201 - 99
pages/ruiDu/index.vue

@@ -13,8 +13,12 @@
           </uni-easyinput>
         </uni-col>
         <uni-col :span="5" class="flex-row justify-end">
-          <button class="mini-btn" type="primary" size="mini" @click="searchList">
-            {{ $t('operation.search') }}
+          <button
+            class="mini-btn"
+            type="primary"
+            size="mini"
+            @click="searchList">
+            {{ $t("operation.search") }}
           </button>
         </uni-col>
       </uni-row>
@@ -28,7 +32,7 @@
           }">
           <!-- 创建时间 -->
           <view class="module-name">
-            {{ item.createTime ? formatDate(item.createTime) : '' }}
+            {{ item.createTime ? formatDate(item.createTime) : "" }}
           </view>
           <!-- 工单状态 -->
           <view
@@ -42,34 +46,74 @@
         <view class="item-content">
           <!-- 带班干部 -->
           <view class="item-title flex-row">
-            <span class="item-title-width">{{ $t('ruiDu.shiftLeader') }}:</span>
+            <span class="item-title-width">{{ $t("ruiDu.shiftLeader") }}:</span>
             <span>{{ item.responsiblePersonNames }}</span>
           </view>
           <!-- 日报名称 -->
           <view class="item-title flex-row">
-            <span class="item-title-width">{{ $t('ruiDu.reportName') }}:</span>
+            <span class="item-title-width">{{ $t("ruiDu.reportName") }}:</span>
             <span>{{ item.reportName }}</span>
           </view>
           <!-- 项目 -->
           <view class="item-title flex-row">
-            <span class="item-title-width">{{ $t('ruiDu.project') }}:</span>
+            <span class="item-title-width">{{ $t("ruiDu.project") }}:</span>
             <span>{{ item.contractName }}</span>
           </view>
           <!-- 任务 -->
           <view class="item-title flex-row">
-            <span class="item-title-width">{{ $t('ruiDu.task') }}:</span>
+            <span class="item-title-width">{{ $t("ruiDu.task") }}:</span>
             <span>{{ item.taskName }}</span>
           </view>
 
           <!-- 创建时间 -->
           <view class="item-title flex-row">
-            <span class="item-title-width">{{ $t('operation.createTime') }}:</span>
-            <span>{{ item.createTime ? formatTime(item.createTime) : '' }}</span>
+            <span class="item-title-width"
+              >{{ $t("operation.createTime") }}:</span
+            >
+            <span>{{
+              item.createTime ? formatTime(item.createTime) : ""
+            }}</span>
           </view>
           <!-- 填写时间 -->
           <view class="item-title flex-row">
-            <span class="item-title-width">{{ $t('operation.fillTime') }}:</span>
-            <span>{{ item.fillTime ? formatTime(item.fillTime) : '' }}</span>
+            <span class="item-title-width"
+              >{{ $t("operation.fillTime") }}:</span
+            >
+            <span>{{ item.fillTime ? formatTime(item.fillTime) : "" }}</span>
+          </view>
+          <view class="item-title flex-row align-center">
+            <span class="item-title-width">{{ "审批状态" }}:</span>
+            <span
+              :class="[
+                'my-tag',
+                item.auditStatus === 0
+                  ? 'my-tag-info'
+                  : item.auditStatus === 10
+                  ? 'my-tag-primary'
+                  : item.auditStatus === 20
+                  ? 'my-tag-success'
+                  : 'my-tag-danger',
+              ]">
+              {{
+                item.auditStatus === 0
+                  ? "待提交"
+                  : item.auditStatus === 10
+                  ? "待审批"
+                  : item.auditStatus === 20
+                  ? "审批通过"
+                  : "审批拒绝"
+              }}
+            </span>
+          </view>
+          <view class="item-title flex-row align-center">
+            <span class="item-title-width">{{ "非生产时间" }}:</span>
+            <span
+              :class="[
+                'my-tag',
+                item.nonProductFlag ? 'my-tag-success' : 'my-tag-danger',
+              ]">
+              {{ item.nonProductFlag ? "已填写" : "未填写" }}
+            </span>
           </view>
         </view>
         <view class="item-btn flex-row align-center justify-end">
@@ -77,11 +121,20 @@
 
           <!-- 查看 -->
           <button type="primary" plain="true" @click="navigatorDetail(item)">
-            {{ $t('operation.view') }}
+            {{ $t("operation.view") }}
           </button>
           <!-- 填写 -->
-          <button v-show="item.status === 0" type="primary" @click="navigatorEdit(item)">
-            {{ $t('operation.fill') }}
+          <button
+            v-show="item.status === 0"
+            type="primary"
+            @click="navigatorEdit(item)">
+            {{ $t("operation.fill") }}
+          </button>
+          <button
+            v-show="item.auditStatus === 20 && rdNonProductFlag"
+            type="primary"
+            @click="navigatorEdit(item, 'true')">
+            {{ $t("operation.time") }}
           </button>
         </view>
       </view>
@@ -90,100 +143,149 @@
 </template>
 
 <script setup>
-  import { ref, reactive, nextTick } from 'vue';
-  import { onShow } from '@dcloudio/uni-app';
-  import dayjs from 'dayjs';
-  import { getRuiDuReportPage } from '@/api/ruiDu';
-  import { useDataDictStore } from '@/store/modules/dataDict';
-
-  // 获取字典项
-  const { getStrDictOptions } = useDataDictStore();
-  // 填写状态
-  const fillStatusDict = reactive({});
-  getStrDictOptions('operation_fill_order_status').map(item => {
-    fillStatusDict[item.value] = item.label;
-  });
-  console.log('🚀 ~ getDataDictList ~ fillStatusDict:', fillStatusDict);
+import { ref, reactive, nextTick } from "vue";
+import { onShow } from "@dcloudio/uni-app";
+import dayjs from "dayjs";
+import { getRuiDuReportPage } from "@/api/ruiDu";
+import { useDataDictStore } from "@/store/modules/dataDict";
+import { getLoginUserInfo } from "@/api/login";
 
-  const orderName = ref('');
-  const placeholderStyle = ref('color:#797979;font-weight:500;font-size:16px');
-  const inputStyles = reactive({
-    backgroundColor: '#FFFFFF',
-    color: '#797979',
-  });
-  const paging = ref(null);
-  // v-model绑定的这个变量不要在分页请求结束中自己赋值,直接使用即可
-  const dataList = ref([]);
-
-  // @query所绑定的方法不要自己调用!!需要刷新列表数据时,只需要调用paging.value.reload()即可
-  const queryList = (pageNo, pageSize) => {
-    // 此处请求仅为演示,请替换为自己项目中的请求
-    getRuiDuReportPage({
-      pageNo,
-      pageSize,
+// 获取字典项
+const { getStrDictOptions } = useDataDictStore();
+// 填写状态
+const fillStatusDict = reactive({});
+getStrDictOptions("operation_fill_order_status").map(item => {
+  fillStatusDict[item.value] = item.label;
+});
+console.log("🚀 ~ getDataDictList ~ fillStatusDict:", fillStatusDict);
+
+const orderName = ref("");
+const placeholderStyle = ref("color:#797979;font-weight:500;font-size:16px");
+const inputStyles = reactive({
+  backgroundColor: "#FFFFFF",
+  color: "#797979",
+});
+const paging = ref(null);
+// v-model绑定的这个变量不要在分页请求结束中自己赋值,直接使用即可
+const dataList = ref([]);
+
+// @query所绑定的方法不要自己调用!!需要刷新列表数据时,只需要调用paging.value.reload()即可
+const queryList = (pageNo, pageSize) => {
+  // 此处请求仅为演示,请替换为自己项目中的请求
+  getRuiDuReportPage({
+    pageNo,
+    pageSize,
+  })
+    .then(res => {
+      // 将请求结果通过complete传给z-paging处理,同时也代表请求结束,这一行必须调用
+      paging.value.complete(res.data.list);
     })
-      .then(res => {
-        // 将请求结果通过complete传给z-paging处理,同时也代表请求结束,这一行必须调用
-        paging.value.complete(res.data.list);
-      })
-      .catch(res => {
-        // 如果请求失败写paging.value.complete(false);
-        // 注意,每次都需要在catch中写这句话很麻烦,z-paging提供了方案可以全局统一处理
-        // 在底层的网络请求抛出异常时,写uni.$emit('z-paging-error-emit');即可
-        paging.value.complete(false);
-      });
-  };
-  const searchList = () => {
-    paging.value.reload();
-  };
-  const navigatorDetail = item => {
-    console.log('item', item);
-    uni.navigateTo({
-      url: '/pages/ruiDu/detail?id=' + item.id,
-    });
-  };
-  const navigatorEdit = item => {
-    console.log('item', item);
-    uni.navigateTo({
-      url: '/pages/ruiDu/edit?id=' + item.id,
-    });
-  };
-  const formatDate = time => {
-    return dayjs(time).format('YYYY-MM-DD');
-  };
-  const formatTime = time => {
-    return dayjs(time).format('YYYY-MM-DD HH:mm:ss');
-  };
-
-  onShow(() => {
-    nextTick(() => {
-      searchList();
+    .catch(res => {
+      // 如果请求失败写paging.value.complete(false);
+      // 注意,每次都需要在catch中写这句话很麻烦,z-paging提供了方案可以全局统一处理
+      // 在底层的网络请求抛出异常时,写uni.$emit('z-paging-error-emit');即可
+      paging.value.complete(false);
     });
+};
+const searchList = () => {
+  paging.value.reload();
+};
+const navigatorDetail = item => {
+  uni.navigateTo({
+    url: "/pages/ruiDu/detail?id=" + item.id,
+  });
+};
+const navigatorEdit = (item, istime = "false") => {
+  uni.navigateTo({
+    url: "/pages/ruiDu/edit?id=" + item.id + "&istime=" + istime,
+  });
+};
+const formatDate = time => {
+  return dayjs(time).format("YYYY-MM-DD");
+};
+const formatTime = time => {
+  return dayjs(time).format("YYYY-MM-DD HH:mm:ss");
+};
+
+onShow(() => {
+  nextTick(() => {
+    searchList();
   });
+});
+
+const rdNonProductFlag = ref(false);
+
+const getLoginUser = async () => {
+  const response = await getLoginUserInfo();
+  if (response.code === 0) {
+    rdNonProductFlag.value = response.data.rdNonProductFlag;
+  }
+};
+getLoginUser();
 </script>
 
 <style lang="scss" scoped>
-  @import '@/style/work-order.scss';
+@import "@/style/work-order.scss";
 
-  .search-row {
-    height: 35px;
-    background: #f3f5f9;
-
-    .mini-btn {
-      height: 35px;
-      line-height: 35px;
-      width: 100%;
-      margin-left: 8px;
-    }
-  }
+.search-row {
+  height: 35px;
+  background: #f3f5f9;
 
-  .item {
+  .mini-btn {
+    height: 35px;
+    line-height: 35px;
     width: 100%;
-    // height: 245px;
-    min-height: 245px;
-    // max-height: fit-content;
-    background: #ffffff;
-    border-radius: 6px;
-    margin-top: 10px;
+    margin-left: 8px;
   }
+}
+
+.item {
+  width: 100%;
+  // height: 245px;
+  min-height: 245px;
+  // max-height: fit-content;
+  background: #ffffff;
+  border-radius: 6px;
+  margin-top: 10px;
+}
+
+.my-tag {
+  display: inline-block;
+  padding: 0 9px;
+  height: 24px;
+  line-height: 22px; /* height - border*2 */
+  font-size: 12px;
+  border-radius: 4px;
+  box-sizing: border-box;
+  border: 1px solid;
+  white-space: nowrap;
+  margin-left: 12px;
+}
+
+/* 已填写 - 绿色 (Success) */
+.my-tag-success {
+  background-color: #f0f9eb;
+  border-color: #e1f3d8;
+  color: #67c23a;
+}
+
+/* 未填写 - 红色 (Danger) */
+.my-tag-danger {
+  background-color: #fef0f0;
+  border-color: #fde2e2;
+  color: #f56c6c;
+}
+
+.my-tag-primary {
+  background-color: #ecf5ff;
+  border-color: #d9ecff;
+  color: #409eff;
+}
+
+/* 信息 - 灰色 (Info) */
+.my-tag-info {
+  background-color: #f4f4f5;
+  border-color: #e9e9eb;
+  color: #909399;
+}
 </style>

+ 126 - 86
pages/ruihen/components/form.vue

@@ -1,5 +1,5 @@
 <script setup>
-  import { ref, computed, watch, nextTick, reactive } from 'vue';
+  import { ref, computed, watch, nextTick } from 'vue';
   import { onLoad } from '@dcloudio/uni-app';
   import { getRuiHenReportDetail } from '@/api/ruihen';
   import { useDataDictStore } from '@/store/modules/dataDict';
@@ -11,6 +11,21 @@
     },
   });
 
+  const NON_PROD_FIELDS = [
+    { key: 'repairTime', label: '设备故障' },
+    { key: 'selfStopTime', label: '设备保养' },
+    { key: 'accidentTime', label: '工程质量' },
+    { key: 'complexityTime', label: '技术受限' },
+    { key: 'rectificationTime', label: '生产组织' },
+    { key: 'waitingStopTime', label: '不可抗力' },
+    { key: 'partyaDesign', label: '甲方设计' },
+    { key: 'partyaPrepare', label: '甲方准备' },
+    { key: 'partyaResource', label: '甲方资源' },
+    { key: 'relocationTime', label: '生产配合' },
+    { key: 'winterBreakTime', label: '待命' },
+    { key: 'otherNptTime', label: '其他非生产时间' },
+  ];
+
   const FORM_KEYS = [
     'id',
     'deptId',
@@ -23,29 +38,46 @@
     'dailyWaterInjection',
     'dailyInjectGasTime',
     'dailyInjectWaterTime',
-    'nonProductionTime',
-    'nptReason',
     'productionStatus',
     'remark',
     'relocationDays',
     'capacity',
     'createTime',
     'opinion',
+    'repairTime',
+    'selfStopTime',
+    'accidentTime',
+    'complexityTime',
+    'rectificationTime',
+    'waitingStopTime',
+    'partyaDesign',
+    'partyaPrepare',
+    'partyaResource',
+    'relocationTime',
+    'winterBreakTime',
+    'otherNptTime',
+    'otherNptReason',
     'status',
     'auditStatus',
   ];
 
   const formType = ref('edit');
 
-  const initFormData = () => ({
-    dailyGasInjection: 0,
-    dailyWaterInjection: 0,
-    dailyInjectGasTime: 0,
-    dailyInjectWaterTime: 0,
-    nonProductionTime: 0,
-    relocationDays: 0,
-    capacity: 0,
-  });
+  const initFormData = () => {
+    const base = {
+      dailyGasInjection: 0,
+      dailyWaterInjection: 0,
+      dailyInjectGasTime: 0,
+      dailyInjectWaterTime: 0,
+      relocationDays: 0,
+      capacity: 0,
+    };
+    // 初始化所有非生产时间字段为 0
+    NON_PROD_FIELDS.forEach(field => {
+      base[field.key] = 0;
+    });
+    return base;
+  };
 
   const form = ref(initFormData());
 
@@ -53,8 +85,12 @@
     try {
       const { data } = await getRuiHenReportDetail({ id });
 
+      form.value = initFormData();
+
       FORM_KEYS.forEach(key => {
-        form.value[key] = data[key] ?? form.value[key];
+        if (Object.prototype.hasOwnProperty.call(data, key) && data[key] !== null && data[key] !== undefined) {
+          form.value[key] = data[key];
+        }
       });
       form.value.id = id;
 
@@ -80,12 +116,17 @@
   const dictStore = useDataDictStore();
 
   const nptReasonOptions = ref([]);
+  const constructionStatusOptions = ref([]);
 
   const loadOptions = () => {
     nptReasonOptions.value = dictStore.getStrDictOptions('nptReason').map(v => ({
       text: v.label,
       value: v.value,
     }));
+    constructionStatusOptions.value = dictStore.getStrDictOptions('constructionStatus').map(v => ({
+      text: v.label,
+      value: v.value,
+    }));
   };
 
   onLoad(options => {
@@ -128,46 +169,38 @@
   const formRef = ref(null);
 
   // 辅助函数:计算总时间
-  const sumTimes = () => {
-    // 注意:uni-app input 出来可能是字符串,需转数字
-    const gas = Number(form.value.dailyInjectGasTime) || 0;
-    const water = Number(form.value.dailyInjectWaterTime) || 0;
-    const npt = Number(form.value.nonProductionTime) || 0;
-
-    return parseFloat((gas + water + npt).toFixed(2));
+  const sumNonProdTimes = () => {
+    let sum = 0;
+    NON_PROD_FIELDS.forEach(field => {
+      sum += Number(form.value[field.key] || 0);
+    });
+    return sum;
   };
 
-  // 校验函数:总时间必须为 24
   const validateTotalTime = (rule, value, data, callback) => {
-    console.log('value :>> ', value);
-    const total = sumTimes();
-    if (total !== 24) {
-      callback(`当前合计 ${total} 小时,三项之和须为 24`);
+    const gasTime = Number(form.value.dailyInjectGasTime || 0);
+    const waterTime = Number(form.value.dailyInjectWaterTime || 0);
+    const nonProdSum = sumNonProdTimes();
+
+    let total = 0;
+    let msg = '';
+
+    if (gasTime === 0 && waterTime > 0) {
+      total = parseFloat((waterTime + nonProdSum).toFixed(2));
+      msg = `注水(${waterTime})+非生产(${nonProdSum})=${total}H,必须为24H`;
+    } else {
+      total = parseFloat((gasTime + nonProdSum).toFixed(2));
+      msg = `注气(${gasTime})+非生产(${nonProdSum})=${total}H,必须为24H`;
     }
-    return true; // uni-forms 如果没调用 callback error,需返回 true 代表通过
-  };
 
-  // // 校验函数:非生产时间原因
-  // const validateNptReason = (rule, value, data, callback) => {
-  //   const npt = Number(form.value.nonProductionTime) || 0;
-  //   console.log('npt :>> ', npt);
-  //   console.log('value :>> ', value);
-  //   if (npt > 0 && !value) {
-  //     callback('非生产时间大于 0 时,必须选择原因');
-  //   }
-  //   return true;
-  // };
-
-  // 复用的时间规则
-  const timeRuleItem = {
-    rules: [
-      { required: true, errorMessage: '请输入时间' },
-      { validateFunction: validateTotalTime }, // 关联自定义校验
-    ],
+    if (Math.abs(total - 24) > 0.01) {
+      callback(msg);
+    }
+    return true;
   };
 
   // uni-forms 规则定义
-  const rules = reactive({
+  const rules = ref({
     dailyGasInjection: {
       rules: [{ required: true, errorMessage: '请输入当日注气量' }],
     },
@@ -177,26 +210,25 @@
     productionStatus: {
       rules: [{ required: true, errorMessage: '请输入生产动态' }],
     },
-
-    // // 时间字段应用复用规则
-    // dailyInjectGasTime: timeRuleItem,
-    // dailyInjectWaterTime: timeRuleItem,
-    // nonProductionTime: timeRuleItem,
-
-    // nptReason: {
-    //   rules: [{ validateFunction: validateNptReason }],
-    // },
+    constructionStatus: {
+      rules: [{ required: true, errorMessage: '请选择施工状态' }],
+    },
+    dailyInjectGasTime: {
+      rules: [{ required: true, errorMessage: '请输入当日注气量时间' }, { validateFunction: validateTotalTime }],
+    },
   });
 
+  const allTimeKeys = ['dailyInjectGasTime', 'dailyInjectWaterTime', ...NON_PROD_FIELDS.map(f => f.key)];
+
   watch(
-    [() => form.value.dailyInjectGasTime, () => form.value.dailyInjectWaterTime, () => form.value.nonProductionTime],
+    () => allTimeKeys.map(key => form.value[key]),
     () => {
       nextTick(() => {
-        formRef.value?.validateField(['nptReason']).catch(() => {});
-        if (sumTimes() === 24) {
-          formRef.value?.clearValidate(['dailyInjectGasTime', 'dailyInjectWaterTime', 'nonProductionTime']);
-        }
+        formRef.value?.validateField('dailyInjectGasTime');
       });
+    },
+    {
+      deep: true,
     }
   );
 
@@ -230,7 +262,7 @@
       labelWidth="auto"
       :model="form"
       :rules="rules"
-      validateTrigger="blur"
+      validateTrigger="submit"
       err-show-type="toast">
       <uni-forms-item label="施工队伍" name="deptName">
         <span class="readOnly">{{ form.deptName }}</span>
@@ -247,6 +279,16 @@
       <uni-forms-item label="运行时效" name="transitTime">
         <span class="readOnly" :class="{ 'red-text': transitTime.original > 1.2 }">{{ transitTime.value }}</span>
       </uni-forms-item>
+      <uni-forms-item label="施工状态" name="constructionStatus" required>
+        <uni-data-select
+          :clear="true"
+          align="right"
+          placeholder="请选择"
+          :localdata="constructionStatusOptions"
+          placement="top"
+          :disabled="disabled('edit')"
+          v-model="form.constructionStatus" />
+      </uni-forms-item>
       <uni-forms-item label="当日注气量(方)" name="dailyGasInjection" required>
         <uni-easyinput
           type="number"
@@ -261,56 +303,54 @@
           :disabled="disabled('edit')"
           v-model="form.dailyWaterInjection" />
       </uni-forms-item>
-      <!-- :class="{ 'orange-text': sumTimes() !== 24 }" -->
-      <uni-forms-item label="当日注气时间(H)" name="dailyInjectGasTime">
+      <uni-forms-item label="生产动态" name="productionStatus" required>
         <uni-easyinput
-          type="number"
+          type="textarea"
+          autoHeight
           v-bind="defaultProps"
+          v-model="form.productionStatus"
           :disabled="disabled('edit')"
-          v-model="form.dailyInjectGasTime" />
+          :maxlength="1000" />
       </uni-forms-item>
-      <uni-forms-item label="当日注水时间(H)" name="dailyInjectWaterTime">
+      <uni-forms-item label="备注" name="remark">
         <uni-easyinput
-          type="number"
+          type="textarea"
+          autoHeight
           v-bind="defaultProps"
           :disabled="disabled('edit')"
-          v-model="form.dailyInjectWaterTime" />
+          v-model="form.remark"
+          :maxlength="1000" />
       </uni-forms-item>
-      <uni-forms-item label="非生产时间(H)" name="nonProductionTime">
+      <uv-divider text="生产时间" textPosition="left"></uv-divider>
+      <uni-forms-item label="当日注气时间(H)" name="dailyInjectGasTime">
         <uni-easyinput
           type="number"
           v-bind="defaultProps"
           :disabled="disabled('edit')"
-          v-model="form.nonProductionTime" />
-      </uni-forms-item>
-      <uni-forms-item label="非生产时间原因" name="nptReason">
-        <uni-data-select
-          :clear="true"
-          align="right"
-          placeholder="请选择"
-          :localdata="nptReasonOptions"
-          placement="top"
-          :disabled="disabled('edit')"
-          v-model="form.nptReason" />
+          v-model="form.dailyInjectGasTime" />
       </uni-forms-item>
-      <uni-forms-item label="生产动态" name="productionStatus" required>
+      <uni-forms-item label="当日注水时间(H)" name="dailyInjectWaterTime">
         <uni-easyinput
-          type="textarea"
-          autoHeight
+          type="number"
           v-bind="defaultProps"
-          v-model="form.productionStatus"
           :disabled="disabled('edit')"
-          :maxlength="1000" />
+          v-model="form.dailyInjectWaterTime" />
       </uni-forms-item>
-      <uni-forms-item label="备注" name="remark">
+      <uv-divider text="非生产时间" textPosition="left"></uv-divider>
+      <uni-forms-item v-for="field in NON_PROD_FIELDS" :key="field.key" :label="field.label + '(H)'" :name="field.key">
+        <uni-easyinput type="number" v-bind="defaultProps" :disabled="disabled('edit')" v-model="form[field.key]" />
+      </uni-forms-item>
+
+      <uni-forms-item label="其他非生产原因" name="otherNptReason">
         <uni-easyinput
           type="textarea"
           autoHeight
           v-bind="defaultProps"
+          v-model="form.otherNptReason"
           :disabled="disabled('edit')"
-          v-model="form.remark"
           :maxlength="1000" />
       </uni-forms-item>
+
       <uni-forms-item v-if="type.includes('approval')" label="审批意见" name="opinion">
         <uni-easyinput
           type="textarea"

+ 53 - 53
pages/ruihen/edit.vue

@@ -1,46 +1,46 @@
 <script setup>
-  import { ref } from 'vue';
-  import { createIotRhDailyReport } from '@/api/ruihen';
-  import Form from './components/form.vue';
+import { ref } from "vue";
+import { createIotRhDailyReport } from "@/api/ruihen";
+import Form from "./components/form.vue";
 
-  const formRef = ref(null);
+const formRef = ref(null);
 
-  const formLoading = ref(false);
+const formLoading = ref(false);
 
-  const submitForm = async () => {
-    if (!formRef.value) return;
+const submitForm = async () => {
+  if (!formRef.value) return;
 
-    try {
-      await formRef.value.formRef.validate();
-      const form = formRef.value.form;
+  try {
+    await formRef.value.formRef.validate();
+    const form = formRef.value.form;
 
-      if (form.nonProductionTime && !form.nptReason) {
-        uni.showToast({
-          title: '非生产时间大于 0 时,必须选择非生产时间原因',
-          icon: 'none',
-        });
-        return;
-      }
+    if (Number(form.otherNptTime) && !form.otherNptReason) {
+      uni.showToast({
+        title: "其他非生产时间大于 0 时,必须填写其他非生产时间原因",
+        icon: "none",
+      });
+      return;
+    }
 
-      formLoading.value = true;
+    formLoading.value = true;
 
-      const { createTime, ...other } = form;
-      const data = { ...other, fillOrderCreateTime: createTime };
+    const { createTime, ...other } = form;
+    const data = { ...other, fillOrderCreateTime: createTime };
 
-      await createIotRhDailyReport(data);
+    await createIotRhDailyReport(data);
 
-      formRef.value.loadDetail(form.id);
+    formRef.value.loadDetail(form.id);
 
-      uni.showToast({
-        title: '修改成功',
-        icon: 'success',
-      });
-    } catch (error) {
-      console.log('error :>> ', error);
-    } finally {
-      formLoading.value = false;
-    }
-  };
+    uni.showToast({
+      title: "修改成功",
+      icon: "success",
+    });
+  } catch (error) {
+    console.log("error :>> ", error);
+  } finally {
+    formLoading.value = false;
+  }
+};
 </script>
 
 <template>
@@ -64,27 +64,27 @@
 </template>
 
 <style lang="scss" scoped>
-  @import '@/style/work-order-segmented.scss';
-  .page {
-    padding-bottom: 0;
+@import "@/style/work-order-segmented.scss";
+.page {
+  padding-bottom: 0;
+}
+
+.footer-btn {
+  display: flex;
+  justify-content: flex-end;
+  align-items: center;
+  padding: 0 32px;
+  height: 100%;
+
+  gap: 0 32px;
+
+  & > uni-button {
+    margin: 0;
   }
+}
 
-  .footer-btn {
-    display: flex;
-    justify-content: flex-end;
-    align-items: center;
-    padding: 0 32px;
-    height: 100%;
-
-    gap: 0 32px;
-
-    & > uni-button {
-      margin: 0;
-    }
-  }
-
-  :deep(.mini-btn) {
-    height: 38px !important;
-    font-size: 16px !important;
-  }
+:deep(.mini-btn) {
+  height: 38px !important;
+  font-size: 16px !important;
+}
 </style>

+ 116 - 181
pages/ruiying/components/form.vue

@@ -11,8 +11,26 @@
     },
   });
 
+  const NON_PROD_FIELDS = [
+    { key: 'repairTime', label: '设备故障' },
+    { key: 'selfStopTime', label: '设备保养' },
+    { key: 'accidentTime', label: '工程质量' },
+    { key: 'complexityTime', label: '技术受限' },
+    { key: 'rectificationTime', label: '生产组织' },
+    { key: 'waitingStopTime', label: '不可抗力' },
+    { key: 'partyaDesign', label: '甲方设计' },
+    { key: 'partyaPrepare', label: '甲方准备' },
+    { key: 'partyaResource', label: '甲方资源' },
+    { key: 'relocationTime', label: '生产配合' },
+    { key: 'winterBreakTime', label: '待命' },
+    { key: 'otherNptTime', label: '其他非生产时间' },
+  ];
+
   const FORM_KEYS = [
     'id',
+    'deptId',
+    'projectId',
+    'taskId',
     'deptName',
     'contractName',
     'taskName',
@@ -27,33 +45,47 @@
     'wellInclination',
     'azimuth',
     'designWellStruct',
+    'personnel',
+    'drillingWorkingTime',
+    'otherProductionTime',
+    'lastCurrentDepth',
+
     'productionStatus',
     'remark',
     'createTime',
-    'deptId',
-    'projectId',
-    'taskId',
+
     'opinion',
-    'personnel',
-    'accidentTime',
     'repairTime',
     'selfStopTime',
+    'accidentTime',
     'complexityTime',
-    'relocationTime',
     'rectificationTime',
     'waitingStopTime',
+    'partyaDesign',
+    'partyaPrepare',
+    'partyaResource',
+    'relocationTime',
     'winterBreakTime',
-    'drillingWorkingTime',
-    'otherProductionTime',
-    'lastCurrentDepth',
-    'opinion',
+    'otherNptTime',
+    'otherNptReason',
+
     'status',
     'auditStatus',
   ];
 
   const formType = ref('edit');
 
-  const initFormData = () => ({});
+  const initFormData = () => {
+    const base = {
+      drillingWorkingTime: 0,
+      otherProductionTime: 0,
+    };
+    // 初始化所有非生产时间字段为 0
+    NON_PROD_FIELDS.forEach(field => {
+      base[field.key] = 0;
+    });
+    return base;
+  };
 
   const form = ref(initFormData());
 
@@ -61,8 +93,12 @@
     try {
       const { data } = await getRuiYingReportDetail({ id });
 
+      form.value = initFormData();
+
       FORM_KEYS.forEach(key => {
-        form.value[key] = data[key] ?? form.value[key];
+        if (Object.prototype.hasOwnProperty.call(data, key) && data[key] !== null && data[key] !== undefined) {
+          form.value[key] = data[key];
+        }
       });
       form.value.id = id;
 
@@ -124,56 +160,34 @@
     else return formType.value === 'readonly';
   });
 
-  // const transitTime = computed(() => {
-  //   const cap = form.value.capacity;
-  //   const gas = form.value.dailyGasInjection ?? 0;
-
-  //   if (!cap) return { original: 0, value: '0%' };
-
-  //   const original = gas / cap;
-  //   return { original, value: (original * 100).toFixed(2) + '%' };
-  // });
-
   const formRef = ref(null);
 
   // 辅助函数:计算总时间
-  const sumTimes = () => {
-    const {
-      drillingWorkingTime = 0,
-      otherProductionTime = 0,
-      accidentTime = 0,
-      repairTime = 0,
-      selfStopTime = 0,
-      complexityTime = 0,
-      relocationTime = 0,
-      rectificationTime = 0,
-      waitingStopTime = 0,
-      winterBreakTime = 0,
-    } = form.value;
-    return parseFloat(
-      (
-        Number(drillingWorkingTime) +
-        Number(otherProductionTime) +
-        Number(accidentTime) +
-        Number(repairTime) +
-        Number(selfStopTime) +
-        Number(complexityTime) +
-        Number(relocationTime) +
-        Number(rectificationTime) +
-        Number(waitingStopTime) +
-        Number(winterBreakTime)
-      ).toFixed(2)
-    );
+  const sumNonProdTimes = () => {
+    let sum = 0;
+    NON_PROD_FIELDS.forEach(field => {
+      sum += Number(form.value[field.key] || 0);
+    });
+    return sum;
   };
 
   // 校验函数:总时间必须为 24
   const validateTotalTime = (rule, value, data, callback) => {
-    const total = sumTimes();
-    if (total !== 24) {
-      callback(`当前合计 ${total} 小时,时间之和必须等于 24`);
-    } else {
-      callback();
+    const drillingTime = Number(form.value.drillingWorkingTime || 0);
+    const otherTime = Number(form.value.otherProductionTime || 0);
+
+    const nonProdSum = sumNonProdTimes();
+
+    let total = 0;
+    let msg = '';
+
+    total = parseFloat((drillingTime + otherTime + nonProdSum).toFixed(2));
+    msg = `进尺(${drillingTime})+其他(${otherTime})+非生产(${nonProdSum})=${total}H,必须为24H`;
+
+    if (Math.abs(total - 24) > 0.01) {
+      callback(msg);
     }
+    return true;
   };
 
   const validateLastCurrentDepth = (rule, value, data, callback) => {
@@ -184,25 +198,6 @@
     }
   };
 
-  // // 校验函数:非生产时间原因
-  // const validateNptReason = (rule, value, data, callback) => {
-  //   const npt = Number(form.value.nonProductionTime) || 0;
-  //   console.log('npt :>> ', npt);
-  //   console.log('value :>> ', value);
-  //   if (npt > 0 && !value) {
-  //     callback('非生产时间大于 0 时,必须选择原因');
-  //   }
-  //   return true;
-  // };
-
-  // 复用的时间规则
-  const timeRuleItem = {
-    rules: [
-      { required: true, errorMessage: '请输入时间' },
-      { validateFunction: validateTotalTime }, // 关联自定义校验
-    ],
-  };
-
   // uni-forms 规则定义
   const rules = reactive({
     currentDepth: {
@@ -212,53 +207,37 @@
     productionStatus: {
       rules: [{ required: true, errorMessage: '请输入生产动态' }],
     },
-
-    drillingWorkingTime: timeRuleItem,
-    otherProductionTime: timeRuleItem,
-    accidentTime: timeRuleItem,
-    repairTime: timeRuleItem,
-    selfStopTime: timeRuleItem,
-    complexityTime: timeRuleItem,
-    relocationTime: timeRuleItem,
-    rectificationTime: timeRuleItem,
-    waitingStopTime: timeRuleItem,
-    winterBreakTime: timeRuleItem,
+    drillingWorkingTime: {
+      rules: [{ required: true, errorMessage: '请输入进尺工作时间' }, { validateFunction: validateTotalTime }],
+    },
   });
 
+  const allTimeKeys = ['drillingWorkingTime', 'otherProductionTime', ...NON_PROD_FIELDS.map(f => f.key)];
+
   watch(
-    [
-      () => form.value.drillingWorkingTime,
-      () => form.value.otherProductionTime,
-      () => form.value.accidentTime,
-      () => form.value.repairTime,
-      () => form.value.selfStopTime,
-      () => form.value.complexityTime,
-      () => form.value.relocationTime,
-      () => form.value.rectificationTime,
-      () => form.value.waitingStopTime,
-      () => form.value.winterBreakTime,
-    ],
+    () => allTimeKeys.map(key => form.value[key]),
     () => {
       nextTick(() => {
-        if (sumTimes() === 24) {
-          formRef.value?.clearValidate([
-            'drillingWorkingTime',
-            'otherProductionTime',
-            'accidentTime',
-            'repairTime',
-            'selfStopTime',
-            'complexityTime',
-            'relocationTime',
-            'rectificationTime',
-            'waitingStopTime',
-            'winterBreakTime',
-          ]);
-        }
+        formRef.value?.validateField('drillingWorkingTime');
       });
     }
   );
 
   defineExpose({ formRef, form, loadDetail });
+
+  const orange = computed(() => {
+    const drillingTime = Number(form.value.drillingWorkingTime || 0);
+    const otherTime = Number(form.value.otherProductionTime || 0);
+
+    const nonProdSum = sumNonProdTimes();
+
+    let total = 0;
+
+    total = parseFloat((drillingTime + otherTime + nonProdSum).toFixed(2));
+
+    if (Math.abs(total - 24) > 0.01) return true;
+    return false;
+  });
 </script>
 
 <template>
@@ -288,7 +267,7 @@
       labelWidth="auto"
       :model="form"
       :rules="rules"
-      validateTrigger="blur"
+      validateTrigger="submit"
       err-show-type="toast">
       <uni-forms-item label="施工队伍" name="deptName">
         <span class="readOnly">{{ form.deptName }}</span>
@@ -367,106 +346,62 @@
           v-model="form.personnel"
           :maxlength="1000" />
       </uni-forms-item>
-      <uv-divider text="生产时间" textPosition="left"></uv-divider>
-      <uni-forms-item label="进尺工作时间(H)" name="drillingWorkingTime" required>
-        <uni-easyinput
-          type="number"
-          v-bind="defaultProps"
-          :class="{ 'orange-text': sumTimes() !== 24 }"
-          :disabled="disabled('edit')"
-          v-model="form.drillingWorkingTime" />
-      </uni-forms-item>
-      <uni-forms-item label="其它生产时间(H)" name="otherProductionTime" required>
-        <uni-easyinput
-          type="number"
-          v-bind="defaultProps"
-          :class="{ 'orange-text': sumTimes() !== 24 }"
-          :disabled="disabled('edit')"
-          v-model="form.otherProductionTime" />
-      </uni-forms-item>
-      <uv-divider text="非生产时间" textPosition="left"></uv-divider>
-      <uni-forms-item label="事故(H)" name="accidentTime" required>
-        <uni-easyinput
-          type="number"
-          v-bind="defaultProps"
-          :class="{ 'orange-text': sumTimes() !== 24 }"
-          :disabled="disabled('edit')"
-          v-model="form.accidentTime" />
-      </uni-forms-item>
-      <uni-forms-item label="修理(H)" name="repairTime" required>
-        <uni-easyinput
-          type="number"
-          v-bind="defaultProps"
-          :class="{ 'orange-text': sumTimes() !== 24 }"
-          :disabled="disabled('edit')"
-          v-model="form.repairTime" />
-      </uni-forms-item>
-      <uni-forms-item label="自停(H)" name="selfStopTime" required>
-        <uni-easyinput
-          type="number"
-          v-bind="defaultProps"
-          :class="{ 'orange-text': sumTimes() !== 24 }"
-          :disabled="disabled('edit')"
-          v-model="form.selfStopTime" />
-      </uni-forms-item>
-      <uni-forms-item label="复杂(H)" name="complexityTime" required>
+      <uni-forms-item label="生产动态" name="productionStatus" required>
         <uni-easyinput
-          type="number"
+          type="textarea"
+          autoHeight
           v-bind="defaultProps"
-          :class="{ 'orange-text': sumTimes() !== 24 }"
+          v-model="form.productionStatus"
           :disabled="disabled('edit')"
-          v-model="form.complexityTime" />
+          :maxlength="1000" />
       </uni-forms-item>
-      <uni-forms-item label="搬迁(H)" name="relocationTime" required>
+      <uni-forms-item label="备注" name="remark">
         <uni-easyinput
-          type="number"
+          type="textarea"
+          autoHeight
           v-bind="defaultProps"
-          :class="{ 'orange-text': sumTimes() !== 24 }"
           :disabled="disabled('edit')"
-          v-model="form.relocationTime" />
+          v-model="form.remark"
+          :maxlength="1000" />
       </uni-forms-item>
-      <uni-forms-item label="整改(H)" name="rectificationTime" required>
+
+      <uv-divider text="生产时间" textPosition="left"></uv-divider>
+      <uni-forms-item label="进尺工作时间(H)" name="drillingWorkingTime" required>
         <uni-easyinput
           type="number"
           v-bind="defaultProps"
-          :class="{ 'orange-text': sumTimes() !== 24 }"
+          :class="{ 'orange-text': orange }"
           :disabled="disabled('edit')"
-          v-model="form.rectificationTime" />
+          v-model="form.drillingWorkingTime" />
       </uni-forms-item>
-      <uni-forms-item label="等停(H)" name="waitingStopTime" required>
+      <uni-forms-item label="其它生产时间(H)" name="otherProductionTime" required>
         <uni-easyinput
           type="number"
           v-bind="defaultProps"
-          :class="{ 'orange-text': sumTimes() !== 24 }"
+          :class="{ 'orange-text': orange }"
           :disabled="disabled('edit')"
-          v-model="form.waitingStopTime" />
+          v-model="form.otherProductionTime" />
       </uni-forms-item>
-      <uni-forms-item label="冬休(H)" name="winterBreakTime" required>
+      <uv-divider text="非生产时间" textPosition="left"></uv-divider>
+      <uni-forms-item v-for="field in NON_PROD_FIELDS" :key="field.key" :label="field.label + '(H)'" :name="field.key">
         <uni-easyinput
           type="number"
+          :class="{ 'orange-text': orange }"
           v-bind="defaultProps"
-          :class="{ 'orange-text': sumTimes() !== 24 }"
           :disabled="disabled('edit')"
-          v-model="form.waitingStopTime" />
+          v-model="form[field.key]" />
       </uni-forms-item>
-      <uni-forms-item label="生产动态" name="productionStatus" required>
-        <uni-easyinput
-          type="textarea"
-          autoHeight
-          v-bind="defaultProps"
-          v-model="form.productionStatus"
-          :disabled="disabled('edit')"
-          :maxlength="1000" />
-      </uni-forms-item>
-      <uni-forms-item label="备注" name="remark">
+
+      <uni-forms-item label="其他非生产原因" name="otherNptReason">
         <uni-easyinput
           type="textarea"
           autoHeight
           v-bind="defaultProps"
+          v-model="form.otherNptReason"
           :disabled="disabled('edit')"
-          v-model="form.remark"
           :maxlength="1000" />
       </uni-forms-item>
+
       <uni-forms-item v-if="type.includes('approval')" label="审批意见" name="opinion">
         <uni-easyinput
           type="textarea"

+ 7 - 7
pages/ruiying/edit.vue

@@ -14,13 +14,13 @@
       await formRef.value.formRef.validate();
       const form = formRef.value.form;
 
-      // if (form.nonProductionTime && !form.nptReason) {
-      //   uni.showToast({
-      //     title: '非生产时间大于 0 时,必须选择非生产时间原因',
-      //     icon: 'none',
-      //   });
-      //   return;
-      // }
+      if (Number(form.otherNptTime) && !form.otherNptReason) {
+        uni.showToast({
+          title: '其他非生产时间大于 0 时,必须填写其他非生产时间原因',
+          icon: 'none',
+        });
+        return;
+      }
 
       formLoading.value = true;
 

+ 131 - 84
pages/ruiyingx/components/form.vue

@@ -11,6 +11,21 @@
     },
   });
 
+  const NON_PROD_FIELDS = [
+    { key: 'repairTime', label: '设备故障' },
+    { key: 'selfStopTime', label: '设备保养' },
+    { key: 'accidentTime', label: '工程质量' },
+    { key: 'complexityTime', label: '技术受限' },
+    { key: 'rectificationTime', label: '生产组织' },
+    { key: 'waitingStopTime', label: '不可抗力' },
+    { key: 'partyaDesign', label: '甲方设计' },
+    { key: 'partyaPrepare', label: '甲方准备' },
+    { key: 'partyaResource', label: '甲方资源' },
+    { key: 'relocationTime', label: '生产配合' },
+    { key: 'winterBreakTime', label: '待命' },
+    { key: 'otherNptTime', label: '其他非生产时间' },
+  ];
+
   const FORM_KEYS = [
     'id',
     'deptId',
@@ -23,30 +38,50 @@
     'technique',
     'wellCategory',
     'designWellDepth',
-    'casingPipeSize',
     'wellControlLevel',
+    'casingPipeSize',
+    'dailyFuel',
     'currentOperation',
     'nextPlan',
-    'transitTime',
     'ratedProductionTime',
     'productionTime',
-    'nonProductionTime',
-    'ryNptReason',
-    'productionStatus',
     'totalStaffNum',
     'onDutyStaffNum',
     'leaveStaffNum',
-    'dailyFuel',
+    'productionStatus',
     'remark',
     'createTime',
     'opinion',
+    'repairTime',
+    'selfStopTime',
+    'accidentTime',
+    'complexityTime',
+    'rectificationTime',
+    'waitingStopTime',
+    'partyaDesign',
+    'partyaPrepare',
+    'partyaResource',
+    'relocationTime',
+    'winterBreakTime',
+    'otherNptTime',
+    'otherNptReason',
     'status',
     'auditStatus',
   ];
 
   const formType = ref('edit');
 
-  const initFormData = () => ({});
+  const initFormData = () => {
+    const base = {
+      ratedProductionTime: 0,
+      productionTime: 0,
+    };
+    // 初始化所有非生产时间字段为 0
+    NON_PROD_FIELDS.forEach(field => {
+      base[field.key] = 0;
+    });
+    return base;
+  };
 
   const form = ref(initFormData());
 
@@ -54,8 +89,12 @@
     try {
       const { data } = await getRuiYingReportDetail({ id });
 
+      form.value = initFormData();
+
       FORM_KEYS.forEach(key => {
-        form.value[key] = data[key] ?? form.value[key];
+        if (Object.prototype.hasOwnProperty.call(data, key) && data[key] !== null && data[key] !== undefined) {
+          form.value[key] = data[key];
+        }
       });
       form.value.id = id;
 
@@ -139,41 +178,33 @@
   });
 
   // 辅助函数:计算总时间
-  const sumTimes = () => {
-    const { productionTime = 0, nonProductionTime = 0 } = form.value;
-    return Number(productionTime) + Number(nonProductionTime);
+  const sumNonProdTimes = () => {
+    let sum = 0;
+    NON_PROD_FIELDS.forEach(field => {
+      sum += Number(form.value[field.key] || 0);
+    });
+    return sum;
   };
 
   // 校验函数:总时间必须为 24
   const validateTotalTime = (rule, value, data, callback) => {
-    const total = sumTimes();
-    if (total !== Number(form.value.ratedProductionTime)) {
-      callback(`生产时间和非生产时间之和必须等于额定生产时间`);
-    } else {
-      callback();
+    const rateTime = Number(form.value.ratedProductionTime || 0);
+    const time = Number(form.value.productionTime || 0);
+
+    const nonProdSum = sumNonProdTimes();
+
+    let total = 0;
+    let msg = '';
+
+    total = parseFloat((time + nonProdSum).toFixed(2));
+    msg = `生产(${time})+非生产(${nonProdSum})=${total}H,必须等于额定${rateTime}H`;
+
+    if (Math.abs(total - rateTime) > 0.01) {
+      callback(msg);
     }
+    return true;
   };
 
-  // // 校验函数:非生产时间原因
-  // const validateNptReason = (rule, value, data, callback) => {
-  //   const npt = Number(form.value.nonProductionTime) || 0;
-  //   console.log('npt :>> ', npt);
-  //   console.log('value :>> ', value);
-  //   if (npt > 0 && !value) {
-  //     callback('非生产时间大于 0 时,必须选择原因');
-  //   }
-  //   return true;
-  // };
-
-  // 复用的时间规则
-  // const timeRuleItem = {
-  //   rules: [
-  //     { required: true, errorMessage: '请输入时间' },
-  //     { validateFunction: validateTotalTime }, // 关联自定义校验
-  //   ],
-  // };
-
-  // uni-forms 规则定义
   const rules = reactive({
     repairStatus: {
       rules: [{ required: true, errorMessage: '请输入施工状态' }],
@@ -181,30 +212,42 @@
     productionStatus: {
       rules: [{ required: true, errorMessage: '请输入生产动态' }],
     },
-
-    // 时间字段应用复用规则
-    // productionTime: timeRuleItem,
-    // nonProductionTime: timeRuleItem,
-    // ratedProductionTime: timeRuleItem,
-
-    // nptReason: {
-    //   rules: [{ validateFunction: validateNptReason }],
-    // },
+    ratedProductionTime: {
+      rules: [{ required: true, errorMessage: '请输入额定生产时间' }, { validateFunction: validateTotalTime }],
+    },
+    productionTime: {
+      rules: [{ required: true, errorMessage: '请输入生产时间' }, { validateFunction: validateTotalTime }],
+    },
   });
 
+  const allTimeKeys = ['ratedProductionTime', 'productionTime', ...NON_PROD_FIELDS.map(f => f.key)];
+
   watch(
-    [() => form.value.dailyInjectGasTime, () => form.value.dailyInjectWaterTime, () => form.value.nonProductionTime],
+    () => allTimeKeys.map(key => form.value[key]),
     () => {
       nextTick(() => {
-        formRef.value?.validateField(['ryNptReason']).catch(() => {});
-        if (sumTimes() === 24) {
-          formRef.value?.clearValidate(['dailyInjectGasTime', 'dailyInjectWaterTime', 'nonProductionTime']);
-        }
+        formRef.value?.validateField(['ratedProductionTime', 'productionTime']);
       });
     }
   );
 
   defineExpose({ formRef, form, loadDetail });
+
+  const orange = computed(() => {
+    const rateTime = Number(form.value.ratedProductionTime || 0);
+    const time = Number(form.value.productionTime || 0);
+
+    const nonProdSum = sumNonProdTimes();
+
+    let total = 0;
+    let msg = '';
+
+    total = parseFloat((time + nonProdSum).toFixed(2));
+    msg = `生产(${time})+非生产(${nonProdSum})=${total}H,必须等于额定${rateTime}H`;
+
+    if (Math.abs(total - rateTime) > 0.01) return true;
+    return false;
+  });
 </script>
 
 <template>
@@ -313,40 +356,6 @@
       <uni-forms-item label="运行时效" name="transitTime">
         <span class="readOnly" :class="{ 'red-text': transitTime.original > 1.0 }">{{ transitTime.value }}</span>
       </uni-forms-item>
-      <uni-forms-item label="额定生产时间(H)" name="ratedProductionTime" required>
-        <uni-easyinput
-          type="number"
-          v-bind="defaultProps"
-          :class="{ 'orange-text': sumTimes() !== Number(form.ratedProductionTime) }"
-          :disabled="disabled('edit')"
-          v-model="form.ratedProductionTime" />
-      </uni-forms-item>
-      <uni-forms-item label="生产时间(H)" name="productionTime" required>
-        <uni-easyinput
-          type="number"
-          v-bind="defaultProps"
-          :class="{ 'orange-text': sumTimes() !== Number(form.ratedProductionTime) }"
-          :disabled="disabled('edit')"
-          v-model="form.productionTime" />
-      </uni-forms-item>
-      <uni-forms-item label="非生产时间(H)" name="nonProductionTime" required>
-        <uni-easyinput
-          type="number"
-          v-bind="defaultProps"
-          :class="{ 'orange-text': sumTimes() !== Number(form.ratedProductionTime) }"
-          :disabled="disabled('edit')"
-          v-model="form.nonProductionTime" />
-      </uni-forms-item>
-      <uni-forms-item label="非生产时间原因" name="ryNptReason">
-        <uni-data-select
-          :clear="true"
-          align="right"
-          placeholder="请选择"
-          :localdata="nptReasonOptions"
-          placement="top"
-          :disabled="disabled('edit')"
-          v-model="form.ryNptReason" />
-      </uni-forms-item>
       <uni-forms-item label="全员数量" name="totalStaffNum">
         <uni-easyinput type="number" v-bind="defaultProps" :disabled="disabled('edit')" v-model="form.totalStaffNum" />
       </uni-forms-item>
@@ -374,6 +383,44 @@
           v-model="form.remark"
           :maxlength="1000" />
       </uni-forms-item>
+      <uv-divider text="生产时间" textPosition="left"></uv-divider>
+      <uni-forms-item label="额定生产时间(H)" name="ratedProductionTime" required>
+        <uni-easyinput
+          type="number"
+          v-bind="defaultProps"
+          :class="{ 'orange-text': orange }"
+          :disabled="disabled('edit')"
+          v-model="form.ratedProductionTime" />
+      </uni-forms-item>
+      <uni-forms-item label="生产时间(H)" name="productionTime" required>
+        <uni-easyinput
+          type="number"
+          v-bind="defaultProps"
+          :class="{ 'orange-text': orange }"
+          :disabled="disabled('edit')"
+          v-model="form.productionTime" />
+      </uni-forms-item>
+
+      <uv-divider text="非生产时间" textPosition="left"></uv-divider>
+      <uni-forms-item v-for="field in NON_PROD_FIELDS" :key="field.key" :label="field.label + '(H)'" :name="field.key">
+        <uni-easyinput
+          type="number"
+          :class="{ 'orange-text': orange }"
+          v-bind="defaultProps"
+          :disabled="disabled('edit')"
+          v-model="form[field.key]" />
+      </uni-forms-item>
+
+      <uni-forms-item label="其他非生产原因" name="otherNptReason">
+        <uni-easyinput
+          type="textarea"
+          autoHeight
+          v-bind="defaultProps"
+          v-model="form.otherNptReason"
+          :disabled="disabled('edit')"
+          :maxlength="1000" />
+      </uni-forms-item>
+
       <uni-forms-item v-if="type.includes('approval')" label="审批意见" name="opinion">
         <uni-easyinput
           type="textarea"

+ 2 - 9
pages/ruiyingx/edit.vue

@@ -14,21 +14,14 @@
       await formRef.value.formRef.validate();
       const form = formRef.value.form;
 
-      if (form.nonProductionTime && !form.ryNptReason) {
+      if (Number(form.otherNptTime) && !form.otherNptReason) {
         uni.showToast({
-          title: '非生产时间大于 0 时,必须选择非生产时间原因',
+          title: '其他非生产时间大于 0 时,必须填写其他非生产时间原因',
           icon: 'none',
         });
         return;
       }
 
-      if (Number(form.productionTime) + Number(form.nonProductionTime) !== Number(form.ratedProductionTime)) {
-        uni.showToast({
-          title: '生产时间和非生产时间之和必须等于额定生产时间',
-          icon: 'none',
-        });
-      }
-
       formLoading.value = true;
 
       const { createTime, ...other } = form;

Some files were not shown because too many files changed in this diff