数据加载中...请稍后(js一句代码)

本文介绍了一种在使用AJAX进行数据请求时显示加载进度提示的方法,通过在请求前后调用$.loading函数,实现用户体验的提升。示例代码展示了如何在获取城市和地区数据时应用这一技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在查询的之前加一句:

$.loading(true, "数据加载中,请稍候...");

查询之后加一句:

$.loading(false, "数据加载中,请稍候...");

ajax: 案例:

    function GetForeSearch() {
        //获取参数
        var citys = $("#citys_id option:selected").val();
        var region = $("#region_id option:selected").val();

        $.loading(true, "数据加载中,请稍候...");
        $.ajax({
            type: "POST",
            data: {
                citys: citys,
                region: region
            },
            url: "GetYdSweet",
            dataType: "JSON",
            success: function (data) {
                $.loading(false, "数据加载中,请稍候...");
            }
        });
    }
// 解析数据引用关系的辅助函数 /** * 解析数据中的引用关系 * 该函数用于处理嵌套的数据结构,将数据中的引用关系解析为实际的对象引用。 * 它会遍历数据中的所有实体,查找属性名中包含的数字(如"item1"), * 并尝试将这些属性值替换为对应类型数据中的实际对象引用。 * @param {Object} data - 包含嵌套引用的原始数据对象 * @returns {Object} 处理后的数据对象,其中引用已被解析为实际对象 */ function resolveDataReferences(data) { const keys = Object.keys(data); for (const key of keys) { const entities = data[key]; for (const entity of entities) { for (const attribute in entity) { if (entity.hasOwnProperty(attribute)) { // 修复:统一使用复数形式查找引用类型 let refType = attribute.replace(/\d/g, ''); // 尝试直接查找复数形式 if (!data[refType] && data[`${refType}s`]) { refType = `${refType}s`; } if (Array.isArray(entity[attribute])) { entity[attribute] = entity[attribute].map(item => data[refType]?.find(updateItem => updateItem.id === item.id) || item ); } else if (typeof entity[attribute] === "object" && entity[attribute] !== null) { entity[attribute] = data[refType]?.find(updateItem => updateItem.id === entity[attribute].id) || entity[attribute]; } } } } } return data; } // 解析单个实体的数据引用 /** * 解析数据引用关系 * 该函数用于处理实体对象与数据源之间的引用关系,自动匹配并更新实体中的引用字段。 * @param {Object} entity - 需要处理的实体对象 * @param {Object} data - 包含引用数据数据源对象 * @returns {Object} 处理后的实体对象 * 功能说明: * 遍历实体对象的每个属性 * 如果属性值是数组,则尝试在数据源中查找匹配项更新数组元素 * 如果属性值是对象,则尝试在数据源中查找匹配项更新该对象 * 自动处理单复数形式的数据源键名 */ function resolveDataReference(entity, data) { for (const attribute in entity) { if (entity.hasOwnProperty(attribute)) { // 修复:统一使用复数形式查找引用类型 let refType = attribute.replace(/\d/g, ''); // 尝试直接查找复数形式 if (!data[refType] && data[`${refType}s`]) { refType = `${refType}s`; } if (Array.isArray(entity[attribute])) { entity[attribute] = entity[attribute].map(item => data[refType]?.find(updateItem => updateItem.id === item.id) || item ); } else if (typeof entity[attribute] === "object" && entity[attribute] !== null) { entity[attribute] = data[refType]?.find(updateItem => updateItem.id === entity[attribute].id) || entity[attribute]; } } } return entity; } /** * 懒加载处理器 * 负责管理实体类之间的关联依赖,实现按需加载 */ class LazyLoader { constructor(dataManager) { this.dataManager = dataManager; this.cache = new Map(); this.entityTypeMap = { bancai: 'bancais', dingdan: 'dingdans', mupi: 'mupis', chanpin: 'chanpins', kucun: 'kucuns', dingdan_bancai: 'dingdan_bancais', chanpin_zujian: 'chanpin_zujians', zujian: 'zujians', caizhi: 'caizhis', dingdan_chanpin: 'dingdan_chanpins', user: 'users', jinhuo: 'jinhuos' }; } /** * 创建实体代理 * @param {Object} entity 实体对象 * @param {string} entityType 实体类型 * @returns {Proxy} 返回代理后的实体 */ // 修复2:增强代理创建逻辑 createProxy(entity, entityType) { // 添加循环引用检测标记 if (entity.__isProxy) return entity; const handler = { get: (target, prop) => { console.log(prop) // 特殊属性处理 // if (prop === '__isProxy') return true; const value = target[prop]; // 基本类型直接返回 if (typeof value !== 'object' || value === null) { return value; } console.warn( baseProp) // 数组类型处理 if (Array.isArray(value)) { return value.map(item => item && !item.__isProxy ? this.createProxy(item, this.getEntityType(item)) : item ); } // 引用类型处理 const refType = this.getReferenceType(prop) || entityType; if (refType) { // 修复3:确保嵌套引用也被代理 if (!value.__isProxy) { return this.loadReference(value, refType); } } return value; }, set: (target, prop, value) => { // 清除相关缓存 this.cache.delete(this.getCacheKey(target)); target[prop] = value; return true; } }; const proxy = new Proxy(entity, handler); entity.__isProxy = true; // 标记为已代理 return proxy; } // 新增方法:根据实体类型获取缓存键 getCacheKey(entity) { if (!entity || !entity.id) return null; const entityType = this.getEntityType(entity) || 'unknown'; return `${entityType}_${entity.id}`; } // 新增方法:根据实体推断类型 getEntityType(entity) { if (!entity) return null; // 通过构造函数名或自定义属性判断类型 if (entity.constructor.name !== 'Object') { return entity.constructor.name.toLowerCase() + 's'; } return null; } // 修改:增强引用类型识别 getReferenceType(prop) { // 处理带数字后缀的属性 (mupi1 → mupis) const baseProp = prop.replace(/\d+$/, ''); const plural = this.entityTypeMap[baseProp] || `${baseProp}s`; // 检查类型是否存在 const ret=this.dataManager._rawData[plural] ? plural : null; console.warn( baseProp) if(!ret){ console.warn( baseProp) } return } // 修改:简化加载逻辑 async loadReference(ref, refType) { if (!ref || !ref.id) return ref; const cacheKey = `${refType}_${ref.id}`; if (this.cache.has(cacheKey)) { return this.cache.get(cacheKey); } // 直接使用现有数据,移除同步调用 const entities = this.dataManager._rawData[refType] || []; const entity = entities.find(e => e.id === ref.id); if (entity) { // 修复5:不再使用resolveDataReference const proxy = this.createProxy(entity, refType); this.cache.set(cacheKey, proxy); return proxy; } return ref; // 保持原始引用 } /** * 加载多个关联引用 * @param {Array} refs 引用对象数组 * @param {string} refType 引用类型(复数形式) * @returns {Promise<Array>} 解析后的实体对象数组 */ async loadReferences(refs, refType) { if (!Array.isArray(refs)) return []; return Promise.all( refs.map(ref => this.loadReference(ref, refType)) ); } /** * 清除缓存 */ clearCache() { this.cache.clear(); } } class MiniProgramDataManager { constructor(baseUrl) { this.baseUrl = baseUrl; this.debug = true; // 调试模式开关 this.requestCount = 0; // 求计数器 // 数据结构定义 this._rawData = { bancais: [], dingdans: [], mupis: [], chanpins: [], kucuns: [], dingdan_bancais: [], chanpin_zujians: [], zujians: [], caizhis: [], dingdan_chanpins: [], users: [], jinhuos: [], _lastModified: null, _lastSync: null }; // 初始化网络状态 this.networkAvailable = false; this.checkNetwork().then(type => { this.networkAvailable = type !== 'none'; }); this.lazyLoader = new LazyLoader(this); this.loadDataFromStorage(); this.isSyncing = false; this.lastSync = null; this.callbacks = { all: [], bancais: [], dingdan: [], mupi: [], chanpin: [], kucun: [], chanpin_zujian: [], dingdan_bancai: [], zujian: [], caizhi: [], dingdan_chanpin: [], user: [], jinhuo: [] }; this.syncQueue = Promise.resolve(); this.entiyeText = { bancai: '板材已存在', dingdan: '订单已存在', mupi: '木皮已存在', chanpin: '产品已存在', kucun: '已有库存记录', chanpin_zujian: '产品已有该组件', dingdan_bancai: '', zujian: '组件已定义过了', caizhi: '材质已定义过了', dingdan_chanpin: '订单下已有该产品', user: '' }; this.syncInterval = 5 * 60 * 1000; // 5分钟 this.storageKey = 'miniProgramData'; // 本地存储的键名 } get data() { const handler = { get: (target, prop) => { if (prop.startsWith('_')) return target[prop]; if (Array.isArray(target[prop])) { // 修复6:直接创建代理数组 return target[prop].map(item => this.lazyLoader.createProxy(item, prop.replace(/s$/, '')) ); } return target[prop]; }, set(target, prop, value) { // 修复7:设置清除相关缓存 if (Array.isArray(value)) { value.forEach(item => this.lazyLoader.cache.delete( this.lazyLoader.getCacheKey(item)) ); } else { this.lazyLoader.cache.delete( this.lazyLoader.getCacheKey(value)); } target[prop] = value; return true; } }; return new Proxy(this._rawData, handler); } // 添加显式初始化方法 async initialize() { // 启动自动同步 this.startAutoSync(); // 执行首次数据同步 await this.syncData(); } /** * 启动自动同步定器 * 每隔syncInterval毫秒检查并执行数据同步 * 如果已有同步任务进行中则跳过 */ startAutoSync() { if (this.autoSyncTimer) clearInterval(this.autoSyncTimer); this.autoSyncTimer = setInterval(() => { if (!this.isSyncing) this.syncData(); }, this.syncInterval); } /** * 停止自动同步 */ stopAutoSync() { clearInterval(this.autoSyncTimer); } /** * 检查网络状态 */ checkNetwork() { return new Promise((resolve) => { wx.getNetworkType({ success: (res) => { resolve(res.networkType); }, fail: () => { resolve('unknown'); } }); }); } /** * 获取所有数据(全量或增量) * @async * @param {string} [since] - 增量获取的间戳,不传则全量获取 * @returns {Promise} 是否获取成功 * @description * 根据since参数决定全量或增量获取数据 * 增量获取会合并新数据到现有数据 * 全量获取会直接替换现有数据 * 成功后会更新同步间并保存到本地存储 * 失败会触发错误回调,若无历史数据则抛出错误 */ async fetchAll(since) { try { console.log(since ? `增量获取数据(自${since})...` : '全量获取数据...'); const params = since ? { since } : {}; const result = await this.request('/app/all', 'GET', params); const resolvedData = result; // 更新networkData Object.keys(this._rawData).forEach(key => { if (key.startsWith('_')) return; if (resolvedData[key]) { if (since) { // 增量更新: 合并新数据到现有数据 resolvedData[key].forEach(newItem => { const index = this._rawData[key].findIndex(item => item.id === newItem.id); if (index >= 0) { this._rawData[key][index] = newItem; } else { this._rawData[key].push(newItem); } }); } else { // 全量更新: 直接替换 this._rawData[key] = resolvedData[key]; } } }); // 更新同步间 this.lastSync = new Date(); this._rawData._lastSync = this.lastSync.toISOString(); // 保存到本地存储 this.saveDataToStorage(); this.triggerCallbacks('refresh', 'all', this.data); return true; } catch (error) { console.error('Fetch error:', error); this.triggerCallbacks('fetch_error', 'all', { error }); // 失败尝试使用本地数据 if (!this.lastSync) { throw new Error('初始化数据获取失败'); } return false; } } /** * 微信小程序API求封装 */ request(url, method = 'GET', data = null, retryCount = 3) { return new Promise((resolve, reject) => { const makeRequest = (attempt) => { const fullUrl = `${this.baseUrl}${url}`; if (this.debug) { console.log(`[求] ${method} ${fullUrl}`, { attempt, data, timestamp: new Date().toISOString() }); } wx.request({ url: fullUrl, method, data, header: { 'Content-Type': 'application/json' }, success: (res) => { if (this.debug) { console.log(`[响应] ${fullUrl}`, { status: res.statusCode, data: res.data, headers: res.header }); } // 修复:更灵活的响应格式处理 if (!res.data) { const err = new Error('空响应数据'); if (attempt < retryCount) { this.retryRequest(makeRequest, attempt, retryCount, err); } else { reject(err); } return; } // 修复:支持多种成功状态码和响应格式 const isSuccess = res.statusCode >= 200 && res.statusCode < 300; const hasData = res.data && (res.data.data !== undefined || typeof res.data === 'object'); if (isSuccess && hasData) { resolve(res.data.data || res.data); } else { const errMsg = res.data.message || res.data.text || 'API错误'; const err = new Error(errMsg); if (attempt < retryCount) { this.retryRequest(makeRequest, attempt, retryCount, err); } else { reject(err); } } }, fail: (err) => { if (this.debug) { console.error(`[失败] ${fullUrl}`, err); } const error = new Error(`网络求失败: ${err.errMsg || '未知错误'}`); if (attempt < retryCount) { this.retryRequest(makeRequest, attempt, retryCount, error); } else { reject(error); } } }); }; makeRequest(1); }); } retryRequest(makeRequest, attempt, retryCount, error) { const delay = 1000 * attempt; console.warn(`求失败 (${attempt}/${retryCount}), ${delay}ms后重试:`, error.message); setTimeout(() => makeRequest(attempt + 1), delay); } /** * 注册回调函数 */ registerCallback(entity, callback) { if (!this.callbacks[entity]) { this.callbacks[entity] = []; } this.callbacks[entity].push(callback); } /** * 注销回调函数 */ unregisterCallback(entity, callback) { if (!this.callbacks[entity]) return; const index = this.callbacks[entity].indexOf(callback); if (index !== -1) { this.callbacks[entity].splice(index, 1); } } /** * 触发回调函数 */ triggerCallbacks(operation, entity, data) { this.callbacks.all.forEach(cb => cb(operation, entity, data)); if (this.callbacks[entity]) { this.callbacks[entity].forEach(cb => cb(operation, data)); } } /** * 检查重复实体 */ checkDuplicate(entity, data) { // 修复:确保引用已解析 const resolvedData = resolveDataReference(data, this.data); switch (entity) { case 'bancai': return this.data.bancais.some(b => b.houdu === resolvedData.houdu && b.caizhi?.id === resolvedData.caizhi?.id && b.mupi1?.id === resolvedData.mupi1?.id && b.mupi2?.id === resolvedData.mupi2?.id ); case 'caizhi': return this.data.caizhis.some(c => c.name === resolvedData.name); case 'mupi': return this.data.mupis.some(m => m.name === resolvedData.name && m.you === resolvedData.you ); case 'chanpin': return this.data.chanpins.some(c => c.bianhao === resolvedData.bianhao); case 'zujian': return this.data.zujians.some(z => z.name === resolvedData.name); case 'dingdan': return this.data.dingdans.some(d => d.number === resolvedData.number); case 'chanpin_zujian': return this.data.chanpin_zujians.some(cz => cz.chanpin?.id === resolvedData.chanpin?.id && cz.zujian?.id === resolvedData.zujian?.id ); case 'dingdan_chanpin': return this.data.dingdan_chanpins.some(dc => dc.dingdan?.id === resolvedData.dingdan?.id && dc.chanpin?.id === resolvedData.chanpin?.id ); case 'dingdan_bancai': return this.data.dingdan_bancais.some(db => db.dingdan?.id === resolvedData.dingdan?.id && db.chanpin?.id === resolvedData.chanpin?.id && db.zujian?.id === resolvedData.zujian?.id && db.bancai?.id === resolvedData.bancai?.id ); case 'user': return this.data.users.some(u => u.name === resolvedData.name); default: return false; } } /** * CRUD操作通用方法 */ async crudOperation(operation, entity, data) { try { // 使用微信求API替代fetch const result = await this.request(`/app/${operation}/${entity}`, 'POST', data); this.updateLocalData(operation, entity, result || data); this.triggerCallbacks(operation, entity, result || data); return result; } catch (error) { console.error('CRUD error:', error); this.triggerCallbacks(`${operation}_error`, entity, { data, error: error.message }); throw error; } } /** * 更新本地数据 * @param {string} operation - 操作类型: 'add' | 'update' | 'delete' * @param {string} entity - 实体名称 * @param {Object} newData - 新数据对象(包含id字段) * @description 根据操作类型对本地数据进行增删改操作 */ updateLocalData(operation, entity, newData) { const key = `${entity}s`; const entities = this._rawData[key]; // 确保新数据的引用已解析 const resolvedData = resolveDataReference(newData, this._rawData); switch (operation) { case 'add': entities.push(resolvedData); break; case 'update': const index = entities.findIndex(item => item.id === resolvedData.id); if (index !== -1) { // 修复:使用对象展开操作符确保属性完整覆盖 entities[index] = { ...entities[index], ...resolvedData }; } else { entities.push(resolvedData); } break; case 'delete': const deleteIndex = entities.findIndex(item => item.id === resolvedData.id); if (deleteIndex !== -1) { entities.splice(deleteIndex, 1); } break; } // 更新最后修改间 this._rawData._lastModified = new Date().toISOString(); // 清除懒加载缓存 this.lazyLoader.clearCache(); // 保存修改后的数据到本地存储 this.saveDataToStorage(); } /** * 同步数据方法 * 该方法用于异步获取所有数据,并处理同步过程中的并发求 * 如果同步正在进行中,会将求标记为待处理(pendingSync) * 同步完成后会自动处理待处理的求 * @async * @throws {Error} 当获取数据失败会抛出错误并记录日志 */ async syncData() { if (this.isSyncing) { this.pendingSync = true; return; } this.isSyncing = true; try { // 1.加载本地数据 this.loadDataFromStorage(); // 2. 获取最后同步间,用于增量更新 const since = this._rawData._lastSync || null; // 3. 获取增量数据 await this.fetchAll(since); // 4. 清除懒加载缓存 this.lazyLoader.clearCache(); // 5. 保存更新后的数据到本地存储 this.saveDataToStorage(); // 6. 触发数据更新回调 this.triggerCallbacks('refresh', 'all', this.data); } catch (error) { console.error('Sync failed:', error); this.triggerCallbacks('sync_error', 'all', { error }); // 失败尝试使用本地数据 if (!this._rawData._lastSync) { throw new Error('初始化数据同步失败'); } } finally { this.isSyncing = false; if (this.pendingSync) { this.pendingSync = false; this.syncData(); } } } /** * 从本地存储加载数据 * 使用微信小程序的同步存储API获取之前保存的数据 */ loadDataFromStorage() { try { const storedData = wx.getStorageSync(this.storageKey); if (storedData) { // 修复:加载到_rawData而非data代理对象 this._rawData = storedData; // 解析所有引用关系 // resolveDataReferences(this._rawData); } } catch (error) { console.error('加载本地存储数据失败:', error); // 提供默认空数据 this._rawData = { bancais: [], dingdans: [], mupis: [], chanpins: [], kucuns: [], dingdan_bancais: [], chanpin_zujians: [], zujians: [], caizhis: [], dingdan_chanpins: [], users: [], jinhuos: [], _lastModified: null, _lastSync: null }; } } /** * 保存数据到本地存储 * 使用微信小程序的同步存储API持久化当前数据 */ saveDataToStorage() { try { // 修复:保存_rawData而非localData wx.setStorageSync(this.storageKey, this._rawData); } catch (error) { console.error('保存数据到本地存储失败:', error); // 提示用户或执行降级策略 wx.showToast({ title: '数据保存失败,稍后重试', icon: 'none' }); } } /** * 添加实体数据 * @async * @param {string} entity - 实体类型 * @param {Object} data - 要添加的实体数据 * @returns {Promise} 返回CRUD操作结果 * @throws {Error} 如果数据已存在则抛出错误 */ async addEntity(entity, data) { if (this.checkDuplicate(entity, data)) { const errorMsg = `${this.entiyeText[entity]}`; this.triggerCallbacks('duplicate_error', entity, { data, error: errorMsg }); throw new Error(errorMsg); } return this.crudOperation('add', entity, data); } /** * 更新实体 */ async updateEntity(entity, data) { return this.crudOperation('update', entity, data); } /** * 删除实体 */ async deleteEntity(entity, id) { return this.crudOperation('delete', entity, { id }); } getBancaisForZujian(zujianId) { const dingdan_bancais = this.data.dingdan_bancais.filter(db => db.zujian?.id == zujianId); return dingdan_bancais.map(db => db.bancai).filter(Boolean); } /** * 获取板材的库存信息 */ getKucunForBancai(bancaiId) { return this.data.kucuns.find(k => k.bancai?.id == bancaiId); } } // 导出模块 module.exports = MiniProgramDataManager;---------------------------------------------第116行的 const handler = {}中的函数就没触发过----------------------------------[Deprecation] SharedArrayBuffer will require cross-origin isolation as of M92, around July 2021. See https://developer.chrome.com/blog/enabling-shared-array-buffer/ for more details. [system] WeChatLib: 3.8.10 (2025.7.4 16:39:26) [system] Subpackages: N/A [system] LazyCodeLoading: false app.js? [sm]:11 小程序启动 app.js? [sm]:18 检测到已登录状态,直接登录 MiniProgramDataManager.js? [sm]:375 增量获取数据(自2025-07-22T08:02:47.308Z)... MiniProgramDataManager.js? [sm]:433 [求] GET http://192.168.1.11:8080/app/all {attempt: 1, data: {…}, timestamp: "2025-07-22T08:05:08.107Z"} Tue Jul 22 2025 16:05:08 GMT+0800 (中国标准) 配置中关闭合法域名、web-view(业务域名)、TLS 版本以及 HTTPS 证书检查 工具未校验合法域名、web-view(业务域名)、TLS 版本以及 HTTPS 证书。 makeRequest @ MiniProgramDataManager.js? [sm]:440 (anonymous) @ MiniProgramDataManager.js? [sm]:497 request @ MiniProgramDataManager.js? [sm]:428 _callee4$ @ MiniProgramDataManager.js? [sm]:378 s @ regeneratorRuntime.js?forceSync=true:1 (anonymous) @ regeneratorRuntime.js?forceSync=true:1 (anonymous) @ regeneratorRuntime.js?forceSync=true:1 asyncGeneratorStep @ asyncToGenerator.js?forceSync=true:1 c @ asyncToGenerator.js?forceSync=true:1 (anonymous) @ asyncToGenerator.js?forceSync=true:1 (anonymous) @ asyncToGenerator.js?forceSync=true:1 fetchAll @ MiniProgramDataManager.js? [sm]:422 _callee6$ @ MiniProgramDataManager.js? [sm]:679 s @ regeneratorRuntime.js?forceSync=true:1 (anonymous) @ regeneratorRuntime.js?forceSync=true:1 (anonymous) @ regeneratorRuntime.js?forceSync=true:1 asyncGeneratorStep @ asyncToGenerator.js?forceSync=true:1 c @ asyncToGenerator.js?forceSync=true:1 (anonymous) @ asyncToGenerator.js?forceSync=true:1 (anonymous) @ asyncToGenerator.js?forceSync=true:1 syncData @ MiniProgramDataManager.js? [sm]:705 _callee3$ @ MiniProgramDataManager.js? [sm]:323 s @ regeneratorRuntime.js?forceSync=true:1 (anonymous) @ regeneratorRuntime.js?forceSync=true:1 (anonymous) @ regeneratorRuntime.js?forceSync=true:1 asyncGeneratorStep @ asyncToGenerator.js?forceSync=true:1 c @ asyncToGenerator.js?forceSync=true:1 (anonymous) @ asyncToGenerator.js?forceSync=true:1 (anonymous) @ asyncToGenerator.js?forceSync=true:1 initialize @ MiniProgramDataManager.js? [sm]:324 onLaunch @ app.js? [sm]:26 (anonymous) @ app.js? [sm]:2 Show 2 more frames MiniProgramDataManager.js? [sm]:449 [响应] http://192.168.1.11:8080/app/all {status: 200, data: {…}, headers: Proxy} index.js? [sm]:44 index页面加载 index.js? [sm]:108 开始更新表格数据 - 优化版 index.js? [sm]:114 {caizhi: {…}, mupi1: {…}, mupi2: {…}, houdu: 3, kucun: null, …} updateTable @ index.js? [sm]:114 updatePageData @ index.js? [sm]:81 onLoad @ index.js? [sm]:56 index.js? [sm]:61 首页显示 [system] Launch Time: 3481 ms
最新发布
07-23
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值