feat(Claude): 左右翻页
This commit is contained in:
parent
b8377cbb80
commit
3a4ef41428
@ -9,11 +9,24 @@ const Reader = (function() {
|
||||
let toolbarVisible = false;
|
||||
let toolbarTimer = null;
|
||||
|
||||
// 翻页模式相关状态
|
||||
let currentReadingMode = 'page'; // 'scroll' 或 'page'
|
||||
let currentPage = 0;
|
||||
let totalPages = 0;
|
||||
let pageContents = []; // 分页后的内容
|
||||
let touchStartX = 0;
|
||||
let touchStartY = 0;
|
||||
let touchEndX = 0;
|
||||
let touchEndY = 0;
|
||||
let isSwiping = false;
|
||||
|
||||
// ========== 初始化阅读器 ==========
|
||||
|
||||
async function init(novelId, chapterIndex = 0) {
|
||||
currentNovelId = novelId;
|
||||
currentChapterIndex = chapterIndex;
|
||||
currentReadingMode = Store.getReadingMode();
|
||||
currentPage = 0;
|
||||
|
||||
// 隐藏导航栏
|
||||
$('#app-header').addClass('header-hidden');
|
||||
@ -98,29 +111,169 @@ const Reader = (function() {
|
||||
}
|
||||
|
||||
const $content = $('#app-content');
|
||||
$content.html(`
|
||||
<div class="reader-page">
|
||||
<div class="reader-content">
|
||||
<h1 class="reader-chapter-title">${chapter.title}</h1>
|
||||
<div class="reader-text">${content}</div>
|
||||
<div class="reader-nav">
|
||||
<button id="nav-prev" ${currentChapterIndex <= 0 ? 'disabled' : ''}>
|
||||
<svg viewBox="0 0 24 24"><path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"/></svg>
|
||||
上一章
|
||||
</button>
|
||||
<button id="nav-next">
|
||||
下一章
|
||||
<svg viewBox="0 0 24 24"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/></svg>
|
||||
</button>
|
||||
|
||||
if (currentReadingMode === 'scroll') {
|
||||
// 上下滚动模式
|
||||
$content.html(`
|
||||
<div class="reader-page scroll-mode">
|
||||
<div class="reader-content">
|
||||
<h1 class="reader-chapter-title">${chapter.title}</h1>
|
||||
<div class="reader-text">${content}</div>
|
||||
<div class="reader-nav">
|
||||
<button id="nav-prev" ${currentChapterIndex <= 0 ? 'disabled' : ''}>
|
||||
<svg viewBox="0 0 24 24"><path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"/></svg>
|
||||
上一章
|
||||
</button>
|
||||
<button id="nav-next">
|
||||
下一章
|
||||
<svg viewBox="0 0 24 24"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/></svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`);
|
||||
`);
|
||||
} else {
|
||||
// 左右翻页模式
|
||||
$content.html(`
|
||||
<div class="reader-page page-mode">
|
||||
<div class="page-container">
|
||||
<div class="page-content">
|
||||
<h1 class="reader-chapter-title">${chapter.title}</h1>
|
||||
<div class="reader-text">${content}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="page-indicator">
|
||||
<span class="page-current">1</span> / <span class="page-total">1</span>
|
||||
</div>
|
||||
<div class="page-tap-zones">
|
||||
<div class="tap-zone tap-prev"></div>
|
||||
<div class="tap-zone tap-center"></div>
|
||||
<div class="tap-zone tap-next"></div>
|
||||
</div>
|
||||
</div>
|
||||
`);
|
||||
|
||||
// 等待DOM渲染后进行分页计算
|
||||
setTimeout(() => {
|
||||
calculatePages();
|
||||
showPage(currentPage);
|
||||
}, 100);
|
||||
}
|
||||
|
||||
// 应用设置
|
||||
applySettings();
|
||||
}
|
||||
|
||||
// ========== 翻页模式相关函数 ==========
|
||||
|
||||
function calculatePages() {
|
||||
if (currentReadingMode !== 'page') return;
|
||||
|
||||
const $container = $('.page-container');
|
||||
const $content = $('.page-content');
|
||||
|
||||
if (!$container.length || !$content.length) return;
|
||||
|
||||
const containerHeight = $container.height();
|
||||
const contentHeight = $content[0].scrollHeight;
|
||||
|
||||
// 计算总页数
|
||||
totalPages = Math.max(1, Math.ceil(contentHeight / containerHeight));
|
||||
pageContents = [];
|
||||
|
||||
// 更新页码显示
|
||||
$('.page-total').text(totalPages);
|
||||
|
||||
// 恢复之前的阅读位置
|
||||
const position = Store.getReadingPosition(currentNovelId);
|
||||
if (position && position.chapterIndex === currentChapterIndex && position.pageIndex !== undefined) {
|
||||
currentPage = Math.min(position.pageIndex, totalPages - 1);
|
||||
} else {
|
||||
currentPage = 0;
|
||||
}
|
||||
}
|
||||
|
||||
function showPage(pageIndex) {
|
||||
if (currentReadingMode !== 'page') return;
|
||||
|
||||
const $container = $('.page-container');
|
||||
const $content = $('.page-content');
|
||||
|
||||
if (!$container.length || !$content.length) return;
|
||||
|
||||
// 确保页码在有效范围内
|
||||
pageIndex = Math.max(0, Math.min(pageIndex, totalPages - 1));
|
||||
currentPage = pageIndex;
|
||||
|
||||
const containerHeight = $container.height();
|
||||
const scrollTop = pageIndex * containerHeight;
|
||||
|
||||
// 使用transform进行平滑翻页
|
||||
$content.css('transform', `translateY(-${scrollTop}px)`);
|
||||
|
||||
// 更新页码显示
|
||||
$('.page-current').text(currentPage + 1);
|
||||
|
||||
// 保存阅读位置
|
||||
saveReadingProgress();
|
||||
|
||||
// 更新进度条
|
||||
updateProgressIndicator();
|
||||
}
|
||||
|
||||
function nextPage() {
|
||||
if (currentReadingMode !== 'page') return;
|
||||
|
||||
if (currentPage < totalPages - 1) {
|
||||
showPage(currentPage + 1);
|
||||
} else {
|
||||
// 已是最后一页,跳转下一章
|
||||
nextChapter();
|
||||
}
|
||||
}
|
||||
|
||||
function prevPage() {
|
||||
if (currentReadingMode !== 'page') return;
|
||||
|
||||
if (currentPage > 0) {
|
||||
showPage(currentPage - 1);
|
||||
} else {
|
||||
// 已是第一页,跳转上一章
|
||||
if (currentChapterIndex > 0) {
|
||||
// 跳转上一章并显示最后一页
|
||||
goToPrevChapterLastPage();
|
||||
} else {
|
||||
Toast.show('已是第一章');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function goToPrevChapterLastPage() {
|
||||
hideToolbar();
|
||||
try {
|
||||
const chapter = await API.getPrevChapter(currentNovelId, currentChapterIndex);
|
||||
if (chapter) {
|
||||
currentChapter = chapter;
|
||||
currentChapterIndex = chapter.index;
|
||||
renderChapter(chapter);
|
||||
saveReadingProgress();
|
||||
updateHistory(currentNovelId, chapter.id);
|
||||
$('#reader-title').text(chapter.title);
|
||||
|
||||
// 等待分页计算完成后跳到最后一页
|
||||
setTimeout(() => {
|
||||
if (totalPages > 0) {
|
||||
showPage(totalPages - 1);
|
||||
}
|
||||
}, 150);
|
||||
} else {
|
||||
Toast.show('已是第一章');
|
||||
}
|
||||
} catch (error) {
|
||||
Toast.show('加载失败');
|
||||
}
|
||||
}
|
||||
|
||||
// ========== 章节导航 ==========
|
||||
|
||||
async function nextChapter() {
|
||||
@ -130,6 +283,7 @@ const Reader = (function() {
|
||||
if (chapter) {
|
||||
currentChapter = chapter;
|
||||
currentChapterIndex = chapter.index;
|
||||
currentPage = 0; // 重置页码
|
||||
renderChapter(chapter);
|
||||
scrollToTop();
|
||||
saveReadingProgress();
|
||||
@ -154,6 +308,7 @@ const Reader = (function() {
|
||||
if (chapter) {
|
||||
currentChapter = chapter;
|
||||
currentChapterIndex = chapter.index;
|
||||
currentPage = 0; // 重置页码
|
||||
renderChapter(chapter);
|
||||
scrollToTop();
|
||||
saveReadingProgress();
|
||||
@ -170,11 +325,13 @@ const Reader = (function() {
|
||||
async function goToChapter(index) {
|
||||
hideToolbar();
|
||||
hideCatalog();
|
||||
currentPage = 0; // 重置页码
|
||||
await loadChapter(currentNovelId, index);
|
||||
scrollToTop();
|
||||
}
|
||||
|
||||
function reload() {
|
||||
currentPage = 0;
|
||||
loadChapter(currentNovelId, currentChapterIndex);
|
||||
}
|
||||
|
||||
@ -221,6 +378,7 @@ const Reader = (function() {
|
||||
function applySettings() {
|
||||
const fontSize = Store.getFontSize();
|
||||
const lineHeight = Store.getLineHeight();
|
||||
const readingMode = Store.getReadingMode();
|
||||
|
||||
$('.reader-text').css({
|
||||
'--reader-font-size': fontSize + 'px',
|
||||
@ -239,6 +397,26 @@ const Reader = (function() {
|
||||
const theme = Store.getTheme();
|
||||
$('.theme-btn').removeClass('active');
|
||||
$(`.theme-btn[data-theme="${theme}"]`).addClass('active');
|
||||
|
||||
// 更新阅读模式按钮状态
|
||||
$('.reading-mode-btn').removeClass('active');
|
||||
$(`.reading-mode-btn[data-mode="${readingMode}"]`).addClass('active');
|
||||
}
|
||||
|
||||
function changeReadingMode(mode) {
|
||||
if (mode === currentReadingMode) return;
|
||||
|
||||
Store.setReadingMode(mode);
|
||||
currentReadingMode = mode;
|
||||
currentPage = 0;
|
||||
|
||||
// 重新渲染当前章节
|
||||
if (currentChapter) {
|
||||
renderChapter(currentChapter);
|
||||
}
|
||||
|
||||
applySettings();
|
||||
Toast.show(mode === 'page' ? '已切换为翻页模式' : '已切换为滚动模式');
|
||||
}
|
||||
|
||||
function changeFontSize(delta) {
|
||||
@ -365,19 +543,31 @@ const Reader = (function() {
|
||||
function saveReadingProgress() {
|
||||
if (!currentNovelId) return;
|
||||
|
||||
Store.setReadingPosition(currentNovelId, {
|
||||
chapterIndex: currentChapterIndex,
|
||||
scrollTop: window.scrollY
|
||||
});
|
||||
if (currentReadingMode === 'page') {
|
||||
Store.setReadingPosition(currentNovelId, {
|
||||
chapterIndex: currentChapterIndex,
|
||||
pageIndex: currentPage,
|
||||
readingMode: 'page'
|
||||
});
|
||||
} else {
|
||||
Store.setReadingPosition(currentNovelId, {
|
||||
chapterIndex: currentChapterIndex,
|
||||
scrollTop: window.scrollY,
|
||||
readingMode: 'scroll'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function restoreScrollPosition() {
|
||||
const position = Store.getReadingPosition(currentNovelId);
|
||||
if (position && position.chapterIndex === currentChapterIndex && position.scrollTop) {
|
||||
if (!position || position.chapterIndex !== currentChapterIndex) return;
|
||||
|
||||
if (currentReadingMode === 'scroll' && position.scrollTop) {
|
||||
setTimeout(() => {
|
||||
window.scrollTo(0, position.scrollTop);
|
||||
}, 100);
|
||||
}
|
||||
// 翻页模式的位置恢复在 calculatePages 中处理
|
||||
}
|
||||
|
||||
async function updateHistory(novelId, chapterId) {
|
||||
@ -400,25 +590,99 @@ const Reader = (function() {
|
||||
}
|
||||
|
||||
function updateProgressIndicator() {
|
||||
const scrollTop = window.scrollY;
|
||||
const docHeight = document.documentElement.scrollHeight - window.innerHeight;
|
||||
const progress = docHeight > 0 ? (scrollTop / docHeight) * 100 : 0;
|
||||
let progress = 0;
|
||||
|
||||
if (currentReadingMode === 'page') {
|
||||
// 翻页模式:基于页码计算进度
|
||||
progress = totalPages > 1 ? (currentPage / (totalPages - 1)) * 100 : 100;
|
||||
} else {
|
||||
// 滚动模式:基于滚动位置计算进度
|
||||
const scrollTop = window.scrollY;
|
||||
const docHeight = document.documentElement.scrollHeight - window.innerHeight;
|
||||
progress = docHeight > 0 ? (scrollTop / docHeight) * 100 : 0;
|
||||
}
|
||||
|
||||
$('.reading-progress-indicator .progress-bar').css('width', progress + '%');
|
||||
}
|
||||
|
||||
// ========== 事件绑定 ==========
|
||||
|
||||
function bindEvents() {
|
||||
// 点击内容区域切换工具栏
|
||||
$(document).off('click.reader').on('click.reader', '.reader-page', function(e) {
|
||||
// 滚动模式:点击内容区域切换工具栏
|
||||
$(document).off('click.reader').on('click.reader', '.reader-page.scroll-mode', function(e) {
|
||||
// 排除按钮点击
|
||||
if ($(e.target).closest('button, a').length) return;
|
||||
toggleToolbar();
|
||||
});
|
||||
|
||||
// 滚动事件
|
||||
// 翻页模式:点击区域处理
|
||||
$(document).off('click.tapprev').on('click.tapprev', '.tap-prev', function(e) {
|
||||
e.stopPropagation();
|
||||
prevPage();
|
||||
});
|
||||
|
||||
$(document).off('click.tapcenter').on('click.tapcenter', '.tap-center', function(e) {
|
||||
e.stopPropagation();
|
||||
toggleToolbar();
|
||||
});
|
||||
|
||||
$(document).off('click.tapnext').on('click.tapnext', '.tap-next', function(e) {
|
||||
e.stopPropagation();
|
||||
nextPage();
|
||||
});
|
||||
|
||||
// 翻页模式:触摸滑动事件
|
||||
$(document).off('touchstart.reader').on('touchstart.reader', '.reader-page.page-mode', function(e) {
|
||||
if ($(e.target).closest('button, a, .tap-zone').length) return;
|
||||
touchStartX = e.originalEvent.touches[0].clientX;
|
||||
touchStartY = e.originalEvent.touches[0].clientY;
|
||||
isSwiping = false;
|
||||
});
|
||||
|
||||
$(document).off('touchmove.reader').on('touchmove.reader', '.reader-page.page-mode', function(e) {
|
||||
if (!touchStartX) return;
|
||||
touchEndX = e.originalEvent.touches[0].clientX;
|
||||
touchEndY = e.originalEvent.touches[0].clientY;
|
||||
|
||||
const diffX = touchEndX - touchStartX;
|
||||
const diffY = touchEndY - touchStartY;
|
||||
|
||||
// 判断是否为水平滑动
|
||||
if (Math.abs(diffX) > Math.abs(diffY) && Math.abs(diffX) > 30) {
|
||||
isSwiping = true;
|
||||
}
|
||||
});
|
||||
|
||||
$(document).off('touchend.reader').on('touchend.reader', '.reader-page.page-mode', function(e) {
|
||||
if (!isSwiping) {
|
||||
touchStartX = 0;
|
||||
touchStartY = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
const diffX = touchEndX - touchStartX;
|
||||
const threshold = 50; // 滑动阈值
|
||||
|
||||
if (diffX > threshold) {
|
||||
// 向右滑动 - 上一页
|
||||
prevPage();
|
||||
} else if (diffX < -threshold) {
|
||||
// 向左滑动 - 下一页
|
||||
nextPage();
|
||||
}
|
||||
|
||||
touchStartX = 0;
|
||||
touchStartY = 0;
|
||||
touchEndX = 0;
|
||||
touchEndY = 0;
|
||||
isSwiping = false;
|
||||
});
|
||||
|
||||
// 滚动模式:滚动事件
|
||||
let scrollTimer;
|
||||
$(window).off('scroll.reader').on('scroll.reader', function() {
|
||||
if (currentReadingMode !== 'scroll') return;
|
||||
|
||||
// 更新进度条
|
||||
updateProgressIndicator();
|
||||
|
||||
@ -437,7 +701,7 @@ const Reader = (function() {
|
||||
$('#reader-settings').off('click').on('click', showSettings);
|
||||
$('#reader-bookmark').off('click').on('click', showBookmarkModal);
|
||||
|
||||
// 章节内导航按钮
|
||||
// 章节内导航按钮(滚动模式)
|
||||
$(document).off('click.navprev').on('click.navprev', '#nav-prev', prevChapter);
|
||||
$(document).off('click.navnext').on('click.navnext', '#nav-next', nextChapter);
|
||||
|
||||
@ -445,17 +709,48 @@ const Reader = (function() {
|
||||
$('#close-settings').off('click').on('click', hideSettings);
|
||||
$('.settings-overlay').off('click').on('click', hideSettings);
|
||||
|
||||
$('#font-decrease').off('click').on('click', () => changeFontSize(-2));
|
||||
$('#font-increase').off('click').on('click', () => changeFontSize(2));
|
||||
$('#font-decrease').off('click').on('click', () => {
|
||||
changeFontSize(-2);
|
||||
// 翻页模式下重新计算分页
|
||||
if (currentReadingMode === 'page') {
|
||||
setTimeout(() => {
|
||||
calculatePages();
|
||||
showPage(0);
|
||||
}, 100);
|
||||
}
|
||||
});
|
||||
$('#font-increase').off('click').on('click', () => {
|
||||
changeFontSize(2);
|
||||
// 翻页模式下重新计算分页
|
||||
if (currentReadingMode === 'page') {
|
||||
setTimeout(() => {
|
||||
calculatePages();
|
||||
showPage(0);
|
||||
}, 100);
|
||||
}
|
||||
});
|
||||
|
||||
$('.line-height-btn').off('click').on('click', function() {
|
||||
changeLineHeight($(this).data('value'));
|
||||
// 翻页模式下重新计算分页
|
||||
if (currentReadingMode === 'page') {
|
||||
setTimeout(() => {
|
||||
calculatePages();
|
||||
showPage(0);
|
||||
}, 100);
|
||||
}
|
||||
});
|
||||
|
||||
$('.theme-btn').off('click').on('click', function() {
|
||||
changeTheme($(this).data('theme'));
|
||||
});
|
||||
|
||||
// 阅读模式切换按钮
|
||||
$(document).off('click.readingmode').on('click.readingmode', '.reading-mode-btn', function() {
|
||||
const mode = $(this).data('mode');
|
||||
changeReadingMode(mode);
|
||||
});
|
||||
|
||||
// 目录面板
|
||||
$('#close-catalog').off('click').on('click', hideCatalog);
|
||||
$('.catalog-overlay').off('click').on('click', hideCatalog);
|
||||
@ -477,14 +772,32 @@ const Reader = (function() {
|
||||
const note = $('#bookmark-note').val();
|
||||
addBookmark(note);
|
||||
});
|
||||
|
||||
// 窗口大小变化时重新计算分页
|
||||
$(window).off('resize.reader').on('resize.reader', function() {
|
||||
if (currentReadingMode === 'page') {
|
||||
setTimeout(() => {
|
||||
calculatePages();
|
||||
showPage(currentPage);
|
||||
}, 100);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function unbindEvents() {
|
||||
$(document).off('click.reader');
|
||||
$(document).off('click.tapprev');
|
||||
$(document).off('click.tapcenter');
|
||||
$(document).off('click.tapnext');
|
||||
$(document).off('touchstart.reader');
|
||||
$(document).off('touchmove.reader');
|
||||
$(document).off('touchend.reader');
|
||||
$(window).off('scroll.reader');
|
||||
$(window).off('resize.reader');
|
||||
$(document).off('click.navprev');
|
||||
$(document).off('click.navnext');
|
||||
$(document).off('click.catalogitem');
|
||||
$(document).off('click.readingmode');
|
||||
}
|
||||
|
||||
// ========== 退出阅读器 ==========
|
||||
@ -534,7 +847,10 @@ const Reader = (function() {
|
||||
goToChapter,
|
||||
showCatalog,
|
||||
showSettings,
|
||||
showBookmarkModal
|
||||
showBookmarkModal,
|
||||
changeReadingMode,
|
||||
nextPage,
|
||||
prevPage
|
||||
};
|
||||
})();
|
||||
|
||||
|
||||
@ -8,7 +8,7 @@ const Store = (function() {
|
||||
THEME: 'novel_reader_theme',
|
||||
FONT_SIZE: 'novel_reader_font_size',
|
||||
LINE_HEIGHT: 'novel_reader_line_height',
|
||||
READ_MODE: 'novel_reader_read_mode', // 阅读模式: 'page'(翻页) | 'scroll'(滚动)
|
||||
READING_MODE: 'novel_reader_reading_mode', // 阅读模式:scroll(上下滚动) / page(左右翻页)
|
||||
READING_POSITION: 'novel_reader_position_',
|
||||
SHELF_CACHE: 'novel_reader_shelf_cache',
|
||||
HISTORY_CACHE: 'novel_reader_history_cache',
|
||||
@ -23,7 +23,7 @@ const Store = (function() {
|
||||
theme: 'dark',
|
||||
fontSize: 18,
|
||||
lineHeight: 1.8,
|
||||
readMode: 'page' // 默认左右翻页模式
|
||||
readingMode: 'page' // 默认左右翻页模式
|
||||
};
|
||||
|
||||
// ========== 基础存储方法 ==========
|
||||
@ -102,16 +102,15 @@ const Store = (function() {
|
||||
|
||||
// ========== 阅读模式设置 ==========
|
||||
|
||||
function getReadMode() {
|
||||
return get(KEYS.READ_MODE, DEFAULTS.readMode);
|
||||
function getReadingMode() {
|
||||
return get(KEYS.READING_MODE, DEFAULTS.readingMode);
|
||||
}
|
||||
|
||||
function setReadMode(mode) {
|
||||
// mode: 'page' (左右翻页) | 'scroll' (上下滚动)
|
||||
if (mode === 'page' || mode === 'scroll') {
|
||||
set(KEYS.READ_MODE, mode);
|
||||
function setReadingMode(mode) {
|
||||
// mode: 'scroll' (上下滚动) 或 'page' (左右翻页)
|
||||
if (mode === 'scroll' || mode === 'page') {
|
||||
set(KEYS.READING_MODE, mode);
|
||||
}
|
||||
return getReadMode();
|
||||
}
|
||||
|
||||
// ========== 阅读位置缓存 ==========
|
||||
@ -227,6 +226,8 @@ const Store = (function() {
|
||||
setFontSize,
|
||||
getLineHeight,
|
||||
setLineHeight,
|
||||
getReadingMode,
|
||||
setReadingMode,
|
||||
|
||||
// 阅读位置
|
||||
getReadingPosition,
|
||||
|
||||
@ -198,6 +198,19 @@
|
||||
<button id="font-increase">A+</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="settings-group">
|
||||
<label>阅读模式</label>
|
||||
<div class="reading-mode-control">
|
||||
<button class="reading-mode-btn active" data-mode="page">
|
||||
<svg viewBox="0 0 24 24"><path d="M18 2H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2zM6 4h5v8l-2.5-1.5L6 12V4z"/></svg>
|
||||
<span>左右翻页</span>
|
||||
</button>
|
||||
<button class="reading-mode-btn" data-mode="scroll">
|
||||
<svg viewBox="0 0 24 24"><path d="M8 16h8v2H8zm0-4h8v2H8zm6-10H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V8l-6-6zm4 18H6V4h7v5h5v11z"/></svg>
|
||||
<span>上下滚动</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="settings-group">
|
||||
<label>行间距</label>
|
||||
<div class="line-height-control">
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user