|
|
|
|
@ -1,303 +1,315 @@
|
|
|
|
|
<script setup lang="ts">
|
|
|
|
|
import type { VbenFormProps } from '@vben/common-ui';
|
|
|
|
|
import type { DeviceQuery, DeviceVO } from '#/api/hazard/device/model';
|
|
|
|
|
|
|
|
|
|
import type { VxeGridProps } from '#/adapter/vxe-table';
|
|
|
|
|
import type { DeviceForm } from '#/api/hazard/device/model';
|
|
|
|
|
import { onMounted, ref } from 'vue';
|
|
|
|
|
|
|
|
|
|
import { h, onMounted, ref } from 'vue';
|
|
|
|
|
import { useRouter } from 'vue-router';
|
|
|
|
|
import { useVbenModal } from '@vben/common-ui';
|
|
|
|
|
|
|
|
|
|
import {
|
|
|
|
|
DeleteOutlined,
|
|
|
|
|
EditOutlined,
|
|
|
|
|
EyeOutlined,
|
|
|
|
|
} from '@ant-design/icons-vue';
|
|
|
|
|
import {
|
|
|
|
|
Button,
|
|
|
|
|
Card,
|
|
|
|
|
Form,
|
|
|
|
|
Input,
|
|
|
|
|
Layout,
|
|
|
|
|
List,
|
|
|
|
|
Pagination,
|
|
|
|
|
Popconfirm,
|
|
|
|
|
RadioButton,
|
|
|
|
|
RadioGroup,
|
|
|
|
|
Tag,
|
|
|
|
|
} from 'ant-design-vue';
|
|
|
|
|
|
|
|
|
|
import { Page, useVbenModal } from '@vben/common-ui';
|
|
|
|
|
import { getVxePopupContainer } from '@vben/utils';
|
|
|
|
|
import {deviceExport, deviceList, deviceRemove} from '#/api/hazard/device';
|
|
|
|
|
import deviceModal from '#/views/hazard/device/device-modal.vue';
|
|
|
|
|
import {useRouter} from "vue-router";
|
|
|
|
|
import {commonDownloadExcel} from "#/utils/file/download";
|
|
|
|
|
// 搜索表单数据
|
|
|
|
|
const searchForm = ref<DeviceQuery>({ name: null, status: null });
|
|
|
|
|
const router = useRouter();
|
|
|
|
|
// 分页相关
|
|
|
|
|
const current = ref<number>(1);
|
|
|
|
|
const currentSize = ref<number>(10);
|
|
|
|
|
const total = ref<number>(1);
|
|
|
|
|
const pageSizeOptions = ['5', '10', '20', '30', '40', '50'];
|
|
|
|
|
// 列表数据模拟
|
|
|
|
|
const listData = ref<DeviceVO[]>([]);
|
|
|
|
|
const [DeviceModal, modalApi] = useVbenModal({
|
|
|
|
|
connectedComponent: deviceModal,
|
|
|
|
|
});
|
|
|
|
|
// 处理搜索事件
|
|
|
|
|
const handleSearch = async () => {
|
|
|
|
|
// console.log('执行搜索:', searchForm.keyword);
|
|
|
|
|
// 实际应用中这里会调用API获取搜索结果
|
|
|
|
|
const params = searchForm.value;
|
|
|
|
|
const response = await deviceList(params);
|
|
|
|
|
listData.value = response.rows;
|
|
|
|
|
console.log('handleSearch', listData.value);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
import { Modal, Popconfirm, Space } from 'ant-design-vue';
|
|
|
|
|
// 处理重置事件
|
|
|
|
|
const handleReset = async () => {
|
|
|
|
|
// searchForm.keyword = '';
|
|
|
|
|
console.log('重置搜索条件');
|
|
|
|
|
searchForm.value = {};
|
|
|
|
|
const response = await deviceList();
|
|
|
|
|
listData.value = response.rows;
|
|
|
|
|
console.log('handleSearch', listData.value);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
import { useVbenVxeGrid, vxeCheckboxChecked } from '#/adapter/vxe-table';
|
|
|
|
|
import { deviceExport, deviceList, deviceRemove } from '#/api/hazard/device';
|
|
|
|
|
import { sensorQuery } from '#/api/hazard/sensor';
|
|
|
|
|
import { commonDownloadExcel } from '#/utils/file/download';
|
|
|
|
|
// 处理分页变化
|
|
|
|
|
const handlePageChange = async (page: number) => {
|
|
|
|
|
console.log('当前页码:', page);
|
|
|
|
|
current.value = page;
|
|
|
|
|
const params = {
|
|
|
|
|
...searchForm.value,
|
|
|
|
|
pageNum: page,
|
|
|
|
|
pageSize: currentSize.value,
|
|
|
|
|
};
|
|
|
|
|
const response = await deviceList(params);
|
|
|
|
|
listData.value = response.rows;
|
|
|
|
|
total.value = response.total;
|
|
|
|
|
// 实际应用中这里会重新加载对应页的数据
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
import { columns, querySchema } from './data';
|
|
|
|
|
import deviceModal from './device-modal.vue';
|
|
|
|
|
// 创建响应式变量存储传感器数据
|
|
|
|
|
let sensors = ref<[]>([]);
|
|
|
|
|
const router = useRouter();
|
|
|
|
|
const exTarColumns: VxeGridProps['columns'] = [
|
|
|
|
|
{
|
|
|
|
|
title: '',
|
|
|
|
|
fixed: 'left',
|
|
|
|
|
width: 60,
|
|
|
|
|
slots: {
|
|
|
|
|
header: ({ _row }) => {
|
|
|
|
|
const selectArr = tableApi.grid.getCheckboxRecords();
|
|
|
|
|
const { visibleData } = tableApi.grid.getTableData();
|
|
|
|
|
return [
|
|
|
|
|
h('input', {
|
|
|
|
|
type: 'checkbox',
|
|
|
|
|
checked: selectArr.length === visibleData.length,
|
|
|
|
|
onChange: () => {
|
|
|
|
|
// 如果全部选择的有的话,就清空
|
|
|
|
|
if (selectArr.length === visibleData.length) {
|
|
|
|
|
tableApi.grid.clearCheckboxRow();
|
|
|
|
|
} else {
|
|
|
|
|
tableApi.grid.toggleAllCheckboxRow();
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
style: {
|
|
|
|
|
height: '18px',
|
|
|
|
|
width: '18px',
|
|
|
|
|
cursor: 'pointer',
|
|
|
|
|
margin: 'auto',
|
|
|
|
|
display: 'block',
|
|
|
|
|
},
|
|
|
|
|
}),
|
|
|
|
|
];
|
|
|
|
|
},
|
|
|
|
|
default: ({ row, rowIndex }) => {
|
|
|
|
|
const isChecked = tableApi.grid.getCheckboxRecords().includes(row); // 用于控制复选框的选中状态
|
|
|
|
|
const { pager } = tableApi.grid.getProxyInfo();
|
|
|
|
|
const pageSize = pager.pageSize;
|
|
|
|
|
const pageIndex = pager.currentPage;
|
|
|
|
|
return [
|
|
|
|
|
// 当复选框显示时,序号消失
|
|
|
|
|
row.isHovered || isChecked
|
|
|
|
|
? h('input', {
|
|
|
|
|
type: 'checkbox',
|
|
|
|
|
checked: tableApi.grid.getCheckboxRecords().includes(row), // 使用表格的多选记录
|
|
|
|
|
onChange: () => {
|
|
|
|
|
tableApi.grid.toggleCheckboxRow(row); // 调用表格的多选方法
|
|
|
|
|
},
|
|
|
|
|
style: {
|
|
|
|
|
height: '18px',
|
|
|
|
|
width: '18px',
|
|
|
|
|
cursor: 'pointer',
|
|
|
|
|
margin: 'auto',
|
|
|
|
|
display: 'block',
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
: h('span', (pageIndex - 1) * pageSize + rowIndex + 1), // 显示序号
|
|
|
|
|
];
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
];
|
|
|
|
|
// 处理每页条数变化
|
|
|
|
|
const handlePageSizeChange = async (page: number, size: number) => {
|
|
|
|
|
console.log(`每页条数变为: ${size}`);
|
|
|
|
|
// 实际应用中这里会按照新的分页大小重新加载数据
|
|
|
|
|
current.value = page;
|
|
|
|
|
currentSize.value = size;
|
|
|
|
|
// 按照新的分页大小重新加载数据,保留查询条件
|
|
|
|
|
const params = {
|
|
|
|
|
...searchForm.value,
|
|
|
|
|
pageNum: page,
|
|
|
|
|
pageSize: size,
|
|
|
|
|
};
|
|
|
|
|
const response = await deviceList(params);
|
|
|
|
|
listData.value = response.rows;
|
|
|
|
|
total.value = response.total;
|
|
|
|
|
};
|
|
|
|
|
// 处理新增事件
|
|
|
|
|
const handleAdd = () => {
|
|
|
|
|
console.log('新增设备');
|
|
|
|
|
// 实际应用中这里会打开新增对话框或跳转到新增页面
|
|
|
|
|
modalApi.setData({});
|
|
|
|
|
modalApi.open();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handleView = async (item: DeviceVO) => {
|
|
|
|
|
await router.push(`/hazard/devicePreview/${item.id}`);
|
|
|
|
|
};
|
|
|
|
|
const handleEdit = async (item: DeviceVO) => {
|
|
|
|
|
console.log('编辑设备', item);
|
|
|
|
|
modalApi.setData({ id: item.id });
|
|
|
|
|
modalApi.open();
|
|
|
|
|
// 刷新查询
|
|
|
|
|
const response = await deviceList({ pageNum: 1, pageSize: 10 });
|
|
|
|
|
listData.value = response.rows;
|
|
|
|
|
total.value = response.total;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const formOptions: VbenFormProps = {
|
|
|
|
|
commonConfig: {
|
|
|
|
|
labelWidth: 80,
|
|
|
|
|
componentProps: {
|
|
|
|
|
allowClear: true,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
schema: querySchema(),
|
|
|
|
|
wrapperClass: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4',
|
|
|
|
|
// 处理区间选择器RangePicker时间格式 将一个字段映射为两个字段 搜索/导出会用到
|
|
|
|
|
// 不需要直接删除
|
|
|
|
|
// fieldMappingTime: [
|
|
|
|
|
// [
|
|
|
|
|
// 'createTime',
|
|
|
|
|
// ['params[beginTime]', 'params[endTime]'],
|
|
|
|
|
// ['YYYY-MM-DD 00:00:00', 'YYYY-MM-DD 23:59:59'],
|
|
|
|
|
// ],
|
|
|
|
|
// ],
|
|
|
|
|
const confirm = async (item: DeviceVO) => {
|
|
|
|
|
await handleDelete(item);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const gridOptions: VxeGridProps = {
|
|
|
|
|
checkboxConfig: {
|
|
|
|
|
// 高亮
|
|
|
|
|
highlight: true,
|
|
|
|
|
// 翻页时保留选中状态
|
|
|
|
|
reserve: true,
|
|
|
|
|
// 点击行选中
|
|
|
|
|
// trigger: 'row',
|
|
|
|
|
trigger: 'cell',
|
|
|
|
|
},
|
|
|
|
|
// 需要使用i18n注意这里要改成getter形式 否则切换语言不会刷新
|
|
|
|
|
// columns: columns(),
|
|
|
|
|
columns: [...exTarColumns, ...columns],
|
|
|
|
|
border: true,
|
|
|
|
|
height: 'auto',
|
|
|
|
|
keepSource: true,
|
|
|
|
|
pagerConfig: {},
|
|
|
|
|
proxyConfig: {
|
|
|
|
|
ajax: {
|
|
|
|
|
query: async ({ page }, formValues = {}) => {
|
|
|
|
|
return await deviceList({
|
|
|
|
|
pageNum: page.currentPage,
|
|
|
|
|
pageSize: page.pageSize,
|
|
|
|
|
...formValues,
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
rowConfig: {
|
|
|
|
|
isHover: true,
|
|
|
|
|
keyField: 'id',
|
|
|
|
|
},
|
|
|
|
|
//设置单元格的样式
|
|
|
|
|
// cellConfig: {
|
|
|
|
|
// // 鼠标移入高亮
|
|
|
|
|
// height: 200,
|
|
|
|
|
// },
|
|
|
|
|
// 表格全局唯一表示 保存列配置需要用到
|
|
|
|
|
id: 'hazard-device-index',
|
|
|
|
|
const cancel = () => {
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
// 处理删除事件
|
|
|
|
|
const handleDelete = async (item: DeviceVO) => {
|
|
|
|
|
await deviceRemove(item.id);
|
|
|
|
|
const params = {
|
|
|
|
|
...searchForm.value,
|
|
|
|
|
pageNum: current.value,
|
|
|
|
|
pageSize: currentSize.value,
|
|
|
|
|
};
|
|
|
|
|
const response = await deviceList(params);
|
|
|
|
|
listData.value = response.rows;
|
|
|
|
|
total.value = response.total;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const checked = ref(false);
|
|
|
|
|
const [BasicTable, tableApi] = useVbenVxeGrid({
|
|
|
|
|
formOptions,
|
|
|
|
|
gridOptions,
|
|
|
|
|
gridEvents: {
|
|
|
|
|
cellMouseenter: (params) => {
|
|
|
|
|
const { row } = params;
|
|
|
|
|
row.isHovered = true;
|
|
|
|
|
},
|
|
|
|
|
cellMouseleave: (params) => {
|
|
|
|
|
const { row } = params;
|
|
|
|
|
row.isHovered = false;
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
const [DeviceModal, modalApi] = useVbenModal({
|
|
|
|
|
connectedComponent: deviceModal,
|
|
|
|
|
// 处理导出事件
|
|
|
|
|
const handleExport = () => {
|
|
|
|
|
console.log('导出设备列表');
|
|
|
|
|
commonDownloadExcel(deviceExport, '设备数据', searchForm.value, {
|
|
|
|
|
fieldMappingTime: [], // 根据实际需要填写时间字段映射
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
onMounted(async () => {
|
|
|
|
|
const response = await deviceList({ pageNum: 1, pageSize: 10 });
|
|
|
|
|
listData.value = response.rows;
|
|
|
|
|
total.value = response.total;
|
|
|
|
|
console.log(response.rows);
|
|
|
|
|
});
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
function handleAdd() {
|
|
|
|
|
modalApi.setData({});
|
|
|
|
|
modalApi.open();
|
|
|
|
|
<template>
|
|
|
|
|
<Layout>
|
|
|
|
|
<Layout.Content class="page-content">
|
|
|
|
|
<!-- 搜索条件区域 -->
|
|
|
|
|
<div class="search-container">
|
|
|
|
|
<div class="search-form-wrapper">
|
|
|
|
|
<Form layout="inline" :model="searchForm">
|
|
|
|
|
<div class="search-conditions">
|
|
|
|
|
<Form.Item label="设备名称">
|
|
|
|
|
<Input v-model:value="searchForm.name" placeholder="请输入" />
|
|
|
|
|
</Form.Item>
|
|
|
|
|
<Form.Item label="状态">
|
|
|
|
|
<RadioGroup
|
|
|
|
|
v-model:value="searchForm.status"
|
|
|
|
|
button-style="solid"
|
|
|
|
|
>
|
|
|
|
|
<RadioButton value="0">离线</RadioButton>
|
|
|
|
|
<RadioButton value="1">在线</RadioButton>
|
|
|
|
|
</RadioGroup>
|
|
|
|
|
</Form.Item>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="search-buttons">
|
|
|
|
|
<Form.Item>
|
|
|
|
|
<Button style="margin-right: 8px" @click="handleReset">
|
|
|
|
|
重置
|
|
|
|
|
</Button>
|
|
|
|
|
<Button type="primary" @click="handleSearch">搜索</Button>
|
|
|
|
|
</Form.Item>
|
|
|
|
|
</div>
|
|
|
|
|
</Form>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- 列表和分页区域 -->
|
|
|
|
|
<div class="list-container">
|
|
|
|
|
<div class="list-actions">
|
|
|
|
|
<div class="list-title">设备列表</div>
|
|
|
|
|
<div class="action-buttons">
|
|
|
|
|
<Button @click="handleExport">导出</Button>
|
|
|
|
|
<Button style="margin-left: 8px" @click="handleAdd">新增</Button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<List
|
|
|
|
|
:grid="{ gutter: 16, column: 4 }"
|
|
|
|
|
:data-source="listData"
|
|
|
|
|
:pagination="false"
|
|
|
|
|
class="list-content"
|
|
|
|
|
>
|
|
|
|
|
<template #renderItem="{ item }">
|
|
|
|
|
<List.Item>
|
|
|
|
|
<Card hoverable style="width: 100%">
|
|
|
|
|
<Card.Meta :title="item.name" />
|
|
|
|
|
<div style="margin-top: 18px">
|
|
|
|
|
<Tag :color="item.status === '1' ? 'green' : 'red'">
|
|
|
|
|
{{ item.status === '1' ? '在线' : '离线' }}
|
|
|
|
|
</Tag>
|
|
|
|
|
</div>
|
|
|
|
|
<template #actions>
|
|
|
|
|
<EyeOutlined key="view" @click="handleView(item)" />
|
|
|
|
|
<EditOutlined key="edit" @click="handleEdit(item)" />
|
|
|
|
|
<Popconfirm
|
|
|
|
|
title="确定要删除这个设备吗?"
|
|
|
|
|
ok-text="是"
|
|
|
|
|
cancel-text="否"
|
|
|
|
|
@confirm="confirm(item)"
|
|
|
|
|
@cancel="cancel"
|
|
|
|
|
>
|
|
|
|
|
<DeleteOutlined key="delete" @click="" />
|
|
|
|
|
</Popconfirm>
|
|
|
|
|
</template>
|
|
|
|
|
</Card>
|
|
|
|
|
</List.Item>
|
|
|
|
|
</template>
|
|
|
|
|
</List>
|
|
|
|
|
|
|
|
|
|
<!-- 分页组件 -->
|
|
|
|
|
<div class="pagination-wrapper">
|
|
|
|
|
<Pagination
|
|
|
|
|
v-model:current="current"
|
|
|
|
|
:total="total"
|
|
|
|
|
show-size-changer
|
|
|
|
|
:page-size-options="pageSizeOptions"
|
|
|
|
|
:show-total="(total) => `共 ${total} 条记录`"
|
|
|
|
|
@change="handlePageChange"
|
|
|
|
|
@show-size-change="handlePageSizeChange"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</Layout.Content>
|
|
|
|
|
</Layout>
|
|
|
|
|
<DeviceModal @reload="handleReset()" />
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<style scoped>
|
|
|
|
|
.page-content {
|
|
|
|
|
padding: 18px;
|
|
|
|
|
background-color: #f0f2f5;
|
|
|
|
|
min-height: calc(100vh - 100px);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function handleEdit(row: Required<DeviceForm>) {
|
|
|
|
|
modalApi.setData({ id: row.id });
|
|
|
|
|
modalApi.open();
|
|
|
|
|
.search-container {
|
|
|
|
|
background: #fff;
|
|
|
|
|
padding: 18px;
|
|
|
|
|
margin-bottom: 16px;
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function handlePreview(row: Required<DeviceForm>) {
|
|
|
|
|
await router.push(`/hazard/devicePreview/${row.id}`);
|
|
|
|
|
.search-form-wrapper {
|
|
|
|
|
display: flex;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
align-items: center;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function handleDelete(row: Required<DeviceForm>) {
|
|
|
|
|
await deviceRemove(row.id);
|
|
|
|
|
await tableApi.query();
|
|
|
|
|
.search-conditions {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function handleMultiDelete() {
|
|
|
|
|
const rows = tableApi.grid.getCheckboxRecords();
|
|
|
|
|
const ids = rows.map((row: Required<DeviceForm>) => row.id);
|
|
|
|
|
Modal.confirm({
|
|
|
|
|
title: '提示',
|
|
|
|
|
okType: 'danger',
|
|
|
|
|
content: `确认删除选中的${ids.length}条记录吗?`,
|
|
|
|
|
onOk: async () => {
|
|
|
|
|
await deviceRemove(ids);
|
|
|
|
|
await tableApi.query();
|
|
|
|
|
checked.value = false;
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
.search-buttons {
|
|
|
|
|
display: flex;
|
|
|
|
|
justify-content: flex-end;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function handleDownloadExcel() {
|
|
|
|
|
commonDownloadExcel(deviceExport, '设备数据', tableApi.formApi.form.values, {
|
|
|
|
|
fieldMappingTime: formOptions.fieldMappingTime,
|
|
|
|
|
});
|
|
|
|
|
.list-container {
|
|
|
|
|
background: #fff;
|
|
|
|
|
padding: 12px 24px;
|
|
|
|
|
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05);
|
|
|
|
|
min-height: calc(100vh - 200px);
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.list-content {
|
|
|
|
|
flex: 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.pagination-wrapper {
|
|
|
|
|
margin-top: 24px;
|
|
|
|
|
text-align: center;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 在组件挂载时获取传感器数据
|
|
|
|
|
onMounted(async () => {
|
|
|
|
|
try {
|
|
|
|
|
sensors.value = await sensorQuery();
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('获取传感器数据失败:', error);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
</script>
|
|
|
|
|
:deep(.ant-layout-content) {
|
|
|
|
|
min-height: calc(100vh - 100px);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
<template>
|
|
|
|
|
<Page :auto-content-height="true">
|
|
|
|
|
<BasicTable table-title="设备列表">
|
|
|
|
|
<template #toolbar-tools>
|
|
|
|
|
<Space>
|
|
|
|
|
<a-button
|
|
|
|
|
v-access:code="['hazard:device:export']"
|
|
|
|
|
@click="handleDownloadExcel"
|
|
|
|
|
>
|
|
|
|
|
{{ $t('pages.common.export') }}
|
|
|
|
|
</a-button>
|
|
|
|
|
<a-button
|
|
|
|
|
:disabled="!vxeCheckboxChecked(tableApi)"
|
|
|
|
|
danger
|
|
|
|
|
type="primary"
|
|
|
|
|
v-access:code="['hazard:device:remove']"
|
|
|
|
|
@click="handleMultiDelete"
|
|
|
|
|
>
|
|
|
|
|
{{ $t('pages.common.delete') }}
|
|
|
|
|
</a-button>
|
|
|
|
|
<a-button
|
|
|
|
|
type="primary"
|
|
|
|
|
v-access:code="['hazard:device:add']"
|
|
|
|
|
@click="handleAdd"
|
|
|
|
|
>
|
|
|
|
|
{{ $t('pages.common.add') }}
|
|
|
|
|
</a-button>
|
|
|
|
|
</Space>
|
|
|
|
|
</template>
|
|
|
|
|
<template #sensorCode="{ row }">
|
|
|
|
|
<div v-if="row.sensorCode">
|
|
|
|
|
{{
|
|
|
|
|
(() => {
|
|
|
|
|
// 处理sensorCode数据,支持数组和逗号分隔字符串
|
|
|
|
|
const sensorIds = Array.isArray(row.sensorCode)
|
|
|
|
|
? row.sensorCode
|
|
|
|
|
: typeof row.sensorCode === 'string'
|
|
|
|
|
? row.sensorCode.split(',').map(id => id.trim()).filter(id => id)
|
|
|
|
|
: [];
|
|
|
|
|
.list-actions {
|
|
|
|
|
display: flex;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
align-items: center;
|
|
|
|
|
margin-bottom: 16px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 根据ID匹配传感器名称
|
|
|
|
|
return sensorIds
|
|
|
|
|
.map(id => {
|
|
|
|
|
const sensor = sensors.find(s => s.id == id);
|
|
|
|
|
return sensor ? sensor.name : id;
|
|
|
|
|
})
|
|
|
|
|
.join('\n'); // 使用换行符连接多个传感器名称
|
|
|
|
|
})()
|
|
|
|
|
}}
|
|
|
|
|
</div>
|
|
|
|
|
<div v-else>-</div>
|
|
|
|
|
</template>
|
|
|
|
|
<template #action="{ row }">
|
|
|
|
|
<Space>
|
|
|
|
|
<ghost-button
|
|
|
|
|
v-access:code="['hazard:device:edit']"
|
|
|
|
|
@click.stop="handlePreview(row)"
|
|
|
|
|
>
|
|
|
|
|
{{ $t('pages.common.preview') }}
|
|
|
|
|
</ghost-button>
|
|
|
|
|
<ghost-button
|
|
|
|
|
v-access:code="['hazard:device:edit']"
|
|
|
|
|
@click.stop="handleEdit(row)"
|
|
|
|
|
>
|
|
|
|
|
{{ $t('pages.common.edit') }}
|
|
|
|
|
</ghost-button>
|
|
|
|
|
<Popconfirm
|
|
|
|
|
:get-popup-container="getVxePopupContainer"
|
|
|
|
|
placement="left"
|
|
|
|
|
title="确认删除?"
|
|
|
|
|
@confirm="handleDelete(row)"
|
|
|
|
|
>
|
|
|
|
|
<ghost-button
|
|
|
|
|
danger
|
|
|
|
|
v-access:code="['hazard:device:remove']"
|
|
|
|
|
@click.stop=""
|
|
|
|
|
>
|
|
|
|
|
{{ $t('pages.common.delete') }}
|
|
|
|
|
</ghost-button>
|
|
|
|
|
</Popconfirm>
|
|
|
|
|
</Space>
|
|
|
|
|
</template>
|
|
|
|
|
</BasicTable>
|
|
|
|
|
<DeviceModal @reload="tableApi.query()" />
|
|
|
|
|
</Page>
|
|
|
|
|
</template>
|
|
|
|
|
.list-title {
|
|
|
|
|
font-size: 18px;
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
color: #333;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.action-buttons {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
}
|
|
|
|
|
</style>
|
|
|
|
|
|