172 行
4.6 KiB
JavaScript
172 行
4.6 KiB
JavaScript
// 已读取AGENTS.md
|
|
import { onShareAppMessage, onShareTimeline, onShow } from '@dcloudio/uni-app';
|
|
import { onMounted } from 'vue';
|
|
|
|
const DEFAULT_SHARE_TITLE = '同城陪伴 · 专业游戏陪玩与生活陪伴';
|
|
const DEFAULT_INDEX_PATH = '/pages/index/index';
|
|
|
|
/**
|
|
* 获取当前登录用户的邀请码/用户ID,用于分销裂变与邀请自动绑定
|
|
*/
|
|
export function getShareInviterParams() {
|
|
try {
|
|
const uid = uni.getStorageSync('userId');
|
|
if (uid) {
|
|
return {
|
|
inviterId: String(uid),
|
|
code: `PW${uid}`
|
|
};
|
|
}
|
|
} catch (_) {}
|
|
return {
|
|
inviterId: '',
|
|
code: ''
|
|
};
|
|
}
|
|
|
|
/**
|
|
* 构造携带邀请人参数与页面参数的分享路径 (用于 onShareAppMessage)
|
|
*/
|
|
export function buildSharePath(basePath = DEFAULT_INDEX_PATH, extraParams = {}) {
|
|
const { inviterId, code } = getShareInviterParams();
|
|
const params = { ...extraParams };
|
|
if (inviterId && !params.inviterId) {
|
|
params.inviterId = inviterId;
|
|
}
|
|
if (code && !params.code) {
|
|
params.code = code;
|
|
}
|
|
|
|
const queryParts = [];
|
|
for (const key of Object.keys(params)) {
|
|
const val = params[key];
|
|
if (val !== undefined && val !== null && val !== '') {
|
|
queryParts.push(`${encodeURIComponent(key)}=${encodeURIComponent(val)}`);
|
|
}
|
|
}
|
|
|
|
const cleanBase = (basePath || DEFAULT_INDEX_PATH).split('?')[0];
|
|
const queryStr = queryParts.join('&');
|
|
return queryStr ? `${cleanBase}?${queryStr}` : cleanBase;
|
|
}
|
|
|
|
/**
|
|
* 构造朋友圈分享的 query 参数字符串 (用于 onShareTimeline,微信规范 query 不带 ?)
|
|
*/
|
|
export function buildTimelineQuery(extraParams = {}) {
|
|
const { inviterId, code } = getShareInviterParams();
|
|
const params = { ...extraParams };
|
|
if (inviterId && !params.inviterId) {
|
|
params.inviterId = inviterId;
|
|
}
|
|
if (code && !params.code) {
|
|
params.code = code;
|
|
}
|
|
|
|
const queryParts = [];
|
|
for (const key of Object.keys(params)) {
|
|
const val = params[key];
|
|
if (val !== undefined && val !== null && val !== '') {
|
|
queryParts.push(`${encodeURIComponent(key)}=${encodeURIComponent(val)}`);
|
|
}
|
|
}
|
|
return queryParts.join('&');
|
|
}
|
|
|
|
/**
|
|
* 显式唤起微信小程序分享菜单 (同时激活【转发给朋友】与【分享到朋友圈】)
|
|
*/
|
|
export function enableShareMenu() {
|
|
// #ifdef MP-WEIXIN
|
|
try {
|
|
if (uni.canIUse && uni.canIUse('showShareMenu')) {
|
|
uni.showShareMenu({
|
|
withShareTicket: true,
|
|
menus: ['shareAppMessage', 'shareTimeline']
|
|
});
|
|
}
|
|
} catch (_) {}
|
|
// #endif
|
|
}
|
|
|
|
/**
|
|
* 页面级分享统一 Composable (支持在 Vue3 <script setup> 内直接调用)
|
|
* @param {Object|Function} options - 分享配置或动态 Getter 函数
|
|
*/
|
|
export function useShare(options = {}) {
|
|
onMounted(() => {
|
|
enableShareMenu();
|
|
});
|
|
|
|
onShow(() => {
|
|
enableShareMenu();
|
|
});
|
|
|
|
// 1. 监听【发送给朋友 / 微信好友 / 微信群】
|
|
onShareAppMessage((res) => {
|
|
const opt = typeof options === 'function' ? options(res) : options;
|
|
const title = (opt && opt.title) || DEFAULT_SHARE_TITLE;
|
|
const basePath = (opt && opt.path) || DEFAULT_INDEX_PATH;
|
|
const extraParams = (opt && opt.params) || {};
|
|
const finalPath = buildSharePath(basePath, extraParams);
|
|
const result = {
|
|
title,
|
|
path: finalPath
|
|
};
|
|
if (opt && opt.imageUrl) {
|
|
result.imageUrl = opt.imageUrl;
|
|
}
|
|
return result;
|
|
});
|
|
|
|
// 2. 监听【分享到朋友圈】
|
|
onShareTimeline(() => {
|
|
const opt = typeof options === 'function' ? options() : options;
|
|
const title = (opt && opt.timelineTitle) || (opt && opt.title) || DEFAULT_SHARE_TITLE;
|
|
const extraParams = (opt && opt.params) || (opt && opt.query) || {};
|
|
const query = typeof extraParams === 'string' ? extraParams : buildTimelineQuery(extraParams);
|
|
const result = {
|
|
title,
|
|
query
|
|
};
|
|
if (opt && opt.imageUrl) {
|
|
result.imageUrl = opt.imageUrl;
|
|
}
|
|
return result;
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 全局共享 Mixin (在 main.js 中注册,为所有未显式定义分享的页面提供兜底分享能力)
|
|
*/
|
|
export const shareMixin = {
|
|
onMounted() {
|
|
enableShareMenu();
|
|
},
|
|
onShow() {
|
|
enableShareMenu();
|
|
},
|
|
onShareAppMessage() {
|
|
let currentPath = DEFAULT_INDEX_PATH;
|
|
try {
|
|
const pages = getCurrentPages();
|
|
if (pages && pages.length > 0) {
|
|
const cur = pages[pages.length - 1];
|
|
if (cur && cur.route) {
|
|
currentPath = '/' + cur.route;
|
|
}
|
|
}
|
|
} catch (_) {}
|
|
return {
|
|
title: DEFAULT_SHARE_TITLE,
|
|
path: buildSharePath(currentPath)
|
|
};
|
|
},
|
|
onShareTimeline() {
|
|
return {
|
|
title: DEFAULT_SHARE_TITLE,
|
|
query: buildTimelineQuery()
|
|
};
|
|
}
|
|
};
|