yanghao 2 日 前
コミット
63d5c62e1c

BIN
src/assets/imgs/leftTree-hide.png


BIN
src/assets/imgs/leftTree-show.png


+ 5 - 62
src/views/pms/iotmainworkorder/index.vue

@@ -2,32 +2,19 @@
   <el-row :gutter="20">
     <el-col
       :class="{ leftcontent: true, collapsed: isLeftContentCollapsed }"
-      :span="isLeftContentCollapsed ? 0 : 4"
+      :span="isLeftContentCollapsed ? 1 : 4"
       :xs="24"
     >
       <ContentWrap class="h-1/1">
-        <DeptTree @node-click="handleDeptNodeClick" />
+        <DeptTree v-model:collapsed="isLeftContentCollapsed" @node-click="handleDeptNodeClick" />
       </ContentWrap>
     </el-col>
     <el-col
       class="rightcontent"
-      :span="isLeftContentCollapsed ? 24 : 20"
+      :span="isLeftContentCollapsed ? 23 : 20"
       :xs="24"
       style="position: relative; height: 100vh"
     >
-      <div
-        class="toggle-button"
-        :style="{ left: isLeftContentCollapsed ? '0px' : '-13px' }"
-        @click="toggleLeftContent"
-        @mouseover="handleMouseOver"
-        @mouseout="handleMouseOut"
-        :title="hoverText"
-      >
-        <span
-          style="font-size: 5px"
-          :class="{ triangle: true, rotated: isLeftContentCollapsed }"
-        ></span>
-      </div>
       <ContentWrap>
         <!-- 搜索工作栏 -->
         <el-form
@@ -350,7 +337,7 @@ const queryParams = reactive({
 })
 const queryFormRef = ref() // 搜索的表单
 const exportLoading = ref(false) // 导出的加载中
-const hoverText = ref('')
+
 
 // 定义表单验证规则
 const delayReasonRules = {
@@ -674,17 +661,7 @@ const getDistanceClass = (distance: number | string | null) => {
   return ''
 }
 
-const toggleLeftContent = () => {
-  isLeftContentCollapsed.value = !isLeftContentCollapsed.value
-}
-
-const handleMouseOver = () => {
-  hoverText.value = isLeftContentCollapsed.value ? '展开' : '收起'
-}
 
-const handleMouseOut = () => {
-  hoverText.value = ''
-}
 
 /** 添加/修改操作 */
 const formRef = ref()
@@ -796,8 +773,7 @@ watch(isLeftContentCollapsed, () => {
 }
 
 .leftcontent.collapsed {
-  width: 0;
-  overflow: hidden;
+  overflow: visible;
 }
 
 /* 正数样式 - 淡绿色 */
@@ -860,40 +836,7 @@ watch(isLeftContentCollapsed, () => {
   width: 100% !important;
 }
 
-.toggle-button {
-  position: absolute;
-  top: 44%;
-  transform: translate(-65%, -50%);
-  width: 12px;
-  height: 40px;
-  background-color: #f0f0f0;
-  cursor: pointer;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  z-index: 1;
-  clip-path: polygon(0 0, 100% 18%, 100% 85%, 0 100%);
-  border-radius: 8px;
-}
 
-/* 添加鼠标悬停样式 */
-.toggle-button:hover {
-  background-color: #afafaf;
-}
-
-.triangle {
-  width: 0;
-  height: 0;
-  border-top: 4px solid transparent;
-  border-bottom: 4px solid transparent;
-  transition: transform 0.4s ease;
-  border-right: 5px solid gray; /* 修改为右边框显示颜色 */
-  border-left: none; /* 移除左边框 */
-}
-
-.triangle.rotated {
-  transform: rotate(180deg);
-}
 
 /* 延时原因 必填星号样式 */
 :deep(.required-item .el-form-item__label:before) {

+ 4 - 7
src/views/pms/qhse/certificate.vue

@@ -2,12 +2,8 @@
 <template>
   <el-row :gutter="20">
     <!-- 左侧部门树 -->
-    <el-col :span="4" :xs="24">
-      <ContentWrap class="h-1/1" v-if="treeShow">
-        <DeptTree @node-click="handleDeptNodeClick" />
-      </ContentWrap>
-    </el-col>
-    <el-col :span="contentSpan" :xs="24">
+    <DeptTree @node-click="handleDeptNodeClick" v-model:collapsed="isLeftContentCollapsed" />
+    <el-col :span="isLeftContentCollapsed ? 24 : 20" :xs="24">
       <ContentWrap>
         <!-- 搜索工作栏 -->
         <el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true">
@@ -274,7 +270,7 @@
 
 <script setup lang="ts">
 import { IotMeasureCertApi } from '@/api/pms/qhse/index'
-import DeptTree from '@/views/system/user/DeptTree.vue'
+import DeptTree from '@/views/system/user/DeptTree2.vue'
 import { handleTree } from '@/utils/tree'
 import * as DeptApi from '@/api/system/dept'
 import { ElMessageBox, ElMessage } from 'element-plus'
@@ -292,6 +288,7 @@ const loading = ref(true) // 列表的加载中
 const formLoading = ref(false) // 表单加载中
 const submitLoading = ref(false) // 提交按钮加载中
 const exportLoading = ref(false) // 导出按钮加载中
+const isLeftContentCollapsed = ref(false)
 
 const { t } = useI18n()
 

+ 132 - 126
src/views/pms/qhse/faultReport/index.vue

@@ -1,131 +1,135 @@
 <template>
-  <div class="app-container">
-    <ContentWrap style="border: 0">
-      <el-form
-        class="-mb-15px"
-        :model="queryParams"
-        ref="queryForm"
-        :inline="true"
-        label-width="100px"
-      >
-        <el-row :gutter="20">
-          <el-col :span="24" :xs="24" :sm="12" :md="6">
-            <el-form-item label="事件级别" prop="accidentGrade">
-              <el-input
-                v-model="queryParams.accidentGrade"
-                placeholder="请输入事件级别"
-                clearable
-                @keyup.enter="handleQuery"
-                style="width: 200px"
-              />
-            </el-form-item>
-          </el-col>
-          <el-col :span="24" :xs="24" :sm="12" :md="6">
-            <el-form-item label="事件类型" prop="accidentType">
-              <el-input
-                v-model="queryParams.accidentType"
-                placeholder="请选择事件类型"
-                clearable
-                style="width: 200px"
-              />
-            </el-form-item>
-          </el-col>
-          <el-col :span="24" :xs="24" :sm="24" :md="12">
-            <el-form-item style="display: block">
-              <el-button type="primary" @click="handleQuery" :icon="Search">搜索</el-button>
-              <el-button @click="resetQuery" :icon="Refresh">重置</el-button>
+  <el-row :gutter="20">
+    <DeptTree @node-click="handleDeptNodeClick" v-model:collapsed="isLeftContentCollapsed" />
+
+    <el-col :xs="24" :span="isLeftContentCollapsed ? 24 : 20">
+      <ContentWrap style="border: 0">
+        <el-form
+          class="-mb-15px"
+          :model="queryParams"
+          ref="queryForm"
+          :inline="true"
+          label-width="100px"
+        >
+          <el-row :gutter="20">
+            <el-col :span="24" :xs="24" :sm="12" :md="6">
+              <el-form-item label="事件级别" prop="accidentGrade">
+                <el-input
+                  v-model="queryParams.accidentGrade"
+                  placeholder="请输入事件级别"
+                  clearable
+                  @keyup.enter="handleQuery"
+                  style="width: 200px"
+                />
+              </el-form-item>
+            </el-col>
+            <el-col :span="24" :xs="24" :sm="12" :md="6">
+              <el-form-item label="事件类型" prop="accidentType">
+                <el-input
+                  v-model="queryParams.accidentType"
+                  placeholder="请选择事件类型"
+                  clearable
+                  style="width: 200px"
+                />
+              </el-form-item>
+            </el-col>
+            <el-col :span="24" :xs="24" :sm="24" :md="12">
+              <el-form-item style="display: block">
+                <el-button type="primary" @click="handleQuery" :icon="Search">搜索</el-button>
+                <el-button @click="resetQuery" :icon="Refresh">重置</el-button>
+                <el-button
+                  type="primary"
+                  @click="openForm('create', undefined, false)"
+                  color="#626aef"
+                  v-hasPermi="['rq:iot-accident-report:create']"
+                >
+                  <Icon icon="ep:plus" class="mr-5px" /> 新增
+                </el-button>
+                <!-- <el-button type="success" plain @click="handleExport" :loading="exportLoading">
+                <Icon icon="ep:download" class="mr-5px" /> 导出
+              </el-button> -->
+              </el-form-item>
+            </el-col>
+          </el-row>
+        </el-form>
+      </ContentWrap>
+
+      <ContentWrap style="border: 0">
+        <el-table
+          v-loading="loading"
+          :data="list"
+          row-key="id"
+          border
+          style="width: 100%"
+          :header-cell-style="{ background: '#f5f7fa', color: '#333', height: '50px' }"
+          :cell-style="{ padding: '12px 8px' }"
+          height="70vh"
+          :max-height="tableHeight"
+        >
+          <el-table-column prop="actualTime" label="事件时间" align="center" min-width="150">
+            <template #default="{ row }">
+              {{ formatDate(row.actualTime) }}
+            </template>
+          </el-table-column>
+          <el-table-column prop="accidentGrade" label="事件级别" align="center" />
+          <el-table-column prop="accidentType" label="事件类型" align="center" />
+          <el-table-column prop="accidentType" label="事件状态" align="center" width="100">
+            <template #default="scope">
+              <dict-tag :type="DICT_TYPE.ACCIDENT_REPORT_STATUS" :value="scope.row.status" />
+            </template>
+          </el-table-column>
+          <el-table-column
+            prop="lossSituation"
+            label="事件损失情况"
+            align="center"
+            show-overflow-tooltip
+            min-width="150"
+          />
+
+          <el-table-column
+            prop="accidentAddress"
+            label="事件地址"
+            align="center"
+            min-width="150"
+            show-overflow-tooltip
+          />
+          <el-table-column prop="deptName" label="部门名称" align="center" />
+          <el-table-column prop="dutyPerson" label="现场负责人" align="center" width="100" />
+          <el-table-column prop="actualTime" label="创建时间" align="center" min-width="150">
+            <template #default="{ row }">
+              {{ formatDate(row.createTime) }}
+            </template>
+          </el-table-column>
+
+          <el-table-column label="操作" align="center" width="150" fixed="right">
+            <template #default="{ row }">
               <el-button
+                link
                 type="primary"
-                @click="openForm('create', undefined, false)"
-                color="#626aef"
-                v-hasPermi="['rq:iot-accident-report:create']"
+                @click="openForm('detail', row.id, true)"
+                :icon="View"
+                v-hasPermi="['rq:iot-accident-report:query']"
+                >详情</el-button
               >
-                <Icon icon="ep:plus" class="mr-5px" /> 新增
-              </el-button>
-              <!-- <el-button type="success" plain @click="handleExport" :loading="exportLoading">
-                <Icon icon="ep:download" class="mr-5px" /> 导出
-              </el-button> -->
-            </el-form-item>
-          </el-col>
-        </el-row>
-      </el-form>
-    </ContentWrap>
-
-    <ContentWrap style="border: 0">
-      <el-table
-        v-loading="loading"
-        :data="list"
-        row-key="id"
-        border
-        style="width: 100%"
-        :header-cell-style="{ background: '#f5f7fa', color: '#333', height: '50px' }"
-        :cell-style="{ padding: '12px 8px' }"
-        height="70vh"
-        :max-height="tableHeight"
-      >
-        <el-table-column prop="actualTime" label="事件时间" align="center" min-width="150">
-          <template #default="{ row }">
-            {{ formatDate(row.actualTime) }}
-          </template>
-        </el-table-column>
-        <el-table-column prop="accidentGrade" label="事件级别" align="center" />
-        <el-table-column prop="accidentType" label="事件类型" align="center" />
-        <el-table-column prop="accidentType" label="事件状态" align="center" width="100">
-          <template #default="scope">
-            <dict-tag :type="DICT_TYPE.ACCIDENT_REPORT_STATUS" :value="scope.row.status" />
-          </template>
-        </el-table-column>
-        <el-table-column
-          prop="lossSituation"
-          label="事件损失情况"
-          align="center"
-          show-overflow-tooltip
-          min-width="150"
-        />
-
-        <el-table-column
-          prop="accidentAddress"
-          label="事件地址"
-          align="center"
-          min-width="150"
-          show-overflow-tooltip
-        />
-        <el-table-column prop="deptName" label="部门名称" align="center" />
-        <el-table-column prop="dutyPerson" label="现场负责人" align="center" width="100" />
-        <el-table-column prop="actualTime" label="创建时间" align="center" min-width="150">
-          <template #default="{ row }">
-            {{ formatDate(row.createTime) }}
-          </template>
-        </el-table-column>
-
-        <el-table-column label="操作" align="center" width="150" fixed="right">
-          <template #default="{ row }">
-            <el-button
-              link
-              type="primary"
-              @click="openForm('detail', row.id, true)"
-              :icon="View"
-              v-hasPermi="['rq:iot-accident-report:query']"
-              >详情</el-button
-            >
-            <el-button link type="primary" @click="openApprovalDialog(row)"> 流转信息 </el-button>
-          </template>
-        </el-table-column>
-      </el-table>
-
-      <!-- 分页 -->
-      <div class="mt-2 mb-2 float-right">
-        <el-pagination
-          v-model:current-page="queryParams.pageNo"
-          v-model:page-size="queryParams.pageSize"
-          :total="total"
-          layout="total, sizes, prev, pager, next"
-          @size-change="handleSizeChange"
-          @current-change="handleCurrentChange"
-          background
-        />
-      </div>
-    </ContentWrap>
+              <el-button link type="primary" @click="openApprovalDialog(row)"> 流转信息 </el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+
+        <!-- 分页 -->
+        <div class="mt-2 mb-2 float-right">
+          <el-pagination
+            v-model:current-page="queryParams.pageNo"
+            v-model:page-size="queryParams.pageSize"
+            :total="total"
+            layout="total, sizes, prev, pager, next"
+            @size-change="handleSizeChange"
+            @current-change="handleCurrentChange"
+            background
+          />
+        </div>
+      </ContentWrap>
+    </el-col>
 
     <!-- 表单弹窗 -->
     <!-- 表单弹窗:添加/修改 -->
@@ -212,7 +216,7 @@
         </div>
       </div>
     </el-drawer>
-  </div>
+  </el-row>
 </template>
 
 <script setup>
@@ -229,8 +233,10 @@ import { DICT_TYPE, getStrDictOptions } from '@/utils/dict'
 import { IotApprovalApi } from '@/api/pms/qhse/index'
 import QhseFaultReportForm from './QhseFaultReportForm.vue'
 import { useRouter } from 'vue-router'
+import DeptTree from '@/views/system/user/DeptTree2.vue'
 
 const router = useRouter()
+const isLeftContentCollapsed = ref(false)
 
 // Data
 const loading = ref(false)
@@ -291,7 +297,7 @@ const tableHeight = computed(() => {
   if (isMobile.value) {
     return window.innerHeight - 300 // 为移动端减少高度,考虑其他元素占用空间
   }
-  return '70vh'
+  return '90vh'
 })
 
 // Methods

+ 7 - 7
src/views/pms/qhse/index.vue

@@ -1,12 +1,10 @@
 <template>
   <el-row :gutter="20">
     <!-- 左侧部门树 -->
-    <el-col :span="4" :xs="24">
-      <ContentWrap class="h-1/1" v-if="treeShow">
-        <DeptTree @node-click="handleDeptNodeClick" />
-      </ContentWrap>
-    </el-col>
-    <el-col :span="contentSpan" :xs="24">
+
+    <DeptTree @node-click="handleDeptNodeClick" v-model:collapsed="isLeftContentCollapsed" />
+
+    <el-col :xs="24" :span="isLeftContentCollapsed ? 24 : 20">
       <ContentWrap>
         <!-- 搜索工作栏 -->
         <el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true">
@@ -253,7 +251,7 @@
 
 <script setup lang="ts">
 import { IotInstrumentApi } from '@/api/pms/qhse/index'
-import DeptTree from '@/views/system/user/DeptTree.vue'
+import DeptTree from '@/views/system/user/DeptTree2.vue'
 import { handleTree } from '@/utils/tree'
 import { defaultProps } from '@/utils/tree'
 import * as DeptApi from '@/api/system/dept'
@@ -270,6 +268,8 @@ const formLoading = ref(false) // 表单加载中
 const submitLoading = ref(false) // 提交按钮加载中
 let exportLoading = ref(false)
 
+const isLeftContentCollapsed = ref(false)
+
 const { t } = useI18n()
 
 const list = ref([]) // 列表的数据

+ 228 - 97
src/views/pms/qhse/iotmeasuredetect/index.vue

@@ -1,102 +1,150 @@
 <template>
-  <ContentWrap>
-    <!-- 搜索工作栏 -->
-    <el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true">
-      <el-form-item label="检测/校准日期" prop="detectDate">
-        <el-date-picker
-          v-model="queryParams.detectDate"
-          value-format="YYYY-MM-DD HH:mm:ss"
-          type="daterange"
-          start-placeholder="开始日期"
-          end-placeholder="结束日期"
-          :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
-          class="!w-200px"
-        />
-      </el-form-item>
-      <el-form-item label="检测/校准机构" prop="detectOrg">
-        <el-input
-          v-model="queryParams.detectOrg"
-          placeholder="请输入检测/校准机构"
-          clearable
-          @keyup.enter="handleQuery"
-          class="!w-150px"
-        />
-      </el-form-item>
-      <el-form-item label="检测/校准有效期" prop="validityPeriod">
-        <el-date-picker
-          v-model="queryParams.validityPeriod"
-          value-format="YYYY-MM-DD"
-          type="date"
-          placeholder="选择检测/校准有效期"
-          clearable
-          class="!w-150px"
-        />
-      </el-form-item>
-      <el-form-item label="校准金额" prop="detectAmount">
-        <el-input
-          v-model="queryParams.detectAmount"
-          placeholder="请输入校准金额"
-          clearable
-          @keyup.enter="handleQuery"
-          class="!w-150px"
+  <el-row :gutter="20">
+    <el-col
+      :class="{ leftcontent: true, collapsed: isLeftContentCollapsed }"
+      :span="isLeftContentCollapsed ? 0 : 4"
+      :xs="24"
+    >
+      <ContentWrap class="h-1/1">
+        <DeptTree @node-click="handleDeptNodeClick" />
+      </ContentWrap>
+    </el-col>
+
+    <el-col
+      class="rightcontent"
+      :span="isLeftContentCollapsed ? 24 : 20"
+      :xs="24"
+      style="position: relative; height: 100vh"
+    >
+      <!-- 图片形式的切换按钮 -->
+      <div
+        class="toggle-button"
+        :style="{ left: isLeftContentCollapsed ? '0px' : '-13px' }"
+        @click="toggleLeftContent"
+        @mouseover="handleMouseOver"
+        @mouseout="handleMouseOut"
+      >
+        <img
+          :src="isLeftContentCollapsed ? hideimage : showimage"
+          alt="切换按钮"
+          class="toggle-icon"
         />
-      </el-form-item>
-
-      <el-form-item>
-        <el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
-        <el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
-        <el-button type="primary" plain @click="openForm('create')">
-          <Icon icon="ep:plus" class="mr-5px" /> 新增
-        </el-button>
-        <el-button type="success" plain @click="handleExport" :loading="exportLoading">
-          <Icon icon="ep:download" class="mr-5px" /> 导出
-        </el-button>
-      </el-form-item>
-    </el-form>
-  </ContentWrap>
-
-  <!-- 列表 -->
-  <ContentWrap>
-    <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
-      <el-table-column label="计量器具名称" align="center" prop="measureName" />
-      <el-table-column label="证书编码" align="center" prop="measureCertNo" />
-      <el-table-column label="检测/校准日期" align="center" prop="detectDate">
-        <template #default="scope">
-          <span>{{ formatDateCorrectly(scope.row.detectDate) }}</span>
-        </template>
-      </el-table-column>
-      <el-table-column label="检测/校准机构" align="center" prop="detectOrg" />
-      <el-table-column label="检测/校准标准" align="center" prop="detectStandard" />
-      <el-table-column label="检测/校准内容" align="center" prop="detectContent">
-        <template #default="scope">
-          <div v-html="scope.row.detectContent"></div>
-        </template>
-      </el-table-column>
-      <el-table-column label="检测/校准有效期" align="center" prop="validityPeriod" width="180px">
-        <template #default="scope">
-          <span>{{ formatDateCorrectly(scope.row.validityPeriod) }}</span>
-        </template>
-      </el-table-column>
-      <el-table-column label="校准金额" align="center" prop="detectAmount" />
-
-      <el-table-column label="部门名称" align="center" prop="deptName" />
-      <el-table-column label="操作" align="center" min-width="120px">
-        <template #default="scope">
-          <el-button link type="primary" @click="openForm('update', scope.row.id)">
-            编辑
-          </el-button>
-          <el-button link type="danger" @click="handleDelete(scope.row.id)"> 删除 </el-button>
-        </template>
-      </el-table-column>
-    </el-table>
-    <!-- 分页 -->
-    <Pagination
-      :total="total"
-      v-model:page="queryParams.pageNo"
-      v-model:limit="queryParams.pageSize"
-      @pagination="getList"
-    />
-  </ContentWrap>
+      </div>
+
+      <ContentWrap>
+        <!-- 搜索工作栏 -->
+        <el-form :model="queryParams" ref="queryFormRef" :inline="true">
+          <el-form-item label="检测/校准日期" prop="detectDate">
+            <el-date-picker
+              v-model="queryParams.detectDate"
+              value-format="YYYY-MM-DD HH:mm:ss"
+              type="daterange"
+              start-placeholder="开始日期"
+              end-placeholder="结束日期"
+              :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
+              class="!w-200px"
+            />
+          </el-form-item>
+          <el-form-item label="检测/校准机构" prop="detectOrg">
+            <el-input
+              v-model="queryParams.detectOrg"
+              placeholder="请输入检测/校准机构"
+              clearable
+              @keyup.enter="handleQuery"
+              class="!w-150px"
+            />
+          </el-form-item>
+          <el-form-item label="检测/校准有效期" prop="validityPeriod">
+            <el-date-picker
+              v-model="queryParams.validityPeriod"
+              value-format="YYYY-MM-DD"
+              type="date"
+              placeholder="选择检测/校准有效期"
+              clearable
+              class="!w-150px"
+            />
+          </el-form-item>
+          <el-form-item label="校准金额" prop="detectAmount">
+            <el-input
+              v-model="queryParams.detectAmount"
+              placeholder="请输入校准金额"
+              clearable
+              @keyup.enter="handleQuery"
+              class="!w-150px"
+            />
+          </el-form-item>
+
+          <el-form-item>
+            <el-button @click="handleQuery">
+              <Icon icon="ep:search" class="mr-5px" /> 搜索
+            </el-button>
+            <el-button @click="resetQuery">
+              <Icon icon="ep:refresh" class="mr-5px" /> 重置
+            </el-button>
+            <el-button type="primary" plain @click="openForm('create')">
+              <Icon icon="ep:plus" class="mr-5px" /> 新增
+            </el-button>
+            <el-button type="success" plain @click="handleExport" :loading="exportLoading">
+              <Icon icon="ep:download" class="mr-5px" /> 导出
+            </el-button>
+          </el-form-item>
+        </el-form>
+      </ContentWrap>
+
+      <!-- 列表 -->
+      <ContentWrap>
+        <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
+          <el-table-column label="计量器具名称" align="center" prop="measureName" min-width="160" />
+          <el-table-column label="证书编码" align="center" prop="measureCertNo" min-width="160" />
+          <el-table-column label="检测/校准日期" align="center" prop="detectDate" width="140">
+            <template #default="scope">
+              <span class="iot-md-date">{{ formatDateCorrectly(scope.row.detectDate) }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column label="检测/校准机构" align="center" prop="detectOrg" min-width="160" />
+          <el-table-column
+            label="检测/校准标准"
+            align="center"
+            prop="detectStandard"
+            min-width="160"
+          />
+          <el-table-column
+            label="检测/校准内容"
+            align="center"
+            prop="detectContent"
+            min-width="220"
+          >
+            <template #default="scope">
+              <div class="detect-content" v-html="scope.row.detectContent"></div>
+            </template>
+          </el-table-column>
+          <el-table-column label="检测/校准有效期" align="center" prop="validityPeriod" width="140">
+            <template #default="scope">
+              <span class="iot-md-date">{{ formatDateCorrectly(scope.row.validityPeriod) }}</span>
+            </template>
+          </el-table-column>
+          <el-table-column label="校准金额" align="center" prop="detectAmount" width="120" />
+          <el-table-column label="部门名称" align="center" prop="deptName" min-width="140" />
+          <el-table-column label="操作" align="center" width="140" fixed="right">
+            <template #default="scope">
+              <el-button link type="primary" @click="openForm('update', scope.row.id)">
+                编辑
+              </el-button>
+              <el-button link type="danger" @click="handleDelete(scope.row.id)"> 删除 </el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+        <div class="iot-md-pagination">
+          <Pagination
+            :total="total"
+            v-model:page="queryParams.pageNo"
+            v-model:limit="queryParams.pageSize"
+            @pagination="getList"
+          />
+        </div>
+      </ContentWrap>
+    </el-col>
+  </el-row>
 
   <!-- 表单弹窗:添加/修改 -->
   <IotMeasureDetectForm ref="formRef" @success="getList" />
@@ -107,11 +155,16 @@ import download from '@/utils/download'
 import { IotMeasureDetectApi, IotMeasureDetectVO } from '@/api/pms/qhse/index'
 import IotMeasureDetectForm from './IotMeasureDetectForm.vue'
 import { formatDate } from '@/utils/formatTime'
+import DeptTree from '@/views/system/user/DeptTree.vue'
+import hideimage from '@/assets/imgs/leftTree-hide.png'
+import showimage from '@/assets/imgs/leftTree-show.png'
 /** 计量器具-检测校准明细 列表 */
 defineOptions({ name: 'IotMeasureDetect' })
 
 const message = useMessage() // 消息弹窗
 const { t } = useI18n() // 国际化
+const isLeftContentCollapsed = ref(false)
+const hoverText = ref('')
 
 const loading = ref(true) // 列表的加载中
 const list = ref<IotMeasureDetectVO[]>([]) // 列表的数据
@@ -148,6 +201,26 @@ const handleQuery = () => {
   queryParams.pageNo = 1
   getList()
 }
+
+const selectedDept = ref<{ id: number; name: string }>()
+
+const handleDeptNodeClick = async (row) => {
+  selectedDept.value = { id: row.id, name: row.name }
+  queryParams.deptId = row.id
+  await getList()
+}
+
+const toggleLeftContent = () => {
+  isLeftContentCollapsed.value = !isLeftContentCollapsed.value
+}
+
+const handleMouseOver = () => {
+  hoverText.value = isLeftContentCollapsed.value ? '展开' : '收起'
+}
+
+const handleMouseOut = () => {
+  hoverText.value = ''
+}
 const formatDateCorrectly = (timestamp) => {
   if (!timestamp) return ''
 
@@ -219,3 +292,61 @@ onMounted(() => {
   getList()
 })
 </script>
+
+<style scoped>
+.leftcontent {
+  transition: width 0.3s ease;
+  position: relative;
+}
+
+.leftcontent.collapsed {
+  width: 0;
+  overflow: hidden;
+}
+
+.rightcontent {
+  position: relative;
+}
+
+.toggle-button {
+  position: absolute;
+  top: 44%;
+  transform: translate(6%, -50%);
+  /* width: 18px;
+  height: 40px;
+  cursor: pointer;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  z-index: 1;
+
+  border-radius: 8px;
+  background-color: #f0f0f0;
+  transition: all 0.3s ease; */
+}
+
+/* 图片样式 - 保持原始尺寸 */
+.toggle-icon {
+  width: auto; /* 自动宽度 */
+  height: auto; /* 自动高度 */
+  max-width: 100%; /* 不超过容器宽度 */
+  max-height: 100%; /* 不超过容器高度 */
+  /* filter: brightness(1); */
+  transition: all 0.3s ease;
+  z-index: 999;
+  cursor: pointer;
+}
+
+/* 鼠标悬停时图片颜色变深 */
+.toggle-button:hover .toggle-icon {
+  filter: brightness(0.9);
+}
+
+/* 确保图片在容器内居中 */
+.toggle-button img {
+  display: block;
+  margin: auto;
+  width: auto;
+  height: auto;
+}
+</style>

+ 273 - 0
src/views/system/user/DeptTree2.vue

@@ -0,0 +1,273 @@
+<template>
+  <el-col
+    :class="{ leftcontent: true, collapsed: isCollapsed }"
+    :span="isCollapsed ? 0 : 4"
+    :xs="24"
+  >
+    <ContentWrap class="h-[85vh]">
+      <div class="dept-tree" :class="{ 'is-collapsed': isCollapsed }" style="overflow-y: auto">
+        <div class="head-container" style="display: flex; flex-direction: row">
+          <el-input
+            v-model="deptName"
+            class="mb-18px"
+            style="height: 35px"
+            clearable
+            placeholder="请输入部门名称"
+          >
+            <template #prefix>
+              <Icon icon="ep:search" />
+            </template>
+          </el-input>
+        </div>
+        <div class="tree-container">
+          <el-tree
+            v-show="!isCollapsed"
+            ref="treeRef"
+            :data="deptList"
+            :expand-on-click-node="false"
+            :filter-node-method="filterNode"
+            :props="defaultProps"
+            :default-expanded-keys="firstLevelKeys"
+            highlight-current
+            node-key="id"
+            @node-click="handleNodeClick"
+            @node-contextmenu="handleRightClick"
+          />
+        </div>
+      </div>
+      <div
+        v-show="menuVisible"
+        class="custom-menu"
+        :style="{ left: menuX + 'px', top: menuY + 'px' }"
+      >
+        <ul>
+          <li @click="handleMenuClick('add')">新增子节点</li>
+          <li @click="handleMenuClick('edit')">重命名</li>
+          <li @click="handleMenuClick('delete')">删除</li>
+        </ul>
+      </div>
+    </ContentWrap>
+  </el-col>
+
+  <!-- 切换按钮移到外部,始终可见 -->
+  <button
+    :class="isCollapsed ? 'tree-toggle--outside' : 'tree-toggle--outside2'"
+    type="button"
+    :aria-label="isCollapsed ? '展开组织树' : '收起组织树'"
+    @click="toggleCollapsed"
+    :title="isCollapsed ? '展开' : '收起'"
+  >
+    <img class="tree-toggle__img" :src="isCollapsed ? hideimage : showimage" alt="" />
+  </button>
+</template>
+
+<script lang="ts" setup>
+import { ElTree } from 'element-plus'
+import * as DeptApi from '@/api/system/dept'
+import { defaultProps, handleTree } from '@/utils/tree'
+import { useTreeStore } from '@/store/modules/usersTreeStore'
+import hideimage from '@/assets/imgs/leftTree-hide.png'
+import showimage from '@/assets/imgs/leftTree-show.png'
+
+defineOptions({ name: 'SystemUserDeptTree' })
+
+type Props = {
+  collapsed?: boolean
+  collapsible?: boolean
+}
+
+const props = defineProps<Props>()
+const emits = defineEmits<{
+  (e: 'node-click', row: any): void
+  (e: 'update:collapsed', value: boolean): void
+  (e: 'toggle', value: boolean): void
+}>()
+
+const collapsible = computed(() => props.collapsible !== false)
+const collapsedLocal = ref(false)
+const isCollapsed = computed(() => (props.collapsed ?? collapsedLocal.value) === true)
+
+const deptName = ref('')
+const deptList = ref<Tree[]>([]) // 树形结构
+const treeRef = ref<InstanceType<typeof ElTree>>()
+const menuVisible = ref(false)
+const menuX = ref(0)
+const menuY = ref(0)
+const firstLevelKeys = ref([])
+let selectedNode = null
+const treeStore = useTreeStore()
+
+watch(
+  () => props.collapsed,
+  (val) => {
+    if (typeof val === 'boolean') collapsedLocal.value = val
+  },
+  { immediate: true }
+)
+
+const toggleCollapsed = () => {
+  const next = !isCollapsed.value
+  collapsedLocal.value = next
+  emits('update:collapsed', next)
+  emits('toggle', next)
+}
+
+const handleRightClick = (event, { node, data }) => {
+  event.preventDefault()
+  menuX.value = event.clientX
+  menuY.value = event.clientY
+  selectedNode = data // 存储当前操作的节点数据 ‌:ml-citation{ref="7" data="citationList"}
+  //menuVisible.value = true;
+}
+const treeContainer = ref(null)
+const setHeight = () => {
+  if (!treeContainer.value) return
+  const windowHeight = window.innerHeight
+
+  treeContainer.value.style.height = `${windowHeight * 0.78}px` // 60px 底部预留
+}
+const handleMenuClick = (action) => {
+  switch (action) {
+    case 'add':
+      // 调用新增节点逻辑 ‌:ml-citation{ref="4" data="citationList"}
+      break
+    case 'edit':
+      // 调用编辑节点逻辑 ‌:ml-citation{ref="7" data="citationList"}
+      break
+    case 'delete':
+      // 调用删除节点逻辑 ‌:ml-citation{ref="4" data="citationList"}
+      break
+  }
+  menuVisible.value = false
+}
+/** 获得部门树 */
+const getTree = async () => {
+  const res = await DeptApi.getSimpleDeptList()
+  deptList.value = []
+  deptList.value.push(...handleTree(res))
+  firstLevelKeys.value = deptList.value.map((node) => node.id)
+}
+
+/** 基于名字过滤 */
+const filterNode = (name: string, data: Tree) => {
+  if (!name) return true
+  return data.name.includes(name)
+}
+
+/** 处理部门被点击 */
+const handleNodeClick = async (row: { [key: string]: any }) => {
+  emits('node-click', row)
+  treeStore.setSelectedId(row.id)
+}
+
+/** 监听deptName */
+watch(deptName, (val) => {
+  treeRef.value!.filter(val)
+})
+
+/** 初始化 */
+onMounted(async () => {
+  await getTree()
+  // setHeight()
+  // window.addEventListener('resize', setHeight)
+})
+onUnmounted(() => {
+  window.removeEventListener('resize', setHeight)
+})
+</script>
+<style lang="scss" scoped>
+.dept-tree {
+  max-height: 100%;
+  overflow-y: auto;
+}
+.custom-menu {
+  position: fixed;
+  background: white;
+  border: 1px solid #ccc;
+  box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.1);
+  z-index: 1000;
+}
+.custom-menu ul {
+  list-style: none;
+  padding: 0;
+  margin: 0;
+}
+.custom-menu li {
+  padding: 8px 20px;
+  cursor: pointer;
+}
+.custom-menu li:hover {
+  background: #f5f5f5;
+}
+.tree-container {
+  overflow-y: auto;
+  max-height: 100%;
+  min-width: 100%;
+  // border: 1px solid #e4e7ed;
+  border-radius: 4px;
+  position: relative;
+  overflow-x: visible;
+}
+
+// 外部按钮样式 - 定位到左侧边缘
+.tree-toggle--outside {
+  position: absolute;
+  top: 30vh;
+  left: 0;
+  transform: translate(-50%, 0%);
+  z-index: 10;
+  background: transparent;
+  border: none;
+  cursor: pointer;
+  padding: 0;
+  line-height: 0;
+  transition: color 0.3s ease;
+}
+
+.tree-toggle--outside2 {
+  position: absolute;
+  top: 38%;
+  left: 16.5%;
+  transform: translate(-50%, 0%);
+  z-index: 10;
+  background: transparent;
+  border: none;
+  cursor: pointer;
+  padding: 0;
+  line-height: 0;
+  transition: color 0.3s ease;
+}
+
+.tree-toggle--outside:hover {
+  filter: brightness(0.9);
+  transition: color 0.3s ease;
+}
+
+.tree-toggle--outside2:hover {
+  filter: brightness(0.9);
+  transition: color 0.3s ease;
+}
+
+.tree-toggle__img {
+  display: block;
+  width: auto;
+  height: auto;
+  max-width: 100%;
+  max-height: 100%;
+  user-select: none;
+}
+
+.dept-tree.is-collapsed .tree-container {
+  overflow-y: auto;
+}
+
+.leftcontent {
+  transition: width 0.3s ease;
+  position: relative;
+}
+
+.leftcontent.collapsed {
+  width: 0 !important;
+  overflow: hidden;
+}
+</style>