@liujitcn/kratos-admin-system 0.0.51 → 0.0.53
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/package/declarations/src/api/base/v1/sse.d.ts +1 -1
- package/dist/package/declarations/src/components/tenant-project/TenantProjectManager.vue.d.ts +1 -2
- package/dist/package/declarations/src/components/tenant-project/tenant-project-manager-data.d.ts +10 -0
- package/dist/package/declarations/src/components/tenant-project/tenant-project-manager.d.ts +8 -3
- package/dist/package/declarations/src/index.d.ts +1 -1
- package/dist/package/declarations/src/locales/generated.d.ts +32 -0
- package/dist/package/declarations/src/rpc/base/v1/ai_search.d.ts +26 -0
- package/dist/package/declarations/src/rpc/system/admin/v1/base_redact_output_policy.d.ts +0 -1
- package/dist/package/declarations/src/views/ai/chat/components/speech-recognition.d.ts +6 -2
- package/dist/package/src/api/base/v1/sse.ts +19 -12
- package/dist/package/src/components/log/LogTable.vue +25 -18
- package/dist/package/src/components/notification/Notification.vue +14 -7
- package/dist/package/src/components/tenant-project/TenantProjectManager.vue +106 -62
- package/dist/package/src/components/tenant-project/tenant-project-manager-data.ts +39 -1
- package/dist/package/src/components/tenant-project/tenant-project-manager.ts +19 -4
- package/dist/package/src/components/tenant-project-grant/ProjectGrantDialog.vue +22 -7
- package/dist/package/src/index.ts +2 -0
- package/dist/package/src/locales/en-US.json +8 -0
- package/dist/package/src/locales/ja-JP.json +8 -0
- package/dist/package/src/locales/zh-CN.json +8 -0
- package/dist/package/src/locales/zh-TW.json +8 -0
- package/dist/package/src/rpc/base/v1/ai_search.ts +37 -0
- package/dist/package/src/rpc/system/admin/v1/base_redact_output_policy.ts +0 -1
- package/dist/package/src/views/ai/chat/components/XSender.vue +1 -36
- package/dist/package/src/views/ai/chat/components/speech-recognition.ts +28 -7
- package/dist/package/src/views/ai/chat/index.vue +16 -7
- package/dist/package/src/views/base/api-log/index.vue +1 -1
- package/dist/package/src/views/base/area/index.vue +15 -9
- package/dist/package/src/views/base/backup-management/archive-config/index.vue +22 -10
- package/dist/package/src/views/base/backup-management/backup-config/index.vue +13 -6
- package/dist/package/src/views/base/config/index.vue +38 -14
- package/dist/package/src/views/base/dept/index.vue +31 -25
- package/dist/package/src/views/base/dict/index.vue +12 -8
- package/dist/package/src/views/base/dict/item.vue +12 -8
- package/dist/package/src/views/base/i18n-custom/index.vue +13 -7
- package/dist/package/src/views/base/job/index.vue +12 -8
- package/dist/package/src/views/base/job/log.vue +14 -9
- package/dist/package/src/views/base/language/index.vue +7 -4
- package/dist/package/src/views/base/login-policy/index.vue +22 -11
- package/dist/package/src/views/base/menu/index.vue +23 -16
- package/dist/package/src/views/base/message/index.vue +65 -21
- package/dist/package/src/views/base/message-category/index.vue +10 -4
- package/dist/package/src/views/base/oauth-client/index.vue +15 -5
- package/dist/package/src/views/base/post/index.vue +10 -4
- package/dist/package/src/views/base/redact-output-policy/index.vue +12 -5
- package/dist/package/src/views/base/redact-rule/index.vue +8 -7
- package/dist/package/src/views/base/redact-storage-policy/index.vue +32 -8
- package/dist/package/src/views/base/role/index.vue +24 -17
- package/dist/package/src/views/base/tenant/index.vue +7 -6
- package/dist/package/src/views/base/tenant-project-grant/index.vue +44 -27
- package/dist/package/src/views/base/user/components/dept-tree.vue +4 -9
- package/dist/package/src/views/base/user/index.vue +39 -28
- package/dist/package/src/views/message/inbox/index.vue +8 -3
- package/dist/package/src/views/profile/components/base.vue +1 -1
- package/dist/package/src/views/profile/index.vue +1 -1
- package/dist/package/src/views/tool/cache/index.vue +1 -1
- package/dist/package/src/views/tool/code-gen/columns/index.vue +35 -16
- package/dist/package/src/views/tool/code-gen/table/index.vue +58 -31
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -153,7 +153,7 @@ export const adminModules = [systemAdminModule];
|
|
|
153
153
|
|
|
154
154
|
跨模块跳转使用 Vue Router;复用 System 代码时只引用 `package.json#exports` 公开的 npm 子路径。
|
|
155
155
|
|
|
156
|
-
租户项目管理组件通过 `TenantProjectManager`
|
|
156
|
+
租户项目管理组件通过 `TenantProjectManager` 公开。默认租户创建项目时在表单中选择目标租户,普通租户由服务端自动使用当前租户;默认租户查询全部项目,普通租户按项目授权范围查询。外部业务模块可以传入 `extraColumns`、`extraActions` 和 `loadExtraData`:扩展列可通过 `after` 指定插入到哪个基础字段后面,列的同名表格插槽会沿用该位置,未配置时默认插入备注后面,例如 `{ prop: "address", after: "name" }` 配合 `#address` 插槽即可把内容放到项目名称后面;数据加载器接收当前页的 `tenant_id + project_id` 集合,单条操作回调接收同一组双键以及项目基础数据。组件也会透传表格具名插槽,并向行插槽增加 `tenantProject` 上下文;保存业务配置后可通过组件实例的 `refresh()` 刷新列表。按外部业务字段搜索或排序时,应由外部接口参与分页查询,不能只在当前页加载后过滤。
|
|
157
157
|
|
|
158
158
|
外部项目可以在自己的页面中包装该组件,并通过菜单将项目管理页面的 `component` 指向包装页面:
|
|
159
159
|
|
|
@@ -17,7 +17,7 @@ export declare class SseServiceImpl {
|
|
|
17
17
|
/** 创建或复用 SSE 订阅连接。 */
|
|
18
18
|
SubscribeSse(request: SubscribeSseRequest): SharedSseConnection | null;
|
|
19
19
|
/** 释放 SSE 共享连接。 */
|
|
20
|
-
ReleaseSse(request: SubscribeSseRequest): void;
|
|
20
|
+
ReleaseSse(request: SubscribeSseRequest, connection?: SharedSseConnection): void;
|
|
21
21
|
/** 构建 SSE 订阅地址。 */
|
|
22
22
|
private buildSubscribeURL;
|
|
23
23
|
/** 构建 SSE 共享连接键。 */
|
package/dist/package/declarations/src/components/tenant-project/TenantProjectManager.vue.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { ColumnProps } from "@liujitcn/kratos-admin-core/components/ProTable/interface";
|
|
2
1
|
import { type TenantProjectAction, type TenantProjectManagerProps } from "./tenant-project-manager";
|
|
3
2
|
/** 刷新项目表格。 */
|
|
4
3
|
declare function refreshTable(): Promise<void>;
|
|
@@ -16,7 +15,7 @@ declare const __VLS_base: import("vue").DefineComponent<TenantProjectManagerProp
|
|
|
16
15
|
}, string, import("vue").PublicProps, Readonly<TenantProjectManagerProps> & Readonly<{
|
|
17
16
|
"onExtra-data-error"?: ((error: unknown) => any) | undefined;
|
|
18
17
|
}>, {
|
|
19
|
-
extraColumns:
|
|
18
|
+
extraColumns: import("./tenant-project-manager").TenantProjectExtraColumn[];
|
|
20
19
|
extraActions: TenantProjectAction[];
|
|
21
20
|
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
22
21
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
package/dist/package/declarations/src/components/tenant-project/tenant-project-manager-data.d.ts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import type { BaseTenantProject } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/base_tenant_project";
|
|
2
|
+
/** 租户项目表格列的最小结构,用于在不依赖表格组件的情况下排列扩展列。 */
|
|
3
|
+
type TenantProjectColumnLike = {
|
|
4
|
+
prop?: string;
|
|
5
|
+
type?: string;
|
|
6
|
+
};
|
|
2
7
|
/** 租户项目业务数据查询键。 */
|
|
3
8
|
export interface TenantProjectKey {
|
|
4
9
|
/** 租户 ID。 */
|
|
@@ -8,7 +13,12 @@ export interface TenantProjectKey {
|
|
|
8
13
|
}
|
|
9
14
|
/** 租户项目扩展数据,外层键由租户 ID 和项目 ID 组成。 */
|
|
10
15
|
export type TenantProjectExtraData = Record<string, Record<string, unknown>>;
|
|
16
|
+
/** 按基础字段位置排列租户项目管理的扩展列。 */
|
|
17
|
+
export declare function arrangeTenantProjectColumns<T extends TenantProjectColumnLike>(baseColumns: T[], extraColumns: Array<T & {
|
|
18
|
+
after?: string;
|
|
19
|
+
}>): T[];
|
|
11
20
|
/** 创建租户项目扩展数据的稳定键。 */
|
|
12
21
|
export declare function tenantProjectKey(tenantId: number, projectId: number): string;
|
|
13
22
|
/** 将外部业务字段合并到项目行,同时保护公共项目字段。 */
|
|
14
23
|
export declare function mergeTenantProjectExtraData(project: BaseTenantProject, extra?: Record<string, unknown>): BaseTenantProject & Record<string, unknown>;
|
|
24
|
+
export {};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { BaseTenantProject, PageBaseTenantProjectRequest } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/base_tenant_project";
|
|
2
2
|
import type { ColumnProps, TableActionProps } from "@liujitcn/kratos-admin-core/components/ProTable/interface";
|
|
3
3
|
import type { TenantProjectExtraData, TenantProjectKey } from "./tenant-project-manager-data";
|
|
4
|
-
export { mergeTenantProjectExtraData, tenantProjectKey, type TenantProjectExtraData, type TenantProjectKey } from "./tenant-project-manager-data";
|
|
4
|
+
export { arrangeTenantProjectColumns, mergeTenantProjectExtraData, tenantProjectKey, type TenantProjectExtraData, type TenantProjectKey } from "./tenant-project-manager-data";
|
|
5
5
|
/** 租户项目单条业务上下文。 */
|
|
6
6
|
export interface TenantProjectContext<TData extends Record<string, unknown> = Record<string, unknown>> extends TenantProjectKey {
|
|
7
7
|
/** 公共项目基础数据。 */
|
|
@@ -29,10 +29,15 @@ export type TenantProjectAction = Omit<TableActionProps, "disabled" | "hidden" |
|
|
|
29
29
|
/** 执行项目扩展操作。 */
|
|
30
30
|
onClick: (context: TenantProjectContext, params?: Record<string, any>) => void | Promise<void>;
|
|
31
31
|
};
|
|
32
|
+
/** 租户项目管理的扩展列配置。 */
|
|
33
|
+
export type TenantProjectExtraColumn = ColumnProps & {
|
|
34
|
+
/** 插入到指定基础字段后面,未配置时默认插入备注字段后面。 */
|
|
35
|
+
after?: string;
|
|
36
|
+
};
|
|
32
37
|
/** 租户项目管理组件属性。 */
|
|
33
38
|
export interface TenantProjectManagerProps {
|
|
34
|
-
/**
|
|
35
|
-
extraColumns?:
|
|
39
|
+
/** 追加到基础列表的表格列,可通过 after 指定插入位置。 */
|
|
40
|
+
extraColumns?: TenantProjectExtraColumn[];
|
|
36
41
|
/** 追加到基础操作列的业务操作。 */
|
|
37
42
|
extraActions?: TenantProjectAction[];
|
|
38
43
|
/** 加载当前页外部业务字段。 */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { ADMIN_AI_EXTENSION, getAdminAiExtension } from "./ai";
|
|
2
2
|
export type { AdminAiExtension } from "./ai";
|
|
3
3
|
export { default as TenantProjectManager } from "./components/tenant-project/TenantProjectManager.vue";
|
|
4
|
-
export { mergeTenantProjectExtraData, tenantProjectKey, type TenantProjectAction, type TenantProjectContext, type TenantProjectExtraData, type TenantProjectExtraDataLoadContext, type TenantProjectExtraDataLoader, type TenantProjectKey, type TenantProjectManagerProps } from "./components/tenant-project/tenant-project-manager";
|
|
4
|
+
export { mergeTenantProjectExtraData, arrangeTenantProjectColumns, tenantProjectKey, type TenantProjectAction, type TenantProjectContext, type TenantProjectExtraColumn, type TenantProjectExtraData, type TenantProjectExtraDataLoadContext, type TenantProjectExtraDataLoader, type TenantProjectKey, type TenantProjectManagerProps } from "./components/tenant-project/tenant-project-manager";
|
|
5
5
|
export { systemAdminModule } from "./module";
|
|
@@ -399,6 +399,8 @@ export declare const LOCALE_MESSAGES: {
|
|
|
399
399
|
"system.base.log.field.os": string;
|
|
400
400
|
"system.base.log.field.path": string;
|
|
401
401
|
"system.base.log.field.project": string;
|
|
402
|
+
"system.base.log.field.role_code": string;
|
|
403
|
+
"system.base.log.field.role_id": string;
|
|
402
404
|
"system.base.log.field.reason": string;
|
|
403
405
|
"system.base.log.field.reason_code": string;
|
|
404
406
|
"system.base.log.field.referer": string;
|
|
@@ -649,6 +651,11 @@ export declare const LOCALE_MESSAGES: {
|
|
|
649
651
|
"system.base.message.content_format.plain": string;
|
|
650
652
|
"system.base.message.detail.action": string;
|
|
651
653
|
"system.base.message.detail.title": string;
|
|
654
|
+
"system.base.message.dispatch_status.pending": string;
|
|
655
|
+
"system.base.message.dispatch_status.running": string;
|
|
656
|
+
"system.base.message.dispatch_status.succeeded": string;
|
|
657
|
+
"system.base.message.dispatch_status.failed": string;
|
|
658
|
+
"system.base.message.dispatch_status.cancelled": string;
|
|
652
659
|
"system.base.message.field.action_target": string;
|
|
653
660
|
"system.base.message.field.action_type": string;
|
|
654
661
|
"system.base.message.field.attempt_count": string;
|
|
@@ -761,6 +768,7 @@ export declare const LOCALE_MESSAGES: {
|
|
|
761
768
|
"system.base.migration.title.list": string;
|
|
762
769
|
"system.base.migration.value.default_module": string;
|
|
763
770
|
"system.base.oauth_client.action.copy_credentials": string;
|
|
771
|
+
"system.base.oauth_client.confirm.rotate_credentials": string;
|
|
764
772
|
"system.base.oauth_client.field.api": string;
|
|
765
773
|
"system.base.oauth_client.field.client_id": string;
|
|
766
774
|
"system.base.oauth_client.field.client_name": string;
|
|
@@ -1971,6 +1979,8 @@ export declare const LOCALE_MESSAGES: {
|
|
|
1971
1979
|
"system.base.log.field.os": string;
|
|
1972
1980
|
"system.base.log.field.path": string;
|
|
1973
1981
|
"system.base.log.field.project": string;
|
|
1982
|
+
"system.base.log.field.role_code": string;
|
|
1983
|
+
"system.base.log.field.role_id": string;
|
|
1974
1984
|
"system.base.log.field.reason": string;
|
|
1975
1985
|
"system.base.log.field.reason_code": string;
|
|
1976
1986
|
"system.base.log.field.referer": string;
|
|
@@ -2221,6 +2231,11 @@ export declare const LOCALE_MESSAGES: {
|
|
|
2221
2231
|
"system.base.message.content_format.plain": string;
|
|
2222
2232
|
"system.base.message.detail.action": string;
|
|
2223
2233
|
"system.base.message.detail.title": string;
|
|
2234
|
+
"system.base.message.dispatch_status.pending": string;
|
|
2235
|
+
"system.base.message.dispatch_status.running": string;
|
|
2236
|
+
"system.base.message.dispatch_status.succeeded": string;
|
|
2237
|
+
"system.base.message.dispatch_status.failed": string;
|
|
2238
|
+
"system.base.message.dispatch_status.cancelled": string;
|
|
2224
2239
|
"system.base.message.field.action_target": string;
|
|
2225
2240
|
"system.base.message.field.action_type": string;
|
|
2226
2241
|
"system.base.message.field.attempt_count": string;
|
|
@@ -2333,6 +2348,7 @@ export declare const LOCALE_MESSAGES: {
|
|
|
2333
2348
|
"system.base.migration.title.list": string;
|
|
2334
2349
|
"system.base.migration.value.default_module": string;
|
|
2335
2350
|
"system.base.oauth_client.action.copy_credentials": string;
|
|
2351
|
+
"system.base.oauth_client.confirm.rotate_credentials": string;
|
|
2336
2352
|
"system.base.oauth_client.field.api": string;
|
|
2337
2353
|
"system.base.oauth_client.field.client_id": string;
|
|
2338
2354
|
"system.base.oauth_client.field.client_name": string;
|
|
@@ -3543,6 +3559,8 @@ export declare const LOCALE_MESSAGES: {
|
|
|
3543
3559
|
"system.base.log.field.os": string;
|
|
3544
3560
|
"system.base.log.field.path": string;
|
|
3545
3561
|
"system.base.log.field.project": string;
|
|
3562
|
+
"system.base.log.field.role_code": string;
|
|
3563
|
+
"system.base.log.field.role_id": string;
|
|
3546
3564
|
"system.base.log.field.reason": string;
|
|
3547
3565
|
"system.base.log.field.reason_code": string;
|
|
3548
3566
|
"system.base.log.field.referer": string;
|
|
@@ -3793,6 +3811,11 @@ export declare const LOCALE_MESSAGES: {
|
|
|
3793
3811
|
"system.base.message.content_format.plain": string;
|
|
3794
3812
|
"system.base.message.detail.action": string;
|
|
3795
3813
|
"system.base.message.detail.title": string;
|
|
3814
|
+
"system.base.message.dispatch_status.pending": string;
|
|
3815
|
+
"system.base.message.dispatch_status.running": string;
|
|
3816
|
+
"system.base.message.dispatch_status.succeeded": string;
|
|
3817
|
+
"system.base.message.dispatch_status.failed": string;
|
|
3818
|
+
"system.base.message.dispatch_status.cancelled": string;
|
|
3796
3819
|
"system.base.message.field.action_target": string;
|
|
3797
3820
|
"system.base.message.field.action_type": string;
|
|
3798
3821
|
"system.base.message.field.attempt_count": string;
|
|
@@ -3905,6 +3928,7 @@ export declare const LOCALE_MESSAGES: {
|
|
|
3905
3928
|
"system.base.migration.title.list": string;
|
|
3906
3929
|
"system.base.migration.value.default_module": string;
|
|
3907
3930
|
"system.base.oauth_client.action.copy_credentials": string;
|
|
3931
|
+
"system.base.oauth_client.confirm.rotate_credentials": string;
|
|
3908
3932
|
"system.base.oauth_client.field.api": string;
|
|
3909
3933
|
"system.base.oauth_client.field.client_id": string;
|
|
3910
3934
|
"system.base.oauth_client.field.client_name": string;
|
|
@@ -5115,6 +5139,8 @@ export declare const LOCALE_MESSAGES: {
|
|
|
5115
5139
|
"system.base.log.field.os": string;
|
|
5116
5140
|
"system.base.log.field.path": string;
|
|
5117
5141
|
"system.base.log.field.project": string;
|
|
5142
|
+
"system.base.log.field.role_code": string;
|
|
5143
|
+
"system.base.log.field.role_id": string;
|
|
5118
5144
|
"system.base.log.field.reason": string;
|
|
5119
5145
|
"system.base.log.field.reason_code": string;
|
|
5120
5146
|
"system.base.log.field.referer": string;
|
|
@@ -5365,6 +5391,11 @@ export declare const LOCALE_MESSAGES: {
|
|
|
5365
5391
|
"system.base.message.content_format.plain": string;
|
|
5366
5392
|
"system.base.message.detail.action": string;
|
|
5367
5393
|
"system.base.message.detail.title": string;
|
|
5394
|
+
"system.base.message.dispatch_status.pending": string;
|
|
5395
|
+
"system.base.message.dispatch_status.running": string;
|
|
5396
|
+
"system.base.message.dispatch_status.succeeded": string;
|
|
5397
|
+
"system.base.message.dispatch_status.failed": string;
|
|
5398
|
+
"system.base.message.dispatch_status.cancelled": string;
|
|
5368
5399
|
"system.base.message.field.action_target": string;
|
|
5369
5400
|
"system.base.message.field.action_type": string;
|
|
5370
5401
|
"system.base.message.field.attempt_count": string;
|
|
@@ -5477,6 +5508,7 @@ export declare const LOCALE_MESSAGES: {
|
|
|
5477
5508
|
"system.base.migration.title.list": string;
|
|
5478
5509
|
"system.base.migration.value.default_module": string;
|
|
5479
5510
|
"system.base.oauth_client.action.copy_credentials": string;
|
|
5511
|
+
"system.base.oauth_client.confirm.rotate_credentials": string;
|
|
5480
5512
|
"system.base.oauth_client.field.api": string;
|
|
5481
5513
|
"system.base.oauth_client.field.client_id": string;
|
|
5482
5514
|
"system.base.oauth_client.field.client_name": string;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/** AI 助手联网搜索请求 */
|
|
2
|
+
export interface SearchAiWebRequest {
|
|
3
|
+
/** 搜索关键词 */
|
|
4
|
+
query: string;
|
|
5
|
+
/** 返回结果数量:0 表示默认5条,最大10条 */
|
|
6
|
+
limit: number;
|
|
7
|
+
}
|
|
8
|
+
/** AI 助手联网搜索响应 */
|
|
9
|
+
export interface SearchAiWebResponse {
|
|
10
|
+
/** 搜索结果列表 */
|
|
11
|
+
items: SearchAiWebItem[];
|
|
12
|
+
}
|
|
13
|
+
/** AI 助手联网搜索结果 */
|
|
14
|
+
export interface SearchAiWebItem {
|
|
15
|
+
/** 结果标题 */
|
|
16
|
+
title: string;
|
|
17
|
+
/** 结果链接 */
|
|
18
|
+
url: string;
|
|
19
|
+
/** 结果摘要 */
|
|
20
|
+
snippet: string;
|
|
21
|
+
}
|
|
22
|
+
/** Base AI 助手联网搜索服务 */
|
|
23
|
+
export interface AiSearchService {
|
|
24
|
+
/** 联网搜索公开信息并返回结果摘要 */
|
|
25
|
+
SearchAiWeb(request: SearchAiWebRequest): Promise<SearchAiWebResponse>;
|
|
26
|
+
}
|
|
@@ -3,6 +3,7 @@ export type SpeechResultList = ArrayLike<{
|
|
|
3
3
|
0?: {
|
|
4
4
|
transcript: string;
|
|
5
5
|
};
|
|
6
|
+
isFinal?: boolean;
|
|
6
7
|
length: number;
|
|
7
8
|
}>;
|
|
8
9
|
/** 语音识别错误的最小结构,兼容浏览器事件和不支持错误。 */
|
|
@@ -21,8 +22,11 @@ type SpeechRecognitionOptions = {
|
|
|
21
22
|
/** 识别结果回调。 */
|
|
22
23
|
onResult?: (text: string) => void;
|
|
23
24
|
};
|
|
24
|
-
/**
|
|
25
|
-
export declare function
|
|
25
|
+
/** 增量累积语音识别结果,避免连续模式下 interim 结果重复计入已确认文本。 */
|
|
26
|
+
export declare function accumulateSpeechResultText(results: SpeechResultList, resultIndex: number, previousFinalText: string): {
|
|
27
|
+
finalText: string;
|
|
28
|
+
text: string;
|
|
29
|
+
};
|
|
26
30
|
/** 创建浏览器语音识别实例,并统一结果、状态和卸载处理。 */
|
|
27
31
|
export declare function useSpeechRecognition({ onError, onStart, onEnd, onResult }?: SpeechRecognitionOptions): {
|
|
28
32
|
loading: globalThis.Ref<boolean, boolean>;
|
|
@@ -61,10 +61,10 @@ export class SseServiceImpl {
|
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
/** 释放 SSE 共享连接。 */
|
|
64
|
-
ReleaseSse(request: SubscribeSseRequest) {
|
|
64
|
+
ReleaseSse(request: SubscribeSseRequest, connection?: SharedSseConnection) {
|
|
65
65
|
const connectionKey = this.buildConnectionKey(request);
|
|
66
66
|
const cachedConnection = this.sharedConnections.get(connectionKey);
|
|
67
|
-
if (!cachedConnection) {
|
|
67
|
+
if (!cachedConnection || (connection && cachedConnection !== connection)) {
|
|
68
68
|
return;
|
|
69
69
|
}
|
|
70
70
|
cachedConnection.refCount -= 1;
|
|
@@ -77,10 +77,9 @@ export class SseServiceImpl {
|
|
|
77
77
|
|
|
78
78
|
/** 构建 SSE 订阅地址。 */
|
|
79
79
|
private buildSubscribeURL(request: SubscribeSseRequest) {
|
|
80
|
-
const url = new URL(SSE_URL
|
|
81
|
-
url.searchParams.set("stream", request.stream);
|
|
80
|
+
const url = new URL(`${SSE_URL}/${encodeURIComponent(request.stream)}`, window.location.origin);
|
|
82
81
|
if (request.channel_id) {
|
|
83
|
-
url.searchParams.set("
|
|
82
|
+
url.searchParams.set("channel_id", request.channel_id);
|
|
84
83
|
}
|
|
85
84
|
return url.toString();
|
|
86
85
|
}
|
|
@@ -100,19 +99,27 @@ export class SseServiceImpl {
|
|
|
100
99
|
try {
|
|
101
100
|
const accessToken = await getRequestAccessToken();
|
|
102
101
|
if (!accessToken) {
|
|
103
|
-
this.sharedConnections.delete(connectionKey);
|
|
102
|
+
if (this.sharedConnections.get(connectionKey) === connection) this.sharedConnections.delete(connectionKey);
|
|
104
103
|
return;
|
|
105
104
|
}
|
|
106
105
|
|
|
106
|
+
const headers: Record<string, string> = {
|
|
107
|
+
Accept: EventStreamContentType,
|
|
108
|
+
Authorization: accessToken,
|
|
109
|
+
...getLocaleRequestHeaders()
|
|
110
|
+
};
|
|
107
111
|
await fetchEventSource(url, {
|
|
108
112
|
method: "GET",
|
|
109
113
|
signal: controller.signal,
|
|
110
114
|
openWhenHidden: true,
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
+
fetch: async (input, init) => {
|
|
116
|
+
const token = await getRequestAccessToken();
|
|
117
|
+
if (!token) return new Response(null, { status: 401 });
|
|
118
|
+
const requestHeaders = new Headers(init?.headers);
|
|
119
|
+
requestHeaders.set("Authorization", token);
|
|
120
|
+
return window.fetch(input, { ...init, headers: requestHeaders });
|
|
115
121
|
},
|
|
122
|
+
headers,
|
|
116
123
|
async onopen(response) {
|
|
117
124
|
const contentType = response.headers.get("content-type") ?? "";
|
|
118
125
|
if (response.ok && contentType.startsWith(EventStreamContentType)) {
|
|
@@ -161,7 +168,7 @@ export class SseServiceImpl {
|
|
|
161
168
|
} else if (error instanceof SsePermissionError) {
|
|
162
169
|
ElMessage.error(error.message);
|
|
163
170
|
}
|
|
164
|
-
this.sharedConnections.delete(connectionKey);
|
|
171
|
+
if (this.sharedConnections.get(connectionKey) === connection) this.sharedConnections.delete(connectionKey);
|
|
165
172
|
}
|
|
166
173
|
}
|
|
167
174
|
}
|
|
@@ -199,6 +206,6 @@ export function subscribeSseEvent<T>(
|
|
|
199
206
|
if (currentListeners && currentListeners.size === 0) {
|
|
200
207
|
connection.listeners.delete(eventName);
|
|
201
208
|
}
|
|
202
|
-
defSseService.ReleaseSse(request);
|
|
209
|
+
defSseService.ReleaseSse(request, connection);
|
|
203
210
|
};
|
|
204
211
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<div class="table-box">
|
|
3
3
|
<ProTable ref="proTable" row-key="id" :columns="resolvedColumns" :request-api="requestTable" />
|
|
4
4
|
|
|
5
|
-
<ProDialog v-model="dialog.visible" :title="config.detailTitle" width="1280px" @close="handleCloseDialog">
|
|
5
|
+
<ProDialog ref="dialogRef" v-model="dialog.visible" :title="config.detailTitle" width="1280px" @close="handleCloseDialog">
|
|
6
6
|
<el-descriptions border :column="2" class="detail-container">
|
|
7
7
|
<el-descriptions-item
|
|
8
8
|
v-for="field in config.detailFields"
|
|
@@ -93,6 +93,7 @@ export interface LogTableConfig {
|
|
|
93
93
|
|
|
94
94
|
const props = defineProps<{ config: LogTableConfig }>();
|
|
95
95
|
const proTable = ref<ProTableInstance>();
|
|
96
|
+
const dialogRef = ref<InstanceType<typeof ProDialog>>();
|
|
96
97
|
const detail = reactive<Record<string, unknown>>({});
|
|
97
98
|
const dialog = reactive({ visible: false });
|
|
98
99
|
const traceItems = ref<BaseLogTraceItem[]>([]);
|
|
@@ -107,27 +108,33 @@ async function requestTable(params: Record<string, unknown>) {
|
|
|
107
108
|
|
|
108
109
|
/** 打开审计详情弹窗。 */
|
|
109
110
|
async function handleOpenDialog(id: string) {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
111
|
+
await dialogRef.value?.open({
|
|
112
|
+
load: async () => {
|
|
113
|
+
const value = await props.config.get(id);
|
|
114
|
+
const requestID = String(value.request_id ?? "");
|
|
115
|
+
const traceID = String(value.trace_id ?? "");
|
|
116
|
+
let traces: BaseLogTraceItem[] = [];
|
|
117
|
+
if (props.config.trace && (requestID || traceID)) {
|
|
118
|
+
try {
|
|
119
|
+
traces = await props.config.trace(requestID, traceID);
|
|
120
|
+
} catch {
|
|
121
|
+
traces = [];
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return { value, traces };
|
|
125
|
+
},
|
|
126
|
+
commit: ({ value, traces }) => {
|
|
127
|
+
Object.keys(detail).forEach(key => delete detail[key]);
|
|
128
|
+
Object.assign(detail, value);
|
|
129
|
+
traceItems.value = traces;
|
|
130
|
+
traceLoading.value = false;
|
|
131
|
+
}
|
|
132
|
+
});
|
|
126
133
|
}
|
|
127
134
|
|
|
128
135
|
/** 关闭并清理审计详情弹窗。 */
|
|
129
136
|
function handleCloseDialog() {
|
|
130
|
-
|
|
137
|
+
dialogRef.value?.close();
|
|
131
138
|
Object.keys(detail).forEach(key => delete detail[key]);
|
|
132
139
|
traceItems.value = [];
|
|
133
140
|
traceLoading.value = false;
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
<el-button class="notification-more" text @click="openInbox">{{ t("system.notification.action.view_all") }}</el-button>
|
|
39
39
|
</div>
|
|
40
40
|
</el-popover>
|
|
41
|
-
<ProDialog v-model="detailVisible" :title="detail?.title" width="720px" destroy-on-close :show-footer="false">
|
|
41
|
+
<ProDialog ref="detailDialogRef" v-model="detailVisible" :title="detail?.title" width="720px" destroy-on-close :show-footer="false">
|
|
42
42
|
<div v-if="detail" class="notification-detail">
|
|
43
43
|
<div class="notification-detail-meta">
|
|
44
44
|
<span class="notification-detail-category" :style="{ color: detail.category_color || undefined }">
|
|
@@ -82,6 +82,7 @@ import {
|
|
|
82
82
|
|
|
83
83
|
const router = useRouter();
|
|
84
84
|
const popoverVisible = ref(false);
|
|
85
|
+
const detailDialogRef = ref<InstanceType<typeof ProDialog>>();
|
|
85
86
|
const unreadTotal = ref(0);
|
|
86
87
|
const latestDeliveryID = ref(0);
|
|
87
88
|
const notifications = ref<Notification[]>([]);
|
|
@@ -154,12 +155,18 @@ async function markAllRead() {
|
|
|
154
155
|
async function openNotification(row: Notification) {
|
|
155
156
|
popoverVisible.value = false;
|
|
156
157
|
const wasUnread = !row.read_at;
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
158
|
+
await detailDialogRef.value?.open({
|
|
159
|
+
load: async () => {
|
|
160
|
+
const [notification] = await Promise.all([
|
|
161
|
+
defNotificationService.GetNotification({ id: row.id }),
|
|
162
|
+
wasUnread ? defNotificationService.MarkNotificationRead({ ids: [row.id] }) : Promise.resolve()
|
|
163
|
+
]);
|
|
164
|
+
return notification;
|
|
165
|
+
},
|
|
166
|
+
commit: notification => {
|
|
167
|
+
detail.value = notification;
|
|
168
|
+
}
|
|
169
|
+
});
|
|
163
170
|
notifications.value = notifications.value.filter(item => item.id !== row.id);
|
|
164
171
|
if (wasUnread) unreadTotal.value = Math.max(0, unreadTotal.value - 1);
|
|
165
172
|
}
|