fix: req:bug
This commit is contained in:
@@ -42,9 +42,12 @@
|
|||||||
:label="`${card.iccid} - 插槽${card.slot_position} - ${card.carrier_name}`"
|
:label="`${card.iccid} - 插槽${card.slot_position} - ${card.carrier_name}`"
|
||||||
:value="card.iccid"
|
:value="card.iccid"
|
||||||
>
|
>
|
||||||
<div style="display: flex; align-items: center; justify-content: space-between">
|
<div style="display: flex; align-items: center; justify-content: space-between; width: 100%">
|
||||||
<span>{{ card.iccid }}</span>
|
<span>{{ card.iccid }}</span>
|
||||||
<ElTag size="small" style="margin-left: 10px">插槽{{ card.slot_position }}</ElTag>
|
<div>
|
||||||
|
<ElTag size="small" style="margin-left: 10px">插槽{{ card.slot_position }}</ElTag>
|
||||||
|
<ElTag v-if="card.carrier_name" size="small" type="success" style="margin-left: 5px">{{ card.carrier_name }}</ElTag>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ElOption>
|
</ElOption>
|
||||||
</ElSelect>
|
</ElSelect>
|
||||||
|
|||||||
@@ -374,8 +374,9 @@ export interface StandaloneIotCard {
|
|||||||
activated_at?: string | null // 激活时间 (可选)
|
activated_at?: string | null // 激活时间 (可选)
|
||||||
created_at: string // 创建时间
|
created_at: string // 创建时间
|
||||||
updated_at: string // 更新时间
|
updated_at: string // 更新时间
|
||||||
series_id?: number | null // 套餐系列ID
|
series_id: number | null // 套餐系列ID
|
||||||
series_name?: string // 套餐系列名称
|
series_name: string // 套餐系列名称
|
||||||
|
realname_policy: string // 实名制策略
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========== 单卡批量分配和回收相关 ==========
|
// ========== 单卡批量分配和回收相关 ==========
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="card-header-right">
|
<div class="card-header-right">
|
||||||
<ElTooltip content="开启后系统将自动轮询更新资产状态" placement="top">
|
<ElTooltip content="开启后系统将自动轮询更新资产状态" placement="top">
|
||||||
<div class="polling-switch-wrapper">
|
<div v-if="canShowPolling" class="polling-switch-wrapper">
|
||||||
<span class="polling-label">自动轮询</span>
|
<span class="polling-label">自动轮询</span>
|
||||||
<ElSwitch
|
<ElSwitch
|
||||||
:model-value="pollingEnabled"
|
:model-value="pollingEnabled"
|
||||||
@@ -131,9 +131,6 @@
|
|||||||
</ElTag>
|
</ElTag>
|
||||||
</ElDescriptionsItem>
|
</ElDescriptionsItem>
|
||||||
|
|
||||||
<ElDescriptionsItem label="固件版本">{{
|
|
||||||
cardInfo?.software_version || '-'
|
|
||||||
}}</ElDescriptionsItem>
|
|
||||||
<ElDescriptionsItem label="切卡模式">{{
|
<ElDescriptionsItem label="切卡模式">{{
|
||||||
getSwitchModeName(cardInfo?.switch_mode)
|
getSwitchModeName(cardInfo?.switch_mode)
|
||||||
}}</ElDescriptionsItem>
|
}}</ElDescriptionsItem>
|
||||||
@@ -211,7 +208,7 @@
|
|||||||
size="small"
|
size="small"
|
||||||
link
|
link
|
||||||
@click="handleEnableBindingCard(scope.row)"
|
@click="handleEnableBindingCard(scope.row)"
|
||||||
v-permission="'iot_card:start'"
|
v-permission="'iot_info:start'"
|
||||||
>
|
>
|
||||||
启用此卡
|
启用此卡
|
||||||
</ElButton>
|
</ElButton>
|
||||||
@@ -221,7 +218,7 @@
|
|||||||
size="small"
|
size="small"
|
||||||
link
|
link
|
||||||
@click="handleDisableBindingCard(scope.row)"
|
@click="handleDisableBindingCard(scope.row)"
|
||||||
v-permission="'iot_card:stop'"
|
v-permission="'iot_info:stop'"
|
||||||
>
|
>
|
||||||
停用此卡
|
停用此卡
|
||||||
</ElButton>
|
</ElButton>
|
||||||
@@ -367,20 +364,53 @@
|
|||||||
class="card-operations"
|
class="card-operations"
|
||||||
style="margin-top: 16px; text-align: right"
|
style="margin-top: 16px; text-align: right"
|
||||||
>
|
>
|
||||||
<ElButton type="success" @click="handleEnableCard"> 启用此卡 </ElButton>
|
<ElButton v-permission="'iot_info:start'" type="success" @click="handleEnableCard">
|
||||||
<ElButton type="warning" @click="handleDisableCard"> 停用此卡 </ElButton>
|
启用此卡
|
||||||
<!--<ElButton type="danger" @click="handleManualDeactivate"> 手动停用 </ElButton>-->
|
</ElButton>
|
||||||
<ElButton v-if="canShowRealnamePolicy" type="primary" @click="handleShowRealnamePolicy"> 实名认证策略 </ElButton>
|
<ElButton v-permission="'iot_info:stop'" type="warning" @click="handleDisableCard">
|
||||||
|
停用此卡
|
||||||
|
</ElButton>
|
||||||
|
<!--<ElButton type="danger" v-permission="'iot_info:handler_stop'" @click="handleManualDeactivate"> 手动停用 </ElButton>-->
|
||||||
|
<!-- 手动停用暂时不开放 -->
|
||||||
|
<ElButton
|
||||||
|
v-if="canShowRealnamePolicy"
|
||||||
|
v-permission="'asset:card_realname_policy'"
|
||||||
|
type="primary"
|
||||||
|
@click="handleShowRealnamePolicy"
|
||||||
|
>
|
||||||
|
实名认证策略
|
||||||
|
</ElButton>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 设备操作按钮 -->
|
<!-- 设备操作按钮 -->
|
||||||
<div v-else class="device-operations" style="margin-top: 16px; text-align: right">
|
<div v-else class="device-operations" style="margin-top: 16px; text-align: right">
|
||||||
<ElButton type="info" @click="handleShowSwitchMode">设置切卡模式</ElButton>
|
<ElButton v-permission="'device_info:switch_mode'" type="info" @click="handleShowSwitchMode"
|
||||||
<ElButton type="primary" @click="handleRebootDevice"> 重启设备 </ElButton>
|
>设置切卡模式</ElButton
|
||||||
<ElButton type="warning" @click="handleResetDevice"> 恢复出厂 </ElButton>
|
>
|
||||||
<ElButton type="success" @click="handleShowSwitchCard"> 切换SIM卡 </ElButton>
|
<ElButton v-permission="'device_info:reboot'" type="primary" @click="handleRebootDevice">
|
||||||
<ElButton type="primary" @click="handleShowSetWiFi"> 设置WiFi </ElButton>
|
重启设备
|
||||||
<ElButton v-if="canShowRealnamePolicy" type="primary" @click="handleShowRealnamePolicy"> 实名认证策略 </ElButton>
|
</ElButton>
|
||||||
|
<ElButton v-permission="'device_info:reset'" type="warning" @click="handleResetDevice">
|
||||||
|
恢复出厂
|
||||||
|
</ElButton>
|
||||||
|
<ElButton
|
||||||
|
v-permission="'device_info:switch_card'"
|
||||||
|
type="success"
|
||||||
|
@click="handleShowSwitchCard"
|
||||||
|
>
|
||||||
|
切换SIM卡
|
||||||
|
</ElButton>
|
||||||
|
<ElButton v-permission="'device_info:set_wifi'" type="primary" @click="handleShowSetWiFi">
|
||||||
|
设置WiFi
|
||||||
|
</ElButton>
|
||||||
|
<ElButton
|
||||||
|
v-if="canShowRealnamePolicy"
|
||||||
|
v-permission="'asset_info:device_realname_policy'"
|
||||||
|
type="primary"
|
||||||
|
@click="handleShowRealnamePolicy"
|
||||||
|
>
|
||||||
|
实名认证策略
|
||||||
|
</ElButton>
|
||||||
</div>
|
</div>
|
||||||
</ElCard>
|
</ElCard>
|
||||||
</template>
|
</template>
|
||||||
@@ -499,11 +529,21 @@
|
|||||||
const { hasAuth } = useAuth()
|
const { hasAuth } = useAuth()
|
||||||
|
|
||||||
const realnamePolicyPermission = computed(() => {
|
const realnamePolicyPermission = computed(() => {
|
||||||
return props.cardInfo?.asset_type === 'card' ? 'asset:card_realname_policy' : 'asset:device_realname_policy'
|
return props.cardInfo?.asset_type === 'card'
|
||||||
|
? 'asset:card_realname_policy'
|
||||||
|
: 'asset:device_realname_policy'
|
||||||
})
|
})
|
||||||
|
|
||||||
const canShowRealnamePolicy = computed(() => hasAuth(realnamePolicyPermission.value))
|
const canShowRealnamePolicy = computed(() => hasAuth(realnamePolicyPermission.value))
|
||||||
|
|
||||||
|
const pollingPermission = computed(() => {
|
||||||
|
return props.cardInfo?.asset_type === 'card'
|
||||||
|
? 'iot_info:auto_polling'
|
||||||
|
: 'device_info:auto_polling'
|
||||||
|
})
|
||||||
|
|
||||||
|
const canShowPolling = computed(() => hasAuth(pollingPermission.value))
|
||||||
|
|
||||||
// Emits
|
// Emits
|
||||||
interface Emits {
|
interface Emits {
|
||||||
(e: 'update:pollingEnabled', value: boolean): void
|
(e: 'update:pollingEnabled', value: boolean): void
|
||||||
|
|||||||
@@ -87,7 +87,8 @@
|
|||||||
<!-- 对话框组件 -->
|
<!-- 对话框组件 -->
|
||||||
<SwitchCardDialog
|
<SwitchCardDialog
|
||||||
v-model="switchCardDialogVisible"
|
v-model="switchCardDialogVisible"
|
||||||
:cards="cardInfo?.cards"
|
:device-info="cardInfo?.virtual_no || ''"
|
||||||
|
:cards="cardInfo?.cards || []"
|
||||||
@confirm="handleConfirmSwitchCard"
|
@confirm="handleConfirmSwitchCard"
|
||||||
/>
|
/>
|
||||||
<SwitchModeDialog
|
<SwitchModeDialog
|
||||||
@@ -140,13 +141,13 @@
|
|||||||
|
|
||||||
// 引入对话框组件
|
// 引入对话框组件
|
||||||
import {
|
import {
|
||||||
SwitchCardDialog,
|
|
||||||
SwitchModeDialog,
|
SwitchModeDialog,
|
||||||
WiFiConfigDialog,
|
WiFiConfigDialog,
|
||||||
PackageRechargeDialog,
|
PackageRechargeDialog,
|
||||||
DailyRecordsDialog,
|
DailyRecordsDialog,
|
||||||
OrderHistoryDialog
|
OrderHistoryDialog
|
||||||
} from './components/dialogs'
|
} from './components/dialogs'
|
||||||
|
import SwitchCardDialog from '@/components/device/SwitchCardDialog.vue'
|
||||||
import RealnamePolicyDialog from '@/components/device/RealnamePolicyDialog.vue'
|
import RealnamePolicyDialog from '@/components/device/RealnamePolicyDialog.vue'
|
||||||
|
|
||||||
// 引入 composables
|
// 引入 composables
|
||||||
|
|||||||
@@ -335,19 +335,24 @@
|
|||||||
ref="bindCardFormRef"
|
ref="bindCardFormRef"
|
||||||
:model="bindCardForm"
|
:model="bindCardForm"
|
||||||
:rules="bindCardRules"
|
:rules="bindCardRules"
|
||||||
label-width="100px"
|
label-width="80"
|
||||||
>
|
>
|
||||||
<ElRow :gutter="20">
|
<ElRow :gutter="20">
|
||||||
<ElCol :span="10">
|
<ElCol :span="10">
|
||||||
<ElFormItem label="IoT卡" prop="iot_card_id">
|
<ElFormItem label="IoT卡" prop="iot_card_id">
|
||||||
<ElSelect
|
<ElSelect
|
||||||
v-model="bindCardForm.iot_card_id"
|
v-model="bindCardForm.iot_card_id"
|
||||||
placeholder="请选择或搜索IoT卡(支持ICCID搜索)"
|
:placeholder="
|
||||||
|
iotCardList.length === 0 && !iotCardSearchLoading
|
||||||
|
? '当前没有未绑定设备的卡'
|
||||||
|
: '请选择或搜索IoT卡(支持ICCID搜索)'
|
||||||
|
"
|
||||||
filterable
|
filterable
|
||||||
remote
|
remote
|
||||||
reserve-keyword
|
reserve-keyword
|
||||||
:remote-method="searchIotCards"
|
:remote-method="searchIotCards"
|
||||||
:loading="iotCardSearchLoading"
|
:loading="iotCardSearchLoading"
|
||||||
|
:disabled="iotCardList.length === 0 && !iotCardSearchLoading"
|
||||||
clearable
|
clearable
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
>
|
>
|
||||||
@@ -376,7 +381,7 @@
|
|||||||
</ElSelect>
|
</ElSelect>
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
</ElCol>
|
</ElCol>
|
||||||
<ElCol :span="4">
|
<ElCol :span="3">
|
||||||
<ElButton
|
<ElButton
|
||||||
type="primary"
|
type="primary"
|
||||||
@click="handleConfirmBindCard"
|
@click="handleConfirmBindCard"
|
||||||
@@ -438,76 +443,14 @@
|
|||||||
</ElDialog>
|
</ElDialog>
|
||||||
|
|
||||||
<!-- 切换SIM卡对话框 -->
|
<!-- 切换SIM卡对话框 -->
|
||||||
<ElDialog v-model="switchCardDialogVisible" title="切换SIM卡" width="600px">
|
<SwitchCardDialog
|
||||||
<div v-if="loadingDeviceCards" style="padding: 40px; text-align: center">
|
v-model="switchCardDialogVisible"
|
||||||
<ElIcon class="is-loading" :size="40"><Loading /></ElIcon>
|
:device-info="currentOperatingImei"
|
||||||
<div style="margin-top: 16px">加载设备绑定的卡列表中...</div>
|
:cards="deviceBindingCards"
|
||||||
</div>
|
:loading="loadingDeviceCards"
|
||||||
|
:confirm-loading="switchCardLoading"
|
||||||
<template v-else>
|
@confirm="handleConfirmSwitchCard"
|
||||||
<ElAlert
|
/>
|
||||||
v-if="deviceBindingCards.length === 0"
|
|
||||||
title="该设备暂无绑定的SIM卡"
|
|
||||||
type="warning"
|
|
||||||
:closable="false"
|
|
||||||
style="margin-bottom: 20px"
|
|
||||||
>
|
|
||||||
<template #default>
|
|
||||||
<div>当前设备没有绑定任何SIM卡,无法进行切换操作。</div>
|
|
||||||
<div>请先为设备绑定SIM卡后再进行切换。</div>
|
|
||||||
</template>
|
|
||||||
</ElAlert>
|
|
||||||
|
|
||||||
<ElForm
|
|
||||||
v-if="deviceBindingCards.length > 0"
|
|
||||||
ref="switchCardFormRef"
|
|
||||||
:model="switchCardForm"
|
|
||||||
:rules="switchCardRules"
|
|
||||||
label-width="120px"
|
|
||||||
>
|
|
||||||
<ElFormItem label="设备号">
|
|
||||||
<span style="font-weight: bold; color: #409eff">{{ currentOperatingImei }}</span>
|
|
||||||
</ElFormItem>
|
|
||||||
<ElFormItem label="目标ICCID" prop="target_iccid">
|
|
||||||
<ElSelect
|
|
||||||
v-model="switchCardForm.target_iccid"
|
|
||||||
placeholder="请选择要切换到的目标ICCID"
|
|
||||||
style="width: 100%"
|
|
||||||
clearable
|
|
||||||
>
|
|
||||||
<ElOption
|
|
||||||
v-for="card in deviceBindingCards"
|
|
||||||
:key="card.iccid"
|
|
||||||
:label="`${card.iccid} - 插槽${card.slot_position} - ${card.carrier_name}${card.is_current ? ' (当前)' : ''}`"
|
|
||||||
:value="card.iccid"
|
|
||||||
>
|
|
||||||
<div style="display: flex; align-items: center; justify-content: space-between">
|
|
||||||
<span>{{ card.iccid }}</span>
|
|
||||||
<ElTag size="small" style="margin-left: 10px"
|
|
||||||
>插槽{{ card.slot_position }}</ElTag
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</ElOption>
|
|
||||||
</ElSelect>
|
|
||||||
<div style="margin-top: 8px; font-size: 12px; color: #909399">
|
|
||||||
当前设备共绑定 {{ deviceBindingCards.length }} 张SIM卡
|
|
||||||
</div>
|
|
||||||
</ElFormItem>
|
|
||||||
</ElForm>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template #footer>
|
|
||||||
<ElButton @click="switchCardDialogVisible = false">取消</ElButton>
|
|
||||||
<ElButton
|
|
||||||
v-if="deviceBindingCards.length > 0"
|
|
||||||
type="primary"
|
|
||||||
@click="handleConfirmSwitchCard"
|
|
||||||
:loading="switchCardLoading"
|
|
||||||
>
|
|
||||||
确认切换
|
|
||||||
</ElButton>
|
|
||||||
</template>
|
|
||||||
</ElDialog>
|
|
||||||
|
|
||||||
<!-- 设置WiFi对话框 -->
|
<!-- 设置WiFi对话框 -->
|
||||||
<ElDialog v-model="setWiFiDialogVisible" title="设置WiFi" width="500px">
|
<ElDialog v-model="setWiFiDialogVisible" title="设置WiFi" width="500px">
|
||||||
@@ -566,7 +509,9 @@
|
|||||||
label-width="120px"
|
label-width="120px"
|
||||||
>
|
>
|
||||||
<ElFormItem label="设备标识">
|
<ElFormItem label="设备标识">
|
||||||
<span style="font-weight: bold; color: #409eff">{{ currentOperatingDeviceIdentifier }}</span>
|
<span style="font-weight: bold; color: #409eff">{{
|
||||||
|
currentOperatingDeviceIdentifier
|
||||||
|
}}</span>
|
||||||
</ElFormItem>
|
</ElFormItem>
|
||||||
<ElFormItem label="当前模式">
|
<ElFormItem label="当前模式">
|
||||||
<ElTag :type="currentDeviceSwitchMode === 0 ? 'success' : 'warning'">
|
<ElTag :type="currentDeviceSwitchMode === 0 ? 'success' : 'warning'">
|
||||||
@@ -621,6 +566,7 @@
|
|||||||
import { ElMessage, ElMessageBox, ElTag, ElIcon, ElRadioGroup, ElRadio } from 'element-plus'
|
import { ElMessage, ElMessageBox, ElTag, ElIcon, ElRadioGroup, ElRadio } from 'element-plus'
|
||||||
import { Loading } from '@element-plus/icons-vue'
|
import { Loading } from '@element-plus/icons-vue'
|
||||||
import type { FormInstance, FormRules } from 'element-plus'
|
import type { FormInstance, FormRules } from 'element-plus'
|
||||||
|
import SwitchCardDialog from '@/components/device/SwitchCardDialog.vue'
|
||||||
import type {
|
import type {
|
||||||
Device,
|
Device,
|
||||||
DeviceStatus,
|
DeviceStatus,
|
||||||
@@ -708,6 +654,7 @@
|
|||||||
const bindCardFormRef = ref<FormInstance>()
|
const bindCardFormRef = ref<FormInstance>()
|
||||||
const iotCardList = ref<any[]>([])
|
const iotCardList = ref<any[]>([])
|
||||||
const iotCardSearchLoading = ref(false)
|
const iotCardSearchLoading = ref(false)
|
||||||
|
const iotCardHasSearched = ref(false) // 标记是否已执行过搜索
|
||||||
const bindCardForm = reactive({
|
const bindCardForm = reactive({
|
||||||
iot_card_id: undefined as number | undefined,
|
iot_card_id: undefined as number | undefined,
|
||||||
slot_position: 1
|
slot_position: 1
|
||||||
@@ -724,13 +671,6 @@
|
|||||||
|
|
||||||
const switchCardDialogVisible = ref(false)
|
const switchCardDialogVisible = ref(false)
|
||||||
const switchCardLoading = ref(false)
|
const switchCardLoading = ref(false)
|
||||||
const switchCardFormRef = ref<FormInstance>()
|
|
||||||
const switchCardForm = reactive({
|
|
||||||
target_iccid: ''
|
|
||||||
})
|
|
||||||
const switchCardRules = reactive<FormRules>({
|
|
||||||
target_iccid: [{ required: true, message: '请选择目标ICCID', trigger: 'change' }]
|
|
||||||
})
|
|
||||||
const deviceBindingCards = ref<any[]>([]) // 设备绑定的卡列表
|
const deviceBindingCards = ref<any[]>([]) // 设备绑定的卡列表
|
||||||
const loadingDeviceCards = ref(false) // 加载设备绑定卡列表的状态
|
const loadingDeviceCards = ref(false) // 加载设备绑定卡列表的状态
|
||||||
|
|
||||||
@@ -868,7 +808,7 @@
|
|||||||
{ label: '已绑定卡数', prop: 'bound_card_count' },
|
{ label: '已绑定卡数', prop: 'bound_card_count' },
|
||||||
{ label: '状态', prop: 'status' },
|
{ label: '状态', prop: 'status' },
|
||||||
{ label: '在线状态', prop: 'online_status' },
|
{ label: '在线状态', prop: 'online_status' },
|
||||||
{ label: '固件版本', prop: 'software_version' },
|
|
||||||
{ label: '切卡模式', prop: 'switch_mode' },
|
{ label: '切卡模式', prop: 'switch_mode' },
|
||||||
{ label: '最后在线时间', prop: 'last_online_time' },
|
{ label: '最后在线时间', prop: 'last_online_time' },
|
||||||
{ label: '最后同步时间', prop: 'last_gateway_sync_at' },
|
{ label: '最后同步时间', prop: 'last_gateway_sync_at' },
|
||||||
@@ -917,8 +857,8 @@
|
|||||||
// 重置绑定卡表单
|
// 重置绑定卡表单
|
||||||
bindCardForm.iot_card_id = undefined
|
bindCardForm.iot_card_id = undefined
|
||||||
bindCardForm.slot_position = 1
|
bindCardForm.slot_position = 1
|
||||||
// 加载设备卡列表和默认IoT卡列表
|
// 只加载设备卡列表
|
||||||
await Promise.all([loadDeviceCards(device.virtual_no), loadDefaultIotCards()])
|
await loadDeviceCards(device.virtual_no)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载设备绑定的卡列表
|
// 加载设备绑定的卡列表
|
||||||
@@ -927,15 +867,9 @@
|
|||||||
try {
|
try {
|
||||||
const res = await DeviceService.getDeviceCards(virtualNo)
|
const res = await DeviceService.getDeviceCards(virtualNo)
|
||||||
if (res.code === 0 && res.data) {
|
if (res.code === 0 && res.data) {
|
||||||
deviceCards.value = res.data.bindings || []
|
deviceCards.value = (res.data.bindings || []).sort(
|
||||||
console.log('设备绑定的卡列表:', deviceCards.value)
|
(a, b) => a.slot_position - b.slot_position
|
||||||
|
)
|
||||||
// 🔧 临时调试:强制第一张卡显示为当前卡(方便测试UI效果)
|
|
||||||
// 测试完成后请删除此代码
|
|
||||||
if (deviceCards.value.length > 0) {
|
|
||||||
deviceCards.value[0].is_current = true
|
|
||||||
console.log('🧪 测试模式:已将第一张卡标记为当前卡')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('获取设备绑定的卡列表失败:', error)
|
console.error('获取设备绑定的卡列表失败:', error)
|
||||||
@@ -950,7 +884,8 @@
|
|||||||
try {
|
try {
|
||||||
const res = await CardService.getStandaloneIotCards({
|
const res = await CardService.getStandaloneIotCards({
|
||||||
page: 1,
|
page: 1,
|
||||||
page_size: 20
|
page_size: 20,
|
||||||
|
is_standalone: true
|
||||||
})
|
})
|
||||||
if (res.code === 0 && res.data?.items) {
|
if (res.code === 0 && res.data?.items) {
|
||||||
iotCardList.value = res.data.items
|
iotCardList.value = res.data.items
|
||||||
@@ -969,11 +904,13 @@
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
iotCardSearchLoading.value = true
|
iotCardSearchLoading.value = true
|
||||||
|
iotCardHasSearched.value = true
|
||||||
try {
|
try {
|
||||||
const res = await CardService.getStandaloneIotCards({
|
const res = await CardService.getStandaloneIotCards({
|
||||||
page: 1,
|
page: 1,
|
||||||
page_size: 20,
|
page_size: 20,
|
||||||
iccid: query
|
iccid: query,
|
||||||
|
is_standalone: true
|
||||||
})
|
})
|
||||||
if (res.code === 0 && res.data?.items) {
|
if (res.code === 0 && res.data?.items) {
|
||||||
iotCardList.value = res.data.items
|
iotCardList.value = res.data.items
|
||||||
@@ -1182,13 +1119,6 @@
|
|||||||
return h(ElTag, { type: status.type }, () => status.text)
|
return h(ElTag, { type: status.type }, () => status.text)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
prop: 'software_version',
|
|
||||||
label: '固件版本',
|
|
||||||
width: 120,
|
|
||||||
showOverflowTooltip: true,
|
|
||||||
formatter: (row: Device) => row.software_version || '-'
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
prop: 'switch_mode',
|
prop: 'switch_mode',
|
||||||
label: '切卡模式',
|
label: '切卡模式',
|
||||||
@@ -1201,6 +1131,20 @@
|
|||||||
return modeMap[row.switch_mode || ''] || '-'
|
return modeMap[row.switch_mode || ''] || '-'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
prop: 'realname_policy',
|
||||||
|
label: '实名认证策略',
|
||||||
|
width: 150,
|
||||||
|
formatter: (row: Device) => {
|
||||||
|
const policy = row.realname_policy || ''
|
||||||
|
const policyMap: Record<string, string> = {
|
||||||
|
none: '无需实名',
|
||||||
|
before_order: '先实名后充值/购买',
|
||||||
|
after_order: '先充值/购买后实名'
|
||||||
|
}
|
||||||
|
return policyMap[policy] || (policy ? policy : '未知')
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
prop: 'last_online_time',
|
prop: 'last_online_time',
|
||||||
label: '最后在线时间',
|
label: '最后在线时间',
|
||||||
@@ -1229,13 +1173,17 @@
|
|||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
|
||||||
|
let isFirstActivation = true
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getTableData()
|
getTableData()
|
||||||
})
|
})
|
||||||
|
|
||||||
// 当页面被 keep-alive 激活时自动刷新数据
|
// 当页面被 keep-alive 激活时自动刷新数据
|
||||||
onActivated(() => {
|
onActivated(() => {
|
||||||
getTableData()
|
if (!isFirstActivation) {
|
||||||
|
getTableData()
|
||||||
|
}
|
||||||
|
isFirstActivation = false
|
||||||
})
|
})
|
||||||
|
|
||||||
// 获取设备列表
|
// 获取设备列表
|
||||||
@@ -1758,7 +1706,6 @@
|
|||||||
// 显示切换SIM卡对话框
|
// 显示切换SIM卡对话框
|
||||||
const showSwitchCardDialog = async (imei: string) => {
|
const showSwitchCardDialog = async (imei: string) => {
|
||||||
currentOperatingImei.value = imei
|
currentOperatingImei.value = imei
|
||||||
switchCardForm.target_iccid = ''
|
|
||||||
deviceBindingCards.value = []
|
deviceBindingCards.value = []
|
||||||
switchCardDialogVisible.value = true
|
switchCardDialogVisible.value = true
|
||||||
|
|
||||||
@@ -1775,14 +1722,6 @@
|
|||||||
const res = await DeviceService.getDeviceCards(device.virtual_no)
|
const res = await DeviceService.getDeviceCards(device.virtual_no)
|
||||||
if (res.code === 0 && res.data) {
|
if (res.code === 0 && res.data) {
|
||||||
deviceBindingCards.value = res.data.bindings || []
|
deviceBindingCards.value = res.data.bindings || []
|
||||||
|
|
||||||
// 🔧 临时调试:强制第一张卡显示为当前卡(方便测试UI效果)
|
|
||||||
// 测试完成后请删除此代码
|
|
||||||
if (deviceBindingCards.value.length > 0) {
|
|
||||||
deviceBindingCards.value[0].is_current = true
|
|
||||||
console.log('🧪 切换SIM卡测试模式:已将第一张卡标记为当前卡')
|
|
||||||
}
|
|
||||||
|
|
||||||
if (deviceBindingCards.value.length === 0) {
|
if (deviceBindingCards.value.length === 0) {
|
||||||
ElMessage.warning('该设备暂无绑定的SIM卡')
|
ElMessage.warning('该设备暂无绑定的SIM卡')
|
||||||
}
|
}
|
||||||
@@ -1795,29 +1734,20 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 确认切换SIM卡
|
// 确认切换SIM卡
|
||||||
const handleConfirmSwitchCard = async () => {
|
const handleConfirmSwitchCard = async (data: { target_iccid: string }) => {
|
||||||
if (!switchCardFormRef.value) return
|
try {
|
||||||
|
const res = await DeviceService.switchCard(currentOperatingImei.value, {
|
||||||
await switchCardFormRef.value.validate(async (valid) => {
|
target_iccid: data.target_iccid
|
||||||
if (valid) {
|
})
|
||||||
switchCardLoading.value = true
|
if (res.code === 0) {
|
||||||
try {
|
ElMessage.success('切换SIM卡指令已发送')
|
||||||
const res = await DeviceService.switchCard(currentOperatingImei.value, {
|
switchCardDialogVisible.value = false
|
||||||
target_iccid: switchCardForm.target_iccid
|
} else {
|
||||||
})
|
ElMessage.error(res.msg || '切换失败')
|
||||||
if (res.code === 0) {
|
|
||||||
ElMessage.success('切换SIM卡指令已发送')
|
|
||||||
switchCardDialogVisible.value = false
|
|
||||||
} else {
|
|
||||||
ElMessage.error(res.msg || '切换失败')
|
|
||||||
}
|
|
||||||
} catch (error: any) {
|
|
||||||
console.error('切换SIM卡失败:', error)
|
|
||||||
} finally {
|
|
||||||
switchCardLoading.value = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
} catch (error: any) {
|
||||||
|
console.error('切换SIM卡失败:', error)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 显示设置WiFi对话框
|
// 显示设置WiFi对话框
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<ArtSearchBar
|
<ArtSearchBar
|
||||||
v-model:filter="formFilters"
|
v-model:filter="formFilters"
|
||||||
:items="formItems"
|
:items="formItems"
|
||||||
label-width="90"
|
label-width="120"
|
||||||
@reset="handleReset"
|
@reset="handleReset"
|
||||||
@search="handleSearch"
|
@search="handleSearch"
|
||||||
></ArtSearchBar>
|
></ArtSearchBar>
|
||||||
@@ -927,7 +927,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '独立卡',
|
label: '是否绑定设备',
|
||||||
prop: 'is_standalone',
|
prop: 'is_standalone',
|
||||||
type: 'select',
|
type: 'select',
|
||||||
config: {
|
config: {
|
||||||
@@ -955,6 +955,7 @@
|
|||||||
{ label: '激活状态', prop: 'activation_status' },
|
{ label: '激活状态', prop: 'activation_status' },
|
||||||
{ label: '网络状态', prop: 'network_status' },
|
{ label: '网络状态', prop: 'network_status' },
|
||||||
{ label: '实名状态', prop: 'real_name_status' },
|
{ label: '实名状态', prop: 'real_name_status' },
|
||||||
|
{ label: '实名认证策略', prop: 'realname_policy' },
|
||||||
{ label: '累计流量(MB)', prop: 'data_usage_mb' },
|
{ label: '累计流量(MB)', prop: 'data_usage_mb' },
|
||||||
{ label: '创建时间', prop: 'created_at' }
|
{ label: '创建时间', prop: 'created_at' }
|
||||||
]
|
]
|
||||||
@@ -1046,10 +1047,6 @@
|
|||||||
return typeMap[status] || 'info'
|
return typeMap[status] || 'info'
|
||||||
}
|
}
|
||||||
|
|
||||||
const formatCardPrice = (price: number) => {
|
|
||||||
return `¥${(price / 100).toFixed(2)}`
|
|
||||||
}
|
|
||||||
|
|
||||||
// 动态列配置
|
// 动态列配置
|
||||||
const { columnChecks, columns } = useCheckedColumns(() => [
|
const { columnChecks, columns } = useCheckedColumns(() => [
|
||||||
{
|
{
|
||||||
@@ -1151,6 +1148,21 @@
|
|||||||
return h(ElTag, { type }, () => text)
|
return h(ElTag, { type }, () => text)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
prop: 'realname_policy',
|
||||||
|
label: '实名认证策略',
|
||||||
|
width: 150,
|
||||||
|
formatter: (row: StandaloneIotCard) => {
|
||||||
|
const policy = row.realname_policy || ''
|
||||||
|
const policyMap: Record<string, string> = {
|
||||||
|
none: '无需实名',
|
||||||
|
before_order: '先实名后充值/购买',
|
||||||
|
after_order: '先充值/购买后实名'
|
||||||
|
}
|
||||||
|
const text = policyMap[policy] || (policy ? policy : '未知')
|
||||||
|
return text
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
prop: 'data_usage_mb',
|
prop: 'data_usage_mb',
|
||||||
label: '累计流量(MB)',
|
label: '累计流量(MB)',
|
||||||
@@ -1711,99 +1723,6 @@
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 查询流量使用
|
|
||||||
const showFlowUsageDialog = async (iccid: string) => {
|
|
||||||
flowUsageDialogVisible.value = true
|
|
||||||
flowUsageLoading.value = true
|
|
||||||
flowUsageData.value = null
|
|
||||||
|
|
||||||
try {
|
|
||||||
// 通过 ICCID 解析获取资产信息,resolveAsset 接口已包含所有需要的数据
|
|
||||||
const res = await AssetService.resolveAsset(iccid)
|
|
||||||
if (res.code === 0 && res.data) {
|
|
||||||
// 直接使用 resolveAsset 返回的流量信息
|
|
||||||
flowUsageData.value = {
|
|
||||||
totalFlow: res.data.package_total_mb || 0,
|
|
||||||
usedFlow: res.data.package_used_mb || 0,
|
|
||||||
remainFlow: res.data.package_remain_mb || 0,
|
|
||||||
extend: res.data.extend
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ElMessage.error(res.msg || '查询失败')
|
|
||||||
flowUsageDialogVisible.value = false
|
|
||||||
}
|
|
||||||
} catch (error: any) {
|
|
||||||
console.error('查询流量使用失败:', error)
|
|
||||||
flowUsageDialogVisible.value = false
|
|
||||||
} finally {
|
|
||||||
flowUsageLoading.value = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询实名认证状态
|
|
||||||
const showRealnameStatusDialog = async (iccid: string) => {
|
|
||||||
realnameStatusDialogVisible.value = true
|
|
||||||
realnameStatusLoading.value = true
|
|
||||||
realnameStatusData.value = null
|
|
||||||
|
|
||||||
try {
|
|
||||||
// 通过 ICCID 解析获取资产信息,resolveAsset 接口已包含所有需要的数据
|
|
||||||
const res = await AssetService.resolveAsset(iccid)
|
|
||||||
if (res.code === 0 && res.data) {
|
|
||||||
// 直接使用 resolveAsset 返回的实名状态,real_name_status: 0未实名 1已实名
|
|
||||||
let statusText = '未知'
|
|
||||||
switch (res.data.real_name_status) {
|
|
||||||
case 0:
|
|
||||||
statusText = '未实名'
|
|
||||||
break
|
|
||||||
case 1:
|
|
||||||
statusText = '已实名'
|
|
||||||
break
|
|
||||||
}
|
|
||||||
realnameStatusData.value = {
|
|
||||||
status: statusText,
|
|
||||||
extend: res.data.extend
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ElMessage.error(res.msg || '查询失败')
|
|
||||||
realnameStatusDialogVisible.value = false
|
|
||||||
}
|
|
||||||
} catch (error: any) {
|
|
||||||
console.error('查询实名状态失败:', error)
|
|
||||||
realnameStatusDialogVisible.value = false
|
|
||||||
} finally {
|
|
||||||
realnameStatusLoading.value = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询卡实时状态
|
|
||||||
const showCardStatusDialog = async (iccid: string) => {
|
|
||||||
cardStatusDialogVisible.value = true
|
|
||||||
cardStatusLoading.value = true
|
|
||||||
cardStatusData.value = null
|
|
||||||
|
|
||||||
try {
|
|
||||||
// 通过 ICCID 解析获取资产信息,resolveAsset 接口已包含所有需要的数据
|
|
||||||
const res = await AssetService.resolveAsset(iccid)
|
|
||||||
if (res.code === 0 && res.data) {
|
|
||||||
// 直接使用 resolveAsset 返回的网络状态
|
|
||||||
cardStatusData.value = {
|
|
||||||
iccid: iccid,
|
|
||||||
cardStatus: res.data.network_status === 1 ? '正常' : '停机',
|
|
||||||
extend: res.data.extend
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ElMessage.error(res.msg || '查询失败')
|
|
||||||
cardStatusDialogVisible.value = false
|
|
||||||
}
|
|
||||||
} catch (error: any) {
|
|
||||||
console.error('查询卡状态失败:', error)
|
|
||||||
cardStatusDialogVisible.value = false
|
|
||||||
} finally {
|
|
||||||
cardStatusLoading.value = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 启用此卡(复机)
|
// 启用此卡(复机)
|
||||||
const handleStartCard = (iccid: string) => {
|
const handleStartCard = (iccid: string) => {
|
||||||
ElMessageBox.confirm('确定要启用该卡片吗?', '确认启用', {
|
ElMessageBox.confirm('确定要启用该卡片吗?', '确认启用', {
|
||||||
|
|||||||
Reference in New Issue
Block a user