[!简介]

当然可以。我们来创建一个更复杂的例子,涉及到多层嵌套对象、数组、和自定义类型。这个例子将模拟一个在线商店的订单系统。

首先,我们定义一些复杂的类型:

import { Elysia, t } from 'elysia';
 
// 自定义类型
const ProductType = t.Enum(['Physical', 'Digital', 'Service']);
 
// 商品类型
const Product = t.Object({
  id: t.String(),
  name: t.String(),
  price: t.Number(),
  type: ProductType,
  attributes: t.Record(t.String(), t.Any())
});
 
// 地址类型
const Address = t.Object({
  street: t.String(),
  city: t.String(),
  state: t.String(),
  country: t.String(),
  zipCode: t.String()
});
 
// 客户类型
const Customer = t.Object({
  id: t.String(),
  name: t.String(),
  email: t.String(),
  phone: t.Optional(t.String()),
  address: Address
});
 
// 订单项类型
const OrderItem = t.Object({
  product: Product,
  quantity: t.Number(),
  customizations: t.Optional(t.Array(t.String()))
});
 
// 支付信息类型
const PaymentInfo = t.Object({
  method: t.Enum(['CreditCard', 'PayPal', 'BankTransfer']),
  transactionId: t.String(),
  amount: t.Number()
});
 
// 完整的订单类型
const Order = t.Object({
  orderId: t.String(),
  customer: Customer,
  items: t.Array(OrderItem),
  totalAmount: t.Number(),
  status: t.Enum(['Pending', 'Processing', 'Shipped', 'Delivered']),
  paymentInfo: PaymentInfo,
  notes: t.Optional(t.String()),
  createdAt: t.String(),
  lastUpdated: t.String()
});

现在,我们创建一个处理订单的路由:

const app = new Elysia();
 
app.post('/process-order', ({ body }) => {
  // 复杂的订单处理逻辑
  const order = body;
  
  // 验证订单
  if (order.items.length === 0) {
    return { error: 'Order must contain at least one item' };
  }
 
  // 计算总金额
  const calculatedTotal = order.items.reduce((total, item) => 
    total + (item.product.price * item.quantity), 0);
  
  if (calculatedTotal !== order.totalAmount) {
    return { error: 'Total amount mismatch' };
  }
 
  // 处理每个订单项
  order.items.forEach(item => {
    if (item.product.type === 'Physical') {
      // 检查库存
      checkInventory(item.product.id, item.quantity);
    } else if (item.product.type === 'Digital') {
      // 准备数字下载链接
      prepareDigitalDownload(item.product.id);
    }
  });
 
  // 处理支付
  processPayment(order.paymentInfo);
 
  // 更新订单状态
  order.status = 'Processing';
  order.lastUpdated = new Date().toISOString();
 
  // 保存订单到数据库
  saveOrderToDatabase(order);
 
  // 发送确认邮件
  sendOrderConfirmationEmail(order.customer.email, order);
 
  return { 
    message: 'Order processed successfully', 
    orderId: order.orderId 
  };
}, {
  body: Order
});
 
app.listen(3000);
 
// 模拟的辅助函数
function checkInventory(productId: string, quantity: number) {
  console.log(`Checking inventory for product ${productId}, quantity: ${quantity}`);
}
 
function prepareDigitalDownload(productId: string) {
  console.log(`Preparing digital download for product ${productId}`);
}
 
function processPayment(paymentInfo: any) {
  console.log(`Processing payment: ${JSON.stringify(paymentInfo)}`);
}
 
function saveOrderToDatabase(order: any) {
  console.log(`Saving order to database: ${order.orderId}`);
}
 
function sendOrderConfirmationEmail(email: string, order: any) {
  console.log(`Sending confirmation email to ${email} for order ${order.orderId}`);
}

这个例子展示了如何处理一个非常复杂的订单对象。订单包含了客户信息、多个订单项(每个都有自己的产品信息和定制选项)、支付信息等。

在 HTMX 中,你可以这样触发这个复杂的请求:

<button hx-post="/process-order" 
        hx-trigger="click"
        hx-vals='{"orderId":"ORD12345","customer":{"id":"CUST789","name":"Alice Johnson","email":"alice@example.com","address":{"street":"123 Main St","city":"Springfield","state":"IL","country":"USA","zipCode":"62701"}},"items":[{"product":{"id":"PROD1","name":"Laptop","price":999.99,"type":"Physical","attributes":{"brand":"TechBrand","model":"X1"}},"quantity":1},{"product":{"id":"PROD2","name":"Software License","price":199.99,"type":"Digital","attributes":{"version":"2.0"}},"quantity":1,"customizations":["Extra User"]}],"totalAmount":1199.98,"status":"Pending","paymentInfo":{"method":"CreditCard","transactionId":"TXN987654","amount":1199.98},"createdAt":"2023-06-15T10:30:00Z","lastUpdated":"2023-06-15T10:30:00Z"}'>
  Process Order
</button>

这个例子展示了如何处理非常复杂的参数结构。它包括:

  1. 多层嵌套对象(如客户信息中的地址)
  2. 数组(订单项)
  3. 枚举类型(产品类型、订单状态、支付方式)
  4. 可选字段(客户电话、订单备注)
  5. 自定义类型(如 Product, Address 等)

在实际应用中,你可能需要将这个复杂的 JSON 数据分解成多个表单字段,或者使用 JavaScript 来动态构建这个对象。此外,服务器端的处理逻辑也可能更加复杂,包括数据库操作、第三方 API 调用等。

这个例子展示了 TypeScript 和 Elysia 如何优雅地处理复杂的数据结构,同时也展示了如何在后端实现复杂的业务逻辑。