sa2kit 1.6.91 → 1.6.96
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client-BlkUL2To.d.ts +26 -0
- package/dist/client-DpMIhrlS.d.mts +26 -0
- package/dist/huarongdao/index.d.mts +8 -0
- package/dist/huarongdao/index.d.ts +8 -0
- package/dist/huarongdao/index.js +360 -0
- package/dist/huarongdao/index.js.map +1 -0
- package/dist/huarongdao/index.mjs +338 -0
- package/dist/huarongdao/index.mjs.map +1 -0
- package/dist/huarongdao/logic/index.d.mts +11 -0
- package/dist/huarongdao/logic/index.d.ts +11 -0
- package/dist/huarongdao/logic/index.js +89 -0
- package/dist/huarongdao/logic/index.js.map +1 -0
- package/dist/huarongdao/logic/index.mjs +81 -0
- package/dist/huarongdao/logic/index.mjs.map +1 -0
- package/dist/huarongdao/routes/index.d.mts +38 -0
- package/dist/huarongdao/routes/index.d.ts +38 -0
- package/dist/huarongdao/routes/index.js +114 -0
- package/dist/huarongdao/routes/index.js.map +1 -0
- package/dist/huarongdao/routes/index.mjs +108 -0
- package/dist/huarongdao/routes/index.mjs.map +1 -0
- package/dist/huarongdao/server/index.d.mts +14 -0
- package/dist/huarongdao/server/index.d.ts +14 -0
- package/dist/huarongdao/server/index.js +60 -0
- package/dist/huarongdao/server/index.js.map +1 -0
- package/dist/huarongdao/server/index.mjs +57 -0
- package/dist/huarongdao/server/index.mjs.map +1 -0
- package/dist/huarongdao/service/index.d.mts +31 -0
- package/dist/huarongdao/service/index.d.ts +31 -0
- package/dist/huarongdao/service/index.js +45 -0
- package/dist/huarongdao/service/index.js.map +1 -0
- package/dist/huarongdao/service/index.mjs +42 -0
- package/dist/huarongdao/service/index.mjs.map +1 -0
- package/dist/huarongdao/types/index.d.mts +46 -0
- package/dist/huarongdao/types/index.d.ts +46 -0
- package/dist/huarongdao/types/index.js +4 -0
- package/dist/huarongdao/types/index.js.map +1 -0
- package/dist/huarongdao/types/index.mjs +3 -0
- package/dist/huarongdao/types/index.mjs.map +1 -0
- package/dist/huarongdao/ui/web/index.d.mts +3 -0
- package/dist/huarongdao/ui/web/index.d.ts +3 -0
- package/dist/huarongdao/ui/web/index.js +237 -0
- package/dist/huarongdao/ui/web/index.js.map +1 -0
- package/dist/huarongdao/ui/web/index.mjs +229 -0
- package/dist/huarongdao/ui/web/index.mjs.map +1 -0
- package/dist/index-B48rcsqv.d.ts +27 -0
- package/dist/index-BNqJdwX4.d.ts +37 -0
- package/dist/index-C7yh6b5Q.d.mts +17 -0
- package/dist/index-CDapUIT5.d.mts +51 -0
- package/dist/index-Cv9jlnNz.d.ts +17 -0
- package/dist/index-D3UbkUai.d.ts +51 -0
- package/dist/index-DOtQI_mz.d.mts +37 -0
- package/dist/index-Da2X78GE.d.mts +27 -0
- package/dist/index.d.mts +18 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +1707 -79
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1675 -82
- package/dist/index.mjs.map +1 -1
- package/dist/mikuContest/index.d.mts +13 -0
- package/dist/mikuContest/index.d.ts +13 -0
- package/dist/mikuContest/index.js +1310 -0
- package/dist/mikuContest/index.js.map +1 -0
- package/dist/mikuContest/index.mjs +1253 -0
- package/dist/mikuContest/index.mjs.map +1 -0
- package/dist/mikuContest/logic/index.d.mts +32 -0
- package/dist/mikuContest/logic/index.d.ts +32 -0
- package/dist/mikuContest/logic/index.js +511 -0
- package/dist/mikuContest/logic/index.js.map +1 -0
- package/dist/mikuContest/logic/index.mjs +483 -0
- package/dist/mikuContest/logic/index.mjs.map +1 -0
- package/dist/mikuContest/routes/index.d.mts +80 -0
- package/dist/mikuContest/routes/index.d.ts +80 -0
- package/dist/mikuContest/routes/index.js +821 -0
- package/dist/mikuContest/routes/index.js.map +1 -0
- package/dist/mikuContest/routes/index.mjs +791 -0
- package/dist/mikuContest/routes/index.mjs.map +1 -0
- package/dist/mikuContest/server/index.d.mts +766 -0
- package/dist/mikuContest/server/index.d.ts +766 -0
- package/dist/mikuContest/server/index.js +705 -0
- package/dist/mikuContest/server/index.js.map +1 -0
- package/dist/mikuContest/server/index.mjs +672 -0
- package/dist/mikuContest/server/index.mjs.map +1 -0
- package/dist/mikuContest/service/index.d.mts +30 -0
- package/dist/mikuContest/service/index.d.ts +30 -0
- package/dist/mikuContest/service/index.js +139 -0
- package/dist/mikuContest/service/index.js.map +1 -0
- package/dist/mikuContest/service/index.mjs +135 -0
- package/dist/mikuContest/service/index.mjs.map +1 -0
- package/dist/mikuContest/types/index.d.mts +179 -0
- package/dist/mikuContest/types/index.d.ts +179 -0
- package/dist/mikuContest/types/index.js +4 -0
- package/dist/mikuContest/types/index.js.map +1 -0
- package/dist/mikuContest/types/index.mjs +3 -0
- package/dist/mikuContest/types/index.mjs.map +1 -0
- package/dist/mikuContest/ui/miniapp/index.d.mts +3 -0
- package/dist/mikuContest/ui/miniapp/index.d.ts +3 -0
- package/dist/mikuContest/ui/miniapp/index.js +566 -0
- package/dist/mikuContest/ui/miniapp/index.js.map +1 -0
- package/dist/mikuContest/ui/miniapp/index.mjs +540 -0
- package/dist/mikuContest/ui/miniapp/index.mjs.map +1 -0
- package/dist/mikuContest/ui/web/index.d.mts +4 -0
- package/dist/mikuContest/ui/web/index.d.ts +4 -0
- package/dist/mikuContest/ui/web/index.js +353 -0
- package/dist/mikuContest/ui/web/index.js.map +1 -0
- package/dist/mikuContest/ui/web/index.mjs +343 -0
- package/dist/mikuContest/ui/web/index.mjs.map +1 -0
- package/dist/qqbot/server/index.d.mts +126 -1
- package/dist/qqbot/server/index.d.ts +126 -1
- package/dist/qqbot/server/index.js +250 -0
- package/dist/qqbot/server/index.js.map +1 -1
- package/dist/qqbot/server/index.mjs +246 -1
- package/dist/qqbot/server/index.mjs.map +1 -1
- package/dist/service-D7DM1wW-.d.ts +38 -0
- package/dist/service-DPr2rlvH.d.mts +38 -0
- package/dist/types-BS7Xz09b.d.mts +14 -0
- package/dist/types-k4koMp4m.d.ts +14 -0
- package/package.json +76 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/mikuContest/ui/miniapp/components/MikuContestMiniappHome.tsx","../../../../src/mikuContest/logic/shared/defaults.ts","../../../../src/mikuContest/logic/shared/validators.ts","../../../../src/mikuContest/logic/shared/voting.ts","../../../../src/mikuContest/server/service.ts","../../../../src/mikuContest/server/persistence/drizzle-schema.ts","../../../../src/mikuContest/logic/hooks/useMikuContest.ts","../../../../src/mikuContest/ui/miniapp/pages/MikuContestMiniappPage.tsx"],"names":["React","text","useState","useMemo"],"mappings":"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","file":"index.mjs","sourcesContent":["import React from 'react';\nimport type { MikuContestStateSnapshot } from '../../../types';\n\nexport interface MikuContestMiniappHomeProps {\n snapshot: MikuContestStateSnapshot;\n}\n\nconst MikuContestMiniappHome: React.FC<MikuContestMiniappHomeProps> = ({ snapshot }) => {\n return (\n <div>\n <h3>{snapshot.contest.name}</h3>\n <p>投稿:{snapshot.submissions.length} | 公告:{snapshot.announcements.length}</p>\n <ol>\n {snapshot.leaderboard.slice(0, 3).map((item) => (\n <li key={item.submissionId}>\n {item.title}({item.voteCount}票)\n </li>\n ))}\n </ol>\n </div>\n );\n};\n\nexport default MikuContestMiniappHome;\n","import type { MikuContestConfig, MikuVotingRules } from '../../types';\n\nexport const defaultMikuVotingRules: MikuVotingRules = {\n maxVotesPerDay: 3,\n forbidDuplicateVotePerWork: true,\n maxVotesPerDevicePerDay: 20,\n maxVotesPerIpPerDay: 100,\n};\n\nexport const createDefaultMikuContestConfig = (overrides?: Partial<MikuContestConfig>): MikuContestConfig => ({\n id: overrides?.id || 'miku-contest-default',\n name: overrides?.name || '初音未来社团征稿大赛',\n theme: overrides?.theme || '初音未来主题创作征稿',\n organizer: overrides?.organizer || '初音未来社团',\n awards: overrides?.awards || ['一等奖', '二等奖', '三等奖', '人气奖'],\n rules: overrides?.rules || '请确保作品原创且符合社团规范。',\n copyright: overrides?.copyright || '投稿即视为授权赛事展示与公示。',\n timeline: overrides?.timeline || {\n submissionStartAt: new Date().toISOString(),\n submissionEndAt: new Date().toISOString(),\n votingStartAt: new Date().toISOString(),\n votingEndAt: new Date().toISOString(),\n publicResultAt: new Date().toISOString(),\n },\n votingRules: {\n ...defaultMikuVotingRules,\n ...(overrides?.votingRules || {}),\n },\n toggles: {\n submissionEnabled: overrides?.toggles?.submissionEnabled ?? true,\n votingEnabled: overrides?.toggles?.votingEnabled ?? true,\n resultEnabled: overrides?.toggles?.resultEnabled ?? false,\n },\n});\n","import type { CreateMikuSubmissionInput, MikuWorkType } from '../../types';\n\nconst DESCRIPTION_LIMIT = 500;\nconst MINIAPP_DESCRIPTION_LIMIT = 200;\nconst TEXT_CONTENT_LIMIT = 2000;\nconst MAX_TAGS = 3;\n\nconst hasValue = (value: unknown): boolean => {\n return typeof value === 'string' ? value.trim().length > 0 : value !== null && value !== undefined;\n};\n\nconst validateByType = (type: MikuWorkType, input: CreateMikuSubmissionInput): string[] => {\n const errors: string[] = [];\n const { content } = input;\n\n switch (type) {\n case 'visual': {\n const imageCount = content.images?.length || 0;\n if (imageCount < 1 || imageCount > 3) {\n errors.push('视觉类作品需上传 1-3 张图片');\n }\n break;\n }\n case 'video': {\n if (!hasValue(content.videoLink)) {\n errors.push('视频类作品需提供视频链接');\n }\n if (!hasValue(content.coverImage)) {\n errors.push('视频类作品需提供封面图');\n }\n break;\n }\n case 'text': {\n const text = content.textContent || '';\n if (!text.trim()) {\n errors.push('文字类作品需填写正文');\n }\n if (text.length > TEXT_CONTENT_LIMIT) {\n errors.push(`文字正文不能超过 ${TEXT_CONTENT_LIMIT} 字`);\n }\n break;\n }\n case 'audio': {\n if (!hasValue(content.audioLink)) {\n errors.push('音频类作品需提供音频链接');\n }\n break;\n }\n default:\n break;\n }\n\n return errors;\n};\n\nexport const validateMikuSubmissionInput = (\n input: CreateMikuSubmissionInput,\n mode: 'web' | 'miniapp' = 'web',\n): string[] => {\n const errors: string[] = [];\n\n if (!input.contestId.trim()) errors.push('contestId 不能为空');\n if (!input.authorId.trim()) errors.push('authorId 不能为空');\n if (!input.authorNickname.trim()) errors.push('作者昵称不能为空');\n if (!input.title.trim()) errors.push('作品名称不能为空');\n\n const descriptionLimit = mode === 'miniapp' ? MINIAPP_DESCRIPTION_LIMIT : DESCRIPTION_LIMIT;\n if (input.description.length > descriptionLimit) {\n errors.push(`作品简介不能超过 ${descriptionLimit} 字`);\n }\n\n if ((input.tags?.length || 0) > MAX_TAGS) {\n errors.push(`标签最多 ${MAX_TAGS} 个`);\n }\n\n errors.push(...validateByType(input.type, input));\n return errors;\n};\n","import type { MikuVoteRecord, MikuVotingRules } from '../../types';\n\nexport const toVoteDayKey = (date: Date = new Date()): string => {\n const y = date.getUTCFullYear();\n const m = String(date.getUTCMonth() + 1).padStart(2, '0');\n const d = String(date.getUTCDate()).padStart(2, '0');\n return `${y}-${m}-${d}`;\n};\n\nexport interface VoteCheckContext {\n existingVotes: MikuVoteRecord[];\n submissionId: string;\n voterId: string;\n dayKey: string;\n rules: MikuVotingRules;\n}\n\nexport const checkVoteEligibility = (context: VoteCheckContext): { ok: boolean; reason?: string } => {\n const { existingVotes, submissionId, voterId, dayKey, rules } = context;\n\n const userTodayVotes = existingVotes.filter((vote) => vote.voterId === voterId && vote.dayKey === dayKey);\n\n if (userTodayVotes.length >= rules.maxVotesPerDay) {\n return { ok: false, reason: '已达到今日投票上限' };\n }\n\n if (rules.forbidDuplicateVotePerWork) {\n const duplicated = userTodayVotes.some((vote) => vote.submissionId === submissionId);\n if (duplicated) return { ok: false, reason: '不可重复投同一作品' };\n }\n\n return { ok: true };\n};\n\nexport const sortByVotesDesc = <T extends { voteCount: number; createdAt?: string }>(items: T[]): T[] => {\n return [...items].sort((a, b) => {\n if (b.voteCount === a.voteCount) {\n return (a.createdAt || '').localeCompare(b.createdAt || '');\n }\n return b.voteCount - a.voteCount;\n });\n};\n","import {\n checkVoteEligibility,\n createDefaultMikuContestConfig,\n sortByVotesDesc,\n toVoteDayKey,\n validateMikuSubmissionInput,\n} from '../logic/shared';\nimport * as XLSX from 'xlsx';\nimport type {\n CreateMikuAnnouncementInput,\n CreateMikuSubmissionInput,\n MikuAnnouncement,\n MikuContestConfig,\n MikuContestPersistedState,\n MikuContestStateSnapshot,\n MikuLeaderboardItem,\n MikuSubmissionExportRow,\n MikuSubmissionFilter,\n MikuSubmission,\n MikuVoterRestriction,\n MikuVoteRecord,\n ResetMikuVotesInput,\n ReviewMikuSubmissionInput,\n SetMikuVoterRestrictionInput,\n VoteMikuSubmissionInput,\n} from '../types';\n\nconst randomId = (prefix: string): string => {\n return `${prefix}_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;\n};\n\nconst serialNo = (): string => {\n const now = new Date();\n const y = now.getFullYear();\n const m = String(now.getMonth() + 1).padStart(2, '0');\n const d = String(now.getDate()).padStart(2, '0');\n const seq = Math.floor(Math.random() * 9000 + 1000);\n return `MIKU-${y}${m}${d}-${seq}`;\n};\n\nexport interface MikuContestServiceOptions {\n contestConfig?: Partial<MikuContestConfig>;\n}\n\nexport class MikuContestService {\n private contest: MikuContestConfig;\n\n private readonly submissions = new Map<string, MikuSubmission>();\n\n private readonly votes: MikuVoteRecord[] = [];\n\n private readonly announcements = new Map<string, MikuAnnouncement>();\n\n private readonly voterRestrictions = new Map<string, MikuVoterRestriction>();\n\n constructor(options: MikuContestServiceOptions = {}) {\n this.contest = createDefaultMikuContestConfig(options.contestConfig);\n }\n\n getContestConfig(): MikuContestConfig {\n return this.contest;\n }\n\n updateContestConfig(patch: Partial<MikuContestConfig>): MikuContestConfig {\n this.contest = {\n ...this.contest,\n ...patch,\n votingRules: {\n ...this.contest.votingRules,\n ...(patch.votingRules || {}),\n },\n toggles: {\n ...this.contest.toggles,\n ...(patch.toggles || {}),\n },\n timeline: {\n ...this.contest.timeline,\n ...(patch.timeline || {}),\n },\n };\n\n return this.contest;\n }\n\n createSubmission(input: CreateMikuSubmissionInput, mode: 'web' | 'miniapp' = 'web'): MikuSubmission {\n if (!this.contest.toggles.submissionEnabled) {\n throw new Error('当前未开放投稿');\n }\n\n const errors = validateMikuSubmissionInput(input, mode);\n if (errors.length > 0) {\n throw new Error(errors.join(';'));\n }\n\n const now = new Date().toISOString();\n const next: MikuSubmission = {\n id: randomId('submission'),\n serialNo: serialNo(),\n contestId: input.contestId,\n authorId: input.authorId,\n authorNickname: input.authorNickname,\n title: input.title,\n type: input.type,\n description: input.description,\n tags: input.tags || [],\n content: input.content,\n voteCount: 0,\n status: 'pending',\n createdAt: now,\n updatedAt: now,\n };\n\n this.submissions.set(next.id, next);\n return next;\n }\n\n listSubmissions(filter?: MikuSubmissionFilter): MikuSubmission[] {\n const authorKeyword = filter?.authorKeyword?.trim().toLowerCase();\n const titleKeyword = filter?.titleKeyword?.trim().toLowerCase();\n\n return [...this.submissions.values()].filter((item) => {\n if (filter?.status && item.status !== filter.status) return false;\n if (filter?.type && item.type !== filter.type) return false;\n if (filter?.authorId && item.authorId !== filter.authorId) return false;\n if (authorKeyword && !item.authorNickname.toLowerCase().includes(authorKeyword)) return false;\n if (titleKeyword && !item.title.toLowerCase().includes(titleKeyword)) return false;\n return true;\n });\n }\n\n getSubmission(submissionId: string): MikuSubmission | null {\n return this.submissions.get(submissionId) || null;\n }\n\n reviewSubmission(input: ReviewMikuSubmissionInput): MikuSubmission {\n const current = this.submissions.get(input.submissionId);\n if (!current) throw new Error('投稿不存在');\n\n if (input.action === 'reject' && !input.rejectReason?.trim()) {\n throw new Error('驳回需填写原因');\n }\n\n const reviewed: MikuSubmission = {\n ...current,\n status: input.action === 'approve' ? 'approved' : 'rejected',\n rejectReason: input.action === 'reject' ? input.rejectReason?.trim() : undefined,\n reviewedAt: new Date().toISOString(),\n updatedAt: new Date().toISOString(),\n };\n\n this.submissions.set(reviewed.id, reviewed);\n return reviewed;\n }\n\n vote(input: VoteMikuSubmissionInput): MikuSubmission {\n if (!this.contest.toggles.votingEnabled) {\n throw new Error('当前未开放投票');\n }\n\n const restriction = this.voterRestrictions.get(input.voterId);\n if (restriction?.banned) {\n throw new Error('当前账号已被限制投票');\n }\n\n const target = this.submissions.get(input.submissionId);\n if (!target) throw new Error('作品不存在');\n if (target.status !== 'approved') throw new Error('仅可对已过审作品投票');\n\n const dayKey = toVoteDayKey();\n const eligible = checkVoteEligibility({\n existingVotes: this.votes,\n submissionId: input.submissionId,\n voterId: input.voterId,\n dayKey,\n rules: this.contest.votingRules,\n });\n\n if (!eligible.ok) {\n throw new Error(eligible.reason || '投票失败');\n }\n\n const vote: MikuVoteRecord = {\n id: randomId('vote'),\n contestId: input.contestId,\n submissionId: input.submissionId,\n voterId: input.voterId,\n votedAt: new Date().toISOString(),\n dayKey,\n deviceId: input.deviceId,\n ip: input.ip,\n };\n\n this.votes.push(vote);\n\n const updated: MikuSubmission = {\n ...target,\n voteCount: target.voteCount + 1,\n updatedAt: new Date().toISOString(),\n };\n this.submissions.set(updated.id, updated);\n\n return updated;\n }\n\n getVoterRestriction(voterId: string): MikuVoterRestriction | null {\n return this.voterRestrictions.get(voterId) || null;\n }\n\n setVoterRestriction(input: SetMikuVoterRestrictionInput): MikuVoterRestriction {\n const next: MikuVoterRestriction = {\n voterId: input.voterId,\n banned: input.banned,\n reason: input.reason,\n operatorId: input.operatorId,\n updatedAt: new Date().toISOString(),\n };\n\n this.voterRestrictions.set(input.voterId, next);\n return next;\n }\n\n resetVotes(input: ResetMikuVotesInput): { removedVotes: number; affectedSubmissions: string[] } {\n if (!input.submissionId && !input.voterId) {\n throw new Error('submissionId 与 voterId 至少提供一个');\n }\n\n const before = this.votes.length;\n const affected = new Set<string>();\n const remained = this.votes.filter((vote) => {\n const matchSubmission = input.submissionId ? vote.submissionId === input.submissionId : true;\n const matchVoter = input.voterId ? vote.voterId === input.voterId : true;\n const shouldRemove = matchSubmission && matchVoter;\n if (shouldRemove) affected.add(vote.submissionId);\n return !shouldRemove;\n });\n\n this.votes.length = 0;\n this.votes.push(...remained);\n this.recalculateVoteCounts();\n\n return {\n removedVotes: before - remained.length,\n affectedSubmissions: [...affected],\n };\n }\n\n listAnnouncements(contestId?: string): MikuAnnouncement[] {\n const all = [...this.announcements.values()];\n return contestId ? all.filter((item) => item.contestId === contestId) : all;\n }\n\n publishAnnouncement(input: CreateMikuAnnouncementInput): MikuAnnouncement {\n const now = new Date().toISOString();\n const announcement: MikuAnnouncement = {\n id: randomId('notice'),\n contestId: input.contestId,\n title: input.title,\n content: input.content,\n type: input.type,\n createdBy: input.createdBy,\n createdAt: now,\n updatedAt: now,\n };\n\n this.announcements.set(announcement.id, announcement);\n return announcement;\n }\n\n getLeaderboard(limit = 10): MikuLeaderboardItem[] {\n const ranked = sortByVotesDesc(this.listSubmissions({ status: 'approved' })).slice(0, limit);\n return ranked.map((item, index) => ({\n submissionId: item.id,\n title: item.title,\n authorNickname: item.authorNickname,\n voteCount: item.voteCount,\n rank: index + 1,\n }));\n }\n\n getSnapshot(): MikuContestStateSnapshot {\n return {\n contest: this.contest,\n submissions: this.listSubmissions(),\n announcements: this.listAnnouncements(),\n leaderboard: this.getLeaderboard(),\n };\n }\n\n getSubmissionExportRows(filter?: MikuSubmissionFilter): MikuSubmissionExportRow[] {\n return this.listSubmissions(filter).map((item) => ({\n 投稿编号: item.serialNo,\n 投稿ID: item.id,\n 赛事ID: item.contestId,\n 作者ID: item.authorId,\n 作者昵称: item.authorNickname,\n 作品名称: item.title,\n 作品类型: item.type,\n 简介: item.description,\n 标签: item.tags.join(','),\n 审核状态: item.status,\n 驳回原因: item.rejectReason || '',\n 票数: item.voteCount,\n 提交时间: item.createdAt,\n 更新时间: item.updatedAt,\n }));\n }\n\n exportSubmissionExcel(filter?: MikuSubmissionFilter): Uint8Array {\n const rows = this.getSubmissionExportRows(filter);\n const workbook = XLSX.utils.book_new();\n const worksheet = XLSX.utils.json_to_sheet(rows);\n XLSX.utils.book_append_sheet(workbook, worksheet, 'submissions');\n return XLSX.write(workbook, { bookType: 'xlsx', type: 'buffer' }) as Uint8Array;\n }\n\n private recalculateVoteCounts(): void {\n const counts = new Map<string, number>();\n for (const vote of this.votes) {\n counts.set(vote.submissionId, (counts.get(vote.submissionId) || 0) + 1);\n }\n\n for (const [id, submission] of this.submissions.entries()) {\n const nextCount = counts.get(id) || 0;\n if (submission.voteCount === nextCount) continue;\n this.submissions.set(id, {\n ...submission,\n voteCount: nextCount,\n updatedAt: new Date().toISOString(),\n });\n }\n }\n\n exportPersistenceState(): MikuContestPersistedState {\n return {\n contest: this.contest,\n submissions: [...this.submissions.values()],\n votes: [...this.votes],\n announcements: [...this.announcements.values()],\n voterRestrictions: [...this.voterRestrictions.values()],\n updatedAt: new Date().toISOString(),\n };\n }\n\n importPersistenceState(state: MikuContestPersistedState): void {\n this.contest = state.contest;\n this.submissions.clear();\n this.announcements.clear();\n this.voterRestrictions.clear();\n this.votes.length = 0;\n\n for (const item of state.submissions) {\n this.submissions.set(item.id, item);\n }\n for (const item of state.announcements) {\n this.announcements.set(item.id, item);\n }\n for (const item of state.voterRestrictions) {\n this.voterRestrictions.set(item.voterId, item);\n }\n this.votes.push(...state.votes);\n }\n}\n\nexport const createMikuContestService = (options?: MikuContestServiceOptions): MikuContestService => {\n return new MikuContestService(options);\n};\n","import { integer, jsonb, pgTable, text, timestamp } from 'drizzle-orm/pg-core';\nimport type {\n MikuAnnouncement,\n MikuContestConfig,\n MikuSubmissionContent,\n MikuVoterRestriction,\n MikuVoteRecord,\n} from '../../types';\n\nexport const mikuContestConfigs = pgTable('miku_contest_configs', {\n contestId: text('contest_id').primaryKey(),\n config: jsonb('config').$type<MikuContestConfig>().notNull(),\n createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),\n updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),\n});\n\nexport const mikuContestSubmissions = pgTable('miku_contest_submissions', {\n id: text('id').primaryKey(),\n contestId: text('contest_id').notNull(),\n serialNo: text('serial_no').notNull(),\n authorId: text('author_id').notNull(),\n authorNickname: text('author_nickname').notNull(),\n title: text('title').notNull(),\n type: text('type').notNull(),\n description: text('description').notNull(),\n tags: jsonb('tags').$type<string[]>().notNull(),\n content: jsonb('content').$type<MikuSubmissionContent>().notNull(),\n voteCount: integer('vote_count').notNull().default(0),\n status: text('status').notNull(),\n rejectReason: text('reject_reason'),\n createdAt: timestamp('created_at', { withTimezone: true }).notNull(),\n reviewedAt: timestamp('reviewed_at', { withTimezone: true }),\n updatedAt: timestamp('updated_at', { withTimezone: true }).notNull(),\n});\n\nexport const mikuContestVotes = pgTable('miku_contest_votes', {\n id: text('id').primaryKey(),\n contestId: text('contest_id').notNull(),\n submissionId: text('submission_id').notNull(),\n voterId: text('voter_id').notNull(),\n votedAt: text('voted_at').notNull(),\n dayKey: text('day_key').notNull(),\n deviceId: text('device_id'),\n ip: text('ip'),\n});\n\nexport const mikuContestNotices = pgTable('miku_contest_notices', {\n id: text('id').primaryKey(),\n contestId: text('contest_id').notNull(),\n title: text('title').notNull(),\n content: text('content').notNull(),\n type: text('type').notNull(),\n createdBy: text('created_by').notNull(),\n createdAt: text('created_at').notNull(),\n updatedAt: text('updated_at').notNull(),\n});\n\nexport const mikuContestVoterRestrictions = pgTable('miku_contest_voter_restrictions', {\n id: text('id').primaryKey(),\n contestId: text('contest_id').notNull(),\n data: jsonb('data').$type<MikuVoterRestriction>().notNull(),\n});\n\nexport type MikuContestVoteRow = typeof mikuContestVotes.$inferSelect & MikuVoteRecord;\nexport type MikuContestNoticeRow = typeof mikuContestNotices.$inferSelect & MikuAnnouncement;\n","import { useMemo, useState } from 'react';\nimport { createMikuContestService, type MikuContestServiceOptions } from '../../server';\n\nexport const useMikuContest = (options?: MikuContestServiceOptions) => {\n const [service] = useState(() => createMikuContestService(options));\n const [version, setVersion] = useState(0);\n\n const refresh = () => setVersion((value) => value + 1);\n\n const snapshot = useMemo(() => {\n void version;\n return service.getSnapshot();\n }, [service, version]);\n\n return {\n service,\n snapshot,\n refresh,\n };\n};\n","import React, { useMemo, useState } from 'react';\nimport { useMikuContest } from '../../../logic';\nimport type { MikuWorkType } from '../../../types';\n\nconst MikuContestMiniappPage: React.FC = () => {\n const { service, snapshot, refresh } = useMikuContest();\n\n const [tab, setTab] = useState<'vote' | 'submit'>('vote');\n const [voterId, setVoterId] = useState('miniapp-voter');\n const [authorId, setAuthorId] = useState('miniapp-author');\n const [authorNickname, setAuthorNickname] = useState('小程序画师');\n const [title, setTitle] = useState('');\n const [desc, setDesc] = useState('');\n const [type, setType] = useState<MikuWorkType>('visual');\n const [error, setError] = useState<string | null>(null);\n\n const approvedWorks = useMemo(() => {\n return snapshot.submissions.filter((item) => item.status === 'approved');\n }, [snapshot.submissions]);\n\n const vote = (submissionId: string) => {\n try {\n service.vote({\n contestId: snapshot.contest.id,\n submissionId,\n voterId,\n });\n refresh();\n setError(null);\n } catch (e) {\n setError((e as Error).message);\n }\n };\n\n const submit = () => {\n try {\n service.createSubmission(\n {\n contestId: snapshot.contest.id,\n authorId,\n authorNickname,\n title,\n description: desc,\n type,\n content: {},\n },\n 'miniapp',\n );\n setTitle('');\n setDesc('');\n refresh();\n setError(null);\n } catch (e) {\n setError((e as Error).message);\n }\n };\n\n return (\n <div>\n <h3>{snapshot.contest.name}</h3>\n <p>小程序端示例页面</p>\n <button onClick={() => setTab('vote')}>观众投票</button>\n <button onClick={() => setTab('submit')}>画师投稿</button>\n\n {error ? <p style={{ color: 'crimson' }}>错误:{error}</p> : null}\n\n {tab === 'vote' ? (\n <div>\n <input value={voterId} onChange={(e) => setVoterId(e.target.value)} placeholder=\"voterId\" />\n <ul>\n {approvedWorks.map((item) => (\n <li key={item.id}>\n {item.title}({item.voteCount}票)\n <button onClick={() => vote(item.id)}>投票</button>\n </li>\n ))}\n </ul>\n </div>\n ) : null}\n\n {tab === 'submit' ? (\n <div>\n <input value={authorId} onChange={(e) => setAuthorId(e.target.value)} placeholder=\"authorId\" />\n <input value={authorNickname} onChange={(e) => setAuthorNickname(e.target.value)} placeholder=\"作者昵称\" />\n <input value={title} onChange={(e) => setTitle(e.target.value)} placeholder=\"作品标题\" />\n <input value={desc} onChange={(e) => setDesc(e.target.value)} placeholder=\"作品简介\" />\n <select value={type} onChange={(e) => setType(e.target.value as MikuWorkType)}>\n <option value=\"visual\">visual</option>\n <option value=\"video\">video</option>\n <option value=\"text\">text</option>\n <option value=\"audio\">audio</option>\n </select>\n <button onClick={submit}>提交</button>\n </div>\n ) : null}\n </div>\n );\n};\n\nexport default MikuContestMiniappPage;\n"]}
|
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var React4 = require('react');
|
|
4
|
+
|
|
5
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
6
|
+
|
|
7
|
+
var React4__default = /*#__PURE__*/_interopDefault(React4);
|
|
8
|
+
|
|
9
|
+
// src/mikuContest/ui/web/components/MikuContestDashboard.tsx
|
|
10
|
+
var MikuContestDashboard = ({ snapshot }) => {
|
|
11
|
+
return /* @__PURE__ */ React4__default.default.createElement("div", null, /* @__PURE__ */ React4__default.default.createElement("h2", null, snapshot.contest.name), /* @__PURE__ */ React4__default.default.createElement("p", null, snapshot.contest.theme), /* @__PURE__ */ React4__default.default.createElement("p", null, "\u6295\u7A3F\u6570\uFF1A", snapshot.submissions.length), /* @__PURE__ */ React4__default.default.createElement("p", null, "\u516C\u544A\u6570\uFF1A", snapshot.announcements.length), /* @__PURE__ */ React4__default.default.createElement("ul", null, snapshot.leaderboard.map((item) => /* @__PURE__ */ React4__default.default.createElement("li", { key: item.submissionId }, "#", item.rank, " ", item.title, " - ", item.voteCount, "\u7968"))));
|
|
12
|
+
};
|
|
13
|
+
var MikuContestDashboard_default = MikuContestDashboard;
|
|
14
|
+
|
|
15
|
+
// src/mikuContest/service/api/client.ts
|
|
16
|
+
var toQueryString = (filter) => {
|
|
17
|
+
if (!filter) return "";
|
|
18
|
+
const params = new URLSearchParams();
|
|
19
|
+
if (filter.status) params.set("status", filter.status);
|
|
20
|
+
if (filter.type) params.set("type", filter.type);
|
|
21
|
+
if (filter.authorId) params.set("authorId", filter.authorId);
|
|
22
|
+
if (filter.authorKeyword) params.set("authorKeyword", filter.authorKeyword);
|
|
23
|
+
if (filter.titleKeyword) params.set("titleKeyword", filter.titleKeyword);
|
|
24
|
+
const query = params.toString();
|
|
25
|
+
return query ? `?${query}` : "";
|
|
26
|
+
};
|
|
27
|
+
var unwrap = (result) => {
|
|
28
|
+
if (!result.success || result.data === void 0) {
|
|
29
|
+
throw new Error(result.error || "\u8BF7\u6C42\u5931\u8D25");
|
|
30
|
+
}
|
|
31
|
+
return result.data;
|
|
32
|
+
};
|
|
33
|
+
var createMikuContestApiClient = (basePath, requester) => {
|
|
34
|
+
return {
|
|
35
|
+
async getSnapshot() {
|
|
36
|
+
const result = await requester(`${basePath}/contest`, { method: "GET" });
|
|
37
|
+
return unwrap(result);
|
|
38
|
+
},
|
|
39
|
+
async updateContestConfig(patch) {
|
|
40
|
+
const result = await requester(`${basePath}/contest`, {
|
|
41
|
+
method: "PATCH",
|
|
42
|
+
body: patch
|
|
43
|
+
});
|
|
44
|
+
return unwrap(result);
|
|
45
|
+
},
|
|
46
|
+
async createSubmission(input, mode = "web") {
|
|
47
|
+
const result = await requester(`${basePath}/submissions`, {
|
|
48
|
+
method: "POST",
|
|
49
|
+
body: { payload: input, mode }
|
|
50
|
+
});
|
|
51
|
+
return unwrap(result);
|
|
52
|
+
},
|
|
53
|
+
async listSubmissions(filter) {
|
|
54
|
+
const result = await requester(
|
|
55
|
+
`${basePath}/submissions${toQueryString(filter)}`,
|
|
56
|
+
{ method: "GET" }
|
|
57
|
+
);
|
|
58
|
+
return unwrap(result);
|
|
59
|
+
},
|
|
60
|
+
async reviewSubmission(input) {
|
|
61
|
+
const result = await requester(`${basePath}/submissions/review`, {
|
|
62
|
+
method: "POST",
|
|
63
|
+
body: input
|
|
64
|
+
});
|
|
65
|
+
return unwrap(result);
|
|
66
|
+
},
|
|
67
|
+
async vote(input) {
|
|
68
|
+
const result = await requester(`${basePath}/votes`, {
|
|
69
|
+
method: "POST",
|
|
70
|
+
body: input
|
|
71
|
+
});
|
|
72
|
+
return unwrap(result);
|
|
73
|
+
},
|
|
74
|
+
async setVoterRestriction(input) {
|
|
75
|
+
const result = await requester(`${basePath}/admin/voter-restrictions`, {
|
|
76
|
+
method: "POST",
|
|
77
|
+
body: input
|
|
78
|
+
});
|
|
79
|
+
return unwrap(result);
|
|
80
|
+
},
|
|
81
|
+
async resetVotes(input) {
|
|
82
|
+
const result = await requester(
|
|
83
|
+
`${basePath}/admin/votes/reset`,
|
|
84
|
+
{
|
|
85
|
+
method: "POST",
|
|
86
|
+
body: input
|
|
87
|
+
}
|
|
88
|
+
);
|
|
89
|
+
return unwrap(result);
|
|
90
|
+
},
|
|
91
|
+
async exportSubmissions(filter) {
|
|
92
|
+
const response = await fetch(`${basePath}/admin/submissions/export${toQueryString(filter)}`);
|
|
93
|
+
if (!response.ok) {
|
|
94
|
+
throw new Error(`\u5BFC\u51FA\u5931\u8D25: ${response.status}`);
|
|
95
|
+
}
|
|
96
|
+
return response.arrayBuffer();
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
// src/mikuContest/service/web/client.ts
|
|
102
|
+
var defaultRequester = (options) => {
|
|
103
|
+
const baseUrl = options.baseUrl || "";
|
|
104
|
+
const commonHeaders = options.headers || {};
|
|
105
|
+
return async (url, requestOptions) => {
|
|
106
|
+
const response = await fetch(`${baseUrl}${url}`, {
|
|
107
|
+
method: requestOptions?.method || "GET",
|
|
108
|
+
headers: {
|
|
109
|
+
"Content-Type": "application/json",
|
|
110
|
+
...commonHeaders
|
|
111
|
+
},
|
|
112
|
+
body: requestOptions?.body ? JSON.stringify(requestOptions.body) : void 0
|
|
113
|
+
});
|
|
114
|
+
const json = await response.json();
|
|
115
|
+
return json;
|
|
116
|
+
};
|
|
117
|
+
};
|
|
118
|
+
var createMikuContestWebClient = (options = {}) => {
|
|
119
|
+
const basePath = options.basePath || "/api/miku-contest";
|
|
120
|
+
return createMikuContestApiClient(basePath, defaultRequester(options));
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
// src/mikuContest/ui/web/pages/MikuContestAudiencePage.tsx
|
|
124
|
+
var MikuContestAudiencePage = ({
|
|
125
|
+
client,
|
|
126
|
+
voterId,
|
|
127
|
+
title = "\u89C2\u4F17\u6295\u7968\u533A"
|
|
128
|
+
}) => {
|
|
129
|
+
const api = React4.useMemo(() => client || createMikuContestWebClient(), [client]);
|
|
130
|
+
const [snapshot, setSnapshot] = React4.useState(null);
|
|
131
|
+
const [loading, setLoading] = React4.useState(false);
|
|
132
|
+
const [error, setError] = React4.useState(null);
|
|
133
|
+
const approvedWorks = React4.useMemo(() => {
|
|
134
|
+
if (!snapshot) return [];
|
|
135
|
+
return snapshot.submissions.filter((item) => item.status === "approved");
|
|
136
|
+
}, [snapshot]);
|
|
137
|
+
const loadSnapshot = async () => {
|
|
138
|
+
setLoading(true);
|
|
139
|
+
setError(null);
|
|
140
|
+
try {
|
|
141
|
+
const data = await api.getSnapshot();
|
|
142
|
+
setSnapshot(data);
|
|
143
|
+
} catch (e) {
|
|
144
|
+
setError(e.message);
|
|
145
|
+
} finally {
|
|
146
|
+
setLoading(false);
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
React4.useEffect(() => {
|
|
150
|
+
void loadSnapshot();
|
|
151
|
+
}, []);
|
|
152
|
+
const handleVote = async (submission) => {
|
|
153
|
+
if (!snapshot) return;
|
|
154
|
+
try {
|
|
155
|
+
await api.vote({
|
|
156
|
+
contestId: snapshot.contest.id,
|
|
157
|
+
submissionId: submission.id,
|
|
158
|
+
voterId
|
|
159
|
+
});
|
|
160
|
+
await loadSnapshot();
|
|
161
|
+
} catch (e) {
|
|
162
|
+
setError(e.message);
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
return /* @__PURE__ */ React4__default.default.createElement("section", null, /* @__PURE__ */ React4__default.default.createElement("h2", null, title), /* @__PURE__ */ React4__default.default.createElement("button", { onClick: () => void loadSnapshot(), disabled: loading }, loading ? "\u5237\u65B0\u4E2D..." : "\u5237\u65B0\u6570\u636E"), error ? /* @__PURE__ */ React4__default.default.createElement("p", { style: { color: "crimson" } }, "\u9519\u8BEF\uFF1A", error) : null, !snapshot ? null : /* @__PURE__ */ React4__default.default.createElement(React4__default.default.Fragment, null, /* @__PURE__ */ React4__default.default.createElement("p", null, "\u8D5B\u4E8B\uFF1A", snapshot.contest.name, "\uFF5C\u4E3B\u9898\uFF1A", snapshot.contest.theme), /* @__PURE__ */ React4__default.default.createElement("p", null, "\u5DF2\u8FC7\u5BA1\u4F5C\u54C1\uFF1A", approvedWorks.length, "\uFF5C\u6BCF\u65E5\u4E0A\u9650\uFF1A", snapshot.contest.votingRules.maxVotesPerDay), /* @__PURE__ */ React4__default.default.createElement("ul", null, approvedWorks.map((work) => /* @__PURE__ */ React4__default.default.createElement("li", { key: work.id }, /* @__PURE__ */ React4__default.default.createElement("strong", null, work.title), "\uFF08", work.authorNickname, "\uFF09- \u5F53\u524D ", work.voteCount, " \u7968", " ", /* @__PURE__ */ React4__default.default.createElement("button", { onClick: () => void handleVote(work) }, "\u6295\u7968"))))));
|
|
166
|
+
};
|
|
167
|
+
var MikuContestAudiencePage_default = MikuContestAudiencePage;
|
|
168
|
+
var workTypes = ["visual", "video", "text", "audio"];
|
|
169
|
+
var MikuContestArtistPage = ({
|
|
170
|
+
client,
|
|
171
|
+
authorId,
|
|
172
|
+
authorNickname,
|
|
173
|
+
title = "\u753B\u5E08\u6295\u7A3F\u533A"
|
|
174
|
+
}) => {
|
|
175
|
+
const api = React4.useMemo(() => client || createMikuContestWebClient(), [client]);
|
|
176
|
+
const [snapshot, setSnapshot] = React4.useState(null);
|
|
177
|
+
const [mySubmissions, setMySubmissions] = React4.useState([]);
|
|
178
|
+
const [submitting, setSubmitting] = React4.useState(false);
|
|
179
|
+
const [loading, setLoading] = React4.useState(false);
|
|
180
|
+
const [error, setError] = React4.useState(null);
|
|
181
|
+
const [titleInput, setTitleInput] = React4.useState("");
|
|
182
|
+
const [descInput, setDescInput] = React4.useState("");
|
|
183
|
+
const [coverImage, setCoverImage] = React4.useState("");
|
|
184
|
+
const [workType, setWorkType] = React4.useState("visual");
|
|
185
|
+
const loadData = async () => {
|
|
186
|
+
setLoading(true);
|
|
187
|
+
setError(null);
|
|
188
|
+
try {
|
|
189
|
+
const [contest, mine] = await Promise.all([
|
|
190
|
+
api.getSnapshot(),
|
|
191
|
+
api.listSubmissions({ authorId })
|
|
192
|
+
]);
|
|
193
|
+
setSnapshot(contest);
|
|
194
|
+
setMySubmissions(mine);
|
|
195
|
+
} catch (e) {
|
|
196
|
+
setError(e.message);
|
|
197
|
+
} finally {
|
|
198
|
+
setLoading(false);
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
React4.useEffect(() => {
|
|
202
|
+
void loadData();
|
|
203
|
+
}, []);
|
|
204
|
+
const submitWork = async () => {
|
|
205
|
+
if (!snapshot) return;
|
|
206
|
+
const payload = {
|
|
207
|
+
contestId: snapshot.contest.id,
|
|
208
|
+
authorId,
|
|
209
|
+
authorNickname,
|
|
210
|
+
title: titleInput,
|
|
211
|
+
description: descInput,
|
|
212
|
+
type: workType,
|
|
213
|
+
tags: ["web"],
|
|
214
|
+
content: {
|
|
215
|
+
coverImage,
|
|
216
|
+
images: coverImage ? [coverImage] : void 0
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
setSubmitting(true);
|
|
220
|
+
setError(null);
|
|
221
|
+
try {
|
|
222
|
+
await api.createSubmission(payload, "web");
|
|
223
|
+
setTitleInput("");
|
|
224
|
+
setDescInput("");
|
|
225
|
+
setCoverImage("");
|
|
226
|
+
await loadData();
|
|
227
|
+
} catch (e) {
|
|
228
|
+
setError(e.message);
|
|
229
|
+
} finally {
|
|
230
|
+
setSubmitting(false);
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
return /* @__PURE__ */ React4__default.default.createElement("section", null, /* @__PURE__ */ React4__default.default.createElement("h2", null, title), /* @__PURE__ */ React4__default.default.createElement("button", { onClick: () => void loadData(), disabled: loading }, loading ? "\u5237\u65B0\u4E2D..." : "\u5237\u65B0\u6570\u636E"), error ? /* @__PURE__ */ React4__default.default.createElement("p", { style: { color: "crimson" } }, "\u9519\u8BEF\uFF1A", error) : null, /* @__PURE__ */ React4__default.default.createElement("div", null, /* @__PURE__ */ React4__default.default.createElement("h3", null, "\u65B0\u5EFA\u6295\u7A3F"), /* @__PURE__ */ React4__default.default.createElement("input", { value: titleInput, onChange: (e) => setTitleInput(e.target.value), placeholder: "\u4F5C\u54C1\u6807\u9898" }), /* @__PURE__ */ React4__default.default.createElement("br", null), /* @__PURE__ */ React4__default.default.createElement("textarea", { value: descInput, onChange: (e) => setDescInput(e.target.value), placeholder: "\u4F5C\u54C1\u7B80\u4ECB" }), /* @__PURE__ */ React4__default.default.createElement("br", null), /* @__PURE__ */ React4__default.default.createElement("input", { value: coverImage, onChange: (e) => setCoverImage(e.target.value), placeholder: "\u5C01\u9762 URL" }), /* @__PURE__ */ React4__default.default.createElement("br", null), /* @__PURE__ */ React4__default.default.createElement("select", { value: workType, onChange: (e) => setWorkType(e.target.value) }, workTypes.map((item) => /* @__PURE__ */ React4__default.default.createElement("option", { value: item, key: item }, item))), /* @__PURE__ */ React4__default.default.createElement("button", { onClick: () => void submitWork(), disabled: submitting || !snapshot }, submitting ? "\u63D0\u4EA4\u4E2D..." : "\u63D0\u4EA4\u7A3F\u4EF6")), /* @__PURE__ */ React4__default.default.createElement("div", null, /* @__PURE__ */ React4__default.default.createElement("h3", null, "\u6211\u7684\u6295\u7A3F\uFF08", mySubmissions.length, "\uFF09"), /* @__PURE__ */ React4__default.default.createElement("ul", null, mySubmissions.map((item) => /* @__PURE__ */ React4__default.default.createElement("li", { key: item.id }, item.title, "\uFF5C\u72B6\u6001\uFF1A", item.status, "\uFF5C\u7968\u6570\uFF1A", item.voteCount, item.rejectReason ? `\uFF5C\u9A73\u56DE\uFF1A${item.rejectReason}` : "")))));
|
|
234
|
+
};
|
|
235
|
+
var MikuContestArtistPage_default = MikuContestArtistPage;
|
|
236
|
+
var MikuContestAdminPage = ({
|
|
237
|
+
client,
|
|
238
|
+
adminId,
|
|
239
|
+
title = "\u7BA1\u7406\u5458\u9762\u677F"
|
|
240
|
+
}) => {
|
|
241
|
+
const api = React4.useMemo(() => client || createMikuContestWebClient(), [client]);
|
|
242
|
+
const [snapshot, setSnapshot] = React4.useState(null);
|
|
243
|
+
const [submissions, setSubmissions] = React4.useState([]);
|
|
244
|
+
const [loading, setLoading] = React4.useState(false);
|
|
245
|
+
const [error, setError] = React4.useState(null);
|
|
246
|
+
const [voterId, setVoterId] = React4.useState("");
|
|
247
|
+
const loadData = async () => {
|
|
248
|
+
setLoading(true);
|
|
249
|
+
setError(null);
|
|
250
|
+
try {
|
|
251
|
+
const [contest, list] = await Promise.all([api.getSnapshot(), api.listSubmissions()]);
|
|
252
|
+
setSnapshot(contest);
|
|
253
|
+
setSubmissions(list);
|
|
254
|
+
} catch (e) {
|
|
255
|
+
setError(e.message);
|
|
256
|
+
} finally {
|
|
257
|
+
setLoading(false);
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
React4.useEffect(() => {
|
|
261
|
+
void loadData();
|
|
262
|
+
}, []);
|
|
263
|
+
const review = async (item, action) => {
|
|
264
|
+
try {
|
|
265
|
+
await api.reviewSubmission({
|
|
266
|
+
submissionId: item.id,
|
|
267
|
+
reviewerId: adminId,
|
|
268
|
+
action,
|
|
269
|
+
rejectReason: action === "reject" ? "\u7BA1\u7406\u5458\u9A73\u56DE" : void 0
|
|
270
|
+
});
|
|
271
|
+
await loadData();
|
|
272
|
+
} catch (e) {
|
|
273
|
+
setError(e.message);
|
|
274
|
+
}
|
|
275
|
+
};
|
|
276
|
+
const toggleVoting = async (enabled) => {
|
|
277
|
+
if (!snapshot) return;
|
|
278
|
+
try {
|
|
279
|
+
await api.updateContestConfig({
|
|
280
|
+
toggles: {
|
|
281
|
+
...snapshot.contest.toggles,
|
|
282
|
+
votingEnabled: enabled
|
|
283
|
+
}
|
|
284
|
+
});
|
|
285
|
+
await loadData();
|
|
286
|
+
} catch (e) {
|
|
287
|
+
setError(e.message);
|
|
288
|
+
}
|
|
289
|
+
};
|
|
290
|
+
const setRestriction = async (banned) => {
|
|
291
|
+
if (!snapshot || !voterId.trim()) return;
|
|
292
|
+
try {
|
|
293
|
+
await api.setVoterRestriction({
|
|
294
|
+
voterId: voterId.trim(),
|
|
295
|
+
banned,
|
|
296
|
+
reason: banned ? "\u7BA1\u7406\u5458\u624B\u52A8\u5C01\u7981" : "\u7BA1\u7406\u5458\u89E3\u9664\u5C01\u7981",
|
|
297
|
+
operatorId: adminId
|
|
298
|
+
});
|
|
299
|
+
setVoterId("");
|
|
300
|
+
} catch (e) {
|
|
301
|
+
setError(e.message);
|
|
302
|
+
}
|
|
303
|
+
};
|
|
304
|
+
const resetVotesByVoter = async () => {
|
|
305
|
+
if (!voterId.trim()) return;
|
|
306
|
+
try {
|
|
307
|
+
await api.resetVotes({ voterId: voterId.trim() });
|
|
308
|
+
setVoterId("");
|
|
309
|
+
await loadData();
|
|
310
|
+
} catch (e) {
|
|
311
|
+
setError(e.message);
|
|
312
|
+
}
|
|
313
|
+
};
|
|
314
|
+
const exportExcel = async () => {
|
|
315
|
+
try {
|
|
316
|
+
const data = await api.exportSubmissions();
|
|
317
|
+
const blob = new Blob([data], {
|
|
318
|
+
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
|
319
|
+
});
|
|
320
|
+
const url = URL.createObjectURL(blob);
|
|
321
|
+
const a = document.createElement("a");
|
|
322
|
+
a.href = url;
|
|
323
|
+
a.download = "miku-submissions.xlsx";
|
|
324
|
+
a.click();
|
|
325
|
+
URL.revokeObjectURL(url);
|
|
326
|
+
} catch (e) {
|
|
327
|
+
setError(e.message);
|
|
328
|
+
}
|
|
329
|
+
};
|
|
330
|
+
return /* @__PURE__ */ React4__default.default.createElement("section", null, /* @__PURE__ */ React4__default.default.createElement("h2", null, title), /* @__PURE__ */ React4__default.default.createElement("button", { onClick: () => void loadData(), disabled: loading }, loading ? "\u5237\u65B0\u4E2D..." : "\u5237\u65B0\u6570\u636E"), error ? /* @__PURE__ */ React4__default.default.createElement("p", { style: { color: "crimson" } }, "\u9519\u8BEF\uFF1A", error) : null, /* @__PURE__ */ React4__default.default.createElement("div", null, /* @__PURE__ */ React4__default.default.createElement("h3", null, "\u8D5B\u4E8B\u5F00\u5173"), /* @__PURE__ */ React4__default.default.createElement("button", { onClick: () => void toggleVoting(true), disabled: !snapshot }, "\u5F00\u542F\u6295\u7968"), /* @__PURE__ */ React4__default.default.createElement("button", { onClick: () => void toggleVoting(false), disabled: !snapshot }, "\u5173\u95ED\u6295\u7968")), /* @__PURE__ */ React4__default.default.createElement("div", null, /* @__PURE__ */ React4__default.default.createElement("h3", null, "\u6295\u7A3F\u5BA1\u6838\uFF08", submissions.length, "\uFF09"), /* @__PURE__ */ React4__default.default.createElement("ul", null, submissions.map((item) => /* @__PURE__ */ React4__default.default.createElement("li", { key: item.id }, /* @__PURE__ */ React4__default.default.createElement("strong", null, item.title), "\uFF5C\u4F5C\u8005\uFF1A", item.authorNickname, "\uFF5C\u72B6\u6001\uFF1A", item.status, "\uFF5C\u7968\u6570\uFF1A", item.voteCount, item.status === "pending" ? /* @__PURE__ */ React4__default.default.createElement(React4__default.default.Fragment, null, " ", /* @__PURE__ */ React4__default.default.createElement("button", { onClick: () => void review(item, "approve") }, "\u901A\u8FC7"), /* @__PURE__ */ React4__default.default.createElement("button", { onClick: () => void review(item, "reject") }, "\u9A73\u56DE")) : null)))), /* @__PURE__ */ React4__default.default.createElement("div", null, /* @__PURE__ */ React4__default.default.createElement("h3", null, "\u6295\u7968\u98CE\u63A7"), /* @__PURE__ */ React4__default.default.createElement("input", { value: voterId, onChange: (e) => setVoterId(e.target.value), placeholder: "voterId" }), /* @__PURE__ */ React4__default.default.createElement("button", { onClick: () => void setRestriction(true), disabled: !snapshot }, "\u5C01\u7981\u6295\u7968"), /* @__PURE__ */ React4__default.default.createElement("button", { onClick: () => void setRestriction(false), disabled: !snapshot }, "\u89E3\u9664\u5C01\u7981"), /* @__PURE__ */ React4__default.default.createElement("button", { onClick: () => void resetVotesByVoter() }, "\u6E05\u96F6\u8BE5\u7528\u6237\u7968\u6570")), /* @__PURE__ */ React4__default.default.createElement("div", null, /* @__PURE__ */ React4__default.default.createElement("h3", null, "\u5BFC\u51FA"), /* @__PURE__ */ React4__default.default.createElement("button", { onClick: () => void exportExcel() }, "\u5BFC\u51FA\u6295\u7A3F Excel")));
|
|
331
|
+
};
|
|
332
|
+
var MikuContestAdminPage_default = MikuContestAdminPage;
|
|
333
|
+
|
|
334
|
+
// src/mikuContest/ui/web/pages/MikuContestPage.tsx
|
|
335
|
+
var MikuContestPage = ({
|
|
336
|
+
defaultView = "audience",
|
|
337
|
+
viewerVoterId = "viewer-demo",
|
|
338
|
+
artistId = "artist-demo",
|
|
339
|
+
artistNickname = "Demo \u753B\u5E08",
|
|
340
|
+
adminId = "admin-demo"
|
|
341
|
+
}) => {
|
|
342
|
+
const [view, setView] = React4.useState(defaultView);
|
|
343
|
+
return /* @__PURE__ */ React4__default.default.createElement("div", null, /* @__PURE__ */ React4__default.default.createElement("h1", null, "Miku Contest"), /* @__PURE__ */ React4__default.default.createElement("div", null, /* @__PURE__ */ React4__default.default.createElement("button", { onClick: () => setView("audience") }, "\u89C2\u4F17\u7AEF"), /* @__PURE__ */ React4__default.default.createElement("button", { onClick: () => setView("artist") }, "\u753B\u5E08\u7AEF"), /* @__PURE__ */ React4__default.default.createElement("button", { onClick: () => setView("admin") }, "\u7BA1\u7406\u5458\u7AEF")), view === "audience" ? /* @__PURE__ */ React4__default.default.createElement(MikuContestAudiencePage_default, { voterId: viewerVoterId }) : null, view === "artist" ? /* @__PURE__ */ React4__default.default.createElement(MikuContestArtistPage_default, { authorId: artistId, authorNickname: artistNickname }) : null, view === "admin" ? /* @__PURE__ */ React4__default.default.createElement(MikuContestAdminPage_default, { adminId }) : null);
|
|
344
|
+
};
|
|
345
|
+
var MikuContestPage_default = MikuContestPage;
|
|
346
|
+
|
|
347
|
+
exports.MikuContestAdminPage = MikuContestAdminPage_default;
|
|
348
|
+
exports.MikuContestArtistPage = MikuContestArtistPage_default;
|
|
349
|
+
exports.MikuContestAudiencePage = MikuContestAudiencePage_default;
|
|
350
|
+
exports.MikuContestDashboard = MikuContestDashboard_default;
|
|
351
|
+
exports.MikuContestPage = MikuContestPage_default;
|
|
352
|
+
//# sourceMappingURL=index.js.map
|
|
353
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/mikuContest/ui/web/components/MikuContestDashboard.tsx","../../../../src/mikuContest/service/api/client.ts","../../../../src/mikuContest/service/web/client.ts","../../../../src/mikuContest/ui/web/pages/MikuContestAudiencePage.tsx","../../../../src/mikuContest/ui/web/pages/MikuContestArtistPage.tsx","../../../../src/mikuContest/ui/web/pages/MikuContestAdminPage.tsx","../../../../src/mikuContest/ui/web/pages/MikuContestPage.tsx"],"names":["React","useMemo","useState","useEffect"],"mappings":"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","file":"index.js","sourcesContent":["import React from 'react';\nimport type { MikuContestStateSnapshot } from '../../../types';\n\nexport interface MikuContestDashboardProps {\n snapshot: MikuContestStateSnapshot;\n}\n\nconst MikuContestDashboard: React.FC<MikuContestDashboardProps> = ({ snapshot }) => {\n return (\n <div>\n <h2>{snapshot.contest.name}</h2>\n <p>{snapshot.contest.theme}</p>\n <p>投稿数:{snapshot.submissions.length}</p>\n <p>公告数:{snapshot.announcements.length}</p>\n <ul>\n {snapshot.leaderboard.map((item) => (\n <li key={item.submissionId}>\n #{item.rank} {item.title} - {item.voteCount}票\n </li>\n ))}\n </ul>\n </div>\n );\n};\n\nexport default MikuContestDashboard;\n","import type {\n CreateMikuSubmissionInput,\n MikuContestConfig,\n MikuContestStateSnapshot,\n MikuSubmission,\n MikuSubmissionFilter,\n MikuVoterRestriction,\n ResetMikuVotesInput,\n ReviewMikuSubmissionInput,\n SetMikuVoterRestrictionInput,\n VoteMikuSubmissionInput,\n} from '../../types';\n\nexport interface MikuContestApiClient {\n getSnapshot(): Promise<MikuContestStateSnapshot>;\n updateContestConfig(patch: Partial<MikuContestConfig>): Promise<MikuContestConfig>;\n createSubmission(input: CreateMikuSubmissionInput, mode?: 'web' | 'miniapp'): Promise<MikuSubmission>;\n listSubmissions(filter?: MikuSubmissionFilter): Promise<MikuSubmission[]>;\n reviewSubmission(input: ReviewMikuSubmissionInput): Promise<MikuSubmission>;\n vote(input: VoteMikuSubmissionInput): Promise<MikuSubmission>;\n setVoterRestriction(input: SetMikuVoterRestrictionInput): Promise<MikuVoterRestriction>;\n resetVotes(input: ResetMikuVotesInput): Promise<{ removedVotes: number; affectedSubmissions: string[] }>;\n exportSubmissions(filter?: MikuSubmissionFilter): Promise<ArrayBuffer>;\n}\n\nexport type HttpMethod = 'GET' | 'POST' | 'PATCH';\n\nexport interface Requester {\n <T>(url: string, options?: { method?: HttpMethod; body?: unknown }): Promise<T>;\n}\n\nconst toQueryString = (filter?: MikuSubmissionFilter): string => {\n if (!filter) return '';\n const params = new URLSearchParams();\n if (filter.status) params.set('status', filter.status);\n if (filter.type) params.set('type', filter.type);\n if (filter.authorId) params.set('authorId', filter.authorId);\n if (filter.authorKeyword) params.set('authorKeyword', filter.authorKeyword);\n if (filter.titleKeyword) params.set('titleKeyword', filter.titleKeyword);\n const query = params.toString();\n return query ? `?${query}` : '';\n};\n\ninterface ApiEnvelope<T> {\n success: boolean;\n data?: T;\n error?: string;\n}\n\nconst unwrap = <T>(result: ApiEnvelope<T>): T => {\n if (!result.success || result.data === undefined) {\n throw new Error(result.error || '请求失败');\n }\n return result.data;\n};\n\nexport const createMikuContestApiClient = (\n basePath: string,\n requester: Requester,\n): MikuContestApiClient => {\n return {\n async getSnapshot() {\n const result = await requester<ApiEnvelope<MikuContestStateSnapshot>>(`${basePath}/contest`, { method: 'GET' });\n return unwrap(result);\n },\n async updateContestConfig(patch) {\n const result = await requester<ApiEnvelope<MikuContestConfig>>(`${basePath}/contest`, {\n method: 'PATCH',\n body: patch,\n });\n return unwrap(result);\n },\n async createSubmission(input, mode = 'web') {\n const result = await requester<ApiEnvelope<MikuSubmission>>(`${basePath}/submissions`, {\n method: 'POST',\n body: { payload: input, mode },\n });\n return unwrap(result);\n },\n async listSubmissions(filter) {\n const result = await requester<ApiEnvelope<MikuSubmission[]>>(\n `${basePath}/submissions${toQueryString(filter)}`,\n { method: 'GET' },\n );\n return unwrap(result);\n },\n async reviewSubmission(input) {\n const result = await requester<ApiEnvelope<MikuSubmission>>(`${basePath}/submissions/review`, {\n method: 'POST',\n body: input,\n });\n return unwrap(result);\n },\n async vote(input) {\n const result = await requester<ApiEnvelope<MikuSubmission>>(`${basePath}/votes`, {\n method: 'POST',\n body: input,\n });\n return unwrap(result);\n },\n async setVoterRestriction(input) {\n const result = await requester<ApiEnvelope<MikuVoterRestriction>>(`${basePath}/admin/voter-restrictions`, {\n method: 'POST',\n body: input,\n });\n return unwrap(result);\n },\n async resetVotes(input) {\n const result = await requester<ApiEnvelope<{ removedVotes: number; affectedSubmissions: string[] }>>(\n `${basePath}/admin/votes/reset`,\n {\n method: 'POST',\n body: input,\n },\n );\n return unwrap(result);\n },\n async exportSubmissions(filter) {\n const response = await fetch(`${basePath}/admin/submissions/export${toQueryString(filter)}`);\n if (!response.ok) {\n throw new Error(`导出失败: ${response.status}`);\n }\n return response.arrayBuffer();\n },\n };\n};\n","import { createMikuContestApiClient, type Requester } from '../api';\n\nexport interface MikuContestWebClientOptions {\n baseUrl?: string;\n basePath?: string;\n headers?: Record<string, string>;\n}\n\nconst defaultRequester = (options: MikuContestWebClientOptions): Requester => {\n const baseUrl = options.baseUrl || '';\n const commonHeaders = options.headers || {};\n\n return async <T>(url: string, requestOptions?: { method?: 'GET' | 'POST' | 'PATCH'; body?: unknown }): Promise<T> => {\n const response = await fetch(`${baseUrl}${url}`, {\n method: requestOptions?.method || 'GET',\n headers: {\n 'Content-Type': 'application/json',\n ...commonHeaders,\n },\n body: requestOptions?.body ? JSON.stringify(requestOptions.body) : undefined,\n });\n\n const json = (await response.json()) as T;\n return json;\n };\n};\n\nexport const createMikuContestWebClient = (options: MikuContestWebClientOptions = {}) => {\n const basePath = options.basePath || '/api/miku-contest';\n return createMikuContestApiClient(basePath, defaultRequester(options));\n};\n","import React, { useEffect, useMemo, useState } from 'react';\nimport { createMikuContestWebClient } from '../../../service/web';\nimport type { MikuContestApiClient } from '../../../service/api';\nimport type { MikuContestStateSnapshot, MikuSubmission } from '../../../types';\n\nexport interface MikuContestAudiencePageProps {\n client?: Pick<MikuContestApiClient, 'getSnapshot' | 'vote'>;\n voterId: string;\n title?: string;\n}\n\nconst MikuContestAudiencePage: React.FC<MikuContestAudiencePageProps> = ({\n client,\n voterId,\n title = '观众投票区',\n}) => {\n const api = useMemo(() => client || createMikuContestWebClient(), [client]);\n\n const [snapshot, setSnapshot] = useState<MikuContestStateSnapshot | null>(null);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const approvedWorks = useMemo(() => {\n if (!snapshot) return [];\n return snapshot.submissions.filter((item) => item.status === 'approved');\n }, [snapshot]);\n\n const loadSnapshot = async () => {\n setLoading(true);\n setError(null);\n try {\n const data = await api.getSnapshot();\n setSnapshot(data);\n } catch (e) {\n setError((e as Error).message);\n } finally {\n setLoading(false);\n }\n };\n\n useEffect(() => {\n void loadSnapshot();\n }, []);\n\n const handleVote = async (submission: MikuSubmission) => {\n if (!snapshot) return;\n try {\n await api.vote({\n contestId: snapshot.contest.id,\n submissionId: submission.id,\n voterId,\n });\n await loadSnapshot();\n } catch (e) {\n setError((e as Error).message);\n }\n };\n\n return (\n <section>\n <h2>{title}</h2>\n <button onClick={() => void loadSnapshot()} disabled={loading}>\n {loading ? '刷新中...' : '刷新数据'}\n </button>\n {error ? <p style={{ color: 'crimson' }}>错误:{error}</p> : null}\n\n {!snapshot ? null : (\n <>\n <p>\n 赛事:{snapshot.contest.name}|主题:{snapshot.contest.theme}\n </p>\n <p>\n 已过审作品:{approvedWorks.length}|每日上限:{snapshot.contest.votingRules.maxVotesPerDay}\n </p>\n <ul>\n {approvedWorks.map((work) => (\n <li key={work.id}>\n <strong>{work.title}</strong>({work.authorNickname})- 当前 {work.voteCount} 票{' '}\n <button onClick={() => void handleVote(work)}>投票</button>\n </li>\n ))}\n </ul>\n </>\n )}\n </section>\n );\n};\n\nexport default MikuContestAudiencePage;\n","import React, { useEffect, useMemo, useState } from 'react';\nimport { createMikuContestWebClient } from '../../../service/web';\nimport type { MikuContestApiClient } from '../../../service/api';\nimport type { CreateMikuSubmissionInput, MikuContestStateSnapshot, MikuSubmission, MikuWorkType } from '../../../types';\n\nexport interface MikuContestArtistPageProps {\n client?: Pick<MikuContestApiClient, 'getSnapshot' | 'createSubmission' | 'listSubmissions'>;\n authorId: string;\n authorNickname: string;\n title?: string;\n}\n\nconst workTypes: MikuWorkType[] = ['visual', 'video', 'text', 'audio'];\n\nconst MikuContestArtistPage: React.FC<MikuContestArtistPageProps> = ({\n client,\n authorId,\n authorNickname,\n title = '画师投稿区',\n}) => {\n const api = useMemo(() => client || createMikuContestWebClient(), [client]);\n\n const [snapshot, setSnapshot] = useState<MikuContestStateSnapshot | null>(null);\n const [mySubmissions, setMySubmissions] = useState<MikuSubmission[]>([]);\n const [submitting, setSubmitting] = useState(false);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const [titleInput, setTitleInput] = useState('');\n const [descInput, setDescInput] = useState('');\n const [coverImage, setCoverImage] = useState('');\n const [workType, setWorkType] = useState<MikuWorkType>('visual');\n\n const loadData = async () => {\n setLoading(true);\n setError(null);\n try {\n const [contest, mine] = await Promise.all([\n api.getSnapshot(),\n api.listSubmissions({ authorId }),\n ]);\n setSnapshot(contest);\n setMySubmissions(mine);\n } catch (e) {\n setError((e as Error).message);\n } finally {\n setLoading(false);\n }\n };\n\n useEffect(() => {\n void loadData();\n }, []);\n\n const submitWork = async () => {\n if (!snapshot) return;\n const payload: CreateMikuSubmissionInput = {\n contestId: snapshot.contest.id,\n authorId,\n authorNickname,\n title: titleInput,\n description: descInput,\n type: workType,\n tags: ['web'],\n content: {\n coverImage,\n images: coverImage ? [coverImage] : undefined,\n },\n };\n\n setSubmitting(true);\n setError(null);\n try {\n await api.createSubmission(payload, 'web');\n setTitleInput('');\n setDescInput('');\n setCoverImage('');\n await loadData();\n } catch (e) {\n setError((e as Error).message);\n } finally {\n setSubmitting(false);\n }\n };\n\n return (\n <section>\n <h2>{title}</h2>\n <button onClick={() => void loadData()} disabled={loading}>\n {loading ? '刷新中...' : '刷新数据'}\n </button>\n {error ? <p style={{ color: 'crimson' }}>错误:{error}</p> : null}\n\n <div>\n <h3>新建投稿</h3>\n <input value={titleInput} onChange={(e) => setTitleInput(e.target.value)} placeholder=\"作品标题\" />\n <br />\n <textarea value={descInput} onChange={(e) => setDescInput(e.target.value)} placeholder=\"作品简介\" />\n <br />\n <input value={coverImage} onChange={(e) => setCoverImage(e.target.value)} placeholder=\"封面 URL\" />\n <br />\n <select value={workType} onChange={(e) => setWorkType(e.target.value as MikuWorkType)}>\n {workTypes.map((item) => (\n <option value={item} key={item}>\n {item}\n </option>\n ))}\n </select>\n <button onClick={() => void submitWork()} disabled={submitting || !snapshot}>\n {submitting ? '提交中...' : '提交稿件'}\n </button>\n </div>\n\n <div>\n <h3>我的投稿({mySubmissions.length})</h3>\n <ul>\n {mySubmissions.map((item) => (\n <li key={item.id}>\n {item.title}|状态:{item.status}|票数:{item.voteCount}\n {item.rejectReason ? `|驳回:${item.rejectReason}` : ''}\n </li>\n ))}\n </ul>\n </div>\n </section>\n );\n};\n\nexport default MikuContestArtistPage;\n","import React, { useEffect, useMemo, useState } from 'react';\nimport { createMikuContestWebClient } from '../../../service/web';\nimport type { MikuContestApiClient } from '../../../service/api';\nimport type { MikuContestStateSnapshot, MikuSubmission } from '../../../types';\n\nexport interface MikuContestAdminPageProps {\n client?: Pick<\n MikuContestApiClient,\n | 'getSnapshot'\n | 'listSubmissions'\n | 'reviewSubmission'\n | 'setVoterRestriction'\n | 'resetVotes'\n | 'exportSubmissions'\n | 'updateContestConfig'\n >;\n adminId: string;\n title?: string;\n}\n\nconst MikuContestAdminPage: React.FC<MikuContestAdminPageProps> = ({\n client,\n adminId,\n title = '管理员面板',\n}) => {\n const api = useMemo(() => client || createMikuContestWebClient(), [client]);\n\n const [snapshot, setSnapshot] = useState<MikuContestStateSnapshot | null>(null);\n const [submissions, setSubmissions] = useState<MikuSubmission[]>([]);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [voterId, setVoterId] = useState('');\n\n const loadData = async () => {\n setLoading(true);\n setError(null);\n try {\n const [contest, list] = await Promise.all([api.getSnapshot(), api.listSubmissions()]);\n setSnapshot(contest);\n setSubmissions(list);\n } catch (e) {\n setError((e as Error).message);\n } finally {\n setLoading(false);\n }\n };\n\n useEffect(() => {\n void loadData();\n }, []);\n\n const review = async (item: MikuSubmission, action: 'approve' | 'reject') => {\n try {\n await api.reviewSubmission({\n submissionId: item.id,\n reviewerId: adminId,\n action,\n rejectReason: action === 'reject' ? '管理员驳回' : undefined,\n });\n await loadData();\n } catch (e) {\n setError((e as Error).message);\n }\n };\n\n const toggleVoting = async (enabled: boolean) => {\n if (!snapshot) return;\n try {\n await api.updateContestConfig({\n toggles: {\n ...snapshot.contest.toggles,\n votingEnabled: enabled,\n },\n });\n await loadData();\n } catch (e) {\n setError((e as Error).message);\n }\n };\n\n const setRestriction = async (banned: boolean) => {\n if (!snapshot || !voterId.trim()) return;\n try {\n await api.setVoterRestriction({\n voterId: voterId.trim(),\n banned,\n reason: banned ? '管理员手动封禁' : '管理员解除封禁',\n operatorId: adminId,\n });\n setVoterId('');\n } catch (e) {\n setError((e as Error).message);\n }\n };\n\n const resetVotesByVoter = async () => {\n if (!voterId.trim()) return;\n try {\n await api.resetVotes({ voterId: voterId.trim() });\n setVoterId('');\n await loadData();\n } catch (e) {\n setError((e as Error).message);\n }\n };\n\n const exportExcel = async () => {\n try {\n const data = await api.exportSubmissions();\n const blob = new Blob([data], {\n type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = 'miku-submissions.xlsx';\n a.click();\n URL.revokeObjectURL(url);\n } catch (e) {\n setError((e as Error).message);\n }\n };\n\n return (\n <section>\n <h2>{title}</h2>\n <button onClick={() => void loadData()} disabled={loading}>\n {loading ? '刷新中...' : '刷新数据'}\n </button>\n {error ? <p style={{ color: 'crimson' }}>错误:{error}</p> : null}\n\n <div>\n <h3>赛事开关</h3>\n <button onClick={() => void toggleVoting(true)} disabled={!snapshot}>\n 开启投票\n </button>\n <button onClick={() => void toggleVoting(false)} disabled={!snapshot}>\n 关闭投票\n </button>\n </div>\n\n <div>\n <h3>投稿审核({submissions.length})</h3>\n <ul>\n {submissions.map((item) => (\n <li key={item.id}>\n <strong>{item.title}</strong>|作者:{item.authorNickname}|状态:{item.status}|票数:{item.voteCount}\n {item.status === 'pending' ? (\n <>\n {' '}\n <button onClick={() => void review(item, 'approve')}>通过</button>\n <button onClick={() => void review(item, 'reject')}>驳回</button>\n </>\n ) : null}\n </li>\n ))}\n </ul>\n </div>\n\n <div>\n <h3>投票风控</h3>\n <input value={voterId} onChange={(e) => setVoterId(e.target.value)} placeholder=\"voterId\" />\n <button onClick={() => void setRestriction(true)} disabled={!snapshot}>\n 封禁投票\n </button>\n <button onClick={() => void setRestriction(false)} disabled={!snapshot}>\n 解除封禁\n </button>\n <button onClick={() => void resetVotesByVoter()}>清零该用户票数</button>\n </div>\n\n <div>\n <h3>导出</h3>\n <button onClick={() => void exportExcel()}>导出投稿 Excel</button>\n </div>\n </section>\n );\n};\n\nexport default MikuContestAdminPage;\n","import React, { useState } from 'react';\nimport MikuContestAudiencePage from './MikuContestAudiencePage';\nimport MikuContestArtistPage from './MikuContestArtistPage';\nimport MikuContestAdminPage from './MikuContestAdminPage';\n\ntype MikuContestView = 'audience' | 'artist' | 'admin';\n\nexport interface MikuContestPageProps {\n defaultView?: MikuContestView;\n viewerVoterId?: string;\n artistId?: string;\n artistNickname?: string;\n adminId?: string;\n}\n\nconst MikuContestPage: React.FC<MikuContestPageProps> = ({\n defaultView = 'audience',\n viewerVoterId = 'viewer-demo',\n artistId = 'artist-demo',\n artistNickname = 'Demo 画师',\n adminId = 'admin-demo',\n}) => {\n const [view, setView] = useState<MikuContestView>(defaultView);\n\n return (\n <div>\n <h1>Miku Contest</h1>\n <div>\n <button onClick={() => setView('audience')}>观众端</button>\n <button onClick={() => setView('artist')}>画师端</button>\n <button onClick={() => setView('admin')}>管理员端</button>\n </div>\n\n {view === 'audience' ? <MikuContestAudiencePage voterId={viewerVoterId} /> : null}\n {view === 'artist' ? <MikuContestArtistPage authorId={artistId} authorNickname={artistNickname} /> : null}\n {view === 'admin' ? <MikuContestAdminPage adminId={adminId} /> : null}\n </div>\n );\n};\n\nexport default MikuContestPage;\n"]}
|