Epub
筆摘記同步方案
- 上報筆記摘記數(shù)據(jù)
上報接口均為:API_addNote稚机,后臺以 note_type 字段值作為區(qū)分通今,具體參數(shù)如下:
NSMutableDictionary *params = @{
@"note_type": type, //0--筆記漂坏;1--摘記
@"app_type": @"iOS",
@"take_note": markModel.markContent, // 原文內(nèi)容
@"notes": markModel.markInfo, // 用戶筆記內(nèi)容,摘記時為空
@"book_id": markModel.bookId,
@"ios_location_note": jsonString, // 定位數(shù)據(jù)
}.mutableCopy;
///
/// 上報成功處理提示:
if ([type isEqualToNumber:@1]) {
[ToastTool showTipMessageInWindow:@"可到‘我的筆記’查看"];
} else {
[ToastTool showTipMessageInWindow:@"可到‘我的摘記本’查看"];
}
- 獲取筆記摘記數(shù)據(jù)
獲取接口為:
筆記 - API_getNoteByBookId
摘記 - API_getNoteByBookId
/** 模型
@property (nonatomic, copy) NSString *iosLocationNote; // iOS定位數(shù)據(jù)
@property (nonatomic, copy) NSString *webLocationNote; // Android定位數(shù)據(jù)
@property (nonatomic, copy) NSString *takeNote; // Web定位數(shù)據(jù)
*/
/** 某條筆/摘記解析后的數(shù)據(jù)模型示例:
<MyNoteModel>
[takeNote]: 她驚異地搖了搖頭:“沒有。你怎么會想到他要給我包裹?”
[id]: 4625f96c6f0b4e45b48e5579e6bd1a03
[notes]: ?shide
[webLocationNote]: <nil>
[locationNote]: <nil>
[chapterTitle]: <nil>
[iosLocationNote]: {"playOrder":5,"CharIndex":0,"ParagraphIndex":1007,"Element...
[createTime]: 2020-07-14 08:50:37
[isOpening]: 0
</MyNoteModel>
*/
/** iosLocationNote 定位數(shù)據(jù)
{
"playOrder":5,
"CharIndex":0,
"ParagraphIndex":1007,
"ElementIndex":0,
"timeStamp":1594687821.30233,
"indexEnd":2115,
"chapterId":"8232126329250033",
"startOffset":0,
"markContent":"她驚異地搖了搖頭:“沒有漠酿。你怎么會想到他要給我包裹?”",
"markInfo":"?shide",
"markType":0,
"endText":"她驚異地搖了搖頭:“沒有谎亩。你怎么會想到他要給我包裹炒嘲?”",
"contentPathId":"id122",
"markId":"6612626366525154",
"paragraph":1007,
"startText":"她驚異地搖了搖頭:“沒有。你怎么會想到他要給我包裹匈庭?”",
"Uid":"6612626366525154",
"bookId":"18d109dbf6ff4c3fb5e3f54d150615df",
"myEnd":{
"ParagraphIndex":1007,
"CharIndex":1,
"ElementIndex":27
},
"endOffset":26,
"indexStart":2089
}
*/
其中用于同步的字段為:
/*三端筆記摘記數(shù)據(jù)同步/
@property (nonatomic, copy) NSString *contentPathId; //筆記所在章節(jié)的文件ID夫凸,解析書籍內(nèi)opf文件可知'id'
@property (nonatomic, copy) NSString *startText; //筆記起始段落內(nèi)容
@property (nonatomic, copy) NSString *endText; //筆記結(jié)束段落內(nèi)容
@property (nonatomic, assign) NSInteger startOffset; //筆記結(jié)束位置本段落內(nèi)偏移量
@property (nonatomic, assign) NSInteger endOffset; //筆記結(jié)束位置本段落內(nèi)偏移量
方案描述:
三端(iOS、Android阱持、Web)均上報以上字段值夭拌,解析不同端的數(shù)據(jù)時以此為準(zhǔn)!
具體描述:
epub書籍文件是一個大的壓縮包衷咽,里面包含著若干描述書籍信息和內(nèi)容的文件鸽扁,閱讀時會先將其解壓縮后放置一個文件夾內(nèi),然后再對這些文件做解析處理兵罢。通常献烦,epub書籍內(nèi)容是由N個文件的內(nèi)容組合而成滓窍,一個文件里存放著一個章節(jié)的內(nèi)容卖词;然而,也有少部分epub書籍的內(nèi)容只有一個內(nèi)容文件吏夯,這個僅有的文件里存放著N個章節(jié)此蜈。但是無論那種情況,這些章節(jié)文件都有對應(yīng)的ID(即上報的字段contentPathId)噪生,它們的對應(yīng)關(guān)系在++content.opf++文件里可以看到裆赵。
由于Android、iOS兩端所采用對epub的底層解析庫的不同跺嗽,使得兩端對各自數(shù)據(jù)的定位方式不一樣(Android解析后的內(nèi)容數(shù)據(jù)都是基于段落的位置战授,其段落的規(guī)則較復(fù)雜,iOS無法與其準(zhǔn)確對應(yīng))桨嫁,經(jīng)過多次調(diào)試驗證植兰,最終決定++采用章節(jié)內(nèi)內(nèi)容匹配的方式來定位數(shù)據(jù),然后轉(zhuǎn)換成各自需要的數(shù)據(jù)進行處理++璃吧。
++為減少誤差楣导,先進行開始段落和結(jié)束段落的位置匹配,然后再根據(jù)段落內(nèi)的偏移量確定具體內(nèi)容++畜挨。
例如:iOS數(shù)據(jù)定位是根據(jù)章節(jié)內(nèi)容的偏移量來定位筒繁,當(dāng)獲取到Android或Web的數(shù)據(jù)后噩凹,將他端原始數(shù)據(jù)經(jīng)過方法處理后轉(zhuǎn)成自己需要的章節(jié)序列號及偏移量,再進行后續(xù)操作即可毡咏。
**數(shù)據(jù)轉(zhuǎn)換**
- (EpubMarkModel *)epubMarkModelConversion:(id)object {
if ([object isKindOfClass:[EpubMarkModelForAndroid class]]) {
//安卓筆摘記
/**********數(shù)據(jù)處理***********/
return iOSModel;
} else {
//Web筆摘記
/**********數(shù)據(jù)處理***********/
return iOSModel;
}
}
進度同步:
章節(jié)contentPathId驮宴、基于章節(jié)內(nèi)容的偏移量currentIndex
Txt
txt書籍內(nèi)容結(jié)構(gòu)簡單,僅有單獨一個txt文件血当,直接加載內(nèi)容幻赚。
筆摘記同步方案:
上報筆記摘記劃線內(nèi)容的起始位置、結(jié)束位置臊旭,這個是相對于整本書的內(nèi)容的落恼。
@property (nonatomic, assign) NSInteger indexStart; //想法起始位置
@property (nonatomic, assign) NSInteger indexEnd; //想法結(jié)束位置
進度同步:
章節(jié)contentPathId、基于章節(jié)內(nèi)容的偏移量currentIndex
同步方案:
// 無筆記摘記
進度同步:頁碼 page