diff --git a/apps/im_app/assets/loginData.json b/apps/im_app/assets/loginData.json new file mode 100644 index 0000000..222e7c1 --- /dev/null +++ b/apps/im_app/assets/loginData.json @@ -0,0 +1,31 @@ +{ + "code": 0, + "message": "OK", + "data": { + "account_id": "1713925030yFMUBu", + "profile": { + "uid": 2137067, + "uuid": "1713925030yFMUBu", + "last_online": 1772819822, + "profile_pic": "Image/7e/f5/7ef5b60dd83a34a74c164a21fbd1f098/7ef5b60dd83a34a74c164a21fbd1f098.jpg", + "profile_pic_gaussian": "", + "nickname": "Happi(哈比)", + "contact": "86552205", + "country_code": "+65", + "email": "happi@winwayinfo.com", + "recovery_email": "", + "username": "happi", + "bio": "", + "relationship": 2, + "user_alias": null, + "channel_id": 1, + "channel_group_id": 1, + "hint": "1111" + }, + "nonce": "", + "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOjIxMzcwNjcsInVkaWQiOjI2NjI2MzcsInNpZCI6IjE3NzI4NjU0NDc0Z1c2VWc9PSIsImlzcyI6ImFiYy5jb20iLCJhdWQiOlsidXNlciJdLCJleHAiOjE3NzQxNjE0NDcsIm5iZiI6MTc3Mjg2NTQ0NywiaWF0IjoxNzcyODY1NDQ3fQ.gUL6hyKgyPP8Tw9y7kRSq-ndNKfV9uGFhU4YKiQzg0I", + "refresh_token": "ps0FF3XayvnJB_P8Cnfu7w-uD781b1-vfmUjbrONZxI=", + "device_id": "SP1A.210812", + "login_data": "" + } +} diff --git a/apps/im_app/lib/data/local/drift/app_database.dart b/apps/im_app/lib/data/local/drift/app_database.dart index 638e0f7..adbcd58 100644 --- a/apps/im_app/lib/data/local/drift/app_database.dart +++ b/apps/im_app/lib/data/local/drift/app_database.dart @@ -29,25 +29,25 @@ class AppDatabase extends _$AppDatabase { return {}; } return { - Favourite: database.favourites, - Sound: database.sounds, - Tag: database.tags, - PendingFriendRequestHistory: database.pendingFriendRequestHistories, - Message: database.messages, - RecentMiniApp: database.recentMiniApps, - Retry: database.retries, - Group: database.groups, - FavoriteMiniApp: database.favoriteMiniApps, - DiscoverMiniApp: database.discoverMiniApps, - ChatCategory: database.chatCategories, - ChatBot: database.chatBots, - FavouriteDetail: database.favouriteDetails, - UserRequestHistory: database.userRequestHistories, - Workspace: database.workspaces, - User: database.users, - ExploreMiniApp: database.exploreMiniApps, - CallLog: database.callLogs, - Chat: database.chats, + DriftFavourite: database.favourites, + DriftSound: database.sounds, + DriftTag: database.tags, + DriftPendingFriendRequestHistory: database.pendingFriendRequestHistories, + DriftMessage: database.messages, + DriftRecentMiniApp: database.recentMiniApps, + DriftRetry: database.retries, + DriftGroup: database.groups, + DriftFavoriteMiniApp: database.favoriteMiniApps, + DriftDiscoverMiniApp: database.discoverMiniApps, + DriftChatCategory: database.chatCategories, + DriftChatBot: database.chatBots, + DriftFavouriteDetail: database.favouriteDetails, + DriftUserRequestHistory: database.userRequestHistories, + DriftWorkspace: database.workspaces, + DriftUser: database.users, + DriftExploreMiniApp: database.exploreMiniApps, + DriftCallLog: database.callLogs, + DriftChat: database.chats, }; } diff --git a/apps/im_app/lib/data/local/drift/tables/call_logs.dart b/apps/im_app/lib/data/local/drift/tables/call_logs.dart index c956bc8..5aae228 100644 --- a/apps/im_app/lib/data/local/drift/tables/call_logs.dart +++ b/apps/im_app/lib/data/local/drift/tables/call_logs.dart @@ -1,6 +1,6 @@ import 'package:drift/drift.dart'; -@DataClassName('CallLog') +@DataClassName('DriftCallLog') class CallLogs extends Table { TextColumn get id => text()(); IntColumn get callerId => integer().nullable()(); diff --git a/apps/im_app/lib/data/local/drift/tables/chat_bots.dart b/apps/im_app/lib/data/local/drift/tables/chat_bots.dart index eecffaa..c0837f4 100644 --- a/apps/im_app/lib/data/local/drift/tables/chat_bots.dart +++ b/apps/im_app/lib/data/local/drift/tables/chat_bots.dart @@ -1,6 +1,6 @@ import 'package:drift/drift.dart'; -@DataClassName('ChatBot') +@DataClassName('DriftChatBot') class ChatBots extends Table { IntColumn get id => integer()(); TextColumn get name => text().nullable()(); diff --git a/apps/im_app/lib/data/local/drift/tables/chat_categories.dart b/apps/im_app/lib/data/local/drift/tables/chat_categories.dart index 2bd07d3..42b3f6c 100644 --- a/apps/im_app/lib/data/local/drift/tables/chat_categories.dart +++ b/apps/im_app/lib/data/local/drift/tables/chat_categories.dart @@ -1,9 +1,9 @@ import 'package:drift/drift.dart'; -@DataClassName('ChatCategory') +@DataClassName('DriftChatCategory') class ChatCategories extends Table { IntColumn get id => integer()(); - TextColumn get name => text().nullable().unique()(); + TextColumn get name => text().nullable()(); TextColumn get includedChatIds => text().nullable()(); TextColumn get excludedChatIds => text().nullable()(); IntColumn get seq => integer().nullable()(); diff --git a/apps/im_app/lib/data/local/drift/tables/chats.dart b/apps/im_app/lib/data/local/drift/tables/chats.dart index 61eea86..eaff81a 100644 --- a/apps/im_app/lib/data/local/drift/tables/chats.dart +++ b/apps/im_app/lib/data/local/drift/tables/chats.dart @@ -1,6 +1,6 @@ import 'package:drift/drift.dart'; -@DataClassName('Chat') +@DataClassName('DriftChat') class Chats extends Table { IntColumn get id => integer()(); IntColumn get typ => integer().nullable()(); diff --git a/apps/im_app/lib/data/local/drift/tables/discover_mini_apps.dart b/apps/im_app/lib/data/local/drift/tables/discover_mini_apps.dart index a3fbb06..44ba236 100644 --- a/apps/im_app/lib/data/local/drift/tables/discover_mini_apps.dart +++ b/apps/im_app/lib/data/local/drift/tables/discover_mini_apps.dart @@ -1,6 +1,6 @@ import 'package:drift/drift.dart'; -@DataClassName('DiscoverMiniApp') +@DataClassName('DriftDiscoverMiniApp') class DiscoverMiniApps extends Table { TextColumn get id => text()(); TextColumn get name => text().nullable()(); diff --git a/apps/im_app/lib/data/local/drift/tables/explore_mini_apps.dart b/apps/im_app/lib/data/local/drift/tables/explore_mini_apps.dart index b4c2949..73d5750 100644 --- a/apps/im_app/lib/data/local/drift/tables/explore_mini_apps.dart +++ b/apps/im_app/lib/data/local/drift/tables/explore_mini_apps.dart @@ -1,6 +1,6 @@ import 'package:drift/drift.dart'; -@DataClassName('ExploreMiniApp') +@DataClassName('DriftExploreMiniApp') class ExploreMiniApps extends Table { TextColumn get id => text()(); TextColumn get name => text().nullable()(); diff --git a/apps/im_app/lib/data/local/drift/tables/favorite_mini_apps.dart b/apps/im_app/lib/data/local/drift/tables/favorite_mini_apps.dart index 3f61047..9e38bb7 100644 --- a/apps/im_app/lib/data/local/drift/tables/favorite_mini_apps.dart +++ b/apps/im_app/lib/data/local/drift/tables/favorite_mini_apps.dart @@ -1,6 +1,6 @@ import 'package:drift/drift.dart'; -@DataClassName('FavoriteMiniApp') +@DataClassName('DriftFavoriteMiniApp') class FavoriteMiniApps extends Table { TextColumn get id => text()(); TextColumn get name => text().nullable()(); diff --git a/apps/im_app/lib/data/local/drift/tables/favourite_details.dart b/apps/im_app/lib/data/local/drift/tables/favourite_details.dart index ea1ed95..678af16 100644 --- a/apps/im_app/lib/data/local/drift/tables/favourite_details.dart +++ b/apps/im_app/lib/data/local/drift/tables/favourite_details.dart @@ -1,6 +1,6 @@ import 'package:drift/drift.dart'; -@DataClassName('FavouriteDetail') +@DataClassName('DriftFavouriteDetail') class FavouriteDetails extends Table { IntColumn get id => integer().autoIncrement()(); TextColumn get relatedId => text().withDefault(const Constant(''))(); diff --git a/apps/im_app/lib/data/local/drift/tables/favourites.dart b/apps/im_app/lib/data/local/drift/tables/favourites.dart index d2b2758..289e1d8 100644 --- a/apps/im_app/lib/data/local/drift/tables/favourites.dart +++ b/apps/im_app/lib/data/local/drift/tables/favourites.dart @@ -1,6 +1,6 @@ import 'package:drift/drift.dart'; -@DataClassName('Favourite') +@DataClassName('DriftFavourite') class Favourites extends Table { IntColumn get id => integer()(); TextColumn get parentId => text().withDefault(const Constant(''))(); diff --git a/apps/im_app/lib/data/local/drift/tables/groups.dart b/apps/im_app/lib/data/local/drift/tables/groups.dart index 228d491..61da3ba 100644 --- a/apps/im_app/lib/data/local/drift/tables/groups.dart +++ b/apps/im_app/lib/data/local/drift/tables/groups.dart @@ -1,6 +1,6 @@ import 'package:drift/drift.dart'; -@DataClassName('Group') +@DataClassName('DriftGroup') class Groups extends Table { IntColumn get id => integer()(); IntColumn get userJoinDate => integer().nullable()(); diff --git a/apps/im_app/lib/data/local/drift/tables/message.dart b/apps/im_app/lib/data/local/drift/tables/message.dart index bd64691..30bb7c4 100644 --- a/apps/im_app/lib/data/local/drift/tables/message.dart +++ b/apps/im_app/lib/data/local/drift/tables/message.dart @@ -1,6 +1,6 @@ import 'package:drift/drift.dart'; -@DataClassName('Message') +@DataClassName('DriftMessage') class Messages extends Table { IntColumn get id => integer()(); IntColumn get messageId => integer().nullable()(); diff --git a/apps/im_app/lib/data/local/drift/tables/pending_friend_request_histories.dart b/apps/im_app/lib/data/local/drift/tables/pending_friend_request_histories.dart index 05787b6..cddf2e6 100644 --- a/apps/im_app/lib/data/local/drift/tables/pending_friend_request_histories.dart +++ b/apps/im_app/lib/data/local/drift/tables/pending_friend_request_histories.dart @@ -1,6 +1,6 @@ import 'package:drift/drift.dart'; -@DataClassName('PendingFriendRequestHistory') +@DataClassName('DriftPendingFriendRequestHistory') class PendingFriendRequestHistories extends Table { IntColumn get id => integer()(); IntColumn get uid => integer()(); diff --git a/apps/im_app/lib/data/local/drift/tables/recent_mini_apps.dart b/apps/im_app/lib/data/local/drift/tables/recent_mini_apps.dart index c149979..043b176 100644 --- a/apps/im_app/lib/data/local/drift/tables/recent_mini_apps.dart +++ b/apps/im_app/lib/data/local/drift/tables/recent_mini_apps.dart @@ -1,6 +1,6 @@ import 'package:drift/drift.dart'; -@DataClassName('RecentMiniApp') +@DataClassName('DriftRecentMiniApp') class RecentMiniApps extends Table { TextColumn get id => text()(); TextColumn get name => text().nullable()(); diff --git a/apps/im_app/lib/data/local/drift/tables/retries.dart b/apps/im_app/lib/data/local/drift/tables/retries.dart index 19ad126..ca39eb6 100644 --- a/apps/im_app/lib/data/local/drift/tables/retries.dart +++ b/apps/im_app/lib/data/local/drift/tables/retries.dart @@ -1,6 +1,6 @@ import 'package:drift/drift.dart'; -@DataClassName('Retry') +@DataClassName('DriftRetry') class Retries extends Table { IntColumn get id => integer().autoIncrement()(); IntColumn get uid => integer().nullable()(); diff --git a/apps/im_app/lib/data/local/drift/tables/sounds.dart b/apps/im_app/lib/data/local/drift/tables/sounds.dart index 84173f3..0e5eec1 100644 --- a/apps/im_app/lib/data/local/drift/tables/sounds.dart +++ b/apps/im_app/lib/data/local/drift/tables/sounds.dart @@ -1,6 +1,6 @@ import 'package:drift/drift.dart'; -@DataClassName('Sound') +@DataClassName('DriftSound') class Sounds extends Table { IntColumn get id => integer()(); TextColumn get filePath => text().withDefault(const Constant(''))(); diff --git a/apps/im_app/lib/data/local/drift/tables/tags.dart b/apps/im_app/lib/data/local/drift/tables/tags.dart index 15db57e..8da5fdc 100644 --- a/apps/im_app/lib/data/local/drift/tables/tags.dart +++ b/apps/im_app/lib/data/local/drift/tables/tags.dart @@ -1,6 +1,6 @@ import 'package:drift/drift.dart'; -@DataClassName('Tag') +@DataClassName('DriftTag') class Tags extends Table { IntColumn get id => integer().autoIncrement()(); IntColumn get uid => integer().nullable()(); diff --git a/apps/im_app/lib/data/local/drift/tables/user_request_histories.dart b/apps/im_app/lib/data/local/drift/tables/user_request_histories.dart index d04e802..4ce2660 100644 --- a/apps/im_app/lib/data/local/drift/tables/user_request_histories.dart +++ b/apps/im_app/lib/data/local/drift/tables/user_request_histories.dart @@ -1,6 +1,6 @@ import 'package:drift/drift.dart'; -@DataClassName('UserRequestHistory') +@DataClassName('DriftUserRequestHistory') class UserRequestHistories extends Table { IntColumn get id => integer()(); IntColumn get status => integer().nullable()(); diff --git a/apps/im_app/lib/data/local/drift/tables/users.dart b/apps/im_app/lib/data/local/drift/tables/users.dart index 57d48e5..b6f9cf9 100644 --- a/apps/im_app/lib/data/local/drift/tables/users.dart +++ b/apps/im_app/lib/data/local/drift/tables/users.dart @@ -1,9 +1,9 @@ import 'package:drift/drift.dart'; -@DataClassName('User') +@DataClassName('DriftUser') class Users extends Table { IntColumn get id => integer().autoIncrement()(); - IntColumn get uid => integer().nullable()(); + IntColumn get uid => integer().unique()(); TextColumn get uuid => text().nullable()(); IntColumn get lastOnline => integer().nullable()(); TextColumn get profilePic => text().nullable()(); @@ -36,6 +36,7 @@ class Users extends Table { TextColumn get publicKey => text().nullable()(); IntColumn get configBits => integer().withDefault(const Constant(0))(); TextColumn get hint => text().nullable()(); + @override String get tableName => 'user'; } \ No newline at end of file diff --git a/apps/im_app/lib/data/local/drift/tables/workspaces.dart b/apps/im_app/lib/data/local/drift/tables/workspaces.dart index 4b53b57..ea91f74 100644 --- a/apps/im_app/lib/data/local/drift/tables/workspaces.dart +++ b/apps/im_app/lib/data/local/drift/tables/workspaces.dart @@ -1,6 +1,6 @@ import 'package:drift/drift.dart'; -@DataClassName('Workspace') +@DataClassName('DriftWorkspace') class Workspaces extends Table { IntColumn get id => integer()(); TextColumn get name => text().nullable()(); diff --git a/apps/im_app/lib/data/models/call_log_dto.dart b/apps/im_app/lib/data/models/call_log_dto.dart new file mode 100644 index 0000000..d493247 --- /dev/null +++ b/apps/im_app/lib/data/models/call_log_dto.dart @@ -0,0 +1,122 @@ +import 'package:drift/drift.dart'; +import 'package:im_app/data/local/drift/app_database.dart'; +import 'package:im_app/domain/entities/call_log.dart'; + +/// 通话记录 DTO(Data Transfer Object) +/// +/// local / remote 共用的数据传输对象。 +/// 提供与 Domain Entity [CallLog] 之间的双向转换。 +class CallLogDto { + final String id; + final int? callerId; + final int? receiverId; + final int? chatId; + final int? duration; + final int? videoCall; + final int? createdAt; + final int? updatedAt; + final int? endedAt; + final int? status; + final int? isDeleted; + final int? deletedAt; + final int? isRead; + + const CallLogDto({ + required this.id, + this.callerId, + this.receiverId, + this.chatId, + this.duration, + this.videoCall, + this.createdAt, + this.updatedAt, + this.endedAt, + this.status, + this.isDeleted, + this.deletedAt, + this.isRead, + }); + + factory CallLogDto.fromJson(Map json) => CallLogDto( + id: json['id'] as String, + callerId: json['caller_id'], + receiverId: json['receiver_id'], + chatId: json['chat_id'], + duration: json['duration'], + videoCall: json['video_call'], + createdAt: json['created_at'], + updatedAt: json['updated_at'], + endedAt: json['ended_at'], + status: json['status'], + isDeleted: json['is_deleted'], + deletedAt: json['deleted_at'], + isRead: json['is_read'], + ); + + Map toJson() => { + 'id': id, + 'caller_id': callerId, + 'receiver_id': receiverId, + 'chat_id': chatId, + 'duration': duration, + 'video_call': videoCall, + 'created_at': createdAt, + 'updated_at': updatedAt, + 'ended_at': endedAt, + 'status': status, + 'is_deleted': isDeleted, + 'deleted_at': deletedAt, + 'is_read': isRead, + }; + + /// DTO → Domain Entity + CallLog toEntity() => CallLog( + id: id, + callerId: callerId, + receiverId: receiverId, + chatId: chatId, + duration: duration, + videoCall: videoCall, + createdAt: createdAt, + updatedAt: updatedAt, + endedAt: endedAt, + status: status, + isDeleted: isDeleted, + deletedAt: deletedAt, + isRead: isRead, + ); + + /// Domain Entity → DTO + factory CallLogDto.fromEntity(CallLog callLog) => CallLogDto( + id: callLog.id, + callerId: callLog.callerId, + receiverId: callLog.receiverId, + chatId: callLog.chatId, + duration: callLog.duration, + videoCall: callLog.videoCall, + createdAt: callLog.createdAt, + updatedAt: callLog.updatedAt, + endedAt: callLog.endedAt, + status: callLog.status, + isDeleted: callLog.isDeleted, + deletedAt: callLog.deletedAt, + isRead: callLog.isRead, + ); + + /// DTO → Drift Companion (for DB insert/update) + CallLogsCompanion toCompanion() => CallLogsCompanion( + id: Value(id), + callerId: Value(callerId), + receiverId: Value(receiverId), + chatId: Value(chatId), + duration: Value(duration), + videoCall: Value(videoCall), + createdAt: Value(createdAt), + updatedAt: Value(updatedAt), + endedAt: Value(endedAt), + status: Value(status), + isDeleted: Value(isDeleted), + deletedAt: Value(deletedAt), + isRead: Value(isRead), + ); +} \ No newline at end of file diff --git a/apps/im_app/lib/data/models/chat_bot_dto.dart b/apps/im_app/lib/data/models/chat_bot_dto.dart new file mode 100644 index 0000000..adf1b29 --- /dev/null +++ b/apps/im_app/lib/data/models/chat_bot_dto.dart @@ -0,0 +1,179 @@ +import 'package:drift/drift.dart'; +import 'package:im_app/data/local/drift/app_database.dart'; +import 'package:im_app/domain/entities/chat_bot.dart'; + +/// 聊天机器人 DTO +class ChatBotDto { + final int id; + final String? name; + final String? username; + final int? botUserId; + final String? icon; + final String? iconGaussian; + final String? description; + final String? token; + final int? flag; + final int? status; + final String? webhook; + final String? commands; + final String? banner; + final int? channelId; + final int? channelGroupId; + final int? deletedAt; + final String? internalWebhook; + final int? mode; + final String? redirectUrl; + final int? isInvitable; + final int? isAllowForward; + final String? tips; + + const ChatBotDto({ + required this.id, + this.name, + this.username, + this.botUserId, + this.icon, + this.iconGaussian, + this.description, + this.token, + this.flag, + this.status, + this.webhook, + this.commands, + this.banner, + this.channelId, + this.channelGroupId, + this.deletedAt, + this.internalWebhook, + this.mode, + this.redirectUrl, + this.isInvitable, + this.isAllowForward, + this.tips, + }); + + factory ChatBotDto.fromJson(Map json) => ChatBotDto( + id: json['id'] as int, + name: json['name'], + username: json['username'], + botUserId: json['bot_user_id'], + icon: json['icon'], + iconGaussian: json['icon_gaussian'], + description: json['description'], + token: json['token'], + flag: json['flag'], + status: json['status'], + webhook: json['webhook'], + commands: json['commands'], + banner: json['banner'], + channelId: json['channel_id'], + channelGroupId: json['channel_group_id'], + deletedAt: json['deleted_at'], + internalWebhook: json['internal_webhook'], + mode: json['mode'], + redirectUrl: json['redirect_url'], + isInvitable: json['is_invitable'], + isAllowForward: json['is_allow_forward'], + tips: json['tips'], + ); + + Map toJson() => { + 'id': id, + 'name': name, + 'username': username, + 'bot_user_id': botUserId, + 'icon': icon, + 'icon_gaussian': iconGaussian, + 'description': description, + 'token': token, + 'flag': flag, + 'status': status, + 'webhook': webhook, + 'commands': commands, + 'banner': banner, + 'channel_id': channelId, + 'channel_group_id': channelGroupId, + 'deleted_at': deletedAt, + 'internal_webhook': internalWebhook, + 'mode': mode, + 'redirect_url': redirectUrl, + 'is_invitable': isInvitable, + 'is_allow_forward': isAllowForward, + 'tips': tips, + }; + + ChatBot toEntity() => ChatBot( + id: id, + name: name, + username: username, + botUserId: botUserId, + icon: icon, + iconGaussian: iconGaussian, + description: description, + token: token, + flag: flag, + status: status, + webhook: webhook, + commands: commands, + banner: banner, + channelId: channelId, + channelGroupId: channelGroupId, + deletedAt: deletedAt, + internalWebhook: internalWebhook, + mode: mode, + redirectUrl: redirectUrl, + isInvitable: isInvitable, + isAllowForward: isAllowForward, + tips: tips, + ); + + factory ChatBotDto.fromEntity(ChatBot chatBot) => ChatBotDto( + id: chatBot.id, + name: chatBot.name, + username: chatBot.username, + botUserId: chatBot.botUserId, + icon: chatBot.icon, + iconGaussian: chatBot.iconGaussian, + description: chatBot.description, + token: chatBot.token, + flag: chatBot.flag, + status: chatBot.status, + webhook: chatBot.webhook, + commands: chatBot.commands, + banner: chatBot.banner, + channelId: chatBot.channelId, + channelGroupId: chatBot.channelGroupId, + deletedAt: chatBot.deletedAt, + internalWebhook: chatBot.internalWebhook, + mode: chatBot.mode, + redirectUrl: chatBot.redirectUrl, + isInvitable: chatBot.isInvitable, + isAllowForward: chatBot.isAllowForward, + tips: chatBot.tips, + ); + + ChatBotsCompanion toCompanion() => ChatBotsCompanion( + id: Value(id), + name: Value(name), + username: Value(username), + botUserId: Value(botUserId), + icon: Value(icon), + iconGaussian: Value(iconGaussian), + description: Value(description), + token: Value(token), + flag: Value(flag), + status: Value(status), + webhook: Value(webhook ?? ''), + commands: Value(commands ?? '[]'), + banner: Value(banner), + channelId: Value(channelId), + channelGroupId: Value(channelGroupId), + deletedAt: Value(deletedAt), + internalWebhook: Value(internalWebhook), + mode: Value(mode), + redirectUrl: Value(redirectUrl), + isInvitable: Value(isInvitable), + isAllowForward: Value(isAllowForward), + tips: Value(tips), + ); +} \ No newline at end of file diff --git a/apps/im_app/lib/data/models/chat_category_dto.dart b/apps/im_app/lib/data/models/chat_category_dto.dart new file mode 100644 index 0000000..5b6bf24 --- /dev/null +++ b/apps/im_app/lib/data/models/chat_category_dto.dart @@ -0,0 +1,90 @@ +import 'package:drift/drift.dart'; +import 'package:im_app/data/local/drift/app_database.dart'; +import 'package:im_app/domain/entities/chat_category.dart'; + +/// 聊天分类 DTO +class ChatCategoryDto { + final int id; + final String? name; + final String? includedChatIds; + final String? excludedChatIds; + final int? seq; + final int isHide; + final int createdAt; + final int updatedAt; + final int deletedAt; + + const ChatCategoryDto({ + required this.id, + this.name, + this.includedChatIds, + this.excludedChatIds, + this.seq, + this.isHide = 0, + this.createdAt = 0, + this.updatedAt = 0, + this.deletedAt = 0, + }); + + factory ChatCategoryDto.fromJson(Map json) => + ChatCategoryDto( + id: json['id'] as int, + name: json['name'], + includedChatIds: json['included_chat_ids'], + excludedChatIds: json['excluded_chat_ids'], + seq: json['seq'], + isHide: json['is_hide'] ?? 0, + createdAt: json['created_at'] ?? 0, + updatedAt: json['updated_at'] ?? 0, + deletedAt: json['deleted_at'] ?? 0, + ); + + Map toJson() => { + 'id': id, + 'name': name, + 'included_chat_ids': includedChatIds, + 'excluded_chat_ids': excludedChatIds, + 'seq': seq, + 'is_hide': isHide, + 'created_at': createdAt, + 'updated_at': updatedAt, + 'deleted_at': deletedAt, + }; + + ChatCategory toEntity() => ChatCategory( + id: id, + name: name, + includedChatIds: includedChatIds, + excludedChatIds: excludedChatIds, + seq: seq, + isHide: isHide, + createdAt: createdAt, + updatedAt: updatedAt, + deletedAt: deletedAt, + ); + + factory ChatCategoryDto.fromEntity(ChatCategory chatCategory) => + ChatCategoryDto( + id: chatCategory.id, + name: chatCategory.name, + includedChatIds: chatCategory.includedChatIds, + excludedChatIds: chatCategory.excludedChatIds, + seq: chatCategory.seq, + isHide: chatCategory.isHide, + createdAt: chatCategory.createdAt, + updatedAt: chatCategory.updatedAt, + deletedAt: chatCategory.deletedAt, + ); + + ChatCategoriesCompanion toCompanion() => ChatCategoriesCompanion( + id: Value(id), + name: Value(name), + includedChatIds: Value(includedChatIds), + excludedChatIds: Value(excludedChatIds), + seq: Value(seq), + isHide: Value(isHide), + createdAt: Value(createdAt), + updatedAt: Value(updatedAt), + deletedAt: Value(deletedAt), + ); +} \ No newline at end of file diff --git a/apps/im_app/lib/data/models/chat_dto.dart b/apps/im_app/lib/data/models/chat_dto.dart new file mode 100644 index 0000000..63e7f1d --- /dev/null +++ b/apps/im_app/lib/data/models/chat_dto.dart @@ -0,0 +1,200 @@ +/// 聊天 Domain 实体 +class Chat { + final int id; + final int? typ; + final int? lastId; + final int? lastTyp; + final String? lastMsg; + final int? lastTime; + final int lastPos; + final int firstPos; + final int? msgIdx; + final String? profile; + final String? pin; + final String? icon; + final String iconGaussian; + final String? name; + final int? userId; + final int? chatId; + final int? friendId; + final int? sort; + final int? unreadNum; + final int? unreadCount; + final int? hideChatMsgIdx; + final int? readChatMsgIdx; + final int? otherReadIdx; + final String? unreadAtMsgIdx; + final int? deleteTime; + final int? addIndex; + final int flag; + final int? flagMy; + final int? autoDeleteInterval; + final int? mute; + final int? verified; + final int? createTime; + final int? startIdx; + final int? isReadMsg; + final String translateOutgoing; + final String translateIncoming; + final int incomingIdx; + final int outgoingIdx; + final int incomingSoundId; + final int outgoingSoundId; + final int notificationSoundId; + final String chatKey; + final String activeChatKey; + final int coverIdx; + final int round; + final int workspaceId; + final int localPermission; + + const Chat({ + required this.id, + this.typ, + this.lastId, + this.lastTyp, + this.lastMsg, + this.lastTime, + this.lastPos = 0, + this.firstPos = -1, + this.msgIdx, + this.profile, + this.pin, + this.icon, + this.iconGaussian = '', + this.name, + this.userId, + this.chatId, + this.friendId, + this.sort, + this.unreadNum, + this.unreadCount, + this.hideChatMsgIdx, + this.readChatMsgIdx, + this.otherReadIdx, + this.unreadAtMsgIdx, + this.deleteTime, + this.addIndex, + this.flag = 0, + this.flagMy, + this.autoDeleteInterval, + this.mute, + this.verified, + this.createTime, + this.startIdx, + this.isReadMsg, + this.translateOutgoing = '', + this.translateIncoming = '', + this.incomingIdx = 0, + this.outgoingIdx = 0, + this.incomingSoundId = 0, + this.outgoingSoundId = 0, + this.notificationSoundId = 0, + this.chatKey = '', + this.activeChatKey = '', + this.coverIdx = 0, + this.round = 0, + this.workspaceId = 0, + this.localPermission = 0, + }); + + Chat copyWith({ + int? id, + int? typ, + int? lastId, + int? lastTyp, + String? lastMsg, + int? lastTime, + int? lastPos, + int? firstPos, + int? msgIdx, + String? profile, + String? pin, + String? icon, + String? iconGaussian, + String? name, + int? userId, + int? chatId, + int? friendId, + int? sort, + int? unreadNum, + int? unreadCount, + int? hideChatMsgIdx, + int? readChatMsgIdx, + int? otherReadIdx, + String? unreadAtMsgIdx, + int? deleteTime, + int? addIndex, + int? flag, + int? flagMy, + int? autoDeleteInterval, + int? mute, + int? verified, + int? createTime, + int? startIdx, + int? isReadMsg, + String? translateOutgoing, + String? translateIncoming, + int? incomingIdx, + int? outgoingIdx, + int? incomingSoundId, + int? outgoingSoundId, + int? notificationSoundId, + String? chatKey, + String? activeChatKey, + int? coverIdx, + int? round, + int? workspaceId, + int? localPermission, + }) { + return Chat( + id: id ?? this.id, + typ: typ ?? this.typ, + lastId: lastId ?? this.lastId, + lastTyp: lastTyp ?? this.lastTyp, + lastMsg: lastMsg ?? this.lastMsg, + lastTime: lastTime ?? this.lastTime, + lastPos: lastPos ?? this.lastPos, + firstPos: firstPos ?? this.firstPos, + msgIdx: msgIdx ?? this.msgIdx, + profile: profile ?? this.profile, + pin: pin ?? this.pin, + icon: icon ?? this.icon, + iconGaussian: iconGaussian ?? this.iconGaussian, + name: name ?? this.name, + userId: userId ?? this.userId, + chatId: chatId ?? this.chatId, + friendId: friendId ?? this.friendId, + sort: sort ?? this.sort, + unreadNum: unreadNum ?? this.unreadNum, + unreadCount: unreadCount ?? this.unreadCount, + hideChatMsgIdx: hideChatMsgIdx ?? this.hideChatMsgIdx, + readChatMsgIdx: readChatMsgIdx ?? this.readChatMsgIdx, + otherReadIdx: otherReadIdx ?? this.otherReadIdx, + unreadAtMsgIdx: unreadAtMsgIdx ?? this.unreadAtMsgIdx, + deleteTime: deleteTime ?? this.deleteTime, + addIndex: addIndex ?? this.addIndex, + flag: flag ?? this.flag, + flagMy: flagMy ?? this.flagMy, + autoDeleteInterval: autoDeleteInterval ?? this.autoDeleteInterval, + mute: mute ?? this.mute, + verified: verified ?? this.verified, + createTime: createTime ?? this.createTime, + startIdx: startIdx ?? this.startIdx, + isReadMsg: isReadMsg ?? this.isReadMsg, + translateOutgoing: translateOutgoing ?? this.translateOutgoing, + translateIncoming: translateIncoming ?? this.translateIncoming, + incomingIdx: incomingIdx ?? this.incomingIdx, + outgoingIdx: outgoingIdx ?? this.outgoingIdx, + incomingSoundId: incomingSoundId ?? this.incomingSoundId, + outgoingSoundId: outgoingSoundId ?? this.outgoingSoundId, + notificationSoundId: notificationSoundId ?? this.notificationSoundId, + chatKey: chatKey ?? this.chatKey, + activeChatKey: activeChatKey ?? this.activeChatKey, + coverIdx: coverIdx ?? this.coverIdx, + round: round ?? this.round, + workspaceId: workspaceId ?? this.workspaceId, + localPermission: localPermission ?? this.localPermission, + ); + } +} \ No newline at end of file diff --git a/apps/im_app/lib/data/models/discover_mini_app_dto.dart b/apps/im_app/lib/data/models/discover_mini_app_dto.dart new file mode 100644 index 0000000..89b81a2 --- /dev/null +++ b/apps/im_app/lib/data/models/discover_mini_app_dto.dart @@ -0,0 +1,112 @@ +/// 发现小程序 Domain 实体 +class DiscoverMiniApp { + final String id; + final String? name; + final String? openuid; + final String? devId; + final String? icon; + final String? iconGaussian; + final String? downloadUrl; + final String? description; + final int? version; + final int? typ; + final int? flag; + final int? reviewStatus; + final int? favoriteAt; + final int? isActive; + final int? createdAt; + final int? updatedAt; + final int? deletedAt; + final double? score; + final String? channels; + final String? devName; + final String? pictureGaussian; + final String? picture; + final int? commentNum; + final String? lastLoginAt; + final String? screen; + + const DiscoverMiniApp({ + required this.id, + this.name, + this.openuid, + this.devId, + this.icon, + this.iconGaussian, + this.downloadUrl, + this.description, + this.version, + this.typ, + this.flag, + this.reviewStatus, + this.favoriteAt, + this.isActive, + this.createdAt, + this.updatedAt, + this.deletedAt, + this.score, + this.channels, + this.devName, + this.pictureGaussian, + this.picture, + this.commentNum, + this.lastLoginAt, + this.screen, + }); + + DiscoverMiniApp copyWith({ + String? id, + String? name, + String? openuid, + String? devId, + String? icon, + String? iconGaussian, + String? downloadUrl, + String? description, + int? version, + int? typ, + int? flag, + int? reviewStatus, + int? favoriteAt, + int? isActive, + int? createdAt, + int? updatedAt, + int? deletedAt, + double? score, + String? channels, + String? devName, + String? pictureGaussian, + String? picture, + int? commentNum, + String? lastLoginAt, + String? screen, + }) { + return DiscoverMiniApp( + id: id ?? this.id, + name: name ?? this.name, + openuid: openuid ?? this.openuid, + devId: devId ?? this.devId, + icon: icon ?? this.icon, + iconGaussian: iconGaussian ?? this.iconGaussian, + downloadUrl: downloadUrl ?? this.downloadUrl, + description: description ?? this.description, + version: version ?? this.version, + typ: typ ?? this.typ, + flag: flag ?? this.flag, + reviewStatus: reviewStatus ?? this.reviewStatus, + favoriteAt: favoriteAt ?? this.favoriteAt, + isActive: isActive ?? this.isActive, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + deletedAt: deletedAt ?? this.deletedAt, + score: score ?? this.score, + channels: channels ?? this.channels, + devName: devName ?? this.devName, + pictureGaussian: pictureGaussian ?? this.pictureGaussian, + picture: picture ?? this.picture, + commentNum: commentNum ?? this.commentNum, + lastLoginAt: lastLoginAt ?? this.lastLoginAt, + screen: screen ?? this.screen, + ); + } +} \ No newline at end of file diff --git a/apps/im_app/lib/data/models/explore_mini_app_dto.dart b/apps/im_app/lib/data/models/explore_mini_app_dto.dart new file mode 100644 index 0000000..f8eeb2e --- /dev/null +++ b/apps/im_app/lib/data/models/explore_mini_app_dto.dart @@ -0,0 +1,202 @@ +import 'package:drift/drift.dart'; +import 'package:im_app/data/local/drift/app_database.dart'; +import 'package:im_app/domain/entities/explore_mini_app.dart'; + +/// 探索小程序 DTO +class ExploreMiniAppDto { + final String id; + final String? name; + final String? openuid; + final String? devId; + final String? icon; + final String? iconGaussian; + final String? downloadUrl; + final String? description; + final int? version; + final int? typ; + final int? flag; + final int? reviewStatus; + final int? favoriteAt; + final int? isActive; + final int? createdAt; + final int? updatedAt; + final int? deletedAt; + final double? score; + final String? channels; + final String? devName; + final String? pictureGaussian; + final String? picture; + final int? commentNum; + final int? lastLoginAt; + final String? screen; + + const ExploreMiniAppDto({ + required this.id, + this.name, + this.openuid, + this.devId, + this.icon, + this.iconGaussian, + this.downloadUrl, + this.description, + this.version, + this.typ, + this.flag, + this.reviewStatus, + this.favoriteAt, + this.isActive, + this.createdAt, + this.updatedAt, + this.deletedAt, + this.score, + this.channels, + this.devName, + this.pictureGaussian, + this.picture, + this.commentNum, + this.lastLoginAt, + this.screen, + }); + + factory ExploreMiniAppDto.fromJson(Map json) => + ExploreMiniAppDto( + id: json['id'] as String, + name: json['name'], + openuid: json['openuid'], + devId: json['dev_id'], + icon: json['icon'], + iconGaussian: json['icon_gaussian'], + downloadUrl: json['download_url'], + description: json['description'], + version: json['version'], + typ: json['typ'], + flag: json['flag'], + reviewStatus: json['review_status'], + favoriteAt: json['favorite_at'], + isActive: json['is_active'], + createdAt: json['created_at'], + updatedAt: json['updated_at'], + deletedAt: json['deleted_at'], + score: json['score']?.toDouble(), + channels: json['channels'], + devName: json['dev_name'], + pictureGaussian: json['picture_gaussian'], + picture: json['picture'], + commentNum: json['comment_num'], + lastLoginAt: json['last_login_at'], + screen: json['screen'], + ); + + Map toJson() => { + 'id': id, + 'name': name, + 'openuid': openuid, + 'dev_id': devId, + 'icon': icon, + 'icon_gaussian': iconGaussian, + 'download_url': downloadUrl, + 'description': description, + 'version': version, + 'typ': typ, + 'flag': flag, + 'review_status': reviewStatus, + 'favorite_at': favoriteAt, + 'is_active': isActive, + 'created_at': createdAt, + 'updated_at': updatedAt, + 'deleted_at': deletedAt, + 'score': score, + 'channels': channels, + 'dev_name': devName, + 'picture_gaussian': pictureGaussian, + 'picture': picture, + 'comment_num': commentNum, + 'last_login_at': lastLoginAt, + 'screen': screen, + }; + + ExploreMiniApp toEntity() => ExploreMiniApp( + id: id, + name: name, + openuid: openuid, + devId: devId, + icon: icon, + iconGaussian: iconGaussian, + downloadUrl: downloadUrl, + description: description, + version: version, + typ: typ, + flag: flag, + reviewStatus: reviewStatus, + favoriteAt: favoriteAt, + isActive: isActive, + createdAt: createdAt, + updatedAt: updatedAt, + deletedAt: deletedAt, + score: score, + channels: channels, + devName: devName, + pictureGaussian: pictureGaussian, + picture: picture, + commentNum: commentNum, + lastLoginAt: lastLoginAt, + screen: screen, + ); + + factory ExploreMiniAppDto.fromEntity(ExploreMiniApp app) => + ExploreMiniAppDto( + id: app.id, + name: app.name, + openuid: app.openuid, + devId: app.devId, + icon: app.icon, + iconGaussian: app.iconGaussian, + downloadUrl: app.downloadUrl, + description: app.description, + version: app.version, + typ: app.typ, + flag: app.flag, + reviewStatus: app.reviewStatus, + favoriteAt: app.favoriteAt, + isActive: app.isActive, + createdAt: app.createdAt, + updatedAt: app.updatedAt, + deletedAt: app.deletedAt, + score: app.score, + channels: app.channels, + devName: app.devName, + pictureGaussian: app.pictureGaussian, + picture: app.picture, + commentNum: app.commentNum, + lastLoginAt: app.lastLoginAt, + screen: app.screen, + ); + + ExploreMiniAppsCompanion toCompanion() => ExploreMiniAppsCompanion( + id: Value(id), + name: Value(name), + openuid: Value(openuid), + devId: Value(devId), + icon: Value(icon), + iconGaussian: Value(iconGaussian), + downloadUrl: Value(downloadUrl), + description: Value(description), + version: Value(version), + typ: Value(typ), + flag: Value(flag), + reviewStatus: Value(reviewStatus), + favoriteAt: Value(favoriteAt), + isActive: Value(isActive), + createdAt: Value(createdAt), + updatedAt: Value(updatedAt), + deletedAt: Value(deletedAt), + score: Value(score), + channels: Value(channels), + devName: Value(devName), + pictureGaussian: Value(pictureGaussian), + picture: Value(picture), + commentNum: Value(commentNum), + lastLoginAt: Value(lastLoginAt), + screen: Value(screen), + ); +} \ No newline at end of file diff --git a/apps/im_app/lib/data/models/favorite_mini_app_dto.dart b/apps/im_app/lib/data/models/favorite_mini_app_dto.dart new file mode 100644 index 0000000..d80b64a --- /dev/null +++ b/apps/im_app/lib/data/models/favorite_mini_app_dto.dart @@ -0,0 +1,202 @@ +import 'package:drift/drift.dart'; +import 'package:im_app/data/local/drift/app_database.dart'; +import 'package:im_app/domain/entities/favorite_mini_app.dart'; + +/// 收藏小程序 DTO +class FavoriteMiniAppDto { + final String id; + final String? name; + final String? openuid; + final String? devId; + final String? icon; + final String? iconGaussian; + final String? downloadUrl; + final String? description; + final int? version; + final int? typ; + final int? flag; + final int? reviewStatus; + final int? favoriteAt; + final int? isActive; + final int? createdAt; + final int? updatedAt; + final int? deletedAt; + final double? score; + final String? channels; + final String? devName; + final String? pictureGaussian; + final String? picture; + final int? commentNum; + final int? lastLoginAt; + final String? screen; + + const FavoriteMiniAppDto({ + required this.id, + this.name, + this.openuid, + this.devId, + this.icon, + this.iconGaussian, + this.downloadUrl, + this.description, + this.version, + this.typ, + this.flag, + this.reviewStatus, + this.favoriteAt, + this.isActive, + this.createdAt, + this.updatedAt, + this.deletedAt, + this.score, + this.channels, + this.devName, + this.pictureGaussian, + this.picture, + this.commentNum, + this.lastLoginAt, + this.screen, + }); + + factory FavoriteMiniAppDto.fromJson(Map json) => + FavoriteMiniAppDto( + id: json['id'] as String, + name: json['name'], + openuid: json['openuid'], + devId: json['dev_id'], + icon: json['icon'], + iconGaussian: json['icon_gaussian'], + downloadUrl: json['download_url'], + description: json['description'], + version: json['version'], + typ: json['typ'], + flag: json['flag'], + reviewStatus: json['review_status'], + favoriteAt: json['favorite_at'], + isActive: json['is_active'], + createdAt: json['created_at'], + updatedAt: json['updated_at'], + deletedAt: json['deleted_at'], + score: json['score']?.toDouble(), + channels: json['channels'], + devName: json['dev_name'], + pictureGaussian: json['picture_gaussian'], + picture: json['picture'], + commentNum: json['comment_num'], + lastLoginAt: json['last_login_at'], + screen: json['screen'], + ); + + Map toJson() => { + 'id': id, + 'name': name, + 'openuid': openuid, + 'dev_id': devId, + 'icon': icon, + 'icon_gaussian': iconGaussian, + 'download_url': downloadUrl, + 'description': description, + 'version': version, + 'typ': typ, + 'flag': flag, + 'review_status': reviewStatus, + 'favorite_at': favoriteAt, + 'is_active': isActive, + 'created_at': createdAt, + 'updated_at': updatedAt, + 'deleted_at': deletedAt, + 'score': score, + 'channels': channels, + 'dev_name': devName, + 'picture_gaussian': pictureGaussian, + 'picture': picture, + 'comment_num': commentNum, + 'last_login_at': lastLoginAt, + 'screen': screen, + }; + + FavoriteMiniApp toEntity() => FavoriteMiniApp( + id: id, + name: name, + openuid: openuid, + devId: devId, + icon: icon, + iconGaussian: iconGaussian, + downloadUrl: downloadUrl, + description: description, + version: version, + typ: typ, + flag: flag, + reviewStatus: reviewStatus, + favoriteAt: favoriteAt, + isActive: isActive, + createdAt: createdAt, + updatedAt: updatedAt, + deletedAt: deletedAt, + score: score, + channels: channels, + devName: devName, + pictureGaussian: pictureGaussian, + picture: picture, + commentNum: commentNum, + lastLoginAt: lastLoginAt, + screen: screen, + ); + + factory FavoriteMiniAppDto.fromEntity(FavoriteMiniApp app) => + FavoriteMiniAppDto( + id: app.id, + name: app.name, + openuid: app.openuid, + devId: app.devId, + icon: app.icon, + iconGaussian: app.iconGaussian, + downloadUrl: app.downloadUrl, + description: app.description, + version: app.version, + typ: app.typ, + flag: app.flag, + reviewStatus: app.reviewStatus, + favoriteAt: app.favoriteAt, + isActive: app.isActive, + createdAt: app.createdAt, + updatedAt: app.updatedAt, + deletedAt: app.deletedAt, + score: app.score, + channels: app.channels, + devName: app.devName, + pictureGaussian: app.pictureGaussian, + picture: app.picture, + commentNum: app.commentNum, + lastLoginAt: app.lastLoginAt, + screen: app.screen, + ); + + FavoriteMiniAppsCompanion toCompanion() => FavoriteMiniAppsCompanion( + id: Value(id), + name: Value(name), + openuid: Value(openuid), + devId: Value(devId), + icon: Value(icon), + iconGaussian: Value(iconGaussian), + downloadUrl: Value(downloadUrl), + description: Value(description), + version: Value(version), + typ: Value(typ), + flag: Value(flag), + reviewStatus: Value(reviewStatus), + favoriteAt: Value(favoriteAt), + isActive: Value(isActive), + createdAt: Value(createdAt), + updatedAt: Value(updatedAt), + deletedAt: Value(deletedAt), + score: Value(score), + channels: Value(channels), + devName: Value(devName), + pictureGaussian: Value(pictureGaussian), + picture: Value(picture), + commentNum: Value(commentNum), + lastLoginAt: Value(lastLoginAt), + screen: Value(screen), + ); +} \ No newline at end of file diff --git a/apps/im_app/lib/data/models/favourite_detail_dto.dart b/apps/im_app/lib/data/models/favourite_detail_dto.dart new file mode 100644 index 0000000..0169108 --- /dev/null +++ b/apps/im_app/lib/data/models/favourite_detail_dto.dart @@ -0,0 +1,83 @@ +import 'package:drift/drift.dart'; +import 'package:im_app/data/local/drift/app_database.dart'; +import 'package:im_app/domain/entities/favourite_detail.dart'; + +/// 收藏详情 DTO +class FavouriteDetailDto { + final int? id; + final String relatedId; + final String content; + final int? typ; + final int? messageId; + final int? sendId; + final int? chatId; + final int? sendTime; + + const FavouriteDetailDto({ + this.id, + this.relatedId = '', + this.content = '', + this.typ, + this.messageId, + this.sendId, + this.chatId, + this.sendTime, + }); + + factory FavouriteDetailDto.fromJson(Map json) => + FavouriteDetailDto( + id: json['id'], + relatedId: json['related_id'] ?? '', + content: json['content'] ?? '', + typ: json['typ'], + messageId: json['messageId'], + sendId: json['sendId'], + chatId: json['chatId'], + sendTime: json['sendTime'], + ); + + Map toJson() => { + 'id': id, + 'related_id': relatedId, + 'content': content, + 'typ': typ, + 'messageId': messageId, + 'sendId': sendId, + 'chatId': chatId, + 'sendTime': sendTime, + }; + + FavouriteDetail toEntity() => FavouriteDetail( + id: id, + relatedId: relatedId, + content: content, + typ: typ, + messageId: messageId, + sendId: sendId, + chatId: chatId, + sendTime: sendTime, + ); + + factory FavouriteDetailDto.fromEntity(FavouriteDetail detail) => + FavouriteDetailDto( + id: detail.id, + relatedId: detail.relatedId, + content: detail.content, + typ: detail.typ, + messageId: detail.messageId, + sendId: detail.sendId, + chatId: detail.chatId, + sendTime: detail.sendTime, + ); + + FavouriteDetailsCompanion toCompanion() => FavouriteDetailsCompanion( + id: id != null ? Value(id!) : const Value.absent(), + relatedId: Value(relatedId), + content: Value(content), + typ: Value(typ), + messageId: Value(messageId), + sendId: Value(sendId), + chatId: Value(chatId), + sendTime: Value(sendTime), + ); +} \ No newline at end of file diff --git a/apps/im_app/lib/data/models/favourite_dto.dart b/apps/im_app/lib/data/models/favourite_dto.dart new file mode 100644 index 0000000..2c3b2cb --- /dev/null +++ b/apps/im_app/lib/data/models/favourite_dto.dart @@ -0,0 +1,130 @@ +import 'package:drift/drift.dart'; +import 'package:im_app/data/local/drift/app_database.dart'; +import 'package:im_app/domain/entities/favourite.dart'; + +/// 收藏 DTO +class FavouriteDto { + final int id; + final String parentId; + final String data; + final int createdAt; + final int updatedAt; + final int deletedAt; + final int? source; + final int? userId; + final int? authorId; + final String typ; + final String tag; + final int isPin; + final int chatTyp; + final int isUploaded; + final String urls; + + const FavouriteDto({ + required this.id, + this.parentId = '', + this.data = '', + this.createdAt = 0, + this.updatedAt = 0, + this.deletedAt = 0, + this.source, + this.userId, + this.authorId, + this.typ = '[]', + this.tag = '[]', + this.isPin = 0, + this.chatTyp = 0, + this.isUploaded = 1, + this.urls = '[]', + }); + + factory FavouriteDto.fromJson(Map json) => FavouriteDto( + id: json['id'] as int, + parentId: json['parent_id'] ?? '', + data: json['data'] ?? '', + createdAt: json['created_at'] ?? 0, + updatedAt: json['updated_at'] ?? 0, + deletedAt: json['deleted_at'] ?? 0, + source: json['source'], + userId: json['user_id'], + authorId: json['author_id'], + typ: json['typ'] ?? '[]', + tag: json['tag'] ?? '[]', + isPin: json['is_pin'] ?? 0, + chatTyp: json['chat_typ'] ?? 0, + isUploaded: json['is_uploaded'] ?? 1, + urls: json['urls'] ?? '[]', + ); + + Map toJson() => { + 'id': id, + 'parent_id': parentId, + 'data': data, + 'created_at': createdAt, + 'updated_at': updatedAt, + 'deleted_at': deletedAt, + 'source': source, + 'user_id': userId, + 'author_id': authorId, + 'typ': typ, + 'tag': tag, + 'is_pin': isPin, + 'chat_typ': chatTyp, + 'is_uploaded': isUploaded, + 'urls': urls, + }; + + Favourite toEntity() => Favourite( + id: id, + parentId: parentId, + data: data, + createdAt: createdAt, + updatedAt: updatedAt, + deletedAt: deletedAt, + source: source, + userId: userId, + authorId: authorId, + typ: typ, + tag: tag, + isPin: isPin, + chatTyp: chatTyp, + isUploaded: isUploaded, + urls: urls, + ); + + factory FavouriteDto.fromEntity(Favourite favourite) => FavouriteDto( + id: favourite.id, + parentId: favourite.parentId, + data: favourite.data, + createdAt: favourite.createdAt, + updatedAt: favourite.updatedAt, + deletedAt: favourite.deletedAt, + source: favourite.source, + userId: favourite.userId, + authorId: favourite.authorId, + typ: favourite.typ, + tag: favourite.tag, + isPin: favourite.isPin, + chatTyp: favourite.chatTyp, + isUploaded: favourite.isUploaded, + urls: favourite.urls, + ); + + FavouritesCompanion toCompanion() => FavouritesCompanion( + id: Value(id), + parentId: Value(parentId), + data: Value(data), + createdAt: Value(createdAt), + updatedAt: Value(updatedAt), + deletedAt: Value(deletedAt), + source: Value(source), + userId: Value(userId), + authorId: Value(authorId), + typ: Value(typ), + tag: Value(tag), + isPin: Value(isPin), + chatTyp: Value(chatTyp), + isUploaded: Value(isUploaded), + urls: Value(urls), + ); +} \ No newline at end of file diff --git a/apps/im_app/lib/data/models/group_dto.dart b/apps/im_app/lib/data/models/group_dto.dart new file mode 100644 index 0000000..05e218d --- /dev/null +++ b/apps/im_app/lib/data/models/group_dto.dart @@ -0,0 +1,221 @@ +import 'package:drift/drift.dart'; +import 'package:im_app/data/local/drift/app_database.dart'; +import 'package:im_app/domain/entities/group.dart'; + +/// 群组 DTO +class GroupDto { + final int id; + final int? userJoinDate; + final String? name; + final String? profile; + final String? icon; + final String iconGaussian; + final int? permission; + final int? admin; + final String? members; + final int? owner; + final String? admins; + final int? visible; + final int? speakInterval; + final int? groupType; + final int? roomType; + final int? maxNumber; + final int? channelId; + final int? channelGroupId; + final int? createTime; + final int? updateTime; + final int? addIndex; + final int? maxMember; + final int? expireTime; + final int workspaceId; + final int mode; + final int redpacketPlay; + final String? topic; + final String? rp; + + const GroupDto({ + required this.id, + this.userJoinDate, + this.name, + this.profile, + this.icon, + this.iconGaussian = '', + this.permission, + this.admin, + this.members, + this.owner, + this.admins, + this.visible, + this.speakInterval, + this.groupType, + this.roomType, + this.maxNumber, + this.channelId, + this.channelGroupId, + this.createTime, + this.updateTime, + this.addIndex, + this.maxMember, + this.expireTime, + this.workspaceId = 0, + this.mode = 0, + this.redpacketPlay = 0, + this.topic, + this.rp, + }); + + factory GroupDto.fromJson(Map json) => GroupDto( + id: json['id'] as int, + userJoinDate: json['user_join_date'], + name: json['name'], + profile: json['profile'], + icon: json['icon'], + iconGaussian: json['icon_gaussian'] ?? '', + permission: json['permission'], + admin: json['admin'], + members: json['members'], + owner: json['owner'], + admins: json['admins'], + visible: json['visible'], + speakInterval: json['speak_interval'], + groupType: json['group_type'], + roomType: json['room_type'], + maxNumber: json['max_number'], + channelId: json['channel_id'], + channelGroupId: json['channel_group_id'], + createTime: json['create_time'], + updateTime: json['update_time'], + addIndex: json['__add_index'], + maxMember: json['max_member'], + expireTime: json['expire_time'], + workspaceId: json['workspace_id'] ?? 0, + mode: json['mode'] ?? 0, + redpacketPlay: json['redpacket_play'] ?? 0, + topic: json['topic'], + rp: json['rp'], + ); + + Map toJson() => { + 'id': id, + 'user_join_date': userJoinDate, + 'name': name, + 'profile': profile, + 'icon': icon, + 'icon_gaussian': iconGaussian, + 'permission': permission, + 'admin': admin, + 'members': members, + 'owner': owner, + 'admins': admins, + 'visible': visible, + 'speak_interval': speakInterval, + 'group_type': groupType, + 'room_type': roomType, + 'max_number': maxNumber, + 'channel_id': channelId, + 'channel_group_id': channelGroupId, + 'create_time': createTime, + 'update_time': updateTime, + '__add_index': addIndex, + 'max_member': maxMember, + 'expire_time': expireTime, + 'workspace_id': workspaceId, + 'mode': mode, + 'redpacket_play': redpacketPlay, + 'topic': topic, + 'rp': rp, + }; + + Group toEntity() => Group( + id: id, + userJoinDate: userJoinDate, + name: name, + profile: profile, + icon: icon, + iconGaussian: iconGaussian, + permission: permission, + admin: admin, + members: members, + owner: owner, + admins: admins, + visible: visible, + speakInterval: speakInterval, + groupType: groupType, + roomType: roomType, + maxNumber: maxNumber, + channelId: channelId, + channelGroupId: channelGroupId, + createTime: createTime, + updateTime: updateTime, + addIndex: addIndex, + maxMember: maxMember, + expireTime: expireTime, + workspaceId: workspaceId, + mode: mode, + redpacketPlay: redpacketPlay, + topic: topic, + rp: rp, + ); + + factory GroupDto.fromEntity(Group group) => GroupDto( + id: group.id, + userJoinDate: group.userJoinDate, + name: group.name, + profile: group.profile, + icon: group.icon, + iconGaussian: group.iconGaussian, + permission: group.permission, + admin: group.admin, + members: group.members, + owner: group.owner, + admins: group.admins, + visible: group.visible, + speakInterval: group.speakInterval, + groupType: group.groupType, + roomType: group.roomType, + maxNumber: group.maxNumber, + channelId: group.channelId, + channelGroupId: group.channelGroupId, + createTime: group.createTime, + updateTime: group.updateTime, + addIndex: group.addIndex, + maxMember: group.maxMember, + expireTime: group.expireTime, + workspaceId: group.workspaceId, + mode: group.mode, + redpacketPlay: group.redpacketPlay, + topic: group.topic, + rp: group.rp, + ); + + GroupsCompanion toCompanion() => GroupsCompanion( + id: Value(id), + userJoinDate: Value(userJoinDate), + name: Value(name), + profile: Value(profile), + icon: Value(icon), + iconGaussian: Value(iconGaussian), + permission: Value(permission), + admin: Value(admin), + members: Value(members), + owner: Value(owner), + admins: Value(admins), + visible: Value(visible), + speakInterval: Value(speakInterval), + groupType: Value(groupType), + roomType: Value(roomType), + maxNumber: Value(maxNumber), + channelId: Value(channelId), + channelGroupId: Value(channelGroupId), + createTime: Value(createTime), + updateTime: Value(updateTime), + addIndex: Value(addIndex), + maxMember: Value(maxMember), + expireTime: Value(expireTime), + workspaceId: Value(workspaceId), + mode: Value(mode), + redpacketPlay: Value(redpacketPlay), + topic: Value(topic), + rp: Value(rp), + ); +} \ No newline at end of file diff --git a/apps/im_app/lib/data/models/message_dto.dart b/apps/im_app/lib/data/models/message_dto.dart new file mode 100644 index 0000000..2f5908b --- /dev/null +++ b/apps/im_app/lib/data/models/message_dto.dart @@ -0,0 +1,137 @@ +import 'package:drift/drift.dart'; +import 'package:im_app/data/local/drift/app_database.dart'; +import 'package:im_app/domain/entities/message.dart'; + +/// 消息 DTO +class MessageDto { + final int id; + final int? messageId; + final int? chatId; + final int? chatIdx; + final int? sendId; + final String? content; + final int? typ; + final int? sendTime; + final int? expireTime; + final int? createTime; + final String? atUsers; + final String emojis; + final int editTime; + final int refTyp; + final int flag; + final String cmid; + + const MessageDto({ + required this.id, + this.messageId, + this.chatId, + this.chatIdx, + this.sendId, + this.content, + this.typ, + this.sendTime, + this.expireTime, + this.createTime, + this.atUsers, + this.emojis = '[]', + this.editTime = 0, + this.refTyp = 0, + this.flag = 0, + this.cmid = '', + }); + + factory MessageDto.fromJson(Map json) => MessageDto( + id: json['id'] as int, + messageId: json['message_id'], + chatId: json['chat_id'], + chatIdx: json['chat_idx'], + sendId: json['send_id'], + content: json['content'], + typ: json['typ'], + sendTime: json['send_time'], + expireTime: json['expire_time'], + createTime: json['create_time'], + atUsers: json['at_users'], + emojis: json['emojis'] ?? '[]', + editTime: json['edit_time'] ?? 0, + refTyp: json['ref_typ'] ?? 0, + flag: json['flag'] ?? 0, + cmid: json['cmid'] ?? '', + ); + + Map toJson() => { + 'id': id, + 'message_id': messageId, + 'chat_id': chatId, + 'chat_idx': chatIdx, + 'send_id': sendId, + 'content': content, + 'typ': typ, + 'send_time': sendTime, + 'expire_time': expireTime, + 'create_time': createTime, + 'at_users': atUsers, + 'emojis': emojis, + 'edit_time': editTime, + 'ref_typ': refTyp, + 'flag': flag, + 'cmid': cmid, + }; + + Message toEntity() => Message( + id: id, + messageId: messageId, + chatId: chatId, + chatIdx: chatIdx, + sendId: sendId, + content: content, + typ: typ, + sendTime: sendTime, + expireTime: expireTime, + createTime: createTime, + atUsers: atUsers, + emojis: emojis, + editTime: editTime, + refTyp: refTyp, + flag: flag, + cmid: cmid, + ); + + factory MessageDto.fromEntity(Message message) => MessageDto( + id: message.id, + messageId: message.messageId, + chatId: message.chatId, + chatIdx: message.chatIdx, + sendId: message.sendId, + content: message.content, + typ: message.typ, + sendTime: message.sendTime, + expireTime: message.expireTime, + createTime: message.createTime, + atUsers: message.atUsers, + emojis: message.emojis, + editTime: message.editTime, + refTyp: message.refTyp, + flag: message.flag, + cmid: message.cmid, + ); + + MessagesCompanion toCompanion() => MessagesCompanion( + id: Value(id), + messageId: Value(messageId), + chatId: Value(chatId), + chatIdx: Value(chatIdx), + sendId: Value(sendId), + content: Value(content), + typ: Value(typ), + sendTime: Value(sendTime), + expireTime: Value(expireTime), + createTime: Value(createTime), + atUsers: Value(atUsers), + emojis: Value(emojis), + editTime: Value(editTime), + refTyp: Value(refTyp), + flag: Value(flag), + cmid: Value(cmid), + ); +} \ No newline at end of file diff --git a/apps/im_app/lib/data/models/pending_friend_request_history_dto.dart b/apps/im_app/lib/data/models/pending_friend_request_history_dto.dart new file mode 100644 index 0000000..cdac263 --- /dev/null +++ b/apps/im_app/lib/data/models/pending_friend_request_history_dto.dart @@ -0,0 +1,71 @@ +import 'package:drift/drift.dart'; +import 'package:im_app/data/local/drift/app_database.dart'; +import 'package:im_app/domain/entities/pending_friend_request_history.dart'; + +/// 待处理好友请求历史 DTO +class PendingFriendRequestHistoryDto { + final int id; + final int uid; + final int requestTime; + final String? remarks; + final String? source; + final int? rs; + + const PendingFriendRequestHistoryDto({ + required this.id, + required this.uid, + required this.requestTime, + this.remarks, + this.source, + this.rs, + }); + + factory PendingFriendRequestHistoryDto.fromJson(Map json) => + PendingFriendRequestHistoryDto( + id: json['id'] as int, + uid: json['uid'] as int, + requestTime: json['request_time'] as int, + remarks: json['remarks'], + source: json['source'], + rs: json['rs'], + ); + + Map toJson() => { + 'id': id, + 'uid': uid, + 'request_time': requestTime, + 'remarks': remarks, + 'source': source, + 'rs': rs, + }; + + PendingFriendRequestHistory toEntity() => PendingFriendRequestHistory( + id: id, + uid: uid, + requestTime: requestTime, + remarks: remarks, + source: source, + rs: rs, + ); + + factory PendingFriendRequestHistoryDto.fromEntity( + PendingFriendRequestHistory history) => + PendingFriendRequestHistoryDto( + id: history.id, + uid: history.uid, + requestTime: history.requestTime, + remarks: history.remarks, + source: history.source, + rs: history.rs, + ); + + PendingFriendRequestHistoriesCompanion toCompanion() => + PendingFriendRequestHistoriesCompanion( + id: Value(id), + uid: Value(uid), + requestTime: Value(requestTime), + remarks: Value(remarks), + source: Value(source), + rs: Value(rs), + ); +} \ No newline at end of file diff --git a/apps/im_app/lib/data/models/recent_mini_app_dto.dart b/apps/im_app/lib/data/models/recent_mini_app_dto.dart new file mode 100644 index 0000000..09b0f10 --- /dev/null +++ b/apps/im_app/lib/data/models/recent_mini_app_dto.dart @@ -0,0 +1,201 @@ +import 'package:drift/drift.dart'; +import 'package:im_app/data/local/drift/app_database.dart'; +import 'package:im_app/domain/entities/recent_mini_app.dart'; + +/// 最近小程序 DTO +class RecentMiniAppDto { + final String id; + final String? name; + final String? openuid; + final String? devId; + final String? icon; + final String? iconGaussian; + final String? downloadUrl; + final String? description; + final int? version; + final int? typ; + final int? flag; + final int? reviewStatus; + final int? favoriteAt; + final int? isActive; + final int? createdAt; + final int? updatedAt; + final int? deletedAt; + final double? score; + final String? channels; + final String? devName; + final String? pictureGaussian; + final String? picture; + final int? commentNum; + final int? lastLoginAt; + final String? screen; + + const RecentMiniAppDto({ + required this.id, + this.name, + this.openuid, + this.devId, + this.icon, + this.iconGaussian, + this.downloadUrl, + this.description, + this.version, + this.typ, + this.flag, + this.reviewStatus, + this.favoriteAt, + this.isActive, + this.createdAt, + this.updatedAt, + this.deletedAt, + this.score, + this.channels, + this.devName, + this.pictureGaussian, + this.picture, + this.commentNum, + this.lastLoginAt, + this.screen, + }); + + factory RecentMiniAppDto.fromJson(Map json) => + RecentMiniAppDto( + id: json['id'] as String, + name: json['name'], + openuid: json['openuid'], + devId: json['dev_id'], + icon: json['icon'], + iconGaussian: json['icon_gaussian'], + downloadUrl: json['download_url'], + description: json['description'], + version: json['version'], + typ: json['typ'], + flag: json['flag'], + reviewStatus: json['review_status'], + favoriteAt: json['favorite_at'], + isActive: json['is_active'], + createdAt: json['created_at'], + updatedAt: json['updated_at'], + deletedAt: json['deleted_at'], + score: json['score']?.toDouble(), + channels: json['channels'], + devName: json['dev_name'], + pictureGaussian: json['picture_gaussian'], + picture: json['picture'], + commentNum: json['comment_num'], + lastLoginAt: json['last_login_at'], + screen: json['screen'], + ); + + Map toJson() => { + 'id': id, + 'name': name, + 'openuid': openuid, + 'dev_id': devId, + 'icon': icon, + 'icon_gaussian': iconGaussian, + 'download_url': downloadUrl, + 'description': description, + 'version': version, + 'typ': typ, + 'flag': flag, + 'review_status': reviewStatus, + 'favorite_at': favoriteAt, + 'is_active': isActive, + 'created_at': createdAt, + 'updated_at': updatedAt, + 'deleted_at': deletedAt, + 'score': score, + 'channels': channels, + 'dev_name': devName, + 'picture_gaussian': pictureGaussian, + 'picture': picture, + 'comment_num': commentNum, + 'last_login_at': lastLoginAt, + 'screen': screen, + }; + + RecentMiniApp toEntity() => RecentMiniApp( + id: id, + name: name, + openuid: openuid, + devId: devId, + icon: icon, + iconGaussian: iconGaussian, + downloadUrl: downloadUrl, + description: description, + version: version, + typ: typ, + flag: flag, + reviewStatus: reviewStatus, + favoriteAt: favoriteAt, + isActive: isActive, + createdAt: createdAt, + updatedAt: updatedAt, + deletedAt: deletedAt, + score: score, + channels: channels, + devName: devName, + pictureGaussian: pictureGaussian, + picture: picture, + commentNum: commentNum, + lastLoginAt: lastLoginAt, + screen: screen, + ); + + factory RecentMiniAppDto.fromEntity(RecentMiniApp app) => RecentMiniAppDto( + id: app.id, + name: app.name, + openuid: app.openuid, + devId: app.devId, + icon: app.icon, + iconGaussian: app.iconGaussian, + downloadUrl: app.downloadUrl, + description: app.description, + version: app.version, + typ: app.typ, + flag: app.flag, + reviewStatus: app.reviewStatus, + favoriteAt: app.favoriteAt, + isActive: app.isActive, + createdAt: app.createdAt, + updatedAt: app.updatedAt, + deletedAt: app.deletedAt, + score: app.score, + channels: app.channels, + devName: app.devName, + pictureGaussian: app.pictureGaussian, + picture: app.picture, + commentNum: app.commentNum, + lastLoginAt: app.lastLoginAt, + screen: app.screen, + ); + + RecentMiniAppsCompanion toCompanion() => RecentMiniAppsCompanion( + id: Value(id), + name: Value(name), + openuid: Value(openuid), + devId: Value(devId), + icon: Value(icon), + iconGaussian: Value(iconGaussian), + downloadUrl: Value(downloadUrl), + description: Value(description), + version: Value(version), + typ: Value(typ), + flag: Value(flag), + reviewStatus: Value(reviewStatus), + favoriteAt: Value(favoriteAt), + isActive: Value(isActive), + createdAt: Value(createdAt), + updatedAt: Value(updatedAt), + deletedAt: Value(deletedAt), + score: Value(score), + channels: Value(channels), + devName: Value(devName), + pictureGaussian: Value(pictureGaussian), + picture: Value(picture), + commentNum: Value(commentNum), + lastLoginAt: Value(lastLoginAt), + screen: Value(screen), + ); +} \ No newline at end of file diff --git a/apps/im_app/lib/data/models/retry_dto.dart b/apps/im_app/lib/data/models/retry_dto.dart new file mode 100644 index 0000000..72ddf54 --- /dev/null +++ b/apps/im_app/lib/data/models/retry_dto.dart @@ -0,0 +1,109 @@ +import 'package:drift/drift.dart'; +import 'package:im_app/data/local/drift/app_database.dart'; +import 'package:im_app/domain/entities/retry.dart'; + +/// 重试 DTO +class RetryDto { + final int? id; + final int? uid; + final String apiType; + final String endPoint; + final String requestData; + final int? synced; + final String callbackFun; + final int? expired; + final int? replace; + final int? expireTime; + final int? createTime; + final int? addIndex; + + const RetryDto({ + this.id, + this.uid, + this.apiType = '', + this.endPoint = '', + this.requestData = '', + this.synced, + this.callbackFun = '', + this.expired, + this.replace, + this.expireTime, + this.createTime, + this.addIndex, + }); + + factory RetryDto.fromJson(Map json) => RetryDto( + id: json['id'], + uid: json['uid'], + apiType: json['api_type'] ?? '', + endPoint: json['end_point'] ?? '', + requestData: json['request_data'] ?? '', + synced: json['synced'], + callbackFun: json['callback_fun'] ?? '', + expired: json['expired'], + replace: json['replace'], + expireTime: json['expire_time'], + createTime: json['create_time'], + addIndex: json['__add_index'], + ); + + Map toJson() => { + 'id': id, + 'uid': uid, + 'api_type': apiType, + 'end_point': endPoint, + 'request_data': requestData, + 'synced': synced, + 'callback_fun': callbackFun, + 'expired': expired, + 'replace': replace, + 'expire_time': expireTime, + 'create_time': createTime, + '__add_index': addIndex, + }; + + Retry toEntity() => Retry( + id: id, + uid: uid, + apiType: apiType, + endPoint: endPoint, + requestData: requestData, + synced: synced, + callbackFun: callbackFun, + expired: expired, + replace: replace, + expireTime: expireTime, + createTime: createTime, + addIndex: addIndex, + ); + + factory RetryDto.fromEntity(Retry retry) => RetryDto( + id: retry.id, + uid: retry.uid, + apiType: retry.apiType, + endPoint: retry.endPoint, + requestData: retry.requestData, + synced: retry.synced, + callbackFun: retry.callbackFun, + expired: retry.expired, + replace: retry.replace, + expireTime: retry.expireTime, + createTime: retry.createTime, + addIndex: retry.addIndex, + ); + + RetriesCompanion toCompanion() => RetriesCompanion( + id: id != null ? Value(id!) : const Value.absent(), + uid: Value(uid), + apiType: Value(apiType), + endPoint: Value(endPoint), + requestData: Value(requestData), + synced: Value(synced), + callbackFun: Value(callbackFun), + expired: Value(expired), + replace: Value(replace), + expireTime: Value(expireTime), + createTime: Value(createTime), + addIndex: Value(addIndex), + ); +} \ No newline at end of file diff --git a/apps/im_app/lib/data/models/sound_dto.dart b/apps/im_app/lib/data/models/sound_dto.dart new file mode 100644 index 0000000..b23d21a --- /dev/null +++ b/apps/im_app/lib/data/models/sound_dto.dart @@ -0,0 +1,88 @@ +import 'package:drift/drift.dart'; +import 'package:im_app/data/local/drift/app_database.dart'; +import 'package:im_app/domain/entities/sound.dart'; + +/// 音效 DTO +class SoundDto { + final int id; + final String filePath; + final int typ; + final String name; + final int createdAt; + final int updatedAt; + final int deletedAt; + final int channelGroupId; + final int isDefault; + + const SoundDto({ + required this.id, + this.filePath = '', + required this.typ, + this.name = '', + required this.createdAt, + required this.updatedAt, + this.deletedAt = 0, + required this.channelGroupId, + required this.isDefault, + }); + + factory SoundDto.fromJson(Map json) => SoundDto( + id: json['id'] as int, + filePath: json['file_path'] ?? '', + typ: json['typ'] as int, + name: json['name'] ?? '', + createdAt: json['created_at'] as int, + updatedAt: json['updated_at'] as int, + deletedAt: json['deleted_at'] ?? 0, + channelGroupId: json['channel_group_id'] as int, + isDefault: json['is_default'] as int, + ); + + Map toJson() => { + 'id': id, + 'file_path': filePath, + 'typ': typ, + 'name': name, + 'created_at': createdAt, + 'updated_at': updatedAt, + 'deleted_at': deletedAt, + 'channel_group_id': channelGroupId, + 'is_default': isDefault, + }; + + Sound toEntity() => Sound( + id: id, + filePath: filePath, + typ: typ, + name: name, + createdAt: createdAt, + updatedAt: updatedAt, + deletedAt: deletedAt, + channelGroupId: channelGroupId, + isDefault: isDefault, + ); + + factory SoundDto.fromEntity(Sound sound) => SoundDto( + id: sound.id, + filePath: sound.filePath, + typ: sound.typ, + name: sound.name, + createdAt: sound.createdAt, + updatedAt: sound.updatedAt, + deletedAt: sound.deletedAt, + channelGroupId: sound.channelGroupId, + isDefault: sound.isDefault, + ); + + SoundsCompanion toCompanion() => SoundsCompanion( + id: Value(id), + filePath: Value(filePath), + typ: Value(typ), + name: Value(name), + createdAt: Value(createdAt), + updatedAt: Value(updatedAt), + deletedAt: Value(deletedAt), + channelGroupId: Value(channelGroupId), + isDefault: Value(isDefault), + ); +} \ No newline at end of file diff --git a/apps/im_app/lib/data/models/tag_dto.dart b/apps/im_app/lib/data/models/tag_dto.dart new file mode 100644 index 0000000..1589ca3 --- /dev/null +++ b/apps/im_app/lib/data/models/tag_dto.dart @@ -0,0 +1,74 @@ +import 'package:drift/drift.dart'; +import 'package:im_app/data/local/drift/app_database.dart'; +import 'package:im_app/domain/entities/tag.dart'; + +/// 标签 DTO +class TagDto { + final int? id; + final int? uid; + final String name; + final int? type; + final int? createdAt; + final int? updatedAt; + final int? addIndex; + + const TagDto({ + this.id, + this.uid, + this.name = '', + this.type, + this.createdAt, + this.updatedAt, + this.addIndex, + }); + + factory TagDto.fromJson(Map json) => TagDto( + id: json['id'], + uid: json['uid'], + name: json['name'] ?? '', + type: json['type'], + createdAt: json['created_at'], + updatedAt: json['updated_at'], + addIndex: json['__add_index'], + ); + + Map toJson() => { + 'id': id, + 'uid': uid, + 'name': name, + 'type': type, + 'created_at': createdAt, + 'updated_at': updatedAt, + '__add_index': addIndex, + }; + + Tag toEntity() => Tag( + id: id, + uid: uid, + name: name, + type: type, + createdAt: createdAt, + updatedAt: updatedAt, + addIndex: addIndex, + ); + + factory TagDto.fromEntity(Tag tag) => TagDto( + id: tag.id, + uid: tag.uid, + name: tag.name, + type: tag.type, + createdAt: tag.createdAt, + updatedAt: tag.updatedAt, + addIndex: tag.addIndex, + ); + + TagsCompanion toCompanion() => TagsCompanion( + id: id != null ? Value(id!) : const Value.absent(), + uid: Value(uid), + name: Value(name), + type: Value(type), + createdAt: Value(createdAt), + updatedAt: Value(updatedAt), + addIndex: Value(addIndex), + ); +} \ No newline at end of file diff --git a/apps/im_app/lib/data/models/user_dto.dart b/apps/im_app/lib/data/models/user_dto.dart index 5c05b30..beb55c0 100644 --- a/apps/im_app/lib/data/models/user_dto.dart +++ b/apps/im_app/lib/data/models/user_dto.dart @@ -1,68 +1,148 @@ -import 'package:json_annotation/json_annotation.dart'; - -import '../../domain/entities/user.dart'; - -part 'user_dto.g.dart'; +import 'package:drift/drift.dart'; +import 'package:im_app/data/local/drift/app_database.dart'; +import 'package:im_app/domain/entities/user.dart'; /// 用户 DTO(Data Transfer Object) /// /// local / remote 共用的数据传输对象,放在 data/models/。 /// 提供与 Domain Entity [User] 之间的双向转换。 -/// -/// ## 数据流位置(本地存储场景) -/// -/// ``` -/// 写入本地: -/// LoginData.toEntity() → User -/// → UserDto.fromEntity(user) → ★ UserDto ★ ← 你在这里 -/// → toJson() → SQLite / SharedPreferences -/// -/// 读取本地: -/// SQLite / SharedPreferences → JSON -/// → ★ UserDto.fromJson() ★ ← 你在这里 -/// → UserDto.toEntity() → User -/// → ViewModel.state → View -/// ``` -/// -/// 注意:登录接口的 Response DTO 是 [LoginData](含 token), -/// 本类用于纯用户信息的本地持久化,不含 token。 -@JsonSerializable() class UserDto { - @JsonKey(name: 'user_id') - final String userId; - final String email; + final int uid; + final String? uuid; + final int? lastOnline; + final String? profilePic; + final String? profilePicGaussian; final String? nickname; - final String? avatar; + final String? contact; + final String? countryCode; + final String? email; + final String? recoveryEmail; + final String? username; + final String? bio; + final int? relationship; + final String? userAlias; + final int? channelId; + final int? channelGroupId; + final String? hint; const UserDto({ - required this.userId, - required this.email, + required this.uid, + this.uuid, + this.lastOnline, + this.profilePic, + this.profilePicGaussian, this.nickname, - this.avatar, + this.contact, + this.countryCode, + this.email, + this.recoveryEmail, + this.username, + this.bio, + this.relationship, + this.userAlias, + this.channelId, + this.channelGroupId, + this.hint, }); - factory UserDto.fromJson(Map json) => - _$UserDtoFromJson(json); + factory UserDto.fromJson(Map json) => UserDto( + uid: json['uid'] as int, + uuid: json['uuid'], + lastOnline: json['last_online'], + profilePic: json['profile_pic'], + profilePicGaussian: json['profile_pic_gaussian'] ?? '', + nickname: json['nickname'], + contact: json['contact'], + countryCode: json['country_code'], + email: json['email'], + recoveryEmail: json['recovery_email'] ?? '', + username: json['username'], + bio: json['bio'] ?? '', + relationship: json['relationship'], + userAlias: json['user_alias'], + channelId: json['channel_id'], + channelGroupId: json['channel_group_id'], + hint: json['hint'], + ); - Map toJson() => _$UserDtoToJson(this); + Map toJson() => { + 'uid': uid, + 'uuid': uuid, + 'last_online': lastOnline, + 'profile_pic': profilePic, + 'profile_pic_gaussian': profilePicGaussian, + 'nickname': nickname, + 'contact': contact, + 'country_code': countryCode, + 'email': email, + 'recovery_email': recoveryEmail, + 'username': username, + 'bio': bio, + 'relationship': relationship, + 'user_alias': userAlias, + 'channel_id': channelId, + 'channel_group_id': channelGroupId, + 'hint': hint, + }; /// DTO → Domain Entity - User toEntity() { - return User( - id: userId, - email: email, - nickname: nickname, - avatar: avatar, - ); - } + User toEntity() => User( + uid: uid, + uuid: uuid, + lastOnline: lastOnline, + profilePic: profilePic, + profilePicGaussian: profilePicGaussian, + nickname: nickname, + contact: contact, + countryCode: countryCode, + email: email, + recoveryEmail: recoveryEmail, + username: username, + bio: bio, + relationship: relationship, + userAlias: userAlias, + channelId: channelId, + channelGroupId: channelGroupId, + hint: hint, + ); /// Domain Entity → DTO - factory UserDto.fromEntity(User user) { - return UserDto( - userId: user.id, - email: user.email, - nickname: user.nickname, - avatar: user.avatar, - ); - } -} + factory UserDto.fromEntity(User user) => UserDto( + uid: user.uid, + uuid: user.uuid, + lastOnline: user.lastOnline, + profilePic: user.profilePic, + profilePicGaussian: user.profilePicGaussian, + nickname: user.nickname, + contact: user.contact, + countryCode: user.countryCode, + email: user.email, + recoveryEmail: user.recoveryEmail, + username: user.username, + bio: user.bio, + relationship: user.relationship, + userAlias: user.userAlias, + channelId: user.channelId, + channelGroupId: user.channelGroupId, + hint: user.hint, + ); + + /// DTO → Drift Companion (for DB insert/update) + UsersCompanion toCompanion() => UsersCompanion( + uid: Value(uid), + uuid: Value(uuid), + lastOnline: Value(lastOnline), + profilePic: Value(profilePic), + profilePicGaussian: Value(profilePicGaussian ?? ''), + nickname: Value(nickname), + contact: Value(contact), + countryCode: Value(countryCode), + email: Value(email), + recoveryEmail: Value(recoveryEmail), + username: Value(username), + bio: Value(bio), + relationship: Value(relationship), + userAlias: Value(userAlias), + hint: Value(hint), + ); +} \ No newline at end of file diff --git a/apps/im_app/lib/data/models/user_request_history_dto.dart b/apps/im_app/lib/data/models/user_request_history_dto.dart new file mode 100644 index 0000000..49b2b35 --- /dev/null +++ b/apps/im_app/lib/data/models/user_request_history_dto.dart @@ -0,0 +1,49 @@ +import 'package:drift/drift.dart'; +import 'package:im_app/data/local/drift/app_database.dart'; +import 'package:im_app/domain/entities/user_request_history.dart'; + +/// 用户请求历史 DTO +class UserRequestHistoryDto { + final int id; + final int? status; + final int? createdAt; + + const UserRequestHistoryDto({ + required this.id, + this.status, + this.createdAt, + }); + + factory UserRequestHistoryDto.fromJson(Map json) => + UserRequestHistoryDto( + id: json['id'] as int, + status: json['status'], + createdAt: json['created_at'], + ); + + Map toJson() => { + 'id': id, + 'status': status, + 'created_at': createdAt, + }; + + UserRequestHistory toEntity() => UserRequestHistory( + id: id, + status: status, + createdAt: createdAt, + ); + + factory UserRequestHistoryDto.fromEntity(UserRequestHistory history) => + UserRequestHistoryDto( + id: history.id, + status: history.status, + createdAt: history.createdAt, + ); + + UserRequestHistoriesCompanion toCompanion() => + UserRequestHistoriesCompanion( + id: Value(id), + status: Value(status), + createdAt: Value(createdAt), + ); +} \ No newline at end of file diff --git a/apps/im_app/lib/data/models/workspace_dto.dart b/apps/im_app/lib/data/models/workspace_dto.dart new file mode 100644 index 0000000..35c2a7a --- /dev/null +++ b/apps/im_app/lib/data/models/workspace_dto.dart @@ -0,0 +1,116 @@ +import 'package:drift/drift.dart'; +import 'package:im_app/data/local/drift/app_database.dart'; +import 'package:im_app/domain/entities/workspace.dart'; + +/// 工作空间 DTO +class WorkspaceDto { + final int id; + final String? name; + final int? ownerId; + final String? description; + final String? logo; + final int? grade; + final int? cap; + final String? currency; + final int? status; + final int? createdAt; + final int? updatedAt; + final int? deletedAt; + final int? channelGroupId; + + const WorkspaceDto({ + required this.id, + this.name, + this.ownerId, + this.description, + this.logo, + this.grade, + this.cap, + this.currency, + this.status, + this.createdAt, + this.updatedAt, + this.deletedAt, + this.channelGroupId, + }); + + factory WorkspaceDto.fromJson(Map json) => WorkspaceDto( + id: json['id'] as int, + name: json['name'], + ownerId: json['owner_id'], + description: json['description'], + logo: json['logo'], + grade: json['grade'], + cap: json['cap'], + currency: json['currency'], + status: json['status'], + createdAt: json['created_at'], + updatedAt: json['updated_at'], + deletedAt: json['deleted_at'], + channelGroupId: json['channel_group_id'], + ); + + Map toJson() => { + 'id': id, + 'name': name, + 'owner_id': ownerId, + 'description': description, + 'logo': logo, + 'grade': grade, + 'cap': cap, + 'currency': currency, + 'status': status, + 'created_at': createdAt, + 'updated_at': updatedAt, + 'deleted_at': deletedAt, + 'channel_group_id': channelGroupId, + }; + + Workspace toEntity() => Workspace( + id: id, + name: name, + ownerId: ownerId, + description: description, + logo: logo, + grade: grade, + cap: cap, + currency: currency, + status: status, + createdAt: createdAt, + updatedAt: updatedAt, + deletedAt: deletedAt, + channelGroupId: channelGroupId, + ); + + factory WorkspaceDto.fromEntity(Workspace workspace) => WorkspaceDto( + id: workspace.id, + name: workspace.name, + ownerId: workspace.ownerId, + description: workspace.description, + logo: workspace.logo, + grade: workspace.grade, + cap: workspace.cap, + currency: workspace.currency, + status: workspace.status, + createdAt: workspace.createdAt, + updatedAt: workspace.updatedAt, + deletedAt: workspace.deletedAt, + channelGroupId: workspace.channelGroupId, + ); + + WorkspacesCompanion toCompanion() => WorkspacesCompanion( + id: Value(id), + name: Value(name), + ownerId: Value(ownerId), + description: Value(description), + logo: Value(logo), + grade: Value(grade), + cap: Value(cap), + currency: Value(currency), + status: Value(status), + createdAt: Value(createdAt), + updatedAt: Value(updatedAt), + deletedAt: Value(deletedAt), + channelGroupId: Value(channelGroupId), + ); +} \ No newline at end of file diff --git a/apps/im_app/lib/data/remote/get_profile_request.dart b/apps/im_app/lib/data/remote/get_profile_request.dart index a02a3bb..5398026 100644 --- a/apps/im_app/lib/data/remote/get_profile_request.dart +++ b/apps/im_app/lib/data/remote/get_profile_request.dart @@ -28,31 +28,75 @@ part 'get_profile_request.g.dart'; /// 用户资料响应 DTO(只需反序列化,禁止生成无用的 toJson) @JsonSerializable(createToJson: false) class ProfileData { - @JsonKey(name: 'user_id') - final String userId; + final int uid; + final String uuid; + @JsonKey(name: 'last_online') + final int lastOnline; + @JsonKey(name: 'profile_pic') + final String profilePic; + @JsonKey(name: 'profile_pic_gaussian') + final String profilePicGaussian; + final String nickname; + final String contact; + @JsonKey(name: 'country_code') + final String countryCode; final String email; - final String? nickname; - final String? avatar; + @JsonKey(name: 'recovery_email') + final String recoveryEmail; + final String username; + final String bio; + final int relationship; + @JsonKey(name: 'user_alias') + final String? userAlias; + @JsonKey(name: 'channel_id') + final int channelId; + @JsonKey(name: 'channel_group_id') + final int channelGroupId; + final String hint; const ProfileData({ - required this.userId, + required this.uid, + required this.uuid, + required this.lastOnline, + required this.profilePic, + required this.profilePicGaussian, + required this.nickname, + required this.contact, + required this.countryCode, required this.email, - this.nickname, - this.avatar, + required this.recoveryEmail, + required this.username, + required this.bio, + required this.relationship, + this.userAlias, + required this.channelId, + required this.channelGroupId, + required this.hint, }); factory ProfileData.fromJson(Map json) => _$ProfileDataFromJson(json); /// DTO → Domain Entity - User toEntity() { - return User( - id: userId, - email: email, - nickname: nickname, - avatar: avatar, - ); - } + User toEntity() => User( + uid: uid, + uuid: uuid, + lastOnline: lastOnline, + profilePic: profilePic, + profilePicGaussian: profilePicGaussian, + nickname: nickname, + contact: contact, + countryCode: countryCode, + email: email, + recoveryEmail: recoveryEmail, + username: username, + bio: bio, + relationship: relationship, + userAlias: userAlias, + channelId: channelId, + channelGroupId: channelGroupId, + hint: hint, + ); } // ───────────────────────────────────────────── diff --git a/apps/im_app/lib/data/remote/login_request.dart b/apps/im_app/lib/data/remote/login_request.dart index e5e6468..4145d71 100644 --- a/apps/im_app/lib/data/remote/login_request.dart +++ b/apps/im_app/lib/data/remote/login_request.dart @@ -8,75 +8,155 @@ part 'login_request.g.dart'; /// # /auth/login — 登录接口 /// -/// 一个端点 = 一个文件,Response DTO + Request 放在同一文件中。 -/// /// ## 数据流位置 /// /// ``` /// AuthRepositoryImpl.login(email, password) /// → _client.executeRequest( ★ LoginRequest ★ ) ← 你在这里 /// → 服务端 POST /auth/login -/// → 响应 JSON → ★ LoginData ★ ← 也在这里 -/// → LoginData.toEntity() → User +/// → 响应 JSON → ★ LoginResponse ★ ← 也在这里 +/// → LoginResponse.toEntity() → User /// ``` // ───────────────────────────────────────────── // Response DTO // ───────────────────────────────────────────── -/// 登录响应 DTO -/// -/// 服务端返回的登录数据,包含 token 和用户信息。 -/// 通过 [toEntity] 转换为 Domain Entity [User]。 -@JsonSerializable() -class LoginData { - final String token; - @JsonKey(name: 'user_id') - final String userId; +@JsonSerializable(createToJson: false) +class LoginProfile { + final int uid; + final String uuid; + @JsonKey(name: 'last_online') + final int lastOnline; + @JsonKey(name: 'profile_pic') + final String profilePic; + @JsonKey(name: 'profile_pic_gaussian') + final String profilePicGaussian; + final String nickname; + final String contact; + @JsonKey(name: 'country_code') + final String countryCode; final String email; - final String? nickname; - final String? avatar; + @JsonKey(name: 'recovery_email') + final String recoveryEmail; + final String username; + final String bio; + final int relationship; + @JsonKey(name: 'user_alias') + final String? userAlias; + @JsonKey(name: 'channel_id') + final int channelId; + @JsonKey(name: 'channel_group_id') + final int channelGroupId; + final String hint; + + const LoginProfile({ + required this.uid, + required this.uuid, + required this.lastOnline, + required this.profilePic, + required this.profilePicGaussian, + required this.nickname, + required this.contact, + required this.countryCode, + required this.email, + required this.recoveryEmail, + required this.username, + required this.bio, + required this.relationship, + this.userAlias, + required this.channelId, + required this.channelGroupId, + required this.hint, + }); + + factory LoginProfile.fromJson(Map json) => + _$LoginProfileFromJson(json); + + User toEntity() => User( + uid: uid, + uuid: uuid, + lastOnline: lastOnline, + profilePic: profilePic, + profilePicGaussian: profilePicGaussian, + nickname: nickname, + contact: contact, + countryCode: countryCode, + email: email, + recoveryEmail: recoveryEmail, + username: username, + bio: bio, + relationship: relationship, + userAlias: userAlias, + channelId: channelId, + channelGroupId: channelGroupId, + hint: hint, + ); +} + +@JsonSerializable(createToJson: false, explicitToJson: true) +class LoginData { + @JsonKey(name: 'account_id') + final String accountId; + final LoginProfile profile; + final String nonce; + @JsonKey(name: 'access_token') + final String accessToken; + @JsonKey(name: 'refresh_token') + final String refreshToken; + @JsonKey(name: 'device_id') + final String deviceId; + @JsonKey(name: 'login_data') + final String loginData; const LoginData({ - required this.token, - required this.userId, - required this.email, - this.nickname, - this.avatar, + required this.accountId, + required this.profile, + required this.nonce, + required this.accessToken, + required this.refreshToken, + required this.deviceId, + required this.loginData, }); factory LoginData.fromJson(Map json) => _$LoginDataFromJson(json); - Map toJson() => _$LoginDataToJson(this); + User toEntity() => profile.toEntity(); +} - /// DTO → Domain Entity - User toEntity() { - return User( - id: userId, - email: email, - nickname: nickname, - avatar: avatar, - ); - } +/// Top-level envelope: { "code": 0, "message": "OK", "data": { ... } } +@JsonSerializable(createToJson: false, explicitToJson: true) +class LoginResponse { + final int code; + final String message; + final LoginData data; + + const LoginResponse({ + required this.code, + required this.message, + required this.data, + }); + + factory LoginResponse.fromJson(Map json) => + _$LoginResponseFromJson(json); + + User toEntity() => data.toEntity(); } // ───────────────────────────────────────────── // Request // ───────────────────────────────────────────── -/// 登录请求 -/// -/// `@ApiRequest` 自动生成 `_$LoginRequestApi` mixin, -/// 提供 path / method / requestType / includeToken / fromJson 自动注册。 @ApiRequest( path: ApiPaths.authLogin, method: HttpMethod.post, - responseType: LoginData, + responseType: LoginResponse, requestType: ApiRequestType.login, ) @JsonSerializable() -class LoginRequest extends ApiRequestable with _$LoginRequestApi { +class LoginRequest extends ApiRequestable + with _$LoginRequestApi { final String email; final String password; @@ -87,4 +167,4 @@ class LoginRequest extends ApiRequestable with _$LoginRequestApi { @override Map toJson() => _$LoginRequestToJson(this); -} +} \ No newline at end of file diff --git a/apps/im_app/lib/data/repositories/auth_repository_impl.dart b/apps/im_app/lib/data/repositories/auth_repository_impl.dart index 912e628..0dc93e2 100644 --- a/apps/im_app/lib/data/repositories/auth_repository_impl.dart +++ b/apps/im_app/lib/data/repositories/auth_repository_impl.dart @@ -30,18 +30,18 @@ class AuthRepositoryImpl implements AuthRepository { AuthRepositoryImpl({required NetworksSdkApi client, required void Function(String?) onTokenUpdate,}) : _client = client, _onTokenUpdate = onTokenUpdate; @override - Future login({required String email, required String password,}) async - { - final LoginData? loginData = await _client.executeRequest(LoginRequest(email: email, password: password),); + Future login({required String email, required String password}) async { + final LoginResponse? loginResponse = await _client.executeRequest( + LoginRequest(email: email, password: password), + ); - if (loginData == null) { - throw Exception('Login failed: empty response'); // TODO: 接入国际化 + if (loginResponse == null) { + throw Exception('Login failed: empty response'); } - // 回调写入 Token(内存 + 持久化由 Provider 层组合) - _onTokenUpdate(loginData.token); + _onTokenUpdate(loginResponse.data.accessToken); - return loginData.toEntity(); // DTO → Domain Entity + return loginResponse.toEntity(); } @override diff --git a/apps/im_app/lib/domain/entities/call_log.dart b/apps/im_app/lib/domain/entities/call_log.dart new file mode 100644 index 0000000..e60c3cd --- /dev/null +++ b/apps/im_app/lib/domain/entities/call_log.dart @@ -0,0 +1,67 @@ +/// 通话记录 Domain 实体 +/// +/// 全局共享实体,被 call / chat 等多个 Feature 共用。 +/// 纯 Dart 类,零 Flutter / 零网络 / 零 DB 依赖。 +class CallLog { + final String id; + final int? callerId; + final int? receiverId; + final int? chatId; + final int? duration; + final int? videoCall; + final int? createdAt; + final int? updatedAt; + final int? endedAt; + final int? status; + final int? isDeleted; + final int? deletedAt; + final int? isRead; + + const CallLog({ + required this.id, + this.callerId, + this.receiverId, + this.chatId, + this.duration, + this.videoCall, + this.createdAt, + this.updatedAt, + this.endedAt, + this.status, + this.isDeleted, + this.deletedAt, + this.isRead, + }); + + CallLog copyWith({ + String? id, + int? callerId, + int? receiverId, + int? chatId, + int? duration, + int? videoCall, + int? createdAt, + int? updatedAt, + int? endedAt, + int? status, + int? isDeleted, + int? deletedAt, + int? isRead, + }) { + return CallLog( + id: id ?? this.id, + callerId: callerId ?? this.callerId, + receiverId: receiverId ?? this.receiverId, + chatId: chatId ?? this.chatId, + duration: duration ?? this.duration, + videoCall: videoCall ?? this.videoCall, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + endedAt: endedAt ?? this.endedAt, + status: status ?? this.status, + isDeleted: isDeleted ?? this.isDeleted, + deletedAt: deletedAt ?? this.deletedAt, + isRead: isRead ?? this.isRead, + ); + } +} \ No newline at end of file diff --git a/apps/im_app/lib/domain/entities/chat.dart b/apps/im_app/lib/domain/entities/chat.dart new file mode 100644 index 0000000..63e7f1d --- /dev/null +++ b/apps/im_app/lib/domain/entities/chat.dart @@ -0,0 +1,200 @@ +/// 聊天 Domain 实体 +class Chat { + final int id; + final int? typ; + final int? lastId; + final int? lastTyp; + final String? lastMsg; + final int? lastTime; + final int lastPos; + final int firstPos; + final int? msgIdx; + final String? profile; + final String? pin; + final String? icon; + final String iconGaussian; + final String? name; + final int? userId; + final int? chatId; + final int? friendId; + final int? sort; + final int? unreadNum; + final int? unreadCount; + final int? hideChatMsgIdx; + final int? readChatMsgIdx; + final int? otherReadIdx; + final String? unreadAtMsgIdx; + final int? deleteTime; + final int? addIndex; + final int flag; + final int? flagMy; + final int? autoDeleteInterval; + final int? mute; + final int? verified; + final int? createTime; + final int? startIdx; + final int? isReadMsg; + final String translateOutgoing; + final String translateIncoming; + final int incomingIdx; + final int outgoingIdx; + final int incomingSoundId; + final int outgoingSoundId; + final int notificationSoundId; + final String chatKey; + final String activeChatKey; + final int coverIdx; + final int round; + final int workspaceId; + final int localPermission; + + const Chat({ + required this.id, + this.typ, + this.lastId, + this.lastTyp, + this.lastMsg, + this.lastTime, + this.lastPos = 0, + this.firstPos = -1, + this.msgIdx, + this.profile, + this.pin, + this.icon, + this.iconGaussian = '', + this.name, + this.userId, + this.chatId, + this.friendId, + this.sort, + this.unreadNum, + this.unreadCount, + this.hideChatMsgIdx, + this.readChatMsgIdx, + this.otherReadIdx, + this.unreadAtMsgIdx, + this.deleteTime, + this.addIndex, + this.flag = 0, + this.flagMy, + this.autoDeleteInterval, + this.mute, + this.verified, + this.createTime, + this.startIdx, + this.isReadMsg, + this.translateOutgoing = '', + this.translateIncoming = '', + this.incomingIdx = 0, + this.outgoingIdx = 0, + this.incomingSoundId = 0, + this.outgoingSoundId = 0, + this.notificationSoundId = 0, + this.chatKey = '', + this.activeChatKey = '', + this.coverIdx = 0, + this.round = 0, + this.workspaceId = 0, + this.localPermission = 0, + }); + + Chat copyWith({ + int? id, + int? typ, + int? lastId, + int? lastTyp, + String? lastMsg, + int? lastTime, + int? lastPos, + int? firstPos, + int? msgIdx, + String? profile, + String? pin, + String? icon, + String? iconGaussian, + String? name, + int? userId, + int? chatId, + int? friendId, + int? sort, + int? unreadNum, + int? unreadCount, + int? hideChatMsgIdx, + int? readChatMsgIdx, + int? otherReadIdx, + String? unreadAtMsgIdx, + int? deleteTime, + int? addIndex, + int? flag, + int? flagMy, + int? autoDeleteInterval, + int? mute, + int? verified, + int? createTime, + int? startIdx, + int? isReadMsg, + String? translateOutgoing, + String? translateIncoming, + int? incomingIdx, + int? outgoingIdx, + int? incomingSoundId, + int? outgoingSoundId, + int? notificationSoundId, + String? chatKey, + String? activeChatKey, + int? coverIdx, + int? round, + int? workspaceId, + int? localPermission, + }) { + return Chat( + id: id ?? this.id, + typ: typ ?? this.typ, + lastId: lastId ?? this.lastId, + lastTyp: lastTyp ?? this.lastTyp, + lastMsg: lastMsg ?? this.lastMsg, + lastTime: lastTime ?? this.lastTime, + lastPos: lastPos ?? this.lastPos, + firstPos: firstPos ?? this.firstPos, + msgIdx: msgIdx ?? this.msgIdx, + profile: profile ?? this.profile, + pin: pin ?? this.pin, + icon: icon ?? this.icon, + iconGaussian: iconGaussian ?? this.iconGaussian, + name: name ?? this.name, + userId: userId ?? this.userId, + chatId: chatId ?? this.chatId, + friendId: friendId ?? this.friendId, + sort: sort ?? this.sort, + unreadNum: unreadNum ?? this.unreadNum, + unreadCount: unreadCount ?? this.unreadCount, + hideChatMsgIdx: hideChatMsgIdx ?? this.hideChatMsgIdx, + readChatMsgIdx: readChatMsgIdx ?? this.readChatMsgIdx, + otherReadIdx: otherReadIdx ?? this.otherReadIdx, + unreadAtMsgIdx: unreadAtMsgIdx ?? this.unreadAtMsgIdx, + deleteTime: deleteTime ?? this.deleteTime, + addIndex: addIndex ?? this.addIndex, + flag: flag ?? this.flag, + flagMy: flagMy ?? this.flagMy, + autoDeleteInterval: autoDeleteInterval ?? this.autoDeleteInterval, + mute: mute ?? this.mute, + verified: verified ?? this.verified, + createTime: createTime ?? this.createTime, + startIdx: startIdx ?? this.startIdx, + isReadMsg: isReadMsg ?? this.isReadMsg, + translateOutgoing: translateOutgoing ?? this.translateOutgoing, + translateIncoming: translateIncoming ?? this.translateIncoming, + incomingIdx: incomingIdx ?? this.incomingIdx, + outgoingIdx: outgoingIdx ?? this.outgoingIdx, + incomingSoundId: incomingSoundId ?? this.incomingSoundId, + outgoingSoundId: outgoingSoundId ?? this.outgoingSoundId, + notificationSoundId: notificationSoundId ?? this.notificationSoundId, + chatKey: chatKey ?? this.chatKey, + activeChatKey: activeChatKey ?? this.activeChatKey, + coverIdx: coverIdx ?? this.coverIdx, + round: round ?? this.round, + workspaceId: workspaceId ?? this.workspaceId, + localPermission: localPermission ?? this.localPermission, + ); + } +} \ No newline at end of file diff --git a/apps/im_app/lib/domain/entities/chat_bot.dart b/apps/im_app/lib/domain/entities/chat_bot.dart new file mode 100644 index 0000000..28c35c3 --- /dev/null +++ b/apps/im_app/lib/domain/entities/chat_bot.dart @@ -0,0 +1,100 @@ +/// 聊天机器人 Domain 实体 +class ChatBot { + final int id; + final String? name; + final String? username; + final int? botUserId; + final String? icon; + final String? iconGaussian; + final String? description; + final String? token; + final int? flag; + final int? status; + final String? webhook; + final String? commands; + final String? banner; + final int? channelId; + final int? channelGroupId; + final int? deletedAt; + final String? internalWebhook; + final int? mode; + final String? redirectUrl; + final int? isInvitable; + final int? isAllowForward; + final String? tips; + + const ChatBot({ + required this.id, + this.name, + this.username, + this.botUserId, + this.icon, + this.iconGaussian, + this.description, + this.token, + this.flag, + this.status, + this.webhook, + this.commands, + this.banner, + this.channelId, + this.channelGroupId, + this.deletedAt, + this.internalWebhook, + this.mode, + this.redirectUrl, + this.isInvitable, + this.isAllowForward, + this.tips, + }); + + ChatBot copyWith({ + int? id, + String? name, + String? username, + int? botUserId, + String? icon, + String? iconGaussian, + String? description, + String? token, + int? flag, + int? status, + String? webhook, + String? commands, + String? banner, + int? channelId, + int? channelGroupId, + int? deletedAt, + String? internalWebhook, + int? mode, + String? redirectUrl, + int? isInvitable, + int? isAllowForward, + String? tips, + }) { + return ChatBot( + id: id ?? this.id, + name: name ?? this.name, + username: username ?? this.username, + botUserId: botUserId ?? this.botUserId, + icon: icon ?? this.icon, + iconGaussian: iconGaussian ?? this.iconGaussian, + description: description ?? this.description, + token: token ?? this.token, + flag: flag ?? this.flag, + status: status ?? this.status, + webhook: webhook ?? this.webhook, + commands: commands ?? this.commands, + banner: banner ?? this.banner, + channelId: channelId ?? this.channelId, + channelGroupId: channelGroupId ?? this.channelGroupId, + deletedAt: deletedAt ?? this.deletedAt, + internalWebhook: internalWebhook ?? this.internalWebhook, + mode: mode ?? this.mode, + redirectUrl: redirectUrl ?? this.redirectUrl, + isInvitable: isInvitable ?? this.isInvitable, + isAllowForward: isAllowForward ?? this.isAllowForward, + tips: tips ?? this.tips, + ); + } +} \ No newline at end of file diff --git a/apps/im_app/lib/domain/entities/chat_category.dart b/apps/im_app/lib/domain/entities/chat_category.dart new file mode 100644 index 0000000..6dc9d75 --- /dev/null +++ b/apps/im_app/lib/domain/entities/chat_category.dart @@ -0,0 +1,48 @@ +/// 聊天分类 Domain 实体 +class ChatCategory { + final int id; + final String? name; + final String? includedChatIds; + final String? excludedChatIds; + final int? seq; + final int isHide; + final int createdAt; + final int updatedAt; + final int deletedAt; + + const ChatCategory({ + required this.id, + this.name, + this.includedChatIds, + this.excludedChatIds, + this.seq, + this.isHide = 0, + this.createdAt = 0, + this.updatedAt = 0, + this.deletedAt = 0, + }); + + ChatCategory copyWith({ + int? id, + String? name, + String? includedChatIds, + String? excludedChatIds, + int? seq, + int? isHide, + int? createdAt, + int? updatedAt, + int? deletedAt, + }) { + return ChatCategory( + id: id ?? this.id, + name: name ?? this.name, + includedChatIds: includedChatIds ?? this.includedChatIds, + excludedChatIds: excludedChatIds ?? this.excludedChatIds, + seq: seq ?? this.seq, + isHide: isHide ?? this.isHide, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + deletedAt: deletedAt ?? this.deletedAt, + ); + } +} \ No newline at end of file diff --git a/apps/im_app/lib/domain/entities/discover_mini_app.dart b/apps/im_app/lib/domain/entities/discover_mini_app.dart new file mode 100644 index 0000000..89b81a2 --- /dev/null +++ b/apps/im_app/lib/domain/entities/discover_mini_app.dart @@ -0,0 +1,112 @@ +/// 发现小程序 Domain 实体 +class DiscoverMiniApp { + final String id; + final String? name; + final String? openuid; + final String? devId; + final String? icon; + final String? iconGaussian; + final String? downloadUrl; + final String? description; + final int? version; + final int? typ; + final int? flag; + final int? reviewStatus; + final int? favoriteAt; + final int? isActive; + final int? createdAt; + final int? updatedAt; + final int? deletedAt; + final double? score; + final String? channels; + final String? devName; + final String? pictureGaussian; + final String? picture; + final int? commentNum; + final String? lastLoginAt; + final String? screen; + + const DiscoverMiniApp({ + required this.id, + this.name, + this.openuid, + this.devId, + this.icon, + this.iconGaussian, + this.downloadUrl, + this.description, + this.version, + this.typ, + this.flag, + this.reviewStatus, + this.favoriteAt, + this.isActive, + this.createdAt, + this.updatedAt, + this.deletedAt, + this.score, + this.channels, + this.devName, + this.pictureGaussian, + this.picture, + this.commentNum, + this.lastLoginAt, + this.screen, + }); + + DiscoverMiniApp copyWith({ + String? id, + String? name, + String? openuid, + String? devId, + String? icon, + String? iconGaussian, + String? downloadUrl, + String? description, + int? version, + int? typ, + int? flag, + int? reviewStatus, + int? favoriteAt, + int? isActive, + int? createdAt, + int? updatedAt, + int? deletedAt, + double? score, + String? channels, + String? devName, + String? pictureGaussian, + String? picture, + int? commentNum, + String? lastLoginAt, + String? screen, + }) { + return DiscoverMiniApp( + id: id ?? this.id, + name: name ?? this.name, + openuid: openuid ?? this.openuid, + devId: devId ?? this.devId, + icon: icon ?? this.icon, + iconGaussian: iconGaussian ?? this.iconGaussian, + downloadUrl: downloadUrl ?? this.downloadUrl, + description: description ?? this.description, + version: version ?? this.version, + typ: typ ?? this.typ, + flag: flag ?? this.flag, + reviewStatus: reviewStatus ?? this.reviewStatus, + favoriteAt: favoriteAt ?? this.favoriteAt, + isActive: isActive ?? this.isActive, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + deletedAt: deletedAt ?? this.deletedAt, + score: score ?? this.score, + channels: channels ?? this.channels, + devName: devName ?? this.devName, + pictureGaussian: pictureGaussian ?? this.pictureGaussian, + picture: picture ?? this.picture, + commentNum: commentNum ?? this.commentNum, + lastLoginAt: lastLoginAt ?? this.lastLoginAt, + screen: screen ?? this.screen, + ); + } +} \ No newline at end of file diff --git a/apps/im_app/lib/domain/entities/explore_mini_app.dart b/apps/im_app/lib/domain/entities/explore_mini_app.dart new file mode 100644 index 0000000..0e6b347 --- /dev/null +++ b/apps/im_app/lib/domain/entities/explore_mini_app.dart @@ -0,0 +1,112 @@ +/// 探索小程序 Domain 实体 +class ExploreMiniApp { + final String id; + final String? name; + final String? openuid; + final String? devId; + final String? icon; + final String? iconGaussian; + final String? downloadUrl; + final String? description; + final int? version; + final int? typ; + final int? flag; + final int? reviewStatus; + final int? favoriteAt; + final int? isActive; + final int? createdAt; + final int? updatedAt; + final int? deletedAt; + final double? score; + final String? channels; + final String? devName; + final String? pictureGaussian; + final String? picture; + final int? commentNum; + final int? lastLoginAt; + final String? screen; + + const ExploreMiniApp({ + required this.id, + this.name, + this.openuid, + this.devId, + this.icon, + this.iconGaussian, + this.downloadUrl, + this.description, + this.version, + this.typ, + this.flag, + this.reviewStatus, + this.favoriteAt, + this.isActive, + this.createdAt, + this.updatedAt, + this.deletedAt, + this.score, + this.channels, + this.devName, + this.pictureGaussian, + this.picture, + this.commentNum, + this.lastLoginAt, + this.screen, + }); + + ExploreMiniApp copyWith({ + String? id, + String? name, + String? openuid, + String? devId, + String? icon, + String? iconGaussian, + String? downloadUrl, + String? description, + int? version, + int? typ, + int? flag, + int? reviewStatus, + int? favoriteAt, + int? isActive, + int? createdAt, + int? updatedAt, + int? deletedAt, + double? score, + String? channels, + String? devName, + String? pictureGaussian, + String? picture, + int? commentNum, + int? lastLoginAt, + String? screen, + }) { + return ExploreMiniApp( + id: id ?? this.id, + name: name ?? this.name, + openuid: openuid ?? this.openuid, + devId: devId ?? this.devId, + icon: icon ?? this.icon, + iconGaussian: iconGaussian ?? this.iconGaussian, + downloadUrl: downloadUrl ?? this.downloadUrl, + description: description ?? this.description, + version: version ?? this.version, + typ: typ ?? this.typ, + flag: flag ?? this.flag, + reviewStatus: reviewStatus ?? this.reviewStatus, + favoriteAt: favoriteAt ?? this.favoriteAt, + isActive: isActive ?? this.isActive, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + deletedAt: deletedAt ?? this.deletedAt, + score: score ?? this.score, + channels: channels ?? this.channels, + devName: devName ?? this.devName, + pictureGaussian: pictureGaussian ?? this.pictureGaussian, + picture: picture ?? this.picture, + commentNum: commentNum ?? this.commentNum, + lastLoginAt: lastLoginAt ?? this.lastLoginAt, + screen: screen ?? this.screen, + ); + } +} \ No newline at end of file diff --git a/apps/im_app/lib/domain/entities/favorite_mini_app.dart b/apps/im_app/lib/domain/entities/favorite_mini_app.dart new file mode 100644 index 0000000..3b00e1e --- /dev/null +++ b/apps/im_app/lib/domain/entities/favorite_mini_app.dart @@ -0,0 +1,112 @@ +/// 收藏小程序 Domain 实体 +class FavoriteMiniApp { + final String id; + final String? name; + final String? openuid; + final String? devId; + final String? icon; + final String? iconGaussian; + final String? downloadUrl; + final String? description; + final int? version; + final int? typ; + final int? flag; + final int? reviewStatus; + final int? favoriteAt; + final int? isActive; + final int? createdAt; + final int? updatedAt; + final int? deletedAt; + final double? score; + final String? channels; + final String? devName; + final String? pictureGaussian; + final String? picture; + final int? commentNum; + final int? lastLoginAt; + final String? screen; + + const FavoriteMiniApp({ + required this.id, + this.name, + this.openuid, + this.devId, + this.icon, + this.iconGaussian, + this.downloadUrl, + this.description, + this.version, + this.typ, + this.flag, + this.reviewStatus, + this.favoriteAt, + this.isActive, + this.createdAt, + this.updatedAt, + this.deletedAt, + this.score, + this.channels, + this.devName, + this.pictureGaussian, + this.picture, + this.commentNum, + this.lastLoginAt, + this.screen, + }); + + FavoriteMiniApp copyWith({ + String? id, + String? name, + String? openuid, + String? devId, + String? icon, + String? iconGaussian, + String? downloadUrl, + String? description, + int? version, + int? typ, + int? flag, + int? reviewStatus, + int? favoriteAt, + int? isActive, + int? createdAt, + int? updatedAt, + int? deletedAt, + double? score, + String? channels, + String? devName, + String? pictureGaussian, + String? picture, + int? commentNum, + int? lastLoginAt, + String? screen, + }) { + return FavoriteMiniApp( + id: id ?? this.id, + name: name ?? this.name, + openuid: openuid ?? this.openuid, + devId: devId ?? this.devId, + icon: icon ?? this.icon, + iconGaussian: iconGaussian ?? this.iconGaussian, + downloadUrl: downloadUrl ?? this.downloadUrl, + description: description ?? this.description, + version: version ?? this.version, + typ: typ ?? this.typ, + flag: flag ?? this.flag, + reviewStatus: reviewStatus ?? this.reviewStatus, + favoriteAt: favoriteAt ?? this.favoriteAt, + isActive: isActive ?? this.isActive, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + deletedAt: deletedAt ?? this.deletedAt, + score: score ?? this.score, + channels: channels ?? this.channels, + devName: devName ?? this.devName, + pictureGaussian: pictureGaussian ?? this.pictureGaussian, + picture: picture ?? this.picture, + commentNum: commentNum ?? this.commentNum, + lastLoginAt: lastLoginAt ?? this.lastLoginAt, + screen: screen ?? this.screen, + ); + } +} \ No newline at end of file diff --git a/apps/im_app/lib/domain/entities/favourite.dart b/apps/im_app/lib/domain/entities/favourite.dart new file mode 100644 index 0000000..6ce8110 --- /dev/null +++ b/apps/im_app/lib/domain/entities/favourite.dart @@ -0,0 +1,72 @@ +/// 收藏 Domain 实体 +class Favourite { + final int id; + final String parentId; + final String data; + final int createdAt; + final int updatedAt; + final int deletedAt; + final int? source; + final int? userId; + final int? authorId; + final String typ; + final String tag; + final int isPin; + final int chatTyp; + final int isUploaded; + final String urls; + + const Favourite({ + required this.id, + this.parentId = '', + this.data = '', + this.createdAt = 0, + this.updatedAt = 0, + this.deletedAt = 0, + this.source, + this.userId, + this.authorId, + this.typ = '[]', + this.tag = '[]', + this.isPin = 0, + this.chatTyp = 0, + this.isUploaded = 1, + this.urls = '[]', + }); + + Favourite copyWith({ + int? id, + String? parentId, + String? data, + int? createdAt, + int? updatedAt, + int? deletedAt, + int? source, + int? userId, + int? authorId, + String? typ, + String? tag, + int? isPin, + int? chatTyp, + int? isUploaded, + String? urls, + }) { + return Favourite( + id: id ?? this.id, + parentId: parentId ?? this.parentId, + data: data ?? this.data, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + deletedAt: deletedAt ?? this.deletedAt, + source: source ?? this.source, + userId: userId ?? this.userId, + authorId: authorId ?? this.authorId, + typ: typ ?? this.typ, + tag: tag ?? this.tag, + isPin: isPin ?? this.isPin, + chatTyp: chatTyp ?? this.chatTyp, + isUploaded: isUploaded ?? this.isUploaded, + urls: urls ?? this.urls, + ); + } +} \ No newline at end of file diff --git a/apps/im_app/lib/domain/entities/favourite_detail.dart b/apps/im_app/lib/domain/entities/favourite_detail.dart new file mode 100644 index 0000000..de4373f --- /dev/null +++ b/apps/im_app/lib/domain/entities/favourite_detail.dart @@ -0,0 +1,44 @@ +/// 收藏详情 Domain 实体 +class FavouriteDetail { + final int? id; + final String relatedId; + final String content; + final int? typ; + final int? messageId; + final int? sendId; + final int? chatId; + final int? sendTime; + + const FavouriteDetail({ + this.id, + this.relatedId = '', + this.content = '', + this.typ, + this.messageId, + this.sendId, + this.chatId, + this.sendTime, + }); + + FavouriteDetail copyWith({ + int? id, + String? relatedId, + String? content, + int? typ, + int? messageId, + int? sendId, + int? chatId, + int? sendTime, + }) { + return FavouriteDetail( + id: id ?? this.id, + relatedId: relatedId ?? this.relatedId, + content: content ?? this.content, + typ: typ ?? this.typ, + messageId: messageId ?? this.messageId, + sendId: sendId ?? this.sendId, + chatId: chatId ?? this.chatId, + sendTime: sendTime ?? this.sendTime, + ); + } +} \ No newline at end of file diff --git a/apps/im_app/lib/domain/entities/group.dart b/apps/im_app/lib/domain/entities/group.dart new file mode 100644 index 0000000..ac25a52 --- /dev/null +++ b/apps/im_app/lib/domain/entities/group.dart @@ -0,0 +1,124 @@ +/// 群组 Domain 实体 +class Group { + final int id; + final int? userJoinDate; + final String? name; + final String? profile; + final String? icon; + final String iconGaussian; + final int? permission; + final int? admin; + final String? members; + final int? owner; + final String? admins; + final int? visible; + final int? speakInterval; + final int? groupType; + final int? roomType; + final int? maxNumber; + final int? channelId; + final int? channelGroupId; + final int? createTime; + final int? updateTime; + final int? addIndex; + final int? maxMember; + final int? expireTime; + final int workspaceId; + final int mode; + final int redpacketPlay; + final String? topic; + final String? rp; + + const Group({ + required this.id, + this.userJoinDate, + this.name, + this.profile, + this.icon, + this.iconGaussian = '', + this.permission, + this.admin, + this.members, + this.owner, + this.admins, + this.visible, + this.speakInterval, + this.groupType, + this.roomType, + this.maxNumber, + this.channelId, + this.channelGroupId, + this.createTime, + this.updateTime, + this.addIndex, + this.maxMember, + this.expireTime, + this.workspaceId = 0, + this.mode = 0, + this.redpacketPlay = 0, + this.topic, + this.rp, + }); + + Group copyWith({ + int? id, + int? userJoinDate, + String? name, + String? profile, + String? icon, + String? iconGaussian, + int? permission, + int? admin, + String? members, + int? owner, + String? admins, + int? visible, + int? speakInterval, + int? groupType, + int? roomType, + int? maxNumber, + int? channelId, + int? channelGroupId, + int? createTime, + int? updateTime, + int? addIndex, + int? maxMember, + int? expireTime, + int? workspaceId, + int? mode, + int? redpacketPlay, + String? topic, + String? rp, + }) { + return Group( + id: id ?? this.id, + userJoinDate: userJoinDate ?? this.userJoinDate, + name: name ?? this.name, + profile: profile ?? this.profile, + icon: icon ?? this.icon, + iconGaussian: iconGaussian ?? this.iconGaussian, + permission: permission ?? this.permission, + admin: admin ?? this.admin, + members: members ?? this.members, + owner: owner ?? this.owner, + admins: admins ?? this.admins, + visible: visible ?? this.visible, + speakInterval: speakInterval ?? this.speakInterval, + groupType: groupType ?? this.groupType, + roomType: roomType ?? this.roomType, + maxNumber: maxNumber ?? this.maxNumber, + channelId: channelId ?? this.channelId, + channelGroupId: channelGroupId ?? this.channelGroupId, + createTime: createTime ?? this.createTime, + updateTime: updateTime ?? this.updateTime, + addIndex: addIndex ?? this.addIndex, + maxMember: maxMember ?? this.maxMember, + expireTime: expireTime ?? this.expireTime, + workspaceId: workspaceId ?? this.workspaceId, + mode: mode ?? this.mode, + redpacketPlay: redpacketPlay ?? this.redpacketPlay, + topic: topic ?? this.topic, + rp: rp ?? this.rp, + ); + } +} \ No newline at end of file diff --git a/apps/im_app/lib/domain/entities/message.dart b/apps/im_app/lib/domain/entities/message.dart new file mode 100644 index 0000000..76eff73 --- /dev/null +++ b/apps/im_app/lib/domain/entities/message.dart @@ -0,0 +1,76 @@ +/// 消息 Domain 实体 +class Message { + final int id; + final int? messageId; + final int? chatId; + final int? chatIdx; + final int? sendId; + final String? content; + final int? typ; + final int? sendTime; + final int? expireTime; + final int? createTime; + final String? atUsers; + final String emojis; + final int editTime; + final int refTyp; + final int flag; + final String cmid; + + const Message({ + required this.id, + this.messageId, + this.chatId, + this.chatIdx, + this.sendId, + this.content, + this.typ, + this.sendTime, + this.expireTime, + this.createTime, + this.atUsers, + this.emojis = '[]', + this.editTime = 0, + this.refTyp = 0, + this.flag = 0, + this.cmid = '', + }); + + Message copyWith({ + int? id, + int? messageId, + int? chatId, + int? chatIdx, + int? sendId, + String? content, + int? typ, + int? sendTime, + int? expireTime, + int? createTime, + String? atUsers, + String? emojis, + int? editTime, + int? refTyp, + int? flag, + String? cmid, + }) { + return Message( + id: id ?? this.id, + messageId: messageId ?? this.messageId, + chatId: chatId ?? this.chatId, + chatIdx: chatIdx ?? this.chatIdx, + sendId: sendId ?? this.sendId, + content: content ?? this.content, + typ: typ ?? this.typ, + sendTime: sendTime ?? this.sendTime, + expireTime: expireTime ?? this.expireTime, + createTime: createTime ?? this.createTime, + atUsers: atUsers ?? this.atUsers, + emojis: emojis ?? this.emojis, + editTime: editTime ?? this.editTime, + refTyp: refTyp ?? this.refTyp, + flag: flag ?? this.flag, + cmid: cmid ?? this.cmid, + ); + } +} \ No newline at end of file diff --git a/apps/im_app/lib/domain/entities/pending_friend_request_history.dart b/apps/im_app/lib/domain/entities/pending_friend_request_history.dart new file mode 100644 index 0000000..ce323f2 --- /dev/null +++ b/apps/im_app/lib/domain/entities/pending_friend_request_history.dart @@ -0,0 +1,36 @@ +/// 待处理好友请求历史 Domain 实体 +class PendingFriendRequestHistory { + final int id; + final int uid; + final int requestTime; + final String? remarks; + final String? source; + final int? rs; + + const PendingFriendRequestHistory({ + required this.id, + required this.uid, + required this.requestTime, + this.remarks, + this.source, + this.rs, + }); + + PendingFriendRequestHistory copyWith({ + int? id, + int? uid, + int? requestTime, + String? remarks, + String? source, + int? rs, + }) { + return PendingFriendRequestHistory( + id: id ?? this.id, + uid: uid ?? this.uid, + requestTime: requestTime ?? this.requestTime, + remarks: remarks ?? this.remarks, + source: source ?? this.source, + rs: rs ?? this.rs, + ); + } +} \ No newline at end of file diff --git a/apps/im_app/lib/domain/entities/recent_mini_app.dart b/apps/im_app/lib/domain/entities/recent_mini_app.dart new file mode 100644 index 0000000..2a9cd37 --- /dev/null +++ b/apps/im_app/lib/domain/entities/recent_mini_app.dart @@ -0,0 +1,112 @@ +/// 最近小程序 Domain 实体 +class RecentMiniApp { + final String id; + final String? name; + final String? openuid; + final String? devId; + final String? icon; + final String? iconGaussian; + final String? downloadUrl; + final String? description; + final int? version; + final int? typ; + final int? flag; + final int? reviewStatus; + final int? favoriteAt; + final int? isActive; + final int? createdAt; + final int? updatedAt; + final int? deletedAt; + final double? score; + final String? channels; + final String? devName; + final String? pictureGaussian; + final String? picture; + final int? commentNum; + final int? lastLoginAt; + final String? screen; + + const RecentMiniApp({ + required this.id, + this.name, + this.openuid, + this.devId, + this.icon, + this.iconGaussian, + this.downloadUrl, + this.description, + this.version, + this.typ, + this.flag, + this.reviewStatus, + this.favoriteAt, + this.isActive, + this.createdAt, + this.updatedAt, + this.deletedAt, + this.score, + this.channels, + this.devName, + this.pictureGaussian, + this.picture, + this.commentNum, + this.lastLoginAt, + this.screen, + }); + + RecentMiniApp copyWith({ + String? id, + String? name, + String? openuid, + String? devId, + String? icon, + String? iconGaussian, + String? downloadUrl, + String? description, + int? version, + int? typ, + int? flag, + int? reviewStatus, + int? favoriteAt, + int? isActive, + int? createdAt, + int? updatedAt, + int? deletedAt, + double? score, + String? channels, + String? devName, + String? pictureGaussian, + String? picture, + int? commentNum, + int? lastLoginAt, + String? screen, + }) { + return RecentMiniApp( + id: id ?? this.id, + name: name ?? this.name, + openuid: openuid ?? this.openuid, + devId: devId ?? this.devId, + icon: icon ?? this.icon, + iconGaussian: iconGaussian ?? this.iconGaussian, + downloadUrl: downloadUrl ?? this.downloadUrl, + description: description ?? this.description, + version: version ?? this.version, + typ: typ ?? this.typ, + flag: flag ?? this.flag, + reviewStatus: reviewStatus ?? this.reviewStatus, + favoriteAt: favoriteAt ?? this.favoriteAt, + isActive: isActive ?? this.isActive, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + deletedAt: deletedAt ?? this.deletedAt, + score: score ?? this.score, + channels: channels ?? this.channels, + devName: devName ?? this.devName, + pictureGaussian: pictureGaussian ?? this.pictureGaussian, + picture: picture ?? this.picture, + commentNum: commentNum ?? this.commentNum, + lastLoginAt: lastLoginAt ?? this.lastLoginAt, + screen: screen ?? this.screen, + ); + } +} \ No newline at end of file diff --git a/apps/im_app/lib/domain/entities/retry.dart b/apps/im_app/lib/domain/entities/retry.dart new file mode 100644 index 0000000..384a1e7 --- /dev/null +++ b/apps/im_app/lib/domain/entities/retry.dart @@ -0,0 +1,60 @@ +/// 重试 Domain 实体 +class Retry { + final int? id; + final int? uid; + final String apiType; + final String endPoint; + final String requestData; + final int? synced; + final String callbackFun; + final int? expired; + final int? replace; + final int? expireTime; + final int? createTime; + final int? addIndex; + + const Retry({ + this.id, + this.uid, + this.apiType = '', + this.endPoint = '', + this.requestData = '', + this.synced, + this.callbackFun = '', + this.expired, + this.replace, + this.expireTime, + this.createTime, + this.addIndex, + }); + + Retry copyWith({ + int? id, + int? uid, + String? apiType, + String? endPoint, + String? requestData, + int? synced, + String? callbackFun, + int? expired, + int? replace, + int? expireTime, + int? createTime, + int? addIndex, + }) { + return Retry( + id: id ?? this.id, + uid: uid ?? this.uid, + apiType: apiType ?? this.apiType, + endPoint: endPoint ?? this.endPoint, + requestData: requestData ?? this.requestData, + synced: synced ?? this.synced, + callbackFun: callbackFun ?? this.callbackFun, + expired: expired ?? this.expired, + replace: replace ?? this.replace, + expireTime: expireTime ?? this.expireTime, + createTime: createTime ?? this.createTime, + addIndex: addIndex ?? this.addIndex, + ); + } +} \ No newline at end of file diff --git a/apps/im_app/lib/domain/entities/sound.dart b/apps/im_app/lib/domain/entities/sound.dart new file mode 100644 index 0000000..954127c --- /dev/null +++ b/apps/im_app/lib/domain/entities/sound.dart @@ -0,0 +1,48 @@ +/// 音效 Domain 实体 +class Sound { + final int id; + final String filePath; + final int typ; + final String name; + final int createdAt; + final int updatedAt; + final int deletedAt; + final int channelGroupId; + final int isDefault; + + const Sound({ + required this.id, + this.filePath = '', + required this.typ, + this.name = '', + required this.createdAt, + required this.updatedAt, + this.deletedAt = 0, + required this.channelGroupId, + required this.isDefault, + }); + + Sound copyWith({ + int? id, + String? filePath, + int? typ, + String? name, + int? createdAt, + int? updatedAt, + int? deletedAt, + int? channelGroupId, + int? isDefault, + }) { + return Sound( + id: id ?? this.id, + filePath: filePath ?? this.filePath, + typ: typ ?? this.typ, + name: name ?? this.name, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + deletedAt: deletedAt ?? this.deletedAt, + channelGroupId: channelGroupId ?? this.channelGroupId, + isDefault: isDefault ?? this.isDefault, + ); + } +} \ No newline at end of file diff --git a/apps/im_app/lib/domain/entities/tag.dart b/apps/im_app/lib/domain/entities/tag.dart new file mode 100644 index 0000000..9777aef --- /dev/null +++ b/apps/im_app/lib/domain/entities/tag.dart @@ -0,0 +1,40 @@ +/// 标签 Domain 实体 +class Tag { + final int? id; + final int? uid; + final String name; + final int? type; + final int? createdAt; + final int? updatedAt; + final int? addIndex; + + const Tag({ + this.id, + this.uid, + this.name = '', + this.type, + this.createdAt, + this.updatedAt, + this.addIndex, + }); + + Tag copyWith({ + int? id, + int? uid, + String? name, + int? type, + int? createdAt, + int? updatedAt, + int? addIndex, + }) { + return Tag( + id: id ?? this.id, + uid: uid ?? this.uid, + name: name ?? this.name, + type: type ?? this.type, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + addIndex: addIndex ?? this.addIndex, + ); + } +} \ No newline at end of file diff --git a/apps/im_app/lib/domain/entities/user.dart b/apps/im_app/lib/domain/entities/user.dart index 509d0ed..0e15597 100644 --- a/apps/im_app/lib/domain/entities/user.dart +++ b/apps/im_app/lib/domain/entities/user.dart @@ -14,15 +14,81 @@ /// → View 渲染 /// ``` class User { - final String id; - final String email; + final int uid; + final String? uuid; + final int? lastOnline; + final String? profilePic; + final String? profilePicGaussian; final String? nickname; - final String? avatar; + final String? contact; + final String? countryCode; + final String? email; + final String? recoveryEmail; + final String? username; + final String? bio; + final int? relationship; + final String? userAlias; + final int? channelId; + final int? channelGroupId; + final String? hint; const User({ - required this.id, - required this.email, + required this.uid, + this.uuid, + this.lastOnline, + this.profilePic, + this.profilePicGaussian, this.nickname, - this.avatar, + this.contact, + this.countryCode, + this.email, + this.recoveryEmail, + this.username, + this.bio, + this.relationship, + this.userAlias, + this.channelId, + this.channelGroupId, + this.hint, }); -} + + User copyWith({ + int? uid, + String? uuid, + int? lastOnline, + String? profilePic, + String? profilePicGaussian, + String? nickname, + String? contact, + String? countryCode, + String? email, + String? recoveryEmail, + String? username, + String? bio, + int? relationship, + String? userAlias, + int? channelId, + int? channelGroupId, + String? hint, + }) { + return User( + uid: uid ?? this.uid, + uuid: uuid ?? this.uuid, + lastOnline: lastOnline ?? this.lastOnline, + profilePic: profilePic ?? this.profilePic, + profilePicGaussian: profilePicGaussian ?? this.profilePicGaussian, + nickname: nickname ?? this.nickname, + contact: contact ?? this.contact, + countryCode: countryCode ?? this.countryCode, + email: email ?? this.email, + recoveryEmail: recoveryEmail ?? this.recoveryEmail, + username: username ?? this.username, + bio: bio ?? this.bio, + relationship: relationship ?? this.relationship, + userAlias: userAlias ?? this.userAlias, + channelId: channelId ?? this.channelId, + channelGroupId: channelGroupId ?? this.channelGroupId, + hint: hint ?? this.hint, + ); + } +} \ No newline at end of file diff --git a/apps/im_app/lib/domain/entities/user_request_history.dart b/apps/im_app/lib/domain/entities/user_request_history.dart new file mode 100644 index 0000000..8d197bf --- /dev/null +++ b/apps/im_app/lib/domain/entities/user_request_history.dart @@ -0,0 +1,24 @@ +/// 用户请求历史 Domain 实体 +class UserRequestHistory { + final int id; + final int? status; + final int? createdAt; + + const UserRequestHistory({ + required this.id, + this.status, + this.createdAt, + }); + + UserRequestHistory copyWith({ + int? id, + int? status, + int? createdAt, + }) { + return UserRequestHistory( + id: id ?? this.id, + status: status ?? this.status, + createdAt: createdAt ?? this.createdAt, + ); + } +} \ No newline at end of file diff --git a/apps/im_app/lib/domain/entities/workspace.dart b/apps/im_app/lib/domain/entities/workspace.dart new file mode 100644 index 0000000..06d5aeb --- /dev/null +++ b/apps/im_app/lib/domain/entities/workspace.dart @@ -0,0 +1,64 @@ +/// 工作空间 Domain 实体 +class Workspace { + final int id; + final String? name; + final int? ownerId; + final String? description; + final String? logo; + final int? grade; + final int? cap; + final String? currency; + final int? status; + final int? createdAt; + final int? updatedAt; + final int? deletedAt; + final int? channelGroupId; + + const Workspace({ + required this.id, + this.name, + this.ownerId, + this.description, + this.logo, + this.grade, + this.cap, + this.currency, + this.status, + this.createdAt, + this.updatedAt, + this.deletedAt, + this.channelGroupId, + }); + + Workspace copyWith({ + int? id, + String? name, + int? ownerId, + String? description, + String? logo, + int? grade, + int? cap, + String? currency, + int? status, + int? createdAt, + int? updatedAt, + int? deletedAt, + int? channelGroupId, + }) { + return Workspace( + id: id ?? this.id, + name: name ?? this.name, + ownerId: ownerId ?? this.ownerId, + description: description ?? this.description, + logo: logo ?? this.logo, + grade: grade ?? this.grade, + cap: cap ?? this.cap, + currency: currency ?? this.currency, + status: status ?? this.status, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + deletedAt: deletedAt ?? this.deletedAt, + channelGroupId: channelGroupId ?? this.channelGroupId, + ); + } +} \ No newline at end of file diff --git a/apps/im_app/lib/features/chat/presentation/chat_db_test_view_model.dart b/apps/im_app/lib/features/chat/presentation/chat_db_test_view_model.dart index da6fa16..00df1da 100644 --- a/apps/im_app/lib/features/chat/presentation/chat_db_test_view_model.dart +++ b/apps/im_app/lib/features/chat/presentation/chat_db_test_view_model.dart @@ -1,7 +1,6 @@ import 'dart:math'; import 'package:drift/drift.dart'; -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:im_app/app/di/db_provider.dart'; import 'package:im_app/data/local/drift/app_database.dart'; @@ -87,12 +86,12 @@ class ChatDbTestViewModel extends _$ChatDbTestViewModel { final chunk = List.generate( chunkSize.clamp(0, count - i), (j) => UsersCompanion.insert( - uid: Value(i + j), + uid: i + j, nickname: Value('User ${i + j}'), ), ); - await db.batchInsertOrReplace(chunk); + await db.batchInsertOrReplace(chunk); completed += chunk.length; // 让出主线程 diff --git a/apps/im_app/lib/features/login/presentation/login_view_model.dart b/apps/im_app/lib/features/login/presentation/login_view_model.dart index 0c29082..e81cd20 100644 --- a/apps/im_app/lib/features/login/presentation/login_view_model.dart +++ b/apps/im_app/lib/features/login/presentation/login_view_model.dart @@ -1,4 +1,8 @@ -import 'package:flutter/foundation.dart'; +import 'dart:convert'; + +import 'package:flutter/services.dart'; +import 'package:im_app/data/models/user_dto.dart'; +import 'package:im_app/data/remote/login_request.dart'; import 'package:networks_sdk/networks_sdk.dart'; import 'package:im_app/app/di/db_provider.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; @@ -56,10 +60,23 @@ class LoginViewModel extends _$LoginViewModel { /// 正式 [login] 成功后同样需要调用 [AuthNotifier.login] 更新守卫状态。 Future demoLogin() async { final storageApi = ref.read(storageSdkProvider); - ///TODO: StorageSDKLifeCycle 需要只在主项目暴露 final storageLifeCycle = storageApi as StorageSdkLifecycle; - ref.read(authNotifierProvider).login(); - await storageLifeCycle.openDatabase(1234567); + final provider = ref.read(authNotifierProvider); + + // Read mock response from assets + final String raw = await rootBundle.loadString('assets/loginData.json'); + final Map json = jsonDecode(raw); + + // Parse into LoginData (nested under 'data' key) + final loginResponse = LoginResponse.fromJson(json); + final user = loginResponse.data.toEntity(); + + provider.login(); + // Open database for the user + await storageLifeCycle.openDatabase(user.uid); + ///TODO: User 和 DTO和数据库之间转换 + final userCompanion = UserDto.fromEntity(user).toCompanion(); + storageApi.insert(userCompanion); } /// 执行登录 diff --git a/apps/im_app/pubspec.yaml b/apps/im_app/pubspec.yaml index e02f3fb..404e3a3 100644 --- a/apps/im_app/pubspec.yaml +++ b/apps/im_app/pubspec.yaml @@ -62,3 +62,5 @@ dev_dependencies: flutter: uses-material-design: true + assets: + - assets/ diff --git a/packages/storage_sdk/lib/src/data/repositories/database_repository_impl.dart b/packages/storage_sdk/lib/src/data/repositories/database_repository_impl.dart index a7f1246..1bb80f0 100644 --- a/packages/storage_sdk/lib/src/data/repositories/database_repository_impl.dart +++ b/packages/storage_sdk/lib/src/data/repositories/database_repository_impl.dart @@ -18,19 +18,19 @@ class DatabaseRepositoryImpl implements DatabaseRepository { @override Future insertOrReplace( - TableInfo table, - Insertable companion, - ) async { + TableInfo table, + Insertable companion, + ) async { final db = _db; if (db == null) return; - await db.into(table).insertOnConflictUpdate(companion); + await db.into(table).insert(companion, mode: InsertMode.insertOrReplace); } @override Future insert( - TableInfo table, - Insertable companion, - ) async { + TableInfo table, + Insertable companion, + ) async { final db = _db; if (db == null) return; await db.into(table).insert(companion, mode: InsertMode.insertOrIgnore); @@ -38,13 +38,17 @@ class DatabaseRepositoryImpl implements DatabaseRepository { @override Future batchInsertOrReplace( - TableInfo table, - List> companions, - ) async { + TableInfo table, + List> companions, + ) async { final db = _db; if (db == null) return; await db.batch( - (batch) => batch.insertAllOnConflictUpdate(table, companions), + (batch) => batch.insertAll( + table, + companions, + mode: InsertMode.insertOrReplace, + ), ); } @@ -52,10 +56,10 @@ class DatabaseRepositoryImpl implements DatabaseRepository { @override Future updateWhere( - TableInfo table, - Insertable companion, - Expression Function(T) filter, - ) async { + TableInfo table, + Insertable companion, + Expression Function(T) filter, + ) async { final db = _db; if (db == null) return; await (db.update(table)..where(filter)).write(companion); @@ -65,9 +69,9 @@ class DatabaseRepositoryImpl implements DatabaseRepository { @override Future deleteWhere( - TableInfo table, - Expression Function(T) filter, - ) async { + TableInfo table, + Expression Function(T) filter, + ) async { final db = _db; if (db == null) return; await (db.delete(table)..where(filter)).go(); @@ -91,9 +95,9 @@ class DatabaseRepositoryImpl implements DatabaseRepository { @override Future> selectWhere( - TableInfo table, - Expression Function(T) filter, - ) async { + TableInfo table, + Expression Function(T) filter, + ) async { final db = _db; if (db == null) return []; return (db.select(table)..where(filter)).get(); @@ -101,9 +105,9 @@ class DatabaseRepositoryImpl implements DatabaseRepository { @override Future selectFirst( - TableInfo table, - Expression Function(T) filter, - ) async { + TableInfo table, + Expression Function(T) filter, + ) async { final db = _db; if (db == null) return null; return (db.select(table)..where(filter)..limit(1)).getSingleOrNull(); @@ -120,9 +124,9 @@ class DatabaseRepositoryImpl implements DatabaseRepository { @override Stream> watchWhere( - TableInfo table, - Expression Function(T) filter, - ) { + TableInfo table, + Expression Function(T) filter, + ) { final db = _db; if (db == null) return const Stream.empty(); return (db.select(table)..where(filter)).watch(); @@ -130,9 +134,9 @@ class DatabaseRepositoryImpl implements DatabaseRepository { @override Stream watchFirst( - TableInfo table, - Expression Function(T) filter, - ) { + TableInfo table, + Expression Function(T) filter, + ) { final db = _db; if (db == null) return const Stream.empty(); return (db.select(table)..where(filter)..limit(1)).watchSingleOrNull(); @@ -142,24 +146,24 @@ class DatabaseRepositoryImpl implements DatabaseRepository { @override Future> rawQuery( - String sql, [ - List args = const [], - ]) async { + String sql, [ + List args = const [], + ]) async { final db = _db; if (db == null) return []; return db .customSelect( - sql, - variables: args.map((e) => Variable(e)).toList(), - ) + sql, + variables: args.map((e) => Variable(e)).toList(), + ) .get(); } @override Future rawExecute( - String sql, [ - List args = const [], - ]) async { + String sql, [ + List args = const [], + ]) async { final db = _db; if (db == null) return; await db.customStatement(sql, args); @@ -169,9 +173,9 @@ class DatabaseRepositoryImpl implements DatabaseRepository { @override Future count( - TableInfo table, { - Expression Function(T)? filter, - }) async { + TableInfo table, { + Expression Function(T)? filter, + }) async { final db = _db; if (db == null) return 0; final countExpr = table.$columns.first.count(); @@ -180,4 +184,4 @@ class DatabaseRepositoryImpl implements DatabaseRepository { final row = await query.getSingle(); return row.read(countExpr) ?? 0; } -} +} \ No newline at end of file