一: 添加页面
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(); //补0 month=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); //将转化后的对象传给service service.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 @Override public 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 */ @Override public int billsListAdd(Connection conn, BillsVo billsVo) { //定义sql String sql="INSERT INTO t_bills(" + "bills_code," + "supplier_id," + "warehouse_id," + "warehouse_addr," + "user_id," + "bills_person," + "bills_phone," + "bills_amount," + "bills_del" + ")VALUES(?,?,?,?,?,?,?,?,?)"; //打印sql System.out.println(sql); //执行sql return 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 */ @Override public void addGoodsBills(Connection conn, Integer goodsId, int billsId, Integer gbNum, BigDecimal gbOutlay) { //定义sql String sql="INSERT INTO t_goods_bills(goods_id,bills_id,gb_num,gb_outlay)VALUES(?,?,?,?)\n"; //打印sql System.out.println(sql); //执行sql baseUpdate(conn,sql,goodsId,billsId,gbNum,gbOutlay); }
3.更新库存数量
正常的修改语句(修改的是商品表的数量,进货是+,退货是- 修改语句不要忘记 where id=?)
/** * 更新库存 * @param conn * @param goodsId * @param gbNum */ @Override public void updGoods(Connection conn, Integer goodsId, Integer gbNum) { //定义sql String sql=" UPDATE t_goods SET goods_num=goods_num+? where goods_id=? "; //打印sql System.out.println(sql); //执行sql baseUpdate(conn,sql,gbNum,goodsId); }