基于Node.js搭建CHORD-X报告生成与管理后台

news2026/3/21 15:26:27
基于Node.js搭建CHORD-X报告生成与管理后台最近在做一个数据分析项目需要定期生成结构化的报告。手动整理数据、写文档、再导出PDF一套流程下来半天时间就没了。后来我们团队接触到了CHORD-X一个专门用于生成分析报告的智能工具效果确实不错。但问题来了每次生成报告都得手动操作没法批量处理也没法集成到我们自己的系统里。于是我就琢磨着能不能自己搭一个轻量级的后台把CHORD-X的报告生成能力“包装”起来变成一个可以随时调用的服务。这样一来其他系统或者团队成员只需要通过简单的API调用就能自动生成报告还能统一管理所有的报告模板和生成结果。这个想法听起来挺复杂但用Node.js和Express框架来实现其实比想象中要简单。今天我就来分享一下我是怎么一步步把这个后台搭起来的从环境准备到API设计再到用户认证希望能给有类似需求的全栈开发者提供一个清晰的参考思路。1. 项目目标与环境准备我们的目标是构建一个Web后台它主要干四件事接收外部请求提交报告生成任务。管理报告模板比如上传新的模板文件。处理生成好的报告存起来并提供下载。加一道简单的“门禁”确保只有授权用户才能使用。1.1 技术栈选择为什么选Node.js和Express原因很简单快、轻、生态好。对于这种需要快速处理I/O操作比如文件上传、API响应的后台服务Node.js的非阻塞特性非常合适。Express则是Node.js生态里最流行的Web框架用它来搭建RESTful API就像搭积木一样方便。除了它们我们还需要一些帮手Multer 专门处理文件上传的中间件用它来接收用户上传的报告模板。jsonwebtoken (JWT) 用来实现用户认证生成和验证访问令牌。一个数据库 这里为了简单我用SQLite。它不需要单独安装数据库服务一个文件就搞定非常适合原型开发和小型应用。当然你也可以换成MySQL或PostgreSQL。一个CHORD-X的客户端SDK或API 这是核心我们需要通过它来真正调用CHORD-X的报告生成能力。这里假设CHORD-X提供了Node.js的SDK包。1.2 Node.js安装及环境配置如果你还没装Node.js先去官网下载安装包。建议选择LTS长期支持版本比较稳定。安装过程就是一路下一步很简单。安装完成后打开终端Windows上是命令提示符或PowerShellMac/Linux上是Terminal输入以下命令检查是否安装成功node --version npm --version如果能看到版本号比如v18.17.0和9.6.7说明安装没问题。npm是Node.js的包管理器我们后面安装各种依赖库全靠它。接下来我们创建一个项目文件夹并初始化它mkdir chordx-report-backend cd chordx-report-backend npm init -y这个npm init -y命令会快速生成一个package.json文件里面记录了项目的基本信息和依赖。现在安装我们需要的依赖包npm install express multer jsonwebtoken sqlite3 dotenv npm install --save-dev nodemonexpress: 我们的Web框架。multer: 处理文件上传。jsonwebtoken: 用户认证。sqlite3: 操作SQLite数据库。dotenv: 管理环境变量比如数据库路径、JWT密钥等敏感信息。nodemon: 开发工具它会监视文件变化并自动重启服务器省去我们手动重启的麻烦。安装完成后你的package.json文件里的dependencies和devDependencies部分应该能看到这些包。最后在项目根目录创建一个.env文件用来存放环境变量PORT3000 JWT_SECRETyour_super_secret_jwt_key_change_this DB_PATH./reports.db UPLOAD_PATH./uploads记得把JWT_SECRET换成你自己的一串复杂随机字符串。这个文件不要提交到代码仓库记得把它加到.gitignore里。2. 核心功能设计与实现环境准备好了我们开始敲代码。我会按照功能模块来讲解你可以跟着一步步来。2.1 项目结构与入口文件先创建基本的项目结构chordx-report-backend/ ├── node_modules/ ├── uploads/ # 存放上传的模板和生成的报告 ├── .env ├── .gitignore ├── package.json ├── app.js # 主应用文件 ├── routes/ # 路由文件 │ ├── auth.js │ ├── templates.js │ └── reports.js ├── controllers/ # 控制器处理业务逻辑 │ ├── authController.js │ ├── templateController.js │ └── reportController.js ├── models/ # 数据模型 │ └── db.js └── middleware/ # 自定义中间件 └── auth.js首先创建主文件app.js// app.js const express require(express); const dotenv require(dotenv); const path require(path); // 加载环境变量 dotenv.config(); const app express(); const PORT process.env.PORT || 3000; // 中间件解析JSON请求体 app.use(express.json()); // 中间件解析URL编码的请求体来自表单提交 app.use(express.urlencoded({ extended: true })); // 静态文件服务让uploads文件夹可以通过URL访问 app.use(/uploads, express.static(path.join(__dirname, uploads))); // 引入路由 const authRoutes require(./routes/auth); const templateRoutes require(./routes/templates); const reportRoutes require(./routes/reports); // 使用路由 app.use(/api/auth, authRoutes); app.use(/api/templates, templateRoutes); app.use(/api/reports, reportRoutes); // 简单的根路由用于健康检查 app.get(/, (req, res) { res.json({ message: CHORD-X Report Backend is running! }); }); // 启动服务器 app.listen(PORT, () { console.log(Server is running on http://localhost:${PORT}); });2.2 数据库模型初始化在models/db.js中我们初始化SQLite数据库并创建必要的表。// models/db.js const sqlite3 require(sqlite3).verbose(); const path require(path); const dbPath process.env.DB_PATH || ./reports.db; // 创建数据库连接 const db new sqlite3.Database(dbPath, (err) { if (err) { console.error(Could not connect to database, err); } else { console.log(Connected to SQLite database.); initDb(); } }); function initDb() { // 用户表 db.run(CREATE TABLE IF NOT EXISTS users ( id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT UNIQUE NOT NULL, password_hash TEXT NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP )); // 报告模板表 db.run(CREATE TABLE IF NOT EXISTS templates ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, file_path TEXT NOT NULL, uploader_id INTEGER, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (uploader_id) REFERENCES users (id) )); // 报告任务表 db.run(CREATE TABLE IF NOT EXISTS report_tasks ( id INTEGER PRIMARY KEY AUTOINCREMENT, template_id INTEGER, input_data TEXT, -- 存储JSON格式的输入参数 status TEXT DEFAULT pending, -- pending, processing, completed, failed output_file_path TEXT, error_message TEXT, created_by INTEGER, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (template_id) REFERENCES templates (id), FOREIGN KEY (created_by) REFERENCES users (id) )); console.log(Database tables initialized (if they did not exist).); } module.exports db;2.3 用户认证与授权我们使用JWT来实现无状态的认证。用户先登录获取一个令牌Token之后在请求需要认证的API时在HTTP头里带上这个令牌。首先创建认证中间件middleware/auth.js// middleware/auth.js const jwt require(jsonwebtoken); const authMiddleware (req, res, next) { // 从请求头中获取token const authHeader req.headers[authorization]; const token authHeader authHeader.split( )[1]; // 格式Bearer token if (!token) { return res.status(401).json({ error: Access token is required }); } jwt.verify(token, process.env.JWT_SECRET, (err, user) { if (err) { return res.status(403).json({ error: Invalid or expired token }); } // 将解码后的用户信息挂载到请求对象上方便后续使用 req.user user; next(); }); }; module.exports authMiddleware;然后创建认证相关的控制器controllers/authController.js和路由routes/auth.js。为了简化我们这里实现一个简单的注册和登录密码使用bcrypt加密但为了减少依赖示例中先省略加密步骤实际生产环境必须加密。// controllers/authController.js const jwt require(jsonwebtoken); const db require(../models/db); // 用户登录 const login (req, res) { const { username, password } req.body; // 实际应用中这里应该查询数据库并验证加密后的密码 // 此处为演示假设有一个固定用户 if (username admin password password123) { // 生成JWT令牌有效期为1小时 const token jwt.sign( { username: username, userId: 1 }, process.env.JWT_SECRET, { expiresIn: 1h } ); res.json({ token }); } else { res.status(401).json({ error: Invalid username or password }); } }; // 用户注册示例实际需要密码加密和更严格的验证 const register async (req, res) { const { username, password } req.body; // 这里应该先检查用户名是否存在然后对密码进行哈希处理再存入数据库 // 示例代码省略了这些步骤 res.status(201).json({ message: User registered (demo) }); }; module.exports { login, register };// routes/auth.js const express require(express); const router express.Router(); const { login, register } require(../controllers/authController); router.post(/login, login); router.post(/register, register); module.exports router;2.4 报告模板管理这个模块负责让用户上传和管理报告模板文件比如.docx, .html文件。我们使用multer来处理文件上传。首先配置multer。在项目根目录创建一个config/multerConfig.js记得先创建config文件夹// config/multerConfig.js const multer require(multer); const path require(path); // 设置存储引擎和文件名 const storage multer.diskStorage({ destination: function (req, file, cb) { cb(null, process.env.UPLOAD_PATH || ./uploads/templates); }, filename: function (req, file, cb) { // 生成唯一文件名时间戳-原始文件名 const uniqueSuffix Date.now() - Math.round(Math.random() * 1E9); cb(null, uniqueSuffix path.extname(file.originalname)); } }); // 文件过滤器可选限制文件类型 const fileFilter (req, file, cb) { const allowedTypes [.docx, .html, .txt]; // 允许的模板文件类型 const ext path.extname(file.originalname).toLowerCase(); if (allowedTypes.includes(ext)) { cb(null, true); } else { cb(new Error(Invalid file type. Only .docx, .html, .txt are allowed.)); } }; const upload multer({ storage: storage, fileFilter: fileFilter, limits: { fileSize: 10 * 1024 * 1024 } // 限制10MB }); module.exports upload;然后创建模板控制器和路由// controllers/templateController.js const db require(../models/db); const path require(path); // 上传模板 const uploadTemplate (req, res) { if (!req.file) { return res.status(400).json({ error: No template file uploaded. }); } const { name } req.body; const filePath /uploads/templates/${req.file.filename}; // 存储相对路径 const uploaderId req.user.userId; // 从认证中间件获取 const sql INSERT INTO templates (name, file_path, uploader_id) VALUES (?, ?, ?); db.run(sql, [name, filePath, uploaderId], function(err) { if (err) { return res.status(500).json({ error: Failed to save template info to database. }); } res.status(201).json({ message: Template uploaded successfully., templateId: this.lastID, filePath: filePath }); }); }; // 获取模板列表 const getTemplates (req, res) { const sql SELECT id, name, file_path, created_at FROM templates ORDER BY created_at DESC; db.all(sql, [], (err, rows) { if (err) { return res.status(500).json({ error: Failed to fetch templates. }); } res.json(rows); }); }; module.exports { uploadTemplate, getTemplates };// routes/templates.js const express require(express); const router express.Router(); const upload require(../config/multerConfig); const authMiddleware require(../middleware/auth); const { uploadTemplate, getTemplates } require(../controllers/templateController); // 所有模板相关操作都需要认证 router.use(authMiddleware); // 上传模板单个文件字段名为templateFile router.post(/upload, upload.single(templateFile), uploadTemplate); // 获取模板列表 router.get(/, getTemplates); module.exports router;2.5 报告生成任务管理这是最核心的部分。我们设计一个异步任务处理流程用户提交一个任务请求选择模板、提供数据。后台立即创建一个pending状态的任务记录并返回任务ID。后台异步调用CHORD-X服务生成报告。生成完成后更新任务状态为completed并存储报告文件路径如果失败则更新为failed并记录错误信息。由于CHORD-X的调用可能是耗时的我们这里用一个简单的模拟来处理。在实际项目中你可能需要使用消息队列如Bull和独立的Worker进程。首先创建报告控制器// controllers/reportController.js const db require(../models/db); const { simulateChordXGeneration } require(../services/chordxService); // 假设的CHORD-X服务 // 提交报告生成任务 const submitReportTask (req, res) { const { templateId, inputData } req.body; // inputData 是JSON字符串或对象 const createdBy req.user.userId; const sql INSERT INTO report_tasks (template_id, input_data, created_by, status) VALUES (?, ?, ?, pending); db.run(sql, [templateId, JSON.stringify(inputData), createdBy], function(err) { if (err) { return res.status(500).json({ error: Failed to create report task. }); } const taskId this.lastID; // **关键异步处理报告生成** // 立即响应告知任务已接收 res.status(202).json({ message: Report generation task submitted successfully., taskId: taskId, statusUrl: /api/reports/tasks/${taskId}/status }); // 异步调用生成函数 processReportTask(taskId, templateId, inputData); }); }; // 异步处理任务的函数 async function processReportTask(taskId, templateId, inputData) { try { // 1. 更新任务状态为 processing db.run(UPDATE report_tasks SET status processing, updated_at CURRENT_TIMESTAMP WHERE id ?, [taskId]); // 2. 模拟调用CHORD-X服务生成报告 // 这里需要你根据CHORD-X的实际API或SDK进行替换 const outputFilePath await simulateChordXGeneration(templateId, inputData); // 假设 simulateChordXGeneration 返回生成报告的文件路径如 /uploads/reports/report_123.pdf // 3. 任务成功更新状态和输出路径 db.run(UPDATE report_tasks SET status completed, output_file_path ?, updated_at CURRENT_TIMESTAMP WHERE id ?, [outputFilePath, taskId]); console.log(Task ${taskId} completed successfully.); } catch (error) { // 4. 任务失败更新状态和错误信息 console.error(Task ${taskId} failed:, error); db.run(UPDATE report_tasks SET status failed, error_message ?, updated_at CURRENT_TIMESTAMP WHERE id ?, [error.message, taskId]); } } // 查询任务状态 const getTaskStatus (req, res) { const { taskId } req.params; const sql SELECT id, status, output_file_path, error_message, created_at, updated_at FROM report_tasks WHERE id ?; db.get(sql, [taskId], (err, row) { if (err) { return res.status(500).json({ error: Database error. }); } if (!row) { return res.status(404).json({ error: Task not found. }); } res.json(row); }); }; // 获取报告文件提供下载 const downloadReport (req, res) { const { taskId } req.params; const sql SELECT output_file_path, status FROM report_tasks WHERE id ?; db.get(sql, [taskId], (err, row) { if (err || !row) { return res.status(404).json({ error: Report not found. }); } if (row.status ! completed) { return res.status(400).json({ error: Report is not ready. Current status: ${row.status} }); } // 假设文件存储在项目根目录下的uploads文件夹 const filePath path.join(__dirname, .., row.output_file_path); res.download(filePath); // Express 提供的方法触发文件下载 }); }; // 获取用户的任务列表 const getUserTasks (req, res) { const userId req.user.userId; const sql SELECT id, template_id, status, created_at FROM report_tasks WHERE created_by ? ORDER BY created_at DESC; db.all(sql, [userId], (err, rows) { if (err) { return res.status(500).json({ error: Failed to fetch tasks. }); } res.json(rows); }); }; module.exports { submitReportTask, getTaskStatus, downloadReport, getUserTasks };然后创建一个模拟的CHORD-X服务文件services/chordxService.js// services/chordxService.js const path require(path); const fs require(fs).promises; // 这是一个模拟函数实际应替换为真正的CHORD-X API调用 async function simulateChordXGeneration(templateId, inputData) { console.log(Simulating CHORD-X generation for template ${templateId} with data:, inputData); // 模拟处理耗时 await new Promise(resolve setTimeout(resolve, 3000)); // 模拟生成一个PDF文件 const fileName report_${Date.now()}.pdf; const outputDir path.join(__dirname, .., uploads, reports); const outputPath /uploads/reports/${fileName}; const fullOutputPath path.join(__dirname, .., outputPath); // 确保目录存在 await fs.mkdir(path.dirname(fullOutputPath), { recursive: true }); // 这里实际应该调用CHORD-X SDK生成文件并保存到fullOutputPath // 现在我们只是创建一个空的模拟文件 await fs.writeFile(fullOutputPath, This is a simulated report for template ${templateId}. Data: ${JSON.stringify(inputData)}); console.log(Simulated report saved to: ${outputPath}); return outputPath; // 返回相对路径便于存储和下载 } module.exports { simulateChordXGeneration };最后创建报告任务的路由// routes/reports.js const express require(express); const router express.Router(); const authMiddleware require(../middleware/auth); const { submitReportTask, getTaskStatus, downloadReport, getUserTasks } require(../controllers/reportController); // 所有报告操作都需要认证 router.use(authMiddleware); // 提交新的报告生成任务 router.post(/tasks, submitReportTask); // 查询特定任务的状态 router.get(/tasks/:taskId/status, getTaskStatus); // 下载已完成的报告 router.get(/tasks/:taskId/download, downloadReport); // 获取当前用户的所有任务 router.get(/tasks, getUserTasks); module.exports router;3. 运行与测试代码都写好了让我们来启动服务并测试一下。首先在package.json的scripts里添加一个启动命令{ scripts: { start: node app.js, dev: nodemon app.js } }然后在终端运行开发模式npm run dev如果看到Server is running on http://localhost:3000说明服务启动成功了。现在我们可以用curl或者Postman这样的工具来测试API。1. 用户登录获取Token:curl -X POST http://localhost:3000/api/auth/login \ -H Content-Type: application/json \ -d {username:admin,password:password123}你会得到一个JWT令牌像这样{token:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...}。复制这个token。2. 上传一个模板需要Token:假设你有一个叫my_template.docx的文件。curl -X POST http://localhost:3000/api/templates/upload \ -H Authorization: Bearer YOUR_TOKEN_HERE \ -F name季度销售报告模板 \ -F templateFile/path/to/your/my_template.docx记得替换YOUR_TOKEN_HERE和文件路径。成功后会返回模板ID和存储路径。3. 提交报告生成任务需要Token:curl -X POST http://localhost:3000/api/reports/tasks \ -H Authorization: Bearer YOUR_TOKEN_HERE \ -H Content-Type: application/json \ -d { templateId: 1, inputData: {period: Q3-2024, region: North, metrics: [sales, growth]} }这会立即返回一个任务ID和一个状态查询URL。4. 查询任务状态:curl -H Authorization: Bearer YOUR_TOKEN_HERE \ http://localhost:3000/api/reports/tasks/1/status多查几次你会看到状态从pending-processing-completed。5. 下载报告:当状态变为completed后你可以通过返回的output_file_path来下载。curl -H Authorization: Bearer YOUR_TOKEN_HERE \ http://localhost:3000/api/reports/tasks/1/download \ --output my_report.pdf4. 总结与后续优化建议整个搭建过程走下来你会发现用Node.js和Express构建这样一个管理后台核心逻辑其实非常清晰定义数据模型、设计RESTful API、处理文件、连接数据库、加上认证。代码量不大但已经具备了任务提交、状态跟踪、文件管理和基础安全的能力。在实际使用中这个基础版本还有很大的优化空间。比如现在的报告生成是直接在API请求处理函数里模拟的这可能会阻塞其他请求。更好的做法是引入一个真正的任务队列比如Bull或Agenda把生成任务丢到队列里由后台的工作进程去消费。这样前端提交任务后立刻就能得到响应用户体验更好。另外用户管理、模板版本控制、报告生成结果的更多格式支持比如直接生成HTML在线查看、更细致的权限管理比如区分管理员和普通用户都是可以继续深化的方向。数据库方面如果报告量和用户数增长SQLite可能成为瓶颈届时可以平滑迁移到PostgreSQL或MySQL。总的来说这个项目提供了一个坚实的起点。它把CHORD-X这样一个独立的报告生成工具变成了一个可以通过网络调用的、可管理的服务为集成到更大的业务系统中铺平了道路。你可以根据自己项目的具体需求在这个骨架上添加血肉构建出更强大、更健壮的报告生成平台。获取更多AI镜像想探索更多AI镜像和应用场景访问 CSDN星图镜像广场提供丰富的预置镜像覆盖大模型推理、图像生成、视频生成、模型微调等多个领域支持一键部署。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2433833.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;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…