SEU_scheduleV1.0


特殊时期,被迫宅在家中无所事事,就想学一下简单的后端,搭建一个数据库。肝了整整三天 ,终于从零开始完成了一个简单的demo,还是蛮有成就(cu si )感的。
现在把搭建过程记录一下,也算一个小型数据库的搭建教程。

SEU_scheduleV1.0:http://byzeal.cn/SEU/SEU_schedule.html
SEU_scheduleV1.0:http://49.232.58.172/SEU/SEU_schedule.html

(由于2020.2.13前新域名都在备案,所以给出服务器地址吧qwq)

这是一个小工具,把学校课程做成数据库,前端做成了动态表格,实现了查询、分页、筛选的功能

思路概括

一个好的网页项目,需要有舒适体验的前端以及不掉链子的后端。之前不管是写自己的主页还是在csdn上写博客,不管是html还是md,我的体验都局限于静态页面,从未接触过真正的数据库。所以这次我把重点放在了研究后端上,在开始写网页前,查了很多关于数据库的资料,最终确定了自己的数据库形式。
总的来说,就是搭建前台,前台做好response和request响应;搭建后台,将需要的数据导入数据库;再写好数据库及其接口,使其能处理response和request;接下来,在接口的基础上写一些处理不同request的函数,比如搜索引擎,分页算法等等;最后,做一些润色工作,使网页体验更加舒适。当然,在每一步的尝试中,我都遇到了很多困难,换了很多种不同的实现方法。开始尝试了mysql、mongodb、lowdb等等,后来不断遇到问题不断换思路,东拼西凑了一堆方法方法最终实现了这个小工具(最终是用layui+nodejs+json小数据库实现)。

实现过程

1.爬取数据

选择你想要爬取数据的来源,我选择的是学校的教务处网站
SEU教务处的数据服务地址:http://xk.urp.seu.edu.cn/jw_service
注意:爬取数据的网址尽量选一些校园网,公益教育网之类的,不然处理繁杂的数据也不是一件易事。
基于python urllib和request包,从服务器中爬取数据,具体细节就不说了,这并不是重点。

有趣的是,在爬取数据的过程中,意外的发现在服务器中竟然存在着静态的数据文件。所以没花多长时间就搞到了全校的课程数据。之后数据可以选择先保存成txt(注意编码,不是utf-8可能之后会出现汉字乱码问题),也可以用pandas转成excel(我转成了excel),方便之后的转化。

2.处理数据:excel数据与json数据转换

.json是很多数据库与前端交换数据的文件形式,我们可以先将上一步爬到的数据变成json文件
这里介绍一个很好的转换工具http://excel.wj2015.com/,提供layui数据格式转换。由于我确定要使用layui完成前端,所以在转换完成后格式上不需要更改。如果你使用别的数据格式,根据data[]数组进行修改即可。

layui数据格式:
在这里插入图片描述
如果只保留data数组:
在这里插入图片描述
在数据对象中A属性我设置成了编号,想着之后检索快一点(事实证明似乎没有卵用

3.后端准备:选择数据接口

有什么方便的,不需要新学动态网页语言的,操作简单的数据接口搭建方式吗?有的!!!就是nodejs!!!
百度百科是这么描述它的:

Node 是一个让 JavaScript 运行在服务端的开发平台,它让 JavaScript 成为与PHP、Python、Perl、Ruby
等服务端语言平起平坐的脚本语言。

完全不需要接触php,在nodejs的运行环境中,你可以轻松的用JavaScript 搭建自己的数据接口。

安装与配置nodejs的教程在这里:nodejs

安装完nodejs后,其实还需要安装一堆扩展包,后面都会用到。这里我就先总结一下
需要:express、body、cors

npm install -g express –registry=https://registry.npm.taobao.org

它们安装都在cmd终端,指令格式可以参考上条语句

nodejs本体和扩展包都安装完了就可以开始工作了

先做一个服务器测试,新建test.js脚本

var express = require("express");
var app = express();
app.listen(3000);
app.get("/",function(req,res){
  res.send("第一个本地服务器");
});

终端执行

node test.js

用浏览器打开127.0.0.1:3000
在这里插入图片描述
测试成功

接下来就是搭建数据接口了
这里给出我做好的数据接口

const express=require('express');
const cors=require('cors');
const app=express();
app.listen(7979,()=>console.log('server start'));
app.use(cors());
app.all('*', (req, res) => 
{
    console.log(req.query);
    console.log(req.query.page);
    res.json("这里是你想要返回给前台的数据");
}
});

cors=require(‘cors’) 必须要用,跨域访问,这就是之前需要安装的扩展包,我在这卡了好长时间T^T,没有它访问就是空白
app.listen(7979)表示监听7979端口,这个任意设置,只要不与你的服务器上其他端口重合就行
console.log(req.query) 用于在cmd上显示日志,合理添加一些console.log可以方便地掌握数据交换全过程
res.json() 以json文件形式返回,res共有三种,详情见nodejs的api文档

日志信息
在这里插入图片描述

4.前端html设计

选择layui框架来做表格,用了一次过于上瘾,甚至以后所有的博客都想用layui写
给出表格框框的代码

function tablefun(_table, _type, _data) {
      
      _table.render({
        elem: '#type' + _type
        , data: _data 
        , page: true
		, toolbar: '<div><b style="color:#009688">2019-2020-3</b></div>' 
		, defaultToolbar: []
        , cols: [[ 
       {field:'B', title: '课程名', width:200, sort: true}
      ,{field:'C', title: '面向年级', width:120,sort: true}
      ,{field:'D', title: '任课教师', width:120}
      ,{field:'E', title: '上课安排', width:350}
      ,{field:'F', title: '开设院系', width:230,sort: true} 
      ,{field:'point', title: '学分', width: 100} 
    
    ]],
        text: {
          none: '没有查到想要的课程(T^T),缩小关键词试试?' 
        }
      });
    }

因为我需要分页和搜索的功能,所以我单写了一个table函数出来,如果只是官方标准表格的话,用一个简单的渲染就可以了

上述代码实现效果
在这里插入图片描述
搜索框的实现代码

<div class="layui-form-item">
<label class="layui-form-label">课程名:</label>
<div class="layui-input-block">
<input type="text" class="layui-input layui-input-wide" name="B"  placeholder="课程关键词,eg:计算机科学基础Ⅱ" autocomplete="off">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">任课教师:</label>
<div class="layui-input-block">
<input type="text" class="layui-input layui-input-wide" name="D"  placeholder="需查询的姓名,eg:万国瑞" autocomplete="off">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">时间/地点:</label>
<div class="layui-input-block">
<input type="text" class="layui-input layui-input-wide" name="E"  placeholder="查询时间或者地点,eg:周五 或 教八" autocomplete="off">
</div>
</div>
<div class="layui-form-item">
    <label class="layui-form-label">开课学院:</label>
    <div class="layui-input-block">
      <select name="F" >
        <option value=""></option>
        <option value="教务处">教务处</option>
<option value="[01]建筑">[01]建筑</option>
//这里是一堆选择,按照自己需求添加
<option value="[TJ]工科试验班 (土木交通类)">[TJ]工科试验班 (土木交通类)</option>
      </select>
    </div>
  </div>  

<div class="layui-form-item">
<label class="layui-form-label"></label>
<div class="layui-input-inline">
<button class="layui-btn" lay-submit lay-filter="search">查询</button>
<button type="reset" class="layui-btn layui-btn-primary" onclick="ResetSearch()">重置</button>
</div>
</div>
</form>

搜索框的实现效果
在这里插入图片描述
在这里插入图片描述

5.实现前端到后端数据传递:$.ajax和request

由于我设想的功能是搜索和数据分页显示,所以我需要构建两个请求

对于分页的请求:layui表格模块自己有一个request请求参数,向后台返回用户选择要看第几页和页面大小两个参数(详情见layui文档),在后台捕捉就可以了。

对于搜索的请求:这其实就是一般化的前端请求,我们需要用$.ajax发送
在网页中引入jquery

<head>
<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js">
</script>
</head>

建议使用百度镜像,现存的版本都比较稳定

$.ajax请求格式如下(这不是网页中源码,网页中ajax很简陋,这里放一个完整版ajax看得更清楚一点)
关于 $.ajax具体配置这里有详细解释:ajax

$(function(){
    $('#send').click(function(){
         $.ajax({
             type: "GET",
             url: "test.json",
             data: {username:$("#username").val(), content:$("#content").val()},
             dataType: "json",
             success: function(data){
                         $('#resText').empty();   //清空resText里面的所有内容
                         var html = ''; 
                         $.each(data, function(commentIndex, comment){
                               html += '<div class="comment"><h6>' + comment['username']
                                         + ':</h6><p class="para"' + comment['content']
                                         + '</p></div>';
                         });
                         $('#resText').html(html);
                      }
         });
    });
});

6.实现自己的搜索引擎&分页算法

这部分是最肝的地方,需要设计一些算法。因为没有学过js,很多处理数据的函数都不太会用,所以每写一点都要查好多资料,最后的实现函数写得也不是很好,回过来再看简直是一坨屎山 ,以后慢慢再修改算法吧······

先是分页算法:

function pagination(page, limit, array) {
   offset = (page - 1) * limit;
   return array.slice(offset, offset + limit);
}

function pagetest(a,b,c){
    arr2 = pagination(a,b,c);
    ob2 = {"code":0,"msg":"","count":3206,"data":arr2};
  return ob2;
}

这两个函数第一个是核心,根据前台传过来的两个参数page limit确定需要发送的数据;第二个函数则是将确定要发送的数据封装成layui表格可以接受的形式。
注意count:3206这一句是数据条数,因为我的数据不会变所以直接写出来,数据条数变时需要改成数据数组的长度

然后是搜索算法:

for (i in AllData) {
          var flag = true;
		  if (gtype > 0) {
            flag &= AllData[i].t_type == gtype;
          }
          
          if (last_param['B'] != '') {
            flag &= (AllData[i].B||"").toLowerCase().indexOf(last_param['B'].toLowerCase()) > -1;
          }
          if (last_param['D'] != '') {
            flag &= (AllData[i].D||"").toLowerCase().indexOf(last_param['D'].toLowerCase()) > -1;
          }
          if (last_param['E'] != '') {
            flag &= (AllData[i].E||"").toLowerCase().indexOf(last_param['E'].toLowerCase()) > -1;
          }
          if (last_param['F'] != '') {
            flag &= (AllData[i].F||"").toLowerCase().indexOf(last_param['F'].toLowerCase()) > -1;
          }
          if (flag) tmpData.push(AllData[i]);
        }

这个刚开始封装成函数了,后来修改了一堆自己也搞不清了,就单拎出来核心算法好了。alldata经过B D E F的限制最后得到tmpdata为搜索后筛选出来的数据。
讲道理,一个普通的模糊搜索算法应该不是很难,但是因为不熟悉各种字符串、对象的操作,这里耽误了不少时间。
这些函数都可以在JavaScript文档中找到,没有什么特别需要注意的。
简单给出描述:
toLowerCase() 用于把字符串转换为小写
indexOf() 可返回某个指定的字符串值在字符串中首次出现的位置,没有查到就返回-1,老亲切的形式了,业界规矩

7.收尾:润色移动端转码

上述工作全部串起来,再自己写写页面,基本就完工了。
我的页面整体布局是这样
在这里插入图片描述
PC端的体验还算良好,然后去试一下移动端(自己手机有问题还找同学的手机进行调试T^T)
发现页面是这样的
在这里插入图片描述
发现手机上完全按照PC端的格式显示出来了,而手机屏幕小可能没有办法看清楚课程信息,所以就想着能不能让屏幕网页自适应屏幕大小。查了一些资料,发现< meta >就可以实现layui的自适应。
只需在网页中加入这句话

< meta name=“viewport” content=“width=device-width, initial-scale=1, maximum-scale=1”>

加入后网页效果:
在这里插入图片描述
okk这样移动端的优化就做完啦,到此第一版SEU_schedule就全部完工了。以后还会不定时更新一下(ノ゚▽゚)ノ(maybe

SEU_schedule开源链接

SEU_scheduleV1.1-master