create-lumfall 1.0.0 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -17
- package/cli.js +179 -24
- package/package.json +5 -7
- package/templates/basic/README.md +0 -113
- package/templates/basic/app/controller/demo.js +0 -28
- package/templates/basic/app/extend/README.md +0 -3
- package/templates/basic/app/middleware/README.md +0 -2
- package/templates/basic/app/middleware.js +0 -13
- package/templates/basic/app/pages/home/entry.home.js +0 -4
- package/templates/basic/app/pages/home/home.vue +0 -164
- package/templates/basic/app/router/demo.js +0 -17
- package/templates/basic/app/router-schema/demo.js +0 -29
- package/templates/basic/app/service/demo.js +0 -51
- package/templates/basic/app/webpack.config.js +0 -4
- package/templates/basic/build.js +0 -7
- package/templates/basic/config/config.beta.js +0 -4
- package/templates/basic/config/config.default.js +0 -32
- package/templates/basic/config/config.local.js +0 -4
- package/templates/basic/config/config.prod.js +0 -6
- package/templates/basic/package.json +0 -31
- package/templates/basic/server.js +0 -26
- package/templates/document/README.md +0 -145
- package/templates/document/app/extend/README.md +0 -6
- package/templates/document/app/middleware/README.md +0 -2
- package/templates/document/app/middleware.js +0 -2
- package/templates/document/app/pages/docs/assets/docs-logo.svg +0 -5
- package/templates/document/app/pages/docs/components/doc-layout.vue +0 -144
- package/templates/document/app/pages/docs/components/doc-navbar.vue +0 -103
- package/templates/document/app/pages/docs/components/doc-search.vue +0 -131
- package/templates/document/app/pages/docs/components/doc-sidebar.vue +0 -29
- package/templates/document/app/pages/docs/components/doc-toc.vue +0 -21
- package/templates/document/app/pages/docs/content.js +0 -28
- package/templates/document/app/pages/docs/docs-config.js +0 -154
- package/templates/document/app/pages/docs/docs.vue +0 -24
- package/templates/document/app/pages/docs/entry.docs.js +0 -26
- package/templates/document/app/pages/docs/markdown/highlight.js +0 -30
- package/templates/document/app/pages/docs/markdown/index.js +0 -129
- package/templates/document/app/pages/docs/search.js +0 -142
- package/templates/document/app/pages/docs/styles/docs.less +0 -1091
- package/templates/document/app/pages/docs/styles/vars.less +0 -87
- package/templates/document/app/pages/docs/theme.js +0 -47
- package/templates/document/app/pages/docs/utils.js +0 -58
- package/templates/document/app/pages/docs/views/doc-home.vue +0 -56
- package/templates/document/app/pages/docs/views/doc-page.vue +0 -147
- package/templates/document/app/webpack.config.js +0 -15
- package/templates/document/build.js +0 -6
- package/templates/document/config/config.beta.js +0 -2
- package/templates/document/config/config.default.js +0 -9
- package/templates/document/config/config.local.js +0 -2
- package/templates/document/config/config.prod.js +0 -2
- package/templates/document/docs/advanced/dashboard.md +0 -66
- package/templates/document/docs/advanced/health.md +0 -72
- package/templates/document/docs/advanced/monitoring.md +0 -60
- package/templates/document/docs/advanced/security.md +0 -88
- package/templates/document/docs/core/app-instance.md +0 -114
- package/templates/document/docs/core/controller-service.md +0 -113
- package/templates/document/docs/core/lifecycle.md +0 -60
- package/templates/document/docs/core/middleware.md +0 -83
- package/templates/document/docs/core/plugins.md +0 -77
- package/templates/document/docs/core/router-schema.md +0 -102
- package/templates/document/docs/dsl/api-contract.md +0 -88
- package/templates/document/docs/dsl/extend.md +0 -311
- package/templates/document/docs/dsl/menu.md +0 -101
- package/templates/document/docs/dsl/model-project.md +0 -122
- package/templates/document/docs/dsl/overview.md +0 -116
- package/templates/document/docs/dsl/reference.md +0 -175
- package/templates/document/docs/dsl/schema-actions.md +0 -135
- package/templates/document/docs/dsl/schema.md +0 -121
- package/templates/document/docs/frontend/build.md +0 -118
- package/templates/document/docs/frontend/curl.md +0 -75
- package/templates/document/docs/frontend/page.md +0 -99
- package/templates/document/docs/frontend/widgets.md +0 -151
- package/templates/document/docs/guide/config.md +0 -108
- package/templates/document/docs/guide/deployment.md +0 -115
- package/templates/document/docs/guide/getting-started.md +0 -199
- package/templates/document/docs/guide/introduction.md +0 -55
- package/templates/document/docs/guide/structure.md +0 -98
- package/templates/document/docs/reference/commands.md +0 -70
- package/templates/document/docs/reference/faq.md +0 -94
- package/templates/document/package.json +0 -36
- package/templates/document/scripts/build-static.js +0 -129
- package/templates/document/server.js +0 -13
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<main class="home-page">
|
|
3
|
-
<section class="hero">
|
|
4
|
-
<h1 class="hero-title">Lumfall Basic Project</h1>
|
|
5
|
-
<p class="hero-desc">
|
|
6
|
-
基于 lumfall 的基础业务项目骨架。这个页面演示了:页面入口约定、
|
|
7
|
-
$lumfallCurl 调用 /api 接口、参数校验与统一响应结构。
|
|
8
|
-
</p>
|
|
9
|
-
<div class="hero-links">
|
|
10
|
-
<a-button type="primary" @click="goHealth">健康检查页</a-button>
|
|
11
|
-
<a-button @click="loadData">刷新数据</a-button>
|
|
12
|
-
</div>
|
|
13
|
-
</section>
|
|
14
|
-
|
|
15
|
-
<a-card class="panel" title="服务端配置(GET /api/demo/info)">
|
|
16
|
-
<a-descriptions :column="1" size="medium" v-if="info">
|
|
17
|
-
<a-descriptions-item label="应用名">{{ info.appName }}</a-descriptions-item>
|
|
18
|
-
<a-descriptions-item label="demoMessage">
|
|
19
|
-
<a-tag color="arcoblue">{{ info.demoMessage }}</a-tag>
|
|
20
|
-
</a-descriptions-item>
|
|
21
|
-
<a-descriptions-item label="服务端时间">{{ info.serverTime }}</a-descriptions-item>
|
|
22
|
-
</a-descriptions>
|
|
23
|
-
</a-card>
|
|
24
|
-
|
|
25
|
-
<a-card class="panel" title="笔记列表(GET /api/demo/note/list)">
|
|
26
|
-
<template #extra>
|
|
27
|
-
<a-space>
|
|
28
|
-
<a-input-search
|
|
29
|
-
v-model="newNote"
|
|
30
|
-
placeholder="输入内容,回车新建笔记"
|
|
31
|
-
style="width: 260px"
|
|
32
|
-
@search="handleCreate"
|
|
33
|
-
allow-clear
|
|
34
|
-
/>
|
|
35
|
-
</a-space>
|
|
36
|
-
</template>
|
|
37
|
-
|
|
38
|
-
<a-table
|
|
39
|
-
:data="noteList"
|
|
40
|
-
:loading="loading"
|
|
41
|
-
:pagination="pagination"
|
|
42
|
-
size="medium"
|
|
43
|
-
>
|
|
44
|
-
<template #columns>
|
|
45
|
-
<a-table-column title="ID" data-index="id" :width="80" />
|
|
46
|
-
<a-table-column title="内容" data-index="content" />
|
|
47
|
-
<a-table-column title="创建时间" data-index="createdAt" :width="200" />
|
|
48
|
-
</template>
|
|
49
|
-
</a-table>
|
|
50
|
-
</a-card>
|
|
51
|
-
</main>
|
|
52
|
-
</template>
|
|
53
|
-
|
|
54
|
-
<script setup>
|
|
55
|
-
import { computed, onMounted, ref } from "vue";
|
|
56
|
-
import { Message } from "@arco-design/web-vue";
|
|
57
|
-
import $curl from "$lumfallCurl";
|
|
58
|
-
|
|
59
|
-
const info = ref(null);
|
|
60
|
-
const noteList = ref([]);
|
|
61
|
-
const loading = ref(false);
|
|
62
|
-
const newNote = ref("");
|
|
63
|
-
const total = ref(0);
|
|
64
|
-
const currentPage = ref(1);
|
|
65
|
-
const pageSize = ref(10);
|
|
66
|
-
|
|
67
|
-
const pagination = computed(() => ({
|
|
68
|
-
total: total.value,
|
|
69
|
-
current: currentPage.value,
|
|
70
|
-
pageSize: pageSize.value,
|
|
71
|
-
showTotal: true,
|
|
72
|
-
}));
|
|
73
|
-
|
|
74
|
-
async function loadInfo() {
|
|
75
|
-
const res = await $curl({ method: "get", url: "/api/demo/info" });
|
|
76
|
-
if (res && res.success) {
|
|
77
|
-
info.value = res.data;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
async function loadNoteList() {
|
|
82
|
-
loading.value = true;
|
|
83
|
-
const res = await $curl({
|
|
84
|
-
method: "get",
|
|
85
|
-
url: "/api/demo/note/list",
|
|
86
|
-
query: {
|
|
87
|
-
page: String(currentPage.value),
|
|
88
|
-
pageSize: String(pageSize.value),
|
|
89
|
-
},
|
|
90
|
-
});
|
|
91
|
-
loading.value = false;
|
|
92
|
-
if (res && res.success) {
|
|
93
|
-
noteList.value = res.data;
|
|
94
|
-
total.value = res.metadata.total;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
async function handleCreate() {
|
|
99
|
-
const content = newNote.value.trim();
|
|
100
|
-
if (!content) {
|
|
101
|
-
Message.warning("请输入笔记内容");
|
|
102
|
-
return;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
const res = await $curl({
|
|
106
|
-
method: "post",
|
|
107
|
-
url: "/api/demo/note",
|
|
108
|
-
data: { content },
|
|
109
|
-
});
|
|
110
|
-
if (res && res.success) {
|
|
111
|
-
newNote.value = "";
|
|
112
|
-
Message.success("创建成功");
|
|
113
|
-
currentPage.value = 1;
|
|
114
|
-
await loadNoteList();
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
function loadData() {
|
|
119
|
-
loadInfo();
|
|
120
|
-
loadNoteList();
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
function goHealth() {
|
|
124
|
-
window.location.href = "/view/health";
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
onMounted(loadData);
|
|
128
|
-
</script>
|
|
129
|
-
|
|
130
|
-
<style lang="less" scoped>
|
|
131
|
-
.home-page {
|
|
132
|
-
box-sizing: border-box;
|
|
133
|
-
max-width: 960px;
|
|
134
|
-
margin: 0 auto;
|
|
135
|
-
padding: 48px 24px 64px;
|
|
136
|
-
|
|
137
|
-
.hero {
|
|
138
|
-
margin-bottom: 32px;
|
|
139
|
-
|
|
140
|
-
.hero-title {
|
|
141
|
-
margin: 0 0 12px;
|
|
142
|
-
font-size: 32px;
|
|
143
|
-
font-weight: 700;
|
|
144
|
-
color: var(--color-text-1);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
.hero-desc {
|
|
148
|
-
margin: 0 0 20px;
|
|
149
|
-
font-size: 15px;
|
|
150
|
-
line-height: 1.8;
|
|
151
|
-
color: var(--color-text-2);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
.hero-links {
|
|
155
|
-
display: flex;
|
|
156
|
-
gap: 12px;
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
.panel {
|
|
161
|
-
margin-bottom: 20px;
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
</style>
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
// 路由只负责把 URL 绑到 controller 方法。
|
|
2
|
-
// 注意绑定时要 .bind(controller),否则方法内的 this 会丢失。
|
|
3
|
-
module.exports = (app, router) => {
|
|
4
|
-
const { demo: demoController } = app.controllers;
|
|
5
|
-
|
|
6
|
-
router.get("/api/demo/info", demoController.getInfo.bind(demoController));
|
|
7
|
-
|
|
8
|
-
router.get(
|
|
9
|
-
"/api/demo/note/list",
|
|
10
|
-
demoController.getNoteList.bind(demoController)
|
|
11
|
-
);
|
|
12
|
-
|
|
13
|
-
router.post(
|
|
14
|
-
"/api/demo/note",
|
|
15
|
-
demoController.createNote.bind(demoController)
|
|
16
|
-
);
|
|
17
|
-
};
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
// API 参数校验:key 必须是已注册路由的 path,method 必须全小写,否则启动失败。
|
|
2
|
-
// 只作用于 /api 开头的请求;校验失败返回 HTTP 200 + { success: false, code: 442 }。
|
|
3
|
-
module.exports = {
|
|
4
|
-
"/api/demo/info": {
|
|
5
|
-
get: {},
|
|
6
|
-
},
|
|
7
|
-
"/api/demo/note/list": {
|
|
8
|
-
get: {
|
|
9
|
-
query: {
|
|
10
|
-
type: "object",
|
|
11
|
-
properties: {
|
|
12
|
-
page: { type: "string" },
|
|
13
|
-
pageSize: { type: "string" },
|
|
14
|
-
},
|
|
15
|
-
},
|
|
16
|
-
},
|
|
17
|
-
},
|
|
18
|
-
"/api/demo/note": {
|
|
19
|
-
post: {
|
|
20
|
-
body: {
|
|
21
|
-
type: "object",
|
|
22
|
-
properties: {
|
|
23
|
-
content: { type: "string", minLength: 1, maxLength: 200 },
|
|
24
|
-
},
|
|
25
|
-
required: ["content"],
|
|
26
|
-
},
|
|
27
|
-
},
|
|
28
|
-
},
|
|
29
|
-
};
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
// 示例 service:演示「工厂返回 class、继承 BaseService」的约定。
|
|
2
|
-
// 文件名 demo.js + 无子目录 → 挂载到 app.services.demo
|
|
3
|
-
// 数据放在内存里,重启即清空;真实业务请换成数据库 / 远程服务调用。
|
|
4
|
-
module.exports = (app) => {
|
|
5
|
-
const BaseService = require("lumfall").Service.Base(app);
|
|
6
|
-
|
|
7
|
-
// 内存数据池
|
|
8
|
-
const notePool = [
|
|
9
|
-
{ id: 1, content: "第一条示例笔记:这是一个基于 lumfall 的基础项目骨架", createdAt: "2026-10-02 10:00:00" },
|
|
10
|
-
{ id: 2, content: "在 app/service 下新建文件即可被自动加载", createdAt: "2026-10-02 10:01:00" },
|
|
11
|
-
{ id: 3, content: "配置通过 config/config.<env>.js 按 _ENV 合并", createdAt: "2026-10-02 10:02:00" },
|
|
12
|
-
];
|
|
13
|
-
let nextId = notePool.length + 1;
|
|
14
|
-
|
|
15
|
-
return class DemoService extends BaseService {
|
|
16
|
-
// 请求阶段读 this.config(= app.config)是安全的;
|
|
17
|
-
// 不要在工厂执行期或构造期读,那时 configLoader 还没跑
|
|
18
|
-
getInfo() {
|
|
19
|
-
return {
|
|
20
|
-
appName: this.config.name,
|
|
21
|
-
demoMessage: this.config.demoMessage,
|
|
22
|
-
serverTime: new Date().toISOString(),
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* 分页查询笔记
|
|
28
|
-
* @param {{ page: number, size: number }} param0
|
|
29
|
-
*/
|
|
30
|
-
getNoteList({ page = 1, size = 10 }) {
|
|
31
|
-
const start = (page - 1) * size;
|
|
32
|
-
const data = notePool.slice(start, start + size).map((note) => ({ ...note }));
|
|
33
|
-
|
|
34
|
-
return { data, total: notePool.length, page, size };
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* 新建笔记
|
|
39
|
-
* @param {{ content: string }} param0
|
|
40
|
-
*/
|
|
41
|
-
createNote({ content }) {
|
|
42
|
-
const note = {
|
|
43
|
-
id: nextId++,
|
|
44
|
-
content,
|
|
45
|
-
createdAt: new Date().toISOString().slice(0, 19).replace("T", " "),
|
|
46
|
-
};
|
|
47
|
-
notePool.unshift(note);
|
|
48
|
-
return note;
|
|
49
|
-
}
|
|
50
|
-
};
|
|
51
|
-
};
|
package/templates/basic/build.js
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
// 所有环境共享的基础配置。合并顺序(后者覆盖前者同名键):
|
|
2
|
-
// 框架 config.default -> 业务 config.default -> 框架 config.<env> -> 业务 config.<env>
|
|
3
|
-
// 环境由 _ENV 决定(local / beta / prod,缺省 local),不是 NODE_ENV。
|
|
4
|
-
module.exports = {
|
|
5
|
-
// 应用名,与 server.js 的 name 保持一致
|
|
6
|
-
name: "lumfall-basic-project",
|
|
7
|
-
|
|
8
|
-
// API 路径前缀约定:框架的参数校验(apiParamsVerify)与安全策略(securityPolicy)
|
|
9
|
-
// 只作用于 /api 开头的请求
|
|
10
|
-
apiBasePath: "/api",
|
|
11
|
-
|
|
12
|
-
// 示例配置:演示「配置如何从服务端流动到接口/页面」,各环境文件里都有同名键
|
|
13
|
-
demoMessage: "hello from config.default",
|
|
14
|
-
|
|
15
|
-
// 安全策略(可选)。不配置这段时,框架等价于「接口签名关闭 + projectKey 开启」
|
|
16
|
-
security: {
|
|
17
|
-
// 接口签名校验:开启后 /api 请求必须携带 s_sign = md5(secret + "_" + st)、
|
|
18
|
-
// st = 毫秒时间戳(前端 $lumfallCurl 默认带的是 s_sign / s_t,均可识别),
|
|
19
|
-
// 时间差超过 maxAgeMs 或时间戳在未来都会返回 code 445。
|
|
20
|
-
// 生产开启时 secret 建议走环境变量 / 配置中心,不要提交到仓库。
|
|
21
|
-
apiSignature: {
|
|
22
|
-
enabled: false,
|
|
23
|
-
maxAgeMs: 600000,
|
|
24
|
-
},
|
|
25
|
-
// project_key 校验:只作用于 /api/project/ 路径,缺 header 返回 code 446。
|
|
26
|
-
// /api/project/model_list、/api/project/list 内置豁免,可用 freePaths 追加。
|
|
27
|
-
projectKey: {
|
|
28
|
-
enabled: true,
|
|
29
|
-
headerName: "project_key",
|
|
30
|
-
},
|
|
31
|
-
},
|
|
32
|
-
};
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "lumfall-basic-project",
|
|
3
|
-
"version": "1.0.0",
|
|
4
|
-
"description": "基于 lumfall 的基础业务项目骨架:目录约定、示例 API 与示例页面,开箱即用",
|
|
5
|
-
"main": "server.js",
|
|
6
|
-
"scripts": {
|
|
7
|
-
"dev": "_ENV='local' nodemon --exitcrash server.js",
|
|
8
|
-
"beta": "_ENV='beta' nodemon --exitcrash server.js",
|
|
9
|
-
"prod": "_ENV='prod' node server.js",
|
|
10
|
-
"build:dev": "_ENV='local' node --max_old_space_size=4096 ./build.js",
|
|
11
|
-
"build:prod": "_ENV='prod' node ./build.js",
|
|
12
|
-
"start:dev": "concurrently --kill-others-on-fail -n webpack,server -c cyan,green \"pnpm build:dev\" \"pnpm dev\"",
|
|
13
|
-
"start:prod": "pnpm build:prod && pnpm prod",
|
|
14
|
-
"new-page": "node ./node_modules/lumfall/scripts/generate-page.js"
|
|
15
|
-
},
|
|
16
|
-
"dependencies": {
|
|
17
|
-
"lumfall": "^1.2.1"
|
|
18
|
-
},
|
|
19
|
-
"devDependencies": {
|
|
20
|
-
"concurrently": "^10.0.5",
|
|
21
|
-
"nodemon": "^3.1.14"
|
|
22
|
-
},
|
|
23
|
-
"packageManager": "pnpm@10.30.0",
|
|
24
|
-
"keywords": [
|
|
25
|
-
"lumfall",
|
|
26
|
-
"koa",
|
|
27
|
-
"vue",
|
|
28
|
-
"fullstack"
|
|
29
|
-
],
|
|
30
|
-
"license": "ISC"
|
|
31
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
const { serviceStart } = require("lumfall");
|
|
2
|
-
|
|
3
|
-
const app = serviceStart({
|
|
4
|
-
// 应用名:渲染页面模板 <title> 时使用
|
|
5
|
-
name: "lumfall-basic-project",
|
|
6
|
-
|
|
7
|
-
// 未命中任何路由时的 302 兜底目标。
|
|
8
|
-
// 注意:serviceStart 一旦传入 options 对象,就不再套用框架默认值,
|
|
9
|
-
// homePath 必须在这里显式声明,否则兜底重定向会退化为 "/"
|
|
10
|
-
homePath: "/view/home",
|
|
11
|
-
|
|
12
|
-
// 可选:配置强校验。传入 JSON Schema,合并后的配置不匹配会直接启动失败
|
|
13
|
-
// configSchema: require("./config/config.schema.js"),
|
|
14
|
-
|
|
15
|
-
// 可选:启动 / 停止 hook(beforeStart / beforeRouteLoad / afterRouteLoad /
|
|
16
|
-
// afterStart / onError / beforeStop / afterStop),启动期 hook 必须同步
|
|
17
|
-
// lifecycle: {},
|
|
18
|
-
|
|
19
|
-
// 可选:插件(数据库、缓存等先于业务中间件/路由初始化的能力)
|
|
20
|
-
// plugins: [],
|
|
21
|
-
|
|
22
|
-
// 可选:请求级观测 hook(traceId / onRequestStart / onRequestEnd / onRequestError)
|
|
23
|
-
// monitoring: {},
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
module.exports = app;
|
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
# lumfall-document
|
|
2
|
-
|
|
3
|
-
基于 [lumfall](https://www.npmjs.com/package/lumfall) 的技术文档站模板,
|
|
4
|
-
对标 VitePress 的使用体验:顶部导航、侧边栏、页面目录(TOC)、
|
|
5
|
-
站内搜索(Ctrl/Cmd+K)、代码高亮与复制、亮 / 暗主题、上一篇/下一篇、移动端适配。
|
|
6
|
-
|
|
7
|
-
模板本身是自举的:**内置内容就是 lumfall 框架的技术文档**,换掉内容即可为
|
|
8
|
-
任何项目搭文档站。文档是纯前端渲染的 SPA,内容由构建期打进产物,无需后端 API。
|
|
9
|
-
|
|
10
|
-
## 快速开始
|
|
11
|
-
|
|
12
|
-
```sh
|
|
13
|
-
pnpm install
|
|
14
|
-
pnpm start:dev # 本地开发:webpack dev server + 服务
|
|
15
|
-
# 打开 http://localhost:3000/view/docs
|
|
16
|
-
|
|
17
|
-
pnpm start:prod # 生产构建 + 启动(Koa 服务)
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
环境变量 `_ENV`(local / beta / prod)与构建部署细节同 lumfall 基础工程,
|
|
21
|
-
见[构建与部署文档](docs/guide/deployment.md)。
|
|
22
|
-
|
|
23
|
-
## 部署到 Vercel(静态托管)
|
|
24
|
-
|
|
25
|
-
文档站是纯前端 SPA:markdown 在构建期全部打进 bundle,运行时不调用任何接口,
|
|
26
|
-
因此**不需要 Node 进程**,可以直接以静态站点部署到 Vercel / Netlify / Nginx。
|
|
27
|
-
|
|
28
|
-
```sh
|
|
29
|
-
pnpm build:static # 产出 dist-static/(index.html + app.html + vercel.json + dist/prod/)
|
|
30
|
-
|
|
31
|
-
cd dist-static && vercel --prod # CLI 部署
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
或使用 Git 集成:Vercel 项目设置 **Build Command** = `pnpm build:static`,
|
|
35
|
-
**Output Directory** = `dist-static`,Framework Preset 选 Other。
|
|
36
|
-
|
|
37
|
-
`dist-static/` 的组成:
|
|
38
|
-
|
|
39
|
-
| 文件 | 作用 |
|
|
40
|
-
| --- | --- |
|
|
41
|
-
| `app.html` | 应用外壳(由框架页面模板转换,`window.__LUMFALL__` 替换为静态值) |
|
|
42
|
-
| `index.html` | `/` 的重定向页(跳到 `/view/docs`,替代 Koa 的 302 兜底) |
|
|
43
|
-
| `vercel.json` | SPA rewrite:`/view/docs/*` → `app.html`;`dist/prod/*` 长缓存头 |
|
|
44
|
-
| `dist/prod/...` | 构建产物(保持 `/dist/prod/` 绝对路径可解析) |
|
|
45
|
-
|
|
46
|
-
其他平台的等价配置:把 `/view/docs` 与 `/view/docs/:path*` rewrite 到
|
|
47
|
-
`app.html`(Netlify 的 `_redirects`、Nginx 的 `try_files` 即可),`/` 指向
|
|
48
|
-
`index.html`。深链接刷新、站内路由、客户端 404 页全部由前端自行处理。
|
|
49
|
-
|
|
50
|
-
::: warning 静态模式的能力边界
|
|
51
|
-
静态部署只有文档站页面:框架自带的 `/view/health`、`/view/dashboard`、
|
|
52
|
-
`/health/*`、`/api/*` 都不存在;如果往文档站里加 curl 调接口的功能,
|
|
53
|
-
需要回到 Koa 部署(或为接口单独部署服务)。
|
|
54
|
-
:::
|
|
55
|
-
|
|
56
|
-
## 目录结构
|
|
57
|
-
|
|
58
|
-
```text
|
|
59
|
-
lumfall-document/
|
|
60
|
-
├── server.js # 服务端入口(homePath 指向 /view/docs)
|
|
61
|
-
├── build.js # 前端构建入口
|
|
62
|
-
├── scripts/build-static.js # 静态站点构建(pnpm build:static → dist-static/)
|
|
63
|
-
├── config/ # 环境配置(同基础工程)
|
|
64
|
-
├── docs/ # ★ 文档内容:全部 markdown,目录结构随意
|
|
65
|
-
│ ├── guide/
|
|
66
|
-
│ ├── core/
|
|
67
|
-
│ ├── dsl/ # Dashboard DSL 章节(Model+Project、schema 模块、接口契约)
|
|
68
|
-
│ ├── frontend/
|
|
69
|
-
│ ├── advanced/
|
|
70
|
-
│ └── reference/
|
|
71
|
-
└── app/
|
|
72
|
-
├── webpack.config.js # 额外声明了 .md 的 asset/source 规则
|
|
73
|
-
└── pages/
|
|
74
|
-
└── docs/ # 文档站页面(单页 + 站内路由)
|
|
75
|
-
├── entry.docs.js # 页面入口:注册 /view/docs 两条路由
|
|
76
|
-
├── docs-config.js # ★ 站点配置:导航、侧栏、首页 hero、页脚
|
|
77
|
-
├── content.js # 内容加载器:require.context 扫 docs/ 下所有 .md
|
|
78
|
-
├── markdown/ # markdown-it 渲染器(锚点/TOC/代码块/提示块/链接)
|
|
79
|
-
├── search.js # 站内搜索索引
|
|
80
|
-
├── theme.js # 亮暗主题
|
|
81
|
-
├── components/ # navbar / sidebar / toc / search / layout
|
|
82
|
-
├── views/ # 首页(hero)与文档页
|
|
83
|
-
└── styles/ # 设计变量与排版样式(CSS 变量驱动双主题)
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
## 用它搭自己的文档站
|
|
87
|
-
|
|
88
|
-
三步:
|
|
89
|
-
|
|
90
|
-
1. **改内容**:把 `docs/` 下的 markdown 换成自己的(目录层级随意,
|
|
91
|
-
两级以内体验最佳)。文档里可以互相引用,支持相对链接:
|
|
92
|
-
```markdown
|
|
93
|
-
[配置](./config.md) → 同目录
|
|
94
|
-
[路由](../core/router-schema.md) → 上级目录
|
|
95
|
-
[某节](./config.md#读取配置) → 带锚点
|
|
96
|
-
```
|
|
97
|
-
2. **改配置**:`app/pages/docs/docs-config.js` 是唯一需要动的配置文件——
|
|
98
|
-
站点名、导航、侧栏分组、首页 hero、页脚。侧栏条目的 `path` 对应
|
|
99
|
-
`docs/` 下的文件路径(`/view/docs/<path>` ↔ `docs/<path>.md`)
|
|
100
|
-
3. **可选**:改主题色(`app/pages/docs/styles/vars.less` 的 `--doc-brand`
|
|
101
|
-
等变量)、换 logo(`app/pages/docs/assets/docs-logo.svg`)
|
|
102
|
-
|
|
103
|
-
## 功能清单
|
|
104
|
-
|
|
105
|
-
| 功能 | 说明 |
|
|
106
|
-
| --- | --- |
|
|
107
|
-
| 首页 hero | 大标题 + 标语 + 按钮 + 特性卡片(配置驱动) |
|
|
108
|
-
| 侧边栏 | 分组导航,当前页高亮,移动端抽屉 |
|
|
109
|
-
| 页面目录 | 正文右侧 TOC,滚动联动高亮(<1280px 隐藏) |
|
|
110
|
-
| 站内搜索 | `Ctrl/Cmd + K` 或 `/` 唤起;标题 / 小节 / 正文加权匹配,关键词高亮摘要,键盘导航 |
|
|
111
|
-
| 代码块 | highlight.js 按需注册语言、语言标签、一键复制、亮暗配色 |
|
|
112
|
-
| markdown 扩展 | `::: tip / info / warning / danger <可选标题>` 提示块、标题锚点(悬停显示 #)、外链新窗口 |
|
|
113
|
-
| 主题 | 亮 / 暗(右上角切换),首次进站跟随系统,localStorage 记忆 |
|
|
114
|
-
| 上一篇/下一篇 | 按侧边栏顺序自动生成 |
|
|
115
|
-
| 路由 | `/view/docs` 首页,`/view/docs/<path>` 文档页,未知路径显示 404 引导 |
|
|
116
|
-
| SEO 基础 | 每页动态 `document.title`;如需完整 SEO 需要额外的预渲染方案 |
|
|
117
|
-
|
|
118
|
-
## 写作约定
|
|
119
|
-
|
|
120
|
-
- 每篇文档以 `# 一级标题` 开头(渲染为页面标题),章节用 `##` / `###`
|
|
121
|
-
(自动进入右侧 TOC 与搜索索引)
|
|
122
|
-
- 代码块标注语言(`js` / `vue` / `bash` / `json`…)才会高亮
|
|
123
|
-
- 小节标题会被 slug 化为锚点 id(中文保留原文字符),可直接 `#锚点` 引用
|
|
124
|
-
- 不支持的内容:数学公式、mermaid 图(markdown-it 未接插件,需要时可在
|
|
125
|
-
`app/pages/docs/markdown/index.js` 自行扩展)
|
|
126
|
-
|
|
127
|
-
## 搜索原理
|
|
128
|
-
|
|
129
|
-
构建时全部 markdown 以文本形式打进 bundle(`asset/source`),
|
|
130
|
-
搜索在浏览器内存里做索引(标题 / 小节标题 / 正文三级加权,代码块不参与)。
|
|
131
|
-
文档量在几百页以内体验良好;更大规模时建议接后端搜索或引入 lunr/minisearch。
|
|
132
|
-
|
|
133
|
-
## 常见问题
|
|
134
|
-
|
|
135
|
-
- **改了 docs/ 下的 md 没生效**:dev 模式需要重新触发编译(保存任意被引用的
|
|
136
|
-
文件);生产模式需要重新 `pnpm build:prod`
|
|
137
|
-
- **侧栏点进去 404**:`docs-config.js` 里的 path 与 `docs/` 实际文件不一致
|
|
138
|
-
- **想改页面挂载路径(/view/docs)**:改 `docs-config.js` 的 `DOCS_BASE`
|
|
139
|
-
与 `entry.docs.js` 里的两条路由 path,三处保持一致
|
|
140
|
-
|
|
141
|
-
## 相关项目
|
|
142
|
-
|
|
143
|
-
- `lumfall-basic-project/`:基础业务工程骨架(本模板的工程底座)
|
|
144
|
-
- `lumfall-business/`:B 端全栈模板(Dashboard / schema 组件)
|
|
145
|
-
- `lumfall/`:框架本体
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
|
2
|
-
<rect x="2" y="2" width="28" height="28" rx="7" fill="#165dff"/>
|
|
3
|
-
<path d="M10 9v11a3 3 0 0 0 3 3h9v-2h-9a1 1 0 0 1-1-1V9h-2z" fill="#fff"/>
|
|
4
|
-
<path d="M13 9h9a1 1 0 0 1 1 1v8h-8a2 2 0 0 0-2 2V9z" fill="#9fd4ff"/>
|
|
5
|
-
</svg>
|