This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* 认证模块 API
|
||||
*/
|
||||
import { get, post } from '@/utils/request'
|
||||
import { get, post, put } from '@/utils/request'
|
||||
|
||||
/**
|
||||
* 登录请求参数
|
||||
@@ -104,8 +104,5 @@ export function refreshToken(refresh_token: string) {
|
||||
* PUT /api/auth/password
|
||||
*/
|
||||
export function changePassword(data: ChangePasswordParams) {
|
||||
return post<void>('/api/auth/password', {
|
||||
data,
|
||||
method: 'PUT',
|
||||
})
|
||||
return put<void>('/api/auth/password', { data })
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
{
|
||||
"path": "pages/agent-system/home/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "卡管H5",
|
||||
"navigationBarTitleText": "代理企业端H5",
|
||||
"navigationStyle": "custom"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -112,12 +112,13 @@ const cardHasMore = ref(true)
|
||||
const deviceHasMore = ref(true)
|
||||
const pageSize = 20
|
||||
// 搜索和筛选
|
||||
const iccidKeyword = ref('')
|
||||
const virtualNoKeyword = ref('')
|
||||
const searchType = ref<'iccid' | 'virtual'>('iccid')
|
||||
const searchKeyword = ref('')
|
||||
const carrierFilter = ref<number | undefined>(undefined)
|
||||
const statusFilter = ref<number | undefined>(undefined)
|
||||
const showCarrierPicker = ref(false)
|
||||
const showStatusPicker = ref(false)
|
||||
const showSearchTypePicker = ref(false)
|
||||
// 运营商列表
|
||||
const carrierList = ref<CarrierInfo[]>([])
|
||||
// 运营商选择器选项
|
||||
@@ -133,6 +134,11 @@ const statusOptions = [
|
||||
{ label: '已激活', value: 3 },
|
||||
{ label: '已停用', value: 4 }
|
||||
]
|
||||
// 搜索类型选项
|
||||
const searchTypeOptions = [
|
||||
{ label: 'ICCID', value: 'iccid' },
|
||||
{ label: '虚拟号', value: 'virtual' }
|
||||
]
|
||||
|
||||
// 合并后的资产列表
|
||||
const assetList = computed<AssetItem[]>(() => {
|
||||
@@ -209,11 +215,12 @@ async function loadCards(isRefresh = false) {
|
||||
if (statusFilter.value !== undefined) {
|
||||
params.status = statusFilter.value
|
||||
}
|
||||
if (iccidKeyword.value) {
|
||||
params.iccid = iccidKeyword.value
|
||||
}
|
||||
if (virtualNoKeyword.value) {
|
||||
params.virtual_no = virtualNoKeyword.value
|
||||
if (searchKeyword.value) {
|
||||
if (searchType.value === 'iccid') {
|
||||
params.iccid = searchKeyword.value
|
||||
} else {
|
||||
params.virtual_no = searchKeyword.value
|
||||
}
|
||||
}
|
||||
|
||||
let cardsData: any
|
||||
@@ -269,8 +276,8 @@ async function loadDevices(isRefresh = false) {
|
||||
page_size: pageSize,
|
||||
}
|
||||
|
||||
if (virtualNoKeyword.value) {
|
||||
params.virtual_no = virtualNoKeyword.value
|
||||
if (searchKeyword.value) {
|
||||
params.virtual_no = searchKeyword.value
|
||||
}
|
||||
if (statusFilter.value !== undefined) {
|
||||
params.status = statusFilter.value
|
||||
@@ -351,6 +358,11 @@ function onStatusConfirm(option: { label: string, value: any }) {
|
||||
refreshList()
|
||||
}
|
||||
|
||||
// 选择搜索类型
|
||||
function onSearchTypeConfirm(option: { label: string, value: any }) {
|
||||
searchType.value = option.value
|
||||
}
|
||||
|
||||
// 获取当前选中的运营商名称
|
||||
const selectedCarrierName = computed(() => {
|
||||
if (carrierFilter.value === undefined) return '运营商'
|
||||
@@ -385,8 +397,7 @@ function changeTab(tab: 'card' | 'device') {
|
||||
if (activeTab.value === tab) return
|
||||
|
||||
activeTab.value = tab
|
||||
iccidKeyword.value = ''
|
||||
virtualNoKeyword.value = ''
|
||||
searchKeyword.value = ''
|
||||
carrierFilter.value = undefined
|
||||
statusFilter.value = undefined
|
||||
|
||||
@@ -565,104 +576,98 @@ onMounted(async () => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="bg-page safe-area-bottom min-h-screen">
|
||||
<!-- 搜索和筛选 -->
|
||||
<view class="safe-area-top px-4 pt-4 pb-3">
|
||||
<!-- IoT卡搜索和筛选 -->
|
||||
<view v-if="activeTab === 'card'">
|
||||
<!-- ICCID搜索 -->
|
||||
<view class="bg-white rounded-full px-4 py-2 flex items-center mb-2">
|
||||
<i class="i-mdi-credit-card text-lg text-[#94a3b8] mr-2" />
|
||||
<input
|
||||
v-model="iccidKeyword"
|
||||
class="flex-1 text-sm text-[#1e293b]"
|
||||
placeholder="ICCID"
|
||||
/>
|
||||
<i
|
||||
v-if="iccidKeyword"
|
||||
class="i-mdi-close-circle text-lg text-[#94a3b8] ml-2"
|
||||
@click="iccidKeyword = ''"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<!-- 虚拟号搜索 -->
|
||||
<view class="bg-white rounded-full px-4 py-2 flex items-center mb-2">
|
||||
<i class="i-mdi-phone text-lg text-[#94a3b8] mr-2" />
|
||||
<input
|
||||
v-model="virtualNoKeyword"
|
||||
class="flex-1 text-sm text-[#1e293b]"
|
||||
placeholder="虚拟号"
|
||||
/>
|
||||
<i
|
||||
v-if="virtualNoKeyword"
|
||||
class="i-mdi-close-circle text-lg text-[#94a3b8] ml-2"
|
||||
@click="virtualNoKeyword = ''"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<!-- 筛选条件 -->
|
||||
<view class="flex items-center gap-2 mb-2">
|
||||
<!-- 运营商 -->
|
||||
<view class="flex-1 bg-white rounded-full px-3 py-2 flex items-center" @click="showCarrierPicker = true">
|
||||
<text class="flex-1 text-sm text-[#1e293b]">{{ selectedCarrierName }}</text>
|
||||
<i class="i-mdi-chevron-down text-lg text-[#94a3b8]" />
|
||||
<view class="bg-page safe-area-bottom min-h-screen flex flex-col">
|
||||
<!-- 搜索区域 -->
|
||||
<view class="bg-white px-4 pt-4 pb-3">
|
||||
<!-- 搜索框 -->
|
||||
<view class="relative flex items-center">
|
||||
<input
|
||||
v-model="searchKeyword"
|
||||
class="flex-1 h-10 bg-[#f1f5f9] rounded-full pl-4 pr-12 text-sm text-[#1e293b] placeholder-[#94a3b8]"
|
||||
:placeholder="searchType === 'iccid' ? '搜索ICCID' : '搜索虚拟号'"
|
||||
@confirm="refreshList"
|
||||
/>
|
||||
<view
|
||||
class="absolute right-1 flex items-center"
|
||||
>
|
||||
<view
|
||||
v-if="searchKeyword"
|
||||
class="w-8 h-8 flex items-center justify-center text-[#94a3b8]"
|
||||
@click="searchKeyword = ''"
|
||||
>
|
||||
<i class="i-mdi-close-circle text-lg" />
|
||||
</view>
|
||||
|
||||
<!-- 状态 -->
|
||||
<view class="flex-1 bg-white rounded-full px-3 py-2 flex items-center" @click="showStatusPicker = true">
|
||||
<text class="flex-1 text-sm text-[#1e293b]">{{ selectedStatusName }}</text>
|
||||
<i class="i-mdi-chevron-down text-lg text-[#94a3b8]" />
|
||||
<view
|
||||
class="w-8 h-8 flex items-center justify-center text-brand"
|
||||
@click="refreshList"
|
||||
>
|
||||
<i class="i-mdi-magnify text-xl" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 搜索按钮 -->
|
||||
<view class="bg-brand rounded-full py-2.5 text-center" @click="refreshList">
|
||||
<text class="text-sm font-500 text-white">搜索</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 设备搜索 -->
|
||||
<view v-else>
|
||||
<view class="bg-white rounded-full px-4 py-2 flex items-center mb-2">
|
||||
<i class="i-mdi-phone text-lg text-[#94a3b8] mr-2" />
|
||||
<input
|
||||
v-model="virtualNoKeyword"
|
||||
class="flex-1 text-sm text-[#1e293b]"
|
||||
placeholder="虚拟号"
|
||||
/>
|
||||
<i
|
||||
v-if="virtualNoKeyword"
|
||||
class="i-mdi-close-circle text-lg text-[#94a3b8] ml-2"
|
||||
@click="virtualNoKeyword = ''"
|
||||
/>
|
||||
<!-- 筛选和类型切换 -->
|
||||
<view class="flex items-center gap-2 mt-3 flex-wrap">
|
||||
|
||||
<view
|
||||
class="flex items-center gap-1 px-3 py-1.5 bg-[#f8fafc] rounded-full flex-shrink-0"
|
||||
@click="showSearchTypePicker = true"
|
||||
>
|
||||
<text class="text-12px" :class="searchType !== 'iccid' ? 'text-brand font-medium' : 'text-[#64748b]'">
|
||||
{{ searchType === 'iccid' ? 'ICCID' : '虚拟号' }}
|
||||
</text>
|
||||
<i class="i-mdi-chevron-down text-12px text-[#94a3b8]" />
|
||||
</view>
|
||||
|
||||
<!-- 搜索按钮 -->
|
||||
<view class="bg-brand rounded-full py-2.5 text-center" @click="refreshList">
|
||||
<text class="text-sm font-500 text-white">搜索</text>
|
||||
<view
|
||||
class="flex items-center gap-1.5 px-3 py-1.5 bg-[#f8fafc] rounded-full flex-shrink-0 max-w-36"
|
||||
@click="showCarrierPicker = true"
|
||||
>
|
||||
<text class="text-12px truncate" :class="carrierFilter !== undefined ? 'text-brand font-medium' : 'text-[#64748b]'">
|
||||
{{ selectedCarrierName }}
|
||||
</text>
|
||||
<i class="i-mdi-chevron-down text-12px text-[#94a3b8] flex-shrink-0" />
|
||||
</view>
|
||||
|
||||
<view
|
||||
class="flex items-center gap-1.5 px-3 py-1.5 bg-[#f8fafc] rounded-full flex-shrink-0"
|
||||
@click="showStatusPicker = true"
|
||||
>
|
||||
<text class="text-12px" :class="statusFilter !== undefined ? 'text-brand font-medium' : 'text-[#64748b]'">
|
||||
{{ selectedStatusName }}
|
||||
</text>
|
||||
<i class="i-mdi-chevron-down text-12px text-[#94a3b8]" />
|
||||
</view>
|
||||
|
||||
<view
|
||||
v-if="carrierFilter !== undefined || statusFilter !== undefined"
|
||||
class="flex items-center gap-1 px-2 py-1.5 rounded-full bg-[#ff4d4f]/10 text-[#ff4d4f] flex-shrink-0"
|
||||
@click="carrierFilter = undefined; statusFilter = undefined; refreshList()"
|
||||
>
|
||||
<i class="i-mdi-close text-12px" />
|
||||
<text class="text-12px font-medium">清除</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 筛选标签 -->
|
||||
<view class="px-4 pb-3">
|
||||
<view class="bg-white rounded-full p-1 flex items-center">
|
||||
<!-- IoT卡 -->
|
||||
<view
|
||||
class="flex-1 py-2 rounded-full transition-fast text-center"
|
||||
:class="activeTab === 'card' ? 'bg-brand' : ''"
|
||||
@click="changeTab('card')"
|
||||
>
|
||||
<text class="text-sm font-500" :class="activeTab === 'card' ? 'text-white' : 'text-[#64748b]'">IoT卡</text>
|
||||
</view>
|
||||
|
||||
<!-- 设备 -->
|
||||
<view
|
||||
class="flex-1 py-2 rounded-full transition-fast text-center"
|
||||
:class="activeTab === 'device' ? 'bg-brand' : ''"
|
||||
@click="changeTab('device')"
|
||||
>
|
||||
<text class="text-sm font-500" :class="activeTab === 'device' ? 'text-white' : 'text-[#64748b]'">设备</text>
|
||||
<!-- 卡片/设备标签 -->
|
||||
<view class="bg-white px-4 pb-3">
|
||||
<view class="border-t border-[#f1f5f9] pt-3">
|
||||
<view class="bg-[#f1f5f9] rounded-full p-1 flex">
|
||||
<view
|
||||
class="flex-1 py-2 rounded-full text-center transition-all"
|
||||
:class="activeTab === 'card' ? 'bg-white shadow-sm text-[#1e293b] font-medium' : 'text-[#64748b]'"
|
||||
@click="changeTab('card')"
|
||||
>
|
||||
<text class="text-sm">IoT卡</text>
|
||||
</view>
|
||||
<view
|
||||
class="flex-1 py-2 rounded-full text-center transition-all"
|
||||
:class="activeTab === 'device' ? 'bg-white shadow-sm text-[#1e293b] font-medium' : 'text-[#64748b]'"
|
||||
@click="changeTab('device')"
|
||||
>
|
||||
<text class="text-sm">设备</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -673,8 +678,7 @@ onMounted(async () => {
|
||||
<!-- 资产列表 -->
|
||||
<view
|
||||
v-else
|
||||
class="overflow-y-auto"
|
||||
:style="{ height: activeTab === 'card' ? 'calc(100vh - 380px)' : 'calc(100vh - 280px)' }"
|
||||
class="flex-1 overflow-y-auto min-h-0"
|
||||
@scroll="onScroll"
|
||||
>
|
||||
<view v-if="assetList.length > 0" class="px-4 pb-4">
|
||||
@@ -730,36 +734,32 @@ onMounted(async () => {
|
||||
<template v-if="asset.type === 'card'">
|
||||
<template v-if="(asset.raw as CardInfo).network_status === 0">
|
||||
<view
|
||||
class="px-3 py-1 rounded-lg"
|
||||
style="background: #52c41a; color: white;"
|
||||
class="px-3 py-1.5 rounded-10px text-12px font-medium bg-[#52c41a] text-white shadow-sm shadow-[#52c41a]/30 active:scale-95 transition-transform"
|
||||
@click="handleStartCard(asset, $event)"
|
||||
>
|
||||
<text class="text-12px font-500">复机</text>
|
||||
复机
|
||||
</view>
|
||||
</template>
|
||||
<template v-else-if="(asset.raw as CardInfo).network_status === 1">
|
||||
<view
|
||||
class="px-3 py-1 rounded-lg"
|
||||
style="background: #ff4d4f; color: white;"
|
||||
class="px-3 py-1.5 rounded-10px text-12px font-medium bg-[#ff4d4f] text-white shadow-sm shadow-[#ff4d4f]/30 active:scale-95 transition-transform"
|
||||
@click="handleStopCard(asset, $event)"
|
||||
>
|
||||
<text class="text-12px font-500">停机</text>
|
||||
停机
|
||||
</view>
|
||||
</template>
|
||||
<template v-else>
|
||||
<view
|
||||
class="px-3 py-1 rounded-lg"
|
||||
style="background: #ff4d4f; color: white;"
|
||||
class="px-3 py-1.5 rounded-10px text-12px font-medium bg-[#ff4d4f] text-white shadow-sm shadow-[#ff4d4f]/30 active:scale-95 transition-transform"
|
||||
@click="handleStopCard(asset, $event)"
|
||||
>
|
||||
<text class="text-12px font-500">停机</text>
|
||||
停机
|
||||
</view>
|
||||
<view
|
||||
class="px-3 py-1 rounded-lg"
|
||||
style="background: #52c41a; color: white;"
|
||||
class="px-3 py-1.5 rounded-10px text-12px font-medium bg-[#52c41a] text-white shadow-sm shadow-[#52c41a]/30 active:scale-95 transition-transform"
|
||||
@click="handleStartCard(asset, $event)"
|
||||
>
|
||||
<text class="text-12px font-500">复机</text>
|
||||
复机
|
||||
</view>
|
||||
</template>
|
||||
</template>
|
||||
@@ -767,18 +767,16 @@ onMounted(async () => {
|
||||
<!-- 设备操作按钮 -->
|
||||
<template v-else>
|
||||
<view
|
||||
class="px-3 py-1 rounded-lg"
|
||||
style="background: #ff4d4f; color: white;"
|
||||
class="px-3 py-1.5 rounded-10px text-12px font-medium bg-[#ff4d4f] text-white shadow-sm shadow-[#ff4d4f]/30 active:scale-95 transition-transform"
|
||||
@click="handleStopDevice(asset, $event)"
|
||||
>
|
||||
<text class="text-12px font-500">停机</text>
|
||||
停机
|
||||
</view>
|
||||
<view
|
||||
class="px-3 py-1 rounded-lg"
|
||||
style="background: #52c41a; color: white;"
|
||||
class="px-3 py-1.5 rounded-10px text-12px font-medium bg-[#52c41a] text-white shadow-sm shadow-[#52c41a]/30 active:scale-95 transition-transform"
|
||||
@click="handleStartDevice(asset, $event)"
|
||||
>
|
||||
<text class="text-12px font-500">复机</text>
|
||||
复机
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@@ -802,7 +800,7 @@ onMounted(async () => {
|
||||
<view class="bg-white rounded-2xl py-12 flex flex-col items-center">
|
||||
<i class="i-mdi-package-variant-closed text-6xl text-[#cbd5e1] mb-3" />
|
||||
<text class="text-base text-[#64748b] mb-1">暂无数据</text>
|
||||
<text class="text-sm text-[#94a3b8]">{{ iccidKeyword || virtualNoKeyword ? '未找到相关结果' : '暂无资产数据' }}</text>
|
||||
<text class="text-sm text-[#94a3b8]">{{ searchKeyword ? '未找到相关结果' : '暂无资产数据' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -822,5 +820,13 @@ onMounted(async () => {
|
||||
title="选择状态"
|
||||
@confirm="onStatusConfirm"
|
||||
/>
|
||||
|
||||
<!-- 搜索类型选择器 -->
|
||||
<SimplePicker
|
||||
v-model:show="showSearchTypePicker"
|
||||
:options="searchTypeOptions"
|
||||
title="选择搜索类型"
|
||||
@confirm="onSearchTypeConfirm"
|
||||
/>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
300
代理企业管理系统-移动端.md
300
代理企业管理系统-移动端.md
@@ -1,300 +0,0 @@
|
||||
# 代理/企业管理系统 - 移动端 H5
|
||||
|
||||
> **小米米家APP风格** - 亮色、简约、大气的移动端单页应用
|
||||
|
||||
---
|
||||
|
||||
## 🚀 快速启动
|
||||
|
||||
```bash
|
||||
# 启动开发服务器
|
||||
pnpm dev:h5
|
||||
|
||||
# 访问地址
|
||||
http://localhost:5173/
|
||||
```
|
||||
|
||||
**默认入口**: `pages/agent-system/mobile.vue`
|
||||
|
||||
---
|
||||
|
||||
## ✨ 功能清单
|
||||
|
||||
### 代理端
|
||||
|
||||
| 模块 | 功能 | 状态 |
|
||||
|------|------|------|
|
||||
| 📊 数据概览 | 今日收益、累计佣金、资产统计 | ✅ |
|
||||
| 💰 佣金钱包 | 佣金余额、收益明细 | ✅ |
|
||||
| 💳 余额钱包 | 余额查询、充值记录 | ⏳ |
|
||||
| 🏦 提现管理 | 提现申请、提现记录 | ⏳ |
|
||||
| 📦 资产管理 | 资产列表 | ✅ |
|
||||
| 🎁 套餐管理 | 套餐列表 | ⏳ |
|
||||
|
||||
### 企业端
|
||||
|
||||
| 模块 | 功能 | 状态 |
|
||||
|------|------|------|
|
||||
| 📊 数据概览 | 资产统计、套餐统计 | ✅ |
|
||||
| 📦 资产管理 | 资产列表 | ✅ |
|
||||
| 🎁 套餐管理 | 套餐列表 | ⏳ |
|
||||
| 🏷️ 标签管理 | 标签列表、分配标签 | ✅ |
|
||||
|
||||
**注意**: 企业端没有佣金和钱包功能
|
||||
|
||||
---
|
||||
|
||||
## 🎨 设计风格
|
||||
|
||||
### 配色 (小米米家)
|
||||
|
||||
```scss
|
||||
#ff6700 // 主色 - 小米橙
|
||||
#ff8533 // Hover状态
|
||||
#fff7f0 // 橙色背景
|
||||
|
||||
#fafafa // 页面背景
|
||||
#ffffff // 卡片背景
|
||||
#f5f5f5 // 输入框背景
|
||||
#eeeeee // 分割线
|
||||
```
|
||||
|
||||
### 布局特点
|
||||
|
||||
- **顶部固定导航** - Logo + 角色切换 + 搜索
|
||||
- **卡片化布局** - 2列网格统计卡片
|
||||
- **圆角** - 12px卡片, 8px按钮
|
||||
- **柔和阴影** - `shadow-[0_2px_8px_rgba(0,0,0,0.04)]`
|
||||
|
||||
---
|
||||
|
||||
## 📱 页面结构
|
||||
|
||||
```
|
||||
┌─────────────────────────────────┐
|
||||
│ Logo [代理端][企业端] │ ← 固定顶部
|
||||
│ [搜索框] │
|
||||
├─────────────────────────────────┤
|
||||
│ │
|
||||
│ 数据概览 (默认页) │
|
||||
│ ┌────┬────┐ │
|
||||
│ │统计│统计│ │
|
||||
│ ├────┼────┤ │
|
||||
│ │统计│统计│ │
|
||||
│ └────┴────┘ │
|
||||
│ │
|
||||
│ 快捷操作 (4格) │
|
||||
│ 收益趋势图 │
|
||||
│ 最近动态列表 │
|
||||
│ │
|
||||
└─────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🧭 导航逻辑
|
||||
|
||||
### 页面切换
|
||||
|
||||
点击快捷操作按钮切换页面:
|
||||
|
||||
- **数据概览** (`dashboard`) - 默认首页
|
||||
- **佣金钱包** (`commission`) - 佣金余额 + 明细
|
||||
- **资产管理** (`assets`) - 资产列表
|
||||
- **标签管理** (`tags`) - 企业端独有
|
||||
|
||||
### 返回逻辑
|
||||
|
||||
所有子页面都有**返回按钮**,点击返回数据概览
|
||||
|
||||
```vue
|
||||
<button @click="navigateTo('dashboard')">
|
||||
<i class="i-mdi-chevron-left" />
|
||||
返回
|
||||
</button>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 💡 使用说明
|
||||
|
||||
### 1. 切换角色
|
||||
|
||||
顶部右侧角色切换:
|
||||
|
||||
```
|
||||
[代理端] [企业端]
|
||||
```
|
||||
|
||||
### 2. 快捷操作
|
||||
|
||||
数据概览页的 4 格快捷操作:
|
||||
|
||||
**代理端**:
|
||||
- 申请提现
|
||||
- 佣金钱包
|
||||
- 余额钱包
|
||||
- 我的资产
|
||||
|
||||
**企业端**:
|
||||
- 标签管理
|
||||
- 添加资产
|
||||
- 套餐管理
|
||||
- 数据统计
|
||||
|
||||
### 3. 查看详情
|
||||
|
||||
- 点击资产卡片 → 资产详情 (待实现)
|
||||
- 点击标签卡片 → 标签分配 (待实现)
|
||||
- 点击佣金记录 → 记录详情 (待实现)
|
||||
|
||||
---
|
||||
|
||||
## 🎯 下一步开发
|
||||
|
||||
### 优先级 P0
|
||||
|
||||
- [ ] **余额钱包页** (复制佣金钱包结构)
|
||||
- [ ] **提现申请表单**
|
||||
- 输入金额
|
||||
- 选择提现方式
|
||||
- 提交按钮
|
||||
- [ ] **提现记录列表**
|
||||
|
||||
### 优先级 P1
|
||||
|
||||
- [ ] **资产详情页**
|
||||
- [ ] **套餐列表页**
|
||||
- [ ] **套餐详情页**
|
||||
|
||||
### 优先级 P2
|
||||
|
||||
- [ ] **图表集成** (ECharts for H5)
|
||||
- [ ] **下拉刷新** (z-paging)
|
||||
- [ ] **上拉加载更多**
|
||||
- [ ] **标签分配拖拽**
|
||||
|
||||
---
|
||||
|
||||
## 🔧 代码示例
|
||||
|
||||
### 添加新页面
|
||||
|
||||
```vue
|
||||
<script setup>
|
||||
const currentView = ref('dashboard')
|
||||
|
||||
function navigateTo(view: string) {
|
||||
currentView.value = view
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- 新页面 -->
|
||||
<view v-if="currentView === 'new-page'" class="px-4">
|
||||
<button @click="navigateTo('dashboard')">
|
||||
<i class="i-mdi-chevron-left" />
|
||||
返回
|
||||
</button>
|
||||
|
||||
<text class="text-20px font-700">新页面</text>
|
||||
<!-- 页面内容 -->
|
||||
</view>
|
||||
</template>
|
||||
```
|
||||
|
||||
### 小米风格卡片
|
||||
|
||||
```vue
|
||||
<view class="
|
||||
bg-white rounded-12px p-4
|
||||
shadow-[0_2px_8px_rgba(0,0,0,0.04)]
|
||||
">
|
||||
<text class="text-16px font-600 text-[#212121]">
|
||||
卡片标题
|
||||
</text>
|
||||
</view>
|
||||
```
|
||||
|
||||
### 橙色渐变卡片
|
||||
|
||||
```vue
|
||||
<view class="
|
||||
bg-gradient-to-br from-[#ff6700] to-[#ff8533]
|
||||
rounded-16px p-6
|
||||
shadow-[0_8px_24px_rgba(255,103,0,0.2)]
|
||||
">
|
||||
<text class="text-white text-40px font-700">
|
||||
¥ 12,580.00
|
||||
</text>
|
||||
</view>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📐 尺寸规范
|
||||
|
||||
### 字号
|
||||
|
||||
```
|
||||
40px - 主要金额
|
||||
24px - 统计数值
|
||||
20px - Logo
|
||||
16px - 卡片标题
|
||||
15px - 列表标题
|
||||
14px - 正文
|
||||
13px - 小标签/按钮
|
||||
12px - 次要信息
|
||||
11px - 徽章/状态
|
||||
```
|
||||
|
||||
### 圆角
|
||||
|
||||
```
|
||||
16px - 大卡片 (余额卡)
|
||||
12px - 标准卡片
|
||||
8px - 按钮
|
||||
full - 圆形/药丸形
|
||||
```
|
||||
|
||||
### 间距
|
||||
|
||||
```
|
||||
gap-2 - 8px (小间距)
|
||||
gap-3 - 12px (标准间距)
|
||||
gap-4 - 16px (大间距)
|
||||
gap-6 - 24px (章节间距)
|
||||
|
||||
p-4 - 16px (卡片内边距)
|
||||
px-4 - 16px (页面左右边距)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✅ 检查清单
|
||||
|
||||
提交代码前确认:
|
||||
|
||||
- [ ] 使用十六进制颜色 (不用CSS变量)
|
||||
- [ ] 卡片圆角 12px
|
||||
- [ ] 按钮圆角 8px
|
||||
- [ ] 阴影透明度 0.04
|
||||
- [ ] 图标使用 MDI
|
||||
- [ ] 橙色仅用于强调
|
||||
- [ ] 测试代理/企业切换
|
||||
- [ ] 测试返回按钮
|
||||
- [ ] 页面可滚动
|
||||
|
||||
---
|
||||
|
||||
## 📂 文件位置
|
||||
|
||||
```
|
||||
src/pages/agent-system/
|
||||
├── mobile.vue # 移动端主页面 (当前)
|
||||
└── index.vue # PC端页面 (已废弃)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**设计理念**: 参考小米米家APP - 简约、卡片化、橙色点缀 🎨
|
||||
372
套餐列表页面说明.md
372
套餐列表页面说明.md
@@ -1,372 +0,0 @@
|
||||
# 套餐列表页面 - 使用说明
|
||||
|
||||
> **小米米家风格** - 简约、纯粹的套餐管理页面
|
||||
|
||||
---
|
||||
|
||||
## 🚀 快速启动
|
||||
|
||||
```bash
|
||||
pnpm dev:h5
|
||||
# 访问 http://localhost:5173/
|
||||
```
|
||||
|
||||
**页面入口**: `src/pages/agent-system/index.vue`
|
||||
|
||||
---
|
||||
|
||||
## ✨ 页面结构
|
||||
|
||||
### 简化设计
|
||||
|
||||
- ✅ **无顶部导航** - 去除Logo、搜索框、角色切换
|
||||
- ✅ **直接显示列表** - 首页即套餐列表
|
||||
- ✅ **两层结构** - 列表页 + 详情页
|
||||
|
||||
```
|
||||
首页 (套餐列表)
|
||||
├─ 统计卡片 (4个)
|
||||
├─ 筛选标签 (全部、生效中、待生效、已过期)
|
||||
└─ 套餐卡片列表
|
||||
└─ 点击卡片 → 套餐详情页
|
||||
└─ 点击返回 → 回到首页
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📱 页面展示
|
||||
|
||||
### 首页 - 套餐列表
|
||||
|
||||
```
|
||||
┌─────────────────────────────────┐
|
||||
│ │
|
||||
│ ┌──────┬──────┐ │ ← 统计卡片
|
||||
│ │套餐 │生效中│ │
|
||||
│ │总数 │ │ │
|
||||
│ │ 4 │ 2 │ │
|
||||
│ └──────┴──────┘ │
|
||||
│ ┌──────┬──────┐ │
|
||||
│ │待生效│已过期│ │
|
||||
│ │ 1 │ 1 │ │
|
||||
│ └──────┴──────┘ │
|
||||
│ │
|
||||
│ [全部] 生效中 待生效 已过期 → │ ← 筛选标签
|
||||
│ │
|
||||
│ ┌─────────────────────┐ │ ← 套餐卡片
|
||||
│ │ 月付套餐 50GB 生效中│ │
|
||||
│ │ 正式套餐 优先级:1 │ │
|
||||
│ │ │ │
|
||||
│ │ 虚流量使用 │ │
|
||||
│ │ [████░░░] 25/100GB │ │
|
||||
│ │ 真流量: 12.5/50GB │ │
|
||||
│ │ │ │
|
||||
│ │ 激活:03-01 到期:04-01 │ │
|
||||
│ │ (剩5天) │ │
|
||||
│ └─────────────────────┘ │
|
||||
│ │
|
||||
│ ┌─────────────────────┐ │
|
||||
│ │ 加油包 20GB 生效中│ │
|
||||
│ │ 加油包 优先级:2 │ │
|
||||
│ │ [████░░░] 10/40GB │ │
|
||||
│ │ 激活:03-15 到期:04-15│ │
|
||||
│ └─────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 详情页 - 套餐详情
|
||||
|
||||
```
|
||||
┌─────────────────────────────────┐
|
||||
│ ← 返回 │
|
||||
├─────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌─────────────────────┐ │ ← 基本信息
|
||||
│ │ 月付套餐 50GB 生效中│ │
|
||||
│ │ │ │
|
||||
│ │ 套餐类型: 正式套餐 │ │
|
||||
│ │ 优先级: 1 │ │
|
||||
│ └─────────────────────┘ │
|
||||
│ │
|
||||
│ ┌─────────────────────┐ │ ← 流量详情
|
||||
│ │ 流量使用 │ │
|
||||
│ │ │ │
|
||||
│ │ 虚流量使用 25% │ │
|
||||
│ │ [████████░░] │ │
|
||||
│ │ │ │
|
||||
│ │ 已用 剩余 总量│ │
|
||||
│ │ 25GB 75GB 100GB│ │
|
||||
│ │ │ │
|
||||
│ │ 真流量: 12.5/50GB │ │
|
||||
│ │ [████░░░░░] │ │
|
||||
│ │ │ │
|
||||
│ │ 虚流量比例: 1:2 │ │
|
||||
│ └─────────────────────┘ │
|
||||
│ │
|
||||
│ ┌─────────────────────┐ │ ← 时间信息
|
||||
│ │ 时间信息 │ │
|
||||
│ │ 创建:2024-02-25 │ │
|
||||
│ │ 激活:2024-03-01 │ │
|
||||
│ │ 到期:2024-04-01 │ │
|
||||
│ │ 剩余5天 │ │
|
||||
│ └─────────────────────┘ │
|
||||
│ │
|
||||
│ [续费套餐] [购买加油包] │
|
||||
│ │
|
||||
└─────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎨 核心功能
|
||||
|
||||
### 1. 统计卡片 (4个)
|
||||
|
||||
```vue
|
||||
套餐总数 - 蓝色图标
|
||||
生效中 - 绿色图标
|
||||
待生效 - 橙色图标
|
||||
已过期 - 红色图标
|
||||
```
|
||||
|
||||
### 2. 状态筛选
|
||||
|
||||
点击筛选标签过滤套餐:
|
||||
|
||||
| 标签 | 筛选条件 | 颜色 |
|
||||
|------|---------|------|
|
||||
| 全部 | 显示所有 | 橙色背景 (激活态) |
|
||||
| 生效中 | status = 1 | 绿色背景 (激活态) |
|
||||
| 待生效 | status = 0 | 橙色背景 (激活态) |
|
||||
| 已过期 | status = 3 | 红色背景 (激活态) |
|
||||
|
||||
### 3. 套餐卡片
|
||||
|
||||
每个卡片显示:
|
||||
|
||||
- **标题行** - 套餐名称 + 状态标签
|
||||
- **类型行** - 套餐类型 + 优先级
|
||||
- **虚流量进度条** - 8px高度,显示使用比例
|
||||
- **真流量文字** - 已用/总量
|
||||
- **时间行** - 激活时间 + 到期时间 + 剩余天数
|
||||
|
||||
### 4. 套餐详情
|
||||
|
||||
点击卡片进入详情页,显示:
|
||||
|
||||
- **基本信息** - 名称、类型、优先级、关联主套餐
|
||||
- **流量使用** - 虚流量大进度条 + 三格统计 + 真流量小进度条 + 比例
|
||||
- **时间信息** - 创建、激活、到期、剩余天数
|
||||
- **操作按钮** - 续费套餐 / 购买加油包
|
||||
|
||||
---
|
||||
|
||||
## 🎯 状态颜色
|
||||
|
||||
### 套餐状态标签
|
||||
|
||||
| 状态 | 文字颜色 | 背景颜色 |
|
||||
|------|---------|---------|
|
||||
| 待生效 | `#ff9800` | `#fff3e0` |
|
||||
| 生效中 | `#4caf50` | `#e8f5e9` |
|
||||
| 已用完 | `#9e9e9e` | `#f5f5f5` |
|
||||
| 已过期 | `#f44336` | `#ffebee` |
|
||||
| 已失效 | `#757575` | `#eeeeee` |
|
||||
|
||||
### 进度条颜色
|
||||
|
||||
```scss
|
||||
// 虚流量进度条
|
||||
status === 1 (生效中) → #4caf50 绿色
|
||||
status === 2 (已用完) → #f44336 红色
|
||||
其他状态 → #9e9e9e 灰色
|
||||
|
||||
// 真流量进度条
|
||||
固定使用 #2196f3 蓝色
|
||||
```
|
||||
|
||||
### 剩余天数
|
||||
|
||||
```scss
|
||||
≤ 7天 → #f44336 红色 (紧急)
|
||||
8-30天 → #ff9800 橙色 (提醒)
|
||||
> 30天 → 不显示颜色 (正常)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 💡 交互说明
|
||||
|
||||
### 列表页交互
|
||||
|
||||
1. **点击统计卡片** - 无交互 (纯展示)
|
||||
2. **点击筛选标签** - 过滤套餐列表
|
||||
3. **点击套餐卡片** - 进入套餐详情页
|
||||
4. **上下滑动** - 浏览套餐列表
|
||||
|
||||
### 详情页交互
|
||||
|
||||
1. **点击返回按钮** - 返回套餐列表
|
||||
2. **点击续费套餐** - (待实现) 打开续费表单
|
||||
3. **点击购买加油包** - (待实现) 跳转加油包选择页
|
||||
|
||||
---
|
||||
|
||||
## 📊 数据示例
|
||||
|
||||
### 套餐列表数据
|
||||
|
||||
```typescript
|
||||
interface PackageUsage {
|
||||
package_usage_id: number // 使用记录ID
|
||||
package_id: number // 套餐模板ID
|
||||
package_name: string // 套餐名称
|
||||
package_type: 'formal' | 'addon' // 套餐类型
|
||||
status: 0 | 1 | 2 | 3 | 4 // 状态
|
||||
status_name: string // 状态名称
|
||||
data_limit_mb: number // 真流量总量(MB)
|
||||
data_usage_mb: number // 已用真流量(MB)
|
||||
virtual_limit_mb: number // 虚流量总量(MB)
|
||||
virtual_used_mb: number // 已用虚流量(MB)
|
||||
virtual_remain_mb: number // 剩余虚流量(MB)
|
||||
virtual_ratio: number // 虚流量比例
|
||||
priority: number // 优先级
|
||||
usage_type: string // 使用类型
|
||||
master_usage_id: number | null // 主套餐ID
|
||||
activated_at: string | null // 激活时间
|
||||
expires_at: string | null // 到期时间
|
||||
created_at: string // 创建时间
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔧 核心函数
|
||||
|
||||
### 1. 流量格式化
|
||||
|
||||
```typescript
|
||||
function formatDataSize(mb: number): string {
|
||||
if (mb < 1024) return `${mb}MB`
|
||||
return `${(mb / 1024).toFixed(1)}GB`
|
||||
}
|
||||
|
||||
// 示例:
|
||||
formatDataSize(512) // → "512MB"
|
||||
formatDataSize(51200) // → "50.0GB"
|
||||
```
|
||||
|
||||
### 2. 使用百分比
|
||||
|
||||
```typescript
|
||||
function calcUsagePercent(used: number, total: number): number {
|
||||
if (total === 0) return 0
|
||||
return Math.min(Math.round((used / total) * 100), 100)
|
||||
}
|
||||
|
||||
// 示例:
|
||||
calcUsagePercent(25600, 102400) // → 25
|
||||
```
|
||||
|
||||
### 3. 剩余天数
|
||||
|
||||
```typescript
|
||||
function calcRemainingDays(expiresAt: string | null): number | null {
|
||||
if (!expiresAt) return null
|
||||
const now = new Date()
|
||||
const expireDate = new Date(expiresAt)
|
||||
const diff = expireDate.getTime() - now.getTime()
|
||||
return Math.ceil(diff / (1000 * 60 * 60 * 24))
|
||||
}
|
||||
|
||||
// 示例:
|
||||
calcRemainingDays('2024-04-01T10:00:00Z') // → 5 (假设今天是3月27日)
|
||||
```
|
||||
|
||||
### 4. 时间格式化
|
||||
|
||||
```typescript
|
||||
function formatDate(dateStr: string | null): string {
|
||||
if (!dateStr) return '--'
|
||||
const date = new Date(dateStr)
|
||||
return `${date.getMonth() + 1}-${String(date.getDate()).padStart(2, '0')}`
|
||||
}
|
||||
|
||||
// 示例:
|
||||
formatDate('2024-03-01T10:00:00Z') // → "3-01"
|
||||
formatDate(null) // → "--"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✅ 设计检查清单
|
||||
|
||||
- [x] 移除顶部导航栏
|
||||
- [x] 移除Logo和搜索框
|
||||
- [x] 移除角色切换
|
||||
- [x] 首页直接显示套餐列表
|
||||
- [x] 统计卡片正常显示
|
||||
- [x] 筛选标签功能正常
|
||||
- [x] 套餐卡片样式正确
|
||||
- [x] 详情页返回功能正常
|
||||
- [x] 状态颜色准确
|
||||
- [x] 进度条显示正确
|
||||
|
||||
---
|
||||
|
||||
## 🎯 下一步开发
|
||||
|
||||
### 优先级 P0 (核心功能)
|
||||
|
||||
- [ ] **API接口对接** - 获取真实套餐数据
|
||||
- [ ] **下拉刷新** - 刷新套餐列表
|
||||
- [ ] **上拉加载** - 分页加载更多
|
||||
|
||||
### 优先级 P1 (重要功能)
|
||||
|
||||
- [ ] **续费功能** - 续费套餐表单和支付
|
||||
- [ ] **购买加油包** - 加油包选择和购买流程
|
||||
- [ ] **套餐详情操作** - 更多操作选项
|
||||
|
||||
### 优先级 P2 (增强体验)
|
||||
|
||||
- [ ] **图表统计** - 流量使用趋势图
|
||||
- [ ] **到期提醒** - 即将到期推送通知
|
||||
- [ ] **搜索功能** - 按套餐名称搜索
|
||||
|
||||
---
|
||||
|
||||
## 📐 布局尺寸
|
||||
|
||||
### 间距
|
||||
|
||||
```scss
|
||||
页面边距: px-4 (16px)
|
||||
卡片间距: gap-3 (12px)
|
||||
卡片内边距: p-4 (16px)
|
||||
小元素间距: gap-2 (8px)
|
||||
```
|
||||
|
||||
### 字号
|
||||
|
||||
```scss
|
||||
24px - 统计数值
|
||||
16px - 套餐名称
|
||||
14px - 按钮文字
|
||||
13px - 流量数值
|
||||
12px - 状态标签
|
||||
11px - 时间信息
|
||||
```
|
||||
|
||||
### 圆角
|
||||
|
||||
```scss
|
||||
12px - 卡片圆角
|
||||
8px - 进度条圆角
|
||||
full - 状态标签圆角
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**小米米家风格 - 简约纯粹** 🎨
|
||||
413
套餐管理系统说明.md
413
套餐管理系统说明.md
@@ -1,413 +0,0 @@
|
||||
# 套餐管理系统 - 移动端H5
|
||||
|
||||
> **小米米家风格** - 套餐使用记录管理系统
|
||||
|
||||
---
|
||||
|
||||
## ✨ 功能说明
|
||||
|
||||
这是一个**套餐使用记录管理系统**,展示和管理用户的套餐使用情况。
|
||||
|
||||
### 核心功能
|
||||
|
||||
- ✅ **套餐统计** - 总数、生效中、待生效、已过期
|
||||
- ✅ **套餐列表** - 筛选、搜索、分类展示
|
||||
- ✅ **套餐详情** - 流量使用、时间信息、操作按钮
|
||||
- ✅ **状态管理** - 5种状态标识和颜色区分
|
||||
- ✅ **流量可视化** - 进度条显示虚流量/真流量
|
||||
|
||||
---
|
||||
|
||||
## 🚀 快速启动
|
||||
|
||||
```bash
|
||||
# 启动开发服务器
|
||||
pnpm dev:h5
|
||||
|
||||
# 访问地址
|
||||
http://localhost:5173/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📋 数据字段说明
|
||||
|
||||
### 套餐状态 (status)
|
||||
|
||||
| 值 | 状态名称 | 颜色 | 说明 |
|
||||
|----|---------|------|------|
|
||||
| 0 | 待生效 | 橙色 | 已购买但未激活 |
|
||||
| 1 | 生效中 | 绿色 | 正常使用中 |
|
||||
| 2 | 已用完 | 灰色 | 流量已耗尽 |
|
||||
| 3 | 已过期 | 红色 | 超过有效期 |
|
||||
| 4 | 已失效 | 灰色 | 主动失效 |
|
||||
|
||||
### 套餐类型 (package_type)
|
||||
|
||||
- **formal** - 正式套餐 (主套餐)
|
||||
- **addon** - 加油包 (附加套餐,有master_usage_id)
|
||||
|
||||
### 使用类型 (usage_type)
|
||||
|
||||
- **single_card** - 单卡使用
|
||||
- **device** - 设备使用
|
||||
|
||||
### 流量相关
|
||||
|
||||
- **data_limit_mb** - 真流量总量(MB)
|
||||
- **data_usage_mb** - 已用真流量(MB)
|
||||
- **virtual_limit_mb** - 虚流量总量(MB)
|
||||
- **virtual_used_mb** - 已用虚流量(MB)
|
||||
- **virtual_remain_mb** - 剩余虚流量(MB)
|
||||
- **virtual_ratio** - 虚流量比例 (真实/虚拟)
|
||||
|
||||
**示例**: 如果 virtual_ratio = 0.5
|
||||
- 真流量 1GB = 虚流量 2GB
|
||||
- 显示比例: 1:2
|
||||
|
||||
---
|
||||
|
||||
## 🎨 页面结构
|
||||
|
||||
### 1. 数据概览页 (Dashboard)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────┐
|
||||
│ GT Agent [代理端][企业端] │
|
||||
│ 🔍 [搜索套餐名称...] │
|
||||
├─────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌──────┬──────┐ │ ← 统计卡片
|
||||
│ │套餐 │生效中│ │
|
||||
│ │总数 │ │ │
|
||||
│ │ 4 │ 2 │ │
|
||||
│ └──────┴──────┘ │
|
||||
│ ┌──────┬──────┐ │
|
||||
│ │待生效│已过期│ │
|
||||
│ │ 1 │ 1 │ │
|
||||
│ └──────┴──────┘ │
|
||||
│ │
|
||||
│ ┌─────────────────────┐ │ ← 快捷操作
|
||||
│ │ 套餐 添加 统计 记录│ │
|
||||
│ └─────────────────────┘ │
|
||||
│ │
|
||||
│ ┌─────────────────────┐ │ ← 最近套餐
|
||||
│ │ 最近套餐 查看全部→│ │
|
||||
│ │ │ │
|
||||
│ │ 月付套餐 50GB │ │
|
||||
│ │ 生效中 │ │
|
||||
│ │ [进度条] 25/100GB │ │
|
||||
│ │ 到期: 2024-04-01 │ │
|
||||
│ └─────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 2. 套餐列表页
|
||||
|
||||
```
|
||||
┌─────────────────────────────────┐
|
||||
│ ← 返回 套餐列表 [筛选] │
|
||||
├─────────────────────────────────┤
|
||||
│ │
|
||||
│ [全部] 生效中 待生效 已过期 → │ ← 筛选标签
|
||||
│ │
|
||||
│ ┌─────────────────────┐ │ ← 套餐卡片
|
||||
│ │ 月付套餐 50GB 生效中│ │
|
||||
│ │ 正式套餐 优先级:1 │ │
|
||||
│ │ │ │
|
||||
│ │ 虚流量使用 │ │
|
||||
│ │ [████░░░] 25/100GB │ │
|
||||
│ │ 真流量: 12.5/50GB │ │
|
||||
│ │ │ │
|
||||
│ │ 激活:2024-03-01 │ │
|
||||
│ │ 到期:2024-04-01(剩5天) │ │
|
||||
│ └─────────────────────┘ │
|
||||
│ │
|
||||
│ ┌─────────────────────┐ │
|
||||
│ │ 加油包 20GB 生效中│ │
|
||||
│ │ 加油包 优先级:2 │ │
|
||||
│ │ [████░░░] 10/40GB │ │
|
||||
│ └─────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 3. 套餐详情页
|
||||
|
||||
```
|
||||
┌─────────────────────────────────┐
|
||||
│ ← 返回列表 │
|
||||
├─────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌─────────────────────┐ │ ← 基本信息
|
||||
│ │ 月付套餐 50GB 生效中│ │
|
||||
│ │ │ │
|
||||
│ │ 套餐类型: 正式套餐 │ │
|
||||
│ │ 优先级: 1 │ │
|
||||
│ └─────────────────────┘ │
|
||||
│ │
|
||||
│ ┌─────────────────────┐ │ ← 流量使用
|
||||
│ │ 流量使用 │ │
|
||||
│ │ │ │
|
||||
│ │ 虚流量使用 25% │ │
|
||||
│ │ [████████░░] │ │
|
||||
│ │ │ │
|
||||
│ │ 已用 剩余 总量│ │
|
||||
│ │ 25GB 75GB 100GB│ │
|
||||
│ │ │ │
|
||||
│ │ 真流量: 12.5/50GB │ │
|
||||
│ │ [████░░░░░] │ │
|
||||
│ │ │ │
|
||||
│ │ 虚流量比例: 1:2 │ │
|
||||
│ └─────────────────────┘ │
|
||||
│ │
|
||||
│ ┌─────────────────────┐ │ ← 时间信息
|
||||
│ │ 时间信息 │ │
|
||||
│ │ 创建:2024-02-25 │ │
|
||||
│ │ 激活:2024-03-01 │ │
|
||||
│ │ 到期:2024-04-01 │ │
|
||||
│ │ 剩余5天 │ │
|
||||
│ └─────────────────────┘ │
|
||||
│ │
|
||||
│ [续费套餐] [购买加油包] │
|
||||
│ │
|
||||
└─────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎨 状态颜色方案
|
||||
|
||||
### 套餐状态标签
|
||||
|
||||
```scss
|
||||
// 待生效 (status: 0)
|
||||
color: #ff9800
|
||||
background: #fff3e0
|
||||
|
||||
// 生效中 (status: 1)
|
||||
color: #4caf50
|
||||
background: #e8f5e9
|
||||
|
||||
// 已用完 (status: 2)
|
||||
color: #9e9e9e
|
||||
background: #f5f5f5
|
||||
|
||||
// 已过期 (status: 3)
|
||||
color: #f44336
|
||||
background: #ffebee
|
||||
|
||||
// 已失效 (status: 4)
|
||||
color: #757575
|
||||
background: #eeeeee
|
||||
```
|
||||
|
||||
### 进度条颜色
|
||||
|
||||
```scss
|
||||
// 正常使用 (status: 1)
|
||||
进度条: #4caf50 (绿色)
|
||||
|
||||
// 已用完 (status: 2)
|
||||
进度条: #f44336 (红色)
|
||||
|
||||
// 真流量进度条
|
||||
进度条: #2196f3 (蓝色)
|
||||
```
|
||||
|
||||
### 剩余天数颜色
|
||||
|
||||
```scss
|
||||
// ≤ 7天 (即将过期)
|
||||
text-color: #f44336 (红色)
|
||||
|
||||
// 7-30天 (提醒)
|
||||
text-color: #ff9800 (橙色)
|
||||
|
||||
// > 30天 (正常)
|
||||
text-color: #4caf50 (绿色)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 💡 交互说明
|
||||
|
||||
### 1. 套餐筛选
|
||||
|
||||
点击顶部筛选标签:
|
||||
- **全部** - 显示所有套餐
|
||||
- **生效中** - 仅显示 status = 1
|
||||
- **待生效** - 仅显示 status = 0
|
||||
- **已过期** - 仅显示 status = 3
|
||||
|
||||
### 2. 查看详情
|
||||
|
||||
点击套餐卡片 → 跳转详情页
|
||||
|
||||
### 3. 返回导航
|
||||
|
||||
- 列表页 → 点击"← 返回" → 数据概览
|
||||
- 详情页 → 点击"← 返回列表" → 列表页
|
||||
|
||||
---
|
||||
|
||||
## 📊 流量计算逻辑
|
||||
|
||||
### 虚流量比例计算
|
||||
|
||||
```typescript
|
||||
// 示例: virtual_ratio = 0.5
|
||||
// 真流量 1GB = 虚流量 2GB
|
||||
|
||||
显示比例 = 1 : (1 / virtual_ratio)
|
||||
= 1 : (1 / 0.5)
|
||||
= 1 : 2
|
||||
|
||||
// 虚流量换算
|
||||
virtual_limit_mb = data_limit_mb / virtual_ratio
|
||||
= 50GB / 0.5
|
||||
= 100GB
|
||||
```
|
||||
|
||||
### 使用百分比
|
||||
|
||||
```typescript
|
||||
usagePercent = (used / total) * 100
|
||||
= (25600 / 102400) * 100
|
||||
= 25%
|
||||
```
|
||||
|
||||
### 剩余天数
|
||||
|
||||
```typescript
|
||||
remainingDays = (expires_at - now) / (24小时)
|
||||
= 向上取整
|
||||
|
||||
// 颜色判断
|
||||
if (remainingDays <= 7) → 红色
|
||||
else if (remainingDays <= 30) → 橙色
|
||||
else → 绿色
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔧 数据示例
|
||||
|
||||
### 示例 1: 正式套餐
|
||||
|
||||
```json
|
||||
{
|
||||
"package_usage_id": 1,
|
||||
"package_id": 101,
|
||||
"package_name": "月付套餐 50GB",
|
||||
"package_type": "formal",
|
||||
"status": 1,
|
||||
"status_name": "生效中",
|
||||
"data_limit_mb": 51200, // 50GB
|
||||
"data_usage_mb": 12800, // 12.5GB
|
||||
"virtual_limit_mb": 102400, // 100GB (50GB / 0.5)
|
||||
"virtual_used_mb": 25600, // 25GB
|
||||
"virtual_remain_mb": 76800, // 75GB
|
||||
"virtual_ratio": 0.5, // 1:2比例
|
||||
"priority": 1,
|
||||
"usage_type": "single_card",
|
||||
"master_usage_id": null,
|
||||
"activated_at": "2024-03-01T10:00:00Z",
|
||||
"expires_at": "2024-04-01T10:00:00Z",
|
||||
"created_at": "2024-02-25T15:30:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
### 示例 2: 加油包
|
||||
|
||||
```json
|
||||
{
|
||||
"package_usage_id": 2,
|
||||
"package_id": 102,
|
||||
"package_name": "加油包 20GB",
|
||||
"package_type": "addon",
|
||||
"status": 1,
|
||||
"status_name": "生效中",
|
||||
"data_limit_mb": 20480, // 20GB
|
||||
"data_usage_mb": 5120, // 5GB
|
||||
"virtual_limit_mb": 40960, // 40GB
|
||||
"virtual_used_mb": 10240, // 10GB
|
||||
"virtual_remain_mb": 30720, // 30GB
|
||||
"virtual_ratio": 0.5,
|
||||
"priority": 2,
|
||||
"usage_type": "single_card",
|
||||
"master_usage_id": 1, // 关联主套餐ID
|
||||
"activated_at": "2024-03-15T14:00:00Z",
|
||||
"expires_at": "2024-04-15T14:00:00Z",
|
||||
"created_at": "2024-03-15T13:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✅ 设计检查清单
|
||||
|
||||
- [x] 套餐状态使用对应颜色标签
|
||||
- [x] 进度条颜色区分状态
|
||||
- [x] 虚流量/真流量分别展示
|
||||
- [x] 虚流量比例清晰显示
|
||||
- [x] 剩余天数有颜色提醒
|
||||
- [x] 加油包显示主套餐关联
|
||||
- [x] 待生效套餐不显示激活/到期时间
|
||||
- [x] 流量单位自动换算 (MB/GB)
|
||||
- [x] 所有时间格式统一
|
||||
- [x] 空状态有友好提示
|
||||
|
||||
---
|
||||
|
||||
## 🎯 下一步开发
|
||||
|
||||
### 优先级 P0
|
||||
|
||||
- [ ] **API接口对接** - 获取真实套餐数据
|
||||
- [ ] **搜索功能** - 按套餐名称搜索
|
||||
- [ ] **下拉刷新** - 刷新套餐列表
|
||||
- [ ] **分页加载** - 长列表分页
|
||||
|
||||
### 优先级 P1
|
||||
|
||||
- [ ] **续费功能** - 续费套餐表单
|
||||
- [ ] **购买加油包** - 加油包选择和购买
|
||||
- [ ] **套餐详情操作** - 更多操作选项
|
||||
- [ ] **使用记录** - 流量使用历史
|
||||
|
||||
### 优先级 P2
|
||||
|
||||
- [ ] **图表统计** - 流量使用趋势图
|
||||
- [ ] **到期提醒** - 即将到期推送
|
||||
- [ ] **自动续费** - 自动续费开关
|
||||
|
||||
---
|
||||
|
||||
## 📐 字段映射表
|
||||
|
||||
| API字段 | 显示名称 | 类型 | 说明 |
|
||||
|---------|---------|------|------|
|
||||
| package_usage_id | 套餐使用ID | number | 主键 |
|
||||
| package_id | 套餐ID | number | 套餐模板ID |
|
||||
| package_name | 套餐名称 | string | 显示标题 |
|
||||
| package_type | 套餐类型 | string | formal/addon |
|
||||
| status | 状态码 | number | 0-4 |
|
||||
| status_name | 状态名称 | string | 中文状态 |
|
||||
| data_limit_mb | 真流量总量 | number | MB单位 |
|
||||
| data_usage_mb | 真流量已用 | number | MB单位 |
|
||||
| virtual_limit_mb | 虚流量总量 | number | MB单位 |
|
||||
| virtual_used_mb | 虚流量已用 | number | MB单位 |
|
||||
| virtual_remain_mb | 虚流量剩余 | number | MB单位 |
|
||||
| virtual_ratio | 虚流量比例 | number | 小数 |
|
||||
| priority | 优先级 | number | 越小越优先 |
|
||||
| usage_type | 使用类型 | string | single_card/device |
|
||||
| master_usage_id | 主套餐ID | number/null | 加油包关联 |
|
||||
| activated_at | 激活时间 | datetime/null | ISO格式 |
|
||||
| expires_at | 到期时间 | datetime/null | ISO格式 |
|
||||
| created_at | 创建时间 | datetime | ISO格式 |
|
||||
|
||||
---
|
||||
|
||||
**小米米家风格 - 简约、清晰、易用** 🎨
|
||||
Reference in New Issue
Block a user