1 员工端审批
- 需求分析
1.1 查询审批分类与模板接口
- 需求分析
- 返回的数据格式(ProcessType实体类)
- 同时返回审批类型和所有的审批模板processTemplateList
@TableField(exist = false)
private List<ProcessTemplate> processTemplateList;
- 在controllerr下新建一个包api,专门用来存放客户端的代码
- com.atguigu.serviceoa.process.controller.api.ProcessApiController
package com.atguigu.serviceoa.process.controller.api;
import com.atguigu.common.result.Result;
import com.atguigu.enity.model.process.ProcessType;
import com.atguigu.serviceoa.process.service.ProcessTemplateService;
import com.atguigu.serviceoa.process.service.ProcessTypeService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@Api(tags = "员工端审批流管理")
@RestController
@RequestMapping(value="/admin/process")
@CrossOrigin //解决跨域(访问协议、IP地址、端口号有一个不一样)
public class ProcessApiController {
@Autowired
private ProcessTypeService processTypeService;
@ApiOperation(value = "获取全部审批分类及审批分类的所有模板")
@GetMapping("findProcessType")
public Result findProcessType() {
List<ProcessType> list= processTypeService.findProcessType();
return Result.ok(list);
}
}
- com.atguigu.serviceoa.process.service.ProcessTypeService
// 获取全部审批分类及审批分类的所有模板
List<ProcessType> findProcessType();
- com.atguigu.serviceoa.process.service.impl.ProcessTypeServiceImpl
@Autowired
private ProcessTemplateService processTemplateService;
// 获取全部审批分类及审批分类的所有模板
@Override
public List<ProcessType> findProcessType() {
// 1 查询所有审批分类,返回list集合
List<ProcessType> processTypeList = baseMapper.selectList(null);
// 2 遍历list集合,返回每一个审批分类
processTypeList.stream().forEach( item -> {
// 3 得到每一个审批分类,根据审批分类ID查询对应的审批模板
LambdaQueryWrapper<ProcessTemplate> lqw = new LambdaQueryWrapper<>();
lqw.eq(ProcessTemplate::getProcessTypeId,item.getId());
List<ProcessTemplate> processTemplateList = processTemplateService.list(lqw);
// 4 把审批模板数据封装到对应的审批的分类中
item.setProcessTemplateList(processTemplateList);
});
// 5 返回数据
return processTypeList;
}
- 前端整合:复制粘贴即可
1.2 审批申请
1.3 启动流程实例
1.3.1 修改认证过滤器
- 创建用户信息帮助类,获取当前用户信息帮助类
- com.atguigu.common.springSecurity.custom.LoginUserInfoHelper
package com.atguigu.common.springSecurity.custom;
/**
* 获取当前用户信息帮助类
*/
public class LoginUserInfoHelper {
private static ThreadLocal<Long> userId = new ThreadLocal<Long>();
private static ThreadLocal<String> username = new ThreadLocal<String>();
public static void setUserId(Long _userId) {
userId.set(_userId);
}
public static Long getUserId() {
return userId.get();
}
public static void removeUserId() {
userId.remove();
}
public static void setUsername(String _username) {
username.set(_username);
}
public static String getUsername() {
return username.get();
}
public static void removeUsername() {
username.remove();
}
}
- 修改过滤器TokenAuthenticationFilter
- 通过ThreadLocal记录当前登录人信息
// token不为空
if (!StringUtils.isEmpty(token)) {
String username = JwtHelper.getUsername(token);
// usename不为空 返回返回封装的对象
if (!StringUtils.isEmpty(username)) {
//通过ThreadLocal记录当前登录人信息
LoginUserInfoHelper.setUserId(JwtHelper.getUserId(token));
LoginUserInfoHelper.setUsername(username);
// 通过用户名称从redis中获取权限数据
String authorString = (String) redisTemplate.opsForValue().get(username);
- 封装启动流程对象
- com.atguigu.enity.vo.process.ProcessFormVo
package com.atguigu.enity.vo.process;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(description = "流程表单")
public class ProcessFormVo {
@ApiModelProperty(value = "审批模板id")
private Long processTemplateId;
@ApiModelProperty(value = "审批类型id")
private Long processTypeId;
@ApiModelProperty(value = "表单值")
private String formValues;
}
- 前端返回的数据格式
- com.atguigu.serviceoa.process.controller.api.ProcessApiController
@ApiOperation(value = "启动流程实例")
@PostMapping("/startUp")
public Result start(@RequestBody ProcessFormVo processFormVo) {
processService.startUp(processFormVo);
return Result.ok();
}
- com.atguigu.serviceoa.process.service.ProcessService
// 启动流程实例
void startUp(ProcessFormVo processFormVo);
- com.atguigu.serviceoa.process.service.impl.ProcessServiceImpl
// 启动流程实例
@Override
public void startUp(ProcessFormVo processFormVo) {
// 1 根据当前用户ID获取用户信息
// 用户ID保存在LoginUserInfoHelper中,直接取就好
SysUser sysUser = sysUserService.getById(LoginUserInfoHelper.getUserId());
// 2 根据审批模板id查询审批模板信息
ProcessTemplate processTemplate = processTemplateService.getById(processFormVo.getProcessTemplateId());
// 3 保存用户提交的审批信息到业务表:oa-process
// 定义一个新的oa_process
Process process = new Process();
// 使用一个工具类 processFormVo的值复制到process 对应值可以全部复制进去
BeanUtils.copyProperties(processFormVo,process);
// 其他值 一个一个set
// 加空格 转化为string
String workNo = System.currentTimeMillis() + "";
process.setProcessCode(workNo);
process.setUserId(LoginUserInfoHelper.getUserId());
process.setFormValues(processFormVo.getFormValues());
process.setTitle(sysUser.getName() + "发起" + processTemplate.getName() + "申请");
process.setStatus(1);
baseMapper.insert(process);
// 4 启动流程实例
// 4.1 流程定义key
String processDefinitionKey = processTemplate.getProcessDefinitionKey();
// 4.2 业务Key 用processId表示 Long类型转化为String类型
String businessId = String.valueOf(process.getId());
// 4.3 流程参数 form表单数据-json格式,转化为map集合
// 后台是json数据格式,传到前台变成了string
String formValues = processFormVo.getFormValues();
// Object格式逆转为JOSN格式
JSONObject jsonObject = JSON.parseObject(formValues);
// 取出JOSN数据中 formData对应的数据
JSONObject formData = jsonObject.getJSONObject("formData");
// 遍历formData得到里面的数据,封装集合
Map<String,Object> map = new HashMap<>();
// 这段代码在复习一下java基础
for (Map.Entry<String, Object> entry : formData.entrySet()) {
map.put(entry.getKey(), entry.getValue());
}
// 定义一个新的map,key:data value:map
Map<String,Object> variables = new HashMap<>();
variables.put("data", map);
// 重载了很多方法,这次我们用包含三个参数的,启动流程实例
// 第二个参数必须是string类型
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey
(processDefinitionKey,businessId,variables);
// 5 查询下一个审批人
// 审批人可能有多个
// Task的包不要导错啦
// 根据id返回当前任务列表 activity的知识点
List<Task> taskList = this.getCurrentTaskList(processInstance.getId());
// 遍历任务列表 返回下一个审批人集合
List<Object> nameList = taskList.stream().map(item -> {
// 从任务列表中得到审批人是谁
String assignee = item.getAssignee();
// 自己之前写的一个方法 通过用户名取得用户对象
SysUser sysUserByUserName = sysUserService.getUserByUsername(assignee);
// name里面才是真实姓名
String name = sysUserByUserName.getName();
return name;
}).collect(Collectors.toList());
//TODO 6 推送消息到微信公众号
// 7 业务和流程关联 更新oa-process,保存最完整的数据
// 流程实例id
process.setProcessInstanceId(processInstance.getId());
// 描述信息 nameList变成数组,并且用逗号隔开
process.setDescription("等待" + StringUtils.join(nameList.toArray(), ",") + "审批");
baseMapper.updateById(process);
}
// 根据id返回当前任务列表
private List<Task> getCurrentTaskList(String id) {
List<Task> tasks = taskService.createTaskQuery().processInstanceId(id).list();
return tasks;
}
1.4 记录提交记录
- 需求分析
- 代码生成器生成service和mapper,不需要controller
- com.atguigu.serviceoa.process.service.ProcessRecordService
package com.atguigu.serviceoa.process.service;
import com.atguigu.enity.model.process.ProcessRecord;
import com.baomidou.mybatisplus.extension.service.IService;
import org.springframework.stereotype.Service;
/**
* 审批记录 服务类
*/
@Service
public interface ProcessRecordService extends IService<ProcessRecord> {
// 记录提交记录
void record(Long processId,Integer status,String description);
}
- com.atguigu.serviceoa.process.service.impl.ProcessRecordServiceImpl
package com.atguigu.serviceoa.process.service.impl;
import com.atguigu.common.springSecurity.custom.LoginUserInfoHelper;
import com.atguigu.enity.model.process.ProcessRecord;
import com.atguigu.enity.model.system.SysUser;
import com.atguigu.serviceoa.auth.service.SysUserService;
import com.atguigu.serviceoa.process.mapper.ProcessRecordMapper;
import com.atguigu.serviceoa.process.service.ProcessRecordService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* 审批记录 服务实现类
*/
@Service
public class ProcessRecordServiceImpl extends ServiceImpl<ProcessRecordMapper, ProcessRecord> implements ProcessRecordService {
@Autowired
private SysUserService sysUserService;
@Override
public void record(Long processId, Integer status, String description) {
// 定义一个实例对象
ProcessRecord processRecord = new ProcessRecord();
// 获取当前登录用户ID
Long userId = LoginUserInfoHelper.getUserId();
SysUser sysUser = sysUserService.getById(userId);
// 往里面set数据
processRecord.setProcessId(processId);
processRecord.setStatus(status);
processRecord.setDescription(description);
// 放的应该是发出申请的人的信息
processRecord.setOperateUserId(userId);
processRecord.setOperateUser(sysUser.getName());
baseMapper.insert(processRecord);
}
}
- 修改com.atguigu.serviceoa.process.service.impl.ProcessServiceImpl
- 加上第八步
// 7 业务和流程关联 更新oa-process,保存最完整的数据
// 流程实例id
process.setProcessInstanceId(processInstance.getId());
// 描述信息 nameList变成数组,并且用逗号隔开
process.setDescription("等待" + StringUtils.join(nameList.toArray(), ",") + "审批");
baseMapper.updateById(process);
// 8 记录操作审批记录
// TODO 这里有个疑问:process是我们自己set的,还没有存入数据库,会带有id吗
processRecordService.record(process.getId(),1,"发起申请");
1.5 待处理列表
- 启动流程后,审批人就可以在待处理列表中获取审批列表了
1.6 执行审批
- com.atguigu.serviceoa.process.service.ProcessService
// 执行审批
void approve(ApprovalVo approvalVo);
- com.atguigu.serviceoa.process.service.impl.ProcessServiceImpl
// 执行审批
public void approve(ApprovalVo approvalVo) {
// 1 从approvalVo中获取任务id 根据任务id获取流程变量
String taskId = approvalVo.getTaskId();
// TODO 这一段不太懂
Map<String, Object> variables = taskService.getVariables(taskId);
for (Map.Entry<String, Object> entry : variables.entrySet()) {
System.out.println("Key = " + entry.getKey());
System.out.println("Value = " + entry.getValue());
}
// 2 判断审批状态值
if (approvalVo.getStatus() == 1){
// 2.1 状态值为2 审批通过
// 如果有别的流程变量 可以继续设置 我们这里没有 就是定义一个结构
Map<String, Object> variable = new HashMap<String, Object>();
taskService.complete(taskId, variable);
} else {
// 2.2 状态值为-1 审批驳回 流程直接结束
this.endTask(taskId);
}
// 3 记录审批过程相关信息 oa_prrocess_record
// 这个方法已经写过了 传递三个参数
processRecordService.record(
approvalVo.getProcessId(),
approvalVo.getStatus(),
approvalVo.getDescription());
// 4 查询下一个审批人(更新流程表记录) process表记录
Process process = baseMapper.selectById(approvalVo.getProcessId());
// 根据流程实例Id查询任务(前面写过)
List<Task> currentTaskList = this.getCurrentTaskList(process.getProcessInstanceId());
// 如果查询出来的任务为空 说明没有下一个审批人
if (!CollectionUtils.isEmpty(currentTaskList)){
// 一个任务可能有多人审批
List<String> assignList = new ArrayList<>();
for (Task task : currentTaskList) {
// 这里的assignee对应的是sysuser的username
String assignee = task.getAssignee();
// 根据username查询用户对象
SysUser sysUser = sysUserService.getUserByUsername(assignee);
assignList.add(sysUser.getName());
// TODO 微信公众号推送
}
// (更新流程表记录) process表记录
process.setDescription("等待" + StringUtils.join(assignList.toArray(), ",") + "审批");
process.setStatus(1);
} else {
// 没有审批任务了 审批完成
if (approvalVo.getStatus().intValue()== 1){
process.setStatus(2);
process.setDescription("审批完成(通过)");
} else {
process.setStatus(-1);
process.setDescription("审批完成(驳回)");
}
}
// 做最后的更新
baseMapper.updateById(process);
}
- com.atguigu.serviceoa.process.controller.ProcessController
@ApiOperation(value = "执行审批")
@PostMapping("approve")
public Result approve(@RequestBody ApprovalVo approvalVo) {
processService.approve(approvalVo);
return Result.ok();
}
- 状态值为-1 审批驳回 流程直接结束
- com.atguigu.serviceoa.process.service.impl.ProcessServiceImpl
// 状态是-1 直接结束流程 根据任务ID直接结束流程
// 这个代码 直接复制粘贴即可
private void endTask(String taskId) {
// 1 根据任务Id获取当前任务对象 Task
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
// 2 获取流程定义模型 BpmnModel
BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
// 3 获取结束流向节点
List endEventList = bpmnModel.getMainProcess().findFlowElementsOfType(EndEvent.class);
if(CollectionUtils.isEmpty(endEventList)) {
return;
}
FlowNode endFlowNode = (FlowNode) endEventList.get(0);
// 4 获取当前流向节点
FlowNode currentFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(task.getTaskDefinitionKey());
// 5 清理当前流动方向
// 临时保存当前活动的原始方向
List originalSequenceFlowList = new ArrayList<>();
originalSequenceFlowList.addAll(currentFlowNode.getOutgoingFlows());
// 清理活动方向
currentFlowNode.getOutgoingFlows().clear();
// 6 创建新流向
SequenceFlow newSequenceFlow = new SequenceFlow();
newSequenceFlow.setId("newSequenceFlowId");
newSequenceFlow.setSourceFlowElement(currentFlowNode);
newSequenceFlow.setTargetFlowElement(endFlowNode);
List newSequenceFlowList = new ArrayList<>();
newSequenceFlowList.add(newSequenceFlow);
// 7 当前节点指向新方向
currentFlowNode.setOutgoingFlows(newSequenceFlowList);
// 8 完成当前任务
taskService.complete(task.getId());
}
1.7 查询已处理信息
- 需求分析
- 还是写一个分页查询(练习一下)
- com.atguigu.serviceoa.process.controller.ProcessController
@ApiOperation(value = "查询已处理已处理")
@GetMapping("/findProcessed/{page}/{limit}")
public Result findProcessed(@PathVariable Long page, @PathVariable Long limit) {
Page<Process> pageParam = new Page<>(page, limit);
// 查询已处理
IPage<ProcessVo> pageModel = processService.findProcessed(pageParam);
return Result.ok(pageModel);
}
- com.atguigu.serviceoa.process.service.ProcessService
// 查询已处理
IPage<ProcessVo> findProcessed(Page<Process> pageParam);
- com.atguigu.serviceoa.process.service.impl.ProcessServiceImpl
// 查询已处理
public IPage<ProcessVo> findProcessed(Page<Process> pageParam) {
// 1 封装查询条件
HistoricTaskInstanceQuery query = historyService
.createHistoricTaskInstanceQuery()
// 根据当前登录的用户名
.taskAssignee(LoginUserInfoHelper.getUsername())
.finished()
.orderByTaskCreateTime()
.desc();
// 2 调用方法分页查询 返回List集合
// query自带的方法listPage
// listPage有两个参数:
// 第一个参数:开始位置 (当前页面-1)*,每页记录数
int begin = (int) ((pageParam.getCurrent() - 1) * pageParam.getSize());
// 第二个参数:每页显示记录数
int size = (int) pageParam.getSize();
// 用的是listPage 返回List<HistoricTaskInstance>集合
List<HistoricTaskInstance> list = query.listPage(begin, size);
// 3 遍历返回的List集合 封装为IPage<ProcessVo>
// 先定义一个List<ProcessVo>的空集合
List<ProcessVo> processVoList = new ArrayList<>();
for (HistoricTaskInstance item : list) {
// 获取流程实例ID
String processInstanceId = item.getProcessInstanceId();
// 根据流程实例ID获取对应的process信息
LambdaQueryWrapper<Process> lqw = new LambdaQueryWrapper<>();
lqw.eq(Process::getProcessInstanceId,processInstanceId);
Process process = baseMapper.selectOne(lqw);
// 把process转化为processVo
ProcessVo processVo = new ProcessVo();
BeanUtils.copyProperties(process,processVo);
// 放到List 中
processVoList.add(processVo);
}
// 4 IPage封装分页查询所有数据,返回
// 返回的数据总条数
long count = query.count();
IPage<ProcessVo> pageModel = new Page<ProcessVo>(pageParam.getCurrent(),pageParam.getSize(),count);
pageModel.setRecords(processVoList);
return pageModel;
}
1.8 查询已发起
- 根据当前用户ID查询oa_process表
- 与之前的一个方法很像:
- com.atguigu.serviceoa.process.mapper.ProcessMapper
// 获取审批管理分页列表
// @Param("vo"):在xml文件中processQueryVo参数就叫做vo
IPage<ProcessVo> selectPage(Page<ProcessVo> page, @Param("vo") ProcessQueryVo processQueryVo);
- com.atguigu.serviceoa.process.controller.ProcessController
@ApiOperation(value = "查询已发起")
@GetMapping("/findStarted/{page}/{limit}")
public Result findStarted(
@ApiParam(name = "page", value = "当前页码", required = true)
@PathVariable Long page,
@ApiParam(name = "limit", value = "每页记录数", required = true)
@PathVariable Long limit) {
Page<ProcessVo> pageParam = new Page<>(page, limit);
IPage<ProcessVo> pageModel = processService.findStarted(pageParam);
return Result.ok(pageModel);
}
- com.atguigu.serviceoa.process.service.ProcessService
// 查询已发起
IPage<ProcessVo> findStarted(Page<ProcessVo> pageParam);
- com.atguigu.serviceoa.process.service.impl.ProcessServiceImpl
@Override
// 查询已发起
// 与之前的一个方法很像
public IPage<ProcessVo> findStarted(Page<ProcessVo> pageParam) {
ProcessQueryVo processQueryVo = new ProcessQueryVo();
// 一共有三个条件 这里只有一个条件userID
processQueryVo.setUserId(LoginUserInfoHelper.getUserId());
IPage<ProcessVo> pageModel = baseMapper.selectPage(pageParam, processQueryVo);
return pageModel;
}
1.9 用户基本信息
- com.atguigu.serviceoa.process.controller.ProcessController
@ApiOperation(value = "获取当前用户基本信息")
@GetMapping("getCurrentUser")
public Result getCurrentUser() {
Map<String,Object> map = sysUserService.getCurrentUser();
return Result.ok(map);
}
- com.atguigu.serviceoa.auth.service.SysUserService
// 获取当前用户基本信息
Map<String, Object> getCurrentUser();
- com.atguigu.serviceoa.auth.service.impl.SysUserServiceImpl
@Override
// 获取当前用户基本信息
public Map<String, Object> getCurrentUser() {
SysUser sysUser = baseMapper.selectById(LoginUserInfoHelper.getUserId());
Map<String, Object> map = new HashMap<>();
map.put("name", sysUser.getName());
map.put("phone", sysUser.getPhone());
return map;
}
2 微信小程序
2.1 功能说明
- 员工端使用微信公众号完成审批操作,涉及到的功能包含:自定义菜单、授权登录、消息
- 微信公众号一级菜单为:审批列表、审批中心、我的
- 员工关注公众号,员工第一次登录微信公众号,通过微信授权登录进行员工账号绑定
- 员工通过公众号提交审批和审批信息,系统根据微信公众号推送审批信息,及时反馈审批过程
- 公众号一级菜单,数据库默认初始化(审批列表、审批中心、我的)
2.2 公众号菜单CRUD
2.2.1 代码生成器细节知识——去掉表格前缀
// 5、策略配置
StrategyConfig strategy = new StrategyConfig();
// 指定表的名称
strategy.setInclude("wechat_menu");
// 去除数据库表格的的前缀
strategy.setTablePrefix("wechat_");
2.2.2 MenuVo——树形结构
- 多了一个属性,menu中没有
- children中就是二级三级菜单
@ApiModelProperty(value = "下级")
@TableField(exist = false)
private List<MenuVo> children;
2.2.3 具体代码
- com.atguigu.serviceoa.wechat.controller.MenuController
package com.atguigu.serviceoa.wechat.controller;
import com.atguigu.common.result.Result;
import com.atguigu.enity.model.wechat.Menu;
import com.atguigu.enity.vo.wechat.MenuVo;
import com.atguigu.serviceoa.wechat.service.MenuService;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/admin/wechat/menu")
@Slf4j
public class MenuController {
@Autowired
private MenuService menuService;
//@PreAuthorize("hasAuthority('bnt.menu.list')")
@ApiOperation(value = "获取全部菜单——树形结构")
@GetMapping("findMenuInfo")
public Result findMenuInfo() {
List<MenuVo> menuVoList = menuService.findMenuInfo();
return Result.ok(menuVoList);
}
//@PreAuthorize("hasAuthority('bnt.menu.list')")
@ApiOperation(value = "根据ID获取菜单对象")
@GetMapping("get/{id}")
public Result get(@PathVariable Long id) {
Menu menu = menuService.getById(id);
return Result.ok(menu);
}
//@PreAuthorize("hasAuthority('bnt.menu.add')")
@ApiOperation(value = "新增")
@PostMapping("save")
public Result save(@RequestBody Menu menu) {
menuService.save(menu);
return Result.ok();
}
//@PreAuthorize("hasAuthority('bnt.menu.update')")
@ApiOperation(value = "修改")
@PutMapping("update")
public Result updateById(@RequestBody Menu menu) {
menuService.updateById(menu);
return Result.ok();
}
//@PreAuthorize("hasAuthority('bnt.menu.remove')")
@ApiOperation(value = "删除")
@DeleteMapping("remove/{id}")
public Result remove(@PathVariable Long id) {
menuService.removeById(id);
return Result.ok();
}
}
- com.atguigu.serviceoa.wechat.service.MenuService
package com.atguigu.serviceoa.wechat.service;
import com.atguigu.enity.model.wechat.Menu;
import com.atguigu.enity.vo.wechat.MenuVo;
import com.baomidou.mybatisplus.extension.service.IService;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* 菜单 服务类
*/
@Service
public interface MenuService extends IService<Menu> {
// 获取全部菜单——树形结构
List<MenuVo> findMenuInfo();
}
- com.atguigu.serviceoa.wechat.service.impl.MenuServiceImpl
package com.atguigu.serviceoa.wechat.service.impl;
import com.atguigu.enity.model.wechat.Menu;
import com.atguigu.enity.vo.wechat.MenuVo;
import com.atguigu.serviceoa.wechat.mapper.MenuMapper;
import com.atguigu.serviceoa.wechat.service.MenuService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* <p>
* 菜单 服务实现类
* </p>
*\
* @author atguigu
* @since 2023-05-06
*/
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements MenuService {
@Override
// 获取全部菜单——树形结构
// 目前只有两个层级,不用搞树形结构那么麻烦
public List<MenuVo> findMenuInfo() {
// 1 查询所有菜单List<Menu>集合
List<Menu> menuList = baseMapper.selectList(null);
// 把List<Menu>复制到ListVo<Menu>
// 只能复制对象 不能直接复制对象集合
List<MenuVo> menuVoList = new ArrayList<>();
menuList.stream().forEach( item ->{
MenuVo menuVo = new MenuVo();
BeanUtils.copyProperties(item,menuVo);
menuVoList.add(menuVo);
});
// 2 查询所有一级菜单 parent_id = 0 ,返回一级菜单List<Menu>集合
List<MenuVo> menuListVo1 = menuVoList.stream()
.filter(item -> item.getParentId().longValue() == 0)
.collect(Collectors.toList());
// 3 一级菜单List集合遍历,得到每个一级菜单
for (MenuVo menuVo : menuListVo1) {
List<MenuVo> children = new ArrayList<>();
menuVoList.stream().forEach( item ->{
// 4 获取每个一级菜单里面的所有二级菜单 一级菜单id等于二级菜单parentId
// 定义一个空集合 children,用来封装二级菜单
if (item.getParentId().longValue() == menuVo.getId().longValue()){
// 5 把一级菜单里面的所有二级菜单找到,封装在一级菜单的children里面
children.add(item);
}
});
menuVo.setChildren(children);
}
// 3 一级菜单List集合遍历,得到每个一级菜单
// for (MenuVo menuVo : menuListVo1) {
// List<MenuVo> children = menuVoList.stream().filter(item -> {
// // 4 获取每个一级菜单里面的所有二级菜单 一级菜单id等于二级菜单parentId
// if (item.getParentId().longValue() == menuVo.getId().longValue()) {
// return item;
// }
// }).collect(Collectors.toList());
// }
return menuListVo1;
}
}
2.推送菜单
- 需求分析
- 后台员工账号与微信账号是没有关联的,在点击微信菜单时,要判断是否登录
- 第一次访问则弹出关联层,建立微信账号与员工账号的绑定
- 即:通过员工手机号码与微信openId建立绑定,后续进入就知道用户身份了。
- 老师的免费域名:
- http://ggkt2.vipgz1.91tunnel.com 8800 ID:075952342272
- http://ggkt1.vipgz1.91tunnel.com 9090 ID:075735342272