ソースを参照

优化排班表,受压元件

xuzhancheng 3 週間 前
コミット
0da93b96f7

+ 6 - 0
yudao-ui-admin-vue3/src/api/pressure2/equipboiler/index.ts

@@ -125,6 +125,7 @@ export interface EquipBoilerVO {
   lng:number // 经度
   lat:number // 纬度
   unitId:string
+  pressureParts?: any[] // 受压元件列表
 }
 
 // 锅炉设备 API
@@ -162,4 +163,9 @@ export const EquipBoilerApi = {
   getNameByIds : async (data:any) => {
     return await request.post({ url: `/pressure2/equip-boiler/getNameByIds`, data })
   },
+
+  // 查询锅炉受压元件列表
+  getPressureParts: async (boilerId: string) => {
+    return await request.get({ url: `/pressure2/equip-boiler/pressure-parts`, params: { boilerId } })
+  },
 }

+ 77 - 5
yudao-ui-admin-vue3/src/views/pressure2/equipboiler/EquipBoilerForm.vue

@@ -766,6 +766,56 @@
           />
         </el-form-item>
       </div>
+      <el-collapse v-model="activeCollapse" class="mb-15px">
+        <el-collapse-item title="受压元件" name="pressureParts">
+          <div style="margin-bottom: 10px;">
+            <el-button type="primary" size="small" @click="handleAddPressurePart">
+              <Icon icon="ep:plus" class="mr-5px" /> 添加
+            </el-button>
+          </div>
+          <el-table :data="pressureParts" border size="small" style="width: 100%">
+            <el-table-column label="部件" width="180" align="center">
+              <template #default="{ row }">
+                <el-select v-model="row.partType" placeholder="请选择部件" clearable size="small">
+                  <el-option
+                    v-for="dict in getStrDictOptions(DICT_TYPE.PRESSURE2_BOILER_PART_TYPE)"
+                    :key="dict.value"
+                    :label="dict.label"
+                    :value="dict.value"
+                  />
+                </el-select>
+              </template>
+            </el-table-column>
+            <el-table-column label="受压元件名称" width="180" align="center">
+              <template #default="{ row }">
+                <el-input v-model="row.partName" placeholder="请输入" size="small" />
+              </template>
+            </el-table-column>
+            <el-table-column label="规格" width="160" align="center">
+              <template #default="{ row }">
+                <el-input v-model="row.specification" placeholder="请输入" size="small" />
+              </template>
+            </el-table-column>
+            <el-table-column label="材质" width="160" align="center">
+              <template #default="{ row }">
+                <el-input v-model="row.material" placeholder="请输入" size="small" />
+              </template>
+            </el-table-column>
+            <el-table-column label="备注" min-width="180" align="center">
+              <template #default="{ row }">
+                <el-input v-model="row.remark" placeholder="请输入" size="small" />
+              </template>
+            </el-table-column>
+            <el-table-column label="操作" width="80" align="center" fixed="right">
+              <template #default="{ $index }">
+                <el-button type="danger" size="small" @click="handleRemovePressurePart($index)">
+                  删除
+                </el-button>
+              </template>
+            </el-table-column>
+          </el-table>
+        </el-collapse-item>
+      </el-collapse>
     </el-form>
     <template #footer>
       <el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
@@ -809,6 +859,7 @@ import SmartTable from "@/components/SmartTable/SmartTable";
 import dayjs from "dayjs";
 import Copy from "@/views/system/equipcontainer/components/Copy.vue";
 import { useEmitt } from '@/hooks/web/useEmitt'
+import { Icon } from '@/components/Icon'
 
 /** 锅炉设备 表单 */
 defineOptions({ name: 'EquipBoilerForm' })
@@ -980,6 +1031,10 @@ const formData = ref({
   waterlastresult: undefined,
   workpressure: undefined,
 })
+const pressureParts = ref<any[]>([]) // 受压元件列表
+// 有受压元件时默认展开,没有时折叠
+const activeCollapse = computed(() => pressureParts.value.length > 0 ? ['pressureParts'] : [])
+
 const formRules = reactive({
   equipDistrict: [{ required: true, message: '设备所在行政区域不能为空', trigger: 'blur' }],
   equipCode: [{ required: true, message: '设备注册代码不能为空', trigger: 'blur' }],
@@ -1001,17 +1056,15 @@ const open = async (type: string, id?: number) => {
   dialogTitle.value = t('action.' + type)
   formType.value = type
   resetForm()
+  pressureParts.value = []
   // 修改时,设置数据
   if (id) {
     formLoading.value = true
     try {
       formData.value = await EquipBoilerApi.getEquipBoiler(id)
       formData.value.useStatus = formData.value.useStatus?.toString()
-      // formData.value = res || {};
-      // formData.value['exceedDate'] = (res.exceedDate || []).length > 0 ? dayjs((res.exceedDate).join('-')) : null
-      // formData.value['isExceedTimeLimit'] = typeof res.isExceedTimeLimit === 'boolean' ? [res.isExceedTimeLimit ? '1' : '0'] : []
-      // 设置当前选中的设备类型
-      // activeEquipType.value = formData.value.type || equipTypeOptions.value[0]?.value || ''
+      // 加载受压元件列表
+      pressureParts.value = await EquipBoilerApi.getPressureParts(String(id))
     } finally {
       formLoading.value = false
     }
@@ -1028,6 +1081,8 @@ const submitForm = async () => {
   formLoading.value = true
   try {
     const data = formData.value as unknown as EquipBoilerVO
+    // 附加受压元件
+    data.pressureParts = pressureParts.value
     if (formType.value === 'create') {
       await EquipBoilerApi.createEquipBoiler(data)
       message.success(t('common.createSuccess'))
@@ -1257,6 +1312,23 @@ const handleUnitConfirm = () => {
   formData.value.unitCode = selectedRow[0].code
   formData.value.unitId = selectedRow[0].id
 }
+
+// 新增受压元件行
+const handleAddPressurePart = () => {
+  pressureParts.value.push({
+    partType: '',
+    partName: '',
+    specification: '',
+    material: '',
+    remark: ''
+  })
+}
+
+// 删除受压元件行
+const handleRemovePressurePart = (index: number) => {
+  pressureParts.value.splice(index, 1)
+}
+
 // 打开单位选择框
 const handleOpenUnitDialog = (ev) => {
   ev.target.blur()

+ 39 - 89
yudao-ui-admin-vue3/src/views/pressure2/schedule/components/ShiftSchedule.vue

@@ -332,20 +332,21 @@ const handleCheckerSelectChange = (selectedCheckers: CheckerItem[], row: Schedul
     }
   })
   row.teamList = Array.from(teamMap.values())
-  // 标记为已修改
+  // 标记为已修改并自动保存
   row.modified = true
+  autoSaveRow(row)
 }
 
 // 处理日期变更
 const handleDateChange = (row: ScheduleRow) => {
   if (!row.date) {
-    ElMessage.warning('请选择日期')
     return
   }
   // 更新星期
   row.week = calculateWeek(row.date)
-  // 标记为已修改
+  // 标记为已修改并自动保存
   row.modified = true
+  autoSaveRow(row)
 }
 
 // 通过日期计算星期
@@ -401,11 +402,6 @@ const canEdit = (row: ScheduleRow): boolean => {
   return false
 }
 
-// 是否有复制的行
-const hasCopiedRows = computed(() => {
-  return tableData.value.some(row => row.isCopied && !row.submitted)
-})
-
 // 获取行类名
 const getRowClassName = ({ row }: { row: ScheduleRow }): string => {
   if (row.isCopied && !row.submitted) {
@@ -542,103 +538,58 @@ const handleQuery = async () => {
   })
   loading.value = false
 }
-// 提交 - 提交全部修改和复制的行
-const handleSubmit = async () => {
-  // 获取所有需要提交的行:复制的行和修改的行
-  const copiedRows = tableData.value.filter(row => row.isCopied && !row.submitted)
-  const modifiedRows = tableData.value.filter(row => row.modified && !row.isCopied)
-
-  if (copiedRows.length === 0 && modifiedRows.length === 0) {
-    ElMessage.warning('没有需要提交的行')
+// 自动保存单行:修改日期或检验员后实时保存
+// 前提:日期不重复 + 检验员不为空
+const autoSaveRow = async (row: ScheduleRow) => {
+  // 校验:日期不能为空
+  if (!row.date || row.date.trim() === '') {
     return
   }
-
-  // 校验复制的行
-  if (copiedRows.length > 0) {
-    const rowsWithoutDate = copiedRows.filter(row => !row.date || row.date.trim() === '')
-    if (rowsWithoutDate.length > 0) {
-      ElMessage.warning('请为所有复制的行选择日期')
-      return
-    }
-
-    let isDuplicate = false
-    copiedRows.forEach(row => {
-      let confirmOrderId = row.confirmOrderId
-      let rows = tableData.value.filter(r => r.confirmOrderId === confirmOrderId)
-      rows.forEach(item => {
-        if (item.date === row.date && row !== item) {
-          isDuplicate = true
-        }
-      })
-    })
-    if (isDuplicate) {
-      ElMessage.warning('请为所有复制的行选择不同的日期')
-      return
-    }
-
-    const rowsWithoutCheckers = copiedRows.filter(row => !row.checkers || row.checkers.length === 0)
-    if (rowsWithoutCheckers.length > 0) {
-      ElMessage.warning('请为所有复制的行选择检验员')
-      return
-    }
+  // 校验:检验员不能为空
+  if (!row.checkers || row.checkers.length === 0) {
+    return
   }
-
-  // 校验修改的行
-  if (modifiedRows.length > 0) {
-    const rowsWithoutDate = modifiedRows.filter(row => !row.date || row.date.trim() === '')
-    if (rowsWithoutDate.length > 0) {
-      ElMessage.warning('请为所有修改的行选择日期')
-      return
-    }
-
-    const rowsWithoutCheckers = modifiedRows.filter(row => !row.checkers || row.checkers.length === 0)
-    if (rowsWithoutCheckers.length > 0) {
-      ElMessage.warning('请为所有修改的行选择检验员')
+  // 校验:同 confirmOrderId 日期不能重复
+  if (row.confirmOrderId) {
+    const sameGroup = tableData.value.filter(r => r.confirmOrderId === row.confirmOrderId)
+    const duplicate = sameGroup.some(item => item.date === row.date && item !== row)
+    if (duplicate) {
+      ElMessage.warning('同一个约检确认单下日期不能重复')
       return
     }
   }
 
   try {
-    const allSubmitData: any[] = []
-
-    copiedRows.forEach(row => {
-      const teamList = (row.teamList || []).map(team => ({
-        groupTeamId: team.groupTeamId,
-        leaderId: team.leaders?.[0]?.id || '',
-        memberIdList: team.members?.map(member => member.id) || []
-      }))
-      allSubmitData.push({
+    const teamList = (row.teamList || []).map(team => ({
+      groupTeamId: team.groupTeamId,
+      leaderId: team.leaders?.[0]?.id || '',
+      memberIdList: team.members?.map(member => member.id) || []
+    }))
+
+    if (row.isCopied && !row.submitted) {
+      // 复制行
+      await EquipPipeSchedulingApi.setShiftSchedule([{
         isCopy: true,
         sourceId: row.id,
         date: row.date,
         teamList: teamList
-      })
-    })
-
-    modifiedRows.forEach(row => {
-      const teamList = (row.teamList || []).map(team => ({
-        groupTeamId: team.groupTeamId,
-        leaderId: team.leaders?.[0]?.id || '',
-        memberIdList: team.members?.map(member => member.id) || []
-      }))
-      allSubmitData.push({
+      }])
+      row.submitted = true
+      row.modified = false
+    } else {
+      // 修改行
+      await EquipPipeSchedulingApi.setShiftSchedule([{
         isCopy: false,
         id: row.id,
         date: row.date,
         teamList: teamList
-      })
-    })
-
-    console.log('提交数据:', allSubmitData)
-    await EquipPipeSchedulingApi.setShiftSchedule(allSubmitData)
-
-    const totalCount = copiedRows.length + modifiedRows.length
-    ElMessage.success(`成功提交 ${totalCount} 条数据`)
-
-    await handleQuery()
+      }])
+      row.modified = false
+    }
+    ElMessage.success('保存成功')
   } catch (error) {
-    console.error('提交失败:', error)
-    ElMessage.error('提交失败')
+    console.error('自动保存失败:', error)
+    ElMessage.error('保存失败')
   }
 }
 
@@ -732,7 +683,6 @@ const handleExport = async () => {
 // 暴露方法给父组件
 defineExpose({
   handleQuery,
-  handleSubmit,
   handleSubmitSelected,
   handleExport
 })

+ 0 - 8
yudao-ui-admin-vue3/src/views/pressure2/schedule/pipeindex.vue

@@ -98,9 +98,6 @@
       <Icon icon="ep:upload" class="mr-5px" /> 提交计划
     </el-button>
     <template v-if="queryParams.type === '300'">
-      <el-button type="success" @click="handleShiftSubmit">
-        <Icon icon="ep:upload" class="mr-5px" /> 提交全部修改
-      </el-button>
       <el-button type="success" @click="handleShiftExport" :loading="shiftExportLoading">
         <Icon icon="ep:download" class="mr-5px" /> 导出
       </el-button>
@@ -789,11 +786,6 @@ const handleSubmitPlan = async () => {
   }
 }
 
-// 排班表 - 提交全部修改
-const handleShiftSubmit = () => {
-  shiftScheduleRef.value?.handleSubmit()
-}
-
 // 排班表 - 导出
 const handleShiftExport = async () => {
   shiftScheduleRef.value?.handleExport()