编辑代码

// build.sbt 依赖配置
name := "OrderAnalysisTool"
version := "1.0"
scalaVersion := "2.13.12"

libraryDependencies ++= Seq(
  "io.circe" %% "circe-core" % "0.14.7",
  "io.circe" %% "circe-generic" % "0.14.7",
  "io.circe" %% "circe-parser" % "0.14.7"
)

// 主程序入口
object OrderAnalyzer {
  case class Order(
    orderId: String,
    userId: String,
    products: List[Product],
    orderTime: LocalDate
  ) {
    def totalAmount: Double = products.map(p => p.quantity * p.unitPrice).sum
  }

  case class Product(productId: String, quantity: Int, unitPrice: Double)

  // 内置示例数据
  val sampleData: String = """
    [
      {
        "orderId": "SAMPLE-001",
        "userId": "TEST-USER",
        "products": [{"productId": "P-001", "quantity": 2, "unitPrice": 99.99}],
        "orderTime": "2025-06-01"
      },
      {
        "orderId": "SAMPLE-002",
        "userId": "TEST-USER",
        "products": [{"productId": "P-002", "quantity": 1, "unitPrice": 499.00}],
        "orderTime": "2025-06-05"
      }
    ]
  """.stripMargin

  def main(args: Array[String]): Unit = {
    val parser = new scopt.OptionParser[Config] {
      head("OrderAnalyzer", "1.0")
      
      opt[String]('i', "input")
        .action((x, c) => c.copy(input = x))
        .text("输入JSON文件路径(默认使用内置示例数据)")
      
      opt[String]('o', "output")
        .action((x, c) => c.copy(output = x))
        .text("输出报告路径")
      
      opt[Int]('d', "days")
        .action((x, c) => c.copy(recentDays = x))
        .text("近N天订单分析(默认30天)")
    }

    parser.parse(args, Config("", "", 30)) match {
      case Some(config) => 
        runAnalysis(config).foreach { result =>
          println(s"分析完成,结果已保存至:${config.output}")
          generateCsvReport(result)
        }
      case None => // 错误处理由scopt自动完成
    }
  }

  case class Config(input: String, output: String, recentDays: Int)

  def runAnalysis(config: Config): Either[String, Map[String, Any]] = {
    import io.circe.parser._
    import io.circe.generic.auto._

    // 1. 数据加载
    val orders = loadOrders(config.input)
    
    // 2. 基础统计
    val stats = Map(
      "userSpending" -> userStatistics(orders),
      "topProducts" -> topSellingProducts(orders),
      "monthlyStats" -> monthlyStatistics(orders)
    )

    // 3. 数据筛选
    val filtered = Map(
      "highValue" -> highValueOrders(orders),
      "recentOrders" -> recentOrders(orders, config.recentDays)
    )

    Right(stats ++ filtered)
  }

  // 数据加载模块
  def loadOrders(filePath: String): Either[String, List[Order]] = {
    if (filePath.isEmpty) {
        println("[提示]使用内置数据...")
        parse(sampleData).map(_.asInstanceOf[List[Order]])
    } else{
    import scala.util.Try
    Try {
      val source = scala.io.Source.fromFile(filePath)
      val json = source.mkString
      source.close()
      decode[List[Order]](json)
    } match {
      case scala.util.Success(result) => Right(result)
      case scala.util.Failure(e) => Left(s"解析失败: ${e.getMessage}")
    }
   }
  }

  // 用户消费统计
  def userStatistics(orders: List[Order]): Map[String, Double] = {
    orders.groupBy(_.userId)
      .view
      .mapValues(_.map(_.totalAmount).sum)
      .toMap
  }

  // 畅销商品分析
  def topSellingProducts(orders: List[Order]): List[(String, Int)] = {
    orders.flatMap(_.products)
      .groupBy(_.productId)
      .view
      .mapValues(_.size)
      .toList
      .sortBy(-_._2)
      .take(3)
  }

  // 月度统计
  def monthlyStatistics(orders: List[Order]): Map[String, (Int, Double)] = {
    orders.groupBy(order => 
      s"${order.orderTime.getYear}-${order.orderTime.getMonthValue:02d}"
    ).view
      .mapValues { orders =>
        val count = orders.size
        val amount = orders.map(_.totalAmount).sum
        (count, amount)
      }
      .toMap
  }

  // 高价值订单筛选
  def highValueOrders(orders: List[Order]): List[Order] = {
    orders.filter(_.totalAmount > 500)
  }

  // 近期订单筛选
  def recentOrders(orders: List[Order], days: Int): List[Order] = {
    val cutoff = java.time.LocalDate.now.minusDays(days)
    orders.filter(_.orderTime.isAfter(cutoff))
  }

  // CSV报告生成(扩展功能)
  def generateCsvReport(data: Map[String, Any]): Unit = {
    import java.io.PrintWriter
    val writer = new PrintWriter(config.output)
    writer.println("指标,数值")
    
    data.foreach {
      case ("userSpending", m: Map[_, _]) => 
        m.foreach { case (k, v) => writer.println(s"用户 $k 消费额,$v") }
      case ("topProducts", l: List[_]) => 
        l.foreach { case (id, cnt) => writer.println(s"商品 $id 销量,$cnt") }
      case ("monthlyStats", m: Map[_, _]) => 
        m.foreach { case (k, (cnt, amt)) => 
          writer.println(s"月份 $k 订单数,$cnt | 金额,$amt")
        }
      case _ => // 其他数据项
    }
    
    writer.close()
  }
}