nodejs:express + js-mdict 作为后端,vue 3 + vite 作为前端,在线查询英汉词典

向 doubao.com/chat/ 提问:
node.js + js-mdict 作为后端,vue 3 + vite 作为前端,编写在线查询英汉词典

后端部分(express + js-mdict

1. 项目结构

首先,创建一个项目目录,结构如下:cd \js
mkdir mydict-app

mydict-app/
├── public/
│   ├── index.html
│   ├── styles.css
│   └── script.js
├── server/
│   └── app.js
├── package.json
└── README.md

英汉词典文件(*.mdx , *.mdd)  已经放在 /js/testdict/ 

在 public 中添加一些英汉字典的样式:oalecd8e.css , oalecd8e.js , uk_pron.png, us_pron.png,
copy jquery-3.2.1.min.js pulibc\jquery.js 

2. 安装依赖

在项目根目录下运行以下命令,初始化项目并安装所需的依赖:
cd mydict-app
npm init -y
npm install express  cors
added 69 packages in 6s

npm install js-mdict 
added 3 packages in 2s

3. 编写后端代码

创建 app.js 文件,代码如下:

const express = require('express');
const cors = require('cors');
const Mdict = require('js-mdict');
const path = require('path');const app = express();
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
// 提供静态文件
app.use(express.static(path.join(__dirname, '../public')));// 加载MDict词典文件
//const mdict = new Mdict('path/to/your/dictionary.mdx');
const mdx = new Mdict.MDX('/js/testdict/oale8.mdx');
const mdd = new Mdict.MDD('/js/testdict/oale8.mdd');const isWord = (txt) => {// 只允许字母、/、空格、-return /^[a-zA-Z \/\-]+$/.test(txt);
};// 处理查询请求,响应:单词的定义(html)
app.get('/query', (req, res) => {let word = req.query.word;if (!word) {return res.status(400).json({ error: 'No word input'});}if (word) {let data = mdx.lookup(word);console.log("cha: "+ word);if(data.definition){res.send(data.definition);} else {res.status(400).send('this word not found');}} else {res.status(400).send('error: No word input');}
});// 处理查询请求,响应:单词的定义(json)
app.get('/search', async (req, res) => {const word = req.query.word;if (!word) {return res.status(400).json({ error: 'No word input'});}console.log("cha: "+ word);try {let data = await mdx.lookup(word);let result;if (data.definition){ result = data.definition;}else { result ='';}res.json({ result });} catch (error) {console.error('Error searching in MDict:', error);res.status(500).json({ error: 'Internal server error' });}
});// 处理前缀查询请求
app.get('/prefix', (req, res) => {let word = req.query.word;// 检查word是否合法if (word.length <2) {return res.status(400).json({ error: 'input too short'});} else if (word.length>50 || !isWord(word)) {return res.status(400).json({ error: 'Invalid input.'});}if (word) {let alist = mdx.prefix(word);console.log("pre: "+ word);if(alist.length >0){let wordls = [];alist.forEach(function(value){wordls.push(value.keyText);});  res.json({wordls});} else {res.status(500).json({ info: 'this word not found'});}} else {res.status(500).json({ error: 'No word input'});}
});// 处理模糊查询请求
app.get('/fuzzy', (req, res) => {let word = req.query.word;// 检查word是否合法if (word.length>50 || !isWord(word)) {return res.status(400).json({ error: 'Invalid input.'});}if (word) {let alist = mdx.fuzzy_search(word,3,1);console.log("fuzzy: "+ word);if(alist.length >0){let wordls = [];alist.forEach(function(value){wordls.push(value.keyText);});  res.json({wordls});} else {res.status(500).json({ info: 'this word not found'});}} else {res.status(500).json({ error: 'No word input'});}
});var MIME = {'css': 'text/css','bmp': 'image','img': 'image','gif': 'image','jpg': 'image/jpeg','png': 'image/png','spx': 'audio/x-speex','wav': 'audio/wav','mp3': 'audio/mp3','js' : 'text/javascript'
};
// 指定目录
const dir1 = "/";// 实现文件下载,*/是路径
app.get('/data/*/:fileName', (req, res, next) => {let path1 = req.params[0]; // 捕获 * 匹配的部分let fileName = req.params.fileName; // 捕获文件名// 检查路径中是否包含非法字符(如 ..)if (path1.includes('..') || fileName.includes('..')) {return res.status(400).send('Invalid path: Path traversal is not allowed.');}let extname = path.extname(fileName);let ext = extname.substring(1).toLowerCase();if (['mp3','spx','wav'].includes(ext)){let filePath = path.join(dir1,path1, fileName);//console.log(filePath);let data = mdd.locate(filePath);if (data){console.log('key: '+ data.keyText);//console.log(Buffer.isBuffer(data.definition));if (data.definition){let binaryData = Buffer.from(data.definition, 'base64');//res.setHeader('Content-Type', 'application/octet-stream');res.set({'Content-Type': MIME[ext] || 'audio','Content-Disposition': 'attachment;','Content-Length': Buffer.byteLength(binaryData)});//console.log(MIME[ext]);res.end(binaryData);} else {res.status(400).send('error: data.definition is null');}} else {res.status(400).send('error: data is null');}} else {res.status(400).send('filename.ext is not .mp3');}
});// 实现文件下载,*/是路径
app.get('/*/:fileName', (req, res, next) => {let path1 = req.params[0]; // 捕获 * 匹配的部分let fileName = req.params.fileName; // 捕获文件名// 检查路径中是否包含非法字符(如 ..)if (fileName.includes('..')) {return res.status(400).send('Invalid path: Path traversal is not allowed.');}//console.log(fileName);let extname = path.extname(fileName);let ext = extname.substring(1).toLowerCase();if (['bmp','gif','jpg','png'].includes(ext)){let filePath = path.join(dir1,path1, fileName);//console.log(filePath);let data = mdd.locate(filePath);if (data){console.log('key: '+ data.keyText);//console.log(Buffer.isBuffer(data.definition));if (data.definition){let binaryData = Buffer.from(data.definition, 'base64');//res.setHeader('Content-Type', 'application/octet-stream');res.set({'Content-Type': MIME[ext] || 'image','Content-Disposition': 'attachment;','Content-Length': Buffer.byteLength(binaryData)});//console.log(MIME[ext]);res.end(binaryData);} else {res.status(400).send('error: data.definition is null');}} else {res.status(400).send('error: data is null');}} else {console.log(fileName);res.status(400).send('filename.ext is not image');}
});const port = process.env.PORT || 8006;
app.listen(port, () => {console.log(`Server is running on port:${port}`);
});

4. 运行后端服务

cd mydict-app
node server/app.js
Server is running on port:8006


前端部分(Vue 3 + Vite)

1. 创建前端项目

node -v
v18.20.6
npm -v
10.8.2

cd \js
cnpm create vite@latest mydict-web --template vue
 选 Vue 
 选 JavaScript

项目结构‌:Vite 会自动创建一个基本的项目结构,包括 src目录下的组件、路由和状态管理等文件。主要文件和目录如下:

  • App.vue:根组件
  • main.js:应用程序入口
  • router:Vue Router配置
  • store:状态管理

在 public 中添加一些英汉字典的样式:oalecd8e.css , oalecd8e.js , uk_pron.png, us_pron.png,
copy jquery-3.2.1.min.js pulibc\jquery.js 

2. 安装依赖

cd mydict-web
cnpm install axios

cnpm install vue-router -S

 package.json 如下

{"name": "mydict-web","private": true,"version": "0.1.0","type": "module","scripts": {"dev": "vite","build": "vite build","preview": "vite preview"},"dependencies": {"axios": "^1.7.9","vue": "^3.5.13","vue-router": "^4.5.0"},"devDependencies": {"@vitejs/plugin-vue": "^5.2.1","vite": "^6.1.0"}
}

3. 编写前端代码

修改 src/App.vue 文件:

<template><div id="app"><input v-model="sWord" placeholder="请输入英文单词" @keyup.enter="search">&nbsp; <button @click="search">查询</button>&nbsp; <button @click="prefix">前缀查询</button>&nbsp; <button @click="fuzzy">模糊查询</button><div v-if="result"><h3>查询结果</h3><div id="result" name="result" v-html="result"></div></div><div v-if="error">{{ error }}</div></div>
</template><script setup>
import { ref } from 'vue';
import axios from 'axios';const sWord = ref('');
const result = ref('');
const error = ref('');// 查询
const search = async () => {try {const response = await axios.get('http://localhost:8006/search', {params: {word: sWord.value}});result.value = response.data.result;error.value = '';} catch (err) {result.value = '';error.value = err.response?.data?.error || '请求出错,请稍后重试';}
};// 前缀查询
const prefix = async () => {try {const response = await axios.get('http://localhost:8006/prefix', {params: {word: sWord.value}});let items = [];let wordls = response.data.wordls;wordls.forEach((item, i) => {if (i<=20){items[i] = `<a href="http://localhost:8006/query?word=${item}" target="result">${item}</a>`;}});if (items.length >0){ result.value = items.join(', ');}else {result.value = '';}error.value = '';} catch (err) {result.value = '';error.value = err.response?.data?.error || '请求出错,请稍后重试';}
};// 模糊查询
const fuzzy = async () => {try {const response = await axios.get('http://localhost:8006/fuzzy', {params: {word: sWord.value}});let items = [];let wordls = response.data.wordls;wordls.forEach((item, i) => {if (i<=20){items[i] = `<a href="http://localhost:8006/query?word=${item}" target="result">${item}</a>`;}});if (items.length >0){ result.value = items.join(', ');}else {result.value = '';}error.value = '';} catch (err) {result.value = '';error.value = err.response?.data?.error || '请求出错,请稍后重试';}
};</script><style scoped>
#app {font-family: Avenir, Helvetica, Arial, sans-serif;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;text-align: left;color: #2c3e50;margin-top: 10px;
}
</style>

4. 运行前端项目

cd mydict-web
npm run dev

> mydict-web@0.1.0 dev
> viteVITE v6.1.1  ready in 1083 ms➜  Local:   http://localhost:5173/➜  Network: use --host to expose➜  press h + enter to show help
hShortcutspress r + enter to restart the serverpress u + enter to show server urlpress o + enter to open in browserpress c + enter to clear consolepress q + enter to quit
o

注意事项

  • 跨域问题:在开发环境中使用 cors 中间件解决跨域问题,在生产环境中可以通过配置反向代理等方式处理。
  • MDX 文件路径:确保 app.js 中的 mdict Path 指向正确的 .mdx 词典文件。
  • 安全性:在生产环境中,需要考虑对后端接口进行安全防护,如限制请求频率、验证请求来源等。

通过以上步骤,你就可以实现一个简单的在线英汉词典查询系统。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网络原理--TCP的特性

TCP报文的结构&#xff1a; TCP的报头前20字节是固定长度&#xff0c;也可以通过“选项”来增加。 一、用来确保可靠性&#xff0c;最核心的机制&#xff0c;称为“确认应答” 引入一个情景&#xff1a; A向B询问cat和dog的意思&#xff1a; 这种情况是理想情况&#xff0c;…

Java 大视界 -- 深度洞察 Java 大数据安全多方计算的前沿趋势与应用革新(52)

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

【HTML— 快速入门】HTML 基础

准备工作 vscode下载 百度网盘 Subline Text 下载 Sublime Text下载 百度网盘 vscode 下载 Sublime Text 是一款轻量好用的文本编辑器&#xff0c;我们在写前端代码时&#xff0c;使用 Sublime Text 打开比使用记事本打开&#xff0c;得到的代码体验更好&#xff0c;比 vscode…

深圳南柯电子|医疗设备EMC测试整改检测:零到一,保障医疗安全

在当今医疗科技飞速发展的时代&#xff0c;医疗设备的电磁兼容性&#xff08;EMC&#xff09;已成为确保其安全、有效运行的关键要素之一。EMC测试整改检测不仅关乎设备的性能稳定性&#xff0c;更是保障患者安全、避免电磁干扰引发医疗事故的重要措施。 一、医疗设备EMC测试整…

Tomcat安装与环境变量配置(图文详解)

一、前置条件 tomcat依赖java环境&#xff0c;需要先安装java环境。 jdk环境变量配置可参考&#xff1a;win7、win10系统JDK环境变量配置-CSDN博客 二、Tomcat的下载与安装 1.进入Tomcat官网&#xff1a; https://tomcat.apache.org/ 2.在该网页左侧栏红框标记的download…

网络安全之Web后端PHP

目录 一、PHP基础语法 1.PHP基础 &#xff08;1&#xff09;php的优点 &#xff08;2&#xff09;PhpStorm的优点 2.PHP基本语法 3.PHP变量 4.PHP运算符 二、PHP流控与数组 1.php流程控制语句以及循环 &#xff08;1&#xff09;if 语句 &#xff08;2&#xff09;if…

Python 批量横屏转竖屏视频处理工具

Python 批量横屏转竖屏视频处理工具 相关资源文件已经打包成EXE文件&#xff0c;可双击直接运行程序&#xff0c;且文章末尾已附上相关源码&#xff0c;以供大家学习交流&#xff0c;博主主页还有更多Python相关程序案例&#xff0c;秉着开源精神的想法&#xff0c;望大家喜欢&…

ESP32S3:解决RWDT无法触发中断问题,二次开发者怎么才能使用内部RTC看门狗中断RWDT呢?

目录 基于ESP32S3:解决RWDT无法触发中断问题引言解决方案1. 查看报错日志2. 分析报错及一步一步找到解决方法3.小结我的源码基于ESP32S3:解决RWDT无法触发中断问题 引言 在嵌入式系统中,RWDT(看门狗定时器)是确保系统稳定性的重要组件。然而,在某些情况下,RWDT可能无法…

在windows下安装windows+Ubuntu16.04双系统(上)

这篇文章的内容主要来源于这篇文章&#xff0c;给文章很详细的介绍了如何从windows下安装windowsubuntu16.04双系统。我刚开始装双系统都是参照这个方法&#xff0c;该作者前后更新了两个版本&#xff0c;在这里对其稍微进行整理一下。 一、准备&#xff1a;&#xff08;这里推…

计算机单位之详解——存储单位Byte 网络传输单位bps 视频码率单位bps

前言&#xff1a; 计算机里面单位有点复杂&#xff0c;容易混淆&#xff0c;很多时候混起来就容易概念不理解&#xff0c;包括一些小问题&#xff0c;比如说&#xff1a;为什么我买了1T硬盘&#xff0c;实际存在虚标。为什么所谓的千兆宽带&#xff0c;下载起来没有1G每秒&…

博客系统完整开发流程

前言 通过前⾯课程的学习, 我们掌握了Spring框架和MyBatis的基本使用, 并完成了图书管理系统的常规功能开发, 接下来我们系统的从0到1完成⼀个项⽬的开发. 企业开发的流程 1. 需求评审(产品经理(PM)会和运营(想口号),UI,测试,开发等沟通) ,会涉及到背景/目标/怎么做,可能会有多…

MFC笔记:本专栏课件

专栏导航 上一篇&#xff1a;在VS2019里面&#xff0c;调整代码字体大小 回到目录 下一篇&#xff1a;无 本节前言 在之前的讲解里面&#xff0c;我讲解了 Visual Studio 软件的一些个基础操作步骤。从本节开始&#xff0c;我们进入预备章。 本节内容&#xff0c;属于是 …

Flutter - 基础Widget

Flutter 中万物皆 Widget&#xff0c;基础Widget 同步对应 Android View. 普通文本 Text /*** 控制文本样式统一使用 style:TextStyle, 例&#xff1a;fontSize(字体大小),color(颜色),shadows(阴影)等等* 控制文本布局需单独设置&#xff1a;* textAlign(文不对齐方式)* te…

蓝桥杯之日期题

文章目录 1.蓝桥杯必备知识点2. 题型13.需求2 1.蓝桥杯必备知识点 蓝桥杯是一个面向全国高校计算机相关专业学生的学科竞赛&#xff0c;涵盖多个赛道&#xff0c;常见的有软件类&#xff08;如 C/C 程序设计、Java 软件开发、Python 程序设计&#xff09;和电子类&#xff08;…

本地部署大模型: LM Studio、Open WebUI 与 Chatbox 全面对比以及选型指南

1. 工具概述 LM Studio 定位&#xff1a;专注于本地化大模型实验与推理的桌面工具&#xff0c;支持多模型并行、Hugging Face集成及离线运行。 核心功能&#xff1a; 图形化界面直接加载GGUF模型文件&#xff0c;支持NVIDIA/AMD GPU加速。 内置OpenAI兼容API&#xff0c;可搭…

springboot实现多文件上传

springboot实现多文件上传 代码 package com.sh.system.controller;import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.PostMap…

最新版IDEA下载安装教程

一、下载IDEA 点击前往官网下载 或者去网盘下载 点击前往百度网盘下载 点击前往夸克网盘下载 进去后点击IDEA 然后点击Download 选择自己电脑对应的系统 点击下载 等待下载即可 二、安装IDEA 下载好后双击应用程序 点击下一步 选择好安装目录后点击下一步 勾选这两项后点击…

vue3学习2

ts定义接口&#xff1a; 引入的时候要加type&#xff1a; 调用&#xff1a; ts创建自定义type类型&#xff0c;引入的时候也要加type&#xff1a; reactive可以直接传泛型&#xff1a; 加?声明不强制&#xff1a; defineProps接收父组件传递的props&#xff0c;其中defineProp…

Proof Beyond Boundaries: Hong Kong zkNight 活动精彩回顾

2 月 19 日&#xff0c;随着夜幕的降临&#xff0c;一场汇聚行业智慧与前瞻视野的高端主题活动 ——Proof Beyond Boundaries: Hong Kong zkNight&#xff0c;在香港铜锣湾 Vpoint 的 6/F 盛大启幕。本次活动由 ZEROBASE 主办&#xff0c;Techub News 承办&#xff0c;吸引了众…

PDF转HTML 超级好用 免费在线转换PDF 完美转换格式

PDF转HTML 超级好用 免费在线转换PDF 完美转换格式&#xff0c;PDF已成为一种广泛使用的文件格式&#xff0c;用于保存和分享文档。然而&#xff0c;PDF文件在某些场景下可能不够灵活&#xff0c;特别是在需要在网页上直接展示其内容时。为了满足这一需求&#xff0c;小白工具推…