H5实名购买顺序与后台批量配置
All checks were successful
构建并部署前端到测试环境 / build-and-deploy (push) Successful in 5m48s

This commit is contained in:
luo
2026-07-21 16:13:40 +08:00
parent 47a2d88c9d
commit 830476d49d
11 changed files with 433 additions and 2 deletions

View File

@@ -0,0 +1,33 @@
# Change: 新增资产批量实名认证策略配置
## Why
运营需要一次性为多个卡或设备配置实名认证顺序。现有后台仅支持单资产设置实名认证策略,无法满足列表多选后的批量配置需求。
## What Changes
- 在后台卡列表和设备列表分别增加“批量修改实名顺序”入口,基于当前勾选资产执行配置。
- 批量配置弹框展示已选资产数量,并提供“无需实名”“先实名后购买”“先购买后实名”三种互斥策略。
- 卡列表调用 `POST /api/admin/iot-cards/batch-update-realname-policy`;设备列表调用 `POST /api/admin/devices/batch-update-realname-policy`
- 批量请求传递 `asset_ids``realname_policy`;前端限制单次提交至多 500 条,并在超限时阻止提交并明确提示。
- 设备批量配置弹框提示“实际H5流程由设备策略决定”。
- 后端批量接口按全成全败处理;前端在失败时展示明确的后端业务错误,成功后刷新当前列表。
- 前端不根据资产类型、卡类型或其他字段自行覆盖或推导实名认证策略。
- 本提案不包含任何 H5 初始化、购买流程或 `effective_realname_policy` 的处理。
## Impact
- Affected specs:
- `iot-card-management`
- `device-management`
- Affected code:
- `src/api/modules/asset.ts` 或对应卡、设备 API 模块
- `src/types/api/asset.ts` 或对应卡、设备 API 类型
- `src/views/asset-management/iot-card-management/index.vue`
- `src/views/asset-management/device-list/index.vue`
- API contracts:
- `POST /api/admin/iot-cards/batch-update-realname-policy`
- `POST /api/admin/devices/batch-update-realname-policy`
- Out of scope:
- H5 初始化返回字段和购买流程
- 单资产实名认证策略设置接口 `PATCH /api/admin/assets/{identifier}/realname-mode`

View File

@@ -0,0 +1,54 @@
## ADDED Requirements
### Requirement: Device Batch Realname Policy Configuration
The device management list SHALL provide a `批量修改实名顺序` action for selected devices. The action SHALL submit the selected device IDs and exactly one realname policy to `POST /api/admin/devices/batch-update-realname-policy`.
#### Scenario: Open batch realname policy dialog for selected devices
- **GIVEN** 用户在设备列表勾选了一台或多台设备
- **WHEN** 用户点击“批量修改实名顺序”
- **THEN** 页面 MUST open a dialog that displays the selected device count
- **AND** 页面 MUST provide mutually exclusive options `无需实名``先实名后购买``先购买后实名`
- **AND** 页面 MUST display `实际H5流程由设备策略决定` 提示
#### Scenario: Submit selected device policy
- **GIVEN** 用户已选择一项实名认证策略
- **WHEN** 用户确认批量修改
- **THEN** 系统 MUST call `POST /api/admin/devices/batch-update-realname-policy`
- **AND** 请求 MUST contain the selected device IDs as `asset_ids`
- **AND** 请求 MUST contain the selected `realname_policy` as `none``before_order``after_order`
#### Scenario: Refresh devices after all-or-nothing success
- **WHEN** 设备批量实名认证策略接口成功返回
- **THEN** 页面 MUST close the dialog
- **AND** 页面 MUST refresh the current device list
#### Scenario: Show failed batch update reason
- **WHEN** 设备批量实名认证策略接口返回业务失败或请求失败
- **THEN** 页面 MUST display the backend business reason when provided
- **AND** 页面 MUST NOT refresh the list as a partial-success result
### Requirement: Device Batch Realname Policy Limit
The device management list MUST limit each realname policy batch submission to 500 selected devices.
#### Scenario: Prevent device batch submission over the limit
- **GIVEN** 用户在设备列表选择超过 500 台设备
- **WHEN** 用户尝试确认批量修改实名认证策略
- **THEN** 页面 MUST prevent the request from being sent
- **AND** 页面 MUST display an explicit maximum-500-items error
### Requirement: Device Batch Policy Is User Selected
The device management list MUST submit the policy explicitly selected by the user and MUST NOT infer, override, or transform it from asset type, card type, or other asset fields.
#### Scenario: Preserve selected device policy value
- **GIVEN** 用户在批量配置弹框选择任一实名认证策略
- **WHEN** 用户确认提交
- **THEN** 请求中的 `realname_policy` MUST equal the selected option

View File

@@ -0,0 +1,53 @@
## ADDED Requirements
### Requirement: IoT Card Batch Realname Policy Configuration
The IoT card management list SHALL provide a `批量修改实名顺序` action for selected cards. The action SHALL submit the selected card IDs and exactly one realname policy to `POST /api/admin/iot-cards/batch-update-realname-policy`.
#### Scenario: Open batch realname policy dialog for selected cards
- **GIVEN** 用户在卡列表勾选了一张或多张卡
- **WHEN** 用户点击“批量修改实名顺序”
- **THEN** 页面 MUST open a dialog that displays the selected card count
- **AND** 页面 MUST provide mutually exclusive options `无需实名``先实名后购买``先购买后实名`
#### Scenario: Submit selected card policy
- **GIVEN** 用户已选择一项实名认证策略
- **WHEN** 用户确认批量修改
- **THEN** 系统 MUST call `POST /api/admin/iot-cards/batch-update-realname-policy`
- **AND** 请求 MUST contain the selected card IDs as `asset_ids`
- **AND** 请求 MUST contain the selected `realname_policy` as `none``before_order``after_order`
#### Scenario: Refresh cards after all-or-nothing success
- **WHEN** 卡批量实名认证策略接口成功返回
- **THEN** 页面 MUST close the dialog
- **AND** 页面 MUST refresh the current card list
#### Scenario: Show failed batch update reason
- **WHEN** 卡批量实名认证策略接口返回业务失败或请求失败
- **THEN** 页面 MUST display the backend business reason when provided
- **AND** 页面 MUST NOT refresh the list as a partial-success result
### Requirement: IoT Card Batch Realname Policy Limit
The IoT card management list MUST limit each realname policy batch submission to 500 selected cards.
#### Scenario: Prevent card batch submission over the limit
- **GIVEN** 用户在卡列表选择超过 500 张卡
- **WHEN** 用户尝试确认批量修改实名认证策略
- **THEN** 页面 MUST prevent the request from being sent
- **AND** 页面 MUST display an explicit maximum-500-items error
### Requirement: IoT Card Batch Policy Is User Selected
The IoT card management list MUST submit the policy explicitly selected by the user and MUST NOT infer, override, or transform it from asset type, card type, or other asset fields.
#### Scenario: Preserve selected card policy value
- **GIVEN** 用户在批量配置弹框选择任一实名认证策略
- **WHEN** 用户确认提交
- **THEN** 请求中的 `realname_policy` MUST equal the selected option

View File

@@ -0,0 +1,28 @@
## 1. API Contract
- [x] 1.1 定义批量实名认证策略请求类型,包含 `asset_ids:int64[]``realname_policy:none|before_order|after_order`
- [x] 1.2 接入卡批量更新接口 `POST /api/admin/iot-cards/batch-update-realname-policy`
- [x] 1.3 接入设备批量更新接口 `POST /api/admin/devices/batch-update-realname-policy`
## 2. IoT Card Batch Configuration
- [x] 2.1 在卡列表多选操作区增加“批量修改实名顺序”入口。
- [x] 2.2 弹框展示已选卡数量并提供三种互斥实名认证策略。
- [x] 2.3 超过 500 张卡时阻止提交并显示明确提示。
- [x] 2.4 成功后关闭弹框并刷新卡列表;失败时保留选择并展示后端业务原因。
## 3. Device Batch Configuration
- [x] 3.1 在设备列表多选操作区增加“批量修改实名顺序”入口。
- [x] 3.2 弹框展示已选设备数量并提供三种互斥实名认证策略。
- [x] 3.3 展示“实际H5流程由设备策略决定”提示。
- [x] 3.4 超过 500 台设备时阻止提交并显示明确提示。
- [x] 3.5 成功后关闭弹框并刷新设备列表;失败时保留选择并展示后端业务原因。
## 4. Policy Integrity and Verification
- [x] 4.1 前端不根据资产类型、卡类型或其他字段覆盖或推导提交策略。
- [ ] 4.2 验证卡和设备三种策略均按所选值提交,且单次 500 条以内成功。
- [ ] 4.3 验证超过 500 条、后端全成全败失败和网络失败均显示明确错误且不部分刷新列表。
- [ ] 4.4 验证设备弹框显示 H5 流程归属提示。
- [x] 4.5 运行相关前端校验,并执行 `openspec validate add-asset-batch-realname-policy --strict`

View File

@@ -35,7 +35,8 @@ import type {
AssetAllocationRecord, AssetAllocationRecord,
AssetAllocationRecordDetail, AssetAllocationRecordDetail,
BatchSetCardSeriesBindingRequest, BatchSetCardSeriesBindingRequest,
BatchSetCardSeriesBindingResponse BatchSetCardSeriesBindingResponse,
BatchUpdateAssetRealnamePolicyRequest
} from '@/types/api' } from '@/types/api'
type ApiQueryParams = PaginationParams & Record<string, unknown> type ApiQueryParams = PaginationParams & Record<string, unknown>
@@ -411,6 +412,20 @@ export class CardService extends BaseService {
) )
} }
/**
* 批量更新卡实名认证策略
*/
static batchUpdateRealnamePolicy(
data: BatchUpdateAssetRealnamePolicyRequest,
config?: Record<string, any>
): Promise<BaseResponse<void>> {
return this.post<BaseResponse<void>>(
'/api/admin/iot-cards/batch-update-realname-policy',
data,
config
)
}
// ========== IoT卡网关操作相关 ========== // ========== IoT卡网关操作相关 ==========
/** /**

View File

@@ -17,6 +17,7 @@ import type {
RecallDevicesResponse, RecallDevicesResponse,
BatchSetDeviceSeriesBindingRequest, BatchSetDeviceSeriesBindingRequest,
BatchSetDeviceSeriesBindingResponse, BatchSetDeviceSeriesBindingResponse,
BatchUpdateAssetRealnamePolicyRequest,
ImportDeviceRequest, ImportDeviceRequest,
ImportDeviceResponse, ImportDeviceResponse,
DeviceImportTaskQueryParams, DeviceImportTaskQueryParams,
@@ -169,6 +170,20 @@ export class DeviceService extends BaseService {
) )
} }
/**
* 批量更新设备实名认证策略
*/
static batchUpdateRealnamePolicy(
data: BatchUpdateAssetRealnamePolicyRequest,
config?: Record<string, any>
): Promise<BaseResponse<void>> {
return this.post<BaseResponse<void>>(
'/api/admin/devices/batch-update-realname-policy',
data,
config
)
}
// ========== 设备操作相关 ========== // ========== 设备操作相关 ==========
/** /**

View File

@@ -0,0 +1,93 @@
<template>
<ElDialog v-model="visible" title="批量修改实名顺序" width="520px" @closed="resetPolicy">
<ElForm label-width="110px">
<ElFormItem label="已选数量">
<span class="selected-count">{{ selectedCount }} {{ assetUnit }}</span>
</ElFormItem>
<ElFormItem label="实名认证策略">
<ElRadioGroup v-model="policy" :disabled="loading">
<ElRadio value="none">无需实名</ElRadio>
<ElRadio value="before_order">先实名后购买</ElRadio>
<ElRadio value="after_order">先购买后实名</ElRadio>
</ElRadioGroup>
</ElFormItem>
<ElAlert
v-if="devicePolicyHint"
title="实际H5流程由设备策略决定"
type="info"
:closable="false"
show-icon
/>
<ElAlert
v-if="errorMessage"
:title="errorMessage"
type="error"
:closable="false"
show-icon
class="error-alert"
/>
</ElForm>
<template #footer>
<ElButton :disabled="loading" @click="visible = false">取消</ElButton>
<ElButton type="primary" :loading="loading" @click="emit('confirm', policy)">
确认修改
</ElButton>
</template>
</ElDialog>
</template>
<script setup lang="ts">
import { computed, ref } from 'vue'
import {
ElAlert,
ElButton,
ElDialog,
ElForm,
ElFormItem,
ElRadio,
ElRadioGroup
} from 'element-plus'
import type { AssetRealnamePolicy } from '@/types/api'
interface Props {
modelValue: boolean
selectedCount: number
assetUnit: string
loading?: boolean
errorMessage?: string
devicePolicyHint?: boolean
}
const props = withDefaults(defineProps<Props>(), {
loading: false,
errorMessage: '',
devicePolicyHint: false
})
const emit = defineEmits<{
'update:modelValue': [value: boolean]
confirm: [policy: AssetRealnamePolicy]
}>()
const policy = ref<AssetRealnamePolicy>('none')
const visible = computed({
get: () => props.modelValue,
set: (value) => emit('update:modelValue', value)
})
const resetPolicy = () => {
policy.value = 'none'
}
</script>
<style scoped lang="scss">
.selected-count {
font-weight: 600;
color: var(--el-color-primary);
}
.error-alert {
margin-top: 12px;
}
</style>

View File

@@ -63,6 +63,15 @@ export interface AssetStartResponse {
real_name_status_name: string // 最新实名状态名称 real_name_status_name: string // 最新实名状态名称
} }
// 资产实名认证策略
export type AssetRealnamePolicy = 'none' | 'before_order' | 'after_order'
// 批量更新资产实名认证策略请求
export interface BatchUpdateAssetRealnamePolicyRequest {
asset_ids: number[]
realname_policy: AssetRealnamePolicy
}
// 换货关联资产 // 换货关联资产
export interface AssetExchangeTraceAsset { export interface AssetExchangeTraceAsset {
asset_type: AssetType asset_type: AssetType

View File

@@ -70,6 +70,7 @@ declare module 'vue' {
ArtWorkTab: typeof import('./../components/core/layouts/art-work-tab/index.vue')['default'] ArtWorkTab: typeof import('./../components/core/layouts/art-work-tab/index.vue')['default']
BasicSettings: typeof import('./../components/core/layouts/art-settings-panel/widget/BasicSettings.vue')['default'] BasicSettings: typeof import('./../components/core/layouts/art-settings-panel/widget/BasicSettings.vue')['default']
BatchOperationDialog: typeof import('./../components/business/BatchOperationDialog.vue')['default'] BatchOperationDialog: typeof import('./../components/business/BatchOperationDialog.vue')['default']
BatchRealnamePolicyDialog: typeof import('./../components/business/BatchRealnamePolicyDialog.vue')['default']
BoxStyleSettings: typeof import('./../components/core/layouts/art-settings-panel/widget/BoxStyleSettings.vue')['default'] BoxStyleSettings: typeof import('./../components/core/layouts/art-settings-panel/widget/BoxStyleSettings.vue')['default']
CardOperationDialog: typeof import('./../components/business/CardOperationDialog.vue')['default'] CardOperationDialog: typeof import('./../components/business/CardOperationDialog.vue')['default']
CardStatusTag: typeof import('./../components/business/CardStatusTag.vue')['default'] CardStatusTag: typeof import('./../components/business/CardStatusTag.vue')['default']

View File

@@ -40,6 +40,14 @@
> >
批量设置套餐系列 批量设置套餐系列
</ElButton> </ElButton>
<ElButton
type="primary"
:disabled="!selectedDevices.length"
@click="showBatchRealnamePolicyDialog"
v-permission="'device:realname_policy'"
>
批量修改实名顺序
</ElButton>
<ElButton <ElButton
type="primary" type="primary"
:disabled="!selectedDevices.length" :disabled="!selectedDevices.length"
@@ -685,6 +693,15 @@
:current-policy="currentRealnamePolicy" :current-policy="currentRealnamePolicy"
@confirm="handleConfirmRealnamePolicy" @confirm="handleConfirmRealnamePolicy"
/> />
<BatchRealnamePolicyDialog
v-model="batchRealnamePolicyDialogVisible"
:selected-count="selectedDevices.length"
asset-unit="台设备"
:loading="batchRealnamePolicyLoading"
:error-message="batchRealnamePolicyError"
device-policy-hint
@confirm="handleConfirmBatchRealnamePolicy"
/>
<!-- 操作审计日志弹窗 --> <!-- 操作审计日志弹窗 -->
<OperationLogsDialog <OperationLogsDialog
@@ -985,8 +1002,10 @@
EnterpriseRecallDevicesResponse EnterpriseRecallDevicesResponse
} from '@/types/api/enterpriseDevice' } from '@/types/api/enterpriseDevice'
import RealnamePolicyDialog from '@/components/device/RealnamePolicyDialog.vue' import RealnamePolicyDialog from '@/components/device/RealnamePolicyDialog.vue'
import BatchRealnamePolicyDialog from '@/components/business/BatchRealnamePolicyDialog.vue'
import OperationLogsDialog from '@/components/business/OperationLogsDialog.vue' import OperationLogsDialog from '@/components/business/OperationLogsDialog.vue'
import ExportTaskCreateDialog from '@/components/business/ExportTaskCreateDialog.vue' import ExportTaskCreateDialog from '@/components/business/ExportTaskCreateDialog.vue'
import type { AssetRealnamePolicy } from '@/types/api'
defineOptions({ name: 'DeviceList' }) defineOptions({ name: 'DeviceList' })
@@ -1013,6 +1032,9 @@
const allocateDialogVisible = ref(false) const allocateDialogVisible = ref(false)
const recallDialogVisible = ref(false) const recallDialogVisible = ref(false)
const selectedDevices = ref<Device[]>([]) const selectedDevices = ref<Device[]>([])
const batchRealnamePolicyDialogVisible = ref(false)
const batchRealnamePolicyLoading = ref(false)
const batchRealnamePolicyError = ref('')
const operationLogsDialogVisible = ref(false) const operationLogsDialogVisible = ref(false)
const operationLogsIdentifier = ref('') const operationLogsIdentifier = ref('')
const exportDialogVisible = ref(false) const exportDialogVisible = ref(false)
@@ -2201,6 +2223,50 @@
selectedDevices.value = selection selectedDevices.value = selection
} }
const showBatchRealnamePolicyDialog = () => {
if (selectedDevices.value.length === 0) {
ElMessage.warning('请先选择要修改的设备')
return
}
batchRealnamePolicyError.value = ''
batchRealnamePolicyDialogVisible.value = true
}
const handleConfirmBatchRealnamePolicy = async (realnamePolicy: AssetRealnamePolicy) => {
const assetIds = selectedDevices.value.map((device) => device.id)
if (assetIds.length === 0) {
batchRealnamePolicyError.value = '请先选择要修改的设备'
return
}
if (assetIds.length > 500) {
batchRealnamePolicyError.value = '单次最多可修改500台设备'
return
}
batchRealnamePolicyError.value = ''
batchRealnamePolicyLoading.value = true
try {
const res = await DeviceService.batchUpdateRealnamePolicy(
{ asset_ids: assetIds, realname_policy: realnamePolicy },
{ requestOptions: { errorMessageMode: 'none' } }
)
if (res.code !== 0) {
batchRealnamePolicyError.value = res.msg || '批量修改实名顺序失败'
return
}
ElMessage.success('批量修改实名顺序成功')
batchRealnamePolicyDialogVisible.value = false
selectedDevices.value = []
await getTableData()
} catch (error: any) {
batchRealnamePolicyError.value = error?.response?.data?.msg || '批量修改实名顺序失败'
} finally {
batchRealnamePolicyLoading.value = false
}
}
// 删除设备 // 删除设备
const deleteDevice = (row: Device) => { const deleteDevice = (row: Device) => {
ElMessageBox.confirm( ElMessageBox.confirm(

View File

@@ -42,6 +42,14 @@
> >
批量设置套餐系列 批量设置套餐系列
</ElButton> </ElButton>
<ElButton
type="primary"
:disabled="selectedCards.length === 0"
@click="showBatchRealnamePolicyDialog"
v-permission="'iot_card:realname_policy'"
>
批量修改实名顺序
</ElButton>
<ElButton <ElButton
type="primary" type="primary"
:disabled="selectedCards.length === 0" :disabled="selectedCards.length === 0"
@@ -976,6 +984,14 @@
:current-policy="currentRealnamePolicy" :current-policy="currentRealnamePolicy"
@confirm="handleConfirmRealnamePolicy" @confirm="handleConfirmRealnamePolicy"
/> />
<BatchRealnamePolicyDialog
v-model="batchRealnamePolicyDialogVisible"
:selected-count="selectedCards.length"
asset-unit="张卡"
:loading="batchRealnamePolicyLoading"
:error-message="batchRealnamePolicyError"
@confirm="handleConfirmBatchRealnamePolicy"
/>
<!-- 更新实名状态对话框 --> <!-- 更新实名状态对话框 -->
<UpdateRealnameStatusDialog <UpdateRealnameStatusDialog
@@ -1019,6 +1035,7 @@
import { ElMessage, ElTag, ElIcon, ElMessageBox } from 'element-plus' import { ElMessage, ElTag, ElIcon, ElMessageBox } from 'element-plus'
import { Loading } from '@element-plus/icons-vue' import { Loading } from '@element-plus/icons-vue'
import RealnamePolicyDialog from '@/components/device/RealnamePolicyDialog.vue' import RealnamePolicyDialog from '@/components/device/RealnamePolicyDialog.vue'
import BatchRealnamePolicyDialog from '@/components/business/BatchRealnamePolicyDialog.vue'
import UpdateRealnameStatusDialog from '@/components/business/UpdateRealnameStatusDialog.vue' import UpdateRealnameStatusDialog from '@/components/business/UpdateRealnameStatusDialog.vue'
import ExportTaskCreateDialog from '@/components/business/ExportTaskCreateDialog.vue' import ExportTaskCreateDialog from '@/components/business/ExportTaskCreateDialog.vue'
import type { FormInstance, FormRules } from 'element-plus' import type { FormInstance, FormRules } from 'element-plus'
@@ -1039,7 +1056,7 @@
BatchSetCardSeriesBindingResponse BatchSetCardSeriesBindingResponse
} from '@/types/api/card' } from '@/types/api/card'
import { CardSelectionType } from '@/types/api/card' import { CardSelectionType } from '@/types/api/card'
import type { PackageSeriesResponse } from '@/types/api' import type { AssetRealnamePolicy, PackageSeriesResponse } from '@/types/api'
import type { EnterpriseItem } from '@/types/api/enterprise' import type { EnterpriseItem } from '@/types/api/enterprise'
import type { AllocateCardsResponse, RecallCardsResponse } from '@/types/api/enterpriseCard' import type { AllocateCardsResponse, RecallCardsResponse } from '@/types/api/enterpriseCard'
import OperationLogsDialog from '@/components/business/OperationLogsDialog.vue' import OperationLogsDialog from '@/components/business/OperationLogsDialog.vue'
@@ -1062,6 +1079,9 @@
const allocateFormRef = ref<FormInstance>() const allocateFormRef = ref<FormInstance>()
const recallFormRef = ref<FormInstance>() const recallFormRef = ref<FormInstance>()
const selectedCards = ref<StandaloneIotCard[]>([]) const selectedCards = ref<StandaloneIotCard[]>([])
const batchRealnamePolicyDialogVisible = ref(false)
const batchRealnamePolicyLoading = ref(false)
const batchRealnamePolicyError = ref('')
const allocationResult = ref<AllocateStandaloneCardsResponse>({ const allocationResult = ref<AllocateStandaloneCardsResponse>({
allocation_no: '', allocation_no: '',
total_count: 0, total_count: 0,
@@ -2364,6 +2384,50 @@
selectedCards.value = selection selectedCards.value = selection
} }
const showBatchRealnamePolicyDialog = () => {
if (selectedCards.value.length === 0) {
ElMessage.warning('请先选择要修改的卡')
return
}
batchRealnamePolicyError.value = ''
batchRealnamePolicyDialogVisible.value = true
}
const handleConfirmBatchRealnamePolicy = async (realnamePolicy: AssetRealnamePolicy) => {
const assetIds = selectedCards.value.map((card) => card.id)
if (assetIds.length === 0) {
batchRealnamePolicyError.value = '请先选择要修改的卡'
return
}
if (assetIds.length > 500) {
batchRealnamePolicyError.value = '单次最多可修改500张卡'
return
}
batchRealnamePolicyError.value = ''
batchRealnamePolicyLoading.value = true
try {
const res = await CardService.batchUpdateRealnamePolicy(
{ asset_ids: assetIds, realname_policy: realnamePolicy },
{ requestOptions: { errorMessageMode: 'none' } }
)
if (res.code !== 0) {
batchRealnamePolicyError.value = res.msg || '批量修改实名顺序失败'
return
}
ElMessage.success('批量修改实名顺序成功')
batchRealnamePolicyDialogVisible.value = false
selectedCards.value = []
await getTableData()
} catch (error: any) {
batchRealnamePolicyError.value = error?.response?.data?.msg || '批量修改实名顺序失败'
} finally {
batchRealnamePolicyLoading.value = false
}
}
// 显示批量分配对话框 // 显示批量分配对话框
const showAllocateDialog = () => { const showAllocateDialog = () => {
if (selectedCards.value.length === 0) { if (selectedCards.value.length === 0) {