فهرست منبع

Merge branch 'refs/heads/weixin'

yusm 1 ماه پیش
والد
کامیت
18c20a6406
18فایلهای تغییر یافته به همراه1185 افزوده شده و 3 حذف شده
  1. 5 0
      fhKeeper/formulahousekeeper/management-crm/pom.xml
  2. 21 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/UserQrCodeController.java
  3. 420 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/WechatAccountController.java
  4. 182 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/WeiXinTicketController.java
  5. 69 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/UserQrCode.java
  6. 89 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/WechatAccount.java
  7. 18 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/WeiXinTicketEntity.java
  8. 16 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/mapper/UserQrCodeMapper.java
  9. 31 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/mapper/WechatAccountMapper.java
  10. 16 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/UserQrCodeService.java
  11. 16 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/WechatAccountService.java
  12. 20 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/UserQrCodeServiceImpl.java
  13. 14 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/UserServiceImpl.java
  14. 99 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/WechatAccountServiceImpl.java
  15. 115 0
      fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/util/FileZipUtil.java
  16. 12 3
      fhKeeper/formulahousekeeper/management-crm/src/main/resources/application.yml
  17. 20 0
      fhKeeper/formulahousekeeper/management-crm/src/main/resources/mapper/UserQrCodeMapper.xml
  18. 22 0
      fhKeeper/formulahousekeeper/management-crm/src/main/resources/mapper/WechatAccountMapper.xml

+ 5 - 0
fhKeeper/formulahousekeeper/management-crm/pom.xml

@@ -21,6 +21,11 @@
             <scope>system</scope>
             <systemPath>${basedir}/src/main/resources/lib/taobao-sdk-java-auto_1479188381469-20210623.jar</systemPath>
         </dependency>
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+            <version>2.11.0</version>
+        </dependency>
         <dependency>
             <groupId>com.fasterxml.jackson.core</groupId>
             <artifactId>jackson-databind</artifactId>

+ 21 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/UserQrCodeController.java

@@ -0,0 +1,21 @@
+package com.management.platform.controller;
+
+
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ *  前端控制器
+ * </p>
+ *
+ * @author Seyason
+ * @since 2025-04-16
+ */
+@RestController
+@RequestMapping("/user-qr-code")
+public class UserQrCodeController {
+
+}
+

+ 420 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/WechatAccountController.java

@@ -0,0 +1,420 @@
+package com.management.platform.controller;
+
+
+import com.alibaba.fastjson2.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
+import com.management.platform.entity.User;
+import com.management.platform.entity.UserQrCode;
+import com.management.platform.entity.WechatAccount;
+import com.management.platform.service.CompanyService;
+import com.management.platform.service.UserQrCodeService;
+import com.management.platform.service.UserService;
+import com.management.platform.service.WechatAccountService;
+import com.management.platform.util.FileZipUtil;
+import com.management.platform.util.HttpRespMsg;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.conn.ssl.NoopHostnameVerifier;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.ssl.SSLContexts;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.*;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.client.RestTemplate;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+/**
+ * <p>
+ * 微信公众号账号表 前端控制器
+ * </p>
+ *
+ * @author Seyason
+ * @since 2025-04-15
+ */
+@Slf4j
+@RestController
+@RequestMapping("/wechat-account")
+public class WechatAccountController {
+
+    @Resource
+    private WechatAccountService wechatAccountService;
+
+    @Resource
+    private UserService userService;
+
+    @Resource
+    private RestTemplate restTemplate;
+
+    @Resource
+    private UserQrCodeService userQrCodeService;
+
+    @Resource
+    private CompanyService companyService;
+
+    @Value(value ="${upload.path}")
+    private String uploadPath;
+
+    private final static String prefixUrl="https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=";
+
+
+    //保存或修改
+    @RequestMapping("/saveOrUpdate")
+    public HttpRespMsg saveOrUpdate(WechatAccount wechatAccount ,HttpServletRequest request) {
+        HttpRespMsg httpRespMsg = new HttpRespMsg();
+        String token = request.getHeader("Token");
+        User user = userService.getById(token);
+        if (wechatAccount.getId()==null){
+            int count = wechatAccountService.count(new QueryWrapper<WechatAccount>().eq("company_id", user.getCompanyId()));
+            if (count>0){
+                httpRespMsg.setError("公司配置已存在,请传公司关键信息");
+                return httpRespMsg;
+            }
+            wechatAccount.setCompanyId(user.getCompanyId());
+            wechatAccountService.save(wechatAccount);
+        }else {
+            wechatAccountService.update(null,new UpdateWrapper<WechatAccount>()
+                    .set("company_name", wechatAccount.getCompanyName())
+                    .set("app_id", wechatAccount.getAppId())
+                    .set("app_secret", wechatAccount.getAppSecret())
+                    .eq("id", wechatAccount.getId()));
+
+        }
+        return httpRespMsg;
+    }
+
+    //获取企业微信公众号配置
+    @RequestMapping("/getCompanyWeiXin")
+    public HttpRespMsg getCompanyWeiXin(HttpServletRequest request) {
+        HttpRespMsg httpRespMsg = new HttpRespMsg();
+        String token = request.getHeader("Token");
+        User user = userService.getById(token);
+        WechatAccount wechatAccount = wechatAccountService.getOne(new QueryWrapper<WechatAccount>().eq("company_id", user.getCompanyId()));
+        httpRespMsg.setData(wechatAccount);
+        return httpRespMsg;
+    }
+
+
+    /**
+     * 保存修改并获取公司对应的accessToken
+     * @param request
+     * @return
+     */
+    @RequestMapping("/getAccessToken")
+    public HttpRespMsg getAccessToken(HttpServletRequest request) {
+        HttpRespMsg httpRespMsg = new HttpRespMsg();
+        String token = request.getHeader("Token");
+        User user = userService.getById(token);
+        WechatAccount wechatAccount = wechatAccountService.getOne(new QueryWrapper<WechatAccount>().eq("company_id", user.getCompanyId()));
+        if (wechatAccount==null){
+            httpRespMsg.setError("该公司没有配置公众号相关的参数");
+            return httpRespMsg;
+        }
+        String accessToken = wechatAccountService.getAccessToken(user.getCompanyId(), wechatAccount.getAppId());
+        httpRespMsg.setData(accessToken);
+        return httpRespMsg;
+    }
+
+    @RequestMapping(value = "sendInterviewInvitation")
+    public HttpRespMsg sendInterviewInvitation(String userId,HttpServletRequest request) {
+        HttpRespMsg msg = new HttpRespMsg();
+        String token = request.getHeader("Token");
+        User user = userService.getById(token);
+        WechatAccount wechatAccount = wechatAccountService.getOne(new QueryWrapper<WechatAccount>().eq("company_id", user.getCompanyId()));
+        String accessToken = wechatAccountService.getAccessToken(user.getCompanyId(), wechatAccount.getAppId());
+        try {
+
+            String result =createForeverStrTicket(accessToken, userId);
+            JSONObject jsonObject = JSONObject.parseObject(result);
+            String ticket = null ;
+            if(null!=jsonObject){
+                ticket = jsonObject.getString("ticket");
+                System.out.println("创建永久带参二维码成功,ticket="+ticket);
+            }
+            msg.data=ticket;
+            return msg;
+        } catch (Exception e) {
+            msg.setData(e.getMessage());
+        }
+        return msg;
+    }
+
+
+    //根据用户id获取对应的二维码信息
+    @RequestMapping(value = "getQrCodeFromTableOrWX")
+    public HttpRespMsg getQrCodeFromTableOrWX(String userId,HttpServletRequest request) {
+        HttpRespMsg msg = new HttpRespMsg();
+        String token = request.getHeader("Token");
+        User user = userService.getById(token);
+        UserQrCode qrCode = userQrCodeService.getOne(new QueryWrapper<UserQrCode>().eq("user_id", userId));
+        if (qrCode!=null){
+            qrCode.setUrlPlusTicket(prefixUrl+qrCode.getTicket());
+            msg.data=qrCode;
+            return msg;
+        }
+        else {
+            WechatAccount wechatAccount = wechatAccountService.getOne(new QueryWrapper<WechatAccount>().eq("company_id", user.getCompanyId()));
+            if (wechatAccount==null){
+                msg.setError("该公司没有配置公众号相关的参数");
+                return msg;
+            }
+            //获取公众号token
+            String accessToken = wechatAccountService.getAccessToken(user.getCompanyId(), wechatAccount.getAppId());
+            try {
+                //获取二维码相关信息相关
+                String result =createForeverStrTicket(accessToken, userId);
+                if (result==null|| StringUtils.isEmpty(result)){
+                    msg.setError("获取二维码信息失败");
+                    return msg;
+                }else {
+                    JSONObject jsonObject = JSONObject.parseObject(result);
+
+                    if (null != jsonObject) {
+                        String ticket = jsonObject.getString("ticket");
+                        System.out.println("创建永久带参二维码成功,ticket=" + ticket);
+                        String url = jsonObject.getString("url");
+                        System.out.println("创建永久带参二维码成功,url=" + url);
+
+                        UserQrCode userQrCode = new UserQrCode();
+                        userQrCode.setUserId(userId);
+                        userQrCode.setTicket(ticket);
+                        userQrCode.setUrl(url);
+                        userQrCode.setCompanyId(user.getCompanyId());
+                        //保存图片
+                        String imgPrefix=(StringUtils.isEmpty(user.getJobNumber())?"":user.getJobNumber())+"_"+user.getName();
+                        CompletableFuture<String> future = saveWeChatQrCodeImgHttpClient(prefixUrl + ticket, imgPrefix, uploadPath);
+                        String imgName = future.get(10, TimeUnit.SECONDS);// 添加超时
+                        if (imgName.isEmpty()){
+                            msg.setError("二维码图片保存失败");
+                            return msg;
+                        }else {
+                            userQrCode.setImg(imgName);
+                        }
+
+                        userQrCodeService.save(userQrCode);
+                        userQrCode.setUrlPlusTicket(prefixUrl+userQrCode.getTicket());
+                        msg.setData(userQrCode);
+                    }
+
+                    return msg;
+                }
+            } catch (Exception e) {
+                msg.setData(e.getMessage());
+            }
+            return msg;
+        }
+    }
+
+    //一键生成所有员工的二维码
+    @RequestMapping(value = "oneClickGeneration")
+    public HttpRespMsg oneClickGeneration(HttpServletRequest request) {
+        HttpRespMsg msg = new HttpRespMsg();
+        String token = request.getHeader("Token");
+        User user = userService.getById(token);
+
+        WechatAccount wechatAccount = wechatAccountService.getOne(new QueryWrapper<WechatAccount>().eq("company_id", user.getCompanyId()));
+        if (wechatAccount==null){
+            msg.setError("该公司没有配置公众号相关的参数");
+            return msg;
+        }
+        //获取公众号token
+        String accessToken = wechatAccountService.getAccessToken(user.getCompanyId(), wechatAccount.getAppId());
+
+        List<UserQrCode> qrCodeList = userQrCodeService.list(new QueryWrapper<UserQrCode>().eq("company_id", user.getCompanyId()));
+        List<String> userAlreadyIds = qrCodeList.stream().map(UserQrCode::getUserId).collect(Collectors.toList());//已经生成二维码的员工
+        userAlreadyIds.add("-1");
+
+        List<User> userList = userService.list(new QueryWrapper<User>().notIn("id", userAlreadyIds)
+                .eq("company_id", user.getCompanyId()));//未生成二维码的员工
+        if (!userList.isEmpty()){
+            for (User u : userList) {
+                String userId = u.getId();
+                try {
+                    //获取二维码相关信息相关
+                    String result =createForeverStrTicket(accessToken, userId);
+                    if (result==null|| StringUtils.isEmpty(result)){
+                        msg.setError("获取二维码信息失败");
+                        return msg;
+                    }else {
+                        JSONObject jsonObject = JSONObject.parseObject(result);
+                        if (null != jsonObject) {
+                            String ticket = jsonObject.getString("ticket");
+                            System.out.println("创建永久带参二维码成功,ticket=" + ticket);
+                            String url = jsonObject.getString("url");
+                            System.out.println("创建永久带参二维码成功,url=" + url);
+
+                            UserQrCode userQrCode = new UserQrCode();
+                            userQrCode.setUserId(userId);
+                            userQrCode.setTicket(ticket);
+                            userQrCode.setUrl(url);
+                            userQrCode.setCompanyId(user.getCompanyId());
+                            //保存图片
+                            String imgPrefix=(StringUtils.isEmpty(u.getJobNumber())?"":u.getJobNumber())+"_"+u.getName();
+                            CompletableFuture<String> future = saveWeChatQrCodeImgHttpClient(prefixUrl + ticket, imgPrefix, uploadPath);
+                            String imgName = future.get(10, TimeUnit.SECONDS);// 添加超时
+                            if (imgName.isEmpty()){
+                                msg.setError("二维码图片保存失败");
+                                return msg;
+                            }else {
+                                userQrCode.setImg(imgName);
+                            }
+                            userQrCodeService.save(userQrCode);
+                        }
+                    }
+                } catch (Exception e) {
+                    msg.setData(e.getMessage());
+                }
+            }
+        }
+        return msg;
+    }
+
+
+
+
+    @Async("taskExecutor")
+    public CompletableFuture<String> saveWeChatQrCodeImg(String qrCodeUrl, String ticket, String uploadPath) {
+        try {
+            log.info("开始保存二维码图片,ticket: {}", ticket);
+
+            // 确保目录存在
+            File uploadDir = new File(uploadPath);
+            if (!uploadDir.exists() && !uploadDir.mkdirs()) {
+                throw new IOException("无法创建目录: " + uploadPath);
+            }
+
+            // 构建目标文件路径
+            String fileName = ticket + ".jpg";
+            File destFile = new File(uploadPath, fileName);
+
+            // 从URL下载图片
+            log.info("qrCodeUrl==>{}", qrCodeUrl);
+            ResponseEntity<byte[]> response = restTemplate.getForEntity(qrCodeUrl, byte[].class);
+
+
+            if (!response.getStatusCode().is2xxSuccessful()) {
+                throw new IOException("下载失败,HTTP 状态码: " + response.getStatusCodeValue());
+            }
+
+            // 写入文件
+            try (FileOutputStream fos = new FileOutputStream(destFile)) {
+                fos.write(response.getBody());
+            }
+
+            log.info("二维码图片保存成功,文件名: {}", fileName);
+            return CompletableFuture.completedFuture(fileName);
+
+        } catch (IOException e) {
+            log.error("保存二维码图片失败,ticket: {}", ticket, e);
+            return CompletableFuture.completedFuture("");
+        }
+    }
+
+    @Async("taskExecutor")
+    public CompletableFuture<String> saveWeChatQrCodeImgHttpClient(String qrCodeUrl, String imgPrefix, String uploadPath) {
+        try {
+
+
+            // 确保目录存在
+            File uploadDir = new File(uploadPath);
+            if (!uploadDir.exists() && !uploadDir.mkdirs()) {
+                throw new IOException("无法创建目录: " + uploadPath);
+            }
+
+            // 构建目标文件路径
+            String fileName = imgPrefix + ".jpg";
+            File destFile = new File(uploadPath, fileName);
+
+
+            log.info("qrCodeUrl==>{}", qrCodeUrl);
+            // 创建信任所有证书的HttpClient
+            HttpClient client = HttpClients.custom()
+                    .setSSLContext(SSLContexts.custom().loadTrustMaterial(null, (chain, authType) -> true).build())
+                    .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
+                    .build();
+
+            HttpGet request = new HttpGet(qrCodeUrl);
+            try (CloseableHttpResponse response = (CloseableHttpResponse) client.execute(request);
+                 FileOutputStream fos = new FileOutputStream(destFile)) {
+                if (response.getStatusLine().getStatusCode() != 200) {
+                    throw new IOException("下载失败: " + response.getStatusLine());
+                }
+                response.getEntity().writeTo(fos);
+            }
+            return CompletableFuture.completedFuture(fileName);
+        } catch (Exception e) {
+            return CompletableFuture.completedFuture("");
+        }
+    }
+
+
+    /**
+     * 创建永久二维码(字符串)
+     *
+     * @param accessToken
+     * @param sceneStr
+     *            场景str
+     * @return
+     */
+    public String createForeverStrTicket(String accessToken, String sceneStr){
+        Map<String, String> intMap = new HashMap<>();
+        intMap.put("scene_str", sceneStr);
+        Map<String, Map<String, String>> mapMap = new HashMap<>();
+        mapMap.put("scene", intMap);
+        Map<String, Object> paramsMap = new HashMap<>();
+        paramsMap.put("action_name", "QR_LIMIT_STR_SCENE");
+        paramsMap.put("action_info", mapMap);
+        String  jsonObject = JSONObject.toJSONString(paramsMap);
+
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(MediaType.APPLICATION_JSON);
+        String requestUrl = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token="+accessToken;
+
+
+        HttpEntity<String> requestEntity = new HttpEntity<String>(jsonObject, headers);
+        ResponseEntity<String> responseEntity = restTemplate.exchange(requestUrl,
+                HttpMethod.POST, requestEntity, String.class);
+
+        if (responseEntity.getStatusCode() == HttpStatus.OK) {
+            JSONObject json = JSONObject.parseObject(responseEntity.getBody());
+            assert json != null;
+            log.info("json.toJSONString()"+json.toJSONString());
+            return json.toJSONString();
+        }
+        else return "";
+    }
+
+    /**
+     * 导出
+     */
+    @RequestMapping("/export")
+    public void getExport(HttpServletRequest request, HttpServletResponse response)  {
+        String token = request.getHeader("TOKEN");
+        User user = userService.getById(token);
+        List<UserQrCode> codeList = userQrCodeService.list(new QueryWrapper<UserQrCode>().eq("company_id", user.getCompanyId()));
+
+        List<String> fileNames= codeList.stream().map(UserQrCode::getImg).collect(Collectors.toList());
+        if (!fileNames.isEmpty()){
+            FileZipUtil.exportZip(response,uploadPath ,fileNames, "员工微信公众号二维码压缩包", ".zip");
+        }else return;
+    }
+
+}
+

+ 182 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/controller/WeiXinTicketController.java

@@ -0,0 +1,182 @@
+package com.management.platform.controller;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.management.platform.entity.WeiXinTicketEntity;
+import com.management.platform.service.WechatAccountService;
+import com.management.platform.util.HttpRespMsg;
+import com.management.platform.util.HttpUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.*;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.client.RestTemplate;
+
+import javax.annotation.Resource;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 生成带参二维码的ticket值
+ * @author wyx
+ *
+ */
+
+@RestController
+@RequestMapping("weixinTicket")
+
+@Slf4j
+public class WeiXinTicketController {
+
+	@Value("${weixin.ticket.action_name.QR_SCENE}")
+    private String 	QRSCENE;
+	@Value("${weixin.ticket.action_name.QR_STR_SCENE}")
+    private String 	QR_STR_SCENE;
+
+	private static final String APP_ID = "wx1c1d8fc81bc073a8";
+	private static final String APP_SECRET = "17ad07f90ee845f99f4c1605647ef755";
+	private static final String GRANT_TYPE = "client_credential";
+
+	@Resource
+	private  RestTemplate restTemplate;
+
+	@Resource
+	private WechatAccountService wechatAccountService;
+
+
+	
+	@RequestMapping(value = "sendInterviewInvitation",method=RequestMethod.POST)
+	public HttpRespMsg sendInterviewInvitation(@RequestBody WeiXinTicketEntity reqDto) throws Exception{
+		HttpRespMsg msg = new HttpRespMsg();
+		try {
+			String accessToken = wechatAccountService.getAccessToken(6374,"");
+			String sceneStr = reqDto.getSceneStr();
+			String result =this.createForeverStrTicket(accessToken, sceneStr);
+			JSONObject jsonObject = JSONObject.parseObject(result);
+			String ticket = null ;
+			if(null!=jsonObject){
+				ticket = jsonObject.getString("ticket");  
+                System.out.println("创建永久带参二维码成功,ticket="+ticket);  
+	        }    
+			msg.data=ticket;
+			return msg;
+		} catch (Exception e) {
+			throw new Exception(e);
+		}
+	}
+	
+	/**
+	 * 创建临时带参数二维码 
+	 * 获取灵石带参二维码ticket
+	 * 
+	 * @param accessToken
+	 * @expireSeconds 该二维码有效时间,以秒为单位。 最大不超过2592000(即30天),此字段如果不填,则默认有效期为30秒。
+	 * @param sceneId 场景Id
+	 * @return
+	 */
+	public String createTempTicket(String accessToken, String expireSeconds, int sceneId) throws Exception {
+		Map<String, Integer> intMap = new HashMap<>();
+		intMap.put("scene_id", sceneId);
+		Map<String, Map<String, Integer>> mapMap = new HashMap<>();
+		mapMap.put("scene", intMap);
+		Map<String, Object> paramsMap = new HashMap<>();
+		paramsMap.put("expire_seconds", expireSeconds);
+		paramsMap.put("action_name", QRSCENE);
+		paramsMap.put("action_info", mapMap);
+		String  jsonObject = JSONObject.toJSONString(paramsMap);
+		String requestUrl = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token="+accessToken;
+		String result = HttpUtil.post(requestUrl,accessToken, jsonObject);
+		return result;
+	 
+	}
+	 
+	/**
+	 * 创建永久二维码(数字)
+	 * 
+	 * @param accessToken
+	 * @param sceneId
+	 *            场景Id
+	 * @return
+	 */
+	public String createForeverTicket(String accessToken, int sceneId) throws Exception {
+		Map<String, Integer> intMap = new HashMap<>();
+		intMap.put("scene_id", sceneId);
+		Map<String, Map<String, Integer>> mapMap = new HashMap<>();
+		mapMap.put("scene", intMap);
+		Map<String, Object> paramsMap = new HashMap<>();
+		paramsMap.put("action_name", "QR_LIMIT_STR_SCENE");
+		paramsMap.put("action_info", mapMap);
+		String  jsonObject = JSONObject.toJSONString(paramsMap);
+		String requestUrl = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=";
+		String result = HttpUtil.post(requestUrl,accessToken, jsonObject);
+		return result;
+	}
+	 
+	/**
+	 * 创建永久二维码(字符串)
+	 * 
+	 * @param accessToken
+	 * @param sceneStr
+	 *            场景str
+	 * @return
+	 */
+	public String createForeverStrTicket(String accessToken, String sceneStr){
+		Map<String, String> intMap = new HashMap<>();
+		intMap.put("scene_str", sceneStr);
+		Map<String, Map<String, String>> mapMap = new HashMap<>();
+		mapMap.put("scene", intMap);
+		Map<String, Object> paramsMap = new HashMap<>();
+		paramsMap.put("action_name", "QR_LIMIT_STR_SCENE");
+		paramsMap.put("action_info", mapMap);
+		String  jsonObject = JSONObject.toJSONString(paramsMap);
+
+		HttpHeaders headers = new HttpHeaders();
+		headers.setContentType(MediaType.APPLICATION_JSON);
+		String requestUrl = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token="+accessToken;
+
+
+		HttpEntity<String> requestEntity = new HttpEntity<String>(jsonObject, headers);
+		ResponseEntity<String> responseEntity = this.restTemplate.exchange(requestUrl,
+				HttpMethod.POST, requestEntity, String.class);
+
+		if (responseEntity.getStatusCode() == HttpStatus.OK) {
+			JSONObject json = JSONObject.parseObject(responseEntity.getBody());
+			log.info("返回:" + json.toJSONString());
+			if (json.getIntValue("errcode") == 0) {
+				log.info("");
+			}
+		}
+
+		return "";
+
+	}
+
+
+	//获取第三方应用临时凭证
+	private String getWeiXinAccessToken() {
+		RestTemplate restTemplate = new RestTemplate();
+		String response = restTemplate.getForObject(
+				"https://api.weixin.qq.com/cgi-bin/token",
+				String.class,
+				GRANT_TYPE,
+				APP_ID,
+				APP_SECRET);
+
+		JSONObject jsonObject = JSON.parseObject(response);
+		if (jsonObject.containsKey("access_token")) {
+			return jsonObject.getString("access_token");
+		} else {
+			System.err.println("获取access_token失败: " + response);
+			return null;
+		}
+
+	}
+
+
+
+ 
+ 
+}

+ 69 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/UserQrCode.java

@@ -0,0 +1,69 @@
+package com.management.platform.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author Seyason
+ * @since 2025-04-16
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+public class UserQrCode extends Model<UserQrCode> {
+
+    private static final long serialVersionUID=1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    /**
+     * useId
+     */
+    @TableField("user_id")
+    private String userId;
+
+    /**
+     * 公司id
+     */
+    @TableField("company_id")
+    private Integer companyId;
+
+    /**
+     * 根据员工userId获取的永久公众号ticket
+     */
+    @TableField("ticket")
+    private String ticket;
+
+    /**
+     * 根据员工userId获取的永久公众号url
+     */
+    @TableField("url")
+    private String url;
+
+    /**
+     * 二维码名称
+     */
+    @TableField("img")
+    private String img;
+
+    @TableField(exist = false)
+    private String urlPlusTicket;
+
+    @Override
+    protected Serializable pkVal() {
+        return this.id;
+    }
+
+}

+ 89 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/WechatAccount.java

@@ -0,0 +1,89 @@
+package com.management.platform.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 微信公众号账号表
+ * </p>
+ *
+ * @author Seyason
+ * @since 2025-04-15
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+public class WechatAccount extends Model<WechatAccount> {
+
+    private static final long serialVersionUID=1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    /**
+     * 企业ID
+     */
+    @TableField("company_id")
+    private Integer companyId;
+
+
+    /**
+     * 企业公众号名称
+     */
+    @TableField("company_name")
+    private String companyName;
+
+    /**
+     * 公众号AppID
+     */
+    @TableField("app_id")
+    private String appId;
+
+    /**
+     * 公众号AppSecret
+     */
+    @TableField("app_secret")
+    private String appSecret;
+
+    /**
+     * 访问令牌
+     */
+    @TableField("access_token")
+    private String accessToken;
+
+    /**
+     * 令牌过期时间
+     */
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @TableField("token_expire_time")
+    private LocalDateTime tokenExpireTime;
+
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @TableField("create_time")
+    private LocalDateTime createTime;
+
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @TableField("update_time")
+    private LocalDateTime updateTime;
+
+
+    @Override
+    protected Serializable pkVal() {
+        return this.id;
+    }
+
+}

+ 18 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/entity/WeiXinTicketEntity.java

@@ -0,0 +1,18 @@
+package com.management.platform.entity;
+ 
+import lombok.Data;
+ 
+/**
+ * 
+ * @author 
+ *
+ */
+@Data
+public class WeiXinTicketEntity {
+	/*场景值ID,临时二维码时为32位非0整型,永久二维码时最大值为100000(目前参数只支持1--100000)*/
+	private int sceneId;
+	/*该二维码有效时间,以秒为单位。 最大不超过2592000(即30天),此字段如果不填,则默认有效期为30秒*/
+	private String expireSeconds;
+	/*场景值ID(字符串形式的ID),字符串类型,长度限制为1到64*/
+	private String sceneStr;
+}

+ 16 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/mapper/UserQrCodeMapper.java

@@ -0,0 +1,16 @@
+package com.management.platform.mapper;
+
+import com.management.platform.entity.UserQrCode;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author Seyason
+ * @since 2025-04-16
+ */
+public interface UserQrCodeMapper extends BaseMapper<UserQrCode> {
+
+}

+ 31 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/mapper/WechatAccountMapper.java

@@ -0,0 +1,31 @@
+package com.management.platform.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.management.platform.entity.WechatAccount;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.Update;
+
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 微信公众号账号表 Mapper 接口
+ * </p>
+ *
+ * @author Seyason
+ * @since 2025-04-15
+ */
+public interface WechatAccountMapper extends BaseMapper<WechatAccount> {
+    @Select("SELECT * FROM wechat_account WHERE company_id = #{companyId} AND app_id = #{appId}")
+    WechatAccount findByCompanyAndApp(@Param("companyId") Integer companyId,
+                                      @Param("appId") String appId);
+
+    @Update("UPDATE wechat_account SET access_token = #{accessToken}, " +
+            "token_expire_time = #{tokenExpireTime} " +
+            "WHERE company_id = #{companyId} AND app_id = #{appId}")
+    int updateTokenInfo(@Param("companyId") Integer companyId,
+                        @Param("appId") String appId,
+                        @Param("accessToken") String accessToken,
+                        @Param("tokenExpireTime") LocalDateTime tokenExpireTime);
+}

+ 16 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/UserQrCodeService.java

@@ -0,0 +1,16 @@
+package com.management.platform.service;
+
+import com.management.platform.entity.UserQrCode;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ *  服务类
+ * </p>
+ *
+ * @author Seyason
+ * @since 2025-04-16
+ */
+public interface UserQrCodeService extends IService<UserQrCode> {
+
+}

+ 16 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/WechatAccountService.java

@@ -0,0 +1,16 @@
+package com.management.platform.service;
+
+import com.management.platform.entity.WechatAccount;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * 微信公众号账号表 服务类
+ * </p>
+ *
+ * @author Seyason
+ * @since 2025-04-15
+ */
+public interface WechatAccountService extends IService<WechatAccount> {
+    public String getAccessToken(Integer companyId, String appId) ;
+}

+ 20 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/UserQrCodeServiceImpl.java

@@ -0,0 +1,20 @@
+package com.management.platform.service.impl;
+
+import com.management.platform.entity.UserQrCode;
+import com.management.platform.mapper.UserQrCodeMapper;
+import com.management.platform.service.UserQrCodeService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ *  服务实现类
+ * </p>
+ *
+ * @author Seyason
+ * @since 2025-04-16
+ */
+@Service
+public class UserQrCodeServiceImpl extends ServiceImpl<UserQrCodeMapper, UserQrCode> implements UserQrCodeService {
+
+}

+ 14 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/UserServiceImpl.java

@@ -193,6 +193,10 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
     private SysDictService sysDictService;
     @Resource
     private SuperSonicConfig  superSonicConfig;
+    @Resource
+    private UserQrCodeService userQrCodeService;
+
+    private final static String prefixUrl="https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=";
 
 
     //登录网页端
@@ -987,6 +991,16 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
                     }
                     list = active;
                 }
+                List<UserQrCode> qrCodeList = userQrCodeService.list(new QueryWrapper<UserQrCode>().eq("company_id", companyId));
+                for (Map<String, Object> map : list) {
+                    String userId = map.get("id").toString();
+                    Optional<UserQrCode> first = qrCodeList.stream().filter(q -> userId.equals(q.getUserId())).findFirst();
+                    if (first.isPresent()) {
+                        UserQrCode userQrCode = first.get();
+                        map.put("wxImgName",org.apache.commons.lang3.StringUtils.isEmpty(userQrCode.getImg())?null:userQrCode.getImg());
+                        map.put("wxImgUrlWithTicket", org.apache.commons.lang3.StringUtils.isEmpty(userQrCode.getTicket())?null:prefixUrl+userQrCode.getTicket());
+                    }
+                }
                 resultMap.put("records", list);
                 resultMap.put("total", total);
                 resultMap.put("nextCursor", "");

+ 99 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/service/impl/WechatAccountServiceImpl.java

@@ -0,0 +1,99 @@
+package com.management.platform.service.impl;
+
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONObject;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.management.platform.entity.WechatAccount;
+import com.management.platform.mapper.WechatAccountMapper;
+import com.management.platform.service.WechatAccountService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.web.client.RestTemplate;
+
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 微信公众号账号表 服务实现类
+ * </p>
+ *
+ * @author Seyason
+ * @since 2025-04-15
+ */
+@Service
+public class WechatAccountServiceImpl extends ServiceImpl<WechatAccountMapper, WechatAccount> implements WechatAccountService {
+
+    @Autowired
+    private  WechatAccountMapper wechatAccountMapper;
+    @Autowired
+    private  RestTemplate restTemplate;
+
+    // 提前5分钟刷新,避免临界点问题
+    private static final int TOKEN_EXPIRE_BUFFER = 5 ;
+
+    /**
+     * 获取AccessToken
+     * @param companyId 企业ID
+     * @param appId 公众号AppID
+     * @return AccessToken
+     */
+    public String getAccessToken(Integer companyId, String appId) {
+        // 1. 从数据库获取账号信息
+        WechatAccount account = wechatAccountMapper.findByCompanyAndApp(companyId, appId);
+        if (account == null) {
+            throw new RuntimeException("未找到对应的公众号配置");
+        }
+
+        // 2. 检查Token是否有效
+        if (isTokenValid(account)) {
+            return account.getAccessToken();
+        }
+
+        // 3. Token无效则重新获取
+        return refreshAccessToken(account);
+    }
+
+    /**
+     * 判断Token是否有效
+     */
+    private boolean isTokenValid(WechatAccount account) {
+        return account.getAccessToken() != null
+                && account.getTokenExpireTime() != null
+                && account.getTokenExpireTime().isAfter(
+                LocalDateTime.now().plusMinutes(TOKEN_EXPIRE_BUFFER));
+    }
+
+    /**
+     * 刷新AccessToken
+     */
+    private String refreshAccessToken(WechatAccount account) {
+        String url = String.format(
+                "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s",
+                account.getAppId(), account.getAppSecret());
+
+        try {
+            System.out.println("url==>"+url);
+            String response = restTemplate.getForObject(url, String.class);
+            JSONObject json = JSON.parseObject(response);
+
+            if (json.containsKey("access_token")) {
+                String newToken = json.getString("access_token");
+                int expiresIn = json.getIntValue("expires_in");
+                LocalDateTime expireTime = LocalDateTime.now().plusSeconds(expiresIn);
+
+                // 更新数据库
+                wechatAccountMapper.updateTokenInfo(
+                        account.getCompanyId(),
+                        account.getAppId(),
+                        newToken,
+                        expireTime);
+
+                return newToken;
+            } else {
+                throw new RuntimeException("获取AccessToken失败: " + response);
+            }
+        } catch (Exception e) {
+            throw new RuntimeException("调用微信API失败", e);
+        }
+    }
+}

+ 115 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/java/com/management/platform/util/FileZipUtil.java

@@ -0,0 +1,115 @@
+package com.management.platform.util;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.StringUtils;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.*;
+import java.net.URLEncoder;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+public class FileZipUtil {
+
+    /**
+     * 将指定路径下的所有文件打包zip导出
+     * @param response HttpServletResponse
+     * @param sourceFilePath 需要打包的文件夹路径
+     * @param fileName 下载时的文件名称
+     * @param postfix 下载时的文件后缀 .zip/.rar
+     */
+    public static void exportZip(HttpServletResponse response, String sourceFilePath, List<String> fileNames, String fileName, String postfix) {
+        // 默认文件名以时间戳作为前缀
+        if(StringUtils.isBlank(fileName)){
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
+            fileName = sdf.format(new Date());
+        }
+        String downloadName = fileName + postfix;
+        // 将文件进行打包下载
+        try {
+            OutputStream os = response.getOutputStream();
+            // 接收压缩包字节
+            byte[] data = createZip(sourceFilePath,fileNames);
+            response.reset();
+            response.setCharacterEncoding("UTF-8");
+            response.addHeader("Access-Control-Allow-Origin", "*");
+            response.setHeader("Access-Control-Expose-Headers", "*");
+            // 下载文件名乱码问题
+            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(downloadName, "UTF-8"));
+            //response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + downloadName);
+            response.addHeader("Content-Length", "" + data.length);
+            response.setContentType("application/octet-stream;charset=UTF-8");
+            IOUtils.write(data, os);
+            os.flush();
+            os.close();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 创建zip文件
+     * @param sourceFilePath
+     * @return byte[]
+     * @throws Exception
+     */
+    private static byte[] createZip(String sourceFilePath,List<String> fileNames) throws Exception{
+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+        ZipOutputStream zip = new ZipOutputStream(outputStream);
+        // 将目标文件打包成zip导出
+        File file = new File(sourceFilePath);
+        handlerFile(zip, file,"",fileNames);
+        // 无异常关闭流,它将无条件的关闭一个可被关闭的对象而不抛出任何异常。
+        IOUtils.closeQuietly(zip);
+        return outputStream.toByteArray();
+    }
+
+    /**
+     * 打包处理
+     * @param zip
+     * @param file
+     * @param dir
+     * @throws Exception
+     */
+    private static void handlerFile(ZipOutputStream zip, File file, String dir,List<String> fileNames) throws Exception {
+        // 得到文件列表信息
+        File[] fileArray = file.listFiles();
+
+        if (fileArray == null) {
+            extracted(zip, file, dir);
+        } else {
+            // 过滤出与 fileNames 匹配的文件
+            for (File f : fileArray) {
+                if (fileNames.contains(f.getName())) { // 使用 contains 方法检查
+                    extracted(zip, f, dir + f.getName()); // 打包处理匹配的文件
+                } else if (f.isDirectory()) {
+                    // 递归处理子目录
+                    handlerFile(zip, f, dir + f.getName() + "/", fileNames);
+                }
+            }
+        }
+
+            /*//将文件夹添加到下一级打包目录
+            zip.putNextEntry(new ZipEntry(dir + "/"));
+            dir = dir.length() == 0 ? "" : dir + "/";
+            // 递归将文件夹中的文件打包
+            for (File f : fileArray) {
+                handlerFile(zip, f, dir + f.getName(),fileNames);
+            }*/
+
+    }
+
+    private static void extracted(ZipOutputStream zip, File file, String dir) throws IOException {
+        // 如果当前的是文件,打包处理
+        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
+        ZipEntry entry = new ZipEntry(dir); // 使用完整路径(包含文件名)
+        zip.putNextEntry(entry);
+        zip.write(FileUtils.readFileToByteArray(file));
+        IOUtils.closeQuietly(bis);
+        zip.closeEntry(); // 关闭当前条目
+    }
+}

+ 12 - 3
fhKeeper/formulahousekeeper/management-crm/src/main/resources/application.yml

@@ -1,5 +1,5 @@
 server:
-  port: 10010
+  port: 10011
   tomcat:
     uri-encoding: utf-8
     max-http-form-post-size: -1
@@ -15,7 +15,7 @@ spring:
       location: C:/upload/
   datasource:
     driver-class-name: com.mysql.cj.jdbc.Driver
-    url: jdbc:mysql://1.94.62.58:17089/man_crm_bk?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&rewriteBatchedStatements=true&useSSL=false
+    url: jdbc:mysql://1.94.62.58:17089/man_crm?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&rewriteBatchedStatements=true&useSSL=false
     username: root
     password: P011430@Huoshi*
 
@@ -171,4 +171,13 @@ supersonic:
 
 aiask:
   fileaskurl: http://123.60.32.117:5000/analyze
-  askurl: http://123.60.32.117:5000/analyzeOnlyQuestion
+  askurl: http://123.60.32.117:5000/analyzeOnlyQuestion
+
+  #临时的整型参数值
+weixin:
+  ticket:
+    action_name:
+     QR_SCENE: QR_SCENE
+     QR_STR_SCENE: QR_STR_SCENE
+     QR_LIMIT_SCENE: QR_LIMIT_SCENE
+     QR_LIMIT_STR_SCENE: QR_LIMIT_STR_SCENE

+ 20 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/resources/mapper/UserQrCodeMapper.xml

@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.management.platform.mapper.UserQrCodeMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.management.platform.entity.UserQrCode">
+        <id column="id" property="id" />
+        <result column="user_id" property="userId" />
+        <result column="company_id" property="companyId" />
+        <result column="ticket" property="ticket" />
+        <result column="url" property="url" />
+        <result column="img" property="img" />
+    </resultMap>
+
+    <!-- 通用查询结果列 -->
+    <sql id="Base_Column_List">
+        id, user_id, company_id, ticket, url, img
+    </sql>
+
+</mapper>

+ 22 - 0
fhKeeper/formulahousekeeper/management-crm/src/main/resources/mapper/WechatAccountMapper.xml

@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.management.platform.mapper.WechatAccountMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.management.platform.entity.WechatAccount">
+        <id column="id" property="id" />
+        <result column="company_id" property="companyId" />
+        <result column="app_id" property="appId" />
+        <result column="app_secret" property="appSecret" />
+        <result column="access_token" property="accessToken" />
+        <result column="token_expire_time" property="tokenExpireTime" />
+        <result column="create_time" property="createTime" />
+        <result column="update_time" property="updateTime" />
+    </resultMap>
+
+    <!-- 通用查询结果列 -->
+    <sql id="Base_Column_List">
+        id, company_id, app_id, app_secret, access_token, token_expire_time, create_time, update_time
+    </sql>
+
+</mapper>