Browse Source

pms 瑞都日报 动态属性

zhangcl 1 tuần trước cách đây
mục cha
commit
7baa12d801

+ 64 - 59
src/api/pms/iotdailyreportattrs/index.ts

@@ -1,59 +1,64 @@
-import request from '@/config/axios'
-
-// 日报扩展模板属性 VO
-export interface IotDailyReportAttrsVO {
-  id: number // 主键id
-  templateId: number // 日报扩展模板id
-  deptId: number // 公司id
-  projectId: number // 项目id
-  projectClassification: string // 项目类别(钻井 修井 注氮 酸化压裂 ...)
-  wellType: string // 井型
-  wellCategory: string // 井别
-  technique: string // 施工工艺
-  name: string // 属性名称
-  identifier: string // 属性标识符
-  dataType: string // 数据类型(double text textarea date dropdown)
-  required: number // 是否必填(0非必填 1必填)
-  unit: string // 单位(MPa)
-  accessMode: string // 访问模式(r读  w写)
-  defaultValue: string // 默认值
-  maxValue: string // 最大值
-  minValue: string // 最小值
-  extProperty: string // 不同专业公司的扩展属性
-  sort: number // 排序值
-  remark: string // 备注
-  status: number // 状态(0启用 1禁用)
-}
-
-// 日报扩展模板属性 API
-export const IotDailyReportAttrsApi = {
-  // 查询日报扩展模板属性分页
-  getIotDailyReportAttrsPage: async (params: any) => {
-    return await request.get({ url: `/rq/iot-daily-report-attrs/page`, params })
-  },
-
-  // 查询日报扩展模板属性详情
-  getIotDailyReportAttrs: async (id: number) => {
-    return await request.get({ url: `/rq/iot-daily-report-attrs/get?id=` + id })
-  },
-
-  // 新增日报扩展模板属性
-  createIotDailyReportAttrs: async (data: IotDailyReportAttrsVO) => {
-    return await request.post({ url: `/rq/iot-daily-report-attrs/create`, data })
-  },
-
-  // 修改日报扩展模板属性
-  updateIotDailyReportAttrs: async (data: IotDailyReportAttrsVO) => {
-    return await request.put({ url: `/rq/iot-daily-report-attrs/update`, data })
-  },
-
-  // 删除日报扩展模板属性
-  deleteIotDailyReportAttrs: async (id: number) => {
-    return await request.delete({ url: `/rq/iot-daily-report-attrs/delete?id=` + id })
-  },
-
-  // 导出日报扩展模板属性 Excel
-  exportIotDailyReportAttrs: async (params) => {
-    return await request.download({ url: `/rq/iot-daily-report-attrs/export-excel`, params })
-  },
-}
+import request from '@/config/axios'
+
+// 日报扩展模板属性 VO
+export interface IotDailyReportAttrsVO {
+  id: number // 主键id
+  templateId: number // 日报扩展模板id
+  deptId: number // 公司id
+  projectId: number // 项目id
+  projectClassification: string // 项目类别(钻井 修井 注氮 酸化压裂 ...)
+  wellType: string // 井型
+  wellCategory: string // 井别
+  technique: string // 施工工艺
+  name: string // 属性名称
+  identifier: string // 属性标识符
+  dataType: string // 数据类型(double text textarea date dropdown)
+  required: number // 是否必填(0非必填 1必填)
+  unit: string // 单位(MPa)
+  accessMode: string // 访问模式(r读  w写)
+  defaultValue: string // 默认值
+  maxValue: string // 最大值
+  minValue: string // 最小值
+  extProperty: string // 不同专业公司的扩展属性
+  sort: number // 排序值
+  remark: string // 备注
+  status: number // 状态(0启用 1禁用)
+}
+
+// 日报扩展模板属性 API
+export const IotDailyReportAttrsApi = {
+  // 查询日报扩展模板属性分页
+  getIotDailyReportAttrsPage: async (params: any) => {
+    return await request.get({ url: `/rq/iot-daily-report-attrs/page`, params })
+  },
+
+  // 查询日报扩展属性列表
+  dailyReportAttrs: async (params: any) => {
+    return await request.get({ url: `/rq/iot-daily-report-attrs/dailyReportAttrs`, params })
+  },
+
+  // 查询日报扩展模板属性详情
+  getIotDailyReportAttrs: async (id: number) => {
+    return await request.get({ url: `/rq/iot-daily-report-attrs/get?id=` + id })
+  },
+
+  // 新增日报扩展模板属性
+  createIotDailyReportAttrs: async (data: IotDailyReportAttrsVO) => {
+    return await request.post({ url: `/rq/iot-daily-report-attrs/create`, data })
+  },
+
+  // 修改日报扩展模板属性
+  updateIotDailyReportAttrs: async (data: IotDailyReportAttrsVO) => {
+    return await request.put({ url: `/rq/iot-daily-report-attrs/update`, data })
+  },
+
+  // 删除日报扩展模板属性
+  deleteIotDailyReportAttrs: async (id: number) => {
+    return await request.delete({ url: `/rq/iot-daily-report-attrs/delete?id=` + id })
+  },
+
+  // 导出日报扩展模板属性 Excel
+  exportIotDailyReportAttrs: async (params) => {
+    return await request.download({ url: `/rq/iot-daily-report-attrs/export-excel`, params })
+  },
+}

+ 219 - 8
src/views/pms/iotrddailyreport/FillDailyReportForm.vue

@@ -145,6 +145,64 @@
           </el-col>
         </el-row>
 
+        <!-- 动态属性区域:施工工艺与当日生产动态之间 -->
+        <el-row v-if="dynamicAttrs.length > 0">
+          <el-col
+            v-for="attr in dynamicAttrs"
+            :key="attr.id"
+            :span="attr.dataType === 'textarea' ? 24 : 12"
+          >
+            <el-form-item
+              :label="attr.name + (attr.unit ? `(${attr.unit})` : '')"
+              :prop="'dynamicFields.' + attr.identifier"
+              :rules="getDynamicAttrRules(attr)"
+            >
+              <!-- 文本类型 -->
+              <el-input
+                v-if="attr.dataType === 'text'"
+                v-model="formData.dynamicFields[attr.identifier]"
+                :placeholder="`请输入${attr.name}`"
+              />
+
+              <!-- 文本域类型 -->
+              <el-input
+                v-else-if="attr.dataType === 'textarea'"
+                v-model="formData.dynamicFields[attr.identifier]"
+                :placeholder="`请输入${attr.name}`"
+                type="textarea"
+                :rows="3"
+              />
+
+              <!-- 数字类型 -->
+              <el-input
+                v-else-if="attr.dataType === 'double'"
+                v-model="formData.dynamicFields[attr.identifier]"
+                :placeholder="`请输入${attr.name}`"
+                type="number"
+                :min="attr.minValue || undefined"
+                :max="attr.maxValue || undefined"
+              />
+
+              <!-- 日期类型 -->
+              <el-date-picker
+                v-else-if="attr.dataType === 'date'"
+                v-model="formData.dynamicFields[attr.identifier]"
+                type="date"
+                value-format="x"
+                :placeholder="`选择${attr.name}`"
+                style="width: 100%"
+              />
+
+              <!-- 默认文本输入 -->
+              <el-input
+                v-else
+                v-model="formData.dynamicFields[attr.identifier]"
+                :placeholder="`请输入${attr.name}`"
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+
         <!-- 第三行:当日生产动态 -->
         <el-row>
           <el-col :span="24">
@@ -211,6 +269,7 @@ import { useTagsViewStore } from '@/store/modules/tagsView'
 import { useRouter, useRoute } from 'vue-router'
 import {DICT_TYPE, getDictLabel, getStrDictOptions} from '@/utils/dict'
 import { IotRdDailyReportApi } from '@/api/pms/iotrddailyreport'
+import { IotDailyReportAttrsApi } from '@/api/pms/iotdailyreportattrs'
 import * as DeptApi from '@/api/system/dept'
 import { useUserStore } from '@/store/modules/user'
 import dayjs from 'dayjs'
@@ -232,10 +291,8 @@ const id = params.id // 瑞都日报id
 // 日报数据
 const dailyReportData = ref<any>({})
 
-// 施工工艺相关变量
-const technologyOptions = ref<any[]>([])
-const loadingTechnologyOptions = ref(false)
-const currentTechnologyDictLabel = ref(''); // 存储当前项目对应的施工工艺字典类型
+// 动态属性相关变量
+const dynamicAttrs = ref<any[]>([]) // 存储动态属性列表
 
 // 表单数据
 const formData = ref({
@@ -259,7 +316,10 @@ const formData = ref({
   techniqueIds: [], // 施工工艺
   productionStatus: '', // 当日生产动态
   nextPlan: '', // 下步工作计划
-  externalRental: '' // 外租设备
+  externalRental: '', // 外租设备
+
+  // 添加动态字段对象
+  dynamicFields: {} as Record<string, any>
 })
 
 // 表单验证规则
@@ -270,6 +330,11 @@ const formRules = reactive({
   productionStatus: [{ required: true, message: '当日生产动态不能为空', trigger: 'blur' }]
 })
 
+const queryParams = reactive({
+  deptId: undefined,
+  techniqueIds: [],
+})
+
 // 下拉选项
 const rdStatusOptions = getStrDictOptions(DICT_TYPE.PMS_PROJECT_RD_STATUS)   // 施工状态
 const techniqueOptions = getStrDictOptions(DICT_TYPE.PMS_PROJECT_RD_TECHNOLOGY) // 瑞都施工工艺
@@ -326,6 +391,13 @@ const submitForm = async () => {
     formData.value.endTime = endDate.format('HH:mm:ss')
   }
 
+  // 准备提交数据,包含动态字段
+  const submitData = {
+    ...formData.value,
+    // 将动态字段合并到提交数据中或单独处理,根据后端接口需求调整
+    dynamicFields: formData.value.dynamicFields
+  }
+
   // 提交请求
   formLoading.value = true
   try {
@@ -347,6 +419,143 @@ const resetForm = () => {
   formRef.value?.resetFields()
 }
 
+// 初始化动态属性
+const initDynamicAttrs = (reportData: any) => {
+  if (reportData.dailyReportAttrs && reportData.dailyReportAttrs.length > 0) {
+    dynamicAttrs.value = reportData.dailyReportAttrs
+
+    // 初始化动态字段的值
+    const initialDynamicFields: Record<string, any> = {}
+    reportData.dailyReportAttrs.forEach((attr: any) => {
+      // 优先使用实际值,如果没有则使用默认值
+      const value = (attr.extProperty && attr.extProperty.actualValue !== undefined &&
+        attr.extProperty.actualValue !== null && attr.extProperty.actualValue !== '')
+        ? attr.extProperty.actualValue
+        : (attr.defaultValue || (attr.extProperty?.defaultValue || ''))
+
+      initialDynamicFields[attr.identifier] = value
+    })
+
+    formData.value.dynamicFields = initialDynamicFields
+  }
+}
+
+// 获取动态字段的验证规则
+const getDynamicAttrRules = (attr: any) => {
+  const rules = []
+  if (attr.required === 1) {
+    rules.push({
+      required: true,
+      message: `${attr.name}不能为空`,
+      trigger: 'blur'
+    })
+  }
+
+  // 数字类型验证
+  if (attr.dataType === 'double') {
+    rules.push({
+      validator: (rule: any, value: any, callback: any) => {
+        if (value === '' || value === null || value === undefined) {
+          callback()
+          return
+        }
+
+        const numValue = Number(value)
+        if (isNaN(numValue)) {
+          callback(new Error(`${attr.name}必须是数字`))
+        } else if (attr.minValue && numValue < Number(attr.minValue)) {
+          callback(new Error(`${attr.name}不能小于${attr.minValue}`))
+        } else if (attr.maxValue && numValue > Number(attr.maxValue)) {
+          callback(new Error(`${attr.name}不能大于${attr.maxValue}`))
+        } else {
+          callback()
+        }
+      },
+      trigger: 'blur'
+    })
+  }
+
+  return rules
+}
+
+// 更新动态属性(处理交集、新增和删除)
+const updateDynamicAttrs = async (newAttrs: any[], newTechniqueIds: string[], oldTechniqueIds?: string[]) => {
+  const oldAttrs = [...dynamicAttrs.value]
+  const oldDynamicFields = { ...formData.value.dynamicFields }
+
+  // 计算需要保留的字段(交集)
+  const commonAttrs = oldAttrs.filter(oldAttr =>
+    newAttrs.some(newAttr => newAttr.identifier === oldAttr.identifier)
+  )
+
+  // 计算需要新增的字段
+  const addedAttrs = newAttrs.filter(newAttr =>
+    !oldAttrs.some(oldAttr => oldAttr.identifier === newAttr.identifier)
+  )
+
+  // 计算需要删除的字段
+  const removedAttrs = oldAttrs.filter(oldAttr =>
+    !newAttrs.some(newAttr => newAttr.identifier === oldAttr.identifier)
+  )
+
+  // 构建新的动态属性数组
+  const updatedAttrs = [...commonAttrs, ...addedAttrs]
+
+  // 构建新的动态字段对象
+  const updatedDynamicFields = { ...oldDynamicFields }
+
+  // 移除已删除的字段
+  removedAttrs.forEach(attr => {
+    delete updatedDynamicFields[attr.identifier]
+  })
+
+  // 初始化新增字段的值
+  addedAttrs.forEach(attr => {
+    if (!updatedDynamicFields[attr.identifier]) {
+      // 如果有默认值使用默认值,否则为空
+      updatedDynamicFields[attr.identifier] = attr.defaultValue ||
+        (attr.extProperty?.defaultValue || '')
+    }
+  })
+
+  // 更新响应式数据
+  dynamicAttrs.value = updatedAttrs
+  formData.value.dynamicFields = updatedDynamicFields
+}
+
+// 加载动态属性
+const loadDynamicAttrs = async (newTechniqueIds: string[], oldTechniqueIds?: string[]) => {
+  try {
+    formLoading.value = true
+
+    const queryParams = {
+      techniqueIds: newTechniqueIds.join(',')
+    }
+
+    const response = await IotDailyReportAttrsApi.dailyReportAttrs(queryParams)
+    const newAttrs = response || []
+
+    // 处理动态属性更新
+    await updateDynamicAttrs(newAttrs, newTechniqueIds, oldTechniqueIds)
+
+  } catch (error) {
+    console.error('加载动态属性失败:', error)
+    message.error('加载动态属性失败')
+  } finally {
+    formLoading.value = false
+  }
+}
+
+// 监听施工工艺变化
+watch(() => formData.value.techniqueIds, async (newTechniqueIds, oldTechniqueIds) => {
+  if (newTechniqueIds && newTechniqueIds.length > 0) {
+    await loadDynamicAttrs(newTechniqueIds, oldTechniqueIds)
+  } else {
+    dynamicAttrs.value = []
+    formData.value.dynamicFields = {}
+  }
+}, { deep: true })
+
 // 初始化表单数据
 const initFormData = (reportData: any) => {
   formData.value = {
@@ -360,9 +569,10 @@ const initFormData = (reportData: any) => {
     externalRental: reportData.externalRental || '',
     startTime: reportData.startTime || undefined,
     endTime: reportData.endTime || undefined,
-    companyId: reportData.companyId || ''
+    companyId: reportData.companyId || '',
+    dynamicFields: {} // 确保有初始值
   }
-
+  queryParams.deptId = reportData.companyId
   // 设置时间范围选择器
   if (reportData.startTime && reportData.startTime[0] && reportData.endTime && reportData.endTime[0]) {
     formData.value.timeRange = [
@@ -370,7 +580,8 @@ const initFormData = (reportData: any) => {
       new Date(reportData.endTime[0])
     ]
   }
-
+  // 初始化动态属性
+  initDynamicAttrs(reportData)
 }
 
 onMounted(async () => {