文件
shanghaipeiwan/pwuniapp/common/share.js

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()
};
}
};