Merge remote-tracking branch 'origin/main'

This commit is contained in:
2026-01-04 14:35:38 +08:00
11 changed files with 2868 additions and 5 deletions

View File

@@ -37,7 +37,7 @@ export function userRoleById(id: string | number) {
// 根据角色ID查询关联用户先封装不调用
export function userRoleByRoleId(roleId: string | number) {
return request({
url: `/user-role/getByRoleId/${roleId}`,
url: `/user-role/role/${roleId}`,
method: 'get',
})
}
@@ -45,7 +45,7 @@ export function userRoleByRoleId(roleId: string | number) {
// 根据角色ID删除所有关联先封装不调用
export function userRoleDelByRoleId(roleId: string | number) {
return request({
url: `/user-role/delByRoleId/${roleId}`,
url: `/user-role/role/${roleId}`,
method: 'delete',
})
}
@@ -53,7 +53,7 @@ export function userRoleDelByRoleId(roleId: string | number) {
// 根据用户ID查询关联角色先封装不调用
export function userRoleByUserId(userId: string | number) {
return request({
url: `/user-role/getByUserId/${userId}`,
url: `/user-role/user/${userId}`,
method: 'get',
})
}
@@ -61,7 +61,7 @@ export function userRoleByUserId(userId: string | number) {
// 根据用户ID删除所有关联先封装不调用
export function userRoleDelByUserId(userId: string | number) {
return request({
url: `/user-role/delByUserId/${userId}`,
url: `/user-role/user/${userId}`,
method: 'delete',
})
}

View File

@@ -0,0 +1,47 @@
import request from '@/utils/request'
export function devInfoadd(data: any) {
return request({
url: '/devInfo/add',
method: 'post',
data,
})
}
export function devInfodel(id: string | number) {
return request({
url: `/devInfo/del/${id}`,
method: 'delete',
})
}
export function devInfoupd(data: any) {
return request({
url: '/devInfo/update',
method: 'put',
data,
})
}
export function devInfolist(data: any) {
return request({
url: '/devInfo/listPage',
method: 'get',
params: data,
})
}
export function devInfobyid(id: string | number) {
return request({
url: `/devInfo/getById/${id}`,
method: 'get',
})
}
export function devselect(data: any) {
return request({
url: '/devInfo/all',
method: 'get',
params: data,
})
}

View 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,
})
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@@ -37,6 +37,21 @@ const router = createRouter({
name: 'user-role',
component: () => import('../views/user-role/index.vue'),
},
{
path: '/island-info',
name: 'island-info',
component: () => import('../views/islandInfo/index.vue'),
},
{
path: '/devinfo',
name: 'devinfo',
component: () => import('../views/devinfo/index.vue'),
},
{
path: '/plc-devinfo',
name: 'plc-devinfo',
component: () => import('../views/devinfo/plc.vue'),
},
],
},
],

View File

@@ -61,6 +61,24 @@
<span>用户角色管理</span>
</el-menu-item>
</el-sub-menu>
<el-sub-menu index="island">
<template #title>
<el-icon><Grid /></el-icon>
<span>业务管理</span>
</template>
<el-menu-item index="/island-info">
<el-icon><Setting /></el-icon>
<span>功能岛管理</span>
</el-menu-item>
<el-menu-item index="/devinfo">
<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>
@@ -76,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 } 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()

File diff suppressed because it is too large Load Diff

View 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>

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,5 @@
{
"extends": "@vue/tsconfig/tsconfig.dom.json",
"include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
"exclude": ["src/**/__tests__/*"],