H5实名购买顺序与后台批量配置
All checks were successful
构建并部署前端到测试环境 / build-and-deploy (push) Successful in 5m48s
All checks were successful
构建并部署前端到测试环境 / build-and-deploy (push) Successful in 5m48s
This commit is contained in:
@@ -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卡网关操作相关 ==========
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
)
|
||||
}
|
||||
|
||||
// ========== 设备操作相关 ==========
|
||||
|
||||
/**
|
||||
|
||||
93
src/components/business/BatchRealnamePolicyDialog.vue
Normal file
93
src/components/business/BatchRealnamePolicyDialog.vue
Normal 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>
|
||||
@@ -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
|
||||
|
||||
1
src/types/components.d.ts
vendored
1
src/types/components.d.ts
vendored
@@ -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']
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user