Anthony 5 dias atrás
pai
commit
ac17300e9b

BIN
public/resources/face1.png


BIN
public/resources/people1.jfif


+ 175 - 0
src/views/bdglregular/regularinfo2/index.vue

@@ -0,0 +1,175 @@
+<template>
+  <div class="app-container">
+    <!-- 顶部按钮区 -->
+    <div class="mb8">
+      <el-button type="primary" @click="handleAdd">
+        {{ queryParams.caoZuoType === '1' ? '加分录入' : '减分录入' }}
+      </el-button>
+      <el-button type="danger" @click="batchDelete">删除</el-button>
+      <el-select v-model="queryParams.danWei" placeholder="请选择受检单位" style="margin-left:10px;">
+        <el-option label="单位A" value="单位A" />
+        <el-option label="单位B" value="单位B" />
+      </el-select>
+      <el-select v-model="queryParams.status" placeholder="请选择状态" style="margin-left:10px;">
+        <el-option label="已审批" value="1" />
+        <el-option label="未审批" value="0" />
+      </el-select>
+      <el-button style="margin-left:10px;" @click="resetQuery">重置</el-button>
+    </div>
+
+    <!-- 加分/减分切换 -->
+    <div class="mb8">
+      <el-radio-group v-model="queryParams.caoZuoType" @change="caoZuoTypefun">
+        <el-radio-button label="1">加分</el-radio-button>
+        <el-radio-button label="0">减分</el-radio-button>
+      </el-radio-group>
+    </div>
+
+    <!-- 表格 -->
+    <el-table :data="tableData" border style="width: 100%">
+      <el-table-column type="selection" width="55" />
+      <el-table-column prop="id" label="序号" width="60" />
+      <el-table-column prop="danWei" label="单位" width="120" />
+      <el-table-column prop="leiXing" label="类型" width="120" />
+      <el-table-column prop="jianChaShiJian" label="检查时间" width="180" />
+      <el-table-column prop="jianChaDiDian" label="检查地点" width="120" />
+      <el-table-column label="分值" width="80">
+        <template slot-scope="scope">
+          <span :style="{ color: scope.row.fenZhi > 0 ? 'green' : 'red' }">
+            {{ scope.row.fenZhi }}
+          </span>
+        </template>
+      </el-table-column>
+      <el-table-column prop="shiYou" label="事由" />
+      <el-table-column label="操作" align="center" width="200">
+        <template slot-scope="scope">
+          <el-button size="mini" type="primary" @click="handleEdit(scope.row)">
+            修改
+          </el-button>
+          <el-button size="mini" type="danger" @click="handleDelete(scope.row)">
+            删除
+          </el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <!-- 分页 -->
+    <div style="margin-top: 20px; text-align:right;">
+      <el-pagination
+        background
+        layout="prev, pager, next"
+        :total="tableData.length"
+        :page-size="10"
+      />
+    </div>
+
+    <!-- 修改弹窗 -->
+    <el-dialog title="修改记录" :visible.sync="editDialogVisible" width="600px">
+      <el-form :model="editForm" label-width="100px">
+        <el-form-item label="单位">
+          <el-input v-model="editForm.danWei" />
+        </el-form-item>
+        <el-form-item label="类型">
+          <el-select v-model="editForm.leiXing">
+            <el-option label="日常检查" value="日常检查" />
+            <el-option label="专项检查" value="专项检查" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="检查时间">
+          <el-date-picker
+            v-model="editForm.jianChaShiJian"
+            type="datetime"
+            placeholder="选择时间"
+          />
+        </el-form-item>
+        <el-form-item label="检查地点">
+          <el-input v-model="editForm.jianChaDiDian" />
+        </el-form-item>
+        <el-form-item label="分值">
+          <el-input-number v-model="editForm.fenZhi" :min="-10" :max="10" />
+        </el-form-item>
+        <el-form-item label="事由">
+          <el-input v-model="editForm.shiYou" type="textarea" />
+        </el-form-item>
+      </el-form>
+
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="editDialogVisible = false">取 消</el-button>
+        <el-button type="primary" @click="submitEdit">保 存</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      queryParams: {
+        caoZuoType: "1", // 1=加分, 0=减分
+        danWei: "",
+        status: "",
+      },
+      tableData: [
+        {
+          id: 1,
+          danWei: "单位A",
+          leiXing: "日常检查",
+          jianChaShiJian: "2025-09-04 16:38:13",
+          jianChaDiDian: "11111",
+          fenZhi: 3,
+          shiYou: "表现良好",
+        },
+      ],
+      editDialogVisible: false,
+      editForm: {
+        id: null,
+        danWei: "",
+        leiXing: "",
+        jianChaShiJian: "",
+        jianChaDiDian: "",
+        fenZhi: 0,
+        shiYou: "",
+      },
+    };
+  },
+  methods: {
+    caoZuoTypefun() {
+      this.getList();
+    },
+    getList() {
+      console.log("获取数据,操作类型:", this.queryParams.caoZuoType);
+    },
+    resetQuery() {
+      this.queryParams = { caoZuoType: "1", danWei: "", status: "" };
+      this.getList();
+    },
+    // 新增(这里只是占位,等你接后端接口)
+    handleAdd() {
+      this.$message.info("这里是新增功能,可以弹出新增表单");
+    },
+    // 修改
+    handleEdit(row) {
+      this.editForm = { ...row };
+      this.editDialogVisible = true;
+    },
+    submitEdit() {
+      const index = this.tableData.findIndex((item) => item.id === this.editForm.id);
+      if (index !== -1) {
+        this.tableData.splice(index, 1, { ...this.editForm });
+      }
+      this.editDialogVisible = false;
+      this.$message.success("修改成功!");
+    },
+    // 删除
+    handleDelete(row) {
+      this.tableData = this.tableData.filter((item) => item.id !== row.id);
+      this.$message.success("删除成功!");
+    },
+    // 批量删除
+    batchDelete() {
+      this.$message.warning("批量删除逻辑请自己实现~");
+    },
+  },
+};
+</script>

+ 0 - 0
src/views/demo/shijian.vue


+ 218 - 0
src/views/demo/xinxi.vue

@@ -0,0 +1,218 @@
+<template>
+  <div class="face-management">
+    <div class="header">
+      <h2>人脸管理</h2>
+      <el-button type="primary" @click="openAddDialog">点击添加人员信息</el-button>
+    </div>
+
+    <el-table
+      :data="persons"
+      style="width: 100%"
+      border
+      v-loading="loading"
+    >
+      <el-table-column prop="index" label="#" width="60">
+        <template slot-scope="scope">{{ scope.$index + 1 }}</template>
+      </el-table-column>
+
+      <el-table-column prop="name" label="姓名" width="140" />
+      <el-table-column prop="idCard" label="身份证号" min-width="180" />
+      <el-table-column prop="faceCard" label="人脸卡号" width="160" />
+      <el-table-column prop="phone" label="联系电话" width="140" />
+      <el-table-column prop="department" label="部门/单位" min-width="140" />
+
+      <el-table-column label="头像" width="120">
+        <template slot-scope="scope">
+          <img v-if="scope.row.photoUrl" :src="scope.row.photoUrl" class="avatar" />
+          <span v-else class="no-avatar">无</span>
+        </template>
+      </el-table-column>
+
+      <el-table-column label="操作" fixed="right" width="160">
+        <template slot-scope="scope">
+          <el-button type="text" size="small" @click="openEditDialog(scope.$index, scope.row)">修改</el-button>
+          <el-button type="text" size="small" style="color:#f56c6c" @click="removePerson(scope.$index)">删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <!-- Add / Edit Dialog -->
+    <el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="600px">
+      <el-form :model="form" :rules="rules" ref="personForm" label-width="110px">
+        <el-form-item label="姓名" prop="name">
+          <el-input v-model="form.name" placeholder="请输入姓名" />
+        </el-form-item>
+
+        <el-form-item label="身份证号" prop="idCard">
+          <el-input v-model="form.idCard" placeholder="请输入身份证号" />
+        </el-form-item>
+
+        <el-form-item label="人脸卡号" prop="faceCard">
+          <el-input v-model="form.faceCard" 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="department">
+          <el-input v-model="form.department" placeholder="请输入部门或单位" />
+        </el-form-item>
+
+        <el-form-item label="头像">
+          <el-upload
+            class="avatar-uploader"
+            action=""
+            :show-file-list="false"
+            :before-upload="beforeAvatarUpload"
+            :on-change="handleAvatarChange"
+            :auto-upload="false"
+          >
+            <img v-if="form.photoUrl" :src="form.photoUrl" class="avatar" />
+            <i v-else class="el-icon-plus avatar-upload-icon"></i>
+          </el-upload>
+          <div style="margin-top:8px;color:#999;font-size:12px">建议人脸照片:正脸、白底、jpg/png</div>
+        </el-form-item>
+
+      </el-form>
+
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="dialogVisible = false">取 消</el-button>
+        <el-button type="primary" @click="submitPerson">确 定</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+export default {
+  name: 'FaceManagement',
+  data() {
+    return {
+      loading: false,
+      persons: [
+        // 示例数据(前端暂时写死)
+        {
+          name: '张三',
+          idCard: '110101199001011234',
+          faceCard: 'FC-0001',
+          phone: '13800001111',
+          department: '营部',
+          photoUrl: '',
+        },
+        {
+          name: '李四',
+          idCard: '110101198512129876',
+          faceCard: 'FC-0002',
+          phone: '13800002222',
+          department: '警卫连',
+          photoUrl: '',
+        },
+      ],
+
+      dialogVisible: false,
+      isEdit: false,
+      editIndex: -1,
+      form: {
+        name: '',
+        idCard: '',
+        faceCard: '',
+        phone: '',
+        department: '',
+        photoUrl: '',
+      },
+      rules: {
+        name: [{ required: true, message: '请输入姓名', trigger: 'blur' }],
+        idCard: [{ required: true, message: '请输入身份证号', trigger: 'blur' }],
+        faceCard: [{ required: true, message: '请输入人脸卡号', trigger: 'blur' }],
+      },
+    }
+  },
+  computed: {
+    dialogTitle() {
+      return this.isEdit ? '修改人员信息' : '添加人员信息'
+    }
+  },
+  methods: {
+    openAddDialog() {
+      this.isEdit = false
+      this.editIndex = -1
+      this.resetForm()
+      this.dialogVisible = true
+      this.$nextTick(() => { this.$refs.personForm && this.$refs.personForm.clearValidate() })
+    },
+    openEditDialog(index, row) {
+      this.isEdit = true
+      this.editIndex = index
+      this.form = Object.assign({}, row)
+      this.dialogVisible = true
+      this.$nextTick(() => { this.$refs.personForm && this.$refs.personForm.clearValidate() })
+    },
+    removePerson(index) {
+      this.$confirm('确定删除该人员信息吗?', '提示', {
+        confirmButtonText: '删除',
+        cancelButtonText: '取消',
+        type: 'warning'
+      }).then(() => {
+        this.persons.splice(index, 1)
+        this.$message({ type: 'success', message: '删除成功' })
+      }).catch(() => {})
+    },
+    submitPerson() {
+      this.$refs.personForm.validate((valid) => {
+        if (!valid) return
+        if (this.isEdit && this.editIndex > -1) {
+          this.$set(this.persons, this.editIndex, Object.assign({}, this.form))
+          this.$message({ type: 'success', message: '修改成功' })
+        } else {
+          this.persons.push(Object.assign({}, this.form))
+          this.$message({ type: 'success', message: '添加成功' })
+        }
+        this.dialogVisible = false
+      })
+    },
+    resetForm() {
+      this.form = {
+        name: '',
+        idCard: '',
+        faceCard: '',
+        phone: '',
+        department: '',
+        photoUrl: '',
+      }
+    },
+
+    // avatar upload handlers (client-side preview only)
+    beforeAvatarUpload(file) {
+      const isJPGorPNG = file.type === 'image/jpeg' || file.type === 'image/png'
+      const isLt2M = file.size / 1024 / 1024 < 2
+
+      if (!isJPGorPNG) {
+        this.$message.error('上传头像图片只能是 JPG/PNG 格式!')
+      }
+      if (!isLt2M) {
+        this.$message.error('上传头像图片大小不能超过 2MB!')
+      }
+      return isJPGorPNG && isLt2M
+    },
+    handleAvatarChange(file) {
+      // 生成本地预览(不上传)
+      const reader = new FileReader()
+      reader.onload = (e) => {
+        this.form.photoUrl = e.target.result
+      }
+      reader.readAsDataURL(file.raw)
+    }
+  }
+}
+</script>
+
+<style scoped>
+.face-management { padding: 18px; background: #fff; border-radius: 6px; }
+.header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px; }
+.avatar { width: 56px; height: 56px; border-radius: 4px; object-fit: cover; }
+.no-avatar { color: #999; }
+.avatar-uploader { display: inline-block; width: 56px; height: 56px; border: 1px dashed #d9d9d9; border-radius: 4px; text-align: center; line-height: 56px; }
+.avatar-upload-icon { font-size: 28px; color: #c0c4cc; }
+.dialog-footer { text-align: right; }
+</style>

+ 198 - 0
src/views/doormanManage/carManage/index.vue

@@ -0,0 +1,198 @@
+<template>
+  <div>
+    <!-- 查询区 -->
+    <el-card style="background-color: transparent">
+      <el-form :inline="true" :model="searchForm" label-width="80px">
+        <el-form-item class="che" label="车牌号码">
+          <el-input v-model="searchForm.plateNo" placeholder="请输入车牌号码" />
+        </el-form-item>
+        <el-form-item label="车辆类型">
+          <el-select v-model="searchForm.type" placeholder="全部" clearable>
+            <el-option label="小型车" value="small" />
+            <el-option label="大型车" value="large" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="车主姓名">
+          <el-input v-model="searchForm.ownerName" placeholder="请输入车主姓名" />
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="fetchCars">查询</el-button>
+          <el-button @click="resetForm">重置</el-button>
+        </el-form-item>
+      </el-form>
+    </el-card>
+
+
+    <!-- 操作按钮 -->
+    <div style="margin: 10px 0;">
+      <el-button type="primary" @click="addCar">添加</el-button>
+      <el-button>导入</el-button>
+      <el-button>导出</el-button>
+    </div>
+
+    <!-- 数据展示表格 -->
+    <el-table :data="carList" border style="width: 100%;" height="500">
+      <el-table-column prop="ownerName" label="车主姓名" width="120"/>
+      <el-table-column prop="plateNumber" label="车牌号码" width="120"/>
+      <el-table-column prop="orgName" label="所属组织" width="180"/>
+      <el-table-column prop="isTemporary" label="是否临时车" width="120">
+        <template #default="scope">
+          {{ scope.row.isTemporary ? '是' : '否' }}
+        </template>
+      </el-table-column>
+      <el-table-column prop="carGroup" label="车辆群组" width="120"/>
+      <el-table-column prop="validUntil" label="有效期" width="150"/>
+      <el-table-column label="操作" width="150">
+        <template #default="scope">
+          <el-button type="text" size="small" @click="editCar(scope.row)">编辑</el-button>
+          <el-button type="text" size="small" @click="deleteCar(scope.row)">删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <!-- 添加 / 编辑 对话框 -->
+    <el-dialog :visible.sync="dialogVisible" title="车辆信息">
+      <el-form :model="form" label-width="100px">
+        <el-form-item  label="车主姓名" class="owner-label">
+          <el-input v-model="form.ownerName" />
+        </el-form-item>
+        <el-form-item label="车牌号码" class="owner-label">
+          <el-input v-model="form.plateNumber" />
+        </el-form-item>
+        <el-form-item label="所属组织" class="owner-label">
+          <el-input v-model="form.orgName" />
+        </el-form-item>
+        <el-form-item label="车辆群组" class="owner-label">
+          <el-input v-model="form.carGroup" />
+        </el-form-item>
+<!--        <el-form-item label="有效期" class="owner-label">-->
+<!--          <el-date-picker v-model="form.validUntil" type="date" placeholder="选择日期"/>-->
+<!--        </el-form-item>-->
+        <!-- 有效期逻辑:仅在临时车辆时显示日期选择 -->
+        <el-form-item label="是否为临时车辆" class="owner-label">
+          <el-select v-model="form.isTemporary" placeholder="请选择">
+            <el-option label="是" :value="true" />
+            <el-option label="否" :value="false" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="有效期" class="owner-label" v-if="form.isTemporary">
+          <el-date-picker v-model="form.validUntil" type="date" placeholder="选择有效日期"/>
+        </el-form-item>
+        <el-form-item label="有效期" class="owner-label" v-else>
+          <el-input value="永久有效" disabled />
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <el-button @click="dialogVisible = false">取消</el-button>
+        <el-button type="primary" @click="saveCar">保存</el-button>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import request from "@/utils/request";
+
+export default {
+  data() {
+    return {
+      searchForm: {
+        plateNo: "",
+        type: "",
+        ownerName: "",
+        isTemporary: false,
+        // plateNumber: "",
+        // orgName: "",     // 所属组织
+        // carGroup: "",   // 车辆组群
+        // validUntil: "", // 有效期
+        // createTime: "",
+      },
+      carList: [], // 车辆数据
+      dialogVisible: false,
+      dialogMode: "add",   // add / edi
+      form: {} // 添加/编辑的表单数据
+    }
+  },
+  created() {
+    // 页面加载时自动拉取第一页数据
+    this.fetchCars()
+  },
+  methods: {
+    fetchCars() {
+      // TODO: 请求后端接口,获取数据
+      request({
+        url: "/car/info/list",
+        method: "get",
+      }).then(res => {
+        console.log("获取res数据", res)
+        this.carList = res
+        console.log("获取数据", this.carList)
+      })
+    },
+    resetForm() {
+      this.searchForm = { plateNo: "", type: "", ownerName: "" }
+      this.fetchCars()
+    },
+    addCar() {
+      this.form = {
+        isTemporary: false,  // ✅ 默认值
+        validUntil: null
+      }
+      this.dialogMode = "add"
+      this.dialogVisible = true
+    },
+    editCar(row) {
+      this.form = { ...row }
+      this.form.isTemporary = row.isTemporary === true || row.isTemporary === "true"
+      this.dialogMode = "edit"
+      this.dialogVisible = true
+    },
+    deleteCar(row) {
+      this.$confirm("确定删除该车辆吗?", "提示", { type: "warning" })
+        .then(() => {
+          request({
+            url: `/car/info/delete/${row.id}`,
+            method: "delete",
+            // data: { id: row.id }
+            }).then(res => {
+            this.fetchCars()
+            console.log("删除成功", res)
+          })
+          // TODO: 调用删除接口
+          // this.fetchCars()
+          console.log("删除车辆:", row)
+        })
+    },
+    saveCar() {
+      this.form.isTemporary = this.form.isTemporary === true || this.form.isTemporary === "true"
+
+      // 如果不是临时车,清空有效期
+      if (!this.form.isTemporary) {
+        this.form.validUntil = null
+      }
+      const url = this.dialogMode === "edit"
+        ? `/car/info/update`
+        : "/car/info/add"
+      const method = this.dialogMode === "edit" ? "put" : "post"
+      request({
+        url,
+        method,
+        data: this.form
+      }).then(res => {
+        console.log("保存成功", res)
+        this.fetchCars()
+        this.dialogVisible = false
+      })
+      // TODO: 保存接口
+      console.log("保存车辆信息:", this.form)
+      // this.fetchCars()
+    }
+  }
+}
+</script>
+
+<style scoped>
+
+</style>
+
+

+ 267 - 0
src/views/doormanManage/car_infoManage/index.vue

@@ -0,0 +1,267 @@
+<template>
+  <div class="dashboard">
+    <el-row :gutter="20">
+      <!-- 左上角:设备状态 -->
+      <el-col :span="12">
+        <el-card>
+<!--          <el-tabs v-model=" chooseDevice" type="card" style="float:left;">-->
+<!--            <el-tab-pane label="设备1" name="device1"></el-tab-pane>-->
+<!--            <el-tab-pane label="设备2" name="device2"></el-tab-pane>-->
+<!--          </el-tabs>-->
+          <el-button
+            v-if="!deviceStatus.ok"
+            type="danger"
+            size="mini"
+            style="float:right;"
+            @click="reconnectDevice">
+            重新连接
+          </el-button>
+          <div slot="header" class="clearfix">
+            <span>设备状态</span>
+          </div>
+          <div v-if="deviceStatus.ok" style="text-align:center; padding:20px;">
+            <el-result icon="success" title="运行正常"></el-result>
+          </div>
+          <div v-else style="text-align:center; padding:20px;">
+            <el-result icon="error" title="连接失败"></el-result>
+          </div>
+
+        </el-card>
+      </el-col>
+
+      <!-- 右上角:远程控制 -->
+      <el-col :span="12">
+        <el-card>
+          <div slot="header" class="clearfix">
+            <span>远程控制</span>
+            <el-button type="primary" size="mini" style="float:right;" @click="toggleDoor">
+              {{ doorOpen ? '关门' : '开门' }}
+            </el-button>
+          </div>
+          <el-tabs v-model="activeDevice">
+            <el-tab-pane
+              v-for="d in devices"
+              :key="d.id"
+              :label="d.name"
+              :name="d.id">
+              <div style="background:#000; height:200px; display:flex; align-items:center; justify-content:center; color:white;">
+                {{ d.name }} 视频流
+              </div>
+            </el-tab-pane>
+          </el-tabs>
+        </el-card>
+      </el-col>
+    </el-row>
+
+    <!--    <el-row :gutter="20" style="margin-top:20px;">-->
+    <!--      &lt;!&ndash; 左下角:人员信息 &ndash;&gt;-->
+    <!--      <el-col :span="12">-->
+    <!--        <el-card>-->
+    <!--          <div slot="header">人员信息</div>-->
+    <!--          <p>内部人员:{{ people.internal }}</p>-->
+    <!--          <p>临时访问:{{ people.temporary }}</p>-->
+    <!--          <p>内部人脸:{{ faces.internal }}</p>-->
+    <!--          <p>外部人脸:{{ faces.external }}</p>-->
+    <!--        </el-card>-->
+    <!--      </el-col>-->
+    <!--    </el-row>-->
+    <el-col :span="12">
+      <el-card shadow="hover" class="people-card">
+        <h2 class="section-title">车辆信息总览</h2>
+        <div class="people-info">
+          <div class="info-block">
+            <img src="/resources/people1.jfif" class="info-icon" />
+            <p>人员总数</p>
+            <span>{{ carCount }}</span>
+          </div>
+          <div class="info-block">
+            <!--          <img src="/resources/face1.png" class="info-icon" />-->
+            <p>内部人员总数</p>
+            <span>{{ registeredCount_car }}</span>
+          </div>
+          <div class="info-block">
+            <!--          <img src="/resources/face1.png" class="info-icon" />-->
+            <p>临时访问人员总数</p>
+            <span>{{ unregisteredCount_car }}</span>
+          </div>
+        </div>
+        <!--      <el-row :gutter="20">-->
+        <!--        <el-col :span="6">-->
+        <!--          <el-card shadow="hover" class="overview-card">-->
+        <!--            <img src="/public/resources/people1.jfif" class="card-img" />-->
+        <!--            <div class="card-text">人员信息</div>-->
+        <!--          </el-card>-->
+        <!--        </el-col>-->
+
+        <!--        <el-col :span="6">-->
+        <!--          <el-card shadow="hover" class="overview-card">-->
+        <!--            <img src="/public/resources/face1.png" class="card-img" />-->
+        <!--            <div class="card-text">人脸信息</div>-->
+        <!--          </el-card>-->
+        <!--        </el-col>-->
+
+        <!--        <el-col :span="6">-->
+        <!--          <el-card shadow="hover" class="overview-card">-->
+        <!--            <img src="/public/resources/device.png" class="card-img" />-->
+        <!--            <div class="card-text">设备信息</div>-->
+        <!--          </el-card>-->
+        <!--        </el-col>-->
+
+        <!--        <el-col :span="6">-->
+        <!--          <el-card shadow="hover" class="overview-card">-->
+        <!--            <img src="/public/resources/other.png" class="card-img" />-->
+        <!--            <div class="card-text">其他信息</div>-->
+        <!--          </el-card>-->
+        <!--        </el-col>-->
+        <!--      </el-row>-->
+      </el-card>
+<!--      <el-card shadow="hover" class="face-card">-->
+<!--        <h2 class="section-title">人脸信息总览</h2>-->
+<!--        <div class="face-info">-->
+<!--          <div class="info-block">-->
+<!--            <img src="/resources/face1.png" class="info-icon" />-->
+<!--            <p>人员总数</p>-->
+<!--            <span>{{ faceCount }}</span>-->
+<!--          </div>-->
+<!--          <div class="info-block">-->
+
+<!--            <p>内部人脸总数</p>-->
+<!--            <span>{{ registeredCount_face }}</span>-->
+<!--          </div>-->
+<!--          <div class="info-block">-->
+<!--            &lt;!&ndash;            <img src="/resources/face1.png" class="info-icon" />&ndash;&gt;-->
+<!--            <p>临时访问人脸总数</p>-->
+<!--            <span>{{ unregisteredCount_face }}</span>-->
+<!--          </div>-->
+<!--        </div>-->
+<!--      </el-card>-->
+    </el-col>
+
+    <!--      &lt;!&ndash; 右下角:实时事件 &ndash;&gt;-->
+    <el-col :span="12">
+      <el-card>
+        <div slot="header">实时事件</div>
+        <el-table :data="events" size="mini" height="400" border>
+          <el-table-column prop="eventTime" label="时间" width="150"/>
+          <el-table-column prop="ownerName" label="车主姓名" width="100"/>
+          <el-table-column prop="plateNumber" label="车牌号码" width="120" />
+          <el-table-column prop="eventType" label="进出类型"/>
+        </el-table>
+      </el-card>
+    </el-col>
+
+  </div>
+</template>
+
+<script>
+import request from "@/utils/request";
+
+export default {
+  name: "Dashboard",
+  data() {
+    return {
+      deviceStatus: {
+        device1: { ok: true },
+        device2: { ok: false }
+      },
+      doorOpen: false,
+      chooseDevice: "device1",
+      activeDevice: '1',
+      devices: [
+        { id: '1', name: '进门车辆监控' },
+        { id: '2', name: '出门闸道监控' }
+      ],
+      people: { internal: 10, temporary: 2 },
+      faces: { internal: 8, external: 5 },
+
+      events: [
+      ],
+      // total: 0,
+      carCount: 0,
+      registeredCount_car: 0,
+      unregisteredCount_car: 0,
+      registeredCount_face: 0,
+      unregisteredCount_face: 0,
+    }
+  },
+  created() {
+    // 页面加载时自动拉取第一页数据
+    this.fetchData()
+    this.peopleData()
+    this.fetchPeople()
+  },
+  methods: {
+    fetchData() {
+      request({
+        url: "/car/event/log/list",
+        method: "get",
+      }).then(res => {
+
+        this.events = res.records || []
+        console.log("数据",res)
+        console.log("总条数",res.total)
+        this.total = res.total || 0
+      })
+    },
+    peopleData() {
+      request({
+        url: "/car/info/total",
+        method: "get",
+      }).then(res => {
+        console.log("接口返回:", res)
+        // this.carCount = res.total || []
+        this.carCount = res
+        console.log("人员总数...............",res)
+
+      })
+    },
+    reconnectDevice() {
+      // TODO: 调后端接口
+      this.deviceStatus.ok = true
+    },
+    toggleDoor() {
+      // TODO: 调后端接口
+      this.doorOpen = !this.doorOpen
+    },
+
+    fetchPeople() {
+      this.loading = true
+      request({
+        url: `/car/info/list/`,  // ✅ 模板字符串
+        method: 'GET',
+      }).then(res => {
+
+        // // 内部人员数量 (is_temporary == 0)
+        // this.internalCount = data.filter(p => p.is_temporary == 0).length
+        //
+        // // 临时访问人员数量 (is_temporary == 1)
+        // this.tempCount = data.filter(p => p.is_temporary == 1).length
+        console.log("车辆信息返回:", res)
+        let data = res
+        this.peopleList = data
+        console.log("车辆信息:", this.peopleList)
+        console.log("第一条车辆数据:", data[0])
+        // 内部车辆数量 (is_temporary == 0)
+        this.registeredCount_car = data.filter(p => p.isTemporary  === false).length
+
+        // 临时访问车辆数量 (is_temporary == 1)
+        this.unregisteredCount_car = data.filter(p => p.isTemporary  === true).length
+        console.log("内部人员:", this.registeredCount_car)
+
+      }).finally(() => { this.loading = false })
+    },
+  }
+}
+</script>
+
+<style scoped>
+.dashboard {
+  padding: 20px;
+}
+.info-icon {
+  width: 60px;         /* 图片宽度 */
+  height: 60px;        /* 图片高度 */
+  object-fit: contain; /* 保持比例 */
+  margin-bottom: 8px;  /* 图片和文字之间的间距 */
+}
+</style>

+ 96 - 0
src/views/militaryvehicleManagement/thecarStatistics/index.vue

@@ -0,0 +1,96 @@
+<template>
+  <div class="app-container">
+    <!-- 顶部统计卡片 -->
+    <el-row :gutter="20" class="mb-4">
+      <el-col :span="12">
+        <el-card shadow="hover">
+          <div>
+            <h3>军车统计</h3>
+            <p>总数:{{ stats.military.total }}</p>
+            <p>在位:{{ stats.military.inCamp }}</p>
+            <p>外出:{{ stats.military.outCamp }}</p>
+          </div>
+        </el-card>
+      </el-col>
+      <el-col :span="12">
+        <el-card shadow="hover">
+          <div>
+            <h3>私家车统计</h3>
+            <p>总数:{{ stats.private.total }}</p>
+            <p>在位:{{ stats.private.inCamp }}</p>
+            <p>外出:{{ stats.private.outCamp }}</p>
+          </div>
+        </el-card>
+      </el-col>
+    </el-row>
+
+    <!-- 表格展示 -->
+    <el-card shadow="always">
+      <div class="table-header">
+        <span>车辆实时在位情况</span>
+        <el-button type="primary" size="small" @click="refreshData">
+          刷新数据
+        </el-button>
+      </div>
+
+      <el-table :data="vehicleList" border style="width: 100%; margin-top: 10px">
+        <el-table-column prop="type" label="车辆类别" width="100"></el-table-column>
+        <el-table-column prop="plate" label="车牌号" width="120"></el-table-column>
+        <el-table-column prop="status" label="状态" width="100">
+          <template slot-scope="scope">
+            <el-tag :type="scope.row.status === '在位' ? 'success' : 'danger'">
+              {{ scope.row.status }}
+            </el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column prop="reason" label="外出事由"></el-table-column>
+        <el-table-column prop="time" label="外出时间" width="180"></el-table-column>
+      </el-table>
+    </el-card>
+  </div>
+</template>
+
+<script>
+export default {
+  name: "VehicleStatus",
+  data() {
+    return {
+      // 统计数据(写死)
+      stats: {
+        military: { total: 5, inCamp: 3, outCamp: 2 },
+        private: { total: 6, inCamp: 4, outCamp: 2 },
+      },
+      // 车辆列表(写死)
+      vehicleList: [
+        { type: "军车", plate: "军A-12345", status: "在位", reason: "", time: "" },
+        { type: "军车", plate: "军A-67890", status: "外出", reason: "执行任务", time: "2025-09-04 08:30" },
+        { type: "军车", plate: "军A-11223", status: "外出", reason: "送物资", time: "2025-09-04 09:00" },
+        { type: "军车", plate: "军A-44556", status: "在位", reason: "", time: "" },
+        { type: "军车", plate: "军A-77889", status: "在位", reason: "", time: "" },
+        { type: "私家车", plate: "浙B-88888", status: "在位", reason: "", time: "" },
+        { type: "私家车", plate: "浙B-99999", status: "外出", reason: "回家探亲", time: "2025-09-03 19:20" },
+        { type: "私家车", plate: "浙B-66666", status: "外出", reason: "采购生活用品", time: "2025-09-04 10:15" },
+        { type: "私家车", plate: "浙B-12345", status: "在位", reason: "", time: "" },
+        { type: "私家车", plate: "浙B-54321", status: "在位", reason: "", time: "" },
+        { type: "私家车", plate: "浙B-11111", status: "在位", reason: "", time: "" },
+      ],
+    };
+  },
+  methods: {
+    refreshData() {
+      this.$message.success("数据已刷新(当前为写死数据)");
+    },
+  },
+};
+</script>
+
+<style scoped>
+.mb-4 {
+  margin-bottom: 20px;
+}
+.table-header {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+}
+</style>

+ 104 - 0
src/views/notice/notice_chakan/index.vue

@@ -0,0 +1,104 @@
+<template>
+  <div class="app-container">
+    <el-card class="box-card" shadow="always">
+      <div slot="header" class="clearfix">
+        <span>通知查看</span>
+      </div>
+
+      <el-table :data="noticeList" style="width: 100%">
+        <el-table-column prop="title" label="标题" width="200" />
+        <el-table-column prop="description" label="描述" />
+        <el-table-column prop="fileName" label="附件" width="200" />
+        <el-table-column label="操作" width="180">
+          <template slot-scope="scope">
+            <el-button size="mini" type="primary" @click="previewNotice(scope.row)">预览</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+    </el-card>
+
+    <!-- 预览弹窗 -->
+    <el-dialog
+      title="通知预览"
+      :visible.sync="previewDialogVisible"
+      width="60%"
+      top="5vh"
+    >
+      <div>
+        <h3>{{ previewData.title }}</h3>
+        <p>{{ previewData.description }}</p>
+        <div v-if="previewData.fileUrl">
+          <!-- 如果是 PDF 文件 -->
+          <embed
+            v-if="isPdf(previewData.fileName)"
+            :src="previewData.fileUrl"
+            type="application/pdf"
+            width="100%"
+            height="600px"
+          />
+          <!-- 如果是图片 -->
+          <img
+            v-else-if="isImage(previewData.fileName)"
+            :src="previewData.fileUrl"
+            alt="通知附件"
+            style="max-width:100%; max-height:600px;"
+          />
+          <!-- 其他文件直接提供下载 -->
+          <el-link
+            v-else
+            :href="previewData.fileUrl"
+            target="_blank"
+            type="primary"
+          >
+            点击下载附件
+          </el-link>
+        </div>
+      </div>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="previewDialogVisible = false">关 闭</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+export default {
+  name: "NoticeView",
+  props: {
+    // 从父组件或全局状态管理传入
+    noticeList: {
+      type: Array,
+      default: () => [],
+    },
+  },
+  data() {
+    return {
+      previewDialogVisible: false,
+      previewData: {
+        title: "",
+        description: "",
+        fileUrl: "",
+        fileName: "",
+      },
+    };
+  },
+  methods: {
+    previewNotice(notice) {
+      this.previewData = { ...notice };
+      this.previewDialogVisible = true;
+    },
+    isPdf(fileName) {
+      return fileName && fileName.toLowerCase().endsWith(".pdf");
+    },
+    isImage(fileName) {
+      return fileName && /\.(jpg|jpeg|png|gif|bmp)$/i.test(fileName);
+    },
+  },
+};
+</script>
+
+<style scoped>
+.box-card {
+  margin-bottom: 20px;
+}
+</style>

+ 181 - 0
src/views/notice/notice_exemple/index.vue

@@ -0,0 +1,181 @@
+<template>
+  <div class="app-container">
+    <!-- 新增公告 -->
+    <el-card shadow="always">
+      <div slot="header">
+        <span>新增公告</span>
+      </div>
+      <el-form :model="form" label-width="80px">
+        <el-form-item label="标题">
+          <el-input v-model="form.title" placeholder="请输入标题"></el-input>
+        </el-form-item>
+        <el-form-item label="正文">
+          <el-input
+            type="textarea"
+            v-model="form.content"
+            placeholder="请输入公告正文"
+            :rows="4"
+          ></el-input>
+        </el-form-item>
+        <el-form-item label="发布人">
+          <el-input v-model="form.publisher" placeholder="请输入发布人"></el-input>
+        </el-form-item>
+        <el-form-item label="发布时间">
+          <el-date-picker
+            v-model="form.publishTime"
+            type="datetime"
+            placeholder="选择日期时间"
+          />
+        </el-form-item>
+        <el-form-item>
+          <el-button type="success" @click="addNotice">新增</el-button>
+          <el-button @click="resetForm">重置</el-button>
+        </el-form-item>
+      </el-form>
+    </el-card>
+
+    <!-- 公告列表 -->
+    <el-card shadow="always" style="margin-top: 20px;">
+      <div slot="header">
+        <span>公告列表</span>
+      </div>
+      <el-table :data="noticeList" border style="width: 100%">
+        <el-table-column label="标题" width="250">
+          <template slot-scope="scope">
+            <!-- 鼠标悬停预览 -->
+            <el-popover trigger="hover" placement="top" width="300">
+              <p><b>标题:</b>{{ scope.row.title }}</p>
+              <p><b>正文:</b>{{ scope.row.content }}</p>
+              <p><b>发布人:</b>{{ scope.row.publisher }}</p>
+              <p><b>发布时间:</b>{{ scope.row.publishTime }}</p>
+              <div slot="reference" style="cursor:pointer; color:#409EFF;">
+                {{ scope.row.title }}
+              </div>
+            </el-popover>
+          </template>
+        </el-table-column>
+        <el-table-column prop="publisher" label="发布人" width="120" />
+        <el-table-column prop="publishTime" label="发布时间" width="180" />
+        <el-table-column prop="status" label="状态" width="100" />
+        <el-table-column label="操作" width="250">
+          <template slot-scope="scope">
+            <el-button size="mini" type="primary" @click="editNotice(scope.$index)">
+              编辑
+            </el-button>
+            <el-button size="mini" type="danger" @click="deleteNotice(scope.$index)">
+              删除
+            </el-button>
+            <el-button size="mini" type="success" @click="publishNotice(scope.$index)">
+              发布
+            </el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+    </el-card>
+
+    <!-- 编辑弹窗 -->
+    <el-dialog title="编辑公告" :visible.sync="editDialogVisible" width="600px">
+      <el-form :model="editForm" label-width="80px">
+        <el-form-item label="标题">
+          <el-input v-model="editForm.title"></el-input>
+        </el-form-item>
+        <el-form-item label="正文">
+          <el-input type="textarea" v-model="editForm.content" :rows="4"></el-input>
+        </el-form-item>
+        <el-form-item label="发布人">
+          <el-input v-model="editForm.publisher"></el-input>
+        </el-form-item>
+        <el-form-item label="发布时间">
+          <el-date-picker v-model="editForm.publishTime" type="datetime" />
+        </el-form-item>
+      </el-form>
+      <div slot="footer">
+        <el-button @click="editDialogVisible = false">取消</el-button>
+        <el-button type="primary" @click="confirmEdit">确定</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+export default {
+  name: "NoticeManage",
+  data() {
+    return {
+      form: {
+        title: "",
+        content: "",
+        publisher: "",
+        publishTime: "",
+      },
+      noticeList: [
+        {
+          title: "系统升级通知",
+          content: "系统将于明晚22:00进行升级,请提前保存数据。",
+          publisher: "管理员A",
+          publishTime: "2025-09-01 10:00",
+          status: "未发布",
+        },
+        {
+          title: "会议通知",
+          content: "请各部门负责人于周五上午10点到会议室开会。",
+          publisher: "管理员B",
+          publishTime: "2025-09-02 09:30",
+          status: "已发布",
+        },
+      ],
+      editDialogVisible: false,
+      editForm: {},
+      editIndex: null,
+    };
+  },
+  methods: {
+    addNotice() {
+      if (!this.form.title || !this.form.content) {
+        this.$message.warning("请填写完整公告信息!");
+        return;
+      }
+      this.noticeList.push({
+        ...this.form,
+        status: "未发布",
+      });
+      this.resetForm();
+      this.$message.success("新增成功!");
+    },
+    resetForm() {
+      this.form = {
+        title: "",
+        content: "",
+        publisher: "",
+        publishTime: "",
+      };
+    },
+    deleteNotice(index) {
+      this.noticeList.splice(index, 1);
+      this.$message.success("删除成功!");
+    },
+    editNotice(index) {
+      this.editIndex = index;
+      this.editForm = { ...this.noticeList[index] };
+      this.editDialogVisible = true;
+    },
+    confirmEdit() {
+      if (this.editIndex !== null) {
+        this.noticeList[this.editIndex] = { ...this.editForm };
+        this.$message.success("修改成功!");
+        this.editDialogVisible = false;
+      }
+    },
+    publishNotice(index) {
+      this.noticeList[index].status = "已发布";
+      this.$message.success("公告已发布!");
+    },
+  },
+};
+</script>
+
+<style scoped>
+.app-container {
+  padding: 20px;
+}
+</style>

+ 219 - 0
src/views/notice/notice_xinzeng/index.vue

@@ -0,0 +1,219 @@
+<template>
+  <div class="app-container">
+    <!-- 搜索条件 -->
+    <el-form :inline="true" :model="queryParams" class="demo-form-inline">
+      <el-form-item label="标题">
+        <el-input v-model="queryParams.title" placeholder="请输入标题" clearable />
+      </el-form-item>
+      <el-form-item label="时间">
+        <el-date-picker
+          v-model="queryParams.dateRange"
+          type="daterange"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+          format="yyyy-MM-dd"
+          value-format="yyyy-MM-dd"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" @click="handleQuery">搜索</el-button>
+        <el-button @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <!-- 操作按钮 -->
+    <el-row :gutter="10" class="mb8">
+      <el-col>
+        <el-button type="primary" icon="el-icon-plus" @click="handleAdd">新增</el-button>
+      </el-col>
+    </el-row>
+
+    <!-- 通知列表 -->
+    <el-table :data="filteredList" border style="width: 100%">
+      <el-table-column type="index" label="序号" width="60" />
+      <el-table-column prop="title" label="标题" width="200">
+        <template slot-scope="scope">
+          <el-tooltip effect="dark" :content="scope.row.description" placement="top">
+            <span>{{ scope.row.title }}</span>
+          </el-tooltip>
+        </template>
+      </el-table-column>
+      <el-table-column prop="description" label="描述" show-overflow-tooltip />
+      <el-table-column prop="date" label="发布时间" width="150" />
+      <el-table-column label="附件" width="100">
+        <template slot-scope="scope">
+          <el-button
+            v-if="scope.row.fileUrl"
+            size="mini"
+            type="text"
+            @click="previewFile(scope.row)"
+          >
+            预览
+          </el-button>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" width="150">
+        <template slot-scope="scope">
+          <el-button size="mini" type="danger" @click="deleteNotice(scope.$index)">
+            删除
+          </el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <!-- 新增通知弹窗 -->
+    <el-dialog
+      title="新增通知"
+      :visible.sync="open"
+      width="600px"
+      :close-on-click-modal="false"
+    >
+      <el-form :model="form" ref="formRef" label-width="80px">
+        <el-form-item label="标题" prop="title" :rules="[{ required: true, message: '请输入标题' }]">
+          <el-input v-model="form.title" placeholder="请输入通知标题" />
+        </el-form-item>
+        <el-form-item label="描述">
+          <el-input type="textarea" v-model="form.description" :rows="4" placeholder="请输入通知描述" />
+        </el-form-item>
+        <el-form-item label="附件">
+          <el-upload
+            action="#"
+            :file-list="form.fileList"
+            :auto-upload="false"
+            :on-change="handleFileChange"
+          >
+            <el-button size="small" type="primary">选择文件</el-button>
+          </el-upload>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="open = false">取消</el-button>
+        <el-button type="primary" @click="submitForm">确认新增</el-button>
+      </div>
+    </el-dialog>
+
+    <!-- 预览文件弹窗 -->
+    <el-dialog
+      title="文件预览"
+      :visible.sync="previewVisible"
+      width="800px"
+      top="5vh"
+    >
+      <div v-if="previewType === 'image'">
+        <img :src="previewUrl" alt="预览图片" style="max-width:100%; max-height:70vh;" />
+      </div>
+      <div v-else-if="previewType === 'pdf'">
+        <embed :src="previewUrl" type="application/pdf" width="100%" height="600px" />
+      </div>
+      <div v-else-if="previewType === 'text'">
+        <iframe :src="previewUrl" width="100%" height="600px"></iframe>
+      </div>
+      <div v-else>
+        <p>暂不支持该文件类型的预览,请下载查看。</p>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+export default {
+  name: "NoticeManage",
+  data() {
+    return {
+      open: false,
+      previewVisible: false,
+      previewUrl: "",
+      previewType: "",
+      queryParams: {
+        title: "",
+        dateRange: [],
+      },
+      form: {
+        title: "",
+        description: "",
+        fileList: [],
+        fileUrl: null,
+      },
+      noticeList: [
+        {
+          title: "系统维护通知",
+          description: "本周六晚 22:00-24:00 系统维护,请提前保存数据。",
+          date: "2025-09-07",
+          fileUrl: null,
+          fileType: "",
+        },
+        {
+          title: "宿舍线路检查维修",
+          description: "本周日晚 22:00-24:00 请大家提前做好准备。",
+          date: "2025-09-08",
+          fileUrl: null,
+          fileType: "",
+        },
+      ],
+    };
+  },
+  computed: {
+    filteredList() {
+      return this.noticeList.filter((item) => {
+        const matchTitle = this.queryParams.title
+          ? item.title.includes(this.queryParams.title)
+          : true;
+        const matchDate =
+          this.queryParams.dateRange.length === 2
+            ? item.date >= this.queryParams.dateRange[0] &&
+            item.date <= this.queryParams.dateRange[1]
+            : true;
+        return matchTitle && matchDate;
+      });
+    },
+  },
+  methods: {
+    handleAdd() {
+      this.open = true;
+      this.form = { title: "", description: "", fileList: [], fileUrl: null };
+    },
+    handleFileChange(file, fileList) {
+      this.form.fileList = fileList;
+      if (file.raw) {
+        this.form.fileUrl = URL.createObjectURL(file.raw);
+        const type = file.raw.type;
+        if (type.startsWith("image/")) {
+          this.form.fileType = "image";
+        } else if (type === "application/pdf") {
+          this.form.fileType = "pdf";
+        } else if (type.startsWith("text/")) {
+          this.form.fileType = "text";
+        } else {
+          this.form.fileType = "other";
+        }
+      }
+    },
+    submitForm() {
+      this.$refs.formRef.validate((valid) => {
+        if (valid) {
+          this.noticeList.push({
+            title: this.form.title,
+            description: this.form.description,
+            date: new Date().toISOString().slice(0, 10),
+            fileUrl: this.form.fileUrl,
+            fileType: this.form.fileType,
+          });
+          this.open = false;
+        }
+      });
+    },
+    deleteNotice(index) {
+      this.noticeList.splice(index, 1);
+    },
+    previewFile(row) {
+      this.previewUrl = row.fileUrl;
+      this.previewType = row.fileType;
+      this.previewVisible = true;
+    },
+    handleQuery() {},
+    resetQuery() {
+      this.queryParams = { title: "", dateRange: [] };
+    },
+  },
+};
+</script>

+ 86 - 0
src/views/peopleChuRu/peopleAccess/index.vue

@@ -0,0 +1,86 @@
+<template>
+  <div class="app-container">
+    <h2>人员出入管理(模拟人脸识别)</h2>
+
+    <!-- 人员表 -->
+    <el-table :data="peopleList" border style="width: 100%; margin-bottom: 30px;">
+      <el-table-column prop="id" label="人员ID" width="80" />
+      <el-table-column prop="name" label="姓名" width="120" />
+      <el-table-column prop="dept" label="部门" width="180" />
+      <el-table-column label="当前状态" width="120">
+        <template slot-scope="scope">
+          <el-tag :type="scope.row.status === '在营' ? 'success' : 'info'">
+            {{ scope.row.status }}
+          </el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" width="160">
+        <template slot-scope="scope">
+          <el-button size="mini" type="primary" @click="mockRecognition(scope.row, '入')">模拟入营</el-button>
+          <el-button size="mini" type="danger" @click="mockRecognition(scope.row, '出')">模拟出营</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <!-- 日志记录 -->
+    <el-card shadow="hover">
+      <div slot="header">
+        <span>人脸识别出入记录</span>
+      </div>
+      <el-table :data="logList" border style="width: 100%">
+        <el-table-column prop="time" label="时间" width="180" />
+        <el-table-column prop="name" label="姓名" width="120" />
+        <el-table-column prop="dept" label="部门" width="180" />
+        <el-table-column prop="action" label="出入类型" width="120">
+          <template slot-scope="scope">
+            <el-tag :type="scope.row.action === '入营' ? 'success' : 'danger'">
+              {{ scope.row.action }}
+            </el-tag>
+          </template>
+        </el-table-column>
+      </el-table>
+    </el-card>
+  </div>
+</template>
+
+<script>
+export default {
+  name: "PeopleAccess",
+  data() {
+    return {
+      // 人员信息
+      peopleList: [
+        { id: 1, name: "张三", dept: "一营一连", status: "未识别" },
+        { id: 2, name: "李四", dept: "二营二连", status: "未识别" },
+        { id: 3, name: "王五", dept: "三营三连", status: "未识别" },
+      ],
+      // 出入日志
+      logList: []
+    };
+  },
+  methods: {
+    mockRecognition(person, type) {
+      // 更新时间
+      const now = new Date();
+      const time = now.toLocaleString();
+
+      // 更新状态
+      person.status = type === "入" ? "在营" : "外出";
+
+      // 写入日志
+      this.logList.unshift({
+        time,
+        name: person.name,
+        dept: person.dept,
+        action: type === "入" ? "入营" : "出营"
+      });
+    }
+  }
+};
+</script>
+
+<style scoped>
+h2 {
+  margin-bottom: 20px;
+}
+</style>

+ 695 - 0
src/views/peopleManage/peopleBorrow/index.vue

@@ -0,0 +1,695 @@
+<template>
+  <div class="app-container">
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="el-icon-plus"
+          size="mini"
+          @click="handleAdd"
+          v-hasPermi="['peopleChuRu:peopleBorrow:add']"
+        >新增</el-button
+        >
+      </el-col>
+      <!-- <el-col :span="1.5">
+        <el-button
+          type="success"
+          plain
+          icon="el-icon-edit"
+          size="mini"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['peopleChuRu:peopleBorrow:edit']"
+          >修改</el-button
+        >
+      </el-col> -->
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="el-icon-delete"
+          size="mini"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['peopleChuRu:peopleBorrow:remove']"
+        >删除</el-button
+        >
+      </el-col>
+      <!-- <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          :loading="exportLoading"
+          @click="handleExport"
+          v-hasPermi="['peopleChuRu:peopleBorrow:export']"
+          >导出</el-button
+        >
+      </el-col> -->
+      <!-- <right-toolbar
+        :showSearch.sync="showSearch"
+        @queryTable="getList"
+      ></right-toolbar> -->
+    </el-row>
+
+    <el-table
+      v-loading="loading"
+      :data="peopleBorrowList"
+      @selection-change="handleSelectionChange"
+      :header-cell-style="{ background: '#003C69', color: 'white' }"
+    >
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="序号" align="center" prop="id">
+        <template scope="scope">
+          <span>{{
+              (queryParams.pageNum - 1) * queryParams.pageSize + scope.$index + 1
+            }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="单位" align="center" prop="unitName" />
+      <el-table-column
+        label="借调人姓名"
+        align="center"
+        prop="transferPeople"
+      />
+      <!-- <el-table-column
+        label="借调人id"
+        align="center"
+        prop="transferPeopleId"
+      /> -->
+
+      <!-- <el-table-column label="单位id" align="center" prop="unitId" /> -->
+      <el-table-column
+        label="借调单位"
+        align="center"
+        prop="transferUnitName"
+      />
+      <!-- <el-table-column
+        label="借调单位id"
+        align="center"
+        prop="transferUnitId"
+      /> -->
+      <el-table-column
+        label="开始时间"
+        align="center"
+        prop="startTime"
+        width="180"
+      >
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.startTime, "{y}-{m}-{d}") }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column
+        label="结束时间"
+        align="center"
+        prop="endTime"
+        width="180"
+      >
+        <template slot-scope="scope">
+          <span>{{ parseTime(scope.row.endTime, "{y}-{m}-{d}") }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="借调事由" align="center" prop="transferReason" />
+      <el-table-column label="职位" align="center" prop="jobTitle">
+        <template slot-scope="scope">
+          <dict-tag
+            :options="dict.type.post_Level"
+            :value="scope.row.jobTitle"
+          />
+        </template>
+      </el-table-column>
+      <el-table-column label="军衔" align="center" prop="rankId">
+        <template slot-scope="scope">
+          <dict-tag
+            :options="dict.type.sys_user_rank"
+            :value="scope.row.rankId"
+          />
+        </template>
+      </el-table-column>
+      <!-- <el-table-column label="创建人" align="center" prop="creatName" /> -->
+      <el-table-column label="人员状态" align="center" prop="state">
+        <template slot-scope="scope">
+          <span v-if="scope.row.state == '0'" style="color: #ff4949"
+          >未归队</span
+          >
+          <span v-if="scope.row.state == '1'" style="color: #13ce66"
+          >已归队</span
+          >
+        </template>
+      </el-table-column>
+      <el-table-column
+        label="操作"
+        align="center"
+        class-name="small-padding fixed-width"
+      >
+        <template slot-scope="scope">
+          <el-button
+            v-if="scope.row.common == '1'"
+            size="btu"
+            type="text"
+            v-hasPermi="['peopleChuRu:bdglLeave:guidui']"
+            @click="handle(scope.row)"
+          >归队</el-button
+          >
+          <el-button
+            size="btd"
+            type="text"
+            @click="handleDelete(scope.row)"
+            v-hasPermi="['peopleChuRu:peopleBorrow:remove']"
+          >删除</el-button
+          >
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <!-- <pagination
+      v-show="total > 0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="getList"
+    /> -->
+
+    <!-- 添加或修改人员借调对话框 -->
+    <el-dialog
+      :title="title"
+      :visible.sync="open"
+      width="800px"
+      append-to-body
+      :close-on-click-modal="false"
+    >
+      <el-form
+        ref="form"
+        :model="form"
+        :rules="rules"
+        label-width="80px"
+        inline
+      >
+        <div class="jiben">基本信息</div>
+        <el-form-item label="单位" prop="unitId">
+          <!-- <el-input v-model="form.unitName" placeholder="请输入单位" /> -->
+          <treeselect
+            v-model="form.unitId"
+            :options="deptOptions"
+            placeholder="请选择单位"
+            @select="selectPeo"
+            @open="blurSelect"
+          />
+        </el-form-item>
+        <el-form-item />
+        <el-form-item label="借调人姓名" prop="transferPeople">
+          <el-select
+            v-model="form.transferPeopleId"
+            placeholder="请输入借调人姓名"
+            ref="headerSearchSelect"
+          >
+            <el-option
+              v-for="(item, i) in renYuan"
+              :key="i"
+              :label="item.name"
+              :value="item.id"
+              @click.native="
+                jieRen(item.name, item.rankId, item.jobTitle, item)
+              "
+              class="input_xiala"
+            >
+            </el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="借调单位名称" prop="transferUnitName">
+          <el-input
+            v-model="form.transferUnitName"
+            placeholder="请输入借调单位名称"
+          />
+        </el-form-item>
+        <el-form-item label="借调开始时间" prop="startTime">
+          <el-date-picker
+            clearable
+            size="small"
+            v-model="form.startTime"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="选择借调开始时间"
+          >
+          </el-date-picker>
+        </el-form-item>
+        <el-form-item label="借调结束时间" prop="endTime">
+          <el-date-picker
+            clearable
+            size="small"
+            v-model="form.endTime"
+            type="date"
+            value-format="yyyy-MM-dd"
+            placeholder="选择借调结束时间"
+          >
+          </el-date-picker>
+        </el-form-item>
+        <div class="jiben">借调事由</div>
+        <el-form-item prop="transferReason">
+          <el-input
+            v-model="form.transferReason"
+            type="textarea"
+            placeholder="请输入借调原因"
+          />
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel" size="btn">取 消</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import {
+  listPeopleBorrow,
+  getPeopleBorrow,
+  delPeopleBorrow,
+  addPeopleBorrow,
+  updatePeopleBorrow,
+  exportPeopleBorrow,
+} from "@/api/peopleChuRu/peopleBorrow";
+
+import { getZaiRen, getDept } from "@/api/grassrootsregistration/bdglmeeting";
+// 导入树形结构
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+
+export default {
+  name: "PeopleBorrow",
+  dicts: ["post_Level", "sys_user_rank"],
+  components: {
+    Treeselect,
+  },
+  data() {
+    return {
+      // 遮罩层
+      loading: true,
+      // 导出遮罩层
+      exportLoading: false,
+      // 选中数组
+      ids: [],
+      // 非单个禁用
+      single: true,
+      // 非多个禁用
+      multiple: true,
+      // 显示搜索条件
+      showSearch: true,
+      // 总条数
+      total: 0,
+      // 人员借调表格数据
+      peopleBorrowList: [],
+      // 弹出层标题
+      title: "",
+      // 是否显示弹出层
+      open: false,
+      // 查询参数
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        transferPeople: null,
+        transferPeopleId: null,
+        unitName: null,
+        unitId: null,
+        transferUnitName: null,
+        transferUnitId: null,
+        startTime: null,
+        endTime: null,
+        transferReason: null,
+        jobTitle: null,
+        rankId: null,
+        creatName: null,
+        state: null,
+      },
+      // 表单参数
+      form: {},
+      // 表单校验
+      rules: {
+        unitId: [{ required: true, message: "单位不能为空", trigger: "blur" }],
+        transferPeople: [
+          { required: true, message: "人员不能为空", trigger: "blur" },
+        ],
+      },
+      // 树形结构列表
+      deptOptions: [],
+      // 人员列表
+      renYuan: [],
+      // 归队按钮的显示与隐藏
+      anNiu: true,
+    };
+  },
+  created() {
+    this.getList();
+  },
+  methods: {
+    // 让select失去焦点
+    blurSelect() {
+      this.$refs.headerSearchSelect.blur();
+    },
+    // 重置表单人员
+    ChongZhiRen() {
+      this.form.transferPeopleId = null;
+    },
+    // 请假人选中
+    jieRen(name, rankId, jobTitle, data) {
+      this.form.transferPeople = name;
+      this.form.rankId = rankId;
+      this.form.jobTitle = jobTitle;
+    },
+    // 获取部门列表
+    getBuMeng() {
+      getDept().then((res) => {
+        this.deptOptions = res.data;
+      });
+    },
+    // 选择部门单位触发
+    selectPeo(data) {
+      this.form.unitId = data.id;
+      this.getRen(this.form.unitId, 0);
+      this.ChongZhiRen();
+    },
+    // 获取人员
+    getRen(id, num) {
+      getZaiRen(id, num).then((response) => {
+        this.renYuan = response.data;
+      });
+    },
+    /** 查询人员借调列表 */
+    getList() {
+      this.loading = true;
+      listPeopleBorrow(this.queryParams).then((response) => {
+        this.peopleBorrowList = response.rows;
+        this.total = response.total;
+        this.loading = false;
+      });
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 表单重置
+    reset() {
+      this.form = {
+        id: null,
+        transferPeople: null,
+        transferPeopleId: null,
+        unitName: null,
+        unitId: null,
+        transferUnitName: null,
+        transferUnitId: null,
+        startTime: null,
+        endTime: null,
+        transferReason: null,
+        jobTitle: null,
+        rankId: null,
+        createTime: null,
+        creatName: null,
+        state: null,
+      };
+      this.resetForm("form");
+    },
+    /** 搜索按钮操作 */
+    handleQuery() {
+      this.queryParams.pageNum = 1;
+      this.getList();
+    },
+    /** 重置按钮操作 */
+    resetQuery() {
+      this.resetForm("queryForm");
+      this.handleQuery();
+    },
+    // 多选框选中数据
+    handleSelectionChange(selection) {
+      this.ids = selection.map((item) => item.id);
+      this.single = selection.length !== 1;
+      this.multiple = !selection.length;
+    },
+    /** 新增按钮操作 */
+    handleAdd() {
+      this.getBuMeng();
+      (this.renYuan = []), this.reset();
+      this.open = true;
+      this.title = "添加人员借调";
+    },
+    /** 修改按钮操作 */
+    handleUpdate(row) {
+      this.getBuMeng();
+      this.reset();
+      const id = row.id || this.ids;
+      getPeopleBorrow(id).then((response) => {
+        this.form = response.data;
+        this.getRen(this.form.unitId);
+        this.open = true;
+        this.title = "修改人员借调";
+      });
+    },
+    /** 提交按钮 */
+    submitForm() {
+      this.$refs["form"].validate((valid) => {
+        if (valid) {
+          if (this.form.id != null) {
+            updatePeopleBorrow(this.form).then((response) => {
+              this.$modal.msgSuccess("修改成功");
+              this.open = false;
+              this.getList();
+            });
+          } else {
+            this.form.state = "0";
+            addPeopleBorrow(this.form).then((response) => {
+              this.$modal.msgSuccess("新增成功");
+              this.open = false;
+              this.getList();
+            });
+          }
+        }
+      });
+    },
+    /** 删除按钮操作 */
+    handleDelete(row) {
+      const ids = row.id || this.ids;
+      this.$modal
+        .confirm("是否确认删除人员借调的数据项?")
+        .then(function () {
+          return delPeopleBorrow(ids);
+        })
+        .then(() => {
+          this.getList();
+          this.$modal.msgSuccess("删除成功");
+        })
+        .catch(() => {});
+    },
+    /** 导出按钮操作 */
+    handleExport() {
+      const queryParams = this.queryParams;
+      this.$modal
+        .confirm("是否确认导出所有人员借调数据项?")
+        .then(() => {
+          this.exportLoading = true;
+          return exportPeopleBorrow(queryParams);
+        })
+        .then((response) => {
+          this.$download.name(response.msg);
+          this.exportLoading = false;
+        })
+        .catch(() => {});
+    },
+    // 点击归队弹出询问框
+    handle(row) {
+      this.form.id = row.id;
+      this.$confirm("是否确认归队?", {
+        confirmButtonText: "确定",
+        cancelButtonText: "取消",
+        type: "warning",
+      })
+        .then(() => {
+          this.form.state = "1";
+          updatePeopleBorrow(this.form).then((response) => {
+            this.$modal.msgSuccess("归队成功");
+            this.getList();
+          });
+        })
+        .catch(() => {});
+    },
+  },
+};
+</script>
+<style scoped>
+/* 对话框背景颜色 */
+::v-deep .el-dialog {
+  background: #004d86 !important;
+}
+
+::v-deep .el-textarea__inner {
+  width: 650px;
+  height: 104px;
+  margin: auto;
+}
+
+::v-deep .el-dialog__header {
+  border-bottom: 1px solid #718a9d;
+}
+
+::v-deep .el-dialog__title {
+  color: #fff;
+  font: 18px;
+}
+
+::v-deep .el-dialog__headerbtn .el-dialog__close {
+  color: #fff;
+}
+
+::v-deep .el-form-item__label {
+  font: 16px;
+  color: #fff;
+  width: 100px !important;
+}
+
+::v-deep .el-input__inner {
+  /* width: 200px !important;
+  height: 36px; */
+  background: transparent;
+  color: #fff;
+  border-color: #fff;
+  border: 1px solid white !important;
+}
+
+/* 单位框背景颜色 */
+::v-deep .vue-treeselect__control {
+  background: #004d86 !important;
+}
+
+/* 基本信息背景 */
+.jiben {
+  width: 660px;
+  height: 32px;
+  background-image: url(../../../images/小标题底.png);
+  background-size: 100%;
+  margin-bottom: 25px;
+  color: #fff;
+  padding-left: 16px;
+  line-height: 32px;
+}
+
+/*调整表单间距 */
+::v-deep .el-form-item__content {
+  width: 200px;
+}
+
+::v-deep .el-input__inner {
+  cursor: pointer !important;
+}
+
+/* 底部确定取消按钮 */
+::v-deep .el-dialog__footer {
+  padding: 18px 50px !important;
+  margin-right: 28px !important;
+}
+
+::v-deep .el-dialog__body {
+  /* margin: 10px 30px 20px 30px; */
+  margin-left: 56px;
+  margin-top: 10px;
+  padding-top: 20px !important;
+  box-sizing: border-box;
+  /* padding: 30px 12px 30px 28px; */
+}
+
+.contents {
+  padding: 0px 40px !important;
+}
+
+/* 下拉菜单 */
+.el-dropdown-link {
+  cursor: pointer;
+  color: #409eff;
+}
+
+.el-icon-arrow-down {
+  font-size: 12px;
+}
+
+/* 刷新图标 */
+/* .el-icon-refresh {
+  width: 76px;
+  height: 36px;
+  color: #fff;
+  background-color: #1d96ff !important;
+  border-radius: 4px;
+  border: none;
+  margin-left: 20px;
+  font-size: 14px;
+} */
+/* 下拉菜单字体/背景颜色 */
+.el-select-dropdown__item.hover,
+.el-select-dropdown__item:hover {
+  background-color: #004d86;
+  color: #fff;
+}
+
+.el-select-dropdown__item {
+  color: #fff;
+}
+
+/* 时间选择 */
+::v-deep .el-input--small .el-input__inner {
+  width: 200px;
+  height: 36px;
+  line-height: 36px;
+}
+
+.el-date-editor.el-input {
+  width: 200px;
+  height: 36px;
+  line-height: 36px;
+}
+
+::v-deep .el-date-editor.el-input .el-input__inner {
+  height: 36px;
+  line-height: 36px;
+}
+
+/* 单位框背景颜色 */
+::v-deep .vue-treeselect__control {
+  background: #004d86 !important;
+  color: #fff;
+}
+
+/* 单位下拉菜单选中字体颜色 */
+::v-deep .vue-treeselect__single-value {
+  color: #fff !important;
+}
+
+/* 分页按钮 */
+::v-deep .el-pagination.is-background .el-pager li {
+  background-color: #004d86;
+  color: #fff;
+}
+
+::v-deep .el-pagination.is-background .btn-next {
+  background-color: #004d86;
+  color: #fff;
+}
+
+/* 底部确定取消按钮 */
+::v-deep .el-dialog__footer {
+  padding: 18px 50px;
+  margin-right: 42px;
+}
+
+/* 增加按钮弹框 */
+/* ::v-deep .el-dialog {
+  width: 1060px !important;
+} */
+::v-deep .el-dialog__body {
+  padding: none !important;
+}
+
+/* 表格对其 */
+.el-form--inline .el-form-item {
+  margin-right: 50px;
+}
+</style>

+ 128 - 0
src/views/safety/danger_view/index.vue

@@ -0,0 +1,128 @@
+<template>
+  <div class="risk-dashboard app-container">
+    <!-- 风险统计卡片 -->
+    <div class="stats">
+      <el-card class="stat-card high" shadow="always">
+        <div class="title">高风险</div>
+        <div class="count">{{ stats.high }}</div>
+      </el-card>
+      <el-card class="stat-card medium" shadow="always">
+        <div class="title">中风险</div>
+        <div class="count">{{ stats.medium }}</div>
+      </el-card>
+      <el-card class="stat-card low" shadow="always">
+        <div class="title">低风险</div>
+        <div class="count">{{ stats.low }}</div>
+      </el-card>
+    </div>
+
+    <!-- 风险趋势图 -->
+    <el-card shadow="always" style="margin-top: 20px;">
+      <div slot="header">
+        <span>最近一周风险问题趋势</span>
+      </div>
+      <div id="riskChart" style="height: 300px;"></div>
+    </el-card>
+
+    <!-- 高风险 Top5 -->
+    <el-card shadow="always" style="margin-top: 20px;">
+      <div slot="header">
+        <span>高风险隐患 Top5</span>
+      </div>
+      <el-table :data="topList" border style="width: 100%;" fit>
+        <el-table-column prop="id" label="编号" width="80" />
+        <el-table-column prop="problem" label="问题描述" />
+        <el-table-column prop="date" label="发现时间" width="180" />
+        <el-table-column prop="status" label="状态" width="120" />
+      </el-table>
+    </el-card>
+  </div>
+</template>
+
+<script>
+import * as echarts from "echarts";
+
+export default {
+  name: "RiskDashboard",
+  data() {
+    return {
+      stats: {
+        high: 3,
+        medium: 5,
+        low: 7,
+      },
+      topList: [
+        { id: 1, problem: "电线老化存在安全隐患", status: "未整改", date: "2025-09-01 09:00" },
+        { id: 2, problem: "高压气罐未定期检查", status: "未整改", date: "2025-09-02 11:20" },
+        { id: 3, problem: "化学品存放不规范", status: "未整改", date: "2025-09-03 14:10" },
+        { id: 4, problem: "消防通道堵塞", status: "未整改", date: "2025-09-03 17:40" },
+        { id: 5, problem: "仓库堆放易燃物品", status: "已整改", date: "2025-09-04 09:30" },
+      ],
+      trendData: [2, 3, 1, 5, 4, 2, 3], // 模拟最近 7 天新增问题
+    };
+  },
+  mounted() {
+    this.initChart();
+  },
+  methods: {
+    initChart() {
+      const chart = echarts.init(document.getElementById("riskChart"));
+      chart.setOption({
+        tooltip: { trigger: "axis" },
+        xAxis: {
+          type: "category",
+          data: ["周一", "周二", "周三", "周四", "周五", "周六", "周日"],
+        },
+        yAxis: { type: "value" },
+        series: [
+          {
+            name: "新增隐患数",
+            type: "bar",
+            data: this.trendData,
+            itemStyle: { color: "#ff4d4f" },
+          },
+        ],
+      });
+    },
+  },
+};
+</script>
+
+<style scoped>
+.risk-dashboard {
+  padding: 20px;
+}
+
+.stats {
+  display: flex;
+  gap: 20px;
+}
+
+.stat-card {
+  flex: 1;
+  text-align: center;
+  padding: 20px;
+}
+
+.stat-card .title {
+  font-size: 16px;
+  margin-bottom: 10px;
+}
+
+.stat-card .count {
+  font-size: 32px;
+  font-weight: bold;
+}
+
+.high {
+  border-left: 6px solid #ff4d4f;
+}
+
+.medium {
+  border-left: 6px solid #faad14;
+}
+
+.low {
+  border-left: 6px solid #1890ff;
+}
+</style>

+ 126 - 0
src/views/safety/safetyManage/index.vue

@@ -0,0 +1,126 @@
+<template>
+  <div class="app-container">
+    <!-- 新增风险问题 -->
+    <div style="margin-bottom: 20px; display: flex; align-items: center;">
+      <el-input
+        v-model="form.problem"
+        placeholder="请输入风险问题描述"
+        style="width: 400px; margin-right: 10px;"
+      />
+      <el-select v-model="form.level" placeholder="风险等级" style="width: 150px; margin-right: 10px;">
+        <el-option label="低" value="低"></el-option>
+        <el-option label="中" value="中"></el-option>
+        <el-option label="高" value="高"></el-option>
+      </el-select>
+      <el-button type="success" @click="addProblem">录入问题</el-button>
+    </div>
+
+    <!-- 隐患台账(表格) -->
+    <el-card shadow="always">
+      <div slot="header">
+        <span>安全隐患台账(实时显示)</span>
+      </div>
+      <el-table :data="problemList" border style="width: 100%;" fit>
+        <el-table-column prop="id" label="编号" width="80" />
+        <el-table-column prop="problem" label="问题描述" />
+        <el-table-column prop="level" label="风险等级" width="120">
+          <template slot-scope="scope">
+            <el-tag :type="scope.row.level === '高' ? 'danger' : scope.row.level === '中' ? 'warning' : 'info'">
+              {{ scope.row.level }}
+            </el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column prop="status" label="状态" width="120" />
+        <el-table-column prop="date" label="发现时间" width="180" />
+        <el-table-column label="操作" width="180">
+          <template slot-scope="scope">
+            <el-button size="mini" type="primary" @click="markResolved(scope.$index)">
+              标记已整改
+            </el-button>
+            <el-button size="mini" type="danger" @click="deleteProblem(scope.$index)">
+              删除
+            </el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <div style="margin-top: 10px;">隐患总数:{{ problemList.length }}</div>
+    </el-card>
+  </div>
+</template>
+
+<script>
+export default {
+  name: "RiskWarning",
+  data() {
+    return {
+      form: {
+        problem: "",
+        level: "",
+      },
+      // 死数据示例
+      problemList: [
+        {
+          id: 1,
+          problem: "电线老化存在安全隐患",
+          level: "高",
+          status: "未整改",
+          date: "2025-09-01 09:00",
+        },
+        {
+          id: 2,
+          problem: "消防器材过期",
+          level: "中",
+          status: "未整改",
+          date: "2025-09-02 10:30",
+        },
+        {
+          id: 3,
+          problem: "仓库通道堆放杂物",
+          level: "低",
+          status: "已整改",
+          date: "2025-09-02 15:20",
+        },
+      ],
+    };
+  },
+  methods: {
+    addProblem() {
+      if (!this.form.problem || !this.form.level) {
+        this.$message.warning("请填写完整问题信息!");
+        return;
+      }
+      const newId = this.problemList.length
+        ? Math.max(...this.problemList.map((p) => p.id)) + 1
+        : 1;
+      this.problemList.push({
+        id: newId,
+        problem: this.form.problem,
+        level: this.form.level,
+        status: "未整改",
+        date: new Date().toLocaleString(),
+      });
+      this.$message.success("录入成功!");
+      this.form.problem = "";
+      this.form.level = "";
+    },
+    markResolved(index) {
+      this.problemList[index].status = "已整改";
+      this.$message.success("该问题已标记为整改完成!");
+    },
+    deleteProblem(index) {
+      this.$confirm("确认删除该问题吗?", "提示", {
+        type: "warning",
+      }).then(() => {
+        this.problemList.splice(index, 1);
+        this.$message.success("删除成功!");
+      });
+    },
+  },
+};
+</script>
+
+<style scoped>
+.app-container {
+  padding: 20px;
+}
+</style>