|
|
@@ -0,0 +1,526 @@
|
|
|
+<script setup>
|
|
|
+import request from "@/utils/request.js";
|
|
|
+import {onMounted, reactive, ref} from "vue";
|
|
|
+import {
|
|
|
+ ElButton,
|
|
|
+ ElDialog,
|
|
|
+ ElForm,
|
|
|
+ ElFormItem,
|
|
|
+ ElInput,
|
|
|
+ ElMessage,
|
|
|
+ ElMessageBox,
|
|
|
+ ElPagination,
|
|
|
+ ElTable,
|
|
|
+ ElTableColumn
|
|
|
+} from "element-plus";
|
|
|
+import PoleDetail from "@/views/device/pole/pole-detail.vue";
|
|
|
+
|
|
|
+const poleList = ref([]);
|
|
|
+const loading = ref(false);
|
|
|
+const total = ref(0);
|
|
|
+const currentPage = ref(1);
|
|
|
+const pageSize = ref(10);
|
|
|
+const search = ref({
|
|
|
+ deviceName: "",
|
|
|
+});
|
|
|
+
|
|
|
+// 表格多选
|
|
|
+const multipleSelection = ref([]);
|
|
|
+const handleSelectionChange = (val) => {
|
|
|
+ multipleSelection.value = val;
|
|
|
+};
|
|
|
+
|
|
|
+// 对话框控制
|
|
|
+const dialogVisible = ref(false);
|
|
|
+const dialogTitle = ref('');
|
|
|
+const formMode = ref('add'); // 'add' or 'edit'
|
|
|
+
|
|
|
+// 详情对话框控制
|
|
|
+const detailDialogVisible = ref(false);
|
|
|
+const currentCheckDevice = ref('');
|
|
|
+const currentDeviceName = ref('');
|
|
|
+
|
|
|
+// 表单数据
|
|
|
+const formData = reactive({
|
|
|
+ id: '',
|
|
|
+ deviceName: '',
|
|
|
+ deviceNumber: '',
|
|
|
+ model: '',
|
|
|
+ location: '',
|
|
|
+ alarmStatus: '1', // 保留在数据中,但不在表单中显示
|
|
|
+ remarks: '',
|
|
|
+ type: '3' // 固定值
|
|
|
+});
|
|
|
+
|
|
|
+// 表单规则
|
|
|
+const rules = {
|
|
|
+ deviceName: [{ required: true, message: '请输入灯杆名称', trigger: 'blur' }],
|
|
|
+ deviceNumber: [{ required: true, message: '请输入灯杆编号', trigger: 'blur' }]
|
|
|
+};
|
|
|
+
|
|
|
+const formRef = ref(null);
|
|
|
+
|
|
|
+const getList = async () => {
|
|
|
+ loading.value = true;
|
|
|
+ try {
|
|
|
+ const arr = [];
|
|
|
+ arr.push({
|
|
|
+ column: "type",
|
|
|
+ type: "eq",
|
|
|
+ value: "3",
|
|
|
+ });
|
|
|
+ arr.push({
|
|
|
+ column: "create_time",
|
|
|
+ type: "orderByDesc",
|
|
|
+ });
|
|
|
+
|
|
|
+ if(search.value.deviceName){
|
|
|
+ arr.push({
|
|
|
+ column: "device_name",
|
|
|
+ type: "like",
|
|
|
+ value: search.value.deviceName,
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ const res = await request.get("/base/devices/findByPage", {
|
|
|
+ params: {
|
|
|
+ pageNum: currentPage.value,
|
|
|
+ pageSize: pageSize.value,
|
|
|
+ conditionJson: encodeURIComponent(JSON.stringify(arr))
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ if (res.code !== 200) {
|
|
|
+ ElMessage.error(res.msg);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ poleList.value = res.data.records;
|
|
|
+ total.value = res.data.total;
|
|
|
+ } catch (error) {
|
|
|
+ ElMessage.error("获取数据失败");
|
|
|
+ } finally {
|
|
|
+ loading.value = false;
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 搜索
|
|
|
+const handleSearch = () => {
|
|
|
+ currentPage.value = 1;
|
|
|
+ getList();
|
|
|
+};
|
|
|
+
|
|
|
+// 重置搜索
|
|
|
+const resetSearch = () => {
|
|
|
+ search.value.deviceName = '';
|
|
|
+ currentPage.value = 1;
|
|
|
+ getList();
|
|
|
+};
|
|
|
+
|
|
|
+// 打开新增对话框
|
|
|
+const openAddDialog = () => {
|
|
|
+ formMode.value = 'add';
|
|
|
+ dialogTitle.value = '新增灯杆设备';
|
|
|
+ // 重置表单
|
|
|
+ Object.assign(formData, {
|
|
|
+ id: '',
|
|
|
+ deviceName: '',
|
|
|
+ deviceNumber: '',
|
|
|
+ model: '',
|
|
|
+ location: '',
|
|
|
+ alarmStatus: '1', // 默认值,但不在表单中显示
|
|
|
+ remarks: '',
|
|
|
+ type: '3'
|
|
|
+ });
|
|
|
+ dialogVisible.value = true;
|
|
|
+};
|
|
|
+
|
|
|
+// 打开编辑对话框
|
|
|
+const openEditDialog = async (row) => {
|
|
|
+ formMode.value = 'edit';
|
|
|
+ dialogTitle.value = '编辑灯杆设备';
|
|
|
+
|
|
|
+ try {
|
|
|
+ // 获取最新的设备信息
|
|
|
+ const deviceInfo = await getDeviceInfo(row.id);
|
|
|
+ if (deviceInfo) {
|
|
|
+ Object.assign(formData, {
|
|
|
+ id: deviceInfo.id,
|
|
|
+ deviceName: deviceInfo.deviceName,
|
|
|
+ deviceNumber: deviceInfo.deviceNumber,
|
|
|
+ model: deviceInfo.model || '',
|
|
|
+ location: deviceInfo.location || '',
|
|
|
+ alarmStatus: deviceInfo.alarmStatus, // 保留原值,但不在表单中显示
|
|
|
+ remarks: deviceInfo.remarks || '',
|
|
|
+ type: '3'
|
|
|
+ });
|
|
|
+ dialogVisible.value = true;
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ ElMessage.error("获取设备信息失败");
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 提交表单
|
|
|
+const submitForm = async () => {
|
|
|
+ if (!formRef.value) return;
|
|
|
+
|
|
|
+ await formRef.value.validate(async (valid) => {
|
|
|
+ if (valid) {
|
|
|
+ if (formMode.value === 'add') {
|
|
|
+ await addDevice();
|
|
|
+ } else {
|
|
|
+ await updateDevice(formData);
|
|
|
+ }
|
|
|
+ dialogVisible.value = false;
|
|
|
+ }
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+// 更新设备信息的方法
|
|
|
+const updateDevice = async (data) => {
|
|
|
+ try {
|
|
|
+ const res = await request.post("/base/devices/update", {
|
|
|
+ id: data.id,
|
|
|
+ deviceName: data.deviceName,
|
|
|
+ deviceNumber: data.deviceNumber,
|
|
|
+ model: data.model,
|
|
|
+ location: data.location,
|
|
|
+ remarks: data.remarks,
|
|
|
+ type: '3',
|
|
|
+ alarmStatus: data.alarmStatus // 保留原值传递给API
|
|
|
+ });
|
|
|
+
|
|
|
+ if (res.code !== 200) {
|
|
|
+ ElMessage.error(res.msg);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ ElMessage.success("更新成功");
|
|
|
+ getList();
|
|
|
+ } catch (error) {
|
|
|
+ ElMessage.error("更新失败");
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 根据id查询设备信息
|
|
|
+const getDeviceInfo = async (deviceId) => {
|
|
|
+ try {
|
|
|
+ const res = await request.get("/base/devices/getById/" + deviceId);
|
|
|
+
|
|
|
+ if (res.code !== 200) {
|
|
|
+ ElMessage.error(res.msg);
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ return res.data;
|
|
|
+ } catch (error) {
|
|
|
+ ElMessage.error("获取设备信息失败");
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 删除单个设备
|
|
|
+const handleDelete = (row) => {
|
|
|
+ ElMessageBox.confirm('确认删除该设备?', '提示', {
|
|
|
+ confirmButtonText: '确定',
|
|
|
+ cancelButtonText: '取消',
|
|
|
+ type: 'warning'
|
|
|
+ }).then(() => {
|
|
|
+ deleteDevice([row.id]);
|
|
|
+ }).catch(() => {});
|
|
|
+};
|
|
|
+
|
|
|
+// 批量删除设备
|
|
|
+const handleBatchDelete = () => {
|
|
|
+ if (multipleSelection.value.length === 0) {
|
|
|
+ ElMessage.warning('请至少选择一条记录');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ ElMessageBox.confirm(`确认删除选中的 ${multipleSelection.value.length} 条记录?`, '提示', {
|
|
|
+ confirmButtonText: '确定',
|
|
|
+ cancelButtonText: '取消',
|
|
|
+ type: 'warning'
|
|
|
+ }).then(() => {
|
|
|
+ const ids = multipleSelection.value.map(item => item.id);
|
|
|
+ deleteDevice(ids);
|
|
|
+ }).catch(() => {});
|
|
|
+};
|
|
|
+
|
|
|
+// 删除设备信息
|
|
|
+const deleteDevice = async (ids) => {
|
|
|
+ try {
|
|
|
+ const res = await request.delete("/base/devices/delete", {
|
|
|
+ data: ids,
|
|
|
+ });
|
|
|
+
|
|
|
+ if (res.code !== 200) {
|
|
|
+ ElMessage.error(res.msg);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ ElMessage.success("删除成功");
|
|
|
+ getList();
|
|
|
+ } catch (error) {
|
|
|
+ ElMessage.error("删除失败");
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+// 新增设备信息
|
|
|
+const addDevice = async () => {
|
|
|
+ try {
|
|
|
+ const res = await request.post("/base/devices/save", {
|
|
|
+ deviceName: formData.deviceName,
|
|
|
+ deviceNumber: formData.deviceNumber,
|
|
|
+ location: formData.location,
|
|
|
+ model: formData.model,
|
|
|
+ remarks: formData.remarks,
|
|
|
+ alarmStatus: formData.alarmStatus, // 使用默认值
|
|
|
+ type: "3", // 写死的不能让修改
|
|
|
+ });
|
|
|
+
|
|
|
+ if (res.code !== 200) {
|
|
|
+ ElMessage.error(res.msg);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ ElMessage.success("新增成功");
|
|
|
+ getList();
|
|
|
+ } catch (error) {
|
|
|
+ ElMessage.error("新增失败");
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+const handlePageChange = (page) => {
|
|
|
+ currentPage.value = page;
|
|
|
+ getList();
|
|
|
+};
|
|
|
+
|
|
|
+const handleSizeChange = (size) => {
|
|
|
+ pageSize.value = size;
|
|
|
+ currentPage.value = 1;
|
|
|
+ getList();
|
|
|
+};
|
|
|
+
|
|
|
+const formatDate = (dateString) => {
|
|
|
+ if (!dateString) return '-';
|
|
|
+ const date = new Date(dateString);
|
|
|
+ return date.toLocaleString('zh-CN', {
|
|
|
+ year: 'numeric',
|
|
|
+ month: '2-digit',
|
|
|
+ day: '2-digit',
|
|
|
+ hour: '2-digit',
|
|
|
+ minute: '2-digit'
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+// 查看详情
|
|
|
+const checkDetail = (row) => {
|
|
|
+ currentCheckDevice.value = row.deviceNumber;
|
|
|
+ currentDeviceName.value = row.deviceName;
|
|
|
+ detailDialogVisible.value = true;
|
|
|
+};
|
|
|
+
|
|
|
+// 关闭详情对话框
|
|
|
+const closeDetailDialog = () => {
|
|
|
+ detailDialogVisible.value = false;
|
|
|
+};
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ getList();
|
|
|
+});
|
|
|
+</script>
|
|
|
+
|
|
|
+<template>
|
|
|
+ <div class="w-full p-4">
|
|
|
+ <!-- 搜索区域 -->
|
|
|
+ <div class="bg-gray-50 p-4 mb-4 rounded-md">
|
|
|
+ <el-form :inline="true" class="flex flex-wrap items-end">
|
|
|
+ <el-form-item label="灯杆名称">
|
|
|
+ <el-input v-model="search.deviceName" placeholder="请输入灯杆名称" clearable/>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item>
|
|
|
+ <el-button type="primary" @click="handleSearch">搜索</el-button>
|
|
|
+ <el-button @click="resetSearch">重置</el-button>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 操作按钮区域 -->
|
|
|
+ <div class="mb-4 flex justify-between">
|
|
|
+ <div>
|
|
|
+ <el-button type="primary" @click="openAddDialog">新增灯杆</el-button>
|
|
|
+ <el-button type="danger" @click="handleBatchDelete" :disabled="multipleSelection.length === 0">批量删除
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 表格区域 -->
|
|
|
+ <el-table
|
|
|
+ :data="poleList"
|
|
|
+ border
|
|
|
+ stripe
|
|
|
+ v-loading="loading"
|
|
|
+ class="w-full"
|
|
|
+ row-key="id"
|
|
|
+ header-row-class-name="bg-gray-100"
|
|
|
+ @selection-change="handleSelectionChange"
|
|
|
+ >
|
|
|
+ <el-table-column type="selection" width="55"/>
|
|
|
+ <el-table-column prop="deviceName" label="灯杆名称" />
|
|
|
+ <el-table-column prop="deviceNumber" label="灯杆编号" />
|
|
|
+ <el-table-column prop="model" label="设备型号" >
|
|
|
+ <template #default="{ row }">
|
|
|
+ {{ row.model || '-' }}
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="location" label="位置">
|
|
|
+ <template #default="{ row }">
|
|
|
+ {{ row.location || '-' }}
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="remarks" label="备注">
|
|
|
+ <template #default="{ row }">
|
|
|
+ {{ row.remarks || '-' }}
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="创建时间">
|
|
|
+ <template #default="{ row }">
|
|
|
+ {{ formatDate(row.createTime) }}
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="更新时间">
|
|
|
+ <template #default="{ row }">
|
|
|
+ {{ formatDate(row.updateTime) }}
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="操作" fixed="right">
|
|
|
+ <template #default="{ row }">
|
|
|
+ <el-button type="primary" link @click="openEditDialog(row)">编辑</el-button>
|
|
|
+ <el-button type="danger" link @click="handleDelete(row)">删除</el-button>
|
|
|
+ <el-button type="info" link @click="checkDetail(row)">查看详情</el-button>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+
|
|
|
+ <!-- 分页区域 -->
|
|
|
+ <div class="flex justify-end mt-4">
|
|
|
+ <el-pagination
|
|
|
+ v-model:current-page="currentPage"
|
|
|
+ v-model:page-size="pageSize"
|
|
|
+ :page-sizes="[10, 20, 50, 100]"
|
|
|
+ layout="total, sizes, prev, pager, next, jumper"
|
|
|
+ :total="total"
|
|
|
+ @size-change="handleSizeChange"
|
|
|
+ @current-change="handlePageChange"
|
|
|
+ background
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 新增/编辑对话框 -->
|
|
|
+ <el-dialog
|
|
|
+ v-model="dialogVisible"
|
|
|
+ :title="dialogTitle"
|
|
|
+ width="500px"
|
|
|
+ append-to-body
|
|
|
+ destroy-on-close
|
|
|
+ >
|
|
|
+ <el-form
|
|
|
+ ref="formRef"
|
|
|
+ :model="formData"
|
|
|
+ :rules="rules"
|
|
|
+ label-width="100px"
|
|
|
+ label-position="right"
|
|
|
+ >
|
|
|
+ <el-form-item label="灯杆名称" prop="deviceName">
|
|
|
+ <el-input v-model="formData.deviceName" placeholder="请输入灯杆名称"/>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="灯杆编号" prop="deviceNumber">
|
|
|
+ <el-input v-model="formData.deviceNumber" placeholder="请输入灯杆编号" :disabled="formMode === 'edit'"/>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="设备型号">
|
|
|
+ <el-input v-model="formData.model" placeholder="请输入设备型号"/>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="位置">
|
|
|
+ <el-input v-model="formData.location" placeholder="请输入位置"/>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="备注">
|
|
|
+ <el-input v-model="formData.remarks" type="textarea" placeholder="请输入备注"/>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ <template #footer>
|
|
|
+ <div class="dialog-footer">
|
|
|
+ <el-button @click="dialogVisible = false">取消</el-button>
|
|
|
+ <el-button type="primary" @click="submitForm">确定</el-button>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
+ <!-- 详情全屏对话框 -->
|
|
|
+ <el-dialog
|
|
|
+ v-model="detailDialogVisible"
|
|
|
+ :title="`灯杆详情 - ${currentDeviceName}`"
|
|
|
+ fullscreen
|
|
|
+ destroy-on-close
|
|
|
+ :show-close="true"
|
|
|
+ :close-on-click-modal="false"
|
|
|
+ :close-on-press-escape="true"
|
|
|
+ >
|
|
|
+ <div class="detail-dialog-content">
|
|
|
+ <PoleDetail :device-number="currentCheckDevice" />
|
|
|
+ </div>
|
|
|
+ <template #footer>
|
|
|
+ <div class="dialog-footer">
|
|
|
+ <el-button type="primary" @click="closeDetailDialog">关闭</el-button>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </el-dialog>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<style>
|
|
|
+.el-table .warning-row {
|
|
|
+ --el-table-tr-bg-color: var(--el-color-warning-light-9);
|
|
|
+}
|
|
|
+
|
|
|
+/* 响应式调整 */
|
|
|
+@media (max-width: 768px) {
|
|
|
+ .el-form-item {
|
|
|
+ margin-bottom: 12px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .el-form--inline .el-form-item {
|
|
|
+ margin-right: 0;
|
|
|
+ width: 100%;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/* 详情对话框样式 */
|
|
|
+.detail-dialog-content {
|
|
|
+ padding: 20px;
|
|
|
+ height: calc(100vh - 120px);
|
|
|
+ overflow-y: auto;
|
|
|
+}
|
|
|
+
|
|
|
+.el-dialog__body {
|
|
|
+ padding: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.el-dialog.is-fullscreen {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+}
|
|
|
+
|
|
|
+.el-dialog.is-fullscreen .el-dialog__header {
|
|
|
+ padding: 16px 20px;
|
|
|
+ margin-right: 0;
|
|
|
+ border-bottom: 1px solid #e4e7ed;
|
|
|
+}
|
|
|
+
|
|
|
+.el-dialog.is-fullscreen .el-dialog__footer {
|
|
|
+ padding: 10px 20px;
|
|
|
+ border-top: 1px solid #e4e7ed;
|
|
|
+ margin-top: auto;
|
|
|
+}
|
|
|
+</style>
|