befly-admin-ui 1.8.33 → 1.8.34

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "befly-admin-ui",
3
- "version": "1.8.33",
4
- "gitHead": "84b6e4e0adde7f566cfc890887b024ccf10b0516",
3
+ "version": "1.8.34",
4
+ "gitHead": "c47d1e515dabe142531e0a8415979cccb2729259",
5
5
  "private": false,
6
6
  "description": "Befly - 管理后台功能组件",
7
7
  "keywords": [
@@ -49,10 +49,10 @@
49
49
  <div class="card-title">统计信息</div>
50
50
  </div>
51
51
 
52
- <div class="product-switch-list">
53
- <button v-for="item in productOptions" :key="item.key" type="button" class="product-switch" :class="{ active: item.key === selectedProduct?.key }" @click="selectProduct(item.key)">
54
- <span class="product-switch-name">{{ item.productName }}</span>
55
- </button>
52
+ <div class="product-select-wrap">
53
+ <TSelect :model-value="productState.selectedKey" class="product-select" placeholder="请选择产品" @change="selectProduct">
54
+ <TOption v-for="item in productOptions" :key="item.key" :value="item.key" :label="item.productName" />
55
+ </TSelect>
56
56
  </div>
57
57
  </div>
58
58
 
@@ -191,6 +191,7 @@
191
191
 
192
192
  <script setup>
193
193
  import { computed, reactive } from "vue";
194
+ import { Option as TOption, Select as TSelect } from "tdesign-vue-next";
194
195
  import { InfoCircleIcon, TrendingUpIcon } from "tdesign-icons-vue-next";
195
196
 
196
197
  import { $Config } from "@/plugins/config";
@@ -250,12 +251,29 @@ const errorTodayCount = computed(() => {
250
251
 
251
252
  const productOptions = computed(() => {
252
253
  const list = Array.isArray(productState.options) ? productState.options.slice() : [];
254
+ const fallbackProduct = buildFallbackProduct();
253
255
 
254
- if (list.length > 0) {
255
- return list;
256
+ if (list.length === 0) {
257
+ return [fallbackProduct];
256
258
  }
257
259
 
258
- return [buildFallbackProduct()];
260
+ list.sort((a, b) => {
261
+ if (a.productName === productInfo.productName && b.productName !== productInfo.productName) {
262
+ return -1;
263
+ }
264
+
265
+ if (b.productName === productInfo.productName && a.productName !== productInfo.productName) {
266
+ return 1;
267
+ }
268
+
269
+ if (Number(b.totalPv || 0) !== Number(a.totalPv || 0)) {
270
+ return Number(b.totalPv || 0) - Number(a.totalPv || 0);
271
+ }
272
+
273
+ return String(a.productName || "").localeCompare(String(b.productName || ""), "zh-CN");
274
+ });
275
+
276
+ return [fallbackProduct, ...list];
259
277
  });
260
278
 
261
279
  const selectedProduct = computed(() => {
@@ -269,31 +287,6 @@ const selectedProduct = computed(() => {
269
287
  return matched || list[0];
270
288
  });
271
289
 
272
- const selectedProductToday = computed(() => {
273
- return (
274
- selectedProduct.value?.today || {
275
- pv: 0,
276
- uv: 0
277
- }
278
- );
279
- });
280
-
281
- const selectedProductTotalPv = computed(() => {
282
- if (selectedProduct.value?.totalPv !== undefined) {
283
- return Number(selectedProduct.value.totalPv || 0);
284
- }
285
-
286
- return sumTrendField(selectedProduct.value?.days || [], "pv");
287
- });
288
-
289
- const selectedProductTotalUv = computed(() => {
290
- if (selectedProduct.value?.totalUv !== undefined) {
291
- return Number(selectedProduct.value.totalUv || 0);
292
- }
293
-
294
- return sumTrendField(selectedProduct.value?.days || [], "uv");
295
- });
296
-
297
290
  const selectedDaysTrend = computed(() => sortTrendList(selectedProduct.value?.days || [], "reportDate"));
298
291
  const selectedDaysFilled = computed(() => buildFilledTrendDays(selectedProduct.value?.days || [], 30));
299
292
  const selectedDaysHasData = computed(() => selectedDaysTrend.value.length > 0);
@@ -321,7 +314,7 @@ function buildFallbackProduct() {
321
314
 
322
315
  return {
323
316
  key: "all-products",
324
- productName: productInfo.productName,
317
+ productName: "全部产品",
325
318
  productCode: productInfo.productCode,
326
319
  productVersion: productInfo.productVersion,
327
320
  today: {
@@ -406,8 +399,8 @@ function ensureSelectedProduct() {
406
399
  return;
407
400
  }
408
401
 
409
- const currentProduct = list.find((item) => item.productCode === productInfo.productCode && item.productVersion === productInfo.productVersion);
410
- productState.selectedKey = currentProduct?.key || list[0].key;
402
+ const currentProduct = list.find((item) => item.productName === productInfo.productName);
403
+ productState.selectedKey = currentProduct?.key || "all-products";
411
404
  }
412
405
 
413
406
  function selectProduct(productKey) {
@@ -538,7 +531,55 @@ const fetchData = async () => {
538
531
  realtimeStats.todayPv = Number(onlineStatsRes.data?.today?.pv || 0);
539
532
  realtimeStats.todayUv = Number(onlineStatsRes.data?.today?.uv || 0);
540
533
  realtimeStats.days = Array.isArray(onlineStatsRes.data?.days) ? onlineStatsRes.data.days : [];
541
- productState.options = [];
534
+ productInfo.productName = String($Config.productName || "-");
535
+ productInfo.productCode = String($Config.productCode || "-");
536
+ productInfo.productVersion = String($Config.productVersion || "-");
537
+ productState.options = Array.isArray(onlineStatsRes.data?.products)
538
+ ? onlineStatsRes.data.products.map((item) => {
539
+ return {
540
+ key: String(item?.key || item?.productName || ""),
541
+ productName: String(item?.productName || "-"),
542
+ today: {
543
+ pv: Number(item?.today?.pv || 0),
544
+ uv: Number(item?.today?.uv || 0)
545
+ },
546
+ week: {
547
+ pv: Number(item?.week?.pv || 0),
548
+ uv: Number(item?.week?.uv || 0)
549
+ },
550
+ month: {
551
+ pv: Number(item?.month?.pv || 0),
552
+ uv: Number(item?.month?.uv || 0)
553
+ },
554
+ days: Array.isArray(item?.days) ? item.days : [],
555
+ totalPv: Number(item?.totalPv || 0),
556
+ totalUv: Number(item?.totalUv || 0)
557
+ };
558
+ })
559
+ : [];
560
+ if (Array.isArray(infoStatsRes.data?.month?.productNames) && infoStatsRes.data.month.productNames.length === 1 && productInfo.productName !== "-") {
561
+ productState.options = [
562
+ {
563
+ key: productInfo.productName,
564
+ productName: productInfo.productName,
565
+ today: {
566
+ pv: realtimeStats.todayPv,
567
+ uv: realtimeStats.todayUv
568
+ },
569
+ week: {
570
+ pv: Number(onlineStatsRes.data?.week?.pv || 0),
571
+ uv: Number(onlineStatsRes.data?.week?.uv || 0)
572
+ },
573
+ month: {
574
+ pv: Number(onlineStatsRes.data?.month?.pv || 0),
575
+ uv: Number(onlineStatsRes.data?.month?.uv || 0)
576
+ },
577
+ days: realtimeStats.days,
578
+ totalPv: sumTrendField(realtimeStats.days, "pv"),
579
+ totalUv: sumTrendField(realtimeStats.days, "uv")
580
+ }
581
+ ];
582
+ }
542
583
  uaStats.deviceTypes = Array.isArray(infoStatsRes.data?.today?.deviceTypes) ? infoStatsRes.data.today.deviceTypes : [];
543
584
  uaStats.browsers = Array.isArray(infoStatsRes.data?.today?.browsers) ? infoStatsRes.data.today.browsers : [];
544
585
  uaStats.browserVersions = Array.isArray(infoStatsRes.data?.today?.browserVersions) ? infoStatsRes.data.today.browserVersions : [];
@@ -549,9 +590,6 @@ const fetchData = async () => {
549
590
  uaStats.engines = Array.isArray(infoStatsRes.data?.today?.engines) ? infoStatsRes.data.today.engines : [];
550
591
  uaStats.cpuArchitectures = Array.isArray(infoStatsRes.data?.today?.cpuArchitectures) ? infoStatsRes.data.today.cpuArchitectures : [];
551
592
  errorStats.trend = Array.isArray(errorStatsRes.data?.trend) ? errorStatsRes.data.trend : [];
552
- productInfo.productName = String($Config.productName || "-");
553
- productInfo.productCode = String($Config.productCode || "-");
554
- productInfo.productVersion = String($Config.productVersion || "-");
555
593
  ensureSelectedProduct();
556
594
  } catch (_error) {
557
595
  // 静默失败:不阻断页面展示
@@ -710,47 +748,13 @@ fetchData();
710
748
  color: var(--text-primary);
711
749
  }
712
750
 
713
- .product-switch-list {
751
+ .product-select-wrap {
714
752
  display: flex;
715
- flex-wrap: wrap;
716
753
  justify-content: flex-end;
717
- gap: 8px;
718
754
  }
719
755
 
720
- .product-switch {
721
- display: inline-flex;
722
- align-items: center;
723
- justify-content: center;
724
- min-width: 0;
725
- min-height: 36px;
726
- padding: 0 12px;
727
- border: 1px solid rgba(0, 0, 0, 0.08);
728
- border-radius: 8px;
729
- background: rgba(255, 255, 255, 0.88);
730
- color: var(--text-primary);
731
- cursor: pointer;
732
- transition: all 0.2s ease;
733
-
734
- &:hover {
735
- border-color: rgba(var(--primary-color-rgb), 0.3);
736
- background: rgba(var(--primary-color-rgb), 0.05);
737
- }
738
-
739
- &.active {
740
- border-color: rgba(var(--primary-color-rgb), 0.45);
741
- background: rgba(var(--primary-color-rgb), 0.08);
742
- box-shadow: inset 0 0 0 1px rgba(var(--primary-color-rgb), 0.08);
743
- }
744
- }
745
-
746
- .product-switch-name {
747
- max-width: 160px;
748
- overflow: hidden;
749
- text-overflow: ellipsis;
750
- white-space: nowrap;
751
- font-size: 12px;
752
- font-weight: 600;
753
- letter-spacing: 0.2px;
756
+ .product-select {
757
+ width: 220px;
754
758
  }
755
759
 
756
760
  .product-metrics-grid {
@@ -1100,7 +1104,8 @@ fetchData();
1100
1104
  align-items: flex-start;
1101
1105
  }
1102
1106
 
1103
- .product-switch-list {
1107
+ .product-select-wrap {
1108
+ width: 100%;
1104
1109
  justify-content: flex-start;
1105
1110
  }
1106
1111
 
@@ -1128,7 +1133,7 @@ fetchData();
1128
1133
  min-height: 0;
1129
1134
  }
1130
1135
 
1131
- .product-switch {
1136
+ .product-select {
1132
1137
  width: 100%;
1133
1138
  }
1134
1139