Some checks failed
Build and Deploy / build-and-deploy (push) Has been cancelled
前端: - store 改为 votedArtists[] + zustand persist - VoteModal 删除 1/3/5/ALL 选择器,改三态(待投/已投/满额) - 卡片/排行/详情页加 hasVoted 状态 + ✓ 角标 - Hero 右上角 Countdown 替换为 HeroVoteProgress(12 格点亮进度) - /me 改为终身额度叙事(QuotaCard / StatsGrid / MyFanSupport) 后端: - votes 表加 @@unique([userId, artistId])(已 apply 到生产 RDS) - /api/vote 重写:12 票上限 + P2002 ALREADY_VOTED + P2003 NOT_FOUND 兜底 - /api/me 新增 votedArtists[] + voteQuota,移除 dailyQuota - 新增 ERR.ALREADY_VOTED 错误码 测试: - DB 层 5/5 + E2E 18/18 通过(scripts/e2e-vote-flow.sh) - 修复 P2003 FK 违反未识别的 bug 详情见 docs/todo/voting-refactor-完成报告.md 与 voting-refactor-backend-完成报告.md Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
94 lines
2.8 KiB
JavaScript
94 lines
2.8 KiB
JavaScript
// 只读探查生产 DB 真实状态 —— 不写任何数据,不改任何 schema。
|
|
// 用法:node scripts/inspect-db.mjs
|
|
import { PrismaClient } from "@prisma/client";
|
|
|
|
const prisma = new PrismaClient({ log: ["error"] });
|
|
|
|
async function main() {
|
|
console.log("=== 生产 DB 真实状态(只读)===\n");
|
|
|
|
// 1. 用户量级
|
|
const userCount = await prisma.user.count();
|
|
console.log(`users 总数: ${userCount}`);
|
|
|
|
// 2. 投票量级
|
|
const voteCount = await prisma.vote.count();
|
|
console.log(`votes 总数: ${voteCount}`);
|
|
|
|
// 3. 是否存在重复 (userId, artistId) — 加 unique 前必看
|
|
const dup = await prisma.$queryRaw`
|
|
SELECT user_id, artist_id, COUNT(*) AS cnt
|
|
FROM votes
|
|
GROUP BY user_id, artist_id
|
|
HAVING cnt > 1
|
|
ORDER BY cnt DESC
|
|
LIMIT 20
|
|
`;
|
|
console.log(`重复 (userId, artistId) 行数: ${dup.length}`);
|
|
if (dup.length > 0) {
|
|
console.log("Top 20 重复样本:");
|
|
for (const row of dup) {
|
|
console.log(` user=${row.user_id} artist=${row.artist_id} 重复=${row.cnt}`);
|
|
}
|
|
}
|
|
|
|
// 4. 单用户最大投票数 — 看是否有人已超过 12 票
|
|
const topVoters = await prisma.$queryRaw`
|
|
SELECT user_id, COUNT(*) AS total_votes, COUNT(DISTINCT artist_id) AS unique_artists
|
|
FROM votes
|
|
GROUP BY user_id
|
|
ORDER BY total_votes DESC
|
|
LIMIT 10
|
|
`;
|
|
console.log(`\nTop 10 投票最多的用户:`);
|
|
for (const row of topVoters) {
|
|
console.log(
|
|
` user=${row.user_id} total=${row.total_votes} 不同艺人=${row.unique_artists}`,
|
|
);
|
|
}
|
|
|
|
// 5. DailyQuota 状态
|
|
const dqCount = await prisma.dailyQuota.count();
|
|
console.log(`\ndaily_quota 总数: ${dqCount}`);
|
|
|
|
// 6. FanSupport 状态
|
|
const fsCount = await prisma.fanSupport.count();
|
|
console.log(`fan_supports 总数: ${fsCount}`);
|
|
|
|
// 7. ActivityConfig 配置
|
|
const config = await prisma.activityConfig.findUnique({ where: { id: 1 } });
|
|
console.log(`\nactivity_config:`);
|
|
if (config) {
|
|
console.log(` voteEnabled=${config.voteEnabled}`);
|
|
console.log(` dailyQuota=${config.dailyQuota}`);
|
|
console.log(` perArtistLimit=${config.perArtistLimit}`);
|
|
console.log(` startAt=${config.startAt.toISOString()}`);
|
|
console.log(` endAt=${config.endAt.toISOString()}`);
|
|
} else {
|
|
console.log(" (空)");
|
|
}
|
|
|
|
// 8. Vote 表当前索引(原始 SQL 探)
|
|
const indexes = await prisma.$queryRaw`
|
|
SHOW INDEX FROM votes
|
|
`;
|
|
console.log(`\nvotes 当前索引:`);
|
|
for (const idx of indexes) {
|
|
console.log(
|
|
` ${idx.Key_name} col=${idx.Column_name} seq=${idx.Seq_in_index} unique=${idx.Non_unique === 0 ? "Y" : "N"}`,
|
|
);
|
|
}
|
|
|
|
// 9. 服务器版本
|
|
const ver = await prisma.$queryRaw`SELECT VERSION() AS v`;
|
|
console.log(`\nMySQL 版本: ${ver[0].v}`);
|
|
|
|
await prisma.$disconnect();
|
|
}
|
|
|
|
main().catch(async (e) => {
|
|
console.error(e);
|
|
await prisma.$disconnect();
|
|
process.exit(1);
|
|
});
|