odf_new/odf-uniapp/pages/search/index.vue

361 lines
8.2 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="search-page">
<image class="bg-image" src="/static/images/home_bg.png" mode="aspectFill" />
<view class="content">
<!-- 顶部导航栏 -->
<view class="nav-bar" :style="{ paddingTop: statusBarHeight + 'px' }">
<view class="nav-bar-inner">
<image
class="nav-icon"
src="/static/images/ic_back.png"
mode="aspectFit"
@click="goBack"
/>
<text class="nav-title">搜索</text>
<view class="nav-icon-placeholder" />
</view>
</view>
<!-- 搜索栏 -->
<view class="search-bar">
<input
class="search-input"
v-model="keyword"
placeholder="请输入要搜索的备注内容"
confirm-type="search"
@confirm="doSearch"
/>
<view class="search-btn" @click="doSearch">
<text class="search-btn-text">搜索</text>
</view>
</view>
<!-- 搜索结果 -->
<view class="result-area" v-if="searched">
<!-- 机房区域 -->
<view class="section" v-if="rooms.length > 0">
<text class="section-title">机房</text>
<view
class="room-card"
v-for="item in rooms"
:key="item.roomId"
@click="goRack(item)"
>
<text class="room-card-name">{{ item.roomName }}</text>
</view>
</view>
<!-- 备注信息区域 -->
<view class="section" v-if="ports.length > 0">
<text class="section-title">备注信息</text>
<view
class="port-card"
v-for="item in ports"
:key="item.id"
@click="goPortDetail(item)"
>
<view class="port-card-row">
<text class="port-label">机房:</text>
<text class="port-value">{{ item.roomName }}</text>
</view>
<view class="port-card-row" v-if="item.address">
<text class="port-label">地址:</text>
<text class="port-value">{{ item.address }}</text>
</view>
<view class="port-card-row">
<text class="port-label">ODF名称</text>
<text class="port-value">{{ item.rackName }}</text>
</view>
<view class="port-card-row">
<text class="port-label">点位置:</text>
<text class="port-value">{{ item.frameName }}{{ item.name }}</text>
</view>
<view class="port-card-row" v-if="item.remarks">
<text class="port-label">备注:</text>
<text class="port-value">{{ item.remarks }}</text>
</view>
<view class="port-card-row" v-if="item.opticalAttenuation">
<text class="port-label">光衰信息:</text>
<text class="port-value">{{ item.opticalAttenuation }}</text>
</view>
<view class="port-card-row" v-if="item.historyRemarks">
<text class="port-label">历史故障:</text>
<text class="port-value">{{ item.historyRemarks }}</text>
</view>
<view class="port-card-row" v-if="item.opticalCableOffRemarks">
<text class="port-label">光缆段信息:</text>
<text class="port-value">{{ item.opticalCableOffRemarks }}</text>
</view>
<view class="port-card-row">
<text class="port-label">状态:</text>
<view class="status-wrap">
<view
class="status-dot"
:class="item.status === 1 ? 'status-green' : 'status-red'"
/>
<text class="status-text">{{ item.status === 1 ? '已连接' : '已断开' }}</text>
</view>
</view>
</view>
</view>
<!-- 无结果 -->
<view class="no-result" v-if="rooms.length === 0 && ports.length === 0">
<text class="no-result-text">暂无搜索结果</text>
</view>
</view>
</view>
</view>
</template>
<script setup>
import { ref } from 'vue'
import { onReachBottom } from '@dcloudio/uni-app'
import { searchPorts } from '@/services/search'
const statusBarHeight = uni.getSystemInfoSync().statusBarHeight || 0
const keyword = ref('')
const rooms = ref([])
const ports = ref([])
const searched = ref(false)
const pageNum = ref(1)
const pageSize = 20
const totalPage = ref(0)
const loading = ref(false)
async function doSearch() {
const key = keyword.value.trim()
if (!key) return
pageNum.value = 1
loading.value = true
try {
const res = await searchPorts(key, 1, pageSize)
if (res.code === 200 && res.data) {
rooms.value = res.data.rooms || []
const portsData = res.data.ports || {}
ports.value = portsData.result || []
totalPage.value = portsData.totalPage || 0
}
} finally {
loading.value = false
searched.value = true
}
}
async function loadMore() {
if (loading.value) return
if (pageNum.value >= totalPage.value) return
loading.value = true
pageNum.value++
try {
const res = await searchPorts(keyword.value.trim(), pageNum.value, pageSize)
if (res.code === 200 && res.data) {
const portsData = res.data.ports || {}
ports.value = [...ports.value, ...(portsData.result || [])]
totalPage.value = portsData.totalPage || 0
}
} finally {
loading.value = false
}
}
function goBack() {
uni.navigateBack()
}
function goRack(item) {
uni.navigateTo({
url: '/pages/rack/index?roomId=' + item.roomId + '&roomName=' + encodeURIComponent(item.roomName)
})
}
function goPortDetail(item) {
uni.navigateTo({
url: '/pages/rack-detail/index?rackId=' + item.rackId + '&rackName=' + encodeURIComponent(item.rackName) + '&roomName=' + encodeURIComponent(item.roomName) + '&portId=' + item.id
})
}
onReachBottom(() => {
loadMore()
})
</script>
<style scoped>
.search-page {
position: relative;
min-height: 100vh;
background-color: #F5F5F5;
}
.bg-image {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 500rpx;
z-index: 0;
}
.content {
position: relative;
z-index: 1;
}
.nav-bar {
width: 100%;
}
.nav-bar-inner {
display: flex;
align-items: center;
justify-content: space-between;
height: 88rpx;
padding: 0 24rpx;
}
.nav-icon {
width: 44rpx;
height: 44rpx;
}
.nav-icon-placeholder {
width: 44rpx;
height: 44rpx;
}
.nav-title {
font-size: 34rpx;
font-weight: 600;
color: #fff;
}
.search-bar {
display: flex;
align-items: center;
padding: 16rpx 24rpx;
}
.search-input {
flex: 1;
height: 72rpx;
padding: 0 24rpx;
background-color: #fff;
border-radius: 12rpx;
font-size: 28rpx;
}
.search-btn {
margin-left: 16rpx;
padding: 0 28rpx;
height: 72rpx;
display: flex;
align-items: center;
justify-content: center;
background-color: #1A73EC;
border-radius: 12rpx;
}
.search-btn-text {
color: #fff;
font-size: 28rpx;
}
.result-area {
padding: 16rpx 24rpx;
}
.section {
margin-bottom: 24rpx;
}
.section-title {
font-size: 30rpx;
font-weight: 600;
color: #333;
margin-bottom: 16rpx;
}
.room-card {
display: flex;
align-items: center;
padding: 32rpx 24rpx;
margin-bottom: 20rpx;
background-color: #fff;
border-radius: 12rpx;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.06);
}
.room-card-name {
font-size: 30rpx;
font-weight: 500;
color: #333;
}
.port-card {
padding: 24rpx;
margin-bottom: 20rpx;
background-color: #fff;
border-radius: 12rpx;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.06);
}
.port-card-row {
display: flex;
align-items: flex-start;
margin-bottom: 12rpx;
}
.port-card-row:last-child {
margin-bottom: 0;
}
.port-label {
font-size: 26rpx;
color: #999;
flex-shrink: 0;
}
.port-value {
font-size: 26rpx;
color: #333;
flex: 1;
}
.status-wrap {
display: flex;
align-items: center;
}
.status-dot {
width: 16rpx;
height: 16rpx;
border-radius: 50%;
margin-right: 8rpx;
}
.status-green {
background-color: #4CAF50;
}
.status-red {
background-color: #F44336;
}
.status-text {
font-size: 26rpx;
color: #333;
}
.no-result {
display: flex;
justify-content: center;
padding: 80rpx 0;
}
.no-result-text {
font-size: 28rpx;
color: #999;
}
</style>