diff --git a/wechat-mp-config.mjs b/wechat-mp-config.mjs
index 6e1c43b..c630e9f 100644
--- a/wechat-mp-config.mjs
+++ b/wechat-mp-config.mjs
@@ -4,6 +4,8 @@ const DEFAULT_STATUS_TEXT =
'我在这边。上一条如果还没完成,我会继续把结果发给你;你也可以直接补一句要求。';
const DEFAULT_UNSUPPORTED_TEXT = '当前先支持文字消息,你可以直接发文字给我。';
const DEFAULT_UNBOUND_TEXT = '先点这里完成绑定,再继续和专属 Agent 对话:';
+const DEFAULT_SUBSCRIBE_INTRO_URL =
+ 'https://m.tkmind.cn/MindSpace/a70ff537-8908-486e-9b6c-042e07cc25db/public/tkmind-deep-intro.html';
const DEFAULT_PROGRESS_DELAY_MS = 8000;
const DEFAULT_SESSION_IDLE_ROTATE_MS = 30 * 60 * 1000;
const DEFAULT_SESSION_MESSAGE_ROTATE_COUNT = 200;
@@ -69,6 +71,8 @@ export function loadWechatMpConfig(env = process.env) {
statusText: env.H5_WECHAT_MP_STATUS_TEXT?.trim() || DEFAULT_STATUS_TEXT,
unsupportedText: env.H5_WECHAT_MP_UNSUPPORTED_TEXT?.trim() || DEFAULT_UNSUPPORTED_TEXT,
unboundTextPrefix: env.H5_WECHAT_MP_UNBOUND_TEXT_PREFIX?.trim() || DEFAULT_UNBOUND_TEXT,
+ subscribeIntroUrl:
+ env.H5_WECHAT_MP_SUBSCRIBE_INTRO_URL?.trim() || DEFAULT_SUBSCRIBE_INTRO_URL,
tokenUrl: env.H5_WECHAT_MP_TOKEN_URL?.trim() || DEFAULT_WECHAT_TOKEN_URL,
customerServiceUrl:
env.H5_WECHAT_MP_CUSTOMER_SERVICE_URL?.trim() || DEFAULT_WECHAT_CUSTOMER_SERVICE_URL,
diff --git a/wechat-mp.mjs b/wechat-mp.mjs
index 039a8ca..89b1f23 100644
--- a/wechat-mp.mjs
+++ b/wechat-mp.mjs
@@ -42,6 +42,7 @@ import { handleWechatIntentTransaction } from './wechat/handlers/intent-transact
import { handleWechatScheduledTaskIntent } from './wechat/handlers/scheduled-task.mjs';
import {
buildStatusText,
+ buildSubscribeWelcomeText,
resolveSyncReply,
shouldHandleSyncReply,
} from './wechat/handlers/sync-replies.mjs';
@@ -3768,7 +3769,10 @@ export function createWechatMpService({
body: buildWechatTextReply({
toUserName: inbound.fromUserName,
fromUserName: inbound.toUserName,
- content: `${config.unboundTextPrefix}\n${buildBindUrl()}`,
+ content: buildSubscribeWelcomeText({
+ bindUrl: buildBindUrl(),
+ introUrl: config.subscribeIntroUrl,
+ }),
}),
};
}
diff --git a/wechat/handlers/sync-replies.mjs b/wechat/handlers/sync-replies.mjs
index 92b2a6d..bc73c2b 100644
--- a/wechat/handlers/sync-replies.mjs
+++ b/wechat/handlers/sync-replies.mjs
@@ -1,5 +1,42 @@
import { resolveWechatAddressName } from '../user/display-name.mjs';
+export const DEFAULT_SUBSCRIBE_INTRO_URL =
+ 'https://m.tkmind.cn/MindSpace/a70ff537-8908-486e-9b6c-042e07cc25db/public/tkmind-deep-intro.html';
+
+/** 103 生产默认绑定入口:{H5_PUBLIC_BASE_URL}/auth/wechat/authorize?intent=login */
+export const DEFAULT_PRODUCTION_BIND_URL =
+ 'https://m.tkmind.cn/auth/wechat/authorize?intent=login';
+
+export function buildWechatTextLink(href, label) {
+ const normalizedHref = String(href ?? '').trim();
+ const normalizedLabel = String(label ?? '').trim();
+ if (!normalizedHref) return normalizedLabel;
+ if (!normalizedLabel) return normalizedHref;
+ return `${normalizedLabel}`;
+}
+
+export function buildSubscribeWelcomeText({ bindUrl, introUrl = DEFAULT_SUBSCRIBE_INTRO_URL } = {}) {
+ const normalizedBindUrl = String(bindUrl ?? '').trim();
+ const normalizedIntroUrl = String(introUrl ?? '').trim();
+ const lines = [
+ '欢迎关注 TKMind 智趣 👋',
+ '',
+ '在微信里直接发消息即可:',
+ '· 问答、写作、翻译',
+ '· 生成精美网页并给链接',
+ '· 发图解读报告/截图',
+ '· 设置定时提醒与每日推送',
+ ];
+ if (normalizedIntroUrl) {
+ lines.push('', '📖 了解更多:', buildWechatTextLink(normalizedIntroUrl, '点击链接'));
+ }
+ if (normalizedBindUrl) {
+ lines.push('', '👉 先完成绑定再开始对话:', buildWechatTextLink(normalizedBindUrl, '点我绑定'));
+ }
+ lines.push('', '绑定后回复「你好」,或试试:', '「帮我做一个读书笔记页面」');
+ return lines.join('\n');
+}
+
export function buildGreetingText(user) {
const name = resolveWechatAddressName(user);
return name ? `你好,${name}!我在呢,有什么需要?` : '你好!我在呢,有什么需要?';
diff --git a/wechat/handlers/sync-replies.test.mjs b/wechat/handlers/sync-replies.test.mjs
new file mode 100644
index 0000000..2dd1f59
--- /dev/null
+++ b/wechat/handlers/sync-replies.test.mjs
@@ -0,0 +1,45 @@
+import test from 'node:test';
+import assert from 'node:assert/strict';
+
+import {
+ buildSubscribeWelcomeText,
+ buildWechatTextLink,
+ DEFAULT_PRODUCTION_BIND_URL,
+ DEFAULT_SUBSCRIBE_INTRO_URL,
+} from './sync-replies.mjs';
+
+test('buildWechatTextLink renders WeChat anchor without exposing raw url', () => {
+ assert.equal(
+ buildWechatTextLink(DEFAULT_PRODUCTION_BIND_URL, '点我绑定'),
+ `点我绑定`,
+ );
+});
+
+test('buildSubscribeWelcomeText uses clickable anchors instead of raw urls', () => {
+ const text = buildSubscribeWelcomeText({ bindUrl: DEFAULT_PRODUCTION_BIND_URL });
+
+ assert.match(text, /欢迎关注 TKMind 智趣/);
+ assert.match(text, /生成精美网页并给链接/);
+ assert.match(text, /📖 了解更多:/);
+ assert.match(
+ text,
+ /点击链接<\/a>/,
+ );
+ assert.match(text, /👉 先完成绑定再开始对话:/);
+ assert.match(
+ text,
+ /点我绑定<\/a>/,
+ );
+ assert.doesNotMatch(text, /\nhttps:\/\/m\.tkmind\.cn/);
+ assert.match(text, /帮我做一个读书笔记页面/);
+});
+
+test('buildSubscribeWelcomeText omits intro section when introUrl is empty', () => {
+ const text = buildSubscribeWelcomeText({
+ bindUrl: 'https://m.tkmind.cn/bind',
+ introUrl: '',
+ });
+
+ assert.doesNotMatch(text, /📖 了解更多:/);
+ assert.doesNotMatch(text, /tkmind-deep-intro\.html/);
+});