Quellcode durchsuchen

瑞都新增日报

Zimo vor 16 Stunden
Ursprung
Commit
f9c5805487

+ 1 - 1
src/api/pms/iotrddailyreport/index.ts

@@ -71,7 +71,7 @@ export const IotRdDailyReportApi = {
   },
 
   // 新增瑞都日报
-  createIotRdDailyReport: async (data: IotRdDailyReportVO) => {
+  createIotRdDailyReport: async (data: any) => {
     return await request.post({ url: `/pms/iot-rd-daily-report/create`, data })
   },
 

+ 4 - 2
src/api/system/user/index.ts

@@ -34,7 +34,7 @@ export const companyDeptsEmployee = (params: PageParam) => {
 }
 
 // 获取选择的部门包含的子部门下的所有人员
-export const selectedDeptsEmployee = (params: PageParam) => {
+export const selectedDeptsEmployee = (params: any) => {
   return request.get({ url: '/system/user/selectedDeptsEmployee', params })
 }
 
@@ -94,7 +94,9 @@ export const getDeptUsers = (id): Promise<UserVO[]> => {
   return request.get({ url: '/system/user/dept/users?userId=' + id })
 }
 export const getMaintainUsers = (id, businessId): Promise<UserVO[]> => {
-  return request.get({ url: '/rq/iot-maintain/maintain/users?userId=' + id + '&businessId=' + businessId})
+  return request.get({
+    url: '/rq/iot-maintain/maintain/users?userId=' + id + '&businessId=' + businessId
+  })
 }
 export const getDeptUsersByDeptId = (id): Promise<UserVO[]> => {
   return request.get({ url: '/system/user/dept/users/id?userId=' + id })

+ 370 - 0
src/views/pms/iotrddailyreport/create-rd-form.vue

@@ -0,0 +1,370 @@
+<script setup lang="ts">
+import { FormInstance, FormRules } from 'element-plus'
+import { Close } from '@element-plus/icons-vue'
+import * as UserApi from '@/api/system/user'
+import { useUserStore } from '@/store/modules/user'
+import { getStrDictOptions } from '@/utils/dict'
+import * as DeptApi from '@/api/system/dept'
+import { IotRdDailyReportApi } from '@/api/pms/iotrddailyreport'
+
+const deptId = useUserStore().getUser.deptId
+
+interface Props {
+  visible: boolean
+  loadList: () => void
+}
+
+const props = withDefaults(defineProps<Props>(), {
+  visible: false
+})
+
+const emits = defineEmits(['update:visible'])
+
+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: '其他非生产时间' }
+]
+
+interface Form {
+  deptId: number
+  location: string
+  responsiblePerson: number
+  timeRange: string[]
+  rdStatus: string
+  dailyFuel: number
+  productionStatus: string
+  nextPlan: string
+  externalRental: string
+  malfunction: string
+  otherNptReason: string
+  [key: (typeof NON_PROD_FIELDS)[number]['key']]: any
+}
+
+const original = {
+  deptId,
+  timeRange: ['08:00', '08:00'],
+  ...NON_PROD_FIELDS.reduce((acc, field) => ({ ...acc, [field.key]: 0 }), {}),
+  winterBreakTime: 24
+}
+
+const formRef = ref<FormInstance>()
+
+const form = ref<Partial<Form>>({ ...original })
+
+function noProductionTimeRule() {
+  return {
+    validator: (_rule: any, _value: any, callback: any) => {
+      let totalTime = 0
+      NON_PROD_FIELDS.forEach((field) => {
+        const val = parseFloat(form.value[field.key])
+        if (!isNaN(val)) {
+          totalTime += val
+        }
+      })
+      const fixedTotal = Number(totalTime.toFixed(2))
+      if (fixedTotal > 24) {
+        callback(new Error(`总时间(${fixedTotal}h)不能超过 24 小时`))
+      } else {
+        callback()
+      }
+    },
+    trigger: 'blur'
+  }
+}
+
+function handleRowValidate(key: string) {
+  if (!formRef.value) return
+
+  const propsToValidate = NON_PROD_FIELDS.map((field) => field.key)
+
+  if (key === 'otherNptTime') propsToValidate.push('otherNptReason')
+
+  formRef.value.validateField(propsToValidate)
+}
+
+const rules: FormRules = {
+  timeRange: [
+    { required: true, message: '请选择时间节点', trigger: ['blur', 'change'], type: 'array' }
+  ],
+  location: [{ required: true, message: '请输入施工地点', trigger: ['blur', 'change'] }],
+  responsiblePerson: [
+    { required: true, message: '请选择带班干部', trigger: ['blur', 'change'], type: 'array' }
+  ],
+  rdStatus: [{ required: true, message: '请选择施工状态', trigger: ['blur', 'change'] }],
+  dailyFuel: [{ required: true, message: '请输入当日油耗', trigger: ['blur', 'change'] }],
+  productionStatus: [{ required: true, message: '请输入生产状态', trigger: ['blur', 'change'] }],
+  nextPlan: [{ required: true, message: '请输入下计划', trigger: ['blur', 'change'] }]
+}
+
+interface UserOptions {
+  label: string
+  value: number
+  raw: any
+}
+
+const userOptions = ref<UserOptions[]>([])
+
+const deptName = ref('')
+
+async function loadDept() {
+  const res = await DeptApi.getDept(deptId)
+  deptName.value = res.name
+}
+
+async function loadUserOptions() {
+  const res = await UserApi.selectedDeptsEmployee({ deptIds: [deptId] })
+  userOptions.value = res.map((item: any) => ({
+    label: item.nickname,
+    value: item.id,
+    raw: item
+  }))
+}
+
+const loading = ref(false)
+
+async function load() {
+  loading.value = true
+  await loadDept()
+  await loadUserOptions()
+  loading.value = false
+}
+
+const rdStatusOptions = getStrDictOptions(DICT_TYPE.PMS_PROJECT_RD_STATUS)
+
+function handleOpenForm() {
+  form.value = { ...original }
+  load()
+  emits('update:visible', true)
+}
+
+function handleCloseForm() {
+  emits('update:visible', false)
+}
+
+defineExpose({ handleOpenForm })
+
+const formLoading = ref(false)
+
+const message = useMessage()
+
+async function submitForm() {
+  if (!formRef.value) return
+
+  try {
+    formLoading.value = true
+    await formRef.value.validate()
+    const { timeRange, ...rest } = form.value
+    const data = { ...rest, startTime: timeRange?.[0], endTime: timeRange?.[1] }
+
+    await IotRdDailyReportApi.createIotRdDailyReport(data)
+
+    message.success('新增成功')
+    handleCloseForm()
+    props.loadList()
+  } catch (error) {
+    console.log('error :>> ', error)
+  } finally {
+    formLoading.value = false
+  }
+}
+</script>
+
+<template>
+  <el-drawer
+    :model-value="visible"
+    @update:model-value="emits('update:visible', $event)"
+    header-class="mb-0!"
+    :with-header="false"
+    size="50%"
+    :close-on-press-escape="false"
+    :close-on-click-modal="false"
+  >
+    <div class="size-full flex flex-col gap-4">
+      <div class="flex justify-between items-center">
+        <div class="text-xl font-bold text-gray-900 leading-tight"> 新建日报 </div>
+        <el-button link @click="handleCloseForm">
+          <el-icon size="24"><Close /></el-icon>
+        </el-button>
+      </div>
+      <el-form
+        ref="formRef"
+        size="default"
+        label-position="top"
+        :model="form"
+        require-asterisk-position="right"
+        class="flex flex-col"
+        :rules="rules"
+        :loading="loading"
+      >
+        <div class="grid grid-cols-2 gap-x-8">
+          <el-form-item label="施工队伍">{{ deptName }}</el-form-item>
+          <el-form-item label="施工地点" prop="location">
+            <el-input v-model="form.location" clearable placeholder="请输入施工地点" />
+          </el-form-item>
+          <el-form-item label="带班干部" prop="responsiblePerson">
+            <el-select
+              v-model="form.responsiblePerson"
+              multiple
+              :options="userOptions"
+              clearable
+              filterable
+              collapse-tags
+              collapse-tags-tooltip
+              :max-collapse-tags="5"
+              tag-type="primary"
+              placeholder="请选择带班干部"
+            />
+          </el-form-item>
+          <el-form-item label="时间节点" prop="timeRange">
+            <el-time-picker
+              v-model="form.timeRange"
+              is-range
+              range-separator="至"
+              start-placeholder="开始时间"
+              end-placeholder="结束时间"
+              placeholder="选择时间范围"
+              clearable
+              format="HH:mm"
+              value-format="HH:mm"
+            />
+          </el-form-item>
+          <el-form-item label="施工状态" prop="rdStatus">
+            <el-select
+              v-model="form.rdStatus"
+              :options="rdStatusOptions"
+              placeholder="请选择"
+              class="w-full"
+              clearable
+            />
+          </el-form-item>
+          <el-form-item label="当日油耗(L)" prop="dailyFuel">
+            <el-input-number
+              v-model="form.dailyFuel"
+              :min="0"
+              :controls="false"
+              align="left"
+              class="w-full!"
+              placeholder="请输入当日油耗"
+            >
+              <template #suffix>升(L)</template>
+            </el-input-number>
+          </el-form-item>
+          <el-form-item label="当日生产动态" prop="productionStatus">
+            <el-input
+              v-model="form.productionStatus"
+              type="textarea"
+              :autosize="{ minRows: 2 }"
+              resize="none"
+              show-word-limit
+              :maxlength="1000"
+              placeholder="请输入外组设备"
+            />
+          </el-form-item>
+          <el-form-item label="下步工作计划" prop="nextPlan">
+            <el-input
+              v-model="form.nextPlan"
+              type="textarea"
+              :autosize="{ minRows: 2 }"
+              resize="none"
+              show-word-limit
+              :maxlength="1000"
+              placeholder="请输入下步工作计划"
+            />
+          </el-form-item>
+
+          <el-form-item label="外租设备" prop="externalRental">
+            <el-input
+              v-model="form.externalRental"
+              type="textarea"
+              :autosize="{ minRows: 2 }"
+              resize="none"
+              show-word-limit
+              :maxlength="1000"
+              placeholder="请输入外组设备"
+            />
+          </el-form-item>
+          <el-form-item label="故障情况" prop="malfunction">
+            <el-input
+              v-model="form.malfunction"
+              type="textarea"
+              :autosize="{ minRows: 2 }"
+              show-word-limit
+              resize="none"
+              :maxlength="1000"
+              placeholder="请输入故障情况"
+            />
+          </el-form-item>
+        </div>
+        <el-divider class="m-0! mb-3! border-2! border-[var(--el-color-primary)]!" />
+        <h3 class="text-lg font-bold text-gray-800 mb-6 flex items-center gap-2">
+          <div class="w-1 h-4 bg-blue-600 rounded-full"></div>
+          非生产时间
+        </h3>
+        <div class="grid grid-cols-4 gap-x-8">
+          <el-form-item
+            v-for="field in NON_PROD_FIELDS"
+            :key="field.key"
+            :label="field.label"
+            :prop="field.key"
+            :rules="noProductionTimeRule()"
+          >
+            <el-input-number
+              v-model="form[field.key]"
+              :min="0"
+              :max="24"
+              :controls="false"
+              class="w-full!"
+              align="left"
+              @blur="handleRowValidate(field.key)"
+            >
+              <template #suffix>小时(H)</template>
+            </el-input-number>
+          </el-form-item>
+
+          <el-form-item
+            class="col-span-4"
+            label="其他非生产原因"
+            prop="otherNptReason"
+            :rules="{
+              required: form.otherNptTime > 0,
+              message: '请填写原因',
+              trigger: ['blur', 'change']
+            }"
+          >
+            <el-input
+              v-model="form.otherNptReason"
+              type="textarea"
+              :autosize="{ minRows: 2 }"
+              resize="none"
+              show-word-limit
+              :maxlength="1000"
+              placeholder="当'其他非生产时间'大于0时必填"
+            />
+          </el-form-item>
+        </div>
+      </el-form>
+    </div>
+    <template #footer>
+      <el-button size="default" type="primary" @click="submitForm" :loading="formLoading">
+        确 定
+      </el-button>
+      <el-button size="default" @click="emits('update:visible', false)">取 消</el-button>
+    </template>
+  </el-drawer>
+</template>
+
+<style scoped>
+:deep(.el-form-item__label) {
+  font-weight: 500;
+}
+</style>

+ 15 - 8
src/views/pms/iotrddailyreport/fillDailyReport.vue

@@ -6,7 +6,7 @@ import { DICT_TYPE, getDictOptions } from '@/utils/dict'
 import { rangeShortcuts } from '@/utils/formatTime'
 import { useDebounceFn } from '@vueuse/core'
 import dayjs from 'dayjs'
-import rdForm from './rd-form.vue'
+import createRdForm from './create-rd-form.vue'
 
 defineOptions({ name: 'FillDailyReport' })
 
@@ -123,13 +123,13 @@ watch(
 
 const visible = ref(false)
 
-// const formRef = ref()
+const formRef = ref()
 
-// function handleOpenForm(id: number, type: 'edit' | 'detail' | 'approval' | 'time') {
-//   if (formRef.value) {
-//     formRef.value.handleOpenForm(id, type)
-//   }
-// }
+function handleOpenCreateForm() {
+  if (formRef.value) {
+    formRef.value.handleOpenForm()
+  }
+}
 
 function handleOpenForm(id: number, type: 'edit' | 'detail' | 'approval' | 'time') {
   router.push({
@@ -219,6 +219,13 @@ function realValue(type: any, value: string) {
         </el-form-item>
       </div>
       <el-form-item>
+        <el-button
+          type="primary"
+          @click="handleOpenCreateForm()"
+          v-hasPermi="['pms:iot-rd-daily-report:update']"
+        >
+          新增日报
+        </el-button>
         <el-button type="primary" @click="handleQuery()">
           <Icon icon="ep:search" class="mr-5px" /> 搜索
         </el-button>
@@ -366,7 +373,7 @@ function realValue(type: any, value: string) {
       </div>
     </div>
   </div>
-  <rd-form ref="formRef" :load-list="loadList" v-model:visible="visible" />
+  <create-rd-form ref="formRef" :load-list="loadList" v-model:visible="visible" />
   <!-- <IotRdDailyReportForm ref="formRef" @success="loadList" /> -->
 </template>