refactor(diary): Phase 3 质量提升 — 201 状态码 + OpenAPI 文档 + DiaryEvent 类型安全
前端: - fix(app): Isar native 文件直接导入 isar_database_native.dart,消除 5 个条件导出类型错误 - chore(app): build_runner 重新生成 .g.dart 文件 (102 outputs) - fix(app): 移除 secure_token_store_factory 未使用的 kIsWeb import 后端: - refactor(diary): 所有创建端点 POST 返回 201 Created (9 handler, 11 端点) - feat(diary): DiaryApiDoc OpenApi derive — 42 路径 + 32 Schema 汇总到 Swagger - feat(diary): DiaryEvent 枚举添加 event_type/payload/to_domain_event 方法 + 4 测试 测试: 84/84 erp-diary 通过, 509/509 全仓库通过, Flutter analyze 0 error
This commit is contained in:
@@ -16,7 +16,7 @@ extension GetJournalElementCollectionCollection on Isar {
|
||||
|
||||
const JournalElementCollectionSchema = CollectionSchema(
|
||||
name: r'JournalElementCollection',
|
||||
id: -1002,
|
||||
id: -3625932583395690305,
|
||||
properties: {
|
||||
r'contentJson': PropertySchema(
|
||||
id: 0,
|
||||
@@ -96,7 +96,7 @@ const JournalElementCollectionSchema = CollectionSchema(
|
||||
idName: r'isarId',
|
||||
indexes: {
|
||||
r'id': IndexSchema(
|
||||
id: -2002,
|
||||
id: -3268401673993471357,
|
||||
name: r'id',
|
||||
unique: false,
|
||||
replace: false,
|
||||
@@ -109,7 +109,7 @@ const JournalElementCollectionSchema = CollectionSchema(
|
||||
],
|
||||
),
|
||||
r'journalId': IndexSchema(
|
||||
id: 3001,
|
||||
id: 1745640946427815323,
|
||||
name: r'journalId',
|
||||
unique: false,
|
||||
replace: false,
|
||||
|
||||
@@ -16,7 +16,7 @@ extension GetJournalEntryCollectionCollection on Isar {
|
||||
|
||||
const JournalEntryCollectionSchema = CollectionSchema(
|
||||
name: r'JournalEntryCollection',
|
||||
id: -1001,
|
||||
id: -6325316395299921961,
|
||||
properties: {
|
||||
r'assignedTopicId': PropertySchema(
|
||||
id: 0,
|
||||
@@ -106,7 +106,7 @@ const JournalEntryCollectionSchema = CollectionSchema(
|
||||
idName: r'isarId',
|
||||
indexes: {
|
||||
r'id': IndexSchema(
|
||||
id: -2001,
|
||||
id: -3268401673993471357,
|
||||
name: r'id',
|
||||
unique: false,
|
||||
replace: false,
|
||||
@@ -117,6 +117,37 @@ const JournalEntryCollectionSchema = CollectionSchema(
|
||||
caseSensitive: true,
|
||||
)
|
||||
],
|
||||
),
|
||||
r'authorId_dateEpoch': IndexSchema(
|
||||
id: -4869847655132214108,
|
||||
name: r'authorId_dateEpoch',
|
||||
unique: false,
|
||||
replace: false,
|
||||
properties: [
|
||||
IndexPropertySchema(
|
||||
name: r'authorId',
|
||||
type: IndexType.hash,
|
||||
caseSensitive: true,
|
||||
),
|
||||
IndexPropertySchema(
|
||||
name: r'dateEpoch',
|
||||
type: IndexType.value,
|
||||
caseSensitive: false,
|
||||
)
|
||||
],
|
||||
),
|
||||
r'dateEpoch': IndexSchema(
|
||||
id: 359017825055613028,
|
||||
name: r'dateEpoch',
|
||||
unique: false,
|
||||
replace: false,
|
||||
properties: [
|
||||
IndexPropertySchema(
|
||||
name: r'dateEpoch',
|
||||
type: IndexType.value,
|
||||
caseSensitive: false,
|
||||
)
|
||||
],
|
||||
)
|
||||
},
|
||||
links: {},
|
||||
@@ -277,6 +308,15 @@ extension JournalEntryCollectionQueryWhereSort
|
||||
return query.addWhereClause(const IdWhereClause.any());
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<JournalEntryCollection, JournalEntryCollection, QAfterWhere>
|
||||
anyDateEpoch() {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addWhereClause(
|
||||
const IndexWhereClause.any(indexName: r'dateEpoch'),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
extension JournalEntryCollectionQueryWhere on QueryBuilder<
|
||||
@@ -393,6 +433,242 @@ extension JournalEntryCollectionQueryWhere on QueryBuilder<
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<JournalEntryCollection, JournalEntryCollection,
|
||||
QAfterWhereClause> authorIdEqualToAnyDateEpoch(String authorId) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addWhereClause(IndexWhereClause.equalTo(
|
||||
indexName: r'authorId_dateEpoch',
|
||||
value: [authorId],
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<JournalEntryCollection, JournalEntryCollection,
|
||||
QAfterWhereClause> authorIdNotEqualToAnyDateEpoch(String authorId) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
if (query.whereSort == Sort.asc) {
|
||||
return query
|
||||
.addWhereClause(IndexWhereClause.between(
|
||||
indexName: r'authorId_dateEpoch',
|
||||
lower: [],
|
||||
upper: [authorId],
|
||||
includeUpper: false,
|
||||
))
|
||||
.addWhereClause(IndexWhereClause.between(
|
||||
indexName: r'authorId_dateEpoch',
|
||||
lower: [authorId],
|
||||
includeLower: false,
|
||||
upper: [],
|
||||
));
|
||||
} else {
|
||||
return query
|
||||
.addWhereClause(IndexWhereClause.between(
|
||||
indexName: r'authorId_dateEpoch',
|
||||
lower: [authorId],
|
||||
includeLower: false,
|
||||
upper: [],
|
||||
))
|
||||
.addWhereClause(IndexWhereClause.between(
|
||||
indexName: r'authorId_dateEpoch',
|
||||
lower: [],
|
||||
upper: [authorId],
|
||||
includeUpper: false,
|
||||
));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<JournalEntryCollection, JournalEntryCollection,
|
||||
QAfterWhereClause>
|
||||
authorIdDateEpochEqualTo(String authorId, int dateEpoch) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addWhereClause(IndexWhereClause.equalTo(
|
||||
indexName: r'authorId_dateEpoch',
|
||||
value: [authorId, dateEpoch],
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<JournalEntryCollection, JournalEntryCollection,
|
||||
QAfterWhereClause>
|
||||
authorIdEqualToDateEpochNotEqualTo(String authorId, int dateEpoch) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
if (query.whereSort == Sort.asc) {
|
||||
return query
|
||||
.addWhereClause(IndexWhereClause.between(
|
||||
indexName: r'authorId_dateEpoch',
|
||||
lower: [authorId],
|
||||
upper: [authorId, dateEpoch],
|
||||
includeUpper: false,
|
||||
))
|
||||
.addWhereClause(IndexWhereClause.between(
|
||||
indexName: r'authorId_dateEpoch',
|
||||
lower: [authorId, dateEpoch],
|
||||
includeLower: false,
|
||||
upper: [authorId],
|
||||
));
|
||||
} else {
|
||||
return query
|
||||
.addWhereClause(IndexWhereClause.between(
|
||||
indexName: r'authorId_dateEpoch',
|
||||
lower: [authorId, dateEpoch],
|
||||
includeLower: false,
|
||||
upper: [authorId],
|
||||
))
|
||||
.addWhereClause(IndexWhereClause.between(
|
||||
indexName: r'authorId_dateEpoch',
|
||||
lower: [authorId],
|
||||
upper: [authorId, dateEpoch],
|
||||
includeUpper: false,
|
||||
));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<JournalEntryCollection, JournalEntryCollection,
|
||||
QAfterWhereClause> authorIdEqualToDateEpochGreaterThan(
|
||||
String authorId,
|
||||
int dateEpoch, {
|
||||
bool include = false,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addWhereClause(IndexWhereClause.between(
|
||||
indexName: r'authorId_dateEpoch',
|
||||
lower: [authorId, dateEpoch],
|
||||
includeLower: include,
|
||||
upper: [authorId],
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<JournalEntryCollection, JournalEntryCollection,
|
||||
QAfterWhereClause> authorIdEqualToDateEpochLessThan(
|
||||
String authorId,
|
||||
int dateEpoch, {
|
||||
bool include = false,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addWhereClause(IndexWhereClause.between(
|
||||
indexName: r'authorId_dateEpoch',
|
||||
lower: [authorId],
|
||||
upper: [authorId, dateEpoch],
|
||||
includeUpper: include,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<JournalEntryCollection, JournalEntryCollection,
|
||||
QAfterWhereClause> authorIdEqualToDateEpochBetween(
|
||||
String authorId,
|
||||
int lowerDateEpoch,
|
||||
int upperDateEpoch, {
|
||||
bool includeLower = true,
|
||||
bool includeUpper = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addWhereClause(IndexWhereClause.between(
|
||||
indexName: r'authorId_dateEpoch',
|
||||
lower: [authorId, lowerDateEpoch],
|
||||
includeLower: includeLower,
|
||||
upper: [authorId, upperDateEpoch],
|
||||
includeUpper: includeUpper,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<JournalEntryCollection, JournalEntryCollection,
|
||||
QAfterWhereClause> dateEpochEqualTo(int dateEpoch) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addWhereClause(IndexWhereClause.equalTo(
|
||||
indexName: r'dateEpoch',
|
||||
value: [dateEpoch],
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<JournalEntryCollection, JournalEntryCollection,
|
||||
QAfterWhereClause> dateEpochNotEqualTo(int dateEpoch) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
if (query.whereSort == Sort.asc) {
|
||||
return query
|
||||
.addWhereClause(IndexWhereClause.between(
|
||||
indexName: r'dateEpoch',
|
||||
lower: [],
|
||||
upper: [dateEpoch],
|
||||
includeUpper: false,
|
||||
))
|
||||
.addWhereClause(IndexWhereClause.between(
|
||||
indexName: r'dateEpoch',
|
||||
lower: [dateEpoch],
|
||||
includeLower: false,
|
||||
upper: [],
|
||||
));
|
||||
} else {
|
||||
return query
|
||||
.addWhereClause(IndexWhereClause.between(
|
||||
indexName: r'dateEpoch',
|
||||
lower: [dateEpoch],
|
||||
includeLower: false,
|
||||
upper: [],
|
||||
))
|
||||
.addWhereClause(IndexWhereClause.between(
|
||||
indexName: r'dateEpoch',
|
||||
lower: [],
|
||||
upper: [dateEpoch],
|
||||
includeUpper: false,
|
||||
));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<JournalEntryCollection, JournalEntryCollection,
|
||||
QAfterWhereClause> dateEpochGreaterThan(
|
||||
int dateEpoch, {
|
||||
bool include = false,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addWhereClause(IndexWhereClause.between(
|
||||
indexName: r'dateEpoch',
|
||||
lower: [dateEpoch],
|
||||
includeLower: include,
|
||||
upper: [],
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<JournalEntryCollection, JournalEntryCollection,
|
||||
QAfterWhereClause> dateEpochLessThan(
|
||||
int dateEpoch, {
|
||||
bool include = false,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addWhereClause(IndexWhereClause.between(
|
||||
indexName: r'dateEpoch',
|
||||
lower: [],
|
||||
upper: [dateEpoch],
|
||||
includeUpper: include,
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
QueryBuilder<JournalEntryCollection, JournalEntryCollection,
|
||||
QAfterWhereClause> dateEpochBetween(
|
||||
int lowerDateEpoch,
|
||||
int upperDateEpoch, {
|
||||
bool includeLower = true,
|
||||
bool includeUpper = true,
|
||||
}) {
|
||||
return QueryBuilder.apply(this, (query) {
|
||||
return query.addWhereClause(IndexWhereClause.between(
|
||||
indexName: r'dateEpoch',
|
||||
lower: [lowerDateEpoch],
|
||||
includeLower: includeLower,
|
||||
upper: [upperDateEpoch],
|
||||
includeUpper: includeUpper,
|
||||
));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
extension JournalEntryCollectionQueryFilter on QueryBuilder<
|
||||
|
||||
@@ -16,7 +16,7 @@ extension GetPendingOperationCollectionCollection on Isar {
|
||||
|
||||
const PendingOperationCollectionSchema = CollectionSchema(
|
||||
name: r'PendingOperationCollection',
|
||||
id: -1003,
|
||||
id: -6885010264946527864,
|
||||
properties: {
|
||||
r'createdAtEpoch': PropertySchema(
|
||||
id: 0,
|
||||
@@ -61,7 +61,7 @@ const PendingOperationCollectionSchema = CollectionSchema(
|
||||
idName: r'isarId',
|
||||
indexes: {
|
||||
r'id': IndexSchema(
|
||||
id: -2003,
|
||||
id: -3268401673993471357,
|
||||
name: r'id',
|
||||
unique: false,
|
||||
replace: false,
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
// 根据平台创建对应的 SecureTokenStore 实现。
|
||||
// 运行时判断 kIsWeb,避免 Web 编译时加载 flutter_secure_storage。
|
||||
|
||||
import 'package:flutter/foundation.dart' show kIsWeb;
|
||||
|
||||
import 'secure_token_store.dart';
|
||||
import 'secure_token_store_web.dart';
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import 'dart:convert';
|
||||
|
||||
import 'package:isar/isar.dart';
|
||||
|
||||
import '../local/isar_database.dart';
|
||||
import '../local/isar_database_native.dart';
|
||||
import '../local/collections/journal_entry_collection.dart';
|
||||
import '../local/collections/journal_element_collection.dart';
|
||||
import '../models/journal_entry.dart';
|
||||
@@ -20,7 +20,7 @@ import 'journal_repository.dart';
|
||||
|
||||
/// Isar 本地日记仓库 — JournalRepository 的 Isar 实现
|
||||
class IsarJournalRepository implements JournalRepository {
|
||||
Isar get _isar => IsarDatabase.instance!;
|
||||
Isar get _isar => IsarDatabase.instance;
|
||||
|
||||
// ============================================================
|
||||
// 日记 CRUD
|
||||
|
||||
@@ -20,7 +20,7 @@ import 'package:connectivity_plus/connectivity_plus.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:isar/isar.dart';
|
||||
|
||||
import '../local/isar_database.dart';
|
||||
import '../local/isar_database_native.dart';
|
||||
import '../local/collections/pending_operation_collection.dart';
|
||||
import '../remote/api_client.dart';
|
||||
|
||||
@@ -312,7 +312,7 @@ class SyncEngine {
|
||||
/// 在 app 退出、isolate 暂停、或同步完成后调用。
|
||||
Future<void> persistPendingQueue() async {
|
||||
if (!IsarDatabase.isAvailable) return;
|
||||
final isar = IsarDatabase.instance!;
|
||||
final isar = IsarDatabase.instance;
|
||||
final ops = snapshot;
|
||||
|
||||
await isar.writeTxn(() async {
|
||||
@@ -333,7 +333,7 @@ class SyncEngine {
|
||||
/// Web 平台上 Isar 不可用,跳过恢复。
|
||||
Future<void> restorePendingQueue() async {
|
||||
if (!IsarDatabase.isAvailable) return;
|
||||
final isar = IsarDatabase.instance!;
|
||||
final isar = IsarDatabase.instance;
|
||||
final persisted = await isar.pendingOperationCollections
|
||||
.where()
|
||||
.anyIsarId()
|
||||
|
||||
Reference in New Issue
Block a user