前端开发者如何构建个人工具箱:从工具函数到配置片段的效率实践

news2026/5/16 6:09:20
1. 项目概述一个前端开发者的“百宝箱”仓库在多年的前端开发生涯中我养成了一个习惯每当遇到一个精巧的解决方案、一个高频使用的工具函数或者一个值得反复琢磨的配置片段我都会把它们收集起来。久而久之这些零散的代码片段、配置文件和笔记就汇聚成了一个名为my-js的私人仓库。这个仓库与其说是一个项目不如说是一个前端工程师的“个人工具箱”或“知识沉淀库”。它不追求成为一个完整的、可发布的NPM包而是纯粹服务于个人效率提升和知识体系构建。harryheman/my-js这个标题直白地揭示了它的归属和核心领域——它属于“harryheman”内容聚焦于“我的JavaScript”世界。对于任何一位希望提升开发效率、构建个人技术壁垒的开发者而言建立和维护这样一个仓库其价值远超于代码本身。它能帮你避免重复造轮子快速复用经验并在整理的过程中深化对技术的理解。接下来我将深度拆解构建这样一个“百宝箱”的核心思路、技术选型、组织结构并分享我在维护过程中的实战心得与避坑指南。2. 仓库整体架构与设计哲学2.1 核心定位私人化与实用性的平衡my-js这类仓库的首要设计原则是“为自己服务”。这意味着它的架构不需要考虑广泛的兼容性、极致的性能或完善的文档而应优先考虑检索效率、使用便捷性和个人理解成本。我的设计哲学是模块清晰、即拿即用、注释即文档。仓库不应该是一个黑盒而应该是一个打开就能看懂、复制就能运行的代码集合。因此我放弃了复杂的构建流程和打包工具采用最直接的ES Module组织方式。每个工具函数、每个组件片段、每个配置示例都是一个独立的文件通过清晰的目录结构进行归类。这样当我在新项目中需要一个“深度合并对象”的函数时我无需去NPM寻找也无需回忆多年前写过的代码直接进入仓库的utils/object目录找到deepMerge.js复制即可其函数签名、参数说明和边界情况处理都在文件的注释里写得明明白白。2.2 目录结构规划逻辑分类高于技术分类一个混乱的仓库会迅速失去其价值。我采用的目录结构不是按技术类型如react/,vue/,node/划分而是按解决的问题域进行划分。这是因为在实际开发中我们首先想到的是“我要解决一个什么问题”而不是“我要用哪个框架的技术”。my-js/ ├── utils/ # 纯函数工具库无副作用不依赖特定环境 │ ├── array/ # 数组操作去重、扁平化、分组、排序等 │ ├── object/ # 对象操作合并、克隆、路径取值、类型判断等 │ ├── string/ # 字符串处理格式化、加密、脱敏、模板渲染等 │ ├── function/ # 函数相关节流、防抖、柯里化、记忆化等 │ ├── date/ # 日期时间处理格式化、计算、比较等 │ └── number/ # 数值计算精度处理、随机数、范围映射等 ├── browser/ # 浏览器环境相关API封装与兼容方案 │ ├── storage/ # localStorage/sessionStorage增强封装 │ ├── dom/ # DOM操作快捷方法、事件封装 │ ├── device/ # 设备信息检测UA、横竖屏、网络状态 │ └── performance/ # 性能监控相关代码片段 ├── node/ # Node.js环境下的脚本与工具 │ ├── cli/ # 常用的命令行工具脚本如批量重命名、文件搜索 │ ├── fs/ # 文件系统操作增强递归读写、路径解析 │ └── http/ # 简易HTTP服务器、请求代理片段 ├── config-snippets/ # 各类配置文件片段 │ ├── webpack/ # Webpack不同场景下的配置片段 │ ├── babel/ # Babel配置示例 │ ├── eslint/ # ESLint规则集 │ └── vite/ # Vite配置示例 ├── components/ # 前端UI组件片段非完整组件库 │ ├── vue/ # Vue3组合式API实现的业务通用组件逻辑 │ ├── react/ # React Hooks实现的通用逻辑 │ └── common/ # 纯CSS/HTML实现的通用样式与结构 └── playground/ # 实验场存放一些临时性、探索性的代码注意playground目录非常重要它是一个“缓冲区”。任何新的想法、从网上看到的炫酷代码、不确定是否值得长期保留的片段都先放在这里。定期比如每季度回顾和清理这个目录将其中经过验证、有价值的代码迁移到正式分类中淘汰过时或无用的部分。这能保证核心仓库的简洁和高质量。3. 核心工具函数的设计与实现要点工具函数是my-js仓库的基石。它们必须健壮、清晰、可预测。我为自己制定了一套工具函数编写规范。3.1 函数签名与注释规范每个工具函数文件都必须遵循固定的注释模板这比任何外部文档都有效。以utils/array/chunk.js将数组分割成指定大小的块为例/** * 将给定数组分割成多个指定大小的子数组块。 * * param {Array} array - 需要被分割的原始数组。 * param {number} size - 每个子数组块的大小必须为正整数。 * returns {Array} - 返回一个由子数组构成的新数组。如果原数组为空或size小于等于0则返回空数组。 * throws {TypeError} - 当第一个参数不是数组时抛出。 * * example * chunk([1, 2, 3, 4, 5], 2); // 返回 [[1, 2], [3, 4], [5]] * chunk([1, 2, 3], 5); // 返回 [[1, 2, 3]] * chunk([], 2); // 返回 [] */ export function chunk(array, size 1) { if (!Array.isArray(array)) { throw new TypeError(Expected an array, but got ${typeof array}); } if (!Number.isInteger(size) || size 0) { // 这里选择静默处理返回空数组符合多数工具库的惯例。也可选择抛错根据个人偏好。 return []; } const result []; for (let i 0; i array.length; i size) { result.push(array.slice(i, i size)); } return result; }实操心得throws注释非常关键。它明确告知使用者函数在什么情况下会报错让你在调用时能提前做好防御或错误处理。对于参数校验我的原则是对于外部输入如API响应转换来的参数做宽松处理返回默认值或空结果对于内部调用、预期类型明确的参数做严格校验直接抛错。这能快速定位问题源头。3.2 性能与边缘情况的考量工具函数必须考虑边缘情况Edge Cases。以utils/object/deepClone.js深克隆为例一个简单的递归实现会遇到循环引用和特殊对象如Date, RegExp, Set, Map的问题。/** * 深克隆一个对象或数组支持处理循环引用和常见内置对象。 * param {*} target - 需要克隆的目标 * param {WeakMap} [hash new WeakMap()] - 用于解决循环引用的哈希表内部使用 * returns {*} - 克隆后的新对象 */ export function deepClone(target, hash new WeakMap()) { // 基础类型和函数直接返回 if (target null || typeof target ! object) { return target; } // 处理循环引用 if (hash.has(target)) { return hash.get(target); } // 处理特殊对象类型 const Constructor target.constructor; switch (Constructor) { case Date: return new Date(target.getTime()); case RegExp: return new RegExp(target.source, target.flags); case Set: { const cloneSet new Set(); hash.set(target, cloneSet); target.forEach(val cloneSet.add(deepClone(val, hash))); return cloneSet; } case Map: { const cloneMap new Map(); hash.set(target, cloneMap); target.forEach((val, key) cloneMap.set(key, deepClone(val, hash))); return cloneMap; } // 可以继续添加其他需要特殊处理的对象如Error, ArrayBuffer等 } // 处理普通对象和数组 const cloneObj new Constructor(); // 保持原型链 hash.set(target, cloneObj); // 使用 Reflect.ownKeys 获取所有自身属性包括Symbol for (let key of Reflect.ownKeys(target)) { // 这里可以添加过滤逻辑例如跳过某些属性 cloneObj[key] deepClone(target[key], hash); } return cloneObj; }提示深克隆是一个复杂问题上述实现覆盖了大部分日常场景但对于Function、Promise、DOM元素等克隆行为需要根据具体业务定义。在my-js中我通常会标注这个函数的局限性并在playground里存放更复杂场景的实验代码。4. 浏览器与Node.js环境特定代码的封装4.1 浏览器API的优雅降级与统一封装浏览器环境碎片化严重封装的目的在于提供一致的API体验。以browser/storage/storage.js为例我不仅封装了localStorage还增加了过期时间、序列化/反序列化、命名空间等功能。/** * 增强型本地存储封装 */ class EnhancedStorage { constructor(namespace myApp, driver localStorage) { this.namespace namespace; this.driver driver; this.prefix ${namespace}:; } _makeKey(key) { return this.prefix key; } set(key, value, options {}) { const storeItem { data: value, _expiry: options.expires ? Date.now() options.expires : null, _created: Date.now() }; try { this.driver.setItem(this._makeKey(key), JSON.stringify(storeItem)); return true; } catch (e) { // 存储满时尝试清理过期数据后重试 if (e.name QuotaExceededError) { this._clearExpired(); try { this.driver.setItem(this._makeKey(key), JSON.stringify(storeItem)); return true; } catch (e2) { console.warn(Storage is still full after clearing expired items.); return false; } } return false; } } get(key) { const itemStr this.driver.getItem(this._makeKey(key)); if (!itemStr) return null; try { const item JSON.parse(itemStr); // 检查是否过期 if (item._expiry Date.now() item._expiry) { this.remove(key); return null; } return item.data; } catch (e) { // 数据被破坏清除之 this.remove(key); return null; } } // ... 其他方法remove, clear, keys, _clearExpired 等 } // 提供默认实例和创建工厂 export const myStorage new EnhancedStorage(myJs); export const createStorage (namespace, driver) new EnhancedStorage(namespace, driver);踩坑记录localStorage的setItem在存储空间已满时会抛出QuotaExceededError异常直接崩溃程序。上述封装提供了简单的清理重试机制虽然不能完全解决问题但避免了程序崩溃并在控制台给出友好提示。对于更重要的数据应考虑使用indexedDB相关封装片段可以放在browser/storage/indexedDB-wrapper.js中。4.2 Node.js实用脚本提升日常效率node/cli/目录下的脚本是我命令行效率的延伸。例如一个快速创建项目模板的脚本node/cli/create-project.js#!/usr/bin/env node // 注意文件顶部的 shebang使其可直接运行 import fs from fs/promises; import path from path; import { fileURLToPath } from url; import { dirname } from path; import inquirer from inquirer; // 需要安装 inquirer 包 const __filename fileURLToPath(import.meta.url); const __dirname dirname(__filename); const TEMPLATES { vue3-vite: templates/vue3-vite, react-vite-ts: templates/react-vite-ts, node-express: templates/node-express, // ... 其他模板 }; async function main() { const answers await inquirer.prompt([ { type: input, name: projectName, message: 请输入项目名称, validate: input input.trim() ! || 项目名称不能为空 }, { type: list, name: template, message: 请选择项目模板, choices: Object.keys(TEMPLATES) }, { type: confirm, name: installDep, message: 是否立即安装依赖, default: true } ]); const targetDir path.join(process.cwd(), answers.projectName); const templateDir path.join(__dirname, .., .., TEMPLATES[answers.template]); // 检查目标目录是否存在 try { await fs.access(targetDir); console.error(错误目录 ${targetDir} 已存在); process.exit(1); } catch {} // 复制模板文件 console.log(正在创建项目 ${answers.projectName}...); await copyDir(templateDir, targetDir); // 更新 package.json 中的项目名 const pkgPath path.join(targetDir, package.json); const pkg JSON.parse(await fs.readFile(pkgPath, utf-8)); pkg.name answers.projectName; await fs.writeFile(pkgPath, JSON.stringify(pkg, null, 2)); console.log(项目创建成功目录${targetDir}); if (answers.installDep) { const { execa } await import(execa); // 动态导入避免无此依赖时报错 console.log(正在安装依赖使用pnpm...); process.chdir(targetDir); await execa(pnpm, [install], { stdio: inherit }); // 使用pnpm可改为npm或yarn console.log(依赖安装完成); } } // 递归复制目录的辅助函数 async function copyDir(src, dest) { await fs.mkdir(dest, { recursive: true }); const entries await fs.readdir(src, { withFileTypes: true }); for (let entry of entries) { const srcPath path.join(src, entry.name); const destPath path.join(dest, entry.name); if (entry.isDirectory()) { await copyDir(srcPath, destPath); } else { await fs.copyFile(srcPath, destPath); } } } main().catch(console.error);实操心得这类脚本的核心价值在于自动化重复劳动。我将常用的项目结构如Vue3VitePiniaElement Plus做成模板放在templates/目录下。每次新建项目运行node create-project.js回答几个问题一个配置好基础路由、状态管理、代码规范和常用工具函数的项目骨架就生成了节省了大量复制粘贴和配置的时间。关键在于模板要保持更新与主流技术栈同步。5. 配置片段的管理与版本化config-snippets/目录是应对前端工程化配置复杂性的利器。Webpack、Babel、ESLint、Prettier等工具的配置经常需要根据项目微调记住所有细节是不可能的。5.1 Webpack配置的模块化拆解我不会保存一个完整的、庞大的webpack.config.js而是将其拆解成按功能划分的片段。config-snippets/webpack/ ├── base.js # 基础配置入口、输出、模块解析 ├── dev.js # 开发环境devServer、sourceMap ├── prod.js # 生产环境压缩、代码分割、资源优化 ├── rules/ # 各种loader配置 │ ├── javascript.js │ ├── vue.js │ ├── react.js │ ├── css.js # 处理CSS、Less、Sass │ └── assets.js # 处理图片、字体等 └── plugins/ # 常用插件配置 ├── html.js # HtmlWebpackPlugin ├── clean.js # CleanWebpackPlugin └── bundle-analyzer.js # WebpackBundleAnalyzer每个文件导出一个配置对象或函数。当需要组合时使用webpack-merge// 在项目中的 webpack.config.js const { merge } require(webpack-merge); const baseConfig require(./config-snippets/webpack/base); const devConfig require(./config-snippets/webpack/dev); const cssRules require(./config-snippets/webpack/rules/css); module.exports merge(baseConfig, devConfig, { module: { rules: [cssRules] } });注意事项配置片段必须注明其适用的Webpack版本和核心依赖包版本。因为Webpack的配置项在不同大版本间可能有破坏性更新。我会在文件顶部用注释清晰标明// Webpack 5 配置片段 // 依赖css-loader^6.x, style-loader^3.x, postcss-loader^7.x5.2 ESLint与Prettier配置的个性化组合每个人和每个团队的代码风格偏好不同。我的config-snippets/eslint/目录下存放了多种预设eslint/recommended.js: 继承自eslint:recommended的基础规则。eslint/vue3.js: 针对Vue3项目的规则包含vuejs-accessibility等插件。eslint/react.js: 针对React项目的规则。eslint/typescript.js: 针对TypeScript的规则。eslint/stylistic.js: 我自己偏好的代码风格规则如引号、分号、缩进等这部分与Prettier可能重叠需要仔细处理优先级。然后在项目根目录的.eslintrc.js中我可以像搭积木一样组合module.exports { root: true, extends: [ ./config-snippets/eslint/recommended, ./config-snippets/eslint/vue3, ./config-snippets/eslint/typescript, ./config-snippets/eslint/stylistic ], parserOptions: { project: ./tsconfig.json }, rules: { // 项目级别的规则覆盖 no-console: process.env.NODE_ENV production ? warn : off, } };避坑技巧ESLint的风格规则如quotes,semi很容易与Prettier冲突。我的解决方案是使用eslint-config-prettier禁用所有与格式相关的ESLint规则将格式问题完全交给Prettier处理。在eslint/stylistic.js中我只保留那些与代码质量、潜在错误相关的规则如no-unused-vars,eqeqeq而将所有关于空格、换行、引号的规则都移除。6. 组件片段的积累与复用逻辑components/目录存放的不是完整的、可发布的组件库而是可复用的业务逻辑片段和高频UI模式。它们的价值在于其思想而非样式。6.1 Vue3组合式函数Composables例如一个管理模态框Modal显示状态的组合式函数components/vue/useModal.jsimport { ref, computed } from vue; /** * 用于管理模态框显示/隐藏状态的组合式函数 * param {Object} options - 配置选项 * param {boolean} options.initialVisible - 初始是否可见默认为false * param {Function} options.beforeOpen - 打开前的钩子返回false可阻止打开 * param {Function} options.afterClose - 关闭后的钩子 * returns {Object} - 返回状态和方法 */ export function useModal(options {}) { const { initialVisible false, beforeOpen, afterClose } options; const visible ref(initialVisible); const loading ref(false); // 可用于提交时的加载状态 const open async (...args) { if (beforeOpen) { const shouldOpen await Promise.resolve(beforeOpen(...args)); if (shouldOpen false) return; } visible.value true; }; const close async (...args) { visible.value false; if (afterClose) { await Promise.resolve(afterClose(...args)); } }; const toggle () { visible.value ? close() : open(); }; // 一个计算属性常用于绑定到模态框组件的 v-model 或 :visible const modelValue computed({ get: () visible.value, set: (val) { val ? open() : close(); } }); return { // 状态 visible, loading, // 方法 open, close, toggle, // 用于v-model的便捷属性 modelValue }; } // 在组件中的使用示例 /* import { useModal } from /components/vue/useModal; export default { setup() { const modal useModal({ beforeOpen: () { console.log(将要打开模态框); // 可以在这里做数据初始化 return true; // 返回false会阻止打开 }, afterClose: () { console.log(模态框已关闭); // 可以在这里做清理工作 } }); const handleSubmit async () { modal.loading.value true; try { await api.submit(); modal.close(); } catch (error) { console.error(error); } finally { modal.loading.value false; } }; return { ...modal, handleSubmit }; } }; */这个useModal抽象了模态框的通用状态逻辑在任何需要弹窗的组件中都可以直接复用避免了在每个组件里重复定义visible、loading和open/close方法。6.2 通用业务逻辑HookReact同理在React中components/react/usePagination.js封装了分页逻辑import { useState, useMemo, useCallback } from react; /** * 分页逻辑Hook * param {Object} options * param {number} options.initialPage - 初始页码默认为1 * param {number} options.initialPageSize - 初始每页大小默认为10 * param {number} options.total - 数据总数默认为0 * returns {Object} 分页状态与方法 */ export function usePagination(options {}) { const { initialPage 1, initialPageSize 10, total 0 } options; const [current, setCurrent] useState(initialPage); const [pageSize, setPageSize] useState(initialPageSize); // 计算总页数 const totalPage useMemo(() { return Math.ceil(total / pageSize) || 1; }, [total, pageSize]); // 跳转到指定页 const goToPage useCallback((page) { const validPage Math.max(1, Math.min(page, totalPage)); setCurrent(validPage); return validPage; }, [totalPage]); // 改变每页大小 const changePageSize useCallback((newSize) { setPageSize(newSize); // 通常改变pageSize后需要重新计算当前页是否有效这里简单跳回第一页 setCurrent(1); }, []); // 上一页/下一页 const prevPage useCallback(() goToPage(current - 1), [current, goToPage]); const nextPage useCallback(() goToPage(current 1), [current, goToPage]); // 是否在第一页/最后一页 const isFirstPage current 1; const isLastPage current totalPage; // 获取当前页的数据范围用于显示 const range useMemo(() { const start (current - 1) * pageSize 1; const end Math.min(current * pageSize, total); return { start, end }; }, [current, pageSize, total]); return { // 状态 current, pageSize, total, totalPage, // 计算属性 isFirstPage, isLastPage, range, // 方法 setCurrent: goToPage, // 别名更语义化 goToPage, changePageSize, prevPage, nextPage }; }经验之谈积累这类组件片段的关键在于抽象层级。不要过早抽象当一个模式在三个以上不同的地方出现时再考虑将其抽离到my-js仓库中。同时片段要保持“纯净”只处理状态和逻辑不包含任何UI和样式这样才能实现最大程度的复用。7. 仓库的维护、更新与知识内化拥有一个my-js仓库只是开始如何让它持续产生价值避免变成“代码坟墓”才是关键。7.1 定期回顾与重构我设定了一个季度回顾机制。每个季度末我会花几个小时浏览整个仓库删除过时内容检查playground/和各个目录删除那些已经不再使用、或有更好替代方案的代码。更新依赖版本检查config-snippets/中的配置片段确保其注释里标明的依赖版本与当前主流版本没有太大脱节。重构与优化用更新的知识审视旧代码。例如早期可能用for循环实现的工具函数现在可以用更简洁的Array.prototype.reduce或新的语法糖重写并更新注释。补充测试用例对于核心的utils/函数逐步补充简单的测试用例可以使用Node.js自带的assert模块放在同目录的*.test.js文件中确保其行为符合预期。7.2 建立个人知识索引my-js仓库本身就是一个结构化的知识库。但为了更快地检索我维护了一个简单的README.md在根目录它不描述项目而是作为一个索引和更新日志。# My JavaScript Toolbox 这是一个个人前端工具与代码片段仓库按领域分类。 ## 快速索引 ### 高频工具函数 - **数组分组**: utils/array/chunk.js - **对象深克隆**: utils/object/deepClone.js (支持循环引用、Set/Map) - **函数防抖/节流**: utils/function/debounce.js, utils/function/throttle.js - **日期格式化**: utils/date/format.js ### 浏览器环境 - **增强存储**: browser/storage/storage.js (带过期时间、命名空间) - **URL参数解析**: browser/url/parseQuery.js - **图片懒加载**: browser/performance/lazyLoad.js (IntersectionObserver实现) ### 项目配置 - **Vite Vue3 TypeScript**: 见 config-snippets/vite/vue3-ts/ - **ESLint规则集**: config-snippets/eslint/ (组合使用) - **Git提交规范**: 见 config-snippets/git/commitlint.config.js ### React/Vue 逻辑片段 - **通用分页Hook**: components/react/usePagination.js - **模态框状态管理**: components/vue/useModal.js - **无限滚动列表**: components/common/useInfiniteScroll.js (框架无关) ## 最近更新 (2024-05) - 重构 deepClone增加对 URL 对象的支持。 - 新增 useFetch Hook (components/react/useFetch.js)封装请求状态。 - 更新Webpack生产配置片段支持Webpack 5的 asset modules。 ## 使用原则 1. **即拿即用**每个文件应独立、清晰通过注释了解用法。 2. **按需复制**不建议直接npm link或作为子模块引入。将需要的文件复制到项目中并根据项目上下文进行调整。 3. **理解优先**复制代码前请花几分钟阅读实现确保你理解它在做什么。这个README让我能在一分钟内找到所需内容而“最近更新”部分则强迫我定期为仓库注入新内容。7.3 从“收集”到“创造”的转变维护my-js的最终目的不是成为一个代码搬运工而是促进知识的内化和能力的提升。当你面对一个新问题并最终将它优雅地解决后思考一下这个解决方案是否有通用性是否可以抽象成模式如果可以就把它添加到仓库中并写下清晰的注释。这个过程本身就是一次深度的学习和技术沉淀。久而久之你会发现很多新问题不过是旧问题的变体你可以从容地从你的“百宝箱”里找到或组合出解决方案开发效率和质量都会得到质的提升。这个仓库最终会成为你个人技术能力最直观、最坚实的体现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2617320.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…