一: 添加页面
1.在列表页面写添加的按钮,跳转添加页面
/*** 给添加按钮绑定一个点击事件*/$("#billsAdd").click(function () {//跳转添加页面location.href="add.jsp";})
2.添加页面先写,页面布局
2.① : 页面布局该使用什么标签,用什么标签
单号使用 span 标签,
下拉框使用 select 标签
单号: <span id="billsCode"></span><br>供应商ID: <select id="supplierId"><option value="">请选择</option></select><br>进货仓库ID: <select id="warehouseId" onchange="getAddr()"><option value="">请选择</option></select><br>联系地址: <span id="warehouseAddr"></span><br><%--隐藏ID--%><input type="hidden" value="${user.userId}" id="userId">采购员: ${user.userName}<br>联系人: <input type="text" id="billsPerson"><br>联系电话: <input type="text" id="billsPho
3.采购员/制单人使用session取的
<%--隐藏ID--%><input type="hidden" value="${user.userId}" id="userId">采购员: ${user.userName}<br>
4.要写什么按钮,写什么按钮
<%--新增按钮--%><input type="button" value="新增" id="seek"><%--返回上一个--%><input type="button" value="返回上一页" onclick="history.back()">
5.随机单号
5. ① 先写文档就绪函数
// 1. 调用随机数的方法
// 2. 调用下拉框的方法
/*** 文档就绪函数*/$(function () {//调用下拉框的方法supplierList()warehouseList()//调用随机数的方法$("#billsCode").html(getNum()).css("color","purple")})
② 定义随机单号的方法
//1. 随机数 : Math.floor(Math.random()*(最大值-最小值+1)-最小值)
//2. 年月日补0 : month=month<10?'0' +month:month(月份+1)
/*** 随机数*/function getNum() {//获取随机数let number = Math.floor(Math.random()*(99999-10000+1)-10000);//固定格式输出return "E"+number}
/*** 随机单号*/function getBillsNum() {//前缀 JH+年月日随机数let number = Math.floor(Math.random()*(9999-1000-1)+1000);let date = new Date();let fullYear = date.getFullYear();let month = date.getMonth()+1;let day = date.getDate();//补0month=month<10?'0'+month:month;day=day<10?'0'+day:day;let time=`\${fullYear}\${month}\${day}`;//返回随机数return "JH"+time+number}
③ 定义下拉框的方法
//1. ajax只有两步 : url datatype
/*** 供应商的下拉框*/function supplierList() {$.ajax({url: "/supplier/supplierList",dataType: "json",success(res) {//打印console.log(res)//循环追加数据for (let x of res) {$("#supplierId").append(`<option value="\${x.supplierId}">\${x.supplierName}</option>`)}},error() {alert("供应商下拉框展示失败")}})
//2. 动态下拉框
在id的双引号外面 写 data-address(这些写address下面也写address)
/*** 仓库下拉框*/function warehouseList() {$.ajax({url: "/warehouse/warehouseList",dataType: "json",success(res) {//打印console.log(res)//循环追加数据for (let x of res) {$("#warehouseId").append(`<option value="\${x.warehouseId}" data-address="\${x.warehouseAddr}">\${x.warehouseName}</option>`)}},error() {alert("供应商下拉框展示失败")}})}
7.按钮的下面写小列表(商品表)
7.① 小列表根据题给的样式写
(题上给的购买数量和采购金额是中间表的数据)
<%--商品列表--%><table id="table"><tr><td>商品编码</td><td>商品名称</td><td>型号规格</td><td>单位</td><td>数量</td><td>单价</td><td>购买数量</td><td>采购金额</td></tr></table>
8.给(查询)按钮绑定一个点击事件(可以开多个脚本)
6.① 根据题目要求写,比如(根据供应商的查询商品列表)
6.② 获取供应商的ID
6.③ 组装对象
6.④ ajax
在ajax的成功回调函数里:
//1. 清空表头
//2. 追加表头(绑定复选框,value绑商品ID)
给复选框绑定一个改变事件(用来计算最后付钱的商品)
//3. 追加表数据
//4. 商品表的最后两个数据是中间表的字段
购买数量使用inp标签
购买数量自己算自己的,绑定动态ID,绑定一个改变事件,用来计算购买金额(传3个参数 1.商品ID,购买数量,商品价格)
购买金额使用span标签,绑定动态ID(因为金钱是算法算出来的用户不可更改)
//5. 在循环外追加确认按钮(结账按钮)
给确认按钮绑定一个js的事件
$("#seek").click(function () {//取值let supplierId = $("#supplierId").val();//组装let obj={supplierId:supplierId}//ajax$.ajax({url: "/goods/goodsList",type:"post",data:{reqInfos:JSON.stringify(obj)},dataType: "json",success(res) {//打印console.log(res)//清空表$("#table").empty()//追加表头$("#table").append(`<tr><td><input type="checkbox" id="check" onchange="getNumMoney()"></td><td>商品编码</td><td>商品名称</td><td>型号规格</td><td>单位</td><td>数量</td><td>单价</td><td>购买数量</td><td>采购金额</td></tr>`)//追加表数据for (let x of res) {$("#table").append(`<tr><!--5个商品,结账时只要两个,获取选中的复选框的值--><td><input type="checkbox" class="ck" value="\${x.goodsId}" onchange="getNumMoney()"></td><td>\${x.goodsCode}</td><td>\${x.goodsName}</td><td>\${x.goodsModel}</td><td>\${x.goodsDept}</td><td>\${x.goodsNum}</td><td>\${x.goodsPrice}</td><td><!--购买数量 绑定动态ID, 绑定改变事件,进货3个参(主键ID,价格,数量)--><input type="text" id="gbNum\${x.goodsId}" onchange="getMoney(\${x.g0oodsId},this,\${x.goodsPrice})"></td><td><!--中间表的采购金额--><span id="gbOutlay\${x.goodsId}"></span></td></tr>`)}/*** “确认”按钮*/$("#table").append(`<tr><td colspan="100"><input type="button" value="确认" onclick="surePay()"></td></tr>`)},error() {alert("商品列表展示失败")}})})
9.全选/全不选按钮
/*** 全选/全不选*/$(document).on("click","#check",function () {$(".ck").prop("checked",this.checked)})
10.动态地址的2行代码
/*** 仓库动态地址*/function getAddr() {//取值let addr = $("#warehouseId option:selected").data("address")//取页面布局的详细字段 把取到的动态地址给这个字段,用spqn标签展示出来$("#warehouseAddr").html(addr).css("color","purple")}
11.购买金额的计算
11① : 在小列表里给中间表的字段(购买数量)绑定了改变事件,计算这个
11② : (传3个参数 : 商品ID,购买数量,商品价格)
11③ : 取值 : 取中间表数量的字段 上面用 this 代替传参了,取值的不用"#",直接取
11④ : 对购买数量判断,不能<=0 , 输入错误强制清空,return结束
11⑤ : 购买的金额=购买数量*商品价格
11⑥ : 算出来的钱,给购买金额(中间表的字段)用,小列表里的金额用span标签,用html显示
11⑦ : 调用计算总额的方法
/***购买金额计算*/function getMoney(goodsId, gbNum, goodsPrice) {//取数量值let n = $(gbNum).val();//判断if (n<=0){alert("购买数量有误,重新输出")//强制清空$(gbNum).val("")//结束return}//购买金额 单价*数量let sum=n*goodsPrice//赋值 给购买金额赋值(中间表的购买金额)$("#gbOutlay"+goodsId).html(sum)//调用计算总额的方法getNumMoney()}
12.总额计算方法
12.① 这个计算方法 : 比如5个商品,结账的时候只要3个,支付这3个的钱
12.② 定义sum=0;
12.③ 获取选中的复选框(复选框的value绑定了商品id,取值时用this,返回值写商品ID就可以了)
12.④ 获取选中的复选框的值(获取当前的复选框的值,小列表给的是span标签,用html展示)+动态id
12.⑤ 对当前选中的复选框的钱数做累计计算
12.⑥ 给页面布局里的总金额用span标签展示出来
/*** 总额计算*/function getNumMoney() {let sum=0;//获取选中的复选框的$(".ck:checked").each(function () {//商品ID的值let goodsId = $(this).val();//获取当前选中的复选框的值let gbOutlay = $("#gbOutlay"+goodsId).html();//累计求和sum+= +gbOutlay;//总额赋值$("#billsAmount").html(sum).css("color","purple")})}
13.确认按钮(一对多的添加)
13.①创建数组
13.②取单据表的数据(页面布局的字段)
13.③判空
13.④取中间表的字段
//1.获取复选框的值
//2.获取选中的复选框的值
//3.获取购买数量的值(小列表里中间表的购买数量的值)
//4.获取购买金额的值(小列表里中间表的购买金额的值)
//5.组装对象(3个字段 商品ID(复选框回值回出来的商品ID,购买数量,购买金额))
//6.添加进数组里
//7.1对多的数据组装(+上数组,和单据表里的数组相互对应)
13.⑤添加的ajax
/*** 1对多的添加 确认按钮*/function surePay() {//创建数组let arr=[]//取值 单据表取值let billsCode = $("#billsCode").html()let supplierId = $("#supplierId").val()let warehouseId = $("#warehouseId").val()let warehouseAddr = $("#warehouseAddr").html()let userId = $("#userId").val()let billsPerson = $("#billsPerson").val()let billsPhone = $("#billsPhone").val()let billsAmount = $("#billsAmount").html()//判空if (!billsCode ||!supplierId ||!warehouseId ||!warehouseAddr ||!userId ||!billsPerson ||!billsPhone ||!billsAmount){alert("请先输入")}//中间表(结账是结选中的要买单的商品)$(".ck:checked").each(function () {//获取选中的复选框的值let goodsId = $(this).val();//购买金额 中间表的购买金额let gbNum = $("#gbNum"+goodsId).val();//购买数量let gbOutlay = $("#gbOutlay"+goodsId).html();//组装中间表的对象 (3个字段 : 商品id,购买金额,购买数量)let a={goodsId:goodsId,gbOutlay:gbOutlay,gbNum:gbNum}//添加进数组里arr.push(a)})//1对多的数据组装let obj={billsCode:billsCode,supplierId:supplierId,warehouseId:warehouseId,warehouseAddr:warehouseAddr,userId:userId,billsPerson:billsPerson,billsPhone:billsPhone,billsAmount:billsAmount,arr:arr}//添加的ajax$.ajax({url: "/bills/billsListAdd",type: "post",data: {reqInfos:JSON.stringify(obj)},dataType: "json",success(res) {console.log(res)if (res===200){alert("单据表添加成功")location.href="list.jsp"}},error() {alert("单据表添加失败")}})}
Controller层
和正常的添加Controller一样
/*** 添加* @param req* @param resp* @throws ServletException* @throws IOException*/protected void billsListAdd(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {//接参String reqInfos = req.getParameter("reqInfos");//将json对象转换成java对象BillsVo billsVo = JSONObject.parseObject(reqInfos, BillsVo.class);//将转化后的对象传给serviceservice.billsListAdd(billsVo);//将处理后的结果响应给用户resp.getWriter().println(JSONObject.toJSONString(200));}
service层
1.获取连接
2.关闭连接
3.捕获异常
4.关闭自动提交,开启手动提交
5.在finally里 //恢复自动提交 //关闭连接
6.给单据表添加一条事务,(单据表的所有字段)
7.获取单据表里创建的集合
8.遍历集合
9.在集合里面给中间表添加一条数据(参数 : 事务,中间表的所有字段)
(单据表添加一条数据,回值回的是单据表的ID,中间表添加数据时,直接写回值的单据ID就可以了)
10.跟新库存数量(参数是 : //事务 //中间表里商品ID //中间表的数量)
11.提交事务
12.catch里回滚事务 +打印异常
/*** 添加* @param billsVo*/@SneakyThrows@Overridepublic void billsListAdd(BillsVo billsVo) {Connection conn = null;try {//获取连接conn = JDBCUtil.getConn();//关闭自动提交,开启手动提交conn.setAutoCommit(false);//给单据表添加一条事务,把事务传过去,获取ID,int billsId = billsDao.billsListAdd(conn,billsVo);//获取单表的集合ArrayList<GoodsBills> arr = billsVo.getArr();//遍历for (GoodsBills goodsBills : arr) {//(添加中间表的所有字段)billsDao.addGoodsBills(conn,goodsBills.getGoodsId(),billsId,goodsBills.getGbNum(),goodsBills.getGbOutlay());//跟新库存数量 //修改商品表(参数是 中间表里的商品ID和商品的数量 通过商品ID修改商品数量)billsDao.updGoods(conn,goodsBills.getGoodsId(),goodsBills.getGbNum());}//提交事务conn.commit();} catch (Exception e) {//回滚conn.rollback();//打印异常e.printStackTrace();} finally {//恢自动提交conn.setAutoCommit(true);//关闭连接conn.close();}}
dao层
1.给单据表添加一条数据
(就是正常的添加sql,执行sql是baseInserWithId,传事务,传sql,传单据表的ID(从service传过来的),添加的字段)
/*** 单据表添加一条数据* @param conn* @param billsVo* @return*/@Overridepublic int billsListAdd(Connection conn, BillsVo billsVo) {//定义sqlString sql="INSERT INTO t_bills(" +"bills_code," +"supplier_id," +"warehouse_id," +"warehouse_addr," +"user_id," +"bills_person," +"bills_phone," +"bills_amount," +"bills_del" +")VALUES(?,?,?,?,?,?,?,?,?)";//打印sqlSystem.out.println(sql);//执行sqlreturn baseInsertWithId(conn,sql,"bills_id",billsVo.getBillsCode(),billsVo.getSupplierId(),billsVo.getWarehouseId(),billsVo.getWarehouseAddr(),billsVo.getUserId(),billsVo.getBillsPerson(),billsVo.getBillsPhone(),billsVo.getBillsAmount(),billsVo.getBillsDel());}
2.给中间表添加一条数据
正常的添加(添加中间表的所有字段)
/*** 中间表添加一条数据* @param conn* @param goodsId* @param billsId* @param gbNum* @param gbOutlay*/@Overridepublic void addGoodsBills(Connection conn, Integer goodsId, int billsId, Integer gbNum, BigDecimal gbOutlay) {//定义sqlString sql="INSERT INTO t_goods_bills(goods_id,bills_id,gb_num,gb_outlay)VALUES(?,?,?,?)\n";//打印sqlSystem.out.println(sql);//执行sqlbaseUpdate(conn,sql,goodsId,billsId,gbNum,gbOutlay);}
3.更新库存数量
正常的修改语句(修改的是商品表的数量,进货是+,退货是- 修改语句不要忘记 where id=?)
/*** 更新库存* @param conn* @param goodsId* @param gbNum*/@Overridepublic void updGoods(Connection conn, Integer goodsId, Integer gbNum) {//定义sqlString sql=" UPDATE t_goods SET goods_num=goods_num+? where goods_id=? ";//打印sqlSystem.out.println(sql);//执行sqlbaseUpdate(conn,sql,gbNum,goodsId);}