Git版本管理工具使用知识汇总

Git版本管理工具使用知识汇总

版本管理在软件开发中是非常重要的,版本管理可以有效的降低代码版本丢失风险,极大的方便了软件开发中不同版本代码的管理。

本文内容包括:

  • 如何使用git工具
  • 规范化commit信息的格式
  • 使用commitlint验证commit信息的格式是否符合规范
  • 使用husky强制执行commit格式的规范化验证
  • 如何在代码提交前对代码格式验证
  • 最后封装成一键脚本自动化配置 commitizen

版本管理工具有很多:

  • svn :中心化在线版本管理控制工具,老旧的版本管理工具。
  • git :分布式版本控制工具,支持离线版本管理,目前主流的版本管理工具。

安装Git

Git网站

这里有不同平台的所有安装包,安装后你可以通过git命令或者GUI窗口进行版本管理。

了解Git命令

初学者对git版本管理有点迷糊,没关系,这里有个Git CheatSheet 帮你快速理解Git的工作原理及命令的作用。

访问 Git Cheat Sheet 学习一下Git命令用法。

在这里插入图片描述

规范化commit信息格式

由于commit 提交信息的作用是描述本次提交的改动信息及原因,可往往开发者处于懒惰而省略了很多描述信息,这将导致我们对git项目提交信息的管理变得困难,因此就产生了 commitizen 工具,帮我们规范化 代码提交信息。

提交信息可以告诉阅读这当前提交做了些什么变更,是代码修改了或者文档变更等等。这样,阅读这可以选择性的审阅代码内容。可以让提交信息更加有价值和实际的意义。

常规的commit的message格式规范化(主流Angular规范)如下:

<header>
<空行>
<body>
<空行>
<footer>

  • 目前很少用到,本用于更详细的说明每一个改动点,但对于每次只提交一小部分改动的变更,只需要填写subject概述信息就足够了。

  • 包含有关重大更改和弃用的信息,常规小改动很少用到。 若看到 **"BREAKING CHANGE: " ** 表示本次提交有重大改动,而 "DEPRECATED: " 则表示本次提交弃用了某些内容。

  • <header> 包含提交信息的概述,必填字段,此部分信息的常用Angular规范格式如下:

<type>(<scope>?): <subject>
  │       │             │
  │       │             └─⫸变更内容概述信息,英文不区分大小写,行末不能有句点(.)结束.
  │       │
  │       └─⫸ 提交范围,可选字段.
  │
  └─⫸ 提交类型(变更分类): build|ci|docs|feat|fix|perf|refactor|test
  

Type 字段取值含义:

  • feat : 新增加功能特性
  • fix : 修复bug
  • refactor: 一些代码结构上的优化,没有新特性和bug修复.
  • perf : 性能优化的代码改动
  • release: release版本提交
  • chore: 一些与主要业务无关的构建/工程依赖/工具等功能改动
  • ci : CI持续集成提交变更
  • docs: 文档更新
  • style: 码的样式美化,不涉及到功能修改等
  • test: 测试代码相关新增或变更

Scope字段为影响范围,很少用到,想了解可以去阅读Angular Commit Message Guidelines 详细相关说明。

Subject内容通常为提交内容的概述文本,用于说明本次提交做了哪些改动,以及改动原因或目标等。

到这里,我们基本了解了commit常用的规范化格式信息,当然Angular规范化格式只是比较流行的其中一种,还有些其他类似的格式,这里不再介绍。

开始安装commitizen规范化工具

每次都按照上面格式人工拼写难免会有出错的可能,所以下面就来介绍如何通过工具来辅助我们实现 规范化的commit文本提交。

安装 commitizen工具

npm安装方式有两种,本地安装和全局安装,个人比较推荐全局安装,养成一个好的版本提交规范化习惯很重要。

前提依赖:

全局安装方法:

npm install -g commitizen
或者
npm install --location=global commitizen

npm install -g cz-conventional-changelog

echo '{ "path": "cz-conventional-changelog" }' > ~/.czrc

本地安装方法:

npm install --save-dev commitizen

安装完毕后,使用conventional-changelog初始化项目,命令如下:

commitizen init cz-conventional-changelog --save-dev --save-exact

如果遇到错误,提示已经初始化过,可以使用--force参数强制重新初始化一次。

执行成功后,我们看到当前项目多了如下几个文件和目录:

node_modules  package.json  package-lock.json

其中 package.json 文件内容多了如下部分:

{
  "devDependencies": {
    "cz-conventional-changelog": "^3.3.0"
  },
  "config": {
    "commitizen": {
      "path": "./node_modules/cz-conventional-changelog"
    }
  }
}

到这里,我们就可以使用 git cz命令提交规范化文本信息了:

image-20220812212740915

对于英文不好的朋友,还可以使用git-cz替代commitizen, 应为 git-cz支持配置定制,我们可以配置后实现中文提示,效果如下:

image-20220812215618409

这样是不是很人性化呢? 具体使用可以直接访问Github项目地址 ,安装后,在项目根目录下添加如下文件即可达到效果:

// 文件名: changelog.config.js 
// 作用: commit 规范化配置
// 参考文档:https://github.com/streamich/git-cz

module.exports = {
  disableEmoji: true,
  // format: '{type}{scope}: {emoji}{subject}',
  list: ['test', 'feat', 'fix', 'chore', 'docs', 'refactor', 'style', 'ci', 'perf', 'build'],
  maxMessageLength: 72,
  minMessageLength: 3,
  questions: ['type', 'scope', 'subject', 'body', 'breaking', 'issues', 'lerna'],
  scopes: [],
  types: {
    chore: {
      description: '一些与主要业务无关的构建/工程依赖/工具等功能改动',
      emoji: '🤖',
      value: 'chore'
    },
    ci: {
      description: 'CI持续集成相关变更',
      emoji: '🎡',
      value: 'ci'
    },
    docs: {
      description: '文档更新(如:README)',
      emoji: '✏️',
      value: 'docs'
    },
    feat: {
      description: '新的特性',
      emoji: '🎸',
      value: 'feat'
    },
    fix: {
      description: 'BUG修复',
      emoji: '🐛',
      value: 'fix'
    },
    perf: {
      description: '优化了性能的代码改动',
      emoji: '⚡️',
      value: 'perf'
    },
    refactor: {
      description: '一些代码结构上优化,既不是新特性也不是修 Bug',
      emoji: '💡',
      value: 'refactor'
    },
    release: {
      description: '发布Release版本提交',
      emoji: '🏹',
      value: 'release'
    },
    style: {
      description: '代码的样式美化,不涉及到功能修改等',
      emoji: '💄',
      value: 'style'
    },
    test: {
      description: '新增或修改已有的测试代码',
      emoji: '💍',
      value: 'test'
    },
    build: {
      description: '影响构建系统或外部依赖项的更改(示例范围:gulp、broccoli、npm)',
      emoji: '💍',
      value: 'build'
    }
  }
};

安装commitlint验证commit信息是否规范化

规范化的commit格式只是防君子不防小人的约定,总会有人不遵守约定而胡乱提交信息,所以就出现了 commitlint工具来验证提交信息的格式是否合格。

首先说明的是,commitlint 是用于检验 git工具的commit 提交信息是否符合 规范的commit格式的工具。

全局安装命令如下:

npm install -g @commitlint/cli @commitlint/config-conventional

仅在当前项目安装方法如下:

npm install --save-dev @commitlint/config-conventional @commitlint/cli

安装后,我们需要新增加一个配置文件commitlint.config.js 设置 commit规范格式,在项目的根目录下新建一个 commitlint.config.js 文件,内容如下:

module.exports = {
    extends: ['@commitlint/config-conventional'],
    rules: {
        // level[0..2]: 0表示禁用规则,1为警告,2为错误
        // Appliable : always 适用此规则, never反转规则
        // Value 用于此规则的值
        'body-leading-blank': [2, 'always'], // body 开始于空白行
        'header-max-length': [2, 'always', 72], // header 字符最大长度为 72
        'subject-full-stop': [0, 'never'], // subject 结尾不加 '.'
        'type-empty': [2, 'never'], // type字段不可以为空
        'type-enum': [2, 'always', [
            'feat', // 新特性、需求
            'fix', // bug 修复
            'docs', // 文档内容改动
            'style', // 不影响代码含义的改动,例如去掉空格、改变缩进、增删分号
            'refactor', // 代码重构
            'test', // 添加或修改测试
            'chore', // 不修改 src 或者 test 的其余修改,例如构建过程或辅助工具的变动
            'revert', // 执行 git revert 打印的 message
            'build', // 影响构建系统或外部依赖项的更改(示例范围:gulp、broccoli、npm)
        ]],
    }
};

想了解更多commitlint配置规则请阅读 commitlint-规则参考, 这里有更全面的介绍 配置规则。

重点说明: 此时还无法自动化使用 commitlint 进行验证,还需要husky 添加一个 commit-msg的钩子,让git提交信息时自动触发 commitlint验证功能。接下来,我们就来了解一下如何配置 husky

使用husky强制使用规范提交

husky工具 可用于git的commit或push时对commit信息格式化验证自动测试以及代码格式化等等任何工作,husky支持git所有钩子。

  • 安装husky命令: npm install --save-dev husky
  • 激活钩子: npx husky install
  • 添加commitlint钩子: npx husky add .husky/commit-msg 'npx --no -- commitlint --edit $1'

验证commit信息是否符合规范化要求

首先,检验上次提交信息是否合格的命令:

$ npx commitlint --from HEAD~1 --to HEAD --verbose
⧗   input: docs: 文档变更
✔   found 0 problems, 0 warnings

接下来,我们来验证一下husky添加的钩子是否生效:

$ git commit -m "foo: this is a test"
⧗   input: foo: this is a testtype must be one of [feat, fix, docs, style, refactor, test, chore, revert, build] [type-enum]

✖   found 1 problems, 0 warnings
ⓘ   Get help: https://github.com/conventional-changelog/commitlint/#what-is-commitlint

husky - commit-msg hook exited with code 1 (error)

可以看到,钩子生效了,随便提交的文本信息就这样被拒绝了。

$ git cz
? Select the type of change that you're committing: chore:      一些与主要业务无关的构建/工程依赖/工具等功能改动
? Write a short, imperative mood description of the change: 
  [---------------------------------------------------------------------] 62 chars left
   chore: 更新了changelog.config.js与commitlint.config.js文件
? Provide a longer description of the change:
  
? List any breaking changes
  BREAKING CHANGE: 
? Issues this commit closes, e.g #123: 
[daily 12024a1] chore: 更新了changelog.config.js与commitlint.config.js文件
 2 files changed, 36 insertions(+), 27 deletions(-)
 rewrite commitlint.config.js (97%)
$ 

验证完毕,到这儿我们就完成了版本管理中commit信息规范化的配置工作。

最后

总结一下上面所用到的命令,为了方便以后新建项目可以自动执行命令完成配置工作,将上面命令封装为一个自动化配置脚本,脚本内容如下:

#!/usr/bin/env bash
#########################################################
# 功能:  自动化配置 git 规范化commit 脚本
# 作者: Awkee
# 日期: 2022-08-12
# 邮箱:  xiaoyu0720@gmail.com
#########################################################

pre_check() {
    #安装前检测是否已经安装了npm
    npm -v > /dev/null 2>&1
    if [ $? -ne 0 ]; then
        echo "npm is not installed, please install npm first"
        echo "install nodejs: https://nodejs.org/en/download/"
        exit 1
    fi
    ver=$(npm -v | cut -d. -f1)
    if [ $ver -lt 7 ]; then
        echo "npm version is less than 7, please upgrade npm first"
        echo "upgrade npm: npm install -g npm"
        exit 1
    fi
    git --version > /dev/null 2>&1
    if [ $? -ne 0 ]; then
        echo "git is not installed, please install git first"
        echo "install git: https://git-scm.com/downloads"
        exit 1
    fi
    user_name=$(git config --global user.name)
    if [ -z "$user_name" ]; then
        echo "git user.name is not set, please set it first"
        exit 1
    fi
    user_email=$(git config --global user.email)
    if [ -z "$user_email" ]; then
        echo "git user.email is not set, please set it first"
        exit 1
    fi
    
}


gen_changelog_config_file() {
    echo -n "Ly8g5paH5Lu25ZCNOiBjaGFuZ2Vsb2cuY29uZmlnLmpzIAovLyDkvZznlKg6IGNvbW1pdCDop4TojIPljJbphY3nva4KLy8g5Y+C6ICD5paH5qGj77yaaHR0cHM6Ly9naXRodWIuY29tL3N0cmVhbWljaC9naXQtY3oKCm1vZHVsZS5leHBvcnRzID0gewogIGRpc2FibGVFbW9qaTogdHJ1ZSwKICAvLyBmb3JtYXQ6ICd7dHlwZX17c2NvcGV9OiB7ZW1vaml9e3N1YmplY3R9JywKICBsaXN0OiBbJ3Rlc3QnLCAnZmVhdCcsICdmaXgnLCAnY2hvcmUnLCAnZG9jcycsICdyZWZhY3RvcicsICdzdHlsZScsICdjaScsICdwZXJmJywgJ2J1aWxkJ10sCiAgbWF4TWVzc2FnZUxlbmd0aDogNzIsCiAgbWluTWVzc2FnZUxlbmd0aDogMywKICBxdWVzdGlvbnM6IFsndHlwZScsICdzY29wZScsICdzdWJqZWN0JywgJ2JvZHknLCAnYnJlYWtpbmcnLCAnaXNzdWVzJywgJ2xlcm5hJ10sCiAgc2NvcGVzOiBbXSwKICB0eXBlczogewogICAgY2hvcmU6IHsKICAgICAgZGVzY3JpcHRpb246ICfkuIDkupvkuI7kuLvopoHkuJrliqHml6DlhbPnmoTmnoTlu7ov5bel56iL5L6d6LWWL+W3peWFt+etieWKn+iDveaUueWKqCcsCiAgICAgIGVtb2ppOiAn8J+klicsCiAgICAgIHZhbHVlOiAnY2hvcmUnCiAgICB9LAogICAgY2k6IHsKICAgICAgZGVzY3JpcHRpb246ICdDSeaMgee7rembhuaIkOebuOWFs+WPmOabtCcsCiAgICAgIGVtb2ppOiAn8J+OoScsCiAgICAgIHZhbHVlOiAnY2knCiAgICB9LAogICAgZG9jczogewogICAgICBkZXNjcmlwdGlvbjogJ+aWh+aho+abtOaWsCjlpoLvvJpSRUFETUUpJywKICAgICAgZW1vamk6ICfinI/vuI8nLAogICAgICB2YWx1ZTogJ2RvY3MnCiAgICB9LAogICAgZmVhdDogewogICAgICBkZXNjcmlwdGlvbjogJ+aWsOeahOeJueaApycsCiAgICAgIGVtb2ppOiAn8J+OuCcsCiAgICAgIHZhbHVlOiAnZmVhdCcKICAgIH0sCiAgICBmaXg6IHsKICAgICAgZGVzY3JpcHRpb246ICdCVUfkv67lpI0nLAogICAgICBlbW9qaTogJ/CfkJsnLAogICAgICB2YWx1ZTogJ2ZpeCcKICAgIH0sCiAgICBwZXJmOiB7CiAgICAgIGRlc2NyaXB0aW9uOiAn5LyY5YyW5LqG5oCn6IO955qE5Luj56CB5pS55YqoJywKICAgICAgZW1vamk6ICfimqHvuI8nLAogICAgICB2YWx1ZTogJ3BlcmYnCiAgICB9LAogICAgcmVmYWN0b3I6IHsKICAgICAgZGVzY3JpcHRpb246ICfkuIDkupvku6PnoIHnu5PmnoTkuIrkvJjljJbvvIzml6LkuI3mmK/mlrDnibnmgKfkuZ/kuI3mmK/kv64gQnVnJywKICAgICAgZW1vamk6ICfwn5KhJywKICAgICAgdmFsdWU6ICdyZWZhY3RvcicKICAgIH0sCiAgICByZWxlYXNlOiB7CiAgICAgIGRlc2NyaXB0aW9uOiAn5Y+R5biDUmVsZWFzZeeJiOacrOaPkOS6pCcsCiAgICAgIGVtb2ppOiAn8J+PuScsCiAgICAgIHZhbHVlOiAncmVsZWFzZScKICAgIH0sCiAgICBzdHlsZTogewogICAgICBkZXNjcmlwdGlvbjogJ+S7o+eggeeahOagt+W8j+e+juWMlu+8jOS4jea2ieWPiuWIsOWKn+iDveS/ruaUueetiScsCiAgICAgIGVtb2ppOiAn8J+ShCcsCiAgICAgIHZhbHVlOiAnc3R5bGUnCiAgICB9LAogICAgdGVzdDogewogICAgICBkZXNjcmlwdGlvbjogJ+aWsOWinuaIluS/ruaUueW3suacieeahOa1i+ivleS7o+eggScsCiAgICAgIGVtb2ppOiAn8J+SjScsCiAgICAgIHZhbHVlOiAndGVzdCcKICAgIH0sCiAgICBidWlsZDogewogICAgICBkZXNjcmlwdGlvbjogJ+W9seWTjeaehOW7uuezu+e7n+aIluWklumDqOS+nei1lumhueeahOabtOaUue+8iOekuuS+i+iMg+WbtO+8mmd1bHDjgIFicm9jY29saeOAgW5wbe+8iScsCiAgICAgIGVtb2ppOiAn8J+SjScsCiAgICAgIHZhbHVlOiAnYnVpbGQnCiAgICB9CiAgfQp9Owo=" | base64 -d
}

gen_commitlint_config_file() {
    echo -n "bW9kdWxlLmV4cG9ydHMgPSB7CiAgICBleHRlbmRzOiBbJ0Bjb21taXRsaW50L2NvbmZpZy1jb252ZW50aW9uYWwnXSwKICAgIHJ1bGVzOiB7CiAgICAgICAgLy8gbGV2ZWxbMC4uMl06IDDooajnpLrnpoHnlKjop4TliJnvvIwx5Li66K2m5ZGK77yMMuS4uumUmeivrwogICAgICAgIC8vIEFwcGxpYWJsZSA6IGFsd2F5cyDpgILnlKjmraTop4TliJnvvIwgbmV2ZXLlj43ovazop4TliJkKICAgICAgICAvLyBWYWx1ZSDnlKjkuo7mraTop4TliJnnmoTlgLwKICAgICAgICAnYm9keS1sZWFkaW5nLWJsYW5rJzogWzIsICdhbHdheXMnXSwgLy8gYm9keSDlvIDlp4vkuo7nqbrnmb3ooYwKICAgICAgICAnaGVhZGVyLW1heC1sZW5ndGgnOiBbMiwgJ2Fsd2F5cycsIDcyXSwgLy8gaGVhZGVyIOWtl+espuacgOWkp+mVv+W6puS4uiA3MgogICAgICAgICdzdWJqZWN0LWZ1bGwtc3RvcCc6IFswLCAnbmV2ZXInXSwgLy8gc3ViamVjdCDnu5PlsL7kuI3liqAgJy4nCiAgICAgICAgJ3R5cGUtZW1wdHknOiBbMiwgJ25ldmVyJ10sIC8vIHR5cGXlrZfmrrXkuI3lj6/ku6XkuLrnqboKICAgICAgICAndHlwZS1lbnVtJzogWzIsICdhbHdheXMnLCBbCiAgICAgICAgICAgICdmZWF0JywgLy8g5paw54m55oCn44CB6ZyA5rGCCiAgICAgICAgICAgICdmaXgnLCAvLyBidWcg5L+u5aSNCiAgICAgICAgICAgICdkb2NzJywgLy8g5paH5qGj5YaF5a655pS55YqoCiAgICAgICAgICAgICdzdHlsZScsIC8vIOS4jeW9seWTjeS7o+eggeWQq+S5ieeahOaUueWKqO+8jOS+i+WmguWOu+aOieepuuagvOOAgeaUueWPmOe8qei/m+OAgeWinuWIoOWIhuWPtwogICAgICAgICAgICAncmVmYWN0b3InLCAvLyDku6PnoIHph43mnoQKICAgICAgICAgICAgJ3Rlc3QnLCAvLyDmt7vliqDmiJbkv67mlLnmtYvor5UKICAgICAgICAgICAgJ2Nob3JlJywgLy8g5LiN5L+u5pS5IHNyYyDmiJbogIUgdGVzdCDnmoTlhbbkvZnkv67mlLnvvIzkvovlpoLmnoTlu7rov4fnqIvmiJbovoXliqnlt6XlhbfnmoTlj5jliqgKICAgICAgICAgICAgJ3JldmVydCcsIC8vIOaJp+ihjCBnaXQgcmV2ZXJ0IOaJk+WNsOeahCBtZXNzYWdlCiAgICAgICAgICAgICdidWlsZCcsIC8vIOW9seWTjeaehOW7uuezu+e7n+aIluWklumDqOS+nei1lumhueeahOabtOaUue+8iOekuuS+i+iMg+WbtO+8mmd1bHDjgIFicm9jY29saeOAgW5wbe+8iQogICAgICAgIF1dLAogICAgfQp9Owo="  | base64 -d
}

install_commitizen() {

    if which cz > /dev/null; then
        echo "commitizen 已经安装!"
        return 0
    fi
    echo "安装 commitizen ..."
    npm install -g commitizen
    echo "安装 commitizen 成功!"
}

install_cz_changelog() {
    if  grep "cz-conventional-changelog" "$HOME/.czrc" > /dev/null 2>&1 ; then
        echo "cz-conventional-changelog 已经安装!"
    else
        echo "安装 cz-conventional-changelog ..."
        npm install -g cz-conventional-changelog
        echo "安装 cz-conventional-changelog 成功!"
        echo "添加 cz-conventional-changelog 到 .czrc"
        mv $HOME/.czrc $HOME/.czrc.bak
        echo '{ "path": "cz-conventional-changelog" }' > "$HOME/.czrc"
        echo "添加 cz-conventional-changelog 到 .czrc 成功!"
    fi
}

install_commitlint() {
    if which commitlint > /dev/null 2>&1; then
        echo "commitlint 已经安装!"
    else
        echo "安装 commitlint ..."
        npm install -g @commitlint/{cli,config-conventional}
        echo "安装 commitlint 成功!"
    fi
}

config_cz() {

    install_commitizen
    install_cz_changelog
    install_commitlint

    echo "初始化 commitizen:"
    commitizen init cz-conventional-changelog --save-dev --save-exact --force

    echo "检测 .gitignore 中是否过滤掉了 node_modules目录"
    if grep "node_modules" "./.gitignore" > /dev/null 2>&1 ; then
        echo "node_modules is already in .gitignore"
    else
        echo "添加 node_modules 到 .gitignore"
        echo "node_modules" >> "./.gitignore"
    fi

    if [ -f "changelog.config.js" ] ; then
        echo "changelog.config.js 已存在"
    else
        echo "生成 changelog.config.js"
        gen_changelog_config_file > changelog.config.js
    fi

    if [ -f "./commitlint.config.js" ] ; then
        echo "commitlint.config.js 已存在"
    else
        echo "生成 commitlint.config.js"
        gen_commitlint_config_file > commitlint.config.js
    fi

    if  grep commitlint "./.husky/commit-msg" >/dev/null 2>&1 ; then
        echo "husky已经安装,commitlint已经配置"
    else
        echo "安装 husky:"
        npm install --save-dev husky
        echo "激活钩子:"
        npx husky install
        echo "添加 commitlint 钩子:"
        npx husky add .husky/commit-msg 'npx --no -- commitlint --edit $1'
    fi
    echo "配置完毕!"
    echo "请修改内容后执行 git cz 提交命令验证配置是否正确"
}

usage() {
    cat <<END
Usage:
    自动化配置 git commitlint 和 commitizen

    `basename $0` config

END
}

pre_check

case $1 in
    config)
        config_cz
        ;;
    *)
        usage
        ;;
esac

所有关于git的内容到此结束!


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

根叔的修行笔记

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

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

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

打赏作者

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

抵扣说明:

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

余额充值