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

@@ -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;
}