@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,703 @@
1
+ <!-- 代码生成 Proto 能力配置 -->
2
+ <template>
3
+ <div v-loading="loading" class="app-container code-gen-sub-page">
4
+ <el-card class="code-gen-sub-card" shadow="never">
5
+ <template v-if="formData.id">
6
+ <div class="code-gen-toolbar">
7
+ <!-- 展示当前 Proto 配置对应的业务表。 -->
8
+ <div class="code-gen-proto-toolbar__meta">
9
+ <span class="code-gen-proto-toolbar__table-name" :title="formData.name">表名:{{ formData.name }}</span>
10
+ <span class="code-gen-proto-toolbar__table-comment" :title="formData.comment || '--'">
11
+ 表注释:{{ formData.comment || "--" }}
12
+ </span>
13
+ </div>
14
+ <el-button type="primary" :icon="Document" :disabled="!canEdit" @click="handleSaveProtoMethods()">保存</el-button>
15
+ </div>
16
+
17
+ <ProTable
18
+ row-key="sort"
19
+ :data="protoChecks"
20
+ :columns="protoColumns"
21
+ :pagination="false"
22
+ :tool-button="false"
23
+ >
24
+ <template #exists="{ row }">
25
+ <div class="code-gen-proto-status">
26
+ <el-tag :type="row.exists ? 'success' : 'warning'">{{ row.exists ? "已存在" : "缺失" }}</el-tag>
27
+ <span class="code-gen-proto-cell__secondary" :title="row.message">{{ row.message }}</span>
28
+ </div>
29
+ </template>
30
+ <template #proto_info="{ row }">
31
+ <el-popover trigger="hover" placement="top-start" :width="720" :show-after="150">
32
+ <template #reference>
33
+ <div class="code-gen-proto-capability-trigger">
34
+ <span class="code-gen-proto-capability-trigger__comment" :title="row.method_comment || '--'">
35
+ {{ row.method_comment || "--" }}
36
+ </span>
37
+ </div>
38
+ </template>
39
+ <div class="code-gen-proto-capability-popover">
40
+ <div class="code-gen-proto-capability-popover__item">
41
+ <span>方法描述</span>
42
+ <span class="code-gen-proto-capability-popover__value">{{ row.method_comment || "--" }}</span>
43
+ </div>
44
+ <div class="code-gen-proto-capability-popover__item">
45
+ <span>方法名</span>
46
+ <code>{{ row.method_name || "--" }}</code>
47
+ </div>
48
+ <div class="code-gen-proto-capability-popover__item">
49
+ <span>Proto路径</span>
50
+ <code class="code-gen-proto-capability-popover__path">{{ row.proto_file_path || "--" }}</code>
51
+ </div>
52
+ <div class="code-gen-proto-capability-popover__item">
53
+ <span>服务描述</span>
54
+ <span class="code-gen-proto-capability-popover__value">{{ row.service_comment || "--" }}</span>
55
+ </div>
56
+ <div class="code-gen-proto-capability-popover__item">
57
+ <span>服务名</span>
58
+ <code>{{ row.service_name || "--" }}</code>
59
+ </div>
60
+ <pre class="code-gen-proto-capability-popover__preview"><code>{{ resolveProtoDefinition(row) }}</code></pre>
61
+ </div>
62
+ </el-popover>
63
+ </template>
64
+ <template #generate_when_missing="{ row }">
65
+ <div class="code-gen-proto-generate">
66
+ <el-checkbox v-model="row.generate_when_missing" :disabled="row.exists || !canEdit">生成接口</el-checkbox>
67
+ <el-button
68
+ v-if="showProtoConfigButton(row)"
69
+ type="primary"
70
+ size="small"
71
+ link
72
+ :icon="Setting"
73
+ :disabled="!canEdit"
74
+ @click="openProtoConfigDialog(row)"
75
+ >
76
+ 配置
77
+ </el-button>
78
+ </div>
79
+ </template>
80
+ </ProTable>
81
+ </template>
82
+ <el-empty v-else description="请先选择生成记录" />
83
+ </el-card>
84
+
85
+ <ProDialog
86
+ v-model="configDialog.visible"
87
+ :title="`${configDialog.methodName} - ${resolveAPIKindLabel(configDialog.apiKind)}配置`"
88
+ width="min(520px, calc(100vw - 32px))"
89
+ destroy-on-close
90
+ :show-close="false"
91
+ :close-on-click-modal="false"
92
+ :close-on-press-escape="false"
93
+ :show-footer="false"
94
+ @closed="handleProtoConfigDialogClosed"
95
+ >
96
+ <template #header="{ titleId, titleClass }">
97
+ <div class="code-gen-config-dialog__header">
98
+ <span :id="titleId" :class="titleClass">
99
+ {{ `${configDialog.methodName} - ${resolveAPIKindLabel(configDialog.apiKind)}配置` }}
100
+ </span>
101
+ <el-button
102
+ type="primary"
103
+ :icon="Document"
104
+ :disabled="!canEdit"
105
+ aria-label="保存并关闭"
106
+ @click="handleSaveProtoConfigDialog"
107
+ >
108
+ 保存
109
+ </el-button>
110
+ </div>
111
+ </template>
112
+
113
+ <ProForm
114
+ :model="protoConfigFormModel"
115
+ :fields="protoConfigFields"
116
+ label-position="top"
117
+ class="code-gen-proto-config-form"
118
+ />
119
+ </ProDialog>
120
+ </div>
121
+ </template>
122
+
123
+ <script setup lang="ts">
124
+ import { computed, onMounted, reactive, ref, watch } from "vue";
125
+ import { Document, Setting } from "@element-plus/icons-vue";
126
+ import { useRoute, useRouter } from "vue-router";
127
+ import ProDialog from "@liujitcn/kratos-admin-core/components/Dialog/ProDialog.vue";
128
+ import ProForm from "@liujitcn/kratos-admin-core/components/ProForm/index.vue";
129
+ import type { ProFormField, ProFormOption } from "@liujitcn/kratos-admin-core/components/ProForm/interface";
130
+ import type { ColumnProps } from "@liujitcn/kratos-admin-core/components/ProTable/interface";
131
+ import ProTable from "@liujitcn/kratos-admin-core/components/ProTable";
132
+ import { useAuthButtons } from "@liujitcn/kratos-admin-core/auth";
133
+ import { useTabsStore } from "@liujitcn/kratos-admin-core/stores/runtime";
134
+ import { defCodeGenColumnService } from "@liujitcn/kratos-admin-system/api/system/code_gen_column";
135
+ import { defCodeGenProtoService } from "@liujitcn/kratos-admin-system/api/system/code_gen_proto";
136
+ import { defCodeGenTableService } from "@liujitcn/kratos-admin-system/api/system/code_gen_table";
137
+ import type { CodeGenProto, CodeGenProtoCheck, CodeGenProtoConfig } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/code_gen_proto";
138
+ import type { CodeGenDatabaseTable, CodeGenTableForm } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/code_gen_table";
139
+ import { createDefaultCodeGenTableForm } from "../config";
140
+
141
+ defineOptions({
142
+ name: "CodeGenProto",
143
+ inheritAttrs: false
144
+ });
145
+
146
+ const route = useRoute();
147
+ const router = useRouter();
148
+ const tabsStore = useTabsStore();
149
+ const { BUTTONS } = useAuthButtons();
150
+
151
+ const loading = ref(false);
152
+ const protoChecks = ref<CodeGenProtoCheck[]>([]);
153
+ const databaseTables = ref<CodeGenDatabaseTable[]>([]);
154
+ const targetColumnOptions = reactive<Record<string, ProFormOption[]>>({});
155
+ const loadingTargetColumns = reactive(new Set<string>());
156
+ const formData = reactive<CodeGenTableForm>(createDefaultCodeGenTableForm());
157
+
158
+ const triggerTypeLabels: Record<string, string> = {
159
+ crud: "基础能力",
160
+ page_tree: "树形页面",
161
+ left_tree: "左树数据",
162
+ entity_option: "实体选项",
163
+ field_option: "字段选项",
164
+ field_status: "字段状态"
165
+ };
166
+
167
+ const apiKindLabels: Record<string, string> = {
168
+ crud: "增删改查",
169
+ list: "分页列表",
170
+ option: "选项",
171
+ tree: "树形",
172
+ status: "状态"
173
+ };
174
+
175
+ /** Proto 类型配置弹窗上下文。 */
176
+ interface CodeGenProtoConfigDialog {
177
+ visible: boolean;
178
+ row: CodeGenProtoCheck | undefined;
179
+ methodName: string;
180
+ apiKind: string;
181
+ config: CodeGenProtoConfig;
182
+ }
183
+
184
+ /** Proto 配置中引用数据库字段的键。 */
185
+ type CodeGenProtoColumnKey = "parent_column" | "label_column" | "value_column" | "status_column";
186
+
187
+ const configDialog = reactive<CodeGenProtoConfigDialog>({
188
+ visible: false,
189
+ row: undefined,
190
+ methodName: "",
191
+ apiKind: "",
192
+ config: createDefaultCodeGenProtoConfig()
193
+ });
194
+
195
+ /** Proto 检查结果表格列配置。 */
196
+ const protoColumns: ColumnProps[] = [
197
+ { prop: "trigger_type", label: "触发来源", minWidth: 150, render: scope => resolveTriggerTypeLabel(String(scope.row.trigger_type)) },
198
+ { prop: "api_kind", label: "接口类型", minWidth: 150, render: scope => resolveAPIKindLabel(String(scope.row.api_kind)) },
199
+ { prop: "proto_info", label: "接口能力", minWidth: 290 },
200
+ { prop: "exists", label: "状态", minWidth: 210 },
201
+ { prop: "generate_when_missing", label: "生成设置", minWidth: 230 }
202
+ ];
203
+
204
+ /** 将 Proto 配置对象适配为 ProForm 所需的通用表单模型。 */
205
+ const protoConfigFormModel = computed<Record<string, any>>(() => configDialog.config as Record<string, any>);
206
+
207
+ /** Proto 配置弹窗的动态表单字段。 */
208
+ const protoConfigFields = computed<ProFormField[]>(() => [
209
+ {
210
+ prop: "parent_column",
211
+ label: "父节点字段",
212
+ component: "select",
213
+ options: () => configColumnOptions.value,
214
+ props: () => ({ loading: configDialogLoading.value, filterable: true, clearable: true, placeholder: "请选择父节点字段" }),
215
+ visible: () => configDialog.apiKind === "tree"
216
+ },
217
+ {
218
+ prop: "label_column",
219
+ label: "显示字段",
220
+ component: "select",
221
+ options: () => configColumnOptions.value,
222
+ props: () => ({ loading: configDialogLoading.value, filterable: true, clearable: true, placeholder: "请选择显示字段" }),
223
+ visible: () => ["option", "tree"].includes(configDialog.apiKind)
224
+ },
225
+ {
226
+ prop: "value_column",
227
+ label: "值字段",
228
+ component: "select",
229
+ options: () => configColumnOptions.value,
230
+ props: () => ({ loading: configDialogLoading.value, filterable: true, clearable: true, placeholder: "请选择值字段" }),
231
+ visible: () => ["option", "tree"].includes(configDialog.apiKind)
232
+ },
233
+ {
234
+ prop: "lazy",
235
+ label: "加载方式",
236
+ component: "checkbox",
237
+ checkboxLabel: "懒加载子节点",
238
+ props: () => ({ disabled: configDialog.apiKind !== "tree" }),
239
+ visible: () => configDialog.apiKind === "tree"
240
+ },
241
+ {
242
+ prop: "status_column",
243
+ label: "状态字段",
244
+ component: "select",
245
+ options: () => configColumnOptions.value,
246
+ props: () => ({ loading: configDialogLoading.value, filterable: true, clearable: true, placeholder: "请选择状态字段" }),
247
+ visible: () => configDialog.apiKind === "status"
248
+ }
249
+ ]);
250
+
251
+ /** 当前生成对象 ID。 */
252
+ const tableId = computed(() => {
253
+ const value = route.params.tableId ?? route.query.tableId;
254
+ const id = Number(Array.isArray(value) ? value[0] : value);
255
+ return Number.isFinite(id) && id > 0 ? id : 0;
256
+ });
257
+
258
+ /** 是否可以维护 Proto 配置。 */
259
+ const canEdit = computed(() => !!BUTTONS.value["tool:code-gen-table:proto"]);
260
+
261
+ /** 当前配置弹窗可选的数据库字段。 */
262
+ const configColumnOptions = computed(() =>
263
+ configDialog.row ? resolveColumnNameOptions(configDialog.row) : ([] as ProFormOption[])
264
+ );
265
+
266
+ /** 当前配置弹窗是否正在加载目标表字段。 */
267
+ const configDialogLoading = computed(() => {
268
+ const tableName = configDialog.row ? resolveTargetTableName(configDialog.row) : "";
269
+ return !!tableName && loadingTargetColumns.has(tableName);
270
+ });
271
+
272
+ // 路由生成对象变化时重新加载 Proto 配置。
273
+ watch(tableId, () => {
274
+ void handleQuery();
275
+ });
276
+
277
+ /**
278
+ * 查询生成对象字段与 Proto 配置。
279
+ */
280
+ async function handleQuery() {
281
+ loading.value = true;
282
+ try {
283
+ Object.assign(formData, createDefaultCodeGenTableForm());
284
+ protoChecks.value = [];
285
+ databaseTables.value = [];
286
+ Object.keys(targetColumnOptions).forEach(key => delete targetColumnOptions[key]);
287
+ if (!tableId.value) return;
288
+ const [table, tableResponse] = await Promise.all([
289
+ defCodeGenTableService.GetCodeGenTable({ id: tableId.value }),
290
+ defCodeGenTableService.ListCodeGenDatabaseTable({})
291
+ ]);
292
+ Object.assign(formData, table);
293
+ databaseTables.value = tableResponse.tables ?? [];
294
+ const columnResponse = await defCodeGenColumnService.ListCodeGenDatabaseColumn({ table_name: formData.name });
295
+ targetColumnOptions[formData.name] = createColumnOptions(columnResponse.columns ?? []);
296
+ await loadProtoChecks();
297
+ syncWorkspaceTitle();
298
+ } finally {
299
+ loading.value = false;
300
+ }
301
+ }
302
+
303
+ /**
304
+ * 同步当前页签和浏览器标题。
305
+ */
306
+ function syncWorkspaceTitle() {
307
+ const tableTitle = formData.comment || formData.name;
308
+ const title = tableTitle ? `${tableTitle} Proto 能力` : "Proto 能力";
309
+ tabsStore.setTabsTitle(title);
310
+ document.title = `${title} - ${import.meta.env.VITE_GLOB_APP_TITLE}`;
311
+ }
312
+
313
+ /**
314
+ * 自动检查当前生成对象需要的 Proto 能力。
315
+ */
316
+ async function loadProtoChecks() {
317
+ if (!formData.id) return;
318
+ const data = await defCodeGenProtoService.ListCodeGenProto({ table_id: formData.id });
319
+ protoChecks.value = (data.code_gen_protos ?? []).map(item => ({
320
+ ...item,
321
+ config: normalizeCodeGenProtoConfig(item.config)
322
+ }));
323
+ const targetTableNames = new Set(protoChecks.value.map(resolveTargetTableName).filter(Boolean));
324
+ await Promise.all(Array.from(targetTableNames, loadTargetColumnOptions));
325
+ }
326
+
327
+ /** 根据检查项目标实体返回真实数据库表名。 */
328
+ function resolveTargetTableName(row: CodeGenProtoCheck) {
329
+ if (row.target_entity_name === toPascalCase(formData.name)) return formData.name;
330
+ return databaseTables.value.find(item => toPascalCase(item.name) === row.target_entity_name)?.name ?? "";
331
+ }
332
+
333
+ /** 返回检查项目标表对应的字段选项。 */
334
+ function resolveColumnNameOptions(row: CodeGenProtoCheck) {
335
+ return targetColumnOptions[resolveTargetTableName(row)] ?? [];
336
+ }
337
+
338
+ /** 返回触发来源的展示文案。 */
339
+ function resolveTriggerTypeLabel(triggerType: string) {
340
+ return triggerTypeLabels[triggerType] ?? triggerType;
341
+ }
342
+
343
+ /** 返回接口类型的展示文案。 */
344
+ function resolveAPIKindLabel(apiKind: string) {
345
+ return apiKindLabels[apiKind] ?? apiKind;
346
+ }
347
+
348
+ /** 返回生成 RPC 的请求与响应类型签名。 */
349
+ function resolveProtoRPCSignature(row: CodeGenProtoCheck) {
350
+ const methodName = row.method_name || "--";
351
+ const entity = row.target_entity_name || toPascalCase(formData.name);
352
+ let responseType = "google.protobuf.Empty";
353
+ switch (row.api_kind) {
354
+ case "list":
355
+ case "tree":
356
+ responseType = row.api_kind === "tree" && ["entity_option", "field_option", "left_tree"].includes(row.trigger_type)
357
+ ? ".common.v1.TreeOptionResponse"
358
+ : `${methodName}Response`;
359
+ break;
360
+ case "option":
361
+ responseType = ".common.v1.SelectOptionResponse";
362
+ break;
363
+ case "crud":
364
+ responseType = methodName === `Get${entity}` ? `${entity}Form` : "google.protobuf.Empty";
365
+ break;
366
+ }
367
+ return `rpc ${methodName}(${methodName}Request) returns (${responseType})`;
368
+ }
369
+
370
+ /** 返回准备生成的 Proto 服务和 RPC 片段。 */
371
+ function resolveProtoDefinition(row: CodeGenProtoCheck) {
372
+ const serviceName = row.service_name || "--";
373
+ return [
374
+ `// ${row.service_comment || "--"}`,
375
+ `service ${serviceName} {`,
376
+ ` // ${row.method_comment || "--"}`,
377
+ ` ${resolveProtoRPCSignature(row)}`,
378
+ "}"
379
+ ].join("\n");
380
+ }
381
+
382
+ /** 判断接口类型是否需要额外配置。 */
383
+ function needsProtoConfig(apiKind: string) {
384
+ return ["option", "tree", "status"].includes(apiKind);
385
+ }
386
+
387
+ /** 仅在勾选生成且类型需要配置时展示配置入口。 */
388
+ function showProtoConfigButton(row: CodeGenProtoCheck) {
389
+ return !row.exists && row.generate_when_missing && needsProtoConfig(row.api_kind);
390
+ }
391
+
392
+ /** 创建完整的 Proto 类型配置默认值。 */
393
+ function createDefaultCodeGenProtoConfig(): CodeGenProtoConfig {
394
+ return {
395
+ parent_column: "",
396
+ label_column: "",
397
+ value_column: "",
398
+ status_column: "",
399
+ lazy: false
400
+ };
401
+ }
402
+
403
+ /** 将接口返回的可选配置补齐为前端编辑模型。 */
404
+ function normalizeCodeGenProtoConfig(config: CodeGenProtoConfig | undefined) {
405
+ return { ...createDefaultCodeGenProtoConfig(), ...(config ?? {}) };
406
+ }
407
+
408
+ /** 打开弹窗时仅为目标表存在的空配置字段填入约定默认值。 */
409
+ function applyProtoConfigDefaults(row: CodeGenProtoCheck, config: CodeGenProtoConfig) {
410
+ const availableColumns = new Set(resolveColumnNameOptions(row).map(item => String(item.value)));
411
+ const applyDefault = (key: CodeGenProtoColumnKey, value: string) => {
412
+ if (!config[key] && availableColumns.has(value)) config[key] = value;
413
+ };
414
+ // 不同接口类型只填充其生成模板固定消费的字段。
415
+ switch (row.api_kind) {
416
+ case "option":
417
+ applyDefault("label_column", "name");
418
+ applyDefault("value_column", "id");
419
+ break;
420
+ case "tree":
421
+ applyDefault("parent_column", "parent_id");
422
+ applyDefault("label_column", "name");
423
+ applyDefault("value_column", "id");
424
+ break;
425
+ case "status":
426
+ applyDefault("status_column", "status");
427
+ break;
428
+ }
429
+ }
430
+
431
+ /** 打开当前接口的类型配置弹窗。 */
432
+ function openProtoConfigDialog(row: CodeGenProtoCheck) {
433
+ const config = normalizeCodeGenProtoConfig(row.config);
434
+ applyProtoConfigDefaults(row, config);
435
+ configDialog.row = row;
436
+ configDialog.methodName = row.method_name;
437
+ configDialog.apiKind = row.api_kind;
438
+ Object.assign(configDialog.config, config);
439
+ configDialog.visible = true;
440
+ }
441
+
442
+ /** 保存 Proto 配置草稿并关闭弹窗。 */
443
+ function handleSaveProtoConfigDialog() {
444
+ if (configDialog.row) configDialog.row.config = normalizeCodeGenProtoConfig(configDialog.config);
445
+ configDialog.visible = false;
446
+ }
447
+
448
+ /** 清理 Proto 配置弹窗上下文。 */
449
+ function handleProtoConfigDialogClosed() {
450
+ configDialog.row = undefined;
451
+ configDialog.methodName = "";
452
+ configDialog.apiKind = "";
453
+ Object.assign(configDialog.config, createDefaultCodeGenProtoConfig());
454
+ }
455
+
456
+ /** 判断勾选生成的接口是否已具备完整类型配置。 */
457
+ function hasCompleteProtoConfig(row: CodeGenProtoCheck) {
458
+ const config = normalizeCodeGenProtoConfig(row.config);
459
+ // 每种接口类型检查其生成模板消费的固定字段。
460
+ switch (row.api_kind) {
461
+ case "option":
462
+ return !!config.label_column && !!config.value_column;
463
+ case "tree":
464
+ return !!config.parent_column && !!config.label_column && !!config.value_column;
465
+ case "status":
466
+ return !!config.status_column;
467
+ default:
468
+ return true;
469
+ }
470
+ }
471
+
472
+ /** 保存前定位第一个缺少必要配置的接口。 */
473
+ function validateProtoConfigs() {
474
+ const row = protoChecks.value.find(
475
+ item => !item.exists && item.generate_when_missing && needsProtoConfig(item.api_kind) && !hasCompleteProtoConfig(item)
476
+ );
477
+ if (!row) return true;
478
+ ElMessage.warning(`请先配置接口 ${row.method_name}`);
479
+ openProtoConfigDialog(row);
480
+ return false;
481
+ }
482
+
483
+ /** 加载并缓存目标数据库表字段。 */
484
+ async function loadTargetColumnOptions(tableName: string) {
485
+ if (!tableName || targetColumnOptions[tableName] || loadingTargetColumns.has(tableName)) return;
486
+ loadingTargetColumns.add(tableName);
487
+ try {
488
+ const data = await defCodeGenColumnService.ListCodeGenDatabaseColumn({ table_name: tableName });
489
+ targetColumnOptions[tableName] = createColumnOptions(data.columns ?? []);
490
+ } finally {
491
+ loadingTargetColumns.delete(tableName);
492
+ }
493
+ }
494
+
495
+ /** 将数据库字段或生成字段转换成下拉选项。 */
496
+ function createColumnOptions(columns: Array<{ name: string; comment: string }>) {
497
+ return columns
498
+ .filter(item => item.name)
499
+ .map(item => ({
500
+ label: item.comment ? `${item.name}(${item.comment})` : item.name,
501
+ value: item.name
502
+ }));
503
+ }
504
+
505
+ /**
506
+ * 保存缺失 Proto 接口的生成选择。
507
+ */
508
+ async function handleSaveProtoMethods(showMessage = true) {
509
+ if (!formData.id) return false;
510
+ if (!validateProtoConfigs()) return false;
511
+ const codeGenProtos: CodeGenProto[] = protoChecks.value.map((item, index) => ({
512
+ id: 0,
513
+ table_id: formData.id,
514
+ trigger_type: item.trigger_type,
515
+ api_kind: item.api_kind,
516
+ config: normalizeCodeGenProtoConfig(item.config),
517
+ generate_when_missing: !item.exists && item.generate_when_missing,
518
+ sort: index + 1
519
+ }));
520
+ await defCodeGenProtoService.SaveCodeGenProto({
521
+ table_id: formData.id,
522
+ code_gen_protos: codeGenProtos
523
+ });
524
+ if (showMessage) ElMessage.success("保存Proto生成选择成功");
525
+ // 路由切换前保留当前页签地址,避免误删目标页签。
526
+ const currentPath = route.fullPath;
527
+ await router.push("/code/gen/table");
528
+ await tabsStore.removeTabs(currentPath, false);
529
+ return true;
530
+ }
531
+
532
+ /** 将数据库表名转换为生成器使用的实体名。 */
533
+ function toPascalCase(value: string) {
534
+ return value
535
+ .split("_")
536
+ .filter(Boolean)
537
+ .map(part => part.charAt(0).toUpperCase() + part.slice(1))
538
+ .join("");
539
+ }
540
+
541
+ onMounted(() => {
542
+ syncWorkspaceTitle();
543
+ void handleQuery();
544
+ });
545
+ </script>
546
+
547
+ <style scoped lang="scss">
548
+ .code-gen-sub-card {
549
+ background: var(--admin-page-card-bg);
550
+ border: 1px solid var(--admin-page-card-border);
551
+ border-radius: var(--admin-page-radius);
552
+ box-shadow: var(--admin-page-shadow);
553
+ }
554
+
555
+ .code-gen-config-dialog__header {
556
+ display: flex;
557
+ gap: 12px;
558
+ align-items: center;
559
+ justify-content: space-between;
560
+ width: 100%;
561
+ }
562
+
563
+ :deep(.code-gen-toolbar) {
564
+ display: flex;
565
+ flex-wrap: wrap;
566
+ gap: 10px;
567
+ align-items: center;
568
+ justify-content: space-between;
569
+ margin-bottom: 14px;
570
+ }
571
+ .code-gen-proto-toolbar__meta {
572
+ display: flex;
573
+ flex-wrap: wrap;
574
+ gap: 8px;
575
+ min-width: 0;
576
+ color: var(--admin-page-text-secondary);
577
+ }
578
+ .code-gen-proto-toolbar__meta span {
579
+ padding: 3px 8px;
580
+ overflow: hidden;
581
+ text-overflow: ellipsis;
582
+ font-size: 12px;
583
+ line-height: 18px;
584
+ white-space: nowrap;
585
+ background: var(--admin-page-card-bg-soft);
586
+ border: 1px solid var(--admin-page-card-border-soft);
587
+ border-radius: 999px;
588
+ }
589
+ .code-gen-proto-toolbar__table-name {
590
+ max-width: 220px;
591
+ }
592
+ .code-gen-proto-toolbar__table-comment {
593
+ max-width: 280px;
594
+ }
595
+ .code-gen-proto-cell {
596
+ /* 将名称、标签和说明保持在同一行,长文本优先收缩并通过 title 保留完整内容。 */
597
+ display: flex;
598
+ gap: 6px;
599
+ align-items: center;
600
+ justify-content: center;
601
+ min-width: 0;
602
+ }
603
+ .code-gen-proto-cell__primary,
604
+ .code-gen-proto-cell__path,
605
+ .code-gen-proto-status .code-gen-proto-cell__secondary {
606
+ min-width: 0;
607
+ overflow: hidden;
608
+ text-overflow: ellipsis;
609
+ white-space: nowrap;
610
+ }
611
+ .code-gen-proto-cell__primary {
612
+ flex: 0 1 auto;
613
+ color: var(--admin-page-text-primary);
614
+ }
615
+ .code-gen-proto-cell__tags,
616
+ .code-gen-proto-status,
617
+ .code-gen-proto-generate {
618
+ display: flex;
619
+ flex-wrap: wrap;
620
+ gap: 8px;
621
+ align-items: center;
622
+ /* 多行单元格与列标题保持居中,避免文本继承居中而 Flex 子项贴左。 */
623
+ justify-content: center;
624
+ min-width: 0;
625
+ }
626
+ .code-gen-proto-cell__tags {
627
+ flex: 0 0 auto;
628
+ flex-wrap: nowrap;
629
+ }
630
+ .code-gen-proto-cell__secondary,
631
+ .code-gen-proto-cell__path {
632
+ flex: 0 1 auto;
633
+ font-size: 12px;
634
+ line-height: 18px;
635
+ color: var(--admin-page-text-secondary);
636
+ }
637
+ .code-gen-proto-status {
638
+ flex-wrap: nowrap;
639
+ }
640
+ .code-gen-proto-status .code-gen-proto-cell__secondary {
641
+ flex: 0 1 auto;
642
+ }
643
+ .code-gen-proto-capability-trigger {
644
+ display: flex;
645
+ flex-direction: column;
646
+ gap: 2px;
647
+ min-width: 0;
648
+ cursor: pointer;
649
+ text-align: left;
650
+ }
651
+ .code-gen-proto-capability-trigger__comment {
652
+ overflow: hidden;
653
+ text-overflow: ellipsis;
654
+ white-space: nowrap;
655
+ color: var(--admin-page-text-primary);
656
+ }
657
+ .code-gen-proto-capability-popover {
658
+ display: flex;
659
+ flex-direction: column;
660
+ gap: 10px;
661
+ }
662
+ .code-gen-proto-capability-popover__preview {
663
+ max-width: 100%;
664
+ margin: 0;
665
+ padding: 10px;
666
+ overflow-x: auto;
667
+ font-size: 12px;
668
+ line-height: 18px;
669
+ color: var(--admin-page-text-primary);
670
+ white-space: pre;
671
+ background: var(--admin-page-card-bg-soft);
672
+ border: 1px solid var(--admin-page-card-border-soft);
673
+ border-radius: 4px;
674
+ }
675
+ .code-gen-proto-capability-popover__item {
676
+ display: grid;
677
+ grid-template-columns: 72px minmax(0, 1fr);
678
+ gap: 10px;
679
+ align-items: start;
680
+ min-width: 0;
681
+ color: var(--admin-page-text-secondary);
682
+ }
683
+ .code-gen-proto-capability-popover__item code {
684
+ min-width: 0;
685
+ overflow-wrap: anywhere;
686
+ color: var(--admin-page-text-primary);
687
+ }
688
+ .code-gen-proto-capability-popover__item .code-gen-proto-capability-popover__path {
689
+ display: block;
690
+ max-width: 100%;
691
+ overflow-x: auto;
692
+ overflow-wrap: normal;
693
+ white-space: nowrap;
694
+ }
695
+ .code-gen-proto-capability-popover__value {
696
+ min-width: 0;
697
+ overflow-wrap: anywhere;
698
+ color: var(--admin-page-text-primary);
699
+ }
700
+ .code-gen-proto-config-form :deep(.el-select) {
701
+ width: 100%;
702
+ }
703
+ </style>