@liujitcn/kratos-admin-system 0.0.28 → 0.0.31
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 +19 -2
- package/dist/package/declarations/src/api/base/notification.d.ts +24 -0
- package/dist/package/declarations/src/api/system/base_audit_log.d.ts +55 -0
- package/dist/package/declarations/src/api/system/base_dashboard.d.ts +14 -0
- package/dist/package/declarations/src/api/system/base_file.d.ts +13 -0
- package/dist/package/declarations/src/api/system/base_i18n.d.ts +5 -5
- package/dist/package/declarations/src/api/system/base_login_policy.d.ts +10 -0
- package/dist/package/declarations/src/api/system/base_message.d.ts +24 -0
- package/dist/package/declarations/src/api/system/base_message_category.d.ts +21 -0
- package/dist/package/declarations/src/api/system/base_session.d.ts +11 -0
- package/dist/package/declarations/src/api/system/oauth_client.d.ts +24 -0
- package/dist/package/declarations/src/components/AuditLogTable.vue.d.ts +45 -0
- package/dist/package/declarations/src/components/DynamicI18nCell.vue.d.ts +16 -0
- package/dist/package/declarations/src/components/DynamicI18nEditor.vue.d.ts +20 -0
- package/dist/package/declarations/src/components/auditLog.d.ts +9 -0
- package/dist/package/declarations/src/components/dynamicI18n.d.ts +38 -0
- package/dist/package/declarations/src/locales/generated.d.ts +1364 -68
- package/dist/package/declarations/src/rpc/base/v1/login.d.ts +149 -0
- package/dist/package/declarations/src/rpc/base/v1/notification.d.ts +281 -0
- package/dist/package/declarations/src/rpc/base/v1/oauth.d.ts +25 -0
- package/dist/package/declarations/src/rpc/base/v1/oauth_client.d.ts +23 -0
- package/dist/package/declarations/src/rpc/system/admin/v1/base_audit_log.d.ts +640 -0
- package/dist/package/declarations/src/rpc/system/admin/v1/base_config.d.ts +3 -3
- package/dist/package/declarations/src/rpc/system/admin/v1/base_dashboard.d.ts +60 -0
- package/dist/package/declarations/src/rpc/system/admin/v1/base_dict.d.ts +4 -4
- package/dist/package/declarations/src/rpc/system/admin/v1/base_file.d.ts +73 -0
- package/dist/package/declarations/src/rpc/system/admin/v1/base_i18n.d.ts +27 -23
- package/dist/package/declarations/src/rpc/system/admin/v1/base_job.d.ts +5 -0
- package/dist/package/declarations/src/rpc/system/admin/v1/base_login_policy.d.ts +51 -0
- package/dist/package/declarations/src/rpc/system/admin/v1/base_menu.d.ts +2 -2
- package/dist/package/declarations/src/rpc/system/admin/v1/base_message.d.ts +193 -0
- package/dist/package/declarations/src/rpc/system/admin/v1/base_message_category.d.ts +125 -0
- package/dist/package/declarations/src/rpc/system/admin/v1/base_session.d.ts +33 -0
- package/dist/package/declarations/src/rpc/system/admin/v1/base_user.d.ts +3 -3
- package/dist/package/declarations/src/rpc/system/admin/v1/code_gen.d.ts +1 -1
- package/dist/package/declarations/src/rpc/system/admin/v1/oauth_client.d.ts +145 -0
- package/dist/package/declarations/src/views/base/api-log/index.vue.d.ts +3 -0
- package/dist/package/declarations/src/views/base/dashboard/index.vue.d.ts +3 -0
- package/dist/package/declarations/src/views/base/data-access-log/index.vue.d.ts +3 -0
- package/dist/package/declarations/src/views/base/file/index.vue.d.ts +3 -0
- package/dist/package/declarations/src/views/base/login-log/index.vue.d.ts +3 -0
- package/dist/package/declarations/src/views/base/login-policy/index.vue.d.ts +3 -0
- package/dist/package/declarations/src/views/base/message/index.vue.d.ts +3 -0
- package/dist/package/declarations/src/views/base/message-category/index.vue.d.ts +3 -0
- package/dist/package/declarations/src/views/base/oauth-client/index.vue.d.ts +3 -0
- package/dist/package/declarations/src/views/base/operation-log/index.vue.d.ts +3 -0
- package/dist/package/declarations/src/views/base/permission-log/index.vue.d.ts +3 -0
- package/dist/package/declarations/src/views/base/policy-evaluation-log/index.vue.d.ts +3 -0
- package/dist/package/declarations/src/views/message/inbox/index.vue.d.ts +3 -0
- package/dist/package/declarations/src/views/profile/components/session.vue.d.ts +3 -0
- package/dist/package/src/api/base/notification.ts +69 -0
- package/dist/package/src/api/base/sse.ts +4 -4
- package/dist/package/src/api/system/auth.ts +1 -0
- package/dist/package/src/api/system/base_audit_log.ts +168 -0
- package/dist/package/src/api/system/base_dashboard.ts +55 -0
- package/dist/package/src/api/system/base_file.ts +43 -0
- package/dist/package/src/api/system/base_i18n.ts +12 -12
- package/dist/package/src/api/system/base_login_policy.ts +32 -0
- package/dist/package/src/api/system/base_message.ts +70 -0
- package/dist/package/src/api/system/base_message_category.ts +57 -0
- package/dist/package/src/api/system/base_session.ts +33 -0
- package/dist/package/src/api/system/oauth_client.ts +102 -0
- package/dist/package/src/components/AuditLogTable.vue +105 -0
- package/dist/package/src/components/{DynamicTranslationCell.vue → DynamicI18nCell.vue} +50 -50
- package/dist/package/src/components/{DynamicTranslationEditor.vue → DynamicI18nEditor.vue} +45 -45
- package/dist/package/src/components/Notification.vue +196 -0
- package/dist/package/src/components/auditLog.ts +46 -0
- package/dist/package/src/components/{dynamicTranslation.ts → dynamicI18n.ts} +15 -15
- package/dist/package/src/locales/README.md +5 -3
- package/dist/package/src/locales/en-US.json +345 -21
- package/dist/package/src/locales/ja-JP.json +347 -23
- package/dist/package/src/locales/zh-CN.json +343 -19
- package/dist/package/src/locales/zh-TW.json +346 -22
- package/dist/package/src/module.ts +5 -2
- package/dist/package/src/rpc/base/v1/login.ts +172 -0
- package/dist/package/src/rpc/base/v1/notification.ts +315 -0
- package/dist/package/src/rpc/base/v1/oauth.ts +25 -0
- package/dist/package/src/rpc/base/v1/oauth_client.ts +33 -0
- package/dist/package/src/rpc/system/admin/v1/base_audit_log.ts +737 -0
- package/dist/package/src/rpc/system/admin/v1/base_config.ts +3 -3
- package/dist/package/src/rpc/system/admin/v1/base_dashboard.ts +81 -0
- package/dist/package/src/rpc/system/admin/v1/base_dict.ts +4 -4
- package/dist/package/src/rpc/system/admin/v1/base_file.ts +88 -0
- package/dist/package/src/rpc/system/admin/v1/base_i18n.ts +27 -23
- package/dist/package/src/rpc/system/admin/v1/base_job.ts +5 -0
- package/dist/package/src/rpc/system/admin/v1/base_login_policy.ts +63 -0
- package/dist/package/src/rpc/system/admin/v1/base_menu.ts +2 -2
- package/dist/package/src/rpc/system/admin/v1/base_message.ts +236 -0
- package/dist/package/src/rpc/system/admin/v1/base_message_category.ts +149 -0
- package/dist/package/src/rpc/system/admin/v1/base_session.ts +44 -0
- package/dist/package/src/rpc/system/admin/v1/base_user.ts +3 -3
- package/dist/package/src/rpc/system/admin/v1/code_gen.ts +1 -1
- package/dist/package/src/rpc/system/admin/v1/oauth_client.ts +174 -0
- package/dist/package/src/views/ai/chat/components/ChatPanel.vue +2 -2
- package/dist/package/src/views/ai/chat/message.ts +7 -3
- package/dist/package/src/views/base/api-log/index.vue +83 -0
- package/dist/package/src/views/base/config/index.vue +41 -41
- package/dist/package/src/views/base/dashboard/index.vue +200 -0
- package/dist/package/src/views/base/data-access-log/index.vue +84 -0
- package/dist/package/src/views/base/dict/index.vue +23 -23
- package/dist/package/src/views/base/dict/item.vue +25 -25
- package/dist/package/src/views/base/file/index.vue +119 -0
- package/dist/package/src/views/base/job/index.vue +62 -7
- package/dist/package/src/views/base/language/index.vue +2 -1
- package/dist/package/src/views/base/login-log/index.vue +92 -0
- package/dist/package/src/views/base/login-policy/index.vue +219 -0
- package/dist/package/src/views/base/menu/index.vue +23 -23
- package/dist/package/src/views/base/message/index.vue +582 -0
- package/dist/package/src/views/base/message-category/index.vue +356 -0
- package/dist/package/src/views/base/oauth-client/index.vue +411 -0
- package/dist/package/src/views/base/operation-log/index.vue +82 -0
- package/dist/package/src/views/base/permission-log/index.vue +85 -0
- package/dist/package/src/views/base/policy-evaluation-log/index.vue +82 -0
- package/dist/package/src/views/message/inbox/index.vue +249 -0
- package/dist/package/src/views/profile/components/base.vue +6 -5
- package/dist/package/src/views/profile/components/password.vue +2 -2
- package/dist/package/src/views/profile/components/security.vue +475 -62
- package/dist/package/src/views/profile/components/session.vue +153 -0
- package/dist/package/src/views/profile/index.vue +35 -22
- package/dist/package/src/views/tool/code-gen/code-preview/index.vue +9 -9
- package/dist/package/src/views/tool/code-gen/columns/index.vue +1 -1
- package/dist/package/src/views/tool/code-gen/components/CodeGenLocaleEditor.vue +8 -8
- package/dist/package/src/views/tool/code-gen/config.ts +1 -0
- package/dist/package/src/views/tool/code-gen/table/index.vue +7 -7
- package/dist/package/src/views/tool/ops-monitoring/index.vue +25 -21
- package/package.json +2 -2
- package/dist/package/declarations/src/api/system/base_log.d.ts +0 -9
- package/dist/package/declarations/src/components/DynamicTranslationCell.vue.d.ts +0 -16
- package/dist/package/declarations/src/components/DynamicTranslationEditor.vue.d.ts +0 -20
- package/dist/package/declarations/src/components/dynamicTranslation.d.ts +0 -38
- package/dist/package/declarations/src/rpc/system/admin/v1/base_log.d.ts +0 -87
- package/dist/package/src/api/system/base_log.ts +0 -32
- package/dist/package/src/rpc/system/admin/v1/base_log.ts +0 -101
- package/dist/package/src/views/base/log/index.vue +0 -339
- /package/dist/package/declarations/src/{views/base/log/index.vue.d.ts → components/Notification.vue.d.ts} +0 -0
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<el-card class="session-card" shadow="never">
|
|
3
|
+
<template #header>
|
|
4
|
+
<div class="session-header">
|
|
5
|
+
<div>
|
|
6
|
+
<h3>{{ t("system.profile.session.title") }}</h3>
|
|
7
|
+
<p>{{ t("system.profile.session.description") }}</p>
|
|
8
|
+
</div>
|
|
9
|
+
<el-button :loading="loading" @click="loadSession">
|
|
10
|
+
<el-icon><Refresh /></el-icon>
|
|
11
|
+
{{ t("system.profile.session.action.refresh") }}
|
|
12
|
+
</el-button>
|
|
13
|
+
</div>
|
|
14
|
+
</template>
|
|
15
|
+
|
|
16
|
+
<el-skeleton v-if="loading && !session" :rows="5" animated />
|
|
17
|
+
<el-empty v-else-if="!session" :description="t('system.profile.session.empty')" />
|
|
18
|
+
<div v-else class="session-details">
|
|
19
|
+
<div class="session-status">
|
|
20
|
+
<el-tag type="success" effect="plain">{{ t("system.profile.session.status.active") }}</el-tag>
|
|
21
|
+
<span>{{ session.user_name }} · {{ session.tenant_code }}</span>
|
|
22
|
+
</div>
|
|
23
|
+
<dl class="session-grid">
|
|
24
|
+
<div>
|
|
25
|
+
<dt>{{ t("system.profile.session.field.client_ip") }}</dt>
|
|
26
|
+
<dd>{{ session.client_ip || "-" }}</dd>
|
|
27
|
+
</div>
|
|
28
|
+
<div>
|
|
29
|
+
<dt>{{ t("system.profile.session.field.device") }}</dt>
|
|
30
|
+
<dd>{{ session.device || "-" }}</dd>
|
|
31
|
+
</div>
|
|
32
|
+
<div>
|
|
33
|
+
<dt>{{ t("system.profile.session.field.issued_at") }}</dt>
|
|
34
|
+
<dd>{{ session.issued_at || "-" }}</dd>
|
|
35
|
+
</div>
|
|
36
|
+
<div>
|
|
37
|
+
<dt>{{ t("system.profile.session.field.expires_in") }}</dt>
|
|
38
|
+
<dd>{{ formatExpires(session.expires_in) }}</dd>
|
|
39
|
+
</div>
|
|
40
|
+
</dl>
|
|
41
|
+
<div class="session-actions">
|
|
42
|
+
<el-button type="danger" plain @click="revokeAll">
|
|
43
|
+
<el-icon><SwitchButton /></el-icon>
|
|
44
|
+
{{ t("system.profile.session.action.revoke_all") }}
|
|
45
|
+
</el-button>
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
</el-card>
|
|
49
|
+
</template>
|
|
50
|
+
|
|
51
|
+
<script setup lang="ts">
|
|
52
|
+
import { onMounted, ref } from "vue";
|
|
53
|
+
import { useRouter } from "vue-router";
|
|
54
|
+
import { t } from "@liujitcn/kratos-admin-core";
|
|
55
|
+
import { LOGIN_URL } from "@liujitcn/kratos-admin-core/config";
|
|
56
|
+
import { useUserStore } from "@liujitcn/kratos-admin-core/stores/runtime";
|
|
57
|
+
import { defBaseSessionService } from "@liujitcn/kratos-admin-system/api/system/base_session";
|
|
58
|
+
import type { BaseSession } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/base_session";
|
|
59
|
+
|
|
60
|
+
const loading = ref(false);
|
|
61
|
+
const session = ref<BaseSession>();
|
|
62
|
+
const router = useRouter();
|
|
63
|
+
const userStore = useUserStore();
|
|
64
|
+
|
|
65
|
+
/** 拉取当前会话信息。 */
|
|
66
|
+
async function loadSession() {
|
|
67
|
+
loading.value = true;
|
|
68
|
+
try {
|
|
69
|
+
session.value = await defBaseSessionService.GetCurrentBaseSession({});
|
|
70
|
+
} finally {
|
|
71
|
+
loading.value = false;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** 撤销当前用户全部会话并返回登录页。 */
|
|
76
|
+
async function revokeAll() {
|
|
77
|
+
await ElMessageBox.confirm(t("system.profile.session.confirm.revoke_all"), t("system.profile.session.confirm.title"), {
|
|
78
|
+
type: "warning"
|
|
79
|
+
});
|
|
80
|
+
await defBaseSessionService.RevokeAllBaseSessions({});
|
|
81
|
+
userStore.clearAuthData();
|
|
82
|
+
ElMessage.success(t("system.profile.session.message.revoked"));
|
|
83
|
+
session.value = undefined;
|
|
84
|
+
await router.replace(LOGIN_URL);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** 将秒数格式化为可读的剩余有效期。 */
|
|
88
|
+
function formatExpires(seconds: number) {
|
|
89
|
+
if (!seconds || seconds < 60) return t("system.profile.session.value.less_than_minute");
|
|
90
|
+
const hours = Math.floor(seconds / 3600);
|
|
91
|
+
const minutes = Math.floor((seconds % 3600) / 60);
|
|
92
|
+
if (hours > 0) return t("system.profile.session.value.hours_minutes", { hours, minutes });
|
|
93
|
+
return t("system.profile.session.value.minutes", { minutes });
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
onMounted(loadSession);
|
|
97
|
+
</script>
|
|
98
|
+
|
|
99
|
+
<style scoped lang="scss">
|
|
100
|
+
.session-card {
|
|
101
|
+
border: 1px solid var(--el-border-color-light);
|
|
102
|
+
}
|
|
103
|
+
.session-header,
|
|
104
|
+
.session-status,
|
|
105
|
+
.session-actions {
|
|
106
|
+
display: flex;
|
|
107
|
+
align-items: center;
|
|
108
|
+
justify-content: space-between;
|
|
109
|
+
gap: 12px;
|
|
110
|
+
}
|
|
111
|
+
.session-header h3 {
|
|
112
|
+
margin: 0;
|
|
113
|
+
color: var(--el-text-color-primary);
|
|
114
|
+
font-size: 18px;
|
|
115
|
+
}
|
|
116
|
+
.session-header p {
|
|
117
|
+
margin: 6px 0 0;
|
|
118
|
+
color: var(--el-text-color-secondary);
|
|
119
|
+
font-size: 13px;
|
|
120
|
+
}
|
|
121
|
+
.session-grid {
|
|
122
|
+
display: grid;
|
|
123
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
124
|
+
gap: 16px;
|
|
125
|
+
margin: 24px 0;
|
|
126
|
+
}
|
|
127
|
+
.session-grid div {
|
|
128
|
+
padding: 14px;
|
|
129
|
+
background: var(--el-fill-color-light);
|
|
130
|
+
border-radius: 6px;
|
|
131
|
+
}
|
|
132
|
+
.session-grid dt {
|
|
133
|
+
color: var(--el-text-color-secondary);
|
|
134
|
+
font-size: 12px;
|
|
135
|
+
}
|
|
136
|
+
.session-grid dd {
|
|
137
|
+
margin: 6px 0 0;
|
|
138
|
+
color: var(--el-text-color-primary);
|
|
139
|
+
overflow-wrap: anywhere;
|
|
140
|
+
}
|
|
141
|
+
.session-actions {
|
|
142
|
+
justify-content: flex-end;
|
|
143
|
+
}
|
|
144
|
+
@media screen and (width <= 640px) {
|
|
145
|
+
.session-header {
|
|
146
|
+
align-items: flex-start;
|
|
147
|
+
flex-direction: column;
|
|
148
|
+
}
|
|
149
|
+
.session-grid {
|
|
150
|
+
grid-template-columns: 1fr;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
</style>
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
@refreshed="loadUserProfile"
|
|
27
27
|
@switch-tab="handleTabChange"
|
|
28
28
|
/>
|
|
29
|
+
<ProfileSession v-else-if="activeTab === 'session'" />
|
|
29
30
|
<ProfilePassword v-else />
|
|
30
31
|
</main>
|
|
31
32
|
</section>
|
|
@@ -47,10 +48,10 @@ import { useUserStore } from "@liujitcn/kratos-admin-core/stores/runtime";
|
|
|
47
48
|
import ProfileBase from "./components/base.vue";
|
|
48
49
|
import ProfileSecurity from "./components/security.vue";
|
|
49
50
|
import ProfilePassword from "./components/password.vue";
|
|
50
|
-
import
|
|
51
|
+
import ProfileSession from "./components/session.vue";
|
|
51
52
|
|
|
52
53
|
/** 个人中心标签页。 */
|
|
53
|
-
type ProfileTab = "account" | "security" | "password";
|
|
54
|
+
type ProfileTab = "account" | "security" | "password" | "session";
|
|
54
55
|
|
|
55
56
|
/** 左侧导航项结构。 */
|
|
56
57
|
interface ProfileTabOption {
|
|
@@ -65,23 +66,33 @@ interface ProfileTabOption {
|
|
|
65
66
|
const userStore = useUserStore();
|
|
66
67
|
const route = useRoute();
|
|
67
68
|
const activeTab = ref<ProfileTab>("account");
|
|
68
|
-
const profileTabs = computed<ProfileTabOption[]>(() =>
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
69
|
+
const profileTabs = computed<ProfileTabOption[]>(() => {
|
|
70
|
+
const tabs: ProfileTabOption[] = [
|
|
71
|
+
{
|
|
72
|
+
value: "account",
|
|
73
|
+
label: t("system.profile.account.title"),
|
|
74
|
+
description: t("system.profile.account.nav_description")
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
value: "security",
|
|
78
|
+
label: t("system.profile.security.title"),
|
|
79
|
+
description: t("system.profile.security.nav_description")
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
value: "password",
|
|
83
|
+
label: t("system.profile.password.title"),
|
|
84
|
+
description: t("system.profile.password.nav_description")
|
|
85
|
+
}
|
|
86
|
+
];
|
|
87
|
+
if (userStore.userInfo.role_code === "super") {
|
|
88
|
+
tabs.push({
|
|
89
|
+
value: "session",
|
|
90
|
+
label: t("system.profile.session.title"),
|
|
91
|
+
description: t("system.profile.session.nav_description")
|
|
92
|
+
});
|
|
83
93
|
}
|
|
84
|
-
|
|
94
|
+
return tabs;
|
|
95
|
+
});
|
|
85
96
|
const userProfileForm = reactive<UserProfileForm>({
|
|
86
97
|
user_name: "",
|
|
87
98
|
nick_name: "",
|
|
@@ -115,8 +126,10 @@ async function loadUserProfile() {
|
|
|
115
126
|
}
|
|
116
127
|
|
|
117
128
|
onMounted(async () => {
|
|
118
|
-
|
|
119
|
-
|
|
129
|
+
if (route.query.tab === "password") {
|
|
130
|
+
activeTab.value = "password";
|
|
131
|
+
} else if (route.query.oauth_bind_success || route.query.oauth_bind_error) {
|
|
132
|
+
// OAuth 绑定回跳时优先打开安全设置,让子组件消费绑定结果并刷新状态。
|
|
120
133
|
activeTab.value = "security";
|
|
121
134
|
}
|
|
122
135
|
await loadUserProfile();
|
|
@@ -139,7 +152,7 @@ onMounted(async () => {
|
|
|
139
152
|
padding: 16px;
|
|
140
153
|
background: #ffffff;
|
|
141
154
|
border: 1px solid #ebeef5;
|
|
142
|
-
border-radius:
|
|
155
|
+
border-radius: var(--admin-page-radius);
|
|
143
156
|
box-shadow: 0 2px 12px rgb(0 0 0 / 4%);
|
|
144
157
|
}
|
|
145
158
|
.nav-item {
|
|
@@ -153,7 +166,7 @@ onMounted(async () => {
|
|
|
153
166
|
cursor: pointer;
|
|
154
167
|
background: #ffffff;
|
|
155
168
|
border: 1px solid transparent;
|
|
156
|
-
border-radius:
|
|
169
|
+
border-radius: var(--admin-page-radius);
|
|
157
170
|
transition: all 0.2s ease;
|
|
158
171
|
}
|
|
159
172
|
.nav-item + .nav-item {
|
|
@@ -60,7 +60,7 @@ const table = ref<CodeGenTableForm>();
|
|
|
60
60
|
const files = ref<CodeGenPreviewFile[]>([]);
|
|
61
61
|
const loading = ref(false);
|
|
62
62
|
const previewError = ref("");
|
|
63
|
-
const
|
|
63
|
+
const missingI18ns = ref<string[]>([]);
|
|
64
64
|
const progressTaskId = ref(typeof window === "undefined" ? "" : (window.sessionStorage.getItem(codeGenTaskStorageKey) ?? ""));
|
|
65
65
|
const progressDialogVisible = ref(
|
|
66
66
|
!!progressTaskId.value &&
|
|
@@ -94,7 +94,7 @@ async function loadCodePreview() {
|
|
|
94
94
|
table.value = undefined;
|
|
95
95
|
files.value = [];
|
|
96
96
|
previewError.value = "";
|
|
97
|
-
|
|
97
|
+
missingI18ns.value = [];
|
|
98
98
|
if (!tableId.value) return;
|
|
99
99
|
loading.value = true;
|
|
100
100
|
try {
|
|
@@ -103,10 +103,10 @@ async function loadCodePreview() {
|
|
|
103
103
|
try {
|
|
104
104
|
const preview = await defCodeGenService.PreviewCodeGen({ table_id: tableId.value, output_paths: undefined });
|
|
105
105
|
files.value = preview.files ?? [];
|
|
106
|
-
|
|
107
|
-
if (
|
|
108
|
-
previewError.value = t("system.code.gen.preview.message.
|
|
109
|
-
items:
|
|
106
|
+
missingI18ns.value = preview.missing_i18ns ?? [];
|
|
107
|
+
if (missingI18ns.value.length) {
|
|
108
|
+
previewError.value = t("system.code.gen.preview.message.missing_i18ns", {
|
|
109
|
+
items: missingI18ns.value.join(t("system.code.gen.preview.value.list_separator"))
|
|
110
110
|
});
|
|
111
111
|
}
|
|
112
112
|
if (!files.value.length && !previewError.value) previewError.value = t("system.code.gen.preview.message.no_preview_files");
|
|
@@ -134,11 +134,11 @@ async function handleGenerate() {
|
|
|
134
134
|
ElMessage.warning(t("system.code.gen.table.message.disabled", { name: table.value.name }));
|
|
135
135
|
return;
|
|
136
136
|
}
|
|
137
|
-
if (
|
|
137
|
+
if (missingI18ns.value.length) {
|
|
138
138
|
try {
|
|
139
139
|
await ElMessageBox.alert(
|
|
140
|
-
t("system.code.gen.preview.message.
|
|
141
|
-
items:
|
|
140
|
+
t("system.code.gen.preview.message.missing_i18ns", {
|
|
141
|
+
items: missingI18ns.value.join(t("system.code.gen.preview.value.list_separator"))
|
|
142
142
|
}),
|
|
143
143
|
t("common.title.warning"),
|
|
144
144
|
{
|
|
@@ -557,7 +557,7 @@ import type {
|
|
|
557
557
|
} from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/code_gen_column";
|
|
558
558
|
import type { CodeGenDatabaseTable, CodeGenTableForm } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/code_gen_table";
|
|
559
559
|
import CodeGenLocaleEditor from "../components/CodeGenLocaleEditor.vue";
|
|
560
|
-
import { getEditableLanguageOptions } from "@liujitcn/kratos-admin-system/components/
|
|
560
|
+
import { getEditableLanguageOptions } from "@liujitcn/kratos-admin-system/components/dynamicI18n";
|
|
561
561
|
import {
|
|
562
562
|
copyCodeGenOptionToEmptyMatches,
|
|
563
563
|
copyFirstMatchingCodeGenOption,
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
:disabled="!canTranslate(locale.value, 'comment', sourceComment)"
|
|
36
36
|
@click="handleTranslate(locale.value, 'comment', sourceComment, locale.label)"
|
|
37
37
|
>
|
|
38
|
-
{{ t("system.base.
|
|
38
|
+
{{ t("system.base.i18n.action.translate") }}
|
|
39
39
|
</el-button>
|
|
40
40
|
</div>
|
|
41
41
|
<div v-if="showLeftTreeComment" class="code-gen-locale-editor__control">
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
:disabled="!canTranslate(locale.value, 'left_tree_comment', sourceLeftTreeComment)"
|
|
57
57
|
@click="handleTranslate(locale.value, 'left_tree_comment', sourceLeftTreeComment, locale.label)"
|
|
58
58
|
>
|
|
59
|
-
{{ t("system.base.
|
|
59
|
+
{{ t("system.base.i18n.action.translate") }}
|
|
60
60
|
</el-button>
|
|
61
61
|
</div>
|
|
62
62
|
</div>
|
|
@@ -140,13 +140,13 @@ async function handleTranslate(locale: string, field: keyof CodeGenLocaleConfig,
|
|
|
140
140
|
if (!canTranslate(locale, field, source)) return;
|
|
141
141
|
translatingField.value = `${locale}:${field}`;
|
|
142
142
|
try {
|
|
143
|
-
const response = await defBaseI18nService.
|
|
144
|
-
const
|
|
145
|
-
if (!
|
|
146
|
-
updateLocale(locale, field,
|
|
147
|
-
ElMessage.success(t("system.base.
|
|
143
|
+
const response = await defBaseI18nService.DraftBaseI18n({ source, locale });
|
|
144
|
+
const i18n = response.i18ns.find(item => item.locale === locale)?.i18n;
|
|
145
|
+
if (!i18n) throw new Error("i18n not found");
|
|
146
|
+
updateLocale(locale, field, i18n);
|
|
147
|
+
ElMessage.success(t("system.base.i18n.message.translate_success", { language }));
|
|
148
148
|
} catch {
|
|
149
|
-
ElMessage.error(t("system.base.
|
|
149
|
+
ElMessage.error(t("system.base.i18n.message.translate_failed", { language }));
|
|
150
150
|
} finally {
|
|
151
151
|
translatingField.value = "";
|
|
152
152
|
}
|
|
@@ -73,6 +73,7 @@ const codeGenFormComponentLabelKeys: Record<ProFormComponentType, string> = {
|
|
|
73
73
|
password: "system.code.gen.component.password",
|
|
74
74
|
textarea: "system.code.gen.component.textarea",
|
|
75
75
|
"input-number": "system.code.gen.component.input_number",
|
|
76
|
+
"color-picker": "system.code.gen.component.color_picker",
|
|
76
77
|
segmented: "system.code.gen.component.segmented",
|
|
77
78
|
switch: "system.code.gen.component.switch",
|
|
78
79
|
checkbox: "system.code.gen.component.checkbox",
|
|
@@ -212,7 +212,7 @@ const formFields = computed<ProFormField[]>(() => [
|
|
|
212
212
|
},
|
|
213
213
|
{
|
|
214
214
|
prop: "i18n_config",
|
|
215
|
-
label: t("system.code.gen.i18n.field.
|
|
215
|
+
label: t("system.code.gen.i18n.field.i18ns"),
|
|
216
216
|
component: "slot",
|
|
217
217
|
slotName: "tableI18nConfig",
|
|
218
218
|
colSpan: 24,
|
|
@@ -589,7 +589,7 @@ async function handleGenerate(selected: CodeGenGenerateTarget) {
|
|
|
589
589
|
return;
|
|
590
590
|
}
|
|
591
591
|
generating.value = true;
|
|
592
|
-
let
|
|
592
|
+
let missingI18ns: string[] = [];
|
|
593
593
|
try {
|
|
594
594
|
const previewEntries = await Promise.all(
|
|
595
595
|
tables.map(async table => ({
|
|
@@ -597,17 +597,17 @@ async function handleGenerate(selected: CodeGenGenerateTarget) {
|
|
|
597
597
|
preview: await defCodeGenService.PreviewCodeGen({ table_id: table.id, output_paths: undefined })
|
|
598
598
|
}))
|
|
599
599
|
);
|
|
600
|
-
|
|
601
|
-
(preview.
|
|
600
|
+
missingI18ns = previewEntries.flatMap(({ table, preview }) =>
|
|
601
|
+
(preview.missing_i18ns ?? []).map(item => (tables.length === 1 ? item : `${table.name}: ${item}`))
|
|
602
602
|
);
|
|
603
603
|
} finally {
|
|
604
604
|
generating.value = false;
|
|
605
605
|
}
|
|
606
|
-
if (
|
|
606
|
+
if (missingI18ns.length) {
|
|
607
607
|
try {
|
|
608
608
|
await ElMessageBox.alert(
|
|
609
|
-
t("system.code.gen.preview.message.
|
|
610
|
-
items:
|
|
609
|
+
t("system.code.gen.preview.message.missing_i18ns", {
|
|
610
|
+
items: missingI18ns.join(t("system.code.gen.preview.value.list_separator"))
|
|
611
611
|
}),
|
|
612
612
|
t("common.title.warning"),
|
|
613
613
|
{
|
|
@@ -128,7 +128,7 @@
|
|
|
128
128
|
<code>{{ item.address }}</code>
|
|
129
129
|
</div>
|
|
130
130
|
</div>
|
|
131
|
-
<el-tag :type="item.status
|
|
131
|
+
<el-tag :type="isNormalStatus(item.status) ? 'success' : 'warning'" size="small" effect="plain">{{
|
|
132
132
|
item.statusLabel
|
|
133
133
|
}}</el-tag>
|
|
134
134
|
</div>
|
|
@@ -199,12 +199,7 @@
|
|
|
199
199
|
<strong>{{ metric.percentageLabel }}</strong>
|
|
200
200
|
</span>
|
|
201
201
|
</div>
|
|
202
|
-
<el-progress
|
|
203
|
-
:percentage="metric.percentage"
|
|
204
|
-
:show-text="false"
|
|
205
|
-
:stroke-width="10"
|
|
206
|
-
:color="metric.color"
|
|
207
|
-
/>
|
|
202
|
+
<el-progress :percentage="metric.percentage" :show-text="false" :stroke-width="10" :color="metric.color" />
|
|
208
203
|
</div>
|
|
209
204
|
</div>
|
|
210
205
|
</div>
|
|
@@ -362,11 +357,17 @@ const alerts = ref<OpsAlertsResponse>();
|
|
|
362
357
|
const windowMinutes = ref(15);
|
|
363
358
|
const lastCollectedAt = ref("");
|
|
364
359
|
const trendGridLines = [16, 62, 108, 154, 198];
|
|
365
|
-
const
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
360
|
+
const monitoringStatusKeys = [
|
|
361
|
+
"system.ops_monitoring.status.normal",
|
|
362
|
+
"system.ops_monitoring.status.unconfigured",
|
|
363
|
+
"system.ops_monitoring.status.error",
|
|
364
|
+
"system.ops_monitoring.status.attention"
|
|
365
|
+
] as const;
|
|
366
|
+
const nodeMetricLabelKeys = [
|
|
367
|
+
"system.ops_monitoring.node_metric.heap_memory",
|
|
368
|
+
"system.ops_monitoring.node_metric.memory",
|
|
369
|
+
"system.ops_monitoring.node_metric.disk"
|
|
370
|
+
] as const;
|
|
370
371
|
const byteUnits = ["B", "KB", "MB", "GB", "TB", "PB"];
|
|
371
372
|
const trafficSummary = computed(() => traffic.value?.traffic);
|
|
372
373
|
|
|
@@ -454,7 +455,7 @@ const availabilityItems = computed<AvailabilityItem[]>(() =>
|
|
|
454
455
|
(services.value?.services ?? []).map(service => ({
|
|
455
456
|
label: service.name,
|
|
456
457
|
value: translateStatus(service.status),
|
|
457
|
-
tone: service.status
|
|
458
|
+
tone: isNormalStatus(service.status) ? "ok" : "warn"
|
|
458
459
|
}))
|
|
459
460
|
);
|
|
460
461
|
|
|
@@ -580,17 +581,20 @@ function formatRelativeTime(value?: string) {
|
|
|
580
581
|
}
|
|
581
582
|
|
|
582
583
|
function translateStatus(status?: string) {
|
|
583
|
-
|
|
584
|
-
if (
|
|
585
|
-
if (status === "异常") return t("system.ops_monitoring.status.error");
|
|
586
|
-
if (status === "关注") return t("system.ops_monitoring.status.attention");
|
|
584
|
+
const localeKey = monitoringStatusKeys.find(key => t(key) === status);
|
|
585
|
+
if (localeKey) return t(localeKey);
|
|
587
586
|
return status || t("system.ops_monitoring.unknown");
|
|
588
587
|
}
|
|
589
588
|
|
|
589
|
+
/** 判断监控状态是否为当前语言下的正常状态。 */
|
|
590
|
+
function isNormalStatus(status?: string) {
|
|
591
|
+
return status === t("system.ops_monitoring.status.normal");
|
|
592
|
+
}
|
|
593
|
+
|
|
590
594
|
function mapStorage(item: OpsStorage) {
|
|
591
595
|
return {
|
|
592
596
|
...item,
|
|
593
|
-
color: item.status
|
|
597
|
+
color: isNormalStatus(item.status) ? "var(--el-color-success)" : "var(--el-color-warning)",
|
|
594
598
|
statusLabel: translateStatus(item.status),
|
|
595
599
|
shortName: item.short_name || item.name,
|
|
596
600
|
capacityLabel: item.capacity_label || t("system.ops_monitoring.capacity"),
|
|
@@ -606,7 +610,7 @@ function mapEndpoint(endpoint: OpsEndpoint): EndpointItem {
|
|
|
606
610
|
latency: `${formatNumber(endpoint.p95_latency_ms)} ms`,
|
|
607
611
|
errorRate: `${formatNumber(endpoint.error_rate)}%`,
|
|
608
612
|
status: translateStatus(endpoint.status),
|
|
609
|
-
healthy: endpoint.status
|
|
613
|
+
healthy: isNormalStatus(endpoint.status)
|
|
610
614
|
};
|
|
611
615
|
}
|
|
612
616
|
|
|
@@ -649,7 +653,7 @@ function formatFixedNumber(value: number) {
|
|
|
649
653
|
|
|
650
654
|
/** 翻译实例资源指标名称,未知指标保留后端原值。 */
|
|
651
655
|
function translateNodeMetricLabel(label: string) {
|
|
652
|
-
const localeKey = nodeMetricLabelKeys
|
|
656
|
+
const localeKey = nodeMetricLabelKeys.find(key => t(key) === label);
|
|
653
657
|
return localeKey ? t(localeKey) : label;
|
|
654
658
|
}
|
|
655
659
|
|
|
@@ -658,7 +662,7 @@ function mapAlert(alert: OpsAlert) {
|
|
|
658
662
|
title: alert.title,
|
|
659
663
|
detail: alert.detail,
|
|
660
664
|
at: alert.at,
|
|
661
|
-
tone: alert.status
|
|
665
|
+
tone: isNormalStatus(alert.status) ? "ok" : "warn"
|
|
662
666
|
};
|
|
663
667
|
}
|
|
664
668
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@liujitcn/kratos-admin-system",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.31",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "kratos-admin system management module",
|
|
7
7
|
"license": "MIT",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"sortablejs": "^1.15.2",
|
|
16
16
|
"swagger-ui-dist": "^5.32.9",
|
|
17
17
|
"vue-element-plus-x": "^2.0.3",
|
|
18
|
-
"@liujitcn/kratos-admin-core": "0.0.
|
|
18
|
+
"@liujitcn/kratos-admin-core": "0.0.31"
|
|
19
19
|
},
|
|
20
20
|
"peerDependencies": {
|
|
21
21
|
"@element-plus/icons-vue": "^2.3.1",
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { type BaseLog, type BaseLogService, type GetBaseLogRequest, type PageBaseLogRequest, type PageBaseLogResponse } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/base_log";
|
|
2
|
-
/** Admin系统日志服务 */
|
|
3
|
-
export declare class BaseLogServiceImpl implements BaseLogService {
|
|
4
|
-
/** 查询系统日志分页列表 */
|
|
5
|
-
PageBaseLog(request: PageBaseLogRequest): Promise<PageBaseLogResponse>;
|
|
6
|
-
/** 查询系统日志 */
|
|
7
|
-
GetBaseLog(request: GetBaseLogRequest): Promise<BaseLog>;
|
|
8
|
-
}
|
|
9
|
-
export declare const defBaseLogService: BaseLogServiceImpl;
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import type { BaseI18n } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/base_i18n";
|
|
2
|
-
import { TranslationTargetType } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/base_i18n";
|
|
3
|
-
/** DynamicTranslationCellProps 动态翻译列表单元格属性。 */
|
|
4
|
-
interface DynamicTranslationCellProps {
|
|
5
|
-
/** 资源源文。 */
|
|
6
|
-
source: string;
|
|
7
|
-
/** 统一翻译表目标类型。 */
|
|
8
|
-
targetType?: TranslationTargetType;
|
|
9
|
-
/** 目标资源编号。 */
|
|
10
|
-
targetId?: number;
|
|
11
|
-
/** 资源列表返回的非主语言翻译。 */
|
|
12
|
-
translations?: BaseI18n[];
|
|
13
|
-
}
|
|
14
|
-
declare const __VLS_export: import("vue").DefineComponent<DynamicTranslationCellProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<DynamicTranslationCellProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
15
|
-
declare const _default: typeof __VLS_export;
|
|
16
|
-
export default _default;
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { type DynamicTranslationValue } from "./dynamicTranslation";
|
|
2
|
-
/** DynamicTranslationEditorProps 动态翻译编辑器属性。 */
|
|
3
|
-
interface DynamicTranslationEditorProps {
|
|
4
|
-
modelValue: DynamicTranslationValue[];
|
|
5
|
-
/** 当前语言源文本。 */
|
|
6
|
-
source?: string;
|
|
7
|
-
maxlength?: number;
|
|
8
|
-
multiline?: boolean;
|
|
9
|
-
}
|
|
10
|
-
declare const __VLS_export: import("vue").DefineComponent<DynamicTranslationEditorProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
11
|
-
"update:modelValue": (value: DynamicTranslationValue[]) => any;
|
|
12
|
-
}, string, import("vue").PublicProps, Readonly<DynamicTranslationEditorProps> & Readonly<{
|
|
13
|
-
"onUpdate:modelValue"?: ((value: DynamicTranslationValue[]) => any) | undefined;
|
|
14
|
-
}>, {
|
|
15
|
-
source: string;
|
|
16
|
-
maxlength: number;
|
|
17
|
-
multiline: boolean;
|
|
18
|
-
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
19
|
-
declare const _default: typeof __VLS_export;
|
|
20
|
-
export default _default;
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import type { TranslationTargetType } from "@liujitcn/kratos-admin-system/rpc/system/admin/v1/base_i18n";
|
|
2
|
-
/** DynamicTranslationValue 动态资源单语言翻译编辑状态。 */
|
|
3
|
-
export interface DynamicTranslationValue {
|
|
4
|
-
/** 语言代码。 */
|
|
5
|
-
locale: string;
|
|
6
|
-
text: string;
|
|
7
|
-
id: number;
|
|
8
|
-
}
|
|
9
|
-
/** DynamicTranslationRecord 描述三类动态资源翻译共有字段。 */
|
|
10
|
-
export interface DynamicTranslationRecord extends Omit<DynamicTranslationValue, "text"> {
|
|
11
|
-
target_type?: TranslationTargetType;
|
|
12
|
-
target_id?: number;
|
|
13
|
-
name?: string;
|
|
14
|
-
/** 兼容旧接口缓存中的字段名。 */
|
|
15
|
-
title?: string;
|
|
16
|
-
label?: string;
|
|
17
|
-
}
|
|
18
|
-
/** DynamicLanguageOption 动态翻译编辑器显示的语言选项。 */
|
|
19
|
-
export interface DynamicLanguageOption {
|
|
20
|
-
/** 语言代码。 */
|
|
21
|
-
value: string;
|
|
22
|
-
/** 语言显示名称。 */
|
|
23
|
-
label: string;
|
|
24
|
-
}
|
|
25
|
-
/** 返回语言管理中启用且非主语言的翻译语言选项。 */
|
|
26
|
-
export declare function getEditableLanguageOptions(): DynamicLanguageOption[];
|
|
27
|
-
/** 返回语言管理中的语言显示名称。 */
|
|
28
|
-
export declare function getLanguageLabel(locale: string): string;
|
|
29
|
-
/** normalizeDynamicTranslations 将后端翻译记录补齐为全部非主语言编辑状态。 */
|
|
30
|
-
export declare function normalizeDynamicTranslations(records: DynamicTranslationRecord[] | undefined, _textField: "title" | "name" | "label", locales?: string[]): DynamicTranslationValue[];
|
|
31
|
-
/** serializeDynamicTranslations 将编辑状态转换回后端资源翻译结构。 */
|
|
32
|
-
export declare function serializeDynamicTranslations(values: DynamicTranslationValue[], targetType: TranslationTargetType, targetId: number): Array<{
|
|
33
|
-
id: number;
|
|
34
|
-
target_type: TranslationTargetType;
|
|
35
|
-
target_id: number;
|
|
36
|
-
locale: string;
|
|
37
|
-
name: string;
|
|
38
|
-
}>;
|