分类

课内:
不限
类型:
不限 毕业设计 课程设计 小学期 大作业
汇编语言 C语言 C++ JAVA C# JSP PYTHON PHP
数据结构与算法 操作系统 编译原理 数据库 计算机网络 软件工程 VC++程序设计
游戏 PC程序 APP 网站 其他
评分:
不限 10 9 8 7 6 5 4 3 2 1
年份:
不限 2018 2019 2020 2021

资源列表

  • 基于JAVA实现的2048小游戏

    一、实现方案本游戏采用Java语言编写,使用Eclipse编译器, jdk1.7.0_51编译环境。游戏的UI主要运用Java图形界面编程(AWT),实现窗口化可视化的界面。
    游戏的后台通过监听键盘方向键来移动数字方块,运用随机数的思想随机产生一个2或4的随机数,显示在随机方块中,运用二维数组存储、遍历查找等思想,在每次移动前循环查找二维数组相邻的移动方向的行或列可以合并与否,如果没有可以合并的数字方块同时又没有空余的空间产生新的数字则游戏宣告结束,同时,当检测到合并的结果中出现2048,也宣告游戏结束。
    游戏设计了非常简单的交互逻辑,流程如下:

    为了增加游戏的用户体验,后期加入了操作音效(音效文件提取自百度移动应用商店——2048),在移动和合并方块时播放不同声音。
    二、具体代码及程序框图分析整个游戏有三个类,分别为游戏的主类Game.class、事件处理类MyListener.class、声音处理类PlaySound.class,下面对Game.class和MyListener.class进行说明。
    Game.class的简单程序框图如下:

    游戏的主类Game.class是窗体程序JFrame的扩展类,主要负责界面的搭建,完成界面绘图的工作。该类作为主类,主方法public static void main(String[] args)中先新建一个该类的对象,接着调用用与创建界面控件的方法IntUI(),代码如下:
    public static void main(String[] args) { Game UI = new Game(); UI.IntUI();}
    IntUI()方法用于JFrame控件及界面框架的搭建,代码解析如下:
    首先创建一个窗体,标题为“2048小游戏”,把坐标固定在屏幕的x=450,y=100的位置,把窗体大小设置为宽400像素高500像素,然后把JPlane的布局管理器设置为空,具体代码如下:
    this.setTitle("2048小游戏");this.setLocation(450, 100);this.setSize(400, 500);this.setLayout(null);
    接下来分别是【新游戏】、【帮助】、和【退一步】的按钮,以【新游戏】按钮为例,创建一个新游戏的图片按钮,图片相对路径为res/start.png,为了达到更美观的显示效果,把聚焦,边线等特征设置为false,把相对窗体的坐标设置为(5, 10),大小设置为宽120像素高30像素,具体代码如下:
    ImageIcon imgicon = new ImageIcon("res/start.png"); JButton bt = new JButton(imgicon); bt.setFocusable(false); bt.setBorderPainted(false); bt.setFocusPainted(false); bt.setContentAreaFilled(false); bt.setBounds(-15, 10, 120, 30);this.add(bt);
    而分数显示控件与按钮控件类似,不再赘述。
    布置好控件后,为了彻底结束进程,不再占用内存,使用 System exit 方法退出应用程序,同时由于按钮都是相对窗体固定坐标的,所以不允许用户随意改变窗体大小,最后把界面设置为可见,具体代码如下:
    this.setDefaultCloseOperation(3);this.setResizable(false);this.setVis ible(true);
    对于按钮的监听,是在 MyListener.class 中处理的,在 IntUI 中只是新建一个对象来引用该类,该类具体后面会有说明,这里引用的代码如下:
    MyListener cl = new MyListener(this, Numbers, lb, bt, about, back);bt.addActionListener(cl);about.addActionListener(cl);back.addActionListener(cl);this.addKeyListener(cl);
    IntUI 方法至此结束。
    接下来便是游戏中大方框和数字小方框的绘制,这里用到了 paint 方法来绘制容器。 paint 方法不需要调用,只需要重写。
    在继承父类的方法后,先绘制出大矩形框,为了美观,这里绘制圆角矩形框,底色的 16 进制值为:0xBBADA0,边长为 370 像素,在窗口的相对位置为 x=15 像素,y=110 像素,上下弧度为 15,代码如下:
    super.paint(g);g.setColor(new Color(0xBBADA0));g.fillRoundRect(15, 110, 370, 370, 15, 15);
    接下来,通过双重循环,绘制 4*4 的小方框,关于小方框的绘制的相对位置这里有个关键的算法,因为每一个小方框都要距离边框及相邻边框的大小相等才能达到相对美观的效果,以水平方向为例,分析如下:
    因为总的宽度为 370 像素,假如让每个小方框的间距为 10 像素,那么在 370 像素里面除去 5 个小方框距离的像素值 10*5=50 像素外,还剩下 320 像素,一行 4 个方框,正好 80 像素一个小方框。在写这双重循环前,可以先绘制了一个简单的位置图如下:

    以第一行的横坐标为例,每绘制完一个小方框,绘制下一个小方框时就要加上前一个方框的宽度,再加上边框之前的距离,所以绘制 4*4 颜色为 0xCDC1B4 的小边框的双重循环的代码如下:
    g.setColor(new Color(0xCDC1B4));for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { g.fillRoundRect(25 + i * 90, 120 + j * 90, 80, 80, 15, 15); } }
    由于 2048 游戏里面可能显示的数值有 2、4、8、16 等等不同的数值,同样是为了美观考虑,我们给显示不同数值的方框绘制不同的颜色,同样,由于一位数字 2 与两位数字 16 甚至多位数字 128 或 1024 等来说,如果显示的位置与大小相同,那么 2 等一位数字的显示是完美的,但是 2048 这些数字的显示就会超出小方框,影响观感所以还要对数字的相对位置和大小做一定的调整,这里的具体代码如下:
    for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { if (Numbers[j][i] != 0) { int FontSize = 30; int MoveX = 0, MoveY = 0; switch (Numbers[j][i]) { case 2: g.setColor(new Color(0xeee4da)); FontSize = 30; MoveX = 0; MoveY = 0; break; case 4: g.setColor(new Color(0xede0c8)); FontSize = 30; MoveX = 0; MoveY = 0; break; case 8: g.setColor(new Color(0xf2b179)); FontSize = 30; MoveX = 0; MoveY = 0; break; case 16: g.setColor(new Color(0xf59563)); FontSize = 29; MoveX = -5; MoveY = 0; break; case 32: g.setColor(new Color(0xf67c5f)); FontSize = 29; MoveX = -5; MoveY = 0; break; case 64: g.setColor(new Color(0xf65e3b)); FontSize = 29; MoveX = -5; MoveY = 0; break; case 128: g.setColor(new Color(0xedcf72)); FontSize = 28; MoveX = -10; MoveY = 0; break; case 256: g.setColor(new Color(0xedcc61)); FontSize = 28; MoveX = -10; MoveY = 0; break; case 512: g.setColor(new Color(0xedc850)); FontSize = 28; MoveX = -10; MoveY = 0; break; case 1024: g.setColor(new Color(0xedc53f)); FontSize = 27; MoveX = -15; MoveY = 0; break; case 2048: g.setColor(new Color(0xedc22e)); FontSize = 27; MoveX = -15; MoveY = 0; break; default: g.setColor(new Color(0x000000)); break; } g.fillRoundRect(25 + i * 90, 120 + j * 90, 80, 80, 10, 10); g.setColor(new Color(0x000000)); g.setFont(new Font("Arial", Font.PLAIN, FontSize)); g.drawString(Numbers[j][i] + "", 25 + i * 90 + 30 + MoveX,120 + j * 90 + 50 + MoveY); } } }
    至此,Game.class 的分析结束,下面是对按钮监听及时间处理的 MyListener.class 的分析。
    MyListener.class 是一个键盘监听事件的扩展类,该类的简单程序框图如下:

    在该类的开始,先声明一些变量,如用于接收传递进来的数组Numbers[][],随机数rand,备份数组用的BackUp[][],BackUp2[][]等等,代码如下:
    private Game UI; private int Numbers[][];private Random rand = new Random();private int BackUp[][]= new int[4][4]; private int BackUp2[][]= new int[4][4]; public JLabel lb;int score = 0;int tempscore,tempscore2; public JButton bt,about,back;private boolean isWin=false, relive=false, hasBack=false, isSound=true;
    然后是MyListener的构造方法,把来自Game类中传进来的参数接收,代码如下:
    public MyListener(Game UI, int Numbers[][], JLabel lb,JButton bt,JButton about,JButton back,JCheckBox isSoundBox) { this.UI = UI; this.Numbers = Numbers; this.lb = lb; this.bt=bt; this.about=about; this.back=back; this.isSoundBox=isSoundBox; }
    接下来是按钮的监听,通过e.getSource()取得按钮相应的值,进行相应的处理,下面分别解析下【新游戏】按钮和【退一步】按钮的代码:
    【新游戏】按钮作为游戏的开始,将会在按下该按钮是初始化很多数据,例如游戏胜利标志,分数值,4*4的二维数组等,该按钮的控制代码的工作逻辑是这样的:先把胜利标志置为false,然后通过双重循环,把所有的小方格的数据初始化为0,接着把分数值置为0,接下来分别定义四个4以内的随机数整型变量,两两为行数和列数,当它们组合相等时再重新产生两个新的,直到不相等为止,然后生成2个2或者4的数字赋值到对应的位置,完成赋值后,重写一次paint函数,把数组的非零元素绘制在对应位置的小方框内,代码如下:
    if(e.getSource() ==bt ){ isWin=false;for (int i = 0; i < 4; i++) for (int j = 0; j < 4; j++) Numbers[i][j] = 0; score = 0; lb.setText("分数:" + score); int r1 = rand.nextInt(4); int r2 = rand.nextInt(4); int c1 = rand.nextInt(4); int c2 = rand.nextInt(4); while (r1 == r2 && c1 == c2) { r2 = rand.nextInt(4); c2 = rand.nextInt(4); } int value1 = rand.nextInt(2) * 2 + 2;int value2 = rand.nextInt(2) * 2 + 2; Numbers[r1][c1] = value1; Numbers[r2][c2] = value2; UI.paint(UI.getGraphics());}
    【退一步】按钮分了两种情况考虑,为了出现退一步继续按【退一步】按钮出现异常情况,加了一个是否已经进行过一次回退操作了的标志hasBack,进入回退按钮的操作后,先判断是否是起死回生类型的回退,如果不是起死回生类型的回退则把非起死回生分数备份的变量tempscore赋值回记录分数的变量score,然后循环调用java.util.Arrays.copyOf()方法复制数组,把备份的数组复制回去Numbers数组;如果是起死回生类型的回退,重新复制等操作和前面是一样的,不同点在于起死回生类型的回退在操作后,把起死回生回退的标志relive重新置为false。在完成这些操作后,重新绘图,代码如下:
    else if(e.getSource()==back&&hasBack==false){ hasBack=true; if(relive==false){ score=tempscore; lb.setText("分数:" + score); for(int i=0;i<BackUp.length;i++){ Numbers[i]=Arrays.copyOf(BackUp[i], BackUp[i].length); } } else{ score=tempscore2; lb.setText("分数:" + score); for(int i=0;i<BackUp2.length;i++){ Numbers[i]=Arrays.copyOf(BackUp2[i], BackUp2[i].length); } relive=false; } UI.paint(UI.getGraphics()); }
    下面是按键监听的解析,按键监听通过相应的键值识别按键,然后运用switch开关语句控制不同按键的事件。在处理所有时间之前,先定义三个整型变量,用于计数,然后判断BackUp数组是否为空,因为第一次运行时用于普通数组备份的BackUp数组是没有任何东西的,直接拿来备份会报异常。在备份好数组后,就是对应的键值的监听,以按下方向键左为例(其它三个方向键处理方式基本相同,只是行列及方向的区别),向左移动时,采用三个双重循环,三个循环均为外循环的变量h控制行数,内循环变量l控制列数。在第一个双重循环中,内循环先遍历每一列,判断该列的前一列是否为0,如果前一列为0,则把该列赋值给一个临时变量,把临时变量的值赋值给前一列,然后把该列置0;外循环是遍历行数,每完成一行的操作转至下一行继续重复操作。该操作的代码如下:
    for (int h = 0; h < 4; h++) for (int l = 0; l < 4; l++) if (Numbers[h][l] != 0) { int temp = Numbers[h][l]; int pre = l - 1; while (pre >=0 && Numbers[h][pre] == 0) { Numbers[h][pre] = temp; Numbers[h][pre + 1] = 0; pre--; Counter++; } }
    在完成一次靠左移动后,接下来的双重循环使用来合并小方格中数字相同的元素的,把他们相加并放到靠左的方格中,同样外循环是用来控制行数,内循环控制列数,在内循环中加了一个判断条件,当列数加1小于4时(因为只需循环到第三列即可完成该操作),同时该列与该列+1的那一列的元素值相等且它们都不等于0时,即可进行合并操作,合并后,把该列的值置为两元素相加的结果,并把该列+1列置为0,然后把统计是否移动了的计数器进行一个自增操作。完成该操作的代码如下:
    for(int h=0;h<4;h++) for(int l=0;l<4;l++) if(l+1<4&&(Numbers[h][l]==Numbers[h][l+1])&&(Numbers[h][l]!=0||Number s[h][l+1]!=0)){ new PlaySound("merge.wav").start(); Numbers[h][l]=Numbers[h][l]+Numbers[h][l+1]; Numbers[h][l+1]=0; Counter++; score+=Numbers[h][l]; if(Numbers[h][l]==2048){ isWin=true; } }
    在完成该操作后,为了避免合并后,出现方块不在最左边的情况,还需要一次整体遍历左移,这次整体遍历左移和第一次的双重循环一样,所以这里不再分析。
    在完成移动及合并操作后,要判断相邻的方块是否还能合并,因为有可能出现移动后,相邻的方块又能进行新的合并,如果不加这个判断的话,当所有的方块全部填满时会无判断游戏结束。
    这里判断相邻的新的方块是否能进一步合并也是用到双重循环,外循环控制行数,内循环控制列数,逐个判断下和右是否能进一步合并,如果能则相邻方块的计数器做自增操作,代码如下:
    for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (Numbers[i][j] == Numbers[i][j + 1]&& Numbers[i][j] != 0) { NumNearCounter++; } if (Numbers[i][j] == Numbers[i + 1][j]&& Numbers[i][j] != 0) { NumNearCounter++; } if (Numbers[3][j] == Numbers[3][j + 1]&& Numbers[3][j] != 0) { NumNearCounter++; } if (Numbers[i][3] == Numbers[i + 1][3]&& Numbers[i][3] != 0) { NumNearCounter++; } }}
    在完成上述操作后,在判断非0元素的个数,应为当非零元素个数为0时,即代表所有的小方块中已经有元素存在了,16个方块全部都满了,这里的代码如下:
    for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { if (Numbers[i][j] != 0) { NumCounter++; } } }
    在完成统计空格个数后,如果按下按键后发生了移动,就完成分数的更新,因为要移动一次后在随机的空的格子(这里指元素值为0的格子)里面产生新的基于2或者4的随机数,代码如下:
    if (Counter > 0) { lb.setText("分数:" + score); int r1 = rand.nextInt(4); int c1 = rand.nextInt(4); while (Numbers[r1][c1] != 0) { r1 = rand.nextInt(4); c1 = rand.nextInt(4); } int value1 = rand.nextInt(2) * 2 + 2; Numbers[r1][c1] = value1; }
    接下来判断这次移动后,有没有出现 isWin == true 的情况,如果出现了,就弹出游戏胜利的标志,代码如下:
    if (isWin == true){ UI.paint(UI.getGraphics()); JOptionPane.showMessageDialog(UI, "恭喜你赢了!\n 您的最终 得分为:" + score); }
    然后,判断是否是16个格子全满了同时相邻的方格不能进一步合并了,如果是则把可以进行起死回生操作的标志relive置为true,同时弹出游戏结束的提示语,代码如下:
    if (NumCounter == 16 && NumNearCounter == 0) { relive = true; JOptionPane.showMessageDialog(UI, "没地方可以合并咯!!" + "\n 很遗憾,您输了~>_<~" + "\n 悄悄告诉你,游戏有起死回 生功能哦,不信你“退一步”试试?" + "\n 说不定能扭转乾坤捏 (^_~)"); }
    最后,重新绘制图形。
    MyListener 类的分析到此结束。
    三、程序演示游戏初始界面

    游戏画面

    游戏失败画面
    3 评论 172 下载 2019-01-03 19:29:17 下载需要11点积分
  • 基于JAVA的聊天室

    聊天室系统
    一、课程设计要求与目的目的:编写一个小型Java聊天室系统,掌握Java网络通信、多线程、IO文件操作等高级应用编程技能。
    完成如下功能:

    多客户端模式下,实现客户与客户的单独通信,要求信息通过服务器中转
    端到端的通信,实现并行通信模式(不再是你说一句,我说一句,一端的信息发送不受另一端的影响)
    实现端到端的文件传输
    添加图形界面(选做)

    二、系统设计服务器端:分为两个class文件,一个是MultiTalkServer类,还有一个是ServerThread类。MultiTalkServer实现的功能有:监听客户请求,根据得到的Socket对象和客户计数创建服务线程,并启动。将serverSocket.accept()返回的socket作为参数,传入到ServerThread中。
    ServerThread实现的功能有:判断是否下线,判断IP地址是否正确,判断目标客户是否在线,判断是否传输文件,获取目标的socket套接字。

    三、系统实现服务器端:

    MultiTalkServer:
    public class MultiTalkServer{ 静态成员变量,记录当前客户的个数 public static void main(String args[]) { 初始化 新建服务器套接字 while(listening){//监听 监听到客户请求,根据得到的Socket对象和客户计数创建服务线程,并启动它 }
    ServerThread:
    public class ServerThread extends Thread{ 数据成员: 保存与本线程相关的Socket对象/保存本进程的客户计数新建哈希表,用于保存用户的Ip与socket的键值对String IP用于保存IP地址的模板 构造方法 初始化socket变量 初始化clientnum变量将IP和socket放入哈希表中 splitMessage判断用户是否退出当发送空消息或发送“quit”时则退出 用于发送文件 SendDocument 用于创建输入输出流并收发文件 线程主体run() //获取哈希表的大小并输出; //创建输入输出流 while(true) {//监听 ①判断是否要下线如果下线则发送quit并将下线用户套接字移除 ②判断输入的IP是否为正确的IP地址如果IP地址不能和模板相匹配,则输出Wrong IP ③判断目标客户是否在线如果不在线则输出:The Client you call is not online! ④判断是否传输文件 获取目标的Socket套接字 调用模块进行文件发送 关闭Socket输出流 关闭Socket输入流 关闭Socket}
    四、系统测试4.1 收发消息基本功能测试在用户输入对象的IP 发送的消息后,对方可以收到

    4.2 收发文件进本功能测试在用户输入对象的IP +消息+文件路径后,对方可以收到

    4.3 异常测试4.3.1 发消息4.3.1.1 格式错误4.3.1.2 格式正确
    IP地址错误
    目标客户不在线

    4.4 发文件4.4.1 格式错误会当成消息发送出去
    4.4.2 格式正确
    IP地址错误
    目标客户不在线
    找不到文件
    文件重名(文件覆盖)

    会成功发送,但是会将源文件覆盖。
    五、课程设计总结在本次课程设计中,学会了Java网络编程。实现了端到端通信,实现并行通信模式(不再是你说一句,我说一句,一端的信息发送不受另一端的影响),实现端到端的文件传输。学会了收发消息、收发文件的相关操作,输入输出流的包装,知道了做项目的基本流程。理解了Java要按接口编程的核心思想。
    6 评论 54 下载 2019-04-20 23:26:07 下载需要11点积分
  • 高校图书馆座位管理系统之选座功能的实现

    一、技术简介1.1 ReactReact 可以非常轻松地创建用户交互界面。为你应用的每一个状态设计简洁的视图,在数据改变时 React 也可以高效地更新渲染界面。以声明式编写UI,可以让你的代码更加可靠,且方便调试。创建好拥有各自状态的组件,再由组件构成更加复杂的界面。无需再用模版代码,通过使用JavaScript编写的组件你可以更好地传递数据,将应用状态和DOM拆分开来。
    1.2 VueVue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。
    1.3 Egg.js为企业级框架和应用而生的nodejs框架,egg.js是阿里推出的基于koa的node开发框架。为企业级框架和应用而生。Egg 的插件机制有很高的可扩展性,一个插件只做一件事(比如 Nunjucks 模板封装成了 egg-view-nunjucks、MySQL 数据库封装成了 egg-mysql)。Egg 通过框架聚合这些插件,并根据自己的业务场景定制配置,这样应用的开发成本就变得很低。
    1.4 YarnYarn 对代码来说是一个包管理器,可以通过它使用全世界开发者的代码, 或者分享自己的代码。Yarn 做这些快捷、安全、可靠。
    通过Yarn可以使用其他开发者针对不同问题的解决方案,使开发过程更简单。 使用过程中遇到问题,可以将其上报或者贡献解决方案。一旦问题被修复, Yarn会更新保持同步。
    1.5 iViewiView 是一套基于 Vue.js 的开源 UI 组件库,主要服务于 PC 界面的中后台产品。
    1.6 Ant Design Mobile是 Ant Design 的移动规范的 React 实现,服务于蚂蚁及口碑无线业务。
    1.7 JSON Web TokenJSON Web Token(JWT)是目前最流行的跨域身份验证解决方案。它是一个很长的字符串,中间用点(.)分隔成三个部分。客户端收到服务器返回的 JWT,可以储存在 Cookie 里面,也可以储存在 localStorage。此后,客户端每次与服务器通信,都要带上这个 JWT。你可以把它放在 Cookie 里面自动发送,但是这样不能跨域,所以更好的做法是放在 HTTP 请求的头信息Authorization字段里面。
    1.8 KnexKnex.js是为Postgres,MSSQL,MySQL,MariaDB,SQLite3,Oracle和Amazon Redshift设计的“包含电池”SQL查询构建器,其设计灵活,便于携带并且使用起来非常有趣。它具有传统的节点样式回调以及用于清洁异步流控制的承诺接口,流接口,全功能查询和模式构建器,事务支持(带保存点),连接池 以及不同查询客户和方言之间的标准化响应。
    二、系统概要设计系统的设计主要前台和后台两个部分。
    2.1 系统需求分析
    管理端
    登入/登出座位管理
    实时座位占用清空查询编辑自习室/图书馆座位创建自习室
    学校管理(增删改查,分页)管理员管理(增删)个人信息(密码验证,修改密码)

    2.2 可行性分析这里讲的可行性分析的任务是从技术上、经济上分析需解决的问题是否存在可行性。其目的是在尽可能短的时间内用尽可能小的代价确定问题是否有解。
    技术上的可行性分析主要分析技术条件能否顺利完成开发工作,硬、软件能否满足开发者的需要等。
    本套系统采用vue、react与egg实现,代码完全开源,文档完善,便于二次开发与维护,简单培训即可使用与维护。
    2.3 Server端模型
    由前台客户端发起请求来请求数据,Egg服务器判断是否在白名单或请求头中的token是否有效,若满足条件之一,则放行请求,根据router访问对应的controller,controller为数据的处理层,将数据处理好后通过service对数据库进行访问与操作,然后将service返回的结果在controller进行再次处理与封装,然后将响应数据和状态码(默认200)返回前台
    四、数据库设计4.1 数据概念结构设计E-R模型是数据进行第一层抽象的表示方法。它的主要成分包括:实体、联系和属性。我们可以用E-R图将内容表达出来,辅助设计的实现[6]。
    4.2 数据库关系设计该系统数据库关系图如下所示:

    五、后台设计在接口设计方面,使用restful API设计原则,访问同一资源的不同操作时,使用同一命名空间,使用不同的请求方式区分不同的操作。
    数据中均没有使用物理删除,只做了逻辑删除,保证数据可回溯。
    新增与更新,都使用同一个接口,根据是否有id去判断是更新还是新增
    5.1 Egg本系统后台采用egg.js编写,egg继承于koa,操作与配置更加简洁,每个请求发送至后台时,先通过编写好的中间件(middleware),然后根据访问的路由(router)去执行对应的控制器(controller),控制器中只做数据操作,不对数据库进行直接操作,将数据整理为服务(service)所需要的形式,直接发送给对应的服务,服务对数据库进行直接操作,然后将结果直接返回给控制器,控制器再将结果响应给前台。
    如此,完成了一次请求。
    5.2 权限校验已登录的用户,在请求时的请求头会带Authorization字段,若请求在白名单内,则不需要通过jwt中间件,直接放行,否则要校验此字段,字段里是bare + 登录时生成的json web token。
    jwt中间件对token进行解码后,判断是否合法并且在有效期内,通过则放行,不通过则直接返回状态码401(无权限)
    当请求为两端的login时,jwt中间件不进行验证,直接放行。


    5.3 连接数据库本系统通过knex对数据库进行操作,以函数式编程的方式,简化了手写sql语句的操作,使代码更具语义化与可读性。
    配置MySQL数据库:

    5.4 JavaScript异步并发问题js为单线程,多协程语言,同一时间只有一个线程在执行任务,而发起请求、执行sql语句、timer等异步任务则会放到任务栈中执行。
    ES6中原生支持了promise处理异步问题而又避免了回调地狱,但由于promise的链式调用代码量过大,不易维护,所以本系统中大量使用ES7中的async/await处理异步问题,将异步代码转化为同步调用,减少代码量。
    但由于await会阻塞异步进程,无法执行高并发任务,所以此处做了一些处理:

    当需要执行并发异步请求时,先将请求完整地发出,返回一个数组,这个数组的每一项都是一个<promise pending>,等待中的promise回调,这样就解决了并发问题,然后再下一步进行同步的循环赋值,在赋值时去await等待每一个promise的返回值,这样只需要等待最慢的一个即可,又保证了返回值的顺序,这样做的优点是代码可读性高,便于维护,缺点是性能略有损耗,但是每次请求只有几百条数据,这样的性能代价比起大量的不易维护的promise代码,还是值得的。
    六、管理端设计页面采用蚂蚁金服出品的Ant Design UI 组件库,提供了完善的设计原则、最佳实践和设计资源文件(Sketch 和 Axure),来帮助业务快速设计出高质量的产品原型。
    6.1 登录页面
    输入用户名密码,点击登录,将login_name和password发送至后台,后台进行校验,匹配后将Json Web Token响应回来,将这个token存至cookie中,设定7天的过期时间,当前端再次发起其他请求时,将这个token带到请求头的Authorization字段中,供后台解析。
    若cookie中无token,则中止请求,使页面跳转回login页面,重新登录。

    6.2 主页
    页面采用了传统的管理端页面布局,左侧侧边栏通过jsx渲染一个json数据生成,当侧边栏功能需要编辑时,只需修改json即可,减少了代码维护的复杂度。
    jsx渲染部分

    菜单json数据

    6.3 座位管理6.3.1 座位情况
    根据大学名称获取当前学校的自习室,然后选择自习室查询对应的自习室座位。

    此处通过远程搜索实现,获取大学列表,并且通过lodash中的debounce实现防抖功能。
    当连续输入时,如果每次都发送请求,则会产生很多无用请求,造成服务器负载过大,此时使用防抖功能,当输入内容300毫秒后才会发起请求,若300毫秒内又有输入,则重新开始计时,可以减少很多无用请求,提升请求效率。

    当选择大学后,会发起请求此大学自习室的请求,该请求会返回自习室名称、id与、总座位数与当前可选座位数。

    选择后点击查询按钮,即可查询到座位图的实时占用情况。
    座位数据为一个数组,每一项为一行,value为0代表此处为无座,1代表空座,2代表已被占用,渲染图如下:


    渲染座位图中白色座位点击可提示座位ID。

    红色座位为被占用座位,点击可显示座位ID、占用时间并且提示是否对其进行强制签退。

    点击强制签退,则将座位的结束时间设置为当前时间。
    6.3.2 编辑座位选择学校与自习室功能与上一模块相同,此处不再赘述。

    查询到座位图后,灰色座位渲染出来即为无座,白色座位为有座,上侧与左侧可添加列与行,下侧与右侧可删除列与行,删除到最后一行或最后一列时会有提示信息。

    提交座位时会弹出提示信息,这里采用对数据库中的座位全量更新,即将当前自习室/图书馆的座位全置为删除状态,再将新的座位数据完整写入。这么做是为了避免更新座位后有的人的预约还在但是有的人的预约失效,造成数据不一致。
    由于编辑座位操作是将座位全量更新,会导致当前预约的座位全部失效,请谨慎操作。

    6.3.3 创建自习室
    创建部分对应地做了正则表达式校验。

    必须输入自习室名称并且选择对应的学校。
    座位图与关键字查询学校在之前的部分都有提及,功能及实现方法基本一致。
    6.4 学校管理
    此页面做了分页,每页查询十条数据,每次返回的数据会将总数据量返回,以此显示总页数。

    删除提示使用的气泡弹窗的样式,减少了滥用覆盖层,既避免了打断用户心流,又减少了用户的误操作。

    在对学校进行编辑操作时,由于只需要编辑学校名称,此处就没有做弹窗,直接在表格内编辑,当名称在表中已存在时会弹出提示。


    创建学校使用了弹窗,需要输入,同样也做了非空非重复的校验。

    6.5 管理员管理
    仅超级管理员可进入此界面,普通管理员没有这个tab页签,而且仅可删除普通管理员。点击新建即可创建新的管理员。

    登录名与密码均做了非空与正则表达式的校验。


    6.6 个人信息此处只做基本信息的展示与密码修改功能。

    当点击密码时弹出密码修改框。

    输入原密码与两次新密码后,会先发送一个密码校验的请求,校验通过后会发送新密码与登录名,去修改密码。
    七、手机端设计7.1 用户登录
    当学号与密码有空时,会弹出提示框。

    输入正确用户名密码后会弹出登录成功提示并跳转。

    7.2 首页
    登入后,会根据token请求到用户信息,这里使用了redux状态管理工具,通过dispatch(派发)调用reducer,将用户信息保存到redux状态管理中,统一对状态进行管理,在用户信息保存好之后,进入首页,首页又分为两个路由页,一个为自习室列表页另一个为详情页。
    列表页会在用户信息中获取university_id,用这个id获取学校信息,并显示学校名称。
    获取到的自习室列表显示当前总座位数与可用座位数。点击可跳转至详情页。
    路由实现:

    点击自习室可跳转至详情页。

    页面会进行查询指定时间段内当前自习室占用情况,默认时间段为当前时间至一小时后,最小可选时间为当前时间,最大可选时间为当天23点59分,并可配置。
    开始时间

    结束时间

    座位图使用了pinchzoom进行缩放与平移控制。

    座位为单选,单击后所选座位会变为红色,点击提交-确定即可预约。

    点击确定后会重新检索座位情况,若在此时间段内有人占用,座位会显示灰色。

    点击此座位会显示该座位占用时间,以此让用户方便知道该座位可预约什么时段,提高座位利用率。

    当用户在预约的时段内已有其他预约,则不可预约。

    7.3 预约列表
    在这个页显示自己曾经预约的座位,根据创建时间排序,已结束预约或已取消的座位会显示对应状态,占用中的座位点击可提前取消。
    7.4 个人信息
    可修改手机号,必须符合标准手机号格式,通过正则表达式进行校验:
    /^(13[0-9]|14[579]|15[0-3,5-9]|16[6]|17[0135678]|18[0-9]|19[89])\d{8}$/点击密码可修改,第一个弹框会提示输入原密码,密码验证后会自动弹出第二个弹框输入新密码,确认即可成功修改。
    3 评论 9 下载 2021-02-10 12:13:29 下载需要12点积分
  • 基于JSP实现的医院住院管理系统

    一、课程设计介绍1.1 目的软件综合课程设计是学生在学习完数据库系统概论后必须进行的一项重要的实践环节。通过该课程设计,学习数据库设计工具的使用,掌握数据库设计的基本方法、步骤和数据库设计各阶段的任务,完成对某一小型数据库应用系统的基本流程进行分析,数据库设计和相应文档的编写工作。加深对课堂理论学习的理解,增强动手能力,使学生更加深入地掌握数据库系统分析与设计的基本概念和基本方法,以培养学生合作的能力,为毕业设计作好实践环节上的准备。
    1.2 内容课程设计的题目与设计要求由指导老师指定,每组学生最终需要实现一个功能完整、可运行的 MIS 系统。
    课程设计报告中应包括需求分析、概要设计、数据库设计、详细设计、编码实现、总结等,具体地:

    设计报告中应首先包括设计题目、学号、姓名、专业、班级、指导教师、完成日期
    概要设计中应包括设计思想、实现方法、系统中主要模块及各模块间的关系的描述
    设计包括根据需求分析所得到的信息,用 E-R 图完成系统的概念结构设计,并对 E-R 图进行优化。将系统 E-R 图转换为选定的 DBMS 所支持的关系模型,并按关系规范化理论对关系模型进行优化
    详细设计中应对各模块,各功能进一步细化,写各功能的算法等
    编程实现中应包括对主要模块、主要功能、关键功能的代码说明,代码中应有适当的注释
    总结里主要写该系统用何种开发语言,开发了何种系统,主要实现了哪些功能,系统性能如何,有何不足等

    2 系统需求通过简单的需求分析,完成的医院住院管理系统,能够实现辅助医院医 护人员工作,提高医院医护人员的工作效率。通过本系统,能够实现对住院 部门的病人和病房两大信息的管理包括增、删、改、查,减轻医护人员的工 作负担。本系统提供强大的查询功能,可以让系统用户根据各种不同的查询 条件查询出相应的数据。出入院操作能够简单的实现病人的出入院操作,方 便医院医护人员的操作,系统应该界面美观,操作简单,功能明确、完善。 系统操作,应该有很高的效率,数据库操作方面应该提高效率,不能反应缓 慢,这在系统搭建上要求合理、完善。
    通过建立该医院住院管理系统,采用计算机对医院病房和病人进行管理 和查询,进一步提高医院住院管理效益和现代化水平,帮助提高医院住院管 理工作人员工作效率,实现医院住院管理工作流程的系统化、规范化和自动 化。系统应该具有很好的扩展性,这就要求系统架构合理、可扩展,充分考 虑到以后的需求变化。设计良好的代码允许更多的功能在必要时可以被插入 到适当的位置中。这样做的好处是为了应对未来可能需要进行的修改,这就 需要系统设计时能够有一个良好的软件框架。系统的安全性,也是本次系统 设计的一个重要目标,设计中要考虑到用户的非法访问,通过拒绝用户的非 法访问来保证用户数据的安全和系统的安全。
    2.1 系统总体目标
    加快办理病人入院、出院的速度,实现病人的资料在住院的全过程中实现信息化管理
    准确记录病人和床位的各项信息,并提供全方位的查询功能,让病人、医生、护士,能够及时准确的掌握病人和床位的各种信息,从而有效提高工作效率,缩短工作时间
    系统具有一定的安全性和运行稳定性、可扩展性。系统需要医院员 工输入账号和密码才能操作,可以避免其它人员的恶意操作给医院信息带来的损失
    系统能够提供一个界面友好、功能完善的信息管理系统,方面医护 人员学习和操作,尽可能的简化医院操作,减少医护人员学习和掌握系统的时间

    2.2 功能需求本系统主要实现与病人相关的各种信息的系统化、规范化和自动化,本 住院管理系统主要完成的功能有:

    出入院管理模块:包括入院登记、病人出院操作
    病房管理模块:包括对病房的增删改查(CRUD)操作,支持多种查询条件
    病人管理模块:包括对病人信息的维护,增删改查操作,支持多种查询条件
    系统管理模块:包括对修改用户、添加用户、删除用户、退出系统
    系统功能模块:包括首页、前进、后退、刷新等操作和显示当前时间

    功能分析得到数据流图如下所示:

    3 概要设计3.1 医生功能模块图
    3.2 管理员功能模块图
    3.3 总体联系3.3.1 医护人员
    3.3.2 管理
    4 详细设计4.1 总体流程图
    4.2 实体及其属性
    病人:住院编号,病人姓名,病人性别,入住病房编号,病人入院时间, 病人出生地
    病房:病房编号,病房类型,病房租金,病房状态,病房所属科室,病房 医生,病房医生号码
    医生:医生姓名,医生性别,电话号码,医生地址

    各个实体间有如下关系:一个病人只能入住一个病房,而一个病房可以住多名病人。
    4.3 E-R 图实体与实体间的对应关系是一对一,“m”、“ n”表示实体与实体间的关系是一对多。

    4.4 数据库设计数据库设计是整个程序设计的最关键部分。数据库的设计是否合理,将 对数据库的大小、代码的优化起到至关重要的作用。因此,在设计程序前必 须对数据库进行设计,而在设计数据库前必须对所要完成的功能进行认真的研究分析。
    根据系统的要求,需要建立存放系统使用过程中所用到的各种信息表: 医生信息表、病人信息表、病房信息表、管理员信息表。
    用户信息表:用来存放使用此系统的用户的信息。

    管理员信息表:存放病人信息。

    病房信息表:存放病房信息。

    病人信息表:存放病人信息。

    5 系统实现5.1 数据库代码部分医生信息表
    create table doc_info ( user_id int PRIMARY KEY auto_increment, user_num varchar(12), -- 12 user_name varchar(10), user_pwd char(32), sex char(4), tel char(11), addr varchar(50))
    管理员信息表
    create table admin_info ( user_id int PRIMARY KEY auto_increment, user_num varchar(12), -- 12 user_name varchar(10), user_pwd char(32), sex char(4), tel char(11), addr varchar(50))
    病人信息表
    CREATE TABLE pati_info( pati_id int primary key auto_increment, pati_num char(5), -- P0000 pati_name varchar(10), pati_sex char(4), pati_ward_num char(5), -- 病房编号 pati_birthday char(12), -- 流水号处理日期 pati_birthplace varchar(50) );
    病人信息表的触发器
    create trigger trig_pati before INSERT on pati_info for each ROW begin declare p char(5); declare n int; DECLARE num int; DECLARE type char(4); set new.pati_birthday=date_format(sysdate(),'%Y%m%d%H%i'); set p=(select MAX(pati_num) from pati_info); if p is null then set p='P1000'; end if; set n=substring(p,2)+1; set new.pati_num=concat('P',n); set num =(select COUNT(*) from pati_info group by new.pati_ward_num); set type=(select ward_type from ward_info where new.pati_ward_num=ward_info.ward_num); if (type='单人') then if(num=0) then update ward_info set ward_status=1 where ward_info.ward_num = new.pati_ward_num; end if; ELSEIF (type='双人') then if(num=1) then update ward_info set ward_status=1 where ward_info.ward_num=new.pati_ward_num ; end if; ELSE if (num=3) then update ward_info set ward_status=1 where ward_info.ward_num=new.pati_ward_num; end if; end if;end; create TRIGGER trig_pati_delete AFTER DELETEon pati_info for each ROW BEGIN DECLARE num int; DECLARE type char(4); set num =(select COUNT(*) from pati_info group by old.pati_ward_num); set type=(select ward_type from ward_info where old.pati_ward_num=ward_info.ward_num); if (type='单人') then if(num=0) then update ward_info set ward_status=0 where ward_info.ward_num=old.pati_ward_num ; end if; ELSEIF (type='双人') then if(num<2) then update ward_info set ward_status=0 where ward_info.ward_num=old.pati_ward_num ; end if; ELSE if (num<4) then update ward_info set ward_status=0 where ward_info.ward_num=old.pati_ward_num ; end if; end if;end;
    病房信息表
    create table ward_info ( ward_id int PRIMARY KEY auto_increment, ward_num char(5), /*W0000*/ ward_type char(4), -- 病房类型 -- ward_depart varchar(10), -- 所属科室 -- ward_doc varchar(10), -- 管理医生 -- ward_doc_tel char(11), -- 医生电话 -- ward_rent DECIMAL(5,1), -- 租金 -- ward_status int DEFAULT 0 -- 1 满)
    病房信息表的触发器
    create TRIGGER trig_ward_num before insert on ward_infofor each row begin DECLARE w char(5); DECLARE n int; set w=(select max(ward_num) from ward_info); if w is null then set w='W1000'; end if; set n=SUBSTRING(w,2)+1; set new.ward_num=CONCAT('W',n); end;
    病人住院信息视图
    Create view v_pati_ward (pw_ward_num, pw_pati_num, pw_pati_name, pw_pati_sex, pw_ward_depart, pw_ward_doc, pw_ward_doc_tel, pw_ward_rent) as SELECT ward_num, pati_num, pati_name, pati_sex, ward_depart, ward_doc, ward_doc_tel, ward_rent from pati_info, ward_info where pati_info.pati_ward_num=ward_info.ward_num;
    5.2 JSP 前端页面代码<script> function show(f) { var chs=document.getElementsByName("pati_id"); for(var i=0;i<chs.length;i++) { chs[i].checked=f; } } function batdelete(){ var flag=0; var pati_id=document.getElementsByName("pati_id"); for(var j=0;j<pati_id.length;j++){ if(pati_id[j].checked==true){ flag=1; } } if( flag==1 ){ for(var i=0;i<pati_id.length;i++){ if(pati_id[i].checked==true){ //window.location.href="DeletePatiServlet?pati_id="+pati_id[i].value; }else{ pati_id[i].value=""; } } } else{ $("form").attr("action",""); alert(" 请选中要删除的病人信息!"); } } // 单个删除 function del(id){ window.location.href='javascript:doDelete('+id+')'; } var doDelete=function(n){ var f=confirm("确定删除吗?"); if(f) { window.location.href="DeletePatiServlet?pati_id="+n; } }; </script>
    医生界面左侧导航页面 JSP 代码
    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <link rel="stylesheet" type="text/css" href="bootstrap/css/bootstrap.min.css"> <style> *{ margin:0px; padding:0px; } body{ background-color: #E0E0E0; } #left{ height:300px; padding-top:150px; margin-left:27px; } .navi{ font-size:17px; } a{ color: black; } </style> </head> <body> <div id="left"> <ul class="nav nav-stacked"> <li class="active"> <a class="navi" href="Welcome.jsp" target="main">首页</a> </li> <li> <a class="navi" href="ToUpdateDocServlet?user_id=${sessionScope.doc.user_id }" target="main">个人信息</a> </li> <li class="dropdown"> <a class="dropdown-toggle navi" data-toggle="dropdown">病人管理<span class="caret"></span></a> <ul class="dropdown-menu"> <li onmouseover="activ(this);" onmouseout="defau(this);"> <a href="addpati.jsp" target="main">添加病人信息</a></li> <li class="nav-divider"></li> <li onmouseover="activ(this);" onmouseout="defau(this);"> <a href="SearchPatiServlet" target="main"> 病人信息查询 </a></li> </ul> </li> <li class="dropdown"> <a class="dropdown-toggle navi" data-toggle="dropdown">病房管理<span class="caret"></span></a> <ul class="dropdown-menu"> <li onmouseover="activ(this);" onmouseout="defau(this);"> <a href="SearchWardServlet" target="main"> 病房信息查询</a></li> </ul> </li> <li class="dropdown"> <a class="dropdown-toggle navi" data-toggle="dropdown">综合信息查询<span class="caret"></span></a> <ul class="dropdown-menu"> <li onmouseover="activ(this);" onmouseout="defau(this);"> <a href="SearchPwServlet" target="main"> 住 院 信 息 查 询</a></li> </ul> </li> <li> <a href="aboutus.jsp" target="main" class="navi">关于我们</a> </li> </ul> </div> </body> <script src="jquery-3.2.1.min.js"></script> <script src="bootstrap/js/bootstrap.min.js"></script> <script> function activ(obj){ if(obj.className!=null) obj.className+=" active"; else obj.className="active"; } function defau(obj){ if(obj.className=="active") obj.className-="active"; else obj.className-=" active"; } </script> </html>
    管理员界面左侧导航页面 JSP 代码
    <%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>欢迎使用</title> <meta content="IE=edge,chrome=1" http-equiv="X-UA-Compatible"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="description" content=""> <meta name="author" content=""> <link rel="stylesheet" type="text/css" href="lib/bootstrap/css/bootstrap.css"> <link rel="stylesheet" type="text/css" href="stylesheets/theme.css"> <link rel="stylesheet" href="lib/font-awesome/css/font-awesome.css"> <script src="lib/jquery-1.7.2.min.js" type="text/javascript"></script> <!-- Demo page code --> <style type="text/css"> #line-chart { height:300px; width:800px; margin: 0px auto; margin-top: 1em; } .brand { font-family: georgia, serif; } .brand .first { color: #ccc; font-style: italic; } .brand .second { color: #fff; font-weight: bold; } </style> <link rel="shortcut icon" href="../assets/ico/favicon.ico"> <link rel="apple-touch-icon-precomposed" href="../assets/ico/appletouch-icon-57-precomposed.png"> <style type="text/css"> <!-- .STYLE2 {color: #FFFFFF} --> </style> </head> <body class=""> <div class="sidebar-nav"> <a href="Welcome.jsp" target="Newmain" class="nav-header" ><i class="icon-dashboard"></i>欢迎</a> <a href="#dashboard-menu" data-toggle="collapse" class="nav-header" ><i class="icon-dashboard"></i>医生操作</a> <ul id="dashboard-menu" class="nav nav-list collapse in"> <li ><a href="DelDoc.jsp" target="Newmain"> 删除医生账户</a></li> <li ><a href="SearchDocServlet" target="Newmain">查询医生账户</a></li> </ul> <a href="#accounts-menu" class="nav-header" data-toggle="collapse"><i class="icon-briefcase"></i>病房操作</a> <ul id="accounts-menu" class="nav nav-list collapse"> <li ><a href="NewAddRoom.jsp" target="Newmain"> 添 置 病 房</a></li> <li ><a href="NewDelRoom.jsp" target="Newmain"> 删 除 病 房</a></li> <li ><a href="NewSearchNullBedServlet" target="Newmain"> 病房查询</a></li> </ul> <a href="ToEditAdminServlet?user_num=${sessionScope.map.user_num }" class="nav-header" target="Newmain"><i class="icon-question-sign"></i>个人信息维护</a></div> <script src="lib/bootstrap/js/bootstrap.js"></script> <script type="text/javascript"> $("[rel=tooltip]").tooltip(); $(function() { $('.demo-cancel-click').click(function(){return false;}); }); </script> <body> </body> </html>
    5.3 后端代码package com.neu.service; import java.util.List; import java.util.Map; import java.util.HashMap; import com.neu.dao.AdminInfoDao; import com.neu.util.ConvertUtil; public class AdminInfoService { private AdminInfoDao adminInfoDao; public AdminInfoService(){ this.adminInfoDao=new AdminInfoDao(); } public boolean doReg(Map<String,String[]> params){ boolean flag=false; Map<String,String> map=ConvertUtil.convertMap(params); int row=adminInfoDao.insert(map); if(row>0){ flag=true; } return flag; } public List<Map<String,String>> findByParams(Map<String,String[]> params){ List<Map<String,String>> list=null; Map<String,String> map=ConvertUtil.convertMap(params); list=adminInfoDao.search(map); return list; } public boolean doDelete(Map<String,String[]> params){ boolean flag=false; Map<String,String> map=ConvertUtil.convertMap(params); int row=adminInfoDao.delete(map); if(row>0){ flag=true; } return flag; } public Map<String, String> checkLogin(Map<String,String[]> params){ Map<String, String> item=null; Map<String,String> map=ConvertUtil.convertMap(params); List<Map<String, String>> list=adminInfoDao.search(map); if(list.size()>0){ item=list.get(0); } return item; } public boolean doUpdate(Map<String, String[]> params){ boolean flag=false; Map<String, String> map=ConvertUtil.convertMap(params); // 存放 修改语句的条件 Map<String,String> where=new HashMap<String, String>(); where.put("user_num", map.get("user_num")); // 必须把作为条件的列从map中移除 map.remove("user_num"); int row=adminInfoDao.update(map, where); if(row>0){ flag=true; } return flag; } public Map<String,String> findById(Map<String,String[]> params){ Map<String,String> item=null; Map<String,String> map=ConvertUtil.convertMap(params); List<Map<String,String>> list=adminInfoDao.search(map); if(list.size()>0){ item=list.get(0); } return item; } }
    5.4 功能截图删除病房

    修改病房信息

    病床查询

    添置病床

    删除医生账户

    管理员主界面

    查询医生账户

    修改个人信息

    医生账户操作面板

    6 用户说明书第一步:登录界面,分为管理员和用户两种身份,登录不同的账号跳转到不同的页面如图 7-1:

    第二步:根据你的身份登录完成后,如果你的身份是医生,那么你可以 进行病人信息的增删改查以及查询空病房,添加病房等操作。如果你是管理 员,那么你可以进行对医生的查询和删除操作,病房的增删改查操作,以及 对自己个人信息的修改操作。

    第三步:根据你的身份你可以在页面上进行你想进行的操作了,例如:我 是一名管理员,我想知道某某某医生的信息,那么经过如下页面操作即可完成:


    参考文献[1] 林来兴. 空间控制技术. 宇航出版社, 1992:34-36
    [2] J.R.McDonnell,D.Wagen. Evolving Recurrent Perceptions for Time-Seeies Modeling. IEEE Trans. on Neural Networks. 1994,5(1):24-38
    [3] 洪炳熔. 自由浮游空间机器人捕捉目标的运动规划研究. 中国第五届机 器人学术会议论文集. 哈尔滨, 1997:75-80
    10 评论 318 下载 2018-11-05 22:18:09 下载需要14点积分
  • 基于SSM的网上购物系统的设计与开发

    摘 要本论文主要对网上购物商城的设计与开发进行了一些论述,包括了系统的设计和实现一共两个大部分,设计部分主要对系统和数据库的分析与设计进行了描述;实现部分主要包括系统的各个功能的实现。
    网上购物商城包括两大模块:前台用户模块和后台管理员模块,前台用户可以通过浏览器客户端页面进行登陆和一系列的购物操作。后台管理员可以查看所有用户的所有信息;可以对网站中所有的商品分类进行修改,同时也可以对所有用户的订单状态进行查看。
    系统前台通过JSP页面来来展示数据,后台基于java技术和eclipse (朱诺)和tomcat 7.x开发,前台运用html+css技术渲染页面,后台使用springmvc、spring、myBatis对数据进行封装和操作,该系统运用MySql 5.X 数据库进行数据的维护。页面美观,使用方便。
    关键词:MySql数据库; JAVA; SSM;网上购物商城
    AbstractThis paper mainly focuses on the clothing sales system design and development of a number of paper, including the system design and implementation of a total of two parts, part of the system design and database analysis and design were described; the realization part includes the various functions of the system.
    Clothing sales system includes two modules: front user module and the background administrator module, the front desk users can browse through the browser client page and a series of shopping operations. The background administrator can view all the information of all users can be on the site of all the clothing category to modify, but also for all users to view the order status.
    In front of the system through the JSP page to display the background data, Java technology and based on eclipse (Zhu Nuo) and Tomcat 7.x development, the use of html+css technology to render the page, the background using springmvc, spring, myBatis package and operation of data, the system uses MySql 5.X database for data maintenance. Beautiful page, easy to use.
    Keywords: MYSQL DB;JAVA;SSM;CLOTHING SALES SYSTEM
    1 绪论1.1 研究背景在如今这个信息时代,“网上购物”这种购物方式已经为越来越多的人所接受。在这种背景之下,一个安全稳定并且强大的网络购物平台不可或缺,在这种成熟的市场需求的推动下,在先进的信息技术的支持下,商品产品销售系统应运而生。它可以使消费者和商家更紧密地联系起来,以更快地满足顾客的需求,也可以让用户选择自己真正喜欢的商品。目前市面上已经有此类的网上购物商城,但是现有商品网站系统或多或少存在着功能比较单一、维护比较复杂、操作比较繁琐等问题。有的系统甚至直接采用静态网页发布商品商品信息,这些因素在一定程度上限制了网上购物商城在目前市场上的推广。如何开发出费用低廉、功能强大的系统正是我们需要解决的课题。
    1.2 目的和意义本软件旨在降低商品销售商家的工作强度,提高工作效率,大大地减少了操作员手工录入数据的工作量,极大限度的避免了人力浪费,有效避免重复操作时间消耗;而且此软件方便了用户对自己所需商品的查询和购买,打破了传统的销售模式,极大限度的方便了用户。商家应用此软件之后,可以拓展销售门路,增加销售业绩。应用此软件是为了在传统销售模式之外,再开辟一条销售通路,减少库存堆积,利用网络共享和互动的优点,结合地面销售的优点,借助数据库管理技术,开发此平台,是为了实现规范化、个性化、人性化的商品网上销售。此软件的数据统计分析功能灵活完善,稳定安全、使用方便、界面友好、操作简单,可以成为一个能真正帮助商品销售行业管理发展的有力工具。
    1.3 开发工具及技术该网上购物商城前端使用了jsp来实现数据的展示,后端通过java代码来对数据进行一系列的操作,前端使用了原生的html页面技术进行渲染,同时也加入了jquery技术制作了一下控件效果,后端使用了经典的spring技术对整个系统进行统一调度,使用springMvc框架实现了前端和后端的交互。开发工具使用了Eclipse以及tomcat服务器,同时使用了Mysql数据库对数据进行存储和维护。
    在该系统实现的过程中,使用spring和springMvc的同时后端还使用了MyBatis技术对数据进行封装和操作。前端还采用了dtree框架规范了页面的显示。整个系统的架构也是基于经典的mvc设计模式来设计的。
    Mybatis是一个经典的后端开源框架,它的前身就是iBatis,MyBatis的执行原理是应用程序根据XML配置文件创建出SqlSessionFactory,然后SqlSessionFactory根据配置文件或者注解创建出SqlSession,SqlSession这个对象包含了所有的执行sql所需要的所有方法,可以通过SqlSession这个实例执行所有的方法对数据库进行操作,操作结束后执行相应的事物控制,本系统中的事物控制全部交由spring容器进行统一调度,本次采用的是spring的申明式 方式。MyBatis相对于 其他的ORM框架具有很多的优点,比如mybatis本身属于轻量级框架简单易学,没有第三方的依赖。mybatis比较灵活,开发人员可以自己编写sql语句来对数据进行操作。mybatis提供了xml标签,支持编写动态sql.
    dtree框架就是一个简单的树形菜单js组件,开源免费,自身不需要复杂的操作,同时也支持动态的将数据引入jsp页面。
    MVC模式是一种软件架构模式。它将系统分为三个部分:模型,视图和控制器。MVC模式出现的目的就是方便了后续程序的修改和扩展简化,同时使系统中某一段代码的重复利用成为可能。此模式降低了模块之间的耦合度,对自身各个部分进行了分离的同时也使得各个部分具备了应有的功能。
    Spring是从实际开发中抽取出来的开源框架,为企业的开发提供一个轻量级的解决方案。该解决方案包括:基于Ioc(控制反转)的核心机制,以及AOP(面向切面编程)的思想,能与多种持久层技术的整合,是优秀的Web MVC框架等。Spring致力于Java EE应用各层的解决方案而不是仅仅专注于某一层的方案,它贯穿表现层、业务层、持久层,降低各层组件的耦合度,实现软件各层的解耦.Spring内部最核心的就是IOC了,动态注入,让一个对象的创建不用new了,可以自动的生产,这其实就是利用java里的反射,反射其实就是在运行时动态的去创建、调用对象,Spring就是在运行时,跟xml Spring的配置文件来动态的创建对象,和调用对象里的方法的。还有一个核心就是AOP这个就是面向切面编程,可以为某一类对象 进行监督和控制(也就是 在调用这类对象的具体方法的前后去调用你指定的 模块)从而达到对一个模块扩充的功能。这些都是通过配置类达到的。Spring是一个容器,凡是在容器里的对象才会有Spring所提供的这些服务和功能。
    2 需求分析2.1 功能需求分析2.1.1 网站前台功能
    首页:提供一个网站首页,显示该企业的商标,该网站用户的登录,注册,所有商品的一级分类,热门商品和最新商品的展示等
    用户的注册:针对还未注册的用户完成注册功能的使用,在注册的过程中涉及数据的合法性校验,以及利用ajax完成用户名是否已被注册的异步校验
    用户的登录:对于已经注册并且激活的用户提供的登录操作
    用户的退出:对于已经登录的用户,退出系统
    首页商品展示:展示出最新商品和热门商品
    分类页面商品展示:根据一级分类和二级分类去展示该分类下的所有商品
    商品详情展示:点击某个商品时可以展示该商品的具体详细信息
    购物车:用于存放用户的购物内容,用户可根据自己的情况修改自己的购物车
    订单:对于已经登录的用户可以对购物车内容进行付款生成订单,可以为自己的订单进行付款或者查看
    留言评价分享:网站单独开辟了留言分享区域,供登录的用户自由发表评价分享心得信息,进行交流互动

    2.1.2 网站后台功能
    管理员登录:管理者根据账户和密码进行登录
    商品一级、二级分类管理:管理者可以对前台显示的一级、二级分类进行管理,包括添加、删除、修改操作
    商品管理:管理者可以对前台显示的商品进行管理包括添加,修改,删除,查询的功能,也可以上传商品的图片
    用户管理:管理者可以查看该网站中已经注册过的所有用户的所有信息

    2.2 性能分析响应时间:忽略网络、硬件以及插件的因素,以本地测试为准,前台响应时间为0.8秒,后台操作响应时间:0.9秒。
    2.3 系统用户用例图用户用例图
    用户为系统的使用者,可以通过前台注册激活登录后进行一系列的购物操作。

    管理员用例图
    管理员是整个系统的最高权限拥有者,他用于对所有用户的所有信息的查看,网站商品显示的增删改查,更换图片,所有商品所属一级二级分类的修改。

    3 系统设计3.1 系统的总体设计该系统的开发采用B/S模式,整个系统的构建基于ssm(Spring+SpringMvc+MyBatis)整合框架。
    深入研究JavaEE体系结构,所项目的技术选型中选取的个个框架分别进行分析和研究。SpringMvc是一个web端框架。Mybatis是一个轻量级的持久层框架,以面向对象的方式提供了持久化类到数据库之间的映射,是一种优秀的ORM框架。Spring也是一种轻量级框架,它的IOC和AOP思想,值得架构师学习。通过三大框架的整合,可以很方便的构建出可扩展,可移植,可维护的软件系统。
    SSM框架是目前J2EE领域中最热门而且用的比较成熟的一套开源框架,它是基于MVC设计模式之上,充分发挥了MVC的优点。SSM是一套轻量级框架,相对于EJB而言,SSM继承了它的优点的同时,在开发和执行效率上也有了明显的提高,而对于开发者而言,它比EJB更加易学和掌握。目前SSM框架也正在不断地进行优化和维护,运行也是越来越稳定。
    根据以上功能分析,得到系统功能模块结构图如图3-1所示:

    3.2 数据库的分析与设计数据库,我们可以形象的将它称为一个仓库,因为它一般被用来存放汉字、字符、数据、货币、日期等信息,并且对这些信息按照一定规则存放,对数据进行安全、低冗余性、规范的进行集成化管理。从发展的历史历程来看,数据库可以看成是由文件管理系统发展而来的。
    数据库的基本结构可以分为三个层次包括物理数据层、概念数据层、逻辑数据层。数据库不同层次之间的联系是通过映射进行转换的,数据库的特点包括实现数据共享、减少数据的冗余度、数据的独立性、数据实现集中控制、数据一致性和可维护性。
    本系统采用的的数据库是Mysql5.0,本系统所有与数据库相关的开发都遵循Mysql5.0数据库开发原则。
    3.2.1 数据库概念设计用户实体
    用户实体包括编号、用户账号、姓名、联系方式、性别、用户状态、用户邮箱和密码等属性。用户实体的实体联系图(E-R图)如下所示:

    管理员实体
    管理员实体包括编号、账号和登录密码属性。管理员实体的实体联系图(E-R图)如下所示:

    商品实体
    商品实体包括商品id、商品名称、市场价、商场价、商品图片、商品描述、上架日期、所属二级分类id。商品实体的实体联系图(E-R图)如下所示:

    订单实体
    订单实体主要包括订单id、订单总价、订单状态、收货人、收货地址、收货电话、下单时间、购买者id、购买商品id。订单实体的实体联系图(E-R图)如下所示:

    3.2.2 数据库物理结构为该系统设计了7张表,在这里列出7张表分别为如下所示:



    数据表
    描述




    adminuser
    后台管理员表


    category
    一级分类表


    categorysecond
    二级分类表


    orderitem
    订单项表


    orders
    订单表


    product
    商品表


    user
    前台用户表



    管理员表主要记录了管理员的基本消息,表结构如表3-1所示。



    字段
    数据类型
    允许空值(默认NO)
    自动递增
    备注




    id
    int(11)
    YES
    YES
    账号


    username
    varchar(1000)
    NO
    NO
    用户名


    password
    varchar(1000)
    NO
    NO
    密码



    一级分类表主要记录了一级分类的基本信息,表结构如图3-2所示。



    字段
    数据类型
    允许空值(默认NO)
    自动递增
    备注




    cid
    int(11)
    YES
    YES
    一级分类ID


    cname
    varchar(1000)
    NO
    NO
    一级分类名



    二级分类表主要记录了二级分类的基本信息,表结构如图3-3所示。



    字段
    数据类型
    允许空值(默认NO)
    自动递增
    备注




    Csid
    int(11)
    YES
    YES
    二级分类id


    Csname
    varchar(1000)

    NO
    二级分类名称


    cid
    varchar(1000)

    NO
    所属一级分类id



    订单项表主要记录了订单项的基本信息,表结构如图3-4所示。



    字段
    数据类型
    允许空值(默认NO)
    自动递增
    备注




    Oiid
    int(11)
    YES
    YES
    订单项id


    count
    varchar(1000)


    购买数量


    subtotal
    double


    单项总价id


    Pid
    int(11)


    所购商品id


    cid
    int(11)


    所属订单id



    订单表主要记录了订单的基本信息,表结构如图3-5所示。



    字段
    数据类型
    允许空值(默认NO)
    自动递增
    备注




    oid
    int(11)
    YES
    YES
    订单id


    money
    double


    订单总价


    state
    Int(11)


    订单状态


    Receiveinfo
    Varchar(255)


    收货地址


    phonum
    Varchar(255)


    收货人电话


    Order_time
    datetime


    下单时间


    Uid
    Int(11)


    所属用户id



    商品表主要记录了商品的基本信息,表结构如图3-6所示。



    字段
    数据类型
    允许空值(默认NO)
    自动递增
    备注




    Pid
    int(11)
    YES
    YES
    商品id


    Pname
    Varchar(255)


    商品名称


    Market_price
    Int(11)


    市场价


    Shop_price
    Varchar(255)


    商城价


    image
    Varchar(255)


    商品图片


    Pdesc
    Varchar(255)


    商品描述


    Is_hot
    int(11)


    是否热门


    Pdate
    datetime


    商品上架日期


    csid
    int(11)


    所属二级分类id



    前台用户表主要记录了前台用户的基本信息,表结构如图3-7所示。



    字段
    数据类型
    允许空值(默认NO)
    自动递增
    备注




    Uid
    int(11)
    YES
    YES
    用户id


    Username
    Varchar(255)


    用户名


    password
    Varchar(255)


    用户密码


    Name
    Varchar(255)


    用户真实姓名


    Email
    Varchar(255)


    用户游戏


    Phone
    Varchar(255)


    用户手机号


    Addr
    Varchar(255)


    用户地址


    State
    int(11)


    用户状态



    3.3 小结本章主要是对数据库进行了设计和说明。对数据库的概念设计思路和物理结构进行了详细的说明,并对数据库中涉及到的实体进行了说明。
    4 系统主要功能实现4.1 系统注册页面实现4.1.1 客户端用户注册用户登录网站出现页面,点击“注册”,进入注册页面,填写数据,点击注册按钮进行注册,注册完之后保存数据库表中,即可登录网站。
    注册效果如图4-1所示:

    var username = document.getElementById("username").value;var xmlHttp = creatXMLHttpreauest();xmlHttp.open("GET","${pageContext.request.contextPath}/registFindByid.action?username="+ username, true); xmlHttp.send(null); xmlHttp.onreadystatechange = function() { if (xmlHttp.readyState == 4 && xmlHttp.status == 200) { document.getElementById("span1").innerHTML = xmlHttp.responseText;
    服务器端二次数据合法性校验(此处采用的配置文件加注解的方式)
    user.username.length.error=用户名的名字的长度必须是1至30user.email.notNull=邮箱不可为空@Size(min=2,max=30,message="{user.username.length.error}") private String username; @NotNull(message="{user.email.notNull}") private String email;
    4.2 系统登录页面实现4.2.1 用户登录用户在注册后,在客户端登录页面输入正确的用户名和密码,进入网站进行购物。 程序运行如下图4-2所示:

    设计思路
    编写用户登录的页面login.jsp,用户在首页点击“登录”按钮后,浏览器跳转到登录页面,用户可以填写用户名和密码进行登录,当用户填写用户名并使光标移开 时,触发onblur()事件,进行ajax异步请求,判断用户名是否可以登录,用户在填写验证码时可以点击图片,进行跟换验证码,触发onclick=”change()” 事件进行更换,当用户点击“登录”按钮时,服务器进行数据判断,如果用户名和密码都正确则跳转到首页并显示该用户的用户名,如果有错误则跳转到msg.jsp全局页面显示错误消息。
    4.2.2 管理员用户登录后台管理员通过访问正确的路径之后进入到管理员登录页面,如果访问的不是正确页面但出现了admin路径则自动跳转到admin页面,然后输入正确的用户名和密码进行登录,如果出错,服务器会将错误信息回显到登录页面,如果正确则跳转到管理员页面。
    程序运行结果如图所示,图4-3显示了管理员登录的页面,图4-4则是管理员登录成功后的主页面:


    4.3 系统前台功能实现系统前台页面包括以下几个部分:首页一级分类,热门商品,最新商品的显示,二级分类的显示,已登录用户的订单以及用户所操作过的购物的展示,其中一级分类和二级分类在各个页面中都有所设计,因此这里采用的是页面包含技术。
    4.3.1 一级分类模块查询一级分类描述
    本系统中首页显示的一级分类都是存放于数据库中,当用户访问该网站首页的同时就查询了一级分类。一级分类显示效果如图4-5所示:

    设计思路
    一级分类展示于系统的首页,当用户访问index.action时,最终跳转至系统首页即index.jsp,跳转之前,服务器内部已经进行了一级分类的查询,并将已经查询到的以及分类存放于List集合中,最终存放于session域中。
    查询某个一级分类描述
    用户在进入系统首页时,当点击一级分类时就要求查询系统在下一个页面中显示出该一级分类中包含的所有二级分类。查询某个二级分类的效果图如图4-6所示:

    设计思路
    当用户点击首页中的一级分类时系统则根据此一级分类的id查询出该一级分类下所有的二级分类,并存放于session域中,将页面进行跳转,并进行展示。
    主要代码
    request.getSession().setAttribute("cid",cid);PageBean<Product> proPageBean = productService.findProductyBycid(cid,page);model.addAttribute("pageBean",proPageBean);return "category";
    4.3.2 商品模块查询最热商品描述
    当用户访问该网站时,首先显示的是网站的首页,首页中将显示本网站中最热的商品。程序运行结果如图4-7所示:

    设计思路
    用户访问首页index时,根据路劲“/index.action”首先调用的是系统的index.action,最后跳转至系统的首页index.jsp,因为最热商品显示于首页中,因此在页面跳转之前必须前往数据库查询出本系统中所有的热门商品,因此使用了findHotProduct()这个方法,由于首页中仅仅显示了最新商品中的前十个,因此这里是使用的分页查询,最终查询的结果是一个list集合,最终保存在Model中。
    前段控制层代码
    List<Product> hList= productService.findHotProduct();
    service层代码
    List<Product> list = productMapper.selectByExample(example);
    查询最新商品描述
    当用户访问该网站时,首先显示的是网站的首页,首页中将显示本网站中最新的商品。程序运行结果如图4-8所示:

    设计思路
    用户访问首页index时,根据路劲“/index.action”首先调用的是系统的index.action,最后跳转至系统的首页index.jsp,因为最新商品和最热商品一样都是显示于首页中,因此在页面跳转之前必须前往数据库查询出本系统中所有的最新商品,因此使用了findNewProduct()这个方法,查询最新商品的依据是商品被上传的时间,根据时间来进行排序,由于首页中仅仅显示了最新商品中的前十个,因此这里是使用的分页查询,最终查询的结果是一个list集合,最终保存在Model中。
    前端控制层代码
    List<Product> nList =productService.findNewProduct();
    service层代码
    ProductExample example = new ProductExample();ProductExample.Criteria criteria = example.createCriteria();example.setOrderByClause("pdate DESC");example.setBeginPage(0);example.setEnd(10);
    查询分类商品描述
    用户在点击首页的一级分类时,系统自动跳转页面,同时要求在右面显示某个二级分类下的商品。程序运行结果如图4-9所示:

    设计思路
    首先导入页面,页面和查询二级分类下的商品使用的是同一个页面category.jsp。当用户点击按钮时,客户端向服务器请求发送请求并携带一级分类的主键id,因此服务器端应该接受参数并使用这个参数来调用方法然后去数据库进行查询数据,最后将查询出的数据把保存于Model中,最后跳转页面。
    由于页面大小的关系,这里仅仅显示12个商品,因此这里采用了分页查询,并在右下角设置相应的按钮,方便用户来回查看该分类下所有的商品。
    前端控制层接收参数并调用service层代码
    //根据一级目录查找二级目录下面的商品productService.findProductyBycid(cid,page);model.addAttribute("pageBean",proPageBean);
    Servive层代码
    int totlePage = 0;totlePage = productMapper.countProducyByCid(cid);if(Math.ceil(totlePage % limitPage)==0){totlePage=totlePage / limitPage;}else{totlePage=totlePage / limitPage+1;pageBean.setTotlePage(totlePage);int beginPage= (page-1)*limitPage;
    查询二级分类商品用户在点击首页的一级分类时,系统自动跳转页面,并且在页面的左面显示所有一级分类包含的二级分类,同时要求在右面显示某个二级分类下的商品。程序运行结果如图4-10所示。

    设计思路
    首先编写页面category.jsp,这个页面用来显示某个二级分类下的所有的商品,当用户点击二级分类时系统访问对应的action,并且携带参数(相应二级分类的主键id),到前端控制层,然后findCategorySecond1()方法接收主键id和分页的数目去product表查询商品,最终将查询到的结果存放于Model中。由于页面大小的关系,这里仅仅显示12个商品,因此这里采用了分页查询,并在右下角设置相应的按钮,方便用户来回查看该分类下所有的商品。
    前端控制层接收参数并调用service层
    // 根据csid来分页查询商品PageBean<Product> proPageBean = productService.finbProductByCsid(csid,page);model.addAttribute("pageBean",proPageBean);
    查询商品信息用户再浏览该商场,查看某个商品的详细信息。程序运行结果如图4-11所示:

    设计思路
    首先编写页面,这里使用的是product.jsp,在这个页面中显示了以及分类的信息,还有每个一级分类下的二级分类,右下方是某个商品的具体信息,其中包括商品的名称,商品的商城价和市场价,包括一个选择框,用于用户选择购买数量,最下面则是商品的具体介绍。当用户点击某个想要查看的商品图片时,其实就是点击了某个超链接,向服务器发送链接并携带参数(商品的主键id),服务器端接收这个参数,并使用这个参数去数据库中查看这个商品的具体信息最后封装于product中,最终存放于Model中。
    前端控制层接收参数并调用service层,Service层直接调用Mybatis提供的mapper接口
    //根据pid来查询商品Product product = prodcutService.productFindByPid(pid);model.addAttribute("product", product);
    4.3.3购物模块添加到购物车对于已经登录的用户,可以将看中的商品具体信息保存于自己的购物车中。

    设计思路
    首先编写cart.jsp用于显示登录用户的购物车,如果用户没有登录会有提示,用点击查看商品的详情之后会出现一个“加入购物车”按钮,当点击此按钮时,自动访问服务器,并通过隐藏表单携带参数(商品的主键id),服务器端在接受此参数,并接收用户选购的数量,最终保存于我们为每个用户在session域中创建的cart。最后进行页面跳转,在cart.jsp中展示购物车的信息,主要包括:商品的具体信息和每项的价格和购物车的总价。对于已登录用户的页面,可以看到一个购物车的图标,用户可以查看自己的购物车。
    主要代码
    //添加到购物车Product product = productService.finbProductByPid(pid);//存进一个购物项CartItem cartItem = new CartItem();cartItem.setCount(count);cartItem.setProduct(product);cartItem.setSubtotle(count*product.getShopPrice());//存进购物车Cart cart=getCart(request);cart.addCart(cartItem);
    从购物车中移除商品用户点击购物车页面中每个购物项后面的删除按钮即可删除该购物项。程序运行结果如图4-13所示:

    设计思路
    当用户点击 “删除”按钮时,向服务器端进行请求,并携带参数(商品的主键id),服务器端在设计购物车时采用的是用Map集合存储的,key值即商品的id,因此删除的时候只需从session中拿到购物车直接根据主键删除,最后将页面重定向到cart.jsp.
    主要代码
    Cart cart=getCart(request);cart.delProFromCart(pid); //删除某个购物项
    清空购物车用户点击“清空购物车”按钮,购物车里面的购物项全部删除。程序运行结果如图4-17所示:

    设计思路
    当用户点击 “清空购物车”按钮时,向服务器端进行请求,服务器端收到请求之后,从session域中取出cart购物车,由于cart在设计的时候使用的是Map集合,所以只需调用Map中的clear()方法即可,并且还需将购物车的总价改为0,最后将页面重定向到cart.jsp.
    主要代码
    // 清空购物车Cart cart=getCart(request);cart.clearCart();
    4.3.4 订单模块生成订单当用户点击“生成订单”按钮时,页面跳转至order.jsp,并让用户填写相关信息。程序运行结果如图4-15所示:

    设计思路
    首先编写order.jsp页面,其中包含用户的购物信息和收货地址、收货人和联系方式。当用户点击cart.jsp中的生成订单按钮时,向服务器发送请求,服务器端从session域中拿到cart中的信息,并将这些信息保存于order表中,此时,需要清空购物车并且将订单信息保存到session域中,最后跳转到order.jsp页面让用户填写相关信息,并付款。
    主要代码
    Orders orders = new Orders();Cart cart = (Cart) request.getSession().getAttribute("cart");User loginUser = (User) request.getSession().getAttribute("loginUser");if(loginUser==null){ model.addAttribute("message", "对不起您还没有登录"); return "msg";}//生成订单
    我的订单用户对自己的选购的商品所生成的订单项进行付款。即可生成订单,进入我的订单列表界面;程序运行结果如图4-16所示:

    设计思路
    为订单付款页面还是使用的是order.jsp,当用户点击cart.jsp中的提交按钮时,页面进行跳转并显示相关的订单信息,此时,用户可以暂时不对订单进行付款,此时订单的状态为0。如果用户在生成订单的同时一并付款,或者点击用户的最上方右边的红色字体“我的订单”时,页面会进行跳转,并显示该用户的所有订单和订单的状态,此时想要付款则点击按钮“付款”,也会跳转到order.jsp,此时需要用户填写订单的具体信息,包括收货地址、收货人、联系方式以及付款的银行,此时客户端和服务器端一样会进行非空和数据合法性校验,当用户填写好信息并点击“付款”按钮时,其实就是服务器端拿订单的具体信息,并将订单的状态改为“1”,同时将用户填写的关于收货的信息保存于数据库order表中,最终服务器端会将页面重定向到orderList.jsp,向用户展示他的所有的订单以及订单的具体信息。在orderList.jsp中展示该用户的所有订单时采用的是分页查询,在订单的右下角同时也设置了按钮,方便用户查看自己的所有按钮。
    4.3.5 留言模块留言板当用户点击“留言板”按钮时,页面跳转至messageList.jsp,并让用户填写相关信息。程序运行结果如下图所示:

    4.4 系统后台功能实现4.4.1 用户模块查询用户管理员进入后台管理页面之后,当他点击“用户管理”按钮时,则在主页面中显示所有用户的详细信息。程序运行结果如图4-17所示:

    设计思路
    先编辑list.jsp页面,当用户点击“用户管理”按钮时,服务器端收到请求,调用service层的admin_findAll()方法由service 层调用myBatis提供的mapper接口,返回一个list集合,最终所有信息封装于Model中将页面跳转到list.jsp并进行展示。
    主要代码
    if(adminuserLogin==null){ request.getSession().setAttribute("message","对不起您还没有登录"); return "admin/index";
    4.4.2 一级分类模块添加一级分类此功能属于管理员的权限范围内,用户管理员为网站添加新的一级商品系别。程序运行结果如图4-18所示:

    设计思路
    首先编写add.jsp页面,当用户在一级分类list.jsp页面点击“添加”按钮时, 服务器将页面跳转至add.jsp,在此页面共有三个按钮,“确定”按钮用于提交信息,“重置”按钮清空表单中的内容,“返回”按钮返回前一个页面。当用户填写好要添加的一级分类的名称之后点击“确定”按钮,服务器端接收此表单中的内容,然后调用service层的addCategory()方法,将新增的一级分类保存到数据库category表中,最后将页面重定向到list.jsp页面,展示所有的一级分类。
    主要代码
    Category addCategory = new Category();addCategory.setCname(cname);categoryService.addCategory(addCategory);
    修改一级分类此功能属于管理员的权限范围内,管理员用户修改网站中各大服饰的一级分类的名称。程序运行结果如图4-19所示:

    设计思路
    首先编写edit.jsp页面,当用户在一级分类list.jsp页面点击“添加”按钮时, 服务器将页面跳转至edit.jsp,在此页面共有三个按钮,“确定”按钮用于提交信息,“重置”按钮清空表单中的内容,“返回”按钮返回前一个页面。当用户填写好要修改的一级分类的名称之后点击“确定”按钮,服务器端接收此表单中的内容,然后调用service层的adminCategory_update()方法,将修改的一级分类更新到数据库category表中,最后将页面重定向到list.jsp页面,展示所有的一级分类。
    删除一级分类后台管理员点击每个一级分类后面的删除按钮即可删除该一级分类。程序运行结果如图4-20所示:

    设计思路
    当用户点击每个一级分类后面的“删除”按钮时,服务器接收到请求然后接收携带过来的参数(一级分类主键id),当我们准备删除一级分类时,如果删除了改一级分类那么相应的二级分类和二级分类下的商品就得全部删除,因此我们根据myBatis的规则。先根据外键删除二级分类然后再删除一级分类,因此首先调用adminCategorySecond_deleteByCid(cid)删除二级分类然后再调用categoryService.deleteCategoryByCid(cid);删除一级分类,最终将页面重定向到list.jsp页面。
    主要代码
    categorySecondService.adminCategorySecond_deleteByCid(cid); categoryService.deleteCategoryByCid(cid);
    查询一级分类管理员点击“一级分类管理”按钮时,展示所有的一级分类的详细信息。程序运行结果如图4-21所示:

    设计思路
    首先编写list.jsp页面,当管理员用户点击“一级分类管理页面”按钮时,服务器端接收请求然后调用adminbFindCategory()方法最终由service层调用myBatis提供的Mapper接口将所有的一级分类的信息查询出来保存到list集合中,最终保存到Model中并将信息进行展示。考虑到一级分类比较多,这里使用了分页查询,在页面展示的效果就是每页显示固定的个数,并在右下角提供了相应的按钮方便用户进行查看其他的一级分类。
    主要代码
    List<Category> categoryList = categoryService.adminbFindCategory();model.addAttribute("categoryList", categoryList);
    4.4.3 二级分类模块添加二级分类管理员用户为新增加的一级分类添加二级分类。程序运行结果如图4-22所示:

    设计思路
    首先编写二级分类添加页面add.jsp,管理员用户点击“添加”按钮时,页面跳转到add.jsp,同时服务器端将查询出所有的一级分类的名称,用于管理员选择新增的二级分类的归属,这在add.jsp页面中通过一个下拉列表进行显示。管理员用户在填写好新增的二级分类的名称并选择好所属的一级分类之后点击“确定”按钮,服务器端接收新增的二级分类名称和所属的一级分类的主键id,然后调用adminCategorySecond_save()方法将新增的Categorysecond保存于数据库的categorysecond表中。最后将页面重定向到二级分类的list.jsp页面进行展示。
    主要代码
    Categorysecond categorysecond = new Categorysecond();categorysecond.setCsname(csname);categorysecond.setCid(cid);categorySecondService.adminCategorySecond_save(categorysecond);
    修改二级分类管理员用户可以为网站中所有的二级分类的名称进行编辑。程序运行结果如图4-23所示:

    设计思路
    首先编写二级分类修改页面edit.jsp,管理员在list.jsp点击“编辑”按钮时,页面跳转到edit.jsp页面,跳转之前,服务器端查询到对应的二级分类的名称并将二级分类的名称保存到edit.jsp对应的表单中,这样方便用户知道自己修改的是哪个二级分,增加了用户体验度
    查询出对应的二级分类的名称存放于表单中,增加了用户体验
    Categorysecond findByCsid = categorySecondService.findByCsid(csid);model.addAttribute("findByCsid", findByCsid);
    更新修改的二级分类
    Categorysecond categorysecond = new Categorysecond();categorysecond.setCsname(csname);categorysecond.setCsid(csid);CategorySecondService.adminCategorySecond_update(categorysecond);
    删除二级分类后台管理员根据查询出的二级分类列表对二级分类进行操作,根据系统的要求,管理员用户在删除二级分类的同时应该删除该二级分类下的所有商品。
    设计思路
    管理员用户在点击“二级分类用户”按钮时,在管理员页面展示所有的二级分类,当用户点击“删除”按钮时,服务器端收到客户端发来的请求,并接受客户端传来的数据(二级分类的主键id),然后根据二级分类的主键id调用adminCategorySecond_delete(csid)方法,删除二级分类,然后根据外键删除商品。最后将页面重定向到二级分类的list.jsp页面。
    主要代码
    // 删除二级分类,二级分类关联二级分类下面的商品categorySecondService.adminCategorySecond_delete(csid);categorySecondService.adminProduct_deleteByCsid(csid);
    查询二级分类管理员通过点击“二级分类管理”来查看网站中所有的二级分类。程序运行结果如图4-24所示:

    设计思路
    首先得编写二级分类的list.jsp页面。管理员用户点击“二级分类管理”按钮时,给服务器发送请求,并携带分页参数,服务器端接收此参数之后开始查询所有的二级分类,这里创建了一个pageBean对象用于封装查询出来的数据,包括二级分类的集合,当前的页数,一共的页数等信息,最后直接返回一个pageBean对象,因为二级分类较多,这里采用了分页查询,需要用到这些数据因此直接封装在了pageBean对象里。用户可以通过二级分类的list.jsp页面右下方的按钮来查看所有的二级分类。
    4.4.4 商品分类模块添加商品管理用户通过点击商品展示页面list.jsp上的“添加”按钮可给网站添加新的商品。程序运行结果如图4-25所示:

    设计思路
    首先编写商品添加页面add.jsp。管理员用户点击商品展示页面list.jsp上的“添加”按钮之后客服端跳转到add.jsp页面,在客户端页面跳转之前,服务器端需要查询出所有商品的二级分类,方便上传用户选择该商品所属的二级分类。管理员需要填写页面上的信息包括商品名称、选择是否热门、市场价格、商城价格、上传商品图片、选择所属二级分类和编写商品描述这些信息。管理员用户点击“确定”按钮之后客户端将数据提交给服务器,客户端在上传上传组件时必须将上传组件表单type设置为file类型,这样服务器端才能正确的识别。最后服务器端接收到数据之后封装于product对象中,并调用adminProduct_save(product);将新上传的product保存到数据库中的product表中,最后将页面重定向到商品的list.jsp页面。
    主要代码
    product.setPdate(new Date());if (file != null) { String path = request.getServletContext().getRealPath("/products"); String uploadFileName = file.getOriginalFilename(); String fileName = UUIDUtiils.getUUID()+uploadFileName; File diskFile = new File(path + "//" + fileName); product.setImage("products/" + fileName);
    删除商品管理员用户点击“商品管理”来到展示所有商品页面,通过点击页面上的删除按钮即可删除指定的商品。
    设计思路
    这个功能是基于商品的展示页面list.jsp进行开发的,展示用户页面时pageBean里面封装了product的所有信息,当用户在点击“删除”按钮时即向服务器发送请求并携带参数(商品的主键id),服务端在接收到请求之后,根据客户端传来的参数进行删除该商品,最终将页面重定向到商品的展示页面list.jsp.
    jsp页面方法主要代码
    function deletecs(pid) { window.location.href = " ${pageContext.request.contextPath}/ admin/adminProduct_deletecs.action?pid="+pid;
    查询商品管理员通过点击“商品管理”按钮来查看本网站中所有的商品信息。程序运行结果如图4-26所示:

    设计思路
    首先编写商品下面的list.jsp页面,管理员用户在点击“商品管理”按钮时,给服务器发送请求,并携带分页参数,服务器端接收此参数之后开始查询所有的商品信息,这里创建了一个pageBean对象用于封装查询出来的数据,包括商品的集合,当前的页数,一共的页数等信息,最后直接返回一个pageBean对象,因为商品个数较多,这里采用了分页查询,需要用到这些数据因此直接封装在了pageBean对象里。用户可以通过商品文件夹里面的list.jsp页面右下方的按钮来查看所有的是商品信息。
    主要代码
    // admin的商品管理(查询所有的商品)PageBean<Product> allProPageBean = productService.findAllProduct(page);model.addAttribute("allProPageBean", allProPageBean);
    4.4.5 留言管理模块管理用户通过点击留言管理链接,即可打开前台顾客的留言列表界面,并且可以删除不合时宜的留言信息。程序运行结果如图4-26所示:

    5 系统测试与维护5.1 系统测试环境5.1.1 硬件环境
    CPU:英特尔酷睿四核
    内存:4G

    5.1.2 软件环境
    操作系统:windows 7
    服务器:Tomcat 7
    浏览器:Mozilla Firefox 和chrome

    5.2 系统测试内容使用eclipse编程软件编写Java源程序是遇到语法错误会自动报错,需要及时修改错误。对系统进行测试视为系统能有效运行并且没有异常产生。
    在程序模块编写时,每编写完一个模块需要进行模块单元测试,保证单元模块功能正常,在所有单元测试进行结束之后,需要进行整个系统的集成测试。本系统需要做如下的测试:

    登录注册测试:多次注册用户并且登录。则表达式检验的文本框输入错误信息,检测代码是否可行,注册成功后,检验用户是否可以正常显示,并查看数据库,检验数据是否成功插入。登录时,交叉使用正确和错误的密码进行登录测试,校验是否有异常
    查询一级分类测试:测试当用户访问index.action时,是否可以至系统首页即index.jsp,测试成功
    查询二级分类测试:测试用户在点击首页的一级分类时,系统是否会自动跳转页面,并且在页面的左面显示所有一级分类包含的二级分类
    购物车测试:测试已登录的用户是否可以将商品添加到购物车、移除购物车内商品、清空购物车
    订单模块测试:测试是否可以正常生成订单、取消订单、为订单付款

    5.3 系统维护系统维护是为了让系统能够在正常运行的基础上,对系统中的一些小问题进行修复并且不断完善的过程,通过系统维护能够使系统保证在不同的运行环境下均可以正常的工作,各个模块功能正常运行。
    由于本系统的本质就是一个电子商城,所以难免会有很多过期的没用的数据。所以需要定期进行“垃圾”信息的删除,对于系统中重要的一些内容如用户和商品等。要定期对数据库备份,保证数据的正确性。本系统的维护就是为了使本系统能够稳定的运行,所以需要定期维护,并且备份数据。
    小结:本章首先介绍了系统的测试环境,接下来详细介绍了单元模块测试的方法和整体集成测试的主要内容,最后介绍了系统维护的方案。
    6 总结如今,JavaEE是一个非常优秀的企业信息化开发平台,由于其拥有一些很好的性质包括稳定的性能、良好的开发性和非常高的安全性因此被广泛运用于企业级开发。这篇论文基于当前比较流行的电商系统为项目背景,遵循javaEE应用软件的规则进行开发,将系统划分为四个层次包括模型model层,持久层,业务逻辑service层和表现层,并整合了目前在企业中广泛运用的spring、springMvc和myBatis框架进行开发。Spring用于整个系统的统一调度,贯穿于各层之间,springMvc框架着重于mvc模式的实现,myBatis框架完成数据的映射和持久化工作,myBatis的逆向工程极大的方便了dao层的开发,也方便了系统dao层的维护。
    本论文主要完成了以下的任务:

    正确分析了电商目前的发展形势,特别是对网购的发展进行了深入的调查和研究
    深入明确了系统的总体架构,在技术选型上选取了三个主流的框架,对三者的功能,整合做了详细的描述
    系统项目的开发严格遵循软件的开发规范,制定了详细的系统开发步骤,开发之前做了大量的工作包括:需求分析、技术选型、架构设计等
    完成了预期赋予系统的功能的实现

    本文虽然完成了预期研究和目标,但后期还有很多工作需要完成:,随着web应用的快速发展,处于信息时代下会有更多的技术应运而生,不光需要对框架进行深入学习和研究还要对系统的架构进行研究。目前客户端技术正在崛起,我们需要认真做调查和研究做出一能让用户体验度更好的产品。以上只是目前的构想,接下来会继续深入研究并作进一步的完善和设计开发。
    7 参考文献[1] 杨开振等. Java EE互联网轻量级框架整合开发— —SSM框架(Spring MVC+Spring+MyBatis)和Redis实现[M]. 电子工业出版,2017.07.
    [2] 李俊民.HTML 5+CSS 3网页设计经典范例[M].电子工业出版,2010.
    [3] 邹红霆. 基于SSM框架的Web系统研究与应用[J]. 湖南理工学院学报(自科版), 2017, 30(1):39-43.
    [4] 王珊 萨师煊 数据库系统概论[M] 北京:高等教育出版社 2007
    [5] 陈雄华 Spring企业级应用开发详解[M] 北京:电子工业出版社 2009
    [6] 原著施奈德 成栋翻译 电子商务[M] 北京:机械工业出版社 2008
    [7] 阿里巴巴网络技术有限公司 中小企业电子商务之路[M] 北京:清华大学出版社 2007
    [8] 刘克强 电子商务平台建设[M] 北京:人民邮电出版社 2007
    [9] 程杰 大话设计模式[M] 北京:清华大学出版社 2010
    [10] 雷之宇 朱训雨 张麟 JAVA实用组件集[M] 北京:电子工业出版社 2008
    19 评论 582 下载 2019-05-15 16:31:24 下载需要15点积分
  • 基于Qt和sqlite实现的餐厅服务与管理系统

    1 系统功能设计1.1 总体功能描述1.1.1 开发背景随着信息时代的飞速发展,人们的生活水平不断提高,餐饮业的消费持续增长。传统的单纯靠人工管理日常运作、人工记录顾客的点菜、人工通知厨师所需做的菜品、人工结账等等的以人工为主导的方式早已无法满足新时代的需求。所以,一套基于互联网的高效的餐厅服务与管理系统应时而生。如此不但能提高工作效率,也避免了传统方式会产生的不必要的麻烦,同时也方便了管理者对餐厅的运营。
    1.1.2 顾客操作的相关功能用户若以顾客身份登录,如果有账号密码,可直接输入登录,或注册之后再进行登录。登录成功后,会进入到座位选择界面,选择座位结束后,进入到点餐界面。顾客可以浏览菜品的名称、单价、平均评价星数(5 星满)。点餐结束后,待服务员、厨师认领。认领成功后,顾客可发送催菜、加水等消息于服务员。用餐完毕后进行结账并离开桌位。确认离开座位后,顾客可以选择性对服务员和已 点的菜品进行评价。
    1.1.3 服务人员操作的相关功能服务人员主要包括服务员和厨师。用户以服务员身份登录后,直接进入到服务员界面。服务员可以实时得到待服务的桌号信息,以及正在服务的桌号信息。同时,也能实时收到由顾客发来的 加水、催菜等消息,且能够接收菜品已就绪的消息(以便为顾客上菜)。 用户以厨师身份登录后,直接进入到厨师界面。厨师可以认领菜品。烹饪完成后,确认已完成。
    1.1.4 运营者操作的相关功能运营者主要包括管理员和经理。用户以管理员身份登录后,进入到管理员界面。管理员可以查看用户的信息以及菜品的信息。同时可以对其中的信息进行适当的修改,比如添加菜品类别、 修改菜品单价、删除菜品,以及对用户身份的修改。用户以经理身份登录后,进入到经理界面。经理可以实时查看服务员、厨师的工作量以及平均评价,同时可以逐条浏览顾客对服务员以及菜品的评价。同时, 经理也可以进入管理员界面进行管理员的一系列操作。
    1.2 功能流程描述1.2.1 顾客
    顾客功能如流程图所示,其中,结账之后,才能离开座位。确认离开座位之后,会弹出是否进行评价的窗口,根据顾客意愿判断是否进行评价。

    注册:顾客初次使用该系统需要注册一个账号,输出手机号、密码、确认密码即可完成注册。其中,要求顾客输入规范的国内手机号码,密码不小于 7 位。注册界面实时对注册信息的规范性进行判断并反馈给正在注册的顾客
    登录:用户输入已注册的账号及密码,待系统核实正确后,即可完成登录
    选择桌位:顾客登录之后,若之前未选择桌位,则进入选择桌位界面
    点菜:选择桌位之后,进入点菜界面。顾客可查看到所有菜品,当前桌号、当前服务员。同时也能查看顾客的购物车,下单之前可以随时增减菜品。确认下单后,等待服务员上菜。等待上菜期间,顾客可以实时查看菜品完成情况,且可以发送加水、催菜等消息给服务员
    评价:用餐完毕后,进行结账。顾客确认离开座位后,会出现评价对话框,顾客根据个人意愿对服务员、所点菜品进行星数、文本的评价

    1.2.2 管理员
    管理员功能如上流程图所示。管理员可以查看关于账户和菜品的信息,如菜品的总销量、平均评价。同时可以对信息进行管理,实现对菜品以及账户的增、 删、改、查的功能。

    管理员登录:管理员的账号需要经理或原有管理员进行授权,无法注册获得管理员权限
    查询管理:登录后,管理员可以查询账户及菜品的一系列信息,同时能够对相关信息进行管理,实现对账户和菜品的分类管理以及“增删查改”的功能。本餐厅系统的管理员同时拥有适当修改身份的功能,即厨师、服务员的权限无法注册得到,只能通过经理或服务员获得

    1.2.3 服务员、厨师
    厨师、服务员功能流程如上图。其中,厨师认领由顾客下单后发送的点餐信息中的菜品,完成菜品之后,将信息发送给服务员,使得服务员收到正在服务的餐桌的菜品已就绪的消息并上菜。同时,服务员能够收到由顾客发来的加水、催菜的信息。

    服务员:认领服务桌位;进入服务员界面之后,服务员可以认领待服务的桌位,并能查看正在服务的桌号以及其发送的催菜、加水消息和其菜品的完成情况
    厨师:认领、完成菜品;进入厨师界面后,厨师可以认领待做的菜肴,以及确认完成已认领的菜品,并自动将菜品就绪的消息发送给顾客及服务员

    1.2.4 经理
    经理功能流程如上图所示。在此餐厅运作系统中,经理拥有最大的权限,即同时拥有管理员和经理本身的权限。经理可以查看服务员和厨师的工作记录以及顾客对服务员和菜品的评论。

    查看记录:经理可以查看服务员的工作量、平均评价、厨师的工作量、顾客订单 信息、厨师与服务员的工作记录
    查看评论:经理可以逐条查看顾客对服务员以及各个菜品的评论以了解餐厅经营 的基本情况
    管理员权限:经理拥有管理员的所有功能,能够完成管理员权限的一系列操作

    2 系统结构设计2.1 模块说明概要2.1.1 数据库的构造该系统使用了 Qt 中的 Qt SQL 模块,底层选用了 SQLITE 数据库接口。
    该系统共建立一个数据库,其中创建了 10 个表格。

    其中 account 存储用户相关信息,cook_record,cook_workload 用来存储厨师工作记录,dish 用来存储菜品信息,order_record 用来存储订单信息, remark_dishes、remark_waiters 存储顾客对菜品、服务员的评论,tables 用来存储桌号的相关信息,waiter_record,waiter_workload 用来存储服务员的工作信息。
    2.1.2 界面层该系统共有 11 个 ui 界面,其中有登陆界面,注册界面,餐桌状态查询界面,查询菜品评论界面,查询服务员评论界面,管理员界面,服务员工作界面,厨师工作界面,顾客评论界面,经理界面。

    2.1.3 逻辑层
    2.1.4 数据库与逻辑层的交互系统在程序运行初进行初始化,将数据库的内容读入内存,在逻辑层中对内存的数据进行操作。程序关闭之后,在调用主界面析构函数之前,将内存中的数据存入数据库加以保存。
    2.1.5 逻辑层与界面层的交互逻辑层与界面层的交互主要借助了 Qt 中的信号和槽机制、QListWidget、QtableView、QTableWidget 等等 Qt 中的一系列功能,实现了界面间的切换以及将内存中的数据在界面中的显示,使得顾客、服务员、厨师、经理能够获取一定的信息。同时,数据库与 TableView 的组合,能够使管理员对餐厅信息进行适当的管理。
    2.2 UML 类图



    3 系统详细设计3.1 类结构设计3.1.1 Object 类
    由Object抽象类派生出People类和Dishes类,People类派生出Ordinary_user、Cook、Waiter 三个类,由 Dishes 派生出 Have_ordered_dishes 类。Object 作为基类,内包括 ID、name 等私有成员。Dishes 是菜品类,Have_order_dishes 是顾客已点菜品类,故由 Dishes 类派生。 Ordinary_user 是顾客类,Cook 为厨师类,Waiter 是服务员类,继承了 People 中的 mobile、password、identity 等私有成员。People 类中声明纯虚函数,使得派生出的三个类根据自身需要进行定义,实现了多态。
    该结构合理使用了类的组合。Waiter 类的定义中使用 Ordinary_user 类,用来记录服务员正在服务的用户的相关信息;Ordinary_user 类的定义中使用 Have_ordered_dishes 类,用来记录顾客已点的菜品。
    3.1.2 Record 类
    Record为记录类,用来记录相关信息。由此派生出Order_record、Cook_record、Waiter_record,分别用来记录订单信息、厨师工作信息、服务员信息。
    3.1.3 Table 类Table 类的成员变量多数为对餐桌状态的记录,如是否空闲、是否已下单、是否已结账、是否向服务员催菜加水、是否离开等等。
    3.1.4 Remark 类Remark 类是评论类,可以记录评论的评论者、被评论对象、评价星级、评论文本、评论 ID、以及评论日期。
    3.1.5 Data 类Data 类内定义的静态变量用来实现变量的跨文件使用,进而实现跨界面的信息传递。
    3.2 数据层3.2.1 表格的创建具体代码如下:
    创建数据库
    void create_database(){ QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE"); db.setDatabaseName("my_account4.db"); db.open(); QSqlQuery query(db); query.exec("create table cook_workload (mobile varchar primary key,remark_star double" ",workload int,remark_num int)"); query.exec("create table waiter_workload (mobile varchar primary key,remark_star double" ",workload int,remark_num int)"); query.exec("create table remark_dishes (id int primary key, mobile varchar, dish_name varchar,point int , text varchar" ",date varchar)"); query.exec("create table remark_waiters (id int primary key, mobile varchar, waiter_mobile varchar,point int , text varchar" ",date varchar)"); query.exec("create table order_record (id int primary key, mobile varchar, dish_name varchar,num int" ",date varchar)"); query.exec("create table waiter_record (id int primary key,waiter_mobile varchar, mobile varchar" ",date varchar)"); query.exec("create table cook_record (id int primary key,cook_mobile varchar,dish_name varchar,num int,mobile varchar" ",date varchar)"); query.exec("create table dish (id int primary key,dish_name varchar,unit_price double ,remark_star double , remark_num int , sales_volume int" ",kind varchar)"); query.exec("create table tables (num int primary key,mobile varchar,price int,settle_account int,have_waiter int,cook_claim int,is_free int,is_ordering int" ",add_water int,push_dishes int)"); for(int i = 1;i <= 36 ;i++) { query.exec(QString("insert into tables values(%1,'',0,0,0,0,1,0,0,0)").arg(i)); } query.exec("create table account (id varchar primary key,identity varchar" ",password varchar)"); db.close();}
    读取数据库
    void read_database(){ QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE"); db.setDatabaseName("my_account4.db"); db.open(); QSqlQuery query(db); for(int i = 0 ; i < Data::cook_num ; i++) { query.prepare("insert into cook_workload(mobile,remark_star,workload,remark_num) values (?,?,?,?)"); query.addBindValue(Data::cook[i].get_id()); query.addBindValue(Data::cook[i].get_remark_star()); query.addBindValue(Data::cook[i].get_work_load()); query.addBindValue(Data::cook[i].get_remark_num()); query.exec(); } for(int i = 0 ; i < Data::waiter_num ; i++) { query.prepare("insert into waiter_workload(mobile,remark_star,workload,remark_num) values (?,?,?,?)"); query.addBindValue(Data::waiter[i].get_id()); query.addBindValue(Data::waiter[i].get_remark_star()); query.addBindValue(Data::waiter[i].get_work_load()); query.addBindValue(Data::waiter[i].get_remark_num()); query.exec(); } db.close();}
    3.2.2 数据初始化在 main 函数中,定义了 void initialize() 函数,将数据库的信息读取到内存,将相关变量进行初始化。
    3.3.3 数据的储存在主界面析构函数调用前,将相关数据存入数据库,使得在程序正常关闭之后,内存中的相应数据会存储到数据库中,实现对数据的储存。
    3.3 界面层3.3.1 界面结构
    3.3.2 登录/注册界面
    登录界面由3个PushButton, 1个ComboBox,以及一个输入文本为“Restaurant” 的 Label 组成。由于 ComboBox 的默认样式与整个登录界面不搭,故修改了其样式,代码如下:
    ui->model_chosen->setStyleSheet ("QComboBox::drop-down {\ subcontrol-origin: padding;\ subcontrol-position: top right;\ width: 30px;\ border-left-width: 1px;\ border-left-color: white;\ border-left-style: solid; /* just a single line */\ border-top-right-radius: 3px; /* same radius as the QComboBox */\ border-bottom-right-radius: 3px;\ }" "QComboBox::down-arrow { image: url(:/Image/下拉框图标3.png);}" "QComboBox{border: 1px solid #32435E;\ border-radius:10% ;color:rgb(200, 193, 197); font: 10pt '微软雅黑'; padding-left:20%; }" );
    账号和密码的输出框设置了 placeholderText,以提示用户输入 LineEdit 的要求。

    注册界面与登录界面比较类似。
    3.3.3 桌位界面
    桌位界面主要由 5 个 Label,1 个 groupBox,1 个“离开座位”的 PushButton,以及在 groupBox 中动态生成的总桌数的 PushBuuton。
    右上角为图例,当桌位上有人时,则桌位变为灰色,空闲时为橙色,如下图所示:

    当点击空闲桌位时,会出现对话框提示桌号并询问是否确认选桌。同时选桌成功后进入点餐界面可以实时查询餐桌状态。

    3.3.4 点餐界面
    点餐界面的主体是 ListWidget。
    确认下单之前,界面如上图。顾客可以查询所有菜品,得知菜品的类别、名字、单价、评价。同时为了方便顾客查询已点,本系统将购物车和菜单放置在同一界面里。顾客可以实时查询餐桌状态,并可以得到当前服务员 ID 信息。右下方通过使用重载 QDailog 的 paintEvent,实时更新当前已点菜品的总价格。
    确认下单后,如图所示:

    顾客可以实时查看菜品烹饪状态,并可以给服务员发送催菜、加水等消息。
    3.3.5 评价界面评价界面主要由 TabWidget 构成,包括服务员评价界面和已点菜品评价界面。评价支持星级评价以及文本评价。星级评价由 5 个 PushButton 组成,根据鼠标点击不同位置的星星而调用相应的槽函数。


    菜品界面通过 back 和 next 的 PushButton 依次对已点菜品进行评价。并且,顾客的操作记录都得到了保存。确认提交评价之后,相关信息会传送给经理。
    3.3.6 服务员界面
    服务员主要由 4 个 ListWidget 构成,依次获取待服务的桌号、正在服务的桌号及其菜品信息、催菜加水消息。
    3.3.7 厨师界面
    厨师的界面主要由 2 个 ListWidget 构成,依次获取待认领的菜以及需要完成的菜。厨师通过“认领选中”、“完成选中”两个按钮,将菜品的烹饪进度消息发送给顾客及服务员。
    3.3.8 管理员界面
    管理员主要负责用户和菜品信息的管理,可以实现对相关信息的增、删、添、查、改。对账户管理的主要信息为 ID、身份、密码;对菜品管理的主要信息为 ID、菜名、单价、评价星级、评价数量、菜品总销量以及菜品的种类。
    3.3.9 经理界面
    经理界面主要由 4 个 ListWidget 构成。主要显示服务员工作信息、厨师工作信息、订单记录、厨师工作记录。经理可以逐条查看菜品评论及服务员评论。

    3.4 程序运行流程
    3.5 容错功能3.5.1 数据库容错管理员的修改账户或菜品信息时,为防止数据库出现丢失或其他问题,在将数据更新至数据库之前,对数据库的有效性进行相应的判断。
    3.5.2 用户操作容错注册界面:该系统规定注册账号格式为中国大陆手机号格式,密码由字母和数字组成,至少七位。对 QDailog 的 paintEvent 重载,使得实时判断输出格式的规范性并进行提示
    点餐界面:顾客登录选桌后,会通过成员变量记录顾客已选桌的状态。这样,即使顾客在确认订单前误操而退出,也能保存顾客已有的订单记录,再次登录时,仍能看到购物车内的菜品。在进行餐桌状态查询时,由于记录了已选桌状态,所以顾客在离开桌位之前不能重复选桌,而且该系统设置,顾客只有在结账之后才 能离开桌位
    3.5.3 信息储存容错该系统将信息储存的环节放在了主界面析构函数调用之前。为了防止误操将界面关闭,代码中重载了主界面的 closeEvent,在关闭事件发生前,会出现 QMessageBox 的问题对话框,信息在确认关闭之后才能进行存储到数据库。
    3.5.4 输入机制容错利用Qt 的QTextCodec 类,使得用户输入的所有文本都被视为UTF-8字符串,避免由于用户输入不常见字符导致系统无法识别而崩溃的可能。同时,在注册界面和登录界面,利用了正则表达式,将账号输入框设置为只能输入数字,将密码输入框设置为只能输入数字和字母,以避免由于误输其他字符造成的不必要的麻烦。
    3.6 关键设计思路构建本系统框架时,关键的设计思路是数据储存以及多界面间的信息传递。为此,该系统合理利用了类的组合,Ordinary_user 内 Have_ordered_dishes 存储顾客已点的菜品的相关信息,Waiter 类 Ordinary_user 存储服务员服务的顾客的相关信息。在程序初始化时,数据库中的数据会读取到存储信息的 Data 类相应的 vector 类型的静态变量中,从而实现动态存储与读取。
    4 项目总结4.1 设计总结该系统主要分为三个模块:逻辑层、界面层、数据层。三个层次彼此分明: 逻辑层和数据层通过程序运行时的初始化和主界面析构之前的数据保存进行对接;逻辑层和界面层通过 Qt 相应功能进行对接。该系统合理应用 C++的 OOP 思想,合理利用类的继承与派生、多态性等知识点。
    该系统的界面设计利用了适量 CSS 的知识,试图最大可能的将界面进行合理的美化。
    为了避免因误操或其他原因而造成的错误,该系统在构建时考虑到适当的容错系统,如应用正则表达式来限制账号或密码输入框的输入字符的格式。
    4.2 开发及调试工作中的问题及解决方法在开发时,遇到了一个很久才解决的 bug:在一个类中添加新的类成员,在编译时,总是报错。后经上网查询相关资料,得出原因是 Qt 内部自身的 bug,解决方法是将项目 rebuilt 重新构建即可。
    此外,在应用数据库初时,总会遇到 database not open 这样无法打开数据库的错误。经查阅书籍,得出错误原因是数据库连接代码出现了问题,解决方案是将数据库连接的代码进行修改。
    4.3 难点与亮点4.3.1 难点
    难点一是界面设计:合理地设计界面格外重要,使得界面既看起来美观,使用起来也方便。这对于一个没有任何美工经验的人是一个很大的挑战。在设计好每个界面的框架之后,尽最大努力使界面变得尽可能美观。但由于一定原因,该系统的界面仍有很多优化的余地
    难点二是跨界面信息的传递:为了减少代码量,跨界面将数据传递成为其中一个难点。为此,把跨文件的变量设为静态变量使用从而实现了对跨界面信息的传递

    4.3.2 亮点
    亮点一是多界面合一的设计:不同于多数的每个流程都做一个界面的想法, 本系统将界面的个数进行压缩,将可合并的界面放在了一个界面中,实现了对界面数量的优化。在既不影响操作和美观的情况下,最大程度的将界面数量减少
    亮点二是一定的容错能力:为了避免由于误操而造成的不必要的麻烦,在逻辑层中,加入了一些容错的代码。同时运用正则表达式、QTextCode::setCodecForLocale 等知识,对用户输入的格式进行限制,增强了系统运行的安全性

    4.4 心得体会4.4.1 自学能力的重要性C++与程序设计小学期这门课是以实践为核心,编程能力的提升的根本途径无疑是多进行上机实践。Qt 在大作业中属于自学模块,除此之外,对于界面的优化还需要学习一些 CSS 的知识。在领悟知识的基础之上,更重要的就是合理的应用所学的知识:如何合理的构建类的框架、如何合理的构建界面的框架、如何合理的利用数据库合理的存储与读取数据。
    4.4.2 框架构建的重要性在正式写该项目之前,首要的把该项目的框架构建出来。框架主要分为三个层面:逻辑层、界面层、数据层。其中界面层主要应用 Qt 的相关知识,数据层主要应用数据库的相关知识,而逻辑层是该框架的核心,运用了面向对象的思想,将应有的类合理规划,理清继承和派等等类之间的关系。其次,合理设计每个层面之间的对接。在主要框架构建结束之后开始正式写此项目,会避免由于没有大体的框架而造成的反复的修改代码的结构的麻烦。
    0 评论 2 下载 2021-04-19 12:34:45 下载需要12点积分
  • 基于MFC实现的PL/0编译系统

    引言PL/0编译系统,语言:C++,MFC界面,IDE:VS2015。编译系统包含词法分析、语法分析、符号表管理、语义分析及目标代码Pcode的生成、错误处理以及Pcode的解释执行。整个编译器以语法分析程序为中心,调用词法分析程序识别单词,生成相应的代码,查询或填写相应的符号表项,在出错时调用错误处理程序,报告错误,同时跳过出错部分继续进行语法分析。
    一、PL/0语言1.1 PL/0描述PL0是一种十分简单的“高级”程序设计语言,它只有整数一种类型,但却具有相当完全的可嵌套型的分程序结构。PL/0可进行常量定义、变量说明和过程调用,并具有通常程序设计语言所必需的的最基本的语句,如赋值语句、条件语句、循环语句、过程调用语句和复合语句。考虑到输入/输出的需要,我们添加了简单的读、写语句。PL/0过程没有参数,但可以递归调用,因此,过程所加工的数据只能通过全局变量进行传递。
    PL/0语言是一种类PASCAL语言,是教学用程序设计语言,它比PASCAL语言简单,作了一些限制。比如:数据类型只有无符号整数;标识符类型只有简单变量(var)和常量(const);嵌套的层数最大值为3等。
    1.2 PL/0语言文法<程序> ::= <分程序>.<分程序> ::= [<常量说明部分>][变量说明部分>][<过程说明部分>]<语句><常量说明部分> ::= const<常量定义>{,<常量定义>};<常量定义> ::= <标识符>=<无符号整数><无符号整数> ::= <数字>{<数字>}<标识符> ::= <字母>{<字母>|<数字>}<变量说明部分>::= var<标识符>{,<标识符>};<过程说明部分> ::= <过程首部><分程序>;{<过程说明部分>}<过程首部> ::= procedure<标识符>;<语句> ::= <赋值语句>|<条件语句>|<当型循环语句>|<过程调用语句>|<读语句>|<写语句>|<复合语句>|<重复语句>|<空><赋值语句> ::= <标识符>:=<表达式><表达式> ::= [+|-]<项>{<加法运算符><项>}<项> ::= <因子>{<乘法运算符><因子>}<因子> ::= <标识符>|<无符号整数>|'('<表达式>')'<加法运算符> ::= +|-<乘法运算符> ::= *|/<条件> ::= <表达式><关系运算符><表达式>|odd<表达式><关系运算符> ::= =|<>|<|<=|>|>=<条件语句> ::= if<条件>then<语句>[else<语句>]<当型循环语句> ::= while<条件>do<语句><过程调用语句> ::= call<标识符><复合语句> ::= begin<语句>{;<语句>}end<重复语句> ::= repeat<语句>{;<语句>}until<条件><读语句> ::= read'('<标识符>{,<标识符>}')'<写语句> ::= write'('<标识符>{,<标识符>}')'<字母> ::= a|b|...|X|Y|Z<数字> ::= 0|1|2|...|8|9
    1.3 PL/0编译系统结构PL/0编译系统是一个编译-解释执行程序,整个编译过程分两个阶段进行。第一阶段先把PL/0源程序编译成假想计算机的目标程序(P-code指令),第二阶段再对该目标程序进行解释执行,得到运行结果。PL/0编译程序采用一遍扫描,即以语法分析为核心,由它调用词法分析程序取单词,在语法分析过程中同时进行语义分析处理,并生成目标指令。如遇到语法、语义错误,则随时挑用出错处理程序,打印出错信息。在编译过程中要利用符号表的登录和查找来进行信息之间的联系。一边扫描的PL/0编译和P-code解释执行框图如图1所示。
    PL/0编译系统结构框图

    二、分析与实现2.1 PL/0的词法分析PL/0编译系统中所有的字符和字符串的类型可简单分为七类,为如下表格:
    PL/0编译系统字符/字符串类型



    保留字
    Begin, end, if, then, else, const, procedure, var, do, while, odd, call, read, write, repeat, until




    算数运算符
    + | - | * | /


    比较运算符
    <> | < | <= | > | >= | =


    赋值符
    := | =


    标识符
    变量名,过程名,常数名


    常数
    整数


    界符
    , | . | ; | ( | )



    PL/0的词法分析程序getsym作为一个独立的子程序有语法分析程序调用,它的主要功能及代码结构如下:

    跳过源程序中的空格、缩进、换行等字符
    识别单词符号,并把其类别以枚举变量值存入sym中
    用变量id存放标识符,二分法查找保留字数组word[]
    若读取无符号整数,则将相应数字自妇产转换为整数存于变量num中
    通过调用getch取得一个字符,为了优化读取字符效率,每次读取一行源程序,存入缓冲区line,变量ll为源程序当前行的长度,cc为当前正在读取的字符位置

    词法分析getsym函数

    PL/0的语法分析采用了“单符号先行”技术,即在进入某个语法成分的分析子程序之前,先读取一个单词放入sym中,相对应的,在getsym中,也总是先读取一个字符存放在变量ch中。整个编译过程是先读一个单词加一个字符。
    2.2 PL/0的符号表管理2.2.1符号表结构符号表数组table存放所有的符号表项,其中符号表项结构体定义如下:
    //符号表项struct tab { string name; //名字 objecttype kind; //类型(const/var/proc) int val; //值,const专用 int level; //层次,var/proc专用 int adr; //地址,var/proc专用};
    2.2.2 符号表管理PL/0符号表管理函数


    登录符号表,即新增符号表项

    k:标识符的种类,可以为const,var或proceduredx:当前应分配的变量的相对地址,分配后要增加1lev:标识符所在的层次tx:符号表尾指针的指针,可以直接改变符号表尾指针的值
    查询符号表,查找标识符在符号表中的位置从tx开始倒序查找标识符

    找到则返回在符号表中的位置,否则返回0id:要查找的标识符名字tx:当前符号表尾指针(倒序查找)

    2.3 PL/0的语法分析PL/0采用了递归子程序法进行语法分析,即为每一个语法成分编写一个分析子程序,根据当前读取的符号,可以选择相应的子程序进行语法分析。采用不带回溯的递归子程序法,对语言文法有一定的要求:

    文法必须是非左递归
    文法的任一非终结符,其规则右部多个选择所生成的FIRST集合两两不相交
    若文法具有形如:




    根据PL/0的文法BNF表达,下表中列出了PL/0有关的语法成分的FIRST集合FOLLOW集,可以判断出满足递归子程序的要求。表说明:R表示关系运算符,id和num分别表示标识符和无符号整数。
    PL/0文法非终结符的开始符号集与后继符号集



    非终结符
    FIRST集
    FOLLOW集




    分程序block
    const var procedure id if call begin while repeat read write
    . ;


    语句statement
    Id call begin if while read write until
    . ; end


    条件condition
    odd + - ( id num
    then do


    表达式expression
    + - ( id num
    , ; ) R end then do


    项term
    id num (
    , ; ) R + - end then do


    因子factor
    id num (
    . ; ) R + - * / end then do



    PL/0的语法关系调用图如下,可以清晰地看出进行直接或间接的递归调用。

    与上图相对应,图5是语法分析函数声明,具体实现可查看syntax.cpp。

    2.4 生成目标代码Pcode语言:一种栈式机的语言。此类栈式机没有累加器和通用寄存器,有一个栈式存储器,有四个控制寄存器(指令寄存器 I,指令地址寄存器 P,栈顶寄存器 T和基址寄存器 B),算术逻辑运算都在栈顶进行。
    指令格式形如F L A,其中F表示操作码,可用枚举变量表示;L表示层次差 (标识符引用层减去定义层);A不同的指令含义不同。指令项结构体定义如下:
    //操作指令struct instruction { fct f; //操作码 int l; //层次差 int a;};
    2.4.1 地址返填技术对于if then [else],while do和repeat until语句,要生成跳转指令,采用地址返填技术。目标代码生成模式如下:
    if <condition> then <statement>[else]<condition>JPC addr1<statement>addr1:[else]
    while <condition> do <statement>addr2:<condition>JPC addr3<statement>JPC addr2addr3:
    repeat <statement> until <condition>addr4:<statement><condition>JPC addr4
    2.4.2 生成Pcode在语法分析的过程中,同时也在不断地生成Pcode。在语法分析函数中通过调用gen函数将每条指令存入code指令数组中,供之后解释执行。Listcode函数输出所有Pcode指令,存入outPcode.txt文件中。
    PL/0 Pcode管理函数

    2.5 错误处理2.5.1 错误处理的原则
    任何源程序输入序列都不会导致编译工作的崩溃
    尽可能多地发现源程序中的语法和语义在错误,并尽可能准确指出错误位置和错误属性
    尽可能进行校正,对于出现的错误,予以校正使编译继续进行

    2.5.2 错误校正对于简单的错误,如遗忘了分号,赋值符号写错等,除了给出错误信息,可以予以简单校正,使程序尽可能继续进行。
    在每个语法分析子程序的入口或出口处,调用isLegal函数, 检测下一个取得的单词是否是当前语法成分的合法头符号集或者后继符号,若不是,给出错误信息,并且跳读一段程序,直至取得合法的后继符号。
    然而,为了防止跳读的程序段太多,程序中设置了一个停止符号集合,此集合中元素为明显可以使程序开始正常编译的符号,所以只要新取来的符号属于合法后继符号集或者停止符号集,都可以停止跳读。
    在block的出口处,statement的出口处,factor的入口和出口处,都调用了合法性检测函数,isLegal函数定义如下:
    PL/0语义合法性判断

    2.5.3 错误信息教材中给出了26类错误信息,个人修改了这些错误信息的描述,使之更加清晰易懂,之后又添加了几类其他的错误信息,尽可能地检测出源程序中存在的问题。
    PL/0编译程序的错误信息



    出错编号
    出错原因




    1
    常数说明中应是’=’而不是’:=’


    2
    常数说明中’=’后应为数字


    3
    常数说明中标识符后应为’=’


    4
    const,var,procedure后应为标识符


    5
    漏掉逗号或分号


    6
    过程说明后的符号不正确


    7
    应为语句开始符号


    8
    程序体内语句部分后的符号不正确


    9
    程序结尾应为句号


    10
    语句之间漏了分号


    11
    标识符未说明


    12
    不可向常量或过程赋值


    13
    赋值语句中应为赋值运算符’:=’


    14
    call后应为标识符


    15
    call后标识符属性应为过程,不可调用常量或变量


    16
    条件语句中缺失then


    17
    应为分号或end


    18
    while型循环语句中缺失do


    19
    语句后的符号不正确


    20
    应为关系运算符


    21
    表达式内不可有过程标识符


    22
    缺失右括号


    23
    因子后不可为此符号


    24
    表达式不能以此符号开始


    25
    repeat循环语句中缺失until


    26
    代码太长,无法编译


    27
    RuntimeError,地址偏移越界


    28
    Read语句括号内不是标识符


    30
    这个数太大,超过INT32_MAX


    40
    缺失左括号



    三、扩展:解释器与GUI界面3.1 Pcode解释器其实在生成Pcode时,已经理解了Pcode每条指令的含义,很快就可以写出相应的解释器,代码对应于interpret.h和interpret.cpp中。
    假想的一个PL/0计算机,有两个存储器、一个指令寄存器和三个地址寄存器组成。存储器code存放程序Pcode指令,存储器S作为运行栈, 实现栈式动态存储分配。指令寄存器ins存放当前执行的Pcode指令;栈顶地址寄存器top作为栈顶指针,总是指向运行栈S的栈顶;程序地址寄存器p存放下一条要执行的指令地址(数组索引);基地址寄存器bp,存放当前运行的分程序数据区在数据栈S中的起始地址,即bp总是指向动态链的链头。
    如下表格4是Pcode的指令含义及其解释执行过程。说明:base函数作用是通过静态链求出数据区的基地址,Cin、Cout为输入输出流,对应着input.txt与output.txt文件。
    Pcode的含义与解释执行



    指令
    具体含义
    具体操作




    LIT 0 a
    取常量a置于栈顶
    top++; S[top] = ins.a;


    OPR 0 a
    执行运算,a的值表示执行何种运算
    根据a值的不同执行不同的操作


    LOD l a
    取变量(层次差为l,相对地址为a)置于栈顶
    top++; S[top] = S[base(ins.l) + ins.a];


    STO l a
    将栈顶值存入变量(层次差为l,相对地址为a)
    S[base(ins.l) + ins.a] = S[top]; top—;


    CAL l a
    调用过程(层次差为l,入口指令地址为a)
    S[top + 1] = base(ins.l); S[top + 2] = bp; S[top + 3] = p; bp = top + 1; p = ins.a;


    INT 0 a
    分配空间,栈指针top增加a
    top += ins.a;


    JMP 0 a
    无条件跳转至地址a
    p = ins.a;


    JPC 0 a
    条件跳转至地址a
    if (S[top] == 0) p = ins.a; top—;


    RED l a
    读数据,存入变量(层次差为l,相对地址为a)
    Cin >> S[base(ins.l) + ins.a];


    WRT 0 0
    写数据,将栈顶值输出
    Cout << S[top] << endl; top++;



    3.2 GUI界面PL/0编译器界面采用简易MFC制作,编译系统初始界面如图8。
    界面中左上文本框为代码输入区,可直接输入Pl/0代码。上面有三个按钮,其中导入按钮可以选择文件导入代码编辑区;点击编译按钮,将会编译代码编辑区中的代码,右侧显示Pcode,左下方会显示编译成功或者显示错误信息,其中代码编辑区的代码会保存在inCode.txt中,输出Pcode会保存在outPcode.txt中;在点击解释按钮前,如果程序中有输入数据,先在输入框中输入数据(数据可多不可少),再点击解释按钮,否则会弹出数据不够,左下的输出框会显示解释结果。所有重要的信息在后台都有文件的备份。
    MFC初始界面

    这里,我们导入测试样例1求解鸡兔同笼问题(吐槽一句,这个求解代码方法错误),图9是点击编译之后的结果。
    MFC编译代码界面

    我们现在输入框中输入数据,比如5 14,在点击解释按钮,在左下的输出框中就能看到程序执行的结果啦!
    MFC执行代码界面

    再来看一个输出错误信息的样例, 导入样例4语法错误样例,再点击编译,结果如图11,虽然出现了很多很多条错误信息(必须的),在右侧还是可以看到100多条Pcode指令,说明我们的错误校正还是挺有用的,至少没有直接结束编译,
    MFC执行代码界面

    3.3 测试样例说明一共设计七个测试样例文件,如下表格
    PL/0编译系统测试用例



    样例编号
    样例描述




    1
    教材P309例14.1 求解鸡兔同笼问题


    2
    教材P310例14.2 求最大公约数和最小公倍数


    3
    教材P310例14.3 打印素数表


    4
    教材P320例14.7.2 语法错误样例


    5
    if then else测试样例


    6
    repeat until测试样例


    7
    个人错误测试样例



    3.4 编译系统文件说明PL/0编译系统源代码文件



    文件名
    文件描述




    console.h/console.cpp
    编译系统程序总控程序,初始化变量,并启动词法、语法分析


    error.h/error.cpp
    错误输出,分析过程中随时输出错误信息


    Init.h
    编译系统各部分“联系人”,保存着所有的全局变量


    interpret.h/interpret.cpp
    解释执行模块,包含base函数与interpret函数


    lexica.h/lexcica.cpp
    词法分析模块,包含getch、getsys、isLegal函数


    pcode.h/pcode.cpp
    Pcode处理模块,包含gen、listcode函数


    sytax.h/sytax.cpp
    语法分析模块,包含递归子程序各个函数


    sysTab.h/sysTab.cpp
    符号表管理模块,包含enter、position函数


    inCode.txt
    代码输入区的备份


    input.txt
    数去数据的备份


    outError.txt
    错误处理信息的备份


    outPcode.txt
    Pcode指令集的备份


    output.txt
    输出数据的备份



    四、实践感想不得不说,语言处理是个细腻差事。从最开始根本不懂什么是Pcode,到现在甚至可以大脑生成Pcode(开玩笑的),中间是个“痛苦”的过程。
    由于之前对PL/0进行过词法分析,这一块问题倒是不大,有所改变的是这一次并不是整个代码一次全部分析完,而是通过语法分析程序一个一个取得单词,作为语法分析的资源池。最难的一块当属语法分析模块,虽然对递归子程序法比较了解,实验也写过,语句、表达式、条件、项之间的递归调用自然没问题,难就难在语法分析程序是整个编译系统的核心,他另一边还连着符号表以及Pcode的生成,最后还有众多的错误处理,这的是一下子炸开了,删掉重写了好多次,肝了n天。最后慢慢地,一个一个慢慢加上去,而不是想到什么写什么,一下子符号表,一下子又写错误处理,到头来代码乱成一团,自己都看不懂了。
    个人认为第二个难点在于Pcode的理解,如果不能理解,不仅无法生成正确的Pcode代码,扩展中的解释执行更是别想了。虽然只有10个不同的指令类别,用起来时还是变换万千的,从网上找了些博客,一条一条地理解每类指令的作用,以及在分析过程中什么时候需要什么指令操作,最后才在语法分析程序中添加了Pcode的生成代码,实在是不容易。在理解了Pcode后,写解释执行的程序也就变得简单了,只需要两个函数,100多行代码就可以模拟栈式计算机解释执行Pcode了。
    其实错误处理也是有难度的,因为教材中已经给出了26条错误信息,一开始慢慢的加,总是不能覆盖所有的错误,大概花了两天的时间才把教材中的所有错误都用上了,甚至还自己加了几条新的错误信息,可把我牛逼坏了。
    通过这次实践,第一感受就是写代码条例要清晰,头脑要冷静。千万不能想到什么就写什么,到头来真的是鬼也看不懂的代码。功能也是要一个一个地加,写好一个,再来写下一个,不能多路开发。可以说,这个实践作业包括了本学期编译原理课程的大部分重要内容,在将近期末之际,也顺便复习了一波课程内容,一点不亏。结合每一章的重点内容,凑齐了PL/0编译系统的每一个模块,最终效果不错,不负多个晚上的熬夜以及那快掉完的头发sad
    有些不满意的就是GUI界面了,一直以来就不太会用C++写界面,MFC更是不太熟练,用起来比较生硬,最后功能虽然比较齐全,外表看起来还是挺朴素的。另外一个不太好的设计就是输入数据那块,要求事先输入数据是个不太好的设计,如果可以在执行过程中弹出窗口进行输入的话或更好一些,这也是需要改进的地方。
    0 评论 1 下载 2021-04-18 11:33:07 下载需要10点积分
  • 基于React和MySQL实现的宠物领养管理系统

    一、技术简介1.1 HTML5技术简介HTML5 将成为 HTML、XHTML 以及 HTML DOM 的新标准。HTML 的上一个版本诞生于 1999 年。自从那以后,Web 世界已经经历了巨变。HTML5 仍处于完善之中。然而,大部分现代浏览器已经具备了某些 HTML5 支持。
    1.2 ES6简介ECMAScript 6(以下简称ES6)是JavaScript语言的下一代标准,于2015年6月批准通过。ECMAScript6的目标,是使得JavaScript语言可以用来编写复杂的大型应用程序,成为企业级开发语言。让代码更加准确,更易于阅读。
    ECMAScript是JavaScript语言的国际标准,JavaScript是ECMAScript的实现(ES是规范,JS是实现)。在日常场合,这两个词是可以互换的。
    1.3 ReactReact 是一个用于构建用户界面的 JAVASCRIPT 库。
    React主要用于构建UI,很多人认为 React 是 MVC 中的 V(视图)。
    React 起源于 Facebook 的内部项目,用来架设 Instagram 的网站,并于 2013 年 5 月开源。
    1.4 Koa2Koa 是一个新的 web 框架,由 Express 幕后的原班人马打造, 致力于成为 web 应用和 API 开发领域中的一个更小、更富有表现力、更健壮的基石。 通过利用 async 函数,Koa 帮你丢弃回调函数,并有力地增强错误处理。 Koa 并没有捆绑任何中间件, 而是提供了一套优雅的方法,帮助您快速而愉快地编写服务端应用程序。
    1.5 Ant Design这里是 Ant Design 的 React 实现,开发和服务于企业级后台产品。主要服务于 PC 界面的中后台产品。提炼自企业级中后台产品的交互语言和视觉风格。开箱即用的高质量 React 组件。使用 TypeScript 构建,提供完整的类型定义文件。全链路开发和设计工具体系。
    1.6 JSON Web TokenJSON Web Token(缩写 JWT)是目前最流行的跨域认证解决方案,用于向Web应用传递一些非敏感信息。例如完成加好友、下订单的操作等等。用于设计用户认证和授权系统。实现Web应用的单点登录。一个JWT实际上就是一个字符串,它由三部分组成:头部、载荷与签名。
    1.7 MySQLMysql是最流行的关系型数据库管理系统,在WEB应用方面MySQL是最好的RDBMS(Relational Database Management System:关系数据库管理系统)应用软件之一。
    1.8 NavicatNavicat 是一套能帮助你快速直观地构建精确模型的图形化工具,使各个层面的用户都能轻松地创建高品质的数据模型。它能为专业人士提供适合其特殊需要的复杂功能,但是对数据模型的新手来说又相当容易上手。
    创建一个优良的数据模型可以是很困难的。我们将一切保持简单方便,让你专注于你的数据库设计,而不会令得它变得更复杂。
    为了让你无需花费时间学习,便能对你的模型有一个简单而精确的了解,Navicat 拥有难以置信的迅速反应和简洁美观的设计,大大增强了其性能和可用性。
    再加上准确的字段类型预测功能和无限次的撤消或重做功能,它就能减省开发所需的时间并提供一个快捷高效的方式来创建和编辑你的表或视图结构。
    无论你是想从一个数据模型创建新的数据库,或者从现有数据库导入数据模型。Navicat Data Modeler 就是你所需要的工具。
    1.9 VScodeVisual Studio Code(以下简称vscode)是一个轻量且强大的代码编辑器,支持Windows,OS X和Linux。内置JavaScript、TypeScript和Node.js支持,而且拥有丰富的插件生态系统,可通过安装插件来支持C++、C#、Python、PHP等其他语言。
    据vscode的作者介绍,这款产品可能是微软第一款支持Linux的产品。
    微软对于vscode的定位如下图,位于编辑器与IDE之间,但是更像一个编辑器。有人说是披着编辑器外衣的IDE,我觉得是披着IDE外衣的编辑器。
    深入了解了vscode之后发现了vscode很贴心地内置了很多功能,让我觉得我可以很快适应到vscode的使用。
    二、系统概要设计系统的设计主要前台和后台两个部分:

    前台客户端:是展现给用户的,包括登录注册、查看网站首页、查看宠物列表、根据种类筛选宠物列表、查看宠物详情、认领宠物、查看个人宠物认领情况
    后台管理端:是宠物店管理人员使用的,包括管理员登入与登出、查看管理员列表、查看与编辑宠物分类、查看与编辑宠物信息、用户管理、处理领养申请、网站首页轮播图管理

    2.1 系统需求分析
    管理端

    登录(权限校验)个人信息管理管理员管理(增删改查)前台用户管理(删改查)宠物信息管理(增删改查,需要上传图片,状态更改:发布中、已选择领养人、已领养)宠物分类管理(增删改查,联动删除)领养订单处理(增删改查,审核)
    用户端

    登录/注册首页展示筛选宠物信息(地区、品种、年龄筛选,关键字查询)查看宠物详情(展示,点击按钮报名)报名领养查看订单列表(订单状态:已报名、已通过、已领养)个人信息管理

    前台发起报名,后台管理端查看前台报名的用户信息,选择进行联系,择一通过。
    2.2 可行性分析这里讲的可行性分析的任务是从技术上、经济上分析需解决的问题是否存在可行性。其目的是在尽可能短的时间内用尽可能小的代价确定问题是否有解。
    2.2.1 技术可行性技术上的可行性分析主要分析技术条件能否顺利完成开发工作,硬、软件能否满足开发者的需要等。
    本系统前端设计React框架实现,并使用阿里的Ant Design框架构建UI,React 可以非常轻松地创建用户交互界面。为你应用的每一个状态设计简洁的视图,在数据改变时 React 也可以高效地更新渲染界面。以声明式编写UI,可以让你的代码更加可靠,且方便调试。创建好拥有各自状态的组件,再由组件构成更加复杂的界面。无需再用模版代码,通过使用JavaScript编写的组件你可以更好地传递数据,将应用状态和DOM拆分开来。无论你现在正在使用什么技术栈,你都可以随时引入 React 开发新特性。
    本系统数据库使用的MySQL,MySQL是最流行的关系型数据库管理系统,在WEB应用方面MySQL是最好的关系型数据库,轻量、开源、简便易用,使用Navicat Premium 12做数据库图形化管理更高效率进行前后端开发
    2.2.2 经济可行性如今是信息化时代,信息化管理可以使宠物领养的管理工作更加系统化、快速化、全面化。这样可以为社会带来较高的工作效益和经济效益,本系统对计算机配置的要求不高,普通私人电脑都可以完全满足需要,本系统作为一个设计,其开发目的是为巩固所学知识,无需开发经费,因此在经济上也是可行的。
    综上所述,本系统的开发目标已经明确,且在技术和经济上都是可行的,因此系统的开发是完全可行的。
    2.2.3 操作可行性该系统如投入使用,预期作到界面友好,管理方便,使用简单,管理人员经过培训,也是完全能够使用本系统管理相关信息的。
    综上所述,本系统的开发目标已经明确,且在技术和经济上都是可行的,因此系统的开发是完全可行的。
    2.3 网站模型
    2.4 Server端模型
    利用Koa服务器,用于连接客户端和数据库服务器。对于客户端发出的需要对数据库进行访问的请求,Koa服务器负责客户端与数据库服务器的网络通信,并将相关数据嵌入返回给客户端的页面;对于客户端发出的不需要对数据库进行访问的请求,Koa服务器将直接处理这些请求,并将最终生成的数据发往客户端浏览器。
    三、数据库设计3.1 数据概念结构设计E-R模型是数据进行第一层抽象的表示方法。它的主要成分包括:实体、联系和属性。我们可以用E-R图将内容表达出来,辅助设计的实现[6]。
    3.2 数据库关系设计该网络学校系统数据库关系图如下所示:

    3.3 数据字典管理员表(admin_user)



    字段
    类型
    主键
    允许空值
    备注




    id
    int(11)
    P

    自动递增


    username
    varchar(255)





    password
    varchar(255)





    role
    tinyint(4)


    1:管理员;2:超级管理员


    is_delete
    tinyint(4)


    默认0


    phone
    varchar(255)





    address
    varchar(255)





    create_time
    varchar(255)





    宠物申请表(order_list)



    字段
    类型
    主键
    允许空值
    备注




    id
    int(11)
    P

    自动递增


    user_id
    int(11)





    pet_id
    int(11)


    时间戳


    is_delete
    tinyint(4)





    create_time
    varchar(20)





    status
    tinyint(4)


    0 申请中;1 申请通过;2 申请未通过



    用户表(user)



    字段
    类型
    主键
    允许空值
    备注




    id
    int(11)
    P

    自动递增


    username
    varchar(255)





    password
    varchar(255)





    is_delete
    tinyint(4)


    默认0


    phone
    varchar(255)





    address
    varchar(255)





    create_time
    varchar(255)





    宠物表(pet)



    字段
    类型
    主键
    允许空值
    备注




    id
    int(11)
    P

    自动递增


    name
    varchar(255)





    image
    bigint(13)





    age
    tinyint(4)





    status
    tinyint(4)


    0 待申请;1 申请中;2 被领养


    area
    text





    category_id
    int(11)





    pet_desc
    text





    pet_breed
    varchar(255)





    is_delete
    tinyint(4)


    默认0


    create_time
    varchar(20)





    宠物分类(pet_cate)



    字段
    类型
    主键
    允许空值
    备注




    id
    int(11)
    P

    自动递增


    name
    varchar(255)





    create_time
    varchar(255)





    宠物品种表(pet_cate)



    字段
    类型
    主键
    允许空值
    备注




    id
    int(11)
    P

    自动递增


    name
    varchar(255)





    create_time
    varchar(255)





    cate_id
    int(11)





    首页轮播图表(slider_img)



    字段
    类型
    主键
    允许空值
    备注




    id
    int(11)
    P

    自动递增


    image
    varchar(255)





    create_time
    varchar(255)





    display_order
    int(11)

    默认0



    pet_id
    varchar(20)





    四、 前端部分4.1 管理端部分4.1.1 登录部分
    用户输入用户名密码,密码使用md5加密,点击登录向后台发送,若匹配失败,返回’用户名或密码错误’并弹出提示消息;若匹配成功,向前端返回一个token令牌,前端储存在localStorage中,并弹出登录成功的提示,后跳转入home路由。
    登录成功后,进入main路由,此时将cookie中的token取出并发送给后台,后台匹配token是否存在且未过期,若匹配失败,则跳转回login路由;若成功,则将用户信息发送至前端,前端将信息存在vuex的state中。
    当用户点击退出登录时,清除localStorage中的token并跳转回login路由。
    4.1.2 管理员管理
    管理员管理页面显示管理员列表包括管理员的 用户名、电话、地址、删除按钮,添加管理员的按钮,点击添加管理员的按钮出现添加管理员的对话框。

    添加管理员的操作,对表单的数据做了正确性校验,通过校验才可以提交表单:

    删除的操作会有确认删除的提示:

    4.1.3 宠物分类管理
    宠物分类的页面获取所有的宠物分类,可以添加分类、编辑分类、删除分类、添加种类、删除种类.
    添加分类会判断数据不能为空才可以提交:

    编辑分类:

    删除分类的提示:

    4.1.4 宠物信息
    宠物信息页面获取所有的宠物信息,每页显示10条数据,可以添加宠物,编辑宠物、删除宠物,添加宠物成功后会现在本地添加数据,减少请求的次数,删除的操作也会先从本地的数据删除对应的那条,减少添加删除的操作后有需要去请求新的数据,减少服务器压力。
    添加宠物的对话框会对表单的数据做合理性校验,上传图片的操作会先将图片保存到服务器中,返回图片的存储路径,而后表单提交的时候整体提交数据。

    4.1.5 用户管理
    用户管理页面获取所有的用户数据,用于查看数据、删除用户。
    删除会有确认删除的提示:

    4.1.6 个人信息
    个人信息会展示当前用户的信息,可以快捷的修改电话和地址。
    点击修改密码的按钮,出现输入新密码的输入框,会有两次密码相同的校验。

    4.1.7 领养申请
    领养申请页面用于管理员管理用户的申请请求,可以看到订单的状态,允许、拒绝的操作以及删除订单的操作、并在获取列表时做了分页处理。
    4.1.8 首页轮播图管理
    首页轮播图的用户从宠物列表中添加宠物展示到web端的首页的轮播图中。

    4.1.9 404当用户访问不存在的页面时,跳转入404 no found页面。

    4.2 客户端部分4.2.1 登录
    用户输入用户名密码,密码使用md5加密,点击登录向后台发送,若匹配失败,返回’用户名或密码错误’并弹出提示消息;若匹配成功,向前端返回一个token令牌,前端储存在localStorage中,当用户点击退出登录时,清除localStorage中的token;在需要判断权限的地方再拿token做校验。
    4.2.2 注册
    用户注册页面,选项均做了表单校验,用户名、密码与手机号做了正则表达式的校验。
    4.2.3 个人信息
    个人信息页面用来展示个人的信息、以及修改电话和地址等基本信息,点击修改密码的按钮可以进行修改密码的操作。
    4.2.4 首页信息
    首页展示所有的宠物信息、宠物分类、以及首页轮播图的展示。
    宠物分类下的种类选择:

    4.2.5 宠物详情点击宠物卡片上详情按钮,可以弹出宠物详情的对话框,用来展示宠物信息以及做认领操作。

    4.2.6 申请列表只有处于登录状态,才可以获取申请宠物的列表,否则会提示‘请先登录的操作’,登录后可以查看该用户的申请列表的信息。

    4.2.7 搜索可以通过顶部的搜索输入框按照宠物姓名去搜索宠物。

    五、后台部分5.1 路由RESTful架构遵循统一接口原则,访问同一资源时均使用相同路由,根据不同请求方式进行数据操作。
    使用koa-router中间件对路由进行处理。
    5.2 初始化数据库脚本本系统后台使用nodejs初始化数据库,在MySQL中新建一个名为pet的数据库,执行initTable.js即可初始化数据库。

    5.3 权限校验本系统在后台校验用户权限,每一次用户发起请求,须经过一中间件,中间件中先判断请求是否在白名单内,若不在,则根据token校验用户权限,使用JSON Web Token进行校验,若校验失败,则须用户重新登录,若校验成功,则进行下一中间件的执行。

    5.4 跨域跨域是前后端联调开发中经常会遇到的问题,由于浏览器有同源策略,用来防止CSRF攻击,当前端发出请求的时候,请求的协议名,地址,端口号与当前的有一个不同,就会引发浏览器拒绝跨域请求,解决跨域问题的方法有很多,比如jsonp,服务器代理,document.domain + iframe等等方式解决跨域问题。
    本系统使用的node服务器代理,通过nodejs将接口的请求代理到 localhost:3000 ,由node层发送请求不会受到浏览器同源策略的影响,以此解决跨域问题。

    5.5 图片处理图片上传功能使用文件流发送至后台,后台使用nodejs的fs模块对文件进行操作。

    5.6 密码加密为保障用户密码安全性,在数据库中没有使用明文显示,而是经过了一步MD5加密,MD5消息摘要算法是一种被广泛使用的密码散列函数,可以产生出一个128位(16字节)的散列值(hash value),用于确保信息传输完整一致。用户注册和登录时,后台会将发送来的密码通过passwordMd5Fn进行加密后再存库或查询匹配。

    六、结论6.1 系统的特点本系统是一个宠物领养管理系统,采用前后台分离的模式来开发。本系统从功能上来说,比较完备。系统以Web界面与用户交互,为用户提供信息并接受其操作,同时通过数据库管理系统来存储信息数据。系统实现了对信息数据的浏览、查询、编辑和管理等基本数据库操作,系统采用了模块化设计方法,根据用户的需求及程序的应用与维护的易用性,将各个部分置于不同的模块当中,方便了程序的扩展与维护,同时建立了程序功能复用的基础。使用jsonwebtoken做权限验证,实现了单点登录的功能,使系统更加安全可靠.
    6.2 系统的不足和改进本系统基本上满足了宠物领养管理系统关于信息管理方面的需要。实现了宠物领养管理系统所需的功能。在界面上力求做到美观、在操作方面尽量避免由于用户操作不当带来系统的出错现象。但由于时间仓促,本系统还存在一些不足之处,界面不够美观,需要进一步修饰和美化;对数据库操作的性能有待进一步优化,虽然本系统优化了不少,但要达到理想状态还有一段距离,如部分功能程序代码过长,如果后台数据库过大将会影响运行速度;部分数据库表的设计存在一定的冗余,有待进一步优化。根据系统的不足,继续改进和完善本系统。提高审美观点,可使用photoshop、fireworks等图片处理工具修饰图片,力求给用户提供美观友好的界面;简化程序代码,可使不同界面之间能共享一些方法、函数和变量,对于相同的功能模块可生成程序包供其它界面引用,这样就会提高系统的运行速度;使用数据库连接池技术提高数据库操作的性能;数据库的关系模式可以进一步规范化,减少冗余现象。
    0 评论 2 下载 2021-04-17 10:39:36 下载需要12点积分
  • 基于汇编实现的欢乐QQ堂小游戏

    一、介绍本次实现制作了汇编版的QQ堂,使用了VGA 320x200 256色视频显示, FAT12文件系统、时钟中断,nasm + gcc联合编译,通过端口设置调色板。其中除了AI,游戏界面、逻辑等均由汇编实现。游戏具有良好的图形界面,流畅的操作性,令人愉快的玩法,并且有AI与你作战。
    首先展示游戏的开始界面:

    按任意键可以进入游戏界面:

    胜利,成功打败年兽:

    二、实现方式这里重点说明视频显示的方法:
    进入视频模式
    通过设置ah = 0, al = 13h, 调用0x13号中断,进入320 x 200 256色视频模式。
    视频显存与缓存
    段0xA000为显存段,每个字节对应屏幕上的一个像素。使用一个内存段作绘制缓存,每次更新画面,首先将图像绘制到内存,最后将结果拷贝到显存中,这样的方式避免了屏幕刷新各个图片的层次覆盖出错的问题(如人物被地图覆盖)。
    颜色处理

    每个像素对应的字节分为3段,从高位到低位,R、G各占3位,B占2位
    通过端口设置调色板颜色(color.asm)
    使用时钟中断,确保屏幕每秒刷新60次,也很好地控制了角色等事件的刷新速度

    图片存储
    图片的存储格式为一个二进制文件,每个字节对应一个像素。使用python脚本tu.py将png或jpg文件转换为二进制文件。
    图片加载
    由于固定段地址后,偏移量的取值范围为64k,而图片总共大小远远超过了这个范围。因此使用了FAT12文件系统存储图片,从文件系统中读取图片文件,并放到指定的不同段中。
    三、操作方式
    操作方式

    方向键移动空格开始游戏,或者在结束游戏时返回开始界面
    剧情

    年兽来糖果王国踢足球了,你要打败它界面上方为年兽的血量,共5 HP你可以踢足球:-)在驱逐年兽的同时,要避免足球炸弹的伤害

    四、实验环境与工具4.1 实验环境
    物理机操作系统:Arch Linux 4.5.4-1
    调试使用虚拟机:qemu-system-i386, bochs
    虚拟机软件:VMware Workstation 12 Pro
    虚拟机配置:CPU: i7-4702MQ @ 2.20GHz, 使用单核单线程
    内存:4 MB
    硬盘:32 MB

    4.2 实验工具
    编辑器:Vim 7.4
    汇编工具:NASM 2.11.08
    C语言编译器:gcc 6.1.1
    链接工具:GNU ld 2.26.0.20160501
    构建工具:GNU Make 4.1
    调试工具:Bochs x86 Emulator 2.6.8
    虚拟机:qemu-system-i386
    VMWare Workstation 12 Pro
    合并文件:dd
    图像编辑:gimp2.8.16
    地图编辑:RPG Maker XP 1.02
    另外使用了Python 2.7的PIL,numpy等库

    五、小结这次实验,我做了汇编版的QQ堂,这是我比较喜欢玩的游戏,我觉得我做的游戏在技术上(VGA视频显示,图片的存储与读取,AI,代码规范),细节上(游戏的流畅性,炸弹爆炸的细节(可以看见不同方向的火焰图像是不一样的,火焰距离是根据是否能经过某格判定的),可以重新开始游戏)比较满意的。除了LoadKnl.asm和disk.asm借用了老师的代码,其他代码(游戏本体,AI,图片转换,地图数据导出)都是自己编写的。我在小学的时候,已经能使用RPG Maker XP制作这一个游戏,里面的图片大多数是自己截图并整理的,有趣的是开始界面的图片也是我以前使用画图绘制,现在稍作修改的。在9天的时间内,能通过汇编完成这个游戏的基本框架,我觉得是很大的突破。
    0 评论 1 下载 2021-04-15 11:35:57 下载需要9点积分
  • 基于C#实现的电影院售票管理系统

    一、引言1.1选题背景随着互联网和电子商务的快速发展,网上购物已经成了现代人生活中很重要的一种方式,如:数码产品、生活用品、化妆品护肤品等,只要是人们需要到的东西,基本都可以在网上购买。除了购买各种物品,现代人的生活也不再向过去一样单调,除了学习和工作之余,人们的娱乐生活也逐渐丰富,最普遍的娱乐休闲方式之一就是到电影院看电影,那么传统的电影订票窗口显然已经不能满足人们的需要了,所以开发一个电影院网上订票系统是非常必要和可行的。以前传统的电影票订票方法是去电影院的购票窗口查看电影的上映时间、场次、可选座位等信息再进行购票,人们往往需要排队才能买到电影票,这样不仅浪费了人们宝贵的时间,而且电影院工作人员的工作量也很大,对于这种低效率、浪费时间的事情,完全可以以网上购票的方式来改变。
    为了提高劳动的效率、节约成本、提高服务质量,我们小组开发了此款系统,用以方便影院的售票和客户的购买,通过这个系统,可以很快的实现会员注册、登录、购票,后台管理员可以新增影片、排片等基本操作。
    二、需求分析2.1 用户需求需要在网上购买电影票的用户可使用本系统,进行会员的注册登陆之后可以进行网上查询电影、购买电影票等操作,省去了去电影院实体窗口排队买票的繁 琐程序。
    2.2 系统功能分析
    新用户的注册、登录,用户数据能存在后台数据库中
    电影的录入、删除、查询、修改
    电影的排片
    管理员查询会员级别等信息
    会员查询影片信息
    会员购买电影票

    2.3 条件与限制系统可以实现一些基本的购票功能,但系统较简单,尚存在很多缺陷,不能实现完善和全面的功能。
    缺陷:

    首先要使用admin进行登录才能开始注册会员
    购票后无法查看购票信息
    不可以支持选座
    购票时不能通过搜索影片名字等来查找影片

    三、模块设计3.1 系统流程图系统流程图如图一所示:

    系统功能图如图二所示:

    3.2 系统使用指南对于用户
    首先,系统使用者先通过admin登录,进入到新用户注册页面,以管理员的身份为用户注册一个新的会员账号,已注册好的账号密码自动保存在后台数据库中,用户下次可以直接使用已注册的会员账号登录本系统进行电影的查询、购票等操作。
    对于管理员
    首先,管理员可以为新用户注册不同级别的会员账号、查看会员的信息。其次,管理员可在系统后台做电影的录入、删除、查询、修改等基本操作,除此之外,添加好影片后可以对电影进行的排片。
    四、数据库设计及实现4.1 系统E-R图E-R图如图三所示:

    4.2 逻辑结构设计(关系数据库设计)
    顾客(Cus、CusCard、CusType、CusTel(key))
    登陆(UserName、UsePwd、UserType)
    电影(Mname(key)、MBZ、MLanguage、MTYPE、MDirector、MACT、MTime)
    排片(MName(key)、MPrice、MRoom、Mcount、MTime、MBRQ、MERQ)
    上映(ID(key)、MName、MPrice、MRoom、MCount、MTime、MRQ)
    购票(PID(key)、Cname、GPCount、GPJE、MName、SYRQ、FYT、GPRQ、CZY)

    4.3 数据库主要代码及触发器会员信息
    CREATE TABLE [dbo].[Cus]( [CusTel] VARCHAR(50) NOT NULL PRIMARY KEY, [CusName] VARCHAR(50) NOT NULL, [CusCard] VARCHAR(50) NULL, [CusType] VARCHAR(50) NULL)
    触发器
    SET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOALTER TRIGGER [dbo].[InsertULogin] on [dbo].[Cus]after insertasdeclare @username varchar(50)declare @userpwd varchar(50)select @username=CusTel from inserted select @userpwd= right(CusCard,6) from inserted insert into ULogin values(@username,@userpwd,'C')
    购票信息
    CREATE TABLE [dbo].[GP]( [PID] VARCHAR(50) NOT NULL PRIMARY KEY, [CName] VARCHAR(50) NOT NULL, [GPCount] INT NULL, [GPJE] FLOAT NULL, [MName] VARCHAR(50) NULL, [SYRQ] VARCHAR(50) NULL, [GPRQ] VARCHAR(50) NULL, [CZY] VARCHAR(50) NULL, [FYT] VARCHAR(50) NULL)
    触发器
    SET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOALTER TRIGGER [dbo].[UpdatePP] on [dbo].[GP]after insertasdeclare @MName varchar(50)declare @SYRQ varchar(50)declare @count intselect @MName= MName,@SYRQ=SYRQ,@count=GPCount from inserted update MovieSY set mcount=mcount-@count where MName=@MName and MRQ=@SYRQ
    电影信息
    CREATE TABLE [dbo].[Movie]( [MName] VARCHAR(50) NOT NULL PRIMARY KEY, [MLanguage] VARCHAR(50) NOT NULL, [MDirector] VARCHAR(50) NULL, [MAct] VARCHAR(50) NULL, [MName] INT NULL, [MBZ] VARCHAR(255) NULL, [MType] VARCHAR(50) NULL)
    上映信息
    CREATE TABLE [dbo].[MovieSY]( [ID] INT NOT NULL PRIMARY KEY, [MName] VARCHAR(50) NOT NULL, [MRoom] INT NULL, [MCount] varchar(50) NULL, [MName] INT NULL, [MTime] VARCHAR(50) NULL, [MRQ] VARCHAR(50) NULL)
    排片信息
    CREATE TABLE [dbo].[PP]( [MName] VARCHAR(50) NOT NULL PRIMARY KEY, [MPrice] INT NOT NULL, [MRoom] VARCHAR(50) NULL, [MCount] INT NULL, [MTime] VARCHAR(50) NULL, [MBRQ] VARCHAR(50) NULL, [MERQ] VARCHAR(50) NULL)
    触发器
    SET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOALTER TRIGGER [dbo].[InsertPP] on [dbo].[PP]after insertasdeclare @MName varchar(50)declare @BRQ varchar(50)declare @ERQ varchar(50)declare @MTime varchar(50)declare @MRoom varchar(50)declare @MPrice intdeclare @MCount intdeclare @MBRQ datetimedeclare @MERQ datetimedeclare @RQ varchar(50)select @MName= MName,@BRQ=MBRQ,@ERQ=MERQ,@MTime=MTime,@MRoom=MRoom,@MPrice=MPrice, @MCount=MCount from inserted set @MBRQ=CONVERT (datetime,@BRQ)set @MERQ=CONVERT (datetime,@ERQ)while @MBRQ<=@MERQbegin set @rq=CONVERT(varchar(50), @MBRQ, 112)insert into MovieSY values(@MName,@MPrice,@MRoom,@MCount,@MTime,@RQ) set @MBRQ=DATEADD(DAY,1,@MBRQ)endCREATE TABLE [dbo].[MovieSY]( [UserName] VARCHAR(50) NOT NULL PRIMARY KEY, [UserPwd] VARCHAR(50) NOT NULL, [UserType] VARCHAR(50) NULL)
    五、系统设计与实现5.1系统开发环境
    硬件环境

    Intel Pentium 166MHz或以上;内存:需要至少512MHZ;
    软件环境

    运行于Windows2010版的操作系统之上;SQL Server2008数据库;Visual Studio2013;

    5.2 功能模块
    输入功能模块
    查询显示功能模块
    查询、售票功能模块
    登录、注册功能模块

    5.3 系统主要页面展示登录、注册页面

    登陆后的页面

    会员注册页面

    会员信息查询页面

    添加影片页面

    查询修改影片页面

    排片页面

    “排片”页面通过连接数据库,可以搜索影片的名字、导演、主演来选择影片,再输入票价,放映大厅,座位数,放映时间等信息,最后确认排片。
    购票页面

    购票页面通过对获得的已经被排片的电影进行选择而进行购票这一操作。在购票前需填入购票数量、联系电话,系统会自动计算合计金额。之后点击购票按钮则能进行购票操作。但一旦购票成功则不能进行退票操作,也不能查看所购买的电影票。
    数据库页面

    六、主要特色6.1 系统实用性系统首先可以进行新用户的注册,用户数据能存在后台数据库中。管理员可以进行电影的录入、删除、查询、修改,添加好影片后进行电影的排片。退出登录后再使用之前注册的会员登录,可以购买电影票。
    6.2 突出优势和特色(创新点)
    购票时可以看到影片的导演、主演等信息
    用户分为钻石用户,白金用户和普通用户,对用户进行了分类

    7 小结数据库技术课程设计是一次对课堂所学知识的灵活应用,是理论知识与实践的相结合。经过了一周的课程设计,本系统基本达到了当初的设计要求,设计上也基本合理。我们不仅对数据库系统的认识更加深入,同时也掌握了面向实体的系统分析的基本方法,对VS也有了新的认识,也知道了要有坚持不懈,不惧困难的精神,才能取得成功。一个简单的系统,每一个细节都需要在实践中去挖掘并进行进一步的修改完善。本次课设让我们受益匪浅,在分析问题以及解决问题等方面的能力有所提高,也是一次很好的同学之间交流合作的机会。数据库技术的用途很广,还有很多值得我们学习,希望今后能有更多这样的机会。
    27 评论 323 下载 2019-01-01 21:08:08 下载需要18点积分
  • 基于JAVA和SQL SERVER数据库实现的个人财务管理系统

    一、需求分析个人财务管理系统是智能化简单化个人管理的重要的组成部分。并且随着计算机技术的飞速发展,计算机在管理方面应用的旁及,利用计算机来实现个人财务管理势在必行。本文首先介绍了个人财务管理系统的开发目的,其次对个人财务管理系统的需求分析做了详细的描述。接着,又对系统数据库设计和功能结构的划分做了详细论述。然后又对个人财务管理系统的实现做了详尽的说明。在报告的最后给出了项目的测试结果以及结果分析。
    本系统是对个人的收支情况做一个简单的管理,其中宝库哦个人信息管理以及收支信息管理。 其中,个人信息管理包括用户对自己的信息进行增删查改的一些操作,同样,收支信息管理包括用户对收支情况的信息进行增删查改的管理。
    1.1 系统业务需求该系统具体需求应该有用户登录模块,用户修改信息模块,用户修改信息模块,收支查询模块,收支删除模块,收支添加模块,收支修改模块。
    1.2 系统技术目标该系统的目标主要是能对个人信息以及收支信息进行较快的增删查改,同时也能对收支信息进行各种方式的查询。
    1.3 系统的具体需求根据以上对系统的任务和目标的分析,系统的具体需求如下:

    个人信息:用户名(唯一),密码,姓名,性别,出生日期,工作,身份证号,电话号码
    收支信息:收支编号(唯一),收支日期,收支方式,收支项目,收入金额,支出金额,,总金额

    二、软件功能结构分析由需求分析可知,软件的功能应包括:个人信息管理,收支信息管理。其中,个人信息应包括,个人信息的增删查该,登录时候验证功能。收支信息管理应包括对对收支信息的各种方式查询,以及对收支信息的增加,修改以及删除功能。当然,每个用户应对应其各自的收支信息。
    2.1 个人信息功能在登录界面用户输入用户名以及密码,如果用户与密码都输入正确则可以登录进系统,如果其中任何一项与数据库中的数据不匹配则要求重新输入。当用户没有账户时候,可以点击登录界面的注册按钮注册。成功进入系统后,可以进行个人信息的查询以及修改。
    具体流程图如下:

    2.2 收支管理功能用户登录成功后进入主界面后可以选择查询方式,全部查询:查询用户所有收入支出的信息;收入查询:查询用户收入信息;支出查询:查询用户支出信息;按日期查询:查询用户当天的收入支出信息。用户也可以对收入支出信息进行修改和删除以及添加。
    具体流程图如下:

    三、数据库设计经过以上的需求的分析以及系统功能的分析,需要建立出该系统数据库的各种模型,为建立一个好的,完善的数据库做准备。
    3.1 概念模型由于该系统涉及的较少,只涉及到用户以及财务管理,所以设计比较简单。一个用户可以有多条收支记录,所以用户表与收支表是一对多的关系。通过PowerDesigner工具设计出的概念数据模型如下:

    其对应的E-R模型如下图:

    3.2 逻辑模型联系转换
    一个用户可以有多条记录,而一条记录只能对应一个用户,所以用户与记录之间是一对多的关系。
    其逻辑结构设计如下

    个人信息(用户名,密码,姓名,性别,出生日期,工作,身份证号,电话号码)
    收支信息(收支编号,收支日期,收支方式,收支项目,收入金额,支出金额,总金额)

    关系模式

    个人信息(用户名,密码,姓名,性别,出生日期,工作,身份证号,电话号码)
    收支信息(收支编号,收支日期,收支方式,收支项目,收入金额,支出金额,总金额)

    3.3 物理模型通过PowerDesigner中的概念模型生成物理模型如下:

    3.4 表结构设计用户表

    收支信息表

    四、软件代码设计本系统是对个人财政的管理,下面给出具体的功能模块以及代码实现。
    4.1 功能模块登录界面模块

    说明:

    该界面为登录界面,如果没有账户,则可以点击注册按钮注册
    当用户输入的用户名或者密码输入错误时,会提示用户名或者密码输入错误
    当点击登录时,如果用户名以及密码都正确则会提示登录成功,并跳转到主界面

    用户注册模块

    说明:

    该界面为用户注册模块
    用户填入信息,其中用户名唯一,当用户名重复时会提示“用户名已存在,请重新输入”

    主界面模块

    说明:
    该界面为用户主信息界面

    用户可以有多种查询方式:全部查询(查询全部收支信息)、收入查询(只查询收入信息)、支出管理(只查询支出信息)、日期查询(查询当天收支信息)
    显示用户所有的收入总计、支出总计以及收入支出总计

    个人信息显示模块

    说明:

    该界面为用户显示模块
    用户如果不想使用该系统可以注销掉自己的账户

    个人信息修改模块
    说明:

    修改界面与个人信息查询界面在同一模块
    用户名不能修改

    收支信息插入模块
    说明:

    该界面为添加收支信息界面
    当点击主界面的插入按钮时候,会跳转到该界面
    收支编号不能重复


    收支信息修改界面

    说明:

    该界面为收支信息修改界面
    当点击主界面中的修改按钮时(必须选中一行),跳转到该界面
    收支编号不能修改

    收支信息删除界面
    说明:

    该功能与在主界面上
    选中一行,然后点击删除,即可提示删除成功

    4.2 代码实现登录界面主要功能实现(Login.java)
    jb1.addActionListener(new ActionListener() {//登陆按钮 public void actionPerformed(ActionEvent e) { jLabel5.setVisible(false); String ad = jf1.getText(); String pass = jf2.getText(); int i=0; String sc = "select userName,passWord from admin where userName='"+ad+"'"; try { ResultSet rs = st.executeQuery(sc); while (rs.next()) { i++; String userName = rs.getString("userName"); System.out.println(userName+"sdgdfgdf"); String password = rs.getString("passWord"); if (!ad.equals(userName)||userName.equals("")) { jLabel5.setVisible(true); } else if (!pass.equals(password)) { jLabel6.setVisible(true); } else { JOptionPane.showMessageDialog(null, "登陆成功!"); Show show = new Show(); show.s=jf1.getText(); show.setVisible(true); setVisible(false); } } System.out.println(i+"sdfd"); } catch (SQLException ex) { Logger.getLogger(Login.class.getName()).log(Level.SEVERE, null, ex); } if(i==0){ jLabel5.setVisible(true); } } });
    说明:该代码实现了登录界面的登录、判断用户名与密码输入是否正确。当用户名或者密码输入错误的时候会提示用户名或者密码错误。同时还添加了一个注册按钮让没有账户的用户注册账户。
    用户注册功能实现(UserInsert.java)
    jb1.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { try { String s1 = jf1.getText();//y用户名 String s2 = jf2.getText();//姓名 String s12 = jf7.getText();//密码 String s3 = (String) jcb.getSelectedItem();//性别 String s5 = jf4.getText();//职业 String s6 = jf5.getText();//身份证号码 String s7 = jf6.getText();//电话号码 String s8 = (String) jcb1.getSelectedItem(); String s9 = (String) jcb2.getSelectedItem(); String s10 = (String) jcb3.getSelectedItem(); String s11 = s8 + "-" + s9 + "-" + s10;//出生日期 ResultSet rs; String str ="select userName from admin where userName='"+s1+"'"; rs = st.executeQuery(str); int i=0; while (rs.next()) { i++; } if (i == 0) { if (s6.length() != 18 || s7.length() != 11) { if (s6.length() != 18) { jLabel5.setVisible(true); } if (s7.length() != 11) { jLabel14.setVisible(true); } } else { String sql = "insert into admin Values ('" + s1 + "','" + s12 + "','" + s2 + "','" + s3 + "','" + s11 + "','" + s7 + "','" + s5 + "','" + s6 + "')"; st.executeUpdate(sql); JOptionPane.showMessageDialog(null, "注册成功"); setVisible(false); } } else{ jLabel15.setVisible(true); } } catch (SQLException ex) { Logger.getLogger(UserInsert.class.getName()).log(Level.SEVERE, null, ex); } } });
    说明:该代码实现了个人信息的注册,其中用户名唯一,重复会给出提示“用户名已存在”,并且判断身份证与电话号码填写的格式是否正确。*
    全部查询实现函数(Show.java)
    jb1.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { ....... ....... } });
    收入查询实现函数(Show.java)
    jb2.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { ....... ....... } });
    支出查询实现函数(Show.java)
    jb3.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { ....... ....... } });
    日期查询实现函数(Show.java)
    jb4.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { ....... ....... } });
    个人信息查询功能模块(Show.java)
    jb9.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { ....... ....... } });
    个人信息修改功能模块(User.java)
    jb2.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { ....... ....... } });
    个人信息删除功能模块(User.java)
    Jb3.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { ....... ....... } });
    收支信息插入功能模块(UserInsert.java)
    jb1.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { ....... ....... } });
    收支信息添加功能模块(Insert.java)
    jb1.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { ....... ....... } });
    收支信息删除功能模块(show.java)
    Jb7.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { ....... ....... } });
    五、总结通过该课程设计,我认识到软件设计是基于需求分析和可行性分析的基础上的,软件设计阶段需要合理的分析需求分析中的细节部分的实现,既要考虑到关键处代码的可实现性,又要考虑到开发过程中遇到的问题。刚开始觉得该 项目建立的数据库比较简单,没有认真进行需求分析,所有导致后面举步维艰。后来重新进行需求分析,一步一步来,最终完成了该课程设计。软件设计是把需求分析中的问题抽象化,又要把抽象化了的需求形象的从预期的实现中体现出来。 本小组的个人财务管理系统系统的设计实现了预期的功能,对个人消费进行记录,个人的收入进行统计,对个人收支进行汇总并给出相应的理财提示信息。在这次的个人财务管理系统设计中将理论知识应用到实际中使得对理论知识的理解有了更进一步的理解,如果仅仅只是运用理论知识,是远远不够的。必须理论联系实际,才能很好的将各门课程学好,并用于实际案例中。
    这次设计使我的编程水平提高了一大步。由于这次设计涉及到数据库,我的学到了不少编程工具与数据库连接的知识,对数据库的操作有了进一步的了解。这次设计对我的综合能力是一次很好的锻炼,自己的能力和知识还很有限。所以今后我的学习道路还是很漫长的。
    12 评论 413 下载 2018-10-25 21:36:27 下载需要15点积分
  • 基于Python实现的新闻搜索引擎

    一、Scraper - 爬虫使用的库有:

    requests
    BeautifulSoup4

    爬虫分为两部分,网络通信部分(scraper.py)与适配器(adapers/*.py)部分。
    1.1 网络通信部分网络部分也分为两部分:

    第一部分是初始化部分,使用适配器提供的链接,下载数据后发给适配器(适配器用这些链接捕获哪些链接是下一步需要爬取的)
    第二部分是爬取新闻的部分,适配器在前一步里得到了大量的新闻链接,通信部分便用这些链接进行爬取。爬取之后,再将这些数据传入适配器,然后得到返回值(包含新闻的ID、标题、内容、日期、来源)

    全部爬完之后,将新闻数据以json格式存入到文件里,其中新闻的内容是html,不是纯文本(保留了原网站的一些排版、外链图片等信息)。
    这一部分是多线程(默认是10个线程)的,也就是说适配器必须要是线程安全的。
    1.2 适配器部分适配器部分为通信部分提供链接(url)、报文头(headers)、请求参数(params),需要实现7个函数:

    hasNextInit():判断是否有下一个初始链接,有的话返回True
    nextInitParam():返回下一个初始链接的信息,包括op和上述的url、headers、params,其中op是你想加入的额外的信息
    init(op, text):op表示上一个函数你所加入的额外的信息,text表示上一个函数请求的url所得到的html数据
    hasNext():判断是否有下一个新闻链接,有的话返回True
    nextParam():返回下一个新闻链接的信息,包括op和上述的url、headers、params,其中op是你想加入的额外的信息
    eval(op, text):op表示上一个函数你所加入的额外的信息,text表示上一个函数请求的url所得到的html数据
    ‘encoding()’:返回所爬取网页用的编码格式(用于网络部分解析html数据)

    请一定注意,这些函数都必须要线程安全。
    二、Web - 网页2.1 前端
    使用Boostrap 3写的UI
    使用JavaScript(大部分是jQuery)进行各种UI更新操作,比如分页、高亮、使用ajax获取各种服务器上的数据,动态更新网页等
    包含三种页面:主页(/)、搜索页(/s??wd=中国&bg=2001-01-25&ed=2018-01-25)、新闻详细页(/post?id=people_1)

    2.2 后端我使用的数据库是Django默认自带的SQLite,因此我只需要实现几个models就能实现数据的读写了。我一共写了4个models(位于/web/postdb/models.py):

    WebInfo:存储每个适配器(adapter)的数据信息

    name:适配器的名字(比如people、xinhua)count:该适配器目前有多少数据从爬虫部分的json文件里导入进了数据库(用于下一次从该json文件里更新数据)
    PostInfo:存储每篇新闻的数据信息

    NID(Number ID):每篇新闻的纯数字ID(从1开始),用于减少网络通信时数据传输的大小TID(Text ID):每篇新闻的文本ID,是适配器名字_number这样命名,比如people_1,用于在/post?id=people_1里展示(而不是以纯数字的方式,因为这样难以区分)time:新闻发表的时间,用datetime类型存储category:新闻的分类(中文),比如“社会”、“时政”、“军事”等title:新闻的标题content:新闻的内容(html)plain:新闻的内容(纯文本)url:新闻是从哪里爬取的?就是从该url爬取的sourceLink:新闻的来源链接(每篇新闻都有个来源,不一定就是url)sourceText:新闻的来源文本(比如“新华网”、“人民网”)
    IndexInfo:存储每个词语对应的新闻(倒排列表索引),同时存储新闻的一些信息

    key:词语value:该词语所对应的倒排列表(list),这个列表的每一个元素的格式为[在该新闻里的出现次数, 该新闻的NID,该新闻的发表时间], 比如[1234, '3', datetime(2018, 1, 2)]。该列表会转化成json格式的字符串存储在value内
    PostRelation:存储每篇新闻相关联的几篇新闻(默认是3篇),将其作为该新闻的推荐新闻

    NID:新闻的NIDrelation:相关联新闻的列表(list),这个列表的每一个元素的格式为{'title': 关联新闻的标题, 'TID': 关联新闻的ITD}。该列表会转化成json格式的字符串存储在relation内

    2.3 新闻搜索算法先介绍IndexInfo数据库的建立。
    将每篇新闻的纯文本进行分词(使用thulac),同时统计每个词出现的次数。然后根据格式存入IndexInfo里的value。
    对于每一个搜索的字符串,我们将这个字符串也分词。对于每个词语,我们从IndexInfo里取出倒排列表,将每个新闻的出现次数累加。最后根据每条新闻的累加次数,从大到小排个序,然后返回这些新闻的NID。
    2.4 推荐新闻算法用一个最简单的办法:将这篇新闻的标题拿去新闻搜索算法里进行搜索,然后取出前几条新闻即可。这是因为,新闻的标题有高度的概括性(而且是人为的),在一定程度上可以代表整篇文章。
    我们用该办法预处理一下每篇新闻,然后存入PostRelation数据库里即可。
    三、界面首页

    搜索新闻

    推荐展示

    四、使用说明4.1 本机环境
    Python 3.7.0
    Django 2.1.1
    requests 2.19.1
    BeautifulSoup4 4.6.3
    thulac

    4.2 使用首先使用scraper文件夹下的爬虫scraper.py对“人民网”、“新华网”的新闻进行爬取:
    python scraper.py之后会将爬取的数据存储到people.json和xinhua.json中,然后在web文件夹下,运行:
    python manage.py makemigrationspython manage.py migrate初始化数据库,然后再执行:
    python manage.py updateDB将爬取的数据导入到数据库中(这可能会等很长时间),之后再执行:
    python manage.py updateRelation更新文章推荐的数据库,最后:
    python manage.py runserver启动服务器即可,你就可以通过127.0.0.1:8000进行访问网站了。
    目前的效率是,17000篇新闻的话,在i5-7200U的机子上查询新闻只要0.1s左右。(反正Django自带的sqlite有多快我这个就有多快)
    1 评论 8 下载 2021-02-09 10:39:27 下载需要11点积分
  • 基于QT实现的可视化链表(单链表、循环链表、双向链表)

    1.1 题目题号1:分别以单链表、循环链表、双向链表为例,实现线性表的建立、插入、删除、查找等基本操作。
    要求:能够把建立、插入、删除等基本操作的过程随时显示输出来。
    1.2 软件功能功能分为三个板块,分别是单链表、循环链表、双向链表的建立、插入、删除等基本操作的过程。
    单链表

    查看单链表定义,相应算法代码
    建立一个带头结点的空单链表
    指定插入位置及元素值到单链表中
    随机插入5个元素到单链表的尾部
    指定删除元素位置(从1开始),从单链表中删除
    输入查找值,得到元素在单链表中位置
    清空销毁单链表
    能够调整演示的速度快慢

    循环链表

    查看循环链表定义,相应算法代码
    建立一个带头结点的空循环链表
    指定插入位置及元素值到循环链表中
    随机插入5个元素到循环链表的尾部
    指定删除元素位置(从1开始),从循环链表中删除
    输入查找值,得到元素在循环链表中位置
    清空销毁循环链表
    能够调整演示的速度快慢

    双向链表

    查看双向链表定义,相应算法代码
    建立一个带头结点的空双向链表
    指定插入位置及元素值到双向链表中
    随机插入5个元素到双向链表的尾部
    指定删除元素位置(从1开始),从双向链表中删除
    输入查找值,得到元素在双向链表中位置
    清空销毁双向链表
    能够调整演示的速度快慢

    上述所有功能采用面向对象的方法通过C++语言程序结合QT框架实现,后面会详细介绍。
    1.3 设计思想
    学习相应知识,做好必要的准备工作由于以前都是采用控制台进行编程,即便涉及一些简单的图像界面,但是比较粗制简陋,无法入眼,并不是标准规范、人性化的用户交互界面,所以要完成本次的数据结构课程设计必须从零起步,学习可视化编程开发。在C++的一系列可视化开发框架下,我选择用Qt来实现程序的功能,因为Qt相对较为简单,容易上手入门,同时Qt是较为新兴的技术框架,并且跨平台开发,很有前景和实用性。通过几天的学习,理解掌握的Qt的必要知识,包括最为核心的信号和槽函数机制、UI控件的使用、Scene-View视图框架等核心技术。
    自顶向下设计有了必要的准备知识,就可以进行程序的总体规划设计了。自顶向下分析是常用的分析方法,本次题目其实较为简单,常用的链表结构我们在学习数据结构课程时已经非常熟练,此次实现图形化界面的演示需要结合原有结构,融入图形化元素和用户界面接口,对程序的功能分析,显然程序的功能分为三个子功能模块,分别对每个模块进行设计即可完成整个任务。
    分模块实现虽然程序有三个部分组成,但是每个部分的功能需要完全一样,用户界面完全一样,划分为三个模块,只要实现一个模块,其余两个模块只要非常短的时间就可完成。实际开发时,先实现单链表模块,完成以后,循环链表和双向链表只需要在前面基础上稍作修改即可。
    自底向上实现具体实现时,先定义每个类的属性和相应函数,然后根据定义,设计相应算法自底向上进行实现,逐个击破,最终完成所有程序的设计。

    1.4 逻辑结构与物理结构1.4.1 单链表节点定义

    单链表

    1.4.2 循环链表节点定义

    循环链表

    1.4.3 双向(循环)链表节点定义

    双向循环链表

    1.5 开发平台1.5.1 开发平台
    计算机型号:惠普Pavilion M4
    计算机内存:4.00GB
    CPU:Intel Core i5 2.6GHz
    操作系统:Windows 10 家庭版
    开发语言:C++(C++11标准以上)
    开发框架:QT
    集成开发环境:Qt Version 5.9.1
    编译器:MinGW 32bit

    1.5.2 运行环境
    可在上述集成环境下运行
    通过windeployqt.exe及Enigma Virtual Box进行整合压缩为发布为了一个 LinkListVisualizer.exe 文件,可在普通 Windows 机型下运行

    1.6 系统的运行结果分析说明1.6.1 调试及开发过程1.6.1.1 调试本次开发采用的是新技术框架Qt,同时也是跨平台的,在Qt Creator中开发调试,Qt中包含了大量的库类,类似于java开发简便,Qt有较好的调试器,但是在本次开发中没有用到,偶尔遇到一些小麻烦或者小bug,我们只需在控制台中输出一些数据便可分析定位错误原因。
    例如:

    输出:

    1.6.1.2 开发本题目虽然有三个小题,但是三个子题目大同小异,架构类似,所以采用分模块逐步开发方式。先确定主窗口,控制好整体界面和架构,然后完成最简单的单链表设计和开发,单链表完成以后整个题目大部分工作已经完成,剩下循环链表和双向链表只需要简单修改就可完成。
    1.6.2 成果分析1.6.2.1 正确性经过多次不同角度的验证,程序表现的十分优秀,与预期没有任何差错。
    单链表运行样例图



    循环链表运行样例图




    双向(循环)链表运行样例图



    1.6.2.2 稳定性图形的大小均采用了宏定义,可根据需要随时调整。

    可通过下拉框和左右拉框看到调整大小和未显示的区域。

    在不同速度调节下,不同速度均表现的十分稳定。

    三个小部件均能同时稳定正确运行。

    1.6.2.3 容错能力本程序有非常好的容错能力,如下:
    按钮只有在能够进行操作的情况下,才会处于有效状态,例如,初始时,只能“创建”,不能“插入”、“删除”等操作;

    在没有节点时,不能“删除”;

    输入利用控件保证输入的正确性;插入删除位置通过选择保证正确;

    输入的合理性通过输入控件保证,当要求输入数字时,输入其它非法字符将不会处理,输入范围在[-999999999, 999999999],其它范围是无法输入的。
    1.7 操作说明本题目分为了三个部分,分别是单链表、循环链表、双向链表的基本操作演示。通过前面介绍的运行环境下进行程序的运行。
    1.7.1 主界面操作1.7.1.1 主界面按下相应按钮进入相应功能。

    将鼠标悬停在相应按钮上可得到相应提示。



    1.7.2 单链表1.7.2.1 进入功能区点击主菜单的“单链表”进入,可以看到初始界面:
    按钮或输入控件较亮表示可以点击或输入,否则处于不可编辑状态。

    1.7.2.2 调节演示速度右下角有操作后的状态提示及过程显示的速度快慢调节器,状态提示不可编辑,速度调节器可以通过鼠标直接“点击”或者点击后按“左右方向键”进行速度调节,最右段为最快速度。

    1.7.2.3 创建单链表点击创建按钮可以创建一个单链表,或者在已经创建一个单链表后销毁并重新创建新的单链表。

    1.7.2.4 插入节点插入节点有两种方式,可以手动插入,也可自动插入。
    手动插入节点方式:

    点击插入位置下拉框,选择插入位置(从1开始)在插入文本框中输入插入值点击插入

    点击“尾端随机5个”按钮,即可自动插入五个随机值到链表尾部去。

    1.7.2.5 删除节点点击删除位置下拉框,可选择相应的删除节点位置,然后点击删除按钮。

    删除后

    1.7.2.5 查找节点在查找值中输入要查找的值,点击“查找”按钮。

    查找结果:

    1.7.2.6 销毁链表点击清空按钮,清空单链表,释放资源。

    1.7.3 循环链表循环链表的操作与单链表完全一样,不再赘述。
    1.7.4 双向(循环)链表双向循环链表的操作与单链表完全一样,不再赘述。
    6 评论 127 下载 2018-11-04 17:36:08 下载需要13点积分
  • 基于JSP和SQL server的塞北村镇旅游网站设计与实现

    摘 要城市旅游产业的日新月异影响着村镇旅游产业的发展变化。网络、电子科技的迅猛前进同样牵动着旅游产业的快速成长。随着人们消费理念的不断发展变化,越来越多的人开始注意精神文明的追求,而不仅仅只是在意物质消费的提高。塞北村镇旅游网站的设计就是帮助村镇发展旅游产业,达到宣传效果,带动一方经济发展。而在线消费与查询正在以高效,方便,时尚等的特点成为广大互联网用户的首选。塞北村镇旅游网站设计与开发以方便、快捷、费用低的优点正慢慢地进入人们的生活。人们从传统的旅游方式转变为在线预览,减轻了劳动者的工作量。使得旅游从业人员有更多时间来获取、了解、掌握信息。
    塞北村镇旅游网站根据当地旅游风景和特色的实际情况,设计出一套适合当地旅游信息网站,通过网络,实现该网站的推广从而达到宣传的效果。
    本系统在设计方面采用JSP和Java语言以及html脚本语言,同时采用B/S模式,进行各个界面和每个功能的设计与实现,后台管理与设计选用了SQL Server 2005数据库,前台设计与后台管理相结合,共同完成各功能模块的功能。
    关键词:SQL2005 ;塞北村镇旅游;JSP ;B/S
    AbstractThe rapid development of the urban tourism industry has led to the rapid development of the tourism industry in the village. The rapid advance of the Internet and electronic technology has also led to the rapid development of the tourism industry. With the improvement of people’s living standards, more and more people are paying attention to the pursuit of spiritual civilization, and the consumption idea is constantly changing. The design of the tourism site in the town of saibei is to help the village development tourism industry, to achieve the publicity effect, to drive one side economic development. And the online consumption and the query is in the high efficiency, convenience, fashion and so on the characteristic become the first choice of the Internet user. The design and development of the tourism website in the town of saibei are slowly entering people’s lives with the advantages of convenience, speed and cost. People have switched from traditional travel to online previews, reducing the workload of workers. The travel industry has more time for information, information and information.
    Camels rural tourism website according to the actual situation of local tourism landscape and characteristic, design a set of suitable for the local tourist information web site, through the network, realize the website promotion so as to achieve the effect of propaganda.
    This system using JSP and Java language in terms of design and HTML scripting language, using B/S mode at the same time, for each interface and the design and implementation of each function, background management and design chose the SQL Server 2005 database, the front desk design combined with background management, complete the function of each function module.
    Keywords: SQL2005; JSP; B/S in villages and towns;
    1 概述1.1 项目研究背景社会经济的发展和提高潜移默化的影响了人们对精神消费的日益看中与提高,所以越来越多的人们开始选择更健康有趣的生活活动,随之而来的旅游便成了人们消费的必选。随着旅客需求的日趋丰富和个性化,这势必将推动我国第三产业、旅游服务行业的迅猛发展前进。旅游行业如何能够提供多样化、个性化的服务来满足人们的多方面需求,这是一个值得深究的课题。旅游行业快速成长的同时,各个行业相互间的联系与竞争也就不断加强。互联网时代的大背景环境下,电子信息服务的将会是一个最便捷最省力最有效的服务方式。这就要求旅游行业能够提供一个综合性服务的信息平台,同时必须拥有强大的后台支撑、智能化的信息提供和服务,快速有效的信息应答,多种多样的信息功能等等。虽然目前我国电子信息科技迅猛发展,但是也有差强人意的地方,比如说,

    交互性差:多数信息系统是封闭性的,缺乏与各种其他信息系统的共享与交互,这就造成了信息资源的浪费和利用率低等问题
    实时性差:系统在开发时存在系统漏洞,不能很好的对空间信息进行全方位的挖崛与利用。用户所需要的信息可能不能及时得到跟新与回复。这是摆在多数旅游系统面前的一个现实需求
    个性化服务缺乏:大多数旅游系统还不完善,没有按实际情况来满足用户多方面的需求,而是片面的加入一些没有必要的或者说运用率并不高的功能
    旅游系统的单一化:不难看出,大多数旅游系统功能服务基本相同,没有自己的特色,创新程度不强。电子科技迅速发展,也需要我们不断的去追求创新

    1.2 研究目的及意义随着旅游业的迅猛发展,21世纪的中国将会成为世界上最大的旅游国家,对于旅游者而言获取相关的旅游信息以便于做出最优的旅游选择是十分必要的。塞北村镇旅游网站中以帮助客户怎么样才能更快速方便的找自己旅游公司咨询和旅游信息。因此开发塞北村镇旅游网站可以发布塞北村镇旅游信息,让客户自己在网上就可以方便快捷的了解到旅行社的所有旅行动态,大大方便了旅行者对旅游信息的查询和获取,旅行者也更愿意在电子信息平台下进行咨询和消费。
    1.3 开发软件介绍1.3.1 技术介绍JSP是一种能实现动态网页的技术。Sun公司最先提倡发行,并由多家公司共同开发与完善的。JSP技术通俗来说其实就是在普通的网页HTML文件中首先加上Java程序段来实现具体功能,然后再根据需要添加JSP标记(tag)进行记录,这样二者结合就可以形成JSP文件。其功能特别强大,基本可以实现大多数动态网页所需要的各种效果。用JSP技术所开发的网页具有跨平台的特点,在不同的操作系统,例如Windows,Linux,Winxp等操作系统上都可以运行起来。在服务器端进行大部分复杂的程序操作和功能实现操作,而这些并不需要用户直接参与或操作,最后的结果通过网络传送给用户。这样就减轻了用户工作量的同时也减少了浏览器的负担。因为有些浏览器并不支持Java语言,然而这不影响功能操作的实现,同样能够登录JSP网页,达到预想效果。
    Java server page(以下简称JSP)为servlet技术的简化。JSP的功用在于它实现了Html语法中以<%, %>形式的java扩张。但是,值得注意的是,因为JSP与Servlet均在服务器端运行,故而往往以HTML文本为主要形式呈现客户端面前,所以当有 需求时,客户端可以便捷地通过浏览器来实现浏览。当网页服务器(web)遇到访问JSP提出的要求时,需要进行以下两个步骤:首先执行程序段,后将结果与htlm返回,以便系统更好运行。至于为何要进行的Java代码段的插入操作,其主要目的在于进行数据库的连接、网页重定向等等,以满足网页动态实现所需的各类功能。
    同时,我们也应该认识到JSP技术所使用的俩种程序:即类XML的tags和scriptlets,这些都是用Java语言实现的。另一方面,对于服务端也可以通过tags和scriptlets实现对资源的访问。除此之外,JSP将网页逻辑和网页设计分离开来,大大方便了编程人员实现对应用程序的设计与开发。同时,由于JSP的发展运用,使得网页设计变得更加灵活便捷,也使得网页的实现更加容易。
    Html语言是一种脚本语言,是一种规范和标准,在所有的开发语言中,是较为简单易学的一种,它有很多标签,运用标签就可以实现很多静态页面效果。虽然html语言相对其他语言来说比较简单,但是他能够实现的功能却很强大,因此受到广大用户的热爱。他可以实现静态网页设计,是学习前端设计的一门基础性语言。Html的结构包括头和主体部分,是WWW的描述语言。
    Java语言是一种完全面向对象的语言。具有继承,多态性,封装性等特点,还具有垃圾自动回收机构,程序员不用考虑内存使用不足的情况,因为内存在程序员不再使用后的一段时间内会自动释放。而且具有跨平台性。这些别的语言所没有的特点让java能够快速发展强大起来,它吸收了计算机领域的各种最新成果,功能十分强大。Java的应用也是到处可见,从计算机到移动平台,从办公软件到手机应用,从小型系统到大型企业,Java身影无处不在。Java能得到如此广泛的应用的另一个重要原因是因为java语言是动态的,它可以适应动态变化环境。
    Myeclipse其实是在经过一系列已有软件产品的补充和更新的基础上产生出来的,是一款功能丰富的企业级开发环境。在多种程序开发、服务器效能的提高、功能实现等各个方面起到了不可估量的用处,很大程度上增强了开发效率。总之,Myeclipse和eclipse有着千丝万缕的关系,它其实就相当于一个功能插件,并且它具有丰富的开发环境,使用范围广泛,能够实现多种功能,支撑目前流行的几乎所有开源工具。像JavaServlet,JSP,JSF,Spring,AJAX等等。而在结构上,Myeclipse的特征有WEB开发工具,应用程序服务器的连接器等等7大类(在此只举出2类)。这种结构布局使得模块间各自独立,各个模块各自运行,他们之间互不影响,单独完成各自的升级或者扩展。MyEclipse 是基于Eclipse插件的解决方案,功能强大并且支持十分广泛,支持云开发、java web开发、移动开发、优化开发、RESTful Web服务开发、保持Maven、架构、企业交付、测试等等,此外,Myeclipse版本更新迅速,不断完善已有功能,弥补漏洞,方便开发。MyEclipse具有完备的编码、调试、测试和发布功能,是一款功能丰富的JavaEE集成开发环境。
    MyEclipse这一开发工具,每个版本都有其各自的特点,本文使用的MyEclise8.5。8.5版本经过长期的投入使用,较以前旧的版本修正了许多bug,性能比较稳定,界面比较美观,用起来也方便,操作较为简单。但是就兼容性来说,Myeclipse6.5相对比较好。而8.5版本容量大,用起来可能会存在卡的情况。但是除此之外,8.5也有很多优点,比如说它用起来十分灵活,对前台开发的支持性比较好。其实,每个版本都有自己的特点,具体选用哪一版本,还需要根据实际情况,结合所开发项目进行选择。
    另外,MyEclipse还有很好的自动查错功能、自动补全功能。程序员在进行项目开发的时候,可以方便准确的找出出错的地方。此外,自动补全功能也可以大大节省程序员的编程时间,极大的提高了工作效率。总之,在进行软件系统开发时,一个得心应手的开发环境是十分必要的,这一点是会影响到开发的效率。Myeclipse很好的解决了这样的难题,为软件开发提供了便利条件。
    Tomcat服务器是一个免费的应用服务器,他的封面设计以一个动物的素描为灵感,正是因为这个设计理念,所以该项目以一个英文的动物名字为项目名称。因为其免费又好用,功能强大,所以成为大多数程序员的首选。Tomcat是一个小型的,轻量级的软件产品,他在启动运行时占用非常少的内存资源和系统开销,扩展性能比较好,支持多种应用需求,如果一个开发员对某一项功能实现特别感兴趣,他就直接可以将此功能加入到其中。Tomcat可以独立运行,身为网站的服务器,可以加载动态网页。
    1.3.2 SQL2005数据库SQL 数据库设计简单易懂,功能相对来说比较全面,为软件产品的开发应用提供了良好的环境和数据帮助。关系型数据和结构化数据为数据库提供了新的功能,使得信息能够更好的存储和组织,完善了SQL数据库,这样一来,程序员可以运用这一优势,在软件产品开发过程中,能够为用户开发出高质量高性能的数据应用软件。此外,Microsoft SQL Server 2005 还整合了各种功能:例如分析、集成等。用户凭借此完成了对方案的构建。SQL2005数据库为实现系统后台与前台连接起到了十分重要的地位。一个没有连接数据库的系统是无法实现任何有价值的功能的。数据库可以帮助开发人员整合管理数据,有效实现系统所需功能,同时还可以进行权限的设置和数据的添加。总之,SQL可以满足人们基本的几乎所有要求,为其提供一套经济,有效的开发策略,使得用户付出最少的代价获得最多的回报。
    2 系统分析2.1 可行性研究2.1.1 经济上的可行性实现塞北村镇旅游网站所需要花费的时间,人力,金钱成本较该网站投入使用时能够获得的收益来讲,差距是比较大的。所以,从经济方面讨论时,开发该网站显然是比较合理的。这样可以对当地村镇旅游信息进行有效的整合和集中,及时的发布与更新,可以使旅客及时获得各种景点、住宿、攻略等信息,方便得使消费者获得想要的信息,同时使企业盈利。这样可以为当地经济带来更好的工作效益和社会效益,开发出本网站可以减少旅游人力成本,而且管理便捷,各功能实现迅速,以对数据实施有效的管理。管理上的有效便捷,信息得以及时获取,选择上的方便等所能达到的利益是不可估量的,这样帮助村镇实现信息化的同时帮助他们宣传家乡文化、提高收入。所以,从经济这个角度来说,可以进行该网站的建设。
    2.1.2 技术上的可行性技术是否成熟关乎该网站能否可以顺利进行,是不可忽视的一个重要方面。技术可行性的研究是指的目前而言已知的的各项技术中哪些可以高质量的完成对该软件系统的开发。同时要兼顾已有的软硬件配置的要求。就本系统而言,需要软硬件配置较高的PC机,Windows操作系统,另外,需要安装SQL2005数据库服务器,JDK, Myeclipse,tomcat,任意浏览器,配置好基本的所需环境以后,采用合java,JSP语言进行旅游网站的设计、开发与运行。从技术上来说,这些基本的软件系统开发所需技术是不成问题的。
    2.1.3 操作上的可行性首先,进行网站设计的几种软件都具有较高的普及性和较高的可操作性,设计人员可以较为轻松地使用软件对塞北村镇旅游网站进行设计和完善。第二,管理员可对客户进行验证,对信息平台的信息进行发布,修改,管理,还可以实现酒店预订,修改,删除等各种功能。第三,客户可以在提示下进行一系列的留言,预订,查看等各项功能。而这些功能都是比较简单可行的,这些功能也比较普遍化,一般人员胜任是没有问题的。这样说来,从操作上来说是可行的。
    结合以上分析与介绍,从经济、技术、操作等方面来说,现有的有效环境和条件、技术是可以开发出一个具有较高可操作性和功能强大的个性化旅游网站,实现各项功能,完成测试。
    2.2 开发结构分析B/S模式即浏览器/服务器模式体系结构,这对较为小型的系统来说更加适用。他最大的优势在于不需要客户端的维护,适用于客户端需求较为多变的系统。这对客户来说,该模式界面友好,具有实用性。所以塞北村镇旅游网站采用通用性好,成本低,开发相对简单的B/S模式体系结构。管理方便也是该系统的又一个优势,此外,针对用户来讲,该网站用户数量大,变化性和流动性也强。经过上述分析探讨,最终认为B/S模式是该网站的最好选择。如图2-1B/S模式图所示:

    B/S三层模式结构所具有的特征包括:

    开放的标准:B/S体系标准由国际组织统一规定,这样就使得该体系具有很强的通用性,同时也使得该系统就有很强的跨平台性。它的使用方便了广大用户和相关企业,在不同的系统不同的平台上都可以运行,不受限制
    较低的开发和维护成本:B/S体系结构优点在于不用对客户端进行专门的维护,用户只需要有一个浏览器即可。这样就大大减少了开发维护成本,需要做的仅仅对系统和服务器进行升级,从而便大幅度地降低了维护开发所消耗的资金
    用户使用简单,界面友好:B/S体系结构对于用户来说只是一个简单的浏览器。用户对面的不是一堆复杂的数据和冗杂的代码操作,而是快捷方便的点击交互式的显示操作。这样就减少了客户端开发成本,用户不必在意内在实现过程,只需要了解自己需求而进行相应的图文式操作

    根据以上所分析不难看出,B/S是该网站系统最合适的体系结构。它开发成本小,简单便捷,容易实现的特点是我们的不二选择。所以,该网站系统基于B/S体系结构实现了旅游信息发布,线路管理,景点管理等功能。
    2.3 功能需求分析需求分析在软件开发周期中起着十分重要的作用也可以说起着决定性作用,它是每一个软件产品在设计与实现之前必须进行的。当然了,该项工作如此重要,一定也有它的难度。在进行需求时,了解用户的需求是最关键的。旅游网站面向广大网络在线用户,它的特点就在于电子科技的广泛应用。根据该特点,我们可以通过网上网上调查,问卷调查,走访等方式了解网站需求。如何满足广大用户需要,尽可能多的细化网站功能就是摆在眼前的一个问题。同样的,不光用户需求需要注意,了解管理者的需求也同样很重要,一般来说,网站后台的主要对象主要是系统管理者,为了满足管理者的需求,开发出合适产品,在实现网站之前,需要提前与管理者进行沟通,需要系统实现什么功能,整合统计什么数据,完成哪些便捷操作。最后,还应该使网站具有较好的系统伸缩性和容错性。因为不管是用户还是系统管理者,他们的需求会根据实际情况,时间推移发生不断的变换,所以,系统应该尽可能提高容错性和可维护性,避免后期修改消耗人力物力。下面对该网站需求功能进行研究探讨:
    塞北村镇旅游网站的功能比较全面丰富,尽量满足大部分旅游客户的要求,在网站的首页显示了该网站的具体实现模块部分。包含塞北人文、塞北故事、酒店信息 、旅游景点、 自驾游线路 、旅游地图查询、天气预报 、在线评价 、用户注册、 后台管理等功能:后台管理包括:塞北人文、塞北故事、酒店信息、旅游景点、自驾游线路、酒店预订,在线留言、用户增加删除修改、系统等的管理。
    上边所述的功能是基本的旅游网站所需功能,它涵盖了一般客户的需求,也是此系统的主体功能。此外,在开发过程中还要不断的完善和修改,增加一些个性化和细节功能,使得系统具有很好的完整性和可操作性。
    2.4 数据流图进行业务流程分析也是一个重要环节。他的分析应该参照信息流动的整个过程,对每一个环节进行业务处理、数据流图的调查分析。数据流图可以清除的表明计算机软件系统的工作情况,他是一种图形表示。这样,可以简化工作难度,便于开发人员准确表达交流。同时便于开发端,维护端,测试端,应用端的相互交流合作。也就是说,数据流图不仅适合专业人员读取了解方便,也同样适用于非专业人员。在需求分析中是一种便于修改和交流的表达工具。
    总体流程图

    数据流程分析

    2.5 业务流程分析业务流程分析在需求分析中的占有十分重要的分量。业务流程分析其实就是对产品业务处理过程的详细细节进行反应,也就是信息的流动过程的具体描述。业务流程分析需要根据具体业务画出流程中的具体活动,还有各个活动相互间的联系与逻辑,流程的输入输出以及流程的执行者等等。流程分析方法有顺向法、查询法、具体分析法、逻辑推理法。
    业务流程分析可以帮助系统开发人员理清工作流程顺序,同时更好的分析业务相互间联系的因素关系。了解网站具体要求和业务需要,从而形成科学的、合理的工作管理和运作方式。而具体流程图的实现过程还具有相应的规范和标准,一般具有所规定的特定的一些符号、方框、箭头和线段来表示。具体如图2-4业务流程分析图所示:

    2.6 数据字典对数据流程中的各个元素进行详细的说明是数据字典的主要目的和用途。它在系统开发阶段有着重要作用。数据字典中包括数据类型、字段、属性等等。有了数据字典,数据库在设计的时候也可以根据数据字典中的各元素成分进行数据的相关定义。下面根据具体的实例进一步说明数据字典中元素的的条目,如表2-1数据元条目、表2-2数据结构条目、表2-3数据流条目、表2-4 数据存储条目、表2-5 处理过程条目和表2-6 外部实体条目所示:
    数据元素条目

    数据结构条目

    数据流条目

    数据存储条目

    处理过程条目

    外部实体条目

    以上简单列举了一部分数据字典条目。根据上述数据条目的具体分析,不难得出看出,数据结构中可以包含多个数据项以及数据结构。数据字典就是将数据中的各个成分加以组织说明,减轻系统开发人工作量,达到最好的工作效率。
    3 网站总体设计3.1 系统功能描述塞北村镇旅游网站的功能主要分为俩部分:前台界面管理和后台数据库管理。它的主要功能包括:对塞北人文的增加删除修改查看 ,对塞北故事的增加删除修改查看,对酒店信息进行增加删除修改预订,对旅游景点的信息进行增加删除修改查看,还有路线查询,天气预报、用户评价、管理员后台登录管理。这些具体的板块涵盖了网站的设计的总体布局。
    首页塞北人文板块、塞北故事板块、酒店信息板块、旅游景点板块、自驾游线路板块、用户评论板块、在线留言板块、天气预报板块都有自己具体实现的操作,供客户进行选择和查看、管理。
    3.2 系统界面设计一个美观、清晰、操作便捷的界面可以增加用户量,吸引更多的人进行访问。通过对界面的访问,用户可以在最短时间内了解该网站的功能、属性、特点等等,同样也可以满足自己的需求。所以,在进行界面设计的时候一定要多花时间使得界面具有吸引力并且以最少的语言和图形传达最多的信息。该网站在设计界面的时候是根据以下几个方面进行的:

    图文搭配:在进行界面设计的时候,太多的文字会使得用户觉得晦涩难懂,不愿意多花时间去进行研究。所以很有必要用图片进行展示,再加以必要的简洁的文字说明,这样用户会节省大量的时间去浏览更多网页并且可以获得自己想要的信息。塞北旅游网站界面设计采用文字加图片的形式,文字可以直观的向用户传递具体模块构造与功能,而图片可以更加形象的让用户感受到旅游地方的具体实景
    界面设计应当美观大方:太多的文字会使人们感觉到无聊不愿意阅读,然而太多的图片、动画也同样会使得界面太过花哨,凡事应该讲究适度原则。所以,在进行界面设计的时候切记要做到美观大方。塞北村镇旅游网站在设计的时候秉承这个原则,整个界面大方又不失美感。既不是一味的进行文字说明,也不是夸张的色泽艳丽
    字体选用应该注意突出重点:文字说明的时候也有讲究,对于重点的内容,就应该加以特别说明,字体应该适当加粗或者换种颜色
    色彩搭配应该柔和:在进行界面美化设计方面,色彩搭配也是一个很重要的环节。界面应该具有自己的主色调,而这个主色调最好采用暖色,这样可以给人一种柔和亲切的感觉。另外,界面颜色不宜太多。与网站所宣传的内容相符合、有自己的特色就好

    3.3 系统功能结构图塞北村镇旅游网站是基于B/S体系结构的旅游网站。通过全方位综合分析,该系统功能设计相对比较全面,能够满足大部分用户的需求。但是,做到满足每一个客户要求也是不可能的,只能是争取尽可能完善网站功能,到达更好的效果。塞北村镇旅游网站主要是通过各功能模块的介绍,对塞北村镇旅游进行宣传,包括首页,塞北人文,塞北故事等部分。具体前后台各部分实现如图3-1网站前台结构、图3-2网站后台结构所示:
    网站前台/后台结构图

    3.4 系统设计目标用户特点、系统属性特点和实际需求是系统目标重要的考虑因素,该网络管理系统应该尽量满足操作灵活,界面友好,使用方便等设计要求。本网站应实现下面提到的几个任务目标:

    人机交互:用户可以方便快速的获取所需要的信息,同时系统必须可以给予客户及时的应答。界面设计灵活友好,数据存取安全
    对塞北村镇旅游网站的质量进行评估,达到预期效果,各功能完善
    实现以上所述各部分模块的功能操作
    设置数据检查,尽量避免数据的冗杂和出错

    3.5 系统实现的软硬件平台
    硬件系统:硬件平台实际上就是支撑系统进行开发运行的物理设备,具有计算,输入输出、存储等功能,即计算机或PC机。本网站由Windows操作系统作为硬件支撑平台得以实现
    软件服务:Myeclipse、tomcat、SQL

    4 数据库设计4.1 数据库概念结构设计数据库是每一个系统所必需具备的。数据库的主要用途是实现对各种资源数据的存储,提供给该网站多种服务。通俗来讲,数据库其实就是一组具有相互关联的信息资源的有序集合,这些信息以一定的方式存放在一起,供系统使用。而对于程序来说,其与数据库又保持高度的独立性。
    用户信息实体属性图

    景点实体属性图

    评价实体属性图

    站内信息实体属性图

    留言板实体属性

    数据库E-R图

    4.2 数据库逻辑结构设计数据库其实可以理解为一个仓库,而这个仓库不像一般的仓库存放物体,这个仓库是用来存储数据信息的。而这些数据并不是杂乱无章的进行存储,它们是按照一定的结构、组织方式、方法规定将这些数据以最少的冗余度最好的方式存储在一起的数据的集合。数据库的逻辑结构就是根据E-R图转换而来的模型结构。数据库可以帮助系统整合数据信息,可以将数据库比作人的大脑系统,它帮助系统获取、记忆、识别信息。一个没有数据库的系统是无法完成特定功能要求的,更不能进行后台连接应用。塞北村镇旅游网站对数据库的逻辑结构进行个性化设计,保证数据存储的合理有效性。帮助网站进行客户数据信息的记录,整理从而使得该网站具有实践意义。
    allusers是权限为管理员的信息表,记录数据库中所设定的信息。

    jingdianxinxi是景点的信息表,记录数据库中所设定的景点信息。

    liuyanban是用户所留言的信息表,记录数据库中所记录的留言板信息。

    xinwentongzhi是新闻通知的信息表,记录数据库中所设定的新闻信息。

    kefang是客房的信息表,记录数据库中所设定的酒店信息。

    yonghuzhuce是注册用户的信息表,记录数据库中所记录的用户信息。

    4.3 本章小结在塞北村镇旅游网站的设计和实现过程中,对于后台管理的设计,首先是对数据库进行数据的概念结构进行设计,之后又对数据库的逻辑进行设计。这是因为一个适合本系统的数据库对于软件开发的十分重要的,所以本网站在数据库设计过程中花费了很长的时间,争取将数据存放在一个结构清晰,安排合理的数据库中,这样就可以有效的存储,满足用户要求。
    5 系统详细设计5.1 主界面模块设计塞北村镇旅游网站的首页界面设计以简单、便捷、清晰为主。色彩搭配柔和,最上边包含各个模块的链接,另外还有系统公告、站内新闻,村镇旅游景点图片,友情链接等部分组成。塞北主界面整体结构比较单调大方,网页最上边以不同色彩的字体显示网站的名称,并配有网站特征标志,而在界面的名称下边包括系统公告和用户登录、站内搜索、友情链接。另外,界面上还显示了站内新闻、酒店推荐和系统简介。除此之外,界面还配置相应的图片,显示部分景点风景。还有推荐酒店的具体详细图文。系统用户将光标移动到对应模块并进行单击时候,都会跳转到相应的另一个网页。例如,当单击塞北人文时,页面会进入到对应的塞北人文介绍网页界面。类似的,单击塞北故事时,页面也会进入到塞北故事介绍网页界面。点击酒店信息时,界面下端会出现塞北村镇旅游网站所有酒店信息供用户选择,包括酒店星级,编号,名称,电话,照片,操作等。而同样在旅游景点界面中,包括该旅游景点星级,名字,具体方位,简介,图片还有旅游价格。点击天气预报,出现天气预报界面,将鼠标移动到指定省或者地方之后会显示该地具体天气预报,点击旅游地图查询,可以查看各个地方旅游路线。点击在线评价模块,用户就能够对该网站服务进行评价或者给出意见。在用户申请模块中,用户可以根据自己的实际情况进行基本信息的设置与提供,等待管理员审核通过之后方能登录。登录后,可以对该网站的各个功能进行管理,进行增加删除修改预订等功能。下图中显示的是塞北村镇旅游网站的首页,点击各个板块之后运行效果也如图5-1首页效果图、图5-2首页塞北人文、图5-3首页酒店信息、图5-4首页景点信息、图5-5自驾游路线、图5-6首页天气预报、图5-7在线留言、图5-8用户注册、图5-9首页后台登录所示:
    首页效果图

    首页塞北人文

    首页酒店信息

    首页景点信息

    自驾游路线

    首页天气预报

    在线留言

    用户注册

    首页后台登录

    5.2 用户注册模块设计申请注册流程需要通过每一个使用该网站的客户提供个人详细资料完成对该网站的注册。用户注册完成后,经过管理员的审核以后方能成功登录。用户注册成功以后,可以进行预订管理,个人信息管理以及旅游路线管理等功能。同时,用户可以对该系统的服务进行在线评论,及时把意见反馈给管理人员。用户在注册过程中,对于某些信息可以不用填写,但是对于有标记*号的信息必须进行填写,否则的话,系统会自动弹出请输入用户名(密码)(姓名)的对话框,注册失败。其次,只有填写正确有效的详细信息才能提交成功,等待管理员审核。如图5-10用户注册界面、图5-11用户填写不成功、图5-12用户注册成功所示,本文用图片的方式详细展示了用户申请注册和注册成功的界面:
    用户注册界面

    信息填写不成功

    用户注册成功

    5.3 旅游景点模块设计在该模块部分中,用户可以在此对显示出来的并且是自己感兴趣的旅游景点进行查看。点击首页的旅游景点之后,用户可以看到该网站上所有旅游景点的具体详细信息,在搜索栏的名称一栏中填写对应的找寻的名字,就可以显示符合该名称或者与该名称有相同关键字的旅游景点信息。同样的,在搜索栏中的星级栏中搜索某级景点,点击搜索按钮之后便可将对应的星级景点信息加以显示出来。供用户快速便捷的搜索到自己想要的旅游景点信息。如图5-13景点信息展示、图5-14景点名称查询、图5-15旅游景点效果图所示,可以清楚的看出,该部分风景的查询与显示。
    景点信息展示

    景点名称查询

    旅游景点效果图

    5.4 酒店预定模块设计塞北村镇旅游网站根据用户的实际需要,在该网站中加入了酒店预订部分。其目的在于为用户提供一体化的服务,同时减轻酒店工作人员的工作量,用户可以自己进行房间的选择与订购。用户登录以后,点击本网站首页最上边显示的酒店信息,就可以出现出本网站酒店的具体信息。点击出现页面操作栏的详细,就可以出现如下图所示的酒店详情。最下边一栏有酒店预订,点击相应按钮后,就可以提供详细的预定所需资料。当填写完基本预订信息之后,单击提交按钮,就会出现操作成功的对话框。点击确定以后,就可以返回到主界面上,此时,可以登录个人后台管理,查看自身已经预订的酒店信息。值得注意的是,酒店预订必须是在登录完成以后,才可以进行。如果没有进行客户登录,只可以进行具体资料查看操作但是却没有办法完成预订操作。如图5-16酒店详细信息图、图5-17酒店预订图、图5-18酒店预订成功图、图5-19酒店预订成功列表所示,可以清晰的展现出酒店订购模块的具体操作和运行效果。
    酒店详细信息图

    酒店预订图

    酒店预订成功图

    酒店预定成功列表

    5.5 后台管理设计后台管理和数据库部分相连接,要求只有该登录名和密码与数据库所设置的用户一致时,才可以进行后台登录操作。只有符合数据库数据的用户名和密码才可以登录。登录后,可以实施各种操作。实现对网站基本信息的管理。系统功能列表里主要包括:

    账号管理,在这里管理员可以修改个人信息,包括密码和个人资料等等
    用户注册管理部分是对该网站的申请注册的用户进行验证通过,管理员可以对该网站申请的所有用户进行删除修改和审核。审核通过以后,用户方可注册成功,成为该网站用户,实现以后一系列的操作。管理员也可以对该注册用户实施一票否定权,此时用户注册不成功。用户还需重新注册
    塞北人文添加模块主要是对该网站中塞北人文的管理,管理员可以对塞北人文进行更新修改和删除。操作完成以后,在主页面的塞北人文模块可以相应的出现管理员之前修改或者更新过的塞北人文。再者,该模块还有塞北人文查询模块,管理员在对塞北人文添加更新完毕以后,可以在查询模块里找寻对应的修改,完成想要的操作
    塞北故事管理模块同样包含俩部分内容,一是塞北故事添加,二是塞北故事查询。管理员可根据实际情况对塞北故事进行更新或者添加删除。操作完成以后,首页中的塞北故事模块就会显示相应的修改。而塞北故事查询模块是对管理员进行以上操作之后进行的查询工作。在这里,管理员可以对自己刚添加或者已经添加的塞北故事进行查看,确定是否添加成功。同样的,管理员对于自己添加的信息有所不满或者添加错误的时候,也可以进行相应的改正或者删除操作
    塞北景点进行的操作包含塞北风景信息的添加和塞北风景的查询。同塞北人文和塞北故事模块一样,管理员也同样可以对景点信息进行适当的添加和实时更新。改正过后的景点具体资料同样可以在首页的景点信息模块得以显示。管理员在景点查询模块可以对自己已经添加修改过的景点信息进行查看,有错误的地方还可以修改或者删除
    自驾游路线管理主要是对路线的实时更新和查询。管理员通过路线发布模块对塞北旅游网站进行路线的发布,方便广大旅客进行查找。在前台的首页部分也会相应的进行更新显示。而在旅游路线查询部分管理员同样可以进行旅游驾车线路的问询和修改。同以上三个模块功能基本相同,此处不做太多叙述
    酒店信息管理模块一共涵盖三部分内容。包括信息添加,信息管理操作以及订购操作。在此模块中,除了和以上所介绍的模块一样管理员可以进行酒店信息的添加和查询管理,之后可以在主界面进行显示以外,又增加了一项新的功能,即酒店预订管理。所有该网站注册用户的酒店预订信息管理员都可以进行查看,这样可以方便帮助管理员安排与用户要求所相符合的酒店。同时,该酒店预订管理还可以进行搜索功能。管理员可根据需求搜索自己想要查询的酒店预订管理。还可以对已经预订的酒店信息进行添加和撤销等操作
    留言板管理较为简单。该模块实现功能较为单一。管理员有权限对客户的在线评论进行一系列操作,包括删除和回复。管理员在查看用户留言之后,可针对用户提出来的问题或者意见进行回复和做出实时修改。这样解决了该网站管理员与广大客户之间的沟通交流问题
    最后包括修改密码和退出登录模块。该项功能也比较简单,在上述的叙述中也有提到,在此不重复说明。后台管理模块具体实现的功能如图5-20后台管理功能所示:


    5.5.1 后台登录模块设计后台登录是整个系统的核心部分,在这里可以对该网站的信息进行基本的管理。登录页面设计清晰明了,由俩个文本框、一个选择文本框和俩个按钮构成。文本框内需要用户填写用户名和密码,选择文本框的权限是管理员。也就是说,只有管理员才可以登录,其他普通用户不可以登录。用户在上述文本框内填写管理员用户名与密码,若填写的用户和密码与数据库中管理员的用户和密码一致,方可进行登录,跳转到后台管理页面。如果所填写的用户和密码与数据库内容不一致,则无法进入跳转页面,进行相应的操作,同时系统还会显示错误信息,清空文本框内填写的信息。用户如果还需登录,那么就需要重新填写信息。后台登录模块的流程图如图5-21用户登录模块流程图、5-22后台登录界面以及图5-23后台登录失败、图5-24后台登录成功所示,从而进行显示,运行效果也如下。
    用户登陆模块流程图

    后台登录界面

    后台登录失败

    后台登录成功

    5.5.2 旅游景点模块设计旅游景点介绍和管理是整个网站的重点设计部分。景点信息需要及时进行更新和添加,管理员也可以对景点资料进行查阅。管理员在后台对景点添加模块对塞北村镇网站景点进行添加之后,点击提交按钮,会提示添加成功的对话框,按确定之后重新回到上一级页面。添加成功后,前台用户可以实时的看到管理员更新过的景点信息,以便进行更好的选择。同样的,管理员在后台对景点信息进行添加之后,还可以在景点信息查询模块对自己所修改过的景点信息进行查询操作,对应不满意的地方还可以进行进一步的修改删除。该模块最上边还设置有搜索框,管理员可以根据时间或者星级或者名称来查找相关景点资料信息。图5-25旅游景点后台管理、图5-26景点添加图、图5-27景点添加成功、图5-28景点信息查询、图5-29景点信息前台查询和图5-30景点信息添加页面所示,展示了该模块的运行示意图。
    旅游景点后台管理

    景点添加图

    景点添加成功

    景点信息查询

    景点信息前台查询

    5.5.3 线路管理模块设计路线管理实际上是为了方便广大用户,为其制定合理省时的路线方案。管理员可以对自驾游路线进行添加和查询。管理员在后台对旅游路线进行发布和更新,用户可以在前台首页点击自驾游路线进行路线的查看。而在后台自驾游路线查询中,管理员可以在此进行路线的查询,修改,删除等操作功能。而在自驾游路线查询页面的最上边设有路线编号,路线名称,目的地,交通工具,出行时间,发布人等栏目,管理员可以根据以上提示信息,填入关键字,对自己已经发布的路线进行查找。如图5-31路线添加界面、图5-32路线查询界面所示,展示了路线管理模块的实现图。
    路线添加界面

    路线查询界面

    6 系统测试6.1 测试的任务及目标6.1.1 测试的任务软件测试的需要完成的任务有:在软件产品进行生产运营之前,以最少的时间成本和人力资源、最大限度的发现或者找出软件产品中已经存在的或者尚未发现的不足和漏洞,保证产品能够正常运转并且能够满足用户对产品的所有要求。同时可以有效的和系统工作人员互动,实现改进软件的最终目标。具体主要包括以下几个方面:

    更早的发现并找出软件产品中的bug
    尽量多的避免软件缺陷的出现
    尽可能全面的评价软件产品的各项性能指标,保证软件产品的功能和容错性
    时刻关注需求的变化
    功能检查:检查每个部分功能能否运作,是否有漏洞或者运行不出来的情况
    性能检查:检查性能是否合格
    初始化、终止检查:检查程序是否能够正常开始和正常结束终止

    6.1.2 测试的重要性及目标软件测试是软件开发过程中的一个重要部分环节,可以说在软件产品开发周期中起着举足轻重的地位。而在以前的软件开发中,并不重视测试部分。他们经常只是存在于系统的运行和维护阶段之前进行,其他部分并不涉及。所以,这就成了所发开的软件在完成之前进入投入使用的质量标准是否合格进行的唯一测试和保障。这就导致后期维护成本增加,系统漏洞出现频率增高。在最近几年来来,开发维护人员逐渐意识到系统测试的重要性,所以提出,应该在系统生命周期的每一个阶段都应该包含测试,这样就可以验证系统能否达到用户所期望的效果和需要,能否高效的实现了用户要求的全部功能,是否存在运行不出来或者运行出错的问题。若少了这些环节,不提早进行各个时间段的具体测试任务和细节,后期开发维护成本将会大幅度增加,而且问题的蔓延往往使得产品错上加错,越滚越大,最后甚至会导致软件开发难以继续进行进而宣告失败。
    理论上具有很大的可行性,但是事实上,对于测试系统来讲,不论进行如何精细的测试方案、技术和方法,系统不可避免的还会出现错误。然而,创新合理的方法,周密的方案,新的语言,能够大大减少问题的发生的概率,绝对的避免问题的发生几乎是不能够完成的。测试人员应该通过测试不断修改完善系统中存在的问题。进行系统测试工作应该至少达到整个软件产品发开时间和任务的40%以上。因为测试占据重要地位,关乎软件开发成功与否,更关乎成本的投入数量。统计表明,典型的系统项目投入的总资金中,测试部分大概就要花百分之30到50的资金总额。如果没有合适的测试部分,也可以说在测试部分没有投入太多工作量就直接交付成品,可能就会导致二次开发、三次开发甚至多次开发的严重后果。最后不仅开发的系统不合格,资金投入高,严重时还会使得软件被弃用。这样说来,测试工作必须得花费时间仔细完成。正因为系统测试具有如此重要性,所以在运营之前进行测试是必不可少的,同样,测试可以到达的目标也是十分重要的。软件测试的目标主要是力求避免或者减少bug和漏洞的发生,以求可以确保系统的正常运行。
    6.2 测试方案在测试的过程中,方案的选取是十分重要的。根据系统的不同,制定不同的测试方案,既能到达预测效果,又能节省成本,符合系统制定规则。而测试方案的设计是否成功,不仅仅只是资金和时间上的节省,更重要的是能否找到系统已经存在或者潜在的bug。能够找出多种证明系统错误或者漏洞的数据,这才是成功的测试数据和方案。黑盒测试以及白盒测试是经常使用到的两种固有方案。
    黑盒测试也称为功能测试,主要针对接口之间。黑盒测试不在乎内部结构如何,它只关心程序能否实现已经规定好的各种功能,正确输入输出即能否正常接收数据然后获得预期效果一样的输出结果,同时保持程序结构的无差错性。黑盒测试的优点在于简单,便捷的获得想要的结果,找出系统错误,而不必担心程序内部如何运行,这就大大简化了测试人员的工作量又可以达到自己想要的结果。常用的黑盒测试方法主要包括:等价法、边界值分析法、因果图法、猜错法等等。
    白盒测试又称为逻辑测试。该方法与黑盒测试方法正好相反,该方法关注的是程序内部逻辑的实现,而不在乎外部接口。白盒测试方法将系统看成一个透明的盒子,它关心的是程序内部实现逻辑和结构,对系统的逻辑路径及过程一一进行测试。检验系统是否与预期效果是否相符。白盒测试需要设计多种测试用例,对已有代码进行全方面的检测,保证代码的正确性。白盒测试的俩种方法有:逻辑覆盖法和路径覆盖法。该测试依照程序内部的逻辑结构顺序进行程序的检验,检验其程序中的正确性。
    本系统开发过程进行的测试步骤如下:
    6.2.1 模块测试模块测试在测试的过程中往往是一个常常选用的测试方案。其的要完成的任务是将系统一个部分一个部分的分开进行检验,保证每一个单元都能正常运行。在模块测试执行中出现的问题一般都是详细设计或者编码过程中出现的问题。简单通俗来说,单元测试其实就是根据已知条件和具体情况来检验某功能函数执行过程和结果是否可以达到要求。模块测试是由程序员自己完成,就像某程序员定义了一个函数,需要查看一下该函数是否能够正确执行,程序员可以自己设计一些代码段来对该函数进行验证。对软件产品而言,就可以及时发现不足加以改善。对于程序员而言,单元测试的良好习惯可以使得程序出错性低,产品质量好。
    6.2.2 集成测试集成测试以单元测试为基础,在单元测试的前提条件下,将多个单元之间进行联合测试,发现这些单元之间的接口可能存在的问题。因为如果一个单元模块可以正常运行,但是将他们联合起来并不一定能够完成任务,达到预期效果。程序在某些局部反映不出来的问题,有可能在全局上就显示出来了。集成测试是一个过程,需要精细周密的设计,他的任务是检查各个不同模块相互间是否有连接错误问题。
    在集成测试的多种测试方法中,渐增式集成测试是比较占有优势的,所以在本网站测试环节中,使用的是该联合测试方法。但是单一的测试方式是难以将测试方法做到完美,应该使用多种混合的方式,这样可以更多更早的发现软件产品中存在的问题。所以,在软件产品的上部采用自上而下,相反的,在软件的中下部采用自下而上的测试方法。多种方式可以相互结合,共同完成测试工作。
    6.2.3 验收测试验收测试是最后一个操作,也称为交付测试。软件产品在完成以上模块,集成,系统测试之后,下一步就需要进行最后的检验。验收测试可以保障软件开发各项功能全部就绪,让客户最后决定其所需的所有任务。而验收测试所用的最多的方式是黑盒法,其常用的方法有三种:正式验收、Alpha测试和Beta测试。具体方式的采用往往根据各种标准和应用领域。
    6.2.4 平行运行所谓平行运行其实就是将不同系统之间同时运行,比较不同系统之间的运行参数和结果,这样可以互为参考,同时便于新旧俩个系统的处理结果进行比较。这样做的目的有:

    系统能够在已有的准确的生产环境中运行试验,减少系统风险
    能够对各种已经交付的指南、说明、手册等的文档进行验证
    对于用户来说,对新系统的熟悉也比较方便
    可以准确检验软件成品的各种功能和性能指标,对新系统进行合理的分析

    6.3 系统评价系统评价是指系统测试交付成功以后,运行一定时间内,对该系统进行客观的评价,包括功能性能,技术,反应速度等各个方面的评价。根据该网站的评价如下:

    系统功能评价:该网站的所有需求基本上得以实现,网站运行良好,得到了用户和管理者的基本需求
    系统技术评价:本网站采用的技术合理,容错性强,运行稳定可靠,大大提高了网站效率,同时技术简单易懂,安全实用
    系统经济评价:在指定时间内,达到系统目标要求,且经济成本低廉,实用。各项性能指标都合格

    6.4 本章小结本章主要介绍了系统测试模块所采用的几种测试方案。每一个系统在发开阶段都应该注意系统测试部分,因为测试可以及时发现问题,找出系统不足的地方,进行全面的修改,这样就可以减少后期维护成本,开发出来的产品性能才会比较高。
    结论在塞北村镇旅游网站的设计和实现过程中,最开始通过网上问卷调查等方式对该网站进行了系统的需求分析,向广大互联网用户了解到旅游网站一般应该具备哪些基本的功能与特征。然后下一步对网站从技术上,经济上,操作上进行可行性分析,分别对这三方面可行性进行分析确认。可行性分析通过之后又进入详细设计阶段,这个阶段主要是对数据库进行选择和设计。这一过程非常重要,是整个详细设计阶段的最重要部分。只有数据库设计合理有效,才能为下面一系列模块实现工作打下坚实的基础,为具体工作做好准备。最后是划分各个部分所要实现的内容,然后着手每个部分代码的实现。
    该网站开发采用MyEclipse作为开发工具,运用JSP、JAVA、HTML等技术,SQL2005数据库这样一个简单的小型数据库。整个界面便清晰便捷,客户使用0起来简单方便。在网站的开发过程中,特别注意强调的是,开发过程采用的是边开发边测试。这样就可以及时发现问题,及时改正。不然会因为前期工作的失败造成后续工作额度难以推行,找不到出错位置。首先进行单元测试,确保各个模块正确无误之后再进行下一模块代码的编写与实现,最后进行个模块接口的实现,完成模块之间的整合,最后进行一次最终的测试。考虑到该网站在未来投入使用过程中不可避免的出现各种错误操作,还需要对系统可能出现的各种异常都进行提示框处理。完成具体模块功能以及整合后,还需要修修改改,不断美化界面,达到完美。最终实现了集性能稳定及页面美观为一体的一个完整的旅游网站。
    塞北村镇旅游网站基本可以满足塞北村镇对其当地景点宣传的需要。基本上达到了预期效果。但是,人无完人,笔者在网站设计过程中,不可避免的还会有一些不完善的现象,比如说,功能实现不够细致还需进一步深思改正,界面设计不太美观还需要进一步美化等等。另外,在数据存储上可能也存在一定缺陷,数据表的设计也存在不足。一些功能的实现没有找到最简便的方法,代码太长导致网站系统反应时间太长等等。根据系统的不足,继续改进和完善本系统。虽然存在上述问题,但是整体而言,本网站有许多地方还是做的非常不错,希望可以在以后的学习工作中不断完善与改正。
    参考文献[1] 张文琳.基于JSP的旅游网站设计与实现.经营管理者.2014
    [2] 刘昱.旅游网站系统设计与实现.电子科技大.2011.11
    [3] 王青.旅游网站的优化设计研究.北京印刷学院 2011.07
    [4] 王国辉.Java Web 开发实战宝典[M].清华大学出版社.2010.1.
    [5] 王海心.大学生互助旅游网站设计与运营研究.龙江科技信息.2016
    [6] 张红.利用Java Servlet实现在Web服务器平台上的开发.[J].桂林电子科技大学学报.2009.29(3).
    [7] 黄勇. 基于JSP的电子商务系统中关键技术研究[J], 商场现代化, 2008.1(528): 133~134.
    [8] Marty Hall, Larry Brown著. Servlet与JSP核心编程(第2版)[M]:北京.清华大学出版社.
    [9] Christine Canning Esposito.The business of restoring a car’s beauty.[J].Coatings World .2002.7(9).
    [10] David Flanagan. JavaScript: The Definitive Guide[M]. O’Reilly Media, Inc.2006.
    3 评论 36 下载 2020-07-23 09:06:42 下载需要13点积分
  • 毕业设计选题系统

    摘 要随着在校大学生人数的不断增加,教务系统的数据量也不断的上涨。以往的毕业设计选题是随堂报名。这种方法虽然直接,但是造成选题的盲目性和教务处处理数据的繁重性。为了减轻教务处工作,以及每个学生更好的选择自己所喜欢的课题。针对学生选题这一环节,本系统从学生网上自主选题以及教师的课题发布两个大方面进行了设计,基本实现了学生的在线信息查询、选题功能以及教师对课题信息发布的管理等功能。
    本文通过分析浏览器服务器结构的特点并结合选题的实际情况,提出了基于浏览器服务器结构网上选课系统的基本设计思想,简要介绍了系统各功能模块及数据库的设计,着重讨论了用 ASP.NET技术和SQL Server 数据库设计开发网上选课系统时的数据库访问技术和动态网页制作技术,并给出了部分实现代码。通过该系统,使学生可以方便地进行网上选课。该B/S结构的系统在Windows 10系统和ASP.NET平台下开发完成,使用C#作为ASP.NET的开发语言,SQL Server 2012作为数据库。系统有较高的安全性和较好的性能。其中连接数据库的字符串可以随时在Web.config里修改,并经过编码加密,增加了灵活性,保护了数据库的安全。代码尽量使用存储过程和尽量减少数据库连接的打开时间等手段来提高性能。
    本系统的实现使得网上毕业设计选题简单实用,主要目的是使老师能更好的管理课程设计,也能使学生能更好的把自己想要的课题正确无误的选出来。使处在选题时期的学生能有条不紊的进行。从而加强毕业设计的管理,提高教师的工作效率,降低教师的工作量。
    一、开发背景计算机技术高度发达的今天,利用信息技术对大量复杂的信息进行有效的管理成为一种普遍而实用的手段。一方面,这极大的减少了簿记和人力的开销,另一方面,现代计算机强大的计算能力和网络的普遍部署,大大简化了大量信息的处理和流动。每年毕业临近时,都有优良的毕业生需要进行毕业设计,这其中的首要关节就是课题的选择,以往指导老师都是采用人工手写方式给学生们提供相关的毕业课题提供学生选择,如果指导老师带领的学生比较多,或者是当年毕业的学生比较多,这样就造成学生的毕业课题选择很混乱,指导老师难于统计学生的毕业课题选择情况等一系列问题,基于这些传统问题,我们需要一个能够自动统计,实时分配课题的一个管理平台来帮助学生、指导老师。
    此系统的开发,主要目的是使老师能更好地管理课程设计,也能使学生能更好地把自己想要选的课程准确无误的选出来,使在选择毕业课题时期的学生能有条不紊的进行。
    二、需求分析1、用户基本需求描述下面就对毕业设计选题系统的设计进行需求分析。
    根据系统用户分析各个角色为学生、教师、管理员。
    学生登录系统后,可以修改个人信息,查看所有可选择的毕业设计课题,并且可以执行选题操作,如果学生的选题请求被批准,则不能再重新选题根据需求调查可以得出学生用户在登录系统之后的需求如下:

    查看选题信息:学生在选题之前可以查看教师所提交的所有未被“确选”的课题详细信息
    查看教师信息:学生可以了解到所有教师的详情信息
    选择课题:学生可以根据选题要求自主选择题目,并直接把选题请求提交到教师
    个人信息管理:学生可以修改登录密码以及个人的详细资料

    教师是系统的主要用户之一,他们是毕业设计课题的提出者,并且也是学生选题的最后决定人。教师在登录系统后,可以进行个人资料管理,课题管理以及确认学生选题等操作。根据需求调查可以得出学生用户在登录系统之后的需求如下:

    课题管理:教师可以对添加课题,修改课题描述,以及删除未审核的课题等操作
    学生选题确认:在查看到学生对某一个课题的选题申请和学生详细信息后,可以确定具体的一位学生作为最终完成课题的人。其他同学的选题申请被拒绝后,自动进入到再次选题状态
    个人信息管理:教师可以修改登录密码以及个人的详细资料

    管理员是系统的管理者,包括教务工作管理人员,他们可以添加、管理系统用户信息,可以对课题信息进行管理,并且对系统进行维护。根据需求调查可以得出管理员用户在登录系统之后的需求如下:

    用户管理:可以对系统的用户,包括学生和教师的信息进行查询、添加、修改和删除。同时可以根据不同身份的用户赋予不同的操作权限
    课题管理:对教师提交的课题进行审核,符合相关规定以及要求才能通过;并可以删除不符合相关要求和规定的课题
    选题情况管理:可以查看已选题、未选题以及选题但未被老师通过的学生信息
    基础信息管理:可以添加学校系部以及专业;可以修改系统网站的名称,添加、编辑以及删除系统中的教师所属科研室、教师的职称名

    2、数据流图分析


    3、数据字典数据字典(Data Dictionary,DD)用来定义系统中各成分的具体含义,它以详细、清晰、准确、无歧义的说明为系统的分析、设计及维护提供了有关元素的一致的定义和详细的描述。数据字典是数据库的重要部分,它是数据流图中所有要素严格定义的场所,这些要素包括数据流、数据流的组成、文件、加工小说明及其他应进入字典的一切数据,其中每个要素对应数据字典中的一项条目。






    三、详细设计1、概念模型设计
    2、关系模型设计
    课题 (课题编号,课题名称,课题难度,课题描述,审核状态,审核人,审核时间,教师编号,确定状态)
    用户 (用户编号,密码,有效标识,角色编号,教师编号,学号)
    学生选择课题(课题编号,学号,确定状态,确认时间,解决方案,)
    教师(教师编号,姓名,性别,出生日期,身份证号,教师职称,professionId)
    学生(学号,姓名,性别,出生日期,身份证号,班级,professionId)
    权限 (权限编号,privilegeMaster,privilegeMasterValue,privilegeOperation)
    角色 (角色编号,角色名称,角色排序,角色描述)
    功能模块 (功能编号,功能名称,功能请求路径,功能序号,图标,功能层级,是否有效,功能上级编号)
    专业 (professionId,专业编号,专业名称,departmentId)
    学校系部(departmentId,系部编号,系部名称)

    3、物理模型设计该系统在设计数据库的表的时候,因为考虑到在系统运行时,录入的数据具备一定的意义性,完整性。在设计数据库表时对记录设置数据完整性约束以及参考3NF,对字段设置域完整性、参照完整性、自定义完整性等三类数据完整性。数据完整性约束是为了防止不符合规范的数据进入数据库,在用户对数据进行插入、修改、删除等操作时,DBMS自动按照一定的约束条件对数据进行监测,使不符合规范的数据不能进入数据库,以确保数据库中存储的数据正确、有效、相容。综合以上条件数据库设计表一共10张表。



    四、系统功能模块说明1、用户登录模块
    功能描述:此模块的主要功能是实现用户登录。用户输入用户名、密码通过系统认证,可登录系统
    输入:用户名、密码
    输出:登录成功进入主界面或者登录失败重新登录

    2、用户管理模块
    功能描述:此模块的主要功能是管理员和用户对信息的管理。用户进行修改资料, 查询资料。管理员添加、修改、删除用户信息
    输入:用户修改和查询资料数据以及管理员添加、修改、删除用户信息
    输出:修改成功或查询成功显示相应数据. 添加成功或者修改成功或者删除成功

    3、权限管理模块
    功能描述:此模块的功能是用来配置权限信息的。管理员对角色和用户进行权限信息的配置
    输入:权限信息配置
    输出:权限配置成功

    4、课题管理模块
    功能描述:此模块的功能是老师设置课题,学生来浏览课题。教师:在系统上报课题,设置课题难度,修改课题,添加课题和删除课题;学生:浏览本专业所有老师上报的可选课题
    输入:教师设置课题难度或者修改课题或者添加课题或者删除课题、学生输入要浏览课题题目
    输出:课题设置成功或者修改成功或者添加成功或者删除成功,浏览相应课题信息

    5、选题管理模块
    功能描述:此模块的功能是管理员审核课题,学生选择课题,教师审核学生选择课题
    管理员:对所有上报课题的内容和难度进行审核,审核通过的课题则为可选课题
    学生:可以以根据选题要求自主选择题目,并直接把选题请求提交到教师
    教师:审核学生所选择的选题
    输入:管理审核课题、学生选择课题、教师审核学生选择课题
    输出:审核通过转入可选课题、选题提交教师审核、审核通过或者审核不通过重新选题

    6、选题情况管理模块
    功能描述:此模块是管理员管理选题情况的。可以查看已选题、未选题以及选题但未被老师通过的学生信息
    输入:管理员查看学生选题情况
    输出:展示学生的各种选题情况信息

    7、基础信息管理模块
    功能描述:此模块是管理员用来对系统基本信息管理的。管理员对科研室、教师职称、系部、专业和修改系统网站的名称
    输入:管理修改各种基础信息
    输出:基础信息修改成功

    五、系统实现1、项目结构
    2、登录界面
    管理员、学生和教师输入正确的账号密码登录系统,进入主界面。
    3、主界面
    管理员登录进入主界面,拥有选题模块、课题模块、权限模块和系统基本信息模块。

    学生登录进入主页面,拥有选题模块、用户模块。

    教师登录进入主界面,拥有选题模块、课题模块和用户模块。
    4、用户管理
    管理员用户对学生、老师和管理员的管理增删改查。

    学生用户对教师的信息进行查询。

    实现对用户自身的信息进行查看和修改。
    5、权限模块
    管理员用户实现对管理员、学生和教师的权限进行分配(添加、修改、删除、查询)。
    6、系统基本信息模块
    管理员用户实现对系部和专业的管理(添加、修改、删除、查询)。
    7、课题模块
    实现对课题的管理(添加、修改、删除、查询),教师只能操作自己的上报课题,已审核的课题无法进行删除和修改。

    管理员用户对教师上报的课题进行管理(审核、拒审),只能审核未被审核的课题,拒审可以将已审核的课题返回到未审核状态(如有学生已选此课题则无法拒审)。
    8、选题模块
    实现对课题的管理(选择课题、取消选择),只能一个课题、如果已选择课题在审核或者已通过状态无法再选择课题、如果课题已审核无法取消选择。

    实现教师用户对学生选择课题的管理(查询课题、审核通过),点击课题排列出所有已选择该课题的学生,右击通过,并为其他未通过学生提供选题方案。符合该课题的学生则选题状态已通过,其余选择该课题的学生则是未通过状态并显示选题方案。
    六、总结我们团队小组经过两周的努力,基本完成了毕业设计选题系统的设计开发。这段时间里,从需求分析到软件编码完成,从中学到了很多知识,不仅让我更深层次的掌握了数据库原理、SQL Server数据库应用、异步交互技术以及项目开发的大致流程,并且结合着软件工程的理论,让我在这次毕业设计中真正懂得了做软件需要的不仅仅是好的思维和编程技巧。更重要的是在调研的过程中,学到了很多实际的业务,并学到对一种业务从不同角度出发考虑,对业务从不同角度处理等。同时也学到将众多的数据进行筛选,后进行分析,对这些数据进行归纳总结,并将归纳的结果进一步变成知识消化。
    开发毕业设计选题系统意在提供一个更方便的选题环境,方便同学选题的同时也便于学校进行统一的教务管理。此系统基本实现了所有功能,从学生选题,教师审核选题,管理员管理选题等,这些都可以在实际中运用。且系统界面友好,易于操作,即使没有使用电脑经验的用户也能轻松上手,快速准确的完成选题等工作。由于时间的仓促,本系统仍有一些有待完善的功能,例如用户查询输入相关信息的中文拼音就能检索出数据以及录入数据界面交互不够快捷,因此还可以进一步完善系统的功能,提供更方便快捷的服务。
    在设计中我们深知自己掌握的知识还远远不够,将掌握的一些理论知识应用到时间中去,总会出现这样或者那样的问题,不是理论没有掌握好,而是光知道书本上的知识是远远不够的,一定要把理论知识和实践结合起来。把学到的知识应用到实践中去,多做多练才可以把理论的精华发挥出来。
    参考文献[1].贾铁军.软件工程与实践[M].清华大学出版社,2016.
    [2].章忠宪.ASP.NET应用程序开发技术[M].机械工业出版社,2014.
    [3].王丹丹,陈康.软件工程技术现状与发展趋势[J].信息与电脑(理论版),2016(6):50-51.
    [4].白尚旺,党伟超.软件分析建模与PowerDesigner实现[M].清华大学出版社,2010.
    [5].王小科.ASP.NET典型模块开发全程实录[M].清华大学出版社,2013.
    [6].福勒.企业应用架构模式[M].北京机械工业出版社,2010.
    [7].任靖.浅析ASP.NET MVC框架开发特性[J].信息记录材料,2018,19(06):46-47.
    [8].毕传林,裴南平.ASP.NET MVC中自定义授权过滤器在软件系统中的应用[J].信息通信,2017(12):136-138.
    16 评论 153 下载 2020-02-08 14:46:01 下载需要15点积分
显示 45 到 60 ,共 15 条
eject