This commit is contained in:
zpc 2025-08-06 02:29:13 +08:00
parent 3ad57648de
commit 42c7dd2bdd
14 changed files with 2681 additions and 3 deletions

View File

@ -5,7 +5,7 @@ VITE_APP_API_HOST = 'http://localhost:8888/'
# 开发环境
# VITE_APP_BASE_API = 'http://localhost:8888/'
VITE_APP_BASE_API = 'https://gift.zpc-xy.com/'
VITE_APP_BASE_API = 'http://localhost:8888/'
# 路由前缀
VITE_APP_ROUTER_PREFIX = '/'
@ -14,4 +14,4 @@ VITE_APP_ROUTER_PREFIX = '/'
VITE_APP_UPLOAD_URL = 'Common/UploadFile'
#socket API
VITE_APP_SOCKET_API = 'https://gift.zpc-xy.com/msghub'
VITE_APP_SOCKET_API = 'http://localhost:8888/msghub'

View File

@ -0,0 +1,57 @@
import request from '@/utils/request'
/**
* -信息分页查询
* @param {查询条件} data
*/
export function listOdfFrames(query) {
return request({
url: 'business/OdfFrames/list',
method: 'get',
params: query,
})
}
/**
* 新增框-信息
* @param data
*/
export function addOdfFrames(data) {
return request({
url: 'business/OdfFrames',
method: 'post',
data: data,
})
}
/**
* 修改框-信息
* @param data
*/
export function updateOdfFrames(data) {
return request({
url: 'business/OdfFrames',
method: 'PUT',
data: data,
})
}
/**
* 获取框-信息详情
* @param {Id}
*/
export function getOdfFrames(id) {
return request({
url: 'business/OdfFrames/' + id,
method: 'get'
})
}
/**
* 删除框-信息
* @param {主键} pid
*/
export function delOdfFrames(pid) {
return request({
url: 'business/OdfFrames/delete/' + pid,
method: 'POST'
})
}

View File

@ -0,0 +1,14 @@
import request from '@/utils/request'
import { downFile } from '@/utils/request'
/**
* 机房列表分页查询
* @param {查询条件} data
*/
export function getOdfRoomsTreeList(query) {
return request({
url: 'business/OdfRooms/tree',
method: 'get',
params: query,
})
}

View File

@ -0,0 +1,62 @@
import request from '@/utils/request'
import { downFile } from '@/utils/request'
/**
* 端口分页查询
* @param {查询条件} data
*/
export function listOdfPorts(query) {
return request({
url: 'business/OdfPorts/list',
method: 'get',
params: query,
})
}
/**
* 新增端口
* @param data
*/
export function addOdfPorts(data) {
return request({
url: 'business/OdfPorts',
method: 'post',
data: data,
})
}
/**
* 修改端口
* @param data
*/
export function updateOdfPorts(data) {
return request({
url: 'business/OdfPorts',
method: 'PUT',
data: data,
})
}
/**
* 获取端口详情
* @param {Id}
*/
export function getOdfPorts(id) {
return request({
url: 'business/OdfPorts/' + id,
method: 'get'
})
}
/**
* 删除端口
* @param {主键} pid
*/
export function delOdfPorts(pid) {
return request({
url: 'business/OdfPorts/delete/' + pid,
method: 'POST'
})
}
// 导出端口
export async function exportOdfPorts(query) {
await downFile('business/OdfPorts/export', { ...query })
}

View File

@ -0,0 +1,62 @@
import request from '@/utils/request'
import { downFile } from '@/utils/request'
/**
* 机架列表分页查询
* @param {查询条件} data
*/
export function listOdfRacks(query) {
return request({
url: 'business/OdfRacks/list',
method: 'get',
params: query,
})
}
/**
* 新增机架列表
* @param data
*/
export function addOdfRacks(data) {
return request({
url: 'business/OdfRacks',
method: 'post',
data: data,
})
}
/**
* 修改机架列表
* @param data
*/
export function updateOdfRacks(data) {
return request({
url: 'business/OdfRacks',
method: 'PUT',
data: data,
})
}
/**
* 获取机架列表详情
* @param {Id}
*/
export function getOdfRacks(id) {
return request({
url: 'business/OdfRacks/' + id,
method: 'get'
})
}
/**
* 删除机架列表
* @param {主键} pid
*/
export function delOdfRacks(pid) {
return request({
url: 'business/OdfRacks/delete/' + pid,
method: 'POST'
})
}
// 导出机架列表
export async function exportOdfRacks(query) {
await downFile('business/OdfRacks/export', { ...query })
}

View File

@ -0,0 +1,62 @@
import request from '@/utils/request'
import { downFile } from '@/utils/request'
/**
* 机房列表分页查询
* @param {查询条件} data
*/
export function listOdfRooms(query) {
return request({
url: 'business/OdfRooms/list',
method: 'get',
params: query,
})
}
/**
* 新增机房列表
* @param data
*/
export function addOdfRooms(data) {
return request({
url: 'business/OdfRooms',
method: 'post',
data: data,
})
}
/**
* 修改机房列表
* @param data
*/
export function updateOdfRooms(data) {
return request({
url: 'business/OdfRooms',
method: 'PUT',
data: data,
})
}
/**
* 获取机房列表详情
* @param {Id}
*/
export function getOdfRooms(id) {
return request({
url: 'business/OdfRooms/' + id,
method: 'get'
})
}
/**
* 删除机房列表
* @param {主键} pid
*/
export function delOdfRooms(pid) {
return request({
url: 'business/OdfRooms/delete/' + pid,
method: 'POST'
})
}
// 导出机房列表
export async function exportOdfRooms(query) {
await downFile('business/OdfRooms/export', { ...query })
}

View File

@ -0,0 +1,255 @@
<!--
* @Descripttion: ODF端口表单组件
* @Author: (admin)
* @Date: (2025-01-16)
-->
<template>
<el-dialog :title="title" :lock-scroll="false" v-model="dialogVisible" @close="handleClose">
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
<el-row :gutter="20">
<!-- 可编辑字段 -->
<el-col :lg="12">
<el-form-item label="端口名称" prop="name">
<el-input v-model="form.name" placeholder="请输入端口名称" />
</el-form-item>
</el-col>
<el-col :lg="12">
<el-form-item label="连接状态" prop="status">
<el-radio-group v-model="form.status">
<el-radio v-for="item in options.odf_ports_status" :key="item.dictValue" :value="parseInt(item.dictValue)">
{{ item.dictLabel }}
</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :lg="12">
<el-form-item label="光衰值dB" prop="opticalAttenuation">
<el-input v-model="form.opticalAttenuation" placeholder="请输入光衰值dB" />
</el-form-item>
</el-col>
<el-col :lg="24">
<el-form-item label="备注" prop="remarks">
<el-input type="textarea" v-model="form.remarks" placeholder="请输入备注" />
</el-form-item>
</el-col>
<el-col :lg="24">
<el-form-item label="历史故障表" prop="historyRemarks">
<el-input type="textarea" v-model="form.historyRemarks" placeholder="请输入历史故障表" />
</el-form-item>
</el-col>
<!-- 分隔线 -->
<el-col :lg="24">
<el-divider content-position="left">
<span style="color: #909399; font-size: 12px">基础信息不可修改</span>
</el-divider>
</el-col>
<!-- 不可编辑字段 -->
<el-col :lg="12">
<el-form-item label="机房名称" prop="roomName">
<el-input v-model="form.roomName" disabled placeholder="请输入机房名称" />
</el-form-item>
</el-col>
<el-col :lg="12">
<el-form-item label="机架名称" prop="rackName">
<el-input v-model="form.rackName" disabled placeholder="请输入机架名称" />
</el-form-item>
</el-col>
<el-col :lg="12">
<el-form-item label="机框名称" prop="frameName">
<el-input v-model="form.frameName" disabled placeholder="请输入框名称" />
</el-form-item>
</el-col>
<el-col :lg="6">
<el-form-item label="行号" prop="rowNumber">
<el-input v-model="form.rowNumber" disabled :controls="true" controls-position="right" placeholder="请输入行号1-6" />
</el-form-item>
</el-col>
<el-col :lg="6">
<el-form-item label="列号" prop="portNumber">
<el-input v-model="form.portNumber" disabled :controls="true" controls-position="right" placeholder="请输入端口号1-12" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer>
<el-button text @click="handleClose">{{ $t('btn.cancel') }}</el-button>
<el-button type="primary" :loading="submitLoading" @click="submitForm">{{ $t('btn.submit') }}</el-button>
</template>
</el-dialog>
</template>
<script setup name="odfPortForm">
import { addOdfPorts, updateOdfPorts, getOdfPorts } from '@/api/business/odfports.js'
const props = defineProps({
visible: {
type: Boolean,
default: false
},
id: {
type: [String, Number],
default: null
}
})
const emit = defineEmits(['update:visible', 'success'])
const { proxy } = getCurrentInstance()
const formRef = ref()
const submitLoading = ref(false)
//
const dialogVisible = computed({
get: () => props.visible,
set: (value) => emit('update:visible', value)
})
const isEdit = computed(() => !!props.id)
const title = computed(() => (isEdit.value ? '修改端口' : '添加端口'))
//
const form = ref({
id: null,
name: null,
roomId: null,
roomName: null,
rackId: null,
rackName: null,
frameId: null,
frameName: null,
deptId: null,
rowNumber: null,
portNumber: null,
status: null,
opticalAttenuation: null,
remarks: null,
historyRemarks: null,
createdAt: null,
updatedAt: null
})
//
const rules = {
name: [{ required: true, message: '端口名称不能为空', trigger: 'blur' }],
roomName: [{ required: true, message: '机房名称不能为空', trigger: 'blur' }],
rackName: [{ required: true, message: '机架名称不能为空', trigger: 'blur' }],
frameName: [{ required: true, message: '框名称不能为空', trigger: 'blur' }],
rowNumber: [{ required: true, message: '行号不能为空', trigger: 'blur', type: 'number' }],
portNumber: [{ required: true, message: '列号不能为空', trigger: 'blur', type: 'number' }],
status: [{ required: true, message: '连接状态', trigger: 'blur', type: 'number' }]
}
//
const options = reactive({
odf_ports_status: []
})
//
var dictParams = ['odf_ports_status']
proxy.getDicts(dictParams).then((response) => {
response.data.forEach((element) => {
options[element.dictType] = element.list
})
})
//
function resetForm() {
form.value = {
id: null,
name: null,
roomId: null,
roomName: null,
rackId: null,
rackName: null,
frameId: null,
frameName: null,
deptId: null,
rowNumber: null,
portNumber: null,
status: null,
opticalAttenuation: null,
remarks: null,
historyRemarks: null,
createdAt: null,
updatedAt: null
}
nextTick(() => {
proxy.resetForm('formRef')
})
}
//
function loadData() {
if (props.id) {
getOdfPorts(props.id).then((res) => {
const { code, data } = res
if (code == 200) {
form.value = { ...data }
}
})
} else {
resetForm()
}
}
//
function submitForm() {
proxy.$refs['formRef'].validate((valid) => {
if (valid) {
submitLoading.value = true
if (isEdit.value) {
updateOdfPorts(form.value)
.then((res) => {
proxy.$modal.msgSuccess('修改成功')
handleSuccess()
})
.finally(() => {
submitLoading.value = false
})
} else {
addOdfPorts(form.value)
.then((res) => {
proxy.$modal.msgSuccess('新增成功')
handleSuccess()
})
.finally(() => {
submitLoading.value = false
})
}
}
})
}
//
function handleSuccess() {
dialogVisible.value = false
emit('success')
}
//
function handleClose() {
dialogVisible.value = false
resetForm()
}
//
watch(
() => props.visible,
(newVal) => {
if (newVal) {
loadData()
}
}
)
</script>

View File

@ -135,6 +135,7 @@ function handleOutsideClick() {
position: relative;
height: 100%;
overflow-x: hidden;
// padding: 0px;
}
.sidebar-mobile {
.el-drawer__body {

View File

@ -0,0 +1,330 @@
<!--
* @Descripttion: (-信息/odf_frames)
* @Author: (admin)
* @Date: (2025-08-05)
-->
<template>
<div>
<el-form :model="queryParams" label-position="right" inline ref="queryRef" v-show="showSearch" @submit.prevent>
<el-form-item label="ODF机架ID" prop="rackId">
<el-input v-model.number="queryParams.rackId" placeholder="请输入ODF机架ID" />
</el-form-item>
<el-form-item label="名称" prop="portsName">
<el-input v-model="queryParams.portsName" placeholder="请输入名称" />
</el-form-item>
<el-form-item>
<el-button icon="search" type="primary" @click="handleQuery">{{ $t('btn.search') }}</el-button>
<el-button icon="refresh" @click="resetQuery">{{ $t('btn.reset') }}</el-button>
</el-form-item>
</el-form>
<!-- 工具区域 -->
<el-row :gutter="15" class="mb10">
<el-col :span="1.5">
<el-button type="primary" v-hasPermi="['odfframes:add']" plain icon="plus" @click="handleAdd">
{{ $t('btn.add') }}
</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList" :columns="columns"></right-toolbar>
</el-row>
<el-table
:data="dataList"
v-loading="loading"
ref="table"
border
header-cell-class-name="el-table-header-cell"
highlight-current-row
@sort-change="sortChange"
>
<el-table-column prop="id" label="Id" align="center" v-if="columns.showColumn('id')"/>
<el-table-column prop="rackId" label="ODF机架ID" align="center" v-if="columns.showColumn('rackId')"/>
<el-table-column prop="portsName" label="名称" align="center" :show-overflow-tooltip="true" v-if="columns.showColumn('portsName')"/>
<el-table-column prop="sequenceNumber" label="序号" align="center" v-if="columns.showColumn('sequenceNumber')"/>
<el-table-column prop="createdAt" label="创建时间" :show-overflow-tooltip="true" v-if="columns.showColumn('createdAt')"/>
<el-table-column prop="updateAt" label="修改时间" :show-overflow-tooltip="true" v-if="columns.showColumn('updateAt')"/>
<el-table-column label="操作" width="160">
<template #default="scope">
<el-button type="success" size="small" icon="edit" title="编辑" v-hasPermi="['odfframes:edit']" @click="handleUpdate(scope.row)"></el-button>
<el-button type="danger" size="small" icon="delete" title="删除" v-hasPermi="['odfframes:delete']" @click="handleDelete(scope.row)"></el-button>
</template>
</el-table-column>
</el-table>
<pagination :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
<el-dialog :title="title" :lock-scroll="false" v-model="open" >
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
<el-row :gutter="20">
<el-col :lg="12">
<el-form-item label="ODF机架ID" prop="rackId">
<el-input v-model.number="form.rackId" placeholder="请输入ODF机架ID" />
</el-form-item>
</el-col>
<el-col :lg="12">
<el-form-item label="名称" prop="portsName">
<el-input v-model="form.portsName" placeholder="请输入名称" />
</el-form-item>
</el-col>
<el-col :lg="12">
<el-form-item label="所属部门" prop="deptId">
<el-input v-model.number="form.deptId" placeholder="请输入所属部门" />
</el-form-item>
</el-col>
<el-col :lg="12">
<el-form-item label="序号" prop="sequenceNumber">
<el-input v-model.number="form.sequenceNumber" placeholder="请输入序号" />
</el-form-item>
</el-col>
<el-col :lg="12">
<el-form-item label="端口数量" prop="portsCount">
<el-input v-model.number="form.portsCount" placeholder="请输入端口数量" />
</el-form-item>
</el-col>
<el-col :lg="12">
<el-form-item label="列数量" prop="portsCol">
<el-input v-model.number="form.portsCol" placeholder="请输入列数量" />
</el-form-item>
</el-col>
<el-col :lg="12">
<el-form-item label="行数量" prop="portsRow">
<el-input v-model.number="form.portsRow" placeholder="请输入行数量" />
</el-form-item>
</el-col>
<el-col :lg="12">
<el-form-item label="创建时间" prop="createdAt">
<el-date-picker
v-model="form.createdAt"
type="datetime"
placeholder="选择日期时间"
value-format="YYYY-MM-DD HH:mm:ss">
</el-date-picker>
</el-form-item>
</el-col>
<el-col :lg="12">
<el-form-item label="修改时间" prop="updateAt">
<el-date-picker
v-model="form.updateAt"
type="datetime"
placeholder="选择日期时间"
value-format="YYYY-MM-DD HH:mm:ss">
</el-date-picker>
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer v-if="opertype != 3">
<el-button text @click="cancel">{{ $t('btn.cancel') }}</el-button>
<el-button type="primary" :loading="state.submitLoading" @click="submitForm">{{ $t('btn.submit') }}</el-button>
</template>
</el-dialog>
</div>
</template>
<script setup name="odfframes">
import { listOdfFrames,
addOdfFrames, delOdfFrames,
updateOdfFrames,getOdfFrames,
}
from '@/api/business/odfframes.js'
const { proxy } = getCurrentInstance()
const ids = ref([])
const loading = ref(false)
const showSearch = ref(true)
const queryParams = reactive({
pageNum: 1,
pageSize: 10,
sort: 'SequenceNumber',
sortType: 'asc',
rackId: undefined,
portsName: undefined,
})
const columns = ref([
{ visible: true, align: 'center', type: '', prop: 'id', label: 'Id' },
{ visible: true, align: 'center', type: '', prop: 'rackId', label: 'ODF机架ID' ,dictType: 'sql_odf_room' },
{ visible: true, align: 'center', type: '', prop: 'portsName', label: '名称' ,showOverflowTooltip: true },
{ visible: true, align: 'center', type: '', prop: 'sequenceNumber', label: '序号' },
{ visible: false, align: 'center', type: '', prop: 'createdAt', label: '创建时间' ,showOverflowTooltip: true },
{ visible: false, align: 'center', type: '', prop: 'updateAt', label: '修改时间' ,showOverflowTooltip: true },
//{ visible: false, prop: 'actions', label: '', type: 'slot', width: '160' }
])
const total = ref(0)
const dataList = ref([])
const queryRef = ref()
const defaultTime = ref([new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 2, 1, 23, 59, 59)])
var dictParams = [
]
function getList(){
loading.value = true
listOdfFrames(queryParams).then(res => {
const { code, data } = res
if (code == 200) {
dataList.value = data.result
total.value = data.totalNum
loading.value = false
}
})
}
//
function handleQuery() {
queryParams.pageNum = 1
getList()
}
//
function resetQuery(){
proxy.resetForm("queryRef")
handleQuery()
}
//
function sortChange(column) {
var sort = undefined
var sortType = undefined
if (column.prop != null && column.order != null) {
sort = column.prop
sortType = column.order
}
queryParams.sort = sort
queryParams.sortType = sortType
handleQuery()
}
/*************** form操作 ***************/
const formRef = ref()
const title = ref('')
// 1add 2edit 3view
const opertype = ref(0)
const open = ref(false)
const state = reactive({
single: true,
multiple: true,
submitLoading: false,
form: {},
rules: {
rackId: [{ required: true, message: "ODF机架ID不能为空", trigger: "blur" , type: "number" }],
},
options: {
}
})
const { form, rules, options, single, multiple } = toRefs(state)
// dialog
function cancel(){
open.value = false
reset()
}
//
function reset() {
form.value = {
id: null,
rackId: null,
portsName: null,
deptId: null,
sequenceNumber: null,
portsCount: null,
portsCol: null,
portsRow: null,
createdAt: null,
updateAt: null,
};
proxy.resetForm("formRef")
}
//
function handleAdd() {
reset();
open.value = true
state.submitLoading = false
title.value = '添加框-信息'
opertype.value = 1
}
//
function handleUpdate(row) {
reset()
state.submitLoading = false
const id = row.id || ids.value
getOdfFrames(id).then((res) => {
const { code, data } = res
if (code == 200) {
open.value = true
title.value = '修改框-信息'
opertype.value = 2
form.value = {
...data,
}
}
})
}
// &
function submitForm() {
proxy.$refs["formRef"].validate((valid) => {
if (valid) {
state.submitLoading = true
if (form.value.id != undefined && opertype.value === 2) {
updateOdfFrames(form.value).then((res) => {
proxy.$modal.msgSuccess("修改成功")
open.value = false
getList()
})
} else {
addOdfFrames(form.value).then((res) => {
proxy.$modal.msgSuccess("新增成功")
open.value = false
getList()
})
.finally(() => {
setTimeout(() => {
state.submitLoading = false
}, 800)
})
}
}
})
}
//
function handleDelete(row) {
const Ids = row.id || ids.value
proxy
.$confirm('是否确认删除参数编号为"' + Ids + '"的数据项?', "警告", {
confirmButtonText: proxy.$t('common.ok'),
cancelButtonText: proxy.$t('common.cancel'),
type: "warning",
})
.then(function () {
return delOdfFrames(Ids)
})
.then(() => {
getList()
proxy.$modal.msgSuccess("删除成功")
})
}
handleQuery()
</script>

View File

@ -0,0 +1,747 @@
<template>
<div class="app-container">
<el-row :gutter="5">
<!--左侧部门数据-->
<el-col :span="5" :xs="24">
<div class="left-panel">
<div class="head-container">
<el-tree-select
style="width: 100%"
clearable
v-model="selectFrom.deptId"
:data="deptOptions"
:props="{ value: 'id', label: 'label', children: 'children' }"
value-key="key"
placeholder="请选择所属部门"
check-strictly
:render-after-expand="false" />
</div>
<div class="head-container search-container">
<el-input
v-model="selectFrom.selectName"
placeholder="请输入机房名称、备注模糊查询"
clearable
prefix-icon="search"
class="search-input" />
<el-button icon="search" @click="handleSearch" class="search-button" />
</div>
<div class="head-container">
<el-tree
ref="treeRef"
:key="treeKey"
style="width: 100%; max-height: calc(100vh - 320px); overflow-y: auto"
@node-click="handleNodeClick"
:props="props"
:load="loadNode"
:default-expanded-keys="defaultExpandedKeys"
node-key="id"
lazy>
<template #default="{ node, data }">
<div class="custom-tree-node">
<div class="node-label">
<span>{{ node.label }}</span>
</div>
<div class="tree-node-actions">
<el-tooltip v-if="data.level > 0 && data.level < 4" class="box-item" effect="dark" :content="getAddNodeTooltip(node, data)">
<el-icon v-if="data.level > 0 && data.level < 4" @click.stop="handleAddNode(node, data)"><CirclePlus /></el-icon>
</el-tooltip>
<el-icon v-if="data.level > 1 && data.level < 4" @click.stop="handleEditNode(node, data)"><EditPen /></el-icon>
</div>
</div>
</template>
</el-tree>
</div>
</div>
</el-col>
<!--右侧内容区域-->
<el-col :span="19" :xs="24">
<div class="right-content">
<div style="margin-left: 10px; margin-top: 10px">
<el-form :model="queryParams" label-position="right" inline ref="queryRef" v-show="showSearch" @submit.prevent>
<el-form-item label="端口" prop="name">
<el-input v-model="queryParams.name" placeholder="请输入端口" />
</el-form-item>
<el-form-item label="备注" prop="remarks">
<el-input v-model="queryParams.remarks" placeholder="请输入备注" />
</el-form-item>
<el-form-item label="历史故障记录" prop="historyRemarks">
<el-input v-model="queryParams.historyRemarks" placeholder="请输入备注" />
</el-form-item>
<el-form-item>
<el-button icon="search" type="primary" @click="handleQuery">{{ $t('btn.search') }}</el-button>
<el-button icon="refresh" @click="resetQuery">{{ $t('btn.reset') }}</el-button>
</el-form-item>
</el-form>
</div>
<!-- 工具区域 -->
<div class="toolbar-container">
<el-row :gutter="15">
<el-col :span="1.5">
<el-dropdown trigger="click" v-hasPermi="['odfports:import']">
<el-button type="primary" plain icon="Upload">
{{ $t('btn.import') }}<el-icon class="el-icon--right"><arrow-down /></el-icon>
</el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item command="upload">
<importData
templateUrl="business/OdfPorts/importTemplate"
importUrl="/business/OdfPorts/importData"
@success="handleFileSuccess"></importData>
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="download" @click="handleExport" v-hasPermi="['odfports:export']">
{{ $t('btn.export') }}
</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList" :columns="columns"></right-toolbar>
</el-row>
</div>
<!-- 表格区域 -->
<div class="table-container">
<el-table
:data="dataList"
v-loading="loading"
ref="table"
border
header-cell-class-name="el-table-header-cell"
highlight-current-row
height="100%"
@sort-change="sortChange"
@selection-change="handleSelectionChange">
<el-table-column type="selection" width="50" align="center" />
<el-table-column prop="id" label="Id" width="50" align="center" v-if="columns.showColumn('id')" />
<el-table-column
prop="roomName"
min-width="110"
label="机房信息"
align="center"
:show-overflow-tooltip="true"
v-if="columns.showColumn('roomName')">
<template #default="scope">
<div class="room-info">
<div class="info-item">部门{{ scope.row.deptName }}</div>
<div class="info-item">机房{{ scope.row.roomName }}</div>
<div class="info-item">机架{{ scope.row.rackName }}</div>
<div class="info-item">机框{{ scope.row.frameName }}</div>
</div>
</template>
</el-table-column>
<el-table-column prop="name" width="80" label="端口" align="center" :show-overflow-tooltip="true" v-if="columns.showColumn('name')" />
<el-table-column prop="status" width="90" label="连接状态" align="center" v-if="columns.showColumn('status')">
<template #default="scope">
<el-tag :type="scope.row.status === '0' ? 'success' : 'danger'" size="small">
{{ scope.row.status === '0' ? '正常' : '断开' }}
</el-tag>
</template>
</el-table-column>
<el-table-column
prop="opticalAttenuation"
width="80"
label="光衰值dB"
align="center"
:show-overflow-tooltip="true"
v-if="columns.showColumn('opticalAttenuation')" />
<el-table-column
prop="remarks"
min-width="150"
label="备注"
align="center"
:show-overflow-tooltip="true"
v-if="columns.showColumn('remarks')" />
<el-table-column
min-width="150"
prop="historyRemarks"
label="历史故障记录"
align="center"
:show-overflow-tooltip="true"
v-if="columns.showColumn('historyRemarks')" />
<el-table-column prop="createdAt" label="数据信息" width="130" :show-overflow-tooltip="true" v-if="columns.showColumn('createdAt')">
<template #default="scope">
<div class="time-info">
<div class="time-item">创建{{ scope.row.createdAt }}</div>
<div class="time-item">修改{{ scope.row.updatedAt }}</div>
</div>
</template>
</el-table-column>
<el-table-column label="操作" width="80" fixed="right">
<template #default="scope">
<div class="action-buttons">
<el-button
type="success"
size="small"
icon="edit"
title="编辑"
v-hasPermi="['odfports:edit']"
@click="handleUpdate(scope.row)"></el-button>
</div>
</template>
</el-table-column>
</el-table>
</div>
<!-- 分页区域 -->
<div class="pagination-container">
<pagination :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
</div>
</div>
</el-col>
</el-row>
<!-- ODF端口表单组件 -->
<OdfPortForm v-model:visible="formVisible" :id="currentId" @success="handleFormSuccess" />
</div>
</template>
<script setup name="odfIndex">
import { CirclePlus, EditPen } from '@element-plus/icons-vue'
import { getOdfRoomsTreeList } from '@/api/business/odfindex'
import OdfPortForm from '@/components/business/OdfPortForm.vue'
const { proxy } = getCurrentInstance()
import { treeselect } from '@/api/system/dept'
//
const selectTreeName = ref('')
const deptOptions = ref([])
const selectedDept = ref(null)
const formVisible = ref(false)
const currentId = ref(null)
let selectFrom = ref({
deptId: '',
selectName: ''
})
const treeRef = ref(null)
const treeKey = ref(0)
const defaultExpandedKeys = ref(['all-rooms'])
const handleSearch = () => {
// key
treeKey.value++
}
//
function handleFormSuccess() {
getList()
}
const getAddNodeTooltip = (node, data) => {
if (node.level == 1) {
return '添加机房'
}
if (node.level == 2) {
return '添加机架'
}
if (node.level == 3) {
return '添加机框'
}
return ''
}
const handleAddNode = (node, data) => {
console.log(node, data)
}
const handleEditNode = (node, data) => {}
const props = {
label: 'name',
isLeaf: 'leaf'
}
const loadNode = (node, resolve, reject) => {
if (node.level === 0) {
return resolve([
{
id: 'all-rooms',
name: '全部机房',
level: 1
}
])
}
if (node.level >= 1) {
console.log(node.data)
getOdfRoomsTreeList({
level: node.level,
roomId: node.data.roomId,
racksId: node.data.racksId,
framesId: node.data.framesId,
name: selectFrom.value.selectName,
deptId: selectFrom.value.deptId
}).then((res) => {
console.log(res)
// idAPIid
const dataWithIds = res.data.map((item, index) => ({
...item,
id: item.id || `${node.level}-${index}-${Date.now()}`
}))
resolve(dataWithIds)
})
}
}
/** 根据名称筛选部门树 */
watch(selectTreeName, (val) => {
// proxy.$refs['deptTreeRef'].filter(val)
})
/** 查询部门下拉树结构 */
function getTreeselect() {
treeselect().then((response) => {
deptOptions.value = [{ id: 0, label: '未知部门', children: [] }, ...response.data]
})
}
/** 节点单击事件 */
function handleNodeClick(data) {
console.log(data)
queryParams.roomId = data.roomId
queryParams.racksId = data.racksId
queryParams.framesId = data.framesId
queryParams.deptId = data.deptId
handleQuery()
// selectedDept.value = data
// console.log('', data.name)
//
}
import { listOdfPorts, addOdfPorts, delOdfPorts, updateOdfPorts, getOdfPorts } from '@/api/business/odfports.js'
import importData from '@/components/ImportData'
const ids = ref([])
const loading = ref(false)
const showSearch = ref(true)
const queryParams = reactive({
pageNum: 1,
pageSize: 10,
sort: 'Id',
sortType: 'asc',
roomId: null,
racksId: null,
framesId: null,
deptId: null
})
const columns = ref([
{ visible: true, align: 'center', type: '', prop: 'id', label: 'Id' },
{ visible: true, align: 'center', type: '', prop: 'roomName', label: '机房信息', showOverflowTooltip: true },
{ visible: true, align: 'center', type: '', prop: 'name', label: '端口名称', showOverflowTooltip: true },
{ visible: true, align: 'center', type: 'dict', prop: 'status', label: '连接状态0正常1断开' },
{ visible: true, align: 'center', type: '', prop: 'remarks', label: '备注', showOverflowTooltip: true },
{ visible: true, align: 'center', type: '', prop: 'opticalAttenuation', label: '光衰值dB', showOverflowTooltip: true },
{ visible: true, align: 'center', type: '', prop: 'historyRemarks', label: '历史故障表', showOverflowTooltip: true },
{ visible: true, align: 'center', type: '', prop: 'createdAt', label: '数据信息', showOverflowTooltip: true }
//{ visible: false, prop: 'actions', label: '', type: 'slot', width: '160' }
])
const total = ref(0)
const dataList = ref([])
const queryRef = ref()
const defaultTime = ref([new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 2, 1, 23, 59, 59)])
var dictParams = []
function getList() {
loading.value = true
listOdfPorts(queryParams).then((res) => {
const { code, data } = res
if (code == 200) {
dataList.value = data.result
total.value = data.totalNum
loading.value = false
}
})
}
//
function handleQuery() {
queryParams.pageNum = 1
getList()
}
//
function resetQuery() {
proxy.resetForm('queryRef')
handleQuery()
}
const state = reactive({
single: true,
multiple: true,
submitLoading: false,
form: {},
rules: {
name: [{ required: true, message: '端口名称不能为空', trigger: 'blur' }],
roomId: [{ required: true, message: '机房ID不能为空', trigger: 'blur', type: 'number' }],
roomName: [{ required: true, message: '机房名称不能为空', trigger: 'blur' }],
rackId: [{ required: true, message: '机架ID不能为空', trigger: 'blur', type: 'number' }],
rackName: [{ required: true, message: '机架名称不能为空', trigger: 'blur' }],
frameId: [{ required: true, message: '框ID不能为空', trigger: 'blur', type: 'number' }],
frameName: [{ required: true, message: '框名称不能为空', trigger: 'blur' }],
deptId: [{ required: true, message: '部门ID不能为空', trigger: 'blur', type: 'number' }],
rowNumber: [{ required: true, message: '行号1-6不能为空', trigger: 'blur', type: 'number' }],
portNumber: [{ required: true, message: '端口号1-12不能为空', trigger: 'blur', type: 'number' }],
createdAt: [{ required: true, message: '创建时间不能为空', trigger: 'blur' }],
updatedAt: [{ required: true, message: '修改时间不能为空', trigger: 'blur' }]
},
options: {
// 01 eg:{ dictLabel: '', dictValue: '0'}
statusOptions: []
}
})
const { form, rules, options, single, multiple } = toRefs(state)
//
function handleSelectionChange(selection) {
ids.value = selection.map((item) => item.id)
single.value = selection.length != 1
multiple.value = !selection.length
}
//
function sortChange(column) {
var sort = undefined
var sortType = undefined
if (column.prop != null && column.order != null) {
sort = column.prop
sortType = column.order
}
queryParams.sort = sort
queryParams.sortType = sortType
handleQuery()
}
//
function handleAdd() {
console.log('添加功能')
}
//
function handleUpdate(row) {
console.log(row)
const id = row?.id
currentId.value = id
formVisible.value = true
}
function handleDelete(row) {
console.log('删除功能', row)
}
function handleFileSuccess() {
console.log('文件上传成功')
getList()
}
//
function handleExport() {
proxy
.$confirm('是否确认导出端口数据项?', '警告', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(async () => {
await proxy.downFile('/business/OdfPorts/export', { ...queryParams })
})
}
//
getTreeselect()
handleQuery()
</script>
<style scoped>
.app-container {
padding: 0px;
background-color: #f8f9fa;
min-height: calc(100vh - 160px);
border-radius: 8px;
}
.head-container {
margin-bottom: 0px;
background: #ffffff;
padding: 7px;
border-radius: 8px;
/* box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
border: 1px solid #e4e7ed; */
}
.custom-tree-node {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
padding: 4px 8px;
border-radius: 6px;
transition: all 0.2s ease;
}
.custom-tree-node:hover {
background-color: #f0f9ff;
}
.custom-tree-node .node-label {
width: 75%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 14px;
color: #303133;
}
.content-area {
height: calc(100vh - 160px);
background: #ffffff;
border-radius: 8px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
border: 1px solid #e4e7ed;
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 16px 20px;
border-bottom: 1px solid #e4e7ed;
background: #fafafa;
}
.content-body {
min-height: 400px;
padding: 20px;
}
.placeholder-content {
margin-top: 50px;
}
.search-container {
display: flex;
gap: 8px;
align-items: center;
}
.search-input {
flex: 1;
}
.el-form-item {
margin-bottom: 5px;
}
.search-button {
flex-shrink: 0;
width: 40px;
height: 32px;
}
.tree-node-actions {
display: flex;
gap: 8px;
align-items: center;
opacity: 0;
transition: opacity 0.2s ease;
}
.custom-tree-node:hover .tree-node-actions {
opacity: 1;
}
/* .tree-node-actions .el-icon {
cursor: pointer;
padding: 6px;
border-radius: 4px;
transition: all 0.2s ease;
color: #606266;
font-size: 14px;
} */
.tree-node-actions .el-icon:hover {
/* background-color: #409eff; */
/* color: #ffffff; */
transform: scale(1.1);
}
/* 左侧面板样式 */
.left-panel {
background: #ffffff;
border-radius: 8px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
border: 1px solid #e4e7ed;
height: calc(100vh - 160px);
overflow: hidden;
}
/* 右侧内容区域样式 */
.right-content {
background: #ffffff;
border-radius: 8px;
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
border: 1px solid #e4e7ed;
height: calc(100vh - 160px);
display: flex;
flex-direction: column;
}
/* 工具栏样式 */
.toolbar-container {
padding: 6px 20px;
border-bottom: 1px solid #e4e7ed;
background: #fafbfc;
border-radius: 8px 8px 0 0;
}
/* 表格容器样式 */
.table-container {
flex: 1;
/* padding: 0 20px 20px 20px; */
overflow: auto;
}
/* 分页样式 */
.pagination-container {
padding: 16px 20px;
border-top: 1px solid #e4e7ed;
background: #fafbfc;
border-radius: 0 0 8px 8px;
}
/* 表格内容样式 */
.room-info {
text-align: left;
line-height: 1.4;
}
.info-item {
font-size: 12px;
color: #606266;
margin-bottom: 2px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.info-item:last-child {
margin-bottom: 0;
}
.time-info {
text-align: left;
line-height: 1.4;
}
.time-item {
font-size: 11px;
color: #909399;
margin-bottom: 2px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.time-item:last-child {
margin-bottom: 0;
}
.action-buttons {
display: flex;
gap: 4px;
justify-content: center;
}
.action-buttons .el-button {
padding: 5px 8px;
min-height: auto;
}
/* 表格样式优化 */
:deep(.el-table) {
border-radius: 6px;
overflow: hidden;
}
:deep(.el-table__header-wrapper) {
background: #f8f9fa;
}
:deep(.el-table th.el-table__cell) {
background: #f8f9fa;
color: #303133;
font-weight: 600;
border-bottom: 1px solid #e4e7ed;
}
:deep(.el-table td.el-table__cell) {
border-bottom: 1px solid #f0f2f5;
}
:deep(.el-table__row:hover > td.el-table__cell) {
background-color: #f5f7fa;
}
/* Element Plus组件样式优化 */
:deep(.el-tree-node__content) {
height: 36px;
border-radius: 4px;
margin: 2px 0;
}
:deep(.el-tree-node__content:hover) {
background-color: #f0f9ff;
}
:deep(.el-tree-select .el-select__wrapper) {
border-radius: 6px;
}
:deep(.el-input__wrapper) {
border-radius: 6px;
}
:deep(.el-button) {
border-radius: 6px;
}
/* 响应式设计 */
@media (max-width: 768px) {
.app-container {
padding: 12px;
}
.head-container {
padding: 8px;
margin-bottom: 12px;
}
.left-panel,
.right-content {
height: auto;
margin-bottom: 16px;
}
.search-container {
flex-direction: column;
gap: 12px;
}
.search-input {
width: 100%;
}
.search-button {
width: 100%;
height: 36px;
}
.toolbar-container {
padding: 12px;
}
.table-container {
padding: 0 12px 12px 12px;
}
.pagination-container {
padding: 12px;
}
}
</style>

View File

@ -0,0 +1,291 @@
<!--
* @Descripttion: (端口/odf_ports)
* @Author: (admin)
* @Date: (2025-08-06)
-->
<template>
<div>
<el-form :model="queryParams" label-position="right" inline ref="queryRef" v-show="showSearch" @submit.prevent>
<el-form-item>
<el-button icon="search" type="primary" @click="handleQuery">{{ $t('btn.search') }}</el-button>
<el-button icon="refresh" @click="resetQuery">{{ $t('btn.reset') }}</el-button>
</el-form-item>
</el-form>
<!-- 工具区域 -->
<el-row :gutter="15" class="mb10">
<el-col :span="1.5">
<el-button type="primary" v-hasPermi="['odfports:add']" plain icon="plus" @click="handleAdd">
{{ $t('btn.add') }}
</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" :disabled="single" v-hasPermi="['odfports:edit']" plain icon="edit" @click="handleUpdate">
{{ $t('btn.edit') }}
</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" :disabled="multiple" v-hasPermi="['odfports:delete']" plain icon="delete" @click="handleDelete">
{{ $t('btn.delete') }}
</el-button>
</el-col>
<el-col :span="1.5">
<el-dropdown trigger="click" v-hasPermi="['odfports:import']">
<el-button type="primary" plain icon="Upload">
{{ $t('btn.import') }}<el-icon class="el-icon--right"><arrow-down /></el-icon>
</el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item command="upload">
<importData
templateUrl="business/OdfPorts/importTemplate"
importUrl="/business/OdfPorts/importData"
@success="handleFileSuccess"></importData>
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="download" @click="handleExport" v-hasPermi="['odfports:export']">
{{ $t('btn.export') }}
</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList" :columns="columns"></right-toolbar>
</el-row>
<el-table
:data="dataList"
v-loading="loading"
ref="table"
border
header-cell-class-name="el-table-header-cell"
highlight-current-row
@sort-change="sortChange"
@selection-change="handleSelectionChange">
<el-table-column type="selection" width="50" align="center" />
<el-table-column prop="id" label="Id" align="center" v-if="columns.showColumn('id')" />
<el-table-column prop="name" label="端口名称" align="center" :show-overflow-tooltip="true" v-if="columns.showColumn('name')" />
<el-table-column prop="roomId" label="机房ID" align="center" v-if="columns.showColumn('roomId')" />
<el-table-column prop="roomName" label="机房名称" align="center" :show-overflow-tooltip="true" v-if="columns.showColumn('roomName')" />
<el-table-column prop="rackId" label="机架ID" align="center" v-if="columns.showColumn('rackId')" />
<el-table-column prop="rackName" label="机架名称" align="center" :show-overflow-tooltip="true" v-if="columns.showColumn('rackName')" />
<el-table-column prop="frameId" label="框ID" align="center" v-if="columns.showColumn('frameId')" />
<el-table-column prop="frameName" label="框名称" align="center" :show-overflow-tooltip="true" v-if="columns.showColumn('frameName')" />
<el-table-column prop="deptId" label="部门ID" align="center" v-if="columns.showColumn('deptId')" />
<el-table-column prop="rowNumber" label="行号1-6" align="center" v-if="columns.showColumn('rowNumber')" />
<el-table-column prop="portNumber" label="端口号1-12" align="center" v-if="columns.showColumn('portNumber')" />
<el-table-column prop="status" label="连接状态0正常1断开" align="center" v-if="columns.showColumn('status')">
<template #default="scope">
<dict-tag :options="options.odf_ports_status" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column
prop="opticalAttenuation"
label="光衰值dB"
align="center"
:show-overflow-tooltip="true"
v-if="columns.showColumn('opticalAttenuation')" />
<el-table-column prop="remarks" label="备注" align="center" :show-overflow-tooltip="true" v-if="columns.showColumn('remarks')" />
<el-table-column
prop="historyRemarks"
label="历史故障表"
align="center"
:show-overflow-tooltip="true"
v-if="columns.showColumn('historyRemarks')" />
<el-table-column label="操作" width="160">
<template #default="scope">
<el-button
type="success"
size="small"
icon="edit"
title="编辑"
v-hasPermi="['odfports:edit']"
@click="handleUpdate(scope.row)"></el-button>
<el-button
type="danger"
size="small"
icon="delete"
title="删除"
v-hasPermi="['odfports:delete']"
@click="handleDelete(scope.row)"></el-button>
</template>
</el-table-column>
</el-table>
<pagination :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
<!-- ODF端口表单组件 -->
<OdfPortForm v-model:visible="formVisible" :id="currentId" @success="handleFormSuccess" />
</div>
</template>
<script setup name="odfports">
import { listOdfPorts, delOdfPorts } from '@/api/business/odfports.js'
import importData from '@/components/ImportData'
import OdfPortForm from '@/components/business/OdfPortForm.vue'
const { proxy } = getCurrentInstance()
const ids = ref([])
const loading = ref(false)
const showSearch = ref(true)
const formVisible = ref(false)
const currentId = ref(null)
const queryParams = reactive({
pageNum: 1,
pageSize: 10,
sort: 'Id',
sortType: 'asc'
})
const columns = ref([
{ visible: true, align: 'center', type: '', prop: 'id', label: 'Id' },
{ visible: true, align: 'center', type: '', prop: 'name', label: '端口名称', showOverflowTooltip: true },
{ visible: true, align: 'center', type: '', prop: 'roomId', label: '机房ID' },
{ visible: true, align: 'center', type: '', prop: 'roomName', label: '机房名称', showOverflowTooltip: true },
{ visible: true, align: 'center', type: '', prop: 'rackId', label: '机架ID' },
{ visible: true, align: 'center', type: '', prop: 'rackName', label: '机架名称', showOverflowTooltip: true },
{ visible: true, align: 'center', type: '', prop: 'frameId', label: '框ID' },
{ visible: true, align: 'center', type: '', prop: 'frameName', label: '框名称', showOverflowTooltip: true },
{ visible: false, align: 'center', type: '', prop: 'deptId', label: '部门ID' },
{ visible: false, align: 'center', type: '', prop: 'rowNumber', label: '行号1-6' },
{ visible: false, align: 'center', type: '', prop: 'portNumber', label: '端口号1-12' },
{ visible: false, align: 'center', type: 'dict', prop: 'status', label: '连接状态0正常1断开', dictType: 'odf_ports_status' },
{ visible: false, align: 'center', type: '', prop: 'opticalAttenuation', label: '光衰值dB', showOverflowTooltip: true },
{ visible: false, align: 'center', type: '', prop: 'remarks', label: '备注', showOverflowTooltip: true },
{ visible: false, align: 'center', type: '', prop: 'historyRemarks', label: '历史故障表', showOverflowTooltip: true }
//{ visible: false, prop: 'actions', label: '', type: 'slot', width: '160' }
])
const total = ref(0)
const dataList = ref([])
const queryRef = ref()
const defaultTime = ref([new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 2, 1, 23, 59, 59)])
var dictParams = ['odf_ports_status']
const state = reactive({
single: true,
multiple: true,
options: {
odf_ports_status: []
}
})
const { single, multiple, options } = toRefs(state)
proxy.getDicts(dictParams).then((response) => {
response.data.forEach((element) => {
state.options[element.dictType] = element.list
})
})
function getList() {
loading.value = true
listOdfPorts(queryParams).then((res) => {
const { code, data } = res
if (code == 200) {
dataList.value = data.result
total.value = data.totalNum
loading.value = false
}
})
}
//
function handleQuery() {
queryParams.pageNum = 1
getList()
}
//
function resetQuery() {
proxy.resetForm('queryRef')
handleQuery()
}
//
function handleSelectionChange(selection) {
ids.value = selection.map((item) => item.id)
state.single = selection.length != 1
state.multiple = !selection.length
}
//
function sortChange(column) {
var sort = undefined
var sortType = undefined
if (column.prop != null && column.order != null) {
sort = column.prop
sortType = column.order
}
queryParams.sort = sort
queryParams.sortType = sortType
handleQuery()
}
//
function handleAdd() {
currentId.value = null
formVisible.value = true
}
//
function handleUpdate(row) {
const id = row?.id || ids.value[0]
currentId.value = id
formVisible.value = true
}
//
function handleFormSuccess() {
getList()
}
//
function handleDelete(row) {
const Ids = row.id || ids.value
proxy
.$confirm('是否确认删除参数编号为"' + Ids + '"的数据项?', '警告', {
confirmButtonText: proxy.$t('common.ok'),
cancelButtonText: proxy.$t('common.cancel'),
type: 'warning'
})
.then(function () {
return delOdfPorts(Ids)
})
.then(() => {
getList()
proxy.$modal.msgSuccess('删除成功')
})
}
//
const handleFileSuccess = (response) => {
const { item1, item2 } = response.data
var error = ''
item2.forEach((item) => {
error += item.storageMessage + ','
})
proxy.$alert(item1 + '<p>' + error + '</p>', '导入结果', {
dangerouslyUseHTMLString: true
})
getList()
}
//
function handleExport() {
proxy
.$confirm('是否确认导出端口数据项?', '警告', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(async () => {
await proxy.downFile('/business/OdfPorts/export', { ...queryParams })
})
}
handleQuery()
</script>

View File

@ -0,0 +1,382 @@
<!--
* @Descripttion: (机架列表/odf_racks)
* @Author: (admin)
* @Date: (2025-08-05)
-->
<template>
<div>
<el-form :model="queryParams" label-position="right" inline ref="queryRef" v-show="showSearch" @submit.prevent>
<el-form-item label="机房" prop="roomId">
<el-select clearable v-model="queryParams.roomId" placeholder="请选择机房">
<el-option v-for="item in options.sql_odf_room" :key="item.dictValue" :label="item.dictLabel" :value="item.dictValue">
<span class="fl">{{ item.dictLabel }}</span>
<span class="fr" style="color: var(--el-text-color-secondary)">{{ item.dictValue }}</span>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="ODF名称" prop="rackName">
<el-input v-model="queryParams.rackName" placeholder="请输入ODF名称" />
</el-form-item>
<el-form-item>
<el-button icon="search" type="primary" @click="handleQuery">{{ $t('btn.search') }}</el-button>
<el-button icon="refresh" @click="resetQuery">{{ $t('btn.reset') }}</el-button>
</el-form-item>
</el-form>
<!-- 工具区域 -->
<el-row :gutter="15" class="mb10">
<el-col :span="1.5">
<el-button type="primary" v-hasPermi="['odfracks:add']" plain icon="plus" @click="handleAdd">
{{ $t('btn.add') }}
</el-button>
</el-col>
<el-col :span="1.5">
<el-dropdown trigger="click" v-hasPermi="['odfracks:import']">
<el-button type="primary" plain icon="Upload">
{{ $t('btn.import') }}<el-icon class="el-icon--right"><arrow-down /></el-icon>
</el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item command="upload">
<importData
templateUrl="business/OdfRacks/importTemplate"
importUrl="/business/OdfRacks/importData"
@success="handleFileSuccess"></importData>
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="download" @click="handleExport" v-hasPermi="['odfracks:export']">
{{ $t('btn.export') }}
</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList" :columns="columns"></right-toolbar>
</el-row>
<el-table
:data="dataList"
v-loading="loading"
ref="table"
border
header-cell-class-name="el-table-header-cell"
highlight-current-row
@sort-change="sortChange">
<el-table-column prop="id" label="Id" align="center" v-if="columns.showColumn('id')" />
<el-table-column prop="roomId" label="机房" align="center" v-if="columns.showColumn('roomId')">
<template #default="scope">
<dict-tag :options="options.sql_odf_room" :value="scope.row.roomId" />
</template>
</el-table-column>
<el-table-column prop="sequenceNumber" label="序号" align="center" v-if="columns.showColumn('sequenceNumber')" />
<el-table-column prop="rackName" label="ODF名称" align="center" :show-overflow-tooltip="true" v-if="columns.showColumn('rackName')" />
<el-table-column prop="frameCount" label="框数量固定9框" align="center" v-if="columns.showColumn('frameCount')" />
<el-table-column prop="createdAt" label="创建时间" :show-overflow-tooltip="true" v-if="columns.showColumn('createdAt')" />
<el-table-column prop="updatedAt" label="修改时间" :show-overflow-tooltip="true" v-if="columns.showColumn('updatedAt')" />
<el-table-column label="操作" width="160">
<template #default="scope">
<el-button
type="success"
size="small"
icon="edit"
title="编辑"
v-hasPermi="['odfracks:edit']"
@click="handleUpdate(scope.row)"></el-button>
<el-button
type="danger"
size="small"
icon="delete"
title="删除"
v-hasPermi="['odfracks:delete']"
@click="handleDelete(scope.row)"></el-button>
</template>
</el-table-column>
</el-table>
<pagination :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
<el-dialog :title="title" :lock-scroll="false" v-model="open">
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
<el-row :gutter="20">
<el-col :lg="12">
<el-form-item label="机房" prop="roomId">
<el-select v-model="form.roomId" placeholder="请选择机房">
<el-option
v-for="item in options.sql_odf_room"
:key="item.dictValue"
:label="item.dictLabel"
:value="parseInt(item.dictValue)"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :lg="12">
<el-form-item label="序号" prop="sequenceNumber">
<el-input-number v-model.number="form.sequenceNumber" :controls="true" controls-position="right" placeholder="请输入序号" />
</el-form-item>
</el-col>
<el-col :lg="12">
<el-form-item label="ODF名称" prop="rackName">
<el-input v-model="form.rackName" placeholder="请输入ODF名称" />
</el-form-item>
</el-col>
<el-col :lg="12">
<el-form-item label="框数量固定9框" prop="frameCount">
<el-input v-model.number="form.frameCount" placeholder="请输入框数量固定9框" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer v-if="opertype != 3">
<el-button text @click="cancel">{{ $t('btn.cancel') }}</el-button>
<el-button type="primary" :loading="state.submitLoading" @click="submitForm">{{ $t('btn.submit') }}</el-button>
</template>
</el-dialog>
</div>
</template>
<script setup name="odfracks">
import { listOdfRacks, addOdfRacks, delOdfRacks, updateOdfRacks, getOdfRacks } from '@/api/business/odfracks.js'
import { treeselect } from '@/api/system/dept'
import importData from '@/components/ImportData'
const { proxy } = getCurrentInstance()
const ids = ref([])
const loading = ref(false)
const showSearch = ref(true)
const queryParams = reactive({
pageNum: 1,
pageSize: 10,
sort: 'SequenceNumber',
sortType: 'asc',
roomId: undefined,
rackName: undefined
})
const columns = ref([
{ visible: true, align: 'center', type: '', prop: 'id', label: 'Id' },
{ visible: true, align: 'center', type: 'dict', prop: 'roomId', label: '机房', dictType: 'sql_odf_room' },
{ visible: true, align: 'center', type: '', prop: 'sequenceNumber', label: '序号' },
{ visible: true, align: 'center', type: '', prop: 'rackName', label: 'ODF名称', showOverflowTooltip: true },
{ visible: true, align: 'center', type: '', prop: 'frameCount', label: '框数量固定9框' },
{ visible: true, align: 'center', type: '', prop: 'createdAt', label: '创建时间', showOverflowTooltip: true },
{ visible: true, align: 'center', type: '', prop: 'updatedAt', label: '修改时间', showOverflowTooltip: true }
//{ visible: false, prop: 'actions', label: '', type: 'slot', width: '160' }
])
const deptOptions = ref([])
/** 查询部门下拉树结构 */
function getTreeselect() {
treeselect().then((response) => {
deptOptions.value = [{ id: 0, label: '未知部门', children: [] }, ...response.data]
})
}
/** 初始化部门数据 */
function initTreeData() {
//
if (deptOptions.value === undefined) {
treeselect().then((response) => {
deptOptions.value = response.data
})
}
}
const total = ref(0)
const dataList = ref([])
const queryRef = ref()
const defaultTime = ref([new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 2, 1, 23, 59, 59)])
var dictParams = ['sql_odf_room']
proxy.getDicts(dictParams).then((response) => {
response.data.forEach((element) => {
state.options[element.dictType] = element.list
})
})
function getList() {
loading.value = true
listOdfRacks(queryParams).then((res) => {
const { code, data } = res
if (code == 200) {
dataList.value = data.result
total.value = data.totalNum
loading.value = false
}
})
}
//
function handleQuery() {
queryParams.pageNum = 1
getList()
}
//
function resetQuery() {
proxy.resetForm('queryRef')
handleQuery()
}
//
function sortChange(column) {
var sort = undefined
var sortType = undefined
if (column.prop != null && column.order != null) {
sort = column.prop
sortType = column.order
}
queryParams.sort = sort
queryParams.sortType = sortType
handleQuery()
}
/*************** form操作 ***************/
const formRef = ref()
const title = ref('')
// 1add 2edit 3view
const opertype = ref(0)
const open = ref(false)
const state = reactive({
single: true,
multiple: true,
submitLoading: false,
form: {},
rules: {
roomId: [{ required: true, message: '机房不能为空', trigger: 'change', type: 'number' }],
sequenceNumber: [{ required: true, message: '序号不能为空', trigger: 'blur', type: 'number' }],
rackName: [{ required: true, message: 'ODF名称不能为空', trigger: 'blur' }]
},
options: {
// eg:{ dictLabel: '', dictValue: '0'}
sql_odf_room: []
}
})
const { form, rules, options, single, multiple } = toRefs(state)
// dialog
function cancel() {
open.value = false
reset()
}
//
function reset() {
form.value = {
id: null,
roomId: null,
sequenceNumber: null,
rackName: null,
frameCount: null,
createdAt: null,
updatedAt: null
}
proxy.resetForm('formRef')
}
//
function handleAdd() {
reset()
initTreeData()
open.value = true
state.submitLoading = false
title.value = '添加机架列表'
opertype.value = 1
}
//
function handleUpdate(row) {
reset()
initTreeData()
state.submitLoading = false
const id = row.id || ids.value
getOdfRacks(id).then((res) => {
const { code, data } = res
if (code == 200) {
open.value = true
title.value = '修改机架列表'
opertype.value = 2
form.value = {
...data
}
}
})
}
// &
function submitForm() {
proxy.$refs['formRef'].validate((valid) => {
if (valid) {
state.submitLoading = true
if (form.value.id != undefined && opertype.value === 2) {
updateOdfRacks(form.value).then((res) => {
proxy.$modal.msgSuccess('修改成功')
open.value = false
getList()
})
} else {
addOdfRacks(form.value)
.then((res) => {
proxy.$modal.msgSuccess('新增成功')
open.value = false
getList()
})
.finally(() => {
setTimeout(() => {
state.submitLoading = false
}, 800)
})
}
}
})
}
//
function handleDelete(row) {
const Ids = row.id || ids.value
proxy
.$confirm('是否确认删除参数编号为"' + Ids + '"的数据项?', '警告', {
confirmButtonText: proxy.$t('common.ok'),
cancelButtonText: proxy.$t('common.cancel'),
type: 'warning'
})
.then(function () {
return delOdfRacks(Ids)
})
.then(() => {
getList()
proxy.$modal.msgSuccess('删除成功')
})
}
//
const handleFileSuccess = (response) => {
const { item1, item2 } = response.data
var error = ''
item2.forEach((item) => {
error += item.storageMessage + ','
})
proxy.$alert(item1 + '<p>' + error + '</p>', '导入结果', {
dangerouslyUseHTMLString: true
})
getList()
}
//
function handleExport() {
proxy
.$confirm('是否确认导出机架列表数据项?', '警告', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(async () => {
await proxy.downFile('/business/OdfRacks/export', { ...queryParams })
})
}
getTreeselect()
handleQuery()
</script>

View File

@ -0,0 +1,415 @@
<!--
* @Descripttion: (机房列表/odf_rooms)
* @Author: (admin)
* @Date: (2025-08-05)
-->
<template>
<div>
<el-form :model="queryParams" label-position="right" inline ref="queryRef" v-show="showSearch" @submit.prevent>
<el-form-item label="机房名称" prop="roomName">
<el-input v-model="queryParams.roomName" placeholder="请输入机房名称" />
</el-form-item>
<el-form-item label="机房位置" prop="roomAddress">
<el-input v-model="queryParams.roomAddress" placeholder="请输入机房位置" />
</el-form-item>
<el-form-item label="备注" prop="remarks">
<el-input v-model="queryParams.remarks" placeholder="请输入备注" />
</el-form-item>
<el-form-item>
<el-button icon="search" type="primary" @click="handleQuery">{{ $t('btn.search') }}</el-button>
<el-button icon="refresh" @click="resetQuery">{{ $t('btn.reset') }}</el-button>
</el-form-item>
</el-form>
<!-- 工具区域 -->
<el-row :gutter="15" class="mb10">
<el-col :span="1.5">
<el-button type="primary" v-hasPermi="['odfrooms:add']" plain icon="plus" @click="handleAdd">
{{ $t('btn.add') }}
</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="success" :disabled="single" v-hasPermi="['odfrooms:edit']" plain icon="edit" @click="handleUpdate">
{{ $t('btn.edit') }}
</el-button>
</el-col>
<el-col :span="1.5">
<el-button type="danger" :disabled="multiple" v-hasPermi="['odfrooms:delete']" plain icon="delete" @click="handleDelete">
{{ $t('btn.delete') }}
</el-button>
</el-col>
<el-col :span="1.5">
<el-dropdown trigger="click" v-hasPermi="['odfrooms:import']">
<el-button type="primary" plain icon="Upload">
{{ $t('btn.import') }}<el-icon class="el-icon--right"><arrow-down /></el-icon>
</el-button>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item command="upload">
<importData
templateUrl="business/OdfRooms/importTemplate"
importUrl="/business/OdfRooms/importData"
@success="handleFileSuccess"></importData>
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</el-col>
<el-col :span="1.5">
<el-button type="warning" plain icon="download" @click="handleExport" v-hasPermi="['odfrooms:export']">
{{ $t('btn.export') }}
</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList" :columns="columns"></right-toolbar>
</el-row>
<el-table
:data="dataList"
v-loading="loading"
ref="table"
border
header-cell-class-name="el-table-header-cell"
highlight-current-row
@sort-change="sortChange"
@selection-change="handleSelectionChange">
<el-table-column type="selection" width="50" align="center" />
<el-table-column prop="id" label="Id" align="center" v-if="columns.showColumn('id')" />
<el-table-column prop="deptName" label="部门名称" align="center" :show-overflow-tooltip="true" v-if="columns.showColumn('deptName')" />
<el-table-column prop="roomName" label="机房名称" align="center" :show-overflow-tooltip="true" v-if="columns.showColumn('roomName')" />
<el-table-column prop="roomAddress" label="机房位置" align="center" :show-overflow-tooltip="true" v-if="columns.showColumn('roomAddress')" />
<el-table-column prop="racksCount" label="机架数量" align="center" v-if="columns.showColumn('racksCount')" />
<el-table-column prop="remarks" label="备注" align="center" :show-overflow-tooltip="true" v-if="columns.showColumn('remarks')" />
<el-table-column prop="createdAt" label="创建时间" :show-overflow-tooltip="true" v-if="columns.showColumn('createdAt')" />
<el-table-column prop="updatedAt" label="修改时间" :show-overflow-tooltip="true" v-if="columns.showColumn('updatedAt')" />
<el-table-column label="操作" width="160">
<template #default="scope">
<el-button type="primary" size="small" icon="view" title="详情" @click="handlePreview(scope.row)"></el-button>
<el-button
type="success"
size="small"
icon="edit"
title="编辑"
v-hasPermi="['odfrooms:edit']"
@click="handleUpdate(scope.row)"></el-button>
<el-button
type="danger"
size="small"
icon="delete"
title="删除"
v-hasPermi="['odfrooms:delete']"
@click="handleDelete(scope.row)"></el-button>
</template>
</el-table-column>
</el-table>
<pagination :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
<el-dialog :title="title" :lock-scroll="false" v-model="open">
<el-form ref="formRef" :model="form" :rules="rules" label-width="100px">
<el-row :gutter="20">
<el-col :lg="12">
<el-form-item label="机房名称" prop="roomName">
<el-input v-model="form.roomName" placeholder="请输入机房名称" />
</el-form-item>
</el-col>
<el-col :lg="12">
<el-form-item label="所属部门" prop="deptId">
<el-tree-select
v-model="form.deptId"
:data="deptOptions"
:props="{ value: 'id', label: 'label', children: 'children' }"
value-key="id"
placeholder="请选择所属部门"
check-strictly
:render-after-expand="false" />
</el-form-item>
</el-col>
<el-col :lg="24">
<el-form-item label="机房位置" prop="roomAddress">
<el-input v-model="form.roomAddress" placeholder="请输入机房位置" />
</el-form-item>
</el-col>
<el-col :lg="24">
<el-form-item label="机架数量" prop="racksCount">
<el-input v-model.number="form.racksCount" placeholder="请输入机架数量" />
</el-form-item>
</el-col>
<el-col :lg="24">
<el-form-item label="备注" prop="remarks">
<el-input v-model="form.remarks" placeholder="请输入备注" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<template #footer v-if="opertype != 3">
<el-button text @click="cancel">{{ $t('btn.cancel') }}</el-button>
<el-button type="primary" :loading="state.submitLoading" @click="submitForm">{{ $t('btn.submit') }}</el-button>
</template>
</el-dialog>
</div>
</template>
<script setup name="odfrooms">
import { listOdfRooms, addOdfRooms, delOdfRooms, updateOdfRooms, getOdfRooms } from '@/api/business/odfrooms.js'
import importData from '@/components/ImportData'
import { treeselect } from '@/api/system/dept'
const { proxy } = getCurrentInstance()
const ids = ref([])
const loading = ref(false)
const showSearch = ref(true)
const queryParams = reactive({
pageNum: 1,
pageSize: 10,
sort: 'Id',
sortType: 'desc',
roomName: undefined,
roomAddress: undefined,
remarks: undefined
})
const columns = ref([
{ visible: true, align: 'center', type: '', prop: 'id', label: 'Id' },
{ visible: true, align: 'center', type: '', prop: 'deptName', label: '部门名称', showOverflowTooltip: true },
{ visible: true, align: 'center', type: '', prop: 'roomName', label: '机房名称', showOverflowTooltip: true },
{ visible: true, align: 'center', type: '', prop: 'roomAddress', label: '机房位置', showOverflowTooltip: true },
{ visible: true, align: 'center', type: '', prop: 'racksCount', label: '机架数量' },
{ visible: true, align: 'center', type: '', prop: 'remarks', label: '备注', showOverflowTooltip: true },
{ visible: true, align: 'center', type: '', prop: 'createdAt', label: '创建时间', showOverflowTooltip: true },
{ visible: false, align: 'center', type: '', prop: 'updatedAt', label: '修改时间', showOverflowTooltip: true }
//{ visible: false, prop: 'actions', label: '', type: 'slot', width: '160' }
])
const total = ref(0)
const dataList = ref([])
const queryRef = ref()
const defaultTime = ref([new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 2, 1, 23, 59, 59)])
const deptOptions = ref([])
/** 查询部门下拉树结构 */
function getTreeselect() {
treeselect().then((response) => {
deptOptions.value = [{ id: 0, label: '未知部门', children: [] }, ...response.data]
})
}
/** 初始化部门数据 */
function initTreeData() {
//
if (deptOptions.value === undefined) {
treeselect().then((response) => {
deptOptions.value = response.data
})
}
}
var dictParams = []
function getList() {
loading.value = true
listOdfRooms(queryParams).then((res) => {
const { code, data } = res
if (code == 200) {
dataList.value = data.result
total.value = data.totalNum
loading.value = false
}
})
}
//
function handleQuery() {
queryParams.pageNum = 1
getList()
}
//
function resetQuery() {
proxy.resetForm('queryRef')
handleQuery()
}
//
function handleSelectionChange(selection) {
ids.value = selection.map((item) => item.id)
single.value = selection.length != 1
multiple.value = !selection.length
}
//
function sortChange(column) {
var sort = undefined
var sortType = undefined
if (column.prop != null && column.order != null) {
sort = column.prop
sortType = column.order
}
queryParams.sort = sort
queryParams.sortType = sortType
handleQuery()
}
/*************** form操作 ***************/
const formRef = ref()
const title = ref('')
// 1add 2edit 3view
const opertype = ref(0)
const open = ref(false)
const state = reactive({
single: true,
multiple: true,
submitLoading: false,
form: {},
rules: {
roomName: [{ required: true, message: '机房名称不能为空', trigger: 'blur' }]
},
options: {}
})
const { form, rules, options, single, multiple } = toRefs(state)
// dialog
function cancel() {
open.value = false
reset()
}
//
function reset() {
form.value = {
id: null,
deptId: 0,
deptName: null,
roomName: null,
roomAddress: null,
racksCount: null,
remarks: null,
createdAt: null,
updatedAt: null
}
proxy.resetForm('formRef')
}
/**
* 查看
* @param {*} row
*/
function handlePreview(row) {
reset()
initTreeData()
const id = row.id
getOdfRooms(id).then((res) => {
const { code, data } = res
if (code == 200) {
open.value = true
title.value = '查看'
opertype.value = 3
form.value = {
...data
}
}
})
}
//
function handleAdd() {
reset()
initTreeData()
open.value = true
state.submitLoading = false
title.value = '添加机房列表'
opertype.value = 1
}
//
function handleUpdate(row) {
reset()
initTreeData()
state.submitLoading = false
const id = row.id || ids.value
getOdfRooms(id).then((res) => {
const { code, data } = res
if (code == 200) {
open.value = true
title.value = '修改机房列表'
opertype.value = 2
form.value = {
...data
}
}
})
}
// &
function submitForm() {
proxy.$refs['formRef'].validate((valid) => {
if (valid) {
state.submitLoading = true
if (form.value.id != undefined && opertype.value === 2) {
updateOdfRooms(form.value).then((res) => {
proxy.$modal.msgSuccess('修改成功')
open.value = false
getList()
})
} else {
addOdfRooms(form.value)
.then((res) => {
proxy.$modal.msgSuccess('新增成功')
open.value = false
getList()
})
.finally(() => {
setTimeout(() => {
state.submitLoading = false
}, 800)
})
}
}
})
}
//
function handleDelete(row) {
const Ids = row.id || ids.value
proxy
.$confirm('是否确认删除参数编号为"' + Ids + '"的数据项?', '警告', {
confirmButtonText: proxy.$t('common.ok'),
cancelButtonText: proxy.$t('common.cancel'),
type: 'warning'
})
.then(function () {
return delOdfRooms(Ids)
})
.then(() => {
getList()
proxy.$modal.msgSuccess('删除成功')
})
}
//
const handleFileSuccess = (response) => {
const { item1, item2 } = response.data
var error = ''
item2.forEach((item) => {
error += item.storageMessage + ','
})
proxy.$alert(item1 + '<p>' + error + '</p>', '导入结果', {
dangerouslyUseHTMLString: true
})
getList()
}
//
function handleExport() {
proxy
.$confirm('是否确认导出机房列表数据项?', '警告', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
})
.then(async () => {
await proxy.downFile('/business/OdfRooms/export', { ...queryParams })
})
}
getTreeselect()
handleQuery()
</script>

View File

@ -183,7 +183,7 @@
<el-input v-model="form.nickName" placeholder="请输入用户昵称" />
</el-form-item>
</el-col>
<el-col :lg="12">
<el-col :lg="12" >
<el-form-item label="归属部门" prop="deptId">
<el-tree-select
v-model="form.deptId"