feat: 新增更新资产实名认证策略
All checks were successful
构建并部署前端到测试环境 / build-and-deploy (push) Successful in 5m5s
All checks were successful
构建并部署前端到测试环境 / build-and-deploy (push) Successful in 5m5s
This commit is contained in:
@@ -201,4 +201,19 @@ export class AssetService extends BaseService {
|
|||||||
params
|
params
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新资产实名认证策略
|
||||||
|
* PATCH /api/admin/assets/:identifier/realname-mode
|
||||||
|
* @param identifier 资产标识符(ICCID 或 VirtualNo)
|
||||||
|
* @param realname_policy 实名认证策略 (none:无需实名, before_order:先实名后充值/购买, after_order:先充值/购买后实名)
|
||||||
|
*/
|
||||||
|
static updateRealnamePolicy(
|
||||||
|
identifier: string,
|
||||||
|
realname_policy: string
|
||||||
|
): Promise<BaseResponse> {
|
||||||
|
return this.patch<BaseResponse>(`/api/admin/assets/${identifier}/realname-mode`, {
|
||||||
|
realname_policy
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
116
src/components/device/RealnamePolicyDialog.vue
Normal file
116
src/components/device/RealnamePolicyDialog.vue
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
<template>
|
||||||
|
<ElDialog v-model="visible" title="设置实名认证策略" width="500px">
|
||||||
|
<ElForm ref="formRef" :model="form" :rules="rules" label-width="120px">
|
||||||
|
<ElFormItem label="资产标识">
|
||||||
|
<span style="font-weight: bold; color: #409eff">{{ assetIdentifier }}</span>
|
||||||
|
</ElFormItem>
|
||||||
|
<ElFormItem label="当前策略">
|
||||||
|
<ElTag :type="getPolicyTagType(currentPolicy)">
|
||||||
|
{{ getPolicyName(currentPolicy) }}
|
||||||
|
</ElTag>
|
||||||
|
</ElFormItem>
|
||||||
|
<ElFormItem label="实名认证策略" prop="realname_policy">
|
||||||
|
<ElRadioGroup v-model="form.realname_policy">
|
||||||
|
<ElRadio value="none">无需实名</ElRadio>
|
||||||
|
<ElRadio value="before_order">先实名后充值/购买</ElRadio>
|
||||||
|
<ElRadio value="after_order">先充值/购买后实名</ElRadio>
|
||||||
|
</ElRadioGroup>
|
||||||
|
</ElFormItem>
|
||||||
|
<ElFormItem>
|
||||||
|
<div style="font-size: 12px; color: #909399; line-height: 1.6">
|
||||||
|
<p>说明:</p>
|
||||||
|
<p>• <strong>无需实名</strong>:用户使用设备无需进行实名认证</p>
|
||||||
|
<p>• <strong>先实名后充值/购买</strong>:用户必须先完成实名认证才能进行充值或购买套餐</p>
|
||||||
|
<p>• <strong>先充值/购买后实名</strong>:用户可以先充值或购买套餐,之后需要完成实名认证</p>
|
||||||
|
</div>
|
||||||
|
</ElFormItem>
|
||||||
|
</ElForm>
|
||||||
|
|
||||||
|
<template #footer>
|
||||||
|
<ElButton @click="handleCancel">取消</ElButton>
|
||||||
|
<ElButton type="primary" @click="handleConfirm" :loading="confirmLoading">确认设置</ElButton>
|
||||||
|
</template>
|
||||||
|
</ElDialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, reactive, computed, watch } from 'vue'
|
||||||
|
import { ElDialog, ElForm, ElFormItem, ElRadioGroup, ElRadio, ElTag } from 'element-plus'
|
||||||
|
import type { FormInstance, FormRules } from 'element-plus'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
modelValue: boolean
|
||||||
|
assetIdentifier: string
|
||||||
|
currentPolicy?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Emits {
|
||||||
|
(e: 'update:modelValue', value: boolean): void
|
||||||
|
(e: 'confirm', data: { realname_policy: string }): void
|
||||||
|
}
|
||||||
|
|
||||||
|
const props = withDefaults(defineProps<Props>(), {
|
||||||
|
currentPolicy: 'none'
|
||||||
|
})
|
||||||
|
const emit = defineEmits<Emits>()
|
||||||
|
|
||||||
|
const formRef = ref<FormInstance>()
|
||||||
|
const confirmLoading = ref(false)
|
||||||
|
|
||||||
|
const form = reactive({
|
||||||
|
realname_policy: 'none'
|
||||||
|
})
|
||||||
|
|
||||||
|
const rules: FormRules = {
|
||||||
|
realname_policy: [{ required: true, message: '请选择实名认证策略', trigger: 'change' }]
|
||||||
|
}
|
||||||
|
|
||||||
|
const visible = computed({
|
||||||
|
get: () => props.modelValue,
|
||||||
|
set: (value) => emit('update:modelValue', value)
|
||||||
|
})
|
||||||
|
|
||||||
|
const currentPolicy = computed(() => props.currentPolicy ?? 'none')
|
||||||
|
|
||||||
|
const getPolicyName = (policy?: string) => {
|
||||||
|
if (!policy || policy === '') return '未知'
|
||||||
|
const map: Record<string, string> = {
|
||||||
|
none: '无需实名',
|
||||||
|
before_order: '先实名后充值/购买',
|
||||||
|
after_order: '先充值/购买后实名'
|
||||||
|
}
|
||||||
|
return map[policy] || '未知'
|
||||||
|
}
|
||||||
|
|
||||||
|
const getPolicyTagType = (policy?: string) => {
|
||||||
|
if (!policy || policy === '') return 'info'
|
||||||
|
const map: Record<string, string> = {
|
||||||
|
none: 'success',
|
||||||
|
before_order: 'warning',
|
||||||
|
after_order: 'info'
|
||||||
|
}
|
||||||
|
return map[policy] || 'info'
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(visible, (newVal) => {
|
||||||
|
if (newVal) {
|
||||||
|
form.realname_policy = props.currentPolicy ?? 'none'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const handleCancel = () => {
|
||||||
|
visible.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleConfirm = async () => {
|
||||||
|
if (!formRef.value) return
|
||||||
|
try {
|
||||||
|
await formRef.value.validate()
|
||||||
|
emit('confirm', { realname_policy: form.realname_policy })
|
||||||
|
} catch (error) {
|
||||||
|
console.error('表单验证失败:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped></style>
|
||||||
@@ -53,6 +53,7 @@ export interface Device {
|
|||||||
last_gateway_sync_at?: string | null // 最后 sync-info 同步时间
|
last_gateway_sync_at?: string | null // 最后 sync-info 同步时间
|
||||||
imei?: string // IMEI(设备国际移动设备识别码)
|
imei?: string // IMEI(设备国际移动设备识别码)
|
||||||
sn?: string // 设备序列号
|
sn?: string // 设备序列号
|
||||||
|
realname_policy?: string // 实名认证策略
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设备查询参数
|
// 设备查询参数
|
||||||
|
|||||||
1
src/types/components.d.ts
vendored
1
src/types/components.d.ts
vendored
@@ -138,6 +138,7 @@ declare module 'vue' {
|
|||||||
MenuStyleSettings: typeof import('./../components/core/layouts/art-settings-panel/widget/MenuStyleSettings.vue')['default']
|
MenuStyleSettings: typeof import('./../components/core/layouts/art-settings-panel/widget/MenuStyleSettings.vue')['default']
|
||||||
OperatorSelect: typeof import('./../components/business/OperatorSelect.vue')['default']
|
OperatorSelect: typeof import('./../components/business/OperatorSelect.vue')['default']
|
||||||
PackageSelector: typeof import('./../components/business/PackageSelector.vue')['default']
|
PackageSelector: typeof import('./../components/business/PackageSelector.vue')['default']
|
||||||
|
RealnamePolicyDialog: typeof import('./../components/device/RealnamePolicyDialog.vue')['default']
|
||||||
RouterLink: typeof import('vue-router')['RouterLink']
|
RouterLink: typeof import('vue-router')['RouterLink']
|
||||||
RouterView: typeof import('vue-router')['RouterView']
|
RouterView: typeof import('vue-router')['RouterView']
|
||||||
SectionTitle: typeof import('./../components/core/layouts/art-settings-panel/widget/SectionTitle.vue')['default']
|
SectionTitle: typeof import('./../components/core/layouts/art-settings-panel/widget/SectionTitle.vue')['default']
|
||||||
|
|||||||
@@ -197,11 +197,6 @@
|
|||||||
</ElTag>
|
</ElTag>
|
||||||
</template>
|
</template>
|
||||||
</ElTableColumn>
|
</ElTableColumn>
|
||||||
<ElTableColumn label="实名认证策略" width="180">
|
|
||||||
<template #default="scope">
|
|
||||||
{{ getRealnamePolicyName(scope.row.realname_policy) }}
|
|
||||||
</template>
|
|
||||||
</ElTableColumn>
|
|
||||||
<ElTableColumn label="实名时间" width="180">
|
<ElTableColumn label="实名时间" width="180">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
{{ scope.row.real_name_at ? formatDateTime(scope.row.real_name_at) : '-' }}
|
{{ scope.row.real_name_at ? formatDateTime(scope.row.real_name_at) : '-' }}
|
||||||
@@ -375,6 +370,7 @@
|
|||||||
<ElButton type="success" @click="handleEnableCard"> 启用此卡 </ElButton>
|
<ElButton type="success" @click="handleEnableCard"> 启用此卡 </ElButton>
|
||||||
<ElButton type="warning" @click="handleDisableCard"> 停用此卡 </ElButton>
|
<ElButton type="warning" @click="handleDisableCard"> 停用此卡 </ElButton>
|
||||||
<ElButton type="danger" @click="handleManualDeactivate"> 手动停用 </ElButton>
|
<ElButton type="danger" @click="handleManualDeactivate"> 手动停用 </ElButton>
|
||||||
|
<ElButton type="primary" @click="handleShowRealnamePolicy"> 实名认证策略 </ElButton>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 设备操作按钮 -->
|
<!-- 设备操作按钮 -->
|
||||||
@@ -384,6 +380,7 @@
|
|||||||
<ElButton type="warning" @click="handleResetDevice"> 恢复出厂 </ElButton>
|
<ElButton type="warning" @click="handleResetDevice"> 恢复出厂 </ElButton>
|
||||||
<ElButton type="success" @click="handleShowSwitchCard"> 切换SIM卡 </ElButton>
|
<ElButton type="success" @click="handleShowSwitchCard"> 切换SIM卡 </ElButton>
|
||||||
<ElButton type="primary" @click="handleShowSetWiFi"> 设置WiFi </ElButton>
|
<ElButton type="primary" @click="handleShowSetWiFi"> 设置WiFi </ElButton>
|
||||||
|
<ElButton type="primary" @click="handleShowRealnamePolicy"> 实名认证策略 </ElButton>
|
||||||
</div>
|
</div>
|
||||||
</ElCard>
|
</ElCard>
|
||||||
</template>
|
</template>
|
||||||
@@ -420,6 +417,7 @@
|
|||||||
network_status?: number
|
network_status?: number
|
||||||
real_name_status?: number
|
real_name_status?: number
|
||||||
real_name_at?: string
|
real_name_at?: string
|
||||||
|
realname_policy?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
interface AssetInfo {
|
interface AssetInfo {
|
||||||
@@ -509,6 +507,7 @@
|
|||||||
(e: 'showSwitchCard'): void
|
(e: 'showSwitchCard'): void
|
||||||
(e: 'showSwitchMode'): void
|
(e: 'showSwitchMode'): void
|
||||||
(e: 'show-set-wifi'): void
|
(e: 'show-set-wifi'): void
|
||||||
|
(e: 'showRealnamePolicy'): void
|
||||||
(e: 'enableBindingCard', payload: { card: BindingCard }): void
|
(e: 'enableBindingCard', payload: { card: BindingCard }): void
|
||||||
(e: 'disableBindingCard', payload: { card: BindingCard }): void
|
(e: 'disableBindingCard', payload: { card: BindingCard }): void
|
||||||
(e: 'navigateToCard', iccid: string): void
|
(e: 'navigateToCard', iccid: string): void
|
||||||
@@ -610,6 +609,10 @@
|
|||||||
emit('show-set-wifi')
|
emit('show-set-wifi')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleShowRealnamePolicy = () => {
|
||||||
|
emit('showRealnamePolicy')
|
||||||
|
}
|
||||||
|
|
||||||
// 绑定卡操作
|
// 绑定卡操作
|
||||||
const handleEnableBindingCard = (card: BindingCard) => {
|
const handleEnableBindingCard = (card: BindingCard) => {
|
||||||
ElMessageBox.confirm(`确定要启用此卡(${card.iccid})吗?`, '启用确认', {
|
ElMessageBox.confirm(`确定要启用此卡(${card.iccid})吗?`, '启用确认', {
|
||||||
|
|||||||
@@ -98,7 +98,10 @@
|
|||||||
<ElDescriptionsItem label="套餐类型">
|
<ElDescriptionsItem label="套餐类型">
|
||||||
{{ getPackageTypeName(currentPackage.package_type) }}
|
{{ getPackageTypeName(currentPackage.package_type) }}
|
||||||
</ElDescriptionsItem>
|
</ElDescriptionsItem>
|
||||||
<ElDescriptionsItem v-if="currentPackage.enable_virtual_data && isSuperAdmin" label="虚流量比例">
|
<ElDescriptionsItem
|
||||||
|
v-if="currentPackage.enable_virtual_data && isSuperAdmin"
|
||||||
|
label="虚流量比例"
|
||||||
|
>
|
||||||
{{ currentPackage.virtual_ratio || '-' }}
|
{{ currentPackage.virtual_ratio || '-' }}
|
||||||
</ElDescriptionsItem>
|
</ElDescriptionsItem>
|
||||||
<ElDescriptionsItem v-if="currentPackage.duration_days" label="套餐时长" :span="3">
|
<ElDescriptionsItem v-if="currentPackage.duration_days" label="套餐时长" :span="3">
|
||||||
@@ -110,11 +113,6 @@
|
|||||||
<ElDescriptionsItem label="到期时间">
|
<ElDescriptionsItem label="到期时间">
|
||||||
{{ formatDateTime(currentPackage.expire_time) || '-' }}
|
{{ formatDateTime(currentPackage.expire_time) || '-' }}
|
||||||
</ElDescriptionsItem>
|
</ElDescriptionsItem>
|
||||||
<ElDescriptionsItem label="状态">
|
|
||||||
<ElTag :type="getPackageStatusTagType(currentPackage.status)" size="small">
|
|
||||||
{{ currentPackage.status_name || '-' }}
|
|
||||||
</ElTag>
|
|
||||||
</ElDescriptionsItem>
|
|
||||||
</ElDescriptions>
|
</ElDescriptions>
|
||||||
|
|
||||||
<!-- 空状态 -->
|
<!-- 空状态 -->
|
||||||
|
|||||||
@@ -67,13 +67,13 @@ export function useAssetFormatters(deviceRealtime?: Ref<any>) {
|
|||||||
|
|
||||||
// 获取实名认证策略名称
|
// 获取实名认证策略名称
|
||||||
const getRealnamePolicyName = (policy?: string) => {
|
const getRealnamePolicyName = (policy?: string) => {
|
||||||
if (!policy) return '-'
|
if (!policy || policy === '') return '未知'
|
||||||
const policyMap: Record<string, string> = {
|
const policyMap: Record<string, string> = {
|
||||||
none: '无需实名',
|
none: '无需实名',
|
||||||
before_order: '先实名后充值/购买',
|
before_order: '先实名后充值/购买',
|
||||||
after_order: '先充值/购买后实名'
|
after_order: '先充值/购买后实名'
|
||||||
}
|
}
|
||||||
return policyMap[policy] || policy
|
return policyMap[policy] || '未知'
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取资产状态名称
|
// 获取资产状态名称
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
@show-switch-card="showSwitchCardDialog"
|
@show-switch-card="showSwitchCardDialog"
|
||||||
@show-switch-mode="showSwitchModeDialog"
|
@show-switch-mode="showSwitchModeDialog"
|
||||||
@show-set-wifi="showSetWiFiDialog"
|
@show-set-wifi="showSetWiFiDialog"
|
||||||
|
@show-realname-policy="showRealnamePolicyDialog"
|
||||||
@enable-binding-card="handleEnableBindingCard"
|
@enable-binding-card="handleEnableBindingCard"
|
||||||
@disable-binding-card="handleDisableBindingCard"
|
@disable-binding-card="handleDisableBindingCard"
|
||||||
@navigate-to-card="handleNavigateToCard"
|
@navigate-to-card="handleNavigateToCard"
|
||||||
@@ -116,6 +117,12 @@
|
|||||||
:asset-identifier="cardInfo?.identifier"
|
:asset-identifier="cardInfo?.identifier"
|
||||||
:asset-type="cardInfo?.asset_type"
|
:asset-type="cardInfo?.asset_type"
|
||||||
/>
|
/>
|
||||||
|
<RealnamePolicyDialog
|
||||||
|
v-model="realnamePolicyDialogVisible"
|
||||||
|
:asset-identifier="cardInfo?.identifier || ''"
|
||||||
|
:current-policy="cardInfo?.realname_policy"
|
||||||
|
@confirm="handleConfirmRealnamePolicy"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -140,6 +147,7 @@
|
|||||||
DailyRecordsDialog,
|
DailyRecordsDialog,
|
||||||
OrderHistoryDialog
|
OrderHistoryDialog
|
||||||
} from './components/dialogs'
|
} from './components/dialogs'
|
||||||
|
import RealnamePolicyDialog from '@/components/device/RealnamePolicyDialog.vue'
|
||||||
|
|
||||||
// 引入 composables
|
// 引入 composables
|
||||||
import { useAssetInfo } from './composables/useAssetInfo'
|
import { useAssetInfo } from './composables/useAssetInfo'
|
||||||
@@ -196,6 +204,7 @@
|
|||||||
const rechargeDialogVisible = ref(false)
|
const rechargeDialogVisible = ref(false)
|
||||||
const dailyRecordsDialogVisible = ref(false)
|
const dailyRecordsDialogVisible = ref(false)
|
||||||
const orderHistoryDialogVisible = ref(false)
|
const orderHistoryDialogVisible = ref(false)
|
||||||
|
const realnamePolicyDialogVisible = ref(false)
|
||||||
const selectedPackageUsageId = ref<number | null>(null)
|
const selectedPackageUsageId = ref<number | null>(null)
|
||||||
|
|
||||||
// ========== 套餐列表分页状态 ==========
|
// ========== 套餐列表分页状态 ==========
|
||||||
@@ -343,6 +352,34 @@
|
|||||||
setWiFiDialogVisible.value = false
|
setWiFiDialogVisible.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 显示实名认证策略对话框
|
||||||
|
*/
|
||||||
|
const showRealnamePolicyDialog = () => {
|
||||||
|
realnamePolicyDialogVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 确认实名认证策略
|
||||||
|
*/
|
||||||
|
const handleConfirmRealnamePolicy = async (form: { realname_policy: string }) => {
|
||||||
|
try {
|
||||||
|
const { AssetService } = await import('@/api/modules')
|
||||||
|
const identifier = cardInfo.value?.identifier || ''
|
||||||
|
const res = await AssetService.updateRealnamePolicy(identifier, form.realname_policy)
|
||||||
|
if (res.code === 0) {
|
||||||
|
ElMessage.success('设置实名认证策略成功')
|
||||||
|
realnamePolicyDialogVisible.value = false
|
||||||
|
await refreshAsset(cardInfo.value!.identifier, cardInfo.value!.asset_type)
|
||||||
|
} else {
|
||||||
|
ElMessage.error(res.msg || '设置实名认证策略失败')
|
||||||
|
}
|
||||||
|
} catch (error: any) {
|
||||||
|
console.error('设置实名认证策略失败:', error)
|
||||||
|
ElMessage.error('设置实名认证策略失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 绑定卡操作 - 启用绑定卡
|
* 绑定卡操作 - 启用绑定卡
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -592,6 +592,14 @@
|
|||||||
</ElButton>
|
</ElButton>
|
||||||
</template>
|
</template>
|
||||||
</ElDialog>
|
</ElDialog>
|
||||||
|
|
||||||
|
<!-- 实名认证策略对话框 -->
|
||||||
|
<RealnamePolicyDialog
|
||||||
|
v-model="realnamePolicyDialogVisible"
|
||||||
|
:asset-identifier="currentRealnamePolicyAsset"
|
||||||
|
:current-policy="currentRealnamePolicy"
|
||||||
|
@confirm="handleConfirmRealnamePolicy"
|
||||||
|
/>
|
||||||
</ElCard>
|
</ElCard>
|
||||||
</div>
|
</div>
|
||||||
</ArtTableFullScreen>
|
</ArtTableFullScreen>
|
||||||
@@ -623,6 +631,7 @@
|
|||||||
import { useAuth } from '@/composables/useAuth'
|
import { useAuth } from '@/composables/useAuth'
|
||||||
import { formatDateTime } from '@/utils/business/format'
|
import { formatDateTime } from '@/utils/business/format'
|
||||||
import type { PackageSeriesResponse } from '@/types/api'
|
import type { PackageSeriesResponse } from '@/types/api'
|
||||||
|
import RealnamePolicyDialog from '@/components/device/RealnamePolicyDialog.vue'
|
||||||
|
|
||||||
defineOptions({ name: 'DeviceList' })
|
defineOptions({ name: 'DeviceList' })
|
||||||
|
|
||||||
@@ -755,6 +764,11 @@
|
|||||||
switch_mode: [{ required: true, message: '请选择切卡模式', trigger: 'change' }]
|
switch_mode: [{ required: true, message: '请选择切卡模式', trigger: 'change' }]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 实名认证策略相关
|
||||||
|
const realnamePolicyDialogVisible = ref(false)
|
||||||
|
const currentRealnamePolicyAsset = ref<string>('')
|
||||||
|
const currentRealnamePolicy = ref<string>('none')
|
||||||
|
|
||||||
// 搜索表单初始值
|
// 搜索表单初始值
|
||||||
const initialSearchState = {
|
const initialSearchState = {
|
||||||
virtual_no: '',
|
virtual_no: '',
|
||||||
@@ -1601,6 +1615,35 @@
|
|||||||
case 'switch-mode':
|
case 'switch-mode':
|
||||||
showSwitchModeDialog(deviceNo, device?.switch_mode)
|
showSwitchModeDialog(deviceNo, device?.switch_mode)
|
||||||
break
|
break
|
||||||
|
case 'realname-policy':
|
||||||
|
showRealnamePolicyDialog(deviceNo, device?.realname_policy)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 显示实名认证策略对话框
|
||||||
|
const showRealnamePolicyDialog = (deviceNo: string, currentPolicy?: string) => {
|
||||||
|
currentRealnamePolicyAsset.value = deviceNo
|
||||||
|
currentRealnamePolicy.value = currentPolicy ?? 'none'
|
||||||
|
realnamePolicyDialogVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确认设置实名认证策略
|
||||||
|
const handleConfirmRealnamePolicy = async (data: { realname_policy: string }) => {
|
||||||
|
try {
|
||||||
|
const res = await AssetService.updateRealnamePolicy(
|
||||||
|
currentRealnamePolicyAsset.value,
|
||||||
|
data.realname_policy
|
||||||
|
)
|
||||||
|
if (res.code === 0) {
|
||||||
|
ElMessage.success('设置实名认证策略成功')
|
||||||
|
realnamePolicyDialogVisible.value = false
|
||||||
|
await getTableData()
|
||||||
|
} else {
|
||||||
|
ElMessage.error(res.msg || '设置失败')
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('设置实名认证策略失败:', error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1913,6 +1956,14 @@
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hasAuth('asset:realname_policy')) {
|
||||||
|
moreActions.push({
|
||||||
|
label: '实名认证策略',
|
||||||
|
handler: () => handleDeviceOperation('realname-policy', row.virtual_no, row),
|
||||||
|
type: 'primary'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// if (hasAuth('device:manual_deactivate')) {
|
// if (hasAuth('device:manual_deactivate')) {
|
||||||
// moreActions.push({
|
// moreActions.push({
|
||||||
// label: '手动停用',
|
// label: '手动停用',
|
||||||
|
|||||||
@@ -545,6 +545,14 @@
|
|||||||
:menu-width="180"
|
:menu-width="180"
|
||||||
@select="handleMoreMenuSelect"
|
@select="handleMoreMenuSelect"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<!-- 实名认证策略对话框 -->
|
||||||
|
<RealnamePolicyDialog
|
||||||
|
v-model="realnamePolicyDialogVisible"
|
||||||
|
:asset-identifier="currentRealnamePolicyIccid"
|
||||||
|
:current-policy="currentRealnamePolicy"
|
||||||
|
@confirm="handleConfirmRealnamePolicy"
|
||||||
|
/>
|
||||||
</ElCard>
|
</ElCard>
|
||||||
</div>
|
</div>
|
||||||
</ArtTableFullScreen>
|
</ArtTableFullScreen>
|
||||||
@@ -557,6 +565,7 @@
|
|||||||
import { CardService, ShopService, PackageSeriesService, AssetService } from '@/api/modules'
|
import { CardService, ShopService, PackageSeriesService, AssetService } from '@/api/modules'
|
||||||
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 type { FormInstance, FormRules } from 'element-plus'
|
import type { FormInstance, FormRules } from 'element-plus'
|
||||||
import type { SearchFormItem } from '@/types'
|
import type { SearchFormItem } from '@/types'
|
||||||
import { useCheckedColumns } from '@/composables/useCheckedColumns'
|
import { useCheckedColumns } from '@/composables/useCheckedColumns'
|
||||||
@@ -636,6 +645,54 @@
|
|||||||
const cardStatusLoading = ref(false)
|
const cardStatusLoading = ref(false)
|
||||||
const cardStatusData = ref<any>(null)
|
const cardStatusData = ref<any>(null)
|
||||||
|
|
||||||
|
// 实名认证策略对话框
|
||||||
|
const realnamePolicyDialogVisible = ref(false)
|
||||||
|
const currentRealnamePolicyIccid = ref('')
|
||||||
|
const currentRealnamePolicy = ref('none')
|
||||||
|
|
||||||
|
// 显示实名认证策略对话框
|
||||||
|
const handleShowRealnamePolicy = async (iccid: string, currentPolicy?: string) => {
|
||||||
|
currentRealnamePolicyIccid.value = iccid
|
||||||
|
if (currentPolicy !== undefined && currentPolicy !== null) {
|
||||||
|
currentRealnamePolicy.value = String(currentPolicy)
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
const res = await AssetService.resolveAsset(iccid)
|
||||||
|
if (res.code === 0 && res.data) {
|
||||||
|
currentRealnamePolicy.value = res.data.realname_policy ?? 'none'
|
||||||
|
} else {
|
||||||
|
currentRealnamePolicy.value = 'none'
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
currentRealnamePolicy.value = 'none'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
realnamePolicyDialogVisible.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确认设置实名认证策略
|
||||||
|
const handleConfirmRealnamePolicy = async (data: { realname_policy: string }) => {
|
||||||
|
if (!currentRealnamePolicyIccid.value) {
|
||||||
|
ElMessage.warning('未指定卡片')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const res = await AssetService.updateRealnamePolicy(
|
||||||
|
currentRealnamePolicyIccid.value,
|
||||||
|
data.realname_policy
|
||||||
|
)
|
||||||
|
if (res.code === 0) {
|
||||||
|
ElMessage.success('设置实名认证策略成功')
|
||||||
|
realnamePolicyDialogVisible.value = false
|
||||||
|
await getTableData()
|
||||||
|
} else {
|
||||||
|
ElMessage.error(res.msg || '设置失败')
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('设置实名认证策略失败:', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 更多操作右键菜单
|
// 更多操作右键菜单
|
||||||
const moreMenuRef = ref<InstanceType<typeof ArtMenuRight>>()
|
const moreMenuRef = ref<InstanceType<typeof ArtMenuRight>>()
|
||||||
|
|
||||||
@@ -1153,6 +1210,29 @@
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hasAuth('asset:realname_policy')) {
|
||||||
|
actions.push({
|
||||||
|
label: '实名认证策略',
|
||||||
|
handler: () => handleCardOperation('realname-policy', row.iccid, row),
|
||||||
|
type: 'primary'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更多操作放到"更多"下拉菜单中
|
||||||
|
const moreActions: any[] = []
|
||||||
|
|
||||||
|
if (hasAuth('iot_card:clear_series')) {
|
||||||
|
moreActions.push({
|
||||||
|
label: '清除关联',
|
||||||
|
handler: () => handleCardOperation('clear-series', row.iccid),
|
||||||
|
type: 'primary'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (moreActions.length > 0) {
|
||||||
|
actions.push(...moreActions)
|
||||||
|
}
|
||||||
|
|
||||||
// if (hasAuth('iot_card:manual_deactivate')) {
|
// if (hasAuth('iot_card:manual_deactivate')) {
|
||||||
// actions.push({
|
// actions.push({
|
||||||
// label: '手动停用',
|
// label: '手动停用',
|
||||||
@@ -1524,13 +1604,6 @@
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasAuth('iot_card:clear_series')) {
|
|
||||||
items.push({
|
|
||||||
key: 'clearSeries',
|
|
||||||
label: '清除关联'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return items
|
return items
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -1632,7 +1705,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// IoT卡操作处理函数
|
// IoT卡操作处理函数
|
||||||
const handleCardOperation = (command: string, iccid: string) => {
|
const handleCardOperation = (command: string, iccid: string, row?: any) => {
|
||||||
switch (command) {
|
switch (command) {
|
||||||
case 'realname-status':
|
case 'realname-status':
|
||||||
showRealnameStatusDialog(iccid)
|
showRealnameStatusDialog(iccid)
|
||||||
@@ -1646,12 +1719,48 @@
|
|||||||
case 'stop-card':
|
case 'stop-card':
|
||||||
handleStopCard(iccid)
|
handleStopCard(iccid)
|
||||||
break
|
break
|
||||||
|
case 'realname-policy':
|
||||||
|
handleShowRealnamePolicy(iccid, row?.realname_policy)
|
||||||
|
break
|
||||||
case 'manual-deactivate':
|
case 'manual-deactivate':
|
||||||
handleManualDeactivate(iccid)
|
handleManualDeactivate(iccid)
|
||||||
break
|
break
|
||||||
|
case 'clear-series':
|
||||||
|
handleClearSingleCardSeries(iccid)
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 清除单卡套餐系列绑定
|
||||||
|
const handleClearSingleCardSeries = (iccid: string) => {
|
||||||
|
ElMessageBox.confirm(`确定要清除该卡(${iccid})的套餐系列关联吗?`, '确认清除', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
})
|
||||||
|
.then(async () => {
|
||||||
|
try {
|
||||||
|
const res = await CardService.batchSetCardSeriesBinding({
|
||||||
|
iccids: [iccid],
|
||||||
|
series_id: 0
|
||||||
|
})
|
||||||
|
if (res.code === 0) {
|
||||||
|
if (res.data.fail_count === 0) {
|
||||||
|
ElMessage.success('清除关联成功')
|
||||||
|
} else {
|
||||||
|
ElMessage.warning(`失败:${res.data.failed_items?.[0]?.reason || '未知原因'}`)
|
||||||
|
}
|
||||||
|
await getTableData()
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('清除关联失败:', error)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
// 用户取消
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// 查询流量使用
|
// 查询流量使用
|
||||||
const showFlowUsageDialog = async (iccid: string) => {
|
const showFlowUsageDialog = async (iccid: string) => {
|
||||||
flowUsageDialogVisible.value = true
|
flowUsageDialogVisible.value = true
|
||||||
|
|||||||
Reference in New Issue
Block a user