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

@@ -35,7 +35,8 @@ import type {
AssetAllocationRecord,
AssetAllocationRecordDetail,
BatchSetCardSeriesBindingRequest,
BatchSetCardSeriesBindingResponse
BatchSetCardSeriesBindingResponse,
BatchUpdateAssetRealnamePolicyRequest
} from '@/types/api'
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卡网关操作相关 ==========
/**

View File

@@ -17,6 +17,7 @@ import type {
RecallDevicesResponse,
BatchSetDeviceSeriesBindingRequest,
BatchSetDeviceSeriesBindingResponse,
BatchUpdateAssetRealnamePolicyRequest,
ImportDeviceRequest,
ImportDeviceResponse,
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 // 最新实名状态名称
}
// 资产实名认证策略
export type AssetRealnamePolicy = 'none' | 'before_order' | 'after_order'
// 批量更新资产实名认证策略请求
export interface BatchUpdateAssetRealnamePolicyRequest {
asset_ids: number[]
realname_policy: AssetRealnamePolicy
}
// 换货关联资产
export interface AssetExchangeTraceAsset {
asset_type: AssetType

View File

@@ -70,6 +70,7 @@ declare module 'vue' {
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']
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']
CardOperationDialog: typeof import('./../components/business/CardOperationDialog.vue')['default']
CardStatusTag: typeof import('./../components/business/CardStatusTag.vue')['default']

View File

@@ -40,6 +40,14 @@
>
批量设置套餐系列
</ElButton>
<ElButton
type="primary"
:disabled="!selectedDevices.length"
@click="showBatchRealnamePolicyDialog"
v-permission="'device:realname_policy'"
>
批量修改实名顺序
</ElButton>
<ElButton
type="primary"
:disabled="!selectedDevices.length"
@@ -685,6 +693,15 @@
:current-policy="currentRealnamePolicy"
@confirm="handleConfirmRealnamePolicy"
/>
<BatchRealnamePolicyDialog
v-model="batchRealnamePolicyDialogVisible"
:selected-count="selectedDevices.length"
asset-unit="台设备"
:loading="batchRealnamePolicyLoading"
:error-message="batchRealnamePolicyError"
device-policy-hint
@confirm="handleConfirmBatchRealnamePolicy"
/>
<!-- 操作审计日志弹窗 -->
<OperationLogsDialog
@@ -985,8 +1002,10 @@
EnterpriseRecallDevicesResponse
} from '@/types/api/enterpriseDevice'
import RealnamePolicyDialog from '@/components/device/RealnamePolicyDialog.vue'
import BatchRealnamePolicyDialog from '@/components/business/BatchRealnamePolicyDialog.vue'
import OperationLogsDialog from '@/components/business/OperationLogsDialog.vue'
import ExportTaskCreateDialog from '@/components/business/ExportTaskCreateDialog.vue'
import type { AssetRealnamePolicy } from '@/types/api'
defineOptions({ name: 'DeviceList' })
@@ -1013,6 +1032,9 @@
const allocateDialogVisible = ref(false)
const recallDialogVisible = ref(false)
const selectedDevices = ref<Device[]>([])
const batchRealnamePolicyDialogVisible = ref(false)
const batchRealnamePolicyLoading = ref(false)
const batchRealnamePolicyError = ref('')
const operationLogsDialogVisible = ref(false)
const operationLogsIdentifier = ref('')
const exportDialogVisible = ref(false)
@@ -2201,6 +2223,50 @@
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) => {
ElMessageBox.confirm(

View File

@@ -42,6 +42,14 @@
>
批量设置套餐系列
</ElButton>
<ElButton
type="primary"
:disabled="selectedCards.length === 0"
@click="showBatchRealnamePolicyDialog"
v-permission="'iot_card:realname_policy'"
>
批量修改实名顺序
</ElButton>
<ElButton
type="primary"
:disabled="selectedCards.length === 0"
@@ -976,6 +984,14 @@
:current-policy="currentRealnamePolicy"
@confirm="handleConfirmRealnamePolicy"
/>
<BatchRealnamePolicyDialog
v-model="batchRealnamePolicyDialogVisible"
:selected-count="selectedCards.length"
asset-unit="张卡"
:loading="batchRealnamePolicyLoading"
:error-message="batchRealnamePolicyError"
@confirm="handleConfirmBatchRealnamePolicy"
/>
<!-- 更新实名状态对话框 -->
<UpdateRealnameStatusDialog
@@ -1019,6 +1035,7 @@
import { ElMessage, ElTag, ElIcon, ElMessageBox } from 'element-plus'
import { Loading } from '@element-plus/icons-vue'
import RealnamePolicyDialog from '@/components/device/RealnamePolicyDialog.vue'
import BatchRealnamePolicyDialog from '@/components/business/BatchRealnamePolicyDialog.vue'
import UpdateRealnameStatusDialog from '@/components/business/UpdateRealnameStatusDialog.vue'
import ExportTaskCreateDialog from '@/components/business/ExportTaskCreateDialog.vue'
import type { FormInstance, FormRules } from 'element-plus'
@@ -1039,7 +1056,7 @@
BatchSetCardSeriesBindingResponse
} 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 { AllocateCardsResponse, RecallCardsResponse } from '@/types/api/enterpriseCard'
import OperationLogsDialog from '@/components/business/OperationLogsDialog.vue'
@@ -1062,6 +1079,9 @@
const allocateFormRef = ref<FormInstance>()
const recallFormRef = ref<FormInstance>()
const selectedCards = ref<StandaloneIotCard[]>([])
const batchRealnamePolicyDialogVisible = ref(false)
const batchRealnamePolicyLoading = ref(false)
const batchRealnamePolicyError = ref('')
const allocationResult = ref<AllocateStandaloneCardsResponse>({
allocation_no: '',
total_count: 0,
@@ -2364,6 +2384,50 @@
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 = () => {
if (selectedCards.value.length === 0) {