Skip to content

Commit e136cbc

Browse files
committed
chore: move business logic to service instead of internal
1 parent 9d85412 commit e136cbc

11 files changed

Lines changed: 450 additions & 448 deletions

File tree

file_classification_cli/src/bin/file_classification_cli.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ enum FileActions {
8383
/// 根据组ID查询文件
8484
ListByGroupId {
8585
#[clap(short, long)]
86-
group_id: i64,
86+
group_id: i32,
8787
},
8888
/// 更新文件
8989
UpdateByConditions {
@@ -190,7 +190,7 @@ enum TagActions {
190190
/// 根据组ID查询标签
191191
ListByGroupId {
192192
#[clap(short, long)]
193-
group_id: i64,
193+
group_id: i32,
194194
},
195195
/// 更新标签
196196
UpdateByConditions {

file_classification_core/src/internal/file_group.rs

Lines changed: 61 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ use crate::model::schema::{file_groups, files};
88
use diesel::prelude::*;
99
use crate::utils::database::AnyConnection;
1010
use crate::model::models::{File, FileGroupOrderBy, FileGroupQueryOptions, OrderDirection};
11-
use crate::utils::errors::AppError;
12-
use crate::utils::errors::AppError::CannotUnbindPrimaryGroup;
1311

1412
/// 插入一个新的文件-分组关联记录
1513
///
@@ -30,38 +28,48 @@ pub fn insert_file_group(
3028

3129
/// 根据 DTO 中的信息删除一个文件-分组关联记录
3230
///
33-
/// 注意:若尝试解除文件与其主分组的关系,则会抛出 `CannotUnbindPrimaryGroup` 错误。
34-
///
3531
/// 参数:
3632
/// - `conn`: 数据库连接对象
3733
/// - `file_group_dto`: 包含要删除记录信息的 DTO 对象
3834
///
3935
/// 返回值:
40-
/// 成功时返回影响的行数(通常应为1),失败则返回自定义错误或数据库错误
41-
pub fn delete_file_group_by_id(
36+
/// 成功时返回影响的行数(通常应为1),失败则返回数据库错误
37+
pub fn delete_file_group_by_dto(
4238
conn: &mut AnyConnection,
4339
file_group_dto: &FileGroupDTO,
44-
) -> Result<usize, AppError> {
45-
// 检查是否试图解绑文件的主分组
46-
let file = files::table
47-
.select(File::as_select())
48-
.filter(files::id.eq(file_group_dto.file_id))
49-
.first(conn);
50-
51-
if file.is_ok() && file?.group_id == file_group_dto.group_id {
52-
return Err(CannotUnbindPrimaryGroup);
53-
}
54-
55-
// 执行实际的删除操作
40+
) -> Result<usize, diesel::result::Error> {
5641
diesel::delete(
5742
file_groups::table
5843
.filter(file_groups::group_id.eq(file_group_dto.group_id))
5944
.filter(file_groups::file_id.eq(file_group_dto.file_id)),
6045
)
6146
.execute(conn)
62-
.map_err(AppError::from) // 将 QueryResult 转换为 AppError
6347
}
6448

49+
/// 根据多个 DTO 对象批量删除文件-分组关联记录(带事务支持)
50+
///
51+
/// 参数:
52+
/// - `conn`: 数据库连接对象
53+
/// - `file_group_dtos`: 包含要删除记录信息的 DTO 对象向量
54+
///
55+
/// 返回值:
56+
/// 成功时返回影响的行数,失败则返回数据库错误
57+
pub fn delete_file_groups_by_dtos(
58+
conn: &mut AnyConnection,
59+
file_group_dtos: Vec<FileGroupDTO>,
60+
) -> Result<usize, diesel::result::Error> {
61+
conn.transaction::<usize, diesel::result::Error, _>(|conn| {
62+
let mut total_deleted = 0;
63+
64+
for dto in file_group_dtos {
65+
total_deleted += delete_file_group_by_dto(conn, &dto)?;
66+
}
67+
68+
Ok(total_deleted)
69+
})
70+
}
71+
72+
6573
/// 构建符合 Diesel 查询语法的条件表达式
6674
///
6775
/// 参数:
@@ -199,60 +207,43 @@ pub fn select_file_groups_by_conditions_with_options(
199207
.select(FileGroupDTO::as_select())
200208
.load(conn)
201209
}
202-
/// 根据给定条件批量删除文件-分组关联记录
203-
///
204-
/// 注意:若尝试解除文件与其主分组的关系,则会抛出 `CannotUnbindPrimaryGroup` 错误。
205-
/// 该操作在事务中执行,任何一个删除失败都会导致整个操作回滚。
210+
211+
/// 检查指定分组是否为空(没有关联的文件)
206212
///
207213
/// 参数:
208214
/// - `conn`: 数据库连接对象
209-
/// - `conditions`: 删除条件集合,各条件之间采用 AND 连接
215+
/// - `group_id`: 要检查的分组ID
210216
///
211217
/// 返回值:
212-
/// 成功删除的记录数目或数据库错误
213-
pub fn delete_file_groups_by_conditions(
214-
conn: &mut AnyConnection,
215-
conditions: Vec<FileGroupCondition>,
216-
) -> Result<usize, AppError> {
217-
// 开始事务
218-
conn.transaction::<usize, AppError, _>(|conn| {
219-
// 首先查询将要删除的所有记录
220-
let mut select_query = file_groups::table.into_boxed::<<AnyConnection as Connection>::Backend>();
221-
222-
// 应用所有条件到查询
223-
for condition in &conditions {
224-
let boxed_condition = build_file_group_condition(condition.clone());
225-
select_query = select_query.filter(boxed_condition);
226-
}
227-
228-
// 获取将要删除的记录
229-
let records_to_delete: Vec<FileGroupDTO> = select_query
230-
.select(FileGroupDTO::as_select())
231-
.load(conn)?;
232-
233-
// 检查每条记录是否是文件的主分组关联
234-
for record in &records_to_delete {
235-
let file = files::table
236-
.select(File::as_select())
237-
.filter(files::id.eq(record.file_id))
238-
.first(conn);
239-
240-
// 如果文件存在且该分组是其主分组,则不允许删除
241-
if file.is_ok() && file?.group_id == record.group_id {
242-
return Err(CannotUnbindPrimaryGroup);
243-
}
244-
}
245-
246-
// 执行实际的删除操作
247-
let mut delete_query = diesel::delete(file_groups::table).into_boxed::<<AnyConnection as Connection>::Backend>();
248-
249-
// 应用所有删除条件
250-
for condition in conditions {
251-
let boxed_condition = build_file_group_condition(condition);
252-
delete_query = delete_query.filter(boxed_condition);
253-
}
254-
255-
let deleted_count = delete_query.execute(conn)?;
256-
Ok(deleted_count)
257-
})
218+
/// 成功时返回布尔值,true表示分组为空,false表示分组不为空;失败则返回数据库错误
219+
pub fn check_group_empty(conn: &mut AnyConnection, group_id: i32) -> Result<bool, diesel::result::Error> {
220+
let count = file_groups::table
221+
.filter(file_groups::group_id.eq(group_id))
222+
.count()
223+
.first::<i64>(conn)?;
224+
225+
Ok(count == 0)
258226
}
227+
228+
// /// 根据给定条件批量删除文件-分组关联记录
229+
// ///
230+
// /// 参数:
231+
// /// - `conn`: 数据库连接对象
232+
// /// - `conditions`: 删除条件集合,各条件之间采用 AND 连接
233+
// ///
234+
// /// 返回值:
235+
// /// 成功删除的记录数目或数据库错误
236+
// pub fn delete_file_groups_by_conditions(
237+
// conn: &mut AnyConnection,
238+
// conditions: Vec<FileGroupCondition>,
239+
// ) -> Result<usize, diesel::result::Error> {
240+
// let mut query = diesel::delete(file_groups::table).into_boxed::<<AnyConnection as Connection>::Backend>();
241+
//
242+
// // 应用所有删除条件
243+
// for condition in conditions {
244+
// let boxed_condition = build_file_group_condition(condition);
245+
// query = query.filter(boxed_condition);
246+
// }
247+
//
248+
// query.execute(conn)
249+
// }

file_classification_core/src/internal/files.rs

Lines changed: 85 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use diesel::sql_types::Bool;
1919
///
2020
/// 返回值:
2121
/// 成功时返回影响的行数(通常应为1),失败则返回数据库错误
22-
pub fn create_file(conn: &mut AnyConnection, new_file: &CreateFileDTO) -> Result<usize, diesel::result::Error> {
22+
pub fn insert_file(conn: &mut AnyConnection, new_file: &CreateFileDTO) -> Result<usize, diesel::result::Error> {
2323
diesel::insert_into(files::table)
2424
.values(new_file).execute(conn)
2525
}
@@ -48,7 +48,7 @@ pub fn find_file_by_id(conn: &mut AnyConnection, _id: i32) -> Result<Option<File
4848
///
4949
/// 返回值:
5050
/// 成功时返回影响的行数(通常应为1),失败则返回数据库错误
51-
pub fn increase_file_reference_count(
51+
pub fn increase_file_reference_count_by_id(
5252
conn: &mut AnyConnection,
5353
file_id: i32,
5454
) -> Result<usize, diesel::result::Error> {
@@ -65,7 +65,7 @@ pub fn increase_file_reference_count(
6565
///
6666
/// 返回值:
6767
/// 成功时返回影响的行数(通常应为1),失败则返回数据库错误
68-
pub fn decrease_file_reference_count(
68+
pub fn decrease_file_reference_count_by_id(
6969
conn: &mut AnyConnection,
7070
file_id: i32,
7171
) -> Result<usize, diesel::result::Error> {
@@ -74,6 +74,42 @@ pub fn decrease_file_reference_count(
7474
.execute(conn)
7575
}
7676

77+
/// 根据多个文件ID批量增加文件引用计数
78+
///
79+
/// 参数:
80+
/// - `conn`: 数据库连接对象
81+
/// - `file_ids`: 文件ID列表
82+
///
83+
/// 返回值:
84+
/// 成功时返回影响的行数,失败则返回数据库错误
85+
pub fn increase_file_reference_count_by_ids(
86+
conn: &mut AnyConnection,
87+
file_ids: Vec<i32>,
88+
) -> Result<usize, diesel::result::Error> {
89+
diesel::update(files::table)
90+
.filter(files::id.eq_any(file_ids))
91+
.set(files::reference_count.eq(files::reference_count + 1))
92+
.execute(conn)
93+
}
94+
95+
/// 根据多个文件ID批量减少文件引用计数
96+
///
97+
/// 参数:
98+
/// - `conn`: 数据库连接对象
99+
/// - `file_ids`: 文件ID列表
100+
///
101+
/// 返回值:
102+
/// 成功时返回影响的行数,失败则返回数据库错误
103+
pub fn decrease_file_reference_count_by_ids(
104+
conn: &mut AnyConnection,
105+
file_ids: Vec<i32>,
106+
) -> Result<usize, diesel::result::Error> {
107+
diesel::update(files::table)
108+
.filter(files::id.eq_any(file_ids))
109+
.set(files::reference_count.eq(files::reference_count - 1))
110+
.execute(conn)
111+
}
112+
77113
/// [已弃用] 根据过滤条件查询文件列表
78114
///
79115
/// 参数:
@@ -84,7 +120,7 @@ pub fn decrease_file_reference_count(
84120
/// 返回值:
85121
/// 查询成功的文件记录列表或数据库错误
86122
#[deprecated]
87-
pub fn select_files(
123+
pub fn select_files_by_filter(
88124
conn: &mut AnyConnection,
89125
search_input: FileFilter,
90126
limit: i64,
@@ -127,6 +163,26 @@ pub fn delete_file_by_id(conn: &mut AnyConnection, file_id: i32) -> Result<usize
127163
diesel::delete(files.filter(files::id.eq(file_id))).execute(conn)
128164
}
129165

166+
/// 根据多个文件ID批量删除文件记录
167+
///
168+
/// 参数:
169+
/// - `conn`: 数据库连接对象
170+
/// - `file_ids`: 要删除的文件ID列表
171+
///
172+
/// 返回值:
173+
/// 成功时返回影响的行数,失败则返回数据库错误
174+
pub fn delete_files_by_ids(
175+
conn: &mut AnyConnection,
176+
file_ids: Vec<i32>,
177+
) -> Result<usize, diesel::result::Error> {
178+
diesel::delete(
179+
files::table
180+
.filter(files::id.eq_any(file_ids))
181+
)
182+
.execute(conn)
183+
}
184+
185+
130186
/// 构建符合 Diesel 查询语法的条件表达式
131187
///
132188
/// 参数:
@@ -318,28 +374,28 @@ pub fn update_files_by_conditions(
318374
query.set(update_set).execute(conn)
319375
}
320376

321-
/// 根据给定条件批量删除文件记录
322-
///
323-
/// 参数:
324-
/// - `conn`: 数据库连接对象
325-
/// - `conditions`: 删除条件集合,各条件之间采用 AND 连接
326-
///
327-
/// 返回值:
328-
/// 成功删除的记录数目或数据库错误
329-
pub fn delete_files_by_conditions(
330-
conn: &mut AnyConnection,
331-
conditions: Vec<FileCondition>,
332-
) -> Result<usize, diesel::result::Error> {
333-
let mut query = diesel::delete(files::table).into_boxed::<<AnyConnection as Connection>::Backend>();
334-
335-
// 应用所有条件
336-
for condition in conditions {
337-
let boxed_condition = build_file_condition(condition);
338-
query = query.filter(boxed_condition);
339-
}
340-
341-
query.execute(conn)
342-
}
377+
// /// 根据给定条件批量删除文件记录
378+
// ///
379+
// /// 参数:
380+
// /// - `conn`: 数据库连接对象
381+
// /// - `conditions`: 删除条件集合,各条件之间采用 AND 连接
382+
// ///
383+
// /// 返回值:
384+
// /// 成功删除的记录数目或数据库错误
385+
// pub fn delete_files_by_conditions(
386+
// conn: &mut AnyConnection,
387+
// conditions: Vec<FileCondition>,
388+
// ) -> Result<usize, diesel::result::Error> {
389+
// let mut query = diesel::delete(files::table).into_boxed::<<AnyConnection as Connection>::Backend>();
390+
//
391+
// // 应用所有条件
392+
// for condition in conditions {
393+
// let boxed_condition = build_file_condition(condition);
394+
// query = query.filter(boxed_condition);
395+
// }
396+
//
397+
// query.execute(conn)
398+
// }
343399

344400
/// 根据给定条件批量增加文件引用计数
345401
///
@@ -397,15 +453,15 @@ pub fn decrease_files_reference_count_by_conditions(
397453
///
398454
/// 返回值:
399455
/// 查询成功的文件记录列表或数据库错误
400-
pub fn select_file_by_group_id(
456+
pub fn select_files_by_group_id(
401457
conn: &mut AnyConnection,
402-
other_group_id: i64,
458+
other_group_id: i32,
403459
) -> Result<Vec<File>, diesel::result::Error> {
404460
use crate::model::schema::file_groups;
405461

406462
files::table
407463
.inner_join(file_groups::table.on(files::id.eq(file_groups::file_id)))
408-
.filter(file_groups::group_id.eq(other_group_id as i32))
464+
.filter(file_groups::group_id.eq(other_group_id))
409465
.select(File::as_select())
410466
.load(conn)
411467
}

0 commit comments

Comments
 (0)