Files
one-pipe-system/src/views/product/sim-card/index.vue
sexygoat 222e5bb11a Initial commit: One Pipe System
完整的管理系统,包含账户管理、卡片管理、套餐管理、财务管理等功能模块。

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-01-22 16:35:33 +08:00

276 lines
9.4 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="page-content">
<ElRow>
<ElCol :xs="24" :sm="12" :lg="6">
<ElInput v-model="searchQuery" placeholder="号卡名称/编码" clearable></ElInput>
</ElCol>
<div style="width: 12px"></div>
<ElCol :xs="24" :sm="12" :lg="6">
<ElSelect v-model="operatorFilter" placeholder="运营商" clearable style="width: 100%">
<ElOption label="中国移动" value="cmcc" />
<ElOption label="中国联通" value="cucc" />
<ElOption label="中国电信" value="ctcc" />
</ElSelect>
</ElCol>
<div style="width: 12px"></div>
<ElCol :xs="24" :sm="12" :lg="6" class="el-col2">
<ElButton v-ripple @click="handleSearch">搜索</ElButton>
<ElButton v-ripple @click="showDialog('add')">新增号卡</ElButton>
</ElCol>
</ElRow>
<ArtTable :data="filteredData" index>
<template #default>
<ElTableColumn label="号卡名称" prop="cardName" min-width="150" />
<ElTableColumn label="号卡编码" prop="cardCode" />
<ElTableColumn label="运营商" prop="operator">
<template #default="scope">
<ElTag :type="getOperatorTagType(scope.row.operator)">
{{ getOperatorText(scope.row.operator) }}
</ElTag>
</template>
</ElTableColumn>
<ElTableColumn label="套餐类型" prop="packageType" />
<ElTableColumn label="月租(元)" prop="monthlyFee">
<template #default="scope"> ¥{{ scope.row.monthlyFee.toFixed(2) }} </template>
</ElTableColumn>
<ElTableColumn label="库存" prop="stock" />
<ElTableColumn label="状态" prop="status">
<template #default="scope">
<ElTag :type="scope.row.status === 'online' ? 'success' : 'info'">
{{ scope.row.status === 'online' ? '上架' : '下架' }}
</ElTag>
</template>
</ElTableColumn>
<ElTableColumn label="创建时间" prop="createTime" width="180" />
<ElTableColumn fixed="right" label="操作" width="180">
<template #default="scope">
<el-button link @click="showDialog('edit', scope.row)">编辑</el-button>
<el-button
link
:type="scope.row.status === 'online' ? 'danger' : 'primary'"
@click="toggleStatus(scope.row)"
>
{{ scope.row.status === 'online' ? '下架' : '上架' }}
</el-button>
</template>
</ElTableColumn>
</template>
</ArtTable>
<ElDialog
v-model="dialogVisible"
:title="dialogType === 'add' ? '新增号卡' : '编辑号卡'"
width="700px"
align-center
>
<ElForm ref="formRef" :model="form" :rules="rules" label-width="120px">
<ElRow :gutter="20">
<ElCol :span="12">
<ElFormItem label="号卡名称" prop="cardName">
<ElInput v-model="form.cardName" placeholder="请输入号卡名称" />
</ElFormItem>
</ElCol>
<ElCol :span="12">
<ElFormItem label="号卡编码" prop="cardCode">
<ElInput v-model="form.cardCode" placeholder="请输入号卡编码" />
</ElFormItem>
</ElCol>
</ElRow>
<ElRow :gutter="20">
<ElCol :span="12">
<ElFormItem label="运营商" prop="operator">
<ElSelect v-model="form.operator" placeholder="请选择运营商" style="width: 100%">
<ElOption label="中国移动" value="cmcc" />
<ElOption label="中国联通" value="cucc" />
<ElOption label="中国电信" value="ctcc" />
</ElSelect>
</ElFormItem>
</ElCol>
<ElCol :span="12">
<ElFormItem label="套餐类型" prop="packageType">
<ElInput v-model="form.packageType" placeholder="例如:流量套餐" />
</ElFormItem>
</ElCol>
</ElRow>
<ElRow :gutter="20">
<ElCol :span="12">
<ElFormItem label="月租(元)" prop="monthlyFee">
<ElInputNumber v-model="form.monthlyFee" :min="0" :precision="2" style="width: 100%" />
</ElFormItem>
</ElCol>
<ElCol :span="12">
<ElFormItem label="初始库存" prop="stock">
<ElInputNumber v-model="form.stock" :min="0" style="width: 100%" />
</ElFormItem>
</ElCol>
</ElRow>
<ElFormItem label="号卡描述" prop="description">
<ElInput v-model="form.description" type="textarea" :rows="3" placeholder="请输入号卡描述" />
</ElFormItem>
<ElFormItem label="状态">
<ElSwitch v-model="form.status" active-value="online" inactive-value="offline" />
<span style="margin-left: 8px; color: var(--el-text-color-secondary)">{{
form.status === 'online' ? '上架' : '下架'
}}</span>
</ElFormItem>
</ElForm>
<template #footer>
<div class="dialog-footer">
<ElButton @click="dialogVisible = false">取消</ElButton>
<ElButton type="primary" @click="handleSubmit(formRef)">提交</ElButton>
</div>
</template>
</ElDialog>
</div>
</template>
<script setup lang="ts">
import { ElMessage, ElMessageBox } from 'element-plus'
import type { FormInstance, FormRules } from 'element-plus'
defineOptions({ name: 'SimCard' })
interface SimCard {
id?: string
cardName: string
cardCode: string
operator: string
packageType: string
monthlyFee: number
stock: number
description?: string
status: 'online' | 'offline'
createTime?: string
}
const mockData = ref<SimCard[]>([
{
id: '1',
cardName: '移动流量卡30GB',
cardCode: 'CARD_CMCC_30GB',
operator: 'cmcc',
packageType: '流量套餐',
monthlyFee: 29.9,
stock: 1000,
description: '移动30GB流量卡全国通用',
status: 'online',
createTime: '2026-01-01 10:00:00'
},
{
id: '2',
cardName: '联通流量卡50GB',
cardCode: 'CARD_CUCC_50GB',
operator: 'cucc',
packageType: '流量套餐',
monthlyFee: 49.9,
stock: 800,
description: '联通50GB流量卡全国通用',
status: 'online',
createTime: '2026-01-02 11:00:00'
}
])
const searchQuery = ref('')
const operatorFilter = ref('')
const dialogVisible = ref(false)
const dialogType = ref<'add' | 'edit'>('add')
const formRef = ref<FormInstance>()
const form = reactive<SimCard>({
cardName: '',
cardCode: '',
operator: '',
packageType: '',
monthlyFee: 0,
stock: 0,
description: '',
status: 'online'
})
const rules = reactive<FormRules>({
cardName: [{ required: true, message: '请输入号卡名称', trigger: 'blur' }],
cardCode: [{ required: true, message: '请输入号卡编码', trigger: 'blur' }],
operator: [{ required: true, message: '请选择运营商', trigger: 'change' }],
monthlyFee: [{ required: true, message: '请输入月租', trigger: 'blur' }]
})
const filteredData = computed(() => {
let data = mockData.value
if (searchQuery.value) {
data = data.filter(
(item) => item.cardName.includes(searchQuery.value) || item.cardCode.includes(searchQuery.value)
)
}
if (operatorFilter.value) {
data = data.filter((item) => item.operator === operatorFilter.value)
}
return data
})
const getOperatorText = (operator: string) => {
const map: Record<string, string> = { cmcc: '中国移动', cucc: '中国联通', ctcc: '中国电信' }
return map[operator] || '未知'
}
const getOperatorTagType = (operator: string) => {
const map: Record<string, string> = { cmcc: '', cucc: 'success', ctcc: 'warning' }
return map[operator] || 'info'
}
const handleSearch = () => {}
const showDialog = (type: 'add' | 'edit', row?: SimCard) => {
dialogType.value = type
dialogVisible.value = true
if (type === 'edit' && row) {
Object.assign(form, row)
} else {
Object.assign(form, {
cardName: '',
cardCode: '',
operator: '',
packageType: '',
monthlyFee: 0,
stock: 0,
description: '',
status: 'online'
})
}
}
const handleSubmit = async (formEl: FormInstance | undefined) => {
if (!formEl) return
await formEl.validate((valid) => {
if (valid) {
if (dialogType.value === 'add') {
mockData.value.push({
...form,
id: Date.now().toString(),
createTime: new Date().toLocaleString('zh-CN')
})
ElMessage.success('新增成功')
} else {
const index = mockData.value.findIndex((item) => item.id === form.id)
if (index !== -1) mockData.value[index] = { ...form }
ElMessage.success('修改成功')
}
dialogVisible.value = false
formEl.resetFields()
}
})
}
const toggleStatus = (row: SimCard) => {
const action = row.status === 'online' ? '下架' : '上架'
ElMessageBox.confirm(`确定要${action}该号卡吗?`, `${action}确认`, {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
row.status = row.status === 'online' ? 'offline' : 'online'
ElMessage.success(`${action}成功`)
})
}
</script>