课设小结——商品信息管理系统(JavaWeb+layui+sql)

课设小结——商品信息管理系统(JavaWeb+layui+sql)

  • 假期课设实现了商品信息管理系统,主要运用了数据库、后端JavaWeb、前端layui框架技术,下面分享一下他们实现过程。

1.数据库的建立

1.题目要求

在该项目中,应按照实际需求分析过程建立关系,并实现增删改查及其他功能

  • 商店信息:商店编号、商店名称、区域名、经理姓名、总金额
  • 销售信息:商店编号、商品编号、销售日期、销售数量;
  • 商品信息:商品编号、商品名称、类别(家电﹑食品﹑日用百货﹑其它)、进价、售价。

2.数据库和基本表的建立

#建立shangpin数据库
create database shangpin;
use shangpin;
#建立用户表
Create table userTable(
	id int(11) primary key auto_increment,#自然增长,后续添加商品时不需要手动添加序号
	Username varchar(20),
	Password varchar(20)
)
#建立商店表
Create table shopTable(
	shopid int(3) primary key auto_increment,
	shopname varchar(20),
	area varchar(20),
	manager varchar(20),
	total int(10)
);
#建立商品表
Create table goodsTable(
	goodsid int(10) primary key auto_increment,
	goodsname varchar(20),
	type varchar(20),
	purchase int(10),
	sell int(10)
);
#建立销售表
Create table saleTable(
	saleid int(10) primary key auto_increment,
	shopid int(3) references shopTable(shopid),
	goodsid int(10) references goodsTable(goodsid),
	saledate varchar(20),
	salenum int(10)
);

3.触发器的设计

触发程序的优点如下:

  • 触发程序的执行是自动的,当对触发程序相关表的数据做出相应的修改后立即执行。
  • 触发程序可以通过数据库中相关的表数据变动,修改其他表的数据。
  • 触发程序可以实施比 FOREIGN KEY 约束、CHECK 约束更为复杂的检查和操作。

在这里我们主要利用它的第二条优点,由于saletable的增加、删除和更改都会影响shoptable中total的数据,因此我们需要对saletable设计三个触发器。下面以INSERT触发器为例

#INSERT触发器
CREATE TRIGGER `add_saletable` AFTER INSERT ON `saletable` FOR EACH ROW begin
	declare nshopid int(3);
	declare ngoodsid int(10);
	declare nsalenum int(10);
	declare nsaleid int(10);
	declare npurchase int(10);
	declare nsell int(10);
	declare ntotal int(10);
	set nsaleid=(select max(saleid) from saletable);#set nsaleid=new.saleid
	set nshopid=(select shopid from saletable where saleid=nsaleid);
	set ngoodsid=(select goodsid from saletable where saleid=nsaleid);
	set nsalenum=(select salenum from saletable where saleid=nsaleid);
	if exists (select goodsid from goodstable where goodsid=ngoodsid) then
		set npurchase=(select purchase from goodstable where goodsid=ngoodsid);
		set nsell=(select sell from goodstable where goodsid=ngoodsid);
		if exists (select shopid from shoptable where shopid=nshopid) then
			set ntotal=(select total from shoptable where shopid=nshopid);
			update shoptable set total=ntotal+(nsell-npurchase)*nsalenum where shopid=nshopid;
		end if;
	end if;
end;

3.触发器补充

补充内容部分来源于:小白不再菜

1) INSERT 触发器

在 INSERT 语句执行之前或之后响应的触发器。

使用 INSERT 触发器需要注意以下几点:

  • 在 INSERT 触发器代码内,可引用一个名为 NEW(不区分大小写)的虚拟表来访问被插入的行。
  • 在 BEFORE INSERT 触发器中,NEW 中的值也可以被更新,即允许更改被插入的值(只要具有对应的操作权限)。
  • 对于 AUTO_INCREMENT 列,NEW 在 INSERT 执行之前包含的值是 0,在 INSERT 执行之后将包含新的自动生成值。

本项目设计的数据库用到了第三条,INSERT触发器中set nsaleid=(select max(saleid) from saletable);就是基于这个前提才成立的,也可以用set nsaleid=new.saleid代替

2) UPDATE 触发器

在 UPDATE 语句执行之前或之后响应的触发器。

使用 UPDATE 触发器需要注意以下几点:

  • 在 UPDATE 触发器代码内,可引用一个名为 NEW(不区分大小写)的虚拟表来访问更新的值。
  • 在 UPDATE 触发器代码内,可引用一个名为 OLD(不区分大小写)的虚拟表来访问 UPDATE 语句执行前的值。
  • 在 BEFORE UPDATE 触发器中,NEW 中的值可能也被更新,即允许更改将要用于 UPDATE 语句中的值(只要具有对应的操作权限)。
  • OLD 中的值全部是只读的,不能被更新。

注意:当触发器设计对触发表自身的更新操作时,只能使用 BEFORE 类型的触发器,AFTER 类型的触发器将不被允许。

3) DELETE 触发器

在 DELETE 语句执行之前或之后响应的触发器。

使用 DELETE 触发器需要注意以下几点:

  • 在 DELETE 触发器代码内,可以引用一个名为 OLD(不区分大小写)的虚拟表来访问被删除的行。
  • OLD 中的值全部是只读的,不能被更新。

2.后端JavaWeb的设计

1.DB设计

  • 数据库的连接

        //连接数据库
        public DB(){
            url= "jdbc:mysql://localhost:3306/shangpin?characterEncoding=UTF-8"+"&serverTimezone=UTC";
            user ="root";
            密码 ="xxx";
            try{
                Class.forName("com.mysql.jdbc.Driver");
                ct=DriverManager.getConnection(url,user,密码);
            }catch(Exception e){
                e.printStackTrace();
            }
        }
    
  • 增删改查功能的实现(以saletable为例)

    • 查看saleTable所有信息

       public ArrayList findSaleInfo(){
              try{
                  pstmt=ct.prepareStatement("select * from saleTable");
                  ArrayList al=new ArrayList();
      
                  ResultSet rs=pstmt.executeQuery();
                  while(rs.next()){
                      Sale sale=new Sale();
                      sale.setSaleid(rs.getInt(1));
                      sale.setShopid(rs.getInt(2));
                      sale.setGoodsid(rs.getInt(3));
                      sale.setSaledate(rs.getString(4));
                      sale.setSalenum(rs.getInt(5));
                      al.add(sale);
                  }
                  return al;
              }catch(Exception e){
                  e.printStackTrace();
                  return null;
              }
          }
      
    • 向saleTable增加信息

      public boolean addSaleInfo(Sale sale){
              try{
                  pstmt=ct.prepareStatement("insert into saleTable (shopid, goodsid, saledate, salenum) values(?,?,?,?)");
                  pstmt.setInt(1, sale.getShopid());
                  pstmt.setInt(2, sale.getGoodsid());
                  pstmt.setString(3, sale.getSaledate());
                  pstmt.setInt(4, sale.getSalenum());
                  pstmt.executeUpdate();
                  return true;
              }catch(Exception e){
                  e.printStackTrace();
                  return false;
              }
          }
      
    • 在saleTable删除信息

      public boolean deleteSaleInfo(int saleid){
              try{
                  pstmt=ct.prepareStatement("delete from saleTable where saleid=?");
                  pstmt.setInt(1,saleid);
                  pstmt.executeUpdate();
                  return true;
              }catch (Exception e){
                  e.printStackTrace();
                  return false;
              }
          }
      
    • 在saleTable修改信息

      public boolean updateSaleInfo(Sale sale){
              try{
                  pstmt=ct.prepareStatement("update saleTable set shopid=?, goodsid=?, saledate=?, salenum=? where saleid=?");
                  pstmt.setInt(1, sale.getShopid());
                  pstmt.setInt(2, sale.getGoodsid());
                  pstmt.setString(3, sale.getSaledate());
                  pstmt.setInt(4, sale.getSalenum());
                  pstmt.setInt(5,sale.getSaleid());
                  pstmt.executeUpdate();
                  return true;
              }catch (Exception e){
                  e.printStackTrace();
                  return false;
              }
          }
      
    • 在saleTable查找信息saleid查找

       public ArrayList findSaleInfoBySaleid(int saleid){
              try {
                  pstmt=ct.prepareStatement("select * from saleTable where saleid=?");
                  pstmt.setInt(1,saleid);
                  ArrayList al=new ArrayList();
      
                  ResultSet rs=pstmt.executeQuery();
                  while(rs.next()){
                      Sale sale=new Sale();
                      sale.setSaleid(rs.getInt(1));
                      sale.setShopid(rs.getInt(2));
                      sale.setGoodsid(rs.getInt(3));
                      sale.setSaledate(rs.getString(4));
                      sale.setSalenum(rs.getInt(5));
                      al.add(sale);
                  }
                  return al;
              }
              catch(Exception e){
                  e.printStackTrace();
                  return null;
              }
          }
      

2.model设计

  • 这个文件主要用于设计商店表、商品表、销售表、用户表相应的基本操作

  • 以销售表为例

    public class Sale implements Serializable{
        private int shopid;
        private int goodsid;
        private String saledate;
        private int salenum;
        private int saleid;
    
        public int getShopid(){
            return shopid;
        }
        public void setShopid(int shopid){
            this.shopid=shopid;
        }
        public int getGoodsid(){
            return goodsid;
        }
        public void setGoodsid(int goodsid){
            this.goodsid=goodsid;
        }
        public String getSaledate(){
            return saledate;
        }
        public void setSaledate(String saledate){
            this.saledate=saledate;
        }
        public int getSalenum(){
            return salenum;
        }
        public void setSalenum(int salenum){
            this.salenum=salenum;
        }
        public int getSaleid(){
            return saleid;
        }
        public void setSaleid(int saleid){
            this.saleid=saleid;
        }
    }
    
    

3.Servelet设计

  • Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。使用 Servlet,可以收集来自网页表单的用户输入,呈现来自数据库或者其他源的记录,还可以动态创建网页。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1ZEv2xPX-1660286022058)(C:\Users\86186\AppData\Roaming\Typora\typora-user-images\image-20220811210545250.png)]

  • 以AddGoodsServlet为例

    public class AddGoodsServlet extends HttpServlet{
        public void doGet(HttpServletRequest request,HttpServletResponse response)
                throws ServletException,IOException{
            request.setCharacterEncoding("utf-8");
            response.setContentType("utf-8");
    
            String goodsname=request.getParameter("goodsname");
            String type=request.getParameter("type");
            int purchase=Integer.parseInt(request.getParameter("purchase"));
            int sell=Integer.parseInt(request.getParameter("sell"));
    
            Goods goods=new Goods();
            goods.setGoodsname(goodsname);
            goods.setType(type);
            goods.setPurchase(purchase);
            goods.setSell(sell);
            if(new DB().addGoodsInfo(goods)){
                response.sendRedirect("success.jsp");
            }
        }
        public void doPost(HttpServletRequest request,HttpServletResponse response)
                throws ServletException,IOException{
            doGet(request,response);
        }
    }
    

4.web.xml和pom.xml文件的配置

1.web.xml的配置
  • web.xml主要用来配置Filter,Listener,Servlet等。

  • web容器的加载顺序ServletContext -> context-param -> listener -> filter -> servlet。并且这些元素可以配置在文件中的任意位置,不会因为filter在web.xml文件中写在listener前面就先加载filter。

  • 由于本项目运用了servlet,所以需要对其进行配置(以AddGoodsServlet为例)

      <servlet>
        <servlet-name>addGoodsServlet</servlet-name>
        <servlet-class>servlet.AddGoodsServlet</servlet-class>
      </servlet>
     <servlet-mapping>
        <servlet-name>addGoodsServlet</servlet-name>
        <url-pattern>/addGoodsServlet</url-pattern>
      </servlet-mapping>
    
2.pom.xml的配置
  • pom.xml主要保存当前组件的版本,如sql、servlet、tomcat、junit等,只需改成对应版本,一般放在dependencies里

      <dependencies>
        <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>4.11</version>
          <scope>test</scope>
        </dependency>
        <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          <version>8.0.15</version>
        </dependency>
        <dependency>
          <groupId>javax.servlet</groupId>
          <artifactId>javax.servlet-api</artifactId>
          <version>3.1.0</version>
          <scope>provided</scope>
        </dependency>
      </dependencies>
    

3.前端文件的设置及其亮点

由于我主要设置前端,所以会对其功能进行详细说明

1.layui文件的下载

  • 前端系统主要使用技术:layui框架,需要到官网下载相关包并导入相关的jsp

    <link rel="stylesheet" href="css/style.css">
    <link rel="stylesheet" href="layui_right.css">
    <link rel="stylesheet" href="layui/css/layui.css" media="all">
    <script src="layui/layui.js" charset="utf-8"></script>
    <script src="js/jquery.js" charset="utf-8"></script>
    

    在文件中的位置:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FLOt11jz-1660286022059)(C:\Users\86186\AppData\Roaming\Typora\typora-user-images\image-20220811212637252.png)]

2.登录注册界面的设置

  • 这部分并没有调用layui框架,而是调用另外的css、js文件
  • 由于javaweb初始时自动调用index.jsp,所以把其设置为登录界面

下面是登录界面的渲染效果:

  1. 动态动画效果的实现:

    其主要原理是通过在js文件设置相关函数,生成随机点并将最近的几个随机点相连

    • 随着鼠标位置移动:

      function mouseMove(e) {
              var posx = posy = 0;
              if (e.pageX || e.pageY) {
                  posx = e.pageX;
                  posy = e.pageY;
              }
              else if (e.clientX || e.clientY)    {
                  posx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
                  posy = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
              }
              target.x = posx;
              target.y = posy;
          }
      
    • 设置随机点

       points = [];
              for(var x = 0; x < width; x = x + width/20) {
                  for(var y = 0; y < height; y = y + height/20) {
                      var px = x + Math.random()*width/20;
                      var py = y + Math.random()*height/20;
                      var p = {x: px, originX: px, y: py, originY: py };
                      points.push(p);
                  }
              }
      
  2. 登录和注册不同的页面跳转方式:

    • 登录按钮的跳转:通过form action中loginServlet跳转,将相关值传递过去

    • 注册按钮的跳转:由于注册按钮不需要传递任何参数,所以设置了一个onclick事件进行跳转

         <p class="act-but">
         <input  type="button" class="btn btn-primary" value="注册"onclick="regist()">
         </p><!--注册按钮-->
      
    • 跳转函数设置

      <script type="text/javascript">
          function regist() {
              // 如果需要在新窗口打开注册界面;
              // window.open('Untitled-2.html');
              // 如果需要在当前窗口打开登录界面
              window.location.href = 'register.jsp';
          }
      </script>
      

      jsp文件中函数需要放在中才能实现

  3. 密码的显隐性设置:

    • 密码显隐性设置,也是通过onclick事件实现,并通过js文件分析解析

      //显示隐藏对应的密码方法:
      function show_hide_pwd(id)
      {
          let type = $("#"+id).attr('type')
          if (type === "password") {
              $("#"+id+"eye").attr('src', "img/eye_close.svg"); 
              $("#"+id).attr("type", "text");
          } else {
              $("#"+id+"eye").attr('src', "img/eye_open.svg"); 
              $("#"+id).attr("type", "password");
          }
      }
      
  4. 注意事项:

    • loginServlet中request.setCharacterEncoding需要设置为gb2312,否则会乱码
    • loginServlet中不能写User user=(User)session.getAttribute("user"),因为他可以追踪你已经登录的用户,从而导致二次登录会发生异常。应该为User user=null;
    • register.jsp和index.jsp的pageEncoding的设置需相同,否则会导致乱码

3.主界面的设置

  • 通过相应的div class分别设置页面的头部、顶部logo、右边栏目、页面侧边栏、页面主体内容和页面底端,下面是主界面的渲染效果:

    在这里插入图片描述

  1. 下拉框的实现:通过<dd><dl>实现,注意图片和文字需要放在一个<li>中,才能实现其中任何一个都能出现下拉框,同时<a href="javascript:;">表示跳转到任何界面,而是直接出现下拉框
  2. 页面侧边栏中layui-this属性保证了当前选中的查询表现为高亮

4.表格的实现与设计

1.数据表格的构造
  • 静态表格参数说明:

    <table height="600" lay-filter="parse-table-demo" lay-data="{id: 'idTest'}" style="margin: 0 auto;">
    
    • lay-filter是区分不同表格的标志,相当于选择器

    • lay-data用于表格的自动渲染

      <table class="layui-table" lay-data="{
              height: 500,
              id:'test',
              url:'${ctx}/servlet/StaffServlet?type=tabStaff', //请求路径
              page: true,//是否显示分页工具条
              limit: 10,//每页默认显示的数量
              method: 'post', //提交方式      
              }" lay-filter="test">
      
  • 通过循环枚举数据库的数据,先形成静态表格,如下图:

    在这里插入图片描述

    再通过layui.use中table.init方法转化成数据表格,如下图:

    在这里插入图片描述

    如果有数据的json文件,也可以通过table.render方法形成数据表格

  • table.init详解

<script>
table.init('parse-table-demo', { //转化静态表格
                        height: '350'
                        ,toolbar: '#toolbarDemo' 
                        ,defaultToolbar: ['filter', 'exports', 'print', { //自定义头部工具栏右侧图标。如无需自定义,去除该参数即可
                            title: '提示'
                            ,layEvent: 'LAYTABLE_TIPS'
                            ,icon: 'layui-icon-tips'
                        }]
                        ,even:true
                        ,page:true
                        console.log(data);
                        ,totalRow: true

                    });
</script>
  • 'parse-table-demo’为表格的id,也可以通过elem:‘xxx’来实现
  • toolbar: ‘xxx’ 用于开启头部工具栏,其功能需要我们自己去实现,xxx为对应的script的id
  • defaultToolbar:也是自定义头部工具栏,只不过固定在右侧,同时提供筛选、导出和打印功能
  • even:使单双行颜色不一样,page:开启分页,totalRow:开启总和行
  • 当然init中还有其他参数比如done、limit等,有需要的可以自行查阅
2.数据表格的渲染
  • 数据表格的颜色、背景、高度、宽度、排序、求和、加粗、斜体、居中、拉伸、左右固定都是通过设置渲染出来的

    <thead>
    <tr>
        <th lay-data="{field:'',type:'checkbox'}"></th>
        <th lay-data="{field:'shopid',  width:140, sort: true,totalRowText: '合计', templet: '#idTpl',align:'center'}">商店编号</th>
        <th lay-data="{field:'shopname', width:150, sort: true,style:'background-color: #eee;',align:'center'}">商店名称</th>
        <th lay-data="{field:'area', width:150,sort:true, align:'center',templet: function(res){return '<em>'+ res.area +'</em>'}}">区域名</th>
        <th lay-data="{field:'manager', width:150, sort: true,align:'center',templet: function(res){return '<strong>'+ res.manager +'</strong>'}}">经理姓名</th>
        <th lay-data="{field:'total', width:150,sort:true,totalRow: true,templet: '#totalTpl',align:'center'}">总金额</th>
        <th lay-data="{field:'operation', toolbar: '#barDemo', align:'center'}">操作</th>
    </tr>
    </thead>
    
    field每一项的标志
    width表格宽度,如果不设置会自动调整
    align设置对其方式
    sort该列列是否排序
    totalRowText该列是否求和
    backgroundcolor背景颜色
    templet通过函数自定义样式
  • templet功能实现

    • 像加粗、倾斜简单功能,可以直接在建表时候实现,res.xxx,其中xxx为对应表格的field

      templet: function(res){return '<strong>'+ res.manager +'</strong>'}}">经理姓名</th>
      
    • 设置颜色等复杂功能

      • 首先建表时,表头需要引用对应script的id,如templet: '#idTpl'

      • script设置函数功能

        <script type="text/html" id="idTpl">
            {{#  if(d.shopid %2==0){ }}
            <span style="color: #F581B1;">{{ d.shopid }}</span>
            {{#  } else { }}
            <span style="color: #00BFFF;">{{ d.shopid }}</span>
            {{#  } }}
        </script>
        

        奇偶编号颜色不一样,注意其书写方式,只能写一个if-else

3.头工具栏的实现
  • 首先要将工具栏的按键放在一个script中,其中id是识别这组工具栏的标识,调用方法是放在table.init的toolbar或者defaultToolbar中

    <script type="text/html" id="toolbarDemo">
        <div class="layui-btn-container">
            <button class="layui-btn layui-btn-sm layui-btn-warm" lay-event="getCheckData">获取选中商店数据</button>
            <button class="layui-btn layui-btn-sm layui-btn-normal" lay-event="getCheckLength">获取选中商店数目</button>
            <button class="layui-btn layui-btn-sm" lay-event="isAll">验证是否全选</button>
            <button class="layui-btn layui-btn-sm layui-btn-danger" lay-event="addShop"><i class="layui-icon layui-icon-add-circle-fine" style="font-size:20px;font-weight:bold"></i>新增商店</button>
        </div>
    </script>
    
  • lay-event在这里相当于每一个button的标识

  • table.on详解

    <script>
        table.on('toolbar(parse-table-demo)', function(obj){
        var checkStatus = table.checkStatus(obj.config.id);
        switch(obj.event){
            case 'getCheckData':
                var temp="";
                var data = checkStatus.data;
                for(var i=0;i<data.length;i++){    //循环筛选出id
                    temp=temp+data[i].shopid+' '+data[i].shopname+' '+data[i].area+' '+data[i].manager+' '+data[i].total+'</br>';
                }
                layer.msg(temp, {icon: 1});
                // layer.alert(JSON.stringify(data));
                break;
    </script>
    
    • table.on(‘toolbar(xxx)’),其中xxx为表格id
    • table.checkStatus(xxx)。打他,xxx为表格id,用于获得表格选中字段数据
    • 这里obj.event对应之前的lay-event
    • data[i].xxx,这里xxx是表格每一项的field
4.表格数据的获取
  • 方法一:将数据存储在一个json文件中,之后通过table.render的data或url中设置
<script>
    table.render({
    elem: '#test-table-toolbar'
     ,url:"http://localhost:8090/program-web/api/magic_change/oj/problem/page_list?userId=youcongtech"
    ,toolbar: '#test-table-toolbar-toolbarDemo'
    ,title: '程序设计题绑定'
    ,cols: [[//设置表头
      {type: 'checkbox', fixed: 'left'},
      {field:'problemId', width:300, title: 'ID', sort: true}
      ,{field:'title', width:400, title: '题目'}
      ,{width:215, align:'center', fixed: 'right', toolbar: '#test-table-toolbar-barDemo'}
    ]]
    ,page: true
  });
</script>
  • 方法二:静态表格转化为数据表格

    前文已经讲过如何转化,下面说一下数据如何实时保存与更新

    <%
        DB db=new DB();
        ArrayList<Shop> list=db.findShopInfo();
        if(list!=null&&list.size()>0){
            for(int i=0;i<list.size();i++){
                Shop shop=list.get(i);
    %>
    <tbody>
    <tr><td></td>
        <td><%=shop.getShopid()%></td>
        <td><%=shop.getShopname()%></td>
        <td><%=shop.getArea()%></td>
        <td><%=shop.getManager()%></td>
        <td><%=shop.getTotal()%></td>
    </tr>
    </tbody>
    <%
            }
        }
    %>
    

    通过循环,将数据存储在表格中,不管增删改,只要更新界面数据就会跟着变

5.增删改功能的实现

  • 增删改都用到了layer相关函数,先将layer常用函数总结一下

    layer.use后面可以接([‘table’,’form’],function)等要渲染的工具
    layer.msg弹出提示消息,可设置time和icon等
    layer.alert弹出提示框
    layer.open跳出弹窗
    layer.confirm跳出确认框
    layer.prompt跳出要更改的信息框
    layer.close关闭消息框和弹窗

    layer.msg和layer.alert换行要用<br>

    1.添加功能
    <script type="text/html" id="toolbarDemo">
    <button class="layui-btn" lay-event="addShop"></i>新增商店</button>
    </script>
    
    • 首先找出其script的id和其button的lay-event,将id放到table.init的toolbar中。toolbar=‘#toolbarDemo’

    • 通过layer.open跳出弹窗

      case 'addShop':
      layer.open({
          title:'新增商店',
          type: 2,
          skin: 'layui-layer-rim', //加上边框
          area: ['800px', '480px'], //宽高
          content: 'addShop.jsp',
          //btn:['确认','取消']
          maxmin: true,
          shadeClose: true, //点击遮罩关闭层
      });
      
      • type: Layer提供了5种层类型。可传入的值有:0(信息框,默认)1(页面层)2(iframe层)3(加载层)4(tips层)

      • content:支持jsp、html以及获取DOM元素等,这里选用的是jsp页面(注意jsp文件名区分大小写)

        最开始选择的是type:1,将jsp内容直接写入content(需要加单引号),但因为其本质是字符串,识别不了onclick函数功能,所以改用直接跳jsp

      • btn是其自带的两个可以调用的按钮,其用法:

        yes: function(index){//layer.msg('yes');    //点击确定回调
            },
            btn2: function(){//layer.alert('aaa',{title:'msg title'});  点击取消回调
            }
        

        我们这不需要,因为直接在add.jsp设置了按钮

    • addshops.jsp设置

      其渲染效果如下:

      下面是部分代码:

          <form action="addShopServlet" method="post">
              <div style="padding: 15px">
              <div class="layui-form-item"><label class="layui-form-label">商店名称</label><div class="layui-input-block"><input id="shopname" name="shopname" class="layui-input" placeholder="请输入商店名称" /></div></div>
              <div class="layui-btn-container" style="margin-top: 45px;">
                  <button style="float: right" class="layui-btn layui-btn-normal" lay-filter="login_button" lay-submit="">新增商店</button>
                  <button  style="float: right" class="layui-btn layui-btn-primary" type="reset">重置</button>
              </div>
              </div>
          </form>
      
      • placeholder:描述输入的预期值信息
      • 注意button中lay submit=“”不要忘记写,这样form action才能识别
      • form action中的值区分大小写
    • success.jsp的设置

      • 运行成功会弹出消息:操作成功

      • 之后会刷新返回原来界面

        <script>
            // showMessage('添加成功')
            layer.msg("操作成功!", {
                icon: 6,
                time: 2000
            }, function () {
                parent.window.location.reload();
                var index = parent.layer.getFrameIndex(window.name); //获取窗口索引
                parent.layer.close(index);
            });
        </script>
        
    2.删除功能
    if(obj.event === 'del'){
        layer.confirm('真的删除行么', function(index){
            obj.del();
            layer.open({
                title:'提示',
                type: 2,
                skin: 'layui-layer-rim', //加上边框
                area: ['400px', '240px'], //宽高
                content: 'deleteShop.jsp?shopid='+id,
                maxmin: true,
                shadeClose: true, //点击遮罩关闭层
            });
            layer.close(index);
        });
    
    • 前期准备和添加功能相同,删除功能这里先有一个layer.confirm用于提示是否真的删除,只有确定才能执行里面layer.open的功能,从而跳转到deleteshop.jsp界面

    • content中jsp后面有一个?shopid='+id,是向jsp传递的参数

    • deleteShop.jsp的设计,本项目没有通过servlet实现删除,而是在jsp中直接实现

      • 首先要连接数据库

        <%!
            public static final String DBDRIVER="com.mysql.jdbc.Driver";
            public static final String DBURL="jdbc:mysql://localhost:3306/shangpin?characterEncoding=UTF-8"+"&serverTimezone=UTC";
            public static final String DBUSER="root";
            public static final String DBPASS="xxx;
        %>
        
      • 接着通过request.getParameter("shopid");获取参数

        <%
            Connection conn=null;
            PreparedStatement pst=null;
            int rs=0;
            String shopid=request.getParameter("shopid");
        %>
        
      • 然后用java和sql语言实现删除功能(参考上面deleteSaleServlet写法)

      • 最后弹出提示,刷新界面

        <script>
            // showMessage('添加成功')
            layer.msg("删除成功!", {
                icon: 6,
                time: 2000
            }
            , function () {
                parent.window.location.reload();
                var index = parent.layer.getFrameIndex(window.name); //获取窗口索引
                parent.layer.close(index);
            });
        </script>
        

        jsp文件中的java代码都要放在<%%>中

    3.更改功能

    其实现原理与添加功能几乎相同,只不过本项目对updateShop.jsp进行了对用户友好的处理

    • updateShop.jsp设计,首先看一下它的渲染效果

      在这里插入图片描述

    • 由于商品编号是重要信息,用户不可更改,所以设置了只读功能,即readonly=“true”

       <div class="layui-form-item"><label class="layui-form-label">商店编号</label><div class="layui-input-block"><input id="shopid" name="shopid" class="layui-input"  readonly="true" style="background:#CCCCCC" value="<%=shoplist.get(0).getShopid()%>" placeholder="<%=shoplist.get(0).getShopid()%>" /></div></div>
      

      设置readonly=“true”表示只读,disabled=“diabled”表示不可更改,form action也不能将value传递过去,所以只能用readonly

    • 由于更改信息时用户可能要参照之前的信息进行更改,所以placeholder中保存了其原有信息,实现该功能只需找到该项的数据

      <%
          int shopid=Integer.parseInt(request.getParameter("shopid"));
          DB db=new DB();
          List<Shop> shoplist=new ArrayList<Shop>();
          shoplist=db.findShopInfoByShopid(shopid);
      %>
      

      这里只将shopid传过来,而没有将其他数据传过来,因为可能会造成乱码

6.查询功能实现

  • 这里实现了多条件查询功能,即满足任意几个查询条件都可以组合查询

  • 为了方便查询,这里设置了搜索选择框,将各列数据保存在下拉框中

    <div class="layui-input-inline">
        <select name="shopid" lay-verify="required" lay-search="">
            <option value="">请选择商店编号</option>
            <%
                if(shop_list!=null&&shop_list.size()>0){
                    for(int i=0;i<shop_list.size();i++){
                        Shop shop=shop_list.get(i);
            %>
            <option value=<%=shop.getShopid()%> ><%=shop.getShopid()%></option>
            <%
                    }
                }
            %>
        </select>
    </div>
    
    • 通过循环实现信息的搜集
    • 为了防止option value的值传递后乱码,将pageEncoding设置为utf-8即可
  • 为了实现查询后,将符合条件的数据传递到数据表格呈现,findShop.jsp与shops.jsp代码几乎设置一样,只是循环前验证了shop_list是否为null

    <%if(request.getAttribute("shop_list")!=null);{%>
        <%
            List<Shop> shopList=(List)request.getAttribute("shop_list");
            if(shopList!=null&&shopList.size()>0){
                for(int i=0;i<shopList.size();i++){
                    Shop shop=shopList.get(i);
        %>
        <tbody>
            <td></td>
            <td><%=shop.getShopid()%></td>
            <td><%=shop.getShopname()%></td>
            <td><%=shop.getArea()%></td>
            <td><%=shop.getManager()%></td>
            <td><%=shop.getTotal()%></td>
    
        </tbody>
        <%
                }
            }
        %>
    
    <%} %>
    

7.颜色及符号设置

layer.msg(“测试”,{icon:x})效果
0
1
2
3
4
5
6

4.项目亮点小结

  • 登录界面通过js设计实现了动态效果

  • 登录界面密码的显隐性设置帮助用户记忆密码

  • 数据表格筛选、导出、打印、提示功能,方便表格编辑

  • 表格数据可以实现排序及求和功能,并且销售表改变,商店表总金额也会改变

  • 表格各列可以实现左右自由拉伸改变宽度

  • 表格具有分页功能,可以切换页数

  • 表格居中,颜色丰富不单一

  • 表格序号单双号颜色不同,总额以500为界限不同,方便用户判断

  • 各列颜色、格式一致,方便用户区分

  • 新增商品和添加商品跳出弹窗添加,使得主界面更简洁干净

  • 删除商品会有提示,避免用户误删

  • 更新商品序号为重要信息,对用户设为只读

  • 更新商品输入框会提示原商品的信息,方便用户对照修改

  • 执行操作成功会有弹窗提示操作成功,并且会立刻更新界面

  • 查询商品实现多条件查询,任意几个查询条件都可以组合

  • 查询框为搜索选择框,方便用户选择商品

  • 查询结果会展示所有符合条件结果,没有符合条件的会显示无数据

  • 3
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
要编写一个基于JavaWebSQLServer的客户关系管理系统,需要首先进行系统的需求分析和设计。系统主要功能包括客户信息管理、订单管理、产品管理、销售管理等模块。 在编写客户关系管理系统的过程中,需要使用JavaWeb作为开发平台,结合JSP、Servlet和JDBC等技术进行页面展示、业务逻辑处理和数据库操作。首先可以创建一个基于MVC模式的项目结构,将页面展示与业务逻辑分离,提高代码的可维护性和可扩展性。 在设计数据库时,需要创建客户信息表、订单信息表、产品信息表、销售信息表等相关的数据库表。通过SQLServer进行数据库设计和建表操作,确保数据的存储和安全性。同时,需要编写SQL语句和存储过程用于数据的增删改查等操作。 在编写Java代码时,需要编写JavaBean实体类用于与数据库表对应,通过JDBC连接数据库进行数据的增删改查操作。同时,使用JSP进行页面的展示和交互,通过Servlet处理页面传递的请求,进行相应的业务逻辑操作。 除此之外,还需要考虑系统的安全性、性能优化和用户体验等方面。可以采用权限管理、数据加密和前端优化等技术手段,提高系统的安全性和性能。 总之,编写JavaWeb SQLServer客户关系管理系统需要综合运用多种技术手段,并且需要进行全面的系统规划和设计,确保系统的功能完备和稳定运行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

放学等我_红橙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值