feat: 新增卡视角以及设备视角的实名同步时间,卡状态同步时间,流量同步时间
All checks were successful
构建并部署前端到测试环境 / build-and-deploy (push) Successful in 4m56s

This commit is contained in:
sexygoat
2026-05-18 12:23:35 +08:00
parent 877c741d72
commit 894aea0e74
18 changed files with 544 additions and 63 deletions

View File

@@ -59,6 +59,9 @@
<ElDescriptionsItem label="实名时间">{{
cardInfo?.real_name_at ? formatDateTime(cardInfo.real_name_at) : '-'
}}</ElDescriptionsItem>
<ElDescriptionsItem label="实名同步时间">{{
formatDateTime(cardInfo?.last_real_name_check_at) || '-'
}}</ElDescriptionsItem>
<ElDescriptionsItem label="MSISDN">{{ cardInfo?.msisdn || '-' }}</ElDescriptionsItem>
<ElDescriptionsItem label="资产状态">
@@ -66,8 +69,14 @@
{{ getAssetStatusName(cardInfo?.status) }}
</ElTag>
</ElDescriptionsItem>
<ElDescriptionsItem label="卡状态同步时间">{{
formatDateTime(cardInfo?.last_card_status_check_at) || '-'
}}</ElDescriptionsItem>
<ElDescriptionsItem label="流量同步时间">{{
formatDateTime(cardInfo?.last_data_check_at) || '-'
}}</ElDescriptionsItem>
<ElDescriptionsItem label="运营商停机原因" :span="2">
<ElDescriptionsItem label="运营商状态" :span="1">
<span class="gateway-extend-text">{{ cardInfo?.gateway_extend || '-' }}</span>
</ElDescriptionsItem>
@@ -246,96 +255,117 @@
<!-- 设备实时信息 -->
<ElDivider content-position="left">设备实时信息</ElDivider>
<div v-if="deviceRealtime" v-loading="realtimeLoading" style="margin-top: 16px">
<div v-if="hasDeviceRealtimeSection" v-loading="realtimeLoading" style="margin-top: 16px">
<ElDescriptions :column="4" border>
<!-- 基本状态 -->
<ElDescriptionsItem label="在线状态">
<ElTag :type="deviceRealtime.online_status === 1 ? 'success' : 'danger'" size="small">
{{ deviceRealtime.online_status === 1 ? '在线' : '离线' }}
<ElTag :type="getOnlineStatusType(deviceRealtime?.online_status)" size="small">
{{ getOnlineStatusName(deviceRealtime?.online_status) }}
</ElTag>
</ElDescriptionsItem>
<ElDescriptionsItem label="电量">
{{
deviceRealtime.battery_level !== null && deviceRealtime.battery_level !== undefined
? `${deviceRealtime.battery_level}%`
deviceRealtime?.battery_level !== null && deviceRealtime?.battery_level !== undefined
? `${deviceRealtime?.battery_level}%`
: '-'
}}
</ElDescriptionsItem>
<!-- 时间信息 -->
<ElDescriptionsItem label="本次开机时长">
{{ formatDuration(deviceRealtime.run_time) }}
{{ formatDuration(deviceRealtime?.run_time) }}
</ElDescriptionsItem>
<ElDescriptionsItem label="本次联网时长">
{{ formatDuration(deviceRealtime.connect_time) }}
{{ formatDuration(deviceRealtime?.connect_time) }}
</ElDescriptionsItem>
<ElDescriptionsItem label="最后在线时间">
{{ formatDateTime(deviceRealtime.last_online_time) || '-' }}
{{ formatDateTime(deviceRealtime?.last_online_time) || '-' }}
</ElDescriptionsItem>
<ElDescriptionsItem label="实名同步时间">
{{ formatDateTime(cardInfo?.last_real_name_check_at) || '-' }}
</ElDescriptionsItem>
<ElDescriptionsItem label="卡状态同步时间">
{{ formatDateTime(cardInfo?.last_card_status_check_at) || '-' }}
</ElDescriptionsItem>
<ElDescriptionsItem label="流量同步时间">
{{ formatDateTime(cardInfo?.last_data_check_at) || '-' }}
</ElDescriptionsItem>
<!-- 信号信息 -->
<ElDescriptionsItem label="信号综合判断">
<ElTag :type="getSignalQualityType(deviceRealtime.signal_quality)" size="small">
{{ getSignalQualityText(deviceRealtime.signal_quality) }}
<ElTag :type="getSignalQualityType(deviceRealtime?.signal_quality)" size="small">
{{ getSignalQualityText(deviceRealtime?.signal_quality) }}
</ElTag>
</ElDescriptionsItem>
<ElDescriptionsItem label="信号较弱原因" :span="3">
{{ getSignalBadReasonText(deviceRealtime.signal_bad_reason) }}
{{ getSignalBadReasonText(deviceRealtime?.signal_bad_reason) }}
</ElDescriptionsItem>
<ElDescriptionsItem label="已连接设备数">
{{ deviceRealtime.client_number ?? '-' }} / {{ deviceRealtime.max_clients ?? '-' }}
{{ deviceRealtime?.client_number ?? '-' }} / {{ deviceRealtime?.max_clients ?? '-' }}
</ElDescriptionsItem>
<!-- WiFi 信息 -->
<ElDescriptionsItem label="WiFi 状态">
<ElTag :type="deviceRealtime.wifi_enabled ? 'success' : 'info'" size="small">
{{ deviceRealtime.wifi_enabled ? '已开启' : '已关闭' }}
<ElTag :type="deviceRealtime?.wifi_enabled ? 'success' : 'info'" size="small">
{{
deviceRealtime?.wifi_enabled === undefined
? '-'
: deviceRealtime.wifi_enabled
? '已开启'
: '已关闭'
}}
</ElTag>
</ElDescriptionsItem>
<ElDescriptionsItem label="WiFi 名称">
{{ deviceRealtime.ssid || '-' }}
{{ deviceRealtime?.ssid || '-' }}
</ElDescriptionsItem>
<ElDescriptionsItem label="WiFi 密码">
{{ deviceRealtime.wifi_password || '-' }}
{{ deviceRealtime?.wifi_password || '-' }}
</ElDescriptionsItem>
<!-- 网络信息 -->
<ElDescriptionsItem label="WAN IP">
{{ deviceRealtime.wan_ip || '-' }}
{{ deviceRealtime?.wan_ip || '-' }}
</ElDescriptionsItem>
<ElDescriptionsItem label="LAN IP">
{{ deviceRealtime.lan_ip || '-' }}
{{ deviceRealtime?.lan_ip || '-' }}
</ElDescriptionsItem>
<ElDescriptionsItem label="MAC 地址">
{{ deviceRealtime.mac_address || '-' }}
{{ deviceRealtime?.mac_address || '-' }}
</ElDescriptionsItem>
<ElDescriptionsItem label="IMSI">
{{ deviceRealtime.imsi || '-' }}
{{ deviceRealtime?.imsi || '-' }}
</ElDescriptionsItem>
<!-- 设备配置 -->
<ElDescriptionsItem label="限速">
{{ deviceRealtime.limit_speed ? `${deviceRealtime.limit_speed} KB/s` : '不限速' }}
{{
deviceRealtime?.limit_speed === undefined
? '-'
: deviceRealtime.limit_speed
? `${deviceRealtime.limit_speed} KB/s`
: '不限速'
}}
</ElDescriptionsItem>
<ElDescriptionsItem label="固件版本">
{{ deviceRealtime.software_version || '-' }}
{{ deviceRealtime?.software_version || '-' }}
</ElDescriptionsItem>
<ElDescriptionsItem label="切卡模式">
{{
deviceRealtime.switch_mode === '0'
deviceRealtime?.switch_mode === '0'
? '自动'
: deviceRealtime.switch_mode === '1'
: deviceRealtime?.switch_mode === '1'
? '手动'
: '-'
}}
</ElDescriptionsItem>
<ElDescriptionsItem label="上报周期">
{{ deviceRealtime.sync_interval ? `${deviceRealtime.sync_interval}` : '-' }}
{{ deviceRealtime?.sync_interval ? `${deviceRealtime.sync_interval}` : '-' }}
</ElDescriptionsItem>
<ElDescriptionsItem label="信息更新时间">
{{ formatDateTime(deviceRealtime.last_update_time) || '-' }}
{{ formatDateTime(deviceRealtime?.last_update_time) || '-' }}
</ElDescriptionsItem>
</ElDescriptions>
</div>
@@ -451,6 +481,9 @@
real_name_at?: string
realname_policy?: string
gateway_extend?: string
last_data_check_at?: string | null
last_real_name_check_at?: string | null
last_card_status_check_at?: string | null
}
interface AssetInfo {
@@ -477,6 +510,10 @@
real_name_at?: string
supplier?: string
gateway_extend?: string
last_sync_time?: string | null
last_data_check_at?: string | null
last_real_name_check_at?: string | null
last_card_status_check_at?: string | null
bound_device_id?: number
bound_device_no?: string
bound_device_name?: string
@@ -496,13 +533,13 @@
battery_level?: number | null
run_time?: string
connect_time?: string
last_online_time?: string
last_online_time?: string | null
client_number?: number
max_clients?: number
current_iccid?: string
signal_quality?: string
signal_bad_reason?: string
wifi_enabled?: boolean
wifi_enabled?: boolean | number
ssid?: string
wifi_password?: string
ip_address?: string
@@ -516,8 +553,8 @@
switch_mode?: string
sync_interval?: number
device_id?: string
last_sync_time?: string
last_update_time?: string
last_sync_time?: string | null
last_update_time?: string | null
}
interface Props {
@@ -610,6 +647,14 @@
return props.cardInfo.cards.find((card: BindingCard) => card.is_current) || null
})
const hasDeviceRealtimeSection = computed(
() =>
Boolean(props.deviceRealtime) ||
props.cardInfo?.last_data_check_at !== undefined ||
props.cardInfo?.last_real_name_check_at !== undefined ||
props.cardInfo?.last_card_status_check_at !== undefined
)
// 处理轮询开关变化
const handlePollingChange = (value: string | number | boolean) => {
emit('update:pollingEnabled', Boolean(value))

View File

@@ -7,7 +7,7 @@
{{ data.package_name }}
</ElDescriptionsItem>
<ElDescriptionsItem label="总使用流量" :span="2">
{{ formatDataSize(data.total_usage_mb) }}
{{ formatDataSize(displayedTotalUsageMb) }}
</ElDescriptionsItem>
</ElDescriptions>
@@ -59,9 +59,9 @@
<ElTableColumn label="使用进度" min-width="200">
<template #default="{ row }">
<ElProgress
:percentage="getUsageProgress(row.cumulative_usage_mb, data.total_usage_mb)"
:percentage="getUsageProgress(row.cumulative_usage_mb, displayedTotalUsageMb)"
:color="
getProgressColor(getUsageProgress(row.cumulative_usage_mb, data.total_usage_mb))
getProgressColor(getUsageProgress(row.cumulative_usage_mb, displayedTotalUsageMb))
"
/>
</template>
@@ -86,14 +86,28 @@
ElTable,
ElTableColumn,
ElProgress,
ElEmpty,
ElMessage
ElEmpty
} from 'element-plus'
import { CardService } from '@/api/modules'
import type { PackageInfo } from '../../types'
interface Props {
modelValue: boolean
packageUsageId?: number
packageRow?: PackageInfo
}
interface DailyRecordItem {
date: string
daily_usage_mb: number
cumulative_usage_mb: number
}
interface DailyRecordsResponseData {
package_name: string
package_usage_id: number
total_usage_mb: number
records: DailyRecordItem[]
}
interface Emits {
@@ -104,16 +118,19 @@
const emit = defineEmits<Emits>()
const loading = ref(false)
const data = ref<any>(null)
const data = ref<DailyRecordsResponseData | null>(null)
const filterType = ref<'all' | 'day' | 'month'>('all')
const selectedDate = ref<string>('')
const selectedMonth = ref<string>('')
const filteredRecords = ref<any[]>([])
const filteredRecords = ref<DailyRecordItem[]>([])
const visible = computed({
get: () => props.modelValue,
set: (value) => emit('update:modelValue', value)
})
const displayedTotalUsageMb = computed(
() => props.packageRow?.real_total_mb ?? data.value?.total_usage_mb ?? 0
)
// 监听对话框打开,加载数据
watch(visible, async (newVal) => {
@@ -168,7 +185,7 @@
return
}
filteredRecords.value = data.value.records.filter((record: any) => {
filteredRecords.value = data.value.records.filter((record) => {
return record.date === selectedDate.value
})
}
@@ -181,7 +198,7 @@
return
}
filteredRecords.value = data.value.records.filter((record: any) => {
filteredRecords.value = data.value.records.filter((record) => {
return record.date.startsWith(selectedMonth.value)
})
}

View File

@@ -20,6 +20,12 @@ type TrafficDisplaySource = {
enable_virtual_data?: boolean | null
}
const NULLABLE_REALTIME_CARD_FIELDS = new Set([
'last_data_check_at',
'last_real_name_check_at',
'last_card_status_check_at'
])
/**
* 格式化数据大小(MB -> GB/MB)
*/
@@ -54,7 +60,7 @@ const mergeAssetBoundCards = (
const mergedCard = { ...existingCard } as unknown as Record<string, unknown>
for (const [key, value] of Object.entries(realtimeCard)) {
if (value !== null && value !== undefined) {
if (value !== undefined && (value !== null || NULLABLE_REALTIME_CARD_FIELDS.has(key))) {
mergedCard[key] = value
}
}
@@ -304,6 +310,15 @@ export function useAssetInfo() {
if (data.last_sync_time !== undefined) {
cardInfo.value.last_sync_time = data.last_sync_time
}
if (data.last_data_check_at !== undefined) {
cardInfo.value.last_data_check_at = data.last_data_check_at
}
if (data.last_real_name_check_at !== undefined) {
cardInfo.value.last_real_name_check_at = data.last_real_name_check_at
}
if (data.last_card_status_check_at !== undefined) {
cardInfo.value.last_card_status_check_at = data.last_card_status_check_at
}
if (data.current_month_usage_mb !== undefined) {
cardInfo.value.current_month_usage_mb = data.current_month_usage_mb
}
@@ -320,6 +335,15 @@ export function useAssetInfo() {
// 仅用实时接口中非 null/undefined 的字段覆盖,避免清掉 resolve 接口返回的静态数据
cardInfo.value.cards = mergeAssetBoundCards(cardInfo.value.cards || [], data.cards)
}
if (data.last_data_check_at !== undefined) {
cardInfo.value.last_data_check_at = data.last_data_check_at
}
if (data.last_real_name_check_at !== undefined) {
cardInfo.value.last_real_name_check_at = data.last_real_name_check_at
}
if (data.last_card_status_check_at !== undefined) {
cardInfo.value.last_card_status_check_at = data.last_card_status_check_at
}
if (data.online_status !== undefined) {
cardInfo.value.online_status = data.online_status
}

View File

@@ -137,6 +137,7 @@
<DailyRecordsDialog
v-model="dailyRecordsDialogVisible"
:package-usage-id="selectedPackageUsageId ?? undefined"
:package-row="selectedPackageRow ?? undefined"
/>
<OrderHistoryDialog
v-model="orderHistoryDialogVisible"
@@ -196,7 +197,7 @@
import { useAssetOperations } from './composables/useAssetOperations'
// 引入类型
import type { BindingCard, SwitchCardForm, WiFiForm } from './types'
import type { BindingCard, PackageInfo, SwitchCardForm, WiFiForm } from './types'
defineOptions({ name: 'SingleCard' })
@@ -264,6 +265,7 @@
const realnamePolicyDialogVisible = ref(false)
const updateRealnameStatusDialogVisible = ref(false)
const selectedPackageUsageId = ref<number | null>(null)
const selectedPackageRow = ref<PackageInfo | null>(null)
// 绑定卡实名状态更新
const bindingCardRealnameStatusDialogVisible = ref(false)
@@ -610,9 +612,10 @@
/**
* 显示流量详单
*/
const handleShowDailyRecords = (payload: { packageRow: any }) => {
const handleShowDailyRecords = (payload: { packageRow: PackageInfo }) => {
const { packageRow } = payload
selectedPackageUsageId.value = packageRow.package_usage_id
selectedPackageUsageId.value = packageRow.package_usage_id ?? packageRow.id
selectedPackageRow.value = packageRow
dailyRecordsDialogVisible.value = true
}

View File

@@ -29,6 +29,10 @@ export interface AssetInfo {
cards?: BindingCard[]
status?: number
gateway_extend?: string
last_sync_time?: string | null
last_data_check_at?: string | null
last_real_name_check_at?: string | null
last_card_status_check_at?: string | null
}
// 设备绑定卡信息
@@ -45,6 +49,9 @@ export interface BindingCard {
real_name_status?: number
realname_policy?: string
gateway_extend?: string
last_data_check_at?: string | null
last_real_name_check_at?: string | null
last_card_status_check_at?: string | null
}
// 设备实时信息接口
@@ -99,7 +106,9 @@ export interface DeviceRealtimeInfo {
// 套餐信息接口
export interface PackageInfo {
id: number
package_usage_id?: number
package_id: number
order_id?: number
package_name: string
package_price: number
paid_amount?: number
@@ -114,6 +123,7 @@ export interface PackageInfo {
status: number
status_name?: string
duration_days?: number
data_usage_mb?: number
reduction_pct?: number // 展示增幅比例
package_type?: string // 套餐类型: formal正式套餐/ addon加油包
enable_virtual_data?: boolean // 是否启用虚流量

View File

@@ -243,6 +243,15 @@
<ElInput v-model="seriesBindingForm.virtual_no_end" placeholder="请输入结束设备号" />
</ElFormItem>
<div
v-if="
seriesBindingForm.selection_type === DeviceSelectionType.RANGE &&
seriesBindingRangeCountText
"
class="range-allocation-hint range-allocation-hint--device"
>
共分配{{ seriesBindingRangeCountText }}台设备
</div>
<ElFormItem
v-if="seriesBindingForm.selection_type === DeviceSelectionType.FILTER"
label="设备号"
@@ -666,7 +675,7 @@
</template>
<script setup lang="ts">
import { h } from 'vue'
import { computed, h } from 'vue'
import { useRouter } from 'vue-router'
import { RoutesAlias } from '@/router/routesAlias'
import {
@@ -814,6 +823,65 @@
created_at_end: ''
})
const seriesBindingForm = reactive(createInitialSeriesBindingState())
const parseNumericStringToBigInt = (value: string): bigint | null => {
const normalizedValue = value.trim()
if (!normalizedValue || !/^\d+$/.test(normalizedValue)) {
return null
}
try {
return BigInt(normalizedValue)
} catch {
return null
}
}
const getPositiveRangeCountText = (start: bigint | null, end: bigint | null): string => {
if (start === null || end === null || end < start) {
return ''
}
return (end - start + 1n).toString()
}
const parseDeviceRangeEndpoint = (value: string): { prefix: string; number: bigint } | null => {
const normalizedValue = value.trim()
if (!normalizedValue) {
return null
}
const numericValue = parseNumericStringToBigInt(normalizedValue)
if (numericValue !== null) {
return {
prefix: '',
number: numericValue
}
}
const match = normalizedValue.match(/^(.*?)(\d+)$/)
if (!match) {
return null
}
try {
return {
prefix: match[1],
number: BigInt(match[2])
}
} catch {
return null
}
}
const getDeviceRangeCountText = (startValue: string, endValue: string): string => {
const start = parseDeviceRangeEndpoint(startValue)
const end = parseDeviceRangeEndpoint(endValue)
if (!start || !end || start.prefix !== end.prefix) {
return ''
}
return getPositiveRangeCountText(start.number, end.number)
}
const seriesBindingRangeCountText = computed(() =>
getDeviceRangeCountText(seriesBindingForm.virtual_no_start, seriesBindingForm.virtual_no_end)
)
const seriesBindingRules = reactive<FormRules>({
selection_type: [{ required: true, message: '请选择选设备方式', trigger: 'change' }],
series_id: [{ required: true, message: '请选择套餐系列', trigger: 'change' }],
@@ -2389,6 +2457,16 @@
height: 100%;
}
.range-allocation-hint {
color: var(--el-text-color-secondary);
font-size: 13px;
line-height: 20px;
}
.range-allocation-hint--device {
margin: -6px 0 18px 120px;
}
:deep(.el-table__row.table-row-with-context-menu) {
cursor: pointer;
}

View File

@@ -379,6 +379,15 @@
>
<ElInput v-model="seriesBindingForm.iccid_end" placeholder="请输入结束ICCID" />
</ElFormItem>
<div
v-if="
seriesBindingForm.selection_type === CardSelectionType.RANGE &&
seriesBindingRangeCountText
"
class="range-allocation-hint range-allocation-hint--card"
>
共分配{{ seriesBindingRangeCountText }}张卡
</div>
<ElFormItem
v-if="seriesBindingForm.selection_type === CardSelectionType.FILTER"
label="运营商"
@@ -608,7 +617,7 @@
</template>
<script setup lang="ts">
import { h } from 'vue'
import { computed, h } from 'vue'
import { useRouter } from 'vue-router'
import { RoutesAlias } from '@/router/routesAlias'
import {
@@ -689,6 +698,31 @@
batch_no: ''
})
const seriesBindingForm = reactive(createInitialSeriesBindingState())
const parseNumericStringToBigInt = (value: string): bigint | null => {
const normalizedValue = value.trim()
if (!normalizedValue || !/^\d+$/.test(normalizedValue)) {
return null
}
try {
return BigInt(normalizedValue)
} catch {
return null
}
}
const getPositiveRangeCountText = (start: bigint | null, end: bigint | null): string => {
if (start === null || end === null || end < start) {
return ''
}
return (end - start + 1n).toString()
}
const seriesBindingRangeCountText = computed(() =>
getPositiveRangeCountText(
parseNumericStringToBigInt(seriesBindingForm.iccid_start),
parseNumericStringToBigInt(seriesBindingForm.iccid_end)
)
)
const seriesBindingRules = reactive<FormRules>({
selection_type: [{ required: true, message: '请选择选卡方式', trigger: 'change' }],
series_id: [{ required: true, message: '请选择套餐系列', trigger: 'change' }],
@@ -2149,6 +2183,16 @@
</script>
<style lang="scss" scoped>
.range-allocation-hint {
color: var(--el-text-color-secondary);
font-size: 13px;
line-height: 20px;
}
.range-allocation-hint--card {
margin: -6px 0 18px 100px;
}
:deep(.el-table__row.table-row-with-context-menu) {
cursor: pointer;
}

View File

@@ -60,15 +60,14 @@
<ElFormItem label="充值金额" prop="amount">
<ElInputNumber
v-model="createForm.amount"
:min="100"
:max="1000000"
:min="0.01"
:precision="2"
:step="100"
:step="0.01"
style="width: 100%"
placeholder="请输入充值金额(元)"
/>
<div style="margin-top: 8px; font-size: 12px; color: var(--el-text-color-secondary)">
充值范围: ¥100 ~ ¥1,000,000
最小: ¥0.01最大: 不限制
</div>
</ElFormItem>
<ElFormItem label="支付方式" prop="payment_method">
@@ -337,10 +336,27 @@
const createFormRef = ref<FormInstance>()
const confirmPayFormRef = ref<FormInstance>()
const uploadRef = ref()
const MIN_RECHARGE_AMOUNT = 0.01
const createRules = computed<FormRules>(() => {
const rules: FormRules = {
amount: [{ required: true, message: '请输入充值金额', trigger: 'blur' }],
amount: [
{ required: true, message: '请输入充值金额', trigger: 'blur' },
{
validator: (_rule, value, callback) => {
if (value == null || value === '') {
callback()
return
}
if (Number(value) < MIN_RECHARGE_AMOUNT) {
callback(new Error(`充值金额最小为 ¥${MIN_RECHARGE_AMOUNT.toFixed(2)}`))
return
}
callback()
},
trigger: 'blur'
}
],
payment_method: [{ required: true, message: '请选择支付方式', trigger: 'change' }],
shop_id: [{ required: true, message: '请选择目标店铺', trigger: 'change' }]
}
@@ -362,7 +378,7 @@
shop_id: number | null
payment_voucher_key?: string
}>({
amount: 100,
amount: MIN_RECHARGE_AMOUNT,
payment_method: '',
shop_id: null,
payment_voucher_key: undefined
@@ -646,7 +662,7 @@
// 对话框关闭后的清理
const handleCreateDialogClosed = () => {
createFormRef.value?.resetFields()
createForm.amount = 100
createForm.amount = MIN_RECHARGE_AMOUNT
createForm.payment_method = ''
createForm.shop_id = null
createForm.payment_voucher_key = undefined
@@ -702,14 +718,15 @@
// 创建充值订单
const handleCreateRecharge = async () => {
if (!createFormRef.value) return
const formRef = createFormRef.value
if (!formRef) return
await createFormRef.value.validate(async (valid) => {
await formRef.validate(async (valid) => {
if (valid) {
createLoading.value = true
try {
const data: CreateAgentRechargeRequest = {
amount: createForm.amount * 100, // 元转分
amount: Math.round(createForm.amount * 100), // 元转分
payment_method: createForm.payment_method as AgentRechargePaymentMethod,
shop_id: createForm.shop_id!
}
@@ -721,7 +738,7 @@
await AgentRechargeService.createAgentRecharge(data)
ElMessage.success('充值订单创建成功')
createDialogVisible.value = false
createFormRef.value.resetFields()
formRef.resetFields()
await getTableData()
} catch (error) {
console.error(error)
@@ -747,18 +764,20 @@
// 确认线下支付
const handleConfirmPay = async () => {
if (!confirmPayFormRef.value || !currentRecharge.value) return
const formRef = confirmPayFormRef.value
const recharge = currentRecharge.value
if (!formRef || !recharge) return
await confirmPayFormRef.value.validate(async (valid) => {
await formRef.validate(async (valid) => {
if (valid) {
confirmPayLoading.value = true
try {
await AgentRechargeService.confirmOfflinePayment(currentRecharge.value.id, {
await AgentRechargeService.confirmOfflinePayment(recharge.id, {
operation_password: confirmPayForm.operation_password
})
ElMessage.success('确认支付成功')
confirmPayDialogVisible.value = false
confirmPayFormRef.value.resetFields()
formRef.resetFields()
await getTableData()
} catch (error) {
console.error(error)