@jx3box/jx3box-ui 2.3.19 → 2.3.20

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,6 +1,6 @@
1
1
  {
2
2
  "name": "@jx3box/jx3box-ui",
3
- "version": "2.3.19",
3
+ "version": "2.3.20",
4
4
  "description": "JX3BOX Vue3 UI",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -11,30 +11,67 @@
11
11
  </template>
12
12
  <script>
13
13
  import JX3BOX from "@jx3box/jx3box-common/data/jx3box.json";
14
+ import { getUserHonor } from "../../service/cms";
14
15
  import { inRange } from "lodash";
15
16
 
16
17
  const { __cdn, __Root } = JX3BOX;
17
18
  export default {
18
19
  props: {
20
+ uid: {
21
+ type: [Number, String],
22
+ default: 0,
23
+ },
19
24
  honor: {
20
25
  type: Object,
21
- default: null,
22
26
  },
23
27
  },
28
+ data: function () {
29
+ return {
30
+ legacyHonor: null,
31
+ honorRequestId: 0,
32
+ };
33
+ },
24
34
  computed: {
25
35
  displayHonor() {
26
- return this.formatHonor(this.honor);
36
+ const honor = this.honor !== undefined ? this.honor : this.legacyHonor;
37
+ return this.formatHonor(honor);
38
+ },
39
+ legacyRequestKey() {
40
+ return this.honor === undefined && this.uid ? String(this.uid) : "";
27
41
  },
28
42
  url() {
29
43
  return this.displayHonor?.honor_info?.url ? __Root + this.displayHonor.honor_info.url : "";
30
44
  },
31
45
  },
46
+ watch: {
47
+ legacyRequestKey: {
48
+ immediate: true,
49
+ handler(key) {
50
+ this.loadLegacyHonor(key);
51
+ },
52
+ },
53
+ },
32
54
  methods: {
33
55
  imgUrl: function () {
34
56
  let item = this.displayHonor?.honor_info;
35
57
  if (!item) return;
36
58
  return __cdn + `design/decoration/honor/${item.img}/${item.img}.${item.img_ext || "png"}`;
37
59
  },
60
+ loadLegacyHonor(key) {
61
+ const requestId = ++this.honorRequestId;
62
+ this.legacyHonor = null;
63
+ if (!key) return;
64
+
65
+ getUserHonor(this.uid)
66
+ .then((res) => {
67
+ if (requestId !== this.honorRequestId || key !== this.legacyRequestKey) return;
68
+ this.legacyHonor = res?.data?.data || null;
69
+ })
70
+ .catch(() => {
71
+ if (requestId !== this.honorRequestId || key !== this.legacyRequestKey) return;
72
+ this.legacyHonor = null;
73
+ });
74
+ },
38
75
  formatHonor(honor) {
39
76
  if (!honor?.honor_info) return null;
40
77
  const data = { ...honor };
@@ -63,7 +63,7 @@
63
63
  </div>
64
64
  </div>
65
65
  </div>
66
- <Honor :honor="honor"></Honor>
66
+ <Honor :uid="uid" :honor="honor"></Honor>
67
67
  <div class="u-bio">{{ data.user_bio }}</div>
68
68
  </div>
69
69
  </template>
@@ -93,7 +93,6 @@ export default {
93
93
  },
94
94
  honor: {
95
95
  type: Object,
96
- default: null,
97
96
  },
98
97
  },
99
98
  components: {
@@ -4,13 +4,13 @@
4
4
  <img svg-inline src="../../assets/img/leftsidebar/medal.svg" />
5
5
  <span>{{ $jx3boxT("jx3boxUi.authorMedals.title", "作者荣誉") }}</span>
6
6
  </div>
7
- <div class="u-medals" v-if="medals && medals.length">
7
+ <div class="u-medals" v-if="displayMedals.length">
8
8
  <el-tooltip
9
9
  class="item"
10
10
  effect="dark"
11
11
  :content="item.medal_desc"
12
12
  placement="top"
13
- v-for="item in medals"
13
+ v-for="item in displayMedals"
14
14
  :key="item.id"
15
15
  >
16
16
  <a :href="getMedalLink(item)" target="_blank" class="u-medal">
@@ -24,6 +24,7 @@
24
24
  <script>
25
25
  import * as utilModule from "@jx3box/jx3box-common/js/utils";
26
26
  const { getMedalLink } = utilModule;
27
+ import { getUserMedals } from "../../service/author";
27
28
  import JX3BOX from "@jx3box/jx3box-common/data/jx3box.json";
28
29
  import i18nMixin from "../../i18n/mixin";
29
30
  const { __cdn, __Root } = JX3BOX;
@@ -32,18 +33,59 @@ export default {
32
33
  name: "AuthorMedals",
33
34
  mixins: [i18nMixin],
34
35
  props: {
36
+ uid: {
37
+ type: [Number, String],
38
+ default: 0,
39
+ },
35
40
  medals: {
36
41
  type: Array,
37
- default: () => [],
38
42
  },
39
43
  },
40
44
  components: {},
45
+ data: function () {
46
+ return {
47
+ legacyMedals: [],
48
+ medalsRequestId: 0,
49
+ };
50
+ },
41
51
  computed: {
52
+ displayMedals: function () {
53
+ if (this.medals !== undefined) {
54
+ return Array.isArray(this.medals) ? this.medals : [];
55
+ }
56
+ return this.legacyMedals;
57
+ },
58
+ legacyRequestKey: function () {
59
+ return this.medals === undefined && this.uid ? String(this.uid) : "";
60
+ },
42
61
  ready: function () {
43
- return this.medals && this.medals.length;
62
+ return this.displayMedals.length;
63
+ },
64
+ },
65
+ watch: {
66
+ legacyRequestKey: {
67
+ immediate: true,
68
+ handler: function (key) {
69
+ this.loadLegacyMedals(key);
70
+ },
44
71
  },
45
72
  },
46
73
  methods: {
74
+ loadLegacyMedals: function (key) {
75
+ const requestId = ++this.medalsRequestId;
76
+ this.legacyMedals = [];
77
+ if (!key) return;
78
+
79
+ getUserMedals(this.uid, { is_wear: 1 })
80
+ .then((data) => {
81
+ if (requestId !== this.medalsRequestId || key !== this.legacyRequestKey) return;
82
+ this.legacyMedals = Array.isArray(data) ? data : [];
83
+ })
84
+ .catch(() => {
85
+ if (requestId !== this.medalsRequestId || key !== this.legacyRequestKey) return;
86
+ this.legacyMedals = [];
87
+ });
88
+ },
47
89
  showIcon(medal) {
48
90
  return __cdn + "design/medals/user/" + medal + ".webp";
49
91
  },
@@ -63,7 +105,7 @@ export default {
63
105
  .u-medals {
64
106
  display: flex;
65
107
  flex-wrap: wrap;
66
- gap:5px;
108
+ gap: 5px;
67
109
  margin-top: 5px;
68
110
  }
69
111
  .u-medal {
@@ -31,15 +31,41 @@ assert(author.includes('item?.type === "medals"'), "Author should read active me
31
31
 
32
32
  assert(author.includes(':medals="activeMedals"'), "Author should pass active medals to AuthorMedals");
33
33
 
34
- assert(!authorMedals.includes("getUserMedals"), "AuthorMedals should not request medals independently");
34
+ assert(authorMedals.includes("getUserMedals"), "AuthorMedals should retain the legacy uid endpoint");
35
35
 
36
- assert(!authorMedals.includes("getUserMedals"), "AuthorMedals should not request the legacy medal endpoint");
36
+ assert(
37
+ authorMedals.includes("this.medals === undefined && this.uid"),
38
+ "AuthorMedals should only use the legacy endpoint when the new medals prop is absent"
39
+ );
37
40
 
38
- assert(authorInfo.includes(':honor="honor"'), "AuthorInfo should pass the active honor to AuthorHonor");
41
+ assert(
42
+ authorMedals.includes("requestId !== this.medalsRequestId"),
43
+ "AuthorMedals should ignore stale legacy endpoint responses"
44
+ );
45
+
46
+ assert(
47
+ authorInfo.includes('<Honor :uid="uid" :honor="honor">'),
48
+ "AuthorInfo should pass both the legacy uid and the active honor to AuthorHonor"
49
+ );
50
+
51
+ assert(
52
+ !/honor:\s*\{[\s\S]*?default:\s*null/.test(authorInfo),
53
+ "AuthorInfo should leave an omitted honor undefined so legacy uid consumers still load it"
54
+ );
39
55
 
40
56
  assert(!authorHonor.includes("sessionStorage"), "AuthorHonor should not use session storage");
41
57
 
42
- assert(!authorHonor.includes("getUserHonor"), "AuthorHonor should not request the legacy active honor endpoint");
58
+ assert(authorHonor.includes("getUserHonor"), "AuthorHonor should retain the legacy uid endpoint");
59
+
60
+ assert(
61
+ authorHonor.includes("this.honor === undefined && this.uid"),
62
+ "AuthorHonor should only use the legacy endpoint when the new honor prop is absent"
63
+ );
64
+
65
+ assert(
66
+ authorHonor.includes("requestId !== this.honorRequestId"),
67
+ "AuthorHonor should ignore stale legacy endpoint responses"
68
+ );
43
69
 
44
70
  assert(author.includes("backgroundPosition: this.sidebarSkinPosition"), "Author should apply skin position");
45
71