修正團體管理的 BUG
This commit is contained in:
@@ -367,7 +367,7 @@ export class UserService extends DatabaseServiceBase {
|
||||
const appsSql = `
|
||||
SELECT COUNT(*) as total_apps
|
||||
FROM apps
|
||||
WHERE creator_id = '${userId}' AND is_active = TRUE
|
||||
WHERE creator_id = '${userId}' AND is_active = 1
|
||||
`;
|
||||
const appsResult = await this.query(appsSql, []);
|
||||
const totalApps = appsResult[0]?.total_apps || 0;
|
||||
@@ -385,7 +385,7 @@ export class UserService extends DatabaseServiceBase {
|
||||
const likesSql = `
|
||||
SELECT COALESCE(SUM(a.likes_count), 0) as total_likes
|
||||
FROM apps a
|
||||
WHERE a.creator_id = '${userId}' AND a.is_active = TRUE
|
||||
WHERE a.creator_id = '${userId}' AND a.is_active = 1
|
||||
`;
|
||||
const likesResult = await this.query(likesSql, []);
|
||||
const totalLikes = likesResult[0]?.total_likes || 0;
|
||||
@@ -602,7 +602,7 @@ export class UserService extends DatabaseServiceBase {
|
||||
COALESCE(SUM(views_count), 0) as total_views,
|
||||
COALESCE(SUM(likes_count), 0) as total_likes
|
||||
FROM apps
|
||||
WHERE is_active = TRUE
|
||||
WHERE is_active = 1
|
||||
`;
|
||||
const appStats = await this.queryOne(appStatsSql);
|
||||
|
||||
@@ -713,7 +713,7 @@ export class UserService extends DatabaseServiceBase {
|
||||
a.created_at
|
||||
FROM apps a
|
||||
LEFT JOIN user_ratings ur ON a.id = ur.app_id
|
||||
WHERE a.is_active = TRUE
|
||||
WHERE a.is_active = 1
|
||||
GROUP BY a.id, a.name, a.description, a.views_count, a.likes_count, a.category, a.created_at
|
||||
ORDER BY (a.views_count + a.likes_count * 2) DESC
|
||||
LIMIT ${limit}
|
||||
@@ -1010,11 +1010,13 @@ export class TeamService extends DatabaseServiceBase {
|
||||
SELECT t.*,
|
||||
u.name as leader_name,
|
||||
u.phone as leader_phone,
|
||||
COUNT(tm.id) as member_count
|
||||
COUNT(DISTINCT tm.id) as member_count,
|
||||
COUNT(DISTINCT a.id) as app_count
|
||||
FROM teams t
|
||||
LEFT JOIN users u ON t.leader_id = u.id
|
||||
LEFT JOIN team_members tm ON t.id = tm.team_id
|
||||
WHERE t.is_active = TRUE
|
||||
LEFT JOIN apps a ON t.id = a.team_id AND a.is_active = 1
|
||||
WHERE t.is_active = 1
|
||||
GROUP BY t.id
|
||||
ORDER BY t.created_at DESC
|
||||
`;
|
||||
@@ -1030,7 +1032,7 @@ export class TeamService extends DatabaseServiceBase {
|
||||
u.phone as leader_phone
|
||||
FROM teams t
|
||||
LEFT JOIN users u ON t.leader_id = u.id
|
||||
WHERE t.id = ? AND t.is_active = TRUE
|
||||
WHERE t.id = ? AND t.is_active = 1
|
||||
`;
|
||||
const results = await DatabaseServiceBase.safeQuery(sql, [id]);
|
||||
return results.length > 0 ? results[0] : null;
|
||||
@@ -1044,7 +1046,7 @@ export class TeamService extends DatabaseServiceBase {
|
||||
u.phone as leader_phone
|
||||
FROM teams t
|
||||
LEFT JOIN users u ON t.leader_id = u.id
|
||||
WHERE t.name = ? AND t.is_active = TRUE
|
||||
WHERE t.name = ? AND t.is_active = 1
|
||||
`;
|
||||
const results = await DatabaseServiceBase.safeQuery(sql, [name]);
|
||||
return results.length > 0 ? results[0] : null;
|
||||
@@ -1058,24 +1060,97 @@ export class TeamService extends DatabaseServiceBase {
|
||||
contact_email: string;
|
||||
description: string;
|
||||
total_likes: number;
|
||||
members?: Array<{
|
||||
user_id: string;
|
||||
role: string;
|
||||
}>;
|
||||
apps?: string[];
|
||||
}>): Promise<boolean> {
|
||||
const fields = Object.keys(updates).filter(key => key !== 'id' && key !== 'created_at');
|
||||
|
||||
if (fields.length === 0) {
|
||||
console.log('沒有字段需要更新');
|
||||
return true;
|
||||
}
|
||||
|
||||
const setClause = fields.map(field => `${field} = ?`).join(', ');
|
||||
const values = fields.map(field => updates[field as keyof typeof updates]);
|
||||
try {
|
||||
// 更新團隊基本信息
|
||||
const teamFields = Object.keys(updates).filter(key =>
|
||||
key !== 'id' &&
|
||||
key !== 'created_at' &&
|
||||
key !== 'members' &&
|
||||
key !== 'apps'
|
||||
);
|
||||
|
||||
if (teamFields.length > 0) {
|
||||
const setClause = teamFields.map(field => `${field} = ?`).join(', ');
|
||||
const values = teamFields.map(field => updates[field as keyof typeof updates]);
|
||||
values.push(id);
|
||||
|
||||
const sql = `UPDATE teams SET ${setClause}, updated_at = CURRENT_TIMESTAMP WHERE id = ?`;
|
||||
|
||||
try {
|
||||
const result = await DatabaseServiceBase.safeUpdate(sql, values);
|
||||
console.log('團隊更新結果:', result);
|
||||
return result.affectedRows > 0;
|
||||
const result = await DatabaseServiceBase.safeUpdate(sql, values);
|
||||
console.log('團隊基本信息更新結果:', result);
|
||||
|
||||
if (result.affectedRows === 0) {
|
||||
console.log('團隊基本信息更新失敗');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 更新團隊成員(如果提供了成員信息)
|
||||
if (updates.members && Array.isArray(updates.members)) {
|
||||
try {
|
||||
// 先刪除現有成員
|
||||
console.log('刪除現有團隊成員...');
|
||||
await DatabaseServiceBase.safeDelete('DELETE FROM team_members WHERE team_id = ?', [id]);
|
||||
|
||||
// 添加新成員(如果成員列表不為空)
|
||||
if (updates.members.length > 0) {
|
||||
console.log('添加新團隊成員...');
|
||||
for (const member of updates.members) {
|
||||
if (member.user_id && member.role) {
|
||||
console.log(`添加成員: ${member.user_id} (${member.role})`);
|
||||
await DatabaseServiceBase.safeInsert(
|
||||
'INSERT INTO team_members (team_id, user_id, role, joined_at) VALUES (?, ?, ?, NOW())',
|
||||
[id, member.user_id, member.role]
|
||||
);
|
||||
}
|
||||
}
|
||||
console.log('團隊成員更新完成');
|
||||
} else {
|
||||
console.log('成員列表為空,只刪除現有成員');
|
||||
}
|
||||
} catch (memberError) {
|
||||
console.error('更新團隊成員時發生錯誤:', memberError);
|
||||
// 成員更新失敗不應該影響整個更新操作
|
||||
// 可以選擇繼續或回滾
|
||||
}
|
||||
}
|
||||
|
||||
// 更新團隊應用(如果提供了應用信息)
|
||||
if (updates.apps && Array.isArray(updates.apps)) {
|
||||
try {
|
||||
// 先移除現有應用的團隊關聯
|
||||
console.log('移除現有應用的團隊關聯...');
|
||||
await DatabaseServiceBase.safeUpdate('UPDATE apps SET team_id = NULL WHERE team_id = ?', [id]);
|
||||
|
||||
// 添加新應用的團隊關聯(如果應用列表不為空)
|
||||
if (updates.apps.length > 0) {
|
||||
console.log('添加新應用的團隊關聯...');
|
||||
for (const appId of updates.apps) {
|
||||
if (appId) {
|
||||
console.log(`關聯應用: ${appId}`);
|
||||
await DatabaseServiceBase.safeUpdate(
|
||||
'UPDATE apps SET team_id = ? WHERE id = ?',
|
||||
[id, appId]
|
||||
);
|
||||
}
|
||||
}
|
||||
console.log('團隊應用更新完成');
|
||||
} else {
|
||||
console.log('應用列表為空,只移除現有關聯');
|
||||
}
|
||||
} catch (appError) {
|
||||
console.error('更新團隊應用時發生錯誤:', appError);
|
||||
// 應用更新失敗不應該影響整個更新操作
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('更新團隊錯誤:', error);
|
||||
return false;
|
||||
@@ -1165,7 +1240,7 @@ export class TeamService extends DatabaseServiceBase {
|
||||
// 綁定應用到團隊
|
||||
static async bindAppToTeam(teamId: string, appId: string): Promise<boolean> {
|
||||
try {
|
||||
const sql = 'UPDATE apps SET team_id = ? WHERE id = ? AND is_active = TRUE';
|
||||
const sql = 'UPDATE apps SET team_id = ? WHERE id = ? AND is_active = 1';
|
||||
const result = await DatabaseServiceBase.safeUpdate(sql, [teamId, appId]);
|
||||
return result.affectedRows > 0;
|
||||
} catch (error) {
|
||||
@@ -1196,7 +1271,7 @@ export class TeamService extends DatabaseServiceBase {
|
||||
u.name as creator_name, u.department as creator_department
|
||||
FROM apps a
|
||||
LEFT JOIN users u ON a.creator_id = u.id
|
||||
WHERE a.team_id = ? AND a.is_active = TRUE
|
||||
WHERE a.team_id = ? AND a.is_active = 1
|
||||
ORDER BY a.created_at DESC
|
||||
`;
|
||||
console.log('📝 getTeamApps SQL:', sql);
|
||||
@@ -1211,7 +1286,7 @@ export class TeamService extends DatabaseServiceBase {
|
||||
const sql = `
|
||||
SELECT
|
||||
COUNT(*) as totalTeams,
|
||||
COUNT(CASE WHEN is_active = TRUE THEN 1 END) as activeTeams,
|
||||
COUNT(CASE WHEN is_active = 1 THEN 1 END) as activeTeams,
|
||||
COUNT(CASE WHEN is_active = FALSE THEN 1 END) as inactiveTeams,
|
||||
AVG(member_count) as avgMembersPerTeam
|
||||
FROM (
|
||||
@@ -1278,7 +1353,7 @@ export class CompetitionService extends DatabaseServiceBase {
|
||||
|
||||
// 根據名稱獲取競賽
|
||||
static async getCompetitionByName(name: string): Promise<Competition | null> {
|
||||
const sql = 'SELECT * FROM competitions WHERE name = ? AND is_active = TRUE';
|
||||
const sql = 'SELECT * FROM competitions WHERE name = ? AND is_active = 1';
|
||||
return await db.queryOne<Competition>(sql, [name]);
|
||||
}
|
||||
|
||||
@@ -1313,7 +1388,7 @@ export class CompetitionService extends DatabaseServiceBase {
|
||||
|
||||
// 獲取所有競賽
|
||||
static async getAllCompetitions(): Promise<Competition[]> {
|
||||
const sql = 'SELECT * FROM competitions WHERE is_active = TRUE ORDER BY year DESC, month DESC';
|
||||
const sql = 'SELECT * FROM competitions WHERE is_active = 1 ORDER BY year DESC, month DESC';
|
||||
const competitions = await db.query<any>(sql);
|
||||
|
||||
// 轉換字段名稱以匹配前端期望的格式
|
||||
@@ -1365,7 +1440,7 @@ export class CompetitionService extends DatabaseServiceBase {
|
||||
// 獲取當前競賽
|
||||
static async getCurrentCompetition(): Promise<any | null> {
|
||||
try {
|
||||
const sql = 'SELECT * FROM competitions WHERE is_current = TRUE AND is_active = TRUE LIMIT 1';
|
||||
const sql = 'SELECT * FROM competitions WHERE is_current = 1 AND is_active = 1 LIMIT 1';
|
||||
const competitions = await db.query<any>(sql);
|
||||
|
||||
if (competitions.length > 0) {
|
||||
@@ -1485,7 +1560,7 @@ export class CompetitionService extends DatabaseServiceBase {
|
||||
SELECT j.*, cj.assigned_at
|
||||
FROM competition_judges cj
|
||||
JOIN judges j ON cj.judge_id = j.id
|
||||
WHERE cj.competition_id = ? AND j.is_active = TRUE
|
||||
WHERE cj.competition_id = ? AND j.is_active = 1
|
||||
ORDER BY cj.assigned_at ASC
|
||||
`;
|
||||
return await DatabaseServiceBase.safeQuery(sql, [competitionId]);
|
||||
@@ -1546,7 +1621,7 @@ export class CompetitionService extends DatabaseServiceBase {
|
||||
FROM competition_teams ct
|
||||
JOIN teams t ON ct.team_id = t.id
|
||||
LEFT JOIN users u ON t.leader_id = u.id
|
||||
WHERE ct.competition_id = ? AND t.is_active = TRUE
|
||||
WHERE ct.competition_id = ? AND t.is_active = 1
|
||||
ORDER BY ct.registered_at ASC
|
||||
`;
|
||||
return await DatabaseServiceBase.safeQuery(sql, [competitionId]);
|
||||
@@ -1577,7 +1652,7 @@ export class CompetitionService extends DatabaseServiceBase {
|
||||
FROM apps a
|
||||
LEFT JOIN users u ON a.creator_id = u.id
|
||||
LEFT JOIN teams t ON a.team_id = t.id
|
||||
WHERE a.team_id IN (${placeholders}) AND a.is_active = TRUE
|
||||
WHERE a.team_id IN (${placeholders}) AND a.is_active = 1
|
||||
ORDER BY a.created_at ASC
|
||||
`;
|
||||
apps = await DatabaseServiceBase.safeQuery(sql, teamIds);
|
||||
@@ -1590,7 +1665,7 @@ export class CompetitionService extends DatabaseServiceBase {
|
||||
FROM competition_apps ca
|
||||
JOIN apps a ON ca.app_id = a.id
|
||||
LEFT JOIN users u ON a.creator_id = u.id
|
||||
WHERE ca.competition_id = ? AND a.is_active = TRUE
|
||||
WHERE ca.competition_id = ? AND a.is_active = 1
|
||||
ORDER BY ca.submitted_at ASC
|
||||
`;
|
||||
apps = await DatabaseServiceBase.safeQuery(sql, [competitionId]);
|
||||
@@ -1934,7 +2009,7 @@ export class AppService extends DatabaseServiceBase {
|
||||
u.department as creator_department
|
||||
FROM apps a
|
||||
LEFT JOIN users u ON a.creator_id = u.id
|
||||
WHERE a.id = ? AND a.is_active = TRUE
|
||||
WHERE a.id = ? AND a.is_active = 1
|
||||
`;
|
||||
return await this.queryOne(sql, [appId]);
|
||||
}
|
||||
@@ -1962,7 +2037,7 @@ export class AppService extends DatabaseServiceBase {
|
||||
u.department as creator_department
|
||||
FROM apps a
|
||||
LEFT JOIN users u ON a.creator_id = u.id
|
||||
WHERE a.name = ? AND a.is_active = TRUE
|
||||
WHERE a.name = ? AND a.is_active = 1
|
||||
`;
|
||||
return await this.queryOne(sql, [name]);
|
||||
}
|
||||
@@ -1986,7 +2061,7 @@ export class AppService extends DatabaseServiceBase {
|
||||
// 根據狀態篩選
|
||||
if (status && status !== 'all') {
|
||||
if (status === 'active') {
|
||||
whereConditions.push('a.is_active = TRUE');
|
||||
whereConditions.push('a.is_active = 1');
|
||||
} else if (status === 'inactive') {
|
||||
whereConditions.push('a.is_active = FALSE');
|
||||
}
|
||||
@@ -2058,6 +2133,7 @@ export class AppService extends DatabaseServiceBase {
|
||||
app_url?: string;
|
||||
icon?: string;
|
||||
icon_color?: string;
|
||||
department?: string;
|
||||
}): Promise<{ success: boolean; app?: any; error?: string }> {
|
||||
try {
|
||||
const updateFields = [];
|
||||
@@ -2092,20 +2168,41 @@ export class AppService extends DatabaseServiceBase {
|
||||
params.push(updates.icon_color);
|
||||
}
|
||||
|
||||
if (updateFields.length === 0) {
|
||||
// 如果沒有要更新的欄位,檢查是否需要更新部門
|
||||
if (updateFields.length === 0 && !updates.department) {
|
||||
return { success: false, error: '沒有要更新的欄位' };
|
||||
}
|
||||
|
||||
// 如果需要更新部門,先更新創建者的部門
|
||||
if (updates.department) {
|
||||
// 先獲取應用的創建者 ID
|
||||
const appSql = 'SELECT creator_id FROM apps WHERE id = ? AND is_active = 1';
|
||||
const appResult = await this.query(appSql, [appId]);
|
||||
|
||||
if (appResult.length === 0) {
|
||||
return { success: false, error: '應用不存在' };
|
||||
}
|
||||
|
||||
const creatorId = appResult[0].creator_id;
|
||||
|
||||
// 更新創建者的部門
|
||||
const userUpdateSql = 'UPDATE users SET department = ? WHERE id = ?';
|
||||
await this.query(userUpdateSql, [updates.department, creatorId]);
|
||||
}
|
||||
|
||||
// 如果有其他欄位需要更新
|
||||
if (updateFields.length > 0) {
|
||||
updateFields.push('updated_at = NOW()');
|
||||
params.push(appId);
|
||||
|
||||
const sql = `
|
||||
UPDATE apps
|
||||
SET ${updateFields.join(', ')}
|
||||
WHERE id = ? AND is_active = TRUE
|
||||
WHERE id = ? AND is_active = 1
|
||||
`;
|
||||
|
||||
await this.query(sql, params);
|
||||
}
|
||||
|
||||
// 獲取更新後的應用
|
||||
const updatedApp = await this.getAppById(appId);
|
||||
@@ -2173,7 +2270,7 @@ export class AppService extends DatabaseServiceBase {
|
||||
const sql = `
|
||||
SELECT
|
||||
COUNT(*) as total_apps,
|
||||
COUNT(CASE WHEN is_active = TRUE THEN 1 END) as active_apps,
|
||||
COUNT(CASE WHEN is_active = 1 THEN 1 END) as active_apps,
|
||||
COUNT(CASE WHEN is_active = FALSE THEN 1 END) as inactive_apps,
|
||||
COALESCE(SUM(views_count), 0) as total_views,
|
||||
COALESCE(SUM(likes_count), 0) as total_likes,
|
||||
@@ -2605,7 +2702,7 @@ export class AppService extends DatabaseServiceBase {
|
||||
COUNT(DISTINCT a.id) as count
|
||||
FROM apps a
|
||||
JOIN users u ON a.creator_id = u.id
|
||||
WHERE a.is_active = TRUE
|
||||
WHERE a.is_active = 1
|
||||
GROUP BY u.department
|
||||
ORDER BY count DESC, u.department ASC
|
||||
`;
|
||||
@@ -2629,7 +2726,7 @@ export class AppService extends DatabaseServiceBase {
|
||||
type,
|
||||
COUNT(*) as count
|
||||
FROM apps
|
||||
WHERE is_active = TRUE
|
||||
WHERE is_active = 1
|
||||
GROUP BY type
|
||||
ORDER BY count DESC, type ASC
|
||||
`;
|
||||
@@ -2653,7 +2750,7 @@ export class AppService extends DatabaseServiceBase {
|
||||
category,
|
||||
COUNT(*) as count
|
||||
FROM apps
|
||||
WHERE is_active = TRUE
|
||||
WHERE is_active = 1
|
||||
GROUP BY category
|
||||
ORDER BY count DESC, category ASC
|
||||
`;
|
||||
@@ -2847,7 +2944,7 @@ export class AppService extends DatabaseServiceBase {
|
||||
const appStatsSql = `
|
||||
SELECT
|
||||
COUNT(*) as total_apps,
|
||||
COUNT(CASE WHEN is_active = TRUE THEN 1 END) as active_apps,
|
||||
COUNT(CASE WHEN is_active = 1 THEN 1 END) as active_apps,
|
||||
COUNT(CASE WHEN is_active = FALSE THEN 1 END) as inactive_apps,
|
||||
COUNT(CASE WHEN created_at >= DATE_SUB(CURDATE(), INTERVAL 30 DAY) THEN 1 END) as new_apps_this_month,
|
||||
COALESCE(SUM(views_count), 0) as total_views,
|
||||
@@ -2997,7 +3094,7 @@ export class AppService extends DatabaseServiceBase {
|
||||
SELECT COUNT(*) as total
|
||||
FROM user_favorites uf
|
||||
JOIN apps a ON uf.app_id = a.id
|
||||
WHERE uf.user_id = ? AND a.is_active = TRUE
|
||||
WHERE uf.user_id = ? AND a.is_active = 1
|
||||
`;
|
||||
const countResult = await this.queryOne(countSql, [userId]);
|
||||
const total = countResult?.total || 0;
|
||||
@@ -3022,7 +3119,7 @@ export class AppService extends DatabaseServiceBase {
|
||||
FROM user_favorites uf
|
||||
JOIN apps a ON uf.app_id = a.id
|
||||
LEFT JOIN users u ON a.creator_id = u.id
|
||||
WHERE uf.user_id = ? AND a.is_active = TRUE
|
||||
WHERE uf.user_id = ? AND a.is_active = 1
|
||||
ORDER BY uf.created_at DESC
|
||||
LIMIT ${limit} OFFSET ${offset}
|
||||
`;
|
||||
@@ -3334,7 +3431,7 @@ export class AppService extends DatabaseServiceBase {
|
||||
for (const activity of activities) {
|
||||
try {
|
||||
// 嘗試從應用表獲取類別
|
||||
const appSql = 'SELECT type FROM apps WHERE id = ? AND is_active = TRUE';
|
||||
const appSql = 'SELECT type FROM apps WHERE id = ? AND is_active = 1';
|
||||
const appResult = await this.query(appSql, [activity.resource_id]);
|
||||
|
||||
let category = '未分類';
|
||||
|
Reference in New Issue
Block a user