Zimo пре 2 дана
родитељ
комит
39d1df1f79

+ 22 - 0
src/utils/formatTime.ts

@@ -443,3 +443,25 @@ export function formatDateNoTime(timestamp?: number) {
   if (!timestamp) return ''
   return dayjs(timestamp).format('YYYY-MM-DD')
 }
+
+export const formatT = (arr: number[]) =>
+  `${arr[0].toString().padStart(2, '0')}:${arr[1].toString().padStart(2, '0')}`
+
+export const calculateDuration = (row: any) => {
+  if (!row.startTime || !row.endTime) {
+    row.duration = 0
+    return
+  }
+
+  const todayStr = dayjs().format('YYYY-MM-DD')
+  const start = dayjs(`${todayStr} ${row.startTime}`)
+  const end = dayjs(`${todayStr} ${row.endTime}`)
+
+  let diffMinutes = end.diff(start, 'minute')
+
+  if (diffMinutes < 0) {
+    diffMinutes += 1440
+  }
+
+  row.duration = Number((diffMinutes / 60).toFixed(2))
+}

+ 1 - 23
src/views/pms/iotrddailyreport/rd-form.vue

@@ -2,7 +2,7 @@
 import { IotRdDailyReportApi } from '@/api/pms/iotrddailyreport'
 import { FormInstance, FormRules } from 'element-plus'
 import { Close, CircleCheck, Plus, Delete } from '@element-plus/icons-vue'
-import { formatDateNoTime } from '@/utils/formatTime'
+import { calculateDuration, formatDateNoTime, formatT } from '@/utils/formatTime'
 import { getStrDictOptions } from '@/utils/dict'
 import { IotDailyReportAttrsApi } from '@/api/pms/iotdailyreportattrs'
 import { useTableComponents } from '@/components/ZmTable/useTableComponents'
@@ -272,9 +272,6 @@ const initDailyFuel = () => {
   }
 }
 
-const formatT = (arr: number[]) =>
-  `${arr[0].toString().padStart(2, '0')}:${arr[1].toString().padStart(2, '0')}`
-
 const loading = ref(false)
 async function loadDetail(id: number) {
   loading.value = true
@@ -624,25 +621,6 @@ const removeReportDetailRow = (index: number) => {
   form.value.reportDetails?.splice(index, 1)
 }
 
-const calculateDuration = (row: any) => {
-  if (!row.startTime || !row.endTime) {
-    row.duration = 0
-    return
-  }
-
-  const todayStr = dayjs().format('YYYY-MM-DD')
-  const start = dayjs(`${todayStr} ${row.startTime}`)
-  const end = dayjs(`${todayStr} ${row.endTime}`)
-
-  let diffMinutes = end.diff(start, 'minute')
-
-  if (diffMinutes < 0) {
-    diffMinutes += 1440
-  }
-
-  row.duration = Number((diffMinutes / 60).toFixed(2))
-}
-
 const handleListChange = useDebounceFn(() => {
   let total = 0
   form.value.reportFuels.forEach((item) => {

+ 16 - 20
src/views/pms/iotrydailyreport/ry-form.vue

@@ -6,6 +6,7 @@ import { FormInstance, FormRules } from 'element-plus'
 import { computed, reactive, ref, watch, nextTick } from 'vue'
 import { Delete, Plus } from '@element-plus/icons-vue'
 import dayjs from 'dayjs'
+import { calculateDuration, formatT } from '@/utils/formatTime'
 
 interface Props {
   visible: boolean
@@ -183,7 +184,16 @@ async function loadDetail(id: number) {
       }
     })
 
-    form.value.reportDetails = res.reportDetails ? (res.reportDetails as any[]) : []
+    form.value.reportDetails = (res.reportDetails ? (res.reportDetails as any[]) : []).map(
+      (item) => ({
+        startTime: formatT(item.startTime),
+        endTime: formatT(item.endTime),
+        duration: item.duration,
+        currentDepth: item.currentDepth,
+        currentOperation: item.currentOperation,
+        constructionDetail: item.constructionDetail
+      })
+    )
 
     if (!form.value.reportDetails.length) {
       addProductionStatusRow()
@@ -375,6 +385,9 @@ const handleAudit = async (auditStatus: 20 | 30) => {
   if (!formRef.value) return
   try {
     formLoading.value = true
+
+    await formRef.value.validate()
+
     await IotRyDailyReportApi.approvalIotRyDailyReport({
       id: form.value.id!,
       auditStatus,
@@ -403,25 +416,6 @@ const orange = computed(() => {
   if (Math.abs(total - 24) > 0.01) return true
   return false
 })
-
-const calculateDuration = (row: any) => {
-  if (!row.startTime || !row.endTime) {
-    row.duration = 0
-    return
-  }
-
-  const todayStr = dayjs().format('YYYY-MM-DD')
-  const start = dayjs(`${todayStr} ${row.startTime}`)
-  const end = dayjs(`${todayStr} ${row.endTime}`)
-
-  let diffMinutes = end.diff(start, 'minute')
-
-  if (diffMinutes < 0) {
-    diffMinutes += 1440
-  }
-
-  row.duration = Number((diffMinutes / 60).toFixed(2))
-}
 </script>
 
 <template>
@@ -698,6 +692,7 @@ const calculateDuration = (row: any) => {
                       value-format="HH:mm"
                       class="w-full!"
                       @change="calculateDuration(row)"
+                      :disabled="isMainFieldDisabled"
                     />
                   </el-form-item>
                 </template>
@@ -722,6 +717,7 @@ const calculateDuration = (row: any) => {
                       value-format="HH:mm"
                       class="w-full!"
                       @change="calculateDuration(row)"
+                      :disabled="isMainFieldDisabled"
                     />
                   </el-form-item>
                 </template>

+ 179 - 147
src/views/pms/iotrydailyreport/ry-xj-form.vue

@@ -2,8 +2,11 @@
 import { IotRyDailyReportApi } from '@/api/pms/iotrydailyreport'
 import { useTableComponents } from '@/components/ZmTable/useTableComponents'
 import { DICT_TYPE, getStrDictOptions } from '@/utils/dict'
+import { calculateDuration, formatT } from '@/utils/formatTime'
 import { FormInstance, FormRules } from 'element-plus'
 import { computed, reactive, ref, watch, nextTick } from 'vue'
+import { Delete, Plus } from '@element-plus/icons-vue'
+import dayjs from 'dayjs'
 
 interface Props {
   visible: boolean
@@ -35,13 +38,12 @@ const NON_PROD_FIELDS = [
   { key: 'otherNptTime', label: '其他非生产时间' }
 ] as const
 
-interface ProductionStatus {
-  date: string
-  start_time: string
-  end_time: string
+interface ReportDetail {
+  startTime: string
+  endTime: string
   duration: number
-  operatingMode: string
-  detail: string
+  currentOperation: string
+  constructionDetail: string
 }
 
 interface FormOriginal {
@@ -83,8 +85,9 @@ interface FormOriginal {
 
   // 其他非生产时间原因(仅作为备注字段存在)
   otherNptReason: string
+  constructionBrief: string
 
-  productionStatus: ProductionStatus[]
+  reportDetails: ReportDetail[]
   remark: string
   createTime: string
   opinion: string
@@ -115,7 +118,8 @@ const FORM_KEYS: (keyof FormOriginal)[] = [
   'totalStaffNum',
   'onDutyStaffNum',
   'leaveStaffNum',
-  // 'productionStatus',
+  'constructionBrief',
+  'reportDetails',
   'remark',
   'createTime',
   'opinion',
@@ -177,7 +181,19 @@ async function loadDetail(id: number) {
       }
     })
 
-    form.value.productionStatus = []
+    form.value.reportDetails = (res.reportDetails ? (res.reportDetails as any[]) : []).map(
+      (item) => ({
+        startTime: formatT(item.startTime),
+        endTime: formatT(item.endTime),
+        duration: item.duration,
+        currentOperation: item.currentOperation,
+        constructionDetail: item.constructionDetail
+      })
+    )
+
+    if (!form.value.reportDetails.length) {
+      addProductionStatusRow()
+    }
 
     if (props.type === 'edit' && !props.noValidateStatus && res.status !== 0)
       formType.value = 'readonly'
@@ -189,24 +205,26 @@ async function loadDetail(id: number) {
 }
 
 const addProductionStatusRow = () => {
-  if (!form.value.productionStatus) {
-    form.value.productionStatus = []
+  if (!form.value.reportDetails) {
+    form.value.reportDetails = []
   }
-  form.value.productionStatus.push({
-    date: '',
-    start_time: '',
-    end_time: '',
+  form.value.reportDetails.push({
+    startTime: '',
+    endTime: '',
     duration: 0,
-    operatingMode: '',
-    detail: ''
+    currentOperation: '',
+    constructionDetail: ''
   })
 }
 
 const removeProductionStatusRow = (index: number) => {
-  form.value.productionStatus?.splice(index, 1)
+  if (index === 0) {
+    message.warning('至少填写一条生产动态')
+  }
+  form.value.reportDetails?.splice(index, 1)
 }
 
-const { ZmTable, ZmTableColumn } = useTableComponents<ProductionStatus>()
+const { ZmTable, ZmTableColumn } = useTableComponents<ReportDetail>()
 
 function handleOpenForm(id: number, type: 'edit' | 'readonly') {
   formType.value = type
@@ -280,7 +298,10 @@ const validateOtherReason = (_rule: any, value: any, callback: any) => {
 // 动态构建校验规则
 const rules = reactive<FormRules>({
   repairStatus: [{ required: true, message: '请选择施工状态', trigger: ['change', 'blur'] }],
-  productionStatus: [{ required: true, message: '请输入生产动态', trigger: ['blur', 'change'] }],
+  reportDetails: [{ required: true, message: '请填写生产动态', type: 'array' }],
+  constructionBrief: [
+    { required: true, message: '请填写施工简报', type: 'string', trigger: ['blur', 'change'] }
+  ],
 
   // 生产时间绑定校验
   ratedProductionTime: [
@@ -348,6 +369,9 @@ const handleAudit = async (auditStatus: 20 | 30) => {
   if (!formRef.value) return
   try {
     formLoading.value = true
+
+    await formRef.value.validateField('constructionBrief')
+
     await IotRyDailyReportApi.approvalIotRyDailyReport({
       id: form.value.id!,
       auditStatus,
@@ -594,7 +618,7 @@ const orange = computed(() => {
         </el-form-item>
 
         <div class="col-span-2">
-          <div class="flex items-center justify-between mb-2">
+          <div class="flex items-center justify-between mb-6">
             <div class="flex items-center gap-2">
               <div class="bg-[var(--el-color-primary)] w-1 h-5 rounded-full"></div>
               <div class="text-lg font-medium text-[var(--el-text-color-primary)]">生产动态</div>
@@ -602,144 +626,152 @@ const orange = computed(() => {
             <el-button
               type="primary"
               link
-              icon="ep:plus"
+              :icon="Plus"
               @click="addProductionStatusRow"
               :disabled="isMainFieldDisabled"
             >
               添加一行
             </el-button>
           </div>
-
-          <ZmTable :data="form.productionStatus!" :loading="false" class="mb-4">
-            <ZmTableColumn label="日期" min-width="140" align="center">
-              <template #default="{ row, $index }">
-                <el-form-item
-                  :prop="`productionStatus.${$index}.date`"
-                  :rules="{ required: true, message: '请选择日期', trigger: 'change' }"
-                  class="mb-0!"
-                >
-                  <el-date-picker
-                    v-model="row.date"
-                    type="date"
-                    value-format="YYYY-MM-DD"
-                    placeholder="选择日期"
-                    :clearable="false"
-                    class="!w-full"
-                    :disabled="isMainFieldDisabled"
-                  />
-                </el-form-item>
-              </template>
-            </ZmTableColumn>
-
-            <ZmTableColumn label="开始时间" min-width="120" align="center">
-              <template #default="{ row, $index }">
-                <el-form-item
-                  :prop="`productionStatus.${$index}.start_time`"
-                  :rules="{ required: true, message: '必填', trigger: 'change' }"
-                  class="mb-0!"
-                >
-                  <el-time-picker
-                    v-model="row.start_time"
-                    format="HH:mm"
-                    value-format="HH:mm"
-                    placeholder="开始"
-                    class="!w-full"
-                    :clearable="false"
-                    :disabled="isMainFieldDisabled"
-                  />
-                </el-form-item>
-              </template>
-            </ZmTableColumn>
-
-            <ZmTableColumn label="结束时间" min-width="120" align="center">
-              <template #default="{ row, $index }">
-                <el-form-item
-                  :prop="`productionStatus.${$index}.end_time`"
-                  :rules="{ required: true, message: '必填', trigger: 'change' }"
-                  class="mb-0!"
-                >
-                  <el-time-picker
-                    v-model="row.end_time"
-                    format="HH:mm"
-                    value-format="HH:mm"
-                    placeholder="结束"
-                    class="!w-full"
-                    :clearable="false"
+          <el-form-item prop="reportDetails">
+            <ZmTable :data="form.reportDetails!" :loading="false" class="mb-4">
+              <ZmTableColumn
+                label="日期"
+                :width="105"
+                cover-formatter
+                :real-value="
+                  () => (form.createTime ? dayjs(form.createTime).format('YYYY-MM-DD') : '')
+                "
+              />
+
+              <ZmTableColumn :width="160" label="开始时间" prop="startTime">
+                <template #default="{ row, $index }">
+                  <el-form-item
+                    v-if="$index >= 0"
+                    class="mb-0!"
+                    :prop="`reportDetails.${$index}.startTime`"
+                    :rules="{
+                      required: true,
+                      message: '请选择开始时间',
+                      trigger: ['change', 'blur']
+                    }"
+                  >
+                    <el-time-picker
+                      v-model="row.startTime"
+                      placeholder="选择开始时间"
+                      clearable
+                      format="HH:mm"
+                      value-format="HH:mm"
+                      class="w-full!"
+                      @change="calculateDuration(row)"
+                      :disabled="isMainFieldDisabled"
+                    />
+                  </el-form-item>
+                </template>
+              </ZmTableColumn>
+              <ZmTableColumn :width="160" label="结束时间" prop="endTime">
+                <template #default="{ row, $index }">
+                  <el-form-item
+                    v-if="$index >= 0"
+                    class="mb-0!"
+                    :prop="`reportDetails.${$index}.endTime`"
+                    :rules="{
+                      required: true,
+                      message: '请选择结束时间',
+                      trigger: ['change', 'blur']
+                    }"
+                  >
+                    <el-time-picker
+                      v-model="row.endTime"
+                      placeholder="选择结束时间"
+                      clearable
+                      format="HH:mm"
+                      value-format="HH:mm"
+                      class="w-full!"
+                      @change="calculateDuration(row)"
+                      :disabled="isMainFieldDisabled"
+                    />
+                  </el-form-item>
+                </template>
+              </ZmTableColumn>
+              <ZmTableColumn :width="80" label="时长(H)" prop="duration" />
+
+              <ZmTableColumn label="工况" min-width="120">
+                <template #default="{ row, $index }">
+                  <el-form-item
+                    v-if="$index >= 0"
+                    :prop="`reportDetails.${$index}.currentOperation`"
+                    :rules="{ required: true, message: '请输入工况', trigger: ['change', 'blur'] }"
+                    class="mb-0!"
+                  >
+                    <el-input
+                      v-model="row.currentOperation"
+                      type="textarea"
+                      :autosize="{ minRows: 1 }"
+                      resize="none"
+                      show-word-limit
+                      :maxlength="1000"
+                      placeholder="请输入工况"
+                      :disabled="isMainFieldDisabled"
+                    />
+                  </el-form-item>
+                </template>
+              </ZmTableColumn>
+
+              <ZmTableColumn label="详细描述" min-width="200" align="center">
+                <template #default="{ row, $index }">
+                  <el-form-item
+                    v-if="$index >= 0"
+                    :prop="`reportDetails.${$index}.constructionDetail`"
+                    :rules="{ required: true, message: '请输入详细描述', trigger: 'blur' }"
+                    class="mb-0!"
+                  >
+                    <el-input
+                      v-model="row.constructionDetail"
+                      type="textarea"
+                      :autosize="{ minRows: 1 }"
+                      resize="none"
+                      show-word-limit
+                      :maxlength="1000"
+                      placeholder="请输入详细描述"
+                      :disabled="isMainFieldDisabled"
+                    />
+                  </el-form-item>
+                </template>
+              </ZmTableColumn>
+
+              <ZmTableColumn label="操作" width="80" fixed="right" align="center">
+                <template #default="{ $index }">
+                  <el-button
+                    link
+                    type="danger"
+                    :icon="Delete"
+                    @click="removeProductionStatusRow($index)"
                     :disabled="isMainFieldDisabled"
-                  />
-                </el-form-item>
-              </template>
-            </ZmTableColumn>
-
-            <ZmTableColumn label="时长(h)" min-width="100" align="center">
-              <template #default="{ row, $index }">
-                <el-form-item :prop="`productionStatus.${$index}.duration`" class="mb-0!">
-                  <el-input-number
-                    v-model="row.duration"
-                    :min="0"
-                    :controls="false"
-                    class="!w-full"
-                    :disabled="isMainFieldDisabled"
-                  />
-                </el-form-item>
-              </template>
-            </ZmTableColumn>
-
-            <ZmTableColumn label="工况" min-width="120" align="center">
-              <template #default="{ row, $index }">
-                <el-form-item
-                  :prop="`productionStatus.${$index}.operatingMode`"
-                  :rules="{ required: true, message: '必填', trigger: 'blur' }"
-                  class="mb-0!"
-                >
-                  <el-input
-                    v-model="row.operatingMode"
-                    placeholder="请输入工况"
-                    :disabled="isMainFieldDisabled"
-                  />
-                </el-form-item>
-              </template>
-            </ZmTableColumn>
-
-            <ZmTableColumn label="详细描述" min-width="200" align="center">
-              <template #default="{ row, $index }">
-                <el-form-item
-                  :prop="`productionStatus.${$index}.detail`"
-                  :rules="{ required: true, message: '必填', trigger: 'blur' }"
-                  class="mb-0!"
-                >
-                  <el-input
-                    v-model="row.detail"
-                    placeholder="生产详情"
-                    :disabled="isMainFieldDisabled"
-                  />
-                </el-form-item>
-              </template>
-            </ZmTableColumn>
-
-            <ZmTableColumn label="操作" width="60" fixed="right" align="center">
-              <template #default="{ $index }">
-                <el-button
-                  link
-                  type="danger"
-                  @click="removeProductionStatusRow($index)"
-                  :disabled="isMainFieldDisabled"
-                >
-                  删除
-                </el-button>
-              </template>
-            </ZmTableColumn>
-          </ZmTable>
+                  >
+                    删除
+                  </el-button>
+                </template>
+              </ZmTableColumn>
+            </ZmTable>
+          </el-form-item>
         </div>
 
-        <el-form-item v-if="isApproval" class="col-span-2" label="当日生产简报" prop="remark">
+        <el-form-item
+          v-if="isApproval"
+          class="col-span-2"
+          label="当日施工简报"
+          prop="constructionBrief"
+        >
           <el-input
-            v-model="form.remark"
+            v-model="form.constructionBrief"
             type="textarea"
-            autosize
-            maxlength="1000"
+            :autosize="{ minRows: 2 }"
+            show-word-limit
+            resize="none"
+            :maxlength="1000"
+            placeholder="请输入当日施工简报"
             :disabled="formType === 'readonly'"
-            placeholder="请输入当日生产简报"
           />
         </el-form-item>