Jelajahi Sumber

人员台账修改

yanghao 2 hari lalu
induk
melakukan
f4f5c9ca9f
1 mengubah file dengan 260 tambahan dan 238 penghapusan
  1. 260 238
      src/views/pms/qhse/certificate.vue

+ 260 - 238
src/views/pms/qhse/certificate.vue

@@ -1,253 +1,272 @@
 <!-- src/views/pms/qhse/certificate.vue -->
 <template>
-  <el-row :gutter="20">
-    <!-- 左侧部门树 -->
-    <DeptTree @node-click="handleDeptNodeClick" v-model:collapsed="isLeftContentCollapsed" />
-    <el-col :span="isLeftContentCollapsed ? 24 : 20" :xs="24">
-      <div class="stats-cards">
-        <div class="stats-card stats-card--expired">
-          <div class="flex items-center gap-2">
-            <Icon icon="ep:info-filled" color="#de3b3b" />
-            <div class="stats-card__label">已过期</div>
-          </div>
-
-          <div class="stats-card__value">
-            <CountTo
-              :duration="2600"
-              :end-val="expired"
-              :start-val="0"
-              class="stats-card__value text-[40px]! pt-10 text-center! text-[#e35656]!" />
-          </div>
+  <div
+    class="qhse-page grid grid-cols-[auto_1fr] grid-rows-[auto_auto_minmax(0,1fr)_auto] gap-3 gap-x-4 h-[calc(100vh-20px-var(--top-tool-height)-var(--tags-view-height)-var(--app-footer-height))]">
+    <DeptTreeSelect
+      class="row-span-4"
+      :top-id="rootDeptId"
+      :deptId="deptId"
+      v-model="queryParams.deptId"
+      :init-select="false"
+      :show-title="false"
+      request-api="getSimpleDeptList"
+      @node-click="handleDeptNodeClick" />
+
+    <div class="stats-cards">
+      <div class="stats-card stats-card--expired">
+        <div class="flex items-center gap-2">
+          <Icon icon="ep:info-filled" color="#de3b3b" />
+          <div class="stats-card__label">已过期</div>
         </div>
-        <div class="stats-card stats-card--warn">
-          <div class="flex items-center gap-2">
-            <Icon icon="ep:bell-filled" color="#d97706" />
-            <div class="stats-card__label">60天预警</div>
-          </div>
-          <div class="stats-card__value">
-            <CountTo
-              :duration="2600"
-              :end-val="warn"
-              :start-val="0"
-              class="stats-card__value text-[40px]! pt-10 text-center! text-[#d97706]!" />
-          </div>
+
+        <div class="stats-card__value">
+          <CountTo
+            :duration="2600"
+            :end-val="expired"
+            :start-val="0"
+            class="stats-card__value text-[40px]! pt-10 text-center! text-[#e35656]!" />
+        </div>
+      </div>
+      <div class="stats-card stats-card--warn">
+        <div class="flex items-center gap-2">
+          <Icon icon="ep:bell-filled" color="#d97706" />
+          <div class="stats-card__label">60天预警</div>
+        </div>
+        <div class="stats-card__value">
+          <CountTo
+            :duration="2600"
+            :end-val="warn"
+            :start-val="0"
+            class="stats-card__value text-[40px]! pt-10 text-center! text-[#d97706]!" />
+        </div>
+      </div>
+      <div class="stats-card stats-card--total">
+        <div class="flex items-center gap-2">
+          <Icon icon="eos-icons:counting" color="#2563eb" />
+          <div class="stats-card__label">证书总数</div>
+        </div>
+
+        <div class="stats-card__value">
+          <CountTo
+            :duration="2600"
+            :end-val="totalCert"
+            :start-val="0"
+            class="stats-card__value text-[40px]! pt-10 text-center! text-[#2563eb]!" />
         </div>
-        <div class="stats-card stats-card--total">
-          <div class="flex items-center gap-2">
-            <Icon icon="eos-icons:counting" color="#2563eb" />
-            <div class="stats-card__label">证书总数</div>
-          </div>
-
-          <div class="stats-card__value">
-            <CountTo
-              :duration="2600"
-              :end-val="totalCert"
-              :start-val="0"
-              class="stats-card__value text-[40px]! pt-10 text-center! text-[#2563eb]!" />
-          </div>
+      </div>
+      <div class="stats-card stats-card--personal">
+        <div class="flex items-center gap-2">
+          <Icon
+            icon="material-symbols-light:account-circle-outline"
+            class="w-20 h-20"
+            color="#2563eb" />
+          <div class="stats-card__label">个人证书</div>
         </div>
-        <div class="stats-card stats-card--personal">
-          <div class="flex items-center gap-2">
-            <Icon
-              icon="material-symbols-light:account-circle-outline"
-              class="w-20 h-20"
-              color="#2563eb" />
-            <div class="stats-card__label">个人证书</div>
-          </div>
-
-          <div class="stats-card__value">
-            <CountTo
-              :duration="2600"
-              :end-val="personal"
-              :start-val="0"
-              class="stats-card__value text-[40px]! pt-10 text-center! text-[#2563eb]!" />
-          </div>
+
+        <div class="stats-card__value">
+          <CountTo
+            :duration="2600"
+            :end-val="personal"
+            :start-val="0"
+            class="stats-card__value text-[40px]! pt-10 text-center! text-[#2563eb]!" />
         </div>
       </div>
-      <div style="border: none" class="!border-none bg-white rounded-sm pt-4 px-2">
-        <!-- 搜索工作栏 -->
-        <el-form :model="queryParams" ref="queryFormRef" :inline="true">
-          <el-form-item label="证书类型" prop="type">
-            <el-select v-model="queryParams.type" placeholder="请选择证书类型" style="width: 120px">
-              <el-option label="个人证书" value="personal" />
-              <el-option label="组织证书" value="organization" />
-              <el-option label="其他" value="other" />
-            </el-select>
-          </el-form-item>
-
-          <el-form-item label="证书类别" prop="classify">
-            <el-select
-              v-model="queryParams.classify"
-              placeholder="证书类别"
-              clearable
-              class="!w-150px">
-              <el-option
-                v-for="dict in getStrDictOptions(DICT_TYPE.PERSON_CERT).concat(
-                  getStrDictOptions(DICT_TYPE.ORG_CERT)
-                )"
-                :key="dict.value"
-                :label="dict.label"
-                :value="dict.value" />
-            </el-select>
-          </el-form-item>
-
-          <el-form-item label="所属人" prop="userName">
-            <el-input placeholder="输入所属人" v-model="queryParams.userName" />
-          </el-form-item>
-
-          <el-form-item label="是否过期" prop="expired">
-            <el-select
-              v-model="queryParams.expired"
-              placeholder="请选择是否过期"
-              clearable
-              style="width: 150px">
-              <el-option
-                v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
-                :key="dict.value"
-                :label="dict.label"
-                :value="dict.value" />
-            </el-select>
-          </el-form-item>
-
-          <el-form-item label="是否预警" prop="alertWarn">
-            <el-select
-              v-model="queryParams.alertWarn"
-              placeholder="请选择是否预警"
-              clearable
-              style="width: 150px">
-              <el-option
-                v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
-                :key="dict.value"
-                :label="dict.label"
-                :value="dict.value" />
-            </el-select>
-          </el-form-item>
-
-          <el-form-item>
-            <el-button @click="handleAdd" type="primary"
-              ><Icon icon="ep:plus" class="mr-5px" />新增</el-button
-            >
-            <el-button @click="handleQuery"
-              ><Icon icon="ep:search" class="mr-5px" /> {{ t('devicePerson.search') }}</el-button
-            >
-            <el-button @click="resetQuery"
-              ><Icon icon="ep:refresh" class="mr-5px" /> {{ t('devicePerson.reset') }}</el-button
-            >
-            <el-button @click="handleExport" type="success" plain :loading="exportLoading"
-              ><Icon icon="ep:download" class="mr-5px" /> 导出</el-button
-            >
-          </el-form-item>
-        </el-form>
+    </div>
+
+    <!-- 搜索工作栏 -->
+    <el-form
+      class="bg-white dark:bg-[#1d1e1f] rounded-lg shadow px-8 pt-4 flex items-center flex-wrap min-w-0"
+      :model="queryParams"
+      ref="queryFormRef"
+      :inline="true">
+      <el-form-item label="证书类型" prop="type">
+        <el-select v-model="queryParams.type" placeholder="请选择证书类型" style="width: 120px">
+          <el-option label="个人证书" value="personal" />
+          <el-option label="组织证书" value="organization" />
+          <el-option label="其他" value="other" />
+        </el-select>
+      </el-form-item>
+
+      <el-form-item label="证书类别" prop="classify">
+        <el-select v-model="queryParams.classify" placeholder="证书类别" clearable class="!w-150px">
+          <el-option
+            v-for="dict in getStrDictOptions(DICT_TYPE.PERSON_CERT).concat(
+              getStrDictOptions(DICT_TYPE.ORG_CERT)
+            )"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value" />
+        </el-select>
+      </el-form-item>
+
+      <el-form-item label="所属人" prop="userName">
+        <el-input placeholder="输入所属人" v-model="queryParams.userName" />
+      </el-form-item>
+
+      <el-form-item label="是否过期" prop="expired">
+        <el-select
+          v-model="queryParams.expired"
+          placeholder="请选择是否过期"
+          clearable
+          style="width: 150px">
+          <el-option
+            v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value" />
+        </el-select>
+      </el-form-item>
+
+      <el-form-item label="是否预警" prop="alertWarn">
+        <el-select
+          v-model="queryParams.alertWarn"
+          placeholder="请选择是否预警"
+          clearable
+          style="width: 150px">
+          <el-option
+            v-for="dict in getBoolDictOptions(DICT_TYPE.INFRA_BOOLEAN_STRING)"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value" />
+        </el-select>
+      </el-form-item>
+
+      <el-form-item>
+        <el-button @click="handleAdd" type="primary"
+          ><Icon icon="ep:plus" class="mr-5px" />新增</el-button
+        >
+        <el-button @click="handleQuery"
+          ><Icon icon="ep:search" class="mr-5px" /> {{ t('devicePerson.search') }}</el-button
+        >
+        <el-button @click="resetQuery"
+          ><Icon icon="ep:refresh" class="mr-5px" /> {{ t('devicePerson.reset') }}</el-button
+        >
+        <el-button @click="handleExport" type="success" plain :loading="exportLoading"
+          ><Icon icon="ep:download" class="mr-5px" /> 导出</el-button
+        >
+      </el-form-item>
+    </el-form>
+
+    <div class="bg-white dark:bg-[#1d1e1f] shadow rounded-lg flex flex-col p-2 pt-3 min-w-0">
+      <div class="flex-1 relative min-h-0">
+        <el-auto-resizer class="absolute">
+          <template #default="{ width, height }">
+            <zm-table
+              :loading="loading"
+              :data="list"
+              :width="width"
+              :height="height"
+              :show-overflow-tooltip="true"
+              :row-style="tableRowStyle"
+              :row-class-name="tableRowClassName">
+              >
+              <zm-table-column :label="t('monitor.serial')" width="70" align="center">
+                <template #default="scope">
+                  {{ scope.$index + 1 }}
+                </template>
+              </zm-table-column>
+
+              <zm-table-column label="证书类型" align="center" prop="type">
+                <template #default="scope">
+                  {{ getCertificateTypeText(scope.row.type) }}
+                </template>
+              </zm-table-column>
+
+              <zm-table-column label="证书类别" align="center" width="150" prop="classify">
+                <template #default="scope">
+                  <dict-tag
+                    v-if="scope.row.type === 'organization'"
+                    :type="DICT_TYPE.ORG_CERT"
+                    :value="scope.row.classify" />
+                  <dict-tag v-else :type="DICT_TYPE.PERSON_CERT" :value="scope.row.classify" />
+                </template>
+              </zm-table-column>
+              <zm-table-column
+                label="证书名称"
+                align="center"
+                prop="certName"
+                show-overflow-tooltip />
+
+              <zm-table-column label="所属人" align="center" prop="userName" />
+              <zm-table-column label="所在部门" align="center" prop="deptName" />
+
+              <zm-table-column label="颁发机构" align="center" prop="certOrg" />
+
+              <zm-table-column label="证书标准" align="center" prop="certStandard" />
+
+              <zm-table-column label="颁发时间" align="center" prop="certIssue">
+                <template #default="scope">
+                  {{ formatDateCorrectly(scope.row.certIssue) }}
+                </template>
+              </zm-table-column>
+
+              <zm-table-column label="有效期" align="center">
+                <template #default="scope">
+                  {{ formatDateCorrectly(scope.row.certExpire) }}
+                </template>
+              </zm-table-column>
+
+              <zm-table-column label="到期提醒" align="center">
+                <template #default="scope"> {{ scope.row.noticeBefore }}天前提醒 </template>
+              </zm-table-column>
+
+              <zm-table-column label="备注" align="center" prop="remark" />
+              <zm-table-column
+                :label="t('devicePerson.operation')"
+                align="center"
+                fixed="right"
+                min-width="180px"
+                action>
+                <template #default="scope">
+                  <el-button link type="primary" @click="handleEdit(scope.row)"> 编辑 </el-button>
+                  <el-button link type="danger" @click="handleDelete(scope.row.id)">
+                    删除
+                  </el-button>
+                  <el-button
+                    link
+                    type="success"
+                    v-if="scope.row.certPic"
+                    @click="viewFile(scope.row.certPic)">
+                    查看证书
+                  </el-button>
+                </template>
+              </zm-table-column>
+            </zm-table>
+          </template>
+        </el-auto-resizer>
       </div>
 
-      <!-- 列表 -->
-      <ContentWrap class="flex-1 overflow-hidden mt-15px" style="border: none">
-        <zm-table
-          :loading="loading"
-          :data="list"
-          height="calc(61vh - 220px)"
-          :show-overflow-tooltip="true"
-          :row-style="tableRowStyle"
-          :row-class-name="tableRowClassName">
-          >
-          <zm-table-column :label="t('monitor.serial')" width="70" align="center">
-            <template #default="scope">
-              {{ scope.$index + 1 }}
-            </template>
-          </zm-table-column>
-
-          <zm-table-column label="证书类型" align="center" prop="type">
-            <template #default="scope">
-              {{ getCertificateTypeText(scope.row.type) }}
-            </template>
-          </zm-table-column>
-
-          <zm-table-column label="证书类别" align="center" width="150" prop="classify">
-            <template #default="scope">
-              <dict-tag
-                v-if="scope.row.type === 'organization'"
-                :type="DICT_TYPE.ORG_CERT"
-                :value="scope.row.classify" />
-              <dict-tag v-else :type="DICT_TYPE.PERSON_CERT" :value="scope.row.classify" />
-            </template>
-          </zm-table-column>
-          <zm-table-column label="证书名称" align="center" prop="certName" show-overflow-tooltip />
-
-          <zm-table-column label="所属人" align="center" prop="userName" />
-          <zm-table-column label="所在部门" align="center" prop="deptName" />
-
-          <zm-table-column label="颁发机构" align="center" prop="certOrg" />
-
-          <zm-table-column label="证书标准" align="center" prop="certStandard" />
-
-          <zm-table-column label="颁发时间" align="center" prop="certIssue">
-            <template #default="scope">
-              {{ formatDateCorrectly(scope.row.certIssue) }}
-            </template>
-          </zm-table-column>
-
-          <zm-table-column label="有效期" align="center">
-            <template #default="scope">
-              {{ formatDateCorrectly(scope.row.certExpire) }}
-            </template>
-          </zm-table-column>
-
-          <zm-table-column label="到期提醒" align="center">
-            <template #default="scope"> {{ scope.row.noticeBefore }}天前提醒 </template>
-          </zm-table-column>
-
-          <zm-table-column label="备注" align="center" prop="remark" />
-          <zm-table-column
-            :label="t('devicePerson.operation')"
-            align="center"
-            fixed="right"
-            min-width="180px"
-            action>
-            <template #default="scope">
-              <el-button link type="primary" @click="handleEdit(scope.row)"> 编辑 </el-button>
-              <el-button link type="danger" @click="handleDelete(scope.row.id)"> 删除 </el-button>
-              <el-button
-                link
-                type="success"
-                v-if="scope.row.certPic"
-                @click="viewFile(scope.row.certPic)">
-                查看证书
-              </el-button>
-            </template>
-          </zm-table-column>
-        </zm-table>
-
-        <!-- 分页 -->
+      <div class="h-8 mt-2 flex items-center justify-end">
         <Pagination
           :total="total"
           v-model:page="queryParams.pageNo"
           v-model:limit="queryParams.pageSize"
           @pagination="getList" />
-      </ContentWrap>
+      </div>
+    </div>
 
-      <ContentWrap style="margin-top: -5px">
-        <el-alert title="证书已过期红色预警" type="error" show-icon :closable="false">
-          <template #icon>
-            <Bell />
-          </template>
-        </el-alert>
-
-        <el-alert
-          title="证书60天橙色预警"
-          type="warning"
-          show-icon
-          :closable="false"
-          style="margin-top: 5px">
-          <template #icon>
-            <Bell />
-          </template>
-        </el-alert>
-      </ContentWrap>
-    </el-col>
-  </el-row>
+    <div class="bg-white dark:bg-[#1d1e1f] shadow rounded-lg p-3 min-w-0">
+      <el-alert title="证书已过期红色预警" type="error" show-icon :closable="false">
+        <template #icon>
+          <Bell />
+        </template>
+      </el-alert>
+
+      <el-alert
+        title="证书60天橙色预警"
+        type="warning"
+        show-icon
+        :closable="false"
+        style="margin-top: 5px">
+        <template #icon>
+          <Bell />
+        </template>
+      </el-alert>
+    </div>
+  </div>
 
   <!-- 新增/编辑证书对话框 -->
-  <el-dialog
+  <Dialog
     :title="dialogTitle"
     v-model="dialogVisible"
     width="600px"
@@ -257,7 +276,7 @@
       ref="formRef"
       :model="formData"
       :rules="formRules"
-      label-width="120px"
+      label-width="auto"
       v-loading="formLoading">
       <el-form-item label="证书类型" prop="type">
         <el-select
@@ -371,9 +390,9 @@
       <el-button @click="closeDialog">取 消</el-button>
       <el-button type="primary" @click="submitForm" :loading="submitLoading">确 定</el-button>
     </template>
-  </el-dialog>
+  </Dialog>
 
-  <el-dialog v-model="dialogFileView" title="证书附件">
+  <Dialog v-model="dialogFileView" title="证书附件">
     <div
       v-for="(file, index) in fileList"
       :key="index"
@@ -394,7 +413,7 @@
         <el-button type="primary" @click="dialogFileView = false"> 确认 </el-button>
       </div>
     </template>
-  </el-dialog>
+  </Dialog>
 </template>
 
 <script setup lang="ts">
@@ -414,6 +433,9 @@ const userStore = useUserStore()
 
 defineOptions({ name: 'IotQHSECertificate' })
 
+const rootDeptId = 156
+const deptId = useUserStore().getUser.deptId || rootDeptId
+
 const loading = ref(true) // 列表的加载中
 const formLoading = ref(false) // 表单加载中
 const submitLoading = ref(false) // 提交按钮加载中
@@ -828,7 +850,7 @@ onMounted(async () => {
   display: grid;
   grid-template-columns: repeat(4, minmax(0, 1fr));
   gap: 12px;
-  margin-bottom: 16px;
+  margin-bottom: 5px;
 }
 
 .stats-card {