@liujitcn/kratos-admin-system 0.0.36 → 0.0.38
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 +0 -3
- package/dist/package/declarations/src/locales/generated.d.ts +0 -28
- package/dist/package/src/locales/en-US.json +0 -7
- package/dist/package/src/locales/ja-JP.json +0 -7
- package/dist/package/src/locales/zh-CN.json +0 -7
- package/dist/package/src/locales/zh-TW.json +0 -7
- package/package.json +2 -2
- package/dist/package/declarations/src/api/system/admin/v1/project_document.d.ts +0 -9
- package/dist/package/declarations/src/rpc/system/admin/v1/project_document.d.ts +0 -70
- package/dist/package/declarations/src/views/tool/project-doc/index.vue.d.ts +0 -3
- package/dist/package/src/api/system/admin/v1/project_document.ts +0 -33
- package/dist/package/src/rpc/system/admin/v1/project_document.ts +0 -85
- package/dist/package/src/views/tool/project-doc/index.vue +0 -565
package/README.md
CHANGED
|
@@ -64,7 +64,6 @@ packages/modules/system
|
|
|
64
64
|
| `src/api/system/admin/v1/code_gen*.ts` | 代码生成服务请求。 |
|
|
65
65
|
| `src/api/system/admin/v1/oauth_client.ts` | 开放授权客户端服务请求。 |
|
|
66
66
|
| `src/api/system/admin/v1/ops_monitoring.ts` | 运维监控服务请求。 |
|
|
67
|
-
| `src/api/system/admin/v1/project_document.ts` | 项目文档服务请求。 |
|
|
68
67
|
| `src/api/system/admin/v1/runtime_log.ts` | 运行日志服务请求。 |
|
|
69
68
|
| `src/api/system/admin/v1/cache.ts` | 运行时缓存服务请求。 |
|
|
70
69
|
| `@liujitcn/kratos-admin-core/api/base/v1/mfa` | 当前用户 MFA 服务请求。 |
|
|
@@ -101,7 +100,6 @@ packages/modules/system
|
|
|
101
100
|
| `src/views/base/user/components/dept-tree.vue` | 用户页的部门树筛选组件。 |
|
|
102
101
|
| `src/views/profile/` | 个人中心与安全设置页面。 |
|
|
103
102
|
| `src/views/tool/api-doc/index.vue` | OpenAPI/Swagger 文档页。 |
|
|
104
|
-
| `src/views/tool/project-doc/index.vue` | 多项目 Markdown 树形导航与阅读页。 |
|
|
105
103
|
| `src/views/tool/code-gen/table/index.vue` | 代码生成数据表列表页。 |
|
|
106
104
|
| `src/views/tool/code-gen/columns/index.vue` | 代码生成字段配置页。 |
|
|
107
105
|
| `src/views/tool/code-gen/columns/option-copy.ts` | 字段选项复制规则。 |
|
|
@@ -137,7 +135,6 @@ export const adminModules = [systemAdminModule];
|
|
|
137
135
|
| 个人中心 | `system/profile/index` |
|
|
138
136
|
| AI 助手 | `system/ai/chat/index` |
|
|
139
137
|
| API 文档 | `system/tool/api-doc/index` |
|
|
140
|
-
| 项目文档 | `system/tool/project-doc/index` |
|
|
141
138
|
|
|
142
139
|
不再兼容 `base/user/index`、`profile/index` 等无模块前缀路径。不同业务模块可以拥有同名 `views`,core 会按 `<module>/<view>` 解析,不发生覆盖。
|
|
143
140
|
|
|
@@ -967,13 +967,6 @@ export declare const LOCALE_MESSAGES: {
|
|
|
967
967
|
"system.code.gen.preview.message.delete_success": string;
|
|
968
968
|
"system.code.gen.preview.message.missing_i18ns": string;
|
|
969
969
|
"system.code.gen.preview.value.list_separator": string;
|
|
970
|
-
"system.project.document.title.navigation": string;
|
|
971
|
-
"system.project.document.placeholder.search": string;
|
|
972
|
-
"system.project.document.message.no_match": string;
|
|
973
|
-
"system.project.document.message.empty": string;
|
|
974
|
-
"system.project.document.message.select": string;
|
|
975
|
-
"system.project.document.message.uncollected": string;
|
|
976
|
-
"system.project.document.value.updated_at": string;
|
|
977
970
|
"system.cache.title": string;
|
|
978
971
|
"system.cache.readonly": string;
|
|
979
972
|
"system.cache.field.key": string;
|
|
@@ -2474,13 +2467,6 @@ export declare const LOCALE_MESSAGES: {
|
|
|
2474
2467
|
"system.code.gen.preview.message.delete_success": string;
|
|
2475
2468
|
"system.code.gen.preview.message.missing_i18ns": string;
|
|
2476
2469
|
"system.code.gen.preview.value.list_separator": string;
|
|
2477
|
-
"system.project.document.title.navigation": string;
|
|
2478
|
-
"system.project.document.placeholder.search": string;
|
|
2479
|
-
"system.project.document.message.no_match": string;
|
|
2480
|
-
"system.project.document.message.empty": string;
|
|
2481
|
-
"system.project.document.message.select": string;
|
|
2482
|
-
"system.project.document.message.uncollected": string;
|
|
2483
|
-
"system.project.document.value.updated_at": string;
|
|
2484
2470
|
"system.cache.title": string;
|
|
2485
2471
|
"system.cache.readonly": string;
|
|
2486
2472
|
"system.cache.field.key": string;
|
|
@@ -3981,13 +3967,6 @@ export declare const LOCALE_MESSAGES: {
|
|
|
3981
3967
|
"system.code.gen.preview.message.delete_success": string;
|
|
3982
3968
|
"system.code.gen.preview.message.missing_i18ns": string;
|
|
3983
3969
|
"system.code.gen.preview.value.list_separator": string;
|
|
3984
|
-
"system.project.document.title.navigation": string;
|
|
3985
|
-
"system.project.document.placeholder.search": string;
|
|
3986
|
-
"system.project.document.message.no_match": string;
|
|
3987
|
-
"system.project.document.message.empty": string;
|
|
3988
|
-
"system.project.document.message.select": string;
|
|
3989
|
-
"system.project.document.message.uncollected": string;
|
|
3990
|
-
"system.project.document.value.updated_at": string;
|
|
3991
3970
|
"system.cache.title": string;
|
|
3992
3971
|
"system.cache.readonly": string;
|
|
3993
3972
|
"system.cache.field.key": string;
|
|
@@ -5488,13 +5467,6 @@ export declare const LOCALE_MESSAGES: {
|
|
|
5488
5467
|
"system.code.gen.preview.message.delete_success": string;
|
|
5489
5468
|
"system.code.gen.preview.message.missing_i18ns": string;
|
|
5490
5469
|
"system.code.gen.preview.value.list_separator": string;
|
|
5491
|
-
"system.project.document.title.navigation": string;
|
|
5492
|
-
"system.project.document.placeholder.search": string;
|
|
5493
|
-
"system.project.document.message.no_match": string;
|
|
5494
|
-
"system.project.document.message.empty": string;
|
|
5495
|
-
"system.project.document.message.select": string;
|
|
5496
|
-
"system.project.document.message.uncollected": string;
|
|
5497
|
-
"system.project.document.value.updated_at": string;
|
|
5498
5470
|
"system.cache.title": string;
|
|
5499
5471
|
"system.cache.readonly": string;
|
|
5500
5472
|
"system.cache.field.key": string;
|
|
@@ -966,13 +966,6 @@
|
|
|
966
966
|
"system.code.gen.preview.message.delete_success": "Deleted",
|
|
967
967
|
"system.code.gen.preview.message.missing_i18ns": "Complete these i18ns before generation: {items}",
|
|
968
968
|
"system.code.gen.preview.value.list_separator": ", ",
|
|
969
|
-
"system.project.document.title.navigation": "Project document navigation",
|
|
970
|
-
"system.project.document.placeholder.search": "Search projects or paths",
|
|
971
|
-
"system.project.document.message.no_match": "No matching documents",
|
|
972
|
-
"system.project.document.message.empty": "No project documents",
|
|
973
|
-
"system.project.document.message.select": "Select a project document",
|
|
974
|
-
"system.project.document.message.uncollected": "Referenced document was not collected: {path}",
|
|
975
|
-
"system.project.document.value.updated_at": "Updated {time}",
|
|
976
969
|
"system.cache.title": "Cache query",
|
|
977
970
|
"system.cache.readonly": "Read-only",
|
|
978
971
|
"system.cache.field.key": "Cache key",
|
|
@@ -966,13 +966,6 @@
|
|
|
966
966
|
"system.code.gen.preview.message.delete_success": "削除に成功しました",
|
|
967
967
|
"system.code.gen.preview.message.missing_i18ns": "は正式に生成する前に完了する必要があります: {items}",
|
|
968
968
|
"system.code.gen.preview.value.list_separator": "、",
|
|
969
|
-
"system.project.document.title.navigation": "プロジェクトドキュメントディレクトリ",
|
|
970
|
-
"system.project.document.placeholder.search": "検索項目またはパス",
|
|
971
|
-
"system.project.document.message.no_match": "一致するドキュメントがまだありません",
|
|
972
|
-
"system.project.document.message.empty": "プロジェクト ドキュメントがまだありません",
|
|
973
|
-
"system.project.document.message.select": "プロジェクトドキュメントを選択してください",
|
|
974
|
-
"system.project.document.message.uncollected": "参照ドキュメントが収集されていません: {path}",
|
|
975
|
-
"system.project.document.value.updated_at": "が {time} から更新されました",
|
|
976
969
|
"system.cache.title": "キャッシュ照会",
|
|
977
970
|
"system.cache.readonly": "読み取り専用",
|
|
978
971
|
"system.cache.field.key": "キャッシュキー",
|
|
@@ -966,13 +966,6 @@
|
|
|
966
966
|
"system.code.gen.preview.message.delete_success": "删除成功",
|
|
967
967
|
"system.code.gen.preview.message.missing_i18ns": "正式生成前还需补齐:{items}",
|
|
968
968
|
"system.code.gen.preview.value.list_separator": "、",
|
|
969
|
-
"system.project.document.title.navigation": "项目文档目录",
|
|
970
|
-
"system.project.document.placeholder.search": "搜索项目或路径",
|
|
971
|
-
"system.project.document.message.no_match": "暂无匹配文档",
|
|
972
|
-
"system.project.document.message.empty": "暂无项目文档",
|
|
973
|
-
"system.project.document.message.select": "请选择一篇项目文档",
|
|
974
|
-
"system.project.document.message.uncollected": "未收集引用文档:{path}",
|
|
975
|
-
"system.project.document.value.updated_at": "更新于 {time}",
|
|
976
969
|
"system.cache.title": "缓存查询",
|
|
977
970
|
"system.cache.readonly": "只读",
|
|
978
971
|
"system.cache.field.key": "缓存键",
|
|
@@ -966,13 +966,6 @@
|
|
|
966
966
|
"system.code.gen.preview.message.delete_success": "刪除成功",
|
|
967
967
|
"system.code.gen.preview.message.missing_i18ns": "正式生成前還需補齊:{items}",
|
|
968
968
|
"system.code.gen.preview.value.list_separator": "、",
|
|
969
|
-
"system.project.document.title.navigation": "專案文件目錄",
|
|
970
|
-
"system.project.document.placeholder.search": "搜尋專案或路徑",
|
|
971
|
-
"system.project.document.message.no_match": "暫無匹配文件",
|
|
972
|
-
"system.project.document.message.empty": "暫無專案文件",
|
|
973
|
-
"system.project.document.message.select": "請選擇一篇專案文件",
|
|
974
|
-
"system.project.document.message.uncollected": "未收集引用文件:{path}",
|
|
975
|
-
"system.project.document.value.updated_at": "更新於 {time}",
|
|
976
969
|
"system.cache.title": "快取查詢",
|
|
977
970
|
"system.cache.readonly": "唯讀",
|
|
978
971
|
"system.cache.field.key": "快取鍵",
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@liujitcn/kratos-admin-system",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.38",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "kratos-admin system management module",
|
|
7
7
|
"license": "MIT",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"sortablejs": "^1.15.2",
|
|
16
16
|
"swagger-ui-dist": "^5.32.9",
|
|
17
17
|
"vue-element-plus-x": "^2.0.3",
|
|
18
|
-
"@liujitcn/kratos-admin-core": "0.0.
|
|
18
|
+
"@liujitcn/kratos-admin-core": "0.0.38"
|
|
19
19
|
},
|
|
20
20
|
"peerDependencies": {
|
|
21
21
|
"@element-plus/icons-vue": "^2.3.1",
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { GetProjectDocumentRequest, ProjectDocument, ProjectDocumentService, TreeProjectDocumentRequest, TreeProjectDocumentResponse } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/project_document";
|
|
2
|
-
/** Admin项目文档服务。 */
|
|
3
|
-
export declare class ProjectDocumentServiceImpl implements ProjectDocumentService {
|
|
4
|
-
/** 查询项目文档树。 */
|
|
5
|
-
TreeProjectDocument(request: TreeProjectDocumentRequest): Promise<TreeProjectDocumentResponse>;
|
|
6
|
-
/** 查询项目文档详情。 */
|
|
7
|
-
GetProjectDocument(request: GetProjectDocumentRequest): Promise<ProjectDocument>;
|
|
8
|
-
}
|
|
9
|
-
export declare const defProjectDocumentService: ProjectDocumentServiceImpl;
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
/** 项目文档树查询条件 */
|
|
2
|
-
export interface TreeProjectDocumentRequest {
|
|
3
|
-
}
|
|
4
|
-
/** 项目文档树响应 */
|
|
5
|
-
export interface TreeProjectDocumentResponse {
|
|
6
|
-
/** 项目文档树 */
|
|
7
|
-
projects: ProjectDocumentProject[];
|
|
8
|
-
}
|
|
9
|
-
/** 项目文档详情查询条件 */
|
|
10
|
-
export interface GetProjectDocumentRequest {
|
|
11
|
-
/** 项目文档ID */
|
|
12
|
-
id: string;
|
|
13
|
-
}
|
|
14
|
-
/** 项目文档目录项 */
|
|
15
|
-
export interface ProjectDocumentListItem {
|
|
16
|
-
/** 项目文档ID */
|
|
17
|
-
id: string;
|
|
18
|
-
/** 项目内相对路径 */
|
|
19
|
-
path: string;
|
|
20
|
-
/** 当前语言下的文档显示文件名 */
|
|
21
|
-
name: string;
|
|
22
|
-
/** Markdown文件更新时间,RFC3339格式 */
|
|
23
|
-
updated_at: string;
|
|
24
|
-
}
|
|
25
|
-
/** 项目文档树 */
|
|
26
|
-
export interface ProjectDocumentProject {
|
|
27
|
-
/** 与OpenAPI文档一致的项目标识 */
|
|
28
|
-
key: string;
|
|
29
|
-
/** 与OpenAPI文档一致的项目名称 */
|
|
30
|
-
name: string;
|
|
31
|
-
/** 项目根目录下的文档 */
|
|
32
|
-
documents: ProjectDocumentListItem[];
|
|
33
|
-
/** 项目根目录下的子目录 */
|
|
34
|
-
directories: ProjectDocumentDirectory[];
|
|
35
|
-
}
|
|
36
|
-
/** 项目文档目录节点 */
|
|
37
|
-
export interface ProjectDocumentDirectory {
|
|
38
|
-
/** 目录名称 */
|
|
39
|
-
name: string;
|
|
40
|
-
/** 项目内相对目录路径 */
|
|
41
|
-
path: string;
|
|
42
|
-
/** 当前目录下的文档 */
|
|
43
|
-
documents: ProjectDocumentListItem[];
|
|
44
|
-
/** 当前目录下的子目录 */
|
|
45
|
-
directories: ProjectDocumentDirectory[];
|
|
46
|
-
}
|
|
47
|
-
/** 项目文档 */
|
|
48
|
-
export interface ProjectDocument {
|
|
49
|
-
/** 项目文档ID */
|
|
50
|
-
id: string;
|
|
51
|
-
/** 与OpenAPI文档一致的项目标识 */
|
|
52
|
-
project_key: string;
|
|
53
|
-
/** 与OpenAPI文档一致的项目名称 */
|
|
54
|
-
project_name: string;
|
|
55
|
-
/** 项目内相对路径 */
|
|
56
|
-
path: string;
|
|
57
|
-
/** 当前语言下的文档显示文件名 */
|
|
58
|
-
name: string;
|
|
59
|
-
/** Markdown文档内容 */
|
|
60
|
-
content: string;
|
|
61
|
-
/** Markdown文件更新时间,RFC3339格式 */
|
|
62
|
-
updated_at: string;
|
|
63
|
-
}
|
|
64
|
-
/** 项目文档服务 */
|
|
65
|
-
export interface ProjectDocumentService {
|
|
66
|
-
/** 查询项目文档树 */
|
|
67
|
-
TreeProjectDocument(request: TreeProjectDocumentRequest): Promise<TreeProjectDocumentResponse>;
|
|
68
|
-
/** 查询项目文档详情 */
|
|
69
|
-
GetProjectDocument(request: GetProjectDocumentRequest): Promise<ProjectDocument>;
|
|
70
|
-
}
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
|
|
2
|
-
declare const _default: typeof __VLS_export;
|
|
3
|
-
export default _default;
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import service from "@liujitcn/kratos-admin-core/request";
|
|
2
|
-
import type {
|
|
3
|
-
GetProjectDocumentRequest,
|
|
4
|
-
ProjectDocument,
|
|
5
|
-
ProjectDocumentService,
|
|
6
|
-
TreeProjectDocumentRequest,
|
|
7
|
-
TreeProjectDocumentResponse
|
|
8
|
-
} from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/project_document";
|
|
9
|
-
|
|
10
|
-
const PROJECT_DOCUMENT_URL = "/v1/admin/project-document";
|
|
11
|
-
const PROJECT_DOCUMENT_TREE_URL = `${PROJECT_DOCUMENT_URL}/tree`;
|
|
12
|
-
|
|
13
|
-
/** Admin项目文档服务。 */
|
|
14
|
-
export class ProjectDocumentServiceImpl implements ProjectDocumentService {
|
|
15
|
-
/** 查询项目文档树。 */
|
|
16
|
-
TreeProjectDocument(request: TreeProjectDocumentRequest): Promise<TreeProjectDocumentResponse> {
|
|
17
|
-
return service<TreeProjectDocumentRequest, TreeProjectDocumentResponse>({
|
|
18
|
-
url: PROJECT_DOCUMENT_TREE_URL,
|
|
19
|
-
method: "get",
|
|
20
|
-
params: request
|
|
21
|
-
});
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/** 查询项目文档详情。 */
|
|
25
|
-
GetProjectDocument(request: GetProjectDocumentRequest): Promise<ProjectDocument> {
|
|
26
|
-
return service<GetProjectDocumentRequest, ProjectDocument>({
|
|
27
|
-
url: `${PROJECT_DOCUMENT_URL}/${request.id}`,
|
|
28
|
-
method: "get"
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export const defProjectDocumentService = new ProjectDocumentServiceImpl();
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
// Code generated by protoc-gen-ts_proto. DO NOT EDIT.
|
|
2
|
-
// versions:
|
|
3
|
-
// protoc-gen-ts_proto v2.12.1
|
|
4
|
-
// protoc unknown
|
|
5
|
-
// source: system/admin/v1/project_document.proto
|
|
6
|
-
|
|
7
|
-
/* eslint-disable */
|
|
8
|
-
|
|
9
|
-
/** 项目文档树查询条件 */
|
|
10
|
-
export interface TreeProjectDocumentRequest {
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/** 项目文档树响应 */
|
|
14
|
-
export interface TreeProjectDocumentResponse {
|
|
15
|
-
/** 项目文档树 */
|
|
16
|
-
projects: ProjectDocumentProject[];
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/** 项目文档详情查询条件 */
|
|
20
|
-
export interface GetProjectDocumentRequest {
|
|
21
|
-
/** 项目文档ID */
|
|
22
|
-
id: string;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/** 项目文档目录项 */
|
|
26
|
-
export interface ProjectDocumentListItem {
|
|
27
|
-
/** 项目文档ID */
|
|
28
|
-
id: string;
|
|
29
|
-
/** 项目内相对路径 */
|
|
30
|
-
path: string;
|
|
31
|
-
/** 当前语言下的文档显示文件名 */
|
|
32
|
-
name: string;
|
|
33
|
-
/** Markdown文件更新时间,RFC3339格式 */
|
|
34
|
-
updated_at: string;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/** 项目文档树 */
|
|
38
|
-
export interface ProjectDocumentProject {
|
|
39
|
-
/** 与OpenAPI文档一致的项目标识 */
|
|
40
|
-
key: string;
|
|
41
|
-
/** 与OpenAPI文档一致的项目名称 */
|
|
42
|
-
name: string;
|
|
43
|
-
/** 项目根目录下的文档 */
|
|
44
|
-
documents: ProjectDocumentListItem[];
|
|
45
|
-
/** 项目根目录下的子目录 */
|
|
46
|
-
directories: ProjectDocumentDirectory[];
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/** 项目文档目录节点 */
|
|
50
|
-
export interface ProjectDocumentDirectory {
|
|
51
|
-
/** 目录名称 */
|
|
52
|
-
name: string;
|
|
53
|
-
/** 项目内相对目录路径 */
|
|
54
|
-
path: string;
|
|
55
|
-
/** 当前目录下的文档 */
|
|
56
|
-
documents: ProjectDocumentListItem[];
|
|
57
|
-
/** 当前目录下的子目录 */
|
|
58
|
-
directories: ProjectDocumentDirectory[];
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/** 项目文档 */
|
|
62
|
-
export interface ProjectDocument {
|
|
63
|
-
/** 项目文档ID */
|
|
64
|
-
id: string;
|
|
65
|
-
/** 与OpenAPI文档一致的项目标识 */
|
|
66
|
-
project_key: string;
|
|
67
|
-
/** 与OpenAPI文档一致的项目名称 */
|
|
68
|
-
project_name: string;
|
|
69
|
-
/** 项目内相对路径 */
|
|
70
|
-
path: string;
|
|
71
|
-
/** 当前语言下的文档显示文件名 */
|
|
72
|
-
name: string;
|
|
73
|
-
/** Markdown文档内容 */
|
|
74
|
-
content: string;
|
|
75
|
-
/** Markdown文件更新时间,RFC3339格式 */
|
|
76
|
-
updated_at: string;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/** 项目文档服务 */
|
|
80
|
-
export interface ProjectDocumentService {
|
|
81
|
-
/** 查询项目文档树 */
|
|
82
|
-
TreeProjectDocument(request: TreeProjectDocumentRequest): Promise<TreeProjectDocumentResponse>;
|
|
83
|
-
/** 查询项目文档详情 */
|
|
84
|
-
GetProjectDocument(request: GetProjectDocumentRequest): Promise<ProjectDocument>;
|
|
85
|
-
}
|
|
@@ -1,565 +0,0 @@
|
|
|
1
|
-
<template>
|
|
2
|
-
<div v-loading="loading" class="table-box project-doc-page">
|
|
3
|
-
<main class="project-doc-shell">
|
|
4
|
-
<aside class="document-navigation" :aria-label="t('system.project.document.title.navigation')">
|
|
5
|
-
<header class="navigation-header">
|
|
6
|
-
<el-input v-model="keyword" clearable :placeholder="t('system.project.document.placeholder.search')" :prefix-icon="Search" />
|
|
7
|
-
<span class="document-count">{{ filteredDocumentCount }} / {{ documents.length }}</span>
|
|
8
|
-
</header>
|
|
9
|
-
|
|
10
|
-
<div v-if="documents.length" class="document-tree-scroll">
|
|
11
|
-
<el-tree
|
|
12
|
-
v-show="filteredDocumentCount > 0"
|
|
13
|
-
ref="documentTreeRef"
|
|
14
|
-
class="document-tree"
|
|
15
|
-
:data="documentTree"
|
|
16
|
-
node-key="key"
|
|
17
|
-
:props="{ children: 'children', label: 'label' }"
|
|
18
|
-
:current-node-key="selectedDocumentNodeKey"
|
|
19
|
-
:filter-node-method="filterTreeNode"
|
|
20
|
-
default-expand-all
|
|
21
|
-
highlight-current
|
|
22
|
-
@node-click="handleTreeNodeClick"
|
|
23
|
-
>
|
|
24
|
-
<template #default="{ data }">
|
|
25
|
-
<span class="document-tree-node" :class="`is-${data.kind}`" :title="data.path || data.label">
|
|
26
|
-
<el-icon v-if="data.kind === 'document'" class="document-tree-node__icon"><Document /></el-icon>
|
|
27
|
-
<span class="document-tree-node__label">{{ data.label }}</span>
|
|
28
|
-
<code v-if="data.kind === 'project'">{{ data.projectKey }}</code>
|
|
29
|
-
</span>
|
|
30
|
-
</template>
|
|
31
|
-
</el-tree>
|
|
32
|
-
<el-empty v-if="filteredDocumentCount === 0" :description="t('system.project.document.message.no_match')" :image-size="72" />
|
|
33
|
-
</div>
|
|
34
|
-
<el-empty v-else :description="t('system.project.document.message.empty')" :image-size="72" />
|
|
35
|
-
</aside>
|
|
36
|
-
|
|
37
|
-
<section class="document-reader">
|
|
38
|
-
<div v-if="detailLoading && !selectedDocument" class="reader-loading">
|
|
39
|
-
<el-skeleton :rows="10" animated />
|
|
40
|
-
</div>
|
|
41
|
-
<template v-else-if="selectedDocument">
|
|
42
|
-
<header class="reader-header">
|
|
43
|
-
<div class="reader-header__identity">
|
|
44
|
-
<el-icon><Document /></el-icon>
|
|
45
|
-
<div class="reader-header__title">
|
|
46
|
-
<strong>{{ selectedDocumentName }}</strong>
|
|
47
|
-
<span :title="selectedDocument.path">{{ selectedDocument.project_name }} / {{ selectedDocument.path }}</span>
|
|
48
|
-
</div>
|
|
49
|
-
</div>
|
|
50
|
-
<time v-if="selectedDocumentUpdatedAt" :datetime="selectedDocumentUpdatedAt" :title="selectedDocumentUpdatedAt">
|
|
51
|
-
{{ t("system.project.document.value.updated_at", { time: formatDocumentUpdatedAt(selectedDocumentUpdatedAt) }) }}
|
|
52
|
-
</time>
|
|
53
|
-
</header>
|
|
54
|
-
<div ref="readerScrollRef" v-loading="detailLoading" class="reader-scroll">
|
|
55
|
-
<div ref="markdownRef" class="project-markdown" @click="handleMarkdownClick">
|
|
56
|
-
<MarkdownPreview
|
|
57
|
-
id="project-doc-preview"
|
|
58
|
-
class="project-markdown__preview"
|
|
59
|
-
:model-value="selectedDocument.content"
|
|
60
|
-
:is-dark="globalStore.isDark"
|
|
61
|
-
/>
|
|
62
|
-
</div>
|
|
63
|
-
</div>
|
|
64
|
-
</template>
|
|
65
|
-
<el-empty v-else :description="t('system.project.document.message.select')" />
|
|
66
|
-
</section>
|
|
67
|
-
</main>
|
|
68
|
-
</div>
|
|
69
|
-
</template>
|
|
70
|
-
|
|
71
|
-
<script setup lang="ts">
|
|
72
|
-
import { computed, nextTick, onMounted, ref, watch } from "vue";
|
|
73
|
-
import { Search } from "@element-plus/icons-vue";
|
|
74
|
-
import type { TreeNodeData } from "element-plus";
|
|
75
|
-
import { getCurrentLocale, t, useLocaleStore } from "@liujitcn/kratos-admin-core";
|
|
76
|
-
import MarkdownPreview from "@liujitcn/kratos-admin-core/components/MarkdownPreview/index.vue";
|
|
77
|
-
import { useGlobalStore } from "@liujitcn/kratos-admin-core/stores/runtime";
|
|
78
|
-
import { defProjectDocumentService } from "@liujitcn/kratos-admin-system/api/system/admin/v1/project_document";
|
|
79
|
-
import type {
|
|
80
|
-
ProjectDocument,
|
|
81
|
-
ProjectDocumentDirectory,
|
|
82
|
-
ProjectDocumentListItem,
|
|
83
|
-
ProjectDocumentProject
|
|
84
|
-
} from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/project_document";
|
|
85
|
-
|
|
86
|
-
defineOptions({
|
|
87
|
-
name: "ProjectDocument",
|
|
88
|
-
inheritAttrs: false
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
/** 项目文档树节点类型。 */
|
|
92
|
-
type ProjectDocumentTreeNodeKind = "project" | "directory" | "document";
|
|
93
|
-
|
|
94
|
-
/** 管理端项目文档树节点。 */
|
|
95
|
-
interface ProjectDocumentTreeNode {
|
|
96
|
-
/** 树节点稳定标识。 */
|
|
97
|
-
key: string;
|
|
98
|
-
/** 树节点展示名称。 */
|
|
99
|
-
label: string;
|
|
100
|
-
/** 树节点类型。 */
|
|
101
|
-
kind: ProjectDocumentTreeNodeKind;
|
|
102
|
-
/** 所属项目标识。 */
|
|
103
|
-
projectKey: string;
|
|
104
|
-
/** 所属项目名称。 */
|
|
105
|
-
projectName: string;
|
|
106
|
-
/** 项目内相对路径。 */
|
|
107
|
-
path: string;
|
|
108
|
-
/** 文档叶子节点数据。 */
|
|
109
|
-
document?: ProjectDocumentListItem;
|
|
110
|
-
/** 子节点。 */
|
|
111
|
-
children: ProjectDocumentTreeNode[];
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
const globalStore = useGlobalStore();
|
|
115
|
-
const { locale } = useLocaleStore();
|
|
116
|
-
const loading = ref(false);
|
|
117
|
-
const detailLoading = ref(false);
|
|
118
|
-
const keyword = ref("");
|
|
119
|
-
const projects = ref<ProjectDocumentProject[]>([]);
|
|
120
|
-
const selectedDocumentId = ref("");
|
|
121
|
-
const selectedDocument = ref<ProjectDocument>();
|
|
122
|
-
const detailRequestToken = ref(0);
|
|
123
|
-
const documentTreeRef = ref<InstanceType<typeof ElTree>>();
|
|
124
|
-
const markdownRef = ref<HTMLElement>();
|
|
125
|
-
const readerScrollRef = ref<HTMLElement>();
|
|
126
|
-
const documentTree = computed<ProjectDocumentTreeNode[]>(() => projects.value.map(buildProjectTreeNode));
|
|
127
|
-
const documents = computed<ProjectDocumentTreeNode[]>(() => flattenDocumentTree(documentTree.value));
|
|
128
|
-
const documentPathIndex = computed(() => {
|
|
129
|
-
const index = new Map<string, ProjectDocumentListItem>();
|
|
130
|
-
for (const node of documents.value) {
|
|
131
|
-
if (node.document) {
|
|
132
|
-
index.set(`${node.projectKey}\0${node.path}`, node.document);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
return index;
|
|
136
|
-
});
|
|
137
|
-
const filteredDocumentCount = computed(() => {
|
|
138
|
-
const search = keyword.value.trim().toLocaleLowerCase();
|
|
139
|
-
if (!search) return documents.value.length;
|
|
140
|
-
return documents.value.filter(node =>
|
|
141
|
-
[node.label, node.projectKey, node.projectName, node.path].some(value => value.toLocaleLowerCase().includes(search))
|
|
142
|
-
).length;
|
|
143
|
-
});
|
|
144
|
-
const selectedDocumentNodeKey = computed(() => (selectedDocumentId.value ? buildDocumentNodeKey(selectedDocumentId.value) : ""));
|
|
145
|
-
const selectedDocumentName = computed(() => selectedDocument.value?.name ?? "");
|
|
146
|
-
const selectedDocumentUpdatedAt = computed(
|
|
147
|
-
() => documents.value.find(node => node.document?.id === selectedDocumentId.value)?.document?.updated_at ?? ""
|
|
148
|
-
);
|
|
149
|
-
|
|
150
|
-
/** 加载项目文档目录并恢复当前选择。 */
|
|
151
|
-
async function loadDocuments() {
|
|
152
|
-
loading.value = true;
|
|
153
|
-
try {
|
|
154
|
-
const response = await defProjectDocumentService.TreeProjectDocument({});
|
|
155
|
-
projects.value = response.projects ?? [];
|
|
156
|
-
const nextId = documents.value.some(node => node.document?.id === selectedDocumentId.value)
|
|
157
|
-
? selectedDocumentId.value
|
|
158
|
-
: (documents.value[0]?.document?.id ?? "");
|
|
159
|
-
await nextTick();
|
|
160
|
-
documentTreeRef.value?.filter(keyword.value);
|
|
161
|
-
if (nextId) {
|
|
162
|
-
await selectDocument(nextId);
|
|
163
|
-
} else {
|
|
164
|
-
selectedDocumentId.value = "";
|
|
165
|
-
selectedDocument.value = undefined;
|
|
166
|
-
detailRequestToken.value += 1;
|
|
167
|
-
}
|
|
168
|
-
} finally {
|
|
169
|
-
loading.value = false;
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
/** 选择项目文档并加载 Markdown 详情。 */
|
|
174
|
-
async function selectDocument(id: string, anchor = "") {
|
|
175
|
-
if (!id) return;
|
|
176
|
-
selectedDocumentId.value = id;
|
|
177
|
-
detailLoading.value = true;
|
|
178
|
-
const requestToken = detailRequestToken.value + 1;
|
|
179
|
-
detailRequestToken.value = requestToken;
|
|
180
|
-
try {
|
|
181
|
-
const detail = await defProjectDocumentService.GetProjectDocument({ id });
|
|
182
|
-
if (detailRequestToken.value === requestToken && selectedDocumentId.value === id) {
|
|
183
|
-
selectedDocument.value = detail;
|
|
184
|
-
await nextTick();
|
|
185
|
-
documentTreeRef.value?.setCurrentKey(buildDocumentNodeKey(id));
|
|
186
|
-
scrollToAnchor(anchor);
|
|
187
|
-
}
|
|
188
|
-
} finally {
|
|
189
|
-
if (detailRequestToken.value === requestToken) {
|
|
190
|
-
detailLoading.value = false;
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
/** 处理项目文档树节点选择。 */
|
|
196
|
-
function handleTreeNodeClick(node: ProjectDocumentTreeNode) {
|
|
197
|
-
if (!node.document) return;
|
|
198
|
-
void selectDocument(node.document.id);
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
/** 按项目、目录或路径过滤项目文档树。 */
|
|
202
|
-
function filterTreeNode(value: unknown, data: TreeNodeData) {
|
|
203
|
-
const node = data as ProjectDocumentTreeNode;
|
|
204
|
-
const search = String(value ?? "")
|
|
205
|
-
.trim()
|
|
206
|
-
.toLocaleLowerCase();
|
|
207
|
-
if (!search) return true;
|
|
208
|
-
return [node.label, node.projectKey, node.projectName, node.path].some(field => field.toLocaleLowerCase().includes(search));
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
/** 处理 Markdown 中的页内锚点、相对文档和外部链接。 */
|
|
212
|
-
function handleMarkdownClick(event: MouseEvent) {
|
|
213
|
-
const target = event.target;
|
|
214
|
-
if (!(target instanceof Element)) return;
|
|
215
|
-
const anchor = target.closest("a");
|
|
216
|
-
const href = anchor?.getAttribute("href");
|
|
217
|
-
if (!anchor || !href || !selectedDocument.value) return;
|
|
218
|
-
if (href.startsWith("#")) {
|
|
219
|
-
event.preventDefault();
|
|
220
|
-
scrollToAnchor(href.slice(1));
|
|
221
|
-
return;
|
|
222
|
-
}
|
|
223
|
-
if (/^(?:[a-z][a-z\d+.-]*:|\/\/)/i.test(href)) {
|
|
224
|
-
event.preventDefault();
|
|
225
|
-
window.open(href, "_blank", "noopener,noreferrer");
|
|
226
|
-
return;
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
event.preventDefault();
|
|
230
|
-
const [rawPath, rawAnchor = ""] = href.split("#", 2);
|
|
231
|
-
const linkPath = decodeURIComponent(rawPath.split("?", 1)[0] ?? "");
|
|
232
|
-
const documentPath = resolveDocumentPath(selectedDocument.value.path, linkPath);
|
|
233
|
-
const linkedDocument = documentPathIndex.value.get(`${selectedDocument.value.project_key}\0${documentPath}`);
|
|
234
|
-
if (!linkedDocument) {
|
|
235
|
-
ElMessage.warning(t("system.project.document.message.uncollected", { path: documentPath }));
|
|
236
|
-
return;
|
|
237
|
-
}
|
|
238
|
-
void selectDocument(linkedDocument.id, decodeURIComponent(rawAnchor));
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
/** 基于当前文档目录解析项目内相对路径。 */
|
|
242
|
-
function resolveDocumentPath(currentPath: string, linkPath: string) {
|
|
243
|
-
const baseSegments = linkPath.startsWith("/") ? [] : currentPath.split("/").slice(0, -1);
|
|
244
|
-
for (const segment of linkPath.split("/")) {
|
|
245
|
-
if (!segment || segment === ".") continue;
|
|
246
|
-
if (segment === "..") {
|
|
247
|
-
baseSegments.pop();
|
|
248
|
-
continue;
|
|
249
|
-
}
|
|
250
|
-
baseSegments.push(segment);
|
|
251
|
-
}
|
|
252
|
-
return baseSegments.join("/");
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
/** 在当前 Markdown 阅读区滚动到指定标题锚点。 */
|
|
256
|
-
function scrollToAnchor(anchor: string) {
|
|
257
|
-
if (!anchor) {
|
|
258
|
-
readerScrollRef.value?.scrollTo({ top: 0 });
|
|
259
|
-
return;
|
|
260
|
-
}
|
|
261
|
-
const decodedAnchor = decodeURIComponent(anchor);
|
|
262
|
-
const heading = markdownRef.value?.querySelector<HTMLElement>(`#${CSS.escape(decodedAnchor)}`);
|
|
263
|
-
heading?.scrollIntoView({ block: "start" });
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
/** 将 RFC3339 更新时间格式化为紧凑的本地时间。 */
|
|
267
|
-
function formatDocumentUpdatedAt(value: string) {
|
|
268
|
-
const date = new Date(value);
|
|
269
|
-
if (Number.isNaN(date.getTime())) return value;
|
|
270
|
-
return new Intl.DateTimeFormat(getCurrentLocale(), {
|
|
271
|
-
month: "2-digit",
|
|
272
|
-
day: "2-digit",
|
|
273
|
-
hour: "2-digit",
|
|
274
|
-
minute: "2-digit",
|
|
275
|
-
hourCycle: "h23"
|
|
276
|
-
})
|
|
277
|
-
.format(date)
|
|
278
|
-
.replaceAll("/", "-");
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
/** 将接口项目节点转换为管理端树节点。 */
|
|
282
|
-
function buildProjectTreeNode(project: ProjectDocumentProject): ProjectDocumentTreeNode {
|
|
283
|
-
return {
|
|
284
|
-
key: `project:${project.key}`,
|
|
285
|
-
label: project.name,
|
|
286
|
-
kind: "project",
|
|
287
|
-
projectKey: project.key,
|
|
288
|
-
projectName: project.name,
|
|
289
|
-
path: "",
|
|
290
|
-
children: [
|
|
291
|
-
...(project.documents ?? []).map(document => buildDocumentTreeNode(document, project.key, project.name)),
|
|
292
|
-
...(project.directories ?? []).map(directory => buildDirectoryTreeNode(directory, project.key, project.name))
|
|
293
|
-
]
|
|
294
|
-
};
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
/** 递归转换接口目录节点。 */
|
|
298
|
-
function buildDirectoryTreeNode(
|
|
299
|
-
directory: ProjectDocumentDirectory,
|
|
300
|
-
projectKey: string,
|
|
301
|
-
projectName: string
|
|
302
|
-
): ProjectDocumentTreeNode {
|
|
303
|
-
return {
|
|
304
|
-
key: `directory:${projectKey}:${directory.path}`,
|
|
305
|
-
label: directory.name,
|
|
306
|
-
kind: "directory",
|
|
307
|
-
projectKey,
|
|
308
|
-
projectName,
|
|
309
|
-
path: directory.path,
|
|
310
|
-
children: [
|
|
311
|
-
...(directory.documents ?? []).map(document => buildDocumentTreeNode(document, projectKey, projectName)),
|
|
312
|
-
...(directory.directories ?? []).map(child => buildDirectoryTreeNode(child, projectKey, projectName))
|
|
313
|
-
]
|
|
314
|
-
};
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
/** 将接口文档目录项转换为树叶子节点。 */
|
|
318
|
-
function buildDocumentTreeNode(
|
|
319
|
-
document: ProjectDocumentListItem,
|
|
320
|
-
projectKey: string,
|
|
321
|
-
projectName: string
|
|
322
|
-
): ProjectDocumentTreeNode {
|
|
323
|
-
return {
|
|
324
|
-
key: buildDocumentNodeKey(document.id),
|
|
325
|
-
label: document.name,
|
|
326
|
-
kind: "document",
|
|
327
|
-
projectKey,
|
|
328
|
-
projectName,
|
|
329
|
-
path: document.path,
|
|
330
|
-
document,
|
|
331
|
-
children: []
|
|
332
|
-
};
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
/** 构造文档树叶子节点稳定标识。 */
|
|
336
|
-
function buildDocumentNodeKey(id: string) {
|
|
337
|
-
return `document:${id}`;
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
/** 将树中的文档叶子节点展开为导航节点。 */
|
|
341
|
-
function flattenDocumentTree(nodes: ProjectDocumentTreeNode[]): ProjectDocumentTreeNode[] {
|
|
342
|
-
const documents: ProjectDocumentTreeNode[] = [];
|
|
343
|
-
for (const node of nodes) {
|
|
344
|
-
if (node.document) {
|
|
345
|
-
documents.push(node);
|
|
346
|
-
}
|
|
347
|
-
documents.push(...flattenDocumentTree(node.children));
|
|
348
|
-
}
|
|
349
|
-
return documents;
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
watch(keyword, value => {
|
|
353
|
-
documentTreeRef.value?.filter(value);
|
|
354
|
-
});
|
|
355
|
-
|
|
356
|
-
watch(locale, () => {
|
|
357
|
-
void loadDocuments();
|
|
358
|
-
});
|
|
359
|
-
|
|
360
|
-
onMounted(() => {
|
|
361
|
-
void loadDocuments();
|
|
362
|
-
});
|
|
363
|
-
</script>
|
|
364
|
-
|
|
365
|
-
<style scoped lang="scss">
|
|
366
|
-
.project-doc-page {
|
|
367
|
-
box-sizing: border-box;
|
|
368
|
-
color: var(--admin-page-text-primary);
|
|
369
|
-
background: var(--el-bg-color-page);
|
|
370
|
-
}
|
|
371
|
-
.project-doc-shell {
|
|
372
|
-
display: grid;
|
|
373
|
-
flex: 1;
|
|
374
|
-
grid-template-columns: 340px minmax(0, 1fr);
|
|
375
|
-
min-width: 0;
|
|
376
|
-
min-height: 520px;
|
|
377
|
-
overflow: hidden;
|
|
378
|
-
background: var(--admin-page-card-bg);
|
|
379
|
-
border: 1px solid var(--admin-page-card-border);
|
|
380
|
-
border-radius: var(--admin-page-radius);
|
|
381
|
-
box-shadow: var(--admin-page-shadow);
|
|
382
|
-
}
|
|
383
|
-
.document-navigation,
|
|
384
|
-
.document-reader {
|
|
385
|
-
display: flex;
|
|
386
|
-
flex-direction: column;
|
|
387
|
-
min-width: 0;
|
|
388
|
-
min-height: 0;
|
|
389
|
-
overflow: hidden;
|
|
390
|
-
}
|
|
391
|
-
.document-navigation {
|
|
392
|
-
border-right: 1px solid var(--admin-page-divider);
|
|
393
|
-
}
|
|
394
|
-
.navigation-header {
|
|
395
|
-
display: flex;
|
|
396
|
-
gap: 12px;
|
|
397
|
-
align-items: center;
|
|
398
|
-
padding: 16px;
|
|
399
|
-
border-bottom: 1px solid var(--admin-page-divider);
|
|
400
|
-
}
|
|
401
|
-
.document-count {
|
|
402
|
-
flex: 0 0 auto;
|
|
403
|
-
font-size: 12px;
|
|
404
|
-
color: var(--admin-page-text-secondary);
|
|
405
|
-
white-space: nowrap;
|
|
406
|
-
}
|
|
407
|
-
.document-tree-scroll {
|
|
408
|
-
flex: 1;
|
|
409
|
-
min-height: 0;
|
|
410
|
-
padding: 8px;
|
|
411
|
-
overflow-y: auto;
|
|
412
|
-
}
|
|
413
|
-
.document-tree {
|
|
414
|
-
min-width: 100%;
|
|
415
|
-
color: var(--admin-page-text-primary);
|
|
416
|
-
background: transparent;
|
|
417
|
-
|
|
418
|
-
--el-tree-node-hover-bg-color: var(--el-fill-color-light);
|
|
419
|
-
}
|
|
420
|
-
.document-tree :deep(.el-tree-node__content) {
|
|
421
|
-
height: 34px;
|
|
422
|
-
padding-right: 8px;
|
|
423
|
-
border-radius: var(--admin-page-radius);
|
|
424
|
-
}
|
|
425
|
-
.document-tree :deep(.el-tree-node.is-current > .el-tree-node__content) {
|
|
426
|
-
color: var(--el-color-primary);
|
|
427
|
-
background: var(--admin-page-accent-soft-bg);
|
|
428
|
-
box-shadow: inset 3px 0 0 var(--el-color-primary);
|
|
429
|
-
}
|
|
430
|
-
.document-tree-node {
|
|
431
|
-
display: flex;
|
|
432
|
-
flex: 1;
|
|
433
|
-
gap: 7px;
|
|
434
|
-
align-items: center;
|
|
435
|
-
min-width: 0;
|
|
436
|
-
overflow: hidden;
|
|
437
|
-
}
|
|
438
|
-
.document-tree-node__icon {
|
|
439
|
-
flex: 0 0 auto;
|
|
440
|
-
font-size: 15px;
|
|
441
|
-
color: var(--admin-page-text-secondary);
|
|
442
|
-
}
|
|
443
|
-
.document-tree-node__label {
|
|
444
|
-
min-width: 0;
|
|
445
|
-
overflow: hidden;
|
|
446
|
-
text-overflow: ellipsis;
|
|
447
|
-
white-space: nowrap;
|
|
448
|
-
}
|
|
449
|
-
.document-tree-node.is-project .document-tree-node__label {
|
|
450
|
-
font-weight: 650;
|
|
451
|
-
}
|
|
452
|
-
.document-tree-node.is-directory .document-tree-node__label {
|
|
453
|
-
font-weight: 550;
|
|
454
|
-
}
|
|
455
|
-
.document-tree-node code {
|
|
456
|
-
flex: 0 0 auto;
|
|
457
|
-
margin-left: auto;
|
|
458
|
-
font-size: 11px;
|
|
459
|
-
color: var(--admin-page-text-secondary);
|
|
460
|
-
}
|
|
461
|
-
.reader-header {
|
|
462
|
-
box-sizing: border-box;
|
|
463
|
-
display: flex;
|
|
464
|
-
gap: 20px;
|
|
465
|
-
align-items: center;
|
|
466
|
-
justify-content: space-between;
|
|
467
|
-
min-height: 64px;
|
|
468
|
-
padding: 10px 24px;
|
|
469
|
-
border-bottom: 1px solid var(--admin-page-divider);
|
|
470
|
-
}
|
|
471
|
-
.reader-header__identity {
|
|
472
|
-
display: flex;
|
|
473
|
-
gap: 10px;
|
|
474
|
-
align-items: center;
|
|
475
|
-
min-width: 0;
|
|
476
|
-
}
|
|
477
|
-
.reader-header__identity > :deep(.el-icon) {
|
|
478
|
-
flex: 0 0 auto;
|
|
479
|
-
font-size: 18px;
|
|
480
|
-
color: var(--el-color-primary);
|
|
481
|
-
}
|
|
482
|
-
.reader-header__title {
|
|
483
|
-
display: flex;
|
|
484
|
-
flex-direction: column;
|
|
485
|
-
gap: 3px;
|
|
486
|
-
min-width: 0;
|
|
487
|
-
}
|
|
488
|
-
.reader-header__title strong,
|
|
489
|
-
.reader-header__title span {
|
|
490
|
-
overflow: hidden;
|
|
491
|
-
text-overflow: ellipsis;
|
|
492
|
-
white-space: nowrap;
|
|
493
|
-
}
|
|
494
|
-
.reader-header__title strong {
|
|
495
|
-
font-size: 15px;
|
|
496
|
-
color: var(--admin-page-text-primary);
|
|
497
|
-
}
|
|
498
|
-
.reader-header__title span,
|
|
499
|
-
.reader-header time {
|
|
500
|
-
font-size: 12px;
|
|
501
|
-
color: var(--admin-page-text-secondary);
|
|
502
|
-
}
|
|
503
|
-
.reader-header time {
|
|
504
|
-
flex: 0 0 auto;
|
|
505
|
-
font-variant-numeric: tabular-nums;
|
|
506
|
-
white-space: nowrap;
|
|
507
|
-
}
|
|
508
|
-
.reader-scroll {
|
|
509
|
-
flex: 1;
|
|
510
|
-
min-height: 0;
|
|
511
|
-
padding: 28px clamp(24px, 4vw, 52px) 40px;
|
|
512
|
-
overflow-y: auto;
|
|
513
|
-
scrollbar-gutter: stable;
|
|
514
|
-
}
|
|
515
|
-
.project-markdown {
|
|
516
|
-
width: 100%;
|
|
517
|
-
max-width: 1040px;
|
|
518
|
-
margin: 0 auto;
|
|
519
|
-
overflow-wrap: anywhere;
|
|
520
|
-
}
|
|
521
|
-
.reader-loading {
|
|
522
|
-
padding: 24px;
|
|
523
|
-
}
|
|
524
|
-
|
|
525
|
-
@media (width <= 900px) {
|
|
526
|
-
.project-doc-shell {
|
|
527
|
-
grid-template-columns: 280px minmax(0, 1fr);
|
|
528
|
-
}
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
@media (width <= 720px) {
|
|
532
|
-
.project-doc-shell {
|
|
533
|
-
display: flex;
|
|
534
|
-
flex-direction: column;
|
|
535
|
-
}
|
|
536
|
-
.document-navigation {
|
|
537
|
-
flex: 0 0 auto;
|
|
538
|
-
height: 240px;
|
|
539
|
-
border-right: 0;
|
|
540
|
-
border-bottom: 1px solid var(--admin-page-divider);
|
|
541
|
-
}
|
|
542
|
-
.document-reader {
|
|
543
|
-
flex: 1;
|
|
544
|
-
min-height: 0;
|
|
545
|
-
}
|
|
546
|
-
.reader-scroll {
|
|
547
|
-
padding-top: 24px;
|
|
548
|
-
padding-right: 16px;
|
|
549
|
-
padding-left: 16px;
|
|
550
|
-
}
|
|
551
|
-
.reader-header {
|
|
552
|
-
padding-right: 16px;
|
|
553
|
-
padding-left: 16px;
|
|
554
|
-
}
|
|
555
|
-
.reader-header time {
|
|
556
|
-
display: none;
|
|
557
|
-
}
|
|
558
|
-
.project-markdown :deep(h1) {
|
|
559
|
-
font-size: 26px;
|
|
560
|
-
}
|
|
561
|
-
.project-markdown :deep(h2) {
|
|
562
|
-
font-size: 21px;
|
|
563
|
-
}
|
|
564
|
-
}
|
|
565
|
-
</style>
|