mirror of
https://github.com/KingHWJ/WeReadBoard.git
synced 2026-11-03 18:24:58 +08:00
126 lines
3.7 KiB
JavaScript
126 lines
3.7 KiB
JavaScript
/* ==========================================================================
|
||
阅间 · 数据层(v2)
|
||
--------------------------------------------------------------------------
|
||
把后端 /api/v2/* 接口封装成前端可直接使用的数据结构。
|
||
设计稿(Design Demo)原本使用 demo-data.js 里的静态示例数据,
|
||
这里替换为真实接口调用,字段名与设计稿保持一致。
|
||
========================================================================== */
|
||
(function (global) {
|
||
'use strict';
|
||
|
||
const BASE = '/api/v2';
|
||
|
||
async function request(path, params) {
|
||
const url = new URL(BASE + path, global.location.origin);
|
||
Object.entries(params || {}).forEach(([key, value]) => {
|
||
if (value !== undefined && value !== null && value !== '') url.searchParams.set(key, value);
|
||
});
|
||
const response = await fetch(url.toString(), { headers: { Accept: 'application/json' } });
|
||
let payload = null;
|
||
try {
|
||
payload = await response.json();
|
||
} catch (error) {
|
||
payload = null;
|
||
}
|
||
if (!response.ok) {
|
||
const message = (payload && (payload.error || payload.detail)) || `请求失败(${response.status})`;
|
||
const err = new Error(message);
|
||
err.status = response.status;
|
||
err.payload = payload;
|
||
throw err;
|
||
}
|
||
return payload;
|
||
}
|
||
|
||
/* ------------------------------ 工具函数 ------------------------------ */
|
||
|
||
function durationText(seconds) {
|
||
const total = Math.max(0, Math.round(Number(seconds) || 0));
|
||
const hours = Math.floor(total / 3600);
|
||
const minutes = Math.round((total % 3600) / 60);
|
||
return hours ? `${hours}小时${minutes}分钟` : `${minutes}分钟`;
|
||
}
|
||
|
||
function percentText(value) {
|
||
const num = Number(value) || 0;
|
||
return `${num}%`;
|
||
}
|
||
|
||
/* ------------------------------ 接口封装 ------------------------------ */
|
||
|
||
const WeApi = {
|
||
durationText,
|
||
percentText,
|
||
|
||
status() {
|
||
return request('/status');
|
||
},
|
||
|
||
/**
|
||
* 书架数据
|
||
* @param {string} tab all|reading|done|wish
|
||
* @param {{keyword?:string, limit?:number, offset?:number, progress?:boolean}} options
|
||
*/
|
||
shelf(tab, options) {
|
||
const opts = options || {};
|
||
return request('/shelf', {
|
||
tab: tab || 'all',
|
||
keyword: opts.keyword || '',
|
||
limit: opts.limit,
|
||
offset: opts.offset,
|
||
progress: opts.progress ? 1 : 0,
|
||
});
|
||
},
|
||
|
||
dashboard(period) {
|
||
return request('/dashboard', { period: period || 'week' });
|
||
},
|
||
|
||
notebooks() {
|
||
return request('/notebooks');
|
||
},
|
||
|
||
/** bookId 传 'all' 时聚合笔记最多的前 limit 本 */
|
||
notes(bookId, limit) {
|
||
return request('/notes', { book_id: bookId, limit: limit });
|
||
},
|
||
|
||
book(bookId) {
|
||
return request('/book/' + encodeURIComponent(bookId));
|
||
},
|
||
|
||
reviews(bookId, type, count) {
|
||
return request(`/book/${encodeURIComponent(bookId)}/reviews`, { type: type || 0, count: count || 10 });
|
||
},
|
||
|
||
highlights(bookId, chapterUid) {
|
||
return request(`/book/${encodeURIComponent(bookId)}/highlights`, { chapter_uid: chapterUid || 0 });
|
||
},
|
||
|
||
underlineThoughts(bookId, chapterUid, range) {
|
||
return request(`/book/${encodeURIComponent(bookId)}/underline-thoughts`, {
|
||
chapter_uid: chapterUid,
|
||
range: range,
|
||
});
|
||
},
|
||
|
||
thought(reviewId) {
|
||
return request('/thought/' + encodeURIComponent(reviewId));
|
||
},
|
||
|
||
archives() {
|
||
return request('/archives');
|
||
},
|
||
|
||
recommend(maxIdx, refresh = false) {
|
||
return request('/recommend', { maxIdx: maxIdx || 0, refresh: refresh ? 1 : 0 });
|
||
},
|
||
|
||
search(keyword, scope) {
|
||
return request('/search', { keyword: keyword, scope: scope || 'books' });
|
||
},
|
||
};
|
||
|
||
global.WeApi = WeApi;
|
||
})(window);
|