一键导入
simple-web-dev-guide
轻量级网站/应用开发指南。适用于搭建各类Web系统、数据分析报表、数据管理后台、数据增删改查功能。包含完整项目结构、前端HTML/JS/Vue、后端Python FastAPI+SQLite的开发指引与代码模板。
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
轻量级网站/应用开发指南。适用于搭建各类Web系统、数据分析报表、数据管理后台、数据增删改查功能。包含完整项目结构、前端HTML/JS/Vue、后端Python FastAPI+SQLite的开发指引与代码模板。
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
电商数据分析(商品/订单/用户三表分析)。当用户需要对商品表(products)、订单表(orders)、用户表(users)进行数据分析时触发此技能。支持根据用户问题动态生成分析脚本,涵盖:商品销售排行、库存预警、分类销售分析;用户消费排行、复购率、注册趋势;订单状态分布、销售额趋势、客单价分析;以及商品关联购买分析、用户品类偏好等交叉分析。输出包括:Markdown格式统计摘要。触发词包括:数据分析、电商分析、商品分析、订单分析、用户分析、销售分析、复购率、库存预警、商品排行、销售趋势、关联分析等。数据来源为PostgreSQL数据库,数据源地址通过动态变量从agent记忆中获取。
Sets up {module-name} module in a project. Use when the user requests to 'install {module-code} module', 'configure {module-name}', or 'setup {module-name}'.
Plans, creates, and validates BMad modules. Use when the user requests to 'ideate module', 'plan a module', 'create module', 'build a module', or 'validate module'.
Builds, converts, and analyzes workflows and skills. Use when the user requests to "build a workflow", "modify a workflow", "quality check workflow", "analyze skill", or "convert a skill".
当沙箱中有 Web 应用启动并有 URL 地址时自动打开沙箱浏览器。触发场景:检测到 Python Web 服务启动(uvicorn/fastapi/flask/streamlit/gradio/http.server 等)并生成了 URL;用户说'打开浏览器'/'访问这个地址'/'打开网页看看'/'打开链接'/'打开 VNC'等;需要让用户通过 VNC 查看 Web 界面时。核心动作:探测服务端口就绪 → 启动沙箱 chromium 浏览器 → 返回 VNC 访问链接给用户。
Podman 镜像构建与推送。包含 Dockerfile 编写、本地构建测试、推送到阿里云 ACR 个人版仓库。当用户需要制作 Dockerfile、打包镜像、推送镜像时使用此技能。
| name | simple-web-dev-guide |
| description | 轻量级网站/应用开发指南。适用于搭建各类Web系统、数据分析报表、数据管理后台、数据增删改查功能。包含完整项目结构、前端HTML/JS/Vue、后端Python FastAPI+SQLite的开发指引与代码模板。 |
⚠️ 强制约束:所有项目文件必须放在一个独立的文件夹目录下,避免与其他文件耦合。
my-project/ # 项目根目录(所有文件必须放在此目录下)
├── frontend/ # 前端文件
│ ├── index.html # 主页面
│ ├── css/ # 样式
│ ├── js/ # 脚本
│ └── assets/ # 静态资源
├── backend/ # 后端API
│ ├── main.py # FastAPI入口
│ ├── models.py # 数据模型
│ ├── database.py # SQLite连接
│ └── api/ # API路由
└── requirements.txt # Python依赖(可选)
目录约束说明:
my-project/)前端:
后端:
数据库:
项目文件直接本地管理,无需版本控制。
默认推荐风格:整体以白色为主色调,搭配简洁的灰色系文字,配合一两种鲜明的点缀色(如蓝色、绿色或橙色),打造清新、专业的视觉效果。
在开发前端 UI 界面时,必须参考 ./references/frontend-design.md 的设计理念,打造独特、高质量的用户界面:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>我的应用</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<div id="app">
<h1>欢迎</h1>
<button id="btn">点击</button>
</div>
<script src="js/app.js"></script>
</body>
</html>
// 简便API调用
// 同一个容器内:用相对路径或localhost
const API_BASE = ''; // 相对路径,生产环境可换成实际地址
async function callApi(endpoint, data) {
const res = await fetch(API_BASE + endpoint, {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(data)
});
return res.json();
}
// 开发环境:后端在不同端口
const API_BASE = 'http://localhost:8000';
// 生产环境(Docker同一容器):用相对路径
// const API_BASE = '';
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script>
const { createApp, ref } = Vue;
createApp({
setup() {
const message = ref('Hello');
return { message };
}
}).mount('#app');
</script>
前端访问后端API的两种方式:
方式1:相对路径(推荐,同一容器内)
const API_BASE = ''; // 用相对路径
// 调用
async function getItems() {
const res = await fetch(API_BASE + '/api/items');
return res.json();
}
async function createItem(name) {
const res = await fetch(API_BASE + '/api/items', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({name})
});
return res.json();
}
方式2:完整URL(本地开发)
const API_BASE = 'http://localhost:8000'; // 本地开发
// 调用
async function getItems() {
const res = await fetch(API_BASE + '/api/items');
return res.json();
}
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>我的应用</title>
</head>
<body>
<div id="app">
<h1>物品管理</h1>
<input v-model="newItem" @keyup.enter="addItem" placeholder="输入名称">
<button @click="addItem">添加</button>
<ul>
<li v-for="item in items">{{ item.name }}</li>
</ul>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script>
const { createApp, ref, onMounted } = Vue;
const API_BASE = ''; // 同容器用相对路径
createApp({
setup() {
const items = ref([]);
const newItem = ref('');
const loadItems = async () => {
const res = await fetch(API_BASE + '/api/items');
items.value = await res.json();
};
const addItem = async () => {
if (!newItem.value) return;
await fetch(API_BASE + '/api/items', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({name: newItem.value})
});
newItem.value = '';
await loadItems();
};
onMounted(() => {
loadItems();
});
return { items, newItem, addItem };
}
}).mount('#app');
</script>
</body>
</html>
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
import sqlite3
app = FastAPI()
# 允许前端跨域访问
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_methods=["*"],
allow_headers=["*"],
)
# SQLite连接
def get_db():
conn = sqlite3.connect('data.db')
conn.row_factory = sqlite3.Row
return conn
@app.get("/api/hello")
def hello():
return {"message": "你好"}
import sqlite3
def init_db():
conn = sqlite3.connect('data.db')
cursor = conn.cursor()
cursor.execute('''
CREATE TABLE IF NOT EXISTS items (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
''')
conn.commit()
conn.close()
@app.post("/api/items")
def create_item(item: dict):
conn = get_db()
cursor = conn.cursor()
cursor.execute("INSERT INTO items (name) VALUES (?)", (item['name'],))
conn.commit()
item_id = cursor.lastrowid
conn.close()
return {"id": item_id, "name": item['name']}
@app.get("/api/items")
def list_items():
conn = get_db()
cursor = conn.cursor()
cursor.execute("SELECT * FROM items ORDER BY created_at DESC")
items = cursor.fetchall()
conn.close()
return [{"id": r['id'], "name": r['name']} for r in items]
直接用浏览器打开 frontend/index.html
或使用简单HTTP服务器:
# Python 3
python -m http.server 8080 --directory frontend
# 安装依赖
pip install fastapi uvicorn
# 启动
uvicorn main:app --reload --port 8000
uvicorn backend.main:app 启动(保持与Docker一致)当使用 Docker 部署时,uvicorn 以模块路径方式启动:
uvicorn backend.main:app --host 0.0.0.0 --port 8000
这意味着:
/app(不是 /app/backend)main.py 位于 /app/backend/main.pyfrom database import 找不到 /app/database.py# main.py 位于 /app/backend/main.py
# database.py 位于 /app/backend/database.py
# ✅ 正确:用包路径前缀
from backend.database import get_db, init_db
# ❌ 错误:假设工作目录是 /app/backend
from database import get_db, init_db
| uvicorn 启动方式 | main.py 位置 | 正确 import |
|---|---|---|
uvicorn main:app | /app/main.py | from database import |
uvicorn backend.main:app | /app/backend/main.py | from backend.database import |
uvicorn backend.api.main:app | /app/backend/api/main.py | from backend.api.models import |
必须统一使用模块路径方式启动,否则本地开发和 Docker 部署的 import 行为会不一致:
# ✅ 推荐:项目根目录下运行(与 Docker 行为一致)
uvicorn backend.main:app --reload --port 8000
# ❌ 不推荐:进入 backend 目录运行(与 Docker 行为不同)
# cd backend && uvicorn main:app
<input type="file" id="fileInput">
<button onclick="uploadFile()">上传</button>
<script>
async function uploadFile() {
const fileInput = document.getElementById('fileInput');
const file = fileInput.files[0];
if (!file) return alert('请选择文件');
const formData = new FormData();
formData.append('file', file);
const res = await fetch('http://localhost:8000/api/upload', {
method: 'POST',
body: formData
});
const data = await res.json();
if (data.success) {
alert('上传成功: ' + data.filename);
} else {
alert('上传失败');
}
}
</script>
import os
from fastapi import UploadFile
# 上传文件保存目录
UPLOAD_DIR = "uploads"
os.makedirs(UPLOAD_DIR, exist_ok=True)
@app.post("/api/upload")
async def upload_file(file: UploadFile):
# 保存文件到本地
file_path = os.path.join(UPLOAD_DIR, file.filename)
content = await file.read()
with open(file_path, 'wb') as f:
f.write(content)
return {"success": True, "filename": file.filename}
uploads/ 文件夹需要完整的 Docker 构建、推送阿里云 ACR、服务器部署流程? 请使用
docker-acr-deploy技能获取详细指南。
dist/ 目录已生成requirements.txt 包含 fastapi/appQ: 什么时候该用Vue/React而不是原生JS? A: 页面有复杂交互(如表单验证、动态列表、数据绑定)再用Vue/React。简单展示页面用原生JS即可。
Q: 什么时候该换MySQL/PostgreSQL? A: 需要多用户同时访问、有复杂查询需求、或数据量超过1万条时再考虑。
Q: 前端怎么连接后端API? A: 使用fetch或axios发起HTTP请求,后端需要配置CORS允许跨域访问。
重要: 只要有程序启动的URL地址,必须执行以下操作:
http://{沙箱VNC地址}/vnc/index.html?autoconnect=true,方便用户直接在新窗口打开