@jx3box/jx3box-common 8.7.5 → 9.0.0

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/js/api.js ADDED
@@ -0,0 +1,242 @@
1
+ // 统一 API 封装(由 https_v2.js / https.js / request.js 合并)
2
+ import axios from "axios";
3
+ import domains from "../data/jx3box.json";
4
+ import { SSE } from "./sse";
5
+ import { ElMessage, ElMessageBox, ElNotification } from "element-plus";
6
+ import utilModule, { getTokenFromUrl } from "./utils";
7
+
8
+ const { jx3ClientType } = utilModule;
9
+
10
+ function readAuthToken() {
11
+ const tokenFromUrl = getTokenFromUrl();
12
+ if (tokenFromUrl) return tokenFromUrl;
13
+ return (localStorage && (localStorage.getItem("__token") || localStorage.getItem("token"))) || "";
14
+ }
15
+
16
+ function readEnv(key) {
17
+ // 需要在 vite.config.js 配置 envPrefix 包含 VUE_APP_
18
+ return (import.meta && import.meta.env && import.meta.env[key]) || "";
19
+ }
20
+
21
+ function localProxyEnabled(options) {
22
+ if (!import.meta?.env?.DEV) return false;
23
+ if (options && options.proxy === false) return false;
24
+ if (options && options.proxy === true) return true;
25
+ const raw = (readEnv("VUE_APP_PROXY_ENABLE") || "").toString().toLowerCase();
26
+ return raw === "1" || raw === "true" || raw === "yes" || raw === "on";
27
+ }
28
+
29
+ function localProxyBase(serviceKey) {
30
+ const prefix = readEnv("VUE_APP_PROXY_PREFIX") || "/__proxy";
31
+ return `${prefix}/${serviceKey}`;
32
+ }
33
+
34
+ function loadPop(msg, popType = "message") {
35
+ const message = msg || "网络请求异常";
36
+ switch (popType) {
37
+ case "message":
38
+ ElMessage({ message, type: "error" });
39
+ break;
40
+ case "alert":
41
+ ElMessageBox.alert(message, "错误");
42
+ break;
43
+ case "notify":
44
+ ElNotification({ title: "错误", message, duration: 3000 });
45
+ break;
46
+ default:
47
+ ElMessage({ message, type: "error" });
48
+ break;
49
+ }
50
+ }
51
+
52
+ function throwError(err) {
53
+ console.log(err?.response);
54
+ return Promise.reject(err);
55
+ }
56
+
57
+ function loadDefaultRequestErrorPop(err, popType = "message") {
58
+ const status = err?.response?.status ?? "";
59
+ const statusText = err?.response?.statusText ?? "Request Error";
60
+ loadPop(`[${status}]${statusText}`, popType);
61
+ }
62
+
63
+ function installInterceptors(target, options) {
64
+ const popType = (options && options.popType) || "message";
65
+ target.interceptors.response.use(
66
+ (response) => response,
67
+ (err) => {
68
+ if (!options || !options.mute) {
69
+ if (err?.response?.data?.msg) {
70
+ loadPop(err.response.data.msg, popType);
71
+ } else {
72
+ loadDefaultRequestErrorPop(err, popType);
73
+ }
74
+ }
75
+ return throwError(err);
76
+ }
77
+ );
78
+ }
79
+
80
+ function installStandardInterceptors(target, options) {
81
+ const popType = (options && options.popType) || "message";
82
+ target.interceptors.response.use(
83
+ (response) => {
84
+ if (response?.data?.code) {
85
+ if (!options || !options.mute) {
86
+ response.data.msg && loadPop(`[${response.data.code}]${response.data.msg}`, popType);
87
+ }
88
+ return Promise.reject(response);
89
+ }
90
+ return response;
91
+ },
92
+ (err) => {
93
+ if (!options || !options.mute) {
94
+ if (err?.response?.data?.msg) {
95
+ loadPop(err.response.data.msg, popType);
96
+ } else {
97
+ loadDefaultRequestErrorPop(err, popType);
98
+ }
99
+ }
100
+ return throwError(err);
101
+ }
102
+ );
103
+ }
104
+
105
+ function installHelperInterceptors(target, options) {
106
+ const popType = (options && options.popType) || "message";
107
+ target.interceptors.response.use(
108
+ (response) => {
109
+ const code = response?.data?.code;
110
+ if (code === 200 || !code) return response;
111
+ if (!options || !options.mute) {
112
+ loadPop(`[${code}]${response?.data?.message || ""}`, popType);
113
+ }
114
+ return Promise.reject(response);
115
+ },
116
+ (err) => {
117
+ if (!options || !options.mute) {
118
+ loadDefaultRequestErrorPop(err, popType);
119
+ }
120
+ return throwError(err);
121
+ }
122
+ );
123
+ }
124
+
125
+ function $cms(options = {}, axiosConfig = {}) {
126
+ const { interceptor = true, domain, progress } = options;
127
+ const requestDomain = domain || readEnv("VUE_APP_CMS_API") || domains.__cms;
128
+ const token = readAuthToken();
129
+
130
+ const config = {
131
+ withCredentials: true,
132
+ auth: { username: token || "", password: "cms common request" },
133
+ baseURL: localProxyEnabled(options) ? localProxyBase("cms") : requestDomain,
134
+ headers: {},
135
+ };
136
+ if (progress) config.onUploadProgress = progress;
137
+
138
+ const ins = axios.create(Object.assign(axiosConfig, config));
139
+ interceptor && installStandardInterceptors(ins, options);
140
+ return ins;
141
+ }
142
+
143
+ function $helper(options = {}) {
144
+ const domain = (options && options.domain) || readEnv("VUE_APP_HELPER_API") || domains.__helperUrl;
145
+ const token = readAuthToken();
146
+
147
+ const config = {
148
+ withCredentials: true,
149
+ auth: { username: token || "", password: "helper common request" },
150
+ baseURL: localProxyEnabled(options) ? localProxyBase("helper") : domain,
151
+ headers: {
152
+ Accept: "application/prs.helper.v2+json",
153
+ "JX3-Client-Type": (options && options.client_id) || jx3ClientType(),
154
+ },
155
+ };
156
+
157
+ if (options && options.headers) {
158
+ config.headers = Object.assign(config.headers, options.headers);
159
+ }
160
+
161
+ const ins = axios.create(config);
162
+ installHelperInterceptors(ins, options);
163
+ return ins;
164
+ }
165
+
166
+ function $next(options = {}, axiosConfig = {}) {
167
+ const { interceptor = true, domain, progress } = options;
168
+ const requestDomain = domain || readEnv("VUE_APP_NEXT_API") || domains.__next;
169
+ const token = readAuthToken();
170
+ const serviceKey = (options && options.serviceKey) || "next";
171
+
172
+ const config = {
173
+ withCredentials: true,
174
+ auth: { username: token || "", password: "next common request" },
175
+ baseURL: localProxyEnabled(options) ? localProxyBase(serviceKey) : requestDomain,
176
+ headers: {},
177
+ };
178
+ if (progress) config.onUploadProgress = progress;
179
+
180
+ const ins = axios.create(Object.assign(axiosConfig, config));
181
+ interceptor && installStandardInterceptors(ins, options);
182
+ return ins;
183
+ }
184
+
185
+ function $team(options = {}) {
186
+ const requestDomain = (options && options.domain) || readEnv("VUE_APP_TEAM_API") || domains.__team;
187
+ return $next(Object.assign({}, options, { domain: requestDomain, serviceKey: "team" }));
188
+ }
189
+
190
+ function $pay(options = {}) {
191
+ const requestDomain = (options && options.domain) || readEnv("VUE_APP_PAY_API") || domains.__pay;
192
+ return $next(Object.assign({}, options, { domain: requestDomain, serviceKey: "pay" }));
193
+ }
194
+
195
+ function $lua(options = {}) {
196
+ const requestDomain = (options && options.domain) || readEnv("VUE_APP_LUA_API") || domains.__lua;
197
+ return $next(Object.assign({}, options, { domain: requestDomain, serviceKey: "lua" }));
198
+ }
199
+
200
+ function $node(options = {}) {
201
+ const requestDomain = (options && options.domain) || readEnv("VUE_APP_NODE_API") || domains.__node;
202
+ const token = readAuthToken();
203
+ const config = {
204
+ withCredentials: true,
205
+ auth: { username: token || "", password: "node common request" },
206
+ baseURL: localProxyEnabled(options) ? localProxyBase("node") : requestDomain,
207
+ };
208
+ const ins = axios.create(config);
209
+ installInterceptors(ins, options);
210
+ return ins;
211
+ }
212
+
213
+ function $http(options) {
214
+ const domain = typeof options === "string" ? options : options.domain;
215
+ const token = readAuthToken();
216
+ const config = {
217
+ withCredentials: true,
218
+ auth: { username: token || "", password: "common request" },
219
+ baseURL: domain,
220
+ headers: Object.assign({}, (options && options.headers) || {}),
221
+ };
222
+ const ins = axios.create(config);
223
+ installStandardInterceptors(ins, options);
224
+ return ins;
225
+ }
226
+
227
+ export {
228
+ axios,
229
+ SSE,
230
+ $cms,
231
+ $next,
232
+ $helper,
233
+ $node,
234
+ $team,
235
+ $pay,
236
+ $lua,
237
+ $http,
238
+ // 兼容:少数脚本会直接用到拦截器
239
+ installInterceptors,
240
+ installStandardInterceptors,
241
+ installHelperInterceptors,
242
+ };
package/js/user.js CHANGED
@@ -1,11 +1,6 @@
1
1
  import { showAvatar } from "./utils";
2
- import { $pay, $cms } from "./request";
3
- import {
4
- __Links,
5
- default_avatar,
6
- __server,
7
- __userLevel,
8
- } from "../data/jx3box.json";
2
+ import { $pay, $cms } from "./api";
3
+ import { __Links, default_avatar, __userLevel } from "../data/jx3box.json";
9
4
  import { tokenExpires } from "../data/conf.json";
10
5
  import Fingerprint2 from "fingerprintjs2";
11
6
  import { getTokenFromUrl } from "./utils";
@@ -38,22 +33,15 @@ class User {
38
33
  check() {
39
34
  if (this.isLogin()) {
40
35
  this.profile.uid = localStorage && localStorage.getItem("uid");
41
- this.profile.group =
42
- (localStorage && localStorage.getItem("group")) || 1;
36
+ this.profile.group = (localStorage && localStorage.getItem("group")) || 1;
43
37
  this.profile.token = localStorage && localStorage.getItem("token");
44
38
  this.profile.name = localStorage && localStorage.getItem("name");
45
- this.profile.status =
46
- localStorage && localStorage.getItem("status");
47
- this.profile.bind_wx =
48
- localStorage && localStorage.getItem("bind_wx");
49
- this.profile.avatar_origin =
50
- (localStorage && localStorage.getItem("avatar")) ||
51
- default_avatar;
39
+ this.profile.status = localStorage && localStorage.getItem("status");
40
+ this.profile.bind_wx = localStorage && localStorage.getItem("bind_wx");
41
+ this.profile.avatar_origin = (localStorage && localStorage.getItem("avatar")) || default_avatar;
52
42
  this.profile.avatar = showAvatar(this.profile.avatar_origin, "s");
53
- this.profile.permission =
54
- localStorage && localStorage.getItem("jx3box_permission");
55
- this.profile.is_teammate =
56
- localStorage && localStorage.getItem("is_teammate");
43
+ this.profile.permission = localStorage && localStorage.getItem("jx3box_permission");
44
+ this.profile.is_teammate = localStorage && localStorage.getItem("is_teammate");
57
45
  } else {
58
46
  this.profile = this.anonymous;
59
47
  }
@@ -71,11 +59,8 @@ class User {
71
59
  if (token) {
72
60
  return true;
73
61
  }
74
- this.created_at = !localStorage.getItem("created_at")
75
- ? -Infinity
76
- : localStorage.getItem("created_at");
77
- this.logged_in =
78
- localStorage.getItem("logged_in") == "true" ? true : false;
62
+ this.created_at = !localStorage.getItem("created_at") ? -Infinity : localStorage.getItem("created_at");
63
+ this.logged_in = localStorage.getItem("logged_in") == "true" ? true : false;
79
64
  return this.logged_in && Date.now() - this.created_at < this.expires;
80
65
  }
81
66
 
@@ -108,7 +93,7 @@ class User {
108
93
  if (localStorage) {
109
94
  localStorage.clear();
110
95
  this._save(data);
111
- resolve(value);
96
+ resolve(data);
112
97
  } else {
113
98
  reject(new Error("localStorage不可用"));
114
99
  }
@@ -185,13 +170,11 @@ class User {
185
170
  if (this.isLogin()) {
186
171
  return $cms()
187
172
  .get("/api/cms/user/is_super_author/" + this.getInfo().uid)
188
- .then(res => {
173
+ .then((res) => {
189
174
  return res.data.data;
190
175
  });
191
176
  } else {
192
- return new Promise((resolve, reject) => {
193
- resolve(false);
194
- });
177
+ return Promise.resolve(false);
195
178
  }
196
179
  }
197
180
 
@@ -229,11 +212,9 @@ class User {
229
212
  // 判断是否为VIP
230
213
  isVIP() {
231
214
  if (this.asset) {
232
- return new Promise((resolve, reject) => {
233
- resolve(this._isPRO(this.asset) || this._isVIP(this.asset));
234
- });
215
+ return Promise.resolve(this._isPRO(this.asset) || this._isVIP(this.asset));
235
216
  } else {
236
- return this.getAsset().then(asset => {
217
+ return this.getAsset().then((asset) => {
237
218
  return this._isPRO(asset) || this._isVIP(asset);
238
219
  });
239
220
  }
@@ -242,11 +223,9 @@ class User {
242
223
  // 判断是否为PRO
243
224
  isPRO() {
244
225
  if (this.asset) {
245
- return new Promise((resolve, reject) => {
246
- resolve(this._isPRO(this.asset));
247
- });
226
+ return Promise.resolve(this._isPRO(this.asset));
248
227
  } else {
249
- return this.getAsset().then(asset => {
228
+ return this.getAsset().then((asset) => {
250
229
  return this._isPRO(asset);
251
230
  });
252
231
  }
@@ -255,28 +234,26 @@ class User {
255
234
  // 获取用户资产
256
235
  getAsset() {
257
236
  if (!this.isLogin()) {
258
- return new Promise((resolve, reject) => {
259
- let asset = {
260
- was_vip: 0,
261
- expire_date: "1970-02-02T16:00:00.000Z",
262
- total_day: 0,
263
- was_pro: 0,
264
- pro_expire_date: "1970-02-02T16:00:00.000Z",
265
- pro_total_day: 0,
266
- rename_card_count: 0,
267
- had_renamed: 0,
268
- namespace_card_count: 0,
269
- box_coin: 0,
270
- points: 0,
271
- };
272
- this.asset = asset;
273
- // 空资产
274
- resolve(asset);
275
- });
237
+ const asset = {
238
+ was_vip: 0,
239
+ expire_date: "1970-02-02T16:00:00.000Z",
240
+ total_day: 0,
241
+ was_pro: 0,
242
+ pro_expire_date: "1970-02-02T16:00:00.000Z",
243
+ pro_total_day: 0,
244
+ rename_card_count: 0,
245
+ had_renamed: 0,
246
+ namespace_card_count: 0,
247
+ box_coin: 0,
248
+ points: 0,
249
+ };
250
+ this.asset = asset;
251
+ // 空资产
252
+ return Promise.resolve(asset);
276
253
  } else {
277
254
  return $pay()
278
255
  .get("/api/vip/i")
279
- .then(res => {
256
+ .then((res) => {
280
257
  let asset = res.data.data;
281
258
  this.asset = asset;
282
259
  return asset;
package/js/user_old.js ADDED
@@ -0,0 +1,330 @@
1
+ import { showAvatar } from "./utils";
2
+ import { $pay, $cms } from "./request";
3
+ import {
4
+ __Links,
5
+ default_avatar,
6
+ __server,
7
+ __userLevel,
8
+ } from "../data/jx3box.json";
9
+ import { tokenExpires } from "../data/conf.json";
10
+ import Fingerprint2 from "fingerprintjs2";
11
+ import { getTokenFromUrl } from "./utils";
12
+
13
+ class User {
14
+ constructor() {
15
+ // TOKEN有效期
16
+ this.expires = tokenExpires;
17
+ this.created_at = 0;
18
+ // 登录状态
19
+ this.logged_in = false;
20
+
21
+ // 缓存资料
22
+ this.profile = {};
23
+ this.anonymous = {
24
+ uid: 0,
25
+ group: 0,
26
+ name: "未登录",
27
+ status: 0,
28
+ bind_wx: 0,
29
+ avatar: showAvatar(null, "s"),
30
+ avatar_origin: default_avatar,
31
+ };
32
+
33
+ // 资产缓存
34
+ this.asset = "";
35
+ }
36
+
37
+ // 检查当前状态
38
+ check() {
39
+ if (this.isLogin()) {
40
+ this.profile.uid = localStorage && localStorage.getItem("uid");
41
+ this.profile.group =
42
+ (localStorage && localStorage.getItem("group")) || 1;
43
+ this.profile.token = localStorage && localStorage.getItem("token");
44
+ this.profile.name = localStorage && localStorage.getItem("name");
45
+ this.profile.status =
46
+ localStorage && localStorage.getItem("status");
47
+ this.profile.bind_wx =
48
+ localStorage && localStorage.getItem("bind_wx");
49
+ this.profile.avatar_origin =
50
+ (localStorage && localStorage.getItem("avatar")) ||
51
+ default_avatar;
52
+ this.profile.avatar = showAvatar(this.profile.avatar_origin, "s");
53
+ this.profile.permission =
54
+ localStorage && localStorage.getItem("jx3box_permission");
55
+ this.profile.is_teammate =
56
+ localStorage && localStorage.getItem("is_teammate");
57
+ } else {
58
+ this.profile = this.anonymous;
59
+ }
60
+ return this;
61
+ }
62
+
63
+ // 更新指定缓存字段
64
+ refresh(key, val) {
65
+ return localStorage.setItem(key, val);
66
+ }
67
+
68
+ // 判断是否已登录
69
+ isLogin() {
70
+ const token = getTokenFromUrl();
71
+ if (token) {
72
+ return true;
73
+ }
74
+ this.created_at = !localStorage.getItem("created_at")
75
+ ? -Infinity
76
+ : localStorage.getItem("created_at");
77
+ this.logged_in =
78
+ localStorage.getItem("logged_in") == "true" ? true : false;
79
+ return this.logged_in && Date.now() - this.created_at < this.expires;
80
+ }
81
+
82
+ // 判断是否已过期
83
+ isExpired() {
84
+ return Date.now() - this.created_at > this.expires;
85
+ }
86
+
87
+ // 保存用户资料
88
+ _save(data) {
89
+ localStorage.setItem("created_at", Date.now());
90
+ localStorage.setItem("logged_in", true);
91
+ localStorage.setItem("token", data.token);
92
+ localStorage.setItem("uid", data.uid);
93
+ localStorage.setItem("group", data.group);
94
+ localStorage.setItem("name", data.name);
95
+ localStorage.setItem("status", data.status);
96
+ localStorage.setItem("bind_wx", data.bind_wx);
97
+ localStorage.setItem("avatar", data.avatar);
98
+ }
99
+
100
+ // 更新用户资料
101
+ update(data) {
102
+ return new Promise((resolve, reject) => {
103
+ try {
104
+ this._save(data);
105
+ resolve(this);
106
+ } catch (err) {
107
+ //如果localStorage不存在或已满
108
+ if (localStorage) {
109
+ localStorage.clear();
110
+ this._save(data);
111
+ resolve(value);
112
+ } else {
113
+ reject(new Error("localStorage不可用"));
114
+ }
115
+ }
116
+ });
117
+ }
118
+
119
+ // 获取用户基础缓存信息
120
+ getInfo() {
121
+ this.check();
122
+ return this.profile;
123
+ }
124
+
125
+ // 销毁登录状态
126
+ async destroy() {
127
+ return $cms()
128
+ .post("api/cms/user/account/email/logout")
129
+ .finally(() => {
130
+ localStorage.removeItem("created_at");
131
+ localStorage.setItem("logged_in", "false");
132
+ localStorage.removeItem("token");
133
+ localStorage.removeItem("jx3box_permission");
134
+ });
135
+ }
136
+
137
+ // 跳转至登录
138
+ toLogin(url) {
139
+ url = url ? encodeURIComponent(url) : encodeURIComponent(location.href);
140
+ location.href = __Links.account.login + "?redirect=" + url;
141
+ }
142
+
143
+ // 获取本地令牌
144
+ getToken() {
145
+ return this.getInfo().token;
146
+ }
147
+
148
+ // 获取UUID
149
+ getUUID() {
150
+ return localStorage.getItem("device_id");
151
+ }
152
+
153
+ // 判断是否邮箱验证
154
+ isEmailMember() {
155
+ return this.getInfo().group >= 8;
156
+ }
157
+
158
+ // 判断是否绑定手机
159
+ isPhoneMember() {
160
+ return this.getInfo().group >= 16;
161
+ }
162
+
163
+ // 判断是否为管理员|编辑
164
+ isEditor() {
165
+ return this.getInfo().group >= 64;
166
+ }
167
+
168
+ // 判断是否为管理员|运营
169
+ isAdmin() {
170
+ return this.getInfo().group >= 128;
171
+ }
172
+
173
+ // 判断是否为管理员|开发
174
+ isDeveloper() {
175
+ return this.getInfo().group >= 256;
176
+ }
177
+
178
+ // 判断是否为超管
179
+ isSuperAdmin() {
180
+ return this.getInfo().group >= 512;
181
+ }
182
+
183
+ // 判断是否为签约作者
184
+ isSuperAuthor() {
185
+ if (this.isLogin()) {
186
+ return $cms()
187
+ .get("/api/cms/user/is_super_author/" + this.getInfo().uid)
188
+ .then(res => {
189
+ return res.data.data;
190
+ });
191
+ } else {
192
+ return new Promise((resolve, reject) => {
193
+ resolve(false);
194
+ });
195
+ }
196
+ }
197
+
198
+ // 判断是否为团队成员
199
+ isTeammate() {
200
+ return this.getInfo().is_teammate == "true";
201
+ }
202
+
203
+ // 是否绑定微信
204
+ hasBindwx() {
205
+ return this.getInfo().bind_wx;
206
+ }
207
+
208
+ // PRE身份判断
209
+ _isVIP(asset) {
210
+ let isPRE = asset.was_vip;
211
+ if (isPRE) {
212
+ let isExpired = new Date(asset.expire_date) - new Date() > 0;
213
+ return isExpired;
214
+ } else {
215
+ return false;
216
+ }
217
+ }
218
+ // PRO身份判断
219
+ _isPRO(asset) {
220
+ let isPRO = asset.was_pro;
221
+ if (isPRO) {
222
+ let isExpired = new Date(asset.pro_expire_date) - new Date() > 0;
223
+ return isExpired;
224
+ } else {
225
+ return false;
226
+ }
227
+ }
228
+
229
+ // 判断是否为VIP
230
+ isVIP() {
231
+ if (this.asset) {
232
+ return new Promise((resolve, reject) => {
233
+ resolve(this._isPRO(this.asset) || this._isVIP(this.asset));
234
+ });
235
+ } else {
236
+ return this.getAsset().then(asset => {
237
+ return this._isPRO(asset) || this._isVIP(asset);
238
+ });
239
+ }
240
+ }
241
+
242
+ // 判断是否为PRO
243
+ isPRO() {
244
+ if (this.asset) {
245
+ return new Promise((resolve, reject) => {
246
+ resolve(this._isPRO(this.asset));
247
+ });
248
+ } else {
249
+ return this.getAsset().then(asset => {
250
+ return this._isPRO(asset);
251
+ });
252
+ }
253
+ }
254
+
255
+ // 获取用户资产
256
+ getAsset() {
257
+ if (!this.isLogin()) {
258
+ return new Promise((resolve, reject) => {
259
+ let asset = {
260
+ was_vip: 0,
261
+ expire_date: "1970-02-02T16:00:00.000Z",
262
+ total_day: 0,
263
+ was_pro: 0,
264
+ pro_expire_date: "1970-02-02T16:00:00.000Z",
265
+ pro_total_day: 0,
266
+ rename_card_count: 0,
267
+ had_renamed: 0,
268
+ namespace_card_count: 0,
269
+ box_coin: 0,
270
+ points: 0,
271
+ };
272
+ this.asset = asset;
273
+ // 空资产
274
+ resolve(asset);
275
+ });
276
+ } else {
277
+ return $pay()
278
+ .get("/api/vip/i")
279
+ .then(res => {
280
+ let asset = res.data.data;
281
+ this.asset = asset;
282
+ return asset;
283
+ });
284
+ }
285
+ }
286
+
287
+ // 获取用户等级
288
+ getLevel(exp) {
289
+ for (let level in __userLevel) {
290
+ let range = __userLevel[level];
291
+ if (exp >= range[0] && exp < range[1]) {
292
+ return ~~level;
293
+ }
294
+ }
295
+ }
296
+
297
+ // 用户是否有权限
298
+ hasPermission(permission) {
299
+ if (this.getInfo().group >= 512) return true;
300
+ let userPermission = this.getInfo().permission;
301
+ if (userPermission) {
302
+ const permissions = userPermission.split(",");
303
+ return permissions.includes(permission);
304
+ } else {
305
+ return false;
306
+ }
307
+ }
308
+
309
+ // 生成设备指纹
310
+ generateFingerprint(callback) {
311
+ const cache = localStorage.getItem("jx3box_fingerprint");
312
+ if (cache) {
313
+ return cache;
314
+ }
315
+ Fingerprint2.get(function (components) {
316
+ const values = components.map((component) => component.value);
317
+ const murmur = Fingerprint2.x64hash128(values.join(""), 31);
318
+
319
+ localStorage.setItem("jx3box_fingerprint", murmur);
320
+ callback(murmur);
321
+ });
322
+ }
323
+
324
+ // 获取设备指纹
325
+ getDeviceFingerprint() {
326
+ return localStorage.getItem("jx3box_fingerprint");
327
+ }
328
+ }
329
+
330
+ export default new User();
package/js/utils.js CHANGED
@@ -1,15 +1,4 @@
1
- import {
2
- default_avatar,
3
- __sourceType,
4
- __postType,
5
- __wikiType,
6
- __appType,
7
- __gameType,
8
- __imgPath,
9
- __iconPath,
10
- __clients,
11
- __ossMirror,
12
- } from "../data/jx3box.json";
1
+ import { default_avatar, __sourceType, __postType, __wikiType, __appType, __gameType, __imgPath, __iconPath, __clients, __ossMirror } from "../data/jx3box.json";
13
2
  import tvmap from "../data/tvmap.json";
14
3
 
15
4
  export function resolveImagePath(str) {
@@ -26,10 +15,7 @@ export function checkImageLoad(jq) {
26
15
  jq.length &&
27
16
  jq.one("error", function () {
28
17
  var img_url = $(this).attr("src");
29
- var fix_url = img_url.replace(
30
- /cdn\.jx3box\.com/g,
31
- "oss.jx3box.com"
32
- );
18
+ var fix_url = img_url.replace(/cdn\.jx3box\.com/g, "oss.jx3box.com");
33
19
  $(this).attr("src", fix_url);
34
20
  });
35
21
  }
@@ -150,12 +136,7 @@ export function iconLink(icon_id, client = "std") {
150
136
  * 获取应用图标
151
137
  */
152
138
  export function getAppIcon(key, colorful = false) {
153
- return (
154
- __imgPath +
155
- (colorful ? "image/box-colorful/" : "image/box/") +
156
- key +
157
- ".svg"
158
- );
139
+ return __imgPath + (colorful ? "image/box-colorful/" : "image/box/") + key + ".svg";
159
140
  }
160
141
 
161
142
  /**
@@ -189,10 +170,7 @@ export function getLink(type, id, level) {
189
170
  id = id || "";
190
171
 
191
172
  // 核心作品、休闲数据
192
- if (
193
- __sourceType.cms_types.includes(type) ||
194
- __sourceType.pvx_types.includes(type)
195
- ) {
173
+ if (__sourceType.cms_types.includes(type) || __sourceType.pvx_types.includes(type)) {
196
174
  return "/" + type + "/" + id;
197
175
 
198
176
  // 百科类型
@@ -290,13 +268,7 @@ export function getQuery(key) {
290
268
  }
291
269
 
292
270
  export function getTypeLabel(type) {
293
- let types = Object.assign(
294
- {},
295
- __postType,
296
- __wikiType,
297
- __appType,
298
- __gameType
299
- );
271
+ let types = Object.assign({}, __postType, __wikiType, __appType, __gameType);
300
272
  return types[type] || "未知";
301
273
  }
302
274
 
@@ -316,11 +288,7 @@ export function ts2str(timestamp, opt = { polished: true, separator: "-" }) {
316
288
  let year = dt.getFullYear();
317
289
  let month = dt.getMonth() + 1;
318
290
  let date = dt.getDate();
319
- let str = opt.polished
320
- ? `${year}${opt.separator}${polish(month)}${opt.separator}${polish(
321
- date
322
- )}`
323
- : `${year}${opt.separator}${month}${opt.separator}${date}`;
291
+ let str = opt.polished ? `${year}${opt.separator}${polish(month)}${opt.separator}${polish(date)}` : `${year}${opt.separator}${month}${opt.separator}${date}`;
324
292
  return str;
325
293
 
326
294
  function polish(val) {
@@ -340,10 +308,7 @@ export function jx3ClientType() {
340
308
  */
341
309
  export function extractTextContent(str) {
342
310
  if (!str || typeof str !== "string") return [];
343
- const innerHTML = str.replace(
344
- /<Text>(.*?)<\/text>/gimsy,
345
- `<span $1></span>`
346
- );
311
+ const innerHTML = str.replace(/<Text>(.*?)<\/text>/gimsy, `<span $1></span>`);
347
312
  const parser = new DOMParser();
348
313
  const doc = parser.parseFromString(innerHTML, "text/html");
349
314
  const spans = doc.querySelectorAll("span");
@@ -388,8 +353,7 @@ export function showClientLabel(client) {
388
353
  }
389
354
 
390
355
  export function getMedalLink(event_id, subtype) {
391
- if (subtype === "rank" || subtype === "superstar")
392
- return `/rank/race/#/${event_id}/${subtype}`;
356
+ if (subtype === "rank" || subtype === "superstar") return `/rank/race/#/${event_id}/${subtype}`;
393
357
  return `${subtype}/${event_id}`;
394
358
  }
395
359
 
@@ -415,34 +379,33 @@ export function isMiniProgram() {
415
379
  return navigator.userAgent.toLowerCase().includes("miniprogram");
416
380
  }
417
381
 
418
-
419
382
  /**
420
383
  * 判断当前环境是否为app
421
384
  * 判断url是否包含__env=app
422
385
  */
423
386
  export function isApp() {
424
- return new URLSearchParams(window.location.search).get("__env") === "app";
387
+ return new URLSearchParams(window.location.search).get("__env") === "app" || localStorage.getItem("__env") === "app";
425
388
  }
426
389
 
427
390
  export function miniprogramHack() {
428
- document.addEventListener('DOMContentLoaded', function() {
391
+ document.addEventListener("DOMContentLoaded", function () {
429
392
  // 检查 html 标签是否有 wechat-miniprogram 类
430
- if (document.documentElement.classList.contains('wechat-miniprogram')) {
393
+ if (document.documentElement.classList.contains("wechat-miniprogram")) {
431
394
  // 为整个 document 添加一个点击事件监听器
432
- document.addEventListener('click', function(event) {
395
+ document.addEventListener("click", function (event) {
433
396
  // 检查被点击的元素是否是一个链接
434
- if (event.target.tagName === 'A') {
435
- var href = event.target.getAttribute('href');
436
-
397
+ if (event.target.tagName === "A") {
398
+ var href = event.target.getAttribute("href");
399
+
437
400
  // 检查是否是相对链接
438
- var isRelative = !href.startsWith('http://') && !href.startsWith('https://') && !href.startsWith('//');
439
-
401
+ var isRelative = !href.startsWith("http://") && !href.startsWith("https://") && !href.startsWith("//");
402
+
440
403
  // 检查是否是jx3box.com域名
441
404
  var isJx3boxDomain = /jx3box\.com/.test(href);
442
-
405
+
443
406
  // 检查是否是jx3.xoyo.com域名
444
407
  var isJx3Domain = /jx3\.xoyo\.com/.test(href);
445
-
408
+
446
409
  // 如果不是相对链接且不是jx3box.com域名
447
410
  if (!isRelative && !isJx3boxDomain && !isJx3Domain) {
448
411
  // 阻止默认行为
@@ -476,7 +439,6 @@ export function getTokenFromUrl() {
476
439
  }
477
440
  }
478
441
 
479
-
480
442
  export default {
481
443
  resolveImagePath,
482
444
  checkImageLoad,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jx3box/jx3box-common",
3
- "version": "8.7.5",
3
+ "version": "9.0.0",
4
4
  "description": "JX3BOX公共基础模块",
5
5
  "main": "main.js",
6
6
  "repository": {
@@ -12,7 +12,6 @@
12
12
  "axios": "^1.6.8",
13
13
  "cheerio": "1.0.0-rc.12",
14
14
  "dayjs": "^1.11.10",
15
- "element-ui": "^2.13.2",
16
15
  "fingerprintjs2": "^2.1.4",
17
16
  "localforage": "^1.7.3",
18
17
  "uuid": "^9.0.0",