Cordova 开发鸿蒙PC应用快递查询应用实现技术博客

Cordova 开发鸿蒙PC应用快递查询应用实现技术博客

目录

  1. 项目概述
  2. 技术选型
  3. 功能需求分析
  4. 实现步骤
  5. 核心代码解析
  6. API 集成详解
  7. 用户体验优化
  8. 常见问题与解决方案
  9. 最佳实践
  10. 总结

项目概述

快递查询应用是一个基于 Cordova 框架开发的移动应用,通过调用第三方 API 实现快递物流轨迹查询功能。用户只需输入快递单号,即可查询快递的实时物流状态和详细轨迹信息。应用支持自动识别快递公司,也支持手动选择,并针对顺丰和中通快递提供了手机号后四位查询功能。

效果

image-20251121174523083

核心功能

  • 多快递公司支持:支持中通、申通、顺丰、极兔、百世、圆通等主流快递公司
  • 自动识别快递公司:系统能够自动识别快递单号对应的快递公司
  • 手动选择快递公司:支持手动选择快递公司,提高查询准确性
  • 手机号查询:支持手机号后四位查询(顺丰/中通必填)
  • 物流轨迹展示:时间线形式展示完整的物流轨迹信息
  • 状态标签显示:清晰显示快递状态(运输中、已签收、已揽收等)
  • Token 管理:自动保存和加载 API Token
  • 响应式设计:完美适配移动设备和桌面浏览器

技术选型

前端技术栈

  • HTML5:页面结构
  • CSS3:样式设计和响应式布局
  • JavaScript (ES6+):业务逻辑和 API 调用
  • Cordova:跨平台移动应用框架

API 服务

  • API 提供商:AlAPI(alapi.cn
  • 快递查询接口https://v3.alapi.cn/api/kd
  • 快递公司列表接口https://v3.alapi.cn/api/kd/com
  • 请求方式:POST
  • 数据格式:URL-encoded form data

功能需求分析

1. 用户输入需求

  • API Token(必填)
  • 快递单号(必填)
  • 快递公司(可选,默认自动识别)
  • 手机号后四位(可选,顺丰/中通必填)

2. 功能需求

  • 快递公司列表自动加载
  • 快递查询和错误处理
  • 物流轨迹时间线展示
  • Token 本地存储
  • 加载状态提示
  • 错误信息提示

3. 用户体验需求

  • 响应式设计
  • 流畅的交互动画
  • 清晰的错误提示
  • Token 获取引导
  • 时间线可视化展示

实现步骤

步骤 1: 创建页面结构

创建 express.html 文件,包含:

  • 导航栏
  • 页面标题和说明
  • 表单区域(Token、快递单号、快递公司、手机号)
  • 结果展示区域(物流轨迹时间线)
  • Token 获取弹窗

步骤 2: 设计 UI 样式

使用 CSS3 实现:

  • 响应式布局
  • 渐变背景和阴影效果
  • 表单样式和焦点效果
  • 时间线样式设计
  • 状态标签样式
  • 弹窗样式
  • 移动端适配

步骤 3: 实现 JavaScript 逻辑

创建 express.js 文件,实现:

  • 快递公司列表加载
  • 表单提交处理
  • API 调用
  • 数据验证
  • 结果展示(时间线)
  • Token 存储

步骤 4: 配置安全策略

更新 Content Security Policy (CSP),允许:

  • 访问 API 域名
  • 加载 iframe 内容
  • 执行必要的脚本

核心代码解析

1. HTML 结构

表单部分
<form id="express-form">
    <div class="form-group">
        <label for="token" class="label-with-help">
            <span>API Token *</span>
            <button type="button" class="help-btn" onclick="openTokenModal()">获取 Token</button>
        </label>
        <div class="token-input-wrapper">
            <input type="text" id="token" name="token" placeholder="请输入API Token" required>
        </div>
    </div>

    <div class="form-group">
        <label for="number">快递单号 *</label>
        <input type="text" id="number" name="number" placeholder="请输入快递单号" required>
    </div>

    <div class="form-row">
        <div class="form-group">
            <label for="com">快递公司(可选)</label>
            <select id="com" name="com">
                <option value="">自动识别</option>
            </select>
        </div>

        <div class="form-group">
            <label for="phone">手机号后四位(可选)</label>
            <input type="text" id="phone" name="phone" placeholder="顺丰/中通必填" maxlength="4" pattern="[0-9]{4}">
        </div>
    </div>

    <button type="submit" class="submit-btn" id="submit-btn">查询</button>
</form>
结果展示区域
<div class="result-container" id="result-container">
    <div class="result-title">查询结果</div>
    <div class="express-info" id="express-info"></div>
</div>

2. CSS 样式设计

时间线样式
.tracking-list {
    list-style: none;
    padding: 0;
    margin: 0;
    position: relative;
}

.tracking-list::before {
    content: '';
    position: absolute;
    left: 15px;
    top: 0;
    bottom: 0;
    width: 2px;
    background: linear-gradient(to bottom, #3498db, #e0e0e0);
}

.tracking-item {
    position: relative;
    padding-left: 45px;
    padding-bottom: 25px;
    border-left: 2px solid transparent;
}

.tracking-item::before {
    content: '';
    position: absolute;
    left: 8px;
    top: 5px;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background-color: #3498db;
    border: 3px solid white;
    box-shadow: 0 0 0 2px #3498db;
}

.tracking-item:first-child::before {
    background-color: #27ae60;
    box-shadow: 0 0 0 2px #27ae60;
}
状态标签样式
.status-badge {
    padding: 8px 16px;
    border-radius: 20px;
    font-size: 14px;
    font-weight: bold;
}

.status-badge.transport {
    background-color: #e3f2fd;
    color: #1976d2;
}

.status-badge.signed {
    background-color: #e8f5e9;
    color: #388e3c;
}

.status-badge.collect {
    background-color: #fff3e0;
    color: #f57c00;
}

3. JavaScript 核心逻辑

快递公司列表加载
// 快递公司列表
let expressCompanies = [];

// 加载快递公司列表
function loadExpressCompanies() {
    const token = localStorage.getItem('express_api_token');
    if (!token) {
        console.log('未找到Token,跳过加载快递公司列表');
        return;
    }

    const params = new URLSearchParams();
    params.append('token', token);

    fetch('https://v3.alapi.cn/api/kd/com', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded',
        },
        body: params.toString()
    })
    .then(response => {
        if (!response.ok) {
            throw new Error('网络请求失败: ' + response.status);
        }
        return response.json();
    })
    .then(data => {
        console.log('快递公司列表响应:', data);
        
        if (data.success && data.code === 200 && Array.isArray(data.data)) {
            expressCompanies = data.data;
            updateCompanySelect(data.data);
        } else {
            console.error('获取快递公司列表失败:', data.message);
        }
    })
    .catch(error => {
        console.error('获取快递公司列表错误:', error);
    });
}
更新快递公司下拉框
function updateCompanySelect(companies) {
    const select = document.getElementById('com');
    // 保留"自动识别"选项
    const autoOption = select.querySelector('option[value=""]');
    select.innerHTML = '';
    if (autoOption) {
        select.appendChild(autoOption);
    }
    
    companies.forEach(company => {
        const option = document.createElement('option');
        option.value = company.code;
        option.textContent = company.name;
        select.appendChild(option);
    });
}
快递查询函数
function queryExpress() {
    const submitBtn = document.getElementById('submit-btn');
    const loading = document.getElementById('loading');
    const errorMessage = document.getElementById('error-message');
    const resultContainer = document.getElementById('result-container');
    
    // 获取表单数据
    const formData = {
        token: document.getElementById('token').value.trim(),
        number: document.getElementById('number').value.trim(),
        com: document.getElementById('com').value,
        phone: document.getElementById('phone').value.trim()
    };
    
    // 验证快递单号
    if (!formData.number) {
        showError('请输入快递单号');
        return;
    }
    
    // 验证token
    if (!formData.token) {
        showError('请输入API Token');
        return;
    }
    
    // 显示加载状态
    submitBtn.disabled = true;
    submitBtn.textContent = '查询中...';
    loading.classList.add('show');
    errorMessage.classList.remove('show');
    resultContainer.classList.remove('show');
    
    // 构建请求参数
    const params = new URLSearchParams();
    params.append('token', formData.token);
    params.append('number', formData.number);
    if (formData.com) {
        params.append('com', formData.com);
    }
    if (formData.phone) {
        params.append('phone', formData.phone);
    }
    
    // 发送POST请求
    fetch('https://v3.alapi.cn/api/kd', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded',
        },
        body: params.toString()
    })
    .then(response => {
        if (!response.ok) {
            throw new Error('网络请求失败: ' + response.status);
        }
        return response.json();
    })
    .then(data => {
        console.log('API响应:', data);
        
        if (data.success && data.code === 200) {
            displayExpressInfo(data.data);
            // 如果成功查询,更新快递公司列表
            if (!expressCompanies.length) {
                loadExpressCompanies();
            }
        } else {
            showError(data.message || '查询失败,请检查参数');
        }
    })
    .catch(error => {
        console.error('请求错误:', error);
        showError('请求失败: ' + error.message + '。请检查网络连接或API Token是否正确');
    })
    .finally(() => {
        // 恢复按钮状态
        submitBtn.disabled = false;
        submitBtn.textContent = '查询';
        loading.classList.remove('show');
    });
}
状态映射
// 状态映射
const statusMap = {
    'TRANSPORT': { text: '运输中', class: 'transport' },
    'SIGNED': { text: '已签收', class: 'signed' },
    'COLLECT': { text: '已揽收', class: 'collect' }
};
结果展示函数
function displayExpressInfo(data) {
    const resultContainer = document.getElementById('result-container');
    const expressInfo = document.getElementById('express-info');
    
    let html = '';
    
    // 快递基本信息
    html += '<div class="info-header">';
    html += '<div class="info-header-left">';
    html += `<h3>${data.com_text || '未知快递公司'}</h3>`;
    html += `<p>快递单号:${data.nu || '未知'}</p>`;
    html += '</div>';
    
    // 状态标签
    const status = statusMap[data.status] || { text: data.status_desc || '未知', class: 'transport' };
    html += `<span class="status-badge ${status.class}">${status.text}</span>`;
    html += '</div>';
    
    // 物流轨迹列表
    if (data.info && Array.isArray(data.info) && data.info.length > 0) {
        html += '<ul class="tracking-list">';
        data.info.forEach((item, index) => {
            const itemStatus = statusMap[item.status] || { text: item.status_desc || '', class: 'transport' };
            html += '<li class="tracking-item">';
            html += '<div class="tracking-content">';
            html += `<div class="tracking-time">${item.time || ''}</div>`;
            html += `<div class="tracking-text">${item.content || ''}</div>`;
            if (item.status_desc) {
                html += `<div style="margin-top: 5px; font-size: 12px; color: #7f8c8d;">状态:${item.status_desc}</div>`;
            }
            html += '</div>';
            html += '</li>';
        });
        html += '</ul>';
    } else {
        html += '<div style="text-align: center; padding: 20px; color: #7f8c8d;">暂无物流轨迹信息</div>';
    }
    
    expressInfo.innerHTML = html;
    
    // 显示结果容器
    resultContainer.classList.add('show');
    
    // 滚动到结果区域
    resultContainer.scrollIntoView({ behavior: 'smooth', block: 'start' });
}

API 集成详解

1. 快递公司列表 API

请求参数
参数名类型必填说明示例
tokenstring接口调用token,需要在token管理中创建qlVquQZPYSeaCi6u
响应格式
{
  "request_id": "727661733887553536",
  "success": true,
  "message": "success",
  "code": 200,
  "data": [
    {"name": "申通快递", "code": "sto"},
    {"name": "圆通快递", "code": "yto"},
    {"name": "顺丰快递", "code": "sf"},
    {"name": "中通快递", "code": "zto"},
    {"name": "百世快运", "code": "best"},
    {"name": "极兔快递", "code": "jt"}
  ],
  "time": 1734448076,
  "usage": 0
}

2. 快递查询 API

请求参数
参数名类型必填说明示例
tokenstring接口调用token,需要在token管理中创建qlVquQZPYSeaCi6u
numberstring要查询的快递编号18118763460
comstring快递公司编码,默认自动识别,不用填写sto
phonestring寄/收件人手机号后四位,顺丰快递和中通快递必填1234
响应格式
{
  "request_id": "727660081369522176",
  "success": true,
  "message": "success",
  "code": 200,
  "data": {
    "nu": "18118763460",
    "com": "best",
    "com_text": "百世快运",
    "state": 3,
    "status": "TRANSPORT",
    "status_desc": "运输中",
    "info": [
      {
        "time": "2019-11-18 15:53:02",
        "content": "已签收(4/4)。有问题请联系派件员杨娇19136004279,投诉电话18040471611。",
        "status": "TRANSPORT",
        "status_desc": "运输中"
      }
    ]
  },
  "time": 1734447686,
  "usage": 0
}
响应参数说明
参数名类型必填说明
nustring快递编号
comstring快递公司编码
com_textstring快递公司名称
statestring签收状态,3已签收
statusstring最后一条物流状态
status_descstring物流状态描述
infoarray物流轨迹列表
info[].timestring轨迹更新时间
info[].contentstring轨迹更新内容
info[].statusstring轨迹状态
info[].status_descstring状态描述

3. 请求实现

// 构建请求参数
const params = new URLSearchParams();
params.append('token', formData.token);
params.append('number', formData.number);
if (formData.com) {
    params.append('com', formData.com);
}
if (formData.phone) {
    params.append('phone', formData.phone);
}

// 发送POST请求
fetch('https://v3.alapi.cn/api/kd', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
    },
    body: params.toString()
})

用户体验优化

1. 自动加载快递公司列表

// 页面加载时自动获取快递公司列表
document.addEventListener('deviceready', function() {
    console.log('设备就绪,快递查询功能可用');
    loadExpressCompanies();
}, false);

// Token 更新后重新加载
document.getElementById('token').addEventListener('blur', function() {
    const token = this.value.trim();
    if (token) {
        localStorage.setItem('express_api_token', token);
        loadExpressCompanies();
    }
});

2. 时间线可视化展示

使用 CSS 实现时间线效果:

.tracking-list::before {
    content: '';
    position: absolute;
    left: 15px;
    top: 0;
    bottom: 0;
    width: 2px;
    background: linear-gradient(to bottom, #3498db, #e0e0e0);
}

.tracking-item::before {
    content: '';
    position: absolute;
    left: 8px;
    top: 5px;
    width: 16px;
    height: 16px;
    border-radius: 50%;
    background-color: #3498db;
    border: 3px solid white;
    box-shadow: 0 0 0 2px #3498db;
}

.tracking-item:first-child::before {
    background-color: #27ae60;  /* 最新状态使用绿色 */
    box-shadow: 0 0 0 2px #27ae60;
}

3. 状态标签颜色区分

const statusMap = {
    'TRANSPORT': { text: '运输中', class: 'transport' },  // 蓝色
    'SIGNED': { text: '已签收', class: 'signed' },        // 绿色
    'COLLECT': { text: '已揽收', class: 'collect' }       // 橙色
};

4. 手机号输入验证

<input type="text" id="phone" name="phone" 
       placeholder="顺丰/中通必填" 
       maxlength="4" 
       pattern="[0-9]{4}">

5. 错误处理和提示

function showError(message) {
    const errorMessage = document.getElementById('error-message');
    errorMessage.textContent = message;
    errorMessage.classList.add('show');
}

常见问题与解决方案

问题 1: 快递公司列表加载失败

原因:Token 未设置或无效

解决方案

function loadExpressCompanies() {
    const token = localStorage.getItem('express_api_token');
    if (!token) {
        console.log('未找到Token,跳过加载快递公司列表');
        return;  // 静默失败,不影响主功能
    }
    // ... 加载逻辑
}

问题 2: 顺丰/中通查询失败

原因:缺少手机号后四位

解决方案

  1. 在表单中提示用户输入手机号后四位
  2. 在查询前验证是否为顺丰/中通,并检查手机号
// 可以添加验证逻辑
if ((formData.com === 'sf' || formData.com === 'zto') && !formData.phone) {
    showError('顺丰/中通快递需要输入手机号后四位');
    return;
}

问题 3: 时间线显示不完整

原因:CSS 样式问题或数据格式问题

解决方案

.tracking-item {
    position: relative;
    padding-left: 45px;
    padding-bottom: 25px;
}

.tracking-content {
    background-color: #f8f9fa;
    padding: 15px;
    border-radius: 6px;
    word-wrap: break-word;  /* 长文本自动换行 */
}

问题 4: 自动识别快递公司不准确

原因:某些快递单号格式相似

解决方案

  1. 提供手动选择快递公司的选项
  2. 在查询失败时提示用户手动选择

问题 5: 物流轨迹为空

原因:快递单号错误或快递公司不支持

解决方案

if (data.info && Array.isArray(data.info) && data.info.length > 0) {
    // 显示轨迹
} else {
    html += '<div style="text-align: center; padding: 20px; color: #7f8c8d;">暂无物流轨迹信息</div>';
}

最佳实践

1. 代码组织

  • 分离关注点:HTML 负责结构,CSS 负责样式,JavaScript 负责逻辑
  • 模块化设计:将功能拆分为独立的函数
  • 命名规范:使用有意义的变量和函数名

2. 错误处理

fetch('https://v3.alapi.cn/api/kd', {
    method: 'POST',
    // ...
})
.then(response => {
    if (!response.ok) {
        throw new Error('网络请求失败: ' + response.status);
    }
    return response.json();
})
.then(data => {
    if (data.success && data.code === 200) {
        displayExpressInfo(data.data);
    } else {
        showError(data.message || '查询失败,请检查参数');
    }
})
.catch(error => {
    console.error('请求错误:', error);
    showError('请求失败: ' + error.message);
});

3. 性能优化

// 缓存快递公司列表
let expressCompanies = [];

// 只在 Token 更新时重新加载
document.getElementById('token').addEventListener('blur', function() {
    const token = this.value.trim();
    if (token && token !== localStorage.getItem('express_api_token')) {
        localStorage.setItem('express_api_token', token);
        loadExpressCompanies();
    }
});

4. 用户体验

  • 即时反馈:按钮状态、加载提示、错误信息
  • 数据持久化:Token 自动保存
  • 无障碍访问:合理的标签和提示文字
  • 响应式设计:适配各种屏幕尺寸

5. 安全性

  • 输入验证:前端和后端双重验证
  • CSP 配置:限制资源加载来源
  • Token 安全:不在代码中硬编码 Token
  • HTTPS:生产环境使用 HTTPS
  • XSS 防护:使用 textContent 而非 innerHTML(注意:本示例使用 innerHTML 是因为需要动态创建 HTML 结构,实际应用中应使用模板引擎或 DOM API)

项目结构

www/
├── express.html          # 快递查询页面
├── js/
│   └── express.js        # 快递查询功能脚本
├── index.html            # 首页
├── about.html            # 关于我们
├── poem.html             # 藏头诗页面
├── translate.html        # 翻译页面
└── css/
    └── index.css         # 样式文件

harmonyos/entry/src/main/resources/rawfile/www/
├── express.html          # 快递查询页面(同步)
├── js/
│   └── express.js         # 快递查询功能脚本(同步)
└── ...

部署说明

1. 开发环境

# 添加浏览器平台(用于测试)
hcordova platform add browser

# 运行浏览器预览
hcordova run browser

2. 生产环境

# 构建 HarmonyOS 应用
hcordova build harmonyos

# 构建 Android 应用
hcordova build android

# 构建 iOS 应用(仅 macOS)
hcordova build ios

3. 配置检查

  • ✅ 检查 config.xml 中的 CSP 配置
  • ✅ 确认 API 域名在白名单中
  • ✅ 测试 Token 获取功能
  • ✅ 验证表单验证逻辑
  • ✅ 测试各种快递公司的查询

测试建议

1. 功能测试

  • 表单验证测试(快递单号、Token)
  • API 调用测试(正常情况、错误情况)
  • Token 存储测试(保存、加载)
  • 快递公司列表加载测试
  • 自动识别快递公司测试
  • 手动选择快递公司测试
  • 手机号后四位查询测试(顺丰/中通)
  • 物流轨迹展示测试

2. 兼容性测试

  • 不同浏览器测试(Chrome、Safari、Firefox)
  • 移动设备测试(iOS、Android、HarmonyOS)
  • 不同屏幕尺寸测试
  • 不同快递公司测试

3. 性能测试

  • API 响应时间
  • 页面加载速度
  • 内存使用情况
  • 长列表渲染性能

扩展功能建议

1. 历史记录

// 保存查询历史
function saveHistory(expressData) {
    const history = JSON.parse(localStorage.getItem('express_history') || '[]');
    history.unshift({
        number: expressData.nu,
        company: expressData.com_text,
        timestamp: Date.now()
    });
    // 只保留最近 20 条
    if (history.length > 20) {
        history.pop();
    }
    localStorage.setItem('express_history', JSON.stringify(history));
}

2. 收藏功能

// 收藏快递单号
function favoriteExpress(expressData) {
    const favorites = JSON.parse(localStorage.getItem('express_favorites') || '[]');
    favorites.push({
        number: expressData.nu,
        company: expressData.com_text,
        phone: document.getElementById('phone').value
    });
    localStorage.setItem('express_favorites', JSON.stringify(favorites));
}

3. 推送通知

// 使用 Cordova 推送插件实现物流更新推送
function subscribeExpressUpdates(number) {
    // 定期查询快递状态
    setInterval(() => {
        queryExpress();
        // 如果状态更新,发送推送通知
    }, 3600000); // 每小时查询一次
}

4. 分享功能

// 分享快递信息
function shareExpress(expressData) {
    if (navigator.share) {
        navigator.share({
            title: `快递查询 - ${expressData.com_text}`,
            text: `快递单号:${expressData.nu}\n状态:${expressData.status_desc}`
        });
    } else {
        // 复制到剪贴板
        navigator.clipboard.writeText(`快递单号:${expressData.nu}`);
        alert('快递单号已复制到剪贴板');
    }
}

5. 批量查询

// 支持批量查询多个快递单号
function batchQuery(numbers) {
    const promises = numbers.map(number => {
        return fetch('https://v3.alapi.cn/api/kd', {
            method: 'POST',
            body: new URLSearchParams({
                token: token,
                number: number
            })
        }).then(res => res.json());
    });
    
    Promise.all(promises).then(results => {
        // 展示所有查询结果
    });
}

总结

本文详细介绍了如何在 Cordova 应用中实现快递查询功能,包括:

  1. 完整的实现方案:从页面设计到 API 集成
  2. 双 API 集成:快递公司列表和快递查询
  3. 用户体验优化:表单验证、加载提示、错误处理
  4. 时间线可视化:美观的物流轨迹展示
  5. Token 管理:自动保存和获取引导
  6. 响应式设计:完美适配各种设备
  7. 最佳实践:代码组织、错误处理、性能优化

关键技术点

  • 双 API 调用:快递公司列表 + 快递查询
  • 时间线设计:CSS 实现物流轨迹可视化
  • 状态映射:友好的状态显示
  • 自动加载:页面加载时自动获取快递公司列表
  • LocalStorage:客户端数据持久化
  • 响应式 CSS:移动端适配

项目亮点

  • 📦 多快递公司支持:支持主流快递公司查询
  • 🤖 智能识别:自动识别快递公司
  • 📱 时间线展示:直观的物流轨迹可视化
  • 🏷️ 状态标签:清晰的状态显示
  • 💾 智能的 Token 管理:自动保存、一键获取
  • 📱 完美的移动端适配:响应式布局、触摸优化
  • 良好的性能:快速响应、流畅交互

应用场景

  • 个人用户:查询自己的快递物流信息
  • 电商平台:集成到订单详情页
  • 物流管理:批量查询和管理快递
  • 企业应用:内部物流跟踪系统

通过本文的指导,您可以快速实现一个功能完整、用户体验良好的快递查询应用。希望本文对您的开发工作有所帮助!


作者: 坚果派开发团队
最后更新: 2025年
版本: 1.0

参考资源

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序媛夏天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值