丁烨烨 1 tahun lalu
induk
melakukan
184b33460a
4 mengubah file dengan 381 tambahan dan 5 penghapusan
  1. 1 5
      components.d.ts
  2. 11 0
      src/router/route.ts
  3. 368 0
      src/views/abrylr/index.vue
  4. 1 0
      src/views/zhdpgl/yqzl/yqdl.vue

+ 1 - 5
components.d.ts

@@ -7,6 +7,7 @@ export {}
 /* prettier-ignore */
 declare module 'vue' {
   export interface GlobalComponents {
+    ElAvatar: typeof import('element-plus/es')['ElAvatar']
     ElButton: typeof import('element-plus/es')['ElButton']
     ElCard: typeof import('element-plus/es')['ElCard']
     ElCol: typeof import('element-plus/es')['ElCol']
@@ -20,7 +21,6 @@ declare module 'vue' {
     ElHeader: typeof import('element-plus/es')['ElHeader']
     ElIcon: typeof import('element-plus/es')['ElIcon']
     ElInput: typeof import('element-plus/es')['ElInput']
-    ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
     ElLink: typeof import('element-plus/es')['ElLink']
     ElMain: typeof import('element-plus/es')['ElMain']
     ElMenu: typeof import('element-plus/es')['ElMenu']
@@ -33,17 +33,13 @@ declare module 'vue' {
     ElSelect: typeof import('element-plus/es')['ElSelect']
     ElSkeleton: typeof import('element-plus/es')['ElSkeleton']
     ElSkeletonItem: typeof import('element-plus/es')['ElSkeletonItem']
-    ElStatistic: typeof import('element-plus/es')['ElStatistic']
     ElSubMenu: typeof import('element-plus/es')['ElSubMenu']
     ElSwitch: typeof import('element-plus/es')['ElSwitch']
     ElTable: typeof import('element-plus/es')['ElTable']
     ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
     ElTag: typeof import('element-plus/es')['ElTag']
     ElText: typeof import('element-plus/es')['ElText']
-    ElTimeline: typeof import('element-plus/es')['ElTimeline']
-    ElTimelineItem: typeof import('element-plus/es')['ElTimelineItem']
     ElTimePicker: typeof import('element-plus/es')['ElTimePicker']
-    ElTooltip: typeof import('element-plus/es')['ElTooltip']
     ElUpload: typeof import('element-plus/es')['ElUpload']
     IconCommunity: typeof import('./src/components/icons/IconCommunity.vue')['default']
     IconDocumentation: typeof import('./src/components/icons/IconDocumentation.vue')['default']

+ 11 - 0
src/router/route.ts

@@ -487,6 +487,17 @@ export const routeList:RouterType[] = [
     icon: 'Location',
     addr: 'zhhj/pzpcyz'
   },
+  {
+    path: 'abrylr',
+    name: '安保管理',
+    icon: 'Location',
+  },
+  {
+    path: 'abrylr/index',
+    name: '安保录入',
+    icon: 'Location',
+    addr: 'abrylr/index'
+  },
 ]
 export const useDynamicRoutes: () => RouterType[] = () => {
   routeList.forEach(item => {

+ 368 - 0
src/views/abrylr/index.vue

@@ -0,0 +1,368 @@
+<template>
+  <div class="min-h-screen bg-gray-50 p-8">
+    <div class="mx-auto">
+      <!-- 头部区域 -->
+      <div class="mb-6 flex items-center justify-between">
+        <h1 class="text-2xl font-bold text-gray-900">安保人员管理</h1>
+        <el-button type="primary" class="!rounded-button" @click="handleAdd">
+          <el-icon class="mr-1">
+            <Plus />
+          </el-icon>新增安保人员
+        </el-button>
+      </div>
+
+      <!-- 搜索区域 -->
+      <div class="mb-6 flex gap-4 rounded-lg bg-white p-4 shadow-sm">
+        <el-input v-model="searchForm.name" placeholder="请输入姓名搜索" class="max-w-xs" clearable>
+          <template #prefix>
+            <el-icon>
+              <Search />
+            </el-icon>
+          </template>
+        </el-input>
+        <el-input v-model="searchForm.phone" placeholder="请输入手机号搜索" class="max-w-xs" clearable>
+          <template #prefix>
+            <el-icon>
+              <Phone />
+            </el-icon>
+          </template>
+        </el-input>
+        <el-button type="primary" class="!rounded-button" @click="handleSearch">
+          搜索
+        </el-button>
+        <el-button class="!rounded-button" @click="handleReset">重置</el-button>
+      </div>
+
+      <!-- 表格区域 -->
+      <div class="rounded-lg bg-white p-6 shadow-sm">
+        <el-table :data="tableData" stripe style="width: 100%">
+          <el-table-column type="index" label="序号" />
+          <el-table-column label="头像">
+            <template #default="{ row }">
+              <el-avatar :size="50" :src="row.avatar" />
+            </template>
+          </el-table-column>
+          <el-table-column prop="name" label="姓名" />
+          <el-table-column prop="gender" label="性别" />
+          <el-table-column prop="IDNO" label="证件号码" />
+          <el-table-column prop="phone" label="手机号" width="130" />
+          <el-table-column prop="DEPARTMENT" label="所属部门" />
+          <el-table-column prop="PositionLevel" label="职位级别" />
+          <el-table-column prop="entryTime" label="入职时间" />
+          <el-table-column prop="contractPeriod" label="合同期限" />
+          <el-table-column prop="PPS" label="试用期状态" />
+          <el-table-column prop="DirectSupervisor" label="直属领导" />
+          <el-table-column prop="WorkLocation" label="工作地点" />
+          <el-table-column prop="certName" label="证书名称" />
+          <el-table-column prop="certStatus" label="证书状态">
+            <template #default="{ row }">
+              <el-tag :type="getCertStatusType(row.certStatus)" class="whitespace-nowrap">
+                {{ row.certStatus }}
+              </el-tag>
+            </template>
+          </el-table-column>
+          <el-table-column label="操作" fixed="right" width="150">
+            <template #default="{ row }">
+              <el-button type="primary" link class="!rounded-button" @click="handleEdit(row)">
+                编辑
+              </el-button>
+              <el-button type="danger" link class="!rounded-button" @click="handleDelete(row)">
+                删除
+              </el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+
+        <div class="mt-4 flex    justify-end">
+          <el-pagination v-model:current-page="currentPage" v-model:page-size="pageSize" :total="total"
+            :page-sizes="[10, 20, 30, 50]" layout="total, sizes, prev, pager, next" @size-change="handleSizeChange"
+            @current-change="handleCurrentChange" />
+        </div>
+      </div>
+    </div>
+
+    <!-- 新增/编辑弹窗 -->
+    <el-dialog v-model="dialogVisible" :title="dialogType === 'add' ? '新增安保人员' : '编辑安保人员'" width="600px">
+      <el-form ref="formRef" :model="form" :rules="rules" label-width="100px" class="mt-4">
+        <el-form-item label="姓名" prop="name">
+          <el-input v-model="form.name" placeholder="请输入姓名" />
+        </el-form-item>
+        <el-form-item label="手机号" prop="phone">
+          <el-input v-model="form.phone" placeholder="请输入手机号" />
+        </el-form-item>
+        <el-form-item label="出生日期" prop="certDate">
+          <el-date-picker v-model="form.certDate" type="date" placeholder="出生日期"
+            :default-value="new Date(2010, 9, 1)" />
+        </el-form-item>
+      </el-form>
+
+      <template #footer>
+        <span class="dialog-footer">
+          <el-button class="!rounded-button" @click="dialogVisible = false">取消</el-button>
+          <el-button type="primary" class="!rounded-button" @click="handleSubmit">确认</el-button>
+        </span>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script lang="ts" setup>
+import { ref, reactive } from 'vue';
+import {
+  Plus,
+  Search,
+  Phone,
+  Upload,
+} from '@element-plus/icons-vue';
+import type { FormInstance, FormRules } from 'element-plus';
+import { clientDel, clientGet, clientPost, clientPut } from '@/utils/request.ts'
+import type { BaseResponse } from '@/utils/type.ts'
+
+
+interface IntroductItem {
+  id: string;
+  parkName: string;
+  remarks: string;
+  totalArea: string;
+  enteredCompany: string;
+  numberBuildings: string;
+  parkPersonnel: string;
+  standardFactory: string;
+  parkingLot: string;
+  productionLand: string;
+  officeLand: string;
+  greenVegetation: string;
+  infrastructure: string;
+  developmentArea: string;
+  createTime: string;
+  businessType: string;
+  updateTime: string;
+  isEnable: number;
+  filePath?: string;
+  file?: File;
+}
+
+interface IntroductResponse extends BaseResponse {
+  data: IntroductItem[]
+}
+const searchForm = reactive({
+  name: '',
+  phone: '',
+});
+
+const tableData = ref([
+  {
+    avatar: 'https://ai-public.mastergo.com/ai/img_res/ab6b2a2731dd9309532c1d31e77e37d8.jpg',
+    name: '邵建国',
+    gender: '男',
+    IDNO: '430524199808084151',
+    DEPARTMENT: '保安一部',
+    PositionLevel: '二级',
+    entryTime: '2025-01-02',
+    contractPeriod: '一年',
+    PPS: '实习',
+    DirectSupervisor: '张三',
+    WorkLocation: '综合楼',
+    phone: '13812345678',
+    certName: '安保人员资格证',
+    certStatus: '有效',
+  },
+  {
+    avatar: 'https://ai-public.mastergo.com/ai/img_res/adb4757a51078fd93278243eabcbf90a.jpg',
+    name: '李志强',
+    gender: '男',
+    IDNO: '430524199808084151',
+    DEPARTMENT: '保安一部',
+    PositionLevel: '二级',
+    entryTime: '2025-01-02',
+    contractPeriod: '一年',
+    PPS: '实习',
+    DirectSupervisor: '张三',
+    WorkLocation: '综合楼',
+    phone: '13812345678',
+    certName: '安保人员资格证',
+    certStatus: '有效',
+  },
+  {
+    avatar: 'https://ai-public.mastergo.com/ai/img_res/4e3ef5f71c53f38ea1cf35689071b390.jpg',
+    name: '王秀英',
+    gender: '男',
+    IDNO: '430524199808084151',
+    DEPARTMENT: '保安一部',
+    PositionLevel: '二级',
+    entryTime: '2025-01-02',
+    contractPeriod: '一年',
+    PPS: '实习',
+    DirectSupervisor: '张三',
+    WorkLocation: '综合楼',
+    phone: '13812345678',
+    certName: '安保人员资格证',
+    certStatus: '有效',
+  },
+]);
+
+const currentPage = ref(1);
+const pageSize = ref(10);
+const total = ref(100);
+
+const dialogVisible = ref(false);
+const dialogType = ref<'add' | 'edit'>('add');
+const formRef = ref<FormInstance>();
+
+const form = reactive({
+  avatar: '',
+  name: '',
+  phone: '',
+  cert: '',
+  certDate: [],
+});
+
+
+const getData = async () => {
+  const res = await clientGet<null, IntroductResponse>('/park/securityPersonnel/getList')
+  if (res.code === 200) {
+    console.log("获取到数据:", res.data)
+  }
+}
+
+getData();
+
+const rules: FormRules = {
+  name: [{ required: true, message: '请输入姓名', trigger: 'blur' }],
+  phone: [
+    { required: true, message: '请输入手机号', trigger: 'blur' },
+    {
+      pattern: /^1[3-9]\d{9}$/,
+      message: '请输入正确的手机号',
+      trigger: 'blur',
+    },
+  ],
+  cert: [{ required: true, message: '请上传证书', trigger: 'change' }],
+  certDate: [{ required: true, message: '请选择证书有效期', trigger: 'change' }],
+};
+
+const handleSearch = () => {
+  // 实现搜索逻辑
+};
+
+const handleReset = () => {
+  searchForm.name = '';
+  searchForm.phone = '';
+};
+
+const handleAdd = () => {
+  dialogType.value = 'add';
+  dialogVisible.value = true;
+  Object.assign(form, {
+    avatar: '',
+    name: '',
+    phone: '',
+    cert: '',
+    certDate: [],
+  });
+
+
+  // try {
+  //   const formData = new FormData();
+  //   Object.entries(addForm.value).forEach(([key, value]) => {
+  //     if (key === 'file' && value instanceof File) {
+  //       formData.append('file', value);
+  //     } else {
+  //       formData.append(key, String(value));
+  //     }
+  //   });
+
+  //   const res = await clientPost<FormData, BaseResponse>('/park/parkInfo/save', formData, {
+  //     headers: {
+  //       'Content-Type': 'multipart/form-data',
+  //     },
+  //   });
+
+  //   if (res.code === 200) {
+  //     getData();
+  //     dialogVisible.value = false;
+  //     ElMessage.success('新增成功');
+  //     addForm.value = initData;
+  //   }
+  // } catch (error) {
+  //   console.error('新增失败', error);
+  //   ElMessage.error('新增失败');
+  // }
+};
+
+const handleEdit = (row: any) => {
+  dialogType.value = 'edit';
+  dialogVisible.value = true;
+  Object.assign(form, row);
+};
+
+const handleDelete = (row: any) => {
+  ElMessageBox.confirm('确认删除该安保人员?', '提示', {
+    confirmButtonText: '确定',
+    cancelButtonText: '取消',
+    type: 'warning',
+  }).then(() => {
+    ElMessage({
+      type: 'success',
+      message: '删除成功',
+    });
+  });
+};
+
+const handleSizeChange = (val: number) => {
+  pageSize.value = val;
+};
+
+const handleCurrentChange = (val: number) => {
+  currentPage.value = val;
+};
+
+const handleAvatarSuccess = (response: any) => {
+  form.avatar = response.url;
+};
+
+const handleCertSuccess = (response: any) => {
+  form.cert = response.url;
+};
+
+const handleSubmit = async () => {
+  if (!formRef.value) return;
+  await formRef.value.validate((valid) => {
+    if (valid) {
+      ElMessage({
+        type: 'success',
+        message: dialogType.value === 'add' ? '添加成功' : '修改成功',
+      });
+      dialogVisible.value = false;
+    }
+  });
+};
+
+const getCertStatusType = (status: string) => {
+  const statusMap: Record<string, string> = {
+    有效: 'success',
+    即将过期: 'warning',
+    已过期: 'danger',
+  };
+  return statusMap[status] || 'info';
+};
+</script>
+
+
+<style scoped>
+.avatar-uploader {
+  width: 100px;
+  height: 100px;
+}
+
+.avatar-uploader-icon {
+  font-size: 28px;
+  width: 100px;
+  height: 100px;
+}
+
+.avatar-image {
+  width: 100%;
+}
+</style>
+

+ 1 - 0
src/views/zhdpgl/yqzl/yqdl.vue

@@ -118,6 +118,7 @@ const closeDetail = () => {
           <x class="h-5 w-5" />
         </button>
 
+
         <div class="text-center pt-2 pb-4">
           <h3 class="text-lg font-bold">设备详情</h3>
         </div>