完善设备管理+PLC设备管理
This commit is contained in:
47
rc_autoplc_front/src/api/tb/devparam.ts
Normal file
47
rc_autoplc_front/src/api/tb/devparam.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function devparamadd(data: any) {
|
||||
return request({
|
||||
url: '/devParam/add',
|
||||
method: 'post',
|
||||
data,
|
||||
})
|
||||
}
|
||||
|
||||
export function devparamdel(id: string | number) {
|
||||
return request({
|
||||
url: `/devParam/del/${id}`,
|
||||
method: 'delete',
|
||||
})
|
||||
}
|
||||
|
||||
export function devparamupd(data: any) {
|
||||
return request({
|
||||
url: '/devParam/update',
|
||||
method: 'put',
|
||||
data,
|
||||
})
|
||||
}
|
||||
|
||||
export function devparamlist(data: any) {
|
||||
return request({
|
||||
url: '/devParam/listPage',
|
||||
method: 'get',
|
||||
params: data,
|
||||
})
|
||||
}
|
||||
|
||||
export function devparambyid(id: string | number) {
|
||||
return request({
|
||||
url: `/devParam/getById/${id}`,
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
|
||||
export function devparamselect(data: any) {
|
||||
return request({
|
||||
url: '/devParam/list',
|
||||
method: 'get',
|
||||
params: data,
|
||||
})
|
||||
}
|
||||
BIN
rc_autoplc_front/src/assets/image/right.png
Normal file
BIN
rc_autoplc_front/src/assets/image/right.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.1 KiB |
@@ -47,6 +47,11 @@ const router = createRouter({
|
||||
name: 'devinfo',
|
||||
component: () => import('../views/devinfo/index.vue'),
|
||||
},
|
||||
{
|
||||
path: '/plc-devinfo',
|
||||
name: 'plc-devinfo',
|
||||
component: () => import('../views/devinfo/plc.vue'),
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
@@ -74,6 +74,10 @@
|
||||
<el-icon><Monitor /></el-icon>
|
||||
<span>设备管理</span>
|
||||
</el-menu-item>
|
||||
<el-menu-item index="/plc-devinfo">
|
||||
<el-icon><Connection /></el-icon>
|
||||
<span>PLC设备管理</span>
|
||||
</el-menu-item>
|
||||
</el-sub-menu>
|
||||
</el-menu>
|
||||
</el-aside>
|
||||
@@ -90,7 +94,7 @@
|
||||
import { ref, computed } from 'vue'
|
||||
import { useRouter, useRoute } from 'vue-router'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { User, Setting, Avatar, OfficeBuilding, Briefcase, Document, CaretBottom, UserFilled, Grid, Monitor } from '@element-plus/icons-vue'
|
||||
import { User, Setting, Avatar, OfficeBuilding, Briefcase, Document, CaretBottom, UserFilled, Grid, Monitor, Connection, Plus } from '@element-plus/icons-vue'
|
||||
import { useAuthStore } from '@/stores/auth'
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
@@ -73,26 +73,6 @@
|
||||
{{ row.devModel || '暂无' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="ipAddr" label="IP地址" min-width="120" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
{{ row.ipAddr || '暂无' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="port" label="端口" width="80">
|
||||
<template #default="{ row }">
|
||||
{{ row.port !== null && row.port !== undefined ? row.port : '暂无' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="protocolType" label="协议" min-width="100" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
{{ row.protocolType || '暂无' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="company" label="公司名" min-width="120" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
{{ row.company || '暂无' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="status" label="状态" width="100" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="getStatusType(row.status)" size="small">
|
||||
@@ -115,8 +95,17 @@
|
||||
{{ row.remark || '暂无' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="150" fixed="right">
|
||||
<el-table-column label="操作" width="220" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button
|
||||
type="success"
|
||||
size="small"
|
||||
link
|
||||
@click="handleConfigParams(row)"
|
||||
>
|
||||
<el-icon><Setting /></el-icon>
|
||||
配置参数
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
size="small"
|
||||
@@ -183,36 +172,6 @@
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="IP地址" prop="ipAddr">
|
||||
<el-input
|
||||
v-model="formData.ipAddr"
|
||||
placeholder="请输入IP地址"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="端口" prop="port">
|
||||
<el-input-number
|
||||
v-model="formData.port"
|
||||
placeholder="请输入端口"
|
||||
:min="0"
|
||||
:max="65535"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="协议" prop="protocolType">
|
||||
<el-input
|
||||
v-model="formData.protocolType"
|
||||
placeholder="请输入协议类型"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="公司名" prop="company">
|
||||
<el-input
|
||||
v-model="formData.company"
|
||||
placeholder="请输入公司名"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="描述" prop="devDesc">
|
||||
<el-input
|
||||
v-model="formData.devDesc"
|
||||
@@ -241,13 +200,160 @@
|
||||
</div>
|
||||
</template>
|
||||
</el-drawer>
|
||||
|
||||
<!-- 参数配置对话框 -->
|
||||
<el-dialog
|
||||
v-model="paramDialogVisible"
|
||||
:title="`设备参数配置 - ${currentDevice?.devName || ''}`"
|
||||
width="1200px"
|
||||
:before-close="handleParamDialogClose"
|
||||
>
|
||||
<div class="param-config-container">
|
||||
<!-- 工具栏 -->
|
||||
<div class="param-toolbar">
|
||||
<el-button type="primary" @click="handleAddParamRow">
|
||||
<el-icon><Plus /></el-icon>
|
||||
添加一行
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<!-- 参数列表 -->
|
||||
<el-table
|
||||
v-loading="paramLoading"
|
||||
:data="paramList"
|
||||
border
|
||||
stripe
|
||||
style="width: 100%"
|
||||
:empty-text="paramEmptyText"
|
||||
>
|
||||
<el-table-column type="index" label="序号" width="60" :index="getParamIndex" />
|
||||
|
||||
<!-- 参数名称 -->
|
||||
<el-table-column label="参数名称" min-width="120">
|
||||
<template #default="{ row }">
|
||||
<el-input
|
||||
v-if="row.isEditing"
|
||||
v-model="row.paramName"
|
||||
placeholder="请输入参数名称"
|
||||
size="small"
|
||||
/>
|
||||
<span v-else>{{ row.paramName || '暂无' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<!-- 参数类型 -->
|
||||
<el-table-column label="参数类型" min-width="120">
|
||||
<template #default="{ row }">
|
||||
<el-select
|
||||
v-if="row.isEditing"
|
||||
v-model="row.paramType"
|
||||
placeholder="请选择参数类型"
|
||||
size="small"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="type in paramTypeOptions"
|
||||
:key="type.value"
|
||||
:label="type.label"
|
||||
:value="type.value"
|
||||
/>
|
||||
</el-select>
|
||||
<span v-else>{{ row.paramType || '暂无' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<!-- 参数单位 -->
|
||||
<el-table-column label="参数单位" min-width="100">
|
||||
<template #default="{ row }">
|
||||
<el-input
|
||||
v-if="row.isEditing"
|
||||
v-model="row.paramUnit"
|
||||
placeholder="请输入参数单位"
|
||||
size="small"
|
||||
/>
|
||||
<span v-else>{{ row.paramUnit || '暂无' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<!-- 表单控件 -->
|
||||
<el-table-column label="表单控件" min-width="120">
|
||||
<template #default="{ row }">
|
||||
<el-select
|
||||
v-if="row.isEditing"
|
||||
v-model="row.formType"
|
||||
placeholder="请选择表单控件"
|
||||
size="small"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="form in formTypeOptions"
|
||||
:key="form.value"
|
||||
:label="form.label"
|
||||
:value="form.value"
|
||||
/>
|
||||
</el-select>
|
||||
<span v-else>{{ row.formType || '暂无' }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<!-- 操作列 -->
|
||||
<el-table-column label="操作" width="180" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button
|
||||
v-if="row.isEditing"
|
||||
type="primary"
|
||||
size="small"
|
||||
link
|
||||
@click="handleSaveParam(row)"
|
||||
>
|
||||
<el-icon><Check /></el-icon>
|
||||
保存
|
||||
</el-button>
|
||||
<el-button
|
||||
v-else
|
||||
type="primary"
|
||||
size="small"
|
||||
link
|
||||
@click="handleEditParam(row)"
|
||||
>
|
||||
<el-icon><Edit /></el-icon>
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button
|
||||
type="danger"
|
||||
size="small"
|
||||
link
|
||||
@click="handleDeleteParam(row)"
|
||||
>
|
||||
<el-icon><Delete /></el-icon>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 分页 -->
|
||||
<div class="param-pagination">
|
||||
<el-pagination
|
||||
v-model:current-page="paramPagination.pageNum"
|
||||
v-model:page-size="paramPagination.pageSize"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
:total="paramTotal"
|
||||
background
|
||||
@current-change="handleParamCurrentChange"
|
||||
@size-change="handleParamSizeChange"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { Plus, Edit, Delete } from '@element-plus/icons-vue'
|
||||
import { Plus, Edit, Delete, Setting, Check } from '@element-plus/icons-vue'
|
||||
import {
|
||||
devInfoadd,
|
||||
devInfodel,
|
||||
@@ -256,6 +362,13 @@ import {
|
||||
devInfobyid,
|
||||
} from '@/api/tb/devinfo'
|
||||
import { islandInfobyid, islandInfolist } from '@/api/tb/islandinfo'
|
||||
import {
|
||||
devparamadd,
|
||||
devparamdel,
|
||||
devparamupd,
|
||||
devparamlist,
|
||||
devparambyid,
|
||||
} from '@/api/tb/devparam'
|
||||
|
||||
// 加载状态
|
||||
const loading = ref(false)
|
||||
@@ -293,10 +406,6 @@ const formData = reactive({
|
||||
id: undefined,
|
||||
devName: '',
|
||||
devModel: '',
|
||||
ipAddr: '',
|
||||
port: undefined,
|
||||
protocolType: '',
|
||||
company: '',
|
||||
devDesc: '',
|
||||
remark: '',
|
||||
status: 0, // 状态自动设置为0
|
||||
@@ -396,6 +505,8 @@ const getDeviceList = async () => {
|
||||
if (queryForm.islandId !== undefined && queryForm.islandId !== null) {
|
||||
params.islandId = queryForm.islandId
|
||||
}
|
||||
// 排除 devModel 为 PLC 的设备
|
||||
params.devModelNot = 'PLC'
|
||||
|
||||
const res: any = await devInfolist(params)
|
||||
|
||||
@@ -415,10 +526,16 @@ const getDeviceList = async () => {
|
||||
? data
|
||||
: []
|
||||
|
||||
const totalValue =
|
||||
data.total ?? data.count ?? data.totalCount ?? records.length ?? 0
|
||||
// 过滤掉 devModel 为 PLC 的设备(前端过滤作为备用)
|
||||
const filteredRecords = records.filter((item: any) => {
|
||||
const devModel = item.devModel || ''
|
||||
return devModel.toUpperCase() !== 'PLC'
|
||||
})
|
||||
|
||||
deviceList.value = records
|
||||
const totalValue =
|
||||
data.total ?? data.count ?? data.totalCount ?? filteredRecords.length ?? 0
|
||||
|
||||
deviceList.value = filteredRecords
|
||||
total.value = Number(totalValue) || 0
|
||||
} catch (error) {
|
||||
console.error('获取设备列表失败:', error)
|
||||
@@ -467,10 +584,6 @@ const resetForm = () => {
|
||||
formData.id = undefined
|
||||
formData.devName = ''
|
||||
formData.devModel = ''
|
||||
formData.ipAddr = ''
|
||||
formData.port = undefined
|
||||
formData.protocolType = ''
|
||||
formData.company = ''
|
||||
formData.devDesc = ''
|
||||
formData.remark = ''
|
||||
formData.status = 0
|
||||
@@ -488,10 +601,6 @@ const handleEdit = async (item: any) => {
|
||||
formData.id = data.id ?? item.id
|
||||
formData.devName = data.devName ?? ''
|
||||
formData.devModel = data.devModel ?? ''
|
||||
formData.ipAddr = data.ipAddr ?? ''
|
||||
formData.port = data.port ?? undefined
|
||||
formData.protocolType = data.protocolType ?? ''
|
||||
formData.company = data.company ?? ''
|
||||
formData.devDesc = data.devDesc ?? ''
|
||||
formData.remark = data.remark ?? ''
|
||||
formData.status = data.status ?? 0
|
||||
@@ -581,18 +690,6 @@ const handleSubmit = async () => {
|
||||
if (formData.devModel) {
|
||||
submitData.devModel = formData.devModel
|
||||
}
|
||||
if (formData.ipAddr) {
|
||||
submitData.ipAddr = formData.ipAddr
|
||||
}
|
||||
if (formData.port !== undefined && formData.port !== null) {
|
||||
submitData.port = formData.port
|
||||
}
|
||||
if (formData.protocolType) {
|
||||
submitData.protocolType = formData.protocolType
|
||||
}
|
||||
if (formData.company) {
|
||||
submitData.company = formData.company
|
||||
}
|
||||
if (formData.devDesc) {
|
||||
submitData.devDesc = formData.devDesc
|
||||
}
|
||||
@@ -638,6 +735,266 @@ const handleDrawerClose = () => {
|
||||
resetForm()
|
||||
}
|
||||
|
||||
// 参数配置相关
|
||||
const paramDialogVisible = ref(false)
|
||||
const paramLoading = ref(false)
|
||||
const paramList = ref<any[]>([])
|
||||
const paramTotal = ref(0)
|
||||
const currentDevice = ref<any>(null)
|
||||
const paramEmptyText = ref('该设备暂无参数,请完成配置')
|
||||
|
||||
const paramPagination = reactive({
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
})
|
||||
|
||||
// 参数类型选项(固定数据类型)
|
||||
const paramTypeOptions = [
|
||||
{ label: '字符串', value: 'string' },
|
||||
{ label: '整数', value: 'integer' },
|
||||
{ label: '浮点数', value: 'float' },
|
||||
{ label: '布尔值', value: 'boolean' },
|
||||
{ label: '日期', value: 'date' },
|
||||
{ label: '时间', value: 'datetime' },
|
||||
{ label: 'JSON', value: 'json' },
|
||||
]
|
||||
|
||||
// 表单控件选项(常用表单控件)
|
||||
const formTypeOptions = [
|
||||
{ label: '输入框', value: 'input' },
|
||||
{ label: '文本域', value: 'textarea' },
|
||||
{ label: '数字输入框', value: 'number' },
|
||||
{ label: '下拉选择', value: 'select' },
|
||||
{ label: '单选按钮', value: 'radio' },
|
||||
{ label: '复选框', value: 'checkbox' },
|
||||
{ label: '日期选择器', value: 'datepicker' },
|
||||
{ label: '时间选择器', value: 'timepicker' },
|
||||
{ label: '开关', value: 'switch' },
|
||||
]
|
||||
|
||||
// 获取参数序号
|
||||
const getParamIndex = (index: number) => {
|
||||
return (paramPagination.pageNum - 1) * paramPagination.pageSize + index + 1
|
||||
}
|
||||
|
||||
// 打开参数配置对话框
|
||||
const handleConfigParams = async (row: any) => {
|
||||
currentDevice.value = row
|
||||
paramPagination.pageNum = 1
|
||||
paramPagination.pageSize = 10
|
||||
paramDialogVisible.value = true
|
||||
await getParamList()
|
||||
}
|
||||
|
||||
// 获取参数列表
|
||||
const getParamList = async () => {
|
||||
if (!currentDevice.value?.id) return
|
||||
|
||||
try {
|
||||
paramLoading.value = true
|
||||
const params: any = {
|
||||
pageNum: paramPagination.pageNum,
|
||||
pageSize: paramPagination.pageSize,
|
||||
devId: currentDevice.value.id, // 只查询该设备的参数
|
||||
}
|
||||
|
||||
const res: any = await devparamlist(params)
|
||||
|
||||
const data = res?.data ?? res ?? {}
|
||||
|
||||
// 兼容多种返回格式
|
||||
const recordsFromData =
|
||||
data.records ||
|
||||
data.list ||
|
||||
data.rows ||
|
||||
data.items ||
|
||||
(Array.isArray(data.data) ? data.data : undefined)
|
||||
|
||||
const records = Array.isArray(recordsFromData)
|
||||
? recordsFromData
|
||||
: Array.isArray(data)
|
||||
? data
|
||||
: []
|
||||
|
||||
const totalValue =
|
||||
data.total ?? data.count ?? data.totalCount ?? records.length ?? 0
|
||||
|
||||
// 为每条记录添加编辑状态标识
|
||||
paramList.value = records.map((item: any) => ({
|
||||
...item,
|
||||
isEditing: false,
|
||||
}))
|
||||
paramTotal.value = Number(totalValue) || 0
|
||||
|
||||
if (paramList.value.length === 0) {
|
||||
paramEmptyText.value = '该设备暂无参数,请完成配置'
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取参数列表失败:', error)
|
||||
ElMessage.error('获取参数列表失败')
|
||||
paramList.value = []
|
||||
paramTotal.value = 0
|
||||
} finally {
|
||||
paramLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 参数分页大小改变
|
||||
const handleParamSizeChange = (size: number) => {
|
||||
paramPagination.pageSize = size
|
||||
getParamList()
|
||||
}
|
||||
|
||||
// 参数当前页改变
|
||||
const handleParamCurrentChange = (page: number) => {
|
||||
paramPagination.pageNum = page
|
||||
getParamList()
|
||||
}
|
||||
|
||||
// 添加一行参数
|
||||
const handleAddParamRow = () => {
|
||||
const newRow = {
|
||||
id: undefined,
|
||||
devId: currentDevice.value?.id,
|
||||
paramName: '',
|
||||
paramType: '',
|
||||
paramUnit: '',
|
||||
formType: '',
|
||||
paramValue: '',
|
||||
isEditing: true,
|
||||
isNew: true, // 标记为新添加的行
|
||||
}
|
||||
paramList.value.unshift(newRow)
|
||||
paramTotal.value += 1
|
||||
}
|
||||
|
||||
// 编辑参数
|
||||
const handleEditParam = (row: any) => {
|
||||
row.isEditing = true
|
||||
}
|
||||
|
||||
// 保存参数
|
||||
const handleSaveParam = async (row: any) => {
|
||||
// 验证必填项
|
||||
if (!row.paramName || row.paramName.trim() === '') {
|
||||
ElMessage.warning('参数名称不能为空')
|
||||
return
|
||||
}
|
||||
|
||||
if (!currentDevice.value?.id) {
|
||||
ElMessage.error('设备ID不存在')
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
paramLoading.value = true
|
||||
|
||||
const submitData: any = {
|
||||
devId: currentDevice.value.id,
|
||||
paramName: row.paramName.trim(),
|
||||
}
|
||||
|
||||
// 添加其他字段(如果非空)
|
||||
if (row.paramType) {
|
||||
submitData.paramType = row.paramType
|
||||
}
|
||||
if (row.paramUnit) {
|
||||
submitData.paramUnit = row.paramUnit
|
||||
}
|
||||
if (row.formType) {
|
||||
submitData.formType = row.formType
|
||||
}
|
||||
if (row.paramValue !== undefined && row.paramValue !== null) {
|
||||
submitData.paramValue = row.paramValue
|
||||
}
|
||||
|
||||
let res: any
|
||||
if (row.isNew && !row.id) {
|
||||
// 新增
|
||||
res = await devparamadd(submitData)
|
||||
} else {
|
||||
// 更新 - 需要传入ID,其他字段可选(非空则更新)
|
||||
res = await devparamupd({
|
||||
id: row.id,
|
||||
...submitData,
|
||||
})
|
||||
}
|
||||
|
||||
if (res?.code === '0' || res?.code === 0 || res?.success) {
|
||||
const wasNew = row.isNew
|
||||
ElMessage.success(wasNew ? '新增成功' : '更新成功')
|
||||
row.isEditing = false
|
||||
row.isNew = false
|
||||
// 如果是新增,刷新列表以获取ID
|
||||
if (wasNew) {
|
||||
await getParamList()
|
||||
}
|
||||
} else {
|
||||
ElMessage.error(res?.message || res?.msg || (row.isNew ? '新增失败' : '更新失败'))
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('保存参数失败:', error)
|
||||
ElMessage.error('保存参数失败')
|
||||
} finally {
|
||||
paramLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 删除参数
|
||||
const handleDeleteParam = async (row: any) => {
|
||||
try {
|
||||
// 如果是新添加的行(还未保存),直接从列表中移除
|
||||
if (row.isNew && !row.id) {
|
||||
const index = paramList.value.findIndex((item) => item === row)
|
||||
if (index > -1) {
|
||||
paramList.value.splice(index, 1)
|
||||
paramTotal.value -= 1
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if (!row.id) {
|
||||
ElMessage.warning('无法删除:参数ID不存在')
|
||||
return
|
||||
}
|
||||
|
||||
await ElMessageBox.confirm(
|
||||
`确定要删除参数"${row.paramName || '未命名'}"吗?`,
|
||||
'提示',
|
||||
{
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
}
|
||||
)
|
||||
|
||||
paramLoading.value = true
|
||||
const res: any = await devparamdel(row.id)
|
||||
|
||||
if (res?.code === '0' || res?.code === 0 || res?.success) {
|
||||
ElMessage.success('删除成功')
|
||||
await getParamList()
|
||||
} else {
|
||||
ElMessage.error(res?.message || res?.msg || '删除失败')
|
||||
}
|
||||
} catch (error: any) {
|
||||
if (error !== 'cancel') {
|
||||
console.error('删除参数失败:', error)
|
||||
ElMessage.error('删除参数失败')
|
||||
}
|
||||
} finally {
|
||||
paramLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 关闭参数配置对话框
|
||||
const handleParamDialogClose = () => {
|
||||
paramDialogVisible.value = false
|
||||
paramList.value = []
|
||||
paramTotal.value = 0
|
||||
currentDevice.value = null
|
||||
}
|
||||
|
||||
// 初始化
|
||||
onMounted(() => {
|
||||
getIslandList().then(() => {
|
||||
@@ -682,5 +1039,23 @@ onMounted(() => {
|
||||
justify-content: flex-end;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.param-config-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.param-toolbar {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.param-pagination {
|
||||
margin-top: 16px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
583
rc_autoplc_front/src/views/devinfo/plc.vue
Normal file
583
rc_autoplc_front/src/views/devinfo/plc.vue
Normal file
@@ -0,0 +1,583 @@
|
||||
<template>
|
||||
<div class="plc-devinfo-page">
|
||||
<!-- 搜索栏 -->
|
||||
<el-card class="search-card" shadow="never">
|
||||
<div class="search-bar">
|
||||
<el-form :inline="true" :model="queryForm" label-width="100px">
|
||||
<el-form-item label="设备名称">
|
||||
<el-input
|
||||
v-model="queryForm.devName"
|
||||
placeholder="输入设备名称"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="设备状态">
|
||||
<el-select
|
||||
v-model="queryForm.status"
|
||||
placeholder="请选择设备状态"
|
||||
clearable
|
||||
style="width: 200px"
|
||||
>
|
||||
<el-option label="空闲" :value="0" />
|
||||
<el-option label="运行" :value="1" />
|
||||
<el-option label="故障" :value="4" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="handleSearch">查询</el-button>
|
||||
<el-button @click="resetSearch">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<div class="toolbar">
|
||||
<el-button type="primary" @click="handleAdd">
|
||||
<el-icon><Plus /></el-icon>
|
||||
新增PLC设备
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!-- PLC设备列表 -->
|
||||
<el-card shadow="never">
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="deviceList"
|
||||
border
|
||||
stripe
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-table-column type="index" label="序号" width="60" :index="getIndex" />
|
||||
<el-table-column prop="devName" label="设备名称" min-width="120" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
{{ row.devName || '暂无' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="devModel" label="设备型号" min-width="100" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
{{ row.devModel || '暂无' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="ipAddr" label="IP地址" min-width="120" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
{{ row.ipAddr || '暂无' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="port" label="端口" width="100" align="center">
|
||||
<template #default="{ row }">
|
||||
{{ row.port || '暂无' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="protocolType" label="协议" min-width="100" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
{{ row.protocolType || '暂无' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="company" label="公司名" min-width="120" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
{{ row.company || '暂无' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="status" label="状态" width="100" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="getStatusType(row.status)" size="small">
|
||||
{{ getStatusText(row.status) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="devDesc" label="描述" min-width="150" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
{{ row.devDesc || '暂无' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="remark" label="备注" min-width="150" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
{{ row.remark || '暂无' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="180" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button
|
||||
type="primary"
|
||||
size="small"
|
||||
link
|
||||
@click="handleEdit(row)"
|
||||
>
|
||||
<el-icon><Edit /></el-icon>
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button
|
||||
type="danger"
|
||||
size="small"
|
||||
link
|
||||
@click="handleDelete(row)"
|
||||
>
|
||||
<el-icon><Delete /></el-icon>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 分页 -->
|
||||
<div class="pagination">
|
||||
<el-pagination
|
||||
v-model:current-page="pagination.pageNum"
|
||||
v-model:page-size="pagination.pageSize"
|
||||
:page-sizes="[10, 20, 50, 100]"
|
||||
layout="total, sizes, prev, pager, next, jumper"
|
||||
:total="total"
|
||||
background
|
||||
@current-change="handleCurrentChange"
|
||||
@size-change="handleSizeChange"
|
||||
/>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!-- 新增/编辑抽屉 -->
|
||||
<el-drawer
|
||||
v-model="drawerVisible"
|
||||
:title="drawerTitle"
|
||||
direction="rtl"
|
||||
size="500px"
|
||||
:before-close="handleDrawerClose"
|
||||
>
|
||||
<el-form
|
||||
ref="formRef"
|
||||
:model="formData"
|
||||
:rules="formRules"
|
||||
label-width="100px"
|
||||
label-position="left"
|
||||
>
|
||||
<el-form-item label="设备名称" prop="devName">
|
||||
<el-input
|
||||
v-model="formData.devName"
|
||||
placeholder="请输入设备名称"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="设备型号">
|
||||
<el-input
|
||||
v-model="formData.devModel"
|
||||
disabled
|
||||
placeholder="PLC"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="IP地址" prop="ipAddr">
|
||||
<el-input
|
||||
v-model="formData.ipAddr"
|
||||
placeholder="请输入IP地址"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="端口" prop="port">
|
||||
<el-input-number
|
||||
v-model="formData.port"
|
||||
:min="1"
|
||||
:max="65535"
|
||||
placeholder="请输入端口"
|
||||
style="width: 100%"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="协议" prop="protocolType">
|
||||
<el-input
|
||||
v-model="formData.protocolType"
|
||||
placeholder="请输入协议类型"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="公司名" prop="company">
|
||||
<el-input
|
||||
v-model="formData.company"
|
||||
placeholder="请输入公司名"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="描述" prop="devDesc">
|
||||
<el-input
|
||||
v-model="formData.devDesc"
|
||||
type="textarea"
|
||||
:rows="3"
|
||||
placeholder="请输入描述"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input
|
||||
v-model="formData.remark"
|
||||
type="textarea"
|
||||
:rows="3"
|
||||
placeholder="请输入备注"
|
||||
clearable
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="drawer-footer">
|
||||
<el-button @click="handleDrawerClose">取消</el-button>
|
||||
<el-button type="primary" @click="handleSubmit" :loading="submitting">
|
||||
确定
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-drawer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, onMounted } from 'vue'
|
||||
import { ElMessage, ElMessageBox } from 'element-plus'
|
||||
import { Plus, Edit, Delete } from '@element-plus/icons-vue'
|
||||
import {
|
||||
devInfoadd,
|
||||
devInfodel,
|
||||
devInfoupd,
|
||||
devInfolist,
|
||||
devInfobyid,
|
||||
} from '@/api/tb/devinfo'
|
||||
|
||||
// 加载状态
|
||||
const loading = ref(false)
|
||||
const submitting = ref(false)
|
||||
|
||||
// 设备列表
|
||||
const deviceList = ref<any[]>([])
|
||||
const total = ref(0)
|
||||
|
||||
// 查询表单
|
||||
const queryForm = reactive({
|
||||
devName: '',
|
||||
status: undefined as number | undefined,
|
||||
})
|
||||
|
||||
// 分页
|
||||
const pagination = reactive({
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
})
|
||||
|
||||
// 抽屉相关
|
||||
const drawerVisible = ref(false)
|
||||
const drawerTitle = ref('新增PLC设备')
|
||||
const isEdit = ref(false)
|
||||
const formRef = ref()
|
||||
|
||||
// 表单数据
|
||||
const formData = reactive({
|
||||
id: undefined,
|
||||
devName: '',
|
||||
devModel: 'PLC',
|
||||
ipAddr: '',
|
||||
port: undefined as number | undefined,
|
||||
protocolType: '',
|
||||
company: '',
|
||||
devDesc: '',
|
||||
remark: '',
|
||||
status: 0, // 状态自动设置为0
|
||||
})
|
||||
|
||||
// 表单验证规则
|
||||
const formRules = {
|
||||
devName: [
|
||||
{ required: true, message: '请输入设备名称', trigger: 'blur' },
|
||||
],
|
||||
}
|
||||
|
||||
// 获取序号
|
||||
const getIndex = (index: number) => {
|
||||
return (pagination.pageNum - 1) * pagination.pageSize + index + 1
|
||||
}
|
||||
|
||||
// 获取状态类型
|
||||
const getStatusType = (status: number | null | undefined) => {
|
||||
if (status === 0) return 'success' // 空闲 - 绿色
|
||||
if (status === 1) return 'warning' // 运行 - 黄色
|
||||
if (status === 4) return 'danger' // 故障 - 红色
|
||||
return 'info'
|
||||
}
|
||||
|
||||
// 获取状态文本
|
||||
const getStatusText = (status: number | null | undefined) => {
|
||||
if (status === 0) return '空闲'
|
||||
if (status === 1) return '运行'
|
||||
if (status === 4) return '故障'
|
||||
return '未知'
|
||||
}
|
||||
|
||||
// 获取设备列表(只查询devModel为PLC的设备)
|
||||
const getDeviceList = async () => {
|
||||
try {
|
||||
loading.value = true
|
||||
const params: any = {
|
||||
pageNum: pagination.pageNum,
|
||||
pageSize: pagination.pageSize,
|
||||
devModel: 'PLC', // 只查询PLC设备
|
||||
}
|
||||
|
||||
// 设备名称模糊查询
|
||||
if (queryForm.devName) {
|
||||
params.devName = queryForm.devName
|
||||
}
|
||||
// 设备状态精确查询
|
||||
if (queryForm.status !== undefined && queryForm.status !== null) {
|
||||
params.status = queryForm.status
|
||||
}
|
||||
|
||||
const res: any = await devInfolist(params)
|
||||
|
||||
const data = res?.data ?? res ?? {}
|
||||
|
||||
// 兼容多种返回格式
|
||||
const recordsFromData =
|
||||
data.records ||
|
||||
data.list ||
|
||||
data.rows ||
|
||||
data.items ||
|
||||
(Array.isArray(data.data) ? data.data : undefined)
|
||||
|
||||
const records = Array.isArray(recordsFromData)
|
||||
? recordsFromData
|
||||
: Array.isArray(data)
|
||||
? data
|
||||
: []
|
||||
|
||||
// 再次过滤,确保只显示PLC设备
|
||||
const plcRecords = records.filter((item: any) => item.devModel === 'PLC')
|
||||
|
||||
const totalValue =
|
||||
data.total ?? data.count ?? data.totalCount ?? plcRecords.length ?? 0
|
||||
|
||||
deviceList.value = plcRecords
|
||||
total.value = Number(totalValue) || 0
|
||||
} catch (error) {
|
||||
console.error('获取PLC设备列表失败:', error)
|
||||
ElMessage.error('获取PLC设备列表失败')
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 查询
|
||||
const handleSearch = () => {
|
||||
pagination.pageNum = 1
|
||||
getDeviceList()
|
||||
}
|
||||
|
||||
// 重置查询
|
||||
const resetSearch = () => {
|
||||
queryForm.devName = ''
|
||||
queryForm.status = undefined
|
||||
handleSearch()
|
||||
}
|
||||
|
||||
// 分页大小改变
|
||||
const handleSizeChange = (size: number) => {
|
||||
pagination.pageSize = size
|
||||
getDeviceList()
|
||||
}
|
||||
|
||||
// 当前页改变
|
||||
const handleCurrentChange = (page: number) => {
|
||||
pagination.pageNum = page
|
||||
getDeviceList()
|
||||
}
|
||||
|
||||
// 打开新增抽屉
|
||||
const handleAdd = () => {
|
||||
isEdit.value = false
|
||||
drawerTitle.value = '新增PLC设备'
|
||||
resetForm()
|
||||
drawerVisible.value = true
|
||||
}
|
||||
|
||||
// 重置表单
|
||||
const resetForm = () => {
|
||||
formData.id = undefined
|
||||
formData.devName = ''
|
||||
formData.devModel = 'PLC'
|
||||
formData.ipAddr = ''
|
||||
formData.port = undefined
|
||||
formData.protocolType = ''
|
||||
formData.company = ''
|
||||
formData.devDesc = ''
|
||||
formData.remark = ''
|
||||
formData.status = 0
|
||||
formRef.value?.clearValidate()
|
||||
}
|
||||
|
||||
// 编辑设备
|
||||
const handleEdit = async (item: any) => {
|
||||
try {
|
||||
loading.value = true
|
||||
const res: any = await devInfobyid(item.id)
|
||||
|
||||
const data = res?.data ?? res ?? {}
|
||||
|
||||
formData.id = data.id ?? item.id
|
||||
formData.devName = data.devName ?? ''
|
||||
formData.devModel = data.devModel ?? 'PLC'
|
||||
formData.ipAddr = data.ipAddr ?? ''
|
||||
formData.port = data.port ?? undefined
|
||||
formData.protocolType = data.protocolType ?? ''
|
||||
formData.company = data.company ?? ''
|
||||
formData.devDesc = data.devDesc ?? ''
|
||||
formData.remark = data.remark ?? ''
|
||||
formData.status = data.status ?? 0
|
||||
|
||||
isEdit.value = true
|
||||
drawerTitle.value = '编辑PLC设备'
|
||||
drawerVisible.value = true
|
||||
} catch (error) {
|
||||
console.error('获取PLC设备信息失败:', error)
|
||||
ElMessage.error('获取PLC设备信息失败')
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 删除设备
|
||||
const handleDelete = async (item: any) => {
|
||||
try {
|
||||
await ElMessageBox.confirm(
|
||||
`确定要删除PLC设备"${item.devName || '未命名'}"吗?`,
|
||||
'提示',
|
||||
{
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning',
|
||||
}
|
||||
)
|
||||
|
||||
loading.value = true
|
||||
const res: any = await devInfodel(item.id)
|
||||
|
||||
if (res?.code === '0' || res?.code === 0 || res?.success) {
|
||||
ElMessage.success('删除成功')
|
||||
getDeviceList()
|
||||
} else {
|
||||
ElMessage.error(res?.message || res?.msg || '删除失败')
|
||||
}
|
||||
} catch (error: any) {
|
||||
if (error !== 'cancel') {
|
||||
console.error('删除PLC设备失败:', error)
|
||||
ElMessage.error('删除PLC设备失败')
|
||||
}
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 提交表单
|
||||
const handleSubmit = async () => {
|
||||
if (!formRef.value) return
|
||||
|
||||
try {
|
||||
await formRef.value.validate()
|
||||
submitting.value = true
|
||||
|
||||
// 构建提交数据,只包含非空字段(根据后端要求:非空则入库/更新)
|
||||
const submitData: any = {
|
||||
devName: formData.devName,
|
||||
devModel: 'PLC', // 设备型号固定为PLC
|
||||
status: 0, // 状态自动设置为0
|
||||
}
|
||||
|
||||
// 添加其他字段(如果非空)
|
||||
if (formData.ipAddr) {
|
||||
submitData.ipAddr = formData.ipAddr
|
||||
}
|
||||
if (formData.port !== undefined && formData.port !== null) {
|
||||
submitData.port = formData.port
|
||||
}
|
||||
if (formData.protocolType) {
|
||||
submitData.protocolType = formData.protocolType
|
||||
}
|
||||
if (formData.company) {
|
||||
submitData.company = formData.company
|
||||
}
|
||||
if (formData.devDesc) {
|
||||
submitData.devDesc = formData.devDesc
|
||||
}
|
||||
if (formData.remark) {
|
||||
submitData.remark = formData.remark
|
||||
}
|
||||
|
||||
let res: any
|
||||
if (isEdit.value && formData.id) {
|
||||
// 编辑 - 需要传入ID,其他字段可选(非空则更新)
|
||||
res = await devInfoupd({
|
||||
id: formData.id,
|
||||
...submitData,
|
||||
})
|
||||
} else {
|
||||
// 新增
|
||||
res = await devInfoadd(submitData)
|
||||
}
|
||||
|
||||
if (res?.code === '0' || res?.code === 0 || res?.success) {
|
||||
ElMessage.success(isEdit.value ? '编辑成功' : '新增成功')
|
||||
drawerVisible.value = false
|
||||
getDeviceList()
|
||||
} else {
|
||||
ElMessage.error(res?.message || res?.msg || (isEdit.value ? '编辑失败' : '新增失败'))
|
||||
}
|
||||
} catch (error: any) {
|
||||
if (error !== false) {
|
||||
console.error('提交失败:', error)
|
||||
ElMessage.error('提交失败,请检查表单')
|
||||
}
|
||||
} finally {
|
||||
submitting.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 关闭抽屉
|
||||
const handleDrawerClose = () => {
|
||||
drawerVisible.value = false
|
||||
resetForm()
|
||||
}
|
||||
|
||||
// 初始化
|
||||
onMounted(() => {
|
||||
getDeviceList()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.plc-devinfo-page {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.search-card {
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
|
||||
.search-bar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.toolbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.pagination {
|
||||
margin-top: 16px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.drawer-footer {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 10px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{
|
||||
|
||||
"extends": "@vue/tsconfig/tsconfig.dom.json",
|
||||
"include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
|
||||
"exclude": ["src/**/__tests__/*"],
|
||||
|
||||
Reference in New Issue
Block a user