@quantabit/account-link-sdk 1.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/dist/index.esm.js +867 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/index.iife.js +886 -0
- package/dist/index.iife.js.map +1 -0
- package/dist/index.js +885 -0
- package/dist/index.js.map +1 -0
- package/dist/index.umd.js +887 -0
- package/dist/index.umd.js.map +1 -0
- package/package.json +39 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,885 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
5
|
+
|
|
6
|
+
var sdkConfig = require('@quantabit/sdk-config');
|
|
7
|
+
var React = require('react');
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Account Link SDK - API 客户端
|
|
11
|
+
* 子账号关联系统后端接口封装
|
|
12
|
+
*
|
|
13
|
+
* 使用 BaseApiClient 基类简化代码
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* 账号关联 API 客户端
|
|
19
|
+
*/
|
|
20
|
+
class AccountLinkApiClient extends sdkConfig.BaseApiClient {
|
|
21
|
+
constructor(config = {}) {
|
|
22
|
+
super('/account/link', config);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// ============ 关联查询 ============
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* 获取我的关联账号列表
|
|
29
|
+
*/
|
|
30
|
+
async getLinkedAccounts() {
|
|
31
|
+
return this.get('/list');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* 获取关联账号详情
|
|
36
|
+
* @param {string} linkId - 关联 ID
|
|
37
|
+
*/
|
|
38
|
+
async getLinkedAccount(linkId) {
|
|
39
|
+
return this.get(`/${linkId}`);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* 获取关联类型列表
|
|
44
|
+
*/
|
|
45
|
+
async getLinkTypes() {
|
|
46
|
+
return this.get('/types');
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// ============ 创建关联 ============
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* 创建子账号关联
|
|
53
|
+
* @param {Object} linkData - 关联数据
|
|
54
|
+
*/
|
|
55
|
+
async createLink(linkData) {
|
|
56
|
+
return this.post('/create', linkData);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* 发送关联邀请
|
|
61
|
+
* @param {string} targetUserId - 目标用户 ID
|
|
62
|
+
* @param {string} linkType - 关联类型 (family/employee/agent)
|
|
63
|
+
*/
|
|
64
|
+
async sendLinkInvite(targetUserId, linkType) {
|
|
65
|
+
return this.post('/invite', {
|
|
66
|
+
target_user_id: targetUserId,
|
|
67
|
+
link_type: linkType
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* 接受关联邀请
|
|
73
|
+
* @param {string} inviteId - 邀请 ID
|
|
74
|
+
*/
|
|
75
|
+
async acceptInvite(inviteId) {
|
|
76
|
+
return this.post(`/invite/${inviteId}/accept`);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* 拒绝关联邀请
|
|
81
|
+
* @param {string} inviteId - 邀请 ID
|
|
82
|
+
*/
|
|
83
|
+
async rejectInvite(inviteId) {
|
|
84
|
+
return this.post(`/invite/${inviteId}/reject`);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* 获取待处理的邀请
|
|
89
|
+
*/
|
|
90
|
+
async getPendingInvites() {
|
|
91
|
+
return this.get('/invites/pending');
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// ============ 管理关联 ============
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* 更新关联信息
|
|
98
|
+
* @param {string} linkId - 关联 ID
|
|
99
|
+
* @param {Object} updates - 更新数据
|
|
100
|
+
*/
|
|
101
|
+
async updateLink(linkId, updates) {
|
|
102
|
+
return this.put(`/${linkId}`, updates);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* 解除关联
|
|
107
|
+
* @param {string} linkId - 关联 ID
|
|
108
|
+
*/
|
|
109
|
+
async removeLink(linkId) {
|
|
110
|
+
return this.delete(`/${linkId}`);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* 设置关联权限
|
|
115
|
+
* @param {string} linkId - 关联 ID
|
|
116
|
+
* @param {Object} permissions - 权限配置
|
|
117
|
+
*/
|
|
118
|
+
async setLinkPermissions(linkId, permissions) {
|
|
119
|
+
return this.put(`/${linkId}/permissions`, permissions);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* 获取关联权限
|
|
124
|
+
* @param {string} linkId - 关联 ID
|
|
125
|
+
*/
|
|
126
|
+
async getLinkPermissions(linkId) {
|
|
127
|
+
return this.get(`/${linkId}/permissions`);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// ============ 家庭组 ============
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* 创建家庭组
|
|
134
|
+
* @param {Object} groupData - 家庭组数据
|
|
135
|
+
*/
|
|
136
|
+
async createFamilyGroup(groupData) {
|
|
137
|
+
return this.post('/family/create', groupData);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* 获取家庭组信息
|
|
142
|
+
*/
|
|
143
|
+
async getFamilyGroup() {
|
|
144
|
+
return this.get('/family');
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* 添加家庭成员
|
|
149
|
+
* @param {string} userId - 用户 ID
|
|
150
|
+
* @param {string} role - 角色 (parent/child/other)
|
|
151
|
+
*/
|
|
152
|
+
async addFamilyMember(userId, role) {
|
|
153
|
+
return this.post('/family/members', {
|
|
154
|
+
user_id: userId,
|
|
155
|
+
role
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* 移除家庭成员
|
|
161
|
+
* @param {string} memberId - 成员 ID
|
|
162
|
+
*/
|
|
163
|
+
async removeFamilyMember(memberId) {
|
|
164
|
+
return this.delete(`/family/members/${memberId}`);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// ============ 企业员工号 ============
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* 获取企业信息
|
|
171
|
+
*/
|
|
172
|
+
async getEnterprise() {
|
|
173
|
+
return this.get('/enterprise');
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* 获取员工列表
|
|
178
|
+
* @param {Object} params - 查询参数
|
|
179
|
+
*/
|
|
180
|
+
async getEmployees(params = {}) {
|
|
181
|
+
return this.get('/enterprise/employees', params);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* 绑定员工号
|
|
186
|
+
* @param {string} employeeId - 员工 ID
|
|
187
|
+
* @param {string} enterpriseCode - 企业代码
|
|
188
|
+
*/
|
|
189
|
+
async bindEmployee(employeeId, enterpriseCode) {
|
|
190
|
+
return this.post('/enterprise/bind', {
|
|
191
|
+
employee_id: employeeId,
|
|
192
|
+
enterprise_code: enterpriseCode
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* 解绑员工号
|
|
198
|
+
*/
|
|
199
|
+
async unbindEmployee() {
|
|
200
|
+
return this.post('/enterprise/unbind');
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// ============ 代理账号 ============
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* 获取代理的账号列表
|
|
207
|
+
*/
|
|
208
|
+
async getAgentAccounts() {
|
|
209
|
+
return this.get('/agent/accounts');
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* 代理登录
|
|
214
|
+
* @param {string} targetUserId - 目标用户 ID
|
|
215
|
+
*/
|
|
216
|
+
async agentLogin(targetUserId) {
|
|
217
|
+
return this.post('/agent/login', {
|
|
218
|
+
target_user_id: targetUserId
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* 退出代理
|
|
224
|
+
*/
|
|
225
|
+
async exitAgent() {
|
|
226
|
+
return this.post('/agent/exit');
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// 创建默认实例
|
|
231
|
+
const accountLinkApi = new AccountLinkApiClient();
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Account Link SDK - React Hooks
|
|
235
|
+
* 子账号关联功能的 React Hooks
|
|
236
|
+
*/
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* 使用账号关联功能
|
|
241
|
+
*/
|
|
242
|
+
function useAccountLink() {
|
|
243
|
+
const [linkedAccounts, setLinkedAccounts] = React.useState([]);
|
|
244
|
+
const [pendingInvites, setPendingInvites] = React.useState([]);
|
|
245
|
+
const [loading, setLoading] = React.useState(false);
|
|
246
|
+
const [error, setError] = React.useState(null);
|
|
247
|
+
|
|
248
|
+
// 获取关联账号列表
|
|
249
|
+
const fetchLinkedAccounts = React.useCallback(async () => {
|
|
250
|
+
setLoading(true);
|
|
251
|
+
setError(null);
|
|
252
|
+
try {
|
|
253
|
+
const result = await accountLinkApi.getLinkedAccounts();
|
|
254
|
+
setLinkedAccounts(result.data || []);
|
|
255
|
+
return result;
|
|
256
|
+
} catch (err) {
|
|
257
|
+
setError(err.message);
|
|
258
|
+
throw err;
|
|
259
|
+
} finally {
|
|
260
|
+
setLoading(false);
|
|
261
|
+
}
|
|
262
|
+
}, []);
|
|
263
|
+
|
|
264
|
+
// 获取待处理邀请
|
|
265
|
+
const fetchPendingInvites = React.useCallback(async () => {
|
|
266
|
+
try {
|
|
267
|
+
const result = await accountLinkApi.getPendingInvites();
|
|
268
|
+
setPendingInvites(result.data || []);
|
|
269
|
+
return result;
|
|
270
|
+
} catch (err) {
|
|
271
|
+
setError(err.message);
|
|
272
|
+
throw err;
|
|
273
|
+
}
|
|
274
|
+
}, []);
|
|
275
|
+
|
|
276
|
+
// 发送关联邀请
|
|
277
|
+
const sendInvite = React.useCallback(async (targetUserId, linkType) => {
|
|
278
|
+
setLoading(true);
|
|
279
|
+
try {
|
|
280
|
+
const result = await accountLinkApi.sendLinkInvite(targetUserId, linkType);
|
|
281
|
+
return result;
|
|
282
|
+
} catch (err) {
|
|
283
|
+
setError(err.message);
|
|
284
|
+
throw err;
|
|
285
|
+
} finally {
|
|
286
|
+
setLoading(false);
|
|
287
|
+
}
|
|
288
|
+
}, []);
|
|
289
|
+
|
|
290
|
+
// 接受邀请
|
|
291
|
+
const acceptInvite = React.useCallback(async inviteId => {
|
|
292
|
+
setLoading(true);
|
|
293
|
+
try {
|
|
294
|
+
const result = await accountLinkApi.acceptInvite(inviteId);
|
|
295
|
+
await fetchLinkedAccounts();
|
|
296
|
+
await fetchPendingInvites();
|
|
297
|
+
return result;
|
|
298
|
+
} catch (err) {
|
|
299
|
+
setError(err.message);
|
|
300
|
+
throw err;
|
|
301
|
+
} finally {
|
|
302
|
+
setLoading(false);
|
|
303
|
+
}
|
|
304
|
+
}, [fetchLinkedAccounts, fetchPendingInvites]);
|
|
305
|
+
|
|
306
|
+
// 拒绝邀请
|
|
307
|
+
const rejectInvite = React.useCallback(async inviteId => {
|
|
308
|
+
setLoading(true);
|
|
309
|
+
try {
|
|
310
|
+
const result = await accountLinkApi.rejectInvite(inviteId);
|
|
311
|
+
await fetchPendingInvites();
|
|
312
|
+
return result;
|
|
313
|
+
} catch (err) {
|
|
314
|
+
setError(err.message);
|
|
315
|
+
throw err;
|
|
316
|
+
} finally {
|
|
317
|
+
setLoading(false);
|
|
318
|
+
}
|
|
319
|
+
}, [fetchPendingInvites]);
|
|
320
|
+
|
|
321
|
+
// 解除关联
|
|
322
|
+
const removeLink = React.useCallback(async linkId => {
|
|
323
|
+
setLoading(true);
|
|
324
|
+
try {
|
|
325
|
+
const result = await accountLinkApi.removeLink(linkId);
|
|
326
|
+
await fetchLinkedAccounts();
|
|
327
|
+
return result;
|
|
328
|
+
} catch (err) {
|
|
329
|
+
setError(err.message);
|
|
330
|
+
throw err;
|
|
331
|
+
} finally {
|
|
332
|
+
setLoading(false);
|
|
333
|
+
}
|
|
334
|
+
}, [fetchLinkedAccounts]);
|
|
335
|
+
React.useEffect(() => {
|
|
336
|
+
fetchLinkedAccounts();
|
|
337
|
+
fetchPendingInvites();
|
|
338
|
+
}, [fetchLinkedAccounts, fetchPendingInvites]);
|
|
339
|
+
return {
|
|
340
|
+
linkedAccounts,
|
|
341
|
+
pendingInvites,
|
|
342
|
+
loading,
|
|
343
|
+
error,
|
|
344
|
+
fetchLinkedAccounts,
|
|
345
|
+
fetchPendingInvites,
|
|
346
|
+
sendInvite,
|
|
347
|
+
acceptInvite,
|
|
348
|
+
rejectInvite,
|
|
349
|
+
removeLink
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* 使用家庭组功能
|
|
355
|
+
*/
|
|
356
|
+
function useFamilyGroup() {
|
|
357
|
+
const [familyGroup, setFamilyGroup] = React.useState(null);
|
|
358
|
+
const [members, setMembers] = React.useState([]);
|
|
359
|
+
const [loading, setLoading] = React.useState(false);
|
|
360
|
+
const [error, setError] = React.useState(null);
|
|
361
|
+
|
|
362
|
+
// 获取家庭组信息
|
|
363
|
+
const fetchFamilyGroup = React.useCallback(async () => {
|
|
364
|
+
setLoading(true);
|
|
365
|
+
setError(null);
|
|
366
|
+
try {
|
|
367
|
+
const result = await accountLinkApi.getFamilyGroup();
|
|
368
|
+
setFamilyGroup(result.data);
|
|
369
|
+
setMembers(result.data?.members || []);
|
|
370
|
+
return result;
|
|
371
|
+
} catch (err) {
|
|
372
|
+
setError(err.message);
|
|
373
|
+
throw err;
|
|
374
|
+
} finally {
|
|
375
|
+
setLoading(false);
|
|
376
|
+
}
|
|
377
|
+
}, []);
|
|
378
|
+
|
|
379
|
+
// 创建家庭组
|
|
380
|
+
const createFamily = React.useCallback(async groupData => {
|
|
381
|
+
setLoading(true);
|
|
382
|
+
try {
|
|
383
|
+
const result = await accountLinkApi.createFamilyGroup(groupData);
|
|
384
|
+
await fetchFamilyGroup();
|
|
385
|
+
return result;
|
|
386
|
+
} catch (err) {
|
|
387
|
+
setError(err.message);
|
|
388
|
+
throw err;
|
|
389
|
+
} finally {
|
|
390
|
+
setLoading(false);
|
|
391
|
+
}
|
|
392
|
+
}, [fetchFamilyGroup]);
|
|
393
|
+
|
|
394
|
+
// 添加成员
|
|
395
|
+
const addMember = React.useCallback(async (userId, role) => {
|
|
396
|
+
setLoading(true);
|
|
397
|
+
try {
|
|
398
|
+
const result = await accountLinkApi.addFamilyMember(userId, role);
|
|
399
|
+
await fetchFamilyGroup();
|
|
400
|
+
return result;
|
|
401
|
+
} catch (err) {
|
|
402
|
+
setError(err.message);
|
|
403
|
+
throw err;
|
|
404
|
+
} finally {
|
|
405
|
+
setLoading(false);
|
|
406
|
+
}
|
|
407
|
+
}, [fetchFamilyGroup]);
|
|
408
|
+
|
|
409
|
+
// 移除成员
|
|
410
|
+
const removeMember = React.useCallback(async memberId => {
|
|
411
|
+
setLoading(true);
|
|
412
|
+
try {
|
|
413
|
+
const result = await accountLinkApi.removeFamilyMember(memberId);
|
|
414
|
+
await fetchFamilyGroup();
|
|
415
|
+
return result;
|
|
416
|
+
} catch (err) {
|
|
417
|
+
setError(err.message);
|
|
418
|
+
throw err;
|
|
419
|
+
} finally {
|
|
420
|
+
setLoading(false);
|
|
421
|
+
}
|
|
422
|
+
}, [fetchFamilyGroup]);
|
|
423
|
+
React.useEffect(() => {
|
|
424
|
+
fetchFamilyGroup();
|
|
425
|
+
}, [fetchFamilyGroup]);
|
|
426
|
+
return {
|
|
427
|
+
familyGroup,
|
|
428
|
+
members,
|
|
429
|
+
loading,
|
|
430
|
+
error,
|
|
431
|
+
fetchFamilyGroup,
|
|
432
|
+
createFamily,
|
|
433
|
+
addMember,
|
|
434
|
+
removeMember
|
|
435
|
+
};
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
/**
|
|
439
|
+
* Account Link SDK - 账号关联管理组件
|
|
440
|
+
*/
|
|
441
|
+
|
|
442
|
+
|
|
443
|
+
/**
|
|
444
|
+
* 关联账号列表组件
|
|
445
|
+
*/
|
|
446
|
+
function LinkedAccountsList({
|
|
447
|
+
onSelect
|
|
448
|
+
}) {
|
|
449
|
+
const {
|
|
450
|
+
linkedAccounts,
|
|
451
|
+
loading,
|
|
452
|
+
error,
|
|
453
|
+
removeLink
|
|
454
|
+
} = useAccountLink();
|
|
455
|
+
if (loading) {
|
|
456
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
457
|
+
className: "eco-account-link-loading"
|
|
458
|
+
}, "\u52A0\u8F7D\u4E2D...");
|
|
459
|
+
}
|
|
460
|
+
if (error) {
|
|
461
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
462
|
+
className: "eco-account-link-error"
|
|
463
|
+
}, error);
|
|
464
|
+
}
|
|
465
|
+
if (linkedAccounts.length === 0) {
|
|
466
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
467
|
+
className: "eco-account-link-empty"
|
|
468
|
+
}, "\u6682\u65E0\u5173\u8054\u8D26\u53F7");
|
|
469
|
+
}
|
|
470
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
471
|
+
className: "eco-linked-accounts-list"
|
|
472
|
+
}, linkedAccounts.map(account => /*#__PURE__*/React.createElement("div", {
|
|
473
|
+
key: account.id,
|
|
474
|
+
className: "eco-linked-account-item"
|
|
475
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
476
|
+
className: "eco-linked-account-avatar"
|
|
477
|
+
}, account.avatar ? /*#__PURE__*/React.createElement("img", {
|
|
478
|
+
src: account.avatar,
|
|
479
|
+
alt: account.display_name
|
|
480
|
+
}) : /*#__PURE__*/React.createElement("span", null, account.display_name?.[0] || '?')), /*#__PURE__*/React.createElement("div", {
|
|
481
|
+
className: "eco-linked-account-info"
|
|
482
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
483
|
+
className: "eco-linked-account-name"
|
|
484
|
+
}, account.display_name), /*#__PURE__*/React.createElement("div", {
|
|
485
|
+
className: "eco-linked-account-type"
|
|
486
|
+
}, account.link_type)), /*#__PURE__*/React.createElement("div", {
|
|
487
|
+
className: "eco-linked-account-actions"
|
|
488
|
+
}, onSelect && /*#__PURE__*/React.createElement("button", {
|
|
489
|
+
className: "eco-btn eco-btn-sm",
|
|
490
|
+
onClick: () => onSelect(account)
|
|
491
|
+
}, "\u9009\u62E9"), /*#__PURE__*/React.createElement("button", {
|
|
492
|
+
className: "eco-btn eco-btn-sm eco-btn-danger",
|
|
493
|
+
onClick: () => removeLink(account.id)
|
|
494
|
+
}, "\u89E3\u9664")))));
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
/**
|
|
498
|
+
* 待处理邀请组件
|
|
499
|
+
*/
|
|
500
|
+
function PendingInvitesList() {
|
|
501
|
+
const {
|
|
502
|
+
pendingInvites,
|
|
503
|
+
loading,
|
|
504
|
+
acceptInvite,
|
|
505
|
+
rejectInvite
|
|
506
|
+
} = useAccountLink();
|
|
507
|
+
if (loading) {
|
|
508
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
509
|
+
className: "eco-account-link-loading"
|
|
510
|
+
}, "\u52A0\u8F7D\u4E2D...");
|
|
511
|
+
}
|
|
512
|
+
if (pendingInvites.length === 0) {
|
|
513
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
514
|
+
className: "eco-account-link-empty"
|
|
515
|
+
}, "\u6682\u65E0\u5F85\u5904\u7406\u9080\u8BF7");
|
|
516
|
+
}
|
|
517
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
518
|
+
className: "eco-pending-invites-list"
|
|
519
|
+
}, pendingInvites.map(invite => /*#__PURE__*/React.createElement("div", {
|
|
520
|
+
key: invite.id,
|
|
521
|
+
className: "eco-pending-invite-item"
|
|
522
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
523
|
+
className: "eco-invite-info"
|
|
524
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
525
|
+
className: "eco-invite-from"
|
|
526
|
+
}, "\u6765\u81EA: ", invite.from_user?.display_name), /*#__PURE__*/React.createElement("div", {
|
|
527
|
+
className: "eco-invite-type"
|
|
528
|
+
}, "\u7C7B\u578B: ", invite.link_type), /*#__PURE__*/React.createElement("div", {
|
|
529
|
+
className: "eco-invite-time"
|
|
530
|
+
}, new Date(invite.created_at).toLocaleString())), /*#__PURE__*/React.createElement("div", {
|
|
531
|
+
className: "eco-invite-actions"
|
|
532
|
+
}, /*#__PURE__*/React.createElement("button", {
|
|
533
|
+
className: "eco-btn eco-btn-primary eco-btn-sm",
|
|
534
|
+
onClick: () => acceptInvite(invite.id)
|
|
535
|
+
}, "\u63A5\u53D7"), /*#__PURE__*/React.createElement("button", {
|
|
536
|
+
className: "eco-btn eco-btn-sm",
|
|
537
|
+
onClick: () => rejectInvite(invite.id)
|
|
538
|
+
}, "\u62D2\u7EDD")))));
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
/**
|
|
542
|
+
* 发送邀请表单
|
|
543
|
+
*/
|
|
544
|
+
function SendInviteForm({
|
|
545
|
+
onSuccess
|
|
546
|
+
}) {
|
|
547
|
+
const [userId, setUserId] = React.useState('');
|
|
548
|
+
const [linkType, setLinkType] = React.useState('family');
|
|
549
|
+
const {
|
|
550
|
+
sendInvite,
|
|
551
|
+
loading,
|
|
552
|
+
error
|
|
553
|
+
} = useAccountLink();
|
|
554
|
+
const handleSubmit = async e => {
|
|
555
|
+
e.preventDefault();
|
|
556
|
+
try {
|
|
557
|
+
await sendInvite(userId, linkType);
|
|
558
|
+
setUserId('');
|
|
559
|
+
onSuccess?.();
|
|
560
|
+
} catch (err) {
|
|
561
|
+
// 错误已在 hook 中处理
|
|
562
|
+
}
|
|
563
|
+
};
|
|
564
|
+
return /*#__PURE__*/React.createElement("form", {
|
|
565
|
+
className: "eco-send-invite-form",
|
|
566
|
+
onSubmit: handleSubmit
|
|
567
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
568
|
+
className: "eco-form-group"
|
|
569
|
+
}, /*#__PURE__*/React.createElement("label", null, "\u7528\u6237 ID"), /*#__PURE__*/React.createElement("input", {
|
|
570
|
+
type: "text",
|
|
571
|
+
value: userId,
|
|
572
|
+
onChange: e => setUserId(e.target.value),
|
|
573
|
+
placeholder: "\u8F93\u5165\u8981\u9080\u8BF7\u7684\u7528\u6237 ID",
|
|
574
|
+
required: true
|
|
575
|
+
})), /*#__PURE__*/React.createElement("div", {
|
|
576
|
+
className: "eco-form-group"
|
|
577
|
+
}, /*#__PURE__*/React.createElement("label", null, "\u5173\u8054\u7C7B\u578B"), /*#__PURE__*/React.createElement("select", {
|
|
578
|
+
value: linkType,
|
|
579
|
+
onChange: e => setLinkType(e.target.value)
|
|
580
|
+
}, /*#__PURE__*/React.createElement("option", {
|
|
581
|
+
value: "family"
|
|
582
|
+
}, "\u5BB6\u5EAD\u6210\u5458"), /*#__PURE__*/React.createElement("option", {
|
|
583
|
+
value: "employee"
|
|
584
|
+
}, "\u4F01\u4E1A\u5458\u5DE5"), /*#__PURE__*/React.createElement("option", {
|
|
585
|
+
value: "agent"
|
|
586
|
+
}, "\u4EE3\u7406\u8D26\u53F7"))), error && /*#__PURE__*/React.createElement("div", {
|
|
587
|
+
className: "eco-form-error"
|
|
588
|
+
}, error), /*#__PURE__*/React.createElement("button", {
|
|
589
|
+
type: "submit",
|
|
590
|
+
className: "eco-btn eco-btn-primary",
|
|
591
|
+
disabled: loading
|
|
592
|
+
}, loading ? '发送中...' : '发送邀请'));
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
/**
|
|
596
|
+
* 家庭组管理组件
|
|
597
|
+
*/
|
|
598
|
+
function FamilyGroupManager() {
|
|
599
|
+
const {
|
|
600
|
+
familyGroup,
|
|
601
|
+
members,
|
|
602
|
+
loading,
|
|
603
|
+
createFamily,
|
|
604
|
+
addMember,
|
|
605
|
+
removeMember
|
|
606
|
+
} = useFamilyGroup();
|
|
607
|
+
const [showAddForm, setShowAddForm] = React.useState(false);
|
|
608
|
+
const [newMemberId, setNewMemberId] = React.useState('');
|
|
609
|
+
const [newMemberRole, setNewMemberRole] = React.useState('other');
|
|
610
|
+
const handleAddMember = async e => {
|
|
611
|
+
e.preventDefault();
|
|
612
|
+
try {
|
|
613
|
+
await addMember(newMemberId, newMemberRole);
|
|
614
|
+
setNewMemberId('');
|
|
615
|
+
setShowAddForm(false);
|
|
616
|
+
} catch (err) {
|
|
617
|
+
// 错误已在 hook 中处理
|
|
618
|
+
}
|
|
619
|
+
};
|
|
620
|
+
if (loading) {
|
|
621
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
622
|
+
className: "eco-family-loading"
|
|
623
|
+
}, "\u52A0\u8F7D\u4E2D...");
|
|
624
|
+
}
|
|
625
|
+
if (!familyGroup) {
|
|
626
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
627
|
+
className: "eco-family-empty"
|
|
628
|
+
}, /*#__PURE__*/React.createElement("p", null, "\u60A8\u8FD8\u6CA1\u6709\u5BB6\u5EAD\u7EC4"), /*#__PURE__*/React.createElement("button", {
|
|
629
|
+
className: "eco-btn eco-btn-primary",
|
|
630
|
+
onClick: () => createFamily({
|
|
631
|
+
name: '我的家庭'
|
|
632
|
+
})
|
|
633
|
+
}, "\u521B\u5EFA\u5BB6\u5EAD\u7EC4"));
|
|
634
|
+
}
|
|
635
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
636
|
+
className: "eco-family-manager"
|
|
637
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
638
|
+
className: "eco-family-header"
|
|
639
|
+
}, /*#__PURE__*/React.createElement("h3", null, familyGroup.name), /*#__PURE__*/React.createElement("span", {
|
|
640
|
+
className: "eco-family-count"
|
|
641
|
+
}, members.length, " \u4F4D\u6210\u5458")), /*#__PURE__*/React.createElement("div", {
|
|
642
|
+
className: "eco-family-members"
|
|
643
|
+
}, members.map(member => /*#__PURE__*/React.createElement("div", {
|
|
644
|
+
key: member.id,
|
|
645
|
+
className: "eco-family-member"
|
|
646
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
647
|
+
className: "eco-member-avatar"
|
|
648
|
+
}, member.avatar ? /*#__PURE__*/React.createElement("img", {
|
|
649
|
+
src: member.avatar,
|
|
650
|
+
alt: member.display_name
|
|
651
|
+
}) : /*#__PURE__*/React.createElement("span", null, member.display_name?.[0] || '?')), /*#__PURE__*/React.createElement("div", {
|
|
652
|
+
className: "eco-member-info"
|
|
653
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
654
|
+
className: "eco-member-name"
|
|
655
|
+
}, member.display_name), /*#__PURE__*/React.createElement("div", {
|
|
656
|
+
className: "eco-member-role"
|
|
657
|
+
}, member.role)), /*#__PURE__*/React.createElement("button", {
|
|
658
|
+
className: "eco-btn eco-btn-sm eco-btn-danger",
|
|
659
|
+
onClick: () => removeMember(member.id)
|
|
660
|
+
}, "\u79FB\u9664")))), showAddForm ? /*#__PURE__*/React.createElement("form", {
|
|
661
|
+
className: "eco-add-member-form",
|
|
662
|
+
onSubmit: handleAddMember
|
|
663
|
+
}, /*#__PURE__*/React.createElement("input", {
|
|
664
|
+
type: "text",
|
|
665
|
+
value: newMemberId,
|
|
666
|
+
onChange: e => setNewMemberId(e.target.value),
|
|
667
|
+
placeholder: "\u6210\u5458 ID",
|
|
668
|
+
required: true
|
|
669
|
+
}), /*#__PURE__*/React.createElement("select", {
|
|
670
|
+
value: newMemberRole,
|
|
671
|
+
onChange: e => setNewMemberRole(e.target.value)
|
|
672
|
+
}, /*#__PURE__*/React.createElement("option", {
|
|
673
|
+
value: "parent"
|
|
674
|
+
}, "\u5BB6\u957F"), /*#__PURE__*/React.createElement("option", {
|
|
675
|
+
value: "child"
|
|
676
|
+
}, "\u5B50\u5973"), /*#__PURE__*/React.createElement("option", {
|
|
677
|
+
value: "other"
|
|
678
|
+
}, "\u5176\u4ED6")), /*#__PURE__*/React.createElement("button", {
|
|
679
|
+
type: "submit",
|
|
680
|
+
className: "eco-btn eco-btn-primary eco-btn-sm"
|
|
681
|
+
}, "\u6DFB\u52A0"), /*#__PURE__*/React.createElement("button", {
|
|
682
|
+
type: "button",
|
|
683
|
+
className: "eco-btn eco-btn-sm",
|
|
684
|
+
onClick: () => setShowAddForm(false)
|
|
685
|
+
}, "\u53D6\u6D88")) : /*#__PURE__*/React.createElement("button", {
|
|
686
|
+
className: "eco-btn eco-btn-outline",
|
|
687
|
+
onClick: () => setShowAddForm(true)
|
|
688
|
+
}, "+ \u6DFB\u52A0\u6210\u5458"));
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
/**
|
|
692
|
+
* 账号关联管理面板
|
|
693
|
+
*/
|
|
694
|
+
function AccountLinkPanel() {
|
|
695
|
+
const [activeTab, setActiveTab] = React.useState('linked');
|
|
696
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
697
|
+
className: "eco-account-link-panel"
|
|
698
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
699
|
+
className: "eco-panel-tabs"
|
|
700
|
+
}, /*#__PURE__*/React.createElement("button", {
|
|
701
|
+
className: `eco-tab ${activeTab === 'linked' ? 'active' : ''}`,
|
|
702
|
+
onClick: () => setActiveTab('linked')
|
|
703
|
+
}, "\u5DF2\u5173\u8054"), /*#__PURE__*/React.createElement("button", {
|
|
704
|
+
className: `eco-tab ${activeTab === 'pending' ? 'active' : ''}`,
|
|
705
|
+
onClick: () => setActiveTab('pending')
|
|
706
|
+
}, "\u5F85\u5904\u7406"), /*#__PURE__*/React.createElement("button", {
|
|
707
|
+
className: `eco-tab ${activeTab === 'family' ? 'active' : ''}`,
|
|
708
|
+
onClick: () => setActiveTab('family')
|
|
709
|
+
}, "\u5BB6\u5EAD\u7EC4"), /*#__PURE__*/React.createElement("button", {
|
|
710
|
+
className: `eco-tab ${activeTab === 'invite' ? 'active' : ''}`,
|
|
711
|
+
onClick: () => setActiveTab('invite')
|
|
712
|
+
}, "\u9080\u8BF7")), /*#__PURE__*/React.createElement("div", {
|
|
713
|
+
className: "eco-panel-content"
|
|
714
|
+
}, activeTab === 'linked' && /*#__PURE__*/React.createElement(LinkedAccountsList, null), activeTab === 'pending' && /*#__PURE__*/React.createElement(PendingInvitesList, null), activeTab === 'family' && /*#__PURE__*/React.createElement(FamilyGroupManager, null), activeTab === 'invite' && /*#__PURE__*/React.createElement(SendInviteForm, null)));
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
/**
|
|
718
|
+
* Account Link SDK - 国际化
|
|
719
|
+
*/
|
|
720
|
+
|
|
721
|
+
const zh = {
|
|
722
|
+
accountLink: {
|
|
723
|
+
title: '关联账号',
|
|
724
|
+
subtitle: '管理您的子账号和家庭组',
|
|
725
|
+
linkedAccounts: '已关联账号',
|
|
726
|
+
noLinkedAccounts: '暂无关联账号',
|
|
727
|
+
pendingInvites: '待处理邀请',
|
|
728
|
+
noPendingInvites: '暂无待处理邀请',
|
|
729
|
+
// 关联类型
|
|
730
|
+
linkType: {
|
|
731
|
+
family: '家庭成员',
|
|
732
|
+
employee: '企业员工',
|
|
733
|
+
agent: '代理账号',
|
|
734
|
+
child: '子账号'
|
|
735
|
+
},
|
|
736
|
+
// 操作
|
|
737
|
+
actions: {
|
|
738
|
+
sendInvite: '发送邀请',
|
|
739
|
+
accept: '接受',
|
|
740
|
+
reject: '拒绝',
|
|
741
|
+
remove: '解除关联',
|
|
742
|
+
setPermissions: '设置权限'
|
|
743
|
+
},
|
|
744
|
+
// 家庭组
|
|
745
|
+
family: {
|
|
746
|
+
title: '家庭组',
|
|
747
|
+
create: '创建家庭组',
|
|
748
|
+
members: '家庭成员',
|
|
749
|
+
addMember: '添加成员',
|
|
750
|
+
removeMember: '移除成员',
|
|
751
|
+
roles: {
|
|
752
|
+
parent: '家长',
|
|
753
|
+
child: '子女',
|
|
754
|
+
other: '其他'
|
|
755
|
+
}
|
|
756
|
+
},
|
|
757
|
+
// 企业
|
|
758
|
+
enterprise: {
|
|
759
|
+
title: '企业账号',
|
|
760
|
+
bind: '绑定员工号',
|
|
761
|
+
unbind: '解绑',
|
|
762
|
+
employeeId: '员工 ID',
|
|
763
|
+
enterpriseCode: '企业代码'
|
|
764
|
+
},
|
|
765
|
+
// 消息
|
|
766
|
+
messages: {
|
|
767
|
+
inviteSent: '邀请已发送',
|
|
768
|
+
inviteAccepted: '已接受邀请',
|
|
769
|
+
inviteRejected: '已拒绝邀请',
|
|
770
|
+
linkRemoved: '已解除关联',
|
|
771
|
+
familyCreated: '家庭组创建成功',
|
|
772
|
+
memberAdded: '成员添加成功',
|
|
773
|
+
memberRemoved: '成员移除成功'
|
|
774
|
+
},
|
|
775
|
+
// 错误
|
|
776
|
+
errors: {
|
|
777
|
+
fetchFailed: '获取关联账号失败',
|
|
778
|
+
inviteFailed: '发送邀请失败',
|
|
779
|
+
acceptFailed: '接受邀请失败',
|
|
780
|
+
removeFailed: '解除关联失败'
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
};
|
|
784
|
+
const en = {
|
|
785
|
+
accountLink: {
|
|
786
|
+
title: 'Linked Accounts',
|
|
787
|
+
subtitle: 'Manage your sub-accounts and family group',
|
|
788
|
+
linkedAccounts: 'Linked Accounts',
|
|
789
|
+
noLinkedAccounts: 'No linked accounts',
|
|
790
|
+
pendingInvites: 'Pending Invites',
|
|
791
|
+
noPendingInvites: 'No pending invites',
|
|
792
|
+
linkType: {
|
|
793
|
+
family: 'Family Member',
|
|
794
|
+
employee: 'Employee',
|
|
795
|
+
agent: 'Agent Account',
|
|
796
|
+
child: 'Sub Account'
|
|
797
|
+
},
|
|
798
|
+
actions: {
|
|
799
|
+
sendInvite: 'Send Invite',
|
|
800
|
+
accept: 'Accept',
|
|
801
|
+
reject: 'Reject',
|
|
802
|
+
remove: 'Remove Link',
|
|
803
|
+
setPermissions: 'Set Permissions'
|
|
804
|
+
},
|
|
805
|
+
family: {
|
|
806
|
+
title: 'Family Group',
|
|
807
|
+
create: 'Create Family Group',
|
|
808
|
+
members: 'Family Members',
|
|
809
|
+
addMember: 'Add Member',
|
|
810
|
+
removeMember: 'Remove Member',
|
|
811
|
+
roles: {
|
|
812
|
+
parent: 'Parent',
|
|
813
|
+
child: 'Child',
|
|
814
|
+
other: 'Other'
|
|
815
|
+
}
|
|
816
|
+
},
|
|
817
|
+
enterprise: {
|
|
818
|
+
title: 'Enterprise Account',
|
|
819
|
+
bind: 'Bind Employee ID',
|
|
820
|
+
unbind: 'Unbind',
|
|
821
|
+
employeeId: 'Employee ID',
|
|
822
|
+
enterpriseCode: 'Enterprise Code'
|
|
823
|
+
},
|
|
824
|
+
messages: {
|
|
825
|
+
inviteSent: 'Invite sent',
|
|
826
|
+
inviteAccepted: 'Invite accepted',
|
|
827
|
+
inviteRejected: 'Invite rejected',
|
|
828
|
+
linkRemoved: 'Link removed',
|
|
829
|
+
familyCreated: 'Family group created',
|
|
830
|
+
memberAdded: 'Member added',
|
|
831
|
+
memberRemoved: 'Member removed'
|
|
832
|
+
},
|
|
833
|
+
errors: {
|
|
834
|
+
fetchFailed: 'Failed to fetch linked accounts',
|
|
835
|
+
inviteFailed: 'Failed to send invite',
|
|
836
|
+
acceptFailed: 'Failed to accept invite',
|
|
837
|
+
removeFailed: 'Failed to remove link'
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
};
|
|
841
|
+
|
|
842
|
+
/**
|
|
843
|
+
* @quantabit/account-link-sdk - 子账号关联 SDK
|
|
844
|
+
*
|
|
845
|
+
* 支持家庭组、企业员工、代理账号等多种关联模式
|
|
846
|
+
*/
|
|
847
|
+
|
|
848
|
+
// 类型定义
|
|
849
|
+
const LinkType = {
|
|
850
|
+
FAMILY: 'family',
|
|
851
|
+
ENTERPRISE: 'enterprise',
|
|
852
|
+
GUARDIAN: 'guardian',
|
|
853
|
+
AGENT: 'agent',
|
|
854
|
+
CHILD: 'child'
|
|
855
|
+
};
|
|
856
|
+
const LinkRole = {
|
|
857
|
+
OWNER: 'owner',
|
|
858
|
+
ADMIN: 'admin',
|
|
859
|
+
MEMBER: 'member',
|
|
860
|
+
CHILD: 'child',
|
|
861
|
+
PARENT: 'parent'
|
|
862
|
+
};
|
|
863
|
+
const LinkStatus = {
|
|
864
|
+
PENDING: 'pending',
|
|
865
|
+
ACTIVE: 'active',
|
|
866
|
+
REJECTED: 'rejected',
|
|
867
|
+
REMOVED: 'removed'
|
|
868
|
+
};
|
|
869
|
+
|
|
870
|
+
exports.AccountLinkApiClient = AccountLinkApiClient;
|
|
871
|
+
exports.AccountLinkPanel = AccountLinkPanel;
|
|
872
|
+
exports.FamilyGroupManager = FamilyGroupManager;
|
|
873
|
+
exports.LinkRole = LinkRole;
|
|
874
|
+
exports.LinkStatus = LinkStatus;
|
|
875
|
+
exports.LinkType = LinkType;
|
|
876
|
+
exports.LinkedAccountsList = LinkedAccountsList;
|
|
877
|
+
exports.PendingInvitesList = PendingInvitesList;
|
|
878
|
+
exports.SendInviteForm = SendInviteForm;
|
|
879
|
+
exports.accountLinkApi = accountLinkApi;
|
|
880
|
+
exports.default = accountLinkApi;
|
|
881
|
+
exports.en = en;
|
|
882
|
+
exports.useAccountLink = useAccountLink;
|
|
883
|
+
exports.useFamilyGroup = useFamilyGroup;
|
|
884
|
+
exports.zh = zh;
|
|
885
|
+
//# sourceMappingURL=index.js.map
|