xzc 5 napja
szülő
commit
ecdd66aca3

+ 179 - 59
yudao-ui-admin-vue3/src/views/pressure2/boilerReportPreparationList/BoilerReportList.vue

@@ -1,46 +1,89 @@
 <template>
-  <div class="report-list-container">
-    <span
-      v-for="item in row.reportDOList"
-      :key="item?.id"
-      class="report-item"
+  <div>
+    <el-tooltip
+      placement="top"
+      effect="light"
+      popper-class="report-list-tooltip"
+      :disabled="isExpanded"
     >
-      <el-icon v-if="item?.recheckStatus === 300"
-               class="warning-icon" size="16"
+      <template #content>
+        <div class="tooltip-report-list">
+          <div
+            v-for="item in row.reportDOList"
+            :key="item?.id"
+            class="tooltip-report-item"
+            @click="handleClick(row, item)"
+          >
+            <span
+              class="tooltip-dot"
+              :style="{ backgroundColor: getStatusColor(item.taskStatus) }"
+            ></span>
+            <span class="tooltip-name">{{ getReportName(item) }}</span>
+            <span v-if="item?.fee" class="tooltip-fee">({{ item?.fee }})</span>
+          </div>
+        </div>
+      </template>
+      <div
+        ref="containerRef"
+        :class="['report-list-container', { expanded: isExpanded }]"
       >
-        <WarningFilled/>
-      </el-icon>
-      <span v-else
-            class="color-dot"
-            :style="{ backgroundColor: getStatusColor(item.taskStatus) }"
-      ></span>
-      <span
-        class="report-name"
-        :style="{ color: getStatusColor(item.taskStatus) }"
-        @click="() => handleClick(row, item)"
-      >
-        {{ getReportName(item) }}
-      </span>
-      <span
-        v-if="item?.fee"
-        class="report-fee"
-        :style="{ color: getStatusColor(item.taskStatus) }"
+        <span
+          v-for="item in row.reportDOList"
+          :key="item?.id"
+          class="report-item"
+        >
+          <el-icon v-if="item?.recheckStatus === 300"
+                   class="warning-icon" size="16"
+          >
+            <WarningFilled/>
+          </el-icon>
+          <span v-else
+                class="color-dot"
+                :style="{ backgroundColor: getStatusColor(item.taskStatus) }"
+          ></span>
+          <span
+            class="report-name"
+            :style="{ color: getStatusColor(item.taskStatus) }"
+            @click="() => handleClick(row, item)"
+          >
+            {{ getReportName(item) }}
+          </span>
+          <span
+            v-if="item?.fee"
+            class="report-fee"
+            :style="{ color: getStatusColor(item.taskStatus) }"
+          >
+            ({{ item?.fee }})
+          </span>
+        </span>
+      </div>
+    </el-tooltip>
+    <div
+      v-if="isOverflow || isExpanded"
+      class="expand-toggle"
+      @click="isExpanded = !isExpanded"
+    >
+      <span>{{ isExpanded ? '收起' : '全部展开' }}</span>
+      <el-icon
+        :style="{
+          transition: 'transform 0.3s',
+          transform: isExpanded ? 'rotate(180deg)' : 'rotate(0deg)'
+        }"
       >
-        ({{ item?.fee }})
-      </span>
-    </span>
+        <ArrowDown />
+      </el-icon>
+    </div>
   </div>
 </template>
 
 <script setup lang="ts">
+import { ref, onMounted, nextTick, onUpdated } from 'vue'
 import { DICT_TYPE, getStrDictOptions } from '@/utils/dict'
-import {useRouter} from "vue-router";
-import { WarningFilled } from '@element-plus/icons-vue'
-import {
-  PressureTaskOrderTaskStatus
-} from '@/utils/constants'
-import {useUserStore} from "@/store/modules/user";
-import {BoilerTaskOrderApi} from "@/api/pressure2/boilertaskorder";
+import { useRouter } from 'vue-router'
+import { WarningFilled, ArrowDown } from '@element-plus/icons-vue'
+import { PressureTaskOrderTaskStatus } from '@/utils/constants'
+import { useUserStore } from '@/store/modules/user'
+import { BoilerTaskOrderApi } from '@/api/pressure2/boilertaskorder'
 
 interface ReportItem {
   id: string
@@ -56,6 +99,16 @@ const props = defineProps<{
   row
 }>()
 
+const containerRef = ref<HTMLElement>()
+const isOverflow = ref(false)
+const isExpanded = ref(false)
+
+const checkOverflow = () => {
+  if (containerRef.value) {
+    isOverflow.value = containerRef.value.scrollHeight > containerRef.value.clientHeight + 1
+  }
+}
+
 const PartTypeList = getStrDictOptions(DICT_TYPE.PRESSURE2_BOILER_PART_TYPE)
 const userStore = useUserStore()
 const getTypeName = (item) => {
@@ -72,13 +125,13 @@ const getReportName = (item: ReportItem) => {
 
 const getStatusColor = (status: number): string => {
   const statusMap: Record<number, string> = {
-    100: '#5B9BD5',  // 待录入
-    400: '#70AD47',  // 记录录入
-    500: '#9973C2',  // 记录校核
-    520: '#FFC000',  // 报告编制
-    600: '#ED7D31',  // 报告审核
-    700: '#FF8DC7',  // 报告审批
-    800: '#303133'   // 报告办结
+    100: '#5B9BD5',
+    400: '#70AD47',
+    500: '#9973C2',
+    520: '#FFC000',
+    600: '#ED7D31',
+    700: '#FF8DC7',
+    800: '#303133'
   }
   return statusMap[status] || '#A7D78B'
 }
@@ -88,19 +141,17 @@ const handleClick = async (row, item: ReportItem) => {
     return
   }
 
-  if (!canCheckInput(row)){
+  if (!canCheckInput(row)) {
     return
   }
 
-  // 校验是否有完成审核审批的检验方案
   const res = await BoilerTaskOrderApi.checkSchemeStatus(row.id)
   if (!res) {
     ElMessage.warning('请先完成检验方案的审核审批')
     return
   }
 
-  //判断报告编制时是否有结束检验日期
-  if (row.taskStatus >= PressureTaskOrderTaskStatus.REPORT_INPUT){
+  if (row.taskStatus >= PressureTaskOrderTaskStatus.REPORT_INPUT) {
     if (!row.endCheckDate) {
       ElMessage.error('请添加结束检验时间再进行编制!')
       return
@@ -110,53 +161,63 @@ const handleClick = async (row, item: ReportItem) => {
   localStorage.setItem('activeBoilerDetailItemId', item.id)
   router.push({
     name: 'BoilerCheckerTaskDetail',
-    query: {id: row.id, type: 'BoilerMyTask'},
+    query: { id: row.id, type: 'BoilerMyTask' }
   })
 }
 
-// 判断是否可以检验录入:当前用户是检验员或主检人
+onMounted(() => {
+  nextTick(() => {
+    setTimeout(checkOverflow, 100)
+  })
+})
+
+onUpdated(() => {
+  nextTick(checkOverflow)
+})
+
 const canCheckInput = (row: PipeTaskOrderOrderItemVO) => {
   const userId = userStore.user.id
-  // 检查是否是主检人
   if (row.mainCheckerUser && row.mainCheckerUser.id === userId) {
     return true
   }
-  // 检查是否是检验员
   if (row.checkUsers && row.checkUsers.length > 0) {
     return row.checkUsers.some(user => user.id === userId)
   }
   return false
 }
-
 </script>
 
 <style lang="scss" scoped>
 .report-list-container {
-  display: inline;
+  display: block;
   line-height: 1.8;
+  overflow: hidden;
+  max-height: 5.4em;
+
+  &.expanded {
+    max-height: none;
+  }
 }
 
 .report-item {
-  display: inline-flex;
-  align-items: center;
+  display: inline-block;
   white-space: nowrap;
   margin-right: 12px;
+  vertical-align: top;
 
   .color-dot {
-    display: inline-flex;
-    align-items: center;
-    justify-content: center;
+    display: inline-block;
     width: 8px;
     height: 8px;
     border-radius: 50%;
+    vertical-align: middle;
     margin-right: 4px;
   }
 
   .warning-icon {
     color: lightcoral;
-    display: inline-flex;
-    align-items: center;
-    justify-content: center;
+    display: inline-block;
+    vertical-align: middle;
     margin-right: 4px;
   }
 
@@ -174,4 +235,63 @@ const canCheckInput = (row: PipeTaskOrderOrderItemVO) => {
     margin-left: 2px;
   }
 }
+
+.expand-toggle {
+  display: inline-flex;
+  align-items: center;
+  gap: 2px;
+  color: #409eff;
+  font-size: 12px;
+  cursor: pointer;
+  user-select: none;
+  margin-top: 2px;
+
+  &:hover {
+    color: #66b1ff;
+  }
+}
+</style>
+
+<style lang="scss">
+.report-list-tooltip {
+  max-width: 400px !important;
+  padding: 12px 16px !important;
+}
+
+.tooltip-report-list {
+  max-height: 300px;
+  overflow-y: auto;
+}
+
+.tooltip-report-item {
+  display: flex;
+  align-items: center;
+  line-height: 2;
+  white-space: nowrap;
+  cursor: pointer;
+  padding: 2px 4px;
+  border-radius: 4px;
+
+  &:hover {
+    background-color: #f5f7fa;
+  }
+}
+
+.tooltip-dot {
+  display: inline-block;
+  width: 8px;
+  height: 8px;
+  border-radius: 50%;
+  margin-right: 8px;
+  flex-shrink: 0;
+}
+
+.tooltip-name {
+  color: #303133;
+}
+
+.tooltip-fee {
+  color: #909399;
+  margin-left: 4px;
+}
 </style>

+ 179 - 59
yudao-ui-admin-vue3/src/views/pressure2/pipeReportPreparationList/PipeReportList.vue

@@ -1,46 +1,89 @@
 <template>
-  <div class="report-list-container">
-    <span
-      v-for="item in row.reportDOList"
-      :key="item?.id"
-      class="report-item"
+  <div>
+    <el-tooltip
+      placement="top"
+      effect="light"
+      popper-class="report-list-tooltip"
+      :disabled="isExpanded"
     >
-      <el-icon v-if="item?.recheckStatus === 300"
-               class="warning-icon" size="16"
+      <template #content>
+        <div class="tooltip-report-list">
+          <div
+            v-for="item in row.reportDOList"
+            :key="item?.id"
+            class="tooltip-report-item"
+            @click="handleClick(row, item)"
+          >
+            <span
+              class="tooltip-dot"
+              :style="{ backgroundColor: getStatusColor(item.taskStatus) }"
+            ></span>
+            <span class="tooltip-name">{{ getReportName(item) }}</span>
+            <span v-if="item?.fee" class="tooltip-fee">({{ item?.fee }})</span>
+          </div>
+        </div>
+      </template>
+      <div
+        ref="containerRef"
+        :class="['report-list-container', { expanded: isExpanded }]"
       >
-        <WarningFilled/>
-      </el-icon>
-      <span v-else
-         class="color-dot"
-         :style="{ backgroundColor: getStatusColor(item.taskStatus) }"
-      ></span>
-      <span
-        class="report-name"
-        :style="{ color: getStatusColor(item.taskStatus) }"
-        @click="() => handleClick(row, item)"
-      >
-        {{ getReportName(item) }}
-      </span>
-      <span
-        v-if="item?.fee"
-        class="report-fee"
-        :style="{ color: getStatusColor(item.taskStatus) }"
+        <span
+          v-for="item in row.reportDOList"
+          :key="item?.id"
+          class="report-item"
+        >
+          <el-icon v-if="item?.recheckStatus === 300"
+                   class="warning-icon" size="16"
+          >
+            <WarningFilled/>
+          </el-icon>
+          <span v-else
+             class="color-dot"
+             :style="{ backgroundColor: getStatusColor(item.taskStatus) }"
+          ></span>
+          <span
+            class="report-name"
+            :style="{ color: getStatusColor(item.taskStatus) }"
+            @click="() => handleClick(row, item)"
+          >
+            {{ getReportName(item) }}
+          </span>
+          <span
+            v-if="item?.fee"
+            class="report-fee"
+            :style="{ color: getStatusColor(item.taskStatus) }"
+          >
+            ({{ item?.fee }})
+          </span>
+        </span>
+      </div>
+    </el-tooltip>
+    <div
+      v-if="isOverflow || isExpanded"
+      class="expand-toggle"
+      @click="isExpanded = !isExpanded"
+    >
+      <span>{{ isExpanded ? '收起' : '全部展开' }}</span>
+      <el-icon
+        :style="{
+          transition: 'transform 0.3s',
+          transform: isExpanded ? 'rotate(180deg)' : 'rotate(0deg)'
+        }"
       >
-        ({{ item?.fee }})
-      </span>
-    </span>
+        <ArrowDown />
+      </el-icon>
+    </div>
   </div>
 </template>
 
 <script setup lang="ts">
+import { ref, onMounted, nextTick, onUpdated } from 'vue'
 import { DICT_TYPE, getStrDictOptions } from '@/utils/dict'
-import {useRouter} from "vue-router";
-import { WarningFilled } from '@element-plus/icons-vue'
-import {
-  PressureTaskOrderTaskStatus
-} from '@/utils/constants'
-import {PipeTaskOrderApi, PipeTaskOrderOrderItemVO} from "@/api/pressure2/pipetaskorder";
-import {useUserStore} from "@/store/modules/user";
+import { useRouter } from 'vue-router'
+import { WarningFilled, ArrowDown } from '@element-plus/icons-vue'
+import { PressureTaskOrderTaskStatus } from '@/utils/constants'
+import { PipeTaskOrderApi, PipeTaskOrderOrderItemVO } from '@/api/pressure2/pipetaskorder'
+import { useUserStore } from '@/store/modules/user'
 
 interface ReportItem {
   id: string
@@ -56,6 +99,16 @@ const props = defineProps<{
   row
 }>()
 
+const containerRef = ref<HTMLElement>()
+const isOverflow = ref(false)
+const isExpanded = ref(false)
+
+const checkOverflow = () => {
+  if (containerRef.value) {
+    isOverflow.value = containerRef.value.scrollHeight > containerRef.value.clientHeight + 1
+  }
+}
+
 const PartTypeList = getStrDictOptions(DICT_TYPE.PRESSURE2_BOILER_PART_TYPE)
 const userStore = useUserStore()
 const getTypeName = (type: string) => {
@@ -72,13 +125,13 @@ const getReportName = (item: ReportItem) => {
 
 const getStatusColor = (status: number): string => {
   const statusMap: Record<number, string> = {
-    100: '#5B9BD5',  // 待录入
-    400: '#70AD47',  // 记录录入
-    500: '#9973C2',  // 记录校核
-    520: '#FFC000',  // 报告编制
-    600: '#ED7D31',  // 报告审核
-    700: '#FF8DC7',  // 报告审批
-    800: '#303133'   // 报告办结
+    100: '#5B9BD5',
+    400: '#70AD47',
+    500: '#9973C2',
+    520: '#FFC000',
+    600: '#ED7D31',
+    700: '#FF8DC7',
+    800: '#303133'
   }
   return statusMap[status] || '#A7D78B'
 }
@@ -88,19 +141,17 @@ const handleClick = async (row, item: ReportItem) => {
     return
   }
 
-  if (!canCheckInput(row)){
+  if (!canCheckInput(row)) {
     return
   }
 
-  // 校验是否有完成审核审批的检验方案
   const res = await PipeTaskOrderApi.checkSchemeStatus(row.orderId)
   if (!res) {
     ElMessage.warning('请先完成检验方案的审核审批')
     return
   }
 
-  //判断报告编制时是否有结束检验日期
-  if (row.taskStatus >= PressureTaskOrderTaskStatus.REPORT_INPUT){
+  if (row.taskStatus >= PressureTaskOrderTaskStatus.REPORT_INPUT) {
     if (!row.endCheckDate) {
       ElMessage.error('请添加结束检验时间再进行编制!')
       return
@@ -110,53 +161,63 @@ const handleClick = async (row, item: ReportItem) => {
   localStorage.setItem('activePipeDetailItemId', item.id)
   router.push({
     name: 'PipeCheckerTaskDetail',
-    query: {id: row.id, type: 'PipeMyTask'},
+    query: { id: row.id, type: 'PipeMyTask' }
   })
 }
 
-// 判断是否可以检验录入:当前用户是检验员或主检人
+onMounted(() => {
+  nextTick(() => {
+    setTimeout(checkOverflow, 100)
+  })
+})
+
+onUpdated(() => {
+  nextTick(checkOverflow)
+})
+
 const canCheckInput = (row: PipeTaskOrderOrderItemVO) => {
   const userId = userStore.user.id
-  // 检查是否是主检人
   if (row.mainCheckerUser && row.mainCheckerUser.id === userId) {
     return true
   }
-  // 检查是否是检验员
   if (row.checkUsers && row.checkUsers.length > 0) {
     return row.checkUsers.some(user => user.id === userId)
   }
   return false
 }
-
 </script>
 
 <style lang="scss" scoped>
 .report-list-container {
-  display: inline;
+  display: block;
   line-height: 1.8;
+  overflow: hidden;
+  max-height: 5.4em;
+
+  &.expanded {
+    max-height: none;
+  }
 }
 
 .report-item {
-  display: inline-flex;
-  align-items: center;
+  display: inline-block;
   white-space: nowrap;
   margin-right: 12px;
+  vertical-align: top;
 
   .color-dot {
-    display: inline-flex;
-    align-items: center;
-    justify-content: center;
+    display: inline-block;
     width: 8px;
     height: 8px;
     border-radius: 50%;
+    vertical-align: middle;
     margin-right: 4px;
   }
 
   .warning-icon {
     color: lightcoral;
-    display: inline-flex;
-    align-items: center;
-    justify-content: center;
+    display: inline-block;
+    vertical-align: middle;
     margin-right: 4px;
   }
 
@@ -174,4 +235,63 @@ const canCheckInput = (row: PipeTaskOrderOrderItemVO) => {
     margin-left: 2px;
   }
 }
+
+.expand-toggle {
+  display: inline-flex;
+  align-items: center;
+  gap: 2px;
+  color: #409eff;
+  font-size: 12px;
+  cursor: pointer;
+  user-select: none;
+  margin-top: 2px;
+
+  &:hover {
+    color: #66b1ff;
+  }
+}
+</style>
+
+<style lang="scss">
+.report-list-tooltip {
+  max-width: 400px !important;
+  padding: 12px 16px !important;
+}
+
+.tooltip-report-list {
+  max-height: 300px;
+  overflow-y: auto;
+}
+
+.tooltip-report-item {
+  display: flex;
+  align-items: center;
+  line-height: 2;
+  white-space: nowrap;
+  cursor: pointer;
+  padding: 2px 4px;
+  border-radius: 4px;
+
+  &:hover {
+    background-color: #f5f7fa;
+  }
+}
+
+.tooltip-dot {
+  display: inline-block;
+  width: 8px;
+  height: 8px;
+  border-radius: 50%;
+  margin-right: 8px;
+  flex-shrink: 0;
+}
+
+.tooltip-name {
+  color: #303133;
+}
+
+.tooltip-fee {
+  color: #909399;
+  margin-left: 4px;
+}
 </style>