@liujitcn/kratos-admin-system 0.0.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.
Files changed (208) hide show
  1. package/README.md +137 -0
  2. package/dist/package/declarations/index.d.ts +1 -0
  3. package/dist/package/declarations/src/ai.d.ts +10 -0
  4. package/dist/package/declarations/src/api/base/ai_message.d.ts +27 -0
  5. package/dist/package/declarations/src/api/base/ai_session.d.ts +17 -0
  6. package/dist/package/declarations/src/api/base/ai_tool.d.ts +7 -0
  7. package/dist/package/declarations/src/api/base/oauth.d.ts +13 -0
  8. package/dist/package/declarations/src/api/base/sse.d.ts +31 -0
  9. package/dist/package/declarations/src/api/system/auth.d.ts +17 -0
  10. package/dist/package/declarations/src/api/system/base_api.d.ts +22 -0
  11. package/dist/package/declarations/src/api/system/base_area.d.ts +19 -0
  12. package/dist/package/declarations/src/api/system/base_config.d.ts +20 -0
  13. package/dist/package/declarations/src/api/system/base_dept.d.ts +21 -0
  14. package/dist/package/declarations/src/api/system/base_dict.d.ts +32 -0
  15. package/dist/package/declarations/src/api/system/base_job.d.ts +28 -0
  16. package/dist/package/declarations/src/api/system/base_log.d.ts +9 -0
  17. package/dist/package/declarations/src/api/system/base_menu.d.ts +21 -0
  18. package/dist/package/declarations/src/api/system/base_migration.d.ts +10 -0
  19. package/dist/package/declarations/src/api/system/base_post.d.ts +21 -0
  20. package/dist/package/declarations/src/api/system/base_role.d.ts +23 -0
  21. package/dist/package/declarations/src/api/system/base_tenant.d.ts +21 -0
  22. package/dist/package/declarations/src/api/system/base_user.d.ts +23 -0
  23. package/dist/package/declarations/src/api/system/code_gen.d.ts +14 -0
  24. package/dist/package/declarations/src/api/system/code_gen_column.d.ts +12 -0
  25. package/dist/package/declarations/src/api/system/code_gen_proto.d.ts +10 -0
  26. package/dist/package/declarations/src/api/system/code_gen_sse.d.ts +8 -0
  27. package/dist/package/declarations/src/api/system/code_gen_table.d.ts +18 -0
  28. package/dist/package/declarations/src/api/system/project_document.d.ts +9 -0
  29. package/dist/package/declarations/src/components/Ai.vue.d.ts +3 -0
  30. package/dist/package/declarations/src/index.d.ts +3 -0
  31. package/dist/package/declarations/src/module.d.ts +2 -0
  32. package/dist/package/declarations/src/rpc/base/v1/ai_message.d.ts +82 -0
  33. package/dist/package/declarations/src/rpc/base/v1/ai_session.d.ts +176 -0
  34. package/dist/package/declarations/src/rpc/base/v1/ai_tool.d.ts +59 -0
  35. package/dist/package/declarations/src/rpc/base/v1/oauth.d.ts +167 -0
  36. package/dist/package/declarations/src/rpc/base/v1/sse.d.ts +13 -0
  37. package/dist/package/declarations/src/rpc/common/v1/common.d.ts +57 -0
  38. package/dist/package/declarations/src/rpc/common/v1/enum.d.ts +58 -0
  39. package/dist/package/declarations/src/rpc/common/v1/types.d.ts +60 -0
  40. package/dist/package/declarations/src/rpc/google/protobuf/empty.d.ts +11 -0
  41. package/dist/package/declarations/src/rpc/google/protobuf/timestamp.d.ts +107 -0
  42. package/dist/package/declarations/src/rpc/system/admin/v1/auth.d.ts +156 -0
  43. package/dist/package/declarations/src/rpc/system/admin/v1/base_api.d.ts +193 -0
  44. package/dist/package/declarations/src/rpc/system/admin/v1/base_area.d.ts +82 -0
  45. package/dist/package/declarations/src/rpc/system/admin/v1/base_config.d.ts +112 -0
  46. package/dist/package/declarations/src/rpc/system/admin/v1/base_dept.d.ts +112 -0
  47. package/dist/package/declarations/src/rpc/system/admin/v1/base_dict.d.ts +215 -0
  48. package/dist/package/declarations/src/rpc/system/admin/v1/base_job.d.ts +177 -0
  49. package/dist/package/declarations/src/rpc/system/admin/v1/base_log.d.ts +87 -0
  50. package/dist/package/declarations/src/rpc/system/admin/v1/base_menu.d.ts +151 -0
  51. package/dist/package/declarations/src/rpc/system/admin/v1/base_migration.d.ts +64 -0
  52. package/dist/package/declarations/src/rpc/system/admin/v1/base_post.d.ts +112 -0
  53. package/dist/package/declarations/src/rpc/system/admin/v1/base_role.d.ts +128 -0
  54. package/dist/package/declarations/src/rpc/system/admin/v1/base_tenant.d.ts +112 -0
  55. package/dist/package/declarations/src/rpc/system/admin/v1/base_user.d.ts +161 -0
  56. package/dist/package/declarations/src/rpc/system/admin/v1/code_gen.d.ts +155 -0
  57. package/dist/package/declarations/src/rpc/system/admin/v1/code_gen_column.d.ts +143 -0
  58. package/dist/package/declarations/src/rpc/system/admin/v1/code_gen_proto.d.ts +86 -0
  59. package/dist/package/declarations/src/rpc/system/admin/v1/code_gen_table.d.ts +149 -0
  60. package/dist/package/declarations/src/rpc/system/admin/v1/project_document.d.ts +64 -0
  61. package/dist/package/declarations/src/rpc/system/common/v1/enum.d.ts +67 -0
  62. package/dist/package/declarations/src/views/ai/chat/attachment.d.ts +14 -0
  63. package/dist/package/declarations/src/views/ai/chat/components/AiMarkdown.vue.d.ts +13 -0
  64. package/dist/package/declarations/src/views/ai/chat/components/ChatPanel.vue.d.ts +45 -0
  65. package/dist/package/declarations/src/views/ai/chat/components/SessionPanel.vue.d.ts +34 -0
  66. package/dist/package/declarations/src/views/ai/chat/components/XSender.vue.d.ts +12 -0
  67. package/dist/package/declarations/src/views/ai/chat/index.vue.d.ts +4 -0
  68. package/dist/package/declarations/src/views/ai/chat/message.d.ts +59 -0
  69. package/dist/package/declarations/src/views/ai/chat/stream.d.ts +10 -0
  70. package/dist/package/declarations/src/views/ai/chat/types.d.ts +115 -0
  71. package/dist/package/declarations/src/views/base/api/index.vue.d.ts +3 -0
  72. package/dist/package/declarations/src/views/base/area/index.vue.d.ts +3 -0
  73. package/dist/package/declarations/src/views/base/config/index.vue.d.ts +3 -0
  74. package/dist/package/declarations/src/views/base/dept/index.vue.d.ts +3 -0
  75. package/dist/package/declarations/src/views/base/dict/index.vue.d.ts +3 -0
  76. package/dist/package/declarations/src/views/base/dict/item.vue.d.ts +3 -0
  77. package/dist/package/declarations/src/views/base/job/index.vue.d.ts +3 -0
  78. package/dist/package/declarations/src/views/base/job/log.vue.d.ts +3 -0
  79. package/dist/package/declarations/src/views/base/log/index.vue.d.ts +3 -0
  80. package/dist/package/declarations/src/views/base/menu/index.vue.d.ts +3 -0
  81. package/dist/package/declarations/src/views/base/migration/index.vue.d.ts +4 -0
  82. package/dist/package/declarations/src/views/base/post/index.vue.d.ts +3 -0
  83. package/dist/package/declarations/src/views/base/role/index.vue.d.ts +3 -0
  84. package/dist/package/declarations/src/views/base/tenant/index.vue.d.ts +3 -0
  85. package/dist/package/declarations/src/views/base/user/components/dept-tree.vue.d.ts +19 -0
  86. package/dist/package/declarations/src/views/base/user/index.vue.d.ts +3 -0
  87. package/dist/package/declarations/src/views/profile/components/base.vue.d.ts +13 -0
  88. package/dist/package/declarations/src/views/profile/components/password.vue.d.ts +3 -0
  89. package/dist/package/declarations/src/views/profile/components/security.vue.d.ts +15 -0
  90. package/dist/package/declarations/src/views/profile/index.vue.d.ts +3 -0
  91. package/dist/package/declarations/src/views/tool/api-doc/index.vue.d.ts +4 -0
  92. package/dist/package/declarations/src/views/tool/code-gen/code-preview/index.vue.d.ts +3 -0
  93. package/dist/package/declarations/src/views/tool/code-gen/columns/index.vue.d.ts +3 -0
  94. package/dist/package/declarations/src/views/tool/code-gen/columns/option-copy.d.ts +25 -0
  95. package/dist/package/declarations/src/views/tool/code-gen/components/CodeGenProgressDialog.vue.d.ts +16 -0
  96. package/dist/package/declarations/src/views/tool/code-gen/components/CodePreviewPane.vue.d.ts +9 -0
  97. package/dist/package/declarations/src/views/tool/code-gen/config.d.ts +32 -0
  98. package/dist/package/declarations/src/views/tool/code-gen/preview/capabilities.d.ts +20 -0
  99. package/dist/package/declarations/src/views/tool/code-gen/preview/data.d.ts +42 -0
  100. package/dist/package/declarations/src/views/tool/code-gen/preview/index.vue.d.ts +3 -0
  101. package/dist/package/declarations/src/views/tool/code-gen/proto/index.vue.d.ts +3 -0
  102. package/dist/package/declarations/src/views/tool/code-gen/table/index.vue.d.ts +3 -0
  103. package/dist/package/declarations/src/views/tool/project-doc/index.vue.d.ts +4 -0
  104. package/dist/package/src/ai.ts +16 -0
  105. package/dist/package/src/api/base/ai_message.ts +139 -0
  106. package/dist/package/src/api/base/ai_session.ts +77 -0
  107. package/dist/package/src/api/base/ai_tool.ts +22 -0
  108. package/dist/package/src/api/base/oauth.ts +47 -0
  109. package/dist/package/src/api/base/sse.ts +192 -0
  110. package/dist/package/src/api/system/auth.ts +65 -0
  111. package/dist/package/src/api/system/base_api.ts +95 -0
  112. package/dist/package/src/api/system/base_area.ts +73 -0
  113. package/dist/package/src/api/system/base_config.ts +82 -0
  114. package/dist/package/src/api/system/base_dept.ts +83 -0
  115. package/dist/package/src/api/system/base_dict.ts +144 -0
  116. package/dist/package/src/api/system/base_job.ts +125 -0
  117. package/dist/package/src/api/system/base_log.ts +32 -0
  118. package/dist/package/src/api/system/base_menu.ts +83 -0
  119. package/dist/package/src/api/system/base_migration.ts +35 -0
  120. package/dist/package/src/api/system/base_post.ts +83 -0
  121. package/dist/package/src/api/system/base_role.ts +93 -0
  122. package/dist/package/src/api/system/base_tenant.ts +83 -0
  123. package/dist/package/src/api/system/base_user.ts +93 -0
  124. package/dist/package/src/api/system/code_gen.ts +56 -0
  125. package/dist/package/src/api/system/code_gen_column.ts +43 -0
  126. package/dist/package/src/api/system/code_gen_proto.ts +32 -0
  127. package/dist/package/src/api/system/code_gen_sse.ts +33 -0
  128. package/dist/package/src/api/system/code_gen_table.ts +74 -0
  129. package/dist/package/src/api/system/project_document.ts +33 -0
  130. package/dist/package/src/components/Ai.vue +57 -0
  131. package/dist/package/src/index.ts +3 -0
  132. package/dist/package/src/module.ts +17 -0
  133. package/dist/package/src/rpc/base/v1/ai_message.ts +98 -0
  134. package/dist/package/src/rpc/base/v1/ai_session.ts +214 -0
  135. package/dist/package/src/rpc/base/v1/ai_tool.ts +74 -0
  136. package/dist/package/src/rpc/base/v1/oauth.ts +199 -0
  137. package/dist/package/src/rpc/base/v1/sse.ts +22 -0
  138. package/dist/package/src/rpc/common/v1/common.ts +71 -0
  139. package/dist/package/src/rpc/common/v1/enum.ts +71 -0
  140. package/dist/package/src/rpc/common/v1/types.ts +77 -0
  141. package/dist/package/src/rpc/google/protobuf/empty.ts +19 -0
  142. package/dist/package/src/rpc/google/protobuf/timestamp.ts +115 -0
  143. package/dist/package/src/rpc/system/admin/v1/auth.ts +208 -0
  144. package/dist/package/src/rpc/system/admin/v1/base_api.ts +241 -0
  145. package/dist/package/src/rpc/system/admin/v1/base_area.ts +105 -0
  146. package/dist/package/src/rpc/system/admin/v1/base_config.ts +140 -0
  147. package/dist/package/src/rpc/system/admin/v1/base_dept.ts +140 -0
  148. package/dist/package/src/rpc/system/admin/v1/base_dict.ts +249 -0
  149. package/dist/package/src/rpc/system/admin/v1/base_job.ts +206 -0
  150. package/dist/package/src/rpc/system/admin/v1/base_log.ts +101 -0
  151. package/dist/package/src/rpc/system/admin/v1/base_menu.ts +195 -0
  152. package/dist/package/src/rpc/system/admin/v1/base_migration.ts +81 -0
  153. package/dist/package/src/rpc/system/admin/v1/base_post.ts +134 -0
  154. package/dist/package/src/rpc/system/admin/v1/base_role.ts +151 -0
  155. package/dist/package/src/rpc/system/admin/v1/base_tenant.ts +134 -0
  156. package/dist/package/src/rpc/system/admin/v1/base_user.ts +190 -0
  157. package/dist/package/src/rpc/system/admin/v1/code_gen.ts +176 -0
  158. package/dist/package/src/rpc/system/admin/v1/code_gen_column.ts +170 -0
  159. package/dist/package/src/rpc/system/admin/v1/code_gen_proto.ts +104 -0
  160. package/dist/package/src/rpc/system/admin/v1/code_gen_table.ts +179 -0
  161. package/dist/package/src/rpc/system/admin/v1/project_document.ts +79 -0
  162. package/dist/package/src/rpc/system/common/v1/enum.ts +80 -0
  163. package/dist/package/src/typings/swagger-ui-dist.d.ts +28 -0
  164. package/dist/package/src/typings/x-markdown-vue.d.ts +1 -0
  165. package/dist/package/src/views/ai/chat/attachment.ts +65 -0
  166. package/dist/package/src/views/ai/chat/components/AiMarkdown.vue +162 -0
  167. package/dist/package/src/views/ai/chat/components/ChatPanel.vue +1861 -0
  168. package/dist/package/src/views/ai/chat/components/SessionPanel.vue +316 -0
  169. package/dist/package/src/views/ai/chat/components/XSender.vue +554 -0
  170. package/dist/package/src/views/ai/chat/index.vue +848 -0
  171. package/dist/package/src/views/ai/chat/message.ts +416 -0
  172. package/dist/package/src/views/ai/chat/stream.ts +115 -0
  173. package/dist/package/src/views/ai/chat/types.ts +126 -0
  174. package/dist/package/src/views/base/api/index.vue +455 -0
  175. package/dist/package/src/views/base/area/index.vue +269 -0
  176. package/dist/package/src/views/base/config/index.vue +530 -0
  177. package/dist/package/src/views/base/dept/index.vue +461 -0
  178. package/dist/package/src/views/base/dict/index.vue +304 -0
  179. package/dist/package/src/views/base/dict/item.vue +373 -0
  180. package/dist/package/src/views/base/job/index.vue +535 -0
  181. package/dist/package/src/views/base/job/log.vue +202 -0
  182. package/dist/package/src/views/base/log/index.vue +317 -0
  183. package/dist/package/src/views/base/menu/index.vue +944 -0
  184. package/dist/package/src/views/base/migration/index.vue +791 -0
  185. package/dist/package/src/views/base/post/index.vue +324 -0
  186. package/dist/package/src/views/base/role/index.vue +684 -0
  187. package/dist/package/src/views/base/tenant/index.vue +328 -0
  188. package/dist/package/src/views/base/user/components/dept-tree.vue +75 -0
  189. package/dist/package/src/views/base/user/index.vue +783 -0
  190. package/dist/package/src/views/profile/components/base.vue +320 -0
  191. package/dist/package/src/views/profile/components/password.vue +269 -0
  192. package/dist/package/src/views/profile/components/security.vue +443 -0
  193. package/dist/package/src/views/profile/index.vue +199 -0
  194. package/dist/package/src/views/tool/api-doc/index.vue +275 -0
  195. package/dist/package/src/views/tool/code-gen/code-preview/index.vue +233 -0
  196. package/dist/package/src/views/tool/code-gen/columns/index.vue +1456 -0
  197. package/dist/package/src/views/tool/code-gen/columns/option-copy.ts +125 -0
  198. package/dist/package/src/views/tool/code-gen/components/CodeGenProgressDialog.vue +328 -0
  199. package/dist/package/src/views/tool/code-gen/components/CodePreviewPane.vue +42 -0
  200. package/dist/package/src/views/tool/code-gen/config.ts +175 -0
  201. package/dist/package/src/views/tool/code-gen/preview/capabilities.ts +34 -0
  202. package/dist/package/src/views/tool/code-gen/preview/data.ts +331 -0
  203. package/dist/package/src/views/tool/code-gen/preview/index.vue +831 -0
  204. package/dist/package/src/views/tool/code-gen/proto/index.vue +703 -0
  205. package/dist/package/src/views/tool/code-gen/table/index.vue +864 -0
  206. package/dist/package/src/views/tool/project-doc/index.vue +561 -0
  207. package/package.json +60 -0
  208. package/tsconfig.json +13 -0
@@ -0,0 +1,561 @@
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="项目文档目录">
5
+ <header class="navigation-header">
6
+ <el-input v-model="keyword" clearable placeholder="搜索项目或路径" :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
+ <time
29
+ v-if="data.kind === 'document' && data.document?.updated_at"
30
+ class="document-tree-node__updated-at"
31
+ :datetime="data.document.updated_at"
32
+ :title="data.document.updated_at"
33
+ >
34
+ {{ formatDocumentUpdatedAt(data.document.updated_at) }}
35
+ </time>
36
+ <code v-if="data.kind === 'project'">{{ data.projectKey }}</code>
37
+ </span>
38
+ </template>
39
+ </el-tree>
40
+ <el-empty v-if="filteredDocumentCount === 0" description="暂无匹配文档" :image-size="72" />
41
+ </div>
42
+ <el-empty v-else description="暂无项目文档" :image-size="72" />
43
+ </aside>
44
+
45
+ <section class="document-reader">
46
+ <div v-if="detailLoading && !selectedDocument" class="reader-loading">
47
+ <el-skeleton :rows="10" animated />
48
+ </div>
49
+ <template v-else-if="selectedDocument">
50
+ <div ref="readerScrollRef" v-loading="detailLoading" class="reader-scroll">
51
+ <div ref="markdownRef" @click="handleMarkdownClick">
52
+ <MarkdownRenderer
53
+ class="project-markdown"
54
+ :markdown="selectedDocument.content"
55
+ :allow-html="false"
56
+ :sanitize="true"
57
+ :enable-breaks="true"
58
+ :enable-latex="false"
59
+ :enable-animate="false"
60
+ :enable-shiki="false"
61
+ :enable-mermaid="false"
62
+ :is-dark="globalStore.isDark"
63
+ :show-code-block-header="true"
64
+ :sticky-code-block-header="false"
65
+ :enable-code-line-number="false"
66
+ code-max-height="480px"
67
+ :style="markdownRootStyle"
68
+ />
69
+ </div>
70
+ </div>
71
+ </template>
72
+ <el-empty v-else description="请选择一篇项目文档" />
73
+ </section>
74
+ </main>
75
+ </div>
76
+ </template>
77
+
78
+ <script setup lang="ts">
79
+ import { computed, nextTick, onMounted, ref, watch } from "vue";
80
+ import { Search } from "@element-plus/icons-vue";
81
+ import type { TreeNodeData } from "element-plus";
82
+ import { MarkdownRenderer } from "x-markdown-vue";
83
+ import "x-markdown-vue/style";
84
+ import { defProjectDocumentService } from "@liujitcn/kratos-admin-system/api/system/project_document";
85
+ import type {
86
+ ProjectDocument,
87
+ ProjectDocumentDirectory,
88
+ ProjectDocumentListItem,
89
+ ProjectDocumentProject
90
+ } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/project_document";
91
+ import { useGlobalStore } from "@liujitcn/kratos-admin-core/stores/runtime";
92
+
93
+ defineOptions({
94
+ name: "ProjectDocument",
95
+ inheritAttrs: false
96
+ });
97
+
98
+ /** 项目文档树节点类型。 */
99
+ type ProjectDocumentTreeNodeKind = "project" | "directory" | "document";
100
+
101
+ /** 管理端项目文档树节点。 */
102
+ interface ProjectDocumentTreeNode {
103
+ /** 树节点稳定标识。 */
104
+ key: string;
105
+ /** 树节点展示名称。 */
106
+ label: string;
107
+ /** 树节点类型。 */
108
+ kind: ProjectDocumentTreeNodeKind;
109
+ /** 所属项目标识。 */
110
+ projectKey: string;
111
+ /** 所属项目名称。 */
112
+ projectName: string;
113
+ /** 项目内相对路径。 */
114
+ path: string;
115
+ /** 文档叶子节点数据。 */
116
+ document?: ProjectDocumentListItem;
117
+ /** 子节点。 */
118
+ children: ProjectDocumentTreeNode[];
119
+ }
120
+
121
+ const globalStore = useGlobalStore();
122
+ const loading = ref(false);
123
+ const detailLoading = ref(false);
124
+ const keyword = ref("");
125
+ const projects = ref<ProjectDocumentProject[]>([]);
126
+ const selectedDocumentId = ref("");
127
+ const selectedDocument = ref<ProjectDocument>();
128
+ const detailRequestToken = ref(0);
129
+ const documentTreeRef = ref<InstanceType<typeof ElTree>>();
130
+ const markdownRef = ref<HTMLElement>();
131
+ const readerScrollRef = ref<HTMLElement>();
132
+ const markdownRootStyle = {
133
+ padding: "0",
134
+ color: "inherit",
135
+ backgroundColor: "transparent"
136
+ };
137
+ const documentUpdatedAtFormatter = new Intl.DateTimeFormat("zh-CN", {
138
+ month: "2-digit",
139
+ day: "2-digit",
140
+ hour: "2-digit",
141
+ minute: "2-digit",
142
+ hourCycle: "h23"
143
+ });
144
+ const documentTree = computed<ProjectDocumentTreeNode[]>(() => projects.value.map(buildProjectTreeNode));
145
+ const documents = computed<ProjectDocumentTreeNode[]>(() => flattenDocumentTree(documentTree.value));
146
+ const documentPathIndex = computed(() => {
147
+ const index = new Map<string, ProjectDocumentListItem>();
148
+ for (const node of documents.value) {
149
+ if (node.document) {
150
+ index.set(`${node.projectKey}\0${node.path}`, node.document);
151
+ }
152
+ }
153
+ return index;
154
+ });
155
+ const filteredDocumentCount = computed(() => {
156
+ const search = keyword.value.trim().toLocaleLowerCase();
157
+ if (!search) return documents.value.length;
158
+ return documents.value.filter(node =>
159
+ [node.projectKey, node.projectName, node.path].some(value => value.toLocaleLowerCase().includes(search))
160
+ ).length;
161
+ });
162
+ const selectedDocumentNodeKey = computed(() => (selectedDocumentId.value ? buildDocumentNodeKey(selectedDocumentId.value) : ""));
163
+
164
+ /** 加载项目文档目录并恢复当前选择。 */
165
+ async function loadDocuments() {
166
+ loading.value = true;
167
+ try {
168
+ const response = await defProjectDocumentService.TreeProjectDocument({});
169
+ projects.value = response.projects ?? [];
170
+ const nextId = documents.value.some(node => node.document?.id === selectedDocumentId.value)
171
+ ? selectedDocumentId.value
172
+ : (documents.value[0]?.document?.id ?? "");
173
+ await nextTick();
174
+ documentTreeRef.value?.filter(keyword.value);
175
+ if (nextId) {
176
+ await selectDocument(nextId);
177
+ } else {
178
+ selectedDocumentId.value = "";
179
+ selectedDocument.value = undefined;
180
+ detailRequestToken.value += 1;
181
+ }
182
+ } finally {
183
+ loading.value = false;
184
+ }
185
+ }
186
+
187
+ /** 选择项目文档并加载 Markdown 详情。 */
188
+ async function selectDocument(id: string, anchor = "") {
189
+ if (!id) return;
190
+ selectedDocumentId.value = id;
191
+ detailLoading.value = true;
192
+ const requestToken = detailRequestToken.value + 1;
193
+ detailRequestToken.value = requestToken;
194
+ try {
195
+ const detail = await defProjectDocumentService.GetProjectDocument({ id });
196
+ if (detailRequestToken.value === requestToken && selectedDocumentId.value === id) {
197
+ selectedDocument.value = detail;
198
+ await nextTick();
199
+ documentTreeRef.value?.setCurrentKey(buildDocumentNodeKey(id));
200
+ scrollToAnchor(anchor);
201
+ }
202
+ } finally {
203
+ if (detailRequestToken.value === requestToken) {
204
+ detailLoading.value = false;
205
+ }
206
+ }
207
+ }
208
+
209
+ /** 处理项目文档树节点选择。 */
210
+ function handleTreeNodeClick(node: ProjectDocumentTreeNode) {
211
+ if (!node.document) return;
212
+ void selectDocument(node.document.id);
213
+ }
214
+
215
+ /** 按项目、目录或路径过滤项目文档树。 */
216
+ function filterTreeNode(value: unknown, data: TreeNodeData) {
217
+ const node = data as ProjectDocumentTreeNode;
218
+ const search = String(value ?? "")
219
+ .trim()
220
+ .toLocaleLowerCase();
221
+ if (!search) return true;
222
+ return [node.label, node.projectKey, node.projectName, node.path].some(field => field.toLocaleLowerCase().includes(search));
223
+ }
224
+
225
+ /** 处理 Markdown 中的页内锚点、相对文档和外部链接。 */
226
+ function handleMarkdownClick(event: MouseEvent) {
227
+ const target = event.target;
228
+ if (!(target instanceof Element)) return;
229
+ const anchor = target.closest("a");
230
+ const href = anchor?.getAttribute("href");
231
+ if (!anchor || !href || !selectedDocument.value) return;
232
+ if (href.startsWith("#")) {
233
+ event.preventDefault();
234
+ scrollToAnchor(href.slice(1));
235
+ return;
236
+ }
237
+ if (/^(?:[a-z][a-z\d+.-]*:|\/\/)/i.test(href)) {
238
+ event.preventDefault();
239
+ window.open(href, "_blank", "noopener,noreferrer");
240
+ return;
241
+ }
242
+
243
+ event.preventDefault();
244
+ const [rawPath, rawAnchor = ""] = href.split("#", 2);
245
+ const linkPath = decodeURIComponent(rawPath.split("?", 1)[0] ?? "");
246
+ const documentPath = resolveDocumentPath(selectedDocument.value.path, linkPath);
247
+ const linkedDocument = documentPathIndex.value.get(`${selectedDocument.value.project_key}\0${documentPath}`);
248
+ if (!linkedDocument) {
249
+ ElMessage.warning(`未收集引用文档:${documentPath}`);
250
+ return;
251
+ }
252
+ void selectDocument(linkedDocument.id, decodeURIComponent(rawAnchor));
253
+ }
254
+
255
+ /** 基于当前文档目录解析项目内相对路径。 */
256
+ function resolveDocumentPath(currentPath: string, linkPath: string) {
257
+ const baseSegments = linkPath.startsWith("/") ? [] : currentPath.split("/").slice(0, -1);
258
+ for (const segment of linkPath.split("/")) {
259
+ if (!segment || segment === ".") continue;
260
+ if (segment === "..") {
261
+ baseSegments.pop();
262
+ continue;
263
+ }
264
+ baseSegments.push(segment);
265
+ }
266
+ return baseSegments.join("/");
267
+ }
268
+
269
+ /** 在当前 Markdown 阅读区滚动到指定标题锚点。 */
270
+ function scrollToAnchor(anchor: string) {
271
+ if (!anchor) {
272
+ readerScrollRef.value?.scrollTo({ top: 0 });
273
+ return;
274
+ }
275
+ const decodedAnchor = decodeURIComponent(anchor);
276
+ const heading = markdownRef.value?.querySelector<HTMLElement>(`#${CSS.escape(decodedAnchor)}`);
277
+ heading?.scrollIntoView({ block: "start" });
278
+ }
279
+
280
+ /** 将 RFC3339 更新时间格式化为紧凑的本地时间。 */
281
+ function formatDocumentUpdatedAt(value: string) {
282
+ const date = new Date(value);
283
+ if (Number.isNaN(date.getTime())) return value;
284
+ return documentUpdatedAtFormatter.format(date).replaceAll("/", "-");
285
+ }
286
+
287
+ /** 将接口项目节点转换为管理端树节点。 */
288
+ function buildProjectTreeNode(project: ProjectDocumentProject): ProjectDocumentTreeNode {
289
+ return {
290
+ key: `project:${project.key}`,
291
+ label: project.name,
292
+ kind: "project",
293
+ projectKey: project.key,
294
+ projectName: project.name,
295
+ path: "",
296
+ children: [
297
+ ...(project.documents ?? []).map(document => buildDocumentTreeNode(document, project.key, project.name)),
298
+ ...(project.directories ?? []).map(directory => buildDirectoryTreeNode(directory, project.key, project.name))
299
+ ]
300
+ };
301
+ }
302
+
303
+ /** 递归转换接口目录节点。 */
304
+ function buildDirectoryTreeNode(
305
+ directory: ProjectDocumentDirectory,
306
+ projectKey: string,
307
+ projectName: string
308
+ ): ProjectDocumentTreeNode {
309
+ return {
310
+ key: `directory:${projectKey}:${directory.path}`,
311
+ label: directory.name,
312
+ kind: "directory",
313
+ projectKey,
314
+ projectName,
315
+ path: directory.path,
316
+ children: [
317
+ ...(directory.documents ?? []).map(document => buildDocumentTreeNode(document, projectKey, projectName)),
318
+ ...(directory.directories ?? []).map(child => buildDirectoryTreeNode(child, projectKey, projectName))
319
+ ]
320
+ };
321
+ }
322
+
323
+ /** 将接口文档目录项转换为树叶子节点。 */
324
+ function buildDocumentTreeNode(
325
+ document: ProjectDocumentListItem,
326
+ projectKey: string,
327
+ projectName: string
328
+ ): ProjectDocumentTreeNode {
329
+ return {
330
+ key: buildDocumentNodeKey(document.id),
331
+ label: document.path.split("/").at(-1) ?? document.path,
332
+ kind: "document",
333
+ projectKey,
334
+ projectName,
335
+ path: document.path,
336
+ document,
337
+ children: []
338
+ };
339
+ }
340
+
341
+ /** 构造文档树叶子节点稳定标识。 */
342
+ function buildDocumentNodeKey(id: string) {
343
+ return `document:${id}`;
344
+ }
345
+
346
+ /** 将树中的文档叶子节点展开为导航节点。 */
347
+ function flattenDocumentTree(nodes: ProjectDocumentTreeNode[]): ProjectDocumentTreeNode[] {
348
+ const documents: ProjectDocumentTreeNode[] = [];
349
+ for (const node of nodes) {
350
+ if (node.document) {
351
+ documents.push(node);
352
+ }
353
+ documents.push(...flattenDocumentTree(node.children));
354
+ }
355
+ return documents;
356
+ }
357
+
358
+ watch(keyword, value => {
359
+ documentTreeRef.value?.filter(value);
360
+ });
361
+
362
+ onMounted(() => {
363
+ void loadDocuments();
364
+ });
365
+ </script>
366
+
367
+ <style scoped lang="scss">
368
+ .project-doc-page {
369
+ box-sizing: border-box;
370
+ color: var(--admin-page-text-primary);
371
+ background: var(--el-bg-color-page);
372
+ }
373
+
374
+ .project-doc-shell {
375
+ display: grid;
376
+ flex: 1;
377
+ grid-template-columns: 340px minmax(0, 1fr);
378
+ min-width: 0;
379
+ min-height: 520px;
380
+ overflow: hidden;
381
+ background: var(--admin-page-card-bg);
382
+ border: 1px solid var(--admin-page-card-border);
383
+ border-radius: var(--admin-page-radius);
384
+ box-shadow: var(--admin-page-shadow);
385
+ }
386
+
387
+ .document-navigation,
388
+ .document-reader {
389
+ display: flex;
390
+ min-width: 0;
391
+ min-height: 0;
392
+ flex-direction: column;
393
+ overflow: hidden;
394
+ }
395
+
396
+ .document-navigation {
397
+ border-right: 1px solid var(--admin-page-divider);
398
+ }
399
+
400
+ .navigation-header {
401
+ display: flex;
402
+ align-items: center;
403
+ gap: 12px;
404
+ padding: 16px;
405
+ border-bottom: 1px solid var(--admin-page-divider);
406
+ }
407
+
408
+ .document-count {
409
+ flex: 0 0 auto;
410
+ font-size: 12px;
411
+ color: var(--admin-page-text-secondary);
412
+ white-space: nowrap;
413
+ }
414
+
415
+ .document-tree-scroll {
416
+ flex: 1;
417
+ min-height: 0;
418
+ padding: 8px;
419
+ overflow-y: auto;
420
+ }
421
+
422
+ .document-tree {
423
+ min-width: 100%;
424
+ color: var(--admin-page-text-primary);
425
+ background: transparent;
426
+ --el-tree-node-hover-bg-color: var(--el-fill-color-light);
427
+ }
428
+
429
+ .document-tree :deep(.el-tree-node__content) {
430
+ height: 34px;
431
+ padding-right: 8px;
432
+ border-radius: 4px;
433
+ }
434
+
435
+ .document-tree :deep(.el-tree-node.is-current > .el-tree-node__content) {
436
+ color: var(--el-color-primary);
437
+ background: var(--admin-page-accent-soft-bg);
438
+ box-shadow: inset 3px 0 0 var(--el-color-primary);
439
+ }
440
+
441
+ .document-tree-node {
442
+ display: flex;
443
+ flex: 1;
444
+ min-width: 0;
445
+ align-items: center;
446
+ gap: 7px;
447
+ overflow: hidden;
448
+ }
449
+
450
+ .document-tree-node__icon {
451
+ flex: 0 0 auto;
452
+ font-size: 15px;
453
+ color: var(--admin-page-text-secondary);
454
+ }
455
+
456
+ .document-tree-node__label {
457
+ min-width: 0;
458
+ overflow: hidden;
459
+ text-overflow: ellipsis;
460
+ white-space: nowrap;
461
+ }
462
+
463
+ .document-tree-node.is-project .document-tree-node__label {
464
+ font-weight: 650;
465
+ }
466
+
467
+ .document-tree-node.is-directory .document-tree-node__label {
468
+ font-weight: 550;
469
+ }
470
+
471
+ .document-tree-node code,
472
+ .document-tree-node__updated-at {
473
+ flex: 0 0 auto;
474
+ margin-left: auto;
475
+ font-size: 11px;
476
+ color: var(--admin-page-text-secondary);
477
+ }
478
+
479
+ .document-tree-node__updated-at {
480
+ font-variant-numeric: tabular-nums;
481
+ white-space: nowrap;
482
+ }
483
+
484
+ .reader-scroll {
485
+ flex: 1;
486
+ min-height: 0;
487
+ padding: 24px;
488
+ overflow-y: auto;
489
+ }
490
+
491
+ .project-markdown {
492
+ width: 100%;
493
+ max-width: 100%;
494
+ overflow-wrap: anywhere;
495
+ }
496
+
497
+ .project-markdown :deep(.x-md-core > :first-child) {
498
+ margin-top: 0;
499
+ }
500
+
501
+ .project-markdown :deep(.x-md-core > :last-child) {
502
+ margin-bottom: 0;
503
+ }
504
+
505
+ .project-markdown :deep(h1),
506
+ .project-markdown :deep(h2),
507
+ .project-markdown :deep(h3),
508
+ .project-markdown :deep(h4),
509
+ .project-markdown :deep(h5),
510
+ .project-markdown :deep(h6) {
511
+ color: var(--admin-page-text-primary);
512
+ scroll-margin-top: 16px;
513
+ }
514
+
515
+ .project-markdown :deep(a) {
516
+ color: var(--el-color-primary);
517
+ }
518
+
519
+ .project-markdown :deep(blockquote) {
520
+ border-left-color: var(--el-border-color);
521
+ }
522
+
523
+ .project-markdown :deep(table) {
524
+ display: block;
525
+ max-width: 100%;
526
+ overflow-x: auto;
527
+ }
528
+
529
+ .reader-loading {
530
+ padding: 24px;
531
+ }
532
+
533
+ @media (max-width: 900px) {
534
+ .project-doc-shell {
535
+ grid-template-columns: 280px minmax(0, 1fr);
536
+ }
537
+ }
538
+
539
+ @media (max-width: 720px) {
540
+ .project-doc-shell {
541
+ display: flex;
542
+ flex-direction: column;
543
+ }
544
+
545
+ .document-navigation {
546
+ height: 320px;
547
+ flex: 0 0 auto;
548
+ border-right: 0;
549
+ border-bottom: 1px solid var(--admin-page-divider);
550
+ }
551
+
552
+ .document-reader {
553
+ min-height: 520px;
554
+ }
555
+
556
+ .reader-scroll {
557
+ padding-right: 16px;
558
+ padding-left: 16px;
559
+ }
560
+ }
561
+ </style>
package/package.json ADDED
@@ -0,0 +1,60 @@
1
+ {
2
+ "name": "@liujitcn/kratos-admin-system",
3
+ "private": false,
4
+ "version": "0.0.1",
5
+ "type": "module",
6
+ "description": "kratos-admin system management module",
7
+ "license": "MIT",
8
+ "homepage": "https://github.com/liujitcn/kratos-admin",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git@github.com:liujitcn/kratos-admin.git"
12
+ },
13
+ "dependencies": {
14
+ "@microsoft/fetch-event-source": "^2.0.1",
15
+ "@shikijs/core": "^3.23.0",
16
+ "sortablejs": "^1.15.2",
17
+ "swagger-ui-dist": "^5.32.9",
18
+ "vue-element-plus-x": "^2.0.3",
19
+ "x-markdown-vue": "^0.0.200",
20
+ "@liujitcn/kratos-admin-core": "0.0.1"
21
+ },
22
+ "peerDependencies": {
23
+ "@element-plus/icons-vue": "^2.3.1",
24
+ "@vueuse/core": "^14.3.0",
25
+ "element-plus": "^2.7.6",
26
+ "vue": "^3.5.35",
27
+ "vue-router": "^5.0.7"
28
+ },
29
+ "engines": {
30
+ "node": "^20.19.0 || >=22.12.0"
31
+ },
32
+ "exports": {
33
+ ".": {
34
+ "types": "./dist/package/declarations/index.d.ts",
35
+ "default": "./dist/package/src/index.ts"
36
+ },
37
+ "./api/*": {
38
+ "types": "./dist/package/declarations/src/api/*.d.ts",
39
+ "default": "./dist/package/src/api/*.ts"
40
+ },
41
+ "./rpc/*": {
42
+ "types": "./dist/package/declarations/src/rpc/*.d.ts",
43
+ "default": "./dist/package/src/rpc/*.ts"
44
+ },
45
+ "./package.json": "./package.json"
46
+ },
47
+ "files": [
48
+ "dist/package",
49
+ "package.json",
50
+ "tsconfig.json"
51
+ ],
52
+ "publishConfig": {
53
+ "access": "public"
54
+ },
55
+ "scripts": {
56
+ "build": "pnpm build:package",
57
+ "build:package": "node ../../../scripts/build-package.mjs .",
58
+ "type:check": "vue-tsc --noEmit --skipLibCheck"
59
+ }
60
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,13 @@
1
+ {
2
+ "extends": "../../../tsconfig.json",
3
+ "include": [
4
+ "../../../packages/core/types/generated/auto-imports.d.ts",
5
+ "../../../packages/core/types/generated/components.d.ts",
6
+ "../../../packages/core/src/typings/*.d.ts",
7
+ "src/**/*.ts",
8
+ "src/**/*.d.ts",
9
+ "src/**/*.tsx",
10
+ "src/**/*.vue"
11
+ ],
12
+ "exclude": ["node_modules", "dist", "**/*.js"]
13
+ }