排版效果

image.png

第一步:获取审批单号

参考:https://developer.work.weixin.qq.com/document/path/91816
请求方式:POST(HTTPS
请求地址:https://qyapi.weixin.qq.com/cgi-bin/oa/getapprovalinfo?access_token=ACCESS_TOKEN
请求示例:

  1. {
  2. "starttime" : "1569546000",
  3. "endtime" : "1569718800",
  4. "cursor" : 0 ,
  5. "size" : 100 ,
  6. "filters" : [
  7. {
  8. "key": "template_id",
  9. "value": "ZLqk8pcsAoaXZ1eY56vpAgfX28MPdYU3ayMaSPHaaa"
  10. },
  11. {
  12. "key" : "creator",
  13. "value" : "WuJunJie"
  14. },
  15. {
  16. "key" : "department",
  17. "value" : "1"
  18. },
  19. {
  20. "key" : "sp_status",
  21. "value" : "1"
  22. }
  23. ]
  24. }

第二步:根据获取的审批单号再去查询审批的详情

参考:https://developer.work.weixin.qq.com/document/path/91983
请求方式:POST(HTTPS
请求地址: https://qyapi.weixin.qq.com/cgi-bin/oa/getapprovaldetail?access_token=ACCESS_TOKEN
请求示例:

  1. {
  2. "sp_no" : "201909270001"
  3. }

JAVA程序

  1. package com.tj.qywx.service.impl;
  2. import com.alibaba.excel.util.ListUtils;
  3. import com.alibaba.excel.util.MapUtils;
  4. import com.alibaba.fastjson.JSON;
  5. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  6. import com.tj.base.service.BaseNumvarService;
  7. import com.tj.qywx.domain.WxApproval;
  8. import com.tj.qywx.domain.WxUserlist;
  9. import com.tj.qywx.service.WxApprovalService;
  10. import com.tj.qywx.service.WxDepartmentService;
  11. import com.tj.qywx.service.WxUserlistService;
  12. import com.tj.utils.TjDateUtils;
  13. import lombok.extern.slf4j.Slf4j;
  14. import org.apache.commons.lang3.StringUtils;
  15. import org.springframework.beans.factory.annotation.Autowired;
  16. import org.springframework.stereotype.Service;
  17. import org.springframework.web.client.RestTemplate;
  18. import java.util.ArrayList;
  19. import java.util.HashMap;
  20. import java.util.List;
  21. import java.util.Map;
  22. @Slf4j
  23. @Service
  24. public class WxApprovalServiceImpl implements WxApprovalService {
  25. @Autowired
  26. private BaseNumvarService baseNumvarService;
  27. @Autowired
  28. private RestTemplate restTemplate;
  29. @Autowired
  30. private WxUserlistService wxUserlistService;
  31. @Autowired
  32. private WxDepartmentService wxDepartmentService;
  33. @Override
  34. public Map<String, Object> show(Integer pagenum, Integer pagesize,
  35. Long starttime, Long endtime,
  36. String applyerName,
  37. String sp_status,
  38. String record_type,
  39. List deptid) {
  40. if (starttime == null) {
  41. //参数:开始时间戳(秒)//30天前0:0:0的时间戳(秒)
  42. starttime = TjDateUtils.chooseDay(TjDateUtils.getTodayBegin(), -30).getTime() / 1000;
  43. }
  44. if (endtime == null) {
  45. //参数:结束时间戳,当前时间的时间戳(秒)
  46. endtime = System.currentTimeMillis() / 1000;
  47. }
  48. String token = baseNumvarService.getAccessTokenBySecret(baseNumvarService.getSecretSp());
  49. String url = "https://qyapi.weixin.qq.com/cgi-bin/oa/getapprovalinfo?access_token=" + token;
  50. //请求体数据,使用hashmap封装
  51. HashMap<String, Object> hashMap = MapUtils.newHashMap();
  52. hashMap.put("starttime", starttime);
  53. hashMap.put("endtime", endtime);
  54. hashMap.put("cursor", (pagenum - 1) * pagesize + 1);
  55. hashMap.put("size", pagesize);
  56. //其他条件
  57. ArrayList<Map> otherList = ListUtils.newArrayList();
  58. otherList.clear();
  59. //判断用户姓名条件
  60. if (applyerName != null) {
  61. LambdaQueryWrapper<WxUserlist> lqwUser = new LambdaQueryWrapper<>();
  62. lqwUser.eq(WxUserlist::getName, applyerName).last("LIMIT 1");//只取1条记录
  63. WxUserlist one = wxUserlistService.getOne(lqwUser);
  64. if (one != null) {
  65. otherListAdd("creator", one.getUserid(), otherList);
  66. }
  67. }
  68. //判断审批状态
  69. if (StringUtils.isNotEmpty(sp_status)) {
  70. otherListAdd("sp_status", sp_status, otherList);
  71. }
  72. //判断审批单类型属性
  73. if (StringUtils.isNotEmpty(record_type)) {
  74. otherListAdd("record_type", record_type, otherList);
  75. }
  76. //部门条件判断
  77. if (deptid != null && deptid.size() > 0) {
  78. for (Object id : deptid) {
  79. otherListAdd("department", String.valueOf(id), otherList);
  80. }
  81. }
  82. //判断filters里的查询条件
  83. if (otherList != null && otherList.size() > 0) {
  84. hashMap.put("filters", otherList);
  85. }
  86. log.info("请求体数据:{}", hashMap);
  87. Map map = restTemplate.postForObject(url, hashMap, Map.class);
  88. log.info("审批单号信息:{}", map);
  89. //用来缓存返回结果
  90. HashMap<String, Object> resMap = MapUtils.newHashMap();
  91. //判断是否有下页,记录总页数
  92. if (map.get("next_cursor") != null) {
  93. resMap.put("total", (Integer) (map.get("next_cursor")));
  94. } else {
  95. resMap.put("total", pagenum * pagesize);
  96. }
  97. if ((Integer) map.get("errcode") == 0) {
  98. List<String> list = (List<String>) map.get("sp_no_list");
  99. if (list != null && list.size() > 0) {
  100. ArrayList<WxApproval> wxApprovalList = ListUtils.newArrayList();
  101. HashMap<String, Object> hashMap1 = MapUtils.newHashMap();
  102. for (String spNo : list) {
  103. hashMap1.clear();
  104. //根据审批单号去查询详情
  105. String urlDetail = "https://qyapi.weixin.qq.com/cgi-bin/oa/getapprovaldetail?access_token=" + token;
  106. hashMap1.put("sp_no", spNo);
  107. Map mapDetail = restTemplate.postForObject(urlDetail, hashMap1, Map.class);
  108. log.info("转换后前》》》》审批单号:{},详情:{}", spNo, mapDetail);
  109. if ((Integer) mapDetail.get("errcode") == 0) {
  110. WxApproval wxApproval = JSON.parseObject(JSON.toJSONString(mapDetail.get("info")), WxApproval.class);
  111. //申请人信息
  112. Map applyer = wxApproval.getApplyer();
  113. //申请人userid
  114. String userid = (String) applyer.get("userid");
  115. wxApproval.setApplyerName(wxUserlistService.getById(userid).getName());
  116. //申请人所在部门id
  117. Integer partyid = Integer.valueOf((String) applyer.get("partyid"));
  118. wxApproval.setPartyName(wxDepartmentService.getById(partyid).getName());
  119. log.info("转换后》》》》{}", wxApproval);
  120. wxApprovalList.add(wxApproval);
  121. }
  122. }
  123. resMap.put("list", wxApprovalList);
  124. return resMap;
  125. }
  126. }
  127. return null;
  128. }
  129. /**
  130. * 审批单号,fiters的条件添加
  131. *
  132. * @param key
  133. * @param value
  134. * @param otherList
  135. */
  136. private void otherListAdd(String key, String value, List otherList) {
  137. HashMap<String, String> map = MapUtils.newHashMap();
  138. map.put("key", key);
  139. map.put("value", value);
  140. otherList.add(map);
  141. }
  142. }

前端查询部分

  1. <template>
  2. <div>
  3. <el-form ref="searchForm" :inline="true" :model="data" class="tj-form-search"
  4. label-width="80px">
  5. <el-form-item label="提交日期">
  6. <el-date-picker @change="datechange" v-model="date" type="daterange" align="right"
  7. unlink-panels range-separator="~" start-placeholder="开始日期"
  8. end-placeholder="结束日期" :picker-options="pickerOptions">
  9. </el-date-picker>
  10. </el-form-item>
  11. <el-form-item label="审批状态">
  12. <el-select clearable v-model="data.sp_status" placeholder="请选择">
  13. <el-option v-for="item in options.status" :key="item.value" :label="item.label"
  14. :value="item.value">
  15. </el-option>
  16. </el-select>
  17. </el-form-item>
  18. <el-form-item label="审批类型">
  19. <el-select clearable v-model="data.record_type" placeholder="请选择">
  20. <el-option v-for="item in options.type" :key="item.value" :label="item.label"
  21. :value="item.value">
  22. </el-option>
  23. </el-select>
  24. </el-form-item>
  25. <el-form-item label="部门">
  26. <el-cascader v-model="data.deptid" :options="options.wxdepts" :props="deptsProps"
  27. :show-all-levels='false' collapse-tags clearable @change="wxdeptChange">
  28. </el-cascader>
  29. </el-form-item>
  30. <el-form-item label="姓名">
  31. <el-input v-model.trim="data.applyerName" placeholder="请输入完整名称"></el-input>
  32. </el-form-item>
  33. <el-form-item>
  34. <el-button @click="search" type="primary" icon="el-icon-search">查询</el-button>
  35. <el-button @click="reset" icon="el-icon-refresh">重置</el-button>
  36. </el-form-item>
  37. </el-form>
  38. </div>
  39. </template>
  40. <script>
  41. import { WXdeptsTree } from '@/utils/common'
  42. import dateoption from '@/utils/dateoption.js'
  43. export default {
  44. props: {
  45. query: { //初始条件
  46. type: String
  47. }
  48. },
  49. data() {
  50. return {
  51. date: [],
  52. data: {
  53. starttime: null,
  54. endtime: null,
  55. filters: []
  56. },
  57. // 级联配置
  58. deptsProps: {
  59. multiple: true,
  60. value: 'id',
  61. label: 'name',
  62. emitPath: false,
  63. checkStrictly: true,//父子互不关联
  64. },
  65. // 全部options
  66. options: {
  67. wxdepts: [],
  68. // 类型
  69. type: [{ label: '请假', value: '1' },
  70. { label: '打卡补卡', value: '2' },
  71. { label: '出差', value: '3' },
  72. { label: '外出', value: '4' },
  73. { label: '加班', value: '5' },
  74. { label: '调班', value: '6' },
  75. { label: '会议室预定', value: '7' },
  76. { label: '退款审批', value: '8' },
  77. { label: '红包报销审批', value: '9' },
  78. ],
  79. // 状态
  80. status: [{ label: '审批中', value: '1' },
  81. { label: '已通过', value: '2' },
  82. { label: '已驳回', value: '3' },
  83. { label: '已撤销', value: '4' },
  84. { label: '通过后撤销', value: '6' },
  85. { label: '已删除', value: '7' },
  86. { label: '已支付', value: '10' },
  87. ],
  88. },
  89. // 日期快捷选项
  90. pickerOptions: dateoption.dayrange,
  91. }
  92. },
  93. methods: {
  94. // 重置
  95. reset() {
  96. this.data = this.$options.data().data
  97. this.date = []
  98. let p = { pagenum: 1 }
  99. console.log('查询条件', p);
  100. this.$emit('search', p)
  101. },
  102. // 查询
  103. async search() {
  104. // 条件合并
  105. this.data.pagenum = 1
  106. // 日期
  107. if (this.date && this.date.length > 0) {
  108. this.data.starttime = this.$dayjs(this.$dayjs(this.date[0]).format('YYYY-MM-DD 00:00:00')).unix() // 时间戳
  109. this.data.endtime = this.$dayjs(this.$dayjs(this.date[1]).format('YYYY-MM-DD 23:59:59')).unix() // 时间戳
  110. } else {
  111. this.data.starttime = null
  112. this.data.endtime = null
  113. }
  114. console.log('查询栏输出的条件', this.data);
  115. this.$emit('search', this.data)
  116. },
  117. datechange() {
  118. console.log(this.date)
  119. },
  120. // 用户ID汇总
  121. inUserid(data) {
  122. let userids = []
  123. if (data && data.length > 0) {
  124. userids = data.map(item => {
  125. return `"${item.userid}"`
  126. })
  127. }
  128. return userids.join()
  129. },
  130. // 获取所有部门信息
  131. async getAllWXdepts() {
  132. let res = await WXdeptsTree()
  133. console.log('res', res);
  134. this.options = {
  135. ...this.options, ...{ wxdepts: res }
  136. }
  137. },
  138. // 部门变化
  139. wxdeptChange(val) {
  140. console.log('val', val);
  141. console.log('this.data.deptid', this.data.deptid);
  142. },
  143. },
  144. created() {
  145. this.getAllWXdepts()
  146. },
  147. }
  148. </script>

注意点

获取审批单号的查询条件filters里面的值全部是字符类型的,里面部门查询的条件是可以多选的,但是值不是数组,而是应该像下面这样写
filters需要根据前端提供的数据,后端使用map进行组装,

{
  "filters" : [ 
    {
      "key" : "department",
      "value" : "1"
    },   
    {
      "key" : "department",
      "value" : "5"
    }, 
    {
      "key" : "department",
      "value" : "12"
    }     
  ]
}