jenkins自动化CICD

部署

中文文档 https://www.jenkins.io/zh/doc/book/installing/

安装 jenkins

  1. 上传yum源

  2. 安装key

    rpm --import jenkins.io.key
    yum -y install jenkins-2.301-1.1.noarch.rpm
    #注:新版 GitLab 的服务端口为 8080,和 GitLab 的服务端口相冲突,修改Jenkins的默认端口8080为198 
    
  3. 配置文件

    vim /etc/sysconfig/jenkins  
    JENKINS_PORT="8888" 
    #数据目录,建议用固态磁盘来存数据,可以自己定义
    JENKINS_HOME="/var/lib/jenkins" 
    JENKINS_USER="root" 
    
    vim /etc/init.d/jenkins
    candidates="
    /data/jdk1.8.0_152/bin/java
    "
    
  4. 修改安装插件源

    cd  ./jenkins/updates/
    sed -i 's/https:\/\/updates.jenkins.io\/download/https:\/\/mirrors.tuna.tsinghua.edu.cn\/jenkins/g' default.json
    sed -i 's/http:\/\/www.google.com/https:\/\/www.baidu.com/g' default.json
    
  5. 启动

    systemctl daemon-reload
    systemctl start jenkins.service
    systemctl restart jenkins.service
    
  6. 访问 Jenkins 并安装相关控件

    http://192.168.66.40:8888
    #查看初始化密码:cat /var/lib/jenkins/secrets/initialAdminPassword 
    f00b76dece1d416ba50346f21cf937d9
    
  7. 安装插件

    选择不需要默认任何插件
    创建管理员用户:admin 密码: 123456 全名: admin到些 jenkins 安装成功。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    把官方下载列表加载到本地
    在这里插入图片描述

    进入插件列表并修改加载源

    cd /var/lib/jenkins/updates
    sed -i 's/http:\/\/updates.jenkinsci.org\/download/https:\/\/mirrors.tuna.tsinghua.edu.cn\/jenkins/g' 		default.json
    sed -i 's/http:\/\/www.google.com/https:\/\/www.baidu.com/g' default.json
    
    https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json
    

    重启Jenkins

    http://192.168.66.101:8888/restart
    

    下载中文汉化插件
    在这里插入图片描述

新增从节点

  1. 开启代理程序的TCP端口

    Manage Jenkins -> Configure Global Security
    在这里插入图片描述

  2. 新建节点

    Manage Jenkins—Manage Nodes—新建节点
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  3. 安装和配置节点

    下载agent.jar,并上传到Slave节点,然后执行页面提示的命令:

    java -jar agent.jar -jnlpUrl http://192.168.66.101:8888/computer/slave1/slave- agent.jnlp -secret f2ecbb99e0c81331e8b7a7917a94d478f39cb9763fc6c66d9a9741c61f9ae6d6 -workDir "/root/jenkins"
    

    刷新页面
    在这里插入图片描述

  4. 测试节点是否可用

    自由风格和Maven风格的项目:
    在这里插入图片描述

安装常用插件:

  1. 管理Jenkins用户权限Role-based Authorization Strategy

    在这里插入图片描述

    开启权限全局安全配置
    在这里插入图片描述
    在这里插入图片描述

    创建角色
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    Global roles(全局角色)、Item roles(项目角色)、Node roles(节点角色)

  2. 凭证管理Jenkins-Credentials Binding

    凭据可以用来存储需要密文保护的数据库密码、Gitlab密码信息、Docker私有 仓库密码等,以便Jenkins可以和这些第三方的应用进行交互
    在这里插入图片描述在这里插入图片描述

    Username with password:用户名和密码
    SSH Username with private key:使用ssh用户和密钥
    Secret file:需要保密的文件文件
    Secret text:需要保存的一个加密文本串
    Certficate:通过上传证书文本方式

  3. 安装Git插件和Git工具

    为了让Jenkins支持从Gitlab拉取源码,需要安装Git插件以及在CentOS7上 安装Git工具。
    在这里插入图片描述

    CentOS7上安装Git工具:

    yum install git -y 安装
    git --version 安装后查看版本
    
  4. 安装Maven来编译和打包项目

    Maven项目构建安装Maven Integration插件
    在这里插入图片描述

    安装Maven

    tar -xzf apache-maven-3.6.2-bin.tar.gz -C /data/
    mv apache-maven-3.6.2/* /data/maven
    创建本地仓库目录
    mkdir /data/maven/repo 
    vi /data/mavenconf/settings.xml
    

    在这里插入图片描述

    添加阿里云私服地址:
    在这里插入图片描述

    配置环境变量

    vim /etc/profile
    export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk export 	MAVEN_HOME=/opt/maven export 	PATH=$PATH:$JAVA_HOME/bin:$MAVEN_HOME/bin
    source /etc/profile
    

    查找Maven版本

    mvn -v 
    
  5. 全局工具配置关联JDK和Maven

    Jenkins->Global Tool Configuration->JDK->新增JDK
    在这里插入图片描述

    Jenkins->Global Tool Configuration->Maven->新增Maven
    在这里插入图片描述

    添加Jenkins全局变量
    Manage Jenkins->Configure System->Global Properties
    在这里插入图片描述

    测试Maven是否配置成功
    在这里插入图片描述

    构建->增加构建步骤->Execute Shell
    在这里插入图片描述
    在这里插入图片描述

    再次构建,如果可以把项目打成war包,代表maven环境配置成功啦
    在这里插入图片描述

  6. Jenkins远程部署到Tomcat的功能Deploy to container

    在这里插入图片描述

  7. 流水线项目构建安装插件pipeline

    Pipeline,一套运行在Jenkins上的工作流框架,将原来独立运行于单个或者多个节点的 任务连接起来,实现单个任务难以完成的复杂流程编排和可视化的工作

    在这里插入图片描述

  8. 邮箱服务器发送构建结果

    Email Extension插件
    在这里插入图片描述

    设置邮箱相关参数
    Manage Jenkins->Configure System
    在这里插入图片描述
    在这里插入图片描述

    设置Jenkins默认邮箱信息
    在这里插入图片描述

  9. 代码审查安装SonarQube

    SonarQube是一个用于管理代码质量的开放平台,可以快速的定位代码中潜在的或者明显的错误。目前支持java,C#,C/C++,Python,PL/SQL,Cobol,JavaScrip,Groovy等二十几种编程语言的代码质量管理与检测。

    物理机安装安装SonarQube

    #创建对应数据库
    #建用户
    CREATE USER 'sonar'@'%' IDENTIFIED BY 'sonar';
    #新建库
    CREATE DATABASE `sonar`CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
    #用户授权
    GRANT ALL PRIVILEGES ON sonar.* TO 'sonar'@'%';
    
    #安装
    unzip -o -d /data/ sonarqube-6.7.4.zip
    mv sonarqube-6.7.4/* /opt/sonarqube
    #创建sonar用户,必须sonar用于启动,否则报错
    useradd sonar
    chown -R sonar. /data/sonarqube
    

    修改sonar配置文件

    vi /data/sonarqube/conf/sonar.properties
    sonar.jdbc.username=sonar
    sonar.jdbc.password=sonar
    sonar.jdbc.url=jdbc:mysql://localhost:3306/sonar
    #注意:sonar默认监听9000端口,如果9000端口被占用,需要更改。
    

    启动sonar

    cd /opt/sonarqube
    启动
    su sonar ./bin/linux-x86-64/sonar.sh start 
    停止
    su sonar ./bin/linux-x86-64/sonar.sh stop 
    查看状态
    su sonar ./bin/linux-x86-64/sonar.sh status 
    tail -f logs/sonar.logs 查看日志
    

    访问sonar、默认账户:admin/admin
    http://192.168.66.101:9000

    创建token
    在这里插入图片描述
    #token要记下来后面要使用

    SonaQube关闭审查结果上传到SCM功能
    在这里插入图片描述

    jenkins安装SonarQube Scanner插件并添加凭证
    在这里插入图片描述

    凭据配置添加凭证
    在这里插入图片描述在这里插入图片描述

    Jenkins进行SonarQube配置
    Manage Jenkins->Configure System->SonarQube servers
    在这里插入图片描述

    Manage Jenkins->Global Tool Configuration

    在这里插入图片描述

  10. Publish Over SSH 插件,实现远程发送Shell命令
    在这里插入图片描述

    配置远程部署服务器

    拷贝公钥到远程服务器

    ssh-copy-id 192.168.66.103
    

    系统配置->添加远程服务器
    在这里插入图片描述

  11. NodeJS插件

    在这里插入图片描述

    Jenkins配置Nginx服务器
    Manage Jenkins->Global Tool Configuration
    在这里插入图片描述

  12. Extended Choice Parameter插件支持多选框

    在这里插入图片描述

  13. 安装插件kubernetes

    用于动态创建代理
    在这里插入图片描述

  14. 安装插件BlueOcean

    Jenkins团队从用户体验角度出发,专为Jenkins Pipeline重新设计的一套 UI 界面,仍 然兼容以前的 fressstyle类型的job,

    BlueOcean 具有以下的一些特性:
    连续交付(CD)Pipeline 的复杂可视化,允许快速直观的了解 Pipeline 的状态
    可以通过 Pipeline 编辑器直观的创建 Pipeline
    需要干预或者出现问题时快速定位,BlueOcean 显示了 Pipeline 需要注意的地方, 便于异常处理和提高生产力
    用于分支和拉取请求的本地集成可以在 GitHub 或者 Bitbucket 中与其他人进行 代码协作时最大限度提高开发人员的生产力。
    在这里插入图片描述

使用

管理用户权限插件:Role-based Authorization Strategy

  1. 创建用户

    在这里插入图片描述

  2. 给用户分配角色

    进入Mannage and Assign->Assign Roles
    在这里插入图片描述

  3. 创建项目测试权限

    以itcast管理员账户创建两个项目,分别为itcast01和itheima01
    结果为:
    在这里插入图片描述

    eric用户登录,只能看到itcast01项目
    jack用户登录,只能看到itheima01项目

Jenkins凭证管理

凭据可以用来存储需要密文保护的数据库密码、Gitlab密码信息、Docker私有仓库密码 等,以便Jenkins可以和这些第三方的应用进行交互

  1. 创建凭证

    Jenkins->凭证->系统->全局凭证->添加凭证
    在这里插入图片描述

  2. 普通类型

    在这里插入图片描述

  3. SSH密钥类型

    #使用root用户生成公钥和私钥
    ssh-keygen -t rsa
    #在/root/.ssh/目录保存了公钥和使用
    id_rsa:私钥文件
    id_rsa.pub:公钥文件
    

    把生成的公钥放在Gitlab中
    root账户登录->点击头像->Settings->SSH Keys
    复制刚才id_rsa.pub文件的内容到这里,点击"Add Key"
    在这里插入图片描述

    在Jenkins中添加凭证,配置私钥
    在Jenkins添加一个新的凭证,类型为"SSH Username with private key",把 刚才生成私有文件内容复制过来
    在这里插入图片描述

  4. 测试凭证是否可用

    创建一个FreeStyle项目:新建Item->FreeStyle Project->确定
    在这里插入图片描述

    找到"源码管理"->“Git”,在Repository URL复制Gitlab中的项目URL
    在这里插入图片描述在这里插入图片描述

    在这里插入图片描述

    点击构建”Build Now“ 开始构建项目
    在这里插入图片描述
    在这里插入图片描述

    查看/var/lib/jenkins/workspace/目录,成功拉取了代码到Jenkins中

构建项目

自由风格软件项目(FreeStyle Project)

拉取代码->编译->打包->部署

  1. 拉取代码

    1)创建项目
    在这里插入图片描述

    2)配置源码管理,从gitlab拉取代码
    在这里插入图片描述

  2. 编译打包

    构建->添加构建步骤->Executor Shell

    echo "开始编译和打包"
    mvn clean package
    echo "编译和打包结束"
    
  3. 部署

    把项目部署到远程的Tomcat里面
    1)安装 Deploy to container插件
    Jenkins本身无法实现远程部署到Tomcat的功能,
    需要安装Deploy to container插件实现
    在这里插入图片描述

    2)添加Tomcat用户凭证
    在这里插入图片描述

    3)添加构建后操作
    在这里插入图片描述
    在这里插入图片描述

    点击"Build Now",开始构建过程

    4)部署成功后,访问项目

Maven项目(Maven Project)
1)安装Maven Integration插件
2)创建Maven项目
在这里插入图片描述

3)配置项目
拉取代码和远程部署的过程和自由风格项目一样,只是"构建"部分不同
在这里插入图片描述

4)添加Tomcat用户凭证
在这里插入图片描述

5)添加构建后操作
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

点击"Build Now",开始构建过程
6)部署成功后,访问项目

流水线项目(Pipeline Project)
Pipeline,一套运行在Jenkins上的工作流框架,将原来独立运行于单个或者多个节点的 任务连接起来,实现单个任务难以完成的复杂流程编排和可视化的工作

  1. 语法使用

    1)声明式Declarative
    在这里插入图片描述

    pipeline {
    agent any
    #代表整个流水线的所有执行阶段,一般只有一个
    stages {
    #某个阶段,可能出现n个,一般分为拉取代码,编译构建,部署等阶段
    stage('拉取代码') {
    #阶段内需要执行的逻辑。steps里面是shell脚本,git拉取代码,ssh远程发布等
    steps {
    checkout([$class: 'GitSCM', branches: [[name: '*/master']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: '68f2087f-a034-4d39-a9ff-1f776dd3dfa8', url: 'git@192.168.66.100:itheima_group/web_demo.git']]])
    }
    }
    stage('编译构建') {
    steps {
    sh label: '', script: 'mvn clean package'
    }
    }
    stage('项目部署') {
    steps {
    deploy adapters: [tomcat8(credentialsId: 'afc43e5e-4a4e-4de6-984f- b1d5a254e434', path: '', url: 'http://192.168.66.102:8080')], contextPath: null, war: 'target/*.war'
    }
    }
    }
    }
    

    2)脚本式Scripted Pipeline
    在这里插入图片描述

    #一个Node就是一个 Jenkins 节点,Master 或者 Agent,是执行 Step 的具体运行环境
    node {
    def mvnHome
    #每个 Stage 代表一组操作
    stage('Preparation') {
    }
    stage('Build') {
    }
    stage('Results') { 
    }
    }
    
  2. 安装Pipeline插件

  3. 创建项目

    在这里插入图片描述

  4. 在代码中引用该文件或者用web界面操作写入

    在这里插入图片描述

构建触发器

触发远程构建

  1. 通过远程地址触发

    在这里插入图片描述

    触发构建url:http://192.168.66.101:8888/job/web_demo_pipeline/build?token=6666

其他工程构建后触发

  1. 创建pre_job流水线工程

    在这里插入图片描述

  2. 配置需要触发的工程

    在这里插入图片描述

定时构建
在这里插入图片描述

定时字符串从左往右分别为: 分 时 日 月 周
#一些定时表达式的例子:
每30分钟构建一次:H代表形参 H/30 * * * * 10:02 10:32
每2个小时构建一次: H H/2 * * *
每天的8点,12点,22点:0 8,12,22 * * *
每天中午12点定时构建一次 H 12 * * *
每天下午18点定时构建一次 H 18 * * *
在每个小时的前半个小时内的每10分钟 H(0-29)/10 * * * *
轮询SCM
轮询SCM,是指定时扫描本地代码仓库的代码是否有变更,如果代码有变更就触发项目构建。
注意:这次构建触发器,Jenkins会定时扫描本地整个项目的代码,增大系统的开销,不建议使用。
在这里插入图片描述

参数化构建
有时在项目构建的过程中,我们需要根据用户的输入动态传入一些参数,从而影响 整个构建结果,这时我们可以使用参数化构建
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

多选框
字符串参数:分支名称
在这里插入图片描述

多选框:项目名称

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述在这里插入图片描述

最后效果:
在这里插入图片描述

代码审查安装SonarQube

SonarQube是一个用于管理代码质量的开放平台,可以快速的定位代码中潜在的或者明显的错误。目前支持java,C#,C/C++,Python,PL/SQL,Cobol,JavaScrip,Groovy等二十几种编程语言的代码质量管理与检测。
(非流水线项目)在项目添加SonaQube代码审查

  1. 添加构建步骤:

    #在给定的SonarQube实例中必须是唯一的
    sonar.projectKey=web_demo_cxk
    sonar.projectName=web_demo_cxk
    sonar.projectVersion=1.0 
    #审查代码项目/下面那些目录当前
    sonar.sources=. 
    #在上面审查的目录下排除那些目录
    sonar.exclusions=**/test/**,**/target/** 
    sonar.java.source=1.8 
    sonar.java.target=1.8 
    sonar.sourceEncoding=UTF-8
    

    (流水线项目)在项目添加SonaQube代码审查
    项目根目录下,创建sonar-project.properties文件
    在这里插入图片描述

    #在给定的SonarQube实例中必须是唯一的
    sonar.projectKey=web_demo_cxk
    sonar.projectName=web_demo_cxk
    sonar.projectVersion=1.0 
    #审查代码项目/下面那些目录当前
    sonar.sources=. 
    #在上面审查的目录下排除那些目录
    sonar.exclusions=**/test/**,**/target/** 
    sonar.java.source=1.8 
    sonar.java.target=1.8 
    sonar.sourceEncoding=UTF-8
    

    修改Jenkinsfile,加入SonarQube代码审查阶段

    pipeline { 
    agent any 
    stages { 
    stage('拉取代码') { 
    steps { 
    checkout([$class: 'GitSCM', branches: [[name: '*/master']], 
    doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], 
    userRemoteConfigs: [[credentialsId: '68f2087f-a034-4d39-a9ff-1f776dd3dfa8', url: 
    'git@192.168.66.100:itheima_group/web_demo.git']]]) 
    } 
    }
    stage('编译构建') { 
    steps { 
    sh label: '', script: 'mvn clean package' 
    } 
    }
    stage('SonarQube代码审查') { 
    steps{ 
    script { 
    scannerHome = tool 'sonarqube-scanner' 
    }
    withSonarQubeEnv('sonarqube6.7.4') { 
    sh """ 
    cd ${project_name} 	${scannerHome}/bin/sonar-scanner
    """
    } 
    } 
    }
    stage('项目部署') { 
    steps { 
    deploy adapters: [tomcat8(credentialsId: 'afc43e5e-4a4e-4de6-984f- 
    b1d5a254e434', path: '', url: 'http://192.168.66.102:8080')], contextPath: null, 
    war: 'target/*.war' 
    } 
    } 
    }
    post { 
    always { 
    emailext( 
    subject: '构建通知:${PROJECT_NAME} - Build # ${BUILD_NUMBER} - 
    ${BUILD_STATUS}!', 
    body: '${FILE,path="email.html"}', 
    to: '1014671449@qq.com' 
    ) 
    } 
    } 
    } 
    

    构建后到SonarQube的UI界面查看审查结果
    在这里插入图片描述

邮箱服务器发送构建结果

  1. 安装插件Email Extension插件

  2. 设置邮箱相关参数

  3. 准备邮件内容

    在项目根目录编写email.html,并把文件推送到

    Gitlab,内容如下:
    <!DOCTYPE html> 
    <html> 
    <head>
    <meta charset="UTF-8"> 
    <title>${ENV, var="JOB_NAME"}-第${BUILD_NUMBER}次构建日志</title> 
    </head> 
    <body leftmargin="8" marginwidth="0" topmargin="8" marginheight="4" 
    offset="0"> 
    <table width="95%" cellpadding="0" cellspacing="0" 
    style="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, sans- 
    serif"> 
    <tr>
    <td>(本邮件是程序自动下发的,请勿回复!)</td> 
    </tr> 
    <tr>
    <td><h2> 
    <font color="#0000FF">构建结果 - ${BUILD_STATUS}</font> 
    </h2></td> 
    </tr> 
    <tr>
    <td><br /> 
    <b><font color="#0B610B">构建信息</font></b> 
    <hr size="2" width="100%" align="center" /></td> 
    </tr> 
    <tr>
    <td>
    <ul>
    <li>项目名称 : ${PROJECT_NAME}</li> 
    <li>构建编号 : 第${BUILD_NUMBER}次构建</li> 
    <li>触发原因: ${CAUSE}</li> 
    <li>构建日志: <a 
    href="${BUILD_URL}console">${BUILD_URL}console</a></li> 
    <li>构建  Url : <a 
    href="${BUILD_URL}">${BUILD_URL}</a></li> 
    <li>工作目录 : <a 
    href="${PROJECT_URL}ws">${PROJECT_URL}ws</a></li> 
    <li>项目  Url : <a 
    href="${PROJECT_URL}">${PROJECT_URL}</a></li> 
    </ul> 
    </td> 
    </tr> 
    <tr>
    <td><b><font color="#0B610B">Changes Since Last 
    Successful Build:</font></b> 
    <hr size="2" width="100%" align="center" /></td> 
    </tr>
    <tr>
    <td>
    <ul>
    <li>历史变更记录 : <a 
    href="${PROJECT_URL}changes">${PROJECT_URL}changes</a></li> 
    </ul> ${CHANGES_SINCE_LAST_SUCCESS,reverse=true, format="Changes for 
    Build #%n:<br />%c<br />",showPaths=true,changesFormat="<pre>[%a]<br 
    />%m</pre>",pathFormat="    %p"} 
    </td> 
    </tr> 
    <tr>
    <td><b>Failed Test Results</b> 
    <hr size="2" width="100%" align="center" /></td> 
    </tr> 
    <tr>
    <td><pre
    style="font-size: 11pt; font-family: Tahoma, Arial, Helvetica, 
    sans-serif">$FAILED_TESTS</pre> 
    <br /></td> 
    </tr> 
    <tr>
    <td><b><font color="#0B610B">构建日志 (最后 100行):</font></b> 
    <hr size="2" width="100%" align="center" /></td> 
    </tr> 
    <tr>
    <td><textarea cols="80" rows="30" readonly="readonly" 
    style="font-family: Courier New">${BUILD_LOG, 
    maxLines=100}</textarea> 
    </td> 
    </tr> 
    </table> 
    </body> 
    </html>
    

    编写Jenkinsfile添加构建后发送邮件

    pipeline { 
    agent any
    stages { 
    stage('拉取代码') {
    steps { 
    checkout([$class: 'GitSCM', branches: [[name: '*/master']], 
    doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], 
    userRemoteConfigs: [[credentialsId: '68f2087f-a034-4d39-a9ff-1f776dd3dfa8', url: 
    'git@192.168.66.100:itheima_group/web_demo.git']]]) 
    } 
    }
    stage('编译构建') { 
    steps { 
    sh label: '', script: 'mvn clean package' 
    } 
    }
    stage('项目部署') { 
    steps { 
    deploy adapters: [tomcat8(credentialsId: 'afc43e5e-4a4e-4de6-984f- 
    b1d5a254e434', path: '', url: 'http://192.168.66.102:8080')], contextPath: null, 
    war: 'target/*.war' 
    } 
    } 
    }
    post { 
    always { 
    emailext( 
    subject: '构建通知:${PROJECT_NAME} - Build # ${BUILD_NUMBER} - 
    ${BUILD_STATUS}!', 
    body: '${FILE,path="email.html"}', 
    to: 'xxx@qq.com' 
    ) 
    } 
    } 
    }
    
  4. 测试
    在这里插入图片描述

喜欢的亲可以关注点赞评论哦!以后每天都会更新的哦!本文为小编原创文章; 文章中用到的文件、安装包等可以加小编联系方式获得;
欢迎来交流小编联系方式VX:CXKLittleBrother 进入运维交流群

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

含义小哥

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

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

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

打赏作者

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

抵扣说明:

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

余额充值