123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309 |
- import { db } from '@/lib/db';
- import { users, userActivities } from '@/lib/schema';
- import { eq } from 'drizzle-orm';
- export interface CreditDeductionResult {
- success: boolean;
- message: string;
- user?: {
- id: string;
- credits: number;
- };
- credits?: {
- deducted: number;
- remaining: number;
- };
- }
- export interface ActivityRecord {
- id: string;
- type: string;
- description: string;
- creditAmount: number | null;
- metadata: string | null;
- createdAt: Date | null;
- }
- // 扣除用户积分
- export async function deductCredits(
- userId: string,
- amount: number,
- description: string,
- metadata?: any
- ): Promise<CreditDeductionResult> {
- try {
- // 首先获取用户当前积分
- const [user] = await db.select().from(users).where(eq(users.id, userId));
-
- if (!user) {
- return {
- success: false,
- message: '用户不存在'
- };
- }
- // 计算总积分(订阅积分 + 永久积分)
- const totalCredits = (user.subscriptionCredits || 0) + (user.credits || 0);
-
- // 检查积分是否足够
- if (totalCredits < amount) {
- return {
- success: false,
- message: '积分不足'
- };
- }
- // 优先使用订阅积分
- let remainingAmount = amount;
- let newSubscriptionCredits = user.subscriptionCredits || 0;
- let newPermanentCredits = user.credits || 0;
-
- // 先扣除订阅积分
- if (remainingAmount > 0 && newSubscriptionCredits > 0) {
- const deductFromSubscription = Math.min(remainingAmount, newSubscriptionCredits);
- newSubscriptionCredits -= deductFromSubscription;
- remainingAmount -= deductFromSubscription;
- }
-
- // 如果还有剩余需要扣除,则从永久积分中扣除
- if (remainingAmount > 0) {
- newPermanentCredits -= remainingAmount;
- }
- // 更新用户积分
- await db
- .update(users)
- .set({
- credits: newPermanentCredits,
- subscriptionCredits: newSubscriptionCredits,
- updatedAt: new Date()
- })
- .where(eq(users.id, userId));
- // 记录活动
- await db.insert(userActivities).values({
- userId: userId,
- type: 'credit_deduct',
- description: description,
- creditAmount: -amount,
- metadata: metadata ? JSON.stringify({
- ...metadata,
- deductedFromSubscription: (user.subscriptionCredits || 0) - newSubscriptionCredits,
- deductedFromPermanent: (user.credits || 0) - newPermanentCredits
- }) : null
- });
- return {
- success: true,
- message: '积分扣除成功',
- user: {
- id: userId,
- credits: newPermanentCredits + newSubscriptionCredits
- },
- credits: {
- deducted: amount,
- remaining: newPermanentCredits + newSubscriptionCredits
- }
- };
- } catch (error) {
- console.error('扣除积分失败:', error);
- return {
- success: false,
- message: '积分扣除失败'
- };
- }
- }
- // 增加用户积分
- export async function addCredits(
- userId: string,
- amount: number,
- description: string,
- metadata?: any,
- creditType: 'permanent' | 'subscription' = 'permanent'
- ): Promise<CreditDeductionResult> {
- try {
- // 首先获取用户当前积分
- const [user] = await db.select().from(users).where(eq(users.id, userId));
-
- if (!user) {
- return {
- success: false,
- message: '用户不存在'
- };
- }
- // 根据积分类型增加相应的积分
- let updateData: any = { updatedAt: new Date() };
-
- if (creditType === 'subscription') {
- // 添加订阅积分
- const newSubscriptionCredits = (user.subscriptionCredits || 0) + amount;
- updateData.subscriptionCredits = newSubscriptionCredits;
- } else {
- // 添加永久积分
- const newCredits = user.credits + amount;
- updateData.credits = newCredits;
- }
- await db
- .update(users)
- .set(updateData)
- .where(eq(users.id, userId));
- // 记录活动
- await db.insert(userActivities).values({
- userId: userId,
- type: 'credit_add',
- description: description,
- creditAmount: amount,
- metadata: metadata ? JSON.stringify({
- ...metadata,
- creditType: creditType
- }) : JSON.stringify({ creditType: creditType })
- });
- // 计算总积分
- const totalCredits = (creditType === 'subscription'
- ? (user.subscriptionCredits || 0) + amount + user.credits
- : user.credits + amount + (user.subscriptionCredits || 0)
- );
- return {
- success: true,
- message: '积分增加成功',
- user: {
- id: userId,
- credits: totalCredits
- },
- credits: {
- deducted: -amount, // 负数表示增加
- remaining: totalCredits
- }
- };
- } catch (error) {
- console.error('增加积分失败:', error);
- return {
- success: false,
- message: '积分增加失败'
- };
- }
- }
- // 记录用户活动(不涉及积分变化)
- export async function recordActivity(
- userId: string,
- type: string,
- description: string,
- metadata?: Record<string, any>
- ): Promise<boolean> {
- try {
- await db.insert(userActivities).values({
- userId: userId,
- type: type,
- description: description,
- creditAmount: null,
- metadata: metadata ? JSON.stringify(metadata) : null,
- });
- return true;
- } catch (error) {
- console.error('记录用户活动失败:', error);
- return false;
- }
- }
- // 获取用户活动记录
- export async function getUserActivities(
- userId: string,
- limit: number = 20,
- offset: number = 0
- ): Promise<ActivityRecord[]> {
- try {
- const activities = await db.query.userActivities.findMany({
- where: eq(userActivities.userId, userId),
- orderBy: (userActivities, { desc }) => [desc(userActivities.createdAt)],
- limit: limit,
- offset: offset,
- });
- return activities;
- } catch (error) {
- console.error('获取用户活动失败:', error);
- return [];
- }
- }
- // 清零用户订阅积分(订阅过期时调用)
- export async function clearSubscriptionCredits(
- userId: string,
- reason: string = 'credit_description.subscription_expired'
- ): Promise<CreditDeductionResult> {
- try {
- // 首先获取用户当前积分
- const [user] = await db.select().from(users).where(eq(users.id, userId));
-
- if (!user) {
- return {
- success: false,
- message: '用户不存在'
- };
- }
- const clearedAmount = user.subscriptionCredits || 0;
-
- if (clearedAmount === 0) {
- return {
- success: true,
- message: '订阅积分已为零,无需清零',
- user: {
- id: userId,
- credits: user.credits
- },
- credits: {
- deducted: 0,
- remaining: user.credits
- }
- };
- }
- // 清零订阅积分
- await db
- .update(users)
- .set({
- subscriptionCredits: 0,
- updatedAt: new Date()
- })
- .where(eq(users.id, userId));
- // 记录活动
- await db.insert(userActivities).values({
- userId: userId,
- type: 'subscription_expired',
- description: reason,
- creditAmount: -clearedAmount,
- metadata: JSON.stringify({
- clearedSubscriptionCredits: clearedAmount,
- remainingPermanentCredits: user.credits
- })
- });
- return {
- success: true,
- message: '订阅积分已清零',
- user: {
- id: userId,
- credits: user.credits // 只保留永久积分
- },
- credits: {
- deducted: clearedAmount,
- remaining: user.credits
- }
- };
- } catch (error) {
- console.error('清零订阅积分失败:', error);
- return {
- success: false,
- message: '清零订阅积分失败'
- };
- }
- }
|