Bootstrap

从零搭建一个简单的node管理项目

node 项目

服务端项目配置介绍
	1.需要先创建一空的文件夹,然后再继承终端中打开 我们需要用到的是express的架构模式还有nodem配合的服务端还有mongoose数据库来怕搭配使用
    2.先再继承中高端中打开 执行命令->express -e 回车下载
    3.现在出现一个整体的结构,结构本来就携带者很多包,接下来让我们下载我们需要的包名,注意一定要注意版本号看看是不是支持,如果不支持需要降低版本号,z再下载插件的时候你也可以通过此命令来查询这个插件的版本号如下->npm view 插件名称 versions,如果下载的比较慢可以用nrm ls 查看你的镜像 nrm test 查看速度,如果感觉到慢就 nrm use 镜像名称 比如 taobao等等.....
	4.需要下载到项目依赖的有
    	 "dependencies": {
    			"art-template": "^4.13.2",渲染art的插件
    			"cookie-parser": "~1.4.4", 是验证cookie的插件
    			"debug": "~2.6.9", 执行简介的
    			"ejs": "~2.6.1", 是一个渲染的模块
    			"express": "~4.16.1", 是架构的模式
    			"express-art-template": "^1.0.1", 渲染art的插件
    			"http-errors": "~1.6.3", 一个简介的服务器
    			"mongoose": "^6.4.4", 是一个数据库
    			"morgan": "~1.9.1", 节点HTTP 请求的插件
    			"multer": "^1.0.0" 处理多数据 多表单的插件
                 "cookie-session": "^2.0.0", cookie 验证的
    			"jsonwebtoken": "^8.5.1", 自动登录保存的
      	},
 	5.需要下载到开发依赖的有
    		"devDependencies": {
    			"cross-env": "^7.0.3", 能帮你改变端口号
    			"nodemon": "^2.0.19" 能让你的代码实施运行着 查看结果
 		}
	6.需要配置一个这样的启动项
    		"scripts": {
                第一个部分表是的重定向的是一个4000的端口哈,默认的是3000端口号,后就是一个nodemon启动的服务器能试试更新你的代码
    			"start": "cross-env PROT=4000 nodemon ./bin/www"
  		},
     7.接下来让我们来配置app.js文件里面的内容
		1.需要引入的包名有一下
        	var multer = requer("multer")();加上括号表示就是立即执行
         2.需要早app.use部分插入一个
			app.use(multer.none());
		3.需要把app.set里面的aej改成art,还需要引入的插件有
			app.engine("art",require("express-art-template"))
	8.然后你还需要把views文件的默认生成出来的,改成art扩展名称
    9.创建一个mondb的文件
    	1.然后再创建一个db.js让我们配置数据库,你需要下载一个mongodb有windos版的下载到电脑上,进行配置,然后把数据库运行起来,才能操作数据的连接已经查询创建等
		2.数据库里面的内容
			var mongoose = require('mongoose');//引入mongdb的库
var Schema = mongoose.Schema;
mongoose.connect('mongodb://localhost/game');

// 创建一个数据库表的,并且配置好数据
var UserData = new Schema({
    username: { type: String, unique: true, index: true },//第一个表示是字符串型的数据,第二表示
    password: String,//数据是字符型
    name: String,//数据是字符型
    age: Number,//数值型
    tel: String,//数据是字符型
    email: String,//数据是字符型
});

var Users = mongoose.model('userlist', UserData);//User是数据表名
function insert (data) {
    return new Promise(function (resolve, reject) {//是一个异步的函数
        var item = new Users(data);//在这里引用这个数据表 并且赋值给 item 通过操作这个item就可以或者对应的数据
        console.log("连接成功!");
        item.save({}, function (err, res) {
            if (err) {
                console.log(err + '插入失败❌')//错误的信息返回
                resolve(null);
            } else {
                console.log('插入成功✅')//返回连接成功的提示u
                resolve(res)
            }
        })
    })
}
//查询语句
function selectAll () {
    return new Promise(function (resolve, reject) {
        Users.find({}, function (err, res) {
            if (err) {
                console.log('查询失败❌');
                resolve(null);
            } else {
                console.log('查询成功✅')
                resolve(res);
            }
        })
    })
}

// 不能重复的插入数据 如果重复插入的数或报错,每个id但是唯一的
function update (condition, value) {
    return new Promise(function (resolve, reject) {
        Users.updateOne(condition, { $set: value }, function (err, res) {
            if (err) {
                console.log(err + '数据重复失败❌');
            } else {
                resolve(res);
            }
        })
    })
}
// 是查用户名名称的
function selectUser (data) {
    return new Promise(function (resolve, reject) {
        Users.find(data, function (err, res) {
            if (err) {
                console.log(err + "查询用户失败❌");
            } else {
                console.log('查询用户成功从✅');
                resolve(res);
            }
        })
    })
}

exports.insert = insert;//导出连接
exports.selectAll = selectAll;//导出插入
exports.update = update;//查询数据吧
exports.selectUser = selectUser;//查询用户名称的

	还需要创建router文件夹
	1.第一个index.js文件里面有
		var express = require('express');
		var router = express.Router();
		var { selectAll } = require("../model/db");

		/* GET home page. */
		router.post('/', async function (req, res, next) {
		  var result = await selectAll();
		  if (!result) {
		    res.send({ err: "查找错误" });
		  } else {
		    res.send({ err: null, list: result });
		  }
		});
module.exports = router;
	2.在创建一个users.js
			var express = require('express');
			var fsp = require("fs/promises");
			var router = express.Router();
			var path = require("path");
			var { insert, selectAll, update, selectUser } = require("../model/db.js")// 连接数据库
			var token = require('jsonwebtoken')


			router.post('/logup', async function (req, res, next) {
			  var result = await insert(req.body);
			  if (result) {
			    res.send({ err: null });
			  } else {
			    res.send({ err: '注册失败' })
			  }
			});

			router.post("/login", async function (req, res, next) {
			  var result = await selectUser(req.body);
			  if (!result || result.length === 0) {
			    res.send({ err: "登录失败" });
			  } else {
			    req.session.username = result[0].username;
			    res.send({ err: null, username: result[0].username });
			  }
			})


			router.post('/auth', async function (req, res, next) {
			  var txt = await fsp.readFile(path.join(__dirname, "../rsa_public_key.pem"));
			  var obj = token.verify(req.body.info, txt)//解密
			  console.log(obj)
			  if (!req.session.username) {
			    res.send({ err: "重新登录" });
			  } else {
			    res.send({ err: null, username: req.session.username });
			  }
			})


			router.post('/logout', function (req, res, next) {
			  req.session.username = null;
			  res.send({ err: null, msg: '退出成功' })
			})

			module.exports = router;
		3.差不多了,让我们把服务器跑起来 npm i下载更新 SET DEBUG=server:* & npm start 不要关闭继续下面的操作
客户端服务配置如下
	1.第一步需要创建一个文件,再文件下面执行终端 npm i init -y 出来一个json的文件 找到对应一下操作吧下面代码放入对应位置执行npm i 把所有的插件下载更新下来,接下来我们还需要配置两个运行的程序,再scripts里面添加,每次添加完如果还需要添加的话,后面跟上,来添加下一句     "dev": "webpack","start": "webpack-dev-server",把以上两句放进去然后执行 npm i 进行更新,然后如果你webpack.confilg.js文件已经配置好了,可以执行 npm run dev 再开一个黑色窗口执行npm run start,如果没有配置wabpack,带着你一块配置找到配置文件往下找,
	2.需要配置再package.js的文件如下
		01.项目依赖的有如下:
        	"dependencies": {
    			"sme-router": "^0.12.8", 以快速路由样式实现的轻量级路由器库
    			"jsonwebtoken": "^8.5.1" 是一个令牌 能实现自动登录的过程
  			},
          02.开发依赖的部分有如下:
			 "devDependencies": {
    			"webpack": "^4.46.0",捆绑 ES 模块、CommonJS 和 AMD 模块(甚至组合)。
    			"webpack-cli": "^3.3.12", 自定义配置的插件
    			"webpack-dev-server": "^3.11.3", 将 webpack 与提供实时重新加载的开发服务器一起使用。这应该仅用于开发。快速访问
    			"html-webpack-plugin": "^4.5.2",插件,可简化HTML文件的创建以为您的捆绑包提供服务,能捆绑 就比如可以理解成钩子 构住他
    			"clean-webpack-plugin": "^3.0.0", 一个用于删除/清理构建文件夹的webpack插件。
    			"copy-webpack-plugin": "^6.4.1", 将已存在的单个文件或整个目录复制到生成目录。
    			"style-loader": "^1.3.0",CSS 注入 DOM 就是css可以引入到js里面使用
    			"css-loader": "^5.0.2", 解释和喜欢,并将解决它们。css-loader@importurl()import/require()
    			"art-template": "^4.13.2", art-template是一个简单而超快的模板引擎,它通过范围预先声明的技术优化模板渲染速度,从而实现接近JavaScript极限的运行时性能。同时,它同时支持NodeJS和浏览器 渲染速度比较快
    			"art-template-loader": "^1.4.3" 默认情况下,每个本地都是必需的 ()。您可能需要为配置中的映像指定加载程序(推荐或 )比如:<img src="image.png">require('./image.png')file-loaderurl-loader
  			}

2.接下来让我们配置webpack.config.js文件
	1.先新创建一个webpack.config.js文件,然后依次创建scr文件,src文件下面创建->css,js,view文件夹,创建一个app.js
	2.然后再创建一个public文件 再这个文件下面创建->css,js,html,js.image,picture,font
	3.操作完一以上的步骤,让我们解析来配置webpack.confilg.js文件,打开文件然后就是猛地操作哈哈
	4.让我们引入几个插件
    	1.var path = require("path");//需要引入文件的路径
		2. var HtmlWebpackPlugin = require("html-webpack-plugin");//可以简化HTML文件的创建以为您的捆绑包提供服务,可以称为钩子
		3.var { CleanWebpackPlugin } = require("clean-webpack-plugin");//一个用于删除/清理构建文件夹的webpack插件。
		4.var CopyPlugin = require("copy-webpack-plugin");//使用 webpack 复制文件 && 目录
	5.然后再需要把你配置的东西导出出去一下代码
    	1.module.exports = {
    		mode: "development",
    		devtool: 'source-map', //是映射文件
    	2.entry: {
        	"js/main": "./src/app.js",//其实位置-结束的位置
    	},
    	// 复制出来新的文件 放入到一个叫做dist文件下
    	3.output: {
        	path: path.join(__dirname, "./dist"),//指定床啊金一新的文件
        	filename: "[name][hash:6].min.js",//解析js文件 让js 文件不重复 加上hash字符
    	},
		//从一个模块转换到另一个模块
    	4.module: {
        	rules: [
            	{ test: /\.css$/i, use: ['style-loader', 'css-loader'] },//正则表达式来解析css的名字
            	{ test: /\.art$/i, use: { loader: 'art-template-loader' } },//解析art的渲染文件的格式带入插件
       		 ],
    	},
    	// 创建一个自动创建hrml文件
    	5.plugins: [
        	new HtmlWebpackPlugin({
            	template: path.join(__dirname, "./public/html/index.html"),
            	app: "index.html",//每次传入的index.html 文件都用这个名字
            	inject: true//问问你是不是需要把html里面的所有文件都带过去
        	}),
            //他会把你每次重复创建的js文件,把重复的给删除掉
        6.new CleanWebpackPlugin(),
            //复制-到终点,就是从哪里复制,把东西复制到哪里
        7.new CopyPlugin({
            patterns: [
                //需要解析的文件有一下这么多,每次都需要把他们带入到指定dist文件下的格式,让一个你想要改动,直接该扩展名进行
                { from: path.join(__dirname, "./public/image"), to: path.join(__dirname, "./dist/image") },
                { from: path.join(__dirname, "./public/css"), to: path.join(__dirname, "./dist/css") },
                { from: path.join(__dirname, "./public/font"), to: path.join(__dirname, "./dist/font") },
                { from: path.join(__dirname, "./public/js"), to: path.join(__dirname, "./dist/js") },
                { from: path.join(__dirname, "./public/picture"), to: path.join(__dirname, "./dist/picture") },
            ]
        })
    ],
    // 来创建服务器以及中转栈api
    8.devServer: {
        contentBase: path.join(__dirname, "./dist"),
        port: 4001,//服务端端口哈
        proxy: {//使用的代理来进行准发的
            "/api": {
                target: "http://localhost:4000",//对接服务端的
                pathRewrite: { "^/api": "" }
            }
        }
    }
}

9.配置完成以后public里面有你写的对应的网站的信息的话,你已经成功一般了,接下里让我们运行 起来项目 npm run dev npm run start 然后还需要运行起来你的server文件下面的服务器 也是再黑色窗口运行 SET DEBUG=server:* & npm start 我这里输入的server是对应的文件名称,你可以改成自己文件名然后执行回车就跑起来了,然后再地址地址栏输入:http://localhost:4000 是打开的你服务端的页面,http://localhost:4001 这个才是打开你自己创作的网页的,完成以上操作你的静态网页基本上已经完成了,接下里就是写js 和 路由进行操作交互了..............

10.然后接下来需要操作的是src文件下的东西
	需要创建scr文件下面还有css文件,js文件,view文件,app,js  需要在js文件下面创建两个文件夹 在user文件下面创建 3个分分别是login main logup js文件 在router文件下创建userRouter.js文件
	1.userRouter.js配置如下:
			import Router from "sme-router";
			import logins from "../../view/logins.art";
			import logUp from "../../view/signup.art";


			import userMain from '../user/main.js';
			import userLogin from '../user/login.js';
			import userLogup from '../user/logup.js';


			var userRouter = new Router("app");
			userRouter.route("/main", function (req, res, next) {
			    $(".active").removeClass("active");
			    $("#main").addClass("active"); userMain(res);
			    userMain(res);
			})

			userRouter.route("/login", function (req, res, next) {
			    res.render(logins());
			    userLogin();//调用导出的登录js
			    $(".active").removeClass("active");
			    $("#login").addClass("active");
			})

			userRouter.route("/logup", function (req, res, next) {
			    res.render(logUp());
			    userLogup();//调用导出的注册的js
			    $(".active").removeClass("active");
			    $("#logup").addClass("active");
			})


			userRouter.route('/login', function (req, res, next) {
			    res.render(logins());
			    userLogin();
			    $('.active').removeClass('active');
			    $('#login').removeClass('active');
			})


			userRouter.route("/logup", function (req, res, next) {
			    res.render(logUp());
			    userLogup();
			    $('.active').removeClass('active');
			    $('#logup').removeClass('active');
			})


			userRouter.route("/logout", async function (req, res, next) {
			    var result = await fetch("http://localhost:4001/api/users/logout", {
			        method: 'POST'
			    });
			    var data = result.json();
			    $('.active').text('未登录');
			    if (!data.err) {
			        userRouter.go('/main')
			    }
			})

		export default userRouter;

		2.login.js如下:
			import userRouter from "../router/userRouter.js";
			function userLogin () {
			    $("#logoutBn").css("display", "none");
			    $("#loginBn").css("display", "block");
			    // $("li").attr("style", "display: none;");
			    $('#main').hide();//点击隐藏

			    $("#form_login").on("submit", loginHandler);
			}

			async function loginHandler (e) {
			    e.preventDefault();
			    var fd = new FormData(this);
			    var res = await fetch("http://localhost:4001/api/users/login", {
			        method: "post",
			        body: fd
			    })
			    var data = await res.json();
			    if (data.err) {
			        alert("登录失败");
			    } else {
			        $("#username").text(data.username);
			        $("#logoutBn").css("display", "block");
			        $("#loginBn").css("display", "none");
			        $('#main').show("display", "block");//点击显示
			        userRouter.go("/main");
			    }
			}
			export default userLogin;
		3.logup.js文件如下
			import userRouter from "../router/userRouter.js";
			function userLogup () {
			    $("#form_logup").on("submit", submitHandler);
			}

			async function submitHandler (e) {
			    e.preventDefault();
			    var fd = new FormData(this);
			    var res = await fetch("http://localhost:4001/api/users/logup", {
			        method: "post",
			        body: fd
			    });
			    var data = await res.json();
			    if (!data.err) {
			        userRouter.go("/login");
			    } else {
			        alert(data.err);
			    }
			}

			export default userLogup;
		4.创建main.js文件如下
				import main from '../../view/main.art'

				async function userMain (res) {
				    var result = await fetch("http://localhost:4001/api/main", {
				        method: 'POST',
				    })
				    var data = await result.json();
				    res.render(main(data))
				}
				export default userMain//导出


在view问价下面床架login.art main.art siginp.art三个文件
	1.<div class="login-container">
	<div class="login-progressbar">
		<div>登录</div>
	</div>

	<div class="login-form">

		<div class="login-content">

			<div class="form-login-error">
				<h3>Invalid login</h3>
				<p>Enter <strong>demo</strong>/<strong>demo</strong> as login and password.</p>
			</div>

			<form method="post" role="form" id="form_login" novalidate="novalidate">

				<div class="form-group">

					<div class="input-group">
						<div class="input-group-addon">
							<i class="entypo-user"></i>
						</div>

						<input type="text" class="form-control" name="username" id="username" placeholder="Username" autocomplete="off">
					</div>

				</div>

				<div class="form-group">

					<div class="input-group">
						<div class="input-group-addon">
							<i class="entypo-key"></i>
						</div>

						<input type="password" class="form-control" name="password" id="password" placeholder="Password" autocomplete="off">
					</div>

				</div>

				<div class="form-group">
					<button type="submit" class="btn btn-primary btn-block btn-login">
						<i class="entypo-login"></i>
						Login In
					</button>
				</div>
			</form>
		</div>

	</div>

</div>
	第二个
		<table class="table table-bordered datatable dataTable" id="table-1" aria-describedby="table-1_info">
	<thead>
		<tr role="row">
			<th data-hide="phone" class="sorting_asc" role="columnheader" tabindex="0" aria-controls="table-1"
				rowspan="1" colspan="1" aria-sort="ascending"
				aria-label="Rendering engine: activate to sort column descending">序号</th>
			<th class="sorting" role="columnheader" tabindex="0" aria-controls="table-1" rowspan="1" colspan="1"
				aria-label="Browser: activate to sort column ascending">用户名</th>
			<th data-hide="phone" class="sorting" role="columnheader" tabindex="0" aria-controls="table-1" rowspan="1"
				colspan="1" aria-label="Platform(s): activate to sort column ascending">年龄</th>
			<th data-hide="phone" class="sorting" role="columnheader" tabindex="0" aria-controls="table-1" rowspan="1"
				colspan="1" aria-label="Platform(s): activate to sort column ascending">手机号</th>
			<th data-hide="phone" class="sorting" role="columnheader" tabindex="0" aria-controls="table-1" rowspan="1"
				colspan="1" aria-label="Platform(s): activate to sort column ascending">邮箱</th>
			<th data-hide="phone" class="sorting" role="columnheader" tabindex="0" aria-controls="table-1" rowspan="1"
				colspan="1" aria-label="Platform(s): activate to sort column ascending">操作</th>
		</tr>
	</thead>

	<tbody role="alert" aria-live="polite" aria-relevant="all">

		{{each list}}
		<tr class="gradeA {{$index%2===0 ? 'even' : 'odd'}}">
			<td class="  sorting_1">{{$index}}</td>
			<td class=" ">{{$value.username}}</td>
			<td class=" ">{{$value.age}}</td>
			<td class=" ">{{$value.tel}}</td>
			<td class=" ">{{$value.email}}</td>
			<td class=" ">
				<button class="span1-button--warning left">增加</button>
				<button class="span2-button--warning left">修改</button>
				<button class="span3-button--danger left">删除</button>
			</td>
		</tr>
		{{/each}}
	</tbody>
</table>
第三个
	<div class="login-container">



	<div class="login-form">

		<div class="login-content">

			<div class="form-login-error">
				<h3>注册</h3>
				<p>Enter <strong>demo</strong>/<strong>demo</strong> as logup and password.</p>
			</div>

			<form method="post" role="form" id="form_logup" novalidate="novalidate">

				<div class="form-group">
					<div class="input-group">
						<div class="input-group-addon">
							<i class="entypo-user"></i>
						</div>

						<input type="text" class="form-control" name="username" id="username" placeholder="Username" autocomplete="off">
					</div>
				</div>

				<div class="form-group">
					<div class="input-group">
						<div class="input-group-addon">
							<i class="entypo-key"></i>
						</div>
						<input type="password" class="form-control" name="password" id="password" placeholder="Password" autocomplete="off">
					</div>
				</div>



				<div class="form-group">
					<div class="input-group">
						<div class="input-group-addon">
							<i class=""></i>
						</div>
						<input type="name" class="form-control" name="name" id="name" placeholder="name" autocomplete="off">
					</div>
				</div>

				<div class="form-group">
					<div class="input-group">
						<div class="input-group-addon">
							<i class=""></i>
						</div>
						<input type="age" class="form-control" name="age" id="age" placeholder="age" autocomplete="off">
					</div>
				</div>

				<div class="form-group">
					<div class="input-group">
						<div class="input-group-addon">
							<i class=""></i>
						</div>
						<input type="tel" class="form-control" name="tel" id="tel" placeholder="tel" autocomplete="off">
					</div>
				</div>

				<div class="form-group">
					<div class="input-group">
						<div class="input-group-addon">
							<i class=""></i>
						</div>
						<input type="email" class="form-control" name="email" id="email" placeholder="email" autocomplete="off">
					</div>
				</div>
				<div class="form-group">
					<button type="submit" class="btn btn-primary btn-block btn-login">
						<i class="entypo-login"></i>
						Login Up
					</button>
				</div>
		</div>

	</div>

</div>
按照顺序创建以上文件,然后把代码赋值到对应的我文件里去
	1.到这里差不多了,然后npm i 下载跟新插件,需要把server文件运行起来,然后再邮箱client文件然后
	2.client在终端打开 npm i   npm start  然后去浏览器数据http://localhost:4001是服务端,http://localhost:4000客户端 ,如果不详细 私信源码

;