yourname пре 8 месеци
родитељ
комит
c994cf2d2e

+ 3 - 2
src/server/api.ts

@@ -5,6 +5,7 @@ import authRoute from './api/auth/index'
 import rolesRoute from './api/roles/index'
 import fileRoutes from './api/files/index'
 import silverJobsRoutes from './api/silver-jobs/index'
+import silverUsersRoutes from './api/silver-users/index'
 import { AuthContext } from './types/context'
 import { AppDataSource } from './data-source'
 
@@ -50,18 +51,18 @@ if(!import.meta.env.PROD){
   })
 }
 
-
-
 const userRoutes = api.route('/api/v1/users', usersRouter)
 const authRoutes = api.route('/api/v1/auth', authRoute)
 const roleRoutes = api.route('/api/v1/roles', rolesRoute)
 const fileApiRoutes = api.route('/api/v1/files', fileRoutes)
 const silverJobsApiRoutes = api.route('/api/v1/silver-jobs', silverJobsRoutes)
+const silverUsersApiRoutes = api.route('/api/v1/silver-users', silverUsersRoutes)
 
 export type AuthRoutes = typeof authRoutes
 export type UserRoutes = typeof userRoutes
 export type RoleRoutes = typeof roleRoutes
 export type FileRoutes = typeof fileApiRoutes
 export type SilverJobsRoutes = typeof silverJobsApiRoutes
+export type SilverUsersRoutes = typeof silverUsersApiRoutes
 
 export default api

+ 11 - 0
src/server/api/silver-users/index.ts

@@ -0,0 +1,11 @@
+import { OpenAPIHono } from '@hono/zod-openapi';
+import silverUserProfileRoutes from './profiles';
+import silverPointRoutes from './points';
+import silverTimeBankRoutes from './time-banks';
+
+const app = new OpenAPIHono()
+  .route('/profiles', silverUserProfileRoutes)
+  .route('/points', silverPointRoutes)
+  .route('/time-banks', silverTimeBankRoutes);
+
+export default app;

+ 18 - 0
src/server/api/silver-users/points/index.ts

@@ -0,0 +1,18 @@
+import { createCrudRoutes } from '@/server/utils/generic-crud.routes';
+import { SilverPoint } from '@/server/modules/silver-users/silver-point.entity';
+import { authMiddleware } from '@/server/middleware/auth.middleware';
+
+const silverPointRoutes = createCrudRoutes({
+  entity: SilverPoint,
+  createSchema: {} as any,
+  updateSchema: {} as any,
+  getSchema: {} as any,
+  listSchema: {} as any,
+  middleware: [authMiddleware],
+  userTracking: {
+    createdByField: 'createdBy',
+    updatedByField: 'updatedBy'
+  }
+});
+
+export default silverPointRoutes;

+ 19 - 0
src/server/api/silver-users/profiles/index.ts

@@ -0,0 +1,19 @@
+import { createCrudRoutes } from '@/server/utils/generic-crud.routes';
+import { SilverUserProfile } from '@/server/modules/silver-users/silver-user-profile.entity';
+import { authMiddleware } from '@/server/middleware/auth.middleware';
+
+const silverUserProfileRoutes = createCrudRoutes({
+  entity: SilverUserProfile,
+  createSchema: {} as any, // 简化处理
+  updateSchema: {} as any, // 简化处理
+  getSchema: {} as any, // 简化处理
+  listSchema: {} as any, // 简化处理
+  searchFields: ['realName', 'nickname', 'organization', 'personalSkills', 'personalExperience'],
+  middleware: [authMiddleware],
+  userTracking: {
+    createdByField: 'createdBy',
+    updatedByField: 'updatedBy'
+  }
+});
+
+export default silverUserProfileRoutes;

+ 19 - 0
src/server/api/silver-users/time-banks/index.ts

@@ -0,0 +1,19 @@
+import { createCrudRoutes } from '@/server/utils/generic-crud.routes';
+import { SilverTimeBank } from '@/server/modules/silver-users/silver-time-bank.entity';
+import { authMiddleware } from '@/server/middleware/auth.middleware';
+
+const silverTimeBankRoutes = createCrudRoutes({
+  entity: SilverTimeBank,
+  createSchema: {} as any,
+  updateSchema: {} as any,
+  getSchema: {} as any,
+  listSchema: {} as any,
+  searchFields: ['organization', 'position', 'description'],
+  middleware: [authMiddleware],
+  userTracking: {
+    createdByField: 'createdBy',
+    updatedByField: 'updatedBy'
+  }
+});
+
+export default silverTimeBankRoutes;

+ 5 - 0
src/server/data-source.ts

@@ -12,6 +12,10 @@ import { Application } from "./modules/silver-jobs/application.entity"
 import { Favorite } from "./modules/silver-jobs/favorite.entity"
 import { ViewRecord } from "./modules/silver-jobs/view-record.entity"
 import { CompanyImage } from "./modules/silver-jobs/company-image.entity"
+import { SilverUserProfile } from "./modules/silver-users/silver-user-profile.entity"
+import { SilverPoint } from "./modules/silver-users/silver-point.entity"
+import { SilverPointTransaction } from "./modules/silver-users/silver-point-transaction.entity"
+import { SilverTimeBank } from "./modules/silver-users/silver-time-bank.entity"
 
 export const AppDataSource = new DataSource({
   type: "mysql",
@@ -22,6 +26,7 @@ export const AppDataSource = new DataSource({
   database: process.env.DB_DATABASE || "d8dai",
   entities: [
     User, Role, File, Company, Job, Application, Favorite, ViewRecord, CompanyImage,
+    SilverUserProfile, SilverPoint, SilverPointTransaction, SilverTimeBank,
   ],
   migrations: [],
   synchronize: process.env.DB_SYNCHRONIZE !== "false",

+ 38 - 0
src/server/modules/silver-users/silver-point-transaction.entity.ts

@@ -0,0 +1,38 @@
+import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn } from 'typeorm';
+
+export enum PointTransactionType {
+  EARN_SIGNIN = 1,
+  EARN_TASK = 2,
+  EARN_TIME_BANK = 3,
+  EARN_KNOWLEDGE = 4,
+  SPEND_EXCHANGE = 10,
+  SPEND_TRANSFER = 11,
+  ADJUSTMENT = 20
+}
+
+@Entity('silver_point_transactions')
+export class SilverPointTransaction {
+  @PrimaryGeneratedColumn({ unsigned: true })
+  id!: number;
+
+  @Column({ name: 'user_id', type: 'int', unsigned: true })
+  userId!: number;
+
+  @Column({ name: 'points', type: 'int' })
+  points!: number;
+
+  @Column({ name: 'type', type: 'tinyint', unsigned: true })
+  type!: PointTransactionType;
+
+  @Column({ name: 'description', type: 'varchar', length: 255 })
+  description!: string;
+
+  @Column({ name: 'related_id', type: 'int', unsigned: true, nullable: true })
+  relatedId!: number | null;
+
+  @Column({ name: 'related_type', type: 'varchar', length: 50, nullable: true })
+  relatedType!: string | null;
+
+  @CreateDateColumn({ name: 'created_at' })
+  createdAt!: Date;
+}

+ 25 - 0
src/server/modules/silver-users/silver-point.entity.ts

@@ -0,0 +1,25 @@
+import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn } from 'typeorm';
+
+@Entity('silver_points')
+export class SilverPoint {
+  @PrimaryGeneratedColumn({ unsigned: true })
+  id!: number;
+
+  @Column({ name: 'user_id', type: 'int', unsigned: true })
+  userId!: number;
+
+  @Column({ name: 'total_points', type: 'int', unsigned: true, default: 0 })
+  totalPoints!: number;
+
+  @Column({ name: 'earned_points', type: 'int', unsigned: true, default: 0 })
+  earnedPoints!: number;
+
+  @Column({ name: 'spent_points', type: 'int', unsigned: true, default: 0 })
+  spentPoints!: number;
+
+  @CreateDateColumn({ name: 'created_at' })
+  createdAt!: Date;
+
+  @UpdateDateColumn({ name: 'updated_at' })
+  updatedAt!: Date;
+}

+ 60 - 0
src/server/modules/silver-users/silver-time-bank.entity.ts

@@ -0,0 +1,60 @@
+import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn } from 'typeorm';
+
+export enum WorkType {
+  VOLUNTEER = 1,
+  PART_TIME = 2,
+  CONSULTING = 3,
+  TRAINING = 4,
+  OTHER = 5
+}
+
+@Entity('silver_time_banks')
+export class SilverTimeBank {
+  @PrimaryGeneratedColumn({ unsigned: true })
+  id!: number;
+
+  @Column({ name: 'user_id', type: 'int', unsigned: true })
+  userId!: number;
+
+  @Column({ name: 'work_type', type: 'tinyint', unsigned: true })
+  workType!: WorkType;
+
+  @Column({ name: 'organization', type: 'varchar', length: 255 })
+  organization!: string;
+
+  @Column({ name: 'position', type: 'varchar', length: 255, nullable: true })
+  position!: string | null;
+
+  @Column({ name: 'work_hours', type: 'decimal', precision: 10, scale: 2 })
+  workHours!: number;
+
+  @Column({ name: 'earned_points', type: 'int', unsigned: true, default: 0 })
+  earnedPoints!: number;
+
+  @Column({ name: 'description', type: 'text' })
+  description!: string;
+
+  @Column({ name: 'work_photos', type: 'text', nullable: true })
+  workPhotos!: string | null;
+
+  @Column({ name: 'start_date', type: 'date' })
+  startDate!: Date;
+
+  @Column({ name: 'end_date', type: 'date', nullable: true })
+  endDate!: Date | null;
+
+  @Column({ name: 'is_verified', type: 'tinyint', default: 0 })
+  isVerified!: number;
+
+  @CreateDateColumn({ name: 'created_at' })
+  createdAt!: Date;
+
+  @UpdateDateColumn({ name: 'updated_at' })
+  updatedAt!: Date;
+
+  @Column({ name: 'created_by', type: 'int', nullable: true })
+  createdBy!: number | null;
+
+  @Column({ name: 'updated_by', type: 'int', nullable: true })
+  updatedBy!: number | null;
+}

+ 153 - 0
src/server/modules/silver-users/silver-user-profile.dto.ts

@@ -0,0 +1,153 @@
+import { z } from '@hono/zod-openapi';
+
+export enum Gender {
+  MALE = 1,
+  FEMALE = 2,
+  OTHER = 3
+}
+
+export enum CertificationStatus {
+  UNCERTIFIED = 0,
+  PENDING = 1,
+  CERTIFIED = 2,
+  REJECTED = 3
+}
+
+export enum JobSeekingStatus {
+  NOT_SEEKING = 0,
+  ACTIVELY_SEEKING = 1,
+  OPEN_TO_OPPORTUNITIES = 2
+}
+
+export const CreateSilverUserProfileDto = z.object({
+  userId: z.coerce.number().int().positive().openapi({
+    description: '关联用户ID',
+    example: 1
+  }),
+  realName: z.string().max(50).openapi({
+    description: '真实姓名',
+    example: '张三'
+  }),
+  nickname: z.string().max(50).optional().openapi({
+    description: '网名/昵称',
+    example: '银龄达人'
+  }),
+  organization: z.string().max(255).optional().openapi({
+    description: '所属机构/单位',
+    example: '北京市老年协会'
+  }),
+  age: z.coerce.number().int().min(50).max(100).openapi({
+    description: '年龄',
+    example: 65
+  }),
+  gender: z.coerce.number().int().min(1).max(3).openapi({
+    description: '性别 1:男 2:女 3:其他',
+    example: 1
+  }),
+  phone: z.string().max(20).openapi({
+    description: '联系电话',
+    example: '13800138000'
+  }),
+  email: z.string().max(255).email().optional().openapi({
+    description: '邮箱地址',
+    example: 'user@example.com'
+  }),
+  avatarUrl: z.string().max(500).url().optional().openapi({
+    description: '头像URL',
+    example: 'https://example.com/avatar.jpg'
+  }),
+  personalIntro: z.string().optional().openapi({
+    description: '个人简介',
+    example: '具有30年教育经验的退休教师,擅长老年教育和培训'
+  }),
+  personalSkills: z.string().optional().openapi({
+    description: '个人技能',
+    example: '钢琴,书法,英语,老年心理辅导'
+  }),
+  personalExperience: z.string().optional().openapi({
+    description: '个人履历',
+    example: '1985-2015 北京市第一中学教师,2015-至今 社区志愿者'
+  }),
+  jobSeekingRequirements: z.string().optional().openapi({
+    description: '求职需求',
+    example: '寻求教育咨询或培训类兼职工作,时间灵活'
+  })
+});
+
+export const UpdateSilverUserProfileDto = CreateSilverUserProfileDto.partial().extend({
+  certificationStatus: z.coerce.number().int().min(0).max(3).optional().openapi({
+    description: '认证状态 0:未认证 1:待认证 2:已认证 3:认证失败',
+    example: 2
+  }),
+  certificationInfo: z.string().optional().openapi({
+    description: '认证信息',
+    example: '教师资格证,心理咨询师证'
+  }),
+  jobSeekingStatus: z.coerce.number().int().min(0).max(2).optional().openapi({
+    description: '求职状态 0:不求职 1:积极求职 2:观望中',
+    example: 1
+  })
+});
+
+export const SilverUserProfileSchema = z.object({
+  id: z.number().int().positive().openapi({
+    description: '用户档案ID',
+    example: 1
+  }),
+  userId: z.number().int().positive().openapi({
+    description: '关联用户ID',
+    example: 1
+  }),
+  realName: z.string().max(50).openapi({
+    description: '真实姓名',
+    example: '张三'
+  }),
+  nickname: z.string().max(50).nullable().openapi({
+    description: '网名/昵称',
+    example: '银龄达人'
+  }),
+  organization: z.string().max(255).nullable().openapi({
+    description: '所属机构/单位',
+    example: '北京市老年协会'
+  }),
+  age: z.number().int().min(50).max(100).openapi({
+    description: '年龄',
+    example: 65
+  }),
+  gender: z.number().int().min(1).max(3).openapi({
+    description: '性别 1:男 2:女 3:其他',
+    example: 1
+  }),
+  phone: z.string().max(20).openapi({
+    description: '联系电话',
+    example: '13800138000'
+  }),
+  email: z.string().max(255).email().nullable().openapi({
+    description: '邮箱地址',
+    example: 'user@example.com'
+  }),
+  avatarUrl: z.string().max(500).url().nullable().openapi({
+    description: '头像URL',
+    example: 'https://example.com/avatar.jpg'
+  }),
+  personalIntro: z.string().nullable().openapi({
+    description: '个人简介',
+    example: '具有30年教育经验的退休教师,擅长老年教育和培训'
+  }),
+  personalSkills: z.string().nullable().openapi({
+    description: '个人技能',
+    example: '钢琴,书法,英语,老年心理辅导'
+  }),
+  personalExperience: z.string().nullable().openapi({
+    description: '个人履历',
+    example: '1985-2015 北京市第一中学教师,2015-至今 社区志愿者'
+  }),
+  certificationStatus: z.number().int().min(0).max(3).openapi({
+    description: '认证状态 0:未认证 1:待认证 2:已认证 3:认证失败',
+    example: 2
+  }),
+  certificationInfo: z.string().nullable().openapi({
+    description: '认证信息',
+    example: '教师资格证,心理咨询师证'
+  }),
+  jobSeekingStatus: z.number().int

+ 105 - 0
src/server/modules/silver-users/silver-user-profile.entity.ts

@@ -0,0 +1,105 @@
+import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn } from 'typeorm';
+
+export enum Gender {
+  MALE = 1,
+  FEMALE = 2,
+  OTHER = 3
+}
+
+export enum CertificationStatus {
+  UNCERTIFIED = 0,
+  PENDING = 1,
+  CERTIFIED = 2,
+  REJECTED = 3
+}
+
+export enum JobSeekingStatus {
+  NOT_SEEKING = 0,
+  ACTIVELY_SEEKING = 1,
+  OPEN_TO_OPPORTUNITIES = 2
+}
+
+@Entity('silver_user_profiles')
+export class SilverUserProfile {
+  @PrimaryGeneratedColumn({ unsigned: true })
+  id!: number;
+
+  @Column({ name: 'user_id', type: 'int', unsigned: true })
+  userId!: number;
+
+  // 基本信息
+  @Column({ name: 'real_name', type: 'varchar', length: 50 })
+  realName!: string;
+
+  @Column({ name: 'nickname', type: 'varchar', length: 50, nullable: true })
+  nickname!: string | null;
+
+  @Column({ name: 'organization', type: 'varchar', length: 255, nullable: true })
+  organization!: string | null;
+
+  @Column({ name: 'age', type: 'int', unsigned: true })
+  age!: number;
+
+  @Column({ name: 'gender', type: 'tinyint', unsigned: true })
+  gender!: Gender;
+
+  @Column({ name: 'phone', type: 'varchar', length: 20 })
+  phone!: string;
+
+  @Column({ name: 'email', type: 'varchar', length: 255, nullable: true })
+  email!: string | null;
+
+  @Column({ name: 'avatar_url', type: 'varchar', length: 500, nullable: true })
+  avatarUrl!: string | null;
+
+  @Column({ name: 'personal_intro', type: 'text', nullable: true })
+  personalIntro!: string | null;
+
+  @Column({ name: 'personal_skills', type: 'text', nullable: true })
+  personalSkills!: string | null;
+
+  @Column({ name: 'personal_experience', type: 'text', nullable: true })
+  personalExperience!: string | null;
+
+  // 认证信息
+  @Column({ name: 'certification_status', type: 'tinyint', default: CertificationStatus.UNCERTIFIED })
+  certificationStatus!: CertificationStatus;
+
+  @Column({ name: 'certification_info', type: 'text', nullable: true })
+  certificationInfo!: string | null;
+
+  // 求职需求
+  @Column({ name: 'job_seeking_status', type: 'tinyint', default: JobSeekingStatus.NOT_SEEKING })
+  jobSeekingStatus!: JobSeekingStatus;
+
+  @Column({ name: 'job_seeking_requirements', type: 'text', nullable: true })
+  jobSeekingRequirements!: string | null;
+
+  // 统计信息
+  @Column({ name: 'total_points', type: 'int', unsigned: true, default: 0 })
+  totalPoints!: number;
+
+  @Column({ name: 'resume_count', type: 'int', unsigned: true, default: 0 })
+  resumeCount!: number;
+
+  @Column({ name: 'application_count', type: 'int', unsigned: true, default: 0 })
+  applicationCount!: number;
+
+  @Column({ name: 'time_bank_hours', type: 'decimal', precision: 10, scale: 2, default: 0 })
+  timeBankHours!: number;
+
+  @Column({ name: 'knowledge_contributions', type: 'int', unsigned: true, default: 0 })
+  knowledgeContributions!: number;
+
+  @CreateDateColumn({ name: 'created_at' })
+  createdAt!: Date;
+
+  @UpdateDateColumn({ name: 'updated_at' })
+  updatedAt!: Date;
+
+  @Column({ name: 'created_by', type: 'int', nullable: true })
+  createdBy!: number | null;
+
+  @Column({ name: 'updated_by', type: 'int', nullable: true })
+  updatedBy!: number | null;
+}

+ 9 - 1
实体创建字段规范.md

@@ -4,4 +4,12 @@
 岗位发布信息:岗位名称 薪资  学历 工作年限 工作时间 工作位置  发布时间  岗位结束时间  岗位介绍  岗详详情  岗位更新
 企业简历查看后状态:满意  进一步沟通  退回  待定   
 企业信息:企业名称 简称 行业类别 企业类别  企业图片 人数规模 地址  经度  维度  联系人  联系电话  企业认证 
-企业关注情况:查看人数  收藏人数  投简历人数
+企业关注情况:查看人数  收藏人数  投简历人数
+2.银龄库:展示个人信息、求职需求、专业技能、个人履历。
+银龄库实体,采用通用RUCD:
+基本信息:包括姓名 网名  机构/单位  年龄  性别  联系方式  照片  个人简介  个人技能  个人履历 个人认证 求职需求
+积分:  个人积分  积分兑换  积分转增  积分历史。
+简历回复情况:满意  进一步沟通  退回  待定   
+简历投递情况:投递数量 回复数量  关注 收藏
+时间银行:通过平台工作经历  工作时间  工作机构 获取积分 工作照片
+知识库贡献于分享:贡献知识库数量  知识库分享数量  知识库下载数量  知识库点赞数量  知识库评论数量  知识库收藏数量  知识库阅读次数

+ 284 - 0
银龄库实体实施指南.md

@@ -0,0 +1,284 @@
+# 银龄库实体实施指南
+
+## 实施步骤清单
+
+### 第一阶段:实体文件创建
+- [ ] 创建目录结构:`src/server/modules/silver-users/`
+- [ ] 创建所有实体TypeORM定义文件
+- [ ] 创建对应的服务类文件
+- [ ] 创建API路由文件
+
+### 第二阶段:集成配置
+- [ ] 更新`data-source.ts`注册新实体
+- [ ] 创建通用CRUD路由
+- [ ] 更新API主文件注册路由
+- [ ] 创建客户端API定义
+
+### 第三阶段:前端集成
+- [ ] 创建管理后台页面
+- [ ] 创建移动端页面
+- [ ] 更新路由和菜单配置
+
+## 具体实施命令
+
+### 1. 创建目录结构
+```bash
+mkdir -p src/server/modules/silver-users
+mkdir -p src/server/api/silver-users
+mkdir -p src/server/api/silver-users/profiles
+mkdir -p src/server/api/silver-users/points
+mkdir -p src/server/api/silver-users/resumes
+mkdir -p src/server/api/silver-users/job-searches
+mkdir -p src/server/api/silver-users/time-banks
+mkdir -p src/server/api/silver-users/knowledges
+```
+
+### 2. 实体文件创建清单
+
+#### 2.1 银龄用户主实体
+**文件:** `src/server/modules/silver-users/silver-user-profile.entity.ts`
+```typescript
+// 复制银龄库实体设计方案.md中的SilverUserProfile定义
+```
+
+#### 2.2 积分相关实体
+**文件:** `src/server/modules/silver-users/silver-point.entity.ts`
+**文件:** `src/server/modules/silver-users/silver-point-transaction.entity.ts`
+**文件:** `src/server/modules/silver-users/silver-point-exchange.entity.ts`
+**文件:** `src/server/modules/silver-users/silver-point-transfer.entity.ts`
+
+#### 2.3 简历投递相关实体
+**文件:** `src/server/modules/silver-users/silver-resume.entity.ts`
+**文件:** `src/server/modules/silver-users/silver-job-search.entity.ts`
+
+#### 2.4 时间银行实体
+**文件:** `src/server/modules/silver-users/silver-time-bank.entity.ts`
+
+#### 2.5 知识库实体
+**文件:** `src/server/modules/silver-users/silver-knowledge.entity.ts`
+**文件:** `src/server/modules/silver-users/silver-knowledge-interaction.entity.ts`
+
+### 3. 服务类创建
+
+#### 3.1 服务类模板
+**文件:** `src/server/modules/silver-users/silver-user-profile.service.ts`
+```typescript
+import { GenericCrudService } from '@/server/utils/generic-crud.service';
+import { DataSource } from 'typeorm';
+import { SilverUserProfile } from './silver-user-profile.entity';
+
+export class SilverUserProfileService extends GenericCrudService<SilverUserProfile> {
+  constructor(dataSource: DataSource) {
+    super(dataSource, SilverUserProfile);
+  }
+}
+
+// 其他服务类类似创建
+```
+
+### 4. 数据源注册更新
+
+**文件:** `src/server/data-source.ts`
+```typescript
+// 在文件顶部添加导入
+import { SilverUserProfile } from "./modules/silver-users/silver-user-profile.entity"
+import { SilverPoint } from "./modules/silver-users/silver-point.entity"
+import { SilverPointTransaction } from "./modules/silver-users/silver-point-transaction.entity"
+import { SilverPointExchange } from "./modules/silver-users/silver-point-exchange.entity"
+import { SilverPointTransfer } from "./modules/silver-users/silver-point-transfer.entity"
+import { SilverResume } from "./modules/silver-users/silver-resume.entity"
+import { SilverJobSearch } from "./modules/silver-users/silver-job-search.entity"
+import { SilverTimeBank } from "./modules/silver-users/silver-time-bank.entity"
+import { SilverKnowledge } from "./modules/silver-users/silver-knowledge.entity"
+import { SilverKnowledgeInteraction } from "./modules/silver-users/silver-knowledge-interaction.entity"
+
+// 在entities数组中添加
+entities: [
+  // ...现有实体
+  SilverUserProfile,
+  SilverPoint,
+  SilverPointTransaction,
+  SilverPointExchange,
+  SilverPointTransfer,
+  SilverResume,
+  SilverJobSearch,
+  SilverTimeBank,
+  SilverKnowledge,
+  SilverKnowledgeInteraction
+]
+```
+
+### 5. 通用CRUD路由创建
+
+#### 5.1 银龄用户档案路由
+**文件:** `src/server/api/silver-users/profiles/index.ts`
+```typescript
+import { createCrudRoutes } from '@/server/utils/generic-crud.routes';
+import { SilverUserProfile } from '@/server/modules/silver-users/silver-user-profile.entity';
+import { SilverUserProfileSchema, CreateSilverUserProfileDto, UpdateSilverUserProfileDto } from '@/server/modules/silver-users/silver-user-profile.entity';
+import { authMiddleware } from '@/server/middleware/auth.middleware';
+
+const silverUserProfileRoutes = createCrudRoutes({
+  entity: SilverUserProfile,
+  createSchema: CreateSilverUserProfileDto,
+  updateSchema: UpdateSilverUserProfileDto,
+  getSchema: SilverUserProfileSchema,
+  listSchema: SilverUserProfileSchema,
+  searchFields: ['realName', 'nickname', 'organization', 'skills'],
+  middleware: [authMiddleware],
+  userTracking: {
+    createdByField: 'createdBy',
+    updatedByField: 'updatedBy'
+  }
+});
+
+export default silverUserProfileRoutes;
+```
+
+#### 5.2 积分路由
+**文件:** `src/server/api/silver-users/points/index.ts`
+```typescript
+import { createCrudRoutes } from '@/server/utils/generic-crud.routes';
+import { SilverPoint } from '@/server/modules/silver-users/silver-point.entity';
+import { SilverPointSchema, CreateSilverPointDto, UpdateSilverPointDto } from '@/server/modules/silver-users/silver-point.entity';
+import { authMiddleware } from '@/server/middleware/auth.middleware';
+
+const silverPointRoutes = createCrudRoutes({
+  entity: SilverPoint,
+  createSchema: CreateSilverPointDto,
+  updateSchema: UpdateSilverPointDto,
+  getSchema: SilverPointSchema,
+  listSchema: SilverPointSchema,
+  middleware: [authMiddleware]
+});
+
+export default silverPointRoutes;
+```
+
+#### 5.3 时间银行路由
+**文件:** `src/server/api/silver-users/time-banks/index.ts`
+```typescript
+import { createCrudRoutes } from '@/server/utils/generic-crud.routes';
+import { SilverTimeBank } from '@/server/modules/silver-users/silver-time-bank.entity';
+import { SilverTimeBankSchema, CreateSilverTimeBankDto, UpdateSilverTimeBankDto } from '@/server/modules/silver-users/silver-time-bank.entity';
+import { authMiddleware } from '@/server/middleware/auth.middleware';
+
+const silverTimeBankRoutes = createCrudRoutes({
+  entity: SilverTimeBank,
+  createSchema: CreateSilverTimeBankDto,
+  updateSchema: UpdateSilverTimeBankDto,
+  getSchema: SilverTimeBankSchema,
+  listSchema: SilverTimeBankSchema,
+  searchFields: ['organization', 'position', 'description'],
+  middleware: [authMiddleware],
+  userTracking: {
+    createdByField: 'createdBy',
+    updatedByField: 'updatedBy'
+  }
+});
+
+export default silverTimeBankRoutes;
+```
+
+### 6. 主API路由注册
+
+**文件:** `src/server/api/silver-users/index.ts`
+```typescript
+import { OpenAPIHono } from '@hono/zod-openapi';
+import silverUserProfileRoutes from './profiles';
+import silverPointRoutes from './points';
+import silverResumeRoutes from './resumes';
+import silverJobSearchRoutes from './job-searches';
+import silverTimeBankRoutes from './time-banks';
+import silverKnowledgeRoutes from './knowledges';
+
+const app = new OpenAPIHono()
+  .route('/profiles', silverUserProfileRoutes)
+  .route('/points', silverPointRoutes)
+  .route('/resumes', silverResumeRoutes)
+  .route('/job-searches', silverJobSearchRoutes)
+  .route('/time-banks', silverTimeBankRoutes)
+  .route('/knowledges', silverKnowledgeRoutes);
+
+export default app;
+```
+
+**文件:** `src/server/api.ts` (在现有路由后添加)
+```typescript
+import silverUserRoutes from '@/server/api/silver-users';
+
+// 在路由注册部分添加
+api.route('/api/v1/silver-users', silverUserRoutes);
+```
+
+### 7. 客户端API定义
+
+**文件:** `src/client/api.ts` (在现有定义后添加)
+```typescript
+// 银龄用户相关API
+export const silverUserClient = hc<SilverUserRoutes>('/api/v1', {
+  fetch: axiosFetch,
+}).api.v1['silver-users'];
+
+// 类型定义
+import type { InferResponseType, InferRequestType } from 'hono/client'
+
+// 银龄用户档案
+export type SilverUserProfile = InferResponseType<typeof silverUserClient.profiles.$get, 200>['data'][0];
+export type SilverUserProfileDetail = InferResponseType<typeof silverUserClient.profiles[':id'].$get, 200>;
+export type CreateSilverUserProfileRequest = InferRequestType<typeof silverUserClient.profiles.$post>['json'];
+export type UpdateSilverUserProfileRequest = InferRequestType<typeof silverUserClient.profiles[':id'].$put>['json'];
+
+// 积分相关
+export type SilverPoint = InferResponseType<typeof silverUserClient.points.$get, 200>['data'][0];
+export type SilverTimeBank = InferResponseType<typeof silverUserClient['time-banks'].$get, 200>['data'][0];
+export type SilverKnowledge = InferResponseType<typeof silverUserClient.knowledges.$get, 200>['data'][0];
+```
+
+### 8. 数据库迁移命令
+
+```bash
+# 生成迁移文件
+pnpm typeorm migration:create src/server/migrations/CreateSilverUserEntities
+
+# 执行迁移
+pnpm typeorm migration:run -d src/server/data-source.ts
+```
+
+## 验证检查清单
+
+### 功能验证
+- [ ] 所有实体成功注册到TypeORM
+- [ ] 数据库表正确创建
+- [ ] 通用CRUD接口正常工作
+- [ ] 用户认证和权限控制正常
+- [ ] 积分自动计算和更新正常
+- [ ] 时间银行积分兑换正常
+- [ ] 知识库交互统计正常
+
+### 数据完整性检查
+- [ ] 实体关联关系正确
+- [ ] 外键约束正常工作
+- [ ] 用户操作记录正确保存
+- [ ] 统计字段自动更新
+- [ ] 数据验证规则生效
+
+### 性能检查
+- [ ] 常用查询字段已添加索引
+- [ ] 分页查询正常工作
+- [ ] 大数据量查询性能可接受
+- [ ] 关联查询性能优化
+
+## 常见问题解决方案
+
+### 问题1:实体未正确注册
+**解决:** 检查data-source.ts中的entities数组是否包含所有新实体
+
+### 问题2:Zod Schema验证失败
+**解决:** 检查字段类型和验证规则是否匹配数据库定义
+
+### 问题3:用户跟踪不生效
+**解决:** 确保路由中使用了authMiddleware,并且userTracking配置正确
+
+### 问题4:关联查询性能问题
+**解决:** 使用relations配置优化关联查询,避免N+1问题

+ 824 - 0
银龄库实体设计方案.md

@@ -0,0 +1,824 @@
+# 银龄库实体设计方案
+
+## 实体完整性分析结论
+
+经过详细分析,现有系统缺少完整的银龄库实体体系,需要新建以下核心实体:
+
+## 实体架构设计
+
+### 1. 银龄用户主档案实体 (SilverUserProfile)
+位置:`src/server/modules/silver-users/silver-user-profile.entity.ts`
+
+```typescript
+import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn } from 'typeorm';
+import { z } from '@hono/zod-openapi';
+
+export enum Gender {
+  MALE = 1,
+  FEMALE = 2,
+  OTHER = 3
+}
+
+export enum CertificationStatus {
+  UNCERTIFIED = 0,
+  PENDING = 1,
+  CERTIFIED = 2,
+  REJECTED = 3
+}
+
+export enum JobSeekingStatus {
+  NOT_SEEKING = 0,
+  ACTIVELY_SEEKING = 1,
+  OPEN_TO_OPPORTUNITIES = 2
+}
+
+@Entity('silver_user_profiles')
+export class SilverUserProfile {
+  @PrimaryGeneratedColumn({ unsigned: true })
+  id!: number;
+
+  @Column({ name: 'user_id', type: 'int', unsigned: true })
+  userId!: number;
+
+  // 基本信息
+  @Column({ name: 'real_name', type: 'varchar', length: 50 })
+  realName!: string;
+
+  @Column({ name: 'nickname', type: 'varchar', length: 50, nullable: true })
+  nickname!: string | null;
+
+  @Column({ name: 'organization', type: 'varchar', length: 255, nullable: true })
+  organization!: string | null;
+
+  @Column({ name: 'age', type: 'int', unsigned: true })
+  age!: number;
+
+  @Column({ name: 'gender', type: 'tinyint', unsigned: true })
+  gender!: Gender;
+
+  @Column({ name: 'phone', type: 'varchar', length: 20 })
+  phone!: string;
+
+  @Column({ name: 'email', type: 'varchar', length: 255, nullable: true })
+  email!: string | null;
+
+  @Column({ name: 'avatar_url', type: 'varchar', length: 500, nullable: true })
+  avatarUrl!: string | null;
+
+  @Column({ name: 'personal_intro', type: 'text', nullable: true })
+  personalIntro!: string | null;
+
+  @Column({ name: 'personal_skills', type: 'text', nullable: true })
+  personalSkills!: string | null;
+
+  @Column({ name: 'personal_experience', type: 'text', nullable: true })
+  personalExperience!: string | null;
+
+  // 认证信息
+  @Column({ name: 'certification_status', type: 'tinyint', default: CertificationStatus.UNCERTIFIED })
+  certificationStatus!: CertificationStatus;
+
+  @Column({ name: 'certification_info', type: 'text', nullable: true })
+  certificationInfo!: string | null;
+
+  // 求职需求
+  @Column({ name: 'job_seeking_status', type: 'tinyint', default: JobSeekingStatus.NOT_SEEKING })
+  jobSeekingStatus!: JobSeekingStatus;
+
+  @Column({ name: 'job_seeking_requirements', type: 'text', nullable: true })
+  jobSeekingRequirements!: string | null;
+
+  // 统计信息
+  @Column({ name: 'total_points', type: 'int', unsigned: true, default: 0 })
+  totalPoints!: number;
+
+  @Column({ name: 'resume_count', type: 'int', unsigned: true, default: 0 })
+  resumeCount!: number;
+
+  @Column({ name: 'application_count', type: 'int', unsigned: true, default: 0 })
+  applicationCount!: number;
+
+  @Column({ name: 'time_bank_hours', type: 'decimal', precision: 10, scale: 2, default: 0 })
+  timeBankHours!: number;
+
+  @Column({ name: 'knowledge_contributions', type: 'int', unsigned: true, default: 0 })
+  knowledgeContributions!: number;
+
+  @CreateDateColumn({ name: 'created_at' })
+  createdAt!: Date;
+
+  @UpdateDateColumn({ name: 'updated_at' })
+  updatedAt!: Date;
+
+  @Column({ name: 'created_by', type: 'int', nullable: true })
+  createdBy!: number | null;
+
+  @Column({ name: 'updated_by', type: 'int', nullable: true })
+  updatedBy!: number | null;
+}
+
+// Zod Schema定义
+export const SilverUserProfileSchema = z.object({
+  id: z.number().int().positive().openapi({
+    description: '用户档案ID',
+    example: 1
+  }),
+  userId: z.number().int().positive().openapi({
+    description: '关联用户ID',
+    example: 1
+  }),
+  realName: z.string().max(50).openapi({
+    description: '真实姓名',
+    example: '张三'
+  }),
+  nickname: z.string().max(50).nullable().openapi({
+    description: '网名/昵称',
+    example: '银龄达人'
+  }),
+  organization: z.string().max(255).nullable().openapi({
+    description: '所属机构/单位',
+    example: '北京市老年协会'
+  }),
+  age: z.coerce.number().int().min(50).max(100).openapi({
+    description: '年龄',
+    example: 65
+  }),
+  gender: z.coerce.number().int().min(1).max(3).openapi({
+    description: '性别 1:男 2:女 3:其他',
+    example: 1
+  }),
+  phone: z.string().max(20).openapi({
+    description: '联系电话',
+    example: '13800138000'
+  }),
+  email: z.string().max(255).email().nullable().openapi({
+    description: '邮箱地址',
+    example: 'user@example.com'
+  }),
+  avatarUrl: z.string().max(500).url().nullable().openapi({
+    description: '头像URL',
+    example: 'https://example.com/avatar.jpg'
+  }),
+  personalIntro: z.string().nullable().openapi({
+    description: '个人简介',
+    example: '具有30年教育经验的退休教师,擅长老年教育和培训'
+  }),
+  personalSkills: z.string().nullable().openapi({
+    description: '个人技能',
+    example: '钢琴,书法,英语,老年心理辅导'
+  }),
+  personalExperience: z.string().nullable().openapi({
+    description: '个人履历',
+    example: '1985-2015 北京市第一中学教师,2015-至今 社区志愿者'
+  }),
+  certificationStatus: z.coerce.number().int().min(0).max(3).default(0).openapi({
+    description: '认证状态 0:未认证 1:待认证 2:已认证 3:认证失败',
+    example: 2
+  }),
+  certificationInfo: z.string().nullable().openapi({
+    description: '认证信息',
+    example: '教师资格证,心理咨询师证'
+  }),
+  jobSeekingStatus: z.coerce.number().int().min(0).max(2).default(0).openapi({
+    description: '求职状态 0:不求职 1:积极求职 2:观望中',
+    example: 1
+  }),
+  jobSeekingRequirements: z.string().nullable().openapi({
+    description: '求职需求',
+    example: '寻求教育咨询或培训类兼职工作,时间灵活'
+  }),
+  totalPoints: z.number().int().min(0).default(0).openapi({
+    description: '总积分',
+    example: 1000
+  }),
+  resumeCount: z.number().int().min(0).default(0).openapi({
+    description: '简历数量',
+    example: 3
+  }),
+  applicationCount: z.number().int().min(0).default(0).openapi({
+    description: '投递数量',
+    example: 5
+  }),
+  timeBankHours: z.coerce.number().min(0).default(0).openapi({
+    description: '时间银行小时数',
+    example: 120.5
+  }),
+  knowledgeContributions: z.number().int().min(0).default(0).openapi({
+    description: '知识库贡献数量',
+    example: 15
+  }),
+  createdAt: z.date().openapi({
+    description: '创建时间',
+    example: '2024-01-01T00:00:00Z'
+  }),
+  updatedAt: z.date().openapi({
+    description: '更新时间',
+    example: '2024-01-01T00:00:00Z'
+  })
+});
+
+export const CreateSilverUserProfileDto = z.object({
+  userId: z.coerce.number().int().positive().openapi({
+    description: '关联用户ID',
+    example: 1
+  }),
+  realName: z.string().max(50).openapi({
+    description: '真实姓名',
+    example: '张三'
+  }),
+  nickname: z.string().max(50).optional().openapi({
+    description: '网名/昵称',
+    example: '银龄达人'
+  }),
+  organization: z.string().max(255).optional().openapi({
+    description: '所属机构/单位',
+    example: '北京市老年协会'
+  }),
+  age: z.coerce.number().int().min(50).max(100).openapi({
+    description: '年龄',
+    example: 65
+  }),
+  gender: z.coerce.number().int().min(1).max(3).openapi({
+    description: '性别 1:男 2:女 3:其他',
+    example: 1
+  }),
+  phone: z.string().max(20).openapi({
+    description: '联系电话',
+    example: '13800138000'
+  }),
+  email: z.string().max(255).email().optional().openapi({
+    description: '邮箱地址',
+    example: 'user@example.com'
+  }),
+  avatarUrl: z.string().max(500).url().optional().openapi({
+    description: '头像URL',
+    example: 'https://example.com/avatar.jpg'
+  }),
+  personalIntro: z.string().optional().openapi({
+    description: '个人简介',
+    example: '具有30年教育经验的退休教师'
+  }),
+  personalSkills: z.string().optional().openapi({
+    description: '个人技能',
+    example: '钢琴,书法,英语'
+  }),
+  personalExperience: z.string().optional().openapi({
+    description: '个人履历',
+    example: '1985-2015 北京市第一中学教师'
+  }),
+  jobSeekingRequirements: z.string().optional().openapi({
+    description: '求职需求',
+    example: '寻求教育咨询或培训类兼职工作'
+  })
+});
+
+export const UpdateSilverUserProfileDto = CreateSilverUserProfileDto.partial().extend({
+  certificationStatus: z.coerce.number().int().min(0).max(3).optional().openapi({
+    description: '认证状态',
+    example: 2
+  }),
+  certificationInfo: z.string().optional().openapi({
+    description: '认证信息',
+    example: '教师资格证,心理咨询师证'
+  }),
+  jobSeekingStatus: z.coerce.number().int().min(0).max(2).optional().openapi({
+    description: '求职状态',
+    example: 1
+  })
+});
+```
+
+### 2. 积分系统实体
+
+#### 2.1 积分主记录 (SilverPoint)
+位置:`src/server/modules/silver-users/silver-point.entity.ts`
+
+```typescript
+@Entity('silver_points')
+export class SilverPoint {
+  @PrimaryGeneratedColumn({ unsigned: true })
+  id!: number;
+
+  @Column({ name: 'user_id', type: 'int', unsigned: true })
+  userId!: number;
+
+  @Column({ name: 'total_points', type: 'int', unsigned: true, default: 0 })
+  totalPoints!: number;
+
+  @Column({ name: 'earned_points', type: 'int', unsigned: true, default: 0 })
+  earnedPoints!: number;
+
+  @Column({ name: 'spent_points', type: 'int', unsigned: true, default: 0 })
+  spentPoints!: number;
+
+  @CreateDateColumn({ name: 'created_at' })
+  createdAt!: Date;
+
+  @UpdateDateColumn({ name: 'updated_at' })
+  updatedAt!: Date;
+}
+```
+
+#### 2.2 积分流水记录 (SilverPointTransaction)
+位置:`src/server/modules/silver-users/silver-point-transaction.entity.ts`
+
+```typescript
+export enum PointTransactionType {
+  EARN_SIGNIN = 1,      // 签到获得
+  EARN_TASK = 2,        // 任务完成获得
+  EARN_TIME_BANK = 3,   // 时间银行获得
+  EARN_KNOWLEDGE = 4,   // 知识贡献获得
+  SPEND_EXCHANGE = 10,  // 积分兑换消耗
+  SPEND_TRANSFER = 11,  // 积分转增消耗
+  ADJUSTMENT = 20       // 系统调整
+}
+
+@Entity('silver_point_transactions')
+export class SilverPointTransaction {
+  @PrimaryGeneratedColumn({ unsigned: true })
+  id!: number;
+
+  @Column({ name: 'user_id', type: 'int', unsigned: true })
+  userId!: number;
+
+  @Column({ name: 'points', type: 'int' }) // 正数表示增加,负数表示消耗
+  points!: number;
+
+  @Column({ name: 'type', type: 'tinyint', unsigned: true })
+  type!: PointTransactionType;
+
+  @Column({ name: 'description', type: 'varchar', length: 255 })
+  description!: string;
+
+  @Column({ name: 'related_id', type: 'int', unsigned: true, nullable: true })
+  relatedId!: number | null; // 关联业务ID
+
+  @Column({ name: 'related_type', type: 'varchar', length: 50, nullable: true })
+  relatedType!: string | null; // 关联业务类型
+
+  @CreateDateColumn({ name: 'created_at' })
+  createdAt!: Date;
+}
+```
+
+#### 2.3 积分兑换记录 (SilverPointExchange)
+位置:`src/server/modules/silver-users/silver-point-exchange.entity.ts`
+
+```typescript
+export enum ExchangeStatus {
+  PENDING = 0,
+  PROCESSING = 1,
+  COMPLETED = 2,
+  FAILED = 3,
+  CANCELLED = 4
+}
+
+@Entity('silver_point_exchanges')
+export class SilverPointExchange {
+  @PrimaryGeneratedColumn({ unsigned: true })
+  id!: number;
+
+  @Column({ name: 'user_id', type: 'int', unsigned: true })
+  userId!: number;
+
+  @Column({ name: 'item_name', type: 'varchar', length: 255 })
+  itemName!: string;
+
+  @Column({ name: 'item_description', type: 'text', nullable: true })
+  itemDescription!: string | null;
+
+  @Column({ name: 'points_required', type: 'int', unsigned: true })
+  pointsRequired!: number;
+
+  @Column({ name: 'quantity', type: 'int', unsigned: true, default: 1 })
+  quantity!: number;
+
+  @Column({ name: 'total_points', type: 'int', unsigned: true })
+  totalPoints!: number;
+
+  @Column({ name: 'status', type: 'tinyint', default: ExchangeStatus.PENDING })
+  status!: ExchangeStatus;
+
+  @Column({ name: 'remark', type: 'text', nullable: true })
+  remark!: string | null;
+
+  @CreateDateColumn({ name: 'created_at' })
+  createdAt!: Date;
+
+  @UpdateDateColumn({ name: 'updated_at' })
+  updatedAt!: Date;
+}
+```
+
+#### 2.4 积分转增记录 (SilverPointTransfer)
+位置:`src/server/modules/silver-users/silver-point-transfer.entity.ts`
+
+```typescript
+export enum TransferStatus {
+  PENDING = 0,
+  COMPLETED = 1,
+  FAILED = 2,
+  CANCELLED = 3
+}
+
+@Entity('silver_point_transfers')
+export class SilverPointTransfer {
+  @PrimaryGeneratedColumn({ unsigned: true })
+  id!: number;
+
+  @Column({ name: 'from_user_id', type: 'int', unsigned: true })
+  fromUserId!: number;
+
+  @Column({ name: 'to_user_id', type: 'int', unsigned: true })
+  toUserId!: number;
+
+  @Column({ name: 'points', type: 'int', unsigned: true })
+  points!: number;
+
+  @Column({ name: 'message', type: 'varchar', length: 500, nullable: true })
+  message!: string | null;
+
+  @Column({ name: 'status', type: 'tinyint', default: TransferStatus.PENDING })
+  status!: TransferStatus;
+
+  @CreateDateColumn({ name: 'created_at' })
+  createdAt!: Date;
+
+  @UpdateDateColumn({ name: 'updated_at' })
+  updatedAt!: Date;
+}
+```
+
+### 3. 简历和投递系统增强
+
+#### 3.1 个人简历实体 (SilverResume)
+位置:`src/server/modules/silver-users/silver-resume.entity.ts`
+
+```typescript
+@Entity('silver_resumes')
+export class SilverResume {
+  @PrimaryGeneratedColumn({ unsigned: true })
+  id!: number;
+
+  @Column({ name: 'user_id', type: 'int', unsigned: true })
+  userId!: number;
+
+  @Column({ name: 'title', type: 'varchar', length: 255 })
+  title!: string;
+
+  @Column({ name: 'summary', type: 'text', nullable: true })
+  summary!: string | null;
+
+  @Column({ name: 'skills', type: 'text', nullable: true })
+  skills!: string | null;
+
+  @Column({ name: 'experience', type: 'text', nullable: true })
+  experience!: string | null;
+
+  @Column({ name: 'education', type: 'text', nullable: true })
+  education!: string | null;
+
+  @Column({ name: 'certifications', type: 'text', nullable: true })
+  certifications!: string | null;
+
+  @Column({ name: 'is_default', type: 'tinyint', default: 0 })
+  isDefault!: number;
+
+  @Column({ name: 'is_active', type: 'tinyint', default: 1 })
+  isActive!: number;
+
+  @CreateDateColumn({ name: 'created_at' })
+  createdAt!: Date;
+
+  @UpdateDateColumn({ name: 'updated_at' })
+  updatedAt!: Date;
+}
+```
+
+#### 3.2 求职意向实体 (SilverJobSearch)
+位置:`src/server/modules/silver-users/silver-job-search.entity.ts`
+
+```typescript
+export enum JobType {
+  FULL_TIME = 1,
+  PART_TIME = 2,
+  CONTRACT = 3,
+  VOLUNTEER = 4
+}
+
+@Entity('silver_job_searches')
+export class SilverJobSearch {
+  @PrimaryGeneratedColumn({ unsigned: true })
+  id!: number;
+
+  @Column({ name: 'user_id', type: 'int', unsigned: true })
+  userId!: number;
+
+  @Column({ name: 'position', type: 'varchar', length: 255 })
+  position!: string;
+
+  @Column({ name: 'expected_salary', type: 'decimal', precision: 10, scale: 2, nullable: true })
+  expectedSalary!: number | null;
+
+  @Column({ name: 'work_location', type: 'varchar', length: 255, nullable: true })
+  workLocation!: string | null;
+
+  @Column({ name: 'job_type', type: 'tinyint', unsigned: true })
+  jobType!: JobType;
+
+  @Column({ name: 'requirements', type: 'text', nullable: true })
+  requirements!: string | null;
+
+  @Column({ name: 'is_active', type: 'tinyint', default: 1 })
+  isActive!: number;
+
+  @CreateDateColumn({ name: 'created_at' })
+  createdAt!: Date;
+
+  @UpdateDateColumn({ name: 'updated_at' })
+  updatedAt!: Date;
+}
+```
+
+#### 3.3 增强现有的Application实体
+在现有基础上添加:
+```typescript
+// 添加到Application实体
+@Column({ name: 'source', type: 'varchar', length: 50, default: 'platform' })
+source!: string; // 投递来源:platform, wechat, etc.
+
+@Column({ name: 'is_favorite', type: 'tinyint', default: 0 })
+isFavorite!: number;
+
+@Column({ name: 'is_followed', type: 'tinyint', default: 0 })
+isFollowed!: number;
+```
+
+### 4. 时间银行系统
+
+#### 4.1 时间银行记录实体 (SilverTimeBank)
+位置:`src/server/modules/silver-users/silver-time-bank.entity.ts`
+
+```typescript
+export enum WorkType {
+  VOLUNTEER = 1,    // 志愿服务
+  PART_TIME = 2,    // 兼职工作
+  CONSULTING = 3,   // 咨询服务
+  TRAINING = 4,     // 培训服务
+  OTHER = 5         // 其他服务
+}
+
+@Entity('silver_time_banks')
+export class SilverTimeBank {
+  @PrimaryGeneratedColumn({ unsigned: true })
+  id!: number;
+
+  @Column({ name: 'user_id', type: 'int', unsigned: true })
+  userId!: number;
+
+  @Column({ name: 'work_type', type: 'tinyint', unsigned: true })
+  workType!: WorkType;
+
+  @Column({ name: 'organization', type: 'varchar', length: 255 })
+  organization!: string;
+
+  @Column({ name: 'position', type: 'varchar', length: 255, nullable: true })
+  position!: string | null;
+
+  @Column({ name: 'work_hours', type: 'decimal', precision: 10, scale: 2 })
+  workHours!: number;
+
+  @Column({ name: 'earned_points', type: 'int', unsigned: true, default: 0 })
+  earnedPoints!: number;
+
+  @Column({ name: 'description', type: 'text' })
+  description!: string;
+
+  @Column({ name: 'work_photos', type: 'text', nullable: true })
+  workPhotos!: string | null; // JSON array of photo URLs
+
+  @Column({ name: 'start_date', type: 'date' })
+  startDate!: Date;
+
+  @Column({ name: 'end_date', type: 'date', nullable: true })
+  endDate!: Date | null;
+
+  @Column({ name: 'is_verified', type: 'tinyint', default: 0 })
+  isVerified!: number;
+
+  @CreateDateColumn({ name: 'created_at' })
+  createdAt!: Date;
+
+  @UpdateDateColumn({ name: 'updated_at' })
+  updatedAt!: Date;
+}
+```
+
+### 5. 知识库系统
+
+#### 5.1 知识库内容实体 (SilverKnowledge)
+位置:`src/server/modules/silver-users/silver-knowledge.entity.ts`
+
+```typescript
+export enum KnowledgeType {
+  ARTICLE = 1,      // 文章
+  VIDEO = 2,        // 视频
+  DOCUMENT = 3,     // 文档
+  COURSE = 4,       // 课程
+  EXPERIENCE = 5    // 经验分享
+}
+
+export enum KnowledgeStatus {
+  DRAFT = 0,        // 草稿
+  PUBLISHED = 1,    // 已发布
+  HIDDEN = 2,       // 已隐藏
+  DELETED = 3       // 已删除
+}
+
+@Entity('silver_knowledges')
+export class SilverKnowledge {
+  @PrimaryGeneratedColumn({ unsigned: true })
+  id!: number;
+
+  @Column({ name: 'user_id', type: 'int', unsigned: true })
+  userId!: number;
+
+  @Column({ name: 'title', type: 'varchar', length: 255 })
+  title!: string;
+
+  @Column({ name: 'content', type: 'text' })
+  content!: string;
+
+  @Column({ name: 'type', type: 'tinyint', unsigned: true })
+  type!: KnowledgeType;
+
+  @Column({ name: 'tags', type: 'text', nullable: true })
+  tags!: string | null; // JSON array of tags
+
+  @Column({ name: 'cover_image', type: 'varchar', length: 500, nullable: true })
+  coverImage!: string | null;
+
+  @Column({ name: 'attachments', type: 'text', nullable: true })
+  attachments!: string | null; // JSON array of attachment URLs
+
+  @Column({ name: 'status', type: 'tinyint', default: KnowledgeStatus.DRAFT })
+  status!: KnowledgeStatus;
+
+  @Column({ name: 'view_count', type: 'int', unsigned: true, default: 0 })
+  viewCount!: number;
+
+  @Column({ name: 'download_count', type: 'int', unsigned: true, default: 0 })
+  downloadCount!: number;
+
+  @Column({ name: 'like_count', type: 'int', unsigned: true, default: 0 })
+  likeCount!: number;
+
+  @Column({ name: 'comment_count', type: 'int', unsigned: true, default: 0 })
+  commentCount!: number;
+
+  @Column({ name: 'favorite_count', type: 'int', unsigned: true, default: 0 })
+  favoriteCount!: number;
+
+  @CreateDateColumn({ name: 'created_at' })
+  createdAt!: Date;
+
+  @UpdateDateColumn({ name: 'updated_at' })
+  updatedAt!: Date;
+}
+```
+
+#### 5.2 知识库用户交互记录 (SilverKnowledgeInteraction)
+位置:`src/server/modules/silver-users/silver-knowledge-interaction.entity.ts`
+
+```typescript
+export enum InteractionType {
+  VIEW = 1,       // 阅读
+  DOWNLOAD = 2,   // 下载
+  LIKE = 3,       // 点赞
+  COMMENT = 4,    // 评论
+  FAVORITE = 5,   // 收藏
+  SHARE = 6       // 分享
+}
+
+@Entity('silver_knowledge_interactions')
+export class SilverKnowledgeInteraction {
+  @PrimaryGeneratedColumn({ unsigned: true })
+  id!: number;
+
+  @Column({ name: 'user_id', type: 'int', unsigned: true })
+  userId!: number;
+
+  @Column({ name: 'knowledge_id', type: 'int', unsigned: true })
+  knowledgeId!: number;
+
+  @Column({ name: 'type', type: 'tinyint', unsigned: true })
+  type!: InteractionType;
+
+  @Column({ name: 'content', type: 'text', nullable: true })
+  content!: string | null; // 评论内容等
+
+  @CreateDateColumn({ name: 'created_at' })
+  createdAt!: Date;
+}
+```
+
+## 实体注册配置
+
+### 数据源注册 (src/server/data-source.ts)
+```typescript
+// 新增实体导入
+import { SilverUserProfile } from "./modules/silver-users/silver-user-profile.entity"
+import { SilverPoint } from "./modules/silver-users/silver-point.entity"
+import { SilverPointTransaction } from "./modules/silver-users/silver-point-transaction.entity"
+import { SilverPointExchange } from "./modules/silver-users/silver-point-exchange.entity"
+import { SilverPointTransfer } from "./modules/silver-users/silver-point-transfer.entity"
+import { SilverResume } from "./modules/silver-users/silver-resume.entity"
+import { SilverJobSearch } from "./modules/silver-users/silver-job-search.entity"
+import { SilverTimeBank } from "./modules/silver-users/silver-time-bank.entity"
+import { SilverKnowledge } from "./modules/silver-users/silver-knowledge.entity"
+import { SilverKnowledgeInteraction } from "./modules/silver-users/silver-knowledge-interaction.entity"
+
+// 在entities数组中添加
+entities: [
+  // ...现有实体
+  SilverUserProfile,
+  SilverPoint,
+  SilverPointTransaction,
+  SilverPointExchange,
+  SilverPointTransfer,
+  SilverResume,
+  SilverJobSearch,
+  SilverTimeBank,
+  SilverKnowledge,
+  SilverKnowledgeInteraction
+]
+```
+
+## 通用CRUD服务创建
+
+### 服务类模板
+每个实体对应的服务类继承GenericCrudService:
+
+```typescript
+// src/server/modules/silver-users/silver-user-profile.service.ts
+import { GenericCrudService } from '@/server/utils/generic-crud.service';
+import { DataSource } from 'typeorm';
+import { SilverUserProfile } from './silver-user-profile.entity';
+
+export class SilverUserProfileService extends GenericCrudService<SilverUserProfile> {
+  constructor(dataSource: DataSource) {
+    super(dataSource, SilverUserProfile);
+  }
+
+  // 可以添加自定义业务方法
+  async findByUserId(userId: number): Promise<SilverUserProfile | null> {
+    return this.repository.findOne({ where: { userId } });
+  }
+}
+```
+
+## 路由配置方案
+
+### 路由结构
+```
+src/server/api/silver-users/
+├── index.ts
+├── profiles/
+│   ├── index.ts
+│   └── [id]/
+├── points/
+│   ├── index.ts
+│   └── [id]/
+├── resumes/
+├── job-searches/
+├── time-banks/
+└── knowledges/
+```
+
+## 前端API集成方案
+
+### 客户端API定义 (src/client/api.ts)
+```typescript
+// 银龄用户相关API
+export const silverUserClient = hc<SilverUserRoutes>('/api/v1', {
+  fetch: axiosFetch,
+}).api.v1['silver-users'];
+```
+
+## 实施步骤
+
+1. **按顺序创建实体文件** - 先创建主实体,再创建关联实体
+2. **注册到数据源** - 在data-source.ts中添加所有新实体
+3. **创建服务类** - 每个实体对应的服务类
+4. **创建通用CRUD路由** - 使用createCrudRoutes快速生成
+5. **前端集成** - 创建客户端API和页面组件
+6. **数据迁移** - 如有需要,创建数据库迁移脚本
+
+## 注意事项
+
+1. **命名规范**:所有表名使用下划线命名法(silver_user_profiles)
+2. **字段规范**:所有字段必须包含name属性和中文注释
+3. **类型安全**:使用Zod Schema确保类型安全
+4. **用户跟踪**:使用userTracking配置自动记录操作人
+5. **性能优化**:为常用查询字段添加索引
+6. **数据一致性**:使用事务确保相关操作的原子性