Compare commits

...

2 Commits

Author SHA1 Message Date
2e79fcfeb0 feat: 配置生产环境后端服务器动态地址支持
- 添加环境变量支持,可通过 NEXT_PUBLIC_API_BASE_URL 配置后端地址
- 实现智能地址获取:无配置时自动使用当前域名+3006端口
- 添加 .env.template 模板文件,方便部署时配置
- 更新 package.json 脚本支持通过 PORT 环境变量配置前端端口
- 修改 .gitignore 允许模板文件提交但保护敏感环境文件

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-23 09:08:55 +08:00
700f252454 fix: 修复handleBatchUpdate函数类型定义不匹配问题
- 更新UseAccountsReturn接口中handleBatchUpdate的类型签名,添加可选的targetIds参数
- 更新BatchOperationsProps接口中onBatchUpdate的类型定义以匹配实际函数签名
- 修复response.data可能为null的TypeScript严格检查错误

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-23 08:57:45 +08:00
7 changed files with 41 additions and 8 deletions

View File

@@ -3,7 +3,12 @@
"allow": [
"Bash(pnpm dlx:*)",
"Bash(pnpm dev:*)",
"Bash(mkdir:*)"
"Bash(mkdir:*)",
"Bash(git remote add:*)",
"Bash(git push:*)",
"Bash(git add:*)",
"Bash(npm run build:*)",
"Bash(git add:*)"
],
"deny": []
}

11
.env.template Normal file
View File

@@ -0,0 +1,11 @@
# 环境配置模板
# 部署时复制此文件为 .env.production 并修改相应配置
# 前端服务端口(默认 3000
PORT=3000
# 后端 API 基础地址
# NEXT_PUBLIC_API_BASE_URL=http://当前域名:3006
# 环境
NODE_ENV=production

1
.gitignore vendored
View File

@@ -32,6 +32,7 @@ yarn-error.log*
# env files (can opt-in for committing if needed)
.env*
!.env.template
# vercel
.vercel

View File

@@ -13,7 +13,7 @@ interface BatchOperationsProps {
selectedCount: number;
selectedAccounts: Account[];
stats: StatsOverview | null;
onBatchUpdate: (payload: Partial<Pick<Account, 'status' | 'ownerId' | 'notes' | 'platform'>>) => Promise<void>;
onBatchUpdate: (payload: Partial<Pick<Account, 'status' | 'ownerId' | 'notes' | 'platform'>>, targetIds?: number[]) => Promise<void>;
onBatchDelete: () => Promise<void>;
}

View File

@@ -8,13 +8,28 @@ import {
ScriptUploadItem
} from './types';
const API_BASE_URL = 'http://localhost:3006';
const getApiBaseUrl = () => {
// 检查是否有配置的环境变量(构建时注入)
const envUrl = process.env.NEXT_PUBLIC_API_BASE_URL;
if (envUrl && envUrl !== 'undefined') {
return envUrl;
}
// 在浏览器环境中,没有配置则使用当前域名
if (typeof window !== 'undefined') {
return `${window.location.protocol}//${window.location.hostname}:3006`;
}
// 服务端渲染时的默认值
return 'http://localhost:3006';
};
class ApiClient {
private async request<T>(
endpoint: string,
options: RequestInit = {}
): Promise<ApiResponse<T>> {
const API_BASE_URL = getApiBaseUrl(); // 每次请求时动态获取
const url = `${API_BASE_URL}${endpoint}`;
const response = await fetch(url, {

View File

@@ -47,7 +47,7 @@ export interface UseAccountsReturn {
handleSelectAll: (checked: boolean) => void;
handleSelectOne: (id: number, checked: boolean) => void;
handleBatchDelete: () => Promise<void>;
handleBatchUpdate: (payload: Partial<Pick<Account, 'status' | 'ownerId' | 'notes' | 'platform'>>) => Promise<void>;
handleBatchUpdate: (payload: Partial<Pick<Account, 'status' | 'ownerId' | 'notes' | 'platform'>>, targetIds?: number[]) => Promise<void>;
handleUploadAccounts: (accounts: ScriptUploadItem[], ownerId: string) => Promise<void>;
setSelectedIds: (ids: number[]) => void;
}
@@ -108,8 +108,8 @@ export function useAccounts(): UseAccountsReturn {
setAccounts(response.data.list);
setPagination(prev => ({
...prev,
total: response.data.pagination.total,
totalPages: response.data.pagination.totalPages
total: response.data!.pagination.total,
totalPages: response.data!.pagination.totalPages
}));
}
} catch (error) {

View File

@@ -4,8 +4,9 @@
"private": true,
"scripts": {
"dev": "next dev --turbopack",
"build": "next build --turbopack",
"start": "next start"
"build": "next build --turbopack",
"start": "next start -p ${PORT:-3000}",
"start:prod": "next start -p ${PORT:-3000}"
},
"dependencies": {
"@radix-ui/react-checkbox": "^1.3.3",