Improve WeChat MP replies and ship MindSpace/H5 production updates.
Add WeChat service account routing with sync acks, connectivity tests, and context isolation; document deploy runbooks; and bundle related MindSpace, voice, Plaza, and server gateway changes for production rollout. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+39
-5
@@ -92,6 +92,7 @@ function pageResponse(row) {
|
||||
status: row.status,
|
||||
visibility: row.visibility,
|
||||
publicationAccessMode: row.pub_access_mode ?? null,
|
||||
publicationUrl: row.pub_public_url ?? null,
|
||||
currentVersionId: row.current_version_id,
|
||||
versionNo: asNumber(row.version_no),
|
||||
content: row.content,
|
||||
@@ -225,6 +226,37 @@ export function createPageService(pool, options = {}) {
|
||||
return resolved;
|
||||
};
|
||||
|
||||
const resolveStoragePathCandidates = (storageKey) => {
|
||||
const normalized = String(storageKey ?? '').replace(/\\/g, '/');
|
||||
const withoutMd = normalized.endsWith('.md') ? normalized.slice(0, -3) : normalized;
|
||||
const match = withoutMd.match(/^users\/([^/]+)\/(assets|pages)\/([^/]+)\/(v\d+)$/);
|
||||
if (!match) return [normalized];
|
||||
const [, userId, scope, entityId, versionTag] = match;
|
||||
return [
|
||||
normalized,
|
||||
`users/${userId}/${scope}/${entityId}/versions/${versionTag}.md`,
|
||||
`users/${userId}/${scope}/${entityId}/versions/${versionTag}`,
|
||||
].filter((candidate, index, list) => list.indexOf(candidate) === index);
|
||||
};
|
||||
|
||||
const resolveReadableStoragePath = async (storageKey) => {
|
||||
let lastError = null;
|
||||
for (const candidate of resolveStoragePathCandidates(storageKey)) {
|
||||
const absolutePath = absoluteStoragePath(candidate);
|
||||
try {
|
||||
await fs.stat(absolutePath);
|
||||
return absolutePath;
|
||||
} catch (error) {
|
||||
if (error?.code === 'ENOENT') {
|
||||
lastError = error;
|
||||
continue;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
throw lastError ?? Object.assign(new Error('存储文件不存在'), { code: 'storage_not_found' });
|
||||
};
|
||||
|
||||
const writeVersionContent = async (userId, assetId, versionId, content) => {
|
||||
const storageKey = path.posix.join(
|
||||
'users',
|
||||
@@ -479,8 +511,8 @@ export function createPageService(pool, options = {}) {
|
||||
|
||||
const findPageBySourceAsset = async (userId, assetId) => {
|
||||
if (!assetId) return null;
|
||||
const [rows] = await pool.query(
|
||||
`SELECT p.*, c.category_code, pv.version_no, pr.access_mode AS pub_access_mode
|
||||
const [rows] = await pool.query(
|
||||
`SELECT p.*, c.category_code, pv.version_no, pr.access_mode AS pub_access_mode, pr.public_url AS pub_public_url
|
||||
FROM h5_page_records p
|
||||
JOIN h5_space_categories c ON c.id = p.category_id AND c.user_id = p.user_id
|
||||
LEFT JOIN h5_page_versions pv ON pv.id = p.current_version_id
|
||||
@@ -501,7 +533,7 @@ export function createPageService(pool, options = {}) {
|
||||
params.push(filters.status);
|
||||
}
|
||||
const [rows] = await pool.query(
|
||||
`SELECT p.*, c.category_code, pv.version_no, pr.access_mode AS pub_access_mode
|
||||
`SELECT p.*, c.category_code, pv.version_no, pr.access_mode AS pub_access_mode, pr.public_url AS pub_public_url
|
||||
FROM h5_page_records p
|
||||
JOIN h5_space_categories c ON c.id = p.category_id AND c.user_id = p.user_id
|
||||
LEFT JOIN h5_page_versions pv ON pv.id = p.current_version_id
|
||||
@@ -526,7 +558,8 @@ export function createPageService(pool, options = {}) {
|
||||
);
|
||||
const row = rows[0];
|
||||
if (!row) throw pageError('页面不存在', 'page_not_found');
|
||||
const content = await fs.readFile(absoluteStoragePath(row.storage_key), 'utf8');
|
||||
const storagePath = await resolveReadableStoragePath(row.storage_key);
|
||||
const content = await fs.readFile(storagePath, 'utf8');
|
||||
return pageResponse({ ...row, content });
|
||||
}
|
||||
|
||||
@@ -863,7 +896,8 @@ export function createPageService(pool, options = {}) {
|
||||
if (row.page_type !== 'html') {
|
||||
throw pageError('该页面不支持缩略图', 'thumbnail_not_supported');
|
||||
}
|
||||
const content = await fs.readFile(absoluteStoragePath(row.storage_key), 'utf8');
|
||||
const storagePath = await resolveReadableStoragePath(row.storage_key);
|
||||
const content = await fs.readFile(storagePath, 'utf8');
|
||||
let snapshot = {};
|
||||
try {
|
||||
snapshot = JSON.parse(row.source_snapshot_json ?? '{}');
|
||||
|
||||
Reference in New Issue
Block a user