Initial commit: Memind H5 portal with MindSpace, Plaza, and agent jobs.

Track application source and tests; exclude local env, user workspaces, and runtime data via .gitignore.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
John
2026-06-15 15:04:43 -07:00
commit 2e14873f2d
272 changed files with 64133 additions and 0 deletions
+57
View File
@@ -0,0 +1,57 @@
export function isWechatBrowser(userAgent = navigator.userAgent) {
const ua = userAgent || '';
return /MicroMessenger/i.test(ua) || /WindowsWechat/i.test(ua);
}
/** 从服务号链接进入时带的参数(即使 UA 识别失败也展示微信登录) */
export function isWechatEntryUrl(search = window.location.search) {
const params = new URLSearchParams(search);
const from = (params.get('from') || '').toLowerCase();
const utm = (params.get('utm_source') || '').toLowerCase();
return from === 'wechat' || utm === 'wechat';
}
export function isWechatContext(options?: {
userAgent?: string;
search?: string;
serverInWechat?: boolean;
}) {
if (options?.serverInWechat) return true;
if (isWechatBrowser(options?.userAgent)) return true;
return isWechatEntryUrl(options?.search);
}
export function buildWechatAuthorizeUrl(options?: {
returnTo?: string;
utmSource?: string;
utmMedium?: string;
utmCampaign?: string;
}) {
const params = new URLSearchParams();
const returnTo =
options?.returnTo ??
`${window.location.pathname}${window.location.search}${window.location.hash}`;
if (returnTo && returnTo !== '/') {
params.set('return_to', returnTo);
}
if (options?.utmSource) params.set('utm_source', options.utmSource);
if (options?.utmMedium) params.set('utm_medium', options.utmMedium);
if (options?.utmCampaign) params.set('utm_campaign', options.utmCampaign);
const query = params.toString();
return query ? `/auth/wechat/authorize?${query}` : '/auth/wechat/authorize';
}
export function readWechatAuthError(): string | null {
const params = new URLSearchParams(window.location.search);
const error = params.get('wechat_error');
if (!error) return null;
params.delete('wechat_error');
const nextSearch = params.toString();
const nextUrl = `${window.location.pathname}${nextSearch ? `?${nextSearch}` : ''}${window.location.hash}`;
window.history.replaceState({}, '', nextUrl);
try {
return decodeURIComponent(error);
} catch {
return error;
}
}