Javascript网页设计案例:通过PDF.js实现一款PDF阅读器,包括预览、页面旋转、页面切换、放大缩小、黑夜模式等功能
前言
目前功能包括:
- 切换到首页。
- 切换到尾页。
- 上一页。
- 下一页。
- 添加标签。
- 标签管理
- 页面旋转
- 页面随意拖动
- 双击后还原位置
其实按照自己的预期来说,有很多功能还没有开发完,配色也没有全都搞完,先发出来吧,后期有需要继续添加功能。
功能预览
1.加载后的主页面
白天模式

黑夜模式

2.功能区

一、关于这款PDF阅读器的功能说明
1. 基本布局与样式
- 具有响应式设计,通过
meta标签设置视口以适应不同设备宽度。 - 支持主题切换(明暗模式),定义了一系列CSS变量来管理颜色和布局相关属性,方便切换不同主题风格。
2. 工具栏功能
- 导航功能:包含首页、上一页、下一页、末页的导航按钮,对应
firstPage()、prevPage()、nextPage()、lastPage()函数。 - 缩放功能:有缩小、放大按钮,分别对应
zoomOut()和zoomIn()函数,还提供了一个范围输入控件#zoomControl用于更精确地控制缩放比例。 - 旋转功能:顺时针旋转和逆时针旋转按钮,对应
rotateClockwise()和rotateCounterClockwise()函数。 - 书签功能:可以输入书签名称,点击添加书签按钮(
addBookmark()函数)添加书签,还有书签管理按钮(toggleBookmarkPanel()函数)用于管理已添加的书签。 - 主题切换:有一个主题切换按钮(
toggleTheme()函数),点击可切换明暗主题。
3. 侧边栏与缩略图
- 侧边栏(
.sidebar)用于显示PDF文档的缩略图,缩略图容器为#thumbnails,每个缩略图项(.thumbnail-item)包含一个canvas元素用于显示缩略图,点击缩略图项可进行相关操作。
4. 主内容区域
- 主内容区域(
.main-content)包含PDF文档的显示区域(#pdf-container),其中有一个canvas元素(#pdf-canvas)用于渲染PDF页面,用户可以通过鼠标抓取操作(cursor: -webkit-grab)进行交互。 - 状态栏(
.status-bar)用于显示一些状态信息,如页码等。
5. 模态窗口
- 书签管理模态窗口(
#bookmarks-modal),默认隐藏,用于管理已添加的书签,包含书签列表(#bookmarks-list)和一些操作按钮(.modal-buttons)。
二、Html代码
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css"><title>PDF阅读器</title><style>:root {--primary-color: #2196F3;--hover-color: #1976D2;--background-color: #1a1a1a;--surface-color: #2d2d2d;--toolbar-bg: #333333;--text-color: #ffffff;--error-color: #ff4444;--border-radius: 8px;--gap: 20px;--toolbar-height: 60px;}body {font-family: Arial, sans-serif;margin: 0;padding: 20px;background-color: var(--background-color);color: var(--text-color);box-sizing: border-box;}.pdf-reader-container {display: flex;gap: var(--gap);max-width: 100%;min-width: 800px;margin: 0 auto;background-color: var(--surface-color);border-radius: var(--border-radius);box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);padding: var(--gap) ; /* 0 上下内边距 */margin-top: var(--toolbar-height);box-sizing: border-box;flex-wrap: nowrap;}.toolbar {position: fixed;top: 0;left: 0;right: 0;height: var(--toolbar-height);display: flex;align-items: center;justify-content: space-between;padding: 0 var(--gap);background-color: var(--toolbar-bg);border-radius: 0 0 var(--border-radius) var(--border-radius);box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);z-index: 1000;box-sizing: border-box;}.logo {display: flex;align-items: center;padding: 0 20px;height: 60%;}.logo img {height: 100%;object-fit: contain; transition: transform 0.3s ease; }.toolbar-buttons {display: flex;gap: 10px;}/* 修改按钮样式部分 */button {padding: 8px 12px;font-size: 16px;cursor: pointer;background-color: var(--primary-color);color: var(--text-color);border: none;border-radius: 50%;aspect-ratio: 1/1;transition: all 0.3s ease;display: flex;align-items: center;justify-content: center;width: 40px;height: 40px;position: relative;}button:hover {background-color: var(--hover-color);transform: translateY(-2px);box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);}button::before {font-family: "Font Awesome 5 Free";font-weight: 900;}/* 为每个按钮指定图标 */button:nth-child(1)::before { content: "\f100"; } /* 首页 */button:nth-child(2)::before { content: "\f104"; } /* 上一页 */button:nth-child(3)::before { content: "\f105"; } /* 下一页 */button:nth-child(4)::before { content: "\f101"; } /* 末页 */button:nth-child(5)::before { content: "\f068"; } /* 缩小 */button:nth-child(7)::before { content: "\f067"; } /* 放大 */button:nth-child(8)::before { content: "\f2f9"; } /* 顺时针旋转 */button:nth-child(9)::before { content: "\f2ea"; } /* 逆时针旋转 */button:nth-child(11)::before { content: "\f02e"; } /* 添加书签 */button:nth-child(12)::before { content: "\f02e"; } /* 书签管理 */button span {display: none;}.toolbar-buttons {display: flex;gap: 8px;align-items: center;}#zoomControl {width: 100px;height: 6px;background: var(--surface-color);border-radius: 3px;}#bookmarkLabel {padding: 8px;border-radius: var(--border-radius);border: 1px solid var(--primary-color);background: var(--surface-color);color: var(--text-color);}button::after {content: attr(aria-label);position: absolute;bottom: -30px;left: 50%;transform: translateX(-50%);background: var(--toolbar-bg);color: var(--text-color);padding: 4px 8px;border-radius: 4px;font-size: 12px;white-space: nowrap;opacity: 0;transition: opacity 0.2s;pointer-events: none;}button:hover::after {opacity: 1;}::-webkit-scrollbar {width: 8px;}::-webkit-scrollbar-track {background-color: var(--toolbar-bg);border-radius: 4px;}::-webkit-scrollbar-thumb {background-color: var(--primary-color);border-radius: 4px;}::-webkit-scrollbar-thumb:hover {background-color: var(--hover-color);}/* 侧边栏样式 */.sidebar {flex: 0 0 250px;background-color: var(--toolbar-bg);border-radius: var(--border-radius);padding: 16px;height: calc(100vh - var(--toolbar-height) - var(--gap)*2 - 40px);overflow-y: auto;box-sizing: border-box;}.thumbnail-container {display: flex;flex-direction: column;gap: 10px;}.thumbnail-item {position: relative;cursor: pointer;border-radius: 4px;overflow: hidden;box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);}.thumbnail-item canvas {width: 100%;height: auto;}.thumbnail-item.active {border: 2px solid var(--primary-color);}.main-content {flex: 1;background-color: var(--surface-color);border-radius: var(--border-radius);/* padding: 16px; */height: calc(100vh - var(--toolbar-height) - var(--gap)*2 - 40px);box-sizing: border-box;}#pdf-container {width: 100%;height: 96%;/* height: calc(100vh - var(--toolbar-height) - var(--gap)*2 - 80px - 40px); */border: 1px solid var(--toolbar-bg);border-radius: var(--border-radius);overflow: auto;background-color: #333333;/* padding: 16px; */box-sizing: border-box;overflow-x: hidden;}.status-bar {height: 4%;font-size: 14px;color: var(--text-color);/* padding: 5px; */background-color: var(--toolbar-bg);border-radius: var(--border-radius);margin-top: auto;}.error-message {color: var(--error-color);padding: 10px;margin-top: 10px;background-color: #4d4d4d;border-radius: var(--border-radius);}/* 模态窗口样式 */.modal {display: none;position: fixed;top: 0;left: 0;width: 100%;height: 100%;background-color: rgba(0, 0, 0, 0.5);z-index: 1000;transition: opacity 0.3s ease;}.modal-content {background-color: var(--toolbar-bg);margin: 15% auto;padding: 20px;width: 80%;max-width: 500px;position: relative;border-radius: var(--border-radius);}.close {position: absolute;right: 20px;top: 10px;font-size: 28px;cursor: pointer;color: var(--text-color);}.close:hover {color: var(--primary-color);}#bookmarks-list {list-style-type: none;padding: 0;margin: 0;}#bookmarks-list li {padding: 8px;margin: 4px 0;cursor: pointer;border-radius: 4px;}#bookmarks-list li:hover {background-color: var(--primary-color);color: var(--text-color);}.modal-buttons {margin-top: 20px;}.modal-buttons button {margin: 0 5px;}canvas#pdf-canvas {position: relative;cursor: -webkit-grab;}.theme-toggle {position: relative;display: inline-block;}.light-theme {--background-color: #f9fafb; --surface-color: #ffffff;--toolbar-bg: #e5e7eb; --text-color: #374151;--error-color: #ef4444;--primary-color: #3b82f6;--hover-color: #2563eb; }.light-theme .toolbar {background-color: var(--toolbar-bg);}.light-theme .sidebar {background-color: var(--toolbar-bg);}.light-theme .main-content {background-color: var(--surface-color);}.light-theme button {background-color: var(--primary-color);color: var(--text-color);}.light-theme .status-bar {background-color: var(--toolbar-bg);}</style>
</head>
<body><div class="toolbar"><div class="logo"><img src="logo.png" alt="Logo"></div><div class="toolbar-buttons"><button onclick="firstPage()" aria-label="首页"><span>首页</span></button><button onclick="prevPage()" aria-label="上一页"><span>上一页</span></button><button onclick="nextPage()" aria-label="下一页"><span>下一页</span></button><button onclick="lastPage()" aria-label="末页"><span>末页</span></button><button onclick="zoomOut()" aria-label="缩小"><span>缩小</span></button><input type="range" min="0.5" max="2.0" step="0.1" value="1.0" id="zoomControl"><button onclick="zoomIn()" aria-label="放大"><span>放大</span></button><button onclick="rotateClockwise()" aria-label="顺时针旋转"><span>顺时针旋转</span></button><button onclick="rotateCounterClockwise()" aria-label="逆时针旋转"><span>逆时针旋转</span></button><input type="text" id="bookmarkLabel" placeholder="输入书签名称"><button onclick="addBookmark()" aria-label="添加书签"><span>添加书签</span></button><button onclick="toggleBookmarkPanel()" aria-label="书签管理"><span>书签管理</span></button><button onclick="toggleTheme()" aria-label="切换主题" class="theme-toggle"><i class="fas fa-moon"></i></button></div></div><div class="pdf-reader-container"><div class="sidebar"><div class="thumbnail-container" id="thumbnails"></div></div><div class="main-content"><div id="pdf-container"><canvas id="pdf-canvas"></canvas></div><div class="status-bar" id="status-bar"></div></div></div><div id="bookmarks-modal" class="modal" style="display: none;"><div class="modal-content"><span class="close" onclick="closeBookmarkPanel()">×</span><h3>书签管理</h3><ul id="bookmarks-list"></ul><div class="modal-buttons"><button onclick="addBookmark()">添加书签</button><button onclick="clearBookmarks()">清除书签</button><button onclick="closeBookmarkPanel()">关闭</button></div></div></div><script src="pdf.min.js"></script> <script src="pdf-reader.js"></script>
</body>
</html>
三、Javascript代码
let doc = null;
let currentPage = 1;
let scale = 1.5;
let rotation = 0;
let bookmarks = [];
let isDragging = false;
let lastX = 0;
let lastY = 0;
let offsetX = 0;
let offsetY = 0;let thumbnails = [];const thumbnailsContainer = document.getElementById('thumbnails'); const bookmarksList = document.getElementById('bookmarks-list');
const bookmarksPanel = document.getElementById('bookmarks-panel'); const container = document.getElementById('pdf-container'); // 新增变量用于存储当前视口的偏移量
let viewportOffsetX = 0;
let viewportOffsetY = 0;// 在window.onload 中添加键盘事件监听
window.addEventListener('keydown', function(e) {if (e.key === 'ArrowLeft') {prevPage();} else if (e.key === 'ArrowRight') {nextPage();}
});// 初始化滚动条
const zoomControl = document.getElementById('zoomControl');
zoomControl.value = scale.toString(); // 初始化旋转状态
const savedRotation = localStorage.getItem('pdfRotation');
if (savedRotation !== null) {rotation = parseInt(savedRotation);
}// 加载PDF文件
function loadPDF(fileUrl) {pdfjsLib.getDocument(fileUrl).promise.then(function (loadedDoc) {doc = loadedDoc;const numPages = doc.numPages; loadPage(currentPage);createThumbnails(numPages);// 更新状态栏 document.getElementById('status-bar').textContent =`第 ${currentPage} 页 / 共 ${numPages} 页 | 缩放比例: ${scale * 100}% | 旋转: ${rotation}°`;}).catch(function (error) {console.error('Error loading PDF:', error);showError(`加载PDF时出错:${error.message}`); });
}// 创建缩略图
function createThumbnails(numPages) {thumbnailsContainer.innerHTML = '';for (let i = 1; i <= numPages; i++) {const thumbnailItem = document.createElement('div'); thumbnailItem.className = 'thumbnail-item';thumbnailItem.dataset.page = i;const canvas = document.createElement('canvas'); thumbnailItem.appendChild(canvas); thumbnailsContainer.appendChild(thumbnailItem); loadThumbnail(i, canvas);thumbnailItem.addEventListener('click', function() {currentPage = i;loadPage(currentPage);updateThumbnailsActiveState();});}
}// 更新缩略图活动状态
function updateThumbnailsActiveState() {const items = thumbnailsContainer.querySelectorAll('.thumbnail-item'); items.forEach(item => {item.classList.remove('active'); });const currentItem = thumbnailsContainer.querySelector(`[data-page="${currentPage}"]`); if (currentItem) {currentItem.classList.add('active'); }
}// 加载指定页面
// 修改loadPage函数
function loadPage(pageNum) {if (!doc) {showError('未加载PDF文件,请检查文件路径。');return;}doc.getPage(pageNum).then(function (page) {while (container.firstChild) {container.removeChild(container.firstChild); }const defaultViewport = page.getViewport({ scale: scale });const containerWidth = container.clientWidth; const containerHeight = container.clientHeight; const newScale = Math.min( containerWidth / defaultViewport.width, containerHeight / defaultViewport.height );const finalScale = Math.max(0.5, Math.min(2.0, newScale));const viewport = page.getViewport({ scale: scale,rotation: rotation});const canvas = document.createElement('canvas'); canvas.id = 'pdf-canvas';container.appendChild(canvas); adjustCanvasSize(canvas, viewport);const context = canvas.getContext('2d'); if (!context) {showError('无法获取Canvas上下文,请检查浏览器支持。');return;}page.render({ canvasContext: context,viewport: viewport}).promise.then(() => {console.log('Page rendered successfully');hideError();// 初始化偏移量viewportOffsetX = (container.clientWidth - canvas.width) / 2;viewportOffsetY = 0;updateCanvasPosition();}).catch(error => {console.error('Error rendering page:', error);showError(`渲染页面时出错:${error.message}`); });document.getElementById('status-bar').textContent =`第 ${pageNum} 页 / 共 ${doc.numPages} 页 | 缩放比例: ${Number(scale.toFixed(1)) * 100}% | 旋转: ${rotation}°`;}).catch(error => {console.error('Error getting page:', error);showError(`获取页面时出错:${error.message}`); });}// 调整Canvas尺寸以适应页面内容
function adjustCanvasSize(canvas, viewport) {canvas.width = viewport.width; canvas.height = viewport.height; const containerRect = container.getBoundingClientRect(); const canvasRect = canvas.getBoundingClientRect(); canvas.style.left = `${(containerRect.width - canvasRect.width) / 2}px`;canvas.style.top = `${(containerRect.height - canvasRect.height) / 2}px`;
}// 修改导航函数
function firstPage() {currentPage = 1;loadPage(currentPage);
}function prevPage() {currentPage = Math.max(1, currentPage - 1);loadPage(currentPage);
}function nextPage() {currentPage = Math.min(doc.numPages, currentPage + 1);loadPage(currentPage);
}function lastPage() {currentPage = doc.numPages; loadPage(currentPage);
}// 缩放功能
function zoomIn() {scale = Math.min(2.0, scale + 0.1);zoomControl.value = scale.toString(); updateZoomButtons();loadPage(currentPage);
}function zoomOut() {scale = Math.max(0.5, scale - 0.1);zoomControl.value = scale.toString(); updateZoomButtons();loadPage(currentPage);
}// 错误提示功能
function showError(message) {const errorDiv = document.createElement('div'); errorDiv.className = 'error-message';errorDiv.textContent = message;document.body.appendChild(errorDiv);
}function hideError() {const errorDiv = document.querySelector('.error-message'); if (errorDiv) {errorDiv.remove(); }
}// 旋转功能
function rotateClockwise() {rotation += 90;if (rotation >= 360) rotation = 0;localStorage.setItem('pdfRotation', rotation);loadPage(currentPage);
}function rotateCounterClockwise() {rotation -= 90;if (rotation < 0) rotation += 360;localStorage.setItem('pdfRotation', rotation);loadPage(currentPage);
}// 初始化PDF阅读器
window.onload = function () {const fileUrl = 'https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/web/compressed.tracemonkey-pldi-09.pdf'; loadPDF(fileUrl);// 恢复旋转状态 if (savedRotation !== null) {rotation = parseInt(savedRotation);loadPage(currentPage);}// 加载保存的书签 loadSavedBookmarks();// 新增事件监听const PDF = document.getElementById('pdf-container'); console.log(PDF);PDF.addEventListener('mousedown', startDrag);PDF.addEventListener('mousemove', drag);PDF.addEventListener('mouseup', stopDrag);PDF.addEventListener('wheel', zoomWithWheel);PDF.addEventListener('dblclick', resetPosition);const currentTheme = localStorage.getItem('theme') || 'dark';if (currentTheme === 'light') {document.body.classList.add('light-theme'); }};// 新增拖拽功能
function startDrag(e) {if (e.button === 0) { // 左键点击isDragging = true;lastX = e.clientX; lastY = e.clientY; }
}// 双击还原
function resetPosition(e) {canvas = document.getElementById("pdf-canvas");viewportOffsetX = (container.clientWidth - canvas.width) / 2;viewportOffsetY = 0;updateCanvasPosition();
}function drag(e) {if (isDragging) {const deltaX = e.clientX - lastX;const deltaY = e.clientY - lastY;// 更新偏移量viewportOffsetX += deltaX;viewportOffsetY += deltaY;// 限制偏移范围const canvas = document.getElementById('pdf-canvas'); // 更新canvas位置updateCanvasPosition();lastX = e.clientX; lastY = e.clientY; }
}function stopDrag() {isDragging = false;
}// 新增滚轮缩放功能
function zoomWithWheel(e) {e.preventDefault(); const delta = e.deltaY; if (delta > 0) {zoomOut();} else {zoomIn();}
}// 更新canvas位置
function updateCanvasPosition() {const canvas = document.getElementById('pdf-canvas'); if (canvas) {canvas.style.left = `${viewportOffsetX}px`;canvas.style.top = `${viewportOffsetY}px`;}
}/*** 更新缩放按钮的显示 */
function updateZoomButtons() {const buttons = document.querySelectorAll('button'); buttons.forEach(button => {if (button.onclick === zoomIn) {button.textContent = `放大 (${scale.toFixed(1)})`; } else if (button.onclick === zoomOut) {button.textContent = `缩小 (${scale.toFixed(1)})`; }});
}/*** 处理滚动条输入事件 */
zoomControl.addEventListener('input', function (e) {const inputValue = parseFloat(e.target.value); // 反向计算 scale 值 scale = inputValue - 0.1;updateZoomButtons();// 使用节流处理以优化性能 throttledLoadPage(currentPage);
});/*** 节流函数 * @param {function} func 目标函数 * @param {number} wait 延迟时间(毫秒)* @returns {function} 节流后的函数 */
function throttle(func, wait) {let timeout;return function (...args) {if (!timeout) {func.apply(this, args);timeout = setTimeout(() => {timeout = null;}, wait);}};
}// 对 loadPage 进行节流处理
const throttledLoadPage = throttle(loadPage, 100);// 监听窗口调整大小事件
window.addEventListener('resize', function () {if (doc && currentPage) {loadPage(currentPage);}
});// 切换书签面板显示状态
function toggleBookmarkPanel() {const isHidden = bookmarksPanel.style.display === 'none';bookmarksPanel.style.display = isHidden ? 'block' : 'none';if (isHidden) {loadBookmarks();}
}// 关闭书签面板
function closeBookmarkPanel() {bookmarksPanel.style.display = 'none';
}// 添加当前页面为书签
function addBookmark() {const bookmarkLabel = document.getElementById('bookmarkLabel').value.trim(); if (!bookmarkLabel) {showError('请输入书签名称');return;}const bookmark = {page: currentPage,scale: scale,label: bookmarkLabel };bookmarks.push(bookmark); saveBookmarks();loadBookmarks();document.getElementById('bookmarkLabel').value = ''; // 清空输入框
}// 加载并显示所有书签
function loadBookmarks() {const bookmarksList = document.getElementById('bookmarks-list'); bookmarksList.innerHTML = '';bookmarks.forEach((bookmark, index) => {const li = document.createElement('li'); li.innerHTML = `<span>${bookmark.label}</span> <button onclick="jumpToBookmark(${index})">跳转</button><button onclick="deleteBookmark(${index})">删除</button>`;li.style.backgroundColor = '#4CAF50';li.style.color = 'white';li.style.padding = '8px';li.style.margin = '4px 0';li.style.borderRadius = '4px';bookmarksList.appendChild(li); });
}// 删除指定索引的书签
function deleteBookmark(index) {bookmarks.splice(index, 1);saveBookmarks();loadBookmarks();
}// 清除所有书签
function clearBookmarks() {bookmarks = [];saveBookmarks();loadBookmarks();
}// 跳转到指定书签
function jumpToBookmark(index) {const bookmark = bookmarks[index];currentPage = bookmark.page; scale = bookmark.scale; loadPage(currentPage);
}// 保存书签到 localStorage
function saveBookmarks() {localStorage.setItem('pdfBookmarks', JSON.stringify(bookmarks));
}// 加载保存的书签
function loadSavedBookmarks() {const saved = localStorage.getItem('pdfBookmarks'); if (saved) {bookmarks = JSON.parse(saved); loadBookmarks();}
}function toggleBookmarkPanel() {const modal = document.getElementById('bookmarks-modal'); modal.style.display = 'block';loadBookmarks();
}function closeBookmarkPanel() {const modal = document.getElementById('bookmarks-modal'); modal.style.display = 'none';
}// 加载缩略图
function loadThumbnail(pageNum, canvas) {doc.getPage(pageNum).then(function (page) {const viewport = page.getViewport({ scale: 0.5 });canvas.width = viewport.width; canvas.height = viewport.height; const context = canvas.getContext('2d'); if (!context) return;page.render({ canvasContext: context,viewport: viewport}).promise.then(() => {if (pageNum === currentPage) {thumbnailItem.classList.add('active'); }});});
}function toggleTheme() {document.body.classList.toggle('light-theme'); const root = document.documentElement; root.style.setProperty('--background-color', document.body.classList.contains('light-theme') ? '#f5f5f5' : '#1a1a1a');root.style.setProperty('--surface-color', document.body.classList.contains('light-theme') ? '#ffffff' : '#2d2d2d');root.style.setProperty('--toolbar-bg', document.body.classList.contains('light-theme') ? '#f0f0f0' : '#333333');root.style.setProperty('--text-color', document.body.classList.contains('light-theme') ? '#333333' : '#ffffff');root.style.setProperty('--error-color', document.body.classList.contains('light-theme') ? '#cc0000' : '#ff4444');}
相关文章:
Javascript网页设计案例:通过PDF.js实现一款PDF阅读器,包括预览、页面旋转、页面切换、放大缩小、黑夜模式等功能
前言 目前功能包括: 切换到首页。切换到尾页。上一页。下一页。添加标签。标签管理页面旋转页面随意拖动双击后还原位置 其实按照自己的预期来说,有很多功能还没有开发完,配色也没有全都搞完,先发出来吧,后期有需要…...
各类系统Pycharm安装教程
各类系统Pycharm安装教程 一、安装前的准备 1. 系统要求 操作系统: Windows:Windows 10 或更高版本(64位)。macOS:macOS 10.14 或更高版本。Linux:Ubuntu 18.04+、Fedora 30+ 等主流发行版。硬件要求: 内存:至少 4GB(推荐 8GB 以上)。磁盘空间:至少 2.5GB 可用空间…...
哈希表(C语言版)
文章目录 哈希表原理实现(无自动扩容功能)代码运行结果 分析应用 哈希表 如何统计一段文本中,小写字母出现的次数? 显然,我们可以用数组 int table[26] 来存储每个小写字母出现的次数,而且这样处理,效率奇高。假如我们想知道字…...
内容中台驱动企业数字化内容管理高效协同架构
内容概要 在数字化转型加速的背景下,企业对内容管理的需求从单一存储向全链路协同演进。内容中台作为核心支撑架构,通过统一的内容资源池与智能化管理工具,重塑了内容生产、存储、分发及迭代的流程。其核心价值在于打破部门壁垒,…...
LLaMA-Factory DeepSeek-R1 模型 微调基础教程
LLaMA-Factory 模型 微调基础教程 LLaMA-FactoryLLaMA-Factory 下载 AnacondaAnaconda 环境创建软硬件依赖 详情LLaMA-Factory 依赖安装CUDA 安装量化 BitsAndBytes 安装可视化微调启动 数据集准备所需工具下载使用教程所需数据合并数据集预处理 DeepSeek-R1 可视化微调数据集处…...
vue 文件下载(导出)excel的方法
目前有一个到处功能的需求,这是我用过DeepSeek生成的导出(下载)excel的一个方法。 1.excel的文件名是后端生成的,放在了响应头那里。 2.这里也可以自己制定文件名。 3.axios用的是原生的axios,不要用处理过的ÿ…...
【第4章:循环神经网络(RNN)与长短时记忆网络(LSTM)— 4.3 RNN与LSTM在自然语言处理中的应用案例】
咱今天来聊聊在人工智能领域里,特别重要的两个神经网络:循环神经网络(RNN)和长短时记忆网络(LSTM),主要讲讲它们在自然语言处理里的应用。你想想,平常咱们用手机和别人聊天、看新闻、听语音助手说话,背后说不定就有 RNN 和 LSTM 在帮忙呢! 二、RNN 是什么? (一)…...
LLMs Ollama
LLMs 即大型语言模型(Large Language Models),是人工智能领域基于深度学习的重要技术,以下是关于它的详细介绍: 定义与原理 定义:LLMs 是一类基于深度学习的人工智能模型,通过海量数据和大量计…...
Blackbox.AI:高效智能的生产力工具新选择
前言 在当今数字化时代,一款高效、智能且功能全面的工具对于开发者、设计师以及全栈工程师来说至关重要。Blackbox.AI凭借其独特的产品特点,在众多生产力工具中脱颖而出,成为了我近期测评的焦点。以下是我对Blackbox.AI的详细测评࿰…...
计算机专业知识【 轻松理解数据库四大运算:笛卡尔积、选择、投影与连接】
在数据库的世界里,有几个关键的运算操作,就像是神奇的魔法工具,能帮助我们对数据进行各种处理和组合。今天,咱们就来聊聊笛卡尔积运算、选择运算、投影运算和连接运算这四大运算,用超简单的例子让小白也能轻松理解。 …...
C/C++字符串格式化全解析:从printf到std::format的安全演进与实战指南
目录 C 语言中的格式化函数对比 1. printf / fprintf / sprintf 的异同 C 中的字符串格式化 1. 流式输出 (std::ostringstream) 2. C20/23 格式化库 (std::format,需编译器支持) 跨语言对比与最佳实践 实战建议 总结 C 语言中的格式化函数对比 1. printf / …...
【C++】stack 和 queue 的适配器模式与实现
> 🍃 本系列为初阶C的内容,如果感兴趣,欢迎订阅🚩 > 🎊个人主页:[小编的个人主页])小编的个人主页 > 🎀 🎉欢迎大家点赞👍收藏⭐文章 > ✌️ 🤞 …...
【python】You-Get
文章目录 1、介绍2、安装与使用文档3、下载图片4、下载视频5、下载音乐6、参考 1、介绍 You-Get is a tiny command-line utility to download media contents (videos, audios, images) from the Web, in case there is no other handy way to do it. 源码:https…...
PHP基础部分
但凡是和输入、写入相关的一定要预防别人植入恶意代码! HTML部分 语句格式 <br> <hr> 分割符 <p>插入一行 按住shift 输入! 然后按回车可快速输入html代码(VsCode需要先安装live server插件) html:<h1>标题 数字越大越往后</h1> <p…...
gitee SSH 公钥设置教程
Gitee 提供了基于 SSH 协议的 Git 服务,在使用 SSH 协议访问仓库仓库之前,需要先配置好账户 SSH 公钥。 1、生成秘钥 Windows 用户建议使用 Windows PowerShell 或者 Git Bash,在 命令提示符 下无 cat 和 ls 命令。 ssh-keygen -t ed25519 -C "Gitee SSH Key"中间…...
Java零基础入门笔记:(3)程序控制
前言 本笔记是学习狂神的java教程,建议配合视频,学习体验更佳。 【狂神说Java】Java零基础学习视频通俗易懂_哔哩哔哩_bilibili Scanner对象 之前我们学的基本语法中我们并没有实现程序和人的交互,但是Java给我们提供了这样一个工具类&…...
鸡兔同笼问题
鸡兔同笼问题是这样一个问题: 现有鸡、兔合装在一个笼子里。数头一共100个头,数脚一共300只脚。问有多少只鸡多少只兔? 在这里讨论这个问题的解法当然太小儿科了。但是y_tab这个C语言解释器只提供了1维数组。如果需要用到2维数组时ÿ…...
【Pytorch 库】自定义数据集相关的类
torch.utils.data.Dataset 类torch.utils.data.DataLoader 类自定义数据集示例1. 自定义 Dataset 类2. 在其他 .py 文件中引用和使用该自定义 Dataset torch_geometric.data.Dataset 类torch_geometric.data.Dataset VS torch.utils.data.Dataset 详细信息,参阅 tor…...
electron打包基本教程
从0开始搭建 概要步骤基础软件运行项目打包项目 注意事项 概要 将html打包成桌面的主流有electron和nwjs,nwjs更加简单,但是使用效果不如electron,electron打包比较麻烦,但是效果比较好,反正各有优势和缺点 步骤 基…...
实现pytorch注意力机制-one demo
主要组成部分: 1. 定义注意力层: 定义一个Attention_Layer类,接受两个参数:hidden_dim(隐藏层维度)和is_bi_rnn(是否是双向RNN)。 2. 定义前向传播: 定义了注意力层的…...
多模态2025:技术路线“神仙打架”,视频生成冲上云霄
文|魏琳华 编|王一粟 一场大会,聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中,汇集了学界、创业公司和大厂等三方的热门选手,关于多模态的集中讨论达到了前所未有的热度。其中,…...
C++实现分布式网络通信框架RPC(3)--rpc调用端
目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中,我们已经大致实现了rpc服务端的各项功能代…...
AI Agent与Agentic AI:原理、应用、挑战与未来展望
文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例:使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例:使用OpenAI GPT-3进…...
QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...
【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)
1.获取 authorizationCode: 2.利用 authorizationCode 获取 accessToken:文档中心 3.获取手机:文档中心 4.获取昵称头像:文档中心 首先创建 request 若要获取手机号,scope必填 phone,permissions 必填 …...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
Angular微前端架构:Module Federation + ngx-build-plus (Webpack)
以下是一个完整的 Angular 微前端示例,其中使用的是 Module Federation 和 npx-build-plus 实现了主应用(Shell)与子应用(Remote)的集成。 🛠️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
WebRTC从入门到实践 - 零基础教程
WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC? WebRTC(Web Real-Time Communication)是一个支持网页浏览器进行实时语音…...
HubSpot推出与ChatGPT的深度集成引发兴奋与担忧
上周三,HubSpot宣布已构建与ChatGPT的深度集成,这一消息在HubSpot用户和营销技术观察者中引发了极大的兴奋,但同时也存在一些关于数据安全的担忧。 许多网络声音声称,这对SaaS应用程序和人工智能而言是一场范式转变。 但向任何技…...
