分类

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

资源列表

  • 基于JAVA的图形填充

    Overview计算机图形学期末PJ

    多边形区域填充
    3D立方体投影展示程序

    RequirementsJDK1.6
    How to run1. git clone https://github.com/whimsycwd/GemetoryPJ.git2. mvn clean compile3. mvn exec:java -Dexec.mainClass="base.FillPolygon" # 多边形填充4. mvn exec:java -Dexec.mainClass="bonus.Cube" # 3D立方体投影Hot to Operate多边形填充

    鼠标点击n个点
    最后一个点双击
    这n个点组成的的多边形内部被染色

    示例:

    3D立方体投影

    w and s : Pitch
    a and d : Yaw
    q and e : Roll

    实现算法多边形填充
    跨立实验判断线段相交
    public double cross(Point a, Point b, Point c) { return (double) (b.x - a.x) * (c.y - a.y) - (double) (b.y - a.y) * (c.x - a.x); } public int sign(double value) { if (value > 1e-8) return 1; if (value < -1e-8) return -1; return 0; } public boolean intersection(Point a, Point b, Point c, Point d) { if (sign(cross(a,b,c)) * sign(cross(a, b, d)) > 0) return false; if (sign(cross(c,d,a)) * sign(cross(c,d,b)) > 0) return false; return true; }
    针对每个像素, 采用射线法, 奇数个与多边形相交的点则为内部点.
    private void fill() { Point sp = new Point(9998, 9999); int n = nodes.size(); for (int i = 0; i < WIDTH; ++i) { for (int j = 0; j < HEIGHT; ++j) { int intersectionNumber = 0; for (int k = 0; k < nodes.size(); ++k) { if (intersection(nodes.get(k), nodes.get((k + 1) % n), new Point(i,j), sp)) { ++intersectionNumber; } } if (intersectionNumber % 2 == 1) { Graphics g = p.getGraphics(); g.drawLine(i, j, i, j); } } }3D立方体投影
    图形旋转参考右手系旋转的方式
    // rotate along axis X double [][] matrixAlpha = new double[4][4]; matrixAlpha[0][0] = 1; matrixAlpha[1][1] = Math.cos(alpha); matrixAlpha[1][2] = Math.sin(alpha); matrixAlpha[2][1] = -Math.sin(alpha); matrixAlpha[2][2] = Math.cos(alpha); matrixAlpha[3][3] = 1; // rotate along axis Y; double [][] matrixBeta = new double[4][4]; matrixBeta[0][0] = Math.cos(beta); matrixBeta[0][2] = -Math.sin(beta); matrixBeta[1][1] = 1; matrixBeta[2][0] = Math.sin(beta); matrixBeta[2][2] = Math.cos(beta); matrixBeta[3][3] = 1; double [][] matrixGamma = new double[4][4]; matrixGamma[0][0] = Math.cos(gamma); matrixGamma[0][1] = Math.sin(gamma); matrixGamma[1][0] = -Math.sin(gamma); matrixGamma[1][1] = Math.cos(gamma); matrixGamma[2][2] = 1; matrixGamma[3][3] = 1; g.setColor(Color.white); g.clearRect(p.getX(), p.getY(), p.getWidth(), p.getHeight()); Point3D [] points2 = new Point3D[8]; for (int i = 0; i < 8; ++i) { double [] row = new double[4]; row[0] = points[i].getX(); row[1] = points[i].getY(); row[2] = points[i].getZ(); row[3] = 1; row = multiply(row, matrixAlpha); row = multiply(row, matrixBeta); row = multiply(row, matrixGamma); points2[i] = new Point3D(row[0], row[1], row[2]); drawDot(g, row[0], row[1]); }
    面染色采用 P497 画家算法, 先对平面的Z重心进行排序, 由远及近进行染色.
    // fill in color double [] center = new double[6]; for (int i = 0; i < 6; ++i) { center[i] = avg(points2, facet[i]); } int [] idx = new int[6]; for (int i = 0; i < 6; ++i) { idx[i] = i; } for (int i = 0; i < 6; ++i) { for (int j = i+1; j < 6; ++j) { if (center[idx[i]] > center[idx[j]]) { int t = idx[i]; idx[i] = idx[j]; idx[j] = t; } } } for (int i = 0; i < 6; ++i) { Polygon polygon = new Polygon(); for (int j = 0; j < 4; ++j) { int nodeId = facet[idx[i]][j]; polygon.addPoint(transform(points2[nodeId].getX()), transform(points2[nodeId].getY())); } g.setColor(penColor[idx[i]]); g.fillPolygon(polygon); }遇到的困难
    Point3D类属于javafx包, 不是标准包, 最终改为自定义的类
    图形渲染闪烁问题, 从AWT转化为Swing, 用其框架自动的Double-Buffering来避免闪烁问题, 其中在画图的时候应传递同一个Graphics 否则会导致画布刷新, 从而展示不出新的东西.

    参考文献
    http://docs.oracle.com/javase/tutorial/extra/fullscreen/doublebuf.html
    http://www.cnblogs.com/muding/archive/2013/02/19/3031447.html
    http://www.vineetmanohar.com/2009/11/3-ways-to-run-java-main-from-maven/
    http://mojo.codehaus.org/exec-maven-plugin/
    http://www.ibm.com/developerworks/cn/java/l-java3d/
    0 评论 1 下载 2019-08-09 13:58:24 下载需要8点积分
  • 基于C#和SQL SERVER的企业进销存管理系统的设计和实现

    摘要进销存管理是现代企业生产经营中的重要环节,是完成企业资源配置的重要管理工作,对企业生产经营效率的最大化发挥着重要作用。本文以我国中小企业的进销存管理为研究对象,描述了企业进销存管理系统从需求分析、系统设计、系统实现到系统测试的全周期。在本次设计确定了进销存系统的基础功能需求,深入剖析了企业进销存的业务流程,完成了基础设置模块、客户管理模块、产品管理模块、进销存管理模块和系统管理模块的功能设计。分析部分对系统的概念、特点、运行环境及数据库设计进行了分析描述;设计部分根据系统的总体描述、模块及结构图提出了系统的总体设计方案内容;实现部分介绍了系统中各个模块的实现方法,做到客观实际,具有通用性。
    关键词:进销存管理系统;.NET;B/S 模式;SQL
    ABSTRACTInventory management inmodern enterprise production and management is an important aspect. It alsoplay an important role to maximize the efficiency of the production andoperation of enterprises. Taking inventory management of SMEs in China for thestudy, this page describes the enterprise inventory management system fromrequirements analysis, system design, system implementation to a full cycle ofsystem testing. In this page to determine the basis functional requirements of Invoicingsystem, in-depth analysis of the business processes of enterprises Invoicingcompleted basic settings module, customer management module, product managementmodule, inventory management module and system management module functionaldesign. Part of the concept of systems analysis, features, operatingenvironment and database design are analyzed description; according to thegeneral description of the design part, modules and structural diagram of theproposed system design program content; implementation section introduces theimplementation of the system in each module methods to achieve the objectivereality, with versatility.
    Keywords: Inventory managementsystem; .NET;B/S module; SQL
    第1章 绪论1.1 课题背景随着现代企业管理理论的发展,以及在新形势下信息化技术在现代企业管理的不断应用,许多中小企业在激烈的市场竞争中也开始注意到企业信息化管理的重要性,部署了贴合自身业务的小型管理系统。但当前许多中小企业实现的管理信息系统都是非常独立的系统,采购、销售、库存管理都有独立的系统。大量的系统不利于数据共享和综合的统计分析。因此,中小企业迫切需要部署一个综合的进销存管理系统以实现数据的统一管理。进销存管理系统以库存管理为基础,主要完成企业的采购管理、销售管理、库存管理、客户管理和产品管理等工作,通过对销货进货、库存变更等操作过程的管理,为管理者提供详细企业运营状况,帮助企业打到采购、库存、销售的平衡,降低企业成本。
    1.2 国内外现状美日韩等发达国家因工业水平和计算机技术起步较早走在了世界的前列。自 20 世纪 60 年代起发展了许多实现企业全面管理的企业资源计(ERP系统)。这些 ERP 系统中均有进销存管理相关的模块[1]。但中小企业由于规模与资金限制,只在部分业务普及了信息化。这些软件系统中均具有进销存管理的相关业务模块,例如Communication Oriented Production and Information ControlSystem (COPICS)、商业计划和控制系统(BPCS)、NIPPON TELEGRAPH AND TELEPHONECORPORATION (NTT)系统,业务模块具有较高的集中度,同时也易于扩展,全世界许多企业使用这些管理系统来完成企业的进销存管理工作。美国的一份数据统计表明采用利用软件对企业进销存管理,可减少40%的积压库存,12%的企业生产力增[2]。
    在经济化浪潮下国内也涌现出一批优秀的进销存系统,如用友软件、金蝶公司、浪潮等的 ERP 系统,都在国内得到了广应用。但当前我国进销存管理系统存在的主要缺陷:①软件功能复杂。许多进销存管理系统包括从物流、生产到财务等多个领域,但许多功能并不适用于中小企业;②进销存信息单一,且缺乏对数据的分析功能。无法对进销存信息进行实时分析;③系统网络化程度低。许多传统的进销存管理系统只支持在局域网中进行使用,更无法满足当前网络经济时代的要求。国内进销存管理系统的研究已经从点到面,又向细节逐步深入的阶段,在各方面细节上不断完善系统,为企业进销存管理打造一个坚实的根基[3]。
    1.3 课题的目的和意义本课题的目的是研究设计实现企业进销存管理系统,并通过该系统实现以下目标:

    模块化进销存业务,使企业需求更加明了,方便用户操作
    灵活分配企业员工权责,优化管理
    实现中小企业进销存管理的持续使用

    本课题的意义如下:

    实时下订单
    实时查询库存数量
    为企业管理者提供科学的决策数据

    1.4 本文组织结构
    第一章为绪论,大致介绍本课题的研究背景以及国内外进销存管理系统的现状,以及应用进销存管理系统的主要意义
    第二章为开发进销存管理系统的相关技术,本章主要介绍了开发系统时使用的技术、语言、数据库技术和软件架构等方面
    第三章为进销存管理系统的分析与设计,本章主要说明了该系统的需求、系统的模块规划,以及系统数据库的设计及相应的截图
    第四章为进销存管理系统的实现,本章主要说明了系统的开发环境,介绍了系统各个模块所实现的功能
    第五章为总结与展望,本章主要总结了本系统的开发工作,并指出系统存在的不足,有待改进

    第2章 相关技术介绍2.1 ASP.NET技术ASP.NET技术是用微软开发并推行的,是一种使嵌入网页中的脚本可由因特网服务器执行的服务器端脚本技术,可用于在服务器上生成功能强大的Web应用程序,是ASP技术的升级版。ASP.NET支持多种类型语言的编程开发,其中包括常用的Visual Basic .NET、C#、Perl等语言。因为ASP .NET是基于通用语言的编译运行的程序,其实现完全依赖于虚拟机,所以它拥有跨平台性,ASP .NET构建的应用程序可以运行在几乎全部的平台上[4]。同时,ASP.NET还有许多功能强大的组件,例如DataList、DetailList和Gridview等,可以实现快速简便地与数据库进行连接,并且它本身还自带了服务器空间,简单好用[5]。
    2.2 C#语言C#是微软公司发布的一种面向对象的、运行于.NET Framework之上的高级程序设计语言。它是由C和C++衍生出来的,同时又综合了VB简单的可视化操作和C++的高运行效率,以其强大的操作能力、优雅的语法风格、创新的语言特性和便捷的面向组件编程的支持成为.NET开发的首选语言。
    2.3 SQL Server数据库SQL Server数据库是一个关系数据库管理系统,是一个可扩展、高性能、为分布式客户机/服务器计算所设计的数据库管理系统。它实现了与WindowsNT的有机结合,提供了基于事务的企业级信息管理系统方案[6]。SQL Server数据库具有如下特点:

    高性能的设计。SQL Server数据库可以充分利用Windows NT的优势
    系统管理的先进性。它支持Windows图形化管理工具,支持本地和远程的系统管理和配置
    强大的事务处理功能。SQL Server数据库采用了多种方法,以保证数据的完整性
    支持对称多处理器结构、存储过程、ODBC,并具有自主的SQL语言。SQL Server数据库以其内置的数据复制功能和强大的管理工具,以及其与Internet的紧密集成和开放的系统结构,为广大用户、开发人员和系统集成商提供了一个出众的数据库平台

    2.4 B/S结构B/S结构(即浏览器/服务器结构)是WEB兴起后的一种网络结构模式,其主要是利用日渐成熟的WWW浏览技术,结合VBScript和JavaScript等Script语言,再加上ActiveX技术,将系统功能实现的核心部分转移到了服务器上,简化了系统的开发,是一种全新的软件系统构造技术[7]。用户通过自己电脑的浏览器就可以在家访问数据库,不需要特别安装软件,使得系统的拓展十分便利。
    2.5 AJAXAjax是一种创建交互式网页的web开发技术。它并不是一种单一的、新的技术,而是由Javascript、CSS、Dom、XMLHttpRequest这四中技术集合而成的。它由JavaScript语言写成,使用CSS控制页面的样式,通过DOM使用模型,通过XMLHttpRequest向后台发送数据。Ajax技术很多时候被用于实现页面的局部刷新,大大提高了用户体验感。
    2.6 AndroidAndroid是一种基于Linux的自由及开放源代码的操作系统,主要使用于移动设备,如智能手机和平板电脑,由Google公司和开放手机联盟领导及开发。一个Android 应用是由多个Activity 组成的。这多个Activity 之间 可以进行相互跳转,例如,按下一个Button按钮后,可能会跳转到其他的Activity。和网页跳转稍微有些不一样的是,Activity 之间的跳转有可能返回值,例如,从Activity A 跳转到Activity B,那么当Activity B 运行结束的时候,有可能会给Activity A 一个返回值。这样做在很多时候是相当方便的。
    2.7 本章小结本章主要介绍了在进销存管理系统中使用的相关技术,例如C#和SQL Server数据库的相关介绍,B/S结构的简单阐述以及AJAX的原理。
    第3章 系统分析与设计3.1 系统需求分析进销存管理系统的开发过程中包括了前期准备,市场调研、系统分析、系统设计以及系统实现、测试、评价等步骤。由于调研对象主要集中在中小企业,所以其中的一些功能只做了一些简单的设计。根据系统开发的大小、规模以及应用范围的不同,各个步骤的要求和内容可能不尽相同。
    3.1.1 业务流程分析为了使用户能够更加直观地了解整个系统的业务关系、工作顺序以及相应的管理信息的流向,在此给出了本系统的业务流程图,如图3-1所示。本系统是进销存管理系统,主要实现企业库存的信息管理,设定价表、入货出货和实时查询企业库存[8]。其中,订单模块是本系统的重点。
    如图3-1所示,在本系统中,管理员拥有系统全部基础功能。如新增客户,新增产品和销售区域,新增业务代表等基础信息维护;设定价盘表,可按照不同销售区域对产品进行差异化定价;调整并审核销售单、退货单、收预收款等业务操作。管理员新增业务代表并审核通过后可由业务代表帮助客户下预售单,预售单在管理员审批通过后可由库管发货,审核期间可组合选择付款方式(预收款付款,先进结款等)。
    业务代表在本系统中扮演了重要角色,承担了企业与客户沟通的桥梁,在线下跑订单,下预售订单等都由业务代表完成。业务代表是可以关联车辆的,企业的每一辆运货车可以由一个司机加一个业务代表组合负责。司机负责货运,业务代表负责在手机APP为客户下订单,可下订单包括销售单,预售单,退货单,在手机端业务代表可任意组合自己的付款方式,灵活完成客户订单需求。
    产品价表是本系统的重点,管理员可针对不同渠道不同区域的不同产品差异化定价,尽可能符合当前区域的经济需求。管理员亦可对产品设定活动,活动包括买赠和减免,对于同一客户的下单可直接给业务代表赠送的权利,简化买赠活动为免费赠送单。灵活的定价方式可满足不同区域的消费需求。

    3.1.2 数据流程分析从业务流程图中,我们可以比较直观地了解到整个系统中各个实体以及各个模块之间的业务关系,以及作用顺序,但是对于各类信息的具体处理、存储及流向方面,则不是十分详细。而为了更加清晰地了解一个系统中的数据信息流向和处理存储过程,本文中给出了数据流程图。如图3-2所示,是本系统的数据流程图,从下图我们可以比较明确地知道整个系统的数据走向。

    3.1.3 功能性需求分析进销存管理系统的角色分为系统管理员、业务代表、司机、客户。
    系统管理员可以由系统使用方指定对象担任,人数由使用方决定,系统管理员不需要注册。系统管理员主要管理整个系统中基础信息的调整和订单审核,包括新增业务代表、新增产品、设定产品价表等。具体功能要求如下:

    管理授权:注册其他角色时需要在管理员授权
    修改权限:系统管理员可以根据需求修改系统人员和商品的信息的权限
    业务权限:系统管理员可以对订单进行审核发货和取消
    信息维护:系统管理员可以对整个系统中的信息进行维护
    审核功能:根据新增基础信息需求,审核信息

    业务代表是由管理员添加并审核通过的注册者,在系统中具有下预售单和车销单的权限。具体功能如下:

    客户管理:具有新增客户、修改已存在客户资料等功能
    车销管理:下车销订单
    预售管理:下预售订单
    库存管理:可申请移库,由主仓库移动至车仓库或由车仓库退货
    退货管理:可以查看有关自己的留言,回复他人对自己的提问
    其他信息:订单查询等

    司机是由管理员添加并审核通过的注册者,在系统中具有库存调拨的权限。具体功能如下:

    调拨管理:车销移库或退库
    订单管理:在车销订单中收款

    3.1.4 非功能性需求分析非功能性需求,指的是除了用户所需的功能要求以外,还应该满足的一些其他方面的要求。本系统以下几个方面进行分析:

    系统安全性:防止无权限人员进入系统修改相关信息[14]。若操作系统能给数据库用户分配角色,则安全性管理者必须要有修改操作系统用户安全性区域的操作系统权限
    性能需求:用户在软件响应速度、结果精度、运行时资源消耗量等方面的要求。如对计算机系统的要求,对工作频率、容量、存储量等方面的要求
    易操作需求:界面简单明了,命名明确易懂。如一些系统管理员不太熟悉电脑操作,系统界面必须一目了然、简单易懂、容易上手
    适应性:当外部条件有所改变的时候,系统根据外界因素改变。如时间变化,系统根据当前时间删除发布招募信息时过时时间的选项

    3.2 系统模块划分根据以上分析,可以将库存管理信息管理系统分为基础信息管理、采购管理、销售管理、库存管理、财务管理、报表平台等几个模块。系统管理员主要有信息的维护、审核、权限管理等功能具体,业务代表具有订单权限和新增客户权限,如图3-3所示:

    3.3 系统数据库设计在一个系统的开发过程中,数据库设计可谓是至关重要,一个数据库的设计成功与否,直接关系到整个系统的开发,甚至会影响到整个系统的成败。
    3.3.1 概念设计概念设计是由分析用户需求到生成概念产品的一系列有序的、可组织的、有目标的设计活动,它表现为一个由粗到精、由模糊到清晰、由抽象到具体的不断进化的过程。现在常用的概念模型是E-R模型。在本系统中,各实体直接的关系如图3-4所示:

    3.3.2 逻辑设计逻辑设计是将概念结构转变为某个DBMS支持的数据模型,也可称为优化。将本系统转换后就得到如下关系模型:

    商业客户基本信息表(ID,客户编号,全称,简称,行政城市,邮政编码,客户地址,送货地址,联系人姓名,电话号码,手机号码,传真,Email,企业网址,首要联系人,客户开门时间,客户打烊时间,营业执照号,组织机构代码证号,税务登记证号,客户类型,所有权属性,所有权人,备注,审核标志,新增日期,新增人,更新日期,更新人)
    供货商合作关系表(ID,客户ID,供货商,客户自编码,业务人员,客户合作状态,开始合作日期,截止合作日期,供货价盘表,渠道,区域,销售路线,拜访顺序,拜访模板,备注,审核标志,新增日期,新增人,更新日期,更新人)
    员工信息资料表(ID,姓名,性别,员工编号,身份证号,出生日期,行政城市,地址,邮编,电话号码,手机号码,电子邮件,开始工作日期,截止工作日期,管理片区,职务,在职状态,所有权属性,所有权人,备注,审核流程,审核标志,新增日期,新增人,更新日期,更新人)
    商品基本资料表(ID,产品名称,产品简称,商品编码(平台级编码),规格,整件单位,零售单位,包装系数,整件商品条码,零售商品条码,商品种类,商品品牌,商品类别,段位,整件重量,整件体积,厂家名称,生产厂商,厂家商品码,厂家商品ID,标准经销价,标准分销价,建议零售价,成本价,状态,保质期,所有权属性,所有权人,备注,审核标志,新增日期,新增人,更新日期,更新人)
    订货单信息(ID,订单号,供货商,订购商,业务员,供货价盘表,类别,状态,折扣金额,优惠金额,实际订货金额,要求送达时间,要求送达仓库,提交时间,确认时间,关联拜访记录,备注,审核标志,新增日期,新增人,更新日期,更新人)
    发货单信息(ID,单号,发货商,收货商,发货商仓库,收货商仓库,业务员,送货人,类别,制单模式,状态,供货价盘表,关联订货单,折扣金额,优惠金额,实际销售金额,送货车辆,预计送达时间,装车配货时间,发车时间,实际到达时间,关联拜访记录,备注,审核标志,新增日期,新增人,更新日期,更新人)
    实时库存表(ID,仓库,商品,批号,生产日期,数量,价格,最后更新时间,新增日期,备注)

    3.3.3 物理设计物理设计指的是根据数据库的逻辑结构来选定RDBMS,并设计和实施数据库的存储结构、存取方式等。本系统采用SQL Server数据库,根据以上的分析选取了主要的几张表展示,表之间的关系如图3-5所示

    3.4 本章小结本章节作为全文比较重要的一个章节,具体介绍了进销存管理系统的需求分析,其中包括了功能性需求分析和非功能性需求分析,分别从概念、逻辑、物理这三方面进行了说明。
    第4章 系统实现4.1 系统开发环境的选择本系统的开发是基于.NET平台,以VS2012为开发环境,将C#作为主要开发语言,SQL SERVER为数据库软件。
    4.2 系统通用方法的实现本系统是进销存管理系统,系统重心在下单及库存判断上,但是作为一个应用型系统,其他功能模块也是必不可少的。系统实现过程中运用了大量的ASP.NET控件,例如AJAX、GridView、DataList等。在本节中将介绍通用模块的实现方法。
    4.2.1 连接数据库在一个系统中,数据库的连接可以说是核心部分,至关重要。在本系统中,通过web.config文件增加数据库连接字符串[9],主要代码如下:
    <connectionStrings> <addname="VolunteerConnection"connectionString="Data Source=UGYRPLW5EAMIHEB;Initial Catalog=Volunteer;Persist Security Info=True;User ID=sa;Password=123456"providerName="System.Data.SqlClient"/></connectionStrings>
    并在App_Code文件夹中添加数据库连接方法connet(),在后续的系统功能程序编写中,全部通过调用该方法来实现数据库的连接,主要代码如下:
    privatestaticstring connectString = ConfigurationManager.ConnectionStrings["VolunteerConnection"].ConnectionString;publicstaticSqlConnection Connect(){SqlConnection con = newSqlConnection(connectString);return con;}
    4.2.2 数据的绑定显示作为一个数据管理系统,需要将系统中的部分数据展示出来,因此,数据的显示操作也是十分重要的[10]。在本系统中,数据的显示主要使用了DataList和GridView控件,控件类型的不同导致了这两种控件在使用方法上的差异。在DataList控件中,本文主要采用了DataSet方法来填充数据,该方法处理脱机数据,在多层应用程序中很有用,并且可以在任何时候查看DataSet中任意行的内容,允许修改查询结果的方法,还可以处理分级数据。在本系统中,该方法被用于每一个信息展示页面,例如订单列表页面,采购单列表页面,产品列表页面等,主要代码如下:
    SqlDataAdapter sqlda = newSqlDataAdapter(sqlstr, sqlconn);DataSet ds = newDataSet();sqlda.Fill(ds, "dtxx");
    GridView控件主要使用在系统管理员模块中,通过该控件自带的分页排序功能,可以使得管理员的操作更加简便快捷。GridView控件主要是通过使用SqlDataSource数据源控件来连接数据库的,所以在此不再累赘。
    4.2.3 分页栏DataList控件本身并不带有分页功能,为实现在使用DataList控件时也能方便分页,本系统使用了PagedDataSource数据源方法来绑定DataList控件,使其也能像GridView控件一样实现分页[11]。该方法主要通过PagedDataSource和DataSet方法相结合使用,主要代码如下:
    DataSet ds = newDataSet();sqlda.Fill(ds, "dtxx");PagedDataSource pds = newPagedDataSource();pds.DataSource = ds.Tables["dtxx"].DefaultView;this.DataList1.DataSource = pds;this.DataList1.DataBind();
    4.2.4 页面局部刷新和跳转在本系统中,因为牵涉到大量数据的分页方法,势必会造成在页面刷新过程中的卡顿和不流畅现象,为解决这一问题,本系统还使用了AJAX控件,来实现页面的局部刷新方法[12]。因为AJAX是开发环境中自带的一款封装的控件,所以在使用上也是非常方便的,主要代码如下:
    <asp:ScriptManagerID="ScriptManager1"runat="server"></asp:ScriptManager><asp:UpdatePanelID="UpdatePanel1"runat="server"><ContentTemplate> ……</ContentTemplate></asp:UpdatePanel>
    在AJAX控件中,无法使用Response.Write(“”)方法进行页面信息框的弹出提示已经页面的跳转,所以AJAX也有自己自身的一种提示方法,主要代码如下:
    ScriptManager.RegisterStartupScript(this.Page, this.GetType(), "click", "alert('已完成下单!');location.replace('dygl.aspx');", true);
    4.3 系统主要功能的实现如上节所述,本系统是进销存管理系统,订单模块是本系统的主要模块,该模块实现了下单和查询功能,以及后续的一些统计功能[14]。
    本系统实现的功能主要由两部分组成,即订单和库存这两个模块的功能。进入本系统时需要登录,进入系统会自动根据身份出现可浏览模块。界面如图4-1和4-2所示:


    4.3.1 系统管理员功能系统管理员是由系统开发者或者系统购买者直接指定的,不需要注册,系统管理员的信息直接由开发人员写进数据库中。但是要注意的是,系统管理员的选择应该慎重[15]。在本项目中系统管理员除了可以修改自己的个人信息之外,还有以下众多主要功能:
    1.基础资料管理:企业员工注册客户成功之后就无法自行修改,如果注册时用户信息填写错误,用户可以向管理员线下提起申请,管理员通过用户信息管理界面进行用户信息的修改。系统管理员也可以在该功能模块进行用户权限的修改。该页面主要使用GridView控件实现,在一定程度上节省了开发难度和开发时间,同时使用代码和textbox控件,可以通过关键字搜索用户信息,方便管理员对用户信息的维护。基础资料页面都提供对各类信息的检索方式,如客户界面的关键字会在后台自动匹配客户的名称,编码,简称等属性,而新增日期的时间段则会自动筛选所有符合录入时间的客户,合作状态可选取一种状态,也可选择所有状态下的客户。界面如图4-3所示:

    2.商品信息管理:本系统提供了商品管理这一模块,具有商品操作权限的用户可以自行为企业添加商品,并为产品设定不同类别。每个产品都可以归属于一个类别,可通过类别对产品进行筛选。界面如图4-4所示:

    3.采购管理:企业作为盈利组织,势必要投入一部分成本,而成本的一个重要组成部分便是销售产品的采购。本系统提供企业对产品的采购功能,采购数据会纳入企业进销存体系,作为库存盘点的数据来源。录入采购单据时刻选择企业自身录入的供货商,选择企业的一个仓库作为入库仓库,已完成的采购单管理员可在后台予以确认,采购单据页面会自动罗列出所有的采购商品和采购的总金额,界面如图4-5所示:

    4.订单管理:企业要实现盈利就必须有销量,在实际业务过程中业务代表承担了销售的大部分责任。对于小规模客户业务代表可跟车进行车销现款现货交易,对于大客户业务代表则可通过拜访客户下预售订单的模式销货,预售单在管理员审核通过后可进行派单。订单页面与采购单页面相似,不同的是企业自身已作为供应商,而订购上则是企业客户。订单页面会显示下单的业务员和销售类型及各类采购产品明细,界面如图4-6所示:

    5.库存管理:系统管理员可以在该模块中查看现有个库存中各产品的数量,也可在各仓库之间进行调拨操作并按期对仓库进行盘点。界面图如图4-7所示:

    库存盘点是系统的一个重点功能,用户可在新增盘点单的界面选择需要盘点的仓库,此时界面会以GridView的形式罗列出所有在售产品的现有库存量,并提供一个下拉列表选择盘盈或者盘亏并以文本框形式输入数量。对于每一个产品的库存,对应于后台PBM_DeliveryDetail数据表中的一行数据,在保存时循环GridView的每一行在PBM_DeliveryDetail中插入数据。
    6.价表管理:价表是进销存管理系统的基础,决定了系统的复杂程度。本系统允许多张报表同时存在,默认设置第一张价表为主价表。管理员可新增自定义价表关联渠道或客户类型,也可同时与渠道和客户类型绑定。价表界面图如4-8所示:

    在价表管理页面用户可看到当前价表关联的区域和取到以及是否为默认价表。用户可根据商品分类或关键字查找在价表中或不在价表中的商品,以审核的价表,对于不需要再出现在价表中的产品允许用户进行批量删除,同时不在价表中的产品也可添加到价表并自定义价格。
    4.3.2 业务代表功能
    如图4-9所示,为业务代表操作流程图。业务代表由管理员注册并分配账号后方可登陆系统,主要进行下车销单和预售订单操作。具体操作在手机端完成。用户具体功能如图4-10所示:

    客户信息管理:客户信息管理又分为以下几个功能
    客户信息新增——业务代表可根据实际新增自己管辖范围内的新客户,如果需要修改某些自己无权修改的信息时,可以向管理员申请修改。该模块通过手机APP的形式展现。如图4-11所示:
    客户拜访管理——业务代表在自己管辖的片区内可按照预定线路拜访客户,为提高拜访真实性系统提供对客户门头拍照功能。如图4-12所示:

    订单管理:业务代表对自己线路下的客户有下单权限,具体功能如下:
    车销订单—业务代表在随车拜访客户时可帮助客户下车销单。该模块位于手机APP上,如图4-13所示:预售订单—业务代表在自己管辖区域内拜访大客户时可帮助客户下预售单。该模块位于手机APP上,界面如图4-14所示:

    订单查询——业务代表在APP下单后可在PC端对自己的下单详情查看。界面如图4-15所示:

    4.4 本章小结本章主要描述了本系统的各个模块的功能实现,通过文字叙述和截图的方式展现了本系统的功能模块,分别从系统管理员和业务代表的角度介绍了本系统的功能。
    第5章 总结与展望5.1 总结在信息化建设日益普遍的今天,信息系统的使用以及愈加广泛,为了优化进销存的管理,本文在了解了各种进销存管理系统之后,开发设计了进销存管理系统,并做出如下介绍。
    本文的第一章着重介绍了进销存管理系统这一课题的背景和意义,以及它的研究目的,同时也介绍了本文的内容结构。第二章着重介绍了本系统的一些相关的技术概念,比如ASP.NET技术,SQL数据库等。第三章是本文的一个重点,主要内容是需求分析以及数据库的设计等。第四章详细介绍了本系统的一些功能的实现。
    本系统的重点在于管理员对商品的管理,业务代表下单和库存管理等;难点是针对不同区域和渠道设定不同的产品价格,创新点有系统权限的分配,对财务管理的纳入等。
    经过这段时间的学习和实践,我对课堂掌握的知识有了一个更好地巩固,对不理解和不熟练的一些方面也有了一个更清晰的概念,比如C#语言的应用,SQLServer数据库的应用,以及DIV+CSS的网页布局等方面。
    5.2 展望当然,由于技术方面的因素,本系统的许多方面还存在不足,比如:

    前期的数据库设计问题,导致在系统开发过程中需要不断修改数据库设计,使得数据库的设计不是十分规范
    目前本系统只采用了B/S架构进行开发,并没有结合C/S架构
    由于技术和设备问题,本系统无法自动提示用户相关的信息动态,只能是让用户经常登录自己进行查询
    除此之外,由于目前手机应用日益发达,开发手机APP势在必行,但由于时间和技术问题APP开发暂时只能落于纸上

    参考文献][1]郭旭.基于.NET的企业进销存管理系统的设计与实现[D].吉林大学,2014.
    [2]王洪迪.基于ASP.NET的燃气具企业的进销存系统设计与实现[D].合肥工业大学,2012.
    [3]于瑶瑶.企业进销存管理系统的设计与实现[D].山东大学,2009.
    [4]李洪涛.面向中小家电企业进销存管理系统的设计与开发[D].合肥工业大学,2010.
    [5]赵晓霞. 进销存管理系统的设计与实现[J]. 煤炭技术,2010,01:244-246.
    [6]赵韩,李洪涛,陈科. 基于ASP的中小企业进销存管理系统研究[J]. 微计算机信息,2010,33:43-45.
    [7]庄翔翔. 基于B/S架构的中小企业进销存管理系统的设计与实现[D].中国海洋大学,2010.
    [8]张彦芳,王春艳. 进销存管理系统的设计与实现[J]. 中国管理信息化,2008,07:14-16.
    [9]张岩,张宁. 基于C/S架构的超市进销存管理系统的设计与实现[J]. 北京石油化工学院学报,2013,04:45-50.
    [10]陶俊. 基于.NET的进销存管理系统设计与开发[J]. 江汉大学学报(自然科学版),2007,01:55-57.
    [11]王会青. 医药进销存管理系统设计与实现[J]. 山西科技,2007,03:57-58.
    [12]翁国秀,李露璐. 企业产品进销存管理系统的设计与实现[J]. 电脑知识与技术,2011,07:1493-1494+1506.
    [13]朱士高,朱军,朱彩霞. 基于WEB的企业进销存管理系统的设计[J]. 淮阴工学院学报,2007,05:62-64.
    [14]Xiao-yunJIANG,Pin CHEN,Rong ZHENG Department of Management Science,Xiamen University ofTechnology,Xiamen,China. Study of Modeling and Simulation of Flexsim-basedInventory Management System[A]. 中国机械工程学会工业工程分会、IEEE北京分会.Proceedings of 2010 IEEE the 17th International Conferenceon Industrial Engineering and Engineering Management(Volume 2)[C].中国机械工程学会工业工程分会、IEEE北京分会:,2010:4.
    [15]KaiWANG. The Research of Inventory Management Modes Based on Supply ChainManagement[A]. Chinese Industrial Engineering Institution,CMES、Institute ofElectrical and Electronic Engineers、Beijing Section.Proceedings of2012 IEEE 19th International Conference on Industrial Engineering andEngineering Management(IE&EM 2012)[C].Chinese Industrial EngineeringInstitution,CMES、Institute ofElectrical and Electronic Engineers、Beijing Section:,2012:5.
    2 评论 43 下载 2018-11-13 14:09:18 下载需要7点积分
  • 基于C++的菜鸟驿站

    1 绪论1.1设计背景随着社会的发展,互联网的兴起,网络购物渐成为人们购物的新时尚。快递行业也在网络购物的带动下蓬勃发展,成为人们生活中必不可少的一部分。所以一个智能的快递管理系统,会大大的方便人们的生活,提高快递运送的效率。
    随着快递数量的不断增多,如何将快递安全、准确的送到每一位消费者手上成为了一个问题。而一个智能的快递管理系统可以提高工作人员的效率,帮助工作人员快速清点货物信息。由于快递会在每个地区都设立站点,所以我们设计了一款名为菜鸟驿站管理系统的快递管理系统,用来帮助工作人员高效的完成工作。
    1.2 设计目标针对快递管理的实际需求,采用C语言作为开发语言,使用文件.txt作为数据库,设计并且开发了一个菜鸟驿站管理系统。系统主要包括用户功能模块和管理员功能模块。用户功能模块包括用户注册、用户快递查询、用户快递领取、用户信息修改等功能。管理员功能模块包括录入用户信息、删除用户信息、查询用户信息、修改用户信息、录入快递信息、删除快递信息、修改快递信息、查询快递信息、统计快递领取情况等功能,实现快递管理的信息化,提高工作效率。
    1.3 相关技术介绍本系统采用C语言编写,使用VS2015作为编译器编写系统程序代码,整个系统以.txt作为数据存储的文件。
    1.3.1 C语言简介C语言是一门通用计算机编程语言,广泛应用于底层开发。C语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。尽管C语言提供了许多低级处理的功能,但仍然保持着良好跨平台的特性,以一个标准规格写出的C语言程序可在许多电脑平台上进行编译,甚至包含一些嵌入式处理器(单片机或称MCU)以及超级电脑等作业平台。二十世纪八十年代,为了避免各开发厂商用的C语言语法产生差异,由美国国家标准局为C语言制定了一套完整的美国国家标准语法,称为ANSI C,作为C语言最初的标准。目前2011年12月8日,国际标准化组织(ISO)和国际电工委员会(IEC)发布的C11标准是C语言的第三个官方标准,也是C语言的最新标准,该标准更好的支持了汉字函数名和汉字标识符,一定程度上实现了汉字编程。
    1.4 文档组织结构本文第一部分绪论主要说明了系统的设计背景,设计目标以及C等相关技术;第二部需求分析阐述了系统功能和可行性分析,介绍了系统各个功能模块,并描述了系统的用例图和活动图,可行性分析介绍了系统开发的必要性和可能性;第三部分系统设计则介绍了系统结构设计;第四部分系统实现主要讲了登录模块、管理员模块和用户模块实现的功能;第五部分系统的测试主要介绍了对该系统的测试方法和详细过程。
    2 需求分析2.1系统功能概述系统包括两种不同权限的用户:第一种是用户,即普通用户,这类用户能够通过手机了解最新的快递动态信息,修改自己的个人信息、查询快递信息、注册账号等;第二种是管理员用户,管理员可以管理用户信息,管理和审核账户信息,管理和审核快递信息,还负责管理维护系统等。因此系统的设计可以分成三部分,用户模块、管理员模块和登陆模块。
    普通用户:

    使用手机、电脑来使用该系统;
    使用自己的账号注册并登陆系统;
    新用户注册成功之后,使用唯一的账号作为ID来识别;
    登陆系统可以查看个人信息和快递信息、修改个人信息等;
    不使用时可以退出登陆系统;
    可以根据单号查询和领取快递;

    管理员用户:

    通过管理员的用户名和密码登陆系统的管理员端;
    登陆系统后具有管理系统用户账户信息的功能;

    登陆后具有管理用户信息的功能,可以对用户信息进行增、删、改、查等操作;
    可以管理用户的快递;
    可以统计快递的领取情况,有无滞留时间过长的快递;
    可以设置新的管理员;
    可以查看快递的其他信息等。

    2.2 系统执行流程描述通过研究快递管理系统的需求分析,可以将系统设计成了三个主要模块,这三个模块是登陆模块,管理员模块,用户模块。

    登录模块,可选择用户登录和管理员登录,用户登录界面可以选择新用户注册和老用户登录具体的活动图如图所示。


    管理员模块,通过这个模块能够查看,添加,删除以及修改用户信息,能够修改快递、删除快递、增加快递、查询快递等操作。在管理员模块里面,所有的具体操作的是嵌套的,详细的活动图如图所示。


    用户模块,用户通过这个模块能够查询或者修改个人信息,能够查询快递信息和领取快递。每一个操作都是平行和嵌套的,该活动图如图所示。

    3 系统设计3.1 系统结构设计根据系统需求分析,可以设计出整个校友信息管理系统的总体结构。由于本系统包含两种不同权限的用户,每种用户进入系统后所能用的功能和权限不一样,因此在对系统结构设计时要分别考虑。

    管理员页面结构设计


    校友用户页面结构设计

    4 系统实现4.1 登陆模块实现用户注册模块。打开系统,进入欢迎界面,选择用户,如下图4-1所示。还没有账号可以点击注册,注册的时候输入账号、手机号、密码,然后点击注册的时候系统会调用regs()方法,该方法会给用户注册,然后将注册信息插入用户信息表中,然后就可以使用该账号登陆系统了。

    用户和管理员登陆。输入账号、密码,然后选择用户或者管理员,点击登录时系统会调用stu_land()方法,该方法会通过查询数据库相应的表来判断输入的信息是否正确;如果账号和密码都成功的在数据库中匹配成功的话,系统就会自动判断输入的账号和密码都正确,然后就会自动跳转至用户界面或者管理员界面;如果账号或者密码中的其中有一个没有在数据库中匹配成功话,管理系统就会弹出提示框,并且会显示相关的错误提示。
    4.2 管理员模块实现首页模块。输入正确的管理员登陆信息之后,系统判断用户名,密码和数据库中的信息匹配之后就会跳转到本系统的管理员首页,如图所示。

    维护用户信息模块。管理员首页通过后台的add_student()、display_all_student()和dele_student()方法查询、修改数据库中的用户信息,如图所示。

    录入用户信息。录入用户的账号、手机号等信息,录完之后,输入y保存,输入n取消,最后按enter返回,如图所示。

    浏览用户信息。可以浏览到用户的账号、姓名、手机号码和登录密码等基本信息,按enter键返回,如图所示。

    删除用户信息。输入要删除的学生账号,系统会自动删除该账号内的所有信息,如果输入账号信息有误,会提示错误,按enter键返回,如图所示。

    维护货物模块。选择维护货物模块,系统就会跳转到维护货物模块页面。如图所示。

    录入货物信息。按单号、手机号,系统会实时录入货物入库时间,并付给货物未领取的状态,录完之后,输入y保存,输入n取消,最后按enter返回,如图所示。

    浏览货物信息。可以浏览到用户的快递单号、手机号、入库时间、状态和取货码等信息,按enter键返回,如图所示。

    删除货物信息模块。如图所示。

    修改货物信息模块。如图所示。

    未取货物信息模块。如图所示。

    4.3 用户模块实现用户首页模块。以用户身份登录,同时输入的账号和密码都正确就会跳转到图所示的校友用户首页,显示用户模块的所有功能。输入对应的功能数字就可以使用相应的功能。操作之后系统就会待用户操作完成后,然后就会全部数据更新到文件中。如果密码或者账号输入不正确的话,系统会提示“请输入正确的账号和密码”。

    用户使用模块。输入对应的数字,进入对应的功能使用模块,可以完成用户的需求。
    查询个人信息。如图所示。

    修改个人信息。如图所示。

    领取快递。如图所示。

    返回主界面。如图所示。

    5 系统测试5.1 系统测试概述所谓系统测试是根据软件开发各阶段的规约和软件的内部结构,精心设计一批软件测试用例,并利用这些测试用例去运行程序,用来发现软件中不符合软件质量特性要求的过程。
    系统测试过程可以看成不断进行排错、测试、修改程序和文档,然后进行回归测试,直到软件达到用户的质量特性要求的一个循环过程。
    5.2 系统测试方法目前主要使用的系统测试方法有白盒测试和黑盒测试:

    白盒测试,这个方法可以对程序内部的具体逻辑进行测试,相当于微观的看待事物,详细的说就是根据具体的每一个方法测试它是否运行正确,是否有错误等;
    黑盒测试,该方法把程序当成一个整体,相当于宏观的看待事物,具体的说就是不看内部具体方法只是根据设计的需求来测试系统,然后判断是否符合设计的要求,是否能够正常使用该系统。

    5.3 系统的测试打开VS2015,运行程序源码,然后进入系统的欢迎界面了。本系统采用黑盒测试,对每一个模块进行用例测试。

    软件中登陆界面的测试
    首先,打开菜鸟驿站管理系统登陆界面,如表所示。



    编号
    输入操作
    预期结果
    测试结果




    1
    选择老用户,输入账号“1”,密码“student”,登陆
    登陆成功,跳转到 用户页面
    通过


    2
    选择管理员,输入账号“admin”,密码“admin”,登陆
    登陆成功,跳转到 管理员页面
    通过


    3
    选择新用户,输入账号“2”,密码“student”,注册,登录
    登陆成功,跳转到 用户页面
    通过


    4
    不输入任何信息,直接点击登陆
    登陆失败,提示输入账号
    通过


    5
    只输入密码“11”,不输入账号,点击登陆
    登陆失败,提示输入账号
    通过


    6
    选择老用户,输入账号“100”,密码“student”,登陆
    登陆失败,提示输入 账号错误
    通过


    7
    选择老用户,输入账号“1”,密码“stu”,登陆
    登陆失败,提示输入 密码错误
    通过




    用户账户信息管理测试
    接下来,对账号信息管理进行测试,如表所示。



    编号
    输入操作
    预期结果
    测试结果




    1
    打开查询功能
    查到个人信息
    通过


    2
    打开修改功能,修改完成后点击保存
    可以对个人信息进行修改
    通过


    3
    打开领取快递,输入用户快递的单号
    可以领取快递
    通过


    4
    打开返回主菜单
    系统返回主菜单
    通过




    管理员维护用户信息测试
    使用管理员模块对用户信息进行管理,如表所示。



    编号
    输入操作
    预期结果
    测试结果




    1
    打开录入功能,录入用户信息
    提示用户添加成功
    通过


    2
    打开修改功能,修改用户信息
    提示用户信息修改完成
    通过


    3
    打开删除功能,删除用户信息
    提示用户信息已删除
    通过


    4
    打开浏览功能,浏览用户信息
    输出用户信息
    通过




    管理员维护货物信息
    对管理员维护货物信息功能进行测试。



    编号
    输入操作
    预期结果
    测试结果




    1
    打开录入功能,录入货物信息
    提示货物信息添加成功
    通过


    2
    打开修改功能,修改货物信息
    提示货物信息修改完成
    通过


    3
    打开删除功能,删除货物信息
    提示货物信息已删除
    通过


    4
    打开浏览功能,浏览货物信息
    输出货物信息
    通过


    5
    打开统计货物信息
    会输出未领取货物的信息
    通过



    结束语通过对这个系统的设计和实现,我对该系统的了解更加深了。本系统主要是完成了用户信息管理、快递信息的管理以及信息统计分析等功能。通过本次学年设计,我对软件项目的开发流程以及所运用的知识如C语言等有了更多的自己的理解,锻炼了自己解决工程问题的能力以及提升了自己系统分析和设计能力。另一方面,本系统的实现,仍存在不足,如本人对于统计分析这个模块理解不足,以致在实现功能时没有考虑到具体的情况,造成某些功能设计的不是很合理。
    0 评论 6 下载 2019-08-07 10:51:07 下载需要10点积分
  • 基于WPF实现的简单绘图工具

    1、系统功能设计
    开发、测试环境

    开发环境: Visual Studio 2012 Premium运行框架:.net framework 4.5测试环境:Windows 8.1、Windows 7
    开发语言

    C#XAML

    1.1 前言当初选择这么一个软件来编写纯粹是出于对玩弄文字游戏的xx管理系统的不喜,但我们没有料想到,经实践表明,涉及实时跟踪鼠标键盘事件和实时绘图的软件编写难度远大于主要通过文字实现信息交互的xx管理系统。仅仅实现一个屏幕上图形的框选功能就让我改了六七遍代码,我的队友更是间断地找出了五个bug。当终于能够把整体功能流畅地实现时,我们对软件开发者的了解与敬意又加深了一层。
    1.2 总体功能描述当今图像处理越发普及,人们对于图像处理的需求也各不相同。而一些绘图软件存在过于复杂(如PS)或是只具备基础功能(如windows自带画图)的问题,因此我们开发一个基于Windows Presentation Foundation(WPF)的简单绘图工具。
    以下为程序的工作界面

    1.3 功能点说明


    功能类型
    功能点名称
    按键
    实现方式
    功能点描述




    基本功能
    主流类型图片载入
    Ctrl+O
    自己编写C#代码
    支持.png.jpg.gif.bmp.eps等主流图片类型的读入和加载。使用C#标准OpenFileDialog对象获得文件路径并且使用Uri读入之后转为BitmapImage,用Image控件显示


    基本功能
    图片保存
    Ctrl+S
    自己编写C#代码
    支持bmp(位图)和eps(矢量图)两种格式。使用SaveFileDialog对象获得文件路径之后用filestream输出。


    基本功能
    鼠标手绘图形
    鼠标拖框
    自己编写C#代码
    包括矩形、圆角矩形、圆、椭圆、直线、贝塞尔曲线等


    基本功能
    单击选择图形
    鼠标单击
    自己编写C#代码
    调用类接口SelectPoint来实现


    复杂功能
    框选图形
    鼠标拖框
    自己编写C#代码
    递归调用类接口SelectRect来实现


    复杂功能
    全选图形
    Ctrl+A
    自己编写C#代码
    调用类接口SelectAll来实现


    复杂功能
    多次选中图形
    Shift+鼠标拖框
    自己编写C#代码
    调用类接口MergeComposite来实现


    复杂功能
    被选择图形的闪烁

    自己编写C#代码
    通过来回设置选择的CompositeGraphic的isVisible属性来达到闪烁的目的。


    复杂功能
    删除图形
    Delete
    自己编写C#代码
    调用类接口Clear来实现


    复杂功能
    图形状态变更

    自己编写C#代码
    设置类属性DrawMode来实现。可以设置图形的边框粗细、颜色,以及内部颜色


    复杂功能
    调色板

    使用第三方库
    支持通过ARGB属性或是在图形中直接选色的方式给图形的边框和填充分别选色


    复杂功能
    拖动图形
    鼠标按住拖动
    自己编写C#代码
    调用类接口Move来实现


    复杂功能
    键盘移动
    Up,Down, Left,Right
    自己编写C#代码
    通过长按可快速移动


    复杂功能
    剪切选中图形
    Ctrl+X
    自己编写C#代码
    将选中的图形加入一个List,并从画布上删除选中的图形


    复杂功能
    复制选中图形
    Ctrl+C
    自己编写C#代码
    将选中的图形加入一个List,但不从画布上删除选中的图形


    复杂功能
    粘贴图形
    Ctrl+V
    自己编写C#代码
    对上述List中的所有成员递归调用接口 ICloneable.Clone。长按Ctrl+V可以连续粘贴


    统计功能
    图形个数统计

    自己编写C#代码
    递归调用类属性Count并将它和Label绑定


    用户体验优化
    打开和新建图片、关闭程序时的友情提醒。

    自己编写C#代码
    防止误删未完成画布中的内容。


    用户体验优化
    显示系统时间

    自己编写C#代码
    使用DateTime.Now.ToString方法


    错误处理
    载入图像时对不支持图像及无法处理的图像的抛出。

    自己编写C#代码
    若捕获异常,会弹出对话框



    2、系统总体结构2.1 概要设计按照“面向接口编程,而不是面向实现编程”的面向对象基本原则,在建立解决方案的时候我就将解决方案分成了Ccao-big-homework(UI,WPF工程项目,由我的队友邵键准同学实现,调用者)和Ccao-big-homework-core(实现,C#类库,由我实现,被调用者)。双方互不干涉,独立调试,在整个大作业过程中不曾因为接口耦合问题出现bug。
    由于采用了多种科学合理的设计模式(见下文各模块介绍),本类库在维持良好的可复用性的同时,不曾进行过任何强制类型转换,不曾进行过任何运行时类型判定,所有的多态都靠重载函数来实现,充分体现了面向对象的思想。
    3、具体实现3.1 GUI的设计GUI的设计采用了较为简洁的风格,设计完成后曾请求周边同学进行体验并对细节进行改进,力求用户体验较好。主体采用XAML语言,实现设计和功能的分离,并配之以C#的事件处理函数。程序取消了不怎么美观的窗口边框,并采取点住程序窗口任何一个位置均可拖动的方法。
    3.1.1 程序启动和关闭动画设计程序的主要窗口在开始和结束时都是通过淡入和淡出来呈现和销毁窗口,实现此效果使用了一个计时器,并让窗口的透明度随计时器而改变。下图为启动过程截图,可看见窗体还是半透明状态(请无视背景的代码)。
    3.1.2 程序启动界面的设计界面包括版本号与开发人员,“新建绘图”按钮在鼠标移上后会有高亮,点击进入绘图页面,点击“离开”按钮则直接调用Application.Current.Shutdown()函数销毁窗口。
    3.1.3 程序主体绘图界面设计主体绘图界面如下。

    上部为菜单栏,具体按钮功能见使用手册,实现了鼠标移到某个按键上时该按钮闪烁一次并且放大,同时调整整个工作框的布局。效果如下。

    左部为绘图框,选择后可使用鼠标绘制不同的图形,包括直线、圆、椭圆、正方形、长方形、贝塞尔曲线。其中贝塞尔曲线限于WPF提供的贝塞尔曲线构造函数的局限性,其必定从画布的左上角开始绘制。
    左下角为一个图标,无实际作用。
    3.1.4 程序图标的添加我们的程序可是有图标的哦!

    下面是调色板的图标。

    3.2 逻辑层主要实现解决方案Ccao-big-homework。
    3.2.1 工作窗口WorkWindow部分3.2.1.1 概述主要实现人与程序的交互,包括鼠标事件和键盘事件等。由于绘图软件基本是在一个窗口进行操作,一般使用组合而非继承的方式,因此类的结构比较扁平。类图如下。


    由于没有继承,全部实现在一个窗口里代码显得非常臃肿,因此我根据功能的不同将同一个窗口类分成了如下几个文件。

    下面逐步介绍各个文件实现的方法。
    3.2.1.2 BtnEvent实现菜单栏所有按钮功能,包括新建、打开、保存、退出、全选、复制、剪切、粘贴、样式选择按钮。实现方法是调用其他文件里的私有函数。
    3.2.1.3 FileEvent实现图片读写的相关方法。我们的程序支持使用文件夹视图来把文件保存到计算机的任意位置或是从计算机任意位置载入图片。同时还在现有图片未保存时弹出对话框提示用户要保存,防止了图片的误删,优化用户体验。

    实现画布的新建与刷新,并实现程序的退出功能。
    3.2.1.4 FishEyePanel实现上部菜单栏中当鼠标移到某个按键上时该按钮闪烁一次并且放大,同时调整整个工作框的布局。此处采用了组合的形式,FishEyePanel是一个新的类,在WorkWindow类中创建该类的对象,并布局到主窗口上。
    3.2.1.5 GraphicsOperation实现图像整体操作,包括:

    全选:调用队友提供的SelectRect接口,并把范围设置成整个画布大小的矩形,从而得到一个类型为List<CompositeGraphic>的对象,添加到selectedGraphics里
    复制:调用队友提供的Clone()函数,往clonedGraphics这个对象里添加对象
    剪切:复制的同时清空selectedGraphics
    粘贴:将clonedGraphics里的所有成员添加到总画布compositeGraphic的Children()成员中,从而实现绘制,并向右下角移动(10,10),从而和复制的原图区分开,然后清空clonedGraphics(),并再次调用复制函数(),从而实现粘贴的连续性,即复制一次可连续粘贴。下图为按下Ctrl+C后连续按下Ctrl+V的效果


    3.2.1.6 KeyBoard实现键盘的按键监控,包括:

    Ctrl+A:全选图像
    Ctrl+C:复制选中图像
    Ctrl+V:粘贴选中图像
    Ctrl+X:剪切选中图像
    Ctrl+W:关闭程序
    Ctrl+O:打开图片
    Ctrl+N:新建画布
    Ctrl+S:保存图片
    Delete:删除选中图像
    Key Up、Key Down、Key Left、Key Right:选中图像的上下左右移动
    Shift:按住时可多次增加选择已选中的图形

    3.2.1.7 MouseEvent我的工作中最难的部分,而且肩负调试队友代码的使命。

    Window_MouseLeftButtonDown事件:实现鼠标不在画布上时窗口根据鼠标的移动而拖动
    OnMouseLeftButtonDown事件:鼠标左键按下处理事件。主要记录鼠标开始移动的点startPoint,让画布捕捉到鼠标,并标记左侧的ToolBar是否选中rbSelect选择按钮
    OnMouseMove事件:鼠标移动时的处理事件。当鼠标移动且画布捕捉到鼠标的时候,若是发现rbSelect选择按钮被选中且当前有图形被选中且Shift键未被按下,那么说明这个鼠标事件需要的是移动图形,因而用虚直线实时绘制鼠标指示的移动路径;若是其他绘图按钮被选中,则说明要绘制图形,则用虚长方形或是虚直线实时绘制图形
    OnMouseLeftButtonUp事件:鼠标左键抬起的处理事件。首先判断鼠标抬起时和按下时位置是否相同。若是相同,则说明用户只是按了一下,那么不管左侧ToolBar是选中的什么,说明用户都是想选中一个图像,因此将左侧的工具条调整到rbSelect按钮,并且调用总画布compositrGraphic的SelectPoint方法,得到这个点选中的图像,将其加入selectGraphics,在这个List里面的对象,每隔0.5秒更改一次可见性,从外观看来,选中的图形会闪烁。若是鼠标移动了,且选项选中的是图形选项卡,则绘制对应的图形,并且刷新画布,并把之前实时跟踪鼠标的虚线图形删去。接下来判断选项卡是否为贝塞尔曲线选项,若是则把该点增加到贝塞尔曲线的List里,当List里的成员个数增加到4时,绘制一条贝塞尔曲线并清空该List。最后是最为复杂的rbSelect按钮,如果当时选中的图形为0,即selectGraphics为空,则说明用户想要选中他框选的图形,则调用SelectRect得到选中的所有图形,并把其加入selectGraphics中使其闪烁。若selectGraphics不为空,则说明用户想要移动选中的图形,则调用move方法移动选中的图形,并把selectGraphics清空。同时,如果整个过程中Shift键被按下且rbSelect被选中,说明用户想要增加选择图形,于是将选中的图形增加到selectGraphics里面。

    以上方法还各自特判了贝塞尔曲线绘制时的点四个点的情况。
    3.2.1.8 Paint各种图形的绘制,包括:

    直线
    长方形
    正方形

    椭圆
    圆角矩形
    贝塞尔曲线

    其中(1)~(6)的绘制方式基本相同,都是新建一个该图形的对象,然后根据传来的两个点确定图形的长宽和位置,将这个对象添加至总画布compositeGraphic,然后刷新画布。
    对于(7),绘制方式是在画布上点四个点,则出现贝塞尔曲线。
    3.2.1.9 其他零碎功能主要包括一些动画效果。启动时工具条的移入运用了ThicknessAnimation控件。为了美观我特意写了一个函数隐藏了工具条尾部的小箭头。选中图形闪烁的功能则使用了一个DispatcherTimer计时器,每过500ms就把selectGraphics的成员的可见性改变一次。图形个数统计调用总画布compositeGraphic的count属性,每隔0.5秒刷新一次。系统时间标签则使用DateTime.Now.ToString方法获取。
    3.2.2 启动窗口MainWindow部分这个窗口很简单,只实现了弹出WorkWindow和关闭窗口退出的功能。并贴了一张图,写了版本号。
    3.2.3 颜色拾取窗口StyleSettingWindow部分颜色拾取窗口我并没有花太多时间自己写,本来以为WPF自带调色板控件,结果发现没有,于是在网上找了一个扩展控件,并组合到WorkWindow类中,在按下上部菜单栏中的“样式选择”按钮时弹出。

    3.3 类库Ccao-big-homework-core-wpf的实现3.3.1概述。本类库(Ccao-big-homework-core-wpf.csproj)基于WPF,文件统一注释为”Du 2015.9”。

    由于本类库被设计作为实现图形操作的类的类库,所以各类之间比起“is-implemented-in-term-of-a“或者”has-a“来说更符合”is-a”关系,所以本类库大量使用了继承、多态、递归调用这些OO的方法,和UI相比更好的体现了这次大作业的教育目的。

    3.3.2 MyGraphic类基本的图像类。之所以声明为类而不是接口是因为有几个函数要有默认实现。
    下图是Mygraphic类的全部类图。各函数基本都是函数名自解释的,如果一眼看不出来有什么用可以参见源代码的注释。

    乍看上去,Ienumerator和Ienumerable两个接口(包括count,getenumerator,current,add,clear,dispose,reset等,可以使得这个类被像list一样用foreach遍历)看上去都不应该是MyGraphic类作为一个基本的图像类应该有的方法或者属性。事实上这里采用了Composite设计模式。为了使得单个对象和组合对象的使用具有一致性,其他库函数(以及用户)能够统一的使用组合结构中的所有对象(具体来说,使得我们不用在override各种函数的时候来写出诸如MyGraphic g as CompositeGraphic这种效率很低的运行时类型判定代码来),所以在MyGraphic类中定义了Composite类的各种接口,并且给以了默认实现(当然了由于MyGraphic不是CompositeGraphic,默认实现理应是空实现)。
    另外,MyGraphic类还实现了接口ICloneable,这个接口允许MyGraphic被深复制,因而实现了UI的复制-粘贴功能。
    IsVisible指示本图像是否会被画到画布上。
    Father指示MyGraphic类的父图像。Father类的set方法被重写来调用父图像的DisposeChildren方法来删除父图像维护列表中自己的存在。这样就能保证整个MyGraphic类是一棵树(树的顶点是由UI保存的一个Composite,事实上充当了画布的功能),为递归遍历创造了条件。所以同时,当Father被置null的时候,本图形就会因为失去一切引用而被C#的GC机制自动回收,相当于是被Dispose了。因此本程序的效率大大提高,本人的电脑在有1500个图形的时候还能够正常工作。
    SelectError指示点击一个点的时候允许多大的误差以选中一个图形。
    还有不少函数在MyGraphic类中被声明仅仅是为了作为接口被递归调用,例如SelectRect、Count属性等就是这样,当然整个程序中最重要的Draw也不例外。
    3.3.3 SingleModeGraphic类顾名思义,是整个图形有同一个drawmode的类,也是所有基本图形(basic_graphics)的基类。显然composite类由于可以add进各种drawmode的图形所以不可能能维持有同一个drawmode。

    drawmode指示一个给定border的geometry的图形如何被绘制,将调用drawmode的draw方法(见3.3.6)。
    重载了基类的SelectRect方法,当选中时返回包括自己的一个CompositeGraphic,反之返回null。
    getGeometry方法返回这个对象的border的geometry。
    3.3.4 CompositeGraphic类可以包含其他graphic的graphic的实现,或者说用windows画图打比方的话,就是那个选框功能。重载了IEnumerable和IEnumerator接口。

    首先,作为Composite设计模式的一部分,override了MyGraphic中的Composite相关的函数(isComposite, Clear, Add, MoveNext, Reset, Current),进行了事实上的操作。
    CompositeGraphic类维护一个私有的辅助list,用来保存每个成员相对于本体的左上角的相对位置。当CompositeGraphic类要执行某个操作的时候(例如Draw或者SelectRect),它就递归调用每个成员的相应操作,好像这个类不曾存在过一样(如果设置了isCombined = false,当这个标记被置true的时候整个CompositeGraphic将被视为是一个整体,类似于PPT或者Flash提供的“组合”功能)
    另外CompositeGraphic也像SingleModeGraphic一样有drawmode类型的属性backgroundmode,这是为了画出它的边界和背景色。边界总是一个矩形。
    当调用SelectRect的时候,由于递归调用的过程会产生大量很多层的CompositeGraphic(因为selectRect的原理是将所有被选中的图形改为连接到同一个Composite中,然后将这个Composite的父图形设为this),所以设计了MergeComposite,将一个Composite中的全部内容合并到另一个中,减少了递归的层次(在这种设计之下,递归最多两层),有效提高了运行效率。
    3.3.5 基本的图像类(basic_graphics)这些类都继承自SingleModeGraphic并且是Sealed类。有几个属性来记录自己的形状,并且override了getGeometry接口来确定自己的外形。如类图所显示的那样,新建一个基本的图像类是非常简单的,只需要实现getGeometry方法和Clone方法两个方法,并且定义几个足够确定图形位置和形状的属性,就能够被立刻应用到类库之中,像其他图形一样被选择、被移动、被更改颜色、被剪切、被复制、被粘贴,这充分体现了本类库良好的可扩充性。

    对于Ellipse、Line、Rectangle,WPF都提供了相应的Geometry对象来绘画,然而对于Bezier,WPF并没有提供相应的Geometry,而是提供了一个PathSegment——BezierSegment。BezierSegment只有三个参数(也就是说默认从原点开始画),第四个点需要通过设置PathFigure的起始点来确定。
    3.3.6 DrawMode类
    抽象类。指示如何绘制一个Geometry形状的Mygraphic为drawing。这个类其实做成接口也没什么问题。如果深究起来的话把绘图方式单独封装起来似乎也是一种设计模式,学名叫做Strategy模式。Strategy模式的好处也是显而易见的——如果直接将各种绘图方式以硬编码的方式写在SingleModeGraphic中,虽然可以少几个类,但是这意味着你可以在完全不破坏类库的情况下添加新的DrawMode,使得它易于切换、易于理解、易于扩展,进一步体现了作为一个类库的重要理念——可扩充性。(嘛,不过这毕竟只是大作业,虽说类库要可扩充性良好,但是也就我自己扩充我自己的类库玩罢了…但是当我发现WPF的drawing系列图像的构架思想竟然和我一开始手画的类图一模一样的时候,我心中别提有多得意了)
    3.3.7 DrawMode类的派生类
    这些类都继承自Drawmode类并且是Sealed类。有几个属性来记录自己的绘图方式,且override了draw来绘制。
    3.3.8 defaultConstant类
    储存一些常量。在GDI+中有System.Drawing.Color枚举,然而在WPF中似乎没有对应字段,为了方便类库的设计所以作为static readonly变量定义在这里,效果类似于C++的全局const。另外准备了defaultbrush(透明色)和defaultpen(黑色,宽2.0f)来作为GeometryMode的默认构造值。
    由于是常量,所以被作为partial类分散定义在drawmode的各个派生类中。
    3.3.9 DrawingUIElement类
    本来作为一个普适的类库有上面的类就已经能够绘图了;但是我所写的这个类库毕竟是个wpf类库,然而wpf的基本控件Canvas的Children只接受某种System.Windows.UIElement作为它的子成员。所以为了避免推倒重来,此处采用了Adapter(或者叫做Wrapper)设计模式,将本类库的接口类型(System.Windows.Media.Drawing)转换为我的调用方,邵键准同学的UI能够接受的参数UIElement。
    重写了OnRender方法,只要对它调用UIElement所固有的InvalidateVisual方法就能迫使控件重画,从而将drawing指示的画面显示在wpf界面上。
    3.4 类库Ccao-big-homework-core-winform的实现本类库(Ccao-big-homework-core-winform.csproj,并没有被本次大作业引用)是一开始我的队友尚未开始施工的时候编写而成的(文件注释为”Du 2015.8”),当时前期调研做的不够好,没有意识到wpf和winform不兼容,所以手贱就先写了一个winform版。Winform版实现比wpf版要早,Class Diagram也和wpf版类似,几乎所有的类名都一样,只是winform版基于GDI+,命名空间为System.Drawing,而wpf版基于WPF,命名空间为System.Windows。在此对于两个类库之间雷同的部分不再赘述。
    在本大作业中并没有用到winform类库(因为winform的界面远没有wpf美观),但是winform类库在我们往届的测试中证明是可以使用的(见github上9.6晚上的commit,hash为87ce7da,当时有一个基于VB的样例test基于winform测试了这个类库的可行性)。如果有兴趣做winform开发,可以尝试使用这个类库。
    本类库和wpf版的唯一区别在于draw的实现。在wpf版中,draw函数是一个普通的返回System.Windows.Media.Drawing的函数。然而在winform中我们采取的并不是Adapter模式,而是另一种著名设计模式Bridge模式:我们有一个接口IWindow实现drawpath和fillpath两个接口,然后draw函数接受参数IWindow,并在函数体内调用这两个接口进行绘图,没有返回值。这样做的好处在于可以将抽象部分与它的实现分离,使得双方都可以有独立的变化。无论类库将要面对怎样的UI(即便这是个WPF UI甚至是个VB项目,例如我的测试用项目),只要这个UI实现了接口IWindow,类库就可以不作任何修改的应用到这个UI上。
    以下是项目文件列表,除了IWindow外的所有类都和wpf版一样。

    4、项目总结4.1 亮点首先,由于采用了Composite模式,所以几乎所有的Composite接口都是通过递归调用来完成的,简洁明了,体现了合理设计模式的优越性。假使不采用Composite模式,那么(任举一例),SelectRect方法将不得不返回一个list<MyGraphic>,且不说这样子将使得这个类库丧失组合/打散的固有功能,而且返回list将使得对于这个list的每个操作都必须由客户端通过类似foreach MyGraphic g…这样子的调用方式手动对每个list的成员执行。现在只需要调用Composite的对应函数,就能通过递归调用在对客户隐藏的情况下执行了,体现了良好的封装。
    其次,本类库的可扩充性堪称良好。向本类库中加入新的几何图形只需要继承SingleModeGraphic并且重写getGraphic和Clone;向本类库中加入新的绘图方式只需要继承DrawMode并且重写Draw。
    4.2 OOP模式的优越性接口和实现的分离极大提高了我们的开发效率。只需要知道给接口提供什么参数,能得到什么结果就可以了,不需要知道它是如何被实现的,这样的黑箱极大地提高了我们的开发效率。
    4.3 版本控制的重要性版本控制不仅让我们能够清晰地了解自己的开发进度,而且在开发出现重大bug的时候,能够迅速地回滚到以前的版本。这样不会出现自己写了什么挂了都不知道的,结果只好全部删除重来的情况。况且,每一次在Git上的Commit都意味着我实现了新的功能,内心总能感到满足。
    4.4 自主解决困难的能力为了写大作业我估计百度了不下300次,基本开发的状态就是:想实现某功能—>发现自己不会—>百度google大法好—>会了—>实现该功能—>又想实现某功能。
    开发过程中我遇到过很多困难,举个例子:关闭窗口时我写了个淡出动画,结果发现动画刚开始运行就程序就被退出,表现为动画无法播放。百度了一个小时,终于找到解决办法:在给程序的OnClosing事件中,把close命令取消,然后坐等0.6秒动画放完后再退出程序。
    真正到开发程序才发现以前学的都是纸上谈兵,经过一份大作业的洗礼我收获了极大提升的编程技能。
    2 评论 17 下载 2019-04-02 10:31:11 下载需要12点积分
  • 基于C#的聊天程序

    1.引言1.1目的编写详细设计说明书是软件开发过程必不可少的部分,其目的是为了在完成需求分析说明书的基础上完成需求分析说明规定的各项模块的具体实现的设计工作。
    1.2定义套接字Socket:网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。
    端点IPEndPoint:由IP地址和端口号构成,端口对应进程。这两个组合起来可以唯一的标识网络中某台主机上的某一个进程。这样就有一个唯一的身份标识,后面可以进行通信了。
    TCP协议:TCP是一种面向连接的,可靠的,基于字节流的传输层通信协议。
    回环端口:即本机的一个虚拟端口,为IPAddress.Loopback,其IP地址为127.0.0.1
    2.总体设计2.1软件描述荆棘鸟聊天程序是基于Socket设计的一个windows桌面端多人聊天程序,采用C/S架构,服务器可以自定义监听的IP(可设置为仅能本机使用或允许联机使用),客户端也可以设置服务器的IP,但是客户端设置的IP必须与服务器监听的IP相同,否则会连接不上服务器,如果不自己设置IP,默认为只能本机使用,即127.0.0.1.
    2.2设计方法本软件采用传统的软件开发生命周期的方法,采用自顶向下,逐步求精的结构化的软件设计方法
    2.3软件结构2.3.1总体结构
    3. 模块设计说明3.1程序描述本程序分成两部分,分别是服务器端和客户端。服务器启动后,用户使用客户端连上服务器后即可进行多人聊天 。在一台机器上,服务器只能启动一个,而客户端可以启动很多个,但是客户端的总数目不得超过100个。对于服务器和客户端,均采用多线程异步处理机制,在关闭程序后会自动回收所有子线程。
    3.2功能本程序能实现多人聊天功能。服务器打开后,客户端需要通过设置正确的服务器IP来连接服务器,服务器也可以设置自己能监听的IP地址进行监听,如果客户端与服务器均不手动设置IP,那么默认的IP是本机的回环地址(IPAddress.Loopback),而且客户端的IP和服务器端的IP必须设置为相同的才能正常连接上。客户端连接服务器的要求是必须设置一个唯一的用户名,用户名若重复则会进行提示并需要重新设置一个唯一的用户名后才能连接上服务器。同时客户端也会检测用户名是否包含敏感词汇(会影响程序正常运行的词),若包含也需要重新设置用户名。客户端连上服务器后,能显示服务器状态信息(服务器是否关闭)、是否有用户上下线以及其他用户发出来的消息。服务器端能显示用户的连接与下线信息,以及服务器的状态信息。同时服务器也能恢复默认监听的IP地址,即IPaddress.Loopback(127.0.0.1),且服务器会显示当前监听的IP地址。
    3.3 性能对于1M的带宽的网络

    客户端连接上服务器的时间在10秒以内。
    客户端间通信的时间间隔不得超过10秒。

    3.4 输入项
    服务器:需要输入(选填)监听的IP,如果不填则默认是本地回环端口127.0.0.1,输入的IP必须为格式正确且服务器所能监听的IP,否则将会进行提示。
    客户端:

    需要输入唯一的用户名(前17个字符不能为“Server has closed”,否则会影响程序正常运行),且用户名不能为空。连接上服务器后用户名将不能进行修改。需要输入服务器的IP以进行连接,格式和服务器的监听的IP相同,且客户端输入的IP必须和服务器监听的IP相同,否则将无法连接上。连接上服务器后服务器的IP不可修改。允许在输入框中输入文本信息以进行多人聊天,但是仅限文本信息。

    3.5 输出项
    服务器 :

    能显示当前监听的IP,如果不自己设置监听IP,则默认为127.0.0.1。能显示服务器的状态,即时启动还是关闭。能显示客户端连接服务器的状态,当客户端连接或者断开连接时,服务器端会显示。
    客户端:

    显示服务器状态信息,即服务器是否已经关闭。显示其他用户发来的信息,即进行正常的聊天。显示其他用户的上下线信息。

    3.6 流程逻辑首先启动服务器(服务器程序打开后会自动启动,此时监听的端口为127.0.0.1)。然后启动客户端,设置用户名,设置服务器的IP(如果不设置则默认为127.0.0.1)。点击客户端的连接服务器按钮,检查用户名是否合法,不合法则直接终止并需要重新设置用户名后重试,若用户名合法,则检查客户端设置的IP格式是否正确,若不正确则中断连接并需要重新设置服务器IP。然后进行客户端与服务器端的连接。若客户端与服务器设置的IP不一样,或者服务器未开启,则会提示连接失败,服务器未打开。
    正常连接上后,其他在线的客户端会提示此用户上线了。服务器可以点击关闭服务器,此时所有客户端都会提示服务器已关闭并自动关闭客户端与服务器的连接。客户端也可以点击退出聊天,可以关闭与服务器之间的连接,此时服务器端与其他在线用户均能收到此用户已下线的消息。
    服务器端在服务器开启后会显示当前所监听IP,若选择重置,则会先断开所有客户端的连接,然后重新开启服务器,并监听所设置的IP,显示的当前监听的IP也会随之改变。此时所有客户端全部被强制下线,必须设置与服务器相同的IP并重新连接服务器后才能继续进行聊天。
    3.7 接口
    当新用户连接上服务器后,会给服务器发送 “用户名”+“$”,服务器读取到这种格式的数据会将’$’去掉之后将其当成新用户进行保存,与该用户的套接字一起以键值对形式保存在字典中,并将上线消息进行转发。
    当用户需要退出聊天时,会给服务器发送“$”,服务器读取到仅有一个‘$’的数据时会将对该用户的连接关闭,并将其从用户字典中删去,且将用户下线信息进行转发。
    clientSocket为客户端中用来连接服务器的套接字,客户端用clientSocket != null && clientSocket.Connected根据情况判断是否连接上了服务器或服务器是否关闭。
    当服务器向用户发送的消息为“#用户名#”的时候,表示该用户名已经有人使用,需要客户端更换用户名后才能重新连接。
    当服务器向客户端发送的消息的前17个字符为“Server has closed”时,表示服务器已经关闭。
    在服务器端代码中,类Broadcast的成员函数PushMessage(String msg, String uName, Boolean flag, Dictionary<String, Socket> clientList)是用来对所有客户端进行转发信息的。当flag为false时表示是系统消息,直接发送msg+DateTime.Now.ToString(),而如果是其他客户端发送的聊天信息需要转发时,则设置flag为true,会发送uName: msg+ DateTime.Now.ToString()。

    3.8 注释设计函数模块的注释放在函数的头部,关键语句的注释放在语句的上面一行或者语句的后面。对所有参考资料均在注视中标明来源网址,并抄下或者自己写下了关键性的注解。
    3.9 限制条件本程序只能在64位windows操作系统下运行,且该系统必须装有.NET 4.5及以上的框架。
    0 评论 4 下载 2019-08-05 11:45:33 下载需要5点积分
  • 基于Java的迷宫老鼠游戏

    一、功能简介迷宫老鼠系统包括以下功能:

    自定义迷宫大小
    使用图的深度遍历随机生成迷宫
    用户使用鼠标绘制自定义迷宫
    单步求解迷宫
    一键求解迷宫
    声音特效

    二、程序截图




    三、系统开发平台
    名称:迷宫老鼠
    目的:利用堆栈寻找迷宫的路径解法。

    编程语言:Java开发工具:Eclipse操作系统:Windows

    四、系统规划4.1 任务陈述现实生活中总会有各种各样的寻径问题,比如地图寻路、导航驾驶等等。本次要开发的是将日常遇到的问题抽象化后形成的系统,抽象化提出要求后,根据具体需要,可设计为游戏或者应用。本次项目的名称是迷宫老鼠,它的应用主要用于解决迷宫的寻径问题。
    4.2 任务目标
    解决迷宫问题:入口A已经给出,要求从A进入,正确的尽可能快速的从出口B走出。
    随机设计一个迷宫并且求解
    自定义一个迷宫并且求解。

    五、流程图
    六、需求分析6.1 数据结构需求数据结构主要涉及三个部分:

    顶点的数据对象:包含四个1/0整数数据表示该点四个方向的连通状况,数据之间没有联系。
    迷宫的地图:需要对迷宫的路径进行存储,大小固定,组内元素没有联系,互不影响,没有先后顺序。组内的数据类型为封装好的顶点对象类。
    迷宫求解中的路径:需要存储经过的路径,元素为封装的顶点对象。元素必须按照顺序排列,先进先出,数据大小无影响。

    6.2 操作需求6.2.1 随机模式
    6.2.2 自定义模式中
    七、 实现思想(分两部分:随机生成可解迷宫与自定义迷宫)7.1 随机生成可解迷宫首先,迷宫由n*n个方阵点组成,每个点有控制上下左右,4个方向的墙的属性值,以推倒墙的方式来构建两点间的通路。要是两点间有通路,即要使左边的正方形推倒右墙,右边的正方形推倒左墙,则形成此通路,通过设置点的属性值来保存构成迷宫的点。
    利用图的深度优先遍历原则,从起点(0,0)开始,想任意可访问的点进行随机深度遍历,直至所有点都被遍历到为止(此处遍历全部的点是为了使迷宫看起来更加和谐好看,也增加了迷宫的复杂度),深度遍历的路径即为迷宫可行走的通路,当解迷宫时只能在此规定的通路上寻求通路,也就间接的形成了迷宫。
    由于图的深度遍历的特点,起点(0,0)可以到达图中任何一个点,此处设置终点为矩阵的最后一个点,确保了起点到终点一定有通路,且通路唯一。将构成迷宫的所有点形成一个可变数组ArrayList,以供解迷宫时使用。
    解迷宫时,方向选择按照先右,后下,再左上,并且提供计算两点间在确定方向上是否存在通路的判断方法,如果该点找到了下一个可通行的点,则将该点加入堆栈,如果找不到,则从堆栈中取出一个点,即形成了回路。
    7.2 自定义迷宫首先根据输入生成m*n个方格,通过鼠标点击事件,生成点击的方格处设置障碍,由此生成迷宫。解迷宫时,在上述解迷宫的基础上,加入没有通路的判断(即到达不了终点的判断),即堆栈已经为空,但仍要从其中取出点时,表示此迷宫已经没有可以再到达的点,此时反映迷宫无通路,给予用户提示,解迷宫完成。
    八、 数据结构设计首先,利用动态数组储存迷宫的所有点类(MazePoint类),随机生成与自定义迷宫的过程中,便是通过设置这些迷宫点来构造迷宫的。
    数据结构设计关键在解迷宫时予以体现,此处我利用堆栈的思想,讲解迷宫时经过的点压入堆栈,当在一点找不到可到达的下一点时,便取出堆栈中最顶层的点,将此点设为当前点寻找可到达的点,依次进行此过程,直至到达终点或堆栈中已没有点可以被取出为止。
    以为在解迷宫的过程中,寻找过得点被唯一标识,当形成回路再寻找可到达的点时,这些被唯一标识的点不会被二次到达,以此保证迷宫不会出现死循环的状态。
    0 评论 1 下载 2019-08-04 10:07:02 下载需要10点积分
  • 基于C++的画图程序

    (实验说明:本程序是在linux系统下编写编译的,没有Windows可执行文件,所以只能给出源码,但是经测试好像源码在windows系统下opencv库有一些问题,不能正常编译,所以只能在linux下运行,编译器使用clion即可。要想在本地运行成功,需要修改画图程序main文件第98行的fopen的参数为本地的一个位置,并把图形程序mainwindow.cpp中所有的fopen(”/home/li/cghm/binary.dat”,”wb”)中的”/home/li/cghm/binary.dat”改为上面修改的路径,同时修改该文件第54行的program->start函数的参数为图形程序编译后生成的可执行文件的路径。最后图形程序和画图程序要分别编译。以后如有时间,我会写一个自动配置这些东西的脚本,目前只能用这样的方法将就运行一下。生成的图片在画图程序目录下,名字为“test.jpg”)
    用到的计算机图形学原理
    投影变换原理:在世界坐标系内构建物体,根据摄像机位置应用坐标变换,得到观察者坐标系;再利用投影矩阵得到观察到的图象。
    物体遮挡:根据z-buffer算法计算不同物体的次序,形成观察者看到的图象。

    <应用算法> 坐标变换、投影变换、z-buffer.
    主要代码实现原理一、类架构MyPoint:

    <变量> h-齐次坐标, x,y,z-三维空间位置;Distance-记录该点到观察点的距离;next-所有点组成的链表
    <函数> Assignment-复制另一个点Equal-判断两个点是否相等CalcDistance-计算距离
    MyLine:

    <变量> Start End – 起始、终止点;PointOnLine – 该直线上所有点next – 所有直线组成的链表<函数> BulidLine – 构建一条直线
    MyPlane:所有的平面都设定为三角形平面,简化类别

    <变量> Vertex-i 表示三个顶点;PointOnPlane 平面上所有点;next 一个物体中的所有平面<函数> IsExisted 判断某点是否出现在该平面上;
    MyObject:

    <变量> 记录点、线、面的数量;以链表形式存储点、线、面;存储物体颜色;<函数>添加 点、线、面。
    PointInfo:

    记录与投影平面相关的一些信息,包括某个点到投影平面的距离、该点的颜色。
    MyGraph:

    <变量> ObjectOfWorld – 世界坐标系中的物体MyView – 投影平面,设定大小是256*512;Camera – 记录摄像机的坐标;Delta – 表示摄像机在平动方向的移动距离;Rotationangle – 表示摄像机旋转的角度<函数> AddObject – 添加物体;Trans – 将其转化为图片输出。
    二、投影变换Projection:世界坐标系转换至观察者坐标系

    Displacement:摄像机平移

    Rotation:摄像机旋转

    三、进程机制为了使得每次有新的输入都会重新计算并更新图像,在主函数里采取了检查机制,每20ms检查一下输入文件里的内容是否改变,改变就执行绘图主函数,否则就等待。
    界面的编写界面用qt5编写,开发界面如下

    主要思路是start按钮用来执行第一遍画图程序,上下左右按钮调整观察点位置
    横向滑动条用来改变视角方向,垂直滑动条用来调整视角高低
    每次有动作就会更新视角角度,位置的xyz坐标等参数,写入二进制文本中,供画图程序重新画图,按钮滑动条的控制使用了qt的信号槽技术
    展示效果初始图像

    按↓平移

    再按←平移

    视角向左移动

    视角向上移动

    视角向下移动

    可改进的地方一开始写这个程序的时候没有考虑到内存的问题,“MyPoint”这个类设计的不好,投影点和原来的点是不同的对象,每次都要新建一个链表存这些对象,一幅256*512,三个几何体的图像占用内存25Mb左右,执行几十次内存就爆了。尝试过析构,但是因为中间不知道哪里写的有问题,强行析构会报运行错误。
    之后想到了更好的数据结构,让MyPoint类包含投影点坐标数据成员,这样不用新建链表,理论上内存不会变多,无论执行多少次都会维持在50Mb以下。但是由于时间仓促,而且改数据结构整个程序也要全部配合修改,没有来得及改动。打算暑假修改一下,这样可以让程序更流畅,而且显示的图形可以更多。
    改用新的数据结构后,理论上也可以应用更快的填充算法,图像可以做的分辨率更高而不占用更多资源。
    在倒数第二节课上的光线效果也提供了一个新思路,可以添加光源并计算物体表面的亮度,这个改动对于这个程序来说并不困难,也可以考虑加进来。
    还有就是图形界面与操作的优化,实际上用界面上提供的几个按钮与滑动条控制视角效果很奇怪,我在考虑换成直接在图像上拖拽的操作形式。
    以及应用上的改进,这个程序实际上有很强的应用性,可以模拟3D效果,目前想到的应用有3D魔方小游戏,4维几何体在三维空间投影的演示。
    0 评论 0 下载 2019-08-03 17:49:13 下载需要9点积分
  • 基于C语言的饭卡程序

    第1部分 实训题目与要求1. 问题提出饭堂用饭卡卖饭,不仅提高卖饭速度,还通过计算机管理,提高了管理效率和管理质量。
    2. 功能要求重复显示如图所示的主菜单,在主菜单中选择任意一项,均实现相应功能。

    在主菜单中选择1,建立名为card.dat的文件,并在其中添加若干人的饭卡号、姓名、金额、挂失信息,要求饭卡号是唯一的。
    在主菜单中选择2,要求用户输入饭卡号、饭费,然后系统自动从该人的饭卡中减去饭钱,并分别显示买饭前后的金额,如果原来饭卡中的余额不足5元,则不能买饭,而且显示“余额不够,请续钱!”,如果挂失信息为真,则显示“本卡已冻结!”。
    在主菜单中选择3,要求用户输入饭卡号、续钱额,续钱完成后分别显示续钱前后的金额。
    在主菜单中选择4,添加新饭卡,这时要求新饭卡号和已有的饭卡号不能重号。
    在主菜单中选择5,注销旧饭卡。
    在主菜单中选择6,要求用户输入饭卡号和挂失信息,然后更新该饭卡的挂失信息。
    在主菜单中选择7、8、9,此项功能学生自由发挥,根据本组爱好增加与本题目相关的新功能。
    在主菜单中选择0,显示结束信息(如“感谢使用本软件!已正常退出,按任意键结束!”),按任意键后,退出本系统。
    第2部分 设计实训题目功能1. 总体设计
    2.算法设计2.1 Input_Choice
    2.2 Build_File
    2.3 Creat_new
    2.4 Start_Card
    2.5 Insert_Card
    2.6 Use_Card
    2.7 Charge_Money
    2.8 Delete_Card
    2.9 Lost_Card
    2.10 Search_Card
    2.11 Sort_Card
    2.12 Print_Card
    2.13 Open_File&Close_File
    3. 数据结构#define C card_imf#define S struct#define I intS C{ long number; char name[20]; double money; I lost; S C *next;};
    在这个数据结构中,以long型定义的number表示饭卡号,char型定义的name代表学生的姓名,double型money代表饭卡中的余额,int型lost代表饭卡是否挂失。
    4. 程序代码设计4.1 Input_Choice用for循环+if\else语句把可视化框架打出来,接收用户的返回值赋给主函数中的switch语句。
    4.2 Build_File从无到有新建一个“card.dat”文件。
    4.3 Creat_new从内存上动态分配若干个长度为该结构数组的空间作为链表,把存储介质上 “card.dat”文件中的数据导入链表。
    4.4 Start_Card初次运行程序时输入的初始数据,由于不存在数据赋给头指针,若直接运行函数“Insert_Card”会造成错误,即群龙无首,所以增加“Start_Card”函数避免此问题。
    4.5 Insert_Card在通过“Start_Card”函数创建完成第一个结构数组的数据后,通过此函数创建更多的学生数据。
    4.6 Use_Card首先这个函数会调用“Check_Card”函数扫描一遍学生数据,判定该饭卡信息是否存在;如果不存在输出“饭卡不存在!”。如果存在,系统自动从该人的饭卡中减去饭钱,并分别显示买饭前后的金额,如果原来饭卡中的余额不足5元,或余额低于当前消费额,则不能买饭,并显示“余额不够,请续钱!”,以及如果挂失信息为真,则亦不能消费,并显示“本卡已冻结!”。
    4.7 Charge_Money首先这个函数会调用“Check_Card”函数扫描一遍学生数据,判定该饭卡信息是否存在;确定存在后会让用户输入充值额,充值后会显示充值前后的余额。以及如果挂失信息为真,则不能充值,并显示“本卡已冻结!”。
    4.8 Delete_Card首先这个函数会调用“Check_Card”函数扫描一遍学生数据,判定该饭卡信息是否存在;确定存在后使该行信息脱离链表,即删除该饭卡的信息,输出“旧饭卡注销成功!”。
    4.9 Lost_Card首先这个函数会调用“Check_Card”函数扫描一遍学生数据,判定该饭卡信息是否存在;确定存在后再输出此卡的挂失状态,由用户变更此卡的挂失状态。
    4.10 Search_Card首先这个函数会调用“Check_Card”函数扫描一遍学生数据,判定该饭卡信息是否存在;确定存在后输出该饭卡信息。
    4.11 Sort_Card由用户决定将所有信息升序&降序排列,程序将用“选择排序法”对所有链表信息进行排序,排完后将链表中的数据输出到“card.dat”文件。
    4.12 Print_Card遍历饭卡文件,输出到屏幕。
    4.13 Open_File&Close_File各函数打开“card.dat”文件的方式不同,由各函数传回的openmode决定以何种方式打开文件;开关文件若不成功,输出相应的提示语。
    5. 测试与调试


    测试数据类型
    测试数据合法性
    测试数据
    预期结果
    实测结果




    Input_Choice

    4
    跳转至Insert_Card或Start_Card函数
    跳转成功,下一步输入饭卡的详细信息


    Input_Choice

    10
    清屏
    清屏


    Use_Card

    任意数字(此时测试数据组饭卡余额为4)
    无法消费并弹出“余额不足,请充值!”字样
    与预期结果一致


    Sort_Card

    1
    所有饭卡数据降序排列,输出“已按照您的选项进行排列!”字样
    通过遍历函数输出后证明与预期结果一致


    Sort_Card

    3
    输出“请输入正确的选项编号”字样
    与预期结果一致


    Search_Card

    (输入一个文件中不存在的饭卡编号)
    输出“饭卡不存在!”字样
    与预期结果一致



    第3部分 实训总结
    通过宏定义有效减少了重复的定义名的输入,加快了编程效率;
    由于平时上课有认真听,课后也有更加深入地学习相关的编程知识,所以一路写下来基本没有遇到困难,唯一遇到的「群龙无首」问题也很快通过if-else语句解决了。
    本来想在遍历函数前写一个管理员身份验证的函数,但考虑到并没有什么卵用,毕竟“card.dat”整体未被加密,想看随时打开dat文件就能看了。再写一个验证步骤显得特别矫情。
    这里详细为大家讲解一下如何通过两个指针就能实现链表的冒泡排序:首先与对数组进行冒泡排序的思路一致,各相邻结构数组比较某个成员的大小,不符合当前大小排序条件的就两两互换;以按照饭卡号升序(由小到大)排列为例,整个链表中饭卡号最大的那个结构数组通过这样的交换会成为整个链表的最后成员,这样还剩余(所有成员数-1)个成员需要排列,这样使用双for语句嵌套循环即可完成对整个链表的排序。而指针扮演的是搬运工的角色:用p1、p2分别指向满足交换条件相邻的两个成员,然后把前一个成员的值赋给过渡成员temp,再让temp(前一个成员的值)的next指向后一个成员的next,再把后一个成员的值赋给前一个成员,把temp(前一个成员的值)的值赋给后一个成员,此时前后两个成员的值已经互换了,最后把前一个成员(值为之前的后一个成员)的next赋给后一个成员(值为之前的前一个成员)即可。这样p1、p2依然指向前后两个已经交换了位置的成员,相较于本人之前考虑直接断链再接时发生的p1、p2所指向的成员发生颠倒的情况,这种办法更为简洁有效。接下来p1、p2指向其对应的next,对下一组相邻的成员再次执行以上的成员交换,直到双循环结束。
    其实之前是想做出更好的可视化窗口的,但问了一圈各路编程大佬之后还是放弃了,他们异口同声地告诉我,现在学的C语言其实是在学核心算法,算法最重要,这些算法搞定了以后可以用其他比C更好的语言写可视化窗口。后来一想,其实道理确实是这样的,一开始我们可能做不出什么像模像样的软件,但这就是学习的必经之路,只有一步一个脚印扎扎实实把基础的编程思想学好了,以后才有能力去做那些复杂的工程。所以对于我个人而言,稍安勿躁,步步为营,把该学的学好才是重点,而不是急于求成地迫切想做出什么实质性的东西,就算做出来,也未必是最优的。
    0 评论 5 下载 2019-08-02 18:03:16 下载需要5点积分
  • 基于QT与mplayer的视频播放器

    一、课题的介绍和课题的任务1.1 课题的介绍本次课程设计我选的题目是视频播放器。目前市场上各种应用商店上有各种播放器,而且功能都很强大。一直对里面的具体实现有兴趣,所以这次就尝试着写了个视频播放器。并且加进去了一些很实用的功能,比如截屏和录屏。
    1.2 课题的任务包括视频的播放暂停、音量的加减、播放速度的设置、以及视频文件的添加删除、屏幕的截屏以及录屏。画面不卡顿。播放时进度条能刷新。
    二、设计的要求
    能进行视频的播放
    能暂停正在播放的视频
    能播放正在暂停的视频
    能调节视频播放的视频
    能进行视频播放进度的调节
    能停止正在播放的视频
    能添加新的视频文件到播放列表
    能删除播放列表中选中的视频
    能改变视频播放的速度
    能对正在播放的视频进行截屏
    能录制正在播放的视频

    三、系统的分析和系统中类的设计
    窗口类QMainWidndow
    按钮类QPushButton
    标签类QLabel
    列表类QList
    滑动条类QSilider
    显示类QWidge

    四、系统的实现及调试系统模块框架图

    程序具体实现
    4.1 添加文件进视频播放列表
    代码实现:
    void mplayer_video::on_open_clicked(){ QStringList filenames =QFileDialog::getOpenFileNames(this,tr("选择文件"),"/",tr("视频文件(*mp3 *mp4 *wma *3gp *wav *avi *flv *rmvb *mkv *ts *wmv)")); // *号和前面的要隔开至少一个空格,不能连起来。 if(filenames.count()!=0) ui->list->addItems(filenames);}
    4.2 双击列表选项进行播放
    代码实现:
    void mplayer_video::on_list_itemDoubleClicked(QListWidgetItem *item){ speed=1; ui->lupin_lable->setVisible(false); play(item->text());}void mplayer_video::play(QString fileName){ QStringList arg1; process->kill(); process=new QProcess(this); arg1 << fileName; arg1 << "-slave";//默认情况下,mplayer接受键盘的命令,而"-slave"使其不再接受键盘事件,而是作为后台程序运行, //接受以“\n”结束的命令控制,这样我们可以在进程中给他发送命令,而不需要操作键盘了. arg1 << "-quiet"; //尽可能的不打印播放信息 arg1 << "-zoom"; //视频居中,四周黑条,全屏播放 arg1 << "-wid" << QString::number((unsigned int)(ui->widget->winId())); // "-wid <窗口标识>" 是指让MPlayer依附于那个窗口, //ui->widget->winId() 这个指令就是用来获取widget的标识码 , //这样视频播放的时候,就在这个部件里播放,相当于给他固定起来。 connect(process,SIGNAL(readyReadStandardOutput()),this,SLOT(dataRecieve())); process->start(arg,arg1); //开始播放进程 ui->zanting->setText("暂停");}void mplayer_video::dataRecieve(){ process->write("get_time_length\n"); process->write("get_time_pos\n"); process->write("get_percent_pos\n"); while(process->canReadLine()) { QByteArray b=process->readLine(); if(b.startsWith("ANS_TIME_POSITION")) { b.replace(QByteArray("\n"),QByteArray("")); QString s(b); currentStr=s.mid(18); ui->horizontalSlider->setValue(s.mid(18).toFloat()); //更新进度条 } else if((b.startsWith("ANS_LENGTH"))) { b.replace(QByteArray("\n"),QByteArray("")); QString s(b); totalTime=s.mid(11); ui->label_time->setText(currentStr+"秒/"+totalTime+"秒 "); //显示时间进度 ui->horizontalSlider->setRange(0,s.mid(11).toFloat()); } else if((b.startsWith("ANS_PERCENT_POSITION"))) { b.replace(QByteArray("\n"),QByteArray("")); QString s(b); currentPercent=s.mid(21); ui->percentLabel->setText(currentPercent+"%"); } }}
    4.3 播放与暂停的实现
    代码实现:
    void mplayer_video::on_zanting_clicked(){ ui->lupin_lable->setVisible(false); process->write("pause\n"); //ui->list->currentRow()!=-1 判断是否有选中某条数据 //play(ui->list->item(ui->list->currentRow())->text()); 播放选中的某条数据 if(ui->zanting->text()=="播放") { if(ui->list->count()==0) QMessageBox::warning(this,"提示","播放列表为空",QMessageBox::Yes); else { connect(process,SIGNAL(readyReadStandardOutput()),this,SLOT(dataRecieve())); process->write("get_time_length\n"); process->write("get_time_pos\n"); process->write("get_percent_pos\n"); ui->zanting->setText("暂停"); } } else { disconnect(process,SIGNAL(readyReadStandardOutput()),this,SLOT(dataRecieve())); ui->zanting->setText("播放"); }}
    4.4 快进与回退代码实现:
    void mplayer_video::on_back_clicked(){ process->write("seek -10\n");}void mplayer_video::on_quick_clicked(){ process->write("seek +10\n");}
    4.5 加速与减速代码实现:
    void mplayer_video::on_back_clicked(){ process->write("seek -10\n");}void mplayer_video::on_quick_clicked(){ process->write("seek +10\n");}
    4.6 停止播放代码实现:
    void mplayer_video::on_stop_clicked(){ process->write("quit\n"); ui->horizontalSlider->setSliderPosition(0); ui->label_time->clear(); ui->percentLabel->clear(); ui->zanting->setText("播放");}
    4.7 从播放列表中删除中选中的视频
    代码实现:
    void mplayer_video::on_del_clicked(){ if(ui->list->currentRow()==-1) QMessageBox::warning(this,"提示","未选中项目或列表为空",QMessageBox::Yes); else { ui->list->takeItem(ui->list->currentRow()); process->close(); ui->horizontalSlider->setSliderPosition(0); //更新进度条 ui->label_time->clear(); ui->percentLabel->clear(); }}
    4.8 加速播放与减速播放
    代码实现:
    定义一个全局静态浮点型变量 speed并初始化为1,每次点击加速,speed的值乘以二,每次点击减速,speed的值除以2
    void mplayer_video::on_jiansu_clicked(){ speed=speed/2; process->write(QString("speed_set "+QString::number(speed)+" 2\n").toUtf8());}void mplayer_video::on_jiasu_clicked(){ speed=speed*2; process->write(QString("speed_set "+QString::number(speed)+" 2\n").toUtf8());}
    4.9 视频播放进度条的刷新这是本程序里最复杂的部分之一。
    主要实现是用connect函数链接进程与DataRecieve函数
    代码实现:
    void mplayer_video::dataRecieve(){ process->write("get_time_length\n"); process->write("get_time_pos\n"); process->write("get_percent_pos\n"); while(process->canReadLine()) { QByteArray b=process->readLine(); if(b.startsWith("ANS_TIME_POSITION")) { b.replace(QByteArray("\n"),QByteArray("")); QString s(b); currentStr=s.mid(18); ui->horizontalSlider->setValue(s.mid(18).toFloat()); //更新进度条 } else if((b.startsWith("ANS_LENGTH"))) { b.replace(QByteArray("\n"),QByteArray("")); QString s(b); totalTime=s.mid(11); ui->label_time->setText(currentStr+"秒/"+totalTime+"秒 "); //显示时间进度 ui->horizontalSlider->setRange(0,s.mid(11).toFloat()); } else if((b.startsWith("ANS_PERCENT_POSITION"))) { b.replace(QByteArray("\n"),QByteArray("")); QString s(b); currentPercent=s.mid(21); ui->percentLabel->setText(currentPercent+"%"); } }}
    4.10 声音滑动条对声音的调节
    代码实现:
    void mplayer_video::on_voice_slider_sliderMoved(int v){ if(ui->zanting->text()=="播放") { process->write(QString("volume "+QString::number(v)+" 2\n").toUtf8()); process->write("pause\n"); } else{ process->write(QString("volume "+QString::number(v)+" 2\n").toUtf8()); }}
    4.11 设置图片按钮
    代码实现:
    QPixmap pixmap; pixmap.load("G:/mplayer_video/voice.jpg"); ui->voice->setFixedSize(pixmap.width(),pixmap.height()); ui->voice->setIcon(pixmap); ui->voice->setIconSize(QSize(pixmap.width(),pixmap.height())); ui->voice->setToolTip("音量"); ui->voice->show();
    4.12 屏幕截图
    代码实现:
    void mplayer_video::on_jietu_clicked(){ cout<<"ok"<<endl; process->write("pause\n"); if(ui->zanting->text()=="播放") { cout<<"1"<<endl; QPixmap snapImage = QPixmap::grabWindow(QApplication::desktop()->winId()); QString filename; QString slcStr; filename = QFileDialog::getSaveFileName(this,tr("保存图片"),"./未命名",tr("PNG(*.png);;JPG(*.jpg);;BMP(*.bmp)"),&slcStr);//弹出保存图片的文件窗口 if(slcStr.left(3)=="JPG") { if(filename.right(3)!="jpg") { filename+=".jpg"; } } if(slcStr.left(3)=="PNG") { if(filename.right(3)!="png") { filename+=".png"; } } if(slcStr.left(3)=="BMP") { if(filename.right(3)!="bmp") { filename+=".bmp"; } } if(filename!=NULL) { snapImage.save(filename); } } else { cout<<"2"<<endl; disconnect(process,SIGNAL(readyReadStandardOutput()),this,SLOT(dataRecieve())); ui->zanting->setText("播放"); QPixmap snapImage = QPixmap::grabWindow(QApplication::desktop()->winId()); QString filename; QString slcStr; filename = QFileDialog::getSaveFileName(this,tr("保存图片"),"./未命名",tr("PNG(*.png);;JPG(*.jpg);;BMP(*.bmp)"),&slcStr);//弹出保存图片的文件窗口 if(slcStr.left(3)=="JPG") { if(filename.right(3)!="jpg") { filename+=".jpg"; } } if(slcStr.left(3)=="PNG") { if(filename.right(3)!="png") { filename+=".png"; } } if(slcStr.left(3)=="BMP") { if(filename.right(3)!="bmp") { filename+=".bmp"; } } if(filename!=NULL) { snapImage.save(filename); } connect(process,SIGNAL(readyReadStandardOutput()),this,SLOT(dataRecieve())); process->write("get_time_length\n"); process->write("get_time_pos\n"); process->write("get_percent_pos\n"); ui->zanting->setText("暂停"); }}
    4.13 屏幕录制代码实现:
    void mplayer_video::on_lupin_clicked(){ if(ui->lupin->text()=="录屏") { photoStart(); timer->start(50); ui->lupin->setText("停止"); } else { timer->stop(); ui->lupin->setText("录屏"); }}void mplayer_video::photoStart(){ QDir *d = new QDir(); QString dirName("D:\\video"); if(!d->exists(dirName)) { d->mkdir(dirName); }}void mplayer_video::timerUpdate(){ QPixmap p; QString dirNamee("D:\\video\\"); dirNamee=dirNamee+QString::number(number)+".jpg"; p = QPixmap::grabWindow(QApplication::desktop()->winId()); p.save(dirNamee); number+=1;}
    4.14 屏幕录屏播放代码实现:
    void mplayer_video::on_lupinstart_clicked(){ process->write("quit\n"); QString dirName("D:\\video"); qdir = new QDir(dirName); qdir->setSorting(QDir::Reversed|QDir::Time); list = qdir->entryInfoList(); number2=0; timer2->start(100);}void mplayer_video::on_stop_bofang_clicked(){ timer2->stop(); ui->lupin_lable->setVisible(false);}
    五、系统的使用说明打开程序,点击添加文件进行视频播放列表视频的添加。双击列表中某条记录进行视频的播放,播放按钮自动转换成暂停按钮。点击播放将会播放视频,点击暂停视频会暂停。除了一些视频播放器的基本功能外,本程序还加入了屏幕截图与屏幕录制的功能。具体操作用按钮可以实现。
    1 评论 109 下载 2018-11-15 11:06:06 下载需要8点积分
  • 基于javascript的银行家算法

    1. 实验目的加深了解死锁概念,体会产生死锁的原因,掌握避免死锁的具体实施方法。
    2. 实验内容编写一个系统动态分配资源的模拟程序,采用银行家算法有效地避免死锁的发生。要求程序能够在进程提出资源申请后判断系统是否处于安全状态,如果安全则打印资源分配表和安全序列;如果不安全则输出不能分配的提示。提示:

    银行家算法可参阅教材和课件。
    利用文件读写操作配置系统状态。
    利用动态内存分配解决资源和进程数量动态变化的问题。

    3. 系统开发和运行环境


    操作系统
    Windows 7




    编程语言及工具
    JavaScript(jQuery),IE9以上/FireFox/ Chrome


    配置文件
    文件目录下的testfile.txt


    备注



    4. 程序设计4.1 数据结构var Max = []var Allocation = []var Need = []var Resourcevar Availablevar Requestvar safe = []var Work_Allocation = []var P = ['P0', 'P1', 'P2', 'P3', 'P4']function run() { Work_Allocation = [] //可分配资源+进程释放的已分配资源 Max = getMaxArr() //最大需求资源 Allocation = getAllocationArr() //已分配资源 Need = getNeedArr(Max, Allocation) //需求资源 Resource = getResource() //总资源数 Available = getAvailable() //可利用资源 Request = getRequest() //请求资源}

    可利用资源向量Available。这是一个数组对象,其中的每一个属性代表一类可利用资源数目,其初始值是系统中所配置的该类全部可用资源的数目,其数值随该类资源的分配和回收而动态的改变。如果Available.j=K,则表示系统中现有Rj类资源K个。
    最大需求矩阵Max。这是一个n*m的矩阵,它定义了系统中n个进程中的每一个进程对m类资源的最大需求。如果Max[i].j=K;则表示进程i需要Rj类资源的最大数目为K。
    分配矩阵Allocation。这也是一个n*m的矩阵,它定义了系统中每一类资源当前已分配给每一进程的资源数。如果Allocation[i].j=K,则表示进程i当前已分得Rj类资源的数目为K。
    需求矩阵Need。这也是一个n*m的矩阵,用以表示每一个进程尚需的各类资源数。如果Need[i,j]=K,则表示进程i还需要Rj类资源K个,方能完成任务。

    上述三个矩阵间存在下述关系:Need[i].j=Max[i].j-Allocation[i].j
    4.2 主要算法设计

    5. 程序运行演示5.1 初始化页面
    5.2 读取文件数据点击

    选择testfile.txt文件

    输出结果:

    5.3 选择进程并输入请求资源数量
    输出结果:

    5.4 重置点击重置按钮

    输出结果:

    5.5 清空点击清空按钮

    输出结果:

    6. 实验总结
    用前端的html+bootstrap+javascript+jquery完成此次实验。
    支持文件的读取操作,以文本方式读取数据。
    用bootstrap渲染页面,简洁美观。
    从文件加载数据时采用了动态内存分配方式。
    用jQuery操作DOM对象,代码量减少。
    0 评论 1 下载 2019-08-01 12:59:05 下载需要10点积分
  • 基于HTML5实现的网页汽车商店

    摘 要随着人们生活质量的提高,有车的人是越来越多,无论你是有钱人还是没钱人,要么就是去买车,要么就是在买车的路上。而在当前,互联网在人们生活中的应用越来越频繁,死守传统的销售模式而不拥抱互联网的销售手段,将越来越难以打开销量。在移动互联网的时代,将销售模式与互联网结合起来的汽车销售网页的设计,使得人们可以更加方便地了解各类汽车信息和更加方便地购买汽车产品。这次的汽车商店网页设计,是以汽车及其配件的销售为题材,用HTML5及相关手段制作的一个网上汽车销售的网页。文章先介绍了前端技术的起源历史与发展以及未来前景,然后详细介绍了制作过程,最后总结这次的制作心得。
    关键字:网页;HTML5;汽车
    一、背景通过网络进行汽车销售,是这个时代发展的必然结果,是随着网络的普及和电子商务概念的兴盛而兴起的。这种全新出现的新型汽车销售形式,与传统通过4s店面进行销售的方式相比优势显著:

    降低了汽车销售成本
    改变汽车传统的了解和购买方式,使用网络平台了解汽车信息并购买,使得商业活动没有空间和时间的限制
    汽车信息的传递更有效率和直观,新车信息上传后,人们可以立即了解咨询,交易可以马上进行,从而大大提高了汽车交易的效率

    正是由于这些巨大的优势,汽车商店网页才能得以迅速地开拓市场。汽车商店网页主要是借助网页作为交易平台,将汽车的各项指标,优势劣势,精美图片发布到网络上,人们能够借助网络登录汽车商店网页来查看各种汽车的信息并提交订单或者预定汽车,实现在线交易。
    二、前端开发技术的起源及历史所谓前端是指针对浏览器的开发,代码在浏览器运行。而与之相对的后则是针对服务器的开发,代码在服务器运行。然而在互联网发展的早期,前后端开发是一体的,前端代码是后端代码的一部分。
    早在1991年的时候HTML就已经作为前端开发的统一语言,HTML代码部门其实很简单,任何一款浏览器在打开任意网页后检查页面源代码,就可以看到由很多不同的标识表记标帜加上中间的标识表记标帜名构成的标识表记标帜的作用只有一个,就是格式化的内容,例如文字的大小、颜色、位置等,以达到网站制作者想要表达的展示效果。所以网页的早期形态大都完全基于HTML页面,并且所有内容都是静态的。
    HTML5中的5代表版本号,可以简单地理解为第五代HTML尺度,实际在此之前有非常多的非主流版本的更新,不过这一代尺度提出了很多重大的功能更新。例如:Canvas标识表记标帜,轻松地实现网页动画与游戏;直接的多媒体支持,不再需要FLASH来提供多媒体内容;WebSocket,使得用户可以不借助任何额外的插件就能够通过网页来制作游戏及其他软件。H5的诞生不是巧合也不是人为炒作,而是历史的一定选择,这是历史的潮流,不能否认当今是互联网飞速发展的年代。
    三、HTML5的国内外发展现状与前景3.1 HTML5存在的意义HTML5的优点即是“一次性开发,多次分发”,它使得一次设计适应不同终端成为可能。信息流架构应用化都是直接在WEB端抓取数据,而HTML5可以直接使用跨平台数据面不使用后台API,大大降低了研发维护成本而且呈现的效果几乎没有什么区别。HTML5最大的意义在于改变WEB文档的结构方式,借助于header, foot, section, article这些标配、标签我们可以实现更具结构化语义化的WEB文档。这样,搜索引擎更容易索引到WEB站点,我们可以搜索到更快更准备的信息。HTML5的诞生,来自对浏览器和网页开发技术的改进,是一系列Web标准草案的集合。它不仅仅局限于HTML语言本身,还包括了CSS3以及JavaScript语言里新增的函数和功能。HTML5始终坚持不断发展,并很快得到广泛认可,这与其在制定之初就确立的核心理念有很大的关系。这些核心理念就是我们今天在W3C站点上所看到的HTML5设计原理这份文档,概括起来就是——兼容性、实用性、互操作性以及普遍可访问性。
    3.2 HTML5的国内外发展现状酷炫、快速、跨平台,在HTML5出现前,这些词从未这样紧紧与网页相关联在一起。HTML5改变了人们脑海中对传统网页的印象,取而代之的是堪比桌面程序和移动原生应用程序的用户体验。相比HTML4,现在的网页可以做到的显然要更多:音频、视频不再需要插件的支持,避免插件安装失败等可能导致的问题;JavaScript能力大为增强,借助HTML中新增的Canvas元素,更是能在网页中进行2D和3D图形、图像的实时绘制;CSS3的强大和良好的支持度让网页变得更加生动,同时还可以利用浏览器本身的硬件加速完成transition、animation等动画效果以及合成;网页还可以直接通过JavaScript访问摄像头、陀螺仪等等硬件设备。等等这些,所有的目的只有一个——让网页可以做得和原生应用一样强大、一样优秀。美国的HTML5市场经过数十年的长期发展之后,早进入理性的状态,不是炒作概念或者单纯的市场宣讲活动,甚至关注度出现了下降,已经变成了在web技术各个独立领域深度探索和创新。而中国的HTML5市场在2015年的才出现第一次的火热状态,相比于美国市场出现了更进一步的延后。
    3.3 HTML5的发展前景随着HTML5技术的发展,越来越多的商家倾向于基于HTML5的游戏开发。我国拥有世界上较大的游戏市场、最多的游戏用户,然而在游戏的研发以及发行上与国际市场仍有差距。目前很多HTML5游戏发行商在找靠谱的合作伙伴和产品,优质产品是现阶段的稀缺资源,这也算是当下HTML5游戏的一个市场机遇。此外,HTML5是移动互联网前端的主流开发语言,目前还没有任何一个前端的开发语言能取代HTML5的位置,无论做手机网站还是手机app应用,前端的样式都是HTML5开发,通过手机与电脑上网的使用率来看,目前通过手机上网的用户远远高于电脑端,这些数据都足以证明未来的移动互联网的发展前景,而HTML5又作为移动互联网主流前端开发语言,所以HTML5的发展前景一片光明。
    四、设计思想这次的网页汽车商店以汽车及其配件的销售为题材,制作的一个网上汽车销售的网页。
    4.1 网页的整体设计网页的整体设计采用了课堂上学的划分区域的方式,并且采用了div + css 的排版,使得整个页面的样式丰富多彩,形式多种多样。即使同样的素材,也可以通过css不同的设置而变得多彩。同时css还将页面的版式固定,不会因为显示器的大小的变化而变化,而使得页面的兼容性增加。

    4.2 “广告”的引入为了丰富网页的多样性,使得汽车销售网页更加真实化,我还在网页的左右两边、右上脚以及中间适当处添加了广告,当然,仅仅是相应的图片。

    4.3 登录注册页面 登录和注册页面使用了javascript脚本语言,帐户名验证和密码验证,使得网站在运行时的数据交换率减少,也在一定程度上提高了网页的加载速度。同时使用javascript还能做出更多丰富多彩的,页面特效,使得页面更加绚丽。



    五、部分实现代码及注释5.1 网页中汽车外饰用品的罗列<div id="mymall" class="fl bcolor2"> <ul><h3><a name="B">外饰用品<sup><img src="../images/xinpin.gif" /></sup></a></h3> <hr width="90%"/> <li><a href="#" target="_blank"><p>车衣</p></a></li> <li><a href="#" target="_blank"><p>车贴</p></a></li> <li><a href="#" target="_blank"><p>防滑链</p></a></li> <li><a href="#" target="_blank"><p>汽车贴膜</p></a></li> <li><a href="#" target="_blank"><p>爆闪灯</p></a></li> <li><a href="#" target="_blank"><p>车牌架</p></a></li> <li><a href="#" target="_blank"><p>车标</p></a></li> <li><a href="#" target="_blank"><p>密封条</p></a></li> <li><a href="#" target="_blank"><p>晴雨挡</p></a></li> <li><a href="#" target="_blank"><p>保险杠</p></a></li> <li><a href="#" target="_blank"><p>涡轮</p></a></li> <li><a href="#" target="_blank"><p>内车轮</p></a></li> </ul></div>
    5.2 网页中汽车内饰用品的罗列<div id="mymall" class="fl bcolor1"> <ul><h3><a name="A">内饰用品<sup><img src="../images/xinpin.gif" /></sup></a></h3> <hr width="90%"/> <li><a href="#" target="_blank"><p>汽车坐垫</p></a></li> <li><a href="#" target="_blank"><p>汽车座套</p></a></li> <li><a href="#" target="_blank"><p>方向盘套</p></a></li> <li><a href="#" target="_blank"><p>汽车脚垫</p></a></li> <li><a href="#" target="_blank"><p>汽车香水</p></a></li> <li><a href="#" target="_blank"><p>汽车挂件</p></a></li> <li><a href="#" target="_blank"><p>儿童座椅</p></a></li> <li><a href="#" target="_blank"><p>汽车摆件</p></a></li> <li><a href="#" target="_blank"><p>车钥匙扣</p></a></li> <li><a href="#" target="_blank"><p>车置物箱</p></a></li> <li><a href="#" target="_blank"><p>后备箱垫</p></a></li> <li><a href="#" target="_blank"><p>车灭火器</p></a></li> <li><a href="#" target="_blank"><p>防静电物</p></a></li> <li><a href="#" target="_blank"><p>小套饰</p></a></li> </ul> </div>
    5.3 网页中立体滚动球的制作<div id="qiu" class="bcolor fr"> <a href="#A">内饰用品<sup><img src="../images/rexiao.gif"</sup></sup></a> <a href="#A">汽车坐垫<sup><img src="../images/rexiao.gif"</sup></sup></a> <a href="#A">汽车座套</a> <a href="#A">方向盘套</a> <a href="#A">汽车挂件<sup><img src="../images/xinpin.gif" /></sup></a> <a href="#A">车灭火器</a> <a href="#A">小套饰<sup><img src="../images/xinpin.gif" /></sup></a> <a href="#A">防静电饰品<sup><img src="../images/xinpin.gif" /></sup></a> <a href="#A">汽车摆件</a> <a href="#A">车钥匙扣<sup><img src="../images/xinpin.gif" /></sup></a> <a href="#B">车衣</a> <a href="#B">车贴<sup><img src="../images/xinpin.gif" /></sup></a> <a href="#B">防滑链</a> <a href="#B">汽车贴膜</a> <a href="#B">爆闪灯</a> <a href="#B">车牌架</a> <a href="#B">车标</a> <a href="#B">密封条</a> <a href="#B">晴雨挡</a> <a href="#B">保险杠</a> <a href="#B">涡轮<sup><img src="../images/rexiao.gif" /></sup></a> <a href="#B">内车轮</a> <a href="#C">涡轮增压</a> <a href="#C">后视灯<sup><img src="../images/rexiao.gif" /></sup></a> <a href="#C">雪地胎</a> <a href="#C">疝气灯<sup><img src="../images/xinpin.gif" /></sup></a> <a href="#C">日行灯</a> <a href="#C">挡泥板</a> <a href="#C">行李架</a> <a href="#C">车位锁</a> <a href="#C">鲨鱼鳍</a> <a href="#C">倒车灯</a> <a href="#C">尾翼</a> <a href="#C">发动机护板</a> </div>
    六、制作心得通过此次网页制作的过程,我学到了很多,首先我学会了HTML网页制作语言,虽然我学到的仅仅只是一部分,但是我明白了作为网页设计语言,HTML5的强大之处,使得我对这门语言的看法发生了根本性的转变,希望可以接触到更多的关于这方面的知识。当然在网页制作的过程中,我也遇到了许许多多的问题,但是通过不懈的努力,以及同学们的互帮互助,使我克服了这些困难。更多的希望在以后的学习和生活中我都会像在这次制作设计中一样,帮助别人,请教别人。希望老师在我学习的过程中多批评、多指教,感谢老师对我的教导。
    七、不足之处这次的网页汽车商店的设计,整体的设计思想是很完善的,但是由于水平有限、经验不足等,制作出来的成品还是存在这样或那样的瑕疵。比如,虽然我在网页的顶端加上了一个搜索栏,但是具体的搜索功能还有待完善;其次,右上角的购物车、我的车库以及联系客服栏目还没具体的实现……不过,这次的网页设计极大的唤起了我对网页设计的热情,从而也使我的个人技术进一步的提升。
    八、参考文献[1] 邢增智,郭龙,杜豪,刘顺林,彭永凤,段兴悦。 基于HTML5与CSS3的工业物联网工程中心网站开发[J]. 物联网技术,2017,(03):92-93+97.
    [2] 郭鲁。 基于HTML5的Web App前端开发的前景分析[J]. 南方农机,2017,(02):92.
    [3] 盛婷婷。 基于HTML5技术的移动Web前端设计与开发分析[J]. 电子制作,2016,(19):46-47+75.
    [4] 王燕妮。 HTML5应用现状分析[J]. 无线互联科技,2016,(13):28-29.
    0 评论 1 下载 2019-07-31 09:55:02 下载需要9点积分
  • 基于C++实现公司职工管理系统

    1、管理系统需求职工管理系统可以用来管理公司内所有员工的信息,教程主要利用C++来实现一个基于多态的职工管理系统。
    公司中职工分为三类:普通员工、经理、老板,显示信息时,需要显示职工编号、职工姓名、职工岗位、以及职责

    普通员工职责:完成经理交给的任务
    经理职责:完成老板交给的任务,并下发任务给员工
    老板职责:管理公司所有事务

    管理系统中需要实现的功能如下:

    退出管理程序:退出当前管理系统
    增加职工信息:实现批量添加职工功能,将信息录入到文件中,职工信息为:职工编号、姓名、部门编号
    显示职工信息:显示公司内部所有职工的信息
    删除离职职工:按照编号删除指定的职工
    修改职工信息:按照编号修改职工个人信息
    查找职工信息:按照职工的编号或者职工的姓名进行查找相关的人员信息
    按照编号排序:按照职工编号,进行排序,排序规则由用户指定
    清空所有文档:清空文件中记录的所有职工信息 (清空前需要再次确认,防止误删)

    系统界面效果图如下:

    2、创建项目创建项目步骤如下:

    创建新项目
    添加文件

    3、创建管理类管理类负责的内容如下:

    与用户的沟通菜单界面
    对职工增删改查的操作
    与文件的读写交互

    3.1 创建文件在头文件和源文件的文件夹下分别创建workerManager.h 和 workerManager.cpp文件
    3.2 头文件实现在workerManager.h中设计管理类
    代码如下:
    #pragma once#include<iostream>using namespace std;class WorkerManager{public: //构造函数 WorkerManager(); //析构函数 ~WorkerManager();};
    3.3 源文件实现在workerManager.cpp中将构造和析构函数空实现补全
    #include "workerManager.h"WorkerManager::WorkerManager(){}WorkerManager::~WorkerManager(){}
    4、菜单功能功能描述:与用户的沟通界面
    4.1 添加成员函数在管理类workerManager.h中添加成员函数 void Show_Menu();
    4.2 菜单功能实现在管理类workerManager.cpp中实现 Show_Menu()函数
    void WorkerManager::Show_Menu(){ cout << "********************************************" << endl; cout << "********* 欢迎使用职工管理系统! **********" << endl; cout << "************* 0.退出管理程序 *************" << endl; cout << "************* 1.增加职工信息 *************" << endl; cout << "************* 2.显示职工信息 *************" << endl; cout << "************* 3.删除离职职工 *************" << endl; cout << "************* 4.修改职工信息 *************" << endl; cout << "************* 5.查找职工信息 *************" << endl; cout << "************* 6.按照编号排序 *************" << endl; cout << "************* 7.清空所有文档 *************" << endl; cout << "********************************************" << endl; cout << endl;}
    4.3 测试菜单功能在职工管理系统.cpp中测试菜单功能
    代码:
    #include<iostream>using namespace std;#include "workerManager.h"int main() { WorkerManager wm; wm.Show_Menu(); system("pause"); return 0;}
    5、退出功能5.1 提供功能接口在main函数中提供分支选择,提供每个功能接口
    代码:
    int main() { WorkerManager wm; int choice = 0; while (true) { //展示菜单 wm.Show_Menu(); cout << "请输入您的选择:" << endl; cin >> choice; switch (choice) { case 0: //退出系统 break; case 1: //添加职工 break; case 2: //显示职工 break; case 3: //删除职工 break; case 4: //修改职工 break; case 5: //查找职工 break; case 6: //排序职工 break; case 7: //清空文件 break; default: system("cls"); break; } } system("pause"); return 0;}
    5.2 实现退出功能在workerManager.h中提供退出系统的成员函数 void exitSystem();
    在workerManager.cpp中提供具体的功能实现
    void WorkerManager::exitSystem(){ cout << "欢迎下次使用" << endl; system("pause"); exit(0);}
    6、创建职工类6.1 创建职工抽象类职工的分类为:普通员工、经理、老板
    将三种职工抽象到一个类(worker)中,利用多态管理不同职工种类
    职工的属性为:职工编号、职工姓名、职工所在部门编号
    职工的行为为:岗位职责信息描述,获取岗位名称
    头文件文件夹下 创建文件worker.h 文件并且添加如下代码:
    #pragma once#include<iostream>#include<string>using namespace std;//职工抽象基类class Worker{public: //显示个人信息 virtual void showInfo() = 0; //获取岗位名称 virtual string getDeptName() = 0; int m_Id; //职工编号 string m_Name; //职工姓名 int m_DeptId; //职工所在部门名称编号};
    6.2 创建普通员工类普通员工类继承职工抽象类,并重写父类中纯虚函数
    在头文件和源文件的文件夹下分别创建employee.h 和 employee.cpp文件
    employee.h中代码如下:
    #pragma once #include<iostream>using namespace std;#include "worker.h"//员工类class Employee :public Worker{public: //构造函数 Employee(int id, string name, int dId); //显示个人信息 virtual void showInfo(); //获取职工岗位名称 virtual string getDeptName();};
    employee.cpp中代码如下:
    #include "employee.h"Employee::Employee(int id, string name, int dId){ this->m_Id = id; this->m_Name = name; this->m_DeptId = dId;}void Employee::showInfo(){ cout << "职工编号: " << this->m_Id << " \t职工姓名: " << this->m_Name << " \t岗位:" << this->getDeptName() << " \t岗位职责:完成经理交给的任务" << endl;}string Employee::getDeptName(){ return string("员工");}
    6.3 创建经理类经理类继承职工抽象类,并重写父类中纯虚函数,和普通员工类似
    在头文件和源文件的文件夹下分别创建manager.h 和 manager.cpp文件
    manager.h中代码如下:
    #pragma once#include<iostream>using namespace std;#include "worker.h"//经理类class Manager :public Worker{public: Manager(int id, string name, int dId); //显示个人信息 virtual void showInfo(); //获取职工岗位名称 virtual string getDeptName();};
    manager.cpp中代码如下:
    #include "manager.h"Manager::Manager(int id, string name, int dId){ this->m_Id = id; this->m_Name = name; this->m_DeptId = dId;}void Manager::showInfo(){ cout << "职工编号: " << this->m_Id << " \t职工姓名: " << this->m_Name << " \t岗位:" << this->getDeptName() << " \t岗位职责:完成老板交给的任务,并下发任务给员工" << endl;}string Manager::getDeptName(){ return string("经理");}
    6.4 创建老板类老板类继承职工抽象类,并重写父类中纯虚函数,和普通员工类似
    在头文件和源文件的文件夹下分别创建boss.h 和 boss.cpp文件
    boss.h中代码如下:
    #pragma once#include<iostream>using namespace std;#include "worker.h"//老板类class Boss :public Worker{public: Boss(int id, string name, int dId); //显示个人信息 virtual void showInfo(); //获取职工岗位名称 virtual string getDeptName();};
    boss.cpp中代码如下:
    #include "boss.h"Boss::Boss(int id, string name, int dId){ this->m_Id = id; this->m_Name = name; this->m_DeptId = dId;}void Boss::showInfo(){ cout << "职工编号: " << this->m_Id << " \t职工姓名: " << this->m_Name << " \t岗位:" << this->getDeptName() << " \t岗位职责:管理公司所有事务" << endl;}string Boss::getDeptName(){ return string("总裁");}
    6.5 测试多态在职工管理系统.cpp中添加测试函数,并且运行能够产生多态
    测试代码如下:
    #include "worker.h"#include "employee.h"#include "manager.h"#include "boss.h"void test(){ Worker * worker = NULL; worker = new Employee(1, "张三", 1); worker->showInfo(); delete worker; worker = new Manager(2, "李四", 2); worker->showInfo(); delete worker; worker = new Boss(3, "王五", 3); worker->showInfo(); delete worker;}
    7、添加职工功能描述:批量添加职工,并且保存到文件中
    7.1 功能分析分析:
    用户在批量创建时,可能会创建不同种类的职工
    如果想将所有不同种类的员工都放入到一个数组中,可以将所有员工的指针维护到一个数组里
    如果想在程序中维护这个不定长度的数组,可以将数组创建到堆区,并利用Worker **的指针维护
    7.2 功能实现在WokerManager.h头文件中添加成员属性 代码:
    //记录文件中的人数个数 int m_EmpNum; //员工数组的指针 Worker ** m_EmpArray;
    在WorkerManager构造函数中初始化属性
    WorkerManager::WorkerManager(){ //初始化人数 this->m_EmpNum = 0; //初始化数组指针 this->m_EmpArray = NULL;}
    在workerManager.h中添加成员函数
    //增加职工 void Add_Emp();
    在WorkerManager.cpp的析构函数中,释放堆区数据
    WorkerManager::~WorkerManager(){ if (this->m_EmpArray != NULL) { delete[] this->m_EmpArray; }}
    8、文件交互 - 写文件功能描述:对文件进行读写

    在上一个添加功能中,我们只是将所有的数据添加到了内存中,一旦程序结束就无法保存了
    因此文件管理类中需要一个与文件进行交互的功能,对于文件进行读写操作

    8.1 设定文件路径首先我们将文件路径,在workerManager.h中添加宏常量,并且包含头文件 fstream
    #include <fstream>#define FILENAME "empFile.txt"
    8.2 成员函数声明在workerManager.h中类里添加成员函数 void save()
    //保存文件void save();
    8.3 保存文件功能实现void WorkerManager::save(){ ofstream ofs; ofs.open(FILENAME, ios::out); for (int i = 0; i < this->m_EmpNum; i++) { ofs << this->m_EmpArray[i]->m_Id << " " << this->m_EmpArray[i]->m_Name << " " << this->m_EmpArray[i]->m_DeptId << endl; } ofs.close();}
    9、文件交互 - 读文件功能描述:将文件中的内容读取到程序中
    虽然我们实现了添加职工后保存到文件的操作,但是每次开始运行程序,并没有将文件中数据读取到程序中
    而我们的程序功能中还有清空文件的需求
    因此构造函数初始化数据的情况分为三种

    第一次使用,文件未创建
    文件存在,但是数据被用户清空
    文件存在,并且保存职工的所有数据

    9.1 文件未创建在workerManager.h中添加新的成员属性 m_FileIsEmpty标志文件是否为空
    //标志文件是否为空 bool m_FileIsEmpty;
    修改WorkerManager.cpp中构造函数代码
    WorkerManager::WorkerManager(){ ifstream ifs; ifs.open(FILENAME, ios::in); //文件不存在情况 if (!ifs.is_open()) { cout << "文件不存在" << endl; //测试输出 this->m_EmpNum = 0; //初始化人数 this->m_FileIsEmpty = true; //初始化文件为空标志 this->m_EmpArray = NULL; //初始化数组 ifs.close(); //关闭文件 return; }}
    删除文件后,测试文件不存在时初始化数据功能
    9.2 文件存在且数据为空在workerManager.cpp中的构造函数追加代码:
    //文件存在,并且没有记录 char ch; ifs >> ch; if (ifs.eof()) { cout << "文件为空!" << endl; this->m_EmpNum = 0; this->m_FileIsEmpty = true; this->m_EmpArray = NULL; ifs.close(); return; }
    9.3 文件存在且保存职工数据9.3.1 获取记录的职工人数在workerManager.h中添加成员函数 int get_EmpNum();
    //统计人数 int get_EmpNum();
    在workerManager.cpp构造函数中继续追加代码:
    int num = this->get_EmpNum(); cout << "职工个数为:" << num << endl; //测试代码 this->m_EmpNum = num; //更新成员属性
    9.3.2 初始化数组根据职工的数据以及职工数据,初始化workerManager中的Worker ** m_EmpArray 指针
    在WorkerManager.h中添加成员函数 void init_Emp();
    //初始化员工 void init_Emp();
    10、显示职工功能描述:显示当前所有职工信息
    10.1 显示职工函数声明在workerManager.h中添加成员函数 void Show_Emp();
    //显示职工 void Show_Emp();
    11、删除职工功能描述:按照职工的编号进行删除职工操作
    11.1 删除职工函数声明在workerManager.h中添加成员函数 void Del_Emp();
    //删除职工 void Del_Emp();
    11.2 职工是否存在函数声明很多功能都需要用到根据职工是否存在来进行操作如:删除职工、修改职工、查找职工
    因此添加该公告函数,以便后续调用
    在workerManager.h中添加成员函数 int IsExist(int id);
    //按照职工编号判断职工是否存在,若存在返回职工在数组中位置,不存在返回-1 int IsExist(int id);
    11.3 职工是否存在函数实现在workerManager.cpp中实现成员函数 int IsExist(int id);
    int WorkerManager::IsExist(int id){ int index = -1; for (int i = 0; i < this->m_EmpNum; i++) { if (this->m_EmpArray[i]->m_Id == id) { index = i; break; } } return index;}
    12、修改职工功能描述:能够按照职工的编号对职工信息进行修改并保存
    12.1 修改职工函数声明在workerManager.h中添加成员函数 void Mod_Emp();
    //修改职工 void Mod_Emp();
    13、查找职工功能描述:提供两种查找职工方式,一种按照职工编号,一种按照职工姓名
    13.1 查找职工函数声明在workerManager.h中添加成员函数 void Find_Emp();
    //查找职工 void Find_Emp();
    14、排序功能描述:按照职工编号进行排序,排序的顺序由用户指定
    14.1 排序函数声明在workerManager.h中添加成员函数 void Sort_Emp();
    //排序职工 void Sort_Emp();
    15、清空文件功能描述:将文件中记录数据清空
    15.1 清空函数声明在workerManager.h中添加成员函数 void Clean_File();
    //清空文件 void Clean_File();
    0 评论 3 下载 2019-07-26 17:22:01 下载需要15点积分
  • 仿天猫电子商务(含前端后台数据库)

    一、基础1.1 项目简介1.1.1 基于J2EE整套技术本项目没有使用SSH,SSM框架,而是使用J2EE整套技术来作为解决方案,实现各种业务场景。在项目中借助反射等技术,采用了精妙的设计模式,开发效率并不低于使用框架。
    1.1.2 典型场景一个完整的J2EE应用包含的各种典型商务应用场景的需求,展示相应的解决思路与办法
    1.2 开发流程1.2.1 技术准备
    Java:java基础和java中级的内容
    前端:html,css,js,jquery
    J2EE:tomcat,servlet,jsp,filter
    数据库:mysql

    1.2.2 开发流程模仿天猫整站是一个比较大的项目,将按照商业项目的开发流程有条不紊的一一展开:
    1.2.2.1 需求分析首先确定要做哪些功能,需求分析包括前台和后台。前台又分为单纯要展示的那些功能-需求分析-展示,以及会提交数据到服务端的哪些功能-需求分析-交互。
    1.2.2.2 表结构设计接着是表结构设计,表结构设计是围绕功能需求进行,如果表结构设计有问题,那么将会影响功能的实现。除了表与表关系,建表SQL语句之外,为了更好的帮助大家理解表结构以及关系,还特意把表与页面功能一一对应起来
    1.2.2.3 原型接着是界面原型,与客户沟通顺畅的项目设计流程里一定会有原型这个环节。 借助界面原型,可以低成本,高效率的与客户达成需求的一致性。 同样的,原型分为了前台原型和后台原型。
    1.2.2.4 实体类设计接着开始实体类的设计与开发,实体类不仅仅是对数据库中的表的一一映射,同时还需要兼顾对业务功能的支持。
    1.2.2.5 DAO类设计然后是DAO类的设计,除了进行典型的ORM支持功能之外,也需要提供各种业务方法。
    1.2.2.6 业务类介绍讲解的业务类的概念,以及为什么在本项目中没有包含这一层
    1.2.2.7 后台-分类管理接下来开始进行功能开发,按照模块之间的依赖关系,首先进行后台-分类管理功能开发。严格来说,这是开发的第一个功能,所以讲解的十分详细,不仅提供了可运行的项目,还详细解释了其中用到的设计模式,JSP包含关系,以及每个具体的功能: 查询,分页,增加,删除,编辑,修改。 把每个细节都掰的很细,可以更好的理解,消化和吸收。 在把后台-分类管理 吃透之后,后续的其他后台管理功能,做起来就会更加顺畅。
    1.2.2.8 后台-其他管理在把后台-分类管理 消化吸收之后,就可以加速进行 后台其他页面的学习。
    1.2.2.9 前台-首页前台也包括许多功能, 与后台-分类管理类似的,首先把前台-首页这个功能单独拿出来,进行精讲。前台-首页 消化吸收好之后,再进行其他前台功能的开发。
    1.2.2.10 前台无需登录从前台模块之间的依赖性,以及开发顺序的合理性来考虑,把前台功能分为了 无需登录 即可使用的功能,和需要登录 才能访问的功能。 建立在前一步前台-首页的基础之上,开始进行一系列的无需登录功能开发。
    1.2.2.11 前台需要登录最后是需要登录的前台功能。 这部分功能基本上都是和购物相关的。 因此,一开始先把购物流程 单独拿出来捋清楚,其中还特别注明了购物流程环节与表关系,这样能够更好的建立对前端购物功能的理解。随着这部分功能的开发,就会进入订单生成部分,在此之前,先准备了一个 订单状态图,在理解了这个图之后,可以更好的进行订单相关功能的开发。
    1.2.2.12 总结最后总结整个项目的项目结构,都实现了哪些典型场景,运用了哪些设计模式,把学习到的知识都沉淀下来,转换,消化,吸收为自己的技能。
    二、需求分析2.1 概述以下需求都是基于模仿天猫整站整理出来的,主要分为3类:
    2.1.1 前端展示在前端页面上显示数据库中的数据,如首页,产品页,购物车,分类页面等等。
    2.1.2 前端交互这里的交互指的是通过POST,GET等http协议,与服务端进行同步或者异步数据交互。 比如购买,购物车,生成订单,登录等等功能。
    2.1.3 后台功能比如分类管理,分类属性管理,产品管理,产品图片管理,用户管理,订单管理等等。
    2.2 前台展示2.2.1 首页
    步骤 1 : 先看完整页面效果
    步骤 2 : 在横向导航栏上提供4个分类连接
    步骤 3 : 在纵向导航栏上提供全部17个分类连接
    步骤 4 : 当鼠标移动到某一个纵向分类连接的时候,显示这个分类下的推荐商品
    步骤 5 : 按照每种分类显示5个商品的方式,显示所有17种分类

    2.2.2 产品页
    步骤 1 : 显示分辨率为950x100的当前商品对应的分类图片
    步骤 2 : 显示本商品的5个单独图片
    步骤 3 : 商品的基本信息,如标题,小标题,价格,销量,评价数量,库存等
    步骤 4 : 商品详情
    步骤 5 : 评价信息
    步骤 6 : 5张商品详细图片

    2.2.3 分类页
    步骤 1 : 显示分辨率为950x100的当前分类图片
    步骤 2 : 显示本分类下的所有产品

    2.2.4 搜索结果页
    步骤 1 :显示满足查询条件的商品
    2.2.5 购物车查看页
    步骤 1 :在购物车中显示订单项
    2.2.6 结算页
    步骤 1 :在结算页面显示被选中的订单项
    2.2.7 确认支付页
    步骤 1 :确认支付页面显示本次订单的金额总数
    2.2.8 支付成功页
    步骤 1 :付款成功时,显示本次付款金额
    2.2.9 我的订单页
    步骤 1 :显示所有订单,以及对应的订单项
    2.2.10 确认收货页
    步骤 1 : 显示订单项内容
    步骤 2 : 显示订单信息,收货人地址等

    2.2.11 评价页
    步骤 1 : 显示要评价的商品信息,商品当前的总评价数
    步骤 2 : 评价成功后,显示当前商品所有的评价信息

    2.2.12 页头信息展示
    步骤 1 : 未登录状态
    步骤 2 : 已登录状态

    2.3 前台交互2.3.1 分类页排序
    步骤 1 : 按照综合,人气,新品,销量,价格排序
    步骤 2 : 进行价格筛选,这个不算,这个是做在浏览器端的,并不是和服务器端的交互

    2.3.2 立即购买
    步骤 1 : 在产品页,未登录状态时候,点击立即购买
    步骤 2 : 在产品页,如果已经登录,点击购买

    2.3.3 加入购物车
    步骤 1 : 在未登录状态,点击加入购物车
    步骤 2 : 在已登录状态,点击加入购物车

    2.3.4 调整订单项数量
    步骤 1 :在购物车页面,调整订单项数量
    2.3.5 删除订单项
    步骤 1 :在购物车页面,删除订单项
    2.3.6 生成订单
    步骤 1 :在结算页面,提交订单
    2.3.7 订单页功能
    步骤 1 :我的订单页面:订单页面上有3个按钮,付款,确认收货和评价,这些按钮都没有提交数据到服务端,而是提交到下一个页面的二次操作,才提交数据到服务端的。
    2.3.8 确认付款点击确认支付,提交本信息到服务端,服务端修改订单中的支付日期
    2.3.9 确认收货确认收货页面,点击确认支付,提交数据到服务端,并且修改订单中的确认收货日期
    2.3.10 提交评价信息提交评价信息到服务端
    2.3.11 登录输入正确账号密码,登录成功后跳转到首页,失败提示错误信息
    2.3.12 注册
    步骤 1 : 注册页面
    2.3.13 退出退出登录
    2.3.14 搜索提交关键字到服务端,服务端查询数据库,并返回匹配的产品
    2.3.15 前台需求列表2.4 后台管理2.4.1 分类管理
    步骤 1 : 分页查询
    步骤 2 : 新增分类
    步骤 3 : 编辑修改
    步骤 4 : 删除

    2.4.2 属性管理
    步骤 1 : 属性概念这里的属性,指的是产品属性。假定同一类产品,都有相同的属性
    步骤 2 : 分页查询
    步骤 3 : 新增属性
    步骤 4 : 编辑修改
    步骤 5 : 删除

    2.4.3 产品管理
    步骤 1 : 分页查询
    步骤 2 : 新增产品
    步骤 3 : 编辑修改
    步骤 4 : 删除

    2.4.4 产品图片管理
    步骤 1 : 产品图片概念一件产品,对应多条 单个图片一件产品,对应多条 详情图片
    步骤 2 : 产品图片管理

    2.4.5 产品属性管理
    步骤 1 : 产品属性值设置根据属性管理中的讲解,一种产品所具备的属性,在其对应的分类中进行了维护。那么,要修改产品的这些属性值,就在本页面进行。这里采用异步提交方式,编辑即修改,修改成功用绿色边框表示
    2.4.6 用户管理用户管理就提供了一个分页查询,做的比较简约,几个原因:

    用户是不能删除的
    用户信息的修改,应该交由前端由客户自己修改,比如密码,基本信息等
    用户的增加,是前端注册导致的,后台不负责用户的增加

    2.4.7 订单管理
    步骤 1 : 订单分页查询
    步骤 2 : 查看详情
    步骤 3 : 发货

    2.4.8 后台需求列表三、表结构设计3.1 概述在需求分析结束之后,接下来要做的不是马上开发功能,而是进行表结构的设计。
    3.2 数据库创建数据库:tmall。并且将数据库的编码设置为utf8,便于存放中文
    3.3 表与表关系3.3.1 表关系图
    3.3.2 表


    表名
    中文含义
    介绍




    Category
    分类表
    存放分类信息,如女装,平板电视,沙发等


    Property
    属性表
    存放属性信息,如颜色,重量,品牌,厂商,型号等


    Product
    产品表
    存放产品信息,如LED40EC平板电视机,海尔EC6005热水器


    PropertyValue
    属性值表
    存放属性值信息,如重量是900g,颜色是粉红色


    ProductImage
    产品图片表
    存放产品图片信息,如产品页显示的5个图片


    Review
    评论表
    存放评论信息,如买回来的蜡烛很好用,么么哒


    User
    用户表
    存放用户信息,如斩手狗,千手小粉红


    Order
    订单表
    存放订单信息,包括邮寄地址,电话号码等信息


    OrderItem
    订单项表
    存放订单项信息,包括购买产品种类,数量等



    3.3.3 表关系从最上面的表关系图中可以看到,有关系的表之间,都是一对多关系(反过来就是多对一关系),并没有一对一关系,和多对多关系。
    3.4 建表sql语句3.4.1 建表顺序在建表过程中,会设置外键约束,所以表和表之间有依赖关系。 因此会先建立被外键指向的表,比如User,Category,然后再是其他表
    3.4.2 表的字段
    用户表user主键Id,name用户名,password登陆密码
    分类表category主键id,name分类名
    属性表property主键id,名称name,外键cid指向category的id
    产品表主键id, name产品名称,subTitle小标题,orignalPrice原始价格,promotePrice优惠价格,stock库存,createDate创建日期,外键cid指向category的id
    属性值表propertyvalue主键id,属性值value,外键ptid指向property的id,外键pid指向product的id
    产品图片表主键id,type图片文件,外键pid指向product的id
    评价表主键id,content评价内容,createDate创建日期,外键pid指向product的id,外键uid指向用户表的id
    订单表

    orderCode:订单号address:收货地址post: 邮编receiver: 收货人信息mobile: 手机号码userMessage: 用户备注信息createDate: 订单创建日期payDate: 支付日期deliveryDate: 发货日期confirmDate:确认收货日期status: 订单状态外键uid,指向用户表id字段
    订单项表

    外键pid,指向产品表id字段外键oid,指向订单表id字段外键uid,指向用户表id字段number字段表示购买数量

    四、实体类4.1 概述所谓的实体类,就是对于数据库中的表的互相映射的类。 这是一种ORM的设计思想,即一个对象,对应数据库里的一条记录
    4.2 所有实体类对于一对多的表,在“一”的类中添加“多”的类集合,在“多”的类中添加“一”的类。
    五.DAO类设计5.1 概述DAO是Data Access Object的缩写,这些类专门用于进行数据库访问的操作。

    首先讲解两个工具类,DBUtil和DateUtil,因为在DAO类中会用到这两个工具类
    接着按照依赖顺序,逐个讲解不同的DAO类以及其中的方法

    5.2 工具类
    DBUtil类初始化驱动,并返回数据库连接
    DateUtil用于实体类和数据库中日期格式的转换

    5.3 DAO类六.Service6.1 通常的设计流程作为J2EE web 应用,一般会按照如图所示的设计流程进行Servlet -> Service(业务类) -> DAO -> database当浏览器提交请求到tomcat web 服务器的时候,对应的servlet的doGet/doPost方法会被调用,接着在servlet中调用Service类,然后在Service类中调用DAO类,最后在DAO中访问数据库获取相应的数据。

    6.2 不使用Service的原因在本模仿天猫整站-J2ee 版本中,不使用Service这一层。 原因是在DAO进行了比较详细的设计,已经提供了很好的支持业务的方法。
    七.后台7.1 原型-后端7.1.1 概述本项目里的后端又不仅仅是CRUD维护管理页面,还有一些其他略复杂的功能,所以还是把这些原型界面都做出来。 后续开发功能的时候,就可以基于这些原型界面进行。
    7.1.2 分类管理
    7.1.3 属性管理
    7.1.4 产品管理
    7.1.5 产品图片管理
    7.1.6 产品属性管理
    7.1.7 用户管理
    7.1.8 订单管理
    7.2 后台-分类管理7.2.1 概述开发整站的顺序,通常来说还是按照依赖性来进行,前端需要的数据,都要先通过后台的功能维护在数据库中,才可以拿到。 所以,先进行后台功能的开发,然后再是前台功能的开发。
    后台在系统设计的时候,并不是简单的每个功能对应一个Servlet,而是使用了反射的技术,结合过滤器Filter进行了封装,使得开发配置以及维护成本降低了很多。
    7.2.2 静态资源接下来,解析这个可运行项目。 首先从最简单的静态资源开始。
    7.2.3 Filter配合Servlet步骤一:每种实体类,对应了一个Servlet,而不是对应了5个,这样首先从Servlet数量上来讲,就大大的减少了。原理流程图:

    假设访问路径是 http://127.0.0.1:8080/tmall/admin_category_list
    过滤器BackServletFilter进行拦截,判断访问的地址是否以/admin_开头
    如果是,那么做如下操作

    取出两个下划线之间的值 category取出最后一个下划线之后的值 list然后根据这个值,服务端跳转到categoryServlet,并且把list这个值传递过去
    categoryServlet 继承了BaseBackServlet,其service方法会被调用。 在service中,借助反射技术,根据传递过来的值 list,调用对应categoryServlet 中的方法list()
    这样就实现了当访问的路径是 admin_category_list的时候,就会调用categoryServlet.list()方法这样一个效果

    步骤二:代码讲解-BackServletFilter:

    首先在web.xml配置文件中,让所有的请求都会经过BackServletFilter<url-pattern>/*</url-pattern>
    还是假设访问的路径是:http://127.0.0.1:8080/tmall/admin_category_list
    在BackServletFilter 中通过request.getRequestURI()取出访问的uri: /tmall/admin_category_list
    然后截掉/tmall,得到路径/admin_category_list
    判断其是否以/admin开头
    如果是,那么就取出两个_之间的字符串,category,并且拼接成/categoryServlet,通过服务端跳转到/categoryServlet
    在跳转之前,还取出了list字符串,然后通过request.setAttribute的方式,借助服务端跳转,传递到categoryServlet里去

    步骤3:代码讲解-CategoryServlet和BaseBackServlet服务端跳转/categoryServlet就到了CategoryServlet这个类里

    首先CategoryServlet继承了BaseBackServlet,而BaseBackServlet又继承了HttpServlet
    服务端跳转过来之后,会访问CategoryServlet的doGet()或者doPost()方法
    在访问doGet()或者doPost()之前,会访问service()方法
    BaseBackServlet中重写了service() 方法,所以流程就进入到了service()中
    在service()方法中有三块内容

    第一块是获取分页信息第二块是根据反射访问对应的方法第三块是根据对应方法的返回值,进行服务端跳转、客户端跳转、或者直接输出字符串。
    第一块和第三块放在后面讲解,这里着重讲解第二块是根据反射访问对应的方法

    取到从BackServletFilter中request.setAttribute()传递过来的值 list根据这个值list,借助反射机制调用CategoryServlet类中的list()方法,这样就达到了CategoryServlet.list()方法被调用的效果

    7.2.4 JSP包含关系步骤一:分类查询对应的JSP文件分类查询对应的JSP文件是listCategory.jsp,用到了4个公共包含文件:

    <%@include file=”../include/admin/adminHeader.jsp”%>
    <%@include file=”../include/admin/adminNavigator.jsp”%>
    <%@include file=”../include/admin/adminPage.jsp”%>
    <%@include file=”../include/admin/adminFooter.jsp”%>

    步骤二:每个后台页面都在开始使用了adminHeader.jsp

    html5
    jsp指令
    引入JSTL
    引入js和css
    预先定义一些判断输入框的js函数
    对于删除链接,需要进行确认操作

    步骤三:adminNavigator.jsp导航部分,包括一张图片和4个链接
    7.2.5 查询步骤1:MVC设计思想根据 MVC设计模式的思想,做J2EE web应用,从MVC的角度来看,就是把不同的数据显示在不同的页面上。数据就是 模型 ( bean, dao )、页面就是 视图 ( jsp )、控制不同的模型显示在不同的视图上,这件事,就是由控制器来完成 ( servlet )。所以分类管理,从MVC的角度来看,就是把多条分类Category数据放在一个集合里, 让listCategory.jsp 这个视图去显示出来。
    步骤2:list()方法在list()方法里做的事情是,取出数据,并且交由jsp显示。

    通过categoryDAO取得数据集合 cs
    通过request.setAttribute 放在 “thecs” 这个key中,为后续服务端跳转到jsp之后使用
    return “admin/listCategory.jsp”;

    步骤3:服务端跳转list()方法跳转到jsp页面
    步骤4:listCategory.jsp作为视图,担当的角色是显示数据。所以关键就是从第44行开始,借助JSTL的c:forEach标签遍历从CategoryServlet的list() 的request.setAttribute(“thecs”, cs); 传递过来的分类集合。
    7.2.6 分页步骤1:page.javaPage这个类专门为分页提供必要信息。
    步骤2:获取分页参数Service方法获取网页上传递来的开始位置,以及每页需要显示的数量。如果传递数据过来,开始位置取0,每页显示的数量取默认值:5.
    步骤3:基于分页参数,获取数据通过反射调用list()方法,list调用DAO获取分页数据。
    步骤4: 为page对象设置总数在分页显示的时候,依据这个总数来判断一共有多少页面,最后一页是多少。
    7.2.7 增加步骤1:增加的部分是坐在查询结果页面的。步骤2:提交数据会导致add()方法被调用。步骤3:接收数据并处理:parseUpload方法获取文件流步骤4:ImageUtil工具类:转换文件格式为jpg,改变文件大小步骤5:中文问题,在过滤器中对提交的数据进行统一编码步骤6:客户端跳转,add()方法返回@admin_category_list
    7.2.8 删除步骤1:用于删除的超链,指向地址admin_category_delete,并且会传递当前分类对象的id过去。步骤2:在adminHeader.jsp中对所有的删除连接都进行了监听。步骤 3 : 删除调用CategoryServlet.delete()方法。
    7.2.9 编辑步骤1 : 编辑超链,用于编辑的超链,指向地址admin_category_edit,并且会传递当前分类对象的id过去。步骤2 : 调用CategoryServlet.edit()方法。步骤3:服务端跳转到editCategory.jsp,在editCategory.jsp页面里,获取由CategoryServlet.edit() 通过request传递过来的Category对象,获取name和id。
    7.2.10 修改步骤1:编辑页面提交数据。步骤2:CategoryServlet.update() 方法和CategoryServlet.add()方法的处理很类似,有所不同之处在于增加操作一定会提交图片,而修改不一定提交图片。
    7.3 后台-其他管理7.3.1概述后台的其他管理页面与分类管理用到的设计思路类似。
    7.3.2 属性管理7.3.3 产品管理7.3.4 产品图片管理7.3.5 产品属性管理7.3.6 用户管理7.3.7 订单管理八. 前台8.1 原型-前端8.1.1 概述在开发功能之前,都会先有原型界面。 通常原型界面的数据不是真实的,是临时写在页面上,为用户提供一个直观的界面感受的。
    关于前端的关注点,着重落在如何获取服务端的数据,显示在页面上,以及前端页面与服务端的同步/异步数据交互上。
    8.1.2 首页
    8.1.3 分类页
    8.1.4 产品页面
    8.1.5购物车页面
    8.1.6 我的订单页面
    8.1.7 结算页面
    8.1.8 查询结果页面
    8.1.9 支付页面
    8.1.10 支付成功页面
    8.1.11 确认收货页面
    8.1.12 收货成功页面
    8.1.13 评价页面
    8.1.14 登录页面
    8.2 前台-首页8.2.1 概述8.2.1.1 前台无需登录从前台模块之间的依赖性,以及开发顺序的合理性来考虑,把前台功能分为了 无需登录 即可使用的功能,和需要登录 才能访问的功能。 建立在前一步前台-首页的基础之上,开始进行一系列的无需登录功能开发。
    8.2.1.2 前台需要登录接着是需要登录的前台功能。 这部分功能基本上都是和购物相关的。 因此,一开始先把购物流程 单独拿出来捋清楚,其中还特别注明了购物流程环节与表关系,这样能够更好的建立对前端购物功能的理解。随着这部分功能的开发,就会进入订单生成部分,在此之前,先准备了一个 订单状态图,在理解了这个图之后,可以更好的进行订单相关功能的开发
    8.2.2 静态资源步骤1:图片资源Site目录,轮播图片,分类图片,产品图片
    步骤2:css,js
    8.2.3 Filter配合Servlet步骤1:ForeServletFilter与BackServletFilter相似,如果访问路径以/fore而不是以/foreServlet开头,就跳转到foreServlet。
    步骤2:ForeServlet和BaseForeServlet在ForeServlet类里,就提供了所有前端需要用到的业务方法。BaseForeServlet与BaseBackServlet相似,不过前台没有用到分页,所以service主要是根据反射调用ForeServlet的home()方法以及根据home()的返回值进行跳转。
    8.2.4 home方法步骤1:首页展示的数据

    在横向导航栏上提供4个分类连接
    在纵向导航栏上提供全部17个分类连接
    当鼠标移动到某一个纵向分类连接的时候,显示这个分类下的推荐商品
    按照每种分类显示5个商品的方式,显示所有17种分类

    步骤2:home方法获取所有分类,为分类填充产品,推荐产品。
    8.2.5 home.jsp步骤1:包含页面根据前台页面的特点,我们把home.jsp设计成如代码所示。

    header.jsp引入标准标签库,js,css,自定义javascript函数等
    top.jsp置顶导航
    search.jsp搜索栏
    homePage.jsp首页业务页面
    footer.jsp页脚

    8.2.6 homePage.jsp步骤1:homepage.jsp所包含的页面关系

    categoryAndCarousel.jsp,分类和轮播
    categoryMenu.jsp,竖状分类菜单productsAsideCategorys.jsp,竖状分类菜单右侧的推荐产品carousel.jsp,轮播。
    homepageCategoryProducts.jsp主题的17种分类以及每种分类对应的5个产品
    步骤2:categoryAndCarousel.jspcategoryAndcarousel.jsp 页面利用ForeServlet传递过来的数据,天猫国际几个字旁边显示4个分类超链,另外包含了其他3个页面:categoryMenu.jsp、productsAsideCategorys.jsp、carousel.jsp

    8.3 前台-无需登录8.3.1 概述我们把前台功能分为两部分:

    无需登录有一些功能,无需登录也可以使用的,比如登录,注册本身,分类页面,查询,产品页面等
    需要登录有一些功能,必须建立在已经登录的基础之上,比如购买,加入购物车,查看购物车,结算页面,订单页面等等。

    8.3.2 注册与首页的home.jsp相仿,register.jsp也包含了header.jsp,top.jsp,footer.jsp等公共页面。不同的是,没有使用首页的search.jsp,而是用的简单一点的 simpleSearch.jsp。
    8.3.3 登录与register.jsp相仿,login.jsp也包含了header.jsp,footer.jsp等公共页面。中间是登录业务页面loginPage.jsp
    8.3.4 退出清除session中的user
    8.3.5 产品页product()方法用来展示产品。productPage.jsp 又由3个页面组成

    imgAndInfo.jsp:单个图片和基本信息
    productReview.jsp:评价信息
    productDetail.jsp:详情图片

    8.3.6 模态登录在未登录状态,点击购买或者加入购物车就会弹出这个模态对话框,在这个模态对话框上可以进行登录操作.
    立即购买和加入购物车这两个按钮的监听是放在imgAndInfo.jsp页面中这两个按钮都会通过JQuery的.get方法,用异步ajax的方式访问forecheckLogin,获取当前是否登录状态。如果返回的不是”success” 即表明是未登录状态,那么就会打开登录的模态窗口。
    模态窗口modal.jsp被footer.jsp所包含。
    8.3.7 分类页步骤1:5个Comparator比较器分类这个页面有排序功能,所以ForeServlet之前,先准备5个Comparator比较器:

    ProductAllComparator 综合比较器,把 销量*评价 高的放前面
    ProductReviewComparator 人气比较器,把 评价数量多的放前面
    ProductDateComparator 新品比较器,把 创建日期晚的放前面
    ProductSaleCountComparator 销量比较器,把 销量高的放前面
    ProductPriceComparator 价格比较器,把 价格低的放前面

    步骤2:ForeServlet.category()根据cid获取分类c,为c填充产品,为产品填充销量和评价。获取参数sort,进行排序。
    步骤3:categoryPage.jspcategoryPage.jsp 里有3个内容:

    显示当前分类图片
    <img src="img/category/${c.id}.jpg">排序条 sortBar.jsp
    产品列表 productsByCategory.jsp

    步骤4:sortBar.jspsortBar.jsp即排序条,作用如下:

    根据sort参数判断那个排序按钮高亮
    每个排序按钮提交到本页面,即/forecategory,并带上参数sort

    步骤5:productsByCategory.jspproductsByCategory.jsp显示当前分类下的所有产品,通过forEach遍历c.products集合里的每个产品,并把产品标题,价格,图片,评价数,成交数打印出来。categorycount是用于测试的,在访问地址的时候加这个参数可以控制显示的产品数量。
    8.3.8 搜索Search()方法进行模糊查询,将结果返回给jsp,最终在productBySearch.jsp页面中显示出来。
    8.4 前台-需要登录8.4.1 购物流程步骤1:购买的业务流程

    登录

    访问产品页
    立即购买

    进入结算页面

    加入购物车

    查看购物车

    选中购物车中的商品

    又到了第4步的结算页面
    在结算页面生成订单
    付款

    确认收货
    评价

    步骤2:购物流程环节与表观系围绕购物流程最重要的两个表是OrderItem 和 Order表,关于OrderItem的业务行为:

    立即购买 —— 新增 OrderItem
    加入购物车 —— 新增 OrderItem
    查看购物车 —— 显示未和Order关联的OrderItem
    选中购物车中的商品 —— 选中OrderItem
    结算页面 —— 显示选中的OrderItem


    生成订单 —— 新增Order
    付款 —— 修改Order状态
    我的订单 —— 显示Order
    确认收货 —— 修改Order状态

    8.4.2 立即购买步骤1:buyone()

    获取p和user
    增加订单项OrderItem或调整数量
    跳转到结算页面/forebuy

    8.4.3 结算页面步骤1:buy()

    getParamValues获取多个oiid
    根据oiid将订单项放入集合ois中
    计算ois的价格总数total
    ois放入session,total放入request
    服务端跳转到buy.jsp

    步骤2:buyPage.jsp

    遍历出订单项集合ois中的订单数据,从立即购买跳转到结算页面只会有一件产品。
    显示总金额
    提交订单项到订单

    8.4.4 加入购物车步骤1:登录之后,点击加入购物车,会使用Ajax提交数据到addCart()
    步骤2:addCart()和buyone()一样:

    获取pid,num
    从session中获取user
    新增订单项或只增加数量

    8.4.5 查看购物车页面步骤1:cart()

    获取当前用户
    获取用户的ois
    跳转到cart.jsp

    8.4.6 登录状态Filter准备一个过滤器,当访问那些需要登录才能做的页面的时候,进行是否登录的判断,如果不通过,那么就跳转到login.jsp页面去,提示用户登录。新建过滤器ForeAuthFilter,

    不需要登陆的页面注册,登录,产品,首页,分类,查询
    需要登陆的页面购买行为,加入购物车,查看购物车,查看订单

    8.4.7 购物车页面操作步骤1.调整订单数量,通过ajax访问/forechangOrderItem

    判断用户是否登录
    获取pid和number
    遍历OrderItem
    根据pid找到OrderItem,更新OrderItem
    返回success

    步骤2.删除订单项,通过ajax访问/foredeleteOrderItem

    判断用户是否登录
    获取oiid
    删除oiid对应的OrderItem数据
    返回字符串”success”

    8.4.8 订单状态图

    首先是创建订单,刚创建好之后,订单处于waitPay 待付款状态
    接着是付款,付款后,订单处于waitDelivery 待发货状态
    前两部都是前台用户操作导致的,接下来需要到后台做发货操作,发货后,订单处于waitConfirm 待确认收货状态
    接着又是前台用户进行确认收货操作,操作之后,订单处于waitReview 待评价状态
    最后进行评价,评价之后,订单处于finish 完成状态

    比较特殊的是,无论当前订单处于哪个状态,都可以进行删除操作。 像订单这样极其重要的业务数据,实际上是不运行真正从数据库中删除掉的,而是把状态标记为删除,以表示其被删掉了,所以在删除之后,订单处于 delete 已删除状态
    8.4.9 生成订单步骤1.提交订单调用createOrder()方法

    获取参数创建订单对象
    更新订单项
    跳转到确认支付页forealipay,并带上id和总金额

    步骤2:确认支付页显示总金额,支付后跳转到forepayed页面,带上id和总金额
    步骤3:支付成功页显示订单的基本信息
    8.4.10 我的订单页bought方法获取user中不是delete状态的订单集合osbought.jsp显示订单的日期、金额等信息,显示每个订单项对应的产品
    8.4.11 我的订单操作步骤1:在我的订单页面,根据订单的不同状态,可以做出如下不同的操作:

    付款 —— 已经生成,但是未付款
    确认收货 —— 通过后台发货后
    评价 —— 确认收货后, 进行评价
    删除 —— 任意状态下

    步骤2:确认收货/foreconfirmPay

    为订单对象o填充订单项,
    confirmPay.jsp显示订单的创建的时间等信息

    步骤3:确认收货成功/foreorderConfirmed

    修改订单o的状态为等待评价,修改其确认支付时间
    更新到数据库
    orderConfirmPage.jsp显示成功信息

    步骤4:评价
    步骤5:删除/foredeleteOrder

    修改状态,更新
    返回字符串success
    boughtPage.jsp的js代码隐藏当前订单

    8.4.12 评价产品步骤1:评价产品页面/foreview

    为订单o填充订单项
    获取第一个订单项的产品,显示其图片
    获取这个产品的评价集合
    为产品设置数量和销量
    把产品,订单和评价放在request上
    在reviewPage.jsp中显示产品图片,产品标题,价格,产品销量,产品评价数量,以及订单信息等。 同时还显示出了该产品所有的评价,但是默认是隐藏的

    步骤2:提交评价/foredoreview

    获取订单o,修改状态,更新到数据库
    获取产品对象p,获取参数content(评价信息),对评价信息进行转义
    获取当前用户,获取评价对象review
    为review设置评价信息等,提交到数据库
    跳转到/foreview:参数showonly=true,显示评价信息

    九.总结9.1 项目总结9.1.1 项目结构
    项目名称 tmall
    ava源代码包结构

    tmall.bean 实体类tmall.comparator 比较器tmall.dao DAO类tmall.filter 过滤器tmall.servlet servlettmall.test 测试类tmall.util 工具类
    web目录

    css css文件img 图片资源js文件admin 后台管理用到的jsp文件include 被包含的jsp文件

    9.1.2 典型场景
    购物车
    订单状态流转
    CRUD
    分页
    一类产品多属性配置
    一款产品多图片维护
    产品展示
    搜索查询
    登录、注册
    登录验证

    9.1.3 设计模式
    MVCMVC设计模式贯穿于整个后台与前台功能开发始末
    Filter+Servlet+反射采用Filter+Servlet+反射的设计模式,把原本后台需要20多个Servlet的经典Servlet设计方式,精简到了7个。把原本前台需要20多个Servlet的经典Servlet设计方式,精简到了2个。web.xml的配置文件也大大减少,降低了开发和维护的工作量,减少了出错的几率。
    统一的分页查询简化开发所有的后台都使用同一个分页机制,仅仅需要一份简化的adminPage.jsp即满足了各种分页功能的需求,简化了开发,提升了开发速度。
    模块化JSP设计从大的JSP文件中,通过JSP包含关系抽象出多个公共文件,并把业务JSP按照功能,设计为多个小的JSP文件,便于维护和理解

    9.2 改进练习还有些功能可以继续完善。

    后台管理员登陆模块
    产品图片排序
    前台分类下显示产品,提供分页功能

    等等
    2 评论 2 下载 2019-07-16 18:06:17 下载需要20点积分
  • 基于Java Web的投票管理系统

    摘 要相较于传统投票方式,在线投票是任何一-次商演(时间短、影响范围小)、电视(投入大,效果不明显)或者户外广告(不能快速吸引消费者眼球)在投入产出效率上都难以企及的。在线投票能够迅速提升活动商家的广告价值,降低商家广告成本,提高知名度以及美誉度。网络投票的主要目的就是人群放大:通过网络投票,可以吸引大量的选手及相关亲友的关注,通过以往的数据统计,一名选手参 与投票,会带动60人参与。这样可以最大程度的向客户展现实力,扩大社会影响力。
    系统分为前台和后台两部分,前台主要是对普通用户开放。普通用户将实现匿名投票操作:后台主要作用是管理员实现登录、投票管理、用户管理等操作。依据前台和后台的不同权限需求,在线投票系统主要分为普通用户和管理员两个功能模块。
    普通用户模块将实现用户登录、用户投票以及查看投票结果等功能。管理员模块将实现管理员登录、发布新投票、查看所有投票、及用户管理等功能。
    关键词:网上投票、JSP、MYSQL
    1 概述随着科技的飞速发展,计算机已经广泛的应用于各个领域之中,而且日趋普及。在计算机应用中很重要的一部分就是编程语言,编程语言的出现打开了计算机应用的新篇章。在这些编程语言中JSP占有着重要的地位,JSP 拥有Java编程语言“一-次编写,各处运行”的特点口。在当今的网络应用中JSP无处不在,在线投票系统就是JSP功能强大的-一个最好的例证。
    在线投票系统有很多传统投票方式不可比拟的优势。首先,它可以在很短的时间内,通过互联网将不同时间不同地域的用户投票组合到一起,并进行结果反馈,这是传统的投票方法完全做不到的;其次,在线投票系统的效率要比以往的传统投票方法高很多,在这个寸时如寸金的年代,在线投票系统不但省去了投票与计票环节的人力成本,还可以节省很多时间以用作处理其他更重要的事情:综上所述,在线投票系统有着快捷、经济、方便、省时省力等诸多优点都注定它将是未来投票方式的主流。
    2 课程设计任务及要求2.1 任务设计一个投票系统,实现学生对教师的匿名投票。有管理用户,实现对整个系统的管理。
    2.2 要求用户分为管理员用户和普通用户。
    普通用户提供以下功能:系统首页上显示所有投票选项的列表,显示当前登录用户并提供注销功能,用户可以通过选中某个选项并点击“投票”按钮进行投票操作。用户点击后可在当前一页面上看到各个投票选项目前的投票情况,主要包括各选项所得的票数,并且以柱形显示各选项的得票率,可以让用户从直观上看到各项的得票情况。
    管理员用户提供以下功能:显示当前登录用户并提供注销功能,提供系统管理实现用户的增删查改及重新投票等功能,还能显示用户列表及投票情况表。开发的系统数据库设计要合理,能够实现设计的全部功能,能够运行演示。能够体一个软件的基本功能。
    3 需求分析3.1 功能需求用户能够正常的登录及注销,每个用户在每一次投票中只能匿名投票一次。管理员能够新建账号、删除账号、修改账号及初始话投票。在管理员页面显示投票情况及用户情况等系统详情。
    整个系统要进行session检查,防止非法用户访问受限页面。
    3.2 硬件需求运行windows的硬件平台并装有如下软件:

    Jdk1.8
    tomcat6.0
    eclipse
    sql server 2008

    4 概要设计4.1 总体模块设计4.1.1 普通用户模块
    登录:使用普通用户账号登录到投票界面
    投票:选择投票对象并进行投票
    注销:清空用户session退回到欢迎界面

    其各部分关系图如图1所示。

    4.1.2 管理员用户模块
    登录:使用管理员账号登录到后台管理界面
    注销:清空用户session退回到欢迎界面
    用户管理:管理员可以增加、删除、修改用户账号,不能删除当前登录用户
    初始化投票:管理员可以初始化投票系统,开启下一次投票
    查看所有用户:显示系统中已存在的用户账号及其投票情况
    查看得票数:显示当前的投票情况

    其各部分关系如图2所示。

    4.2 开发工具简介在在线投票系统的设计发开过程中主要用了JSP技术,其中用到的工具有:JDK1.8、Eclipse、MySQL、Tomcat 等。
    4.2.1 JSP简介JSP技术有点类似ASP技术,它是在传统的网页HTML文件中插入Java程序段和JSP,从而形成JSP文件”。JSP技术使用Java编程语言编写类XML的tags和scriptlets,来封装产生动态网页的处理逻辑。在线投票系统用JSP将网页逻辑与网页设计和显示分离,支持可重用的基于组件的设计,使本系统基于Web的应用程序的开发变得迅速和容易。

    一次编写,到处运行。在这一一点上Java比PHP更出色,除了系统之外,代码不用做任何更改
    系统的多平台支持。基本上可以在所有平台上的任意环境中开发,在任意环境中进行系统部署,在任意环境中扩展。相比ASP/PHP的局限性是现而易见的
    强大的可伸缩性。从只有一个小的Jar文件就可以运行Servlet/JSP,到由多台服务器进行集群和负载均衡,到多台Application进行事务处理,消处理,-台服务器到无数台服务器,Java 显示了一个巨大的生命力
    多样化和功能强大的开发工具支持。这一点与ASP很像,Java已经有了许多非常优秀的开发工具,而且许多可以免费得到,并且其中许多已经可以顺利的运行于多种平台之下

    4.2.2 SQL server简介SQL Server系列软件是Microsoft 公司推出的关系型数据库管理系统。2008年10月,SQL Server 2008简体中文版在中国正式上市,SQL Server 2008 版本可以将结构化、半结构化和非结构化文档的数据直接存储到数据库中。可以对数据进行查询、搜索、同步、报告和分析之类的操作。数据可以存储在各种设备上,从数据中心最大的服务器一直到桌面计算机和移动设备,它都可以控制数据而不用管数据存储在哪里。
    此外,SQL Server 2008 允许使用 Microsoft .NET 和Visual Studio开发的自定义应用程序中使用数据,在面向服务的架构(SOA)和通过 Microsoft BizTalk Server 进行的业务流程中使用数据。信息工作人员可以通过日常使用的工具直接访问数据。
    4.3 数据库设计数据库设计是软件开发中的重要环节,是对系统数据全面的、详细的分析。数据库设计的好坏直接关系到整个项目设计的效率的高低,关系到设计的稳定性。根据在线投票系统不同模块之间的联系和前期的设计目的与需求,设计了三个不同的数据表,它们分别是用户表、投票选项表和投票主题表。
    4.3.1 用户表(T_USER)用户表包括所有用户的各种信息,如账户、密码等详细数据并规定了每个字段的类型,如表1所示。



    字段名
    数据类型
    长度
    是否主键
    描述




    ACCOUNT
    VARCHAR
    40

    账号


    PASSWARD
    VARCHAR
    40

    密码


    UNAME
    VARCHAR
    40

    用户姓名


    ADMIN
    BIT
    1

    管理员标识


    TICKET
    INT
    255

    票数



    4.3.2 投票表(T_VOTE)投票表包括教师编号、教师姓名和得票数。如表2所示。



    字段名
    数据类型
    长度
    是否主键
    描述




    TEACHERNO
    VARCHER
    40

    教师编号


    TEACHERNAME
    VARCHER
    40

    教师姓名


    VOTE
    INT
    255

    得票数



    5 开发与实现5.1 程序模块实现5.1.1 用户登录模块关键代码<% request.setCharacterEncoding("gb2312"); String account = request.getParameter("account"); String password = request.getParameter("password"); UserDao udao = new UserDao(); User user = udao.getUserByAccount(account); if(user == null||!user.getPassword().equals(password)){ %> <br><br><br><br><br><br> 登录失败,<a href="loginForm.jsp">返回登录页面</a> <% } else if(user.getAdmin()==true){ session.setAttribute("user", user); response.sendRedirect("admin.jsp"); } else{ session.setAttribute("user", user); response.sendRedirect("display.jsp"); }%>
    5.1.2 投票模块关键代码<% String account=user.getAccount(); String[]teacherno =request.getParameterValues("teacherno"); VoteDao vdao = new VoteDao(); UserDao udao = new UserDao(); int ticket= udao.ticket(account); if(ticket>0){ if(teacherno!=null){ vdao.updateVotes(teacherno); vdao.updateTictet(account); } response.sendRedirect("display.jsp"); } else{ response.sendRedirect("noTicket.jsp"); } %>
    5.1.3 新建用户模块关键代码<% request.setCharacterEncoding("gb2312"); String account = request.getParameter("account"); String password = request.getParameter("password"); String uname = request.getParameter("uname"); String admin =request.getParameter("admin"); UserDao udao = new UserDao(); User user2=udao.getUserByAccount(account); if(user2!=null){ %> <jsp:forward page="changeError2.jsp"></jsp:forward> <% } udao.adduser(account, password, uname, admin); %> <br><br><br><br><br><br> <p align="center">创建用户成功!<br> <a href="admin.jsp">返回</a></p>
    5.1.4 删除用户模块关键代码<% request.setCharacterEncoding("gb2312"); String account = request.getParameter("account"); String acc = user.getAccount(); if(acc.equals(account)){ %> <jsp:forward page="changeError3.jsp"></jsp:forward> <% } UserDao udao = new UserDao(); User user2=udao.getUserByAccount(account); if(user2==null){ %> <jsp:forward page="changeError.jsp"></jsp:forward> <% } udao.deluser(account); %> <br><br><br><br><br><br> <p align="center">删除用户成功!<br> <a href="admin.jsp">返回</a></p>
    5.1.5 修改用户模块关键代码<% request.setCharacterEncoding("gb2312"); String account = request.getParameter("account"); String password = request.getParameter("password"); String uname = request.getParameter("uname"); String admin =request.getParameter("admin"); UserDao udao = new UserDao(); User user2=udao.getUserByAccount(account); if(user2==null){ %> <jsp:forward page="changeError.jsp"></jsp:forward> <% } udao.changeuser(account, password, uname, admin); %> <br><br><br><br><br><br> <p align="center">修改用户成功!<br> <a href="admin.jsp">返回管理页面</a></p>
    5.1.6 初始化投票模块关键代码public void initVote() throws Exception{ initConnection(); String sql="UPDATE T_VOTE SET VOTE = 0"; PreparedStatement ps = conn.prepareStatement(sql); ps.executeUpdate(); closeConnection();}public void initTicket() throws Exception{ initConnection(); String sql="UPDATE T_USER SET TICKET = 1"; PreparedStatement ps = conn.prepareStatement(sql); ps.executeUpdate(); closeConnection();}
    5.1.7 注销登录模块关键代码<% session.invalidate(); response.sendRedirect("loginForm.jsp");%>
    5.1.8 非法用户的session检查管理员权限
    <% User user =(User)session.getAttribute("user");if(session.getAttribute("user")==null||user.getAdmin()==false { %> <jsp:forward page="loginError.jsp"></jsp:forward> <% } %>
    普通用户权限
    <%5.1.8非法用户的session检查管理员权限: User user =(User)session.getAttribute("user"); if(user==null){ %> <jsp:forward page="loginError.jsp"></jsp:forward> <% } %>
    5.1.9 防刷票的实现public int ticket(String account) throws Exception{ initConnection(); String sql ="SELECT TICKET FROM T_USER WHERE ACCOUNT= ? "; PreparedStatement ps = conn.prepareStatement(sql); ps.setString(1, account); ResultSet rs = ps.executeQuery(); rs.next(); int ticket =rs.getInt("TICKET"); if(ticket==0) { closeConnection(); return 0; } else { closeConnection(); return 1; } }
    5.2 数据库与操作设计开发5.2.1 连接数据库public void initConnection() throws Exception { Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");conn=DriverManager.getConnection("jdbc:sqlserver://localhost:1433;DatabaseName=Vote;user=root;password=123456789"); }
    5.2.2 数据库操作设计public User getUserByAccount(String account) throws Exception{ User use = null; initConnection(); String sql="SELECT ACCOUNT,PASSWORD,UNAME,ADMIN FROM T_USER WHERE ACCOUNT = ?"; PreparedStatement ps = conn.prepareStatement(sql); ps.setString(1, account); ResultSet rs =ps.executeQuery(); if(rs.next()) { use = new User(); use.setAccount(rs.getString("ACCOUNT")); use.setPassword(rs.getString("PASSWORD")); use.setUname(rs.getString("UNAME")); use.setAdmin(rs.getBoolean("ADMIN")); } closeConnection(); return use; }
    6 测试与部署6.1 运行环境
    平台:Windows10
    开发环境:JDK 1.8、 Eclipse4.9、 Tomcat6.0、 SQL server 2008

    6.2 功能测试6.2.1 防止非法访问功能
    功能描述:未登录的用户不能访问受限页面,已登录的普通用户不能访问管理员权限页面
    目的:防止未授权访问,保证安全性
    前提条件:无
    输入:浏览器地址栏直接输入页面地址
    输出:身份验证通过,转到要访问页面;身份验证不通过,转到拒绝访问页面
    是否实现:实现

    6.2.2 初始化投票功能
    功能描述:管理员清空当前投票
    目的:初始化投票者的票数及被投票者的得票数
    前提条件:登录到管理员页面
    输入:点击初始化投票链接
    输出:初始化成功转到管理页面
    是否实现:实现

    6.2.3 登录功能
    功能描述:输入用户名和密码登陆到系统,不同用户登录到不同界面
    目的:检验数据判断能否登陆
    前提条件:进入登陆界面
    输入:用户名和密码
    输出:数据判断成功,普通用户登陆到投票界面,管理员用户登录到后
    一台管理界面:数据判断失败,转到失败页面
    是否实现:实现

    6.2.4 注销登录功能
    功能描述:已登录到系统的用户可以通过注销来退出系统
    目的:用户退出时,清空用户session
    前提条件:用户已登录
    输入:点击注销链接
    输出:注销成功转到初始欢迎页面
    是否实现:实现

    6.2.5 投票功能
    功能描述:给相应的所选教师投票
    目的:实现数据库中相应教师得票数的数据更新
    前提条件:成功登录到投票界面
    输入:勾选教师,点击投票
    输出:相应老师的得票数加1
    是否实现:实现

    6.2.6 添加用户功能
    功能描述:管理员添加用户账号到系统中
    目的:在数据库用户表中添加用户账号信息
    前提条件:成功登录后台管理页面
    输入:新的用户数据
    输出:创建用户成功,输出成功提示转到管理界面;创建用户失败,输出相应失败提示转到管理界面
    是否实现:实现

    6.2.7 删除用户功能
    功能描述:管理员从系统中删除用户账号
    目的:在数据库用户表中删除用户账号信息
    前提条件:成功登录到后台管理页面
    输入:要删除用户的账号
    输出:删除用户成功,输出成功提示转到管理界面;删除用户失败,输出相应提示转到管理界面
    是否实现:实现

    6.2.8 修改用户功能
    功能描述:管理员修改系统中已存在的用户信息
    目的:在数据库中修改相应的用户信息
    前提条件:登录到后台管理页面
    输入:要修改的账号及新的用户信息
    输出:修改成功,输出成功提示转到管理界面;修改失败输出相应失败提示转到管理界面
    是否实现:实现-

    6.2.9 显示系统用户功能
    功能描述:在管理页面显示当前系统中已存在的账号及是信息
    目的:显示账号,账号用户及是否投票
    前提条件:登录到后台管理页面
    输入:无
    输出:系统中的账号信息
    是否实现:实现

    6.2.10 显示得票数功能
    功能描述:在管理页面及投票页面显示当前的得票情况
    目的:显示各教师的得票数,并以相应比例长的的矩形显示
    前提条件:登录到系统中
    输入:无
    输出:各教师的得票情况
    是否实现:实现

    7 结论分析为期数天的jsp集中上机课程设计让我受益匪浅。和上学期数据库课程设计不同,这次要求我们每个人都要做,主要是考查我们jsp 动手实践能力。这次的课程设计让我再一次翻起了sql课本,已经有好些知识忘了,借此机会刚好复习了一遍,由于这次时间安排的比较紧,赶在了我们期末考试这一特殊时期,所以我选择做个功能齐全的投票系统,其实也算不上齐全,但是也学了不少东西。特别是在具体功能的设计上遇到很多问题,但是经过我上网搜索资料以及寻找同学帮助,这些问题都迎刃而解了。但是不足的时还有很多想做的功能由于时间的关系没有实现,例如动态管理投票对象、更改用户可投票数、非匿名投票等等。
    经过了数天的学习研究,终于完成了该课程设计的架构到实现。从开始选定题到系统的规划实现,再到报告的完成,这次的课程设计是对于我们是一个很好的锻炼,通过本次设计,我基本明确了一个基于jsp应用系统从设计到开发的大致流程和重点关注的方向,同时对JSP, SQL语句数据库关系等都有了基本的掌握和应用能力。
    通过这次课程设计,我再一次感受到jsp的魅力,自己设计的不是特别完美,但毕竟做成果,心里很高兴,我们对学习jsp的信心也增强不少。
    参考文献[1] 郭克华、奎晓燕. Java Web程序设计 清华大学出版社2011
    [2] 明日科技 HTML5从入门到精通 清华大学出版社2012
    [3] 何玉洁 数据库基础与实践技术(SQL Server 2008) 机械工业出版社2018
    0 评论 6 下载 2019-07-25 11:35:59 下载需要5点积分
  • 基于QT实现的飞机大战游戏

    一、课程设计内容与目标通过类的继承等来实现一个飞机小游戏,首先实现控制台版的飞机游戏,然后修改与显示相关的部分代码完成从控制台到图形界面的迁移过程。
    飞机游戏中要实现以下几个基本要素:

    玩家飞机发射子弹攻击敌机
    敌机可以发射子弹攻击玩家
    玩家飞机可以自由移动,敌机可以定向移动
    玩家飞机与敌机只有在真正边界相撞时才算相撞,且相撞时双方均要受到一定伤害

    在课程设计一中,我实现了上述的基本功能,并提供了向图形界面的接口函数,在课程设计一中,玩家飞机和敌机均可以通过简单的代码修改任意更改形态
    在课程设计二中,我添加了程序启动界面(就是此实验报告的封面),欢迎界面、背景音乐、暂停、玩家飞机技能、补给掉落、boss 等功能,游戏界面如下图:

    在此游戏中,右下角的 SCORE 为玩家当前击落的敌机数,绿色进度条为玩家飞机当前的血条,下面的蓝色进度条为玩家飞机当前的技能条。玩家可以使用消耗技能值实现一技能,如按 Q 可以三连发(如上图),按 E 可以一次性击落当前所有敌机,按 R 可以一次性消掉当前所有子弹。
    二、类层次关系和实现本次实验中,我总共设计了如下几个两个基类 Plane 和 Bullet。Plane 派生出MyPlane和 EnemyPlane 两个子类。还有一个 Control类管理全局。两次课程设计中主要使用的类没有发生变化,只是类之间的关系稍有变化。
    2.1 第一次课程设计(控制台版)第一次课程设计(控制台版)中各类关系如下:

    如图,Plane 类中聚集了 Bullet 类的实例 bullets 数组,用于记录该飞机发出去的子弹;Plane 类派生出两个子类,MyPlane 与 EnemyPlane,分别是玩家飞机与敌机。这两个类均聚集在 Control 类中,由 Control 类对所有飞机的状态进行管理。由于 Control 与 Plane、MyPlane、EnemyPlane 关系密切,故我将 Control类设置为这几个类的友元。
    在这个版本中,我通过一个循环来检测用户的按键输入和定时动作,如下:

    keyboardHandle是我自己写的一个函数,用于根据用户的不同按键获取用户输入。
    2.2 第二次课程设计(图形界面版)第二次课程设计(图形界面版)中对类的关系进行了一些优化。因为 Plane和 Bullet 类都有一些共同的属性,所以设计了一些共同的基类 Object,以实现一些共同的性质,如 synScreen,delScreen 等。第二次课程设计是用的是 Qt 的QGraphicsScene、QGraphicsItem、QGraphicsView 三组件,其中 Control 继承自QGraphicsScene,Plane 与 Bullet 继承自 QGraphicsItem,在 main 函数中创建QGraphicsView与QGraphicsScene 相关联,主要操作都在 Control中完成。
    类结构图如下:

    第二次课程设计中,Bullet 类不再聚集在 Plane 类中,而是直接实例化为两个数组,聚集在 Control中,便于管理。Object 类均需要使用图片来初始化,所以都是 Qt 提供的 QGraphicsPixmapItem 类的子类。而 Control 类抽象成为QGraphicsScene 类的子类,用于管理 Scene 中的各个 Item。
    除此之外,为了丰富游戏内容,还在增加了其他的一些组件,用以实现游戏启动界面、欢迎界面、背景音乐、血条、技能条、游戏暂停、游戏结束等功能。
    类名及相关游戏组件如下:

    QGraphicsTextItem 游戏标题、提示信息等
    QGraphicsWidget 游戏按钮、遮罩面板(用于在游戏暂停时达到场景变暗的效果)
    QGraphicsRectItem 血条、技能条。

    此外,检测玩家按键输入和定时动作的方式也使用了 QObject 提供的消息机制来实现,使用了如下事件函数:

    timeEvent() 用于接收计时器消息,实现飞机、子弹定时移动,敌机的定时生成
    keyPressEvent() 用于接收键盘控制,实现玩家控制

    三、课程设计一和二的关联与衔接课程设计一为了向课程设计二过渡,设计了一些共同的接口函数,在迁移过程中仅需修改参数即可。
    在过渡中优化了一部分类的设计,比如发现 Bullet、Plane、LifeSupply 都有共同的属性,故让这三个类均继承自 Object 类。
    Object 类与显示相关的函数变动如下表:

    delScreen 用于将子弹在屏幕上抹去,synScreen 用于将子弹显示在屏幕上,hit 用于子弹与飞机相撞时降低子弹生命值,生命值降为 0 时抹去子弹。
    Bullet 类只需要改动一个函数:

    其中 char **screen 为控制台版中 Control 类的一个成员变量,用于保存要在屏幕上显示的所有字符;在图形界面版中 Control类继承自 QGraphicsScene,本身就保存了所有要显示的信息,所以可以直接将 Control类指针传进去。
    Plane 类也只需改动一个函数:

    crash用于飞机与飞机或子弹相撞时降低生命值,生命值降为0时抹去飞机。
    Control类变化较多,因为 Qt中有一些现成的库函数,所以有些地方可以直接使用库函数,变化如下:(参数略去)

    另外,为了更好地适应图形界面,也对一些功能做出了修改,比如控制台版本的子弹相撞可以消掉,但是图形界面中玩家飞机子弹与敌机子弹不能消掉。
    除此之外,为了丰富游戏,增强游戏可玩性和趣味性,还添加了其他的函数以实现:游戏启动界面、游戏欢迎界面及帮助、游戏暂停、背景音乐、玩家技能、随机掉落补给等等功能。
    四、实验成果展示4.1 第一次课程设计(控制台版)控制台版的飞机大战较为简陋,但是可拓展性较好。敌机和玩家飞机的形状可以直接通过更改代码中定义的一个静态数组来改变,且碰撞也是按照实际形状来检测的。玩家可以通过一些按键来控制右侧栏中一系列参数:生命值、子弹威力、子弹速度等等。玩家子弹和敌机子弹相撞时会同时销毁。运行效果如下图 :

    4.2 第二次课程设计(图形界面版)我为我的程序设计了一个安装包,已在附件中。安装之后会在桌面创建一个快捷方式,双击便可运行。如下是启动画面 :

    欢迎界面如下 :

    点击开始游戏,右下方 SCORE 为分数,绿色进度条为生命值,蓝色进度条为技能值,可以使用 J、K、L 三个键释放技能。同时,敌机被击落的时候也会随机掉落声明补给(绿色的加号)。

    按空格键可以暂停,暂停时背景变暗。

    生命值耗尽时游戏结束,玩家可以选择重玩或者退出游戏。

    五、遇到的问题和思考5.1 代码复用的思考在这第一次设计中,类的继承主要体现在 Plane 派生出 MyPlane 与EnemyPlane 上,起到了不错的效果。但是还有可以改进的地方。
    在完成第二次课程设计的过程中,我考虑到在 Bullet 类和 Plane 类中都有delScreen、synScreen 函数功能也非常接近,且有一些共同的成员变量,如果要更好地复用的话,应该让 Bullet 类与Plane 类都继承自同一个 Object 类,于是设计了 Object 类,这样在后续添加新的游戏道具时也会更加方便。
    5.2 字符界面过渡图形界面遇到的困难由于之前没有图形界面编程的经验,所以不知道应该怎样为图形界面留出接口,后来决定用 Qt 之后,查了一些关于 Qt 的资料了解到 QGraphicsScene 与QGraphicsItem 提供的库函数,于是设计了上述的一些函数便于代码迁移。
    5.3 对文档-视结构的思考在 MFC 的文档-视结构中,程序的数据储存在文档类中,文档类是对数据的抽象表示。数据显示由视图负责,视图是程序窗口的客户区,框架窗口是客户区的框架,程序数据显示在窗口,用户通过视图与程序交互。
    在第二次课程设计中,我的代码结构与此类似。我使用的 QGraphicsScene(Control的基类)类似于文档-视中的 CDocument 类,保存的是程序的数据(飞机、子弹、提示信息等);QGraphicsItem 就是文档-视中的数据,通过QGraphicsScene 的 addItem 函数加入到场景中,由 QGraphicsScene 管理;QGraphicsView 类似于文档-视中的 CView 类,通过其 setScene 函数与QGraphicsScene 建立关联。
    2 评论 195 下载 2018-11-05 16:26:20 下载需要10点积分
显示 60 到 75 ,共 15 条
eject