@jx3box/jx3box-ui 2.3.8 → 2.3.9

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.8",
3
+ "version": "2.3.9",
4
4
  "description": "JX3BOX Vue3 UI",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -18,7 +18,15 @@
18
18
  </div>
19
19
 
20
20
  <!-- user -->
21
- <header-user ref="user" class="c-header__user" :client="client" :asset="asset" />
21
+ <header-user
22
+ ref="user"
23
+ class="c-header__user"
24
+ :client="client"
25
+ :asset="asset"
26
+ :header-config="headerConfig"
27
+ :header-config-loaded="headerConfigLoaded"
28
+ :header-config-managed="true"
29
+ />
22
30
  </div>
23
31
  <header-box v-if="isMobile" class="c-header__box c-header-jx3box" :overlayEnable="overlayEnable" />
24
32
  <header-box2 v-else class="c-header__box c-header__box--desktop" />
@@ -45,9 +53,12 @@ import miniprogram from "@jx3box/jx3box-common/data/miniprogram.json";
45
53
 
46
54
  // 数据
47
55
  import { getGlobalConfig } from "../service/header";
56
+ import { getConfig } from "../service/cms";
48
57
  import User from "@jx3box/jx3box-common/js/user.js";
49
58
  import JX3BOX from "@jx3box/jx3box-common/data/jx3box.json";
50
59
 
60
+ const HEADER_CONFIG_KEYS = ["important_notice", "important_notice_url", "vip", "mall"];
61
+
51
62
  export default {
52
63
  name: "Header",
53
64
  components: {
@@ -67,6 +78,8 @@ export default {
67
78
  isMobile: window.innerWidth <= 768,
68
79
 
69
80
  asset: {},
81
+ headerConfig: {},
82
+ headerConfigLoaded: false,
70
83
  };
71
84
  },
72
85
  computed: {
@@ -133,6 +146,7 @@ export default {
133
146
  // 检查
134
147
  init: function () {
135
148
  this.checkIsWebView();
149
+ this.loadHeaderConfig();
136
150
 
137
151
  const token = this.getUrlParam("__token");
138
152
  const env = this.getUrlParam("__env");
@@ -199,6 +213,31 @@ export default {
199
213
  }
200
214
  });
201
215
  },
216
+ loadHeaderConfig: function () {
217
+ getConfig({
218
+ key: HEADER_CONFIG_KEYS.join(","),
219
+ })
220
+ .then((data) => {
221
+ this.headerConfig = this.normalizeHeaderConfig(data);
222
+ })
223
+ .catch(() => {
224
+ this.headerConfig = {};
225
+ })
226
+ .finally(() => {
227
+ this.headerConfigLoaded = true;
228
+ });
229
+ },
230
+ normalizeHeaderConfig: function (data) {
231
+ if (Array.isArray(data)) {
232
+ return data.reduce((result, item) => {
233
+ if (item?.key) {
234
+ result[item.key] = item;
235
+ }
236
+ return result;
237
+ }, {});
238
+ }
239
+ return data?.key ? { [data.key]: data } : {};
240
+ },
202
241
  updateScreen() {
203
242
  this.isMobile = window.innerWidth <= 768;
204
243
  },
@@ -1,14 +1,16 @@
1
1
  <template>
2
2
  <div class="c-header-panel c-header-manage" id="c-header-manage">
3
3
  <span class="u-post u-manage">
4
- <i class="u-pop" style="display: none" v-show="showPop || !isAuth"></i>
5
- <!-- <manageIcon class="u-add" /> -->
6
- <img
7
- class="u-add"
8
- svg-inline
9
- src="../../assets/img/common/manage.svg"
10
- :alt="$jx3boxT('jx3boxUi.commonHeader.manageCenter', '扩展中心')"
11
- />
4
+ <i class="u-icon u-icon-msg">
5
+ <i class="u-pop" style="display: none" v-show="showPop || !isAuth"></i>
6
+ <!-- <manageIcon class="u-add" /> -->
7
+ <img
8
+ class="u-add"
9
+ svg-inline
10
+ src="../../assets/img/common/manage.svg"
11
+ :alt="$jx3boxT('jx3boxUi.commonHeader.manageCenter', '扩展中心')"
12
+ />
13
+ </i>
12
14
  </span>
13
15
  <ul class="u-menu u-pop-content">
14
16
  <template v-for="item in userPanel">
@@ -42,6 +44,7 @@ import i18nMixin from "../../i18n/mixin";
42
44
  import { getConfig } from "../../service/cms";
43
45
  // import manageIcon from "@/assets/img/components/common/header/manage.svg";
44
46
  const { __imgPath } = JX3BOX;
47
+ const NOTICE_POP_KEY = "notice_pop";
45
48
  const defaultPanel = [
46
49
  {
47
50
  key: "manageCenter",
@@ -67,6 +70,22 @@ export default {
67
70
  type: Boolean,
68
71
  default: false,
69
72
  },
73
+ importantNotice: {
74
+ type: Object,
75
+ default: null,
76
+ },
77
+ importantNoticeUrl: {
78
+ type: Object,
79
+ default: null,
80
+ },
81
+ headerConfigLoaded: {
82
+ type: Boolean,
83
+ default: true,
84
+ },
85
+ headerConfigManaged: {
86
+ type: Boolean,
87
+ default: false,
88
+ },
70
89
  },
71
90
  computed: {
72
91
  userPanel: function () {
@@ -84,7 +103,16 @@ export default {
84
103
  },
85
104
  },
86
105
  mounted() {
87
- this.loadPanel();
106
+ if (this.headerConfigLoaded) {
107
+ this.loadPanel();
108
+ }
109
+ },
110
+ watch: {
111
+ headerConfigLoaded: function (val) {
112
+ if (val) {
113
+ this.loadPanel();
114
+ }
115
+ },
88
116
  },
89
117
  methods: {
90
118
  getPanelLabel(item) {
@@ -94,19 +122,16 @@ export default {
94
122
  loadPanel: async function () {
95
123
  try {
96
124
  const panel = JSON.parse(sessionStorage.getItem("panel"));
97
- let config = await getConfig({ key: "important_notice_url" });
125
+ const noticeConfig = await this.getNoticeConfig("important_notice", this.importantNotice);
126
+ const noticeUrlConfig = await this.getNoticeConfig("important_notice_url", this.importantNoticeUrl);
98
127
  if (panel) {
99
- this.panel = panel;
128
+ this.panel = this.applyNoticeConfig(panel, noticeConfig, noticeUrlConfig);
100
129
  const item = this.panel?.find((i) => i.meta);
101
130
  this.initMeta(item);
131
+ sessionStorage.setItem("panel", JSON.stringify(this.panel));
102
132
  } else {
103
133
  getMenu("panel").then((res) => {
104
- this.panel = res.data?.data?.val?.map(item => {
105
- return {
106
- ...item,
107
- link: item.remark == 'feature' ? config.val : item.link
108
- };
109
- });
134
+ this.panel = this.applyNoticeConfig(res.data?.data?.val, noticeConfig, noticeUrlConfig);
110
135
  const item = this.panel?.find((i) => i.meta);
111
136
  this.initMeta(item);
112
137
  sessionStorage.setItem("panel", JSON.stringify(this.panel));
@@ -117,22 +142,33 @@ export default {
117
142
  console.log("loadPanel error", e);
118
143
  }
119
144
  },
145
+ getNoticeConfig: async function (key, config) {
146
+ if (config) return config;
147
+ if (this.headerConfigManaged) return null;
148
+ return await getConfig({ key }).catch(() => null);
149
+ },
150
+ applyNoticeConfig: function (panel = [], noticeConfig, noticeUrlConfig) {
151
+ const items = panel?.length ? panel : defaultPanel;
152
+ return items.map((item) => {
153
+ if (item.remark !== "feature") return item;
154
+ return {
155
+ ...item,
156
+ link: noticeUrlConfig?.val || item.link,
157
+ meta: noticeConfig?.val || item.meta,
158
+ };
159
+ });
160
+ },
120
161
  resolveImg: function (img) {
121
162
  return img ? __imgPath + "image/header/panel/" + img : __imgPath + "image/header/panel/default.svg";
122
163
  },
123
164
  initMeta(item) {
124
- const local = localStorage.getItem("jb_panel_meta");
125
-
126
- if (local) {
127
- this.showPop = item?.meta && item?.meta != local;
128
- } else {
129
- localStorage.setItem("jb_panel_meta", item?.meta);
130
- this.showPop = true;
131
- }
165
+ const meta = item?.meta;
166
+ const local = localStorage.getItem(NOTICE_POP_KEY);
167
+ this.showPop = !!meta && meta != local;
132
168
  },
133
169
  onClick(item) {
134
170
  if (item.meta) {
135
- localStorage.setItem("jb_panel_meta", item.meta);
171
+ localStorage.setItem(NOTICE_POP_KEY, item.meta);
136
172
  this.showPop = false;
137
173
  }
138
174
  },
@@ -180,6 +216,7 @@ export default {
180
216
 
181
217
  .u-icon-msg {
182
218
  .pr;
219
+ .size(18px);
183
220
  }
184
221
 
185
222
  .u-pop {
@@ -188,11 +225,11 @@ export default {
188
225
  color: #fff;
189
226
  background-image: linear-gradient(#fcd14f, #d7a20b);
190
227
  background-clip: padding-box;
191
- border: 2px solid #24292e;
228
+ border: 2px solid @header-bg;
192
229
  border-radius: 50%;
193
230
  position: absolute;
194
- right: 4px;
195
- top: 18px;
231
+ right: -5px;
232
+ top: -4px;
196
233
  z-index: 1;
197
234
  }
198
235
 
@@ -81,7 +81,7 @@ export default {
81
81
  border-radius: 50%;
82
82
  position: absolute;
83
83
  right: -5px;
84
- top: -2px;
84
+ top: -4px;
85
85
  .z(1);
86
86
  }
87
87
  }
@@ -6,7 +6,7 @@
6
6
  placement="bottom"
7
7
  popper-class="c-header-tooltip"
8
8
  >
9
- <a class="u-present" href="/vip/mall">
9
+ <a class="u-present" href="/vip/mall" @click="markPopRead">
10
10
  <i class="u-icon u-icon-msg">
11
11
  <i class="u-pop" style="display: none" v-show="pop"></i>
12
12
  <!-- <shopIcon class="u-icon" /> -->
@@ -23,7 +23,7 @@
23
23
  </template>
24
24
 
25
25
  <script>
26
- import { getConfig, getUserMeta, setUserMeta } from "../../service/cms";
26
+ import { getConfig, getUserMeta } from "../../service/cms";
27
27
  import User from "@jx3box/jx3box-common/js/user";
28
28
  import i18nMixin from "../../i18n/mixin";
29
29
  // import shopIcon from "@/assets/img/components/common/header/gift.svg";
@@ -36,52 +36,66 @@ export default {
36
36
  data: function () {
37
37
  return {
38
38
  pop: false,
39
+ initialized: false,
40
+ popValue: "",
39
41
  };
40
42
  },
43
+ props: {
44
+ config: {
45
+ type: Object,
46
+ default: null,
47
+ },
48
+ configLoaded: {
49
+ type: Boolean,
50
+ default: true,
51
+ },
52
+ configManaged: {
53
+ type: Boolean,
54
+ default: false,
55
+ },
56
+ },
57
+ watch: {
58
+ configLoaded: function (val) {
59
+ if (val) {
60
+ this.init();
61
+ }
62
+ },
63
+ },
41
64
  mounted() {
42
- this.init();
65
+ if (this.configLoaded) {
66
+ this.init();
67
+ }
43
68
  },
44
69
  methods: {
45
70
  async init() {
71
+ if (this.initialized) return;
46
72
  /**
47
- * 1. 用户第一次进入页面时,没有记录,则显示,并记录到meta
48
- * 2. 用户第二次进入页面,此时meta有记录,但是用户并未进入会员中心,则显示
49
- *
50
- * meta如果为null,说明用户未登录,不显示
51
- * meta如果为0,说明用户已经看过,不显示,同时比较config的值,如果config的值大于local,更新local为config的值和meta为1
52
- * meta如果为1,说明用户未看过,显示
73
+ * 只在点击入口后记录本地版本;仅看到气泡不算已处理。
53
74
  */
54
75
  let meta = null;
55
76
  if (User.isLogin()) {
56
77
  meta = await getUserMeta({ key: "mall_pop" });
57
78
  }
58
- let config = await getConfig({ key: "mall" });
59
-
60
- if (meta == null) {
61
- const val = ~~config.val;
62
-
63
- if (val) {
64
- this.pop = true;
65
- localStorage.setItem("mall_pop", config.val);
66
- setUserMeta("mall_pop", { val: 1 });
67
- }
68
- } else {
69
- if (meta == 1) {
70
- this.pop = true;
71
-
72
- localStorage.setItem("mall_pop", config.val);
73
- } else {
74
- const local = localStorage.getItem("mall_pop");
79
+ let config = this.config || (this.configManaged ? null : await getConfig({ key: "mall" }));
80
+ if (!config) return;
81
+ this.initialized = true;
82
+ this.popValue = config.val;
75
83
 
76
- if (~~config.val > ~~local) {
77
- this.pop = true;
84
+ this.pop = this.shouldShowPop(meta, config.val);
85
+ },
86
+ shouldShowPop(meta, value) {
87
+ if (!~~value) return false;
78
88
 
79
- localStorage.setItem("mall_pop", config.val);
89
+ const local = localStorage.getItem("mall_pop");
90
+ if (String(local) === String(value)) return false;
80
91
 
81
- // setUserMeta("mall_pop", { val: 1 });
82
- }
83
- }
84
- }
92
+ if (meta == null || meta == 1) return true;
93
+ return ~~value > ~~local;
94
+ },
95
+ markPopRead() {
96
+ if (!this.pop || this.popValue == null) return;
97
+ localStorage.setItem("mall_pop", this.popValue);
98
+ this.pop = false;
85
99
  },
86
100
  },
87
101
  };
@@ -111,11 +125,11 @@ export default {
111
125
  color: #fff;
112
126
  background-image: linear-gradient(#fcd14f, #d7a20b);
113
127
  background-clip: padding-box;
114
- border: 2px solid #24292e;
128
+ border: 2px solid @header-bg;
115
129
  border-radius: 50%;
116
130
  position: absolute;
117
131
  right: -5px;
118
- top: -6px;
132
+ top: -4px;
119
133
  z-index: 1;
120
134
  }
121
135
  }
@@ -8,16 +8,22 @@
8
8
  <publish />
9
9
 
10
10
  <!-- vip -->
11
- <vip />
11
+ <vip :config="headerConfig.vip" :config-loaded="headerConfigLoaded" :config-managed="headerConfigManaged" />
12
12
 
13
13
  <!-- 商城 -->
14
- <shop />
14
+ <shop :config="headerConfig.mall" :config-loaded="headerConfigLoaded" :config-managed="headerConfigManaged" />
15
15
 
16
16
  <!-- 我的资产 -->
17
17
  <asset :asset="asset" />
18
18
 
19
19
  <!-- manage -->
20
- <manage :isTeammate="isTeammate" />
20
+ <manage
21
+ :isTeammate="isTeammate"
22
+ :important-notice="headerConfig.important_notice"
23
+ :important-notice-url="headerConfig.important_notice_url"
24
+ :header-config-loaded="headerConfigLoaded"
25
+ :header-config-managed="headerConfigManaged"
26
+ />
21
27
 
22
28
  <!-- 语言切换 -->
23
29
  <lang />
@@ -77,6 +83,18 @@ export default {
77
83
  };
78
84
  },
79
85
  },
86
+ headerConfig: {
87
+ type: Object,
88
+ default: () => ({}),
89
+ },
90
+ headerConfigLoaded: {
91
+ type: Boolean,
92
+ default: true,
93
+ },
94
+ headerConfigManaged: {
95
+ type: Boolean,
96
+ default: false,
97
+ },
80
98
  },
81
99
  components: {
82
100
  message,
@@ -6,7 +6,7 @@
6
6
  placement="bottom"
7
7
  popper-class="c-header-tooltip"
8
8
  >
9
- <a class="u-post u-vip" href="/vip/premium">
9
+ <a class="u-post u-vip" href="/vip/premium" @click="markPopRead">
10
10
  <i class="u-icon u-icon-msg">
11
11
  <i class="u-pop" style="display: none" v-show="pop"></i>
12
12
  <!-- <vipIcon class="u-add" /> -->
@@ -23,7 +23,7 @@
23
23
  </template>
24
24
 
25
25
  <script>
26
- import { getConfig, getUserMeta, setUserMeta } from "../../service/cms";
26
+ import { getConfig, getUserMeta } from "../../service/cms";
27
27
  import User from "@jx3box/jx3box-common/js/user";
28
28
  import i18nMixin from "../../i18n/mixin";
29
29
  // import vipIcon from "@/assets/img/components/common/header/vip.svg";
@@ -36,48 +36,66 @@ export default {
36
36
  data: function () {
37
37
  return {
38
38
  pop: false,
39
+ initialized: false,
40
+ popValue: "",
39
41
  };
40
42
  },
43
+ props: {
44
+ config: {
45
+ type: Object,
46
+ default: null,
47
+ },
48
+ configLoaded: {
49
+ type: Boolean,
50
+ default: true,
51
+ },
52
+ configManaged: {
53
+ type: Boolean,
54
+ default: false,
55
+ },
56
+ },
57
+ watch: {
58
+ configLoaded: function (val) {
59
+ if (val) {
60
+ this.init();
61
+ }
62
+ },
63
+ },
41
64
  mounted() {
42
- this.init();
65
+ if (this.configLoaded) {
66
+ this.init();
67
+ }
43
68
  },
44
69
  methods: {
45
70
  async init() {
71
+ if (this.initialized) return;
46
72
  /**
47
- * 1. 用户第一次进入页面时,没有记录,则显示,并记录到meta
48
- * 2. 用户第二次进入页面,此时meta有记录,但是用户并未进入会员中心,则显示
73
+ * 只在点击入口后记录本地版本;仅看到气泡不算已处理。
49
74
  */
50
75
  let meta = null;
51
76
  if (User.isLogin()) {
52
77
  meta = await getUserMeta({ key: "vip_pop" });
53
78
  }
54
- let config = await getConfig({ key: "vip" });
55
-
56
- if (meta == null) {
57
- const val = ~~config.val;
58
-
59
- if (val) {
60
- this.pop = true;
61
- localStorage.setItem("vip_pop", config.val);
62
- setUserMeta("vip_pop", { val: 1 });
63
- }
64
- } else {
65
- if (meta == 1) {
66
- this.pop = true;
67
-
68
- localStorage.setItem("vip_pop", config.val);
69
- } else {
70
- const local = localStorage.getItem("vip_pop");
79
+ let config = this.config || (this.configManaged ? null : await getConfig({ key: "vip" }));
80
+ if (!config) return;
81
+ this.initialized = true;
82
+ this.popValue = config.val;
71
83
 
72
- if (~~config.val > ~~local) {
73
- this.pop = true;
84
+ this.pop = this.shouldShowPop(meta, config.val);
85
+ },
86
+ shouldShowPop(meta, value) {
87
+ if (!~~value) return false;
74
88
 
75
- localStorage.setItem("vip_pop", config.val);
89
+ const local = localStorage.getItem("vip_pop");
90
+ if (String(local) === String(value)) return false;
76
91
 
77
- // setUserMeta("vip_pop", { val: 1 });
78
- }
79
- }
80
- }
92
+ if (meta == null || meta == 1) return true;
93
+ return ~~value > ~~local;
94
+ },
95
+ markPopRead() {
96
+ if (!this.pop || this.popValue == null) return;
97
+ localStorage.setItem("vip_pop", this.popValue);
98
+ this.pop = false;
81
99
  },
82
100
  },
83
101
  };
@@ -99,11 +117,11 @@ export default {
99
117
  color: #fff;
100
118
  background-image: linear-gradient(#fcd14f, #d7a20b);
101
119
  background-clip: padding-box;
102
- border: 2px solid #24292e;
120
+ border: 2px solid @header-bg;
103
121
  border-radius: 50%;
104
122
  position: absolute;
105
123
  right: -5px;
106
- top: -6px;
124
+ top: -4px;
107
125
  z-index: 1;
108
126
  }
109
127
  .u-vip {