项目结构:

ruby
//!# encoding: utf-8
//!# 版权所有 2026 ©涂聚文有限公司™ ®
//!# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
//!# 描述:
//!# Author : geovindu,Geovin Du 涂聚文.
//!# IDE : RustRover 2025.1.1 Rust rustc 1.98.1
//!# os : windows 10
//!# database : mysql 9.0 sql server 2025, postgreSQL 18.0 Oracle 21c Neo4j
//!# Datetime : 2026/9/27 23:42
//!# User : geovindu
//!# Product : RustRover
//!# Project : jewelrysearch
//!# File : models.rs
/// 珠宝领域模型
#[derive(Debug, Clone)]
pub struct JewelryItem {
pub id: String,
pub name: String,
pub category: JewelryCategory,
pub weight: f64,
pub price: f64,
pub stock: u32,
}
/// 珠宝分类(枚举,可扩展)
#[derive(Debug, Clone, PartialEq)]
pub enum JewelryCategory {
Ring,
Necklace,
Bracelet,
Earring,
Pendant,
Other(String),
}
/// 钻石领域模型
#[derive(Debug, Clone)]
pub struct Diamond {
pub cert_no: String,
pub carat: f64,
pub color: String,
pub clarity: String,
pub cut: String,
pub price_per_carat: f64,
}
/// 会员等级领域模型
#[derive(Debug, Clone)]
pub struct MemberLevel {
pub min_consumption: f64,
pub level_name: String,
pub discount: f64,
}
//!# encoding: utf-8
//!# 版权所有 2026 ©涂聚文有限公司™ ®
//!# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
//!# 描述:
//!# Author : geovindu,Geovin Du 涂聚文.
//!# IDE : RustRover 2025.1.1 Rust rustc 1.98.1
//!# os : windows 10
//!# database : mysql 9.0 sql server 2025, postgreSQL 18.0 Oracle 21c Neo4j
//!# Datetime : 2026/9/27 23:42
//!# User : geovindu
//!# Product : RustRover
//!# Project : jewelrysearch
//!# File : repositories.rs
use super::models::{JewelryItem, Diamond, MemberLevel};
/// 珠宝仓储接口
pub trait JewelryRepository: Send + Sync {
fn find_by_id(&self, id: &str) -> Option<JewelryItem>;
fn find_by_category(&self, category: &str) -> Vec<JewelryItem>;
fn find_all(&self) -> Vec<JewelryItem>;
}
/// 钻石仓储接口
pub trait DiamondRepository: Send + Sync {
fn find_by_carat(&self, target_carat: f64, tolerance: f64) -> Option<Diamond>;
fn find_all_sorted_by_carat(&self) -> Vec<Diamond>;
}
/// 会员仓储接口
pub trait MemberLevelRepository: Send + Sync {
fn find_level_by_consumption(&self, consumption: f64) -> Option<MemberLevel>;
}
//!# encoding: utf-8
//!# 版权所有 2026 ©涂聚文有限公司™ ®
//!# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
//!# 描述:
//!# Author : geovindu,Geovin Du 涂聚文.
//!# IDE : RustRover 2025.1.1 Rust rustc 1.98.1
//!# os : windows 10
//!# database : mysql 9.0 sql server 2025, postgreSQL 18.0 Oracle 21c Neo4j
//!# Datetime : 2026/9/27 23:43
//!# User : geovindu
//!# Product : RustRover
//!# Project : jewelrysearch
//!# File : services.rs
use super::models::{Diamond, JewelryItem};
/// 珠宝搜索领域服务
pub struct JewelrySearchService;
impl JewelrySearchService {
/// 线性搜索:根据名称模糊匹配
pub fn search_by_name<'a>(items: &'a [JewelryItem], keyword: &str) -> Vec<&'a JewelryItem> {
items
.iter()
.filter(|item| item.name.to_lowercase().contains(&keyword.to_lowercase()))
.collect()
}
/// 价格区间筛选
pub fn filter_by_price_range<'a>(items: &'a [JewelryItem], min: f64, max: f64) -> Vec<&'a JewelryItem> {
items
.iter()
.filter(|item| item.price >= min && item.price <= max)
.collect()
}
}
/// 钻石搜索领域服务
pub struct DiamondSearchService;
impl DiamondSearchService {
/// 二分查找:在已排序的钻石中查找最接近目标克拉的钻石
pub fn binary_search_by_carat(diamonds: &[Diamond], target_carat: f64, tolerance: f64) -> Option<usize> {
let mut left = 0;
let mut right = diamonds.len();
while left < right {
let mid = left + (right - left) / 2;
let diff = diamonds[mid].carat - target_carat;
if diff.abs() <= tolerance {
return Some(mid);
} else if diamonds[mid].carat < target_carat {
left = mid + 1;
} else {
right = mid;
}
}
None
}
}
ruby
//!# encoding: utf-8
//!# 版权所有 2026 ©涂聚文有限公司™ ®
//!# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
//!# 描述:
//!# Author : geovindu,Geovin Du 涂聚文.
//!# IDE : RustRover 2025.1.1 Rust rustc 1.98.1
//!# os : windows 10
//!# database : mysql 9.0 sql server 2025, postgreSQL 18.0 Oracle 21c Neo4j
//!# Datetime : 2026/9/27 23:45
//!# User : geovindu
//!# Product : RustRover
//!# Project : jewelrysearch
//!# File : commands.rs
// 命令处理器(用于写操作,如新增/更新珠宝)
// 此处留空,可根据需要扩展
pub struct JewelryCommandHandler;
//!# encoding: utf-8
//!# 版权所有 2026 ©涂聚文有限公司™ ®
//!# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
//!# 描述:
//!# Author : geovindu,Geovin Du 涂聚文.
//!# IDE : RustRover 2025.1.1 Rust rustc 1.98.1
//!# os : windows 10
//!# database : mysql 9.0 sql server 2025, postgreSQL 18.0 Oracle 21c Neo4j
//!# Datetime : 2026/9/27 23:44
//!# User : geovindu
//!# Product : RustRover
//!# Project : jewelrysearch
//!# File : dto.rs
use crate::domain::models::JewelryCategory;
/// 珠宝搜索请求 DTO
#[derive(Debug)]
pub struct SearchJewelryRequest {
pub keyword: Option<String>,
pub category: Option<JewelryCategory>,
pub min_price: Option<f64>,
pub max_price: Option<f64>,
}
/// 珠宝搜索结果 DTO
#[derive(Debug)]
pub struct JewelrySearchResult {
pub id: String,
pub name: String,
pub category: String,
pub price: f64,
pub stock: u32,
}
/// 钻石搜索请求 DTO
#[derive(Debug)]
pub struct SearchDiamondRequest {
pub target_carat: f64,
pub tolerance: f64,
}
/// 会员等级查询请求 DTO
#[derive(Debug)]
pub struct GetMemberLevelRequest {
pub consumption: f64,
}
//!# encoding: utf-8
//!# 版权所有 2026 ©涂聚文有限公司™ ®
//!# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
//!# 描述:
//!# Author : geovindu,Geovin Du 涂聚文.
//!# IDE : RustRover 2025.1.1 Rust rustc 1.98.1
//!# os : windows 10
//!# database : mysql 9.0 sql server 2025, postgreSQL 18.0 Oracle 21c Neo4j
//!# Datetime : 2026/9/27 23:44
//!# User : geovindu
//!# Product : RustRover
//!# Project : jewelrysearch
//!# File : queries.rs
use crate::domain::repositories::{JewelryRepository, DiamondRepository, MemberLevelRepository};
use crate::domain::services::{JewelrySearchService, DiamondSearchService};
use super::dto::*;
/// 珠宝查询处理器
pub struct JewelryQueryHandler<R: JewelryRepository> {
repository: R,
}
impl<R: JewelryRepository> JewelryQueryHandler<R> {
pub fn new(repository: R) -> Self {
Self { repository }
}
pub fn search(&self, request: SearchJewelryRequest) -> Vec<JewelrySearchResult> {
let all_items = self.repository.find_all();
let mut results: Vec<&crate::domain::models::JewelryItem> = all_items.iter().collect();
// 按关键词过滤
if let Some(ref keyword) = request.keyword {
results = JewelrySearchService::search_by_name(
&results.iter().map(|i| (*i).clone()).collect::<Vec<_>>(),
keyword,
)
.into_iter()
.map(|item| {
// 重新从原始列表中获取引用
all_items.iter().find(|i| i.id == item.id).unwrap()
})
.collect();
}
// 按分类过滤
if let Some(ref category) = request.category {
results.retain(|item| &item.category == category);
}
// 按价格区间过滤
if let (Some(min), Some(max)) = (request.min_price, request.max_price) {
results = JewelrySearchService::filter_by_price_range(
&results.iter().map(|i| (*i).clone()).collect::<Vec<_>>(),
min,
max,
)
.into_iter()
.map(|item| {
all_items.iter().find(|i| i.id == item.id).unwrap()
})
.collect();
}
results
.into_iter()
.map(|item| JewelrySearchResult {
id: item.id.clone(),
name: item.name.clone(),
category: format!("{:?}", item.category),
price: item.price,
stock: item.stock,
})
.collect()
}
}
/// 钻石查询处理器
pub struct DiamondQueryHandler<R: DiamondRepository> {
repository: R,
}
impl<R: DiamondRepository> DiamondQueryHandler<R> {
pub fn new(repository: R) -> Self {
Self { repository }
}
pub fn search_by_carat(&self, request: SearchDiamondRequest) -> Option<crate::domain::models::Diamond> {
let diamonds = self.repository.find_all_sorted_by_carat();
let idx = DiamondSearchService::binary_search_by_carat(
&diamonds,
request.target_carat,
request.tolerance,
);
idx.map(|i| diamonds[i].clone())
}
}
/// 会员等级查询处理器
pub struct MemberLevelQueryHandler<R: MemberLevelRepository> {
repository: R,
}
impl<R: MemberLevelRepository> MemberLevelQueryHandler<R> {
pub fn new(repository: R) -> Self {
Self { repository }
}
pub fn get_level(&self, consumption: f64) -> Option<crate::domain::models::MemberLevel> {
self.repository.find_level_by_consumption(consumption)
}
}
//!# encoding: utf-8
//!# 版权所有 2026 ©涂聚文有限公司™ ®
//!# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
//!# 描述:
//!# Author : geovindu,Geovin Du 涂聚文.
//!# IDE : RustRover 2025.1.1 Rust rustc 1.98.1
//!# os : windows 10
//!# database : mysql 9.0 sql server 2025, postgreSQL 18.0 Oracle 21c Neo4j
//!# Datetime : 2026/9/27 23:47
//!# User : geovindu
//!# Product : RustRover
//!# Project : jewelrysearch
//!# File : api.rs
use crate::application::queries::{JewelryQueryHandler, DiamondQueryHandler, MemberLevelQueryHandler};
use crate::application::dto::*;
/// 珠宝搜索 API
pub struct JewelrySearchApi {
jewelry_handler: JewelryQueryHandler<crate::infrastructure::repositories::InMemoryJewelryRepository>,
diamond_handler: DiamondQueryHandler<crate::infrastructure::repositories::InMemoryDiamondRepository>,
member_handler: MemberLevelQueryHandler<crate::infrastructure::repositories::InMemoryMemberLevelRepository>,
}
impl JewelrySearchApi {
pub fn new(
jewelry_handler: JewelryQueryHandler<crate::infrastructure::repositories::InMemoryJewelryRepository>,
diamond_handler: DiamondQueryHandler<crate::infrastructure::repositories::InMemoryDiamondRepository>,
member_handler: MemberLevelQueryHandler<crate::infrastructure::repositories::InMemoryMemberLevelRepository>,
) -> Self {
Self {
jewelry_handler,
diamond_handler,
member_handler,
}
}
pub fn search_jewelry(&self, request: SearchJewelryRequest) -> Vec<JewelrySearchResult> {
self.jewelry_handler.search(request)
}
pub fn search_diamond(&self, request: SearchDiamondRequest) -> Option<crate::domain::models::Diamond> {
self.diamond_handler.search_by_carat(request)
}
pub fn get_member_level(&self, consumption: f64) -> Option<crate::domain::models::MemberLevel> {
self.member_handler.get_level(consumption)
}
}
调用:
ruby
//!# encoding: utf-8
//!# 版权所有 2026 ©涂聚文有限公司™ ®
//!# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
//!# 描述:
//!# Author : geovindu,Geovin Du 涂聚文.
//!# IDE : RustRover 2025.1.1 Rust rustc 1.98.1
//!# os : windows 10
//!# database : mysql 9.0 sql server 2025, postgreSQL 18.0 Oracle 21c Neo4j
//!# Datetime : 2026/9/27 23:41
//!# User : geovindu
//!# Product : RustRover
//!# Project : jewelrysearch
//!# File : main.rs
mod domain;
mod application;
mod infrastructure;
mod interfaces;
use std::sync::Arc;
use application::dto::*;
use infrastructure::data_store::InMemoryDataStore;
use infrastructure::repositories::*;
use application::queries::*;
use interfaces::api::JewelrySearchApi;
fn main() {
// 初始化数据存储
let store = Arc::new(InMemoryDataStore::new());
// 初始化仓储
let jewelry_repo = InMemoryJewelryRepository::new(store.clone());
let diamond_repo = InMemoryDiamondRepository::new(store.clone());
let member_repo = InMemoryMemberLevelRepository::new(store.clone());
// 初始化查询处理器
let jewelry_handler = JewelryQueryHandler::new(jewelry_repo);
let diamond_handler = DiamondQueryHandler::new(diamond_repo);
let member_handler = MemberLevelQueryHandler::new(member_repo);
// 初始化 API
let api = JewelrySearchApi::new(jewelry_handler, diamond_handler, member_handler);
// 示例 1:搜索珠宝
println!("=== 搜索珠宝 ===");
let request = SearchJewelryRequest {
keyword: Some("戒指".to_string()),
category: None,
min_price: None,
max_price: None,
};
let results = api.search_jewelry(request);
for r in &results {
println!(" {} | {} | {:.2}元 | 库存: {}", r.name, r.category, r.price, r.stock);
}
// 示例 2:搜索钻石
println!("\n=== 搜索1克拉钻石 ===");
let diamond_request = SearchDiamondRequest {
target_carat: 1.00,
tolerance: 0.01,
};
match api.search_diamond(diamond_request) {
Some(d) => {
println!(" 证书号: {}", d.cert_no);
println!(" 克拉: {} | 颜色: {} | 净度: {} | 切工: {}", d.carat, d.color, d.clarity, d.cut);
println!(" 单价: {:.0}元/克拉 | 总价: {:.2}元", d.price_per_carat, d.carat * d.price_per_carat);
}
None => println!(" 未找到匹配的钻石"),
}
// 示例 3:查询会员等级
println!("\n=== 查询会员等级 ===");
match api.get_member_level(25000.0) {
Some(level) => {
println!(" 等级: {} | 折扣: {:.0}折", level.level_name, level.discount * 10.0);
}
None => println!(" 无会员等级"),
}
}
输出:
