|
|
@@ -1,16 +1,17 @@
|
|
|
<template>
|
|
|
<div style="padding: 10px">
|
|
|
- <!-- 搜索和操作 -->
|
|
|
<div style="height: 50px; display: flex; align-items: center; gap: 10px">
|
|
|
<!-- 选择设备 -->
|
|
|
<el-select
|
|
|
- v-model="queryCondition.selectedDeviceId"
|
|
|
+ v-model="selectedDeviceId"
|
|
|
placeholder="选择设备"
|
|
|
size="small"
|
|
|
- style="width: 150px"
|
|
|
- @change="fetchData"
|
|
|
+ style="width: 200px"
|
|
|
+ clearable
|
|
|
+ @change="handleSearch()"
|
|
|
>
|
|
|
<el-option
|
|
|
+ style="color: black"
|
|
|
v-for="device in devices"
|
|
|
:key="device.id"
|
|
|
:label="device.name"
|
|
|
@@ -18,286 +19,210 @@
|
|
|
/>
|
|
|
</el-select>
|
|
|
<el-input
|
|
|
- v-model="queryCondition.inputPlateNumber"
|
|
|
+ v-model="inputPlateNumber"
|
|
|
placeholder="输入车牌号"
|
|
|
size="small"
|
|
|
+ style="width: 200px"
|
|
|
clearable
|
|
|
- style="width: 150px"
|
|
|
- @keyup.enter.native="fetchData"
|
|
|
+ @keyup.enter.native="handleSearch()"
|
|
|
/>
|
|
|
<el-select
|
|
|
- v-model="queryCondition.selectedEventType"
|
|
|
- placeholder="事件类型"
|
|
|
+ v-model="eventType"
|
|
|
+ placeholder="选择进出类型"
|
|
|
size="small"
|
|
|
+ style="width: 200px"
|
|
|
clearable
|
|
|
- style="width: 120px"
|
|
|
- @change="fetchData"
|
|
|
+ @change="handleSearch()"
|
|
|
>
|
|
|
- <el-option label="全部" value="" />
|
|
|
- <el-option label="进" value="enter" />
|
|
|
- <el-option label="出" value="exit" />
|
|
|
+ <el-option label="全部" :value="''" />
|
|
|
+ <el-option label="进入" :value="'in'" />
|
|
|
+ <el-option label="离开" :value="'out'" />
|
|
|
</el-select>
|
|
|
- <!-- 搜索时间范围 -->
|
|
|
- <el-date-picker
|
|
|
- v-model="queryCondition.startTime"
|
|
|
- type="datetime"
|
|
|
- placeholder="开始时间"
|
|
|
- size="small"
|
|
|
- clearable
|
|
|
- style="width: 200px"
|
|
|
- @change="fetchData"
|
|
|
- />
|
|
|
<el-date-picker
|
|
|
- v-model="queryCondition.endTime"
|
|
|
- type="datetime"
|
|
|
- placeholder="结束时间"
|
|
|
+ v-model="timeRange"
|
|
|
+ type="datetimerange"
|
|
|
+ start-placeholder="选择开始时间"
|
|
|
+ end-placeholder="选择结束时间"
|
|
|
size="small"
|
|
|
- clearable
|
|
|
- style="width: 200px"
|
|
|
- @change="fetchData"
|
|
|
+ style="width: 400px"
|
|
|
/>
|
|
|
- <el-button type="primary" size="small" @click="fetchData">查询</el-button>
|
|
|
- <!-- <el-button type="success" size="small" @click="handleAdd">新增</el-button>-->
|
|
|
+ <el-button type="primary" size="small" @click="handleSearch()"
|
|
|
+ >查询</el-button
|
|
|
+ >
|
|
|
+ <!-- <el-button type="success" @click="handleAdd()" style="margin-left: 10px">新增</el-button>-->
|
|
|
<el-button
|
|
|
+ :disabled="multipleSelection.length === 0"
|
|
|
type="danger"
|
|
|
size="small"
|
|
|
- :disabled="!multipleSelection.length"
|
|
|
@click="handleBatchDelete"
|
|
|
- >批量删除</el-button
|
|
|
+ >批量删除</el-button
|
|
|
>
|
|
|
</div>
|
|
|
|
|
|
- <!-- 表格 -->
|
|
|
<el-table
|
|
|
+ v-loading="loading"
|
|
|
:data="tableData"
|
|
|
style="width: 100%; margin-top: 10px"
|
|
|
border
|
|
|
:header-cell-style="changeHeaderCellStyle"
|
|
|
@selection-change="handleSelectionChange"
|
|
|
- v-loading="loading"
|
|
|
- element-loading-text="加载中..."
|
|
|
>
|
|
|
<el-table-column type="selection" width="50" align="center" />
|
|
|
- <el-table-column label="序号" width="80" align="center" sortable>
|
|
|
- <template #default="scope">
|
|
|
- {{ (currentPage - 1) * pageSize + scope.$index + 1 }}
|
|
|
+ <el-table-column label="序号" type="index" width="60" align="center" sortable>
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <span>{{ (currentPage - 1) * pageSize + scope.$index + 1 }}</span>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
<el-table-column
|
|
|
prop="plateNumber"
|
|
|
label="车牌号"
|
|
|
+ min-width="120"
|
|
|
align="center"
|
|
|
- min-width="100"
|
|
|
sortable
|
|
|
/>
|
|
|
<el-table-column
|
|
|
prop="deviceId"
|
|
|
- label="设备Id"
|
|
|
+ label="设备"
|
|
|
+ min-width="120"
|
|
|
align="center"
|
|
|
- min-width="80"
|
|
|
sortable
|
|
|
/>
|
|
|
<el-table-column
|
|
|
prop="eventType"
|
|
|
- label="事件类型"
|
|
|
+ label="类型"
|
|
|
+ min-width="100"
|
|
|
align="center"
|
|
|
- min-width="60"
|
|
|
sortable
|
|
|
- >
|
|
|
- <template #default="{ row }">{{
|
|
|
- row.eventType === "enter" ? "进" : "出"
|
|
|
- }}</template>
|
|
|
- </el-table-column>
|
|
|
+ />
|
|
|
<el-table-column
|
|
|
prop="captureTime"
|
|
|
label="抓拍时间"
|
|
|
+ min-width="300"
|
|
|
align="center"
|
|
|
- min-width="150"
|
|
|
sortable
|
|
|
/>
|
|
|
- <el-table-column label="图片" align="center" min-width="120">
|
|
|
+ <el-table-column
|
|
|
+ prop="photoUrl"
|
|
|
+ label="照片"
|
|
|
+ min-width="200"
|
|
|
+ align="center"
|
|
|
+ sortable
|
|
|
+ >
|
|
|
<template #default="{ row }">
|
|
|
- <el-image
|
|
|
+ <img
|
|
|
v-if="row.photoUrl"
|
|
|
:src="row.photoUrl"
|
|
|
- :preview-src-list="[row.photoUrl]"
|
|
|
- style="width: 60px; height: 40px; border-radius: 4px"
|
|
|
+ :alt="`人员 ${row.name || ''} 的抓拍照片`"
|
|
|
+ style="
|
|
|
+ width: 100px;
|
|
|
+ height: 80px;
|
|
|
+ object-fit: cover;
|
|
|
+ border-radius: 6px;
|
|
|
+ "
|
|
|
/>
|
|
|
- <span v-else>-</span>
|
|
|
+ <span v-else style="color: #999">无照片</span>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
<el-table-column
|
|
|
prop="remark"
|
|
|
label="备注"
|
|
|
+ min-width="200"
|
|
|
align="center"
|
|
|
- min-width="150"
|
|
|
+ sortable
|
|
|
/>
|
|
|
- <el-table-column label="操作" fixed="right" align="center" width="160">
|
|
|
+ <el-table-column label="操作" min-width="120" align="center">
|
|
|
<template #default="{ row }">
|
|
|
<!-- <el-button type="text" size="small" @click="handleEdit(row)">编辑</el-button>-->
|
|
|
- <el-button type="danger" size="small" @click="handleDelete(row)"
|
|
|
- >删除</el-button
|
|
|
+ <el-button type="text" size="small" @click="handleDelete(row)"
|
|
|
+ >删除</el-button
|
|
|
>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
</el-table>
|
|
|
|
|
|
- <!-- ===== 分页 ===== -->
|
|
|
- <div class="pagination">
|
|
|
- <el-pagination
|
|
|
- background
|
|
|
- layout="total, prev, pager, next, jumper, sizes"
|
|
|
- :current-page="currentPage"
|
|
|
- :page-size="pageSize"
|
|
|
- :total="total"
|
|
|
- :page-sizes="[10, 20, 50, 100]"
|
|
|
- @current-change="handlePageChange"
|
|
|
- @size-change="handleSizeChange"
|
|
|
- />
|
|
|
- </div>
|
|
|
- <!-- <!– 新增/编辑弹窗 –>-->
|
|
|
- <!-- <VehicleAccessRecordEditDialog-->
|
|
|
- <!-- v-if="dialogVisible"-->
|
|
|
- <!-- :visible.sync="dialogVisible"-->
|
|
|
- <!-- :access-record-data="currentAccessRecordData"-->
|
|
|
- <!-- @submit="handleAccessRecordSubmit"-->
|
|
|
- <!-- @cancel="handleAccessRecordCancel"-->
|
|
|
- <!-- />-->
|
|
|
+ <el-pagination
|
|
|
+ background
|
|
|
+ layout="total, prev, pager, next, jumper, sizes"
|
|
|
+ :total="total"
|
|
|
+ :current-page.sync="currentPage"
|
|
|
+ :page-size.sync="pageSize"
|
|
|
+ :page-sizes="[10, 25, 50, 100]"
|
|
|
+ @current-change="handlePageChange"
|
|
|
+ @size-change="handleSizeChange"
|
|
|
+ style="margin-top: 10px; text-align: right"
|
|
|
+ />
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
import request from "@/utils/request";
|
|
|
-import VehicleAccessRecordEditDialog from "./VehicleAccessRecordEditDialog.vue";
|
|
|
-import { debounce } from "lodash";
|
|
|
|
|
|
export default {
|
|
|
- name: "VehicleAccessRecord",
|
|
|
- components: {
|
|
|
- VehicleAccessRecordEditDialog,
|
|
|
- },
|
|
|
data() {
|
|
|
return {
|
|
|
- // 搜索条件
|
|
|
- queryCondition: {
|
|
|
- selectedDeviceId: null,
|
|
|
- inputPlateNumber: "",
|
|
|
- selectedEventType: "",
|
|
|
- startTime: null, // 开始时间
|
|
|
- endTime: null, // 结束时间
|
|
|
- },
|
|
|
+ // 设备列表
|
|
|
devices: [],
|
|
|
+ selectedDeviceId: null,
|
|
|
+ inputPlateNumber: "",
|
|
|
+ eventType: "",
|
|
|
+ timeRange: [],
|
|
|
// 表格数据
|
|
|
tableData: [],
|
|
|
- loading: false,
|
|
|
currentPage: 1,
|
|
|
pageSize: 10,
|
|
|
total: 0,
|
|
|
- // 多选
|
|
|
+ loading: false,
|
|
|
+ // 表格多选
|
|
|
multipleSelection: [],
|
|
|
- // 弹窗
|
|
|
- dialogVisible: false,
|
|
|
- currentAccessRecordData: [],
|
|
|
};
|
|
|
},
|
|
|
mounted() {
|
|
|
this.getDeviceNameInfo();
|
|
|
- this.fetchData();
|
|
|
},
|
|
|
methods: {
|
|
|
- // 查询记录
|
|
|
- async _fetchData() {
|
|
|
+ // 监听多选变化
|
|
|
+ handleSelectionChange(val) {
|
|
|
+ this.multipleSelection = val;
|
|
|
+ },
|
|
|
+ async handleSearch() {
|
|
|
+ console.log("查询");
|
|
|
this.loading = true;
|
|
|
try {
|
|
|
- if (!this.queryCondition.selectedDeviceId) {
|
|
|
- this.$message.info("未选择设备,将查询所有设备数据");
|
|
|
- }
|
|
|
-
|
|
|
- const data = {
|
|
|
- ...this.queryCondition,
|
|
|
+ const params = {
|
|
|
+ deviceId: this.selectedDeviceId,
|
|
|
+ plateNumber: this.inputPlateNumber,
|
|
|
+ eventType: this.eventType,
|
|
|
page: this.currentPage,
|
|
|
size: this.pageSize,
|
|
|
};
|
|
|
- console.log("查询参数", data);
|
|
|
+ if (this.timeRange.length === 2) {
|
|
|
+ params.startTime = this.timeRange[0];
|
|
|
+ params.endTime = this.timeRange[1];
|
|
|
+ }
|
|
|
+ console.log("查询参数:", params);
|
|
|
const res = await request({
|
|
|
url: "/carCamera/accessRecord/list",
|
|
|
method: "POST",
|
|
|
- data: data,
|
|
|
+ data: params,
|
|
|
});
|
|
|
- // 判断返回结构
|
|
|
+ console.log("查询结果:", res);
|
|
|
if (res && res.list) {
|
|
|
- this.tableData = res.list || [];
|
|
|
- this.total = res.total || 0;
|
|
|
+ this.tableData = res.list;
|
|
|
+ this.total = res.total;
|
|
|
} else {
|
|
|
this.tableData = [];
|
|
|
this.total = 0;
|
|
|
this.$message.warning("未获取到数据");
|
|
|
}
|
|
|
- } catch (error) {
|
|
|
- console.error(error);
|
|
|
- this.$message.error("获取数据失败");
|
|
|
+ console.log("查询结果:this.tableData", this.tableData);
|
|
|
} finally {
|
|
|
this.loading = false;
|
|
|
}
|
|
|
},
|
|
|
- // 包裹防抖函数,延迟 300ms
|
|
|
- fetchData: debounce(function () {
|
|
|
- this.fetchData();
|
|
|
- }, 300),
|
|
|
- // 分页
|
|
|
- handlePageChange(page) {
|
|
|
- this.currentPage = page;
|
|
|
- this.fetchData();
|
|
|
- },
|
|
|
- handleSizeChange(size) {
|
|
|
- this.pageSize = size;
|
|
|
- this.currentPage = 1;
|
|
|
- this.fetchData();
|
|
|
- },
|
|
|
- // 表格样式
|
|
|
- changeHeaderCellStyle() {
|
|
|
- return "background: #004279; color: #fff;";
|
|
|
- },
|
|
|
- // 分页控制
|
|
|
- handleSelectionChange(val) {
|
|
|
- this.multipleSelection = val;
|
|
|
- },
|
|
|
- // 新增
|
|
|
- handleAdd() {
|
|
|
- this.currentAccessRecordData = {};
|
|
|
- this.dialogVisible = true;
|
|
|
- },
|
|
|
- // 编辑
|
|
|
- handleEdit(row) {
|
|
|
- this.currentAccessRecordData = { ...row };
|
|
|
- this.dialogVisible = true;
|
|
|
- },
|
|
|
- // 保存(新增/修改)
|
|
|
- handleSubmit() {
|
|
|
- this.$refs.formRef.validate(async (valid) => {
|
|
|
- if (!valid) return;
|
|
|
- const url = this.form.id
|
|
|
- ? "/carCamera/accessRecord/update"
|
|
|
- : "/carCamera/accessRecord/add";
|
|
|
- try {
|
|
|
- const res = await request.post(url, this.form);
|
|
|
- if (res.success) {
|
|
|
- this.$message.success("保存成功");
|
|
|
- this.dialogVisible = false;
|
|
|
- this.fetchData();
|
|
|
- } else {
|
|
|
- this.$message.error(res.msg || "保存失败");
|
|
|
- }
|
|
|
- } catch (e) {
|
|
|
- console.error(e);
|
|
|
- this.$message.error("请求失败");
|
|
|
- }
|
|
|
- });
|
|
|
- },
|
|
|
- // 删除单条
|
|
|
- async handleDelete(row) {
|
|
|
+ // 单条删除
|
|
|
+ handleDelete(row) {
|
|
|
this.$confirm(
|
|
|
- `确定要删除车牌号为【${row.plateNumber}】的记录吗?`,
|
|
|
+ `确定要删除【${row.name || "未知姓名"}】的进出记录吗?`,
|
|
|
"提示",
|
|
|
{
|
|
|
confirmButtonText: "确定",
|
|
|
@@ -305,43 +230,83 @@ export default {
|
|
|
type: "warning",
|
|
|
},
|
|
|
)
|
|
|
- .then(async () => {
|
|
|
- const res = await request.post("/carCamera/accessRecord/delete", {
|
|
|
- ids: [row.id],
|
|
|
- });
|
|
|
- if (res.success) {
|
|
|
- this.$message.success("删除成功");
|
|
|
- this.fetchData();
|
|
|
- } else {
|
|
|
- this.$message.error(res.msg || "删除失败");
|
|
|
- }
|
|
|
+ .then(() => {
|
|
|
+ const data = {
|
|
|
+ id: row.id,
|
|
|
+ };
|
|
|
+ this.deleteUser(data, "/carCamera/accessRecord/delete");
|
|
|
})
|
|
|
- .catch(() => {});
|
|
|
+ .catch(() => {
|
|
|
+ this.$message.info("已取消删除");
|
|
|
+ });
|
|
|
},
|
|
|
// 批量删除
|
|
|
- async handleBatchDelete() {
|
|
|
- if (!this.multipleSelection.length) return;
|
|
|
- const ids = this.multipleSelection.map((i) => i.id);
|
|
|
- this.$confirm(`确定要删除选中的 ${ids.length} 条记录吗?`, "提示", {
|
|
|
- type: "warning",
|
|
|
- })
|
|
|
- .then(async () => {
|
|
|
- const res = await request.post("/carCamera/accessRecord/delete", {
|
|
|
- ids,
|
|
|
- });
|
|
|
- if (res.success) {
|
|
|
- this.$message.success("删除成功");
|
|
|
- this.fetchData();
|
|
|
- } else {
|
|
|
- this.$message.error(res.msg || "删除失败");
|
|
|
- }
|
|
|
+ handleBatchDelete() {
|
|
|
+ const list = this.multipleSelection.map((item) => item.id);
|
|
|
+ if (list.length === 0) {
|
|
|
+ this.$message.warning("请先选择要删除的人员进出记录");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this.$confirm(
|
|
|
+ `确定要删除选中的 ${list.length} 个人员进出记录吗?`,
|
|
|
+ "批量删除确认",
|
|
|
+ {
|
|
|
+ confirmButtonText: "确定",
|
|
|
+ cancelButtonText: "取消",
|
|
|
+ type: "warning",
|
|
|
+ },
|
|
|
+ )
|
|
|
+ .then(() => {
|
|
|
+ const data = {
|
|
|
+ ids: list,
|
|
|
+ };
|
|
|
+ this.deleteUser(data, "/carCamera/accessRecord/batchDelete");
|
|
|
})
|
|
|
- .catch(() => {});
|
|
|
+ .catch(() => {
|
|
|
+ this.$message.info("已取消删除");
|
|
|
+ });
|
|
|
+ },
|
|
|
+ // 通用删除方法
|
|
|
+ async deleteUser(data, url) {
|
|
|
+ console.log("删除人员进出记录参数:", data);
|
|
|
+ console.log("删除人员进出记录url:", url);
|
|
|
+ try {
|
|
|
+ const res = await request({
|
|
|
+ url: url,
|
|
|
+ method: "POST",
|
|
|
+ data: data,
|
|
|
+ });
|
|
|
+ console.log("删除人员进出记录结果:", res);
|
|
|
+ if (res.success === true) {
|
|
|
+ this.$message.success("删除成功");
|
|
|
+ this.multipleSelection = [];
|
|
|
+ this.handleSearch();
|
|
|
+ } else {
|
|
|
+ this.$message.error(res.msg || "删除失败");
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ console.error("删除人员进出记录失败:", e);
|
|
|
+ this.$message.error("请求出错,请稍后重试");
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 表格样式修改
|
|
|
+ changeHeaderCellStyle(row, column, rowIndex, columnIndex) {
|
|
|
+ if (row.columnIndex === 0) {
|
|
|
+ return "background: #004279 ; color:#fff;"; // 修改的样式
|
|
|
+ } else {
|
|
|
+ return "background: #004279 ;color:#fff; ";
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 切换页码
|
|
|
+ handlePageChange(page) {
|
|
|
+ this.currentPage = page;
|
|
|
+ this.handleSearch();
|
|
|
},
|
|
|
- // 重置弹窗表单
|
|
|
- resetDialogForm() {
|
|
|
- this.form = {};
|
|
|
- this.$refs.formRef && this.$refs.formRef.clearValidate();
|
|
|
+ // 修改每页条数
|
|
|
+ handleSizeChange(size) {
|
|
|
+ this.pageSize = size;
|
|
|
+ this.currentPage = 1; // 切换条数后回到第一页
|
|
|
+ this.handleSearch();
|
|
|
},
|
|
|
// 获取设备列表
|
|
|
async getDeviceNameInfo() {
|
|
|
@@ -351,15 +316,23 @@ export default {
|
|
|
url: "/device/listDeviceName",
|
|
|
method: "GET",
|
|
|
});
|
|
|
- const list = res?.data?.list || res?.list || [];
|
|
|
- this.devices = list;
|
|
|
- if (list.length > 0) {
|
|
|
- this.queryCondition.selectedDeviceId = list[0].id;
|
|
|
- this.fetchData();
|
|
|
+ // 判断返回结构
|
|
|
+ if (res && res.list) {
|
|
|
+ this.devices = res.list;
|
|
|
+ console.log("设备列表:", this.devices);
|
|
|
+ if (this.devices.length > 0) {
|
|
|
+ this.selectedDeviceId = this.devices[0].id;
|
|
|
+ console.log("选中的设备ID:", this.selectedDeviceId);
|
|
|
+ // 获取该设备的信息
|
|
|
+ await this.handleSearch();
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ this.devices = [];
|
|
|
+ this.$message.warning("未获取到设备数据");
|
|
|
}
|
|
|
- } catch (e) {
|
|
|
- console.error("获取设备信息失败:", e);
|
|
|
- this.$message.error("获取设备列表失败");
|
|
|
+ } catch (error) {
|
|
|
+ console.error("获取设备信息失败:", error);
|
|
|
+ this.$message.error("获取设备列表失败,请检查网络或后端接口!");
|
|
|
} finally {
|
|
|
this.loading = false;
|
|
|
}
|
|
|
@@ -367,19 +340,3 @@ export default {
|
|
|
},
|
|
|
};
|
|
|
</script>
|
|
|
-
|
|
|
-<style scoped>
|
|
|
-.vehicle-access-container {
|
|
|
- padding: 10px;
|
|
|
-}
|
|
|
-.toolbar {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- gap: 10px;
|
|
|
- margin-bottom: 10px;
|
|
|
-}
|
|
|
-.pagination {
|
|
|
- text-align: right;
|
|
|
- margin-top: 15px;
|
|
|
-}
|
|
|
-</style>
|