@@ -17,10 +17,62 @@ import {
1717import { NotificationService } from "@/features/notifications/service" ;
1818import { getCachedOrganizations } from "@community/lib-server/cache/organizations" ;
1919import { ContributionType } from "@prisma/client" ;
20+ import type { EventStatus , Prisma , SubmissionStatus } from "@prisma/client" ;
2021import { Hono } from "hono" ;
2122import { z } from "zod" ;
2223import { createProjectSchema , updateProjectSchema } from "./projects-schemas" ;
2324
25+ const PUBLIC_EVENT_STATUSES : EventStatus [ ] = [
26+ "PUBLISHED" ,
27+ "REGISTRATION_CLOSED" ,
28+ "ONGOING" ,
29+ "COMPLETED" ,
30+ ] ;
31+
32+ const PUBLIC_SUBMISSION_STATUSES : SubmissionStatus [ ] = [
33+ "SUBMITTED" ,
34+ "UNDER_REVIEW" ,
35+ "APPROVED" ,
36+ "AWARDED" ,
37+ ] ;
38+
39+ const publicProjectVisibilityWhere : Prisma . ProjectWhereInput = {
40+ user : {
41+ profilePublic : true ,
42+ } ,
43+ OR : [
44+ {
45+ isComplete : true ,
46+ } ,
47+ {
48+ isSubmission : true ,
49+ communityUseAuth : true ,
50+ eventSubmissions : {
51+ some : {
52+ status : {
53+ in : PUBLIC_SUBMISSION_STATUSES ,
54+ } ,
55+ event : {
56+ status : {
57+ in : PUBLIC_EVENT_STATUSES ,
58+ } ,
59+ } ,
60+ } ,
61+ } ,
62+ } ,
63+ ] ,
64+ } ;
65+
66+ function getPublicProjectWhere (
67+ where ?: Prisma . ProjectWhereInput ,
68+ ) : Prisma . ProjectWhereInput {
69+ return where
70+ ? {
71+ AND : [ publicProjectVisibilityWhere , where ] ,
72+ }
73+ : publicProjectVisibilityWhere ;
74+ }
75+
2476// 作品完成度计算函数
2577function calculateProjectCompletion ( data : {
2678 title : string ;
@@ -83,36 +135,31 @@ export const projectsRouter = new Hono()
83135 const sort = c . req . query ( "sort" ) ;
84136 const sortOrder = c . req . query ( "sortOrder" ) || "desc" ;
85137
86- const where : any = {
87- user : {
88- profilePublic : true ,
89- } ,
90- isComplete : true ,
91- } ;
138+ const filterWhere : Prisma . ProjectWhereInput = { } ;
92139
93140 // Handle special stage filters
94141 if ( stage === "recruiting" ) {
95- where . isRecruiting = true ;
142+ filterWhere . isRecruiting = true ;
96143 } else if ( stage === "featured" ) {
97- where . featured = true ;
144+ filterWhere . featured = true ;
98145 } else if ( stage === "early" ) {
99- where . stage = {
146+ filterWhere . stage = {
100147 in : [ "IDEA_VALIDATION" , "DEVELOPMENT" , "LAUNCH" ] ,
101148 } ;
102149 } else if ( stage === "mature" ) {
103- where . stage = {
150+ filterWhere . stage = {
104151 in : [ "GROWTH" , "MONETIZATION" , "FUNDING" , "COMPLETED" ] ,
105152 } ;
106153 } else if (
107154 stage &&
108155 stage !== "recruiting" &&
109156 stage !== "featured"
110157 ) {
111- where . stage = stage ;
158+ filterWhere . stage = stage as any ;
112159 }
113160
114161 if ( search ) {
115- where . OR = [
162+ filterWhere . OR = [
116163 {
117164 title : {
118165 contains : search ,
@@ -134,8 +181,7 @@ export const projectsRouter = new Hono()
134181 }
135182
136183 if ( organization ) {
137- where . user = {
138- ...where . user ,
184+ filterWhere . user = {
139185 members : {
140186 some : {
141187 organization : {
@@ -146,6 +192,8 @@ export const projectsRouter = new Hono()
146192 } ;
147193 }
148194
195+ const where = getPublicProjectWhere ( filterWhere ) ;
196+
149197 const orderBy : any = [ { featured : "desc" } ] ;
150198 const direction = sortOrder === "asc" ? "asc" : "desc" ;
151199 if ( sort === "latest" ) {
@@ -159,7 +207,7 @@ export const projectsRouter = new Hono()
159207 }
160208
161209 // 优化后的查询:使用并发查询和缓存组织数据
162- const [ projects , stats , totalProjects , organizations ] =
210+ const [ projectRows , stats , totalProjects , organizations ] =
163211 await Promise . all ( [
164212 db . project . findMany ( {
165213 where,
@@ -181,6 +229,17 @@ export const projectsRouter = new Hono()
181229 isRecruiting : true ,
182230 recruitmentTags : true ,
183231 recruitmentStatus : true ,
232+ attachments : {
233+ where : {
234+ fileType : "image" ,
235+ } ,
236+ orderBy : {
237+ order : "asc" ,
238+ } ,
239+ select : {
240+ fileUrl : true ,
241+ } ,
242+ } ,
184243 likes : session ?. user
185244 ? {
186245 where : {
@@ -237,24 +296,21 @@ export const projectsRouter = new Hono()
237296 _count : {
238297 stage : true ,
239298 } ,
240- where : {
241- user : {
242- profilePublic : true ,
243- } ,
244- isComplete : true ,
245- } ,
299+ where : getPublicProjectWhere ( ) ,
246300 } ) ,
247301 db . project . count ( {
248- where : {
249- user : {
250- profilePublic : true ,
251- } ,
252- isComplete : true ,
253- } ,
302+ where : getPublicProjectWhere ( ) ,
254303 } ) ,
255304 // 使用缓存的组织数据替代直接查询
256305 getCachedOrganizations ( ) ,
257306 ] ) ;
307+ const projects = projectRows . map ( ( { attachments, ...project } ) => ( {
308+ ...project ,
309+ screenshots :
310+ project . screenshots . length > 0
311+ ? project . screenshots
312+ : attachments . map ( ( attachment ) => attachment . fileUrl ) ,
313+ } ) ) ;
258314
259315 return c . json ( {
260316 projects,
@@ -916,13 +972,9 @@ export const projectsRouter = new Hono()
916972
917973 // Get user's public projects
918974 const projects = await db . project . findMany ( {
919- where : {
975+ where : getPublicProjectWhere ( {
920976 userId,
921- user : {
922- profilePublic : true , // Only show projects if user's profile is public
923- } ,
924- isComplete : true , // 只显示高完成度作品
925- } ,
977+ } ) ,
926978 orderBy : [
927979 { featured : "desc" } ,
928980 { order : "asc" } ,
@@ -941,10 +993,31 @@ export const projectsRouter = new Hono()
941993 featured : true ,
942994 createdAt : true ,
943995 updatedAt : true ,
996+ attachments : {
997+ where : {
998+ fileType : "image" ,
999+ } ,
1000+ orderBy : {
1001+ order : "asc" ,
1002+ } ,
1003+ select : {
1004+ fileUrl : true ,
1005+ } ,
1006+ } ,
9441007 } ,
9451008 } ) ;
9461009
947- return c . json ( { projects } ) ;
1010+ return c . json ( {
1011+ projects : projects . map ( ( { attachments, ...project } ) => ( {
1012+ ...project ,
1013+ screenshots :
1014+ project . screenshots . length > 0
1015+ ? project . screenshots
1016+ : attachments . map (
1017+ ( attachment ) => attachment . fileUrl ,
1018+ ) ,
1019+ } ) ) ,
1020+ } ) ;
9481021 } catch ( error ) {
9491022 console . error ( "Error fetching public projects:" , error ) ;
9501023 return c . json ( { error : "Internal server error" } , 500 ) ;
@@ -964,11 +1037,9 @@ export const projectsRouter = new Hono()
9641037
9651038 // Check if project exists and is public
9661039 const project = await db . project . findFirst ( {
967- where : {
968- ...resolveProjectIdentifier ( projectId ) ,
969- user : { profilePublic : true } ,
970- isComplete : true , // 确保是高完成度作品
971- } ,
1040+ where : getPublicProjectWhere (
1041+ resolveProjectIdentifier ( projectId ) ,
1042+ ) ,
9721043 } ) ;
9731044
9741045 if ( ! project ) {
@@ -1066,7 +1137,9 @@ export const projectsRouter = new Hono()
10661137
10671138 // Resolve project identifier
10681139 const project = await db . project . findFirst ( {
1069- where : resolveProjectIdentifier ( projectId ) ,
1140+ where : getPublicProjectWhere (
1141+ resolveProjectIdentifier ( projectId ) ,
1142+ ) ,
10701143 select : { id : true } ,
10711144 } ) ;
10721145
@@ -1125,11 +1198,9 @@ export const projectsRouter = new Hono()
11251198
11261199 // Check if project exists and is public
11271200 const project = await db . project . findFirst ( {
1128- where : {
1129- ...resolveProjectIdentifier ( projectId ) ,
1130- user : { profilePublic : true } ,
1131- isComplete : true , // 确保是高完成度作品
1132- } ,
1201+ where : getPublicProjectWhere (
1202+ resolveProjectIdentifier ( projectId ) ,
1203+ ) ,
11331204 } ) ;
11341205
11351206 if ( ! project ) {
@@ -1186,7 +1257,9 @@ export const projectsRouter = new Hono()
11861257
11871258 // Resolve project identifier
11881259 const project = await db . project . findFirst ( {
1189- where : resolveProjectIdentifier ( projectId ) ,
1260+ where : getPublicProjectWhere (
1261+ resolveProjectIdentifier ( projectId ) ,
1262+ ) ,
11901263 select : { id : true } ,
11911264 } ) ;
11921265
@@ -1240,11 +1313,9 @@ export const projectsRouter = new Hono()
12401313
12411314 // Check if project exists and is public
12421315 const project = await db . project . findFirst ( {
1243- where : {
1244- ...resolveProjectIdentifier ( projectId ) ,
1245- user : { profilePublic : true } ,
1246- isComplete : true , // 确保是高完成度作品
1247- } ,
1316+ where : getPublicProjectWhere (
1317+ resolveProjectIdentifier ( projectId ) ,
1318+ ) ,
12481319 } ) ;
12491320
12501321 if ( ! project ) {
@@ -1327,7 +1398,9 @@ export const projectsRouter = new Hono()
13271398
13281399 // Get project with user information and counts
13291400 const project = await db . project . findFirst ( {
1330- where : resolveProjectIdentifier ( projectId ) ,
1401+ where : getPublicProjectWhere (
1402+ resolveProjectIdentifier ( projectId ) ,
1403+ ) ,
13311404 include : {
13321405 user : {
13331406 select : {
@@ -1348,12 +1421,7 @@ export const projectsRouter = new Hono()
13481421 } ,
13491422 } ) ;
13501423
1351- if (
1352- ! project ||
1353- ! project . user ||
1354- ! project . user . profilePublic ||
1355- ! project . isComplete
1356- ) {
1424+ if ( ! project || ! project . user || ! project . user . profilePublic ) {
13571425 return c . json ( { error : "Project not found" } , 404 ) ;
13581426 }
13591427
@@ -1401,7 +1469,9 @@ export const projectsRouter = new Hono()
14011469
14021470 // Get the project to find the user ID
14031471 const project = await db . project . findFirst ( {
1404- where : resolveProjectIdentifier ( projectId ) ,
1472+ where : getPublicProjectWhere (
1473+ resolveProjectIdentifier ( projectId ) ,
1474+ ) ,
14051475 select : {
14061476 id : true ,
14071477 userId : true ,
@@ -1419,14 +1489,10 @@ export const projectsRouter = new Hono()
14191489
14201490 // Get related projects from the same user
14211491 const relatedProjects = await db . project . findMany ( {
1422- where : {
1492+ where : getPublicProjectWhere ( {
14231493 userId : project . userId ,
14241494 id : { not : project . id } ,
1425- user : {
1426- profilePublic : true ,
1427- } ,
1428- isComplete : true ,
1429- } ,
1495+ } ) ,
14301496 include : {
14311497 user : {
14321498 select : {
0 commit comments