【JavaScript】使用ES6实现雪花算法

js版的雪花算法(SnowFlake) import bigInt from 'big-integer'; // http://peterolson.github.io/BigInteger.js/ /** * Twitter_Snowflake(雪花算法) * * SnowFlake的结构如下(共64bits,每部分用-分开): * 0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000 * | ---------. 阅读详情

talk is cheap, show me the code.

Snowflake.js

/**
 * 雪花算法获取ID
 *
 * @author: tanpeng
 * @since : 2020/7/24 15:00
 */
class Snowflake {
  constructor(_workerId, _dataCenterId, _sequence) {
    this.twepoch = 1288834974657n;
    // this.twepoch = 0n;
    this.workerIdBits = 5n;
    this.dataCenterIdBits = 5n;
    this.maxWrokerId = -1n ^ (-1n << this.workerIdBits); // 值为:31
    this.maxDataCenterId = -1n ^ (-1n << this.dataCenterIdBits); // 值为:31
    this.sequenceBits = 12n;
    this.workerIdShift = this.sequenceBits; // 值为:12
    this.dataCenterIdShift = this.sequenceBits + this.workerIdBits; // 值为:17
    this.timestampLeftShift = this.sequenceBits + this.workerIdBits + this.dataCenterIdBits; // 值为:22
    this.sequenceMask = -1n ^ (-1n << this.sequenceBits); // 值为:4095
    this.lastTimestamp = -1n;
    //设置默认值,从环境变量取
    this.workerId = 1n;
    this.dataCenterId = 1n;
    this.sequence = 0n;
    if (this.workerId > this.maxWrokerId || this.workerId < 0) {
      throw new Error(`_workerId must max than 0 and small than maxWrokerId-[${this.maxWrokerId}]`);
    }
    if (this.dataCenterId > this.maxDataCenterId || this.dataCenterId < 0) {
      throw new Error(`_dataCenterId must max than 0 and small than maxDataCenterId-[${this.maxDataCenterId}]`);
    }

    this.workerId = BigInt(_workerId);
    this.dataCenterId = BigInt(_dataCenterId);
    this.sequence = BigInt(_sequence);
  }

  tilNextMillis(lastTimestamp) {
    let timestamp = this.timeGen();
    while (timestamp <= lastTimestamp) {
      timestamp = this.timeGen();
    }
    return BigInt(timestamp);
  }

  timeGen() {
    return BigInt(Date.now());
  }

  nextId() {
    let timestamp = this.timeGen();
    if (timestamp < this.lastTimestamp) {
      throw new Error(`Clock moved backwards. Refusing to generate id for ${this.lastTimestamp - timestamp}`);
    }
    if (this.lastTimestamp === timestamp) {
      this.sequence = (this.sequence + 1n) & this.sequenceMask;
      if (this.sequence === 0n) {
        timestamp = this.tilNextMillis(this.lastTimestamp);
      }
    } else {
      this.sequence = 0n;
    }
    this.lastTimestamp = timestamp;
    return ((timestamp - this.twepoch) << this.timestampLeftShift) |
      (this.dataCenterId << this.dataCenterIdShift) |
      (this.workerId << this.workerIdShift) |
      this.sequence;
  }
}

Usage

console.time();
const snowflake = new Snowflake(1n, 1n, 0n);
const tempIds = [];
for (let i = 0; i < 10000; i++) {
  const id = snowflake.nextId();
  console.log(id);
  if (tempIds.indexOf(id) < 0) {
    tempIds.push(id);
  }
}
console.log(tempIds.length);
console.timeEnd();

疑问

  • 雪花算法生成的ID是多少位?是固定位数还是会变化?

  • twepoch的起始值为什么都是1288834974657?

雪花算法ID太长?前端JS处理大整数溢出怎么办?一个实战案例带你搞定 本文探讨了雪花算法生成的大整数ID在前端JavaScript中可能引发的精度丢失问题,并提供了四种解决方案:后端返回字符串格式、使用JavaScript的BigInt、json-bigint库处理以及自定义ID转换中间件。通过实战案例展示了如何在电商平台中有效处理订单ID,确保数据准确性和系统稳定性。 阅读详情

相关推荐

JavaScript实现雪花算法(附完整源码)

JavaScript实现雪花算法(附完整源码)

希望我的博客,能帮上你解决学习中工作中所遇到的问题 1438

js 雪花算法

非原创,代码来源找不到了,这里主要是记录代码,备用。 export const randomLenNum = (len, date) => { return tempSnowflake.getId() } export const Snowflake = /** @class */ (function() { function Snowflake(_workerId, _dataCenterId, _sequence) { this.twepoch = 12888349746

梁诗傑的博客 2880

Js Snowflake(雪花算法)生成随机ID的实现方法

1、snowflake-id插件  import SnowflakeId from "snowflake-id"; const guid = num => { const id= new SnowflakeId(); return id.generate(); }; 2、原生使用  var Snowflake = /** @class */ (function() { function Snowflake(_workerId, _dataCenterId, _sequence) { this.twepoch = 1288834974657n; //this.twepoch =

nodejs的中雪花算法(Snowflake)

雪花算法(Snowflake)是Twitter开发的一种分布式唯一ID生成算法,用于生成全局唯一的ID。雪花算法的核心思想是利用时间戳和机器ID来生成唯一的ID,确保在分布式环境下生成的ID不会重复。1位符号位,始终为0。41位的时间戳,精确到毫秒级,可以表示的时间范围约为69年。10位的机器ID,可以部署1024台机器。12位的序列号,表示在同一毫秒内生成的ID序号,最多支持4096个ID的生成。

T3165919332的博客 4174

vivado安装空间与依赖要求:入门须知要点

准备安装Vivado时,需重点关注系统空间和依赖环境的配置。结合vivado安装教程,详细说明最低磁盘要求、内存配置及操作系统兼容性,帮助新手快速搭建开发环境,避免常见安装失败问题。

weixin_34725745的博客 1572

安卓光速虚拟机ADB调试实战:从密钥配置到设备连接

本文详细介绍了在安卓光速虚拟机中进行ADB调试的完整实战流程。核心在于通过密钥配置解决设备未授权问题,并启用网络调试与端口映射,最终实现电脑与虚拟机的稳定连接。文章提供了从原理理解、脚本修改到实战命令和疑难排查的全方位指南,帮助开发者和爱好者高效利用光速虚拟机作为移动测试沙盒。

CAT789的专栏 553

js 去重及去掉数组中的空值

1.数组去重 var arr = ["1343", "rere", "1343", "rerd"]; Array.prototype.unique = function(){ var res = []; var json = {}; for(var i = 0; i < this.length;i++){ if(!json[this[i]]){ res.pu...

weixin_30914981的博客 1035

Linux初级介绍之番外篇:Linux挂载windows中的共享目录

挂载windows共享目录Windows端共享权限设定解禁Guest设置共享目录权限Linux挂载端扫描共享目录挂载共享目录遇到错误的解决方案 Windows端共享权限设定 解禁Guest 右击我的电脑选择管理–>本地用户和组–>在用户项中双击Guest用户–>取消账号已禁用选项 设置共享目录权限 右击共享目录点属性–>在共享页面中点击共享选项–>下拉选择共享对象为Everyone–>点击共享按钮 3.设置本地策略 打开命令框–>输入secpol.msc–&gt

m0_53497201的博客 228

雪花算法生成数字id_JS 雪花算法生成随机 ID

生成一个随机的 ID 有很多种做法,比如说 GUID 和 UUID。但如果想要有序,可以插入数据库中做数字主键,那就有了雪花算法。雪花算法得到的是个比较大的数字,比较大,而 JS 中 Number 类型的最大值 Number.MAX_SAFE_INTEGER:9007199254740991,那这样运算会溢出。所幸的是网上有很多 BigInt 的类库,现在 ES10 标准就包括了它,并且 Chro...

weixin_39986027的博客 1351

用Java实现森林冰火人游戏

g.drawString("游戏结束", CELL_SIZE * COLS / 2 - 100, CELL_SIZE * ROWS / 2);g.drawString("难度级别: " + difficultyLevel, 10, CELL_SIZE * ROWS + 60);g.drawString("生命值: " + playerHealth, 10, CELL_SIZE * ROWS + 20);setTitle("森林冰火人");

2401_82778412的博客 1734

【NodeRed】node-red-contrib-opcua实现PLC读写

在之前的博文【Node-RED】node-red-contrib-opcua-server模块使用(1)中,我们介绍了用node-red-contrib-opcua-server模块实现OPCUA服务端的,以及二次开发的内容。本节博文中我们采用官方社区自带的node-red-contrib-opcua组件开展对OPCUA客户端的介绍,详细阐述用该组件中OpcUa-Client节点实现客户端对PLC的读写,以及实现过程中遇到的问题。由于官方社区中并没有找到该组件的介绍实例,这也是本博文编写的第1个原因。

weixin_48618536的博客 957

牛气的JavaScript,让雪花算法成为空气

http://xjjdog.cn 对200+原创文章进行了细致的分类,阅读更流畅,欢迎收藏。不羡鸳鸯不羡仙,一行代码调半天。原创:小姐姐味道(微信公众号ID:xjjdog),欢迎分享,转...

小姐姐味道 6382

YOLOv11改进 | 注意力篇 | YOLOv11引入CA注意力机制

摘要:最近关于移动网络设计的研究已经证明了通道注意力(例如,挤压和激励注意力)对于提升模型性能的显着有效性,但它们通常忽略了位置信息,而位置信息对于生成空间选择性注意力图很重要。到此本文的正式分享内容就结束了,在这里给大家推荐我的YOLOv11改进有效涨点专栏,本专栏目前为新开的,后期我会根据各种前沿顶会进行论文复现,也会对一些老的改进机制进行补充,如果大家觉得本文帮助到你了,订阅本专栏,关注后续更多的更新~3.2 在Extramodule里创建CA。在CA.py文件里添加给出的CA代码。

tsg6698的博客 2978

Node.js Snowflake 项目使用文档

Node.js Snowflake 项目使用文档 1. 项目的目录结构及介绍 nodejs-snowflake/ ├── LICENSE ├── README.md ├── examples/ │ ├── basic.js │ └── customEpoch.js ├── index.js ├── package.json └── test/ └── snowflake.test....

gitblog_00398的博客 563

Flutter框架GetX从入门到精通第二篇:路由管理-告别繁琐的Navigator

Flutter框架GetX从入门到精通第二篇:告别繁琐的Navigator。本系列将带你从零开始,一步步掌握 GetX 框架的核心功能与实战技巧。

鹏多多的博客 170

基于STM32设计的智能门锁(微信小程序+手机APP等多种方式开锁)(188)

当前智能门锁项目是基于STM32微控制器、ESP8266-WIFI模块、OLED显示屏、指纹模块、蓝牙模块、门禁刷卡模块、烟雾检测模块、火光检测模块、温湿度检测模块等硬件设备开发的一种智能门锁系统

1万+

Js Snowflake(雪花算法)生成随机ID

1、snowflake-id插件 import SnowflakeId from "snowflake-id"; const guid = num => { const id= new SnowflakeId(); return id.generate(); }; 2、原生使用 var Snowflake = /** @class */ (function() { ...

忘川 1万+

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

Node.js 分布式架构实战:基于雪花算法构建高并发ID生成服务

本文详细介绍了如何基于Node.js和雪花算法构建高并发分布式ID生成服务。通过实战案例展示了从工具函数到独立服务的改造过程,包括HTTP接口封装、机器ID动态分配和性能优化技巧。文章还深入探讨了高可用架构设计、生产环境集成指南以及真实场景压测数据,帮助开发者应对电商大促等高并发场景下的ID生成挑战。

weixin_29213525的博客 214

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

Node.js雪花算法避坑指南:时钟回拨、大数精度、机器ID分配,一个都不能少

本文深入探讨Node.js中雪花算法的关键问题与解决方案,包括时钟回拨、大数精度和机器ID分配。通过实战案例和代码示例,提供防御时钟回拨的多层级方案、JavaScript大数处理技巧,以及容器化环境下的动态ID分配策略,帮助开发者构建健壮的分布式ID生成系统。

weixin_29290379的博客 334

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

java数据类型:Long 和 long 在雪花算法ID下的陷阱

摘要: 雪花算法生成的19位长整型ID在前后端交互中易引发精度丢失和类型陷阱,是分布式系统高频故障点。核心问题: Java端:Long包装类计算时可能因拆箱导致NullPointerException,建议使用基本类型long;数据库需用BIGINT存储,误用INT会因超限引发事故。 前端精度丢失:JS的Number仅支持16位安全整数,19位ID会截断(如1478733705032859648变为1478733705032859600)。解决方案: 后端全局配置:通过Jackson将Long序列化为字符串

qxoffice2008的专栏 453

前端不能识别雪花算法id解决⽅案

直接把id类型改为String就⾏,使⽤JackSon包的注解,对应的实体类主键属性加⼊注解@JsonSerialize。雪花算法⽣成的id作为主键时,因为其⻓度为19位,⽽前端JS⼀般能处理16位,如果不处理的话在前端会造成精度。前端使⽤ json-bigint 模块进⾏处理,⼀般都是⽤axios数据请求。

xu990128638的专栏 636

2024年前端最全前端接收后端数据时,遇到精度丢失的问题_前端数字精度丢失,2024年最新前端基础面试题及答案

例如,如果 Java 对象的一个属性是 Long 类型,使用默认的序列化方式时,该属性的值会被序列化为一个数字类型的 JSON 值。前端框架太多了,真的学不动了,别慌,其实对于前端的三大马车,Angular、React、Vue 只要把其中一种框架学明白,底层原理实现,其他两个学起来不会很吃力,这也取决于你以后就职的公司要求你会哪一个框架了,当然,会的越多越好,但是往往每个人的时间是有限的,对于自学的学生,或者即将面试找工作的人,当然要选择一门框架深挖原理。我这部分的学习技巧是,增加次数,减少单次看的内容。

2401_84446580的博客 416

Spring Boot项目前后端Long类型数据传递失真问题的处理方式

场景介绍: 项目场景:目前市场上的大多数项目对于对象表建设的ID属性使用的是Long性并使用雪花算法生成,少量使用String的UUID,极少量的使用Long类型的自增长。 1 . Long型雪花算法ID 雪花算法 : 分布式id生成算法的有很多种,Twitter的SnowFlake就是其中经典的一种。 优点:雪花算法id是一个64bits的Long数据,第一位为零表示其为正数,最后12位为其序列号,生成的id既能完美契合分布式ID的需求,同时后12位序列号也能够保证主键的有序性。 缺点:雪花算法

qq_39941165的博客 4277
上一篇: 【Exception】Uncaught (in promise) Error: Redirected from “/xx” to “/yy” via a navigation guard
下一篇: 【Ubuntu】如何将命令行启动的应用加入到Application?即如何将应用程序添加到启动器?
tanpenggood
博客等级 码龄9年 129粉丝 197原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值