feat(rfid): 新增RFID设备和读取记录管理视图

- 实现RFID设备列表、查询、添加、修改、删除及导出功能
- 实现读取记录列表、查询、添加、修改、删除及导出功能
- 设备管理支持位置选择、在线状态、告警状态及标识筛选
- 读取记录支持设备选择、读取状态、条码信息、记录时间、告警标志等筛选
- 首页新增设备统计卡片显示设备总数、在线、离线及告警设备数量
- 首页新增设备列表及告警状态快速查看与页面跳转功能
main
zangch@mesnac.com 3 weeks ago
parent 748754c82c
commit ba37248df3

@ -1,165 +1,254 @@
<template>
<div class="app-container home">
<el-row :gutter="20">
<el-col :sm="24" :lg="12" style="padding-left: 20px">
<h2>RuoYi-Vue-Plus多租户管理系统</h2>
<p>
RuoYi-Vue-Plus 是基于 RuoYi-Vue 针对 分布式集群 场景升级(不兼容原框架)
<br />
* 前端开发框架 Vue3TSElement Plus<br />
* 后端开发框架 Spring Boot<br />
* 容器框架 Undertow 基于 Netty 的高性能容器<br />
* 权限认证框架 Sa-Token 支持多终端认证系统<br />
* 关系数据库 MySQL 适配 8.X 最低 5.7<br />
* 缓存数据库 Redis 适配 6.X 最低 4.X<br />
* 数据库框架 Mybatis-Plus 快速 CRUD 增加开发效率<br />
* 数据库框架 p6spy 更强劲的 SQL 分析<br />
* 多数据源框架 dynamic-datasource 支持主从与多种类数据库异构<br />
* 序列化框架 Jackson 统一使用 jackson 高效可靠<br />
* Redis客户端 Redisson 性能强劲API丰富<br />
* 分布式限流 Redisson 全局请求IP集群ID 多种限流<br />
* 分布式锁 Lock4j 注解锁工具锁 多种多样<br />
* 分布式幂等 Lock4j 基于分布式锁实现<br />
* 分布式链路追踪 SkyWalking 支持链路追踪网格分析度量聚合可视化<br />
* 分布式任务调度 SnailJob 高性能 高可靠 易扩展<br />
* 文件存储 Minio 本地存储<br />
* 文件存储 七牛阿里腾讯 云存储<br />
* 监控框架 SpringBoot-Admin 全方位服务监控<br />
* 校验框架 Validation 增强接口安全性 严谨性<br />
* Excel框架 FastExcel(原Alibaba EasyExcel) 性能优异 扩展性强<br />
* 文档框架 SpringDocjavadoc 无注解零入侵基于java注释<br />
* 工具类框架 HutoolLombok 减少代码冗余 增加安全性<br />
* 代码生成器 适配MPSpringDoc规范化代码 一键生成前后端代码<br />
* 部署方式 Docker 容器编排 一键部署业务集群<br />
* 国际化 SpringMessage Spring标准国际化方案<br />
</p>
<p><b>当前版本:</b> <span>v5.5.1</span></p>
<p>
<el-tag type="danger">&yen;免费开源</el-tag>
</p>
<p>
<el-button type="primary" icon="Cloudy" plain @click="goTarget('https://gitee.com/dromara/RuoYi-Vue-Plus')">访</el-button>
<el-button type="primary" icon="Cloudy" plain @click="goTarget('https://github.com/dromara/RuoYi-Vue-Plus')">访GitHub</el-button>
<el-button type="primary" icon="Cloudy" plain @click="goTarget('https://plus-doc.dromara.org/#/ruoyi-vue-plus/changlog')"
>更新日志</el-button
>
</p>
<!-- 统计卡片 -->
<el-row :gutter="16" class="mb-4">
<el-col :xs="12" :sm="12" :md="6">
<el-card shadow="hover" class="stat-card">
<div class="stat-card-inner">
<div class="stat-icon bg-primary"><el-icon :size="28"><Monitor /></el-icon></div>
<div class="stat-content">
<div class="stat-title">设备总数</div>
<div class="stat-value">{{ stats.totalDevices || 0 }}</div>
</div>
</div>
</el-card>
</el-col>
<el-col :sm="24" :lg="12" style="padding-left: 20px">
<h2>RuoYi-Cloud-Plus多租户微服务管理系统</h2>
<p>
RuoYi-Cloud-Plus 微服务通用权限管理系统 重写 RuoYi-Cloud 全方位升级(不兼容原框架)
<br />
* 前端开发框架 Vue3TSElement UI<br />
* 后端开发框架 Spring Boot<br />
* 微服务开发框架 Spring CloudSpring Cloud Alibaba<br />
* 容器框架 Undertow 基于 XNIO 的高性能容器<br />
* 权限认证框架 Sa-TokenJwt 支持多终端认证系统<br />
* 关系数据库 MySQL 适配 8.X 最低 5.7<br />
* 关系数据库 Oracle 适配 11g 12c<br />
* 关系数据库 PostgreSQL 适配 13 14<br />
* 关系数据库 SQLServer 适配 2017 2019<br />
* 缓存数据库 Redis 适配 6.X 最低 5.X<br />
* 分布式注册中心 Alibaba Nacos 采用2.X 基于GRPC通信高性能<br />
* 分布式配置中心 Alibaba Nacos 采用2.X 基于GRPC通信高性能<br />
* 服务网关 Spring Cloud Gateway 响应式高性能网关<br />
* 负载均衡 Spring Cloud Loadbalancer 负载均衡处理<br />
* RPC远程调用 Apache Dubbo 原生态使用体验高性能<br />
* 分布式限流熔断 Alibaba Sentinel 无侵入高扩展<br />
* 分布式事务 Alibaba Seata 无侵入高扩展 支持 四种模式<br />
* 分布式消息队列 Apache Kafka 高性能高速度<br />
* 分布式消息队列 Apache RocketMQ 高可用功能多样<br />
* 分布式消息队列 RabbitMQ 支持各种扩展插件功能多样性<br />
* 分布式搜索引擎 ElasticSearch 业界知名<br />
* 分布式链路追踪 Apache SkyWalking 链路追踪网格分析度量聚合可视化<br />
* 分布式日志中心 ELK 业界成熟解决方案<br />
* 分布式监控 PrometheusGrafana 全方位性能监控<br />
* 其余与 Vue 版本一致<br />
</p>
<p><b>当前版本:</b> <span>v2.5.1</span></p>
<p>
<el-tag type="danger">&yen;免费开源</el-tag>
</p>
<p>
<el-button type="primary" icon="Cloudy" plain @click="goTarget('https://gitee.com/dromara/RuoYi-Cloud-Plus')">访</el-button>
<el-button type="primary" icon="Cloudy" plain @click="goTarget('https://github.com/dromara/RuoYi-Cloud-Plus')">访GitHub</el-button>
<el-button type="primary" icon="Cloudy" plain @click="goTarget('https://plus-doc.dromara.org/#/ruoyi-cloud-plus/changlog')"
>更新日志</el-button
>
</p>
<el-col :xs="12" :sm="12" :md="6">
<el-card shadow="hover" class="stat-card">
<div class="stat-card-inner">
<div class="stat-icon bg-success"><el-icon :size="28"><CircleCheck /></el-icon></div>
<div class="stat-content">
<div class="stat-title">在线设备</div>
<div class="stat-value text-success">{{ stats.onlineDevices || 0 }}</div>
</div>
</div>
</el-card>
</el-col>
<el-col :xs="12" :sm="12" :md="6">
<el-card shadow="hover" class="stat-card">
<div class="stat-card-inner">
<div class="stat-icon bg-warning"><el-icon :size="28"><CircleClose /></el-icon></div>
<div class="stat-content">
<div class="stat-title">离线设备</div>
<div class="stat-value text-warning">{{ stats.offlineDevices || 0 }}</div>
</div>
</div>
</el-card>
</el-col>
<el-col :xs="12" :sm="12" :md="6">
<el-card shadow="hover" class="stat-card">
<div class="stat-card-inner">
<div class="stat-icon bg-danger"><el-icon :size="28"><Warning /></el-icon></div>
<div class="stat-content">
<div class="stat-title">告警设备</div>
<div class="stat-value text-danger">{{ stats.alarmDevices || 0 }}</div>
</div>
</div>
</el-card>
</el-col>
</el-row>
<!-- 设备列表与告警记录 -->
<el-row :gutter="16">
<el-col :xs="24" :md="14">
<el-card shadow="hover">
<template #header>
<div class="card-header">
<span>设备列表</span>
<el-button type="primary" link @click="$router.push('/base/rfidDevice')"></el-button>
</div>
</template>
<el-table :data="deviceList" border stripe max-height="400" empty-text="">
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="deviceCode" label="设备编号" min-width="120" />
<el-table-column prop="deviceName" label="设备名称" min-width="120" />
<el-table-column prop="locationAlias" label="所在位置" min-width="100">
<template #default="{ row }">{{ row.locationAlias || '-' }}</template>
</el-table-column>
<el-table-column prop="onlineStatus" label="在线状态" width="100" align="center">
<template #default="{ row }">
<el-tag :type="row.onlineStatus === '1' ? 'success' : 'info'" size="small">
{{ row.onlineStatus === '1' ? '在线' : '离线' }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="alarmStatus" label="告警状态" width="100" align="center">
<template #default="{ row }">
<el-tag :type="row.alarmStatus === '1' ? 'danger' : 'success'" size="small">
{{ row.alarmStatus === '1' ? '告警' : '正常' }}
</el-tag>
</template>
</el-table-column>
</el-table>
</el-card>
</el-col>
<el-col :xs="24" :md="10">
<el-card shadow="hover">
<template #header>
<div class="card-header">
<span>告警记录</span>
<el-button type="primary" link @click="$router.push('/base/rfidReadRecord')"></el-button>
</div>
</template>
<el-table :data="alarmList" border stripe max-height="400" empty-text="">
<el-table-column type="index" label="序号" width="60" align="center" />
<el-table-column prop="deviceName" label="设备" min-width="100">
<template #default="{ row }">{{ row.deviceName || row.deviceCode || '-' }}</template>
</el-table-column>
<el-table-column prop="recordTime" label="时间" min-width="140">
<template #default="{ row }">{{ formatRecordTime(row.recordTime) }}</template>
</el-table-column>
<el-table-column prop="alarmLevel" label="级别" width="80" align="center">
<template #default="{ row }">
<el-tag :type="row.alarmLevel === '2' ? 'danger' : 'warning'" size="small">
{{ row.alarmLevel === '2' ? '严重' : (row.alarmLevel === '1' ? '一般' : '-') }}
</el-tag>
</template>
</el-table-column>
<el-table-column prop="alarmAction" label="行为" min-width="80">
<template #default="{ row }">{{ row.alarmAction || '-' }}</template>
</el-table-column>
</el-table>
</el-card>
</el-col>
</el-row>
<el-divider />
</div>
</template>
<script setup name="Index" lang="ts">
const goTarget = (url: string) => {
window.open(url, '__blank');
import { getDashboardStats } from "@/api/rfid/dashboard";
import { getRfidDeviceList } from "@/api/rfid/rfidDevice";
import { getRfidReadRecordList } from "@/api/rfid/rfidReadRecord";
import type { RfidDeviceVO } from "@/api/rfid/rfidDevice/types";
import type { RfidReadRecordVO } from "@/api/rfid/rfidReadRecord/types";
const stats = ref({
totalDevices: 0,
onlineDevices: 0,
offlineDevices: 0,
alarmDevices: 0
});
const deviceList = ref<RfidDeviceVO[]>([]);
const alarmList = ref<RfidReadRecordVO[]>([]);
const loadStats = async () => {
try {
const res = await getDashboardStats();
if (res.data) {
stats.value = res.data;
}
} catch (e) {
console.error("获取统计数据失败", e);
}
};
const loadDeviceList = async () => {
try {
const res: any = await getRfidDeviceList({ isMarked: "1" } as any);
deviceList.value = res.data || [];
} catch (e) {
console.error("获取设备列表失败", e);
}
};
const loadAlarmList = async () => {
try {
const res: any = await getRfidReadRecordList({ alarmFlag: "1" } as any);
alarmList.value = res.data || [];
} catch (e) {
console.error("获取告警记录失败", e);
}
};
const formatRecordTime = (val: any) => {
if (!val) {
return "-";
}
return String(val).replace("T", " ");
};
onMounted(() => {
loadStats();
loadDeviceList();
loadAlarmList();
});
</script>
<style lang="scss" scoped>
.home {
blockquote {
padding: 10px 20px;
margin: 0 0 20px;
font-size: 17.5px;
border-left: 5px solid #eee;
}
hr {
margin-top: 20px;
margin-bottom: 20px;
border: 0;
border-top: 1px solid #eee;
}
.col-item {
margin-bottom: 20px;
padding: 16px;
.mb-4 {
margin-bottom: 16px;
}
ul {
padding: 0;
margin: 0;
}
font-family: 'open sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-size: 13px;
color: #676a6c;
overflow-x: hidden;
ul {
list-style-type: none;
}
h4 {
margin-top: 0px;
}
h2 {
margin-top: 10px;
font-size: 26px;
font-weight: 100;
}
p {
margin-top: 10px;
b {
font-weight: 700;
//
.stat-card {
:deep(.el-card__body) {
padding: 16px 20px;
}
}
.update-log {
ol {
display: block;
list-style-type: decimal;
margin-block-start: 1em;
margin-block-end: 1em;
margin-inline-start: 0;
margin-inline-end: 0;
padding-inline-start: 40px;
.stat-card-inner {
display: flex;
align-items: center;
}
.stat-icon {
width: 56px;
height: 56px;
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
margin-right: 16px;
flex-shrink: 0;
&.bg-primary { background: linear-gradient(135deg, #409eff, #53a8ff); }
&.bg-success { background: linear-gradient(135deg, #67c23a, #85ce61); }
&.bg-warning { background: linear-gradient(135deg, #e6a23c, #ebb563); }
&.bg-danger { background: linear-gradient(135deg, #f56c6c, #f78989); }
}
.stat-content {
flex: 1;
min-width: 0;
.stat-title {
font-size: 14px;
color: #909399;
margin-bottom: 4px;
}
.stat-value {
font-size: 28px;
font-weight: 600;
color: #303133;
&.text-success { color: #67c23a; }
&.text-warning { color: #e6a23c; }
&.text-danger { color: #f56c6c; }
}
}
//
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
span {
font-size: 16px;
font-weight: 600;
color: #303133;
}
}
//
:deep(.el-card__body) {
padding: 16px;
}
}
</style>

@ -0,0 +1,423 @@
<template>
<div class="p-2">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
<el-form-item label="设备编号" prop="deviceCode">
<el-input v-model="queryParams.deviceCode" placeholder="请输入设备编号" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="设备名称" prop="deviceName">
<el-input v-model="queryParams.deviceName" placeholder="请输入设备名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="所在位置" prop="locationId">
<el-tree-select
v-model="queryParams.locationId"
:data="locationOptions"
:props="{ value: 'id', label: 'locationAlias', children: 'children' }"
value-key="id"
placeholder="请选择所在位置"
check-strictly
clearable
/>
</el-form-item>
<!-- 以下为不常用搜索条件按需开放 -->
<!--
<el-form-item label="设备地址" prop="deviceAddress">
<el-input v-model="queryParams.deviceAddress" placeholder="请输入设备地址" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="设备端口" prop="devicePort">
<el-input-number v-model="queryParams.devicePort" :min="0" :max="65535" placeholder="请输入设备端口" controls-position="right" />
</el-form-item>
<el-form-item label="读取频率" prop="readFrequency">
<el-input-number v-model="queryParams.readFrequency" :min="0" placeholder="请输入读取频率" controls-position="right" />
</el-form-item>
-->
<el-form-item label="在线状态" prop="onlineStatus">
<el-select v-model="queryParams.onlineStatus" placeholder="请选择在线状态" clearable >
<el-option v-for="dict in online_status" :key="dict.value" :label="dict.label" :value="dict.value"/>
</el-select>
</el-form-item>
<el-form-item label="告警状态" prop="alarmStatus">
<el-select v-model="queryParams.alarmStatus" placeholder="请选择告警状态" clearable >
<el-option v-for="dict in alarm_status" :key="dict.value" :label="dict.label" :value="dict.value"/>
</el-select>
</el-form-item>
<el-form-item label="是否标识" prop="isMarked">
<el-select v-model="queryParams.isMarked" placeholder="请选择是否标识" clearable >
<el-option v-for="dict in is_marked" :key="dict.value" :label="dict.label" :value="dict.value"/>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery"></el-button>
<el-button icon="Refresh" @click="resetQuery"></el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</transition>
<el-card shadow="never">
<template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['rfid:rfidDevice:add']"></el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['rfid:rfidDevice:edit']"></el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['rfid:rfidDevice:remove']"></el-button>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['rfid:rfidDevice:export']"></el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
</template>
<el-table v-loading="loading" border :data="rfidDeviceList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column type="index" width="55" align="center" label="序号" />
<el-table-column label="设备编号" align="center" prop="deviceCode" />
<el-table-column label="设备名称" align="center" prop="deviceName" />
<el-table-column label="所在位置" align="center" prop="locationAlias" />
<el-table-column label="设备地址" align="center" prop="deviceAddress" />
<el-table-column label="设备端口" align="center" prop="devicePort" />
<el-table-column label="读取频率" align="center" prop="readFrequency" />
<el-table-column label="在线状态" align="center" prop="onlineStatus">
<template #default="scope">
<dict-tag :options="online_status" :value="scope.row.onlineStatus"/>
</template>
</el-table-column>
<el-table-column label="告警状态" align="center" prop="alarmStatus">
<template #default="scope">
<dict-tag :options="alarm_status" :value="scope.row.alarmStatus"/>
</template>
</el-table-column>
<el-table-column label="是否标识" align="center" prop="isMarked">
<template #default="scope">
<dict-tag :options="is_marked" :value="scope.row.isMarked"/>
</template>
</el-table-column>
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="创建人" align="center" prop="createdBy" />
<el-table-column label="创建时间" align="center" prop="createdAt" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.createdAt, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="更新人" align="center" prop="updatedBy" />
<el-table-column label="更新时间" align="center" prop="updatedAt" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.updatedAt, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
<template #default="scope">
<el-tooltip content="修改" placement="top">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['rfid:rfidDevice:edit']"></el-button>
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['rfid:rfidDevice:remove']"></el-button>
</el-tooltip>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
</el-card>
<!-- 添加或修改设备信息对话框 -->
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
<el-form ref="rfidDeviceFormRef" :model="form" :rules="rules" label-width="80px">
<el-form-item label="设备编号" prop="deviceCode">
<el-input v-model="form.deviceCode" placeholder="请输入设备编号" />
</el-form-item>
<el-form-item label="设备名称" prop="deviceName">
<el-input v-model="form.deviceName" placeholder="请输入设备名称" />
</el-form-item>
<el-form-item label="所在位置" prop="locationId">
<el-tree-select
v-model="form.locationId"
:data="locationOptions"
:props="{ value: 'id', label: 'locationAlias', children: 'children' }"
value-key="id"
placeholder="请选择所在位置"
check-strictly
clearable
/>
</el-form-item>
<el-form-item label="设备地址" prop="deviceAddress">
<el-input v-model="form.deviceAddress" placeholder="请输入设备地址" />
</el-form-item>
<el-form-item label="设备端口" prop="devicePort">
<el-input-number v-model="form.devicePort" :min="0" :max="65535" placeholder="请输入设备端口" controls-position="right" style="width: 100%" />
</el-form-item>
<el-form-item label="读取频率" prop="readFrequency">
<el-input-number v-model="form.readFrequency" :min="0" placeholder="请输入读取频率" controls-position="right" style="width: 100%" />
</el-form-item>
<el-form-item label="在线状态" prop="onlineStatus">
<el-radio-group v-model="form.onlineStatus">
<el-radio
v-for="dict in online_status"
:key="dict.value"
:value="dict.value"
>{{dict.label}}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="告警状态" prop="alarmStatus">
<el-radio-group v-model="form.alarmStatus">
<el-radio
v-for="dict in alarm_status"
:key="dict.value"
:value="dict.value"
>{{dict.label}}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="是否标识" prop="isMarked">
<el-radio-group v-model="form.isMarked">
<el-radio
v-for="dict in is_marked"
:key="dict.value"
:value="dict.value"
>{{dict.label}}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" placeholder="请输入备注" />
</el-form-item>
<!-- 以下为审计字段输入默认由后端维护前端不提供编辑入口如有需要再放开 -->
<!--
<el-form-item label="创建人" prop="createdBy">
<el-input v-model="form.createdBy" placeholder="请输入创建人" />
</el-form-item>
<el-form-item label="创建时间" prop="createdAt">
<el-date-picker clearable
v-model="form.createdAt"
type="datetime"
value-format="YYYY-MM-DD HH:mm:ss"
placeholder="请选择创建时间">
</el-date-picker>
</el-form-item>
<el-form-item label="更新人" prop="updatedBy">
<el-input v-model="form.updatedBy" placeholder="请输入更新人" />
</el-form-item>
<el-form-item label="更新时间" prop="updatedAt">
<el-date-picker clearable
v-model="form.updatedAt"
type="datetime"
value-format="YYYY-MM-DD HH:mm:ss"
placeholder="请选择更新时间">
</el-date-picker>
</el-form-item>
-->
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button :loading="buttonLoading" type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup name="RfidDevice" lang="ts">
import { listRfidDevice, getRfidDevice, delRfidDevice, addRfidDevice, updateRfidDevice } from "@/api/rfid/rfidDevice";
import { RfidDeviceVO, RfidDeviceQuery, RfidDeviceForm } from '@/api/rfid/rfidDevice/types';
import { getRfidLocationList } from "@/api/rfid/rfidLocation";
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { alarm_status, online_status, is_marked } = toRefs<any>(proxy?.useDict('alarm_status', 'online_status', 'is_marked'));
type RfidLocationOption = {
id: number;
locationAlias: string;
children?: RfidLocationOption[];
}
const rfidDeviceList = ref<RfidDeviceVO[]>([]);
const buttonLoading = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const locationOptions = ref<RfidLocationOption[]>([]);
const queryFormRef = ref<ElFormInstance>();
const rfidDeviceFormRef = ref<ElFormInstance>();
const dialog = reactive<DialogOption>({
visible: false,
title: ''
});
const initFormData: RfidDeviceForm = {
id: undefined,
deviceCode: undefined,
deviceName: undefined,
locationId: undefined,
deviceAddress: undefined,
devicePort: undefined,
readFrequency: undefined,
onlineStatus: undefined,
alarmStatus: undefined,
isMarked: '1',
remark: undefined,
createdBy: undefined,
createdAt: undefined,
updatedBy: undefined,
updatedAt: undefined
}
const data = reactive<PageData<RfidDeviceForm, RfidDeviceQuery>>({
form: {...initFormData},
queryParams: {
pageNum: 1,
pageSize: 10,
deviceCode: undefined,
deviceName: undefined,
locationId: undefined,
deviceAddress: undefined,
devicePort: undefined,
readFrequency: undefined,
onlineStatus: undefined,
alarmStatus: undefined,
isMarked: undefined,
createdBy: undefined,
createdAt: undefined,
updatedBy: undefined,
updatedAt: undefined,
params: {
}
},
rules: {
id: [
{ required: true, message: "标识不能为空", trigger: "blur" }
],
deviceCode: [
{ required: true, message: "设备编号不能为空", trigger: "blur" }
],
deviceName: [
{ required: true, message: "设备名称不能为空", trigger: "blur" }
],
onlineStatus: [
{ required: true, message: "在线状态不能为空", trigger: "change" }
],
alarmStatus: [
{ required: true, message: "告警状态不能为空", trigger: "change" }
],
isMarked: [
{ required: true, message: "是否标识不能为空", trigger: "change" }
],
}
});
const { queryParams, form, rules } = toRefs(data);
/** 查询设备信息列表 */
const getList = async () => {
loading.value = true;
const res = await listRfidDevice(queryParams.value);
rfidDeviceList.value = res.rows;
total.value = res.total;
loading.value = false;
}
/** 加载位置下拉树(所在位置),使用 getRfidLocationList 获取全量数据 */
const loadLocationOptions = async () => {
const res = await getRfidLocationList();
locationOptions.value = [];
const root: RfidLocationOption = { id: 0, locationAlias: '顶级节点', children: [] };
root.children = proxy?.handleTree<RfidLocationOption>(res.data, 'id', 'parentId') || [];
locationOptions.value.push(root);
}
/** 取消按钮 */
const cancel = () => {
reset();
dialog.visible = false;
}
/** 表单重置 */
const reset = () => {
form.value = {...initFormData};
rfidDeviceFormRef.value?.resetFields();
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
getList();
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
handleQuery();
}
/** 多选框选中数据 */
const handleSelectionChange = (selection: RfidDeviceVO[]) => {
ids.value = selection.map(item => item.id);
single.value = selection.length != 1;
multiple.value = !selection.length;
}
/** 新增按钮操作 */
const handleAdd = () => {
reset();
dialog.visible = true;
dialog.title = "添加设备信息";
}
/** 修改按钮操作 */
const handleUpdate = async (row?: RfidDeviceVO) => {
reset();
const _id = row?.id || ids.value[0]
const res = await getRfidDevice(_id);
Object.assign(form.value, res.data);
dialog.visible = true;
dialog.title = "修改设备信息";
}
/** 提交按钮 */
const submitForm = () => {
rfidDeviceFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
buttonLoading.value = true;
if (form.value.id) {
await updateRfidDevice(form.value).finally(() => buttonLoading.value = false);
} else {
await addRfidDevice(form.value).finally(() => buttonLoading.value = false);
}
proxy?.$modal.msgSuccess("操作成功");
dialog.visible = false;
await getList();
}
});
}
/** 删除按钮操作 */
const handleDelete = async (row?: RfidDeviceVO) => {
const _ids = row?.id || ids.value;
await proxy?.$modal.confirm('是否确认删除设备信息编号为"' + _ids + '"的数据项?').finally(() => loading.value = false);
await delRfidDevice(_ids);
proxy?.$modal.msgSuccess("删除成功");
await getList();
}
/** 导出按钮操作 */
const handleExport = () => {
proxy?.download('rfid/rfidDevice/export', {
...queryParams.value
}, `rfidDevice_${new Date().getTime()}.xlsx`)
}
onMounted(() => {
getList();
loadLocationOptions();
});
</script>

@ -0,0 +1,386 @@
<template>
<div class="p-2">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
<el-form-item label="位置编号" prop="locationCode">
<el-input v-model="queryParams.locationCode" placeholder="请输入位置编号" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="位置别名" prop="locationAlias">
<el-input v-model="queryParams.locationAlias" placeholder="请输入位置别名" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="位置类型" prop="locationType">
<el-select v-model="queryParams.locationType" placeholder="请选择位置类型" clearable>
<el-option v-for="dict in location_type" :key="dict.value" :label="dict.label" :value="dict.value"/>
</el-select>
</el-form-item>
<!-- <el-form-item label="父级编号对应本表id" prop="parentId">
<el-input v-model="queryParams.parentId" placeholder="请输入父级编号对应本表id" clearable @keyup.enter="handleQuery" />
</el-form-item> -->
<el-form-item label="是否标识" prop="isMarked">
<el-select v-model="queryParams.isMarked" placeholder="请选择是否标识" clearable>
<el-option v-for="dict in is_marked" :key="dict.value" :label="dict.label" :value="dict.value"/>
</el-select>
</el-form-item>
<!-- 以下为审计字段搜索条件按规范默认不暴露如需启用请与业务确认后再放开 -->
<!--
<el-form-item label="创建人" prop="createdBy">
<el-input v-model="queryParams.createdBy" placeholder="请输入创建人" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="创建时间" prop="createdAt">
<el-date-picker clearable
v-model="queryParams.createdAt"
type="date"
value-format="YYYY-MM-DD"
placeholder="选择创建时间"
/>
</el-form-item>
<el-form-item label="更新人" prop="updatedBy">
<el-input v-model="queryParams.updatedBy" placeholder="请输入更新人" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="更新时间" prop="updatedAt">
<el-date-picker clearable
v-model="queryParams.updatedAt"
type="date"
value-format="YYYY-MM-DD"
placeholder="选择更新时间"
/>
</el-form-item>
-->
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery"></el-button>
<el-button icon="Refresh" @click="resetQuery"></el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</transition>
<el-card shadow="never">
<template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="Plus" @click="handleAdd()" v-hasPermi="['rfid:rfidLocation:add']"></el-button>
</el-col>
<el-col :span="1.5">
<el-button type="info" plain icon="Sort" @click="handleToggleExpandAll">/</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
</template>
<el-table
ref="rfidLocationTableRef"
v-loading="loading"
:data="rfidLocationList"
row-key="id"
border
:default-expand-all="isExpandAll"
:tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
>
<el-table-column type="index" width="55" align="center" label="序号" />
<el-table-column label="位置编号" prop="locationCode" />
<el-table-column label="位置别名" align="center" prop="locationAlias" />
<el-table-column label="位置类型" align="center" prop="locationType">
<template #default="scope">
<dict-tag :options="location_type" :value="scope.row.locationType"/>
</template>
</el-table-column>
<el-table-column label="是否标识" align="center" prop="isMarked">
<template #default="scope">
<dict-tag :options="is_marked" :value="scope.row.isMarked"/>
</template>
</el-table-column>
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="创建人" align="center" prop="createdBy" />
<el-table-column label="创建时间" align="center" prop="createdAt" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.createdAt, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="更新人" align="center" prop="updatedBy" />
<el-table-column label="更新时间" align="center" prop="updatedAt" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.updatedAt, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
<template #default="scope">
<el-tooltip content="修改" placement="top">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['rfid:rfidLocation:edit']" />
</el-tooltip>
<el-tooltip content="新增" placement="top">
<el-button link type="primary" icon="Plus" @click="handleAdd(scope.row)" v-hasPermi="['rfid:rfidLocation:add']" />
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['rfid:rfidLocation:remove']" />
</el-tooltip>
</template>
</el-table-column>
</el-table>
</el-card>
<!-- 添加或修改位置信息对话框 -->
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
<el-form ref="rfidLocationFormRef" :model="form" :rules="rules" label-width="80px">
<el-form-item label="父级位置" prop="parentId">
<el-tree-select
v-model="form.parentId"
:data="rfidLocationOptions"
:props="{ value: 'id', label: 'locationAlias', children: 'children' }"
value-key="id"
placeholder="请选择父级位置"
check-strictly
/>
</el-form-item>
<el-form-item label="位置编号" prop="locationCode">
<el-input v-model="form.locationCode" placeholder="请输入位置编号" />
</el-form-item>
<el-form-item label="位置别名" prop="locationAlias">
<el-input v-model="form.locationAlias" placeholder="请输入位置别名" />
</el-form-item>
<el-form-item label="位置类型" prop="locationType">
<el-select v-model="form.locationType" placeholder="请选择位置类型">
<el-option
v-for="dict in location_type"
:key="dict.value"
:label="dict.label"
:value="dict.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="是否标识" prop="isMarked">
<el-radio-group v-model="form.isMarked">
<el-radio
v-for="dict in is_marked"
:key="dict.value"
:value="dict.value"
>{{dict.label}}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" placeholder="请输入备注" />
</el-form-item>
<!-- 以下为审计字段输入按规范由后端自动维护前端默认不提供编辑入口如需启用请与业务确认后再放开 -->
<!--
<el-form-item label="创建人" prop="createdBy">
<el-input v-model="form.createdBy" placeholder="请输入创建人" />
</el-form-item>
<el-form-item label="创建时间" prop="createdAt">
<el-date-picker clearable
v-model="form.createdAt"
type="datetime"
value-format="YYYY-MM-DD HH:mm:ss"
placeholder="选择创建时间"
/>
</el-form-item>
<el-form-item label="更新人" prop="updatedBy">
<el-input v-model="form.updatedBy" placeholder="请输入更新人" />
</el-form-item>
<el-form-item label="更新时间" prop="updatedAt"">
<el-date-picker clearable
v-model="form.updatedAt"
type="datetime"
value-format="YYYY-MM-DD HH:mm:ss"
placeholder="选择更新时间"
/>
</el-form-item>
-->
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button :loading="buttonLoading" type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup name="RfidLocation" lang="ts">
import { listRfidLocation, getRfidLocation, delRfidLocation, addRfidLocation, updateRfidLocation, getRfidLocationList } from "@/api/rfid/rfidLocation";
import { RfidLocationVO, RfidLocationQuery, RfidLocationForm } from '@/api/rfid/rfidLocation/types';
type RfidLocationOption = {
id: number;
locationAlias: string;
children?: RfidLocationOption[];
}
const { proxy } = getCurrentInstance() as ComponentInternalInstance;;
const { location_type, is_marked } = toRefs<any>(proxy?.useDict('location_type', 'is_marked'));
const rfidLocationList = ref<RfidLocationVO[]>([]);
const rfidLocationOptions = ref<RfidLocationOption[]>([]);
const buttonLoading = ref(false);
const showSearch = ref(true);
const isExpandAll = ref(true);
const loading = ref(false);
const queryFormRef = ref<ElFormInstance>();
const rfidLocationFormRef = ref<ElFormInstance>();
const rfidLocationTableRef = ref<ElTableInstance>()
const dialog = reactive<DialogOption>({
visible: false,
title: ''
});
const initFormData: RfidLocationForm = {
id: undefined,
locationCode: undefined,
locationAlias: undefined,
locationType: undefined,
parentId: undefined,
isMarked: '1',
remark: undefined,
createdBy: undefined,
createdAt: undefined,
updatedBy: undefined,
updatedAt: undefined
}
const data = reactive<PageData<RfidLocationForm, RfidLocationQuery>>({
form: {...initFormData},
queryParams: {
locationCode: undefined,
locationAlias: undefined,
locationType: undefined,
parentId: undefined,
isMarked: undefined,
createdBy: undefined,
createdAt: undefined,
updatedBy: undefined,
updatedAt: undefined,
params: {
}
},
rules: {
id: [
{ required: true, message: "标识不能为空", trigger: "blur" }
],
locationCode: [
{ required: true, message: "位置编号不能为空", trigger: "blur" }
],
isMarked: [
{ required: true, message: "是否标识不能为空", trigger: "change" }
],
}
});
const { queryParams, form, rules } = toRefs(data);
/** 查询位置信息列表 */
const getList = async () => {
loading.value = true;
const res = await listRfidLocation(queryParams.value);
const data = proxy?.handleTree<RfidLocationVO>(res.data, "id", "parentId");
if (data) {
rfidLocationList.value = data;
loading.value = false;
}
}
/** 查询位置信息下拉树结构,使用 getRfidLocationList 获取全量数据 */
const getTreeselect = async () => {
const res = await getRfidLocationList();
rfidLocationOptions.value = [];
const data: RfidLocationOption = { id: 0, locationAlias: '顶级节点', children: [] };
data.children = proxy?.handleTree<RfidLocationOption>(res.data, "id", "parentId");
rfidLocationOptions.value.push(data);
}
//
const cancel = () => {
reset();
dialog.visible = false;
}
//
const reset = () => {
form.value = {...initFormData}
rfidLocationFormRef.value?.resetFields();
}
/** 搜索按钮操作 */
const handleQuery = () => {
getList();
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
handleQuery();
}
/** 新增按钮操作 */
const handleAdd = (row?: RfidLocationVO) => {
reset();
getTreeselect();
if (row != null && row.id) {
form.value.parentId = row.id;
} else {
form.value.parentId = 0;
}
dialog.visible = true;
dialog.title = "添加位置信息";
}
/** 展开/折叠操作 */
const handleToggleExpandAll = () => {
isExpandAll.value = !isExpandAll.value;
toggleExpandAll(rfidLocationList.value, isExpandAll.value)
}
/** 展开/折叠操作 */
const toggleExpandAll = (data: RfidLocationVO[], status: boolean) => {
data.forEach((item) => {
rfidLocationTableRef.value?.toggleRowExpansion(item, status)
if (item.children && item.children.length > 0) toggleExpandAll(item.children, status)
})
}
/** 修改按钮操作 */
const handleUpdate = async (row: RfidLocationVO) => {
reset();
await getTreeselect();
if (row != null) {
form.value.parentId = row.parentId;
}
const res = await getRfidLocation(row.id);
Object.assign(form.value, res.data);
dialog.visible = true;
dialog.title = "修改位置信息";
}
/** 提交按钮 */
const submitForm = () => {
rfidLocationFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
buttonLoading.value = true;
if (form.value.id) {
await updateRfidLocation(form.value).finally(() => buttonLoading.value = false);
} else {
await addRfidLocation(form.value).finally(() => buttonLoading.value = false);
}
proxy?.$modal.msgSuccess("操作成功");
dialog.visible = false;
getList();
}
});
}
/** 删除按钮操作 */
const handleDelete = async (row: RfidLocationVO) => {
await proxy?.$modal.confirm('是否确认删除位置信息编号为"' + row.id + '"的数据项?');
loading.value = true;
await delRfidLocation(row.id).finally(() => loading.value = false);
await getList();
proxy?.$modal.msgSuccess("删除成功");
}
onMounted(() => {
getList();
});
</script>

@ -0,0 +1,370 @@
<template>
<div class="p-2">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
<el-form-item label="设备名称" prop="deviceId">
<el-select v-model="queryParams.deviceId" placeholder="请选择设备名称" clearable filterable>
<el-option
v-for="item in deviceOptions"
:key="item.id"
:label="item.deviceName"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="读取状态" prop="readStatus">
<el-select v-model="queryParams.readStatus" placeholder="请选择读取状态" clearable >
<el-option v-for="dict in read_status" :key="dict.value" :label="dict.label" :value="dict.value"/>
</el-select>
</el-form-item>
<el-form-item label="条码信息" prop="barcode">
<el-input v-model="queryParams.barcode" placeholder="请输入条码信息" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="记录时间" prop="recordTime">
<el-date-picker clearable
v-model="queryParams.recordTime"
type="date"
value-format="YYYY-MM-DD"
placeholder="请选择记录时间"
/>
</el-form-item>
<el-form-item label="是否告警" prop="alarmFlag">
<el-select v-model="queryParams.alarmFlag" placeholder="请选择是否告警" clearable >
<el-option v-for="dict in alarm_flag" :key="dict.value" :label="dict.label" :value="dict.value"/>
</el-select>
</el-form-item>
<el-form-item label="告警级别" prop="alarmLevel">
<el-select v-model="queryParams.alarmLevel" placeholder="请选择告警级别" clearable >
<el-option v-for="dict in alarm_level" :key="dict.value" :label="dict.label" :value="dict.value"/>
</el-select>
</el-form-item>
<!-- 以下为不常用搜索条件按需开放 -->
<!--
<el-form-item label="告警类型" prop="alarmType">
<el-input v-model="queryParams.alarmType" placeholder="请输入告警类型" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="告警行为" prop="alarmAction">
<el-input v-model="queryParams.alarmAction" placeholder="请输入告警行为" clearable @keyup.enter="handleQuery" />
</el-form-item>
-->
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery"></el-button>
<el-button icon="Refresh" @click="resetQuery"></el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</transition>
<el-card shadow="never">
<template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['rfid:rfidReadRecord:add']"></el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['rfid:rfidReadRecord:edit']"></el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['rfid:rfidReadRecord:remove']"></el-button>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['rfid:rfidReadRecord:export']"></el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
</template>
<el-table v-loading="loading" border :data="rfidReadRecordList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column type="index" width="55" align="center" label="序号" />
<el-table-column label="设备编号" align="center" prop="deviceCode" />
<el-table-column label="设备名称" align="center" prop="deviceName" />
<el-table-column label="读取状态" align="center" prop="readStatus">
<template #default="scope">
<dict-tag :options="read_status" :value="scope.row.readStatus"/>
</template>
</el-table-column>
<el-table-column label="条码信息" align="center" prop="barcode" />
<el-table-column label="记录时间" align="center" prop="recordTime" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.recordTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="是否告警" align="center" prop="alarmFlag">
<template #default="scope">
<dict-tag :options="alarm_flag" :value="scope.row.alarmFlag"/>
</template>
</el-table-column>
<el-table-column label="告警级别" align="center" prop="alarmLevel">
<template #default="scope">
<dict-tag :options="alarm_level" :value="scope.row.alarmLevel"/>
</template>
</el-table-column>
<el-table-column label="告警类型" align="center" prop="alarmType" />
<el-table-column label="告警行为" align="center" prop="alarmAction" />
<el-table-column label="操作" align="center" fixed="right" class-name="small-padding fixed-width">
<template #default="scope">
<el-tooltip content="修改" placement="top">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['rfid:rfidReadRecord:edit']"></el-button>
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['rfid:rfidReadRecord:remove']"></el-button>
</el-tooltip>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
</el-card>
<!-- 添加或修改读取记录对话框 -->
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
<el-form ref="rfidReadRecordFormRef" :model="form" :rules="rules" label-width="80px">
<el-form-item label="设备名称" prop="deviceId">
<el-select v-model="form.deviceId" placeholder="请选择设备名称" filterable>
<el-option
v-for="item in deviceOptions"
:key="item.id"
:label="item.deviceName"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="读取状态" prop="readStatus">
<el-radio-group v-model="form.readStatus">
<el-radio
v-for="dict in read_status"
:key="dict.value"
:value="dict.value"
>{{dict.label}}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="条码信息" prop="barcode">
<el-input v-model="form.barcode" placeholder="请输入条码信息" />
</el-form-item>
<el-form-item label="记录时间" prop="recordTime">
<el-date-picker clearable
v-model="form.recordTime"
type="datetime"
value-format="YYYY-MM-DD HH:mm:ss"
placeholder="请选择记录时间">
</el-date-picker>
</el-form-item>
<el-form-item label="是否告警" prop="alarmFlag">
<el-radio-group v-model="form.alarmFlag">
<el-radio
v-for="dict in alarm_flag"
:key="dict.value"
:value="dict.value"
>{{dict.label}}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="告警级别" prop="alarmLevel">
<el-select v-model="form.alarmLevel" placeholder="请选择告警级别">
<el-option
v-for="dict in alarm_level"
:key="dict.value"
:label="dict.label"
:value="dict.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="告警类型" prop="alarmType">
<el-input v-model="form.alarmType" placeholder="请输入告警类型" />
</el-form-item>
<el-form-item label="告警行为" prop="alarmAction">
<el-input v-model="form.alarmAction" placeholder="请输入告警行为" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button :loading="buttonLoading" type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup name="RfidReadRecord" lang="ts">
import { listRfidReadRecord, getRfidReadRecord, delRfidReadRecord, addRfidReadRecord, updateRfidReadRecord } from "@/api/rfid/rfidReadRecord";
import { RfidReadRecordVO, RfidReadRecordQuery, RfidReadRecordForm } from '@/api/rfid/rfidReadRecord/types';
import { getRfidDeviceList } from "@/api/rfid/rfidDevice";
import type { RfidDeviceVO } from '@/api/rfid/rfidDevice/types';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { read_status, alarm_level, alarm_flag } = toRefs<any>(proxy?.useDict('read_status', 'alarm_level', 'alarm_flag'));
const rfidReadRecordList = ref<RfidReadRecordVO[]>([]);
const buttonLoading = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const queryFormRef = ref<ElFormInstance>();
const rfidReadRecordFormRef = ref<ElFormInstance>();
const dialog = reactive<DialogOption>({
visible: false,
title: ''
});
const deviceOptions = ref<RfidDeviceVO[]>([]);
const initFormData: RfidReadRecordForm = {
id: undefined,
deviceId: undefined,
readStatus: undefined,
barcode: undefined,
recordTime: undefined,
alarmFlag: undefined,
alarmLevel: undefined,
alarmType: undefined,
alarmAction: undefined
}
const data = reactive<PageData<RfidReadRecordForm, RfidReadRecordQuery>>({
form: {...initFormData},
queryParams: {
pageNum: 1,
pageSize: 10,
deviceId: undefined,
readStatus: undefined,
barcode: undefined,
recordTime: undefined,
alarmFlag: undefined,
alarmLevel: undefined,
alarmType: undefined,
alarmAction: undefined,
params: {
}
},
rules: {
id: [
{ required: true, message: "标识不能为空", trigger: "blur" }
],
deviceId: [
{ required: true, message: "设备名称不能为空", trigger: "change" }
],
readStatus: [
{ required: true, message: "读取状态不能为空", trigger: "change" }
],
barcode: [
{ required: true, message: "条码信息不能为空", trigger: "blur" }
],
recordTime: [
{ required: true, message: "记录时间不能为空", trigger: "blur" }
],
alarmFlag: [
{ required: true, message: "是否告警不能为空", trigger: "change" }
],
}
});
const { queryParams, form, rules } = toRefs(data);
/** 查询读取记录列表 */
const getList = async () => {
loading.value = true;
const res = await listRfidReadRecord(queryParams.value);
rfidReadRecordList.value = res.rows;
total.value = res.total;
loading.value = false;
}
/** 加载设备下拉(设备名称),使用 getRfidDeviceList 获取全量数据 */
const loadDeviceOptions = async () => {
const res: any = await getRfidDeviceList({ isMarked: "1" } as any);
deviceOptions.value = res.data || [];
}
/** 取消按钮 */
const cancel = () => {
reset();
dialog.visible = false;
}
/** 表单重置 */
const reset = () => {
form.value = {...initFormData};
rfidReadRecordFormRef.value?.resetFields();
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
getList();
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
handleQuery();
}
/** 多选框选中数据 */
const handleSelectionChange = (selection: RfidReadRecordVO[]) => {
ids.value = selection.map(item => item.id);
single.value = selection.length != 1;
multiple.value = !selection.length;
}
/** 新增按钮操作 */
const handleAdd = () => {
reset();
dialog.visible = true;
dialog.title = "添加读取记录";
}
/** 修改按钮操作 */
const handleUpdate = async (row?: RfidReadRecordVO) => {
reset();
const _id = row?.id || ids.value[0]
const res = await getRfidReadRecord(_id);
Object.assign(form.value, res.data);
dialog.visible = true;
dialog.title = "修改读取记录";
}
/** 提交按钮 */
const submitForm = () => {
rfidReadRecordFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
buttonLoading.value = true;
if (form.value.id) {
await updateRfidReadRecord(form.value).finally(() => buttonLoading.value = false);
} else {
await addRfidReadRecord(form.value).finally(() => buttonLoading.value = false);
}
proxy?.$modal.msgSuccess("操作成功");
dialog.visible = false;
await getList();
}
});
}
/** 删除按钮操作 */
const handleDelete = async (row?: RfidReadRecordVO) => {
const _ids = row?.id || ids.value;
await proxy?.$modal.confirm('是否确认删除读取记录编号为"' + _ids + '"的数据项?').finally(() => loading.value = false);
await delRfidReadRecord(_ids);
proxy?.$modal.msgSuccess("删除成功");
await getList();
}
/** 导出按钮操作 */
const handleExport = () => {
proxy?.download('rfid/rfidReadRecord/export', {
...queryParams.value
}, `rfidReadRecord_${new Date().getTime()}.xlsx`)
}
onMounted(() => {
getList();
loadDeviceOptions();
});
</script>
Loading…
Cancel
Save