From 06a855c0f4a2e0cad431a7c0bcd2c6d791fc276f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E8=9A=82=E8=9A=81=E4=BA=91?= Date: Sun, 25 Oct 2026 22:53:48 +0800 Subject: [PATCH] =?UTF-8?q?=E7=AD=BE=E5=85=A5=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../.vitepress/config/extract.d.mts | 5 + .../.vitepress/config/extract.mjs | 130 ++++++++ .../.vitepress/config/index.ts | 8 + .../.vitepress/config/seo.ts | 311 ++++++++++++++++++ .../.vitepress/config/shared.ts | 4 +- .../.vitepress/config/zh.ts | 7 +- DjangoAdmin_Tornado_AntdVue/404.md | 12 + DjangoAdmin_Tornado_AntdVue/package.json | 3 +- DjangoAdmin_Tornado_AntdVue/public/llms.txt | 168 ++++++++++ DjangoAdmin_Tornado_AntdVue/public/robots.txt | 33 ++ .../scripts/generate-llms-txt.mjs | 122 +++++++ DjangoAdmin_Tornado_AntdVue/zh/course.md | 2 + .../zh/introduction.md | 6 + .../zh/other/declare.md | 4 + DjangoAdmin_Tornado_AntdVue/zh/struct.md | 2 + .../zh/volume2/code-list.md | 4 + DjangoAdmin_Tornado_AntdVue/zh/volume2/faq.md | 4 + .../zh/volume2/fe-api.md | 4 + .../zh/volume2/fe-router.md | 4 + .../zh/volume2/fe-view.md | 4 + .../zh/volume2/handler.md | 4 + .../zh/volume2/repository.md | 4 + .../zh/volume2/schema.md | 4 + .../zh/volume3/overview.md | 4 + .../zh/volume4/business/article.md | 2 + .../zh/volume4/business/category.md | 2 + .../zh/volume4/business/content.md | 2 + .../zh/volume4/business/dept.md | 2 + .../zh/volume4/business/job.md | 2 + .../zh/volume4/business/menu.md | 2 + .../zh/volume4/business/param.md | 2 + .../zh/volume4/business/role.md | 2 + .../zh/volume4/business/user.md | 2 + .../zh/volume4/core/captcha.md | 2 + .../zh/volume4/core/config.md | 2 + .../zh/volume4/core/demo-mode.md | 2 + .../zh/volume4/core/dict.md | 2 + .../zh/volume4/core/exception.md | 2 + .../zh/volume4/core/jwt.md | 2 + .../zh/volume4/core/login-log.md | 2 + .../zh/volume4/core/operation-log.md | 2 + .../zh/volume4/core/rbac.md | 2 + .../zh/volume4/core/validator.md | 2 + DjangoAdmin_Tornado_AntdVue/zh/why.md | 2 +- .../.vitepress/config/en.ts | 2 +- .../.vitepress/config/extract.d.mts | 5 + .../.vitepress/config/extract.mjs | 130 ++++++++ .../.vitepress/config/index.ts | 8 + .../.vitepress/config/seo.ts | 311 ++++++++++++++++++ .../.vitepress/config/shared.ts | 4 +- .../.vitepress/config/zh.ts | 7 +- DjangoAdmin_Tornado_EleVue/404.md | 12 + DjangoAdmin_Tornado_EleVue/package.json | 3 +- DjangoAdmin_Tornado_EleVue/public/llms.txt | 168 ++++++++++ DjangoAdmin_Tornado_EleVue/public/robots.txt | 33 ++ .../scripts/generate-llms-txt.mjs | 122 +++++++ DjangoAdmin_Tornado_EleVue/zh/course.md | 2 + DjangoAdmin_Tornado_EleVue/zh/introduction.md | 6 + .../zh/other/declare.md | 4 + DjangoAdmin_Tornado_EleVue/zh/struct.md | 2 + .../zh/volume2/code-list.md | 4 + DjangoAdmin_Tornado_EleVue/zh/volume2/faq.md | 4 + .../zh/volume2/fe-api.md | 4 + .../zh/volume2/fe-router.md | 4 + .../zh/volume2/fe-view.md | 4 + .../zh/volume2/handler.md | 4 + .../zh/volume2/model.md | 4 + .../zh/volume2/repository.md | 4 + .../zh/volume2/schema.md | 4 + .../zh/volume3/overview.md | 4 + .../zh/volume4/business/article.md | 2 + .../zh/volume4/business/category.md | 2 + .../zh/volume4/business/content.md | 2 + .../zh/volume4/business/dept.md | 2 + .../zh/volume4/business/job.md | 2 + .../zh/volume4/business/menu.md | 2 + .../zh/volume4/business/param.md | 2 + .../zh/volume4/business/role.md | 2 + .../zh/volume4/business/user.md | 2 + .../zh/volume4/core/captcha.md | 2 + .../zh/volume4/core/config.md | 2 + .../zh/volume4/core/demo-mode.md | 2 + .../zh/volume4/core/dict.md | 2 + .../zh/volume4/core/exception.md | 2 + .../zh/volume4/core/jwt.md | 2 + .../zh/volume4/core/login-log.md | 2 + .../zh/volume4/core/operation-log.md | 2 + .../zh/volume4/core/rbac.md | 2 + .../zh/volume4/core/validator.md | 2 + DjangoAdmin_Tornado_EleVue/zh/why.md | 2 +- .../.vitepress/config/en.ts | 2 +- .../.vitepress/config/extract.d.mts | 5 + .../.vitepress/config/extract.mjs | 130 ++++++++ .../.vitepress/config/index.ts | 8 + .../.vitepress/config/seo.ts | 311 ++++++++++++++++++ .../.vitepress/config/shared.ts | 4 +- .../.vitepress/config/zh.ts | 7 +- DjangoAdmin_Tornado_NaiveVue/404.md | 12 + DjangoAdmin_Tornado_NaiveVue/package.json | 3 +- DjangoAdmin_Tornado_NaiveVue/public/llms.txt | 168 ++++++++++ .../public/robots.txt | 33 ++ .../scripts/generate-llms-txt.mjs | 122 +++++++ DjangoAdmin_Tornado_NaiveVue/zh/course.md | 2 + .../zh/introduction.md | 6 + .../zh/other/declare.md | 4 + DjangoAdmin_Tornado_NaiveVue/zh/struct.md | 2 + .../zh/volume2/code-list.md | 4 + .../zh/volume2/faq.md | 4 + .../zh/volume2/fe-api.md | 4 + .../zh/volume2/fe-router.md | 4 + .../zh/volume2/fe-view.md | 4 + .../zh/volume2/handler.md | 4 + .../zh/volume2/repository.md | 4 + .../zh/volume2/schema.md | 4 + .../zh/volume3/overview.md | 4 + .../zh/volume4/business/article.md | 2 + .../zh/volume4/business/category.md | 2 + .../zh/volume4/business/content.md | 2 + .../zh/volume4/business/dept.md | 2 + .../zh/volume4/business/job.md | 2 + .../zh/volume4/business/menu.md | 2 + .../zh/volume4/business/param.md | 2 + .../zh/volume4/business/role.md | 2 + .../zh/volume4/business/user.md | 2 + .../zh/volume4/core/captcha.md | 2 + .../zh/volume4/core/config.md | 2 + .../zh/volume4/core/demo-mode.md | 2 + .../zh/volume4/core/dict.md | 2 + .../zh/volume4/core/exception.md | 2 + .../zh/volume4/core/jwt.md | 2 + .../zh/volume4/core/login-log.md | 2 + .../zh/volume4/core/operation-log.md | 2 + .../zh/volume4/core/rbac.md | 2 + .../zh/volume4/core/validator.md | 2 + DjangoAdmin_Tornado_NaiveVue/zh/why.md | 2 +- 135 files changed, 2667 insertions(+), 20 deletions(-) create mode 100644 DjangoAdmin_Tornado_AntdVue/.vitepress/config/extract.d.mts create mode 100644 DjangoAdmin_Tornado_AntdVue/.vitepress/config/extract.mjs create mode 100644 DjangoAdmin_Tornado_AntdVue/.vitepress/config/seo.ts create mode 100644 DjangoAdmin_Tornado_AntdVue/404.md create mode 100644 DjangoAdmin_Tornado_AntdVue/public/llms.txt create mode 100644 DjangoAdmin_Tornado_AntdVue/public/robots.txt create mode 100644 DjangoAdmin_Tornado_AntdVue/scripts/generate-llms-txt.mjs create mode 100644 DjangoAdmin_Tornado_EleVue/.vitepress/config/extract.d.mts create mode 100644 DjangoAdmin_Tornado_EleVue/.vitepress/config/extract.mjs create mode 100644 DjangoAdmin_Tornado_EleVue/.vitepress/config/seo.ts create mode 100644 DjangoAdmin_Tornado_EleVue/404.md create mode 100644 DjangoAdmin_Tornado_EleVue/public/llms.txt create mode 100644 DjangoAdmin_Tornado_EleVue/public/robots.txt create mode 100644 DjangoAdmin_Tornado_EleVue/scripts/generate-llms-txt.mjs create mode 100644 DjangoAdmin_Tornado_NaiveVue/.vitepress/config/extract.d.mts create mode 100644 DjangoAdmin_Tornado_NaiveVue/.vitepress/config/extract.mjs create mode 100644 DjangoAdmin_Tornado_NaiveVue/.vitepress/config/seo.ts create mode 100644 DjangoAdmin_Tornado_NaiveVue/404.md create mode 100644 DjangoAdmin_Tornado_NaiveVue/public/llms.txt create mode 100644 DjangoAdmin_Tornado_NaiveVue/public/robots.txt create mode 100644 DjangoAdmin_Tornado_NaiveVue/scripts/generate-llms-txt.mjs diff --git a/DjangoAdmin_Tornado_AntdVue/.vitepress/config/extract.d.mts b/DjangoAdmin_Tornado_AntdVue/.vitepress/config/extract.d.mts new file mode 100644 index 0000000..2a46233 --- /dev/null +++ b/DjangoAdmin_Tornado_AntdVue/.vitepress/config/extract.d.mts @@ -0,0 +1,5 @@ +export declare const SITE_URL: string; +export declare const SITE_DESCRIPTION: string; +export declare function stripNumberPrefix(title: string): string; +export declare function extractDescription(md: string): string; +export declare function extractFaqs(md: string): { q: string; a: string }[]; diff --git a/DjangoAdmin_Tornado_AntdVue/.vitepress/config/extract.mjs b/DjangoAdmin_Tornado_AntdVue/.vitepress/config/extract.mjs new file mode 100644 index 0000000..203c370 --- /dev/null +++ b/DjangoAdmin_Tornado_AntdVue/.vitepress/config/extract.mjs @@ -0,0 +1,130 @@ +/** + * SEO/GEO 共享工具(纯 ESM,零依赖)。 + * + * 同时被两类调用方 import: + * 1. VitePress 配置(.ts,esbuild 打包时内联本文件) + * 2. scripts/generate-llms-txt.mjs(Node 直接运行) + * + * 注意:SITE_URL 是全站唯一 URL 真相源。 + * docs 子域当前 TLS 证书为腾讯 CDN 默认证书(*.cdn.myqcloud.com,校验失败), + * 故暂用 http;证书修复后只需改这里一处。 + */ + +export const SITE_URL = "http://docs.tornado.antdvue.djangoadmin.cn"; + +export const SITE_DESCRIPTION = + "DjangoAdmin Tornado+AntDesign 企业级中台解决方案开发者文档"; + +/** + * 剥离 H1/标题中的章节编号前缀,用于 与 JSON-LD headline。 + * 例:"5.10 字典模块" → "字典模块";"K. 贡献指南" → "贡献指南"。 + * 页内 H1 与侧边栏编号保持不变,仅影响 SEO 输出。 + */ +export function stripNumberPrefix(title) { + return String(title) + .replace(/^(?:\d+(?:\.\d+)+|[A-Z]\.)\s+/, "") + .trim(); +} + +/** + * 从页面 Markdown 提取 meta description: + * 1. 首选 `:::tip xxx` 容器内的首句(141/143 页的标准 opener) + * 2. 回退到 H1 后的第一个普通段落 + * 输出压缩为单行、去除行内 Markdown,按中文句末标点截断(≤100 字符)。 + */ +export function extractDescription(md) { + const src = String(md); + const fm = src.match(/^---\r?\n([\s\S]*?)\r?\n---/); + const body = fm ? src.slice(fm[0].length) : src; + + let text = ""; + // frontmatter description 显式声明优先(无 H1 页面的补齐手段) + const fmDesc = fm && fm[1].match(/^description:\s*(.+)$/m); + if (fmDesc) { + text = fmDesc[1].trim().replace(/^["']|["']$/g, ""); + } + const tip = !text && body.match(/^:::\s*tip[^\n]*\n([\s\S]*?)\n:::/m); + if (tip) { + text = tip[1]; + } + if (!text) { + const afterH1 = body.match(/^# (?!#)(.+)$/m); + if (afterH1) { + const rest = body.slice((afterH1.index ?? 0) + afterH1[0].length); + const para = rest + .split(/\n{2,}/) + .find( + (p) => + p.trim() && + !/^\s*#/.test(p) && + !/^\s*:::/.test(p) && + !/^\s*```/.test(p) && + !/^\s*\|/.test(p), + ); + text = para || ""; + } + } + + text = text + .replace(/\s+/g, " ") + .replace(/`([^`]+)`/g, "$1") + .replace(/\*\*([^*]+)\*\*/g, "$1") + .replace(/\[([^\]]+)\]\([^)]*\)/g, "$1") + .trim(); + + if (!text) return ""; + + // 按中文句末标点截取首句,上限 100 字符;截断时避免切碎词 + const m = text.match(/^.{1,100}?(?:[。!?!?]|$)/); + let out = m ? m[0] : text.slice(0, 100); + if (out.length < text.length && !/[。!?!?]$/.test(out)) { + out = out.replace(/[^\s,、;:,;:]+$/, ""); + } + return out.trim() || text.slice(0, 100); +} + +function cleanText(s) { + return s + .replace(/^:::[^\n]*$/gm, "") + .replace(/^```[^\n]*$/gm, "") + .replace(/`([^`]+)`/g, "$1") + .replace(/\*\*([^*]+)\*\*/g, "$1") + .replace(/\[([^\]]+)\]\([^)]*\)/g, "$1") + .replace(/\s+/g, " ") + .trim(); +} + +/** + * 提取页面中的 Q/A 对(用于 FAQPage JSON-LD),支持两种站内格式: + * A. `### Q:问题` 标题式(如 zh/quickstart/faq.md) + * B. `**Q:问题**` 加粗式(如 zh/appendix/faq.md) + * 返回 [{ q, a }];无匹配返回 []。 + */ +export function extractFaqs(md) { + const body = String(md).replace(/^---[\s\S]*?\n---\s*/, ""); + let faqs = []; + + // 格式 A:按 `### Q:` 切块,答案截断到下一个标题 + for (const part of body.split(/(?=^###\s*Q[::])/m)) { + const m = part.match(/^###\s*Q[::]\s*([^\n]+)\n+([\s\S]*)/); + if (!m) continue; + let a = m[2]; + const cut = a.search(/^#{1,4}\s/m); + if (cut >= 0) a = a.slice(0, cut); + faqs.push({ q: cleanText(m[1]), a: cleanText(a) }); + } + + // 格式 B:按 `**Q:` 切块 + if (!faqs.length) { + for (const part of body.split(/(?=^\*\*Q[::])/m)) { + const m = part.match(/^\*\*Q[::]\s*([^*]+)\*\*\s*\n+([\s\S]*)/); + if (!m) continue; + let a = m[2]; + const cut = a.search(/^(?:#{1,4}\s|\*\*Q)/m); + if (cut >= 0) a = a.slice(0, cut); + faqs.push({ q: cleanText(m[1]), a: cleanText(a) }); + } + } + + return faqs.filter((f) => f.q && f.a); +} diff --git a/DjangoAdmin_Tornado_AntdVue/.vitepress/config/index.ts b/DjangoAdmin_Tornado_AntdVue/.vitepress/config/index.ts index 2294856..6627a76 100644 --- a/DjangoAdmin_Tornado_AntdVue/.vitepress/config/index.ts +++ b/DjangoAdmin_Tornado_AntdVue/.vitepress/config/index.ts @@ -1,14 +1,22 @@ import { defineConfig } from "vitepress"; import { enConfig } from "./en"; +import { createSeoHooks } from "./seo"; import { sharedConfig } from "./shared"; import { zhConfig } from "./zh"; +const seo = createSeoHooks(zhConfig.themeConfig?.sidebar); + export default defineConfig({ ...sharedConfig, ignoreDeadLinks: [ (link) => link.includes('localhost'), ], + // SEO:页面级 title/description、canonical/OG/JSON-LD、sitemap+lastmod + transformPageData: seo.transformPageData, + transformHead: seo.transformHead, + sitemap: seo.sitemap, + locales: { root: { label: "简体中文", lang: "zh-CN", link: "/", ...zhConfig }, // root: { label: "English", lang: "en-US", link: "/", ...enConfig }, diff --git a/DjangoAdmin_Tornado_AntdVue/.vitepress/config/seo.ts b/DjangoAdmin_Tornado_AntdVue/.vitepress/config/seo.ts new file mode 100644 index 0000000..47b942b --- /dev/null +++ b/DjangoAdmin_Tornado_AntdVue/.vitepress/config/seo.ts @@ -0,0 +1,311 @@ +/** + * SEO/GEO 构建期钩子(仅 Node 构建时运行,不进客户端 bundle): + * - transformPageData:每页独立 title(去编号前缀)与 description(取 :::tip 首句) + * - transformHead:canonical / Open Graph / twitter 卡片 / JSON-LD 结构化数据 + * - sitemap.transformItems:注入 lastmod(git 最后提交时间)并过滤 404 + * + * 由 config/index.ts 通过 createSeoHooks(zhConfig.themeConfig?.sidebar) 挂载。 + * 依赖 extract.mjs(纯 ESM,同被 scripts/generate-llms-txt.mjs 复用)。 + */ +import fs from "node:fs"; +import path from "node:path"; +import { execSync } from "node:child_process"; +import { + SITE_URL, + extractDescription, + extractFaqs, + stripNumberPrefix, +} from "./extract.mjs"; + +/** 与 vitepress HeadConfig 同构:[tag, attrs, innerHTML?] */ +type HeadTuple = [string, Record<string, any>, string?]; + +interface SideItem { + text?: string; + link?: string; + items?: SideItem[]; +} + +interface PageDataLike { + relativePath?: string; + title?: string; + description?: string; + frontmatter?: Record<string, any>; + [k: string]: any; +} + +interface TransformCtx { + pageData?: PageDataLike; + title?: string; + description?: string; + content?: string; + siteConfig?: { root?: string; srcDir?: string }; +} + +const ORG = { + "@type": "Organization", + name: "DjangoAdmin", + url: "https://www.djangoadmin.cn", + logo: `${SITE_URL}/logo.png`, + sameAs: [ + "https://gitee.com/djangoadmin/DjangoAdmin_Tornado_AntdVue", + "https://www.djangoadmin.cn", + ], +}; + +/** 相对路径 → 站内路由(cleanUrls 关闭,正文页带 .html) */ +function routeOf(relativePath: string): string { + if (relativePath === "index.md") return "/"; + if (relativePath === "404.md") return "/404.html"; + return `/${relativePath.replace(/\.md$/, ".html")}`; +} + +/** 去掉侧边栏文案前导 emoji/符号,保留 "1.1 项目介绍" 这类编号文字 */ +function cleanLabel(s?: string): string { + return (s || "").replace(/^[^\p{L}\p{N}]+/u, "").trim(); +} + +/** 从侧边栏构建 route → 面包屑文案链(含分组小节) */ +function buildCrumbMap(sidebar: unknown): Map<string, string[]> { + const map = new Map<string, string[]>(); + const groups: SideItem[] = Array.isArray(sidebar) + ? sidebar + : ((sidebar as Record<string, SideItem[]>)?.["/zh/"] ?? []); + const walk = (items: SideItem[], trail: string[]) => { + for (const item of items) { + if (item.link && item.link.startsWith("/")) { + map.set(item.link, [...trail, cleanLabel(item.text)]); + } else if (item.items?.length) { + walk(item.items, [...trail, cleanLabel(item.text)]); + } + } + }; + for (const group of groups) { + walk(group.items ?? [], [cleanLabel(group.text)].filter(Boolean)); + } + return map; +} + +/** 从渲染后的 HTML 提取 H1 纯文本(JSON-LD headline 须与页面 H1 一致) */ +function h1OfHtml(html?: string): string { + const m = (html || "").match(/<h1[^>]*>([\s\S]*?)<\/h1>/i); + if (!m) return ""; + return m[1] + .replace(/<[^>]+>/g, "") + .replace(/&/g, "&") + .replace(/</g, "<") + .replace(/>/g, ">") + .replace(/"/g, '"') + .replace(/'/g, "'") + .trim(); +} + +/** 从 Markdown 源提取 H1 纯文本(去除行内 markdown 标记) */ +function h1OfMd(md: string): string { + // 围栏感知:跳过 ``` 代码块内的 # 注释,取真正的页面 H1 + let inFence = false; + for (const line of md.split("\n")) { + if (line.startsWith("```")) { inFence = !inFence; continue; } + if (!inFence && /^# (?!#)/.test(line)) { + return line + .replace(/^# /, "") + .replace(/`([^`]+)`/g, "$1") + .replace(/\*\*([^*]+)\*\*/g, "$1") + .trim(); + } + } + return ""; +} + +export function createSeoHooks(sidebar: unknown) { + const crumbs = buildCrumbMap(sidebar); + const projectDirs: string[] = []; + let gitDates: Map<string, string> | null = null; + + const readMd = (relativePath: string, srcDir?: string): string => { + try { + return fs.readFileSync( + path.resolve(srcDir || process.cwd(), relativePath), + "utf8", + ); + } catch { + return ""; + } + }; + + /** + * 项目内每个文件最后一次 git 提交的 ISO 时间。 + * 单次 git log 调用构建全量映射(key = 相对路径,与 pageData.relativePath 一致); + * git 不可用时静默降级(sitemap 无 lastmod、JSON-LD 无 dateModified)。 + */ + const getGitDates = (root: string): Map<string, string> => { + if (gitDates) return gitDates; + gitDates = new Map<string, string>(); + try { + const out = execSync( + "git log --format=:::%cI --name-only --relative -n 500 -- .", + { + cwd: root, + encoding: "utf8", + maxBuffer: 64 * 1024 * 1024, + stdio: ["ignore", "pipe", "ignore"], + }, + ); + let current = ""; + for (const line of out.split(/\r?\n/)) { + if (line.startsWith(":::")) { + current = line.slice(3).trim(); + continue; + } + const file = line.trim(); + if (file && current && !gitDates.has(file)) { + gitDates.set(file, current); + } + } + } catch { + // 降级:无 lastmod / dateModified + } + return gitDates; + }; + + /** 每页独立 title(去 "5.10 " 编号前缀,关键词前置)与 description(:::tip 首句) */ + function transformPageData(pageData: PageDataLike, ctx?: any): Record<string, unknown> { + const srcDir: string | undefined = ctx?.siteConfig?.srcDir; + const root: string | undefined = ctx?.siteConfig?.root; + if (root && !projectDirs.includes(root)) projectDirs.push(root); + + const out: Record<string, unknown> = {}; + const rel = pageData.relativePath; + if (rel && !pageData.frontmatter?.description) { + const desc = extractDescription(readMd(rel, srcDir)); + if (desc) out.description = desc; + } + if (pageData.title) { + out.title = stripNumberPrefix(pageData.title); + } + return out; + } + + /** 构建期注入 canonical / OG / twitter / JSON-LD */ + function transformHead(ctx: TransformCtx): HeadTuple[] { + const rel = ctx?.pageData?.relativePath || ""; + if (!rel || rel === "404.md") return []; + + const route = routeOf(rel); + const url = `${SITE_URL}${route}`; + const title = ctx.pageData?.title || ctx.title || ""; + const desc = ctx.description || ""; + const isHome = rel === "index.md"; + const image = `${SITE_URL}/logo.png`; + + const heads: HeadTuple[] = [ + ["link", { rel: "canonical", href: url }], + ["meta", { property: "og:type", content: isHome ? "website" : "article" }], + ["meta", { property: "og:site_name", content: "DjangoAdmin" }], + ["meta", { property: "og:locale", content: "zh_CN" }], + ["meta", { property: "og:title", content: title }], + ["meta", { property: "og:description", content: desc }], + ["meta", { property: "og:url", content: url }], + ["meta", { property: "og:image", content: image }], + ["meta", { property: "twitter:title", content: title }], + ["meta", { property: "twitter:description", content: desc }], + ["meta", { property: "twitter:url", content: url }], + ["meta", { property: "twitter:image", content: image }], + ]; + + // ---- JSON-LD ---- + const root = ctx.siteConfig?.root || projectDirs[0] || process.cwd(); + const srcDir = ctx.siteConfig?.srcDir || root; + const lastMod = getGitDates(root).get(rel); + const blocks: Record<string, any>[] = []; + + if (isHome) { + blocks.push({ + "@context": "https://schema.org", + "@type": "WebSite", + name: "DjangoAdmin 开发文档", + url: `${SITE_URL}/`, + inLanguage: "zh-CN", + description: desc, + }); + blocks.push({ "@context": "https://schema.org", ...ORG }); + } else { + const md = readMd(rel, srcDir); + const article: Record<string, any> = { + "@context": "https://schema.org", + "@type": "TechArticle", + headline: h1OfMd(md) || h1OfHtml(ctx.content) || title, + description: desc, + url, + inLanguage: "zh-CN", + mainEntityOfPage: { "@type": "WebPage", "@id": url }, + publisher: ORG, + }; + if (lastMod) article.dateModified = lastMod; + blocks.push(article); + + const trail = crumbs.get(route); + if (trail?.length) { + const items: Record<string, any>[] = [ + { "@type": "ListItem", position: 1, name: "首页", item: `${SITE_URL}/` }, + ]; + trail.forEach((name, i) => { + const node: Record<string, any> = { + "@type": "ListItem", + position: i + 2, + name, + }; + if (i === trail.length - 1) node.item = url; + items.push(node); + }); + blocks.push({ + "@context": "https://schema.org", + "@type": "BreadcrumbList", + itemListElement: items, + }); + } + + const faqs = extractFaqs(md); + if (faqs.length) { + blocks.push({ + "@context": "https://schema.org", + "@type": "FAQPage", + mainEntity: faqs.map((f) => ({ + "@type": "Question", + name: f.q, + acceptedAnswer: { "@type": "Answer", text: f.a }, + })), + }); + } + } + + // 转义 "<",防止内容中出现 </script> 破坏注入 + const json = JSON.stringify(blocks).replace(/</g, "\\u003c"); + heads.push(["script", { type: "application/ld+json" }, json]); + return heads; + } + + /** sitemap.xml:过滤 404/README,注入 git lastmod */ + const sitemap = { + hostname: SITE_URL, + transformItems(items: { url: string; lastmod?: string }[]) { + const root = projectDirs[0] || process.cwd(); + const dates = getGitDates(root); + const out: { url: string; lastmod?: string }[] = []; + for (const item of items) { + // ⚠ vitepress 传入的 item.url 是相对路径("404.html"、"zh/x.html"、""), + // 无前导斜杠也无域名——hostname 由 SitemapStream 事后拼接。 + if (/(^|\/)404\.html$/.test(item.url)) continue; // 404 页不收录 + if (/(^|\/)README\.html$/.test(item.url)) continue; // 仓库 README 非文档页 + const p = item.url.replace(/^\//, ""); + const rel = + p === "" || p === "index.html" ? "index.md" : p.replace(/\.html$/, ".md"); + const lastmod = dates.get(rel); + out.push(lastmod ? { ...item, lastmod } : item); + } + return out; + }, + }; + + return { transformPageData, transformHead, sitemap }; +} diff --git a/DjangoAdmin_Tornado_AntdVue/.vitepress/config/shared.ts b/DjangoAdmin_Tornado_AntdVue/.vitepress/config/shared.ts index 2858654..e8ef6c5 100644 --- a/DjangoAdmin_Tornado_AntdVue/.vitepress/config/shared.ts +++ b/DjangoAdmin_Tornado_AntdVue/.vitepress/config/shared.ts @@ -1,6 +1,6 @@ import { defineConfig, HeadConfig } from "vitepress"; -export const META_IMAGE = "/social.png"; +export const META_IMAGE = "/logo.png"; const rControl = /[\u0000-\u001f]/g; const rSpecial = /[\s~`!@#$%^&*()\-_+=[\]{}|\\;:"'“”‘’<>,.?/]+/g; @@ -23,6 +23,8 @@ export const slugify = (str: string): string => export const sharedConfig = defineConfig({ title: "小蚂蚁云", + // 页面 <title> 后缀:「环境准备 | DjangoAdmin 开发文档」(index.md frontmatter 可覆盖) + titleTemplate: "DjangoAdmin 开发文档", appearance: "light", markdown: { diff --git a/DjangoAdmin_Tornado_AntdVue/.vitepress/config/zh.ts b/DjangoAdmin_Tornado_AntdVue/.vitepress/config/zh.ts index cb40152..4f9b760 100644 --- a/DjangoAdmin_Tornado_AntdVue/.vitepress/config/zh.ts +++ b/DjangoAdmin_Tornado_AntdVue/.vitepress/config/zh.ts @@ -1,8 +1,9 @@ import type { DefaultTheme, LocaleSpecificConfig } from "vitepress"; -export const META_URL = "https://www.djangoadmin.cn"; -export const META_TITLE = "企业级中台解决方案"; -export const META_DESCRIPTION = "企业级中台解决方案"; +export const META_URL = "http://docs.tornado.antdvue.djangoadmin.cn"; +export const META_TITLE = "DjangoAdmin Tornado+AntDesign 开发文档"; +export const META_DESCRIPTION = + "DjangoAdmin Tornado+AntDesign 企业级中台解决方案开发者文档"; export const zhConfig: LocaleSpecificConfig<DefaultTheme.Config> = { description: META_DESCRIPTION, diff --git a/DjangoAdmin_Tornado_AntdVue/404.md b/DjangoAdmin_Tornado_AntdVue/404.md new file mode 100644 index 0000000..c344b20 --- /dev/null +++ b/DjangoAdmin_Tornado_AntdVue/404.md @@ -0,0 +1,12 @@ +--- +head: + - - meta + - name: robots + content: noindex +--- + +# 页面不存在 + +抱歉,您访问的页面不存在或已被移动。 + +[返回首页](/) · [浏览文档](/zh/introduction) diff --git a/DjangoAdmin_Tornado_AntdVue/package.json b/DjangoAdmin_Tornado_AntdVue/package.json index 77bd941..b5517ed 100644 --- a/DjangoAdmin_Tornado_AntdVue/package.json +++ b/DjangoAdmin_Tornado_AntdVue/package.json @@ -5,7 +5,8 @@ "type": "module", "scripts": { "docs": "vitepress dev .", - "docs:build": "vitepress build .", + "docs:llms": "node scripts/generate-llms-txt.mjs", + "docs:build": "node scripts/generate-llms-txt.mjs && vitepress build .", "docs:preview": "vitepress preview ." }, "dependencies": { diff --git a/DjangoAdmin_Tornado_AntdVue/public/llms.txt b/DjangoAdmin_Tornado_AntdVue/public/llms.txt new file mode 100644 index 0000000..723863f --- /dev/null +++ b/DjangoAdmin_Tornado_AntdVue/public/llms.txt @@ -0,0 +1,168 @@ +# DjangoAdmin Tornado+AntDesign 开发文档 + +> DjangoAdmin Tornado+AntDesign 企业级中台解决方案开发者文档。内置 RBAC 权限体系、代码生成器等开箱即用功能,支持五种数据库一键切换。本文档共 138 篇,按章节组织。 + +## 1. 了解项目 + +- [更新日志](http://docs.tornado.antdvue.djangoadmin.cn/zh/changelog.html): 更新日志是项目演进的完整记录,帮助开发者和企业了解每个版本的能力变化与技术演进方向。 +- [新手入门指南](http://docs.tornado.antdvue.djangoadmin.cn/zh/course.html): 详细的安装步骤请参考 环境准备 章节。 +- [项目介绍](http://docs.tornado.antdvue.djangoadmin.cn/zh/introduction.html): DjangoAdmin 是企业级中台解决方案,后端基于 Tornado + SQLAlchemy,前端基于 Vue3 + AntDesign,内置 RBAC 权限、代码生成器等开箱即用功能, +- [项目目录结构](http://docs.tornado.antdvue.djangoadmin.cn/zh/struct.html): + 保持一致性:目录结构一旦确定,应保持一致性,避免随意更改。 +- [为什么选择我们?](http://docs.tornado.antdvue.djangoadmin.cn/zh/why.html): 本框架提供开箱即用的企业级中台完整解决方案,免去从零搭建成本,助力中大型企业构建统一的数字化基座。 + +## 2. 快速入门 + +- [后端启动](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume1/backend.html): 启动后端前,请确保已完成 环境准备 章节中的所有软件安装。 +- [数据库初始化](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume1/database.html): 数据库初始化前,请确保已完成以下准备工作: 1. 目标数据库服务已启动(如 MySQL 8.0+) 2. .env 文件中的 DB_DRIVER 和数据库连接信息已正确配置 3. Python +- [Docker 快速部署](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume1/docker.html): Docker 部署适合快速体验和生产环境。 +- [环境变量速查表](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume1/env-vars.html): 1. .env.example 是环境变量模板文件,已提交到版本控制。 +- [环境准备](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume1/environment.html): 1. 部分软件安装后需要设置本地环境变量,便于在终端中使用命令。 +- [常见问题FAQ](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume1/faq.html): 遇到问题时,建议先查看终端日志输出和浏览器控制台(F12)的错误信息,通常能快速定位问题原因。 +- [第一个接口调试](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume1/first-api.html): 开始调试前,请确保已完成以下步骤: 1. 后端服务已启动(参见 后端启动) 2. 数据库已初始化(参见 数据库初始化) 3. Redis 服务已启动 +- [前端启动](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume1/frontend.html): 启动前端前,请确保已完成 环境准备 章节中的 Node.js 和 pnpm 安装,并已启动后端服务(参见 后端启动)。 + +## 3. 模块开发实战 + +- [完整代码清单](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume2/code-list.html): 本页汇总友链(Link)模块涉及的全部文件代码,开发时可快速查阅与复制对照。 +- [示例模块(Example)](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume2/example.html): src/modules/example/ 是一个完整的示例模块,演示了标准 CRUD 模块的六文件结构和开发模式。 +- [常见问题与排错](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume2/faq.html): 本页汇总模块开发过程中的常见问题与排错方法,开发受阻时按症状索引即可定位。 +- [前端 API 层](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume2/fe-api.html): 前端 API 层封装后端接口的 HTTP 请求,每个业务模块对应一个 API 文件,本页讲解基于 Axios 封装的编写规范。 +- [前端路由与菜单](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume2/fe-router.html): 本页讲解前端路由与菜单机制——路由和菜单由后端动态返回,前端只需注册路由组件映射。 +- [前端页面视图](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume2/fe-view.html): 前端页面视图是用户直接交互的界面,本页讲解 Vue3 + AntDesign 下一个完整 CRUD 页面的文件组成与编写方式。 +- [请求处理器(Handler)](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume2/handler.html): Handler 层是 HTTP 接口层,负责接收请求、校验权限与记录操作日志,编写新接口从本页开始。 +- [数据模型(Model)](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume2/model.html): BaseModel 是所有业务模型的基类,提供6个通用审计字段和 to_dict() 序列化方法。 +- [概述与目标](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume2/overview.html): 其中 id、create_user、create_time、update_user、update_time、is_delete 由基类 BaseModel 自动提供,业务字段仅需定义 name、 +- [权限节点配置](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume2/permission.html): 实际开发中,查询类权限(page、detail、list)通常合并为一个节点 sys:position:list,减少配置工作量。 +- [Repository 层](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume2/repository.html): Repository 层是数据访问层,封装全部数据库查询操作,本页讲解基于 BaseRepository 基类的通用 CRUD 用法。 +- [路由注册](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume2/router.html): 新模块只需两步: 1. 在 src/api/v1/ 下创建路由文件,定义 routes 列表 2. 在 router.py 的 _RESOURCE_MODULES 中追加模块导入 路由前缀 +- [Pydantic Schema](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume2/schema.html): Schema 层负责请求数据校验,本页讲解基于 Pydantic v2 BaseModel 与 Field 的表单类定义规范。 +- [Service 层](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume2/service.html): repo_cls 是 类属性,值为 Repository 类(不是实例)。 + +## 4. 架构设计 + +- [核心基类体系](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume3/base-classes.html): 四大基类各司其职,覆盖从数据模型到请求校验再到业务逻辑的完整链路。 +- [缓存架构设计](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume3/cache.html): 采用两级缓存架构:第一级为进程内字典缓存(dict_util),第二级为 Redis 分布式缓存。 +- [数据库设计](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume3/database-design.html): 所有业务表继承 base_model 基类,自动获得 6 个通用字段(id / create_user / create_time / update_user / update_time / +- [目录结构设计](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume3/directory.html): 目录结构遵循「按功能分组、按职责分层」的原则。 +- [扩展性设计](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume3/extensibility.html): 遵循开闭原则(OCP):对扩展开放,对修改关闭。 +- [分层架构设计](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume3/layer-arch.html): 采用经典的分层架构,核心原则是:依赖单向、职责单一、接口隔离。 +- [整体架构图](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume3/overview.html): 本页从全局视角阐述系统整体技术架构,涵盖前端、后端、数据库与基础设施等核心组成,理解系统全貌时从本页开始。 +- [请求完整链路](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume3/request-flow.html): 一个典型的 API 请求经过以下阶段:浏览器 → Nginx → Tornado → Handler 生命周期(set_default_headers → prepare → +- [安全架构设计](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume3/security.html): 纵深防御:认证、授权、限流、参数校验多层防护,单一防线失效时仍有其他机制兜底 最小权限:用户仅能访问已授权接口,角色权限按需分配,遵循"够用即可"原则 数据不落地:敏感信息(Token、 +- [技术选型说明](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume3/tech-stack.html): Tornado 是 Python 生态中成熟的异步 Web 框架,基于自有事件循环实现非阻塞 I/O。 +- [Tornado IOLoop 与异步模型](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume3/tornado-async.html): Tornado 基于单线程事件循环(IOLoop),Handler 方法默认为协程(async def)。 + +## 5. 开发指南 + +- [API 接口速查表](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/api-cheatsheet.html): API 接口速查表,按模块分组列出所有 RESTful 接口的请求方法、路径、说明和权限标识。 +- [文章管理](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/business/article.html): 文章管理模块支持富文本编辑、分类关联、封面图片上传、图集管理等功能。 +- [分类管理](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/business/category.html): 分类管理模块用于管理树形分类数据,如文章分类、产品分类等。 +- [行政区划管理](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/business/city.html): 行政区划管理模块提供省市区三级行政区划数据的查询和管理能力,支持树形结构展示和下拉选择。 +- [公告与链接管理](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/business/content.html): 公告、链接、城市是三个简单 CRUD 内容模块,均继承 BaseService,提供标准的增删改查接口。 +- [部门/职级/岗位管理](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/business/dept.html): 部门、职级、岗位是组织架构管理的三个核心模块。 +- [文件模板管理](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/business/file-template.html): 文件模板管理模块提供文件导入导出模板的管理能力,用于维护各种业务场景的 Excel/Word 等模板文件。 +- [定时任务日志](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/business/job-log.html): 定时任务日志模块记录定时任务的执行历史,包括执行时间、执行结果、耗时等信息。 +- [定时任务](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/business/job.html): 定时任务模块基于 APScheduler 实现,支持 Cron 表达式调度、任务执行日志、动态启停等功能。 +- [菜单管理](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/business/menu.html): 菜单管理是 RBAC 权限系统的基础,负责管理系统的导航菜单和权限节点。 +- [参数管理](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/business/param.html): 参数管理模块用于管理动态系统参数,与系统配置模块类似但更侧重于业务参数的灵活配置。 +- [角色管理](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/business/role.html): 角色是 RBAC 权限模型的核心,连接用户和菜单(权限)。 +- [用户管理](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/business/user.html): 用户管理是系统的核心模块,属于复杂业务模块。 +- [认证流程实战](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/core/auth-flow.html): 登录 → Token 获取 → 权限校验 → Token 刷新 → 退出登录的完整认证链路实战说明。 +- [验证码机制](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/core/captcha.html): 验证码是防止自动化攻击的重要安全手段。 +- [系统配置管理](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/core/config.html): 系统配置模块用于管理动态的键值对配置项,与数据字典类似但更偏向系统级参数。 +- [CORS 跨域配置](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/core/cors.html): CORS(Cross-Origin Resource Sharing)跨域资源共享是前后端分离架构必须处理的问题。 +- [演示模式](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/core/demo-mode.html): 演示模式用于在线体验环境,开启后所有写操作(新增、编辑、删除等)将被拦截,返回"演示环境,暂无操作权限"提示。 +- [数据字典使用指南](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/core/dict-guide.html): 数据字典的完整使用流程,从新增字典类型到在代码中使用字典数据的实操指南。 +- [字典模块](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/core/dict.html): 数据字典用于管理系统中的枚举值和配置项,如状态、类型、性别等。 +- [异常与响应处理](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/core/exception.html): 定义了统一的响应格式和全局异常处理机制。 +- [优雅关闭](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/core/graceful-shutdown.html): 优雅关闭确保应用在收到终止信号时,能够完成正在处理的请求、关闭数据库连接、停止定时任务调度器后再退出,避免请求中断和资源泄漏。 +- [用户认证(JWT)](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/core/jwt.html): JWT(JSON Web Token)是的核心认证机制。 +- [登录日志](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/core/login-log.html): 登录日志记录每次登录尝试(成功/失败),包含登录账号、IP地址、浏览器信息、登录时间等。 +- [登录防爆破](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/core/login-protect.html): 登录防爆破机制基于 Redis 实现同一 IP + 用户名维度的连续失败计数与锁定,防止暴力破解密码。 +- [操作日志](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/core/operation-log.html): 操作日志装饰器自动记录写请求(POST/PUT/DELETE/PATCH)的操作日志,无需手动埋点。 +- [权限管理(RBAC)](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/core/rbac.html): 采用基于角色的访问控制(RBAC)模型,通过用户-角色-菜单三层关系实现细粒度的权限管理。 +- [链路追踪(TraceID)](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/core/trace-id.html): 链路追踪通过为每个请求分配唯一的 TraceID,将同一请求的所有日志串联起来,方便问题排查和性能分析。 +- [参数验证(Pydantic)](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/core/validator.html): 使用 Pydantic v2 进行请求参数验证。 +- [API 层开发](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/frontend/api.html): 前端 API 层位于 src/api/ 目录,封装所有与后端的 HTTP 请求。 +- [前端构建](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/frontend/build.html): 前端使用 Vite 构建,支持开发服务器和生产构建。 +- [公共组件库](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/frontend/components.html): 项目提供丰富的公共组件,位于 ui/src/components/ 目录,基于 AntDesign 二次封装,覆盖表格、表单、弹窗、上传、富文本编辑等常见场景。 +- [BasicForm 表单](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/frontend/form.html): BasicForm 位于 src/components/Form/src/BasicForm.vue,基于 AntDesign 的 a-form 二次封装,通过 schemas 配置化定义表单字段, +- [Hooks 组合式函数](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/frontend/hooks.html): 项目封装了一系列组合式函数(Hooks),位于 src/hooks/ 和 src/utils/ 目录,提供权限检查、异步 loading、防重复提交、实时时钟、项目配置等可复用逻辑。 +- [国际化](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/frontend/i18n.html): 当前项目仅支持中文界面,AntDesign 使用中文语言包(zh-cn),所有界面文本直接硬编码在组件中。 +- [Modal 弹窗](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/frontend/modal.html): 项目提供 BasicModal 组件(src/components/Modal/src/BasicModal.vue)和原生 a-modal 两种弹窗用法。 +- [权限指令 v-perm](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/frontend/perm-directive.html): v-perm 和 v-perms 是项目自定义的 Vue 指令,用于按钮级别的权限控制,无权限时自动从 DOM 中移除元素。 +- [路由与菜单](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/frontend/router.html): 前端路由基于 Vue Router 4 实现动态路由生成,菜单数据从后端获取,通过 generator-routers.ts 递归生成路由表,路由守卫控制登录状态和权限。 +- [前端环境与结构](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/frontend/setup.html): 前端基于 Vue3 + AntDesign 构建,使用 pnpm 作为包管理工具,Vite 作为构建工具,TypeScript 作为开发语言。 +- [Store 状态管理](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/frontend/store.html): 前端使用 Pinia 进行状态管理,核心模块包括 user(用户信息与权限)、asyncRoute(动态路由与菜单)、projectSetting(项目配置)、designSetting(主题设计)等。 +- [样式与主题](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/frontend/style.html): 前端样式方案采用 Tailwind CSS + SCSS + AntDesign 主题覆盖,支持深色模式切换。 +- [BasicTable 表格](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/frontend/table.html): BasicTable 位于 src/components/Table/src/Table.vue,基于 AntDesign 的 a-table 二次封装,提供列定义、数据请求、分页、操作列、多选、 +- [工具函数](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/frontend/utils.html): 前端工具函数位于 src/utils/ 目录,提供认证管理、本地存储、日期格式化、树结构操作、文件下载等通用能力。 +- [页面视图开发](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/frontend/view.html): 页面视图位于 src/views/ 目录,每个业务模块遵循 index.vue(列表页)+ edit.vue(编辑弹窗)的标准模式,辅以 columns.ts(列定义)和 +- [接口响应规范](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/integration/api-contract.html): 后端所有接口统一返回 R.ok() / R.failed() 格式的 JSON 响应,前端通过 VAxios 的 transformRequestData 拦截器统一解包处理。 +- [字典数据联调](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/integration/dict-sync.html): 字典数据通过后端字典 API 获取,前端在下拉选择器中渲染选项。 +- [权限节点联动](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/integration/perm-sync.html): 前后端权限通过统一的权限节点字符串联动,后端 @permission_required 校验权限,前端 v-perm 指令和 TableAction 的 auth 属性控制按钮显示。 +- [代理配置](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/integration/proxy.html): 开发环境通过 Vite 代理转发 API 请求到后端,生产环境通过 Nginx 代理。 +- [文件上传联调](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/integration/upload-sync.html): 文件上传涉及前端 Upload 组件、后端上传接口和 URL 拼接三个环节,需要前后端协同配置。 +- [请求上下文(ContextVar)](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/tools/context.html): src/core/context.py 使用 Python 标准库 contextvars 管理请求级别的上下文信息,包括当前用户 ID、用户名、姓名和链路追踪 ID。 +- [数据库会话](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/tools/db-session.html): 数据库会话通过 scoped_session 实现线程级隔离,Repository 层的写操作自动 commit,BaseHandler.on_finish() 兜底关闭会话。 +- [字典缓存工具](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/tools/dict-util.html): src/common/utils/dict_util.py 提供业务字典的缓存读取能力,从 Redis 缓存中获取字典数据,缓存未命中时从数据库加载。 +- [导入导出](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/tools/excel.html): 基于 openpyxl 实现 Excel 导入导出功能,支持通过 file_template 模块管理导入模板配置。 +- [通用 Helper 函数](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/tools/helpers.html): src/common/utils/helpers.py 提供项目中广泛使用的通用工具函数,包括 ID 解析、OS/浏览器检测、参数脱敏等。 +- [IP 归属地解析](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/tools/ip-region.html): src/common/utils/ip2region.py 基于 ip2region 离线数据库,提供 IP 地址到省市区的归属地查询能力,无需网络请求。 +- [日志系统](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/tools/logger.html): 通过 Python 标准库 logging 实现结构化日志,支持控制台 + 文件双输出,日志文件按大小自动轮转。 +- [密码工具](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/tools/password.html): 采用 bcrypt 双重加盐方案存储密码,源码位于 src/core/password.py。 +- [权限缓存](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/tools/perm-cache.html): 通过 Redis 实现用户权限和菜单的缓存,采用用户级缓存 + 全局版本号双层策略。 +- [统一响应封装(R 对象)](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/tools/response.html): src/core/response.py 提供统一的 API 响应封装,所有接口返回格式为 {code, data, msg, ok}。 +- [富文本过滤](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/tools/rich-text.html): 富文本编辑器内容存在存储型 XSS 风险,通过 bleach 库实现 HTML 白名单清洗,在落盘前统一过滤危险内容。 +- [文件上传完整流程](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/tools/upload-guide.html): 富文本编辑器(如 TinyMCE、CKEditor、WangEditor 等)的图片上传同样使用此接口。 +- [文件上传](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume4/tools/upload.html): 提供本地文件上传功能,支持图片和通用文件上传,内置扩展名白名单、大小限制、魔术字节校验和路径遍历防护。 + +## 6. 代码生成器 + +- [CLI 命令行使用](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume5/cli.html): 代码生成器 CLI 模式的使用方法,包括单表生成、批量生成、预览模式和配置导出。 +- [代码生成引擎](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume5/code-engine.html): 代码生成引擎的工作原理,包括配置解析、模板渲染、文件写入和自动注册的完整流程。 +- [配置文件详解](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume5/config.html): 代码生成器 JSON 配置文件的格式说明,包括模块名称、字段属性、字典编码等配置项的详细解释。 +- [实战案例](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume5/demo.html): 以 tornado_example 演示表为完整案例,演示从建表到生成到使用的全流程。 +- [常见问题](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume5/faq.html): 代码生成器使用过程中常见问题的原因分析和解决方案。 +- [概述与架构](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume5/overview.html): 代码生成器的整体架构、核心模块和生成流程概述。 +- [表结构解析引擎](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume5/parser.html): 表结构解析引擎的工作原理,从数据库读取表元数据并智能推断字段用途的过程。 +- [自定义模板](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume5/templates.html): 代码生成器模板的 Jinja2 语法说明,包括模板变量、字段属性和自定义模板的开发方法。 +- [Web 管理界面](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume5/web-ui.html): 代码生成器 Web 管理界面的使用方法,通过可视化界面操作单表生成和批量生成。 + +## 7. 运维部署 + +- [备份与恢复](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume6/backup.html): - 3 份数据副本(1 份生产 + 2 份备份) - 2 种不同存储介质(如本地磁盘 + 远程存储) - 1 份异地备份(防机房级灾难) +- [跨库数据迁移](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume6/db-cross-migrate.html): 项目提供 scripts/migrate_db.py 脚本,支持在不同数据库之间迁移数据(如 MySQL → PostgreSQL / SQL Server / SQLite / Oracle)。 +- [数据库迁移](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume6/db-migrate.html): - 结构迁移:Alembic(自动生成 DDL 差异) - 数据迁移:scripts/migrate_db.py(跨库数据泵) - 初始化:scripts/init_db.py(全新安装一键建库) +- [部署 Checklist](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume6/deploy-checklist.html): 从服务器准备到应用上线的完整部署操作清单,适用于生产环境首次部署和后续版本更新。 +- [Docker容器化](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume6/docker.html): - 环境一致性:消除"在我机器上能跑"的问题 - 快速部署:一条命令启动完整服务 - 资源隔离:应用与宿主机环境解耦 +- [环境规划](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume6/env-plan.html): 各环境之间保持代码一致,仅通过环境变量(.env)区分配置。 +- [健康检查与监控](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume6/monitoring.html): `` 1. 应用层:健康检查端点、业务指标 2. 系统层:CPU/内存/磁盘/网络 3. 中间件:MySQL/Redis 连接状态 4. 日志:集中式日志收集与分析 `` +- [Nginx 反向代理](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume6/nginx.html): `` 客户端 → Nginx(80/443) ├─ / → 前端静态资源(dist/) ├─ /api/v1/... → Tornado 后端(8041) └─ /api/file/ → +- [性能调优](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume6/performance.html): 1. 先测量,后优化:用数据说话,避免盲目调参 2. 瓶颈优先:找到最大瓶颈,集中优化 3. 渐进式:每次只调整一个参数,观察效果 +- [安全加固](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume6/security-hardening.html): - 最小权限:只开放必要的端口和权限 - 纵深防御:多层安全措施叠加 - 默认安全:配置默认值应为安全选项 +- [Supervisor进程管理](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume6/supervisor.html): - Linux 服务器直接部署(非 Docker) - 需要进程自动重启和日志轮转 - 管理多个相关进程 +- [故障排查手册](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume6/troubleshooting.html): 1. 查看日志:tail -f logs/supervisor.out.log 或 docker-compose logs -f 2. 检查配置:.env 文件、数据库连接、Redis 连接 3. +- [版本升级流程](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume6/upgrade.html): 1. 先备份,后升级 2. 先测试环境,后生产环境 3. 每次升级可回滚 4. 低峰期执行升级 + +## 8. 规范标准 + +- [API响应规范](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume7/api-response.html): - 所有接口必须通过 R.ok() 或 R.failed() 返回,禁止直接返回 dict - 成功响应 code=0,失败响应 code=1 - 响应体始终包含 code、data、msg、ok +- [代码审查清单](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume7/code-review.html): - 每次提交必须经过至少一人审查 - 审查关注点:正确性 > 安全性 > 可维护性 > 性能 - 审查意见应具体、可操作,避免主观评价 +- [删除规范](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume7/deletion.html): - is_delete = 0:正常记录(默认值) - is_delete = 1:已删除记录 - 所有查询方法自动过滤 is_delete = 0,业务层无需关心 +- [文档规范](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume7/doc-standard.html): - 文档与代码同步更新 - 使用中文编写(项目约定) - 示例代码可直接运行 +- [前端 API 规范](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume7/fe-api.html): - 每个后端模块对应一个 API 文件 - 函数命名统一使用 名词 + 动词 格式(与后端保持一致) - 请求路径使用相对路径(/position/page),不含 /api/v1 前缀(由 +- [前端页面规范](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume7/fe-component.html): - Vue3(Composition API + <script setup>) - AntDesign - 自定义组件(BasicTable / BasicForm / TableAction / +- [Git提交规范](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume7/git.html): `` <type>(<scope>): <subject> <body> <footer> `` +- [Handler 层规范](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume7/handler.html): - Handler 只做请求分发,不含业务逻辑 - 通过装饰器控制权限和演示模式 - 委托 Service 处理业务逻辑 - 返回 R 封装的响应 +- [分页规范](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume7/pagination.html): - 前端传递 pageNo(页码,从 1 开始)和 pageSize(每页条数) - 后端返回 {records, total, size, current, pages} 结构 - 默认每页 10 +- [Pydantic Schema规范](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume7/pydantic.html): - 请求体参数必须声明为 Pydantic 模型(Form 类) - 字段约束使用 Field(...) 定义 - 自定义校验使用 @field_validator - 唯一性校验在 Schema +- [Repository层规范](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume7/repository.html): - Repository 只做数据访问原语,不处理 R 封装/序列化/业务逻辑 - 软删除由基类自动处理,子类无需关心 - 查询方法自动跳过 None 值条件 +- [Service层规范](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume7/service.html): BaseService 采用模板方法模式:基类定义流程骨架,子类通过声明差异点和覆盖钩子定制行为。 +- [测试规范](http://docs.tornado.antdvue.djangoadmin.cn/zh/volume7/testing.html): 1. 契约测试(Contract):验证路由、权限、表名等契约不变 2. 单元测试(Unit):验证单个函数/方法的逻辑正确性 3. 集成测试(Integration):验证模块间协作、真实数据库操作 + +## 附录 + +- [常见问题汇总](http://docs.tornado.antdvue.djangoadmin.cn/zh/faq.html): 本页汇总了项目各模块的常见问题及解决方案,按场景分类索引。 +- [免责声明](http://docs.tornado.antdvue.djangoadmin.cn/zh/other/declare.html): 使用本产品前必读的法律声明,明确产品性质、使用限制与责任划分,一旦使用本产品即视为接受本声明全部条款。 +- [广告赞助](http://docs.tornado.antdvue.djangoadmin.cn/zh/other/sponsor.html): 1. 投放广告不得与官方全系产品存在结构性冲突和竞争 2. 广告内容需符合国家法律法规,不得包含虚假、误导性信息 3. 广告素材需经官方审核通过后方可上线,审核周期 1-3 个工作日 4. diff --git a/DjangoAdmin_Tornado_AntdVue/public/robots.txt b/DjangoAdmin_Tornado_AntdVue/public/robots.txt new file mode 100644 index 0000000..cce9ce7 --- /dev/null +++ b/DjangoAdmin_Tornado_AntdVue/public/robots.txt @@ -0,0 +1,33 @@ +# DjangoAdmin Tornado+AntDesign 开发文档 +User-agent: * +Allow: / + +# 显式放行生成式引擎 / AI 爬虫(GEO) +User-agent: GPTBot +Allow: / + +User-agent: ChatGPT-User +Allow: / + +User-agent: ClaudeBot +Allow: / + +User-agent: Claude-Web +Allow: / + +User-agent: anthropic-ai +Allow: / + +User-agent: PerplexityBot +Allow: / + +User-agent: Google-Extended +Allow: / + +User-agent: Bytespider +Allow: / + +User-agent: bingbot +Allow: / + +Sitemap: http://docs.tornado.antdvue.djangoadmin.cn/sitemap.xml diff --git a/DjangoAdmin_Tornado_AntdVue/scripts/generate-llms-txt.mjs b/DjangoAdmin_Tornado_AntdVue/scripts/generate-llms-txt.mjs new file mode 100644 index 0000000..e0f22db --- /dev/null +++ b/DjangoAdmin_Tornado_AntdVue/scripts/generate-llms-txt.mjs @@ -0,0 +1,122 @@ +#!/usr/bin/env node +/** + * 生成 public/llms.txt(llmstxt.org 标准)——AI 爬虫的站点摘要索引。 + * + * 数据源:zh 目录下全部 Markdown 的 H1 + :::tip 概述首句(与 meta + * description 同源,复用 .vitepress/config/extract.mjs)。按侧边栏章节分组。 + * + * 用法:node scripts/generate-llms-txt.mjs + * 已挂入 package.json 的 docs:build 前置步骤。 + */ +import fs from "node:fs"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; +import { + SITE_URL, + SITE_DESCRIPTION, + extractDescription, +} from "../.vitepress/config/extract.mjs"; + +const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); +const ZH = path.join(ROOT, "zh"); + +/** 顶层目录 → 侧边栏章节名(与 .vitepress/config/zh.ts 保持一致) */ +const SECTIONS = [ + ["", "1. 了解项目"], + ["volume1", "2. 快速入门"], + ["volume2", "3. 模块开发实战"], + ["volume3", "4. 架构设计"], + ["volume4", "5. 开发指南"], + ["volume5", "6. 代码生成器"], + ["volume6", "7. 运维部署"], + ["volume7", "8. 规范标准"], + ["other", "附录"], +]; + +function walk(dir, out = []) { + for (const entry of fs.readdirSync(dir, { withFileTypes: true })) { + const p = path.join(dir, entry.name); + if (entry.isDirectory()) walk(p, out); + else if (entry.name.endsWith(".md")) out.push(p); + } + return out; +} + +/** 提取首个 H1 文本 */ +function h1Of(md) { + // 围栏感知:跳过 ``` 代码块内的 # 注释,取真正的页面 H1 + let inFence = false; + for (const line of md.split("\n")) { + if (line.startsWith("```")) { inFence = !inFence; continue; } + if (!inFence && line.startsWith("# ") && !line.startsWith("## ")) { + return line.slice(2).trim(); + } + } + return ""; +} + +/** H1 编号排序键:"5.10 x" → [5,10];无编号排最后 */ +function sortKey(h1) { + const m = h1.match(/^(\d+(?:\.\d+)*)/); + if (m) return m[1].split(".").map(Number); + const letter = h1.match(/^([A-Z])\./); + if (letter) return [1000 + letter[1].charCodeAt(0)]; + return [9999]; +} + +function cmpKey(a, b) { + const len = Math.max(a.length, b.length); + for (let i = 0; i < len; i++) { + const x = a[i] ?? 0; + const y = b[i] ?? 0; + if (x !== y) return x - y; + } + return 0; +} + +const files = walk(ZH); +const groups = new Map(SECTIONS.map(([dir, label]) => [label, []])); + +for (const file of files) { + const rel = path.relative(ZH, file).replace(/\\/g, "/"); + const topDir = rel.includes("/") ? rel.split("/")[0] : ""; + const base = rel.split("/").pop(); + const label = (topDir === "" && base === "faq.md") ? "附录" + : SECTIONS.find(([dir]) => dir === topDir)?.[1] ?? "附录"; + + const md = fs.readFileSync(file, "utf8"); + const h1 = h1Of(md); + if (!h1) continue; + const desc = extractDescription(md); + const url = `${SITE_URL}/zh/${rel.replace(/\.md$/, ".html")}`; + groups.get(label).push({ h1, desc, url, key: sortKey(h1) }); +} + +const lines = [ + "# DjangoAdmin Tornado+AntDesign 开发文档", + "", + `> ${SITE_DESCRIPTION}。内置 RBAC 权限体系、代码生成器等开箱即用功能,支持五种数据库一键切换。本文档共 ${files.length} 篇,按章节组织。`, + "", +]; + +// 按章节顺序输出,合并重复 label(appendix/other 同为「附录」,只输出一次) +const printed = new Set(); +for (const [, label] of SECTIONS) { + if (printed.has(label)) continue; + const items = groups.get(label); + if (!items?.length) continue; + printed.add(label); + + lines.push(`## ${label}`, ""); + items.sort((a, b) => cmpKey(a.key, b.key)); + for (const { h1, desc, url } of items) { + lines.push(desc ? `- [${h1}](${url}): ${desc}` : `- [${h1}](${url})`); + } + lines.push(""); +} + +const out = path.join(ROOT, "public", "llms.txt"); +fs.writeFileSync(out, lines.join("\n"), "utf8"); +console.log( + `llms.txt: ${files.length} 页 → ${path.relative(ROOT, out)} (${printed.size} 个章节)`, +); diff --git a/DjangoAdmin_Tornado_AntdVue/zh/course.md b/DjangoAdmin_Tornado_AntdVue/zh/course.md index f414aa0..829cf20 100644 --- a/DjangoAdmin_Tornado_AntdVue/zh/course.md +++ b/DjangoAdmin_Tornado_AntdVue/zh/course.md @@ -1,3 +1,5 @@ +# 新手入门指南 + :::warning 特别提醒 官方精心制作本教程,目的在于方便用户快速掌握软件产品的使用和部署。通过此教程,刚入行的开发者也可以快速掌握并投入产品研发。本地部署时务必请耐心阅读文档操作。 ::: diff --git a/DjangoAdmin_Tornado_AntdVue/zh/introduction.md b/DjangoAdmin_Tornado_AntdVue/zh/introduction.md index f34f722..60c0bea 100644 --- a/DjangoAdmin_Tornado_AntdVue/zh/introduction.md +++ b/DjangoAdmin_Tornado_AntdVue/zh/introduction.md @@ -1,3 +1,9 @@ +# 项目介绍 + +:::tip 概述 +DjangoAdmin 是企业级中台解决方案,后端基于 Tornado + SQLAlchemy,前端基于 Vue3 + AntDesign,内置 RBAC 权限、代码生成器等开箱即用功能,支持五种数据库一键切换。 +::: + <div align="center"> <p align="center"> <img src="/logo.png" height="150" alt="logo"/> diff --git a/DjangoAdmin_Tornado_AntdVue/zh/other/declare.md b/DjangoAdmin_Tornado_AntdVue/zh/other/declare.md index 7737479..915692a 100644 --- a/DjangoAdmin_Tornado_AntdVue/zh/other/declare.md +++ b/DjangoAdmin_Tornado_AntdVue/zh/other/declare.md @@ -1,5 +1,9 @@ # 免责声明 +:::tip 概述 +使用本产品前必读的法律声明,明确产品性质、使用限制与责任划分,一旦使用本产品即视为接受本声明全部条款。 +::: + :::danger 重要提示 任何用户在使用本团队研发的系列软件产品(以下简称「本产品」)前,请仔细阅读并透彻理解本声明。选择不使用本产品,可随时停止使用;一旦使用本产品,即视为对本声明全部内容的认可和接受。 ::: diff --git a/DjangoAdmin_Tornado_AntdVue/zh/struct.md b/DjangoAdmin_Tornado_AntdVue/zh/struct.md index f5ecc54..743372b 100644 --- a/DjangoAdmin_Tornado_AntdVue/zh/struct.md +++ b/DjangoAdmin_Tornado_AntdVue/zh/struct.md @@ -1,3 +1,5 @@ +# 项目目录结构 + ## 目录说明 在软件开发过程中,优秀的软件目录结构对于项目的组织、开发、维护和扩展至关重要,合理的目录结构能够显著提升开发效率和代码可维护性。 diff --git a/DjangoAdmin_Tornado_AntdVue/zh/volume2/code-list.md b/DjangoAdmin_Tornado_AntdVue/zh/volume2/code-list.md index a9f8039..8a07b8b 100644 --- a/DjangoAdmin_Tornado_AntdVue/zh/volume2/code-list.md +++ b/DjangoAdmin_Tornado_AntdVue/zh/volume2/code-list.md @@ -1,5 +1,9 @@ # 完整代码清单 +:::tip 概述 +本页汇总友链(Link)模块涉及的全部文件代码,开发时可快速查阅与复制对照。 +::: + 本章汇总友链(Link)模块涉及的全部文件,便于开发时快速查阅和复制。 ## 后端文件清单 diff --git a/DjangoAdmin_Tornado_AntdVue/zh/volume2/faq.md b/DjangoAdmin_Tornado_AntdVue/zh/volume2/faq.md index e9c1218..f372f58 100644 --- a/DjangoAdmin_Tornado_AntdVue/zh/volume2/faq.md +++ b/DjangoAdmin_Tornado_AntdVue/zh/volume2/faq.md @@ -1,5 +1,9 @@ # 常见问题与排错 +:::tip 概述 +本页汇总模块开发过程中的常见问题与排错方法,开发受阻时按症状索引即可定位。 +::: + 本章汇总模块开发过程中的常见问题和解决方案。 ## 后端问题 diff --git a/DjangoAdmin_Tornado_AntdVue/zh/volume2/fe-api.md b/DjangoAdmin_Tornado_AntdVue/zh/volume2/fe-api.md index 797cc1c..ae9203a 100644 --- a/DjangoAdmin_Tornado_AntdVue/zh/volume2/fe-api.md +++ b/DjangoAdmin_Tornado_AntdVue/zh/volume2/fe-api.md @@ -1,5 +1,9 @@ # 前端 API 层 +:::tip 概述 +前端 API 层封装后端接口的 HTTP 请求,每个业务模块对应一个 API 文件,本页讲解基于 Axios 封装的编写规范。 +::: + 前端 API 层负责封装后端接口的 HTTP 请求。每个业务模块对应一个 API 文件,使用项目封装的 Axios 工具发送请求。 ## 文件位置 diff --git a/DjangoAdmin_Tornado_AntdVue/zh/volume2/fe-router.md b/DjangoAdmin_Tornado_AntdVue/zh/volume2/fe-router.md index 0f79bbe..5c2330b 100644 --- a/DjangoAdmin_Tornado_AntdVue/zh/volume2/fe-router.md +++ b/DjangoAdmin_Tornado_AntdVue/zh/volume2/fe-router.md @@ -1,5 +1,9 @@ # 前端路由与菜单 +:::tip 概述 +本页讲解前端路由与菜单机制——路由和菜单由后端动态返回,前端只需注册路由组件映射。 +::: + 前端路由定义页面的访问路径,菜单是路由的可视化展示。项目的路由和菜单由后端动态返回,前端只需注册路由组件映射。 ## 路由配置 diff --git a/DjangoAdmin_Tornado_AntdVue/zh/volume2/fe-view.md b/DjangoAdmin_Tornado_AntdVue/zh/volume2/fe-view.md index 43f32df..ee2843f 100644 --- a/DjangoAdmin_Tornado_AntdVue/zh/volume2/fe-view.md +++ b/DjangoAdmin_Tornado_AntdVue/zh/volume2/fe-view.md @@ -1,5 +1,9 @@ # 前端页面视图 +:::tip 概述 +前端页面视图是用户直接交互的界面,本页讲解 Vue3 + AntDesign 下一个完整 CRUD 页面的文件组成与编写方式。 +::: + 前端页面视图是用户直接交互的界面。项目使用 Vue3 + AntDesign + Vite 构建。一个完整的 CRUD 页面由 4 个文件组成: ``` diff --git a/DjangoAdmin_Tornado_AntdVue/zh/volume2/handler.md b/DjangoAdmin_Tornado_AntdVue/zh/volume2/handler.md index 9e36ff4..92cbf81 100644 --- a/DjangoAdmin_Tornado_AntdVue/zh/volume2/handler.md +++ b/DjangoAdmin_Tornado_AntdVue/zh/volume2/handler.md @@ -1,5 +1,9 @@ # 请求处理器(Handler) +:::tip 概述 +Handler 层是 HTTP 接口层,负责接收请求、校验权限与记录操作日志,编写新接口从本页开始。 +::: + Handler 层是 HTTP 接口层,负责接收请求、校验权限、记录操作日志,然后委托给 Service 层处理。每个业务模块对应一个 `handlers.py` 文件,所有 Handler 继承 `BaseHandler`。 ## 文件位置 diff --git a/DjangoAdmin_Tornado_AntdVue/zh/volume2/repository.md b/DjangoAdmin_Tornado_AntdVue/zh/volume2/repository.md index e03b9b2..8009a30 100644 --- a/DjangoAdmin_Tornado_AntdVue/zh/volume2/repository.md +++ b/DjangoAdmin_Tornado_AntdVue/zh/volume2/repository.md @@ -1,5 +1,9 @@ # Repository 层 +:::tip 概述 +Repository 层是数据访问层,封装全部数据库查询操作,本页讲解基于 BaseRepository 基类的通用 CRUD 用法。 +::: + Repository 层是数据访问层,封装所有数据库查询操作。项目通过 `BaseRepository` 基类提供通用 CRUD 能力,子类通常只需声明类名,无需编写任何代码。 ## 文件位置 diff --git a/DjangoAdmin_Tornado_AntdVue/zh/volume2/schema.md b/DjangoAdmin_Tornado_AntdVue/zh/volume2/schema.md index 4069def..7917550 100644 --- a/DjangoAdmin_Tornado_AntdVue/zh/volume2/schema.md +++ b/DjangoAdmin_Tornado_AntdVue/zh/volume2/schema.md @@ -1,5 +1,9 @@ # Pydantic Schema +:::tip 概述 +Schema 层负责请求数据校验,本页讲解基于 Pydantic v2 BaseModel 与 Field 的表单类定义规范。 +::: + Schema 层负责请求数据的校验。项目使用 Pydantic v2 的 `BaseModel` 定义表单类,通过 `Field` 约束字段格式,Tornado 在接收请求体时自动执行校验。 ## 文件位置 diff --git a/DjangoAdmin_Tornado_AntdVue/zh/volume3/overview.md b/DjangoAdmin_Tornado_AntdVue/zh/volume3/overview.md index 17b25de..b8b63fd 100644 --- a/DjangoAdmin_Tornado_AntdVue/zh/volume3/overview.md +++ b/DjangoAdmin_Tornado_AntdVue/zh/volume3/overview.md @@ -1,5 +1,9 @@ # 整体架构图 +:::tip 概述 +本页从全局视角阐述系统整体技术架构,涵盖前端、后端、数据库与基础设施等核心组成,理解系统全貌时从本页开始。 +::: + 本章从全局视角阐述系统的整体技术架构,涵盖前端、后端、数据库及基础设施等核心组成部分。 ## 架构总览 diff --git a/DjangoAdmin_Tornado_AntdVue/zh/volume4/business/article.md b/DjangoAdmin_Tornado_AntdVue/zh/volume4/business/article.md index a29edc0..407a1a9 100644 --- a/DjangoAdmin_Tornado_AntdVue/zh/volume4/business/article.md +++ b/DjangoAdmin_Tornado_AntdVue/zh/volume4/business/article.md @@ -1,3 +1,5 @@ +# 文章管理 + :::tip 文章管理 文章管理模块支持富文本编辑、分类关联、封面图片上传、图集管理等功能。适用于新闻、公告、帮助文档等内容管理场景。本模块是典型的「带文件处理」业务模块,涵盖了封面迁移、图集处理、富文本 XSS 清洗等核心机制。 ::: diff --git a/DjangoAdmin_Tornado_AntdVue/zh/volume4/business/category.md b/DjangoAdmin_Tornado_AntdVue/zh/volume4/business/category.md index 9882ab0..c512819 100644 --- a/DjangoAdmin_Tornado_AntdVue/zh/volume4/business/category.md +++ b/DjangoAdmin_Tornado_AntdVue/zh/volume4/business/category.md @@ -1,3 +1,5 @@ +# 分类管理 + :::tip 分类管理 分类管理模块用于管理树形分类数据,如文章分类、产品分类等。通过 `parent_id` 字段实现无限级分类。 ::: diff --git a/DjangoAdmin_Tornado_AntdVue/zh/volume4/business/content.md b/DjangoAdmin_Tornado_AntdVue/zh/volume4/business/content.md index 1d13da6..c34a44b 100644 --- a/DjangoAdmin_Tornado_AntdVue/zh/volume4/business/content.md +++ b/DjangoAdmin_Tornado_AntdVue/zh/volume4/business/content.md @@ -1,3 +1,5 @@ +# 公告与链接管理 + :::tip 公告/链接/城市 公告、链接、城市是三个简单 CRUD 内容模块,均继承 BaseService,提供标准的增删改查接口。适用于系统公告、友情链接、城市数据等场景。 ::: diff --git a/DjangoAdmin_Tornado_AntdVue/zh/volume4/business/dept.md b/DjangoAdmin_Tornado_AntdVue/zh/volume4/business/dept.md index 8759e6d..f3a6c15 100644 --- a/DjangoAdmin_Tornado_AntdVue/zh/volume4/business/dept.md +++ b/DjangoAdmin_Tornado_AntdVue/zh/volume4/business/dept.md @@ -1,3 +1,5 @@ +# 部门/职级/岗位管理 + :::tip 部门/职级/岗位 部门、职级、岗位是组织架构管理的三个核心模块。部门采用树形结构,职级和岗位为简单 CRUD 模块,均继承 `BaseService`。用户表通过 `dept_id`、`position_id`、`level_id` 三个外键关联这三个模块。 ::: diff --git a/DjangoAdmin_Tornado_AntdVue/zh/volume4/business/job.md b/DjangoAdmin_Tornado_AntdVue/zh/volume4/business/job.md index bab60c1..0e4cfd1 100644 --- a/DjangoAdmin_Tornado_AntdVue/zh/volume4/business/job.md +++ b/DjangoAdmin_Tornado_AntdVue/zh/volume4/business/job.md @@ -1,3 +1,5 @@ +# 定时任务 + :::tip 定时任务 定时任务模块基于 APScheduler 实现,支持 Cron 表达式调度、任务执行日志、动态启停等功能。包含 job(任务定义)、job_log(执行日志)、scheduler(调度器)三个子模块。 ::: diff --git a/DjangoAdmin_Tornado_AntdVue/zh/volume4/business/menu.md b/DjangoAdmin_Tornado_AntdVue/zh/volume4/business/menu.md index 48b3b0d..5590488 100644 --- a/DjangoAdmin_Tornado_AntdVue/zh/volume4/business/menu.md +++ b/DjangoAdmin_Tornado_AntdVue/zh/volume4/business/menu.md @@ -1,3 +1,5 @@ +# 菜单管理 + :::tip 菜单管理 菜单管理是 RBAC 权限系统的基础,负责管理系统的导航菜单和权限节点。支持目录/菜单(type=0)和权限按钮节点(type=1)两种类型,通过树形结构组织。权限节点由系统根据前端勾选自动生成,采用 `sys:module:action` 三段式命名。 ::: diff --git a/DjangoAdmin_Tornado_AntdVue/zh/volume4/business/param.md b/DjangoAdmin_Tornado_AntdVue/zh/volume4/business/param.md index 79448fe..a98c3ef 100644 --- a/DjangoAdmin_Tornado_AntdVue/zh/volume4/business/param.md +++ b/DjangoAdmin_Tornado_AntdVue/zh/volume4/business/param.md @@ -1,3 +1,5 @@ +# 参数管理 + :::tip 参数管理 参数管理模块用于管理动态系统参数,与系统配置模块类似但更侧重于业务参数的灵活配置。支持按参数键查询、修改,无需重启服务即可生效。本模块是典型的「BaseService 简单模块」,通过声明差异点即可获得完整 CRUD 能力。 ::: diff --git a/DjangoAdmin_Tornado_AntdVue/zh/volume4/business/role.md b/DjangoAdmin_Tornado_AntdVue/zh/volume4/business/role.md index 44aea0b..8dd9813 100644 --- a/DjangoAdmin_Tornado_AntdVue/zh/volume4/business/role.md +++ b/DjangoAdmin_Tornado_AntdVue/zh/volume4/business/role.md @@ -1,3 +1,5 @@ +# 角色管理 + :::tip 角色管理 角色是 RBAC 权限模型的核心,连接用户和菜单(权限)。通过为角色分配菜单权限,再将角色分配给用户,实现灵活的权限管理。角色删除时需清理关联的用户角色和角色菜单数据,并即时失效受影响用户的权限缓存。 ::: diff --git a/DjangoAdmin_Tornado_AntdVue/zh/volume4/business/user.md b/DjangoAdmin_Tornado_AntdVue/zh/volume4/business/user.md index d1d07c0..8fb95e6 100644 --- a/DjangoAdmin_Tornado_AntdVue/zh/volume4/business/user.md +++ b/DjangoAdmin_Tornado_AntdVue/zh/volume4/business/user.md @@ -1,3 +1,5 @@ +# 用户管理 + :::tip 用户管理 用户管理是系统的核心模块,属于复杂业务模块。包含用户 CRUD、角色关联、密码加密、行政区划、Excel 导入导出等功能。与简单 CRUD 模块不同,用户管理使用自定义 service 函数而非继承 BaseService 的类方法。 ::: diff --git a/DjangoAdmin_Tornado_AntdVue/zh/volume4/core/captcha.md b/DjangoAdmin_Tornado_AntdVue/zh/volume4/core/captcha.md index cc7daf8..a7c973b 100644 --- a/DjangoAdmin_Tornado_AntdVue/zh/volume4/core/captcha.md +++ b/DjangoAdmin_Tornado_AntdVue/zh/volume4/core/captcha.md @@ -1,3 +1,5 @@ +# 验证码机制 + :::tip 验证码 验证码是防止自动化攻击的重要安全手段。使用 Pillow 生成图片验证码,存储在 Redis 中,支持防刷限流和万能验证码(演示模式)。源码位于 `src/common/utils/captcha.py`。 ::: diff --git a/DjangoAdmin_Tornado_AntdVue/zh/volume4/core/config.md b/DjangoAdmin_Tornado_AntdVue/zh/volume4/core/config.md index c392d52..0a7b654 100644 --- a/DjangoAdmin_Tornado_AntdVue/zh/volume4/core/config.md +++ b/DjangoAdmin_Tornado_AntdVue/zh/volume4/core/config.md @@ -1,3 +1,5 @@ +# 系统配置管理 + :::tip 系统配置 系统配置模块用于管理动态的键值对配置项,与数据字典类似但更偏向系统级参数。支持分组管理,可通过接口动态修改,无需重启服务。模块位于 `src/modules/config/` 和 `src/modules/config_item/`,路由位于 `src/api/v1/config.py` 和 `config_item.py`。 ::: diff --git a/DjangoAdmin_Tornado_AntdVue/zh/volume4/core/demo-mode.md b/DjangoAdmin_Tornado_AntdVue/zh/volume4/core/demo-mode.md index 272db54..380900a 100644 --- a/DjangoAdmin_Tornado_AntdVue/zh/volume4/core/demo-mode.md +++ b/DjangoAdmin_Tornado_AntdVue/zh/volume4/core/demo-mode.md @@ -1,3 +1,5 @@ +# 演示模式 + :::tip 演示模式 演示模式用于在线体验环境,开启后所有写操作(新增、编辑、删除等)将被拦截,返回"演示环境,暂无操作权限"提示。通过 `TORNADO_DEMO` 环境变量控制。装饰器位于 `src/common/middleware/access_decorators.py`。 ::: diff --git a/DjangoAdmin_Tornado_AntdVue/zh/volume4/core/dict.md b/DjangoAdmin_Tornado_AntdVue/zh/volume4/core/dict.md index eda49ed..de52238 100644 --- a/DjangoAdmin_Tornado_AntdVue/zh/volume4/core/dict.md +++ b/DjangoAdmin_Tornado_AntdVue/zh/volume4/core/dict.md @@ -1,3 +1,5 @@ +# 字典模块 + :::tip 数据字典 数据字典用于管理系统中的枚举值和配置项,如状态、类型、性别等。通过字典编码统一管理,前端可通过 `useDictStore` 获取字典选项,避免硬编码。后端读取工具位于 `src/common/utils/dict_util.py`,内置进程内 TTL 缓存。 ::: diff --git a/DjangoAdmin_Tornado_AntdVue/zh/volume4/core/exception.md b/DjangoAdmin_Tornado_AntdVue/zh/volume4/core/exception.md index 6783f7e..379b7af 100644 --- a/DjangoAdmin_Tornado_AntdVue/zh/volume4/core/exception.md +++ b/DjangoAdmin_Tornado_AntdVue/zh/volume4/core/exception.md @@ -1,3 +1,5 @@ +# 异常与响应处理 + :::tip 全局异常与响应 定义了统一的响应格式和全局异常处理机制。所有 API 返回 `{code, data, msg, ok}` 标准格式,异常被捕获后也转换为相同格式。响应函数位于 `src/core/response.py`,异常类型位于 `src/core/exceptions.py`。 ::: diff --git a/DjangoAdmin_Tornado_AntdVue/zh/volume4/core/jwt.md b/DjangoAdmin_Tornado_AntdVue/zh/volume4/core/jwt.md index 5b22053..a1a54b9 100644 --- a/DjangoAdmin_Tornado_AntdVue/zh/volume4/core/jwt.md +++ b/DjangoAdmin_Tornado_AntdVue/zh/volume4/core/jwt.md @@ -1,3 +1,5 @@ +# 用户认证(JWT) + :::tip JWT认证 JWT(JSON Web Token)是的核心认证机制。用户登录成功后获取 Token,后续请求通过 `Authorization: Bearer <token>` 头携带 Token 进行身份验证。项目内置了 Token 生成、解析、刷新和黑名单管理功能,源码位于 `src/core/jwt.py`。 ::: diff --git a/DjangoAdmin_Tornado_AntdVue/zh/volume4/core/login-log.md b/DjangoAdmin_Tornado_AntdVue/zh/volume4/core/login-log.md index 0a9fc2f..b37a3b3 100644 --- a/DjangoAdmin_Tornado_AntdVue/zh/volume4/core/login-log.md +++ b/DjangoAdmin_Tornado_AntdVue/zh/volume4/core/login-log.md @@ -1,3 +1,5 @@ +# 登录日志 + :::tip 登录日志 登录日志记录每次登录尝试(成功/失败),包含登录账号、IP地址、浏览器信息、登录时间等。支持 IP 地理位置解析(ip2region)和 User-Agent 解析。登录逻辑位于 `src/modules/auth/service.py`,日志记录位于 `src/modules/login_log/service.py`。 ::: diff --git a/DjangoAdmin_Tornado_AntdVue/zh/volume4/core/operation-log.md b/DjangoAdmin_Tornado_AntdVue/zh/volume4/core/operation-log.md index 3200aa9..35c01e9 100644 --- a/DjangoAdmin_Tornado_AntdVue/zh/volume4/core/operation-log.md +++ b/DjangoAdmin_Tornado_AntdVue/zh/volume4/core/operation-log.md @@ -1,3 +1,5 @@ +# 操作日志 + :::tip 操作日志 操作日志装饰器自动记录写请求(POST/PUT/DELETE/PATCH)的操作日志,无需手动埋点。源码位于 `src/common/middleware/operation_log.py`。 ::: diff --git a/DjangoAdmin_Tornado_AntdVue/zh/volume4/core/rbac.md b/DjangoAdmin_Tornado_AntdVue/zh/volume4/core/rbac.md index 8477416..e0709e6 100644 --- a/DjangoAdmin_Tornado_AntdVue/zh/volume4/core/rbac.md +++ b/DjangoAdmin_Tornado_AntdVue/zh/volume4/core/rbac.md @@ -1,3 +1,5 @@ +# 权限管理(RBAC) + :::tip RBAC权限 采用基于角色的访问控制(RBAC)模型,通过用户-角色-菜单三层关系实现细粒度的权限管理。权限控制贯穿前后端:后端通过 `@permission_required` 装饰器校验(`src/common/middleware/access_decorators.py`),前端通过 `v-perm` 指令控制按钮显隐。 ::: diff --git a/DjangoAdmin_Tornado_AntdVue/zh/volume4/core/validator.md b/DjangoAdmin_Tornado_AntdVue/zh/volume4/core/validator.md index c78e4ef..519dab4 100644 --- a/DjangoAdmin_Tornado_AntdVue/zh/volume4/core/validator.md +++ b/DjangoAdmin_Tornado_AntdVue/zh/volume4/core/validator.md @@ -1,3 +1,5 @@ +# 参数验证(Pydantic) + :::tip 参数验证 使用 Pydantic v2 进行请求参数验证。所有请求体参数通过 Pydantic BaseModel 定义,Tornado 自动解析和验证 JSON 请求体,验证失败返回标准格式错误信息。BaseSchema 基类位于 `src/core/base_schema.py`。 ::: diff --git a/DjangoAdmin_Tornado_AntdVue/zh/why.md b/DjangoAdmin_Tornado_AntdVue/zh/why.md index 058b38a..d37f1fb 100644 --- a/DjangoAdmin_Tornado_AntdVue/zh/why.md +++ b/DjangoAdmin_Tornado_AntdVue/zh/why.md @@ -1,7 +1,7 @@ # 为什么选择我们? :::tip 核心价值 -企业级数据中台不应从零搭建。本框架提供开箱即用的完整解决方案,为中大型企业构建统一的数字化基座。 +本框架提供开箱即用的企业级中台完整解决方案,免去从零搭建成本,助力中大型企业构建统一的数字化基座。 ::: ## 解决什么问题? diff --git a/DjangoAdmin_Tornado_EleVue/.vitepress/config/en.ts b/DjangoAdmin_Tornado_EleVue/.vitepress/config/en.ts index a1a96ef..db48db7 100644 --- a/DjangoAdmin_Tornado_EleVue/.vitepress/config/en.ts +++ b/DjangoAdmin_Tornado_EleVue/.vitepress/config/en.ts @@ -29,7 +29,7 @@ // // themeConfig: { // editLink: { -// pattern: "https://gitee.com/djangoadmin/DjangoAdmin_Fastapi_EleVue", +// pattern: "https://gitee.com/djangoadmin/DjangoAdmin_Tornado_EleVue", // text: "Suggest changes to this page", // }, // diff --git a/DjangoAdmin_Tornado_EleVue/.vitepress/config/extract.d.mts b/DjangoAdmin_Tornado_EleVue/.vitepress/config/extract.d.mts new file mode 100644 index 0000000..2a46233 --- /dev/null +++ b/DjangoAdmin_Tornado_EleVue/.vitepress/config/extract.d.mts @@ -0,0 +1,5 @@ +export declare const SITE_URL: string; +export declare const SITE_DESCRIPTION: string; +export declare function stripNumberPrefix(title: string): string; +export declare function extractDescription(md: string): string; +export declare function extractFaqs(md: string): { q: string; a: string }[]; diff --git a/DjangoAdmin_Tornado_EleVue/.vitepress/config/extract.mjs b/DjangoAdmin_Tornado_EleVue/.vitepress/config/extract.mjs new file mode 100644 index 0000000..b59ba74 --- /dev/null +++ b/DjangoAdmin_Tornado_EleVue/.vitepress/config/extract.mjs @@ -0,0 +1,130 @@ +/** + * SEO/GEO 共享工具(纯 ESM,零依赖)。 + * + * 同时被两类调用方 import: + * 1. VitePress 配置(.ts,esbuild 打包时内联本文件) + * 2. scripts/generate-llms-txt.mjs(Node 直接运行) + * + * 注意:SITE_URL 是全站唯一 URL 真相源。 + * docs 子域当前 TLS 证书为腾讯 CDN 默认证书(*.cdn.myqcloud.com,校验失败), + * 故暂用 http;证书修复后只需改这里一处。 + */ + +export const SITE_URL = "http://docs.tornado.elevue.djangoadmin.cn"; + +export const SITE_DESCRIPTION = + "DjangoAdmin Tornado+ElementPlus 企业级中台解决方案开发者文档"; + +/** + * 剥离 H1/标题中的章节编号前缀,用于 <title> 与 JSON-LD headline。 + * 例:"5.10 字典模块" → "字典模块";"K. 贡献指南" → "贡献指南"。 + * 页内 H1 与侧边栏编号保持不变,仅影响 SEO 输出。 + */ +export function stripNumberPrefix(title) { + return String(title) + .replace(/^(?:\d+(?:\.\d+)+|[A-Z]\.)\s+/, "") + .trim(); +} + +/** + * 从页面 Markdown 提取 meta description: + * 1. 首选 `:::tip xxx` 容器内的首句(141/143 页的标准 opener) + * 2. 回退到 H1 后的第一个普通段落 + * 输出压缩为单行、去除行内 Markdown,按中文句末标点截断(≤100 字符)。 + */ +export function extractDescription(md) { + const src = String(md); + const fm = src.match(/^---\r?\n([\s\S]*?)\r?\n---/); + const body = fm ? src.slice(fm[0].length) : src; + + let text = ""; + // frontmatter description 显式声明优先(无 H1 页面的补齐手段) + const fmDesc = fm && fm[1].match(/^description:\s*(.+)$/m); + if (fmDesc) { + text = fmDesc[1].trim().replace(/^["']|["']$/g, ""); + } + const tip = !text && body.match(/^:::\s*tip[^\n]*\n([\s\S]*?)\n:::/m); + if (tip) { + text = tip[1]; + } + if (!text) { + const afterH1 = body.match(/^# (?!#)(.+)$/m); + if (afterH1) { + const rest = body.slice((afterH1.index ?? 0) + afterH1[0].length); + const para = rest + .split(/\n{2,}/) + .find( + (p) => + p.trim() && + !/^\s*#/.test(p) && + !/^\s*:::/.test(p) && + !/^\s*```/.test(p) && + !/^\s*\|/.test(p), + ); + text = para || ""; + } + } + + text = text + .replace(/\s+/g, " ") + .replace(/`([^`]+)`/g, "$1") + .replace(/\*\*([^*]+)\*\*/g, "$1") + .replace(/\[([^\]]+)\]\([^)]*\)/g, "$1") + .trim(); + + if (!text) return ""; + + // 按中文句末标点截取首句,上限 100 字符;截断时避免切碎词 + const m = text.match(/^.{1,100}?(?:[。!?!?]|$)/); + let out = m ? m[0] : text.slice(0, 100); + if (out.length < text.length && !/[。!?!?]$/.test(out)) { + out = out.replace(/[^\s,、;:,;:]+$/, ""); + } + return out.trim() || text.slice(0, 100); +} + +function cleanText(s) { + return s + .replace(/^:::[^\n]*$/gm, "") + .replace(/^```[^\n]*$/gm, "") + .replace(/`([^`]+)`/g, "$1") + .replace(/\*\*([^*]+)\*\*/g, "$1") + .replace(/\[([^\]]+)\]\([^)]*\)/g, "$1") + .replace(/\s+/g, " ") + .trim(); +} + +/** + * 提取页面中的 Q/A 对(用于 FAQPage JSON-LD),支持两种站内格式: + * A. `### Q:问题` 标题式(如 zh/quickstart/faq.md) + * B. `**Q:问题**` 加粗式(如 zh/appendix/faq.md) + * 返回 [{ q, a }];无匹配返回 []。 + */ +export function extractFaqs(md) { + const body = String(md).replace(/^---[\s\S]*?\n---\s*/, ""); + let faqs = []; + + // 格式 A:按 `### Q:` 切块,答案截断到下一个标题 + for (const part of body.split(/(?=^###\s*Q[::])/m)) { + const m = part.match(/^###\s*Q[::]\s*([^\n]+)\n+([\s\S]*)/); + if (!m) continue; + let a = m[2]; + const cut = a.search(/^#{1,4}\s/m); + if (cut >= 0) a = a.slice(0, cut); + faqs.push({ q: cleanText(m[1]), a: cleanText(a) }); + } + + // 格式 B:按 `**Q:` 切块 + if (!faqs.length) { + for (const part of body.split(/(?=^\*\*Q[::])/m)) { + const m = part.match(/^\*\*Q[::]\s*([^*]+)\*\*\s*\n+([\s\S]*)/); + if (!m) continue; + let a = m[2]; + const cut = a.search(/^(?:#{1,4}\s|\*\*Q)/m); + if (cut >= 0) a = a.slice(0, cut); + faqs.push({ q: cleanText(m[1]), a: cleanText(a) }); + } + } + + return faqs.filter((f) => f.q && f.a); +} diff --git a/DjangoAdmin_Tornado_EleVue/.vitepress/config/index.ts b/DjangoAdmin_Tornado_EleVue/.vitepress/config/index.ts index 2294856..6627a76 100644 --- a/DjangoAdmin_Tornado_EleVue/.vitepress/config/index.ts +++ b/DjangoAdmin_Tornado_EleVue/.vitepress/config/index.ts @@ -1,14 +1,22 @@ import { defineConfig } from "vitepress"; import { enConfig } from "./en"; +import { createSeoHooks } from "./seo"; import { sharedConfig } from "./shared"; import { zhConfig } from "./zh"; +const seo = createSeoHooks(zhConfig.themeConfig?.sidebar); + export default defineConfig({ ...sharedConfig, ignoreDeadLinks: [ (link) => link.includes('localhost'), ], + // SEO:页面级 title/description、canonical/OG/JSON-LD、sitemap+lastmod + transformPageData: seo.transformPageData, + transformHead: seo.transformHead, + sitemap: seo.sitemap, + locales: { root: { label: "简体中文", lang: "zh-CN", link: "/", ...zhConfig }, // root: { label: "English", lang: "en-US", link: "/", ...enConfig }, diff --git a/DjangoAdmin_Tornado_EleVue/.vitepress/config/seo.ts b/DjangoAdmin_Tornado_EleVue/.vitepress/config/seo.ts new file mode 100644 index 0000000..dbfb190 --- /dev/null +++ b/DjangoAdmin_Tornado_EleVue/.vitepress/config/seo.ts @@ -0,0 +1,311 @@ +/** + * SEO/GEO 构建期钩子(仅 Node 构建时运行,不进客户端 bundle): + * - transformPageData:每页独立 title(去编号前缀)与 description(取 :::tip 首句) + * - transformHead:canonical / Open Graph / twitter 卡片 / JSON-LD 结构化数据 + * - sitemap.transformItems:注入 lastmod(git 最后提交时间)并过滤 404 + * + * 由 config/index.ts 通过 createSeoHooks(zhConfig.themeConfig?.sidebar) 挂载。 + * 依赖 extract.mjs(纯 ESM,同被 scripts/generate-llms-txt.mjs 复用)。 + */ +import fs from "node:fs"; +import path from "node:path"; +import { execSync } from "node:child_process"; +import { + SITE_URL, + extractDescription, + extractFaqs, + stripNumberPrefix, +} from "./extract.mjs"; + +/** 与 vitepress HeadConfig 同构:[tag, attrs, innerHTML?] */ +type HeadTuple = [string, Record<string, any>, string?]; + +interface SideItem { + text?: string; + link?: string; + items?: SideItem[]; +} + +interface PageDataLike { + relativePath?: string; + title?: string; + description?: string; + frontmatter?: Record<string, any>; + [k: string]: any; +} + +interface TransformCtx { + pageData?: PageDataLike; + title?: string; + description?: string; + content?: string; + siteConfig?: { root?: string; srcDir?: string }; +} + +const ORG = { + "@type": "Organization", + name: "DjangoAdmin", + url: "https://www.djangoadmin.cn", + logo: `${SITE_URL}/logo.png`, + sameAs: [ + "https://gitee.com/djangoadmin/DjangoAdmin_Tornado_EleVue", + "https://www.djangoadmin.cn", + ], +}; + +/** 相对路径 → 站内路由(cleanUrls 关闭,正文页带 .html) */ +function routeOf(relativePath: string): string { + if (relativePath === "index.md") return "/"; + if (relativePath === "404.md") return "/404.html"; + return `/${relativePath.replace(/\.md$/, ".html")}`; +} + +/** 去掉侧边栏文案前导 emoji/符号,保留 "1.1 项目介绍" 这类编号文字 */ +function cleanLabel(s?: string): string { + return (s || "").replace(/^[^\p{L}\p{N}]+/u, "").trim(); +} + +/** 从侧边栏构建 route → 面包屑文案链(含分组小节) */ +function buildCrumbMap(sidebar: unknown): Map<string, string[]> { + const map = new Map<string, string[]>(); + const groups: SideItem[] = Array.isArray(sidebar) + ? sidebar + : ((sidebar as Record<string, SideItem[]>)?.["/zh/"] ?? []); + const walk = (items: SideItem[], trail: string[]) => { + for (const item of items) { + if (item.link && item.link.startsWith("/")) { + map.set(item.link, [...trail, cleanLabel(item.text)]); + } else if (item.items?.length) { + walk(item.items, [...trail, cleanLabel(item.text)]); + } + } + }; + for (const group of groups) { + walk(group.items ?? [], [cleanLabel(group.text)].filter(Boolean)); + } + return map; +} + +/** 从渲染后的 HTML 提取 H1 纯文本(JSON-LD headline 须与页面 H1 一致) */ +function h1OfHtml(html?: string): string { + const m = (html || "").match(/<h1[^>]*>([\s\S]*?)<\/h1>/i); + if (!m) return ""; + return m[1] + .replace(/<[^>]+>/g, "") + .replace(/&/g, "&") + .replace(/</g, "<") + .replace(/>/g, ">") + .replace(/"/g, '"') + .replace(/'/g, "'") + .trim(); +} + +/** 从 Markdown 源提取 H1 纯文本(去除行内 markdown 标记) */ +function h1OfMd(md: string): string { + // 围栏感知:跳过 ``` 代码块内的 # 注释,取真正的页面 H1 + let inFence = false; + for (const line of md.split("\n")) { + if (line.startsWith("```")) { inFence = !inFence; continue; } + if (!inFence && /^# (?!#)/.test(line)) { + return line + .replace(/^# /, "") + .replace(/`([^`]+)`/g, "$1") + .replace(/\*\*([^*]+)\*\*/g, "$1") + .trim(); + } + } + return ""; +} + +export function createSeoHooks(sidebar: unknown) { + const crumbs = buildCrumbMap(sidebar); + const projectDirs: string[] = []; + let gitDates: Map<string, string> | null = null; + + const readMd = (relativePath: string, srcDir?: string): string => { + try { + return fs.readFileSync( + path.resolve(srcDir || process.cwd(), relativePath), + "utf8", + ); + } catch { + return ""; + } + }; + + /** + * 项目内每个文件最后一次 git 提交的 ISO 时间。 + * 单次 git log 调用构建全量映射(key = 相对路径,与 pageData.relativePath 一致); + * git 不可用时静默降级(sitemap 无 lastmod、JSON-LD 无 dateModified)。 + */ + const getGitDates = (root: string): Map<string, string> => { + if (gitDates) return gitDates; + gitDates = new Map<string, string>(); + try { + const out = execSync( + "git log --format=:::%cI --name-only --relative -n 500 -- .", + { + cwd: root, + encoding: "utf8", + maxBuffer: 64 * 1024 * 1024, + stdio: ["ignore", "pipe", "ignore"], + }, + ); + let current = ""; + for (const line of out.split(/\r?\n/)) { + if (line.startsWith(":::")) { + current = line.slice(3).trim(); + continue; + } + const file = line.trim(); + if (file && current && !gitDates.has(file)) { + gitDates.set(file, current); + } + } + } catch { + // 降级:无 lastmod / dateModified + } + return gitDates; + }; + + /** 每页独立 title(去 "5.10 " 编号前缀,关键词前置)与 description(:::tip 首句) */ + function transformPageData(pageData: PageDataLike, ctx?: any): Record<string, unknown> { + const srcDir: string | undefined = ctx?.siteConfig?.srcDir; + const root: string | undefined = ctx?.siteConfig?.root; + if (root && !projectDirs.includes(root)) projectDirs.push(root); + + const out: Record<string, unknown> = {}; + const rel = pageData.relativePath; + if (rel && !pageData.frontmatter?.description) { + const desc = extractDescription(readMd(rel, srcDir)); + if (desc) out.description = desc; + } + if (pageData.title) { + out.title = stripNumberPrefix(pageData.title); + } + return out; + } + + /** 构建期注入 canonical / OG / twitter / JSON-LD */ + function transformHead(ctx: TransformCtx): HeadTuple[] { + const rel = ctx?.pageData?.relativePath || ""; + if (!rel || rel === "404.md") return []; + + const route = routeOf(rel); + const url = `${SITE_URL}${route}`; + const title = ctx.pageData?.title || ctx.title || ""; + const desc = ctx.description || ""; + const isHome = rel === "index.md"; + const image = `${SITE_URL}/logo.png`; + + const heads: HeadTuple[] = [ + ["link", { rel: "canonical", href: url }], + ["meta", { property: "og:type", content: isHome ? "website" : "article" }], + ["meta", { property: "og:site_name", content: "DjangoAdmin" }], + ["meta", { property: "og:locale", content: "zh_CN" }], + ["meta", { property: "og:title", content: title }], + ["meta", { property: "og:description", content: desc }], + ["meta", { property: "og:url", content: url }], + ["meta", { property: "og:image", content: image }], + ["meta", { property: "twitter:title", content: title }], + ["meta", { property: "twitter:description", content: desc }], + ["meta", { property: "twitter:url", content: url }], + ["meta", { property: "twitter:image", content: image }], + ]; + + // ---- JSON-LD ---- + const root = ctx.siteConfig?.root || projectDirs[0] || process.cwd(); + const srcDir = ctx.siteConfig?.srcDir || root; + const lastMod = getGitDates(root).get(rel); + const blocks: Record<string, any>[] = []; + + if (isHome) { + blocks.push({ + "@context": "https://schema.org", + "@type": "WebSite", + name: "DjangoAdmin 开发文档", + url: `${SITE_URL}/`, + inLanguage: "zh-CN", + description: desc, + }); + blocks.push({ "@context": "https://schema.org", ...ORG }); + } else { + const md = readMd(rel, srcDir); + const article: Record<string, any> = { + "@context": "https://schema.org", + "@type": "TechArticle", + headline: h1OfMd(md) || h1OfHtml(ctx.content) || title, + description: desc, + url, + inLanguage: "zh-CN", + mainEntityOfPage: { "@type": "WebPage", "@id": url }, + publisher: ORG, + }; + if (lastMod) article.dateModified = lastMod; + blocks.push(article); + + const trail = crumbs.get(route); + if (trail?.length) { + const items: Record<string, any>[] = [ + { "@type": "ListItem", position: 1, name: "首页", item: `${SITE_URL}/` }, + ]; + trail.forEach((name, i) => { + const node: Record<string, any> = { + "@type": "ListItem", + position: i + 2, + name, + }; + if (i === trail.length - 1) node.item = url; + items.push(node); + }); + blocks.push({ + "@context": "https://schema.org", + "@type": "BreadcrumbList", + itemListElement: items, + }); + } + + const faqs = extractFaqs(md); + if (faqs.length) { + blocks.push({ + "@context": "https://schema.org", + "@type": "FAQPage", + mainEntity: faqs.map((f) => ({ + "@type": "Question", + name: f.q, + acceptedAnswer: { "@type": "Answer", text: f.a }, + })), + }); + } + } + + // 转义 "<",防止内容中出现 </script> 破坏注入 + const json = JSON.stringify(blocks).replace(/</g, "\\u003c"); + heads.push(["script", { type: "application/ld+json" }, json]); + return heads; + } + + /** sitemap.xml:过滤 404/README,注入 git lastmod */ + const sitemap = { + hostname: SITE_URL, + transformItems(items: { url: string; lastmod?: string }[]) { + const root = projectDirs[0] || process.cwd(); + const dates = getGitDates(root); + const out: { url: string; lastmod?: string }[] = []; + for (const item of items) { + // ⚠ vitepress 传入的 item.url 是相对路径("404.html"、"zh/x.html"、""), + // 无前导斜杠也无域名——hostname 由 SitemapStream 事后拼接。 + if (/(^|\/)404\.html$/.test(item.url)) continue; // 404 页不收录 + if (/(^|\/)README\.html$/.test(item.url)) continue; // 仓库 README 非文档页 + const p = item.url.replace(/^\//, ""); + const rel = + p === "" || p === "index.html" ? "index.md" : p.replace(/\.html$/, ".md"); + const lastmod = dates.get(rel); + out.push(lastmod ? { ...item, lastmod } : item); + } + return out; + }, + }; + + return { transformPageData, transformHead, sitemap }; +} diff --git a/DjangoAdmin_Tornado_EleVue/.vitepress/config/shared.ts b/DjangoAdmin_Tornado_EleVue/.vitepress/config/shared.ts index bbe394e..199c022 100644 --- a/DjangoAdmin_Tornado_EleVue/.vitepress/config/shared.ts +++ b/DjangoAdmin_Tornado_EleVue/.vitepress/config/shared.ts @@ -1,6 +1,6 @@ import { defineConfig, HeadConfig } from "vitepress"; -export const META_IMAGE = "/social.png"; +export const META_IMAGE = "/logo.png"; const rControl = /[\u0000-\u001f]/g; const rSpecial = /[\s~`!@#$%^&*()\-_+=[\]{}|\\;:"'“”‘’<>,.?/]+/g; @@ -23,6 +23,8 @@ export const slugify = (str: string): string => export const sharedConfig = defineConfig({ title: "小蚂蚁云", + // 页面 <title> 后缀:「环境准备 | DjangoAdmin 开发文档」(index.md frontmatter 可覆盖) + titleTemplate: "DjangoAdmin 开发文档", appearance: "light", markdown: { diff --git a/DjangoAdmin_Tornado_EleVue/.vitepress/config/zh.ts b/DjangoAdmin_Tornado_EleVue/.vitepress/config/zh.ts index 936b35e..8fa89b8 100644 --- a/DjangoAdmin_Tornado_EleVue/.vitepress/config/zh.ts +++ b/DjangoAdmin_Tornado_EleVue/.vitepress/config/zh.ts @@ -1,8 +1,9 @@ import type { DefaultTheme, LocaleSpecificConfig } from "vitepress"; -export const META_URL = "https://www.djangoadmin.cn"; -export const META_TITLE = "企业级中台解决方案"; -export const META_DESCRIPTION = "企业级中台解决方案"; +export const META_URL = "http://docs.tornado.elevue.djangoadmin.cn"; +export const META_TITLE = "DjangoAdmin Tornado+ElementPlus 开发文档"; +export const META_DESCRIPTION = + "DjangoAdmin Tornado+ElementPlus 企业级中台解决方案开发者文档"; export const zhConfig: LocaleSpecificConfig<DefaultTheme.Config> = { description: META_DESCRIPTION, diff --git a/DjangoAdmin_Tornado_EleVue/404.md b/DjangoAdmin_Tornado_EleVue/404.md new file mode 100644 index 0000000..c344b20 --- /dev/null +++ b/DjangoAdmin_Tornado_EleVue/404.md @@ -0,0 +1,12 @@ +--- +head: + - - meta + - name: robots + content: noindex +--- + +# 页面不存在 + +抱歉,您访问的页面不存在或已被移动。 + +[返回首页](/) · [浏览文档](/zh/introduction) diff --git a/DjangoAdmin_Tornado_EleVue/package.json b/DjangoAdmin_Tornado_EleVue/package.json index 77bd941..b5517ed 100644 --- a/DjangoAdmin_Tornado_EleVue/package.json +++ b/DjangoAdmin_Tornado_EleVue/package.json @@ -5,7 +5,8 @@ "type": "module", "scripts": { "docs": "vitepress dev .", - "docs:build": "vitepress build .", + "docs:llms": "node scripts/generate-llms-txt.mjs", + "docs:build": "node scripts/generate-llms-txt.mjs && vitepress build .", "docs:preview": "vitepress preview ." }, "dependencies": { diff --git a/DjangoAdmin_Tornado_EleVue/public/llms.txt b/DjangoAdmin_Tornado_EleVue/public/llms.txt new file mode 100644 index 0000000..b3b0290 --- /dev/null +++ b/DjangoAdmin_Tornado_EleVue/public/llms.txt @@ -0,0 +1,168 @@ +# DjangoAdmin Tornado+ElementPlus 开发文档 + +> DjangoAdmin Tornado+ElementPlus 企业级中台解决方案开发者文档。内置 RBAC 权限体系、代码生成器等开箱即用功能,支持五种数据库一键切换。本文档共 138 篇,按章节组织。 + +## 1. 了解项目 + +- [更新日志](http://docs.tornado.elevue.djangoadmin.cn/zh/changelog.html): 更新日志是项目演进的完整记录,帮助开发者和企业了解每个版本的能力变化与技术演进方向。 +- [新手入门指南](http://docs.tornado.elevue.djangoadmin.cn/zh/course.html): 详细的安装步骤请参考 环境准备 章节。 +- [项目介绍](http://docs.tornado.elevue.djangoadmin.cn/zh/introduction.html): DjangoAdmin 是企业级中台解决方案,后端基于 Tornado + SQLAlchemy,前端基于 Vue3 + ElementPlus,内置 RBAC 权限、代码生成器等开箱即用功能, +- [项目目录结构](http://docs.tornado.elevue.djangoadmin.cn/zh/struct.html): + 保持一致性:目录结构一旦确定,应保持一致性,避免随意更改。 +- [为什么选择我们?](http://docs.tornado.elevue.djangoadmin.cn/zh/why.html): 本框架提供开箱即用的企业级中台完整解决方案,免去从零搭建成本,助力中大型企业构建统一的数字化基座。 + +## 2. 快速入门 + +- [后端启动](http://docs.tornado.elevue.djangoadmin.cn/zh/volume1/backend.html): 启动后端前,请确保已完成 环境准备 章节中的所有软件安装。 +- [数据库初始化](http://docs.tornado.elevue.djangoadmin.cn/zh/volume1/database.html): 数据库初始化前,请确保已完成以下准备工作: 1. 目标数据库服务已启动(如 MySQL 8.0+) 2. .env 文件中的 DB_DRIVER 和数据库连接信息已正确配置 3. Python +- [Docker 快速部署](http://docs.tornado.elevue.djangoadmin.cn/zh/volume1/docker.html): Docker 部署适合快速体验和生产环境。 +- [环境变量速查表](http://docs.tornado.elevue.djangoadmin.cn/zh/volume1/env-vars.html): 1. .env.example 是环境变量模板文件,已提交到版本控制。 +- [环境准备](http://docs.tornado.elevue.djangoadmin.cn/zh/volume1/environment.html): 1. 部分软件安装后需要设置本地环境变量,便于在终端中使用命令。 +- [常见问题FAQ](http://docs.tornado.elevue.djangoadmin.cn/zh/volume1/faq.html): 遇到问题时,建议先查看终端日志输出和浏览器控制台(F12)的错误信息,通常能快速定位问题原因。 +- [第一个接口调试](http://docs.tornado.elevue.djangoadmin.cn/zh/volume1/first-api.html): 开始调试前,请确保已完成以下步骤: 1. 后端服务已启动(参见 后端启动) 2. 数据库已初始化(参见 数据库初始化) 3. Redis 服务已启动 +- [前端启动](http://docs.tornado.elevue.djangoadmin.cn/zh/volume1/frontend.html): 启动前端前,请确保已完成 环境准备 章节中的 Node.js 和 pnpm 安装,并已启动后端服务(参见 后端启动)。 + +## 3. 模块开发实战 + +- [完整代码清单](http://docs.tornado.elevue.djangoadmin.cn/zh/volume2/code-list.html): 本页汇总友链(Link)模块涉及的全部文件代码,开发时可快速查阅与复制对照。 +- [示例模块(Example)](http://docs.tornado.elevue.djangoadmin.cn/zh/volume2/example.html): src/modules/example/ 是一个完整的示例模块,演示了标准 CRUD 模块的六文件结构和开发模式。 +- [常见问题与排错](http://docs.tornado.elevue.djangoadmin.cn/zh/volume2/faq.html): 本页汇总模块开发过程中的常见问题与排错方法,开发受阻时按症状索引即可定位。 +- [前端 API 层](http://docs.tornado.elevue.djangoadmin.cn/zh/volume2/fe-api.html): 前端 API 层封装后端接口的 HTTP 请求,每个业务模块对应一个 API 文件,本页讲解基于 Axios 封装的编写规范。 +- [前端路由与菜单](http://docs.tornado.elevue.djangoadmin.cn/zh/volume2/fe-router.html): 本页讲解前端路由与菜单机制——路由和菜单由后端动态返回,前端只需注册路由组件映射。 +- [前端页面视图](http://docs.tornado.elevue.djangoadmin.cn/zh/volume2/fe-view.html): 前端页面视图是用户直接交互的界面,本页讲解 Vue3 + ElementPlus 下一个完整 CRUD 页面的文件组成与编写方式。 +- [请求处理器(Handler)](http://docs.tornado.elevue.djangoadmin.cn/zh/volume2/handler.html): Handler 层是 HTTP 接口层,负责接收请求、校验权限与记录操作日志,编写新接口从本页开始。 +- [数据模型(Model)](http://docs.tornado.elevue.djangoadmin.cn/zh/volume2/model.html): 数据模型是模块开发的第一步,讲解如何用 SQLAlchemy ORM 与基类定义数据库表结构,新建模块时从本页开始。 +- [概述与目标](http://docs.tornado.elevue.djangoadmin.cn/zh/volume2/overview.html): 其中 id、create_user、create_time、update_user、update_time、is_delete 由基类 BaseModel 自动提供,业务字段仅需定义 name、 +- [权限节点配置](http://docs.tornado.elevue.djangoadmin.cn/zh/volume2/permission.html): 实际开发中,查询类权限(page、detail、list)通常合并为一个节点 sys:position:list,减少配置工作量。 +- [Repository 层](http://docs.tornado.elevue.djangoadmin.cn/zh/volume2/repository.html): Repository 层是数据访问层,封装全部数据库查询操作,本页讲解基于 BaseRepository 基类的通用 CRUD 用法。 +- [路由注册](http://docs.tornado.elevue.djangoadmin.cn/zh/volume2/router.html): 新模块只需两步: 1. 在 src/api/v1/ 下创建路由文件,定义 routes 列表 2. 在 router.py 的 _RESOURCE_MODULES 中追加模块导入 路由前缀 +- [Pydantic Schema](http://docs.tornado.elevue.djangoadmin.cn/zh/volume2/schema.html): Schema 层负责请求数据校验,本页讲解基于 Pydantic v2 BaseModel 与 Field 的表单类定义规范。 +- [Service 层](http://docs.tornado.elevue.djangoadmin.cn/zh/volume2/service.html): repo_cls 是 类属性,值为 Repository 类(不是实例)。 + +## 4. 架构设计 + +- [核心基类体系](http://docs.tornado.elevue.djangoadmin.cn/zh/volume3/base-classes.html): 四大基类各司其职,覆盖从数据模型到请求校验再到业务逻辑的完整链路。 +- [缓存架构设计](http://docs.tornado.elevue.djangoadmin.cn/zh/volume3/cache.html): 采用两级缓存架构:第一级为进程内字典缓存(dict_util),第二级为 Redis 分布式缓存。 +- [数据库设计](http://docs.tornado.elevue.djangoadmin.cn/zh/volume3/database-design.html): 所有业务表继承 base_model 基类,自动获得 6 个通用字段(id / create_user / create_time / update_user / update_time / +- [目录结构设计](http://docs.tornado.elevue.djangoadmin.cn/zh/volume3/directory.html): 目录结构遵循「按功能分组、按职责分层」的原则。 +- [扩展性设计](http://docs.tornado.elevue.djangoadmin.cn/zh/volume3/extensibility.html): 遵循开闭原则(OCP):对扩展开放,对修改关闭。 +- [分层架构设计](http://docs.tornado.elevue.djangoadmin.cn/zh/volume3/layer-arch.html): 采用经典的分层架构,核心原则是:依赖单向、职责单一、接口隔离。 +- [整体架构图](http://docs.tornado.elevue.djangoadmin.cn/zh/volume3/overview.html): 本页从全局视角阐述系统整体技术架构,涵盖前端、后端、数据库与基础设施等核心组成,理解系统全貌时从本页开始。 +- [请求完整链路](http://docs.tornado.elevue.djangoadmin.cn/zh/volume3/request-flow.html): 一个典型的 API 请求经过以下阶段:浏览器 → Nginx → Tornado → Handler 生命周期(set_default_headers → prepare → +- [安全架构设计](http://docs.tornado.elevue.djangoadmin.cn/zh/volume3/security.html): 纵深防御:认证、授权、限流、参数校验多层防护,单一防线失效时仍有其他机制兜底 最小权限:用户仅能访问已授权接口,角色权限按需分配,遵循"够用即可"原则 数据不落地:敏感信息(Token、 +- [技术选型说明](http://docs.tornado.elevue.djangoadmin.cn/zh/volume3/tech-stack.html): Tornado 是 Python 生态中成熟的异步 Web 框架,基于自有事件循环实现非阻塞 I/O。 +- [Tornado IOLoop 与异步模型](http://docs.tornado.elevue.djangoadmin.cn/zh/volume3/tornado-async.html): Tornado 基于单线程事件循环(IOLoop),Handler 方法默认为协程(async def)。 + +## 5. 开发指南 + +- [API 接口速查表](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/api-cheatsheet.html): API 接口速查表,按模块分组列出所有 RESTful 接口的请求方法、路径、说明和权限标识。 +- [文章管理](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/business/article.html): 文章管理模块支持富文本编辑、分类关联、封面图片上传、图集管理等功能。 +- [分类管理](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/business/category.html): 分类管理模块用于管理树形分类数据,如文章分类、产品分类等。 +- [行政区划管理](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/business/city.html): 行政区划管理模块提供省市区三级行政区划数据的查询和管理能力,支持树形结构展示和下拉选择。 +- [公告与链接管理](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/business/content.html): 公告、链接、城市是三个简单 CRUD 内容模块,均继承 BaseService,提供标准的增删改查接口。 +- [部门/职级/岗位管理](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/business/dept.html): 部门、职级、岗位是组织架构管理的三个核心模块。 +- [文件模板管理](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/business/file-template.html): 文件模板管理模块提供文件导入导出模板的管理能力,用于维护各种业务场景的 Excel/Word 等模板文件。 +- [定时任务日志](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/business/job-log.html): 定时任务日志模块记录定时任务的执行历史,包括执行时间、执行结果、耗时等信息。 +- [定时任务](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/business/job.html): 定时任务模块基于 APScheduler 实现,支持 Cron 表达式调度、任务执行日志、动态启停等功能。 +- [菜单管理](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/business/menu.html): 菜单管理是 RBAC 权限系统的基础,负责管理系统的导航菜单和权限节点。 +- [参数管理](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/business/param.html): 参数管理模块用于管理动态系统参数,与系统配置模块类似但更侧重于业务参数的灵活配置。 +- [角色管理](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/business/role.html): 角色是 RBAC 权限模型的核心,连接用户和菜单(权限)。 +- [用户管理](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/business/user.html): 用户管理是系统的核心模块,属于复杂业务模块。 +- [认证流程实战](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/core/auth-flow.html): 登录 → Token 获取 → 权限校验 → Token 刷新 → 退出登录的完整认证链路实战说明。 +- [验证码机制](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/core/captcha.html): 验证码是防止自动化攻击的重要安全手段。 +- [系统配置管理](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/core/config.html): 系统配置模块用于管理动态的键值对配置项,与数据字典类似但更偏向系统级参数。 +- [CORS 跨域配置](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/core/cors.html): CORS(Cross-Origin Resource Sharing)跨域资源共享是前后端分离架构必须处理的问题。 +- [演示模式](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/core/demo-mode.html): 演示模式用于在线体验环境,开启后所有写操作(新增、编辑、删除等)将被拦截,返回"演示环境,暂无操作权限"提示。 +- [数据字典使用指南](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/core/dict-guide.html): 数据字典的完整使用流程,从新增字典类型到在代码中使用字典数据的实操指南。 +- [字典模块](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/core/dict.html): 数据字典用于管理系统中的枚举值和配置项,如状态、类型、性别等。 +- [异常与响应处理](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/core/exception.html): 定义了统一的响应格式和全局异常处理机制。 +- [优雅关闭](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/core/graceful-shutdown.html): 优雅关闭确保应用在收到终止信号时,能够完成正在处理的请求、关闭数据库连接、停止定时任务调度器后再退出,避免请求中断和资源泄漏。 +- [用户认证(JWT)](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/core/jwt.html): JWT(JSON Web Token)是的核心认证机制。 +- [登录日志](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/core/login-log.html): 登录日志记录每次登录尝试(成功/失败),包含登录账号、IP地址、浏览器信息、登录时间等。 +- [登录防爆破](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/core/login-protect.html): 登录防爆破机制基于 Redis 实现同一 IP + 用户名维度的连续失败计数与锁定,防止暴力破解密码。 +- [操作日志](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/core/operation-log.html): 操作日志装饰器自动记录写请求(POST/PUT/DELETE/PATCH)的操作日志,无需手动埋点。 +- [权限管理(RBAC)](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/core/rbac.html): 采用基于角色的访问控制(RBAC)模型,通过用户-角色-菜单三层关系实现细粒度的权限管理。 +- [链路追踪(TraceID)](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/core/trace-id.html): 链路追踪通过为每个请求分配唯一的 TraceID,将同一请求的所有日志串联起来,方便问题排查和性能分析。 +- [参数验证(Pydantic)](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/core/validator.html): 使用 Pydantic v2 进行请求参数验证。 +- [API 层开发](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/frontend/api.html): 前端 API 层位于 src/api/ 目录,封装所有与后端的 HTTP 请求。 +- [前端构建](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/frontend/build.html): 前端使用 Vite 构建,支持开发服务器和生产构建。 +- [公共组件库](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/frontend/components.html): 项目提供丰富的公共组件,位于 ui/src/components/ 目录,基于 ElementPlus 二次封装,覆盖表格、表单、弹窗、上传、富文本编辑等常见场景。 +- [BasicForm 表单](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/frontend/form.html): BasicForm 位于 src/components/Form/src/BasicForm.vue,基于 ElementPlus 的 el-form 二次封装,通过 schemas +- [Hooks 组合式函数](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/frontend/hooks.html): 项目封装了一系列组合式函数(Hooks),位于 src/hooks/ 和 src/utils/ 目录,提供权限检查、异步 loading、防重复提交、实时时钟、项目配置等可复用逻辑。 +- [国际化](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/frontend/i18n.html): 当前项目仅支持中文界面,ElementPlus 使用中文语言包(zh-cn),所有界面文本直接硬编码在组件中。 +- [Modal 弹窗](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/frontend/modal.html): 项目提供 BasicModal 组件(src/components/Modal/src/BasicModal.vue)和原生 el-dialog 两种弹窗用法。 +- [权限指令 v-perm](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/frontend/perm-directive.html): v-perm 和 v-perms 是项目自定义的 Vue 指令,用于按钮级别的权限控制,无权限时自动从 DOM 中移除元素。 +- [路由与菜单](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/frontend/router.html): 前端路由基于 Vue Router 4 实现动态路由生成,菜单数据从后端获取,通过 generator-routers.ts 递归生成路由表,路由守卫控制登录状态和权限。 +- [前端环境与结构](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/frontend/setup.html): 前端基于 Vue3 + ElementPlus 构建,使用 pnpm 作为包管理工具,Vite 作为构建工具,TypeScript 作为开发语言。 +- [Store 状态管理](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/frontend/store.html): 前端使用 Pinia 进行状态管理,核心模块包括 user(用户信息与权限)、asyncRoute(动态路由与菜单)、projectSetting(项目配置)、designSetting(主题设计)等。 +- [样式与主题](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/frontend/style.html): 前端样式方案采用 Tailwind CSS + SCSS + ElementPlus 主题覆盖,支持深色模式切换。 +- [BasicTable 表格](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/frontend/table.html): BasicTable 位于 src/components/Table/src/Table.vue,基于 ElementPlus 的 el-table 二次封装,提供列定义、数据请求、分页、操作列、 +- [工具函数](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/frontend/utils.html): 前端工具函数位于 src/utils/ 目录,提供认证管理、本地存储、日期格式化、树结构操作、文件下载等通用能力。 +- [页面视图开发](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/frontend/view.html): 页面视图位于 src/views/ 目录,每个业务模块遵循 index.vue(列表页)+ edit.vue(编辑弹窗)的标准模式,辅以 columns.ts(列定义)和 +- [接口响应规范](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/integration/api-contract.html): 后端所有接口统一返回 R.ok() / R.failed() 格式的 JSON 响应,前端通过 VAxios 的 transformRequestData 拦截器统一解包处理。 +- [字典数据联调](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/integration/dict-sync.html): 字典数据通过后端字典 API 获取,前端在下拉选择器中渲染选项。 +- [权限节点联动](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/integration/perm-sync.html): 前后端权限通过统一的权限节点字符串联动,后端 @permission_required 校验权限,前端 v-perm 指令和 TableAction 的 auth 属性控制按钮显示。 +- [代理配置](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/integration/proxy.html): 开发环境通过 Vite 代理转发 API 请求到后端,生产环境通过 Nginx 代理。 +- [文件上传联调](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/integration/upload-sync.html): 文件上传涉及前端 Upload 组件、后端上传接口和 URL 拼接三个环节,需要前后端协同配置。 +- [请求上下文(ContextVar)](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/tools/context.html): src/core/context.py 使用 Python 标准库 contextvars 管理请求级别的上下文信息,包括当前用户 ID、用户名、姓名和链路追踪 ID。 +- [数据库会话](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/tools/db-session.html): 数据库会话通过 scoped_session 实现线程级隔离,Repository 层的写操作自动 commit,BaseHandler.on_finish() 兜底关闭会话。 +- [字典缓存工具](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/tools/dict-util.html): src/common/utils/dict_util.py 提供业务字典的缓存读取能力,从 Redis 缓存中获取字典数据,缓存未命中时从数据库加载。 +- [导入导出](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/tools/excel.html): 基于 openpyxl 实现 Excel 导入导出功能,支持通过 file_template 模块管理导入模板配置。 +- [通用 Helper 函数](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/tools/helpers.html): src/common/utils/helpers.py 提供项目中广泛使用的通用工具函数,包括 ID 解析、OS/浏览器检测、参数脱敏等。 +- [IP 归属地解析](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/tools/ip-region.html): src/common/utils/ip2region.py 基于 ip2region 离线数据库,提供 IP 地址到省市区的归属地查询能力,无需网络请求。 +- [日志系统](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/tools/logger.html): 通过 Python 标准库 logging 实现结构化日志,支持控制台 + 文件双输出,日志文件按大小自动轮转。 +- [密码工具](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/tools/password.html): 采用 bcrypt 双重加盐方案存储密码,源码位于 src/core/password.py。 +- [权限缓存](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/tools/perm-cache.html): 通过 Redis 实现用户权限和菜单的缓存,采用用户级缓存 + 全局版本号双层策略。 +- [统一响应封装(R 对象)](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/tools/response.html): src/core/response.py 提供统一的 API 响应封装,所有接口返回格式为 {code, data, msg, ok}。 +- [富文本过滤](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/tools/rich-text.html): 富文本编辑器内容存在存储型 XSS 风险,通过 bleach 库实现 HTML 白名单清洗,在落盘前统一过滤危险内容。 +- [文件上传完整流程](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/tools/upload-guide.html): 富文本编辑器(如 TinyMCE、CKEditor、WangEditor 等)的图片上传同样使用此接口。 +- [文件上传](http://docs.tornado.elevue.djangoadmin.cn/zh/volume4/tools/upload.html): 提供本地文件上传功能,支持图片和通用文件上传,内置扩展名白名单、大小限制、魔术字节校验和路径遍历防护。 + +## 6. 代码生成器 + +- [CLI 命令行使用](http://docs.tornado.elevue.djangoadmin.cn/zh/volume5/cli.html): 代码生成器 CLI 模式的使用方法,包括单表生成、批量生成、预览模式和配置导出。 +- [代码生成引擎](http://docs.tornado.elevue.djangoadmin.cn/zh/volume5/code-engine.html): 代码生成引擎的工作原理,包括配置解析、模板渲染、文件写入和自动注册的完整流程。 +- [配置文件详解](http://docs.tornado.elevue.djangoadmin.cn/zh/volume5/config.html): 代码生成器 JSON 配置文件的格式说明,包括模块名称、字段属性、字典编码等配置项的详细解释。 +- [实战案例](http://docs.tornado.elevue.djangoadmin.cn/zh/volume5/demo.html): 以 tornado_example 演示表为完整案例,演示从建表到生成到使用的全流程。 +- [常见问题](http://docs.tornado.elevue.djangoadmin.cn/zh/volume5/faq.html): 代码生成器使用过程中常见问题的原因分析和解决方案。 +- [概述与架构](http://docs.tornado.elevue.djangoadmin.cn/zh/volume5/overview.html): 代码生成器的整体架构、核心模块和生成流程概述。 +- [表结构解析引擎](http://docs.tornado.elevue.djangoadmin.cn/zh/volume5/parser.html): 表结构解析引擎的工作原理,从数据库读取表元数据并智能推断字段用途的过程。 +- [自定义模板](http://docs.tornado.elevue.djangoadmin.cn/zh/volume5/templates.html): 代码生成器模板的 Jinja2 语法说明,包括模板变量、字段属性和自定义模板的开发方法。 +- [Web 管理界面](http://docs.tornado.elevue.djangoadmin.cn/zh/volume5/web-ui.html): 代码生成器 Web 管理界面的使用方法,通过可视化界面操作单表生成和批量生成。 + +## 7. 运维部署 + +- [备份与恢复](http://docs.tornado.elevue.djangoadmin.cn/zh/volume6/backup.html): - 3 份数据副本(1 份生产 + 2 份备份) - 2 种不同存储介质(如本地磁盘 + 远程存储) - 1 份异地备份(防机房级灾难) +- [跨库数据迁移](http://docs.tornado.elevue.djangoadmin.cn/zh/volume6/db-cross-migrate.html): 项目提供 scripts/migrate_db.py 脚本,支持在不同数据库之间迁移数据(如 MySQL → PostgreSQL / SQL Server / SQLite / Oracle)。 +- [数据库迁移](http://docs.tornado.elevue.djangoadmin.cn/zh/volume6/db-migrate.html): - 结构迁移:Alembic(自动生成 DDL 差异) - 数据迁移:scripts/migrate_db.py(跨库数据泵) - 初始化:scripts/init_db.py(全新安装一键建库) +- [部署 Checklist](http://docs.tornado.elevue.djangoadmin.cn/zh/volume6/deploy-checklist.html): 从服务器准备到应用上线的完整部署操作清单,适用于生产环境首次部署和后续版本更新。 +- [Docker容器化](http://docs.tornado.elevue.djangoadmin.cn/zh/volume6/docker.html): - 环境一致性:消除"在我机器上能跑"的问题 - 快速部署:一条命令启动完整服务 - 资源隔离:应用与宿主机环境解耦 +- [环境规划](http://docs.tornado.elevue.djangoadmin.cn/zh/volume6/env-plan.html): 各环境之间保持代码一致,仅通过环境变量(.env)区分配置。 +- [健康检查与监控](http://docs.tornado.elevue.djangoadmin.cn/zh/volume6/monitoring.html): `` 1. 应用层:健康检查端点、业务指标 2. 系统层:CPU/内存/磁盘/网络 3. 中间件:MySQL/Redis 连接状态 4. 日志:集中式日志收集与分析 `` +- [Nginx 反向代理](http://docs.tornado.elevue.djangoadmin.cn/zh/volume6/nginx.html): `` 客户端 → Nginx(80/443) ├─ / → 前端静态资源(dist/) ├─ /api/v1/... → Tornado 后端(8041) └─ /api/file/ → +- [性能调优](http://docs.tornado.elevue.djangoadmin.cn/zh/volume6/performance.html): 1. 先测量,后优化:用数据说话,避免盲目调参 2. 瓶颈优先:找到最大瓶颈,集中优化 3. 渐进式:每次只调整一个参数,观察效果 +- [安全加固](http://docs.tornado.elevue.djangoadmin.cn/zh/volume6/security-hardening.html): - 最小权限:只开放必要的端口和权限 - 纵深防御:多层安全措施叠加 - 默认安全:配置默认值应为安全选项 +- [Supervisor进程管理](http://docs.tornado.elevue.djangoadmin.cn/zh/volume6/supervisor.html): - Linux 服务器直接部署(非 Docker) - 需要进程自动重启和日志轮转 - 管理多个相关进程 +- [故障排查手册](http://docs.tornado.elevue.djangoadmin.cn/zh/volume6/troubleshooting.html): 1. 查看日志:tail -f logs/supervisor.out.log 或 docker-compose logs -f 2. 检查配置:.env 文件、数据库连接、Redis 连接 3. +- [版本升级流程](http://docs.tornado.elevue.djangoadmin.cn/zh/volume6/upgrade.html): 1. 先备份,后升级 2. 先测试环境,后生产环境 3. 每次升级可回滚 4. 低峰期执行升级 + +## 8. 规范标准 + +- [API响应规范](http://docs.tornado.elevue.djangoadmin.cn/zh/volume7/api-response.html): - 所有接口必须通过 R.ok() 或 R.failed() 返回,禁止直接返回 dict - 成功响应 code=0,失败响应 code=1 - 响应体始终包含 code、data、msg、ok +- [代码审查清单](http://docs.tornado.elevue.djangoadmin.cn/zh/volume7/code-review.html): - 每次提交必须经过至少一人审查 - 审查关注点:正确性 > 安全性 > 可维护性 > 性能 - 审查意见应具体、可操作,避免主观评价 +- [删除规范](http://docs.tornado.elevue.djangoadmin.cn/zh/volume7/deletion.html): - is_delete = 0:正常记录(默认值) - is_delete = 1:已删除记录 - 所有查询方法自动过滤 is_delete = 0,业务层无需关心 +- [文档规范](http://docs.tornado.elevue.djangoadmin.cn/zh/volume7/doc-standard.html): - 文档与代码同步更新 - 使用中文编写(项目约定) - 示例代码可直接运行 +- [前端 API 规范](http://docs.tornado.elevue.djangoadmin.cn/zh/volume7/fe-api.html): - 每个后端模块对应一个 API 文件 - 函数命名统一使用 名词 + 动词 格式(与后端保持一致) - 请求路径使用相对路径(/position/page),不含 /api/v1 前缀(由 +- [前端页面规范](http://docs.tornado.elevue.djangoadmin.cn/zh/volume7/fe-component.html): - Vue3(Composition API + <script setup>) - ElementPlus - 自定义组件(BasicTable / BasicForm / TableAction +- [Git提交规范](http://docs.tornado.elevue.djangoadmin.cn/zh/volume7/git.html): `` <type>(<scope>): <subject> <body> <footer> `` +- [Handler 层规范](http://docs.tornado.elevue.djangoadmin.cn/zh/volume7/handler.html): - Handler 只做请求分发,不含业务逻辑 - 通过装饰器控制权限和演示模式 - 委托 Service 处理业务逻辑 - 返回 R 封装的响应 +- [分页规范](http://docs.tornado.elevue.djangoadmin.cn/zh/volume7/pagination.html): - 前端传递 pageNo(页码,从 1 开始)和 pageSize(每页条数) - 后端返回 {records, total, size, current, pages} 结构 - 默认每页 10 +- [Pydantic Schema规范](http://docs.tornado.elevue.djangoadmin.cn/zh/volume7/pydantic.html): - 请求体参数必须声明为 Pydantic 模型(Form 类) - 字段约束使用 Field(...) 定义 - 自定义校验使用 @field_validator - 唯一性校验在 Schema +- [Repository层规范](http://docs.tornado.elevue.djangoadmin.cn/zh/volume7/repository.html): - Repository 只做数据访问原语,不处理 R 封装/序列化/业务逻辑 - 软删除由基类自动处理,子类无需关心 - 查询方法自动跳过 None 值条件 +- [Service层规范](http://docs.tornado.elevue.djangoadmin.cn/zh/volume7/service.html): BaseService 采用模板方法模式:基类定义流程骨架,子类通过声明差异点和覆盖钩子定制行为。 +- [测试规范](http://docs.tornado.elevue.djangoadmin.cn/zh/volume7/testing.html): 1. 契约测试(Contract):验证路由、权限、表名等契约不变 2. 单元测试(Unit):验证单个函数/方法的逻辑正确性 3. 集成测试(Integration):验证模块间协作、真实数据库操作 + +## 附录 + +- [常见问题汇总](http://docs.tornado.elevue.djangoadmin.cn/zh/faq.html): 本页汇总了项目各模块的常见问题及解决方案,按场景分类索引。 +- [免责声明](http://docs.tornado.elevue.djangoadmin.cn/zh/other/declare.html): 使用本产品前必读的法律声明,明确产品性质、使用限制与责任划分,一旦使用本产品即视为接受本声明全部条款。 +- [广告赞助](http://docs.tornado.elevue.djangoadmin.cn/zh/other/sponsor.html): 1. 投放广告不得与官方全系产品存在结构性冲突和竞争 2. 广告内容需符合国家法律法规,不得包含虚假、误导性信息 3. 广告素材需经官方审核通过后方可上线,审核周期 1-3 个工作日 4. diff --git a/DjangoAdmin_Tornado_EleVue/public/robots.txt b/DjangoAdmin_Tornado_EleVue/public/robots.txt new file mode 100644 index 0000000..c503dd1 --- /dev/null +++ b/DjangoAdmin_Tornado_EleVue/public/robots.txt @@ -0,0 +1,33 @@ +# DjangoAdmin Tornado+ElementPlus 开发文档 +User-agent: * +Allow: / + +# 显式放行生成式引擎 / AI 爬虫(GEO) +User-agent: GPTBot +Allow: / + +User-agent: ChatGPT-User +Allow: / + +User-agent: ClaudeBot +Allow: / + +User-agent: Claude-Web +Allow: / + +User-agent: anthropic-ai +Allow: / + +User-agent: PerplexityBot +Allow: / + +User-agent: Google-Extended +Allow: / + +User-agent: Bytespider +Allow: / + +User-agent: bingbot +Allow: / + +Sitemap: http://docs.tornado.elevue.djangoadmin.cn/sitemap.xml diff --git a/DjangoAdmin_Tornado_EleVue/scripts/generate-llms-txt.mjs b/DjangoAdmin_Tornado_EleVue/scripts/generate-llms-txt.mjs new file mode 100644 index 0000000..aec2e77 --- /dev/null +++ b/DjangoAdmin_Tornado_EleVue/scripts/generate-llms-txt.mjs @@ -0,0 +1,122 @@ +#!/usr/bin/env node +/** + * 生成 public/llms.txt(llmstxt.org 标准)——AI 爬虫的站点摘要索引。 + * + * 数据源:zh 目录下全部 Markdown 的 H1 + :::tip 概述首句(与 meta + * description 同源,复用 .vitepress/config/extract.mjs)。按侧边栏章节分组。 + * + * 用法:node scripts/generate-llms-txt.mjs + * 已挂入 package.json 的 docs:build 前置步骤。 + */ +import fs from "node:fs"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; +import { + SITE_URL, + SITE_DESCRIPTION, + extractDescription, +} from "../.vitepress/config/extract.mjs"; + +const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); +const ZH = path.join(ROOT, "zh"); + +/** 顶层目录 → 侧边栏章节名(与 .vitepress/config/zh.ts 保持一致) */ +const SECTIONS = [ + ["", "1. 了解项目"], + ["volume1", "2. 快速入门"], + ["volume2", "3. 模块开发实战"], + ["volume3", "4. 架构设计"], + ["volume4", "5. 开发指南"], + ["volume5", "6. 代码生成器"], + ["volume6", "7. 运维部署"], + ["volume7", "8. 规范标准"], + ["other", "附录"], +]; + +function walk(dir, out = []) { + for (const entry of fs.readdirSync(dir, { withFileTypes: true })) { + const p = path.join(dir, entry.name); + if (entry.isDirectory()) walk(p, out); + else if (entry.name.endsWith(".md")) out.push(p); + } + return out; +} + +/** 提取首个 H1 文本 */ +function h1Of(md) { + // 围栏感知:跳过 ``` 代码块内的 # 注释,取真正的页面 H1 + let inFence = false; + for (const line of md.split("\n")) { + if (line.startsWith("```")) { inFence = !inFence; continue; } + if (!inFence && line.startsWith("# ") && !line.startsWith("## ")) { + return line.slice(2).trim(); + } + } + return ""; +} + +/** H1 编号排序键:"5.10 x" → [5,10];无编号排最后 */ +function sortKey(h1) { + const m = h1.match(/^(\d+(?:\.\d+)*)/); + if (m) return m[1].split(".").map(Number); + const letter = h1.match(/^([A-Z])\./); + if (letter) return [1000 + letter[1].charCodeAt(0)]; + return [9999]; +} + +function cmpKey(a, b) { + const len = Math.max(a.length, b.length); + for (let i = 0; i < len; i++) { + const x = a[i] ?? 0; + const y = b[i] ?? 0; + if (x !== y) return x - y; + } + return 0; +} + +const files = walk(ZH); +const groups = new Map(SECTIONS.map(([dir, label]) => [label, []])); + +for (const file of files) { + const rel = path.relative(ZH, file).replace(/\\/g, "/"); + const topDir = rel.includes("/") ? rel.split("/")[0] : ""; + const base = rel.split("/").pop(); + const label = (topDir === "" && base === "faq.md") ? "附录" + : SECTIONS.find(([dir]) => dir === topDir)?.[1] ?? "附录"; + + const md = fs.readFileSync(file, "utf8"); + const h1 = h1Of(md); + if (!h1) continue; + const desc = extractDescription(md); + const url = `${SITE_URL}/zh/${rel.replace(/\.md$/, ".html")}`; + groups.get(label).push({ h1, desc, url, key: sortKey(h1) }); +} + +const lines = [ + "# DjangoAdmin Tornado+ElementPlus 开发文档", + "", + `> ${SITE_DESCRIPTION}。内置 RBAC 权限体系、代码生成器等开箱即用功能,支持五种数据库一键切换。本文档共 ${files.length} 篇,按章节组织。`, + "", +]; + +// 按章节顺序输出,合并重复 label(appendix/other 同为「附录」,只输出一次) +const printed = new Set(); +for (const [, label] of SECTIONS) { + if (printed.has(label)) continue; + const items = groups.get(label); + if (!items?.length) continue; + printed.add(label); + + lines.push(`## ${label}`, ""); + items.sort((a, b) => cmpKey(a.key, b.key)); + for (const { h1, desc, url } of items) { + lines.push(desc ? `- [${h1}](${url}): ${desc}` : `- [${h1}](${url})`); + } + lines.push(""); +} + +const out = path.join(ROOT, "public", "llms.txt"); +fs.writeFileSync(out, lines.join("\n"), "utf8"); +console.log( + `llms.txt: ${files.length} 页 → ${path.relative(ROOT, out)} (${printed.size} 个章节)`, +); diff --git a/DjangoAdmin_Tornado_EleVue/zh/course.md b/DjangoAdmin_Tornado_EleVue/zh/course.md index bf3e196..a2bb28e 100644 --- a/DjangoAdmin_Tornado_EleVue/zh/course.md +++ b/DjangoAdmin_Tornado_EleVue/zh/course.md @@ -1,3 +1,5 @@ +# 新手入门指南 + :::warning 特别提醒 官方精心制作本教程,目的在于方便用户快速掌握软件产品的使用和部署。通过此教程,刚入行的开发者也可以快速掌握并投入产品研发。本地部署时务必请耐心阅读文档操作。 ::: diff --git a/DjangoAdmin_Tornado_EleVue/zh/introduction.md b/DjangoAdmin_Tornado_EleVue/zh/introduction.md index a714824..8044a61 100644 --- a/DjangoAdmin_Tornado_EleVue/zh/introduction.md +++ b/DjangoAdmin_Tornado_EleVue/zh/introduction.md @@ -1,3 +1,9 @@ +# 项目介绍 + +:::tip 概述 +DjangoAdmin 是企业级中台解决方案,后端基于 Tornado + SQLAlchemy,前端基于 Vue3 + ElementPlus,内置 RBAC 权限、代码生成器等开箱即用功能,支持五种数据库一键切换。 +::: + <div align="center"> <p align="center"> <img src="/logo.png" height="150" alt="logo"/> diff --git a/DjangoAdmin_Tornado_EleVue/zh/other/declare.md b/DjangoAdmin_Tornado_EleVue/zh/other/declare.md index 7737479..915692a 100644 --- a/DjangoAdmin_Tornado_EleVue/zh/other/declare.md +++ b/DjangoAdmin_Tornado_EleVue/zh/other/declare.md @@ -1,5 +1,9 @@ # 免责声明 +:::tip 概述 +使用本产品前必读的法律声明,明确产品性质、使用限制与责任划分,一旦使用本产品即视为接受本声明全部条款。 +::: + :::danger 重要提示 任何用户在使用本团队研发的系列软件产品(以下简称「本产品」)前,请仔细阅读并透彻理解本声明。选择不使用本产品,可随时停止使用;一旦使用本产品,即视为对本声明全部内容的认可和接受。 ::: diff --git a/DjangoAdmin_Tornado_EleVue/zh/struct.md b/DjangoAdmin_Tornado_EleVue/zh/struct.md index f5ecc54..743372b 100644 --- a/DjangoAdmin_Tornado_EleVue/zh/struct.md +++ b/DjangoAdmin_Tornado_EleVue/zh/struct.md @@ -1,3 +1,5 @@ +# 项目目录结构 + ## 目录说明 在软件开发过程中,优秀的软件目录结构对于项目的组织、开发、维护和扩展至关重要,合理的目录结构能够显著提升开发效率和代码可维护性。 diff --git a/DjangoAdmin_Tornado_EleVue/zh/volume2/code-list.md b/DjangoAdmin_Tornado_EleVue/zh/volume2/code-list.md index a9f8039..8a07b8b 100644 --- a/DjangoAdmin_Tornado_EleVue/zh/volume2/code-list.md +++ b/DjangoAdmin_Tornado_EleVue/zh/volume2/code-list.md @@ -1,5 +1,9 @@ # 完整代码清单 +:::tip 概述 +本页汇总友链(Link)模块涉及的全部文件代码,开发时可快速查阅与复制对照。 +::: + 本章汇总友链(Link)模块涉及的全部文件,便于开发时快速查阅和复制。 ## 后端文件清单 diff --git a/DjangoAdmin_Tornado_EleVue/zh/volume2/faq.md b/DjangoAdmin_Tornado_EleVue/zh/volume2/faq.md index e9c1218..f372f58 100644 --- a/DjangoAdmin_Tornado_EleVue/zh/volume2/faq.md +++ b/DjangoAdmin_Tornado_EleVue/zh/volume2/faq.md @@ -1,5 +1,9 @@ # 常见问题与排错 +:::tip 概述 +本页汇总模块开发过程中的常见问题与排错方法,开发受阻时按症状索引即可定位。 +::: + 本章汇总模块开发过程中的常见问题和解决方案。 ## 后端问题 diff --git a/DjangoAdmin_Tornado_EleVue/zh/volume2/fe-api.md b/DjangoAdmin_Tornado_EleVue/zh/volume2/fe-api.md index 797cc1c..ae9203a 100644 --- a/DjangoAdmin_Tornado_EleVue/zh/volume2/fe-api.md +++ b/DjangoAdmin_Tornado_EleVue/zh/volume2/fe-api.md @@ -1,5 +1,9 @@ # 前端 API 层 +:::tip 概述 +前端 API 层封装后端接口的 HTTP 请求,每个业务模块对应一个 API 文件,本页讲解基于 Axios 封装的编写规范。 +::: + 前端 API 层负责封装后端接口的 HTTP 请求。每个业务模块对应一个 API 文件,使用项目封装的 Axios 工具发送请求。 ## 文件位置 diff --git a/DjangoAdmin_Tornado_EleVue/zh/volume2/fe-router.md b/DjangoAdmin_Tornado_EleVue/zh/volume2/fe-router.md index 0f79bbe..5c2330b 100644 --- a/DjangoAdmin_Tornado_EleVue/zh/volume2/fe-router.md +++ b/DjangoAdmin_Tornado_EleVue/zh/volume2/fe-router.md @@ -1,5 +1,9 @@ # 前端路由与菜单 +:::tip 概述 +本页讲解前端路由与菜单机制——路由和菜单由后端动态返回,前端只需注册路由组件映射。 +::: + 前端路由定义页面的访问路径,菜单是路由的可视化展示。项目的路由和菜单由后端动态返回,前端只需注册路由组件映射。 ## 路由配置 diff --git a/DjangoAdmin_Tornado_EleVue/zh/volume2/fe-view.md b/DjangoAdmin_Tornado_EleVue/zh/volume2/fe-view.md index 3639881..fd245a4 100644 --- a/DjangoAdmin_Tornado_EleVue/zh/volume2/fe-view.md +++ b/DjangoAdmin_Tornado_EleVue/zh/volume2/fe-view.md @@ -1,5 +1,9 @@ # 前端页面视图 +:::tip 概述 +前端页面视图是用户直接交互的界面,本页讲解 Vue3 + ElementPlus 下一个完整 CRUD 页面的文件组成与编写方式。 +::: + 前端页面视图是用户直接交互的界面。项目使用 Vue3 + ElementPlus + Vite 构建。一个完整的 CRUD 页面由 4 个文件组成: ``` diff --git a/DjangoAdmin_Tornado_EleVue/zh/volume2/handler.md b/DjangoAdmin_Tornado_EleVue/zh/volume2/handler.md index 9e36ff4..92cbf81 100644 --- a/DjangoAdmin_Tornado_EleVue/zh/volume2/handler.md +++ b/DjangoAdmin_Tornado_EleVue/zh/volume2/handler.md @@ -1,5 +1,9 @@ # 请求处理器(Handler) +:::tip 概述 +Handler 层是 HTTP 接口层,负责接收请求、校验权限与记录操作日志,编写新接口从本页开始。 +::: + Handler 层是 HTTP 接口层,负责接收请求、校验权限、记录操作日志,然后委托给 Service 层处理。每个业务模块对应一个 `handlers.py` 文件,所有 Handler 继承 `BaseHandler`。 ## 文件位置 diff --git a/DjangoAdmin_Tornado_EleVue/zh/volume2/model.md b/DjangoAdmin_Tornado_EleVue/zh/volume2/model.md index ab98701..3bb4d7c 100644 --- a/DjangoAdmin_Tornado_EleVue/zh/volume2/model.md +++ b/DjangoAdmin_Tornado_EleVue/zh/volume2/model.md @@ -1,5 +1,9 @@ # 数据模型(Model) +:::tip 概述 +数据模型是模块开发的第一步,讲解如何用 SQLAlchemy ORM 与基类定义数据库表结构,新建模块时从本页开始。 +::: + 数据模型是模块开发的第一步,用于定义数据库表结构。项目使用 `SQLAlchemy ORM`,模型类通过继承 `BaseModel` 自动获得通用字段和方法。 ## 文件位置 diff --git a/DjangoAdmin_Tornado_EleVue/zh/volume2/repository.md b/DjangoAdmin_Tornado_EleVue/zh/volume2/repository.md index e03b9b2..8009a30 100644 --- a/DjangoAdmin_Tornado_EleVue/zh/volume2/repository.md +++ b/DjangoAdmin_Tornado_EleVue/zh/volume2/repository.md @@ -1,5 +1,9 @@ # Repository 层 +:::tip 概述 +Repository 层是数据访问层,封装全部数据库查询操作,本页讲解基于 BaseRepository 基类的通用 CRUD 用法。 +::: + Repository 层是数据访问层,封装所有数据库查询操作。项目通过 `BaseRepository` 基类提供通用 CRUD 能力,子类通常只需声明类名,无需编写任何代码。 ## 文件位置 diff --git a/DjangoAdmin_Tornado_EleVue/zh/volume2/schema.md b/DjangoAdmin_Tornado_EleVue/zh/volume2/schema.md index 4069def..7917550 100644 --- a/DjangoAdmin_Tornado_EleVue/zh/volume2/schema.md +++ b/DjangoAdmin_Tornado_EleVue/zh/volume2/schema.md @@ -1,5 +1,9 @@ # Pydantic Schema +:::tip 概述 +Schema 层负责请求数据校验,本页讲解基于 Pydantic v2 BaseModel 与 Field 的表单类定义规范。 +::: + Schema 层负责请求数据的校验。项目使用 Pydantic v2 的 `BaseModel` 定义表单类,通过 `Field` 约束字段格式,Tornado 在接收请求体时自动执行校验。 ## 文件位置 diff --git a/DjangoAdmin_Tornado_EleVue/zh/volume3/overview.md b/DjangoAdmin_Tornado_EleVue/zh/volume3/overview.md index 7982902..ab57e43 100644 --- a/DjangoAdmin_Tornado_EleVue/zh/volume3/overview.md +++ b/DjangoAdmin_Tornado_EleVue/zh/volume3/overview.md @@ -1,5 +1,9 @@ # 整体架构图 +:::tip 概述 +本页从全局视角阐述系统整体技术架构,涵盖前端、后端、数据库与基础设施等核心组成,理解系统全貌时从本页开始。 +::: + 本章从全局视角阐述系统的整体技术架构,涵盖前端、后端、数据库及基础设施等核心组成部分。 ## 架构总览 diff --git a/DjangoAdmin_Tornado_EleVue/zh/volume4/business/article.md b/DjangoAdmin_Tornado_EleVue/zh/volume4/business/article.md index a29edc0..407a1a9 100644 --- a/DjangoAdmin_Tornado_EleVue/zh/volume4/business/article.md +++ b/DjangoAdmin_Tornado_EleVue/zh/volume4/business/article.md @@ -1,3 +1,5 @@ +# 文章管理 + :::tip 文章管理 文章管理模块支持富文本编辑、分类关联、封面图片上传、图集管理等功能。适用于新闻、公告、帮助文档等内容管理场景。本模块是典型的「带文件处理」业务模块,涵盖了封面迁移、图集处理、富文本 XSS 清洗等核心机制。 ::: diff --git a/DjangoAdmin_Tornado_EleVue/zh/volume4/business/category.md b/DjangoAdmin_Tornado_EleVue/zh/volume4/business/category.md index cff130e..f4ebd3b 100644 --- a/DjangoAdmin_Tornado_EleVue/zh/volume4/business/category.md +++ b/DjangoAdmin_Tornado_EleVue/zh/volume4/business/category.md @@ -1,3 +1,5 @@ +# 分类管理 + :::tip 分类管理 分类管理模块用于管理树形分类数据,如文章分类、产品分类等。通过 `parent_id` 字段实现无限级分类。 ::: diff --git a/DjangoAdmin_Tornado_EleVue/zh/volume4/business/content.md b/DjangoAdmin_Tornado_EleVue/zh/volume4/business/content.md index 1d13da6..c34a44b 100644 --- a/DjangoAdmin_Tornado_EleVue/zh/volume4/business/content.md +++ b/DjangoAdmin_Tornado_EleVue/zh/volume4/business/content.md @@ -1,3 +1,5 @@ +# 公告与链接管理 + :::tip 公告/链接/城市 公告、链接、城市是三个简单 CRUD 内容模块,均继承 BaseService,提供标准的增删改查接口。适用于系统公告、友情链接、城市数据等场景。 ::: diff --git a/DjangoAdmin_Tornado_EleVue/zh/volume4/business/dept.md b/DjangoAdmin_Tornado_EleVue/zh/volume4/business/dept.md index 8759e6d..f3a6c15 100644 --- a/DjangoAdmin_Tornado_EleVue/zh/volume4/business/dept.md +++ b/DjangoAdmin_Tornado_EleVue/zh/volume4/business/dept.md @@ -1,3 +1,5 @@ +# 部门/职级/岗位管理 + :::tip 部门/职级/岗位 部门、职级、岗位是组织架构管理的三个核心模块。部门采用树形结构,职级和岗位为简单 CRUD 模块,均继承 `BaseService`。用户表通过 `dept_id`、`position_id`、`level_id` 三个外键关联这三个模块。 ::: diff --git a/DjangoAdmin_Tornado_EleVue/zh/volume4/business/job.md b/DjangoAdmin_Tornado_EleVue/zh/volume4/business/job.md index bab60c1..0e4cfd1 100644 --- a/DjangoAdmin_Tornado_EleVue/zh/volume4/business/job.md +++ b/DjangoAdmin_Tornado_EleVue/zh/volume4/business/job.md @@ -1,3 +1,5 @@ +# 定时任务 + :::tip 定时任务 定时任务模块基于 APScheduler 实现,支持 Cron 表达式调度、任务执行日志、动态启停等功能。包含 job(任务定义)、job_log(执行日志)、scheduler(调度器)三个子模块。 ::: diff --git a/DjangoAdmin_Tornado_EleVue/zh/volume4/business/menu.md b/DjangoAdmin_Tornado_EleVue/zh/volume4/business/menu.md index 48b3b0d..5590488 100644 --- a/DjangoAdmin_Tornado_EleVue/zh/volume4/business/menu.md +++ b/DjangoAdmin_Tornado_EleVue/zh/volume4/business/menu.md @@ -1,3 +1,5 @@ +# 菜单管理 + :::tip 菜单管理 菜单管理是 RBAC 权限系统的基础,负责管理系统的导航菜单和权限节点。支持目录/菜单(type=0)和权限按钮节点(type=1)两种类型,通过树形结构组织。权限节点由系统根据前端勾选自动生成,采用 `sys:module:action` 三段式命名。 ::: diff --git a/DjangoAdmin_Tornado_EleVue/zh/volume4/business/param.md b/DjangoAdmin_Tornado_EleVue/zh/volume4/business/param.md index 79448fe..a98c3ef 100644 --- a/DjangoAdmin_Tornado_EleVue/zh/volume4/business/param.md +++ b/DjangoAdmin_Tornado_EleVue/zh/volume4/business/param.md @@ -1,3 +1,5 @@ +# 参数管理 + :::tip 参数管理 参数管理模块用于管理动态系统参数,与系统配置模块类似但更侧重于业务参数的灵活配置。支持按参数键查询、修改,无需重启服务即可生效。本模块是典型的「BaseService 简单模块」,通过声明差异点即可获得完整 CRUD 能力。 ::: diff --git a/DjangoAdmin_Tornado_EleVue/zh/volume4/business/role.md b/DjangoAdmin_Tornado_EleVue/zh/volume4/business/role.md index afb9a5e..2978c8c 100644 --- a/DjangoAdmin_Tornado_EleVue/zh/volume4/business/role.md +++ b/DjangoAdmin_Tornado_EleVue/zh/volume4/business/role.md @@ -1,3 +1,5 @@ +# 角色管理 + :::tip 角色管理 角色是 RBAC 权限模型的核心,连接用户和菜单(权限)。通过为角色分配菜单权限,再将角色分配给用户,实现灵活的权限管理。角色删除时需清理关联的用户角色和角色菜单数据,并即时失效受影响用户的权限缓存。 ::: diff --git a/DjangoAdmin_Tornado_EleVue/zh/volume4/business/user.md b/DjangoAdmin_Tornado_EleVue/zh/volume4/business/user.md index d1d07c0..8fb95e6 100644 --- a/DjangoAdmin_Tornado_EleVue/zh/volume4/business/user.md +++ b/DjangoAdmin_Tornado_EleVue/zh/volume4/business/user.md @@ -1,3 +1,5 @@ +# 用户管理 + :::tip 用户管理 用户管理是系统的核心模块,属于复杂业务模块。包含用户 CRUD、角色关联、密码加密、行政区划、Excel 导入导出等功能。与简单 CRUD 模块不同,用户管理使用自定义 service 函数而非继承 BaseService 的类方法。 ::: diff --git a/DjangoAdmin_Tornado_EleVue/zh/volume4/core/captcha.md b/DjangoAdmin_Tornado_EleVue/zh/volume4/core/captcha.md index cc7daf8..a7c973b 100644 --- a/DjangoAdmin_Tornado_EleVue/zh/volume4/core/captcha.md +++ b/DjangoAdmin_Tornado_EleVue/zh/volume4/core/captcha.md @@ -1,3 +1,5 @@ +# 验证码机制 + :::tip 验证码 验证码是防止自动化攻击的重要安全手段。使用 Pillow 生成图片验证码,存储在 Redis 中,支持防刷限流和万能验证码(演示模式)。源码位于 `src/common/utils/captcha.py`。 ::: diff --git a/DjangoAdmin_Tornado_EleVue/zh/volume4/core/config.md b/DjangoAdmin_Tornado_EleVue/zh/volume4/core/config.md index 0e0170a..040b49d 100644 --- a/DjangoAdmin_Tornado_EleVue/zh/volume4/core/config.md +++ b/DjangoAdmin_Tornado_EleVue/zh/volume4/core/config.md @@ -1,3 +1,5 @@ +# 系统配置管理 + :::tip 系统配置 系统配置模块用于管理动态的键值对配置项,与数据字典类似但更偏向系统级参数。支持分组管理,可通过接口动态修改,无需重启服务。模块位于 `src/modules/config/` 和 `src/modules/config_item/`,路由位于 `src/api/v1/config.py` 和 `config_item.py`。 ::: diff --git a/DjangoAdmin_Tornado_EleVue/zh/volume4/core/demo-mode.md b/DjangoAdmin_Tornado_EleVue/zh/volume4/core/demo-mode.md index 272db54..380900a 100644 --- a/DjangoAdmin_Tornado_EleVue/zh/volume4/core/demo-mode.md +++ b/DjangoAdmin_Tornado_EleVue/zh/volume4/core/demo-mode.md @@ -1,3 +1,5 @@ +# 演示模式 + :::tip 演示模式 演示模式用于在线体验环境,开启后所有写操作(新增、编辑、删除等)将被拦截,返回"演示环境,暂无操作权限"提示。通过 `TORNADO_DEMO` 环境变量控制。装饰器位于 `src/common/middleware/access_decorators.py`。 ::: diff --git a/DjangoAdmin_Tornado_EleVue/zh/volume4/core/dict.md b/DjangoAdmin_Tornado_EleVue/zh/volume4/core/dict.md index 2ba8d18..f3f4984 100644 --- a/DjangoAdmin_Tornado_EleVue/zh/volume4/core/dict.md +++ b/DjangoAdmin_Tornado_EleVue/zh/volume4/core/dict.md @@ -1,3 +1,5 @@ +# 字典模块 + :::tip 数据字典 数据字典用于管理系统中的枚举值和配置项,如状态、类型、性别等。通过字典编码统一管理,前端可通过 `useDictStore` 获取字典选项,避免硬编码。后端读取工具位于 `src/common/utils/dict_util.py`,内置进程内 TTL 缓存。 ::: diff --git a/DjangoAdmin_Tornado_EleVue/zh/volume4/core/exception.md b/DjangoAdmin_Tornado_EleVue/zh/volume4/core/exception.md index 6783f7e..379b7af 100644 --- a/DjangoAdmin_Tornado_EleVue/zh/volume4/core/exception.md +++ b/DjangoAdmin_Tornado_EleVue/zh/volume4/core/exception.md @@ -1,3 +1,5 @@ +# 异常与响应处理 + :::tip 全局异常与响应 定义了统一的响应格式和全局异常处理机制。所有 API 返回 `{code, data, msg, ok}` 标准格式,异常被捕获后也转换为相同格式。响应函数位于 `src/core/response.py`,异常类型位于 `src/core/exceptions.py`。 ::: diff --git a/DjangoAdmin_Tornado_EleVue/zh/volume4/core/jwt.md b/DjangoAdmin_Tornado_EleVue/zh/volume4/core/jwt.md index 5b22053..a1a54b9 100644 --- a/DjangoAdmin_Tornado_EleVue/zh/volume4/core/jwt.md +++ b/DjangoAdmin_Tornado_EleVue/zh/volume4/core/jwt.md @@ -1,3 +1,5 @@ +# 用户认证(JWT) + :::tip JWT认证 JWT(JSON Web Token)是的核心认证机制。用户登录成功后获取 Token,后续请求通过 `Authorization: Bearer <token>` 头携带 Token 进行身份验证。项目内置了 Token 生成、解析、刷新和黑名单管理功能,源码位于 `src/core/jwt.py`。 ::: diff --git a/DjangoAdmin_Tornado_EleVue/zh/volume4/core/login-log.md b/DjangoAdmin_Tornado_EleVue/zh/volume4/core/login-log.md index 0a9fc2f..b37a3b3 100644 --- a/DjangoAdmin_Tornado_EleVue/zh/volume4/core/login-log.md +++ b/DjangoAdmin_Tornado_EleVue/zh/volume4/core/login-log.md @@ -1,3 +1,5 @@ +# 登录日志 + :::tip 登录日志 登录日志记录每次登录尝试(成功/失败),包含登录账号、IP地址、浏览器信息、登录时间等。支持 IP 地理位置解析(ip2region)和 User-Agent 解析。登录逻辑位于 `src/modules/auth/service.py`,日志记录位于 `src/modules/login_log/service.py`。 ::: diff --git a/DjangoAdmin_Tornado_EleVue/zh/volume4/core/operation-log.md b/DjangoAdmin_Tornado_EleVue/zh/volume4/core/operation-log.md index 3200aa9..35c01e9 100644 --- a/DjangoAdmin_Tornado_EleVue/zh/volume4/core/operation-log.md +++ b/DjangoAdmin_Tornado_EleVue/zh/volume4/core/operation-log.md @@ -1,3 +1,5 @@ +# 操作日志 + :::tip 操作日志 操作日志装饰器自动记录写请求(POST/PUT/DELETE/PATCH)的操作日志,无需手动埋点。源码位于 `src/common/middleware/operation_log.py`。 ::: diff --git a/DjangoAdmin_Tornado_EleVue/zh/volume4/core/rbac.md b/DjangoAdmin_Tornado_EleVue/zh/volume4/core/rbac.md index 57e1615..213875f 100644 --- a/DjangoAdmin_Tornado_EleVue/zh/volume4/core/rbac.md +++ b/DjangoAdmin_Tornado_EleVue/zh/volume4/core/rbac.md @@ -1,3 +1,5 @@ +# 权限管理(RBAC) + :::tip RBAC权限 采用基于角色的访问控制(RBAC)模型,通过用户-角色-菜单三层关系实现细粒度的权限管理。权限控制贯穿前后端:后端通过 `@permission_required` 装饰器校验(`src/common/middleware/access_decorators.py`),前端通过 `v-perm` 指令控制按钮显隐。 ::: diff --git a/DjangoAdmin_Tornado_EleVue/zh/volume4/core/validator.md b/DjangoAdmin_Tornado_EleVue/zh/volume4/core/validator.md index dc5aef3..6c1f598 100644 --- a/DjangoAdmin_Tornado_EleVue/zh/volume4/core/validator.md +++ b/DjangoAdmin_Tornado_EleVue/zh/volume4/core/validator.md @@ -1,3 +1,5 @@ +# 参数验证(Pydantic) + :::tip 参数验证 使用 Pydantic v2 进行请求参数验证。所有请求体参数通过 Pydantic BaseModel 定义,Tornado 自动解析和验证 JSON 请求体,验证失败返回标准格式错误信息。BaseSchema 基类位于 `src/core/base_schema.py`。 ::: diff --git a/DjangoAdmin_Tornado_EleVue/zh/why.md b/DjangoAdmin_Tornado_EleVue/zh/why.md index 7f96fda..814107a 100644 --- a/DjangoAdmin_Tornado_EleVue/zh/why.md +++ b/DjangoAdmin_Tornado_EleVue/zh/why.md @@ -1,7 +1,7 @@ # 为什么选择我们? :::tip 核心价值 -企业级数据中台不应从零搭建。本框架提供开箱即用的完整解决方案,为中大型企业构建统一的数字化基座。 +本框架提供开箱即用的企业级中台完整解决方案,免去从零搭建成本,助力中大型企业构建统一的数字化基座。 ::: ## 解决什么问题? diff --git a/DjangoAdmin_Tornado_NaiveVue/.vitepress/config/en.ts b/DjangoAdmin_Tornado_NaiveVue/.vitepress/config/en.ts index a1a96ef..49cb48b 100644 --- a/DjangoAdmin_Tornado_NaiveVue/.vitepress/config/en.ts +++ b/DjangoAdmin_Tornado_NaiveVue/.vitepress/config/en.ts @@ -29,7 +29,7 @@ // // themeConfig: { // editLink: { -// pattern: "https://gitee.com/djangoadmin/DjangoAdmin_Fastapi_EleVue", +// pattern: "https://gitee.com/djangoadmin/DjangoAdmin_Tornado_NaiveVue", // text: "Suggest changes to this page", // }, // diff --git a/DjangoAdmin_Tornado_NaiveVue/.vitepress/config/extract.d.mts b/DjangoAdmin_Tornado_NaiveVue/.vitepress/config/extract.d.mts new file mode 100644 index 0000000..2a46233 --- /dev/null +++ b/DjangoAdmin_Tornado_NaiveVue/.vitepress/config/extract.d.mts @@ -0,0 +1,5 @@ +export declare const SITE_URL: string; +export declare const SITE_DESCRIPTION: string; +export declare function stripNumberPrefix(title: string): string; +export declare function extractDescription(md: string): string; +export declare function extractFaqs(md: string): { q: string; a: string }[]; diff --git a/DjangoAdmin_Tornado_NaiveVue/.vitepress/config/extract.mjs b/DjangoAdmin_Tornado_NaiveVue/.vitepress/config/extract.mjs new file mode 100644 index 0000000..e7286f1 --- /dev/null +++ b/DjangoAdmin_Tornado_NaiveVue/.vitepress/config/extract.mjs @@ -0,0 +1,130 @@ +/** + * SEO/GEO 共享工具(纯 ESM,零依赖)。 + * + * 同时被两类调用方 import: + * 1. VitePress 配置(.ts,esbuild 打包时内联本文件) + * 2. scripts/generate-llms-txt.mjs(Node 直接运行) + * + * 注意:SITE_URL 是全站唯一 URL 真相源。 + * docs 子域当前 TLS 证书为腾讯 CDN 默认证书(*.cdn.myqcloud.com,校验失败), + * 故暂用 http;证书修复后只需改这里一处。 + */ + +export const SITE_URL = "http://docs.tornado.naivevue.djangoadmin.cn"; + +export const SITE_DESCRIPTION = + "DjangoAdmin Tornado+NaiveUI 企业级中台解决方案开发者文档"; + +/** + * 剥离 H1/标题中的章节编号前缀,用于 <title> 与 JSON-LD headline。 + * 例:"5.10 字典模块" → "字典模块";"K. 贡献指南" → "贡献指南"。 + * 页内 H1 与侧边栏编号保持不变,仅影响 SEO 输出。 + */ +export function stripNumberPrefix(title) { + return String(title) + .replace(/^(?:\d+(?:\.\d+)+|[A-Z]\.)\s+/, "") + .trim(); +} + +/** + * 从页面 Markdown 提取 meta description: + * 1. 首选 `:::tip xxx` 容器内的首句(141/143 页的标准 opener) + * 2. 回退到 H1 后的第一个普通段落 + * 输出压缩为单行、去除行内 Markdown,按中文句末标点截断(≤100 字符)。 + */ +export function extractDescription(md) { + const src = String(md); + const fm = src.match(/^---\r?\n([\s\S]*?)\r?\n---/); + const body = fm ? src.slice(fm[0].length) : src; + + let text = ""; + // frontmatter description 显式声明优先(无 H1 页面的补齐手段) + const fmDesc = fm && fm[1].match(/^description:\s*(.+)$/m); + if (fmDesc) { + text = fmDesc[1].trim().replace(/^["']|["']$/g, ""); + } + const tip = !text && body.match(/^:::\s*tip[^\n]*\n([\s\S]*?)\n:::/m); + if (tip) { + text = tip[1]; + } + if (!text) { + const afterH1 = body.match(/^# (?!#)(.+)$/m); + if (afterH1) { + const rest = body.slice((afterH1.index ?? 0) + afterH1[0].length); + const para = rest + .split(/\n{2,}/) + .find( + (p) => + p.trim() && + !/^\s*#/.test(p) && + !/^\s*:::/.test(p) && + !/^\s*```/.test(p) && + !/^\s*\|/.test(p), + ); + text = para || ""; + } + } + + text = text + .replace(/\s+/g, " ") + .replace(/`([^`]+)`/g, "$1") + .replace(/\*\*([^*]+)\*\*/g, "$1") + .replace(/\[([^\]]+)\]\([^)]*\)/g, "$1") + .trim(); + + if (!text) return ""; + + // 按中文句末标点截取首句,上限 100 字符;截断时避免切碎词 + const m = text.match(/^.{1,100}?(?:[。!?!?]|$)/); + let out = m ? m[0] : text.slice(0, 100); + if (out.length < text.length && !/[。!?!?]$/.test(out)) { + out = out.replace(/[^\s,、;:,;:]+$/, ""); + } + return out.trim() || text.slice(0, 100); +} + +function cleanText(s) { + return s + .replace(/^:::[^\n]*$/gm, "") + .replace(/^```[^\n]*$/gm, "") + .replace(/`([^`]+)`/g, "$1") + .replace(/\*\*([^*]+)\*\*/g, "$1") + .replace(/\[([^\]]+)\]\([^)]*\)/g, "$1") + .replace(/\s+/g, " ") + .trim(); +} + +/** + * 提取页面中的 Q/A 对(用于 FAQPage JSON-LD),支持两种站内格式: + * A. `### Q:问题` 标题式(如 zh/quickstart/faq.md) + * B. `**Q:问题**` 加粗式(如 zh/appendix/faq.md) + * 返回 [{ q, a }];无匹配返回 []。 + */ +export function extractFaqs(md) { + const body = String(md).replace(/^---[\s\S]*?\n---\s*/, ""); + let faqs = []; + + // 格式 A:按 `### Q:` 切块,答案截断到下一个标题 + for (const part of body.split(/(?=^###\s*Q[::])/m)) { + const m = part.match(/^###\s*Q[::]\s*([^\n]+)\n+([\s\S]*)/); + if (!m) continue; + let a = m[2]; + const cut = a.search(/^#{1,4}\s/m); + if (cut >= 0) a = a.slice(0, cut); + faqs.push({ q: cleanText(m[1]), a: cleanText(a) }); + } + + // 格式 B:按 `**Q:` 切块 + if (!faqs.length) { + for (const part of body.split(/(?=^\*\*Q[::])/m)) { + const m = part.match(/^\*\*Q[::]\s*([^*]+)\*\*\s*\n+([\s\S]*)/); + if (!m) continue; + let a = m[2]; + const cut = a.search(/^(?:#{1,4}\s|\*\*Q)/m); + if (cut >= 0) a = a.slice(0, cut); + faqs.push({ q: cleanText(m[1]), a: cleanText(a) }); + } + } + + return faqs.filter((f) => f.q && f.a); +} diff --git a/DjangoAdmin_Tornado_NaiveVue/.vitepress/config/index.ts b/DjangoAdmin_Tornado_NaiveVue/.vitepress/config/index.ts index 2294856..6627a76 100644 --- a/DjangoAdmin_Tornado_NaiveVue/.vitepress/config/index.ts +++ b/DjangoAdmin_Tornado_NaiveVue/.vitepress/config/index.ts @@ -1,14 +1,22 @@ import { defineConfig } from "vitepress"; import { enConfig } from "./en"; +import { createSeoHooks } from "./seo"; import { sharedConfig } from "./shared"; import { zhConfig } from "./zh"; +const seo = createSeoHooks(zhConfig.themeConfig?.sidebar); + export default defineConfig({ ...sharedConfig, ignoreDeadLinks: [ (link) => link.includes('localhost'), ], + // SEO:页面级 title/description、canonical/OG/JSON-LD、sitemap+lastmod + transformPageData: seo.transformPageData, + transformHead: seo.transformHead, + sitemap: seo.sitemap, + locales: { root: { label: "简体中文", lang: "zh-CN", link: "/", ...zhConfig }, // root: { label: "English", lang: "en-US", link: "/", ...enConfig }, diff --git a/DjangoAdmin_Tornado_NaiveVue/.vitepress/config/seo.ts b/DjangoAdmin_Tornado_NaiveVue/.vitepress/config/seo.ts new file mode 100644 index 0000000..79ab0ba --- /dev/null +++ b/DjangoAdmin_Tornado_NaiveVue/.vitepress/config/seo.ts @@ -0,0 +1,311 @@ +/** + * SEO/GEO 构建期钩子(仅 Node 构建时运行,不进客户端 bundle): + * - transformPageData:每页独立 title(去编号前缀)与 description(取 :::tip 首句) + * - transformHead:canonical / Open Graph / twitter 卡片 / JSON-LD 结构化数据 + * - sitemap.transformItems:注入 lastmod(git 最后提交时间)并过滤 404 + * + * 由 config/index.ts 通过 createSeoHooks(zhConfig.themeConfig?.sidebar) 挂载。 + * 依赖 extract.mjs(纯 ESM,同被 scripts/generate-llms-txt.mjs 复用)。 + */ +import fs from "node:fs"; +import path from "node:path"; +import { execSync } from "node:child_process"; +import { + SITE_URL, + extractDescription, + extractFaqs, + stripNumberPrefix, +} from "./extract.mjs"; + +/** 与 vitepress HeadConfig 同构:[tag, attrs, innerHTML?] */ +type HeadTuple = [string, Record<string, any>, string?]; + +interface SideItem { + text?: string; + link?: string; + items?: SideItem[]; +} + +interface PageDataLike { + relativePath?: string; + title?: string; + description?: string; + frontmatter?: Record<string, any>; + [k: string]: any; +} + +interface TransformCtx { + pageData?: PageDataLike; + title?: string; + description?: string; + content?: string; + siteConfig?: { root?: string; srcDir?: string }; +} + +const ORG = { + "@type": "Organization", + name: "DjangoAdmin", + url: "https://www.djangoadmin.cn", + logo: `${SITE_URL}/logo.png`, + sameAs: [ + "https://gitee.com/djangoadmin/DjangoAdmin_Tornado_NaiveVue", + "https://www.djangoadmin.cn", + ], +}; + +/** 相对路径 → 站内路由(cleanUrls 关闭,正文页带 .html) */ +function routeOf(relativePath: string): string { + if (relativePath === "index.md") return "/"; + if (relativePath === "404.md") return "/404.html"; + return `/${relativePath.replace(/\.md$/, ".html")}`; +} + +/** 去掉侧边栏文案前导 emoji/符号,保留 "1.1 项目介绍" 这类编号文字 */ +function cleanLabel(s?: string): string { + return (s || "").replace(/^[^\p{L}\p{N}]+/u, "").trim(); +} + +/** 从侧边栏构建 route → 面包屑文案链(含分组小节) */ +function buildCrumbMap(sidebar: unknown): Map<string, string[]> { + const map = new Map<string, string[]>(); + const groups: SideItem[] = Array.isArray(sidebar) + ? sidebar + : ((sidebar as Record<string, SideItem[]>)?.["/zh/"] ?? []); + const walk = (items: SideItem[], trail: string[]) => { + for (const item of items) { + if (item.link && item.link.startsWith("/")) { + map.set(item.link, [...trail, cleanLabel(item.text)]); + } else if (item.items?.length) { + walk(item.items, [...trail, cleanLabel(item.text)]); + } + } + }; + for (const group of groups) { + walk(group.items ?? [], [cleanLabel(group.text)].filter(Boolean)); + } + return map; +} + +/** 从渲染后的 HTML 提取 H1 纯文本(JSON-LD headline 须与页面 H1 一致) */ +function h1OfHtml(html?: string): string { + const m = (html || "").match(/<h1[^>]*>([\s\S]*?)<\/h1>/i); + if (!m) return ""; + return m[1] + .replace(/<[^>]+>/g, "") + .replace(/&/g, "&") + .replace(/</g, "<") + .replace(/>/g, ">") + .replace(/"/g, '"') + .replace(/'/g, "'") + .trim(); +} + +/** 从 Markdown 源提取 H1 纯文本(去除行内 markdown 标记) */ +function h1OfMd(md: string): string { + // 围栏感知:跳过 ``` 代码块内的 # 注释,取真正的页面 H1 + let inFence = false; + for (const line of md.split("\n")) { + if (line.startsWith("```")) { inFence = !inFence; continue; } + if (!inFence && /^# (?!#)/.test(line)) { + return line + .replace(/^# /, "") + .replace(/`([^`]+)`/g, "$1") + .replace(/\*\*([^*]+)\*\*/g, "$1") + .trim(); + } + } + return ""; +} + +export function createSeoHooks(sidebar: unknown) { + const crumbs = buildCrumbMap(sidebar); + const projectDirs: string[] = []; + let gitDates: Map<string, string> | null = null; + + const readMd = (relativePath: string, srcDir?: string): string => { + try { + return fs.readFileSync( + path.resolve(srcDir || process.cwd(), relativePath), + "utf8", + ); + } catch { + return ""; + } + }; + + /** + * 项目内每个文件最后一次 git 提交的 ISO 时间。 + * 单次 git log 调用构建全量映射(key = 相对路径,与 pageData.relativePath 一致); + * git 不可用时静默降级(sitemap 无 lastmod、JSON-LD 无 dateModified)。 + */ + const getGitDates = (root: string): Map<string, string> => { + if (gitDates) return gitDates; + gitDates = new Map<string, string>(); + try { + const out = execSync( + "git log --format=:::%cI --name-only --relative -n 500 -- .", + { + cwd: root, + encoding: "utf8", + maxBuffer: 64 * 1024 * 1024, + stdio: ["ignore", "pipe", "ignore"], + }, + ); + let current = ""; + for (const line of out.split(/\r?\n/)) { + if (line.startsWith(":::")) { + current = line.slice(3).trim(); + continue; + } + const file = line.trim(); + if (file && current && !gitDates.has(file)) { + gitDates.set(file, current); + } + } + } catch { + // 降级:无 lastmod / dateModified + } + return gitDates; + }; + + /** 每页独立 title(去 "5.10 " 编号前缀,关键词前置)与 description(:::tip 首句) */ + function transformPageData(pageData: PageDataLike, ctx?: any): Record<string, unknown> { + const srcDir: string | undefined = ctx?.siteConfig?.srcDir; + const root: string | undefined = ctx?.siteConfig?.root; + if (root && !projectDirs.includes(root)) projectDirs.push(root); + + const out: Record<string, unknown> = {}; + const rel = pageData.relativePath; + if (rel && !pageData.frontmatter?.description) { + const desc = extractDescription(readMd(rel, srcDir)); + if (desc) out.description = desc; + } + if (pageData.title) { + out.title = stripNumberPrefix(pageData.title); + } + return out; + } + + /** 构建期注入 canonical / OG / twitter / JSON-LD */ + function transformHead(ctx: TransformCtx): HeadTuple[] { + const rel = ctx?.pageData?.relativePath || ""; + if (!rel || rel === "404.md") return []; + + const route = routeOf(rel); + const url = `${SITE_URL}${route}`; + const title = ctx.pageData?.title || ctx.title || ""; + const desc = ctx.description || ""; + const isHome = rel === "index.md"; + const image = `${SITE_URL}/logo.png`; + + const heads: HeadTuple[] = [ + ["link", { rel: "canonical", href: url }], + ["meta", { property: "og:type", content: isHome ? "website" : "article" }], + ["meta", { property: "og:site_name", content: "DjangoAdmin" }], + ["meta", { property: "og:locale", content: "zh_CN" }], + ["meta", { property: "og:title", content: title }], + ["meta", { property: "og:description", content: desc }], + ["meta", { property: "og:url", content: url }], + ["meta", { property: "og:image", content: image }], + ["meta", { property: "twitter:title", content: title }], + ["meta", { property: "twitter:description", content: desc }], + ["meta", { property: "twitter:url", content: url }], + ["meta", { property: "twitter:image", content: image }], + ]; + + // ---- JSON-LD ---- + const root = ctx.siteConfig?.root || projectDirs[0] || process.cwd(); + const srcDir = ctx.siteConfig?.srcDir || root; + const lastMod = getGitDates(root).get(rel); + const blocks: Record<string, any>[] = []; + + if (isHome) { + blocks.push({ + "@context": "https://schema.org", + "@type": "WebSite", + name: "DjangoAdmin 开发文档", + url: `${SITE_URL}/`, + inLanguage: "zh-CN", + description: desc, + }); + blocks.push({ "@context": "https://schema.org", ...ORG }); + } else { + const md = readMd(rel, srcDir); + const article: Record<string, any> = { + "@context": "https://schema.org", + "@type": "TechArticle", + headline: h1OfMd(md) || h1OfHtml(ctx.content) || title, + description: desc, + url, + inLanguage: "zh-CN", + mainEntityOfPage: { "@type": "WebPage", "@id": url }, + publisher: ORG, + }; + if (lastMod) article.dateModified = lastMod; + blocks.push(article); + + const trail = crumbs.get(route); + if (trail?.length) { + const items: Record<string, any>[] = [ + { "@type": "ListItem", position: 1, name: "首页", item: `${SITE_URL}/` }, + ]; + trail.forEach((name, i) => { + const node: Record<string, any> = { + "@type": "ListItem", + position: i + 2, + name, + }; + if (i === trail.length - 1) node.item = url; + items.push(node); + }); + blocks.push({ + "@context": "https://schema.org", + "@type": "BreadcrumbList", + itemListElement: items, + }); + } + + const faqs = extractFaqs(md); + if (faqs.length) { + blocks.push({ + "@context": "https://schema.org", + "@type": "FAQPage", + mainEntity: faqs.map((f) => ({ + "@type": "Question", + name: f.q, + acceptedAnswer: { "@type": "Answer", text: f.a }, + })), + }); + } + } + + // 转义 "<",防止内容中出现 </script> 破坏注入 + const json = JSON.stringify(blocks).replace(/</g, "\\u003c"); + heads.push(["script", { type: "application/ld+json" }, json]); + return heads; + } + + /** sitemap.xml:过滤 404/README,注入 git lastmod */ + const sitemap = { + hostname: SITE_URL, + transformItems(items: { url: string; lastmod?: string }[]) { + const root = projectDirs[0] || process.cwd(); + const dates = getGitDates(root); + const out: { url: string; lastmod?: string }[] = []; + for (const item of items) { + // ⚠ vitepress 传入的 item.url 是相对路径("404.html"、"zh/x.html"、""), + // 无前导斜杠也无域名——hostname 由 SitemapStream 事后拼接。 + if (/(^|\/)404\.html$/.test(item.url)) continue; // 404 页不收录 + if (/(^|\/)README\.html$/.test(item.url)) continue; // 仓库 README 非文档页 + const p = item.url.replace(/^\//, ""); + const rel = + p === "" || p === "index.html" ? "index.md" : p.replace(/\.html$/, ".md"); + const lastmod = dates.get(rel); + out.push(lastmod ? { ...item, lastmod } : item); + } + return out; + }, + }; + + return { transformPageData, transformHead, sitemap }; +} diff --git a/DjangoAdmin_Tornado_NaiveVue/.vitepress/config/shared.ts b/DjangoAdmin_Tornado_NaiveVue/.vitepress/config/shared.ts index 67caa1b..e1a6618 100644 --- a/DjangoAdmin_Tornado_NaiveVue/.vitepress/config/shared.ts +++ b/DjangoAdmin_Tornado_NaiveVue/.vitepress/config/shared.ts @@ -1,6 +1,6 @@ import { defineConfig, HeadConfig } from "vitepress"; -export const META_IMAGE = "/social.png"; +export const META_IMAGE = "/logo.png"; const rControl = /[\u0000-\u001f]/g; const rSpecial = /[\s~`!@#$%^&*()\-_+=[\]{}|\\;:"'“”‘’<>,.?/]+/g; @@ -23,6 +23,8 @@ export const slugify = (str: string): string => export const sharedConfig = defineConfig({ title: "小蚂蚁云", + // 页面 <title> 后缀:「环境准备 | DjangoAdmin 开发文档」(index.md frontmatter 可覆盖) + titleTemplate: "DjangoAdmin 开发文档", appearance: "light", markdown: { diff --git a/DjangoAdmin_Tornado_NaiveVue/.vitepress/config/zh.ts b/DjangoAdmin_Tornado_NaiveVue/.vitepress/config/zh.ts index c7c5dbc..36073da 100644 --- a/DjangoAdmin_Tornado_NaiveVue/.vitepress/config/zh.ts +++ b/DjangoAdmin_Tornado_NaiveVue/.vitepress/config/zh.ts @@ -1,8 +1,9 @@ import type { DefaultTheme, LocaleSpecificConfig } from "vitepress"; -export const META_URL = "https://www.djangoadmin.cn"; -export const META_TITLE = "企业级中台解决方案"; -export const META_DESCRIPTION = "企业级中台解决方案"; +export const META_URL = "http://docs.tornado.naivevue.djangoadmin.cn"; +export const META_TITLE = "DjangoAdmin Tornado+NaiveUI 开发文档"; +export const META_DESCRIPTION = + "DjangoAdmin Tornado+NaiveUI 企业级中台解决方案开发者文档"; export const zhConfig: LocaleSpecificConfig<DefaultTheme.Config> = { description: META_DESCRIPTION, diff --git a/DjangoAdmin_Tornado_NaiveVue/404.md b/DjangoAdmin_Tornado_NaiveVue/404.md new file mode 100644 index 0000000..c344b20 --- /dev/null +++ b/DjangoAdmin_Tornado_NaiveVue/404.md @@ -0,0 +1,12 @@ +--- +head: + - - meta + - name: robots + content: noindex +--- + +# 页面不存在 + +抱歉,您访问的页面不存在或已被移动。 + +[返回首页](/) · [浏览文档](/zh/introduction) diff --git a/DjangoAdmin_Tornado_NaiveVue/package.json b/DjangoAdmin_Tornado_NaiveVue/package.json index 77bd941..b5517ed 100644 --- a/DjangoAdmin_Tornado_NaiveVue/package.json +++ b/DjangoAdmin_Tornado_NaiveVue/package.json @@ -5,7 +5,8 @@ "type": "module", "scripts": { "docs": "vitepress dev .", - "docs:build": "vitepress build .", + "docs:llms": "node scripts/generate-llms-txt.mjs", + "docs:build": "node scripts/generate-llms-txt.mjs && vitepress build .", "docs:preview": "vitepress preview ." }, "dependencies": { diff --git a/DjangoAdmin_Tornado_NaiveVue/public/llms.txt b/DjangoAdmin_Tornado_NaiveVue/public/llms.txt new file mode 100644 index 0000000..352d8e4 --- /dev/null +++ b/DjangoAdmin_Tornado_NaiveVue/public/llms.txt @@ -0,0 +1,168 @@ +# DjangoAdmin Tornado+NaiveUI 开发文档 + +> DjangoAdmin Tornado+NaiveUI 企业级中台解决方案开发者文档。内置 RBAC 权限体系、代码生成器等开箱即用功能,支持五种数据库一键切换。本文档共 138 篇,按章节组织。 + +## 1. 了解项目 + +- [更新日志](http://docs.tornado.naivevue.djangoadmin.cn/zh/changelog.html): 更新日志是项目演进的完整记录,帮助开发者和企业了解每个版本的能力变化与技术演进方向。 +- [新手入门指南](http://docs.tornado.naivevue.djangoadmin.cn/zh/course.html): 详细的安装步骤请参考 环境准备 章节。 +- [项目介绍](http://docs.tornado.naivevue.djangoadmin.cn/zh/introduction.html): DjangoAdmin 是企业级中台解决方案,后端基于 Tornado + SQLAlchemy,前端基于 Vue3 + NaiveUI,内置 RBAC 权限、代码生成器等开箱即用功能, +- [项目目录结构](http://docs.tornado.naivevue.djangoadmin.cn/zh/struct.html): + 保持一致性:目录结构一旦确定,应保持一致性,避免随意更改。 +- [为什么选择我们?](http://docs.tornado.naivevue.djangoadmin.cn/zh/why.html): 本框架提供开箱即用的企业级中台完整解决方案,免去从零搭建成本,助力中大型企业构建统一的数字化基座。 + +## 2. 快速入门 + +- [后端启动](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume1/backend.html): 启动后端前,请确保已完成 环境准备 章节中的所有软件安装。 +- [数据库初始化](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume1/database.html): 数据库初始化前,请确保已完成以下准备工作: 1. 目标数据库服务已启动(如 MySQL 8.0+) 2. .env 文件中的 DB_DRIVER 和数据库连接信息已正确配置 3. Python +- [Docker 快速部署](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume1/docker.html): Docker 部署适合快速体验和生产环境。 +- [环境变量速查表](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume1/env-vars.html): 1. .env.example 是环境变量模板文件,已提交到版本控制。 +- [环境准备](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume1/environment.html): 1. 部分软件安装后需要设置本地环境变量,便于在终端中使用命令。 +- [常见问题FAQ](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume1/faq.html): 遇到问题时,建议先查看终端日志输出和浏览器控制台(F12)的错误信息,通常能快速定位问题原因。 +- [第一个接口调试](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume1/first-api.html): 开始调试前,请确保已完成以下步骤: 1. 后端服务已启动(参见 后端启动) 2. 数据库已初始化(参见 数据库初始化) 3. Redis 服务已启动 +- [前端启动](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume1/frontend.html): 启动前端前,请确保已完成 环境准备 章节中的 Node.js 和 pnpm 安装,并已启动后端服务(参见 后端启动)。 + +## 3. 模块开发实战 + +- [完整代码清单](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume2/code-list.html): 本页汇总友链(Link)模块涉及的全部文件代码,开发时可快速查阅与复制对照。 +- [示例模块(Example)](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume2/example.html): src/modules/example/ 是一个完整的示例模块,演示了标准 CRUD 模块的六文件结构和开发模式。 +- [常见问题与排错](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume2/faq.html): 本页汇总模块开发过程中的常见问题与排错方法,开发受阻时按症状索引即可定位。 +- [前端 API 层](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume2/fe-api.html): 前端 API 层封装后端接口的 HTTP 请求,每个业务模块对应一个 API 文件,本页讲解基于 Axios 封装的编写规范。 +- [前端路由与菜单](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume2/fe-router.html): 本页讲解前端路由与菜单机制——路由和菜单由后端动态返回,前端只需注册路由组件映射。 +- [前端页面视图](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume2/fe-view.html): 前端页面视图是用户直接交互的界面,本页讲解 Vue3 + NaiveUI 下一个完整 CRUD 页面的文件组成与编写方式。 +- [请求处理器(Handler)](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume2/handler.html): Handler 层是 HTTP 接口层,负责接收请求、校验权限与记录操作日志,编写新接口从本页开始。 +- [数据模型(Model)](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume2/model.html): BaseModel 是所有业务模型的基类,提供6个通用审计字段和 to_dict() 序列化方法。 +- [概述与目标](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume2/overview.html): 其中 id、create_user、create_time、update_user、update_time、is_delete 由基类 BaseModel 自动提供,业务字段仅需定义 name、 +- [权限节点配置](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume2/permission.html): 实际开发中,查询类权限(page、detail、list)通常合并为一个节点 sys:position:list,减少配置工作量。 +- [Repository 层](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume2/repository.html): Repository 层是数据访问层,封装全部数据库查询操作,本页讲解基于 BaseRepository 基类的通用 CRUD 用法。 +- [路由注册](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume2/router.html): 新模块只需两步: 1. 在 src/api/v1/ 下创建路由文件,定义 routes 列表 2. 在 router.py 的 _RESOURCE_MODULES 中追加模块导入 路由前缀 +- [Pydantic Schema](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume2/schema.html): Schema 层负责请求数据校验,本页讲解基于 Pydantic v2 BaseModel 与 Field 的表单类定义规范。 +- [Service 层](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume2/service.html): repo_cls 是 类属性,值为 Repository 类(不是实例)。 + +## 4. 架构设计 + +- [核心基类体系](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume3/base-classes.html): 四大基类各司其职,覆盖从数据模型到请求校验再到业务逻辑的完整链路。 +- [缓存架构设计](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume3/cache.html): 采用两级缓存架构:第一级为进程内字典缓存(dict_util),第二级为 Redis 分布式缓存。 +- [数据库设计](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume3/database-design.html): 所有业务表继承 base_model 基类,自动获得 6 个通用字段(id / create_user / create_time / update_user / update_time / +- [目录结构设计](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume3/directory.html): 目录结构遵循「按功能分组、按职责分层」的原则。 +- [扩展性设计](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume3/extensibility.html): 遵循开闭原则(OCP):对扩展开放,对修改关闭。 +- [分层架构设计](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume3/layer-arch.html): 采用经典的分层架构,核心原则是:依赖单向、职责单一、接口隔离。 +- [整体架构图](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume3/overview.html): 本页从全局视角阐述系统整体技术架构,涵盖前端、后端、数据库与基础设施等核心组成,理解系统全貌时从本页开始。 +- [请求完整链路](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume3/request-flow.html): 一个典型的 API 请求经过以下阶段:浏览器 → Nginx → Tornado → Handler 生命周期(set_default_headers → prepare → +- [安全架构设计](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume3/security.html): 纵深防御:认证、授权、限流、参数校验多层防护,单一防线失效时仍有其他机制兜底 最小权限:用户仅能访问已授权接口,角色权限按需分配,遵循"够用即可"原则 数据不落地:敏感信息(Token、 +- [技术选型说明](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume3/tech-stack.html): Tornado 是 Python 生态中成熟的异步 Web 框架,基于自有事件循环实现非阻塞 I/O。 +- [Tornado IOLoop 与异步模型](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume3/tornado-async.html): Tornado 基于单线程事件循环(IOLoop),Handler 方法默认为协程(async def)。 + +## 5. 开发指南 + +- [API 接口速查表](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/api-cheatsheet.html): API 接口速查表,按模块分组列出所有 RESTful 接口的请求方法、路径、说明和权限标识。 +- [文章管理](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/business/article.html): 文章管理模块支持富文本编辑、分类关联、封面图片上传、图集管理等功能。 +- [分类管理](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/business/category.html): 分类管理模块用于管理树形分类数据,如文章分类、产品分类等。 +- [行政区划管理](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/business/city.html): 行政区划管理模块提供省市区三级行政区划数据的查询和管理能力,支持树形结构展示和下拉选择。 +- [公告与链接管理](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/business/content.html): 公告、链接、城市是三个简单 CRUD 内容模块,均继承 BaseService,提供标准的增删改查接口。 +- [部门/职级/岗位管理](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/business/dept.html): 部门、职级、岗位是组织架构管理的三个核心模块。 +- [文件模板管理](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/business/file-template.html): 文件模板管理模块提供文件导入导出模板的管理能力,用于维护各种业务场景的 Excel/Word 等模板文件。 +- [定时任务日志](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/business/job-log.html): 定时任务日志模块记录定时任务的执行历史,包括执行时间、执行结果、耗时等信息。 +- [定时任务](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/business/job.html): 定时任务模块基于 APScheduler 实现,支持 Cron 表达式调度、任务执行日志、动态启停等功能。 +- [菜单管理](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/business/menu.html): 菜单管理是 RBAC 权限系统的基础,负责管理系统的导航菜单和权限节点。 +- [参数管理](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/business/param.html): 参数管理模块用于管理动态系统参数,与系统配置模块类似但更侧重于业务参数的灵活配置。 +- [角色管理](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/business/role.html): 角色是 RBAC 权限模型的核心,连接用户和菜单(权限)。 +- [用户管理](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/business/user.html): 用户管理是系统的核心模块,属于复杂业务模块。 +- [认证流程实战](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/core/auth-flow.html): 登录 → Token 获取 → 权限校验 → Token 刷新 → 退出登录的完整认证链路实战说明。 +- [验证码机制](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/core/captcha.html): 验证码是防止自动化攻击的重要安全手段。 +- [系统配置管理](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/core/config.html): 系统配置模块用于管理动态的键值对配置项,与数据字典类似但更偏向系统级参数。 +- [CORS 跨域配置](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/core/cors.html): CORS(Cross-Origin Resource Sharing)跨域资源共享是前后端分离架构必须处理的问题。 +- [演示模式](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/core/demo-mode.html): 演示模式用于在线体验环境,开启后所有写操作(新增、编辑、删除等)将被拦截,返回"演示环境,暂无操作权限"提示。 +- [数据字典使用指南](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/core/dict-guide.html): 数据字典的完整使用流程,从新增字典类型到在代码中使用字典数据的实操指南。 +- [字典模块](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/core/dict.html): 数据字典用于管理系统中的枚举值和配置项,如状态、类型、性别等。 +- [异常与响应处理](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/core/exception.html): 定义了统一的响应格式和全局异常处理机制。 +- [优雅关闭](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/core/graceful-shutdown.html): 优雅关闭确保应用在收到终止信号时,能够完成正在处理的请求、关闭数据库连接、停止定时任务调度器后再退出,避免请求中断和资源泄漏。 +- [用户认证(JWT)](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/core/jwt.html): JWT(JSON Web Token)是的核心认证机制。 +- [登录日志](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/core/login-log.html): 登录日志记录每次登录尝试(成功/失败),包含登录账号、IP地址、浏览器信息、登录时间等。 +- [登录防爆破](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/core/login-protect.html): 登录防爆破机制基于 Redis 实现同一 IP + 用户名维度的连续失败计数与锁定,防止暴力破解密码。 +- [操作日志](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/core/operation-log.html): 操作日志装饰器自动记录写请求(POST/PUT/DELETE/PATCH)的操作日志,无需手动埋点。 +- [权限管理(RBAC)](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/core/rbac.html): 采用基于角色的访问控制(RBAC)模型,通过用户-角色-菜单三层关系实现细粒度的权限管理。 +- [链路追踪(TraceID)](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/core/trace-id.html): 链路追踪通过为每个请求分配唯一的 TraceID,将同一请求的所有日志串联起来,方便问题排查和性能分析。 +- [参数验证(Pydantic)](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/core/validator.html): 使用 Pydantic v2 进行请求参数验证。 +- [API 层开发](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/frontend/api.html): 前端 API 层位于 src/api/ 目录,封装所有与后端的 HTTP 请求。 +- [前端构建](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/frontend/build.html): 前端使用 Vite 构建,支持开发服务器和生产构建。 +- [公共组件库](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/frontend/components.html): 项目提供丰富的公共组件,位于 ui/src/components/ 目录,基于 NaiveUI 二次封装,覆盖表格、表单、弹窗、上传、富文本编辑等常见场景。 +- [BasicForm 表单](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/frontend/form.html): BasicForm 位于 src/components/Form/src/BasicForm.vue,基于 NaiveUI 的 n-form 二次封装,通过 schemas 配置化定义表单字段, +- [Hooks 组合式函数](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/frontend/hooks.html): 项目封装了一系列组合式函数(Hooks),位于 src/hooks/ 和 src/utils/ 目录,提供权限检查、异步 loading、防重复提交、实时时钟、项目配置等可复用逻辑。 +- [国际化](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/frontend/i18n.html): 当前项目仅支持中文界面,NaiveUI 默认使用中文,所有界面文本直接硬编码在组件中。 +- [Modal 弹窗](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/frontend/modal.html): 项目提供 BasicModal 组件(src/components/Modal/src/BasicModal.vue)和 useModal hook 管理弹窗状态。 +- [权限指令 v-perm](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/frontend/perm-directive.html): v-perm 和 v-perms 是项目自定义的 Vue 指令,用于按钮级别的权限控制,无权限时自动从 DOM 中移除元素。 +- [路由与菜单](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/frontend/router.html): 前端路由基于 Vue Router 4 实现动态路由生成,菜单数据从后端获取,通过 generator-routers.ts 递归生成路由表,路由守卫控制登录状态和权限。 +- [前端环境与结构](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/frontend/setup.html): 前端基于 Vue3 + NaiveUI 构建,使用 pnpm 作为包管理工具,Vite 作为构建工具,TypeScript 作为开发语言。 +- [Store 状态管理](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/frontend/store.html): 前端使用 Pinia 进行状态管理,核心模块包括 user(用户信息与权限)、asyncRoute(动态路由与菜单)、projectSetting(项目配置)、designSetting(主题设计)等。 +- [样式与主题](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/frontend/style.html): 前端样式方案采用 Tailwind CSS + SCSS + NaiveUI 主题覆盖,支持深色模式切换。 +- [BasicTable 表格](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/frontend/table.html): BasicTable 位于 src/components/Table/src/Table.vue,基于 NaiveUI 的 n-data-table 二次封装,提供列定义、数据请求、分页、操作列、 +- [工具函数](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/frontend/utils.html): 前端工具函数位于 src/utils/ 目录,提供认证管理、本地存储、日期格式化、树结构操作、文件下载等通用能力。 +- [页面视图开发](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/frontend/view.html): 页面视图位于 src/views/ 目录,每个业务模块遵循 index.vue(列表页)+ edit.vue(编辑弹窗)的标准模式,辅以 columns.ts(列定义)和 +- [接口响应规范](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/integration/api-contract.html): 后端所有接口统一返回 R.ok() / R.failed() 格式的 JSON 响应,前端通过 VAxios 的 transformRequestData 拦截器统一解包处理。 +- [字典数据联调](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/integration/dict-sync.html): 字典数据通过后端字典 API 获取,前端在下拉选择器中渲染选项。 +- [权限节点联动](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/integration/perm-sync.html): 前后端权限通过统一的权限节点字符串联动,后端 @permission_required 校验权限,前端 v-perm 指令和 TableAction 的 auth 属性控制按钮显示。 +- [代理配置](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/integration/proxy.html): 开发环境通过 Vite 代理转发 API 请求到后端,生产环境通过 Nginx 代理。 +- [文件上传联调](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/integration/upload-sync.html): 文件上传涉及前端 Upload 组件、后端上传接口和 URL 拼接三个环节,需要前后端协同配置。 +- [请求上下文(ContextVar)](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/tools/context.html): src/core/context.py 使用 Python 标准库 contextvars 管理请求级别的上下文信息,包括当前用户 ID、用户名、姓名和链路追踪 ID。 +- [数据库会话](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/tools/db-session.html): 数据库会话通过 scoped_session 实现线程级隔离,Repository 层的写操作自动 commit,BaseHandler.on_finish() 兜底关闭会话。 +- [字典缓存工具](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/tools/dict-util.html): src/common/utils/dict_util.py 提供业务字典的缓存读取能力,从 Redis 缓存中获取字典数据,缓存未命中时从数据库加载。 +- [导入导出](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/tools/excel.html): 基于 openpyxl 实现 Excel 导入导出功能,支持通过 file_template 模块管理导入模板配置。 +- [通用 Helper 函数](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/tools/helpers.html): src/common/utils/helpers.py 提供项目中广泛使用的通用工具函数,包括 ID 解析、OS/浏览器检测、参数脱敏等。 +- [IP 归属地解析](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/tools/ip-region.html): src/common/utils/ip2region.py 基于 ip2region 离线数据库,提供 IP 地址到省市区的归属地查询能力,无需网络请求。 +- [日志系统](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/tools/logger.html): 通过 Python 标准库 logging 实现结构化日志,支持控制台 + 文件双输出,日志文件按大小自动轮转。 +- [密码工具](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/tools/password.html): 采用 bcrypt 双重加盐方案存储密码,源码位于 src/core/password.py。 +- [权限缓存](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/tools/perm-cache.html): 通过 Redis 实现用户权限和菜单的缓存,采用用户级缓存 + 全局版本号双层策略。 +- [统一响应封装(R 对象)](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/tools/response.html): src/core/response.py 提供统一的 API 响应封装,所有接口返回格式为 {code, data, msg, ok}。 +- [富文本过滤](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/tools/rich-text.html): 富文本编辑器内容存在存储型 XSS 风险,通过 bleach 库实现 HTML 白名单清洗,在落盘前统一过滤危险内容。 +- [文件上传完整流程](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/tools/upload-guide.html): 富文本编辑器(如 TinyMCE、CKEditor、WangEditor 等)的图片上传同样使用此接口。 +- [文件上传](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume4/tools/upload.html): 提供本地文件上传功能,支持图片和通用文件上传,内置扩展名白名单、大小限制、魔术字节校验和路径遍历防护。 + +## 6. 代码生成器 + +- [CLI 命令行使用](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume5/cli.html): 代码生成器 CLI 模式的使用方法,包括单表生成、批量生成、预览模式和配置导出。 +- [代码生成引擎](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume5/code-engine.html): 代码生成引擎的工作原理,包括配置解析、模板渲染、文件写入和自动注册的完整流程。 +- [配置文件详解](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume5/config.html): 代码生成器 JSON 配置文件的格式说明,包括模块名称、字段属性、字典编码等配置项的详细解释。 +- [实战案例](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume5/demo.html): 以 tornado_example 演示表为完整案例,演示从建表到生成到使用的全流程。 +- [常见问题](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume5/faq.html): 代码生成器使用过程中常见问题的原因分析和解决方案。 +- [概述与架构](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume5/overview.html): 代码生成器的整体架构、核心模块和生成流程概述。 +- [表结构解析引擎](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume5/parser.html): 表结构解析引擎的工作原理,从数据库读取表元数据并智能推断字段用途的过程。 +- [自定义模板](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume5/templates.html): 代码生成器模板的 Jinja2 语法说明,包括模板变量、字段属性和自定义模板的开发方法。 +- [Web 管理界面](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume5/web-ui.html): 代码生成器 Web 管理界面的使用方法,通过可视化界面操作单表生成和批量生成。 + +## 7. 运维部署 + +- [备份与恢复](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume6/backup.html): - 3 份数据副本(1 份生产 + 2 份备份) - 2 种不同存储介质(如本地磁盘 + 远程存储) - 1 份异地备份(防机房级灾难) +- [跨库数据迁移](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume6/db-cross-migrate.html): 项目提供 scripts/migrate_db.py 脚本,支持在不同数据库之间迁移数据(如 MySQL → PostgreSQL / SQL Server / SQLite / Oracle)。 +- [数据库迁移](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume6/db-migrate.html): - 结构迁移:Alembic(自动生成 DDL 差异) - 数据迁移:scripts/migrate_db.py(跨库数据泵) - 初始化:scripts/init_db.py(全新安装一键建库) +- [部署 Checklist](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume6/deploy-checklist.html): 从服务器准备到应用上线的完整部署操作清单,适用于生产环境首次部署和后续版本更新。 +- [Docker容器化](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume6/docker.html): - 环境一致性:消除"在我机器上能跑"的问题 - 快速部署:一条命令启动完整服务 - 资源隔离:应用与宿主机环境解耦 +- [环境规划](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume6/env-plan.html): 各环境之间保持代码一致,仅通过环境变量(.env)区分配置。 +- [健康检查与监控](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume6/monitoring.html): `` 1. 应用层:健康检查端点、业务指标 2. 系统层:CPU/内存/磁盘/网络 3. 中间件:MySQL/Redis 连接状态 4. 日志:集中式日志收集与分析 `` +- [Nginx 反向代理](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume6/nginx.html): `` 客户端 → Nginx(80/443) ├─ / → 前端静态资源(dist/) ├─ /api/v1/... → Tornado 后端(8041) └─ /api/file/ → +- [性能调优](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume6/performance.html): 1. 先测量,后优化:用数据说话,避免盲目调参 2. 瓶颈优先:找到最大瓶颈,集中优化 3. 渐进式:每次只调整一个参数,观察效果 +- [安全加固](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume6/security-hardening.html): - 最小权限:只开放必要的端口和权限 - 纵深防御:多层安全措施叠加 - 默认安全:配置默认值应为安全选项 +- [Supervisor进程管理](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume6/supervisor.html): - Linux 服务器直接部署(非 Docker) - 需要进程自动重启和日志轮转 - 管理多个相关进程 +- [故障排查手册](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume6/troubleshooting.html): 1. 查看日志:tail -f logs/supervisor.out.log 或 docker-compose logs -f 2. 检查配置:.env 文件、数据库连接、Redis 连接 3. +- [版本升级流程](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume6/upgrade.html): 1. 先备份,后升级 2. 先测试环境,后生产环境 3. 每次升级可回滚 4. 低峰期执行升级 + +## 8. 规范标准 + +- [API响应规范](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume7/api-response.html): - 所有接口必须通过 R.ok() 或 R.failed() 返回,禁止直接返回 dict - 成功响应 code=0,失败响应 code=1 - 响应体始终包含 code、data、msg、ok +- [代码审查清单](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume7/code-review.html): - 每次提交必须经过至少一人审查 - 审查关注点:正确性 > 安全性 > 可维护性 > 性能 - 审查意见应具体、可操作,避免主观评价 +- [删除规范](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume7/deletion.html): - is_delete = 0:正常记录(默认值) - is_delete = 1:已删除记录 - 所有查询方法自动过滤 is_delete = 0,业务层无需关心 +- [文档规范](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume7/doc-standard.html): - 文档与代码同步更新 - 使用中文编写(项目约定) - 示例代码可直接运行 +- [前端 API 规范](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume7/fe-api.html): - 每个后端模块对应一个 API 文件 - 函数命名统一使用 名词 + 动词 格式(与后端保持一致) - 请求路径使用相对路径(/position/page),不含 /api/v1 前缀(由 +- [前端页面规范](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume7/fe-component.html): - Vue3(Composition API + <script setup>) - NaiveUI - 自定义组件(BasicTable / BasicForm / TableAction / +- [Git提交规范](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume7/git.html): `` <type>(<scope>): <subject> <body> <footer> `` +- [Handler 层规范](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume7/handler.html): - Handler 只做请求分发,不含业务逻辑 - 通过装饰器控制权限和演示模式 - 委托 Service 处理业务逻辑 - 返回 R 封装的响应 +- [分页规范](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume7/pagination.html): - 前端传递 pageNo(页码,从 1 开始)和 pageSize(每页条数) - 后端返回 {records, total, size, current, pages} 结构 - 默认每页 10 +- [Pydantic Schema规范](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume7/pydantic.html): - 请求体参数必须声明为 Pydantic 模型(Form 类) - 字段约束使用 Field(...) 定义 - 自定义校验使用 @field_validator - 唯一性校验在 Schema +- [Repository层规范](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume7/repository.html): - Repository 只做数据访问原语,不处理 R 封装/序列化/业务逻辑 - 软删除由基类自动处理,子类无需关心 - 查询方法自动跳过 None 值条件 +- [Service层规范](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume7/service.html): BaseService 采用模板方法模式:基类定义流程骨架,子类通过声明差异点和覆盖钩子定制行为。 +- [测试规范](http://docs.tornado.naivevue.djangoadmin.cn/zh/volume7/testing.html): 1. 契约测试(Contract):验证路由、权限、表名等契约不变 2. 单元测试(Unit):验证单个函数/方法的逻辑正确性 3. 集成测试(Integration):验证模块间协作、真实数据库操作 + +## 附录 + +- [常见问题汇总](http://docs.tornado.naivevue.djangoadmin.cn/zh/faq.html): 本页汇总了项目各模块的常见问题及解决方案,按场景分类索引。 +- [免责声明](http://docs.tornado.naivevue.djangoadmin.cn/zh/other/declare.html): 使用本产品前必读的法律声明,明确产品性质、使用限制与责任划分,一旦使用本产品即视为接受本声明全部条款。 +- [广告赞助](http://docs.tornado.naivevue.djangoadmin.cn/zh/other/sponsor.html): 1. 投放广告不得与官方全系产品存在结构性冲突和竞争 2. 广告内容需符合国家法律法规,不得包含虚假、误导性信息 3. 广告素材需经官方审核通过后方可上线,审核周期 1-3 个工作日 4. diff --git a/DjangoAdmin_Tornado_NaiveVue/public/robots.txt b/DjangoAdmin_Tornado_NaiveVue/public/robots.txt new file mode 100644 index 0000000..dd419f6 --- /dev/null +++ b/DjangoAdmin_Tornado_NaiveVue/public/robots.txt @@ -0,0 +1,33 @@ +# DjangoAdmin Tornado+NaiveUI 开发文档 +User-agent: * +Allow: / + +# 显式放行生成式引擎 / AI 爬虫(GEO) +User-agent: GPTBot +Allow: / + +User-agent: ChatGPT-User +Allow: / + +User-agent: ClaudeBot +Allow: / + +User-agent: Claude-Web +Allow: / + +User-agent: anthropic-ai +Allow: / + +User-agent: PerplexityBot +Allow: / + +User-agent: Google-Extended +Allow: / + +User-agent: Bytespider +Allow: / + +User-agent: bingbot +Allow: / + +Sitemap: http://docs.tornado.naivevue.djangoadmin.cn/sitemap.xml diff --git a/DjangoAdmin_Tornado_NaiveVue/scripts/generate-llms-txt.mjs b/DjangoAdmin_Tornado_NaiveVue/scripts/generate-llms-txt.mjs new file mode 100644 index 0000000..02ff8cd --- /dev/null +++ b/DjangoAdmin_Tornado_NaiveVue/scripts/generate-llms-txt.mjs @@ -0,0 +1,122 @@ +#!/usr/bin/env node +/** + * 生成 public/llms.txt(llmstxt.org 标准)——AI 爬虫的站点摘要索引。 + * + * 数据源:zh 目录下全部 Markdown 的 H1 + :::tip 概述首句(与 meta + * description 同源,复用 .vitepress/config/extract.mjs)。按侧边栏章节分组。 + * + * 用法:node scripts/generate-llms-txt.mjs + * 已挂入 package.json 的 docs:build 前置步骤。 + */ +import fs from "node:fs"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; +import { + SITE_URL, + SITE_DESCRIPTION, + extractDescription, +} from "../.vitepress/config/extract.mjs"; + +const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); +const ZH = path.join(ROOT, "zh"); + +/** 顶层目录 → 侧边栏章节名(与 .vitepress/config/zh.ts 保持一致) */ +const SECTIONS = [ + ["", "1. 了解项目"], + ["volume1", "2. 快速入门"], + ["volume2", "3. 模块开发实战"], + ["volume3", "4. 架构设计"], + ["volume4", "5. 开发指南"], + ["volume5", "6. 代码生成器"], + ["volume6", "7. 运维部署"], + ["volume7", "8. 规范标准"], + ["other", "附录"], +]; + +function walk(dir, out = []) { + for (const entry of fs.readdirSync(dir, { withFileTypes: true })) { + const p = path.join(dir, entry.name); + if (entry.isDirectory()) walk(p, out); + else if (entry.name.endsWith(".md")) out.push(p); + } + return out; +} + +/** 提取首个 H1 文本 */ +function h1Of(md) { + // 围栏感知:跳过 ``` 代码块内的 # 注释,取真正的页面 H1 + let inFence = false; + for (const line of md.split("\n")) { + if (line.startsWith("```")) { inFence = !inFence; continue; } + if (!inFence && line.startsWith("# ") && !line.startsWith("## ")) { + return line.slice(2).trim(); + } + } + return ""; +} + +/** H1 编号排序键:"5.10 x" → [5,10];无编号排最后 */ +function sortKey(h1) { + const m = h1.match(/^(\d+(?:\.\d+)*)/); + if (m) return m[1].split(".").map(Number); + const letter = h1.match(/^([A-Z])\./); + if (letter) return [1000 + letter[1].charCodeAt(0)]; + return [9999]; +} + +function cmpKey(a, b) { + const len = Math.max(a.length, b.length); + for (let i = 0; i < len; i++) { + const x = a[i] ?? 0; + const y = b[i] ?? 0; + if (x !== y) return x - y; + } + return 0; +} + +const files = walk(ZH); +const groups = new Map(SECTIONS.map(([dir, label]) => [label, []])); + +for (const file of files) { + const rel = path.relative(ZH, file).replace(/\\/g, "/"); + const topDir = rel.includes("/") ? rel.split("/")[0] : ""; + const base = rel.split("/").pop(); + const label = (topDir === "" && base === "faq.md") ? "附录" + : SECTIONS.find(([dir]) => dir === topDir)?.[1] ?? "附录"; + + const md = fs.readFileSync(file, "utf8"); + const h1 = h1Of(md); + if (!h1) continue; + const desc = extractDescription(md); + const url = `${SITE_URL}/zh/${rel.replace(/\.md$/, ".html")}`; + groups.get(label).push({ h1, desc, url, key: sortKey(h1) }); +} + +const lines = [ + "# DjangoAdmin Tornado+NaiveUI 开发文档", + "", + `> ${SITE_DESCRIPTION}。内置 RBAC 权限体系、代码生成器等开箱即用功能,支持五种数据库一键切换。本文档共 ${files.length} 篇,按章节组织。`, + "", +]; + +// 按章节顺序输出,合并重复 label(appendix/other 同为「附录」,只输出一次) +const printed = new Set(); +for (const [, label] of SECTIONS) { + if (printed.has(label)) continue; + const items = groups.get(label); + if (!items?.length) continue; + printed.add(label); + + lines.push(`## ${label}`, ""); + items.sort((a, b) => cmpKey(a.key, b.key)); + for (const { h1, desc, url } of items) { + lines.push(desc ? `- [${h1}](${url}): ${desc}` : `- [${h1}](${url})`); + } + lines.push(""); +} + +const out = path.join(ROOT, "public", "llms.txt"); +fs.writeFileSync(out, lines.join("\n"), "utf8"); +console.log( + `llms.txt: ${files.length} 页 → ${path.relative(ROOT, out)} (${printed.size} 个章节)`, +); diff --git a/DjangoAdmin_Tornado_NaiveVue/zh/course.md b/DjangoAdmin_Tornado_NaiveVue/zh/course.md index 03b89a5..40cdb8d 100644 --- a/DjangoAdmin_Tornado_NaiveVue/zh/course.md +++ b/DjangoAdmin_Tornado_NaiveVue/zh/course.md @@ -1,3 +1,5 @@ +# 新手入门指南 + :::warning 特别提醒 官方精心制作本教程,目的在于方便用户快速掌握软件产品的使用和部署。通过此教程,刚入行的开发者也可以快速掌握并投入产品研发。本地部署时务必请耐心阅读文档操作。 ::: diff --git a/DjangoAdmin_Tornado_NaiveVue/zh/introduction.md b/DjangoAdmin_Tornado_NaiveVue/zh/introduction.md index f1d32e3..88f703b 100644 --- a/DjangoAdmin_Tornado_NaiveVue/zh/introduction.md +++ b/DjangoAdmin_Tornado_NaiveVue/zh/introduction.md @@ -1,3 +1,9 @@ +# 项目介绍 + +:::tip 概述 +DjangoAdmin 是企业级中台解决方案,后端基于 Tornado + SQLAlchemy,前端基于 Vue3 + NaiveUI,内置 RBAC 权限、代码生成器等开箱即用功能,支持五种数据库一键切换。 +::: + <div align="center"> <p align="center"> <img src="/logo.png" height="150" alt="logo"/> diff --git a/DjangoAdmin_Tornado_NaiveVue/zh/other/declare.md b/DjangoAdmin_Tornado_NaiveVue/zh/other/declare.md index 7737479..915692a 100644 --- a/DjangoAdmin_Tornado_NaiveVue/zh/other/declare.md +++ b/DjangoAdmin_Tornado_NaiveVue/zh/other/declare.md @@ -1,5 +1,9 @@ # 免责声明 +:::tip 概述 +使用本产品前必读的法律声明,明确产品性质、使用限制与责任划分,一旦使用本产品即视为接受本声明全部条款。 +::: + :::danger 重要提示 任何用户在使用本团队研发的系列软件产品(以下简称「本产品」)前,请仔细阅读并透彻理解本声明。选择不使用本产品,可随时停止使用;一旦使用本产品,即视为对本声明全部内容的认可和接受。 ::: diff --git a/DjangoAdmin_Tornado_NaiveVue/zh/struct.md b/DjangoAdmin_Tornado_NaiveVue/zh/struct.md index f5ecc54..743372b 100644 --- a/DjangoAdmin_Tornado_NaiveVue/zh/struct.md +++ b/DjangoAdmin_Tornado_NaiveVue/zh/struct.md @@ -1,3 +1,5 @@ +# 项目目录结构 + ## 目录说明 在软件开发过程中,优秀的软件目录结构对于项目的组织、开发、维护和扩展至关重要,合理的目录结构能够显著提升开发效率和代码可维护性。 diff --git a/DjangoAdmin_Tornado_NaiveVue/zh/volume2/code-list.md b/DjangoAdmin_Tornado_NaiveVue/zh/volume2/code-list.md index a9f8039..8a07b8b 100644 --- a/DjangoAdmin_Tornado_NaiveVue/zh/volume2/code-list.md +++ b/DjangoAdmin_Tornado_NaiveVue/zh/volume2/code-list.md @@ -1,5 +1,9 @@ # 完整代码清单 +:::tip 概述 +本页汇总友链(Link)模块涉及的全部文件代码,开发时可快速查阅与复制对照。 +::: + 本章汇总友链(Link)模块涉及的全部文件,便于开发时快速查阅和复制。 ## 后端文件清单 diff --git a/DjangoAdmin_Tornado_NaiveVue/zh/volume2/faq.md b/DjangoAdmin_Tornado_NaiveVue/zh/volume2/faq.md index e9c1218..f372f58 100644 --- a/DjangoAdmin_Tornado_NaiveVue/zh/volume2/faq.md +++ b/DjangoAdmin_Tornado_NaiveVue/zh/volume2/faq.md @@ -1,5 +1,9 @@ # 常见问题与排错 +:::tip 概述 +本页汇总模块开发过程中的常见问题与排错方法,开发受阻时按症状索引即可定位。 +::: + 本章汇总模块开发过程中的常见问题和解决方案。 ## 后端问题 diff --git a/DjangoAdmin_Tornado_NaiveVue/zh/volume2/fe-api.md b/DjangoAdmin_Tornado_NaiveVue/zh/volume2/fe-api.md index 797cc1c..ae9203a 100644 --- a/DjangoAdmin_Tornado_NaiveVue/zh/volume2/fe-api.md +++ b/DjangoAdmin_Tornado_NaiveVue/zh/volume2/fe-api.md @@ -1,5 +1,9 @@ # 前端 API 层 +:::tip 概述 +前端 API 层封装后端接口的 HTTP 请求,每个业务模块对应一个 API 文件,本页讲解基于 Axios 封装的编写规范。 +::: + 前端 API 层负责封装后端接口的 HTTP 请求。每个业务模块对应一个 API 文件,使用项目封装的 Axios 工具发送请求。 ## 文件位置 diff --git a/DjangoAdmin_Tornado_NaiveVue/zh/volume2/fe-router.md b/DjangoAdmin_Tornado_NaiveVue/zh/volume2/fe-router.md index 0f79bbe..5c2330b 100644 --- a/DjangoAdmin_Tornado_NaiveVue/zh/volume2/fe-router.md +++ b/DjangoAdmin_Tornado_NaiveVue/zh/volume2/fe-router.md @@ -1,5 +1,9 @@ # 前端路由与菜单 +:::tip 概述 +本页讲解前端路由与菜单机制——路由和菜单由后端动态返回,前端只需注册路由组件映射。 +::: + 前端路由定义页面的访问路径,菜单是路由的可视化展示。项目的路由和菜单由后端动态返回,前端只需注册路由组件映射。 ## 路由配置 diff --git a/DjangoAdmin_Tornado_NaiveVue/zh/volume2/fe-view.md b/DjangoAdmin_Tornado_NaiveVue/zh/volume2/fe-view.md index 0b8a7ae..5ce9bc6 100644 --- a/DjangoAdmin_Tornado_NaiveVue/zh/volume2/fe-view.md +++ b/DjangoAdmin_Tornado_NaiveVue/zh/volume2/fe-view.md @@ -1,5 +1,9 @@ # 前端页面视图 +:::tip 概述 +前端页面视图是用户直接交互的界面,本页讲解 Vue3 + NaiveUI 下一个完整 CRUD 页面的文件组成与编写方式。 +::: + 前端页面视图是用户直接交互的界面。项目使用 Vue3 + NaiveUI + Vite 构建。一个完整的 CRUD 页面由 4 个文件组成: ``` diff --git a/DjangoAdmin_Tornado_NaiveVue/zh/volume2/handler.md b/DjangoAdmin_Tornado_NaiveVue/zh/volume2/handler.md index 9e36ff4..92cbf81 100644 --- a/DjangoAdmin_Tornado_NaiveVue/zh/volume2/handler.md +++ b/DjangoAdmin_Tornado_NaiveVue/zh/volume2/handler.md @@ -1,5 +1,9 @@ # 请求处理器(Handler) +:::tip 概述 +Handler 层是 HTTP 接口层,负责接收请求、校验权限与记录操作日志,编写新接口从本页开始。 +::: + Handler 层是 HTTP 接口层,负责接收请求、校验权限、记录操作日志,然后委托给 Service 层处理。每个业务模块对应一个 `handlers.py` 文件,所有 Handler 继承 `BaseHandler`。 ## 文件位置 diff --git a/DjangoAdmin_Tornado_NaiveVue/zh/volume2/repository.md b/DjangoAdmin_Tornado_NaiveVue/zh/volume2/repository.md index e03b9b2..8009a30 100644 --- a/DjangoAdmin_Tornado_NaiveVue/zh/volume2/repository.md +++ b/DjangoAdmin_Tornado_NaiveVue/zh/volume2/repository.md @@ -1,5 +1,9 @@ # Repository 层 +:::tip 概述 +Repository 层是数据访问层,封装全部数据库查询操作,本页讲解基于 BaseRepository 基类的通用 CRUD 用法。 +::: + Repository 层是数据访问层,封装所有数据库查询操作。项目通过 `BaseRepository` 基类提供通用 CRUD 能力,子类通常只需声明类名,无需编写任何代码。 ## 文件位置 diff --git a/DjangoAdmin_Tornado_NaiveVue/zh/volume2/schema.md b/DjangoAdmin_Tornado_NaiveVue/zh/volume2/schema.md index 4069def..7917550 100644 --- a/DjangoAdmin_Tornado_NaiveVue/zh/volume2/schema.md +++ b/DjangoAdmin_Tornado_NaiveVue/zh/volume2/schema.md @@ -1,5 +1,9 @@ # Pydantic Schema +:::tip 概述 +Schema 层负责请求数据校验,本页讲解基于 Pydantic v2 BaseModel 与 Field 的表单类定义规范。 +::: + Schema 层负责请求数据的校验。项目使用 Pydantic v2 的 `BaseModel` 定义表单类,通过 `Field` 约束字段格式,Tornado 在接收请求体时自动执行校验。 ## 文件位置 diff --git a/DjangoAdmin_Tornado_NaiveVue/zh/volume3/overview.md b/DjangoAdmin_Tornado_NaiveVue/zh/volume3/overview.md index bc72c29..6301b2a 100644 --- a/DjangoAdmin_Tornado_NaiveVue/zh/volume3/overview.md +++ b/DjangoAdmin_Tornado_NaiveVue/zh/volume3/overview.md @@ -1,5 +1,9 @@ # 整体架构图 +:::tip 概述 +本页从全局视角阐述系统整体技术架构,涵盖前端、后端、数据库与基础设施等核心组成,理解系统全貌时从本页开始。 +::: + 本章从全局视角阐述系统的整体技术架构,涵盖前端、后端、数据库及基础设施等核心组成部分。 ## 架构总览 diff --git a/DjangoAdmin_Tornado_NaiveVue/zh/volume4/business/article.md b/DjangoAdmin_Tornado_NaiveVue/zh/volume4/business/article.md index a29edc0..407a1a9 100644 --- a/DjangoAdmin_Tornado_NaiveVue/zh/volume4/business/article.md +++ b/DjangoAdmin_Tornado_NaiveVue/zh/volume4/business/article.md @@ -1,3 +1,5 @@ +# 文章管理 + :::tip 文章管理 文章管理模块支持富文本编辑、分类关联、封面图片上传、图集管理等功能。适用于新闻、公告、帮助文档等内容管理场景。本模块是典型的「带文件处理」业务模块,涵盖了封面迁移、图集处理、富文本 XSS 清洗等核心机制。 ::: diff --git a/DjangoAdmin_Tornado_NaiveVue/zh/volume4/business/category.md b/DjangoAdmin_Tornado_NaiveVue/zh/volume4/business/category.md index cff130e..f4ebd3b 100644 --- a/DjangoAdmin_Tornado_NaiveVue/zh/volume4/business/category.md +++ b/DjangoAdmin_Tornado_NaiveVue/zh/volume4/business/category.md @@ -1,3 +1,5 @@ +# 分类管理 + :::tip 分类管理 分类管理模块用于管理树形分类数据,如文章分类、产品分类等。通过 `parent_id` 字段实现无限级分类。 ::: diff --git a/DjangoAdmin_Tornado_NaiveVue/zh/volume4/business/content.md b/DjangoAdmin_Tornado_NaiveVue/zh/volume4/business/content.md index 1d13da6..c34a44b 100644 --- a/DjangoAdmin_Tornado_NaiveVue/zh/volume4/business/content.md +++ b/DjangoAdmin_Tornado_NaiveVue/zh/volume4/business/content.md @@ -1,3 +1,5 @@ +# 公告与链接管理 + :::tip 公告/链接/城市 公告、链接、城市是三个简单 CRUD 内容模块,均继承 BaseService,提供标准的增删改查接口。适用于系统公告、友情链接、城市数据等场景。 ::: diff --git a/DjangoAdmin_Tornado_NaiveVue/zh/volume4/business/dept.md b/DjangoAdmin_Tornado_NaiveVue/zh/volume4/business/dept.md index 8759e6d..f3a6c15 100644 --- a/DjangoAdmin_Tornado_NaiveVue/zh/volume4/business/dept.md +++ b/DjangoAdmin_Tornado_NaiveVue/zh/volume4/business/dept.md @@ -1,3 +1,5 @@ +# 部门/职级/岗位管理 + :::tip 部门/职级/岗位 部门、职级、岗位是组织架构管理的三个核心模块。部门采用树形结构,职级和岗位为简单 CRUD 模块,均继承 `BaseService`。用户表通过 `dept_id`、`position_id`、`level_id` 三个外键关联这三个模块。 ::: diff --git a/DjangoAdmin_Tornado_NaiveVue/zh/volume4/business/job.md b/DjangoAdmin_Tornado_NaiveVue/zh/volume4/business/job.md index bab60c1..0e4cfd1 100644 --- a/DjangoAdmin_Tornado_NaiveVue/zh/volume4/business/job.md +++ b/DjangoAdmin_Tornado_NaiveVue/zh/volume4/business/job.md @@ -1,3 +1,5 @@ +# 定时任务 + :::tip 定时任务 定时任务模块基于 APScheduler 实现,支持 Cron 表达式调度、任务执行日志、动态启停等功能。包含 job(任务定义)、job_log(执行日志)、scheduler(调度器)三个子模块。 ::: diff --git a/DjangoAdmin_Tornado_NaiveVue/zh/volume4/business/menu.md b/DjangoAdmin_Tornado_NaiveVue/zh/volume4/business/menu.md index 48b3b0d..5590488 100644 --- a/DjangoAdmin_Tornado_NaiveVue/zh/volume4/business/menu.md +++ b/DjangoAdmin_Tornado_NaiveVue/zh/volume4/business/menu.md @@ -1,3 +1,5 @@ +# 菜单管理 + :::tip 菜单管理 菜单管理是 RBAC 权限系统的基础,负责管理系统的导航菜单和权限节点。支持目录/菜单(type=0)和权限按钮节点(type=1)两种类型,通过树形结构组织。权限节点由系统根据前端勾选自动生成,采用 `sys:module:action` 三段式命名。 ::: diff --git a/DjangoAdmin_Tornado_NaiveVue/zh/volume4/business/param.md b/DjangoAdmin_Tornado_NaiveVue/zh/volume4/business/param.md index 79448fe..a98c3ef 100644 --- a/DjangoAdmin_Tornado_NaiveVue/zh/volume4/business/param.md +++ b/DjangoAdmin_Tornado_NaiveVue/zh/volume4/business/param.md @@ -1,3 +1,5 @@ +# 参数管理 + :::tip 参数管理 参数管理模块用于管理动态系统参数,与系统配置模块类似但更侧重于业务参数的灵活配置。支持按参数键查询、修改,无需重启服务即可生效。本模块是典型的「BaseService 简单模块」,通过声明差异点即可获得完整 CRUD 能力。 ::: diff --git a/DjangoAdmin_Tornado_NaiveVue/zh/volume4/business/role.md b/DjangoAdmin_Tornado_NaiveVue/zh/volume4/business/role.md index afb9a5e..2978c8c 100644 --- a/DjangoAdmin_Tornado_NaiveVue/zh/volume4/business/role.md +++ b/DjangoAdmin_Tornado_NaiveVue/zh/volume4/business/role.md @@ -1,3 +1,5 @@ +# 角色管理 + :::tip 角色管理 角色是 RBAC 权限模型的核心,连接用户和菜单(权限)。通过为角色分配菜单权限,再将角色分配给用户,实现灵活的权限管理。角色删除时需清理关联的用户角色和角色菜单数据,并即时失效受影响用户的权限缓存。 ::: diff --git a/DjangoAdmin_Tornado_NaiveVue/zh/volume4/business/user.md b/DjangoAdmin_Tornado_NaiveVue/zh/volume4/business/user.md index d1d07c0..8fb95e6 100644 --- a/DjangoAdmin_Tornado_NaiveVue/zh/volume4/business/user.md +++ b/DjangoAdmin_Tornado_NaiveVue/zh/volume4/business/user.md @@ -1,3 +1,5 @@ +# 用户管理 + :::tip 用户管理 用户管理是系统的核心模块,属于复杂业务模块。包含用户 CRUD、角色关联、密码加密、行政区划、Excel 导入导出等功能。与简单 CRUD 模块不同,用户管理使用自定义 service 函数而非继承 BaseService 的类方法。 ::: diff --git a/DjangoAdmin_Tornado_NaiveVue/zh/volume4/core/captcha.md b/DjangoAdmin_Tornado_NaiveVue/zh/volume4/core/captcha.md index cc7daf8..a7c973b 100644 --- a/DjangoAdmin_Tornado_NaiveVue/zh/volume4/core/captcha.md +++ b/DjangoAdmin_Tornado_NaiveVue/zh/volume4/core/captcha.md @@ -1,3 +1,5 @@ +# 验证码机制 + :::tip 验证码 验证码是防止自动化攻击的重要安全手段。使用 Pillow 生成图片验证码,存储在 Redis 中,支持防刷限流和万能验证码(演示模式)。源码位于 `src/common/utils/captcha.py`。 ::: diff --git a/DjangoAdmin_Tornado_NaiveVue/zh/volume4/core/config.md b/DjangoAdmin_Tornado_NaiveVue/zh/volume4/core/config.md index d2def98..1b152ed 100644 --- a/DjangoAdmin_Tornado_NaiveVue/zh/volume4/core/config.md +++ b/DjangoAdmin_Tornado_NaiveVue/zh/volume4/core/config.md @@ -1,3 +1,5 @@ +# 系统配置管理 + :::tip 系统配置 系统配置模块用于管理动态的键值对配置项,与数据字典类似但更偏向系统级参数。支持分组管理,可通过接口动态修改,无需重启服务。模块位于 `src/modules/config/` 和 `src/modules/config_item/`,路由位于 `src/api/v1/config.py` 和 `config_item.py`。 ::: diff --git a/DjangoAdmin_Tornado_NaiveVue/zh/volume4/core/demo-mode.md b/DjangoAdmin_Tornado_NaiveVue/zh/volume4/core/demo-mode.md index 272db54..380900a 100644 --- a/DjangoAdmin_Tornado_NaiveVue/zh/volume4/core/demo-mode.md +++ b/DjangoAdmin_Tornado_NaiveVue/zh/volume4/core/demo-mode.md @@ -1,3 +1,5 @@ +# 演示模式 + :::tip 演示模式 演示模式用于在线体验环境,开启后所有写操作(新增、编辑、删除等)将被拦截,返回"演示环境,暂无操作权限"提示。通过 `TORNADO_DEMO` 环境变量控制。装饰器位于 `src/common/middleware/access_decorators.py`。 ::: diff --git a/DjangoAdmin_Tornado_NaiveVue/zh/volume4/core/dict.md b/DjangoAdmin_Tornado_NaiveVue/zh/volume4/core/dict.md index 3ffe8dc..207a313 100644 --- a/DjangoAdmin_Tornado_NaiveVue/zh/volume4/core/dict.md +++ b/DjangoAdmin_Tornado_NaiveVue/zh/volume4/core/dict.md @@ -1,3 +1,5 @@ +# 字典模块 + :::tip 数据字典 数据字典用于管理系统中的枚举值和配置项,如状态、类型、性别等。通过字典编码统一管理,前端可通过 `useDictStore` 获取字典选项,避免硬编码。后端读取工具位于 `src/common/utils/dict_util.py`,内置进程内 TTL 缓存。 ::: diff --git a/DjangoAdmin_Tornado_NaiveVue/zh/volume4/core/exception.md b/DjangoAdmin_Tornado_NaiveVue/zh/volume4/core/exception.md index 6783f7e..379b7af 100644 --- a/DjangoAdmin_Tornado_NaiveVue/zh/volume4/core/exception.md +++ b/DjangoAdmin_Tornado_NaiveVue/zh/volume4/core/exception.md @@ -1,3 +1,5 @@ +# 异常与响应处理 + :::tip 全局异常与响应 定义了统一的响应格式和全局异常处理机制。所有 API 返回 `{code, data, msg, ok}` 标准格式,异常被捕获后也转换为相同格式。响应函数位于 `src/core/response.py`,异常类型位于 `src/core/exceptions.py`。 ::: diff --git a/DjangoAdmin_Tornado_NaiveVue/zh/volume4/core/jwt.md b/DjangoAdmin_Tornado_NaiveVue/zh/volume4/core/jwt.md index 5b22053..a1a54b9 100644 --- a/DjangoAdmin_Tornado_NaiveVue/zh/volume4/core/jwt.md +++ b/DjangoAdmin_Tornado_NaiveVue/zh/volume4/core/jwt.md @@ -1,3 +1,5 @@ +# 用户认证(JWT) + :::tip JWT认证 JWT(JSON Web Token)是的核心认证机制。用户登录成功后获取 Token,后续请求通过 `Authorization: Bearer <token>` 头携带 Token 进行身份验证。项目内置了 Token 生成、解析、刷新和黑名单管理功能,源码位于 `src/core/jwt.py`。 ::: diff --git a/DjangoAdmin_Tornado_NaiveVue/zh/volume4/core/login-log.md b/DjangoAdmin_Tornado_NaiveVue/zh/volume4/core/login-log.md index 0a9fc2f..b37a3b3 100644 --- a/DjangoAdmin_Tornado_NaiveVue/zh/volume4/core/login-log.md +++ b/DjangoAdmin_Tornado_NaiveVue/zh/volume4/core/login-log.md @@ -1,3 +1,5 @@ +# 登录日志 + :::tip 登录日志 登录日志记录每次登录尝试(成功/失败),包含登录账号、IP地址、浏览器信息、登录时间等。支持 IP 地理位置解析(ip2region)和 User-Agent 解析。登录逻辑位于 `src/modules/auth/service.py`,日志记录位于 `src/modules/login_log/service.py`。 ::: diff --git a/DjangoAdmin_Tornado_NaiveVue/zh/volume4/core/operation-log.md b/DjangoAdmin_Tornado_NaiveVue/zh/volume4/core/operation-log.md index 3200aa9..35c01e9 100644 --- a/DjangoAdmin_Tornado_NaiveVue/zh/volume4/core/operation-log.md +++ b/DjangoAdmin_Tornado_NaiveVue/zh/volume4/core/operation-log.md @@ -1,3 +1,5 @@ +# 操作日志 + :::tip 操作日志 操作日志装饰器自动记录写请求(POST/PUT/DELETE/PATCH)的操作日志,无需手动埋点。源码位于 `src/common/middleware/operation_log.py`。 ::: diff --git a/DjangoAdmin_Tornado_NaiveVue/zh/volume4/core/rbac.md b/DjangoAdmin_Tornado_NaiveVue/zh/volume4/core/rbac.md index 488be70..5672dbe 100644 --- a/DjangoAdmin_Tornado_NaiveVue/zh/volume4/core/rbac.md +++ b/DjangoAdmin_Tornado_NaiveVue/zh/volume4/core/rbac.md @@ -1,3 +1,5 @@ +# 权限管理(RBAC) + :::tip RBAC权限 采用基于角色的访问控制(RBAC)模型,通过用户-角色-菜单三层关系实现细粒度的权限管理。权限控制贯穿前后端:后端通过 `@permission_required` 装饰器校验(`src/common/middleware/access_decorators.py`),前端通过 `v-perm` 指令控制按钮显隐。 ::: diff --git a/DjangoAdmin_Tornado_NaiveVue/zh/volume4/core/validator.md b/DjangoAdmin_Tornado_NaiveVue/zh/volume4/core/validator.md index 9b683df..8b6e019 100644 --- a/DjangoAdmin_Tornado_NaiveVue/zh/volume4/core/validator.md +++ b/DjangoAdmin_Tornado_NaiveVue/zh/volume4/core/validator.md @@ -1,3 +1,5 @@ +# 参数验证(Pydantic) + :::tip 参数验证 使用 Pydantic v2 进行请求参数验证。所有请求体参数通过 Pydantic BaseModel 定义,Tornado 自动解析和验证 JSON 请求体,验证失败返回标准格式错误信息。BaseSchema 基类位于 `src/core/base_schema.py`。 ::: diff --git a/DjangoAdmin_Tornado_NaiveVue/zh/why.md b/DjangoAdmin_Tornado_NaiveVue/zh/why.md index 1068d3b..48e3dbd 100644 --- a/DjangoAdmin_Tornado_NaiveVue/zh/why.md +++ b/DjangoAdmin_Tornado_NaiveVue/zh/why.md @@ -1,7 +1,7 @@ # 为什么选择我们? :::tip 核心价值 -企业级数据中台不应从零搭建。本框架提供开箱即用的完整解决方案,为中大型企业构建统一的数字化基座。 +本框架提供开箱即用的企业级中台完整解决方案,免去从零搭建成本,助力中大型企业构建统一的数字化基座。 ::: ## 解决什么问题?