1、导入坐标
坐标 | 作用 |
---|---|
pagehelper-spring-boot-starter | mybatis分页插件 |
spring-boot-starter-thymeleaf | JSP模板引擎 |
mybatis-spring-boot-starter | mybatis |
spring-boot-starter-web | web |
spring-boot-starter-test | test |
lombok | 不需要再写getter、setter或equals方法,只要有一个注解 |
mybatis-plus-boot-starter | mybatis plus |
druid-spring-boot-starter | druid连接数据库 |
hutool-all | hutool工具类 |
bootstrap | 前端 |
jquery | 前端 |
mysql-connector-java | mysql |
2、配置文件application.yml
# 应用服务 WEB 访问端口
server:port: 8080spring:datasource:driver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://localhost:3306/minzu?useUnicode=true&characterEncoding=utf8username: rootpassword: roottype: com.alibaba.druid.pool.DruidDataSourcedruid:min-idle: 5max-active: 10max-wait: 3000thymeleaf:prefix: classpath:/templates/water/suffix: .html
mybatis-plus:configuration:map-underscore-to-camel-case: truelog-impl: org.apache.ibatis.logging.stdout.StdOutImplglobal-config:db-config:id-type: auto
pagehelper:helper-dialect: mysql
3、登录功能
需要tb_account表
在pojo实体包下创建Account实体类
使用@TableName("tb_account")
注解,用于标识实体类对应的数据库表名
在service层提供登录方法,分为接口和接口实现
@Service
public class AccountServiceImpl implements AccountService {@Autowired//自动注入AccountMapper,AccountMapper继承了BaseMapper<Account>,是mybatisplus接口,有基本的CURDprivate AccountMapper accountMapper;@Overridepublic boolean login(String user, String password) {QueryWrapper<Account> qw = new QueryWrapper<>();qw.eq("user_name",user);//精确查找Account account = accountMapper.selectOne(qw);//从数据库中选择上面查找到的对象if(account == null){return false;}String userPwd = account.getUserPwd();//String s = DigestUtil.md5Hex(password);//System.out.println(s);if(Objects.equals(userPwd,password)){//比较密码return true;}else{return false;}}
}
登录方法的controller
@Controller
public class AccountController {@Autowiredprivate AccountService accountService;@PostMapping("/login")public String login(String userName, String userPwd, Model model, HttpSession session){boolean login = accountService.login(userName,userPwd);//接收前端参数userName和userPwdif(login){session.setAttribute("currentUser",userName);return "waterMainMenu";//用的thymeleaf,配置文件中已经写好路径与.html,直接跳转}else{model.addAttribute("msg","用户名或者密码错误");return "index";}}}
4、主页展示
需要tb_history表
@RestController
@RequestMapping("main")
public class MainMenuController {@Autowiredprivate HistoryService historyService;@Autowiredprivate WorkerService workerService;@RequestMapping("mainMenu")public List<MainMenu> list(){List<MainMenu> list = new ArrayList<>();Map<Integer,Integer> map = new HashMap<>();historyService.queryHistory().forEach(h -> {//遍历数据库,将对应workerId键放入map中,值为sendWaterCountmap.put(h.getWorkerId(),map.getOrDefault(h.getWorkerId(),0)+h.getSendWaterCount());});workerService.queryWorker().forEach(w ->{//遍历数据库中的所有数据,这些数据最后是需要展示的//MainMenu中只有WorkerName和SendWaterCount属性MainMenu mainMenu = new MainMenu();//设置WorkerNamemainMenu.setWorkerName(w.getWorkerName());//设置SendWaterCountmainMenu.setSendWaterCount(map.get(w.getWid())==null?0:map.get(w.getWid()));list.add((mainMenu));});//将所有拿到的数据排序,只取前12个Collections.sort(list,(o1,o2)->{if(o1.getSendWaterCount()>o2.getSendWaterCount()){return -1;}else if(o1.getSendWaterCount()<o2.getSendWaterCount()){return 1;}else{return 0;}});if(list.size()<12){return list;}List<MainMenu> arrList = new ArrayList<>();for(int i=0;i<12;i++){arrList.add(list.get(i));}return arrList;}}
5、客户管理功能模块
需要tb_customer表
用的是PageInfo<>(listCust)
前端展示页面
业务层
@Service
public class CustomerServiceImpl implements CustomerService {@Autowired//自动注入CustmoerMapper,用于连接操作数据库private CustomerMapper customerMapper;@Override//查询展示所有//返回值是一个PageInfo对象,里面放的是从数据库查询到的每个Customer对象public PageInfo<Customer> list(Customer customer) {QueryWrapper<Customer> qw = new QueryWrapper<>();String custName = customer.getCustName();String custMobile = customer.getCustMobile();if(!StringUtils.isNullOrEmpty(custName)){//custName模糊查询qw.like("cust_name",custName);}if(!StringUtils.isNullOrEmpty(custMobile)){//custMobile精确查询qw.eq("cust_mobile",custMobile);}//selectList查询多条数据,封装成集合返回List<Customer> listCust = customerMapper.selectList(qw);return new PageInfo<>(listCust);}@Override//添加public int addCust(Customer customer) {//调用insert方法return customerMapper.insert(customer);}//删除//前端留的接口数据就是cid@Overridepublic int deleteCust(int id) {QueryWrapper<Customer> qw = new QueryWrapper<>();qw.eq("cid",id);//精确比较cid,拿到对象int delete = customerMapper.delete(qw);//用Mapper中的delete方法从数据中删除上面拿到的qwreturn delete;}
}
Controller
@Controller
@RequestMapping("cust")
//前端留的接口就是cust
public class CustomerController {@Autowiredprivate CustomerService customerService;//Customer页面显示@RequestMapping("listCust")public String list(@RequestParam(required = false,defaultValue = "1",value = "pageNum") Integer pageNum,@RequestParam(required = false,defaultValue = "10",value = "pageSize") Integer pageSize,Model model, Customer customer){if(pageNum<=0 || pageNum.equals("")||pageNum==null){pageNum = 1;}if(pageSize<=0 || pageSize.equals("")||pageSize==null){pageNum = 10;}PageHelper.startPage(pageNum,pageSize);PageInfo<Customer> pageInfo = customerService.list(customer);model.addAttribute("pageInfo",pageInfo);//前端留的pageInforeturn "customerList";}//跳转到添加数据页面,有一个单独的custSave.html页面@RequestMapping("preSaveCust")public String preSave(){return "custSave";}//真正的添加数据页面,保存数据@RequestMapping("saveCust")public String save(Customer customer){int i = customerService.addCust(customer);return "redirect:/cust/listCust";}//删除Customer数据@RequestMapping("delCust/{cid}")public String deleteCust(@PathVariable int cid){int i = customerService.deleteCust(cid);return "redirect:/cust/listCust";}
}
6、送水工管理模块
需要tb_worker表
业务层
@Service
public class WorkerServiceImpl implements WorkerService {@Autowiredprivate WorkerMapper workerMapper;@Override//查询所有public List<Worker> queryWorker() {return workerMapper.selectList(null);}@Override//查询所有带分页public PageInfo<Worker> list(Worker worker) {String workName = worker.getWorkerName();QueryWrapper<Worker> qw = new QueryWrapper<>();if(!StringUtils.isNullOrEmpty(workName)){qw.like("worker_name",workName);}List<Worker> workers = workerMapper.selectList(qw);return new PageInfo<>(workers);}@Override//添加public int addWorker(Worker worker) {return workerMapper.insert(worker);}@Overridepublic Worker getWorkerById(Integer id) {QueryWrapper<Worker> qw = new QueryWrapper<>();qw.eq("wid",id);Worker worker = workerMapper.selectOne(qw);return worker;}@Override//更新public int updateWorker(Worker worker) {Integer wid = worker.getWid();QueryWrapper<Worker> qw = new QueryWrapper<>();qw.eq("wid",wid);int update = workerMapper.update(worker, qw);return update;}@Override//更新薪资public int updateSalary(Integer wid, String workerSalary) {QueryWrapper<Worker> qw = new QueryWrapper<>();qw.eq("wid",wid);Worker worker = workerMapper.selectOne(qw);worker.setWorkerSalary(workerSalary);int update = workerMapper.update(worker, qw);return update;}
}
Controller
@Controller
@RequestMapping("worker")
public class WorkerController {@Value("${location}")private String location;@Autowiredprivate WorkerService workerService;@RequestMapping("workerList")public String list(@RequestParam(required = false,defaultValue = "1",value = "pageNum") Integer pageNum,@RequestParam(required = false,defaultValue = "10",value = "pageSize") Integer pageSize,Model model, Worker worker){//Model用于存PageInfoif (pageNum<=0||pageNum.equals("")||pageNum==null){pageNum = 1;}if (pageSize<=0||pageSize.equals("")||pageSize==null){pageSize = 10;}PageHelper.startPage(pageNum,pageSize);PageInfo<Worker> list = workerService.list(worker);model.addAttribute("pageInfo",list);return "workerList";}@RequestMapping("preSaveWorker")public String preAdd(){return "workerSave";}@PostMapping("workerSave")public String add(Worker worker, MultipartFile file){transFile(worker,file);workerService.addWorker(worker);return "redirect:/worker/workerList";}private void transFile(Worker worker, MultipartFile file) {String originalFileName = file.getOriginalFilename();int index = originalFileName.lastIndexOf(".");String suffix = originalFileName.substring(index);String prefix = System.nanoTime()+"";String path = prefix+suffix;File file1 = new File(location);if(!file1.exists()){file1.mkdirs();}File file2 = new File(file1,path);try {file.transferTo(file2);} catch (IOException e) {e.printStackTrace();}worker.setWorkerImage(path);}@RequestMapping("preUpdateWorker/{id}")public String preUpdate(@PathVariable Integer id,Model model){Worker worker = workerService.getWorkerById(id);model.addAttribute("worker",worker);return "workerUpdate";}@RequestMapping("updateWorker")public String update(Worker worker,MultipartFile file){transFile(worker,file);int i = workerService.updateWorker(worker);return "redirect:/worker/workerList";}//ajax传参数放在Data里了,不用@PathVariable接收,也不用跳转@PostMapping("addSalary")@ResponseBodypublic String addSalary(Integer wid,String workerSalary){int i = workerService.updateSalary(wid, workerSalary);if(i>0){//返回值根据前端ajax(workerList.html中)写好的参数返回return "OK";}else{return "error";}}
}
7、送水历史管理模块
需要tb_history表
需要用到一些mybatisPlus没有的方法,需要在mapper下写需要的方法,具体实现在resources/com/example/HistoryMapper.xml
@Repository
public interface HistoryMapper extends BaseMapper<History> {List<History> listHistory(Map<String,Object> map);//除了mybatisPlus自己的一些方法,如果有其他方法,需要自己在下面写//相当于接口,具体实现在resources下的HistoryMapper.xml文件里,写SQL语句//添加int addHis(History history);//批量删除int deleteHis(List<Integer> ids);//根据id获取history对象History getHisById(Integer id);//修改int updateHis(History history);
}
HistoryMapper.xml文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!--记住 我的电脑这里只能是http才能出来小鸟-->
<mapper namespace="com.example.mapper.HistoryMapper"><resultMap id="historyMap" type="com.example.pojo.History"><id column="hid" property="hid"/><result column="send_water_time" property="sendWaterTime"/><result column="send_water_count" property="sendWaterCount"/><association property="customer"><id column="cid" property="cid"/><result column="cust_name" property="custName"/></association><association property="worker"><id column="wid" property="wid"/><result column="worker_name" property="workerName"/></association></resultMap><select id="listHistory" resultType="com.example.pojo.History" resultMap="historyMap">select h.hid, w.worker_name, c.cust_name, h.send_water_time, h.send_water_countfrom tb_history h,tb_customer c,tb_worker w<where>AND h.cust_id=c.cid AND h.worker_id=w.wid<if test="workerName != null and workerName!='' ">and w.worker_name like concat('%',#{workerName},'%')</if><if test="sendWaterTime != null and sendWaterTime !='' ">and h.send_water_time like concat('%',#{sendWaterTime},'%')</if></where></select><insert id="addHis">insert into tb_history (cust_id,worker_id,send_water_time,send_water_count)values (#{customer.cid},#{worker.wid},#{sendWaterTime},#{sendWaterCount})</insert><delete id="deleteHis">delete from tb_historywhere hid in<foreach collection="ids" item="hid" open="(" close=")" separator=",">#{hid}</foreach></delete><select id="getHisById" resultType="com.example.pojo.History" resultMap="historyMap">select h.hid, w.worker_name, c.cust_name, h.send_water_time, h.send_water_countfrom tb_history h,tb_customer c,tb_worker w where h.cust_id=c.cid and h.worker_id=w.wid and hid=#{id}</select><update id="updateHis">update tb_history set cust_id=#{customer.cid},worker_id=#{worker.wid},send_water_time=#{sendWaterTime},send_water_count=#{sendWaterCount}where hid=#{hid}</update>
</mapper>
然后在业务层完成业务,controller层完成,controller层有一个数据回显的功能模块
@RequestMapping("preSaveHis")//添加功能需要数据回显,必须是已经存在的worker和customer//数据回显是放在model中的public String preAddHis(Model model){List<Worker> workers = workerService.queryWorker();List<Customer> customer = customerService.querycustomer();//在historySave.html中有变量名,"custList"需要保持一致model.addAttribute("custList",customer);model.addAttribute("workerList",workers);return "historySave";}
8、计算薪资模块
在pojo创建Salary实体类
在mapper下创建SalaryMapper(用@Repository注解)
主要是sql语句
SalaryMapper.xml文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!--记住 我的电脑这里只能是http才能出来小鸟-->
<mapper namespace="com.example.mapper.SalaryMapper"><select id="list" resultType="com.example.pojo.Salary">SELECT w.worker_name,w.worker_salary,w.worker_money,IFNULL(SUM(h.send_water_count),0) as send_water_count,IFNULL(SUM(w.worker_money*h.send_water_count)+w.worker_salary , w.worker_salary) as final_salaryFROMtb_worker w LEFT JOIN tb_history h on w.wid=h.worker_id<where><if test="startDate!=null and startDate!='' and endDate!=null and endDate != '' ">and h.send_water_time between #{startDate} and #{endDate}</if></where>GROUP BY w.widORDER BY final_salary DESC</select><select id="listAll" resultType="com.example.pojo.Salary">SELECT w.worker_name,w.worker_salary,w.worker_money,IFNULL(SUM(h.send_water_count),0) as send_water_count,IFNULL(SUM(w.worker_money*h.send_water_count)+w.worker_salary , w.worker_salary) as final_salaryFROMtb_worker w LEFT JOIN tb_history h on w.wid=h.worker_idGROUP BY w.widORDER BY final_salary DESC</select><select id="listNull" resultType="com.example.pojo.Salary">SELECT w.worker_name,w.worker_salary,w.worker_money,IFNULL(SUM(h.send_water_count),0) as send_water_count,IFNULL(SUM(w.worker_money*h.send_water_count)+w.worker_salary , w.worker_salary) as final_salaryFROMtb_worker w LEFT JOIN tb_history h on w.wid=h.worker_idwhere h.worker_id is nullGROUP BY w.widORDER BY final_salary DESC</select>
</mapper>