CSDN副业图谱|10分钟用QClaw+Codex搞定毕设(iMind-信息系统思维导图台账管理系统)
本文介绍了一种高效的毕业设计方法:通过对比QClaw和Codex两个工具在相同提示词下的输出结果,快速搭建"iMind-信息系统思维导图台账管理系统"核心框架。该系统模拟企业真实运维场景,包含系统管理、服务器管理、数据管理和可视化功能。采用TypeScript+SQLite技术栈,10分钟内完成项目初始化、框架搭建和环境配置。文章详细展示了双工具对比的过程和效果图,并提供了完整
今天分享一个毕业设计设巧——同时用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存储,核心要求如下:
- 功能:实现系统分类分级台账管理,搭配思维导图可视化界面,支持展开/收缩、悬停查看详情、实时搜索、状态指示(在线/离线/维护),呈现系统→服务器→服务→端口的层级关系;
- 数据:包含系统、服务器、服务、人员相关数据,系统关联负责人、运维、开发人员,服务器关联系统及服务,服务包含端口、协议等信息;
- 项目结构:符合前端+后端一体化规范,包含组件、类型定义、数据、主应用等核心目录,适配npm运行命令;
- 基础配置:配置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的对比分析),贴合企业运维场景,同时体现技术能力,具体可分为以下几个部分:
-
绪论:结合企业运维痛点,说明系统分类分级台账+可视化思维导图的必要性(如企业大批量系统难以管理、资产信息混乱,可视化台账可提升运维效率),结合我的CTF竞赛经历和运维实战经验,说明项目的实战价值,补充QClaw与Codex双工具对比的核心思路;
-
需求分析:详细拆解前文的核心需求,补充需求分析图表(用Visio绘制),说明需求的合理性,可结合企业真实运维场景佐证,同时说明统一提示词的设计思路;
-
系统设计:基于整合后的项目框架,分析系统架构(前端+后端+数据库)、数据模型设计(对应SQLite的表结构)、可视化界面设计(对应思维导图组件),重点说明TypeScript+SQLite的选型原因,以及QClaw与Codex的对比分析、框架整合思路;
-
代码实现:将自行补充的完整代码呈现,补充代码注释说明,解释核心逻辑(如思维导图组件实现、数据库关联、搜索功能实现),插入预留的代码截图,体现代码规范和可扩展性;
-
系统测试:详细说明测试环境、测试用例,插入项目运行截图和功能测试截图,验证系统功能是否符合需求,说明测试结果;
-
总结与展望:总结项目实现的成果,分析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副业变现细节,欢迎关注,一起在技术变现的路上稳步前行!
更多推荐




所有评论(0)