@liujitcn/kratos-taro-app-core 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 (77) hide show
  1. package/README.md +36 -0
  2. package/dist/build.mjs +38 -0
  3. package/dist/runner.mjs +321 -0
  4. package/package.json +51 -0
  5. package/src/api/base/config.ts +20 -0
  6. package/src/api/base/file.ts +57 -0
  7. package/src/api/base/login.ts +87 -0
  8. package/src/api/base/menu.ts +17 -0
  9. package/src/api/base/oauth.ts +149 -0
  10. package/src/api/system/auth.ts +54 -0
  11. package/src/api/system/base_area.ts +34 -0
  12. package/src/api/system/base_dict.ts +24 -0
  13. package/src/bootstrap.ts +32 -0
  14. package/src/build.ts +24 -0
  15. package/src/components/BootstrapStatus.scss +28 -0
  16. package/src/components/BootstrapStatus.tsx +25 -0
  17. package/src/components/KratosPageFrame.scss +41 -0
  18. package/src/components/KratosPageFrame.tsx +51 -0
  19. package/src/components/KratosTabBar.scss +34 -0
  20. package/src/components/KratosTabBar.tsx +45 -0
  21. package/src/index.ts +36 -0
  22. package/src/module.ts +63 -0
  23. package/src/navigation-pattern.d.mts +2 -0
  24. package/src/navigation-pattern.mjs +29 -0
  25. package/src/navigation-tree.d.mts +12 -0
  26. package/src/navigation-tree.mjs +45 -0
  27. package/src/navigation.ts +336 -0
  28. package/src/pages.ts +21 -0
  29. package/src/rpc/base/v1/config.ts +34 -0
  30. package/src/rpc/base/v1/file.ts +66 -0
  31. package/src/rpc/base/v1/login.ts +128 -0
  32. package/src/rpc/base/v1/mcp.ts +20 -0
  33. package/src/rpc/base/v1/oauth.ts +199 -0
  34. package/src/rpc/base/v1/sse.ts +22 -0
  35. package/src/rpc/common/v1/common.ts +71 -0
  36. package/src/rpc/common/v1/enum.ts +71 -0
  37. package/src/rpc/common/v1/types.ts +77 -0
  38. package/src/rpc/google/protobuf/empty.ts +19 -0
  39. package/src/rpc/google/protobuf/wrappers.ts +124 -0
  40. package/src/rpc/system/app/v1/auth.ts +54 -0
  41. package/src/rpc/system/app/v1/base_area.ts +24 -0
  42. package/src/rpc/system/app/v1/base_dict.ts +37 -0
  43. package/src/rpc/system/app/v1/base_menu.ts +61 -0
  44. package/src/rpc/system/common/v1/enum.ts +80 -0
  45. package/src/runner.ts +390 -0
  46. package/src/static/images/avatar.png +0 -0
  47. package/src/static/images/center_bg.png +0 -0
  48. package/src/static/images/logo_icon.png +0 -0
  49. package/src/static/images/navigator_bg.png +0 -0
  50. package/src/static/tabs/home_default.png +0 -0
  51. package/src/static/tabs/home_selected.png +0 -0
  52. package/src/static/tabs/user_default.png +0 -0
  53. package/src/static/tabs/user_selected.png +0 -0
  54. package/src/stores/index.ts +2 -0
  55. package/src/stores/setting.ts +43 -0
  56. package/src/stores/user.ts +152 -0
  57. package/src/styles/base.scss +45 -0
  58. package/src/types/assets.d.ts +9 -0
  59. package/src/utils/auth.ts +55 -0
  60. package/src/utils/file.ts +48 -0
  61. package/src/utils/http.ts +262 -0
  62. package/src/utils/index.ts +35 -0
  63. package/src/utils/navigation.ts +72 -0
  64. package/src/utils/passwordCrypto.ts +257 -0
  65. package/src/views/pages/index/index.scss +137 -0
  66. package/src/views/pages/index/index.tsx +74 -0
  67. package/src/views/pages/login/components/BehaviorCaptcha.h5.tsx +46 -0
  68. package/src/views/pages/login/components/BehaviorCaptcha.tsx +6 -0
  69. package/src/views/pages/login/components/BehaviorCaptcha.weapp.tsx +6 -0
  70. package/src/views/pages/login/components/types.ts +32 -0
  71. package/src/views/pages/login/login.scss +310 -0
  72. package/src/views/pages/login/login.tsx +493 -0
  73. package/src/views/pages/login/protocal.scss +84 -0
  74. package/src/views/pages/login/protocal.tsx +73 -0
  75. package/src/views/pages/status/index.tsx +42 -0
  76. package/src/views/pages/webview/webview.scss +43 -0
  77. package/src/views/pages/webview/webview.tsx +41 -0
@@ -0,0 +1,12 @@
1
+ export type MenuNode<T> = T & { children: Array<MenuNode<T>> }
2
+
3
+ export function buildMenuTree<T extends { id: number; parentId?: number }>(
4
+ menus: ReadonlyArray<T>,
5
+ rootId: number,
6
+ ): Array<MenuNode<T>>
7
+
8
+ export function resolveRootMenuId(
9
+ menus: ReadonlyArray<{ id: number; parentId?: number }>,
10
+ menuId: number,
11
+ rootId: number,
12
+ ): number | undefined
@@ -0,0 +1,45 @@
1
+ /**
2
+ * @template {{id: number, parentId?: number}} T
3
+ * @typedef {T & {children: MenuNode<T>[]}} MenuNode
4
+ */
5
+
6
+ /**
7
+ * 按父级编号将移动端扁平菜单构建为根目录下的树。
8
+ * @template {{id: number, parentId?: number}} T
9
+ * @param {ReadonlyArray<T>} menus
10
+ * @param {number} rootId
11
+ * @returns {MenuNode<T>[]}
12
+ */
13
+ export function buildMenuTree(menus, rootId) {
14
+ /** @type {Map<number, MenuNode<T>>} */
15
+ const nodeMap = new Map(menus.map((menu) => [menu.id, { ...menu, children: [] }]))
16
+ /** @type {MenuNode<T>[]} */
17
+ const roots = []
18
+ for (const node of nodeMap.values()) {
19
+ if (node.parentId === rootId) {
20
+ roots.push(node)
21
+ continue
22
+ }
23
+ nodeMap.get(node.parentId)?.children.push(node)
24
+ }
25
+ return roots
26
+ }
27
+
28
+ /**
29
+ * 沿父级关系查找页面所属的移动端二级菜单编号。
30
+ * @param {ReadonlyArray<{id: number, parentId?: number}>} menus
31
+ * @param {number} menuId
32
+ * @param {number} rootId
33
+ */
34
+ export function resolveRootMenuId(menus, menuId, rootId) {
35
+ const menuMap = new Map(menus.map((menu) => [menu.id, menu]))
36
+ const visited = new Set()
37
+ let currentId = menuId
38
+ while (!visited.has(currentId)) {
39
+ visited.add(currentId)
40
+ const current = menuMap.get(currentId)
41
+ if (!current) return
42
+ if (current.parentId === rootId) return current.id
43
+ currentId = current.parentId
44
+ }
45
+ }
@@ -0,0 +1,336 @@
1
+ import Taro from '@tarojs/taro'
2
+ import { create } from 'zustand'
3
+ import { defBaseMenuService } from './api/base/menu'
4
+ import { resolveStaticView } from './module'
5
+ import { matchLogicalPath, parseLogicalQuery } from './navigation-pattern.mjs'
6
+ import { buildMenuTree } from './navigation-tree.mjs'
7
+ import { hasValidToken } from './utils/auth'
8
+ import { navigateToLogin } from './utils/navigation'
9
+
10
+ /** 移动菜单访问模式。 */
11
+ export type AppMenuAccess = 'PUBLIC' | 'GUEST_ONLY' | 'AUTHENTICATED'
12
+
13
+ /** Taro 运行时使用的扁平菜单。 */
14
+ export interface AppMenu {
15
+ id: number
16
+ parentId?: number
17
+ name: string
18
+ path: string
19
+ viewKey: string
20
+ title: string
21
+ access: AppMenuAccess
22
+ inTabBar: boolean
23
+ icon?: string
24
+ selectedIcon?: string
25
+ }
26
+
27
+ /** Taro 运行时使用的树形菜单节点。 */
28
+ export interface AppMenuNode extends AppMenu {
29
+ children: AppMenuNode[]
30
+ }
31
+
32
+ /** 菜单获取适配器。 */
33
+ export interface AppNavigationAdapter {
34
+ /** 获取扁平移动菜单配置。 */
35
+ list(): Promise<unknown>
36
+ }
37
+
38
+ /** 逻辑路由解析结果。 */
39
+ export interface ResolvedAppRoute {
40
+ menu: AppMenu
41
+ physicalRoute: string
42
+ query: Record<string, string>
43
+ }
44
+
45
+ /** 导航响应式状态。 */
46
+ export interface AppNavigationState {
47
+ menus: AppMenu[]
48
+ ready: boolean
49
+ menuTree: AppMenuNode[]
50
+ tabBar: AppMenuNode[]
51
+ }
52
+
53
+ const ANONYMOUS_CACHE_KEY = 'kratos-taro-app:navigation:anonymous'
54
+ const AUTHENTICATED_CACHE_KEY = 'kratos-taro-app:navigation:authenticated'
55
+ /** 固定移动端菜单根目录编号。 */
56
+ export const APP_MENU_ROOT_ID = 999
57
+ /** 本地兜底移动菜单。 */
58
+ export const defaultAppMenus: AppMenu[] = [
59
+ {
60
+ id: 99901,
61
+ parentId: APP_MENU_ROOT_ID,
62
+ name: 'AppHome',
63
+ path: 'app/home',
64
+ viewKey: 'HOME',
65
+ title: '首页',
66
+ access: 'PUBLIC',
67
+ inTabBar: true,
68
+ icon: 'HOME_DEFAULT',
69
+ selectedIcon: 'HOME_SELECTED',
70
+ },
71
+ {
72
+ id: 99909,
73
+ parentId: APP_MENU_ROOT_ID,
74
+ name: 'AppMy',
75
+ path: 'app/my',
76
+ viewKey: 'PROFILE_HOME',
77
+ title: '我的',
78
+ access: 'PUBLIC',
79
+ inTabBar: true,
80
+ icon: 'USER_DEFAULT',
81
+ selectedIcon: 'USER_SELECTED',
82
+ },
83
+ {
84
+ id: 9990101,
85
+ parentId: 99901,
86
+ name: 'AppLogin',
87
+ path: 'app/login',
88
+ viewKey: 'LOGIN',
89
+ title: '登录',
90
+ access: 'GUEST_ONLY',
91
+ inTabBar: false,
92
+ },
93
+ {
94
+ id: 999010101,
95
+ parentId: 9990101,
96
+ name: 'AppProtocol',
97
+ path: 'app/protocol/:type',
98
+ viewKey: 'PROTOCOL',
99
+ title: '协议详情',
100
+ access: 'PUBLIC',
101
+ inTabBar: false,
102
+ },
103
+ {
104
+ id: 9990901,
105
+ parentId: 99909,
106
+ name: 'AppProfile',
107
+ path: 'app/profile',
108
+ viewKey: 'PROFILE',
109
+ title: '个人信息',
110
+ access: 'AUTHENTICATED',
111
+ inTabBar: false,
112
+ },
113
+ {
114
+ id: 9990902,
115
+ parentId: 99909,
116
+ name: 'AppSettings',
117
+ path: 'app/settings',
118
+ viewKey: 'SETTINGS',
119
+ title: '设置',
120
+ access: 'AUTHENTICATED',
121
+ inTabBar: false,
122
+ },
123
+ {
124
+ id: 9990903,
125
+ parentId: 99909,
126
+ name: 'AppAi',
127
+ path: 'app/ai',
128
+ viewKey: 'AI',
129
+ title: 'AI 助手',
130
+ access: 'AUTHENTICATED',
131
+ inTabBar: false,
132
+ },
133
+ {
134
+ id: 9990102,
135
+ parentId: 99901,
136
+ name: 'AppWebView',
137
+ path: 'app/webview',
138
+ viewKey: 'WEBVIEW',
139
+ title: '',
140
+ access: 'PUBLIC',
141
+ inTabBar: false,
142
+ },
143
+ ]
144
+
145
+ function createNavigationState(menus: AppMenu[], ready: boolean): AppNavigationState {
146
+ const menuTree = buildMenuTree(menus, APP_MENU_ROOT_ID) as AppMenuNode[]
147
+ return { menus, ready, menuTree, tabBar: menuTree.filter((menu) => menu.inTabBar) }
148
+ }
149
+
150
+ /** 应用导航 Zustand Store。 */
151
+ export const useAppNavigation = create<AppNavigationState>(() =>
152
+ createNavigationState(defaultAppMenus, false),
153
+ )
154
+
155
+ let adapter: AppNavigationAdapter = {
156
+ list: () => defBaseMenuService.ListBaseMenu(),
157
+ }
158
+
159
+ /** 替换导航远端适配器,供宿主接入自定义契约。 */
160
+ export function setAppNavigationAdapter(nextAdapter: AppNavigationAdapter): void {
161
+ adapter = nextAdapter
162
+ }
163
+
164
+ /** 初始化导航,远端失败时保留当前身份最后成功配置。 */
165
+ export async function initializeAppNavigation(): Promise<void> {
166
+ const cacheKey = resolveCacheKey()
167
+ const cached = readCachedMenus(cacheKey)
168
+ useAppNavigation.setState(createNavigationState(cached ?? defaultAppMenus, false))
169
+ try {
170
+ const nextMenus = normalizeMenuResponse(await adapter.list())
171
+ validateMenus(nextMenus)
172
+ Taro.setStorageSync(cacheKey, nextMenus)
173
+ useAppNavigation.setState(createNavigationState(nextMenus, true))
174
+ } catch (error) {
175
+ if (!cached) console.warn('navigation fallback to local defaults', error)
176
+ useAppNavigation.setState((state) => ({ ...state, ready: true }))
177
+ }
178
+ }
179
+
180
+ /** 使用已经校验的整份配置进行原子切换。 */
181
+ export function installAppNavigation(nextMenus: AppMenu[]): void {
182
+ validateMenus(nextMenus)
183
+ const snapshot = nextMenus.map((menu) => ({ ...menu }))
184
+ Taro.setStorageSync(resolveCacheKey(), snapshot)
185
+ useAppNavigation.setState(createNavigationState(snapshot, true))
186
+ }
187
+
188
+ /** 解析带路径参数和 query 的逻辑路由。 */
189
+ export function resolveAppRoute(rawRoute: string): ResolvedAppRoute | undefined {
190
+ const [rawPath, rawQuery = ''] = rawRoute.replace(/^\/+/, '').split('?', 2)
191
+ for (const menu of useAppNavigation.getState().menus) {
192
+ const params = matchLogicalPath(menu.path, rawPath)
193
+ if (!params) continue
194
+ const physicalRoute = resolveStaticView(menu.viewKey)
195
+ if (!physicalRoute) return
196
+ return {
197
+ menu,
198
+ physicalRoute,
199
+ query: { ...params, ...parseLogicalQuery(rawQuery) },
200
+ }
201
+ }
202
+ }
203
+
204
+ /** 跳转逻辑路由,并执行登录访问控制。 */
205
+ export function navigateAppRoute(
206
+ rawRoute: string,
207
+ options: { replace?: boolean } = {},
208
+ ): void {
209
+ const resolved = resolveAppRoute(rawRoute)
210
+ if (!resolved) {
211
+ launchAppStatus('NOT_FOUND')
212
+ return
213
+ }
214
+ if (resolved.menu.access === 'AUTHENTICATED' && !hasValidToken()) {
215
+ navigateToLogin(`/pages/bootstrap/index?route=${encodeURIComponent(rawRoute)}`)
216
+ return
217
+ }
218
+ if (resolved.menu.access === 'GUEST_ONLY' && hasValidToken()) {
219
+ const home = useAppNavigation.getState().menus.find((menu) => menu.viewKey === 'HOME')
220
+ if (home) navigateAppRoute(home.path, { replace: true })
221
+ return
222
+ }
223
+ const query = Object.entries(resolved.query)
224
+ .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
225
+ .join('&')
226
+ const url = `/${resolved.physicalRoute}${query ? `?${query}` : ''}`
227
+ if (options.replace || resolved.menu.inTabBar) {
228
+ void Taro.reLaunch({ url })
229
+ return
230
+ }
231
+ void Taro.navigateTo({ url, fail: () => void Taro.reLaunch({ url }) })
232
+ }
233
+
234
+ /** 打开可替换的状态视图。 */
235
+ export function launchAppStatus(
236
+ state: import('./module').BootstrapViewKey,
237
+ detail = '',
238
+ ): void {
239
+ const route = resolveStaticView(state) ?? 'pages/status/index'
240
+ const query = `state=${encodeURIComponent(state)}${detail ? `&detail=${encodeURIComponent(detail)}` : ''}`
241
+ void Taro.reLaunch({ url: `/${route}?${query}` })
242
+ }
243
+
244
+ function resolveCacheKey(): string {
245
+ return hasValidToken() ? AUTHENTICATED_CACHE_KEY : ANONYMOUS_CACHE_KEY
246
+ }
247
+
248
+ function readCachedMenus(cacheKey: string): AppMenu[] | undefined {
249
+ const cached = Taro.getStorageSync<unknown>(cacheKey)
250
+ if (!Array.isArray(cached)) return
251
+ try {
252
+ const normalized = cached.map(normalizeMenu)
253
+ validateMenus(normalized)
254
+ return normalized
255
+ } catch {
256
+ Taro.removeStorageSync(cacheKey)
257
+ }
258
+ }
259
+
260
+ function normalizeMenuResponse(response: unknown): AppMenu[] {
261
+ if (Array.isArray(response)) return response.map(normalizeMenu)
262
+ if (!response || typeof response !== 'object') throw new Error('菜单响应不是对象')
263
+ const record = response as Record<string, unknown>
264
+ const list = record.items ?? record.list ?? record.data
265
+ if (!Array.isArray(list)) throw new Error('菜单响应缺少扁平列表')
266
+ return list.map(normalizeMenu)
267
+ }
268
+
269
+ function normalizeMenu(value: unknown): AppMenu {
270
+ if (!value || typeof value !== 'object') throw new Error('菜单项不是对象')
271
+ const item = value as Record<string, unknown>
272
+ const meta = (item.meta ?? {}) as Record<string, unknown>
273
+ const app = (meta.app ?? item.app ?? {}) as Record<string, unknown>
274
+ return {
275
+ id: Number(item.id),
276
+ parentId:
277
+ item.parent_id === undefined && item.parentId === undefined
278
+ ? undefined
279
+ : Number(item.parent_id ?? item.parentId),
280
+ name: String(item.name ?? ''),
281
+ path: String(item.path ?? ''),
282
+ viewKey: String(app.view_key ?? app.viewKey ?? item.view_key ?? item.viewKey ?? ''),
283
+ title: String(meta.title ?? item.title ?? ''),
284
+ access: String(app.access ?? 'AUTHENTICATED') as AppMenuAccess,
285
+ inTabBar: Boolean(app.in_tab_bar ?? app.inTabBar),
286
+ icon: typeof meta.icon === 'string' ? meta.icon : undefined,
287
+ selectedIcon:
288
+ typeof app.selected_icon === 'string'
289
+ ? app.selected_icon
290
+ : typeof app.selectedIcon === 'string'
291
+ ? app.selectedIcon
292
+ : undefined,
293
+ }
294
+ }
295
+
296
+ function validateMenus(nextMenus: AppMenu[]): void {
297
+ const ids = new Set<number>()
298
+ const names = new Set<string>()
299
+ const paths = new Set<string>()
300
+ for (const menu of nextMenus) {
301
+ if (!Number.isSafeInteger(menu.id) || !menu.name || !menu.path.startsWith('app/')) {
302
+ throw new Error('菜单 id、name 或 app/ 路径无效')
303
+ }
304
+ if (!menu.name.startsWith('App')) throw new Error(`菜单名称必须使用 App 前缀:${menu.name}`)
305
+ if (!['PUBLIC', 'GUEST_ONLY', 'AUTHENTICATED'].includes(menu.access)) {
306
+ throw new Error(`菜单访问模式无效:${menu.access}`)
307
+ }
308
+ if (!resolveStaticView(menu.viewKey)) throw new Error(`未注册 viewKey:${menu.viewKey}`)
309
+ if (ids.has(menu.id) || names.has(menu.name) || paths.has(menu.path)) {
310
+ throw new Error('菜单 id、name、path 必须唯一')
311
+ }
312
+ ids.add(menu.id)
313
+ names.add(menu.name)
314
+ paths.add(menu.path)
315
+ }
316
+ const menuMap = new Map(nextMenus.map((menu) => [menu.id, menu]))
317
+ for (const menu of nextMenus) {
318
+ if (menu.parentId === undefined) throw new Error(`菜单缺少父级编号:${menu.name}`)
319
+ if (menu.parentId === APP_MENU_ROOT_ID) {
320
+ if (!menu.inTabBar) throw new Error(`移动端二级菜单必须作为 tab:${menu.name}`)
321
+ continue
322
+ }
323
+ if (menu.inTabBar) throw new Error(`只有移动端二级菜单可以作为 tab:${menu.name}`)
324
+ const visited = new Set<number>([menu.id])
325
+ let parentId = menu.parentId
326
+ while (parentId !== APP_MENU_ROOT_ID) {
327
+ if (visited.has(parentId)) throw new Error(`移动端菜单存在循环父级:${menu.name}`)
328
+ visited.add(parentId)
329
+ const parent = menuMap.get(parentId)
330
+ if (!parent?.parentId) throw new Error(`移动端菜单父级不存在:${menu.name}`)
331
+ parentId = parent.parentId
332
+ }
333
+ }
334
+ const tabCount = nextMenus.filter((menu) => menu.parentId === APP_MENU_ROOT_ID).length
335
+ if (tabCount === 1 || tabCount > 5) throw new Error('tabBar 只能配置 0 或 2-5 项')
336
+ }
package/src/pages.ts ADDED
@@ -0,0 +1,21 @@
1
+ import type { KratosTaroPageConfig } from './module'
2
+
3
+ /** core 页面编译配置。 */
4
+ export const corePages: Record<string, KratosTaroPageConfig> = {
5
+ 'pages/index/index': {
6
+ style: {
7
+ navigationStyle: 'custom',
8
+ navigationBarTextStyle: 'white',
9
+ navigationBarTitleText: '首页',
10
+ },
11
+ },
12
+ 'pages/login/login': { style: { navigationBarTitleText: '登录' } },
13
+ 'pages/login/protocal': { style: { navigationBarTitleText: '协议详情' } },
14
+ 'pages/webview/webview': { style: { navigationBarTitleText: '' } },
15
+ 'pages/status/index': {
16
+ style: {
17
+ navigationStyle: 'custom',
18
+ navigationBarTitleText: '',
19
+ },
20
+ },
21
+ }
@@ -0,0 +1,34 @@
1
+ // Code generated by protoc-gen-ts_proto. DO NOT EDIT.
2
+ // versions:
3
+ // protoc-gen-ts_proto v2.7.7
4
+ // protoc unknown
5
+ // source: base/v1/config.proto
6
+
7
+ /* eslint-disable */
8
+ import type { BaseConfigSite } from "../../common/v1/enum";
9
+
10
+ /** 获取系统配置条件 */
11
+ export interface GetConfigRequest {
12
+ /** 位置:枚举【BaseConfigSite】 */
13
+ site: BaseConfigSite;
14
+ }
15
+
16
+ /** 系统配置项 */
17
+ export interface ConfigItem {
18
+ /** 配置key */
19
+ key: string;
20
+ /** 配置value */
21
+ value: string;
22
+ }
23
+
24
+ /** 系统配置查询结果 */
25
+ export interface GetConfigResponse {
26
+ /** 系统配置列表 */
27
+ configs: ConfigItem[];
28
+ }
29
+
30
+ /** Base系统配置公共服务 */
31
+ export interface ConfigService {
32
+ /** 获取系统配置 */
33
+ GetConfig(request: GetConfigRequest): Promise<GetConfigResponse>;
34
+ }
@@ -0,0 +1,66 @@
1
+ // Code generated by protoc-gen-ts_proto. DO NOT EDIT.
2
+ // versions:
3
+ // protoc-gen-ts_proto v2.7.7
4
+ // protoc unknown
5
+ // source: base/v1/file.proto
6
+
7
+ /* eslint-disable */
8
+ import type { BytesValue } from "../../google/protobuf/wrappers";
9
+
10
+ /** 批量上传文件请求参数 */
11
+ export interface MultiUploadFileRequest {
12
+ /** 文件名 */
13
+ files: UploadFileInfo[];
14
+ }
15
+
16
+ /** 批量上传文件响应 */
17
+ export interface MultiUploadFileResponse {
18
+ /** 文件上传结果 */
19
+ files: FileInfo[];
20
+ }
21
+
22
+ /** 单文件上传请求参数 */
23
+ export interface UploadFileRequest {
24
+ /** 上传文件信息 */
25
+ file: UploadFileInfo | undefined;
26
+ }
27
+
28
+ /** 上传文件信息 */
29
+ export interface UploadFileInfo {
30
+ /** 文件名 */
31
+ name: string;
32
+ /** 文件扩展名 */
33
+ extname: string;
34
+ /** 文件路径 */
35
+ path: string;
36
+ /** 二进制内容将通过 base64 编码传输 */
37
+ content: Uint8Array;
38
+ }
39
+
40
+ /** 下载文件请求参数 */
41
+ export interface DownloadFileRequest {
42
+ /** 文件名 */
43
+ name: string;
44
+ /** 文件路径 */
45
+ path: string;
46
+ }
47
+
48
+ /** File信息 */
49
+ export interface FileInfo {
50
+ /** 文件路径 */
51
+ url: string;
52
+ /** 文件名 */
53
+ name: string;
54
+ /** 文件扩展名 */
55
+ extname: string;
56
+ }
57
+
58
+ /** Base文件服务 */
59
+ export interface FileService {
60
+ /** 多个文件上传 */
61
+ MultiUploadFile(request: MultiUploadFileRequest): Promise<MultiUploadFileResponse>;
62
+ /** 单个文件上传 */
63
+ UploadFile(request: UploadFileRequest): Promise<FileInfo>;
64
+ /** 下载文件 */
65
+ DownloadFile(request: DownloadFileRequest): Promise<BytesValue>;
66
+ }
@@ -0,0 +1,128 @@
1
+ // Code generated by protoc-gen-ts_proto. DO NOT EDIT.
2
+ // versions:
3
+ // protoc-gen-ts_proto v2.7.7
4
+ // protoc unknown
5
+ // source: base/v1/login.proto
6
+
7
+ /* eslint-disable */
8
+ import type { PasswordCryptoScene } from "../../common/v1/enum";
9
+ import type { PasswordCrypto } from "../../common/v1/types";
10
+ import type { Empty } from "../../google/protobuf/empty";
11
+
12
+ /** 验证码获取条件 */
13
+ export interface CaptchaRequest {
14
+ /** 验证码类型,random 表示随机选择当前支持的验证码类型 */
15
+ type: string;
16
+ }
17
+
18
+ /** 密码临时公钥获取条件 */
19
+ export interface PasswordPublicKeyRequest {
20
+ /** 使用场景 */
21
+ scene: PasswordCryptoScene;
22
+ }
23
+
24
+ /** 登出请求条件 */
25
+ export interface LogoutRequest {
26
+ }
27
+
28
+ /** 验证码响应 */
29
+ export interface CaptchaResponse {
30
+ /** 验证码ID。 */
31
+ captcha_id: string;
32
+ /** 验证码base64 */
33
+ captcha_base64: string;
34
+ /** 本次验证码实际类型 */
35
+ type: string;
36
+ }
37
+
38
+ /** 验证码预校验请求 */
39
+ export interface VerifyCaptchaRequest {
40
+ /** 验证码ID */
41
+ captcha_id: string;
42
+ /** 验证码答案 */
43
+ captcha_code: string;
44
+ }
45
+
46
+ /** 验证码预校验响应 */
47
+ export interface VerifyCaptchaResponse {
48
+ /** 验证码通过令牌 */
49
+ captcha_token: string;
50
+ /** 有效时间,单位秒 */
51
+ expires_in: number;
52
+ }
53
+
54
+ /** 密码临时公钥响应 */
55
+ export interface PasswordPublicKeyResponse {
56
+ /** 临时密钥ID */
57
+ key_id: string;
58
+ /** 临时公钥 */
59
+ public_key: string;
60
+ /** 加密算法 */
61
+ algorithm: string;
62
+ /** 随机值 */
63
+ nonce: string;
64
+ /** 有效时间,单位秒 */
65
+ expires_in: number;
66
+ }
67
+
68
+ /** 刷新令牌请求参数 */
69
+ export interface RefreshTokenRequest {
70
+ /** 更新令牌,用来获取下一次的访问令牌,必选项。 */
71
+ refresh_token: string;
72
+ }
73
+
74
+ /** 刷新令牌响应 */
75
+ export interface RefreshTokenResponse {
76
+ /** 访问令牌,必选项。 */
77
+ access_token: string;
78
+ /** 更新令牌,用来获取下一次的访问令牌,可选项。 */
79
+ refresh_token: string;
80
+ /** 令牌类型,该值大小写不敏感,必选项,可以是bearer类型或mac类型。 */
81
+ token_type: string;
82
+ /** 令牌有效时间,单位为秒。如果访问令牌过期,服务器应回复授予访问令牌的持续时间。如果省略该参数,必须其他方式设置过期时间。 */
83
+ expires_in: number;
84
+ }
85
+
86
+ /** 登录请求参数 */
87
+ export interface LoginRequest {
88
+ /** 租户编码 */
89
+ tenant_code: string;
90
+ /** 用户名,必选项。 */
91
+ user_name: string;
92
+ /** 用户的密码,必选项。 */
93
+ password:
94
+ | PasswordCrypto
95
+ | undefined;
96
+ /** 验证码 */
97
+ captcha_code: string;
98
+ /** 验证码Id */
99
+ captcha_id: string;
100
+ }
101
+
102
+ /** 登录响应 */
103
+ export interface LoginResponse {
104
+ /** 访问令牌,必选项。 */
105
+ access_token: string;
106
+ /** 更新令牌,用来获取下一次的访问令牌,可选项。 */
107
+ refresh_token: string;
108
+ /** 令牌类型,该值大小写不敏感,必选项,可以是bearer类型或mac类型。 */
109
+ token_type: string;
110
+ /** 令牌有效时间,单位为秒。如果访问令牌过期,服务器应回复授予访问令牌的持续时间。如果省略该参数,必须其他方式设置过期时间。 */
111
+ expires_in: number;
112
+ }
113
+
114
+ /** Base登录公共服务 */
115
+ export interface LoginService {
116
+ /** 验证码 */
117
+ Captcha(request: CaptchaRequest): Promise<CaptchaResponse>;
118
+ /** 验证码预校验 */
119
+ VerifyCaptcha(request: VerifyCaptchaRequest): Promise<VerifyCaptchaResponse>;
120
+ /** 获取密码临时公钥 */
121
+ PasswordPublicKey(request: PasswordPublicKeyRequest): Promise<PasswordPublicKeyResponse>;
122
+ /** 登出 */
123
+ Logout(request: LogoutRequest): Promise<Empty>;
124
+ /** 刷新认证令牌 */
125
+ RefreshToken(request: RefreshTokenRequest): Promise<RefreshTokenResponse>;
126
+ /** 登录 */
127
+ Login(request: LoginRequest): Promise<LoginResponse>;
128
+ }
@@ -0,0 +1,20 @@
1
+ // Code generated by protoc-gen-ts_proto. DO NOT EDIT.
2
+ // versions:
3
+ // protoc-gen-ts_proto v2.7.7
4
+ // protoc unknown
5
+ // source: base/v1/mcp.proto
6
+
7
+ /* eslint-disable */
8
+ import type { Empty } from "../../google/protobuf/empty";
9
+
10
+ /** MCP请求参数 */
11
+ export interface HandleMcpRequest {
12
+ /** 服务筛选关键字,必填,支持 app、admin 或任意服务关键字 */
13
+ terminal: string;
14
+ }
15
+
16
+ /** Base MCP服务 */
17
+ export interface McpService {
18
+ /** 处理MCP Streamable HTTP请求 */
19
+ HandleMcp(request: HandleMcpRequest): Promise<Empty>;
20
+ }