Skip to content

Commit b0b5ace

Browse files
author
pengyu
committed
clear chinese comment and update model
1 parent 7232cdb commit b0b5ace

File tree

21 files changed

+276
-135
lines changed

21 files changed

+276
-135
lines changed

backend/src/build-system/__tests__/test.frontend-code-generate.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ describe('FrontendCodeHandler', () => {
1212
name: 'Spotify-like Music Web',
1313
description: 'Users can play music',
1414
databaseType: 'SQLite',
15-
model: 'o3-mini-high',
15+
model: 'o4-mini',
1616
nodes: [
1717
{
1818
handler: FrontendCodeHandler,

backend/src/build-system/context.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ export class BuilderContext {
115115
this.globalContext.set('projectSize', 'small');
116116
break;
117117
case 'gpt-4o':
118-
case 'o3-mini-high':
118+
case 'o4-mini':
119119
this.globalContext.set('projectSize', 'medium');
120120
break;
121121
default:

backend/src/build-system/handlers/frontend-code-generate/CodeReview.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ export class FrontendQueueProcessor {
198198
let fixResponse = await chatSyncWithClocker(
199199
this.context,
200200
{
201-
model: 'o3-mini-high',
201+
model: 'o4-mini',
202202
messages: [
203203
{ role: 'system', content: fixPrompt },
204204
{
@@ -270,7 +270,7 @@ export class FrontendQueueProcessor {
270270
fixResponse = await chatSyncWithClocker(
271271
this.context,
272272
{
273-
model: 'o3-mini-high',
273+
model: 'o4-mini',
274274
messages: [
275275
{ role: 'system', content: fixPrompt },
276276
{

backend/src/build-system/handlers/frontend-code-generate/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -366,8 +366,8 @@ export class FrontendCodeHandler implements BuildHandler<string> {
366366
context,
367367
{
368368
model: isSPAFlag
369-
? 'claude-3.7-sonnet' // Use Claude for SPAs
370-
: 'o3-mini-high', // Use default or fallback for non-SPAs
369+
? 'gpt-4o-mini' // Use Claude for SPAs
370+
: 'o4-mini', // Use default or fallback for non-SPAs
371371
messages,
372372
},
373373
'generate frontend code',

backend/src/build-system/handlers/ux/uiux-layout/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ export class UIUXLayoutHandler implements BuildHandler<string> {
7575
context,
7676
{
7777
// model: context.defaultModel || 'gpt-4o-mini',
78-
model: 'claude-3.7-sonnet',
78+
model: 'gpt-4o-mini',
7979
messages,
8080
},
8181
'generateUIUXLayout',

backend/src/user/user.model.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export class User extends SystemBaseModel {
2222
id: string;
2323

2424
@Field()
25-
@Column()
25+
@Column({ unique: true })
2626
username: string;
2727

2828
@Column()

backend/src/user/user.service.ts

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import {
22
BadRequestException,
3+
ConflictException,
34
Injectable,
45
NotFoundException,
56
} from '@nestjs/common';
@@ -107,4 +108,69 @@ export class UserService {
107108

108109
return true;
109110
}
111+
112+
/**
113+
* Checks if a username already exists in the database
114+
* @param username Username to check
115+
* @param excludeUserId Optional user ID to exclude from the check (for updates)
116+
* @returns Boolean indicating if the username exists
117+
*/
118+
async isUsernameExists(
119+
username: string,
120+
excludeUserId?: string,
121+
): Promise<boolean> {
122+
const query = this.userRepository
123+
.createQueryBuilder('user')
124+
.where('LOWER(user.username) = LOWER(:username)', {
125+
username: username.toLowerCase(),
126+
});
127+
128+
if (excludeUserId) {
129+
query.andWhere('user.id != :userId', { userId: excludeUserId });
130+
}
131+
132+
const count = await query.getCount();
133+
return count > 0;
134+
}
135+
136+
/**
137+
* Updates a user's username with uniqueness validation
138+
* @param userId User ID
139+
* @param newUsername New username to set
140+
* @returns Updated user object
141+
*/
142+
async updateUsername(userId: string, newUsername: string): Promise<User> {
143+
if (!newUsername || newUsername.trim().length < 3) {
144+
throw new BadRequestException(
145+
'Username must be at least 3 characters long',
146+
);
147+
}
148+
149+
// Check if the username is already taken
150+
const exists = await this.isUsernameExists(newUsername, userId);
151+
if (exists) {
152+
throw new ConflictException(
153+
`Username '${newUsername}' is already taken. Please choose another one.`,
154+
);
155+
}
156+
157+
const user = await this.userRepository.findOneBy({ id: userId });
158+
if (!user) {
159+
throw new NotFoundException('User not found');
160+
}
161+
162+
user.username = newUsername;
163+
164+
try {
165+
return await this.userRepository.save(user);
166+
} catch (error) {
167+
// Check for unique constraint error (just in case of race condition)
168+
if (error.code === '23505' || error.message.includes('duplicate')) {
169+
throw new ConflictException(
170+
`Username '${newUsername}' is already taken. Please choose another one.`,
171+
);
172+
}
173+
throw error;
174+
}
175+
}
110176
}

frontend/src/app/api/screenshot/route.ts

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -33,59 +33,72 @@ export async function GET(req: Request) {
3333
);
3434
}
3535

36-
logger.info(`Starting screenshot for URL: ${url}`);
36+
logger.info(`[SCREENSHOT] Starting screenshot for URL: ${url}`);
3737

3838
try {
3939
// Get browser instance
40+
logger.info(`[SCREENSHOT] Attempting to get browser instance`);
4041
const browser = await getBrowser();
41-
logger.info('Browser instance acquired');
42+
logger.info(`[SCREENSHOT] Browser instance acquired successfully`);
4243

4344
// Create a new page
45+
logger.info(`[SCREENSHOT] Creating new page`);
4446
page = await browser.newPage();
45-
logger.info('New page created');
47+
logger.info(`[SCREENSHOT] New page created successfully`);
4648

4749
// Set viewport
50+
logger.info(`[SCREENSHOT] Setting viewport`);
4851
await page.setViewport({ width: 1600, height: 900 });
49-
logger.info('Viewport set to 1600x900');
52+
logger.info(`[SCREENSHOT] Viewport set successfully`);
5053

5154
// Navigate to the URL
52-
logger.info(`Navigating to URL: ${url}`);
55+
logger.info(`[SCREENSHOT] Navigating to URL: ${url}`);
5356
await page.goto(url, {
54-
waitUntil: 'domcontentloaded',
55-
timeout: 60000,
57+
waitUntil: 'networkidle2',
58+
timeout: 90000,
5659
});
57-
logger.info('Page loaded (DOMContentLoaded)');
60+
logger.info(`[SCREENSHOT] Page loaded successfully`);
5861

5962
// Extra wait for rendering
60-
await new Promise((resolve) => setTimeout(resolve, 2000));
61-
logger.info('Waited 2 seconds for rendering');
63+
logger.info(`[SCREENSHOT] Waiting additional time for rendering`);
64+
await new Promise((resolve) => setTimeout(resolve, 5000));
65+
logger.info(`[SCREENSHOT] Additional wait completed`);
6266

6367
// Take screenshot
68+
logger.info(`[SCREENSHOT] Taking screenshot`);
6469
const screenshot = await page.screenshot({
6570
type: 'png',
6671
fullPage: true,
6772
});
68-
logger.info('Screenshot captured');
73+
logger.info(`[SCREENSHOT] Screenshot captured successfully, size: ${screenshot.length} bytes`);
6974

7075
// Clean up
71-
if (page) await page.close();
72-
logger.info('Page closed');
76+
if (page) {
77+
logger.info(`[SCREENSHOT] Closing page`);
78+
await page.close();
79+
logger.info(`[SCREENSHOT] Page closed successfully`);
80+
}
7381

82+
logger.info(`[SCREENSHOT] Returning screenshot response`);
7483
return new Response(screenshot, {
7584
headers: {
7685
'Content-Type': 'image/png',
77-
'Cache-Control': 's-maxage=3600',
86+
'Cache-Control': 'no-cache, no-store, must-revalidate',
87+
'Pragma': 'no-cache',
88+
'Expires': '0'
7889
},
7990
});
8091
} catch (error: any) {
81-
logger.error('Screenshot error:', error);
92+
logger.error(`[SCREENSHOT] Error capturing screenshot: ${error.message}`, error);
93+
logger.error(`[SCREENSHOT] Error stack: ${error.stack}`);
8294

8395
if (page) {
8496
try {
97+
logger.info(`[SCREENSHOT] Attempting to close page after error`);
8598
await page.close();
86-
logger.info('Closed page after error');
99+
logger.info(`[SCREENSHOT] Successfully closed page after error`);
87100
} catch (closeError) {
88-
logger.error('Error closing page:', closeError);
101+
logger.error(`[SCREENSHOT] Error closing page: ${closeError.message}`);
89102
}
90103
}
91104

@@ -96,12 +109,13 @@ export async function GET(req: Request) {
96109
) {
97110
try {
98111
if (browserInstance) {
112+
logger.warn(`[SCREENSHOT] Resetting browser instance due to protocol error`);
99113
await browserInstance.close();
100-
logger.warn('Browser instance was closed due to protocol error');
101114
browserInstance = null;
115+
logger.warn(`[SCREENSHOT] Browser instance reset successfully`);
102116
}
103117
} catch (closeBrowserError) {
104-
logger.error('Error closing browser:', closeBrowserError);
118+
logger.error(`[SCREENSHOT] Error closing browser: ${closeBrowserError.message}`);
105119
}
106120
}
107121

frontend/src/app/globals.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@
8282
height: 1px;
8383
}
8484

85-
/* 修改滚动条颜色为主题色调 */
85+
/* Modify scrollbar color to match theme */
8686
:root {
8787
--scrollbar-thumb-color: rgba(
8888
99,

frontend/src/app/media/[...path]/route.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import path from 'path';
44
import { getMediaDir } from 'codefox-common';
55
import { logger } from '@/app/log/logger';
66

7-
87
export async function GET(
98
request: NextRequest,
109
{ params }: { params: { path: string[] } }
@@ -15,7 +14,7 @@ export async function GET(
1514
const filePath = path.join(mediaDir, ...params.path);
1615
const normalizedPath = path.normalize(filePath);
1716
logger.info(`📁 getMediaDir = ${mediaDir}`);
18-
logger.info(`📂 full filePath = ${filePath}`);
17+
logger.info(`📂 full filePath = ${filePath}`);
1918
logger.debug(`Requested path: ${params.path.join('/')}`);
2019
logger.debug(`Full resolved path: ${filePath}`);
2120

0 commit comments

Comments
 (0)