@jx3box/jx3box-ui 2.3.21 → 2.3.23

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.
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <WikiPanel class="c-wiki-comments" scene="detail">
2
+ <WikiPanel class="c-wiki-comments" scene="detail" :variant="variant">
3
3
  <template #head-title>
4
4
  <i class="u-icon el-icon-chat-line-round"></i>
5
5
  <span class="u-txt">{{ $jx3boxT('jx3boxUi.wikiComments.title', '百科评论') }}</span>
@@ -29,10 +29,18 @@
29
29
  <i class="el-icon-chat-dot-round"></i>
30
30
  <span>{{ $jx3boxT('jx3boxUi.wiki.reply', '回复') }}</span>
31
31
  </h4>
32
- <textarea class="u-reply-content" v-model="reply_form.content"></textarea>
32
+ <textarea
33
+ class="u-reply-content"
34
+ v-model="reply_form.content"
35
+ :aria-label="$jx3boxT('jx3boxUi.wiki.reply', '回复')"
36
+ ></textarea>
33
37
  <div class="u-author">
34
38
  <span>{{ $jx3boxT('jx3boxUi.wiki.nickname', '昵称:') }}</span>
35
- <input v-model="reply_form.user_nickname" type="text" />
39
+ <input
40
+ v-model="reply_form.user_nickname"
41
+ type="text"
42
+ :aria-label="$jx3boxT('jx3boxUi.wiki.nickname', '昵称:')"
43
+ />
36
44
  </div>
37
45
  <el-button type="primary" class="u-submit" @click="create_comment(reply_form)">
38
46
  <i class="el-icon-check"></i>
@@ -61,6 +69,11 @@ export default {
61
69
  type: [Number, String],
62
70
  default: 0,
63
71
  },
72
+ variant: {
73
+ type: String,
74
+ default: "default",
75
+ validator: (value) => ["default", "surface", "plain"].includes(value),
76
+ },
64
77
  },
65
78
  data() {
66
79
  return {
@@ -163,7 +176,9 @@ export default {
163
176
  });
164
177
  },
165
178
  getDefaultNickname() {
166
- return User.isLogin() ? User.getInfo().name : "神秘侠士";
179
+ return User.isLogin()
180
+ ? User.getInfo().name
181
+ : this.$jx3boxT("jx3boxUi.wiki.mysterious", "神秘侠士");
167
182
  },
168
183
  handleCurrentChange(page) {
169
184
  this.page = page;
@@ -1,9 +1,7 @@
1
1
  <template>
2
2
  <div
3
3
  class="c-wiki-panel"
4
- :class="{
5
- border: border,
6
- }"
4
+ :class="rootClasses"
7
5
  >
8
6
  <div class="m-panel-head">
9
7
  <slot name="head-before"></slot>
@@ -11,7 +9,13 @@
11
9
  <slot name="head-title"></slot>
12
10
  </div>
13
11
  <div class="m-panel-actions">
14
- <QRcode v-if="wikiPost && showQR" class="u-qr" />
12
+ <QRcode
13
+ v-if="wikiPost && showQR"
14
+ class="u-qr"
15
+ :trigger-text="$jx3boxT('jx3boxUi.wikiPanel.qrTrigger', '二维码')"
16
+ :popup-text="$jx3boxT('jx3boxUi.wikiPanel.qrScanToVisit', '扫一扫即可访问')"
17
+ popup-class="u-wiki-panel-qrcode-popup"
18
+ />
15
19
  <slot name="head-actions"></slot>
16
20
  </div>
17
21
  <slot name="head-after"></slot>
@@ -72,6 +76,11 @@ export default {
72
76
  type: String,
73
77
  default: "default",
74
78
  },
79
+ variant: {
80
+ type: String,
81
+ default: "default",
82
+ validator: (value) => ["default", "surface", "plain"].includes(value),
83
+ },
75
84
  border: {
76
85
  type: Boolean,
77
86
  default: true,
@@ -86,6 +95,15 @@ export default {
86
95
  stat: null,
87
96
  };
88
97
  },
98
+ computed: {
99
+ rootClasses() {
100
+ return {
101
+ border: this.border,
102
+ [`is-${this.variant}`]: true,
103
+ [`is-scene-${this.scene}`]: true,
104
+ };
105
+ },
106
+ },
89
107
  watch: {
90
108
  wikiPost: {
91
109
  immediate: true,
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <WikiPanel class="c-wiki-revisions" scene="detail">
2
+ <WikiPanel class="c-wiki-revisions" scene="detail" :variant="variant">
3
3
  <template #head-title>
4
4
  <i class="u-icon el-icon-time"></i>
5
5
  <span class="u-txt">{{ $jx3boxT('jx3boxUi.wikiRevisions.title', '历史版本') }}</span>
@@ -62,6 +62,11 @@ export default {
62
62
  type: [Boolean, Number],
63
63
  default: false,
64
64
  },
65
+ variant: {
66
+ type: String,
67
+ default: "default",
68
+ validator: (value) => ["default", "surface", "plain"].includes(value),
69
+ },
65
70
  },
66
71
  data: function () {
67
72
  return {
@@ -0,0 +1,113 @@
1
+ const assert = require("node:assert/strict");
2
+ const test = require("node:test");
3
+
4
+ require("@babel/register")({
5
+ babelrc: false,
6
+ configFile: false,
7
+ extensions: [".js"],
8
+ ignore: [/node_modules/],
9
+ plugins: ["@babel/plugin-transform-modules-commonjs"],
10
+ });
11
+
12
+ const {
13
+ createJx3boxUiI18n,
14
+ getJx3boxUiMessages,
15
+ mergeJx3boxUiMessages,
16
+ setJx3boxUiI18n,
17
+ } = require("../i18n");
18
+ const i18nMixin = require("../i18n/mixin").default;
19
+ const { createI18n } = require("vue-i18n");
20
+
21
+ const TARGET_PREFIXES = [
22
+ "wiki.",
23
+ "wikiPanel.",
24
+ "wikiComments.",
25
+ "wikiComment.",
26
+ "wikiRevisions.",
27
+ "gamePrice.",
28
+ ];
29
+
30
+ function flattenMessages(value, prefix = "", output = {}) {
31
+ Object.entries(value || {}).forEach(([key, child]) => {
32
+ const path = prefix ? `${prefix}.${key}` : key;
33
+ if (child && typeof child === "object" && !Array.isArray(child)) {
34
+ flattenMessages(child, path, output);
35
+ } else {
36
+ output[path] = child;
37
+ }
38
+ });
39
+ return output;
40
+ }
41
+
42
+ function placeholders(value) {
43
+ return [...String(value ?? "").matchAll(/\{(\w+)\}/g)].map((match) => match[1]).sort();
44
+ }
45
+
46
+ test("loads the target component messages for each supported locale", () => {
47
+ const messages = getJx3boxUiMessages();
48
+ Object.entries(messages).forEach(([locale, message]) => {
49
+ const flattened = flattenMessages(message);
50
+ TARGET_PREFIXES.forEach((prefix) => {
51
+ assert.ok(
52
+ Object.keys(flattened).some((key) => key.startsWith(prefix)),
53
+ `${locale} is missing ${prefix}`
54
+ );
55
+ });
56
+ });
57
+
58
+ const i18n = createJx3boxUiI18n({ locale: "en-US" });
59
+ assert.equal(i18n.global.t("jx3boxUi.wikiComment.setTop"), "Pin");
60
+ assert.equal(i18n.global.t("jx3boxUi.wikiPanel.qrTrigger"), "QR code");
61
+ assert.equal(i18n.global.t("jx3boxUi.wikiPanel.qrScanToVisit"), "Scan to open this page");
62
+ assert.equal(i18n.global.t("jx3boxUi.gamePrice.jin"), "gold");
63
+ });
64
+
65
+ test("merges target messages into a host i18n instance", () => {
66
+ const hostI18n = createI18n({
67
+ legacy: false,
68
+ locale: "en-US",
69
+ fallbackLocale: "zh-CN",
70
+ messages: {
71
+ "en-US": {
72
+ host: {
73
+ title: "Host",
74
+ },
75
+ },
76
+ },
77
+ });
78
+
79
+ mergeJx3boxUiMessages(hostI18n);
80
+ setJx3boxUiI18n(hostI18n);
81
+
82
+ assert.equal(hostI18n.global.t("host.title"), "Host");
83
+ assert.equal(hostI18n.global.t("jx3boxUi.wikiComments.title"), "Wiki Comments");
84
+ });
85
+
86
+ test("component mixin keeps the explicit fallback when the host misses a key", () => {
87
+ setJx3boxUiI18n(null);
88
+ const context = {
89
+ $t(key) {
90
+ return key;
91
+ },
92
+ };
93
+
94
+ assert.equal(
95
+ i18nMixin.methods.$jx3boxT.call(context, "jx3boxUi.missing.example", "欢迎 {name}", { name: "侠士" }),
96
+ "欢迎 侠士"
97
+ );
98
+ });
99
+
100
+ test("keeps four locale message keys and placeholders aligned", () => {
101
+ const messages = getJx3boxUiMessages();
102
+ const locales = Object.keys(messages);
103
+ const baseline = flattenMessages(messages["zh-CN"]);
104
+ const baselineKeys = Object.keys(baseline).sort();
105
+
106
+ locales.forEach((locale) => {
107
+ const current = flattenMessages(messages[locale]);
108
+ assert.deepEqual(Object.keys(current).sort(), baselineKeys, `${locale} message keys differ from zh-CN`);
109
+ baselineKeys.forEach((key) => {
110
+ assert.deepEqual(placeholders(current[key]), placeholders(baseline[key]), `${locale}:${key} placeholders differ`);
111
+ });
112
+ });
113
+ });