zouyu
20 小时以前 6d2f26e4c867c1cfba4ebe86d4162edb01da80a0
src/views/environmentAccess/vehicleInformationCollection/index.vue
@@ -1,9 +1,577 @@
<template>
  <div></div>
  <div class="app-container">
    <el-form :model="filters" :inline="true">
      <el-form-item label="车牌号码">
        <el-input
          v-model="filters.plateNumber"
          style="width: 240px"
          placeholder="请输入车牌号码"
          clearable
          :prefix-icon="Search"
          @change="getTableData"
        />
      </el-form-item>
      <el-form-item label="车辆类型">
        <el-select
          v-model="filters.vehicleType"
          style="width: 240px"
          placeholder="请选择车辆类型"
          clearable
          @change="getTableData"
        >
          <el-option label="小型车" value="0"></el-option>
          <el-option label="中型车" value="1"></el-option>
          <el-option label="大型车" value="2"></el-option>
          <el-option label="特种车" value="3"></el-option>
        </el-select>
      </el-form-item>
      <el-form-item label="进出方向">
        <el-select
          v-model="filters.direction"
          style="width: 240px"
          placeholder="请选择进出方向"
          clearable
          @change="getTableData"
        >
          <el-option label="进" value="0"></el-option>
          <el-option label="出" value="1"></el-option>
        </el-select>
      </el-form-item>
      <el-form-item label="进出时间">
        <el-date-picker
          v-model="filters.timeRange"
          type="daterange"
          start-placeholder="开始时间"
          end-placeholder="结束时间"
          value-format="YYYY-MM-DD HH:mm:ss"
          format="YYYY-MM-DD HH:mm"
          clearable
          @change="changeTimeRange"
        />
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="getTableData">搜索</el-button>
        <el-button @click="resetFilters">重置</el-button>
      </el-form-item>
    </el-form>
    <div class="vehicle-stats">
      <div class="stat-card">
        <div class="stat-title">今日进车数</div>
        <div class="stat-value in">{{ todayInCount }}</div>
      </div>
      <div class="stat-card">
        <div class="stat-title">今日出车数</div>
        <div class="stat-value out">{{ todayOutCount }}</div>
      </div>
      <div class="stat-card">
        <div class="stat-title">当前在场车辆</div>
        <div class="stat-value present">{{ presentCount }}</div>
      </div>
      <div class="stat-card">
        <div class="stat-title">今日总流量</div>
        <div class="stat-value total">{{ todayTotalCount }}</div>
      </div>
    </div>
    <div class="table_list">
      <PIMTable
        rowKey="id"
        :column="columns"
        :tableData="dataList"
        :page="{
          current: pagination.currentPage,
          size: pagination.pageSize,
          total: pagination.total,
        }"
        @pagination="changePage"
      >
      </PIMTable>
    </div>
    <!-- 车辆详情弹窗 -->
    <el-dialog
      v-model="detailVisible"
      :title="`车辆详情 - ${selectedVehicle.plateNumber}`"
      width="700px"
    >
      <div v-if="selectedVehicle" class="vehicle-detail">
        <div class="detail-section">
          <h3>基本信息</h3>
          <el-descriptions :column="2" border>
            <el-descriptions-item label="车牌号码">{{
              selectedVehicle.plateNumber
            }}</el-descriptions-item>
            <el-descriptions-item label="车辆类型">{{
              typeMap[selectedVehicle.vehicleType]
            }}</el-descriptions-item>
            <el-descriptions-item label="车辆颜色">{{
              selectedVehicle.color
            }}</el-descriptions-item>
            <el-descriptions-item label="进出方向">{{
              selectedVehicle.direction === "0" ? "进" : "出"
            }}</el-descriptions-item>
            <el-descriptions-item label="进出时间">{{
              selectedVehicle.timestamp
            }}</el-descriptions-item>
            <el-descriptions-item label="通道名称">{{
              selectedVehicle.channelName
            }}</el-descriptions-item>
            <el-descriptions-item label="识别方式">{{
              selectedVehicle.identifyMethod
            }}</el-descriptions-item>
            <el-descriptions-item label="车辆状态">{{
              statusMap[selectedVehicle.status]
            }}</el-descriptions-item>
          </el-descriptions>
        </div>
        <div class="detail-section">
          <h3>车辆图片</h3>
          <div class="vehicle-images">
            <div class="image-item">
              <div class="image-title">正面图片</div>
              <el-image
                :src="selectedVehicle.frontImage"
                fit="cover"
                style="width: 100%; height: 200px"
                :preview-src-list="[
                  selectedVehicle.frontImage,
                  selectedVehicle.sideImage,
                ]"
              ></el-image>
            </div>
            <div class="image-item">
              <div class="image-title">侧面图片</div>
              <el-image
                :src="selectedVehicle.sideImage"
                fit="cover"
                style="width: 100%; height: 200px"
                :preview-src-list="[
                  selectedVehicle.sideImage,
                  selectedVehicle.frontImage,
                ]"
              ></el-image>
            </div>
          </div>
        </div>
      </div>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="detailVisible = false">关闭</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>
<script>
<script setup>
import { ref, reactive, computed, onMounted } from "vue";
import { Search } from "@element-plus/icons-vue";
import dayjs from "dayjs";
// 定义假数据
const mockVehicles = [
  {
    id: 1,
    plateNumber: "京A12345",
    vehicleType: "0",
    color: "白色",
    direction: "0",
    timestamp: "2025-12-31 08:15:30",
    channelName: "东门通道",
    identifyMethod: "车牌识别",
    status: "0",
    frontImage: "https://picsum.photos/id/1024/800/600",
    sideImage: "https://picsum.photos/id/1025/800/600",
    duration: "00:00:00",
    present: true,
  },
  {
    id: 2,
    plateNumber: "沪B67890",
    vehicleType: "1",
    color: "黑色",
    direction: "1",
    timestamp: "2025-12-31 08:10:20",
    channelName: "西门通道",
    identifyMethod: "车牌识别",
    status: "1",
    frontImage: "https://picsum.photos/id/1026/800/600",
    sideImage: "https://picsum.photos/id/1027/800/600",
    duration: "01:25:30",
    present: false,
  },
  {
    id: 3,
    plateNumber: "粤C54321",
    vehicleType: "0",
    color: "红色",
    direction: "0",
    timestamp: "2025-12-31 08:05:15",
    channelName: "南门通道",
    identifyMethod: "IC卡识别",
    status: "0",
    frontImage: "https://picsum.photos/id/1028/800/600",
    sideImage: "https://picsum.photos/id/1029/800/600",
    duration: "00:05:45",
    present: true,
  },
  {
    id: 4,
    plateNumber: "川D98765",
    vehicleType: "2",
    color: "蓝色",
    direction: "0",
    timestamp: "2025-12-31 08:00:00",
    channelName: "北门通道",
    identifyMethod: "车牌识别",
    status: "0",
    frontImage: "https://picsum.photos/id/1030/800/600",
    sideImage: "https://picsum.photos/id/1031/800/600",
    duration: "00:10:30",
    present: true,
  },
  {
    id: 5,
    plateNumber: "苏E13579",
    vehicleType: "0",
    color: "银色",
    direction: "1",
    timestamp: "2025-12-31 07:55:45",
    channelName: "东门通道",
    identifyMethod: "车牌识别",
    status: "1",
    frontImage: "https://picsum.photos/id/1032/800/600",
    sideImage: "https://picsum.photos/id/1033/800/600",
    duration: "02:30:15",
    present: false,
  },
  {
    id: 6,
    plateNumber: "浙F24680",
    vehicleType: "3",
    color: "黄色",
    direction: "0",
    timestamp: "2025-12-31 07:50:30",
    channelName: "南门通道",
    identifyMethod: "人工登记",
    status: "0",
    frontImage: "https://picsum.photos/id/1034/800/600",
    sideImage: "https://picsum.photos/id/1035/800/600",
    duration: "00:15:30",
    present: true,
  },
  {
    id: 7,
    plateNumber: "鲁G97531",
    vehicleType: "1",
    color: "绿色",
    direction: "1",
    timestamp: "2025-12-31 07:45:15",
    channelName: "西门通道",
    identifyMethod: "车牌识别",
    status: "1",
    frontImage: "https://picsum.photos/id/1036/800/600",
    sideImage: "https://picsum.photos/id/1037/800/600",
    duration: "01:45:30",
    present: false,
  },
  {
    id: 8,
    plateNumber: "豫H86420",
    vehicleType: "0",
    color: "灰色",
    direction: "0",
    timestamp: "2025-12-31 07:40:00",
    channelName: "北门通道",
    identifyMethod: "IC卡识别",
    status: "0",
    frontImage: "https://picsum.photos/id/1038/800/600",
    sideImage: "https://picsum.photos/id/1039/800/600",
    duration: "00:20:15",
    present: true,
  },
];
// 响应式数据
const filters = reactive({
  plateNumber: "",
  vehicleType: "",
  direction: "",
  timeRange: [],
});
const dataList = ref([]);
const pagination = reactive({
  currentPage: 1,
  pageSize: 10,
  total: 0,
});
const detailVisible = ref(false);
const selectedVehicle = ref({});
// 时间范围
const timeRange = reactive({
  startTime: "",
  endTime: "",
});
// 状态映射
const statusMap = {
  '0': '<el-tag type="success">正常</el-tag>',
  '1': '<el-tag type="info">已离开</el-tag>',
  '2': '<el-tag type="warning">异常</el-tag>',
};
// 类型映射
const typeMap = {
  0: "小型车",
  1: "中型车",
  2: "大型车",
  3: "特种车",
};
// 统计数据
const todayInCount = computed(() => {
  const today = dayjs().format("YYYY-MM-DD");
  return mockVehicles.filter((vehicle) => {
    return vehicle.direction === "0" && vehicle.timestamp.startsWith(today);
  }).length;
});
const todayOutCount = computed(() => {
  const today = dayjs().format("YYYY-MM-DD");
  return mockVehicles.filter((vehicle) => {
    return vehicle.direction === "1" && vehicle.timestamp.startsWith(today);
  }).length;
});
const presentCount = computed(() => {
  return mockVehicles.filter((vehicle) => vehicle.present).length;
});
const todayTotalCount = computed(() => {
  const today = dayjs().format("YYYY-MM-DD");
  return mockVehicles.filter((vehicle) => {
    return vehicle.timestamp.startsWith(today);
  }).length;
});
// 表格列配置
const columns = [
  {
    label: "车牌号码",
    align: "center",
    prop: "plateNumber",
  },
  {
    label: "车辆类型",
    align: "center",
    prop: "vehicleType",
    formatter: (row) => {
      return typeMap[row.vehicleType];
    },
  },
  {
    label: "车辆颜色",
    align: "center",
    prop: "color",
  },
  {
    label: "进出方向",
    align: "center",
    prop: "direction",
    formatter: (row) => {
      return row.direction === "0" ? '<el-tag type="success">进</el-tag>' : '<el-tag type="info">出</el-tag>';
    },
  },
  {
    label: "进出时间",
    align: "center",
    prop: "timestamp",
  },
  {
    label: "通道名称",
    align: "center",
    prop: "channelName",
  },
  {
    label: "识别方式",
    align: "center",
    prop: "identifyMethod",
  },
  {
    label: "车辆状态",
    align: "center",
    prop: "status",
    formatter: (row) => {
      return statusMap[row.status];
    },
  },
  {
    dataType: "action",
    label: "操作",
    align: "center",
    fixed: "right",
    width: 140,
    operation: [
      {
        name: "查看详情",
        type: "text",
        clickFun: (row) => {
          viewDetail(row);
        },
      },
    ],
  },
];
// 过滤后的数据
const filteredData = computed(() => {
  return mockVehicles.filter((item) => {
    const plateMatch =
      !filters.plateNumber || item.plateNumber.includes(filters.plateNumber);
    const typeMatch =
      !filters.vehicleType || item.vehicleType === filters.vehicleType;
    const directionMatch =
      !filters.direction || item.direction === filters.direction;
    const timeMatch =
      !timeRange.startTime ||
      (item.timestamp >= timeRange.startTime &&
        item.timestamp <= timeRange.endTime);
    return plateMatch && typeMatch && directionMatch && timeMatch;
  });
});
// 获取表格数据
const getTableData = () => {
  pagination.total = filteredData.value.length;
  const start = (pagination.currentPage - 1) * pagination.pageSize;
  const end = start + pagination.pageSize;
  dataList.value = filteredData.value.slice(start, end);
};
// 重置过滤器
const resetFilters = () => {
  filters.plateNumber = "";
  filters.vehicleType = "";
  filters.direction = "";
  filters.timeRange = [];
  timeRange.startTime = "";
  timeRange.endTime = "";
  pagination.currentPage = 1;
  getTableData();
};
// 分页变化
const changePage = ({ page, limit }) => {
  pagination.currentPage = page;
  pagination.pageSize = limit;
  getTableData();
};
// 时间范围变化
const changeTimeRange = (value) => {
  if (value && value.length === 2) {
    timeRange.startTime = value[0];
    timeRange.endTime = value[1];
  } else {
    timeRange.startTime = "";
    timeRange.endTime = "";
  }
  getTableData();
};
// 查看车辆详情
const viewDetail = (row) => {
  selectedVehicle.value = row;
  detailVisible.value = true;
};
// 初始化数据
onMounted(() => {
  getTableData();
});
</script>
<style>
<style lang="scss" scoped>
.table_list {
  margin-top: unset;
}
.vehicle-stats {
  display: flex;
  gap: 20px;
  margin-bottom: 20px;
  .stat-card {
    flex: 1;
    background: #fff;
    padding: 20px;
    border-radius: 8px;
    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
    text-align: center;
    .stat-title {
      font-size: 14px;
      color: #606266;
      margin-bottom: 10px;
    }
    .stat-value {
      font-size: 32px;
      font-weight: bold;
      &.in {
        color: #67c23a;
      }
      &.out {
        color: #409eff;
      }
      &.present {
        color: #e6a23c;
      }
      &.total {
        color: #909399;
      }
    }
  }
}
.vehicle-detail {
  .detail-section {
    margin-bottom: 20px;
    h3 {
      font-size: 16px;
      font-weight: bold;
      margin-bottom: 10px;
      color: #303133;
    }
  }
  .vehicle-images {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 15px;
    .image-item {
      background: #f5f7fa;
      padding: 15px;
      border-radius: 8px;
      .image-title {
        font-size: 14px;
        color: #606266;
        margin-bottom: 10px;
        text-align: center;
      }
    }
  }
}
</style>