您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
无需登录(不可用),快速选择书籍加入书架,复制导出书籍信息
// ==UserScript== // @name 豆瓣读书书架 // @name:zh 豆瓣读书书架 // @namespace https://github.com/ilyydy/tampermonkey-script // @version 0.0.4 // @author ilyydy // @description 无需登录(不可用),快速选择书籍加入书架,复制导出书籍信息 // @description:zh 无需登录(不可用),快速选择书籍加入书架,复制导出书籍信息 // @description:zh-CN 无需登录(不可用),快速选择书籍加入书架,复制导出书籍信息 // @license MIT // @icon data:image/x-icon;base64,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AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP+RwIn////////////4+/j/GnwK/xF3AP8RdwD/EXcA/xF3AP8afAr/+Pv4////////////kcCJ/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/9Xn0v///////////77auf8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP++2rn////////////V59L/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8rhhz/////////////////erNw/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/3qzcP////////////////8rhhz/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/26sZP////////////////81jCf/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/NYwn/////////////////26sZP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/vdm4////////////5PDi/y+IIP8viCD/L4gg/y+IIP8viCD/L4gg/y+IIP8viCD/5PDi////////////vdm4/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/0+bQ/////////////////////////////////////////////////////////////////////////////////////////////////9Pm0P8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP/T5tD/////////////////////////////////////////////////////////////////////////////////////////////////0+bQ/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/9Pm0P///////////9vq2P+Iu4D/iLuA/4i7gP+Iu4D/iLuA/4i7gP+Iu4D/iLuA/4i7gP+Iu4D/iLuA/4i7gP/b6tj////////////T5tD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/0+bQ////////////tdWw/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/7XVsP///////////9Pm0P8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP/T5tD///////////+11bD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/tdWw////////////0+bQ/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/9Pm0P///////////7XVsP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP+11bD////////////T5tD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/0+bQ////////////tdWw/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/7XVsP///////////9Pm0P8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP/T5tD////////////b6tj/iLuA/4i7gP+Iu4D/iLuA/4i7gP+Iu4D/iLuA/4i7gP+Iu4D/iLuA/4i7gP+Iu4D/2+rY////////////0+bQ/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/9Pm0P/////////////////////////////////////////////////////////////////////////////////////////////////T5tD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/0+bQ/////////////////////////////////////////////////////////////////////////////////////////////////9Pm0P8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/+Lu4P//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////4u7g/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/4u7g///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////i7uD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP/i7uD//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////+Lu4P8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AOYRdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwDmEXcASRF3AOYRdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA/xF3AP8RdwD/EXcA5hF3AEkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== // @supportURL https://github.com/ilyydy/tampermonkey-script/issues // @match http*://*book.douban.com/* // @match http*://search.douban.com/book/* // @require https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.global.prod.js // @require data:application/javascript,window.Vue%3DVue%3B // @require https://cdn.jsdelivr.net/npm/[email protected]/dist/index.full.min.js // @require https://cdn.jsdelivr.net/npm/[email protected]/dist/xlsx.full.min.js // @require https://cdn.jsdelivr.net/npm/[email protected]/dist/iife/sync.js // @resource element-plus/dist/index.css https://cdn.jsdelivr.net/npm/[email protected]/dist/index.css // @connect book.douban.com // @grant GM_getResourceText // @grant GM_getValue // @grant GM_setClipboard // @grant GM_setValue // @grant GM_xmlhttpRequest // ==/UserScript== (t=>{const e=document.createElement("style");e.dataset.source="vite-plugin-monkey",e.innerText=t,document.head.appendChild(e)})(".book-field[data-v-5f2bdcc9]{margin-bottom:5px}.item[data-v-bdb4b0de]{display:grid;grid-template-columns:80% 20%}.item-button[data-v-bdb4b0de]{display:grid}.affix[data-v-ed4eeb8f]{position:fixed;bottom:50px;right:50px}.book-list-container[data-v-ed4eeb8f]{margin:auto 20px}.book-list-container-header[data-v-ed4eeb8f]{margin-bottom:20px}.book-list-container-header-select[data-v-ed4eeb8f]{margin-left:10px;width:140px}.book-list-container-header-item[data-v-ed4eeb8f]{margin-left:10px}.book-list-container-empty p[data-v-ed4eeb8f]{font-size:18px;text-align:center}.book-list-container-book-item[data-v-ed4eeb8f]{margin-bottom:20px}"); (function(vue, elementPlus, sync, XLSX2) { "use strict"; function _interopNamespaceDefault(e) { const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } }); if (e) { for (const k in e) { if (k !== "default") { const d = Object.getOwnPropertyDescriptor(e, k); Object.defineProperty(n, k, d.get ? d : { enumerable: true, get: () => e[k] }); } } } n.default = e; return Object.freeze(n); } const XLSX__namespace = /* @__PURE__ */ _interopNamespaceDefault(XLSX2); const cssLoader = (e) => { const t = GM_getResourceText(e), o = document.createElement("style"); return o.innerText = t, document.head.append(o), t; }; cssLoader("element-plus/dist/index.css"); /*! Element Plus Icons Vue v2.0.10 */ var export_helper_default = (sfc, props) => { let target = sfc.__vccOpts || sfc; for (let [key, val] of props) target[key] = val; return target; }; var arrow_down_vue_vue_type_script_lang_default = { name: "ArrowDown" }; var _hoisted_16 = { viewBox: "0 0 1024 1024", xmlns: "http://www.w3.org/2000/svg" }, _hoisted_26 = /* @__PURE__ */ vue.createElementVNode("path", { fill: "currentColor", d: "M831.872 340.864 512 652.672 192.128 340.864a30.592 30.592 0 0 0-42.752 0 29.12 29.12 0 0 0 0 41.6L489.664 714.24a32 32 0 0 0 44.672 0l340.288-331.712a29.12 29.12 0 0 0 0-41.728 30.592 30.592 0 0 0-42.752 0z" }, null, -1), _hoisted_36 = [ _hoisted_26 ]; function _sfc_render6(_ctx, _cache, $props, $setup, $data, $options) { return vue.openBlock(), vue.createElementBlock("svg", _hoisted_16, _hoisted_36); } var arrow_down_default = /* @__PURE__ */ export_helper_default(arrow_down_vue_vue_type_script_lang_default, [["render", _sfc_render6], ["__file", "arrow-down.vue"]]); var arrow_left_vue_vue_type_script_lang_default = { name: "ArrowLeft" }; var _hoisted_18 = { viewBox: "0 0 1024 1024", xmlns: "http://www.w3.org/2000/svg" }, _hoisted_28 = /* @__PURE__ */ vue.createElementVNode("path", { fill: "currentColor", d: "M609.408 149.376 277.76 489.6a32 32 0 0 0 0 44.672l331.648 340.352a29.12 29.12 0 0 0 41.728 0 30.592 30.592 0 0 0 0-42.752L339.264 511.936l311.872-319.872a30.592 30.592 0 0 0 0-42.688 29.12 29.12 0 0 0-41.728 0z" }, null, -1), _hoisted_38 = [ _hoisted_28 ]; function _sfc_render8(_ctx, _cache, $props, $setup, $data, $options) { return vue.openBlock(), vue.createElementBlock("svg", _hoisted_18, _hoisted_38); } var arrow_left_default = /* @__PURE__ */ export_helper_default(arrow_left_vue_vue_type_script_lang_default, [["render", _sfc_render8], ["__file", "arrow-left.vue"]]); var monkeyWindow = window; var GM_setValue = /* @__PURE__ */ (() => monkeyWindow.GM_setValue)(); var GM_xmlhttpRequest = /* @__PURE__ */ (() => monkeyWindow.GM_xmlhttpRequest)(); var GM_setClipboard = /* @__PURE__ */ (() => monkeyWindow.GM_setClipboard)(); var GM_getValue = /* @__PURE__ */ (() => monkeyWindow.GM_getValue)(); const BOOK_SHELF_KEY = "tampermonkey_douban_books"; let books; function useStore$1(force = false) { if (!books || force) { { books = vue.reactive(JSON.parse(GM_getValue(BOOK_SHELF_KEY, "[]"))); vue.watch(books, (newValue) => { GM_setValue(BOOK_SHELF_KEY, JSON.stringify(newValue)); }); } } return books; } function getBookIdx(id) { return books.findIndex((i) => i.id === id); } function getBook$1(id) { return books.find((i) => i.id === id); } function hasBook(id) { return getBookIdx(id) !== -1; } function addBook(book) { if (!hasBook(book.id)) { books.push({ ...book, addTime: Date.now() }); return { success: true, msg: "" }; } else { return { success: false, msg: `《${book.title}》 已在书架中` }; } } function removeBook(id) { const idx = getBookIdx(id); if (idx === -1) return false; books.splice(idx, 1); return true; } function clearBook() { books.splice(0, books.length); } const booksStore = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({ __proto__: null, BOOK_SHELF_KEY, addBook, get books() { return books; }, clearBook, getBook: getBook$1, getBookIdx, hasBook, removeBook, useStore: useStore$1 }, Symbol.toStringTag, { value: "Module" })); function useStore(force = false) { useStore$1(force); return { booksStore }; } function success(msg) { return elementPlus.ElMessage.success({ message: msg, showClose: true, grouping: true }); } function warning(msg) { console.warn(msg); return elementPlus.ElMessage.warning({ message: msg, showClose: true, grouping: true }); } function error(msg) { console.error(msg); return elementPlus.ElMessage.error({ message: msg, showClose: true, grouping: true }); } function exportCsv(rows, filename, options) { const v = sync.stringify(rows, options); { const link = document.createElement("a"); link.download = filename; const blob = new Blob([v], { type: "text/csv;charset=utf-8;" }); link.href = URL.createObjectURL(blob); link.click(); URL.revokeObjectURL(link.href); } } function exportXlsx(rows, filename, aoa2SheetOpts, writingOptions) { const worksheet = XLSX__namespace.utils.aoa_to_sheet(rows, aoa2SheetOpts); const workbook = XLSX__namespace.utils.book_new(); XLSX__namespace.utils.book_append_sheet(workbook, worksheet); XLSX__namespace.writeFile(workbook, filename, writingOptions); } const BOOK_FIELD_MAP = { id: "id", title: "书名", subTitle: "副标题", originName: "原作名", authors: "作者", translators: "译者", publishingHouse: "出版社", publishingTime: "出版时间", seriesName: "丛书", page: "页数", ISBN: "ISBN", score: "评分", scorePeopleCount: "评分人数", coverUrl: "封面图链接", doubanUrl: "豆瓣链接", contentBrief: "内容简介" }; const defaultBookFields = Object.keys(BOOK_FIELD_MAP); const excelFormatterMap = defaultBookFields.reduce((pre, field) => { switch (field) { case "authors": case "translators": pre[field] = (book) => book[field].join(", "); break; default: pre[field] = (book) => book[field]; break; } return pre; }, {}); const specialBookItemFormatters = [ { key: "id", label: BOOK_FIELD_MAP.id, type: "link", getLink: (book) => book.doubanUrl }, { key: "doubanUrl", label: BOOK_FIELD_MAP.doubanUrl, type: "link", getLink: (book) => book.doubanUrl }, { key: "coverUrl", label: BOOK_FIELD_MAP.coverUrl, type: "link", getLink: (book) => book.coverUrl }, { key: "authors", label: BOOK_FIELD_MAP.authors, type: "string", getText: (book) => book.authors.join(", ") }, { key: "translators", label: BOOK_FIELD_MAP.translators, type: "string", getText: (book) => book.translators.join(", ") }, { key: "contentBrief", label: BOOK_FIELD_MAP.contentBrief, type: "string", getText: (book) => book.contentBrief, styleObj: { "line-height": "30px", "white-space": "pre-line", "max-height": "300px", "padding-right": "20px", width: "98%", display: "inline-block", overflow: "auto" } } ]; const bookItemFormatters = defaultBookFields.map((field) => { const v = specialBookItemFormatters.find((i) => i.key === field); if (v) return v; return { key: field, label: BOOK_FIELD_MAP[field], type: "string", getText: (book) => book[field] }; }); function getBookViewText(book, fields = defaultBookFields) { const textList = []; fields.forEach((i) => { const v = book[i]; if (Array.isArray(v)) { if (v.length > 0) textList.push(`${BOOK_FIELD_MAP[i]}: ${v.join(", ")}`); } else if (v) { textList.push(`${BOOK_FIELD_MAP[i]}: ${v}`); } }); return textList.join("\n"); } async function copyBook(book, fields = defaultBookFields) { const text = getBookViewText(book, fields); GM_setClipboard(text, "text"); } async function copyBookWithTip(book, fields = defaultBookFields) { try { await copyBook(book); success("复制成功"); } catch (err) { error(err.msg); } } const exportCsvName = "豆瓣书籍导出.csv"; function exportBookCsv(books2, filename = exportCsvName, options = { bom: true }) { const header = defaultBookFields.map((field) => BOOK_FIELD_MAP[field]); const data = [header]; books2.forEach((book) => { const row = defaultBookFields.map((field) => { return excelFormatterMap[field](book); }); data.push(row); }); exportCsv(data, filename, options); } const exportXlsxName = "豆瓣书籍导出.xlsx"; function exportBookXlsx(books2, filename = exportXlsxName, aoa2SheetOpts, writingOptions) { const header = defaultBookFields.map((field) => BOOK_FIELD_MAP[field]); const data = [header]; books2.forEach((book) => { const row = defaultBookFields.map((field) => { return excelFormatterMap[field](book); }); data.push(row); }); exportXlsx(data, filename, aoa2SheetOpts, writingOptions); } const _hoisted_1$3 = { key: 0 }; const _hoisted_2$2 = { key: 1 }; const _hoisted_3$1 = ["href"]; const _sfc_main$4 = /* @__PURE__ */ vue.defineComponent({ __name: "BookFormatter", props: { book: null, fields: { default: () => defaultBookFields }, hideEmptyField: { type: Boolean, default: true } }, setup(__props) { const props = __props; const bookFormatter = vue.computed( () => bookItemFormatters.filter((i) => { if (!props.fields.includes(i.key)) return false; if (!props.hideEmptyField) return true; const v = props.book[i.key]; if (Array.isArray(v)) return v.length > 0; return !!props.book[i.key]; }) ); return (_ctx, _cache) => { return vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(vue.unref(bookFormatter), (item) => { return vue.openBlock(), vue.createElementBlock("div", { class: "book-field", key: item.key }, [ item.key === "contentBrief" ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_1$3, vue.toDisplayString(item.label) + ":", 1)) : (vue.openBlock(), vue.createElementBlock("span", _hoisted_2$2, vue.toDisplayString(item.label) + ": ", 1)), item.type === "string" ? (vue.openBlock(), vue.createElementBlock("span", { key: 2, style: vue.normalizeStyle(item.styleObj) }, vue.toDisplayString(item.getText ? item.getText(__props.book) : __props.book[item.key]), 5)) : item.type === "link" ? (vue.openBlock(), vue.createElementBlock("a", { key: 3, href: item.getLink ? item.getLink(__props.book) : `${__props.book[item.key]}`, target: "_blank", style: vue.normalizeStyle(item.styleObj) }, vue.toDisplayString(__props.book[item.key]), 13, _hoisted_3$1)) : vue.createCommentVNode("", true) ]); }), 128); }; } }); const BookFormatter_vue_vue_type_style_index_0_scoped_5f2bdcc9_lang = ""; const _export_sfc = (sfc, props) => { const target = sfc.__vccOpts || sfc; for (const [key, val] of props) { target[key] = val; } return target; }; const BookFormatter = /* @__PURE__ */ _export_sfc(_sfc_main$4, [["__scopeId", "data-v-5f2bdcc9"]]); const _hoisted_1$2 = { class: "item" }; const _hoisted_2$1 = { class: "item-button" }; const _sfc_main$3 = /* @__PURE__ */ vue.defineComponent({ __name: "BookItem", props: { book: null }, emits: ["select"], setup(__props, { emit }) { const props = __props; const { booksStore: booksStore2 } = useStore(); const briefFields = ["id", "title", "authors", "score", "ISBN"]; function select() { emit("select", props.book); } return (_ctx, _cache) => { return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$2, [ vue.createElementVNode("div", null, [ vue.createVNode(BookFormatter, { book: __props.book, fields: briefFields, "hide-empty-field": false }, null, 8, ["book"]) ]), vue.createElementVNode("div", _hoisted_2$1, [ vue.createElementVNode("div", null, [ vue.createVNode(vue.unref(elementPlus.ElButton), { round: "", size: "small", type: "primary", onClick: select }, { default: vue.withCtx(() => [ vue.createTextVNode("详情") ]), _: 1 }) ]), vue.createElementVNode("div", null, [ vue.createVNode(vue.unref(elementPlus.ElButton), { round: "", size: "small", type: "primary", onClick: _cache[0] || (_cache[0] = () => vue.unref(copyBookWithTip)(__props.book)) }, { default: vue.withCtx(() => [ vue.createTextVNode("复制") ]), _: 1 }) ]), vue.createElementVNode("div", null, [ vue.createVNode(vue.unref(elementPlus.ElButton), { round: "", size: "small", type: "danger", onClick: _cache[1] || (_cache[1] = ($event) => vue.unref(booksStore2).removeBook(__props.book.id)) }, { default: vue.withCtx(() => [ vue.createTextVNode("移除") ]), _: 1 }) ]) ]) ]); }; } }); const BookItem_vue_vue_type_style_index_0_scoped_bdb4b0de_lang = ""; const BookItem = /* @__PURE__ */ _export_sfc(_sfc_main$3, [["__scopeId", "data-v-bdb4b0de"]]); const _hoisted_1$1 = { key: 0 }; const _sfc_main$2 = /* @__PURE__ */ vue.defineComponent({ __name: "BookDetail", props: { book: null, show: { type: Boolean } }, emits: ["close"], setup(__props, { emit }) { function handleClose() { emit("close"); } return (_ctx, _cache) => { return vue.openBlock(), vue.createBlock(vue.unref(elementPlus.ElDialog), { "model-value": __props.show && !!__props.book, title: "书籍详情", width: "70%", style: { "max-height": "80vh" }, "before-close": handleClose }, { default: vue.withCtx(() => [ !!__props.book ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_1$1, [ vue.createVNode(BookFormatter, { book: __props.book }, null, 8, ["book"]) ])) : vue.createCommentVNode("", true) ]), _: 1 }, 8, ["model-value"]); }; } }); const _withScopeId = (n) => (vue.pushScopeId("data-v-ed4eeb8f"), n = n(), vue.popScopeId(), n); const _hoisted_1 = { class: "affix" }; const _hoisted_2 = { class: "book-list-container" }; const _hoisted_3 = { class: "book-list-container-header" }; const _hoisted_4 = { class: "book-list-container-body" }; const _hoisted_5 = { key: 0 }; const _hoisted_6 = { key: 1, class: "book-list-container-empty" }; const _hoisted_7 = /* @__PURE__ */ _withScopeId(() => /* @__PURE__ */ vue.createElementVNode("p", null, "书架为空", -1)); const _hoisted_8 = [ _hoisted_7 ]; const _sfc_main$1 = /* @__PURE__ */ vue.defineComponent({ __name: "BookShelf", setup(__props) { const { booksStore: booksStore2 } = useStore(); const showDrawer = vue.ref(false); const sortKey = vue.ref("addTime"); const sortAsc = vue.ref(true); const books2 = vue.computed(() => { return [...booksStore2.books].sort((a, b) => { const aValue = a[sortKey.value]; const bValue = b[sortKey.value]; if (Array.isArray(aValue) || Array.isArray(bValue)) return 0; return aValue > bValue ? sortAsc.value ? 1 : -1 : sortAsc.value ? -1 : 1; }); }); const selectedBook = vue.ref(void 0); const showDetail = vue.ref(false); function selectBook(book) { selectedBook.value = book; showDetail.value = true; } return (_ctx, _cache) => { return vue.openBlock(), vue.createElementBlock(vue.Fragment, null, [ vue.withDirectives(vue.createElementVNode("div", _hoisted_1, [ vue.createVNode(vue.unref(elementPlus.ElButton), { icon: vue.unref(arrow_left_default), circle: "", type: "primary", onClick: _cache[0] || (_cache[0] = ($event) => showDrawer.value = !showDrawer.value) }, null, 8, ["icon"]) ], 512), [ [vue.vShow, !showDrawer.value] ]), vue.createVNode(vue.unref(elementPlus.ElDrawer), { modelValue: showDrawer.value, "onUpdate:modelValue": _cache[3] || (_cache[3] = ($event) => showDrawer.value = $event), title: "书架" }, { default: vue.withCtx(() => [ vue.createElementVNode("div", _hoisted_2, [ vue.createElementVNode("div", _hoisted_3, [ vue.createVNode(vue.unref(elementPlus.ElDropdown), { disabled: vue.unref(books2).length === 0 }, { dropdown: vue.withCtx(() => [ vue.createVNode(vue.unref(elementPlus.ElDropdownMenu), null, { default: vue.withCtx(() => [ vue.createVNode(vue.unref(elementPlus.ElDropdownItem), { onClick: _cache[1] || (_cache[1] = () => vue.unref(exportBookXlsx)(vue.unref(books2))) }, { default: vue.withCtx(() => [ vue.createTextVNode("excel ") ]), _: 1 }), vue.createVNode(vue.unref(elementPlus.ElDropdownItem), { onClick: _cache[2] || (_cache[2] = () => vue.unref(exportBookCsv)(vue.unref(books2))) }, { default: vue.withCtx(() => [ vue.createTextVNode("csv ") ]), _: 1 }) ]), _: 1 }) ]), default: vue.withCtx(() => [ vue.createVNode(vue.unref(elementPlus.ElButton), { type: "primary", round: "", disabled: vue.unref(books2).length === 0 }, { default: vue.withCtx(() => [ vue.createTextVNode(" 导出"), vue.createVNode(vue.unref(elementPlus.ElIcon), { class: "el-icon--right" }, { default: vue.withCtx(() => [ vue.createVNode(vue.unref(arrow_down_default)) ]), _: 1 }) ]), _: 1 }, 8, ["disabled"]) ]), _: 1 }, 8, ["disabled"]), vue.createVNode(vue.unref(elementPlus.ElButton), { class: "book-list-container-header-item", round: "", type: "danger", disabled: vue.unref(books2).length === 0, onClick: vue.unref(booksStore2).clearBook }, { default: vue.withCtx(() => [ vue.createTextVNode("清空 ") ]), _: 1 }, 8, ["disabled", "onClick"]) ]), vue.createElementVNode("div", _hoisted_4, [ vue.unref(books2).length > 0 ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_5, [ (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(vue.unref(books2), (book) => { return vue.openBlock(), vue.createElementBlock("div", { class: "book-list-container-book-item", key: book.id }, [ vue.createVNode(BookItem, { book, onSelect: selectBook }, null, 8, ["book"]) ]); }), 128)) ])) : (vue.openBlock(), vue.createElementBlock("div", _hoisted_6, _hoisted_8)) ]) ]) ]), _: 1 }, 8, ["modelValue"]), vue.createVNode(_sfc_main$2, { book: selectedBook.value, show: showDetail.value, onClose: _cache[4] || (_cache[4] = ($event) => showDetail.value = false) }, null, 8, ["book", "show"]) ], 64); }; } }); const BookShelf_vue_vue_type_style_index_0_scoped_ed4eeb8f_lang = ""; const BookShelf = /* @__PURE__ */ _export_sfc(_sfc_main$1, [["__scopeId", "data-v-ed4eeb8f"]]); function getMetaInfo(subjectDoc) { const data = { id: "", doubanUrl: "", title: "", ISBN: "", authors: [] }; const jsonElement = subjectDoc.querySelector('[type="application/ld+json"]'); if (!jsonElement || !jsonElement.textContent) { return data; } const obj = JSON.parse(jsonElement.textContent); data.doubanUrl = obj.url; const id = obj.url.split("/")[4]; data.id = id; data.title = obj.name; data.ISBN = obj.isbn; data.authors = obj.author.map((i) => i.name); return data; } function getFromA(element) { const aElements = []; let current = element; while (current) { const next = current.nextElementSibling; if (!next || next.tagName !== "A") break; current = next; aElements.push(current); } return aElements.map((i) => { var _a; return (_a = i.textContent) == null ? void 0 : _a.trim(); }); } function getFromText(element) { var _a, _b; const text = (_b = (_a = element.nextSibling) == null ? void 0 : _a.textContent) == null ? void 0 : _b.trim(); if (!text || text === ":") return ""; return text; } function getFromAOrText(element) { const resultFromA = getFromA(element); if (resultFromA.length !== 0) { return resultFromA; } const resultFromText = getFromText(element); return resultFromText ? [resultFromText] : []; } function getExtraInfo(subjectDoc) { const data = { publishingHouse: "", subTitle: "", originName: "", publishingTime: "", seriesName: "", page: 0, translators: [] }; const plElements = subjectDoc.querySelectorAll("#info .pl"); Array.from(plElements).forEach((element) => { var _a; switch ((_a = element.textContent) == null ? void 0 : _a.trim()) { case "出版社:": data.publishingHouse = getFromAOrText(element)[0] ?? ""; break; case "副标题:": data.subTitle = getFromText(element); break; case "原作名:": data.originName = getFromText(element); break; case "译者": data.translators = getFromAOrText(element); break; case "出版年:": data.publishingTime = getFromText(element); break; case "页数:": { const pageStr = getFromText(element); data.page = pageStr ? Number.parseInt(pageStr, 10) : 0; break; } case "丛书:": data.seriesName = getFromAOrText(element)[0] ?? ""; break; } }); return data; } function getScoreInfo(subjectDoc) { var _a, _b, _c, _d; const element = subjectDoc.getElementById("interest_sectl"); const scoreStr = (_b = (_a = element == null ? void 0 : element.querySelector("strong")) == null ? void 0 : _a.textContent) == null ? void 0 : _b.trim(); const scorePeopleCountStr = (_d = (_c = element == null ? void 0 : element.querySelector(".rating_people > span")) == null ? void 0 : _c.textContent) == null ? void 0 : _d.trim(); let scorePeopleCount = 0; if (scorePeopleCountStr && !scorePeopleCountStr.includes("目前无人评价")) { scorePeopleCount = Number.parseInt(scorePeopleCountStr, 10); } return { score: scoreStr ? Number.parseFloat(scoreStr) : 0, scorePeopleCount }; } function getContentBrief(subjectDoc) { var _a; const introElements = Array.from( subjectDoc == null ? void 0 : subjectDoc.querySelectorAll("#link-report .intro") ); if (introElements.length === 0) return ""; const pElements = ((_a = introElements[introElements.length - 1]) == null ? void 0 : _a.getElementsByTagName("p")) ?? []; return Array.from(pElements).reduce((str, current, idx) => { var _a2; const text = (_a2 = current.textContent) == null ? void 0 : _a2.trim(); if (text) str += idx === 0 ? text : ` ${text}`; return str; }, ""); } function getCoverUrl(subjectDoc) { var _a; const imgElement = (_a = subjectDoc.getElementById("mainpic")) == null ? void 0 : _a.querySelector("img"); return (imgElement == null ? void 0 : imgElement.src) ?? ""; } function getBook(subjectDoc) { const book = { ...getMetaInfo(subjectDoc), ...getScoreInfo(subjectDoc), ...getExtraInfo(subjectDoc), contentBrief: getContentBrief(subjectDoc), coverUrl: getCoverUrl(subjectDoc) }; return book; } function getAlreadyReadButton(subjectDoc) { return subjectDoc.querySelector("#interest_sect_level > a:nth-child(3)"); } function getLasButton(subjectDoc) { return subjectDoc.querySelector( "#interest_sect_level > a:nth-last-of-type(1)" ); } const parseHeaders = (rawHeaders = "") => { const headers = new Headers(); const preProcessedHeaders = rawHeaders.replace(/\r?\n[\t ]+/g, " "); preProcessedHeaders.split("\r").map(function(header) { return header.startsWith(` `) ? header.substring(1) : header; }).forEach(function(line) { var _a; const parts = line.split(":"); const key = (_a = parts.shift()) == null ? void 0 : _a.trim(); if (key) { const value = parts.join(":").trim(); headers.append(key, value); } }); return headers; }; async function GM_Fetch(xhrRequest) { return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: "GET", async onload(e) { const resp = new Response(e.response ?? e.responseText, { status: e.status, statusText: e.statusText, headers: parseHeaders(e.responseHeaders) }); Object.defineProperty(resp, "url", { value: e.finalUrl }); resolve(resp); }, async onerror() { reject(new TypeError("Network request failed")); }, async ontimeout() { reject(new TypeError("Network request failed")); }, async onabort() { reject(new DOMException("Aborted", "AbortError")); }, ...xhrRequest }); }); } const IDENTIFY_CLASS = "douban_shelf_button"; function createBtn(doc, id, text, clickHandler, style, classList) { const btn = doc.createElement("a"); const clsList = classList || ["j", "a_show_login", "colbutt", "ll"]; btn.classList.add(...clsList); btn.id = id; btn.href = "#"; btn.rel = "nofollow"; if (style) { Object.entries(style).map(([k, v]) => { btn.style[k] = v; }); } const span = doc.createElement("span"); span.classList.add(IDENTIFY_CLASS); span.textContent = text; span.style.fontSize = "13px"; btn.appendChild(span); btn.addEventListener("click", (e) => { e.preventDefault(); clickHandler(); }); return btn; } const COPY_ID = "douban-book-copy"; const ADD_SHELF_ID = "douban-book-add-shelf"; const COPY = "复制"; const ADD_SHELF = "加入书架"; function createCopyBtn(doc, getBook2, id = COPY_ID, style, classList) { const btn = createBtn( doc, id, COPY, async () => { const book = await getBook2(doc); if (!book) return; try { await copyBookWithTip(book); btn.dispatchEvent(new CustomEvent(COPY, { detail: true })); } catch (error2) { btn.dispatchEvent(new CustomEvent(COPY, { detail: false })); throw error2; } }, style, classList ); return btn; } function createAddBtn(doc, getBook2, id = ADD_SHELF_ID, style, classList) { const btn = createBtn( doc, id, ADD_SHELF, async () => { const book = await getBook2(doc); const { booksStore: booksStore2 } = useStore(); const r = booksStore2.addBook(book); if (!r.success) { btn.dispatchEvent(new CustomEvent(ADD_SHELF, { detail: false })); warning(r.msg); } else { btn.dispatchEvent(new CustomEvent(ADD_SHELF, { detail: true })); success("加入成功"); } }, style, classList ); return btn; } async function getBookPageHtmlByUrl(url) { const response = await GM_Fetch({ url }); if (response.status !== 200) { return null; } const text = await response.text(); return text; } function useInitBtns$5(doc) { if (!/\/subject\/\d+\/?$/.test(new URL(doc.URL).pathname)) { return; } const lastButton = getLasButton(doc); if (!lastButton) { warning(`定位'读过'按钮失败`); return; } const span = lastButton.querySelector("span"); if ((span == null ? void 0 : span.textContent) === ADD_SHELF) { return; } const input = span == null ? void 0 : span.querySelector("input"); const alreadyReadButton = (input == null ? void 0 : input.value) === "读过" ? lastButton : getAlreadyReadButton(doc); if (!alreadyReadButton) { warning(`定位'读过'按钮失败`); return; } const copyBtn = createCopyBtn(doc, getBook); const addBtn = createAddBtn(doc, getBook); alreadyReadButton.after(copyBtn); copyBtn.after(addBtn); return { copyBtn, addBtn }; } function init$5(doc) { useInitBtns$5(doc); } function getBookItemList$4(searchDoc) { const rootEle = searchDoc.querySelector("#wrapper #root"); if (!rootEle) return []; return Array.from(rootEle.querySelectorAll(".item-root")).reduce( (list, cur) => { var _a, _b, _c, _d, _e; const aEle = cur.querySelector("a"); if ((_a = aEle == null ? void 0 : aEle.href) == null ? void 0 : _a.startsWith("https://book.douban.com/subject/")) { const name = ((_c = (_b = cur.querySelector(".detail .title")) == null ? void 0 : _b.querySelector("a")) == null ? void 0 : _c.textContent) ?? ""; const id = ((_e = (_d = aEle == null ? void 0 : aEle.href) == null ? void 0 : _d.split("https://book.douban.com/subject/")[1]) == null ? void 0 : _e.split("/")[0]) ?? ""; list.push({ element: cur, url: aEle == null ? void 0 : aEle.href, id, name }); } return list; }, [] ); } function useInitBtns$4(doc) { const btn = doc.getElementById(`${COPY_ID}-0`); if (btn) { return false; } const { booksStore: booksStore2 } = useStore(); const list = getBookItemList$4(doc); list.forEach(({ element, url, name, id }, idx) => { var _a; let bookCache = void 0; const getBook$12 = async () => { if (bookCache) return bookCache; const bookInStore = booksStore2.getBook(id); if (bookInStore) { bookCache = { ...bookInStore }; delete bookCache.addTime; return bookCache; } const html = await getBookPageHtmlByUrl(url); if (!html) { throw new Error(`获取《${name}》页面失败`); } const parser = new DOMParser(); const htmlDoc = parser.parseFromString(html, "text/html"); const book = getBook(htmlDoc); bookCache = book; return book; }; const style = { marginTop: "7px" }; const copyBtn = createCopyBtn(doc, getBook$12, `${COPY_ID}-${idx}`, style); const addBtn = createAddBtn(doc, getBook$12, `${ADD_SHELF_ID}-${idx}`, style); (_a = element.querySelector(".detail")) == null ? void 0 : _a.appendChild(copyBtn); copyBtn.after(addBtn); }); return true; } function init$4(doc) { useInitBtns$4(doc); } function getBookItemList$3(seriesDoc) { return Array.from( seriesDoc.querySelectorAll("#content .subject-item") ).reduce((list, cur) => { var _a, _b, _c, _d; const aEle = (_a = cur.querySelector(".info")) == null ? void 0 : _a.querySelector("a"); if ((_b = aEle == null ? void 0 : aEle.href) == null ? void 0 : _b.startsWith("https://book.douban.com/subject/")) { const id = ((_d = (_c = aEle == null ? void 0 : aEle.href) == null ? void 0 : _c.split("https://book.douban.com/subject/")[1]) == null ? void 0 : _d.split("/")[0]) ?? ""; list.push({ element: cur, url: aEle == null ? void 0 : aEle.href, id, name: (aEle == null ? void 0 : aEle.textContent) ?? "" }); } return list; }, []); } function useInitBtns$3(doc) { if (!/\/series\/\d+\/?$/.test(new URL(doc.URL).pathname)) { return false; } const btn = doc.getElementById(`${COPY_ID}-0`); if (btn) { return false; } const { booksStore: booksStore2 } = useStore(); const list = getBookItemList$3(doc); list.forEach(({ element, url, name, id }, idx) => { var _a; let bookCache = void 0; const getBook$12 = async () => { if (bookCache) return bookCache; const bookInStore = booksStore2.getBook(id); if (bookInStore) { bookCache = { ...bookInStore }; delete bookCache.addTime; return bookCache; } const html = await getBookPageHtmlByUrl(url); if (!html) { throw new Error(`获取《${name}》页面失败`); } const parser = new DOMParser(); const htmlDoc = parser.parseFromString(html, "text/html"); const book = getBook(htmlDoc); bookCache = book; return book; }; const style = { marginTop: "7px" }; const copyBtn = createCopyBtn(doc, getBook$12, `${COPY_ID}-${idx}`, style); const addBtn = createAddBtn(doc, getBook$12, `${ADD_SHELF_ID}-${idx}`, style); (_a = element.querySelector(".info")) == null ? void 0 : _a.appendChild(copyBtn); copyBtn.after(addBtn); }); return true; } function init$3(doc) { useInitBtns$3(doc); } function getBookItemList$2(seriesDoc) { return Array.from(seriesDoc.querySelectorAll("#content .bkdesc")).reduce( (list, cur) => { var _a, _b, _c; const aEle = cur == null ? void 0 : cur.querySelector("a"); if ((_a = aEle == null ? void 0 : aEle.href) == null ? void 0 : _a.startsWith("https://book.douban.com/subject/")) { const id = ((_c = (_b = aEle == null ? void 0 : aEle.href) == null ? void 0 : _b.split("https://book.douban.com/subject/")[1]) == null ? void 0 : _c.split("/")[0]) ?? ""; list.push({ element: cur, url: aEle == null ? void 0 : aEle.href, id, name: (aEle == null ? void 0 : aEle.textContent) ?? "" }); } return list; }, [] ); } function useInitBtns$2(doc) { if (!/\/works\/\d+\/?$/.test(new URL(doc.URL).pathname)) { return false; } const btn = doc.getElementById(`${COPY_ID}-0`); if (btn) { return false; } const { booksStore: booksStore2 } = useStore(); const list = getBookItemList$2(doc); list.forEach(({ element, url, name, id }, idx) => { var _a; let bookCache = void 0; const getBook$12 = async () => { if (bookCache) return bookCache; const bookInStore = booksStore2.getBook(id); if (bookInStore) { bookCache = { ...bookInStore }; delete bookCache.addTime; return bookCache; } const html = await getBookPageHtmlByUrl(url); if (!html) { throw new Error(`获取《${name}》页面失败`); } const parser = new DOMParser(); const htmlDoc = parser.parseFromString(html, "text/html"); const book = getBook(htmlDoc); bookCache = book; return book; }; const classList = ["j", "ll", "colbutt", "a_add2cart", "add2cart"]; const copyBtn = createCopyBtn( doc, getBook$12, `${COPY_ID}-${idx}`, void 0, classList ); const addBtn = createAddBtn( doc, getBook$12, `${ADD_SHELF_ID}-${idx}`, void 0, classList ); (_a = element.querySelector(".rr")) == null ? void 0 : _a.appendChild(copyBtn); copyBtn.after(addBtn); }); return true; } function init$2(doc) { useInitBtns$2(doc); } function getBookItemList$1(seriesDoc) { return Array.from( seriesDoc.querySelectorAll("#content .subject-item") ).reduce((list, cur) => { var _a, _b, _c, _d; const aEle = (_a = cur.querySelector(".info")) == null ? void 0 : _a.querySelector("a"); if ((_b = aEle == null ? void 0 : aEle.href) == null ? void 0 : _b.startsWith("https://book.douban.com/subject/")) { const id = ((_d = (_c = aEle == null ? void 0 : aEle.href) == null ? void 0 : _c.split("https://book.douban.com/subject/")[1]) == null ? void 0 : _d.split("/")[0]) ?? ""; list.push({ element: cur, url: aEle == null ? void 0 : aEle.href, id, name: (aEle == null ? void 0 : aEle.textContent) ?? "" }); } return list; }, []); } function useInitBtns$1(doc) { if (!/\/press\/\d+\/?$/.test(new URL(doc.URL).pathname)) { return false; } const btn = doc.getElementById(`${COPY_ID}-0`); if (btn) { return false; } const { booksStore: booksStore2 } = useStore(); const list = getBookItemList$1(doc); list.forEach(({ element, url, name, id }, idx) => { var _a; let bookCache = void 0; const getBook$12 = async () => { if (bookCache) return bookCache; const bookInStore = booksStore2.getBook(id); if (bookInStore) { bookCache = { ...bookInStore }; delete bookCache.addTime; return bookCache; } const html = await getBookPageHtmlByUrl(url); if (!html) { throw new Error(`获取《${name}》页面失败`); } const parser = new DOMParser(); const htmlDoc = parser.parseFromString(html, "text/html"); const book = getBook(htmlDoc); bookCache = book; return book; }; const style = { marginTop: "7px" }; const classList = ["j", "a_collect_btn"]; const copyBtn = createCopyBtn( doc, getBook$12, `${COPY_ID}-${idx}`, style, classList ); const addBtn = createAddBtn( doc, getBook$12, `${ADD_SHELF_ID}-${idx}`, style, classList ); (_a = element.querySelector(".ft .collect-info")) == null ? void 0 : _a.appendChild(copyBtn); copyBtn.after(addBtn); }); return true; } function init$1(doc) { useInitBtns$1(doc); } function getBookItemList(seriesDoc) { return Array.from(seriesDoc.querySelectorAll("#content li")).reduce( (list, cur) => { var _a, _b, _c; const aEle = cur == null ? void 0 : cur.querySelector("a"); if ((_a = aEle == null ? void 0 : aEle.href) == null ? void 0 : _a.startsWith("https://book.douban.com/subject/")) { const id = ((_c = (_b = aEle == null ? void 0 : aEle.href) == null ? void 0 : _b.split("https://book.douban.com/subject/")[1]) == null ? void 0 : _c.split("/")[0]) ?? ""; list.push({ element: cur, url: aEle == null ? void 0 : aEle.href, id, name: (aEle == null ? void 0 : aEle.textContent) ?? "" }); } return list; }, [] ); } function useInitBtns(doc) { if (!/\/author\/\d+\/books\/?$/.test(new URL(doc.URL).pathname)) { return false; } const btn = doc.getElementById(`${COPY_ID}-0`); if (btn) { return false; } const { booksStore: booksStore2 } = useStore(); const list = getBookItemList(doc); list.forEach(({ element, url, name, id }, idx) => { var _a; let bookCache = void 0; const getBook$12 = async () => { if (bookCache) return bookCache; const bookInStore = booksStore2.getBook(id); if (bookInStore) { bookCache = { ...bookInStore }; delete bookCache.addTime; return bookCache; } const html = await getBookPageHtmlByUrl(url); if (!html) { throw new Error(`获取《${name}》页面失败`); } const parser = new DOMParser(); const htmlDoc = parser.parseFromString(html, "text/html"); const book = getBook(htmlDoc); bookCache = book; return book; }; const classList = ["j", "a_collect_btn"]; const copyBtn = doc.createElement("span"); copyBtn.classList.add("gact"); copyBtn.appendChild( createCopyBtn(doc, getBook$12, `${COPY_ID}-${idx}`, void 0, classList) ); const addBtn = doc.createElement("span"); addBtn.classList.add("gact"); addBtn.appendChild( createAddBtn(doc, getBook$12, `${ADD_SHELF_ID}-${idx}`, void 0, classList) ); (_a = element.querySelector(".author-collect")) == null ? void 0 : _a.appendChild(copyBtn); copyBtn.after(addBtn); }); return true; } function init(doc) { useInitBtns(doc); } const _sfc_main = /* @__PURE__ */ vue.defineComponent({ __name: "App", setup(__props) { vue.onMounted(async () => { const map = { ["book.douban.com/subject"]: init$5, ["search.douban.com/book"]: init$4, ["book.douban.com/series"]: init$3, ["book.douban.com/works"]: init$2, ["book.douban.com/press"]: init$1, ["book.douban.com/author"]: init }; const url = new URL(document.URL); const initFunc = map[url.host + url.pathname.split("/").slice(0, 2).join("/")]; if (initFunc) { initFunc(document); } else { console.warn(`${url} 没有对应的处理方法`); } }); return (_ctx, _cache) => { return vue.openBlock(), vue.createBlock(BookShelf); }; } }); async function run(doc) { const app = document.createElement("div"); doc.body.appendChild(app); setTimeout(() => { vue.createApp(_sfc_main).mount(app); }); } run(document); })(Vue, ElementPlus, csv_stringify_sync, XLSX);
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址