yanghao 16 ore fa
parent
commit
c3e736f1f4

+ 55 - 43
src/views/pms/iotprojectinfo/index.vue

@@ -33,7 +33,7 @@
           class="!w-240px"
         />
       </el-form-item> -->
-      <el-form-item label="合同名称" prop="contractName">
+      <el-form-item label="合同名称" prop="contractName" :width="columnWidths.contractName">
         <el-input
           v-model="queryParams.contractName"
           placeholder="请输入合同名称"
@@ -42,7 +42,7 @@
           class="!w-240px"
         />
       </el-form-item>
-      <el-form-item label="合同编号" prop="contractCode">
+      <el-form-item label="合同编号" prop="contractCode" :width="columnWidths.contractCode">
         <el-input
           v-model="queryParams.contractCode"
           placeholder="请输入合同编号"
@@ -91,6 +91,7 @@
         :stripe="true"
         style="width: 100%"
         :cell-style="{ padding: '5px' }"
+        :show-overflow-tooltip="true"
       >
         <el-table-column
           :label="t('iotDevice.serial')"
@@ -107,7 +108,7 @@
           align="left"
           prop="manufactureName"
           :show-overflow-tooltip="true"
-          width="200px"
+          :min-width="columnWidths.manufactureName"
           class-name="manufacture-name-column"
         />
         <el-table-column
@@ -116,7 +117,7 @@
           prop="contractName"
           class-name="contract-name-column"
           :show-overflow-tooltip="true"
-          width="200px"
+          :min-width="columnWidths.contractName"
         >
           <template #default="scope">
             <el-link type="primary" @click="showTaskList(scope.row)">
@@ -128,7 +129,7 @@
           label="合同编号"
           align="center"
           prop="contractCode"
-          :width="columnWidths.contractCode"
+          :min-width="columnWidths.contractCode"
         />
         <!--
         <el-table-column label="总工作量" align="center" prop="workloadTotal" :width="columnWidths.workloadTotal" />
@@ -138,20 +139,20 @@
           align="center"
           prop="startTime"
           :formatter="dateFormatter2"
-          :width="columnWidths.startTime"
+          :min-width="columnWidths.startTime"
         />
         <el-table-column
           label="合同完成时间"
           align="center"
           prop="endTime"
           :formatter="dateFormatter2"
-          :width="columnWidths.endTime"
+          :min-width="columnWidths.endTime"
         />
         <el-table-column
           :label="t('project.payment')"
           align="center"
           prop="payment"
-          :width="columnWidths.payment"
+          :min-width="columnWidths.payment"
         >
           <template #default="scope">
             <dict-tag :type="DICT_TYPE.PMS_PROJECT_SETTLEMENT" :value="scope.row.payment" />
@@ -162,9 +163,14 @@
           align="center"
           prop="createTime"
           :formatter="dateFormatter"
-          :width="columnWidths.createTime"
+          :min-width="columnWidths.createTime"
         />
-        <el-table-column label="操作" align="center" :width="columnWidths.operation" fixed="right">
+        <el-table-column
+          label="操作"
+          align="center"
+          :min-width="columnWidths.operation"
+          fixed="right"
+        >
           <template #default="scope">
             <el-button
               link
@@ -519,6 +525,11 @@ const calculateColumnWidths = () => {
     const minWidth = Math.max(headerWidth, contentMaxWidth, MIN_WIDTH) + PADDING
     minWidths[key] = minWidth
     totalMinWidth += minWidth
+
+    if (key === 'contractCode') {
+      console.log('minWidth', minWidth)
+    }
+
     return minWidth
   }
 
@@ -528,7 +539,8 @@ const calculateColumnWidths = () => {
     t('iotDevice.serial'),
     (row: any, index: number) => `${index + 1}`
   )
-  // calculateColumnMinWidth('manufactureName', '客户名称', (row: any) => row.manufactureName);
+  calculateColumnMinWidth('manufactureName', '客户名称', (row: any) => row.manufactureName)
+  calculateColumnMinWidth('contractName', '合同名称', (row: any) => row.contractName)
   // 合同名称列:直接固定宽度,不参与动态计算
   calculateColumnMinWidth('contractCode', '合同编号', (row: any) => row.contractCode)
   calculateColumnMinWidth('workloadTotal', '总工作量', (row: any) => row.workloadTotal)
@@ -568,16 +580,16 @@ const calculateColumnWidths = () => {
   newWidths.contractName = '200px'
 
   // 计算可伸缩列需要的宽度
-  if (totalMinWidth < availableWidth) {
-    // 有剩余空间:按比例分配给可伸缩列
-    const extraSpace = availableWidth - totalMinWidth
-    const flexibleColumnCount = FLEXIBLE_COLUMNS.length
-    const spacePerColumn = Math.floor(extraSpace / flexibleColumnCount)
-
-    FLEXIBLE_COLUMNS.forEach((key) => {
-      newWidths[key] = `${minWidths[key] + spacePerColumn}px`
-    })
-  }
+  // if (totalMinWidth < availableWidth) {
+  //   // 有剩余空间:按比例分配给可伸缩列
+  //   const extraSpace = availableWidth - totalMinWidth
+  //   const flexibleColumnCount = FLEXIBLE_COLUMNS.length
+  //   const spacePerColumn = Math.floor(extraSpace / flexibleColumnCount)
+
+  //   FLEXIBLE_COLUMNS.forEach((key) => {
+  //     newWidths[key] = `${minWidths[key] + spacePerColumn}px`
+  //   })
+  // }
 
   // 3. 更新列宽配置
   columnWidths.value = newWidths
@@ -1074,32 +1086,32 @@ watch(
 }
 
 .close-btn {
-  padding: 0;
   min-height: auto;
+  padding: 0;
 }
 
 .dept-names {
-  white-space: nowrap;
+  display: inline-block;
+  max-width: 120px;
   overflow: hidden;
   text-overflow: ellipsis;
-  max-width: 120px;
-  display: inline-block;
+  white-space: nowrap;
 }
 
 .device-names {
-  white-space: nowrap;
+  display: inline-block;
+  max-width: 120px;
   overflow: hidden;
   text-overflow: ellipsis;
-  max-width: 120px;
-  display: inline-block;
+  white-space: nowrap;
 }
 
 .responsible-names {
-  white-space: nowrap;
+  display: inline-block;
+  max-width: 120px;
   overflow: hidden;
   text-overflow: ellipsis;
-  max-width: 120px;
-  display: inline-block;
+  white-space: nowrap;
 }
 
 :deep(.el-step__description) {
@@ -1112,10 +1124,10 @@ watch(
 
 /* 确保步骤标题完全显示 */
 :deep(.timeline-dialog .el-step__title) {
-  white-space: nowrap;
+  max-width: none;
   overflow: visible;
   text-overflow: clip;
-  max-width: none;
+  white-space: nowrap;
 }
 
 /* 调整步骤容器的布局 */
@@ -1159,24 +1171,24 @@ watch(
 }
 
 .progress-section {
-  border: 1px solid #e6e6e6;
-  border-radius: 8px;
   padding: 16px;
   background-color: #fafafa;
+  border: 1px solid #e6e6e6;
+  border-radius: 8px;
 }
 
 .progress-section:first-child {
-  border-color: #409eff;
   background-color: #f0f7ff;
+  border-color: #409eff;
 }
 
 .progress-section:last-child {
-  border-color: #67c23a;
   background-color: #f0f9eb;
+  border-color: #67c23a;
 }
 
 .progress-title {
-  margin: 0 0 16px 0;
+  margin: 0 0 16px;
   font-size: 16px;
   font-weight: bold;
   color: #606266;
@@ -1197,15 +1209,15 @@ watch(
 
 :deep(.progress-section .el-empty__description) {
   margin-top: 8px;
-  color: #909399;
   font-size: 14px;
+  color: #909399;
 }
 
 /* 核心:强制合同名称列的th/td固定宽度+溢出隐藏,确保省略号生效 */
 :deep(.contract-name-column) {
   width: 200px !important; /* 与脚本中固定宽度一致 */
-  min-width: 200px !important;
   max-width: 200px !important;
+  min-width: 200px !important;
 }
 
 /* 覆盖全局的 overflow: visible,强制单元格溢出隐藏 */
@@ -1215,19 +1227,19 @@ watch(
 
 /* 合同名称单元格:溢出显示省略号(原有样式保留,增加优先级) */
 :deep(.contract-name-column .cell) {
+  display: block !important; /* 添加此属性确保省略号生效 */
+  width: 100% !important;
   overflow: hidden !important;
   text-overflow: ellipsis !important;
   white-space: nowrap !important;
-  width: 100% !important;
-  display: block !important; /* 添加此属性确保省略号生效 */
 }
 
 /* 确保合同名称链接也遵守溢出规则 */
 :deep(.contract-name-column .el-link) {
   display: block !important;
+  width: 100% !important;
   overflow: hidden !important;
   text-overflow: ellipsis !important;
   white-space: nowrap !important;
-  width: 100% !important;
 }
 </style>

+ 68 - 7
src/views/pms/iotrddailyreport/create-rd-form.vue

@@ -7,6 +7,7 @@ import { getStrDictOptions } from '@/utils/dict'
 import * as DeptApi from '@/api/system/dept'
 import { IotRdDailyReportApi } from '@/api/pms/iotrddailyreport'
 import { formatT } from '@/utils/formatTime'
+import { defaultProps, handleTree } from '@/utils/tree'
 
 const user = useUserStore().getUser
 
@@ -53,6 +54,8 @@ interface Form {
   externalRental: string
   malfunction: string
   otherNptReason: string
+  createTime: number
+  constructionBrief: string
   [key: (typeof NON_PROD_FIELDS)[number]['key']]: any
 }
 
@@ -99,6 +102,9 @@ function handleRowValidate(key: string) {
 }
 
 const rules: FormRules = {
+  deptId: [{ required: true, message: '请选择施工队伍', trigger: ['blur', 'change'] }],
+  createTime: [{ required: true, message: '请选择施工日期', trigger: ['blur', 'change'] }],
+  constructionBrief: [{ required: true, message: '请输入施工简报', trigger: ['blur', 'change'] }],
   timeRange: [
     { required: true, message: '请选择时间节点', trigger: ['blur', 'change'], type: 'array' }
   ],
@@ -120,13 +126,36 @@ interface UserOptions {
 
 const userOptions = ref<UserOptions[]>([])
 
-const deptName = ref('')
+const deptLoading = ref(false)
+const deptOptions = ref<any[]>([])
 
 const submitterNames = ref('')
 
 async function loadDept() {
-  const res = await DeptApi.getDept(deptId)
-  deptName.value = res.name
+  deptLoading.value = true
+  try {
+    function sortTreeBySort(treeNodes: Tree[]) {
+      if (!treeNodes || !Array.isArray(treeNodes)) return treeNodes
+      const sortedNodes = [...treeNodes].sort((a, b) => {
+        const sortA = a.sort != null ? a.sort : 999999
+        const sortB = b.sort != null ? b.sort : 999999
+        return sortA - sortB
+      })
+
+      sortedNodes.forEach((node) => {
+        if (node.children && Array.isArray(node.children)) {
+          node.children = sortTreeBySort(node.children)
+        }
+      })
+      return sortedNodes
+    }
+
+    const depts = await DeptApi.specifiedSimpleDepts(deptId)
+    deptOptions.value = sortTreeBySort(handleTree(depts))
+  } catch (error) {
+  } finally {
+    deptLoading.value = false
+  }
 }
 
 async function loadUserOptions() {
@@ -144,12 +173,12 @@ async function load() {
   loading.value = true
 
   await loadUserOptions()
+  await loadDept()
 
   submitterNames.value = user.nickname
 
   if (props.isview && props.id) {
     const res = await IotRdDailyReportApi.getIotRdDailyReport(props.id)
-    deptName.value = res.deptName
     submitterNames.value = res.submitterNames
     form.value = {
       deptId: res.deptId,
@@ -163,10 +192,10 @@ async function load() {
       externalRental: res.externalRental,
       malfunction: res.malfunction,
       otherNptReason: res.otherNptReason,
+      createTime: res.createTime,
+      constructionBrief: res.constructionBrief,
       ...NON_PROD_FIELDS.reduce((acc, field) => ({ ...acc, [field.key]: res[field.key] }), {})
     }
-  } else {
-    await loadDept()
   }
 
   loading.value = false
@@ -245,7 +274,28 @@ async function submitForm() {
         :disabled="props.isview !== 'create'"
       >
         <div class="grid grid-cols-2 gap-x-8">
-          <el-form-item label="施工队伍">{{ deptName }}</el-form-item>
+          <el-form-item label="施工队伍" prop="deptId">
+            <el-tree-select
+              v-model="form.deptId"
+              :data="deptOptions"
+              :props="defaultProps"
+              check-strictly
+              node-key="id"
+              filterable
+              class="w-full"
+              placeholder="请选择施工队伍"
+            />
+          </el-form-item>
+          <el-form-item label="施工日期" prop="createTime">
+            <el-date-picker
+              v-model="form.createTime"
+              type="datetime"
+              clearable
+              class="w-full!"
+              placeholder="请选择施工日期"
+              value-format="x"
+            />
+          </el-form-item>
           <el-form-item label="施工地点" prop="location">
             <el-input v-model="form.location" clearable placeholder="请输入施工地点" />
           </el-form-item>
@@ -343,6 +393,17 @@ async function submitForm() {
               placeholder="请输入故障情况"
             />
           </el-form-item>
+          <el-form-item class="col-span-2" label="施工简报" prop="constructionBrief">
+            <el-input
+              v-model="form.constructionBrief"
+              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">

+ 9 - 4
src/views/pms/iotrhdailyreport/rh-form.vue

@@ -71,6 +71,7 @@ interface FormOriginal {
   capacity: number
   createTime: number
   opinion: string
+  location: string
 }
 
 type Form = Partial<FormOriginal>
@@ -107,7 +108,8 @@ const FORM_KEYS: (keyof FormOriginal)[] = [
   'relocationTime',
   'winterBreakTime',
   'otherNptTime',
-  'otherNptReason'
+  'otherNptReason',
+  'location'
 ]
 
 const formRef = ref<FormInstance>()
@@ -403,9 +405,9 @@ const handleAudit = async (auditStatus: 20 | 30) => {
         <el-form-item label="项目" prop="contractName"
           ><el-input v-model="form.contractName" disabled
         /></el-form-item>
-        <el-form-item label="任务" prop="taskName"
-          ><el-input v-model="form.taskName" disabled
-        /></el-form-item>
+        <el-form-item label="任务" prop="taskName">
+          <el-input v-model="form.taskName" disabled />
+        </el-form-item>
         <el-form-item label="搬迁安装天数(D)" prop="relocationDays"
           ><el-input v-model="form.relocationDays" disabled
         /></el-form-item>
@@ -451,6 +453,9 @@ const handleAudit = async (auditStatus: 20 | 30) => {
             :disabled="isMainFieldDisabled"
           />
         </el-form-item>
+        <el-form-item class="col-span-2" label="施工区域" prop="location">
+          <el-input v-model="form.location" disabled />
+        </el-form-item>
         <el-form-item class="col-span-2" label="生产动态" prop="productionStatus">
           <el-input
             v-model="form.productionStatus"

+ 6 - 1
src/views/pms/iotrydailyreport/ry-form.vue

@@ -99,6 +99,7 @@ interface FormOriginal {
   auditStatus: number
 
   nextPlan: string
+  location: string
 }
 
 type Form = Partial<FormOriginal>
@@ -146,7 +147,8 @@ const FORM_KEYS: (keyof FormOriginal)[] = [
   'otherNptTime',
   'otherNptReason',
   'auditStatus',
-  'nextPlan'
+  'nextPlan',
+  'location'
 ]
 
 const formRef = ref<FormInstance>()
@@ -560,6 +562,9 @@ const inputCurrentDepth = useDebounceFn(function inputCurrentDepth() {
             :disabled="form.auditStatus !== 20 && form.auditStatus !== 30"
           />
         </el-form-item>
+        <el-form-item label="施工区域" prop="location">
+          <el-input v-model="form.location" disabled />
+        </el-form-item>
         <el-form-item label="施工状态" prop="rigStatus">
           <el-select
             v-model="form.rigStatus"

+ 6 - 1
src/views/pms/iotrydailyreport/ry-xj-form.vue

@@ -94,6 +94,7 @@ interface FormOriginal {
   opinion: string
 
   auditStatus: number
+  location: string
 }
 
 type Form = Partial<FormOriginal>
@@ -139,7 +140,8 @@ const FORM_KEYS: (keyof FormOriginal)[] = [
   'winterBreakTime',
   'otherNptTime',
   'otherNptReason',
-  'auditStatus'
+  'auditStatus',
+  'location'
 ]
 
 const formRef = ref<FormInstance>()
@@ -522,6 +524,9 @@ const orange = computed(() => {
             :disabled="form.auditStatus !== 20 && form.auditStatus !== 30"
           />
         </el-form-item>
+        <el-form-item label="施工区域" prop="location">
+          <el-input v-model="form.location" disabled />
+        </el-form-item>
         <el-form-item :label="t('project.status')" prop="repairStatus">
           <el-select
             v-model="form.repairStatus"