提交 7573ae84 authored 作者: hejie's avatar hejie

chore: 🔨 合并代码

...@@ -340,9 +340,6 @@ declare module "vue" { ...@@ -340,9 +340,6 @@ declare module "vue" {
interface GlobalComponents {} interface GlobalComponents {}
interface ComponentCustomProperties { interface ComponentCustomProperties {
readonly EffectScope: UnwrapRef<(typeof import("vue"))["EffectScope"]>; readonly EffectScope: UnwrapRef<(typeof import("vue"))["EffectScope"]>;
readonly ElMessageBox: UnwrapRef<
(typeof import("element-plus/es"))["ElMessageBox"]
>;
readonly acceptHMRUpdate: UnwrapRef< readonly acceptHMRUpdate: UnwrapRef<
(typeof import("pinia"))["acceptHMRUpdate"] (typeof import("pinia"))["acceptHMRUpdate"]
>; >;
......
...@@ -85,6 +85,7 @@ ...@@ -85,6 +85,7 @@
"mitt": "^3.0.1", "mitt": "^3.0.1",
"mqtt": "4.3.7", "mqtt": "4.3.7",
"nprogress": "^0.2.0", "nprogress": "^0.2.0",
"ol": "^10.5.0",
"path-browserify": "^1.0.1", "path-browserify": "^1.0.1",
"pinia": "^3.0.1", "pinia": "^3.0.1",
"pinyin-pro": "^3.26.0", "pinyin-pro": "^3.26.0",
......
差异被折叠。
...@@ -4,26 +4,29 @@ import { http } from "@/utils/http"; ...@@ -4,26 +4,29 @@ import { http } from "@/utils/http";
// deviceName: string; // deviceName: string;
// // ... 其他属性 // // ... 其他属性
// } // }
type RecordItem = {
[key: string]: any;
};
type ResultData = { type ResultData = {
fileId?: string; records?: Array<RecordItem>;
records?: Array<any>;
[key: string]: any; [key: string]: any;
// data?: DeviceInfo; // data?: DeviceInfo;
}; };
type Result = { type RcordsResult = {
success?: boolean; success?: boolean;
data: Array<ResultData>; data: ResultData;
msg: string; msg: string;
code: string; code: string;
requestId?: string; requestId?: string;
id?: number; id?: number;
status?: number;
}; };
type RcordsResult = { type Result = {
success?: boolean; success?: boolean;
data: ResultData; data: any;
msg: string; msg: string;
code: string; code: string;
requestId?: string; requestId?: string;
...@@ -123,3 +126,75 @@ export const getOperationRecords = (data?: object) => { ...@@ -123,3 +126,75 @@ export const getOperationRecords = (data?: object) => {
data data
}); });
}; };
// 获取设备分析接口
export const getDeviceAnalysis = (data?: object) => {
return http.request<RcordsResult>(
"post",
"/device/api/dev_device_status/list",
{
data
}
);
};
// 获取最新一条数据日志(监测因子)
export const getDataLogListLatest = (data?: object) => {
return http.request<RecordItem>(
"post",
"/device/api/device/get_device_data_latest",
{
data
}
);
};
// 获取数据日志列表(监测因子)
export const getDataLogList = (data?: object) => {
return http.request<RcordsResult>(
"post",
"/device/api/device/get_device_data_page",
{
data
}
);
};
// 获取数据图表数据
export const getDataChart = (data?: object) => {
return http.request<RcordsResult>(
"post",
"/device/api/device/get_device_data_chart",
{
data
}
);
};
// 获取设备类型数据
export const getDeviceTypeByType = (data?: object) => {
return http.request<RcordsResult>(
"post",
"/device/api/dev_base_data/get_data_by_type",
{
data
},
{
headers: {
"Content-Type": "multipart/form-data"
}
}
);
};
// 根据设备类型获取设备型号
export const getDeviceModel = (data?: object) => {
return http.request<RcordsResult>(
"post",
"/device/api/dev_base_data/get_data_by_parent",
{
data
},
{
headers: {
"Content-Type": "multipart/form-data"
}
}
);
};
...@@ -7,9 +7,9 @@ export default { ...@@ -7,9 +7,9 @@ export default {
}, },
children: [ children: [
{ {
path: "/device/detail2", path: "/device/childrenList",
name: "DeviceDetail2", name: "ChildrenList",
component: () => import("@/views/device/detail2.vue"), component: () => import("@/views/device/childrenList.vue"),
meta: { meta: {
showLink: false, showLink: false,
title: "无人机设备22" title: "无人机设备22"
......
...@@ -14,6 +14,22 @@ import NProgress from "../progress"; ...@@ -14,6 +14,22 @@ import NProgress from "../progress";
import { getToken, formatToken } from "@/utils/auth"; import { getToken, formatToken } from "@/utils/auth";
import { useUserStoreHook } from "@/store/modules/user"; import { useUserStoreHook } from "@/store/modules/user";
import packageJson from "../../../package.json"; import packageJson from "../../../package.json";
// import { debounce, throttle } from "@pureadmin/utils";
/** 节流配置:单位毫秒,key为接口路径 */
const throttleMap = new Map<string, number>();
/** 节流间隔(可根据需要调整) */
const THROTTLE_INTERVAL = 1000;
/** 生成接口唯一标识(可根据实际需求调整) */
function getThrottleKey(config: PureHttpRequestConfig): string {
const url = config.url || "";
const method = config.method || "get";
// 如果需要更细粒度,可以加上参数
const params = config.params ? JSON.stringify(config.params) : "";
const data = config.data ? JSON.stringify(config.data) : "";
return `${method}:${url}?${params}&${data}`;
}
// 相关配置请参考:www.axios-js.com/zh-cn/docs/#axios-request-config-1 // 相关配置请参考:www.axios-js.com/zh-cn/docs/#axios-request-config-1
const defaultConfig: AxiosRequestConfig = { const defaultConfig: AxiosRequestConfig = {
...@@ -65,8 +81,23 @@ class PureHttp { ...@@ -65,8 +81,23 @@ class PureHttp {
/** 请求拦截 */ /** 请求拦截 */
private httpInterceptorsRequest(): void { private httpInterceptorsRequest(): void {
// 请求接口时添加节流操作
PureHttp.axiosInstance.interceptors.request.use( PureHttp.axiosInstance.interceptors.request.use(
async (config: PureHttpRequestConfig): Promise<any> => { async (config: PureHttpRequestConfig): Promise<any> => {
// ====== 节流处理开始 ======
const throttleKey = getThrottleKey(config);
const now = Date.now();
if (throttleMap.has(throttleKey)) {
const lastTime = throttleMap.get(throttleKey)!;
if (now - lastTime < THROTTLE_INTERVAL) {
// 关闭进度条动画
NProgress.done();
// 拒绝本次请求
return Promise.reject({ isCancelRequest: true });
}
}
throttleMap.set(throttleKey, now);
// ====== 节流处理结束 ======
// 开启进度条动画 // 开启进度条动画
NProgress.start(); NProgress.start();
// 优先判断post/get等方法是否传入回调,否则执行初始化设置等回调 // 优先判断post/get等方法是否传入回调,否则执行初始化设置等回调
......
import dayjs from "dayjs";
// 定义一个方法,处理后端返回的二进制流,斌下载文件 // 定义一个方法,处理后端返回的二进制流,斌下载文件
export function downloadFile(response: any, fileName: string) { export function downloadFile(response: any, fileName: string) {
console.log("content-type", response); console.log("content-type", response);
...@@ -15,3 +16,40 @@ export function downloadFile(response: any, fileName: string) { ...@@ -15,3 +16,40 @@ export function downloadFile(response: any, fileName: string) {
document.body.appendChild(a); document.body.appendChild(a);
a.click(); a.click();
} }
/**
*使用dayjs库来处理日期,返回当天的起止日期,格式为YYYY-MM-DD HH:mm:ss
* type: "today" | "yesterday" | "lastWeek" | "lastThreeDays"
* */
export function getStartEndByType(type?: string) {
const start = dayjs().startOf("day").format("YYYY-MM-DD HH:mm:ss"); //获取当天的开始时间
const end = dayjs().endOf("day").format("YYYY-MM-DD HH:mm:ss"); //获取当天结束时间
//获取前一天的开始时间
const yesterdayStart = dayjs()
.subtract(1, "day")
.startOf("day")
.format("YYYY-MM-DD HH:mm:ss");
// 获取前三天的开始时间
const lastThreeDaysStart = dayjs()
.subtract(3, "day")
.startOf("day")
.format("YYYY-MM-DD HH:mm:ss");
// 获取一周的开始时间
const lastWeekStart = dayjs()
.subtract(7, "day")
.startOf("day")
.format("YYYY-MM-DD HH:mm:ss");
// 根据type返回不同的时间范围
switch (type) {
case "today":
return [start, end];
case "yesterday":
return [yesterdayStart, end];
case "lastWeek":
return [lastWeekStart, end];
case "lastThreeDays":
return [lastThreeDaysStart, end];
default:
return [start, end];
}
}
...@@ -11,7 +11,6 @@ const { ...@@ -11,7 +11,6 @@ const {
handleReset, handleReset,
handleSubmit, handleSubmit,
rules, rules,
validateForm,
deviceTypeOptions, deviceTypeOptions,
deviceLevelOptions, deviceLevelOptions,
changeLevel, changeLevel,
...@@ -20,7 +19,9 @@ const { ...@@ -20,7 +19,9 @@ const {
uploadFile, uploadFile,
// handleAvatarSuccess, // handleAvatarSuccess,
beforeAvatarUpload, beforeAvatarUpload,
deviceModelOptions deviceModelOptions,
handleEditImage,
changeDeviceType
} = useAddHook(formRef); } = useAddHook(formRef);
defineComponent({ defineComponent({
...@@ -90,7 +91,7 @@ defineComponent({ ...@@ -90,7 +91,7 @@ defineComponent({
</el-row> </el-row>
<el-row :gutter="50" class="my-5"> <el-row :gutter="50" class="my-5">
<el-col :span="8"> <el-col :span="8">
<el-form-item label="设备编号" prop="deviceCode"> <el-form-item label="设备编号">
<el-input <el-input
v-model="formObj.deviceCode" v-model="formObj.deviceCode"
placeholder="请输入设备编号" placeholder="请输入设备编号"
...@@ -103,6 +104,7 @@ defineComponent({ ...@@ -103,6 +104,7 @@ defineComponent({
<el-select <el-select
v-model="formObj.deviceType" v-model="formObj.deviceType"
placeholder="请选择设备类型" placeholder="请选择设备类型"
@change="changeDeviceType(formObj.deviceType)"
> >
<el-option <el-option
v-for="item in Object.keys(deviceTypeOptions)" v-for="item in Object.keys(deviceTypeOptions)"
...@@ -118,6 +120,7 @@ defineComponent({ ...@@ -118,6 +120,7 @@ defineComponent({
<el-select <el-select
v-model="formObj.deviceModel" v-model="formObj.deviceModel"
placeholder="请选择设备型号" placeholder="请选择设备型号"
:disabled="formObj.deviceType === ''"
> >
<el-option <el-option
v-for="item in Object.keys(deviceModelOptions)" v-for="item in Object.keys(deviceModelOptions)"
...@@ -176,7 +179,7 @@ defineComponent({ ...@@ -176,7 +179,7 @@ defineComponent({
<el-date-picker <el-date-picker
v-model="formObj.factoryTime" v-model="formObj.factoryTime"
type="date" type="date"
format="YYYY/MM/DD" format="YYYY-MM-DD"
value-format="YYYY-MM-DD" value-format="YYYY-MM-DD"
placeholder="请选择设备出厂日期" placeholder="请选择设备出厂日期"
/> />
...@@ -204,7 +207,7 @@ defineComponent({ ...@@ -204,7 +207,7 @@ defineComponent({
<el-date-picker <el-date-picker
v-model="formObj.inspectTime" v-model="formObj.inspectTime"
type="date" type="date"
format="YYYY/MM/DD" format="YYYY-MM-DD"
value-format="YYYY-MM-DD" value-format="YYYY-MM-DD"
placeholder="请选择年检提醒" placeholder="请选择年检提醒"
/> />
...@@ -222,13 +225,9 @@ defineComponent({ ...@@ -222,13 +225,9 @@ defineComponent({
</el-row> </el-row>
</el-col> </el-col>
<el-col :span="4" class="my-5 flex justify-center items-center"> <el-col :span="4" class="my-5 flex justify-center items-center">
<el-form-item <el-form-item label="设备图片" prop="fileUrl" label-position="top">
label="设备图片"
prop="fileList"
label-position="top"
:rules="[{ required: true, message: '附件不能为空' }]"
>
<el-upload <el-upload
v-if="!formObj.fileUrl"
ref="uploadRef" ref="uploadRef"
drag drag
multiple multiple
...@@ -236,14 +235,6 @@ defineComponent({ ...@@ -236,14 +235,6 @@ defineComponent({
:before-upload="beforeAvatarUpload" :before-upload="beforeAvatarUpload"
class="w-[200px]!" class="w-[200px]!"
> >
<!-- <img
:src="
formObj.devicePicture
? formObj.devicePicture
: 'https://shoplineimg.com/65a8de08211b1e008886980e/6659acc772c9d500104bb668/800x.png?'
"
alt=""
/> -->
<IconifyIconOnline <IconifyIconOnline
class="w-35 h-25 text-blue-300" class="w-35 h-25 text-blue-300"
icon="tabler:photo-up" icon="tabler:photo-up"
...@@ -254,6 +245,15 @@ defineComponent({ ...@@ -254,6 +245,15 @@ defineComponent({
<em> 可点击或拖拽上传 </em> <em> 可点击或拖拽上传 </em>
</div> </div>
</el-upload> </el-upload>
<img v-else :src="formObj.fileUrl" alt="" srcset="" />
<!-- 编辑图片按钮 -->
<el-button
type="primary"
size="small"
class="mt-2!"
@click="handleEditImage"
>{{ formObj.fileUrl ? "编辑" : "还原" }}</el-button
>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
......
<!-- 点击设备列表详情时,拥有子设备的时候静茹到此页面 -->
<script setup lang="ts"> <script setup lang="ts">
defineOptions({ defineOptions({
name: "DeviceDetail2" name: "DeviceDetail2"
......
<script setup lang="ts"> <script setup lang="ts">
import { reactive } from "vue"; import { reactive } from "vue";
import { useListHook } from "../utils/listHook";
const { lookDetail, listData } = useListHook();
// 定义props,接收父组件传递过来的数据childrenList // 定义props,接收父组件传递过来的数据childrenList
interface Device { interface Device {
deviceName: string; deviceName: string;
...@@ -15,6 +12,8 @@ interface Device { ...@@ -15,6 +12,8 @@ interface Device {
} }
const props = defineProps<{ const props = defineProps<{
childrenList: Device[]; childrenList: Device[];
lookDetail: (device: Device) => void;
listData: Device[];
}>(); }>();
const labels = reactive([ const labels = reactive([
{ {
...@@ -38,7 +37,7 @@ const deviceList = reactive([ ...@@ -38,7 +37,7 @@ const deviceList = reactive([
}, },
{ {
name: "设备类型", name: "设备类型",
prop: "deviceType", prop: "deviceTypeName",
value: "" value: ""
}, },
{ {
...@@ -48,7 +47,7 @@ const deviceList = reactive([ ...@@ -48,7 +47,7 @@ const deviceList = reactive([
}, },
{ {
name: "所属站点", name: "所属站点",
prop: "deviceSide", prop: "deviceSideName",
value: "" value: ""
}, },
{ {
...@@ -67,21 +66,17 @@ const deviceList = reactive([ ...@@ -67,21 +66,17 @@ const deviceList = reactive([
class="bg-gray-200 py-5 px-10 rounded-2xl mt-3 w-full" class="bg-gray-200 py-5 px-10 rounded-2xl mt-3 w-full"
> >
<el-col :span="3" :gutter="10"> <el-col :span="3" :gutter="10">
<img <img :src="device.fileUrl" alt="" srcset="" width="100"
src="https://shoplineimg.com/65a8de08211b1e008886980e/6659acc772c9d500104bb668/800x.png?"
alt=""
srcset=""
width="100"
/></el-col> /></el-col>
<el-col :span="21" class="cursor-pointer"> <el-col :span="21" class="cursor-pointer">
<div <div
class="flex justify-between items-center" class="flex justify-between items-center"
@click="lookDetail(device, index)" @click="lookDetail(device)"
> >
<div class="flex justify-between items-center"> <div class="flex justify-between items-center">
<span class="mr-10 font-semibold"> {{ device.deviceName }}</span> <span class="mr-10 font-semibold"> {{ device.deviceName }}</span>
</div> </div>
<el-button type="text" @click="lookDetail(device, index)" <el-button type="text" @click="lookDetail(device)"
>查看详情</el-button >查看详情</el-button
> >
</div> </div>
......
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive } from "vue";
import * as echarts from "echarts";
import { onMounted } from "vue"; import { onMounted } from "vue";
const radio = ref("今天"); import { getDataChart } from "@/api/device";
// 定义一个折线图 import LineChart from "./lineCharts.vue";
const tempCharts = ref(null); import timeControl from "./timeControl.vue";
const humiCharts = ref(null); import { getStartEndByType } from "@/utils/utils";
const AtmosphericCharts = ref(null);
const tempData = reactive({ const dataChartList = ref([]); // 数据图表数据
title: {
text: "温度", // 获取数据图表数据
left: "center" const getDataChartList = async (time?: Array<string>) => {
}, const res = await getDataChart({
tooltip: { // deviceCode: router.currentRoute.value.query?.deviceCode,
trigger: "axis" // deviceType: router.currentRoute.value.query?.deviceType || "NOISE",
}, deviceCode: "7012A11102298",
legend: { deviceType: "AIR_7012",
data: ["温度"], startTime: time ? time[0] : getStartEndByType()[0],
left: "left" endTime: time ? time[1] : getStartEndByType()[1]
}, });
xAxis: { if (!res || !res.data) return;
type: "category", dataChartList.value = (res.data as Array<any>) || [];
data: ["1月", "2月", "3月", "4月", "5月", "6月", "7月"] console.log(dataChartList.value);
}, };
yAxis: {
type: "value"
},
series: [
{
name: "温度",
type: "line",
data: [820, 932, 901, 934, 1290, 1330, 1320]
}
]
});
onMounted(() => { onMounted(() => {
// 初始化echarts getDataChartList();
tempCharts.value = echarts.init(document.getElementById("tempCharts"));
// 使用刚指定的配置项和数据显示图表。
tempCharts.value.setOption(tempData);
// 初始化湿度图表
humiCharts.value = echarts.init(document.getElementById("humiCharts"));
// 使用刚指定的配置项和数据显示图表。
humiCharts.value.setOption(tempData);
// 初始化大气压图表
AtmosphericCharts.value = echarts.init(
document.getElementById("AtmosphericCharts")
);
// 使用刚指定的配置项和数据显示图表。
AtmosphericCharts.value.setOption(tempData);
}); });
</script> </script>
<template> <template>
<div> <div>
<!-- 单选(紧凑风格的按钮样式) --> <!-- 单选(紧凑风格的按钮样式) -->
<el-radio-group v-model="radio"> <time-control @changeBtn="getDataChartList" />
<el-radio-button label="今天">今天</el-radio-button> <div class="flex justify-start w-full flex-wrap">
<el-radio-button label="3天">3天</el-radio-button> <div v-for="item in dataChartList" :key="item.id" class="basis-1/3">
<el-radio-button label="自定义">自定义</el-radio-button> <LineChart
</el-radio-group> :chartId="item.targetCode"
<!-- 三个echats折线图,分别是温度、大气压、湿度 --> :title="item.targetName"
<div class="flex justify-between w-full"> :dataChartItem="item.datas"
<div id="tempCharts" class="w-80 h-80" /> />
<div id="humiCharts" class="w-80 h-80" /> </div>
<div id="AtmosphericCharts" class="w-80 h-80" />
</div> </div>
</div> </div>
</template> </template>
......
<script setup lang="ts"> <script setup lang="ts">
import router from "@/router";
import { ref, reactive } from "vue"; import { ref, reactive } from "vue";
const date = ref(""); import { getDataLogList } from "@/api/device";
const pickerOptions = { import { getStartEndByType } from "@/utils/utils";
shortcuts: [ import type { PaginationProps } from "@pureadmin/table";
{
text: "今天", // 定义props,接收dataLogColumns
onClick(picker) { const props = defineProps({
picker.$emit("pick", new Date()); dataLogColumns: {
} type: Array,
}, default: () => []
{
text: "昨天",
onClick(picker) {
const date = new Date();
date.setTime(date.getTime() - 3600 * 1000 * 24);
picker.$emit("pick", date);
}
},
{
text: "一周前",
onClick(picker) {
const date = new Date();
date.setTime(date.getTime() - 3600 * 1000 * 24 * 7);
picker.$emit("pick", date);
}
} }
] });
const dataLogList = ref([]); // 数据日志列表
// const dataLogDate = ref(getStartEndByType());
const dataLogDate = ref(["2020-10-01 00:00:00", "2025-10-01 23:59:59"]);
const pagination = reactive<PaginationProps>({
total: 0,
pageSize: 10,
currentPage: 1,
background: true
});
// 获取数据日志列表数据
const getdeviceLogList = async () => {
const res = await getDataLogList({
deviceCode: router.currentRoute.value.query?.deviceCode,
deviceType: router.currentRoute.value.query?.deviceType || "NOISE",
startTime: dataLogDate.value ? dataLogDate.value[0] : null,
endTime: dataLogDate.value ? dataLogDate.value[1] : null,
pageNum: pagination.currentPage,
pageSize: pagination.pageSize
});
if (!res || !res.data) return;
pagination.total = res.data.total;
dataLogList.value = (res.data.records as Array<any>) || [];
}; };
const tableData = reactive([ // 处理分页大小改变
{ function handleSizeChange(val: number) {
time: "2023-10-01 12:00:00", // 更新分页大小
airPressure: "1013 hPa", pagination.pageSize = val;
temperature: "25 °C", // 获取设备日志列表
windSpeed: "5 m/s", getdeviceLogList();
windDirection: "北", }
rainfall: "0 mm",
L5: "10", // 处理当前页码变化
L10: "20", function handleCurrentChange(val: number) {
L50: "30", // 更新当前页码
L90: "40", pagination.currentPage = val;
L95: "50" // 获取设备日志列表
}, getdeviceLogList();
{ }
time: "2023-10-01 13:00:00", onMounted(() => {
airPressure: "1012 hPa", getdeviceLogList();
temperature: "26 °C", });
windSpeed: "6 m/s",
windDirection: "东北",
rainfall: "1 mm",
L5: "15",
L10: "25",
L50: "35",
L90: "45",
L95: "55"
}
]);
</script> </script>
<template> <template>
<div> <div>
<!-- 一个日期时间范围选择器 --> <!-- 一个日期时间范围选择器 -->
<el-date-picker <el-date-picker
v-model="date" v-model="dataLogDate"
type="daterange" type="datetimerange"
format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss"
class="mb-5"
start-placeholder="开始日期" start-placeholder="开始日期"
end-placeholder="结束日期" end-placeholder="结束日期"
:picker-options="pickerOptions" @change="getdeviceLogList"
/>
<pure-table
ref="tableRef"
border
alignWhole="center"
max-height="300"
height="300"
showOverflowTooltip
:data="dataLogList"
:pagination="{ ...pagination }"
:columns="dataLogColumns"
:header-cell-style="{
background: 'var(--el-fill-color-light)',
color: 'var(--el-text-color-primary)'
}"
@page-size-change="handleSizeChange"
@page-current-change="handleCurrentChange"
/> />
<!-- 一个表格,展示设备数据日志;表头分别是: 时间、大气压、温度、风速、风向、降雨量、L5、L10、L50、L90、L95 -->
<el-table :data="tableData">
<el-table-column prop="time" label="时间" />
<el-table-column prop="airPressure" label="大气压" />
<el-table-column prop="temperature" label="温度" />
<el-table-column prop="windSpeed" label="风速" />
<el-table-column prop="windDirection" label="风向" />
<el-table-column prop="rainfall" label="降雨量" />
<el-table-column prop="L5" label="L5" />
<el-table-column prop="L10" label="L10" />
<el-table-column prop="L50" label="L50" />
<el-table-column prop="L90" label="L90" />
<el-table-column prop="L95" label="L95" />
</el-table>
</div> </div>
</template> </template>
......
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive } from "vue"; import { ref, reactive } from "vue";
const radio = ref("今天"); import router from "@/router";
import { VxeTableBar } from "@/components/ReVxeTableBar";
import { getDeviceAnalysis } from "@/api/device";
import timeControl from "./timeControl.vue";
import { getStartEndByType } from "@/utils/utils";
const vxeTableRef = ref();
const deviceAnalysisList = ref([]); // 设备分析列表
const columns = [
{ field: "updateTime", title: "时间" },
{ field: "statusName", title: "设备状态" }
];
// 获取设别分析列表数据
const getDeviceAnalysisList = async (time?: Array<string>) => {
const res = await getDeviceAnalysis({
deviceCode: router.currentRoute.value.query?.deviceCode,
startTime: time ? time[0] : getStartEndByType()[0],
endTime: time ? time[1] : getStartEndByType()[1],
pageNum: 1,
pageSize: 10
});
if (!res || !res.data) return;
res.data.records.map(i => {
i.statusName = i.status === 1 ? "在线" : "离线";
});
deviceAnalysisList.value = (res.data.records as Array<any>) || [];
};
onMounted(() => {
getDeviceAnalysisList();
});
</script> </script>
<template> <template>
<div> <div>
<!-- 单选(紧凑风格的按钮样式) --> <!-- 单选(紧凑风格的按钮样式) -->
<el-radio-group v-model="radio"> <time-control @changeBtn="getDeviceAnalysisList" />
<el-radio-button label="今天">今天</el-radio-button>
<el-radio-button label="3天">3天</el-radio-button> <VxeTableBar :vxeTableRef="vxeTableRef" :columns="columns" title="设备分析">
<el-radio-button label="自定义">自定义</el-radio-button> <template v-slot="{ size, dynamicColumns }">
</el-radio-group> <vxe-grid
<!-- 这一块时暂无数据 --> ref="vxeTableRef"
<el-empty description="暂无数据" /> show-overflow
:size="size"
height="400"
:row-config="{ isHover: true }"
:scroll-y="{ enabled: true }"
:columns="dynamicColumns"
:data="deviceAnalysisList"
/>
</template>
</VxeTableBar>
</div> </div>
</template> </template>
......
<script setup lang="ts">
import * as echarts from "echarts";
defineOptions({
name: ""
});
const props = defineProps<{
chartId: string;
dataChartItem: Array<any>;
title: string;
// width: string;
// height: string;
}>();
// 定义一个折线图
const tempData = reactive({
tooltip: {
trigger: "axis"
// show: true
},
xAxis: {
type: "category",
data: []
},
yAxis: {
type: "value",
name: "",
axisLine: { show: true }, // 显示y轴轴线
// axisTick: { show: true }, // 显示y轴刻度
splitLine: { show: true } // 显示分割线
},
series: [
{
name: "温度",
type: "line",
data: [],
areaStyle: {
color: "rgba(0, 123, 255, 0.2)" // 蓝色填充,透明度可调
},
// lineStyle: {
// color: "#007bff"
// },
// itemStyle: {
// color: "#007bff"
// },
smooth: true, // 可选,平滑曲线
symbol: "none" // 不显示折线上的点
}
]
});
const tempCharts = ref(null);
onMounted(() => {
// 初始化echarts
tempCharts.value = echarts.init(document.getElementById(props.chartId));
// 使用刚指定的配置项和数据显示图表。
// tempCharts.value.setOption(tempData);
const newData = props.dataChartItem;
const xAxisData = newData.map(item => item.time);
const seriesData = newData.map(item => item.value);
// seriesData 添加10条假数据
if (!seriesData.length) {
for (let i = 0; i < 10; i++) {
seriesData.push(Math.random() * 100);
}
}
tempData.xAxis.data = xAxisData;
tempData.series[0].data = seriesData;
tempData.yAxis.name = props.title;
console.log("tempData", tempData);
// 使用刚指定的配置项和数据显示图表。
tempCharts.value.setOption(tempData);
});
</script>
<template>
<div class="lineCharts">
<div :id="chartId" class="w-60 h-80" />
</div>
</template>
<!-- <style lang="scss" scoped></style> -->
...@@ -23,27 +23,27 @@ const deviceList = reactive([ ...@@ -23,27 +23,27 @@ const deviceList = reactive([
{ {
name: "设备编号", name: "设备编号",
prop: "deviceCode", prop: "deviceCode",
value: "ZR103432434" value: ""
}, },
{ {
name: "设备类型", name: "设备类型",
prop: "deviceType", prop: "deviceTypeName",
value: "气体检测仪" value: ""
}, },
{ {
name: "设备型号", name: "设备型号",
prop: "deviceModel", prop: "deviceModel",
value: "ZR-351" value: ""
}, },
{ {
name: "所属站点", name: "所属站点",
prop: "deviceSide", prop: "deviceSideName",
value: "xxx街道南路01号" value: ""
}, },
{ {
name: "设备部署位置", name: "设备部署位置",
prop: "deviceAddress", prop: "deviceAddress",
value: "准格尔旗薛家湾" value: ""
} }
]); ]);
</script> </script>
...@@ -54,13 +54,13 @@ const deviceList = reactive([ ...@@ -54,13 +54,13 @@ const deviceList = reactive([
v-for="(device, index) in listData" v-for="(device, index) in listData"
:key="device.deviceCode" :key="device.deviceCode"
class="bg-gray-100 py-5 px-10 mb-8" class="bg-gray-100 py-5 px-10 mb-8"
@click="
device.children?.length ? toggleExpand(index) : lookDetail(device)
"
> >
<el-col :span="3" :gutter="10"> <el-col :span="3" :gutter="10">
<img <!-- https://shoplineimg.com/65a8de08211b1e008886980e/6659acc772c9d500104bb668/800x.png? -->
src="https://shoplineimg.com/65a8de08211b1e008886980e/6659acc772c9d500104bb668/800x.png?" <img :src="device.fileUrl" alt="" srcset="" width="100"
alt=""
srcset=""
width="100"
/></el-col> /></el-col>
<el-col :span="21" class="cursor-pointer"> <el-col :span="21" class="cursor-pointer">
<div class="flex justify-between items-center"> <div class="flex justify-between items-center">
...@@ -76,15 +76,13 @@ const deviceList = reactive([ ...@@ -76,15 +76,13 @@ const deviceList = reactive([
</div> </div>
</div> </div>
<div> <div>
<el-button type="text" @click="lookDetail(device.deviceCode)" <el-button type="text" @click.stop="lookDetail(device)"
>查看详情</el-button >查看详情</el-button
> >
<el-button <el-button type="text" @click.stop="handleEdit(device.deviceCode)"
type="text"
@click.prevent="handleEdit(device.deviceCode)"
>编辑</el-button >编辑</el-button
> >
<el-button type="text" @click="deleteDevice(device.deviceCode)" <el-button type="text" @click.stop="deleteDevice(device.deviceCode)"
>删除</el-button >删除</el-button
> >
</div> </div>
...@@ -101,12 +99,15 @@ const deviceList = reactive([ ...@@ -101,12 +99,15 @@ const deviceList = reactive([
:icon=" :icon="
!device.isExpend ? 'tabler:chevrons-up' : 'tabler:chevrons-down' !device.isExpend ? 'tabler:chevrons-up' : 'tabler:chevrons-down'
" "
@click="toggleExpand(index)" @click.stop="toggleExpand(index)"
/> />
</el-col> </el-col>
<childrenListTable <childrenListTable
v-if="device.isExpend" v-if="device.isExpend"
:childrenList="device.children" :childrenList="device.children"
:listData="listData"
:lookDetail="lookDetail"
@click.stop="lookDetail(device)"
/> />
</el-row> </el-row>
</div> </div>
......
<script setup lang="ts"> <script setup lang="ts">
import { ref, reactive } from "vue"; import router from "@/router";
import { useDetailHook } from "../utils/detailHook"; import { getOperationRecords } from "@/api/device";
const { operationRecords, radio } = useDetailHook();
const { lastBuildTime } = __APP_INFO__;
import { useRenderFlicker } from "@/components/ReFlicker"; import { useRenderFlicker } from "@/components/ReFlicker";
import { randomGradient } from "@pureadmin/utils"; import timeControl from "./timeControl.vue";
import { useRenderIcon } from "@/components/ReIcon/src/hooks"; import { getStartEndByType } from "@/utils/utils";
import Iphone from "~icons/ep/iphone";
const operationRecords = ref([]);
const radio = ref("今天");
const activities = [ // 获取操作记录列表数据
{ const getOperationRecordsList = async (time?: Array<string>) => {
content: "支持圆点发光", const params = {
timestamp: lastBuildTime, deviceCode: router.currentRoute.value.query?.deviceCode,
startTime: time ? time[0] : getStartEndByType()[0],
endTime: time ? time[1] : getStartEndByType()[1],
pageNum: 1,
pageSize: 100
};
const res = await getOperationRecords(params);
if (!res || !res.data) return;
operationRecords.value = handleOperationRecords(res.data.records) || [];
};
// 处理操作记录的数据结构
const handleOperationRecords = (data: any) => {
const newData = [];
data.forEach((item: any) => {
item.createTime = item.createTime.slice(0, 19).replace("T", " ");
newData.push({
...item,
timestamp: item.operateTime.slice(0, 19).replace("T", " "),
icon: markRaw(useRenderFlicker()) icon: markRaw(useRenderFlicker())
}, });
{ });
content: "支持方形发光", return newData;
timestamp: lastBuildTime, };
icon: markRaw(useRenderFlicker({ borderRadius: 0, background: "#67C23A" })) onMounted(() => {
}, getOperationRecordsList();
{ });
content: "支持渐变发光",
timestamp: lastBuildTime,
icon: markRaw(
useRenderFlicker({
background: randomGradient({
randomizeHue: true
})
})
)
},
{
content: "支持默认颜色",
timestamp: lastBuildTime
},
{
content: "支持自定义颜色",
timestamp: lastBuildTime,
color: "#F56C6C"
},
{
content: "支持自定义图标",
timestamp: "2023-10-01 12:00:00",
color: "transparent",
icon: useRenderIcon(Iphone, {
color: "#0bbd87"
})
}
];
</script> </script>
<template> <template>
<div> <div>
<!-- 单选(紧凑风格的按钮样式) --> <!-- 单选(紧凑风格的按钮样式) -->
<el-radio-group v-model="radio"> <time-control @changeBtn="getOperationRecordsList" />
<el-radio-button label="今天">今天</el-radio-button>
<el-radio-button label="3天">3天</el-radio-button>
<el-radio-button label="自定义">自定义</el-radio-button>
</el-radio-group>
<!-- 这一块时暂无数据 --> <!-- 这一块时暂无数据 -->
<!-- <el-empty description="暂无数据" /> --> <el-empty v-if="!operationRecords.length" description="暂无数据" />
<div class="mt-6 flex justify-center"> <div class="mt-6 flex justify-center max-h-100 overflow-y-auto">
<el-timeline> <el-timeline>
<el-timeline-item <el-timeline-item
v-for="(activity, index) in operationRecords" v-for="(activity, index) in operationRecords"
...@@ -83,21 +68,6 @@ const activities = [ ...@@ -83,21 +68,6 @@ const activities = [
</el-timeline-item> </el-timeline-item>
</el-timeline> </el-timeline>
</div> </div>
<!-- <el-timeline class="pl-40!">
<el-timeline-item
v-for="(activity, index) in activities"
:key="index"
:icon="activity.icon"
:color="activity.color"
:timestamp="activity.timestamp"
placement="bottom"
>
<div class="message">
vue-pure-admin 第{{ activities.length - index }}个版本发布啦
</div>
</el-timeline-item>
</el-timeline> -->
</div> </div>
</template> </template>
......
<script setup lang="ts">
import { ref, reactive } from "vue";
import { getStartEndByType } from "@/utils/utils";
const emit = defineEmits<{
(e: "changeBtn", value: any[]): void;
}>();
const radio = ref("今天");
const dataLogDate = ref([]);
const changeBtn = (val: string | any) => {
if (val === "今天") {
dataLogDate.value = getStartEndByType();
emit("changeBtn", dataLogDate.value);
} else if (val === "3天") {
dataLogDate.value = getStartEndByType("lastThreeDays");
emit("changeBtn", dataLogDate.value);
} else if (val === "自定义") {
dataLogDate.value = [];
} else {
emit("changeBtn", val);
}
};
</script>
<template>
<div>
<!-- 单选(紧凑风格的按钮样式) -->
<el-radio-group v-model="radio" @change="changeBtn">
<el-radio-button label="今天">今天</el-radio-button>
<el-radio-button label="3天">3天</el-radio-button>
<el-radio-button label="自定义">自定义</el-radio-button>
</el-radio-group>
<el-date-picker
v-if="radio === '自定义'"
v-model="dataLogDate"
type="datetimerange"
format="YYYY-MM-DD HH:mm:ss"
value-format="YYYY-MM-DD HH:mm:ss"
class="ml-5 mt-2"
start-placeholder="开始日期"
end-placeholder="结束日期"
@change="changeBtn"
/>
</div>
</template>
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
defineOptions({ defineOptions({
name: "DeviceDetail" name: "DeviceDetail"
}); });
import { reactive } from "vue";
import { useDetailHook } from "./utils/detailHook"; import { useDetailHook } from "./utils/detailHook";
import type { TabsPaneContext } from "element-plus"; import type { TabsPaneContext } from "element-plus";
import deviceAnalysis from "./components/deviceAnalysis.vue"; import deviceAnalysis from "./components/deviceAnalysis.vue";
...@@ -10,14 +9,15 @@ import dataChart from "./components/dataChart.vue"; ...@@ -10,14 +9,15 @@ import dataChart from "./components/dataChart.vue";
import dataLog from "./components/dataLog.vue"; import dataLog from "./components/dataLog.vue";
import operationRecord from "./components/operationRecord.vue"; import operationRecord from "./components/operationRecord.vue";
const { deviceInfo, labels, deviceList, Factor } = useDetailHook(); const {
deviceInfo,
latestDataLogList,
lateestDataLogColumns,
deviceList,
dataLogColumns
} = useDetailHook();
// { const activeName = ref("1");
// name: "出厂日期",
// value: "ZR-351"
// }
const activeName = ref("4");
const handleClick = (tab: TabsPaneContext, event: Event) => { const handleClick = (tab: TabsPaneContext, event: Event) => {
console.log(tab, event); console.log(tab, event);
...@@ -52,19 +52,21 @@ const handleClick = (tab: TabsPaneContext, event: Event) => { ...@@ -52,19 +52,21 @@ const handleClick = (tab: TabsPaneContext, event: Event) => {
class="felx mb-4! basis-1/4" class="felx mb-4! basis-1/4"
> >
<label>{{ i.name }}</label> <label>{{ i.name }}</label>
<span>{{ deviceInfo[i.prop] }}</span> <span class="ml-2">{{ deviceInfo[i.prop] }}</span>
</p> </p>
</div> </div>
<div <div
class="flex items-center justify-between bg-gray-100 px-12 py-8 mt-10" class="flex gap-y-5 items-center justify-between bg-gray-100 px-12 py-8 mt-10 flex-wrap h-25! overflow-y-scroll"
> >
<p <p
v-for="i in Factor" v-for="i in Object.keys(lateestDataLogColumns)"
:key="i.name" :key="i"
class="flex flex-col items-center" class="flex flex-col basis-1/3 text-center"
> >
<span class="text-gray-400 mb-2">{{ i.name }}</span> <span class="text-gray-400">{{ i }}</span>
<span class="font-semibold text-lg">{{ i.value }}</span> <span class="font-semibold text-lg">{{
latestDataLogList[lateestDataLogColumns[i]] || "--"
}}</span>
</p> </p>
</div> </div>
</div> </div>
...@@ -75,20 +77,26 @@ const handleClick = (tab: TabsPaneContext, event: Event) => { ...@@ -75,20 +77,26 @@ const handleClick = (tab: TabsPaneContext, event: Event) => {
class="demo-tabs" class="demo-tabs"
@tab-click="handleClick" @tab-click="handleClick"
> >
<el-tab-pane label="数据图表" name="1"><dataChart /></el-tab-pane> <el-tab-pane label="数据图表" name="1"
><dataChart v-if="activeName === '1'"
/></el-tab-pane>
<el-tab-pane label="设备分析" name="2" <el-tab-pane label="设备分析" name="2"
><deviceAnalysis ><deviceAnalysis v-if="activeName === '2'"
/></el-tab-pane>
<el-tab-pane label="数据日志" name="3"
><dataLog
v-if="activeName === '3'"
:dataLogColumns="dataLogColumns"
/></el-tab-pane> /></el-tab-pane>
<el-tab-pane label="数据日志" name="3"><dataLog /></el-tab-pane>
<el-tab-pane label="操作记录" name="4" <el-tab-pane label="操作记录" name="4"
><operationRecord ><operationRecord v-if="activeName === '4'"
/></el-tab-pane> /></el-tab-pane>
</el-tabs></div </el-tabs></div
></el-col> ></el-col>
<el-col :span="6" class="pl-10"> <el-col :span="6" class="pl-10">
<p class="text-sm mb-3!">最近更新时间:2025.04.23 15:00:00</p> <p class="text-sm mb-3!">最近更新时间:2025.04.23 15:00:00</p>
<img <img
src="https://shoplineimg.com/65a8de08211b1e008886980e/6659acc772c9d500104bb668/800x.png?" :src="deviceInfo.fileUrl"
alt="" alt=""
class="w-60 h-50! rounded-3xl mr-5 shadow shadow-red-300" class="w-60 h-50! rounded-3xl mr-5 shadow shadow-red-300"
/> />
...@@ -100,8 +108,8 @@ const handleClick = (tab: TabsPaneContext, event: Event) => { ...@@ -100,8 +108,8 @@ const handleClick = (tab: TabsPaneContext, event: Event) => {
><IconifyIconOnline ><IconifyIconOnline
class="cursor-pointer" class="cursor-pointer"
icon="cuida:caret-up-outline" icon="cuida:caret-up-outline"
@click="alarmSetting"
/> />
<!-- @click="alarmSetting" -->
</p> </p>
<div class="p-5"> <div class="p-5">
<p>臭氧≥40mg/m³发生报警</p> <p>臭氧≥40mg/m³发生报警</p>
...@@ -115,6 +123,7 @@ const handleClick = (tab: TabsPaneContext, event: Event) => { ...@@ -115,6 +123,7 @@ const handleClick = (tab: TabsPaneContext, event: Event) => {
<style lang="scss" scoped> <style lang="scss" scoped>
.device-list-detail2 { .device-list-detail2 {
min-height: calc(100vh - 170px);
cursor: pointer; cursor: pointer;
background: white; background: white;
} }
......
<script setup lang="ts">
import { ref } from "vue";
import { useDept } from "./utils/hook";
import { PureTableBar } from "@/components/RePureTableBar";
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
// 导入不同的图标组件
import Delete from "~icons/ep/delete";
import EditPen from "~icons/ep/edit-pen";
import Refresh from "~icons/ep/refresh";
import AddFill from "~icons/ri/add-circle-line";
import { Column } from "element-plus";
defineOptions({ name: "device" });
const formRef = ref();
const tableRef = ref();
const {
form,
loading,
columns,
dataList,
onSearch,
resetForm,
openDialog,
handleDelete,
handleSelectionChange
} = useDept();
function onFullscreen() {
tableRef.value.setAdaptive();
}
</script>
<template>
<div class="main">
<el-form
ref="formRef"
:inline="true"
:model="form"
class="search-form bg-bg_color w-full pl-8 pt-[12px] overflow-auto"
>
<el-form-item label="设备名称:" prop="name">
<el-input
v-model="form.name"
placeholder="请输入设备名称"
clearable
class="w-[180px]!"
/>
</el-form-item>
<el-form-item label="状态:" prop="status">
<el-select
v-model="form.status"
placeholder="请选择状态"
clearable
class="w-[180px]!"
>
<el-option label="启用" :value="1" />
<el-option label="停用" :value="0" />
</el-select>
</el-form-item>
<el-form-item>
<el-button
type="primary"
:icon="useRenderIcon('ri/search-line')"
:loading="loading"
@click="onSearch"
>
搜索框
</el-button>
<el-button :icon="useRenderIcon(Refresh)" @click="resetForm(formRef)">
重置
</el-button>
</el-form-item>
</el-form>
<PureTableBar
:title="'设备(仅演示,操作后不生效)'"
:columns="columns"
:tableRef="tableRef?.getTableRef()"
@refresh="onSearch"
@fullscreen="onFullscreen"
>
<template #buttons>
<el-button
type="primary"
:icon="useRenderIcon(AddFill)"
@click="openDialog()"
>
新增设备
</el-button>
</template>
<template v-slot="{ size, dynamicColumns }">
<pure-table
ref="tableRef"
adaptive
:adaptiveConfig="{ offsetBottom: 45 }"
align-whole="center"
row-key="id"
showOverflowTooltip
table-layout="auto"
default-expand-all
:loading="loading"
:size="size"
:data="dataList"
:columns="dynamicColumns"
:header-cell-style="{
background: 'var(--el-fill-color-light)',
color: 'var(--el-text-color-primary)'
}"
@selection-change="handleSelectionChange"
>
<template #operation="{ row }">
<el-button
class="reset-margin"
link
type="primary"
:size="size"
:icon="useRenderIcon(EditPen)"
@click="openDialog('修改', row)"
>
修改
</el-button>
<el-button
class="reset-margin"
link
type="primary"
:size="size"
:icon="useRenderIcon(AddFill)"
@click="openDialog('新增', { parentId: row.id } as any)"
>
新增
</el-button>
<el-popconfirm
:title="`是否确认删除设备名称为${row.name}的这条数据`"
@confirm="handleDelete(row)"
>
<template #reference>
<el-button
class="reset-margin"
link
type="primary"
:size="size"
:icon="useRenderIcon(Delete)"
>
删除
</el-button>
</template>
</el-popconfirm>
</template>
</pure-table>
</template>
</PureTableBar>
</div>
</template>
<style lang="scss" scoped>
/* 移除表格内滚动条底部的线 */
:deep(.el-table__inner-wrapper::before) {
height: 0;
}
/* 主内容区域样式 */
:deep(.main-content) {
margin: 24px 24px 0 !important;
}
/* 搜索按钮样式 */
:deep(.search-form) {
.el-form-item {
margin-bottom: 12px;
}
}
</style>
<script setup lang="ts"> <script setup lang="ts">
import listTable from "./components/listTable.vue"; import listTable from "./components/listTable.vue";
import { useListHook } from "./utils/listHook"; import router from "@/router";
const { addDevice, importDeviceTemplate } = useListHook(); // 点击新建按钮,跳转到新建页面
const addDevice = () => {
router.push({ path: "/device/add" });
};
// 导入设备模版
const importDeviceTemplate = async () => {
router.push({ path: "/import-templete", query: { type: "device" } });
};
</script> </script>
<template> <template>
...@@ -20,9 +28,10 @@ const { addDevice, importDeviceTemplate } = useListHook(); ...@@ -20,9 +28,10 @@ const { addDevice, importDeviceTemplate } = useListHook();
<style lang="scss" scoped> <style lang="scss" scoped>
.device-list { .device-list {
box-sizing: border-box;
width: 100%; width: 100%;
height: 100%; height: 100%;
padding: 10px 20px; padding: 10px 45px 10px 20px;
background: #fff; background: #fff;
} }
</style> </style>
...@@ -173,8 +173,10 @@ const { ...@@ -173,8 +173,10 @@ const {
<!-- :shortcuts="getPickerShortcuts()" --> <!-- :shortcuts="getPickerShortcuts()" -->
<el-date-picker <el-date-picker
v-model="formObj.factoryTime" v-model="formObj.factoryTime"
type="date" type="datetimerange"
format="YYYY/MM/DD" format="YYYY/MM/DD"
start-placeholder="开始日期"
end-placeholder="结束日期"
value-format="YYYY-MM-DD" value-format="YYYY-MM-DD"
placeholder="请选择设备出厂日期" placeholder="请选择设备出厂日期"
/> />
...@@ -184,6 +186,7 @@ const { ...@@ -184,6 +186,7 @@ const {
<el-form-item label="设备厂商" class="w-5/6" prop="username"> <el-form-item label="设备厂商" class="w-5/6" prop="username">
<el-select <el-select
v-model="formObj.manufacturerId" v-model="formObj.manufacturerId"
multiple
placeholder="请选择设备厂商" placeholder="请选择设备厂商"
> >
<el-option <el-option
...@@ -199,8 +202,10 @@ const { ...@@ -199,8 +202,10 @@ const {
<el-form-item label="年检提醒" class="w-5/6" prop="username"> <el-form-item label="年检提醒" class="w-5/6" prop="username">
<el-date-picker <el-date-picker
v-model="formObj.inspectTime" v-model="formObj.inspectTime"
type="date" type="datetimerange"
format="YYYY/MM/DD" format="YYYY/MM/DD"
start-placeholder="开始日期"
end-placeholder="结束日期"
value-format="YYYY-MM-DD" value-format="YYYY-MM-DD"
placeholder="请选择年检提醒" placeholder="请选择年检提醒"
/> />
......
import { reactive, ref, onMounted, toRaw } from "vue";
import { useRouter } from "vue-router"; import { useRouter } from "vue-router";
import { getDictItems } from "@/api/public";
import { ElMessage } from "element-plus"; import { ElMessage } from "element-plus";
import type { UploadProps, UploadRequestOptions } from "element-plus"; import type { UploadProps, UploadRequestOptions } from "element-plus";
import { formUpload, getFileURL } from "@/api/file"; import { formUpload, getFileURL } from "@/api/file";
import { import {
addDevice, addDevice,
updateDevice, updateDevice,
getDeviceByLevel, getDeviceByLevel,
getDeviceSite, getDeviceSite,
getDeviceInfo getDeviceInfo,
getDeviceTypeByType,
getDeviceModel
} from "@/api/device"; } from "@/api/device";
import { getManufacturerListNoPage } from "@/api/manufacturer"; import { getManufacturerListNoPage } from "@/api/manufacturer";
...@@ -35,9 +34,10 @@ export function useAddHook(formRef: Ref) { ...@@ -35,9 +34,10 @@ export function useAddHook(formRef: Ref) {
inspectTime: "", //年检提醒 inspectTime: "", //年检提醒
devicePurpose: [], //设备用途 devicePurpose: [], //设备用途
notes: "", //备注 notes: "", //备注
devicePicture: "", //设备图片 fileUrl: "", //设备图片
fileId: "" //文件id fileId: "" //文件id
}); });
const deviceImgUrl = ref(""); //设备层级
const deviceTypeOptions = ref({}); //设备类型数据列表 const deviceTypeOptions = ref({}); //设备类型数据列表
const deviceLevelOptions = ref([]); //所属设备数据列表 const deviceLevelOptions = ref([]); //所属设备数据列表
...@@ -45,10 +45,6 @@ export function useAddHook(formRef: Ref) { ...@@ -45,10 +45,6 @@ export function useAddHook(formRef: Ref) {
const deviceManufacturerOptions = ref([]); //设备厂商列表数据 const deviceManufacturerOptions = ref([]); //设备厂商列表数据
const deviceModelOptions = ref({}); //设备型号列表数据 const deviceModelOptions = ref({}); //设备型号列表数据
const validateForm = reactive({
fileList: [],
date: ""
});
const rules = { const rules = {
deviceLevel: [ deviceLevel: [
{ {
...@@ -141,6 +137,10 @@ export function useAddHook(formRef: Ref) { ...@@ -141,6 +137,10 @@ export function useAddHook(formRef: Ref) {
message: "备注长度必须在0到8个字符之间", message: "备注长度必须在0到8个字符之间",
trigger: "blur" trigger: "blur"
} }
],
// 文件上传校验规则
fileUrl: [
{ required: true, message: "设备图片不能为空", trigger: "change" }
] ]
}; };
...@@ -150,16 +150,16 @@ export function useAddHook(formRef: Ref) { ...@@ -150,16 +150,16 @@ export function useAddHook(formRef: Ref) {
// 获取设备类型的字典数据 // 获取设备类型的字典数据
const getDeviceType = async () => { const getDeviceType = async () => {
const res = await getDictItems("deviceType"); const res = await getDeviceTypeByType({ type: "deviceType" });
if (res.code === "0") { if (res.code === "0") {
deviceTypeOptions.value = res.data; deviceTypeOptions.value = res.data;
} else { } else {
ElMessage.error(`获取设备类型失败`); ElMessage.error(`获取设备类型失败`);
} }
}; };
// 获取设备类型的字典数据 // 根据设备类型获取型号列表数据
const getDeviceModelType = async () => { const changeDeviceType = async val => {
const res = await getDictItems("deviceModel"); const res = await getDeviceModel({ parentName: val });
if (res.code === "0") { if (res.code === "0") {
deviceModelOptions.value = res.data; deviceModelOptions.value = res.data;
} else { } else {
...@@ -199,14 +199,6 @@ export function useAddHook(formRef: Ref) { ...@@ -199,14 +199,6 @@ export function useAddHook(formRef: Ref) {
// 判断url上是否有id参数,如果有则调用getDeviceInfo接口获取设备信息,并赋值给formObj // 判断url上是否有id参数,如果有则调用getDeviceInfo接口获取设备信息,并赋值给formObj
if (router.currentRoute.value.query.deviceCode) { if (router.currentRoute.value.query.deviceCode) {
// const res = await getDeviceInfo({
// id: router.currentRoute.value.query.deviceCode
// });
// if (res.code === "0") {
// formObj = res.data;
// } else {
// ElMessage.error(`获取设备信息失败`);
// }
const deviceCode = router.currentRoute.value.query.deviceCode; const deviceCode = router.currentRoute.value.query.deviceCode;
getDeviceInfo({ deviceCode }).then(res => { getDeviceInfo({ deviceCode }).then(res => {
if (res.code === "0") { if (res.code === "0") {
...@@ -240,7 +232,8 @@ export function useAddHook(formRef: Ref) { ...@@ -240,7 +232,8 @@ export function useAddHook(formRef: Ref) {
const res = await formUpload(formData); const res = await formUpload(formData);
// 如果上传成功,则返回文件地址 // 如果上传成功,则返回文件地址
if (res.code === "0") { if (res.code === "0") {
formObj.value.devicePicture = res.data.filePath; formObj.value.fileUrl = res.data.filePath;
formObj.value.fileId = res.data.fileId;
getExcelUrl(res.data.fileId); getExcelUrl(res.data.fileId);
ElMessage.success("图片上传成功"); ElMessage.success("图片上传成功");
} else { } else {
...@@ -249,6 +242,13 @@ export function useAddHook(formRef: Ref) { ...@@ -249,6 +242,13 @@ export function useAddHook(formRef: Ref) {
} }
}; };
// 点击编辑图片按钮,触发handleEditAvatar函数,将formObj.value.fileUrl赋值给imageUrl.value,并打开上传图片的对话框
const handleEditImage = () => {
deviceImgUrl.value = deviceImgUrl.value || formObj.value.fileUrl;
formObj.value.fileUrl = formObj.value.fileUrl ? "" : deviceImgUrl.value;
};
// 定义一个函数,用于处理头像上传成功 // 定义一个函数,用于处理头像上传成功
// const handleAvatarSuccess: UploadProps["onSuccess"] = ( // const handleAvatarSuccess: UploadProps["onSuccess"] = (
// response, // response,
...@@ -305,11 +305,12 @@ export function useAddHook(formRef: Ref) { ...@@ -305,11 +305,12 @@ export function useAddHook(formRef: Ref) {
// 将表单数据转换为原始数据 // 将表单数据转换为原始数据
const params = JSON.parse(JSON.stringify(toRaw(formObj.value))); const params = JSON.parse(JSON.stringify(toRaw(formObj.value)));
params.devicePurpose = params.devicePurpose.toString(); params.devicePurpose = params.devicePurpose?.join(",");
// 判断url是否包含id,如果包含则调用更新设备接口,否则调用添加设备接口 // 判断url是否包含id,如果包含则调用更新设备接口,否则调用添加设备接口
if (router.currentRoute.value.query.deviceCode) { if (router.currentRoute.value.query.deviceCode) {
const deviceCode = router.currentRoute.value.query.deviceCode; params.devicePicture = formObj.value.fileId;
const res = await updateDevice({ ...params, deviceCode }); // const deviceCode = router.currentRoute.value.query.deviceCode;
const res = await updateDevice({ ...params });
if (res.code === "0") { if (res.code === "0") {
ElMessage.success("更新成功"); ElMessage.success("更新成功");
// 更新设备信息后,跳转到设备列表页面 // 更新设备信息后,跳转到设备列表页面
...@@ -339,7 +340,7 @@ export function useAddHook(formRef: Ref) { ...@@ -339,7 +340,7 @@ export function useAddHook(formRef: Ref) {
getDeviceList(); getDeviceList();
getDeviceSiteList(); getDeviceSiteList();
getManufacturerList(); getManufacturerList();
getDeviceModelType(); // getDeviceModelType();
// 获取设备类型 // 获取设备类型
// 获取设备型号 // 获取设备型号
// 获取设备厂商 // 获取设备厂商
...@@ -350,7 +351,6 @@ export function useAddHook(formRef: Ref) { ...@@ -350,7 +351,6 @@ export function useAddHook(formRef: Ref) {
handleReset, handleReset,
handleSubmit, handleSubmit,
rules, rules,
validateForm,
deviceTypeOptions, deviceTypeOptions,
getDeviceType, getDeviceType,
deviceLevelOptions, deviceLevelOptions,
...@@ -360,6 +360,8 @@ export function useAddHook(formRef: Ref) { ...@@ -360,6 +360,8 @@ export function useAddHook(formRef: Ref) {
uploadFile, uploadFile,
beforeAvatarUpload, beforeAvatarUpload,
getExcelUrl, getExcelUrl,
deviceModelOptions deviceModelOptions,
handleEditImage,
changeDeviceType
}; };
} }
import router from "@/router"; import router from "@/router";
import { ref, onMounted } from "vue"; import { ref, onMounted } from "vue";
import { useRenderFlicker } from "@/components/ReFlicker"; // import { useRenderFlicker } from "@/components/ReFlicker";
// import { randomGradient } from "@pureadmin/utils"; // import { randomGradient } from "@pureadmin/utils";
// import { useRenderIcon } from "@/components/ReIcon/src/hooks"; // import { useRenderIcon } from "@/components/ReIcon/src/hooks";
// import Iphone from "~icons/ep/iphone"; // import Iphone from "~icons/ep/iphone";
import { getDeviceInfo, getOperationRecords } from "@/api/device"; import { getDeviceInfo, getDataLogListLatest } from "@/api/device";
// 引入字典接口
import { getDictItems } from "@/api/public";
export function useDetailHook() { export function useDetailHook() {
const deviceInfo = ref({ const deviceInfo = ref({ deviceName: "", fileUrl: "" });
// deviceName: ""
});
const labels = reactive([ const labels = reactive([
{ {
label: "已连接", label: "已连接",
...@@ -47,17 +48,17 @@ export function useDetailHook() { ...@@ -47,17 +48,17 @@ export function useDetailHook() {
// }, // },
{ {
name: "设备联系人", name: "设备联系人",
prop: "deviceContact", prop: "deviceStaff",
value: "" value: ""
}, },
{ {
name: "所属站点", name: "所属站点",
prop: "deviceSite", prop: "deviceSideName",
value: "" value: ""
}, },
{ {
name: "设备部署位置", name: "设备部署位置",
prop: "deviceLocation", prop: "deviceAddress",
value: "" value: ""
}, },
{ {
...@@ -82,8 +83,9 @@ export function useDetailHook() { ...@@ -82,8 +83,9 @@ export function useDetailHook() {
} }
]); ]);
const operationRecords = ref([]); const latestDataLogList = ref({}); // 最新一条数据日志
const radio = ref("今天"); const lateestDataLogColumns = ref({}); // 最新一条数据日志的表头
const dataLogColumns = ref([]); // 数据日志列表的表头
// 根据deviceCode获取设备详情 // 根据deviceCode获取设备详情
const getDeviceInfoByCode = async () => { const getDeviceInfoByCode = async () => {
...@@ -96,50 +98,56 @@ export function useDetailHook() { ...@@ -96,50 +98,56 @@ export function useDetailHook() {
deviceCode: router.currentRoute.value.query?.deviceCode deviceCode: router.currentRoute.value.query?.deviceCode
}); });
deviceInfo.value = res.data || {}; deviceInfo.value = res.data || {};
console.log("deviceInfo.value", deviceInfo.value);
};
// 通过字典接口,获取数据日志的表头
const getDataLogColumns = async () => {
// 获取设备类型的字典数据
const res = await getDictItems("NOISE");
if (res.code === "0") {
if (!res || !res.data) return;
const data = Object.keys(res.data);
const columns = data.map(item => {
return { label: item, prop: res.data[item] };
});
dataLogColumns.value = columns;
lateestDataLogColumns.value = res.data;
} else {
ElMessage.error(`获取表头失败`);
}
}; };
// 获取操作记录列表数据 // 获取最新一条数据日志
const getOperationRecordsList = async () => { const getLatestDataLogList = async () => {
const params = { const res = await getDataLogListLatest({
deviceCode: router.currentRoute.value.query?.deviceCode, deviceCode: router.currentRoute.value.query?.deviceCode,
endTime: "2026-06-28 14:10:00", deviceType: router.currentRoute.value.query?.deviceType || "NOISE",
pageNum: 0, // deviceCode: "3110E30000658",
pageSize: 10, // deviceType: "AIR_3110",
endTime: "2016-06-28 14:10:00",
startTime: "2016-06-28 14:10:00" startTime: "2016-06-28 14:10:00"
}; });
const res = await getOperationRecords(params);
if (!res || !res.data) return; if (!res || !res.data) return;
operationRecords.value = handleOperationRecords(res.data.records) || []; latestDataLogList.value = res.data;
}; };
// 处理操作记录的数据结构
const handleOperationRecords = (data: any) => { const init = () => {
const newData = []; getLatestDataLogList();
data.forEach((item: any) => { getDeviceInfoByCode();
item.createTime = item.createTime.slice(0, 19).replace("T", " "); getDataLogColumns();
newData.push({
...item,
timestamp: item.operateTime.slice(0, 19).replace("T", " "),
icon: markRaw(useRenderFlicker())
});
});
return newData;
}; };
onMounted(() => { onMounted(() => {
// getList(); init();
getDeviceInfoByCode();
getOperationRecordsList();
// 获取设备类型
// 获取设备型号
// 获取设备厂商
// 获取设备状态
}); });
return { return {
deviceInfo, deviceInfo,
labels, labels,
deviceList, deviceList,
Factor, Factor,
operationRecords, dataLogColumns,
radio lateestDataLogColumns,
latestDataLogList
}; };
} }
import dayjs from "dayjs";
import editForm from "../components/form.vue";
import { handleTree } from "@/utils/tree";
import { message } from "@/utils/message";
import { getDeptList, addDept, deleteDept, updateDept } from "@/api/systems";
// import { getDeviceList, addDevice, deleteDevice, updateDevice } from "@/api/device";
import { usePublicHooks } from "@/hooks/hooks";
import { addDialog } from "@/components/ReDialog";
import { reactive, ref, onMounted, h } from "vue";
import type { FormItemProps } from "../types";
import { cloneDeep, isAllEmpty, deviceDetection } from "@pureadmin/utils";
export function useDept() {
const form = reactive({
name: "",
status: null
});
const formRef = ref();
const dataList = ref([]);
const loading = ref(true);
const { tagStyle } = usePublicHooks();
const columns: TableColumnList = [
{
label: "部门名称",
prop: "name",
width: 180,
align: "left"
},
{
label: "排序",
prop: "sort",
minWidth: 70
},
{
label: "状态",
prop: "status",
minWidth: 100,
align: "center",
cellRenderer: ({ row, props }) => (
<el-tag size={props.size} style={tagStyle.value(row.status)}>
{row.status === 1 ? "启用" : "停用"}
</el-tag>
)
},
{
label: "创建时间",
minWidth: 200,
prop: "createTime",
formatter: ({ createTime }) =>
dayjs(createTime).format("YYYY-MM-DD HH:mm:ss")
},
{
label: "操作",
fixed: "right",
width: 210,
slot: "operation"
}
];
function handleSelectionChange(val) {
console.log("handleSelectionChange", val);
}
function resetForm(formEl) {
if (!formEl) return;
formEl.resetFields();
onSearch();
}
async function onSearch() {
loading.value = true;
const params = {
pageNum: 1,
pageSize: 200
};
const { data } = await getDeptList(params);
let newData = (data as any).records;
if (!isAllEmpty(form.name)) {
newData = newData.filter(item => item.name.includes(form.name));
}
if (!isAllEmpty(form.status)) {
newData = newData.filter(item => item.status === form.status);
}
dataList.value = handleTree(newData);
setTimeout(() => {
loading.value = false;
}, 500);
}
function formatHigherDeptOptions(treeList) {
if (!treeList || !treeList.length) return;
const newTreeList = [];
for (let i = 0; i < treeList.length; i++) {
treeList[i].disabled = treeList[i].status === 0;
formatHigherDeptOptions(treeList[i].children);
newTreeList.push(treeList[i]);
}
return newTreeList;
}
function openDialog(title? = "新增", row?) {
addDialog({
title: `${title}部门`,
props: {
formInline: {
higherDeptOptions: formatHigherDeptOptions(cloneDeep(dataList.value)),
parentId: row?.parentId ?? 0,
name: row?.name ?? "",
principal: row?.principal ?? "",
phone: row?.phone ?? "",
email: row?.email ?? "",
sort: row?.sort ?? 0,
status: row?.status ?? 1,
remark: row?.remark ?? ""
}
},
width: "40%",
draggable: true,
fullscreen: deviceDetection(),
fullscreenIcon: true,
closeOnClickModal: false,
contentRenderer: () => h(editForm, { ref: formRef, formInline: null }),
beforeSure: (done, { options }) => {
const FormRef = formRef.value.getRef();
const curData = options.props.formInline as FormItemProps;
function chores() {
message(`您${title}了部门名称为${curData.name}的这条数据`, {
type: "success"
});
done();
onSearch();
}
FormRef.validate(valid => {
if (valid) {
if (title === "新增") {
addDept(curData).then(res => {
if ((res as any).code === "0") {
chores();
} else {
message((res as any).msg, { type: "error" });
}
});
} else {
if (!row?.id) {
message("id不能为空", { type: "error" });
return;
}
curData.id = row.id;
updateDept(curData).then(res => {
if ((res as any).code === "0") {
chores();
} else {
message((res as any).msg, { type: "error" });
}
});
}
}
});
}
});
}
function handleDelete(row) {
console.log("handleDelete", row.id);
deleteDept({ id: row.id }).then(res => {
if ((res as any).code === "0") {
message(`您删除了部门名称为${row.name}的这条数据`, { type: "success" });
onSearch();
}
});
}
onMounted(() => {
onSearch();
});
return {
form,
loading,
columns,
dataList,
onSearch,
resetForm,
openDialog,
handleDelete,
handleSelectionChange
};
}
...@@ -6,11 +6,24 @@ import { getDeviceTreeList, setBlackList } from "@/api/device"; ...@@ -6,11 +6,24 @@ import { getDeviceTreeList, setBlackList } from "@/api/device";
export function useListHook() { export function useListHook() {
const listData = ref([]); const listData = ref([]);
// 根据索引判断跳转到不同的设备详情页面 // 根据索引判断跳转到不同的设备详情页面
const lookDetail = deviceCode => { const lookDetail = deviceItem => {
// if (isChildren) {
// router.push({
// path: "/device/childrenList",
// query: {
// deviceCode: deviceItem.deviceCode,
// deviceType: deviceItem.deviceType
// }
// });
// } else {
router.push({ router.push({
path: "/device/detail", path: "/device/detail",
query: { deviceCode } query: {
deviceCode: deviceItem.deviceCode,
deviceType: deviceItem.deviceType
}
}); });
// }
}; };
// 点击编辑按钮,跳转到编辑页面 // 点击编辑按钮,跳转到编辑页面
...@@ -18,11 +31,6 @@ export function useListHook() { ...@@ -18,11 +31,6 @@ export function useListHook() {
router.push({ path: `/device/edit`, query: { deviceCode } }); router.push({ path: `/device/edit`, query: { deviceCode } });
}; };
// 点击新建按钮,跳转到新建页面
const addDevice = () => {
router.push({ path: "/device/add" });
};
// 获取设备列表 // 获取设备列表
const getList = async () => { const getList = async () => {
// 调用getDeviceList函数,获取设备列表 // 调用getDeviceList函数,获取设备列表
...@@ -55,19 +63,6 @@ export function useListHook() { ...@@ -55,19 +63,6 @@ export function useListHook() {
}); });
}; };
// 导入设备模版
const importDeviceTemplate = async () => {
// // 调用importDevice函数,导入设备模版
// const res = await importDevice();
// // 判断接口返回的code是否为200
// if (res.code === "0") {
// // 如果是200,则显示导入成功
// ElMessage.success("导入成功");
// getList();
// }
router.push({ path: "/import-templete", query: { type: "device" } });
};
// 是否展开二级设备 // 是否展开二级设备
const toggleExpand = index => { const toggleExpand = index => {
listData.value[index].isExpend = !listData.value[index].isExpend; listData.value[index].isExpend = !listData.value[index].isExpend;
...@@ -75,19 +70,13 @@ export function useListHook() { ...@@ -75,19 +70,13 @@ export function useListHook() {
onMounted(() => { onMounted(() => {
getList(); getList();
// 获取设备类型
// 获取设备型号
// 获取设备厂商
// 获取设备状态
}); });
return { return {
lookDetail, lookDetail,
getList, getList,
listData, listData,
toggleExpand, toggleExpand,
addDevice,
handleEdit, handleEdit,
deleteDevice, deleteDevice
importDeviceTemplate
}; };
} }
...@@ -16,7 +16,7 @@ export function useRole(tableRef: Ref) { ...@@ -16,7 +16,7 @@ export function useRole(tableRef: Ref) {
deviceType: "", //设备类型 deviceType: "", //设备类型
deviceCode: "", //设备编码 deviceCode: "", //设备编码
deviceModel: "", //设备型号 deviceModel: "", //设备型号
manufacturerId: "", //设备厂商 manufacturerId: [], //设备厂商
deviceStatus: "", //设备状态 deviceStatus: "", //设备状态
deviceAddress: "", //设备位置 deviceAddress: "", //设备位置
deviceSide: "", //所属站点 deviceSide: "", //所属站点
...@@ -28,7 +28,11 @@ export function useRole(tableRef: Ref) { ...@@ -28,7 +28,11 @@ export function useRole(tableRef: Ref) {
devicePurpose: "", //设备用途 devicePurpose: "", //设备用途
notes: "", //备注 notes: "", //备注
devicePicture: "", //设备图片 devicePicture: "", //设备图片
fileId: "" //文件id fileId: "", //文件id
factoryStartTime: "", //出厂日期开始时间
factoryEndTime: "", //出厂日期结束时间
inspectStartTime: "", //年检提醒开始时间
inspectEndTime: "" //年检提醒结束时间
}); });
const listData = ref([]); const listData = ref([]);
const loading = ref(false); const loading = ref(false);
...@@ -76,7 +80,7 @@ export function useRole(tableRef: Ref) { ...@@ -76,7 +80,7 @@ export function useRole(tableRef: Ref) {
}, },
{ {
label: "设备类型", label: "设备类型",
prop: "deviceType", prop: "deviceTypeName",
minWidth: 100 minWidth: 100
}, },
{ {
...@@ -86,7 +90,7 @@ export function useRole(tableRef: Ref) { ...@@ -86,7 +90,7 @@ export function useRole(tableRef: Ref) {
}, },
{ {
label: "所属站点", label: "所属站点",
prop: "deviceSide", prop: "deviceSideName",
minWidth: 100 minWidth: 100
}, },
{ {
...@@ -181,7 +185,7 @@ export function useRole(tableRef: Ref) { ...@@ -181,7 +185,7 @@ export function useRole(tableRef: Ref) {
// 获取所属设备列表 // 获取所属设备列表
const getDeviceLevelList = async () => { const getDeviceLevelList = async () => {
const res = await getDeviceByLevel({ deviceLevel: 2 }); const res = await getDeviceByLevel({ deviceLevel: 1 });
if (res.code === "0") { if (res.code === "0") {
deviceLevelOptions.value = res.data; deviceLevelOptions.value = res.data;
} else { } else {
...@@ -219,16 +223,33 @@ export function useRole(tableRef: Ref) { ...@@ -219,16 +223,33 @@ export function useRole(tableRef: Ref) {
delete params[key]; delete params[key];
} }
}); });
if (params.factoryTime) {
params.factoryStartTime = params.factoryTime[0];
params.factoryEndTime = params.factoryTime[1];
}
if (params.inspectTime) {
params.inspectStartTime = params.inspectTime[0];
params.inspectEndTime = params.inspectTime[1];
}
const res = await getDeviceList({ const res = await getDeviceList({
...params, ...params,
pageNum: pagination.currentPage, pageNum: pagination.currentPage,
pageSize: pagination.pageSize pageSize: pagination.pageSize
// factoryEndTime: params.factoryTime ? params.factoryTime[1] : "",
// factoryStartTime: params.factoryTime ? params.factoryTime[0] : "",
// inspectEndTime: params.inspectTime ? params.inspectTime[1] : "",
// inspectStartTime: params.inspectTime ? params.inspectTime[0] : ""
// factoryStartTime: params.factoryTime[0],
// inspectEndTime: params.inspectTime[1],
// inspectStartTime: params.inspectTime[0]
}); });
if (res.code === "0") { if (res.code === "0") {
// 给数据添加一个isExpend属性,默认值是false,点击展开按钮的时候,将isExpend属性设置为true,再次点击的时候,将isExpend属性设置为false // 给数据添加一个isExpend属性,默认值是false,点击展开按钮的时候,将isExpend属性设置为true,再次点击的时候,将isExpend属性设置为false
res.data.records.forEach((item: any) => { res.data.records.forEach((item: any) => {
item.isExpend = false; item.isExpend = false;
item.deviceLevel = item.deviceLevel == 1 ? "主设备" : "附属设备";
}); });
listData.value = res.data.records; listData.value = res.data.records;
loading.value = false; loading.value = false;
} else { } else {
...@@ -270,7 +291,7 @@ export function useRole(tableRef: Ref) { ...@@ -270,7 +291,7 @@ export function useRole(tableRef: Ref) {
getDeviceModelType(); getDeviceModelType();
getManufacturerList(); getManufacturerList();
getDeviceSiteList(); getDeviceSiteList();
getDeviceLevelList; getDeviceLevelList();
}); });
return { return {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论