mirror of
https://gitee.com/bookshelfplus/bookshelfplus
synced 2025-10-07 00:15:15 +08:00
引入nodejs项目
This commit is contained in:
19
.gitignore
vendored
19
.gitignore
vendored
@@ -1 +1,20 @@
|
|||||||
|
# 后端部分
|
||||||
target
|
target
|
||||||
|
|
||||||
|
# 前端部分
|
||||||
|
# 排除数据库配置文件
|
||||||
|
dbconfig.js
|
||||||
|
|
||||||
|
# 排除nodejs模块文件夹
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# 排除package-lock.json
|
||||||
|
package-lock.json
|
||||||
|
|
||||||
|
# 排除所有调试产生的log文件
|
||||||
|
*.log
|
||||||
|
|
||||||
|
.vs/*
|
||||||
|
|
||||||
|
*.njsproj.user
|
||||||
|
obj/*
|
7
README.md
Normal file
7
README.md
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
# 计算机类电子书网站开源项目
|
||||||
|
|
||||||
|
> 如需获取计算机类电子书,请访问https://books.only4.work/ ,或前往Git仓库👉([GitHub](https://github.com/only-4/computer-related-books)、[Gitee](https://gitee.com/only4/computer-related-books))
|
||||||
|
|
||||||
|
当前项目为 https://books.only4.work 网站源代码,你也可以通过这个项目搭建一个属于自己的电子书分享与管理平台。
|
||||||
|
|
||||||
|
[接口文档](api.md)
|
2
bookshelfplus-frontend/.env
Normal file
2
bookshelfplus-frontend/.env
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
# 设置开发/测试环境 development / production
|
||||||
|
NODE_ENV=development
|
91
bookshelfplus-frontend/app.js
Normal file
91
bookshelfplus-frontend/app.js
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
'use strict';
|
||||||
|
var debug = require('debug')('my express app');
|
||||||
|
var express = require('express');
|
||||||
|
var path = require('path');
|
||||||
|
var favicon = require('serve-favicon');
|
||||||
|
var logger = require('morgan');
|
||||||
|
var cookieParser = require('cookie-parser');
|
||||||
|
var bodyParser = require('body-parser');
|
||||||
|
let dotenv = require('dotenv');
|
||||||
|
|
||||||
|
// 读取配置文件
|
||||||
|
dotenv.config('./env');
|
||||||
|
// console.log(process.env);
|
||||||
|
|
||||||
|
// 取得API路径
|
||||||
|
global.site = process.env.site;
|
||||||
|
global.API_PREFIX = process.env.API_PREFIX;
|
||||||
|
if(!global.API_PREFIX) {
|
||||||
|
console.log('API_PREFIX is not defined');
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
console.log("[API_PREFIX] " + global.API_PREFIX);
|
||||||
|
|
||||||
|
// 引入路由文件
|
||||||
|
var routes = require('./routes/search');
|
||||||
|
var test = require('./routes/test');
|
||||||
|
|
||||||
|
// 创建应用
|
||||||
|
var app = express();
|
||||||
|
|
||||||
|
// 设置视图引擎 view engine setup
|
||||||
|
app.set('views', path.join(__dirname, 'views'));
|
||||||
|
app.set('view engine', 'ejs'); // pug
|
||||||
|
app.engine('.html', require('ejs').__express);
|
||||||
|
app.set('view engine', 'html');
|
||||||
|
|
||||||
|
app.use(favicon(__dirname + '/public/favicon.ico'));
|
||||||
|
app.use(logger('dev'));
|
||||||
|
app.use(bodyParser.json());
|
||||||
|
app.use(bodyParser.urlencoded({ extended: false }));
|
||||||
|
app.use(cookieParser());
|
||||||
|
app.use(express.static(path.join(__dirname, 'public')));
|
||||||
|
|
||||||
|
// 路由
|
||||||
|
app.use('/search', routes);
|
||||||
|
app.use('/test', test);
|
||||||
|
|
||||||
|
// 捕获404并转发到错误处理程序 catch 404 and forward to error handler
|
||||||
|
app.use(function (req, res, next) {
|
||||||
|
var err = new Error('Not Found');
|
||||||
|
err.status = 404;
|
||||||
|
next(err);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 错误处理 error handlers
|
||||||
|
|
||||||
|
// development error handler
|
||||||
|
// will print stacktrace
|
||||||
|
if (app.get('env') === 'development') {
|
||||||
|
console.log("[NODE_ENV] development");
|
||||||
|
app.use(function (err, req, res, next) {
|
||||||
|
res.status(err.status || 500);
|
||||||
|
res.render('error', {
|
||||||
|
message: err.message,
|
||||||
|
error: err
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// production
|
||||||
|
console.log("[NODE_ENV] production");
|
||||||
|
}
|
||||||
|
|
||||||
|
// production error handler
|
||||||
|
// no stacktraces leaked to user
|
||||||
|
app.use(function (err, req, res, next) {
|
||||||
|
res.status(err.status || 500);
|
||||||
|
res.render('error', {
|
||||||
|
message: err.message,
|
||||||
|
error: {}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
app.set('port', process.env.PORT || 3000);
|
||||||
|
|
||||||
|
var server = app.listen(app.get('port'), function () {
|
||||||
|
debug('Express server listening on port ' + server.address().port);
|
||||||
|
|
||||||
|
// 引入站点配置文件
|
||||||
|
global.site = require("./settings.json");
|
||||||
|
console.log(global.site);
|
||||||
|
});
|
@@ -1,18 +1,26 @@
|
|||||||
{
|
{
|
||||||
"name": "bookshelf-plus",
|
"name": "bookshelf-plus",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"description": "书栖网",
|
"private": true,
|
||||||
"main": "index.js",
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
"start": "node app",
|
||||||
|
"dev": "set NODE_ENV=development & node app",
|
||||||
|
"prod": "set NODE_ENV=production & node app"
|
||||||
},
|
},
|
||||||
"repository": {
|
"description": "书栖网",
|
||||||
"type": "git",
|
"dependencies": {
|
||||||
"url": "https://gitee.com/only4/bookshelf.git"
|
"body-parser": "^1.15.0",
|
||||||
|
"cookie-parser": "^1.4.0",
|
||||||
|
"debug": "^2.2.0",
|
||||||
|
"dotenv": "^16.0.0",
|
||||||
|
"ejs": "^3.1.6",
|
||||||
|
"element-plus": "^1.2.0-beta.6",
|
||||||
|
"express": "^4.14.0",
|
||||||
|
"morgan": "^1.7.0",
|
||||||
|
"mysql": "^2.18.1",
|
||||||
|
"serve-favicon": "^2.3.0"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"devDependencies": {
|
||||||
"书栖网"
|
"nodemon": "^2.0.15"
|
||||||
],
|
}
|
||||||
"author": "Coding Zhang",
|
|
||||||
"license": "MIT"
|
|
||||||
}
|
}
|
||||||
|
2
bookshelfplus-frontend/public/assets/lib/jquery/3.6.0/jquery.min.js
vendored
Normal file
2
bookshelfplus-frontend/public/assets/lib/jquery/3.6.0/jquery.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
18
bookshelfplus-frontend/public/package.json
Normal file
18
bookshelfplus-frontend/public/package.json
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"name": "bookshelf-plus",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "书栖网",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://gitee.com/only4/bookshelf.git"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"书栖网"
|
||||||
|
],
|
||||||
|
"author": "Coding Zhang",
|
||||||
|
"license": "MIT"
|
||||||
|
}
|
13
bookshelfplus-frontend/routes/search.js
Normal file
13
bookshelfplus-frontend/routes/search.js
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
'use strict';
|
||||||
|
var express = require('express');
|
||||||
|
var router = express.Router();
|
||||||
|
|
||||||
|
/* GET home page. */
|
||||||
|
router.get('/', function (req, res) {
|
||||||
|
res.render('search', {
|
||||||
|
title: site.title,
|
||||||
|
page: "首页"
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = router;
|
12
bookshelfplus-frontend/routes/test.js
Normal file
12
bookshelfplus-frontend/routes/test.js
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
'use strict';
|
||||||
|
var express = require('express');
|
||||||
|
var router = express.Router();
|
||||||
|
|
||||||
|
/* GET home page. */
|
||||||
|
router.get('/', function (req, res) {
|
||||||
|
res.render('test', {
|
||||||
|
title: "测试页 | " + site.title
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = router;
|
20
bookshelfplus-frontend/settings.json
Normal file
20
bookshelfplus-frontend/settings.json
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"NODE_ENV": "development",
|
||||||
|
"api": {
|
||||||
|
"prefix": "http://127.0.0.1:8090/"
|
||||||
|
},
|
||||||
|
"title": "张小弟之家电子书分享(测试中)",
|
||||||
|
"footer": {
|
||||||
|
"link": [
|
||||||
|
{
|
||||||
|
"text": "张小弟之家",
|
||||||
|
"url": "https://www.only4.work/",
|
||||||
|
"target": "_blank"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": "加入张小弟之家QQ群(链接待更新)",
|
||||||
|
"url": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
11
bookshelfplus-frontend/views/component/footer.html
Normal file
11
bookshelfplus-frontend/views/component/footer.html
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<footer>
|
||||||
|
<hr />
|
||||||
|
<p>
|
||||||
|
<% site.footer.link.forEach(function(link){ %>
|
||||||
|
<span><a href="<%= link.url; %>" target="<%= link.target %>"><%= link.text; %></a></span>
|
||||||
|
<% }); %>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Copyright © 2021-2022 <%= site.title; %> All Rights Reserved.
|
||||||
|
</p>
|
||||||
|
</footer>
|
7
bookshelfplus-frontend/views/component/header.html
Normal file
7
bookshelfplus-frontend/views/component/header.html
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<!-- StyleSheets -->
|
||||||
|
<link rel="stylesheet" href="/stylesheets/main.css">
|
||||||
|
|
||||||
|
|
||||||
|
<!-- JavaScripts -->
|
||||||
|
<!-- jQuery 3.6.0 -->
|
||||||
|
<script src="/lib/jquery/3.6.0/jquery.min.js"></script>
|
15
bookshelfplus-frontend/views/error.html
Normal file
15
bookshelfplus-frontend/views/error.html
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<title></title>
|
||||||
|
<%- include("./component/header.html"); %>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1><%= message %></h1>
|
||||||
|
<h2><%= error.status %></h2>
|
||||||
|
<pre><%= error.stack %></pre>
|
||||||
|
<%- include("./component/footer.html"); %>
|
||||||
|
</body>
|
||||||
|
</html>
|
152
bookshelfplus-frontend/views/search.html
Normal file
152
bookshelfplus-frontend/views/search.html
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<title><%= page + " | " + title; %></title>
|
||||||
|
<%- include("./component/header.html"); %>
|
||||||
|
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/gridjs/dist/theme/mermaid.min.css" rel="stylesheet" />
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/gridjs/dist/gridjs.umd.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<h1><%= title %></h1>
|
||||||
|
<p>本站电子书由“张小弟之家”整理,出于方便学习之目的,您从本站下载的电子书仅供学习交流使用,如需他用请联系原作者。<a href="https://gitee.com/only4/computer-related-books" target="_blank">查看同步更新Gitee仓库</a></p>
|
||||||
|
<p>由于信息量较大,我们无法做到一一确认相关电子书的权属管理,如本站不慎侵犯了您的权利,请发送邮件至<b>contact@only4.work</b>,来信请注明相关链接以及您的相关证明材料,我们收到邮件后会第一时间与您取得联系并积极处理,多谢理解!</p>
|
||||||
|
|
||||||
|
<main class="main">
|
||||||
|
<div id="container">
|
||||||
|
<div id="cateTable"></div>
|
||||||
|
<div id="itemTable"></div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function getDefaultGridDictTemplate() {
|
||||||
|
return {
|
||||||
|
columns: [],
|
||||||
|
//data: '',
|
||||||
|
|
||||||
|
// 搜索
|
||||||
|
search: true,
|
||||||
|
|
||||||
|
// 分页
|
||||||
|
pagination: {
|
||||||
|
limit: 10
|
||||||
|
},
|
||||||
|
|
||||||
|
// 排序
|
||||||
|
sort: true,
|
||||||
|
|
||||||
|
// 可调整列宽
|
||||||
|
resizable: true,
|
||||||
|
|
||||||
|
// 自适应
|
||||||
|
fixedHeader: true,
|
||||||
|
//height: '400px',
|
||||||
|
|
||||||
|
server: {},
|
||||||
|
|
||||||
|
language: {
|
||||||
|
search: {
|
||||||
|
placeholder: '🔍 搜索一下'
|
||||||
|
},
|
||||||
|
pagination: {
|
||||||
|
previous: '上一页',
|
||||||
|
next: '下一页',
|
||||||
|
navigate: (page, pages) => `第 ${page} 页,共 ${pages} 页`,
|
||||||
|
page: (e) => "第" + e + "页",
|
||||||
|
showing: "显示结果:第",
|
||||||
|
to: "-",
|
||||||
|
of: "条结果,共",
|
||||||
|
results: "条结果"
|
||||||
|
},
|
||||||
|
sort: {
|
||||||
|
sortAsc: "按升序排序",
|
||||||
|
sortDesc: "按降序排序"
|
||||||
|
},
|
||||||
|
loading: "数据正在加载中...",
|
||||||
|
noRecordsFound: "无结果",
|
||||||
|
error: "出错了"
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<script>
|
||||||
|
let cateTableDict = getDefaultGridDictTemplate();
|
||||||
|
cateTableDict.columns = [
|
||||||
|
{
|
||||||
|
name: '分类',
|
||||||
|
sort: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '分类简介',
|
||||||
|
sort: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '操作',
|
||||||
|
sort: false,
|
||||||
|
formatter: (cell, row) => {
|
||||||
|
return gridjs.h('button', {
|
||||||
|
className: 'py-2 mb-4 px-4 border rounded-md text-white bg-blue-600',
|
||||||
|
onClick: () => alert(`Editing "${row.cells[0].data}" "${row.cells[1].data}"`)
|
||||||
|
}, '查看');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
];
|
||||||
|
cateTableDict.server = {
|
||||||
|
url: '/api/getCategoryList?cateLevel=1&parentCateId=', //+'page=1&perpage=20',
|
||||||
|
then: data => data.result.reduce((result, element) => {
|
||||||
|
//console.log(result, element);
|
||||||
|
result.push({
|
||||||
|
分类: element.cateId,
|
||||||
|
分类: element.cateName,
|
||||||
|
分类简介: element.cateDescription,
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}, [ /* reduce result的初始值 */])
|
||||||
|
};
|
||||||
|
|
||||||
|
let cateTable = new gridjs.Grid(cateTableDict);
|
||||||
|
cateTable.render(document.getElementById('cateTable'));
|
||||||
|
</script>
|
||||||
|
<script>
|
||||||
|
let itemTableDict = getDefaultGridDictTemplate();
|
||||||
|
itemTableDict.columns = [
|
||||||
|
{
|
||||||
|
name: '书名',
|
||||||
|
sort: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '简介',
|
||||||
|
sort: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '操作',
|
||||||
|
formatter: (cell, row) => {
|
||||||
|
return gridjs.h('button', {
|
||||||
|
className: 'py-2 mb-4 px-4 border rounded-md text-white bg-blue-600',
|
||||||
|
onClick: () => alert(`Editing "${row.cells[0].data}" "${row.cells[1].data}"`)
|
||||||
|
}, '查看详情');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
];
|
||||||
|
itemTableDict.server = {
|
||||||
|
url: '/api/getBookList',
|
||||||
|
then: data => data.result.reduce((result, element) => {
|
||||||
|
result.push({
|
||||||
|
书名: element.书名,
|
||||||
|
简介: element.书籍简介,
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}, [ /* reduce result的初始值 */])
|
||||||
|
};
|
||||||
|
|
||||||
|
let itemTable = new gridjs.Grid(itemTableDict);
|
||||||
|
itemTable.render(document.getElementById('itemTable'));
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<%- include("./component/footer.html"); %>
|
||||||
|
</body>
|
||||||
|
</html>
|
67
bookshelfplus-frontend/views/test.html
Normal file
67
bookshelfplus-frontend/views/test.html
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<title><%= title; %></title>
|
||||||
|
<%- include("./component/header.html"); %>
|
||||||
|
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/gridjs/dist/theme/mermaid.min.css" rel="stylesheet" />
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/gridjs/dist/gridjs.umd.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<h1><%= title %></h1>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<el-row>
|
||||||
|
<el-button>Default</el-button>
|
||||||
|
<el-button type="primary">Primary</el-button>
|
||||||
|
<el-button type="success">Success</el-button>
|
||||||
|
<el-button type="info">Info</el-button>
|
||||||
|
<el-button type="warning">Warning</el-button>
|
||||||
|
<el-button type="danger">Danger</el-button>
|
||||||
|
<el-button>中文</el-button>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-row>
|
||||||
|
<el-button plain>Plain</el-button>
|
||||||
|
<el-button type="primary" plain>Primary</el-button>
|
||||||
|
<el-button type="success" plain>Success</el-button>
|
||||||
|
<el-button type="info" plain>Info</el-button>
|
||||||
|
<el-button type="warning" plain>Warning</el-button>
|
||||||
|
<el-button type="danger" plain>Danger</el-button>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-row>
|
||||||
|
<el-button round>Round</el-button>
|
||||||
|
<el-button type="primary" round>Primary</el-button>
|
||||||
|
<el-button type="success" round>Success</el-button>
|
||||||
|
<el-button type="info" round>Info</el-button>
|
||||||
|
<el-button type="warning" round>Warning</el-button>
|
||||||
|
<el-button type="danger" round>Danger</el-button>
|
||||||
|
</el-row>
|
||||||
|
|
||||||
|
<el-row>
|
||||||
|
<el-button :icon="Search" circle></el-button>
|
||||||
|
<el-button type="primary" :icon="Edit" circle></el-button>
|
||||||
|
<el-button type="success" :icon="Check" circle></el-button>
|
||||||
|
<el-button type="info" :icon="Message" circle></el-button>
|
||||||
|
<el-button type="warning" :icon="Star" circle></el-button>
|
||||||
|
<el-button type="danger" :icon="Delete" circle></el-button>
|
||||||
|
</el-row>
|
||||||
|
</template>
|
||||||
|
<script type="module">
|
||||||
|
import {
|
||||||
|
Search,
|
||||||
|
Edit,
|
||||||
|
Check,
|
||||||
|
Message,
|
||||||
|
Star,
|
||||||
|
Delete,
|
||||||
|
} from 'element' //from '@element-plus/icons-vue'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<%- include("./component/footer.html"); %>
|
||||||
|
</body>
|
||||||
|
</html>
|
Reference in New Issue
Block a user