feat(账号分析+工作台): 功能三自动联动生成设定卡+双向联动维护+玫瑰金配色定稿+首页数据预览/周榜优化+CDP验证脚本
- mcn-dou-analysis: 功能三产出设定后自动生成设定卡(Step7); 设定md与卡片SVG双向联动维护规则固化(06文档+03文档+SKILL.md); 浅色系配色定稿玫瑰金(#D6A3A9→#9A5563)+背景文字提亮规则; 新增06生成账号设定卡片文档+模板样例 - mcn-work-shop: 首页数据预览条/周榜预览表加宽/改名AI脚本诊断/tab切换/添加账号弹窗等优化 - 新增 cdp-*.mjs 验证脚本14个(可复用); .gitignore 忽略运行日志/截图/tmp
This commit is contained in:
1 parent
96fce56fba
commit
53621279a5
35 files changed
+2567
-117
No files matched your search
@@ -55,6 +55,31 @@ function resolveSafe(rawPath) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// ---- 查找账号设定卡 SVG ----
|
||||
// 产出规范:{产出根}/{达人昵称}/{达人昵称}账号设定卡.svg(功能六产出,与账号设定.md 同目录)
|
||||
// 查找顺序:规范路径 → 根下直挂 → 账号目录内扫描(防目录名/账号名不一致)
|
||||
function findAccountCard(name) {
|
||||
const safeName = String(name || '').replace(/[\\/:*?"<>|]/g, '_').trim();
|
||||
if (!safeName) return null;
|
||||
for (const root of allowedRoots()) {
|
||||
const p1 = path.join(root, safeName, safeName + '账号设定卡.svg');
|
||||
const p2 = path.join(root, safeName + '账号设定卡.svg');
|
||||
for (const c of [p1, p2]) {
|
||||
try { if (fs.existsSync(c) && fs.statSync(c).isFile()) return c; } catch (e) { /* 忽略 */ }
|
||||
}
|
||||
}
|
||||
for (const root of allowedRoots()) {
|
||||
const dir = path.join(root, safeName);
|
||||
try {
|
||||
if (fs.statSync(dir).isDirectory()) {
|
||||
const hit = fs.readdirSync(dir).find((f) => f.toLowerCase().endsWith('.svg') && f.includes('账号设定卡'));
|
||||
if (hit) return path.join(dir, hit);
|
||||
}
|
||||
} catch (e) { /* 忽略 */ }
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// ---- 目录树(递归,跳过隐藏项)----
|
||||
function buildTree(absPath, depth) {
|
||||
if (depth > 4) return null;
|
||||
@@ -206,6 +231,25 @@ const server = http.createServer((req, res) => {
|
||||
return;
|
||||
}
|
||||
|
||||
if (p === '/api/file') {
|
||||
// 内联输出(无 attachment 头):供 <img>/<object> 直接渲染(如账号设定卡 SVG)
|
||||
const safe = resolveSafe(q.get('path'));
|
||||
if (!safe) return sendErr(403, '路径不在允许范围');
|
||||
try {
|
||||
const st = fs.statSync(safe.abs);
|
||||
if (!st.isFile()) return sendErr(404, '文件不存在');
|
||||
res.writeHead(200, {
|
||||
'Content-Type': mimeOf(safe.abs),
|
||||
'Content-Length': st.size,
|
||||
'Cache-Control': 'no-store',
|
||||
});
|
||||
fs.createReadStream(safe.abs).pipe(res);
|
||||
} catch (e) {
|
||||
return sendErr(500, '读取失败: ' + e.message);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// ---------- 数据功能(只读工作台自有数据库副本) ----------
|
||||
const dshOk = (code, obj) => sendJSON(code, { ok: true, ...obj });
|
||||
const dshGuard = (res2) => { if (!dsh.dbAvailable()) { sendJSON(200, { ok: false, error: '未检测到工作台数据库(mcn-plugin.db),本功能不可用' }); return true; } return false; };
|
||||
@@ -257,6 +301,12 @@ const server = http.createServer((req, res) => {
|
||||
const r = dsh.getPersona(qInt('accountId', 0));
|
||||
return dshOk(200, { content: r ? r.content : null, analysisTime: r ? r.analysis_time : null });
|
||||
}
|
||||
if (p === '/api/dsh/account-card') {
|
||||
// 查询账号设定卡 SVG 文件(桌面产出,允许根目录下查找):{账号名}账号设定卡.svg
|
||||
if (dshGuard()) return;
|
||||
const hit = findAccountCard(q.get('name'));
|
||||
return dshOk(200, { exists: !!hit, path: hit || null });
|
||||
}
|
||||
if (p === '/api/dsh/account-analysis') {
|
||||
if (dshGuard()) return;
|
||||
const r = dsh.getAccountAnalysis(qInt('accountId', 0));
|
||||
|
||||
Reference in new issue
Block a user