OpenCode 实践课:4 分钟用 Node.js 写出一个命令行二维码生成器

项目介绍

今天我们用 OpenCode 来做一个命令行二维码生成器(qrmaker)。输入任意文本或 URL,一键生成 PNG/SVG 二维码文件,甚至可以直接在终端里显示二维码。

技术栈:Node.js + commander + qrcode,最终代码约 80 行。

准备工作

终端里进入项目目录,打开 OpenCode:

mkdir qrmaker && cd qrmaker
opencode

实践过程

第 1 步:初始化项目

我对 OpenCode 说:

> 帮我初始化一个 Node.js 项目,包名 qrmaker,入口 index.js,安装 commander 和 qrcode 两个依赖

OpenCode 自动执行:

npm init -y
npm install commander qrcode
npm install -g .

然后修改 package.json,添加 "bin": { "qrmaker": "./index.js" },并给入口文件加上 shebang #!/usr/bin/env node

要点:OpenCode 理解"初始化项目"这个模糊意图,自动补全了创建 bin 命令、修改 package.json 等细节步骤——这正是 AI 编程的便利之处。

第 2 步:实现核心功能

我对 OpenCode 说:

> 写一个命令行工具,接收一个必填的 text 参数作为二维码内容。使用 commander 做参数解析,qrcode 库生成 PNG 图片。默认输出文件为 qrcode.png,支持 -o 指定输出路径、-s 指定图片尺寸(默认 300px)。

OpenCode 直接生成完整代码,一次性可用:

#!/usr/bin/env node
const { Command } = require('commander');
const QRCode = require('qrcode');
const path = require('path');

const program = new Command();

program
  .name('qrmaker')
  .description('命令行二维码生成器')
  .argument('<text>', '要编码的文本或 URL')
  .option('-o, --output <file>', '输出文件路径', 'qrcode.png')
  .option('-s, --size <size>', '图片尺寸(像素)', '300')
  .parse();

const text = program.args[0];
const options = program.opts();

async function generate() {
  const outputPath = path.resolve(options.output);
  const size = parseInt(options.size);
  await QRCode.toFile(outputPath, text, { width: size, margin: 2 });
  console.log(`二维码已生成: ${outputPath} (${size}x${size})`);
}

generate().catch(err => {
  console.error('生成失败:', err.message);
  process.exit(1);
});

测试一下:

node index.js "https://opencode.ai"
# 二维码已生成: qrcode.png (300x300)

第 3 步:增加多样输出格式

我对 OpenCode 说:

> 增加 -f/--format 选项,支持 png(默认)、svg、dataurl 三种输出格式。svg 格式用 QRCode.toString 配合 writeFileSync 写入文件;dataurl 格式用 QRCode.toDataURL 写入文件。

OpenCode 补充了格式判断逻辑,同时为三种格式做了对应处理。我接着又说:

> 增加 -c/--color 和 -b/--bgcolor 选项,允许自定义二维码前景色和背景色,默认黑色前景白色背景。

第 4 步:终端直接显示

我对 OpenCode 说:

> 增加 -t/--terminal 选项,用 QRCode.toString 配合 type: 'terminal' 直接在终端打印二维码字符画,优先级高于文件输出。

OpenCode 添加了终端显示逻辑。现在在终端里也能看到二维码了——虽然只能扫小尺寸文本,但足够酷:

node index.js "hello" -t

第 5 步:收尾完善

我对 OpenCode 说:

> 增加 -l/--level 选项指定纠错级别(L/M/Q/H),默认 M。再添加 --version 显示版本号,完善帮助信息的描述文字。

OpenCode 补全了所有细节,还自动把纠错级别的字母映射为 qrcode 库需要的英文全称。最终运行 qrmaker --help 能看到完整的帮助信息。

完整代码

#!/usr/bin/env node
const { Command } = require('commander');
const QRCode = require('qrcode');
const path = require('path');
const fs = require('fs');

const program = new Command();

program
  .name('qrmaker')
  .description('命令行二维码生成器,支持 PNG/SVG/Terminal 输出')
  .argument('<text>', '要编码的文本或 URL')
  .option('-o, --output <file>', '输出文件路径', 'qrcode.png')
  .option('-s, --size <size>', '图片尺寸(像素)', '300')
  .option('-c, --color <color>', '二维码颜色', '#000000')
  .option('-b, --bgcolor <color>', '背景颜色', '#FFFFFF')
  .option('-t, --terminal', '在终端显示二维码')
  .option('-f, --format <type>', '输出格式: png, svg, dataurl', 'png')
  .option('-l, --level <level>', '纠错级别: L, M, Q, H', 'M')
  .version('1.0.0')
  .parse();

const text = program.args[0];
const options = program.opts();

const errorLevels = { L: 'low', M: 'medium', Q: 'quartile', H: 'high' };

async function generate() {
  const qrOptions = {
    errorCorrectionLevel: errorLevels[options.level] || 'M',
    margin: 2,
    color: { dark: options.color, light: options.bgcolor },
  };

  if (options.terminal) {
    console.log(await QRCode.toString(text, { type: 'terminal', small: true }));
    return;
  }

  const outputPath = path.resolve(options.output);
  const size = parseInt(options.size);

  switch (options.format.toLowerCase()) {
    case 'svg': {
      const svg = await QRCode.toString(text, { ...qrOptions, type: 'svg', width: size });
      fs.writeFileSync(outputPath, svg);
      break;
    }
    case 'dataurl': {
      const dataUrl = await QRCode.toDataURL(text, { ...qrOptions, width: size });
      fs.writeFileSync(outputPath, dataUrl);
      break;
    }
    default:
      await QRCode.toFile(outputPath, text, { ...qrOptions, width: size });
  }

  console.log(`二维码已生成: ${outputPath} (${size}x${size})`);
}

generate().catch(err => {
  console.error('生成失败:', err.message);
  process.exit(1);
});

小结

从零到可用的命令行工具,一共对 OpenCode 说了 5 句自然语言。整个过程不到 4 分钟——没有查文档、没有翻 npm 仓库、没有手写参数解析逻辑。

AI 编程不是替代开发者,而是让人从"怎么写"转向"做什么"。当你能用一句话描述需求、AI 能立刻给出可运行代码时,开发效率的提升是数量级的。

试试 OpenCode,把你的下一个想法在几分钟里变成可运行的工具。