@heybox/hb-sdk 0.4.6 → 0.5.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.
Files changed (37) hide show
  1. package/README.md +39 -5
  2. package/dist/cli-chunks/{create-BahMMgJH.cjs → create-BiCyOEAv.cjs} +1 -1
  3. package/dist/cli-chunks/{dev-CTuXVPpU.cjs → dev-D4XRqzz1.cjs} +1 -1
  4. package/dist/cli-chunks/{doctor-9gg3ZIvt.cjs → doctor-CmHZYQ2I.cjs} +1 -1
  5. package/dist/cli-chunks/{index-CLne_LW7.cjs → index-DXS0s9d7.cjs} +2 -2
  6. package/dist/cli-chunks/{index-DuwxUSkq.cjs → index-kv8oOmFw.cjs} +13 -13
  7. package/dist/cli-chunks/{login-OqaEx-Wd.cjs → login-F9AEL3cF.cjs} +2 -2
  8. package/dist/cli-chunks/{remote-zX17hOT4.cjs → remote-BRktlraB.cjs} +210 -91
  9. package/dist/cli-chunks/{session-D7lF9mpd.cjs → session-DItg0094.cjs} +1 -1
  10. package/dist/cli.cjs +1 -1
  11. package/dist/devtools/mock-host/main.js +987 -7
  12. package/dist/index.cjs.js +51 -0
  13. package/dist/index.esm.js +51 -0
  14. package/dist/miniapp-publish.cjs.js +16 -0
  15. package/dist/miniapp-publish.esm.js +14 -1
  16. package/dist/protocol.cjs.js +50 -0
  17. package/dist/protocol.esm.js +46 -1
  18. package/dist/templates/vue3-vite-ts/README.md.ejs +2 -1
  19. package/package.json +1 -1
  20. package/skill/SKILL.md +1 -1
  21. package/skill/references/api-protocol.md +22 -2
  22. package/skill/references/api-root.md +70 -2
  23. package/skill/references/cli.md +6 -3
  24. package/skill/references/safety-boundaries.md +2 -1
  25. package/skill/skill.json +4 -4
  26. package/types/index.d.ts +1 -1
  27. package/types/miniapp-publish/index.d.ts +10 -0
  28. package/types/modules/share/types.d.ts +2 -2
  29. package/types/modules/user/get-current-user-detail.d.ts +9 -0
  30. package/types/modules/user/get-current-user-profile.d.ts +9 -0
  31. package/types/modules/user/get-platform-account-info.d.ts +12 -0
  32. package/types/modules/user/get-platform-account-overview.d.ts +9 -0
  33. package/types/modules/user/get-steam-game-list.d.ts +12 -0
  34. package/types/modules/user/index.d.ts +33 -1
  35. package/types/modules/user/types.d.ts +285 -0
  36. package/types/protocol/capabilities.d.ts +52 -2
  37. package/types/protocol.d.ts +2 -2
@@ -19,6 +19,16 @@ const AUTH_LOGIN_METHOD = 'auth.login';
19
19
  * 供 SDK 与父容器 runtime 共享同一 bridge method 标识。
20
20
  */
21
21
  const USER_GET_INFO_METHOD = 'user.getInfo';
22
+ /** 当前用户展示详情能力方法名。 */
23
+ const USER_GET_CURRENT_USER_DETAIL_METHOD = 'user.getCurrentUserDetail';
24
+ /** 当前用户敏感资料详情能力方法名。 */
25
+ const USER_GET_CURRENT_USER_PROFILE_METHOD = 'user.getCurrentUserProfile';
26
+ /** 当前用户平台账号概览能力方法名。 */
27
+ const USER_GET_PLATFORM_ACCOUNT_OVERVIEW_METHOD = 'user.getPlatformAccountOverview';
28
+ /** 当前用户指定平台账号详情能力方法名。 */
29
+ const USER_GET_PLATFORM_ACCOUNT_INFO_METHOD = 'user.getPlatformAccountInfo';
30
+ /** 当前用户 Steam 游戏库能力方法名。 */
31
+ const USER_GET_STEAM_GAME_LIST_METHOD = 'user.getSteamGameList';
22
32
  /**
23
33
  * 展示分享面板能力方法名。
24
34
  *
@@ -103,6 +113,41 @@ const MINI_PROGRAM_PROTOCOL_CAPABILITIES = [
103
113
  permission: 'user.getInfo',
104
114
  risk: 'medium',
105
115
  },
116
+ {
117
+ method: USER_GET_CURRENT_USER_DETAIL_METHOD,
118
+ module: 'user',
119
+ capability: USER_GET_CURRENT_USER_DETAIL_METHOD,
120
+ permission: 'user.currentUserDetail',
121
+ risk: 'high',
122
+ },
123
+ {
124
+ method: USER_GET_CURRENT_USER_PROFILE_METHOD,
125
+ module: 'user',
126
+ capability: USER_GET_CURRENT_USER_PROFILE_METHOD,
127
+ permission: 'user.currentUserProfile',
128
+ risk: 'high',
129
+ },
130
+ {
131
+ method: USER_GET_PLATFORM_ACCOUNT_OVERVIEW_METHOD,
132
+ module: 'user',
133
+ capability: USER_GET_PLATFORM_ACCOUNT_OVERVIEW_METHOD,
134
+ permission: 'user.platformAccount.overview',
135
+ risk: 'medium',
136
+ },
137
+ {
138
+ method: USER_GET_PLATFORM_ACCOUNT_INFO_METHOD,
139
+ module: 'user',
140
+ capability: USER_GET_PLATFORM_ACCOUNT_INFO_METHOD,
141
+ permission: 'user.platformAccount.info',
142
+ risk: 'high',
143
+ },
144
+ {
145
+ method: USER_GET_STEAM_GAME_LIST_METHOD,
146
+ module: 'user',
147
+ capability: USER_GET_STEAM_GAME_LIST_METHOD,
148
+ permission: 'user.steamGameList',
149
+ risk: 'high',
150
+ },
106
151
  {
107
152
  method: SHARE_SHOW_SHARE_MENU_METHOD,
108
153
  module: 'share',
@@ -3306,11 +3351,16 @@ async function loginAndGetMiniProgramRuntimeUserInfo(platformAdapter) {
3306
3351
  const DEFAULT_STORAGE_KEY_MAX_LENGTH = 128;
3307
3352
  const STORAGE_KEY_CHAR_RE = /^[A-Za-z0-9_-]+$/;
3308
3353
  function createMiniProgramRuntimeBridgeError(code, message, data) {
3309
- return {
3354
+ return data === undefined
3355
+ ? {
3310
3356
  code,
3311
3357
  message,
3312
3358
  }
3313
- ;
3359
+ : {
3360
+ code,
3361
+ message,
3362
+ data,
3363
+ };
3314
3364
  }
3315
3365
  function isMiniProgramRuntimeRecord(value) {
3316
3366
  return typeof value === 'object' && value !== null && !Array.isArray(value);
@@ -3686,14 +3736,14 @@ function readScreenshotRect(value) {
3686
3736
  }
3687
3737
 
3688
3738
  /** 展示基础分享面板。 */
3689
- function showMiniProgramRuntimeShareMenu(payload, platformAdapter) {
3690
- return platformAdapter.share.showShareMenu(readMiniProgramShareMenuOptions(payload));
3739
+ function showMiniProgramRuntimeShareMenu(payload, platformAdapter, context = {}) {
3740
+ return platformAdapter.share.showShareMenu(readMiniProgramShareMenuOptions(payload, platformAdapter, context));
3691
3741
  }
3692
- function readMiniProgramShareMenuOptions(payload) {
3742
+ function readMiniProgramShareMenuOptions(payload, platformAdapter, context) {
3693
3743
  assertMiniProgramRuntimeRecord(payload, 'share.showShareMenu 参数必须是对象');
3694
3744
  const title = readMiniProgramRuntimeRequiredString(payload.title, 'share.showShareMenu title 必须是非空字符串');
3695
3745
  const desc = readMiniProgramRuntimeRequiredString(payload.desc, 'share.showShareMenu desc 必须是非空字符串');
3696
- const url = readMiniProgramRuntimeHttpUrl(payload.url, 'share.showShareMenu url 必须是 HTTP(S) URL');
3746
+ const url = readMiniProgramShareUrl(payload.url, platformAdapter, context);
3697
3747
  const imageUrl = payload.imageUrl === undefined
3698
3748
  ? undefined
3699
3749
  : readMiniProgramRuntimeHttpUrl(payload.imageUrl, 'share.showShareMenu imageUrl 必须是 HTTP(S) URL');
@@ -3709,6 +3759,33 @@ function readMiniProgramShareMenuOptions(payload) {
3709
3759
  channel,
3710
3760
  };
3711
3761
  }
3762
+ function readMiniProgramShareUrl(value, platformAdapter, context) {
3763
+ if (typeof value === 'string' && value.trim()) {
3764
+ return readMiniProgramRuntimeHttpUrl(value, 'share.showShareMenu url 必须是 HTTP(S) URL');
3765
+ }
3766
+ if (value !== undefined && value !== null && value !== '') {
3767
+ throw createMiniProgramRuntimeBridgeError('INVALID_PARAMS', 'share.showShareMenu url 必须是 HTTP(S) URL');
3768
+ }
3769
+ return createUserMiniprogramShareUrl(platformAdapter, context);
3770
+ }
3771
+ function createUserMiniprogramShareUrl(platformAdapter, context) {
3772
+ const miniProgramId = context.miniProgramId?.trim();
3773
+ if (!miniProgramId) {
3774
+ throw createMiniProgramRuntimeBridgeError('INVALID_PARAMS', 'share.showShareMenu url 必须是 HTTP(S) URL');
3775
+ }
3776
+ try {
3777
+ const shareUrl = new URL('/tools/common_share', platformAdapter.app.getCurrentHref());
3778
+ shareUrl.searchParams.set('user_miniprogram_id', miniProgramId);
3779
+ const miniProgramVersion = context.miniProgramVersion?.trim();
3780
+ if (miniProgramVersion) {
3781
+ shareUrl.searchParams.set('miniprogram_version', miniProgramVersion);
3782
+ }
3783
+ return shareUrl.href;
3784
+ }
3785
+ catch {
3786
+ throw createMiniProgramRuntimeBridgeError('INVALID_PARAMS', 'share.showShareMenu url 必须是 HTTP(S) URL');
3787
+ }
3788
+ }
3712
3789
  function isShareChannel(value) {
3713
3790
  return (value === 'wechatSession' ||
3714
3791
  value === 'wechatTimeline' ||
@@ -3807,6 +3884,662 @@ function hashString(value) {
3807
3884
  return (hash >>> 0).toString(36);
3808
3885
  }
3809
3886
 
3887
+ const SUPPORTED_PLATFORM_ACCOUNT_TYPES = [
3888
+ 'steam',
3889
+ 'epic',
3890
+ 'xbox',
3891
+ 'psn',
3892
+ 'switch',
3893
+ 'pc_hardware',
3894
+ 'mobile',
3895
+ ];
3896
+ const SUPPORTED_PLATFORM_ACCOUNT_TYPE_SET = new Set(SUPPORTED_PLATFORM_ACCOUNT_TYPES);
3897
+ function isPlatformAccountType(value) {
3898
+ return typeof value === 'string' && SUPPORTED_PLATFORM_ACCOUNT_TYPE_SET.has(value);
3899
+ }
3900
+ function readPlatformAccountType(payload) {
3901
+ if (!isMiniProgramRuntimeRecord(payload)) {
3902
+ throw createMiniProgramRuntimeBridgeError('INVALID_PARAMS', 'user.getPlatformAccountInfo 参数必须是对象');
3903
+ }
3904
+ const invalidKeys = Object.keys(payload).filter(key => key !== 'platform');
3905
+ if (invalidKeys.length > 0) {
3906
+ throw createMiniProgramRuntimeBridgeError('INVALID_PARAMS', `user.getPlatformAccountInfo 不支持字段: ${invalidKeys.join(', ')}`);
3907
+ }
3908
+ if (!isPlatformAccountType(payload.platform)) {
3909
+ throw createMiniProgramRuntimeBridgeError('INVALID_PARAMS', 'user.getPlatformAccountInfo platform 不支持');
3910
+ }
3911
+ return payload.platform;
3912
+ }
3913
+
3914
+ const DEFAULT_LIMIT = 20;
3915
+ const MAX_LIMIT = 100;
3916
+ const DEFAULT_OFFSET = 0;
3917
+ const DEFAULT_SORT = 'weeks';
3918
+ const SUPPORTED_SORTS = new Set(['weeks', 'all', 'achieved']);
3919
+ const MAX_QUERY_LENGTH = 100;
3920
+ function readSteamGameListRequest(payload) {
3921
+ if (payload === undefined || payload === null) {
3922
+ return {
3923
+ limit: DEFAULT_LIMIT,
3924
+ offset: DEFAULT_OFFSET,
3925
+ sort: DEFAULT_SORT,
3926
+ includeHidden: false,
3927
+ };
3928
+ }
3929
+ if (!isMiniProgramRuntimeRecord(payload)) {
3930
+ throw createMiniProgramRuntimeBridgeError('INVALID_PARAMS', 'user.getSteamGameList 参数必须是对象');
3931
+ }
3932
+ const invalidKeys = Object.keys(payload).filter(key => ![
3933
+ 'steamId',
3934
+ 'limit',
3935
+ 'offset',
3936
+ 'sort',
3937
+ 'q',
3938
+ 'includeHidden',
3939
+ ].includes(key));
3940
+ if (invalidKeys.length > 0) {
3941
+ throw createMiniProgramRuntimeBridgeError('INVALID_PARAMS', `user.getSteamGameList 不支持字段: ${invalidKeys.join(', ')}`);
3942
+ }
3943
+ return {
3944
+ ...readOptionalSteamId(payload.steamId),
3945
+ limit: readLimit(payload.limit),
3946
+ offset: readOffset(payload.offset),
3947
+ sort: readSort(payload.sort),
3948
+ ...readOptionalQuery(payload.q),
3949
+ includeHidden: readBoolean(payload.includeHidden, false),
3950
+ };
3951
+ }
3952
+ async function getMiniProgramRuntimeSteamGameList(payload, platformAdapter, home) {
3953
+ const request = readSteamGameListRequest(payload);
3954
+ if (!home) {
3955
+ return {
3956
+ isLogin: false,
3957
+ isBound: false,
3958
+ data: null,
3959
+ };
3960
+ }
3961
+ const steamInfo = readRecord$1(home.steam_id_info);
3962
+ if (Object.keys(steamInfo).length === 0) {
3963
+ return {
3964
+ isLogin: true,
3965
+ isBound: false,
3966
+ data: null,
3967
+ };
3968
+ }
3969
+ const envelope = await requestSteamGameListEnvelope(platformAdapter, {
3970
+ ...request,
3971
+ personalInformationOpen: readOptionalBoolean(steamInfo.personal_infomation_open ?? steamInfo.personal_information_open),
3972
+ });
3973
+ return {
3974
+ isLogin: true,
3975
+ isBound: true,
3976
+ data: mapSteamGameListData(envelope, request),
3977
+ };
3978
+ }
3979
+ function requestSteamGameListEnvelope(platformAdapter, request) {
3980
+ if (!platformAdapter.user.getCurrentUserSteamGameListEnvelope) {
3981
+ throw createMiniProgramRuntimeBridgeError('UNSUPPORTED', '当前平台不支持读取 Steam 游戏库');
3982
+ }
3983
+ return platformAdapter.user.getCurrentUserSteamGameListEnvelope(request)
3984
+ .catch((error) => {
3985
+ throw createMiniProgramRuntimeBridgeError('REQUEST_FAILED', error instanceof Error ? error.message : 'Steam 游戏库请求失败', error);
3986
+ });
3987
+ }
3988
+ function mapSteamGameListData(envelope, request) {
3989
+ if (!isMiniProgramRuntimeRecord(envelope)) {
3990
+ throw createMiniProgramRuntimeBridgeError('INVALID_RESPONSE', 'Steam 游戏库响应必须是对象');
3991
+ }
3992
+ const data = envelope;
3993
+ if (data.status !== 'ok') {
3994
+ throw createMiniProgramRuntimeBridgeError('REQUEST_FAILED', readString$1(data.msg) || 'Steam 游戏库请求失败', data);
3995
+ }
3996
+ if (!isMiniProgramRuntimeRecord(data.result)) {
3997
+ throw createMiniProgramRuntimeBridgeError('INVALID_RESPONSE', 'Steam 游戏库 result 必须是对象');
3998
+ }
3999
+ const result = data.result;
4000
+ const gameList = readArray$1(result.game_list)
4001
+ .map(mapSteamGameListItem)
4002
+ .filter((item) => Boolean(item));
4003
+ const total = readOptionalNumber(result.total);
4004
+ const nextOffset = request.offset + gameList.length;
4005
+ const response = {
4006
+ gameList,
4007
+ hasMore: gameList.length >= request.limit,
4008
+ nextOffset,
4009
+ };
4010
+ if (total !== undefined) {
4011
+ response.total = total;
4012
+ response.hasMore = nextOffset < total;
4013
+ }
4014
+ const isMe = readOptionalBoolean(result.is_me);
4015
+ if (isMe !== undefined) {
4016
+ response.isMe = isMe;
4017
+ }
4018
+ return response;
4019
+ }
4020
+ function mapSteamGameListItem(value) {
4021
+ const source = readRecord$1(value);
4022
+ const appid = readOptionalNumber(source.appid);
4023
+ const steamAppid = readOptionalNumber(source.steam_appid) ?? appid;
4024
+ const name = readString$1(source.name);
4025
+ if (appid === undefined || steamAppid === undefined || !name) {
4026
+ return undefined;
4027
+ }
4028
+ const result = {
4029
+ appid,
4030
+ steamAppid,
4031
+ name,
4032
+ };
4033
+ copyStringField$1(result, 'image', source.image);
4034
+ copyStringField$1(result, 'icon', source.appicon ?? source.icon);
4035
+ copyStringField$1(result, 'background', source.background);
4036
+ copyStringField$1(result, 'verticalImage', source.vertical_head_image);
4037
+ copyNumberField(result, 'playtimeForever', source.playtime_forever);
4038
+ copyNumberField(result, 'playtime2Weeks', source.playtime_2weeks);
4039
+ copyNumberField(result, 'playtimePercent', source.playtime_percent);
4040
+ copyNumberField(result, 'achievedCount', source.achieved_count);
4041
+ copyNumberField(result, 'achievementCount', source.achivement_count ?? source.achievement_count);
4042
+ copyBooleanField(result, 'isCleared', source.is_cleared);
4043
+ copyStringField$1(result, 'score', source.score);
4044
+ copyBooleanField(result, 'isFree', source.is_free);
4045
+ copyBooleanField(result, 'notOwned', source.not_owned);
4046
+ copyBooleanField(result, 'hidden', source.hidden ?? source.is_hidden);
4047
+ copyStringField$1(result, 'onlinePlayer', source.online_player);
4048
+ copyStringArray(result, 'tags', source.external_tags ?? source.tags);
4049
+ copyStringArray(result, 'genres', source.genres);
4050
+ const price = mapSteamGamePrice(source.price);
4051
+ if (price) {
4052
+ result.price = price;
4053
+ }
4054
+ return result;
4055
+ }
4056
+ function mapSteamGamePrice(value) {
4057
+ const source = readRecord$1(value);
4058
+ const result = {};
4059
+ copyStringField$1(result, 'current', source.current);
4060
+ copyStringField$1(result, 'initial', source.initial);
4061
+ copyNumberField(result, 'discount', source.discount);
4062
+ copyNumberField(result, 'lowestPrice', source.lowest_price);
4063
+ copyStringField$1(result, 'deadlineDate', source.deadline_date);
4064
+ copyNumberField(result, 'deadlineTimestamp', source.deadline_timestamp);
4065
+ return Object.keys(result).length > 0 ? result : undefined;
4066
+ }
4067
+ function readOptionalSteamId(value) {
4068
+ const steamId = readString$1(value);
4069
+ return steamId ? { steamId } : {};
4070
+ }
4071
+ function readOptionalQuery(value) {
4072
+ const q = readString$1(value);
4073
+ return q ? { q: q.slice(0, MAX_QUERY_LENGTH) } : {};
4074
+ }
4075
+ function readLimit(value) {
4076
+ if (value === undefined) {
4077
+ return DEFAULT_LIMIT;
4078
+ }
4079
+ const limit = readInteger(value);
4080
+ if (limit === undefined || limit < 1) {
4081
+ throw createMiniProgramRuntimeBridgeError('INVALID_PARAMS', 'user.getSteamGameList limit 必须是正整数');
4082
+ }
4083
+ return Math.min(limit, MAX_LIMIT);
4084
+ }
4085
+ function readOffset(value) {
4086
+ if (value === undefined) {
4087
+ return DEFAULT_OFFSET;
4088
+ }
4089
+ const offset = readInteger(value);
4090
+ if (offset === undefined || offset < 0) {
4091
+ throw createMiniProgramRuntimeBridgeError('INVALID_PARAMS', 'user.getSteamGameList offset 必须是非负整数');
4092
+ }
4093
+ return offset;
4094
+ }
4095
+ function readSort(value) {
4096
+ if (value === undefined) {
4097
+ return DEFAULT_SORT;
4098
+ }
4099
+ if (typeof value !== 'string' || !SUPPORTED_SORTS.has(value)) {
4100
+ throw createMiniProgramRuntimeBridgeError('INVALID_PARAMS', 'user.getSteamGameList sort 不支持');
4101
+ }
4102
+ return value;
4103
+ }
4104
+ function readInteger(value) {
4105
+ if (typeof value === 'number' && Number.isInteger(value)) {
4106
+ return value;
4107
+ }
4108
+ return undefined;
4109
+ }
4110
+ function copyStringField$1(target, key, value) {
4111
+ const stringValue = readString$1(value);
4112
+ if (stringValue) {
4113
+ Object.assign(target, { [key]: stringValue });
4114
+ }
4115
+ }
4116
+ function copyNumberField(target, key, value) {
4117
+ const numberValue = readOptionalNumber(value);
4118
+ if (numberValue !== undefined) {
4119
+ Object.assign(target, { [key]: numberValue });
4120
+ }
4121
+ }
4122
+ function copyBooleanField(target, key, value) {
4123
+ const booleanValue = readOptionalBoolean(value);
4124
+ if (booleanValue !== undefined) {
4125
+ Object.assign(target, { [key]: booleanValue });
4126
+ }
4127
+ }
4128
+ function copyStringArray(target, key, value) {
4129
+ const items = readArray$1(value)
4130
+ .map(readString$1)
4131
+ .filter(Boolean);
4132
+ if (items.length > 0) {
4133
+ Object.assign(target, { [key]: items });
4134
+ }
4135
+ }
4136
+ function readRecord$1(value) {
4137
+ return isMiniProgramRuntimeRecord(value) ? value : {};
4138
+ }
4139
+ function readArray$1(value) {
4140
+ return Array.isArray(value) ? value : [];
4141
+ }
4142
+ function readString$1(value) {
4143
+ if (typeof value === 'string') {
4144
+ return value.trim() ? value.trim() : '';
4145
+ }
4146
+ if (typeof value === 'number' || typeof value === 'boolean') {
4147
+ return String(value);
4148
+ }
4149
+ return '';
4150
+ }
4151
+ function readOptionalNumber(value) {
4152
+ if (typeof value === 'number' && Number.isFinite(value)) {
4153
+ return value;
4154
+ }
4155
+ if (typeof value === 'string' && value.trim()) {
4156
+ const numberValue = Number(value);
4157
+ return Number.isFinite(numberValue) ? numberValue : undefined;
4158
+ }
4159
+ return undefined;
4160
+ }
4161
+ function readBoolean(value, fallback) {
4162
+ return readOptionalBoolean(value) ?? fallback;
4163
+ }
4164
+ function readOptionalBoolean(value) {
4165
+ if (value === undefined || value === null || value === '') {
4166
+ return undefined;
4167
+ }
4168
+ if (value === true || value === 1 || value === '1') {
4169
+ return true;
4170
+ }
4171
+ if (value === false || value === 0 || value === '0') {
4172
+ return false;
4173
+ }
4174
+ return undefined;
4175
+ }
4176
+
4177
+ const PLATFORM_SOURCE_KEY_BY_TYPE = {
4178
+ steam: 'steam_id_info',
4179
+ epic: 'epic_account_info',
4180
+ xbox: 'xbox_account_info',
4181
+ psn: 'psn_account_info',
4182
+ switch: 'switch_account_info',
4183
+ pc_hardware: 'hardware_info',
4184
+ mobile: 'mobile_account_info',
4185
+ };
4186
+ const PLATFORM_HIDDEN_KEY_BY_TYPE = {
4187
+ steam: ['steam_is_hidden', 'is_steam_hidden'],
4188
+ epic: ['epic_is_hidden', 'is_epic_hidden'],
4189
+ xbox: ['xbox_is_hidden', 'is_xbox_hidden'],
4190
+ psn: ['psn_is_hidden', 'is_psn_hidden'],
4191
+ switch: ['switch_is_hidden', 'is_switch_hidden'],
4192
+ pc_hardware: ['hardware_is_hidden', 'pc_hardware_is_hidden', 'is_hardware_hidden'],
4193
+ mobile: ['mobile_is_hidden', 'is_mobile_hidden'],
4194
+ };
4195
+ function mapCurrentUserDetail(home) {
4196
+ const accountDetail = readRecord(home.account_detail);
4197
+ const result = {
4198
+ heybox_id: readString(accountDetail.userid) || '',
4199
+ nickname: readString(accountDetail.username) || '',
4200
+ avatar: readString(accountDetail.avartar) || readString(accountDetail.avatar) || '',
4201
+ };
4202
+ copyStringFields(result, accountDetail, [
4203
+ 'sex',
4204
+ 'signature',
4205
+ 'ip_location',
4206
+ 'friends_count',
4207
+ ]);
4208
+ copyRecord(result, 'level_info', mapCurrentUserLevelInfo(accountDetail.level_info));
4209
+ copyArray(result, 'medals', mapCurrentUserMedals(accountDetail.bbs_medal ?? accountDetail.medal ?? accountDetail.medals));
4210
+ copyRecord(result, 'avatar_decoration', mapCurrentUserAvatarDecoration(accountDetail.avatar_decoration));
4211
+ copyRecord(result, 'avatar_config', mapCurrentUserAvatarConfig(accountDetail.avatar_config));
4212
+ copyRecord(result, 'bbs_info', mapCurrentUserBbsInfo(accountDetail.bbs_info));
4213
+ return result;
4214
+ }
4215
+ function mapCurrentUserProfile(home) {
4216
+ const profile = readRecord(home.profile);
4217
+ const result = {
4218
+ heybox_id: readString(profile.heybox_id) || readString(profile.userid) || '',
4219
+ };
4220
+ copyStringFields(result, profile, [
4221
+ 'nickname',
4222
+ 'avatar',
4223
+ 'gender',
4224
+ 'birthday',
4225
+ 'email',
4226
+ 'education',
4227
+ 'career',
4228
+ 'signature',
4229
+ ]);
4230
+ return result;
4231
+ }
4232
+ function mapPlatformAccountOverview(home) {
4233
+ return {
4234
+ platforms: SUPPORTED_PLATFORM_ACCOUNT_TYPES.map(platform => ({
4235
+ platform,
4236
+ is_bound: isPlatformBound(home, platform),
4237
+ is_hidden: readPlatformHidden(home, platform),
4238
+ })),
4239
+ display_order: readPlatformDisplayOrder(home.platform_list),
4240
+ };
4241
+ }
4242
+ function mapPlatformAccountResult(home, platform) {
4243
+ const isLogin = true;
4244
+ const isHidden = readPlatformHidden(home, platform);
4245
+ const accountInfo = mapPlatformAccountInfo(home, platform);
4246
+ const isBound = isPlatformInfoBound(accountInfo);
4247
+ return {
4248
+ isLogin,
4249
+ platform,
4250
+ is_bound: isBound,
4251
+ is_hidden: isHidden,
4252
+ account_info: isBound ? accountInfo : null,
4253
+ };
4254
+ }
4255
+ function createUnauthenticatedPlatformAccountResult(platform) {
4256
+ return {
4257
+ isLogin: false,
4258
+ platform,
4259
+ is_bound: false,
4260
+ is_hidden: false,
4261
+ account_info: null,
4262
+ };
4263
+ }
4264
+ function mapPlatformAccountInfo(home, platform) {
4265
+ const source = readRecord(home[PLATFORM_SOURCE_KEY_BY_TYPE[platform]]);
4266
+ switch (platform) {
4267
+ case 'steam':
4268
+ return mapSteamPlatformAccount(source);
4269
+ case 'epic':
4270
+ return mapEpicPlatformAccount(source);
4271
+ case 'xbox':
4272
+ return mapXboxPlatformAccount(source);
4273
+ case 'psn':
4274
+ return mapPsnPlatformAccount(source);
4275
+ case 'switch':
4276
+ return mapSwitchPlatformAccount(source);
4277
+ case 'pc_hardware':
4278
+ return mapPcHardwareAccount(source);
4279
+ case 'mobile':
4280
+ return mapMobilePlatformAccount(source);
4281
+ default:
4282
+ return {};
4283
+ }
4284
+ }
4285
+ function mapSteamPlatformAccount(source) {
4286
+ const result = mapBasePlatformAccountInfo(source);
4287
+ const steamid = readString(source.steamid);
4288
+ if (steamid) {
4289
+ result.steamid = steamid;
4290
+ }
4291
+ copyStringFields(result, source, [
4292
+ 'short_id',
4293
+ 'level',
4294
+ 'city',
4295
+ 'province',
4296
+ 'country',
4297
+ 'country_code',
4298
+ 'country_flag',
4299
+ 'avatar_frame',
4300
+ 'head_image',
4301
+ 'head_video',
4302
+ 'update_time',
4303
+ 'account_year',
4304
+ 'individuality_signature',
4305
+ 'level_icon',
4306
+ 'total_badge_count',
4307
+ 'total_dlcs_count',
4308
+ 'total_game_count',
4309
+ 'total_game_price',
4310
+ 'total_player_time',
4311
+ ]);
4312
+ copyOptionalBoolean(result, 'friend_code_show', source.friend_code_show);
4313
+ copyOptionalBoolean(result, 'inventory_open', source.inventory_open);
4314
+ copyOptionalBoolean(result, 'personal_information_open', source.personal_infomation_open ?? source.personal_information_open);
4315
+ copyOptionalBoolean(result, 'has_history', source.has_history);
4316
+ if (result.friend_code_show === true) {
4317
+ copyStringField(result, 'friend_code', source.friend_code);
4318
+ }
4319
+ return result;
4320
+ }
4321
+ function mapEpicPlatformAccount(source) {
4322
+ const result = mapBasePlatformAccountInfo(source);
4323
+ copyStringFields(result, source, ['xuid', 'head_color', 'desc']);
4324
+ return result;
4325
+ }
4326
+ function mapXboxPlatformAccount(source) {
4327
+ const result = mapBasePlatformAccountInfo(source);
4328
+ copyStringFields(result, source, ['xuid', 'desc']);
4329
+ return result;
4330
+ }
4331
+ function mapPsnPlatformAccount(source) {
4332
+ const result = mapBasePlatformAccountInfo(source);
4333
+ copyStringField(result, 'background_url', source.bg_img ?? source.background_url);
4334
+ copyStringFields(result, source, ['name', 'level', 'description']);
4335
+ copyOptionalBoolean(result, 'is_open', source.is_open);
4336
+ const pairStats = mapPsnPairStats(source);
4337
+ if (pairStats.length > 0) {
4338
+ result.stats = [...readArray(result.stats), ...pairStats];
4339
+ }
4340
+ return result;
4341
+ }
4342
+ function mapSwitchPlatformAccount(source) {
4343
+ const result = mapBasePlatformAccountInfo(source);
4344
+ copyStringFields(result, source, [
4345
+ 'heybox_id',
4346
+ 'friend_code',
4347
+ 'friends_total',
4348
+ 'games_total',
4349
+ 'server_name',
4350
+ 'type',
4351
+ 'desc',
4352
+ ]);
4353
+ return result;
4354
+ }
4355
+ function mapPcHardwareAccount(source) {
4356
+ const result = {};
4357
+ copyStringFields(result, source, ['cpu', 'gpu', 'board', 'perf_level']);
4358
+ return result;
4359
+ }
4360
+ function mapMobilePlatformAccount(source) {
4361
+ const currentDevice = mapMobileCurrentDevice(readRecord(source.current_device));
4362
+ return Object.keys(currentDevice).length > 0
4363
+ ? {
4364
+ current_device: currentDevice,
4365
+ }
4366
+ : {};
4367
+ }
4368
+ function mapBasePlatformAccountInfo(source) {
4369
+ const result = {};
4370
+ copyStringFields(result, source, ['nickname', 'avatar']);
4371
+ copyStringField(result, 'background_url', source.background_url ?? source.bg_img);
4372
+ const stats = mapPlatformStats(source.stats ?? source.stat ?? source.cards ?? source.card_list);
4373
+ if (stats.length > 0) {
4374
+ result.stats = stats;
4375
+ }
4376
+ return result;
4377
+ }
4378
+ function mapMobileCurrentDevice(source) {
4379
+ const result = {};
4380
+ copyStringFields(result, source, ['id', 'name', 'desc', 'model', 'img_url', 'update_time']);
4381
+ const stats = mapPlatformStats(source.stats ?? source.stat ?? source.cards ?? source.card_list);
4382
+ if (stats.length > 0) {
4383
+ result.stats = stats;
4384
+ }
4385
+ return result;
4386
+ }
4387
+ function mapCurrentUserLevelInfo(value) {
4388
+ const source = readRecord(value);
4389
+ const result = {};
4390
+ copyStringFields(result, source, ['level', 'level_name', 'exp', 'next_exp', 'icon']);
4391
+ return result;
4392
+ }
4393
+ function mapCurrentUserMedals(value) {
4394
+ return readArray(value)
4395
+ .map(item => {
4396
+ const source = readRecord(item);
4397
+ const result = {};
4398
+ copyStringFields(result, source, ['id', 'name', 'desc', 'icon', 'image']);
4399
+ copyOptionalBoolean(result, 'is_wearing', source.is_wearing);
4400
+ return result;
4401
+ })
4402
+ .filter(item => Object.keys(item).length > 0);
4403
+ }
4404
+ function mapCurrentUserAvatarDecoration(value) {
4405
+ const source = readRecord(value);
4406
+ const result = {};
4407
+ copyStringFields(result, source, ['id', 'name', 'image', 'frame_url']);
4408
+ copyOptionalBoolean(result, 'is_using', source.is_using);
4409
+ return result;
4410
+ }
4411
+ function mapCurrentUserAvatarConfig(value) {
4412
+ const source = readRecord(value);
4413
+ const result = {};
4414
+ copyStringFields(result, source, ['avatar', 'frame_url', 'pendant_url']);
4415
+ return result;
4416
+ }
4417
+ function mapCurrentUserBbsInfo(value) {
4418
+ const source = readRecord(value);
4419
+ const result = {};
4420
+ copyStringFields(result, source, ['uid', 'nickname', 'avatar', 'level']);
4421
+ return result;
4422
+ }
4423
+ function mapPlatformStats(value) {
4424
+ return readArray(value)
4425
+ .map(item => {
4426
+ const source = readRecord(item);
4427
+ const result = {};
4428
+ copyStringField(result, 'key', source.key ?? source.k);
4429
+ copyStringField(result, 'name', source.name);
4430
+ copyStringField(result, 'desc', source.desc ?? source.description);
4431
+ copyStringField(result, 'value', source.value ?? source.timestamp);
4432
+ copyStringField(result, 'num', source.num);
4433
+ copyStringField(result, 'icon', source.icon);
4434
+ copyStringField(result, 'img', source.img ?? source.img_url ?? source.right_img);
4435
+ copyStringField(result, 'color', source.color);
4436
+ return result;
4437
+ })
4438
+ .filter(item => Object.keys(item).length > 0);
4439
+ }
4440
+ function mapPsnPairStats(source) {
4441
+ const stats = [];
4442
+ for (let index = 1; index <= 4; index += 1) {
4443
+ const name = readString(source[`key${index}`]);
4444
+ const value = readString(source[`value${index}`]);
4445
+ if (name || value) {
4446
+ stats.push({
4447
+ ...(name ? { name } : {}),
4448
+ ...(value ? { value } : {}),
4449
+ });
4450
+ }
4451
+ }
4452
+ return stats;
4453
+ }
4454
+ function isPlatformBound(home, platform) {
4455
+ return isPlatformInfoBound(mapPlatformAccountInfo(home, platform));
4456
+ }
4457
+ function isPlatformInfoBound(accountInfo) {
4458
+ return Object.keys(accountInfo).length > 0;
4459
+ }
4460
+ function readPlatformHidden(home, platform) {
4461
+ for (const key of PLATFORM_HIDDEN_KEY_BY_TYPE[platform]) {
4462
+ const value = readOptionalRuntimeBoolean(home[key]);
4463
+ if (value !== undefined) {
4464
+ return value;
4465
+ }
4466
+ }
4467
+ const hidden = readRecord(home.hidden);
4468
+ const hiddenAccounts = readRecord(home.hidden_accounts);
4469
+ return readOptionalRuntimeBoolean(hidden[platform]) ?? readOptionalRuntimeBoolean(hiddenAccounts[platform]) ?? false;
4470
+ }
4471
+ function readPlatformDisplayOrder(value) {
4472
+ return readArray(value)
4473
+ .map(item => {
4474
+ if (isPlatformAccountType(item)) {
4475
+ return item;
4476
+ }
4477
+ if (!isMiniProgramRuntimeRecord(item)) {
4478
+ return undefined;
4479
+ }
4480
+ return readPlatformFromRecord(item);
4481
+ })
4482
+ .filter((platform) => Boolean(platform));
4483
+ }
4484
+ function readPlatformFromRecord(value) {
4485
+ const platform = value.platform ?? value.type ?? value.key ?? value.name;
4486
+ return isPlatformAccountType(platform) ? platform : undefined;
4487
+ }
4488
+ function readRecord(value) {
4489
+ return isMiniProgramRuntimeRecord(value) ? value : {};
4490
+ }
4491
+ function readArray(value) {
4492
+ return Array.isArray(value) ? value : [];
4493
+ }
4494
+ function copyRecord(target, key, value) {
4495
+ if (Object.keys(value).length > 0) {
4496
+ target[key] = value;
4497
+ }
4498
+ }
4499
+ function copyArray(target, key, value) {
4500
+ if (value.length > 0) {
4501
+ target[key] = value;
4502
+ }
4503
+ }
4504
+ function copyStringFields(target, source, keys) {
4505
+ for (const key of keys) {
4506
+ copyStringField(target, key, source[key]);
4507
+ }
4508
+ }
4509
+ function copyStringField(target, key, value) {
4510
+ const stringValue = readString(value);
4511
+ if (stringValue) {
4512
+ target[key] = stringValue;
4513
+ }
4514
+ }
4515
+ function copyOptionalBoolean(target, key, value) {
4516
+ const booleanValue = readOptionalRuntimeBoolean(value);
4517
+ if (booleanValue !== undefined) {
4518
+ target[key] = booleanValue;
4519
+ }
4520
+ }
4521
+ function readString(value) {
4522
+ if (typeof value === 'string') {
4523
+ return value.trim() ? value : '';
4524
+ }
4525
+ if (typeof value === 'number' || typeof value === 'boolean') {
4526
+ return String(value);
4527
+ }
4528
+ return '';
4529
+ }
4530
+ function readOptionalRuntimeBoolean(value) {
4531
+ if (value === undefined || value === null || value === '') {
4532
+ return undefined;
4533
+ }
4534
+ if (value === true || value === 1 || value === '1') {
4535
+ return true;
4536
+ }
4537
+ if (value === false || value === 0 || value === '0') {
4538
+ return false;
4539
+ }
4540
+ return undefined;
4541
+ }
4542
+
3810
4543
  /** 设置导航栏关闭按钮与状态栏图标/文字的前景样式。 */
3811
4544
  function setMiniProgramRuntimeNavigationBarStyle(payload, platformAdapter) {
3812
4545
  return platformAdapter.viewport.setNavigationBarStyle(readMiniProgramNavigationBarStyleOptions(payload));
@@ -3829,6 +4562,11 @@ const MINI_PROGRAM_MOCK_RUNTIME_METHODS = MINI_PROGRAM_PROTOCOL_CAPABILITIES.map
3829
4562
  const MINI_PROGRAM_MOCK_RUNTIME_METHOD_HANDLERS = {
3830
4563
  [AUTH_LOGIN_METHOD]: (runtime) => runtime.login(),
3831
4564
  [USER_GET_INFO_METHOD]: (runtime) => runtime.getUserInfo(),
4565
+ [USER_GET_CURRENT_USER_DETAIL_METHOD]: (runtime) => runtime.getCurrentUserDetail(),
4566
+ [USER_GET_CURRENT_USER_PROFILE_METHOD]: (runtime) => runtime.getCurrentUserProfile(),
4567
+ [USER_GET_PLATFORM_ACCOUNT_OVERVIEW_METHOD]: (runtime) => runtime.getPlatformAccountOverview(),
4568
+ [USER_GET_PLATFORM_ACCOUNT_INFO_METHOD]: (runtime, payload) => runtime.getPlatformAccountInfo(payload),
4569
+ [USER_GET_STEAM_GAME_LIST_METHOD]: (runtime, payload) => runtime.getSteamGameList(payload),
3832
4570
  [SHARE_SHOW_SHARE_MENU_METHOD]: (runtime, payload) => runtime.showShareMenu(payload),
3833
4571
  [SHARE_SCREENSHOT_METHOD]: (runtime, payload) => runtime.shareScreenshot(payload),
3834
4572
  [VIEWPORT_GET_WINDOW_INFO_METHOD]: (runtime) => runtime.getWindowInfo(),
@@ -3875,6 +4613,9 @@ function createBrowserMockRuntimePlatformAdapter(options) {
3875
4613
  avatar: currentUser.avatar,
3876
4614
  };
3877
4615
  },
4616
+ async getCurrentUserSteamGameListEnvelope(request) {
4617
+ return createMockSteamGameListEnvelope(request.limit, request.offset);
4618
+ },
3878
4619
  },
3879
4620
  share: {
3880
4621
  async showShareMenu(params) {
@@ -3998,8 +4739,67 @@ class MiniProgramMockRuntime {
3998
4739
  async getUserInfo() {
3999
4740
  return getMiniProgramRuntimeUserInfo(this.adapter);
4000
4741
  }
4742
+ async getCurrentUserDetail() {
4743
+ const home = await this.getMockUserHomeV2Result();
4744
+ return home
4745
+ ? {
4746
+ isLogin: true,
4747
+ data: mapCurrentUserDetail(home),
4748
+ }
4749
+ : {
4750
+ isLogin: false,
4751
+ data: null,
4752
+ };
4753
+ }
4754
+ async getCurrentUserProfile() {
4755
+ const home = await this.getMockUserHomeV2Result();
4756
+ return home
4757
+ ? {
4758
+ isLogin: true,
4759
+ data: mapCurrentUserProfile(home),
4760
+ }
4761
+ : {
4762
+ isLogin: false,
4763
+ data: null,
4764
+ };
4765
+ }
4766
+ async getPlatformAccountOverview() {
4767
+ const home = await this.getMockUserHomeV2Result();
4768
+ return home
4769
+ ? {
4770
+ isLogin: true,
4771
+ data: mapPlatformAccountOverview(home),
4772
+ }
4773
+ : {
4774
+ isLogin: false,
4775
+ data: null,
4776
+ };
4777
+ }
4778
+ async getPlatformAccountInfo(payload) {
4779
+ const platform = readPlatformAccountType(payload);
4780
+ const home = await this.getMockUserHomeV2Result();
4781
+ return home
4782
+ ? mapPlatformAccountResult(home, platform)
4783
+ : createUnauthenticatedPlatformAccountResult(platform);
4784
+ }
4785
+ async getSteamGameList(payload) {
4786
+ const home = await this.getMockUserHomeV2Result();
4787
+ return getMiniProgramRuntimeSteamGameList(payload, {
4788
+ ...this.adapter,
4789
+ user: {
4790
+ ...this.adapter.user,
4791
+ getCurrentUserSteamGameListEnvelope: request => Promise.resolve(createMockSteamGameListEnvelope(request.limit, request.offset)),
4792
+ },
4793
+ }, home);
4794
+ }
4795
+ async getMockUserHomeV2Result() {
4796
+ const result = await this.getUserInfo();
4797
+ return result.isLogin && result.userInfo
4798
+ ? createMockRuntimeUserHomeV2Result(result.userInfo)
4799
+ : undefined;
4800
+ }
4001
4801
  showShareMenu(payload) {
4002
- return showMiniProgramRuntimeShareMenu(payload, this.adapter);
4802
+ return showMiniProgramRuntimeShareMenu(payload, this.adapter, readMockRuntimeShareContext(this.adapter.app.getCurrentHref()));
4003
4803
  }
4004
4804
  shareScreenshot(payload) {
4005
4805
  return shareMiniProgramRuntimeScreenshot(payload, this.adapter);
@@ -4094,6 +4894,70 @@ class MiniProgramMockRuntime {
4094
4894
  this.records.splice(30);
4095
4895
  }
4096
4896
  }
4897
+ function readMockRuntimeShareContext(href) {
4898
+ try {
4899
+ const currentUrl = new URL(href);
4900
+ return {
4901
+ miniProgramId: currentUrl.searchParams.get('mini_program_id') || undefined,
4902
+ miniProgramVersion: currentUrl.searchParams.get('miniprogram_version') || undefined,
4903
+ };
4904
+ }
4905
+ catch {
4906
+ return {};
4907
+ }
4908
+ }
4909
+ function createMockSteamGameListEnvelope(limit, offset) {
4910
+ const gameList = [
4911
+ {
4912
+ appid: 814380,
4913
+ steam_appid: 814380,
4914
+ name: 'Sekiro: Shadows Die Twice',
4915
+ image: 'https://imgheybox.max-c.com/heybox/game/header/814380_lliLB.jpg',
4916
+ appicon: 'https://imgheybox.max-c.com/web/2024/02/14/f072e95b0026fa2efba35f737dbc2aab.webp',
4917
+ background: 'https://cdn.max-c.com/heybox/game/background/814380_cHOHF.jpg',
4918
+ playtime_forever: 2940,
4919
+ playtime_2weeks: 120,
4920
+ playtime_percent: '0.12',
4921
+ achieved_count: 3,
4922
+ achivement_count: 34,
4923
+ score: '9.8',
4924
+ is_free: false,
4925
+ not_owned: false,
4926
+ online_player: '4314',
4927
+ external_tags: ['Action', 'Adventure'],
4928
+ genres: ['Action'],
4929
+ price: {
4930
+ initial: '268',
4931
+ current: '134',
4932
+ discount: 50,
4933
+ lowest_price: 134,
4934
+ },
4935
+ },
4936
+ {
4937
+ appid: 230410,
4938
+ steam_appid: 230410,
4939
+ name: 'Warframe',
4940
+ image: 'https://imgheybox.max-c.com/heybox/game/header/230410_tamuE.jpg',
4941
+ playtime_forever: 1024140,
4942
+ playtime_2weeks: 1500,
4943
+ achieved_count: 142,
4944
+ achivement_count: 193,
4945
+ is_free: true,
4946
+ not_owned: false,
4947
+ online_player: '5万',
4948
+ external_tags: ['MMO', 'Sci-Fi'],
4949
+ genres: ['Action', 'Free To Play'],
4950
+ },
4951
+ ].slice(offset, offset + limit);
4952
+ return {
4953
+ status: 'ok',
4954
+ result: {
4955
+ game_list: gameList,
4956
+ total: 2,
4957
+ is_me: true,
4958
+ },
4959
+ };
4960
+ }
4097
4961
  function isMiniProgramMockRuntimeMethod(method) {
4098
4962
  return MINI_PROGRAM_MOCK_RUNTIME_METHODS.includes(method);
4099
4963
  }
@@ -4232,6 +5096,122 @@ function createVibratePattern(intensity) {
4232
5096
  return 10;
4233
5097
  }
4234
5098
  }
5099
+ function createMockRuntimeUserHomeV2Result(userInfo) {
5100
+ const heyboxId = userInfo.heybox_id || 'debug_user';
5101
+ const nickname = userInfo.nickname || 'PC Debug User';
5102
+ const avatar = userInfo.avatar || '';
5103
+ return {
5104
+ account_detail: {
5105
+ userid: heyboxId,
5106
+ username: nickname,
5107
+ avartar: avatar,
5108
+ signature: '来自 hb-sdk mock runtime 的用户资料',
5109
+ ip_location: 'Mock',
5110
+ friends_count: '128',
5111
+ level_info: {
5112
+ level: '12',
5113
+ level_name: 'Mock Lv.12',
5114
+ exp: '2400',
5115
+ next_exp: '3000',
5116
+ },
5117
+ bbs_medal: [
5118
+ {
5119
+ id: 'mock-medal',
5120
+ name: 'Mock Medal',
5121
+ desc: '本地 mock 勋章',
5122
+ is_wearing: true,
5123
+ },
5124
+ ],
5125
+ },
5126
+ profile: {
5127
+ heybox_id: heyboxId,
5128
+ nickname,
5129
+ avatar,
5130
+ gender: 'unknown',
5131
+ signature: '来自 hb-sdk mock runtime 的个人档案',
5132
+ email: 'mock-user@example.com',
5133
+ },
5134
+ platform_list: ['steam', 'epic', 'xbox', 'psn', 'switch', 'pc_hardware', 'mobile'],
5135
+ steam_is_hidden: false,
5136
+ steam_id_info: {
5137
+ steamid: '76561198000000000',
5138
+ short_id: 'mock-steam',
5139
+ nickname: `${nickname} Steam`,
5140
+ avatar,
5141
+ level: '12',
5142
+ friend_code_show: true,
5143
+ friend_code: '123456789',
5144
+ inventory_open: true,
5145
+ personal_information_open: true,
5146
+ has_history: true,
5147
+ stats: [
5148
+ {
5149
+ key: 'total_game_count',
5150
+ name: '游戏数',
5151
+ value: '42',
5152
+ },
5153
+ {
5154
+ key: 'total_player_time',
5155
+ name: '总时长',
5156
+ value: '128h',
5157
+ },
5158
+ ],
5159
+ },
5160
+ epic_account_info: {
5161
+ nickname: `${nickname} Epic`,
5162
+ avatar,
5163
+ xuid: 'mock-epic-xuid',
5164
+ desc: 'Mock Epic account',
5165
+ },
5166
+ xbox_account_info: {
5167
+ nickname: `${nickname} Xbox`,
5168
+ avatar,
5169
+ xuid: 'mock-xbox-xuid',
5170
+ desc: 'Mock Xbox account',
5171
+ },
5172
+ psn_account_info: {
5173
+ name: `${nickname} PSN`,
5174
+ avatar,
5175
+ level: '8',
5176
+ description: 'Mock PSN account',
5177
+ is_open: true,
5178
+ key1: '白金',
5179
+ value1: '3',
5180
+ },
5181
+ switch_account_info: {
5182
+ heybox_id: heyboxId,
5183
+ nickname: `${nickname} Switch`,
5184
+ avatar,
5185
+ friend_code: 'SW-1234-5678-9012',
5186
+ friends_total: '16',
5187
+ games_total: '9',
5188
+ server_name: 'Mock Server',
5189
+ type: 'switch',
5190
+ },
5191
+ hardware_info: {
5192
+ cpu: 'Mock CPU',
5193
+ gpu: 'Mock GPU',
5194
+ board: 'Mock Board',
5195
+ perf_level: 'A',
5196
+ },
5197
+ mobile_account_info: {
5198
+ current_device: {
5199
+ id: 'mock-device',
5200
+ name: 'Mock Phone',
5201
+ desc: 'hb-sdk mock runtime device',
5202
+ model: 'MockPhone 1',
5203
+ update_time: '2026-06-04',
5204
+ stats: [
5205
+ {
5206
+ key: 'score',
5207
+ name: '跑分',
5208
+ value: '999999',
5209
+ },
5210
+ ],
5211
+ },
5212
+ },
5213
+ };
5214
+ }
4235
5215
  function renderMockToast(toast) {
4236
5216
  const document = readDocument();
4237
5217
  if (!document) {