2025-10-10

项目收藏
This commit is contained in:
2025-10-10 14:15:00 +08:00
parent 0db107f051
commit a7dda9dd65
26 changed files with 312 additions and 38 deletions

View File

@@ -1,6 +1,6 @@
import {Body, Controller, Delete, Get, NotFoundException, Param, Patch, Post, Query} from '@nestjs/common';
import {ProgramService} from "../service";
import {ProgramEntity, ProgramGroupEntity, UsersEntity} from "../entity";
import {ProgramCollectEntity, ProgramEntity, ProgramGroupEntity, UsersEntity} from "../entity";
@Controller('program')
export class ProgramController {
@@ -22,6 +22,38 @@ export class ProgramController {
return this.programService.isChat(group);
}
// 收藏
@Post("collect")
collect(@Body() collect: ProgramCollectEntity) {
return this.programService.collect(collect);
}
// 取消收藏
@Post("uncollect")
unCollect(@Body() collect: ProgramCollectEntity) {
return this.programService.uncollect(collect);
}
// 收藏列表
@Get("collectList")
collectList(@Query() collect: ProgramCollectEntity) {
return this.programService.collectList(collect);
}
// 是否收藏
@Get("isCollect")
isCollect(@Query() collect: ProgramCollectEntity) {
return this.programService.isCollect(collect);
}
// 项目
// 随机选择项目返回(programId)
@Get("/random")
random(@Query() collect: ProgramCollectEntity){
return this.programService.random(collect);
}
@Post()
add(@Body() program: ProgramEntity) {
return this.programService.add(program);

View File

@@ -1,3 +1,4 @@
export * from './program.entity';
export * from './users.entity';
export * from './programGroup.entity'
export * from './programGroup.entity'
export * from './programCollect.entity'

View File

@@ -0,0 +1,29 @@
import { Column, Entity, PrimaryGeneratedColumn } from "typeorm";
import {format} from "date-fns";
@Entity("program_collect", { schema: "test" })
export class ProgramCollectEntity {
@PrimaryGeneratedColumn({ type: "int", name: "id", comment: "自增长ID" })
id: number;
@Column("int", { name: "user_id", comment: "用户ID" })
userId: number;
@Column("int", { name: "program_id", comment: "项目ID" })
programId: number;
@Column("datetime", {
name: "create_time",
comment: "收藏时间",
default: () => "CURRENT_TIMESTAMP",
transformer: {
to: (value: Date) => value,
from: (value: string) => value ? format(value, "yyyy-MM-dd") : null
}
})
createTime: Date;
// 虚拟字段
page: number;
size: number;
}

View File

@@ -10,9 +10,9 @@ import { RegionalAgents } from "./RegionalAgents";
import { Users } from "./Users";
import { RegistrationCodes } from "./RegistrationCodes";
@Index("unique_agent_merchant", ["agentId", "merchantId"], { unique: true })
@Index("merchant_id", ["merchantId"], {})
@Index("registration_code_id", ["registrationCodeId"], {})
@Index("unique_agent_merchant", ["agentId", "merchantId"], { unique: true })
@Entity("agent_merchants", { schema: "test" })
export class AgentMerchants {
@PrimaryGeneratedColumn({ type: "int", name: "id" })

View File

@@ -11,10 +11,10 @@ import { Users } from "./Users";
import { UserAnnouncementReads } from "./UserAnnouncementReads";
@Index("created_by", ["createdBy"], {})
@Index("idx_created_at", ["createdAt"], {})
@Index("idx_publish_time", ["publishTime"], {})
@Index("idx_status", ["status"], {})
@Index("idx_type", ["type"], {})
@Index("idx_publish_time", ["publishTime"], {})
@Index("idx_created_at", ["createdAt"], {})
@Entity("announcements", { schema: "test" })
export class Announcements {
@PrimaryGeneratedColumn({ type: "int", name: "id" })

View File

@@ -1,7 +1,7 @@
import { Column, Entity, Index, PrimaryGeneratedColumn } from "typeorm";
@Index("idx_user_id", ["userId"], {})
@Index("idx_created_at", ["createdAt"], {})
@Index("idx_user_id", ["userId"], {})
@Entity("balance_fix_log", { schema: "test" })
export class BalanceFixLog {
@PrimaryGeneratedColumn({ type: "int", name: "id" })

View File

@@ -1,10 +1,10 @@
import { Column, Entity, Index, PrimaryGeneratedColumn } from "typeorm";
@Index("product_id", ["productId"], {})
@Index("specification_id", ["specificationId"], {})
@Index("unique_user_product_spec", ["userId", "productId", "specificationId"], {
unique: true,
})
@Index("product_id", ["productId"], {})
@Index("specification_id", ["specificationId"], {})
@Entity("cart_items", { schema: "test" })
export class CartItems {
@PrimaryGeneratedColumn({ type: "int", name: "id" })

View File

@@ -1,8 +1,8 @@
import { Column, Entity, Index, PrimaryGeneratedColumn } from "typeorm";
@Index("code", ["code"], { unique: true })
@Index("idx_parent_code", ["parentCode"], {})
@Index("idx_level", ["level"], {})
@Index("idx_parent_code", ["parentCode"], {})
@Entity("china_regions", { schema: "test" })
export class ChinaRegions {
@PrimaryGeneratedColumn({ type: "int", name: "id" })

View File

@@ -10,8 +10,8 @@ import { MatchingOrders } from "./MatchingOrders";
import { Users } from "./Users";
import { Transfers } from "./Transfers";
@Index("matching_order_id", ["matchingOrderId"], {})
@Index("from_user_id", ["fromUserId"], {})
@Index("matching_order_id", ["matchingOrderId"], {})
@Index("to_user_id", ["toUserId"], {})
@Index("transfer_id", ["transferId"], {})
@Entity("order_allocations", { schema: "test" })

View File

@@ -1,9 +1,9 @@
import { Column, Entity, Index, PrimaryGeneratedColumn } from "typeorm";
@Index("uk_out_trade_no", ["outTradeNo"], { unique: true })
@Index("idx_user_id", ["userId"], {})
@Index("idx_status", ["status"], {})
@Index("idx_created_at", ["createdAt"], {})
@Index("idx_status", ["status"], {})
@Index("idx_user_id", ["userId"], {})
@Index("uk_out_trade_no", ["outTradeNo"], { unique: true })
@Entity("payment_orders", { schema: "test" })
export class PaymentOrders {
@PrimaryGeneratedColumn({ type: "int", name: "id", comment: "订单ID" })

View File

@@ -9,8 +9,8 @@ import {
import { Users } from "./Users";
import { Orders } from "./Orders";
@Index("user_id", ["userId"], {})
@Index("order_id", ["orderId"], {})
@Index("user_id", ["userId"], {})
@Entity("points_history", { schema: "test" })
export class PointsHistory {
@PrimaryGeneratedColumn({ type: "int", name: "id" })

View File

@@ -9,8 +9,8 @@ import {
import { Users } from "./Users";
import { Products } from "./Products";
@Index("unique_user_product", ["userId", "productId"], { unique: true })
@Index("product_id", ["productId"], {})
@Index("unique_user_product", ["userId", "productId"], { unique: true })
@Entity("product_favorites", { schema: "test" })
export class ProductFavorites {
@PrimaryGeneratedColumn({ type: "int", name: "id" })

View File

@@ -10,9 +10,9 @@ import { Products } from "./Products";
import { Users } from "./Users";
import { Orders } from "./Orders";
@Index("order_id", ["orderId"], {})
@Index("product_id", ["productId"], {})
@Index("user_id", ["userId"], {})
@Index("order_id", ["orderId"], {})
@Entity("product_reviews", { schema: "test" })
export class ProductReviews {
@PrimaryGeneratedColumn({ type: "int", name: "id" })

View File

@@ -8,11 +8,11 @@ import {
} from "typeorm";
import { Products } from "./Products";
@Index("idx_product_status", ["productId", "status"], {})
@Index("idx_sku_code", ["skuCode"], {})
@Index("unique_product_combination", ["productId", "combinationKey"], {
unique: true,
})
@Index("idx_product_status", ["productId", "status"], {})
@Index("idx_sku_code", ["skuCode"], {})
@Entity("product_spec_combinations", { schema: "test" })
export class ProductSpecCombinations {
@PrimaryGeneratedColumn({ type: "int", name: "id" })

View File

@@ -9,10 +9,10 @@ import {
import { Products } from "./Products";
import { SpecNames } from "./SpecNames";
@Index("spec_name_id", ["specNameId"], {})
@Index("unique_product_spec_name", ["productId", "specNameId"], {
unique: true,
})
@Index("spec_name_id", ["specNameId"], {})
@Entity("product_spec_names", { schema: "test" })
export class ProductSpecNames {
@PrimaryGeneratedColumn({ type: "int", name: "id" })

View File

@@ -8,12 +8,8 @@ export class Program {
@Column("varchar", { name: "name", comment: "项目名称", length: 255 })
name: string;
@Column("varchar", {
name: "linkman_id",
comment: "联系人userid",
length: 255,
})
linkmanId: string;
@Column("int", { name: "linkman_id", comment: "联系人userid" })
linkmanId: number;
@Column("varchar", {
name: "company",

View File

@@ -0,0 +1,20 @@
import { Column, Entity, PrimaryGeneratedColumn } from "typeorm";
@Entity("program_collect", { schema: "test" })
export class ProgramCollect {
@PrimaryGeneratedColumn({ type: "int", name: "id", comment: "自增长ID" })
id: number;
@Column("int", { name: "user_id", comment: "用户ID" })
userId: number;
@Column("int", { name: "program_id", comment: "项目ID" })
programId: number;
@Column("datetime", {
name: "create_time",
comment: "收藏时间",
default: () => "CURRENT_TIMESTAMP",
})
createTime: Date;
}

View File

@@ -0,0 +1,26 @@
import { Column, Entity, PrimaryGeneratedColumn } from "typeorm";
@Entity("program_group", { schema: "test" })
export class ProgramGroup {
@PrimaryGeneratedColumn({ type: "int", name: "group_id", comment: "群组ID" })
groupId: number;
@Column("int", { name: "program_id", comment: "项目ID" })
programId: number;
@Column("int", { name: "charge_id", comment: "负责人ID" })
chargeId: number;
@Column("int", { name: "customer_id", comment: "客服ID" })
customerId: number;
@Column("int", { name: "user_id", comment: "用户ID" })
userId: number;
@Column("datetime", {
name: "create_time",
comment: "创建时间",
default: () => "CURRENT_TIMESTAMP",
})
createTime: Date;
}

View File

@@ -0,0 +1,35 @@
import { Column, Entity, PrimaryGeneratedColumn } from "typeorm";
@Entity("program_group_message", { schema: "test" })
export class ProgramGroupMessage {
@PrimaryGeneratedColumn({
type: "int",
name: "message_id",
comment: "消息ID",
})
messageId: number;
@Column("int", { name: "create_id", comment: "发送人ID" })
createId: number;
@Column("int", { name: "group_id", comment: "群聊ID" })
groupId: number;
@Column("text", { name: "content", comment: "内容" })
content: string;
@Column("enum", {
name: "type",
comment: "消息类型",
enum: ["text", "img", "mp3"],
default: () => "'text'",
})
type: "text" | "img" | "mp3";
@Column("datetime", {
name: "create_time",
comment: "发送时间",
default: () => "CURRENT_TIMESTAMP",
})
createTime: Date;
}

View File

@@ -13,8 +13,8 @@ import { AgentWithdrawals } from "./AgentWithdrawals";
import { Users } from "./Users";
@Index("agent_code", ["agentCode"], { unique: true })
@Index("unique_agent_region", ["userId", "regionId"], { unique: true })
@Index("region_id", ["regionId"], {})
@Index("unique_agent_region", ["userId", "regionId"], { unique: true })
@Entity("regional_agents", { schema: "test" })
export class RegionalAgents {
@PrimaryGeneratedColumn({ type: "int", name: "id" })

View File

@@ -11,12 +11,12 @@ import { AgentMerchants } from "./AgentMerchants";
import { Users } from "./Users";
@Index("code", ["code"], { unique: true })
@Index("created_by_admin_id", ["createdByAdminId"], {})
@Index("fk_registration_codes_agent_id", ["agentId"], {})
@Index("idx_code", ["code"], {})
@Index("idx_expires_at", ["expiresAt"], {})
@Index("idx_is_used", ["isUsed"], {})
@Index("used_by_user_id", ["usedByUserId"], {})
@Index("created_by_admin_id", ["createdByAdminId"], {})
@Index("fk_registration_codes_agent_id", ["agentId"], {})
@Entity("registration_codes", { schema: "test" })
export class RegistrationCodes {
@PrimaryGeneratedColumn({ type: "int", name: "id" })

View File

@@ -9,8 +9,8 @@ import {
import { Users } from "./Users";
import { Orders } from "./Orders";
@Index("user_id", ["userId"], {})
@Index("order_id", ["orderId"], {})
@Index("user_id", ["userId"], {})
@Entity("rongdou_history", { schema: "test" })
export class RongdouHistory {
@PrimaryGeneratedColumn({ type: "int", name: "id" })

View File

@@ -9,8 +9,8 @@ import {
import { Transfers } from "./Transfers";
import { Users } from "./Users";
@Index("transfer_id", ["transferId"], {})
@Index("confirmer_id", ["confirmerId"], {})
@Index("transfer_id", ["transferId"], {})
@Entity("transfer_confirmations", { schema: "test" })
export class TransferConfirmations {
@PrimaryGeneratedColumn({ type: "int", name: "id" })

View File

@@ -9,12 +9,12 @@ import {
import { Users } from "./Users";
import { Announcements } from "./Announcements";
@Index("idx_announcement_id", ["announcementId"], {})
@Index("idx_is_read", ["isRead"], {})
@Index("idx_user_id", ["userId"], {})
@Index("unique_user_announcement", ["userId", "announcementId"], {
unique: true,
})
@Index("idx_user_id", ["userId"], {})
@Index("idx_announcement_id", ["announcementId"], {})
@Index("idx_is_read", ["isRead"], {})
@Entity("user_announcement_reads", { schema: "test" })
export class UserAnnouncementReads {
@PrimaryGeneratedColumn({ type: "int", name: "id" })

View File

@@ -29,10 +29,10 @@ import { UserAddresses } from "./UserAddresses";
import { UserAnnouncementReads } from "./UserAnnouncementReads";
import { UserMatchingPool } from "./UserMatchingPool";
@Index("username", ["username"], { unique: true })
@Index("email", ["email"], { unique: true })
@Index("phone", ["phone"], { unique: true })
@Index("idx_payment_status", ["paymentStatus"], {})
@Index("phone", ["phone"], { unique: true })
@Index("username", ["username"], { unique: true })
@Entity("users", { schema: "test" })
export class Users {
@PrimaryGeneratedColumn({ type: "int", name: "id" })
@@ -238,10 +238,16 @@ export class Users {
name: "user_type",
nullable: true,
comment: "用户类型",
enum: ["user", "directly_operated", "agent", "agent_directly"],
enum: ["user", "directly_operated", "agent", "agent_directly", "customer"],
default: () => "'user'",
})
userType: "user" | "directly_operated" | "agent" | "agent_directly" | null;
userType:
| "user"
| "directly_operated"
| "agent"
| "agent_directly"
| "customer"
| null;
@OneToMany(() => AddressLabels, (addressLabels) => addressLabels.user)
addressLabels: AddressLabels[];

View File

@@ -1,5 +1,5 @@
import {Injectable} from "@nestjs/common";
import {ProgramEntity, ProgramGroupEntity, UsersEntity} from "../entity";
import {ProgramEntity, ProgramGroupEntity, UsersEntity, ProgramCollectEntity} from "../entity";
import {Repository} from "typeorm";
import {InjectRepository} from '@nestjs/typeorm';
import {ResultData} from "../const/result";
@@ -10,6 +10,7 @@ export class ProgramService {
constructor(
@InjectRepository(ProgramEntity) private readonly programRepository: Repository<ProgramEntity>,
@InjectRepository(ProgramGroupEntity) private readonly groupRepository: Repository<ProgramGroupEntity>,
@InjectRepository(ProgramCollectEntity) private readonly collectRepository: Repository<ProgramCollectEntity>,
) {
}
@@ -119,4 +120,132 @@ export class ProgramService {
return ResultData.fail(500, err.message);
}
}
// 收藏项目
async collect(collect: ProgramCollectEntity) {
try {
// 判断参数
if (!collect.programId || !collect.userId) {
throw new Error("参数错误");
}
// 判断是否已收藏
let collectSearchResult = await this.collectRepository.findOne({
where: {
programId: collect.programId,
userId: collect.userId
}
})
if (collectSearchResult != null) {
throw new Error("该项目已收藏");
}
// 没有记录则进行添加收藏
let result = await this.collectRepository.save(collect)
return result != null ? ResultData.success() : ResultData.fail(500, "收藏失败");
} catch (err) {
return ResultData.fail(500, err.message);
}
}
// 取消收藏项目
async uncollect(collect: ProgramCollectEntity) {
try {
// 判断参数
if (!collect.programId || !collect.userId) {
throw new Error("参数错误");
}
const result = await this.collectRepository.delete(collect)
return (result.affected != null && result.affected > 0) ? ResultData.success() : ResultData.fail(500, "取消收藏失败");
} catch (err) {
return ResultData.fail(500, err.message);
}
}
// 收藏列表
async collectList(collect: ProgramCollectEntity) {
try {
collect.page = collect.page || 1;
collect.size = collect.size || 10;
const offset = (collect.page - 1) * collect.size;
const queryBuilder = this.programRepository.createQueryBuilder('collect');
queryBuilder.leftJoinAndMapOne(
'collect.program',
ProgramEntity,
'program',
'program.id = collect.program_id'
)
queryBuilder.leftJoinAndMapOne(
'collect.user',
UsersEntity,
'users',
'users.id = collect.user_id'
)
queryBuilder.where('collect.user_id = :userId', {userId: collect.userId});
queryBuilder
.orderBy('program.createDate', 'DESC')
.take(collect.size || 10)
.skip(offset || 0);
const [items, total] = await queryBuilder.getManyAndCount();
let data = {
list: items,
total,
page: collect.page || 1,
size: collect.size || 10,
pages: Math.ceil(total / (collect.size || 10))
}
return ResultData.success(data);
} catch (err) {
return ResultData.fail(500, err.message);
}
}
// 是否已收藏
async isCollect(collect: ProgramCollectEntity) {
try {
// 判断参数
if (!collect.programId || !collect.userId) {
throw new Error("参数错误");
}
// 是否存在数据
let result = await this.collectRepository.findOne({
where: {
programId: collect.programId,
userId: collect.userId
}
})
return ResultData.success({isCollect: result != null}, "success")
} catch (err) {
return ResultData.fail(500, err.message);
}
}
async random(collect: ProgramCollectEntity) {
try {
if (!collect.userId || !collect.programId){
throw new Error("参数错误");
}
const queryBuilder = this.programRepository.createQueryBuilder("program")
const result = await queryBuilder
.leftJoin(
ProgramCollectEntity, // 收藏表实体名称
"favorite",
"favorite.program_id = program.id AND favorite.user_id = :userId",
{ userId: collect.userId }
)
.where("favorite.id IS NULL") // 没有收藏记录
.andWhere("program.id != :programId", { programId: collect.programId })
.orderBy("RAND()")
.select("program.id", "id") // 选择ID字段
.getRawOne()
if (result == null) {
return ResultData.fail(500, "没有更多项目");
}
return ResultData.success(result);
}catch (err){
return ResultData.fail(500, err.message);
}
}
}