@liujitcn/kratos-admin-system 0.0.27 → 0.0.29

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 (52) hide show
  1. package/README.md +1 -1
  2. package/dist/package/declarations/src/api/system/base_i18n.d.ts +5 -5
  3. package/dist/package/declarations/src/api/system/runtime_log.d.ts +13 -0
  4. package/dist/package/declarations/src/api/system/runtime_log_sse.d.ts +8 -0
  5. package/dist/package/declarations/src/components/DynamicI18nCell.vue.d.ts +16 -0
  6. package/dist/package/declarations/src/components/DynamicI18nEditor.vue.d.ts +20 -0
  7. package/dist/package/declarations/src/components/dynamicI18n.d.ts +38 -0
  8. package/dist/package/declarations/src/locales/generated.d.ts +168 -52
  9. package/dist/package/declarations/src/rpc/system/admin/v1/base_config.d.ts +3 -3
  10. package/dist/package/declarations/src/rpc/system/admin/v1/base_dict.d.ts +4 -4
  11. package/dist/package/declarations/src/rpc/system/admin/v1/base_i18n.d.ts +23 -23
  12. package/dist/package/declarations/src/rpc/system/admin/v1/base_menu.d.ts +2 -2
  13. package/dist/package/declarations/src/rpc/system/admin/v1/code_gen.d.ts +1 -1
  14. package/dist/package/declarations/src/rpc/system/admin/v1/ops_monitoring.d.ts +4 -0
  15. package/dist/package/declarations/src/rpc/system/admin/v1/project_document.d.ts +4 -6
  16. package/dist/package/declarations/src/rpc/system/admin/v1/runtime_log.d.ts +96 -0
  17. package/dist/package/declarations/src/views/tool/runtime-log/index.vue.d.ts +3 -0
  18. package/dist/package/src/api/system/base_i18n.ts +12 -12
  19. package/dist/package/src/api/system/runtime_log.ts +80 -0
  20. package/dist/package/src/api/system/runtime_log_sse.ts +40 -0
  21. package/dist/package/src/components/{DynamicTranslationCell.vue → DynamicI18nCell.vue} +50 -50
  22. package/dist/package/src/components/{DynamicTranslationEditor.vue → DynamicI18nEditor.vue} +45 -45
  23. package/dist/package/src/components/{dynamicTranslation.ts → dynamicI18n.ts} +15 -15
  24. package/dist/package/src/locales/README.md +1 -1
  25. package/dist/package/src/locales/en-US.json +46 -17
  26. package/dist/package/src/locales/ja-JP.json +44 -15
  27. package/dist/package/src/locales/zh-CN.json +44 -15
  28. package/dist/package/src/locales/zh-TW.json +44 -15
  29. package/dist/package/src/rpc/system/admin/v1/base_config.ts +3 -3
  30. package/dist/package/src/rpc/system/admin/v1/base_dict.ts +4 -4
  31. package/dist/package/src/rpc/system/admin/v1/base_i18n.ts +23 -23
  32. package/dist/package/src/rpc/system/admin/v1/base_menu.ts +2 -2
  33. package/dist/package/src/rpc/system/admin/v1/code_gen.ts +1 -1
  34. package/dist/package/src/rpc/system/admin/v1/ops_monitoring.ts +4 -0
  35. package/dist/package/src/rpc/system/admin/v1/project_document.ts +4 -7
  36. package/dist/package/src/rpc/system/admin/v1/runtime_log.ts +113 -0
  37. package/dist/package/src/views/base/config/index.vue +38 -38
  38. package/dist/package/src/views/base/dict/index.vue +23 -23
  39. package/dist/package/src/views/base/dict/item.vue +25 -25
  40. package/dist/package/src/views/base/menu/index.vue +23 -23
  41. package/dist/package/src/views/tool/api-doc/index.vue +14 -6
  42. package/dist/package/src/views/tool/code-gen/code-preview/index.vue +23 -6
  43. package/dist/package/src/views/tool/code-gen/columns/index.vue +1 -1
  44. package/dist/package/src/views/tool/code-gen/components/CodeGenLocaleEditor.vue +96 -14
  45. package/dist/package/src/views/tool/code-gen/table/index.vue +33 -1
  46. package/dist/package/src/views/tool/ops-monitoring/index.vue +130 -24
  47. package/dist/package/src/views/tool/project-doc/index.vue +9 -4
  48. package/dist/package/src/views/tool/runtime-log/index.vue +883 -0
  49. package/package.json +2 -2
  50. package/dist/package/declarations/src/components/DynamicTranslationCell.vue.d.ts +0 -16
  51. package/dist/package/declarations/src/components/DynamicTranslationEditor.vue.d.ts +0 -20
  52. package/dist/package/declarations/src/components/dynamicTranslation.d.ts +0 -38
@@ -189,10 +189,22 @@
189
189
  <code>{{ node.name }}</code>
190
190
  <div class="ops-node-meters">
191
191
  <div v-for="metric in node.metrics" :key="metric.label" class="ops-meter">
192
- <span>{{ metric.label }}</span
193
- ><el-progress :percentage="metric.value" :show-text="false" :color="metric.color" /><strong
194
- >{{ metric.value }}%</strong
195
- >
192
+ <div class="ops-meter-head">
193
+ <span class="ops-meter-label">{{ metric.label }}</span>
194
+ <span class="ops-meter-stats">
195
+ <span>
196
+ {{ t("system.ops_monitoring.node_metric.current") }} {{ metric.usedLabel }} /
197
+ {{ t("system.ops_monitoring.node_metric.total") }} {{ metric.totalLabel }}
198
+ </span>
199
+ <strong>{{ metric.percentageLabel }}</strong>
200
+ </span>
201
+ </div>
202
+ <el-progress
203
+ :percentage="metric.percentage"
204
+ :show-text="false"
205
+ :stroke-width="10"
206
+ :color="metric.color"
207
+ />
196
208
  </div>
197
209
  </div>
198
210
  </div>
@@ -278,12 +290,28 @@ interface EndpointItem {
278
290
  healthy: boolean;
279
291
  }
280
292
 
281
- /** 实例资源指标。 */
293
+ /** 实例资源单项指标。 */
294
+ interface NodeMetricItem {
295
+ /** 指标名称。 */
296
+ label: string;
297
+ /** 指标使用百分比。 */
298
+ percentage: number;
299
+ /** 两位小数百分比。 */
300
+ percentageLabel: string;
301
+ /** 当前已用容量。 */
302
+ usedLabel: string;
303
+ /** 总容量。 */
304
+ totalLabel: string;
305
+ /** 进度条颜色。 */
306
+ color: string;
307
+ }
308
+
309
+ /** 实例资源信息。 */
282
310
  interface NodeItem {
283
311
  /** 实例名称。 */
284
312
  name: string;
285
313
  /** 实例资源指标。 */
286
- metrics: Array<{ label: string; value: number; color: string }>;
314
+ metrics: NodeMetricItem[];
287
315
  }
288
316
 
289
317
  /** 折线图中的流量趋势点。 */
@@ -334,6 +362,12 @@ const alerts = ref<OpsAlertsResponse>();
334
362
  const windowMinutes = ref(15);
335
363
  const lastCollectedAt = ref("");
336
364
  const trendGridLines = [16, 62, 108, 154, 198];
365
+ const nodeMetricLabelKeys: Record<string, string> = {
366
+ 堆内存: "system.ops_monitoring.node_metric.heap_memory",
367
+ 内存: "system.ops_monitoring.node_metric.memory",
368
+ 硬盘: "system.ops_monitoring.node_metric.disk"
369
+ };
370
+ const byteUnits = ["B", "KB", "MB", "GB", "TB", "PB"];
337
371
  const trafficSummary = computed(() => traffic.value?.traffic);
338
372
 
339
373
  const kpiItems = computed<KpiItem[]>(() => [
@@ -579,14 +613,46 @@ function mapEndpoint(endpoint: OpsEndpoint): EndpointItem {
579
613
  function mapNode(node: OpsNode): NodeItem {
580
614
  return {
581
615
  name: node.name,
582
- metrics: (node.metrics ?? []).map(metric => ({
583
- label: metric.label,
584
- value: Math.max(0, Math.min(metric.value, 100)),
585
- color: metric.value >= 70 ? "var(--el-color-warning)" : "var(--el-color-primary)"
586
- }))
616
+ metrics: (node.metrics ?? []).map(metric => {
617
+ const percentage = Math.max(0, Math.min(metric.value, 100));
618
+ return {
619
+ label: translateNodeMetricLabel(metric.label),
620
+ percentage,
621
+ percentageLabel: `${formatFixedNumber(percentage)}%`,
622
+ usedLabel: formatBytes(metric.used_bytes),
623
+ totalLabel: formatBytes(metric.total_bytes),
624
+ color: percentage >= 70 ? "var(--el-color-warning)" : "var(--el-color-primary)"
625
+ };
626
+ })
587
627
  };
588
628
  }
589
629
 
630
+ /** 将字节数格式化为保留两位小数的可读容量。 */
631
+ function formatBytes(value: number) {
632
+ if (!Number.isFinite(value) || value < 0) return "--";
633
+ let unitIndex = 0;
634
+ let displayValue = value;
635
+ while (displayValue >= 1024 && unitIndex < byteUnits.length - 1) {
636
+ displayValue /= 1024;
637
+ unitIndex += 1;
638
+ }
639
+ return `${formatFixedNumber(displayValue)} ${byteUnits[unitIndex]}`;
640
+ }
641
+
642
+ /** 将数值格式化为固定两位小数。 */
643
+ function formatFixedNumber(value: number) {
644
+ return new Intl.NumberFormat(getCurrentLocale(), {
645
+ minimumFractionDigits: 2,
646
+ maximumFractionDigits: 2
647
+ }).format(value);
648
+ }
649
+
650
+ /** 翻译实例资源指标名称,未知指标保留后端原值。 */
651
+ function translateNodeMetricLabel(label: string) {
652
+ const localeKey = nodeMetricLabelKeys[label];
653
+ return localeKey ? t(localeKey) : label;
654
+ }
655
+
590
656
  function mapAlert(alert: OpsAlert) {
591
657
  return {
592
658
  title: alert.title,
@@ -654,6 +720,7 @@ onBeforeUnmount(stopMonitoring);
654
720
  .ops-panel,
655
721
  .ops-storage-card,
656
722
  .ops-alert-panel {
723
+ min-width: 0;
657
724
  background: var(--ops-card-bg);
658
725
  border: 1px solid var(--ops-card-border);
659
726
  border-radius: var(--admin-page-radius);
@@ -934,7 +1001,7 @@ onBeforeUnmount(stopMonitoring);
934
1001
  margin-bottom: 12px;
935
1002
  }
936
1003
  .ops-storage-grid {
937
- grid-template-columns: repeat(2, minmax(0, 1fr));
1004
+ grid-template-columns: minmax(0, 1.4fr) minmax(280px, 0.9fr);
938
1005
  }
939
1006
  .ops-storage-card {
940
1007
  min-width: 0;
@@ -1040,37 +1107,70 @@ onBeforeUnmount(stopMonitoring);
1040
1107
  .ops-node-list {
1041
1108
  display: grid;
1042
1109
  gap: 16px;
1110
+ min-width: 0;
1043
1111
  padding-top: 3px;
1044
1112
  }
1045
1113
  .ops-node-row {
1046
1114
  display: grid;
1047
- grid-template-columns: 95px minmax(0, 1fr);
1048
- gap: 10px;
1049
- align-items: center;
1115
+ grid-template-columns: minmax(110px, 0.24fr) minmax(0, 1fr);
1116
+ gap: 18px;
1117
+ align-items: start;
1118
+ min-width: 0;
1050
1119
  }
1051
1120
  .ops-node-row > code {
1121
+ overflow: hidden;
1052
1122
  font-family: var(--el-font-family-monospace);
1053
1123
  font-size: 11px;
1054
1124
  color: var(--ops-text-secondary);
1125
+ text-overflow: ellipsis;
1126
+ white-space: nowrap;
1055
1127
  }
1056
1128
  .ops-node-meters {
1057
1129
  display: grid;
1058
- gap: 7px;
1130
+ gap: 13px;
1131
+ min-width: 0;
1059
1132
  }
1060
1133
  .ops-meter {
1061
1134
  display: grid;
1062
- grid-template-columns: 34px minmax(0, 1fr) 35px;
1063
1135
  gap: 7px;
1064
- align-items: center;
1065
- font-size: 10px;
1136
+ min-width: 0;
1137
+ font-size: 11px;
1066
1138
  color: var(--ops-text-placeholder);
1067
1139
  }
1068
- .ops-meter strong {
1069
- font-size: 11px;
1070
- font-weight: 500;
1140
+ .ops-meter-head,
1141
+ .ops-meter-stats {
1142
+ display: flex;
1143
+ flex-wrap: wrap;
1144
+ gap: 4px 10px;
1145
+ min-width: 0;
1146
+ align-items: center;
1147
+ justify-content: space-between;
1148
+ }
1149
+ .ops-meter-label {
1150
+ flex: none;
1151
+ font-weight: 600;
1071
1152
  color: var(--ops-text-secondary);
1153
+ }
1154
+ .ops-meter-stats {
1155
+ flex: 1;
1156
+ justify-content: flex-end;
1072
1157
  text-align: right;
1073
1158
  }
1159
+ .ops-meter-stats > span {
1160
+ overflow-wrap: anywhere;
1161
+ }
1162
+ .ops-meter-stats strong {
1163
+ flex: none;
1164
+ font-size: 11px;
1165
+ font-weight: 650;
1166
+ color: var(--ops-text-secondary);
1167
+ font-variant-numeric: tabular-nums;
1168
+ }
1169
+ .ops-meter :deep(.el-progress),
1170
+ .ops-meter :deep(.el-progress-bar) {
1171
+ min-width: 0;
1172
+ width: 100%;
1173
+ }
1074
1174
  .ops-alert-panel {
1075
1175
  margin-bottom: 0;
1076
1176
  }
@@ -1125,6 +1225,7 @@ onBeforeUnmount(stopMonitoring);
1125
1225
  grid-template-columns: repeat(2, minmax(0, 1fr));
1126
1226
  }
1127
1227
  .ops-primary-grid,
1228
+ .ops-storage-grid,
1128
1229
  .ops-secondary-grid {
1129
1230
  grid-template-columns: 1fr;
1130
1231
  }
@@ -1159,8 +1260,13 @@ onBeforeUnmount(stopMonitoring);
1159
1260
  margin-left: 54px;
1160
1261
  }
1161
1262
  .ops-node-row {
1162
- grid-template-columns: 82px minmax(0, 1fr);
1163
- gap: 7px;
1263
+ grid-template-columns: 1fr;
1264
+ gap: 10px;
1265
+ }
1266
+ .ops-meter-stats {
1267
+ flex-basis: 100%;
1268
+ justify-content: flex-start;
1269
+ text-align: left;
1164
1270
  }
1165
1271
  .ops-alert-row {
1166
1272
  grid-template-columns: 8px minmax(0, 1fr);
@@ -72,7 +72,7 @@
72
72
  import { computed, nextTick, onMounted, ref, watch } from "vue";
73
73
  import { Search } from "@element-plus/icons-vue";
74
74
  import type { TreeNodeData } from "element-plus";
75
- import { getCurrentLocale, t } from "@liujitcn/kratos-admin-core";
75
+ import { getCurrentLocale, t, useLocaleStore } from "@liujitcn/kratos-admin-core";
76
76
  import MarkdownPreview from "@liujitcn/kratos-admin-core/components/MarkdownPreview/index.vue";
77
77
  import { useGlobalStore } from "@liujitcn/kratos-admin-core/stores/runtime";
78
78
  import { defProjectDocumentService } from "@liujitcn/kratos-admin-system/api/system/project_document";
@@ -112,6 +112,7 @@ interface ProjectDocumentTreeNode {
112
112
  }
113
113
 
114
114
  const globalStore = useGlobalStore();
115
+ const { locale } = useLocaleStore();
115
116
  const loading = ref(false);
116
117
  const detailLoading = ref(false);
117
118
  const keyword = ref("");
@@ -137,11 +138,11 @@ const filteredDocumentCount = computed(() => {
137
138
  const search = keyword.value.trim().toLocaleLowerCase();
138
139
  if (!search) return documents.value.length;
139
140
  return documents.value.filter(node =>
140
- [node.projectKey, node.projectName, node.path].some(value => value.toLocaleLowerCase().includes(search))
141
+ [node.label, node.projectKey, node.projectName, node.path].some(value => value.toLocaleLowerCase().includes(search))
141
142
  ).length;
142
143
  });
143
144
  const selectedDocumentNodeKey = computed(() => (selectedDocumentId.value ? buildDocumentNodeKey(selectedDocumentId.value) : ""));
144
- const selectedDocumentName = computed(() => selectedDocument.value?.path.split("/").at(-1) ?? "");
145
+ const selectedDocumentName = computed(() => selectedDocument.value?.name ?? "");
145
146
  const selectedDocumentUpdatedAt = computed(
146
147
  () => documents.value.find(node => node.document?.id === selectedDocumentId.value)?.document?.updated_at ?? ""
147
148
  );
@@ -321,7 +322,7 @@ function buildDocumentTreeNode(
321
322
  ): ProjectDocumentTreeNode {
322
323
  return {
323
324
  key: buildDocumentNodeKey(document.id),
324
- label: document.path.split("/").at(-1) ?? document.path,
325
+ label: document.name,
325
326
  kind: "document",
326
327
  projectKey,
327
328
  projectName,
@@ -352,6 +353,10 @@ watch(keyword, value => {
352
353
  documentTreeRef.value?.filter(value);
353
354
  });
354
355
 
356
+ watch(locale, () => {
357
+ void loadDocuments();
358
+ });
359
+
355
360
  onMounted(() => {
356
361
  void loadDocuments();
357
362
  });