搜索引擎不友好的网站特征,怎样做网站平台,怎麽用dw做网站轮播海报,企业管理考研向 doubao.com/chat/ 提问#xff1a; node.js js-mdict 作为后端#xff0c;vue 3 vite 作为前端#xff0c;编写在线查询英汉词典
后端部分#xff08;express js-mdict #xff09;
1. 项目结构
首先#xff0c;创建一个项目目录#xff0c;结构如下#xff1…向 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.length50 || !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.length50 || !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 vitelatest mydict-web --template vue 选 Vue 选 JavaScript
项目结构Vite 会自动创建一个基本的项目结构包括 src目录下的组件、路由和状态管理等文件。主要文件和目录如下
App.vue根组件main.js应用程序入口routerVue 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 文件
templatediv idappinput v-modelsWord placeholder请输入英文单词 keyup.entersearchnbsp; button clicksearch查询/buttonnbsp; button clickprefix前缀查询/buttonnbsp; button clickfuzzy模糊查询/buttondiv v-ifresulth3查询结果/h3div idresult nameresult v-htmlresult/div/divdiv v-iferror{{ error }}/div/div
/templatescript 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 (i20){items[i] a hrefhttp://localhost:8006/query?word${item} targetresult${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 (i20){items[i] a hrefhttp://localhost:8006/query?word${item} targetresult${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 || 请求出错请稍后重试;}
};/scriptstyle 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;
}
/style4. 运行前端项目
cd mydict-web npm run dev mydict-web0.1.0 devviteVITE 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 词典文件。安全性在生产环境中需要考虑对后端接口进行安全防护如限制请求频率、验证请求来源等。
通过以上步骤你就可以实现一个简单的在线英汉词典查询系统。