mirror of
https://github.com/Wei-Shaw/claude-relay-service.git
synced 2026-01-23 00:53:33 +00:00
refactor: standardize code formatting and linting configuration
- Replace .eslintrc.js with .eslintrc.cjs for better ES module compatibility - Add .prettierrc configuration for consistent code formatting - Update package.json with new lint and format scripts - Add nodemon.json for development hot reloading configuration - Standardize code formatting across all JavaScript and Vue files - Update web admin SPA with improved linting rules and formatting - Add prettier configuration to web admin SPA 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
const { v4: uuidv4 } = require('uuid');
|
||||
const logger = require('../utils/logger');
|
||||
const redis = require('../models/redis');
|
||||
const { v4: uuidv4 } = require('uuid')
|
||||
const logger = require('../utils/logger')
|
||||
const redis = require('../models/redis')
|
||||
|
||||
class AccountGroupService {
|
||||
constructor() {
|
||||
this.GROUPS_KEY = 'account_groups';
|
||||
this.GROUP_PREFIX = 'account_group:';
|
||||
this.GROUP_MEMBERS_PREFIX = 'account_group_members:';
|
||||
this.GROUPS_KEY = 'account_groups'
|
||||
this.GROUP_PREFIX = 'account_group:'
|
||||
this.GROUP_MEMBERS_PREFIX = 'account_group_members:'
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -19,22 +19,22 @@ class AccountGroupService {
|
||||
*/
|
||||
async createGroup(groupData) {
|
||||
try {
|
||||
const { name, platform, description = '' } = groupData;
|
||||
|
||||
const { name, platform, description = '' } = groupData
|
||||
|
||||
// 验证必填字段
|
||||
if (!name || !platform) {
|
||||
throw new Error('分组名称和平台类型为必填项');
|
||||
throw new Error('分组名称和平台类型为必填项')
|
||||
}
|
||||
|
||||
|
||||
// 验证平台类型
|
||||
if (!['claude', 'gemini'].includes(platform)) {
|
||||
throw new Error('平台类型必须是 claude 或 gemini');
|
||||
throw new Error('平台类型必须是 claude 或 gemini')
|
||||
}
|
||||
|
||||
const client = redis.getClientSafe();
|
||||
const groupId = uuidv4();
|
||||
const now = new Date().toISOString();
|
||||
|
||||
|
||||
const client = redis.getClientSafe()
|
||||
const groupId = uuidv4()
|
||||
const now = new Date().toISOString()
|
||||
|
||||
const group = {
|
||||
id: groupId,
|
||||
name,
|
||||
@@ -42,20 +42,20 @@ class AccountGroupService {
|
||||
description,
|
||||
createdAt: now,
|
||||
updatedAt: now
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// 保存分组数据
|
||||
await client.hmset(`${this.GROUP_PREFIX}${groupId}`, group);
|
||||
|
||||
await client.hmset(`${this.GROUP_PREFIX}${groupId}`, group)
|
||||
|
||||
// 添加到分组集合
|
||||
await client.sadd(this.GROUPS_KEY, groupId);
|
||||
|
||||
logger.success(`✅ 创建账户分组成功: ${name} (${platform})`);
|
||||
|
||||
return group;
|
||||
await client.sadd(this.GROUPS_KEY, groupId)
|
||||
|
||||
logger.success(`✅ 创建账户分组成功: ${name} (${platform})`)
|
||||
|
||||
return group
|
||||
} catch (error) {
|
||||
logger.error('❌ 创建账户分组失败:', error);
|
||||
throw error;
|
||||
logger.error('❌ 创建账户分组失败:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,46 +67,46 @@ class AccountGroupService {
|
||||
*/
|
||||
async updateGroup(groupId, updates) {
|
||||
try {
|
||||
const client = redis.getClientSafe();
|
||||
const groupKey = `${this.GROUP_PREFIX}${groupId}`;
|
||||
|
||||
const client = redis.getClientSafe()
|
||||
const groupKey = `${this.GROUP_PREFIX}${groupId}`
|
||||
|
||||
// 检查分组是否存在
|
||||
const exists = await client.exists(groupKey);
|
||||
const exists = await client.exists(groupKey)
|
||||
if (!exists) {
|
||||
throw new Error('分组不存在');
|
||||
throw new Error('分组不存在')
|
||||
}
|
||||
|
||||
|
||||
// 获取现有分组数据
|
||||
const existingGroup = await client.hgetall(groupKey);
|
||||
|
||||
const existingGroup = await client.hgetall(groupKey)
|
||||
|
||||
// 不允许修改平台类型
|
||||
if (updates.platform && updates.platform !== existingGroup.platform) {
|
||||
throw new Error('不能修改分组的平台类型');
|
||||
throw new Error('不能修改分组的平台类型')
|
||||
}
|
||||
|
||||
|
||||
// 准备更新数据
|
||||
const updateData = {
|
||||
...updates,
|
||||
updatedAt: new Date().toISOString()
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// 移除不允许修改的字段
|
||||
delete updateData.id;
|
||||
delete updateData.platform;
|
||||
delete updateData.createdAt;
|
||||
|
||||
delete updateData.id
|
||||
delete updateData.platform
|
||||
delete updateData.createdAt
|
||||
|
||||
// 更新分组
|
||||
await client.hmset(groupKey, updateData);
|
||||
|
||||
await client.hmset(groupKey, updateData)
|
||||
|
||||
// 返回更新后的完整数据
|
||||
const updatedGroup = await client.hgetall(groupKey);
|
||||
|
||||
logger.success(`✅ 更新账户分组成功: ${updatedGroup.name}`);
|
||||
|
||||
return updatedGroup;
|
||||
const updatedGroup = await client.hgetall(groupKey)
|
||||
|
||||
logger.success(`✅ 更新账户分组成功: ${updatedGroup.name}`)
|
||||
|
||||
return updatedGroup
|
||||
} catch (error) {
|
||||
logger.error('❌ 更新账户分组失败:', error);
|
||||
throw error;
|
||||
logger.error('❌ 更新账户分组失败:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,37 +116,37 @@ class AccountGroupService {
|
||||
*/
|
||||
async deleteGroup(groupId) {
|
||||
try {
|
||||
const client = redis.getClientSafe();
|
||||
|
||||
const client = redis.getClientSafe()
|
||||
|
||||
// 检查分组是否存在
|
||||
const group = await this.getGroup(groupId);
|
||||
const group = await this.getGroup(groupId)
|
||||
if (!group) {
|
||||
throw new Error('分组不存在');
|
||||
throw new Error('分组不存在')
|
||||
}
|
||||
|
||||
|
||||
// 检查分组是否为空
|
||||
const members = await this.getGroupMembers(groupId);
|
||||
const members = await this.getGroupMembers(groupId)
|
||||
if (members.length > 0) {
|
||||
throw new Error('分组内还有账户,无法删除');
|
||||
throw new Error('分组内还有账户,无法删除')
|
||||
}
|
||||
|
||||
|
||||
// 检查是否有API Key绑定此分组
|
||||
const boundApiKeys = await this.getApiKeysUsingGroup(groupId);
|
||||
const boundApiKeys = await this.getApiKeysUsingGroup(groupId)
|
||||
if (boundApiKeys.length > 0) {
|
||||
throw new Error('还有API Key使用此分组,无法删除');
|
||||
throw new Error('还有API Key使用此分组,无法删除')
|
||||
}
|
||||
|
||||
|
||||
// 删除分组数据
|
||||
await client.del(`${this.GROUP_PREFIX}${groupId}`);
|
||||
await client.del(`${this.GROUP_MEMBERS_PREFIX}${groupId}`);
|
||||
|
||||
await client.del(`${this.GROUP_PREFIX}${groupId}`)
|
||||
await client.del(`${this.GROUP_MEMBERS_PREFIX}${groupId}`)
|
||||
|
||||
// 从分组集合中移除
|
||||
await client.srem(this.GROUPS_KEY, groupId);
|
||||
|
||||
logger.success(`✅ 删除账户分组成功: ${group.name}`);
|
||||
await client.srem(this.GROUPS_KEY, groupId)
|
||||
|
||||
logger.success(`✅ 删除账户分组成功: ${group.name}`)
|
||||
} catch (error) {
|
||||
logger.error('❌ 删除账户分组失败:', error);
|
||||
throw error;
|
||||
logger.error('❌ 删除账户分组失败:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,23 +157,23 @@ class AccountGroupService {
|
||||
*/
|
||||
async getGroup(groupId) {
|
||||
try {
|
||||
const client = redis.getClientSafe();
|
||||
const groupData = await client.hgetall(`${this.GROUP_PREFIX}${groupId}`);
|
||||
|
||||
const client = redis.getClientSafe()
|
||||
const groupData = await client.hgetall(`${this.GROUP_PREFIX}${groupId}`)
|
||||
|
||||
if (!groupData || Object.keys(groupData).length === 0) {
|
||||
return null;
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
// 获取成员数量
|
||||
const memberCount = await client.scard(`${this.GROUP_MEMBERS_PREFIX}${groupId}`);
|
||||
|
||||
const memberCount = await client.scard(`${this.GROUP_MEMBERS_PREFIX}${groupId}`)
|
||||
|
||||
return {
|
||||
...groupData,
|
||||
memberCount: memberCount || 0
|
||||
};
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error('❌ 获取分组详情失败:', error);
|
||||
throw error;
|
||||
logger.error('❌ 获取分组详情失败:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,27 +184,27 @@ class AccountGroupService {
|
||||
*/
|
||||
async getAllGroups(platform = null) {
|
||||
try {
|
||||
const client = redis.getClientSafe();
|
||||
const groupIds = await client.smembers(this.GROUPS_KEY);
|
||||
|
||||
const groups = [];
|
||||
const client = redis.getClientSafe()
|
||||
const groupIds = await client.smembers(this.GROUPS_KEY)
|
||||
|
||||
const groups = []
|
||||
for (const groupId of groupIds) {
|
||||
const group = await this.getGroup(groupId);
|
||||
const group = await this.getGroup(groupId)
|
||||
if (group) {
|
||||
// 如果指定了平台,进行筛选
|
||||
if (!platform || group.platform === platform) {
|
||||
groups.push(group);
|
||||
groups.push(group)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 按创建时间倒序排序
|
||||
groups.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt));
|
||||
|
||||
return groups;
|
||||
groups.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt))
|
||||
|
||||
return groups
|
||||
} catch (error) {
|
||||
logger.error('❌ 获取分组列表失败:', error);
|
||||
throw error;
|
||||
logger.error('❌ 获取分组列表失败:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,27 +216,28 @@ class AccountGroupService {
|
||||
*/
|
||||
async addAccountToGroup(accountId, groupId, accountPlatform) {
|
||||
try {
|
||||
const client = redis.getClientSafe();
|
||||
|
||||
const client = redis.getClientSafe()
|
||||
|
||||
// 获取分组信息
|
||||
const group = await this.getGroup(groupId);
|
||||
const group = await this.getGroup(groupId)
|
||||
if (!group) {
|
||||
throw new Error('分组不存在');
|
||||
throw new Error('分组不存在')
|
||||
}
|
||||
|
||||
|
||||
// 验证平台一致性 (Claude和Claude Console视为同一平台)
|
||||
const normalizedAccountPlatform = accountPlatform === 'claude-console' ? 'claude' : accountPlatform;
|
||||
const normalizedAccountPlatform =
|
||||
accountPlatform === 'claude-console' ? 'claude' : accountPlatform
|
||||
if (normalizedAccountPlatform !== group.platform) {
|
||||
throw new Error('账户平台与分组平台不匹配');
|
||||
throw new Error('账户平台与分组平台不匹配')
|
||||
}
|
||||
|
||||
|
||||
// 添加到分组成员集合
|
||||
await client.sadd(`${this.GROUP_MEMBERS_PREFIX}${groupId}`, accountId);
|
||||
|
||||
logger.success(`✅ 添加账户到分组成功: ${accountId} -> ${group.name}`);
|
||||
await client.sadd(`${this.GROUP_MEMBERS_PREFIX}${groupId}`, accountId)
|
||||
|
||||
logger.success(`✅ 添加账户到分组成功: ${accountId} -> ${group.name}`)
|
||||
} catch (error) {
|
||||
logger.error('❌ 添加账户到分组失败:', error);
|
||||
throw error;
|
||||
logger.error('❌ 添加账户到分组失败:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
@@ -247,15 +248,15 @@ class AccountGroupService {
|
||||
*/
|
||||
async removeAccountFromGroup(accountId, groupId) {
|
||||
try {
|
||||
const client = redis.getClientSafe();
|
||||
|
||||
const client = redis.getClientSafe()
|
||||
|
||||
// 从分组成员集合中移除
|
||||
await client.srem(`${this.GROUP_MEMBERS_PREFIX}${groupId}`, accountId);
|
||||
|
||||
logger.success(`✅ 从分组移除账户成功: ${accountId}`);
|
||||
await client.srem(`${this.GROUP_MEMBERS_PREFIX}${groupId}`, accountId)
|
||||
|
||||
logger.success(`✅ 从分组移除账户成功: ${accountId}`)
|
||||
} catch (error) {
|
||||
logger.error('❌ 从分组移除账户失败:', error);
|
||||
throw error;
|
||||
logger.error('❌ 从分组移除账户失败:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
@@ -266,12 +267,12 @@ class AccountGroupService {
|
||||
*/
|
||||
async getGroupMembers(groupId) {
|
||||
try {
|
||||
const client = redis.getClientSafe();
|
||||
const members = await client.smembers(`${this.GROUP_MEMBERS_PREFIX}${groupId}`);
|
||||
return members || [];
|
||||
const client = redis.getClientSafe()
|
||||
const members = await client.smembers(`${this.GROUP_MEMBERS_PREFIX}${groupId}`)
|
||||
return members || []
|
||||
} catch (error) {
|
||||
logger.error('❌ 获取分组成员失败:', error);
|
||||
throw error;
|
||||
logger.error('❌ 获取分组成员失败:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,11 +283,11 @@ class AccountGroupService {
|
||||
*/
|
||||
async isGroupEmpty(groupId) {
|
||||
try {
|
||||
const members = await this.getGroupMembers(groupId);
|
||||
return members.length === 0;
|
||||
const members = await this.getGroupMembers(groupId)
|
||||
return members.length === 0
|
||||
} catch (error) {
|
||||
logger.error('❌ 检查分组是否为空失败:', error);
|
||||
throw error;
|
||||
logger.error('❌ 检查分组是否为空失败:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
@@ -297,29 +298,30 @@ class AccountGroupService {
|
||||
*/
|
||||
async getApiKeysUsingGroup(groupId) {
|
||||
try {
|
||||
const client = redis.getClientSafe();
|
||||
const groupKey = `group:${groupId}`;
|
||||
|
||||
const client = redis.getClientSafe()
|
||||
const groupKey = `group:${groupId}`
|
||||
|
||||
// 获取所有API Key
|
||||
const apiKeyIds = await client.smembers('api_keys');
|
||||
const boundApiKeys = [];
|
||||
|
||||
const apiKeyIds = await client.smembers('api_keys')
|
||||
const boundApiKeys = []
|
||||
|
||||
for (const keyId of apiKeyIds) {
|
||||
const keyData = await client.hgetall(`api_key:${keyId}`);
|
||||
if (keyData &&
|
||||
(keyData.claudeAccountId === groupKey ||
|
||||
keyData.geminiAccountId === groupKey)) {
|
||||
const keyData = await client.hgetall(`api_key:${keyId}`)
|
||||
if (
|
||||
keyData &&
|
||||
(keyData.claudeAccountId === groupKey || keyData.geminiAccountId === groupKey)
|
||||
) {
|
||||
boundApiKeys.push({
|
||||
id: keyId,
|
||||
name: keyData.name
|
||||
});
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return boundApiKeys;
|
||||
|
||||
return boundApiKeys
|
||||
} catch (error) {
|
||||
logger.error('❌ 获取使用分组的API Key失败:', error);
|
||||
throw error;
|
||||
logger.error('❌ 获取使用分组的API Key失败:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
@@ -330,22 +332,22 @@ class AccountGroupService {
|
||||
*/
|
||||
async getAccountGroup(accountId) {
|
||||
try {
|
||||
const client = redis.getClientSafe();
|
||||
const allGroupIds = await client.smembers(this.GROUPS_KEY);
|
||||
|
||||
const client = redis.getClientSafe()
|
||||
const allGroupIds = await client.smembers(this.GROUPS_KEY)
|
||||
|
||||
for (const groupId of allGroupIds) {
|
||||
const isMember = await client.sismember(`${this.GROUP_MEMBERS_PREFIX}${groupId}`, accountId);
|
||||
const isMember = await client.sismember(`${this.GROUP_MEMBERS_PREFIX}${groupId}`, accountId)
|
||||
if (isMember) {
|
||||
return await this.getGroup(groupId);
|
||||
return await this.getGroup(groupId)
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
return null
|
||||
} catch (error) {
|
||||
logger.error('❌ 获取账户所属分组失败:', error);
|
||||
throw error;
|
||||
logger.error('❌ 获取账户所属分组失败:', error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new AccountGroupService();
|
||||
module.exports = new AccountGroupService()
|
||||
|
||||
Reference in New Issue
Block a user