- WxSDK 新增隐私授权检查和用户信息获取方法 - StorageManager 新增用户信息本地缓存方法 - PageHome 进入时检查隐私授权状态 - PageWriteLevels 分享时获取用户头像昵称并上传服务端 - ApiConfig 新增用户信息 API 端点 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
372 lines
11 KiB
TypeScript
372 lines
11 KiB
TypeScript
import { sys } from 'cc';
|
||
|
||
/**
|
||
* 微信分享配置
|
||
*/
|
||
export interface WxShareConfig {
|
||
/** 分享标题 */
|
||
title: string;
|
||
/** 分享图片 URL 或本地路径 */
|
||
imageUrl?: string;
|
||
/** 查询字符串,从这条转发消息进入后,可通过 wx.getLaunchOptionsSync 或 wx.onShow 获取 */
|
||
query?: string;
|
||
}
|
||
|
||
/**
|
||
* 微信朋友圈分享配置
|
||
*/
|
||
export interface WxShareTimelineConfig {
|
||
/** 分享标题 */
|
||
title: string;
|
||
/** 分享图片 URL 或本地路径 */
|
||
imageUrl?: string;
|
||
/** 查询字符串 */
|
||
query?: string;
|
||
}
|
||
|
||
/**
|
||
* 微信小游戏 SDK 工具类
|
||
* 封装微信平台相关 API,非微信环境下静默降级
|
||
*/
|
||
export class WxSDK {
|
||
/**
|
||
* 是否处于微信小游戏环境
|
||
*/
|
||
static isWechat(): boolean {
|
||
return sys.platform === sys.Platform.WECHAT_GAME;
|
||
}
|
||
|
||
/**
|
||
* 获取 wx 全局对象(仅微信环境下可用)
|
||
*/
|
||
private static getWx(): any {
|
||
if (!WxSDK.isWechat()) return null;
|
||
return typeof wx !== 'undefined' ? wx : null;
|
||
}
|
||
|
||
// ==================== 登录相关 ====================
|
||
|
||
/**
|
||
* 微信登录,获取临时 code
|
||
* @returns Promise<string> 登录 code
|
||
*/
|
||
static login(): Promise<string> {
|
||
return new Promise((resolve, reject) => {
|
||
const wxApi = WxSDK.getWx();
|
||
if (!wxApi) {
|
||
reject(new Error('非微信环境,无法调用 wx.login'));
|
||
return;
|
||
}
|
||
|
||
wxApi.login({
|
||
success: (res: any) => {
|
||
if (res.code) {
|
||
console.log('[WxSDK] wx.login 成功,获取到 code');
|
||
resolve(res.code);
|
||
} else {
|
||
console.error('[WxSDK] wx.login 失败:', res.errMsg);
|
||
reject(new Error(res.errMsg || 'wx.login 失败'));
|
||
}
|
||
},
|
||
fail: (err: any) => {
|
||
console.error('[WxSDK] wx.login 调用失败:', err);
|
||
reject(new Error(err.errMsg || 'wx.login 调用失败'));
|
||
}
|
||
});
|
||
});
|
||
}
|
||
|
||
// ==================== 分享相关 ====================
|
||
|
||
/**
|
||
* 开启转发/分享菜单
|
||
* 调用后用户可通过右上角菜单进行转发
|
||
* @param withShareTicket 是否带 shareTicket,用于获取群信息
|
||
*/
|
||
static showShareMenu(withShareTicket: boolean = true): void {
|
||
const wxApi = WxSDK.getWx();
|
||
if (!wxApi) return;
|
||
|
||
wxApi.showShareMenu({
|
||
withShareTicket,
|
||
menus: ['shareAppMessage', 'shareTimeline'],
|
||
success: () => {
|
||
console.log('[WxSDK] showShareMenu 成功');
|
||
},
|
||
fail: (err: any) => {
|
||
console.warn('[WxSDK] showShareMenu 失败', err);
|
||
}
|
||
});
|
||
}
|
||
|
||
/**
|
||
* 设置被动分享(右上角菜单 "转发给朋友")的内容
|
||
* 需要在页面加载后尽早调用,只需调用一次
|
||
* @param config 分享配置
|
||
*/
|
||
static onShareAppMessage(config: WxShareConfig): void {
|
||
const wxApi = WxSDK.getWx();
|
||
if (!wxApi) return;
|
||
|
||
wxApi.onShareAppMessage(() => ({
|
||
title: config.title,
|
||
imageUrl: config.imageUrl ?? '',
|
||
query: config.query ?? ''
|
||
}));
|
||
|
||
console.log('[WxSDK] onShareAppMessage 已设置');
|
||
}
|
||
|
||
/**
|
||
* 设置分享到朋友圈的内容
|
||
* @param config 朋友圈分享配置
|
||
*/
|
||
static onShareTimeline(config: WxShareTimelineConfig): void {
|
||
const wxApi = WxSDK.getWx();
|
||
if (!wxApi) return;
|
||
|
||
if (typeof wxApi.onShareTimeline !== 'function') {
|
||
console.warn('[WxSDK] 当前微信版本不支持 onShareTimeline');
|
||
return;
|
||
}
|
||
|
||
wxApi.onShareTimeline(() => ({
|
||
title: config.title,
|
||
imageUrl: config.imageUrl ?? '',
|
||
query: config.query ?? ''
|
||
}));
|
||
|
||
console.log('[WxSDK] onShareTimeline 已设置');
|
||
}
|
||
|
||
/**
|
||
* 主动触发转发(拉起分享面板)
|
||
* @param config 分享配置
|
||
*/
|
||
static shareAppMessage(config: WxShareConfig): void {
|
||
const wxApi = WxSDK.getWx();
|
||
if (!wxApi) return;
|
||
|
||
wxApi.shareAppMessage({
|
||
title: config.title,
|
||
imageUrl: config.imageUrl ?? '',
|
||
query: config.query ?? ''
|
||
});
|
||
|
||
console.log('[WxSDK] shareAppMessage 已触发');
|
||
}
|
||
|
||
/**
|
||
* 一键初始化分享功能
|
||
* 开启分享菜单 + 设置被动分享内容 + 设置朋友圈分享内容
|
||
* @param config 分享配置
|
||
*/
|
||
static initShare(config: WxShareConfig): void {
|
||
if (!WxSDK.isWechat()) {
|
||
console.log('[WxSDK] 非微信环境,跳过分享初始化');
|
||
return;
|
||
}
|
||
|
||
WxSDK.showShareMenu();
|
||
WxSDK.onShareAppMessage(config);
|
||
WxSDK.onShareTimeline({
|
||
title: config.title,
|
||
imageUrl: config.imageUrl,
|
||
query: config.query
|
||
});
|
||
|
||
console.log('[WxSDK] 分享功能初始化完成');
|
||
}
|
||
|
||
// ==================== 震动相关 ====================
|
||
|
||
/**
|
||
* 触发短震动(15ms)
|
||
* 用于轻量级反馈,如按钮点击
|
||
*/
|
||
static vibrateShort(): void {
|
||
const wxApi = WxSDK.getWx();
|
||
if (!wxApi) return;
|
||
|
||
wxApi.vibrateShort({
|
||
type: 'medium',
|
||
success: () => {
|
||
console.log('[WxSDK] 短震动成功');
|
||
},
|
||
fail: (err: any) => {
|
||
console.warn('[WxSDK] 短震动失败', err);
|
||
}
|
||
});
|
||
}
|
||
|
||
/**
|
||
* 触发长震动(400ms)
|
||
* 用于重要反馈,如错误提示
|
||
*/
|
||
static vibrateLong(): void {
|
||
const wxApi = WxSDK.getWx();
|
||
if (!wxApi) return;
|
||
|
||
wxApi.vibrateLong({
|
||
success: () => {
|
||
console.log('[WxSDK] 长震动成功');
|
||
},
|
||
fail: (err: any) => {
|
||
console.warn('[WxSDK] 长震动失败', err);
|
||
}
|
||
});
|
||
}
|
||
|
||
/**
|
||
* 从启动参数中获取分享码
|
||
* @returns 分享码,不存在则返回 null
|
||
*/
|
||
static getShareCodeFromLaunch(): string | null {
|
||
const wxApi = WxSDK.getWx();
|
||
if (!wxApi) return null;
|
||
|
||
try {
|
||
const options = wxApi.getLaunchOptionsSync();
|
||
if (options?.query?.shareCode) {
|
||
console.log('[WxSDK] 检测到分享码:', options.query.shareCode);
|
||
return options.query.shareCode;
|
||
}
|
||
} catch (err) {
|
||
console.warn('[WxSDK] 获取启动参数失败:', err);
|
||
}
|
||
return null;
|
||
}
|
||
}
|
||
|
||
// ==================== 隐私授权相关 ====================
|
||
|
||
/**
|
||
* 检查用户是否已授权隐私
|
||
* @returns Promise<{ needAuthorization: boolean }> needAuthorization 为 false 表示已授权
|
||
*/
|
||
export async function checkPrivacySetting(): Promise<{ needAuthorization: boolean }> {
|
||
return new Promise((resolve) => {
|
||
const wxApi = WxSDK.getWx();
|
||
if (!wxApi) {
|
||
// 非微信环境,认为已授权
|
||
resolve({ needAuthorization: false });
|
||
return;
|
||
}
|
||
|
||
if (typeof wxApi.getPrivacySetting !== 'function') {
|
||
// 低版本微信,认为已授权
|
||
console.warn('[WxSDK] 当前微信版本不支持 getPrivacySetting');
|
||
resolve({ needAuthorization: false });
|
||
return;
|
||
}
|
||
|
||
wxApi.getPrivacySetting({
|
||
success: (res: any) => {
|
||
console.log('[WxSDK] 隐私授权检查结果:', res);
|
||
resolve({ needAuthorization: res.needAuthorization });
|
||
},
|
||
fail: (err: any) => {
|
||
console.warn('[WxSDK] 隐私授权检查失败:', err);
|
||
// 检查失败时认为需要授权
|
||
resolve({ needAuthorization: true });
|
||
}
|
||
});
|
||
});
|
||
}
|
||
|
||
/**
|
||
* 引导用户进行隐私授权
|
||
* 调用后会弹出微信隐私授权弹窗
|
||
* @returns Promise<void>
|
||
*/
|
||
export async function requirePrivacyAuthorize(): Promise<void> {
|
||
return new Promise((resolve, reject) => {
|
||
const wxApi = WxSDK.getWx();
|
||
if (!wxApi) {
|
||
console.warn('[WxSDK] 非微信环境,跳过隐私授权');
|
||
resolve();
|
||
return;
|
||
}
|
||
|
||
if (typeof wxApi.requirePrivacyAuthorize !== 'function') {
|
||
console.warn('[WxSDK] 当前微信版本不支持 requirePrivacyAuthorize');
|
||
resolve();
|
||
return;
|
||
}
|
||
|
||
wxApi.requirePrivacyAuthorize({
|
||
success: () => {
|
||
console.log('[WxSDK] 用户已授权隐私');
|
||
resolve();
|
||
},
|
||
fail: (err: any) => {
|
||
console.warn('[WxSDK] 用户拒绝或授权失败:', err);
|
||
reject(new Error(err.errMsg || '隐私授权失败'));
|
||
}
|
||
});
|
||
});
|
||
}
|
||
|
||
// ==================== 用户信息相关 ====================
|
||
|
||
/**
|
||
* 用户信息(头像、昵称)
|
||
*/
|
||
export interface WxUserInfo {
|
||
avatarUrl: string;
|
||
nickName: string;
|
||
country?: string;
|
||
province?: string;
|
||
city?: string;
|
||
gender?: number;
|
||
}
|
||
|
||
/**
|
||
* 获取用户头像和昵称(需要用户主动授权)
|
||
* @returns Promise<WxUserInfo>
|
||
*/
|
||
export async function getUserProfile(): Promise<WxUserInfo> {
|
||
return new Promise((resolve, reject) => {
|
||
const wxApi = WxSDK.getWx();
|
||
if (!wxApi) {
|
||
// 非微信环境,返回 mock 数据
|
||
console.warn('[WxSDK] 非微信环境,返回 mock 用户信息');
|
||
resolve({
|
||
avatarUrl: '',
|
||
nickName: '微信用户'
|
||
});
|
||
return;
|
||
}
|
||
|
||
if (typeof wxApi.getUserProfile !== 'function') {
|
||
console.warn('[WxSDK] 当前微信版本不支持 getUserProfile');
|
||
reject(new Error('当前微信版本不支持 getUserProfile'));
|
||
return;
|
||
}
|
||
|
||
wxApi.getUserProfile({
|
||
desc: '用于完善用户资料',
|
||
success: (res: any) => {
|
||
if (res.userInfo) {
|
||
console.log('[WxSDK] 获取用户信息成功');
|
||
resolve({
|
||
avatarUrl: res.userInfo.avatarUrl,
|
||
nickName: res.userInfo.nickName,
|
||
country: res.userInfo.country,
|
||
province: res.userInfo.province,
|
||
city: res.userInfo.city,
|
||
gender: res.userInfo.gender
|
||
});
|
||
} else {
|
||
console.error('[WxSDK] 获取用户信息失败: 无 userInfo');
|
||
reject(new Error('获取用户信息失败'));
|
||
}
|
||
},
|
||
fail: (err: any) => {
|
||
console.error('[WxSDK] 获取用户信息失败:', err);
|
||
reject(new Error(err.errMsg || '获取用户信息失败'));
|
||
}
|
||
});
|
||
});
|
||
}
|