分类

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

资源列表

  • 基于Python实现的孤立词语音识别系统

    1 任务介绍语音识别是通往真正的人工智能的不可缺少的技术。尽管能真正听懂人类说话的智能机器任然在未来不可捉摸的迷雾之中,但我们必须先解决如何识别出人类语音中包含的自然语言信息的问题。而数字信号处理技术将为这一任务赋能。在本课程项目的任务之中,我们面对的是一个简化的语音识别场景——即孤立词识别。
    我们针对 20 个关键词,采集了所有参与课程的同学朗读每个词 20 遍的语音。我将以此为数据集来构建一个能正确识别这 20 个关键词的孤立词识别系统。
    2 项目实现基于一学期跟随老师学习到的关于信号处理与语音识别技术的知识,我额外查阅多方资料,最终呈现出了我的语音识别系统与报告。
    我实现的语音识别系统的亮点有以下几个方面:

    说话人无关的孤立词识别是语音识别技术发展中一个里程碑。从现代的观点来看,如果将语言信号视作时间序列,那么孤立词识别就是一个模式识别中的分类问题。模式识别问题的解决一般分为特征提取与模型构建两个部分。我们将这两个部分分开处理,使得代码的实现更加具有结构性和层次性。报告也将这两部分的处理分开叙述
    我在整个系统的实现中,除了利用了数值处理函数包 numpy 和自动求导工具包 pytorch之外的所有核心代码都是单纯使用 python 实现。即真正锻炼了代码实现能力,也加深了对语音识别技术的理解。在报告中我也强调了各个方法和过程的代码实现,并将关键代码添加到附录之中以方便检阅
    特别地,我基于课堂上所学的蝶形变换方法,实现了以 2 为基的快速傅里叶变换,并运用到了频域特征的分析之中。这让我更加领略到该算法的优美
    根据我自行实现的快速傅里叶变换,实现了梅尔频率域的倒谱系数的计算,并根据通过梅尔滤波器之后得到梅尔频谱特征设计了基于卷积神经网络的识别算法
    我将计算出的频谱特征视为图片,因而可以使用近年来在大规模图片分类任务上大放异彩的卷积神经网络来进行分类识别。我采用了 2014 年在 ImageNet 的比赛上获胜的VGG Net 作为我们的识别模型,并使用了批归一化和 Dropout 手段来避免过拟合,提高模型的泛化能力

    2.1 预处理首先我对数据进行了清洗。
    各个同学上交的文件结构并不一致,有的是一个压缩包下包含所有文件,有的是一个压缩包中还有以自己的学号命名的文件夹,此外还有一些同学提交的压缩包是在 MacOS 上进行打包的,因此还有一个额外的缓存文件夹。这样的结构不利于我们对数据进行批量的读入。
    因此我编写了程序先解压所有压缩包,然后进行深度优先搜索来遍历所有文件夹,根据文件的命名规则把所有文件提取出来,按照 data/学号/文件名.wav 的格式统一存储。同时因为需要大规模地进行复制提取,为了效率的考量,我使用多线程的方式完成了这一任务。
    此外有几个文件显示已损坏而无法读取,以及一个文件录音长度大于两秒。为了数据的一致性,必须去除掉异常数据,但仅仅删除数据将导致样本不均衡的问题。为此我采用随机替换的方式,用同一个同学在同一个词下的另一个语音文件进行替换。这样就可以缓解数据缺失带来的样本不均衡的问题。

    同时,考虑到最终测试时是采用集外测试的方法,理论上讲应剔除女生的数据。
    在接下来的报告中,如无特殊声明,用 y0, y1 · · · , yt, · · · 来表示离散的信号构成的序列,用 sr来表示采样率。
    2.2 特征提取2.2.1 归一化因为数据在采集的时候声音强度并不一致,为了消除影响,我对每一段音频数据进行归一化。这里只需要对 y 使用 numpy.normailize 方法即可。
    2.2.2 预加重对读入的数据,我首先通过预加重的方法来补偿由于唇和空气导致的声音在产生和传播中高频部分的损失。预加重通常采用一个一阶的线性高通滤波器

    来实现,其中 α = 0.97。在代码实现上,只需要对数组进行加权差分即可。
    2.2.3 分帧一般情况下,语音信号是一种典型的非平稳信号,但是可以认为人说话的语调变换并不是是突然的,因此可假定语音信号在短时间 (10-30ms) 内是平稳的;故而在对语音信号进行分析时,我们可以将语音信号以 10-30ms 的间隔将连续的音频信号截取成一段一段来进行分析。
    用 y[i : j] 来表示 yi, yi+1, · · · , yj−1,为一帧包含为 j − i 个采样点的语音信号,其时长为( j−i)/sr。
    因此,当音频信号采样率为 48kHz 的时候,想要得到时长为 10-30ms 的信号帧,其应该包含480-1500 个采样点。
    另外,从分帧后信号的连续性考量,一般在分帧的时候会让相邻的两帧有 30%-50% 的重叠。分帧的实现是简单的,只需要使用 python 支持的数组切片 (slice) 方法即可方便地取出一帧对应的采样点。
    2.3 加窗对于每一帧数据,我们应当强调该帧数据内中间部分的数据,并将边缘的数据进行弱化。我将使用汉明窗

    作为窗函数。

    而所谓的加窗操作也就是用窗函数与一帧内的采样数据相乘


    考虑之后要进行短时傅里叶变换,对每一帧数据进行加窗的理由将更加充分。观察图 2中的一帧余弦信号,可以看到其开始和结束的位置是断开的。而我们在做离散时间傅里叶变换的时候是将该帧数据在时域上无限延拓成周期信号,这将导致延拓之后的信号在帧的开始与结束会发生跳变。直接进行离散傅里叶变换将导致信号泄露的现象。如图 3所示,左边是取出开始和结束连续的一帧信号的离散傅里叶变换的结果,而中间则没有加窗直接进行变换,右边是加了汉明窗再进行变换的结果。可以观察到中间的结果在信号的主要频率周围有明显的泄露现象,导致在原始数据中不存在的频率成分出现在频率域。而增加了汉明窗后,频率泄露的现象有了明显的改善。

    2.3.1 端点检测为了减少非语音的信号对识别的影响,我首先通过信号的时域特征来检测出语音的端点。可以使用短时平均过零率和短时能量来进行端点的检测。
    想要检测出语音信号的端点,最简单的想法就是通过信号的强度来判断,因为包含语音的信号强度会明显高于背景噪声。而短时能量就是刻画信号强度的一个有效的指标。对信号进行分帧之后,y[i : j] 的短时能量定义为

    即帧内信号的平方和。但如果仅仅采用短时能量作为端点检测的指标,我们将很难检测出清音信号,从而导致语音不完全,譬如说单词”Speech” 中开始的清音就无法检测出来。因此我们引入短时平均过零率这个指标

    即该帧内信号通过 0 的平均次数。
    因为无法检测出来的清音一般出现在单词的开始或者结束,所以我们采用以 SE 指标为主、SC 指标为辅的检测策略。首先观察到不少数据在一开始会有类似敲击键盘的的清脆噪声,导致 SE 指标较大,因此我去掉了前五帧信号;然后我设定一个阈值 E0,对于 SE > E0 的帧,可以断定其包含语音信号;取最开始判定为有语音的帧的开始和最末尾有语音的帧的结束作为粗糙的端点检测结果,再根据 SC 指标,设定一个平均过零率阈值 C0,根据粗糙的结果向前、向后扩展 SC > C0 的帧作为包含清音信号的判定条件。

    问题的难点在于阈值的设定,在多次试验后,我选择了 E0 = 0.98, C0 = 0.002 的参数,可以对大多数数据做到较好的端点检测效果。如图 4所示,上方为用红色标出检测结果的波形,中间为短时能量,下方为短时平均过零率。可以看到,如果仅仅使用短时能量进行检测,将无法测出开始的清音,而短时平均过零率的指标则将清音也一并检测出来了。
    2.3.2 快速傅里叶变换为了得到信号的频域特征,需要对每一帧信号进行离散傅里叶变换,即计算

    假设一帧数据的采样点数 N 是 2 的整次幂,那么

    从而

    用 Ek 表示偶数下标子序列的 DFT,Ok 表示奇数下标子序列的 DFT,则 k < N/2 时

    而 k > N/2 时

    这样就可以按照下标的奇偶性将待变换的信号序列拆成两半,递归地进行计算,然后在从递归计算的两个子序列的结果中计算出整个序列的离散傅里叶变换。该算法被称为基 2 的 CooleyTukey快速傅里叶变换。显然该算法计算量为 T(n) = 2T(n/2) + Θ(n)。根据主定理,该算法的时间复杂度为 Θ(n log(n))。
    在递归的过程中,数据的组合与流向的图样像蝴蝶一般对称而美妙,因此被称作蝶形变换。

    我用 python 实现了该算法,并将其利用到后续的梅尔频率域的频谱特征的计算之中。优美的算法通常在实现上也十分简洁。
    2.3.3 梅尔频率域特征梅尔频率域的理论依据来自于人耳听觉对频率的感受。耳蜗相当于一个滤波器组,在 1000hz以下为线性尺度滤波,在 1000hz 以上为对数尺度滤波。通过 fMel = 2595 + log(1 + f/700) 可以将普通频率变换到梅尔频率尺度,观察这个变换的图形会发现在 1000hz 以下会有更高的分辨率,这和人耳对低频信号更加敏感是相符的。在变换之后的梅尔频率尺度取等间隔的带通滤波器组求倒谱即可得到梅尔倒谱。

    对前述通过预加重、分帧、加汉明窗,离散时间傅里叶变换后得到的频谱变换到梅尔频率域,然后施加等间距的三角形滤波器,对滤波后的结果进行求和和取对数操作,即可得到梅尔频率尺度下的功率谱。

    仔细观察该功率谱的结果,对于同一个词来说,在谱上的图样具有明显的图形特征。我们想到可以将其视为图片,然后利用图片的分类技术对语音进行识别。
    传统上的语音识别特征会继续用离散余弦变换求出倒谱系数。余弦变换是傅里叶变换的一个变种,其结果是实数,没有虚部。离散余弦变换还有一个特点是,对于一般的语音信号,这一步的结果的前几个系数特别大,而后面的系数比较小,就可以忽略。这样就可以对特征进行降维,只需要十几个系数即可作为特征。这对于使用传统的模式识别的方法来说特别重要。
    因为无论是支持向量机、高斯混合模型都需要数据的特征在各个维度上是无关的。而不必要的高维度必然导致特征的相关性,从而使得决策面变得扭曲。但使用深度神经网络的方法则不用担心这一点,因为它可以拟合出任意决策面。
    至此完成了对特征的提取,接下来只需要根据特征图样对进行分类即可。
    2.4 识别模型2.4.1 模型构建我使用了 128 个梅尔滤波器,并使用 30ms 作为分帧长度,以及 10ms 的重叠,因此最终得到的图样大小为 128 × 98。
    我仿照 VGGNet 的设置,使用大小为 3 × 3 的卷积核,并构建了 8 层深度的卷积神经网络。因为经过每一层卷积之前都会对图片进行 1 × 1 的补 0 操作,所以对任意大小的图片都可以进行卷积。在经过卷积网络后,我使用一个多层感知器来作为最后的分类器。
    其具体结构如下:

    为了避免过拟合,我对多层感知机的神经元进行概率为 0.5 的 Dropout,并在每一层的卷积操作和非线性函数之间对进行批归一化。
    2.4.2 数据加载考虑到对模型进行训练和测试的复杂性,需要多种数据的加载方式。首先是对数据集进行划分,我需要将一部分同学的所有语音单独拿出来作为测试集,因为最终测试的时候的说话人并不在我们的训练数据中。其次是因为数据量有限,每个词只有不到 600 个的训练数据,为此我对数据进行了交叉验证的划分,采用 10 折交叉的数据划分方式。我利用 pytorch 提供的 Dataset 和 Dataloader 模块,编写了自己的数据加载器。
    2.4.3 模型训练利用 pytorch 提供的自动反向传播,利用交叉熵损失函数作为优化目标,对模型进行了训练。在一台配置为只需要迭代 5 遍测试数据集即可将模型训练至收敛。

    绘制出训练的损失曲线如下图:

    训练结束后,在训练集上能取得 99.5% 的正确率,而对于不在训练集中的说话人,也能取得98.0% 的正确率。说明该模型的确具有非常好的泛化能力。接下来我编写了交互界面,用于进行直接录音测试。
    2.5 识别交互为了方便测试系统的语音识别效果,我基于我之前设计的录音采集系统进行了修改,使得我的系统可以在任何兼容的浏览器上进行测试,避免了为了测试而配置一系列复杂的环境。
    2.5.1 前端界面基于 Web APIs 技术,通过浏览器获取用户的麦克风进行音频录制。完成录制之后通过 JQuery框架使用 ajax 技术进行语音的上传和获取识别结果,再通过 Vue 框架实现的自动绑定,进行结果展示。这样可以实现不用刷新页面即可进行测试的效果,使得使用体验与桌面应用无异。

    2.5.2 服务器端为了能使用训练好的模型进行测试,我利用 flask 编写了服务端。当其接受到前端传回的语音信号后,就会构建模型,并载入训练好的模型参数,然后进行识别。完成识别后,再将结果传回到前端进行显示。
    3 总结在本项目中,我实现了一个识别效果较好的孤立词识别系统。在这一系列过程中,我编写了大量代码,即锻炼了自己的能力,又讲一学期学到的知识真正运用到了实践之中,加深了对知识的印象和理解。
    2 评论 8 下载 2019-04-18 11:27:58 下载需要12点积分
  • 基于ASP.NET实现的大学BBS论坛

    一、分析与建模1.1 系统业务流程图
    1.2 可行性分析1.2.1 法律可行性该理工学院的BBS论坛系统是为了方便理工学院的大学生进行学习、生活、考研、就业、二手交易、心得体会交流的交流社区网上系统,且规范相关部门工作流程,也可以解决现阶段所大学生一些存在的许多问题,没有违反国家相关法律法规,该项目在法律上是完全可行的。
    1.2.2 技术可行性理工学院的BBS论坛系统,采用SQL Server数据库作为系统的数据存储容器,其强大的备份恢复机制保证了数据的安全性。同时,还是具有高效的结构化查询语言的支持,让系统可以在庞大的数据中很容易得到所需要的统计与分析。前台采用HTML+CSS+JavaScript+ASP.NET等技术,实现了较为友好的人机交互。目前,该项目所需的技术都已经有对应的产品,因此该项目在技术上是可行的。
    1.2.3 经济可行性经过有效的成本/效益分析所计算,得到的净现值是正数,说明该项目收益率为正数,有投资的价值。并且使用该理工BBS论坛系统可大大的增加我校理工的大学生在衣食住行学的多个方面的及时沟通,还可以与附近的湖北师范大学的学生一起进行思想上面的沟通,生活上面的便利交流。最为关键的是相当提供了一个有效的信息沟通平台。增加了许多的便利和一些事情的公开与透明。同时大提高学生学习的效率,缩短信息处理周期,也可以教学质量更上一个台阶,。且在还可以在成功运行试水之后,合适的话,到其他的大学进行推广。从而收取部分经济效益。达到回本和盈利的目的。综合以上分析,该系统的开发在经济上是可行的。
    1.2.4 操作可行性BBS论坛系统是完全根据我校大学生的具体需求量身定制了,在工作流上完全细心周到的服务 。此外,系统的用户交互设计较为友好,功能分明,操作简单,且提供了较为详细的用户简介使用手册和具有良好的新手指导功能。因此,该系统在操作上是可行的。
    1.3 功能需求分析与建模
    1.4 数据需求分析与建模任何一个软件系统本质上都是信息处理系统,对软件设计有深远影响,因此,必须分析系统的数据要求, 而这里为了把用户的数据要求清楚、准确地描述出来,我通过建立E-R图来进行描述,表示的是系统的E-R图。

    二、系统设计2.1 功能结构设计
    2.2 数据库设计2.2.1 实体以及相关的属性
    用户表(t_user)用户编号(唯一,自增长),邮箱,头像,手机号码,网名,密码,注册时间(唯一),性别,真实姓名,身份标识
    小板块表(t_section)小板块编号(唯一,自增长),所属大板块编号,用户编号,小版块名称,小版块标志
    大板块表(t_zone)大板块编号(唯一,自增长),大板块名称,大板块简介
    帖子表(t_topic)帖子编号(唯一,自增长),用户编号,小版块编号,帖子内容,修改帖子时间,第一次发帖时间,帖子标题,帖子点赞数,帖子置顶标记
    回帖表(t_reply)回复帖编号(唯一,自增长),最后回帖时间,回帖时间,回帖内容,回复的帖子标题

    2.2.2 实体之间的联系
    一个用户可以发表多个帖子(一对多的关系)
    一个用户也可以有回复多个回帖(一对多的关系)
    一个用户可以是多个小板块的版主(一对多的关系)
    一个小板块只能够是属于一个大板块空间的(一对一的关系)
    一个大板块空间是可以有多个小板块的(一对多的关系)
    一个帖子可以有多个回复的帖子(一对多的关系)

    2.2.3 物理模型图
    2.2.4 生成的属性信息等关系所有的表



    序号
    中文
    名称
    代码
    数据类型




    1
    回帖
    t_reply
    t_reply



    2
    小板块
    t_section
    t_section



    3
    帖子
    t_topic
    t_topic



    4
    用户
    t_user
    t_user



    5
    大板块
    t_zone
    t_zone




    所有表的属性



    序号
    中文
    名称
    代码
    数据类型




    1
    编号
    id
    id
    int


    2
    名称
    name
    name
    Variable characters (100)


    3
    描述
    description
    description
    Variable characters (200)


    4
    标号
    id
    id
    int


    5
    邮箱
    email
    email
    Variable characters (100)


    6
    头像
    face
    face
    Variable characters (200)


    7
    手机号
    mobile
    mobile
    Char(11)


    8
    网名
    nickname
    nickname
    Variable characters (50)


    9
    密码
    password
    password
    Char (20)


    10
    注册时间
    regtime
    regtime
    Data&Time


    11
    性别
    sex
    sex
    Char(2)


    12
    真实姓名
    truename
    truename
    Char(20)


    13
    身份类型
    type
    type
    Char(4)


    14
    编号
    id
    id
    int


    15
    大板块编号
    t_z_id
    t_z_id
    int


    16
    用户编号
    t_u_id
    t_u_id
    int


    17
    名称
    name
    name
    Char(50)


    18
    标志图片
    logo
    logo
    Char(20)


    19
    编号
    id
    id
    int


    20
    用户编号
    t_u_id
    t_u_id
    int


    21
    大板块编号
    t_s_id
    t_s_id
    int


    22
    内容
    content
    content
    Variable characters (1000)


    23
    修改时间
    modifytime
    modifytime
    Data&Time


    24
    回复时间
    publishtime
    publishtime
    Data&Time


    25
    标题
    title
    title
    Variable characters (100)


    26
    点赞数
    good
    good
    Char(4)


    27
    置顶标记
    top
    top
    Char(4)


    28
    编号
    id
    id
    int


    29
    帖子编号
    t_t_id
    t_t_id
    int


    30
    用户编号
    t_u_id
    t_u_id
    int


    31
    最后回复时间
    modifytime
    modifytime
    Data&Time


    32
    恢复时间
    publishtime
    publishtime
    Data&Time


    33
    内容
    content
    content
    Variable characters (100)


    34
    标题
    title
    title
    Variable characters (1000)



    2.3 关键算法设计在这里一共进行了三个相关的算法,分别是服务器异常断开、重启状态、等突发事件算法设计,头像图片上传算法设计和用户相关信息防泄漏算法与设计。
    2.3.1 服务器异常、突发事件算法设计
    2.3.2 图片文件上传算法设计
    2.3.3 用户相关信息防泄漏算法与设计
    2.4 UI设计2.4.1 用户登陆UI设计
    2.4.2 用户注册UI设计
    2.4.3 置顶、精品UI设计
    2.4.4 大板块查看UI设计
    2.4.5 小板块查看UI设计
    2.4.6 回帖跟帖UI设计
    2.4.7 发帖UI设计
    2.4.8 小板块增加删除主题UI设计
    2.4.9 删帖修改帖子UI设计
    2.4.10 个人中心UI设计
    2.4.11 后台登录UI设计
    2.4.12 大板块增加删除查询UI设计
    三、系统实现中的重难点3.1 系统实现环境该系统采用Microsoft Visual Studio 2015的.Net Frame 4.5作为框架,页面使用了Html+Javascript+ASP.Net作为B/S模式下的前台开发工具,C#作为B/S模式下的后台编码语言,ASP.NET作为B端的数据访问技术,SQL SERVER 2012作为后台的数据库,页面的加载、效果作为div+css作为网页布局。

    开发硬件环境:个人笔记本电脑
    开发软件环境:win10 x64/ Visual Studio 2015/ SQL SERVER 2012/谷歌浏览器稳定版/火狐浏览器

    3.2 系统编码重难点重难点之多条件查询
    3.2.1 界面
    3.2.2 web代码<div class="container-fluid"> <div id="tooBar" style="padding: 10px 0px 0px 10px;"> <button class="btn btn-primary" type="button" data-backdrop="static" data-toggle="modal" data-target="#dlg" onclick="return openAddDlg()">添加小板块</button>     <a href="#" role="button" class="btn btn-danger" onclick="javascrip:deleteSections()">批量删除</a> <form method="post" action="/backstage/SectionList.aspx" class="form-search" style="display: inline;">  小板块名称: <input name="sectionname" id="peisnname" value="<%=sectionname%>" type="text" class="input-medium search-query" placeholder="输入小板块名称..."/>  所属大板块: <select id="zid" name="zid"><option value="">请选择...</option> <%foreach( hua_bbs.Model.Zone zone in zoneList) {%> <option value="<%=zone.id%>" <%= zid == zone.id.ToString() ? "selected": "" %> ><%=zone.name%></option> <%} %> </select>  版主: <select id="uid" name="uid"><option value="">请选择...</option> <% foreach( hua_bbs.Model.User user in userList) {%> <option value="<%=user.id%>" <%= uid == user.id.ToString() ? "selected": ""%> ><%=user.nickname %></option> <%} %> </select>   <button type="submit" class="btn btn-primary" title="Search">查询 <i class="icon icon-search"></i></button> </form> </div> <div id="dlg" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-hidden="true" onclick="return resetValue()">×</button> <h3 id="myModalLabel">增加小板块</h3> </div> <div class="modal-body"> <form id="fm" action="SectionList.aspx" method="post" enctype="multipart/form-data"> <input type="hidden" value="saveOrUpdate" name="flag"/> <table> <tr> <td> <label class="control-label" for="sectionName">请输入小板块名称:</label> </td> <td> <input id="sectionName" type="text" name="ssname" placeholder="请输入…"> </td> </tr> <tr> <td> <img id="ImgPr" class="pull-left" style="width: 120px; height: 120px;" /> </td> <td> </td> </tr> <tr> <td> <label class="control-label" for="logo">上传logo:</label> </td> <td> <input type="file" id="logo" name="logo"> </td> </tr> <tr> <td> <label class="control-label" for="zone">请选择所属大板块:</label> </td> <td> <select id="zone" name="zzid"><option value="">请选择...</option> <%foreach( hua_bbs.Model.Zone zone in zoneList) {%> <option value="<%=zone.id%>"><%=zone.name%></option> <%} %> </select> </td> </tr> <tr> <td> <label class="control-label" for="masterNickName">版主:</label> </td> <td> <select id="masterNickName" name="uuid"><option value="">请选择...</option> <% foreach( hua_bbs.Model.User user in userList) {%> <option value="<%=user.id%>"><%=user.nickname %></option> <%} %> </select> <font id="info" style="color: red;"></font> </td> </tr> </table> <input id="id" type="hidden" name="ssid"> <input type="hidden" id="peipage" name="page"/> <input type="hidden" id="peizid" name="zid"/> <input type="hidden" id="peiuid" name="uid"/> <input type="hidden" id="peisectionname" name="sectionname"/> </form> </div> <div class="modal-footer"> <font id="error" style="color: red;"></font> <button class="btn" data-dismiss="modal" aria-hidden="true" onclick="return resetValue()">关闭</button> <button class="btn btn-primary" onclick="javascript:saveSection()">保存</button> <!-- <button class="btn btn-primary" type="submit">保存</button> --> </div> </div>
    3.2.3 数据库代码public bool MyUpdate(hua_bbs.Model.Section model) { StringBuilder strSql = new StringBuilder(); strSql.Append("update t_section set "); strSql.Append("name=@name,"); strSql.Append("logo=@logo,"); strSql.Append("t_u_id=@t_u_id,"); strSql.Append("t_z_id=@t_z_id"); strSql.Append(" where id=@id"); SqlParameter[] parameters = { new SqlParameter("@name", SqlDbType.VarChar,40), new SqlParameter("@logo", SqlDbType.VarChar,100), new SqlParameter("@id", SqlDbType.Int,4), new SqlParameter("@t_z_id", SqlDbType.Int,4), new SqlParameter("@t_u_id", SqlDbType.Int,4)}; parameters[0].Value = model.name; parameters[1].Value = model.logo; parameters[2].Value = model.id; parameters[3].Value = model.t_z_id; parameters[4].Value = model.t_u_id; int rows = DbHelperSQL.ExecuteSql(strSql.ToString(), parameters); if (rows > 0) { return true; } else { return false; } } /// <summary> /// 得到一个对象实体 /// </summary> public hua_bbs.Model.Section DataRowToSectionZoneUser(DataRow row) { hua_bbs.Model.Section model = new hua_bbs.Model.Section(); model._user = new Model.User(); model._zone = new Model.Zone(); if (row != null) { if (row["id"] != null && row["id"].ToString() != "") { model.id = int.Parse(row["id"].ToString()); } if (row["sname"] != null) { model.name = row["sname"].ToString(); } if (row["logo"] != null) { model.logo = row["logo"].ToString(); } //得到板主id if (row["uid"] != null && row["uid"].ToString() != "") { model.t_u_id = int.Parse(row["uid"].ToString()); } //得到主题id if (row["zid"] != null && row["zid"].ToString() != "") { model.t_z_id = int.Parse(row["zid"].ToString()); } //得到板主名称 if (row["nickname"] != null) { model._user.nickname = row["nickname"].ToString(); } //得到主题名称 if (row["zname"] != null) { model._zone.name = row["zname"].ToString(); } } return model; } //获得Section,Zone,User(3张表的)数据列表 public DataSet GetSectionZoneUserListByPage(string strWhere, string orderby, int startIndex, int endIndex) { StringBuilder strSql = new StringBuilder(); strSql.Append("SELECT * FROM ( "); strSql.Append(" SELECT ROW_NUMBER() OVER ("); if (!string.IsNullOrEmpty(orderby.Trim())) { strSql.Append("order by s." + orderby); } else { strSql.Append("order by s.id desc"); } strSql.Append(")AS Row, s.id,s.name as sname,s.logo,z.name as zname,u.nickname,z.id as zid,u.id as uid from " + "t_section s , t_zone z , t_user u where s.t_z_id = z.id and s.t_u_id = u.id "); if (!string.IsNullOrEmpty(strWhere.Trim())) { strSql.Append(strWhere); } strSql.Append(" ) TT"); strSql.AppendFormat(" WHERE TT.Row between {0} and {1}", startIndex, endIndex); return DbHelperSQL.Query(strSql.ToString()); } /// <summary> /// 获取记录总数 /// </summary> public int GetSectionZoneUserRecordCount(string strWhere) { StringBuilder strSql = new StringBuilder(); strSql.Append("select COUNT(*) from t_section s , t_zone z , t_user u where s.t_z_id = z.id and s.t_u_id = u.id "); if (strWhere.Trim() != "") { strSql.Append(strWhere); } object obj = DbHelperSQL.GetSingle(strSql.ToString()); if (obj == null) { return 0; } else { return Convert.ToInt32(obj); } }public bool MyDelete(int sectionid) { List<Topic> topicList = topicService.GetModelList("t_s_id='" + sectionid + "'"); foreach (Topic topic in topicList) { replyService.DeleteByTid(topic.id);//删除此主贴下的所有回帖 } topicDao.DeleteByTsid(sectionid);//删除此板块下的所有主贴 return dal.Delete(sectionid); } /// <summary> /// 获得数据列表(3表操作) /// </summary> public List<hua_bbs.Model.Section> DataTableToSectionZoneUserList(DataTable dt) { List<hua_bbs.Model.Section> modelList = new List<hua_bbs.Model.Section>(); int rowsCount = dt.Rows.Count; if (rowsCount > 0) { hua_bbs.Model.Section model; for (int n = 0; n < rowsCount; n++) { model = dal.DataRowToSectionZoneUser(dt.Rows[n]); if (model != null) { modelList.Add(model); } } } return modelList; }
    3.2.4 C#代码using hua_bbs.BLL;using hua_bbs.Model;using System;using System.Collections;using System.Collections.Generic;using System.IO;using System.Linq;using System.Web;using System.Web.UI;using System.Web.UI.WebControls;namespace WebApplication.backstage{ public partial class SectionList : System.Web.UI.Page { public List<Section> sectionList { set; get; } public string pageCode { set; get; } public string sectionname { set; get; } public string zid { set; get; } public string uid { set; get; } public List<User> userList { set; get; } public List<Zone> zoneList { set; get; } private SectionService sectionService = new SectionService(); //入口方法 protected void Page_Load(object sender, EventArgs e) { string flag = Request["flag"]; if (flag == null || "".Equals(flag)) { this.show(sender, e); } else if ("saveOrUpdate".Equals(flag)) { this.saveOrUpdate(sender, e); } else if ("delete".Equals(flag)) { this.delete(sender, e); } } public void delete(object sender, EventArgs e) { string ids = Request["ids"]; string[] strid = ids.Split(','); for (int i = 0; i < strid.Length; i++) { sectionService.MyDelete(Int32.Parse(strid[i])); } Response.Write(true); Response.End(); } //添加或修改板块信息 public void saveOrUpdate(object sender, EventArgs e) { int ssid = 0; if (!Int32.TryParse(Request["ssid"], out ssid)) { ssid = 0; } string ssname = Request["ssname"]; int zzid = Int32.Parse(Request["zzid"]); int uuid = Int32.Parse(Request["uuid"]); HttpPostedFile file = Request.Files["logo"];//获取上传的图片 string logo = ""; //关于上传图片的代码 if (file != null && !file.FileName.Equals("")) { string fileName = file.FileName;//得到上传图片的文件名字 string ext = Path.GetExtension(fileName);//后缀名 if (ext == ".jpg" || ext == ".gif" || ext == ".png" || ext == ".jpeg") { string newFileNames = Guid.NewGuid().ToString() + ext; logo = "/images/logo/" + newFileNames; //img文件夹前面在加一个/表示为根目录(一级目录) string fileSavePath = Request.MapPath(logo); file.SaveAs(fileSavePath);//保存图片到服务器指定的目录中去 } else { logo = "/face/yyy123.gif"; } } else { logo = "/face/yyy123.gif"; } Section section = new Section(); section.id = ssid; section.name = ssname; section.t_u_id = uuid; section.t_z_id = zzid; section.logo = logo; sectionService.saveOrUpdate(section); //添加或者修改完成之后 this.show(sender, e); } //进行查询操作数据展示 protected void show(object sender, EventArgs e) { int pageNumber = 0; if (!Int32.TryParse(Request["page"], out pageNumber)) { pageNumber = 1; } uid = Request["uid"]; zid = Request["zid"]; sectionname = Request["sectionname"];
    3.3 系统测试在这一阶段的软件测试里面,在此列举系统的部分功能的测试,为了让大家都了解测试在网站设计过程中重要性,所以在这里将测试流程以及结果如下表暂时出来、并且做一点说明。对于其中开始的黑盒测试做了如下的一些测试,有效输入的等价类测试、无效输入的等价类测试、合法输出的等价类测试、非法输出的等价类测试、边界值的测试。
    测试用例表



    测试对象
    测试方法
    测试用例
    预期结果
    实际结果
    说明
    测试结果




    个人中心信息修改
    白盒测试
    点击“个人中心”“编辑”,输入要修改的信息等,点击“保存”
    弹出对话框提示“修改个人信息成功”
    弹出对话框提示“修改个人信息成功”
    测试和预期相符合
    成功


    发布公告
    黑盒测试
    点击“发布公告”,编写内容,点击“发布”
    弹出对话框提示“发布成功”
    弹出对话框提示“发布成功”
    测试和预期相符合
    成功


    密码修改
    黑盒测试
    输入Asd2345678
    密码修改成功
    密码修改成功
    修改密码,测试通过
    成功


    身份证号修改
    黑盒测试
    输入身份证号
    身份证号码修改成功
    身份证号码修改成功
    修改身份证号码为18位,测试通过
    成功


    图片文件上传
    白盒测试
    点击“发布公告”,编写内容,点击“发布”
    弹出对话框提示“你确定要上传”,“上传文件成功”
    弹出对话框提示“你确定要上传”,“上传文件成功”
    测试和预期相符合
    成功


    注册
    黑盒测试
    点击文件专区,“图片文件上传”,输入相关的文件信息,以及文件的路径,选择点击“提交”,点击“确定”
    弹出对话框提示“该用户已存在”,并且有记录
    没有弹出对话框提示“已存在信息”,也没有数据
    测试和预期相不符合
    失败


    成绩分数修改
    黑盒测试
    输入0
    学生成绩录入成功
    学生成绩录入成功
    教师录入学生成绩,测试通过
    成功


    密码轻度检测
    黑盒测试
    输入Qwe1234
    错误,密码长度太短
    错误,密码长度太短
    用户更改7位长度密码,测试通过
    成功


    分数类型校验
    黑盒测试
    输入99.9
    错误,分数必须为正整数
    错误,分数必须为正整数
    教师录入成绩有小数,测试通过
    成功


    权限设置,修改成绩
    黑盒测试
    修改成绩
    错误,你没有权限执行该操作
    错误,你没有权限执行该操作
    学生试图修改成绩,测试通过
    成功


    分数查询
    黑盒测试
    点击成绩页面,查询分数
    查询成功
    查询成功
    教师查询成绩,测试通过
    成功



    四、总结作为这一阶段的小学期课程的学习,其中的收获发感觉颇丰,在此之前直接接触的基于C/S架构的开发,然后设计过程之中,表之间的联系,数据的架构的过程比较较少。缺乏知识的完备性和完善性。而恰好借助这段时间的学习,我开始接触和了解具体怎么设计一个B/S架构的系统。 在这个里面,这是我写的多个asp.net项目面写的费时间最长, 耗费精力最大,首次商业化的使用MVC三层架构开发,其中在DAO控制层和Servicer业务层开发耗费力气比较大。在这个学习的中间,我觉得其中里面比较重点的知识点有:分页代码查询,多条件查询,多表查询,且有些功能比较重要,登录采用MD5加密,和验证码验证,还有勾选记住我,可以免密码登录在一定日期中,且普通用户具有发帖,评论等功能。版主具有回帖,发帖,删帖,修改个人信息等功能,管理员可以从右下角后台管理进入,登录,对大板块,小板块进行增加,批量删除,普通用户封号,添加还有整体的换肤,等功能。
    通过如上的一系列的功能的实现,其中大部分的设计的功能都是有实现,且通过了测试,但是作为这次的BBS论坛的设计与实现,其中的过程还是又遇到一些不会无法实现的地方,但是在学习的过程中,有老师的耐心讲解和思路上面的引导,和实例的书写,和最后的经过自己百度和谷歌,查询一些博客和资料之后,自己终于解决了,还是感觉非常开心的。在这里也,也今后的之学习路上,感觉自己还是有很多的不会,但是我相信自己,经过自己的学习,多听有着丰富经验的人的话。可以避免少走很多的弯路。让自己学的又快的又稳。展望未来。也希望自己的以后能够学习更多的知识。
    1 评论 1 下载 2019-08-15 09:00:33 下载需要12点积分
  • 基于java和Sql Server数据库的停车场管理系统

    一、实验内容:实现停车场管理系统,应用于车辆的出、入管理。
    二、功能要求:包括车辆进出管理与系统管理等功能模块,可根据车辆停放时间及收费标准自动收费。用户需要事先办理停车卡并充值,停车卡分优惠卡和普通卡两类。

    车场管理:车辆入场、车辆出场
    信息查询:某时间段的出入场信息,当前在场信息,车辆历史停车记录及收费信息
    信息维护:用户及停车卡信息维护、充值等
    系统管理:车位信息,计费标准等

    系统包含两类用户:管理员用户和普通用户。
    管理员可以使用系统所有功能,普通用户只能查询车辆历史记录、用户信息、停车卡充值,查询计费标准。
    三、实验环境:
    Windows XP
    JDK 1.6
    Eclipse
    SQL Server
    备注:

    在XP平台开发DK(JavaDevelopment Kit)是Sun Microsystems针对Java开发员的产品Eclipse进行前台和程序设计,开发图形用户界面和停车收费功能实施
    SQL建立数据库

    四、需求分析与设计:4.1 需求分析:本软件具有如下主要功能:

    本系统包括两类用户:管理员用户和普通用户。管理员可以使用系统所有功能,普通用户只能查询车辆历史记录、用户信息(只限于个人信息)、查询计费标准、查询当前在场信息、查询出入场信息、当前可用车位信息、口令修改。具体模块划分为如下模块:车场管理模块、信息查询模块、信息维护模块、系统管理模块。
    车场管理模块:(应该分为车辆入场和车辆出场两部分)

    车辆入场功能描述:车辆进入停车场时进行登记,记录入场时间并指定车位。只有具有停车卡的车辆才可进场,没有办理停车卡的车辆,应先办理车卡。如果没有相应车位,不能入场;如果卡中余额低于100元,应先充值后再入场。满足条件的车辆,为其指定车位并记录入场时间。车卡分两种类型普通型和优惠型。车辆出场功能描述:车辆开出停车场时进行登记,记录出场的时间并进行自动收费(从卡上扣除)。根据车辆进场时间,出场时间及收费标准自动计算车主应该缴纳的费用。如果停车时间包含不足一小时的时间,超过30分钟按一小时计算,不足三十分钟不计算。如果卡上余额足够则直接扣除;如果卡上余额不足,则应先充值后再扣除相应费用。
    信息查询模块功能描述:在这个模块里用户可以查询出入场信息、当前在场信息、用户个人信息、用户历史记录、收费标准以及当前可用车位信息
    查询出入场信息功能描述: 查询当前在场信息户可以在这里查询到两种车位的总量及当前可有的车位数量。
    查询用户个人信息功能描述:登录的管理员可以根据卡号和名字查询用户信息。登陆的普通用户只可以查到自己的信息。
    查询用户历史记录功能描述:用户可以输入卡号查询相应卡号的历史记录,包括车位号、开始停车时间、结束停车时间、停车总时间、相应收取的费用。
    收费标准功能描述:用户可以在这里查询不同种类的车位和不同卡的计费标准。
    当前在场信息功能描述:用户可以在这里查询到当前在场的车辆信息,包括卡号,车位号,开始停车时间。
    当前可用车位信息功能描述:在这里用户可以查询当前可用的车位的信息,包括车位号、车位类型。
    信息维护模块在这个模块里用户可以实现用户注册、用户修改及用户充值
    用户注册功能描述:在这里管理员可添加新的用户(普通用户)。
    用户修改管理员在这里可以修改用户。这里会以表的形式显示所有的用户信息,包括用户的停车卡信息维护,充值信息等。管理员点击相应的一行用户信息,这行信息会自动填充到表下的面板里,用户可以在面板里修改用户信息,面板下面有两个按钮,修改、删除,点击相应的按钮可以实现相应的功能。
    用户充值功能描述:用户可以再这里查到自己的余额,并且可以在这里完成充值。
    系统管理模块功能描述:在这个模块里可以修改相应的车位信息计费标准、注册管理员、更改用户口令以及查看系统声明信息。
    管理员注册功能描述:管理员可以在这里添加新的管理员。
    更改口令功能描述:用户可以在这里更该自己的密码。注:操作员只可以修改自己的密码。
    计费标准管理功能描述:管理员可以在这里不同车位类型、不同车卡类型的收费标准。
    关于功能描述:用户可以在这里看到系统声明。

    4.2 界面设计登陆界面

    管理员主界面

    普通用户主界面

    车辆入场界面

    车辆出场界面

    计费标准界面

    当场在场信息界面

    用户历史信息界面

    用户个人信息界面

    普通用户个人信息界面

    出入场信息界面

    当前可用车位信息界面

    用户注册界面

    用户修改界面

    用户充值界面

    管理员注册界面

    更改口令界面

    计费标准管理界面

    关于界面

    五、数据库设计5.1 数据库关系图
    5.2 数据表的结构设计


    用户表:users








    字段名称
    数据类型
    可空
    默认值
    说明


    cardid
    int
    不可

    主键,用户的停车卡号


    name
    Nvarchar(20)
    不可

    用户姓名


    password
    Nvarchar(20)


    用户密码


    cardtype
    Nvarchar(20)


    停车卡类型


    userstype
    Nvarchar(20)


    用户类型


    carid
    int


    用户车牌号


    tel
    int


    用户电话号码


    overage
    int


    用户余额






    车位信息表:sit_infor








    字段名称
    数据类型
    可空
    默认值
    说明


    stationid
    int
    不可

    主键,车位号


    stationtype
    Nvarchar(20)
    不可

    车位类型






    停车收费卡收费表:charger








    字段名称
    数据类型
    可空
    默认值
    说明


    cardtype
    Nvarchar(6)


    车卡类型


    stationtype
    Nvarchar(20)


    车位类型(车卡类型与车位类型一起作为主键)


    charge
    int


    价格






    停车表:park








    字段名称
    数据类型
    可空
    默认值
    说明


    cardid
    int


    车卡号(外键)


    stationid
    int


    车位号(外键)


    parkid
    int

    1,每次增加一
    停车号,主键


    startpark
    datetime


    停车开始时间


    endpark
    datetime


    停车结束时间


    fee
    int


    停车的收费


    sumpark
    int


    停车总时间



    六、关键技术介绍6.1 在其他类中得到当前登录用户对象 实现方法:在LoginFrame类中设置两个静态方法,在其他类中只需要引入LoginFrame类,然后调用他的静态方法即可。方法体如下:
    public static users getUser() { return user; } public static void setUser(users user) { LoginFrame.user = user; }
    6.2 实现用户类型不同,主界面不同的功能 可以定义静态方法disMenu().当用户是普通用户时,调用disMenu()方法即可。具体实现如下
    public void disMenu() { mnuPark.setEnabled(false); mnuSever.setEnabled(false); mnuManZhuCe.setEnabled(false); mnuManCharge.setEnabled(false); } if(user.getUserstype().equals("管理员")) { MdiFrame frame1 = new MdiFrame();//创建一个主窗体 frame1.setVisible(true);//设置其可见 LoginFrame.this.setVisible(false);//设置登录窗体为不显示 } else {//判断用户名是否为null MdiFrame frame = new MdiFrame();//创建一个主窗体 frame.disMenu(); frame.setVisible(true);//设置其可见 LoginFrame.this.setVisible(false);//设置登录窗体为不显示 }
    6.3 怎么得到系统时间 SimpleDateFormat myfmt=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); String a4 = myfmt.format(new java.util.Date()).toString();
    6.4 怎么计算时间差值 try { java.util.Date now = myfmt.parse(a3);//a3是系统当前时间(即出场时间) java.util.Date date=myfmt.parse(a7);//a7是入场时间 int l=(int) (now.getTime()-date.getTime());//计算毫秒差值 day=l/(24*60*60*1000);//获取天数 hour=(l/(60*60*1000)-day*24);//获得小时 min=((l/(60*1000))-day*24*60-hour*60);//获得分钟 } catch (Exception e1) { JOptionPane.showMessageDialog(null,"消费计算错误"); } if(min < 30)//如果分钟小于30分钟 a8 = day*24+hour; else //如果分钟大于30分钟 a8 = day*24+hour+1;
    6.5 怎么让布局更优美 使用布局管理器; GridBagLayout,以更改密码界面为例:
    getContentPane().setLayout(new GridBagLayout()); setBounds(234, 129, 285, 223); final JLabel label_5 = new JLabel(); label_5.setText("登 录 名:"); final GridBagConstraints gridBagConstraints_11 = new GridBagConstraints(); gridBagConstraints_11.gridy = 2; gridBagConstraints_11.gridx = 0; getContentPane().add(label_5, gridBagConstraints_11);
    七、系统实现功能结构图
    15 评论 428 下载 2018-11-19 09:31:15 下载需要10点积分
  • 基于react框架和MYSQL数据库的社团管理系统

    一、技术简介1.1 ReactReact 可以非常轻松地创建用户交互界面。为你应用的每一个状态设计简洁的视图,在数据改变时 React 也可以高效地更新渲染界面。以声明式编写UI,可以让你的代码更加可靠,且方便调试。创建好拥有各自状态的组件,再由组件构成更加复杂的界面。无需再用模版代码,通过使用JavaScript编写的组件你可以更好地传递数据,将应用状态和DOM拆分开来。
    1.2 JSX一种 JavaScript 的语法扩展。 我们推荐在 React 中使用 JSX 来描述用户界面。
    JSX 是在 JavaScript 内部实现的。我们知道元素是构成 React 应用的最小单位,JSX 就是用来声明 React 当中的元素。与浏览器的 DOM 元素不同,React 当中的元素事实上是普通的对象,React DOM 可以确保 浏览器 DOM 的数据内容与 React 元素保持一致。
    1.3 webpackwebpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。
    1.4 npmnpm 是 JavaScript 世界的包管理工具,并且是 Node.js 平台的默认包管理工具。通过 npm 可以安装、共享、分发代码,管理项目依赖关系。
    1.5 YarnYarn 对代码来说是一个包管理器,可以通过它使用全世界开发者的代码, 或者分享自己的代码。Yarn 做这些快捷、安全、可靠。
    通过Yarn可以使用其他开发者针对不同问题的解决方案,使开发过程更简单。 使用过程中遇到问题,可以将其上报或者贡献解决方案。一旦问题被修复, Yarn会更新保持同步。
    1.6 iViewiView 是一套基于 Vue.js 的开源 UI 组件库,主要服务于 PC 界面的中后台产品。
    1.7 Ant Designantd服务于企业级产品的设计体系,基于确定和自然的设计价值观上的模块化解决方案,让设计者和开发者专注于更好的用户体验。
    1.8 Eggegg.js是阿里推出的基于koa的node开发框架。为企业级框架和应用而生。Egg 的插件机制有很高的可扩展性,一个插件只做一件事(比如 Nunjucks 模板封装成了 egg-view-nunjucks、MySQL 数据库封装成了 egg-mysql)。Egg 通过框架聚合这些插件,并根据自己的业务场景定制配置,这样应用的开发成本就变得很低。
    Egg 奉行『约定优于配置』,按照一套统一的约定进行应用开发,团队内部采用这种方式可以减少开发人员的学习成本,开发人员不再是『钉子』,可以流动起来。没有约定的团队,沟通成本是非常高的,比如有人会按目录分栈而其他人按目录分功能,开发者认知不一致很容易犯错。但约定不等于扩展性差,相反 Egg 有很高的扩展性,可以按照团队的约定定制框架。使用 Loader 可以让框架根据不同环境定义默认配置,还可以覆盖 Egg 的默认约定。
    1.9 JSON Web TokenJSON Web Token(JWT)是目前最流行的跨域身份验证解决方案。它是一个很长的字符串,中间用点(.)分隔成三个部分。客户端收到服务器返回的 JWT,可以储存在 Cookie 里面,也可以储存在 localStorage。此后,客户端每次与服务器通信,都要带上这个 JWT。你可以把它放在 Cookie 里面自动发送,但是这样不能跨域,所以更好的做法是放在 HTTP 请求的头信息Authorization字段里面。
    1.10 KnexKnex.js是为Postgres,MSSQL,MySQL,MariaDB,SQLite3,Oracle和Amazon Redshift设计的“包含电池”SQL查询构建器,其设计灵活,便于携带并且使用起来非常有趣。它具有传统的节点样式回调以及用于清洁异步流控制的承诺接口,流接口,全功能查询和模式构建器,事务支持(带保存点),连接池 以及不同查询客户和方言之间的标准化响应。
    二、系统概要设计系统的设计主要前台和后台两个部分
    2.1 系统需求分析
    登录/登出
    社团信息管理

    新增/查询/编辑/注销社团移除社团成员关键字查询社团信息
    公告管理

    新增公告预览/查询/删除已创建的公告公告流量统计
    管理员管理

    添加/删除/编辑管理员权限验证
    个人信息管理

    用户名编辑修改密码

    2.2 可行性分析这里讲的可行性分析的任务是从技术上、经济上分析需解决的问题是否存在可行性。其目的是在尽可能短的时间内用尽可能小的代价确定问题是否有解。
    技术上的可行性分析主要分析技术条件能否顺利完成开发工作,硬、软件能否满足开发者的需要等。
    React是一个用于创建可重用且有吸引力的JavaScript框架。它非常适合代表经常变化的数据的组件。使用React,您可以通过将它们分解为组件而不是使用模板或HTML来构建可重用的用户界面。

    灵活性和响应性:它提供最大的灵活性和响应能力
    虚拟DOM:由于它基于文档对象模型,因此它允许浏览器友好地以HTML,XHTML或XML格式排列文档
    丰富的JavaScript库:来自世界各地的贡献者正在努力添加更多功能
    可扩展性:由于其灵活的结构和可扩展性,React已被证明对大型应用程序更好
    不断发展: React得到了Facebook专业开发人员的支持,他们不断寻找改进方法
    Web或移动平台: React提供React Native平台,可通过相同的React组件模型为iOS和Android开发本机呈现的应用程序

    无论是Web还是本机移动开发,React都是大多数用户界面设计平台的理想选择。
    本系统数据库使用的MySQL,MySQL是最流行的关系型数据库管理系统,在WEB应用方面MySQL是最好的关系型数据库,轻量、开源、简便易用,使用Navicat Premium 12做数据库图形化管理更高效率进行前后端开发。
    2.3 Server端模型
    由前台客户端发起请求来请求数据,Egg服务器判断是否在白名单或请求头中的token是否有效,若满足条件之一,则放行请求,根据router访问对应的controller,controller为数据的处理层,将数据处理好后通过service对数据库进行访问与操作,然后将service返回的结果在controller进行再次处理与封装,然后将响应数据和状态码(默认200)返回前台
    三、数据库设计3.1 数据概念结构设计E-R模型是数据进行第一层抽象的表示方法。它的主要成分包括:实体、联系和属性。我们可以用E-R图将内容表达出来,辅助设计的实现[6]。
    3.2 数据库关系设计该系统数据库关系图如下所示:

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



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




    id
    int(11)
    P

    自动递增


    login_name
    varchar(255)





    name
    varchar(255)





    password
    varchar(255)





    role
    int(1)


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


    isDel
    int(1)


    默认0



    学生表(student)



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




    stu_id
    varchar(255)
    P




    stu_name
    varchar(255)





    password
    varchar(255)





    sex
    int(1)


    0:男 1:女


    role
    int(1)


    0:未审核 1:家庭成员 2:业主


    tel
    varchar(255)





    社团表(community)



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




    id
    int(11)
    P

    自动递增


    title
    varchar(255)





    desp
    varchar(255)





    belong_dept
    int(11)





    manage_dept
    int(11)





    chairman_stu_id
    int(11)





    type
    int(11)





    create_time
    varchar(13)





    status
    int(1)


    0:未审核 ; 1:已审核 ; 2:已注销



    社团-学生表(community_student)



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




    id
    int(11)
    P

    自动递增


    stu_id
    int(11)





    community_id
    int(11)





    role
    int(11)


    0:成员; 1:社团管理员


    isDel
    int(11)





    社团类型表(community_type)



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




    id
    int(11)
    P

    自动递增


    type_name
    varchar(255)





    isDel
    int(11)


    默认0



    部门表(dept)



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




    id
    int(11)
    P

    自动递增


    dept_name
    varchar(255)





    isDel
    int(11)


    默认0



    公告表(notice)



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




    id
    int(11)
    P

    自动递增


    title
    varchar(255)





    author
    varchar(255)





    content
    text





    create_time
    varchar(255)





    isDel
    int(11)





    公告日志表(notice_log)



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




    id
    int(11)
    P

    自动递增


    notice_id
    int(11)





    stu_id
    int(11)





    create_time
    varchar(255)





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

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

    4.4 上传图片前端将图片以表单提交的形式传至后台,后台接受一个文件流,将其重命名后存放到目的位置,之后将完整路径发送至前端。

    五、页面设计页面采用蚂蚁金服出品的Ant Design UI 组件库,提供了完善的设计原则、最佳实践和设计资源文件(Sketch 和 Axure),来帮助业务快速设计出高质量的产品原型。
    5.1 登录页面
    输入用户名密码,点击登录,在对密码进行MD5加密后将login_name和password发送至后台,后台进行校验,匹配后将Json Web Token响应回来,将这个token存至cookie中,设定7天的过期时间,当前端再次发起其他请求时,将这个token带到请求头的Authorization字段中,供后台解析。
    若cookie中无请求头,则中止请求,使页面跳转回login页面,重新登录。

    5.2 主页
    antd支持layout和grid两种页面布局,这里采用layout布局,侧边栏通过递归一个JSON对象进行渲染对应的列表内容。

    获取到用户信息时,判断用户的角色,只有超级管理员才可显示管理员管理页签。
    顶部header下拉菜单可以直接跳转到个人信息或者退出登录。

    侧边栏通过collapsed状态进行切换开启或关闭状态。


    主题内容部分采用react-router-dom路由切换,根据url变化切换content内容。

    当页面均无法匹配到对应路由的时候,则进入noFound页面
    5.3 社团管理
    社团列表页面,做了关键字查询与分页功能,分页功能默认每页10条,可更改。

    点击编辑按钮可对当前社团进行更改。

    对每一项均做了填写校验。

    在选择社团主席时,输入学号进行远程搜索,动态选择。
    此处使用Lodash中的防抖功能对输入进行了优化,减少了多次请求造成的性能问题,也避免因请求返回次序不同造成的数据错误。



    当点击详情按钮时,可显示社团内成员,并进行了分组,可对成员进行直接移除。
    5.4 公告管理5.4.1 新增公告
    此处使用react-draft-wysiwyg富文本编辑器制作新增公告功能。编辑好的内容会以HTML标签字符串的形式发送给后台。当发送空值时内容为 ’<p></p>’,此时发布会提示没有添加正文,是否确定提交。

    由于富文本中添加图片是一个比较复杂的操作,此富文本编辑器默认仅可选择在线图片,可增加选取本地图片的选项,但是需要自己后台支持。

    在此处选择图片时,图片限制不可超过500KB并且只可选择’jpg’, ‘jpeg’, ‘png’, ‘gif’这四种格式的图片,选择成功后,会自动将图片上传至服务器,服务器会将处理好的图片的url返回至前台并显示在虚框内,点击添加即可显示到富文本编辑器中,发布时此处会变为<img />标签。
    5.4.2 公告列表
    在此处使用了骨架屏,在数据未完整请求到时,显示骨架,并且为骨架添加必要的延迟,避免白页与页面闪烁。


    当骨架结束后,页面显示内容,对数据进行必要的处理后,点击预览按钮可以显示手机模拟器,预览本条公告。

    手机页面可以进行滚动,但由于在电脑浏览器端显示滚动会有滚动条,很难去掉,有兼容性问题,为了提高体验,显示滚动条,然后将内层盒子扩大出一个滚动条的宽高,再将外层盒子进行over-flow设置为hidden,超出部分不可见,更好地实现模拟手机的滚动功能。


    点击删除按钮时会弹出提示。

    确定后才会删除(逻辑删除)
    5.4.3 流量统计
    默认显示一周以内的公告流量数据,此处使用echarts制作环形图,点击右侧可进行过滤上部时间picker可以选择时间范围,默认为一周内。通过此功能,可以对公告的阅读量进行统计,以便推出更受欢迎的公告资讯。
    5.5 管理员管理只有超级管理员可进入此tab,普通管理员进入不显示这个菜单项,如果在url处输入对应路径,会进入no permission(无权限)页面。


    进入管理员管理页面后,可操作其他管理员但不可操作自己与其他超级管理员。


    此处填写表单均做了表单校验,新增与编辑同理。
    5.6 个人信息
    此处分为基本信息模块与密码模块,基本信息模块可修改用户基本信息,此处只设置了姓名,还可以增加手机号,性别,个性签名,身份证号等等。
    密码模块必须正确输入之前的密码,两次新密码必须一致,而且要满足以字母开头,长度在6~18之间,只能包含字母、数字和下划线才可提交。


    原密码错误会提示错误。
    0 评论 0 下载 2019-08-11 08:41:12 下载需要11点积分
  • 基于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 评论 37 下载 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 评论 2 下载 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 评论 15 下载 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 评论 2 下载 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 评论 3 下载 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 评论 85 下载 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 评论 0 下载 2019-07-31 09:55:02 下载需要9点积分
显示 0 到 15 ,共 15 条
eject