Files
fishery-web/src/views/fishery/deviceSwitch/index.vue

650 lines
23 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="p-2">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="mb-[10px]">
<el-card shadow="hover">
<el-form ref="queryFormRef" :model="queryParams" :inline="true" label-width="100px">
<el-form-item label="设备信息" prop="params.deviceKeyword">
<el-input v-model="queryParams.params.deviceKeyword" placeholder="请输入设备名称或设备编号" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="开关名称" prop="switchName">
<el-input v-model="queryParams.switchName" placeholder="请输入开关名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
<!-- <el-form-item label="塘口id" prop="pondId">
<el-input v-model="queryParams.pondId" placeholder="请输入塘口id" clearable @keyup.enter="handleQuery" />
</el-form-item> -->
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
</el-card>
</div>
</transition>
<el-card shadow="never">
<template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['fishery:deviceSwitch:add']">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['fishery:deviceSwitch:edit']">修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['fishery:deviceSwitch:remove']">删除</el-button>
</el-col>
<!-- <el-col :span="1.5">
<el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['fishery:deviceSwitch:export']">导出</el-button>
</el-col> -->
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
</template>
<el-table v-loading="loading" border :data="deviceSwitchList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="塘口名称" align="center" prop="pondName" />
<el-table-column label="设备名称" align="center" prop="deviceName" />
<el-table-column label="设备编号" align="center" prop="serialNum" width="150"/>
<el-table-column label="开关序号" align="center" prop="index" width="80"/>
<el-table-column label="开关名称" align="center" prop="switchName" width="150"/>
<el-table-column label="开关状态" align="center" prop="isOpen" width="80">
<template #default="scope">
<dict-tag :options="open_close" :value="scope.row.isOpen"/>
</template>
</el-table-column>
<el-table-column label="当前测定电流" align="center" prop="detectElectricValue" />
<el-table-column label="当前测定电压" align="center" prop="detectVoltageValue" />
<el-table-column label="接线方式" align="center" prop="connectVoltageType" width="100">
<template #default="scope">
<dict-tag :options="connect_voltage_type" :value="scope.row.connectVoltageType"/>
</template>
</el-table-column>
<el-table-column label="额定电流设置" align="center" prop="rateElectricValue" />
<el-table-column label="电流告警开关" align="center" prop="electricWarnOpen">
<template #default="scope">
<dict-tag :options="open_close" :value="scope.row.electricWarnOpen"/>
</template>
</el-table-column>
<el-table-column label="联动状态" align="center" prop="isLinkedCtrl" width="80">
<template #default="scope">
<dict-tag :options="is_linked_ctrl" :value="scope.row.isLinkedCtrl"/>
</template>
</el-table-column>
<el-table-column label="上次操作开关时间" align="center" prop="lastTurnTime" width="160"> </el-table-column>
<el-table-column label="定时控制数量" align="center" prop="timingCtrlCount" width="110"/>
<el-table-column label="操作" align="center" fixed="right" width="160" class-name="small-padding fixed-width">
<template #default="scope">
<el-tooltip content="定时控制" placement="top">
<el-button link type="primary" icon="Timer" @click="handleViewTimingCtrl(scope.row)" v-hasPermi="['fishery:timingCtrl:list']"></el-button>
</el-tooltip>
<el-tooltip content="修改" placement="top">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['fishery:deviceSwitch:edit']"></el-button>
</el-tooltip>
<el-tooltip content="删除" placement="top">
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['fishery:deviceSwitch:remove']"></el-button>
</el-tooltip>
</template>
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
</el-card>
<!-- 添加或修改测控一体机开关对话框 -->
<el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
<el-form ref="deviceSwitchFormRef" :model="form" :rules="rules" label-width="120px">
<el-form-item label="设备" prop="deviceId">
<el-input
:value="selectedDevice ? `${selectedDevice.deviceName} (${selectedDevice.serialNum})` : ''"
placeholder="请选择设备"
readonly
@click="openDeviceSelect"
style="cursor: pointer;"
>
<template #append>
<el-button icon="Search" @click="openDeviceSelect">选择</el-button>
</template>
</el-input>
</el-form-item>
<el-form-item label="开关序号" prop="index">
<el-input v-model="form.index" placeholder="请输入开关序号" />
</el-form-item>
<el-form-item label="开关名称" prop="switchName">
<el-input v-model="form.switchName" placeholder="请输入名称" />
</el-form-item>
<el-form-item label="接线方式" prop="connectVoltageType">
<el-select v-model="form.connectVoltageType" placeholder="请选择接线方式" clearable style="width: 100%">
<el-option
v-for="dict in connect_voltage_type"
:key="dict.value"
:label="dict.label"
:value="parseInt(dict.value)"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="塘口" prop="pondId">
<el-input
:value="selectedPondName"
placeholder="请选择设备(塘口将自动关联)"
readonly
disabled
/>
</el-form-item>
<el-form-item label="额定电流设置" prop="rateElectricValue">
<el-input v-model="form.rateElectricValue" placeholder="请输入额定电流设置" />
</el-form-item>
<el-form-item label="电流告警开关" prop="electricWarnOpen">
<el-select v-model="form.electricWarnOpen" placeholder="请选择电流告警开关" clearable style="width: 100%">
<el-option
v-for="dict in open_close"
:key="dict.value"
:label="dict.label"
:value="parseInt(dict.value)"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入备注" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button :loading="buttonLoading" type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog>
<!-- 设备选择对话框 -->
<el-dialog title="选择设备" v-model="deviceSelectVisible" width="1200px" append-to-body>
<!-- 搜索条件 -->
<el-form :model="deviceQueryParams" :inline="true" class="mb-4">
<el-form-item label="用户信息">
<el-input
v-model="deviceQueryParams.params.userKeyword"
placeholder="请输入用户名或手机号"
clearable
style="width: 200px"
@keyup.enter="handleDeviceQuery"
/>
</el-form-item>
<el-form-item label="设备编号">
<el-input
v-model="deviceQueryParams.serialNum"
placeholder="请输入设备编号"
clearable
style="width: 180px"
@keyup.enter="handleDeviceQuery"
/>
</el-form-item>
<el-form-item label="设备名称">
<el-input
v-model="deviceQueryParams.deviceName"
placeholder="请输入设备名称"
clearable
style="width: 180px"
@keyup.enter="handleDeviceQuery"
/>
</el-form-item>
<el-form-item label="设备类型">
<el-select
v-model="deviceQueryParams.deviceType"
placeholder="请选择设备类型"
disabled
style="width: 150px"
>
<el-option
v-for="dict in aqu_device_type"
:key="dict.value"
:label="dict.label"
:value="parseInt(dict.value)"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleDeviceQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetDeviceQuery">重置</el-button>
</el-form-item>
</el-form>
<!-- 设备表格 -->
<el-table
:data="deviceList"
highlight-current-row
height="400px"
border
>
<el-table-column label="用户名" align="center" prop="userName" />
<el-table-column label="手机号" align="center" prop="mobilePhone" />
<el-table-column label="设备编号" align="center" prop="serialNum" />
<el-table-column label="设备名称" align="center" prop="deviceName" />
<el-table-column label="塘口名称" align="center" prop="pondName" />
<el-table-column label="设备类型" align="center" prop="deviceType">
<template #default="scope">
<dict-tag :options="aqu_device_type" :value="scope.row.deviceType"/>
</template>
</el-table-column>
<el-table-column label="绑定时间" align="center" prop="bindTime" width="120">
<template #default="scope">
<span>{{ parseTime(scope.row.bindTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="服务到期时间" align="center" prop="deadTime" width="120">
<template #default="scope">
<span>{{ parseTime(scope.row.deadTime, '{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="100">
<template #default="scope">
<el-button
type="primary"
size="small"
@click="handleDeviceSelect(scope.row)"
>
选择
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<pagination
v-show="deviceTotal > 0"
:total="deviceTotal"
v-model:page="deviceQueryParams.pageNum"
v-model:limit="deviceQueryParams.pageSize"
@pagination="handleDevicePaginationChange"
class="mt-4"
/>
<template #footer>
<div class="dialog-footer">
<el-button @click="cancelDeviceSelect"> </el-button>
</div>
</template>
</el-dialog>
<!-- 定时控制对话框 -->
<el-dialog
:title="`定时控制 - ${currentSwitch?.switchName || ''} (序号:${currentSwitch?.index || ''})`"
v-model="timingCtrlDialogVisible"
width="800px"
append-to-body
@close="closeTimingCtrlDialog"
>
<el-table
v-loading="timingCtrlLoading"
:data="timingCtrlList"
border
height="400px"
>
<el-table-column label="开启时间" align="center" prop="openTime" />
<el-table-column label="关闭时间" align="center" prop="closeTime" />
<el-table-column label="循环类型" align="center" prop="loopType" >
<template #default="scope">
<dict-tag :options="loop_type" :value="scope.row.loopType"/>
</template>
</el-table-column>
<el-table-column label="是否启用" align="center" prop="isOpen" >
<template #default="scope">
<dict-tag :options="open_close" :value="scope.row.isOpen"/>
</template>
</el-table-column>
</el-table>
<template #footer>
<div class="dialog-footer">
<el-button @click="closeTimingCtrlDialog"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup name="DeviceSwitch" lang="ts">
import { listDeviceSwitch, getDeviceSwitch, delDeviceSwitch, addDeviceSwitch, updateDeviceSwitch } from '@/api/fishery/deviceSwitch';
import { DeviceSwitchVO, DeviceSwitchQuery, DeviceSwitchForm } from '@/api/fishery/deviceSwitch/types';
import { listDevice } from '@/api/fishery/device';
import { DeviceVO } from '@/api/fishery/device/types';
import { listTimingCtrl } from '@/api/fishery/timingCtrl';
import { TimingCtrlVO } from '@/api/fishery/timingCtrl/types';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { aqu_device_type, open_close, connect_voltage_type, is_linked_ctrl, loop_type } = toRefs<any>(proxy?.useDict('aqu_device_type', 'open_close', 'connect_voltage_type', 'is_linked_ctrl', 'loop_type'));
const deviceSwitchList = ref<DeviceSwitchVO[]>([]);
const buttonLoading = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
// 设备选择相关
const deviceList = ref<DeviceVO[]>([]);
const selectedDevice = ref<DeviceVO | null>(null);
const selectedPondName = ref<string>(''); // 保存选中设备的塘口名称
const deviceSelectVisible = ref(false);
const deviceQueryParams = reactive<{
pageNum: number;
pageSize: number;
serialNum?: string;
deviceName?: string;
deviceType?: number;
params: {
userKeyword?: string;
deviceKeyword?: string;
};
}>({
pageNum: 1,
pageSize: 10,
serialNum: undefined,
deviceName: undefined,
deviceType: 2, // 默认查询测控一体机假设值为2
params: {
userKeyword: undefined,
deviceKeyword: undefined
}
});
const deviceTotal = ref(0);
// 定时控制对话框
const timingCtrlDialogVisible = ref(false);
const timingCtrlList = ref<TimingCtrlVO[]>([]);
const timingCtrlLoading = ref(false);
const currentSwitch = ref<DeviceSwitchVO | null>(null);
const queryFormRef = ref<ElFormInstance>();
const deviceSwitchFormRef = ref<ElFormInstance>();
const dialog = reactive<DialogOption>({
visible: false,
title: ''
});
const initFormData: DeviceSwitchForm = {
id: undefined,
deviceId: undefined,
index: undefined,
switchName: undefined,
detectElectricValue: undefined,
detectVoltageValue: undefined,
connectVoltageType: undefined,
pondId: undefined,
rateElectricValue: undefined,
isOpen: undefined,
linkedCtrlId: undefined,
electricWarnOpen: undefined,
lastTurnTime: undefined,
remark: undefined
}
const data = reactive<PageData<DeviceSwitchForm, DeviceSwitchQuery>>({
form: {...initFormData},
queryParams: {
pageNum: 1,
pageSize: 10,
deviceId: undefined,
index: undefined,
switchName: undefined,
connectVoltageType: undefined,
pondId: undefined,
isOpen: undefined,
linkedCtrlId: undefined,
lastTurnTime: undefined,
params: {
deviceKeyword: undefined
}
},
rules: {
deviceId: [
{ required: true, message: "设备名称不能为空", trigger: "blur" }
],
index: [
{ required: true, message: "开关序号不能为空", trigger: "blur" }
],
switchName: [
{ required: true, message: "名称不能为空", trigger: "blur" }
],
connectVoltageType: [
{ required: true, message: "接线方式不能为空", trigger: "change" }
],
rateElectricValue: [
{ required: true, message: "额定电流设置不能为空", trigger: "blur" }
],
electricWarnOpen: [
{ required: true, message: "电流告警开关不能为空", trigger: "blur" }
]
}
});
const { queryParams, form, rules } = toRefs(data);
/** 查询测控一体机开关列表 */
const getList = async () => {
loading.value = true;
const res = await listDeviceSwitch(queryParams.value);
deviceSwitchList.value = res.rows;
total.value = res.total;
loading.value = false;
}
/** 取消按钮 */
const cancel = () => {
reset();
dialog.visible = false;
}
/** 表单重置 */
const reset = () => {
form.value = {...initFormData};
selectedDevice.value = null; // 清空设备选择
selectedPondName.value = ''; // 清空塘口名称
deviceSwitchFormRef.value?.resetFields();
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.value.pageNum = 1;
getList();
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value?.resetFields();
handleQuery();
}
/** 多选框选中数据 */
const handleSelectionChange = (selection: DeviceSwitchVO[]) => {
ids.value = selection.map(item => item.id);
single.value = selection.length != 1;
multiple.value = !selection.length;
}
/** 新增按钮操作 */
const handleAdd = () => {
reset();
selectedDevice.value = null; // 清空设备选择
selectedPondName.value = ''; // 清空塘口名称
dialog.visible = true;
dialog.title = "添加测控一体机开关";
}
/** 修改按钮操作 */
const handleUpdate = async (row?: DeviceSwitchVO) => {
reset();
const _id = row?.id || ids.value[0]
const res = await getDeviceSwitch(_id);
Object.assign(form.value, res.data);
// 回显设备信息
if (form.value.deviceId) {
try {
// 加载设备列表以获取设备信息
const deviceRes = await listDevice({
pageNum: 1,
pageSize: 1000,
deviceType: 2 // 测控一体机类型
});
const deviceListData = deviceRes.rows || deviceRes.data || [];
const device = deviceListData.find(d => d.id.toString() === form.value.deviceId.toString());
if (device) {
selectedDevice.value = device;
// 回显塘口名称
selectedPondName.value = (device as any).pondName || '';
} else {
console.warn('未找到设备ID:', form.value.deviceId);
selectedDevice.value = null;
selectedPondName.value = '';
}
} catch (error) {
console.error('加载设备信息失败:', error);
selectedDevice.value = null;
selectedPondName.value = '';
}
} else {
selectedDevice.value = null;
selectedPondName.value = '';
}
dialog.visible = true;
dialog.title = "修改测控一体机开关";
}
/** 提交按钮 */
const submitForm = () => {
deviceSwitchFormRef.value?.validate(async (valid: boolean) => {
if (valid) {
buttonLoading.value = true;
if (form.value.id) {
await updateDeviceSwitch(form.value).finally(() => buttonLoading.value = false);
} else {
await addDeviceSwitch(form.value).finally(() => buttonLoading.value = false);
}
proxy?.$modal.msgSuccess("操作成功");
dialog.visible = false;
await getList();
}
});
}
/** 删除按钮操作 */
const handleDelete = async (row?: DeviceSwitchVO) => {
const _ids = row?.id || ids.value;
await proxy?.$modal.confirm('是否确认删除选中的数据项?').finally(() => loading.value = false);
await delDeviceSwitch(_ids);
proxy?.$modal.msgSuccess("删除成功");
await getList();
}
/** 导出按钮操作 */
const handleExport = () => {
proxy?.download('fishery/deviceSwitch/export', {
...queryParams.value
}, `deviceSwitch_${new Date().getTime()}.xlsx`)
}
/** 获取设备列表 */
const getDeviceList = async () => {
const res = await listDevice(deviceQueryParams);
deviceList.value = res.rows || res.data || [];
deviceTotal.value = res.total || 0;
};
/** 打开设备选择对话框 */
const openDeviceSelect = () => {
// 重置搜索条件
deviceQueryParams.pageNum = 1;
deviceQueryParams.serialNum = undefined;
deviceQueryParams.deviceName = undefined;
deviceQueryParams.deviceType = 2; // 测控一体机类型
deviceQueryParams.params.userKeyword = undefined;
deviceQueryParams.params.deviceKeyword = undefined;
getDeviceList();
deviceSelectVisible.value = true;
};
/** 搜索设备 */
const handleDeviceQuery = () => {
deviceQueryParams.pageNum = 1;
getDeviceList();
};
/** 重置设备搜索 */
const resetDeviceQuery = () => {
deviceQueryParams.pageNum = 1;
deviceQueryParams.serialNum = undefined;
deviceQueryParams.deviceName = undefined;
deviceQueryParams.deviceType = 2; // 测控一体机类型
deviceQueryParams.params.userKeyword = undefined;
deviceQueryParams.params.deviceKeyword = undefined;
getDeviceList();
};
/** 设备分页改变 */
const handleDevicePaginationChange = () => {
getDeviceList();
};
/** 选择设备 */
const handleDeviceSelect = (device: DeviceVO) => {
selectedDevice.value = device;
form.value.deviceId = device.id;
// 同时赋值塘口ID和塘口名称
if (device.pondId) {
form.value.pondId = device.pondId;
// 使用类型断言获取塘口名称(后端返回的数据中包含此字段)
selectedPondName.value = (device as any).pondName || ''; // 显示塘口名称
} else {
form.value.pondId = undefined;
selectedPondName.value = '';
}
deviceSelectVisible.value = false;
};
/** 取消选择设备 */
const cancelDeviceSelect = () => {
deviceSelectVisible.value = false;
};
/** 查看定时控制 */
const handleViewTimingCtrl = async (row: DeviceSwitchVO) => {
currentSwitch.value = row;
await getTimingCtrlList(row.id);
timingCtrlDialogVisible.value = true;
};
/** 获取定时控制列表 */
const getTimingCtrlList = async (switchId: string | number) => {
timingCtrlLoading.value = true;
try {
const res = await listTimingCtrl({
switchId: switchId,
pageNum: 1,
pageSize: 1000 // 获取所有数据
});
timingCtrlList.value = res.rows || res.data || [];
} catch (error) {
console.error('加载定时控制失败:', error);
proxy?.$modal.msgError('加载定时控制失败');
} finally {
timingCtrlLoading.value = false;
}
};
/** 关闭定时控制对话框 */
const closeTimingCtrlDialog = () => {
timingCtrlDialogVisible.value = false;
currentSwitch.value = null;
timingCtrlList.value = [];
};
onMounted(() => {
getList();
});
</script>