好的, 我们来添加短信和邮件通知功能, 以及生成笔试和面试日程表的功能。这些功能将进一步完善招聘流程。我们将使用第三方服务来发送短信和邮件, 并添加一个新的表来管理面试日程。

首先, 让我们更新数据库结构和安装必要的依赖:

  1. 更新数据库结构:
-- 添加电话号码字段到users表
ALTER TABLE users ADD COLUMN phone TEXT;
 
-- 创建interviews表
CREATE TABLE interviews (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  job_id INTEGER NOT NULL,
  user_id INTEGER NOT NULL,
  type TEXT NOT NULL, -- 'written' or 'oral'
  status TEXT NOT NULL, -- 'scheduled', 'completed', 'cancelled'
  datetime DATETIME NOT NULL,
  location TEXT,
  notes TEXT,
  FOREIGN KEY (job_id) REFERENCES jobs(id),
  FOREIGN KEY (user_id) REFERENCES users(id)
);
  1. 安装新的依赖:
bun add nodemailer twilio ical-generator

现在, 让我们更新 src/index.ts 文件, 添加新的功能:

import { Elysia, t } from 'elysia'
import { html } from '@elysiajs/html'
import { staticPlugin } from '@elysiajs/static'
import { cookie } from '@elysiajs/cookie'
import { jwt } from '@elysiajs/jwt'
import { multipart } from '@elysiajs/multipart'
import { Client } from '@libsql/client'
import * as oauth from 'oauth4webapi'
import { writeFile, mkdir } from 'fs/promises'
import { join } from 'path'
import nodemailer from 'nodemailer'
import twilio from 'twilio'
import ical from 'ical-generator'
 
const db = new Client({
  url: 'YOUR_TURSO_DATABASE_URL',
  authToken: 'YOUR_TURSO_AUTH_TOKEN'
})
 
// 配置邮件发送器
const emailTransporter = nodemailer.createTransport({
  host: 'smtp.example.com',
  port: 587,
  secure: false,
  auth: {
    user: 'your-email@example.com',
    pass: 'your-email-password'
  }
})
 
// 配置Twilio客户端
const twilioClient = twilio('YOUR_TWILIO_ACCOUNT_SID', 'YOUR_TWILIO_AUTH_TOKEN')
 
const app = new Elysia()
  // ... (保留之前的配置)
 
  // 更新个人资料
  .post('/profile', async ({ body, jwt, cookie: { auth } }) => {
    if (!auth) return 'Please login to update your profile'
    const { sub: userId } = await jwt.verify(auth)
    const { name, bio, skills, phone, resume, education_cert } = body
 
    // ... (保留之前的文件上传逻辑)
 
    await db.execute({
      sql: `UPDATE users SET name = ?, bio = ?, skills = ?, phone = ?,
            resume_url = COALESCE(?, resume_url), 
            education_cert_url = COALESCE(?, education_cert_url) 
            WHERE id = ?`,
      args: [name, bio, skills, phone, resumeUrl, educationCertUrl, userId]
    })
 
    return 'Profile updated successfully!'
  })
 
  // 应聘者申请职位
  .post('/apply/:id', async ({ params, jwt, cookie: { auth } }) => {
    if (!auth) return 'Please login to apply'
    const { sub: userId } = await jwt.verify(auth)
    const jobId = params.id
 
    // 检查是否已经申请过
    const existingApplication = await db.execute({
      sql: 'SELECT * FROM applications WHERE job_id = ? AND user_id = ?',
      args: [jobId, userId]
    })
 
    if (existingApplication.rows.length > 0) {
      return 'You have already applied for this job'
    }
 
    await db.execute({
      sql: 'INSERT INTO applications (job_id, user_id) VALUES (?, ?)',
      args: [jobId, userId]
    })
 
    // 获取用户和工作信息
    const user = await db.execute({
      sql: 'SELECT * FROM users WHERE id = ?',
      args: [userId]
    })
    const job = await db.execute({
      sql: 'SELECT * FROM jobs WHERE id = ?',
      Args: [jobId]
    })
 
    // 发送邮件通知
    Await emailTransporter.SendMail ({
      from: 'noreply@jobboard.com',
      to: user.rows[0].email,
      subject: `Application Received for ${job.rows[0].title}`,
      text: `Dear ${user.rows[0].name},\n\nYour application for ${job.rows[0].title} at ${job.rows[0].company} has been received. We will contact you soon with further details.\n\nBest regards,\nJob Board Team`
    })
 
    // 发送短信通知
    if (user.rows[0].phone) {
      await twilioClient.messages.create({
        body: `Your application for ${job.rows[0].title} at ${job.rows[0].company} has been received. Check your email for more details.`,
        from: 'YOUR_TWILIO_PHONE_NUMBER',
        to: user.rows[0].phone
      })
    }
 
    return 'Application submitted successfully! Check your email for confirmation.'
  })
 
  // 雇主安排面试
  .post('/schedule-interview', async ({ body }) => {
    const { jobId, userId, type, datetime, location, notes } = body
 
    await db.execute({
      sql: `INSERT INTO interviews (job_id, user_id, type, status, datetime, location, notes) 
            VALUES (?, ?, ?, 'scheduled', ?, ?, ?)`,
      args: [jobId, userId, type, datetime, location, notes]
    })
 
    // 获取用户和工作信息
    const user = await db.execute({
      sql: 'SELECT * FROM users WHERE id = ?',
      args: [userId]
    })
    const job = await db.execute({
      sql: 'SELECT * FROM jobs WHERE id = ?',
      args: [jobId]
    })
 
    // 创建iCal事件
    const cal = ical({ name: 'Interview Schedule' })
    cal.createEvent({
      start: new Date(datetime),
      end: new Date(new Date(datetime).getTime() + 60*60*1000), // 假设面试持续1小时
      summary: `Interview for ${job.rows[0].title}`,
      description: notes,
      location: location
    })
 
    // 发送邮件通知
    await emailTransporter.sendMail({
      from: 'noreply@jobboard.com',
      to: user.rows[0].email,
      subject: `Interview Scheduled for ${job.rows[0].title}`,
      text: `Dear ${user.rows[0].name},\n\nYour interview for ${job.rows[0].title} at ${job.rows[0].company} has been scheduled for ${datetime} at ${location}.\n\nNotes: ${notes}\n\nBest regards,\nJob Board Team`,
      icalEvent: {
        filename: 'interview.ics',
        method: 'REQUEST',
        content: cal.toString()
      }
    })
 
    // 发送短信通知
    if (user.rows[0].phone) {
      await twilioClient.messages.create({
        body: `Your interview for ${job.rows[0].title} has been scheduled for ${datetime}. Check your email for more details.`,
        from: 'YOUR_TWILIO_PHONE_NUMBER',
        to: user.rows[0].phone
      })
    }
 
    return 'Interview scheduled successfully!'
  })
 
  // 获取面试日程表
  .get('/interview-schedule', async ({ jwt, cookie: { auth } }) => {
    if (!auth) return 'Please login to view your interview schedule'
    const { sub: userId } = await jwt.verify(auth)
 
    const interviews = await db.execute({
      sql: `SELECT i.*, j.title, j.company 
            FROM interviews i 
            JOIN jobs j ON i.job_id = j.id 
            WHERE i.user_id = ? 
            ORDER BY i.datetime`,
      args: [userId]
    })
 
    Return interviews.Rows.Map (interview => `
      <div>
        <h3>${interview. Title} at ${interview. Company}</h3>
        <p>Type: ${interview.type}</p>
        <p>Date & Time: ${interview.datetime}</p>
        <p>Location: ${interview.location}</p>
        <p>Notes: ${interview.notes}</p>
        <p>Status: ${interview.status}</p>
      </div>
    `).join('')
  })
 
  // ... (保留之前的路由和其他功能)
 
  .listen(3000)
 
console.log(`Elysia is running at http://localhost:3000`)

这个更新版本添加了以下新功能:

  1. 短信和邮件通知: 当应聘者申请工作或面试被安排时, 系统会发送邮件和短信通知。
  2. 面试安排: 雇主可以为应聘者安排笔试或面试。
  3. ICal 日程生成: 系统会生成包含面试详情的 iCal 文件, 并通过邮件发送给应聘者。
  4. 面试日程表: 应聘者可以查看自己的面试日程表。

要使这个版本正常工作, 你需要:

  1. 更新 Turso 数据库结构。
  2. 配置 SMTP 服务器以发送邮件。
  3. 注册 Twilio 账户并配置短信发送服务。
  4. 确保你的服务器有足够的资源来处理这些额外的功能。

这个版本提供了一个更加完整的招聘网站框架, 包括通知系统和面试管理功能。你可以根据需要进一步优化 UI/UX, 添加更多的错误处理, 实现更复杂的面试安排算法, 或者添加其他功能, 如在线笔试系统、视频面试集成等。