今天分享一个毕业设计设巧——同时用QClaw和Codex接收相同提示词,对比两者完成情况,10分钟快速搭建「iMind-信息系统思维导图台账管理系统」核心框架,高效落地不踩坑!

毕设为程序员的入门实战,既是技术能力的体现,也是副业变现的“敲门砖”——本次设计的iMind-信息系统思维导图台账管理系统,正是企业运维中的高频需求,既贴合我的技术方向,也能直接作为接单、课程的实战案例,一举多得。

核心操作逻辑:给QClaw和Codex输入完全相同的需求提示词,对比两者在项目初始化、框架搭建上的完成效率与效果,最终结合两者优势完善项目,全程不超过10分钟。

先上部分效果图,后文中有详细的互动内容和效果图(如果后续大家有兴趣,可以评论或私信,我根据情况可以发布到GitHub中或私发给大家)

Codex效果在这里插入图片描述

Qclaw效果

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

一、毕设核心需求(企业真实场景复刻)

本次毕设模拟企业真实运维场景:公司需对大批量业务系统进行分类分级管理,整理实时、直观的资产台账,结合思维导图可视化呈现,核心需求如下,也是给QClaw和Codex输入的核心提示词基础:

**- 系统管理:**记录系统类型(如业务系统、监控系统、安全系统)、安全等级(一级/二级/三级),明确系统负责人、运维人员、开发人员信息;

**- 服务器管理:**关联系统与服务器,记录服务器IP、型号、放置地点、资产编号,抓取并维护服务器上运行的各类服务(如Web服务、数据库服务);

**- 数据管理:**实现后台管理页面,支持台账的新增、编辑、删除、查询,数据量不大,采用SQLite轻量存储,兼顾便捷性与稳定性;

**- 可视化需求:**搭建思维导图可视化界面,支持展开/收缩、悬停查看详情、实时搜索、状态指示等功能,呈现系统→服务器→服务→端口的层级关系;

- 技术栈:指定TypeScript开发,贴合前端+后端一体化实战需求,适配毕设查重要求,同时符合企业运维技术选型趋势。

二、实操:10分钟用QClaw+Codex(同提示词对比)搞定核心框架

很多同学做毕设卡在“代码落地”,要么无从下手,要么写得杂乱无章,本次采用双工具同步操作模式:给QClaw(代码生成工具)和Codex(AI编码助手)输入完全相同的需求提示词,对比两者在项目框架搭建、基础配置上的完成情况,无需手动编写基础代码,重点预留代码位置由我后续自行补充,既节省时间,又能通过对比体现技术思考,贴合毕设实战要求。

先说明工具核心用途:两者均接收相同需求提示词,QClaw侧重快速初始化项目结构、配置基础环境;Codex侧重生成核心功能框架,通过对比两者的输出结果,可快速筛选最优框架进行完善,搭配使用效率翻倍,10分钟就能完成项目核心框架搭建,亲测有效!

步骤1:2分钟统一编写需求提示词(同步输入QClaw和Codex)

编写统一的需求提示词,确保输入QClaw和Codex的内容完全一致,避免因提示词差异影响对比结果,核心提示词参考(可直接复制):

用TypeScript开发iMind-信息系统思维导图台账管理系统,基于SQLite存储,核心要求如下:

  1. 功能:实现系统分类分级台账管理,搭配思维导图可视化界面,支持展开/收缩、悬停查看详情、实时搜索、状态指示(在线/离线/维护),呈现系统→服务器→服务→端口的层级关系;
  2. 数据:包含系统、服务器、服务、人员相关数据,系统关联负责人、运维、开发人员,服务器关联系统及服务,服务包含端口、协议等信息;
  3. 项目结构:符合前端+后端一体化规范,包含组件、类型定义、数据、主应用等核心目录,适配npm运行命令;
  4. 基础配置:配置TypeScript环境,集成SQLite依赖,无需多余冗余代码,贴合毕设需求,搭建完整项目框架即可,无需编写具体业务逻辑代码。

提示词编写完成后,同时将其输入QClaw(CLI命令行调用)和Codex(VSCode插件调用),启动双工具同步运行,开始对比两者完成情况。

我们使用相同的提示词

Codex提问过程

在这里插入图片描述

Qclaw提问过程

在这里插入图片描述

步骤2:6分钟对比QClaw与Codex完成情况,筛选最优框架

双工具同步接收提示词后,分别完成基础框架搭建,重点对比以下3个核心维度,最终整合两者优势,形成项目最终框架:

  • 项目初始化效率:QClaw可通过1条命令快速生成完整项目目录,自动配置tsconfig.json、package.json及SQLite依赖,无需手动配置环境;Codex需手动创建项目目录,再逐步生成相关配置文件,效率略低于QClaw;

  • 框架完整性:QClaw生成的目录结构更规范,贴合TypeScript项目标准,包含核心组件、类型定义等目录;Codex生成的框架更侧重功能模块,可快速生成思维导图核心组件的基础结构,两者互补;

  • 适配性:两者生成的框架均贴合需求,但QClaw生成的框架可直接对接npm运行命令,Codex生成的组件结构更贴合思维导图可视化需求,整合后可快速搭建完整项目骨架。

对比完成后,整合QClaw的项目目录结构与Codex的组件基础结构,形成项目核心框架,此时框架搭建完成,全程耗时不超过6分钟。

步骤3:2分钟确认框架可用性,预留代码位置

整合框架后,执行相关命令启动项目,确认项目目录可正常运行、基础环境配置无误,无需编写具体业务代码,重点预留代码及项目相关位置,后续由我自行补充完整代码,至此,核心框架搭建完成,全程不超过10分钟!

三、iMind-信息系统思维导图系统具体设计(补充完整框架)

结合QClaw与Codex对比后的最优框架,补充iMind系统的完整设计详情,明确项目结构、特性、配色及数据结构,所有代码位置均预留,后续自行添加:

🧠 系统核心定位

一个现代时尚的信息系统可视化思维导图,依托TypeScript+SQLite开发,实现系统分类分级台账管理与可视化展示,支持展开/收缩、悬停查看详情等功能,贴合企业运维真实需求,适配毕设实战要求。

✨ 系统核心特性

  • 🎨 现代科技风格 - 深色主题 + 霓虹发光效果,贴合运维系统视觉需求;

  • 📊 层级清晰 - 严格遵循系统 → 服务器 → 服务 → 端口的层级逻辑,可视化呈现资产台账;

  • 🔍 实时搜索 - 支持按系统、服务器、服务名称搜索,高亮匹配节点,快速定位资产;

  • 💡 悬停详情 - 鼠标悬停节点,显示对应资产的详细信息卡片,无需跳转页面;

  • 📦 展开/折叠 - 点击节点即可控制子项显示/隐藏,便捷查看不同层级资产;

  • 🎯 状态指示 - 清晰标注系统、服务器、服务的在线/离线/维护状态,运维更直观。

🚀 系统运行命令

cd imind
npm install
npm run dev

📁 项目结构(整合QClaw与Codex优势,预留代码位置)

imind/
├── src/
│ ├── components/
│ │ ├── TreeVisualization.tsx # 思维导图核心组件【预留代码位置】
│ │ ├── DetailPanel.tsx # 详情面板【预留代码位置】
│ │ └── Toolbar.tsx # 工具栏(搜索、展开/折叠功能)【预留代码位置】
│ ├── types.ts # TypeScript类型定义【预留代码位置】
│ ├── data.ts # 示例数据(关联SQLite)【预留代码位置】
│ ├── App.tsx # 主应用(整合所有组件)【预留代码位置】
│ └── utils/
│ └── db.ts # SQLite数据库操作(CRUD)【预留代码位置】
├── prisma/
│ └── schema.prisma # SQLite数据模型【预留代码位置】
├── package.json # 项目依赖配置【预留代码位置】
└── README.md # 项目说明文档【预留代码位置】

🎨 系统配色方案

元素

颜色

根节点

#00d4ff 青色

系统

#10b981 绿色

服务器

#3b82f6 蓝色

服务

#f59e0b 橙色

📝 系统数据结构(贴合台账需求)

每个节点包含完整的资产信息,关联SQLite数据库,具体如下:

  • 系统:负责人、运维人员、上线时间、状态、描述、安全等级、系统类型;

  • 服务器:IP、地点、CPU、内存、磁盘、操作系统、资产编号、关联系统ID;

  • 服务:端口、协议、运行状态、关联服务器ID、服务版本。

Codex效果在这里插入图片描述

Qclaw效果

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

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

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
其中一个index.js

import express from 'express';
import cors from 'cors';
import initSqlJs from 'sql.js';
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
import { readFileSync, writeFileSync, existsSync } from 'fs';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

const app = express();
const PORT = 3001;
const DB_PATH = join(__dirname, 'imind.db');

// 中间件
app.use(cors());
app.use(express.json({ 
  reviver: (key, value) => {
    // 防止 details 被错误解析
    return value;
  }
}));

let db;

// 初始化数据库
async function initDb() {
  const SQL = await initSqlJs();
  
  // 尝试加载已有数据库
  if (existsSync(DB_PATH)) {
    const buffer = readFileSync(DB_PATH);
    db = new SQL.Database(buffer);
  } else {
    db = new SQL.Database();
  }

  // 创建表
  db.run(`
    -- 系统分类表
    CREATE TABLE IF NOT EXISTS system_category (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      name TEXT NOT NULL UNIQUE,
      color TEXT DEFAULT '#00d4ff',
      icon TEXT DEFAULT 'layers',
      sort_order INTEGER DEFAULT 0,
      created_at DATETIME DEFAULT CURRENT_TIMESTAMP
    )
  `);

  db.run(`
    -- 系统等级表
    CREATE TABLE IF NOT EXISTS system_level (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      name TEXT NOT NULL UNIQUE,
      level INTEGER NOT NULL UNIQUE,
      description TEXT,
      created_at DATETIME DEFAULT CURRENT_TIMESTAMP
    )
  `);

  db.run(`
    -- 系统信息表
    CREATE TABLE IF NOT EXISTS systems (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      name TEXT NOT NULL,
      category_id INTEGER,
      level_id INTEGER,
      parent_id INTEGER,
      owner_dept TEXT,
      owner TEXT,
      operator TEXT,
      developer TEXT,
      launch_date TEXT,
      status TEXT DEFAULT 'online',
      description TEXT,
      custom_fields TEXT,
      sort_order INTEGER DEFAULT 0,
      created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
      updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
    )
  `);

  db.run(`
    -- 服务器信息表
    CREATE TABLE IF NOT EXISTS servers (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      name TEXT NOT NULL,
      system_id INTEGER NOT NULL,
      ip TEXT,
      location TEXT,
      cpu TEXT,
      memory TEXT,
      disk TEXT,
      os TEXT,
      status TEXT DEFAULT 'online',
      description TEXT,
      custom_fields TEXT,
      sort_order INTEGER DEFAULT 0,
      created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
      updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
    )
  `);

  db.run(`
    -- 服务信息表
    CREATE TABLE IF NOT EXISTS services (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      name TEXT NOT NULL,
      server_id INTEGER NOT NULL,
      port INTEGER,
      protocol TEXT DEFAULT 'TCP',
      status TEXT DEFAULT 'running',
      description TEXT,
      custom_fields TEXT,
      created_at DATETIME DEFAULT CURRENT_TIMESTAMP
    )
  `);

  db.run(`
    -- 字段配置表
    CREATE TABLE IF NOT EXISTS field_configs (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      entity_type TEXT NOT NULL,
      key TEXT NOT NULL,
      label TEXT NOT NULL,
      type TEXT DEFAULT 'text',
      options TEXT,
      sort_order INTEGER DEFAULT 0,
      created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
      UNIQUE(entity_type, key)
    )
  `);

  // 初始化默认数据
  const catCount = db.exec('SELECT COUNT(*) FROM system_category')[0]?.values[0][0] || 0;
  if (catCount === 0) {
    db.run(`INSERT INTO system_category (name, color, sort_order) VALUES ('核心系统', '#ef4444', 1)`);
    db.run(`INSERT INTO system_category (name, color, sort_order) VALUES ('支撑系统', '#10b981', 2)`);
    
    db.run(`INSERT INTO system_level (name, level, description) VALUES ('一级系统', 1, '业务系统')`);
    db.run(`INSERT INTO system_level (name, level, description) VALUES ('二级系统', 2, '辅助系统')`);
    db.run(`INSERT INTO system_level (name, level, description) VALUES ('三级系统', 3, '子系统')`);
    
    saveDb();
  }

  console.log('Database initialized');
}

// 保存数据库到文件
function saveDb() {
  const data = db.export();
  const buffer = Buffer.from(data);
  writeFileSync(DB_PATH, buffer);
}

// Helper: 将结果转为对象数组
function resultToArray(result) {
  if (!result || result.length === 0) return [];
  const columns = result[0].columns;
  return result[0].values.map(row => {
    const obj = {};
    columns.forEach((col, i) => obj[col] = row[i]);
    return obj;
  });
}

// ============ 系统分类 API ============
app.get('/api/categories', (req, res) => {
  try {
    const result = db.exec('SELECT * FROM system_category ORDER BY sort_order');
    res.json(resultToArray(result));
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

app.post('/api/categories', (req, res) => {
  try {
    const { name, color, icon, sort_order } = req.body;
    db.run('INSERT INTO system_category (name, color, icon, sort_order) VALUES (?, ?, ?, ?)', [name, color, icon, sort_order]);
    const result = db.exec('SELECT last_insert_rowid() as id');
    const id = result[0].values[0][0];
    saveDb();
    res.json({ id, name, color, icon, sort_order });
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

app.put('/api/categories/:id', (req, res) => {
  try {
    const { id } = req.params;
    const { name, color, icon, sort_order } = req.body;
    db.run('UPDATE system_category SET name = ?, color = ?, icon = ?, sort_order = ? WHERE id = ?', [name, color, icon, sort_order, id]);
    saveDb();
    res.json({ id, name, color, icon, sort_order });
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

app.delete('/api/categories/:id', (req, res) => {
  try {
    const { id } = req.params;
    db.run('DELETE FROM system_category WHERE id = ?', [id]);
    saveDb();
    res.json({ success: true });
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

// ============ 系统等级 API ============
app.get('/api/levels', (req, res) => {
  try {
    const result = db.exec('SELECT * FROM system_level ORDER BY level');
    res.json(resultToArray(result));
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

app.post('/api/levels', (req, res) => {
  try {
    const { name, level, description } = req.body;
    db.run('INSERT INTO system_level (name, level, description) VALUES (?, ?, ?)', [name, level, description]);
    const result = db.exec('SELECT last_insert_rowid() as id');
    const id = result[0].values[0][0];
    saveDb();
    res.json({ id, name, level, description });
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

app.put('/api/levels/:id', (req, res) => {
  try {
    const { id } = req.params;
    const { name, level, description } = req.body;
    db.run('UPDATE system_level SET name = ?, level = ?, description = ? WHERE id = ?', [name, level, description, id]);
    saveDb();
    res.json({ id, name, level, description });
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

app.delete('/api/levels/:id', (req, res) => {
  try {
    const { id } = req.params;
    db.run('DELETE FROM system_level WHERE id = ?', [id]);
    saveDb();
    res.json({ success: true });
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

// ============ 系统信息 API ============
app.get('/api/systems', (req, res) => {
  try {
    const result = db.exec(`
      SELECT s.*, 
             c.name as category_name, c.color as category_color,
             l.name as level_name,
             p.name as parent_name
      FROM systems s
      LEFT JOIN system_category c ON s.category_id = c.id
      LEFT JOIN system_level l ON s.level_id = l.id
      LEFT JOIN systems p ON s.parent_id = p.id
      ORDER BY c.sort_order, s.sort_order
    `);
    res.json(resultToArray(result));
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

app.get('/api/systems/:id', (req, res) => {
  try {
    const result = db.exec(`
      SELECT s.*, 
             c.name as category_name, c.color as category_color,
             l.name as level_name,
             p.name as parent_name
      FROM systems s
      LEFT JOIN system_category c ON s.category_id = c.id
      LEFT JOIN system_level l ON s.level_id = l.id
      LEFT JOIN systems p ON s.parent_id = p.id
      WHERE s.id = ?
    `, [req.params.id]);
    const arr = resultToArray(result);
    res.json(arr[0] || null);
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

app.post('/api/systems', (req, res) => {
  try {
    const { name, category_id, level_id, parent_id, owner_dept, owner, operator, developer, launch_date, status, description, sort_order } = req.body;
    db.run(`
      INSERT INTO systems (name, category_id, level_id, parent_id, owner_dept, owner, operator, developer, launch_date, status, description, sort_order)
      VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
    `, [name, category_id, level_id, parent_id, owner_dept, owner, operator, developer, launch_date, status, description, sort_order]);
    const result = db.exec('SELECT last_insert_rowid() as id');
    const id = result[0].values[0][0];
    saveDb();
    res.json({ id, ...req.body });
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

app.put('/api/systems/:id', (req, res) => {
  try {
    const { id } = req.params;
    const { name, category_id, level_id, parent_id, owner_dept, owner, operator, developer, launch_date, status, description, sort_order } = req.body;
    db.run(`
      UPDATE systems SET 
        name = ?, category_id = ?, level_id = ?, parent_id = ?, 
        owner_dept = ?, owner = ?, operator = ?, developer = ?, 
        launch_date = ?, status = ?, description = ?, sort_order = ?,
        updated_at = datetime('now')
      WHERE id = ?
    `, [name, category_id, level_id, parent_id, owner_dept, owner, operator, developer, launch_date, status, description, sort_order, id]);
    saveDb();
    res.json({ id, ...req.body });
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

app.delete('/api/systems/:id', (req, res) => {
  try {
    const { id } = req.params;
    db.run('DELETE FROM systems WHERE id = ?', [id]);
    saveDb();
    res.json({ success: true });
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

// ============ 服务器 API ============
app.get('/api/servers', (req, res) => {
  try {
    const { system_id } = req.query;
    let result;
    if (system_id) {
      result = db.exec(`
        SELECT s.*, 
               sys.name as system_name, sys.category_id,
               c.name as category_name
        FROM servers s
        JOIN systems sys ON s.system_id = sys.id
        LEFT JOIN system_category c ON sys.category_id = c.id
        WHERE s.system_id = ?
        ORDER BY s.sort_order
      `, [system_id]);
    } else {
      result = db.exec(`
        SELECT s.*, 
               sys.name as system_name, sys.category_id,
               c.name as category_name
        FROM servers s
        JOIN systems sys ON s.system_id = sys.id
        LEFT JOIN system_category c ON sys.category_id = c.id
        ORDER BY c.sort_order, s.sort_order
      `);
    }
    res.json(resultToArray(result));
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

app.post('/api/servers', (req, res) => {
  try {
    const { name, system_id, ip, location, cpu, memory, disk, os, status, description, sort_order } = req.body;
    db.run(`
      INSERT INTO servers (name, system_id, ip, location, cpu, memory, disk, os, status, description, sort_order)
      VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
    `, [name, system_id, ip, location, cpu, memory, disk, os, status, description, sort_order]);
    const result = db.exec('SELECT last_insert_rowid() as id');
    const id = result[0].values[0][0];
    saveDb();
    res.json({ id, ...req.body });
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

app.put('/api/servers/:id', (req, res) => {
  try {
    const { id } = req.params;
    const { name, system_id, ip, location, cpu, memory, disk, os, status, description, sort_order } = req.body;
    db.run(`
      UPDATE servers SET 
        name = ?, system_id = ?, ip = ?, location = ?, 
        cpu = ?, memory = ?, disk = ?, os = ?, 
        status = ?, description = ?, sort_order = ?,
        updated_at = datetime('now')
      WHERE id = ?
    `, [name, system_id, ip, location, cpu, memory, disk, os, status, description, sort_order, id]);
    saveDb();
    res.json({ id, ...req.body });
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

app.delete('/api/servers/:id', (req, res) => {
  try {
    const { id } = req.params;
    db.run('DELETE FROM servers WHERE id = ?', [id]);
    saveDb();
    res.json({ success: true });
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

// ============ 服务 API ============
app.get('/api/services', (req, res) => {
  try {
    const { server_id } = req.query;
    let result;
    if (server_id) {
      result = db.exec(`
        SELECT svc.*, s.name as server_name, s.ip as server_ip, sys.name as system_name
        FROM services svc
        JOIN servers s ON svc.server_id = s.id
        JOIN systems sys ON s.system_id = sys.id
        WHERE svc.server_id = ?
        ORDER BY svc.port
      `, [server_id]);
    } else {
      result = db.exec(`
        SELECT svc.*, s.name as server_name, s.ip as server_ip, sys.name as system_name
        FROM services svc
        JOIN servers s ON svc.server_id = s.id
        JOIN systems sys ON s.system_id = sys.id
        ORDER BY svc.port
      `);
    }
    res.json(resultToArray(result));
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

app.post('/api/services', (req, res) => {
  try {
    const { name, server_id, port, protocol, status, description } = req.body;
    db.run(`
      INSERT INTO services (name, server_id, port, protocol, status, description)
      VALUES (?, ?, ?, ?, ?, ?)
    `, [name, server_id, port, protocol, status, description]);
    const result = db.exec('SELECT last_insert_rowid() as id');
    const id = result[0].values[0][0];
    saveDb();
    res.json({ id, ...req.body });
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

app.put('/api/services/:id', (req, res) => {
  try {
    const { id } = req.params;
    const { name, server_id, port, protocol, status, description } = req.body;
    db.run(`
      UPDATE services SET name = ?, server_id = ?, port = ?, protocol = ?, status = ?, description = ?
      WHERE id = ?
    `, [name, server_id, port, protocol, status, description, id]);
    saveDb();
    res.json({ id, ...req.body });
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

app.delete('/api/services/:id', (req, res) => {
  try {
    const { id } = req.params;
    db.run('DELETE FROM services WHERE id = ?', [id]);
    saveDb();
    res.json({ success: true });
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

// ============ 树形结构 API ============
app.get('/api/tree', (req, res) => {
  try {
    const categories = resultToArray(db.exec('SELECT * FROM system_category ORDER BY sort_order'));
    const levels = resultToArray(db.exec('SELECT * FROM system_level ORDER BY level'));
    const systems = resultToArray(db.exec('SELECT * FROM systems ORDER BY sort_order'));
    const servers = resultToArray(db.exec('SELECT * FROM servers ORDER BY sort_order'));
    const services = resultToArray(db.exec('SELECT * FROM services ORDER BY port'));

    // 构建树形结构
    const tree = {
      id: 'root',
      label: '艾莱依信息系统导图',
      type: 'root',
      color: '#00d4ff',
      expanded: true,
      children: categories.map(cat => ({
        id: `cat_${cat.id}`,
        label: cat.name,
        type: 'category',
        color: cat.color,
        expanded: true,
        children: levels.map(level => {
          const levelSystems = systems.filter(s => s.category_id == cat.id && s.level_id == level.id);
          if (levelSystems.length === 0) return null;
          
          return {
            id: `level_${cat.id}_${level.id}`,
            label: level.name,
            type: 'level',
            color: '#f59e0b',
            expanded: level.id === 1, // 一级系统默认展开
            children: levelSystems.map(sys => {
              const sysServers = servers.filter(s => s.system_id == sys.id);
              return {
                id: `sys_${sys.id}`,
                label: sys.name,
                type: 'system',
                color: '#3b82f6',
                details: {
                  name: sys.name,
                  owner_dept: sys.owner_dept,
                  owner: sys.owner,
                  operator: sys.operator,
                  developer: sys.developer,
                  launch_date: sys.launch_date,
                  status: sys.status,
                  description: sys.description,
                  ...(sys.custom_fields ? JSON.parse(sys.custom_fields) : {})
                },
                children: sysServers.length > 0 ? sysServers.map(srv => ({
                  id: `srv_${srv.id}`,
                  label: srv.name,
                  type: 'server',
                  color: srv.status === 'online' ? '#10b981' : '#ef4444',
                  details: {
                    name: srv.name,
                    ip: srv.ip,
                    location: srv.location,
                    cpu: srv.cpu,
                    memory: srv.memory,
                    disk: srv.disk,
                    os: srv.os,
                    status: srv.status,
                    description: srv.description,
                    ...(srv.custom_fields ? JSON.parse(srv.custom_fields) : {})
                  },
                  children: services.filter(svc => svc.server_id == srv.id).map(svc => ({
                    id: `svc_${svc.id}`,
                    label: `${svc.name} :${svc.port}`,
                    type: 'service',
                    color: svc.status === 'running' ? '#10b981' : '#ef4444',
                    details: {
                      name: svc.name,
                      port: svc.port,
                      protocol: svc.protocol,
                      status: svc.status,
                      description: svc.description
                    }
                  }))
                })) : undefined
              };
            })
          };
        }).filter(Boolean)
      }))
    };

    res.json(tree);
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

// ============ 字段配置 API ============
app.get('/api/field-configs', (req, res) => {
  try {
    const result = db.exec('SELECT * FROM field_configs ORDER BY entity_type, sort_order');
    const configs = resultToArray(result);
    
    // 按实体类型分组
    const grouped = { system: [], server: [], service: [] };
    configs.forEach(c => {
      if (grouped[c.entity_type]) {
        grouped[c.entity_type].push({
          ...c,
          options: c.options ? JSON.parse(c.options) : undefined
        });
      }
    });
    res.json(grouped);
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

app.get('/api/field-configs/:entityType', (req, res) => {
  try {
    const result = db.exec('SELECT * FROM field_configs WHERE entity_type = ? ORDER BY sort_order', [req.params.entityType]);
    const configs = resultToArray(result).map(c => ({
      ...c,
      options: c.options ? JSON.parse(c.options) : undefined
    }));
    res.json(configs);
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

app.post('/api/field-configs', (req, res) => {
  try {
    const { entity_type, key, label, type, options, sort_order } = req.body;
    db.run(`
      INSERT INTO field_configs (entity_type, key, label, type, options, sort_order)
      VALUES (?, ?, ?, ?, ?, ?)
    `, [entity_type, key, label, type, options ? JSON.stringify(options) : null, sort_order]);
    const result = db.exec('SELECT last_insert_rowid() as id');
    const id = result[0].values[0][0];
    saveDb();
    res.json({ id, entity_type, key, label, type, options, sort_order });
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

app.put('/api/field-configs/:id', (req, res) => {
  try {
    const { id } = req.params;
    const { entity_type, key, label, type, options, sort_order } = req.body;
    db.run(`
      UPDATE field_configs SET entity_type = ?, key = ?, label = ?, type = ?, options = ?, sort_order = ?
      WHERE id = ?
    `, [entity_type, key, label, type, options ? JSON.stringify(options) : null, sort_order, id]);
    saveDb();
    res.json({ id, entity_type, key, label, type, options, sort_order });
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

app.delete('/api/field-configs/:id', (req, res) => {
  try {
    const { id } = req.params;
    db.run('DELETE FROM field_configs WHERE id = ?', [id]);
    saveDb();
    res.json({ success: true });
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

// 启动服务器
initDb().then(() => {
  app.listen(PORT, () => {
    console.log(`Server running on http://localhost:${PORT}`);
  });
});

Qclaw的初始效果更好,因为后续通过Qclaw多次互动进行补充更加完善
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

四、毕设后续内容:跟着框架“填空”,高效完成论文

核心框架搭建完成、预留好所有代码位置后,毕设论文的大部分内容都可以围绕框架和系统设计展开,无需再绞尽脑汁凑字数,重点突出“实战性”和“技术思考”(如QClaw与Codex的对比分析),贴合企业运维场景,同时体现技术能力,具体可分为以下几个部分:

  1. 绪论:结合企业运维痛点,说明系统分类分级台账+可视化思维导图的必要性(如企业大批量系统难以管理、资产信息混乱,可视化台账可提升运维效率),结合我的CTF竞赛经历和运维实战经验,说明项目的实战价值,补充QClaw与Codex双工具对比的核心思路;

  2. 需求分析:详细拆解前文的核心需求,补充需求分析图表(用Visio绘制),说明需求的合理性,可结合企业真实运维场景佐证,同时说明统一提示词的设计思路;

  3. 系统设计:基于整合后的项目框架,分析系统架构(前端+后端+数据库)、数据模型设计(对应SQLite的表结构)、可视化界面设计(对应思维导图组件),重点说明TypeScript+SQLite的选型原因,以及QClaw与Codex的对比分析、框架整合思路;

  4. 代码实现:将自行补充的完整代码呈现,补充代码注释说明,解释核心逻辑(如思维导图组件实现、数据库关联、搜索功能实现),插入预留的代码截图,体现代码规范和可扩展性;

  5. 系统测试:详细说明测试环境、测试用例,插入项目运行截图和功能测试截图,验证系统功能是否符合需求,说明测试结果;

  6. 总结与展望:总结项目实现的成果,分析QClaw与Codex双工具使用的优势与不足,结合企业运维发展趋势(如云原生、自动化运维),提出系统可优化方向(如集成Prometheus监控、对接K8s集群),提升毕设的深度。

这里提醒一句:毕设的核心是“实战”,这款iMind系统不仅能完成毕设,还能作为我CSDN博客的实战案例,后续可延伸为接单项目、付费课程素材,完美对接副业变现。

五、CSDN创作者变现全链路(结合自身实战,真实可落地)

借着CSDN程序员副业图谱话题,结合我自身的运维与安全实战经验,和大家梳理最真实、可落地的创作者变现路径,核心是“技术为核,内容为桥”,从基础变现到IP延伸,逐步搭建自己的副业体系,这也是我分享毕设技巧的核心原因——毕设实战案例,正是副业变现的起点。

1. 基础变现:接单(快速变现,积累口碑)

作为运维与安全方向博主,接单的核心是“贴合自身技术栈”,这款iMind-信息系统思维导图台账管理系统,就是典型的企业运维接单需求(中小企业常用轻量可视化台账系统)。接单路径:在CSDN社区分享毕设实战案例(含QClaw与Codex对比技巧)→吸引有类似需求的企业/个人→对接需求,基于现有框架快速定制开发→交付验收,积累口碑。

重点:接单无需追求“大项目”,从中小项目入手,比如企业资产可视化台账、简单监控系统部署,用QClaw+Codex提升开发效率,缩短交付周期,同时依托自己的CTF竞赛经历和运维技术积累,建立信任,后续可承接更复杂的运维、安全相关项目。

2. 进阶变现:课程(体系化输出,被动收入)

将毕设实现过程、QClaw与Codex同提示词对比技巧、iMind系统开发实战,整理成体系化课程,比如《1小时搞定毕设(TypeScript+SQLite可视化实战)》《QClaw+Codex双工具对比,程序员高效编码指南》,发布在CSDN学院、掘金小册等平台。

课程核心优势:贴合毕设刚需,解决学生“代码落地难”“框架搭建无思路”的痛点,同时结合企业运维场景,兼顾实用性,适合学生和刚入行的运维工程师学习。课程收入属于被动收入,一旦上线,后续无需过多维护,持续产生收益,也是我目前重点布局的副业方向。

3. 高阶变现:咨询(发挥专业优势,高单价)

依托自身的企业级运维、数据库运维、网络安全实战经验,提供技术咨询服务,比如:毕设指导(针对计算机专业学生,提供框架搭建、代码优化、论文修改建议)、企业运维咨询(服务器部署、虚拟化配置、监控方案搭建)、CTF竞赛指导(结合自身竞赛佳绩,提供解题技巧)。

咨询变现的核心是“专业背书”,通过CSDN博客分享实战案例、技术干货,积累粉丝和口碑,逐步提升咨询单价,比如毕设指导单次200-500元,企业运维咨询单次1000+元,属于高单价、低投入的变现方式,也是技术博主的核心竞争力所在。

4. IP延伸:多元化变现,放大价值

当积累一定粉丝和口碑后,可延伸IP价值,实现多元化变现:比如将毕设系统、运维实战案例整理成付费文档,发布在CSDN资源区;搭建付费社群,提供技术答疑、接单对接、资源共享服务;与企业合作,提供定制化运维培训、安全检测服务;甚至出版运维相关书籍,进一步强化个人IP。

对我而言,聚焦“企业级运维与安全实战”这一细分领域,不追求广而全,而是做精做深,通过毕设案例、技术干货积累IP,再通过接单、课程、咨询、IP延伸,形成完整的变现闭环,这也是CSDN创作者最可持续的副业路径。

六、总结:毕设+副业,一举两得的程序员成长路径

很多程序员觉得毕设是“负担”,其实不然——一款贴合企业真实需求的毕设,不仅能顺利毕业,还能成为副业变现的“敲门砖”。用QClaw+Codex同步输入相同提示词、对比完成情况,快速搭建项目框架,预留好代码位置,后续自行补充完善,既节省时间,又能体现技术思考,让毕设更具亮点。

而CSDN创作者的变现,从来不是一蹴而就的,从接单积累口碑,到课程实现被动收入,再到咨询和IP延伸,每一步都需要依托自身的技术实力和持续的内容输出。作为聚焦运维与安全实战的博主,我始终相信:技术本身就是最好的“副业资本”,而毕设,正是将技术转化为收益的第一个节点。

后续我会持续分享毕设优化技巧、QClaw+Codex进阶用法、企业运维实战案例,同时拆解更多CSDN副业变现细节,欢迎关注,一起在技术变现的路上稳步前行!

Logo

小龙虾开发者社区是 CSDN 旗下专注 OpenClaw 生态的官方阵地,聚焦技能开发、插件实践与部署教程,为开发者提供可直接落地的方案、工具与交流平台,助力高效构建与落地 AI 应用

更多推荐