Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions assets/flutter_i18n/en_US.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -636,6 +636,19 @@ library:
borrow_list_info: Borrowing {borrow} book(s), among which {dued} book(s) have expired
search_book_window: null
search_here: Search here
normal_search: Normal Search
advanced_search: Advanced Search
search: Search
match_mode: Match Mode
match_exact: Exact
match_fuzzy: Fuzzy
match_prefix: Prefix
document_type: Document Type
document_type_all: All
document_type_book: Book
only_on_shelf: Only on shelf
publish_year_begin: Publish year from
publish_year_end: Publish year to
book_detail: Book details
no_result: No result, change parameter or start your search
library_card:
Expand Down Expand Up @@ -803,6 +816,15 @@ setting:
color_setting: Color theme
simplify_timeline: Simplify schedule timeline
simplify_timeline_description: Reduce space occupation while no schedule
low_electricity_warning: Low electricity card color warning
low_electricity_warning_description:
Change the homepage electricity card color when remaining electricity is below
the threshold
low_electricity_threshold: Low electricity threshold
low_electricity_threshold_description: "Current: {threshold} kWh"
low_electricity_threshold_dialog:
title: Set low electricity threshold
input_hint: Input remaining electricity
account_setting: Account Settings
sport_password_setting: PE system password
experiment_password_setting: Physics experiment password
Expand Down
20 changes: 20 additions & 0 deletions assets/flutter_i18n/zh_CN.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,19 @@ library:
borrow_list_info: 在借 {borrow} 本,其中已过期 {dued} 本
search_book_window: null
search_here: 在此搜索
normal_search: 普通搜索
advanced_search: 高级搜索
search: 搜索
match_mode: 匹配方式
match_exact: 精确匹配
match_fuzzy: 模糊匹配
match_prefix: 前方一致
document_type: 文献类型
document_type_all: 全部
document_type_book: 图书
only_on_shelf: 仅看在架
publish_year_begin: 出版年起
publish_year_end: 出版年止
book_detail: 书籍详细信息
no_result: 没有结果,请修改搜索参数或者开始你的搜索
library_card:
Expand Down Expand Up @@ -726,6 +739,13 @@ setting:
color_setting: 颜色设置
simplify_timeline: 简化日程时间轴
simplify_timeline_description: 没有日程时 减少空间占用
low_electricity_warning: 低电量卡片变色提醒
low_electricity_warning_description: 电量小于阈值时 电量卡片变色提醒
low_electricity_threshold: 低电量阈值
low_electricity_threshold_description: 当前为 {threshold} 度
low_electricity_threshold_dialog:
title: 设置低电量阈值
input_hint: 请输入电量度数
account_setting: 账号设置
sport_password_setting: 体育系统密码设置
experiment_password_setting: 物理实验系统密码设置
Expand Down
20 changes: 20 additions & 0 deletions assets/flutter_i18n/zh_TW.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,19 @@ library:
borrow_list_info: 在借 {borrow} 本,其中已過期 {dued} 本
search_book_window: null
search_here: 在此搜索
normal_search: 普通搜索
advanced_search: 高級搜索
search: 搜索
match_mode: 匹配方式
match_exact: 精確匹配
match_fuzzy: 模糊匹配
match_prefix: 前方一致
document_type: 文獻類型
document_type_all: 全部
document_type_book: 圖書
only_on_shelf: 僅看在架
publish_year_begin: 出版年起
publish_year_end: 出版年止
book_detail: 書籍詳細信息
no_result: 沒有結果,請修改搜索參數或者開始你的搜索
library_card:
Expand Down Expand Up @@ -724,6 +737,13 @@ setting:
color_setting: 顏色設置
simplify_timeline: 簡化日程時間軸
simplify_timeline_description: 沒有日程時 減少空間佔用
low_electricity_warning: 低電量卡片變色提醒
low_electricity_warning_description: 電量小於閾值時 電量卡片變色提醒
low_electricity_threshold: 低電量閾值
low_electricity_threshold_description: 目前為 {threshold} 度
low_electricity_threshold_dialog:
title: 設置低電量閾值
input_hint: 請輸入電量度數
account_setting: 賬號設置
sport_password_setting: 體育系統密碼設置
experiment_password_setting: 物理實驗系統密碼設置
Expand Down
160 changes: 159 additions & 1 deletion lib/model/xidian_ids/library.dart
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,60 @@ class BorrowData {
factory BorrowData.fromJson(Map<String, dynamic> json) =>
_$BorrowDataFromJson(json);

factory BorrowData.fromOpacJson(Map<String, dynamic> json) {

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

不知道我理解的对不对,这里不应该通过写一个新的 factory 解决,而是彻底地修改数据结构,然后跑 https://pub.dev/packages/json_serializable 来解决。

final normReturnDate = _stringValue(json['normReturnDate']);
final dueDate = _parseLibraryDate(normReturnDate);
final today = DateTime.now();
final todayDate = DateTime(today.year, today.month, today.day);

return BorrowData(
lendDay: dueDate.difference(todayDate).inDays,
locationId: _intValue(json['locationId']),
loanId: _intValue(json['loanId']),
renewTimes: _intValue(json['renewTimes']),
recallTimes: _intValue(json['recallTimes']),
loanDate: _stringValue(json['loanDate']),
renewDate: _nullableStringValue(json['renewDate']),
normReturnDate: normReturnDate,
returnDate: _nullableStringValue(json['returnDate']),
loanType: _stringValue(json['loanType']),
locationName: _stringValue(json['locationName']),
itemLibCode: _stringValue(json['curLibCode'] ?? json['itemLibCode']),
itemLibName: _stringValue(json['curLibName'] ?? json['itemLibName']),
loanDeskName: _stringValue(json['loanDeskName']),
title: _stringValue(json['title']),
author: _stringValue(json['author']),
publisher: _stringValue(json['publisher']),
isbn: _stringValue(json['isbn']),
isbn10: _stringValue(json['isbn10']),
isbn13: _stringValue(json['isbn13']),
publishYear: _stringValue(json['publishYear']),
titles: _nullableStringValue(json['titles']),
barcode: _stringValue(json['barcode'] ?? json['propNo']),
);
}

Map<String, dynamic> toJson() => _$BorrowDataToJson(this);
}

int _intValue(Object? value) {
if (value is int) return value;
if (value is num) return value.toInt();
if (value is String) return int.tryParse(value) ?? 0;
return 0;
}

String _stringValue(Object? value) => value?.toString() ?? "";

String? _nullableStringValue(Object? value) => value?.toString();

DateTime _parseLibraryDate(String value) {
if (value.isEmpty) {
return DateTime.now();
}
return DateTime.parse(value.replaceAll('/', '-').split(' ').first);
}

@JsonSerializable()
class BookInfo {
final String? author;
Expand All @@ -92,6 +143,8 @@ class BookInfo {
final List<String?>? barCodes;
final List<String>? searchCode;
final List<BookLocation>? items;
final int? availableCount;
final int? storageCount;
String? imageUrl;

BookInfo({
Expand All @@ -112,15 +165,48 @@ class BookInfo {
this.searchCode,
required this.barCodes,
this.items,
this.availableCount,
this.storageCount,
this.imageUrl,
});

factory BookInfo.fromJson(Map<String, dynamic> json) =>
_$BookInfoFromJson(json);

factory BookInfo.fromOpacJson(Map<String, dynamic> json) {
final callNos = _stringList(json['callNo']);
final barCodes = _nullableStringList(
json['barCodes'] ?? json['barcode'] ?? json['propNo'],
);
return BookInfo(
author: _nullableStringValue(json['author']),
subject: _nullableStringValue(json['subjectWord']),
isbn: _nullableStringValue(json['isbn']),
description: _nullableStringValue(json['adstract'] ?? json['ddAbstract']),
bookName: _stringValue(json['title']),
barCode: _nullableStringValue(json['barcode'] ?? json['propNo']),
docNumber: _intValue(json['recordId']),
publishYear: _nullableStringValue(json['publishYear'] ?? json['year']),
publisherHouse: _nullableStringValue(json['publisher']),
groupCode: _nullableStringValue(json['groupCode']),
callNos: callNos,
searchCode: callNos,
barCodes: barCodes,
availableCount: _nullableIntValue(
json['onShelfCountI'] ?? json['canBrrowCountI'] ?? json['onShelfNum'],
),
storageCount: _nullableIntValue(
json['groupPhysicalCount'] ?? json['physicalCount'],
),
);
}

Map<String, dynamic> toJson() => _$BookInfoToJson(this);

int? get canBeBorrowed {
if (availableCount != null) {
return availableCount;
}
if (items == null) {
return null;
}
Expand All @@ -131,6 +217,20 @@ class BookInfo {
return toReturn;
}

int? get totalStorage {
if (storageCount != null) {
return storageCount;
}
return items?.length;
}

bool get hasBarCodes {
if (barCodes == null || barCodes!.isEmpty) {
return false;
}
return barCodes!.any((e) => e != null && e.isNotEmpty);
}

String get searchCodeStr {
if (searchCode == null || searchCode!.isEmpty) {
return "未提供";
Expand All @@ -142,8 +242,39 @@ class BookInfo {
if (barCodes == null || barCodes!.isEmpty) {
return "未提供";
}
return barCodes!.first ?? "未提供";
for (final code in barCodes!) {
if (code != null && code.isNotEmpty) {
return code;
}
}
return "未提供";
}
}

int? _nullableIntValue(Object? value) {
if (value == null) return null;
if (value is int) return value;
if (value is num) return value.toInt();
if (value is String) return int.tryParse(value);
return null;
}

List<String>? _stringList(Object? value) {
if (value == null) return null;
if (value is List) {
return value.map((e) => e.toString()).where((e) => e.isNotEmpty).toList();
}
final text = value.toString();
return text.isEmpty ? null : [text];
}

List<String?>? _nullableStringList(Object? value) {
if (value == null) return null;
if (value is List) {
return value.map((e) => e?.toString()).toList();
}
final text = value.toString();
return text.isEmpty ? null : [text];
}

@JsonSerializable()
Expand Down Expand Up @@ -183,6 +314,33 @@ class BookLocation {
factory BookLocation.fromJson(Map<String, dynamic> json) =>
_$BookLocationFromJson(json);

factory BookLocation.fromOpacJson(Map<String, dynamic> json) {
final locationName = _stringValue(
json['realLocationName'] ?? json['locationName'],
);
final shelfName = _stringValue(json['urlName']);
final displayLocation = shelfName.isEmpty
? locationName
: "$locationName $shelfName";

return BookLocation(
yearVol: _nullableStringValue(json['vol'] ?? json['yearVol']),
locationName: displayLocation.isEmpty ? null : displayLocation,
searchCode: _stringValue(json['callNo']),
campus: _nullableStringValue(json['campus']),
inDate: _nullableStringValue(json['inDate']),
barCode: _nullableStringValue(json['barcode'] ?? json['propNo']),
itemId: _intValue(json['itemId']),
circAttr: _stringValue(json['circAttr']),
locationId: _nullableStringValue(json['locationId']),
processType: _stringValue(json['processType']),
curLocationId: _stringValue(json['curLocationId']),
propNo: _nullableStringValue(json['propNo']),
borrowStatus: _nullableStringValue(json['borrowStatus']),
noBorrowMessages: _nullableStringValue(json['noBorrowMessages']),
);
}

Map<String, dynamic> toJson() => _$BookLocationToJson(this);
}

Expand Down
4 changes: 4 additions & 0 deletions lib/model/xidian_ids/library.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 13 additions & 2 deletions lib/page/homepage/home_card_padding.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import 'package:flutter/material.dart';
import 'package:styled_widget/styled_widget.dart';

enum HomeCardType { plain, filled }
enum HomeCardType { plain, filled, warning }

extension HomeCardPadding on Widget {
Widget withHomeCardStyle(
Expand All @@ -27,20 +27,29 @@ extension HomeCardPadding on Widget {
iconSize: WidgetStateProperty.all(20),
backgroundColor: WidgetStateProperty.resolveWith((states) {
final colorScheme = Theme.of(context).colorScheme;
if (type == HomeCardType.warning) {
return colorScheme.errorContainer;
}
if (type == HomeCardType.filled) {
return colorScheme.surfaceContainerHigh;
}
return colorScheme.surfaceContainerLow;
}),
foregroundColor: WidgetStateProperty.resolveWith((states) {
final colorScheme = Theme.of(context).colorScheme;
if (type == HomeCardType.warning) {
return colorScheme.onErrorContainer;
}
if (type == HomeCardType.filled) {
return colorScheme.onSurfaceVariant;
}
return colorScheme.onSurfaceVariant;
}),
side: WidgetStateProperty.resolveWith((states) {
final colorScheme = Theme.of(context).colorScheme;
if (type == HomeCardType.warning) {
return BorderSide(color: colorScheme.error);
}
if (type == HomeCardType.filled) {
return BorderSide.none;
}
Expand All @@ -56,7 +65,9 @@ extension HomeCardPadding on Widget {
onPressed: onPressed,
child: DefaultTextStyle(
style: TextStyle(
color: Theme.of(context).brightness == Brightness.dark
color: type == HomeCardType.warning
? Theme.of(context).colorScheme.onErrorContainer
: Theme.of(context).brightness == Brightness.dark
? Theme.of(context).colorScheme.onSurface
: Theme.of(context).colorScheme.onSurfaceVariant,
),
Expand Down
Loading