Initial commit: One Pipe System
完整的管理系统,包含账户管理、卡片管理、套餐管理、财务管理等功能模块。 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
468
src/views/card-management/single-card/index.vue
Normal file
468
src/views/card-management/single-card/index.vue
Normal file
@@ -0,0 +1,468 @@
|
||||
<template>
|
||||
<ArtTableFullScreen>
|
||||
<div class="single-card-page" id="table-full-screen">
|
||||
<!-- 网卡信息卡片 -->
|
||||
<ElCard shadow="never" class="card-info-card" style="margin-bottom: 16px">
|
||||
<template #header>
|
||||
<span>网卡信息</span>
|
||||
</template>
|
||||
<ElForm :model="cardInfo" label-width="120px" :inline="false">
|
||||
<ElRow :gutter="24">
|
||||
<ElCol :span="8">
|
||||
<ElFormItem label="ICCID:">
|
||||
<span>{{ cardInfo.iccid }}</span>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :span="8">
|
||||
<ElFormItem label="IMSI:">
|
||||
<span>{{ cardInfo.imsi }}</span>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :span="8">
|
||||
<ElFormItem label="手机号码:">
|
||||
<span>{{ cardInfo.msisdn }}</span>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
</ElRow>
|
||||
<ElRow :gutter="24">
|
||||
<ElCol :span="8">
|
||||
<ElFormItem label="运营商:">
|
||||
<ElTag :type="getOperatorTagType(cardInfo.operator)">{{
|
||||
cardInfo.operatorName
|
||||
}}</ElTag>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :span="8">
|
||||
<ElFormItem label="网络类型:">
|
||||
<span>{{ cardInfo.networkType }}</span>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
<ElCol :span="8">
|
||||
<ElFormItem label="状态:">
|
||||
<ElTag :type="getStatusTagType(cardInfo.status)">{{ cardInfo.statusName }}</ElTag>
|
||||
</ElFormItem>
|
||||
</ElCol>
|
||||
</ElRow>
|
||||
</ElForm>
|
||||
</ElCard>
|
||||
|
||||
<!-- 操作区域 -->
|
||||
<ElCard shadow="never" class="operation-card" style="margin-bottom: 16px">
|
||||
<template #header>
|
||||
<span>操作区域</span>
|
||||
</template>
|
||||
<div class="operation-buttons">
|
||||
<ElButton type="primary" @click="activateCard" :disabled="cardInfo.status === '1'"
|
||||
>激活网卡</ElButton
|
||||
>
|
||||
<ElButton type="warning" @click="suspendCard" :disabled="cardInfo.status === '2'"
|
||||
>停用网卡</ElButton
|
||||
>
|
||||
<ElButton type="success" @click="showRechargeDialog">充值</ElButton>
|
||||
<ElButton type="info" @click="queryTraffic">流量查询</ElButton>
|
||||
<ElButton type="danger" @click="resetCard">重置网卡</ElButton>
|
||||
<ElButton @click="diagnoseCard">网卡诊断</ElButton>
|
||||
</div>
|
||||
</ElCard>
|
||||
|
||||
<!-- 流量信息 -->
|
||||
<ElCard shadow="never" class="traffic-card" style="margin-bottom: 16px">
|
||||
<template #header>
|
||||
<span>流量信息</span>
|
||||
</template>
|
||||
<ElRow :gutter="24">
|
||||
<ElCol :span="6">
|
||||
<div class="traffic-item">
|
||||
<div class="traffic-value">{{ trafficInfo.totalTraffic }}</div>
|
||||
<div class="traffic-label">总流量</div>
|
||||
</div>
|
||||
</ElCol>
|
||||
<ElCol :span="6">
|
||||
<div class="traffic-item">
|
||||
<div class="traffic-value used">{{ trafficInfo.usedTraffic }}</div>
|
||||
<div class="traffic-label">已用流量</div>
|
||||
</div>
|
||||
</ElCol>
|
||||
<ElCol :span="6">
|
||||
<div class="traffic-item">
|
||||
<div class="traffic-value remaining">{{ trafficInfo.remainingTraffic }}</div>
|
||||
<div class="traffic-label">剩余流量</div>
|
||||
</div>
|
||||
</ElCol>
|
||||
<ElCol :span="6">
|
||||
<div class="traffic-item">
|
||||
<div class="traffic-value percentage">{{ trafficInfo.usagePercentage }}%</div>
|
||||
<div class="traffic-label">使用率</div>
|
||||
</div>
|
||||
</ElCol>
|
||||
</ElRow>
|
||||
<ElProgress :percentage="parseInt(trafficInfo.usagePercentage)" style="margin-top: 16px" />
|
||||
</ElCard>
|
||||
|
||||
<!-- 使用记录 -->
|
||||
<ElCard shadow="never" class="art-table-card">
|
||||
<template #header>
|
||||
<span>使用记录</span>
|
||||
<ElButton style="float: right" @click="refreshUsageRecords">刷新</ElButton>
|
||||
</template>
|
||||
|
||||
<ArtTable
|
||||
ref="tableRef"
|
||||
row-key="id"
|
||||
:loading="loading"
|
||||
:data="usageRecords"
|
||||
:currentPage="pagination.currentPage"
|
||||
:pageSize="pagination.pageSize"
|
||||
:total="pagination.total"
|
||||
@size-change="handleSizeChange"
|
||||
@current-change="handleCurrentChange"
|
||||
>
|
||||
<template #default>
|
||||
<ElTableColumn v-for="col in usageColumns" :key="col.prop || col.type" v-bind="col" />
|
||||
</template>
|
||||
</ArtTable>
|
||||
</ElCard>
|
||||
|
||||
<!-- 充值对话框 -->
|
||||
<ElDialog v-model="rechargeDialogVisible" title="网卡充值" width="400px" align-center>
|
||||
<ElForm
|
||||
ref="rechargeFormRef"
|
||||
:model="rechargeForm"
|
||||
:rules="rechargeRules"
|
||||
label-width="100px"
|
||||
>
|
||||
<ElFormItem label="充值金额" prop="amount">
|
||||
<ElInput v-model="rechargeForm.amount" placeholder="请输入充值金额">
|
||||
<template #append>元</template>
|
||||
</ElInput>
|
||||
</ElFormItem>
|
||||
<ElFormItem label="充值方式" prop="method">
|
||||
<ElSelect v-model="rechargeForm.method" placeholder="请选择充值方式">
|
||||
<ElOption label="支付宝" value="alipay" />
|
||||
<ElOption label="微信支付" value="wechat" />
|
||||
<ElOption label="银联支付" value="unionpay" />
|
||||
</ElSelect>
|
||||
</ElFormItem>
|
||||
</ElForm>
|
||||
<template #footer>
|
||||
<ElButton @click="rechargeDialogVisible = false">取消</ElButton>
|
||||
<ElButton type="primary" @click="handleRecharge">确认充值</ElButton>
|
||||
</template>
|
||||
</ElDialog>
|
||||
</div>
|
||||
</ArtTableFullScreen>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { h } from 'vue'
|
||||
import { ElTag, ElMessageBox, ElMessage, FormInstance } from 'element-plus'
|
||||
import { useRoute } from 'vue-router'
|
||||
import type { FormRules } from 'element-plus'
|
||||
|
||||
defineOptions({ name: 'SingleCard' })
|
||||
|
||||
const loading = ref(false)
|
||||
const rechargeDialogVisible = ref(false)
|
||||
const route = useRoute()
|
||||
|
||||
// 网卡信息
|
||||
const cardInfo = reactive({
|
||||
iccid: '89860123456789012345',
|
||||
imsi: '460012345678901',
|
||||
msisdn: '13800138001',
|
||||
operator: 'mobile',
|
||||
operatorName: '中国移动',
|
||||
networkType: '4G',
|
||||
status: '1',
|
||||
statusName: '激活',
|
||||
activatedDate: '2024-01-15',
|
||||
expiryDate: '2025-01-15'
|
||||
})
|
||||
|
||||
// 流量信息
|
||||
const trafficInfo = reactive({
|
||||
totalTraffic: '10GB',
|
||||
usedTraffic: '2.5GB',
|
||||
remainingTraffic: '7.5GB',
|
||||
usagePercentage: '25'
|
||||
})
|
||||
|
||||
const pagination = reactive({
|
||||
currentPage: 1,
|
||||
pageSize: 10,
|
||||
total: 0
|
||||
})
|
||||
|
||||
// 使用记录
|
||||
const usageRecords = ref([
|
||||
{
|
||||
id: 1,
|
||||
date: '2024-11-07',
|
||||
time: '14:30:25',
|
||||
dataUsage: '125.6MB',
|
||||
fee: '0.12',
|
||||
location: '北京市朝阳区'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
date: '2024-11-07',
|
||||
time: '13:45:12',
|
||||
dataUsage: '256.8MB',
|
||||
fee: '0.26',
|
||||
location: '北京市朝阳区'
|
||||
}
|
||||
])
|
||||
|
||||
// 充值表单
|
||||
const rechargeForm = reactive({
|
||||
amount: '',
|
||||
method: ''
|
||||
})
|
||||
|
||||
const rechargeFormRef = ref<FormInstance>()
|
||||
|
||||
// 表格列配置
|
||||
const usageColumns = [
|
||||
{
|
||||
prop: 'date',
|
||||
label: '日期',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
prop: 'time',
|
||||
label: '时间',
|
||||
width: 100
|
||||
},
|
||||
{
|
||||
prop: 'dataUsage',
|
||||
label: '流量使用量',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
prop: 'fee',
|
||||
label: '费用(元)',
|
||||
width: 100,
|
||||
formatter: (row: any) => `¥${row.fee}`
|
||||
},
|
||||
{
|
||||
prop: 'location',
|
||||
label: '位置',
|
||||
minWidth: 140
|
||||
}
|
||||
]
|
||||
|
||||
// 获取运营商标签类型
|
||||
const getOperatorTagType = (operator: string) => {
|
||||
switch (operator) {
|
||||
case 'mobile':
|
||||
return 'success'
|
||||
case 'unicom':
|
||||
return 'primary'
|
||||
case 'telecom':
|
||||
return 'warning'
|
||||
default:
|
||||
return 'info'
|
||||
}
|
||||
}
|
||||
|
||||
// 获取状态标签类型
|
||||
const getStatusTagType = (status: string) => {
|
||||
switch (status) {
|
||||
case '1':
|
||||
return 'success'
|
||||
case '2':
|
||||
return 'danger'
|
||||
case '3':
|
||||
return 'warning'
|
||||
case '4':
|
||||
return 'info'
|
||||
default:
|
||||
return 'info'
|
||||
}
|
||||
}
|
||||
|
||||
// 激活网卡
|
||||
const activateCard = () => {
|
||||
ElMessageBox.confirm('确定要激活该网卡吗?', '激活网卡', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'info'
|
||||
}).then(() => {
|
||||
cardInfo.status = '1'
|
||||
cardInfo.statusName = '激活'
|
||||
ElMessage.success('网卡激活成功')
|
||||
})
|
||||
}
|
||||
|
||||
// 停用网卡
|
||||
const suspendCard = () => {
|
||||
ElMessageBox.confirm('确定要停用该网卡吗?', '停用网卡', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
cardInfo.status = '2'
|
||||
cardInfo.statusName = '停用'
|
||||
ElMessage.success('网卡停用成功')
|
||||
})
|
||||
}
|
||||
|
||||
// 显示充值对话框
|
||||
const showRechargeDialog = () => {
|
||||
rechargeDialogVisible.value = true
|
||||
if (rechargeFormRef.value) {
|
||||
rechargeFormRef.value.resetFields()
|
||||
}
|
||||
}
|
||||
|
||||
// 流量查询
|
||||
const queryTraffic = () => {
|
||||
ElMessage.info('正在查询流量信息...')
|
||||
// 这里可以调用API查询最新的流量信息
|
||||
}
|
||||
|
||||
// 重置网卡
|
||||
const resetCard = () => {
|
||||
ElMessageBox.confirm('确定要重置该网卡吗?重置后网卡需要重新激活。', '重置网卡', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'error'
|
||||
}).then(() => {
|
||||
ElMessage.success('网卡重置成功')
|
||||
})
|
||||
}
|
||||
|
||||
// 网卡诊断
|
||||
const diagnoseCard = () => {
|
||||
ElMessage.info('正在进行网卡诊断...')
|
||||
setTimeout(() => {
|
||||
ElMessage.success('网卡诊断完成,网卡状态正常')
|
||||
}, 2000)
|
||||
}
|
||||
|
||||
// 充值验证规则
|
||||
const rechargeRules: FormRules = {
|
||||
amount: [
|
||||
{ required: true, message: '请输入充值金额', trigger: 'blur' },
|
||||
{ pattern: /^\d+(\.\d{1,2})?$/, message: '请输入正确的金额格式', trigger: 'blur' }
|
||||
],
|
||||
method: [{ required: true, message: '请选择充值方式', trigger: 'change' }]
|
||||
}
|
||||
|
||||
// 处理充值
|
||||
const handleRecharge = async () => {
|
||||
if (!rechargeFormRef.value) return
|
||||
|
||||
await rechargeFormRef.value.validate((valid) => {
|
||||
if (valid) {
|
||||
ElMessage.success('充值成功')
|
||||
rechargeDialogVisible.value = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 刷新使用记录
|
||||
const refreshUsageRecords = () => {
|
||||
ElMessage.info('正在刷新使用记录...')
|
||||
// 这里可以调用API获取最新的使用记录
|
||||
}
|
||||
|
||||
// 处理表格分页变化
|
||||
const handleSizeChange = (newPageSize: number) => {
|
||||
pagination.pageSize = newPageSize
|
||||
// 重新获取数据
|
||||
}
|
||||
|
||||
const handleCurrentChange = (newCurrentPage: number) => {
|
||||
pagination.currentPage = newCurrentPage
|
||||
// 重新获取数据
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// 检查是否有传递的ICCID参数
|
||||
const iccidFromQuery = route.query.iccid as string
|
||||
if (iccidFromQuery) {
|
||||
// 如果有ICCID参数,更新卡片信息
|
||||
cardInfo.iccid = iccidFromQuery
|
||||
// 可以在这里根据ICCID获取完整的卡片信息
|
||||
console.log('从网卡明细跳转,ICCID:', iccidFromQuery)
|
||||
// 模拟根据ICCID获取卡片详细信息
|
||||
loadCardInfoByIccid(iccidFromQuery)
|
||||
}
|
||||
|
||||
// 初始化数据
|
||||
pagination.total = usageRecords.value.length
|
||||
})
|
||||
|
||||
// 根据ICCID加载卡片信息
|
||||
const loadCardInfoByIccid = async (iccid: string) => {
|
||||
loading.value = true
|
||||
try {
|
||||
// 这里应该调用API根据ICCID获取卡片详细信息
|
||||
// 模拟API调用
|
||||
await new Promise((resolve) => setTimeout(resolve, 500))
|
||||
|
||||
// 模拟更新卡片信息(实际应该从API获取)
|
||||
Object.assign(cardInfo, {
|
||||
iccid: iccid,
|
||||
imsi: '460012345678901',
|
||||
msisdn: '13800138001',
|
||||
operator: 'mobile',
|
||||
operatorName: '中国移动',
|
||||
networkType: '4G',
|
||||
status: '1',
|
||||
statusName: '激活',
|
||||
activatedDate: '2024-01-15',
|
||||
expiryDate: '2025-01-15'
|
||||
})
|
||||
|
||||
ElMessage.success(`已加载ICCID ${iccid} 的详细信息`)
|
||||
} catch (error) {
|
||||
console.error('获取卡片信息失败:', error)
|
||||
ElMessage.error('获取卡片信息失败')
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.single-card-page {
|
||||
.operation-buttons {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.traffic-card {
|
||||
.traffic-item {
|
||||
padding: 16px;
|
||||
text-align: center;
|
||||
|
||||
.traffic-value {
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
color: var(--el-color-primary);
|
||||
|
||||
&.used {
|
||||
color: var(--el-color-warning);
|
||||
}
|
||||
|
||||
&.remaining {
|
||||
color: var(--el-color-success);
|
||||
}
|
||||
|
||||
&.percentage {
|
||||
color: var(--el-color-info);
|
||||
}
|
||||
}
|
||||
|
||||
.traffic-label {
|
||||
margin-top: 8px;
|
||||
font-size: 14px;
|
||||
color: var(--el-text-color-regular);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user