refactor.dashboard: 重构工作台页面

- 移除欢迎信息和分割线
- 添加产品数、设备数等统计卡片
- 新增链式图表组件
- 更新数据面板布局和样式
- 添加设备上报记录功能
-优化地图组件
- 调整产品属性表格
This commit is contained in:
Kven 2025-03-02 17:53:03 +08:00
parent ea1df9d55f
commit 64d2079779
9 changed files with 564 additions and 196 deletions

22
src/api/dashboard.ts Normal file
View File

@ -0,0 +1,22 @@
import axios from 'axios';
// 获取设备信息
export function getDeviceInfo() {
return axios.get('/api/rest/device/status');
}
// 获取消息信息
export function getMessageInfo() {
return axios.get('/api/rest/device/record/status');
}
// 获取告警信息
export function getAlarmInfo() {
return axios.get('/api/rest/device/data/status');
}
// 获取产品信息
export function getProductInfo() {
return axios.get('/api/rest/product/status');
}

View File

@ -32,11 +32,12 @@ export interface DeviceUpdateRecord extends DeviceCreateRecord {
export interface DeviceEventRecord { export interface DeviceEventRecord {
id: number; id: number;
clientId: string; clientId: number;
serveName: string; serveName: string;
params: string; params: string;
} }
// 分页查询 // 分页查询
export function queryDeviceList(data: DeviceRecord) { export function queryDeviceList(data: DeviceRecord) {
return axios({ return axios({
@ -74,11 +75,11 @@ export function deleteDevice(id: number) {
} }
// 查询上报 // 查询上报
export function queryDeviceReport(clientId: number) { export function queryDeviceRecord(data: DeviceRecord) {
return axios({ return axios({
url: `/api/rest/device/record/photo`, url: `/api/rest/device/record/data`,
method: 'get', method: 'get',
params: clientId, params: data,
}); });
} }
@ -95,3 +96,5 @@ export function triggerEvent(data: DeviceEventRecord) {
data, data,
}); });
} }

View File

@ -1,11 +1,11 @@
<template> <template>
<a-col class="banner"> <a-col class="banner">
<a-col :span="8"> <!-- <a-col :span="8">-->
<a-typography-title :heading="5" style="margin-top: 0"> <!-- <a-typography-title :heading="5" style="margin-top: 0">-->
{{ $t('workplace.welcome') }} {{ userInfo.name }} <!-- {{ $t('workplace.welcome') }} {{ userInfo.name }}-->
</a-typography-title> <!-- </a-typography-title>-->
</a-col> <!-- </a-col>-->
<a-divider class="panel-border" /> <!-- <a-divider class="panel-border" />-->
</a-col> </a-col>
</template> </template>
@ -25,7 +25,7 @@
.banner { .banner {
width: 100%; width: 100%;
padding: 20px 20px 0 20px; padding: 20px 20px 0 20px;
background-color: var(--color-bg-2); //background-color: var(--color-bg-2);
border-radius: 4px 4px 0 0; border-radius: 4px 4px 0 0;
} }

View File

@ -0,0 +1,264 @@
<template>
<a-spin :loading="loading" style="width: 100%">
<a-card :bordered="false" :style="cardStyle">
<div class="content-wrap">
<div class="content">
<a-statistic
:title="title"
:value="renderData.count"
:value-from="0"
animation
show-group-separator
/>
<div class="desc">
<a-typography-text type="secondary" class="label">
较昨日
</a-typography-text>
<a-typography-text type="danger">
{{ renderData.growth }}
<icon-arrow-rise />
</a-typography-text>
</div>
</div>
<div class="chart">
<Chart v-if="!loading" :option="chartOption" />
</div>
</div>
</a-card>
</a-spin>
</template>
<script lang="ts" setup>
import { ref, PropType, CSSProperties } from 'vue';
import useLoading from '@/hooks/loading';
import useChartOption from '@/hooks/chart-option';
const barChartOptionsFactory = () => {
const data = ref<any>([]);
const { chartOption } = useChartOption(() => {
return {
grid: {
left: 0,
right: 0,
top: 10,
bottom: 0,
},
xAxis: {
type: 'category',
show: false,
},
yAxis: {
show: false,
},
tooltip: {
show: true,
trigger: 'axis',
},
series: {
name: 'total',
data,
type: 'bar',
barWidth: 7,
itemStyle: {
borderRadius: 2,
},
},
};
});
return {
data,
chartOption,
};
};
const lineChartOptionsFactory = () => {
const data = ref<number[][]>([[], []]);
const { chartOption } = useChartOption(() => {
return {
grid: {
left: 0,
right: 0,
top: 10,
bottom: 0,
},
xAxis: {
type: 'category',
show: false,
},
yAxis: {
show: false,
},
tooltip: {
show: true,
trigger: 'axis',
},
series: [
{
name: '2001',
data: data.value[0],
type: 'line',
showSymbol: false,
smooth: true,
lineStyle: {
color: '#165DFF',
width: 3,
},
},
{
name: '2002',
data: data.value[1],
type: 'line',
showSymbol: false,
smooth: true,
lineStyle: {
color: '#6AA1FF',
width: 3,
type: 'dashed',
},
},
],
};
});
return {
data,
chartOption,
};
};
const pieChartOptionsFactory = () => {
const data = ref<any>([]);
const { chartOption } = useChartOption(() => {
return {
grid: {
left: 0,
right: 0,
top: 0,
bottom: 0,
},
legend: {
show: true,
top: 'center',
right: '0',
orient: 'vertical',
icon: 'circle',
itemWidth: 6,
itemHeight: 6,
textStyle: {
color: '#4E5969',
},
},
tooltip: {
show: true,
},
series: [
{
name: '总计',
type: 'pie',
radius: ['50%', '70%'],
label: {
show: false,
},
data,
},
],
};
});
return {
data,
chartOption,
};
};
const props = defineProps({
title: {
type: String,
default: '',
},
quota: {
type: String,
default: '',
},
chartType: {
type: String,
default: '',
},
cardStyle: {
type: Object as PropType<CSSProperties>,
default: () => {
return {};
},
},
});
const { loading, setLoading } = useLoading(true);
const { chartOption: lineChartOption, data: lineData } =
lineChartOptionsFactory();
const { chartOption: barChartOption, data: barData } =
barChartOptionsFactory();
const { chartOption: pieChartOption, data: pieData } =
pieChartOptionsFactory();
const renderData = ref<any>({
count: 0,
growth: 0,
chartData: [],
});
const chartOption = ref({});
try {
// const { data } = renderData.value
// renderData.value = data;
if (props.chartType === 'bar') {
chartOption.value = barChartOption.value;
} else if (props.chartType === 'line') {
chartOption.value = lineChartOption.value;
} else {
chartOption.value = pieChartOption.value;
}
} catch (err) {
// you can report use errorHandler or other
} finally {
setLoading(false);
}
</script>
<style scoped lang="less">
:deep(.arco-card) {
border-radius: 4px;
}
:deep(.arco-card-body) {
width: 100%;
height: 134px;
padding: 0;
}
.content-wrap {
width: 100%;
padding: 16px;
white-space: nowrap;
}
:deep(.content) {
float: left;
width: 108px;
height: 102px;
}
:deep(.arco-statistic) {
.arco-statistic-title {
font-size: 16px;
font-weight: bold;
white-space: nowrap;
}
.arco-statistic-content {
margin-top: 10px;
}
}
.chart {
float: right;
width: calc(100% - 108px);
height: 90px;
vertical-align: bottom;
}
.label {
padding-right: 8px;
font-size: 12px;
}
</style>

View File

@ -1,158 +1,203 @@
<template> <template>
<div style="width: 100%"> <div style="width: 100%">
<a-grid :cols="24" :row-gap="16" class="panel"> <a-grid :cols="24" :row-gap="10" :col-gap="10" class="panel">
<a-grid-item <a-grid-item
class="panel-col" class="panel-col"
:span="{ xs: 12, sm: 12, md: 12, lg: 12, xl: 12, xxl: 6 }" :span="{ xs: 12, sm: 12, md: 12, lg: 8, xl: 6, xxl: 6 }"
> >
<a-space @click="to('PASS')"> <a-card :bordered="false" class="square-card">
<a-avatar :size="54" class="col-avatar"> <a-row align="center">
<img <a-col :span="12">
alt="avatar" <a-statistic
src="//p3-armor.byteimg.com/tos-cn-i-49unhts6dw/288b89194e657603ff40db39e8072640.svg~tplv-49unhts6dw-image.image" title="产品数"
/> value-style="font-size:36px"
</a-avatar> :value="365"
<a-statistic :value-from="0"
title="通过" animation
:value="formData.pass || 0" >
:value-from="0" </a-statistic>
show-group-separator </a-col>
> <a-col :span="12">
<template #suffix> <a-avatar
<span class="unit">{{ $t('workplace.pecs') }}</span> :size="80"
</template> image-url="http://iot.le5le.cn/iot/img/%E4%BA%A7%E5%93%81.png"
</a-statistic> shape="square"
</a-space> :style="{ backgroundColor: '#ffffff' }"
/>
<!-- <a-avatar-->
<!-- :size="80"-->
<!-- image-url="http://iot.le5le.cn/iot/img/%E6%95%B0%E6%8D%AE.png"-->
<!-- shape="square"-->
<!-- :style="{ backgroundColor: '#ffffff' }"-->
<!-- />-->
</a-col>
</a-row>
<a-descriptions :data="data" layout="inline-vertical" class="responsive-margin" />
</a-card>
</a-grid-item> </a-grid-item>
<a-grid-item <a-grid-item
class="panel-col" class="panel-col"
:span="{ xs: 12, sm: 12, md: 12, lg: 12, xl: 12, xxl: 6 }" :span="{ xs: 12, sm: 12, md: 12, lg: 8, xl: 6, xxl: 6 }"
> >
<a-space @click="to('FAILED')"> <a-card :bordered="false" class="square-card">
<a-avatar :size="54" class="col-avatar"> <a-row align="center">
<img <a-col :span="12">
alt="avatar" <a-statistic
src="//p3-armor.byteimg.com/tos-cn-i-49unhts6dw/fdc66b07224cdf18843c6076c2587eb5.svg~tplv-49unhts6dw-image.image" title="设备数"
/> value-style="font-size:36px"
</a-avatar> :value="deviceInfo.deviceCount"
<a-statistic :value-from="0"
title="未通过" animation
:value="formData.notPass || 0" >
:value-from="0" </a-statistic>
show-group-separator </a-col>
> <a-col :span="12">
<template #suffix> <a-avatar
<span class="unit">{{ $t('workplace.pecs') }}</span> :size="80"
</template> image-url="http://iot.le5le.cn/iot/img/%E8%AE%BE%E5%A4%87.png"
</a-statistic> shape="square"
</a-space> :style="{ backgroundColor: '#ffffff' }"
/>
</a-col>
</a-row>
<a-descriptions :data="data" layout="inline-vertical" class="responsive-margin" />
</a-card>
</a-grid-item> </a-grid-item>
<a-grid-item <a-grid-item
class="panel-col" class="panel-col"
:span="{ xs: 12, sm: 12, md: 12, lg: 12, xl: 12, xxl: 6 }" :span="{ xs: 12, sm: 12, md: 12, lg: 8, xl: 6, xxl: 6 }"
> >
<a-space @click="to('EXAMINE')"> <a-card :bordered="false" class="square-card">
<a-avatar :size="54" class="col-avatar"> <a-row align="center">
<img <a-col :span="12">
alt="avatar" <a-statistic
src="//p3-armor.byteimg.com/tos-cn-i-49unhts6dw/77d74c9a245adeae1ec7fb5d4539738d.svg~tplv-49unhts6dw-image.image" title="产品数"
/> value-style="font-size:36px"
</a-avatar> :value="365"
<a-statistic :value-from="0"
title="未审计" animation
:value="formData.notAudit || 0" >
:value-from="0" </a-statistic>
show-group-separator </a-col>
> <a-col :span="12">
<template #suffix> <a-avatar
<span class="unit">{{ $t('workplace.pecs') }}</span> :size="80"
</template> image-url="http://iot.le5le.cn/iot/img/%E5%91%8A%E8%AD%A6.png"
</a-statistic> shape="square"
</a-space> :style="{ backgroundColor: '#ffffff' }"
/>
</a-col>
</a-row>
<a-descriptions :data="data" layout="inline-vertical" class="responsive-margin" />
</a-card>
</a-grid-item> </a-grid-item>
<a-grid-item <a-grid-item
v-if="userStore.permissions !== 'auditor'"
class="panel-col" class="panel-col"
:span="{ xs: 12, sm: 12, md: 12, lg: 12, xl: 12, xxl: 6 }" :span="{ xs: 12, sm: 12, md: 12, lg: 8, xl: 6, xxl: 6 }"
style="border-right: none"
> >
<a-space @click="to('SUBMIT')"> <Announcement />
<a-avatar :size="54" class="col-avatar"> </a-grid-item>
<img <a-grid-item :span="24">
alt="avatar" <a-divider class="panel-border" />
src="//p3-armor.byteimg.com/tos-cn-i-49unhts6dw/c8b36e26d2b9bb5dbf9b74dd6d7345af.svg~tplv-49unhts6dw-image.image" </a-grid-item>
/> </a-grid>
</a-avatar> <a-grid :span="24" :row-gap="10" :col-gap="10" class="panel">
<a-statistic <a-grid-item
v-model="formData.notFiled" class="panel-col"
title="未归档" :span="{ xs: 12, sm: 12, md: 12, lg: 12, xl: 8, xxl: 8 }">
:value="formData.notFiled || 0" <ChainItem
:value-from="0" title="分享总量"
show-group-separator quota="share"
> chart-type="pie"
<template #suffix> :card-style="{
<span class="unit">{{ $t('workplace.pecs') }}</span> background: isDark
</template> ? 'linear-gradient(180deg, #312565 0%, #201936 100%)'
</a-statistic> : 'linear-gradient(180deg, #F7F7FF 0%, #ECECFF 100%)',
</a-space> }"
/>
</a-grid-item>
<a-grid-item
class="panel-col"
:span="{ xs: 12, sm: 12, md: 12, lg: 12, xl: 8, xxl: 8 }">
<ChainItem
title="分享总量"
quota="share"
chart-type="pie"
:card-style="{
background: isDark
? 'linear-gradient(180deg, #312565 0%, #201936 100%)'
: 'linear-gradient(180deg, #F7F7FF 0%, #ECECFF 100%)',
}"
/>
</a-grid-item>
<a-grid-item
class="panel-col"
:span="{ xs: 12, sm: 12, md: 12, lg: 12, xl: 8, xxl: 8 }">
<ChainItem
title="分享总量"
quota="share"
chart-type="pie"
:card-style="{
background: isDark
? 'linear-gradient(180deg, #312565 0%, #201936 100%)'
: 'linear-gradient(180deg, #F7F7FF 0%, #ECECFF 100%)',
}"
/>
</a-grid-item> </a-grid-item>
<a-grid-item :span="24"> <a-grid-item :span="24">
<a-divider class="panel-border" /> <a-divider class="panel-border" />
</a-grid-item> </a-grid-item>
</a-grid> </a-grid>
<a-card :bordered="false">
<a-space id="TicketEcharts" style="width: 98%; height: 400px"></a-space>
</a-card>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { useI18n } from 'vue-i18n'; import Announcement from '@/views/dashboard/workplace/components/announcement.vue';
import { useUserStore } from '@/store'; import ChainItem from '@/views/dashboard/workplace/components/chain-item.vue';
import useThemes from '@/hooks/themes';
import { getDeviceInfo } from '@/api/dashboard';
import { onMounted, ref } from 'vue'; import { onMounted, ref } from 'vue';
import * as echarts from 'echarts';
import router from '@/router';
const { t } = useI18n(); const data = [{
const userStore = useUserStore(); label: 'Name',
const formData = ref({ value: 'Socrates',
notAudit: undefined, }, {
notFiled: undefined, label: 'Mobile',
notPass: undefined, value: '123',
pass: undefined, }, {
}); label: 'Residence',
value: 'Beijing'
const getHomeData = async (params: { }];
auditorId: number | undefined; const deviceInfo = ref({
userId: number | string | undefined; deviceCount: 0,
}) => { onlineCount: 0,
if (userStore.permissions === 'admin') { offlineCount: 0,
params.userId = ''; alarmCount: 0,
} else if (userStore.permissions === 'auditor') { productCount: 0,
params.auditorId = userStore.id; })
} else if (userStore.permissions === 'user') { const fetchData = async () => {
params.userId = userStore.id; const res = await getDeviceInfo();
} deviceInfo.value = res.data;
}; }
const { isDark } = useThemes();
const to = (key: string) => { onMounted(() => {
router.push({ fetchData();
name: 'TicketManage', })
query: {
status: key,
},
});
};
getHomeData({});
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.arco-grid.panel { .arco-grid.panel {
margin-bottom: 0; margin-bottom: 0;
padding: 16px 20px 0 20px; padding: 10px 20px 0 0;
} }
.panel-col { .panel-col {
padding-left: 43px; padding-left: 20px; // : 使
border-right: 1px solid rgb(var(--gray-2)); border-right: 1px solid rgb(var(--gray-2));
} }
.col-avatar { .col-avatar {
@ -170,4 +215,14 @@
:deep(.panel-border) { :deep(.panel-border) {
margin: 4px 0 0 0; margin: 4px 0 0 0;
} }
.square-card {
width: 100%;
//aspect-ratio: 4 / 3; // : 4:3
padding: 15px 20px 13px 20px;
}
.responsive-margin {
margin-top: 20px; //
}
</style> </style>

View File

@ -16,21 +16,23 @@
</a-grid-item> </a-grid-item>
</a-grid> </a-grid>
</div> </div>
<div class="right-side"> <!-- <div class="right-side">-->
<a-grid :cols="24" :row-gap="16"> <!-- <a-grid :cols="24" :row-gap="16">-->
<a-grid-item :span="24"> <!-- <a-grid-item :span="24">-->
<div class="panel moduler-wrap"> <!-- <div class="panel moduler-wrap">-->
<QuickOperation /> <!--&lt;!&ndash; <QuickOperation />&ndash;&gt;-->
<RecentlyVisited /> <!--&lt;!&ndash; <RecentlyVisited />&ndash;&gt;-->
</div> <!-- </div>-->
</a-grid-item> <!-- </a-grid-item>-->
<a-grid-item class="panel" :span="24"> </a-grid-item> <!-- <a-grid-item class="panel" :span="24">-->
<a-grid-item class="panel" :span="24"> <!-- <Announcement />-->
<Announcement /> <!-- </a-grid-item>-->
</a-grid-item> <!-- <a-grid-item class="panel" :span="24">-->
<a-grid-item class="panel" :span="24"> </a-grid-item> <!-- <Announcement />-->
</a-grid> <!-- </a-grid-item>-->
</div> <!-- <a-grid-item class="panel" :span="24"> </a-grid-item>-->
<!-- </a-grid>-->
<!-- </div>-->
</div> </div>
</template> </template>
@ -50,7 +52,7 @@
<style lang="less" scoped> <style lang="less" scoped>
.container { .container {
background-color: var(--color-fill-2); //background-color: var(--color-fill-2);
padding: 16px 20px; padding: 16px 20px;
padding-bottom: 0; padding-bottom: 0;
display: flex; display: flex;
@ -67,7 +69,7 @@
} }
.panel { .panel {
background-color: var(--color-bg-2); //background-color: var(--color-bg-2);
border-radius: 4px; border-radius: 4px;
overflow: auto; overflow: auto;
} }
@ -77,7 +79,7 @@
} }
.moduler-wrap { .moduler-wrap {
border-radius: 4px; border-radius: 4px;
background-color: var(--color-bg-2); //background-color: var(--color-bg-2);
:deep(.text) { :deep(.text) {
font-size: 12px; font-size: 12px;
text-align: center; text-align: center;

View File

@ -63,6 +63,9 @@
<a-tab-pane key="3" tab="执行服务" title="执行服务"> <a-tab-pane key="3" tab="执行服务" title="执行服务">
执行服务内容 执行服务内容
</a-tab-pane> </a-tab-pane>
<a-tab-pane key="4" tab="上报记录" title="上报记录">
<a-table :columns="deviceReportColumns" :data="deviceReportData" />
</a-tab-pane>
</a-tabs> </a-tabs>
</a-card> </a-card>
</div> </div>
@ -72,7 +75,7 @@
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import { useRoute } from 'vue-router'; import { useRoute } from 'vue-router';
import { onMounted, ref } from 'vue'; import { onMounted, ref } from 'vue';
import { queryDeviceDetail } from '@/api/device'; import { queryDeviceDetail, queryDeviceRecord } from '@/api/device';
const route = useRoute(); const route = useRoute();
const id = Number(route.params.id); const id = Number(route.params.id);
@ -98,11 +101,29 @@
slotName: 'type', slotName: 'type',
}, },
]; ];
const deviceReportColumns = [
{
title: '上报时间',
dataIndex: 'recordTime',
slotName: 'recordTime',
},
{
title: '内容',
dataIndex: 'content',
slotName: 'content',
},
];
const activeKey = ref('1'); const activeKey = ref('1');
const renderData = ref([]); const renderData = ref([]);
const deviceReportData = ref([]);
const fetchData = async (Id: number) => { const fetchData = async (Id: number) => {
const res = await queryDeviceDetail(Id); const res = await queryDeviceDetail(Id);
renderData.value = res.data; renderData.value = res.data;
const res1 = await queryDeviceRecord({
size: 10,
current: 1
});
deviceReportData.value = res1.data;
}; };
const handleMenuClick = (e: any) => { const handleMenuClick = (e: any) => {
activeKey.value = e; activeKey.value = e;

View File

@ -6,13 +6,6 @@
</a-layout-sider> </a-layout-sider>
<a-layout-content> <a-layout-content>
<div id="container"></div> <div id="container"></div>
<!-- 标记点信息弹出框 -->
<a-modal v-model:visible="infoVisible" title="设备信息" :footer="null">
<p>ID: {{ selectedDevice.id }}</p>
<p>名称: {{ selectedDevice.name }}</p>
<p>状态: {{ selectedDevice.state }}</p>
<p>在线状态: {{ selectedDevice.online ? '是' : '否' }}</p>
</a-modal>
</a-layout-content> </a-layout-content>
</a-layout> </a-layout>
</template> </template>
@ -24,43 +17,46 @@
import "@amap/amap-jsapi-types"; import "@amap/amap-jsapi-types";
let map: any = null; let map: any = null;
const selectedDevice = ref<DeviceRecord | null>(null);
const infoVisible = ref(false);
const deviceList = ref<DeviceRecord[]>([]); const deviceList = ref<DeviceRecord[]>([]);
const markerContent = `<div class="custom-content-marker"> AMapLoader.load({
<img src="//a.amap.com/jsapi_demos/static/demo-center/icons/dir-via-marker.png"> key: 'a4e80eed798a56451b226dcfca81b846', // WebKey load
<div class="close-btn">X</div> version: '2.0', // JSAPI 1.4.15
</div>`; plugins: [], // 使'AMap.Scale'
})
.then((AMap) => {
map = new AMap.Map('container', {
// id
viewMode: '3D', // 3D
zoom: 11, //
center: [116.397428, 39.90923], //
});
map.on('click', (e: any) => {
//
const lngLat = e.lnglat;
const content = document.createElement('div');
content.className = 'custom-content-marker';
content.innerHTML = `
<img src="https://webapi.amap.com/theme/v1.3/markers/n/mark_b.png" alt="标记点" />
<div class="close-btn">×</div>`;
//
const marker = new AMap.Marker({
position: lngLat,
content,
});
//
map.add(marker);
//
const closeBtn = marker.getContent().querySelector('.close-btn');
closeBtn.addEventListener('click', () => {
map.remove(marker); //
});
});
})
.catch((e) => {
console.log(e);
});
onMounted(() => { onMounted(() => {
AMapLoader.load({
key: 'a4e80eed798a56451b226dcfca81b846', // WebKey load
version: '2.0', // JSAPI 1.4.15
plugins: [], // 使'AMap.Scale'
})
.then((AMap) => {
map = new AMap.Map('container', {
// id
viewMode: '3D', // 3D
zoom: 11, //
center: [116.397428, 39.90923], //
});
//
const position = new AMap.LngLat(116.397428, 39.90923);
const marker = new AMap.Marker({
position,
content: markerContent,
offset: new AMap.Pixel(-13, -30),
});
map.add(marker);
})
.catch((e) => {
console.log(e);
});
// //
queryDeviceList({ queryDeviceList({
current: 1, current: 1,
@ -74,9 +70,9 @@
}); });
}); });
onUnmounted(() => { // onUnmounted(() => {
map?.destroy(); // map?.destroy();
}); // });
</script> </script>

View File

@ -23,7 +23,11 @@
<template #icon><icon-plus /></template> <template #icon><icon-plus /></template>
新建 新建
</a-button> </a-button>
<a-table :columns="columns" :data="propertyData"> <a-table
:columns="columns"
:data="propertyData"
:pagination="true"
>
<template #operation="{ record }"> <template #operation="{ record }">
<a-button <a-button
v-permission="['iot:property:delete']" v-permission="['iot:property:delete']"
@ -426,6 +430,7 @@
} from '@/api/tsl'; } from '@/api/tsl';
import type { SelectOptionData } from '@arco-design/web-vue/es/select/interface'; import type { SelectOptionData } from '@arco-design/web-vue/es/select/interface';
import { FormInstance } from '@arco-design/web-vue/es/form'; import { FormInstance } from '@arco-design/web-vue/es/form';
import usePagination from '@/hooks/pagination';
import { Message } from '@arco-design/web-vue'; import { Message } from '@arco-design/web-vue';
const { visible, setVisible } = useVisible(); const { visible, setVisible } = useVisible();
@ -579,7 +584,7 @@
const fetchData = async (Id: number) => { const fetchData = async (Id: number) => {
const params = { const params = {
size: 10, size: 50,
current: 1, current: 1,
productId: Id, productId: Id,
}; };