This commit is contained in:
@@ -397,9 +397,6 @@ function changeTab(tab: 'card' | 'device') {
|
|||||||
if (activeTab.value === tab) return
|
if (activeTab.value === tab) return
|
||||||
|
|
||||||
activeTab.value = tab
|
activeTab.value = tab
|
||||||
searchKeyword.value = ''
|
|
||||||
carrierFilter.value = undefined
|
|
||||||
statusFilter.value = undefined
|
|
||||||
|
|
||||||
// 切换后加载对应数据
|
// 切换后加载对应数据
|
||||||
if (tab === 'card' && cardList.value.length === 0) {
|
if (tab === 'card' && cardList.value.length === 0) {
|
||||||
@@ -576,31 +573,21 @@ onMounted(async () => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<view class="bg-page safe-area-bottom min-h-screen flex flex-col">
|
<view class="bg-page min-h-screen">
|
||||||
<!-- 搜索区域 -->
|
<!-- 搜索区域 -->
|
||||||
<view class="bg-white px-4 pt-4 pb-3 mb-3">
|
<view class="bg-white px-4 pb-3 mb-3 fixed top-0 left-0 right-0 z-50"
|
||||||
|
style="padding-top: constant(safe-area-inset-top); padding-top: env(safe-area-inset-top);">
|
||||||
<!-- 搜索框 -->
|
<!-- 搜索框 -->
|
||||||
<view class="relative flex items-center">
|
<view class="relative flex items-center">
|
||||||
<input
|
<input v-model="searchKeyword"
|
||||||
v-model="searchKeyword"
|
|
||||||
class="flex-1 h-10 bg-[#f1f5f9] rounded-full pl-4 pr-12 text-sm text-[#1e293b] placeholder-[#94a3b8]"
|
class="flex-1 h-10 bg-[#f1f5f9] rounded-full pl-4 pr-12 text-sm text-[#1e293b] placeholder-[#94a3b8]"
|
||||||
:placeholder="searchType === 'iccid' ? '搜索ICCID' : '搜索虚拟号'"
|
:placeholder="searchType === 'iccid' ? '搜索ICCID' : '搜索虚拟号'" @confirm="refreshList" />
|
||||||
@confirm="refreshList"
|
<view class="absolute right-1 flex items-center">
|
||||||
/>
|
<view v-if="searchKeyword" class="w-8 h-8 flex items-center justify-center text-[#94a3b8]"
|
||||||
<view
|
@click="searchKeyword = ''">
|
||||||
class="absolute right-1 flex items-center"
|
|
||||||
>
|
|
||||||
<view
|
|
||||||
v-if="searchKeyword"
|
|
||||||
class="w-8 h-8 flex items-center justify-center text-[#94a3b8]"
|
|
||||||
@click="searchKeyword = ''"
|
|
||||||
>
|
|
||||||
<i class="i-mdi-close-circle text-lg" />
|
<i class="i-mdi-close-circle text-lg" />
|
||||||
</view>
|
</view>
|
||||||
<view
|
<view class="w-8 h-8 flex items-center justify-center text-brand" @click="refreshList">
|
||||||
class="w-8 h-8 flex items-center justify-center text-brand"
|
|
||||||
@click="refreshList"
|
|
||||||
>
|
|
||||||
<i class="i-mdi-magnify text-xl" />
|
<i class="i-mdi-magnify text-xl" />
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -610,97 +597,73 @@ onMounted(async () => {
|
|||||||
<view class="flex items-center gap-2 mt-3 flex-wrap">
|
<view class="flex items-center gap-2 mt-3 flex-wrap">
|
||||||
|
|
||||||
<view class="flex bg-[#f1f5f9] rounded-full flex-shrink-0">
|
<view class="flex bg-[#f1f5f9] rounded-full flex-shrink-0">
|
||||||
<view
|
<view class="px-3 py-1.5 text-12px font-medium transition-all rounded-full"
|
||||||
class="px-3 py-1.5 text-12px font-medium transition-all rounded-full"
|
:class="activeTab === 'card' ? 'bg-brand text-white' : 'text-[#64748b]'" @click="changeTab('card')">
|
||||||
:class="activeTab === 'card' ? 'bg-brand text-white' : 'text-[#64748b]'"
|
|
||||||
@click="changeTab('card')"
|
|
||||||
>
|
|
||||||
IoT卡
|
IoT卡
|
||||||
</view>
|
</view>
|
||||||
<view
|
<view class="px-3 py-1.5 text-12px font-medium transition-all rounded-full"
|
||||||
class="px-3 py-1.5 text-12px font-medium transition-all rounded-full"
|
:class="activeTab === 'device' ? 'bg-brand text-white' : 'text-[#64748b]'" @click="changeTab('device')">
|
||||||
:class="activeTab === 'device' ? 'bg-brand text-white' : 'text-[#64748b]'"
|
|
||||||
@click="changeTab('device')"
|
|
||||||
>
|
|
||||||
设备
|
设备
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view
|
<view class="flex items-center gap-1 px-3 py-1.5 bg-[#f8fafc] rounded-full flex-shrink-0"
|
||||||
class="flex items-center gap-1 px-3 py-1.5 bg-[#f8fafc] rounded-full flex-shrink-0"
|
@click="showSearchTypePicker = true">
|
||||||
@click="showSearchTypePicker = true"
|
|
||||||
>
|
|
||||||
<text class="text-12px" :class="searchType !== 'iccid' ? 'text-brand font-medium' : 'text-[#64748b]'">
|
<text class="text-12px" :class="searchType !== 'iccid' ? 'text-brand font-medium' : 'text-[#64748b]'">
|
||||||
{{ searchType === 'iccid' ? 'ICCID' : '虚拟号' }}
|
{{ searchType === 'iccid' ? 'ICCID' : '虚拟号' }}
|
||||||
</text>
|
</text>
|
||||||
<i class="i-mdi-chevron-down text-12px text-[#94a3b8]" />
|
<i class="i-mdi-chevron-down text-12px text-[#94a3b8]" />
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view
|
<view class="flex items-center gap-1.5 px-3 py-1.5 bg-[#f8fafc] rounded-full flex-shrink-0 max-w-36"
|
||||||
class="flex items-center gap-1.5 px-3 py-1.5 bg-[#f8fafc] rounded-full flex-shrink-0 max-w-36"
|
@click="showCarrierPicker = true">
|
||||||
@click="showCarrierPicker = true"
|
<text class="text-12px truncate"
|
||||||
>
|
:class="carrierFilter !== undefined ? 'text-brand font-medium' : 'text-[#64748b]'">
|
||||||
<text class="text-12px truncate" :class="carrierFilter !== undefined ? 'text-brand font-medium' : 'text-[#64748b]'">
|
|
||||||
{{ selectedCarrierName }}
|
{{ selectedCarrierName }}
|
||||||
</text>
|
</text>
|
||||||
<i class="i-mdi-chevron-down text-12px text-[#94a3b8] flex-shrink-0" />
|
<i class="i-mdi-chevron-down text-12px text-[#94a3b8] flex-shrink-0" />
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view
|
<view class="flex items-center gap-1.5 px-3 py-1.5 bg-[#f8fafc] rounded-full flex-shrink-0"
|
||||||
class="flex items-center gap-1.5 px-3 py-1.5 bg-[#f8fafc] rounded-full flex-shrink-0"
|
@click="showStatusPicker = true">
|
||||||
@click="showStatusPicker = true"
|
|
||||||
>
|
|
||||||
<text class="text-12px" :class="statusFilter !== undefined ? 'text-brand font-medium' : 'text-[#64748b]'">
|
<text class="text-12px" :class="statusFilter !== undefined ? 'text-brand font-medium' : 'text-[#64748b]'">
|
||||||
{{ selectedStatusName }}
|
{{ selectedStatusName }}
|
||||||
</text>
|
</text>
|
||||||
<i class="i-mdi-chevron-down text-12px text-[#94a3b8]" />
|
<i class="i-mdi-chevron-down text-12px text-[#94a3b8]" />
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view
|
<view v-if="carrierFilter !== undefined || statusFilter !== undefined"
|
||||||
v-if="carrierFilter !== undefined || statusFilter !== undefined"
|
|
||||||
class="flex items-center gap-1 px-2 py-1.5 rounded-full bg-[#ff4d4f]/10 text-[#ff4d4f] flex-shrink-0"
|
class="flex items-center gap-1 px-2 py-1.5 rounded-full bg-[#ff4d4f]/10 text-[#ff4d4f] flex-shrink-0"
|
||||||
@click="carrierFilter = undefined; statusFilter = undefined; refreshList()"
|
@click="carrierFilter = undefined; statusFilter = undefined; refreshList()">
|
||||||
>
|
|
||||||
<i class="i-mdi-close text-12px" />
|
<i class="i-mdi-close text-12px" />
|
||||||
<text class="text-12px font-medium">清除</text>
|
<text class="text-12px font-medium">清除</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
<!-- 列表内容区域 -->
|
||||||
|
<view class="safe-area-bottom min-h-screen flex flex-col pt-28">
|
||||||
<!-- 加载状态 -->
|
<!-- 加载状态 -->
|
||||||
<Skeleton v-if="loading && assetList.length === 0" type="list" />
|
<Skeleton v-if="loading && assetList.length === 0" type="list" />
|
||||||
|
|
||||||
<!-- 资产列表 -->
|
<!-- 资产列表 -->
|
||||||
<view
|
<view v-else class="flex-1 overflow-y-auto min-h-0" @scroll="onScroll">
|
||||||
v-else
|
|
||||||
class="flex-1 overflow-y-auto min-h-0"
|
|
||||||
@scroll="onScroll"
|
|
||||||
>
|
|
||||||
<view v-if="assetList.length > 0" class="px-4 pb-4">
|
<view v-if="assetList.length > 0" class="px-4 pb-4">
|
||||||
<view
|
<view v-for="asset in assetList" :key="`${asset.type}-${asset.id}`"
|
||||||
v-for="asset in assetList"
|
|
||||||
:key="`${asset.type}-${asset.id}`"
|
|
||||||
class="bg-white rounded-16px shadow-[0_2px_12px_rgba(0,0,0,0.06)] p-4 mb-3 cursor-pointer"
|
class="bg-white rounded-16px shadow-[0_2px_12px_rgba(0,0,0,0.06)] p-4 mb-3 cursor-pointer"
|
||||||
@click="viewAssetDetail(asset)"
|
@click="viewAssetDetail(asset)">
|
||||||
>
|
|
||||||
<!-- 顶部区域:左侧状态+名称,右侧类型标签 -->
|
<!-- 顶部区域:左侧状态+名称,右侧类型标签 -->
|
||||||
<view class="flex items-start justify-between mb-3">
|
<view class="flex items-start justify-between mb-3">
|
||||||
<view class="flex items-center gap-2 flex-1 min-w-0">
|
<view class="flex items-center gap-2 flex-1 min-w-0">
|
||||||
<view
|
<view class="w-2 h-2 rounded-full mt-1 flex-shrink-0" :style="{ backgroundColor: asset.statusColor }" />
|
||||||
class="w-2 h-2 rounded-full mt-1 flex-shrink-0"
|
|
||||||
:style="{ backgroundColor: asset.statusColor }"
|
|
||||||
/>
|
|
||||||
<text class="text-15px font-600 text-[#212121] truncate">
|
<text class="text-15px font-600 text-[#212121] truncate">
|
||||||
{{ asset.name }}
|
{{ asset.name }}
|
||||||
</text>
|
</text>
|
||||||
</view>
|
</view>
|
||||||
<view
|
<view class="px-2 py-1 rounded-6px text-11px font-500 flex-shrink-0 ml-2" :style="{
|
||||||
class="px-2 py-1 rounded-6px text-11px font-500 flex-shrink-0 ml-2"
|
|
||||||
:style="{
|
|
||||||
backgroundColor: asset.type === 'card' ? '#e6f4ff' : '#f5f5f5',
|
backgroundColor: asset.type === 'card' ? '#e6f4ff' : '#f5f5f5',
|
||||||
color: asset.type === 'card' ? 'var(--brand-primary)' : '#666',
|
color: asset.type === 'card' ? 'var(--brand-primary)' : '#666',
|
||||||
}"
|
}">
|
||||||
>
|
|
||||||
{{ asset.type === 'card' ? 'IoT卡' : '设备' }}
|
{{ asset.type === 'card' ? 'IoT卡' : '设备' }}
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -715,10 +678,7 @@ onMounted(async () => {
|
|||||||
<!-- 底部区域:状态标签 + 操作按钮 -->
|
<!-- 底部区域:状态标签 + 操作按钮 -->
|
||||||
<view class="flex items-center justify-between pt-3 border-t border-[#f5f5f5]">
|
<view class="flex items-center justify-between pt-3 border-t border-[#f5f5f5]">
|
||||||
<view class="flex items-center gap-1">
|
<view class="flex items-center gap-1">
|
||||||
<view
|
<view class="w-1.5 h-1.5 rounded-full" :style="{ backgroundColor: asset.statusColor }" />
|
||||||
class="w-1.5 h-1.5 rounded-full"
|
|
||||||
:style="{ backgroundColor: asset.statusColor }"
|
|
||||||
/>
|
|
||||||
<text class="text-13px font-500" :style="{ color: asset.statusColor }">
|
<text class="text-13px font-500" :style="{ color: asset.statusColor }">
|
||||||
{{ asset.status }}
|
{{ asset.status }}
|
||||||
</text>
|
</text>
|
||||||
@@ -730,30 +690,26 @@ onMounted(async () => {
|
|||||||
<template v-if="(asset.raw as CardInfo).network_status === 0">
|
<template v-if="(asset.raw as CardInfo).network_status === 0">
|
||||||
<view
|
<view
|
||||||
class="px-3 py-1.5 rounded-10px text-12px font-medium bg-[#52c41a] text-white shadow-sm shadow-[#52c41a]/30 active:scale-95 transition-transform"
|
class="px-3 py-1.5 rounded-10px text-12px font-medium bg-[#52c41a] text-white shadow-sm shadow-[#52c41a]/30 active:scale-95 transition-transform"
|
||||||
@click="handleStartCard(asset, $event)"
|
@click="handleStartCard(asset, $event)">
|
||||||
>
|
|
||||||
复机
|
复机
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="(asset.raw as CardInfo).network_status === 1">
|
<template v-else-if="(asset.raw as CardInfo).network_status === 1">
|
||||||
<view
|
<view
|
||||||
class="px-3 py-1.5 rounded-10px text-12px font-medium bg-[#ff4d4f] text-white shadow-sm shadow-[#ff4d4f]/30 active:scale-95 transition-transform"
|
class="px-3 py-1.5 rounded-10px text-12px font-medium bg-[#ff4d4f] text-white shadow-sm shadow-[#ff4d4f]/30 active:scale-95 transition-transform"
|
||||||
@click="handleStopCard(asset, $event)"
|
@click="handleStopCard(asset, $event)">
|
||||||
>
|
|
||||||
停机
|
停机
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<view
|
<view
|
||||||
class="px-3 py-1.5 rounded-10px text-12px font-medium bg-[#ff4d4f] text-white shadow-sm shadow-[#ff4d4f]/30 active:scale-95 transition-transform"
|
class="px-3 py-1.5 rounded-10px text-12px font-medium bg-[#ff4d4f] text-white shadow-sm shadow-[#ff4d4f]/30 active:scale-95 transition-transform"
|
||||||
@click="handleStopCard(asset, $event)"
|
@click="handleStopCard(asset, $event)">
|
||||||
>
|
|
||||||
停机
|
停机
|
||||||
</view>
|
</view>
|
||||||
<view
|
<view
|
||||||
class="px-3 py-1.5 rounded-10px text-12px font-medium bg-[#52c41a] text-white shadow-sm shadow-[#52c41a]/30 active:scale-95 transition-transform"
|
class="px-3 py-1.5 rounded-10px text-12px font-medium bg-[#52c41a] text-white shadow-sm shadow-[#52c41a]/30 active:scale-95 transition-transform"
|
||||||
@click="handleStartCard(asset, $event)"
|
@click="handleStartCard(asset, $event)">
|
||||||
>
|
|
||||||
复机
|
复机
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
@@ -763,14 +719,12 @@ onMounted(async () => {
|
|||||||
<template v-else>
|
<template v-else>
|
||||||
<view
|
<view
|
||||||
class="px-3 py-1.5 rounded-10px text-12px font-medium bg-[#ff4d4f] text-white shadow-sm shadow-[#ff4d4f]/30 active:scale-95 transition-transform"
|
class="px-3 py-1.5 rounded-10px text-12px font-medium bg-[#ff4d4f] text-white shadow-sm shadow-[#ff4d4f]/30 active:scale-95 transition-transform"
|
||||||
@click="handleStopDevice(asset, $event)"
|
@click="handleStopDevice(asset, $event)">
|
||||||
>
|
|
||||||
停机
|
停机
|
||||||
</view>
|
</view>
|
||||||
<view
|
<view
|
||||||
class="px-3 py-1.5 rounded-10px text-12px font-medium bg-[#52c41a] text-white shadow-sm shadow-[#52c41a]/30 active:scale-95 transition-transform"
|
class="px-3 py-1.5 rounded-10px text-12px font-medium bg-[#52c41a] text-white shadow-sm shadow-[#52c41a]/30 active:scale-95 transition-transform"
|
||||||
@click="handleStartDevice(asset, $event)"
|
@click="handleStartDevice(asset, $event)">
|
||||||
>
|
|
||||||
复机
|
复机
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
@@ -785,7 +739,8 @@ onMounted(async () => {
|
|||||||
<i class="i-mdi-loading animate-spin text-xl text-brand mr-2" />
|
<i class="i-mdi-loading animate-spin text-xl text-brand mr-2" />
|
||||||
<text class="text-sm text-[#64748b]">加载中...</text>
|
<text class="text-sm text-[#64748b]">加载中...</text>
|
||||||
</view>
|
</view>
|
||||||
<view v-else-if="!((activeTab === 'card' && cardHasMore) || (activeTab === 'device' && deviceHasMore))" class="py-4 text-center">
|
<view v-else-if="!((activeTab === 'card' && cardHasMore) || (activeTab === 'device' && deviceHasMore))"
|
||||||
|
class="py-4 text-center">
|
||||||
<text class="text-sm text-[#94a3b8]">没有更多了</text>
|
<text class="text-sm text-[#94a3b8]">没有更多了</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -801,27 +756,15 @@ onMounted(async () => {
|
|||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 运营商选择器 -->
|
<!-- 运营商选择器 -->
|
||||||
<SimplePicker
|
<SimplePicker v-model:show="showCarrierPicker" :options="carrierOptions" title="选择运营商"
|
||||||
v-model:show="showCarrierPicker"
|
@confirm="onCarrierConfirm" />
|
||||||
:options="carrierOptions"
|
|
||||||
title="选择运营商"
|
|
||||||
@confirm="onCarrierConfirm"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<!-- 状态选择器 -->
|
<!-- 状态选择器 -->
|
||||||
<SimplePicker
|
<SimplePicker v-model:show="showStatusPicker" :options="statusOptions" title="选择状态" @confirm="onStatusConfirm" />
|
||||||
v-model:show="showStatusPicker"
|
|
||||||
:options="statusOptions"
|
|
||||||
title="选择状态"
|
|
||||||
@confirm="onStatusConfirm"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<!-- 搜索类型选择器 -->
|
<!-- 搜索类型选择器 -->
|
||||||
<SimplePicker
|
<SimplePicker v-model:show="showSearchTypePicker" :options="searchTypeOptions" title="选择搜索类型"
|
||||||
v-model:show="showSearchTypePicker"
|
@confirm="onSearchTypeConfirm" />
|
||||||
:options="searchTypeOptions"
|
</view>
|
||||||
title="选择搜索类型"
|
|
||||||
@confirm="onSearchTypeConfirm"
|
|
||||||
/>
|
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
Reference in New Issue
Block a user